# 2.11BSD#431 - /usr/src/local/mkovmake/mkovmake.c

##### Functions

    adlib             X
    getnames          X
    ilikeu            X
    listmodules       X
    main              X
    metoo             X
    nlibs             X
    pname             X

##### Variables

    libs              X
    listnames         X
    module            X
    optimize          X

##### Macros

    IN_BASE           X
    LISTWIDTH         X
    MAXSYMLEN         X
    UNCOMMITTED       X
    isarc             X
    isobj             X

##### struct's

    modstruct         X

       1: /*
       2:  * mkovmake.c	by dennisf@ndcvx.cc.nd.edu  March 1990
       3:  *	makes an overlay makefile for specified object modules.
       4:  *  v1.1: adds -v option, and #defines for ovinit and module[].overlay.
       5:  *  v1.2: -o option renamed to -f, new -o and -l options for output name
       6:  *	and libraries.
       7:  *  v2: Overlay optimizer!  Many changes, practically different program.
       8:  *  v3: Modified to use new object file (strings table) format. 1/9/94 - sms.
       9:  */
      10:
      11: #include <stdio.h>
      12: #include <strings.h>
      13: #include <ctype.h>
      14: #include <sys/param.h>
      15: #include <a.out.h>
      16: #include <sys/file.h>
      17:
      18: #define MAXSYMLEN 32
      19: #define IN_BASE 0
      20: #define UNCOMMITTED -1
      21: #define isobj(name) name[0] && name[0] != '-' && rindex(name,'.') \
      22:     && !strcmp(rindex(name,'.'), ".o")
      23: #define isarc(name) name[0] && name[0] != '-' && rindex(name,'.') \
      24:     && !strcmp(rindex(name,'.'), ".a")
      25:
      26: struct modstruct
      27: {
      28:     char *name;
      29:     unsigned text;
      30:     short overlay;
      31:     char **textnames;
      32:     char **undfnames;
      33: } *module;
      34: FILE *output;
      35: char *malloc(), *realloc(), *adlib(), *libs;
      36: int optimize, listnames;
      37: double metoo();
      38:
      39: main(argc, argv)
      40: int argc;
      41: char **argv;
      42: {
      43:     register i, n;
      44:     int ovinit; /* initial ov number, IN_BASE or UNCOMMITTED */
      45:     int j;      /* redundant-module index */
      46:     int nobj;   /* number of modules, used for malloc()ing */
      47:     long ovtext;    /* total size of text of UNCOMMITTED modules */
      48:     int ov;     /* overlay number, used in for loop */
      49:     int max_ovs;    /* max number of ovs mkovmake can make */
      50:     int ovs_used;   /* number of ovs actually used */
      51:     int modsleftout;/* number of modules not assigned to an ov */
      52:     unsigned max_ovsize;    /* sizeof biggest overlay, multiple of 8k */
      53:     unsigned bigovmod;  /* sizeof biggest module not assigned to base */
      54:     unsigned ovspace;   /* space occupied in current ov */
      55:     unsigned basesize;  /* limit on base, if optimizing */
      56:     int mostroutines;   /* module with biggest global text routines
      57: 				   per kb text ratio, if optimizing base */
      58:     double baseopt;     /* the best such ratio so far */
      59:     int wannabe;    /* module that most wants to be on the overlay,
      60: 			   if optimizing */
      61:     double affinity;/* metoo(ov,wannabe) */
      62:     double affinn;  /* metoo(ov,n) */
      63:     int Zused;  /* -Z option specified somewhere used in -O2 */
      64:     long tmpl;
      65:     char *makename, *program;
      66:     char *arg, switchc;
      67:
      68:     /* Usage */
      69:     if (argc == 1)
      70:     {
      71: usage:      fprintf(stderr,
      72:          "usage:  mkovmake [-On [basesize] [-n]] [-fmakefile] [-sovsize] [-vmax_ovs]\n");
      73:         fprintf(stderr, "\t\t[-oprogram] [-llibs ...] bases.o ... -Z ovmodules.o ...\n");
      74:         exit(1);
      75:     }
      76:
      77:     /* Set defaults */
      78:     Zused = listnames = bigovmod = ovtext = nobj = optimize = 0;
      79:     output = stdout;
      80:     max_ovsize = basesize = UNCOMMITTED;
      81:     ovinit = IN_BASE;
      82:     max_ovs = NOVL;
      83:     program = "$(PROGRAM)";
      84:     libs = malloc(2);
      85:     libs[0] = 0;
      86:     /* First parsing: get options, count object modules */
      87:     for (i = 1; i < argc; ++i)
      88:     {
      89:         if (argv[i][0] != '-')
      90:         {
      91:             if (isobj(argv[i]))
      92:                 ++nobj;
      93:             else if (isarc(argv[i]))
      94:                 adlib(argv[i]);
      95:             else
      96:             {
      97:                 fprintf(stderr, "mkovmake:  %s: unknown file type.\n",
      98:                  argv[i]);
      99:                 exit(5);
     100:             }
     101:         }
     102:         else
     103:         {
     104:             switchc = argv[i][1];
     105:             arg = argv[i] + 2;
     106:             if (!arg[0])
     107:                 arg = argv[++i];
     108:             switch (switchc)
     109:             {
     110:             case 'O':
     111:                 optimize = 1; /* Use given BASE */
     112:                 if (arg[0] == '2')
     113:                 {
     114:                     optimize = 2; /* Determine BASE */
     115:                     if (isdigit(argv[i+1][0]))
     116:                     {
     117:                         basesize = atoi(argv[++i]);
     118:                         if (index(argv[i],'k')
     119:                          || index(argv[i],'K'))
     120:                             basesize *= 1024;
     121:                         if (basesize < 10)
     122:                             basesize *= 8192;
     123:                     }
     124:                 }
     125:                 else
     126:                     --i; /* no argument */
     127:                 break;
     128:             case 'n':
     129:                 ++listnames;
     130:                 --i; /* no argument */
     131:                 break;
     132:             case 'Z':
     133:                 if (optimize != 2 && !nobj)
     134:                     fprintf(stderr, "Nothing in the BASE?  Ok...\n");
     135:                 ++Zused;
     136:                 --i; /* no argument */
     137:                 break;
     138:             case 'f':
     139:                 makename = arg;
     140:                 if ((output = fopen(makename, "w")) == NULL)
     141:                 {
     142:                     fprintf(stderr,
     143:                     "%s: cannot open for output.\n", makename);
     144:                     exit(2);
     145:                 }
     146:                 break;
     147:             case 's':
     148:                 max_ovsize = atoi(arg);
     149:                 if (index(arg,'k') || index(arg,'K'))
     150:                     max_ovsize *= 1024;
     151:                 if (max_ovsize < 10)
     152:                     max_ovsize *= 8192;
     153:                 break;
     154:             case 'v':
     155:                 max_ovs = atoi(arg);
     156:                 if (max_ovs > NOVL)
     157:                 {
     158:                     fprintf(stderr,
     159:                      "mkovmake:  can only use %d overlays.\n",
     160:                      NOVL);
     161:                     max_ovs = NOVL;
     162:                 }
     163:                 break;
     164:             case 'o':
     165:                 program = arg;
     166:                 break;
     167:             case 'l':
     168:                 adlib("-l");
     169:                 adlib(arg);
     170:                 break;
     171:             default:
     172:                 goto usage;
     173:             }
     174:         }
     175:     }
     176:     if (!libs[0])
     177:     {
     178:         free(libs);
     179:         libs = "$(LIBS) ";
     180:     }
     181:     if (!Zused && optimize == 2)
     182:         ovinit = UNCOMMITTED;
     183:
     184:     /* Second parsing: malloc for module[] array and load its members */
     185:     if (!(module = (struct modstruct *) malloc(sizeof(struct modstruct) * ++nobj)))
     186:     {
     187:         fprintf(stderr, "mkovmake:  not enough memory for module list.\n");
     188:         fprintf(stderr, "mkovmake:  can't use mkovmake!  Help!\n");
     189:         exit(6);
     190:     }
     191:     for (i = 1, n = 0; i < argc; ++i)
     192:     {
     193:         for (j = 1; j < i; ++j)
     194:             if (!strcmp(argv[i], argv[j]))
     195:                 break;
     196:         if (argv[i][0] == '-' && argv[i][1] == 'Z')
     197:             ovinit = UNCOMMITTED;
     198:         else if (j == i && isobj(argv[i]))
     199:         {
     200:             module[n].name = argv[i];
     201:             module[n].overlay = ovinit;
     202:             getnames(n);  /* gets sizeof text and name lists */
     203:             if (ovinit != IN_BASE)
     204:             {
     205:                 ovtext += module[n].text;
     206:                 if (module[n].text > bigovmod)
     207:                     bigovmod = module[n].text;
     208:             }
     209:             ++n;
     210:         }
     211:     }
     212:     module[n].name = "";
     213:     if (max_ovsize == UNCOMMITTED)
     214:     {
     215:         max_ovsize = (unsigned) (ovtext / (7680L * max_ovs) + 1) * 8192;
     216:         if (bigovmod > max_ovsize)
     217:             max_ovsize = (bigovmod / 8192 + 1) * 8192;
     218:         fprintf(output, "# Using %dk overlays.\n", max_ovsize/1024);
     219:     }
     220:
     221:     /*
     222: 	 * Optimizer levels:
     223: 	 * 1: use given BASE, all other modules are UNCOMMITTED.
     224: 	 * 2: determine BASE, all modules are UNCOMMITTED.
     225: 	 * 3: programmer gets COMMITTED.
     226: 	 */
     227:     if (optimize == 2)
     228:     {
     229:         if (basesize == UNCOMMITTED)
     230:         {
     231:             /* is this a fudge or what?? */
     232:             tmpl = ((tmpl = 2048 + nlibs()*2048L + ovtext/5)
     233:              > 24576L) ? 24576L : tmpl;
     234:             basesize = (65536L - max_ovsize - tmpl);
     235:             fprintf(output, "# Using %u-byte base, without libraries.\n",
     236:              basesize);
     237:             /* If enough people are interested, I'll make a version
     238: 			   of this that adds up routines used within libraries */
     239:         }
     240:         n = -1;
     241:         while (module[++n].name[0])
     242:             if (module[n].overlay == IN_BASE)
     243:                 basesize -= module[n].text;
     244:         if (basesize < 0)
     245:         {
     246:             fprintf(stderr, "mkovmake:  specified modules don't fit in base.\n");
     247:             fprintf(stderr, "mkovmake:  specify fewer modules or larger base.\n");
     248:             exit(9);
     249:         }
     250:         do /* load the base */
     251:         {
     252:             baseopt = 0.;
     253:             n = -1;
     254:             while(module[++n].name[0])
     255:                 if (module[n].overlay != IN_BASE
     256:                  && module[n].text
     257:                  && module[n].text <= basesize
     258:                  && (double) (sizeof(module[n].textnames)-1)
     259:                  / module[n].text > baseopt)
     260:                 {
     261:                     mostroutines = n;
     262:                     baseopt = (double)
     263:                      (sizeof(module[n].textnames)-1)
     264:                      / module[n].text;
     265:                 }
     266:             if (baseopt)
     267:             {
     268:                 module[mostroutines].overlay = IN_BASE;
     269:                 basesize -= module[mostroutines].text;
     270:             }
     271:         } while(baseopt);
     272:     }
     273:     listmodules(IN_BASE);
     274:
     275:     /*
     276: 	 * overlay packing:
     277: 	 * If not optimizing, just pack modules until no more can fit.
     278: 	 * Otherwise, add a module only if it's the one thats to be on
     279: 	 *	the ov the most, using metoo().
     280: 	 */
     281:     for (ov = 1; ov <= max_ovs; ++ov)
     282:     {
     283:         ovspace = 0;
     284: addmod:     n = -1;
     285:         while (module[++n].name[0])
     286:         {
     287:             if (module[n].overlay == UNCOMMITTED
     288:              && module[n].text + ovspace <= max_ovsize)
     289:             {
     290:                 module[n].overlay = ov;
     291:                 ovspace += module[n].text;
     292:                 /* optimizer needs one */
     293:                 if (optimize && module[n].text)
     294:                     break;
     295:             }
     296:         }
     297:         if (!ovspace) /* max_ovsize is too small for a module */
     298:             break;
     299:         if (optimize && module[n].name[0])
     300:         {
     301:             for (;;) /* only escape is the goto! yuck! */
     302:             {
     303:                 affinity = 0.;
     304:                 n = -1;
     305:                 while (module[++n].name[0])
     306:                 {
     307:                     if (module[n].overlay == UNCOMMITTED
     308:                      && module[n].text
     309:                      && module[n].text + ovspace <= max_ovsize
     310:                      && (affinn = metoo(ov,n)) > affinity)
     311:                     {
     312:                         wannabe = n;
     313:                         affinity = affinn;
     314:                     }
     315:                 }
     316:                 if (!affinity)
     317:                     goto addmod; /* will another mod fit? */
     318:                 module[wannabe].overlay = ov;
     319:                 ovspace += module[wannabe].text;
     320:             }
     321:         }
     322:         listmodules(ov);
     323:     }
     324:     ovs_used = ov;
     325:
     326:     /* And what if they just don't all fit? */
     327:     n = modsleftout = 0;
     328:     while (module[n].name[0])
     329:         if (module[n++].overlay == UNCOMMITTED)
     330:             ++modsleftout;
     331:     if (modsleftout)
     332:     {
     333:         fprintf(stderr, "\nAfter %d overlay", ovs_used-1);
     334:         if (ovs_used != 2)  fprintf(stderr, "s");
     335:         fprintf(stderr, ", the following ");
     336:         if (modsleftout == 1)
     337:             fprintf(stderr, "module was\n");
     338:         else
     339:             fprintf(stderr, "%d modules were\n", modsleftout);
     340:         fprintf(stderr,
     341:          "left out of the BASE and OVerlay definitions:\n");
     342:         n = -1;
     343:         while (module[++n].name[0])
     344:             if (module[n].overlay == UNCOMMITTED)
     345:                 fprintf(stderr, "  %s\n", module[n].name);
     346:         fprintf(stderr,
     347:          "\nYou can 1) Use more or bigger overlays,\n");
     348:         fprintf(stderr, "  2) Use a smaller base, or\n");
     349:         fprintf(stderr, "  3) \"Go buy a VAX.\"\n");
     350:         fclose(output);
     351:         exit(3);
     352:     }
     353:
     354:     fprintf(output,
     355:      "%s:\n\t/bin/ld -i -X -o %s /lib/crt0.o \\\n\t", program, program);
     356:     fprintf(output, "$(BASE) ");
     357:     for (ov = 1; ov < ovs_used; ++ov)
     358:     {
     359:         if (ov % 4 == 1)
     360:             fprintf(output, "\\\n\t");
     361:         fprintf(output, "-Z $(OV%d) ", ov);
     362:     }
     363:     fprintf(output, "\\\n\t-Y %s-lc\n", libs);
     364:     fclose(output);
     365:     free((char *) module);
     366:     free(libs);
     367:     exit(0);
     368: }
     369:
     370: /*
     371:  * listmodules(ov)
     372:  *	lists modules in overlay ov (ov=0 is BASE), each line
     373:  *	preceded by a tab and not exceeding LISTWIDTH characters.
     374:  */
     375:
     376: #define LISTWIDTH   60
     377:
     378: listmodules(ov)
     379: int ov;
     380: {
     381:     int currentwidth = 0, n = -1, namelength;
     382:     unsigned listovspace = 0;
     383:
     384:     if (ov == IN_BASE)
     385:         fprintf(output, "\nBASE=\t");
     386:     else
     387:         fprintf(output, "OV%d=\t", ov);
     388:     while (module[++n].name[0])
     389:     {
     390:         if (module[n].overlay == ov)
     391:         {
     392:             namelength = strlen(module[n].name);
     393:             if (currentwidth + namelength > LISTWIDTH)
     394:             {
     395:                 fprintf(output, "\\\n\t");
     396:                 currentwidth = 0;
     397:             }
     398:             currentwidth += (namelength + 1);
     399:             fprintf(output, "%s ", module[n].name);
     400:             listovspace += module[n].text;
     401:         }
     402:     }
     403:     fprintf(output, "\n# %u bytes.\n\n", listovspace);
     404: }
     405:
     406: /*
     407:  * metoo()	returns how much a module wants to be on an overlay.
     408:  */
     409: double
     410: metoo(ov, mod)
     411: int ov, mod;
     412: {
     413:     int n, postnews;
     414:
     415:     if (!module[mod].text)
     416:         return(0.);
     417:     postnews = 0;
     418:     n = -1;
     419:     while (module[++n].name[0])
     420:         if (module[n].overlay == ov)
     421:             postnews += ilikeu(n, mod) + ilikeu(mod, n);
     422:     return((double) postnews / module[mod].text);
     423: }
     424:
     425: /*
     426:  * ilikeu()	returns how much one module likes another.
     427:  *	Just like life, it's not necessarily symmetrical.
     428:  */
     429: ilikeu(me, you)
     430: int me, you;
     431: {
     432:     int friendly;
     433:     char **ineed, **youhave;
     434:
     435:     friendly = 0;  /* Who are you? */
     436:     ineed = module[me].undfnames;
     437:     youhave = module[you].textnames;
     438:     while(**ineed)
     439:     {
     440:         while(**youhave)
     441:         {
     442:             if (!strcmp(*ineed, *youhave++))
     443:             {
     444:                 ++friendly;
     445:                 break;
     446:             }
     447:         }
     448:         ++ineed;
     449:     }
     450:     return(friendly);
     451: }
     452:
     453: /*
     454:  * adlib(s)	adds s onto libs.
     455:  */
     456: char *
     457: adlib(s)
     458: char *s;
     459: {
     460:     char *morelibs;
     461:
     462:     if (!(morelibs = realloc(libs, strlen(libs)+strlen(s)+3)))
     463:     {
     464:         fprintf(stderr, "mkovmake:  not enough memory for library names.\n");
     465:         exit(7);
     466:     }
     467:     strcat(morelibs, s);
     468:     if (s[0] != '-')
     469:         strcat(morelibs, " ");
     470:     libs = morelibs;
     471:     return(morelibs);
     472: }
     473:
     474: /*
     475:  * nlibs()	How many libs are there?
     476:  */
     477: nlibs()
     478: {
     479:     int i=0;
     480:     char *s;
     481:     s = libs;
     482:     while (*s)
     483:         if (*s++ == ' ')
     484:             ++i;
     485:     return(i);
     486: }
     487:
     488: /*
     489:  * getnames(n)	opens object module n and gets size of text,
     490:  *	and name lists if using optimizer.
     491:  */
     492: getnames(n)
     493: int n;
     494: {
     495:     struct xexec exp;
     496:     struct nlist namentry;
     497:     FILE *obj, *strfp = NULL;
     498:     off_t stroff;
     499:     int nundf, ntext;
     500:     char name[MAXSYMLEN + 2];
     501:
     502:     bzero(name, sizeof (name));
     503:     if ((obj = fopen(module[n].name,"r")) == NULL)
     504:     {
     505:         fprintf(stderr, "mkovmake:  cannot open %s.\n", module[n].name);
     506:         exit(8);
     507:     }
     508:     fread((char *)&exp, 1, sizeof(exp), obj);
     509:     module[n].text = exp.e.a_text;
     510:     if (!optimize)
     511:     {
     512:         fclose(obj);
     513:         return(0);
     514:     }
     515:
     516:     fseek(obj, N_SYMOFF(exp), L_SET);
     517:
     518:     ntext = nundf = 0;
     519:     while (fread((char *)&namentry, sizeof(namentry), 1, obj) == 1)
     520:     {
     521:         if (feof(obj) || ferror(obj))
     522:             break;
     523:         if (namentry.n_type & N_EXT)
     524:         {
     525:             switch (namentry.n_type&N_TYPE)
     526:             {
     527:             case N_UNDF:
     528:                 if (!namentry.n_value)
     529:                     ++nundf;
     530:                 break;
     531:             case N_TEXT:
     532:                 ++ntext;
     533:                 break;
     534:             }
     535:         }
     536:     }
     537:     module[n].textnames = (char **) malloc(++ntext * 2);
     538:     module[n].undfnames = (char **) malloc(++nundf * 2);
     539:     if (!module[n].textnames || !module[n].undfnames)
     540:     {
     541: nosyms:     fprintf(stderr, "mkovmake:  out of memory for symbols list.\n");
     542:         fprintf(stderr, "mkovmake:  can't optimize.\n");
     543:         optimize = 0;
     544:         fclose(obj);
     545:         if (strfp)
     546:             fclose(strfp);
     547:         return(1);
     548:     }
     549:
     550:     strfp = fopen(module[n].name, "r");
     551:     ntext = nundf = 0;
     552:     fseek(obj, N_SYMOFF(exp), L_SET);
     553:     stroff = N_STROFF(exp);
     554:     while (fread((char *)&namentry, sizeof(namentry), 1, obj) == 1)
     555:     {
     556:         if (namentry.n_type & N_EXT)
     557:         {
     558:             switch (namentry.n_type&N_TYPE)
     559:             {
     560:             case N_UNDF:
     561:                 if (!namentry.n_value)
     562:                 {
     563:                     fseek(strfp,
     564:                         stroff + namentry.n_un.n_strx,
     565:                         L_SET);
     566:                     fread(name, sizeof (name), 1, strfp);
     567:                     if (!(module[n].undfnames[nundf]
     568:                         = strdup(name)))
     569:                         goto nosyms;
     570:                     nundf++;
     571:                     if (listnames)
     572:                         pname(n, name, 0);
     573:                 }
     574:                 break;
     575:             case N_TEXT:
     576:                 fseek(strfp, stroff + namentry.n_un.n_strx,
     577:                     L_SET);
     578:                 fread(name, sizeof (name), 1, strfp);
     579:                 if (!(module[n].textnames[ntext]= strdup(name)))
     580:                     goto nosyms;
     581:                 ntext++;
     582:                 if (listnames)
     583:                     pname(n,name,1);
     584:                 break;
     585:             }
     586:         }
     587:     }
     588:     module[n].undfnames[nundf] = "";
     589:     module[n].textnames[ntext] = "";
     590:     fclose(obj);
     591:     fclose(strfp);
     592:     return(0);
     593: }
     594:
     595: /*
     596:  * pname(n,s,t)
     597:  *	prints global Text(t=1) and Undf(t=0) name s encountered in module n.
     598:  */
     599: pname(n,s,t)
     600: int n,t;
     601: char *s;
     602: {
     603:     if (t)
     604:         fprintf(stderr, "%s: T %s\n", module[n].name, s);
     605:     else
     606:         fprintf(stderr, "%s: U %s\n", module[n].name, s);
     607: }

