PWB1/sys/source/s2/ratfor.a

eÿr.g_
ƒ’	¶Ü%{
extern int transfer;
extern	int	indent;
%}

%term	IF ELSE FOR WHILE BREAK NEXT 
%term	DIGITS DO
%term	GOK DEFINE INCLUDE
%term	REPEAT UNTIL
%term	RETURN
%term	SWITCH CASE DEFAULT
%%

statl	: statl  stat
	|
	;
stat	: if stat	={ indent--; outcont($1); }
	| ifelse stat	={ indent--; outcont($1+1); }
	| switch fullcase '}'	={ endsw($1, $2); }
	| while stat	={ whilestat($1); }
	| for stat	={ forstat($1); }
	| repeat stat UNTIL	={ untils($1,1); }
	| repeat stat		={ untils($1,0); }
	| BREAK	={ breakcode($1); }
	| NEXT		={ nextcode($1); }
	| do stat	={ dostat($1); }
	| GOK		={ gokcode($1); }
	| RETURN	={ retcode($1); }
	| ';'
	| '{' statl '}'
	| label stat
	| error		={ errcode($1); yyclearin; }
	;
switch	: sw '{'
	;
sw	: SWITCH	={ swcode(); }
	;
fullcase: caselist	={ $$ = 0; }
	| caselist defpart	={ $$ = 1; }
	;
caselist: casepart
	| caselist casepart
	;
defpart	: default statl
	;
default	: DEFAULT	={ getdefault(); }
	;
casepart: case statl
	;
case	: CASE	={ getcase(); }
	;
label	: DIGITS	={ transfer = 0; outcode($1); }
	;
if	: IF		={ ifcode($1); }
	;
ifelse	: if stat ELSE	={ elsecode($1); }
	;
while	: WHILE	={ whilecode($1); }
	;
for	: FOR		={ forcode($1); }
	;
repeat	: REPEAT	={ repcode($1); }
	;
do	: DO		={ docode($1); }
	;
%%
r.h_
ƒ’	¶”#include <stdio.h>
#include "y.tab.h"

#
#define	putbak(c)	*ip++ = c
/*	#define	getchr()	(ip>ibuf?*--ip: getc(infile[infptr]))	*/

#define	LET	1
#define	DIG	2
#define	CRAP	3
#define	COMMENT	'#'
#define	QUOTE	'"'

extern int	transfer;

#define	INDENT	3	/* indent delta */
#ifdef	gcos
#define	CONTFLD	6
#endif
#ifdef	unix
#define	CONTFLD	1
#endif
extern	int	contfld;	/* column for continuation char */
extern	int	contchar;
extern	int	dbg;
extern	int	yyval;
extern	int	*yypv;
extern	int	yylval;
extern	int	errorflag;

extern	char	comment[];	/* save input comments here */
extern	int	comptr;	/* next free slot in comment */
extern	int	printcom;	/* print comments, etc., if on */
extern	int	indent;	/* level of nesting for indenting */

extern	char	ibuf[];
extern	char	*ip;

extern	FILE	*outfil;	/* output file id */
extern	FILE	*infile[];
extern	char	*curfile[];
extern	int	infptr;
extern	int	linect[];

extern	char	fcname[];

extern	int	svargc;
extern	char	**svargv;

#define NULL 0
#define EOS 0
#define	HSHSIZ	101
struct	nlist {
	char	*name;
	char	*def;
	int	ydef;
	struct	nlist *next;
};

struct nlist	*lookup();
char	*install();
extern	char	*fcnloc;

extern	char	type[];
r1.ck
5Í	¶‘v#include "r.h"

#define	wasbreak	brkused[brkptr]==1 || brkused[brkptr]==3
#define	wasnext	brkused[brkptr]==2 || brkused[brkptr]==3

int	transfer	0;	/* 1 if just finished retrun, break, next */

char	fcname[10];
char	scrat[500];

int	brkptr	-1;
int	brkstk[10];	/* break label */
int	typestk[10];	/* type of loop construct */
int	brkused[10];	/* loop contains BREAK or NEXT */

int	forptr	0;
int	forstk[10];

repcode() {
	transfer = 0;
	outcont(0);
	putcom("repeat");
	yyval = genlab(3);
	indent++;
	outcont(yyval);
	brkstk[++brkptr] = yyval+1;
	typestk[brkptr] = REPEAT;
	brkused[brkptr] = 0;
}

untils(p1,un) int p1,un; {
	outnum(p1+1);
	outtab();
	if (un > 0) {
		outcode("if(.not.");
		balpar();
		outcode(")");
	}
	transfer = 0;
	outgoto(p1);
	indent--;
	if (wasbreak)
		outcont(p1+2);
	brkptr--;
}

