home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / config / mkmakefile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-01  |  13.3 KB  |  616 lines

  1. /*
  2.  * Copyright (c) 1980,1990 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)mkmakefile.c    5.33 (Berkeley) 7/1/91";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  * Build the makefile for the system, from
  40.  * the information in the files files and the
  41.  * additional files for the machine being compiled to.
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <ctype.h>
  46. #include "y.tab.h"
  47. #include "config.h"
  48.  
  49. #define next_word(fp, wd) \
  50.     { register char *word = get_word(fp); \
  51.       if (word == (char *)EOF) \
  52.         return; \
  53.       else \
  54.         wd = word; \
  55.     }
  56. #define next_quoted_word(fp, wd) \
  57.     { register char *word = get_quoted_word(fp); \
  58.       if (word == (char *)EOF) \
  59.         return; \
  60.       else \
  61.         wd = word; \
  62.     }
  63.  
  64. static    struct file_list *fcur;
  65. char *tail();
  66.  
  67. /*
  68.  * Lookup a file, by name.
  69.  */
  70. struct file_list *
  71. fl_lookup(file)
  72.     register char *file;
  73. {
  74.     register struct file_list *fp;
  75.  
  76.     for (fp = ftab ; fp != 0; fp = fp->f_next) {
  77.         if (eq(fp->f_fn, file))
  78.             return (fp);
  79.     }
  80.     return (0);
  81. }
  82.  
  83. /*
  84.  * Lookup a file, by final component name.
  85.  */
  86. struct file_list *
  87. fltail_lookup(file)
  88.     register char *file;
  89. {
  90.     register struct file_list *fp;
  91.  
  92.     for (fp = ftab ; fp != 0; fp = fp->f_next) {
  93.         if (eq(tail(fp->f_fn), tail(file)))
  94.             return (fp);
  95.     }
  96.     return (0);
  97. }
  98.  
  99. /*
  100.  * Make a new file list entry
  101.  */
  102. struct file_list *
  103. new_fent()
  104. {
  105.     register struct file_list *fp;
  106.  
  107.     fp = (struct file_list *) malloc(sizeof *fp);
  108.     bzero(fp, sizeof *fp);
  109.     if (fcur == 0)
  110.         fcur = ftab = fp;
  111.     else
  112.         fcur->f_next = fp;
  113.     fcur = fp;
  114.     return (fp);
  115. }
  116.  
  117. static    struct users {
  118.     int    u_default;
  119.     int    u_min;
  120.     int    u_max;
  121. } users[] = {
  122.     { 24, 8, 1024 },        /* MACHINE_VAX */
  123.     { 4, 2, 128 },            /* MACHINE_TAHOE */
  124.     { 8, 2, 64 },            /* MACHINE_HP300 */
  125.     { 8, 2, 64 },            /* MACHINE_I386 */
  126. };
  127. #define    NUSERS    (sizeof (users) / sizeof (users[0]))
  128.  
  129. /*
  130.  * Build the makefile from the skeleton
  131.  */
  132. makefile()
  133. {
  134.     FILE *ifp, *ofp;
  135.     char line[BUFSIZ];
  136.     struct opt *op;
  137.     struct users *up;
  138.  
  139.     read_files();
  140.     strcpy(line, "Makefile.");
  141.     (void) strcat(line, machinename);
  142.     ifp = fopen(line, "r");
  143.     if (ifp == 0) {
  144.         perror(line);
  145.         exit(1);
  146.     }
  147.     ofp = fopen(path("Makefile"), "w");
  148.     if (ofp == 0) {
  149.         perror(path("Makefile"));
  150.         exit(1);
  151.     }
  152.     fprintf(ofp, "IDENT=-D%s", raise(ident));
  153.     if (profiling)
  154.         fprintf(ofp, " -DGPROF");
  155.     if (cputype == 0) {
  156.         printf("cpu type must be specified\n");
  157.         exit(1);
  158.     }
  159.     { struct cputype *cp;
  160.       for (cp = cputype; cp; cp = cp->cpu_next)
  161.         fprintf(ofp, " -D%s", cp->cpu_name);
  162.     }
  163.     for (op = opt; op; op = op->op_next)
  164.         if (op->op_value)
  165.             fprintf(ofp, " -D%s=\"%s\"", op->op_name, op->op_value);
  166.         else
  167.             fprintf(ofp, " -D%s", op->op_name);
  168.     fprintf(ofp, "\n");
  169.     if (hadtz == 0)
  170.         printf("timezone not specified; gmt assumed\n");
  171.     if ((unsigned)machine > NUSERS) {
  172.         printf("maxusers config info isn't present, using vax\n");
  173.         up = &users[MACHINE_VAX-1];
  174.     } else
  175.         up = &users[machine-1];
  176.     if (maxusers == 0) {
  177.         printf("maxusers not specified; %d assumed\n", up->u_default);
  178.         maxusers = up->u_default;
  179.     } else if (maxusers < up->u_min) {
  180.         printf("minimum of %d maxusers assumed\n", up->u_min);
  181.         maxusers = up->u_min;
  182.     } else if (maxusers > up->u_max)
  183.         printf("warning: maxusers > %d (%d)\n", up->u_max, maxusers);
  184.     fprintf(ofp, "PARAM=-DTIMEZONE=%d -DDST=%d -DMAXUSERS=%d\n",
  185.         zone, dst, maxusers);
  186.     for (op = mkopt; op; op = op->op_next)
  187.         fprintf(ofp, "%s=%s\n", op->op_name, op->op_value);
  188.     if (debugging)
  189.         fprintf(ofp, "DEBUG=-g\n");
  190.     if (profiling)
  191.         fprintf(ofp, "PROF=-pg\n");
  192.     while (fgets(line, BUFSIZ, ifp) != 0) {
  193.         if (*line != '%') {
  194.             fprintf(ofp, "%s", line);
  195.             continue;
  196.         }
  197.         if (eq(line, "%OBJS\n"))
  198.             do_objs(ofp);
  199.         else if (eq(line, "%CFILES\n"))
  200.             do_cfiles(ofp);
  201.         else if (eq(line, "%RULES\n"))
  202.             do_rules(ofp);
  203.         else if (eq(line, "%LOAD\n"))
  204.             do_load(ofp);
  205.         else
  206.             fprintf(stderr,
  207.                 "Unknown %% construct in generic makefile: %s",
  208.                 line);
  209.     }
  210.     (void) fclose(ifp);
  211.     (void) fclose(ofp);
  212. }
  213.  
  214. /*
  215.  * Read in the information about files used in making the system.
  216.  * Store it in the ftab linked list.
  217.  */
  218. read_files()
  219. {
  220.     FILE *fp;
  221.     register struct file_list *tp, *pf;
  222.     register struct device *dp;
  223.     struct device *save_dp;
  224.     register struct opt *op;
  225.     char *wd, *this, *needs, *special;
  226.     char fname[32];
  227.     int nreqs, first = 1, configdep, isdup, std, filetype;
  228.  
  229.     ftab = 0;
  230.     (void) strcpy(fname, "../../conf/files");
  231. openit:
  232.     fp = fopen(fname, "r");
  233.     if (fp == 0) {
  234.         perror(fname);
  235.         exit(1);
  236.     }
  237. next:
  238.     /*
  239.      * filename    [ standard | optional ] [ config-dependent ]
  240.      *    [ dev* | profiling-routine ] [ device-driver]
  241.      *    [ compile-with "compile rule" ]
  242.      */
  243.     wd = get_word(fp);
  244.     if (wd == (char *)EOF) {
  245.         (void) fclose(fp);
  246.         if (first == 1) {
  247.             (void) sprintf(fname, "files.%s", machinename);
  248.             first++;
  249.             goto openit;
  250.         }
  251.         if (first == 2) {
  252.             (void) sprintf(fname, "files.%s", raise(ident));
  253.             first++;
  254.             fp = fopen(fname, "r");
  255.             if (fp != 0)
  256.                 goto next;
  257.         }
  258.         return;
  259.     }
  260.     if (wd == 0)
  261.         goto next;
  262.     this = ns(wd);
  263.     next_word(fp, wd);
  264.     if (wd == 0) {
  265.         printf("%s: No type for %s.\n",
  266.             fname, this);
  267.         exit(1);
  268.     }
  269.     if ((pf = fl_lookup(this)) && (pf->f_type != INVISIBLE || pf->f_flags))
  270.         isdup = 1;
  271.     else
  272.         isdup = 0;
  273.     tp = 0;
  274.     if (first == 3 && (tp = fltail_lookup(this)) != 0)
  275.         printf("%s: Local file %s overrides %s.\n",
  276.             fname, this, tp->f_fn);
  277.     nreqs = 0;
  278.     special = 0;
  279.     configdep = 0;
  280.     needs = 0;
  281.     std = 0;
  282.     filetype = NORMAL;
  283.     if (eq(wd, "standard"))
  284.         std = 1;
  285.     else if (!eq(wd, "optional")) {
  286.         printf("%s: %s must be optional or standard\n", fname, this);
  287.         exit(1);
  288.     }
  289. nextparam:
  290.     next_word(fp, wd);
  291.     if (wd == 0)
  292.         goto doneparam;
  293.     if (eq(wd, "config-dependent")) {
  294.         configdep++;
  295.         goto nextparam;
  296.     }
  297.     if (eq(wd, "compile-with")) {
  298.         next_quoted_word(fp, wd);
  299.         if (wd == 0) {
  300.             printf("%s: %s missing compile command string.\n",
  301.                    fname);
  302.             exit(1);
  303.         }
  304.         special = ns(wd);
  305.         goto nextparam;
  306.     }
  307.     nreqs++;
  308.     if (eq(wd, "device-driver")) {
  309.         filetype = DRIVER;
  310.         goto nextparam;
  311.     }
  312.     if (eq(wd, "profiling-routine")) {
  313.         filetype = PROFILING;
  314.         goto nextparam;
  315.     }
  316.     if (needs == 0 && nreqs == 1)
  317.         needs = ns(wd);
  318.     if (isdup)
  319.         goto invis;
  320.     for (dp = dtab; dp != 0; save_dp = dp, dp = dp->d_next)
  321.         if (eq(dp->d_name, wd)) {
  322.             if (std && dp->d_type == PSEUDO_DEVICE &&
  323.                 dp->d_slave <= 0)
  324.                 dp->d_slave = 1;
  325.             goto nextparam;
  326.         }
  327.     if (std) {
  328.         dp = (struct device *) malloc(sizeof *dp);
  329.         init_dev(dp);
  330.         dp->d_name = ns(wd);
  331.         dp->d_type = PSEUDO_DEVICE;
  332.         dp->d_slave = 1;
  333.         save_dp->d_next = dp;
  334.         goto nextparam;
  335.     }
  336.     for (op = opt; op != 0; op = op->op_next)
  337.         if (op->op_value == 0 && opteq(op->op_name, wd)) {
  338.             if (nreqs == 1) {
  339.                 free(needs);
  340.                 needs = 0;
  341.             }
  342.             goto nextparam;
  343.         }
  344. invis:
  345.     while ((wd = get_word(fp)) != 0)
  346.         ;
  347.     if (tp == 0)
  348.         tp = new_fent();
  349.     tp->f_fn = this;
  350.     tp->f_type = INVISIBLE;
  351.     tp->f_needs = needs;
  352.     tp->f_flags = isdup;
  353.     tp->f_special = special;
  354.     goto next;
  355.  
  356. doneparam:
  357.     if (std == 0 && nreqs == 0) {
  358.         printf("%s: what is %s optional on?\n",
  359.             fname, this);
  360.         exit(1);
  361.     }
  362.  
  363. save:
  364.     if (wd) {
  365.         printf("%s: syntax error describing %s\n",
  366.             fname, this);
  367.         exit(1);
  368.     }
  369.     if (filetype == PROFILING && profiling == 0)
  370.         goto next;
  371.     if (tp == 0)
  372.         tp = new_fent();
  373.     tp->f_fn = this;
  374.     tp->f_type = filetype;
  375.     tp->f_flags = 0;
  376.     if (configdep)
  377.         tp->f_flags |= CONFIGDEP;
  378.     tp->f_needs = needs;
  379.     tp->f_special = special;
  380.     if (pf && pf->f_type == INVISIBLE)
  381.         pf->f_flags = 1;        /* mark as duplicate */
  382.     goto next;
  383. }
  384.  
  385. opteq(cp, dp)
  386.     char *cp, *dp;
  387. {
  388.     char c, d;
  389.  
  390.     for (; ; cp++, dp++) {
  391.         if (*cp != *dp) {
  392.             c = isupper(*cp) ? tolower(*cp) : *cp;
  393.             d = isupper(*dp) ? tolower(*dp) : *dp;
  394.             if (c != d)
  395.                 return (0);
  396.         }
  397.         if (*cp == 0)
  398.             return (1);
  399.     }
  400. }
  401.  
  402. do_objs(fp)
  403.     FILE *fp;
  404. {
  405.     register struct file_list *tp, *fl;
  406.     register int lpos, len;
  407.     register char *cp, och, *sp;
  408.     char swapname[32];
  409.  
  410.     fprintf(fp, "OBJS=");
  411.     lpos = 6;
  412.     for (tp = ftab; tp != 0; tp = tp->f_next) {
  413.         if (tp->f_type == INVISIBLE)
  414.             continue;
  415.         sp = tail(tp->f_fn);
  416.         for (fl = conf_list; fl; fl = fl->f_next) {
  417.             if (fl->f_type != SWAPSPEC)
  418.                 continue;
  419.             (void) sprintf(swapname, "swap%s.c", fl->f_fn);
  420.             if (eq(sp, swapname))
  421.                 goto cont;
  422.         }
  423.         cp = sp + (len = strlen(sp)) - 1;
  424.         och = *cp;
  425.         *cp = 'o';
  426.         if (len + lpos > 72) {
  427.             lpos = 8;
  428.             fprintf(fp, "\\\n\t");
  429.         }
  430.         fprintf(fp, "%s ", sp);
  431.         lpos += len + 1;
  432.         *cp = och;
  433. cont:
  434.         ;
  435.     }
  436.     if (lpos != 8)
  437.         putc('\n', fp);
  438. }
  439.  
  440. do_cfiles(fp)
  441.     FILE *fp;
  442. {
  443.     register struct file_list *tp, *fl;
  444.     register int lpos, len;
  445.     char swapname[32];
  446.  
  447.     fputs("CFILES=", fp);
  448.     lpos = 8;
  449.     for (tp = ftab; tp; tp = tp->f_next)
  450.         if (tp->f_type != INVISIBLE) {
  451.             len = strlen(tp->f_fn);
  452.             if (tp->f_fn[len - 1] != 'c')
  453.                 continue;
  454.             if ((len = 3 + len) + lpos > 72) {
  455.                 lpos = 8;
  456.                 fputs("\\\n\t", fp);
  457.             }
  458.             fprintf(fp, "$S/%s ", tp->f_fn);
  459.             lpos += len + 1;
  460.         }
  461.     for (fl = conf_list; fl; fl = fl->f_next)
  462.         if (fl->f_type == SYSTEMSPEC) {
  463.             (void) sprintf(swapname, "swap%s.c", fl->f_fn);
  464.             if ((len = 3 + strlen(swapname)) + lpos > 72) {
  465.                 lpos = 8;
  466.                 fputs("\\\n\t", fp);
  467.             }
  468.             if (eq(fl->f_fn, "generic"))
  469.                 fprintf(fp, "$S/%s/%s/%s ",
  470.                     machinename, machinename, swapname);
  471.             else
  472.                 fprintf(fp, "%s ", swapname);
  473.             lpos += len + 1;
  474.         }
  475.     if (lpos != 8)
  476.         putc('\n', fp);
  477. }
  478.  
  479. char *
  480. tail(fn)
  481.     char *fn;
  482. {
  483.     register char *cp;
  484.  
  485.     cp = rindex(fn, '/');
  486.     if (cp == 0)
  487.         return (fn);
  488.     return (cp+1);
  489. }
  490.  
  491. /*
  492.  * Create the makerules for each file
  493.  * which is part of the system.
  494.  * Devices are processed with the special c2 option -i
  495.  * which avoids any problem areas with i/o addressing
  496.  * (e.g. for the VAX); assembler files are processed by as.
  497.  */
  498. do_rules(f)
  499.     FILE *f;
  500. {
  501.     register char *cp, *np, och, *tp;
  502.     register struct file_list *ftp;
  503.     char *special;
  504.  
  505.     for (ftp = ftab; ftp != 0; ftp = ftp->f_next) {
  506.         if (ftp->f_type == INVISIBLE)
  507.             continue;
  508.         cp = (np = ftp->f_fn) + strlen(ftp->f_fn) - 1;
  509.         och = *cp;
  510.         *cp = '\0';
  511.         if (och == 'o') {
  512.             fprintf(f, "%so:\n\t-cp $S/%so .\n\n", tail(np), np);
  513.             continue;
  514.         }
  515.         fprintf(f, "%so: $S/%s%c\n", tail(np), np, och);
  516.         tp = tail(np);
  517.         special = ftp->f_special;
  518.         if (special == 0) {
  519.             char *ftype;
  520.             static char cmd[128];
  521.  
  522.             switch (ftp->f_type) {
  523.  
  524.             case NORMAL:
  525.                 ftype = "NORMAL";
  526.                 break;
  527.  
  528.             case DRIVER:
  529.                 ftype = "DRIVER";
  530.                 break;
  531.  
  532.             case PROFILING:
  533.                 if (!profiling)
  534.                     continue;
  535.                 ftype = "PROFILE";
  536.                 break;
  537.  
  538.             default:
  539.                 printf("config: don't know rules for %s\n", np);
  540.                 break;
  541.             }
  542.             (void)sprintf(cmd, "${%s_%c%s}", ftype, toupper(och),
  543.                       ftp->f_flags & CONFIGDEP? "_C" : "");
  544.             special = cmd;
  545.         }
  546.         *cp = och;
  547.         fprintf(f, "\t%s\n\n", special);
  548.     }
  549. }
  550.  
  551. /*
  552.  * Create the load strings
  553.  */
  554. do_load(f)
  555.     register FILE *f;
  556. {
  557.     register struct file_list *fl;
  558.     register int first;
  559.     struct file_list *do_systemspec();
  560.  
  561.     for (first = 1, fl = conf_list; fl; first = 0)
  562.         fl = fl->f_type == SYSTEMSPEC ?
  563.             do_systemspec(f, fl, first) : fl->f_next;
  564.     fputs("all:", f);
  565.     for (fl = conf_list; fl; fl = fl->f_next)
  566.         if (fl->f_type == SYSTEMSPEC)
  567.             fprintf(f, " %s", fl->f_needs);
  568.     putc('\n', f);
  569. }
  570.  
  571. struct file_list *
  572. do_systemspec(f, fl, first)
  573.     FILE *f;
  574.     register struct file_list *fl;
  575.     int first;
  576. {
  577.  
  578.     fprintf(f, "%s: ${SYSTEM_DEP} swap%s.o", fl->f_needs, fl->f_fn);
  579.     if (first)
  580.         fprintf(f, " newvers");
  581.     fprintf(f, "\n\t${SYSTEM_LD_HEAD}\n");
  582.     fprintf(f, "\t${SYSTEM_LD} swap%s.o\n", fl->f_fn);
  583.     fprintf(f, "\t${SYSTEM_LD_TAIL}\n\n");
  584.     do_swapspec(f, fl->f_fn);
  585.     for (fl = fl->f_next; fl->f_type == SWAPSPEC; fl = fl->f_next)
  586.         ;
  587.     return (fl);
  588. }
  589.  
  590. do_swapspec(f, name)
  591.     FILE *f;
  592.     register char *name;
  593. {
  594.  
  595.     if (!eq(name, "generic"))
  596.         fprintf(f, "swap%s.o: swap%s.c\n", name, name);
  597.     else
  598.         fprintf(f, "swapgeneric.o: ../%s/swapgeneric.c\n",
  599.             machinename);
  600.     fprintf(f, "\t${NORMAL_C}\n\n");
  601. }
  602.  
  603. char *
  604. raise(str)
  605.     register char *str;
  606. {
  607.     register char *cp = str;
  608.  
  609.     while (*str) {
  610.         if (islower(*str))
  611.             *str = toupper(*str);
  612.         str++;
  613.     }
  614.     return (cp);
  615. }
  616.