v15i036: Hash long identifiers into unique short ones

Rich Salz rsalz at uunet.uu.net
Tue Jun 7 00:46:20 AEST 1988


Submitted-by: desint!geoff (Geoff Kuenning)
Posting-number: Volume 15, Issue 36
Archive-name: hash8

[  I haven't used this; documentation is in the README files as use
   is likely to be very system-dependent. --r$  ]

This is Arch Robison's "hash8" program, which allows old C compilers
to compile long-identifier programs correctly.  I have added an "lcc"
("longname-cc") shell script to make this even easier.  Useful with
ispell and nethack.

	Geoff Kuenning   geoff at ITcorp.com   {uunet,trwrb}!desint!geoff

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	README.OLD
#	DOC
#	Makefile
#	hash8.c
#	lcc.sh,v
#	ltest.c
#	ltest2.c
#	ltest3.c
#	ncc
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(873 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'

	An Improved Version of Arch Robison's "hash8"

Some time ago, Arch Robison kindly provided me with a copy of his
"hash8" program, which gives long-id capabilities to all C compilers.
Briefly, hash8 replaces all long identifiers in a program with a
numerically-based identifier of 6 characters.  Options allow things
like using debuggers with the original long names.

I have extended Arch's program with a shell script, "lcc.sh", which
does exactly what "cc" does, but compiles long-name programs.  Unfortunately,
the script is quite system-specific, and I have an odd configuration
(68000 running UniSoft System V.0 with V7 compilers), so you will
almost certainly have to edit it before it is completely compatible
with your own "cc".  Nevertheless, for those with older compilers,
this is a life-saver.

	Geoff Kuenning   geoff at ITcorp.com   {uunet,trwrb}!desint!geoff
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'README.OLD'" '(1303 characters)'
if test -f 'README.OLD'
then
	echo shar: will not over-write existing file "'README.OLD'"
else
cat << \SHAR_EOF > 'README.OLD'
>From uucp Sat Oct 25 02:45 PDT 1986
>From ihnp4!uiucdcs!b.cs.uiuc.edu!robison  Sat Oct 25 02:45:46 1986 remote from trwrb
Received: by ihnp4.ATT.COM id AA14044; 22 Oct 86 15:34:56 CDT (Wed)
Received: from b.cs.uiuc.edu by a.cs.uiuc.edu with SMTP (UIUC-5.44/9.7),
	id AA26838; Wed, 22 Oct 86 11:29:19 CDT
Received: by b.cs.uiuc.edu (UIUC-5.44/9.7),
	id AA04280; Wed, 22 Oct 86 11:25:50 CDT
Date: Wed, 22 Oct 86 11:25:50 CDT
From: trwrb!ihnp4!uiucdcs!b.cs.uiuc.edu!robison (Arch Robison)
Message-Id: <8610221625.AA04280 at b.cs.uiuc.edu>
To: desint!geoff
Subject: long-to-short converter


Here is the long-identifier converter.  The converter has been used
to create a long-identifier lint and with cc.  Please send me any bug
reports or comments on how to improve it.  My version of lint that uses 
it has been running for nearly a year now without problems.  Since lint
is a licensed program, I can't send you a copy, though it shouldn't be 
hard to figure out how to modify it.  (Lint is a shell script.)

To use hash8 with debuggers, you will want to modify it to turn off 
stdin/stdout buffering.

To compile the program, make a directory and run the shell script below.
Then "make hash8".

- Arch D. Robison
  Dept. of Computer Science
  University of Illinois at Urbana-Champaign

  robison at uiucdcs

SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'DOC'" '(1324 characters)'
if test -f 'DOC'
then
	echo shar: will not over-write existing file "'DOC'"
else
cat << \SHAR_EOF > 'DOC'
Hash8 documentation				Arch D. Robison
						University of Illinois
						Urbana Champaign

						robison at uiucdcs

			Hash8 

There three files (other than DOC) provided:

	hash8.c     source code for long identifier converter
	Makefile    example makefile
	ncc	    shell script for compiling

The hash8 program allows short-identifier C compilers to compile
long-identifier programs.  It is not intened for production use,
but for quickly porting long-identifier programs.

See the documentation in hash8.c and the Makefile for how to use it with cc.

----------------------------------------------------------------------

			Hash8 with lint

I've been able to hack a short identifier lint with "hash8" so it would work
with long identifier programs.  This was an easy modification since lint is
a shell script.  The "hash8 encode" filter was put in between /lib/cpp and 
/usr/lib/lint/lint and all error message written to a temporary file.
Then "hash8 decode" was used to decode the error messages.

Note that hash8's can not run in parallel, since the identifier map is read all
at once and written all at once.

Thus you can't (regrettably) do: 

     hash8 encode TABLE | /lib/cpp | hash8 decode TABLE

The above would have to be written:

     hash8 encode TABLE >TEMP
     cat TEMP | /lib/cpp | hash8 decode TABLE

SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(1829 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
# Here is the original makefile for a sample program with long identifiers.
#
#snakeomatic:	main.o move.o screen.o
#		cc main.o move.o screen.o -lm
#
#main.o:	snakeomatic.h main.c
#		cc -c main.c
#
#move.o:		snakeomatic.h move.c
#		cc -c move.c
#
#screen.o:	snakeomatic.h screen.c
#		cc -c screen.c

#---------------------------------------------------------------------------
#
# Makefile modified for hash8.  Each source file xxx has been renamed L_xxx.
# The "ncc" shell script filters each L_xxx file with hash8 and puts
# the result in file xxx, which is then compiled.
#
# Also note that any .h file must also be filtered by hash8.
#
# The file TABLE is the identifier mapping table.  You should "make TABLE"
# before your first compilation to initilize the mapping table.
# After that, you should not have to remake the table, even if you
# make corrections in the code.  Hash8 will automatically update
# the table when necessary.
#
SYSTEM = /usr/include/stdio /usr/include/signal.h /usr/include/sgtty.h 

snakeomatic:	main.o move.o screen.o
		cc main.o move.o screen.o -lm 2>&1 | hash8 _decode TABLE

main.o:		snakeomatic.h L_main.c
		ncc main.c

move.o:		snakeomatic.h L_move.c
		ncc move.c

screen.o:	snakeomatic.h L_screen.c
		ncc screen.c

snakeomatic.h:  L_snakeomatic.h
		cat L_snakeomatic.h | hash8 encode TABLE >snakeomatic.h

#
# When the identifier map is first created, all the system #include files
# should be run through hash8.  This usually not necessary, but it
# is possible that your program's identifiers could have a common prefix
# with a system identifier.  By processing the system #include files first,
# we ensure that those identifiers will not be changed.
#
TABLE:		hash8 $(SYSTEM)
		rm -f TABLE
		cat $(SYSTEM) | hash8 encode TABLE >/dev/null

hash8:		hash8.c
		cc $(CFLAGS) hash8.c -o hash8
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'hash8.c'" '(11200 characters)'
if test -f 'hash8.c'
then
	echo shar: will not over-write existing file "'hash8.c'"
else
cat << \SHAR_EOF > 'hash8.c'
/*
 * Date: March 17 1985			Author: Arch D. Robison
 *						Dept. of Computer Science
 *						University of Illinois
 *						Urbana-Champaign
 *
 *					USENET:	robison at uiucdcs
 *
 * Hash8 copies stdin to stdout, while replacing certain identifiers.
 * lint can be converted to accept long identifiers by hacking in hash8
 * between /lib/cpp and /usr/lib/lint/lint appropriately.
 *
 * There are three ways to call hash8:
 *
 *     hash8 encode table
 *         Map long identifiers and those beginning with Q 
 *	   into short identifiers Q%d
 *
 *     hash8 decode table
 *         Map short identifiers Q%d into their long equivalents
 *
 *     hash8 _decode table
 *         Map short identifiers _Q%d into their long equivalents
 * 	   This is used to decode the linker's error messages
 *
 * The 'table' argument is the file name for the identifier map.
 * The 'encode' calls will either create or expand the table.
 *
 * Typically, the encode option is used to preprocess input to the compiler
 * or lint, and the decode option is used to decode error messages from
 * the compiler.
 *
 * The constant HASHBITS may need to be changed.  It is the base two
 * log of the number of distinct long identifiers which may be found.
 * E.g. the value of 12 allows for 4096 long identifiers.
 *
 * Hash8 has not been thoroughly tested, though it can translate itself
 * correctly.  Note that itself contains all sorts of quotes within quotes.
 */
#include <stdio.h>
#include <ctype.h>

/*
 * Reserved is an array of words which we don't want modified, such
 * as the key word "register", or system functions longer than 7 characters.
 * Feel free to add any others, though remember to clear your hash table
 * files after recompiling.
 */
char **Reserved = NULL;
int Res_max = 0;
int Res_count = 0;
char *Def_reserved[] = {
   "continue",
   "register",
   "unsigned"
};

extern char *malloc (), *strcpy ();

#define SIGCHARS 7		/* significant characters in identifier */
#define HASHBITS 12		/* hash table address size */
#define HASHLIMIT (1<<HASHBITS)
#define HASHMASK (HASHLIMIT-1)
#define PAGESIZE 4096		/* Memory allocation pagesize */ 
#define MAXLINE 1024		/* Maximum length of a source line allowed */

#define W_SHORTEN  0		/* Identifier classes */
#define W_NORMAL   1
#define W_RESERVED 2
#define W_Valid(N) ((N) >= 0 && (N) <= 2)

/*
 * HashTab
 *
 * The identifier map is a hash table.  The table uses open addressing
 * with linear probing for collision resolution.  Identifiers in the
 * table are mapped into Qxxx, where xxx is the table address in hex.
 *
 * The hash table is effectively declared:
 *
 *      char *HashTab[HASHLIMIT];
 *
 * though the memory allocation is done with malloc.  Each empty hash table
 * item is NULL.  Full entries point to an identifier.  The first byte of
 * the identifier classifies the identifier:
 *
 *      W_NORMAL - don't modify this identifier
 *	W_SHORTEN - shorten this identifier
 *	W_RESERVE - reserved word 
 */
char **HashTab;
int HashSize = 0;    /* Number of elements in hash table 		    */
int NewTab;          /* Flag which is set to true if hash table is modified */

char *StrFree;	     /* Pointer to base of free string area                 */
int StrLeft = 0;     /* Number of characters left in free string area       */

/*
 * Insert
 * 
 * Insert identifier in hash table
 *
 * In
 *      k = index into hash table
 *      S = identifier
 *	Class = class of identifier (W_NORMAL,W_SHORTEN,W_RESERVED)
 */
void Insert (k,S,Class)
   int k;
   char *S;
   int Class;
   {
      register int L;

      NewTab = 1;
      HashSize++;
      if ((StrLeft -= (L=2+strlen (S))) < 0)
         StrFree = malloc (StrLeft=PAGESIZE);
      *(HashTab[k] = StrFree) = Class;
      strcpy (StrFree+1, S);
      StrFree += L;
      StrLeft -= L;
   }			   

/*
 * LookUp
 *
 * Look up an identifer in the identifier hash table.
 * If not found, then insert it in the table.
 *
 * The hashing uses open addressing with linear probing.
 * The algorithm is a blue-light special, a better hash function
 * (double hashing?) should be used.
 * 
 * In
 *      S = identifier (must be at least seven characters if Duplicate == 0)
 *      Class = identifier class (W_NORMAL,W_SHORTEN,W_RESERVED)
 * Out
 *      result = index into hash table 
 */
int LookUp (S,Class)
   char *S;
   int Class;
   {
      register int k,j;
      register char *T;

      if (Class != W_SHORTEN) {

         /* Hash first seven characters of identifier */ 
         for (j=0,k=0,T=S; j<SIGCHARS; j++, k+= *T++) k = (k<<1) + k;

         /* 7-character search for identifier in table */
         for (j=k; HashTab[j&=HASHMASK] != NULL; j++) 
            if (!strncmp (HashTab[j]+1,S,SIGCHARS)) 
               if (!strcmp (HashTab[j]+1,S)) return j;
	       else {
		  Class = W_SHORTEN;
		  break;
	       }
	 /* The following test and assignment cause identifiers to be
	  * hashed even if they are the first long identifier.  This
	  * protects from truncation by the compiler.  Othewise, when
	  * you run adb you have to know which long id came first.
	  * Geoff Kuenning 11/8/86
	  */
         if (Class == W_NORMAL  &&  strlen (S) > SIGCHARS)
	    Class = W_SHORTEN;
      }

      if (Class == W_SHORTEN) {
	 /* 
	  * There is another identifier with the same 7-character prefix. 
	  * Hash the complete identifier and look it up in the table.
	  */
         for (j=k; *T; j+= *T++) j = (j<<1) + j;

	 /* all characters search for identifier in table */
	 for (; HashTab[j&=HASHMASK] != NULL; j++)
	       if (!strcmp (HashTab[j]+1,S)) return j;
      }

      /* Identifier was not found - insert it in hash table */
      Insert (j,S,Class);
      if (HashSize == HASHLIMIT) 
	 fprintf (stderr,"hash8: table overflow\n"), exit (1);
      return j;
   }

#define C_CODE 0	/* Defines for translator states */
#define S_QUOTE 1
#define D_QUOTE 2
#define COMMENT 3

#define ENCODE 0	/* Mode values for translator */
#define DECODE 1
#define _DECODE 2

/*
 * Translate
 *
 * Translate input stream with identifier map.
 *
 * This should have been written with lex.
 */
Translate (Mode) 
   int Mode;
   {
      register char C, *P, *Q;
      char S[MAXLINE];
      int k, state=C_CODE, IsQ;

      while (NULL != fgets (S,MAXLINE,stdin)) 
         for (P=S; C= *P; )
	    switch (state) {
	       case COMMENT:
	          putchar (*P++);
                  if (C == '*' && *P == '/') state=C_CODE, putchar (*P++);
		  break;
	       case S_QUOTE:
	       case D_QUOTE:
		  putchar (*P++);
		  switch (C) {
		     case '\'': if (state == S_QUOTE) state = C_CODE; break;
		     case '"' : if (state == D_QUOTE) state = C_CODE; break;
		     case '\\': putchar (*P++); break;
		     default: break; 
		  }
	          break;
	       
               case C_CODE:
		  if (isalpha (C) || C=='_') {
	             /* Beginning of identifier */
      	             for (Q=P; C= *Q, isalnum(C)||C=='_'; Q++);
	             *Q = '\0';
   	             switch (Mode) {

			case ENCODE: /* We are encoding C source */
		           IsQ = *P=='Q' && isdigit (P[1]);
   	                   if (Q-P <= SIGCHARS && !IsQ) 
   	                      fputs (P,stdout);
		           else {
			      k = LookUp (P,IsQ ? W_SHORTEN : W_NORMAL);
			      if (*HashTab[k] != W_SHORTEN) fputs (P,stdout);
		              else printf ("Q%d",k);
		           }
			   break;

			case _DECODE: /* We are decoding linker messages */
		           if (*P != '_') {
			      fputs (P,stdout);
			      break;
			   }
			   putchar (*P++);
			   /* continue on down to case DECODE */

			case DECODE: /* We are decoding error message */
   	                   if (*P=='Q' && isdigit (P[1])) { 
			      k=atoi(P+1);
			      if (!(k &~HASHMASK) && HashTab[k]!=NULL) 
				 P = HashTab[k] + 1;
			   }
		           fputs (P,stdout);
			   break;
		     }
   	             *(P=Q) = C;
   	          } else if (isdigit (C)) {
	             /* Skip number to avoid changing long numbers */
	             while (isalnum(*P)) putchar (*P++);
	          } else {
		     putchar (*P++);
		     switch (C) {
		        default: break;
			case '\'': state = S_QUOTE; break;
                        case '"' : state = D_QUOTE; break;
                        case '/' : if (*P != '*') continue;
			           state=COMMENT;
		        case '\\': putchar (*P++); break;
		     }
	          }
	       }
   }

/*
 * ReadTab
 *
 * Read the hash table.
 *
 * In
 *      Name = name of hash table file
 */
ReadTab (Name)
   char *Name;
   {
      FILE *Table;
      char S[MAXLINE];
      int k,L,Class;

      /* First record all words we don't want mangled in hash table */      
      for (k = 0;  k < sizeof (Def_reserved) / sizeof (char *);  k++)
         LookUp (Def_reserved[k], W_RESERVED);
      for (k = 0;  k < Res_count;  k++) 
         LookUp (Reserved[k],W_RESERVED);

      if (NULL == (Table = fopen (Name,"r"))) return;
      while (EOF != (L = fscanf (Table,"%d %d %s",&k,&Class,S))) 
	 if (L != 3 || k &~HASHMASK || !W_Valid (Class))
	    fprintf (stderr,"hash8 table error\n"),
	    exit (1);
         else Insert (k,S,Class);
      fclose (Table); 
      NewTab = 0;
   }

/*
 * WriteTab
 *
 * Write out the hash table
 *
 * In
 *      Name = name of hash table file
 */
WriteTab (Name)
   char *Name; 
   { 
      FILE *Table;
      int i;

      if (NULL == (Table = fopen (Name,"w"))) 
	 fprintf (stderr,"hash8: can't open hash table file '%s'\n",Name),
	 exit (1);
      for (i=0; i<HASHLIMIT; i++)
         if (HashTab[i] != NULL && *HashTab[i] != W_RESERVED) 
            fprintf (Table,"%d	%d	%s\n",i,*HashTab[i],HashTab[i]+1);
      fclose (Table); 
   }

main (argc,argv)
   int argc; char *argv[];
   {
      register char **h;
      int Mode;

      /*
       * Set up the reserved-word list.
       */
      while (argc > 3  &&  argv[1][0] == '-'  &&  argv[1][1] == 'r') {
	 argv[1] += 2;
	 if (argv[1][0] == '\0') {
	    argc--;
	    argv++;
	 }
	 if (Res_count == Res_max) {
	    Res_max += 5;
	    if (Reserved == NULL)
	       Reserved = (char **) malloc (5 * sizeof (char *));
	    else
	       Reserved = (char **)
	        realloc ((char *) Reserved, Res_max * sizeof (char *));
	 }
	 Reserved[Res_count] = argv[1];
	 Res_count++;
	 argc--;
	 argv++;
      }
      if (argc != 3) {
         fprintf (stderr,
           "usage: hash8 [-r reserved] ... (encode|[_]decode) table\n");
         exit (1);
      }

      /*
       * If either stdin or stdout is a tty, set both unbuffered, for use
       * in pipes.
       * Geoff Kuenning, 11/8/86
       */
      if (isatty (fileno (stdin))  ||  isatty (fileno (stdout))) {
	 setbuf (stdin, NULL);
	 setbuf (stdout, NULL);
      }
      HashTab = (char **) malloc ((sizeof (char*)) * (HASHLIMIT));
      for (h = HashTab+HASHLIMIT; --h > HashTab; ) *h = NULL;
     
      ReadTab(argv[2]); 
      
      if (!strcmp (argv[1],"encode")) Mode = ENCODE;
      else if (!strcmp (argv[1],"decode")) Mode = DECODE; 
      else if (!strcmp (argv[1],"_decode")) Mode = _DECODE; 
      else
         fprintf (stderr,"hash8: second arg must be 'encode' or 'decode'\n"),
	 exit (1);

      Translate (Mode);
      if (NewTab) WriteTab(argv[2]);
   }

SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'lcc.sh,v'" '(11956 characters)'
if test -f 'lcc.sh,v'
then
	echo shar: will not over-write existing file "'lcc.sh,v'"
else
cat << \SHAR_EOF > 'lcc.sh,v'
head     1.5;
access   ;
symbols  ;
locks    ; strict;
comment  @# @;


1.5
date     87.03.06.20.34.29;  author geoff;  state Exp;
branches ;
next     1.4;

1.4
date     87.02.28.00.56.50;  author geoff;  state Exp;
branches ;
next     1.3;

1.3
date     86.11.08.23.07.56;  author geoff;  state Exp;
branches ;
next     1.2;

1.2
date     86.11.08.22.15.24;  author geoff;  state Exp;
branches ;
next     1.1;

1.1
date     86.11.08.21.58.14;  author geoff;  state Exp;
branches ;
next     ;


desc
@Shell script to compile long-name C programs.
@


1.5
log
@Make -p work correctly
@
text
@: Use bin/sh
#
# $Header: lcc.sh,v 1.4 87/02/28 00:56:50 geoff Exp $
#
# $Log:	lcc.sh,v $
# Revision 1.4  87/02/28  00:56:50  geoff
# Major changes to handle things much better by running each compiler
# pass separately.  Also add the -R switch, and support for -D and
# library files.
# 
# Revision 1.3  86/11/08  23:07:56  geoff
# Add error processing, not quite like cc's
# 
# Revision 1.2  86/11/08  22:15:24  geoff
# Remove -HP, minor cleanup of output.  Working, except ignores errors
# 
# Revision 1.1  86/11/08  21:58:14  geoff
# Works only if -HP specified
# 
#
#	Replacement for the 'cc' command, with support for long
#	identifiers.
#
#	Usage:
#
#	lcc [options] files
#
#	As with 'cc', the files mentioned can be .c, .s, or .o files.
#
#	All 'cc' options are support (or should be -- report bugs!).
#
#	There are some extra options.  All begin with H:
#
#	-HD	Don't preserve the encode/decode table.  (Normally, it is
#		left in xxxx.t, where xxxx is the first file name encountered,
#		or the -o file name if -o is specified.)
#	-HA name The encode/decode table is put in <name>.  If it exists,
#		the program will append to it.
#	-HL	Only the C compiler itself is deficient;  the assembler
#		and linker can handle long names.  Use this facility to
#		generate long-name object files.  This is incompatible
#		with -P and -S, but conflict is not checked.
#	-R name	Add <name> to the reserved-word list.  Useful for
#		library routines that have long names.
#
#	Options supported:
#
#	-I<dir>	Set include path for cpp
#	-S	Generate .s files
#	-c	Generate .o files;  don't load
#	-n	Generate shared text (ld)
#	-p	Generate profiled output
#	-f*	Passed on to cc
#
TDIR=${TMPDIR:-/tmp}		# Where to put temp files
TFILE=lcc$$			# Base name for encoded source files
TMP=$TDIR/$TFILE		# Base name of cc's encoded input files
TABLE=${TFILE}t			# Where the decode file goes
c1sw=				# Switches for compiler pass 1
ccsw=				# Switches for cc
ldsw=				# Switches for ld
suffix=o			# Suffix of output "object" files:  o, s, or i
forceobj=-c			# How to force "objects":  -c, -P, or -S
load=yes			# Yes to invoke loader
numsrcfiles=			# If this is exactly one x, we kill objects
ofiles=				# Files to be linked
optimize=no			# -O switch specified
optsw=				# Switches for optimizer
preprocess=			# Preprocess option:  null, -P, or -E
reserved=			# Reserved-word list
rmfiles=			# List of object files to remove (only one)
verbose=			# Verbose option:  -v or null
killtable=no			# Yes if $TABLE is to be deleted
tablename=			# Name of the output table
madetable=no			# Yes if we added to the table
dumbcc=no			# Yes if only cc is dumb about long names

if [ -x /lib/c ]
then
    COMPILER=/lib/c
elif [ -x /usr/lib/c ]
then
    COMPILER=/usr/lib/c
else
    COMPILER=c
fi
if [ -x /lib/c2 ]
then
    OPTIMIZER=/lib/c2
elif [ -x /usr/lib/c2 ]
then
    OPTIMIZER=/usr/lib/c2
else
    OPTIMIZER=c2
fi
trap '/bin/rm -f ${TFILE}.? ${TMP}* $TABLE; exit 1' 1 2 15
# 7 is SIGEMT, a fairly obscure one
failure=no
trap "failure=yes" 7
while [ $# -gt 0 ]
do
    case "$1" in
	-HD)
	    TABLE=${TMP}t	# Put output table in $TMPDIR
	    killtable=yes
	    ;;
	-HA)
	    tablename=$2
	    TABLE=$2
	    shift
	    ;;
	-HL)
	    dumbcc=yes
	    ;;
	-R)
	    reserved="$reserved -r $2"
	    shift
	    ;;
	-n)
	    ldsw="$ldsw $1"
	    ;;
	-v)
	    verbose=-v
	    ;;
	-p)
	    ldsw="$ldsw $1"
	    c1sw="$c1sw -Xp"
	    ;;
	-f*)
	    ldsw="$ldsw $1"
	    c1sw="$c1sw $1"
	    ;;
	-o)
	    ldsw="$ldsw $1 $2"
	    tablename=$2.t
	    shift
	    ;;
	-R)
	    ldsw="$ldsw $1 $2"
	    shift
	    ;;
	-E|-P)
	    preprocess=$1
	    forceobj=$1
	    suffix=i
	    load=no
	    ;;
	-O*)
	    optimize=yes
	    optsw=`echo $1 | tr -d O`
	    if [ "X$optsw" = "X-" ]
	    then
		optsw=
	    fi
	    ;;
	-C|-D*|-U*|-I*)
	    ccsw="$ccsw $1"
	    ;;
	-S)
	    forceobj=-S
	    suffix=s
	    load=no
	    numsrcfiles=xx
	    ;;
	-c)
	    load=no
	    numsrcfiles=xx
	    ;;
	-l*)
	    ofiles="$ofiles $1"
	    ;;
	*.o)
	    numsrcfiles=xx
	    ofiles="$ofiles $1"
	    if [ "$tablename" = "" ]
	    then
		tablename=`basename $1 .o`.t
	    fi
	    ;;
	*.s)
	    if  [ "$dumbcc" = "yes" -a "X$preprocess" = "X" ]
	    then
		if cc $ccsw $verbose $forceobj $1
		then
		    :
		else
		    failure=yes
		    break
		fi
	    elif [ "$suffix" != "s" -a "X$preprocess" = "X" ]
	    then
		hash8 $reserved encode $TABLE < $1 > ${TMP}.s
		madetable=yes
		(cc $ccsw $forceobj $verbose ${TMP}.s 2> ${TMP}.e \
		    ||  kill -7 $$) \
		  | sed "s;${TMP}.s;$1;" | hash8 decode $TABLE
		sed "s;${TMP}.s;$1;" ${TMP}.e | hash8 decode $TABLE 1>&2
		if [ "$failure" = "yes" ]
		then
		    break
		fi
		obj=`basename "$1" '.s'`.$suffix
		ofiles="$ofiles $obj"
		rmfiles="$rmfiles $obj"
		mv ${TFILE}.$suffix $obj
		numsrcfiles="x$numsrcfiles"
	    fi
	    if [ "$tablename" = "" ]
	    then
		tablename=`basename $1 .s`.t
	    fi
	    ;;
	*.c)
	    obj=`basename "$1" '.c'`.$suffix
	    ppfile=${TMP}.i
	    if [ "X$verbose" = "X-v" ]
	    then
		echo "${1}:"
		echo "  Preprocessing" 1>&2
	    fi
	    if [ "X$preprocess" = "X-E" ]
	    then
		if cc $ccsw $preprocess $1
		then
		    :
		else
		    failure=yes
		fi
	    elif [ "X$preprocess" = "X-P" ]
	    then
		ppfile=$obj
	    fi
	    if cc $ccsw -E $1 > $ppfile
	    then
		:
	    else
		failure=yes
		/bin/rm -f $ppfile
		break
	    fi
	    if [ "X$preprocess" = "X-P" ]
	    then
		break
	    fi
	    hash8 $reserved encode $TABLE < $ppfile > ${TMP}.c
	    madetable=yes
	    /bin/rm -f $ppfile
	    if [ "$optimize" = yes ]
	    then
		unoptfile=${TMP}.s1
	    else
		unoptfile=${TMP}.s
	    fi
	    if [ "X$verbose" = "X-v" ]
	    then
		echo "  Compiling" 1>&2
	    fi
	    if $COMPILER $c1sw < ${TMP}.c > $unoptfile 2> ${TMP}.e
	    then
		/bin/rm -f ${TMP}.c
	    else
		hash8 decode $TABLE < ${TMP}.e 1>&2
		/bin/rm $unoptfile ${TMP}.c ${TMP}.e
		failure=yes
		break
	    fi
	    if [ $optimize = yes ]
	    then
		if [ "X$verbose" = "X-v" ]
		then
		    echo "  Optimizing" 1>&2
		fi
		if $OPTIMIZER $optsw < $unoptfile > ${TMP}.s 2> ${TMP}.e
		then
		    /bin/rm -f $unoptfile
		    unoptfile=${TMP}.s
		else
		    hash8 decode $TABLE < ${TMP}.e 1>&2
		    /bin/rm -f $unoptfile ${TMP}.s ${TMP}.e
		    failure=yes
		    break
		fi
	    fi
	    case "X$forceobj" in
		X-S)
		    hash8 _decode $TABLE < $unoptfile > $obj
		    /bin/rm -f $unoptfile
		    ;;
		*)
		    if [ "X$verbose" = "X-v" ]
		    then
			echo "  Assembling" 1>&2
		    fi
		    if [ "$dumbcc" = "yes" ]
		    then
			mv $unoptfile ${TMP}.s1
			hash8 _decode $TABLE < ${TMP}.s1 > ${TMP}.s
			/bin/rm -f ${TMP}.s1
			if as -o $obj ${TMP}.s
			then
			    :
			else
			    /bin/rm -f ${TMP}.s $obj
			    failure=yes
			    break
			fi
		    else
			if as -o $obj $unoptfile 2> ${TMP}.e
			then
			    /bin/rm -f $unoptfile ${TMP}.e
			else
			    hash8 _decode $TABLE < ${TMP}.e 1>&2
			    /bin/rm -f $unoptfile ${TMP}.e $obj
			    failure=yes
			    break
			fi
		    fi
		    ofiles="$ofiles $obj"
		    rmfiles="$rmfiles $obj"
		    ;;
	    esac
	    numsrcfiles="x$numsrcfiles"
	    if [ "$tablename" = "" ]
	    then
		tablename=`basename $1 .c`.t
	    fi
	    ;;
	*)
	    echo "lcc:  unrecognized argument $1, passing to cc and ld" 1>&2
	    echo "type 'cat $0' to learn usage"
	    ccsw="$ccsw $1"
	    ldsw="$ldsw $1"
	    ;;
    esac
    shift
