Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
make_depend.cxx
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 
00037 /*
00038  ****************************************************************************
00039  *                              Makedepend
00040  ****************************************************************************
00041  *
00042  *      The is a compiler tool that generates and maintains Makefile
00043  *      dependency information in a file called a Makedepend file.
00044  *      The idea is that some dependencies change over time and the 
00045  *      maintainer of the source code may not recognize the changes
00046  *      but would still like to have the dependency information.
00047  *
00048  *      For example, a makefile will know about FOO.o depending
00049  *      upon FOO.c but it is much harder to write down the web
00050  *      of dependencies for every file included by FOO.c .
00051  *
00052  *      Any tool that links with libcmplrs can call routines from
00053  *      here to manage/update dependency information as it is discovered.
00054  *      The entry points are:
00055  *
00056  *              MDopen          -- begin collecting dependency info for 
00057  *                                 one specified target and one tool.
00058  *              MDupdate        -- add new dependencies for target.
00059  *
00060  *              MDclose         -- process Makedepend file updating
00061  *                                 with new dependency information.
00062  *
00063  *      All valid Makedepend lines look like:
00064  *
00065  *              target : dependency list #:tool\n
00066  *         or
00067  *              target : dependency list \n
00068  *         or
00069  *              blanks \n
00070  *         or
00071  *              # comment \n
00072  *      
00073  ****************************************************************************
00074  *
00075  *      NOTE 1: The Makedepend file is locked only during MDclose.  So 
00076  *              parallel tools do not interfere with each other except
00077  *              if they both call MDclose at the same time, in which case
00078  *              file locking serializes access to the Makedepend file.
00079  *
00080  *      NOTE 2: Locking over NFS is very often broken.  There is some
00081  *              belief that the way we do locking, here, is inherently
00082  *              unstable and will often be broken.  If I could figure
00083  *              out how to append/grow the Makedepend file while it is
00084  *              mmap-ed, without doing using this hack of re-opening 
00085  *              it for append access, we could make this more reliable.
00086  *
00087  ****************************************************************************
00088  */
00089 
00090 #include "cmplrs/make_depend.h"
00091 
00092 #include <ctype.h>
00093 #include <errno.h>
00094 #include <fcntl.h>
00095 #include <stdio.h>
00096 #include "x_stdio.h" // for fdopen()
00097 #include <stdlib.h>
00098 #include <string.h>
00099 #include "x_string.h" // for memccpy(), strdup()
00100 #include <unistd.h>
00101 #include <sys/mman.h>
00102 #include <sys/stat.h>
00103 
00104 /*
00105  *      Debugging macros
00106  */
00107 #if  MD_DEBUG
00108 #define ENTER(s)  printf("ENTER: %s\n",s);
00109 #define EXIT(s)   printf("EXIT : %s\n",s);
00110 #define LOG(s)    printf s ;
00111 #else
00112 #define ENTER(s)  
00113 #define EXIT(s)  
00114 #define LOG(s)  
00115 #endif
00116 
00117 
00118 /*
00119  * Compute initial number of free entries from table size, and initial table
00120  * size estimate from number of entries.
00121  */
00122 #define FREECOUNT(x)    ((x) - (x) / 4)
00123 #define TABLESIZE(n)    ((n) + (n) / 3)
00124 #define INITIALSIZE     (1 << 8)
00125 #define INITSTABSIZE    (0x40000) 
00126 
00127 /*
00128  * We assume that strings will never be longer than this.
00129  * The reason for making this assumption is so that we 
00130  * don't have to scan strings to find out their length
00131  * within the functin MDstrcpy.
00132  */
00133 #define MAXSTRINGLEN    512
00134 
00135 char scratch[80];
00136 
00137 typedef struct dependency Dependency;
00138 
00139 struct dependency {
00140         char            *name;          /* file on which target depends */
00141         Dependency      *next;          /* hash collision linkage */
00142 };
00143 
00144 struct mdrule {
00145         char            *toolname;      /* name of language processor */
00146         char            *filename;      /* name of make-dependencies file */
00147         char            *target;        /* make rule left-hand side */
00148         void            (*error)(char*,...);    /* error reporting function */
00149         unsigned int    entries;        /* number of active entries */
00150         unsigned int    freecount;      /* number of free hash table entries */
00151         unsigned int    hashmask;       /* hash mask, i.e. (table size - 1) */
00152         Dependency      *table;         /* dynamically allocated hash table */
00153         char            *stab;          /* dynamically allocated string table*/
00154         char            *stabcur;       /* next free location in stab   */
00155         char            *stabmax;       /* last byte of stab + 1        */
00156 };
00157 
00158 
00159 typedef struct  mdfile {
00160         int     f;              /* dependency file      */
00161         char*   filename;       /* filename             */
00162         char*   base;           /* map base, if mapped  */
00163         char*   limit;          /* map limit, if mapped */
00164         int     size;           /* map size             */
00165         struct stat stb;        /* stat information     */
00166         } MDfile_t;
00167 
00168 /*
00169  * MDfile_init
00170  *
00171  * Initialize a variable of type MDfile.
00172  */
00173 static
00174 void
00175 MDfile_init ( MDfile_t *m ) {
00176         m->f            = 0;
00177         m->filename     = "";
00178         m->base         = 0;
00179         m->limit        = 0;
00180         m->size         = 0;
00181         m->stb.st_size  = 0;
00182 }
00183         
00184 
00185 /*
00186  * MDtoolcmp
00187  *
00188  *
00189  * Compare a null terminated string (s) with a character array (tool)
00190  * holding the tool signature, terminated by blanks followed by a newline.
00191  *
00192  */
00193 static
00194 int     
00195 MDtoolcmp ( const char *tool, const char *s, int slen ) {
00196         char    *t;
00197         int     toollen;
00198         
00199         t = (char *)strpbrk(tool, " \n");       
00200         toollen = t-tool;
00201 
00202         if ( (t == 0) || (toollen != slen) )   {return -1;}
00203 
00204         return strncmp(tool,s,slen);
00205 }
00206 
00207 
00208 /*
00209  * MDtargcmp
00210  *
00211  *
00212  * Compare a null terminated string (s) with a character array (targ)
00213  * holding the target, terminated by blanks followed by a colon.
00214  *
00215  */
00216 static
00217 int     
00218 MDtargcmp ( const char *targ, const char *s, int slen ) {
00219         char    *t;
00220         int     targlen;
00221         
00222         t = (char *)strpbrk(targ,": "); 
00223         targlen = t-targ;
00224 
00225         if ( (t == 0) || (targlen != slen) )   {return -1;}
00226 
00227         return strncmp(targ,s,slen);
00228 }
00229 
00230 #if 0
00231 /*
00232  * MDstrcatdup
00233  *
00234  * Concatenates the two strings into a new, malloc'd string and
00235  * returns the pointer to the new string. 
00236  *
00237  */
00238 static
00239 char * MDstrcatdup ( const char *s1, const char *s2 ) {
00240         int s1_len, s2_len, targ_len;
00241         char *targ;
00242         s1_len  = strlen(s1);
00243         s2_len  = strlen(s2);
00244         targ_len= s1_len + s2_len;
00245         targ = (char*)malloc(targ_len);
00246         bcopy(s1,targ,s1_len);
00247         bcopy(s2,&targ[s1_len], s2_len);
00248         targ[targ_len]='\0';
00249         return targ;
00250 }
00251 #endif
00252 
00253 /*
00254  * MDnewstab
00255  *
00256  * In order to avoid lots of calls to malloc we do a single malloc
00257  * of INITSTABSIZE.
00258  *
00259  * If the string table overflows, instead of doing something cleaver,
00260  * we just allocate another table and never free the first string
00261  * table.  This is not a big deal as typically, this operation is
00262  * done once at the very end of a compile or link and so it doesn't
00263  * really matter if we free the space or not.  
00264  *
00265  */
00266 void
00267 MDnewstab(MDhandle h) 
00268 {
00269    h->stab      = (char *) malloc(INITSTABSIZE);
00270    h->stabcur   = h->stab;
00271    h->stabmax   = h->stab + INITSTABSIZE;
00272 }
00273 
00274 /*
00275  * MDstrcpy
00276  *
00277  * Copy a string into the stringtable, stab, and return pointer to the
00278  * copy of the string.  
00279  *
00280  * We make a copy of the string because the compilers (and other users
00281  * of this utility) can't guarantee that they don't touch the strings
00282  * that hold the dependency filenames passed into MDupdate.
00283  *
00284  */
00285 char *
00286 MDstrcpy(MDhandle h, char * src ) 
00287 { 
00288         char  *dest;
00289         int     freespace;
00290 
00291         if ( src == NULL ) { return NULL; }
00292 
00293         /*
00294          *  Will we overflow the table?  Get a new one if needed. 
00295          *  Note that we are assuming that all passed in strings
00296          *  are less than MAXSTRINGLEN bytes in length -- probably
00297          *  not a valid assumption.
00298          */
00299         freespace       = (h->stabmax - h->stabcur);
00300         if (freespace < MAXSTRINGLEN) {
00301                 MDnewstab(h);
00302                 freespace=(h->stabmax - h->stabcur);
00303         }
00304 
00305         /*
00306          *  Make a copy of the string into the string table
00307          */
00308         dest            = h->stabcur;
00309         h->stabcur      = (char *)ux_memccpy(h->stabcur, src, '\0', freespace);
00310         if ( h->stabcur == NULL ) { 
00311                 /* 
00312                  *  We're screwed if the string length is 
00313                  *  longer than the whole table 
00314                  */
00315                 h->error("String table overflow in MDupdate\n", h->filename);
00316                 exit(1);
00317         }
00318 
00319         return dest;
00320 }
00321 
00322 
00323 /*
00324  * Avoid accumulating common dependency suffixes (.h, .a, .o) in the least
00325  * significant bits of the hash function.  We don't worry about wasted time
00326  * accumulating the common directory prefixes $ROOT/usr/{include,lib}.
00327  */
00328 static Dependency *
00329 MDhash(MDhandle h, char *s)
00330 {
00331         int len;
00332         char *t;
00333         unsigned int v, c;
00334 
00335         len = strlen(s);
00336         t = s + len - 2;
00337         if (len > 2 && *t == '.' && (t[1] == 'h' || t[1] == 'a' || t[1] == 'o'))
00338                 *t = '\0';
00339         else
00340                 t = 0;
00341         for (v = 0; (c = *s) != 0; s++)
00342                 v += (v << 1) ^ c;
00343         if (t)
00344                 *t = '.';
00345         return &h->table[v & h->hashmask];
00346 }
00347 
00348 /*
00349  * Look for a dependency in h, returning a pointer to a free hash table entry
00350  * if dependency is not found.  Probe linearly in case of collision, but link
00351  * colliding entries so future probes are faster.
00352  */
00353 static Dependency *
00354 MDlookup(MDhandle h, char *dependency)
00355 {
00356         Dependency *d, *prevd;
00357 
00358         for (d = MDhash(h, dependency); d->name; d = d->next) {
00359                 if (!strcmp(d->name, dependency))
00360                         break;
00361                 if (d->next == 0) {
00362                         prevd = d;
00363                         do {
00364                                 if (++d > &h->table[h->hashmask])
00365                                         d = &h->table[0];
00366                         } while (d->name);
00367                         prevd->next = d;
00368                         break;
00369                 }
00370         }
00371         return d;
00372 }
00373 
00374 /*
00375  * Grow the table by doubling its size (does not assume freecount is zero).
00376  */
00377 static void
00378 MDgrow(MDhandle h)
00379 {
00380         int n, m;
00381         Dependency *table, *oldtable;
00382         Dependency *d, *e;
00383 
00384         n = h->hashmask + 1;
00385         m = 2 * n;
00386         table = (Dependency *) calloc(m, sizeof *h->table);
00387         if (table == 0) {
00388                 h->error("can't reallocate memory for %s update", h->filename);
00389                 exit(1);
00390         }
00391 
00392         h->freecount += FREECOUNT(n);
00393         h->hashmask = m - 1;
00394         oldtable = h->table;
00395         h->table = table;
00396         for (d = oldtable; --n >= 0; d++) {
00397                 if (d->name == 0)
00398                         continue;
00399                 e = MDlookup(h, d->name);
00400                 e->name = d->name;
00401         }
00402         free(oldtable);
00403 }
00404 
00405 /*
00406  * Allocate a table for INITIALSIZE entries.
00407  */
00408 
00409 extern "C" {
00410 
00411 MDhandle
00412 MDopen(char *toolname, char *filename, char *target, void (*error)(char*,...))
00413 {
00414         MDhandle h;
00415         Dependency *table;
00416 
00417         h = (mdrule *) malloc(sizeof *h);
00418         MDnewstab(h); 
00419         table = (Dependency *) calloc(INITIALSIZE, sizeof *h->table);
00420         if (h == 0 || table == 0) {
00421                 error("can't allocate memory for %s update", filename);
00422                 if (h)
00423                         free(h);
00424                 if (table)
00425                         free(table);
00426                 return 0;
00427         }
00428 
00429         h->toolname = MDstrcpy(h,toolname);
00430         h->filename = MDstrcpy(h,filename);
00431         h->target   = MDstrcpy(h,target  );
00432         h->error = error;
00433         h->entries = 0;
00434         h->freecount = FREECOUNT(INITIALSIZE);
00435         h->hashmask = INITIALSIZE - 1;
00436         h->table = table;
00437 
00438         return h;
00439 }
00440 
00441 }  /* extern "C" */
00442 
00443 
00444 /*
00445  * Add a dependency to h's rule.
00446  */
00447 void
00448 MDupdate(MDhandle h, char *dependency)
00449 {
00450         Dependency *d;
00451 
00452         if (h == 0)
00453                 return;
00454         d = MDlookup(h, dependency);
00455         if (d->name)
00456                 return;
00457         if (h->freecount == 0) {
00458                 MDgrow(h);
00459                 d = MDlookup(h, dependency);
00460         }
00461 
00462         d->name = MDstrcpy(h,dependency);
00463         --h->freecount;
00464         h->entries++;
00465 }
00466 
00467 
00468 /*
00469  *      MDparseline
00470  *
00471  *      Examines a line in a dependecy file, sets pointer to the 
00472  *      target, and tool, and returns a pointer to the next line in the file.
00473  *      Any errors return a NULL pointer.
00474  *
00475  *      [Note: these are NOT null terminated strings.]
00476  *
00477  *      All makedepend lines look like:
00478  *
00479  *              target : dependency list #:tool\n
00480  *      or
00481  *              target : dependency list \n
00482  *      or
00483  *              blanks \n
00484  *      or
00485  *              # comment \n
00486  *      
00487  *      And after successsful parsing, we return pointers as follows:
00488  *
00489  *              target : dependency list #:tool\n
00490  *              ^                          ^     ^
00491  *      targ ---+                          |     |
00492  *      tool ------------------------------+     |
00493  *      nextline --------------------------------+
00494  *                              
00495  *
00496  *              target : dependency list \n
00497  *              ^                          ^
00498  *      targ ---+                          |
00499  *      tool = NULL                        |
00500  *      nextline --------------------------+
00501  *                              
00502  *
00503  *              blanks \n
00504  *                       ^
00505  *      targ = NULL      |
00506  *      tool = NULL      |
00507  *      nextline --------+
00508  *                              
00509  *              # comment \n
00510  *                          ^
00511  *      targ = NULL         |
00512  *      tool = NULL         |
00513  *      nextline -----------+
00514  *                              
00515  *
00516  *      For any error, we return pointers as follows:
00517  *      targ = <invalid>
00518  *      tool = <invalid>
00519  *      nextline = NULL
00520  *
00521  *
00522  */
00523 #define SKIP_BLANKS     while ( next<limit && *next==' ' ) {next++;} 
00524 #define SKIP_TO_EOL     while ( next<limit && *next!='\n') {next++;} 
00525 #define IS_EOL          (*next=='\n')
00526 #define IS_EOF          (next>=limit)
00527 #define SCAN_FOR(c)     while ( next<limit && *next!=c && *next!='\n') {next++;}
00528 
00529 static
00530 char *
00531 MDparseline ( char* line, char *limit, char **targ, char **tool ) {
00532         char *next;
00533 
00534         /* init */
00535         *targ   = 0;
00536         *tool   = 0;
00537         next    = line;
00538 
00539         /*
00540          *----------------------------------------------------------------
00541          *      Process blank and/or comment lines
00542          *----------------------------------------------------------------
00543          */
00544 
00545         /* skip leading blanks */
00546         SKIP_BLANKS; if ( IS_EOF ) { return 0; }
00547 
00548         /* if this is a blank line then return pointer to nextline */
00549         if ( IS_EOL ) { return ++next; }
00550                 
00551         /* if this is a comment line, then return pointer to nextline */
00552         if ( *next == '#') { 
00553                 SKIP_TO_EOL;
00554                 if ( IS_EOF ) { return 0; }
00555                 if ( IS_EOL ) { return ++next; }
00556         }
00557         
00558         /*
00559          *----------------------------------------------------------------
00560          *      Process actual dependency line
00561          *----------------------------------------------------------------
00562          */
00563 
00564         /* target is always the beginning of the line   */
00565         *targ = next;
00566 
00567         /* scan for the ':' to find the dependency list */
00568         SCAN_FOR(':'); if ( *next != ':' ) return 0;
00569 
00570         /* skip ':' and trailing blanks */
00571         next++; SKIP_BLANKS;
00572 
00573         /* scan for the optional '#:' to find the tool signature */
00574         SCAN_FOR('#'); if ( IS_EOF ) { return 0; }
00575 
00576         /* If we got to the end of line, the tool signature was not present */
00577         if ( IS_EOL ) { return ++next;}
00578 
00579         /* we found '#' so the next character better be ':' */
00580         if ( *++next != ':' ) return 0;
00581 
00582         /* we found ':', so skip over it and any trailing blanks */
00583         next++;
00584         SKIP_BLANKS; if ( IS_EOF ) { return 0; }
00585 
00586         /* we should be pointing at the toolname now; if there isn't
00587          * one specified, we'll treat it as if there was no tool
00588          * signature at all
00589          */
00590         if ( IS_EOL ) { return ++next; }
00591 
00592         /* we must of found the toolname */
00593         *tool = next;
00594 
00595         /* scan for newline after tool */
00596         SKIP_TO_EOL;
00597         if ( IS_EOF ) { return 0; }
00598 
00599         /* skip over '\n'  and return pointer to next line */
00600         return ++next;
00601 
00602 }
00603 
00604 /*
00605  *      MDclose 
00606  *
00607  *      This is where all the work is actually done...
00608  *      Open, Lock, and Map the dependency file.  Scan for this target and 
00609  *      "remove" it. Write the target and dependencies at the end of the file.
00610  *
00611  *      WARNING 1:
00612  *              Be extremely careful whenever you change the order
00613  *              in which this code maps/locks/closes the dependecy
00614  *              file; because it may change the locking behavior.
00615  *
00616  *      WARNING 2:
00617  *              File-locking on NFS is often broken, which can lead
00618  *              to corrupted makedepend files.  This should be fixable
00619  *              if I could figure out how to mmap the Makedepend file
00620  *              and grow it, without doing this goofy re-open for append.
00621  *
00622  *      WARNING 3:
00623  *              Make/pmake/smake   do not use file locking on include
00624  *              files.  Because of this, it is possible for make to
00625  *              read a dependency file in the middle of an update and
00626  *              so look corrupted.
00627  *      
00628  *
00629  */
00630 #define ERR(x)  { h->error x ; goto cleanup; }
00631 void
00632 MDclose(MDhandle h, char *target)
00633 {
00634         struct flock l;
00635         MDfile_t md;            /* current makedepend file              */
00636         FILE    *file;          /* current makedepend file              */
00637 
00638         char    *line;          /* line to be parsed                    */
00639         char    *nextline;      /* next line to be parsed               */
00640         char    *targ;          /* target of the line being parsed      */
00641         char    *tool;          /* tool signature of line being parsed  */
00642         Dependency *d;          /* dependency to write out              */
00643         int     targetlen;      /* length of target string              */
00644         int     toolnamelen;    /* length of toolname string            */
00645         int     found=0;        /* found a target match                 */
00646         int     linelen;        /* length of current line               */
00647         int     remaininglen;   /* remaining length of file             */
00648 
00649 
00650         ENTER("MDclose");
00651 
00652         /*
00653          **********************************************************************
00654          *      Is there work to be done?  
00655          *      If not, release resources and return.
00656          **********************************************************************
00657          */
00658         if (h == 0) return;
00659         if (h->entries == 0) goto relspace;
00660 
00661         /*
00662          **********************************************************************
00663          *      Decide which target to use.
00664          **********************************************************************
00665          */
00666         if (target == 0) target = h->target;
00667         targetlen = strlen(target);
00668 
00669         /*
00670          **********************************************************************
00671          *      Setup file handle information
00672          **********************************************************************
00673          */
00674         MDfile_init ( &md ); md.filename  = ux_strdup ( h->filename );
00675 
00676         /*
00677          **********************************************************************
00678          *      Open, lock, and stat the dependency file.
00679          **********************************************************************
00680          */
00681         LOG(("Opening %s\n",md.filename));
00682         md.f = open(md.filename, O_CREAT|O_RDWR, 0666); 
00683         if ( md.f < 0 ) ERR(("open (%s): %s", md.filename, strerror(errno)));
00684 
00685         l.l_type = F_WRLCK;
00686         l.l_whence = SEEK_SET;
00687         l.l_start = l.l_len = 0;
00688         if ( fcntl(md.f, F_SETLKW, &l) < 0 ) 
00689                 ERR(("fcntl (%s) : %s", md.filename, strerror(errno)));
00690         if ( fstat(md.f,&md.stb) < 0 )
00691                 ERR(("fstat (%s) : %s", md.filename, strerror(errno)));
00692         LOG(("Opening %s successful\n",md.filename));
00693 
00694         /*
00695          **********************************************************************
00696          *      Map the dependency file at base if it is non-empty.
00697          **********************************************************************
00698          */
00699         LOG(("Mapping %s\n",md.filename));
00700         md.base = md.limit = 0;
00701         if ( 0 < md.stb.st_size ) {
00702                 md.base = (char *) mmap ( 0, md.stb.st_size, PROT_READ|PROT_WRITE
00703                                 , MAP_SHARED, md.f, 0);
00704                 if ((long) md.base < 0) 
00705                         ERR(("mmap (%s): %s", md.filename, strerror(errno)));
00706                 md.size  = md.stb.st_size;
00707                 md.limit = md.base + md.size;
00708         }
00709         LOG(("Mapping %s successful \n",md.filename));
00710 
00711         /*
00712          **********************************************************************
00713          *      Scan the dependency file for the target  and tool signature. 
00714          *      
00715          **********************************************************************
00716          */
00717          nextline=0;
00718          found=0;
00719          toolnamelen = strlen(h->toolname);
00720          for ( line=md.base; line<md.limit; line=nextline ) {
00721                 nextline = MDparseline(line, md.limit, &targ, &tool); 
00722                 if ( 0 == nextline ) ERR(("%s: damaged file", md.filename));
00723 
00724                 /* if blank line then contine scanning */
00725                 if ( 0 == targ ) continue;
00726 
00727                 /* if it's our target and tool then stop the search */
00728                 if ( 0 == MDtargcmp(targ,target,targetlen) ) {
00729 
00730                         /* if no tool signature specified, then no match */
00731                         if ( 0 == tool ) { continue; }
00732 
00733                         /* is it the same tool signature? */
00734                         if (0 == MDtoolcmp(tool,h->toolname,toolnamelen)) {
00735                                 found = 1;
00736                                 break;
00737                         }
00738                 }
00739          }
00740 
00741         /*
00742          **********************************************************************
00743          *      If we found the target and tool signature, then remove it by 
00744          *      "sliding" the rest of the file down over the record we are 
00745          *      removing and then truncating the file.
00746          *
00747          *      target: dependency list#:tool\n target: dep.. \n
00748          *      ^                        ^      ^               ^
00749          *      +- line                  +-tool +- nextline     +- limit
00750          *
00751          **********************************************************************
00752          */
00753         if ( found ) {
00754                 LOG(("Found target=%s\n",target));
00755 
00756                 linelen         = nextline - line;
00757                 remaininglen    = md.limit - nextline;
00758                 memmove ( /* to */ line, /*from*/ nextline, remaininglen );
00759 
00760                 LOG(("Truncating %s by 0x%08x bytes\n",md.filename,linelen));
00761 
00762                 if ( 0 != ftruncate(md.f, (md.size-linelen) ) ) 
00763                    ERR(("ftruncate (%s): %s", md.filename, strerror(errno)));
00764         }       
00765 
00766 
00767         /*
00768          **********************************************************************
00769          *      Open the dependency file in append mode,
00770          *      write new record to end of new dependency file,
00771          *      and close the file.
00772          **********************************************************************
00773          */
00774         LOG(("Write final record to %s\n",md.filename));
00775         if ( 0 == (file = ux_fdopen(md.f,"a"))) 
00776                 ERR(("fdopen(%s): %s", md.filename, strerror(errno)));
00777 
00778         fprintf ( file, "%s:", target );
00779         for (d=&h->table[0]; d<= &h->table[h->hashmask]; d++) {
00780                 if (d->name) { fprintf( file, " %s", d->name ); }
00781         }
00782         if ( 0 > fprintf( file, " #:%s\n", h->toolname ) ) 
00783                 ERR(("fprintf(%s): %s", md.filename, strerror(errno)));
00784 
00785 cleanup:
00786         if ( file       != 0            ) { fclose(file); }
00787         if ( md.base    > (char*)0      ) { munmap(md.base, md.stb.st_size ); }
00788         if ( md.f       > 0             ) { close(md.f); }
00789 
00790 relspace:
00791         free(h->table);
00792         free(h->stab);
00793         free(h);
00794         EXIT("MDclose");
00795 }
00796 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines