소스 검색

*** empty log message ***

sater 39 년 전
부모
커밋
b9804696fe
20개의 변경된 파일4075개의 추가작업 그리고 0개의 파일을 삭제
  1. 171 0
      util/ncgg/Makefile
  2. 992 0
      util/ncgg/cgg.y
  3. 249 0
      util/ncgg/coerc.c
  4. 22 0
      util/ncgg/cvtkeywords
  5. 73 0
      util/ncgg/emlookup.c
  6. 54 0
      util/ncgg/error.c
  7. 311 0
      util/ncgg/expr.c
  8. 155 0
      util/ncgg/hall.c
  9. 179 0
      util/ncgg/instruct.c
  10. 187 0
      util/ncgg/iocc.c
  11. 48 0
      util/ncgg/keywords
  12. 65 0
      util/ncgg/lookup.c
  13. 53 0
      util/ncgg/main.c
  14. 15 0
      util/ncgg/makedepend
  15. 837 0
      util/ncgg/output.c
  16. 99 0
      util/ncgg/scan.l
  17. 118 0
      util/ncgg/set.c
  18. 20 0
      util/ncgg/strlookup.c
  19. 382 0
      util/ncgg/subr.c
  20. 45 0
      util/ncgg/var.c

+ 171 - 0
util/ncgg/Makefile

@@ -0,0 +1,171 @@
+# $Header$
+
+CFILES=cgg.c subr.c main.c coerc.c enterkeyw.c error.c emlookup.c expr.c instruct.c iocc.c lookup.c output.c set.c strlookup.c var.c hall.c
+OFILES=cgg.o subr.o main.o coerc.o enterkeyw.o error.o emlookup.o expr.o instruct.o iocc.o lookup.o set.o strlookup.o var.o hall.o
+SOURCES=*.h cgg.y scan.l cvtkeywords keywords coerc.c emlookup.c error.c expr.c hall.c instruct.c iocc.c lookup.c main.c output.c set.c strlookup.c subr.c var.c
+EMH=../../h
+CFLAGS=-I$(EMH)
+YFLAGS=-v -d
+
+
+cgg:	cgg.o $(OFILES) output.o
+	cc $(LDFLAGS) $(OFILES) output.o ../../lib/em_data.a -ll -o cgg
+
+install:	cgg
+	cp cgg ../../lib/ncgg
+
+cmp:	cgg
+	cmp cgg ../../lib/ncgg
+
+debugcgg:	cgg.o $(OFILES) debugoutput.o
+	cc $(LDFLAGS) $(OFILES) debugoutput.o ../../lib/em_data.a -ll -o cgg
+
+cgg.o:	scan.c
+
+enterkeyw.c:	cvtkeywords keywords y.tab.h
+	cvtkeywords
+
+debugoutput.o:	debugoutput.c
+	$(CC) $(CFLAGS) -DCODEDEBUG -c debugoutput.c
+
+debugoutput.c:	output.c
+	cp output.c debugoutput.c
+
+lint:	$(CFILES)
+	lint $(CFLAGS) $(CFILES)
+	touch lint
+
+clean:
+	rm -f cgg.c scan.c y.output y.tab.h enterkeyw.c
+	rm -f $(OFILES) output.o debugoutput.o cgg lint
+
+pr:
+	pr $(SOURCES)
+
+lpr:
+	make pr|lpr
+
+depend:
+	makedepend
+
+cgg.o:	$(EMH)/cgg_cg.h
+coerc.o:	$(EMH)/cgg_cg.h
+debugoutput.o:	$(EMH)/cgg_cg.h
+expr.o:	$(EMH)/cgg_cg.h
+instruct.o:	$(EMH)/cgg_cg.h
+iocc.o:	$(EMH)/cgg_cg.h
+output.o:	$(EMH)/cgg_cg.h
+set.o:	$(EMH)/cgg_cg.h
+subr.o:	$(EMH)/cgg_cg.h
+var.o:	$(EMH)/cgg_cg.h
+# AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
+cgg.o:	expr.h
+cgg.o:	extern.h
+cgg.o:	instruct.h
+cgg.o:	iocc.h
+cgg.o:	lookup.h
+cgg.o:	param.h
+cgg.o:	scan.c
+cgg.o:	set.h
+cgg.o:	varinfo.h
+coerc.o:	assert.h
+coerc.o:	extern.h
+coerc.o:	iocc.h
+coerc.o:	param.h
+coerc.o:	property.h
+coerc.o:	pseudo.h
+coerc.o:	reg.h
+coerc.o:	set.h
+coerc.o:	token.h
+coerc.o:	varinfo.h
+debugoutput.o:	assert.h
+debugoutput.o:	extern.h
+debugoutput.o:	instruct.h
+debugoutput.o:	lookup.h
+debugoutput.o:	param.h
+debugoutput.o:	property.h
+debugoutput.o:	pseudo.h
+debugoutput.o:	reg.h
+debugoutput.o:	regvar.h
+debugoutput.o:	set.h
+debugoutput.o:	token.h
+debugoutput.o:	varinfo.h
+emlookup.o:	expr.h
+emlookup.o:	param.h
+enterkeyw.o:	lookup.h
+expr.o:	assert.h
+expr.o:	expr.h
+expr.o:	extern.h
+expr.o:	lookup.h
+expr.o:	param.h
+expr.o:	property.h
+expr.o:	reg.h
+expr.o:	regvar.h
+expr.o:	set.h
+expr.o:	token.h
+hall.o:	assert.h
+hall.o:	param.h
+hall.o:	set.h
+instruct.o:	expr.h
+instruct.o:	extern.h
+instruct.o:	instruct.h
+instruct.o:	iocc.h
+instruct.o:	param.h
+instruct.o:	pseudo.h
+instruct.o:	set.h
+instruct.o:	varinfo.h
+iocc.o:	assert.h
+iocc.o:	expr.h
+iocc.o:	extern.h
+iocc.o:	iocc.h
+iocc.o:	lookup.h
+iocc.o:	param.h
+iocc.o:	property.h
+iocc.o:	regvar.h
+iocc.o:	set.h
+iocc.o:	token.h
+lookup.o:	assert.h
+lookup.o:	lookup.h
+lookup.o:	param.h
+output.o:	assert.h
+output.o:	extern.h
+output.o:	instruct.h
+output.o:	lookup.h
+output.o:	param.h
+output.o:	property.h
+output.o:	pseudo.h
+output.o:	reg.h
+output.o:	regvar.h
+output.o:	set.h
+output.o:	token.h
+output.o:	varinfo.h
+scan.o:	stdio.h
+set.o:	extern.h
+set.o:	lookup.h
+set.o:	param.h
+set.o:	property.h
+set.o:	set.h
+set.o:	token.h
+strlookup.o:	param.h
+subr.o:	expr.h
+subr.o:	extern.h
+subr.o:	instruct.h
+subr.o:	lookup.h
+subr.o:	param.h
+subr.o:	property.h
+subr.o:	reg.h
+subr.o:	regvar.h
+subr.o:	set.h
+subr.o:	token.h
+subr.o:	varinfo.h
+tables.o:	data.h
+tables.o:	param.h
+tables.o:	tables.h
+tables.o:	types.h
+var.o:	instruct.h
+var.o:	lookup.h
+var.o:	param.h
+var.o:	property.h
+var.o:	reg.h
+var.o:	set.h
+var.o:	token.h

+ 992 - 0
util/ncgg/cgg.y

