Revision: 77704
          http://sourceforge.net/p/brlcad/code/77704
Author:   starseeker
Date:     2020-11-07 02:31:05 +0000 (Sat, 07 Nov 2020)
Log Message:
-----------
Fold exppp into express

Modified Paths:
--------------
    
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/CMakeLists.txt
    brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/export.h
    
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/express/CMakeLists.txt
    
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/utils/dirobj.h
    brlcad/branches/extbuild/src/other/ext/stepcode/src/CMakeLists.txt
    brlcad/branches/extbuild/src/other/ext/stepcode/src/exp2cxx/CMakeLists.txt
    brlcad/branches/extbuild/src/other/ext/stepcode/src/exp2cxx/classes.h
    brlcad/branches/extbuild/src/other/ext/stepcode/src/exp2cxx/complexSupport.h
    brlcad/branches/extbuild/src/other/ext/stepcode/src/express/CMakeLists.txt

Added Paths:
-----------
    
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/express/exppp.h
    brlcad/branches/extbuild/src/other/ext/stepcode/src/express/exppp.c

Removed Paths:
-------------
    brlcad/branches/extbuild/src/other/ext/stepcode/include/dirobj.h
    brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/exppp/
    brlcad/branches/extbuild/src/other/ext/stepcode/src/exppp/

Deleted: brlcad/branches/extbuild/src/other/ext/stepcode/include/dirobj.h
===================================================================
--- brlcad/branches/extbuild/src/other/ext/stepcode/include/dirobj.h    
2020-11-07 02:19:55 UTC (rev 77703)
+++ brlcad/branches/extbuild/src/other/ext/stepcode/include/dirobj.h    
2020-11-07 02:31:05 UTC (rev 77704)
@@ -1,99 +0,0 @@
-
-#ifndef dirobj_h
-#define dirobj_h
-
-/*
-* NIST Utils Class Library
-* clutils/dirobj.h
-* April 1997
-* David Sauder
-* K. C. Morris
-
-* Development of this software was funded by the United States Government,
-* and is not subject to copyright.
-*/
-
-/*
- * DirObj - This object contains a list of files in a directory.
- *      Can be used for checking paths etc.
- *  based on InterViews FBDirectory
- *      Copyright (c) 1987, 1988, 1989 Stanford University from
- *      /depot/iv/src/libInterViews/filebrowser.c <= notice
- *  I commented it, changed variable and function names, added a
- *  few things, and made it so we can actually use it.
- *      David Sauder
- */
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// These header files are a pain between compilers etc ... and
-// I agree they are in a mess.  You will have to CHECK them yourself
-// depending on what you are using -- it works the way it is with g++
-// but you need -I/depot/gnu/lib/g++-include
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "export.h"
-#include <stdlib.h>
-
-#include <string.h>
-#include <string>
-
-
-/*****************************************************************************/
-
-class STEPCODE_UTILS_EXPORT DirObj {
-    public:
-        DirObj( const char * dirName );
-        virtual ~DirObj();
-
-        bool LoadDirectory( const std::string & name );
-        static std::string Normalize( const std::string & s );
-
-        const char * ValidDirectories( const char * );
-
-        int Index( const char * );
-        const char * File( int index );
-        // check for file in the currently loaded directory
-        bool FileExists( const char * file ) {
-            return Index( file ) ? 1 : 0;
-        }
-        bool FileExists( const std::string & file ) {
-            return Index( file.c_str() ) ? true : false;
-        }
-        int Count();
-
-        static bool IsADirectory( const char * );
-    private:
-        const char * RealPath( const char * );
-
-        bool Reset( const std::string & path );
-        void ClearFileList();
-        void CheckIndex( int index );
-        void InsertFile( const char *, int index );
-        void AppendFile( const char * );
-        void RemoveFile( int index );
-        virtual int Position( const char * );
-    private:
-        char ** fileList;
-        int fileCount;
-        int fileListSize;
-};
-
-// Return the number of files in the loaded directory.
-inline int DirObj::Count() {
-    return fileCount;
-}
-
-// Insert a new file into the fileList.
-inline void DirObj::AppendFile( const char * s ) {
-    InsertFile( s, fileCount );
-}
-
-// Return the file at the given index (starting at 0) in the fileList
-inline const char * DirObj::File( int index ) {
-    return ( 0 <= index && index < fileCount ) ? fileList[index] : 0;
-}
-
-#endif
-

Modified: 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/CMakeLists.txt
===================================================================
--- 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/CMakeLists.txt 
    2020-11-07 02:19:55 UTC (rev 77703)
+++ 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/CMakeLists.txt 
    2020-11-07 02:31:05 UTC (rev 77704)
@@ -2,7 +2,6 @@
 add_subdirectory(dai)
 add_subdirectory(editor)
 add_subdirectory(utils)
-add_subdirectory(exppp)
 add_subdirectory(express)
 
 install(FILES export.h

Modified: 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/export.h
===================================================================
--- brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/export.h   
2020-11-07 02:19:55 UTC (rev 77703)
+++ brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/export.h   
2020-11-07 02:31:05 UTC (rev 77704)
@@ -35,19 +35,6 @@
 #  endif
 #endif
 
-/* Import/Export flags for exppp. */
-#ifndef STEPCODE_EXPPP_EXPORT
-#  if defined(STEPCODE_EXPPP_DLL_EXPORTS) && 
defined(STEPCODE_EXPPP_DLL_IMPORTS)
-#    error "Only STEPCODE_EXPPP_DLL_EXPORTS or STEPCODE_EXPPP_DLL_IMPORTS can 
be defined, not both."
-#  elif defined(STEPCODE_EXPPP_DLL_EXPORTS)
-#    define STEPCODE_EXPPP_EXPORT COMPILER_DLLEXPORT
-#  elif defined(STEPCODE_EXPPP_DLL_IMPORTS)
-#    define STEPCODE_EXPPP_EXPORT COMPILER_DLLIMPORT
-#  else
-#    define STEPCODE_EXPPP_EXPORT
-#  endif
-#endif
-
 /* Import/Export flags for utils. */
 #ifndef STEPCODE_UTILS_EXPORT
 #  if defined(STEPCODE_UTILS_DLL_EXPORTS) && 
defined(STEPCODE_UTILS_DLL_IMPORTS)

Modified: 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/express/CMakeLists.txt
===================================================================
--- 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/express/CMakeLists.txt
     2020-11-07 02:19:55 UTC (rev 77703)
+++ 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/express/CMakeLists.txt
     2020-11-07 02:31:05 UTC (rev 77704)
@@ -9,6 +9,7 @@
        entity.h
        error.h
        expbasic.h
+       exppp.h
        expr.h
        express.h
        hash.h

Copied: 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/express/exppp.h
 (from rev 77703, 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/exppp/exppp.h)
===================================================================
--- 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/express/exppp.h
                            (rev 0)
+++ 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/express/exppp.h
    2020-11-07 02:31:05 UTC (rev 77704)
@@ -0,0 +1,67 @@
+#ifndef EXPPP_H
+#define EXPPP_H
+#include "export.h"
+#include "express/alg.h"
+
+extern STEPCODE_EXPRESS_EXPORT int exppp_nesting_indent;    /* default nesting 
indent */
+extern STEPCODE_EXPRESS_EXPORT int exppp_continuation_indent;   /* default 
nesting indent for */
+/* continuation lines */
+extern STEPCODE_EXPRESS_EXPORT int exppp_linelength;        /* leave some slop 
for closing */
+/* parens.  \n is not included in */
+/* this count either */
+extern STEPCODE_EXPRESS_EXPORT bool exppp_rmpp;          /* if true, create 
rmpp */
+extern STEPCODE_EXPRESS_EXPORT bool exppp_alphabetize;       /* if true, 
alphabetize */
+extern STEPCODE_EXPRESS_EXPORT bool exppp_terse;         /* don't describe 
action to stdout */
+extern STEPCODE_EXPRESS_EXPORT bool exppp_reference_info;    /* if true, add 
commentary */
+/* about where things came from */
+extern STEPCODE_EXPRESS_EXPORT bool exppp_preserve_comments; /* if true, 
preserve comments where */
+/* possible */
+extern STEPCODE_EXPRESS_EXPORT char * exppp_output_filename; /* force output 
filename */
+extern STEPCODE_EXPRESS_EXPORT bool exppp_output_filename_reset; /* if true, 
force output filename */
+
+STEPCODE_EXPRESS_EXPORT void EXPRESSout( Express e );
+
+STEPCODE_EXPRESS_EXPORT void ENTITYout( Entity e );
+STEPCODE_EXPRESS_EXPORT void EXPRout( Expression expr );
+STEPCODE_EXPRESS_EXPORT void FUNCout( Function f );
+STEPCODE_EXPRESS_EXPORT void PROCout( Procedure p );
+STEPCODE_EXPRESS_EXPORT void RULEout( Rule r );
+STEPCODE_EXPRESS_EXPORT char * SCHEMAout( Schema s );
+STEPCODE_EXPRESS_EXPORT void SCHEMAref_out( Schema s );
+STEPCODE_EXPRESS_EXPORT void STMTout( Statement s );
+STEPCODE_EXPRESS_EXPORT void TYPEout( Type t );
+STEPCODE_EXPRESS_EXPORT void TYPEhead_out( Type t );
+STEPCODE_EXPRESS_EXPORT void TYPEbody_out( Type t );
+STEPCODE_EXPRESS_EXPORT void WHEREout( Linked_List w );
+
+STEPCODE_EXPRESS_EXPORT char * REFto_string( Dictionary refdict, Linked_List 
reflist, char * type, int level );
+STEPCODE_EXPRESS_EXPORT char * ENTITYto_string( Entity e );
+STEPCODE_EXPRESS_EXPORT char * SUBTYPEto_string( Expression e );
+STEPCODE_EXPRESS_EXPORT char * EXPRto_string( Expression expr );
+STEPCODE_EXPRESS_EXPORT char * FUNCto_string( Function f );
+STEPCODE_EXPRESS_EXPORT char * PROCto_string( Procedure p );
+STEPCODE_EXPRESS_EXPORT char * RULEto_string( Rule r );
+STEPCODE_EXPRESS_EXPORT char * SCHEMAref_to_string( Schema s );
+STEPCODE_EXPRESS_EXPORT char * STMTto_string( Statement s );
+STEPCODE_EXPRESS_EXPORT char * TYPEto_string( Type t );
+STEPCODE_EXPRESS_EXPORT char * TYPEhead_to_string( Type t );
+STEPCODE_EXPRESS_EXPORT char * TYPEbody_to_string( Type t );
+STEPCODE_EXPRESS_EXPORT char * WHEREto_string( Linked_List w );
+
+STEPCODE_EXPRESS_EXPORT int REFto_buffer( Dictionary refdict, Linked_List 
reflist, char * type, int level, char * buffer, int length );
+STEPCODE_EXPRESS_EXPORT int ENTITYto_buffer( Entity e, char * buffer, int 
length );
+STEPCODE_EXPRESS_EXPORT int EXPRto_buffer( Expression e, char * buffer, int 
length );
+STEPCODE_EXPRESS_EXPORT int FUNCto_buffer( Function e, char * buffer, int 
length );
+STEPCODE_EXPRESS_EXPORT int PROCto_buffer( Procedure e, char * buffer, int 
length );
+STEPCODE_EXPRESS_EXPORT int RULEto_buffer( Rule e, char * buffer, int length );
+STEPCODE_EXPRESS_EXPORT int SCHEMAref_to_buffer( Schema s, char * buffer, int 
length );
+STEPCODE_EXPRESS_EXPORT int STMTto_buffer( Statement s, char * buffer, int 
length );
+STEPCODE_EXPRESS_EXPORT int TYPEto_buffer( Type t, char * buffer, int length );
+STEPCODE_EXPRESS_EXPORT int TYPEhead_to_buffer( Type t, char * buffer, int 
length );
+STEPCODE_EXPRESS_EXPORT int TYPEbody_to_buffer( Type t, char * buffer, int 
length );
+STEPCODE_EXPRESS_EXPORT int WHEREto_buffer( Linked_List w, char * buffer, int 
length );
+
+STEPCODE_EXPRESS_EXPORT int EXPRlength( Expression e );
+STEPCODE_EXPRESS_EXPORT int count_newlines( char * s );
+
+#endif

Modified: 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/utils/dirobj.h
===================================================================
--- 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/utils/dirobj.h 
    2020-11-07 02:19:55 UTC (rev 77703)
+++ 
brlcad/branches/extbuild/src/other/ext/stepcode/include/stepcode/utils/dirobj.h 
    2020-11-07 02:31:05 UTC (rev 77704)
@@ -33,7 +33,6 @@
 //
 ///////////////////////////////////////////////////////////////////////////////
 
-#include "config.h"
 #include "export.h"
 #include <stdlib.h>
 

Modified: brlcad/branches/extbuild/src/other/ext/stepcode/src/CMakeLists.txt
===================================================================
--- brlcad/branches/extbuild/src/other/ext/stepcode/src/CMakeLists.txt  
2020-11-07 02:19:55 UTC (rev 77703)
+++ brlcad/branches/extbuild/src/other/ext/stepcode/src/CMakeLists.txt  
2020-11-07 02:31:05 UTC (rev 77704)
@@ -1,5 +1,4 @@
 add_subdirectory(express)
-add_subdirectory(exppp)
 add_subdirectory(exp2cxx)
 add_subdirectory(utils)
 add_subdirectory(dai)

Modified: 
brlcad/branches/extbuild/src/other/ext/stepcode/src/exp2cxx/CMakeLists.txt
===================================================================
--- brlcad/branches/extbuild/src/other/ext/stepcode/src/exp2cxx/CMakeLists.txt  
2020-11-07 02:19:55 UTC (rev 77703)
+++ brlcad/branches/extbuild/src/other/ext/stepcode/src/exp2cxx/CMakeLists.txt  
2020-11-07 02:31:05 UTC (rev 77704)
@@ -26,7 +26,7 @@
   )
 
 add_executable(exp2cxx ${exp2cxx_SOURCES})
