|
|
1.1 root 1: /* Generate code from to output assembler insns as recognized from rtl.
2: Copyright (C) 1987 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: /* This program reads the machine description for the compiler target machine
23: and produces a file containing three things:
24:
25: 1, An array of strings `insn_template' which is indexed by insn code number
26: and contains the template for output of that insn,
27:
28: 2. An array of ints `insn_n_operands' which is indexed by insn code number
29: and contains the number of distinct operands in the pattern for that insn,
30:
31: 3. An array of ints `insn_n_dups' which is indexed by insn code number
32: and contains the number of match_dup's that appear in the insn's pattern.
33: This says how many elements of `recog_dup_loc' are significant
34: after an insn has been recognized.
35:
1.1.1.2 root 36: 4. An array of arrays of operand constraint strings,
1.1 root 37: `insn_operand_constraint',
38: indexed first by insn code number and second by operand number,
39: containing the constraint for that operand.
1.1.1.2 root 40:
1.1 root 41: This array is generated only if register constraints appear in
42: match_operand rtx's.
43:
1.1.1.2 root 44: 5. An array of arrays of chars which indicate which operands of
1.1 root 45: which insn patterns appear within ADDRESS rtx's. This array is
46: called `insn_operand_address_p' and is generated only if there
47: are *no* register constraints in the match_operand rtx's.
48:
1.1.1.2 root 49: 6. An array of arrays of machine modes, `insn_operand_mode',
50: indexed first by insn code number and second by operand number,
51: containing the machine mode that that operand is supposed to have.
52: Also `insn_operand_strict_low', which is nonzero for operands
53: contained in a STRICT_LOW_PART.
54:
55: 7. An array of arrays of int-valued functions, `insn_operand_predicate',
56: indexed first by insn code number and second by operand number,
57: containing the match_operand predicate for this operand.
58:
59: 8. An array of functions `insn_gen_function' which, indexed
1.1 root 60: by insn code number, gives the function to generate a body
61: for that patter, given operands as arguments.
62:
1.1.1.2 root 63: 9. A function `output_insn_hairy' which is called with two arguments
1.1 root 64: (an insn code number and a vector of operand value rtx's)
65: and returns a template to use for output of that insn.
66: This is used only in the cases where the template is not constant.
67: These cases are specified by a * at the beginning of the template string
68: in the machine description. They are identified for the sake of
69: other parts of the compiler by a zero element in `insn_template'.
1.1.1.4 ! root 70:
! 71: 10. An array of structures, `insn_machine_info', that gives machine-specific
! 72: information about the insn.
1.1 root 73:
74: The code number of an insn is simply its position in the machine description;
75: code numbers are assigned sequentially to entries in the description,
76: starting with code number 0.
77:
78: Thus, the following entry in the machine description
79:
80: (define_insn "clrdf"
81: [(set (match_operand:DF 0 "general_operand" "")
82: (const_int 0))]
83: ""
84: "clrd %0")
85:
86: assuming it is the 25th entry present, would cause
1.1.1.2 root 87: insn_template[24] to be "clrd %0", and insn_n_operands[24] to be 1.
1.1 root 88: It would not make an case in output_insn_hairy because the template
89: given in the entry is a constant (it does not start with `*'). */
90:
91: #include <stdio.h>
1.1.1.2 root 92: #include "config.h"
1.1 root 93: #include "rtl.h"
1.1.1.2 root 94: #include "obstack.h"
1.1 root 95:
96: /* No instruction can have more operands than this.
97: Sorry for this arbitrary limit, but what machine will
98: have an instruction with this many operands? */
99:
100: #define MAX_MAX_OPERANDS 40
101:
102: struct obstack obstack;
1.1.1.2 root 103: struct obstack *rtl_obstack = &obstack;
1.1 root 104:
105: #define obstack_chunk_alloc xmalloc
106: #define obstack_chunk_free free
107: extern int xmalloc ();
108: extern void free ();
109:
110: void fatal ();
1.1.1.2 root 111: void mybcopy ();
112: void mybzero ();
1.1 root 113:
114: /* insns in the machine description are assigned sequential code numbers
115: that are used by insn-recog.c (produced by genrecog) to communicate
116: to insn-output.c (produced by this program). */
117:
118: int next_code_number;
119:
120: /* Record in this chain all information that we will output,
121: associated with the code number of the insn. */
122:
123: struct data
124: {
125: int code_number;
126: char *name;
127: char *template; /* string such as "movl %1,%0" */
128: int n_operands; /* Number of operands this insn recognizes */
129: int n_dups; /* Number times match_dup appears in pattern */
130: struct data *next;
131: char *constraints[MAX_MAX_OPERANDS];
1.1.1.2 root 132: char *predicates[MAX_MAX_OPERANDS];
1.1 root 133: char address_p[MAX_MAX_OPERANDS];
134: enum machine_mode modes[MAX_MAX_OPERANDS];
1.1.1.2 root 135: char strict_low[MAX_MAX_OPERANDS];
136: char outfun; /* Nonzero means this has an output function */
1.1.1.4 ! root 137: char *machine_info; /* machine-specific info string. */
1.1 root 138: };
139:
140: /* This variable points to the first link in the chain. */
141:
142: struct data *insn_data;
143:
144: /* Pointer to the last link in the chain, so new elements
145: can be added at the end. */
146:
147: struct data *end_of_insn_data;
148:
149: /* Nonzero if any match_operand has a constraint string;
150: implies that REGISTER_CONSTRAINTS will be defined
151: for this machine description. */
152:
153: int have_constraints;
154:
155: void
156: output_prologue ()
157: {
158:
159: printf ("/* Generated automatically by the program `genoutput'\n\
160: from the machine description file `md'. */\n\n");
161:
162: printf ("#include \"config.h\"\n");
163: printf ("#include \"rtl.h\"\n");
164: printf ("#include \"regs.h\"\n");
165: printf ("#include \"conditions.h\"\n");
166: printf ("#include \"insn-flags.h\"\n");
167: printf ("#include \"insn-config.h\"\n\n");
168:
1.1.1.4 ! root 169: printf ("#ifndef __STDC__\n");
! 170: printf ("#define const\n");
! 171: printf ("#endif\n\n");
! 172:
! 173: printf ("#include \"output.h\"\n");
1.1 root 174: printf ("#include \"aux-output.c\"\n\n");
1.1.1.4 ! root 175:
! 176: /* Make sure there is at least a dummy definition of INSN_MACHINE_INFO. */
! 177: printf ("#ifndef INSN_MACHINE_INFO\n");
! 178: printf ("#define INSN_MACHINE_INFO struct dummy1 {int i;}\n");
! 179: printf ("#endif\n\n");
1.1 root 180: }
181:
182: void
183: output_epilogue ()
184: {
185: register struct data *d;
186:
1.1.1.4 ! root 187: printf ("\nchar * const insn_template[] =\n {\n");
1.1 root 188: for (d = insn_data; d; d = d->next)
189: {
190: if (d->template)
191: printf (" \"%s\",\n", d->template);
192: else
193: printf (" 0,\n");
194: }
195: printf (" };\n");
196:
1.1.1.4 ! root 197: printf ("\nchar *(*const insn_outfun[])() =\n {\n");
1.1.1.2 root 198: for (d = insn_data; d; d = d->next)
199: {
200: if (d->outfun)
1.1.1.3 root 201: printf (" output_%d,\n", d->code_number);
1.1.1.2 root 202: else
203: printf (" 0,\n");
204: }
205: printf (" };\n");
206:
1.1.1.4 ! root 207: printf ("\nrtx (*const insn_gen_function[]) () =\n {\n");
1.1 root 208: for (d = insn_data; d; d = d->next)
209: {
210: if (d->name)
211: printf (" gen_%s,\n", d->name);
212: else
213: printf (" 0,\n");
214: }
215: printf (" };\n");
216:
1.1.1.4 ! root 217: printf ("\nconst int insn_n_operands[] =\n {\n");
1.1 root 218: for (d = insn_data; d; d = d->next)
219: {
220: printf (" %d,\n", d->n_operands);
221: }
222: printf (" };\n");
223:
1.1.1.4 ! root 224: printf ("\nconst int insn_n_dups[] =\n {\n");
1.1 root 225: for (d = insn_data; d; d = d->next)
226: {
227: printf (" %d,\n", d->n_dups);
228: }
229: printf (" };\n");
230:
231: if (have_constraints)
232: {
1.1.1.4 ! root 233: printf ("\nchar *const insn_operand_constraint[][MAX_RECOG_OPERANDS] =\n {\n");
1.1 root 234: for (d = insn_data; d; d = d->next)
235: {
236: register int i;
237: printf (" {");
238: for (i = 0; i < d->n_operands; i++)
1.1.1.2 root 239: {
240: if (d->constraints[i] == 0)
241: printf (" \"\",");
242: else
243: printf (" \"%s\",", d->constraints[i]);
244: }
1.1 root 245: if (d->n_operands == 0)
246: printf (" 0");
247: printf (" },\n");
248: }
249: printf (" };\n");
250: }
251: else
252: {
1.1.1.4 ! root 253: printf ("\nconst char insn_operand_address_p[][MAX_RECOG_OPERANDS] =\n {\n");
1.1 root 254: for (d = insn_data; d; d = d->next)
255: {
256: register int i;
257: printf (" {");
258: for (i = 0; i < d->n_operands; i++)
259: printf (" %d,", d->address_p[i]);
260: if (d->n_operands == 0)
261: printf (" 0");
262: printf (" },\n");
263: }
264: printf (" };\n");
265: }
266:
1.1.1.4 ! root 267: printf ("\nconst enum machine_mode insn_operand_mode[][MAX_RECOG_OPERANDS] =\n {\n");
1.1 root 268: for (d = insn_data; d; d = d->next)
269: {
270: register int i;
271: printf (" {");
272: for (i = 0; i < d->n_operands; i++)
273: printf (" %smode,", GET_MODE_NAME (d->modes[i]));
274: if (d->n_operands == 0)
275: printf (" VOIDmode");
276: printf (" },\n");
277: }
278: printf (" };\n");
1.1.1.2 root 279:
1.1.1.4 ! root 280: printf ("\nconst char insn_operand_strict_low[][MAX_RECOG_OPERANDS] =\n {\n");
1.1.1.2 root 281: for (d = insn_data; d; d = d->next)
282: {
283: register int i;
284: printf (" {");
285: for (i = 0; i < d->n_operands; i++)
286: printf (" %d,", d->strict_low[i]);
287: if (d->n_operands == 0)
288: printf (" 0");
289: printf (" },\n");
290: }
291: printf (" };\n");
292:
1.1.1.4 ! root 293: printf ("\nint (*const insn_operand_predicate[][MAX_RECOG_OPERANDS])() =\n {\n");
1.1.1.2 root 294: for (d = insn_data; d; d = d->next)
295: {
296: register int i;
297: printf (" {");
298: for (i = 0; i < d->n_operands; i++)
299: printf (" %s,", ((d->predicates[i] && d->predicates[i][0])
300: ? d->predicates[i] : "0"));
301: if (d->n_operands == 0)
302: printf (" 0");
303: printf (" },\n");
304: }
305: printf (" };\n");
1.1.1.4 ! root 306:
! 307: printf ("\nconst INSN_MACHINE_INFO insn_machine_info[] =\n {\n");
! 308: for (d = insn_data; d; d = d->next)
! 309: {
! 310: if (d->machine_info)
! 311: printf (" {%s},\n", d->machine_info);
! 312: else
! 313: printf(" {0},\n");
! 314: }
! 315: printf(" };\n");
1.1 root 316: }
317:
318: /* scan_operands (X) stores in max_opno the largest operand
319: number present in X, if that is larger than the previous
320: value of max_opno. It stores all the constraints in `constraints'
1.1.1.2 root 321: and all the machine modes in `modes'.
322:
323: THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS.
324: THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART. */
1.1 root 325:
326: int max_opno;
327: int num_dups;
328: char *constraints[MAX_MAX_OPERANDS];
1.1.1.2 root 329: char *predicates[MAX_MAX_OPERANDS];
1.1 root 330: char address_p[MAX_MAX_OPERANDS];
331: enum machine_mode modes[MAX_MAX_OPERANDS];
1.1.1.2 root 332: char strict_low[MAX_MAX_OPERANDS];
1.1 root 333:
334: void
1.1.1.2 root 335: scan_operands (part, this_address_p, this_strict_low)
1.1 root 336: rtx part;
337: int this_address_p;
1.1.1.2 root 338: int this_strict_low;
1.1 root 339: {
340: register int i, j;
1.1.1.2 root 341: register RTX_CODE code;
1.1 root 342: register char *format_ptr;
343:
1.1.1.2 root 344: if (part == 0)
345: return;
346:
347: code = GET_CODE (part);
348:
1.1 root 349: if (code == MATCH_OPERAND)
350: {
1.1.1.2 root 351: int opno = XINT (part, 0);
352: if (opno > max_opno)
353: max_opno = opno;
354: if (max_opno >= MAX_MAX_OPERANDS)
1.1 root 355: fatal ("Too many operands (%d) in one instruction pattern.\n",
356: max_opno + 1);
1.1.1.2 root 357: modes[opno] = GET_MODE (part);
358: strict_low[opno] = this_strict_low;
359: predicates[opno] = XSTR (part, 1);
360: constraints[opno] = XSTR (part, 2);
1.1 root 361: if (XSTR (part, 2) != 0 && *XSTR (part, 2) != 0)
362: have_constraints = 1;
1.1.1.2 root 363: address_p[opno] = this_address_p;
1.1 root 364: return;
365: }
366:
367: if (code == MATCH_DUP)
368: {
369: ++num_dups;
370: return;
371: }
372:
373: if (code == ADDRESS)
374: {
1.1.1.2 root 375: scan_operands (XEXP (part, 0), 1, 0);
376: return;
377: }
378:
379: if (code == STRICT_LOW_PART)
380: {
381: scan_operands (XEXP (part, 0), 0, 1);
1.1 root 382: return;
383: }
384:
385: format_ptr = GET_RTX_FORMAT (GET_CODE (part));
386:
387: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
388: switch (*format_ptr++)
389: {
390: case 'e':
1.1.1.2 root 391: scan_operands (XEXP (part, i), 0, 0);
1.1 root 392: break;
393: case 'E':
394: if (XVEC (part, i) != NULL)
395: for (j = 0; j < XVECLEN (part, i); j++)
1.1.1.2 root 396: scan_operands (XVECEXP (part, i, j), 0, 0);
1.1 root 397: break;
398: }
399: }
400:
1.1.1.2 root 401: /* Look at a define_insn just read. Assign its code number.
1.1 root 402: Record on insn_data the template and the number of arguments.
1.1.1.2 root 403: If the insn has a hairy output action, output a function for now. */
1.1 root 404:
405: void
406: gen_insn (insn)
407: rtx insn;
408: {
409: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
410: register int i;
411:
412: d->code_number = next_code_number++;
413: if (XSTR (insn, 0)[0])
414: d->name = XSTR (insn, 0);
415: else
416: d->name = 0;
417:
418: /* Build up the list in the same order as the insns are seen
419: in the machine description. */
420: d->next = 0;
421: if (end_of_insn_data)
422: end_of_insn_data->next = d;
423: else
424: insn_data = d;
425:
426: end_of_insn_data = d;
427:
428: max_opno = -1;
429: num_dups = 0;
430:
1.1.1.2 root 431: mybzero (constraints, sizeof constraints);
432: mybzero (predicates, sizeof predicates);
433: mybzero (address_p, sizeof address_p);
434: mybzero (modes, sizeof modes);
435: mybzero (strict_low, sizeof strict_low);
1.1 root 436: for (i = 0; i < XVECLEN (insn, 1); i++)
1.1.1.2 root 437: scan_operands (XVECEXP (insn, 1, i), 0, 0);
1.1 root 438: d->n_operands = max_opno + 1;
439: d->n_dups = num_dups;
1.1.1.2 root 440: mybcopy (constraints, d->constraints, sizeof constraints);
441: mybcopy (predicates, d->predicates, sizeof predicates);
442: mybcopy (address_p, d->address_p, sizeof address_p);
443: mybcopy (modes, d->modes, sizeof modes);
444: mybcopy (strict_low, d->strict_low, sizeof strict_low);
1.1.1.4 ! root 445: d->machine_info = XSTR (insn, 4);
1.1 root 446:
447: /* We need to consider only the instructions whose assembler code template
448: starts with a *. These are the ones where the template is really
449: C code to run to decide on a template to use.
450: So for all others just return now. */
451:
452: if (XSTR (insn, 3)[0] != '*')
453: {
454: d->template = XSTR (insn, 3);
1.1.1.2 root 455: d->outfun = 0;
1.1 root 456: return;
457: }
458:
459: d->template = 0;
1.1.1.2 root 460: d->outfun = 1;
461:
462: printf ("\nchar *\n");
463: printf ("output_%d (operands, insn)\n", d->code_number);
464: printf (" rtx *operands;\n");
465: printf (" rtx insn;\n");
466: printf ("{\n");
467: /* The following is done in a funny way to get around problems in
468: VAX-11 "C" on VMS. It is the equivalent of:
469: printf ("%s\n", &(XSTR (insn, 3)[1])); */
470: {
471: register char *cp = &(XSTR (insn, 3)[1]);
472: while (*cp) putchar (*cp++);
473: putchar ('\n');
474: }
475: printf ("}\n");
1.1 root 476: }
477:
1.1.1.2 root 478: /* Look at a define_peephole just read. Assign its code number.
479: Record on insn_data the template and the number of arguments.
480: If the insn has a hairy output action, output it now. */
481:
482: void
483: gen_peephole (peep)
484: rtx peep;
485: {
486: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
487: register int i;
488:
489: d->code_number = next_code_number++;
490: d->name = 0;
491:
492: /* Build up the list in the same order as the insns are seen
493: in the machine description. */
494: d->next = 0;
495: if (end_of_insn_data)
496: end_of_insn_data->next = d;
497: else
498: insn_data = d;
499:
500: end_of_insn_data = d;
501:
502: max_opno = -1;
503: mybzero (constraints, sizeof constraints);
504:
505: /* Get the number of operands by scanning all the
506: patterns of the peephole optimizer.
507: But ignore all the rest of the information thus obtained. */
508: for (i = 0; i < XVECLEN (peep, 0); i++)
509: scan_operands (XVECEXP (peep, 0, i), 0, 0);
510:
511: d->n_operands = max_opno + 1;
512: d->n_dups = 0;
513: mybcopy (constraints, d->constraints, sizeof constraints);
514: mybzero (d->predicates, sizeof predicates);
515: mybzero (d->address_p, sizeof address_p);
516: mybzero (d->modes, sizeof modes);
517: mybzero (d->strict_low, sizeof strict_low);
1.1.1.4 ! root 518: d->machine_info = XSTR (peep, 3);
1.1.1.2 root 519:
520: /* We need to consider only the instructions whose assembler code template
521: starts with a *. These are the ones where the template is really
522: C code to run to decide on a template to use.
523: So for all others just return now. */
524:
525: if (XSTR (peep, 2)[0] != '*')
526: {
527: d->template = XSTR (peep, 2);
528: d->outfun = 0;
529: return;
530: }
531:
532: d->template = 0;
533: d->outfun = 1;
534:
535: printf ("\nchar *\n");
536: printf ("output_%d (operands, insn)\n", d->code_number);
537: printf (" rtx *operands;\n");
538: printf (" rtx insn;\n");
539: printf ("{\n");
540: printf ("%s\n", &(XSTR (peep, 2)[1]));
541: printf ("}\n");
542: }
543:
544: /* Process a define_expand just read. Assign its code number,
545: only for the purposes of `insn_gen_function'. */
546:
547: void
548: gen_expand (insn)
549: rtx insn;
550: {
551: register struct data *d = (struct data *) xmalloc (sizeof (struct data));
552: register int i;
553:
554: d->code_number = next_code_number++;
555: if (XSTR (insn, 0)[0])
556: d->name = XSTR (insn, 0);
557: else
558: d->name = 0;
559:
560: /* Build up the list in the same order as the insns are seen
561: in the machine description. */
562: d->next = 0;
563: if (end_of_insn_data)
564: end_of_insn_data->next = d;
565: else
566: insn_data = d;
567:
568: end_of_insn_data = d;
569:
570: max_opno = -1;
571: num_dups = 0;
572:
573: /* Scan the operands to get the specified predicates and modes,
574: since expand_binop needs to know them. */
575:
576: mybzero (predicates, sizeof predicates);
577: mybzero (modes, sizeof modes);
578: if (XVEC (insn, 1))
579: for (i = 0; i < XVECLEN (insn, 1); i++)
580: scan_operands (XVECEXP (insn, 1, i), 0, 0);
581: d->n_operands = max_opno + 1;
582: mybcopy (predicates, d->predicates, sizeof predicates);
583: mybcopy (modes, d->modes, sizeof modes);
584:
585: mybzero (d->constraints, sizeof constraints);
586: mybzero (d->address_p, sizeof address_p);
587: mybzero (d->strict_low, sizeof strict_low);
588:
589: d->n_dups = 0;
590: d->template = 0;
591: d->outfun = 0;
1.1.1.4 ! root 592: d->machine_info = 0;
1.1.1.2 root 593: }
594:
595: int
1.1 root 596: xmalloc (size)
597: {
598: register int val = malloc (size);
599:
600: if (val == 0)
1.1.1.2 root 601: fatal ("virtual memory exhausted");
1.1 root 602: return val;
603: }
604:
605: int
606: xrealloc (ptr, size)
607: char *ptr;
608: int size;
609: {
610: int result = realloc (ptr, size);
611: if (!result)
1.1.1.2 root 612: fatal ("virtual memory exhausted");
1.1 root 613: return result;
614: }
615:
616: void
1.1.1.2 root 617: mybzero (b, length)
618: register char *b;
619: register int length;
620: {
621: while (length-- > 0)
622: *b++ = 0;
623: }
624:
625: void
626: mybcopy (b1, b2, length)
627: register char *b1;
628: register char *b2;
629: register int length;
630: {
631: while (length-- > 0)
632: *b2++ = *b1++;
633: }
634:
635: void
1.1 root 636: fatal (s, a1, a2)
637: {
1.1.1.2 root 638: fprintf (stderr, "genoutput: ");
1.1 root 639: fprintf (stderr, s, a1, a2);
640: fprintf (stderr, "\n");
1.1.1.2 root 641: exit (FATAL_EXIT_CODE);
1.1 root 642: }
643:
1.1.1.2 root 644: int
1.1 root 645: main (argc, argv)
646: int argc;
647: char **argv;
648: {
649: rtx desc;
650: FILE *infile;
651: extern rtx read_rtx ();
652: register int c;
653:
1.1.1.2 root 654: obstack_init (rtl_obstack);
1.1 root 655:
656: if (argc <= 1)
657: fatal ("No input file name.");
658:
659: infile = fopen (argv[1], "r");
660: if (infile == 0)
661: {
662: perror (argv[1]);
1.1.1.2 root 663: exit (FATAL_EXIT_CODE);
1.1 root 664: }
665:
666: init_rtl ();
667:
668: output_prologue ();
669: next_code_number = 0;
670: have_constraints = 0;
671:
672: /* Read the machine description. */
673:
674: while (1)
675: {
676: c = read_skip_spaces (infile);
677: if (c == EOF)
678: break;
679: ungetc (c, infile);
680:
681: desc = read_rtx (infile);
1.1.1.2 root 682: if (GET_CODE (desc) == DEFINE_INSN)
683: gen_insn (desc);
684: if (GET_CODE (desc) == DEFINE_PEEPHOLE)
685: gen_peephole (desc);
686: if (GET_CODE (desc) == DEFINE_EXPAND)
687: gen_expand (desc);
1.1 root 688: }
689:
690: output_epilogue ();
691:
1.1.1.2 root 692: fflush (stdout);
693: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
1.1 root 694: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.