do case insensitive comparison on domain name
[unix-history] / usr / src / usr.bin / nm / nm.c
index 5b9d09a..dfa4ec8 100644 (file)
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)nm.c 4.2 %G%";
+static char sccsid[] = "@(#)nm.c 4.8 %G%";
 #endif
 #endif
+
 /*
  * nm - print name list; VAX string table version
  */
 /*
  * nm - print name list; VAX string table version
  */
+
 #include <sys/types.h>
 #include <sys/types.h>
+#include <sys/file.h>
 #include <ar.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <a.out.h>
 #include <stab.h>
 #include <ar.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <a.out.h>
 #include <stab.h>
-#include <stat.h>
+#include <ranlib.h>
 
 
-#define        SELECT  archive ? archdr.ar_name : *xargv
+#define        OARMAG          0177545         /* OLD archive magic number */
+#define        SELECT          (archive ? archdr.ar_name : *xargv)
 
 
-int    aflg, gflg, nflg, oflg, pflg, uflg; 
-int    rflg = 1;
-char   **xargv;
-int    archive;
-struct ar_hdr  archdr;
-union {
-       char    mag_armag[SARMAG+1];
+#define        YES             1
+#define        NO              0
+
+#define        u_strx          n_un.n_strx
+#define        u_name          n_un.n_name
+
+typedef struct nlist   NLIST;
+
+union {                                /* exec header, or magic string from library */
+       char    mag_armag[SARMAG + 1];
        struct  exec mag_exp;
 } mag_un;
        struct  exec mag_exp;
 } mag_un;
-#define        OARMAG  0177545
-FILE   *fi;
-off_t  off;
-off_t  ftell();
-char   *malloc();
-char   *realloc();
-char   *strp;
-char   *stab();
-off_t  strsiz;
-int    compare();
-int    narg;
-int    errs;
+
+struct ar_hdr  archdr;         /* archive file header structure */
+FILE   *fi;                    /* input file stream */
+off_t  off;                    /* offset into file */
+int    aflg,                   /* print debugger symbols */
+       gflg,                   /* print only global (external symbols */
+       nflg,                   /* sort numerically, not alphabetically */
+       oflg,                   /* prepend element name to each output line */
+       pflg,                   /* don't sort */
+       rflg = 1,               /* how to sort */
+       uflg,                   /* print only undefined symbols */
+       narg,                   /* global number of arguments */
+       errs,                   /* global error flag */
+       archive;                /* if file is an archive */
+char   **xargv;                /* global pointer to file name */
 
 main(argc, argv)
 
 main(argc, argv)