@@ -0,0 +1,992 @@
+%{
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include "param.h"
+#include "varinfo.h"
+#include "lookup.h"
+#include "set.h"
+#include "iocc.h"
+#include "instruct.h"
+#include "expr.h"
+#include "extern.h"
+#include <cgg_cg.h>
+#include <em_reg.h>
+
+extern int lineno;
+int instline,saveline;
+int startline;
+int npatterns;
+int patindex[MAXPATTERNS];
+
+int emhere=0;	/* lexical analyzer flag */
+int optexact=0;	/* Inside "with exact" rule */
+int optstack=0;	/* Inside with <blah> STACK rule */
+int saferulefound=0;
+int maxempatlen=0;
+int maxrule=0;
+struct varinfo *defcost;
+
+struct varinfo *gen_inst(),*gen_move(),*gen_test(),*gen_preturn(),*gen_tlab();
+struct varinfo *make_erase();
+expr_t make_expr(),ident_expr(),subreg_expr(),tokm_expr(),all_expr();
+expr_t perc_ident_expr(),sum_expr(),regvar_expr();
+
+set_t ident_to_set(),setproduct(),setsum(),setdiff();
+
+iocc_t subr_iocc(),tokm_iocc(),ident_iocc(),all_iocc(),descr_iocc();
+
+extern int narexpr;
+extern expr_t arexp[];
+
+int niops;
+iocc_t iops[20];
+%}
+
+%union {
+	int yy_int;
+	char * yy_str;
+	varinfo * yy_varinfo;
+	set_t yy_set;
+	operand *yy_oplist;
+	expr_t yy_expr;
+	iocc_t yy_iocc;
+}
+
+%token PROPERTIES
+%token REGISTERS
+%token TOKENS
+%token SETS
+%token MOVES
+%token TESTS
+%token STACKINGRULES COERCIONS
+%token INSTRUCTIONS
+%token PROC CALL EXAMPLE
+%token FROM TO
+%token TEST MOVE STACK RETURN
+%token PATTERNS PAT WITH EXACT KILLS USES REUSING GEN YIELDS LEAVING
+%token DEFINED SAMESIGN SFIT UFIT ROM LOWW HIGHW
+%token CMPEQ CMPNE CMPLT CMPGT CMPLE CMPGE OR2 AND2 LSHIFT RSHIFT NOT COMP
+%token INREG REGVAR REG_ANY REG_FLOAT REG_LOOP REG_POINTER
+%token <yy_int> ADORNACCESS
+%token <yy_int> ADORNCC
+%token INT
+%token ADDR
+%token <yy_int> EMMNEM
+%token <yy_int> NUMBER
+%token <yy_int> DOLLAR PERCENT ALLREG
+%token <yy_str> IDENT PERC_IDENT
+%token <yy_str> STRING
+%token TIMEFACTOR SIZEFACTOR
+%token COST
+%type <yy_varinfo> prop_list property ident_list ident_list_el
+%type <yy_varinfo> att_list att_list_el structdecl optcost optformat
+%type <yy_varinfo> kills allocates yields leaving
+%type <yy_varinfo> generates kill_list kill_list_el uselist uselist_el genlist yieldlist
+%type <yy_varinfo> leavelist leavelist_el gen_instruction
+%type <yy_varinfo> opt_erase_list erase_list erase_list_el
+%type <yy_str> opt_par_string optstring
+%type <yy_int> register propno att_list_el_type tokenset_no
+%type <yy_int> adornlist optstar optuses optregvar regvartype optregvartype
+%type <yy_int> emarg tokarg subreg allreg optsecondstring
+%type <yy_expr> expr
+%type <yy_iocc> tokeninstance
+%type <yy_int> optexpr optexact optstack
+%type <yy_set> tokenset
+%type <yy_oplist> oplist oplist_el
+
+%left OR2
+%left AND2
+%left CMPEQ,CMPNE
+%left CMPLT,CMPLE,CMPGT,CMPGE
+%left RSHIFT,LSHIFT
+%left '+','-'
+%left '*','/','%'
+%nonassoc NOT,COMP,UMINUS
+
+%start machtable
+
+%%
+/*
+ * The machine table consists of a number of sections, with their
+ * own associated parsers.
+ */
+machtable
+	: constants
+	  properties
+	  registers
+	  tokens
+	  	{ make_std_sets(); }
+	  sets
+	  instructions
+	  moves
+	  tests
+	  stacks
+	  coercs
+	  code
+	;
+
+/*
+ * Constants are parsed as name=value pairs
+ */
+constants
+	: constdeflist
+	;
+constdeflist
+	: /* empty */
+	| constdeflist constdef
+	;
+constdef
+	: IDENT'=' NUMBER
+		{ n_const($1,$3); free($1); }
+	| IDENT '=' STRING
+		{ n_sconst($1,$3); free($1); free($3); }
+	| TIMEFACTOR '=' NUMBER '/' NUMBER
+		{ fc1 = $3; fc2 = $5; }
+	| SIZEFACTOR '=' NUMBER '/' NUMBER
+		{ fc3 = $3; fc4 = $5; }
+	| error
+	;
+
+/*
+ * Properties are parsed as a list of names optionally followed by their size
+ */
+properties
+	: PROPERTIES  { make_const(); } prdef_list
+	;
+prdef_list
+	: prdef_list_el
+	| prdef_list optcomma prdef_list_el
+	;
+prdef_list_el
+	: IDENT
+		{ n_prop($1,wordsize); free($1); }
+	| IDENT '(' NUMBER ')'
+		{ n_prop($1,$3); free($1); }
+	;
+
+/*
+ * Registers are rows of reglist:proplist pairs
+ */
+registers
+	: REGISTERS regdef_list
+	;
+regdef_list
+	: regdef_list_el
+	| regdef_list regdef_list_el
+	;
+regdef_list_el
+	: ident_list ':' prop_list optregvar '.'
+		{ regline($1,$3,$4); free((char *) $1); free((char *) $3); }
+	| error '.'
+	;
+optregvar
+	: /* empty */
+		{ $$ = -1; }
+	| REGVAR
+		{ $$ = reg_any; }
+	| REGVAR '(' regvartype ')'
+		{ $$ = $3; }
+	;
+
+regvartype
+	: REG_ANY
+		{ $$ = reg_any;}
+	| REG_FLOAT
+		{ $$ = reg_float;}
+	| REG_LOOP
+		{ $$ = reg_loop;}
+	| REG_POINTER
+		{ $$ = reg_pointer;}
+	;
+
+ident_list
+	: ident_list_el
+	| ident_list optcomma ident_list_el
+		{ $3->vi_next = $1; $$ = $3; }
+	;
+ident_list_el
+	: IDENT opt_par_string
+		{ NEW($$,struct varinfo);
+		  $$->vi_next = 0;
+		  $$->vi_int[0] = n_reg($1,$2,0,0,0);
+		  free($1); if($2!=0) free($2);
+		}
+	| IDENT opt_par_string '=' register
+		{ NEW($$,struct varinfo);
+		  $$->vi_next = 0;
+		  $$->vi_int[0] = n_reg($1,$2,1,$4,0);
+		  free($1); if($2!=0) free($2);
+		}
+	| IDENT opt_par_string '=' register '+' register
+		{ NEW($$,struct varinfo);
+		  $$->vi_next = 0;
+		  $$->vi_int[0] = n_reg($1,$2,2,$4,$6);
+		  free($1); if($2!=0) free($2);
+		}
+	;
+opt_par_string
+	: /* empty */
+		{ $$ = 0; }
+	| '(' STRING ')'
+		{ $$ = $2; }
+	;
+register
+	: IDENT
+		{ register symbol *sy_p;
+
+		  sy_p = lookup($1,symreg,mustexist);
+		  $$ = sy_p->sy_value.syv_regno;
+		  free($1);
+		}
+	;
+prop_list
+	: property
+	| prop_list optcomma property
+		{ $3->vi_next = $1; $$ = $3; }
+	;
+property
+	: IDENT
+		{ register symbol *sy_p;
+		  sy_p = lookup($1,symprop,mustexist);
+		  NEW($$,struct varinfo);
+		  $$->vi_next=0;
+		  $$->vi_int[0]=sy_p->sy_value.syv_propno;
+		  free($1);
+		}
+	;
+propno
+	: IDENT
+		{ register symbol *sy_p;
+		  sy_p = lookup($1,symprop,mustexist);
+		  $$ = sy_p->sy_value.syv_propno;
+		  free($1);
+		}
+	;
+
+/* tokens are parsed as struct definitions
+ * types in the struct can be register properties, ADDR or INT
+ */
+
+tokens
+	: TOKENS tokdeflist
+	;
+tokdeflist
+	: tokdeflist_el
+	| tokdeflist tokdeflist_el
+	;
+tokdeflist_el
+	: IDENT '=' structdecl NUMBER optcost optformat '.'
+		{ n_tok($1,$3,$4,$5,$6);
+		  free($1);
+		  freevi($3);
+		  freevi($5);
+		  freevi($6);
+		}
+	| error '.'
+	;
+structdecl
+	: '{' att_list '}'
+		{ $$ = $2; }
+	;
+att_list
+	: /* empty */
+		{ $$ = 0; }
+	| att_list_el att_list
+		{ $1->vi_next = $2; $$ = $1; }
+	;
+att_list_el
+	: att_list_el_type IDENT ';'
+		{ NEW ($$,struct varinfo);
+		  $$->vi_next = 0;
+		  $$->vi_int[0] = $1;
+		  $$->vi_str[0] = $2;
+		}
+	;
+att_list_el_type
+	: INT
+		{ $$ = -1; }
+	| ADDR
+		{ $$ = -2; }
+	| propno
+	;
+optcost
+	:
+		{ if (defcost==VI_NULL)
+		  	$$=VI_NULL;
+		  else {
+			NEW($$,struct varinfo);
+			*$$ = *defcost;
+		  }
+	 	}
+	| COST '(' NUMBER ',' NUMBER ')'
+		{ NEW ($$,struct varinfo);
+		  $$->vi_int[0] = $3;
+		  $$->vi_int[1] = $5;
+		}
+	;
+optformat
+	:
+		{ $$ = 0; }
+	| STRING optformat
+		{ NEW($$,struct varinfo);
+		  $$->vi_next = $2;
+		  $$->vi_int[0] = 0;
+		  $$->vi_str[0] = $1;
+		}
+	| IDENT optformat
+		{ NEW($$,struct varinfo);
+		  $$->vi_next = $2;
+		  $$->vi_int[0] = 1;
+		  $$->vi_str[0] = $1;
+		}
+	;
+optcomma
+	: ','
+	| /* empty */
+	;
+
+/* sets are parsed as ident = expression */
+
+sets
+	: SETS setdeflist
+	;
+setdeflist
+	: setdeflist_el
+	| setdeflist setdeflist_el
+	;
+setdeflist_el
+	: IDENT '=' tokenset_no '.'
+		{ n_set($1,$3); free($1); }
+	| error '.'
+	;
+tokenset_no
+	: tokenset
+		{ $$ = setlookup($1); }
+	;
+tokenset
+	: IDENT
+		{ $$ = ident_to_set($1); free($1); }
+	| tokenset '*' tokenset
+		{ $$ = setproduct($1,$3); }
+	| tokenset '+' tokenset
+		{ $$ = setsum($1,$3); }
+	| tokenset '-' tokenset
+		{ $$ = setdiff($1,$3); }
+	| '(' tokenset ')'
+		{ $$ = $2; }
+	;
+
+instructions
+	: INSTRUCTIONS optcost instdef_list
+		{ defcost = $2; }
+	;
+instdef_list
+	: instdef_list_el
+	| instdef_list instdef_list_el
+	;
+instdef_list_el
+	: IDENT optstring oplist opt_erase_list optcost '.'
+		{ n_instr($1,$2,$3,$4,$5); freevi($5); }
+	| error '.'
+	;
+oplist
+	: /* empty */
+		{ $$ = 0; }
+	| oplist_el
+	| oplist_el ',' oplist
+		{ $$ = $1; $$->o_next = $3; }
+	;
+oplist_el
+	: tokenset_no adornlist
+		{ NEW($$,struct operand);
+		  $$->o_next  = 0 ;
+		  $$->o_setno = $1;
+		  $$->o_adorn = $2;
+		  checkprintformat($1);
+		}
+	;
+adornlist
+	: /* empty */
+		{ $$ = 0; }
+	| ADORNACCESS adornlist
+		{ if ($2&AD_RWMASK)
+			error("Only one of :ro,:wo,:rw allowed");
+		  $$ = $1 | $2;
+		}
+	| ADORNCC adornlist
+		{ $$ = $1|$2; }
+	;
+opt_erase_list
+	: /* empty */
+		{ $$ = VI_NULL;}
+	| KILLS erase_list
+		{ $$ = $2; }
+	;
+erase_list
+	: erase_list_el
+		{ $$ = $1; }
+	| erase_list_el erase_list
+		{ $1->vi_next = $2; $$ = $1; }
+	;
+erase_list_el
+	: IDENT
+		{ $$ = make_erase($1); }
+	| ADORNCC
+		{ NEW($$, struct varinfo);
+		  $$->vi_int[0] = -1;
+		  $$->vi_next = VI_NULL;
+		}
+	;
+
+/* Now the moves */
+
+moves
+	: MOVES movedeflist
+	| /* empty */
+	;
+movedeflist
+	: movedeflist_el
+	| movedeflist movedeflist_el
+	;
+movedeflist_el
+	: FROM
+		{startline = lineno; }
+	  tokenset_no
+		{ cursetno = $3; }
+	  optexpr TO tokenset_no
+	  	{ cursetno = $7;
+		  tokpatlen=2;
+		  tokpatset[0] = $3;
+		  tokpatset[1] = $7;
+		  tokpatro[0] = 1;
+		}
+	optexpr GEN genlist
+		{ tokpatlen=0;
+		  tokpatro[0]=0;
+		  n_move($3,$5,$7,$9,$11);
+		  freevi($11);
+		}
+	| error
+	;
+
+/* Now the test part */
+
+tests
+	: TESTS testdeflist
+	| /* empty */
+	;
+testdeflist
+	: testdeflist_el
+	| testdeflist testdeflist_el
+	;
+testdeflist_el
+	: TO
+		{ startline = lineno;}
+ 	  TEST tokenset_no
+		{ cursetno = $4;
+		  tokpatlen=1;
+		  tokpatset[0]=$4;
+		  tokpatro[0] = 1;
+		}
+	  optexpr GEN genlist
+	  	{ tokpatlen=0;
+		  tokpatro[0] = 0;
+		  n_test($4,$6,$8);
+		  freevi($8);
+		}
+	| error
+	;
+	  
+/* Now the stacks */
+
+stacks
+	: STACKINGRULES stackdeflist
+	;
+stackdeflist
+	: stackdeflist_el
+	| stackdeflist stackdeflist_el
+	;
+stackdeflist_el
+	: FROM
+		{startline = lineno;}
+	  tokenset_no
+		{ cursetno = $3; 
+		  tokpatlen=1; 
+		  tokpatset[0] = $3; 
+		  tokpatro[0] = 1;
+		}
+	  optexpr TO STACK optuses GEN genlist
+		{ tokpatro[0] = 0;
+		  n_stack($3,$5,$8,$10);
+		  freevi($10);
+		}
+	;
+optuses
+	: /* empty */
+		{ $$ = 0; nallreg=0;}
+	| USES propno
+		{ $$ = $2; nallreg = 1; allreg[0] = $2; }
+	;
+
+/* Now the one-to-one coercion rules */
+
+coercs
+	: COERCIONS coercdeflist
+	;
+coercdeflist
+	: coercdeflist_el
+	| coercdeflist coercdeflist_el
+	;
+coercdeflist_el
+	: FROM
+		{startline = lineno; tokpatlen=0; inithall();}
+	  STACK allocates GEN genlist YIELDS tokeninstance
+		{ checkhall();
+		  n_coerc(0,0,$4,$6,(struct varinfo *) 0,$8);
+		  freevi($4);
+		  freevi($6);
+		}
+	| FROM
+		{startline = lineno;}
+	  tokenset_no
+		{ cursetno = $3; 
+		  tokpatlen=1; 
+		  tokpatset[0]=$3; 
+		  tokpatro[0] = 1;
+		  inithall();
+		}
+	  optexpr allocates generates yields
+	  	{ tokpatro[0] = 0;
+		  checkhall();
+		  n_coerc($3,$5,$6,$7,$8);
+		  freevi($6);
+		  freevi($7);
+		}
+	;
+
+/* Now the code part */
+
+code
+	: PATTERNS coderules
+	;
+coderules
+	: coderule
+	| coderules coderule
+	;
+coderule
+	: PAT {emhere=1;} empattern {emhere=0;} optexpr
+		{ empatexpr = $5;
+		  npatterns = 0;
+		  saferulefound=0;
+		  if (empatlen>maxempatlen)
+			maxempatlen=empatlen;
+		}
+	  patterns
+		{ if (!saferulefound)
+			error("Previous rule impossible on empty stack");
+		  outpatterns();
+		}
+	| PROC IDENT example
+		{ npatterns = 0; saferulefound=0; inproc=1; n_proc($2); }
+	  patterns
+		{ if (!saferulefound)
+			error("Previous rule impossible on empty stack");
+		  outpatterns(); inproc=0;
+		}
+	| error
+		{ skipupto(PAT,"pat"); yyerrok; yyclearin; }
+	;
+example
+	: /* empty */
+		{ empatlen = 0; }
+	| EXAMPLE {emhere=1;} empattern {emhere=0;}
+	;
+empattern
+	: EMMNEM
+		{ empatlen = 1; emmnem[0] = $1; }
+	| empattern EMMNEM
+		{ NEXT(empatlen,EMPATMAX,"Em pattern");
+		  emmnem[empatlen-1] = $2;
+		}
+	;
+patterns
+	: onepattern
+		{ saferulefound=1;
+		  callproc=0;
+		}
+	| morepatterns
+		{ callproc=0;
+		  if (npatterns>maxrule)
+		  	maxrule=npatterns;
+		}
+	| CALL IDENT '(' STRING optsecondstring ')'
+		{ register symbol *sy_p;
+		  saferulefound=1;
+		  sy_p=lookup($2,symproc,mustexist);
+		  callproc=sy_p->sy_value.syv_procoff;
+		  procarg[0] = strlookup($4);
+		  procarg[1] = $5;
+		  free($2);
+		  free($4);
+		}
+	;
+optsecondstring
+	: /* empty */
+		{ $$ = 0; }
+	| ',' STRING
+		{ $$ = strlookup($2); free($2); }
+	;
+
+onepattern
+	: 	{ inithall(); startline=lineno; tokpatlen=0; }
+	  kills allocates generates yields leaving
+		{ optexact=0; optstack=0;
+		  patindex[npatterns++]=codeindex;
+		  checkhall();
+		  dopattern(0,$2,$3,$4,$5,$6);
+		  freevi($2);
+		  freevi($3);
+		  freevi($4);
+		  freevi($5);
+		  freevi($6);
+		}
+	;
+morepatterns
+	: { inithall(); } pattern
+	| morepatterns { inithall(); } pattern
+	;
+
+pattern
+	: stackpattern kills allocates generates yields leaving
+		{ patindex[NEXT(npatterns,MAXPATTERNS,"Patterns")]=codeindex;
+		  if (hall() && !optexact) saferulefound=1;
+		  dopattern(0,$2,$3,$4,$5,$6);
+		  freevi($2);
+		  freevi($3);
+		  freevi($4);
+		  freevi($5);
+		  freevi($6);
+		}
+	;
+stackpattern
+	: WITH optexact
+		{ startline = lineno; }
+	  setlist optstack
+	;
+optexact
+	: /* empty */
+		{ $$ = optexact = 0; }
+	| EXACT
+		{ $$ = optexact = 1; }
+	;
+optstack
+	: /* empty */
+		{ $$ = optstack = 0; }
+	| STACK
+		{ $$ = optstack = 1; }
+	;
+
+setlist
+	: /* empty */
+		{ tokpatlen = 0; }
+	| setlist tokenset_no
+		{ NEXT(tokpatlen,TOKPATMAX,"Stack pattern");
+		  tokpatset[tokpatlen-1] = $2;
+		  checkunstacking($2);
+		}
+	;
+kills
+	: /* empty */
+		{ $$ = 0; }
+	| KILLS kill_list
+		{ $$ = $2;
+		  if (optstack)
+			error("No sense in giving kills in this pattern");
+		}
+	;
+kill_list
+	: kill_list_el
+	| kill_list_el ',' kill_list
+		{ $$=$1; $$->vi_next = $3; }
+	;
+kill_list_el
+	: tokenset_no { cursetno=$1; } optexpr
+		{ NEW($$,struct varinfo);
+		  $$->vi_next = 0;
+		  $$->vi_int[0]=$1;
+		  $$->vi_int[1]=$3;
+		}
+	;
+allocates
+	: /* empty */
+		{ $$ = 0; nallreg=0;}
+	| USES uselist
+		{ $$ = $2; setallreg($2); }
+	;
+uselist
+	: uselist_el
+		{ prophall($1->vi_int[0]); }
+	| uselist_el ',' uselist
+		{ prophall($1->vi_int[0]); $$=$1; $$->vi_next=$3; }
+	;
+uselist_el
+	: property
+		{ $$=$1; $$->vi_int[1] = 0; }
+	| property '=' tokeninstance
+		{ if (!existalmove($3,$$->vi_int[0]))
+			error("No such move defined");
+		  $$=$1; $$->vi_int[1] = $3.in_index; 
+		}
+	| REUSING tokeninstance
+		{ NEW($$,struct varinfo);
+		  $$->vi_next = 0;
+		  $$->vi_int[0] = -1;
+		  $$->vi_int[1] = $2.in_index;
+		}
+	;
+
+
+generates
+	: /* empty */
+		{ $$ = 0; }
+	| GEN genlist
+		{ $$ = $2; }
+	;
+genlist
+	: /* empty */
+		{ $$ = 0; }
+	| gen_instruction genlist
+		{ if ($1!=0) {
+			register struct varinfo *tvip;
+			$$=tvip=$1;
+			while (tvip->vi_next!=VI_NULL)
+				tvip=tvip->vi_next;
+		 	tvip->vi_next = $2;
+		  } else {
+			$$ = $2;
+		  }
+		}
+	;
+gen_instruction
+	: {instline = lineno; } IDENT optstar gen_oplist
+		{ saveline =lineno; lineno=instline;
+		  $$ = gen_inst($2,$3); free($2);
+		  lineno = saveline;
+		}
+	| NUMBER ':'
+		{ $$ = gen_tlab($1); }
+	| MOVE tokeninstance ',' tokeninstance
+		{ $$ = gen_move($2,$4); }
+	| TEST tokeninstance
+		{ $$ = gen_test($2);}
+	| RETURN
+		{ $$ = gen_preturn(); }
+	;
+optstar
+	: /* empty */
+		{ $$=0; }
+	| '*'
+		{ $$=1; }
+	| '[' NUMBER ']'
+		{ $$=$2; }
+	;
+gen_oplist
+	: '.' /* empty gives conflicts */
+		{ niops=0; }
+	| tokeninstance
+		{ niops=1;iops[0]=$1; }
+	| gen_oplist ',' tokeninstance
+		{ iops[niops++] = $3; }
+	;
+
+yields
+	: /* empty */
+		{ $$ = 0; }
+	| YIELDS yieldlist
+		{ $$ = $2; }
+	;
+yieldlist
+	: /* empty */
+		{ $$ = 0; }
+	| tokeninstance yieldlist
+		{ checkstacking($1.in_set);
+		  NEW($$,struct varinfo);
+		  $$->vi_next = $2;
+		  $$->vi_int[0] = $1.in_index;
+		}
+	;
+
+leaving
+	: /* empty */
+		{ $$ = 0; }
+	| LEAVING {emhere=1; } leavelist
+		{ emhere=0; $$ = $3; }
+	;
+leavelist
+	: leavelist_el
+	| leavelist_el leavelist
+		{ $$=$1; $$->vi_next=$2; }
+	;
+leavelist_el
+	: EMMNEM optexpr
+		{ NEW($$,struct varinfo);
+		  $$->vi_next=0;
+		  $$->vi_int[0] = $1;
+		  $$->vi_int[1] = $2;
+		}
+	;
+
+optstring
+	: /* empty */
+		{ $$ = 0; }
+	| STRING
+	;
+optexpr
+	: /* empty */
+		{ $$ = 0; }
+	| expr
+		{ $$ = $1.ex_index; }	/* type checking ? */
+	;
+
+tokeninstance
+	: tokarg subreg
+		{ $$ = subr_iocc($1,$2); }
+	| tokarg '.' IDENT
+		{ $$ = tokm_iocc($1,$3); free($3); }
+	| IDENT
+		{ $$ = ident_iocc($1); free($1);}
+	| allreg subreg
+		{ $$ = all_iocc($1,$2); }
+	| '{' IDENT attlist '}'
+		{ $$ = descr_iocc($2); free($2); }
+	;
+attlist
+	: /* empty */
+		{ narexpr = 0; }
+	| attlist ',' expr
+		{ arexp[narexpr++] = $3; }
+	;
+
+emarg
+	: DOLLAR
+		{ if ($1<1 || $1>empatlen)
+			error("Only %d instructions in pattern",empatlen);
+		  $$ = $1;
+		}
+	;
+tokarg
+	: PERCENT
+		{ if ($1<1 || $1>tokpatlen) {
+			error("Only %d tokens in stackpattern",tokpatlen);
+			$$ =1;
+		  } else {
+			  $$ = $1;
+		  }
+		}
+	;
+subreg
+	: /* empty */
+		{ $$ = 0; }
+	| '.' NUMBER
+		{ if ($2<1 || $2>2) {
+			error("Only 2 subregisters allowed");
+			$$ = 1;
+		  } else {
+			$$ = $2;
+		  }
+		}
+	;
+allreg
+	: ALLREG
+		{ if ($1>=nallreg)
+			fatal("Only %d registers allocated",nallreg);
+		  $$ = $1;
+		}
+	;
+
+expr
+	: NUMBER
+		{ $$ = make_expr(TYPINT,EX_CON, (int) ($1 & 0xFFFF), (int) ($1>>16));
+		}
+	| emarg
+		{ $$ = make_expr(argtyp(emmnem[$1-1]),EX_ARG,$1,0); }
+	| STRING
+		{ $$ = make_expr(TYPADDR,EX_STRING,strlookup($1),0); free($1); }
+	| IDENT
+		{ $$ = ident_expr($1); free($1); }
+	| tokarg subreg
+		{ $$ = subreg_expr($1,$2); }
+	| tokarg '.' IDENT
+		{ $$ = tokm_expr($1,$3); free($3); }
+	| allreg subreg
+		{ $$ = all_expr($1,$2); }
+	| PERC_IDENT
+		{ $$ = perc_ident_expr($1); free($1); }
+	| DEFINED '(' expr ')'
+		{ $$ = make_expr(TYPBOOL,EX_DEFINED,i_expr($3),0); }
+	| SAMESIGN '(' expr ',' expr ')'
+		{ $$ = make_expr(TYPBOOL,EX_SAMESIGN,i_expr($3),i_expr($5)); }
+	| SFIT '(' expr ',' expr ')'
+		{ $$ = make_expr(TYPBOOL,EX_SFIT,i_expr($3),i_expr($5)); }
+	| UFIT '(' expr ',' expr ')'
+		{ $$ = make_expr(TYPBOOL,EX_UFIT,i_expr($3),i_expr($5)); }
+	| ROM '(' emarg ',' NUMBER ')'
+		{ $$ = make_expr(TYPINT,EX_ROM,$3-1,chkincl($5,1,3)-1); }
+	| LOWW '(' emarg ')'
+		{ $$ = make_expr(TYPINT,EX_LOWW,$3-1,0); }
+	| HIGHW '(' emarg ')'
+		{ $$ = make_expr(TYPINT,EX_HIGHW,$3-1,0); }
+	| '(' expr ')'
+		{ $$ = $2; }
+	| expr CMPEQ expr
+		{ $$ = make_expr(TYPBOOL,eq2expr($1,$3),$1.ex_index,$3.ex_index); }
+	| expr CMPNE expr
+		{ $$ = make_expr(TYPBOOL,ne2expr($1,$3),$1.ex_index,$3.ex_index); }
+	| expr CMPLT expr
+		{ $$ = make_expr(TYPBOOL,EX_NCPLT,i_expr($1),i_expr($3)); }
+	| expr CMPGT expr
+		{ $$ = make_expr(TYPBOOL,EX_NCPGT,i_expr($1),i_expr($3)); }
+	| expr CMPLE expr
+		{ $$ = make_expr(TYPBOOL,EX_NCPLE,i_expr($1),i_expr($3)); }
+	| expr CMPGE expr
+		{ $$ = make_expr(TYPBOOL,EX_NCPGE,i_expr($1),i_expr($3)); }
+	| expr OR2 expr
+		{ $$ = make_expr(TYPBOOL,EX_OR2,b_expr($1),b_expr($3)); }
+	| expr AND2 expr
+		{ $$ = make_expr(TYPBOOL,EX_AND2,b_expr($1),b_expr($3)); }
+	| expr '+' expr
+		{ $$ = sum_expr($1,$3); }
+	| expr '-' expr
+		{ $$ = make_expr(TYPINT,EX_MINUS,i_expr($1),i_expr($3)); }
+	| expr '*' expr
+		{ $$ = make_expr(TYPINT,EX_TIMES,i_expr($1),i_expr($3)); }
+	| expr '/' expr
+		{ $$ = make_expr(TYPINT,EX_DIVIDE,i_expr($1),i_expr($3)); }
+	| expr '%' expr
+		{ $$ = make_expr(TYPINT,EX_MOD,i_expr($1),i_expr($3)); }
+	| expr LSHIFT expr
+		{ $$ = make_expr(TYPINT,EX_LSHIFT,i_expr($1),i_expr($3)); }
+	| expr RSHIFT expr
+		{ $$ = make_expr(TYPINT,EX_RSHIFT,i_expr($1),i_expr($3)); }
+	| NOT expr
+		{ $$ = make_expr(TYPBOOL,EX_NOT,b_expr($2),0); }
+	| COMP expr
+		{ $$ = make_expr(TYPINT,EX_COMP,i_expr($2),0); }
+	| INREG '(' expr ')'
+		{ $$ = make_expr(TYPINT,EX_INREG,i_expr($3),0); }
+	| regvartype
+		{ $$ = make_expr(TYPINT,EX_CON, $1+1, 0); }
+	| REGVAR '(' expr optregvartype ')'
+		{ $$ = regvar_expr($3,$4); }
+	;
+
+optregvartype
+	: /* empty */
+		{ $$ = reg_any; }
+	| ',' regvartype
+		{ $$ = $2; }
+	;
+%%
+#include "scan.c"