-target_link_libraries(exp2cxx exppp express)
+target_link_libraries(exp2cxx express)
 install(TARGETS exp2cxx
   RUNTIME DESTINATION ${BIN_DIR}
   LIBRARY DESTINATION ${LIB_DIR}

Modified: brlcad/branches/extbuild/src/other/ext/stepcode/src/exp2cxx/classes.h
===================================================================
--- brlcad/branches/extbuild/src/other/ext/stepcode/src/exp2cxx/classes.h       
2020-11-07 02:19:55 UTC (rev 77703)
+++ brlcad/branches/extbuild/src/other/ext/stepcode/src/exp2cxx/classes.h       
2020-11-07 02:31:05 UTC (rev 77704)
@@ -23,7 +23,7 @@
 
 
 #include "express/express.h"
-#include "exppp/exppp.h"
+#include "express/exppp.h"
 #include "express/dict.h"
 
 #define MAX_LEN              240

Modified: 
brlcad/branches/extbuild/src/other/ext/stepcode/src/exp2cxx/complexSupport.h
===================================================================
--- 
brlcad/branches/extbuild/src/other/ext/stepcode/src/exp2cxx/complexSupport.h    
    2020-11-07 02:19:55 UTC (rev 77703)
+++ 
brlcad/branches/extbuild/src/other/ext/stepcode/src/exp2cxx/complexSupport.h    
    2020-11-07 02:31:05 UTC (rev 77704)
@@ -10,7 +10,7 @@
 #include <string.h>
 #include "classes.h"
 #include "express/express.h"
-#include "exppp/exppp.h"
+#include "express/exppp.h"
 #include "express/dict.h"
 }
 

Modified: 
brlcad/branches/extbuild/src/other/ext/stepcode/src/express/CMakeLists.txt
===================================================================
--- brlcad/branches/extbuild/src/other/ext/stepcode/src/express/CMakeLists.txt  
2020-11-07 02:19:55 UTC (rev 77703)
+++ brlcad/branches/extbuild/src/other/ext/stepcode/src/express/CMakeLists.txt  
2020-11-07 02:31:05 UTC (rev 77704)
@@ -42,6 +42,7 @@
   dict.c
   entity.c
   error.c
+  exppp.c
   expr.c
   express.c
   hash.c

Copied: brlcad/branches/extbuild/src/other/ext/stepcode/src/express/exppp.c 
(from rev 77703, 
brlcad/branches/extbuild/src/other/ext/stepcode/src/exppp/exppp.c)
===================================================================
--- brlcad/branches/extbuild/src/other/ext/stepcode/src/express/exppp.c         
                (rev 0)
