Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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