Subject: C compiler mishandles 'u_long op= long' +FIX (#194)
Index:	lib/ccom/optable,c10.c,c13.c 2.11BSD

Description:
	Some operations using 'unsigned long' cause the compiler to fail
	with a "no code table" error.  The operations which exhibit this
	behaviour are all of the assignment form:

			u_long *= long;
			u_long /= long;

			and so on.

	Also, in some cases the operator is not correctly identified in
	the error message.  The compiler is parsing the program correctly
	but does not know how to generate code for the specified operation.

Repeat-By:
	Attempt to compile the following test program:

	======start
	unsigned long y;
	long	x;
main()
	{

	y /= x;
	x /= y;
	}
	======end

	If something of the form:

Script started on Wed Oct  5 13:55:37 1994
sms.1% cc -S t.c
7: No code table for op 125
8: No code table for op: /=(87) type: 6
sms.2% exit
script done on Wed Oct  5 13:55:54 1994

	is the result then the bug is present and the patch below should
	be applied.

	Note the lack of identifying operator name in the first message.
	Op 125 is the /= operator for u_long being on the left side of an 
	expression.

Fix:
	Save the following patch to a file - /tmp/p.  Then:

	0) SAVE the existing compiler - save /lib/{c0,c1} somewhere or make
	   sure you have them on known good backups.
	1) cd /usr/src/lib/ccom
	2) patch < /tmp/p
	3) make
	4) make install
	5) make clean
	6) make
	7) make install

	The extra steps make sure that the compiler is able to rebuild itself
	(probably not necessary but ...)
	
	The changes to 'c13.c' are cosmetic.  Numbered comments were placed
	in several of the lengthy tables to make it easy to find a particular
	entry.  A number of entries in the operator name tables were filled
	in or corrected.  These are useful when debugging the compiler.

	The main fix is in 'optable'  a couple of rules were added in 
	'cr124' and 'cr86' to handle unsigned longs.  These were overlooked
	when I added the 'u_long' capability last year.  Apparently
	nothing in the rest of the system uses the assignment ops when 
	dealing with unsigned longs otherwise the bug would have shown up
	during the top level make of the system.

	The other problem, that of omitting the operator string, was due to
	new operators being added but the range check not being extended in
	c10.c.  At the same time an available register variable was used 
	in the error handling instead of making repeated structure pointer 
	dereferences (it also shortened the lines and improved readability).

	A version header (ifdef'd out sccsid string) was added to the three
	affected modules.

	The generated code for the test program should look like this (create
	the .s file with "cc -S t.c"):

		.comm	_y,4
		.comm	_x,4
		.globl	_main
		.text
		_main:
		~~main:
		jsr	r5,csv
		jbr	L1
		L2:mov	2+_x,-(sp)
		mov	_x,-(sp)
		mov	$_y,-(sp)
		jsr	pc,ualdiv
		add	$6,sp
		mov	2+_y,-(sp)
		mov	_y,-(sp)
		mov	$_x,-(sp)
		jsr	pc,aldiv
		add	$6,sp
		L3:jmp	cret
		L1:jbr	L2
		.globl
		.data

	Updates to 2.11BSD are available via anonymous FTP to 
	ftp.iipo.gtegsc.com - look in the directory /pub/2.11BSD.

=============cut here
*** /usr/src/lib/ccom/optable.old	Sat Jul  3 21:34:31 1993
--- /usr/src/lib/ccom/optable	Tue Oct  4 21:17:05 1994
***************
*** 2,7 ****
--- 2,10 ----
  /*
   * c code tables-- compile to register
   */
+ #if	!defined(lint) && defined(DOSCCS)
+ static	char	sccsid[] = "@(#)optable	2.1 (2.11BSD GTE) 10/4/94";
+ #endif
  
  struct table regtab[] = {
  	{106,cr106},
***************
*** 712,718 ****
  	mov	#1+2(R),R+
  	mov	#1(R),R
  
! /* =*, =<< (for integer multiply, R must be odd) */
  cr72:
  %a,aw
  %ad,ad
--- 715,721 ----
  	mov	#1+2(R),R+
  	mov	#1(R),R
  
! /* *=, <<= (for integer multiply, R must be odd) */
  cr72:
  %a,aw
  %ad,ad
***************
*** 1163,1178 ****
  %nul,nul
  %	[l82]
  
! /* =*, =/, =rem for unsigned long */
  cr124:
! %n,nul
  %	[l86]
  
! /* =*, =/, =rem for longs */
  /* Operands of the form &x op y, so stack space is known. */
  cr86:
  %[l86:]
  %n,nl
  	SS
  	FS
  	jsr	pc,I
--- 1166,1183 ----
  %nul,nul
  %	[l82]
  
! /* *=, /=, %= for unsigned long */
  cr124:
! %n,nl
! %nl,n
  %	[l86]
  
! /* *=, /=, %= for longs */
  /* Operands of the form &x op y, so stack space is known. */
  cr86:
  %[l86:]
  %n,nl
+ %n,nul
  	SS
  	FS
  	jsr	pc,I
*** /usr/src/lib/ccom/c10.c.old	Sat Jul  3 21:34:10 1993
--- /usr/src/lib/ccom/c10.c	Tue Oct  4 21:15:59 1994
***************
*** 1,7 ****
  /*
! 		C compiler, part 2
  */
  
  #include "c1.h"
  
  #ifdef	DEBUG
--- 1,11 ----
  /*
!  *		C compiler, part 2
  */
  
+ #if	!defined(lint) && defined(DOSCCS)
+ static	char	sccsid[] = "@(#)c10.c	2.1 (2.11BSD GTE) 10/4/94";
+ #endif
+ 
  #include "c1.h"
  
  #ifdef	DEBUG
***************
*** 9,16 ****
  #else
  #define	dbprint(op)	/* */
  #endif
- int debug;
  
  char	maprel[] = {	EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ,
  			LESS, GREATQP, GREATP, LESSEQP, LESSP
  };
--- 13,21 ----
  #else
  #define	dbprint(op)	/* */
  #endif
  
+ static int debug = 0;
+ 
  char	maprel[] = {	EQUAL, NEQUAL, GREATEQ, GREAT, LESSEQ,
  			LESS, GREATQP, GREATP, LESSEQP, LESSP
  };
***************
*** 432,443 ****
  			goto fixup;
  		}
  	}
  	if (tree->t.type == STRUCT)
  		error("Illegal operation on structure");
! 	else if (tree->t.op>0 && tree->t.op<RFORCE && opntab[tree->t.op])
! 		error("No code table for op: %s(%d) type: %d", opntab[tree->t.op],tree->t.op,tree->t.type);
  	else
! 		error("No code table for op %d", tree->t.op);
  	return(reg);
  }
  
--- 437,451 ----
  			goto fixup;
  		}
  	}
+ 
+ 	r = tree->t.op;
  	if (tree->t.type == STRUCT)
  		error("Illegal operation on structure");
! 	else if (r > 0 && r < UASLSHL && opntab[r])
! 		error("No code table for op: %s(%d) type: %d", opntab[r], r,
! 			tree->t.type);
  	else
! 		error("No code table for op %d", r);
  	return(reg);
  }
  
*** /usr/src/lib/ccom/c13.c.old	Sat Jul  3 21:34:22 1993
--- /usr/src/lib/ccom/c13.c	Tue Oct  4 21:16:32 1994
***************
*** 1,12 ****
  /*
   * C second pass -- tables
   */
  #include "c1.h"
  /*
   * Operator dope table-- see description in c0.
   */
  int opdope[] = {
! 	000000,	/* EOFC */
  	000000,	/* ; */
  	000000,	/* { */
  	000000,	/* } */
--- 1,17 ----
  /*
   * C second pass -- tables
   */
+ 
+ #if	!defined(lint) && defined(DOSCCS)
+ static	char	sccsid[] = "@(#)c13.c	2.1 (2.11BSD GTE) 10/4/94";
+ #endif
+ 
  #include "c1.h"
  /*
   * Operator dope table-- see description in c0.
   */
  int opdope[] = {
! 	000000,	/* EOFC (0) */
  	000000,	/* ; */
  	000000,	/* { */
  	000000,	/* } */
***************
*** 16,22 ****
  	002000,	/* ) */
  	014201,	/* : */
  	007001,	/* , */
! 	000000,	/* field selection */
  	000000,	/* reverse field selection */
  	000001,	/* temporary field selection */
  	000001,	/* int->ptr */
--- 21,27 ----
  	002000,	/* ) */
  	014201,	/* : */
  	007001,	/* , */
! 	000000,	/* field selection (10) */
  	000000,	/* reverse field selection */
  	000001,	/* temporary field selection */
  	000001,	/* int->ptr */
***************
*** 25,42 ****
  	000001,	/* field assignment */
  	000001,	/* >> unsigned */
  	000001,	/* >>= unsigned */
! 	000000,	/* 19 */
! 	000400,	/* name */
  	000400,	/* short constant */
  	000400,	/* string */
  	000400,	/* float */
  	000400,	/* double */
! 	0000400,	/* long const */
  	000400,	/* long const <= 16 bits */
  	000400,	/* autoi, *r++ */
  	000400,	/* autod, *--r */
  	000400,	/* () empty arglist */
! 	034213,	/* ++pre */
  	034213,	/* --pre */
  	034213,	/* ++post */
  	034213,	/* --post */
--- 30,47 ----
  	000001,	/* field assignment */
  	000001,	/* >> unsigned */
  	000001,	/* >>= unsigned */
! 	000000,	/* keyword */
! 	000400,	/* name (20) */
  	000400,	/* short constant */
  	000400,	/* string */
  	000400,	/* float */
  	000400,	/* double */
! 	000400,	/* long const */
  	000400,	/* long const <= 16 bits */
  	000400,	/* autoi, *r++ */
  	000400,	/* autod, *--r */
  	000400,	/* () empty arglist */
! 	034213,	/* ++pre (30) */
  	034213,	/* --pre */
  	034213,	/* ++post */
  	034213,	/* --post */
***************
*** 46,52 ****
  	034200,	/* -un */
  	034220,	/* ~un */
  	036001,	/* . (structure reference) */
! 	030101,	/* + */
  	030001,	/* - */
  	032101,	/* * */
  	032001,	/* / */
--- 51,57 ----
  	034200,	/* -un */
  	034220,	/* ~un */
  	036001,	/* . (structure reference) */
! 	030101,	/* + (40) */
  	030001,	/* - */
  	032101,	/* * */
  	032001,	/* / */
***************
*** 56,62 ****
  	020161,	/* & */
  	016161,	/* | */
  	016161,	/* ^ */
! 	036001,	/* -> */
  	001000,	/* int -> double */
  	001000,	/* double -> int */
  	000001,	/* && */
--- 61,67 ----
  	020161,	/* & */
  	016161,	/* | */
  	016161,	/* ^ */
! 	036001,	/* -> (50) */
  	001000,	/* int -> double */
  	001000,	/* double -> int */
  	000001,	/* && */
***************
*** 66,72 ****
  	001000,	/* long -> double */
  	001000,	/* integer -> long */
  	000000,	/* long -> integer */
! 	022005,	/* == */
  	022005,	/* != */
  	024005,	/* <= */
  	024005,	/* < */
--- 71,77 ----
  	001000,	/* long -> double */
  	001000,	/* integer -> long */
  	000000,	/* long -> integer */
! 	022005,	/* == (60) */
  	022005,	/* != */
  	024005,	/* <= */
  	024005,	/* < */
***************
*** 76,82 ****
  	024005,	/* <=p */
  	024005,	/* >p */
  	024005,	/* >=p */
! 	012213,	/* += */
  	012213,	/* -= */
  	012213,	/* *= */
  	012213,	/* /= */
--- 81,87 ----
  	024005,	/* <=p */
  	024005,	/* >p */
  	024005,	/* >=p */
! 	012213,	/* += (70) */
  	012213,	/* -= */
  	012213,	/* *= */
  	012213,	/* /= */
***************
*** 86,92 ****
  	012253,	/* &= */
  	012253,	/* |= */
  	012253,	/* ^= */
! 	012213,	/* = */
  	030001, /* & for tests */
  	032001,	/*  * (long) */
  	032001,	/*  / (long) */
--- 91,97 ----
  	012253,	/* &= */
  	012253,	/* |= */
  	012253,	/* ^= */
! 	012213,	/* = (80) */
  	030001, /* & for tests */
  	032001,	/*  * (long) */
  	032001,	/*  / (long) */
***************
*** 95,102 ****
  	012213,	/* *= (long) */
  	012213,	/* /= (long) */
  	012213,	/* %= (long) */
! 	000000,	/* 89 */
! 	014201,	/* ? */
  	026061,	/* long << */
  	012253,	/* long <<= */
  	000101,	/* max */
--- 100,107 ----
  	012213,	/* *= (long) */
  	012213,	/* /= (long) */
  	012213,	/* %= (long) */
! 	000000,	/* (89) */
! 	014201,	/* question '?' (90) */
  	026061,	/* long << */
  	012253,	/* long <<= */
  	000101,	/* max */
***************
*** 104,144 ****
  	000101,	/* min */
  	000101,	/* minp */
  	000001,	/* , */
! 	000000,	/* 98 */
! 	000000,	/* 99 */
! 	036001,	/* call */
  	036000,	/* mcall */
  	000000,	/* goto */
  	000000,	/* jump cond */
  	000000,	/* branch cond */
  	000400,	/* set nregs */
! 	000000, /* 106 */
! 	030001,	/* 107 */
! 	000000,	/* 108 */
  	000000,	/* int->char */
! 	000000,	/* force r0 */
! 	000000,	/* 111 */
! 	000000,	/* 112 */
! 	000000,	/* 113 */
! 	000000,	/* 114 */
  	000000,	/* structure assign */
  	000001,	/* struct assignment setup */
  	032001,	/* unsigned / */
  	032001,	/* unsigned % */
  	012213,	/* unsigned /= */
! 	012213,	/* unsigned %= */
! 	032001, /* 121 unsigned long * */
! 	032001, /* 122 unsigned long / */
! 	032001, /* 123 unsigned long % */
! 	012213, /* 124 unsigned long *= */
! 	012213, /* 125 unsigned long /= */
! 	012213, /* 126 unsigned long %= */
! 	01000,  /* 127 unsigned long -> float(double) */
! 	026061, /* 128 unsigned long >> */
! 	012253, /* 129 unsigned long >>= */
  };
  
  char	*opntab[] = {
  	0,
  	0,
  	0,
--- 109,150 ----
  	000101,	/* min */
  	000101,	/* minp */
  	000001,	/* , */
! 	000000,	/* call1 */
! 	000000,	/* call2 */
! 	036001,	/* call (100) */
  	036000,	/* mcall */
  	000000,	/* goto */
  	000000,	/* jump cond */
  	000000,	/* branch cond */
  	000400,	/* set nregs */
! 	000000, /* load */
! 	030001,	/* ptoi1 */
! 	000000,	/* (108) */
  	000000,	/* int->char */
! 	000000,	/* force r0 (110) */
! 	000000,	/* branch */
! 	000000,	/* label */
! 	000000,	/* nlabel */
! 	000000,	/* rlabel */
  	000000,	/* structure assign */
  	000001,	/* struct assignment setup */
  	032001,	/* unsigned / */
  	032001,	/* unsigned % */
  	012213,	/* unsigned /= */
! 	012213,	/* unsigned %= (120) */
! 	032001, /* unsigned long * */
! 	032001, /* unsigned long / */
! 	032001, /* unsigned long % */
! 	012213, /* unsigned long *= */
! 	012213, /* unsigned long /= */
! 	012213, /* unsigned long %= */
! 	01000,  /* unsigned long -> float(double) */
! 	026061, /* unsigned long >> */
! 	012253, /* unsigned long >>= (129) */
  };
  
  char	*opntab[] = {
+ 	0,			/* 0 */
  	0,
  	0,
  	0,
***************
*** 146,155 ****
  	0,
  	0,
  	0,
- 	0,
  	":",
  	",",
! 	"field select",
  	0,
  	0,
  	"int->ptr",
--- 152,160 ----
  	0,
  	0,
  	0,
  	":",
  	",",
! 	"field select",		/* 10 */
  	0,
  	0,
  	"int->ptr",
***************
*** 158,165 ****
  	"field assign",
  	">>",
  	">>=",
! 	0,
! 	"name",
  	"short constant",
  	"string",
  	"float",
--- 163,170 ----
  	"field assign",
  	">>",
  	">>=",
! 	"keyword",
! 	"name",			/* 20 */
  	"short constant",
  	"string",
  	"float",
***************
*** 169,175 ****
  	"*r++",
  	"*--r",
  	"()",
! 	"++pre",
  	"--pre",
  	"++post",
  	"--post",
--- 174,180 ----
  	"*r++",
  	"*--r",
  	"()",
! 	"++pre",		/* 30 */
  	"--pre",
  	"++post",
  	"--post",
***************
*** 179,185 ****
  	"-",
  	"~",
  	".",
! 	"+",
  	"-",
  	"*",
  	"/",
--- 184,190 ----
  	"-",
  	"~",
  	".",
! 	"+",			/* 40 */
  	"-",
  	"*",
  	"/",
***************
*** 189,195 ****
  	"&",
  	"|",
  	"^",
! 	"->",
  	"int->double",
  	"double->int",
  	"&&",
--- 194,200 ----
  	"&",
  	"|",
  	"^",
! 	"->",			/* 50 */
  	"int->double",
  	"double->int",
  	"&&",
***************
*** 199,205 ****
  	"long->double",
  	"integer->long",
  	"long->integer",
! 	"==",
  	"!=",
  	"<=",
  	"<",
--- 204,210 ----
  	"long->double",
  	"integer->long",
  	"long->integer",
! 	"==",			/* 60 */
  	"!=",
  	"<=",
  	"<",
***************
*** 209,215 ****
  	"<=p",
  	">p",
  	">=p",
! 	"+=",
  	"-=",
  	"*=",
  	"/=",
--- 214,220 ----
  	"<=p",
  	">p",
  	">=p",
! 	"+=",			/* 70 */
  	"-=",
  	"*=",
  	"/=",
***************
*** 219,225 ****
  	"&=",
  	"|=",
  	"^=",
! 	"=",
  	"& for tests",
  	"*",
  	"/",
--- 224,230 ----
  	"&=",
  	"|=",
  	"^=",
! 	"=",			/* 80 */
  	"& for tests",
  	"*",
  	"/",
***************
*** 229,235 ****
  	"/=",
  	"%=",
  	0,
! 	"?",
  	"<<",
  	"<<=",
  	"\\/",
--- 234,240 ----
  	"/=",
  	"%=",
  	0,
! 	"?",			/* 90 */
  	"<<",
  	"<<=",
  	"\\/",
***************
*** 236,246 ****
  	"\\/",
  	"/\\",
  	"/\\",
! 	0,
! 	"call",
! 	"call",
! 	"call",
! 	0,
  	"goto",
  	"jump cond",
  	"branch cond",
--- 241,251 ----
  	"\\/",
  	"/\\",
  	"/\\",
! 	",",
! 	"call1",
! 	"call2",
! 	"call",			/* 100 */
! 	"mcall",
  	"goto",
  	"jump cond",
  	"branch cond",
***************
*** 249,274 ****
  	"ptr->integer",
  	0,
  	"int->char",
! 	"force register",
! 	"",
! 	"",
! 	"",
! 	"",
  	"=structure",
  	"= (struct setup)",
  	"/",
  	"%",
  	"/=",
! 	"%=",
! 	"*",	/* unsigned long */
! 	"/",	/* unsigned long */
! 	"%",	/* unsigned long */
! 	"*=",	/* unsigned long */
! 	"/=",	/* unsigned long */
! 	"%=",	/* unsigned long */
! 	"u_long->double", /* unsigned long */
! 	">>",	/* unsigned long */
! 	">>=",	/* unsigned long */
  };
  
  /*
--- 254,279 ----
  	"ptr->integer",
  	0,
  	"int->char",
! 	"force register",	/* 110 */
! 	"branch",
! 	"label",
! 	"nlabel",
! 	"rlabel",
  	"=structure",
  	"= (struct setup)",
  	"/",
  	"%",
  	"/=",
! 	"%=",			/* 120 */
! 	"*",			/* unsigned long */
! 	"/",			/* unsigned long */
! 	"%",			/* unsigned long */
! 	"*=",			/* unsigned long */
! 	"/=",			/* unsigned long */
! 	"%=",			/* unsigned long */
! 	"u_long->double", 	/* unsigned long */
! 	">>",			/* unsigned long */
! 	">>=",			/* 129 unsigned long */
  };
  
  /*