done
if [ "$load" = yes -a "$failure" = "no" ]
then
    if [ "X$verbose" = "X-v" ]
    then
	echo "  Loading" 1>&2
    fi
    (cc $ldsw $ofiles 2> ${TMP}.e  ||  kill -7 $$) \
      | if [ "$madetable" = yes ]
        then
	    hash8 _decode $TABLE
	    hash8 _decode $TABLE < ${TMP}.e 1>&2
	elif [ -r "$tablename" ]
	then
	    hash8 _decode $tablename
	    hash8 _decode $tablename < ${TMP}.e 1>&2
	else
	    cat
	    cat ${TMP}.e 1>&2
	fi
    if [ "$numsrcfiles" = x ]
    then
	/bin/rm -f $rmfiles
    fi
fi
/bin/rm -f ${TFILE}.? ${TMP}*
if [ "$killtable" = "yes" -o "$tablename" = "" ]
then
    /bin/rm -f $TABLE
elif [ "$madetable" = yes -a "$TABLE" != "$tablename" ]
then
    mv $TABLE $tablename
fi
if [ "$failure" = "yes" ]
then
    exit 1
else
    exit 0
fi
@


1.4
log
@Major changes to handle things much better by running each compiler
pass separately.  Also add the -R switch, and support for -D and
library files.
@
text
@d3 1
a3 1
# $Header: lcc.sh,v 1.3 86/11/08 23:07:56 geoff Exp $
d6 5
d59 1
d127 1
a127 1
	    ccsw="$ccsw $1"
