[comp.sources.unix] v11i042: Inline code expander for C, Part04/04

rs@uunet.UU.NET (Rich Salz) (09/16/87)

Submitted-by: omepd!mcg
Posting-number: Volume 11, Issue 42
Archive-name: inline/Part04

# This is a shell archive.  Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have original permissions).
# This archive contains the following files:
#	./patchlevel.h
#	./Makefile
#	./scan.l
#	./BUGS
#	./MINVERS
#	./test.c
#	./test2.c
#
if `test ! -s ./patchlevel.h`
then
echo "writing ./patchlevel.h"
sed 's/^X//' > ./patchlevel.h << '\Rogue\Monster\'
X/* patchlevel file */
X
X#define PATCHLEVEL 0
X
X
\Rogue\Monster\
else
  echo "will not over write ./patchlevel.h"
fi
chmod 444 ./patchlevel.h
if [ `wc -c ./patchlevel.h | awk '{printf $1}'` -ne 46 ]
then
echo `wc -c ./patchlevel.h | awk '{print "Got " $1 ", Expected " 46}'`
fi
if `test ! -s ./Makefile`
then
echo "writing ./Makefile"
sed 's/^X//' > ./Makefile << '\Rogue\Monster\'
X#
X# Makefile for 'inline' program - C inline code substituter
X#
X# (c) copyright 1986, 1987, S. McGeady, all rights reserved
X#
X#
X# NOTE - comment out some lines below if you don't have RCS
X#
X
X# CFLAGS=-g -pg
X# CFLAGS=-g
XCFLAGS=-O
X
Xall: inline test
X
XMAJVERS = "3"
XHDRS = inline.h tokens.h
XSRCS = inline.c declare.c expand.c rewrite.c yylex.c tokens.c utils.c mem.c
XOBJS = inline.o declare.o expand.o rewrite.o yylex.o tokens.o utils.o mem.o
X
Xinline: $(OBJS) vers.o
X	$(CC) -o inline $(CFLAGS) $(OBJS) vers.o
X
Xyylex.o: yylex.c $(HDRS)
Xdeclare.o: declare.c $(HDRS)
Xexpand.o: expand.c $(HDRS)
Xutils.o: utils.c $(HDRS)
Xinline.o: inline.c $(HDRS)
Xrewrite.o: rewrite.c $(HDRS)
Xmem.o: mem.c
Xtokens.o: tokens.c
X
Xvers.o: $(OBJS) patchlevel.h
X	-@chmod u+w MINVERS
X	-expr "`cat MINVERS`" + 1 > MINVERS
X	echo '#include "patchlevel.h"' > vers.c
X	echo 'static char *vers[] = {' >> vers.c
X	echo '"$$''Header: inline version' $(MAJVERS).`cat MINVERS` 'compiled' "`date`" "flags '$(CFLAGS)'" '$$",' >> vers.c
X	# if you don't have RCS, this will fail
X	# COMMENT THIS LINE OUT IF YOU DON'T HAVE RCS ON YOUR SYSTEM
X	# perhaps replace with:
X	# grep '\$$''Header:' $(HDRS) $(SRCS) | sed 's/^.*\$$\(.*\)\$$$$/"$$\1$$",/' >> vers.c
X	-ident $(HDRS) $(SRCS) | grep '\$$''Header:' | sed 's/^.*\$$\(.*\)\$$$$/"$$\1$$",/' >> vers.c
X
X	# END OF RCS SECTION
X
X	echo '};' >> vers.c
X	$(CC) -c vers.c
X
X#
X# this is all for verification
X#
X
Xbasex: test.c
X	$(CC) -o basex -Dinline=static test.c
X
Xtestx: inline test.c
X	./inline -w -s < test.c > x.c
X	$(CC) -o testx x.c
X
Xtest2x: inline test2.c
X	./inline -w -2 -s test2.c > x2.c
X	$(CC) -o test2x x2.c
X
Xtest: inline basex testx test2x
X	@echo 'starting validation tests'
X	./basex > base.out
X	./testx > test.out
X	@sh -c 'if grep -s FAIL base.out; then echo "your compiler is broken"; exit 1; else exit 0; fi'
X	@sh -c 'if grep -s FAIL test.out; then echo "something is wrong with inline or your compiler"; exit 1; else exit 0; fi'
X	@sh -c 'if test `wc -l <base.out` -ne `wc -l <test.out`; then echo "something is wrong with inline or your compiler"; exit 1; else exit 0; fi'
X	@echo 'testing two-pass mode'
X	./test2x > test2.out
X	@sh -c 'if grep -s FAIL test2.out; then echo "something is wrong with inline in 2-pass mode"; exit 1; else exit 0; fi'
X	@sh -c 'if test `wc -l <base.out` -ne `wc -l <test2.out`; then echo "something is wrong with inline in 2-pass mode"; exit 1; else exit 0; fi'
X	@echo 'testing complete - everything looks ok'
X
Xclean:
X	rm -f scan.c tstscan.c $(OBJS) vers.o \
X		mon.out core tstscan.o x.c basex testx base.out test.out
X
Xlint:	$(SRCS) $(HDRS)
X	lint -h -c -n inline.c declare.c expand.c rewrite.c utils.c mem.c yylex.c tokens.c
X
X#
X# this expects the 'rogue monster' (mips!roger) shar 
X# -c includes size checking, -p retains permissions, -x X prepends 'X' to lines
X#
Xshar:	$(SRCS) $(HDRS) Makefile inline.1 scan.l
X	shar -c -p -x X -f inline. inline.1 $(HDRS) $(SRCS) patchlevel.h \
X		Makefile scan.l NOTES COPYRIGHT BUGS MINVERS test.c test2.c
X
X
X# scan.o: scan.l inline.h tokens.h
X# tstscan: scan.c tokens.o
X#	cp scan.c tstscan.c
X#	$(CC) -c -DTEST tstscan.c
X#	$(CC) -o tstscan -g tstscan.o tokens.o
X
\Rogue\Monster\
else
  echo "will not over write ./Makefile"