-char **argv;
+       int     argc;
+       char    **argv;
 {
 {
+       extern int      optind;
+       int     ch;                     /* getopts char */
 
 
-       if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) {
-               argv++;
-               while (*++*argv) switch (**argv) {
-
-               case 'n':
-                       nflg++;
-                       continue;
+       while ((ch = getopt(argc, argv, "agnopru")) != EOF)
+               switch((char)ch) {
+               case 'a':
+                       aflg = YES;
+                       break;
                case 'g':
                case 'g':
-                       gflg++;
-                       continue;
-               case 'u':
-                       uflg++;
-                       continue;
+                       gflg = YES;
+                       break;
+               case 'n':
+                       nflg = YES;
+                       break;
+               case 'o':
+                       oflg = YES;
+                       break;
+               case 'p':
+                       pflg = YES;
+                       break;
                case 'r':
                        rflg = -1;
                case 'r':
                        rflg = -1;
-                       continue;
-               case 'p':
-                       pflg++;
-                       continue;
-               case 'o':
-                       oflg++;
-                       continue;
-               case 'a':
-                       aflg++;
-                       continue;
+                       break;
+               case 'u':
+                       uflg = YES;
+                       break;
+               case '?':
                default:
                default:
-                       fprintf(stderr, "nm: invalid argument -%c\n",
-                           *argv[0]);
+                       fputs("usage: nm [-agnopru] [file ...]\n", stderr);
                        exit(2);
                }
                        exit(2);
                }
-               argc--;
-       }
-       if (argc == 0) {
+       argc -= optind;
+       argv += optind;
+       if (!argc) {
                argc = 1;
                argc = 1;
-               argv[1] = "a.out";
+               argv[0] = "a.out";
        }
        narg = argc;
        }
        narg = argc;
-       xargv = argv;
-       while (argc--) {
-               ++xargv;
-               namelist();
-       }
+       for (xargv = argv; argc--; ++xargv)
+               if (fi = fopen(*xargv, "r")) {
+                       namelist();
+                       (void)fclose(fi);
+               }
+               else
+                       error(NO, "cannot open");
        exit(errs);
 }
 
 namelist()
 {
        exit(errs);
 }
 
 namelist()
 {
-       register int j;
+       register NLIST  *N, **L;
+       register int    symcount, nsyms;
+       static  NLIST   *symp, **list;
+       static int      lastnsyms = -1,
+                       laststrsiz = -1;
+       static char     *strp;
+       off_t   strsiz;
+       long    lseek();
+       int     compare();
+       char    *malloc(), *realloc();
 
 
-       archive = 0;
-       fi = fopen(*xargv, "r");
-       if (fi == NULL) {
-               error(0, "cannot open");
+       /*
+        * read first few bytes, determine if an archive,
+        * or executable; if executable, check magic number
+        */
+       /*NOSTRICT*/
+       if (!fread((char *)&mag_un, sizeof(mag_un), 1, fi)) {
+               error(NO, "unable to read file");
                return;
        }
                return;
        }
-       off = SARMAG;
-       fread((char *)&mag_un, 1, sizeof(mag_un), fi);
        if (mag_un.mag_exp.a_magic == OARMAG) {
        if (mag_un.mag_exp.a_magic == OARMAG) {
-               error(0, "old archive");
+               error(NO, "old archive");
                return;
        }
                return;
        }
-       if (strncmp(mag_un.mag_armag, ARMAG, SARMAG)==0)
-               archive++;
-       else if (N_BADMAG(mag_un.mag_exp)) {
-               error(0, "bad format");
-               return;
+       if (bcmp(mag_un.mag_armag, ARMAG, SARMAG)) {
+               if (N_BADMAG(mag_un.mag_exp)) {
+                       error(NO, "bad format");
+                       return;
+               }
+               archive = NO;
+               rewind(fi);
        }
        }
-       fseek(fi, 0L, 0);
-       if (archive) {
-               nextel(fi);
+       else {
+               /*
+                * if archive, skip first entry
+                * if ranlib'd, skip second entry
+                */
+               off = SARMAG;           /* see nextel() */
+               (void)nextel();
+               if (!strcmp(RANLIBMAG, archdr.ar_name))
+                       (void)nextel();
                if (narg > 1)
                        printf("\n%s:\n", *xargv);
                if (narg > 1)
                        printf("\n%s:\n", *xargv);
+               archive = YES;
        }
        }
-       do {
-               off_t o;
-               register i, n, c;
-               struct nlist *symp = NULL;
-               struct nlist sym;
-               struct stat stb;
 
 
-               fread((char *)&mag_un.mag_exp, 1, sizeof(struct exec), fi);
+       do {
+               /* check for bad magic number */
+               /*NOSTRICT*/
+               if (!fread((char *)&mag_un.mag_exp, sizeof(struct exec), 1, fi)) {
+                       error(NO, "unable to read magic number");
+                       return;
+               }
                if (N_BADMAG(mag_un.mag_exp))
                        continue;
                if (N_BADMAG(mag_un.mag_exp))
                        continue;
-               if (archive == 0)
-                       fstat(fileno(fi), &stb);
-               o = N_SYMOFF(mag_un.mag_exp) - sizeof (struct exec);
-               fseek(fi, o, 1);
-               n = mag_un.mag_exp.a_syms / sizeof(struct nlist);
-               if (n == 0) {
-                       error(0, "no name list");
+
+               /* calculate number of symbols in object */
+               if (!(nsyms = mag_un.mag_exp.a_syms / sizeof(NLIST))) {
+                       error(NO, "no name list");
                        continue;
                }
                        continue;
                }
-               if (N_STROFF(mag_un.mag_exp) + sizeof (off_t) >
-                   (archive ? off : stb.st_size))
-                       error(1, "old format .o (no string table) or truncated file");
-               i = 0;
-               if (strp)
-                       free(strp), strp = 0;
-               while (--n >= 0) {
-                       fread((char *)&sym, 1, sizeof(sym), fi);
-                       if (gflg && (sym.n_type&N_EXT)==0)
-                               continue;
-                       if ((sym.n_type&N_STAB) && (!aflg||gflg||uflg))
-                               continue;
-                       if (symp==NULL)
-                               symp = (struct nlist *)
-                                   malloc(sizeof(struct nlist));
-                       else
-                               symp = (struct nlist *)
-                                   realloc(symp,
-                                       (i+1)*sizeof(struct nlist));
-                       if (symp == NULL)
-                               error(1, "out of memory");
-                       symp[i++] = sym;
+
+               /* seek to and read symbols */
+               (void)fseek(fi, (long)(N_SYMOFF(mag_un.mag_exp) - sizeof(struct exec)), L_INCR);
+               if (!symp || nsyms > lastnsyms) {
+                       if (!symp) {
+                               /*NOSTRICT*/
+                               symp = (NLIST *)malloc((u_int)(nsyms * sizeof(NLIST)));
+                               /*NOSTRICT*/
+                               list = (NLIST **)malloc((u_int)(nsyms * sizeof(NLIST *)));
+                       }
+                       else {
+                               /*NOSTRICT*/
+                               symp = (NLIST *)realloc((char *)symp, (u_int)(nsyms * sizeof(NLIST)));
+                               /*NOSTRICT*/
+                               list = (NLIST **)realloc((char *)list, (u_int)(nsyms * sizeof(NLIST *)));
+                       }
+                       if (!symp || !list)
+                               error(YES, "out of memory");
+                       lastnsyms = nsyms;
                }
                }
-               if (archive && ftell(fi)+sizeof(off_t) >= off) {
-                       error(0, "no string table (old format .o?)");
+               /*NOSTRICT*/
+               if (fread((char *)symp, sizeof(NLIST), nsyms, fi) != nsyms) {
+                       error(NO, "bad symbol table");
                        continue;
                }
                        continue;
                }
-               if (fread((char *)&strsiz,sizeof(strsiz),1,fi) != 1) {
-                       error(0, "no string table (old format .o?)");
-                       goto out;
+
+               /* read number of strings, string table */
+               /*NOSTRICT*/
+               if (!fread((char *)&strsiz, sizeof(strsiz), 1, fi)) {
+                       error(NO, "no string table (old format .o?)");
+                       continue;
                }
                }
-               strp = (char *)malloc(strsiz);
-               if (strp == NULL)
-                       error(1, "ran out of memory");
-               if (fread(strp+sizeof(strsiz),strsiz-sizeof(strsiz),1,fi) != 1)
-                       error(1, "error reading string table");
-               for (j = 0; j < i; j++)
-                       if (symp[j].n_un.n_strx)
-                               symp[j].n_un.n_name =
-                                   symp[j].n_un.n_strx + strp;
-                       else
-                               symp[j].n_un.n_name = "";
-               if (pflg==0)
-                       qsort(symp, i, sizeof(struct nlist), compare);
-               if ((archive || narg>1) && oflg==0)
+               if (!strp || strsiz > laststrsiz) {
+                       strp = strp ? realloc(strp, (u_int)strsiz) : malloc((u_int)strsiz);
+                       if (!strp)
+                               error(YES, "out of memory");
+                       laststrsiz = strsiz;
+               }
+               if (!fread(strp + sizeof(strsiz), 1, (int)(strsiz - sizeof(strsiz)), fi)) {
+                       error(NO, "no string table (old format .o?)");
+                       continue;
+               }
+
+               for (symcount = nsyms, L = list, N = symp;--nsyms >= 0;++N)
+                       if (!(N->n_type & N_EXT) && gflg || N->n_type & N_STAB && (!aflg || gflg || uflg))
+                               --symcount;
+                       else {
+                               N->u_name = N->u_strx ? strp + N->u_strx : "";
+                               *L++ = N;
+                       }
+
+               if (!pflg)
+                       qsort(list, symcount, sizeof(NLIST *), compare);
+
+               if ((archive || narg > 1) && !oflg)
                        printf("\n%s:\n", SELECT);
                        printf("\n%s:\n", SELECT);
-               psyms(symp, i);
-               if (symp)
-                       free((char *)symp), symp = 0;
-               if (strp)
-                       free((char *)strp), strp = 0;
-       } while(archive && nextel(fi));
-out:
-       fclose(fi);
+
+               psyms(list, symcount);
+       } while(archive && nextel());
 }
 
 }
 