ifcode(p1) int p1; {
	transfer = 0;
	outtab();
	outcode("if(.not.");
	balpar();
	outcode(")");
	outgoto(yyval=genlab(2));
	indent++;
}

elsecode(p1) {
	outgoto(p1+1);
	indent--;
	putcom("else");
	indent++;
	outcont(p1);
}

whilecode(p1) int p1; {
	transfer = 0;
	outcont(0);
	putcom("while");
	brkstk[++brkptr] = yyval = genlab(2);
	typestk[brkptr] = WHILE;
	brkused[brkptr] = 0;
	outnum(yyval);
	outtab();
	outcode("if(.not.");
	balpar();
	outcode(")");
	outgoto(yyval+1);
	indent++;
}

whilestat(p1) int p1; {
	outgoto(p1);
	indent--;
	putcom("endwhile");
	outcont(p1+1);
	brkptr--;
}

balpar() {
	register c, lpar;
	while ((c=gtok(scrat)) == ' ' || c == '\t')
		;
	if (c != '(') {
		error("missing left paren");
		return;
	}
	outcode(scrat);
	lpar = 1;
	do {
		c = gtok(scrat);
		if (c==';' || c=='{' || c=='}' || c==EOF) {
			pbstr(scrat);
			break;
		}
		if (c=='(')
			lpar++;
		else if (c==')')
			lpar--;
		else if (c == '\n') {
			while ((c = gtok(scrat)) == ' ' || c=='\t' || c=='\n')
				;
			pbstr(scrat);
			continue;
		}
		else if (c == '=' && scrat[1] == '\0')
			error("assigment inside conditional");
		outcode(scrat);
	} while (lpar > 0);
}

int	labval	23000;

genlab(n){
	labval =+ n;
	return(labval-n);
}

gokcode(p1) char *p1; {
	transfer = 0;
	outtab();
	outcode(p1);
	eatup();
	outdon();
}

eatup() {
	int i, t, lpar;
	char temp[100];
	lpar = 0;
	do {
		if ((t = gtok(scrat)) == ';' || t == '\n')
			break;
		if (t == '{' || t == '}' || t == EOF) {
			pbstr(scrat);
			break;
		}
		if (t == ',' || t == '+' || t == '-' || t == '*' || t == '('
		  || t == '&' || t == '|' || t == '=') {
			while (gtok(temp) == '\n')
				;
			pbstr(temp);
		}
		if (t == '(')
			lpar++;
		else if (t==')') {
			lpar--;
			if (lpar < 0) {
				error("missing left paren");
				return(1);
			}
		}
		outcode(scrat);
	} while (lpar >= 0);
	if (lpar > 0) {
		error("missing right paren");
		return(1);
	}
	return(0);
}

forcode(){
	int lpar, t;
	char *calloc(), *ps, *qs;

	transfer = 0;
	outcont(0);
	putcom("for");
	yyval = genlab(3);
	brkstk[++brkptr] = yyval+1;
	typestk[brkptr] = FOR;
	brkused[brkptr] = 0;
	forstk[forptr++] = calloc(1, 1);
	if ((t = gnbtok(scrat)) != '(') {
		error("missing left paren in FOR");
		pbstr(scrat);
		return;
	}
	if (gnbtok(scrat) != ';') {	/* real init clause */
		pbstr(scrat);
		outtab();
		if (eatup() > 0) {
			error("illegal FOR clause");
			return;
		}
		outdon();
	}
	if (gnbtok(scrat) == ';')	/* empty condition */
		outcont(yyval);
	else {	/* non-empty condition */
		pbstr(scrat);
		outnum(yyval);
		outtab();
		outcode("if(.not.(");
		for (lpar=0; lpar >= 0;) {
			if ((t = gnbtok(scrat)) == ';')
				break;
			if (t == '(')
				lpar++;
			else if (t == ')') {
				lpar--;
				if (lpar < 0) {
					error("missing left paren in FOR clause");
					return;
				}
			}
			if (t != '\n')
				outcode(scrat);
		}
		outcode("))");
		outgoto(yyval+2);
		if (lpar < 0)
			error("invalid FOR clause");
	}
	ps = scrat;
	for (lpar=0; lpar >= 0;) {
		if ((t = gtok(ps)) == '(')
			lpar++;
		else if (t == ')')
			lpar--;
		if (lpar >= 0 && t != '\n')
			while(*ps)
				ps++;
	}
	*ps = '\0';
	qs = forstk[forptr-1] = calloc(ps-scrat+1,1);
	ps = scrat;
	while (*qs++ = *ps++)
		;
	indent++;
}