+ 249 - 0
util/ncgg/coerc.c

@@ -0,0 +1,249 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include "assert.h"
+#include "param.h"
+#include "set.h"
+#include "property.h"
+#include "reg.h"
+#include "token.h"
+#include "varinfo.h"
+#include "iocc.h"
+#include <cgg_cg.h>
+#include "pseudo.h"
+#include "extern.h"
+
+extern set_t l_sets[];
+
+int nmoves;
+move_t l_moves[MAXMOVES];
+short posmoves[MAXREGS+MAXTOKENS][SETSIZE];
+
+n_move(s1,e1,s2,e2,vi) struct varinfo *vi; {
+	register move_p mp;
+	register i,j;
+
+	NEXT(nmoves,MAXMOVES,"Moves");
+	mp = &l_moves[nmoves-1];
+	mp->m_set1 = s1;
+	mp->m_expr1 = e1;
+	mp->m_set2 = s2;
+	mp->m_expr2 = e2;
+	mp->m_cindex = codeindex;
+	dopattern(0,VI_NULL,VI_NULL,vi,VI_NULL,VI_NULL);
+	if (mp->m_expr1!=0 || mp->m_expr2!=0)
+		return;
+	for (i=0;i<MAXREGS+MAXTOKENS;i++)
+	    if (BIT(l_sets[mp->m_set1].set_val,i))
+	    	for(j=0;j<SETSIZE;j++)
+		    posmoves[i][j] |= l_sets[mp->m_set2].set_val[j];
+}
+
+existmove(from,sp) iocc_t from; short *sp; {
+	register i;
+
+	for (i=0;i<MAXREGS+MAXTOKENS;i++)
+	    if(BIT(from.in_set,i))
+		if (!subset(sp,posmoves[i],SETSIZE))
+			return(0);
+	return(1);
+}
+
+existalmove(from,prpno) iocc_t from; {
+	short s[SETSIZE];
+	register i;
+	
+	for (i=0;i<SETSIZE;i++)
+		s[i] = i<SZOFSET(MAXREGS) ? l_props[prpno].pr_regset[i] : 0;
+	return(existmove(from,s));
+}
+
+struct varinfo *gen_move(from,to) iocc_t from,to; {
+	register struct varinfo *vp;
+
+	if (existmove(from,to.in_set)==0) {
+		error("No such move defined");
+		return(VI_NULL);
+	}
+	NEW(vp,struct varinfo);
+	vp->vi_int[0] = INSMOVE;
+	vp->vi_int[1] = from.in_index;
+	vp->vi_int[2] = to.in_index;
+	return(vp);
+}
+
+int ntests;
+test_t l_tests[MAXTESTS];
+short postests[SETSIZE];
+
+n_test(s,e,vi) struct varinfo *vi; {
+	register test_p tp;
+	register i;
+
+	NEXT(ntests,MAXTESTS,"Tests");
+	tp = &l_tests[ntests-1];
+	tp->t_set = s;
+	tp->t_expr = e;	
+	tp->t_cindex = codeindex;
+	dopattern(0,VI_NULL,VI_NULL,vi,VI_NULL,VI_NULL);
+	if (tp->t_expr!=0)
+		return;
+	for(i=0;i<SETSIZE;i++)
+		postests[i] |= l_sets[tp->t_set].set_val[i];
+}
+
+struct varinfo *gen_test(from) iocc_t from; {
+	register struct varinfo *vp;
+
+	if (!subset(from.in_set,postests,SETSIZE)) {
+		error("No such test");
+		return(0);
+	}
+	NEW(vp,struct varinfo);
+	vp->vi_int[0] = INSTEST;
+	vp->vi_int[1] = from.in_index;
+	return(vp);
+}
+
+struct varinfo *gen_preturn() {
+	register struct varinfo *vp;
+
+	NEW(vp,struct varinfo);
+	vp->vi_int[0] = INSPRETURN;
+	return(vp);
+}
+
+struct varinfo *gen_tlab(n) {
+	register struct varinfo *vp;
+
+	assert(n>=0 && n<=9);
+	NEW(vp,struct varinfo);
+	vp->vi_int[0] = INSTLAB;
+	vp->vi_int[1] = n;
+	return(vp);
+}
+
+int nstacks;
+c1_t l_stacks[MAXSTACKS];
+set_t ustackset,cstackset;
+
+n_stack(s,e,p,vi) struct varinfo *vi; {
+	register c1_p c1p;
+	register short *sp;
+	register i;
+
+	NEXT(nstacks,MAXSTACKS,"Stacks");
+	c1p= & l_stacks[nstacks-1];
+	c1p->c1_texpno = s;
+	c1p->c1_expr = e;
+	c1p->c1_prop = p;
+	c1p->c1_codep = codeindex;
+	dopattern(0,VI_NULL,VI_NULL,vi,VI_NULL,VI_NULL);
+
+	if (e==0 && p==0)
+		sp = ustackset.set_val;
+	else
+		sp = cstackset.set_val;
+	for(i=0;i<SETSIZE;i++)
+		sp[i] |= l_sets[s].set_val[i];
+}
+
+checkstacking(sp) register short *sp; {
+	register i;
+	register short *chkset;
+	char *warn;
+
+	if (subset(sp,ustackset.set_val,SETSIZE))
+		return;
+	chkset = ustackset.set_val; warn = "";
+	for (i=1;i<nregs;i++)
+		if (BIT(sp,i) && !BIT(chkset,i))
+			error("No %sstacking rule for register %s",warn,
+				l_regs[i].ri_name);
+	for(;i<nregs+MAXTOKENS;i++)
+		if (BIT(sp,i) && !BIT(chkset,i))
+			error("No %sstacking rule for token %s",warn,
+				l_tokens[i-nregs]->tk_name);
+}
+
+int ncoercs;
+c3_t l_coercs[MAXCOERCS];
+set_t unstackset;
+
+/*VARARGS5*/
+
+n_coerc(ti,be,al,ge,rp,in) struct varinfo *al,*ge,*rp; iocc_t in; {
+	register c3_p c3p;
+	register i;
+	register struct varinfo *vi;
+
+	if (ti!=0) {
+		for(i=0,vi=rp;vi!=0;vi=vi->vi_next,i++)
+			;
+		if (i>1) {
+			n_split(ti,be,al,ge,rp,i);
+			return;
+		} else {
+			if (i==0) {
+				error("Coercion should have a result!");
+				return;
+			}
+		}
+	} else {
+		NEW(rp,struct varinfo);
+		rp->vi_next = 0;
+		rp->vi_int[0] = in.in_index;
+	}
+	if (nallreg>1)
+		error("More than 1 register may not be allocated");
+	NEXT(ncoercs,MAXCOERCS,"Coercions");
+	c3p = & l_coercs[ncoercs-1];
+	c3p->c3_texpno = ti;
+	c3p->c3_expr = be;
+	c3p->c3_prop = nallreg==0 ? 0 : allreg[0];
+	c3p->c3_repl = rp->vi_int[0];
+	c3p->c3_codep = codeindex;
+	dopattern(ti==0,VI_NULL,al,ge,rp,VI_NULL);
+	if (ti==0)
+		for(i=0;i<SETSIZE;i++)
+			unstackset.set_val[i] |= in.in_set[i];
+	freevi(rp);
+}
+
+checkunstacking(setno) {
+	register short *sp;
+	register i;
+	short hallset[SETSIZE];
+	
+	sp = l_sets[setno].set_val;
+	for (i=0;i<SETSIZE;i++)
+		hallset[i]=sp[i]&unstackset.set_val[i];
+	nexthall(hallset);
+}
+
+int nsplit,maxsplit;
+c2_t l_split[MAXSPLCOERC];
+
+n_split(ti,be,al,ge,rp,n) struct varinfo *al,*ge,*rp; {
+	register c2_p c2p;
+	register i;
+	register struct varinfo *vi;
+
+	NEXT(nsplit,MAXSPLCOERC,"Splitting coercions");
+	c2p = &l_split[nsplit-1];
+	if (n>MAXSPLIT) {
+		error("Maximum split factor is %d",MAXSPLIT);
+		n = MAXSPLIT;
+	}
+	if (n>maxsplit) maxsplit=n;
+	c2p->c2_texpno = ti;
+	c2p->c2_expr = be;
+	if (nallreg)
+		error("No register uses allowed in splitting coercion");
+	c2p->c2_nsplit = n;
+	for (i=0,vi=rp; i<n; i++,vi=vi->vi_next)
+		c2p->c2_repl[i] = vi->vi_int[0];
+	c2p->c2_codep = codeindex;
+	dopattern(0,VI_NULL,al,ge,rp,VI_NULL);
+}

+ 22 - 0
util/ncgg/cvtkeywords

@@ -0,0 +1,22 @@
+: '$Header$'
+grep '^#' y.tab.h >tokendefs
+ed - keywords <<'!Funky!Stuff!'
+g/^#/d
+1,$s/\([^ 	]*\)[ 	][ 	]*\(.*\)/	sy_p=lookup("\1",symkeyw,newsymbol);sy_p->sy_value.syv_keywno=\2;/
+1i
+#include "lookup.h"
+.
+.r tokendefs
+a
+
+enterkeyw() {
+	register symbol *sy_p;
+
+.
+$a
+}
+.
+w enterkeyw.c
+q
+!Funky!Stuff!
+rm tokendefs

+ 73 - 0
util/ncgg/emlookup.c

@@ -0,0 +1,73 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include "param.h"
+#include "expr.h"
+#include <em_spec.h>
+#include <em_flag.h>
+
+extern char em_mnem[][4];
+
+#define HASHSIZE        (2*(sp_lmnem-sp_fmnem))
+
+struct emhashmnem {
+	char h_name[3];
+	char h_value;
+} emhashmnem[HASHSIZE];
+
+initemhash() {
+	register i;
+
+	for(i=0;i<=sp_lmnem-sp_fmnem;i++)
+		enter(em_mnem[i],i+sp_fmnem);
+}
+
+unsigned emhash(name) register char *name; {
+	register unsigned sum;
+	register i;
+
+	for (sum=i=0;*name;i+=3)
+		sum ^= (*name++)<<(i&07);
+	return(sum);
+}
+
+enter(name,value) char *name; {
+	register unsigned h;
+
+	h=emhash(name)%HASHSIZE;
+	while (emhashmnem[h].h_name[0] != 0)
+		h = (h+1)%HASHSIZE;
+	strncpy(emhashmnem[h].h_name,name,3);
+	emhashmnem[h].h_value = value;
+}
+
+int mlookup(name) char *name; {
+	register unsigned h;
+
+	h = emhash(name)%HASHSIZE;
+	while (strncmp(emhashmnem[h].h_name,name,3) != 0 &&
+	       emhashmnem[h].h_name[0] != 0)
+		h = (h+1)%HASHSIZE;
+	return(emhashmnem[h].h_value&0xFF);      /* 0 if not found */
+}
+
+extern char em_flag[];
+
+argtyp(mn) {
+
+	switch(em_flag[mn-sp_fmnem]&EM_PAR) {
+	case PAR_W:
+	case PAR_S:
+	case PAR_Z:
+	case PAR_O:
+	case PAR_N:
+	case PAR_L:
+	case PAR_F:
+	case PAR_R:
+	case PAR_C:
+		return(TYPINT);
+	default:
+		return(TYPADDR);
+	}
+}

