xref: /csrg-svn/usr.bin/pascal/src/stat.c (revision 3079)
1773Speter /* Copyright (c) 1979 Regents of the University of California */
2773Speter 
3*3079Smckusic static char sccsid[] = "@(#)stat.c 1.3 03/08/81";
4773Speter 
5773Speter #include "whoami.h"
6773Speter #include "0.h"
7773Speter #include "tree.h"
8773Speter #include "objfmt.h"
9773Speter #ifdef PC
10773Speter #   include "pcops.h"
11773Speter #   include "pc.h"
12773Speter #endif PC
13773Speter 
14773Speter int cntstat;
15773Speter short cnts = 3;
16773Speter #include "opcode.h"
17773Speter 
18773Speter /*
19773Speter  * Statement list
20773Speter  */
21773Speter statlist(r)
22773Speter 	int *r;
23773Speter {
24773Speter 	register *sl;
25773Speter 
26773Speter 	for (sl=r; sl != NIL; sl=sl[2])
27773Speter 		statement(sl[1]);
28773Speter }
29773Speter 
30773Speter /*
31773Speter  * Statement
32773Speter  */
33773Speter statement(r)
34773Speter 	int *r;
35773Speter {
36773Speter 	register *s;
37773Speter 	register struct nl *snlp;
38773Speter 	long	soffset;
39773Speter 
40773Speter 	s = r;
41773Speter 	snlp = nlp;
42773Speter 	soffset = sizes[ cbn ].om_off;
43773Speter top:
44773Speter 	if (cntstat) {
45773Speter 		cntstat = 0;
46773Speter 		putcnt();
47773Speter 	}
48773Speter 	if (s == NIL)
49773Speter 		return;
50773Speter 	line = s[1];
51773Speter 	if (s[0] == T_LABEL) {
52773Speter 		labeled(s[2]);
53773Speter 		s = s[3];
54773Speter 		noreach = 0;
55773Speter 		cntstat = 1;
56773Speter 		goto top;
57773Speter 	}
58773Speter 	if (noreach) {
59773Speter 		noreach = 0;
60773Speter 		warning();
61773Speter 		error("Unreachable statement");
62773Speter 	}
63773Speter 	switch (s[0]) {
64773Speter 		case T_PCALL:
65773Speter 			putline();
66773Speter #			ifdef OBJ
67773Speter 			    proc(s);
68773Speter #			endif OBJ
69773Speter #			ifdef PC
70773Speter 			    pcproc( s );
71773Speter #			endif PC
72773Speter 			break;
73773Speter 		case T_ASGN:
74773Speter 			putline();
75773Speter 			asgnop(s);
76773Speter 			break;
77773Speter 		case T_GOTO:
78773Speter 			putline();
79773Speter 			gotoop(s[2]);
80773Speter 			noreach = 1;
81773Speter 			cntstat = 1;
82773Speter 			break;
83773Speter 		default:
84773Speter 			level++;
85773Speter 			switch (s[0]) {
86773Speter 				default:
87773Speter 					panic("stat");
88773Speter 				case T_IF:
89773Speter 				case T_IFEL:
90773Speter 					ifop(s);
91773Speter 					break;
92773Speter 				case T_WHILE:
93773Speter 					whilop(s);
94773Speter 					noreach = 0;
95773Speter 					break;
96773Speter 				case T_REPEAT:
97773Speter 					repop(s);
98773Speter 					break;
99773Speter 				case T_FORU:
100773Speter 				case T_FORD:
1012185Smckusic 				        forop(s);
102773Speter 					noreach = 0;
103773Speter 					break;
104773Speter 				case T_BLOCK:
105773Speter 					statlist(s[2]);
106773Speter 					break;
107773Speter 				case T_CASE:
108773Speter 					putline();
109773Speter #					ifdef OBJ
110773Speter 					    caseop(s);
111773Speter #					endif OBJ
112773Speter #					ifdef PC
113773Speter 					    pccaseop( s );
114773Speter #					endif PC
115773Speter 					break;
116773Speter 				case T_WITH:
117773Speter 					withop(s);
118773Speter 					break;
119773Speter 				case T_ASRT:
120773Speter 					putline();
121773Speter 					asrtop(s);
122773Speter 					break;
123773Speter 			}
124773Speter 			--level;
125773Speter 			if (gotos[cbn])
126773Speter 				ungoto();
127773Speter 			break;
128773Speter 	}
129773Speter 	/*
130773Speter 	 * Free the temporary name list entries defined in
131773Speter 	 * expressions, e.g. STRs, and WITHPTRs from withs.
132773Speter 	 */
133773Speter 	nlfree(snlp);
134773Speter 	    /*
135773Speter 	     *	free any temporaries allocated for this statement
136773Speter 	     *	these come from strings and sets.
137773Speter 	     */
138773Speter 	if ( soffset != sizes[ cbn ].om_off ) {
139773Speter 	    sizes[ cbn ].om_off = soffset;
140773Speter #	    ifdef PC
141773Speter 		putlbracket( ftnno , -sizes[cbn].om_off );
142773Speter #	    endif PC
143773Speter 	}
144773Speter }
145773Speter 
146773Speter ungoto()
147773Speter {
148773Speter 	register struct nl *p;
149773Speter 
150773Speter 	for (p = gotos[cbn]; p != NIL; p = p->chain)
151773Speter 		if ((p->nl_flags & NFORWD) != 0) {
152773Speter 			if (p->value[NL_GOLEV] != NOTYET)
153773Speter 				if (p->value[NL_GOLEV] > level)
154773Speter 					p->value[NL_GOLEV] = level;
155773Speter 		} else
156773Speter 			if (p->value[NL_GOLEV] != DEAD)
157773Speter 				if (p->value[NL_GOLEV] > level)
158773Speter 					p->value[NL_GOLEV] = DEAD;
159773Speter }
160773Speter 
161773Speter putcnt()
162773Speter {
163773Speter 
164773Speter 	if (monflg == 0) {
165773Speter 		return;
166773Speter 	}
167773Speter 	inccnt( getcnt() );
168773Speter }
169773Speter 
170773Speter int
171773Speter getcnt()
172773Speter     {
173773Speter 
174773Speter 	return ++cnts;
175773Speter     }
176773Speter 
177773Speter inccnt( counter )
178773Speter     int	counter;
179773Speter     {
180773Speter 
181773Speter #	ifdef OBJ
182*3079Smckusic 	    put(2, O_COUNT, counter );
183773Speter #	endif OBJ
184773Speter #	ifdef PC
185773Speter 	    putRV( PCPCOUNT , 0 , counter * sizeof (long) , P2INT );
186773Speter 	    putleaf( P2ICON , 1 , 0 , P2INT , 0 );
187773Speter 	    putop( P2ASG P2PLUS , P2INT );
188773Speter 	    putdot( filename , line );
189773Speter #	endif PC
190773Speter     }
191773Speter 
192773Speter putline()
193773Speter {
194773Speter 
195773Speter #	ifdef OBJ
196773Speter 	    if (opt('p') != 0)
197*3079Smckusic 		    put(2, O_LINO, line);
198773Speter #	endif OBJ
199773Speter #	ifdef PC
200773Speter 	    static lastline;
201773Speter 
202773Speter 	    if ( line != lastline ) {
203773Speter 		stabline( line );
204773Speter 		lastline = line;
205773Speter 	    }
206773Speter 	    if ( opt( 'p' ) ) {
207773Speter 		if ( opt('t') ) {
208773Speter 		    putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
209773Speter 			    , "_LINO" );
210773Speter 		    putop( P2UNARY P2CALL , P2INT );
211773Speter 		    putdot( filename , line );
212773Speter 		} else {
213773Speter 		    putRV( STMTCOUNT , 0 , 0 , P2INT );
214773Speter 		    putleaf( P2ICON , 1 , 0 , P2INT , 0 );
215773Speter 		    putop( P2ASG P2PLUS , P2INT );
216773Speter 		    putdot( filename , line );
217773Speter 		}
218773Speter 	    }
219773Speter #	endif PC
220773Speter }
221773Speter 
222773Speter /*
223773Speter  * With varlist do stat
224773Speter  *
225773Speter  * With statement requires an extra word
226773Speter  * in automatic storage for each level of withing.
227773Speter  * These indirect pointers are initialized here, and
228773Speter  * the scoping effect of the with statement occurs
229773Speter  * because lookup examines the field names of the records
230773Speter  * associated with the WITHPTRs on the withlist.
231773Speter  */
232773Speter withop(s)
233773Speter 	int *s;
234773Speter {
235773Speter 	register *p;
236773Speter 	register struct nl *r;
237773Speter 	int i;
238773Speter 	int *swl;
239773Speter 	long soffset;
240773Speter 
241773Speter 	putline();
242773Speter 	swl = withlist;
243773Speter 	soffset = sizes[cbn].om_off;
244773Speter 	for (p = s[2]; p != NIL; p = p[2]) {
245773Speter 		i = sizes[cbn].om_off -= sizeof ( int * );
246773Speter 		if (sizes[cbn].om_off < sizes[cbn].om_max)
247773Speter 			sizes[cbn].om_max = sizes[cbn].om_off;
248773Speter #		ifdef OBJ
249*3079Smckusic 		    put(2, O_LV | cbn <<8+INDX, i );
250773Speter #		endif OBJ
251773Speter #		ifdef PC
252773Speter 		    putlbracket( ftnno , -sizes[cbn].om_off );
253773Speter 		    putRV( 0 , cbn , i , P2PTR|P2STRTY );
254773Speter #		endif PC
255773Speter 		r = lvalue(p[1], MOD , LREQ );
256773Speter 		if (r == NIL)
257773Speter 			continue;
258773Speter 		if (r->class != RECORD) {
259773Speter 			error("Variable in with statement refers to %s, not to a record", nameof(r));
260773Speter 			continue;
261773Speter 		}
262773Speter 		r = defnl(0, WITHPTR, r, i);
263773Speter 		r->nl_next = withlist;
264773Speter 		withlist = r;
265773Speter #		ifdef OBJ
266773Speter 		    put(1, PTR_AS);
267773Speter #		endif OBJ
268773Speter #		ifdef PC
269773Speter 		    putop( P2ASSIGN , P2PTR|P2STRTY );
270773Speter 		    putdot( filename , line );
271773Speter #		endif PC
272773Speter 	}
273773Speter 	statement(s[3]);
274773Speter 	sizes[cbn].om_off = soffset;
275773Speter #	ifdef PC
276773Speter 	    putlbracket( ftnno , -sizes[cbn].om_off );
277773Speter #	endif PC
278773Speter 	withlist = swl;
279773Speter }
280773Speter 
281773Speter extern	flagwas;
282773Speter /*
283773Speter  * var := expr
284773Speter  */
285773Speter asgnop(r)
286773Speter 	int *r;
287773Speter {
288773Speter 	register struct nl *p;
289773Speter 	register *av;
290773Speter 
291773Speter 	if (r == NIL)
292773Speter 		return (NIL);
293773Speter 	/*
294773Speter 	 * Asgnop's only function is
295773Speter 	 * to handle function variable
296773Speter 	 * assignments.  All other assignment
297773Speter 	 * stuff is handled by asgnop1.
298773Speter 	 * the if below checks for unqualified lefthandside:
299773Speter 	 * necessary for fvars.
300773Speter 	 */
301773Speter 	av = r[2];
302773Speter 	if (av != NIL && av[0] == T_VAR && av[3] == NIL) {
303773Speter 		p = lookup1(av[2]);
304773Speter 		if (p != NIL)
305773Speter 			p->nl_flags = flagwas;
306773Speter 		if (p != NIL && p->class == FVAR) {
307773Speter 			/*
308773Speter 			 * Give asgnop1 the func
309773Speter 			 * which is the chain of
310773Speter 			 * the FVAR.
311773Speter 			 */
312773Speter 			p->nl_flags |= NUSED|NMOD;
313773Speter 			p = p->chain;
314773Speter 			if (p == NIL) {
315773Speter 				rvalue(r[3], NIL , RREQ );
316773Speter 				return;
317773Speter 			}
318773Speter #			ifdef OBJ
319*3079Smckusic 			    put(2, O_LV | bn << 8+INDX, (int)p->value[NL_OFFS]);
320773Speter 			    if (isa(p->type, "i") && width(p->type) == 1)
321773Speter 				    asgnop1(r, nl+T2INT);
322773Speter 			    else
323773Speter 				    asgnop1(r, p->type);
324773Speter #			endif OBJ
325773Speter #			ifdef PC
326773Speter 				/*
327773Speter 				 * this should be the lvalue of the fvar,
328773Speter 				 * but since the second pass knows to use
329773Speter 				 * the address of the left operand of an
330773Speter 				 * assignment, what i want here is an rvalue.
331773Speter 				 * see note in funchdr about fvar allocation.
332773Speter 				 */
333773Speter 			    p = p -> ptr[ NL_FVAR ];
334773Speter 			    putRV( p -> symbol , bn , p -> value[ NL_OFFS ]
335773Speter 					, p2type( p -> type ) );
336773Speter 			    asgnop1( r , p -> type );
337773Speter #			endif PC
338773Speter 			return;
339773Speter 		}
340773Speter 	}
341773Speter 	asgnop1(r, NIL);
342773Speter }
343773Speter 
344773Speter /*
345773Speter  * Asgnop1 handles all assignments.
346773Speter  * If p is not nil then we are assigning
347773Speter  * to a function variable, otherwise
348773Speter  * we look the variable up ourselves.
349773Speter  */
350773Speter struct nl *
351773Speter asgnop1(r, p)
352773Speter 	int *r;
353773Speter 	register struct nl *p;
354773Speter {
355773Speter 	register struct nl *p1;
356*3079Smckusic 	int w;
357773Speter 
358773Speter 	if (r == NIL)
359773Speter 		return (NIL);
360773Speter 	if (p == NIL) {
361773Speter #	    ifdef OBJ
362773Speter 		p = lvalue(r[2], MOD|ASGN|NOUSE , LREQ );
363*3079Smckusic 		w = width(p);
364773Speter #	    endif OBJ
365773Speter #	    ifdef PC
366773Speter 		    /*
367773Speter 		     * since the second pass knows that it should reference
368773Speter 		     * the lefthandside of asignments, what i need here is
369773Speter 		     * an rvalue.
370773Speter 		     */
371773Speter 		p = lvalue( r[2] , MOD|ASGN|NOUSE , RREQ );
372773Speter #	    endif PC
373773Speter 	    if ( p == NIL ) {
374773Speter 		rvalue( r[3] , NIL , RREQ );
375773Speter 		return NIL;
376773Speter 	    }
377773Speter 	}
378773Speter #	ifdef OBJ
379*3079Smckusic 	    /*
380*3079Smckusic 	     * assigning to the return value, which is at least
381*3079Smckusic 	     * of width two since it resides on the stack
382*3079Smckusic 	     */
383*3079Smckusic 	    else {
384*3079Smckusic 		w = width(p);
385*3079Smckusic 		if (w < 2)
386*3079Smckusic 		    w = 2;
387*3079Smckusic 	    }
388773Speter 	    p1 = rvalue(r[3], p , RREQ );
389773Speter #	endif OBJ
390773Speter #	ifdef PC
391773Speter 		/*
392773Speter 		 *	if this is a scalar assignment,
393773Speter 		 *	    then i want to rvalue the righthandside.
394773Speter 		 *	if this is a structure assignment,
395773Speter 		 *	    then i want an lvalue to the righthandside.
396773Speter 		 *  that's what the intermediate form sez.
397773Speter 		 */
398773Speter 	    switch ( classify( p ) ) {
399773Speter 		case TINT:
400773Speter 		case TCHAR:
401773Speter 		case TBOOL:
402773Speter 		case TSCAL:
403773Speter 		    precheck( p , "_RANG4" , "_RSNG4" );
404773Speter 		case TDOUBLE:
405773Speter 		case TPTR:
406773Speter 		    p1 = rvalue( r[3] , p , RREQ );
407773Speter 		    break;
408773Speter 		default:
409773Speter 		    p1 = rvalue( r[3] , p , LREQ );
410773Speter 		    break;
411773Speter 	    }
412773Speter #	endif PC
413773Speter 	if (p1 == NIL)
414773Speter 		return (NIL);
415773Speter 	if (incompat(p1, p, r[3])) {
416773Speter 		cerror("Type of expression clashed with type of variable in assignment");
417773Speter 		return (NIL);
418773Speter 	}
419773Speter 	switch (classify(p)) {
420773Speter 		case TINT:
421773Speter 		case TBOOL:
422773Speter 		case TCHAR:
423773Speter 		case TSCAL:
424773Speter #			ifdef OBJ
425773Speter 			    rangechk(p, p1);
426773Speter #			endif OBJ
427773Speter #			ifdef PC
428773Speter 			    postcheck( p );
429773Speter #			endif PC
430773Speter 		case TDOUBLE:
431773Speter 		case TPTR:
432773Speter #			ifdef OBJ
433*3079Smckusic 			    gen(O_AS2, O_AS2, w, width(p1));
434773Speter #			endif OBJ
435773Speter #			ifdef PC
436773Speter 			    putop( P2ASSIGN , p2type( p ) );
437773Speter 			    putdot( filename , line );
438773Speter #			endif PC
439773Speter 			break;
440773Speter 		default:
441773Speter #			ifdef OBJ
442*3079Smckusic 			    put(2, O_AS, w);
443773Speter #			endif OBJ
444773Speter #			ifdef PC
445773Speter 			    putstrop( P2STASG , p2type( p )
446773Speter 					, lwidth( p ) , align( p ) );
447773Speter 			    putdot( filename , line );
448773Speter #			endif PC
449773Speter 	}
450773Speter 	return (p);	/* Used by for statement */
451773Speter }
452773Speter 
453773Speter /*
454773Speter  * if expr then stat [ else stat ]
455773Speter  */
456773Speter ifop(r)
457773Speter 	int *r;
458773Speter {
459773Speter 	register struct nl *p;
460773Speter 	register l1, l2;	/* l1 is start of else, l2 is end of else */
461*3079Smckusic 	int goc;
462*3079Smckusic 	bool nr;
463773Speter 
464773Speter 	goc = gocnt;
465773Speter 	if (r == NIL)
466773Speter 		return;
467773Speter 	putline();
468773Speter 	p = rvalue(r[2], NIL , RREQ );
469773Speter 	if (p == NIL) {
470773Speter 		statement(r[3]);
471773Speter 		noreach = 0;
472773Speter 		statement(r[4]);
473773Speter 		noreach = 0;
474773Speter 		return;
475773Speter 	}
476773Speter 	if (isnta(p, "b")) {
477773Speter 		error("Type of expression in if statement must be Boolean, not %s", nameof(p));
478773Speter 		statement(r[3]);
479773Speter 		noreach = 0;
480773Speter 		statement(r[4]);
481773Speter 		noreach = 0;
482773Speter 		return;
483773Speter 	}
484773Speter #	ifdef OBJ
485*3079Smckusic 	    l1 = put(2, O_IF, getlab());
486773Speter #	endif OBJ
487773Speter #	ifdef PC
488773Speter 	    l1 = getlab();
489773Speter 	    putleaf( P2ICON , l1 , 0 , P2INT , 0 );
490773Speter 	    putop( P2CBRANCH , P2INT );
491773Speter 	    putdot( filename , line );
492773Speter #	endif PC
493773Speter 	putcnt();
494773Speter 	statement(r[3]);
495773Speter 	nr = noreach;
496773Speter 	if (r[4] != NIL) {
497773Speter 		/*
498773Speter 		 * else stat
499773Speter 		 */
500773Speter 		--level;
501773Speter 		ungoto();
502773Speter 		++level;
503773Speter #		ifdef OBJ
504*3079Smckusic 		    l2 = put(2, O_TRA, getlab());
505773Speter #		endif OBJ
506773Speter #		ifdef PC
507773Speter 		    l2 = getlab();
508773Speter 		    putjbr( l2 );
509773Speter #		endif PC
510773Speter 		patch(l1);
511773Speter 		noreach = 0;
512773Speter 		statement(r[4]);
513*3079Smckusic 		noreach = (noreach && nr);
514773Speter 		l1 = l2;
515773Speter 	} else
516773Speter 		noreach = 0;
517773Speter 	patch(l1);
518773Speter 	if (goc != gocnt)
519773Speter 		putcnt();
520773Speter }
521773Speter 
522773Speter /*
523773Speter  * while expr do stat
524773Speter  */
525773Speter whilop(r)
526773Speter 	int *r;
527773Speter {
528773Speter 	register struct nl *p;
529773Speter 	register l1, l2;
530773Speter 	int goc;
531773Speter 
532773Speter 	goc = gocnt;
533773Speter 	if (r == NIL)
534773Speter 		return;
535773Speter 	putlab(l1 = getlab());
536773Speter 	putline();
537773Speter 	p = rvalue(r[2], NIL , RREQ );
538773Speter 	if (p == NIL) {
539773Speter 		statement(r[3]);
540773Speter 		noreach = 0;
541773Speter 		return;
542773Speter 	}
543773Speter 	if (isnta(p, "b")) {
544773Speter 		error("Type of expression in while statement must be Boolean, not %s", nameof(p));
545773Speter 		statement(r[3]);
546773Speter 		noreach = 0;
547773Speter 		return;
548773Speter 	}
549773Speter 	l2 = getlab();
550773Speter #	ifdef OBJ
551*3079Smckusic 	    put(2, O_IF, l2);
552773Speter #	endif OBJ
553773Speter #	ifdef PC
554773Speter 	    putleaf( P2ICON , l2 , 0 , P2INT , 0 );
555773Speter 	    putop( P2CBRANCH , P2INT );
556773Speter 	    putdot( filename , line );
557773Speter #	endif PC
558773Speter 	putcnt();
559773Speter 	statement(r[3]);
560773Speter #	ifdef OBJ
561*3079Smckusic 	    put(2, O_TRA, l1);
562773Speter #	endif OBJ
563773Speter #	ifdef PC
564773Speter 	    putjbr( l1 );
565773Speter #	endif PC
566773Speter 	patch(l2);
567773Speter 	if (goc != gocnt)
568773Speter 		putcnt();
569773Speter }
570773Speter 
571773Speter /*
572773Speter  * repeat stat* until expr
573773Speter  */
574773Speter repop(r)
575773Speter 	int *r;
576773Speter {
577773Speter 	register struct nl *p;
578773Speter 	register l;
579773Speter 	int goc;
580773Speter 
581773Speter 	goc = gocnt;
582773Speter 	if (r == NIL)
583773Speter 		return;
584773Speter 	l = putlab(getlab());
585773Speter 	putcnt();
586773Speter 	statlist(r[2]);
587773Speter 	line = r[1];
588773Speter 	p = rvalue(r[3], NIL , RREQ );
589773Speter 	if (p == NIL)
590773Speter 		return;
591773Speter 	if (isnta(p,"b")) {
592773Speter 		error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p));
593773Speter 		return;
594773Speter 	}
595773Speter #	ifdef OBJ
596*3079Smckusic 	    put(2, O_IF, l);
597773Speter #	endif OBJ
598773Speter #	ifdef PC
599773Speter 	    putleaf( P2ICON , l , 0 , P2INT , 0 );
600773Speter 	    putop( P2CBRANCH , P2INT );
601773Speter 	    putdot( filename , line );
602773Speter #	endif PC
603773Speter 	if (goc != gocnt)
604773Speter 		putcnt();
605773Speter }
606773Speter 
607773Speter /*
608773Speter  * assert expr
609773Speter  */
610773Speter asrtop(r)
611773Speter 	register int *r;
612773Speter {
613773Speter 	register struct nl *q;
614773Speter 
615773Speter 	if (opt('s')) {
616773Speter 		standard();
617773Speter 		error("Assert statement is non-standard");
618773Speter 	}
619773Speter 	if (!opt('t'))
620773Speter 		return;
621773Speter 	r = r[2];
622773Speter #	ifdef OBJ
623773Speter 	    q = rvalue((int *) r, NLNIL , RREQ );
624773Speter #	endif OBJ
625773Speter #	ifdef PC
626773Speter 	    putleaf( P2ICON , 0 , 0
627773Speter 		    , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_ASRT" );
628773Speter 	    q = stkrval( r , NLNIL , RREQ );
629773Speter #	endif PC
630773Speter 	if (q == NIL)
631773Speter 		return;
632773Speter 	if (isnta(q, "b"))
633773Speter 		error("Assert expression must be Boolean, not %ss", nameof(q));
634773Speter #	ifdef OBJ
635*3079Smckusic 	    put(1, O_ASRT);
636773Speter #	endif OBJ
637773Speter #	ifdef PC
638773Speter 	    putop( P2CALL , P2INT );
639773Speter 	    putdot( filename , line );
640773Speter #	endif PC
641773Speter }
642