forstat(p1) int p1; {
	char *bp, *q;
	int i;
	bp = forstk[--forptr];
	if (wasnext)
		outnum(p1+1);
	if (nonblank(bp)){
		outtab();
		outcode(bp);
		outdon();
	}
	outgoto(p1);
	indent--;
	putcom("endfor");
	outcont(p1+2);
	for (q=bp; *q++;);
	cfree(bp, q-bp, 1);
	brkptr--;
}

retcode(p1) int p1; {
	register c;
	if ((c = gnbtok(scrat)) != '\n' && c != ';' && c != '}') {
		pbstr(scrat);
		outtab();
		outcode(fcname);
		outcode(" = ");
		eatup();
		outdon();
	}
	else if (c == '}')
		pbstr(scrat);
	outtab();
	outcode("return");
	outdon();
	transfer = 1;
}

docode(p1) char *p1; {
	transfer = 0;
	outtab();
	outcode("do ");
	yyval = genlab(2);
	brkstk[++brkptr] = yyval;
	typestk[brkptr] = DO;
	brkused[brkptr] = 0;
	outnum(yyval);
	eatup();
	outdon();
	indent++;
}

dostat(p1) int p1; {
	outcont(p1);
	indent--;
	if (wasbreak)
		outcont(p1+1);
	brkptr--;
}

#ifdef	gcos
#define	atoi(s)	(*s-'0')	/* crude!!! */
#endif

breakcode(p1) int p1; {
	int level, t;

	level = 0;
	if ((t=gnbtok(scrat)) == DIG)
		level = atoi(scrat) - 1;
	else if (t != ';')
		pbstr(scrat);
	if (brkptr-level < 0)
		error("illegal BREAK");
	else {
		outgoto(brkstk[brkptr-level]+1);
		brkused[brkptr-level] =| 1;
	}
	transfer = 1;
}

nextcode(p1) int p1; {
	int level, t;

	level = 0;
	if ((t=gnbtok(scrat)) == DIG)
		level = atoi(scrat) - 1;
	else if (t != ';')
		pbstr(scrat);
	if (brkptr-level < 0)
		error("illegal NEXT");
	else {
		outgoto(brkstk[brkptr-level]);
		brkused[brkptr-level] =| 2;
	}
	transfer = 1;
}

nonblank(s) char *s; {
	int c;
	while (c = *s++)
		if (c!=' ' && c!='\t' && c!='\n')
			return(1);
	return(0);
}

int	errorflag	0;

error(s1, s2) char *s1, *s2; {
	if (errorflag == 0)
		fprintf(stderr, "******\n");
	fprintf(stderr, "*****W ratfor: ");
	fprintf(stderr, "error at line %d, file %s: ",linect[infptr],curfile[infptr]);
	fprintf(stderr, s1,s2);
	fprintf(stderr, "\n");
	errorflag = 1;
}

errcode(p1) char *p1; {
	int c;
	if (errorflag == 0)
		fprintf(stderr, "******\n");
	fprintf(stderr, "*****F ratfor:");
	fprintf(stderr, "syntax error, line %d, file %s\n", linect[infptr], curfile[infptr]);
	while ((c=getchr())!=';' && c!='}' && c!='\n' && c!=EOF && c!='\0')
		;
	if (c == EOF || c == '\0')
		putbak(c);
	errorflag = 1;
}
r2.c_
…’	¶C#include "r.h"

char	outbuf[80];
int	outp	0;
int	cont	0;
int	contchar	'&';

char	comment[320];
int	comptr	0;
int	indent	0;

outdon() {
	outbuf[outp] = '\0';
	if (outp > 0)
		fprintf(outfil, "%s\n", outbuf);
	outp = cont = 0;
}

putcom(s) char *s; {
	if (printcom) {
		ptc('c');
		outtab();
		pts(s);
		outdon();
	}
}

outcode(p) char *p; {
	register c, c1, j;
	char *q;
	if (cont == 0 && comptr > 0)	/* flush comment if not on continuation */
		flushcom();
	while( (c = *p++) ){
		c1 = *p;
		if (type[c] == LET || type[c] == DIG) {
			pts(p-1);
			break;
		}
		switch(c){

		case '"': case '\'':
			j = 0;
			for (q=p; *q; q++) {
				if (*q == '\\')
					q++;
				j++;
			}
			if (outp+j+2 > 71)
				contcard();
			outnum(--j);
			ptc('h');
			while (*p != c) {
				if (*p == '\\')
					p++;
				ptc(*p++);
			}
			p++;
			break;
		case '$': case '\\':
			if (length(p-1)+outp > 71)
				contcard();
			if (c1 == '"' || c1 == '\'') {
				ptc(c1);
				p++;
			} else
				for (p--; *p; p++)
					ptc(*p);
			break;
		case '%':
			outp = 0;
			while (*p)
				ptc(*p++);
			break;
		case '>':
			if( c1=='=' ){
				pts(".ge."); p++;
			} else
				pts(".gt.");
			break;
		case '<':
			if( c1=='=' ){
				pts(".le."); p++;
			} else if( c1=='>' ){
				pts(".ne."); p++;
			} else
				pts(".lt.");
			break;
		case '=':
			if( c1=='=' ){
				pts(".eq."); p++;
			} else
				ptc('=');
			break;
		case '!': case '^':
			if( c1=='=' ){
				pts(".ne."); p++;
			} else
				pts(".not.");
			break;
		case '&':
			if( c1=='&' )
				p++;
			pts(".and.");
			break;
		case '|':
			if( c1=='|' )
				p++;
			pts(".or.");
			break;
		case '\t':
			outtab();
			break;
		case '\n':
			ptc(' ');
			break;
		default:
			ptc(c);
			break;
		}
	}
}