d129 4
d156 1
a156 1
	-f*|-C|-D*|-U*|-I*)
d258 1
a258 1
	    if $COMPILER < ${TMP}.c > $unoptfile 2> ${TMP}.e
@


1.3
log
@Add error processing, not quite like cc's
@
text
@d3 1
a3 1
# $Header: lcc.sh,v 1.2 86/11/08 22:15:24 geoff Exp $
d6 3
d37 3
a39 1
#		with -P and -S, but conflict is not cheked.
d61 2
d64 2
d72 19
a90 1
trap "/bin/rm -f ${TFILE}.? ${TMP}* $TABLE; exit 1" 1 2 15
a106 2
	    forceobj=-S
	    suffix=s
d109 4
d138 9
a146 1
	-f*|-O*|-C|-D*|-U*|-I*)
d159 3
d182 1
a182 1
		hash8 encode $TABLE < $1 > ${TMP}.s
d194 1
d204 32
a235 1
	    hash8 encode $TABLE < $1 > ${TMP}.c
d237 2
a238 4
	    (cc $verbose $ccsw $forceobj ${TMP}.c 2> ${TMP}.e  ||  kill -7 $$) \
	      | sed "s;${TMP}.c;$1;" | hash8 decode $TABLE
	    sed "s;${TMP}.c;$1;" ${TMP}.e | hash8 decode $TABLE 1>&2
	    if [ "$failure" = "yes" ]