-psyms(symp, nsyms)
-       register struct nlist *symp;
-       int nsyms;
+psyms(list, nsyms)
+       NLIST   **list;
+       register int    nsyms;
 {
 {
-       register int n, c;
+       register NLIST  *L;
+       register u_char type;
+       char    *stab();
 
 
-       for (n=0; n<nsyms; n++) {
-               c = symp[n].n_type;
-               if (c & N_STAB) {
+       while (nsyms--) {
+               L = *list++;
+               type = L->n_type;
+               if (type & N_STAB) {
                        if (oflg) {
                                if (archive)
                                        printf("%s:", *xargv);
                                printf("%s:", SELECT);
                        }
                        if (oflg) {
                                if (archive)
                                        printf("%s:", *xargv);
                                printf("%s:", SELECT);
                        }
-                       printf("%08x - %02x %04x %5.5s %s\n",
-                           symp[n].n_value,
-                           symp[n].n_other & 0xff, symp[n].n_desc & 0xffff,
-                           stab(symp[n].n_type & 0xff),
-                           symp[n].n_un.n_name);
+                       printf("%08x - %02x %04x %5.5s %s\n", (int)L->n_value, L->n_other & 0xff, L->n_desc & 0xffff, stab(L->n_type), L->u_name);
                        continue;
                }
                        continue;
                }
-               switch (c&N_TYPE) {
-
+               switch (type & N_TYPE) {
                case N_UNDF:
                case N_UNDF:
-                       c = 'u';
-                       if (symp[n].n_value)
-                               c = 'c';
+                       type = L->n_value ? 'c' : 'u';
                        break;
                case N_ABS:
                        break;
                case N_ABS:
-                       c = 'a';
+                       type = 'a';
                        break;
                case N_TEXT:
                        break;
                case N_TEXT:
-                       c = 't';
+                       type = 't';
                        break;
                case N_DATA:
                        break;
                case N_DATA:
-                       c = 'd';
+                       type = 'd';
                        break;
                case N_BSS:
                        break;
                case N_BSS:
-                       c = 'b';
+                       type = 'b';
                        break;
                case N_FN:
                        break;
                case N_FN:
-                       c = 'f';
+                       type = 'f';
+                       break;
+               default:
+                       type = '?';
                        break;
                }
                        break;
                }
-               if (uflg && c!='u')
+               if (uflg && type != 'u')
                        continue;
                if (oflg) {
                        if (archive)
                                printf("%s:", *xargv);
                        printf("%s:", SELECT);
                }
                        continue;
                if (oflg) {
                        if (archive)
                                printf("%s:", *xargv);
                        printf("%s:", SELECT);
                }
-               if (symp[n].n_type&N_EXT)
-                       c = toupper(c);
+               if (L->n_type & N_EXT)
+                       type = toupper(type);
                if (!uflg) {
                if (!uflg) {
-                       if (c=='u' || c=='U')
-                               printf("        ");
+                       if (type == 'u' || type == 'U')
+                               fputs("        ", stdout);
                        else
                        else
-                               printf(N_FORMAT, symp[n].n_value);
-                       printf(" %c ", c);
+                               printf(N_FORMAT, (int)L->n_value);
+                       printf(" %c ", (char)type);
                }
                }
-               printf("%s\n", symp[n].n_un.n_name);
-l1:            ;
+               puts(L->u_name);
        }
 }
 
 compare(p1, p2)
        }
 }
 
 compare(p1, p2)