ptc(c) char c; {
	if( outp > 71 )
		contcard();
	outbuf[outp++] = c;
}

pts(s) char *s; {
	if (length(s)+outp > 71)
		contcard();
	while(*s)
		ptc(*s++);
}

contcard(){
	int n;
	outbuf[outp] = '\0';
	fprintf(outfil, "%s\n", outbuf);
	n = 6;
	if (printcom) {
		n =+ INDENT * indent + 1;
		if (n > 35) n = 35;
	}
	for( outp=0; outp<n; outbuf[outp++] = ' ' );
	outbuf[contfld-1] = contchar;
	cont++;
	if (cont > 19)
		error("more than 19 continuation cards");
}

outtab(){
	int n;
	n = 6;
	if (printcom) {
		n =+ INDENT * indent;
		if (n > 35) n = 35;
	}
	while (outp < n)
		ptc(' ');
}

outnum(n) int n; {
	int a;
	if( a = n/10 )
		outnum(a);
	ptc(n%10 + '0');
}

outcont(n) int n; {
	transfer = 0;
	if (n == 0 && outp == 0)
		return;
	if( n > 0 )
		outnum(n);
	outcode("\tcontinue");
	outdon();
}

outgoto(n) int n; {
	if (transfer != 0)
		return;
	outcode("\tgoto ");
	outnum(n);
	outdon();
}

flushcom() {
	int i, j;
	if (printcom == 0)
		comptr = 0;
	else if (cont == 0 && comptr > 0) {
		for (i=j=0; i < comptr; i++)
			if (comment[i] == '\n') {
				comment[i] = '\0';
				fprintf(outfil, "%s\n", &comment[j]);
				j = i + 1;
			}
		comptr = 0;
	}
}
	rio.c_
†’	¶ž#include "r.h"
#define	BUFSIZE	512
char	ibuf[BUFSIZE];
char	*ip ibuf;

char	type[] {
	0,	CRAP,	CRAP,	CRAP,	CRAP,	CRAP,	CRAP,	CRAP,
	CRAP,	'\t',	'\n',	CRAP,	CRAP,	CRAP,	CRAP,	CRAP,
	CRAP,	CRAP,	CRAP,	CRAP,	CRAP,	CRAP,	CRAP,	CRAP,
	CRAP,	CRAP,	CRAP,	CRAP,	CRAP,	CRAP,	CRAP,	CRAP,
	' ',	'!',	'"',	'#',	'$',	'%',	'&',	'\'',
	'(',	')',	'*',	'+',	',',	'-',	'.',	'/',
	DIG,	DIG,	DIG,	DIG,	DIG,	DIG,	DIG,	DIG,
	DIG,	DIG,	':',	';',	'<',	'=',	'>',	'?',
	'@',	LET,	LET,	LET,	LET,	LET,	LET,	LET,
	LET,	LET,	LET,	LET,	LET,	LET,	LET,	LET,
	LET,	LET,	LET,	LET,	LET,	LET,	LET,	LET,
	LET,	LET,	LET,	'[',	'\\',	']',	'^',	'_',
	'`',	LET,	LET,	LET,	LET,	LET,	LET,	LET,
	LET,	LET,	LET,	LET,	LET,	LET,	LET,	LET,
	LET,	LET,	LET,	LET,	LET,	LET,	LET,	LET,
	LET,	LET,	LET,	'{',	'|',	'}',	'~',	0,
};

