home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / tools / make / tcmak / makemak.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-06-22  |  12.2 KB  |  560 lines

  1.  
  2. #include <string.h>        /* string stuff        */
  3. #include <stdio.h>        /* standard stuff        */
  4. #include <stdlib.h>        /* standard lib stuff*/
  5. #include <dir.h>        /* directory stuff    */
  6. #include <dos.h>        /* DOS stuff            */
  7. #include <errno.h>        /* system error        */
  8. #include <fcntl.h>
  9. /* #include <search.h> */
  10. /* #include <sys\types.h>  */    /* more types!!!        */
  11. #include <sys\stat.h>        /* stat stuff...        */
  12. /* #include    <sys\utime.h> */
  13. #include <time.h>
  14. #include "makemak.h"
  15.  
  16. struct ffblk dp;        /* file entry in directory   */
  17.  
  18.  
  19. struct dir_rec {
  20.     char name[FNAMELEN];    /* name of the file         */
  21.     long time;        /* last modified time     */
  22.     int  checked;        /* has it been checked?   */
  23.        } directory[MAXFILES];
  24.  
  25. int    count    = 0,        /* how many files in directory?         */
  26.         verbose    = 0,    /* -v (verbose) flag set... */
  27.         dependencies = 0, /* -d (dependencies) flag set.. */
  28.         show_times = 0,      /* -s (show times) flag set */
  29.         makefile = 1,     /* if no other options, make makefile */
  30.         srcs = 0,    /* > 0 if source files are present    */
  31.         objs = 0,       /* > 0 if obj files are present        */
  32.         hdrs = 0;    /* > 0 if header files are present    */
  33.  
  34.  
  35. #define _MAX_FNAME 13
  36. extern int errno;        /* system error number */
  37. extern char defaults[][SLEN];
  38. extern char mak_defs[][FNAMELEN];
  39. static char pgm[_MAX_FNAME] = {"makemak"};
  40.  
  41. char *cc_line    = {"\n\t$(CC) $(C_OPTS) $(CDEFS) %s\n\n" };
  42. char *mc_line    = {"\n\t$(MC) $(M_OPTS) $(MDEFS) %s;\n\n" };
  43. char *link_line = {"\t$(LINK) $(L_OPTS) $(OBJS), $(TARGET), $(LMAP), $(LIBS)\n" };
  44. char *link2_line = {"\t$(LINK) $(L_OPTS) @linkfile, $(TARGET), $(LMAP), $(LIBS)\n"};
  45.  
  46. char compile_command[SLEN] = { "" };
  47.  
  48.  
  49. void     initially_read_in_directory();
  50. void     initialize_makefile();
  51. void     finish_makefile();
  52. void     get_file_modification_dates();
  53. void     figure_out_includes(int, int);
  54. void    makelinkfile();
  55. int     check_for_include(char *);
  56. int     read_directory(char *);
  57. int     suffix(char *, char *);
  58. int    compare();        /* must be declared w/o args for qsort */
  59. int    dosvers();
  60. extern int getopt(int, char **, char *);
  61. extern void    mak_help(char *);
  62.  
  63. char *dirp;
  64.  
  65.  
  66. main(int argc, char *argv[])
  67. {
  68.     extern char *getpname(char *, char *);
  69.     extern int mak_cfg(char *);
  70.  
  71.     extern int optind, opterr;
  72.     extern char *optarg;
  73.  
  74.     register int i;
  75.     int c;
  76.     int arg_err = 0;
  77.  
  78.     _osmajor = dosvers();
  79.  
  80.     if (_osmajor < 2) 
  81.        fprintf(stderr, "%s: makemak requires DOS 2.00 or later.\n", pgm);
  82.  
  83.     if (_osmajor >= 3) 
  84.         getpname(*argv, pgm);
  85.  
  86.     opterr = 0;            /* supress getopt error message! */
  87.  
  88.     while ((c = getopt(argc, argv, "dhHsv")) != EOF)
  89.         switch (c)
  90.             {
  91.             case 'd' :
  92.                     dependencies++;
  93.                     makefile = FALSE;
  94.                     break;
  95.             case 'v' :
  96.                     verbose++;
  97.                     makefile = FALSE;
  98.                     break;
  99.             case 's' :
  100.                     show_times++;
  101.                     makefile = FALSE;
  102.                     break;
  103.             case 'h' :
  104.             case 'H' :
  105.             case '?' : 
  106.                     arg_err = TRUE;
  107.                     break;
  108.             }
  109.  
  110.     if (dependencies && verbose)
  111.         {
  112.         fprintf(stderr, "%s: Invalid option combination.\n", pgm);
  113.         exit(4);
  114.         }
  115.     
  116.     argc -= optind;
  117.     argv += optind;
  118.  
  119.     if ((makefile && (argc == 0)) || arg_err)
  120.         {
  121.         mak_help(pgm);
  122.         exit(3);
  123.         }
  124.  
  125.     strcpy(defaults[TARGET], *argv); 
  126.  
  127.     if (mak_cfg(pgm) != 0)
  128.         {
  129.           fprintf(stderr, "%s: bad dependancy configuration file.\n", pgm);
  130.         exit(6);
  131.         }
  132.  
  133.     initially_read_in_directory();        /* start up stuff                */
  134.  
  135.     if (makefile)
  136.       initialize_makefile();
  137.  
  138. /*
  139.     if the user wants to see the dates spin through and
  140.     spit 'em all out!
  141. */
  142.  
  143.     if (show_times)
  144.         {
  145.         get_file_modification_dates();    /* read file dates */
  146.         for (i=0; i < count; i++)
  147.             if (suffix(".c", directory[i].name) ||
  148.                 suffix(".h", directory[i].name) ||
  149.                 suffix(".asm", directory[i].name)) 
  150.   /* a legit file? */
  151.                 printf("%-15s %s", directory[i].name,
  152.                     ctime(&directory[i].time));
  153.         }
  154.  
  155. /* now let's go through and check all the source files */
  156.  
  157. for (i=0; i < count; i++)
  158.    if (suffix(".c", directory[i].name) || suffix(".asm", directory[i].name))
  159.     figure_out_includes(i, 1);            /* a source file? */
  160.  
  161.    if (makefile)
  162.     finish_makefile();
  163.  
  164.    exit(0);
  165. }
  166.  
  167.  
  168. void initially_read_in_directory()
  169. {
  170. /*
  171. initialize the system variables and read in and sort the current directory...
  172. */
  173.  
  174.     if (findfirst(".\\*.*",&dp, 0) == 0)    /* current directory */
  175.         strcpy(directory[count++].name, strlwr(dp.ff_name));
  176.  
  177.     while (read_directory(directory[count++].name) && count < MAXFILES)
  178.         ;
  179.  
  180.     if (count >= MAXFILES)
  181.         {
  182.         fprintf(stderr, 
  183. "%s: Warning: more files than this program can deal with!\n", pgm);
  184.         fprintf(stderr,
  185. "%s continuing, but it might be wrong!\n", pgm);
  186.         }
  187.  
  188.    qsort((void *)directory, (size_t) --count, sizeof (directory[0]), compare);
  189.    
  190. }
  191.  
  192.  
  193.  
  194. void initialize_makefile()
  195. {
  196. /*
  197.     outputs all the leading Makefile information as appropriate
  198. */
  199.  
  200. /* first off, let's dump the makefile_header stuff... */
  201.  
  202.     register int i, len;
  203.     FLAGS k;
  204.     char     buffer[SLEN];
  205.     FILE *fp;
  206.  
  207.     printf("# Custom make file generated by %s for %s\n\n", pgm, defaults[TARGET]);
  208.     for (k = TARGET; k <= LIBS; k++)
  209.         printf("%s = %s\n", mak_defs[k], defaults[k]);
  210.  
  211. /* next, we'll need to output "HDRS", "SRCS" and "OBJS" ... */
  212.  
  213.     printf("HDRS = ");
  214.  
  215.     for (len=8, i=0; i < count; i++)
  216.         if (suffix(".h", directory[i].name))
  217.             {
  218.             ++hdrs;
  219.             if (strlen(directory[i].name) + len > 75)
  220.                 {
  221.                 printf("  \\\n\t");
  222.                 len = 8;
  223.                 }
  224.             printf("%s ", directory[i].name);
  225.             len += strlen(directory[i].name)+1;
  226.             }
  227.  
  228.     putchar('\n');
  229.  
  230.     printf("SRCS = ");
  231.  
  232.     for (len = 8, i=0; i < count; i++)
  233.         if (suffix(".c", directory[i].name)
  234.         || suffix(".asm", directory[i].name))
  235.             {
  236.             ++srcs;
  237.             if (strlen(directory[i].name) + len > 75)
  238.                 {
  239.                 printf("  \\\n\t");
  240.                 len = 8;
  241.                 }
  242.             printf("%s ", directory[i].name);
  243.             len += strlen(directory[i].name)+1;
  244.             }
  245.  
  246.     putchar('\n');
  247.  
  248.     if ((fp = fopen("linkfile","w")) == NULL) {
  249.         fprintf(stderr, "Can't open linkfile\n");
  250.         exit(1);
  251.     }
  252.  
  253.     printf("OBJS = ");
  254.  
  255.     for (len = 8, i=0; i < count; i++)
  256.         if (suffix(".c", directory[i].name) 
  257.         || suffix(".asm", directory[i].name))
  258.             {
  259.             ++objs;
  260.             if (strlen(directory[i].name) + len > 75)
  261.                 {
  262.                 printf("  \\\n\t");
  263.                 fprintf(fp," +\n");
  264.                 len = 8;
  265.                 }
  266.             strcpy(buffer, directory[i].name);
  267.             strcpy(strchr(buffer, '.'), ".obj");    
  268.  /* make it a '.obj' file! */
  269.             printf("%s ", buffer);
  270.             fprintf(fp, "%s ", buffer);
  271.             len += strlen(buffer)+1;
  272.             }
  273.  
  274.     printf(" \n\n");
  275.     fprintf(fp,"\n");
  276.     fflush(fp);
  277.     fclose(fp);
  278.  
  279. }
  280.  
  281.  
  282.  
  283. void finish_makefile()
  284. {
  285. /*
  286.     adds some standard stuff to the end of the makefile
  287. */
  288.  
  289.     printf(compile_command);
  290.  
  291. /* and the default binary target... */
  292.  
  293.     printf("$(TARGET):\t");
  294.     printf("%s", (objs ? "$(OBJS) " : ""));
  295.     printf("%s", (srcs ? "$(SRCS) " : ""));
  296.     printf("%s", (hdrs ? "$(HDRS)\n" : "\n"));
  297.     
  298.     if (lengthcheck()< 50 ){
  299.         printf("%s", link_line);
  300.         printf("# %s", link2_line);
  301.     }
  302.     else {
  303.         printf("# %s", link_line);
  304.         printf("%s", link2_line);
  305.     }
  306. }
  307.  
  308.  
  309.  
  310. void get_file_modification_dates()
  311. {
  312. /*
  313.     do a 'stat' on each file in this directory, saving the last
  314.     modified date of each in the directory structure...
  315. */
  316.  
  317.     struct stat buffer;
  318.     register int i;
  319.  
  320.     for (i = 0; i < count ; i++)
  321.         if ((stat(directory[i].name, &buffer)) != 0)
  322.             {
  323.             fprintf(stderr,"%s: could not stat %s [%d] **\n",
  324.                 pgm, directory[i].name, errno);
  325.             exit(errno);
  326.             }
  327.         else
  328.             {
  329.             directory[i].time = buffer.st_mtime;
  330.             }
  331. }
  332.  
  333.  
  334.  
  335. void figure_out_includes(int index, int cnt)
  336. {
  337. /*
  338.         read the specified file, get all the files that this fellow
  339.     includes, then change the 'time' of the file entry in the
  340.     'directory' structure based on the times of the files it includes.
  341.     'cnt' is the nesting depth that we're currently at (for verbose
  342.     output and other I/O miscellany).
  343. */
  344.  
  345.     FILE *thefile;
  346.     char buffer[SLEN];
  347.     int  findex, i;
  348.  
  349.     if (verbose)
  350.         if (cnt == 1)
  351.             printf("Checking file \"%s\"\n", directory[index].name);
  352.         else
  353.             {
  354.             for (i=0;i<cnt;i++)
  355.                 printf("  ");
  356.             printf("includes file \"%s\"\n", directory[index].name);
  357.             }
  358.  
  359.     if (cnt == 1 && makefile)
  360.         {
  361.         if (strlen(compile_command) > 0)
  362.             printf(compile_command);
  363.         if (suffix(".c", directory[index].name))
  364.             sprintf(compile_command, cc_line, directory[index].name);
  365.         else if (suffix(".asm", directory[index].name))
  366.             sprintf(compile_command, mc_line, directory[index].name);
  367.         }
  368.  
  369.     if (dependencies || (makefile && cnt > 1))
  370.         printf("%s%s ", directory[index].name, cnt == 1 ? ":" : "");
  371.     else if (makefile && cnt == 1)
  372.         {
  373.         strcpy(buffer, directory[index].name);
  374.         strcpy(strchr(buffer, '.'), ".obj");
  375.         printf("%s:\t%s ", buffer, directory[index].name);
  376.         }
  377.  
  378.     if (!verbose && !dependencies && !makefile && directory[index].checked)
  379.         return;
  380.  
  381.     if ((thefile = fopen(directory[index].name,"r")) == NULL)
  382.         {
  383.         fprintf(stderr,"%s: could not open file %s for reading [%d] !\n",
  384.             pgm, directory[index].name, errno);
  385.         exit(errno);
  386.         }
  387.  
  388. /*
  389.     okay, now let's loop through this thing and try 
  390.         to get all the #include lines...
  391. */
  392.  
  393.     while (fgets(buffer, SLEN, thefile) != NULL)
  394.         {
  395.         if (buffer[0] == '#') /* hmmm...a compiler directive... */
  396.             if ((findex = check_for_include(buffer)) != -1)
  397.                 {
  398.                 figure_out_includes(findex, cnt+1);
  399.                               /* recurse... */
  400.                 }
  401.         }
  402.  
  403.         directory[index].checked++;
  404.  
  405.         if (dependencies && cnt==1) printf("\n");
  406.  
  407.         (void) fclose(thefile);
  408. }
  409.  
  410.  
  411.  
  412. int check_for_include(char *line)
  413. {
  414. /*
  415.     Line is an m4 directive line - this routine figures out if it is
  416.     an 'include' line, and if so, what file is being included.  If the
  417.     file included is contained within this directory, then this routine
  418.     will return the index, otherwise it will return -1 if an error.
  419. */
  420.  
  421.     char *line_ptr, *word, *strtok();
  422.     int  i;
  423.  
  424.     line[0] = ' ';  /* remove the '#' */
  425.  
  426. /*
  427.     this first section is so we can have "# include" as well
  428.     as "#include" ... we simply get the first word token via
  429.     calls to 'strtok()'
  430. */
  431.  
  432.     line_ptr = (char *) line;    /* gets the address */
  433.  
  434.     if ((word = strtok(line_ptr," \t")) != NULL)
  435.         {
  436.         if (strcmp(word, "include") != 0)
  437.             return(-1);
  438.         }
  439.     else
  440.         return(-1);
  441.  
  442. /*
  443.     to get to here, it must be an include line and the internal strtok
  444.     pointer must be pointing at the filename surrounded by quotes or
  445.     '<>' characters... (note that the " in the strtok call will also
  446.     suffice to remove the quotes from the filename too)
  447. */
  448.  
  449.     if ((word = strtok(NULL, "\t \"")) != NULL)
  450.         {
  451.         if (word[0] == '<')
  452.             return(-1);
  453.         }
  454.     else
  455.         return(-1);
  456.  
  457. /*
  458.     to get to here, it must have included the file that is specified
  459.     as 'word' currently, and that file must be a specified file in
  460.     the local directory.
  461. */
  462.  
  463.     for (i=0; i < strlen(word); i++)
  464.         if (word[i] == '\\')
  465.             return(-1);
  466.  
  467. /*
  468.     now, finally, we know that 'word' must be a file in the
  469.     current directory, so we merely need to find it's index
  470.     into the directory structure of this program and return it!
  471. */
  472.  
  473.     for (i=0; i < count; i++)
  474.         if (strcmpi(word, directory[i].name) == 0)
  475.             return(i);
  476.  
  477. /* it wasn't in there??? */
  478.  
  479.     fprintf(stderr,"%s: %s not in directory.\n",
  480.             pgm, word);
  481.     return(-1);
  482. }
  483.  
  484.  
  485.  
  486. int read_directory(char *buffer)
  487. {
  488. /*
  489.     return the next name in the directory... returns zero when
  490.     we're out of entries.
  491. */
  492.  
  493.     if (findnext(&dp) == 0)
  494.         {
  495.         strcpy(buffer, strlwr(dp.ff_name));
  496.         return(1);
  497.         }
  498.     
  499.     return(0);
  500. }
  501.  
  502.  
  503.  
  504. int suffix(char *sf, char *string)
  505. {
  506. /* returns true iff the suffix of 'string' is 'sf' */
  507.  
  508.     register int i, j;
  509.  
  510.     i = strlen(string);
  511.     j = strlen(sf);
  512.  
  513.     while (string[i] == sf[j] && j > 0)
  514.         {
  515.         i--;
  516.         j--;
  517.         }
  518.  
  519.     return(sf[0] == string[i] && j == 0);
  520. }
  521.  
  522.  
  523.  
  524. int compare(struct dir_rec *a, struct dir_rec *b)
  525. {
  526. /* strcmp on name field (for sort routine) */
  527.  
  528.     return( strcmp(a->name, b->name));
  529. }
  530.  
  531. int
  532. dosvers()
  533. {
  534.     union REGS REG;
  535.     REG.h.ah = 0x30;
  536.     int86(0x21, ®, ®);
  537.     return(REG.h.al);
  538. }
  539. int
  540. lengthcheck()
  541. {
  542.     struct stat statbuf;
  543.     int h, linklength;
  544.  
  545.     if ((h = open("linkfile",O_RDONLY)) == -1){
  546.         fprintf(stderr,"Cannot open linkfile; exiting\n");
  547.         exit(1);
  548.     }
  549.     if (stat("linkfile", &statbuf) == -1){
  550.         fprintf(stderr,"Cannot stat linkfile; exiting\n");
  551.         exit(1);
  552.     }
  553.     linklength = statbuf.st_size;
  554.     close(h);
  555.     return(linklength);
  556. }
  557.     
  558.     
  559.     
  560.