home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / SASC6571.LZX / extras / mkmk / gensmake.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-24  |  8.1 KB  |  320 lines

  1. /****************************************************/
  2. /*                                                  */
  3. /* Copyright (c) 1993 SAS Institute, Inc.           */
  4. /*                                                  */
  5. /* Support: walker                                  */
  6. /* Script:  mkmkam                                  */
  7. /* Date:    07/12/93                                */
  8. /*                                                  */
  9. /****************************************************/
  10. #include "MKMK.h"
  11. #include "time.h"
  12.  
  13. #define MAXLINELEN 77   // Maximum line size (not counting backslash)
  14.  
  15. static const char verstring[] = "$VER: MKMK " TOOLVER TOOLDATE;
  16.  
  17. /* File types */
  18. #define FT_UNK -1  // Unknown
  19. #define FT_C    0  // C source file
  20. #define FT_CXX  1  // C++ source file
  21. #define FT_ASM  2  // Assembler source file
  22. #define FT_H    3  // Header file
  23.  
  24. static const struct SUFFIXES
  25. {
  26.    char suffix[5];
  27.    char val;
  28. } suffixes[] =
  29. {
  30.    {".a",   FT_ASM},
  31.    {".asm", FT_ASM},
  32.    {".c",   FT_C},
  33.    {".cc",  FT_CXX},
  34.    {".cpp", FT_CXX},
  35.    {".cxx", FT_CXX},
  36.    {".h",   FT_H},
  37.    {".s",   FT_ASM},
  38. };
  39. #define NUMSUFFIXES (sizeof(suffixes)/sizeof(struct SUFFIXES))
  40.  
  41. /* return the file type (as defined above) for a given source file */
  42. int filetype(char *name)
  43. {
  44.    int i, j;
  45.    name = suffix(name);
  46.  
  47.    for(i=0; i<NUMSUFFIXES; i++)
  48.    {
  49.       j = stricmp(name, (char *)suffixes[i].suffix);
  50.       if(j == 0) return suffixes[i].val;
  51.    }
  52.    return FT_UNK;
  53. }
  54.  
  55. /* Return the suffix (portion after the '.') for a source file */
  56. /* Note that no memory is allocated, the return pointer points */
  57. /* =into= the argument string.                                 */
  58. char *suffix(char *s)
  59. {
  60.    char *p;
  61.    for(p=s+strlen(s); p>s && *p != '.'; p--);
  62.    return p;
  63. }
  64.  
  65. /* Return the prefix (portion before the '.') for a source file. */
  66. /* This function DOES allocate memory to copy the prefix into.   */
  67. char *prefix(char *s)
  68. {
  69.    char c;
  70.    char *p = suffix(s);
  71.    if(p != s)
  72.    {
  73.       c = *p;
  74.       *p = 0;
  75.       s = scopy(s);
  76.       *p = c;
  77.       return s;
  78.    }
  79.    else
  80.       return scopy("");
  81. }
  82.  
  83. /* Take a filename as input, and return the object filename */
  84. /* that would correspond to it.  I.E. take "foo.c" as input */
  85. /* and put "foo.o" out.  Note that this functions DOES      */
  86. /* allocate a new copy of the string.                       */
  87. char *objout(char *s)
  88. {
  89.    char *p;
  90.    char *t;
  91.    long l;
  92.    p = suffix(s);
  93.    if(*p != '.') return NULL;
  94.    t = malloc((unsigned long)p-(unsigned long)s+3);
  95.    if(!t) panic("No Memory!");
  96.    l = (unsigned long)p - (unsigned long)s;
  97.    memcpy(t,s,l);
  98.    strcpy(t+l, ".o");
  99.    return t;
  100. }
  101.  
  102. /* Expand file dependancies */
  103. /* We copy the dependancies of all our children into ourself. */
  104. /* If the dependancy is already there, nothing will be added. */
  105. /* Otherwise, it gets added onto the end and fd->ndirect gets */
  106. /* bumped.  When we get there, that dependancy will also be   */
  107. /* expanded.  The result is that all dependancies, no matter  */
  108. /* how far removed, end up on the list for fd.                */
  109.  
  110. void ExpandDeps(struct FileDesc *fd)
  111. {
  112.    int i, j;
  113.    for(i=0; i<fd->ndirect; i++)
  114.    {
  115.       for(j=0; j<fd->Direct[i]->ndirect; j++)
  116.       {
  117.          AddDep(fd, fd->Direct[i]->Direct[j]);
  118.       }
  119.    }
  120. }
  121.  
  122. #define HEADER_COMMENT \
  123. "#\n" \
  124. "# Makefile automatically generated by MKMK V" TOOLVER "\n" \
  125. "# %s" \
  126. "#\n\n"
  127.  
  128. char header_comment[sizeof(HEADER_COMMENT)+26];
  129.  
  130. /* All data has been accumulated;  generate the smakefile */
  131. void GenSmake(FileList *fl)
  132. {
  133.    BPTR fp;
  134.    struct FileDesc *fd;
  135.    char *p;
  136.    int i, j, ft;
  137.    int tmplen, curlen, indent;
  138.    char filename[100];
  139.    long t;
  140.    time(&t);
  141.  
  142.    chkabort();
  143.  
  144.    strcpy(filename, makefile);
  145.  
  146.    if(!force)
  147.    {
  148.       for(i=0; i<100; i++)
  149.       {
  150.          fp = Lock(filename, SHARED_LOCK);
  151.          UnLock(fp);
  152.          if(!fp) break;
  153.          mysprintf(filename, "%s.%02.2ld", makefile, i);
  154.       }
  155.       if(fp)
  156.          panic("Can't determine name for output file!\n");
  157.    }
  158.  
  159.    if(!(fp = Open(filename, MODE_NEWFILE)))
  160.    {
  161.       myfprintf(out, "Can't open output file \"%s\"!\n", filename);
  162.       panic(NULL);
  163.    }
  164.  
  165.    myfprintf(out, "Writing file \"%s\"...", filename);
  166.  
  167.    myfprintf(fp, HEADER_COMMENT, asctime(localtime(&t)));
  168.  
  169.    myfprintf(fp, "OBJS=");
  170.    curlen = indent = 5;
  171.  
  172.    // Put out the list of object files
  173.    for(fd=fl->head; fd; fd=fd->next)
  174.    {
  175.       ft = filetype(fd->name);
  176.       if(ft == FT_C || ft == FT_CXX || ft == FT_ASM)
  177.       {
  178.          if(p = objout(fd->name))
  179.          {
  180.             tmplen = strlen(p) + 1;
  181.             if(curlen + tmplen > MAXLINELEN)
  182.             {
  183.                // Over MAXLINELEN bytes, continue on the next line
  184.                myfprintf(fp, " \\\n");
  185.                for(j=0; j<indent; j++) FPutC(fp, ' ');
  186.                curlen = indent + tmplen;
  187.             }
  188.             else
  189.                curlen += tmplen;
  190.             myfprintf(fp, " %s", p);
  191.                
  192.             /* The first file named will name the project */
  193.             if(target == NULL) target = prefix(p);
  194.  
  195.             free(p);
  196.          }
  197.       }
  198.       else if(ft == FT_UNK)
  199.       {
  200.          /* It's not a file that produces an object file. */
  201.          /* we don't really know what it is, but add it   */
  202.          /* to the dependancy list anyway.  It might be   */
  203.          /* a library or .o file, for example.            */
  204.          myfprintf(fp, " %s", fd->name);
  205.       }
  206.    }
  207.  
  208.    if(!target) target = "Project";
  209.  
  210.    /* Put out the linker command */
  211.    myfprintf(fp, "\n\n%s: $(OBJS)\n   sc link to %s with <<\n$(OBJS)\n<\n\n",
  212.       target, target);
  213.  
  214.    /* Put out the individual file dependancy lists */
  215.    for(fd=fl->head; fd; fd=fd->next)
  216.    {
  217.       ft = filetype(fd->name);
  218.       if(ft == FT_C || ft == FT_CXX || ft == FT_ASM)
  219.       {
  220.          if(!(p = objout(fd->name))) break;
  221.  
  222.          myfprintf(fp, "%s: %s", p, fd->name);
  223.          indent = strlen(p) + 1;
  224.          curlen = indent + strlen(fd->name) + 1;
  225.          free(p);
  226.  
  227.          /* Expand the dependancies of the current file.  This will  */
  228.          /* copy all second, third, .... nth level dependancies into */
  229.          /* the current file descriptor.                             */
  230.          ExpandDeps(fd);
  231.  
  232.          for(i=0; i<fd->ndirect; i++)
  233.          {
  234.             tmplen = strlen(fd->Direct[i]->name) + 1;
  235.             if(curlen + tmplen > MAXLINELEN)
  236.             {
  237.                /* Over MAXLINELEN bytes, continue on a new line */
  238.                myfprintf(fp, " \\\n");
  239.                for(j=0; j<indent; j++) FPutC(fp, ' ');
  240.                curlen = indent + tmplen;
  241.             }
  242.             else
  243.                curlen += tmplen;
  244.             myfprintf(fp, " %s", fd->Direct[i]->name);
  245.          }
  246.          myfprintf(fp, "\n");
  247.       }
  248.       myfprintf(fp, "\n");
  249.    }
  250.  
  251.    Close(fp);   
  252.  
  253.    myfprintf(out, "Done\n");
  254.  
  255.    makeicon(filename);
  256. }
  257.  
  258. #define DEFROOT "sc:icons/def_"
  259.  
  260. //Copy the correct .info file for a given filename
  261. void makeicon(char *name)
  262. {
  263.    int i, len;
  264.    char *xname;
  265.    struct Library *IconBase;
  266.    char data[300];
  267.    struct DiskObject *dobj;
  268.  
  269.    if(!(IconBase = OpenLibrary("icon.library",0)))
  270.       return;
  271.  
  272.    len = strlen(name);
  273.    if(len > sizeof(data)-1) return;
  274.    memcpy(data, name, len+1);
  275.  
  276.    if(iconexists(data)) goto doexit;
  277.  
  278.    for(i=len-1; i>=0; i--)
  279.       if(name[i] == '.' || name[i] == '/' || name[i] == ':')
  280.          break;
  281.  
  282.    /* If no '.', i is -1, which means use the whole name */
  283.  
  284.    xname = name + (i+1);
  285.  
  286.    // xname now points to the extension
  287.    if(!stricmp(xname, "info"))
  288.       goto doexit;  // Don't do icons for .info files!
  289.  
  290.    strcpy(data, DEFROOT);
  291.    strcpy(data + strlen(DEFROOT), xname);
  292.  
  293.    if(!iconexists(data))
  294.       strcpy(data, "sc:icons/def_smakefile");
  295.  
  296.    if(!(dobj = GetDiskObject(data))) goto doexit;  // hmm... bad icon?
  297.    PutDiskObject(name, dobj);
  298.    FreeDiskObject(dobj);
  299. doexit:
  300.    CloseLibrary(IconBase);
  301.    return;
  302. }
  303.  
  304. // Determine if an icon already exists for the name
  305. int iconexists(char *name)
  306. {
  307.    BPTR lock;
  308.    char fullname[256];
  309.    int len;
  310.  
  311.    len = strlen(name);
  312.    if(len>sizeof(fullname)-6) return(-1);
  313.    memcpy(fullname, name, len);
  314.    memcpy(fullname+len, ".info", 6);
  315.  
  316.    if(lock=Lock(fullname, SHARED_LOCK)) UnLock(lock);
  317.  
  318.    return(lock != NULL);
  319. }
  320.