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 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * diagcode library, Sun Private API (PSARC/2004/601) 29 * 30 * undocumented debugging interface: 31 * set environment variable _FM_DC_DEBUG for debug prints to stderr. 32 * set it to 1 for extended error messages only. 33 * set it to 2 to include success info too on interesting functions. 34 * set it to 3 to include success info on trivial functions too. 35 * note that this environment variable is only examined in fm_dc_opendict(). 36 */ 37 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <ctype.h> 42 #include <alloca.h> 43 #include <errno.h> 44 45 #include <fm/diagcode.h> 46 47 /* private (opaque to callers) handle information */ 48 struct fm_dc_handle { 49 const char *dictname; 50 FILE *fp; 51 unsigned maxkey; 52 int version; 53 int debug; 54 /* name/value pairs from .dict header */ 55 struct fm_dc_prop { 56 struct fm_dc_prop *next; 57 const char *lhs; 58 const char *rhs; 59 } *props; 60 }; 61 62 /* 63 * parameters of the various sizes of diagcodes 64 * 65 * table must be in ascending order from smallest databits value to largest. 66 * when faced with more databits than the last entry, we know we have 67 * something that won't fit into a diagcode. 68 */ 69 static const struct info { 70 int databits; /* number of bits used to hold dictionary value */ 71 int numx; /* number of digits (also called X's) in code */ 72 int csumbits; /* number of bits used for checksum */ 73 int sizeval; /* value encoded into "size" field of code */ 74 unsigned long long offset; /* databits==0 stands for this value */ 75 } Info[] = { 76 /* diagcode is: dictname-XXXX-XX */ 77 { 21, 6, 5, 0, 0ULL }, 78 79 /* diagcode is: dictname-XXXX-XXXX-XX */ 80 { 38, 10, 8, 1, 2097152ULL }, 81 82 /* diagcode is: dictname-XXXX-XXXX-XXXX-XX */ 83 { 55, 14, 11, 2, 274880004096ULL }, 84 85 /* diagcode is: dictname-XXXX-XXXX-XXXX-XXXX-XX */ 86 { 72, 18, 14, 3, 36029071898968064ULL } 87 }; 88 #define MAXDATABITS 72 /* highest entry in table above */ 89 #define MAXCODELEN 25 /* big enough to hold the X's, dashes, and \0 */ 90 91 /* forward references for functions private to this file */ 92 typedef struct bitv bitv; 93 static const struct info *dictval2info(const bitv *bv); 94 static const struct info *numx2info(int numx); 95 static void sortkey(const char *key[]); 96 static const char *keymatch(const char *linebuf, const char *key[]); 97 static int buildcode(fm_dc_handle_t *dhp, const char *rhsp, 98 char *code, size_t maxcode, char *debugstr); 99 static bitv *code2dictval(fm_dc_handle_t *dhp, const char *code); 100 struct parsestate { 101 char *parseptr; /* next unparsed character in buffer */ 102 char *rhsp; /* rhs associated with last lhs (or NULL) */ 103 }; 104 static void startparse(struct parsestate *ps, char *ptr); 105 static char *nextlhs(struct parsestate *ps); 106 static char *nextrhs(struct parsestate *ps); 107 static bitv *bitv_alloc(void); 108 static void bitv_free(bitv *bv); 109 static void bitv_shift(bitv *bv, unsigned bits); 110 static void bitv_setlo(bitv *bv, unsigned bits, unsigned val); 111 static void bitv_shiftin(bitv *bv, unsigned bits, unsigned val); 112 static void bitv_shiftinv(bitv *bv, unsigned bits, const bitv *inbv); 113 static int bitv_bits(const bitv *bv); 114 static unsigned bitv_chunk(const bitv *bv, unsigned limbit, unsigned lobit); 115 static int bitv_mul(bitv *bv, unsigned long long val); 116 static int bitv_add(bitv *bv, unsigned long long val); 117 static int bitv_sub(bitv *bv, unsigned long long val); 118 static int bitv_ge(const bitv *bv, unsigned long long val); 119 static bitv *bitv_strparse(const char *s, int bits); 120 static int bitv_cmp(const bitv *bv1, const bitv *bv2); 121 static void crc(unsigned long *crcp, unsigned val); 122 123 #define DICTMAXLINE 10240 /* maximum expected dictionary line length */ 124 125 #define MAXDEBUGSTR 100 /* for debug messages */ 126 127 static const char Suffix[] = ".dict"; /* suffix on dictionary filename */ 128 static const char Defaultpath[] = "/usr/lib/fm/dict"; 129 static const char Debugenv[] = "_FM_DC_DEBUG"; /* debug environment var */ 130 131 /* properties we look for at top of dictionary */ 132 static const char Header[] = "FMDICT: "; 133 static const char Name[] = "name"; 134 static const char Version[] = "version"; 135 static const char Maxkey[] = "maxkey"; 136 137 /* the alphabet used to encode information in a diagcode (base32 digits) */ 138 static const char Alphabet[] = "0123456789ACDEFGHJKLMNPQRSTUVWXY"; 139 140 /* open a dictionary, return opaque handle */ 141 fm_dc_handle_t * 142 fm_dc_opendict(int version, const char *dirpath, const char *dictname) 143 { 144 int debug = 0; /* set by environment variable */ 145 char *debugstr = ""; /* error path debug prefix text */ 146 fm_dc_handle_t *dhp = NULL; 147 char *fname; /* full dict file name */ 148 char linebuf[DICTMAXLINE]; /* line read from dict */ 149 int line = 0; /* line number in dict */ 150 unsigned prop_version = 0; /* version property from dict */ 151 char *prop_name = ""; /* name property from dict */ 152 char *lhsp; /* prop left-hand-side */ 153 char *rhsp; /* prop right-hand-side */ 154 struct parsestate pstate; /* for startparse(), nextlhs(), etc */ 155 156 /* undocumented flag, given via environment variable */ 157 if ((rhsp = getenv(Debugenv)) != NULL) 158 debug = atoi(rhsp); 159 160 if (debug > 1) 161 (void) fprintf(stderr, 162 "fm_dc_opendict: ver %d path \"%s\" dict \"%s\": ", 163 version, (dirpath == NULL) ? "NULL" : dirpath, dictname); 164 else if (debug) 165 debugstr = "fm_dc_opendict: "; /* used in error paths */ 166 167 /* verify caller expects an API version we support */ 168 if (version < 0 || version > FM_DC_VERSION) { 169 if (debug) 170 (void) fprintf(stderr, "%sENOTSUP ver not in [0-%d]\n", 171 debugstr, FM_DC_VERSION); 172 errno = ENOTSUP; 173 return (NULL); 174 } 175 176 /* caller can pass in NULL for default dirpath */ 177 if (dirpath == NULL) 178 dirpath = Defaultpath; 179 180 /* 181 * allocate buffer for dirpath, slash, dictname, and suffix 182 * (sizeof (Suffix) includes the null). 183 */ 184 fname = alloca(strlen(dirpath) + 1 + 185 strlen(dictname) + sizeof (Suffix)); 186 187 /* 188 * allocate the handle. 189 * 190 * allocate the dictname copy kept in the handle. 191 * 192 * if any of these fail, send back ENOMEM. 193 */ 194 if ((dhp = malloc(sizeof (*dhp))) == NULL || 195 (dhp->dictname = strdup(dictname)) == NULL) { 196 if (dhp) 197 free(dhp); 198 if (debug) 199 (void) fprintf(stderr, "%sENOMEM\n", debugstr); 200 errno = ENOMEM; 201 return (NULL); 202 } 203 204 /* initialize the handle */ 205 (void) strcpy(fname, dirpath); 206 (void) strcat(fname, "/"); 207 (void) strcat(fname, dictname); 208 (void) strcat(fname, Suffix); 209 dhp->fp = NULL; 210 dhp->maxkey = 0; 211 dhp->version = version; 212 dhp->debug = debug; 213 dhp->props = NULL; 214 215 /* open the dictionary */ 216 if (debug > 1) 217 (void) fprintf(stderr, "\"%s\": ", fname); 218 if ((dhp->fp = fopen(fname, "r")) == NULL) { 219 int oerrno = errno; /* fopen() set errno to something */ 220 221 if (debug > 1) 222 perror("fopen"); 223 else if (debug) { 224 (void) fprintf(stderr, "%s%s: ", debugstr, fname); 225 errno = oerrno; 226 perror("fopen"); 227 } 228 fm_dc_closedict(dhp); 229 errno = oerrno; 230 return (NULL); 231 } 232 233 /* pull in the header line and parse it */ 234 while (fgets(linebuf, DICTMAXLINE, dhp->fp) != NULL) { 235 line++; 236 if (*linebuf == '\n' || *linebuf == '#') 237 continue; 238 239 /* first non-comment, non-blank line must be header */ 240 if (strncmp(linebuf, Header, sizeof (Header) - 1)) { 241 fm_dc_closedict(dhp); 242 if (debug) 243 (void) fprintf(stderr, 244 "%sEINVAL: line %d: header expected.\n", 245 debugstr, line); 246 errno = EINVAL; 247 return (NULL); 248 } 249 250 /* just wanted header line for now */ 251 break; 252 } 253 254 /* walk through name=value pairs in line after Header string */ 255 startparse(&pstate, &linebuf[sizeof (Header) - 1]); 256 while ((lhsp = nextlhs(&pstate)) != NULL) { 257 struct fm_dc_prop *propp; 258 259 if ((rhsp = nextrhs(&pstate)) == NULL) { 260 if (debug) 261 (void) fprintf(stderr, "%sEINVAL " 262 "%s prop has no value\n", debugstr, lhsp); 263 fm_dc_closedict(dhp); 264 errno = EINVAL; 265 return (NULL); 266 } 267 268 propp = malloc(sizeof (*propp)); 269 if (propp == NULL || 270 (propp->lhs = strdup(lhsp)) == NULL || 271 (propp->rhs = strdup(rhsp)) == NULL) { 272 if (debug) 273 (void) fprintf(stderr, "%sENOMEM\n", debugstr); 274 if (propp != NULL) { 275 if (propp->lhs != NULL) 276 free((void *) propp->lhs); 277 free((void *) propp); 278 } 279 fm_dc_closedict(dhp); 280 errno = ENOMEM; 281 return (NULL); 282 } 283 propp->next = dhp->props; 284 dhp->props = propp; 285 286 if (strcmp(lhsp, Name) == 0) 287 prop_name = rhsp; 288 else if (strcmp(lhsp, Version) == 0) 289 prop_version = strtoul(rhsp, NULL, 0); 290 else if (strcmp(lhsp, Maxkey) == 0) 291 dhp->maxkey = strtoul(rhsp, NULL, 0); 292 } 293 294 /* 295 * require version 1, expected dict name, and maxkey values 296 * (note we use "1" here and not FM_DC_VERSION because this code 297 * implements version 1, so the check below should not float to 298 * newer version numbers if the header file defines them.) 299 */ 300 if (prop_version != 1UL || strcmp(prop_name, dictname) || 301 dhp->maxkey == 0) { 302 fm_dc_closedict(dhp); 303 if (debug) 304 (void) fprintf(stderr, 305 "%sEINVAL ver %d name \"%s\" maxkey %d\n", 306 debugstr, prop_version, prop_name, dhp->maxkey); 307 errno = EINVAL; 308 return (NULL); 309 } 310 311 if (debug > 1) 312 (void) fprintf(stderr, "fm_dc_opendict: dhp 0x%p\n", 313 (void *)dhp); 314 return (dhp); 315 } 316 317 /* close a dictionary */ 318 void 319 fm_dc_closedict(fm_dc_handle_t *dhp) 320 { 321 struct fm_dc_prop *props; 322 struct fm_dc_prop *oprops; 323 324 if (dhp->debug > 1) 325 (void) fprintf(stderr, "fm_dc_closedict: dhp 0x%p\n", 326 (void *)dhp); 327 if (dhp->fp) 328 (void) fclose(dhp->fp); 329 330 free((void *) dhp->dictname); 331 332 props = dhp->props; 333 while (props) { 334 if (props->lhs != NULL) 335 free((void *) props->lhs); 336 if (props->rhs != NULL) 337 free((void *) props->rhs); 338 oprops = props; 339 props = props->next; 340 free((void *) oprops); 341 } 342 343 free(dhp); 344 } 345 346 /* return maximum length (in bytes) of diagcodes for a given dictionary */ 347 size_t 348 fm_dc_codelen(fm_dc_handle_t *dhp) 349 { 350 size_t len = strlen(dhp->dictname); 351 352 /* only one version so far, so dhp->version isn't checked */ 353 354 if (dhp->debug > 2) 355 (void) fprintf(stderr, "fm_dc_codelen: dhp 0x%p: %d\n", 356 (void *)dhp, (int)(len + MAXCODELEN)); 357 return (len + MAXCODELEN); 358 } 359 360 /* return number of strings in key for a given dictionary */ 361 int 362 fm_dc_maxkey(fm_dc_handle_t *dhp) 363 { 364 /* only one version so far, so dhp->version isn't checked */ 365 366 /* this interface counts the NULL entry */ 367 if (dhp->debug > 2) 368 (void) fprintf(stderr, "fm_dc_maxkey: dhp 0x%p: maxkey %d\n", 369 (void *)dhp, dhp->maxkey + 1); 370 return (dhp->maxkey + 1); 371 } 372 373 /* given a key, construct a diagcode */ 374 int 375 fm_dc_key2code(fm_dc_handle_t *dhp, 376 const char *key[], char *code, size_t maxcode) 377 { 378 char *debugstr = ""; /* error path debug prefix text */ 379 int line = 0; /* line number in dict */ 380 char linebuf[DICTMAXLINE]; /* line read from dict */ 381 const char *rhsp; /* right-hand-side of entry */ 382 383 /* only one version so far, so dhp->version isn't checked */ 384 385 if (dhp->debug > 1) { 386 int nel; 387 388 (void) fprintf(stderr, 389 "fm_dc_key2code: dhp 0x%p maxcode %lu ", (void *)dhp, 390 (ulong_t)maxcode); 391 for (nel = 0; key[nel]; nel++) 392 (void) fprintf(stderr, "\"%s\" ", key[nel]); 393 } else if (dhp->debug) 394 debugstr = "fm_dc_key2code: "; 395 396 /* sort the keys */ 397 sortkey(key); 398 399 rewind(dhp->fp); 400 401 while (fgets(linebuf, DICTMAXLINE, dhp->fp) != NULL) { 402 line++; 403 if (*linebuf == '\n' || *linebuf == '#') 404 continue; 405 406 /* first non-comment, non-blank line must be header */ 407 if (strncmp(linebuf, Header, sizeof (Header) - 1) == 0) 408 continue; 409 410 if ((rhsp = keymatch(linebuf, key)) != NULL) { 411 char ndebugstr[MAXDEBUGSTR]; 412 413 if (dhp->debug > 1) 414 (void) fprintf(stderr, "match line %d: ", line); 415 else { 416 (void) snprintf(ndebugstr, MAXDEBUGSTR, 417 "fm_dc_key2code: dictionary line %d", 418 line); 419 debugstr = ndebugstr; 420 } 421 422 return (buildcode(dhp, rhsp, code, maxcode, debugstr)); 423 } 424 } 425 426 /* no match */ 427 if (dhp->debug) 428 (void) fprintf(stderr, "%sENOMSG no match\n", debugstr); 429 errno = ENOMSG; 430 return (-1); 431 } 432 433 /* given a diagcode, return the key (array of strings) */ 434 int 435 fm_dc_code2key(fm_dc_handle_t *dhp, const char *code, 436 char *key[], int maxkey) 437 { 438 char *debugstr = ""; /* error path debug prefix text */ 439 int line = 0; 440 char linebuf[DICTMAXLINE]; 441 bitv *dictval; 442 443 /* only one version so far, so dhp->version isn't checked */ 444 445 if (dhp->debug > 1) 446 (void) fprintf(stderr, 447 "fm_dc_code2key: dhp 0x%p code \"%s\" maxkey %d: ", 448 (void *)dhp, code, maxkey); 449 else if (dhp->debug) 450 debugstr = "fm_dc_code2key: "; 451 452 /* convert code back to bit vector */ 453 if ((dictval = code2dictval(dhp, code)) == NULL) { 454 /* code2dictval() sets errno */ 455 if (dhp->debug) { 456 int oerrno = errno; 457 458 /* handle expected types without printing a number */ 459 if (errno == ENOMEM) 460 (void) fprintf(stderr, 461 "%sENOMEM code2dictval\n", 462 debugstr); 463 else if (errno == EINVAL) 464 (void) fprintf(stderr, 465 "%sEINVAL code2dictval\n", 466 debugstr); 467 else 468 (void) fprintf(stderr, 469 "%scode2dictval error %d\n", 470 debugstr, oerrno); 471 errno = oerrno; 472 } 473 return (-1); 474 } 475 476 rewind(dhp->fp); 477 478 while (fgets(linebuf, DICTMAXLINE, dhp->fp) != NULL) { 479 char *ptr; 480 bitv *thisval; 481 char *beginp; 482 char *endp; 483 int nel; 484 485 line++; 486 if (*linebuf == '\n' || *linebuf == '#') 487 continue; 488 489 /* first non-comment, non-blank line must be header */ 490 if (strncmp(linebuf, Header, sizeof (Header) - 1) == 0) 491 continue; 492 493 if ((ptr = strchr(linebuf, '=')) == NULL) 494 continue; /* ignore malformed entries */ 495 496 *ptr++ = '\0'; 497 498 /* pull in value from dictionary */ 499 if ((thisval = bitv_strparse(ptr, MAXDATABITS)) == NULL) { 500 /* bitv_strparse() sets errno */ 501 if (errno == ENOMEM) { 502 bitv_free(dictval); 503 if (dhp->debug) 504 (void) fprintf(stderr, 505 "%sENOMEM bitv_strparse\n", 506 debugstr); 507 errno = ENOMEM; 508 return (-1); 509 } 510 /* other than ENOMEM, trudge on... */ 511 continue; 512 } 513 514 if (bitv_cmp(thisval, dictval)) { 515 bitv_free(thisval); 516 continue; 517 } 518 519 /* if we got here, we found the match */ 520 bitv_free(thisval); 521 bitv_free(dictval); 522 beginp = linebuf; 523 nel = 0; 524 for (;;) { 525 while (*beginp && isspace(*beginp)) 526 beginp++; 527 if (*beginp == '\0') { 528 /* all done */ 529 key[nel] = NULL; 530 return (0); 531 } 532 if (nel >= maxkey - 1) { 533 if (dhp->debug) 534 (void) fprintf(stderr, 535 "%sENOMEM maxkey %d\n", 536 debugstr, maxkey); 537 errno = ENOMEM; 538 return (-1); 539 } 540 for (endp = beginp; *endp && !isspace(*endp); endp++) 541 ; 542 if (*endp) 543 *endp++ = '\0'; 544 if ((key[nel++] = strdup(beginp)) == NULL) { 545 if (dhp->debug) 546 (void) fprintf(stderr, 547 "%sENOMEM strdup\n", debugstr); 548 errno = ENOMEM; 549 return (-1); 550 } 551 beginp = endp; 552 } 553 } 554 555 bitv_free(dictval); 556 if (dhp->debug) 557 (void) fprintf(stderr, "%sENOMSG\n", debugstr); 558 errno = ENOMSG; 559 return (-1); 560 } 561 562 /* return the right-hand side of a names property from the dict header */ 563 const char * 564 fm_dc_getprop(fm_dc_handle_t *dhp, const char *name) 565 { 566 struct fm_dc_prop *props; 567 568 /* only one version so far, so dhp->version isn't checked */ 569 570 if (dhp->debug > 2) 571 (void) fprintf(stderr, "fm_dc_getprop: dhp 0x%p: \"%s\"", 572 (void *)dhp, name); 573 574 for (props = dhp->props; props; props = props->next) 575 if (strcmp(name, props->lhs) == 0) 576 break; 577 578 if (dhp->debug > 2) 579 (void) fprintf(stderr, "= \"%s\"\n", 580 (props == NULL) ? "NULL" : props->rhs); 581 582 return ((props == NULL) ? NULL : props->rhs); 583 } 584 585 /* find the appropriate diagcode format for a given dictval */ 586 static const struct info * 587 dictval2info(const bitv *bv) 588 { 589 int i; 590 591 for (i = 0; i < sizeof (Info) / sizeof (*Info) - 1; i++) 592 if (!bitv_ge(bv, Info[i + 1].offset)) 593 return (&Info[i]); 594 595 /* return largest format */ 596 return (&Info[sizeof (Info) / sizeof (*Info) - 1]); 597 } 598 599 /* lookup the diagcode parameters given the number of X's used */ 600 static const struct info * 601 numx2info(int numx) 602 { 603 int i; 604 605 for (i = 0; i < sizeof (Info) / sizeof (*Info); i++) 606 if (numx == Info[i].numx) 607 return (&Info[i]); 608 609 return (NULL); 610 } 611 612 /* for use with qsort() */ 613 static int 614 mycmp(const void *a, const void *b) 615 { 616 return (strcmp(*(char **)a, *(char **)b)); 617 } 618 619 /* 620 * sortkey -- make sure key[] array is lexically sorted and without repeats 621 */ 622 static void 623 sortkey(const char *key[]) 624 { 625 int nel; 626 int srci; /* source index when iterating through key[] */ 627 int dsti; /* dest index when storing elements in key[] */ 628 629 /* count the number of elements in key[] */ 630 for (nel = 0; key[nel]; nel++) 631 ; 632 633 if (nel < 2) 634 return; /* nothing to sort */ 635 636 qsort((void *)key, nel, sizeof (char *), mycmp); 637 638 /* go through array and remove repeats */ 639 dsti = 1; 640 for (srci = 1; srci < nel; srci++) 641 if (strcmp(key[srci], key[dsti - 1]) != 0) 642 key[dsti++] = key[srci]; 643 key[dsti] = NULL; 644 } 645 646 /* 647 * keymatch -- check for matching line from the dictionary 648 * 649 * assumes that the key[] array has already been lexically sorted. 650 * returns NULL if no match, otherwise pointer to first character of RHS. 651 */ 652 static const char * 653 keymatch(const char *linebuf, const char *key[]) 654 { 655 int keynum = 0; 656 const char *ptr; 657 658 while (linebuf) { 659 /* skip any initial whitespace in front of name */ 660 while (*linebuf && isspace(*linebuf)) 661 linebuf++; 662 663 ptr = key[keynum]; 664 665 if (ptr == NULL && *linebuf == '=') { 666 /* match */ 667 linebuf++; 668 while (*linebuf && isspace(*linebuf)) 669 linebuf++; 670 return (linebuf); 671 } else if (ptr == NULL) 672 return (NULL); /* dict had more strings for key */ 673 674 /* match the string */ 675 while (*linebuf) 676 if (*ptr == '\0') { 677 if (isspace(*linebuf) || *linebuf == '=') 678 break; /* match */ 679 else 680 return (NULL); /* dict string longer */ 681 } else if (*linebuf != *ptr) 682 return (NULL); /* string don't match */ 683 else { 684 linebuf++; 685 ptr++; 686 } 687 688 keynum++; 689 } 690 691 return (NULL); /* no match */ 692 } 693 694 /* 695 * buildcode -- given the val from the dictionary, create the diagcode 696 */ 697 static int 698 buildcode(fm_dc_handle_t *dhp, const char *rhsp, 699 char *code, size_t maxcode, char *debugstr) 700 { 701 char *codebegin = code; /* remember start of code buffer */ 702 const struct info *infop; /* Info[] table entry */ 703 unsigned long csum = 0; /* checksum (CRC) of diagcode */ 704 const char *ptr; 705 bitv *dictval; /* value from dictionary */ 706 bitv *allbits; /* assembled diagcode in binary */ 707 int bit; /* for looping through bits */ 708 int limbit; /* upper bit limit when looping */ 709 710 /* sanity check that buffer is large enough for diagcode */ 711 if (maxcode < fm_dc_codelen(dhp)) { 712 if (dhp->debug) 713 (void) fprintf(stderr, 714 "%sENOMEM maxcode %lu < codelen %lu\n", 715 debugstr, (ulong_t)maxcode, 716 (ulong_t)fm_dc_codelen(dhp)); 717 errno = ENOMEM; 718 return (-1); 719 } 720 721 /* handle dictname part of checksum */ 722 for (ptr = dhp->dictname; *ptr; ptr++) { 723 crc(&csum, (unsigned)*ptr); 724 *code++ = *ptr; 725 } 726 727 /* pull in value from dictionary */ 728 if ((dictval = bitv_strparse(rhsp, MAXDATABITS)) == NULL) { 729 /* bitv_strparse() sets errno */ 730 if (dhp->debug) { 731 int oerrno = errno; 732 733 /* handle expected types without printing a number */ 734 if (errno == ENOMEM) 735 (void) fprintf(stderr, 736 "%sENOMEM bitv_strparse\n", 737 debugstr); 738 else if (errno == ERANGE) 739 (void) fprintf(stderr, 740 "%sERANGE bitv_strparse\n", 741 debugstr); 742 else 743 (void) fprintf(stderr, 744 "%sbitv_strparse error %d\n", 745 debugstr, oerrno); 746 errno = oerrno; 747 } 748 return (-1); 749 } 750 751 /* determine which format of code we're using */ 752 infop = dictval2info(dictval); 753 754 /* subtract off the offset appropriate for format of code */ 755 if (dhp->debug > 3) 756 (void) fprintf(stderr, 757 "%ssubtract offset %llu\n", debugstr, infop->offset); 758 if (bitv_sub(dictval, infop->offset) < 0) { 759 /* 760 * this "cannot happen" since code format was chosen 761 * so that offset will be smaller than dictval, and 762 * dictval cannot be out of range since bitv_strparse() 763 * should have caught it. 764 */ 765 if (dhp->debug) 766 (void) fprintf(stderr, 767 "%sERANGE from bitv_sub\n", debugstr); 768 bitv_free(dictval); 769 errno = ERANGE; 770 return (-1); 771 } 772 773 /* assemble all the bits for the diagcode */ 774 if ((allbits = bitv_alloc()) == NULL) { 775 bitv_free(dictval); 776 if (dhp->debug) 777 (void) fprintf(stderr, 778 "%sENOMEM from bitv_alloc\n", debugstr); 779 errno = ENOMEM; 780 return (-1); 781 } 782 783 /* 784 * construct the full diagcode by shifting in information: 785 * - 2 bit code type, set to 01 786 * - 2 bit size field 787 * - the databits of the dictionary code itself 788 */ 789 790 bitv_shiftin(allbits, 2, 1); 791 bitv_shiftin(allbits, 2, infop->sizeval); 792 bitv_shiftinv(allbits, infop->databits, dictval); 793 794 /* insert zeros for checksum */ 795 bitv_shiftin(allbits, infop->csumbits, 0); 796 797 /* compute checksum */ 798 limbit = infop->numx * 5; 799 for (bit = 0; bit < infop->numx; bit++) { 800 crc(&csum, bitv_chunk(allbits, limbit, limbit - 5)); 801 limbit -= 5; 802 } 803 804 /* insert the computed checksum */ 805 bitv_setlo(allbits, infop->csumbits, (unsigned)csum); 806 807 /* encode binary values according to alphabet */ 808 limbit = infop->numx * 5; 809 for (bit = 0; bit < infop->numx; bit++) { 810 if (bit % 4 == 0) 811 *code++ = '-'; 812 *code++ = Alphabet[bitv_chunk(allbits, limbit, limbit - 5)]; 813 limbit -= 5; 814 } 815 816 *code = '\0'; 817 bitv_free(allbits); 818 bitv_free(dictval); 819 820 if (dhp->debug > 1) 821 (void) fprintf(stderr, "code \"%s\"\n", codebegin); 822 return (0); 823 } 824 825 /* 826 * code2dictval -- convert a diagcode back to a bit vector 827 */ 828 static bitv * 829 code2dictval(fm_dc_handle_t *dhp, const char *code) 830 { 831 const struct info *infop; 832 int len = strlen(dhp->dictname); 833 bitv *allbits; 834 bitv *dictval; 835 int numx; /* number of X's we count */ 836 unsigned long ocsum; /* original checksum in code */ 837 unsigned long csum; /* our computed checksum */ 838 int bit; /* for looping through bits */ 839 int limbit; /* upper bit limit when looping */ 840 const char *ptr; 841 842 /* check dictname part of code */ 843 if (strncasecmp(code, dhp->dictname, len) || 844 code[len] != '-') { 845 errno = EINVAL; 846 return (NULL); 847 } 848 849 /* convert code back to a bit vector */ 850 if ((allbits = bitv_alloc()) == NULL) { 851 errno = ENOMEM; 852 return (NULL); 853 } 854 855 /* we verified it began with dictname and a dash, so skip it */ 856 code = &code[len + 1]; 857 numx = 0; 858 /* be forgiving about misplaced dashes */ 859 for (; *code; code++) 860 if (*code == '-') 861 continue; 862 else { 863 unsigned val; 864 865 for (val = 0; Alphabet[val]; val++) 866 if (*code == Alphabet[val]) 867 break; 868 if (Alphabet[val] == '\0') { 869 bitv_free(allbits); 870 errno = EINVAL; 871 return (NULL); 872 } 873 bitv_shiftin(allbits, 5, val); 874 numx++; 875 } 876 877 if ((infop = numx2info(numx)) == NULL) { 878 bitv_free(allbits); 879 errno = EINVAL; 880 return (NULL); 881 } 882 883 /* now pull out the csum */ 884 ocsum = bitv_chunk(allbits, infop->csumbits, 0); 885 886 /* set the csum bits to zero */ 887 bitv_setlo(allbits, infop->csumbits, 0); 888 889 /* calculate the checksum and see if it matches */ 890 csum = 0; 891 for (ptr = dhp->dictname; *ptr; ptr++) 892 crc(&csum, (unsigned)*ptr); 893 limbit = numx * 5; 894 for (bit = 0; bit < numx; bit++) { 895 crc(&csum, bitv_chunk(allbits, limbit, limbit - 5)); 896 limbit -= 5; 897 } 898 csum &= (1 << infop->csumbits) - 1; 899 900 if (csum != ocsum) { 901 bitv_free(allbits); 902 errno = EINVAL; 903 return (NULL); 904 } 905 906 /* code looks okay, just return dictval portion */ 907 if ((dictval = bitv_alloc()) == NULL) { 908 bitv_free(allbits); 909 errno = ENOMEM; 910 return (NULL); 911 } 912 limbit = infop->csumbits + infop->databits; 913 while (limbit > infop->csumbits) { 914 bitv_shiftin(dictval, 1, 915 bitv_chunk(allbits, limbit, limbit - 1)); 916 limbit--; 917 } 918 bitv_free(allbits); 919 920 /* add in the offset appropriate for the length of code being used */ 921 if (bitv_add(dictval, infop->offset) < 0) { 922 /* 923 * overflow "cannot happen" since we've pulled in 924 * a given number of bits from the code and the offset 925 * is designed not to overflow... 926 */ 927 bitv_free(dictval); 928 errno = ERANGE; 929 return (NULL); 930 } 931 932 return (dictval); 933 } 934 935 936 /* 937 * private routines to parse a line into name/value pairs... 938 * 939 */ 940 941 /* 942 * startparse -- record starting of buffer containing name=value pairs 943 */ 944 static void 945 startparse(struct parsestate *ps, char *ptr) 946 { 947 ps->parseptr = ptr; 948 } 949 950 /* 951 * nextlhs -- return next left-hand-side of name=value pair, or NULL 952 * 953 * whitespace around the '=' is allowed for, but not required. the 954 * lhs is a simple string that does not contain any whitespace or an 955 * embedded equals sign. no escaped characters, quotes, etc. are 956 * honored here. 957 * 958 * this routine also parses the rhs and saves a pointer to it 959 * in Rhsp so that nextrhs() can return it. if nextrhs() never 960 * gets called, we continue looking for the next lhs *after* any 961 * rhs that was there. 962 */ 963 static char * 964 nextlhs(struct parsestate *ps) 965 { 966 char *lhsp; 967 char *copyto; 968 int equals = 0; 969 int quote = 0; 970 int backslash = 0; 971 972 /* skip whitespace */ 973 while (*ps->parseptr && isspace(*ps->parseptr)) 974 ps->parseptr++; 975 976 /* anything left? */ 977 if (*ps->parseptr == '\0') 978 return (NULL); 979 980 /* remember start of lhs, assume no rhs until we see '=' */ 981 lhsp = ps->parseptr; 982 983 /* find end of token, no escaped chars, quotes, etc. on lhs */ 984 while (*ps->parseptr && !isspace(*ps->parseptr)) 985 if (*ps->parseptr == '=') { 986 equals = 1; 987 break; 988 } else 989 ps->parseptr++; 990 991 /* null terminate the token, possibly nuking the '=' itself */ 992 *ps->parseptr++ = '\0'; 993 994 /* if we haven't seen an '=', see if it happens after whitespace */ 995 if (!equals) { 996 while (*ps->parseptr && isspace(*ps->parseptr)) 997 ps->parseptr++; 998 if (*ps->parseptr == '=') { 999 equals = 1; 1000 ps->parseptr++; 1001 } 1002 } 1003 1004 /* skip whitespace */ 1005 while (*ps->parseptr && isspace(*ps->parseptr)) 1006 ps->parseptr++; 1007 1008 /* isolate the rhs if it is there */ 1009 if (!equals || *ps->parseptr == '\0') { 1010 ps->rhsp = NULL; 1011 return (lhsp); 1012 } 1013 1014 if (*ps->parseptr == '"') { 1015 quote = 1; 1016 ps->parseptr++; 1017 } 1018 1019 /* remember the beginning of the rhs */ 1020 ps->rhsp = copyto = ps->parseptr; 1021 1022 /* now scan to the end of the rhs */ 1023 while (*ps->parseptr) { 1024 if (backslash) { 1025 switch (*ps->parseptr) { 1026 case 't': 1027 *copyto++ = '\t'; 1028 break; 1029 1030 case 'r': 1031 *copyto++ = '\r'; 1032 break; 1033 1034 case 'n': 1035 *copyto++ = '\n'; 1036 break; 1037 1038 case 'f': 1039 *copyto++ = '\f'; 1040 break; 1041 1042 default: 1043 *copyto++ = *ps->parseptr; 1044 break; 1045 } 1046 1047 backslash = 0; 1048 } else if (*ps->parseptr == '\\') 1049 backslash = 1; 1050 else if (quote) { 1051 if (*ps->parseptr == '"') { 1052 ps->parseptr++; 1053 break; /* end of quoted string */ 1054 } else 1055 *copyto++ = *ps->parseptr; 1056 } else if (!isspace(*ps->parseptr)) 1057 *copyto++ = *ps->parseptr; 1058 else { 1059 ps->parseptr++; 1060 break; /* rhs terminated by whitespace */ 1061 } 1062 1063 ps->parseptr++; 1064 } 1065 *copyto = '\0'; 1066 1067 return (lhsp); 1068 } 1069 1070 /* 1071 * nextrhs -- return right-hand-side of name=value pair, or NULL 1072 * 1073 * this routine can only be used after a lhs has been found with 1074 * nextlhs(). the rhs consists of a string with no whitespace in it, 1075 * unless the whitespace is escaped with a backslash. surrounding 1076 * a string with double quotes is also supported here, as are the 1077 * common C escape sequences like \t and \n. 1078 * 1079 * nextlhs() actually does all the hard work. we just return any 1080 * rhs that was found by that routine. 1081 */ 1082 static char * 1083 nextrhs(struct parsestate *ps) 1084 { 1085 return (ps->rhsp); 1086 } 1087 1088 1089 /* 1090 * private routines to manipulate bit vectors (i.e. large integers) 1091 * 1092 * if these bit vector routines are ever supposed to be more 1093 * general, the desired length should be passed in to bitv_alloc() 1094 * instead of defining a maximum here. but knowing the max ahead 1095 * of time allows for simpler code and we know the max that will 1096 * fit into a diagcode. on the minimum side, the below define 1097 * must be at least sizeof (unsigned). 1098 */ 1099 #define BITV_MAX_BYTES 15 1100 1101 /* data structure used to hold a bit vector */ 1102 struct bitv { 1103 unsigned char v[BITV_MAX_BYTES]; 1104 }; 1105 1106 /* allocate a new, zeroed out bit vector */ 1107 static bitv * 1108 bitv_alloc(void) 1109 { 1110 int i; 1111 struct bitv *bv = malloc(sizeof (*bv)); 1112 1113 if (bv) 1114 for (i = 0; i < BITV_MAX_BYTES; i++) 1115 bv->v[i] = 0; 1116 1117 return (bv); 1118 } 1119 1120 /* free a bit vector that was allocated with bitv_alloc() */ 1121 static void 1122 bitv_free(bitv *bv) 1123 { 1124 free(bv); 1125 } 1126 1127 /* shift left a bit vector by a given number of bits. fill with zeros. */ 1128 static void 1129 bitv_shift(bitv *bv, unsigned bits) 1130 { 1131 while (bits > 0) { 1132 unsigned iterbits = bits; 1133 int i; 1134 1135 /* how many bits this iteration? 8 max. */ 1136 if (iterbits > 8) 1137 iterbits = 8; 1138 1139 for (i = BITV_MAX_BYTES - 1; i > 0; i--) { 1140 bv->v[i] <<= iterbits; 1141 bv->v[i] |= bv->v[i - 1] >> (8 - iterbits); 1142 } 1143 bv->v[0] <<= iterbits; 1144 1145 bits -= iterbits; 1146 } 1147 } 1148 1149 /* force a given number of bits to a specific value */ 1150 static void 1151 bitv_setlo(bitv *bv, unsigned bits, unsigned val) 1152 { 1153 int i = 0; 1154 1155 /* assumption: bits * 8 <= sizeof (val) */ 1156 1157 while (bits > 0) { 1158 unsigned iterbits = bits; 1159 unsigned mask; 1160 1161 if (iterbits > 8) 1162 iterbits = 8; 1163 1164 mask = (1 << iterbits) - 1; 1165 1166 bv->v[i] &= ~mask; 1167 bv->v[i] |= val & mask; 1168 1169 val >>= iterbits; 1170 bits -= iterbits; 1171 /* 1172 * the following can't go off end of bv->v[] since 1173 * BITV_MAX_BYTES is assumed to be at least sizeof 1174 * unsigned and val can't be more than sizeof unsigned 1175 * bytes long. 1176 */ 1177 i++; 1178 } 1179 } 1180 1181 /* given a value and number of bits, shift it in from the right */ 1182 static void 1183 bitv_shiftin(bitv *bv, unsigned bits, unsigned val) 1184 { 1185 bitv_shift(bv, bits); 1186 bitv_setlo(bv, bits, val); 1187 } 1188 1189 /* given a bit vector and a number of bits, shift it in from the right */ 1190 static void 1191 bitv_shiftinv(bitv *bv, unsigned bits, const bitv *inbv) 1192 { 1193 int byteindex = bits / 8; 1194 int iterbits = bits % 8; 1195 1196 /* first handle partial byte shift in */ 1197 bitv_shiftin(bv, iterbits, inbv->v[byteindex--]); 1198 1199 /* now handle any remaining full byte shift ins */ 1200 while (byteindex >= 0) 1201 bitv_shiftin(bv, 8, inbv->v[byteindex--]); 1202 } 1203 1204 /* return the number of bits required to hold the current bit vector's value */ 1205 static int 1206 bitv_bits(const bitv *bv) 1207 { 1208 int i; 1209 1210 for (i = BITV_MAX_BYTES - 1; i >= 0; i--) 1211 if (bv->v[i]) { 1212 int bit; 1213 1214 for (bit = 7; bit >= 0; bit--) 1215 if ((bv->v[i] >> bit) & 1) 1216 return (i * 8 + bit + 1); 1217 1218 /* this can't happen, so do *something* */ 1219 return ((i + 1) * 8); 1220 } 1221 1222 return (0); 1223 } 1224 1225 /* extract chunks of bits from bit vector */ 1226 static unsigned 1227 bitv_chunk(const bitv *bv, unsigned limbit, unsigned lobit) 1228 { 1229 unsigned retval = 0; 1230 int bit; 1231 1232 /* 1233 * entry assumptions: 1234 * limbit > lobit 1235 * limbit - lobit <= sizeof (unsigned) * 8 1236 */ 1237 1238 for (bit = limbit - 1; bit >= 0 && bit >= lobit; bit--) { 1239 retval <<= 1; 1240 retval |= (bv->v[bit / 8] >> (bit % 8)) & 1; 1241 } 1242 1243 return (retval); 1244 } 1245 1246 /* 1247 * multiply by a given value 1248 * 1249 * on overflow, bit vector will hold least significant BITV_MAX_BYTES, 1250 * return value will be -1, and errno will be ERANGE. otherwise 1251 * return is zero and bit vector holds the product. 1252 */ 1253 static int 1254 bitv_mul(bitv *bv, unsigned long long val) 1255 { 1256 unsigned short result; 1257 unsigned char prod[BITV_MAX_BYTES]; 1258 unsigned k = 0; 1259 int valbyte; 1260 int bvbyte; 1261 int i; 1262 1263 /* start with a zeroed out bit vector to hold result */ 1264 for (i = 0; i < BITV_MAX_BYTES; i++) 1265 prod[i] = 0; 1266 1267 /* from most-significant byte of val to least... */ 1268 for (valbyte = 0; valbyte < sizeof (val); valbyte++) 1269 /* from most significant byte of bv to least */ 1270 for (bvbyte = 0; bvbyte < BITV_MAX_BYTES; bvbyte++) { 1271 result = ((val >> (valbyte * 8)) & 0xff) * 1272 bv->v[bvbyte] + k; 1273 1274 if (valbyte + bvbyte >= BITV_MAX_BYTES) { 1275 /* 1276 * we're not storing digits past 1277 * BITV_MAX_BYTES, so if they aren't 1278 * zeros, then signal an overflow. 1279 */ 1280 if (result & 0xff) { 1281 errno = ERANGE; 1282 return (-1); 1283 } 1284 } else 1285 prod[valbyte + bvbyte] += result & 0xff; 1286 1287 /* "carry the 1..." */ 1288 k = result >> 8; 1289 } 1290 1291 /* store result in bv */ 1292 for (i = 0; i < BITV_MAX_BYTES; i++) 1293 bv->v[i] = prod[i]; 1294 1295 return (0); 1296 } 1297 1298 /* 1299 * add in a given value 1300 * 1301 * on overflow, bit vector will hold least significant BITV_MAX_BYTES, 1302 * return value will be -1, and errno will be ERANGE. otherwise 1303 * return is zero and bit vector holds the sum. 1304 */ 1305 static int 1306 bitv_add(bitv *bv, unsigned long long val) 1307 { 1308 int cf = 0; /* carry flag */ 1309 unsigned short result; 1310 int i; 1311 1312 for (i = 0; i < BITV_MAX_BYTES; i++) { 1313 if (i < sizeof (val)) 1314 result = cf + bv->v[i] + ((val >> (i * 8)) & 0xff); 1315 else 1316 result = cf + bv->v[i]; 1317 1318 cf = (result >> 8) & 1; 1319 bv->v[i] = result & 0xff; 1320 } 1321 1322 if (cf) { 1323 errno = ERANGE; 1324 return (-1); 1325 } 1326 return (0); 1327 } 1328 1329 /* 1330 * subtract out a given value 1331 * 1332 * on underflow, bit vector will hold least significant BITV_MAX_BYTES, 1333 * return value will be -1, and errno will be ERANGE. otherwise 1334 * return is zero and bit vector holds the difference. 1335 */ 1336 static int 1337 bitv_sub(bitv *bv, unsigned long long val) 1338 { 1339 int bf = 0; /* borrow flag */ 1340 unsigned short minuend; 1341 unsigned short subtrahend; 1342 int i; 1343 1344 for (i = 0; i < BITV_MAX_BYTES; i++) { 1345 minuend = bv->v[i]; 1346 if (i < sizeof (val)) 1347 subtrahend = bf + ((val >> (i * 8)) & 0xff); 1348 else 1349 subtrahend = bf; 1350 if (subtrahend > minuend) { 1351 bf = 1; 1352 minuend += 1 << 8; 1353 } else 1354 bf = 0; 1355 1356 bv->v[i] = minuend - subtrahend; 1357 } 1358 1359 if (bf) { 1360 errno = ERANGE; 1361 return (-1); 1362 } 1363 return (0); 1364 } 1365 1366 /* 1367 * see if bv is greater than or equal to a given value 1368 */ 1369 static int 1370 bitv_ge(const bitv *bv, unsigned long long val) 1371 { 1372 int bf = 0; /* borrow flag */ 1373 unsigned short minuend; 1374 unsigned short subtrahend; 1375 int i; 1376 1377 for (i = 0; i < BITV_MAX_BYTES; i++) { 1378 minuend = bv->v[i]; 1379 if (i < sizeof (val)) 1380 subtrahend = bf + ((val >> (i * 8)) & 0xff); 1381 else 1382 subtrahend = bf; 1383 if (subtrahend > minuend) 1384 bf = 1; 1385 else 1386 bf = 0; 1387 } 1388 1389 return (!bf); 1390 } 1391 1392 /* parse a string into bit vector, honor leading 0/0x for octal/hex */ 1393 static bitv * 1394 bitv_strparse(const char *s, int bits) 1395 { 1396 unsigned long long base = 10; 1397 unsigned long long val; 1398 bitv *bv = bitv_alloc(); 1399 1400 if (bv == NULL) { 1401 errno = ENOMEM; 1402 return (NULL); 1403 } 1404 1405 if (*s == '0') { 1406 s++; 1407 if (*s == 'x') { 1408 s++; 1409 base = 16; 1410 } else 1411 base = 8; 1412 } 1413 1414 while (isxdigit(*s)) { 1415 /* isxdigit() let's in too much, depending on base */ 1416 if (base == 8 && (*s < '0' || *s > '7')) 1417 break; 1418 else if (base == 10 && !isdigit(*s)) 1419 break; 1420 1421 /* convert the digit to binary */ 1422 if (isdigit(*s)) 1423 val = *s - '0'; 1424 else 1425 val = tolower(*s) - 'a' + 10; 1426 1427 /* 1428 * multiply our big integer by base, 1429 * add in the most recent digit, 1430 * and check for overflow 1431 */ 1432 if (bitv_mul(bv, base) < 0 || 1433 bitv_add(bv, val) < 0 || 1434 bitv_bits(bv) > bits) { 1435 bitv_free(bv); 1436 errno = ERANGE; 1437 return (NULL); 1438 } 1439 1440 s++; 1441 } 1442 1443 return (bv); 1444 } 1445 1446 /* return 0 if two bit vectors represent the same number */ 1447 static int 1448 bitv_cmp(const bitv *bv1, const bitv *bv2) 1449 { 1450 int i; 1451 1452 for (i = BITV_MAX_BYTES - 1; i >= 0; i--) 1453 if (bv1->v[i] < bv2->v[i]) 1454 return (-1); 1455 else if (bv1->v[i] > bv2->v[i]) 1456 return (1); 1457 return (0); 1458 } 1459 1460 1461 /* CRC code... */ 1462 static unsigned crctab[256] = { 1463 0x00000000, 1464 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 1465 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 1466 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 1467 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 1468 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F, 1469 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 1470 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 1471 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 1472 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 1473 0xA4AD16EA, 0xA06C0B5D, 0xD4326D90, 0xD0F37027, 0xDDB056FE, 1474 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, 1475 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 1476 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0, 1477 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 1478 0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 1479 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 1480 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 1481 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 1482 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, 1483 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 1484 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 1485 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 1486 0x94EA7B2A, 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 1487 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F, 1488 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 1489 0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 1490 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 1491 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 1492 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E, 0x21DC2629, 1493 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 1494 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 1495 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 1496 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 1497 0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 1498 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, 1499 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 1500 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71, 1501 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 1502 0x857130C3, 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 1503 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 1504 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 1505 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087, 1506 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, 1507 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 1508 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 1509 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 1510 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 1511 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 0x89B8FD09, 1512 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 1513 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 1514 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 1515 }; 1516 1517 static void 1518 crc(unsigned long *crcp, unsigned val) 1519 { 1520 *crcp = (*crcp<<8) ^ crctab[(unsigned char)((*crcp>>24)^val)]; 1521 } 1522