|
|
1.1 root 1: /* C compiler: statement parsing */
2:
3: #include "c.h"
4:
5: #define SWITCHSIZE 512 /* initial size of switch arrays */
6:
7: float density = 0.5; /* minimum switch density */
8: float refinc = 1.0; /* amount by which ref field is incremented */
9:
10: static struct equate { /* deferred equates: */
11: Symbol new; /* new label, i.e., label being defined */
12: Symbol old; /* old label */
13: struct equate *oldlink; /* pointer to equate structure for old=x */
14: struct equate *link; /* next equate on list */
15: } *equlist; /* list of deferred equates */
16: struct swtch { /* switch statement data: */
17: Symbol sym; /* local holding the switch value */
18: int lab; /* label of selection code */
19: Symbol deflab; /* default label */
20: int ncases; /* number of cases */
21: int size; /* size of value & label arrays */
22: int *values; /* value, label pairs */
23: Symbol *labels;
24: };
25:
26: dclproto(static void branch,(int));
27: dclproto(static void caselabel,(struct swtch *, int, int));
28: dclproto(static void cmp,(int, Symbol, int, int));
29: dclproto(static void dostmt,(int, struct swtch *, int));
30: dclproto(static int foldcond,(Tree, Tree));
31: dclproto(static void forstmt,(int, struct swtch *, int));
32: dclproto(static void ifstmt,(int, int, struct swtch *, int));
33: dclproto(static Symbol localaddr,(Tree));
34: dclproto(static void stmtlabel,(char *));
35: dclproto(static int swcode,(struct swtch *, int *, int, int, int));
36: dclproto(static void swgen,(struct swtch *));
37: dclproto(static void swstmt,(int, int, int));
38: dclproto(static void visit,(struct equate *));
39: dclproto(static void whilestmt,(int, struct swtch *, int));
40:
41: /* branch - jump to lab */
42: static void branch(lab) {
43: Code cp;
44:
45: walk(0, 0, 0);
46: for (cp = codelist; cp->kind < Label; )
47: cp = cp->prev;
48: if (lab)
49: while (cp->kind == Label && islabel(cp->u.node)
50: && cp->u.node->syms[0]->u.l.label != lab) {
51: Symbol old = findlabel(lab);
52: equatelab(cp->u.node->syms[0], old);
53: old->ref++;
54: if (cp->prev->next = cp->next)
55: cp->next->prev = cp->prev;
56: else
57: codelist = cp->prev;
58: do
59: cp = cp->prev;
60: while (cp->kind < Label);
61: }
62: if (cp->kind != Jump) {
63: code(Jump);
64: codelist->u.node = lab ? jump(lab) : (Node)0;
65: }
66: /* else do nothing and thus delete dead branch */
67: }
68:
69: /* caselabel - add a label to the current switch list */
70: static void caselabel(swp, val, lab) struct swtch *swp; {
71: int k;
72:
73: if (swp->ncases >= swp->size) {
74: int *vals = swp->values;
75: Symbol *labs = swp->labels;
76: swp->size *= 2;
77: swp->values = (int *) talloc(swp->size*sizeof (int));
78: swp->labels = (Symbol *) talloc(swp->size*sizeof (Symbol));
79: for (k = 0; k < swp->ncases; k++) {
80: swp->values[k] = vals[k];
81: swp->labels[k] = labs[k];
82: }
83: }
84: for (k = swp->ncases; k > 0 && swp->values[k-1] >= val; k--) {
85: swp->values[k] = swp->values[k-1];
86: swp->labels[k] = swp->labels[k-1];
87: }
88: if (k < swp->ncases && swp->values[k] == val)
89: error("duplicate case label `%d'\n", val);
90: swp->values[k] = val;
91: swp->labels[k] = findlabel(lab);
92: ++swp->ncases;
93: if (Aflag >= 2 && swp->ncases == 258)
94: warning("more than 257 cases in a switch statement\n");
95: }
96:
97: /* cmp - generate code for `if (p op n) goto lab' for integer n */
98: static void cmp(op, p, n, lab) Symbol p; {
99: listnodes(eqnode(op, cast(idnode(p), inttype), constnode(n, inttype)), lab, 0);
100: }
101:
102: /* definelab - define a label */
103: void definelab(lab) {
104: Code cp;
105:
106: walk(0, 0, 0);
107: code(Label);
108: codelist->u.node = newnode(LABEL+V, 0, 0, findlabel(lab));
109: for (cp = codelist; cp->kind <= Label; )
110: cp = cp->prev;
111: while (cp->kind == Jump && cp->u.node && cp->u.node->kids[0]
112: && cp->u.node->kids[0]->op == ADDRG+P
113: && cp->u.node->kids[0]->syms[0]->u.l.label == lab) {
114: cp->u.node->kids[0]->syms[0]->ref--;
115: assert(cp->next);
116: cp->prev->next = cp->next;
117: cp->next->prev = cp->prev;
118: cp = cp->prev;
119: }
120: }
121:
122: /* definept - define an execution point n: current token at current pc */
123: Code definept(p) Coordinate *p; {
124: int n;
125: Code cp = code(Defpoint);
126:
127: cp->u.point.src = p ? *p : src;
128: cp->u.point.point = npoints;
129: if (ncalled > 0 && (n = findcount(src.file, src.x, src.y)) >= 0)
130: refinc = n/ncalled + 1;
131: if (glevel > 2)
132: locus(identifiers, &cp->u.point.src);
133: if (events.points) {
134: Tree e = 0;
135: apply(events.points, (Generic)&cp->u.point.src, (Generic)&e);
136: if (e)
137: listnodes(e, 0, 0);
138: }
139: return cp;
140: }
141:
142: /* dostmt - do statement while ( expression ) */
143: static void dostmt(lab, swp, lev) struct swtch *swp; {
144: refinc *= 10;
145: t = gettok();
146: definelab(lab);
147: statement(lab, swp, lev);
148: definelab(lab + 1);
149: expect(WHILE);
150: expect('(');
151: definept(0);
152: walk(conditional(')'), lab, 0);
153: if (findlabel(lab + 2)->ref)
154: definelab(lab + 2);
155: }
156:
157: /* equatelab - add new=old to list of deferred equates */
158: void equatelab(new, old) Symbol new, old; {
159: struct equate *e = (struct equate *) talloc(sizeof *e);
160:
161: e->new = new;
162: e->old = old;
163: e->oldlink = 0;
164: e->link = equlist;
165: equlist = e;
166: for (e = e->link; e; e = e->link)
167: if (e->old == new)
168: e->oldlink = equlist;
169: else if (e->new == old)
170: equlist->oldlink = e;
171: }
172:
173: /* flushequ - flush deferred equates */
174: void flushequ() {
175: for ( ; equlist; equlist = equlist->link)
176: visit(equlist);
177: }
178:
179: /* foldcond - check if initial test in for(e1;e2;e3) S is necessary */
180: static int foldcond(e1, e2) Tree e1, e2; {
181: Opcode op = generic(e2->op);
182: Symbol v;
183:
184: if (e1 == 0 || e2 == 0)
185: return 0;
186: if (generic(e1->op) == ASGN && isaddrop(e1->kids[0]->op)
187: && generic(e1->kids[1]->op) == CNST) {
188: v = e1->kids[0]->u.sym;
189: e1 = e1->kids[1];
190: } else
191: return 0;
192: if ((op==LE || op==LT || op==EQ || op==NE || op==GT || op==GE)
193: && generic(e2->kids[0]->op) == INDIR
194: && e2->kids[0]->kids[0]->u.sym == v
195: && e2->kids[1]->op == e1->op) {
196: e1 = simplify(op, e2->type, e1, e2->kids[1]);
197: if (e1->op == CNST+I)
198: return e1->u.v.i;
199: }
200: return 0;
201: }
202:
203: /* forstmt - for ( [expr1] ; [expr2] ; [expr3] ) statement */
204: static void forstmt(lab, swp, lev) struct swtch *swp; {
205: Tree e1, e2, e3;
206: Coordinate pt2, pt3;
207: static char follow[] = { IF, ID, '}', 0 };
208:
209: e1 = e2 = e3 = 0;
210: t = gettok();
211: expect('(');
212: definept(0);
213: if (kind[t] == ID)
214: e1 = expr0(';');
215: else
216: expect(';');
217: walk(e1, 0, 0);
218: pt2 = src;
219: refinc *= 10;
220: if (kind[t] == ID)
221: e2 = texpr(conditional, ';');
222: else
223: expect(';');
224: pt3 = src;
225: if (kind[t] == ID)
226: e3 = texpr(expr0, ')');
227: else
228: test(')', follow);
229: if (glevel == 2) { /* e1; L: if (!e2) goto L+2; S; L+1: e3; goto L; L+2: */
230: definelab(lab);
231: definept(&pt2);
232: if (e2)
233: walk(e2, 0, lab + 2);
234: statement(lab, swp, lev);
235: definelab(lab + 1);
236: definept(&pt3);
237: if (e3)
238: walk(e3, 0, 0);
239: branch(lab);
240: } else { /* e1; goto L+3; L: S; L+1: e3; L+3: if (e2) goto L; L+2: */
241: int once = 0;
242: if (e2) {
243: once = foldcond(e1, e2);
244: if (!once)
245: branch(lab + 3);
246: }
247: definelab(lab);
248: statement(lab, swp, lev);
249: definelab(lab + 1);
250: definept(&pt3);
251: if (e3)
252: walk(e3, 0, 0);
253: if (e2) {
254: if (!once)
255: definelab(lab + 3);
256: definept(&pt2);
257: walk(e2, lab, 0);
258: } else {
259: definept(&pt2);
260: branch(lab);
261: }
262: }
263: if (findlabel(lab + 2)->ref)
264: definelab(lab + 2);
265: }
266:
267: /* ifstmt - if ( expression ) statement [ else statement ] */
268: static void ifstmt(lab, loop, swp, lev) struct swtch *swp; {
269: t = gettok();
270: expect('(');
271: definept(0);
272: walk(conditional(')'), 0, lab);
273: refinc /= 2;
274: statement(loop, swp, lev);
275: if (t == ELSE) {
276: branch(lab + 1);
277: t = gettok();
278: definelab(lab);
279: statement(loop, swp, lev);
280: if (findlabel(lab + 1)->ref)
281: definelab(lab + 1);
282: } else
283: definelab(lab);
284: }
285:
286: /* localaddr - returns q if p yields the address of local/parameter q; otherwise returns 0 */
287: static Symbol localaddr(p) Tree p; {
288: if (p == 0)
289: return 0;
290: switch (generic(p->op)) {
291: case INDIR: case CALL: case ARG:
292: return 0;
293: case ADDRL: case ADDRF:
294: return p->u.sym;
295: case RIGHT: case ASGN:
296: if (p->kids[1])
297: return localaddr(p->kids[1]);
298: return localaddr(p->kids[0]);
299: case COND: {
300: Symbol q;
301: if (p->kids[1] && (q = localaddr(p->kids[1])))
302: return q;
303: return localaddr(p->kids[2]);
304: }
305: default: {
306: Symbol q;
307: if (p->kids[0] && (q = localaddr(p->kids[0])))
308: return q;
309: return localaddr(p->kids[1]);
310: }
311: }
312: }
313:
314: /* retcode - return p from the current function */
315: void retcode(p, lab) Tree p; {
316: if (p == 0) {
317: if (events.returns)
318: apply(events.returns, (Generic)cfunc, (Generic)0);
319: p = tree(RET+V, voidtype, 0, 0);
320: } else {
321: Type ty;
322: p = pointer(p);
323: if (ty = assign(freturn(cfunc->type), p))
324: p = cast(p, ty);
325: else
326: error("illegal return type; found `%t' expected `%t'\n",
327: p->type, freturn(cfunc->type));
328: if (retv) {
329: if (p->op == RIGHT && p->kids[0]->op == CALL+B
330: && p->kids[1]->op == INDIR+B) {
331: p = p->kids[0];
332: p->kids[1] = idnode(retv);
333: } else
334: p = asgnnode(ASGN, rvalue(idnode(retv)), p);
335: walk(p, 0, 0);
336: if (events.returns)
337: apply(events.returns, (Generic)cfunc, (Generic)rvalue(idnode(retv)));
338: p = tree(RET+V, voidtype, 0, 0);
339: } else {
340: if (events.returns) {
341: Symbol t1 = genident(AUTO, p->type, level);
342: addlocal(t1);
343: walk(asgn(t1, p), 0, 0);
344: apply(events.returns, (Generic)cfunc, (Generic)idnode(t1));
345: p = idnode(t1);
346: }
347: p = cast(p, promote(p->type));
348: if (isptr(p->type)) {
349: Symbol q = localaddr(p);
350: if (q && (q->computed || q->generated))
351: warning("pointer to a %s is an illegal return value\n",
352: q->scope == PARAM ? "parameter" : "local");
353: else if (q)
354: warning("pointer to %s `%s' is an illegal return value\n",
355: q->scope == PARAM ? "parameter" : "local", q->name);
356: p = cast(p, unsignedtype);
357: }
358: p = tree(RET + widen(p->type), p->type, p, 0);
359: }
360: }
361: walk(p, 0, 0);
362: branch(lab);
363: }
364:
365: /* statement - parse statements */
366: void statement(loop, swp, lev) struct swtch *swp; {
367: int lab;
368: float ref = refinc;
369:
370: if (Aflag >= 2 && lev == 15)
371: warning("more than 15 levels of nested statements\n");
372: switch (t) {
373: case IF:
374: ifstmt(genlabel(2), loop, swp, lev + 1);
375: break;
376: case WHILE:
377: whilestmt(genlabel(3), swp, lev + 1);
378: break;
379: case DO:
380: dostmt(genlabel(3), swp, lev + 1);
381: expect(';');
382: break;
383: case FOR:
384: forstmt(genlabel(4), swp, lev + 1);
385: break;
386: case SWITCH:
387: swstmt(loop, genlabel(2), lev + 1);
388: break;
389: case CASE:
390: if (swp == 0)
391: error("illegal case label\n");
392: definelab(lab = genlabel(1));
393: while (t == CASE) {
394: static char follow[] = { IF, ID, 0 };
395: Tree p;
396: t = gettok();
397: p = constexpr(0);
398: if (generic(p->op) == CNST && isint(p->type)) {
399: if (swp) {
400: needconst++;
401: p = cast(p, swp->sym->type);
402: needconst--;
403: caselabel(swp, p->u.v.i, lab);
404: }
405: } else
406: error("case label must be a constant integer expression\n");
407: test(':', follow);
408: ntree = 0;
409: }
410: statement(loop, swp, lev);
411: break;
412: case DEFAULT:
413: if (swp)
414: if (swp->deflab)
415: error("extra default label\n");
416: else {
417: swp->deflab = findlabel(swp->lab);
418: definelab(swp->deflab->u.l.label);
419: }
420: else
421: error("illegal default label\n");
422: t = gettok();
423: expect(':');
424: statement(loop, swp, lev);
425: break;
426: case RETURN:
427: t = gettok();
428: definept(0);
429: if (t != ';')
430: if (freturn(cfunc->type) == voidtype) {
431: error("extraneous return value\n");
432: expr(0);
433: retcode(0, cfunc->u.f.label);
434: } else
435: retcode(expr(0), cfunc->u.f.label);
436: else {
437: if (freturn(cfunc->type) != voidtype
438: && (freturn(cfunc->type) != inttype || Aflag >= 1))
439: warning("missing return value\n");
440: retcode(0, cfunc->u.f.label);
441: }
442: expect(';');
443: break;
444: case BREAK:
445: walk(0, 0, 0);
446: if (swp && swp->lab > loop) {
447: definept(0);
448: branch(swp->lab + 1);
449: t = gettok();
450: expect(';');
451: break;
452: }
453: case CONTINUE:
454: walk(0, 0, 0);
455: definept(0);
456: if (loop)
457: branch(loop + (t == BREAK ? 2 : 1));
458: else
459: error("illegal %k statement\n", t);
460: t = gettok();
461: expect(';');
462: break;
463: case '{':
464: compound(loop, swp, lev + 1);
465: break;
466: case ';':
467: definept(0);
468: t = gettok();
469: break;
470: case GOTO:
471: walk(0, 0, 0);
472: definept(0);
473: t = gettok();
474: if (t == ID) {
475: Symbol p = lookup(token, labels[0]);
476: if (p == 0) {
477: p = install(token, &labels[0], 0);
478: p->u.l.label = genlabel(1);
479: p->u.l.equatedto = p;
480: p->src = src;
481: }
482: p->ref++;
483: use(p, src);
484: branch(p->u.l.label);
485: t = gettok();
486: } else
487: error("missing label in goto\n");
488: expect(';');
489: break;
490: case ID:
491: if (getchr() == ':') {
492: stmtlabel(token);
493: statement(loop, swp, lev);
494: break;
495: }
496: default:
497: definept(0);
498: if (kind[t] != ID) {
499: error("unrecognized statement\n");
500: t = gettok();
501: } else {
502: Tree e = expr0(0);
503: listnodes(e, 0, 0);
504: if (glevel > 1 || nodecount == 0 || nodecount > 200)
505: walk(0, 0, 0);
506: ntree = 0;
507: }
508: expect(';');
509: }
510: if (kind[t] != IF && kind[t] != ID && t != '}' && t != EOI) {
511: static char follow[] = { IF, ID, '}', 0 };
512: error("illegal statement termination\n");
513: skipto(0, follow);
514: }
515: refinc = ref;
516: }
517:
518: /* stmtlabel - label : */
519: static void stmtlabel(label) char *label; {
520: Symbol p;
521:
522: if ((p = lookup(label, labels[0])) == 0) {
523: p = install(label, &labels[0], 0);
524: p->u.l.label = genlabel(1);
525: p->u.l.equatedto = p;
526: }
527: if (p->defined)
528: error("redefinition of label `%s' previously defined at %w\n",
529: label, &p->src);
530: p->defined = 1;
531: p->src = src;
532: definelab(p->u.l.label);
533: t = gettok();
534: expect(':');
535: }
536:
537: /* swcode - generate switch decision code for buckets b[lb..ub] */
538: static int swcode(swp, b, lb, ub, n) struct swtch *swp; int b[]; {
539: int hilab, k, l, lolab, median, u, *v;
540:
541: v = swp->values;
542: median = ((float)v[b[lb]] + (float)v[b[ub+1]-1] + 1)/2;
543: for (l = lb, u = ub; l <= u; ) {
544: k = (l + u)/2;
545: if (v[b[k]] > median)
546: u = k - 1;
547: else if (v[b[k+1]-1] < median)
548: l = k + 1;
549: else
550: break;
551: }
552: if (l > u) { /* which of two buckets is closest to the median? */
553: l = b[k];
554: u = b[k+1] - 1;
555: if (median < v[l] && k > lb && v[l] - median > median - v[l-1])
556: k--;
557: else if (median > v[u] && k < ub && median - v[u] > v[u+1] - median)
558: k++;
559: }
560: l = b[k];
561: u = b[k+1] - 1;
562: lolab = hilab = swp->deflab->u.l.label;
563: if (k > lb) {
564: lolab = 0;
565: if (k < ub)
566: hilab = genlabel(1);
567: } else if (k < ub)
568: hilab = 0;
569: if (n == 0)
570: lolab = hilab = 0;
571: if (u - l + 1 <= 3) {
572: int i;
573: for (i = l; i <= u; i++)
574: cmp(EQ, swp->sym, swp->values[i], swp->labels[i]->u.l.label);
575: if (lolab && lolab == hilab)
576: branch(lolab);
577: else {
578: if (lolab)
579: cmp(LT, swp->sym, swp->values[l], lolab);
580: if (hilab)
581: cmp(GT, swp->sym, swp->values[u], hilab);
582: walk(0, 0, 0);
583: }
584: } else {
585: int lab = genlabel(2);
586: Tree e;
587: cmp(LT, swp->sym, swp->values[l], lolab ? lolab : lab);
588: cmp(GT, swp->sym, swp->values[u], hilab ? hilab : lab);
589: e = tree(ADDRG+P, ptr(voidptype), 0, 0);
590: e->u.sym = findlabel(lab + 1);
591: e->u.sym->sclass = STATIC;
592: e->u.sym->type = e->type;
593: walk(tree(JUMP, voidtype, rvalue((*opnode['+'])(ADD, e,
594: (*opnode['-'])(SUB, cast(idnode(swp->sym), inttype),
595: constnode(swp->values[l], inttype)))), 0), 0, 0);
596: definelab(lab + 1);
597: code(Switch);
598: codelist->u.swtch.sym = swp->sym;
599: codelist->u.swtch.deflab = swp->deflab;
600: codelist->u.swtch.size = u - l + 1;
601: codelist->u.swtch.values = &swp->values[l];
602: codelist->u.swtch.labels = &swp->labels[l];
603: branch(0);
604: definelab(lab);
605: if (swp->values[u] - swp->values[l] + 1 >= 10000)
606: warning("switch generates a huge table\n");
607: }
608: if (k > lb)
609: n = swcode(swp, b, lb, k - 1, n - 1);
610: if (k < ub) {
611: if (hilab)
612: definelab(hilab);
613: n = swcode(swp, b, k + 1, ub, n - 1);
614: }
615: return n;
616: }
617:
618: /* swgen - partition case labels into buckets, initiate code generation */
619: #define den(k,n) ((float)(k-buckets[n]+1)/(float)(v[k]-v[buckets[n]]+1))
620: static void swgen(swp) struct swtch *swp; {
621: int *buckets, k, n, *v;
622:
623: if (swp->ncases == 0)
624: return;
625: buckets = (int *) talloc((swp->ncases + 1)*sizeof *buckets);
626: v = swp->values;
627: n = 0;
628: for (k = 0; k < swp->ncases; k++, n++) {
629: buckets[n] = k;
630: while (n > 0) {
631: float d = den(k, n-1);
632: if (d < density || k < swp->ncases - 1 && d < den(k+1, n))
633: break;
634: n--;
635: }
636: }
637: buckets[n--] = swp->ncases;
638: swcode(swp, buckets, 0, n, n);
639: }
640:
641: /* swstmt - switch ( expression ) statement */
642: static void swstmt(loop, lab, lev) {
643: Tree e;
644: struct swtch sw;
645: Code head, tail;
646:
647: t = gettok();
648: expect('(');
649: definept(0);
650: e = expr(')');
651: if (!isint(e->type)) {
652: error("illegal type `%t' in switch expression\n", e->type);
653: e = retype(e, inttype);
654: }
655: e = cast(e, promote(e->type));
656: if (generic(e->op) == INDIR && isaddrop(e->kids[0]->op)
657: && e->kids[0]->u.sym->type == e->type && !isvolatile(e->kids[0]->u.sym->type)) {
658: sw.sym = e->kids[0]->u.sym;
659: walk(0, 0, 0);
660: } else {
661: sw.sym = genident(REGISTER, e->type, level);
662: addlocal(sw.sym);
663: walk(asgn(sw.sym, e), 0, 0);
664: }
665: code(Switch);
666: head = codelist;
667: sw.lab = lab;
668: sw.deflab = 0;
669: sw.ncases = 0;
670: sw.size = SWITCHSIZE;
671: sw.values = (int *) talloc(SWITCHSIZE*sizeof (int));
672: sw.labels = (Symbol *) talloc(SWITCHSIZE*sizeof (Symbol));
673: refinc /= 10;
674: statement(loop, &sw, lev);
675: if (sw.deflab == 0) {
676: sw.deflab = findlabel(lab);
677: definelab(lab);
678: if (sw.ncases == 0)
679: warning("switch statement with no cases\n");
680: }
681: if (findlabel(lab + 1)->ref)
682: definelab(lab + 1);
683: tail = codelist;
684: codelist = head->prev;
685: swgen(&sw);
686: branch(lab);
687: head->next->prev = codelist;
688: codelist->next = head->next;
689: codelist = tail;
690: }
691:
692: /* visit - equate p->new=p->old, equating predecessor first */
693: static void visit(p) struct equate *p; {
694: if (p && p->old) {
695: visit(p->oldlink);
696: p->new->u.l.equatedto = p->old->u.l.equatedto;
697: p->old = 0;
698: }
699: }
700:
701: /* whilestmt - while ( expression ) statement */
702: static void whilestmt(lab, swp, lev) struct swtch *swp; {
703: Coordinate pt;
704: Tree e;
705:
706: refinc *= 10;
707: t = gettok();
708: expect('(');
709: walk(0, 0, 0);
710: pt = src;
711: e = texpr(conditional, ')');
712: if (generic(e->op) == CNST || glevel == 2) {
713: /* L, L+1: if (!e) goto L+2; S; goto L; L+2: */
714: definelab(lab);
715: definelab(lab + 1);
716: definept(&pt);
717: walk(e, 0, lab + 2);
718: statement(lab, swp, lev);
719: branch(lab);
720: } else { /* goto L+1; L: S; L+1: if (E) goto L; L+2: */
721: branch(lab + 1);
722: definelab(lab);
723: statement(lab, swp, lev);
724: definelab(lab + 1);
725: definept(&pt);
726: walk(e, lab, 0);
727: }
728: if (findlabel(lab + 2)->ref)
729: definelab(lab + 2);
730: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.