+/*
+ * These macros are used to speak ``offsets'' to the outside world,
+ * so that we can use the other source files for sdb essentially
+ * unchanged, even though they believe that we work with symbol
+ * table offsets, and we really have the whole symbol table in
+ * core and would prefer to just work with pointers into it.
+ */
+#define sptooff(sp) (ststart + (int)(sp) - (int)(symtab))
+#define offtosp(off) (&symtab[((off) - ststart) / sizeof (struct nlist))
+
+/*
+ * Initialize the file and procedure tables.
+ *
+ * This routine rummages through the symbol table and builds tables
+ * of the files and procedures referenced there, sorting the latter
+ * table into address order. These tables are used in the other
+ * routines defined here.
+ *
+ * NB:
+ *
+ * In this version of sdb we could well dispense with most of the
+ * fields of these tables, since we have the symbol table in core,
+ * but for compatibility for the time being we duplicate the information
+ * so older code in other sdb files will work unchanged.
+ */
+initfp()
+{
+ register struct nlist *sp;
+ register struct proct *procp;
+ register struct filet *filep;
+ struct stat stb;
+ int nfile, nproc;
+ int class;
+ extern int compar(); /* Sort routine for procedure table */
+
+ firstdata = MAXPOS;
+ /*
+ * Since the symbol table is in core, we can afford
+ * two passes over it to avoid messy allocation strategies
+ * for these tables, who sizes are as yet unknown.
+ */
+ nfile = 0;
+ nproc = 0;
+ for (sp = symtab; sp < esymtab; sp++) switch (sp->n_type & STABMASK) {
+
+ case N_SO:
+ case N_SOL:
+ nfile++;
+ continue;
+ case N_TEXT:
+ if (sp->n_name[0] == '_')
+ nfile++;
+ continue;
+ case N_FUN:
+ case N_ENTRY:
+ nfile++;
+ continue;
+ }
+ files = calloc(nfile+1, sizeof (struct filet));
+ procs = calloc(nfile+1, sizeof (struct filet));
+ if (files == 0 || procs == 0) {
+ printf("Couldn't get space for file/procedure tables\n");
+ exit(1);
+ }
+ if (nfiles == 0)
+ printf("Warning: `%s' not compiled with -g\n", symfil);
+ procp = procs;
+ filep = files;
+ for (sp = symtab; sp < esymtab; sp++) {
+ class = sp->n_type & STABMASK;
+ switch (class) {
+
+ case N_SO:
+ case N_SOL:
+ filep->faddr = sp->n_value;
+ filep->lineflag = (class == N_SOL);
+ filep->stf_offset = sptooff(sp);
+ filep->sfilename = sp->n_name;
+ strcpy(fp, filep->sfilename);
+ if (stat(filework, &stb) == -1)
+ printf("Warning: `%s' not found\n",
+ filep->sfilename);
+ else if (stb.st_mtime > symtime)
+ printf("Warning: `%s' newer than `%s'\n",
+ filep->sfilename, symfil);
+ filep++;
+ break;
+
+ case N_TEXT:
+ if (stentry.n_name[0] != '_')
+ break;
+ case N_FUN:
+ case N_ENTRY:
+ procp->pname = sp->n_name;
+ procp->paddr = sp->n_value;
+ procp->st_offset = sptooff(sp);
+ if (class != N_TEXT) {
+ procp->sfptr = filep - 1;
+ procp->lineno = so->n_desc;
+ } else {
+ procp->sfptr = badfile;
+ procp->lineno = 0;
+ }
+ procp->entrypt = class == N_ENTRY;
+ procp++;
+ break;
+ }
+ if (sp->n_type & N_EXT) {
+ if (!extstart)
+ extstart = sp;
+ /* THIS LOOKS WRONG !!! SHOULD BE (x || y) && z ??? */
+ if (sp->n_type == (N_DATA+N_EXT) ||
+ sp->n_type == (N_BSS+N_EXT) ||
+ sp->n_value < firstdata)
+ firstdata = sp->n_value;
+ }
+ }
+ if (filep != &files[nfile] || procp != &procs[nproc]) {
+ printf("initfp botch - tell someone\n");
+ exit(1);
+ }
+ /*
+ * Now have the file and procedure tables.
+ * Sort the procedure table, and initialize the boundary
+ * elements of the tables.
+ */
+ qsort(procs, procp-procs, sizeof procs[0], compar);
+ badproc = procp;
+ badfile = filep;
+ badproc->st_offset = esymtab;
+ badproc->sfptr = badfile;
+ badproc->pname = badfile->sfilename = "";
+ setcur(1);
+}