2 * COFF file handling for TCC
4 * Copyright (c) 2003, 2004 TK
5 * Copyright (c) 2004 Fabrice Bellard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
26 #define MAX_STR_TABLE 1000000
27 AOUTHDR o_filehdr
; /* OPTIONAL (A.OUT) FILE HEADER */
29 SCNHDR section_header
[MAXNSCNS
];
31 #define MAX_FUNCS 1000
32 #define MAX_FUNC_NAME_LENGTH 128
35 char Func
[MAX_FUNCS
][MAX_FUNC_NAME_LENGTH
];
36 char AssociatedFile
[MAX_FUNCS
][MAX_FUNC_NAME_LENGTH
];
37 int LineNoFilePtr
[MAX_FUNCS
];
38 int EndAddress
[MAX_FUNCS
];
39 int LastLineNo
[MAX_FUNCS
];
40 int FuncEntries
[MAX_FUNCS
];
42 BOOL
OutputTheSection(Section
* sect
);
43 short int GetCoffFlags(const char *s
);
44 void SortSymbolTable(void);
45 Section
*FindSection(TCCState
* s1
, const char *sname
);
47 int C67_main_entry_point
;
49 int FindCoffSymbolIndex(const char *func_name
);
62 unsigned short lineno
;
63 unsigned short nentries
;
71 unsigned short lineno
;
72 unsigned short dummy1
;
75 unsigned short dummy4
;
78 ST_FUNC
int tcc_output_coff(TCCState
*s1
, FILE *f
)
83 char *Coff_str_table
, *pCoff_str_table
;
84 int CoffTextSectionNo
, coff_nb_syms
;
85 FILHDR file_hdr
; /* FILE HEADER STRUCTURE */
86 Section
*stext
, *sdata
, *sbss
;
87 int i
, NSectionsToOutput
= 0;
89 Coff_str_table
= pCoff_str_table
= NULL
;
91 stext
= FindSection(s1
, ".text");
92 sdata
= FindSection(s1
, ".data");
93 sbss
= FindSection(s1
, ".bss");
95 nb_syms
= symtab_section
->data_offset
/ sizeof(Elf32_Sym
);
96 coff_nb_syms
= FindCoffSymbolIndex("XXXXXXXXXX1");
98 file_hdr
.f_magic
= COFF_C67_MAGIC
; /* magic number */
99 file_hdr
.f_timdat
= 0; /* time & date stamp */
100 file_hdr
.f_opthdr
= sizeof(AOUTHDR
); /* sizeof(optional hdr) */
101 file_hdr
.f_flags
= 0x1143; /* flags (copied from what code composer does) */
102 file_hdr
.f_TargetID
= 0x99; /* for C6x = 0x0099 */
104 o_filehdr
.magic
= 0x0108; /* see magic.h */
105 o_filehdr
.vstamp
= 0x0190; /* version stamp */
106 o_filehdr
.tsize
= stext
->data_offset
; /* text size in bytes, padded to FW bdry */
107 o_filehdr
.dsize
= sdata
->data_offset
; /* initialized data " " */
108 o_filehdr
.bsize
= sbss
->data_offset
; /* uninitialized data " " */
109 o_filehdr
.entrypt
= C67_main_entry_point
; /* entry pt. */
110 o_filehdr
.text_start
= stext
->sh_addr
; /* base of text used for this file */
111 o_filehdr
.data_start
= sdata
->sh_addr
; /* base of data used for this file */
114 // create all the section headers
116 file_pointer
= FILHSZ
+ sizeof(AOUTHDR
);
118 CoffTextSectionNo
= -1;
120 for (i
= 1; i
< s1
->nb_sections
; i
++) {
121 coff_sec
= §ion_header
[i
];
122 tcc_sect
= s1
->sections
[i
];
124 if (OutputTheSection(tcc_sect
)) {
127 if (CoffTextSectionNo
== -1 && tcc_sect
== stext
)
128 CoffTextSectionNo
= NSectionsToOutput
; // rem which coff sect number the .text sect is
130 strcpy(coff_sec
->s_name
, tcc_sect
->name
); /* section name */
132 coff_sec
->s_paddr
= tcc_sect
->sh_addr
; /* physical address */
133 coff_sec
->s_vaddr
= tcc_sect
->sh_addr
; /* virtual address */
134 coff_sec
->s_size
= tcc_sect
->data_offset
; /* section size */
135 coff_sec
->s_scnptr
= 0; /* file ptr to raw data for section */
136 coff_sec
->s_relptr
= 0; /* file ptr to relocation */
137 coff_sec
->s_lnnoptr
= 0; /* file ptr to line numbers */
138 coff_sec
->s_nreloc
= 0; /* number of relocation entries */
139 coff_sec
->s_flags
= GetCoffFlags(coff_sec
->s_name
); /* flags */
140 coff_sec
->s_reserved
= 0; /* reserved byte */
141 coff_sec
->s_page
= 0; /* memory page id */
143 file_pointer
+= sizeof(SCNHDR
);
147 file_hdr
.f_nscns
= NSectionsToOutput
; /* number of sections */
149 // now loop through and determine file pointer locations
153 for (i
= 1; i
< s1
->nb_sections
; i
++) {
154 coff_sec
= §ion_header
[i
];
155 tcc_sect
= s1
->sections
[i
];
157 if (OutputTheSection(tcc_sect
)) {
159 coff_sec
->s_scnptr
= file_pointer
; /* file ptr to raw data for section */
160 file_pointer
+= coff_sec
->s_size
;
164 // now loop through and determine file pointer locations
165 // for the relocation data
167 for (i
= 1; i
< s1
->nb_sections
; i
++) {
168 coff_sec
= §ion_header
[i
];
169 tcc_sect
= s1
->sections
[i
];
171 if (OutputTheSection(tcc_sect
)) {
172 // put relocations data
173 if (coff_sec
->s_nreloc
> 0) {
174 coff_sec
->s_relptr
= file_pointer
; /* file ptr to relocation */
175 file_pointer
+= coff_sec
->s_nreloc
* sizeof(struct reloc
);
180 // now loop through and determine file pointer locations
181 // for the line number data
183 for (i
= 1; i
< s1
->nb_sections
; i
++) {
184 coff_sec
= §ion_header
[i
];
185 tcc_sect
= s1
->sections
[i
];
187 coff_sec
->s_nlnno
= 0;
188 coff_sec
->s_lnnoptr
= 0;
190 if (s1
->do_debug
&& tcc_sect
== stext
) {
191 // count how many line nos data
193 // also find association between source file name and function
194 // so we can sort the symbol table
197 Stab_Sym
*sym
, *sym_end
;
198 char func_name
[MAX_FUNC_NAME_LENGTH
],
199 last_func_name
[MAX_FUNC_NAME_LENGTH
];
200 unsigned long func_addr
, last_pc
, pc
;
201 const char *incl_files
[INCLUDE_STACK_SIZE
];
202 int incl_index
, len
, last_line_num
;
205 coff_sec
->s_lnnoptr
= file_pointer
; /* file ptr to linno */
211 last_func_name
[0] = '\0';
212 last_pc
= 0xffffffff;
214 sym
= (Stab_Sym
*) stab_section
->data
+ 1;
216 (Stab_Sym
*) (stab_section
->data
+
217 stab_section
->data_offset
);
220 while (sym
< sym_end
) {
221 switch (sym
->n_type
) {
222 /* function start or end */
224 if (sym
->n_strx
== 0) {
228 file_pointer
+= LINESZ
;
230 pc
= sym
->n_value
+ func_addr
;
233 EndAddress
[nFuncs
] = pc
;
234 FuncEntries
[nFuncs
] =
236 LineNoFilePtr
[nFuncs
]) / LINESZ
- 1;
237 LastLineNo
[nFuncs
++] = last_line_num
+ 1;
239 // beginning of function
241 LineNoFilePtr
[nFuncs
] = file_pointer
;
243 file_pointer
+= LINESZ
;
246 (const char *) stabstr_section
->data
+
249 p
= strchr(str
, ':');
251 pstrcpy(func_name
, sizeof(func_name
), str
);
252 pstrcpy(Func
[nFuncs
], sizeof(func_name
), str
);
255 if (len
> sizeof(func_name
) - 1)
256 len
= sizeof(func_name
) - 1;
257 memcpy(func_name
, str
, len
);
258 memcpy(Func
[nFuncs
], str
, len
);
259 func_name
[len
] = '\0';
262 // save the file that it came in so we can sort later
263 pstrcpy(AssociatedFile
[nFuncs
], sizeof(func_name
),
264 incl_files
[incl_index
- 1]);
266 func_addr
= sym
->n_value
;
270 /* line number info */
272 pc
= sym
->n_value
+ func_addr
;
275 last_line_num
= sym
->n_desc
;
278 strcpy(last_func_name
, func_name
);
281 file_pointer
+= LINESZ
;
286 (const char *) stabstr_section
->data
+ sym
->n_strx
;
288 if (incl_index
< INCLUDE_STACK_SIZE
) {
289 incl_files
[incl_index
++] = str
;
297 if (sym
->n_strx
== 0) {
298 incl_index
= 0; /* end of translation unit */
301 (const char *) stabstr_section
->data
+
303 /* do not add path */
305 if (len
> 0 && str
[len
- 1] != '/')
316 file_hdr
.f_symptr
= file_pointer
; /* file pointer to symtab */
319 file_hdr
.f_nsyms
= coff_nb_syms
; /* number of symtab entries */
321 file_hdr
.f_nsyms
= 0;
323 file_pointer
+= file_hdr
.f_nsyms
* SYMNMLEN
;
325 // OK now we are all set to write the file
328 fwrite(&file_hdr
, FILHSZ
, 1, f
);
329 fwrite(&o_filehdr
, sizeof(o_filehdr
), 1, f
);
331 // write section headers
332 for (i
= 1; i
< s1
->nb_sections
; i
++) {
333 coff_sec
= §ion_header
[i
];
334 tcc_sect
= s1
->sections
[i
];
336 if (OutputTheSection(tcc_sect
)) {
337 fwrite(coff_sec
, sizeof(SCNHDR
), 1, f
);
342 for (i
= 1; i
< s1
->nb_sections
; i
++) {
343 coff_sec
= §ion_header
[i
];
344 tcc_sect
= s1
->sections
[i
];
346 if (OutputTheSection(tcc_sect
)) {
347 fwrite(tcc_sect
->data
, tcc_sect
->data_offset
, 1, f
);
351 // write relocation data
352 for (i
= 1; i
< s1
->nb_sections
; i
++) {
353 coff_sec
= §ion_header
[i
];
354 tcc_sect
= s1
->sections
[i
];
356 if (OutputTheSection(tcc_sect
)) {
357 // put relocations data
358 if (coff_sec
->s_nreloc
> 0) {
359 fwrite(tcc_sect
->reloc
,
360 coff_sec
->s_nreloc
* sizeof(struct reloc
), 1, f
);
366 // group the symbols in order of filename, func1, func2, etc
367 // finally global symbols
372 // write line no data
374 for (i
= 1; i
< s1
->nb_sections
; i
++) {
375 coff_sec
= §ion_header
[i
];
376 tcc_sect
= s1
->sections
[i
];
378 if (s1
->do_debug
&& tcc_sect
== stext
) {
379 // count how many line nos data
382 Stab_Sym
*sym
, *sym_end
;
383 char func_name
[128], last_func_name
[128];
384 unsigned long func_addr
, last_pc
, pc
;
385 const char *incl_files
[INCLUDE_STACK_SIZE
];
386 int incl_index
, len
, last_line_num
;
394 last_func_name
[0] = '\0';
397 sym
= (Stab_Sym
*) stab_section
->data
+ 1;
399 (Stab_Sym
*) (stab_section
->data
+
400 stab_section
->data_offset
);
402 while (sym
< sym_end
) {
403 switch (sym
->n_type
) {
404 /* function start or end */
406 if (sym
->n_strx
== 0) {
409 CoffLineNo
.l_addr
.l_paddr
= last_pc
;
410 CoffLineNo
.l_lnno
= last_line_num
+ 1;
411 fwrite(&CoffLineNo
, 6, 1, f
);
413 pc
= sym
->n_value
+ func_addr
;
417 // beginning of function
420 (const char *) stabstr_section
->data
+
424 p
= strchr(str
, ':');
426 pstrcpy(func_name
, sizeof(func_name
), str
);
429 if (len
> sizeof(func_name
) - 1)
430 len
= sizeof(func_name
) - 1;
431 memcpy(func_name
, str
, len
);
432 func_name
[len
] = '\0';
434 func_addr
= sym
->n_value
;
438 // output a function begin
440 CoffLineNo
.l_addr
.l_symndx
=
441 FindCoffSymbolIndex(func_name
);
442 CoffLineNo
.l_lnno
= 0;
444 fwrite(&CoffLineNo
, 6, 1, f
);
448 /* line number info */
450 pc
= sym
->n_value
+ func_addr
;
454 strcpy(last_func_name
, func_name
);
456 // output a line reference
458 CoffLineNo
.l_addr
.l_paddr
= last_pc
;
460 if (last_line_num
== -1) {
461 CoffLineNo
.l_lnno
= sym
->n_desc
;
463 CoffLineNo
.l_lnno
= last_line_num
+ 1;
466 fwrite(&CoffLineNo
, 6, 1, f
);
469 last_line_num
= sym
->n_desc
;
476 (const char *) stabstr_section
->data
+ sym
->n_strx
;
478 if (incl_index
< INCLUDE_STACK_SIZE
) {
479 incl_files
[incl_index
++] = str
;
487 if (sym
->n_strx
== 0) {
488 incl_index
= 0; /* end of translation unit */
491 (const char *) stabstr_section
->data
+
493 /* do not add path */
495 if (len
> 0 && str
[len
- 1] != '/')
505 // write symbol table
518 Coff_str_table
= (char *) tcc_malloc(MAX_STR_TABLE
);
519 pCoff_str_table
= Coff_str_table
;
522 p
= (Elf32_Sym
*) symtab_section
->data
;
525 for (i
= 0; i
< nb_syms
; i
++) {
527 name
= symtab_section
->link
->data
+ p
->st_name
;
529 for (k
= 0; k
< 8; k
++)
530 csym
._n
._n_name
[k
] = 0;
532 if (strlen(name
) <= 8) {
533 strcpy(csym
._n
._n_name
, name
);
535 if (pCoff_str_table
- Coff_str_table
+ strlen(name
) >
537 error("String table too large");
539 csym
._n
._n_n
._n_zeroes
= 0;
540 csym
._n
._n_n
._n_offset
=
541 pCoff_str_table
- Coff_str_table
+ 4;
543 strcpy(pCoff_str_table
, name
);
544 pCoff_str_table
+= strlen(name
) + 1; // skip over null
548 if (p
->st_info
== 4) {
549 // put a filename symbol
550 csym
.n_value
= 33; // ?????
551 csym
.n_scnum
= N_DEBUG
;
553 csym
.n_sclass
= C_FILE
;
555 fwrite(&csym
, 18, 1, f
);
558 } else if (p
->st_info
== 0x12) {
559 // find the function data
561 for (k
= 0; k
< nFuncs
; k
++) {
562 if (strcmp(name
, Func
[k
]) == 0)
569 sprintf(s
, "debug info can't find function: %s", name
);
573 // put a Function Name
575 csym
.n_value
= p
->st_value
; // physical address
576 csym
.n_scnum
= CoffTextSectionNo
;
577 csym
.n_type
= MKTYPE(T_INT
, DT_FCN
, 0, 0, 0, 0, 0);
578 csym
.n_sclass
= C_EXT
;
580 fwrite(&csym
, 18, 1, f
);
585 auxfunc
.size
= EndAddress
[k
] - p
->st_value
;
586 auxfunc
.fileptr
= LineNoFilePtr
[k
];
587 auxfunc
.nextsym
= n
+ 6; // tktk
589 fwrite(&auxfunc
, 18, 1, f
);
593 strcpy(csym
._n
._n_name
, ".bf");
594 csym
.n_value
= p
->st_value
; // physical address
595 csym
.n_scnum
= CoffTextSectionNo
;
597 csym
.n_sclass
= C_FCN
;
599 fwrite(&csym
, 18, 1, f
);
605 auxbf
.nentries
= FuncEntries
[k
];
606 auxbf
.localframe
= 0;
607 auxbf
.nextentry
= n
+ 6;
609 fwrite(&auxbf
, 18, 1, f
);
613 strcpy(csym
._n
._n_name
, ".ef");
614 csym
.n_value
= EndAddress
[k
]; // physical address
615 csym
.n_scnum
= CoffTextSectionNo
;
617 csym
.n_sclass
= C_FCN
;
619 fwrite(&csym
, 18, 1, f
);
624 auxef
.lineno
= LastLineNo
[k
];
629 fwrite(&auxef
, 18, 1, f
);
634 // try an put some type info
636 if ((p
->st_other
& VT_BTYPE
) == VT_DOUBLE
) {
637 csym
.n_type
= T_DOUBLE
; // int
638 csym
.n_sclass
= C_EXT
;
639 } else if ((p
->st_other
& VT_BTYPE
) == VT_FLOAT
) {
640 csym
.n_type
= T_FLOAT
;
641 csym
.n_sclass
= C_EXT
;
642 } else if ((p
->st_other
& VT_BTYPE
) == VT_INT
) {
643 csym
.n_type
= T_INT
; // int
644 csym
.n_sclass
= C_EXT
;
645 } else if ((p
->st_other
& VT_BTYPE
) == VT_SHORT
) {
646 csym
.n_type
= T_SHORT
;
647 csym
.n_sclass
= C_EXT
;
648 } else if ((p
->st_other
& VT_BTYPE
) == VT_BYTE
) {
649 csym
.n_type
= T_CHAR
;
650 csym
.n_sclass
= C_EXT
;
652 csym
.n_type
= T_INT
; // just mark as a label
653 csym
.n_sclass
= C_LABEL
;
657 csym
.n_value
= p
->st_value
;
660 fwrite(&csym
, 18, 1, f
);
667 fwrite(&auxfunc
, 18, 1, f
);
678 // write string table
680 // first write the size
681 i
= pCoff_str_table
- Coff_str_table
;
684 // then write the strings
685 fwrite(Coff_str_table
, i
, 1, f
);
687 tcc_free(Coff_str_table
);
695 // group the symbols in order of filename, func1, func2, etc
696 // finally global symbols
698 void SortSymbolTable(void)
701 Elf32_Sym
*p
, *p2
, *NewTable
;
704 NewTable
= (Elf32_Sym
*) tcc_malloc(nb_syms
* sizeof(Elf32_Sym
));
706 p
= (Elf32_Sym
*) symtab_section
->data
;
709 // find a file symbol, copy it over
710 // then scan the whole symbol list and copy any function
711 // symbols that match the file association
713 for (i
= 0; i
< nb_syms
; i
++) {
714 if (p
->st_info
== 4) {
715 name
= (char *) symtab_section
->link
->data
+ p
->st_name
;
717 // this is a file symbol, copy it over
721 p2
= (Elf32_Sym
*) symtab_section
->data
;
723 for (j
= 0; j
< nb_syms
; j
++) {
724 if (p2
->st_info
== 0x12) {
725 // this is a func symbol
728 (char *) symtab_section
->link
->data
+ p2
->st_name
;
730 // find the function data index
732 for (k
= 0; k
< nFuncs
; k
++) {
733 if (strcmp(name2
, Func
[k
]) == 0)
741 "debug (sort) info can't find function: %s",
747 if (strcmp(AssociatedFile
[k
], name
) == 0) {
748 // yes they match copy it over
759 // now all the filename and func symbols should have been copied over
760 // copy all the rest over (all except file and funcs)
762 p
= (Elf32_Sym
*) symtab_section
->data
;
763 for (i
= 0; i
< nb_syms
; i
++) {
764 if (p
->st_info
!= 4 && p
->st_info
!= 0x12) {
771 error("Internal Compiler error, debug info");
775 p
= (Elf32_Sym
*) symtab_section
->data
;
776 for (i
= 0; i
< nb_syms
; i
++) {
784 int FindCoffSymbolIndex(const char *func_name
)
790 p
= (Elf32_Sym
*) symtab_section
->data
;
792 for (i
= 0; i
< nb_syms
; i
++) {
794 name
= (char *) symtab_section
->link
->data
+ p
->st_name
;
796 if (p
->st_info
== 4) {
797 // put a filename symbol
799 } else if (p
->st_info
== 0x12) {
801 if (strcmp(func_name
, name
) == 0)
806 // put a Function Name
825 return n
; // total number of symbols
828 BOOL
OutputTheSection(Section
* sect
)
830 const char *s
= sect
->name
;
832 if (!strcmp(s
, ".text"))
834 else if (!strcmp(s
, ".data"))
840 short int GetCoffFlags(const char *s
)
842 if (!strcmp(s
, ".text"))
843 return STYP_TEXT
| STYP_DATA
| STYP_ALIGN
| 0x400;
844 else if (!strcmp(s
, ".data"))
846 else if (!strcmp(s
, ".bss"))
848 else if (!strcmp(s
, ".stack"))
849 return STYP_BSS
| STYP_ALIGN
| 0x200;
850 else if (!strcmp(s
, ".cinit"))
851 return STYP_COPY
| STYP_DATA
| STYP_ALIGN
| 0x200;
856 Section
*FindSection(TCCState
* s1
, const char *sname
)
861 for (i
= 1; i
< s1
->nb_sections
; i
++) {
864 if (!strcmp(sname
, s
->name
))
868 error("could not find section %s", sname
);
872 int tcc_load_coff(TCCState
* s1
, int fd
)
874 // tktk TokenSym *ts;
877 unsigned int str_size
;
878 char *Coff_str_table
, *name
;
882 FILHDR file_hdr
; /* FILE HEADER STRUCTURE */
884 f
= fdopen(fd
, "rb");
886 error("Unable to open .out file for input");
889 if (fread(&file_hdr
, FILHSZ
, 1, f
) != 1)
890 error("error reading .out file for input");
892 if (fread(&o_filehdr
, sizeof(o_filehdr
), 1, f
) != 1)
893 error("error reading .out file for input");
895 // first read the string table
897 if (fseek(f
, file_hdr
.f_symptr
+ file_hdr
.f_nsyms
* SYMESZ
, SEEK_SET
))
898 error("error reading .out file for input");
900 if (fread(&str_size
, sizeof(int), 1, f
) != 1)
901 error("error reading .out file for input");
904 Coff_str_table
= (char *) tcc_malloc(str_size
);
906 if (fread(Coff_str_table
, str_size
- 4, 1, f
) != 1)
907 error("error reading .out file for input");
909 // read/process all the symbols
911 // seek back to symbols
913 if (fseek(f
, file_hdr
.f_symptr
, SEEK_SET
))
914 error("error reading .out file for input");
916 for (i
= 0; i
< file_hdr
.f_nsyms
; i
++) {
917 if (fread(&csym
, SYMESZ
, 1, f
) != 1)
918 error("error reading .out file for input");
920 if (csym
._n
._n_n
._n_zeroes
== 0) {
921 name
= Coff_str_table
+ csym
._n
._n_n
._n_offset
- 4;
923 name
= csym
._n
._n_name
;
926 for (k
= 0; k
< 8; k
++)
934 // if (strcmp("_DAC_Buffer",name)==0) // tktk
937 if (((csym
.n_type
& 0x30) == 0x20 && csym
.n_sclass
== 0x2) || ((csym
.n_type
& 0x30) == 0x30 && csym
.n_sclass
== 0x2) || (csym
.n_type
== 0x4 && csym
.n_sclass
== 0x2) || (csym
.n_type
== 0x8 && csym
.n_sclass
== 0x2) || // structures
938 (csym
.n_type
== 0x18 && csym
.n_sclass
== 0x2) || // pointer to structure
939 (csym
.n_type
== 0x7 && csym
.n_sclass
== 0x2) || // doubles
940 (csym
.n_type
== 0x6 && csym
.n_sclass
== 0x2)) // floats
942 // strip off any leading underscore (except for other main routine)
944 if (name
[0] == '_' && strcmp(name
, "_main") != 0)
947 tcc_add_symbol(s1
, name
, (void*)csym
.n_value
);
949 // skip any aux records
951 if (csym
.n_numaux
== 1) {
952 if (fread(&csym
, SYMESZ
, 1, f
) != 1)
953 error("error reading .out file for input");