+ 54 - 0
util/ncgg/error.c

@@ -0,0 +1,54 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include <stdio.h>
+
+int nerrors=0;
+
+yyerror(s) char *s; {
+
+	error("Parser gives %s",s);
+}
+
+goodbye() {
+
+	error("This was fatal, goodbye!");
+#ifndef NDEBUG
+	abort();
+#endif
+}
+
+/*VARARGS1*/
+fatal(s,a,b,c,d) char *s; {
+
+	error(s,a,b,c,d);
+	errorexit();
+	goodbye();
+	exit(-1);
+}
+
+/*VARARGS1*/
+error(s,a,b,c,d) char *s; {
+	extern int lineno;
+	extern char *filename;
+
+	fprintf(stderr,"\"%s\", line %d:",filename,lineno);
+	fprintf(stderr,s,a,b,c,d);
+	fprintf(stderr,"\n");
+	nerrors++;
+}
+
+#ifndef NDEBUG
+badassertion(string,file,line) char *string,*file; {
+
+	fprintf(stderr,"\"%s\", line %d: Assertion failed \"%s\"\n",
+		file,line,string);
+	goodbye();
+}
+#endif
+
+tabovf(string) char *string; {
+
+	fatal("%s overflow",string);
+}

+ 311 - 0
util/ncgg/expr.c

@@ -0,0 +1,311 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include "assert.h"
+#include "param.h"
+#include "set.h"
+#include "reg.h"
+#include "lookup.h"
+#include "token.h"
+#include "property.h"
+#include "expr.h"
+#include "regvar.h"
+#include <cgg_cg.h>
+#include "extern.h"
+
+extern set_t l_sets[];
+
+i_expr(e) expr_t e; {
+
+	if (e.ex_typ != TYPINT)
+		error("Expression should be integer");
+	return(e.ex_index);
+}
+
+b_expr(e) expr_t e; {
+	if (e.ex_typ != TYPBOOL)
+		error("Expression should be boolean");
+	return(e.ex_index);
+}
+
+expr_t make_expr(type,operator,op1,op2) {
+	expr_t result;
+
+	result.ex_typ=type;
+	result.ex_index=ex_lookup(operator,op1,op2);
+	return(result);
+}
+
+expr_t regno_expr(regno) {
+	expr_t result;
+	register i;
+
+	result.ex_typ = TYPREG;
+	result.ex_index = ex_lookup(EX_REG,regno,0);
+	for (i=0;i<SZOFSET(MAXREGS);i++)
+		result.ex_regset[i] = 0;
+	BIS(result.ex_regset,regno);
+	return(result);
+}
+
+expr_t ident_expr(name) char *name; {
+	register symbol *sy_p;
+
+	sy_p = lookup(name,symany,mustexist);
+	if (sy_p->sy_type==symconst)
+		return(make_expr(TYPINT,EX_CON,
+			   (int) (sy_p->sy_value.syv_cstval&0xFFFF),
+			   (int) (sy_p->sy_value.syv_cstval>>16)));
+	else if (sy_p->sy_type==symsconst)
+		return(make_expr(TYPADDR,EX_STRING,sy_p->sy_value.syv_stringno,0));
+	else if (sy_p->sy_type!=symreg)
+		error("Wrong type of identifier %s",name);
+	return(regno_expr(sy_p->sy_value.syv_regno));
+}
+
+expr_t subreg_expr(tokarg,subreg) {
+	expr_t result;
+
+	result.ex_typ = TYPREG;
+	subregset(l_sets[tokpatset[tokarg-1]].set_val,subreg,result.ex_regset);
+	result.ex_index = ex_lookup(EX_SUBREG,tokarg,subreg);
+	return(result);
+}
+
+subregset(sp,subreg,regset) register short *sp; register short *regset; {
+	register i;
+	register reginfo *rp;
+
+	for (i=0;i<SZOFSET(MAXREGS);i++)
+		regset[i]=0;
+	for (i=1;i<nregs;i++)	if (BIT(sp,i)) {
+		if(subreg) {
+			rp = &l_regs[i];
+			if (rp->ri_memb[subreg-1]==0)
+				error("Register %s in set has no member %d",
+					rp->ri_name,subreg);
+			BIS(regset,rp->ri_memb[subreg-1]);
+		} else
+			BIS(regset,i);
+	}
+	for(;i<nregs+MAXTOKENS;i++) if(BIT(sp,i))
+		error("Set contains %s, which is not a register",
+			l_tokens[i-nregs]->tk_name);
+}
+
+membset(setno,name,regset,appearance,restyp,typp)
+char *name,*appearance;
+short *regset;
+int *typp;
+{
+	register short *sp;
+	register token_p tp;
+	register i,j,k;
+	int thistyp;
+	int typesdiffer=0;
+	int res_j= -1;
+
+	sp = l_sets[setno].set_val;
+	for (i=1;i<nregs;i++) if (BIT(sp,i)) {
+		error("Set in %s contains %s, which is not a token",
+			appearance,l_regs[i].ri_name);
+		break;
+	}
+	for (i=0;i<SZOFSET(MAXREGS);i++)
+		regset[i] = 0;
+	for (i=nregs;i<nregs+MAXTOKENS;i++) if (BIT(sp,i)) {
+		tp = l_tokens[i-nregs];
+		for(j=0;j<MAXATT &&
+		        (tp->tk_att[j].ta_type == -3 ||
+			 strcmp(tp->tk_att[j].ta_name,name));j++)
+			;
+		if (j==MAXATT)
+			error("Token %s does not contain %s",tp->tk_name,name);
+		else if (j!=res_j && res_j != -1)
+			typesdiffer=1;
+		else {
+			res_j = j;
+			thistyp = tp->tk_att[j].ta_type;
+			if (thistyp== -2) {
+				if (restyp!=TYPADDR && restyp!=0)
+					typesdiffer=1;
+				else
+					restyp=TYPADDR;
+			} else if (thistyp== -1) {
+				if (restyp!=TYPINT && restyp!=0)
+					typesdiffer=1;
+				else
+					restyp=TYPINT;
+			} else {
+				if (restyp!=TYPREG && restyp!=0)
+					typesdiffer=1;
+				else {
+					restyp=TYPREG;
+					for(k=0;k<SZOFSET(MAXREGS);k++)
+						regset[k] |=
+						    l_props[tp->tk_att[j].ta_type].pr_regset[k];
+				}
+			}
+		}
+	}
+	if (typesdiffer)
+		error("%s is not a valid expression; types differ in the set",
+			appearance);
+	*typp = restyp==0 ? TYPINT : restyp;
+	return(res_j == -1 ? 0 : res_j);
+}
+
+expr_t memb_expr(setno,name,appearance,tokarg) char *name,*appearance; {
+	expr_t result;
+	int res_j;
+
+	res_j = membset(setno,name,result.ex_regset,appearance,0,&result.ex_typ);
+	result.ex_index = ex_lookup(EX_TOKFIELD,tokarg,res_j+1);
+	return(result);
+}
+
+expr_t tokm_expr(tokarg,name) char *name; {
+	char app[100];
+
+	sprintf(app,"%%%d.%s",tokarg,name);
+	return(memb_expr(tokpatset[tokarg-1],name,app,tokarg));
+}
+
+expr_t perc_ident_expr(name) char *name; {
+	char app[100];
+
+	sprintf(app,"%%%s",name);
+	return(memb_expr(cursetno,name,app,0));
+}
+
+expr_t all_expr(all_no,subreg) {
+	set_t localset;
+	register i;
+	register short *sp;
+	expr_t result;
+
+	sp = l_props[allreg[all_no]].pr_regset;
+	for (i=0;i<SETSIZE;i++)
+		localset.set_val[i] = i<SZOFSET(MAXREGS) ? sp[i] : 0;
+	subregset(localset.set_val,subreg,result.ex_regset);
+	result.ex_typ = TYPREG;
+	result.ex_index = ex_lookup(EX_ALLREG,all_no+1,subreg);
+	return(result);
+}
+
+eq2expr(e1,e2) expr_t e1,e2; {
+
+	if (e1.ex_typ != e2.ex_typ)
+		error("Expressions around == should have equal type");
+	switch (e1.ex_typ) {
+	default: assert(0);
+	case TYPBOOL:
+		error("== on booleans not implemented");
+	case TYPINT:
+		return(EX_NCPEQ);
+	case TYPADDR:
+		return(EX_SCPEQ);
+	case TYPREG:
+		return(EX_RCPEQ);
+	}
+}
+
+ne2expr(e1,e2) expr_t e1,e2; {
+
+	if (e1.ex_typ != e2.ex_typ)
+		error("Expressions around != should have equal type");
+	switch (e1.ex_typ) {
+	default: assert(0);
+	case TYPBOOL:
+		error("!= on booleans not implemented");
+	case TYPINT:
+		return(EX_NCPNE);
+	case TYPADDR:
+		return(EX_SCPNE);
+	case TYPREG:
+		return(EX_RCPNE);
+	}
+}
+
+expr_t sum_expr(e1,e2) expr_t e1,e2; {
+	int operator,op1,op2;
+	expr_t result;
+
+	operator = EX_CAT; op1 = e1.ex_index; op2 = e2.ex_index;
+	if (e1.ex_typ==e2.ex_typ) {
+		result.ex_typ = e1.ex_typ;
+		if (e1.ex_typ == TYPINT)
+			operator = EX_PLUS;
+		else if (e1.ex_typ != TYPADDR)
+			error("+ is not implemented on this type");
+	} else {
+		result.ex_typ = TYPADDR;
+		if (e1.ex_typ != TYPADDR) {
+			if (e1.ex_typ!=TYPINT)
+				error("Wrong left operand of +");
+			op1 = ex_lookup(EX_TOSTRING,op1,0);
+		}
+		if (e2.ex_typ != TYPADDR) {
+			if (e2.ex_typ!=TYPINT)
+				error("Wrong right operand of +");
+			op2 = ex_lookup(EX_TOSTRING,op2,0);
+		}
+	}
+	result.ex_index=ex_lookup(operator,op1,op2);
+	return(result);
+}
+
+expr_t iextoaddr(e) expr_t e; {
+	expr_t result;
+
+	result.ex_typ = TYPADDR;
+	result.ex_index = ex_lookup(EX_TOSTRING,e.ex_index,0);
+	return(result);
+}
+
+expr_t regvar_expr(e,regtyp) expr_t e; {
+	expr_t result;
+	register i;
+	
+	result = make_expr(TYPREG,EX_REGVAR,i_expr(e),0);
+	for(i=0;i<SZOFSET(MAXREGS);i++)
+		result.ex_regset[i]=0;
+	for(i=0;i<nregvar[regtyp];i++)
+		BIS(result.ex_regset,rvnumbers[regtyp][i]);
+	return(result);
+}
+		
+/*
+ * Node table lookup part
+ */
+
+node_t nodes[MAXNODES];
+int nnodes=0;
+
+initnodes() {
+
+	nodes[0].ex_operator = EX_CON;
+	nodes[0].ex_lnode = 0;
+	nodes[0].ex_rnode = 0;
+	nnodes++;
+}
+
+ex_lookup(operator,lnode,rnode) {
+	register node_p p;
+
+	for(p=nodes+1;p< &nodes[nnodes];p++) {
+		if (p->ex_operator != operator)
+			continue;
+		if (p->ex_lnode != lnode)
+			continue;
+		if (p->ex_rnode != rnode)
+			continue;
+		return(p-nodes);
+	}
+	NEXT(nnodes,MAXNODES,"Node");
+	p->ex_operator = operator;
+	p->ex_lnode = lnode;
+	p->ex_rnode = rnode;
+	return(p-nodes);
+}

+ 155 - 0
util/ncgg/hall.c

@@ -0,0 +1,155 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include "assert.h"
+#include "param.h"
+#include "set.h"
+#include <stdio.h>
+
+/*
+ * This file implements the marriage thesis from Hall.
+ * The thesis says that given a number, say N, of subsets from
+ * a finite set, it is possible to create a set with cardinality N,
+ * that contains one member for each of the subsets,
+ * iff for each number, say M, of subsets from 2 to N the union of
+ * each M-tuple sets has cardinality >= M.
+ *
+ * So what, you might say. As indeed I did.
+ * But this is actually used here to check the possibility of each
+ * code rule. If a code rule has a number of token_sets in the with
+ * clause and a number of properties in the uses rule it must be
+ * possible to do this from an empty fakestack. Hall helps.
+ */
+
+#define MAXHALL (TOKPATMAX+MAXALLREG)
+short hallsets[MAXHALL][SETSIZE];
+int nhallsets= -1;
+int hallfreq[MAXHALL][2];
+
+hallverbose() {
+	register i;
+	register max;
+	
+	fprintf(stderr,"Table of hall frequencies\n   #   pre   post\n");
+	for (max=MAXHALL-1;hallfreq[max][0]==0 && hallfreq[max][1]==0;max--)
+		;
+	for (i=0;i<=max;i++)
+		fprintf(stderr,"%3d%6d%6d\n",i,hallfreq[i][0],hallfreq[i][1]);
+}
+
+inithall() {
+
+	assert(nhallsets == -1);
+	nhallsets=0;
+}
+
+nexthall(sp) register short *sp; {
+	register i;
+	
+	assert(nhallsets>=0);
+	for(i=0;i<SETSIZE;i++)
+		hallsets[nhallsets][i] = sp[i];
+	nhallsets++;
+}
+
+card(sp) register short *sp; {
+	register sum,i;
+	
+	sum=0;
+	for(i=0;i<8*SETSIZE;i++)
+		if (BIT(sp,i))
+			sum++;
+	return(sum);
+}
+
+checkhall() {
+
+	assert(nhallsets>=0);
+	if (!hall())
+		error("Hall says: \"You can't have those registers\"");
+}
+
+hall() {
+	register i,j,k;
+	int ok;
+	
+	hallfreq[nhallsets][0]++;
+	/*
+	 * If a set has cardinality >= nhallsets it can never be the cause
+	 * of the hall algorithm failing. So it can be thrown away.
+	 * But then nhallsets is less, so this step can be re-applied.
+	 */
+
+	do {
+		ok = 0;
+		for(i=0;i<nhallsets;i++)
+			if (card(hallsets[i])>=nhallsets) {
+				for (j=i+1;j<nhallsets;j++)
+					for(k=0;k<SETSIZE;k++)
+						hallsets[j-1][k] =
+							hallsets[j][k];
+				nhallsets--;
+				ok = 1;
+				break;
+			}
+	} while (ok);
+	
+	/*
+	 * Now all sets have cardinality < nhallsets
+	 */
+	
+	hallfreq[nhallsets][1]++;
+	ok=recurhall(nhallsets,hallsets);
+	nhallsets = -1;
+	return(ok);
+}
+
+recurhall(nhallsets,hallsets) short hallsets[][SETSIZE]; {
+	short copysets[MAXHALL][SETSIZE];
+	short setsum[SETSIZE];
+	register i,j,k,ncopys;
+	
+	/*
+	 * First check cardinality of union of all
+	 */
+	for(k=0;k<SETSIZE;k++)
+		setsum[k]=0;
+	for(i=0;i<nhallsets;i++)
+		unite(hallsets[i],setsum);
+	if (card(setsum)<nhallsets)
+		return(0);
+	/*
+	 * Now check the hall property of everything but one set,
+	 * for all sets
+	 */
+	for(i=0;i<nhallsets;i++) {
+		ncopys=0;
+		for(j=0;j<nhallsets;j++) if (j!=i) {
+			for(k=0;k<SETSIZE;k++)
+				copysets[ncopys][k] = hallsets[j][k];
+			ncopys++;
+		}
+		assert(ncopys == nhallsets-1);
+		if (!recurhall(ncopys,copysets))
+			return(0);
+	}
+	return(1);
+}
+
+unite(sp,into) register short *sp,*into; {
+	register i;
+	
+	for(i=0;i<SETSIZE;i++)
+		into[i] |= sp[i];
+}
+
+/*
+ * Limerick (rot13)
+ *
+ * N zngurzngvpvna anzrq Unyy
+ * Unf n urknurqebavpny onyy,
+ * 	Naq gur phor bs vgf jrvtug
+ * 	Gvzrf uvf crpxre'f, cyhf rvtug
+ * Vf uvf cubar ahzore -- tvir uvz n pnyy..
+ */