fi
chmod 444 ./Makefile
if [ `wc -c ./Makefile | awk '{printf $1}'` -ne 3126 ]
then
echo `wc -c ./Makefile | awk '{print "Got " $1 ", Expected " 3126}'`
fi
if `test ! -s ./scan.l`
then
echo "writing ./scan.l"
sed 's/^X//' > ./scan.l << '\Rogue\Monster\'
XD			[0-9]
XL			[a-zA-Z_]
XH			[a-fA-F0-9]
XE			[Ee][+-]?{D}+
XLS			(l|L)
XUS			(u|U)
X
X%{
X/*
X * inline code expander
X *
X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
X */
X
X/* $Header: scan.l,v 1.5 87/04/27 18:16:48 mcg Rel $ */
X
X
X#include <stdio.h>
X#include "tokens.h"
X#include "inline.h"
X
X#ifdef COUNTCOLUMN
Xvoid count();
X#else
X#define	count()
X#endif
X
X#define	COMMENT		1
X#define	CPPLINE		2
X#define	STRING		3
X
Xextern char *gather();
X
Xchar *yylval;
X
Xint line = 1;
Xint column = 0;
X
Xstatic int bracelev = 0;
Xstatic int parenlev = 0;
X%}
X
X%%
X"/*"			{ count(); yylval = gather(COMMENT,yytext);
X				/* T_COMMENT gets changed to T_WS later */
X				return(T_COMMENT); }
X^[ \t]*#		{ count(); yylval = gather(CPPLINE,yytext);
X				return(T_CPP); }
X\"			{ count(); yylval = gather(STRING,yytext);
X				return(T_STR); }
X
X"auto"			{ count(); yylval = 0; return(T_AUTO); }
X"break"			{ count(); yylval = 0; return(T_BREAK); }
X"case"			{ count(); yylval = 0; return(T_CASE); }
X"char"			{ count(); yylval = 0; return(T_CHAR); }
X"const"			{ count(); yylval = 0; return(T_CONST); }
X"continue"		{ count(); yylval = 0; return(T_CONTINUE); }
X"default"		{ count(); yylval = 0; return(T_DEFAULT); }
X"do"			{ count(); yylval = 0; return(T_DO); }
X"double"		{ count(); yylval = 0; return(T_DOUBLE); }
X"else"			{ count(); yylval = 0; return(T_ELSE); }
X"enum"			{ count(); yylval = 0; return(T_ENUM); }
X"extern"		{ count(); yylval = 0; return(T_EXTERN); }
X"float"			{ count(); yylval = 0; return(T_FLOAT); }
X"for"			{ count(); yylval = 0; return(T_FOR); }
X"goto"			{ count(); yylval = 0; return(T_GOTO); }
X"if"			{ count(); yylval = 0; return(T_IF); }
X"inline"		{ count(); yylval = 0; return(T_INLINE); }
X"int"			{ count(); yylval = 0; return(T_INT); }
X"long"			{ count(); yylval = 0; return(T_LONG); }
X"register"		{ count(); yylval = 0; return(T_REGISTER); }
X"return"		{ count(); yylval = 0; return(T_RETURN); }
X"short"			{ count(); yylval = 0; return(T_SHORT); }
X"signed"		{ count(); yylval = 0; return(T_SIGNED); }
X"sizeof"		{ count(); yylval = 0; return(T_SIZEOF); }
X"static"		{ count(); yylval = 0; return(T_STATIC); }
X"struct"		{ count(); yylval = 0; return(T_STRUCT); }
X"switch"		{ count(); yylval = 0; return(T_SWITCH); }
X"typedef"		{ count(); yylval = 0; return(T_TYPEDEF); }
X"union"			{ count(); yylval = 0; return(T_UNION); }
X"unsigned"		{ count(); yylval = 0; return(T_UNSIGNED); }
X"void"			{ count(); yylval = 0; return(T_VOID); }
X"volatile"		{ count(); yylval = 0; return(T_VOLATILE); }
X"while"			{ count(); yylval = 0; return(T_WHILE); }
X
X{L}({L}|{D})*		{ count(); yylval= yytext; return(T_IDENT);
X			/* typedefing is checked in gettok() */ }
X
X"0fnan"			{ count(); yylval = yytext; return(T_NUM); }
X"0fNAN"			{ count(); yylval = yytext; return(T_NUM); }
X"0finf"			{ count(); yylval = yytext; return(T_NUM); }
X"0fINF"			{ count(); yylval = yytext; return(T_NUM); }
X
X0[xX]{H}+{LS}?{US}?	{ count(); yylval = yytext; return(T_NUM); }
X0[xX]{H}+{US}?{LS}?	{ count(); yylval = yytext; return(T_NUM); }
X0{D}+{LS}?{US}?		{ count(); yylval = yytext; return(T_NUM); }
X0{D}+{US}?{LS}?		{ count(); yylval = yytext; return(T_NUM); }
X{D}+{LS}?{US}?		{ count(); yylval = yytext; return(T_NUM); }
X{D}+{US}?{LS}?		{ count(); yylval = yytext; return(T_NUM); }
X
X{D}+{E}{LS}?		{ count(); yylval = yytext; return(T_NUM); }
X{D}*"."{D}+({E})?{LS}?	{ count(); yylval = yytext; return(T_NUM); }
X{D}+"."{D}*({E})?{LS}?	{ count(); yylval = yytext; return(T_NUM); }
X
X'(\\.|[^\\'])+'		{ count(); yylval = yytext; return(T_CHARCONST); }
X"..."			{ count(); yylval = 0; return(T_ELLIPSES); }
X">>="			{ count(); yylval = 0; return(T_RS_EQ); }
X"<<="			{ count(); yylval = 0; return(T_LS_EQ); }
X"+="			{ count(); yylval = 0; return(T_ADD_EQ); }
X"-="			{ count(); yylval = 0; return(T_SUB_EQ); }
X"*="			{ count(); yylval = 0; return(T_MUL_EQ); }
X"/="			{ count(); yylval = 0; return(T_DIV_EQ); }
X"%="			{ count(); yylval = 0; return(T_MOD_EQ); }
X"&="			{ count(); yylval = 0; return(T_AND_EQ); }
X"^="			{ count(); yylval = 0; return(T_XOR_EQ); }
X"|="			{ count(); yylval = 0; return(T_OR_EQ); }
X">>"			{ count(); yylval = 0; return(T_RS); }
X"<<"			{ count(); yylval = 0; return(T_LS); }
X"++"			{ count(); yylval = 0; return(T_INC); }
X"--"			{ count(); yylval = 0; return(T_DEC); }
X"->"			{ count(); yylval = 0; return(T_PTR); }
X"&&"			{ count(); yylval = 0; return(T_CAND); }
X"||"			{ count(); yylval = 0; return(T_COR); }
X"<="			{ count(); yylval = 0; return(T_LE); }
X">="			{ count(); yylval = 0; return(T_GE); }
X"=="			{ count(); yylval = 0; return(T_CEQ); }
X"!="			{ count(); yylval = 0; return(T_NE); }
X";"			{ count(); yylval = 0; return(T_SEMIC); }
X"{"			{ count(); yylval = 0; bracelev++; return(T_LBRACE); }
X"}"			{ count(); yylval = 0; bracelev--; return(T_RBRACE); }
X","			{ count(); yylval = 0; return(T_COMMA); }
X":"			{ count(); yylval = 0; return(T_COLON); }
X"="			{ count(); yylval = 0; return(T_EQ); }
X"("			{ count(); yylval = 0; parenlev++; return(T_LPAREN); }
X")"			{ count(); yylval = 0; parenlev--; return(T_RPAREN); }
X"["			{ count(); yylval = 0; return(T_LSQ); }
X"]"			{ count(); yylval = 0; return(T_RSQ); }
X"."			{ count(); yylval = 0; return(T_DOT); }
X"&"			{ count(); yylval = 0; return(T_AMPER); }
X"!"			{ count(); yylval = 0; return(T_NOT); }
X"~"			{ count(); yylval = 0; return(T_TILDE); }
X"-"			{ count(); yylval = 0; return(T_MINUS); }
X"+"			{ count(); yylval = 0; return(T_PLUS); }
X"*"			{ count(); yylval = 0; return(T_STAR); }
X"/"			{ count(); yylval = 0; return(T_DIV); }
X"%"			{ count(); yylval = 0; return(T_MOD); }
X"<"			{ count(); yylval = 0; return(T_LT); }
X">"			{ count(); yylval = 0; return(T_GT); }
X"^"			{ count(); yylval = 0; return(T_XOR); }
X"|"			{ count(); yylval = 0; return(T_OR); }
X"?"			{ count(); yylval = 0; return(T_QUEST); }
X
X[ \t\v\n\f]*		{ count(); yylval = yytext; return(T_WS); }
X.			{ /* ignore bad characters */ }
X
X%%
X
Xyywrap()
X{
X	return(1);
X}
X
X/*
X */
X
Xchar *
Xgather(type,init)
Xint type;
Xchar *init;
X{
X	char buf[1024];
X	register char *tbuf;
X	register int tbufsize = 0;
X	register char *bb = buf;
X	register char *p = bb;
X	register char *ebuf = &buf[1023];
X	
X
X	strcpy(buf,init);
X	p = buf + strlen(init);
X	while (*p = input()) {
X		if (*p == 0)
X			break;
X		switch (type) {
X		case COMMENT:
X			if (*p == '/' && p != bb && p[-1] == '*') {
X				goto end;
X			}
X			break;
X		case CPPLINE:
X			if (*p == '\n' && p != bb && p[-1] != '\\') {
X				unput('\n');
X				*p = '\0';
X				goto end;
X			}
X			break;
X		case STRING:
X			if (*p == '"' && p != bb && p[-1] != '\\') {
X				goto end;
X			}
X			break;
X		}
X		if (++p >= ebuf) {
X			*p = '\0';
X			if (tbufsize == 0) {
X				tbufsize = 1024;
X			}
X			tbuf = (char *) malloc(tbufsize *= 2);
X			strcpy(tbuf, bb);
X			p = tbuf + (p - bb);
X			if (bb != buf) {
X				free(bb);
X			}
X			bb = tbuf;
X			ebuf = bb + tbufsize;
X		}
X	}
X    end:
X	*++p = '\0';
X	p++;
X	if (tbufsize == 0) {
X		tbuf = (char *) malloc(p-bb);
X		strcpy(tbuf, bb);
X		bb = tbuf;
X	}
X	return(bb);
X}
X
X#ifdef COUNTCOLUMN
Xvoid
Xcount()
X{
X	int i;
X
X	for (i = 0; yytext[i] != '\0'; i++)
X		if (yytext[i] == '\n') {
X			column = 0;
X			line++;
X		}
X		else if (yytext[i] == '\t')
X			column += 8 - (column % 8);
X		else
X			column++;
X}
X#endif
X
X#ifndef TEST
X
Xcheck_type(tok)
Xregister struct token *tok;
X{
X	register int i;
X	register char **p;
X
X	for (i = 0; (i < NSCOPE) && (typeid[i] != NIL); i++) {
X		for (p = typeid[i]->type_id; *p != NIL; p++) {
X			if (strcmp(tok->t_id,*p) == 0) {
X				tok->t_tok = T_TYPE_ID;
X				return;
X			}
X		}
X	}
X}
X
Xstruct token *
Xgettok(mem)
Xregister int mem;
X{
X	register int t;
X	struct token *tok;
X
X	if ((t = yylex()) == 0)
X		return((struct token *) 0);
X	tok = newtok(mem, t, yylval);
X	tok->t_line = yylineno;
X	switch(t) {
X	case T_COMMENT:
X	case T_CPP:
X		tok->t_tok = T_WS;
X		/*FALLTHROUGH*/
X	case T_STR:
X		free(yylval);
X		break;
X
X	case T_LBRACE:
X		tok->t_level = bracelev-1;
X		tok->t_paren = parenlev;
X		pushscope(bracelev);
X		break;
X	case T_LPAREN:
X		tok->t_paren = parenlev-1;
X		tok->t_level = bracelev;
X		break;
X	case T_RBRACE:
X		popscope(bracelev+1);
X		/*FALLTHROUGH*/
X	default:
X		tok->t_level = bracelev;
X		tok->t_paren = parenlev;
X		break;
X	}
X	if (t == T_IDENT) {
X		check_type(tok);
X	}
X	return(tok);
X}
X#endif
X
X#ifdef TEST
Xmain() {
X	int tok;
X	extern char *tokens[];
X
X	while(tok = yylex()) {
X		switch (tok) {
X		case T_COMMENT:
X		case T_STR:
X		case T_CPP:
X			free(yylval);
X
X		case T_IDENT:
X		case T_WS:
X		case T_NUM:
X		case T_CHARCONST:
X		case T_TYPE_ID:
X			fputs(yylval,stdout);
X			break;
X		case T_ACTUAL:
X			fputs("<ACTUAL>",stdout);
X			break;
X		case T_RETVAL:
X			fputs("<RETVAL>",stdout);
X			break;
X		case T_ARGLIST:
X			fprintf(stdout,"%s(ARGLIST)", yylval);
X			break;
X		case T_RETLAB:
X			fputs("<RETLAB>",stdout);
X			break;
X		case T_FORMAL:
X			fprintf(stdout,"<FORMAL '%s'>",yylval);
X			break;
X		default:
X			if (tok <= T_INLINE)
X				fputs(tokens[tok],stdout);
X			else
X				fputs("???",stdout);
X
X			break;
X		}
X	}
X}
X#endif
\Rogue\Monster\
else
  echo "will not over write ./scan.l"