gtok(s) char *s; {	/* get token into s */
	register c, t;
	register char *p;
	struct nlist *q;

	for(;;) {
		p = s;
		*p++ = c = getchr();
		switch(t = type[c]) {
		case 0:
			if (infptr > 0) {
				fclose(infile[infptr]);
				infptr--;
				continue;
			}
			if (svargc > 1) {
				svargc--;
				svargv++;
				if (infile[infptr] != stdin)
					fclose(infile[infptr]);
				if( (infile[infptr] = fopen(*svargv,"r")) == NULL )
					cant(*svargv);
				linect[infptr] = 0;
				curfile[infptr] = *svargv;
				continue;
			}
			return(EOF);	/* real eof */
		case ' ':
		case '\t':
			while ((c = getchr()) == ' ' || c == '\t')
				;	/* skip others */
			if (c == COMMENT || c == '_') {
				putbak(c);
				continue;
			}
			if (c != '\n') {
				putbak(c);
				*p = '\0';
				return(' ');
			} else {
				*s = '\n';
				*(s+1) = '\0';
				return(*s);
			}
		case '_':
			while ((c = getchr()) == ' ' || c == '\t')
				;
			if (c == COMMENT) {
				putbak(c);
				gtok(s);	/* recursive */
			}
			else if (c != '\n')
				putbak(c);
			continue;
		case LET:
		case DIG:
			while ((t=type[*p = getchr()]) == LET || t == DIG)
				p++;
			putbak(*p);
			*p = '\0';
			if ((q = lookup(s))->name != NULL && q->ydef == 0) {	/* found but not keyword */
				if (q->def != fcnloc) {	/* not "function" */
					pbstr(q->def);
					continue;
				}
				getfname();	/* recursive gtok */
			}
			for (p=s; *p; p++)
				if (*p>='A' && *p<='Z')
					*p =+ 'a' - 'A';
			for (p=s; *p; p++)
				if (*p < '0' || *p > '9')
					return(LET);
			return(DIG);
		case '[':
			*p = '\0';
			return('{');
		case ']':
			*p = '\0';
			return('}');
		case '$':
		case '\\':
			if ((*p = getchr()) == '(' || *p == ')') {
				putbak(*p=='(' ? '{' : '}');
				continue;
			}
			if (*p == '"' || *p == '\'')
				p++;
			else
				putbak(*p);
			*p = '\0';
			return('$');
		case COMMENT:
			comment[comptr++] = 'c';
			while ((comment[comptr++] = getchr()) != '\n')
				;
			flushcom();
			*s = '\n';
			*(s+1) = '\0';
			return(*s);
		case '"':
		case '\'':
			for (; (*p = getchr()) != c; p++) {
				if (*p == '\\')
					*++p = getchr();
				if (*p == '\n') {
					error("missing quote");
					putbak('\n');
					break;
				}
			}
			*p++ = c;
			*p = '\0';
			return(QUOTE);
		case '%':
			while ((*p = getchr()) != '\n')
				p++;
			putbak(*p);
			*p = '\0';
			return('%');
		case '>': case '<': case '=': case '!': case '^':
			return(peek(p, '='));
		case '&':
			return(peek(p, '&'));
		case '|':
			return(peek(p, '|'));
		case CRAP:
			continue;
		default:
			*p = '\0';
			return(*s);
		}
	}
}

gnbtok(s) char *s; {
	register c;
	while ((c = gtok(s)) == ' ' || c == '\t')
		;
	return(c);
}

getfname() {
	while (gtok(fcname) == ' ')
		;
	pbstr(fcname);
	putbak(' ');
}

peek(p, c1) char *p, c1; {
	register c;
	c = *(p-1);
	if ((*p = getchr()) == c1)
		p++;
	else
		putbak(*p);
	*p = '\0';
	return(c);
}

pbstr(str)
register char *str;
{
	register char *p;

	p = str;
	while (*p++);
	--p;
	if (ip >= &ibuf[BUFSIZE]) {
		error("pushback overflow");
		exit(1);
	}
	while (p > str)
		putbak(*--p);
}

getchr() {
	register c;

	if (ip > ibuf)
		return(*--ip);
	c = getc(infile[infptr]);
	if (c == '\n')
		linect[infptr]++;
	if (c == EOF)
		return(0);
	return(c);
}
rlex.c_
‡’	¶Y# include "r.h"

char *keyword []{
	"do",
	"if",
	"else",
	"for",
	"repeat",
	"until",
	"while",
	"break",
	"next",
	"define",
	"include",
	"return",
	"switch",
	"case",
	"default",
	0};

int keytran[]{
	DO,
	IF,
	ELSE,
	FOR,
	REPEAT,
	UNTIL,
	WHILE,
	BREAK,
	NEXT,
	DEFINE,
	INCLUDE,
	RETURN,
	SWITCH,
	CASE,
	DEFAULT,
	0};

char	*fcnloc;	/* spot for "function" */

int	svargc;
char	**svargv;
char	*curfile[10]	{ "" };
int	infptr	0;
FILE	*outfil	{ stdout };
FILE	*infile[10]	{ stdin };
int	linect[10];

int	contfld	CONTFLD;	/* place to put continuation char */
int	printcom	0;	/* print comments if on */

#ifdef	gcos
char	*ratfor	"tssrat";
int	bcdrat[2];
char	*bwkmeter	".           bwkmeter    ";
int	bcdbwk[5];
#endif

main(argc,argv) int argc; char **argv; {
	int i;
	while(argc>1 && argv[1][0]=='-') {
		if(argv[1][1]=='6') {
			contfld=6;
			if (argv[1][2]!='\0')
				contchar = argv[1][2];
		} else if (argv[1][1] == 'C')
			printcom++;
		argc--;
		argv++;
	}

#ifdef	gcos
	if (!intss()) {
		_fixup();
		ratfor = "batrat";
	}
	ascbcd(ratfor,bcdrat,6);
	ascbcd(bwkmeter,bcdbwk,24);
	acdata(bcdrat[0],1);
	acupdt(bcdbwk[0]);
	if (!intss()) {
		if ((infile[infptr]=fopen("s*", "r")) == NULL)
			cant("s*");
		if ((outfil=fopen("*s", "w")) == NULL)
			cant("*s");
	}
#endif

	svargc = argc;
	svargv = argv;
	if (svargc > 1)
		putbak('\0');
	for (i=0; keyword[i]; i++)
		install(keyword[i], "", keytran[i]);
	fcnloc = install("function", "", 0);
	yyparse();
#ifdef	gcos
	if (!intss())
		bexit(errorflag);
#endif
	exit(errorflag);
}

#ifdef gcos
bexit(status) {
	/* this is the batch version of exit for gcos tss */
	FILE *inf, *outf;
	char c;

	fclose(stderr);	/* make sure diagnostics get flushed */
	if (status) /* abort */
		_nogud();

	/* good: copy output back to s*, call forty */

	fclose(outfil,"r");
	fclose(infile[0],"r");
	inf = fopen("*s", "r");
	outf = fopen("s*", "w");
	while ((c=getc(inf)) != EOF)
		putc(c, outf);
	fclose(inf,"r");
	fclose(outf,"r");
	__imok();
}
#endif

cant(s) char *s; {
	error("cant open %s", s);
	exit(1);
}

inclstat() {
	int i,c,lpar;
	char *ps;
	char fname[100];
	while ((c = getchr()) == ' ' || c == '\t');
	if (c == '(') {
		for (ps=fname; (*ps=getchr()) != ')'; ps++);
		*ps = '\0';
	} else {
		putbak(c);
		for (ps=fname; (*ps=getchr()) != ' ' &&*ps!='\t' && *ps!='\n' && *ps!=';'; ps++);
		*ps = '\0';
	}
	if ((infile[++infptr] = fopen(fname,"r")) == NULL) {
		cant(fname);
		exit(1);
	}
	linect[infptr] = 0;
	curfile[infptr] = fname;
}

char	str[500];
int	strp;
int	nstr;

yylex() {
	int c, t, i;
	for (;;) {
		while ((c=gtok(str))==' ' || c=='\n' || c=='\t')
			;
		yylval = c;
		if (c==';' || c=='{' || c=='}')
			return(c);
		if (c==EOF)
			return(0);
		yylval = str;
		if (c == DIG)
			return(DIGITS);
		t = lookup(str)->ydef;
		if (t==DEFINE)
			defstat();
		else if (t==INCLUDE)
			inclstat();
		else if (t > 0)
			return(t);
		else
			return(GOK);
	}
}

int	dbg	0;

yyerror() {;}


defstat() {
	int c,i,val,t,nlp;
	extern int nstr;
	extern char str[];
	while ((c=getchr())==' ' || c=='\t');
	if (c == '(') {
		t = '(';
		while ((c=getchr())==' ' || c=='\t');
		putbak(c);
	}
	else {
		t = ' ';
		putbak(c);
	}
	for (nstr=0; c=getchr(); nstr++) {
		if (type[c] != LET && type[c] != DIG)
			break;
		str[nstr] = c;
	}
	putbak(c);
	str[nstr] = '\0';
	if (c != ' ' && c != '\t' && c != '\n' && c != ',') {
		error("illegal define statement: %s", str);;
		return;
	}
	val = nstr+1;
	if (t == ' ') {
		while ((c=getchr())==' ' || c=='\t');
		putbak(c);
		for (i=val; (c=getchr())!='\n' && c!='#' && c!='\0'; i++)
			str[i] = c;
		putbak(c);
	} else {
		while ((c=getchr())==' ' || c=='\t' || c==',' || c=='\n');
		putbak(c);
		nlp  = 0;
		for (i=val; nlp>=0 && (c=str[i]=getchr()); i++)
			if (c == '(')
				nlp++;
			else if (c == ')')
				nlp--;
		i--;
	}
	for ( ; i>0; i--)
		if (str[i-1] != ' ' && str[i-1] != '\t')
			break;
	str[i] = '\0';
	install(str, &str[val], 0);
}

}rlook.c_
‡’	¶Â#define NULL 0
#define EOS 0
#define	HSHSIZ	101
struct	nlist {
	char	*name;
	char	*def;
	int	ydef;
	struct	nlist *next;
};

