/* * nm [-1bcdfgruv] file */ #include #define NSY 500 #define NPS 20 #define AB0 0127400 #define AB1 0003243 #define AB2 0127401 #define AB3 0007624 #define RBMAX 128 #define GSD 1 #define G_CSN 1 #define G_ISN 2 #define G_GSN 4 #define G_PSN 5 #define G_DEF 010 typedef unsigned addr_t; typedef unsigned r50_t; struct rb { int type; char data[RBMAX]; }; struct gsde { r50_t g_name[2]; char g_flag; char g_type; addr_t g_value; }; struct sym { char s_name[6]; char s_flag; char s_type; int s_ps; addr_t s_value; }; struct pst { r50_t p_name[2]; addr_t p_size; }; struct rb rb; struct sym sym[NSY]; struct pst pst[NPS]; char *rbe; int nsy; int nps; int cps; char *fn; FILE *fp; int oflag; int bflag; int cflag; int dflag; int fflag; int gflag; int rflag; int uflag; int vflag; main(argc, argv) char *argv[]; { register int i, c; register char *p; fn = NULL; for(i=1; ig_type; if(t==G_CSN || t==G_PSN) cps = lookup(p); else if(t==G_GSN || t==G_ISN) { if(gflag && t==G_ISN) continue; if(!uflag && (p->g_flag&G_DEF)==0) continue; convert(ab, p->g_name); if(!cflag && csym(ab)) continue; if(!bflag && bsym(ab)) continue; if(nsy >= NSY) error("Too many symbols!\n"); sp = &sym[nsy++]; copy(sp->s_name, ab, 6); sp->s_type = t; sp->s_flag = p->g_flag; sp->s_ps = cps; sp->s_value = p->g_value; } } } while(getrec()); } /* * Read a record from the * file into the record * buffer. * True return if the read * was ok. * Set up rbe to point just * beyond the record. */ getrec() { register int n; n = fget(&rb, sizeof(rb), fp); if(feof(fp)) return(0); rbe = &rb; rbe += n; return(1); } /* * Convert 6 radix 50 characters * to ascii. * Map `$' to `_' to agree * with the assembler. */ convert(a, r) register char *a; r50_t *r; { register int n; r50toa(a, r, 2); n = 6; do { if(*a == '$') *a = '_'; ++a; } while(--n); } /* * Test if a 6 character symbol * is a C internal symbol. * These symbols are all numeric * except for a leading dot. */ csym(p) register char *p; { register int c, n; if(*p++ != '.') return(0); n = 5; do { c = *p++; if(c!=' ' && (c<'0' || c>'9')) return(0); } while(--n); return(1); } /* * Test if a 6 character symbol * is an RSX control block * symbol. * These symbols have the form * x.xxxx xx.xxx x_xxxx or xx_xxx */ bsym(p) register char *p; { if(p[1]=='.' || p[1]=='_' || p[2]=='.' || p[2]=='_') return(1); return(0); } /* * Lookup a psection. * Make new entry if new psection. * In any casee return the * psection number. */ lookup(g) register struct gsde *g; { register struct pst *p; register int i; for(i=0; ig_name)) return(i); if(nps >= NPS) error("Too many sections!\n"); p = &pst[nps]; p->p_name[0] = g->g_name[0]; p->p_name[1] = g->g_name[1]; p->p_size = g->g_value; return(nps++); } /* * Compare psection names. * Names are 2 words of (ugh) * radix 50. */ match(a, b) register int *a, *b; { if(a[0]==b[0] && a[1]==b[1]) return(1); return(0); } /* * Run through the symbols, * computing the first order * differencees for the -d option. * The last symbol requires * special handling. * For unknown reasons, the * last symbol sometimes gets * a funny size in spite of * this. */ deltas() { register struct sym *p; sort(1, 0); for(p=&sym[0]; p<&sym[nsy-1]; ++p) p->s_value = (p+1)->s_value - p->s_value; p->s_value = pst[p->s_ps].p_size - p->s_value; } /* * Sort symbols. * v is 1 for sort on value. * r is 1 for reverse sort. */ sort(v, r) { register struct sym *b, *m, *p; struct sym ts; for(b=&sym[0]; b<&sym[nsy-1]; ++b) { m = b; for(p=b+1; p<&sym[nsy]; ++p) if(cmp(v, r, m, p)) m = p; if(m != b) { copy(&ts, m, sizeof(ts)); copy(m, b, sizeof(ts)); copy(b, &ts, sizeof(ts)); } } } /* * Compare routine for * sort. */ cmp(v, r, a, b) register struct sym *a, *b; { register int n; int c; c = 0; if(v) { if(a->s_value > b->s_value) c = 1; } else for(n=0; n<6; ++n) { if(a->s_name[n] > b->s_name[n]) { c = 1; break; } if(a->s_name[n] < b->s_name[n]) break; } if(r) c = !c; return(c); } /* * Walk through the symbols, * formatting them and writing * the result to the standard * output. * Undefined symbols get stars * as a value. */ output() { register struct sym *p; register r50_t *np; register int ntl; int max; char ab[6]; max = oflag ? 1 : 3; ntl = 0; for(p=&sym[0]; p<&sym[nsy]; ++p) { if(ntl >= max) { putchar('\n'); ntl = 0; } else if(p != &sym[0]) putchar(' '); printf("%.6s", p->s_name); printf(" %c ", p->s_type==G_GSN?'g':' '); if((p->s_flag&G_DEF) != 0) printf("%06o", p->s_value); else printf("******"); np = pst[p->s_ps].p_name; if((np[0]==AB0 && np[1]==AB1) || (np[0]==AB2 && np[1]==AB3)) printf(" "); else { convert(ab, np); printf(" (%.6s)", ab); } ++ntl; } if(ntl) putchar('\n'); }