fi
chmod 444 ./scan.l
if [ `wc -c ./scan.l | awk '{printf $1}'` -ne 8829 ]
then
echo `wc -c ./scan.l | awk '{print "Got " $1 ", Expected " 8829}'`
fi
if `test ! -s ./BUGS`
then
echo "writing ./BUGS"
sed 's/^X//' > ./BUGS << '\Rogue\Monster\'
XFri May  8 17:13:05 PDT 1987
X
XCurrent bugs:
X	- multi-line comments that begin on pre-processor lines are not
X	  handled correctly
X
X	- comma operators don't work correctly, e.g.
X		x = (cond, inline_func());
X	  (inline_func() gets called too soon) 
X
XImportant enhancements to be added:
X
X	-
X
XMiscellaneous features to be added:
X
X	-
\Rogue\Monster\
else
  echo "will not over write ./BUGS"
fi
chmod 444 ./BUGS
if [ `wc -c ./BUGS | awk '{printf $1}'` -ne 329 ]
then
echo `wc -c ./BUGS | awk '{print "Got " $1 ", Expected " 329}'`
fi
if `test ! -s ./MINVERS`
then
echo "writing ./MINVERS"
sed 's/^X//' > ./MINVERS << '\Rogue\Monster\'
X0
\Rogue\Monster\
else
  echo "will not over write ./MINVERS"