+++ brlcad/branches/extbuild/src/other/ext/stepcode/src/express/exppp.c 
2020-11-07 02:31:05 UTC (rev 77704)
@@ -0,0 +1,2351 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include "config.h"
+
+#ifdef HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+#include "express/expbasic.h"
+#include "express/express.h"
+#include "express/exppp.h"
+
+#define EXPR_out(e,p) EXPR__out(e,p,OP_UNKNOWN)
+#define EXPRop2_out(oe,string,paren,pad) \
+        EXPRop2__out(oe,string,paren,pad,OP_UNKNOWN)
+#define EXPRop_out(oe,paren) EXPRop__out(oe,paren,OP_UNKNOWN)
+
+void ALGscope_out( Scope s, int level );
+void ENTITYattrs_out( Linked_List attributes, int derived, int level );
+void ENTITY_out( Entity e, int level );
+void ENTITYinverse_out( Linked_List attrs, int level );
+void ENTITYunique_out( Linked_List u, int level );
+void EXPRop__out( struct Op_Subexpression * oe, int paren, int previous_op );
+void EXPRop_string( char * buffer, struct Op_Subexpression * oe );
+void EXPRop1_out( struct Op_Subexpression * eo, char * opcode, int paren );
+void EXPRop2__out( struct Op_Subexpression * eo, char * opcode, int paren, int 
pad, int previous_op );
+void EXPR__out( Expression expr, int paren, int previous_op );
+void EXPRbounds_out( TypeBody tb );
+int EXPRlength( Expression e );
+void FUNC_out( Function fn, int level );
+void PROC_out( Procedure p, int level );
+void REFout( Dictionary refdict, Linked_List reflist, char * type, int level );
+void RULE_out( Rule r, int level );
+void SCOPEalgs_out( Scope s, int level );
+void SCOPEconsts_out( Scope s, int level );
+void SCOPEentities_out( Scope s, int level );
+void SCOPElocals_out( Scope s, int level );
+void SCOPEtypes_out( Scope s, int level );
+void STMT_out( Statement s, int level );
+void STMTlist_out( Linked_List stmts, int level );
+void TYPE_out( Type t, int level );
+void TYPE_head_out( Type t, int level );
+void TYPE_body_out( Type t, int level );
+void WHERE_out( Linked_List wheres, int level );
+
+static Error ERROR_select_empty;
+
+int exppp_nesting_indent = 2;       /* default nesting indent */
+int exppp_continuation_indent = 4;  /* default nesting indent for */
+/* continuation lines */
+int exppp_linelength = 75;          /* leave some room for closing
+                                     * parens. '\n' is not included in this
+                                     * count either
+                                     */
+int indent2;        /* where continuation lines start */
+int curpos;     /* current line position (1 is first position) */
+
+#define NOLEVEL -1  /* unused-level indicator */
+
+char * exppp_output_filename = ( char * )0; /* if this is set, override */
+/* default output filename */
+char filename[1000];    /* output file name */
+Symbol error_sym;   /* only used when printing errors */
+
+char * expheader[] = {
+    "(* This file was generated by exppp (an EXPRESS Pretty Printer)"   ,
+    "written at the National Institute of Standards and Technology"     ,
+    "by Don Libes, February 19, 1993."                  ,
+    ""                                  ,
+    "WARNING: If you modify this file and want to save the changes,"    ,
+    "delete this comment block or else the file will be rewritten"      ,
+    "the next time exppp processes this schema. *)"             ,
+    0
+};
+
+bool exppp_output_filename_reset;    /* if true, force output filename */
+
+bool exppp_alphabetize = false;
+
+bool exppp_terse = false;
+
+bool exppp_reference_info = false;   /* if true, add commentary */
+/* about where things came from */
+
+bool exppp_preserve_comments = false;
+
+bool exppp_rmpp = true;
+char rmfilename[] = "rmpp";
+FILE * rm;
+
+char * rmheader[] = {
+    "# This file was generated by exppp (an EXPRESS Pretty Printer)"    ,
+    "# written at the National Institute of Standards and Technology"   ,
+    "# by Don Libes, February 19, 1993."                    ,
+    ""                                  ,
+    "# Run this script from the shell to remove any files created by"   ,
+    "# the last run of exppp."                      ,
+    ""                                  ,
+    0
+};
+
+FILE * exppp_fp = NULL;     /* output file */
+char * exppp_buf = 0;       /* output buffer */
+int exppp_maxbuflen = 0;        /* size of expppbuf */
+int exppp_buflen = 0;       /* remaining space in expppbuf */
+char * exppp_bufp = 0;      /* pointer to write position in expppbuf */
+/* should usually be pointing to a "\0" */
+
+/* count newlines in a string */
+int
+count_newlines( s )
+char * s;
+{
+    int count = 0;
+    for( ; *s; s++ ) {
+        if( *s == '\n' ) {
+            count++;
+        }
+    }
+    return count;
+}
+
+void
+exp_output( char * buf, int len ) {
+    FILE * fp = ( exppp_fp ? exppp_fp : stdout );
+
+    error_sym.line += count_newlines( buf );
+
+    if( exppp_buf ) {
+        /* output to string */
+        if( len > exppp_buflen ) {
+            /* should provide flag to enable complaint */
+            /* for now, just ignore */
+            return;
+        }
+        memcpy( exppp_bufp, buf, len + 1 );
+        exppp_bufp += len;
+        exppp_buflen -= len;
+    } else {
+        /* output to file */
+        fwrite( buf, 1, len, fp );
+    }
+}
+
+void
+
+wrap( char * fmt, ... ) {
+    char * p;
+    char buf[10000];
+    int len;
+    va_list args;
+
+    va_start( args, fmt );
+    vsprintf( buf, fmt, args );
+    va_end( args );
+
+    len = strlen( buf );
+
+    /* 1st condition checks if string cant fit into current line */
+    /* 2nd condition checks if string cant fit into any line */
+    /* I.e., if we still can't fit after indenting, don't bother to */
+    /* go to newline, just print a long line */
+    if( ( ( curpos + len ) > exppp_linelength ) &&
+            ( ( indent2 + len ) < exppp_linelength ) ) {
+        /* move to new continuation line */
+        char line[1000];
+        sprintf( line, "\n%*s", indent2, "" );
+        exp_output( line, 1 + indent2 );
+
+        curpos = indent2;       /* reset current position */
+    }
+
+    exp_output( buf, len );
+
+    if( len ) {
+        /* reset cur position based on last newline seen */
+        if( 0 == ( p = strrchr( buf, '\n' ) ) ) {
+            curpos += len;
+        } else {
+            curpos = len + buf - p;
+        }
+    }
+}
+
+void
+raw( char * fmt, ... ) {
+    char * p;
+    char buf[10000];
+    int len;
+    va_list args;
+
+    va_start( args, fmt );
+    vsprintf( buf, fmt, args );
+    va_end( args );
+
+    len = strlen( buf );
+
+    exp_output( buf, len );
+
+    if( len ) {
+        /* reset cur position based on last newline seen */
+        if( 0 == ( p = strrchr( buf, '\n' ) ) ) {
+            curpos += len;
+        } else {
+            curpos = len + buf - p;
+        }
+    }
+}
+
+void
+exppp_init() {
+    static bool first_time = true;
+
+    if( !first_time ) {
+        return;
+    }
+    first_time = false;
+
+    ERROR_select_empty = ERRORcreate(
+                             "select type %s has no members", SEVERITY_ERROR );
+}
+
+void
+EXPRESSout( Express e ) {
+    Schema s;
+    DictionaryEntry de;
+    char ** hp;
+
+    exppp_init();
+
+    if( exppp_rmpp ) {
+        if( !( rm = fopen( rmfilename, "w" ) ) ) {
+            ERRORreport( ERROR_file_unwriteable, rmfilename, strerror( errno ) 
);
+            return;
+        }
+
+        for( hp = rmheader; *hp; hp++ ) {
+            fprintf( rm, "%s\n", *hp );
+        }
+        fprintf( rm, "rm -f" );
+    }
+
+    DICTdo_init( e->symbol_table, &de );
+    while( 0 != ( s = ( Schema )DICTdo( &de ) ) ) {
+        ( void ) SCHEMAout( s );
+    }
+
+    if( exppp_rmpp ) {
+        fprintf( rm, " %s\n", rmfilename );
+
+        /* owner+group executable, readable to world */
+        if( 0 != chmod( rmfilename, 0774 ) ) {
+            fprintf( stderr, "%s: could not mark %s executable (%s)\n",
+                     EXPRESSprogram_name, rmfilename, strerror( errno ) );
+            return;
+        }
+    }
+}
+
+void
+exppp_ref_info( Symbol * s ) {
+    if( exppp_reference_info ) {
+        raw( "--info %s %s %d\n", s->name, s->filename, s->line );
+    }
+}
+
+/* normally all non-schema objects start out by printing a newline */
+/* however, this is undesirable when printing out single objects */
+/* use this variable to avoid it */
+static bool first_line = true;       /* if first line */
+
+static void
+first_newline() {
+    if( first_line ) {
+        first_line = false;
+    } else {
+        raw( "\n" );
+    }
+}
+
+char *      /* returns name of file written to in static storage */
+SCHEMAout( Schema s ) {
+#define BUFSIZE     80
+    char buf[BUFSIZE];
+    char * p;
+    FILE * f;
+    int level = 0;
+    char ** hp;
+    bool described = false;
+
+    if( exppp_output_filename_reset ) {
+        exppp_output_filename = 0;
+    }
+
+    if( exppp_output_filename ) {
+        strcpy( filename, exppp_output_filename );
+    } else {
+        /* when there is only a single file, allow user to find */
+        /* out what it is */
+        exppp_output_filename = filename;
+        exppp_output_filename_reset = true;
+
+        /* since we have to generate a filename, make sure we don't */
+        /* overwrite a valuable file */
+
+        sprintf( filename, "%s.exp", s->symbol.name );
+
+        if( 0 != ( f = fopen( filename, "r" ) ) ) {
+            fgets( buf, BUFSIZE, f );
+            if( 0 != ( p = strchr( buf, '\n' ) ) ) {
+                *p = '\0';
+            }
+            if( streq( buf, expheader[0] ) ) {
+                unlink( filename );
+            } else {
+                fprintf( stderr, "%s: %s already exists and appears to be 
hand-written\n",
+                         EXPRESSprogram_name, filename );
+                /*          strcat(bp,".pp");*/
+                strcat( filename, ".pp" );
+                fprintf( stderr, "%s: writing schema file %s instead\n",
+                         EXPRESSprogram_name, filename );
+                described = true;
+            }
+        }
+        if( f ) {
+            fclose( f );
+        }
+    }
+    error_sym.filename = filename;
+
+    if( !described && !exppp_terse ) {
+        fprintf( stdout, "%s: writing schema file %s\n", EXPRESSprogram_name, 
filename );
+    }
+    if( !( exppp_fp = f = fopen( filename, "w" ) ) ) {
+        ERRORreport( ERROR_file_unwriteable, filename, strerror( errno ) );
+        return 0;
+    }
+
+    if( exppp_rmpp && rm ) {
+        fprintf( rm, " %s", filename );
+    }
+
+    error_sym.line = 1;
+    for( hp = expheader; *hp; hp++ ) {
+        raw( "%s\n", *hp );
+    }
+
+    /*  first_newline();*/
+    /*  raw("SCHEMA %s;\n",s->symbol.name);*/
+
+    first_line = false;
+    raw( "\nSCHEMA %s;\n", s->symbol.name );
+
+    if( s->u.schema->usedict || s->u.schema->use_schemas
+            || s->u.schema->refdict || s->u.schema->ref_schemas ) {
+        raw( "\n" );
+    }
+
+    REFout( s->u.schema->usedict, s->u.schema->use_schemas, "USE", level + 
exppp_nesting_indent );
+    REFout( s->u.schema->refdict, s->u.schema->ref_schemas, "REFERENCE", level 
+ exppp_nesting_indent );
+
+    SCOPEconsts_out( s, level + exppp_nesting_indent );
+    SCOPEtypes_out( s, level + exppp_nesting_indent );
+    SCOPEentities_out( s, level + exppp_nesting_indent );
+    SCOPEalgs_out( s, level + exppp_nesting_indent );
+
+    raw( "\nEND_SCHEMA; -- %s\n", s->symbol.name );
+
+    fclose( exppp_fp );
+
+    return filename;
+}
+
+void
+REFout( Dictionary refdict, Linked_List reflist, char * type, int level ) {
+    Dictionary dict;
+    DictionaryEntry de;
+    struct Rename * r;
+    Linked_List list;
+
+    LISTdo( reflist, s, Schema )
+    raw( "%s FROM %s;\n", type, s->symbol.name );
+    LISTod
+
+    if( !refdict ) {
+        return;
+    }
+    dict = DICTcreate( 10 );
+
+    /* sort each list by schema */
+
+    /* step 1: for each entry, store it in a schema-specific list */
+    DICTdo_init( refdict, &de );
+    while( 0 != ( r = ( struct Rename * )DICTdo( &de ) ) ) {
+        Linked_List list;
+
+        list = ( Linked_List )DICTlookup( dict, r->schema->symbol.name );
+        if( !list ) {
+            list = LISTcreate();
+            DICTdefine( dict, r->schema->symbol.name, ( Generic ) list,
+                        ( Symbol * )0, OBJ_UNKNOWN );
+        }
+        LISTadd( list, ( Generic ) r );
+    }
+
+    /* step 2: for each list, print out the renames */
+    level = 6;  /* no special reason, feels good */
+    indent2 = level + exppp_continuation_indent;
+    DICTdo_init( dict, &de );
+    while( 0 != ( list = ( Linked_List )DICTdo( &de ) ) ) {
+        bool first_time = true;
+        LISTdo( list, r, struct Rename * )
+        if( first_time ) {
+            raw( "%s FROM %s\n", type, r->schema->symbol.name );
+        } else {
+            /* finish previous line */
+            raw( ",\n" );
+        }
+
+        if( first_time ) {
+            raw( "%*s(", level, "" );
+            first_time = false;
+        } else {
+            raw( "%*s ", level, "" );
+        }
+        raw( r->old->name );
+        if( r->old != r->nnew ) {
+            wrap( " AS %s", r->nnew->name );
+        }
+        LISTod
+        raw( ");\n" );
+    }
+    HASHdestroy( dict );
+}
+
+void
+ALGscope_out( Scope s, int level ) {
+    SCOPEtypes_out( s, level );
+    SCOPEentities_out( s, level );
+    SCOPEalgs_out( s, level );
+
+    SCOPEconsts_out( s, level );
+    SCOPElocals_out( s, level );
+}
+
+void
+SCOPEadd_inorder( Linked_List list, Scope s ) {
+    Link k = 0;
+
+    LISTdo_links( list, link )
+    if( 0 > strcmp(
+                SCOPEget_name( s ),
+                SCOPEget_name( ( Type )( link->data ) ) ) ) {
+        k = link;
+        break;
+    }
+    LISTod
+
+    LISTadd_before( list, k, ( Generic )s );
+}
+
+/* print the rules in a scope */
+void
+SCOPErules_out( Scope s, int level ) {
+    Rule r;
+    DictionaryEntry de;
+
+    if( exppp_alphabetize == false ) {
+        DICTdo_type_init( s->symbol_table, &de, OBJ_RULE );
+        while( 0 != ( r = ( Rule )DICTdo( &de ) ) ) {
+            RULE_out( r, level );
+        }
+    } else {
+        Linked_List alpha = LISTcreate();
+
+        DICTdo_type_init( s->symbol_table, &de, OBJ_RULE );
+        while( 0 != ( r = ( Rule )DICTdo( &de ) ) ) {
+            SCOPEadd_inorder( alpha, r );
+        }
+
+        LISTdo( alpha, r, Rule )
+        RULE_out( r, level );
+        LISTod
+
+        LISTfree( alpha );
+    }
+
+}
+
+/* print the functions in a scope */
+void
+SCOPEfuncs_out( Scope s, int level ) {
+    Function f;
+    DictionaryEntry de;
+
+    if( exppp_alphabetize == false ) {
+        DICTdo_type_init( s->symbol_table, &de, OBJ_FUNCTION );
+        while( 0 != ( f = ( Function )DICTdo( &de ) ) ) {
+            FUNC_out( f, level );
+        }
+    } else {
+        Linked_List alpha = LISTcreate();
+
+        DICTdo_type_init( s->symbol_table, &de, OBJ_FUNCTION );
+        while( 0 != ( f = ( Function )DICTdo( &de ) ) ) {
+            SCOPEadd_inorder( alpha, f );
+        }
+
+        LISTdo( alpha, f, Function )
+        FUNC_out( f, level );
+        LISTod
+
+        LISTfree( alpha );
+    }
+
+}
+
+/* print the procs in a scope */
+void
+SCOPEprocs_out( Scope s, int level ) {
+    Procedure p;
+    DictionaryEntry de;
+
+    if( exppp_alphabetize == false ) {
+        DICTdo_type_init( s->symbol_table, &de, OBJ_PROCEDURE );
+        while( 0 != ( p = ( Procedure )DICTdo( &de ) ) ) {
+            PROC_out( p, level );
+        }
+    } else {
+        Linked_List alpha = LISTcreate();
+
+        DICTdo_type_init( s->symbol_table, &de, OBJ_PROCEDURE );
+        while( 0 != ( p = ( Procedure )DICTdo( &de ) ) ) {
+            SCOPEadd_inorder( alpha, p );
+        }
+
+        LISTdo( alpha, p, Procedure )
+        PROC_out( p, level );
+        LISTod
+
+        LISTfree( alpha );
+    }
+
+}
+
+/* print the algorithms in a scope */
+void
+SCOPEalgs_out( Scope s, int level ) {
+    /* Supplementary Directivies 2.1.1 requires rules to be separated */
+    /* might as well separate funcs and procs, too */
+    SCOPErules_out( s, level );
+    SCOPEfuncs_out( s, level );
+    SCOPEprocs_out( s, level );
+}
+
+static int
+minimum( int a, int b, int c ) {
+    if( a < b ) {
+        return ( ( a < c ) ? a : c );
+    } else {
+        return ( ( b < c ) ? b : c );
+    }
+}
+
+static void copy_file_chunk( char * filename, int start, int end, int level ) {
+    FILE * infile;
+    char buff[256];
+    int i, indent, undent = 0, fix;
+
+    if( !( infile = fopen( filename, "r" ) ) ) {
+        ERRORreport( ERROR_file_unreadable, filename, strerror( errno ) );
+    }
+
+    /* skip to start of chunk */
+    for( i = start; --i; ) {
+        fgets( buff, 255, infile );
+    }
+
+    /* copy first line and compute indentation correction factor */
+    fgets( buff, 255, infile );
+    indent = level - strspn( buff, " " );
+    if( indent < 0 ) {
+        undent = -indent;
+        indent = 0;
+    }
+    raw( "%*s%s", indent, "", buff + undent );
+    indent = indent - undent;
+
+    /* copy the rest */
+    for( i = end - start; i--; ) {
+        fgets( buff, 255, infile );
+        fix = minimum( undent, strlen( buff ), strspn( buff, " " ) );
+        raw( "%*s%s", indent + fix, "", buff + fix );
+    }
+
+    fclose( infile );
+}
+
+void
+RULE_out( Rule r, int level ) {
+    first_newline();
+    exppp_ref_info( &r->symbol );
+
+    if( exppp_preserve_comments == false ) {
+        int i = 0;
+        raw( "%*sRULE %s FOR (", level, "", r->symbol.name );
+
+        LISTdo( r->u.rule->parameters, p, Variable )
+        i++;
+        if( i != 1 ) {
+            raw( ", " );
+        }
+        wrap( p->name->symbol.name );
+        LISTod;
+        raw( ");\n" );
+
+        ALGscope_out( r, level + exppp_nesting_indent );
+        STMTlist_out( r->u.rule->body, level + exppp_nesting_indent );
+        raw( "\n" );
+        WHERE_out( RULEget_where( r ), level );
+
+        raw( "\n%*sEND_RULE; -- %s\n", level, "", r->symbol.name );
+    } else {
+        copy_file_chunk( r->symbol.filename, r->u.rule->text.start,
+                         r->u.rule->text.end, level );
+    }
+}
+
+/* last arg is not terminated with ; or \n */
+void
+ALGargs_out( Linked_List args, int level ) {
+    Type previoustype = 0;
+    indent2 = level + exppp_continuation_indent;
+
+    /* combine adjacent parameters that have the same type */
+
+    LISTdo( args, v, Variable )
+    if( previoustype != v->type ) {
+        if( previoustype ) {
+            wrap( ":" );
+            TYPE_head_out( previoustype, NOLEVEL );
+            raw( ";\n" );
+        }
+        raw( "%*s", level, "" );
+        EXPR_out( VARget_name( v ), 0 );
+    } else {
+        raw( ", " );
+        EXPR_out( VARget_name( v ), 0 );
+    }
+    previoustype = v->type;
+    LISTod
+
+    wrap( ":" );
+    TYPE_head_out( previoustype, NOLEVEL );
+}
+
+void
+FUNC_out( Function fn, int level ) {
+    if( fn->u.func->builtin ) {
+        return;
+    }
+
+    first_newline();
+    exppp_ref_info( &fn->symbol );
+
+    if( exppp_preserve_comments == false ) {
+        raw( "%*sFUNCTION %s", level, "", fn->symbol.name );
+
+        if( fn->u.func->parameters ) {
+            raw( "(\n" );
+            ALGargs_out( fn->u.func->parameters,
+                         level + strlen( "FUNCTION     " ) );
+            raw( "\n%*s)", level + exppp_continuation_indent, "" );
+        }
+        raw( ":" );
+
+        indent2 = curpos + exppp_continuation_indent;
+        TYPE_head_out( fn->u.func->return_type, NOLEVEL );
+        raw( ";\n" );
+
+        ALGscope_out( fn, level + exppp_nesting_indent );
+        STMTlist_out( fn->u.proc->body, level + exppp_nesting_indent );
+
+        raw( "\n%*sEND_FUNCTION; -- %s\n", level, "", fn->symbol.name );
+    } else {
+        copy_file_chunk( fn->symbol.filename, fn->u.func->text.start,
+                         fn->u.func->text.end, level );
+    }
+}
+void
+PROC_out( Procedure p, int level ) {
+    if( p->u.proc->builtin ) {
+        return;
+    }
+
+    first_newline();
+    exppp_ref_info( &p->symbol );
+
+    if( exppp_preserve_comments == false ) {
+        raw( "%*sPROCEDURE %s(\n", level, "", p->symbol.name );
+
+        ALGargs_out( p->u.proc->parameters, level + strlen( "PROCEDURE     " ) 
);
+
+        raw( "%*s);\n", level + exppp_nesting_indent, "" );
+
+        ALGscope_out( p, level + exppp_nesting_indent );
+        STMTlist_out( p->u.proc->body, level + exppp_nesting_indent );
+
+        raw( "\n%*sEND_PROCEDURE; -- %s\n", level, "", p->symbol.name );
+    } else {
+        copy_file_chunk( p->symbol.filename, p->u.proc->text.start,
+                         p->u.proc->text.end, level );
+    }
+}
+
+void
+SCOPEconsts_out( Scope s, int level ) {
+    Variable v;
+    DictionaryEntry de;
+    size_t max_indent = 0;
+    Dictionary d = s->symbol_table;
+
+    DICTdo_type_init( d, &de, OBJ_VARIABLE );
+    while( 0 != ( v = ( Variable )DICTdo( &de ) ) ) {
+        if( !v->flags.constant ) {
+            continue;
+        }
+        if( strlen( v->name->symbol.name ) > max_indent ) {
+            max_indent = strlen( v->name->symbol.name );
+        }
+    }
+
+    if( !max_indent ) {
+        return;
+    }
+
+    first_newline();
+
+    raw( "%*sCONSTANT\n", level, "" );
+
+    indent2 = level + max_indent + strlen( ": " ) + exppp_continuation_indent;
+
+    DICTdo_type_init( d, &de, OBJ_VARIABLE );
+    while( 0 != ( v = ( Variable )DICTdo( &de ) ) ) {
+        if( !v->flags.constant ) {
+            continue;
+        }
+
+        /* print attribute name */
+        raw( "%*s%-*s :", level, "",
+             max_indent, v->name->symbol.name );
+
+        /* print attribute type */
+        if( VARget_optional( v ) ) {
+            wrap( " OPTIONAL" );
+        }
+        TYPE_head_out( v->type, NOLEVEL );
+
+        if( v->initializer ) {
+            wrap( " := " );
+            EXPR_out( v->initializer, 0 );
+        }
+
+        raw( ";\n" );
+    }
+
+    raw( "%*sEND_CONSTANT;\n", level, "" );
+}
+
+void
+SCOPElocals_out( Scope s, int level ) {
+    Variable v;
+    DictionaryEntry de;
+    size_t max_indent = 0;
+    Dictionary d = s->symbol_table;
+
+    DICTdo_type_init( d, &de, OBJ_VARIABLE );
+    while( 0 != ( v = ( Variable )DICTdo( &de ) ) ) {
+        if( v->flags.constant ) {
+            continue;
+        }
+        if( v->flags.parameter ) {
+            continue;
+        }
+        if( strlen( v->name->symbol.name ) > max_indent ) {
+            max_indent = strlen( v->name->symbol.name );
+        }
+    }
+
+    if( !max_indent ) {
+        return;
+    }
+
+    first_newline();
+
+    raw( "%*sLOCAL\n", level, "" );
+    indent2 = level + max_indent + strlen( ": " ) + exppp_continuation_indent;
+
+    DICTdo_type_init( d, &de, OBJ_VARIABLE );
+    while( 0 != ( v = ( Variable )DICTdo( &de ) ) ) {
+        if( v->flags.constant ) {
+            continue;
+        }
+        if( v->flags.parameter ) {
+            continue;
+        }
+
+        /* print attribute name */
+        raw( "%*s%-*s :", level + exppp_nesting_indent, "",
+             max_indent, v->name->symbol.name );
+
+        /* print attribute type */
+        if( VARget_optional( v ) ) {
+            wrap( " OPTIONAL" );
+        }
+        TYPE_head_out( v->type, NOLEVEL );
+
+        if( v->initializer ) {
+            wrap( " := " );
+            EXPR_out( v->initializer, 0 );
+        }
+
+        raw( ";\n" );
+    }
+
+    raw( "%*sEND_LOCAL;\n", level, "" );
+}
+
+void LOOPout( struct Loop_ *loop, int level ) {
+    Variable v;
+
+    raw( "%*sREPEAT", level, "" );
+
+    /* increment */
+    /*  if (loop->scope->u.incr) {*/
+    if( loop->scope ) {
+        DictionaryEntry de;
+
+        DICTdo_init( loop->scope->symbol_table, &de );
+        v = ( Variable )DICTdo( &de );
+        wrap( " %s := ", v->name->symbol.name );
+        EXPR_out( loop->scope->u.incr->init, 0 );
+        wrap( " TO " );
+        EXPR_out( loop->scope->u.incr->end, 0 );
+        wrap( " BY " ); /* parser always forces a "by" expr */
+        EXPR_out( loop->scope->u.incr->increment, 0 );
+    }
+
+    /* while */
+    if( loop->while_expr ) {
+        wrap( " WHILE " );
+        EXPR_out( loop->while_expr, 0 );
+    }
+
+    /* until */
+    if( loop->until_expr ) {
+        wrap( " UNTIL " );
+        EXPR_out( loop->until_expr, 0 );
+    }
+
+    raw( ";\n" );
+
+    STMTlist_out( loop->statements, level + exppp_nesting_indent );
+
+    raw( "%*sEND_REPEAT;\n", level, "" );
+}
+
+void
+CASEout( struct Case_Statement_ *c, int level ) {
+    int len = 0;
+    int max_indent;
+
+    raw( "%*sCASE ", level, "" );
+    EXPR_out( c->selector, 0 );
+    wrap( " OF\n" );
+
+    /* pass 1: calculate length of longest label */
+    max_indent = 0;
+    LISTdo( c->cases, ci, Case_Item )
+    if( ci->labels ) {
+        LISTdo( ci->labels, label, Expression )
+        len = EXPRlength( label );
+        LISTod
+    } else {
+        len = strlen( "OTHERWISE" );
+    }
+    if( len > max_indent ) {
+        max_indent = len;
+    }
+    LISTod
+
+    level += exppp_nesting_indent;
+
+    /* pass 2: print them */
+    LISTdo( c->cases, ci, Case_Item )
+    if( ci->labels ) {
+        LISTdo( ci->labels, label, Expression )
+        /* print label(s) */
+        indent2 = level + exppp_continuation_indent;
+        raw( "%*s", level, "" );
+        EXPR_out( label, 0 );
+        raw( "%*s : ", level + max_indent - curpos, "" );
+
+        /* print action */
+        STMT_out( ci->action, level + exppp_nesting_indent );
+        LISTod
+    } else {
+        /* print OTHERWISE */
+        indent2 = level + exppp_continuation_indent;
+        raw( "%*s", level, "" );
+        raw( "OTHERWISE" );
+        raw( "%*s : ", level + max_indent - curpos, "" );
+
+        /* print action */
+        STMT_out( ci->action, level + exppp_nesting_indent );
+    }
+    LISTod
+
+    raw( "%*sEND_CASE;\n", level, "" );
+}
+
+void
+STMT_out( Statement s, int level ) {
+    bool first_time = true;
+
+    if( !s ) {  /* null statement */
+        raw( "%*s;\n", level, "" );
+        return;
+    }
+
+    indent2 = level + exppp_continuation_indent;
+
+    switch( s->type ) {
+        case STMT_ASSIGN:
+            raw( "%*s", level, "" );
+            EXPR_out( s->u.assign->lhs, 0 );
+            wrap( " := " );
+            EXPR_out( s->u.assign->rhs, 0 );
+            raw( ";\n", level, "" );
+            break;
+        case STMT_CASE:
+            CASEout( s->u.Case, level );
+            break;
+        case STMT_COMPOUND:
+            raw( "%*sBEGIN\n", level, "" );
+            STMTlist_out( s->u.compound->statements, level + 
exppp_nesting_indent );
+            raw( "%*sEND;\n", level, "" );
+            break;
+        case STMT_COND:
+            raw( "%*sIF ", level, "" );
+            EXPR_out( s->u.cond->test, 0 );
+            wrap( " THEN\n" );
+            STMTlist_out( s->u.cond->code, level + exppp_nesting_indent );
+            if( s->u.cond->otherwise ) {
+                raw( "%*sELSE\n", level, "" );
+                STMTlist_out( s->u.cond->otherwise, level + 
exppp_nesting_indent );
+            }
+            raw( "%*sEND_IF;\n", level, "" );
+            break;
+        case STMT_LOOP:
+            LOOPout( s->u.loop, level );
+            break;
+        case STMT_PCALL:
+            raw( "%*s%s(", level, "", s->symbol.name );
+            LISTdo( s->u.proc->parameters, p, Expression )
+            if( first_time ) {
+                first_time = false;
+            } else {
+                raw( "," );
+            }
+            EXPR_out( p, 0 );
+            LISTod
+            raw( ");\n" );
+            break;
+        case STMT_RETURN:
+            raw( "%*sRETURN", level, "" );
+            if( s->u.ret->value ) {
+                wrap( "(" );
+                EXPR_out( s->u.ret->value, 0 );
+                raw( ")" );
+            }
+            raw( ";\n" );
+            break;
+        case STMT_ALIAS:
+            raw( "%*sALIAS %s for %s;\n", level, "", s->symbol.name,
+                 /* should be generalized reference */
+                 s->u.alias->variable->name->symbol.name );
+            STMTlist_out( s->u.alias->statements, level + exppp_nesting_indent 
);
+            raw( "%*sEND_ALIAS; -- %s\n", level, "", s->symbol.name );
+            break;
+        case STMT_SKIP:
+            raw( "%*sSKIP;\n", level, "" );
+            break;
+        case STMT_ESCAPE:
+            raw( "%*sESCAPE;\n", level, "" );
+            break;
+    }
+}
+
+void
+STMTlist_out( Linked_List stmts, int level ) {
+    LISTdo( stmts, stmt, Statement )
+    STMT_out( stmt, level );
+    LISTod
+}
+
+/* print all entities in a scope */
+void
+SCOPEentities_out( Scope s, int level ) {
+    Entity e;
+    DictionaryEntry de;
+
+    if( exppp_alphabetize == false ) {
+        DICTdo_type_init( s->symbol_table, &de, OBJ_ENTITY );
+        while( 0 != ( e = ( Entity )DICTdo( &de ) ) ) {
+            ENTITY_out( e, level );
+        }
+    } else {
+        Linked_List alpha = LISTcreate();
+
+        DICTdo_type_init( s->symbol_table, &de, OBJ_ENTITY );
+        while( 0 != ( e = ( Entity )DICTdo( &de ) ) ) {
+            SCOPEadd_inorder( alpha, e );
+        }
+
+        LISTdo( alpha, e, Entity )
+        ENTITY_out( e, level );
+        LISTod
+
+        LISTfree( alpha );
+    }
+}
+
+void
+SUBTYPEout( Expression e ) {
+    /* language insists on having parens around entity names */
+    /* even if there is only one, but if the expression is */
+    /* complex, EXPRout will add on its own parens */
+    /*  if (TYPEis_expression(e->type)) {*/
+    raw( "(" );
+    /*  }*/
+
+    EXPR_out( e, 0 );
+
+    /*  if (TYPEis_expression(e->type)) {*/
+    raw( ")" );
+    /*  }*/
+}
+
+#define EXPLICIT 0
+#define DERIVED 1
+
+void
+ENTITY_out( Entity e, int level ) {
+    bool first_time = true;
+
+    first_newline();
+    exppp_ref_info( &e->symbol );
+
+    raw( "%*sENTITY %s", level, "", e->symbol.name );
+
+    level += exppp_nesting_indent;
+    indent2 = level + exppp_continuation_indent;
+
+    if( ENTITYget_abstract( e ) ) {
+        if( e->u.entity->subtype_expression ) {
+            raw( "\n%*sABSTRACT SUPERTYPE OF ", level, "" );
+            SUBTYPEout( e->u.entity->subtype_expression );
+        } else {
+            raw( "\n%*sABSTRACT SUPERTYPE", level, "" );
+        }
+    } else {
+        if( e->u.entity->subtype_expression ) {
+            raw( "\n%*sSUPERTYPE OF ", level, "" );
+            SUBTYPEout( e->u.entity->subtype_expression );
+        }
+    }
+
+    if( e->u.entity->supertype_symbols ) {
+        raw( "\n%*sSUBTYPE OF (", level, "" );
+
+        LISTdo( e->u.entity->supertype_symbols, s, Symbol * )
+        if( first_time ) {
+            first_time = false;
+        } else {
+            raw( ", " );
+        }
+        wrap( s->name );
+        LISTod
+        raw( ")" );
+    }
+
+    raw( ";\n" );
+
+#if 0
+    /* add a little more space before entities if sub or super appears */
+    if( e->u.entity->supertype_symbols || e->u.entity->subtype_expression ) {
+        raw( "\n" );
+    }
+#endif
+
+    ENTITYattrs_out( e->u.entity->attributes, EXPLICIT, level );
+    ENTITYattrs_out( e->u.entity->attributes, DERIVED, level );
+    ENTITYinverse_out( e->u.entity->attributes, level );
+    ENTITYunique_out( e->u.entity->unique, level );
+    WHERE_out( TYPEget_where( e ), level );
+
+    level -= exppp_nesting_indent;
+    raw( "%*sEND_ENTITY; -- %s\n", level, "", e->symbol.name );
+}
+
+void
+ENTITYunique_out( Linked_List u, int level ) {
+    int i;
+    int max_indent;
+    Symbol * sym;
+
+    if( !u ) {
+        return;
+    }
+
+    raw( "%*sUNIQUE\n", level, "" );
+
+    /* pass 1 */
+    max_indent = 0;
+    LISTdo( u, list, Linked_List )
+    if( 0 != ( sym = ( Symbol * )LISTget_first( list ) ) ) {
+        int length;
+        length = strlen( sym->name );
+        if( length > max_indent ) {
+            max_indent = length;
+        }
+    }
+    LISTod
+
+    level += exppp_nesting_indent;
+    indent2 = level + max_indent + strlen( ": " ) + exppp_continuation_indent;
+
+    LISTdo( u, list, Linked_List )
+    i = 0;
+    LISTdo( list, v, Variable )
+    i++;
+    if( i == 1 ) {
+        /* print label if present */
+        if( v ) {
+            raw( "%*s%-*s : ", level, "",
+                 max_indent, ( ( Symbol * )v )->name );
+        } else {
+            raw( "%*s%-*s   ", level, "",
+                 max_indent, "" );
+        }
+    } else {
+        if( i > 2 ) {
+            raw( ", " );
+        }
+        EXPR_out( v->name, 0 );
+    }
+    LISTod
+    raw( ";\n" );
+    LISTod
+}
+
+void
+ENTITYinverse_out( Linked_List attrs, int level ) {
+    int max_indent;
+
+    /* pass 1: calculate length of longest attr name */
+    max_indent = 0;
+    LISTdo( attrs, v, Variable )
+    if( v->inverse_symbol ) {
+        int length;
+        length = strlen( v->name->symbol.name );
+        if( length > max_indent ) {
+            max_indent = length;
+        }
+    }
+    LISTod
+
+    if( max_indent == 0 ) {
+        return;
+    }
+    raw( "%*sINVERSE\n", level, "" );
+    level += exppp_nesting_indent;
+    indent2 = level + max_indent + strlen( ": " ) + exppp_continuation_indent;
+
+    /* pass 2: print them */
+    LISTdo( attrs, v, Variable )
+    if( v->inverse_symbol ) {
+        /* print attribute name */
+        raw( "%*s%-*s :", level, "",
+             max_indent, v->name->symbol.name );
+
+        /* print attribute type */
+        if( VARget_optional( v ) ) {
+            wrap( " OPTIONAL" );
+        }
+        TYPE_head_out( v->type, NOLEVEL );
+
+        raw( " FOR " );
+
+        wrap( v->inverse_attribute->name->symbol.name );
+
+        raw( ";\n" );
+    }
+    LISTod
+}
+
+void
+ENTITYattrs_out( Linked_List attrs, int derived, int level ) {
+    int max_indent;
+
+    /* pass 1: calculate length of longest attr name */
+    max_indent = 0;
+    LISTdo( attrs, v, Variable )
+    if( v->inverse_symbol ) {
+        continue;
+    }
+    if( ( derived && v->initializer ) ||
+            ( !derived && !v->initializer ) ) {
+        int length;
+        length = EXPRlength( v->name );
+        if( length > max_indent ) {
+            max_indent = length;
+        }
+    }
+    LISTod
+
+    if( max_indent == 0 ) {
+        return;
+    }
+    if( derived ) {
+        raw( "%*sDERIVE\n", level, "" );
+    }
+    level += exppp_nesting_indent;
+    indent2 = level + max_indent + strlen( ": " ) + exppp_continuation_indent;
+
+    /* pass 2: print them */
+    LISTdo( attrs, v, Variable )
+    if( v->inverse_symbol ) {
+        continue;
+    }
+    if( ( derived && v->initializer ) ||
+            ( !derived && !v->initializer ) ) {
+        /* print attribute name */
+        raw( "%*s", level, "" );
+        EXPR_out( v->name, 0 );
+        raw( "%*s :", level + max_indent + 1 - curpos, "" );
+
+        /* print attribute type */
+        if( VARget_optional( v ) ) {
+            wrap( " OPTIONAL" );
+        }
+        TYPE_head_out( v->type, NOLEVEL );
+
+        if( derived && v->initializer ) {
+            wrap( " := " );
+            EXPR_out( v->initializer, 0 );
+        }
+
+        raw( ";\n" );
+    }
+    LISTod
+}
+
+void
+WHERE_out( Linked_List wheres, int level ) {
+    size_t max_indent;
+    if( !wheres ) {
+        return;
+    }
+
+    raw( "%*s%s", level, "", "WHERE\n" );
+    level += exppp_nesting_indent;
+
+    /* pass 1: calculate length of longest label */
+    max_indent = 0;
+    LISTdo( wheres, w, Where )
+    if( w->label ) {
+        if( strlen( w->label->name ) > max_indent ) {
+            max_indent = strlen( w->label->name );
+        }
+    }
+    LISTod
+
+    if( max_indent > 10 ) {
+        /* don't bother indenting completely for labels that are */
+        /* ridiculously long */
+        max_indent = 4;
+    }
+    indent2 = level + max_indent + strlen( ": " ) + exppp_continuation_indent;
+
+    /* pass 2: now print labels and exprs */
+    LISTdo( wheres, w, Where )
+    if( w->label ) {
+        raw( "%*s%-*s: ", level, "", max_indent, w->label->name );
+    } else {
+        /* no label */
+        raw( "%*s%-*s  ", level, "", max_indent, "" );
+    }
+    EXPR_out( w->expr, max_indent );
+    raw( ";\n" );
+    LISTod
+}
+
+/* print all types in a scope */
+void
+SCOPEtypes_out( Scope s, int level ) {
+    DictionaryEntry de;
+    Type t;
+
+    if( exppp_alphabetize == false ) {
+        DICTdo_type_init( s->symbol_table, &de, OBJ_TYPE );
+        while( 0 != ( t = ( Type )DICTdo( &de ) ) ) {
+            TYPE_out( t, level );
+        }
+    } else {
+        Linked_List alpha = LISTcreate();
+
+        DICTdo_type_init( s->symbol_table, &de, OBJ_TYPE );
+        while( 0 != ( t = ( Type )DICTdo( &de ) ) ) {
+            SCOPEadd_inorder( alpha, t );
+        }
+
+        LISTdo( alpha, t, Type )
+        TYPE_out( t, level );
+        LISTod
+
+        LISTfree( alpha );
+    }
+}
+
+/* print a type definition.  I.e., a TYPE statement */
+void
+TYPE_out( Type t, int level ) {
+    first_newline();
+    exppp_ref_info( &t->symbol );
+
+    raw( "%*sTYPE %s =", level, "", t->symbol.name );
+    if( TYPEget_head( t ) ) {
+        wrap( " %s", TYPEget_name( TYPEget_head( t ) ) );
+    } else {
+        TYPE_body_out( t, level + exppp_nesting_indent );
+    }
+
+    raw( ";\n" );
+
+    WHERE_out( t->where, level );
+
+    raw( "%*sEND_TYPE; -- %s\n", level, "", t->symbol.name );
+}
+
+/* prints type description (preceded by a space).  I.e., the type of an */
+/* attribute or other object */
+void
+TYPE_head_out( Type t, int level ) {
+    if( t->symbol.name ) {
+        wrap( " %s", t->symbol.name );
+    } else {
+        TYPE_body_out( t, level );
+    }
+}
+
+void TYPEunique_or_optional_out( TypeBody tb ) {
+    if( tb->flags.unique ) {
+        wrap( " UNIQUE" );
+    }
+    if( tb->flags.optional ) {
+        wrap( " OPTIONAL" );
+    }
+}
+
+void
+TYPE_body_out( Type t, int level ) {
+    bool first_time = true;
+
+    Expression expr;
+    DictionaryEntry de;
+
+    TypeBody tb = TYPEget_body( t );
+
+    switch( tb->type ) {
+        case integer_:
+            wrap( " INTEGER" );
+            break;
+        case real_:
+            wrap( " REAL" );
+            break;
+        case string_:
+            wrap( " STRING" );
+            break;
+        case binary_:
+            wrap( " BINARY" );
+            break;
+        case boolean_:
+            wrap( " BOOLEAN" );
+            break;
+        case logical_:
+            wrap( " LOGICAL" );
+            break;
+        case number_:
+            wrap( " NUMBER" );
+            break;
+        case entity_:
+            wrap( " %s", tb->entity->symbol.name );
+            break;
+        case aggregate_:
+        case array_:
+        case bag_:
+        case set_:
+        case list_:
+            switch( tb->type ) {
+                    /* ignore the aggregate bounds for now */
+                case aggregate_:
+                    wrap( " AGGREGATE" );
+                    if( tb->tag ) {
+                        wrap( ":%s", tb->tag->symbol.name );
+                    }
+                    wrap( " OF" );
+                    break;
+
+                case array_:
+                    wrap( " ARRAY" );
+                    EXPRbounds_out( tb );
+                    wrap( " OF" );
+                    TYPEunique_or_optional_out( tb );
+                    break;
+
+                case bag_:
+                    wrap( " BAG" );
+                    EXPRbounds_out( tb );
+                    wrap( " OF" );
+                    break;
+
+                case set_:
+                    wrap( " SET" );
+                    EXPRbounds_out( tb );
+                    wrap( " OF" );
+                    break;
+
+                case list_:
+                    wrap( " LIST" );
+                    EXPRbounds_out( tb );
+                    wrap( " OF" );
+                    TYPEunique_or_optional_out( tb );
+                    break;
+            }
+
+            TYPE_head_out( tb->base, level );
+            break;
+        case enumeration_: {
+#if 1
+            int i, count = 0;
+            char ** names;
+
+            /*
+             * write names out in original order by first bucket sorting
+             * to a temporary array.  This is trivial since all buckets
+             * will get filled with one and only one object.
+             */
+            DICTdo_type_init( t->symbol_table, &de, OBJ_EXPRESSION );
+            while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
+                count++;
+            }
+            names = ( char ** )malloc( count * sizeof( char * ) );
+            DICTdo_type_init( t->symbol_table, &de, OBJ_EXPRESSION );
+            while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
+                names[expr->u.integer - 1] = expr->symbol.name;
+            }
+
+            wrap( " ENUMERATION OF\n" );
+
+            for( i = 0; i < count; i++ ) {
+                /* finish line from previous enum item */
+                if( !first_time ) {
+                    raw( ",\n" );
+                }
+
+                /* start new enum item */
+                if( first_time ) {
+                    raw( "%*s(", level, "" );
+                    first_time = false;
+                } else {
+                    raw( "%*s ", level, "" );
+                }
+                raw( names[i] );
+            }
+            raw( ")" );
+            free( ( char * )names );
+        }
+#else
+            wrap( " ENUMERATION OF\n" );
+            DICTdo_type_init( t->symbol_table, &de, OBJ_EXPRESSION );
+            while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
+
+                /* finish line from previous enum item */
+                if( !first_time ) {
+                    raw( ",\n" );
+                }
+
+                /* start new enum item */
+                if( first_time ) {
+                    raw( "%*s(", level, "" );
+                    first_time = false;
+                } else {
+                    raw( "%*s ", level, "" );
+                }
+                raw( expr->symbol.name );
+            }
+            raw( ")" );
+#endif
+        break;
+        case select_:
+            wrap( " SELECT\n" );
+            LISTdo( tb->list, type, Type )
+            /* finish line from previous entity */
+            if( !first_time ) {
+                raw( ",\n" );
+            }
+
+            /* start new entity */
+            if( first_time ) {
+                raw( "%*s(", level, "" );
+                first_time = false;
+            } else {
+                raw( "%*s ", level, "" );
+            }
+            raw( type->symbol.name );
+            LISTod
+
+            /* if empty, force a left paren */
+            if( first_time ) {
+                ERRORreport_with_symbol( ERROR_select_empty, &error_sym, 
t->symbol.name );
+                raw( "%*s(", level, "" );
+            }
+            raw( ")" );
+            break;
+        case generic_:
+            wrap( " GENERIC" );
+            if( tb->tag ) {
+                wrap( ":%s", tb->tag->symbol.name );
+            }
+            break;
+        default:
+            wrap( " (* unknown type %d *)", tb->type );
+    }
+
+    if( tb->precision ) {
+        wrap( " (" );
+        EXPR_out( tb->precision, 0 );
+        raw( ")" );
+    }
+    if( tb->flags.fixed ) {
+        wrap( " FIXED" );
+    }
+}
+
+void
+EXPRbounds_out( TypeBody tb ) {
+    if( !tb->upper ) {
+        return;
+    }
+
+    wrap( " [" );
+    EXPR_out( tb->lower, 0 );
+    wrap( ":" );
+    EXPR_out( tb->upper, 0 );
+    raw( "]" );
+}
+
+/*
+ if paren == 1, parens are usually added to prevent possible rebind by
+    higher-level context.  If op is similar to previous op (and
+    precedence/associativity is not a problem) parens may be omitted.
+ if paren == 0, then parens may be omitted without consequence
+*/
+void
+EXPR__out( Expression e, int paren, int previous_op ) {
+    int i;  /* trusty temporary */
+
+    switch( TYPEis( e->type ) ) {
+        case integer_:
+            if( e == LITERAL_INFINITY ) {
+                wrap( "?" );
+            } else {
+                wrap( "%d", e->u.integer );
+            }
+            break;
+        case real_:
+            if( e == LITERAL_PI ) {
+                wrap( "PI" );
+            } else if( e == LITERAL_E ) {
+                wrap( "E" );
+            } else {
+                wrap( "%g", e->u.real );
+            }
+            break;
+        case binary_:
+            wrap( "%%%s", e->u.binary ); /* put "%" back */
+            break;
+        case logical_:
+        case boolean_:
+            switch( e->u.logical ) {
+                case Ltrue:
+                    wrap( "TRUE" );
+                    break;
+                case Lfalse:
+                    wrap( "FALSE" );
+                    break;
+                default:
+                    wrap( "UNKNOWN" );
+                    break;
+            }
+            break;
+        case string_:
+            if( TYPEis_encoded( e->type ) ) {
+                wrap( "\"%s\"", e->symbol.name );
+            } else {
+                wrap( "'%s'", e->symbol.name );
+            }
+            break;
+        case entity_:
+        case identifier_:
+        case attribute_:
+        case enumeration_:
+            wrap( "%s", e->symbol.name );
+            break;
+        case query_:
+            wrap( "QUERY ( %s <* ", e->u.query->local->name->symbol.name );
+            EXPR_out( e->u.query->aggregate, 1 );
+            wrap( " | " );
+            EXPR_out( e->u.query->expression, 1 );
+            raw( " )" );
+            break;
+        case self_:
+            wrap( "SELF" );
+            break;
+        case funcall_:
+            wrap( "%s(", e->symbol.name );
+            i = 0;
+            LISTdo( e->u.funcall.list, arg, Expression )
+            i++;
+            if( i != 1 ) {
+                raw( "," );
+            }
+            EXPR_out( arg, 0 );
+            LISTod
+            raw( ")" );
+            break;
+        case op_:
+            EXPRop__out( &e->e, paren, previous_op );
+            break;
+        case aggregate_:
+            wrap( "[" );
+            i = 0;
+            LISTdo( e->u.list, arg, Expression )
+            i++;
+            if( i != 1 ) {
+                raw( "," );
+            }
+            EXPR_out( arg, 0 );
+            LISTod
+            raw( "]" );
+            break;
+        case oneof_:
+            wrap( "ONEOF (" );
+
+            i = 0;
+            LISTdo( e->u.list, arg, Expression )
+            i++;
+            if( i != 1 ) {
+                raw( "," );
+            }
+            EXPR_out( arg, 0 );
+            LISTod
+
+            raw( ")" );
+            break;
+        default:
+            wrap( "unknown expression, type %d", TYPEis( e->type ) );
+    }
+}
+
+#define PAD 1
+#define NOPAD   0
+
+/* print expression that has op and operands */
+void
+EXPRop__out( struct Op_Subexpression * oe, int paren, int previous_op ) {
+    switch( oe->op_code ) {
+        case OP_AND:
+        case OP_ANDOR:
+        case OP_OR:
+        case OP_CONCAT:
+        case OP_EQUAL:
+        case OP_PLUS:
+        case OP_TIMES:
+        case OP_XOR:
+            EXPRop2__out( oe, ( char * )0, paren, PAD, previous_op );
+            break;
+        case OP_EXP:
+        case OP_GREATER_EQUAL:
+        case OP_GREATER_THAN:
+        case OP_IN:
+        case OP_INST_EQUAL:
+        case OP_INST_NOT_EQUAL:
+        case OP_LESS_EQUAL:
+        case OP_LESS_THAN:
+        case OP_LIKE:
+        case OP_MOD:
+        case OP_NOT_EQUAL:
+            EXPRop2_out( oe, ( char * )0, paren, PAD );
+            break;
+        case OP_NOT:
+            EXPRop1_out( oe, "NOT ", paren );
+            break;
+        case OP_REAL_DIV:
+        case OP_DIV:
+            EXPRop2_out( oe, "/", paren, PAD );
+            break;
+        case OP_MINUS:
+            EXPRop2_out( oe, "-", paren, PAD );
+            break;
+        case OP_DOT:
+            EXPRop2_out( oe, ".", paren, NOPAD );
+            break;
+        case OP_GROUP:
+            EXPRop2_out( oe, "\\", paren, NOPAD );
+            break;
+        case OP_NEGATE:
+            EXPRop1_out( oe, "-", paren );
+            break;
+        case OP_ARRAY_ELEMENT:
+            EXPR_out( oe->op1, 1 );
+            wrap( "[" );
+            EXPR_out( oe->op2, 0 );
+            raw( "]" );
+            break;
+        case OP_SUBCOMPONENT:
+            EXPR_out( oe->op1, 1 );
+            wrap( "[" );
+            EXPR_out( oe->op2, 0 );
+            wrap( ":" );
+            EXPR_out( oe->op3, 0 );
+            raw( "]" );
+            break;
+        default:
+            wrap( "(* unknown op-expression *)" );
+    }
+}
+
+void
+EXPRop2__out( struct Op_Subexpression * eo, char * opcode, int paren, int pad, 
int previous_op ) {
+    if( pad && paren && ( eo->op_code != previous_op ) ) {
+        wrap( "(" );
+    }
+    EXPR__out( eo->op1, 1, eo->op_code );
+    if( pad ) {
+        raw( " " );
+    }
+    wrap( "%s", ( opcode ? opcode : EXPop_table[eo->op_code].token ) );
+    if( pad ) {
+        wrap( " " );
+    }
+    EXPR__out( eo->op2, 1, eo->op_code );
+    if( pad && paren && ( eo->op_code != previous_op ) ) {
+        raw( ")" );
+    }
+}
+
+/* Print out a one-operand operation.  If there were more than two of these */
+/* I'd generalize it to do padding, but it's not worth it. */
+void
+EXPRop1_out( struct Op_Subexpression * eo, char * opcode, int paren ) {
+    if( paren ) {
+        wrap( "(" );
+    }
+    wrap( "%s", opcode );
+    EXPR_out( eo->op1, 1 );
+    if( paren ) {
+        raw( ")" );
+    }
+}
+
+int
+EXPRop_length( struct Op_Subexpression * oe ) {
+    switch( oe->op_code ) {
+        case OP_DOT:
+        case OP_GROUP:
+            return( 1 + EXPRlength( oe->op1 )
+                    + EXPRlength( oe->op2 ) );
+        default:
+            fprintf( stdout, "EXPRop_length: unknown op-expression" );
+    }
+    return 0;
+}
+
+/* returns printable representation of expression rather than printing it */
+/* originally only used for general references, now being expanded to handle */
+/* any kind of expression */
+/* contains fragment of string, adds to it */
+void
+EXPRstring( char * buffer, Expression e ) {
+    int i;
+
+    switch( TYPEis( e->type ) ) {
+        case integer_:
+            if( e == LITERAL_INFINITY ) {
+                strcpy( buffer, "?" );
+            } else {
+                sprintf( buffer, "%d", e->u.integer );
+            }
+            break;
+        case real_:
+            if( e == LITERAL_PI ) {
+                strcpy( buffer, "PI" );
+            } else if( e == LITERAL_E ) {
+                strcpy( buffer, "E" );
+            } else {
+                sprintf( buffer, "%g", e->u.real );
+            }
+            break;
+        case binary_:
+            sprintf( buffer, "%%%s", e->u.binary ); /* put "%" back */
+            break;
+        case logical_:
+        case boolean_:
+            switch( e->u.logical ) {
+                case Ltrue:
+                    strcpy( buffer, "TRUE" );
+                    break;
+                case Lfalse:
+                    strcpy( buffer, "FALSE" );
+                    break;
+                default:
+                    strcpy( buffer, "UNKNOWN" );
+                    break;
+            }
+            break;
+        case string_:
+            if( TYPEis_encoded( e->type ) ) {
+                sprintf( buffer, "\"%s\"", e->symbol.name );
+            } else {
+                sprintf( buffer, "'%s'", e->symbol.name );
+            }
+            break;
+        case entity_:
+        case identifier_:
+        case attribute_:
+        case enumeration_:
+            strcpy( buffer, e->symbol.name );
+            break;
+        case query_:
+            sprintf( buffer, "QUERY ( %s <* ", 
e->u.query->local->name->symbol.name );
+            EXPRstring( buffer + strlen( buffer ), e->u.query->aggregate );
+            strcat( buffer, " | " );
+            EXPRstring( buffer + strlen( buffer ), e->u.query->expression );
+            strcat( buffer, " )" );
+            break;
+        case self_:
+            strcpy( buffer, "SELF" );
+            break;
+        case funcall_:
+            sprintf( buffer, "%s(", e->symbol.name );
+            i = 0;
+            LISTdo( e->u.funcall.list, arg, Expression )
+            i++;
+            if( i != 1 ) {
+                strcat( buffer, "," );
+            }
+            EXPRstring( buffer + strlen( buffer ), arg );
+            LISTod
+            strcat( buffer, ")" );
+            break;
+
+        case op_:
+            EXPRop_string( buffer, &e->e );
+            break;
+        case aggregate_:
+            strcpy( buffer, "[" );
+            i = 0;
+            LISTdo( e->u.list, arg, Expression )
+            i++;
+            if( i != 1 ) {
+                strcat( buffer, "," );
+            }
+            EXPRstring( buffer + strlen( buffer ), arg );
+            LISTod
+            strcat( buffer, "]" );
+            break;
+        case oneof_:
+            strcpy( buffer, "ONEOF (" );
+
+            i = 0;
+            LISTdo( e->u.list, arg, Expression )
+            i++;
+            if( i != 1 ) {
+                strcat( buffer, "," );
+            }
+            EXPRstring( buffer + strlen( buffer ), arg );
+            LISTod
+
+            strcat( buffer, ")" );
+            break;
+        default:
+            sprintf( buffer, "EXPRstring: unknown expression, type %d", 
TYPEis( e->type ) );
+            fprintf( stderr, "%s", buffer );
+    }
+}
+
+void
+EXPRop_string( char * buffer, struct Op_Subexpression * oe ) {
+    EXPRstring( buffer, oe->op1 );
+    switch( oe->op_code ) {
+        case OP_DOT:
+            strcat( buffer, "." );
+            break;
+        case OP_GROUP:
+            strcat( buffer, "\\" );
+            break;
+        default:
+            strcat( buffer, "(* unknown op-expression *)" );
+    }
+    EXPRstring( buffer + strlen( buffer ), oe->op2 );
+}
+
+/* returns length of printable representation of expression w.o. printing it */
+int
+EXPRlength( Expression e ) {
+    char buffer[10000];
+
+    *buffer = '\0';
+    EXPRstring( buffer, e );
+    return( strlen( buffer ) );
+}
+
+
+/* Interfacing Definitions */
+
+#define BIGBUFSIZ   100000
+static int old_curpos;
+static int old_lineno;
+static bool string_func_in_use = false;
+static bool file_func_in_use = false;
+
+/* return 0 if successful */
+static int
+prep_buffer( char * buf, int len ) {
+    /* this should never happen */
+    if( string_func_in_use ) {
+        fprintf( stderr, "cannot generate EXPRESS string representations 
recursively!\n" );
+        return 1;
+    }
+    string_func_in_use = true;
+
+    exppp_buf = exppp_bufp = buf;
+    exppp_buflen = exppp_maxbuflen = len;
+
+    *exppp_bufp = '\0';
+    old_curpos = curpos;
+    curpos = 1;
+    old_lineno = 1;
+
+    first_line = true;
+
+    return 0;
+}
+
+/* return length of string */
+static int
+finish_buffer() {
+    exppp_buf = 0;
+    curpos = old_curpos;
+    error_sym.line = old_lineno;
+    string_func_in_use = false;
+    return 1 + exppp_maxbuflen - exppp_buflen;
+}
+
+/* return 0 if successful */
+static int
+prep_string() {
+    /* this should never happen */
+    if( string_func_in_use ) {
+        fprintf( stderr, "cannot generate EXPRESS string representations 
recursively!\n" );
+        return 1;
+    }
+    string_func_in_use = true;
+
+    exppp_buf = exppp_bufp = ( char * )malloc( BIGBUFSIZ );
+    if( !exppp_buf ) {
+        fprintf( stderr, "failed to allocate exppp buffer\n" );
+        return 1;
+    }
+    exppp_buflen = exppp_maxbuflen = BIGBUFSIZ;
+
+    *exppp_bufp = '\0';
+    old_curpos = curpos;
+    old_lineno = error_sym.line;
+    curpos = 1;
+
+    first_line = true;
+
+    return 0;
+}
+
+static char *
+finish_string() {
+    char * b = ( char * )realloc( exppp_buf, 1 + exppp_maxbuflen - 
exppp_buflen );
+
+    if( b == 0 ) {
+        fprintf( stderr, "failed to reallocate exppp buffer\n" );
+        return 0;
+    }
+    exppp_buf = 0;
+    curpos = old_curpos;
+    error_sym.line = old_lineno;
+
+    string_func_in_use = false;
+    return b;
+}
+
+static FILE * oldfp;
+
+static void
+prep_file() {
+    /* this can only happen if user calls output func while suspended */
+    /* inside another output func both called from debugger */
+    if( file_func_in_use ) {
+        fprintf( stderr, "cannot print EXPRESS representations recursively!\n" 
);
+    }
+    file_func_in_use = true;
+
+    /* temporarily change file to stdout and print */
+    /* This avoids messing up any printing in progress */
+    oldfp = exppp_fp ? exppp_fp : stdout;
+    exppp_fp = stdout;
+    curpos = 1;
+}
+
+static void
+finish_file() {
+    exppp_fp = oldfp;       /* reset back to original file */
+    file_func_in_use = false;
+}
+
+static char * placeholder = "placeholder";
+
+char *
+SUBTYPEto_string( Expression e ) {
+    if( prep_string() ) {
+        return placeholder;
+    }
+    EXPR_out( e, 0 );
+    return ( finish_string() );
+}
+
+char *
+ENTITYto_string( Entity e ) {
+    if( prep_string() ) {
+        return placeholder;
+    }
+    ENTITY_out( e, 0 );
+    return ( finish_string() );
+}
+
+/* return length of buffer used */
+int
+ENTITYto_buffer( Entity e, char * buffer, int length ) {
+    if( prep_buffer( buffer, length ) ) {
+        return -1;
+    }
+    ENTITY_out( e, 0 );
+    return( finish_buffer() );
+}
+
+void
+ENTITYout( Entity e ) {
+    prep_file();
+    ENTITY_out( e, 0 );
+    finish_file();
+}
+
+char *
+EXPRto_string( Expression e ) {
+    if( prep_string() ) {
+        return placeholder;
+    }
+    EXPR_out( e, 0 );
+    return ( finish_string() );
+}
+
+/* return length of buffer used */
+int
+EXPRto_buffer( Expression e, char * buffer, int length ) {
+    if( prep_buffer( buffer, length ) ) {
+        return -1;
+    }
+    EXPR_out( e, 0 );
+    return( finish_buffer() );
+}
+
+void
+EXPRout( Expression e ) {
+    prep_file();
+    EXPR_out( e, 0 );
+    finish_file();
+}
+
+char *
+FUNCto_string( Function f ) {
+    if( prep_string() ) {
+        return placeholder;
+    }
+    FUNC_out( f, 0 );
+    return ( finish_string() );
+}
+
+/* return length of buffer used */
+int
+FUNCto_buffer( Function e, char * buffer, int length ) {
+    if( prep_buffer( buffer, length ) ) {
+        return -1;
+    }
+    FUNC_out( e, 0 );
+    return( finish_buffer() );
+}
+
+void
+FUNCout( Function f ) {
+    prep_file();
+    FUNC_out( f, 0 );
+    finish_file();
+}
+
+char *
+PROCto_string( Procedure p ) {
+    if( prep_string() ) {
+        return placeholder;
+    }
+    PROC_out( p, 0 );
+    return ( finish_string() );
+}
+
+/* return length of buffer used */
+int
+PROCto_buffer( Procedure e, char * buffer, int length ) {
+    if( prep_buffer( buffer, length ) ) {
+        return -1;
+    }
+    PROC_out( e, 0 );
+    return( finish_buffer() );
+}
+
+void
+PROCout( Procedure p ) {
+    prep_file();
+    PROC_out( p, 0 );
+    finish_file();
+}
+
+char *
+RULEto_string( Rule r ) {
+    if( prep_string() ) {
+        return placeholder;
+    }
+    RULE_out( r, 0 );
+    return ( finish_string() );
+}
+
+/* return length of buffer used */
+int
+RULEto_buffer( Rule e, char * buffer, int length ) {
+    if( prep_buffer( buffer, length ) ) {
+        return -1;
+    }
+    RULE_out( e, 0 );
+    return( finish_buffer() );
+}
+
+void
+RULEout( Rule r ) {
+    prep_file();
+    RULE_out( r, 0 );
+    finish_file();
+}
+
+char *
+SCHEMAref_to_string( Schema s ) {
+    if( prep_string() ) {
+        return placeholder;
+    }
+    REFout( s->u.schema->usedict, s->u.schema->use_schemas, "USE", 0 );
+    REFout( s->u.schema->refdict, s->u.schema->ref_schemas, "REFERENCE", 0 );
+    return ( finish_string() );
+}
+
+/* return length of buffer used */
+int
+SCHEMAref_to_buffer( Schema s, char * buffer, int length ) {
+    if( prep_buffer( buffer, length ) ) {
+        return -1;
+    }
+    REFout( s->u.schema->usedict, s->u.schema->use_schemas, "USE", 0 );
+    REFout( s->u.schema->refdict, s->u.schema->ref_schemas, "REFERENCE", 0 );
+    return( finish_buffer() );
+}
+
+void
+SCHEMAref_out( Schema s ) {
+    prep_file();
+    REFout( s->u.schema->usedict, s->u.schema->use_schemas, "USE", 0 );
+    REFout( s->u.schema->refdict, s->u.schema->ref_schemas, "REFERENCE", 0 );
+    finish_file();
+}
+
+char *
+STMTto_string( Statement s ) {
+    if( prep_string() ) {
+        return placeholder;
+    }
+    STMT_out( s, 0 );
+    return ( finish_string() );
+}
+
+/* return length of buffer used */
+int
+STMTto_buffer( Statement s, char * buffer, int length ) {
+    if( prep_buffer( buffer, length ) ) {
+        return -1;
+    }
+    STMT_out( s, 0 );
+    return( finish_buffer() );
+}
+
+void
+STMTout( Statement s ) {
+    prep_file();
+    STMT_out( s, 0 );
+    finish_file();
+}
+
+char *
+TYPEto_string( Type t ) {
+    if( prep_string() ) {
+        return placeholder;
+    }
+    TYPE_out( t, 0 );
+    return ( finish_string() );
+}
+
+/* return length of buffer used */
+int
+TYPEto_buffer( Type t, char * buffer, int length ) {
+    if( prep_buffer( buffer, length ) ) {
+        return -1;
+    }
+    TYPE_out( t, 0 );
+    return( finish_buffer() );
+}
+
+void
+TYPEout( Type t ) {
+    prep_file();
+    TYPE_out( t, 0 );
+    finish_file();
+}
+
+char *
+TYPEhead_to_string( Type t ) {
+    if( prep_string() ) {
+        return placeholder;
+    }
+    TYPE_head_out( t, 0 );
+    return ( finish_string() );
+}
+
+/* return length of buffer used */
+int
+TYPEhead_to_buffer( Type t, char * buffer, int length ) {
+    if( prep_buffer( buffer, length ) ) {
+        return -1;
+    }
+    TYPE_out( t, 0 );
+    return( finish_buffer() );
+}
+
+void
+TYPEhead_out( Type t ) {
+    prep_file();
+    TYPE_head_out( t, 0 );
+    finish_file();
+}
+
+char *
+TYPEbody_to_string( Type t ) {
+    if( prep_string() ) {
+        return placeholder;
+    }
+    TYPE_body_out( t, 0 );
+    return ( finish_string() );
+}
+
+/* return length of buffer used */
+int
+TYPEbody_to_buffer( Type t, char * buffer, int length ) {
+    if( prep_buffer( buffer, length ) ) {
+        return -1;
+    }
+    TYPE_body_out( t, 0 );
+    return( finish_buffer() );
+}
+
+void
+TYPEbody_out( Type t ) {
+    prep_file();
+    TYPE_body_out( t, 0 );
+    finish_file();
+}
+
+char *
+WHEREto_string( Linked_List w ) {
+    if( prep_string() ) {
+        return placeholder;
+    }
+    WHERE_out( w, 0 );
+    return ( finish_string() );
+}
+
+/* return length of buffer used */
+int
+WHEREto_buffer( Linked_List w, char * buffer, int length ) {
+    if( prep_buffer( buffer, length ) ) {
+        return -1;
+    }
+    WHERE_out( w, 0 );
+    return( finish_buffer() );
+}
+
+void
+WHEREout( Linked_List w ) {
+    prep_file();
+    WHERE_out( w, 0 );
+    finish_file();
+}

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to