Tue Sep 22 13:02:07 1992 Sean Eric Fagan (sef@cygnus.com)
[external/binutils.git] / gas / config / obj-coffbfd.c
1 /* coff object file format with bfd
2    Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
3
4 This file is part of GAS.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING.  If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /*
21
22  How does this releate to the rest of GAS ?
23
24  Well, all the other files in gas are more or less a black box. It
25  takes care of opening files, parsing command lines, stripping blanks
26  etc etc. This module gets a chance to register what it wants to do by
27  saying that it is interested in various pseduo ops. The other big
28  change is write_object_file. This runs through all the data
29  structures that gas builds, and outputs the file in the format of our
30  choice.
31  
32  Hacked for BFDness by steve chamberlain
33
34  This object module now supports the Hitachi H8/300 and the AMD 29k
35
36  sac@cygnus.com
37 */
38
39 #include "as.h"
40 #include "obstack.h"
41 #include "subsegs.h"
42 #include "frags.h"
43 #include "../bfd/libbfd.h"
44
45
46 #define MIN(a,b) ((a) < (b)? (a) : (b))
47 /* This vector is used to turn an internal segment into a section #
48    suitable for insertion into a coff symbol table 
49  */
50
51 const short seg_N_TYPE[] = { /* in: segT   out: N_TYPE bits */
52         C_ABS_SECTION,
53         1,
54         2,
55         3,
56         4,
57         5,
58         6,
59         7,
60         8,
61         9,
62         10,
63         C_UNDEF_SECTION,                /* SEG_UNKNOWN */
64         C_UNDEF_SECTION,                /* SEG_ABSENT */
65         C_UNDEF_SECTION,                /* SEG_PASS1 */
66         C_UNDEF_SECTION,                /* SEG_GOOF */
67         C_UNDEF_SECTION,                /* SEG_BIG */
68         C_UNDEF_SECTION,                /* SEG_DIFFERENCE */
69         C_DEBUG_SECTION,                /* SEG_DEBUG */
70         C_NTV_SECTION,          /* SEG_NTV */
71         C_PTV_SECTION,          /* SEG_PTV */
72         C_REGISTER_SECTION,     /* SEG_REGISTER */
73 };
74
75
76 int function_lineoff = -1;      /* Offset in line#s where the last function
77                                    started (the odd entry for line #0) */
78
79
80 int had_lineno = 0;
81 int had_reloc = 0;
82
83 static symbolS*last_line_symbol;
84 /* Add 4 to the real value to get the index and compensate the
85    negatives. This vector is used by S_GET_SEGMENT to turn a coff
86    section number into a segment number 
87 */
88 static symbolS *previous_file_symbol = NULL;
89 void c_symbol_merge();
90 static int line_base;
91
92 symbolS *c_section_symbol();
93 bfd *abfd;
94 void EXFUN(bfd_as_write_hook,(struct internal_filehdr *,
95                               bfd *abfd));
96
97 static void EXFUN(fixup_segment,(fixS * fixP,
98                   segT  this_segment_type));
99
100
101 static void EXFUN(fixup_mdeps,(fragS *));
102
103
104 static void EXFUN(fill_section,(bfd *abfd ,
105                                 struct internal_filehdr *f, unsigned
106                                 long *));
107
108
109 char *EXFUN(s_get_name,(symbolS *s));
110 static symbolS *EXFUN(tag_find_or_make,(char *name));
111 static symbolS* EXFUN(tag_find,(char *name));
112
113
114 static int
115 EXFUN(c_line_new,(
116       symbolS *symbol,
117       long paddr,
118       unsigned short line_number,
119                   fragS* frag));
120
121
122 static void EXFUN(w_symbols,
123                   (bfd *abfd ,
124                    char *where ,
125                    symbolS *symbol_rootP));
126
127
128
129 static void EXFUN( obj_coff_def,(int what));
130 static void EXFUN( obj_coff_lcomm,(void));
131 static void EXFUN( obj_coff_dim,(void));
132 static void EXFUN( obj_coff_text,(void));
133 static void EXFUN( obj_coff_data,(void));
134 static void EXFUN( obj_coff_endef,(void));
135 static void EXFUN( obj_coff_line,(void));
136 static void EXFUN( obj_coff_ln,(void));
137 static void EXFUN( obj_coff_scl,(void));
138 static void EXFUN( obj_coff_size,(void));
139 static void EXFUN( obj_coff_tag,(void));
140 static void EXFUN( obj_coff_type,(void));
141 static void EXFUN( obj_coff_val,(void));
142 void EXFUN( obj_coff_section,(void));
143 static void EXFUN( tag_init,(void));
144 static void EXFUN( tag_insert,(char *name, symbolS *symbolP));
145
146
147 static struct hash_control *tag_hash;
148 static symbolS *def_symbol_in_progress = NULL;
149
150 const pseudo_typeS obj_pseudo_table[] = {
151         { "def",        obj_coff_def,           0       },
152         { "dim",        obj_coff_dim,           0       },
153         { "endef",      obj_coff_endef,         0       },
154         { "line",       obj_coff_line,          0       },
155         { "ln",         obj_coff_ln,            0       },
156         { "scl",        obj_coff_scl,           0       },
157         { "size",       obj_coff_size,          0       },
158         { "tag",        obj_coff_tag,           0       },
159         { "type",       obj_coff_type,          0       },
160         { "val",        obj_coff_val,           0       },
161         { "section",    obj_coff_section,       0       },
162         { "use",        obj_coff_section,       0       },
163         { "sect",    obj_coff_section,       0       },
164         { "text",       obj_coff_text,          0       },
165         { "data",       obj_coff_data,          0       },
166         /* we don't yet handle this. */
167         { "ident",      s_ignore,               0       },
168         { "ABORT",      s_abort,                0 },
169         { "lcomm",      obj_coff_lcomm, 0},
170         { NULL} /* end sentinel */
171 }; /* obj_pseudo_table */
172
173
174
175 /* Section stuff 
176
177    We allow more than just the standard 3 sections, infact, we allow
178    10 sections, (though the usual three have to be there).
179
180    This structure performs the mappings for us:
181
182 */
183
184 /* OBS stuff 
185 static struct internal_scnhdr bss_section_header;
186 struct internal_scnhdr data_section_header;
187 struct internal_scnhdr text_section_header;
188
189 const segT N_TYPE_seg [32] =
190 {
191
192 };
193
194 */
195
196 #define N_SEG 32
197 typedef struct 
198 {
199   segT seg_t;  
200 int i;  
201 } seg_info_type;
202
203 seg_info_type seg_info_off_by_4[N_SEG] = 
204 {
205 {SEG_PTV,  },
206 {SEG_NTV,  },
207 {SEG_DEBUG, },
208 {SEG_ABSOLUTE,  },
209 {SEG_UNKNOWN,    },
210 {SEG_E0}, 
211 {SEG_E1},
212 {SEG_E2},
213 {SEG_E3},
214 {SEG_E4},
215 {SEG_E5},
216 {SEG_E6},
217 {SEG_E7},
218 {SEG_E8}, 
219 {SEG_E9},
220 {15},
221 {16},
222 {17},
223 {18},
224 {19},
225 {20},
226 {0},
227 {0},
228 {0},
229 {SEG_REGISTER},0,0,0,0};
230
231 #define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4])
232 #define SEG_INFO_FROM_SEG_NUMBER(x) (seg_info_off_by_4[(x)])
233
234
235  relax_addressT 
236 DEFUN(relax_align,(address, alignment),
237 register relax_addressT address AND
238 register long alignment )
239 {
240   relax_addressT        mask;
241   relax_addressT        new_address;
242
243   mask = ~ ( (~0) << alignment );
244   new_address = (address + mask) & (~ mask);
245   return (new_address - address);
246 } /* relax_align() */
247
248
249 segT 
250 DEFUN(s_get_segment,(x) ,
251 symbolS* x)
252 {
253   return SEG_INFO_FROM_SECTION_NUMBER(x->sy_symbol.ost_entry.n_scnum).seg_t;
254 }
255
256
257
258 /* calculate the size of the frag chain and fill in the section header
259    to contain all of it, also fill in the addr of the sections */
260 static unsigned int  
261 DEFUN(size_section,(abfd, idx),
262       bfd *abfd AND
263       unsigned int idx)
264 {
265
266   unsigned int size = 0;
267   fragS *frag = segment_info[idx].frchainP->frch_root;
268   while (frag) {
269     size = frag->fr_address;
270 #if 0    
271       if (frag->fr_address != size) {   
272           printf("Out of step\n");
273           size = frag->fr_address;
274         }
275
276       switch (frag->fr_type) {
277 #ifdef TC_COFF_SIZEMACHDEP
278        case rs_machine_dependent:
279         size +=  TC_COFF_SIZEMACHDEP(frag);
280         break;
281 #endif
282         case rs_fill:
283         case rs_org:
284       size += frag->fr_fix;
285           size  +=    frag->fr_offset * frag->fr_var;
286           break;
287         case rs_align:
288       size += frag->fr_fix;
289           size  +=   relax_align(size, frag->fr_offset);
290         }
291 #endif
292       frag = frag->fr_next;
293     }
294   segment_info[idx].scnhdr.s_size = size;
295   return size;
296 }
297
298
299 static unsigned int DEFUN(count_entries_in_chain,(idx),
300                           unsigned int idx)
301 {
302     unsigned int nrelocs;
303     fixS *fixup_ptr;
304
305     /* Count the relocations */
306     fixup_ptr = segment_info[idx].fix_root;
307     nrelocs = 0;
308     while (fixup_ptr != (fixS *)NULL) 
309     {
310         if (TC_COUNT_RELOC(fixup_ptr)) 
311         {
312             
313 #ifdef TC_A29K
314
315             if (fixup_ptr->fx_r_type == RELOC_CONSTH)  
316              nrelocs+=2;
317             else                                        
318              nrelocs++;         
319 #else
320             nrelocs++;
321 #endif
322         }
323         
324         fixup_ptr = fixup_ptr->fx_next;
325     }
326     return nrelocs;
327 }
328
329 /* output all the relocations for a section */
330 void DEFUN(do_relocs_for,(abfd, file_cursor),
331            bfd *abfd AND
332            unsigned long *file_cursor)
333 {
334   unsigned int nrelocs;
335   unsigned int idx;
336   unsigned int addr = 0;
337   for (idx = SEG_E0; idx < SEG_E9; idx++) 
338   {
339     if (segment_info[idx].scnhdr.s_name[0]) 
340     {
341
342       struct external_reloc *ext_ptr;
343       struct external_reloc *external_reloc_vec;
344       unsigned int external_reloc_size;
345       unsigned int count = 0;
346       unsigned int base  = addr;
347       fixS *   fix_ptr = segment_info[idx].fix_root;
348       nrelocs = count_entries_in_chain(idx);
349       
350       if (nrelocs) 
351        had_reloc = 1;
352       
353       external_reloc_size = nrelocs * RELSZ;
354       external_reloc_vec =
355        (struct external_reloc*)malloc(external_reloc_size);
356
357         
358             
359       ext_ptr = external_reloc_vec;
360             
361       /* Fill in the internal coff style reloc struct from the
362          internal fix list */
363       while (fix_ptr)
364       {
365         symbolS *symbol_ptr;
366         struct internal_reloc intr;
367
368         /* Only output some of the relocations */
369         if (TC_COUNT_RELOC(fix_ptr))
370         {
371 #ifdef TC_RELOC_MANGLE
372           TC_RELOC_MANGLE(fix_ptr, &intr, base);
373                 
374 #else
375           symbolS *dot;
376           symbol_ptr = fix_ptr->fx_addsy;
377
378           intr.r_type = TC_COFF_FIX2RTYPE(fix_ptr);
379           intr.r_vaddr =
380            base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where ;
381
382           intr.r_offset = fix_ptr->fx_offset;
383
384           intr.r_offset = 0;
385
386           /* Turn the segment of the symbol into an offset
387            */
388           if (symbol_ptr) 
389           {
390             dot = segment_info[S_GET_SEGMENT(symbol_ptr)].dot;
391             if (dot)
392             {
393               intr.r_symndx = dot->sy_number;
394             }
395             else 
396             {
397               intr.r_symndx = symbol_ptr->sy_number;
398             }
399
400           }
401           else 
402           {
403             intr.r_symndx = -1;
404
405
406           }
407 #endif
408
409           (void)bfd_coff_swap_reloc_out(abfd, &intr, ext_ptr);
410           ext_ptr++;
411
412 #if defined(TC_A29K)
413           /* The 29k has a special kludge for the high 16 bit reloc.
414              Two relocations are emmited, R_IHIHALF, and
415              R_IHCONST. The second one doesn't contain a symbol,
416              but uses the value for offset */
417                 
418           if (intr.r_type == R_IHIHALF)
419           {
420             /* now emit the second bit */
421             intr.r_type = R_IHCONST;    
422             intr.r_symndx = fix_ptr->fx_addnumber;
423             (void)bfd_coff_swap_reloc_out(abfd,&intr,ext_ptr);
424             ext_ptr++;
425           }
426 #endif
427         }
428                 
429         fix_ptr = fix_ptr->fx_next;
430       }
431       
432       /* Write out the reloc table */
433       segment_info[idx].scnhdr.s_relptr = *file_cursor;
434       segment_info[idx].scnhdr.s_nreloc = nrelocs;
435       bfd_write((PTR)external_reloc_vec, 1, external_reloc_size, abfd);
436       *file_cursor += external_reloc_size;
437       free( external_reloc_vec);
438     }
439 #if OLDWAY
440     This should work, but causes problems with addends in relocs.
441     Disable it for the moment
442     addr += segment_info[idx].scnhdr.s_size;
443 #else
444     addr = 0;
445 #endif
446   }
447 }
448
449
450 /* run through a frag chain and write out the data to go with it, fill
451    in the scnhdrs with the info on the file postions 
452 */
453 static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
454                   bfd *abfd AND
455                   struct internal_filehdr *filehdr AND
456                   unsigned long *file_cursor)
457 {
458
459   unsigned int i;
460   unsigned int paddr = 0;
461   
462   for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
463   {  
464     unsigned int offset = 0;
465
466     struct internal_scnhdr *s = &( segment_info[i].scnhdr);
467           
468     if (s->s_name[0]) 
469     {
470       fragS *frag = segment_info[i].frchainP->frch_root;
471       char *buffer =  malloc(s->s_size);
472       if (s->s_size != 0) 
473       {
474         s->s_scnptr = *file_cursor;
475         s->s_paddr =  paddr;
476         s->s_vaddr =  paddr;
477
478       }
479       else 
480       {
481         s->s_scnptr = 0;
482         s->s_paddr =  0;
483         s->s_vaddr =  0;
484
485       }
486             
487
488       s->s_flags = STYP_REG;
489       if (strcmp(s->s_name,".text")==0)
490        s->s_flags |= STYP_TEXT;
491       else if (strcmp(s->s_name,".data")==0)
492        s->s_flags |= STYP_DATA;
493       else if (strcmp(s->s_name,".bss")==0)
494        s->s_flags |= STYP_BSS | STYP_NOLOAD;
495       else if (strcmp(s->s_name,".lit")==0)
496        s->s_flags = STYP_LIT | STYP_TEXT;
497
498
499       while (frag) {
500         unsigned int fill_size;
501         switch (frag->fr_type) {
502          case rs_machine_dependent:
503           if(frag->fr_fix) 
504           {
505             memcpy(buffer + frag->fr_address,
506                    frag->fr_literal,
507                    frag->fr_fix);
508             offset += frag->fr_fix;
509           }
510
511           break;
512          case rs_fill:
513          case rs_align:
514          case rs_org:
515           if(frag->fr_fix) 
516           {
517             memcpy(buffer + frag->fr_address,
518                    frag->fr_literal,
519                    frag->fr_fix);
520             offset += frag->fr_fix;
521           }
522
523           fill_size = frag->fr_var;
524           if (fill_size)        
525           {
526             unsigned int count ;
527             unsigned int off = frag->fr_fix;
528             for (count = frag->fr_offset; count;  count--) 
529             {
530               memcpy(buffer +  frag->fr_address  + off,
531                      frag->fr_literal + frag->fr_fix,
532                      fill_size);
533               off += fill_size;
534               offset += fill_size;
535                       
536             }
537
538           }
539           break;
540          case rs_broken_word:
541           break;
542          default:       
543           abort();
544         }
545         frag = frag->fr_next;
546       }
547           
548
549       bfd_write(buffer, s->s_size,1,abfd);
550       free(buffer);
551           
552       *file_cursor += s->s_size;
553
554 #if 0
555     This should work, but causes problems with addends in relocs.
556     Disable it for the moment
557
558       paddr += s->s_size;
559 #else
560       paddr = 0;
561 #endif
562     }      
563   }
564
565 }
566
567
568
569 /* Coff file generation & utilities */
570
571
572 static void 
573 DEFUN(coff_header_append,(abfd, filehdr, aouthdr),
574       bfd *abfd AND
575       struct internal_filehdr *filehdr AND
576       struct internal_aouthdr *aouthdr)
577 {
578   unsigned int i;
579   char buffer[1000];
580   char buffero[1000];
581
582   bfd_seek(abfd, 0, 0);
583 #if 0  
584   filehdr.f_opthdr = bfd_coff_swap_aouthdr_out(abfd, aouthdr,
585                                                buffero);
586 #else
587   filehdr->f_opthdr = 0;
588 #endif
589   i = bfd_coff_swap_filehdr_out(abfd, filehdr, buffer);
590
591   bfd_write(buffer, i ,1, abfd);
592   bfd_write(buffero, filehdr->f_opthdr, 1, abfd);
593
594   for (i = SEG_E0; i < SEG_E9; i++) 
595   {
596     if (segment_info[i].scnhdr.s_name[0]) 
597     {   
598       unsigned int size =
599        bfd_coff_swap_scnhdr_out(abfd,
600                                 &(segment_info[i].scnhdr),
601                                 buffer);
602       bfd_write(buffer, size, 1, abfd);
603     }
604   }
605 }
606
607
608 char *
609 DEFUN(symbol_to_chars,(abfd, where, symbolP),
610       bfd*abfd AND
611       char *where AND
612       symbolS *symbolP)
613 {
614     unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux;
615     unsigned int i;
616
617     /* Turn any symbols with register attributes into abs symbols */
618     if (S_GET_SEGMENT(symbolP) == SEG_REGISTER) 
619     {
620         S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
621     }
622     /* At the same time, relocate all symbols to their output value */
623
624     S_SET_VALUE(symbolP,
625                 segment_info[S_GET_SEGMENT(symbolP)].scnhdr.s_paddr 
626                 + S_GET_VALUE(symbolP));
627
628     where += bfd_coff_swap_sym_out(abfd, &symbolP->sy_symbol.ost_entry,
629                                    where);
630         
631     for (i = 0; i < numaux; i++) 
632     {
633         where += bfd_coff_swap_aux_out(abfd,
634                                        &symbolP->sy_symbol.ost_auxent[i],
635                                        S_GET_DATA_TYPE(symbolP),
636                                        S_GET_STORAGE_CLASS(symbolP),
637                                        where);
638     }
639     return where;
640   
641
642
643
644
645
646 void obj_symbol_new_hook(symbolP)
647 symbolS *symbolP;
648 {
649         char underscore = 0;      /* Symbol has leading _ */
650
651         /* Effective symbol */
652         /* Store the pointer in the offset. */
653         S_SET_ZEROES(symbolP, 0L);
654         S_SET_DATA_TYPE(symbolP, T_NULL);
655         S_SET_STORAGE_CLASS(symbolP, 0);
656         S_SET_NUMBER_AUXILIARY(symbolP, 0);
657         /* Additional information */
658         symbolP->sy_symbol.ost_flags = 0;
659         /* Auxiliary entries */
660         bzero((char*)&symbolP->sy_symbol.ost_auxent[0], AUXESZ);
661
662 #ifdef STRIP_UNDERSCORE
663         /* Remove leading underscore at the beginning of the symbol.
664          * This is to be compatible with the standard librairies.
665          */
666         if (*S_GET_NAME(symbolP) == '_') {
667                 underscore = 1;
668                 S_SET_NAME(symbolP, S_GET_NAME(symbolP) + 1);
669         } /* strip underscore */
670 #endif /* STRIP_UNDERSCORE */
671
672         if (S_IS_STRING(symbolP))
673             SF_SET_STRING(symbolP);
674         if (!underscore && S_IS_LOCAL(symbolP))
675             SF_SET_LOCAL(symbolP);
676
677         return;
678 } /* obj_symbol_new_hook() */
679
680  /* stack stuff */
681 stack* stack_init(chunk_size, element_size)
682 unsigned long chunk_size;
683 unsigned long element_size;
684 {
685         stack* st;
686
687         if ((st = (stack*)malloc(sizeof(stack))) == (stack*)0)
688             return (stack*)0;
689         if ((st->data = malloc(chunk_size)) == (char*)0) {
690                 free(st);
691                 return (stack*)0;
692         }
693         st->pointer = 0;
694         st->size = chunk_size;
695         st->chunk_size = chunk_size;
696         st->element_size = element_size;
697         return st;
698 } /* stack_init() */
699
700 void stack_delete(st)
701 stack* st;
702 {
703     free(st->data);
704     free(st);
705 }
706
707 char *stack_push(st, element)
708 stack *st;
709 char *element;
710 {
711         if (st->pointer + st->element_size >= st->size) {
712                 st->size += st->chunk_size;
713                 if ((st->data = xrealloc(st->data, st->size)) == (char*)0)
714                     return (char*)0;
715         }
716         memcpy(st->data + st->pointer, element, st->element_size);
717         st->pointer += st->element_size;
718         return st->data + st->pointer;
719 } /* stack_push() */
720
721 char* stack_pop(st)
722 stack* st;
723 {
724     if ((st->pointer -= st->element_size) < 0) {
725         st->pointer = 0;
726         return (char*)0;
727     }
728
729     return st->data + st->pointer;
730 }
731
732 char* stack_top(st)
733 stack* st;
734 {
735     return st->data + st->pointer - st->element_size;
736 }
737
738
739 /*
740  * Handle .ln directives.
741  */
742
743 static void obj_coff_ln() 
744 {
745   int l;
746     
747   if (def_symbol_in_progress != NULL) {
748       as_warn(".ln pseudo-op inside .def/.endef: ignored.");
749       demand_empty_rest_of_line();
750       return;
751     }                           /* wrong context */
752
753   c_line_new(0,
754              obstack_next_free(&frags) - frag_now->fr_literal,
755              l = get_absolute_expression(),
756              frag_now);
757 #ifndef NO_LISTING
758 {
759   extern int listing;
760     
761   if (listing) 
762   {
763     listing_source_line(l + line_base - 1);
764   }
765     
766 }
767 #endif
768   demand_empty_rest_of_line();
769   return;
770 }                               /* obj_coff_line() */
771
772 /*
773  *                      def()
774  *
775  * Handle .def directives.
776  *
777  * One might ask : why can't we symbol_new if the symbol does not
778  * already exist and fill it with debug information.  Because of
779  * the C_EFCN special symbol. It would clobber the value of the
780  * function symbol before we have a chance to notice that it is
781  * a C_EFCN. And a second reason is that the code is more clear this
782  * way. (at least I think it is :-).
783  *
784  */
785
786 #define SKIP_SEMI_COLON()       while (*input_line_pointer++ != ';')
787 #define SKIP_WHITESPACES()      while (*input_line_pointer == ' ' || \
788                                       *input_line_pointer == '\t') \
789                                          input_line_pointer++;
790
791 static void 
792 DEFUN(obj_coff_def,(what),
793       int what)
794 {
795     char name_end;              /* Char after the end of name */
796     char *symbol_name;          /* Name of the debug symbol */
797     char *symbol_name_copy;     /* Temporary copy of the name */
798     unsigned int symbol_name_length;
799     /*$char*    directiveP;$ */         /* Name of the pseudo opcode */
800     /*$char directive[MAX_DIRECTIVE];$ */ /* Backup of the directive */
801     /*$char end = 0;$ */ /* If 1, stop parsing */
802
803     if (def_symbol_in_progress != NULL) {
804             as_warn(".def pseudo-op used inside of .def/.endef: ignored.");
805             demand_empty_rest_of_line();
806             return;
807         }                       /* if not inside .def/.endef */
808
809     SKIP_WHITESPACES();
810
811     def_symbol_in_progress = (symbolS *) obstack_alloc(&notes, sizeof(*def_symbol_in_progress));
812     bzero(def_symbol_in_progress, sizeof(*def_symbol_in_progress));
813
814     symbol_name = input_line_pointer;
815     name_end = get_symbol_end();
816     symbol_name_length = strlen(symbol_name);
817     symbol_name_copy = xmalloc(symbol_name_length + 1);
818     strcpy(symbol_name_copy, symbol_name);
819
820     /* Initialize the new symbol */
821 #ifdef STRIP_UNDERSCORE
822     S_SET_NAME(def_symbol_in_progress, (*symbol_name_copy == '_'
823                                         ? symbol_name_copy + 1
824                                         : symbol_name_copy));
825 #else                           /* STRIP_UNDERSCORE */
826     S_SET_NAME(def_symbol_in_progress, symbol_name_copy);
827 #endif                          /* STRIP_UNDERSCORE */
828     /* free(symbol_name_copy); */
829     def_symbol_in_progress->sy_name_offset = ~0;
830     def_symbol_in_progress->sy_number = ~0;
831     def_symbol_in_progress->sy_frag = &zero_address_frag;
832
833     if (S_IS_STRING(def_symbol_in_progress)) {
834             SF_SET_STRING(def_symbol_in_progress);
835         }                       /* "long" name */
836
837     *input_line_pointer = name_end;
838
839     demand_empty_rest_of_line();
840     return;
841 }                               /* obj_coff_def() */
842
843 unsigned int dim_index;
844 static void 
845 DEFUN_VOID(obj_coff_endef) 
846 {
847     symbolS *symbolP = 0;
848     /* DIM BUG FIX sac@cygnus.com */
849     dim_index =0;
850     if (def_symbol_in_progress == NULL) {
851             as_warn(".endef pseudo-op used outside of .def/.endef: ignored.");
852             demand_empty_rest_of_line();
853             return;
854         }                       /* if not inside .def/.endef */
855
856     /* Set the section number according to storage class. */
857     switch (S_GET_STORAGE_CLASS(def_symbol_in_progress)) {
858           case C_STRTAG:
859           case C_ENTAG:
860           case C_UNTAG:
861             SF_SET_TAG(def_symbol_in_progress);
862             /* intentional fallthrough */
863           case C_FILE:
864           case C_TPDEF:
865             SF_SET_DEBUG(def_symbol_in_progress);
866             S_SET_SEGMENT(def_symbol_in_progress, SEG_DEBUG);
867             break;
868
869           case C_EFCN:
870             SF_SET_LOCAL(def_symbol_in_progress); /* Do not emit this symbol. */
871             /* intentional fallthrough */
872           case C_BLOCK:
873             SF_SET_PROCESS(def_symbol_in_progress); /* Will need processing before writing */
874             /* intentional fallthrough */
875           case C_FCN:
876             S_SET_SEGMENT(def_symbol_in_progress, SEG_E0);
877
878             if (def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr[1][1] == 'b'
879                 && def_symbol_in_progress->sy_symbol.ost_entry._n._n_nptr[1][2] == 'f') { /* .bf */
880                     if (function_lineoff < 0) {
881                             fprintf(stderr, "`.bf' symbol without preceding function\n");
882                         }       /* missing function symbol */
883                     SA_GET_SYM_LNNOPTR(last_line_symbol) = function_lineoff;
884                     
885                     SF_SET_PROCESS(last_line_symbol);
886                     function_lineoff = -1;
887                 }
888             break;
889
890 #ifdef C_AUTOARG
891           case C_AUTOARG:
892 #endif                          /* C_AUTOARG */
893           case C_AUTO:
894           case C_REG:
895           case C_MOS:
896           case C_MOE:
897           case C_MOU:
898           case C_ARG:
899           case C_REGPARM:
900           case C_FIELD:
901           case C_EOS:
902             SF_SET_DEBUG(def_symbol_in_progress);
903             S_SET_SEGMENT(def_symbol_in_progress, SEG_ABSOLUTE);
904             break;
905
906           case C_EXT:
907           case C_STAT:
908           case C_LABEL: 
909             /* Valid but set somewhere else (s_comm, s_lcomm, colon) */
910             break;
911
912           case C_USTATIC:
913           case C_EXTDEF:
914           case C_ULABEL:
915             as_warn("unexpected storage class %d", S_GET_STORAGE_CLASS(def_symbol_in_progress));
916             break;
917         }                       /* switch on storage class */
918
919     /* Now that we have built a debug symbol, try to
920        find if we should merge with an existing symbol
921        or not.  If a symbol is C_EFCN or SEG_ABSOLUTE or
922        untagged SEG_DEBUG it never merges. */
923
924     /* Two cases for functions.  Either debug followed
925        by definition or definition followed by debug.
926        For definition first, we will merge the debug
927        symbol into the definition.  For debug first, the
928        lineno entry MUST point to the definition
929        function or else it will point off into space
930        when crawl_symbols() merges the debug
931        symbol into the real symbol.  Therefor, let's
932        presume the debug symbol is a real function
933        reference. */
934
935     /* FIXME-SOON If for some reason the definition
936        label/symbol is never seen, this will probably
937        leave an undefined symbol at link time. */
938
939     if (S_GET_STORAGE_CLASS(def_symbol_in_progress) == C_EFCN
940         || (S_GET_SEGMENT(def_symbol_in_progress) == SEG_DEBUG
941             && !SF_GET_TAG(def_symbol_in_progress))
942         || S_GET_SEGMENT(def_symbol_in_progress) == SEG_ABSOLUTE
943         || (symbolP = symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP)) == NULL) {
944
945             symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
946
947         } else {
948                 /* This symbol already exists, merge the
949                    newly created symbol into the old one.
950                    This is not mandatory. The linker can
951                    handle duplicate symbols correctly. But I
952                    guess that it save a *lot* of space if
953                    the assembly file defines a lot of
954                    symbols. [loic] */
955
956                 /* The debug entry (def_symbol_in_progress)
957                    is merged into the previous definition. */
958
959                 c_symbol_merge(def_symbol_in_progress, symbolP);
960                 /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */
961                 def_symbol_in_progress = symbolP;
962
963                 if (SF_GET_FUNCTION(def_symbol_in_progress)
964                     || SF_GET_TAG(def_symbol_in_progress)) {
965                         /* For functions, and tags, the symbol *must* be where the debug symbol
966                            appears.  Move the existing symbol to the current place. */
967                         /* If it already is at the end of the symbol list, do nothing */
968                         if (def_symbol_in_progress != symbol_lastP) {
969                                 symbol_remove(def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
970                                 symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
971                             }   /* if not already in place */
972                     }           /* if function */
973             }                   /* normal or mergable */
974
975     if (SF_GET_TAG(def_symbol_in_progress)
976         && symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP) == NULL) {
977             tag_insert(S_GET_NAME(def_symbol_in_progress), def_symbol_in_progress);
978         }                       /* If symbol is a {structure,union} tag, associate symbol to its name. */
979
980     if (SF_GET_FUNCTION(def_symbol_in_progress)) {
981             know(sizeof(def_symbol_in_progress) <= sizeof(long));
982             function_lineoff 
983              = c_line_new(def_symbol_in_progress,0, 0, &zero_address_frag);
984
985
986
987             SF_SET_PROCESS(def_symbol_in_progress);
988
989             if (symbolP == NULL) {
990                     /* That is, if this is the first
991                        time we've seen the function... */
992                     symbol_table_insert(def_symbol_in_progress);
993                 }               /* definition follows debug */
994         }                       /* Create the line number entry pointing to the function being defined */
995
996     def_symbol_in_progress = NULL;
997     demand_empty_rest_of_line();
998     return;
999 }                               /* obj_coff_endef() */
1000
1001 static void 
1002 DEFUN_VOID(obj_coff_dim) 
1003 {
1004     register int dim_index;
1005
1006     if (def_symbol_in_progress == NULL) 
1007     {
1008         as_warn(".dim pseudo-op used outside of .def/.endef: ignored.");
1009         demand_empty_rest_of_line();
1010         return;
1011     }                           /* if not inside .def/.endef */
1012
1013     S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
1014
1015     for (dim_index = 0; dim_index < DIMNUM; dim_index++) 
1016     {
1017         SKIP_WHITESPACES();
1018         SA_SET_SYM_DIMEN(def_symbol_in_progress, dim_index, get_absolute_expression());
1019
1020         switch (*input_line_pointer) 
1021         {
1022
1023           case ',':
1024             input_line_pointer++;
1025             break;
1026
1027           default:
1028             as_warn("badly formed .dim directive ignored");
1029             /* intentional fallthrough */
1030           case '\n':
1031           case ';':
1032             dim_index = DIMNUM;
1033             break;
1034         }                       /* switch on following character */
1035     }                           /* for each dimension */
1036
1037     demand_empty_rest_of_line();
1038     return;
1039 }                               /* obj_coff_dim() */
1040
1041 static void obj_coff_line() 
1042 {
1043   int this_base;
1044   
1045   if (def_symbol_in_progress == NULL) {
1046       obj_coff_ln();
1047       return;
1048     }                           /* if it looks like a stabs style line */
1049
1050   this_base = get_absolute_expression();
1051   if (this_base > line_base) 
1052   {
1053     line_base = this_base;
1054   }
1055   
1056     
1057 #ifndef NO_LISTING 
1058 {
1059   extern int listing;
1060   if (listing && 0) {
1061       listing_source_line(line_base);
1062     }
1063 }  
1064 #endif
1065   S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
1066   SA_SET_SYM_LNNO(def_symbol_in_progress, line_base);
1067
1068   demand_empty_rest_of_line();
1069   return;
1070 }                               /* obj_coff_line() */
1071
1072 static void obj_coff_size() {
1073         if (def_symbol_in_progress == NULL) {
1074                 as_warn(".size pseudo-op used outside of .def/.endef ignored.");
1075                 demand_empty_rest_of_line();
1076                 return;
1077         } /* if not inside .def/.endef */
1078
1079         S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
1080         SA_SET_SYM_SIZE(def_symbol_in_progress, get_absolute_expression());
1081         demand_empty_rest_of_line();
1082         return;
1083 } /* obj_coff_size() */
1084
1085 static void obj_coff_scl() {
1086         if (def_symbol_in_progress == NULL) {
1087                 as_warn(".scl pseudo-op used outside of .def/.endef ignored.");
1088                 demand_empty_rest_of_line();
1089                 return;
1090         } /* if not inside .def/.endef */
1091
1092         S_SET_STORAGE_CLASS(def_symbol_in_progress, get_absolute_expression());
1093         demand_empty_rest_of_line();
1094         return;
1095 } /* obj_coff_scl() */
1096
1097 static void obj_coff_tag() {
1098         char *symbol_name;
1099         char name_end;
1100
1101         if (def_symbol_in_progress == NULL) {
1102                 as_warn(".tag pseudo-op used outside of .def/.endef ignored.");
1103                 demand_empty_rest_of_line();
1104                 return;
1105         } /* if not inside .def/.endef */
1106
1107         S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
1108         symbol_name = input_line_pointer;
1109         name_end = get_symbol_end();
1110
1111         /* Assume that the symbol referred to by .tag is always defined. */
1112         /* This was a bad assumption.  I've added find_or_make. xoxorich. */
1113         SA_SET_SYM_TAGNDX(def_symbol_in_progress, (long) tag_find_or_make(symbol_name));
1114         if (SA_GET_SYM_TAGNDX(def_symbol_in_progress) == 0L) {
1115                 as_warn("tag not found for .tag %s", symbol_name);
1116         } /* not defined */
1117
1118         SF_SET_TAGGED(def_symbol_in_progress);
1119         *input_line_pointer = name_end;
1120
1121         demand_empty_rest_of_line();
1122         return;
1123 } /* obj_coff_tag() */
1124
1125 static void obj_coff_type() {
1126         if (def_symbol_in_progress == NULL) {
1127                 as_warn(".type pseudo-op used outside of .def/.endef ignored.");
1128                 demand_empty_rest_of_line();
1129                 return;
1130         } /* if not inside .def/.endef */
1131
1132         S_SET_DATA_TYPE(def_symbol_in_progress, get_absolute_expression());
1133
1134         if (ISFCN(S_GET_DATA_TYPE(def_symbol_in_progress)) &&
1135             S_GET_STORAGE_CLASS(def_symbol_in_progress) != C_TPDEF) {
1136                 SF_SET_FUNCTION(def_symbol_in_progress);
1137         } /* is a function */
1138
1139         demand_empty_rest_of_line();
1140         return;
1141 } /* obj_coff_type() */
1142
1143 static void obj_coff_val() {
1144         if (def_symbol_in_progress == NULL) {
1145                 as_warn(".val pseudo-op used outside of .def/.endef ignored.");
1146                 demand_empty_rest_of_line();
1147                 return;
1148         } /* if not inside .def/.endef */
1149
1150         if (is_name_beginner(*input_line_pointer)) {
1151                 char *symbol_name = input_line_pointer;
1152                 char name_end = get_symbol_end();
1153
1154                 if (!strcmp(symbol_name, ".")) {
1155                         def_symbol_in_progress->sy_frag = frag_now;
1156                         S_SET_VALUE(def_symbol_in_progress, obstack_next_free(&frags) - frag_now->fr_literal);
1157                         /* If the .val is != from the .def (e.g. statics) */
1158                 } else if (strcmp(S_GET_NAME(def_symbol_in_progress), symbol_name)) {
1159                         def_symbol_in_progress->sy_forward = symbol_find_or_make(symbol_name);
1160
1161                         /* If the segment is undefined when the forward
1162                            reference is solved, then copy the segment id
1163                            from the forward symbol. */
1164                         SF_SET_GET_SEGMENT(def_symbol_in_progress);
1165                 }
1166                 /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */
1167                 *input_line_pointer = name_end;
1168         } else {
1169                 S_SET_VALUE(def_symbol_in_progress, get_absolute_expression());
1170         } /* if symbol based */
1171
1172         demand_empty_rest_of_line();
1173         return;
1174 } /* obj_coff_val() */
1175
1176 /*
1177  * Maintain a list of the tagnames of the structres.
1178  */
1179
1180 static void tag_init() {
1181     tag_hash = hash_new();
1182     return ;
1183 } /* tag_init() */
1184
1185 static void tag_insert(name, symbolP)
1186 char *name;
1187 symbolS *symbolP;
1188 {
1189         register char * error_string;
1190
1191         if (*(error_string = hash_jam(tag_hash, name, (char *)symbolP))) {
1192                 as_fatal("Inserting \"%s\" into structure table failed: %s",
1193                          name, error_string);
1194         }
1195         return ;
1196 } /* tag_insert() */
1197
1198 static symbolS *tag_find_or_make(name)
1199 char *name;
1200 {
1201         symbolS *symbolP;
1202
1203         if ((symbolP = tag_find(name)) == NULL) {
1204                 symbolP = symbol_new(name,
1205                                      SEG_UNKNOWN,
1206                                      0,
1207                                      &zero_address_frag);
1208
1209                 tag_insert(S_GET_NAME(symbolP), symbolP);
1210                 symbol_table_insert(symbolP);
1211         } /* not found */
1212
1213         return(symbolP);
1214 } /* tag_find_or_make() */
1215
1216 static symbolS *tag_find(name)
1217 char *name;
1218 {
1219 #ifdef STRIP_UNDERSCORE
1220         if (*name == '_') name++;
1221 #endif /* STRIP_UNDERSCORE */
1222         return((symbolS*)hash_find(tag_hash, name));
1223 } /* tag_find() */
1224
1225 void obj_read_begin_hook() {
1226  /* These had better be the same.  Usually 18 bytes. */
1227 #ifndef BFD_HEADERS
1228         know(sizeof(SYMENT) == sizeof(AUXENT));
1229         know(SYMESZ == AUXESZ);
1230 #endif
1231         tag_init();
1232
1233         return;
1234 } /* obj_read_begin_hook() */
1235
1236 /* This function runs through the symbol table and puts all the
1237    externals onto another chain */
1238
1239 /* The chain of externals */
1240 symbolS *symbol_externP = NULL;
1241 symbolS *symbol_extern_lastP = NULL;
1242
1243 stack*block_stack;
1244   symbolS *last_functionP = NULL;
1245   symbolS *last_tagP;
1246
1247
1248 static unsigned int DEFUN_VOID(yank_symbols)
1249 {
1250   symbolS *symbolP;
1251   unsigned int symbol_number =0;
1252   
1253   for (symbolP = symbol_rootP;
1254        symbolP;
1255        symbolP = symbolP ? symbol_next(symbolP) : symbol_rootP) {
1256       if (!SF_GET_DEBUG(symbolP)) {
1257           /* Debug symbols do not need all this rubbish */
1258           symbolS* real_symbolP;
1259
1260           /* L* and C_EFCN symbols never merge. */
1261           if (!SF_GET_LOCAL(symbolP)
1262               && (real_symbolP = symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP))
1263               && real_symbolP != symbolP) {
1264               /* FIXME-SOON: where do dups come from?
1265                  Maybe tag references before definitions? xoxorich. */
1266               /* Move the debug data from the debug symbol to the
1267                  real symbol. Do NOT do the oposite (i.e. move from
1268                  real symbol to debug symbol and remove real symbol from the
1269                  list.) Because some pointers refer to the real symbol
1270                  whereas no pointers refer to the debug symbol. */
1271               c_symbol_merge(symbolP, real_symbolP);
1272               /* Replace the current symbol by the real one */
1273               /* The symbols will never be the last or the first
1274                  because : 1st symbol is .file and 3 last symbols are
1275                  .text, .data, .bss */
1276               symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
1277               symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
1278               symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
1279               symbolP = real_symbolP;
1280             }                   /* if not local but dup'd */
1281
1282           if (flagseen['R'] && (S_GET_SEGMENT(symbolP) == SEG_E1)) {
1283               S_SET_SEGMENT(symbolP, SEG_E0);
1284             }                   /* push data into text */
1285
1286           S_SET_VALUE(symbolP,
1287                       S_GET_VALUE(symbolP) + symbolP->sy_frag->fr_address);
1288
1289           if (!S_IS_DEFINED(symbolP) && !SF_GET_LOCAL(symbolP)) 
1290           {
1291             S_SET_EXTERNAL(symbolP);
1292           } 
1293           else if (S_GET_STORAGE_CLASS(symbolP) == C_NULL) 
1294           {
1295             if (S_GET_SEGMENT(symbolP) == SEG_E0)
1296             {
1297               S_SET_STORAGE_CLASS(symbolP, C_LABEL);
1298             } 
1299             else 
1300             {
1301               S_SET_STORAGE_CLASS(symbolP, C_STAT);
1302             }
1303           }             
1304
1305           /* Mainly to speed up if not -g */
1306           if (SF_GET_PROCESS(symbolP)) 
1307           {
1308             /* Handle the nested blocks auxiliary info. */
1309             if (S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
1310                 if (!strcmp(S_GET_NAME(symbolP), ".bb"))
1311                  stack_push(block_stack, (char *) &symbolP);
1312                 else {          /* .eb */
1313                     register symbolS* begin_symbolP;
1314                     begin_symbolP = *(symbolS**)stack_pop(block_stack);
1315                     if (begin_symbolP == (symbolS*)0)
1316                      as_warn("mismatched .eb");
1317                     else
1318                      SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number+2);
1319                   }
1320               }
1321             /* If we are able to identify the type of a function, and we
1322                are out of a function (last_functionP == 0) then, the
1323                function symbol will be associated with an auxiliary
1324                entry. */
1325             if (last_functionP == (symbolS*)0 &&
1326                 SF_GET_FUNCTION(symbolP)) {
1327                 last_functionP = symbolP;
1328
1329                 if (S_GET_NUMBER_AUXILIARY(symbolP) < 1) {
1330                     S_SET_NUMBER_AUXILIARY(symbolP, 1);
1331                   }             /* make it at least 1 */
1332
1333                 /* Clobber possible stale .dim information. */
1334 #if 0
1335 /* Iffed out by steve - this fries the lnnoptr info too */
1336                 bzero(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen,
1337                       sizeof(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
1338 #endif
1339               }
1340             /* The C_FCN doesn't need any additional information.
1341                I don't even know if this is needed for sdb. But the
1342                standard assembler generates it, so...
1343                */
1344             if (S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
1345                 if (last_functionP == (symbolS*)0)
1346                  as_fatal("C_EFCN symbol out of scope");
1347                 SA_SET_SYM_FSIZE(last_functionP,
1348                                  (long)(S_GET_VALUE(symbolP) -
1349                                         S_GET_VALUE(last_functionP)));
1350                 SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
1351                 last_functionP = (symbolS*)0;
1352               }
1353           }
1354         } else if (SF_GET_TAG(symbolP)) {
1355             /* First descriptor of a structure must point to
1356                the first slot after the structure description. */
1357             last_tagP = symbolP;
1358
1359           } else if (S_GET_STORAGE_CLASS(symbolP) == C_EOS) {
1360               /* +2 take in account the current symbol */
1361               SA_SET_SYM_ENDNDX(last_tagP, symbol_number + 2);
1362             } else if (S_GET_STORAGE_CLASS(symbolP) == C_FILE) {
1363                 if (S_GET_VALUE(symbolP)) {
1364                     S_SET_VALUE((symbolS *) S_GET_VALUE(symbolP), symbol_number);
1365                     S_SET_VALUE(symbolP, 0);
1366                   }             /* no one points at the first .file symbol */
1367               }                 /* if debug or tag or eos or file */
1368
1369       /* We must put the external symbols apart. The loader
1370          does not bomb if we do not. But the references in
1371          the endndx field for a .bb symbol are not corrected
1372          if an external symbol is removed between .bb and .be.
1373          I.e in the following case :
1374          [20] .bb endndx = 22
1375          [21] foo external
1376          [22] .be
1377          ld will move the symbol 21 to the end of the list but
1378          endndx will still be 22 instead of 21. */
1379
1380
1381       if (SF_GET_LOCAL(symbolP)) {
1382           /* remove C_EFCN and LOCAL (L...) symbols */
1383           /* next pointer remains valid */
1384           symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
1385
1386         }
1387       else if (!S_IS_DEFINED(symbolP)
1388                && !S_IS_DEBUG(symbolP) 
1389                && !SF_GET_STATICS(symbolP) &&
1390                S_GET_STORAGE_CLASS(symbolP) == C_EXT)
1391       { /* C_EXT && !SF_GET_FUNCTION(symbolP))  */
1392             /* if external, Remove from the list */
1393             symbolS *hold = symbol_previous(symbolP);
1394
1395             symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
1396             symbol_clear_list_pointers(symbolP);
1397             symbol_append(symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP);
1398             symbolP = hold;
1399           } else {
1400               if (SF_GET_STRING(symbolP)) {
1401                   symbolP->sy_name_offset = string_byte_count;
1402                   string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
1403                 } else {
1404                     symbolP->sy_name_offset = 0;
1405                   }             /* fix "long" names */
1406
1407               symbolP->sy_number = symbol_number;
1408               symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
1409             }                   /* if local symbol */
1410     }                           /* traverse the symbol list */
1411   return symbol_number;
1412   
1413 }
1414
1415
1416 static unsigned int DEFUN_VOID(glue_symbols)
1417 {
1418   unsigned int symbol_number = 0;
1419   symbolS *symbolP;    
1420   for (symbolP = symbol_externP; symbol_externP;) {
1421       symbolS *tmp = symbol_externP;
1422
1423       /* append */
1424       symbol_remove(tmp, &symbol_externP, &symbol_extern_lastP);
1425       symbol_append(tmp, symbol_lastP, &symbol_rootP, &symbol_lastP);
1426
1427       /* and process */
1428       if (SF_GET_STRING(tmp)) {
1429           tmp->sy_name_offset = string_byte_count;
1430           string_byte_count += strlen(S_GET_NAME(tmp)) + 1;
1431         } else {
1432             tmp->sy_name_offset = 0;
1433           }                     /* fix "long" names */
1434
1435       tmp->sy_number = symbol_number;
1436       symbol_number += 1 + S_GET_NUMBER_AUXILIARY(tmp);
1437     }                           /* append the entire extern chain */
1438   return symbol_number;
1439   
1440 }
1441
1442 static unsigned int DEFUN_VOID(tie_tags)
1443 {
1444   unsigned int symbol_number = 0;
1445   
1446   symbolS*symbolP;  
1447   for (symbolP = symbol_rootP; symbolP; symbolP =
1448        symbol_next(symbolP)) 
1449   {
1450     symbolP->sy_number = symbol_number;
1451
1452
1453
1454     if (SF_GET_TAGGED(symbolP)) 
1455     {
1456       SA_SET_SYM_TAGNDX
1457        (symbolP,
1458         ((symbolS*) SA_GET_SYM_TAGNDX(symbolP))->sy_number);
1459     }           
1460
1461     symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
1462   }             
1463   return symbol_number;
1464   
1465 }
1466
1467 static void 
1468 DEFUN(crawl_symbols,(headers, abfd),
1469       struct    internal_filehdr *headers AND
1470       bfd *abfd)
1471 {
1472
1473   unsigned int i;       
1474   unsigned int ptr = 0;
1475
1476
1477   symbolS *symbolP;
1478
1479   /* Initialize the stack used to keep track of the matching .bb .be */
1480
1481   block_stack = stack_init(512, sizeof(symbolS*));
1482   /* JF deal with forward references first... */
1483   for (symbolP = symbol_rootP;
1484        symbolP;
1485        symbolP = symbol_next(symbolP)) 
1486   {
1487
1488     if (symbolP->sy_forward) {
1489         S_SET_VALUE(symbolP, (S_GET_VALUE(symbolP)
1490                               + S_GET_VALUE(symbolP->sy_forward)
1491                               + symbolP->sy_forward->sy_frag->fr_address));
1492
1493         if (SF_GET_GET_SEGMENT(symbolP)) {
1494             S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
1495           }                     /* forward segment also */
1496
1497         symbolP->sy_forward=0;
1498       }                         /* if it has a forward reference */
1499   }                             /* walk the symbol chain */
1500
1501
1502   /* The symbol list should be ordered according to the following sequence
1503    * order :
1504    * . .file symbol
1505    * . debug entries for functions
1506    * . fake symbols for the sections, including.text .data and .bss
1507    * . defined symbols
1508    * . undefined symbols
1509    * But this is not mandatory. The only important point is to put the
1510    * undefined symbols at the end of the list.
1511    */
1512
1513   if (symbol_rootP == NULL
1514       || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
1515       c_dot_file_symbol("fake");
1516     }
1517   /* Is there a .file symbol ? If not insert one at the beginning. */
1518
1519   /*
1520    * Build up static symbols for the sections, they are filled in later
1521    */
1522
1523
1524   for (i = SEG_E0; i < SEG_E9; i++) 
1525   {
1526     if (segment_info[i].scnhdr.s_name[0])
1527     {
1528       segment_info[i].dot = 
1529        c_section_symbol(segment_info[i].scnhdr.s_name,
1530                         i-SEG_E0+1);
1531             
1532     }
1533   }
1534
1535
1536   /* Take all the externals out and put them into another chain */
1537   headers->f_nsyms =   yank_symbols();
1538   /* Take the externals and glue them onto the end.*/
1539   headers->f_nsyms +=  glue_symbols();
1540
1541   headers->f_nsyms =   tie_tags();
1542   know(symbol_externP == NULL);
1543   know(symbol_extern_lastP  == NULL);
1544
1545   return;
1546 }
1547
1548 /*
1549  * Find strings by crawling along symbol table chain.
1550  */
1551
1552 void DEFUN(w_strings,(where),
1553            char *where)
1554 {
1555   symbolS *symbolP;
1556
1557   /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
1558   md_number_to_chars(where, string_byte_count, sizeof(string_byte_count));
1559   where += sizeof(string_byte_count);
1560   for (symbolP = symbol_rootP;
1561        symbolP;
1562        symbolP = symbol_next(symbolP)) 
1563   {
1564     unsigned int size;
1565     
1566     if (SF_GET_STRING(symbolP)) {
1567         size = strlen(S_GET_NAME(symbolP)) + 1;
1568             
1569         memcpy(where,  S_GET_NAME(symbolP),size);
1570         where += size;
1571             
1572       } 
1573   }             
1574
1575 }
1576
1577
1578
1579
1580
1581 static void 
1582 DEFUN(do_linenos_for,(abfd, file_cursor),
1583       bfd *abfd AND
1584       unsigned long *file_cursor)
1585 {
1586   unsigned int idx;
1587   
1588   for (idx = SEG_E0;  idx < SEG_E9; idx++) 
1589   {
1590     segment_info_type *s = segment_info + idx;    
1591
1592
1593     if (s->scnhdr.s_nlnno != 0) 
1594     {
1595       struct lineno_list *line_ptr ;
1596
1597       struct external_lineno *buffer = 
1598        (struct external_lineno *)xmalloc(s->scnhdr.s_nlnno * LINESZ);
1599
1600       struct external_lineno *dst= buffer;
1601
1602       /* Run through the table we've built and turn it into its external
1603          form, take this chance to remove duplicates */
1604
1605       for (line_ptr = s->lineno_list_head;
1606            line_ptr != (struct lineno_list *)NULL;
1607            line_ptr = line_ptr->next) 
1608       {
1609
1610         if (line_ptr->line.l_lnno == 0) 
1611         {
1612           /* Turn a pointer to a symbol into the symbols' index */
1613           line_ptr->line.l_addr.l_symndx =
1614            ( (symbolS *)line_ptr->line.l_addr.l_symndx)->sy_number;
1615         }         
1616         else 
1617         {
1618           line_ptr->line.l_addr.l_paddr += ((struct frag * )(line_ptr->frag))->fr_address;
1619         }
1620
1621           
1622         (void)  bfd_coff_swap_lineno_out(abfd, &(line_ptr->line), dst);
1623         dst++;
1624         
1625       }
1626
1627       s->scnhdr.s_lnnoptr = *file_cursor;
1628       
1629       bfd_write(buffer, 1, s->scnhdr.s_nlnno* LINESZ, abfd);
1630       free(buffer);
1631       
1632       *file_cursor += s->scnhdr.s_nlnno * LINESZ;
1633     }
1634   }
1635 }
1636
1637
1638 /* Now we run through the list of frag chains in a segment and
1639    make all the subsegment frags appear at the end of the
1640    list, as if the seg 0 was extra long */
1641
1642 static void DEFUN_VOID(remove_subsegs)
1643 {
1644     unsigned int i;     
1645
1646     for (i = SEG_E0; i < SEG_UNKNOWN; i++)
1647     { 
1648         frchainS *head =  segment_info[i].frchainP;
1649         fragS dummy;
1650         fragS * prev_frag = &dummy;
1651         
1652         while (head && head->frch_seg == i) 
1653         {
1654             prev_frag->fr_next = head->frch_root;
1655             prev_frag = head->frch_last;
1656             head = head->frch_next;
1657         }
1658         prev_frag->fr_next = 0;
1659     }
1660 }
1661
1662 int machine;
1663 int coff_flags;
1664 extern void DEFUN_VOID(write_object_file)
1665 {
1666     int i;
1667     struct frchain *frchain_ptr; 
1668
1669     struct internal_filehdr filehdr;
1670     struct internal_aouthdr aouthdr;
1671     unsigned long file_cursor;  
1672     bfd *abfd;
1673       unsigned int addr = 0;  
1674     abfd = bfd_openw(out_file_name, TARGET_FORMAT);
1675
1676
1677     if (abfd == 0) {
1678             as_perror ("FATAL: Can't create %s", out_file_name);
1679             exit(42);
1680         }
1681     bfd_set_format(abfd, bfd_object);
1682     bfd_set_arch_mach(abfd, BFD_ARCH, machine);
1683
1684
1685
1686     string_byte_count = 4;
1687   
1688     for (frchain_ptr = frchain_root;
1689          frchain_ptr != (struct frchain *)NULL; 
1690          frchain_ptr = frchain_ptr->frch_next) {
1691             /* Run through all the sub-segments and align them up. Also close any
1692                open frags. We tack a .fill onto the end of the frag chain so
1693                that any .align's size can be worked by looking at the next
1694                frag */
1695
1696             subseg_new(frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
1697 #define SUB_SEGMENT_ALIGN 1
1698             frag_align(SUB_SEGMENT_ALIGN,0);
1699             frag_wane(frag_now);
1700             frag_now->fr_fix = 0;
1701             know( frag_now->fr_next == NULL );
1702         }
1703
1704
1705     remove_subsegs();
1706     
1707
1708     for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
1709     {
1710         relax_segment(segment_info[i].frchainP->frch_root, i);
1711     }
1712   
1713
1714
1715
1716
1717       filehdr.f_nscns = 0;
1718   
1719       /* Find out how big the sections are */
1720       for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
1721       {
1722
1723         if (segment_info[i].scnhdr.s_name[0]) 
1724         {
1725           filehdr.f_nscns++;
1726         }
1727           
1728         if (i == SEG_E2) 
1729         {
1730           /* THis is a special case, we leave the size alone, which will have */
1731           /* been made up from all and any lcomms seen */
1732         }
1733         else 
1734         {
1735           addr += size_section(abfd, i);
1736         }
1737       }
1738
1739
1740
1741     /* Turn the gas native symbol table shape into a coff symbol table */
1742     crawl_symbols(&filehdr, abfd);
1743 #ifndef TC_H8300
1744     for (i = SEG_E0; i < SEG_UNKNOWN; i++) 
1745     {
1746       fixup_mdeps(segment_info[i].frchainP->frch_root);
1747       fixup_segment(segment_info[i].fix_root, i);
1748     }
1749 #endif
1750
1751     file_cursor =   FILHSZ + SCNHSZ * filehdr.f_nscns ;
1752
1753     bfd_seek(abfd, file_cursor, 0);
1754
1755
1756     do_relocs_for(abfd, &file_cursor);
1757
1758     do_linenos_for(abfd, &file_cursor);
1759
1760
1761     /* Plant the data */
1762
1763     fill_section(abfd,&filehdr, &file_cursor);
1764
1765
1766
1767     filehdr.f_magic = COFF_MAGIC;
1768     filehdr.f_timdat = time(0);
1769     filehdr.f_flags = COFF_FLAGS | coff_flags;
1770     
1771     if (!had_lineno) 
1772     {
1773       filehdr.f_flags |= F_LNNO;
1774     }
1775     if (!had_reloc)
1776     {
1777       filehdr.f_flags |= F_RELFLG;
1778     }
1779     
1780
1781
1782
1783
1784
1785
1786   {
1787
1788       unsigned int   symtable_size = filehdr.f_nsyms * SYMESZ;
1789       char *buffer1 = malloc(symtable_size + string_byte_count + 4);
1790       char *ptr = buffer1;
1791       filehdr.f_symptr = bfd_tell(abfd);
1792       w_symbols(abfd, buffer1, symbol_rootP);
1793       w_strings(buffer1 + symtable_size);
1794       bfd_write(buffer1, 1,symtable_size +  string_byte_count + 4, abfd);
1795       free(buffer1);
1796       
1797   }
1798     coff_header_append(abfd, &filehdr, &aouthdr);
1799
1800     bfd_close_all_done(abfd);
1801 }
1802
1803
1804 static void DEFUN(change_to_section,(name, len, exp),
1805  char *name AND
1806  unsigned int len AND
1807  unsigned int exp)
1808 {
1809   unsigned int i;  
1810   /* Find out if we've already got a section of this name etc */
1811   for(i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0] ; i++) 
1812   {
1813     if (strncmp(segment_info[i].scnhdr.s_name, name, len) == 0) 
1814     {
1815       subseg_new(i, exp);  
1816       return;
1817       
1818     }
1819   }
1820   /* No section, add one */
1821   strncpy(segment_info[i].scnhdr.s_name, name, 8);
1822   subseg_new(i, exp);  
1823 }
1824
1825 void 
1826 DEFUN_VOID(obj_coff_section)
1827 {
1828     /* Strip out the section name */
1829     char *section_name ;
1830     char *section_name_end;
1831     char c;
1832     
1833     unsigned int len;
1834     unsigned int exp;
1835   
1836     section_name =  input_line_pointer;
1837     c =   get_symbol_end();
1838     section_name_end =  input_line_pointer;
1839
1840     len = section_name_end - section_name ;
1841     input_line_pointer++;
1842     SKIP_WHITESPACE();
1843     if (c == ',')
1844     {
1845         exp = get_absolute_expression();
1846     }
1847     else if ( *input_line_pointer == ',') 
1848     {
1849     
1850         input_line_pointer++;
1851         exp = get_absolute_expression();    
1852     }
1853     else 
1854     {
1855         exp = 0;
1856     }
1857   
1858     change_to_section(section_name, len,exp);
1859 *section_name_end = c;    
1860   
1861 }
1862
1863
1864 static void obj_coff_text()
1865 {
1866   change_to_section(".text",5, get_absolute_expression());
1867 }
1868
1869
1870 static void obj_coff_data()
1871 {
1872   change_to_section(".data",5, get_absolute_expression());
1873 }
1874
1875 void c_symbol_merge(debug, normal)
1876 symbolS *debug;
1877 symbolS *normal;
1878 {
1879         S_SET_DATA_TYPE(normal, S_GET_DATA_TYPE(debug));
1880         S_SET_STORAGE_CLASS(normal, S_GET_STORAGE_CLASS(debug));
1881
1882         if (S_GET_NUMBER_AUXILIARY(debug) > S_GET_NUMBER_AUXILIARY(normal)) {
1883                 S_SET_NUMBER_AUXILIARY(normal, S_GET_NUMBER_AUXILIARY(debug));
1884         } /* take the most we have */
1885
1886         if (S_GET_NUMBER_AUXILIARY(debug) > 0) {
1887                 memcpy((char*)&normal->sy_symbol.ost_auxent[0], (char*)&debug->sy_symbol.ost_auxent[0], S_GET_NUMBER_AUXILIARY(debug) * AUXESZ);
1888         } /* Move all the auxiliary information */
1889
1890         /* Move the debug flags. */
1891         SF_SET_DEBUG_FIELD(normal, SF_GET_DEBUG_FIELD(debug));
1892 } /* c_symbol_merge() */
1893
1894 static int
1895 DEFUN(c_line_new,(symbol, paddr, line_number, frag),
1896       symbolS *symbol AND
1897       long paddr AND
1898       unsigned short line_number AND
1899       fragS* frag)
1900 {
1901   struct lineno_list* new_line = 
1902    (struct lineno_list *)xmalloc(sizeof(struct lineno_list));
1903     
1904   segment_info_type *s =   segment_info + now_seg;
1905   new_line->line.l_lnno = line_number;
1906
1907   had_lineno = 1;
1908   
1909   if (line_number == 0) 
1910   {
1911     last_line_symbol = symbol;
1912     new_line->line.l_addr.l_symndx = (long)symbol;
1913   }
1914   else 
1915   {
1916     new_line->line.l_addr.l_paddr = paddr;
1917   }  
1918
1919   new_line->frag = (char*)frag;
1920   new_line->next = (struct lineno_list*)NULL;
1921
1922     
1923   if (s->lineno_list_head == (struct lineno_list *)NULL) 
1924   {
1925     s->lineno_list_head = new_line;
1926   }
1927   else 
1928   {
1929     s->lineno_list_tail->next = new_line;
1930   }
1931   s->lineno_list_tail = new_line;
1932   return LINESZ * s->scnhdr.s_nlnno ++;
1933 }
1934
1935 void c_dot_file_symbol(filename)
1936 char *filename;
1937 {
1938     symbolS* symbolP;
1939
1940     symbolP = symbol_new(".file",
1941                          SEG_DEBUG,
1942                          0,
1943                          &zero_address_frag);
1944
1945     S_SET_STORAGE_CLASS(symbolP, C_FILE);
1946     S_SET_NUMBER_AUXILIARY(symbolP, 1);
1947     SA_SET_FILE_FNAME(symbolP, filename);
1948 #ifndef NO_LISTING
1949   {
1950     extern int listing;
1951     if (listing) 
1952     {
1953       listing_source_file(filename);
1954     }
1955     
1956   }
1957     
1958 #endif    
1959     SF_SET_DEBUG(symbolP);
1960     S_SET_VALUE(symbolP, (long) previous_file_symbol);
1961
1962     previous_file_symbol = symbolP;
1963
1964     /* Make sure that the symbol is first on the symbol chain */
1965     if (symbol_rootP != symbolP) {
1966             if (symbolP == symbol_lastP) {
1967                     symbol_lastP = symbol_lastP->sy_previous;
1968             } /* if it was the last thing on the list */
1969
1970             symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
1971             symbol_insert(symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
1972             symbol_rootP = symbolP;
1973     } /* if not first on the list */
1974
1975 } /* c_dot_file_symbol() */
1976
1977 /*
1978  * Build a 'section static' symbol.
1979  */
1980
1981 symbolS *c_section_symbol(name,idx)
1982 char *name;
1983 int idx;
1984 {
1985     symbolS *symbolP;
1986
1987     symbolP = symbol_new(name,idx,
1988                          0,
1989                          &zero_address_frag);
1990
1991     S_SET_STORAGE_CLASS(symbolP, C_STAT);
1992     S_SET_NUMBER_AUXILIARY(symbolP, 1);
1993
1994     SF_SET_STATICS(symbolP);
1995
1996     return symbolP;
1997 } /* c_section_symbol() */
1998
1999 static void 
2000 DEFUN(w_symbols,(abfd, where, symbol_rootP),
2001 bfd *abfd AND
2002 char *where AND
2003 symbolS *symbol_rootP)
2004 {
2005     symbolS *symbolP;
2006     unsigned int i;
2007     
2008     /* First fill in those values we have only just worked out */
2009     for (i = SEG_E0; i < SEG_E9; i++) 
2010     {
2011         symbolP = segment_info[i].dot;
2012         if (symbolP) 
2013         {
2014     
2015             SA_SET_SCN_SCNLEN(symbolP, segment_info[i].scnhdr.s_size);
2016             SA_SET_SCN_NRELOC(symbolP, segment_info[i].scnhdr.s_nreloc);
2017             SA_SET_SCN_NLINNO(symbolP, segment_info[i].scnhdr.s_nlnno);
2018             
2019         }
2020     }
2021     
2022     /*
2023      * Emit all symbols left in the symbol chain.
2024      */
2025     for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
2026             /* Used to save the offset of the name. It is used to point
2027                to the string in memory but must be a file offset. */
2028             register char *     temp;
2029
2030             tc_coff_symbol_emit_hook(symbolP);
2031
2032             temp = S_GET_NAME(symbolP);
2033             if (SF_GET_STRING(symbolP)) {
2034                     S_SET_OFFSET(symbolP, symbolP->sy_name_offset);
2035                     S_SET_ZEROES(symbolP, 0);
2036                 } else {
2037                         bzero(symbolP->sy_symbol.ost_entry.n_name, SYMNMLEN);
2038                         strncpy(symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN);
2039                     }
2040             where =  symbol_to_chars(abfd, where, symbolP);
2041             S_SET_NAME(symbolP,temp);
2042         }
2043     
2044 }                               /* w_symbols() */
2045
2046 static void DEFUN_VOID(obj_coff_lcomm)
2047 {
2048   char *name;
2049   char c;
2050   int temp;
2051   char *p;
2052   unsigned long vma;
2053
2054   symbolS *symbolP;
2055   name = input_line_pointer;
2056
2057
2058   c = get_symbol_end();
2059   p = input_line_pointer;
2060   *p = c;
2061   SKIP_WHITESPACE();
2062   if (*input_line_pointer != ',') {
2063     as_bad("Expected comma after name");
2064     ignore_rest_of_line();
2065     return;
2066   }
2067   if (*input_line_pointer == '\n') {
2068     as_bad("Missing size expression");
2069     return;
2070   }
2071   input_line_pointer++;
2072   if ((temp = get_absolute_expression ()) < 0) {
2073     as_warn("lcomm length (%d.) <0! Ignored.", temp);
2074     ignore_rest_of_line();
2075     return;
2076   }
2077   *p = 0;
2078
2079   {
2080     /* Allocate zero static local data in the .data section now
2081        instead of the bss section as a symbol with a value */
2082    char *x;
2083    segT  oldseg = now_seg;
2084    int oldsubseg  = now_subseg;
2085      
2086    subseg_new(SEG_DATA, 10);
2087    colon(name);
2088    frag_align(2,0);
2089    record_alignment(SEG_DATA, 4);
2090    x =  frag_var (rs_fill, 1, 1, (relax_substateT)0, (symbolS *)0,
2091                   temp, (char *)0);
2092    * x= 0;
2093
2094    subseg_new(oldseg, oldsubseg);
2095  }
2096   demand_empty_rest_of_line();
2097 }
2098
2099 static void DEFUN(fixup_mdeps,(frags),
2100                   fragS *frags)
2101 {
2102   while (frags) 
2103   {
2104     switch (frags->fr_type) 
2105     {
2106      case rs_align:
2107      case rs_org:
2108       frags->fr_type = rs_fill;
2109       frags->fr_offset =
2110        (frags->fr_next->fr_address - frags->fr_address - frags->fr_fix);
2111       break;
2112      case rs_machine_dependent:
2113       md_convert_frag(0, frags);
2114       break;
2115      default:
2116       ;
2117     }
2118     frags = frags->fr_next;
2119   }
2120
2121 }
2122 #if 1
2123 static void DEFUN(fixup_segment,(fixP, this_segment_type),
2124 register fixS * fixP AND
2125 segT            this_segment_type)
2126 {
2127     register symbolS *add_symbolP;
2128     register symbolS *sub_symbolP;
2129     register long add_number;
2130     register int size;
2131     register char *place;
2132     register long where;
2133     register char pcrel;
2134     register fragS *fragP;
2135     register segT add_symbol_segment = SEG_ABSOLUTE;
2136         
2137         
2138     for ( ;  fixP;  fixP = fixP->fx_next) 
2139     {
2140         fragP       = fixP->fx_frag;
2141         know(fragP);
2142         where     = fixP->fx_where;
2143         place       = fragP->fr_literal + where;
2144         size      = fixP->fx_size;
2145         add_symbolP = fixP->fx_addsy;
2146 #ifdef TC_I960
2147         if (fixP->fx_callj && TC_S_IS_CALLNAME(add_symbolP)) {
2148                 /* Relocation should be done via the
2149                    associated 'bal' entry point
2150                    symbol. */
2151
2152                 if (!TC_S_IS_BALNAME(tc_get_bal_of_call(add_symbolP))) {
2153                         as_bad("No 'bal' entry point for leafproc %s",
2154                                S_GET_NAME(add_symbolP));
2155                         continue;
2156                     }
2157                 fixP->fx_addsy = add_symbolP = tc_get_bal_of_call(add_symbolP);
2158             }                   /* callj relocation */
2159 #endif
2160         sub_symbolP = fixP->fx_subsy;
2161         add_number  = fixP->fx_offset;
2162         pcrel     = fixP->fx_pcrel;
2163
2164         if (add_symbolP) {
2165                 add_symbol_segment = S_GET_SEGMENT(add_symbolP);
2166             }                   /* if there is an addend */
2167                 
2168         if (sub_symbolP) {
2169                 if (!add_symbolP) {
2170                         /* Its just -sym */
2171                         if (S_GET_SEGMENT(sub_symbolP) != SEG_ABSOLUTE) {
2172                                 as_bad("Negative of non-absolute symbol %s", S_GET_NAME(sub_symbolP));
2173                             }   /* not absolute */
2174                                 
2175                         add_number -= S_GET_VALUE(sub_symbolP);
2176                         fixP->fx_subsy = 0;
2177                                 
2178                         /* if sub_symbol is in the same segment that add_symbol
2179                            and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
2180                     } else if ((S_GET_SEGMENT(sub_symbolP) == add_symbol_segment)
2181                                && (SEG_NORMAL(add_symbol_segment)
2182                                    || (add_symbol_segment == SEG_ABSOLUTE))) {
2183                             /* Difference of 2 symbols from same segment. */
2184                             /* Can't make difference of 2 undefineds: 'value' means */
2185                             /* something different for N_UNDF. */
2186 #ifdef TC_I960
2187                             /* Makes no sense to use the difference of 2 arbitrary symbols
2188                              * as the target of a call instruction.
2189                              */
2190                             if (fixP->fx_callj) {
2191                                     as_bad("callj to difference of 2 symbols");
2192                                 }
2193 #endif                          /* TC_I960 */
2194                             add_number += S_GET_VALUE(add_symbolP) - 
2195                              S_GET_VALUE(sub_symbolP);
2196                                 
2197                             add_symbolP = NULL;
2198                             fixP->fx_addsy = NULL;
2199                         } else {
2200                                 /* Different segments in subtraction. */
2201                                 know(!(S_IS_EXTERNAL(sub_symbolP) && (S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)));
2202                                 
2203                                 if ((S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)) {
2204                                         add_number -= S_GET_VALUE(sub_symbolP);
2205                                     } else {
2206                                             as_bad("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %d.",
2207                                                    segment_name(S_GET_SEGMENT(sub_symbolP)),
2208                                                    S_GET_NAME(sub_symbolP), fragP->fr_address + where);
2209                                         } /* if absolute */
2210                             }
2211             }                   /* if sub_symbolP */
2212
2213         if (add_symbolP) {
2214                 if (add_symbol_segment == this_segment_type && pcrel) {
2215                         /*
2216                          * This fixup was made when the symbol's segment was
2217                          * SEG_UNKNOWN, but it is now in the local segment.
2218                          * So we know how to do the address without relocation.
2219                          */
2220 #ifdef TC_I960
2221                         /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal',
2222                          * in which cases it modifies *fixP as appropriate.  In the case
2223                          * of a 'calls', no further work is required, and *fixP has been
2224                          * set up to make the rest of the code below a no-op.
2225                          */
2226                         reloc_callj(fixP);
2227 #endif                          /* TC_I960 */
2228                                 
2229                         add_number += S_GET_VALUE(add_symbolP);
2230                         add_number -= md_pcrel_from (fixP);
2231                         pcrel = 0; /* Lie. Don't want further pcrel processing. */
2232                         fixP->fx_addsy = NULL; /* No relocations please. */
2233                     } else 
2234                     {
2235                         switch (add_symbol_segment) 
2236                         {
2237                           case SEG_ABSOLUTE:
2238 #ifdef TC_I960
2239                             reloc_callj(fixP); /* See comment about reloc_callj() above*/
2240 #endif                          /* TC_I960 */
2241                             add_number += S_GET_VALUE(add_symbolP);
2242                             fixP->fx_addsy = NULL;
2243                             add_symbolP = NULL;
2244                             break;
2245                           default:
2246
2247                             add_number += S_GET_VALUE(add_symbolP) +
2248                 segment_info[S_GET_SEGMENT(add_symbolP)].scnhdr.s_paddr ;
2249                             break;
2250                                         
2251                           case SEG_UNKNOWN:
2252 #ifdef TC_I960
2253                             if ((int)fixP->fx_bit_fixP == 13) {
2254                                     /* This is a COBR instruction.  They have only a
2255                                      * 13-bit displacement and are only to be used
2256                                      * for local branches: flag as error, don't generate
2257                                      * relocation.
2258                                      */
2259                                     as_bad("can't use COBR format with external label");
2260                                     fixP->fx_addsy = NULL; /* No relocations please. */
2261                                     continue;
2262                                 } /* COBR */
2263 #endif                          /* TC_I960 */
2264                 
2265
2266
2267                             break;
2268                                         
2269
2270                         }       /* switch on symbol seg */
2271                     }           /* if not in local seg */
2272             }                   /* if there was a + symbol */
2273
2274         if (pcrel) {
2275                 add_number -= md_pcrel_from(fixP);
2276                 if (add_symbolP == 0) {
2277                         fixP->fx_addsy = & abs_symbol;
2278                     }           /* if there's an add_symbol */
2279             }                   /* if pcrel */
2280                 
2281         if (!fixP->fx_bit_fixP) {
2282                 if ((size==1 &&
2283                      (add_number& ~0xFF)   && ((add_number&~0xFF)!=(-1&~0xFF))) ||
2284                     (size==2 &&
2285                      (add_number& ~0xFFFF) && ((add_number&~0xFFFF)!=(-1&~0xFFFF)))) {
2286                         as_bad("Value of %d too large for field of %d bytes at 0x%x",
2287                                add_number, size, fragP->fr_address + where);
2288                     }           /* generic error checking */
2289 #ifdef WARN_SIGNED_OVERFLOW_WORD
2290                 /* Warn if a .word value is too large when treated as
2291                    a signed number.  We already know it is not too
2292                    negative.  This is to catch over-large switches
2293                    generated by gcc on the 68k.  */
2294                 if (! flagseen['J']
2295                     && size == 2
2296                     && add_number > 0x7fff)
2297                   as_bad ("Signed .word overflow; switch may be too large; %d at 0x%x",
2298                           add_number, fragP->fr_address + where);
2299 #endif
2300             }                   /* not a bit fix */
2301         /* once this fix has been applied, we don't have to output anything 
2302            nothing more need be done -*/
2303         md_apply_fix(fixP, add_number);
2304       
2305     }                           /* For each fixS in this segment. */
2306         
2307
2308 }                               /* fixup_segment() */
2309 #endif
2310
2311
2312
2313