struct	nlist	*hshtab[HSHSIZ];
struct nlist	*lookup();
char	*install();
char	*calloc();
char	*copy();
int	hshval;

struct nlist *lookup(str)
char *str;
{
	register char *s1, *s2;
	register struct nlist *np;
	static struct nlist nodef;

	s1 = str;
	for (hshval = 0; *s1; )
		hshval =+ *s1++;
	hshval =% HSHSIZ;
	for (np = hshtab[hshval]; np!=NULL; np = np->next) {
		s1 = str;
		s2 = np->name;
		while (*s1++ == *s2)
			if (*s2++ == EOS)
				return(np);
	}
	return(&nodef);
}

char *install(nam, val, tran)
char *nam, *val;
int tran;
{
	register struct nlist *np;

	if ((np = lookup(nam))->name == NULL) {
		np = calloc(sizeof(*np),1);
		np->name = copy(nam);
		np->def = copy(val);
		np->ydef = tran;
		np->next = hshtab[hshval];
		hshtab[hshval] = np;
		return(np->def);
	}
	cfree(np->def, length(np->def)+1, 1);
	np->def = copy(val);
	return(np->def);
}

char *copy(s)
register char *s;
{
	register char *p, *s1;

	p = s1 = calloc(length(s)+1,1);
	while (*s1++ = *s++);
	return(p);
}

length(str)
register char *str;
{
	register len;

	len = 0;
	while (*str++ != EOS)
		len++;
	return(len);
}
r0.c_
‡’	¶…#include "r.h"

int	swlevel	-1;
int	swexit[5];
int	nextcase[5];

swcode() {
	transfer = 0;
	putcom("switch");
	swlevel++;
	if (swlevel >= 5)
		error("Switches nested > 5");
	swexit[swlevel] = yyval = genlab(1);
	outcode("\tI");
	outnum(yyval);
	outcode(" = ");
	balpar();
	outdon();
	nextcase[swlevel] = 0;
	indent++;
}

getcase() {
	int t, lpar;
	char token[100];

	if (nextcase[swlevel] != 0) {
		outgoto(swexit[swlevel]);
		outcont(nextcase[swlevel]);
	}
	indent--;
	outcode("\tif(.not.(");
	do {
		outcode("I");
		outnum(swexit[swlevel]);
		outcode(".eq.(");
		lpar = 0;
		do {
			if ((t=gtok(token)) == ':')
				break;
			if (t == '(')
				lpar++;
			else if (t == ')')
				lpar--;
			else if (t == ',') {
				if (lpar == 0)
					break;
				}
			outcode(token);
		} while (lpar >= 0);
		if (lpar < 0)
			error("Missing left parenthesis in case");
		if (t == ',')
			outcode(").or.");
	} while (t != ':');
	if (lpar != 0)
		error("Missing parenthesis in case");
	outcode(")))");
	nextcase[swlevel] = genlab(1);
	outgoto(nextcase[swlevel]);
	indent++;
}

getdefault() {
	char token[20];
	if (gnbtok(token) != ':')
		error("Missing colon after default");
	outgoto(swexit[swlevel]);
	outcont(nextcase[swlevel]);
	indent--;
	putcom("default");
	indent++;
}

