github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/ld/go.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // go-specific code shared across loaders (5l, 6l, 8l). 6 7 #include "l.h" 8 #include "../ld/lib.h" 9 10 // accumulate all type information from .6 files. 11 // check for inconsistencies. 12 13 // TODO: 14 // generate debugging section in binary. 15 // once the dust settles, try to move some code to 16 // libmach, so that other linkers and ar can share. 17 18 /* 19 * package import data 20 */ 21 typedef struct Import Import; 22 struct Import 23 { 24 Import *hash; // next in hash table 25 char *prefix; // "type", "var", "func", "const" 26 char *name; 27 char *def; 28 char *file; 29 }; 30 enum { 31 NIHASH = 1024 32 }; 33 static Import *ihash[NIHASH]; 34 static int nimport; 35 static void imported(char *pkg, char *import); 36 37 static int 38 hashstr(char *name) 39 { 40 int h; 41 char *cp; 42 43 h = 0; 44 for(cp = name; *cp; h += *cp++) 45 h *= 1119; 46 // not if(h < 0) h = ~h, because gcc 4.3 -O2 miscompiles it. 47 h &= 0xffffff; 48 return h; 49 } 50 51 static Import * 52 ilookup(char *name) 53 { 54 int h; 55 Import *x; 56 57 h = hashstr(name) % NIHASH; 58 for(x=ihash[h]; x; x=x->hash) 59 if(x->name[0] == name[0] && strcmp(x->name, name) == 0) 60 return x; 61 x = mal(sizeof *x); 62 x->name = estrdup(name); 63 x->hash = ihash[h]; 64 ihash[h] = x; 65 nimport++; 66 return x; 67 } 68 69 static void loadpkgdata(char*, char*, char*, int); 70 static void loadcgo(char*, char*, char*, int); 71 static int parsemethod(char**, char*, char**); 72 static int parsepkgdata(char*, char*, char**, char*, char**, char**, char**); 73 74 void 75 ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence) 76 { 77 char *data, *p0, *p1, *name; 78 79 if(debug['g']) 80 return; 81 82 if((int)len != len) { 83 fprint(2, "%s: too much pkg data in %s\n", argv0, filename); 84 if(debug['u']) 85 errorexit(); 86 return; 87 } 88 data = mal(len+1); 89 if(Bread(f, data, len) != len) { 90 fprint(2, "%s: short pkg read %s\n", argv0, filename); 91 if(debug['u']) 92 errorexit(); 93 return; 94 } 95 data[len] = '\0'; 96 97 // first \n$$ marks beginning of exports - skip rest of line 98 p0 = strstr(data, "\n$$"); 99 if(p0 == nil) { 100 if(debug['u'] && whence != ArchiveObj) { 101 fprint(2, "%s: cannot find export data in %s\n", argv0, filename); 102 errorexit(); 103 } 104 return; 105 } 106 p0 += 3; 107 while(*p0 != '\n' && *p0 != '\0') 108 p0++; 109 110 // second marks end of exports / beginning of local data 111 p1 = strstr(p0, "\n$$"); 112 if(p1 == nil) { 113 fprint(2, "%s: cannot find end of exports in %s\n", argv0, filename); 114 if(debug['u']) 115 errorexit(); 116 return; 117 } 118 while(p0 < p1 && (*p0 == ' ' || *p0 == '\t' || *p0 == '\n')) 119 p0++; 120 if(p0 < p1) { 121 if(strncmp(p0, "package ", 8) != 0) { 122 fprint(2, "%s: bad package section in %s - %s\n", argv0, filename, p0); 123 if(debug['u']) 124 errorexit(); 125 return; 126 } 127 p0 += 8; 128 while(p0 < p1 && (*p0 == ' ' || *p0 == '\t' || *p0 == '\n')) 129 p0++; 130 name = p0; 131 while(p0 < p1 && *p0 != ' ' && *p0 != '\t' && *p0 != '\n') 132 p0++; 133 if(debug['u'] && whence != ArchiveObj && 134 (p0+6 > p1 || memcmp(p0, " safe\n", 6) != 0)) { 135 fprint(2, "%s: load of unsafe package %s\n", argv0, filename); 136 nerrors++; 137 errorexit(); 138 } 139 if(p0 < p1) { 140 if(*p0 == '\n') 141 *p0++ = '\0'; 142 else { 143 *p0++ = '\0'; 144 while(p0 < p1 && *p0++ != '\n') 145 ; 146 } 147 } 148 if(strcmp(pkg, "main") == 0 && strcmp(name, "main") != 0) { 149 fprint(2, "%s: %s: not package main (package %s)\n", argv0, filename, name); 150 nerrors++; 151 errorexit(); 152 } 153 loadpkgdata(filename, pkg, p0, p1 - p0); 154 } 155 156 // The __.PKGDEF archive summary has no local types. 157 if(whence == Pkgdef) 158 return; 159 160 // local types begin where exports end. 161 // skip rest of line after $$ we found above 162 p0 = p1 + 3; 163 while(*p0 != '\n' && *p0 != '\0') 164 p0++; 165 166 // local types end at next \n$$. 167 p1 = strstr(p0, "\n$$"); 168 if(p1 == nil) { 169 fprint(2, "%s: cannot find end of local types in %s\n", argv0, filename); 170 if(debug['u']) 171 errorexit(); 172 return; 173 } 174 175 loadpkgdata(filename, pkg, p0, p1 - p0); 176 177 // look for cgo section 178 p0 = strstr(p1, "\n$$ // cgo"); 179 if(p0 != nil) { 180 p0 = strchr(p0+1, '\n'); 181 if(p0 == nil) { 182 fprint(2, "%s: found $$ // cgo but no newline in %s\n", argv0, filename); 183 if(debug['u']) 184 errorexit(); 185 return; 186 } 187 p1 = strstr(p0, "\n$$"); 188 if(p1 == nil) 189 p1 = strstr(p0, "\n!\n"); 190 if(p1 == nil) { 191 fprint(2, "%s: cannot find end of // cgo section in %s\n", argv0, filename); 192 if(debug['u']) 193 errorexit(); 194 return; 195 } 196 loadcgo(filename, pkg, p0 + 1, p1 - (p0+1)); 197 } 198 } 199 200 static void 201 loadpkgdata(char *file, char *pkg, char *data, int len) 202 { 203 char *p, *ep, *prefix, *name, *def; 204 Import *x; 205 206 file = estrdup(file); 207 p = data; 208 ep = data + len; 209 while(parsepkgdata(file, pkg, &p, ep, &prefix, &name, &def) > 0) { 210 x = ilookup(name); 211 if(x->prefix == nil) { 212 x->prefix = prefix; 213 x->def = estrdup(def); 214 x->file = file; 215 } else if(strcmp(x->prefix, prefix) != 0) { 216 fprint(2, "%s: conflicting definitions for %s\n", argv0, name); 217 fprint(2, "%s:\t%s %s ...\n", x->file, x->prefix, name); 218 fprint(2, "%s:\t%s %s ...\n", file, prefix, name); 219 nerrors++; 220 } else if(strcmp(x->def, def) != 0) { 221 fprint(2, "%s: conflicting definitions for %s\n", argv0, name); 222 fprint(2, "%s:\t%s %s %s\n", x->file, x->prefix, name, x->def); 223 fprint(2, "%s:\t%s %s %s\n", file, prefix, name, def); 224 nerrors++; 225 } 226 free(name); 227 free(def); 228 } 229 free(file); 230 } 231 232 // replace all "". with pkg. 233 char* 234 expandpkg(char *t0, char *pkg) 235 { 236 int n; 237 char *p; 238 char *w, *w0, *t; 239 240 n = 0; 241 for(p=t0; (p=strstr(p, "\"\".")) != nil; p+=3) 242 n++; 243 244 if(n == 0) 245 return estrdup(t0); 246 247 // use malloc, not mal, so that caller can free 248 w0 = malloc(strlen(t0) + strlen(pkg)*n); 249 if(w0 == nil) { 250 diag("out of memory"); 251 errorexit(); 252 } 253 w = w0; 254 for(p=t=t0; (p=strstr(p, "\"\".")) != nil; p=t) { 255 memmove(w, t, p - t); 256 w += p-t; 257 strcpy(w, pkg); 258 w += strlen(pkg); 259 t = p+2; 260 } 261 strcpy(w, t); 262 return w0; 263 } 264 265 static int 266 parsepkgdata(char *file, char *pkg, char **pp, char *ep, char **prefixp, char **namep, char **defp) 267 { 268 char *p, *prefix, *name, *def, *edef, *meth; 269 int n, inquote; 270 271 // skip white space 272 p = *pp; 273 loop: 274 while(p < ep && (*p == ' ' || *p == '\t' || *p == '\n')) 275 p++; 276 if(p == ep || strncmp(p, "$$\n", 3) == 0) 277 return 0; 278 279 // prefix: (var|type|func|const) 280 prefix = p; 281 if(p + 7 > ep) 282 return -1; 283 if(strncmp(p, "var ", 4) == 0) 284 p += 4; 285 else if(strncmp(p, "type ", 5) == 0) 286 p += 5; 287 else if(strncmp(p, "func ", 5) == 0) 288 p += 5; 289 else if(strncmp(p, "const ", 6) == 0) 290 p += 6; 291 else if(strncmp(p, "import ", 7) == 0) { 292 p += 7; 293 while(p < ep && *p != ' ') 294 p++; 295 p++; 296 name = p; 297 while(p < ep && *p != '\n') 298 p++; 299 if(p >= ep) { 300 fprint(2, "%s: %s: confused in import line\n", argv0, file); 301 nerrors++; 302 return -1; 303 } 304 *p++ = '\0'; 305 imported(pkg, name); 306 goto loop; 307 } 308 else { 309 fprint(2, "%s: %s: confused in pkg data near <<%.40s>>\n", argv0, file, prefix); 310 nerrors++; 311 return -1; 312 } 313 p[-1] = '\0'; 314 315 // name: a.b followed by space 316 name = p; 317 inquote = 0; 318 while(p < ep) { 319 if (*p == ' ' && !inquote) 320 break; 321 322 if(*p == '\\') 323 p++; 324 else if(*p == '"') 325 inquote = !inquote; 326 327 p++; 328 } 329 330 if(p >= ep) 331 return -1; 332 *p++ = '\0'; 333 334 // def: free form to new line 335 def = p; 336 while(p < ep && *p != '\n') 337 p++; 338 if(p >= ep) 339 return -1; 340 edef = p; 341 *p++ = '\0'; 342 343 // include methods on successive lines in def of named type 344 while(parsemethod(&p, ep, &meth) > 0) { 345 *edef++ = '\n'; // overwrites '\0' 346 if(edef+1 > meth) { 347 // We want to indent methods with a single \t. 348 // 6g puts at least one char of indent before all method defs, 349 // so there will be room for the \t. If the method def wasn't 350 // indented we could do something more complicated, 351 // but for now just diagnose the problem and assume 352 // 6g will keep indenting for us. 353 fprint(2, "%s: %s: expected methods to be indented %p %p %.10s\n", argv0, 354 file, edef, meth, meth); 355 nerrors++; 356 return -1; 357 } 358 *edef++ = '\t'; 359 n = strlen(meth); 360 memmove(edef, meth, n); 361 edef += n; 362 } 363 364 name = expandpkg(name, pkg); 365 def = expandpkg(def, pkg); 366 367 // done 368 *pp = p; 369 *prefixp = prefix; 370 *namep = name; 371 *defp = def; 372 return 1; 373 } 374 375 static int 376 parsemethod(char **pp, char *ep, char **methp) 377 { 378 char *p; 379 380 // skip white space 381 p = *pp; 382 while(p < ep && (*p == ' ' || *p == '\t')) 383 p++; 384 if(p == ep) 385 return 0; 386 387 // might be a comment about the method 388 if(p + 2 < ep && strncmp(p, "//", 2) == 0) 389 goto useline; 390 391 // if it says "func (", it's a method 392 if(p + 6 < ep && strncmp(p, "func (", 6) == 0) 393 goto useline; 394 return 0; 395 396 useline: 397 // definition to end of line 398 *methp = p; 399 while(p < ep && *p != '\n') 400 p++; 401 if(p >= ep) { 402 fprint(2, "%s: lost end of line in method definition\n", argv0); 403 *pp = ep; 404 return -1; 405 } 406 *p++ = '\0'; 407 *pp = p; 408 return 1; 409 } 410 411 static void 412 loadcgo(char *file, char *pkg, char *p, int n) 413 { 414 char *pend, *next, *p0, *q; 415 char *f[10], *local, *remote, *lib; 416 int nf; 417 Sym *s; 418 419 USED(file); 420 pend = p + n; 421 p0 = nil; 422 for(; p<pend; p=next) { 423 next = strchr(p, '\n'); 424 if(next == nil) 425 next = ""; 426 else 427 *next++ = '\0'; 428 429 free(p0); 430 p0 = estrdup(p); // save for error message 431 nf = tokenize(p, f, nelem(f)); 432 433 if(strcmp(f[0], "cgo_import_dynamic") == 0) { 434 if(nf < 2 || nf > 4) 435 goto err; 436 437 local = f[1]; 438 remote = local; 439 if(nf > 2) 440 remote = f[2]; 441 lib = ""; 442 if(nf > 3) 443 lib = f[3]; 444 445 if(debug['d']) { 446 fprint(2, "%s: %s: cannot use dynamic imports with -d flag\n", argv0, file); 447 nerrors++; 448 return; 449 } 450 451 if(strcmp(local, "_") == 0 && strcmp(remote, "_") == 0) { 452 // allow #pragma dynimport _ _ "foo.so" 453 // to force a link of foo.so. 454 havedynamic = 1; 455 adddynlib(lib); 456 continue; 457 } 458 459 local = expandpkg(local, pkg); 460 q = strchr(remote, '#'); 461 if(q) 462 *q++ = '\0'; 463 s = lookup(local, 0); 464 if(local != f[1]) 465 free(local); 466 if(s->type == 0 || s->type == SXREF || s->type == SHOSTOBJ) { 467 s->dynimplib = lib; 468 s->extname = remote; 469 s->dynimpvers = q; 470 if(s->type != SHOSTOBJ) 471 s->type = SDYNIMPORT; 472 havedynamic = 1; 473 } 474 continue; 475 } 476 477 if(strcmp(f[0], "cgo_import_static") == 0) { 478 if(nf != 2) 479 goto err; 480 local = f[1]; 481 s = lookup(local, 0); 482 s->type = SHOSTOBJ; 483 s->size = 0; 484 continue; 485 } 486 487 if(strcmp(f[0], "cgo_export_static") == 0 || strcmp(f[0], "cgo_export_dynamic") == 0) { 488 // TODO: Remove once we know Windows is okay. 489 if(strcmp(f[0], "cgo_export_static") == 0 && HEADTYPE == Hwindows) 490 continue; 491 492 if(nf < 2 || nf > 3) 493 goto err; 494 local = f[1]; 495 if(nf > 2) 496 remote = f[2]; 497 else 498 remote = local; 499 local = expandpkg(local, pkg); 500 s = lookup(local, 0); 501 502 // export overrides import, for openbsd/cgo. 503 // see issue 4878. 504 if(s->dynimplib != nil) { 505 s->dynimplib = nil; 506 s->extname = nil; 507 s->dynimpvers = nil; 508 s->type = 0; 509 } 510 511 if(s->cgoexport == 0) { 512 s->extname = remote; 513 if(ndynexp%32 == 0) 514 dynexp = erealloc(dynexp, (ndynexp+32)*sizeof dynexp[0]); 515 dynexp[ndynexp++] = s; 516 } else if(strcmp(s->extname, remote) != 0) { 517 fprint(2, "%s: conflicting cgo_export directives: %s as %s and %s\n", argv0, s->name, s->extname, remote); 518 nerrors++; 519 return; 520 } 521 if(strcmp(f[0], "cgo_export_static") == 0) 522 s->cgoexport |= CgoExportStatic; 523 else 524 s->cgoexport |= CgoExportDynamic; 525 if(local != f[1]) 526 free(local); 527 continue; 528 } 529 530 if(strcmp(f[0], "cgo_dynamic_linker") == 0) { 531 if(nf != 2) 532 goto err; 533 534 if(!debug['I']) { // not overridden by command line 535 if(interpreter != nil && strcmp(interpreter, f[1]) != 0) { 536 fprint(2, "%s: conflict dynlinker: %s and %s\n", argv0, interpreter, f[1]); 537 nerrors++; 538 return; 539 } 540 free(interpreter); 541 interpreter = estrdup(f[1]); 542 } 543 continue; 544 } 545 546 if(strcmp(f[0], "cgo_ldflag") == 0) { 547 if(nf != 2) 548 goto err; 549 if(nldflag%32 == 0) 550 ldflag = erealloc(ldflag, (nldflag+32)*sizeof ldflag[0]); 551 ldflag[nldflag++] = estrdup(f[1]); 552 continue; 553 } 554 } 555 free(p0); 556 return; 557 558 err: 559 fprint(2, "%s: %s: invalid dynimport line: %s\n", argv0, file, p0); 560 nerrors++; 561 } 562 563 static Sym *markq; 564 static Sym *emarkq; 565 566 static void 567 mark1(Sym *s, Sym *parent) 568 { 569 if(s == S || s->reachable) 570 return; 571 if(strncmp(s->name, "go.weak.", 8) == 0) 572 return; 573 s->reachable = 1; 574 s->reachparent = parent; 575 if(markq == nil) 576 markq = s; 577 else 578 emarkq->queue = s; 579 emarkq = s; 580 } 581 582 void 583 mark(Sym *s) 584 { 585 mark1(s, nil); 586 } 587 588 static void 589 markflood(void) 590 { 591 Auto *a; 592 Prog *p; 593 Sym *s; 594 int i; 595 596 for(s=markq; s!=S; s=s->queue) { 597 if(s->text) { 598 if(debug['v'] > 1) 599 Bprint(&bso, "marktext %s\n", s->name); 600 for(a=s->autom; a; a=a->link) 601 mark1(a->gotype, s); 602 for(p=s->text; p != P; p=p->link) { 603 mark1(p->from.sym, s); 604 mark1(p->to.sym, s); 605 } 606 } 607 for(i=0; i<s->nr; i++) 608 mark1(s->r[i].sym, s); 609 mark1(s->gotype, s); 610 mark1(s->sub, s); 611 mark1(s->outer, s); 612 } 613 } 614 615 static char* 616 morename[] = 617 { 618 "runtime.morestack", 619 "runtime.morestackx", 620 621 "runtime.morestack00", 622 "runtime.morestack10", 623 "runtime.morestack01", 624 "runtime.morestack11", 625 626 "runtime.morestack8", 627 "runtime.morestack16", 628 "runtime.morestack24", 629 "runtime.morestack32", 630 "runtime.morestack40", 631 "runtime.morestack48", 632 }; 633 634 static int 635 isz(Auto *a) 636 { 637 for(; a; a=a->link) 638 if(a->type == D_FILE || a->type == D_FILE1) 639 return 1; 640 return 0; 641 } 642 643 static void 644 addz(Sym *s, Auto *z) 645 { 646 Auto *a, *last; 647 648 // strip out non-z 649 last = nil; 650 for(a = z; a != nil; a = a->link) { 651 if(a->type == D_FILE || a->type == D_FILE1) { 652 if(last == nil) 653 z = a; 654 else 655 last->link = a; 656 last = a; 657 } 658 } 659 if(last) { 660 last->link = s->autom; 661 s->autom = z; 662 } 663 } 664 665 void 666 deadcode(void) 667 { 668 int i; 669 Sym *s, *last, *p; 670 Auto *z; 671 Fmt fmt; 672 673 if(debug['v']) 674 Bprint(&bso, "%5.2f deadcode\n", cputime()); 675 676 mark(lookup(INITENTRY, 0)); 677 if(flag_shared) 678 mark(lookup(LIBINITENTRY, 0)); 679 for(i=0; i<nelem(morename); i++) 680 mark(lookup(morename[i], 0)); 681 682 for(i=0; i<ndynexp; i++) 683 mark(dynexp[i]); 684 685 markflood(); 686 687 // keep each beginning with 'typelink.' if the symbol it points at is being kept. 688 for(s = allsym; s != S; s = s->allsym) { 689 if(strncmp(s->name, "go.typelink.", 12) == 0) 690 s->reachable = s->nr==1 && s->r[0].sym->reachable; 691 } 692 693 // remove dead text but keep file information (z symbols). 694 last = nil; 695 z = nil; 696 for(s = textp; s != nil; s = s->next) { 697 if(!s->reachable) { 698 if(isz(s->autom)) 699 z = s->autom; 700 continue; 701 } 702 if(last == nil) 703 textp = s; 704 else 705 last->next = s; 706 last = s; 707 if(z != nil) { 708 if(!isz(s->autom)) 709 addz(s, z); 710 z = nil; 711 } 712 } 713 if(last == nil) 714 textp = nil; 715 else 716 last->next = nil; 717 718 for(s = allsym; s != S; s = s->allsym) 719 if(strncmp(s->name, "go.weak.", 8) == 0) { 720 s->special = 1; // do not lay out in data segment 721 s->reachable = 1; 722 s->hide = 1; 723 } 724 725 // record field tracking references 726 fmtstrinit(&fmt); 727 for(s = allsym; s != S; s = s->allsym) { 728 if(strncmp(s->name, "go.track.", 9) == 0) { 729 s->special = 1; // do not lay out in data segment 730 s->hide = 1; 731 if(s->reachable) { 732 fmtprint(&fmt, "%s", s->name+9); 733 for(p=s->reachparent; p; p=p->reachparent) 734 fmtprint(&fmt, "\t%s", p->name); 735 fmtprint(&fmt, "\n"); 736 } 737 s->type = SCONST; 738 s->value = 0; 739 } 740 } 741 if(tracksym == nil) 742 return; 743 s = lookup(tracksym, 0); 744 if(!s->reachable) 745 return; 746 addstrdata(tracksym, fmtstrflush(&fmt)); 747 } 748 749 void 750 doweak(void) 751 { 752 Sym *s, *t; 753 754 // resolve weak references only if 755 // target symbol will be in binary anyway. 756 for(s = allsym; s != S; s = s->allsym) { 757 if(strncmp(s->name, "go.weak.", 8) == 0) { 758 t = rlookup(s->name+8, s->version); 759 if(t && t->type != 0 && t->reachable) { 760 s->value = t->value; 761 s->type = t->type; 762 s->outer = t; 763 } else { 764 s->type = SCONST; 765 s->value = 0; 766 } 767 continue; 768 } 769 } 770 } 771 772 void 773 addexport(void) 774 { 775 int i; 776 777 if(HEADTYPE == Hdarwin) 778 return; 779 780 for(i=0; i<ndynexp; i++) 781 adddynsym(dynexp[i]); 782 } 783 784 /* %Z from gc, for quoting import paths */ 785 int 786 Zconv(Fmt *fp) 787 { 788 Rune r; 789 char *s, *se; 790 int n; 791 792 s = va_arg(fp->args, char*); 793 if(s == nil) 794 return fmtstrcpy(fp, "<nil>"); 795 796 se = s + strlen(s); 797 while(s < se) { 798 n = chartorune(&r, s); 799 s += n; 800 switch(r) { 801 case Runeerror: 802 if(n == 1) { 803 fmtprint(fp, "\\x%02x", (uchar)*(s-1)); 804 break; 805 } 806 // fall through 807 default: 808 if(r < ' ') { 809 fmtprint(fp, "\\x%02x", r); 810 break; 811 } 812 fmtrune(fp, r); 813 break; 814 case '\t': 815 fmtstrcpy(fp, "\\t"); 816 break; 817 case '\n': 818 fmtstrcpy(fp, "\\n"); 819 break; 820 case '\"': 821 case '\\': 822 fmtrune(fp, '\\'); 823 fmtrune(fp, r); 824 break; 825 } 826 } 827 return 0; 828 } 829 830 831 typedef struct Pkg Pkg; 832 struct Pkg 833 { 834 uchar mark; 835 uchar checked; 836 Pkg *next; 837 char *path; 838 Pkg **impby; 839 int nimpby; 840 int mimpby; 841 Pkg *all; 842 }; 843 844 static Pkg *phash[1024]; 845 static Pkg *pkgall; 846 847 static Pkg* 848 getpkg(char *path) 849 { 850 Pkg *p; 851 int h; 852 853 h = hashstr(path) % nelem(phash); 854 for(p=phash[h]; p; p=p->next) 855 if(strcmp(p->path, path) == 0) 856 return p; 857 p = mal(sizeof *p); 858 p->path = estrdup(path); 859 p->next = phash[h]; 860 phash[h] = p; 861 p->all = pkgall; 862 pkgall = p; 863 return p; 864 } 865 866 static void 867 imported(char *pkg, char *import) 868 { 869 Pkg *p, *i; 870 871 // everyone imports runtime, even runtime. 872 if(strcmp(import, "\"runtime\"") == 0) 873 return; 874 875 pkg = smprint("\"%Z\"", pkg); // turn pkg path into quoted form, freed below 876 p = getpkg(pkg); 877 i = getpkg(import); 878 if(i->nimpby >= i->mimpby) { 879 i->mimpby *= 2; 880 if(i->mimpby == 0) 881 i->mimpby = 16; 882 i->impby = erealloc(i->impby, i->mimpby*sizeof i->impby[0]); 883 } 884 i->impby[i->nimpby++] = p; 885 free(pkg); 886 } 887 888 static Pkg* 889 cycle(Pkg *p) 890 { 891 int i; 892 Pkg *bad; 893 894 if(p->checked) 895 return 0; 896 897 if(p->mark) { 898 nerrors++; 899 print("import cycle:\n"); 900 print("\t%s\n", p->path); 901 return p; 902 } 903 p->mark = 1; 904 for(i=0; i<p->nimpby; i++) { 905 if((bad = cycle(p->impby[i])) != nil) { 906 p->mark = 0; 907 p->checked = 1; 908 print("\timports %s\n", p->path); 909 if(bad == p) 910 return nil; 911 return bad; 912 } 913 } 914 p->checked = 1; 915 p->mark = 0; 916 return 0; 917 } 918 919 void 920 importcycles(void) 921 { 922 Pkg *p; 923 924 for(p=pkgall; p; p=p->all) 925 cycle(p); 926 } 927 928 void 929 setlinkmode(char *arg) 930 { 931 if(strcmp(arg, "internal") == 0) 932 linkmode = LinkInternal; 933 else if(strcmp(arg, "external") == 0) 934 linkmode = LinkExternal; 935 else if(strcmp(arg, "auto") == 0) 936 linkmode = LinkAuto; 937 else { 938 fprint(2, "unknown link mode -linkmode %s\n", arg); 939 errorexit(); 940 } 941 }