+ 179 - 0
util/ncgg/instruct.c

@@ -0,0 +1,179 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include "param.h"
+#include "instruct.h"
+#include "pseudo.h"
+#include "varinfo.h"
+#include "set.h"
+#include "expr.h"
+#include "iocc.h"
+#include <cgg_cg.h>
+#include "extern.h"
+
+extern int niops;
+extern iocc_t iops[];
+extern inproc;
+
+extern set_t l_sets[];
+extern inst_t l_instances[];
+
+extern expr_t subreg_expr(),regno_expr();
+
+struct varinfo * setcoco(n) {
+	struct varinfo *vi;
+	
+	NEW(vi,struct varinfo);
+	vi->vi_next = VI_NULL;
+	vi->vi_int[0] = INSSETCC;
+	vi->vi_int[1] = n;
+	return(vi);
+}
+
+struct varinfo * generase(n) {
+	struct varinfo *vi;
+
+	NEW(vi,struct varinfo);
+	vi->vi_next = VI_NULL;
+	vi->vi_int[0] = INSERASE;
+	vi->vi_int[1] = n;
+	return(vi);
+}
+
+onlyreg(argno) {
+	register bitno;
+	register short *sp;
+	
+	sp = l_sets[tokpatset[argno-1]].set_val;
+	for(bitno=nregs;bitno<nregs+ntokens;bitno++)
+		if (BIT(sp,bitno))
+			return(0);
+	return(1);
+}
+
+makescratch(argno) {
+	set_t s;
+
+	if (tokpatro[argno-1])
+		error("Instruction destroys %%%d, not allowed here",argno);
+	s = l_sets[tokpatset[argno-1]];
+	BIC(s.set_val,0);
+	tokpatset[argno-1] = setlookup(s);
+}
+
+struct varinfo *gen_inst(ident,star) char *ident; {
+	register struct varinfo *vi,*retval,*eravi;
+	register instr_p ip;
+	register struct operand *op;
+	register i;
+	register inst_p insta;
+	
+	if (star && !inproc)
+		error("Variable instruction only allowed inside proc");
+	for (ip=l_instr;ip<l_instr+ninstr;ip++) {
+		if(strcmp(ident,ip->i_name))
+			continue;
+		if (ip->i_nops!=niops)
+			continue;
+		for(i=0,op=ip->i_oplist;i<niops;i++,op=op->o_next) {
+			if (!subset(iops[i].in_set,l_sets[op->o_setno].set_val,SETSIZE))
+				goto cont;
+		}
+		goto found;		/* oh well, one more won't hurt */
+	    cont:;
+	}
+	error("Such an \"%s\" does not exist",ident);
+	return(0);
+found:
+	NEW(vi,struct varinfo);
+	vi->vi_int[0] = ip-l_instr;
+	vi->vi_int[1] = star;
+	vi->vi_next=0;
+	retval = vi;
+	for(i=0;i<niops;i++) {
+		NEW(vi->vi_vi,struct varinfo);
+		vi=vi->vi_vi;
+		vi->vi_int[0] = iops[i].in_index;
+	}
+	vi->vi_vi = 0;
+	vi = retval;
+	for(i=0,op=ip->i_oplist;i<niops;i++,op=op->o_next) {
+	    if(op->o_adorn&AD_CC) {
+		vi->vi_next = setcoco(iops[i].in_index);
+		vi=vi->vi_next;
+	    }
+	    switch(op->o_adorn&AD_RWMASK) {
+	    default:
+		/* Nothing possible to do */
+		break;
+	    case AD_RO:
+		/* It might be possible to do something
+		 * here but not now.
+		 */
+		break;
+	    case AD_RW:
+	    case AD_WO:
+		/* Treated the same for now */
+		insta = &l_instances[iops[i].in_index];
+		switch(insta->in_which) {
+		case IN_COPY:
+			if(insta->in_info[1]==0 && !onlyreg(insta->in_info[0]))
+				break;
+			makescratch(insta->in_info[0]);
+			vi->vi_next = generase(
+			               ex_lookup(
+				        EX_SUBREG,insta->in_info[0],
+					          insta->in_info[1]
+				       )
+				      );
+			vi = vi->vi_next;
+			break;
+		case IN_MEMB:
+			vi->vi_next = generase(
+				       ex_lookup(
+				        EX_TOKFIELD,insta->in_info[0],
+					            insta->in_info[1]
+				       )
+				      );
+			vi=vi->vi_next;
+			break;
+		case IN_RIDENT:
+			vi->vi_next = generase(
+				       ex_lookup(
+				        EX_REG,insta->in_info[0],0
+				       )
+				      );
+			vi = vi->vi_next;
+			break;
+		case IN_ALLOC:
+			vi->vi_next = generase(
+				       ex_lookup(
+				        EX_ALLREG,insta->in_info[0]+1,
+						  insta->in_info[1]
+				       )
+				      );
+			vi = vi->vi_next;
+			break;
+		case IN_S_DESCR:
+		case IN_D_DESCR:
+			vi->vi_next = generase(
+				       ex_lookup(
+				        EX_REGVAR,insta->in_info[1],0
+				       )
+				      );
+			vi = vi->vi_next;
+			break;
+		}
+		break;
+	    }
+	}
+	for (eravi=ip->i_erases;eravi != VI_NULL;eravi=eravi->vi_next) {
+		if (eravi->vi_int[0] < 0)
+			vi->vi_next = setcoco(0);
+		else
+			vi->vi_next = generase(eravi->vi_int[0]);
+		vi=vi->vi_next;
+	}
+	return(retval);
+}

+ 187 - 0
util/ncgg/iocc.c

@@ -0,0 +1,187 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include "assert.h"
+#include "param.h"
+#include "set.h"
+#include "expr.h"
+#include "lookup.h"
+#include "token.h"
+#include "property.h"
+#include "iocc.h"
+#include <cgg_cg.h>
+#include "regvar.h"
+#include "extern.h"
+
+extern set_t l_sets[];
+
+int narexpr;
+expr_t arexp[MAXATT];
+
+expr_t iextoaddr();
+
+iocc_t subr_iocc(tokarg,subreg) {
+	inst_t insta;
+	iocc_t  result;
+	register i;
+
+	insta.in_which = IN_COPY;
+	insta.in_info[0] = tokarg;
+	insta.in_info[1] = subreg;
+	result.in_index = instalookup(insta,2);
+	if (subreg==0)
+		for (i=0;i<SETSIZE;i++)
+			result.in_set[i] = l_sets[tokpatset[tokarg-1]].set_val[i];
+	else {
+		for (i=0;i<SETSIZE;i++)
+			result.in_set[i] = 0;
+		subregset(l_sets[tokpatset[tokarg-1]].set_val,subreg,result.in_set);
+	}
+	return(result);
+}
+
+iocc_t tokm_iocc(tokarg,ident) char *ident; {
+	iocc_t result;
+	inst_t insta;
+	register i;
+	char app[100];
+	int dummy;
+	
+	sprintf(app,"%%%d.%s",tokarg,ident);
+	for(i=0;i<SETSIZE;i++)
+		result.in_set[i] = 0;
+	insta.in_which = IN_MEMB;
+	insta.in_info[0] = tokarg;
+	insta.in_info[1] = 1+membset(tokpatset[tokarg-1],ident,result.in_set,
+				    app,TYPREG,&dummy);
+	result.in_index = instalookup(insta,2);
+	return(result);
+}
+	
+iocc_t ident_iocc(ident) char *ident; {
+	iocc_t result;
+	inst_t insta;
+	register i;
+	register symbol *sy_p;
+
+	for(i=0;i<SETSIZE;i++)
+		result.in_set[i] = 0;
+	insta.in_which = IN_RIDENT;
+	sy_p = lookup(ident,symreg,mustexist);
+	insta.in_info[0] = sy_p->sy_value.syv_regno;
+	result.in_index = instalookup(insta,1);
+	BIS(result.in_set,sy_p->sy_value.syv_regno);
+	return(result);
+}
+
+iocc_t all_iocc(all_no,subreg) {
+	iocc_t result;
+	inst_t insta;
+	register i;
+	set_t localset;
+	register short *sp;
+
+	sp = l_props[allreg[all_no]].pr_regset;
+	for (i=0;i<SETSIZE;i++)
+		localset.set_val[i] = i<SZOFSET(MAXREGS) ? sp[i] : 0;
+	for(i=0;i<SETSIZE;i++)
+		result.in_set[i] = 0;
+	insta.in_which = IN_ALLOC;
+	insta.in_info[0] = all_no;
+	insta.in_info[1] = subreg;
+	subregset(localset.set_val,subreg,result.in_set);
+	result.in_index = instalookup(insta,2);
+	return(result);
+}
+
+iocc_t descr_iocc(ident) char *ident; {
+	iocc_t result;
+	inst_t insta;
+	register symbol *sy_p;
+	register token_p tp;
+	register i;
+	int typerr;
+
+	for(i=0;i<SETSIZE;i++)
+		result.in_set[i] = 0;
+	sy_p = lookup(ident,symtok,mustexist);
+	tp = l_tokens[sy_p->sy_value.syv_tokno];
+	BIS(result.in_set,sy_p->sy_value.syv_tokno+nregs);
+	insta.in_which = IN_DESCR;
+	if (rvused&SL_REGVAR && strcmp(ident,"LOCAL")==0)
+		insta.in_which = IN_S_DESCR;
+	else if (rvused&DL_REGVAR && strcmp(ident,"DLOCAL")==0)
+		insta.in_which = IN_D_DESCR;
+	insta.in_info[0] = sy_p->sy_value.syv_tokno;
+	for (i=0;i<MAXATT;i++) {
+		if (tp->tk_att[i].ta_type == -3) {
+			if (narexpr>i)
+				error("token %s initialized with too many attributes",ident);
+			break;
+		}
+		if (i>= narexpr) {
+			error("token %s initialized with too few attributes",
+					ident);
+			break;
+		}
+		typerr = 0;
+		switch(arexp[i].ex_typ) {
+		default: assert(0);
+		case TYPINT:
+			if (tp->tk_att[i].ta_type != -1)
+				if (tp->tk_att[i].ta_type == -2)
+					arexp[i] = iextoaddr(arexp[i]);
+				else
+					typerr++;
+			break;
+		case TYPBOOL:
+			typerr++; break;
+		case TYPADDR:
+			if (tp->tk_att[i].ta_type != -2)
+				typerr++;
+			break;
+		case TYPREG:
+			if (tp->tk_att[i].ta_type<0)
+				typerr++;
+			else if (!subset(arexp[i].ex_regset,
+			           l_props[tp->tk_att[i].ta_type].pr_regset,
+				   SZOFSET(MAXREGS)))
+				typerr++;
+			break;
+		}
+		if (typerr)
+			error("Attribute %s.%s given wrong type of value",
+				ident,tp->tk_att[i].ta_name);
+		insta.in_info[i+1] = arexp[i].ex_index;
+	}
+	result.in_index = instalookup(insta,i+1);
+	return(result);
+}
+
+/* low level instance package */
+
+int ninstances=1;
+inst_t l_instances[MAXINSTANCES];
+
+instalookup(insta,filled) inst_t insta; {
+	register i,j;
+
+	for (j=filled;j<=MAXATT;j++)
+		insta.in_info[j] = 0;
+	for (i=0;i<ninstances;i++) {
+		if (insta.in_which != l_instances[i].in_which)
+			continue;
+		for(j=0;j<=MAXATT;j++)
+			if (insta.in_info[j]!= l_instances[i].in_info[j])
+				goto cont;
+		return(i);
+	    cont:;
+	}
+	NEXT(ninstances,MAXINSTANCES,"Instances");
+	l_instances[i] = insta;
+	return(i);
+}
+
+	
+				

+ 48 - 0
util/ncgg/keywords

@@ -0,0 +1,48 @@
+# $Header$
+#
+ADDR	ADDR
+COERCIONS	COERCIONS
+INSTRUCTIONS	INSTRUCTIONS
+INT	INT
+MOVES	MOVES
+PATTERNS	PATTERNS
+PROPERTIES	PROPERTIES
+REGISTERS	REGISTERS
+SETS	SETS
+SIZEFACTOR	SIZEFACTOR
+STACK	STACK
+STACKINGRULES	STACKINGRULES
+TESTS	TESTS
+TIMEFACTOR	TIMEFACTOR
+TOKENS	TOKENS
+call	CALL
+cost	COST
+defined	DEFINED
+exact	EXACT
+example	EXAMPLE
+from	FROM
+gen	GEN
+highw	HIGHW
+inreg	INREG
+kills	KILLS
+leaving	LEAVING
+loww	LOWW
+move	MOVE
+pat	PAT
+proc	PROC
+reg_any	REG_ANY
+reg_float	REG_FLOAT
+reg_loop	REG_LOOP
+reg_pointer	REG_POINTER
+regvar	REGVAR
+return	RETURN
+reusing	REUSING
+rom	ROM
+samesign	SAMESIGN
+sfit	SFIT
+test	TEST
+to	TO
+ufit	UFIT
+uses	USES
+with	WITH
+yields	YIELDS

+ 65 - 0
util/ncgg/lookup.c

@@ -0,0 +1,65 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include "assert.h"
+#include "param.h"
+#include "lookup.h"
+
+char *myalloc();
+char *mystrcpy();
+
+symbol dumsym;	/* dummy to return in case of error */
+
+symbol *lookup(name,type,style)
+char *name;
+symtype type;
+lookupstyle style;
+{
+	symbol *sy_p,**sy_pp;
+
+	for (sy_pp = &symhash[hashvalue(name)];(sy_p= *sy_pp) != 0;sy_pp= &sy_p->sy_next) {
+		if (strcmp(sy_p->sy_name,name)!=0)
+			continue;
+		switch(style) {
+		default:
+			assert(0);
+		case justlooking:
+		case mustexist:
+		case makeexist:
+			if (type==symany || type==sy_p->sy_type)
+				return(sy_p);
+			continue;
+		case newsymbol:
+			error("%s already defined",name);
+			return(&dumsym);
+		}
+	}
+	switch(style) {
+	default:
+		assert(0);
+	case justlooking:
+		return((symbol *) 0);
+	case mustexist:
+		fatal("%s is unknown symbol",name);
+		/* NOTREACHED */
+	case newsymbol:
+	case makeexist:
+		NEW(sy_p,symbol);
+		sy_p->sy_next = 0;
+		sy_p->sy_name = mystrcpy(name);
+		assert(type!=symany);
+		sy_p->sy_type = type;
+		*sy_pp = sy_p;
+		return(sy_p);
+	}
+}
+
+hashvalue(s) register char *s; {
+	register unsigned sum=0;
+	register i;
+
+	for(i=0;*s;s++,i=(i+3)&07)
+		sum += *s<<i;
+	return(sum%NSYMHASH);
+}

+ 53 - 0
util/ncgg/main.c

@@ -0,0 +1,53 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include <stdio.h>
+
+char *filename;
+
+main(argc,argv) char **argv; {
+	extern int nerrors;
+	extern int code_in_c;
+	extern int tabledebug;
+	extern int verbose;
+
+	while (argc >1 && argv[1][0]=='-') {
+		switch(argv[1][1]) {
+		case 'c':
+			code_in_c = 0;
+			break;
+		case 'd':
+			tabledebug++;
+			break;
+		case 'v':
+			verbose++;
+			break;
+		default:
+			error("Unknown flag -%c",argv[1][1]);
+		}
+		argc--; argv++;
+	}
+	if (argc==2) {
+		if (freopen(argv[1],"r",stdin)==NULL) {
+			error("Can't open %s",argv[1]);
+			exit(-1);
+		}
+		filename = argv[1];
+	} else
+		error("Usage: %s [-c] [-d] [-v] table",argv[0]);
+	initemhash();
+	enterkeyw();
+	initnodes();
+	initio();
+	yyparse();
+	if (nerrors==0) {
+		finishio();
+		statistics();
+		if (verbose)
+			hallverbose();
+	} else {
+		errorexit();
+	}
+	return(nerrors==0 ? 0 : -1);
+}