d240 15
d257 27
a283 5
	    case "X${preprocess}Y$forceobj" in
		X-P*|*Y-S)
		    obj=`basename "$1" '.c'`.$suffix
		    hash8 _decode $TABLE < ${TFILE}.$suffix > $obj
		    /bin/rm -f ${TFILE}.$suffix
d286 4
a289 1
			if [ "X$verbose" = "X-v" ]
d291 5
a295 1
			    echo "  Assembling" 1>&2
d297 2
a298 1
			if cc $ccsw -c $obj
d300 1
a300 1
			    :
d302 2
a306 2
			/bin/rm -f $obj
			obj=`basename "$1" '.c'`.o
d309 1
a310 7
		X-E*)
		    ;;
		*)
		    obj=`basename "$1" '.c'`.$suffix
		    ofiles="$ofiles $obj"
		    mv ${TFILE}.$suffix $obj
		    ;;
d329 5
a333 1
    (cc $verbose $ldsw $ofiles 2> ${TMP}.e  ||  kill -7 $$) \
d337 1
d341 1
d344 2
a345 1
	fi 1>&2
d348 1
a348 1
	/bin/rm -f $ofiles
@


1.2
log
@Remove -HP, minor cleanup of output.  Working, except ignores errors
@
text
@d3 1
a3 1
# $Header: lcc.sh,v 1.1 86/11/08 21:58:14 geoff Exp $
d6 3
d64 3
d133 7
a139 1
		cc $ccsw $verbose $forceobj $1
