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