fi
chmod 444 ./MINVERS
if [ `wc -c ./MINVERS | awk '{printf $1}'` -ne 2 ]
then
echo `wc -c ./MINVERS | awk '{print "Got " $1 ", Expected " 2}'`
fi
if `test ! -s ./test.c`
then
echo "writing ./test.c"
sed 's/^X//' > ./test.c << '\Rogue\Monster\'
X
X/* test cases for 'inline' */
X
X/* $Header: test.c,v 1.6 87/06/24 13:06:22 mcg Rel $ */
X
X
X/* simple inline */
Xinline int foo(a,b) {
X	register int x = 0;
X
X	printf("foo(%d, %d)\n", a,b);
X	return(a+b);
X}
Xinline int bar(x,y) {
X	register int a;
X
X	a = 0;
X	printf("bar(%d, %d)\n", x,y);
X	return(x-y);
X}
X/* inline with some control flow */
Xinline biff(a) {
X	while(1) return a;
X}
X
X/* inline with a switch */
Xinline insw(i)
Xint i;
X{
X	switch(i) {
X	case 0:	return('0');
X	case 1: return('1');
X	case 2: return('2');
X	case 3: return('3');
X	case 4: return(foo(i,'0'));
X	case 5: return('5');
X	case 6: return('6');
X	case 7: return(foo(i,'0'));
X	case 8: return('8');
X	case 9: return('9');
X	}
X	return(0);
X}
X
Xtypedef char *cptr;
X
Xinline barf() {
X	printf("!!!\n");
X}
X
X/* inline returning a typedef */
Xinline cptr
Xboff(c,s)
Xchar c;
Xcptr s;
X{
X	s[0] = c;
X	return(&s[1]);
X}
X
X/* inline returning a pointer type */
Xinline char *
Xboff2(c,s)
Xchar c;
Xcptr s;
X{
X	s[0] = c;
X	return(&s[1]);
X}
X
Xstruct str {
X	int a;
X	int b;
X	int c;
X};
X
X/* inline returning a structure */
Xinline struct str bipp(a,b,c)
Xint a, b, c;
X{
X	struct str x;
X
X	x.a = a;
X	x.b = b;
X	x.c = c;
X	return(x);
X}
X
X/* inline returning a structure pointer */
Xinline struct str *bupp(z,a,b,c)
Xregister struct str *z;
Xregister int a,b,c;
X{
X	z->a = a;
X	z->b = b;
X	z->c = c;
X	return(z);
X}
X
Xnil(){}
X
X/* inline returning function pointer */
Xinline int (*fp())()
X{
X	return(nil);
X}
X
Xint effect = 0;
X
Xinline int side_effect(a)
Xint a;
X{
X	int old;
X
X	old = effect;
X	effect = a;
X
X	return(old);
X}
X
X/* should have no effect on arguments */
Xinline int swaparg(a,b)
X{
X	int tmp;
X
X	tmp = a;
X	a = b;
X	b = tmp;
X
X	return(a+b);
X}
X
Xinline struct str modarg(a,b)
Xint a;
Xstruct str b;	/* struct arg */
X{
X	switch(a) {
X	case 0:
X		a = 1;
X		b.a = 1;
X		break;
X	case 1:
X		a >>= 1;
X		a <<= 1;
X		b.a = a;
X		break;
X	case 2:
X		a *= 3;
X		b.a = a;
X		break;
X	}
X	return(b);
X}
X
Xinline hardcase1(a,b)
Xint a,b;
X{
X	{ ; }
X	if (a);
X	{{}}
X	if (a) { } else ;
X	return(b);
X}
Xinline char *
Xhardcase2(a,b,c)
Xchar *a;
Xint b,c;
X{
X	char *s = "foo", c = 'c';
X	int x = b;
X
X	if (a) return(s);
X	else {
X		if (b) return(a+c);
X	}
X	return(a+c);
X}
X
Xinline expr1(a,b)
Xint a,b;
X{
X	int x = 0;
X
X	if (foo(0,a+b) == 100) return x+2;	/* a+b == 100, ret = 2 */
X	if (foo(50,50) == 100 && a) return x;	/* a != 0, return = 0 */
X	if (foo(100,0) == 100 && b) return x+1;	/* a == 0 && b != 0, ret = 1 */
X	return x+3;				/* ret = 3 */
X}
X
Xinline expr2(a,b)
Xint a,b;
X{
X	register int x = 0, y = 1;
X
X	if (a) {
X		return(x+y);	/* a != 0, return = 1 */
X	} else {
X		register int x = 100, y = 101;
X
X		if (b) {
X			return(x+y);	/* a == 0 && b != 0, return = 201 */
X		} else {
X			register int x = 200, y = 300;
X
X			return(x+y);	/* a == 0 && b == 0, return = 500 */
X		}
X	}
X}
X
Xinline labs(i)
Xint i;
X{
X	if (i == 1) goto L1;
X	if (i == 2) goto L2;
X	if (i == 3) goto L3;
X	if (i == 4) goto L4;
X	goto L5;
XL6:
X	return(i);
X
XL1:	i++; return(1);
XL2:	if (i == 2) return(2);
XL3:	return(3);
XL4:	{
X	return(4);
X	}
XL5:	goto L6;
X}
X
Xm() {
X	register int x,y,z;
X
X	x = foo(x++,y++);
X}
X
Xmain() {
X	t1(1);
X	t2(2);
X	t3(3);
X	t4(4);
X	t5(5);
X	t6(6);
X	t7(7);
X	t8(8);
X	t9(9);
X	t10(10);
X	t11(11);
X	t12(12);
X	t13(13);
X	t14(14);
X	t15(15,50);
X	t16(16);
X	t17(17);
X	t18(18);
X	return(0);
X}
X
X/*
X * basic expansion of single inline
X */
X
Xt1(i)
Xint i;
X{
X	int a;
X
X	printf("test%d:\n",i);
X	a = foo(1,2);
X	if (a == 3) {
X		printf("test%d ok\n",i);
X	} else {
X		printf("test%d FAIL\n",i);
X	}
X}
X
X/*
X * expansion of multiple inlines in single expression
X */
X
Xt2(i)
Xint i;
X{
X	int a;
X
X	printf("test%d:\n",i);
X	a = foo(1,2) + foo(3,4);
X	if (a == 10) {
X		printf("test%d ok\n",i);
X	} else {
X		printf("test%d FAIL\n",i);
X	}
X}
X
X/*
X * expansion of inlines in various styles of if() statement
X * - check parsing of if compound statement
X */
X
Xt3(i)
Xint i;
X{
X	printf("test%d:\n",i);
X	if (foo(1,2) != 3) {
X		printf("test%d FAIL\n",i); 
X		return;
X	}
X
X	if (foo(1,2) == 3) {
X		;
X	} else {
X		printf("test%d FAIL\n"); 
X		return;
X	}
X
X	if (!foo(1,2)) printf("test%d FAIL\n",i);
X
X	if (foo(1,2) == 3) nil(); else printf("test%d FAIL\n",i);
X
X	if (foo(1,2) == 3) nil(); else {
X		printf("test%d FAIL\n",i);
X	}
X
X	if (foo(1,2) == 3) {
X		printf("test%d ok\n",i);
X	} else
X		printf("test%d FAIL\n",i);
X}
X
X/*
X * inlines as arguments to other inlines
X */
X
Xt4(i)
Xint i;
X{
X	register int a;
X
X	printf("test%d:\n",i);
X	a = foo(foo(1,2),2);
X	if (a != 5) {
X		printf("test%d FAIL\n",i);
X	}
X
X	a = foo(100,bar(5,4));
X	if (a != 101) {
X		printf("test%d FAIL\n",i);
X	}
X	printf("test%d ok\n",i);
X}
X
X/*
X */
X
Xt5(j)
Xint j;
X{
X	register int i;
X	for(i=0; i < 10; i++) {
X		switch(insw(i)) {
X		case '0':
X			if (foo(i,i) != 0) break;
X			if (i != 0) break;
X			continue;
X		case '1':
X			if (i != 1) break;
X			if (foo(i,i) != 2) break;
X			continue;
X		case '2':
X			if (foo(i,i) != 4) break;
X			if (i != 2) break;
X			continue;
X		case '3':
X			if (foo(i,i) != 6) break;
X			if (i != 3) break;
X			continue;
X		case '4':
X			if (i != 4) break;
X			if (foo(i,i) != 8) break;
X			continue;
X		case '5':
X			if (foo(i,i) != 10) break;
X			if (i != 5) break;
X			continue;
X		case '6':
X			if (foo(i,i) != 12) break;
X			if (i != 6) break;
X			continue;
X		case '7':
X			if (i != 7) break;
X			if (foo(i,i) != 14) break;
X			continue;
X		case '8':
X			if (foo(i,i) != 16) break;
X			if (i != 8) break;
X			continue;
X		case '9':
X			if (i != 9) break;
X			continue;
X		}
X		printf("test5 FAIL\n");
X		return;
X	}
X	printf("test5 ok\n");
X}
X
X/*
X * inlines with typedefs and pointer return types
X */
X
Xt6(i)
Xint i;
X{
X	char buf[20];
X	cptr p;
X
X	p = boff('c',buf);
X	if (p != &buf[1] || buf[0] != 'c') {
X		printf("test6 FAIL\n");
X	}
X	p = boff('b',p);
X	if (p != &buf[2] || buf[1] != 'b') {
X		printf("test6 FAIL\n");
X	}
X	p = boff2('d',buf);
X	if (p != &buf[1] || buf[0] != 'd') {
X		printf("test6 FAIL\n");
X	}
X	p = boff2('e',p);
X	if (p != &buf[2] || buf[1] != 'e') {
X		printf("test6 FAIL\n");
X	}
X	printf("test6 ok\n");
X}
X
X/*
X * inlines with looping structures inside
X */
X
Xt7(i)
Xint i;
X{
X	if (biff(1) != 1) {
X		printf("test7 FAIL\n");
X	}
X	if (1) biff(1);
X	if (1) nil();
X	else printf("test7 FAIL\n");
X	printf("test7 ok\n");
X}
X
Xt8(i)
Xint i;
X{
X	if (fp() != nil) {
X		printf("test8 FAIL\n");
X		return;
X	}
X	printf("test8 ok\n");
X}
X
X/*
X * inlines with structure and structure pointer returns
X */
X
Xt9(j)
Xint j;
X{
X	struct str z;
X	struct str *zp, *zp2;
X	int i;
X
X	z = bipp(1,100,3000);
X	if ((z.a != 1) || (z.b != 100) || (z.c != 3000)) {
X		printf("test9 FAIL\n");
X		return;
X	}
X	z = bipp(foo(100,bar(5,4)), z.c, z.b);
X	if ((z.a != 101) || (z.b != 3000) || (z.c != 100)) {
X		printf("test9 FAIL\n");
X		return;
X	}
X/****************
X	i = bipp(1,2,3).a;
X	if (i != 1) {
X		printf("test9 FAIL\n");
X		return;
X	}
X*************/
X	zp = &z;
X	i = bupp(&z,1,2,3)->a;
X	if (i != 1) {
X		printf("test9 FAIL\n");
X		return;
X	}
X	if (zp != bupp(zp,1,2,3)) {
X		printf("test9 FAIL\n");
X		return;
X	}
X	printf("test 9 ok\n");
X}
X
X
X/* special syntax check for function pointer returns */
X
X/* declare fp as function returning pointer to function returning int */
Xint (*fp3())() { return nil; }
X
X/* declare fp as function returning pointer to function returning int */
Xinline int (*fp2())() { return nil; }
X
X/* declare fp as function returning pointer to function returning pointer
X * to function returning int */
Xinline int (*(*fp1())())() { return fp3; }
X
X
Xfpt1() {
X
X/* declare fp as pointer to function returning pointer to function
X * returning int
X */
X	int (*(*fx)())();
X 
X	fx = fp1();
X}
X
X/***/
X
X/* declare fp as pointer to function returning int */
Xfpt2() {
X
X	int (*fx)();
X
X	fx = fp2();
X}
X
X/* check expression rewriting cases */
X
Xt10(n)
Xint n;
X{
X	int i = 0;
X	int j;
X
X	while (i < foo(5,5)) {
X		if (i < 0 || i > 10) {
X			printf("test10 FAIL\n");
X			return;
X		}
X		i = foo(i,1);
X		j = foo(1,2);
X		if (j != 3) {
X			printf("test10 FAIL\n");
X			return;
X		}
X	}
X
X	for (i = foo(5,5); i > 0; i--) {
X		if (i < 0 || i > 10) {
X			printf("test10 FAIL\n");
X			return;
X		}
X		j = foo(1,2);
X		if (j != 3) {
X			printf("test10 FAIL\n");
X			return;
X		}
X	}
X	printf("test10 ok\n");
X}
X
X/*
X * side-effect tests
X */
X
Xt11(n)
Xint n;
X{
X	register int i;
X
X	effect = 0;
X
X	if (effect == 1 && (side_effect(1) == 0)) {
X		printf("test11 FAIL\n");
X		return;
X	}
X
X	/* effect should still be 0 */
X
X	if (effect == 0 || (side_effect(1) == 1)) {
X		nil();
X	}
X
X	/* effect should still be 0 */
X
X	if (effect != 0) {
X		printf("test11 FAIL\n");
X		return;
X	}
X
X	i = (side_effect(1) ? 100 : 200);	/* assert i == 200 */
X						/* assert effect == 1 */
X
X	if (i != 200) {
X		printf("test11 FAIL\n");
X		return;
X	}
X
X	/* a non-expansion case */
X	i = (effect ? side_effect(100) : side_effect(200));
X						/* assert i == 1 */
X
X	if (i != 1) {
X		printf("test11 FAIL\n");
X		return;
X	}
X
X	if (effect != 100) {
X		printf("test11 FAIL\n");
X		return;
X	}
X
X	/* should have a comma-operator test, but it breaks now */
X
X	printf("test11 ok\n");
X}
X
X/*
X * more side-effect tests
X */
X
Xt12(n)
Xint n;
X{
X	int i,j,k,l;
X	struct str b;
X
X	/* might cause syntax errors, might return wrong value */
X	i = swaparg(1,2);
X	if (i != 3) {
X		printf("test12 FAIL\n");
X		return;
X	}
X	i = 100;
X	j = 200;
X	if (swaparg(i,j) != 300 || i != 100 || j != 200) {
X		printf("test12 FAIL\n");
X		return;
X	}
X	for (i = 0;  i < 3; i++) {
X		j = i;
X		b = modarg(i,b);
X		if (i != j) {
X			printf("test12 FAIL\n");
X			return;
X		}
X		if (i == 2) {
X			if (b.a != 6 || j != 2) {
X				printf("test12 FAIL\n");
X				return;
X			} 
X		}
X	}
X	printf("test12 ok\n");
X}
X
Xt13(n)
Xint n;
X{
X	register int i,j,k;
X
X	for (i = 0; i < 5; i++) {
X		if (i == 1) goto i2;
X	     i1:
X		j = foo(i,100);
X		if (i == 2) {
X	     i2:	k = foo(i,200);
X			if (i > 1 && j != i+100) { printf("test 13 FAIL\n"); return;}
X			goto i4;
X		}
X		if (i == 3) {
X			foo(i,300);
X	     i3 /* comment */ :
X			if (j != i+100) { printf("test 13 FAIL\n"); return;}
X			continue;
X		}
X		if (i == 4) {
X			if (j != i+100) { printf("test 13 FAIL\n"); return;}
X			k = foo(i,400);
X	     i4:
X			if (i == 2 && k != 202) { printf("test 13 FAIL\n"); return; }
X			if (i == 4 && k != 404) { printf("test 13 FAIL\n"); return; }
X			k = foo(i,500);
X			continue;
X		}
X		k = foo(i,600);
X		j = 0;
X	}
X	printf("test13 ok\n");
X}
X
Xint var = 0;
X
Xinline evar() {
X	return(var);
X}
X
Xinline mvar(x) {
X	var = x;
X}
X 
Xt14(n)
Xint n;
X{
X	int var = 1;	/* hide outer def'n */
X
X	if (evar() != 0) { printf("test14 FAIL\n"); return;}
X	if (var != 1) { printf("test14 FAIL\n"); return;}
X	mvar(100);
X	if (var != 1) { printf("test14 FAIL\n"); return;}
X	if (evar() != 100) { printf("test14 FAIL\n"); return;}
X	printf("test14 ok\n");
X}
X
Xt15(i,var)
Xint i;
Xint var;
X{
X	int a,b,c;
X
X	mvar(-100);
X
X	a = 1;
X	b = 2;
X	c = 3;
X
X	{
X		int a,b;
X
X		a = 100;
X		b = 200;
X
X		c = foo(a,b);
X	}
X
X	if (a != 1 || b != 2 || c != 300) { printf("test15 FAIL\n"); return; }
X
X	c = var;
X	{
X		int var;
X
X		var = 1000;
X
X		{
X			cptr var, a, b, c;
X	
X			a = "-1";
X			b = "-2";
X			c = "-3";
X			var = "-4";
X			if (evar() != -100) { printf("test15 FAIL\n"); return;}
X		}
X
X		if (evar() != -100) { printf("test15 FAIL\n"); return;}
X	}
X	if (var != c) { printf("test15 FAIL\n"); return; }
X	if (evar() != -100) { printf("test15 FAIL\n"); return;}
X	printf("test15 ok\n");
X}
X
Xt16(n)
Xint n;
X{
X	char *s = "foo";
X
X	if (hardcase1(0,1) != 1) { printf("test16 FAIL\n"); return;}
X	while (1 && (hardcase1(0,1) != 1)) printf("test16 FAIL\n");
X	s = hardcase2("foo",1,0);
X	printf("test16 ok\n");
X}
X
Xt17(n)
Xint n;
X{
X	int x = 1;
X
X	if (x && expr1(1,0) != 0) {printf("test17 FAIL(1)\n"); return;}
X	if (x && expr1(0,1) != 1) {printf("test17 FAIL(2)\n"); return;}
X	if (x && expr1(0,100) != 2) {printf("test17 FAIL(3)\n"); return;}
X	if (x && expr1(0,0) != 3) {printf("test17 FAIL(4)\n"); return;}
X	if (x && expr2(1,0) != 1) {printf("test17 FAIL(5)\n"); return;}
X	if (x && expr2(0,1) != 201) {printf("test17 FAIL(6)\n"); return;}
X	if (x && expr2(0,0) != 500) {printf("test17 FAIL(7)\n"); return;}
X	printf("test17 ok\n");
X}
X
Xt18(n)
Xint n;
X{
X	int i,j;
X
X	i = 0;
XL1:
X	j = labs(i);
X	if (j != i) {printf("test18 FAIL\n"); return; }
X	i++;
X	if (i > 10) goto L2;
X	goto L1;
XL2:
X	printf("test18 ok\n");
X}
X
\Rogue\Monster\
else
  echo "will not over write ./test.c"