d144 8
a151 3
		(cc $ccsw $forceobj $verbose ${TMP}.s 2>&1 ) \
		  | sed "s;${TMP}.s;$1;" \
		  | hash8 decode $TABLE 1>&2
d165 1
a165 1
	    (cc $verbose $ccsw $forceobj ${TMP}.c 2> ${TMP}.e ) \
d168 4
d183 7
a189 1
			cc $ccsw -c $obj
d218 1
a218 1
if [ "$load" = yes ]
d220 1
a220 1
    (cc $verbose $ldsw $ofiles 2>&1) \
d243 6
a248 1
exit
@


1.1
log
@Works only if -HP specified
@
text
@d3 1
a3 1
# $Header$
d5 4
a8 1
# $Log$
a31 3
#	-HP	Hash before passing information to the preprocessor, rather
#		than after.  Useful if your preprocessor is dumb.  Conflicts
#		with -E and -P.
d53 1
a53 1
preprocess=			# Preprocess option:  null, -P, -E, or dumbpp
a77 4
	-HP)
	    preprocess=dumbpp
	    load=no
	    ;;
d146 1
a146 13
	    if [ "X$preprocess" = "X" ]
	    then
		#
		# We preprocess before hashing so that symbols in include
		# files are picked up.  The disadvantage of this is that
		# preprocessor names are not shortened, which gives trouble
		# if your preprocessor is also dumb.  In this case,
		# specify the -HP switch.
		#
		cc $ccsw -E $1 | hash8 encode $TABLE > ${TMP}.c
	    else
		hash8 encode $TABLE < $1 > ${TMP}.c
	    fi
