* as/mcs51/lkarea.c: removed old K&R style,
[fw/sdcc] / as / mcs51 / lkarea.c
1 /* lkarea.c */
2
3 /*
4  * (C) Copyright 1989-1995
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  *
11  *  3-Nov-97 JLH:
12  *           - change lkparea to use a_type == 0 as "virgin area" flag
13  * 02-Apr-98 JLH: add code to link 8051 data spaces
14  */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include "aslink.h"
19
20 /*)Module   lkarea.c
21  *
22  *  The module lkarea.c contains the functions which
23  *  create and link together all area definitions read
24  *  from the .rel file(s).
25  *
26  *  lkarea.c contains the following functions:
27  *      VOID    lnkarea()
28  *      VOID    lnksect()
29  *      VOID    lkparea()
30  *      VOID    newarea()
31  *
32  *  lkarea.c contains no global variables.
33  */
34
35 /*)Function VOID    newarea()
36  *
37  *  The function newarea() creates and/or modifies area
38  *  and areax structures for each A directive read from
39  *  the .rel file(s).  The function lkparea() is called
40  *  to find tha area structure associated with this name.
41  *  If the area does not yet exist then a new area
42  *  structure is created and linked to any existing
43  *  linked area structures. The area flags are copied
44  *  into the area flag variable.  For each occurence of
45  *  an A directive an areax structure is created and
46  *  linked to the areax structures associated with this
47  *  area.  The size of this area section is placed into
48  *  the areax structure.  The flag value for all subsequent
49  *  area definitions for the same area are compared and
50  *  flagged as an error if they are not identical.
51  *  The areax structure created for every occurence of
52  *  an A directive is loaded with a pointer to the base
53  *  area structure and a pointer to the associated
54  *  head structure.  And finally, a pointer to this
55  *  areax structure is loaded into the list of areax
56  *  structures in the head structure.  Refer to lkdata.c
57  *  for details of the structures and their linkage.
58  *
59  *  local variables:
60  *      areax **halp        pointer to an array of pointers
61  *      int     i           counter, loop variable, value
62  *      char    id[]        id string
63  *      int     narea       number of areas in this head structure
64  *      areax * taxp        pointer to an areax structure
65  *                          to areax structures
66  *
67  *  global variables:
68  *      area    *ap         Pointer to the current
69  *                          area structure
70  *      areax   *axp        Pointer to the current
71  *                          areax structure
72  *      head    *hp         Pointer to the current
73  *                          head structure
74  *      int     lkerr       error flag
75  *
76  *  functions called:
77  *      Addr_T  eval()      lkeval.c
78  *      VOID    exit()      c_library
79  *      int     fprintf()   c_library
80  *      VOID    getid()     lklex.c
81  *      VOID    lkparea()   lkarea.c
82  *      VOID    skip()      lklex.c
83  *
84  *  side effects:
85  *      The area and areax structures are created and
86  *      linked with the appropriate head structures.
87  *      Failure to allocate area or areax structure
88  *      space will terminate the linker.  Other internal
89  *      errors most likely caused by corrupted .rel
90  *      files will also terminate the linker.
91  */
92
93 /*
94  * Create an area entry.
95  *
96  * A xxxxxx size nnnn flags mm
97  *   |           |          |
98  *   |           |          `--  ap->a_flag
99  *   |           `------------- axp->a_size
100  *   `-------------------------  ap->a_id
101  *
102  */
103 VOID
104 newarea()
105 {
106     register int i, narea;
107     struct areax *taxp;
108     struct areax **halp;
109     char id[NCPS];
110
111     /*
112      * Create Area entry
113      */
114     getid(id, -1);
115     lkparea(id);
116     /*
117      * Evaluate area size
118      */
119     skip(-1);
120     axp->a_size = eval();
121     /*
122      * Evaluate flags
123      */
124     skip(-1);
125     i = 0;
126     taxp = ap->a_axp;
127     while (taxp->a_axp) {
128         ++i;
129         taxp = taxp->a_axp;
130     }
131     if (i == 0) {
132         ap->a_flag = eval();
133     } else {
134         i = eval();
135 /*      if (i && (ap->a_flag != i)) { */
136 /*          fprintf(stderr, "Conflicting flags in area %8s\n", id); */
137 /*          lkerr++; */
138 /*      } */
139     }
140     /*
141      * Place pointer in header area list
142      */
143     if (headp == NULL) {
144         fprintf(stderr, "No header defined\n");
145         lkexit(1);
146     }
147     narea = hp->h_narea;
148     halp = hp->a_list;
149     for (i=0; i < narea ;++i) {
150         if (halp[i] == NULL) {
151             halp[i] = taxp;
152             return;
153         }
154     }
155     fprintf(stderr, "Header area list overflow\n");
156     lkexit(1);
157 }
158
159 /*)Function VOID    lkparea(id)
160  *
161  *      char *  id      pointer to the area name string
162  *
163  *  The function lkparea() searches the linked area structures
164  *  for a name match.  If the name is not found then an area
165  *  structure is created.  An areax structure is created and
166  *  appended to the areax structures linked to the area structure.
167  *  The associated base area and head structure pointers are
168  *  loaded into the areax structure.
169  *
170  *  local variables:
171  *      area *  tap         pointer to an area structure
172  *      areax * taxp        pointer to an areax structure
173  *
174  *  global variables:
175  *      area    *ap         Pointer to the current
176  *                          area structure
177  *      area    *areap      The pointer to the first
178  *                          area structure of a linked list
179  *      areax   *axp        Pointer to the current
180  *                          areax structure
181  *
182  *  functions called:
183  *      VOID *  new()       lksym()
184  *      char *  strcpy()    c_library
185  *      int     symeq()     lksym.c
186  *
187  *  side effects:
188  *      Area and/or areax structures are created.
189  *      Failure to allocate space for created structures
190  *      will terminate the linker.
191  */
192
193 VOID
194 lkparea(char *id)
195 {
196     register struct area *tap;
197     register struct areax *taxp;
198
199     ap = areap;
200     axp = (struct areax *) new (sizeof(struct areax));
201     while (ap) {
202         if (symeq(id, ap->a_id)) {
203             taxp = ap->a_axp;
204             while (taxp->a_axp)
205                 taxp = taxp->a_axp;
206             taxp->a_axp = axp;
207             axp->a_bap = ap;
208             axp->a_bhp = hp;
209             return;
210         }
211         ap = ap->a_ap;
212     }
213     ap = (struct area *) new (sizeof(struct area));
214     if (areap == NULL) {
215         areap = ap;
216     } else {
217         tap = areap;
218         while (tap->a_ap)
219             tap = tap->a_ap;
220         tap->a_ap = ap;
221     }
222     ap->a_axp = axp;
223     axp->a_bap = ap;
224     axp->a_bhp = hp;
225     strncpy(ap->a_id, id, NCPS);
226     ap->a_addr = 0;
227 }
228
229 /*)Function VOID    lnkarea()
230  *
231  *  The function lnkarea() resolves all area addresses.
232  *  The function evaluates each area structure (and all
233  *  the associated areax structures) in sequence.  The
234  *  linking process supports four (4) possible area types:
235  *
236  *  ABS/OVR -   All sections (each individual areax
237  *          section) starts at the identical base
238  *          area address overlaying all other
239  *          areax sections for this area.  The
240  *          size of the area is largest of the area
241  *          sections.
242  *
243  *  ABS/CON -   All sections (each individual areax
244  *          section) are concatenated with the
245  *          first section starting at the base
246  *          area address.  The size of the area
247  *          is the sum of the section sizes.
248  *
249  *  NOTE:   Multiple absolute (ABS) areas are
250  *          never concatenated with each other,
251  *          thus absolute area A and absolute area
252  *          B will overlay each other if they begin
253  *          at the same location (the default is
254  *          always address 0 for absolute areas).
255  *
256  *  REL/OVR -   All sections (each individual areax
257  *          section) starts at the identical base
258  *          area address overlaying all other
259  *          areax sections for this area.  The
260  *          size of the area is largest of the area
261  *          sections.
262  *
263  *  REL/CON -   All sections (each individual areax
264  *          section) are concatenated with the
265  *          first section starting at the base
266  *          area address.  The size of the area
267  *          is the sum of the section sizes.
268  *
269  *  NOTE:   Relocatable (REL) areas are always concatenated
270  *          with each other, thus relocatable area B
271  *          (defined after area A) will follow
272  *          relocatable area A independent of the
273  *          starting address of area A.  Within a
274  *          specific area each areax section may be
275  *          overlayed or concatenated with other
276  *          areax sections.
277  *
278  *
279  *  If a base address for an area is specified then the
280  *  area will start at that address.  Any relocatable
281  *  areas defined subsequently will be concatenated to the
282  *  previous relocatable area if it does not have a base
283  *  address specified.
284  *
285  *  The names s_<areaname> and l_<areaname> are created to
286  *  define the starting address and length of each area.
287  *
288  *  local variables:
289  *      Addr_T  rloc        ;current relocation address
290  *      char    temp[]      ;temporary string
291  *      struct symbol   *sp ;symbol structure
292  *
293  *  global variables:
294  *      area    *ap         Pointer to the current
295  *                          area structure
296  *      area    *areap      The pointer to the first
297  *                          area structure of a linked list
298  *
299  *  functions called:
300  *      int     fprintf()   c_library
301  *      VOID    lnksect()   lkarea.c
302  *      symbol *lkpsym()    lksym.c
303  *      char *  strncpy()   c_library
304  *      int     symeq()     lksym.c
305  *
306  *  side effects:
307  *      All area and areax addresses and sizes are
308  *      determined and saved in their respective
309  *      structures.
310  */
311
312 /*
313  * Resolve all area addresses.
314  */
315 VOID
316 lnkarea()
317 {
318     Addr_T rloc[4];
319     int  locIndex;
320     char temp[NCPS];
321     struct sym *sp;
322     /*JCF: used to save the REG_BANK_[0-3] and SBIT_BYTES area pointers*/
323     struct area *ta[5];
324     int j;
325
326     rloc[0] = rloc[1] = rloc[2] = rloc[3] = 0;
327     ap = areap;
328     while (ap) {
329         if (ap->a_flag&A_ABS) {
330             /*
331              * Absolute sections
332              */
333             lnksect(ap);
334         } else {
335             /* Determine memory space */
336             locIndex = 0;
337             if (ap->a_flag & A_CODE) {
338                 locIndex = 1;
339             }
340             if (ap->a_flag & A_XDATA) {
341                 locIndex = 2;
342             }
343             if (ap->a_flag & A_BIT) {
344                 locIndex = 3;
345             }
346             /*
347              * Relocatable sections
348              */
349             if (ap->a_type == 0) {  /* JLH */
350                 ap->a_addr = rloc[ locIndex ];
351                 ap->a_type = 1;
352             }
353             lnksect(ap);
354             rloc[ locIndex ] = ap->a_addr + ap->a_size;
355         }
356
357         /*
358          * Create symbols called:
359          *  s_<areaname>    the start address of the area
360          *  l_<areaname>    the length of the area
361          */
362
363         if (! symeq(ap->a_id, _abs_)) {
364             strncpy(temp+2,ap->a_id,NCPS-2);
365             *(temp+1) = '_';
366
367             *temp = 's';
368             sp = lkpsym(temp, 1);
369             sp->s_addr = ap->a_addr ;
370             /* sp->s_axp = ap->a_axp;  JLH: was NULL; */
371             sp->s_type |= S_DEF;
372
373             *temp = 'l';
374             sp = lkpsym(temp, 1);
375             sp->s_addr = ap->a_size;
376             sp->s_axp = NULL;
377             sp->s_type |= S_DEF;
378
379         }
380
381         /*JCF: Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
382         to compute the byte size of BSEG_BYTES: */
383         if (!strcmp(ap->a_id, "BSEG")) {
384             ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/
385         }
386         else if (!strcmp(ap->a_id, "REG_BANK_0")) ta[0]=ap;
387         else if (!strcmp(ap->a_id, "REG_BANK_1")) ta[1]=ap;
388         else if (!strcmp(ap->a_id, "REG_BANK_2")) ta[2]=ap;
389         else if (!strcmp(ap->a_id, "REG_BANK_3")) ta[3]=ap;
390         else if (!strcmp(ap->a_id, "BSEG_BYTES"))
391         {
392             ta[4]=ap;
393             for(j=4; j>1; j--)
394             {
395                 /*If upper register banks are not used roll back the relocation counter*/
396                 if ( (ta[j]->a_size==0) && (ta[j-1]->a_size==0) )
397                 {
398                     rloc[0]-=8;
399                 }
400                 else break;
401             }
402         }
403         ap = ap->a_ap;
404     }
405 }
406
407 /*)Function VOID    lnksect()
408  *
409  *      area *  tap         pointer to an area structure
410  *
411  *  The function lnksect() is the function called by
412  *  lnkarea() to resolve the areax addresses.  Refer
413  *  to the function lnkarea() for more detail. Pageing
414  *  boundary and length errors will be reported by this
415  *  function.
416  *
417  *  local variables:
418  *      Addr_T  size        size of area
419  *      Addr_T  addr        address of area
420  *      areax * taxp        pointer to an areax structure
421  *
422  *  global variables:
423  *      int     lkerr       error flag
424  *
425  *  functions called:
426  *      none
427  *
428  *  side effects:
429  *      All area and areax addresses and sizes area determined
430  *      and linked into the structures.
431  */
432
433 VOID
434 lnksect(register struct area *tap)
435 {
436     register Addr_T size, addr;
437     register struct areax *taxp;
438
439     size = 0;
440     addr = tap->a_addr;
441 #if 0
442     if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
443         fprintf(stderr,
444         "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
445         lkerr++;
446     }
447 #endif
448     taxp = tap->a_axp;
449     if (tap->a_flag&A_OVR) {
450         /*
451          * Overlayed sections
452          */
453         while (taxp) {
454             taxp->a_addr = addr;
455             if (taxp->a_size > size)
456                 size = taxp->a_size;
457             taxp = taxp->a_axp;
458         }
459     } else {
460         /*
461          * Concatenated sections
462          */
463         while (taxp) {
464             taxp->a_addr = addr;
465             addr += taxp->a_size;
466             size += taxp->a_size;
467             taxp = taxp->a_axp;
468         }
469     }
470     tap->a_size = size;
471     if ((tap->a_flag&A_PAG) && (size > 256)) {
472         fprintf(stderr,
473         "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
474         lkerr++;
475     }
476     if ((tap->a_flag&A_PAG) && (tap->a_size) &&
477         ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
478     {
479         fprintf(stderr,
480         "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
481         lkerr++;
482     }
483 }
484
485 void lnksect2 (struct area *tap, int rloc);
486 char idatamap[256];
487
488 /*Modified version of the functions for packing variables in internal data memory*/
489 VOID lnkarea2 (void)
490 {
491     Addr_T rloc[4]={0, 0, 0, 0};
492     int  locIndex;
493     char temp[NCPS];
494     struct sym *sp;
495     int j;
496     struct area *dseg_ap=NULL;
497     struct sym *sp_dseg_s=NULL, *sp_dseg_l=NULL;
498
499     for(j=0; j<256; j++) idatamap[j]=' ';
500
501     ap = areap;
502     while (ap)
503     {
504         /* Determine memory space */
505              if (ap->a_flag & A_CODE)  locIndex = 1;
506         else if (ap->a_flag & A_XDATA) locIndex = 2;
507         else if (ap->a_flag & A_BIT)   locIndex = 3;
508         else locIndex = 0;
509
510         if (ap->a_flag&A_ABS) /* Absolute sections */
511         {
512             lnksect2(ap, locIndex);
513         }
514         else /* Relocatable sections */
515         {
516             if (ap->a_type == 0)
517             {
518                 ap->a_addr=rloc[locIndex];
519                 ap->a_type=1;
520             }
521
522             lnksect2(ap, locIndex);
523             rloc[locIndex] = ap->a_addr + ap->a_size;
524         }
525
526         /*
527          * Create symbols called:
528          *  s_<areaname>    the start address of the area
529          *  l_<areaname>    the length of the area
530          */
531
532         if (! symeq(ap->a_id, _abs_))
533         {
534             strncpy(temp+2,ap->a_id,NCPS-2);
535             *(temp+1) = '_';
536
537             *temp = 's';
538             sp = lkpsym(temp, 1);
539             sp->s_addr = ap->a_addr ;
540             sp->s_type |= S_DEF;
541             if (!strcmp(ap->a_id, "DSEG")) sp_dseg_s=sp;
542
543             *temp = 'l';
544             sp = lkpsym(temp, 1);
545             sp->s_addr = ap->a_size;
546             sp->s_axp = NULL;
547             sp->s_type |= S_DEF;
548             if (!strcmp(ap->a_id, "DSEG")) sp_dseg_l=sp;
549         }
550
551         /*Since area BSEG is defined just before BSEG_BYTES, use the bit size of BSEG
552         to compute the byte size of BSEG_BYTES: */
553         if (!strcmp(ap->a_id, "BSEG"))
554         {
555             ap->a_ap->a_axp->a_size=(ap->a_addr/8)+((ap->a_size+7)/8); /*Bits to bytes*/
556         }
557         else if (!strcmp(ap->a_id, "DSEG"))
558         {
559             dseg_ap=ap; /*Need it later to set its correct size*/
560         }
561         ap = ap->a_ap;
562     }
563
564     /*Compute the size of DSEG*/
565     if(dseg_ap!=NULL)
566     {
567         dseg_ap->a_addr=0;
568         dseg_ap->a_size=0;
569         for(j=0; j<0x80; j++) if(idatamap[j]!=' ') dseg_ap->a_size++;
570     }
571     if(sp_dseg_s!=NULL) sp_dseg_s->s_addr=0;
572     if(sp_dseg_l!=NULL) sp_dseg_l->s_addr=dseg_ap->a_size;
573
574 #if 0
575     /*Print the memory map*/
576     fprintf(stderr, "Internal RAM layout:\n"
577            "      0 1 2 3 4 5 6 7 8 9 A B C D E F");
578     for(j=0; j<256; j++)
579     {
580         if(j%16==0) fprintf(stderr, "\n0x%02x:|", j);
581         fprintf(stderr, "%c|", idatamap[j]);
582     }
583     fprintf(stderr, "\n0-3:Reg Banks, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack\n");
584 #endif
585 }
586
587 void lnksect2 (struct area *tap, int rloc)
588 {
589     register Addr_T size, addr;
590     register struct areax *taxp;
591     int j, k, ramlimit;
592     char fchar, dchar='a';
593     char ErrMsg[]="?ASlink-Error-Could not get %d consecutive byte%s"
594                   " in internal RAM for area %s.\n";
595
596     tap->a_unaloc=0;
597
598     /*Notice that only ISEG and SSEG can be in the indirectly addressable internal RAM*/
599     if( (!strcmp(tap->a_id, "ISEG")) || (!strcmp(tap->a_id, "SSEG")) )
600     {
601         if((iram_size<=0)||(iram_size>0x100))
602             ramlimit=0x100;
603         else
604             ramlimit=iram_size;
605     }
606     else
607     {
608         if((iram_size<=0)||(iram_size>0x80))
609             ramlimit=0x80;
610         else
611             ramlimit=iram_size;
612     }
613
614     size = 0;
615     addr = tap->a_addr;
616 #if 0
617     if ((tap->a_flag&A_PAG) && (addr & 0xFF))
618     {
619         fprintf(stderr,
620           "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
621         lkerr++;
622     }
623 #endif
624     taxp = tap->a_axp;
625
626     /*Use a letter to identify each area in the internal RAM layout map*/
627     if(rloc==0)
628     {
629         /**/ if(!strcmp(tap->a_id, "DSEG"))
630             fchar='D'; /*It will be converted to letters 'a' to 'z' later for each areax*/
631         else if(!strcmp(tap->a_id, "ISEG"))
632             fchar='I';
633         else if(!strcmp(tap->a_id, "SSEG"))
634             fchar='S';
635         else if(!strcmp(tap->a_id, "OSEG"))
636             fchar='Q';
637         else if(!strcmp(tap->a_id, "REG_BANK_0"))
638             fchar='0';
639         else if(!strcmp(tap->a_id, "REG_BANK_1"))
640             fchar='1';
641         else if(!strcmp(tap->a_id, "REG_BANK_2"))
642             fchar='2';
643         else if(!strcmp(tap->a_id, "REG_BANK_3"))
644             fchar='3';
645         else if(!strcmp(tap->a_id, "BSEG_BYTES"))
646             fchar='B';
647         else
648             fchar=' ';/*???*/
649     }
650     else
651     {
652         fchar=' ';
653     }
654
655     if (tap->a_flag&A_OVR) /* Overlayed sections */
656     {
657         while (taxp)
658         {
659             if ( (fchar=='0')||(fchar=='1')||(fchar=='2')||(fchar=='3') ) /*Reg banks*/
660             {
661                 addr=(fchar-'0')*8;
662                 taxp->a_addr=addr;
663                 size=taxp->a_size;
664                 for(j=addr; (j<(int)(addr+taxp->a_size)) && (j<ramlimit); j++)
665                     idatamap[j]=fchar;
666             }
667             else if( (fchar=='S') || (fchar=='Q') ) /*Overlay and stack in internal RAM*/
668             {
669                 /*Find the size of the space currently used for this areax overlay*/
670                 for(j=0, size=0; j<ramlimit; j++)
671                     if(idatamap[j]==fchar) size++;
672
673                 if( (fchar=='S') && (stacksize==0) )
674                 {
675                    /*Search for the largest space available and use it for stack*/
676                     for(j=0, k=0, taxp->a_size=0; j<ramlimit; j++)
677                     {
678                         if(idatamap[j]==' ')
679                         {
680                             if((++k)>(int)taxp->a_size) taxp->a_size=k;
681                         }
682                         else
683                         {
684                             k=0;
685                         }
686                     }
687                     stacksize=taxp->a_size;
688                 }
689
690                 /*If more space required, release the previously allocated areax in
691                 internal RAM and search for a bigger one*/
692                 if((int)taxp->a_size>size)
693                 {
694                     size=(int)taxp->a_size;
695
696                     for(j=0; j<ramlimit; j++)
697                         if(idatamap[j]==fchar) idatamap[j]=' ';
698
699                     /*Search for a space large enough in data memory for this overlay areax*/
700                     for(j=0, k=0; j<ramlimit; j++)
701                     {
702                         if(idatamap[j]==' ')
703                             k++;
704                         else
705                             k=0;
706                         if(k==(int)taxp->a_size) break;
707                     }
708
709                     if(k==(int)taxp->a_size)
710                     {
711                         taxp->a_addr = j-k+1;
712                         if(addr<(unsigned int)ramlimit)
713                         {
714                             for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--);
715                             if(j>=0) addr=j+1;
716                         }
717                     }
718
719                     /*Mark the memory used for overlay*/
720                     if(k==(int)taxp->a_size)
721                     {
722                         for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
723                             idatamap[j]=fchar;
724
725                         /*Set the new size of the data memory area*/
726                         size=ramlimit-addr;
727                     }
728                     else /*Couldn't find a chunk big enough: report the problem.*/
729                     {
730                         tap->a_unaloc=taxp->a_size;
731                         fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
732                         lkerr++;
733                     }
734                }
735
736                 for(j=0; j<ramlimit; j++)
737                 {
738                     if (idatamap[j]==fchar)
739                     {
740                         addr=j;
741                         tap->a_addr=addr;
742                         taxp->a_addr=addr;
743                         break;
744                     }
745                 }
746             }
747             else /*Overlay areas not in internal ram*/
748             {
749                 taxp->a_addr = addr;
750                 if (taxp->a_size > size) size = taxp->a_size;
751             }
752             taxp = taxp->a_axp;
753         }
754     }
755     else /* Concatenated sections */
756     {
757         while (taxp)
758         {
759             if( (fchar=='D') || (fchar=='I') )
760             {
761                 if(taxp->a_size)
762                 {
763                     /*Search for a space large enough in internal RAM for this areax*/
764                     for(j=0, k=0; j<ramlimit; j++)
765                     {
766                         if(idatamap[j]==' ')
767                             k++;
768                         else
769                             k=0;
770                         if(k==(int)taxp->a_size) break;
771                     }
772
773                     if(k==(int)taxp->a_size)
774                     {
775                         taxp->a_addr = j-k+1;
776                         if(addr<(unsigned int)ramlimit)
777                         {
778                             for(j=ramlimit-1; (j>=0)&&(idatamap[j]==' '); j--);
779                             if(j>=0) addr=j+1;
780                             size=ramlimit-addr;
781                         }
782
783                         for(j=taxp->a_addr; (j<(int)(taxp->a_addr+taxp->a_size)) && (j<ramlimit); j++)
784                             idatamap[j]=(fchar=='D')?dchar:fchar;
785                         if((taxp->a_size>0)&&(fchar=='D'))dchar++;
786                         if((dchar<'a')||(dchar>'z')) dchar='D'; /*Ran out of letters?*/
787                     }
788                     else /*We are in trouble, there is not enough memory for an areax chunk*/
789                     {
790                         taxp->a_addr = addr;
791                         addr += taxp->a_size;
792                         size += taxp->a_size;
793                         tap->a_unaloc+=taxp->a_size;
794                         fprintf(stderr, ErrMsg, taxp->a_size, taxp->a_size>1?"s":"", tap->a_id);
795                         lkerr++;
796                     }
797                }
798                taxp = taxp->a_axp;
799             }
800             else if(fchar=='B')
801             {
802                 if(taxp->a_size!=0)
803                 {
804                     for(j=0x20+taxp->a_addr; j<((int)(0x20+taxp->a_addr+taxp->a_size)); j++)
805                         idatamap[j]=fchar;
806                 }
807
808                 taxp->a_addr = addr;
809                 addr += taxp->a_size;
810                 size += taxp->a_size;
811                 taxp = taxp->a_axp;
812             }
813             else /*For concatenated BIT, CODE, and XRAM areax's*/
814             {
815                 if(!strcmp(tap->a_id, "XSTK") && (taxp->a_size == 1))
816                 {
817                     taxp->a_size = 256-(addr & 0xFF);
818                 }
819                 taxp->a_addr = addr;
820                 addr += taxp->a_size;
821                 size += taxp->a_size;
822                 taxp = taxp->a_axp;
823             }
824         }
825     }
826     tap->a_size = size;
827
828     if ((tap->a_flag&A_PAG) && (size > 256))
829     {
830         fprintf(stderr,
831         "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);
832         lkerr++;
833     }
834     if ((tap->a_flag&A_PAG) && (tap->a_size) &&
835         ((tap->a_addr & 0xFFFFFF00) != ((addr-1) & 0xFFFFFF00)))
836     {
837         fprintf(stderr,
838         "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
839         lkerr++;
840     }
841 }