fi
chmod 444 ./test.c
if [ `wc -c ./test.c | awk '{printf $1}'` -ne 11843 ]
then
echo `wc -c ./test.c | awk '{print "Got " $1 ", Expected " 11843}'`
fi
if `test ! -s ./test2.c`
then
echo "writing ./test2.c"
sed 's/^X//' > ./test2.c << '\Rogue\Monster\'
X
X/* test cases for 'inline' */
X
X/* $Header: test2.c,v 1.2 87/06/24 13:06:48 mcg Rel $ */
X
X
Xm() {
X	register int x,y,z;
X
X	x = foo(x++,y++);
X}
X
Xmain() {
X	t1(1);
X	t2(2);
X	t3(3);
X	t4(4);
X	t5(5);
X	t6(6);
X	t7(7);
X	t8(8);
X	t9(9);
X	t10(10);
X	t11(11);
X	t12(12);
X	t13(13);
X	t14(14);
X	t15(15,50);
X	t16(16);
X	t17(17);
X	t18(18);
X	return(0);
X}
X
X/*
X * basic expansion of single inline
X */
X
Xt1(i)
Xint i;
X{
X	int a;
X
X	printf("test%d:\n",i);
X	a = foo(1,2);
X	if (a == 3) {
X		printf("test%d ok\n",i);
X	} else {
X		printf("test%d FAIL\n",i);
X	}
X}
X
X/*
X * expansion of multiple inlines in single expression
X */
X
Xt2(i)
Xint i;
X{
X	int a;
X
X	printf("test%d:\n",i);
X	a = foo(1,2) + foo(3,4);
X	if (a == 10) {
X		printf("test%d ok\n",i);
X	} else {
X		printf("test%d FAIL\n",i);
X	}
X}
X
X/*
X * expansion of inlines in various styles of if() statement
X * - check parsing of if compound statement
X */
X
Xt3(i)
Xint i;
X{
X	printf("test%d:\n",i);
X	if (foo(1,2) != 3) {
X		printf("test%d FAIL\n",i); 
X		return;
X	}
X
X	if (foo(1,2) == 3) {
X		;
X	} else {
X		printf("test%d FAIL\n"); 
X		return;
X	}
X
X	if (!foo(1,2)) printf("test%d FAIL\n",i);
X
X	if (foo(1,2) == 3) nil(); else printf("test%d FAIL\n",i);
X
X	if (foo(1,2) == 3) nil(); else {
X		printf("test%d FAIL\n",i);
X	}
X
X	if (foo(1,2) == 3) {
X		printf("test%d ok\n",i);
X	} else
X		printf("test%d FAIL\n",i);
X}
X
X/*
X * inlines as arguments to other inlines
X */
X
Xt4(i)
Xint i;
X{
X	register int a;
X
X	printf("test%d:\n",i);
X	a = foo(foo(1,2),2);
X	if (a != 5) {
X		printf("test%d FAIL\n",i);
X	}
X
X	a = foo(100,bar(5,4));
X	if (a != 101) {
X		printf("test%d FAIL\n",i);
X	}
X	printf("test%d ok\n",i);
X}
X
X/*
X */
X
Xt5(j)
Xint j;
X{
X	register int i;
X	for(i=0; i < 10; i++) {
X		switch(insw(i)) {
X		case '0':
X			if (foo(i,i) != 0) break;
X			if (i != 0) break;
X			continue;
X		case '1':
X			if (i != 1) break;
X			if (foo(i,i) != 2) break;
X			continue;
X		case '2':
X			if (foo(i,i) != 4) break;
X			if (i != 2) break;
X			continue;
X		case '3':
X			if (foo(i,i) != 6) break;
X			if (i != 3) break;
X			continue;
X		case '4':
X			if (i != 4) break;
X			if (foo(i,i) != 8) break;
X			continue;
X		case '5':
X			if (foo(i,i) != 10) break;
X			if (i != 5) break;
X			continue;
X		case '6':
X			if (foo(i,i) != 12) break;
X			if (i != 6) break;
X			continue;
X		case '7':
X			if (i != 7) break;
X			if (foo(i,i) != 14) break;
X			continue;
X		case '8':
X			if (foo(i,i) != 16) break;
X			if (i != 8) break;
X			continue;
X		case '9':
X			if (i != 9) break;
X			continue;
X		}
X		printf("test5 FAIL\n");
X		return;
X	}
X	printf("test5 ok\n");
X}
X
X/*
X * inlines with typedefs and pointer return types
X */
X
Xt6(i)
Xint i;
X{
X	char buf[20];
X	cptr p;
X
X	p = boff('c',buf);
X	if (p != &buf[1] || buf[0] != 'c') {
X		printf("test6 FAIL\n");
X	}
X	p = boff('b',p);
X	if (p != &buf[2] || buf[1] != 'b') {
X		printf("test6 FAIL\n");
X	}
X	p = boff2('d',buf);
X	if (p != &buf[1] || buf[0] != 'd') {
X		printf("test6 FAIL\n");
X	}
X	p = boff2('e',p);
X	if (p != &buf[2] || buf[1] != 'e') {
X		printf("test6 FAIL\n");
X	}
X	printf("test6 ok\n");
X}
X
X/*
X * inlines with looping structures inside
X */
X
Xt7(i)
Xint i;
X{
X	if (biff(1) != 1) {
X		printf("test7 FAIL\n");
X	}
X	if (1) biff(1);
X	if (1) nil();
X	else printf("test7 FAIL\n");
X	printf("test7 ok\n");
X}
X
Xt8(i)
Xint i;
X{
X	if (fp() != nil) {
X		printf("test8 FAIL\n");
X		return;
X	}
X	printf("test8 ok\n");
X}
X
X/*
X * inlines with structure and structure pointer returns
X */
X
Xt9(j)
Xint j;
X{
X	struct str z;
X	struct str *zp, *zp2;
X	int i;
X
X	z = bipp(1,100,3000);
X	if ((z.a != 1) || (z.b != 100) || (z.c != 3000)) {
X		printf("test9 FAIL\n");
X		return;
X	}
X	z = bipp(foo(100,bar(5,4)), z.c, z.b);
X	if ((z.a != 101) || (z.b != 3000) || (z.c != 100)) {
X		printf("test9 FAIL\n");
X		return;
X	}
X/****************
X	i = bipp(1,2,3).a;
X	if (i != 1) {
X		printf("test9 FAIL\n");
X		return;
X	}
X*************/
X	zp = &z;
X	i = bupp(&z,1,2,3)->a;
X	if (i != 1) {
X		printf("test9 FAIL\n");
X		return;
X	}
X	if (zp != bupp(zp,1,2,3)) {
X		printf("test9 FAIL\n");
X		return;
X	}
X	printf("test 9 ok\n");
X}
X
X
X/* special syntax check for function pointer returns */
X
X/* declare fp as function returning pointer to function returning int */
Xint (*fp3())() { return nil; }
X
X/* declare fp as function returning pointer to function returning int */
Xinline int (*fp2())() { return nil; }
X
X/* declare fp as function returning pointer to function returning pointer
X * to function returning int */
Xinline int (*(*fp1())())() { return fp3; }
X
X
Xfpt1() {
X
X/* declare fp as pointer to function returning pointer to function
X * returning int
X */
X	int (*(*fx)())();
X 
X	fx = fp1();
X}
X
X/***/
X
X/* declare fp as pointer to function returning int */
Xfpt2() {
X
X	int (*fx)();
X
X	fx = fp2();
X}
X
X/* check expression rewriting cases */
X
Xt10(n)
Xint n;
X{
X	int i = 0;
X	int j;
X
X	while (i < foo(5,5)) {
X		if (i < 0 || i > 10) {
X			printf("test10 FAIL\n");
X			return;
X		}
X		i = foo(i,1);
X		j = foo(1,2);
X		if (j != 3) {
X			printf("test10 FAIL\n");
X			return;
X		}
X	}
X
X	for (i = foo(5,5); i > 0; i--) {
X		if (i < 0 || i > 10) {
X			printf("test10 FAIL\n");
X			return;
X		}
X		j = foo(1,2);
X		if (j != 3) {
X			printf("test10 FAIL\n");
X			return;
X		}
X	}
X	printf("test10 ok\n");
X}
X
X/*
X * side-effect tests
X */
X
Xt11(n)
Xint n;
X{
X	register int i;
X
X	effect = 0;
X
X	if (effect == 1 && (side_effect(1) == 0)) {
X		printf("test11 FAIL\n");
X		return;
X	}
X
X	/* effect should still be 0 */
X
X	if (effect == 0 || (side_effect(1) == 1)) {
X		nil();
X	}
X
X	/* effect should still be 0 */
X
X	if (effect != 0) {
X		printf("test11 FAIL\n");
X		return;
X	}
X
X	i = (side_effect(1) ? 100 : 200);	/* assert i == 200 */
X						/* assert effect == 1 */
X
X	if (i != 200) {
X		printf("test11 FAIL\n");
X		return;
X	}
X
X	/* a non-expansion case */
X	i = (effect ? side_effect(100) : side_effect(200));
X						/* assert i == 1 */
X
X	if (i != 1) {
X		printf("test11 FAIL\n");
X		return;
X	}
X
X	if (effect != 100) {
X		printf("test11 FAIL\n");
X		return;
X	}
X
X	/* should have a comma-operator test, but it breaks now */
X
X	printf("test11 ok\n");
X}
X
X/*
X * more side-effect tests
X */
X
Xt12(n)
Xint n;
X{
X	int i,j,k,l;
X	struct str b;
X
X	/* might cause syntax errors, might return wrong value */
X	i = swaparg(1,2);
X	if (i != 3) {
X		printf("test12 FAIL\n");
X		return;
X	}
X	i = 100;
X	j = 200;
X	if (swaparg(i,j) != 300 || i != 100 || j != 200) {
X		printf("test12 FAIL\n");
X		return;
X	}
X	for (i = 0;  i < 3; i++) {
X		j = i;
X		b = modarg(i,b);
X		if (i != j) {
X			printf("test12 FAIL\n");
X			return;
X		}
X		if (i == 2) {
X			if (b.a != 6 || j != 2) {
X				printf("test12 FAIL\n");
X				return;
X			} 
X		}
X	}
X	printf("test12 ok\n");
X}
X
Xt13(n)
Xint n;
X{
X	register int i,j,k;
X
X	for (i = 0; i < 5; i++) {
X		if (i == 1) goto i2;
X	     i1:
X		j = foo(i,100);
X		if (i == 2) {
X	     i2:	k = foo(i,200);
X			if (i > 1 && j != i+100) { printf("test 13 FAIL\n"); return;}
X			goto i4;
X		}
X		if (i == 3) {
X			foo(i,300);
X	     i3 /* comment */ :
X			if (j != i+100) { printf("test 13 FAIL\n"); return;}
X			continue;
X		}
X		if (i == 4) {
X			if (j != i+100) { printf("test 13 FAIL\n"); return;}
X			k = foo(i,400);
X	     i4:
X			if (i == 2 && k != 202) { printf("test 13 FAIL\n"); return; }
X			if (i == 4 && k != 404) { printf("test 13 FAIL\n"); return; }
X			k = foo(i,500);
X			continue;
X		}
X		k = foo(i,600);
X		j = 0;
X	}
X	printf("test13 ok\n");
X}
X
Xint var = 0;
X
Xinline evar() {
X	return(var);
X}
X
Xinline mvar(x) {
X	var = x;
X}
X 
Xt14(n)
Xint n;
X{
X	int var = 1;	/* hide outer def'n */
X
X	if (evar() != 0) { printf("test14 FAIL\n"); return;}
X	if (var != 1) { printf("test14 FAIL\n"); return;}
X	mvar(100);
X	if (var != 1) { printf("test14 FAIL\n"); return;}
X	if (evar() != 100) { printf("test14 FAIL\n"); return;}
X	printf("test14 ok\n");
X}
X
Xt15(i,var)
Xint i;
Xint var;
X{
X	int a,b,c;
X
X	mvar(-100);
X
X	a = 1;
X	b = 2;
X	c = 3;
X
X	{
X		int a,b;
X
X		a = 100;
X		b = 200;
X
X		c = foo(a,b);
X	}
X
X	if (a != 1 || b != 2 || c != 300) { printf("test15 FAIL\n"); return; }
X
X	c = var;
X	{
X		int var;
X
X		var = 1000;
X
X		{
X			cptr var, a, b, c;
X	
X			a = "-1";
X			b = "-2";
X			c = "-3";
X			var = "-4";
X			if (evar() != -100) { printf("test15 FAIL\n"); return;}
X		}
X
X		if (evar() != -100) { printf("test15 FAIL\n"); return;}
X	}
X	if (var != c) { printf("test15 FAIL\n"); return; }
X	if (evar() != -100) { printf("test15 FAIL\n"); return;}
X	printf("test15 ok\n");
X}
X
Xt16(n)
Xint n;
X{
X	char *s = "foo";
X
X	if (hardcase1(0,1) != 1) { printf("test16 FAIL\n"); return;}
X	while (1 && (hardcase1(0,1) != 1)) printf("test16 FAIL\n");
X	s = hardcase2("foo",1,0);
X	printf("test16 ok\n");
X}
X
Xt17(n)
Xint n;
X{
X	int x = 1;
X
X	if (x && expr1(1,0) != 0) {printf("test17 FAIL(1)\n"); return;}
X	if (x && expr1(0,1) != 1) {printf("test17 FAIL(2)\n"); return;}
X	if (x && expr1(0,100) != 2) {printf("test17 FAIL(3)\n"); return;}
X	if (x && expr1(0,0) != 3) {printf("test17 FAIL(4)\n"); return;}
X	if (x && expr2(1,0) != 1) {printf("test17 FAIL(5)\n"); return;}
X	if (x && expr2(0,1) != 201) {printf("test17 FAIL(6)\n"); return;}
X	if (x && expr2(0,0) != 500) {printf("test17 FAIL(7)\n"); return;}
X	printf("test17 ok\n");
X}
X
Xt18(n)
Xint n;
X{
X	int i,j;
X
X	i = 0;
XL1:
X	j = labs(i);
X	if (j != i) {printf("test18 FAIL\n"); return; }
X	i++;
X	if (i > 10) goto L2;
X	goto L1;
XL2:
X	printf("test18 ok\n");
X}
X
X/* simple inline */
Xinline int foo(a,b) {
X	register int x = 0;
X
X	printf("foo(%d, %d)\n", a,b);
X	return(a+b);
X}
Xinline int bar(x,y) {
X	register int a;
X
X	a = 0;
X	printf("bar(%d, %d)\n", x,y);
X	return(x-y);
X}
X/* inline with some control flow */
Xinline biff(a) {
X	while(1) return a;
X}
X
X/* inline with a switch */
Xinline insw(i)
Xint i;
X{
X	switch(i) {
X	case 0:	return('0');
X	case 1: return('1');
X	case 2: return('2');
X	case 3: return('3');
X	case 4: return(foo(i,'0'));
X	case 5: return('5');
X	case 6: return('6');
X	case 7: return(foo(i,'0'));
X	case 8: return('8');
X	case 9: return('9');
X	}
X	return(0);
X}
X
Xtypedef char *cptr;
X
Xinline barf() {
X	printf("!!!\n");
X}
X
X/* inline returning a typedef */
Xinline cptr
Xboff(c,s)
Xchar c;
Xcptr s;
X{
X	s[0] = c;
X	return(&s[1]);
X}
X
X/* inline returning a pointer type */
Xinline char *
Xboff2(c,s)
Xchar c;
Xcptr s;
X{
X	s[0] = c;
X	return(&s[1]);
X}
X
Xstruct str {
X	int a;
X	int b;
X	int c;
X};
X
X/* inline returning a structure */
Xinline struct str bipp(a,b,c)
Xint a, b, c;
X{
X	struct str x;
X
X	x.a = a;
X	x.b = b;
X	x.c = c;
X	return(x);
X}
X
X/* inline returning a structure pointer */
Xinline struct str *bupp(z,a,b,c)
Xregister struct str *z;
Xregister int a,b,c;
X{
X	z->a = a;
X	z->b = b;
X	z->c = c;
X	return(z);
X}
X
Xnil(){}
X
X/* inline returning function pointer */
Xinline int (*fp())()
X{
X	return(nil);
X}
X
Xint effect = 0;
X
Xinline int side_effect(a)
Xint a;
X{
X	int old;
X
X	old = effect;
X	effect = a;
X
X	return(old);
X}
X
X/* should have no effect on arguments */
Xinline int swaparg(a,b)
X{
X	int tmp;
X
X	tmp = a;
X	a = b;
X	b = tmp;
X
X	return(a+b);
X}
X
Xinline struct str modarg(a,b)
Xint a;
Xstruct str b;	/* struct arg */
X{
X	switch(a) {
X	case 0:
X		a = 1;
X		b.a = 1;
X		break;
X	case 1:
X		a >>= 1;
X		a <<= 1;
X		b.a = a;
X		break;
X	case 2:
X		a *= 3;
X		b.a = a;
X		break;
X	}
X	return(b);
X}
X
Xinline hardcase1(a,b)
Xint a,b;
X{
X	{ ; }
X	if (a);
X	{{}}
X	if (a) { } else ;
X	return(b);
X}
Xinline char *
Xhardcase2(a,b,c)
Xchar *a;
Xint b,c;
X{
X	char *s = "foo", c = 'c';
X	int x = b;
X
X	if (a) return(s);
X	else {
X		if (b) return(a+c);
X	}
X	return(a+c);
X}
X
Xinline expr1(a,b)
Xint a,b;
X{
X	int x = 0;
X
X	if (foo(0,a+b) == 100) return x+2;	/* a+b == 100, ret = 2 */
X	if (foo(50,50) == 100 && a) return x;	/* a != 0, return = 0 */
X	if (foo(100,0) == 100 && b) return x+1;	/* a == 0 && b != 0, ret = 1 */
X	return x+3;				/* ret = 3 */
X}
X
Xinline expr2(a,b)
Xint a,b;
X{
X	register int x = 0, y = 1;
X
X	if (a) {
X		return(x+y);	/* a != 0, return = 1 */
X	} else {
X		register int x = 100, y = 101;
X
X		if (b) {
X			return(x+y);	/* a == 0 && b != 0, return = 201 */
X		} else {
X			register int x = 200, y = 300;
X
X			return(x+y);	/* a == 0 && b == 0, return = 500 */
X		}
X	}
X}
X
X
Xinline labs(i)
Xint i;
X{
X	if (i == 1) goto L1;
X	if (i == 2) goto L2;
X	if (i == 3) goto L3;
X	if (i == 4) goto L4;
X	goto L5;
XL6:
X	return(i);
X
XL1:	i++; return(1);
XL2:	if (i == 2) return(2);
XL3:	return(3);
XL4:	{
X	return(4);
X	}
XL5:	goto L6;
X}
\Rogue\Monster\
else
  echo "will not over write ./test2.c"
fi
chmod 444 ./test2.c
if [ `wc -c ./test2.c | awk '{printf $1}'` -ne 11844 ]
then
echo `wc -c ./test2.c | awk '{print "Got " $1 ", Expected " 11844}'`
fi
echo "Finished archive 1 of 3"
# if you want to concatenate archives, remove anything after this line
exit