/* lkarea.c */ /* * (C) Copyright 1989 * All Rights Reserved * * Alan R. Baldwin * 721 Berkeley St. * Kent, Ohio 44240 */ #include #include "aslink.h" /* * Create an area entry. * * A xxxxxx size nnnn flags mm * | | | * | | `-- ap->a_flag * | `------------- axp->a_size * `------------------------- ap->a_id * */ VOID newarea() { register i, narea; struct areax *taxp; struct areax **halp; char id[NCPS]; /* * Create Area entry */ getid(id, -1); lkparea(id); /* * Evaluate area size */ skip(-1); axp->a_size = eval(); /* * Evaluate flags */ skip(-1); i = 0; taxp = ap->a_axp; while (taxp->a_axp) { ++i; taxp = taxp->a_axp; } if (i == 0) { ap->a_flag = eval(); } else { i = eval(); if (i && (ap->a_flag != i)) fprintf(stderr, "Conflicting flags in area %.8s\n", id); } /* * Place pointer in header area list */ if (headp == NULL) { fprintf(stderr, "No header defined\n"); exit(1); } narea = hp->h_narea; halp = (struct areax **) hp->a_list; for (i=0; i < narea ;++i) { if (halp[i] == NULL) { halp[i] = taxp; return; } } fprintf(stderr, "Header area list overflow\n"); exit(1); } /* * Lookup the area `id'. * If it is not found create it. * Then append an area extension. */ VOID lkparea(id) char *id; { register struct area *tap; register struct areax *taxp; ap = areap; axp = (struct areax *) new (sizeof(struct areax)); while (ap) { if (symeq(id, ap->a_id)) { taxp = ap->a_axp; while (taxp->a_axp) taxp = taxp->a_axp; taxp->a_axp = axp; return; } ap = ap->a_ap; } ap = (struct area *) new (sizeof(struct area)); if (areap == NULL) { areap = ap; } else { tap = areap; while (tap->a_ap) tap = tap->a_ap; tap->a_ap = ap; } ap->a_axp = axp; strncpy(ap->a_id, id, NCPS); } /* * Resolve all area addresses. */ VOID lnkarea() { register rloc; rloc = 0; ap = areap; while (ap) { if (ap->a_flag&A_ABS) { /* * Absolute sections */ lnksect(ap); } else { /* * Relocatable sections */ if (ap->a_addr == 0) ap->a_addr = rloc; lnksect(ap); rloc = ap->a_addr + ap->a_size; } ap = ap->a_ap; } } /* * Resolve section addresses within an area. */ VOID lnksect(tap) register struct area *tap; { register addr_t size, addr; register struct areax *taxp; size = 0; addr = tap->a_addr; taxp = tap->a_axp; if (tap->a_flag&A_OVR) { /* * Overlayed sections */ while (taxp) { taxp->a_addr = addr; if (taxp->a_size > size) size = taxp->a_size; taxp = taxp->a_axp; } } else { /* * Concatenated sections */ while (taxp) { taxp->a_addr = addr; addr += taxp->a_size; size += taxp->a_size; taxp = taxp->a_axp; } } tap->a_size = size; }