d149 1
a149 1
	      | hash8 decode $TABLE
d193 1
a193 1
    (cc $ldsw $ofiles 2>&1) \
@
SHAR_EOF
chmod +x 'lcc.sh,v'
fi # end of overwriting check
echo shar: extracting "'ltest.c'" '(1175 characters)'
if test -f 'ltest.c'
then
	echo shar: will not over-write existing file "'ltest.c'"
else
cat << \SHAR_EOF > 'ltest.c'
#include <stdio.h>

/*
 * Test the lcc script
 */

int VeryLongIdentifierNumber1 = 1;
int VeryLongIdentifierNumber2 = 2;

void VeryLongIdentifierNumber3 ();
/*
 * The following should generate a lint complaint, because it actually
 * returns an int.
 */
extern void VeryLongIdentifierNumber4 ();

/*
 * The following will generate a loader error.  On some loaders, this is
 * ok;  on others it will keep you from getting an output file.  If so,
 * you will need to remove the reference below.
 */
extern int VeryLongIdentifierNumber5 ();

int main (argc, argv)
    register int		argc;		/* Argument count */
    register char *		argv[];		/* Argument vector */
    {

    /*
     * Generate a C compiler warning message.  Argv is char **, not char *.
     */
    argv = (char *) argc;
    VeryLongIdentifierNumber3 ();
    /*
     * The following is in a second file
     */
    VeryLongIdentifierNumber4 ();
    return 0;
    }