+ 15 - 0
util/ncgg/makedepend

@@ -0,0 +1,15 @@
+: '$Header$'
+for extension in c y
+do
+    for file in *.$extension
+    do ofile=`basename $file .$extension`.o
+    grep '^# *include.*"' $file|sed "s/.*\"\(.*\)\".*/$ofile:	\1/"
+    done
+done | sort -u >depend
+ed - Makefile <<'!'
+/AUTOAUTOAUTO/+,$d
+$r depend
+w
+q
+!
+rm -f depend

+ 837 - 0
util/ncgg/output.c

@@ -0,0 +1,837 @@
+/* #define CODEDEBUG 	/* print readable code */
+#ifdef CODEDEBUG
+int	code_in_c=0;	/* put readable code in "code" */
+int	tabledebug=1;	/* generate code for table debugging */
+#else
+int	code_in_c=1;	/* put code in "tables.c" */
+int	tabledebug=0;	/* do not generate code for table debugging */
+#endif
+int	verbose=0;	/* print all statistics */
+char	*c_file=	"tables.c";
+char	*h_file=	"tables.H";
+char	*cd_file=	"code";
+
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include "assert.h"
+#include "varinfo.h"
+#include "param.h"
+#include "reg.h"
+#include "property.h"
+#include "token.h"
+#include "set.h"
+#include "instruct.h"
+#include "lookup.h"
+#include <cgg_cg.h>
+#include "pseudo.h"
+#include "regvar.h"
+#include "extern.h"
+
+#define BMASK 0xFF
+#define BSHIFT 8
+
+FILE *ctable,*htable;
+FILE *code;
+short *lineset;
+int maxline;
+
+extern int nstrings;
+extern char *l_strings[];
+
+extern int ninstances;
+extern inst_t l_instances[];
+
+extern int nmoves;
+extern move_t l_moves[];
+extern int ntests;
+extern test_t l_tests[];
+extern int nstacks;
+extern c1_t l_stacks[];
+extern int ncoercs;
+extern c3_t l_coercs[];
+extern int nsplit,maxsplit;
+extern c2_t l_split[];
+extern set_t l_sets[];
+
+int maxallreg=0;
+int maxregvars=0;
+int setsize;
+
+opnfile(f,s) FILE **f; char *s; {
+
+	if ((*f=fopen(s,"w"))==NULL)
+		fatal("Can't create %s",s);
+}
+
+unlfile(f,s) FILE *f; char *s; {
+
+	fclose(f);
+	if (unlink(s)<0)
+		error("%s incorrect, must be removed!!",s);
+}
+
+initio() {
+	extern char *myalloc();
+
+	opnfile(&ctable,c_file);
+	opnfile(&htable,h_file);
+	if (code_in_c)
+		fprintf(ctable,"char coderules[] = {");
+	else
+		opnfile(&code,cd_file);
+	patbyte(0);
+	if (tabledebug)
+		lineset = (short *) myalloc(SZOFSET(MAXSOURCELINES)*sizeof(short));
+}
+
+finishcode() {
+
+	if (code_in_c)
+		fprintf(ctable,"\n};\n\n");
+	if (tabledebug) {
+		int fd;
+		int sz;
+		
+		if ((fd=creat("lineset",0666))>=0) {
+			sz = SZOFSET(maxline)*2;
+			write(fd,&sz,sizeof(int));
+			write(fd,lineset,sz);
+			close(fd);
+		} else
+			error("Can't create lineset");
+	}
+}
+
+errorexit() {
+
+	unlfile(ctable,c_file);
+	unlfile(htable,h_file);
+	if (!code_in_c)
+		unlfile(code,cd_file);
+}
+
+#ifdef CODEDEBUG
+#define code8(x) fprintf(code,"%s","x")
+#define code8nl(x) fprintf(code,"%s\n","x")
+#define code53(x,y) fprintf(code,"%s-%d","x",y)
+#define codeint(x) fprintf(code," %d",x)
+#define codenl() fprintf(code,"\n")
+#else
+code8(x) {
+
+	codeindex++;
+	if (code_in_c)
+		fprintf(ctable,"%d,",x&0377);
+	else
+		putc(x,code);
+}
+
+code8nl(x) {
+
+	code8(x);
+}
+
+code53(x,y) {
+
+	code8(x+(y<<5));
+}
+
+codeint(x) {
+
+	assert(x>=0 && x<=32767);
+	if (x<128) {
+		code8(x);
+	} else {
+		code8(x/256+128);
+		code8(x%256);
+	}
+}
+
+codenl() {
+}
+#endif
+int prevind=0;
+int npatbytes=0;
+char pattern[MAXPATBYTES];
+int pathash[256];
+
+outpatterns() {
+	extern int npatterns;
+	extern int patindex[];
+	extern int empatlen;
+	extern int emmnem[];
+	extern int empatexpr;
+	register i;
+
+	if (!inproc) {
+		patbyte(0);
+		patshort(prevind);
+		prevind = npatbytes-3;
+		patbyte(empatlen);
+		for(i=0;i<empatlen;i++)
+			patbyte(emmnem[i]);
+		pat(empatexpr);
+	}
+	if (callproc==0) {
+		patbyte(npatterns);
+		for(i=0;i<npatterns;i++)
+			pat(patindex[i]);
+	} else {
+		patbyte(0);
+		pat(callproc);
+		pat(procarg[0]);
+		pat(procarg[1]);
+	}
+}
+
+pat(n) {
+
+	assert(n>=0);
+	if (n<128)
+		patbyte(n);
+	else {
+		patbyte(n/256+128);
+		patbyte(n%256);
+	}
+}
+
+patshort(n) {
+
+	patbyte(n%256);
+	patbyte(n/256);
+}
+
+patbyte(n) {
+
+	pattern[npatbytes++]=n;
+}
+
+hashpatterns() {
+	short index;
+	register char *bp,*tp;
+	register short i;
+	unsigned short hashvalue;
+	int patlen;
+
+	index = prevind;
+	while (index != 0) {
+		bp = &pattern[index];
+		tp = &bp[PO_MATCH];
+		i = *tp++&BMASK;
+		if (i==BMASK) {
+			i = *tp++&BMASK;
+			i |= (*tp++&BMASK)<<BSHIFT;
+		}
+		patlen = i;
+		hashvalue = 0;
+		switch(patlen) {
+		default:        /* 3 or more */
+			hashvalue = (hashvalue<<4)^(*tp++&BMASK);
+		case 2:
+			hashvalue = (hashvalue<<4)^(*tp++&BMASK);
+		case 1:
+			hashvalue = (hashvalue<<4)^(*tp++&BMASK);
+		}
+		assert(hashvalue!= ILLHASH);
+		i=index;
+		index = (bp[PO_NEXT]&BMASK)|(bp[PO_NEXT+1]<<BSHIFT);
+		bp[PO_HASH] = hashvalue>>BSHIFT;
+		hashvalue &= BMASK;
+		bp[PO_NEXT] = pathash[hashvalue]&BMASK;
+		bp[PO_NEXT+1] = pathash[hashvalue]>>BSHIFT;
+		pathash[hashvalue] = i;
+	}
+}
+
+outincludes() {
+
+	fprintf(ctable,"#include \"param.h\"\n");
+	fprintf(ctable,"#include \"tables.h\"\n");
+	fprintf(ctable,"#include \"types.h\"\n");
+	fprintf(ctable,"#include <cgg_cg.h>\n");
+	fprintf(ctable,"#include \"data.h\"\n");
+}
+
+outregs() {
+	register i,j,k;
+	short rset[SZOFSET(MAXREGS)];
+	int t,ready;
+
+
+	fprintf(ctable,"char stregclass[] = {\n");
+	for (i=0;i<nregs;i++)
+		fprintf(ctable,"\t%d,\n",l_regs[i].ri_class);
+	fprintf(ctable,"};\n\nstruct reginfo machregs[] = {\n{0},\n");
+	for (i=1;i<nregs;i++) {
+		fprintf(ctable,"{%d,%d",strlookup(l_regs[i].ri_repr),
+			l_regs[i].ri_size);
+		if (maxmembers!=0) {
+			fprintf(ctable,",{");
+			for(j=0;j<2;j++)
+				fprintf(ctable,"%d,",l_regs[i].ri_memb[j]);
+			/* now compute and print set of registers
+			 * that clashes with this register.
+			 * A register clashes with al its children (and theirs)
+			 * and with all their parents.
+			 */
+			for (j=0;j<SZOFSET(MAXREGS);j++)
+				rset[j]=0;
+			BIS(rset,i);
+			do {
+			    ready=1;
+			    for (j=1;j<nregs;j++)
+				if (BIT(rset,j))
+				    for (k=0;k<2;k++)
+					if ((t=l_regs[j].ri_memb[k])!=0) {
+					    if (BIT(rset,t)==0)
+						ready=0;
+					    BIS(rset,t);
+					}
+			} while (!ready);
+			do {
+			    ready=1;
+			    for (j=1;j<nregs;j++)
+				for (k=0;k<2;k++)
+				    if ((t=l_regs[j].ri_memb[k])!=0)
+					if (BIT(rset,t)) {
+						if (BIT(rset,j)==0)
+						    ready=0;
+						BIS(rset,j);
+					}
+			} while (!ready);
+			fprintf(ctable,"},{");
+			for (j=0;j<SZOFSET(nregs);j++)
+				fprintf(ctable,"0%o,",rset[j]&0xFFFF);
+			fprintf(ctable,"}");
+		}
+		fprintf(ctable,",%d",l_regs[i].ri_rregvar>=0);
+		fprintf(ctable,"},\n");
+	}
+	fprintf(ctable,"};\n\n");
+}
+
+outregvars() {
+	register i,j;
+
+	fprintf(htable,"#define REGVARS\n");
+	fprintf(ctable,"#include \"regvar.h\"\n");
+	fprintf(ctable,"int nregvar[4] = { ");
+	for (i=0;i<4;i++) {
+		fprintf(ctable,"%d, ",nregvar[i]);
+		if (nregvar[i]>maxregvars)
+			maxregvars = nregvar[i];
+	}
+	fprintf(ctable,"};\n");
+	for (i=0;i<4;i++)
+		if (nregvar[i]>0)
+			fprintf(ctable,"struct regassigned ratar%d[%d];\n",
+					i,nregvar[i]);
+	for (i=0;i<4;i++) if (nregvar[i]>0) {
+		fprintf(ctable,"int rvtar%d[] = {",i);
+		for (j=0;j<nregvar[i];j++)
+			fprintf(ctable,"%d,",rvnumbers[i][j]);
+		fprintf(ctable,"};\n");
+	}
+	fprintf(ctable,"\nint *rvnumbers[] = {\n");
+	for (i=0;i<4;i++)
+		if (nregvar[i]>0)
+			fprintf(ctable,"\trvtar%d,\n",i);
+		else
+			fprintf(ctable,"\t0,\n");
+	fprintf(ctable,"};\n\nstruct regassigned *regassigned[] = {\n");
+	for (i=0;i<4;i++)
+		if (nregvar[i]>0)
+			fprintf(ctable,"\tratar%d,\n",i);
+		else
+			fprintf(ctable,"\t0,\n");
+	fprintf(ctable,"};\n");
+}
+
+typeconv(n) {
+
+	if (n>=0) return(2);
+	if (n== -1) return(1);
+	if (n== -2) return(3);
+	assert (n== -3);
+	return(0);
+}
+
+outtokens() {
+	register tokno,i;
+	register token_p tp;
+
+	fprintf(ctable,"tkdef_t tokens[] = {{0},\n");
+	for (tokno=1;tokno<ntokens;tokno++) {
+		tp = l_tokens[tokno];
+		fprintf(ctable,"{%d,{%d,%d},{",
+			tp->tk_size, tp->tk_cost.ct_space, tp->tk_cost.ct_time);
+		for(i=0;i<maxtokensize;i++)
+			fprintf(ctable,"%d,",typeconv(tp->tk_att[i].ta_type));
+		fprintf(ctable,"},%d},\n",tp->tk_format);
+	}
+	fprintf(ctable,"{0}};\n\n");
+}
+
+outenodes() {
+	register node_p np;
+	extern node_t nodes[];
+	extern int nnodes;
+
+	fprintf(ctable,"node_t enodes[] = {\n");
+	for (np=nodes;np<&nodes[nnodes];np++)
+		fprintf(ctable,"{%d,%d,%d},\n",
+			np->ex_operator,np->ex_lnode,np->ex_rnode);
+	fprintf(ctable,"};\n\n");
+}
+
+outstrings() {
+	register i;
+	register char *p,c;
+	extern char * filename;
+
+	if (tabledebug)
+		fprintf(ctable,"char *tablename = \"%s\";\n",filename);
+	fprintf(ctable,"string codestrings[] = {\n");
+	for(i=0;i<nstrings;i++) {
+		p= l_strings[i];
+		fprintf(ctable,"\t\"");
+		while ((c= (*p++&0377))!=0)
+			fprintf(ctable, !isascii(c) || iscntrl(c) ? "\\%03o" : "%c",c);
+		fprintf(ctable,"\",\n");
+	}
+	fprintf(ctable,"};\n\n");
+}
+
+outsets() {
+	register i;
+	register set_p sp;
+
+	fprintf(ctable,"set_t machsets[] = {\n");
+	for (sp=l_sets;sp< &l_sets[nsets]; sp++) {
+		fprintf(ctable,"{%3d,{",sp->set_size);
+		for (i=0;i<setsize;i++)
+			fprintf(ctable,"0x%04x,",sp->set_val[i]&0xFFFF);
+		fprintf(ctable,"}},\n");
+	}
+	fprintf(ctable,"};\n\n");
+}
+
+outinstances() {
+	register inst_p ip;
+	register i;
+
+	fprintf(ctable,"inst_t tokeninstances[] = {\n");
+	for (ip=l_instances;ip< &l_instances[ninstances]; ip++) {
+		fprintf(ctable,"{ %d, {",ip->in_which);
+		for(i=0;i<=maxtokensize;i++)
+			fprintf(ctable,"%d,",ip->in_info[i]);
+		fprintf(ctable,"}},\n");
+	}
+	fprintf(ctable,"};\n\n");
+}
+
+outmoves() {
+	register move_p mp;
+
+	fprintf(ctable,"move_t moves[] = {\n");
+	for (mp=l_moves; mp< &l_moves[nmoves]; mp++)
+		fprintf(ctable,"{%d,%d,%d,%d,%d},\n",
+			mp->m_set1, mp->m_expr1,
+			mp->m_set2, mp->m_expr2,
+			mp->m_cindex);
+	fprintf(ctable,"{-1}\n};\n\n");
+}
+
+outtests() {
+	register test_p tp;
+
+	fprintf(ctable,"test_t tests[] = {\n");
+	for (tp=l_tests; tp< &l_tests[ntests]; tp++)
+		fprintf(ctable,"{%d,%d,%d},\n",
+			tp->t_set, tp->t_expr,
+			tp->t_cindex);
+	fprintf(ctable,"{-1}\n};\n\n");
+}
+
+outstacks() {
+	register c1_p cp;
+
+	fprintf(ctable,"c1_t c1coercs[] = {\n");
+	for (cp=l_stacks; cp< &l_stacks[nstacks]; cp++)
+		fprintf(ctable,"{%d,%d,%d,%d},\n",
+			cp->c1_texpno, cp->c1_expr,
+			cp->c1_prop, cp->c1_codep);
+	fprintf(ctable,"{-1}\n};\n\n");
+}
+
+outsplits() {
+	register c2_p cp;
+	register i;
+
+	fprintf(ctable,"c2_t c2coercs[] = {\n");
+	for (cp=l_split; cp< &l_split[nsplit]; cp++) {
+		fprintf(ctable,"{%d,%d,%d,{",
+			cp->c2_texpno, cp->c2_expr, cp->c2_nsplit);
+		for (i=0;i<maxsplit;i++)
+			fprintf(ctable,"%d,",cp->c2_repl[i]);
+		fprintf(ctable,"},%d},\n",cp->c2_codep);
+	}
+	fprintf(ctable,"{-1}\n};\n\n");
+}
+
+outcoercs() {
+	register c3_p cp;
+
+	fprintf(ctable,"c3_t c3coercs[] = {\n");
+	for (cp=l_coercs; cp< &l_coercs[ncoercs]; cp++)
+		fprintf(ctable,"{%d,%d,%d,%d,%d},\n",
+			cp->c3_texpno, cp->c3_expr,
+			cp->c3_prop, cp->c3_repl, cp->c3_codep);
+	fprintf(ctable,"{-1}\n};\n\n");
+}
+
+outproplists() {
+	register propno;
+	register regno;
+
+	for(propno=0;propno<nprops;propno++) {
+		fprintf(ctable,"struct reginfo *rlist%02d[] = {\n",propno);
+		for(regno=1;regno<nregs;regno++)
+			if (BIT(l_props[propno].pr_regset,regno))
+				fprintf(ctable,"&machregs[%d],\n",regno);
+		fprintf(ctable,"0\n};\n");
+	}
+	fprintf(ctable,"struct reginfo **reglist[] = {\n");
+	for(propno=0;propno<nprops;propno++)
+		fprintf(ctable,"rlist%02d,\n",propno);
+	fprintf(ctable,"};\n\n");
+}
+
+outconsts() {
+
+	fprintf(ctable,"unsigned cc1 = %u;\n",fc1);
+	fprintf(ctable,"unsigned cc2 = %u;\n",fc2);
+	fprintf(ctable,"unsigned cc3 = %u;\n",fc3);
+	fprintf(ctable,"unsigned cc4 = %u;\n",fc4);
+}
+
+cdef(s,n) char *s; {
+
+	fprintf(htable,"#define %s %d\n",s,n);
+}
+
+passon(s) char *s; {
+	char buf[32];
+
+	sprintf(buf,"T%s",s);
+	cdef(buf,cmustbeset(s));
+}
+
+outdefs() {
+	register symbol *sy_p;
+	extern int maxempatlen,maxrule;
+	char *wrdfmt;
+
+	passon("EM_WSIZE");
+	passon("EM_PSIZE");
+	passon("EM_BSIZE");
+	if ((sy_p=lookup("FORMAT",symsconst,justlooking))!=0)
+		wrdfmt = l_strings[sy_p->sy_value.syv_stringno];
+	else if (wordsize<=2)
+		wrdfmt = "%d";
+	else
+		wrdfmt = "%ld";
+	fprintf(ctable,"char wrd_fmt[]= \"%s\";\n", wrdfmt);
+	fprintf(htable,"#define WRD_FMT wrd_fmt\n");
+	fprintf(htable,"extern char wrd_fmt[];\n");
+	cdef("MAXALLREG",maxallreg);
+	cdef("SETSIZE",setsize);
+	cdef("NREGS",nregs);
+	cdef("REGSETSIZE",SZOFSET(nregs));
+	cdef("TOKENSIZE",maxtokensize);
+	cdef("MAXMEMBERS",maxmembers);
+	cdef("LONGESTPATTERN",maxempatlen);
+	cdef("MAXRULE",maxrule<16 ? 16 : maxrule);
+	if (nsplit>0) {
+		cdef("MAXSPLIT",maxsplit);
+	}
+	if (tabledebug)
+		cdef("TABLEDEBUG",1);
+}
+
+outars() {
+	register i;
+	
+	if (code_in_c)
+		fprintf(htable,"#define CODEINC 1\n");
+	else {
+		fprintf(ctable,"char coderules[%d];\n",codeindex);
+		fprintf(ctable,"int ncodebytes=%d;\n",codeindex);
+	}
+	fprintf(ctable,"char pattern[%d]={\n",npatbytes);
+	for(i=0;i<npatbytes;i++) {
+		fprintf(ctable,"%d,%c",pattern[i]&BMASK,i%16==15 ? '\n' : ' ');
+	}
+	fprintf(ctable,"};\n\n");
+	fprintf(ctable,"int pathash[256]={\n");
+	for(i=0;i<256;i++) {
+		fprintf(ctable,"%d,%c",pathash[i]&0xFFFF,i%10==9 ? '\n' : ' ');
+	}
+	fprintf(ctable,"};\n");
+}
+
+finishio() {
+	extern int nregs;
+
+	finishcode();
+	hashpatterns();
+	setsize = SZOFSET(nregs+ntokens);
+	outdefs();
+	outincludes();
+	outregs();
+	outtokens();
+	outenodes();
+	outstrings();
+	outsets();
+	outinstances();
+	outmoves();
+	outtests();
+	outstacks();
+	if (nsplit>0)
+		outsplits();
+	outcoercs();
+	outproplists();
+	outconsts();
+	if (rvused)
+		outregvars();
+	outars();
+}
+
+codecoco(cocono) {
+
+	if (cocono== -1)
+		return;
+	code8(DO_SETCC);
+	codeint(cocono);
+	codenl();
+}
+
+dopattern(stackcoerc,kills,allocates,generates,yields,leaving)
+varinfo *kills,*allocates,*generates,*yields,*leaving;
+{
+	register i;
+	int n,nops;
+	register struct varinfo *vp,*vivp;
+	register instr_p instp;
+	int al,deal;
+	int vil;
+	int cocono= -1;
+	cost_t totcost;
+	static char tlab[] = "0:";
+	extern int optexact,optstack,startline;
+	extern char *filename;
+	extern int lineno;
+
+#ifdef CODEDEBUG
+	fprintf(code,"Code(%d) at \"%s\", line %d\n",stackcoerc,filename,lineno);
+#endif
+	if (code_in_c)
+		fprintf(ctable,"\n/* \"%s\", line %d */ ",filename,lineno);
+	if (tabledebug) {
+		code8(DO_DLINE);
+		codeint(startline); 
+		codenl();
+		if (startline<MAXSOURCELINES) {
+			if (startline>maxline)
+				maxline=startline;
+			BIS(lineset,startline);
+		} else {
+			static int beenhere=0;
+
+			if (!beenhere) {
+				beenhere++;
+				error("Too many source lines for table debug");
+			}
+		}
+	}
+	/* MATCH part */
+	if (tokpatlen) {
+		if (optexact)
+			if (optstack)
+				code53(DO_XXMATCH,tokpatlen);
+			else
+				code53(DO_XMATCH,tokpatlen);
+		else
+			code53(DO_MATCH,tokpatlen);
+		for (i=0;i<tokpatlen;i++)
+			codeint(tokpatset[i]);
+		codenl();
+	} else if (stackcoerc)
+		code8nl(DO_COERC);
+	if (optstack) {
+		code53(DO_REMOVE,0);
+		codeint(allsetno);
+		codenl();
+	}
+	/* The kills */
+	for (vp=kills;vp!=0;vp=vp->vi_next) {
+		if (vp->vi_int[1] != 0) {
+			code53(DO_REMOVE,1);
+			codeint(vp->vi_int[0]);
+			codeint(vp->vi_int[1]);
+			codenl();
+		} else {
+			code53(DO_REMOVE,0);
+			codeint(vp->vi_int[0]);
+			codenl();
+		}
+	}
+	/* allocate part */
+	deal=0;al=0;
+	for (vp=allocates;vp!=0;vp=vp->vi_next) {
+		if (vp->vi_int[0] == -1) { /* Deallocate */
+			deal++;
+			code8(DO_DEALLOCATE);
+			codeint(vp->vi_int[1]);
+			codenl();
+		} else {
+			if (vp->vi_int[1]==0) {
+				code53(DO_ALLOCATE,0);
+				codeint(vp->vi_int[0]);
+				codenl();
+			} else {
+				code53(DO_ALLOCATE,1);
+				codeint(vp->vi_int[0]);
+				codeint(vp->vi_int[1]);
+				codenl();
+			}
+			al++;
+		}
+	}
+	if (deal)
+		code8nl(DO_REALLOCATE);
+	if (al>maxallreg)
+		maxallreg=al;
+	totcost.ct_space = 0;
+	totcost.ct_time  = 0;
+	for(vp=generates;vp!=0;vp=vp->vi_next) {
+		n= vp->vi_int[0];
+		switch(n) {
+		default:
+			assert(n>=0);
+			instp = &l_instr[n];
+			nops=instp->i_nops;
+			code53(DO_INSTR,nops);
+			if (vp->vi_int[1]==0) {
+				codeint(instp->i_asname);
+			} else {
+				codeint(10000+vp->vi_int[1]);
+			}
+			vivp=vp->vi_vi;
+			for(i=0;i<nops;i++) {
+				codeint(vivp->vi_int[0]);
+				vivp = vivp->vi_vi;
+			}
+			codenl();
+			totcost.ct_space += instp->i_cost.ct_space;
+			totcost.ct_time  += instp->i_cost.ct_time ;
+			break;
+		case INSMOVE:
+			codecoco(cocono);
+			code8(DO_MOVE);
+			codeint(vp->vi_int[1]);
+			codeint(vp->vi_int[2]);
+			codenl();
+			break;
+		case INSTEST:
+			codecoco(cocono);
+			code8(DO_TEST);
+			codeint(vp->vi_int[1]);
+			codenl();
+			break;
+		case INSPRETURN:
+			code8(DO_PRETURN);
+			codenl();
+			break;
+		case INSTLAB:
+			tlab[0] = vp->vi_int[1] + '0';
+			code53(DO_INSTR,0);
+			codeint(strlookup(tlab));
+			codenl();
+			break;
+		case INSSETCC:
+			cocono=vp->vi_int[1];
+			break;
+		case INSERASE:
+			code8(DO_ERASE);
+			codeint(vp->vi_int[1]);
+			codenl();
+			break;
+		}
+	}
+	codecoco(cocono);
+	vil = vilength(yields);
+	if (vil!=0 || tokpatlen!=0 || allocates!=0) {
+		code53(DO_TOKREPLACE,vilength(yields));
+		for(vp=yields;vp!=0;vp=vp->vi_next) {
+			codeint(vp->vi_int[0]);
+		}
+		codenl();
+	}
+	if (leaving!=0) {
+		code53(DO_EMREPLACE,vilength(leaving));
+		while (leaving!=0) {
+			codeint(leaving->vi_int[0]);
+			codeint(leaving->vi_int[1]);
+			leaving = leaving->vi_next;
+		}
+		codenl();
+	}
+	if (totcost.ct_space!=0 || totcost.ct_time!=0) {
+		code8(DO_COST);
+		codeint(totcost.ct_space);
+		codeint(totcost.ct_time);
+		codenl();
+	}
+	if (empatlen==0 && !inproc)
+		code8nl(DO_RETURN);
+	else
+		code8nl(DO_NEXTEM);
+}
+
+used(resource,use,max) char *resource; {
+
+	if (verbose || 4*use > 3*max)
+		fprintf(stderr,"%s %d(%d)\n",resource,use,max);
+}
+
+statistics() {
+	extern char *end,*sbrk();
+
+	used("Registers",nregs,MAXREGS);
+	used("Properties",nprops,MAXPROPS);
+	used("Tokens",ntokens,MAXTOKENS);
+	used("Tokensize",maxtokensize,MAXATT);
+	used("Sets",nsets,MAXSETS);
+	used("Instructions",ninstr,MAXINSTR);
+	used("Strings",nstrings,MAXSTRINGS);
+	used("Exp-nodes",nnodes,MAXNODES);
+	used("EM-pat length",maxempatlen,EMPATMAX);
+	used("rules/EM-pattern",maxrule,MAXPATTERNS);
+	used("Allocates/rule",maxallreg,MAXALLREG);
+	used("Instances",ninstances,MAXINSTANCES);
+	used("Moves",nmoves,MAXMOVES);
+	used("Tests",ntests,MAXTESTS);
+	used("Stacks",nstacks,MAXSTACKS);
+	used("1->1 Coercions",ncoercs,MAXCOERCS);
+	used("Splitting coercions",nsplit,MAXSPLCOERC);
+	used("Register variables",maxregvars,MAXREGVAR);
+	used("Pat bytes",npatbytes,MAXPATBYTES);
+	if (tabledebug)
+		used("Source lines",maxline,MAXSOURCELINES);
+	fprintf(stderr,"%ldK heap used\n",((long) (sbrk(0)-end+1023))/1024);
+}

