ref: 1ce079ecedd0b95c5c367572b5872a78d2a309ba
dir: /src/cmd/ld/section.c/
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <scc/mach.h>
#include <scc/scc.h>
#include "ld.h"
#define NR_SECTION 32
/*
 * struct sectab has a Section as first field because
 * the code is going to cast from the sections to the tab.
 */
struct sectab {
	Section sec;
	FILE *tmpfp;
	struct sectab *hash;
	struct sectab *next, *prev;
};
static struct sectab *sectab[NR_SECTION];
static struct sectab secs = {.next = &secs, .prev = &secs};
static Section *
linksec(struct sectab *lst, Section *sec)
{
	struct sectab *sp = (struct sectab *) sec;
	sp->next = lst;
	sp->prev = lst->prev;
	lst->prev->next = sp;
	lst->prev = sp;
	return sec;
}
Section *
lookupsec(char *name)
{
	unsigned h;
	size_t len;
	char *s;
	Section *sec;
	struct sectab *sp;
	h = genhash(name) % NR_SECTION;
	for (sp = sectab[h]; sp; sp = sp->hash) {
		if (!strcmp(name, sp->sec.name))
			return &sp->sec;
	}
	len = strlen(name) + 1;
	s = malloc(len);
	sp = malloc(sizeof(*sp));
	if (!s || !sp) {
		error(strerror(errno));
		exit(EXIT_FAILURE);
	}
	sec = &sp->sec;
	sec->name = memcpy(s, name, len);
	sec->type = 'U';
	sec->base = 0;
	sec->size = 0;
	sec->align = 0;
	sec->index = 0;
	sec->flags = 0;
	sp->tmpfp;
	sp->hash = sectab[h];
	sectab[h] = sp;
	return linksec(&secs, sec);
}
void
copy(Obj *obj, Section *osec, Section *sec)
{
	struct sectab *sp = (struct sectab *) sec;
	if (sec->size > ULLONG_MAX - osec->size) {
		error("%s: section too long", sec->name);
		return;
	}
	if (!sp->tmpfp && (sp->tmpfp = tmpfile()) == NULL) {
		error(strerror(errno));
		exit(EXIT_FAILURE);
	}
/*
	if (mapsec(obj, osec->index, sp->tmpfp) < 0) {
		error(strerror(errno));
		return;
	}
*/
	sec->size += osec->size;
}
void
grow(Section *sec, int nbytes)
{
	struct sectab *sp = (struct sectab *) sec;
	if (sec->size > ULLONG_MAX - nbytes) {
		error("%s: section too long", sec->name);
		return;
	}
	if (!sp->tmpfp && (sp->tmpfp = tmpfile()) == NULL) {
		error(strerror(errno));
		exit(EXIT_FAILURE);
	}
	while (nbytes-- > 0)
		putc(0, sp->tmpfp);
	sec->size += nbytes;
}
#ifndef NDEBUG
void
debugsec(void)
{
	struct sectab **spp, *sp;
	Section *sec;
	fputs("Sections:\n", stderr);
	for (spp = sectab; spp < §ab[NR_SECTION]; spp++) {
		for (sp = *spp; sp; sp = sp->hash) {
			sec = &sp->sec;
			fprintf(stderr,
			        "sec: %s - %c (%#llx,%#lx)\n",
			        sec->name,
			        sec->type,
			        sec->base,
			        sec->size);
		}
	}
}
#endif