void VeryLongIdentifierNumber3 ()
    {
    int i = 0;

    printf ("should print 1 2:  %d %d\n", VeryLongIdentifierNumber1,
      VeryLongIdentifierNumber2);
    if (i)				/* Never executed - undefined ref */
	VeryLongIdentifierNumber5 ();
    }
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'ltest2.c'" '(115 characters)'
if test -f 'ltest2.c'
then
	echo shar: will not over-write existing file "'ltest2.c'"
else
cat << \SHAR_EOF > 'ltest2.c'
int VeryLongIdentifierNumber4 ()
    {
    printf ("VeryLongIdentifierNumber4 VerylongIdentifierNumber5\n");
    }
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'ltest3.c'" '(116 characters)'
if test -f 'ltest3.c'
then
	echo shar: will not over-write existing file "'ltest3.c'"
else
cat << \SHAR_EOF > 'ltest3.c'
int VeryLongIdentifierNumber4 ();
    {
    printf ("VeryLongIdentifierNumber4 VerylongIdentifierNumber5\n");
    }
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'ncc'" '(314 characters)'
if test -f 'ncc'
then
	echo shar: will not over-write existing file "'ncc'"
else
cat << \SHAR_EOF > 'ncc'

# Shell script for compiling long-identifier programs.
# (Must be executed by "sh", not "csh".)
#
# The long-identifier source should be named L_xxx.
# The script is then invoked with "ncc xxx"
#
cat L_$1 | hash8 encode TABLE >$1	# Convert long identifiers
cc -c $1 2>&1 | hash8 decode TABLE	# Compile short form
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0

-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.



More information about the Comp.sources.unix mailing list