+ 99 - 0
util/ncgg/scan.l

@@ -0,0 +1,99 @@
+%{
+#ifndef NORCSID
+static char rcsid2[]= "$Header$";
+#endif
+
+char *mystrcpy();
+int   myatoi();
+
+int lineno=1;
+extern char *filename;
+%}
+
+%%
+"/*"                    { char c;
+                          c = input(); if (c=='\n') lineno++;
+                          do {
+                                while (c!='*') {
+                                        c = input();
+					if (c=='\n') lineno++;
+				}
+                                c = input();
+				if (c=='\n') lineno++;
+                          } while (c!='/');
+                        }
+^\#[ \t]+[0-9]+[ \t]+\".*\"$	{
+			  int ind,ind2;
+			  lineno=atoi(yytext+1)-1;
+			  for(ind=0;yytext[ind]!='"';ind++)
+				;
+			  for(ind2=ind+1;yytext[ind2]!='"';ind2++)
+				;
+			  yytext[ind2]=0;
+			  if (strcmp(yytext+ind+1,filename)!=0)
+				filename=mystrcpy(yytext+ind+1);
+			}
+[a-z]{3}		{ if (!emhere || (yylval.yy_int=mlookup(yytext))==0)
+				REJECT;
+			  return(EMMNEM);
+			}
+
+"=="			return(CMPEQ);
+"!="			return(CMPNE);
+"<"			return(CMPLT);
+"<="			return(CMPLE);
+">"			return(CMPGT);
+">="			return(CMPGE);
+"||"			return(OR2);
+"&&"			return(AND2);
+"<<"			return(LSHIFT);
+">>"			return(RSHIFT);
+"!"			return(NOT);
+"~"			return(COMP); 
+":ro"			{ yylval.yy_int = AD_RO; return(ADORNACCESS);  }
+":wo"			{ yylval.yy_int = AD_WO; return(ADORNACCESS);  }
+":rw"			{ yylval.yy_int = AD_RW; return(ADORNACCESS);  }
+":cc"			{ yylval.yy_int = AD_CC; return(ADORNCC);  }
+\$[0-9]+		{ yylval.yy_int = atoi(yytext+1); return(DOLLAR); }
+\%[0-9]+		{ yylval.yy_int = atoi(yytext+1); return(PERCENT); }
+\%[a-z]			{ yylval.yy_int = yytext[1]-'a'; return(ALLREG); }
+[0-9]+|0x[0-9A-Fa-f]+	{ yylval.yy_int = myatoi(yytext); return(NUMBER); }
+[_A-Za-z][_A-Za-z0-9]*	{ register symbol *sy_p;
+    			  if ((sy_p=lookup(yytext,symkeyw,justlooking))!=0)
+				 return(sy_p->sy_value.syv_keywno); 
+			  yylval.yy_str = mystrcpy(yytext); return(IDENT);
+			}
+\%[_A-Za-z][_A-Za-z0-9]* { yylval.yy_str = mystrcpy(yytext+1);
+			   return(PERC_IDENT);
+			 }
+\"[^"\n]*\"		{ yytext[yyleng-1]=0;
+			  yylval.yy_str = mystrcpy(yytext+1);
+			  return(STRING);
+			}
+[0-9][bf]		{ yytext[2]=0;
+			  yylval.yy_str = mystrcpy(yytext);
+			  return(STRING);
+			}
+\n			{ lineno++; }
+[ \t]*			;
+.			return(yytext[0]);
+%%
+int skipping=0;
+
+yywrap() {
+
+	if (skipping)
+		fatal("EOF reached during error recovery");
+	return(1);
+}
+
+skipupto(tok,str) char *str; {
+	register i; 
+
+	skipping=1; 
+	while (yylex()!=tok)
+		;
+	for(i=strlen(str); i>0; i--)
+		unput(str[i-1]);
+	skipping=0; 
+}

+ 118 - 0
util/ncgg/set.c