-struct nlist *p1, *p2;
+       NLIST   **p1, **p2;
 {
 {
-       register i;
-
        if (nflg) {
        if (nflg) {
-               if (p1->n_value > p2->n_value)
+               if ((*p1)->n_value > (*p2)->n_value)
                        return(rflg);
                        return(rflg);
-               if (p1->n_value < p2->n_value)
+               if ((*p1)->n_value < (*p2)->n_value)
                        return(-rflg);
        }
                        return(-rflg);
        }
-       return (rflg * strcmp(p1->n_un.n_name, p2->n_un.n_name));
+       return(rflg * strcmp((*p1)->u_name, (*p2)->u_name));
 }
 
 }
 
-nextel(af)
-FILE *af;
+nextel()
 {
 {
-       register char *cp;
-       register r;
-       long arsize;
+       register char   *cp;
+       long    arsize,
+               lseek();
 
 
-       fseek(af, off, 0);
-       r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af);
-       if (r != sizeof(struct ar_hdr))
+       (void)fseek(fi, off, L_SET);
+       /*NOSTRICT*/
+       if (!fread((char *)&archdr, sizeof(struct ar_hdr), 1, fi))
                return(0);
                return(0);
-       for (cp = archdr.ar_name; cp < &archdr.ar_name[sizeof(archdr.ar_name)]; cp++)
-               if (*cp == ' ')
+       for (cp = archdr.ar_name; cp < &archdr.ar_name[sizeof(archdr.ar_name)]; ++cp)
+               if (*cp == ' ') {
                        *cp = '\0';
                        *cp = '\0';
+                       break;
+               }
        arsize = atol(archdr.ar_size);
        if (arsize & 1)
                ++arsize;
        arsize = atol(archdr.ar_size);
        if (arsize & 1)
                ++arsize;
-       off = ftell(af) + arsize;       /* beginning of next element */
+       off = ftell(fi) + arsize;       /* beginning of next element */
        return(1);
 }
 
        return(1);
 }
 
