00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
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"
00097 #include <stdlib.h>
00098 #include <string.h>
00099 #include "x_string.h"
00100 #include <unistd.h>
00101 #include <sys/mman.h>
00102 #include <sys/stat.h>
00103
00104
00105
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
00120
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
00129
00130
00131
00132
00133 #define MAXSTRINGLEN 512
00134
00135 char scratch[80];
00136
00137 typedef struct dependency Dependency;
00138
00139 struct dependency {
00140 char *name;
00141 Dependency *next;
00142 };
00143
00144 struct mdrule {
00145 char *toolname;
00146 char *filename;
00147 char *target;
00148 void (*error)(char*,...);
00149 unsigned int entries;
00150 unsigned int freecount;
00151 unsigned int hashmask;
00152 Dependency *table;
00153 char *stab;
00154 char *stabcur;
00155 char *stabmax;
00156 };
00157
00158
00159 typedef struct mdfile {
00160 int f;
00161 char* filename;
00162 char* base;
00163 char* limit;
00164 int size;
00165 struct stat stb;
00166 } MDfile_t;
00167
00168
00169
00170
00171
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
00187
00188
00189
00190
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
00210
00211
00212
00213
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
00233
00234
00235
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
00255
00256
00257
00258
00259
00260
00261
00262
00263
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
00276
00277
00278
00279
00280
00281
00282
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
00295
00296
00297
00298
00299 freespace = (h->stabmax - h->stabcur);
00300 if (freespace < MAXSTRINGLEN) {
00301 MDnewstab(h);
00302 freespace=(h->stabmax - h->stabcur);
00303 }
00304
00305
00306
00307
00308 dest = h->stabcur;
00309 h->stabcur = (char *)ux_memccpy(h->stabcur, src, '\0', freespace);
00310 if ( h->stabcur == NULL ) {
00311
00312
00313
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
00325
00326
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
00350
00351
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
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
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 }
00442
00443
00444
00445
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
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
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
00535 *targ = 0;
00536 *tool = 0;
00537 next = line;
00538
00539
00540
00541
00542
00543
00544
00545
00546 SKIP_BLANKS; if ( IS_EOF ) { return 0; }
00547
00548
00549 if ( IS_EOL ) { return ++next; }
00550
00551
00552 if ( *next == '#') {
00553 SKIP_TO_EOL;
00554 if ( IS_EOF ) { return 0; }
00555 if ( IS_EOL ) { return ++next; }
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565 *targ = next;
00566
00567
00568 SCAN_FOR(':'); if ( *next != ':' ) return 0;
00569
00570
00571 next++; SKIP_BLANKS;
00572
00573
00574 SCAN_FOR('#'); if ( IS_EOF ) { return 0; }
00575
00576
00577 if ( IS_EOL ) { return ++next;}
00578
00579
00580 if ( *++next != ':' ) return 0;
00581
00582
00583 next++;
00584 SKIP_BLANKS; if ( IS_EOF ) { return 0; }
00585
00586
00587
00588
00589
00590 if ( IS_EOL ) { return ++next; }
00591
00592
00593 *tool = next;
00594
00595
00596 SKIP_TO_EOL;
00597 if ( IS_EOF ) { return 0; }
00598
00599
00600 return ++next;
00601
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
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;
00636 FILE *file;
00637
00638 char *line;
00639 char *nextline;
00640 char *targ;
00641 char *tool;
00642 Dependency *d;
00643 int targetlen;
00644 int toolnamelen;
00645 int found=0;
00646 int linelen;
00647 int remaininglen;
00648
00649
00650 ENTER("MDclose");
00651
00652
00653
00654
00655
00656
00657
00658 if (h == 0) return;
00659 if (h->entries == 0) goto relspace;
00660
00661
00662
00663
00664
00665
00666 if (target == 0) target = h->target;
00667 targetlen = strlen(target);
00668
00669
00670
00671
00672
00673
00674 MDfile_init ( &md ); md.filename = ux_strdup ( h->filename );
00675
00676
00677
00678
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
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
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
00725 if ( 0 == targ ) continue;
00726
00727
00728 if ( 0 == MDtargcmp(targ,target,targetlen) ) {
00729
00730
00731 if ( 0 == tool ) { continue; }
00732
00733
00734 if (0 == MDtoolcmp(tool,h->toolname,toolnamelen)) {
00735 found = 1;
00736 break;
00737 }
00738 }
00739 }
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
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 ( line, 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
00770
00771
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