@@ -0,0 +1,118 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include "param.h"
+#include "property.h"
+#include "set.h"
+#include "token.h"
+#include "lookup.h"
+#include <cgg_cg.h>
+#include "extern.h"
+
+extern set_t l_sets[];
+
+setlookup(s) set_t s; {
+	register set_p p;
+	register i;
+	int setno;
+
+	for(p=l_sets;p<&l_sets[nsets];p++) {
+		if (p->set_size != s.set_size)
+			continue;
+		for (i=0;i<SETSIZE;i++)
+			if (p->set_val[i] != s.set_val[i])
+				goto cont;
+		return(p-l_sets);
+	    cont:;
+	}
+	setno = NEXT(nsets,MAXSETS,"Sets");
+	l_sets[setno] = s;
+	return(setno);
+}
+
+make_std_sets() {
+	set_t s;
+	register i;
+
+	for(i=0;i<SETSIZE;i++)
+		s.set_val[i]=0;
+	for(i=0;i<nregs+ntokens;i++)
+		BIS(s.set_val,i);
+	s.set_size = 0;
+	allsetno = setlookup(s);
+	n_set("ALL",allsetno);
+}
+
+set_t emptyset;
+
+set_t ident_to_set(name) char *name; {
+	register symbol *sy_p;
+	register i;
+	register struct propinfo *pp;
+	int bitno;
+	set_t result;
+
+	sy_p = lookup(name,symany,mustexist);
+	switch(sy_p->sy_type) {
+	default:
+		error("%s is wrong kind of symbol",name);
+		return(emptyset);
+	case symprop:
+		pp = &l_props[sy_p->sy_value.syv_propno];
+		result.set_size = pp->pr_size;
+		for (i=0;i<SZOFSET(MAXREGS);i++)
+			result.set_val[i] = pp->pr_regset[i];
+		BIS(result.set_val,0);
+		for (;i<SETSIZE;i++)
+			result.set_val[i] = 0;
+		break;
+	case symtok:
+		bitno = sy_p->sy_value.syv_tokno+nregs;
+		for (i=0;i<SETSIZE;i++)
+			result.set_val[i] = 0;
+		BIS(result.set_val,bitno);
+		result.set_size = l_tokens[sy_p->sy_value.syv_tokno]->tk_size;
+		break;
+	case symset:
+		return(l_sets[sy_p->sy_value.syv_setno]);
+	}
+	return(result);
+}
+
+set_t setproduct(s1,s2) set_t s1,s2; {
+	set_t result;
+	register i;
+
+	if ((result.set_size=s1.set_size)==0)
+		result.set_size = s2.set_size;
+	for(i=0;i<SETSIZE;i++)
+		result.set_val[i] = s1.set_val[i] & s2.set_val[i];
+	return(result);
+}
+
+set_t setsum(s1,s2) set_t s1,s2; {
+	set_t result;
+	register i;
+
+	if (s1.set_size == s2.set_size)
+		result.set_size = s1.set_size;
+	else
+		result.set_size = 0;
+	for(i=0;i<SETSIZE;i++)
+		result.set_val[i] = s1.set_val[i] | s2.set_val[i];
+	return(result);
+}
+
+set_t setdiff(s1,s2) set_t s1,s2; {
+	set_t result;
+	register i;
+
+	if (s1.set_size == s2.set_size)
+		result.set_size = s1.set_size;
+	else
+		result.set_size = 0;
+	for(i=0;i<SETSIZE;i++)
+		result.set_val[i] = s1.set_val[i] & ~ s2.set_val[i];
+	return(result);
+}

+ 20 - 0
util/ncgg/strlookup.c

@@ -0,0 +1,20 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include "param.h"
+
+int nstrings=0;
+char *l_strings[MAXSTRINGS];
+
+strlookup(str) char *str; {
+	register i;
+	extern char *mystrcpy();
+
+	for(i=0;i<nstrings;i++)
+		if (strcmp(str,l_strings[i])==0)
+			return(i);
+	NEXT(nstrings,MAXSTRINGS,"String table");
+	l_strings[i] = mystrcpy(str);
+	return(i);
+}

+ 382 - 0
util/ncgg/subr.c

@@ -0,0 +1,382 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include "param.h"
+#include "reg.h"
+#include "lookup.h"
+#include "property.h"
+#include "expr.h"
+#include "set.h"
+#include "varinfo.h"
+#include "instruct.h"
+#include "token.h"
+#include "regvar.h"
+#include <cgg_cg.h>
+#include "extern.h"
+
+n_proc(name) char *name; {
+	register symbol *sy_p;
+	extern int npatbytes;
+
+	sy_p = lookup(name,symproc,newsymbol);
+	sy_p->sy_value.syv_procoff = npatbytes;
+}
+
+struct varinfo *
+make_erase(name) char *name; {
+	expr_t e,ident_expr();
+	struct varinfo *result;
+
+	e = ident_expr(name);
+	if (e.ex_typ != TYPREG)
+		error("Register name required here");
+	NEW(result,struct varinfo);
+	result->vi_next = VI_NULL;
+	result->vi_int[0] = e.ex_index;
+	return(result);
+}
+
+n_instr(name,asname,oplist,eraselist,cost)
+char *name,*asname;
+operand *oplist;
+struct varinfo *eraselist,*cost;
+{
+	register instrno;
+	register cc_count;
+	register instr_p ip;
+
+	instrno = NEXT(ninstr,MAXINSTR,"Instructions");
+	ip = &l_instr[instrno];
+	ip->i_name = name;
+	ip->i_asname = strlookup(asname!=0 ? asname : name);
+	ip->i_nops = 0;
+	ip->i_oplist = oplist;
+	ip->i_erases = eraselist;
+	if (cost==0) {
+		ip->i_cost.ct_space = 0;
+		ip->i_cost.ct_time = 0;
+	} else {
+		ip->i_cost.ct_space = cost->vi_int[0];
+		ip->i_cost.ct_space = cost->vi_int[1];
+	}
+	for (cc_count=0; oplist!=0; oplist = oplist->o_next) {
+		ip->i_nops++;
+		if(oplist->o_adorn&AD_CC)
+			cc_count++;
+	}
+	while (eraselist!=VI_NULL) {
+		if (eraselist->vi_int[0] == -1 && cc_count)
+			error("Instruction can't both set and break the condition codes");
+		eraselist=eraselist->vi_next;
+	}
+	if (cc_count>1)
+		error("No instruction can set condition codes more than once");
+}
+
+n_set(name,number) char *name; {
+	register symbol *sy_p;
+
+	sy_p = lookup(name,symset,newsymbol);
+	sy_p->sy_value.syv_setno = number;
+}
+
+n_tok(name,atts,size,cost,format)
+char *name;
+struct varinfo *atts,*cost,*format;
+{
+	register symbol *sy_p;
+	register token_p tp;
+	register struct varinfo *vip;
+	int i;
+	int tokno;
+	char formstr[50],smallstr[2];
+
+	sy_p = lookup(name,symtok,newsymbol);
+	NEW(tp,token_t);
+	tokno = NEXT(ntokens,MAXTOKENS,"Tokens");
+	sy_p->sy_value.syv_tokno = tokno;
+	l_tokens[tokno] = tp;
+	tp->tk_name = sy_p->sy_name;
+	tp->tk_size = size;
+	if (cost != 0) {
+		tp->tk_cost.ct_space = cost->vi_int[0];
+		tp->tk_cost.ct_time  = cost->vi_int[1];
+	} else {
+		tp->tk_cost.ct_space = 0;
+		tp->tk_cost.ct_time  = 0;
+	}
+	for(i=0,vip=atts;i<MAXATT && vip!=0;i++,vip=vip->vi_next) {
+		tp->tk_att[i].ta_type = vip->vi_int[0];
+		tp->tk_att[i].ta_name = vip->vi_str[0];
+		vip->vi_str[0]=0;
+	}
+	if (i>maxtokensize)
+		maxtokensize=i;
+	if (vip!=0)
+		error("More then %d attributes, rest discarded",MAXATT);
+	for(;i<MAXATT;i++)
+		tp->tk_att[i].ta_type= -3;
+	if (format!=0) {
+		formstr[0] = 0;
+		for (vip=format;vip!=0;vip=vip->vi_next) {
+			if (vip->vi_int[0]==0)
+				strcat(formstr,vip->vi_str[0]);
+			else {
+				for(i=0;i<MAXATT;i++) {
+					if (strcmp(vip->vi_str[0],tp->tk_att[i].ta_name)==0) {
+						smallstr[0] = i+1;
+						smallstr[1] = 0;
+						strcat(formstr,smallstr);
+						break;
+					}
+				}
+				if (i==MAXATT)
+					error("%s not a known attribute",
+						vip->vi_str[0]);
+			}
+		}
+		tp->tk_format = strlookup(formstr);
+	} else
+		tp->tk_format = -1;
+}
+
+checkprintformat(n) {
+	register short *s;
+	register i;
+	extern set_t l_sets[];
+	
+	s= l_sets[n].set_val;
+	for(i=nregs;i<nregs+ntokens;i++)
+		if (BIT(s,i) && l_tokens[i-nregs]->tk_format<0)
+			error("Token %s in set does not have printformat",
+				l_tokens[i-nregs]->tk_name);
+}
+
+n_prop(name,size) char *name; int size; {
+	int propno;
+	register symbol *sp;
+
+	propno = NEXT(nprops,MAXPROPS,"Properties");
+	sp = lookup(name,symprop,newsymbol);
+	sp->sy_value.syv_propno = propno;
+	if (size <= 0) {
+		error("Size of property must be >0");
+		size = wordsize;
+	}
+	l_props[propno].pr_size = size;
+}
+
+prophall(n) {
+	register i;
+	short hallset[SETSIZE];
+	
+	for(i=0;i<SETSIZE;i++)
+		hallset[i] = i<SZOFSET(MAXREGS) ? l_props[n].pr_regset[i] : 0;
+	nexthall(hallset);
+}
+
+n_reg(name,printstring,nmemb,member1,member2) char *name,*printstring; {
+	register symbol *sy_p;
+	register reginfo *ri_p;
+	int regno;
+
+	sy_p = lookup(name,symreg,newsymbol);
+	sy_p->sy_value.syv_regno = regno = NEXT(nregs,MAXREGS,"Number of registers");
+	ri_p = &l_regs[regno];
+	ri_p->ri_name = mystrcpy(name);
+	ri_p->ri_repr = printstring!=0 ? mystrcpy(printstring) : ri_p->ri_name;
+	ri_p->ri_memb[0] = member1;
+	ri_p->ri_memb[1] = member2;
+	if (nmemb>maxmembers)
+		maxmembers=nmemb;
+	return(regno);
+}
+
+make_const() {
+
+	wordsize = cmustbeset("EM_WSIZE");
+	pointersize = cmustbeset("EM_PSIZE");
+}
+
+cmustbeset(ident) char *ident; {
+
+	return(lookup(ident,symconst,mustexist)->sy_value.syv_cstval);
+}
+
+n_const(ident,val) char *ident; {
+	register symbol *sy_p;
+
+	sy_p = lookup(ident,symconst,newsymbol);
+	sy_p->sy_value.syv_cstval = val;
+}
+
+n_sconst(ident,val) char *ident,*val; {
+	register symbol *sy_p;
+
+	sy_p = lookup(ident,symsconst,newsymbol);
+	sy_p->sy_value.syv_stringno = strlookup(val);
+}
+
+regline(rl,pl,rv) varinfo *rl,*pl; {
+	register varinfo *rrl,*rpl;
+	register short *sp;
+	register reginfo *regp;
+	int thissize;
+	int propno;
+
+	for(rrl=rl;rrl!=0;rrl=rrl->vi_next) {
+		regp = &l_regs[rrl->vi_int[0]];
+		thissize = 0;
+		for(rpl=pl;rpl!=0;rpl=rpl->vi_next) {
+			propno = rpl->vi_int[0];
+			sp= l_props[propno].pr_regset;
+			BIS(sp,rrl->vi_int[0]);
+			if (thissize==0)
+				thissize = l_props[propno].pr_size;
+			else if (thissize!=-1 && thissize!=l_props[propno].pr_size)
+				error("Register %s has no clear size",
+					regp->ri_name);
+		}
+		regp->ri_size = thissize;
+		regp->ri_class = regclass;
+		regp->ri_rregvar = rv;
+		if (rv>=0) {
+			if (regp->ri_memb[0]!=0)
+				error("Register variables may not have subregisters");
+			rvused |= ANY_REGVAR;
+			if (regp->ri_size == wordsize)
+				rvused |= SL_REGVAR;
+			else if (regp->ri_size == 2*wordsize)
+				rvused |= DL_REGVAR;
+			if (nregvar[rv]==0)
+				rvsize[rv] = regp->ri_size;
+			else if (rvsize[rv]!=regp->ri_size)
+				error("All register variables of one type must have the same size");
+			NEXT(nregvar[rv],MAXREGVAR,"Register variable");
+			rvnumbers[rv][nregvar[rv]-1] = rrl->vi_int[0];
+		}
+	}
+	regclass++;
+}
+
+setallreg(vi) struct varinfo *vi; {
+
+	nallreg=0;
+	for(;vi!=0;vi=vi->vi_next) {
+		if (vi->vi_int[0]<0)
+			continue;
+		allreg[nallreg++] = vi->vi_int[0];
+	}
+}
+
+freevi(vip) register struct varinfo *vip; {
+	register i;
+	extern char *end;
+
+	if (vip==0)
+		return;
+	freevi(vip->vi_next);
+	freevi(vip->vi_vi);
+	for (i=0;i<VI_NSTR;i++)
+		if (vip->vi_str[i]>end)
+			free((char *) vip->vi_str[i]);
+	free(vip);
+}
+
+int myatoi(s) register char *s; {
+	register int base=10;
+	register sum=0;
+
+	if (*s=='0') {
+		base = 8;
+		s++;
+		if (*s=='x') {
+			base=16;
+			s++;
+		}
+	}
+	for (;;) {
+		switch (*s) {
+		default:	return(sum);
+		case '8':
+		case '9':
+			if (base==8) error("Bad digit in octal number");
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+			sum = sum*base + *s++ - '0';
+			break;
+		case 'a':
+		case 'b':
+		case 'c':
+		case 'd':
+		case 'e':
+		case 'f':
+			if (base!=16) error("Hexletter in number not expected");
+			sum = sum*base + *s++ - 'a';
+			break;
+		case 'A':
+		case 'B':
+		case 'C':
+		case 'D':
+		case 'E':
+		case 'F':
+			if (base!=16) error("Hexletter in number not expected");
+			sum = sum*base + *s++ - 'A';
+			break;
+		}
+	}
+}
+
+char *mystrcpy(s) char *s; {
+	register char *p;
+	char *myalloc();
+
+	p=myalloc(strlen(s)+1);
+	strcpy(p,s);
+	return(p);
+}
+
+char *myalloc(n) register n; {
+	register char *p,*result;
+	char *malloc();
+
+	result=p=malloc(n);
+	if (p== (char *) 0)
+		fatal("Out of memory");
+	do *p++=0; while (--n);
+	return(result);
+}
+
+chkincl(value,lwb,upb) {
+
+	if (value<lwb || value>upb)
+		error("Number %d should have been between %d and %d",
+			value,lwb,upb);
+	return(value);
+}
+
+subset(sp1,sp2,setsize) short *sp1,*sp2; {
+	register i;
+
+	for(i=0;i<setsize;i++)
+		if ( (sp1[i] | sp2[i]) != sp2[i])
+			return(0);
+	return(1);
+}
+
+vilength(vip) register struct varinfo *vip; {
+	register l=0;
+
+	while(vip!=0) {
+		vip=vip->vi_next;
+		l++;
+	}
+	return(l);
+}

+ 45 - 0
util/ncgg/var.c

@@ -0,0 +1,45 @@
+#ifndef NORCSID
+static char rcsid[]= "$Header$";
+#endif
+
+#include "param.h"
+#include "reg.h"
+#include "property.h"
+#include "token.h"
+#include "set.h"
+#include "instruct.h"
+#include "lookup.h"
+#include <cgg_cg.h>
+
+int wordsize;
+int pointersize;
+int nregs=1;
+int nprops;
+int ntokens=1;
+int nsets;
+int ninstr;
+int codeindex;
+int empatlen,emmnem[EMPATMAX];
+int empatexpr;
+int tokpatlen,tokpatset[TOKPATMAX],tokpatro[TOKPATMAX];
+int nallreg,allreg[MAXALLREG];
+int cursetno;
+int allsetno;
+int inproc=0;	/* scanning "procedure" */
+int callproc=0;
+int procarg[2];
+int fc1=1,fc2=1,fc3=1,fc4=1;
+int maxmembers=0;
+int regclass=1;
+int maxtokensize=0;
+int rvused=0;
+int nregvar[4];
+int rvsize[4];
+int rvnumbers[4][MAXREGVAR];
+
+reginfo l_regs[MAXREGS];
+propinfo l_props[MAXPROPS];
+token_p l_tokens[MAXTOKENS];
+set_t l_sets[MAXSETS];
+instr_t l_instr[MAXINSTR];
+symbol *symhash[NSYMHASH];