-error(n, s)
-char *s;
-{
-       fprintf(stderr, "nm: %s:", *xargv);
-       if (archive) {
-               fprintf(stderr, "(%s)", archdr.ar_name);
-               fprintf(stderr, ": ");
-       } else
-               fprintf(stderr, " ");
-       fprintf(stderr, "%s\n", s);
-       if (n)
-               exit(2);
-       errs = 1;
-}
-
 struct stabnames {
        int     st_value;
        char    *st_name;
 } stabnames[] ={
 struct stabnames {
        int     st_value;
        char    *st_name;
 } stabnames[] ={
-       N_GSYM, "GSYM",
-       N_FNAME, "FNAME",
-       N_FUN, "FUN",
-       N_STSYM, "STSYM",
-       N_LCSYM, "LCSYM",
-       N_RSYM, "RSYM",
-       N_SLINE, "SLINE",
-       N_SSYM, "SSYM",
-       N_SO, "SO",
-       N_LSYM, "LSYM",
-       N_SOL, "SOL",
-       N_PSYM, "PSYM",
-       N_ENTRY, "ENTRY",
-       N_LBRAC, "LBRAC",
-       N_RBRAC, "RBRAC",
-       N_BCOMM, "BCOMM",
-       N_ECOMM, "ECOMM",
-       N_ECOML, "ECOML",
-       N_LENG, "LENG",
-       N_PC, "PC",
-       0, 0
+       N_GSYM,         "GSYM",
+       N_FNAME,        "FNAME",
+       N_FUN,          "FUN",
+       N_STSYM,        "STSYM",
+       N_LCSYM,        "LCSYM",
+       N_RSYM,         "RSYM",
+       N_SLINE,        "SLINE",
+       N_SSYM,         "SSYM",
+       N_SO,           "SO",
+       N_LSYM,         "LSYM",
+       N_SOL,          "SOL",
+       N_PSYM,         "PSYM",
+       N_ENTRY,        "ENTRY",
+       N_LBRAC,        "LBRAC",
+       N_RBRAC,        "RBRAC",
+       N_BCOMM,        "BCOMM",
+       N_ECOMM,        "ECOMM",
+       N_ECOML,        "ECOML",
+       N_LENG,         "LENG",
+       N_PC,           "PC",
+       0,              0
 };
 
 char *
 stab(val)
 };
 
 char *
 stab(val)
+       register u_char val;
 {
 {
-       register struct stabnames *sp;
-       static char prbuf[32];
+       register struct stabnames       *sp;
+       static char     prbuf[5];
 
 
-       for (sp = stabnames; sp->st_name; sp++)
+       for (sp = stabnames; sp->st_value; ++sp)
                if (sp->st_value == val)
                if (sp->st_value == val)
-                       return (sp->st_name);
-       sprintf(prbuf, "%02x", val);
-       return (prbuf);
+                       return(sp->st_name);
+       (void)sprintf(prbuf, "%02x", (int)val);
+       return(prbuf);
+}
+
+error(doexit, msg)
+       int     doexit;
+       char    *msg;
+{
+       fprintf(stderr, "nm: %s:", *xargv);
+       if (archive)
+               fprintf(stderr, "(%s): %s\n", archdr.ar_name, msg);
+       else
+               fprintf(stderr, " %s\n", msg);
+       if (doexit)
+               exit(2);
+       errs = 1;
 }
 }