1 /* $NetBSD: read.c,v 1.13 2002/01/31 19:36:56 tv Exp $ */ 2 3 /* 4 * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. 5 * Copyright (c) 1994, 1995 Jochen Pohl 6 * All Rights Reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Jochen Pohl for 19 * The NetBSD Project. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 #if defined(__RCSID) && !defined(lint) 37 __RCSID("$NetBSD: read.c,v 1.13 2002/01/31 19:36:56 tv Exp $"); 38 #endif 39 40 #include <ctype.h> 41 #include <limits.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 46 #include "lint2.h" 47 48 49 /* index of current (included) source file */ 50 static int srcfile; 51 52 /* 53 * The array pointed to by inpfns maps the file name indices of input files 54 * to the file name indices used in lint2 55 */ 56 static short *inpfns; 57 static size_t ninpfns; 58 59 /* 60 * The array pointed to by *fnames maps file name indizes to file names. 61 * Indices of type short are used instead of pointers to save memory. 62 */ 63 const char **fnames; 64 static size_t nfnames; 65 66 /* 67 * Types are shared (to save memory for the types itself) and accessed 68 * via indices (to save memory for references to types (indices are short)). 69 * To share types, a equal type must be located fast. This is done by a 70 * hash table. Access by indices is done via an array of pointers to the 71 * types. 72 */ 73 typedef struct thtab { 74 const char *th_name; 75 u_short th_idx; 76 struct thtab *th_nxt; 77 } thtab_t; 78 static thtab_t **thtab; /* hash table */ 79 type_t **tlst; /* array for indexed access */ 80 static size_t tlstlen; /* length of tlst */ 81 82 static hte_t **renametab; 83 84 /* index of current C source file (as spezified at the command line) */ 85 static int csrcfile; 86 87 88 static void inperr(void); 89 static void setsrc(const char *); 90 static void setfnid(int, const char *); 91 static void funccall(pos_t *, const char *); 92 static void decldef(pos_t *, const char *); 93 static void usedsym(pos_t *, const char *); 94 static u_short inptype(const char *, const char **); 95 static int gettlen(const char *, const char **); 96 static u_short findtype(const char *, size_t, int); 97 static u_short storetyp(type_t *, const char *, size_t, int); 98 static int thash(const char *, size_t); 99 static char *inpqstrg(const char *, const char **); 100 static const char *inpname(const char *, const char **); 101 static int getfnidx(const char *); 102 103 void 104 readfile(const char *name) 105 { 106 FILE *inp; 107 size_t len; 108 const char *cp; 109 char *line, *eptr, rt = '\0'; 110 int cline, isrc, iline; 111 pos_t pos; 112 113 if (inpfns == NULL) 114 inpfns = xcalloc(ninpfns = 128, sizeof (short)); 115 if (fnames == NULL) 116 fnames = xcalloc(nfnames = 256, sizeof (char *)); 117 if (tlstlen == 0) 118 tlst = xcalloc(tlstlen = 256, sizeof (type_t *)); 119 if (thtab == NULL) 120 thtab = xcalloc(THSHSIZ2, sizeof (thtab_t)); 121 122 _inithash(&renametab); 123 124 srcfile = getfnidx(name); 125 126 if ((inp = fopen(name, "r")) == NULL) 127 err(1, "cannot open %s", name); 128 129 while ((line = fgetln(inp, &len)) != NULL) { 130 131 if (len == 0 || line[len - 1] != '\n') 132 inperr(); 133 line[len - 1] = '\0'; 134 cp = line; 135 136 /* line number in csrcfile */ 137 cline = (int)strtol(cp, &eptr, 10); 138 if (cp == eptr) { 139 cline = -1; 140 } else { 141 cp = eptr; 142 } 143 144 /* record type */ 145 if (*cp != '\0') { 146 rt = *cp++; 147 } else { 148 inperr(); 149 } 150 151 if (rt == 'S') { 152 setsrc(cp); 153 continue; 154 } else if (rt == 's') { 155 setfnid(cline, cp); 156 continue; 157 } 158 159 /* 160 * Index of (included) source file. If this index is 161 * different from csrcfile, it refers to an included 162 * file. 163 */ 164 isrc = (int)strtol(cp, &eptr, 10); 165 if (cp == eptr) 166 inperr(); 167 cp = eptr; 168 isrc = inpfns[isrc]; 169 170 /* line number in isrc */ 171 if (*cp++ != '.') 172 inperr(); 173 iline = (int)strtol(cp, &eptr, 10); 174 if (cp == eptr) 175 inperr(); 176 cp = eptr; 177 178 pos.p_src = (u_short)csrcfile; 179 pos.p_line = (u_short)cline; 180 pos.p_isrc = (u_short)isrc; 181 pos.p_iline = (u_short)iline; 182 183 /* process rest of this record */ 184 switch (rt) { 185 case 'c': 186 funccall(&pos, cp); 187 break; 188 case 'd': 189 decldef(&pos, cp); 190 break; 191 case 'u': 192 usedsym(&pos, cp); 193 break; 194 default: 195 inperr(); 196 } 197 198 } 199 200 _destroyhash(renametab); 201 202 if (ferror(inp)) 203 err(1, "read error on %s", name); 204 205 (void)fclose(inp); 206 } 207 208 209 static void 210 inperr(void) 211 { 212 213 errx(1, "input file error: %s", fnames[srcfile]); 214 } 215 216 /* 217 * Set the name of the C source file of the .ln file which is 218 * currently read. 219 */ 220 static void 221 setsrc(const char *cp) 222 { 223 224 csrcfile = getfnidx(cp); 225 } 226 227 /* 228 * setfnid() gets as input an index as used in an input file and the 229 * associated file name. If necessary, it creates a new lint2 file 230 * name index for this file name and creates the mapping of the index 231 * as used in the input file to the index used in lint2. 232 */ 233 static void 234 setfnid(int fid, const char *cp) 235 { 236 237 if (fid == -1) 238 inperr(); 239 240 if (fid >= ninpfns) { 241 inpfns = xrealloc(inpfns, (ninpfns * 2) * sizeof (short)); 242 (void)memset(inpfns + ninpfns, 0, ninpfns * sizeof (short)); 243 ninpfns *= 2; 244 } 245 /* 246 * Should always be true because indices written in the output 247 * file by lint1 are always the previous index + 1. 248 */ 249 if (fid >= ninpfns) 250 errx(1, "internal error: setfnid()"); 251 inpfns[fid] = (u_short)getfnidx(cp); 252 } 253 254 /* 255 * Process a function call record (c-record). 256 */ 257 static void 258 funccall(pos_t *posp, const char *cp) 259 { 260 arginf_t *ai, **lai; 261 char c, *eptr; 262 int rused, rdisc; 263 hte_t *hte; 264 fcall_t *fcall; 265 const char *name; 266 267 fcall = xalloc(sizeof (fcall_t)); 268 STRUCT_ASSIGN(fcall->f_pos, *posp); 269 270 /* read flags */ 271 rused = rdisc = 0; 272 lai = &fcall->f_args; 273 while ((c = *cp) == 'u' || c == 'i' || c == 'd' || 274 c == 'z' || c == 'p' || c == 'n' || c == 's') { 275 cp++; 276 switch (c) { 277 case 'u': 278 if (rused || rdisc) 279 inperr(); 280 rused = 1; 281 break; 282 case 'i': 283 if (rused || rdisc) 284 inperr(); 285 break; 286 case 'd': 287 if (rused || rdisc) 288 inperr(); 289 rdisc = 1; 290 break; 291 case 'z': 292 case 'p': 293 case 'n': 294 case 's': 295 ai = xalloc(sizeof (arginf_t)); 296 ai->a_num = (int)strtol(cp, &eptr, 10); 297 if (cp == eptr) 298 inperr(); 299 cp = eptr; 300 if (c == 'z') { 301 ai->a_pcon = ai->a_zero = 1; 302 } else if (c == 'p') { 303 ai->a_pcon = 1; 304 } else if (c == 'n') { 305 ai->a_ncon = 1; 306 } else { 307 ai->a_fmt = 1; 308 ai->a_fstrg = inpqstrg(cp, &cp); 309 } 310 *lai = ai; 311 lai = &ai->a_nxt; 312 break; 313 } 314 } 315 fcall->f_rused = rused; 316 fcall->f_rdisc = rdisc; 317 318 /* read name of function */ 319 name = inpname(cp, &cp); 320 321 /* first look it up in the renaming table, then in the normal table */ 322 hte = _hsearch(renametab, name, 0); 323 if (hte != NULL) 324 hte = hte->h_hte; 325 else 326 hte = hsearch(name, 1); 327 hte->h_used = 1; 328 329 fcall->f_type = inptype(cp, &cp); 330 331 *hte->h_lcall = fcall; 332 hte->h_lcall = &fcall->f_nxt; 333 334 if (*cp != '\0') 335 inperr(); 336 } 337 338 /* 339 * Process a declaration or definition (d-record). 340 */ 341 static void 342 decldef(pos_t *posp, const char *cp) 343 { 344 sym_t *symp, sym; 345 char c, *ep, *pos1; 346 int used, renamed; 347 hte_t *hte, *renamehte = NULL; 348 const char *name, *rename; 349 350 (void)memset(&sym, 0, sizeof (sym)); 351 STRUCT_ASSIGN(sym.s_pos, *posp); 352 sym.s_def = NODECL; 353 354 used = 0; 355 356 while ((c = *cp) == 't' || c == 'd' || c == 'e' || c == 'u' || 357 c == 'r' || c == 'o' || c == 's' || c == 'v' || 358 c == 'P' || c == 'S') { 359 cp++; 360 switch (c) { 361 case 't': 362 if (sym.s_def != NODECL) 363 inperr(); 364 sym.s_def = TDEF; 365 break; 366 case 'd': 367 if (sym.s_def != NODECL) 368 inperr(); 369 sym.s_def = DEF; 370 break; 371 case 'e': 372 if (sym.s_def != NODECL) 373 inperr(); 374 sym.s_def = DECL; 375 break; 376 case 'u': 377 if (used) 378 inperr(); 379 used = 1; 380 break; 381 case 'r': 382 if (sym.s_rval) 383 inperr(); 384 sym.s_rval = 1; 385 break; 386 case 'o': 387 if (sym.s_osdef) 388 inperr(); 389 sym.s_osdef = 1; 390 break; 391 case 's': 392 if (sym.s_static) 393 inperr(); 394 sym.s_static = 1; 395 break; 396 case 'v': 397 if (sym.s_va) 398 inperr(); 399 sym.s_va = 1; 400 sym.s_nva = (short)strtol(cp, &ep, 10); 401 if (cp == ep) 402 inperr(); 403 cp = ep; 404 break; 405 case 'P': 406 if (sym.s_prfl) 407 inperr(); 408 sym.s_prfl = 1; 409 sym.s_nprfl = (short)strtol(cp, &ep, 10); 410 if (cp == ep) 411 inperr(); 412 cp = ep; 413 break; 414 case 'S': 415 if (sym.s_scfl) 416 inperr(); 417 sym.s_scfl = 1; 418 sym.s_nscfl = (short)strtol(cp, &ep, 10); 419 if (cp == ep) 420 inperr(); 421 cp = ep; 422 break; 423 } 424 } 425 426 /* read symbol name, doing renaming if necessary */ 427 name = inpname(cp, &cp); 428 renamed = 0; 429 if (*cp == 'r') { 430 cp++; 431 name = xstrdup(name); 432 rename = inpname(cp, &cp); 433 434 /* enter it and see if it's already been renamed */ 435 renamehte = _hsearch(renametab, name, 1); 436 if (renamehte->h_hte == NULL) { 437 hte = hsearch(rename, 1); 438 renamehte->h_hte = hte; 439 renamed = 1; 440 } else if (strcmp((hte = renamehte->h_hte)->h_name, rename)) { 441 pos1 = xstrdup(mkpos(&renamehte->h_syms->s_pos)); 442 /* %s renamed multiple times\t%s :: %s */ 443 msg(18, name, pos1, mkpos(&sym.s_pos)); 444 free(pos1); 445 } 446 free((char *)name); 447 } else { 448 /* it might be a previously-done rename */ 449 hte = _hsearch(renametab, name, 0); 450 if (hte != NULL) 451 hte = hte->h_hte; 452 else 453 hte = hsearch(name, 1); 454 } 455 hte->h_used |= used; 456 if (sym.s_def == DEF || sym.s_def == TDEF) 457 hte->h_def = 1; 458 459 sym.s_type = inptype(cp, &cp); 460 461 /* 462 * Allocate memory for this symbol only if it was not already 463 * declared or tentatively defined at the same location with 464 * the same type. Works only for symbols with external linkage, 465 * because static symbols, tentatively defined at the same location 466 * but in different translation units are really different symbols. 467 */ 468 for (symp = hte->h_syms; symp != NULL; symp = symp->s_nxt) { 469 if (symp->s_pos.p_isrc == sym.s_pos.p_isrc && 470 symp->s_pos.p_iline == sym.s_pos.p_iline && 471 symp->s_type == sym.s_type && 472 ((symp->s_def == DECL && sym.s_def == DECL) || 473 (!sflag && symp->s_def == TDEF && sym.s_def == TDEF)) && 474 !symp->s_static && !sym.s_static) { 475 break; 476 } 477 } 478 479 if (symp == NULL) { 480 /* allocsym reserviert keinen Platz fuer s_nva */ 481 if (sym.s_va || sym.s_prfl || sym.s_scfl) { 482 symp = xalloc(sizeof (sym_t)); 483 STRUCT_ASSIGN(*symp, sym); 484 } else { 485 symp = xalloc(sizeof (symp->s_s)); 486 STRUCT_ASSIGN(symp->s_s, sym.s_s); 487 } 488 *hte->h_lsym = symp; 489 hte->h_lsym = &symp->s_nxt; 490 491 /* XXX hack so we can remember where a symbol was renamed */ 492 if (renamed) 493 renamehte->h_syms = symp; 494 } 495 496 if (*cp != '\0') 497 inperr(); 498 } 499 500 /* 501 * Read an u-record (emited by lint1 if a symbol was used). 502 */ 503 static void 504 usedsym(pos_t *posp, const char *cp) 505 { 506 usym_t *usym; 507 hte_t *hte; 508 const char *name; 509 510 usym = xalloc(sizeof (usym_t)); 511 STRUCT_ASSIGN(usym->u_pos, *posp); 512 513 /* needed as delimiter between two numbers */ 514 if (*cp++ != 'x') 515 inperr(); 516 517 name = inpname(cp, &cp); 518 hte = _hsearch(renametab, name, 0); 519 if (hte != NULL) 520 hte = hte->h_hte; 521 else 522 hte = hsearch(name, 1); 523 hte->h_used = 1; 524 525 *hte->h_lusym = usym; 526 hte->h_lusym = &usym->u_nxt; 527 } 528 529 /* 530 * Read a type and return the index of this type. 531 */ 532 static u_short 533 inptype(const char *cp, const char **epp) 534 { 535 char c, s, *eptr; 536 const char *ep; 537 type_t *tp; 538 int narg, i, osdef = 0; 539 size_t tlen; 540 u_short tidx; 541 int h; 542 543 /* If we have this type already, return it's index. */ 544 tlen = gettlen(cp, &ep); 545 h = thash(cp, tlen); 546 if ((tidx = findtype(cp, tlen, h)) != 0) { 547 *epp = ep; 548 return (tidx); 549 } 550 551 /* No, we must create a new type. */ 552 tp = xalloc(sizeof (type_t)); 553 554 tidx = storetyp(tp, cp, tlen, h); 555 556 c = *cp++; 557 558 while (c == 'c' || c == 'v') { 559 if (c == 'c') { 560 tp->t_const = 1; 561 } else { 562 tp->t_volatile = 1; 563 } 564 c = *cp++; 565 } 566 567 if (c == 's' || c == 'u' || c == 'l' || c == 'e') { 568 s = c; 569 c = *cp++; 570 } else { 571 s = '\0'; 572 } 573 574 switch (c) { 575 case 'C': 576 tp->t_tspec = s == 's' ? SCHAR : (s == 'u' ? UCHAR : CHAR); 577 break; 578 case 'S': 579 tp->t_tspec = s == 'u' ? USHORT : SHORT; 580 break; 581 case 'I': 582 tp->t_tspec = s == 'u' ? UINT : INT; 583 break; 584 case 'L': 585 tp->t_tspec = s == 'u' ? ULONG : LONG; 586 break; 587 case 'Q': 588 tp->t_tspec = s == 'u' ? UQUAD : QUAD; 589 break; 590 case 'D': 591 tp->t_tspec = s == 's' ? FLOAT : (s == 'l' ? LDOUBLE : DOUBLE); 592 break; 593 case 'V': 594 tp->t_tspec = VOID; 595 break; 596 case 'P': 597 tp->t_tspec = PTR; 598 break; 599 case 'A': 600 tp->t_tspec = ARRAY; 601 break; 602 case 'F': 603 case 'f': 604 osdef = c == 'f'; 605 tp->t_tspec = FUNC; 606 break; 607 case 'T': 608 tp->t_tspec = s == 'e' ? ENUM : (s == 's' ? STRUCT : UNION); 609 break; 610 } 611 612 switch (tp->t_tspec) { 613 case ARRAY: 614 tp->t_dim = (int)strtol(cp, &eptr, 10); 615 cp = eptr; 616 tp->t_subt = TP(inptype(cp, &cp)); 617 break; 618 case PTR: 619 tp->t_subt = TP(inptype(cp, &cp)); 620 break; 621 case FUNC: 622 c = *cp; 623 if (isdigit((u_char)c)) { 624 if (!osdef) 625 tp->t_proto = 1; 626 narg = (int)strtol(cp, &eptr, 10); 627 cp = eptr; 628 tp->t_args = xcalloc((size_t)(narg + 1), 629 sizeof (type_t *)); 630 for (i = 0; i < narg; i++) { 631 if (i == narg - 1 && *cp == 'E') { 632 tp->t_vararg = 1; 633 cp++; 634 } else { 635 tp->t_args[i] = TP(inptype(cp, &cp)); 636 } 637 } 638 } 639 tp->t_subt = TP(inptype(cp, &cp)); 640 break; 641 case ENUM: 642 tp->t_tspec = INT; 643 tp->t_isenum = 1; 644 /* FALLTHROUGH */ 645 case STRUCT: 646 case UNION: 647 switch (*cp++) { 648 case '1': 649 tp->t_istag = 1; 650 tp->t_tag = hsearch(inpname(cp, &cp), 1); 651 break; 652 case '2': 653 tp->t_istynam = 1; 654 tp->t_tynam = hsearch(inpname(cp, &cp), 1); 655 break; 656 case '3': 657 tp->t_isuniqpos = 1; 658 tp->t_uniqpos.p_line = strtol(cp, &eptr, 10); 659 cp = eptr; 660 cp++; 661 /* xlate to 'global' file name. */ 662 tp->t_uniqpos.p_file = 663 addoutfile(inpfns[strtol(cp, &eptr, 10)]); 664 cp = eptr; 665 cp++; 666 tp->t_uniqpos.p_uniq = strtol(cp, &eptr, 10); 667 cp = eptr; 668 break; 669 } 670 break; 671 case LONG: 672 case VOID: 673 case LDOUBLE: 674 case DOUBLE: 675 case FLOAT: 676 case UQUAD: 677 case QUAD: 678 case ULONG: 679 case UINT: 680 case INT: 681 case USHORT: 682 case SHORT: 683 case UCHAR: 684 case SCHAR: 685 case CHAR: 686 case UNSIGN: 687 case SIGNED: 688 case NOTSPEC: 689 break; 690 case NTSPEC: 691 abort(); 692 } 693 694 *epp = cp; 695 return (tidx); 696 } 697 698 /* 699 * Get the length of a type string. 700 */ 701 static int 702 gettlen(const char *cp, const char **epp) 703 { 704 const char *cp1; 705 char c, s, *eptr; 706 tspec_t t; 707 int narg, i, cm, vm; 708 709 cp1 = cp; 710 711 c = *cp++; 712 713 cm = vm = 0; 714 715 while (c == 'c' || c == 'v') { 716 if (c == 'c') { 717 if (cm) 718 inperr(); 719 cm = 1; 720 } else { 721 if (vm) 722 inperr(); 723 vm = 1; 724 } 725 c = *cp++; 726 } 727 728 if (c == 's' || c == 'u' || c == 'l' || c == 'e') { 729 s = c; 730 c = *cp++; 731 } else { 732 s = '\0'; 733 } 734 735 t = NOTSPEC; 736 737 switch (c) { 738 case 'C': 739 if (s == 's') { 740 t = SCHAR; 741 } else if (s == 'u') { 742 t = UCHAR; 743 } else if (s == '\0') { 744 t = CHAR; 745 } 746 break; 747 case 'S': 748 if (s == 'u') { 749 t = USHORT; 750 } else if (s == '\0') { 751 t = SHORT; 752 } 753 break; 754 case 'I': 755 if (s == 'u') { 756 t = UINT; 757 } else if (s == '\0') { 758 t = INT; 759 } 760 break; 761 case 'L': 762 if (s == 'u') { 763 t = ULONG; 764 } else if (s == '\0') { 765 t = LONG; 766 } 767 break; 768 case 'Q': 769 if (s == 'u') { 770 t = UQUAD; 771 } else if (s == '\0') { 772 t = QUAD; 773 } 774 break; 775 case 'D': 776 if (s == 's') { 777 t = FLOAT; 778 } else if (s == 'l') { 779 t = LDOUBLE; 780 } else if (s == '\0') { 781 t = DOUBLE; 782 } 783 break; 784 case 'V': 785 if (s == '\0') 786 t = VOID; 787 break; 788 case 'P': 789 if (s == '\0') 790 t = PTR; 791 break; 792 case 'A': 793 if (s == '\0') 794 t = ARRAY; 795 break; 796 case 'F': 797 case 'f': 798 if (s == '\0') 799 t = FUNC; 800 break; 801 case 'T': 802 if (s == 'e') { 803 t = ENUM; 804 } else if (s == 's') { 805 t = STRUCT; 806 } else if (s == 'u') { 807 t = UNION; 808 } 809 break; 810 default: 811 inperr(); 812 } 813 814 if (t == NOTSPEC) 815 inperr(); 816 817 switch (t) { 818 case ARRAY: 819 (void)strtol(cp, &eptr, 10); 820 if (cp == eptr) 821 inperr(); 822 cp = eptr; 823 (void)gettlen(cp, &cp); 824 break; 825 case PTR: 826 (void)gettlen(cp, &cp); 827 break; 828 case FUNC: 829 c = *cp; 830 if (isdigit((u_char)c)) { 831 narg = (int)strtol(cp, &eptr, 10); 832 cp = eptr; 833 for (i = 0; i < narg; i++) { 834 if (i == narg - 1 && *cp == 'E') { 835 cp++; 836 } else { 837 (void)gettlen(cp, &cp); 838 } 839 } 840 } 841 (void)gettlen(cp, &cp); 842 break; 843 case ENUM: 844 case STRUCT: 845 case UNION: 846 switch (*cp++) { 847 case '1': 848 (void)inpname(cp, &cp); 849 break; 850 case '2': 851 (void)inpname(cp, &cp); 852 break; 853 case '3': 854 /* unique position: line.file.uniquifier */ 855 (void)strtol(cp, &eptr, 10); 856 if (cp == eptr) 857 inperr(); 858 cp = eptr; 859 if (*cp++ != '.') 860 inperr(); 861 (void)strtol(cp, &eptr, 10); 862 if (cp == eptr) 863 inperr(); 864 cp = eptr; 865 if (*cp++ != '.') 866 inperr(); 867 (void)strtol(cp, &eptr, 10); 868 if (cp == eptr) 869 inperr(); 870 cp = eptr; 871 break; 872 default: 873 inperr(); 874 } 875 break; 876 case FLOAT: 877 case USHORT: 878 case SHORT: 879 case UCHAR: 880 case SCHAR: 881 case CHAR: 882 case UNSIGN: 883 case SIGNED: 884 case NOTSPEC: 885 case INT: 886 case UINT: 887 case DOUBLE: 888 case LDOUBLE: 889 case VOID: 890 case ULONG: 891 case QUAD: 892 case UQUAD: 893 case LONG: 894 break; 895 case NTSPEC: 896 abort(); 897 } 898 899 *epp = cp; 900 return (cp - cp1); 901 } 902 903 /* 904 * Search a type by it's type string. 905 */ 906 static u_short 907 findtype(const char *cp, size_t len, int h) 908 { 909 thtab_t *thte; 910 911 for (thte = thtab[h]; thte != NULL; thte = thte->th_nxt) { 912 if (strncmp(thte->th_name, cp, len) != 0) 913 continue; 914 if (thte->th_name[len] == '\0') 915 return (thte->th_idx); 916 } 917 918 return (0); 919 } 920 921 /* 922 * Store a type and it's type string so we can later share this type 923 * if we read the same type string from the input file. 924 */ 925 static u_short 926 storetyp(type_t *tp, const char *cp, size_t len, int h) 927 { 928 static u_int tidx = 1; /* 0 is reserved */ 929 thtab_t *thte; 930 char *name; 931 932 if (tidx >= USHRT_MAX) 933 errx(1, "sorry, too many types"); 934 935 if (tidx == tlstlen - 1) { 936 tlst = xrealloc(tlst, (tlstlen * 2) * sizeof (type_t *)); 937 (void)memset(tlst + tlstlen, 0, tlstlen * sizeof (type_t *)); 938 tlstlen *= 2; 939 } 940 941 tlst[tidx] = tp; 942 943 /* create a hash table entry */ 944 name = xalloc(len + 1); 945 (void)memcpy(name, cp, len); 946 name[len] = '\0'; 947 948 thte = xalloc(sizeof (thtab_t)); 949 thte->th_name = name; 950 thte->th_idx = tidx; 951 thte->th_nxt = thtab[h]; 952 thtab[h] = thte; 953 954 return ((u_short)tidx++); 955 } 956 957 /* 958 * Hash function for types 959 */ 960 static int 961 thash(const char *s, size_t len) 962 { 963 u_int v; 964 965 v = 0; 966 while (len-- != 0) { 967 v = (v << sizeof (v)) + (u_char)*s++; 968 v ^= v >> (sizeof (v) * CHAR_BIT - sizeof (v)); 969 } 970 return (v % THSHSIZ2); 971 } 972 973 /* 974 * Read a string enclosed by "". This string may contain quoted chars. 975 */ 976 static char * 977 inpqstrg(const char *src, const char **epp) 978 { 979 char *strg, *dst; 980 size_t slen; 981 int c; 982 int v; 983 984 dst = strg = xmalloc(slen = 32); 985 986 if ((c = *src++) != '"') 987 inperr(); 988 if ((c = *src++) == '\0') 989 inperr(); 990 991 while (c != '"') { 992 if (c == '\\') { 993 if ((c = *src++) == '\0') 994 inperr(); 995 switch (c) { 996 case 'n': 997 c = '\n'; 998 break; 999 case 't': 1000 c = '\t'; 1001 break; 1002 case 'v': 1003 c = '\v'; 1004 break; 1005 case 'b': 1006 c = '\b'; 1007 break; 1008 case 'r': 1009 c = '\r'; 1010 break; 1011 case 'f': 1012 c = '\f'; 1013 break; 1014 case 'a': 1015 c = '\a'; 1016 break; 1017 case '\\': 1018 c = '\\'; 1019 break; 1020 case '"': 1021 c = '"'; 1022 break; 1023 case '\'': 1024 c = '\''; 1025 break; 1026 case '0': case '1': case '2': case '3': 1027 v = (c - '0') << 6; 1028 if ((c = *src++) < '0' || c > '7') 1029 inperr(); 1030 v |= (c - '0') << 3; 1031 if ((c = *src++) < '0' || c > '7') 1032 inperr(); 1033 v |= c - '0'; 1034 c = (u_char)v; 1035 break; 1036 default: 1037 inperr(); 1038 } 1039 } 1040 /* keep space for trailing '\0' */ 1041 if (dst - strg == slen - 1) { 1042 strg = xrealloc(strg, slen * 2); 1043 dst = strg + (slen - 1); 1044 slen *= 2; 1045 } 1046 *dst++ = (char)c; 1047 if ((c = *src++) == '\0') 1048 inperr(); 1049 } 1050 *dst = '\0'; 1051 1052 *epp = src; 1053 return (strg); 1054 } 1055 1056 /* 1057 * Read the name of a symbol in static memory. 1058 */ 1059 static const char * 1060 inpname(const char *cp, const char **epp) 1061 { 1062 static char *buf; 1063 static size_t blen = 0; 1064 size_t len, i; 1065 char *eptr, c; 1066 1067 len = (int)strtol(cp, &eptr, 10); 1068 if (cp == eptr) 1069 inperr(); 1070 cp = eptr; 1071 if (len + 1 > blen) 1072 buf = xrealloc(buf, blen = len + 1); 1073 for (i = 0; i < len; i++) { 1074 c = *cp++; 1075 if (!isalnum((unsigned char)c) && c != '_') 1076 inperr(); 1077 buf[i] = c; 1078 } 1079 buf[i] = '\0'; 1080 1081 *epp = cp; 1082 return (buf); 1083 } 1084 1085 /* 1086 * Return the index of a file name. If the name cannot be found, create 1087 * a new entry and return the index of the newly created entry. 1088 */ 1089 static int 1090 getfnidx(const char *fn) 1091 { 1092 int i; 1093 1094 /* 0 ist reserved */ 1095 for (i = 1; fnames[i] != NULL; i++) { 1096 if (strcmp(fnames[i], fn) == 0) 1097 break; 1098 } 1099 if (fnames[i] != NULL) 1100 return (i); 1101 1102 if (i == nfnames - 1) { 1103 fnames = xrealloc(fnames, (nfnames * 2) * sizeof (char *)); 1104 (void)memset(fnames + nfnames, 0, nfnames * sizeof (char *)); 1105 nfnames *= 2; 1106 } 1107 1108 fnames[i] = xstrdup(fn); 1109 return (i); 1110 } 1111 1112 /* 1113 * Separate symbols with static and external linkage. 1114 */ 1115 void 1116 mkstatic(hte_t *hte) 1117 { 1118 sym_t *sym1, **symp, *sym; 1119 fcall_t **callp, *call; 1120 usym_t **usymp, *usym; 1121 hte_t *nhte; 1122 int ofnd; 1123 1124 /* Look for first static definition */ 1125 for (sym1 = hte->h_syms; sym1 != NULL; sym1 = sym1->s_nxt) { 1126 if (sym1->s_static) 1127 break; 1128 } 1129 if (sym1 == NULL) 1130 return; 1131 1132 /* Do nothing if this name is used only in one translation unit. */ 1133 ofnd = 0; 1134 for (sym = hte->h_syms; sym != NULL && !ofnd; sym = sym->s_nxt) { 1135 if (sym->s_pos.p_src != sym1->s_pos.p_src) 1136 ofnd = 1; 1137 } 1138 for (call = hte->h_calls; call != NULL && !ofnd; call = call->f_nxt) { 1139 if (call->f_pos.p_src != sym1->s_pos.p_src) 1140 ofnd = 1; 1141 } 1142 for (usym = hte->h_usyms; usym != NULL && !ofnd; usym = usym->u_nxt) { 1143 if (usym->u_pos.p_src != sym1->s_pos.p_src) 1144 ofnd = 1; 1145 } 1146 if (!ofnd) { 1147 hte->h_used = 1; 1148 /* errors about undef. static symbols are printed in lint1 */ 1149 hte->h_def = 1; 1150 hte->h_static = 1; 1151 return; 1152 } 1153 1154 /* 1155 * Create a new hash table entry 1156 * 1157 * XXX this entry should be put at the beginning of the list to 1158 * avoid to process the same symbol twice. 1159 */ 1160 for (nhte = hte; nhte->h_link != NULL; nhte = nhte->h_link) 1161 continue; 1162 nhte->h_link = xmalloc(sizeof (hte_t)); 1163 nhte = nhte->h_link; 1164 nhte->h_name = hte->h_name; 1165 nhte->h_used = 1; 1166 nhte->h_def = 1; /* error in lint1 */ 1167 nhte->h_static = 1; 1168 nhte->h_syms = NULL; 1169 nhte->h_lsym = &nhte->h_syms; 1170 nhte->h_calls = NULL; 1171 nhte->h_lcall = &nhte->h_calls; 1172 nhte->h_usyms = NULL; 1173 nhte->h_lusym = &nhte->h_usyms; 1174 nhte->h_link = NULL; 1175 nhte->h_hte = NULL; 1176 1177 /* 1178 * move all symbols used in this translation unit into the new 1179 * hash table entry. 1180 */ 1181 for (symp = &hte->h_syms; (sym = *symp) != NULL; ) { 1182 if (sym->s_pos.p_src == sym1->s_pos.p_src) { 1183 sym->s_static = 1; 1184 (*symp) = sym->s_nxt; 1185 if (hte->h_lsym == &sym->s_nxt) 1186 hte->h_lsym = symp; 1187 sym->s_nxt = NULL; 1188 *nhte->h_lsym = sym; 1189 nhte->h_lsym = &sym->s_nxt; 1190 } else { 1191 symp = &sym->s_nxt; 1192 } 1193 } 1194 for (callp = &hte->h_calls; (call = *callp) != NULL; ) { 1195 if (call->f_pos.p_src == sym1->s_pos.p_src) { 1196 (*callp) = call->f_nxt; 1197 if (hte->h_lcall == &call->f_nxt) 1198 hte->h_lcall = callp; 1199 call->f_nxt = NULL; 1200 *nhte->h_lcall = call; 1201 nhte->h_lcall = &call->f_nxt; 1202 } else { 1203 callp = &call->f_nxt; 1204 } 1205 } 1206 for (usymp = &hte->h_usyms; (usym = *usymp) != NULL; ) { 1207 if (usym->u_pos.p_src == sym1->s_pos.p_src) { 1208 (*usymp) = usym->u_nxt; 1209 if (hte->h_lusym == &usym->u_nxt) 1210 hte->h_lusym = usymp; 1211 usym->u_nxt = NULL; 1212 *nhte->h_lusym = usym; 1213 nhte->h_lusym = &usym->u_nxt; 1214 } else { 1215 usymp = &usym->u_nxt; 1216 } 1217 } 1218 1219 /* h_def must be recalculated for old hte */ 1220 hte->h_def = nhte->h_def = 0; 1221 for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) { 1222 if (sym->s_def == DEF || sym->s_def == TDEF) { 1223 hte->h_def = 1; 1224 break; 1225 } 1226 } 1227 1228 mkstatic(hte); 1229 } 1230