1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1996-2002 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <limits.h> 30 #include <stdarg.h> 31 #include <stdio.h> 32 33 #include "stabs.h" 34 35 static struct tdesc *hash_table[BUCKETS]; 36 static struct tdesc *name_table[BUCKETS]; 37 38 static void reset(void); 39 static jmp_buf resetbuf; 40 41 static char *get_line(void); 42 static void parseline(char *cp); 43 static char *soudef(char *cp, enum type type, struct tdesc **rtdp); 44 static void enumdef(char *cp, struct tdesc **rtdp); 45 static int compute_sum(char *w); 46 static struct tdesc *lookup(int h); 47 48 static char *number(char *cp, int *n); 49 static char *name(char *cp, char **w); 50 static char *id(char *cp, int *h); 51 static char *offsize(char *cp, struct mlist *mlp); 52 static char *whitesp(char *cp); 53 static void addhash(struct tdesc *tdp, int num); 54 static void tagadd(char *w, int h, struct tdesc *tdp); 55 static void tagdecl(char *cp, struct tdesc **rtdp, int h, char *w); 56 static char *tdefdecl(char *cp, int h, struct tdesc **rtdp); 57 static char *intrinsic(char *cp, struct tdesc **rtdp); 58 static char *arraydef(char *cp, struct tdesc **rtdp); 59 60 static int line_number = 0; 61 static int debug_line = 0; 62 static char linebuf[MAXLINE]; 63 64 extern int debug_level; 65 66 static void 67 debug(int level, char *cp, char *fmt, ...) 68 { 69 va_list ap; 70 char buf[1024]; 71 char tmp[32]; 72 int i; 73 74 if (level > debug_level) 75 return; 76 77 if (cp != NULL) { 78 for (i = 0; i < 30; i++) { 79 if (cp[i] == '\0') 80 break; 81 if (!iscntrl(cp[i])) 82 tmp[i] = cp[i]; 83 } 84 tmp[i] = '\0'; 85 (void) sprintf(buf, "%s [cp='%s']\n", fmt, tmp); 86 } else { 87 strcpy(buf, fmt); 88 strcat(buf, "\n"); 89 } 90 91 va_start(ap, fmt); 92 (void) vfprintf(stderr, buf, ap); 93 va_end(ap); 94 } 95 96 97 /* Report unexpected syntax in stabs. */ 98 static void 99 expected( 100 char *who, /* what function, or part thereof, is reporting */ 101 char *what, /* what was expected */ 102 char *where) /* where we were in the line of input */ 103 { 104 fprintf(stderr, "%s, input line %d: expecting \"%s\" at \"%s\"\n", 105 who, line_number, what, where); 106 exit(1); 107 } 108 109 /* Read a line from stdin into linebuf and increment line_number. */ 110 static char * 111 get_line(void) 112 { 113 char *cp = fgets(linebuf, MAXLINE, stdin); 114 line_number++; 115 116 /* For debugging, you can set debug_line to a line to stop on. */ 117 if (line_number == debug_line) { 118 fprintf(stderr, "Hit debug line number %d\n", line_number); 119 for (;;) 120 sleep(1); 121 } 122 return (cp); 123 } 124 125 /* Get the continuation of the current input line. */ 126 static char * 127 get_continuation(void) 128 { 129 char *cp = get_line(); 130 if (!cp) { 131 fprintf(stderr, "expecting continuation line, " 132 "got end of input\n"); 133 exit(1); 134 } 135 136 /* Skip to the quoted stuff. */ 137 while (*cp++ != '"') 138 ; 139 return (cp); 140 } 141 142 void 143 parse_input(void) 144 { 145 char *cp; 146 int i = 0; 147 148 for (i = 0; i < BUCKETS; i++) { 149 hash_table[i] = NULL; 150 name_table[i] = NULL; 151 } 152 153 /* 154 * get a line at a time from the .s stabs file and parse. 155 */ 156 while ((cp = get_line()) != NULL) 157 parseline(cp); 158 } 159 160 /* 161 * Parse each line of the .s file (stabs entry) gather meaningful information 162 * like name of type, size, offsets of fields etc. 163 */ 164 static void 165 parseline(char *cp) 166 { 167 struct tdesc *tdp; 168 char c, *w; 169 int h, tagdef; 170 171 /* 172 * setup for reset() 173 */ 174 if (setjmp(resetbuf)) 175 return; 176 177 /* 178 * Look for lines of the form 179 * .stabs "str",n,n,n,n 180 * The part in '"' is then parsed. 181 */ 182 cp = whitesp(cp); 183 #define STLEN 6 184 debug(2, cp, "parseline"); 185 if (strncmp(cp, ".stabs", STLEN) != 0) 186 reset(); 187 cp += STLEN; 188 #undef STLEN 189 cp = whitesp(cp); 190 if (*cp++ != '"') 191 reset(); 192 193 /* 194 * name:type variable (ignored) 195 * name:ttype typedef 196 * name:Ttype struct tag define 197 */ 198 cp = whitesp(cp); 199 cp = name(cp, &w); 200 201 tagdef = 0; 202 switch (c = *cp++) { 203 case 't': /* type */ 204 break; 205 case 'T': /* struct, union, enum */ 206 tagdef = 1; 207 break; 208 default: 209 reset(); 210 } 211 212 /* 213 * The type id and definition follow. 214 */ 215 cp = id(cp, &h); 216 if (*cp == '"') { 217 struct tdesc *ntdp; 218 219 cp++; 220 ntdp = lookup(h); 221 if (ntdp == NULL) { /* if that type isn't defined yet */ 222 if (*cp++ != '=') /* better be defining it now */ 223 expected("parseline/'0-9'", "=", cp - 1); 224 cp = tdefdecl(cp, h, &tdp); 225 addhash(tdp, h); /* for *(x,y) types */ 226 } else { /* that type is already defined */ 227 tdp = malloc(sizeof (*tdp)); 228 tdp->type = TYPEOF; 229 tdp->name = (w != NULL) ? strdup(w) : NULL; 230 tdp->data.tdesc = ntdp; 231 addhash(tdp, h); /* for *(x,y) types */ 232 debug(3, NULL, " %s defined as %s(%d)", w, 233 (ntdp->name != NULL) ? ntdp->name : "anon", h); 234 } 235 return; 236 } else if (*cp++ != '=') { 237 expected("parseline", "=", cp - 1); 238 } 239 if (tagdef) { 240 tagdecl(cp, &tdp, h, w); 241 } else { 242 tdefdecl(cp, h, &tdp); 243 tagadd(w, h, tdp); 244 } 245 } 246 247 /* 248 * Check if we have this node in the hash table already 249 */ 250 static struct tdesc * 251 lookup(int h) 252 { 253 int hash = HASH(h); 254 struct tdesc *tdp = hash_table[hash]; 255 256 while (tdp != NULL) { 257 if (tdp->id == h) 258 return (tdp); 259 tdp = tdp->hash; 260 } 261 return (NULL); 262 } 263 264 static char * 265 whitesp(char *cp) 266 { 267 char *orig, c; 268 269 orig = cp; 270 for (c = *cp++; isspace(c); c = *cp++) 271 ; 272 --cp; 273 return (cp); 274 } 275 276 static char * 277 name(char *cp, char **w) 278 { 279 char *new, *orig, c; 280 int len; 281 282 orig = cp; 283 c = *cp++; 284 if (c == ':') 285 *w = NULL; 286 else if (isalpha(c) || c == '_') { 287 for (c = *cp++; isalnum(c) || c == ' ' || c == '_'; c = *cp++) 288 ; 289 if (c != ':') 290 reset(); 291 len = cp - orig; 292 new = malloc(len); 293 while (orig < cp - 1) 294 *new++ = *orig++; 295 *new = '\0'; 296 *w = new - (len - 1); 297 } else 298 reset(); 299 300 return (cp); 301 } 302 303 static char * 304 number(char *cp, int *n) 305 { 306 char *next; 307 308 *n = (int)strtol(cp, &next, 10); 309 if (next == cp) 310 expected("number", "<number>", cp); 311 return (next); 312 } 313 314 static char * 315 id(char *cp, int *h) 316 { 317 int n1, n2; 318 319 if (*cp == '(') { /* SunPro style */ 320 cp++; 321 cp = number(cp, &n1); 322 if (*cp++ != ',') 323 expected("id", ",", cp - 1); 324 cp = number(cp, &n2); 325 if (*cp++ != ')') 326 expected("id", ")", cp - 1); 327 *h = n1 * 1000 + n2; 328 } else if (isdigit(*cp)) { /* gcc style */ 329 cp = number(cp, &n1); 330 *h = n1; 331 } else { 332 expected("id", "(/0-9", cp); 333 } 334 return (cp); 335 } 336 337 static void 338 tagadd(char *w, int h, struct tdesc *tdp) 339 { 340 struct tdesc *otdp; 341 342 tdp->name = w; 343 if (!(otdp = lookup(h))) 344 addhash(tdp, h); 345 else if (otdp != tdp) { 346 fprintf(stderr, "duplicate entry\n"); 347 fprintf(stderr, "old: %s %d %d %d\n", 348 otdp->name ? otdp->name : "NULL", 349 otdp->type, otdp->id / 1000, otdp->id % 1000); 350 fprintf(stderr, "new: %s %d %d %d\n", 351 tdp->name ? tdp->name : "NULL", 352 tdp->type, tdp->id / 1000, tdp->id % 1000); 353 } 354 } 355 356 static void 357 tagdecl(char *cp, struct tdesc **rtdp, int h, char *w) 358 { 359 debug(1, NULL, "tagdecl: declaring '%s'", w ? w : "(anon)"); 360 if ((*rtdp = lookup(h)) != NULL) { 361 if (w != NULL) { 362 if ((*rtdp)->name != NULL && 363 strcmp((*rtdp)->name, w) != 0) { 364 struct tdesc *tdp; 365 366 tdp = malloc(sizeof (*tdp)); 367 tdp->name = strdup(w); 368 tdp->type = TYPEOF; 369 tdp->data.tdesc = *rtdp; 370 addhash(tdp, h); /* for *(x,y) types */ 371 debug(3, NULL, " %s defined as %s(%d)", w, 372 ((*rtdp)->name != NULL) ? 373 (*rtdp)->name : "anon", h); 374 } else if ((*rtdp)->name == NULL) { 375 (*rtdp)->name = w; 376 addhash(*rtdp, h); 377 } 378 } 379 } else { 380 *rtdp = malloc(sizeof (**rtdp)); 381 (*rtdp)->name = w; 382 addhash(*rtdp, h); 383 } 384 385 switch (*cp++) { 386 case 's': 387 soudef(cp, STRUCT, rtdp); 388 break; 389 case 'u': 390 soudef(cp, UNION, rtdp); 391 break; 392 case 'e': 393 enumdef(cp, rtdp); 394 break; 395 default: 396 expected("tagdecl", "<tag type s/u/e>", cp - 1); 397 break; 398 } 399 } 400 401 static char * 402 tdefdecl(char *cp, int h, struct tdesc **rtdp) 403 { 404 struct tdesc *ntdp; 405 char *w; 406 int c, h2; 407 char type; 408 409 debug(3, cp, "tdefdecl h=%d", h); 410 411 /* Type codes */ 412 switch (type = *cp) { 413 case 'b': /* integer */ 414 c = *++cp; 415 if (c != 's' && c != 'u') 416 expected("tdefdecl/b", "[su]", cp - 1); 417 c = *++cp; 418 if (c == 'c') 419 cp++; 420 cp = intrinsic(cp, rtdp); 421 break; 422 case 'R': /* fp */ 423 /* skip up to and past ';' */ 424 while (*cp++ != ';') 425 /* NULL */; 426 cp = intrinsic(cp, rtdp); 427 break; 428 case '(': /* equiv to another type */ 429 cp = id(cp, &h2); 430 ntdp = lookup(h2); 431 if (ntdp == NULL) { /* if that type isn't defined yet */ 432 if (*cp++ != '=') /* better be defining it now */ 433 expected("tdefdecl/'('", "=", cp - 1); 434 cp = tdefdecl(cp, h2, rtdp); 435 ntdp = malloc(sizeof (*ntdp)); 436 ntdp->type = TYPEOF; 437 ntdp->data.tdesc = *rtdp; 438 addhash(ntdp, h2); 439 } else { /* that type is already defined */ 440 *rtdp = malloc(sizeof (**rtdp)); 441 (*rtdp)->type = TYPEOF; 442 (*rtdp)->data.tdesc = ntdp; 443 } 444 break; 445 case '*': 446 ntdp = NULL; 447 cp = tdefdecl(cp + 1, h, &ntdp); 448 if (ntdp == NULL) 449 expected("tdefdecl/*", "id", cp); 450 451 *rtdp = malloc(sizeof (**rtdp)); 452 (*rtdp)->type = POINTER; 453 (*rtdp)->size = model->pointersize; 454 (*rtdp)->name = "pointer"; 455 (*rtdp)->data.tdesc = ntdp; 456 break; 457 case 'f': 458 cp = tdefdecl(cp + 1, h, &ntdp); 459 *rtdp = malloc(sizeof (**rtdp)); 460 (*rtdp)->type = FUNCTION; 461 (*rtdp)->size = model->pointersize; 462 (*rtdp)->name = "function"; 463 (*rtdp)->data.tdesc = ntdp; 464 break; 465 case 'a': 466 cp++; 467 if (*cp++ != 'r') 468 expected("tdefdecl/a", "r", cp - 1); 469 *rtdp = malloc(sizeof (**rtdp)); 470 (*rtdp)->type = ARRAY; 471 (*rtdp)->name = "array"; 472 cp = arraydef(cp, rtdp); 473 break; 474 case 'x': 475 c = *++cp; 476 if (c != 's' && c != 'u' && c != 'e') 477 expected("tdefdecl/x", "[sue]", cp - 1); 478 cp = name(cp + 1, &w); 479 *rtdp = malloc(sizeof (**rtdp)); 480 (*rtdp)->type = FORWARD; 481 (*rtdp)->name = w; 482 break; 483 case 'B': /* volatile */ 484 cp = tdefdecl(cp + 1, h, &ntdp); 485 *rtdp = malloc(sizeof (**rtdp)); 486 (*rtdp)->type = VOLATILE; 487 (*rtdp)->size = 0; 488 (*rtdp)->name = "volatile"; 489 (*rtdp)->data.tdesc = ntdp; 490 break; 491 case 'k': /* const */ 492 cp = tdefdecl(cp + 1, h, &ntdp); 493 *rtdp = malloc(sizeof (**rtdp)); 494 (*rtdp)->type = CONST; 495 (*rtdp)->size = 0; 496 (*rtdp)->name = "const"; 497 (*rtdp)->data.tdesc = ntdp; 498 break; 499 case '0': case '1': case '2': case '3': case '4': 500 case '5': case '6': case '7': case '8': case '9': 501 /* gcc equiv to another type */ 502 cp = id(cp, &h2); 503 ntdp = lookup(h2); 504 if (ntdp == NULL) { /* if that type isn't defined yet */ 505 /* better be defining it now */ 506 if (*cp++ != '=') { 507 if (h != h2) 508 expected("tdefdecl/'0-9'", "=", cp - 1); 509 /* defined in terms of itself */ 510 *rtdp = malloc(sizeof (**rtdp)); 511 (*rtdp)->type = INTRINSIC; 512 (*rtdp)->name = "void"; 513 (*rtdp)->size = 0; 514 } else { 515 cp = tdefdecl(cp, h2, rtdp); 516 ntdp = malloc(sizeof (*ntdp)); 517 ntdp->type = TYPEOF; 518 ntdp->data.tdesc = *rtdp; 519 addhash(ntdp, h2); 520 } 521 } else { /* that type is already defined */ 522 *rtdp = malloc(sizeof (**rtdp)); 523 (*rtdp)->type = TYPEOF; 524 (*rtdp)->data.tdesc = ntdp; 525 } 526 break; 527 case 'u': 528 case 's': 529 cp++; 530 531 *rtdp = malloc(sizeof (**rtdp)); 532 (*rtdp)->name = NULL; 533 cp = soudef(cp, (type == 'u') ? UNION : STRUCT, rtdp); 534 break; 535 default: 536 expected("tdefdecl", "<type code>", cp); 537 } 538 return (cp); 539 } 540 541 static char * 542 intrinsic(char *cp, struct tdesc **rtdp) 543 { 544 struct tdesc *tdp; 545 int size; 546 547 cp = number(cp, &size); 548 tdp = malloc(sizeof (*tdp)); 549 tdp->type = INTRINSIC; 550 tdp->size = size; 551 tdp->name = NULL; 552 debug(3, NULL, "intrinsic: size=%ld", size); 553 *rtdp = tdp; 554 return (cp); 555 } 556 557 static char * 558 soudef(char *cp, enum type type, struct tdesc **rtdp) 559 { 560 struct mlist **next_pp, *prev_p = NULL; 561 char *w; 562 int size; 563 struct tdesc *tdp; 564 565 cp = number(cp, &size); 566 (*rtdp)->size = size; 567 (*rtdp)->type = type; /* s or u */ 568 569 /* 570 * An '@' here indicates a bitmask follows. This is so the 571 * compiler can pass information to debuggers about how structures 572 * are passed in the v9 world. We don't need this information 573 * so we skip over it. 574 */ 575 if (cp[0] == '@') 576 cp += 3; 577 578 debug(3, cp, "soudef: %s size=%d", 579 (*rtdp)->name ? (*rtdp)->name : "(anonsou)", 580 (*rtdp)->size); 581 582 next_pp = &((*rtdp)->data.members.forw); /* head for forward linklist */ 583 /* fill up the fields */ 584 while ((*cp != '"') && (*cp != ';')) { /* signifies end of fields */ 585 int h; 586 struct mlist *mlp = malloc(sizeof (*mlp)); 587 588 mlp->prev = prev_p; /* links for the backward list */ 589 prev_p = mlp; 590 *next_pp = mlp; /* links for the forward list */ 591 next_pp = &mlp->next; 592 593 cp = name(cp, &w); 594 mlp->name = w; 595 cp = id(cp, &h); 596 /* 597 * find the tdesc struct in the hash table for this type 598 * and stick a ptr in here 599 */ 600 tdp = lookup(h); 601 if (tdp == NULL) { /* not in hash list */ 602 debug(3, NULL, " defines %s (%d)", w, h); 603 if (*cp++ != '=') 604 expected("soudef", "=", cp - 1); 605 cp = tdefdecl(cp, h, &tdp); 606 addhash(tdp, h); 607 debug(4, cp, " soudef now looking at "); 608 cp++; 609 610 } else { 611 debug(3, NULL, " refers to %s (%d, %s)", 612 w ? w : "anon", h, tdp->name ? tdp->name : "anon"); 613 } 614 615 mlp->fdesc = tdp; 616 cp = offsize(cp, mlp); /* cp is now pointing to next field */ 617 if (*cp == '\\') /* could be a continuation */ 618 cp = get_continuation(); 619 } 620 (*rtdp)->data.members.back = prev_p; /* head for backward linklist */ 621 return (cp); 622 } 623 624 static char * 625 offsize(char *cp, struct mlist *mlp) 626 { 627 int offset, size; 628 629 if (*cp == ',') 630 cp++; 631 cp = number(cp, &offset); 632 if (*cp++ != ',') 633 expected("offsize/2", ",", cp - 1); 634 cp = number(cp, &size); 635 if (*cp++ != ';') 636 expected("offsize/3", ";", cp - 1); 637 mlp->offset = offset; 638 mlp->size = size; 639 return (cp); 640 } 641 642 static char * 643 arraydef(char *cp, struct tdesc **rtdp) 644 { 645 int h; 646 int start, end; 647 648 cp = id(cp, &h); 649 if (*cp++ != ';') 650 expected("arraydef/1", ";", cp - 1); 651 652 (*rtdp)->data.ardef = malloc(sizeof (struct ardef)); 653 (*rtdp)->data.ardef->indices = malloc(sizeof (struct element)); 654 (*rtdp)->data.ardef->indices->index_type = lookup(h); 655 656 cp = number(cp, &start); /* lower */ 657 if (*cp++ != ';') 658 expected("arraydef/2", ";", cp - 1); 659 cp = number(cp, &end); /* upper */ 660 if (*cp++ != ';') 661 expected("arraydef/3", ";", cp - 1); 662 (*rtdp)->data.ardef->indices->range_start = start; 663 (*rtdp)->data.ardef->indices->range_end = end; 664 #if 0 665 if (isdigit(*cp)) { 666 cp = number(cp, &contents_type); /* lower */ 667 tdp = lookup(contents_type); 668 if (tdp != NULL) { 669 (*rtdp)->data.ardef->contents = tdp; 670 } else { 671 if (*cp != '=') 672 expected("arraydef/4", "=", cp); 673 cp = tdefdecl(cp + 1, h, &tdp); 674 addhash(tdp, h); /* for *(x,y) types */ 675 (*rtdp)->data.ardef->contents = tdp; 676 } 677 } /* else */ 678 #endif 679 cp = tdefdecl(cp, h, &((*rtdp)->data.ardef->contents)); 680 return (cp); 681 } 682 683 static void 684 enumdef(char *cp, struct tdesc **rtdp) 685 { 686 struct elist *elp, **prev; 687 char *w; 688 689 (*rtdp)->type = ENUM; 690 (*rtdp)->data.emem = NULL; 691 692 prev = &((*rtdp)->data.emem); 693 while (*cp != ';') { 694 elp = malloc(sizeof (*elp)); 695 elp->next = NULL; 696 *prev = elp; 697 cp = name(cp, &w); 698 elp->name = w; 699 cp = number(cp, &elp->number); 700 debug(3, NULL, "enum %s: %s=%ld", 701 (*rtdp)->name ? (*rtdp)->name : "(anon enum)", 702 elp->name, elp->number); 703 prev = &elp->next; 704 if (*cp++ != ',') 705 expected("enumdef", ",", cp - 1); 706 if (*cp == '\\') 707 cp = get_continuation(); 708 } 709 } 710 711 /* 712 * Add a node to the hash queues. 713 */ 714 static void 715 addhash(struct tdesc *tdp, int num) 716 { 717 int hash = HASH(num); 718 struct tdesc *ttdp; 719 char added_num = 0, added_name = 0; 720 721 /* 722 * If it already exists in the hash table don't add it again 723 * (but still check to see if the name should be hashed). 724 */ 725 ttdp = lookup(num); 726 if (ttdp == NULL) { 727 tdp->id = num; 728 tdp->hash = hash_table[hash]; 729 hash_table[hash] = tdp; 730 added_num = 1; 731 } 732 733 if (tdp->name != NULL) { 734 ttdp = lookupname(tdp->name); 735 if (ttdp == NULL) { 736 hash = compute_sum(tdp->name); 737 tdp->next = name_table[hash]; 738 name_table[hash] = tdp; 739 added_name = 1; 740 } 741 } 742 if (!added_num && !added_name) { 743 fprintf(stderr, "stabs: broken hash\n"); 744 exit(1); 745 } 746 } 747 748 struct tdesc * 749 lookupname(char *name) 750 { 751 int hash = compute_sum(name); 752 struct tdesc *tdp, *ttdp = NULL; 753 754 for (tdp = name_table[hash]; tdp != NULL; tdp = tdp->next) { 755 if (tdp->name != NULL && strcmp(tdp->name, name) == 0) { 756 if (tdp->type == STRUCT || tdp->type == UNION || 757 tdp->type == ENUM || tdp->type == INTRINSIC) 758 return (tdp); 759 if (tdp->type == TYPEOF) 760 ttdp = tdp; 761 } 762 } 763 return (ttdp); 764 } 765 766 static int 767 compute_sum(char *w) 768 { 769 char c; 770 int sum; 771 772 for (sum = 0; (c = *w) != '\0'; sum += c, w++) 773 ; 774 return (HASH(sum)); 775 } 776 777 static void 778 reset(void) 779 { 780 longjmp(resetbuf, 1); 781 /* NOTREACHED */ 782 } 783