endsw(n, def) {
	if (def == 0)
		outcont(nextcase[swlevel]);
	swlevel--;
	if (swlevel < -1)
		error("Switches unwound too far");
	indent--;
	outcont(n);
}
!makefilea
úÜ[¶¦a.out:	r0.o r1.o r2.o rio.o rlook.o rlex.o y.tab.o
	cc r*.o y.tab.o -ly -lS

r0.o:	r.h y.tab.h r0.c
r1.o:	r.h y.tab.h r1.c
r2.o:	r.h y.tab.h r2.c
rio.o:	r.h y.tab.h rio.c
rlook.o:	r.h y.tab.h rlook.c
rlex.o:	r.h y.tab.h rlex.c
y.tab.c:	r.g
	yacc -d r.g
y.tab.h:	r.g
	yacc -d r.g

list:
	pr r.g r.h r*.c makefile TODO bfor.g

gcos:
	fsend r.h r*.c y.tab.c y.tab.h

install:
	strip a.out
	cp a.out /usr/bin/ratfor

get:
	ar x /sys/source/s2/ratfor.a

sys:
	ar u /sys/source/s2/ratfor.a

clean:
	rm r.g r.h r*.c y.tab.c info frat.g

export:
	mkdir export
	cp /sys/source/s2/ratfor.a export
	cp /sys/source/s2/rc.c export
	ar r export/stdio.a /sys/source/s4/stdio/*
	ls export

tp:
frat.g_
ˆ’	¶(%term	YLBRACK YRBRACK YLPAR YRPAR YSCOL YDIGITS
%term	YIF YELSE YFOR YWHILE YBREAK YNEXT 
%term	YOLDDO YNEWDO YDO
%term	YGOK YDEFINE YINCLUDE YOPTIONS
%%

statl	: statl stat
	| 
	;
stat	: if stat	={ call outcon($1); }
	| ifelse stat	={ call outcon($1+1); }
	| while stat	={ call whiles($1); }
	| for stat	={ call fors($1); }
	| YBREAK	={ call breakc; }
	| YNEXT		={ call nextc; }
	| newdo stat	={ call dostat($1); }
	| YOLDDO	={ call docode(0); }
	| YGOK		={ call gokcod; }
	| YSCOL
	| YLBRACK statl YRBRACK
	| label stat
	| error		={ call errcod; yyclearin; }
	;
label	: YDIGITS	={ call labelc;}
	;
if	: YIF		={ call ifcode; }
	;
ifelse	: if stat YELSE	={ call outgo($1+1); call outcon($1); }
	;
while	: YWHILE	={ call whilec; }
	;
for	: YFOR		={ call forcod; }
	;
newdo	: YNEWDO	={ call docode(1); }
	;
%%
info_
ˆ’	¶>Ratfor is a Fortran preprocessor that takes a decent
language closely related to Fortran and converts it
into Fortran. The language is best described in
the book Software Tools, by B. W. Kernighan and P. J. Plauger,
Addison-Wesley, 1976.

The version here is in C, and implements a superset
of the Ratfor described in Software Tools. New additions
are 
   return(value)
   break n, next n
   switch
   output formatting

The ratfor compiler lives on several files:

   r.g - the grammar as yacc source
   r.h - header for r*.c
   r0.c - semantic actions for switch statement
   r1.c - semantic actions for input categories, like "if", etc.
   r2.c - output code; formatting, quote conversion, etc.
   rlex.c - lexical phase - reads input, isolates tokens.
   rio.c - input processing
   rlook.c - table lookup code

Compile with

yacc r.g
cc r*.c y.tab.c -ly -lS

The file y.tab.c is produced by yacc.
-ly indicates the use of the yacc runtime
library and -lS is the new Standard C I/O library.

Usage:

a.out [files ...]

Writes on standard output.

Ratfor is best used via the rc command, described in section
I of the Unix Programmers Manual, 6th edition.
rc is very similar to cc, from which it is derived.
To make a new version of rc,

cc rc.c

Usage of rc:
rc [-c] files...
where -c implies no attempt to load, as in cc.
all files ending in .r are assumed to
be ratfor source; they are ratfor'ed, fortran'ed and bound
into a .o .
The complete set of .o's is bound into an a.out unless
there is a compilation error.
There are a number of other less interesting flags,
described in the manual.
bfor.ga
WÜ	¶Ë$      gmap    nxec,ndeck
       lbl     cterm
       ttl     c compiler termination routines
       ttls    january 1974, bell telephone laboratories
*
*      program responsibility:  r. a. faulkner
*
       symdef  ..imok
..imok null                    normal termination
       mme     geroad
       eax1    0               zero the slave prefix
       rpt     17,1
       stz     0,1
       rpt     6,1
       stz     3,1
       stz     31
       ldq     =hratfor
       stq     21              use "r" for object deck ident
	ldq	bufptr
	mme	gerels	get rid of **
	zero	1,0
	bci	1,0000**
	ldaq	save26
	staq	26
       mme     gecall          invoke forty
       bci     1,forty
       zero
       zero
bufptr	zero	buf,-1
buf	bss	355
*
       symdef  .nogud
.nogud null                    abnormal termination
       mme     geroad
       ldq     =o010000,du
       mme     gerets          turn off execute bit
       canq    =o000020,du     test sys. editor bit
       tnz     *+2             on, skip
       mme     gefini          off, terminate
	ldaq	save26
	staq	26
	ldq	=3h0*z,dl
       tra     26              return to editor
*
*
	symdef	.fixup
.fixup	null
	ldaq	26
	staq	save26
	tra	0,1
	even
save26	bss	2
       end