#### Defined functions

adlib defined in line 456; used 4 times

- in line 35, 94, 168-169(2)

getnames defined in line 492; used 1 times

- in line 202

ilikeu defined in line 429; used 2 times

- in line 421(2)

listmodules defined in line 378; used 2 times

- in line 273, 322

main defined in line 39; never used
metoo defined in line 409; used 2 times

- in line 37, 310

nlibs defined in line 477; used 1 times

- in line 232

pname defined in line 599; used 2 times

- in line 572, 583

#### Defined variables

libs defined in line 35; used 11 times

- in line 84-85(2), 176-179(3), 363-366(2), 462(2), 470, 481

listnames defined in line 36; used 4 times

- in line 78, 129, 571, 582

module defined in line 33; used 64 times

- in line 185, 200-212(6), 241-243(3), 254-269(10), 285-293(6), 299, 305-309(4), 318-319(2), 328-329(2), 343-345(3), 365, 388-392(3), 399-400(2), 415-422(4), 436-437(2), 503-509(3), 537-539(4), 550, 567, 579, 588-589(2), 604-606(2)

optimize defined in line 36; used 10 times

- in line 78, 111-114(2), 133, 181, 227, 293, 299, 510, 543

#### Defined struct's

modstruct defined in line 26; used 4 times

- in line 185(4)

#### Defined macros

IN_BASE defined in line 19; used 7 times

- in line 81, 203, 242, 255, 268-273(2), 384

LISTWIDTH defined in line 376; used 1 times

- in line 393

MAXSYMLEN defined in line 18; used 1 times

- in line 500

UNCOMMITTED defined in line 20; used 9 times

- in line 80, 182, 197, 213, 229, 287, 307, 329, 344

isarc defined in line 23; used 1 times

- in line 93

isobj defined in line 21; used 2 times

- in line 91, 198

Last modified: 1994-01-09 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2598 |