2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License, Version 1.0 only 2N/A * (the "License"). You may not use this file except in compliance 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A * diagcode library, Sun Private API (PSARC/2004/601) 2N/A * undocumented debugging interface: 2N/A * set environment variable _FM_DC_DEBUG for debug prints to stderr. 2N/A * set it to 1 for extended error messages only. 2N/A * set it to 2 to include success info too on interesting functions. 2N/A * set it to 3 to include success info on trivial functions too. 2N/A * note that this environment variable is only examined in fm_dc_opendict(). 2N/A#
pragma ident "%Z%%M% %I% %E% SMI" 2N/A/* private (opaque to callers) handle information */ 2N/A * parameters of the various sizes of diagcodes 2N/A * table must be in ascending order from smallest databits value to largest. 2N/A * when faced with more databits than the last entry, we know we have 2N/A * something that won't fit into a diagcode. 2N/A int databits;
/* number of bits used to hold dictionary value */ 2N/A int numx;
/* number of digits (also called X's) in code */ 2N/A int sizeval;
/* value encoded into "size" field of code */ 2N/A unsigned long long offset;
/* databits==0 stands for this value */ 2N/A /* diagcode is: dictname-XXXX-XX */ 2N/A /* diagcode is: dictname-XXXX-XXXX-XX */ 2N/A {
38,
10,
8,
1,
2097152ULL },
2N/A /* diagcode is: dictname-XXXX-XXXX-XXXX-XX */ 2N/A {
55,
14,
11,
2,
274880004096ULL },
2N/A /* diagcode is: dictname-XXXX-XXXX-XXXX-XXXX-XX */ 2N/A {
72,
18,
14,
3,
36029071898968064ULL }
2N/A#
define MAXCODELEN 25 /* big enough to hold the X's, dashes, and \0 */ 2N/A/* forward references for functions private to this file */ 2N/A char *
parseptr;
/* next unparsed character in buffer */ 2N/A char *
rhsp;
/* rhs associated with last lhs (or NULL) */ 2N/A#
define DICTMAXLINE 10240 /* maximum expected dictionary line length */ 2N/Astatic const char Suffix[] =
".dict";
/* suffix on dictionary filename */ 2N/Astatic const char Debugenv[] =
"_FM_DC_DEBUG";
/* debug environment var */ 2N/A/* properties we look for at top of dictionary */ 2N/A/* the alphabet used to encode information in a diagcode (base32 digits) */ 2N/Astatic const char Alphabet[] =
"0123456789ACDEFGHJKLMNPQRSTUVWXY";
2N/A/* open a dictionary, return opaque handle */ 2N/A int debug = 0;
/* set by environment variable */ 2N/A char *
debugstr =
"";
/* error path debug prefix text */ 2N/A int line = 0;
/* line number in dict */ 2N/A char *
lhsp;
/* prop left-hand-side */ 2N/A char *
rhsp;
/* prop right-hand-side */ 2N/A /* undocumented flag, given via environment variable */ 2N/A "fm_dc_opendict: ver %d path \"%s\" dict \"%s\": ",
2N/A debugstr =
"fm_dc_opendict: ";
/* used in error paths */ 2N/A /* verify caller expects an API version we support */ 2N/A /* caller can pass in NULL for default dirpath */ 2N/A * allocate buffer for dirpath, slash, dictname, and suffix 2N/A * (sizeof (Suffix) includes the null). 2N/A * allocate the handle. 2N/A * allocate the dictname copy kept in the handle. 2N/A * if any of these fail, send back ENOMEM. 2N/A /* initialize the handle */ 2N/A /* open the dictionary */ 2N/A /* pull in the header line and parse it */ 2N/A /* first non-comment, non-blank line must be header */ 2N/A "%sEINVAL: line %d: header expected.\n",
2N/A /* just wanted header line for now */ 2N/A /* walk through name=value pairs in line after Header string */ 2N/A * require version 1, expected dict name, and maxkey values 2N/A * (note we use "1" here and not FM_DC_VERSION because this code 2N/A * implements version 1, so the check below should not float to 2N/A * newer version numbers if the header file defines them.) 2N/A "%sEINVAL ver %d name \"%s\" maxkey %d\n",
2N/A/* close a dictionary */ 2N/A/* return maximum length (in bytes) of diagcodes for a given dictionary */ 2N/A /* only one version so far, so dhp->version isn't checked */ 2N/A/* return number of strings in key for a given dictionary */ 2N/A /* only one version so far, so dhp->version isn't checked */ 2N/A /* this interface counts the NULL entry */ 2N/A/* given a key, construct a diagcode */ 2N/A char *
debugstr =
"";
/* error path debug prefix text */ 2N/A int line = 0;
/* line number in dict */ 2N/A const char *
rhsp;
/* right-hand-side of entry */ 2N/A /* only one version so far, so dhp->version isn't checked */ 2N/A "fm_dc_key2code: dhp 0x%p maxcode %lu ", (
void *)
dhp,
2N/A /* first non-comment, non-blank line must be header */ 2N/A "fm_dc_key2code: dictionary line %d",
2N/A/* given a diagcode, return the key (array of strings) */ 2N/A char *
debugstr =
"";
/* error path debug prefix text */ 2N/A /* only one version so far, so dhp->version isn't checked */ 2N/A "fm_dc_code2key: dhp 0x%p code \"%s\" maxkey %d: ",
2N/A /* convert code back to bit vector */ 2N/A /* code2dictval() sets errno */ 2N/A /* handle expected types without printing a number */ 2N/A "%sENOMEM code2dictval\n",
2N/A "%sEINVAL code2dictval\n",
2N/A "%scode2dictval error %d\n",
2N/A /* first non-comment, non-blank line must be header */ 2N/A continue;
/* ignore malformed entries */ 2N/A /* pull in value from dictionary */ 2N/A /* bitv_strparse() sets errno */ 2N/A "%sENOMEM bitv_strparse\n",
2N/A /* other than ENOMEM, trudge on... */ 2N/A /* if we got here, we found the match */ 2N/A "%sENOMEM maxkey %d\n",
2N/A/* return the right-hand side of a names property from the dict header */ 2N/A /* only one version so far, so dhp->version isn't checked */ 2N/A/* find the appropriate diagcode format for a given dictval */ 2N/A for (i = 0; i <
sizeof (
Info) /
sizeof (*
Info) -
1; i++)
2N/A /* return largest format */ 2N/A/* lookup the diagcode parameters given the number of X's used */ 2N/A/* for use with qsort() */ 2N/A * sortkey -- make sure key[] array is lexically sorted and without repeats 2N/A int srci;
/* source index when iterating through key[] */ 2N/A int dsti;
/* dest index when storing elements in key[] */ 2N/A /* count the number of elements in key[] */ 2N/A return;
/* nothing to sort */ 2N/A /* go through array and remove repeats */ 2N/A * keymatch -- check for matching line from the dictionary 2N/A * assumes that the key[] array has already been lexically sorted. 2N/A * returns NULL if no match, otherwise pointer to first character of RHS. 2N/A /* skip any initial whitespace in front of name */ 2N/A return (
NULL);
/* dict had more strings for key */ 2N/A /* match the string */ 2N/A return (
NULL);
/* dict string longer */ 2N/A return (
NULL);
/* string don't match */ 2N/A * buildcode -- given the val from the dictionary, create the diagcode 2N/A unsigned long csum = 0;
/* checksum (CRC) of diagcode */ 2N/A int bit;
/* for looping through bits */ 2N/A int limbit;
/* upper bit limit when looping */ 2N/A /* sanity check that buffer is large enough for diagcode */ 2N/A "%sENOMEM maxcode %lu < codelen %lu\n",
2N/A /* handle dictname part of checksum */ 2N/A /* pull in value from dictionary */ 2N/A /* bitv_strparse() sets errno */ 2N/A /* handle expected types without printing a number */ 2N/A "%sENOMEM bitv_strparse\n",
2N/A "%sERANGE bitv_strparse\n",
2N/A "%sbitv_strparse error %d\n",
2N/A /* determine which format of code we're using */ 2N/A /* subtract off the offset appropriate for format of code */ 2N/A * this "cannot happen" since code format was chosen 2N/A * so that offset will be smaller than dictval, and 2N/A * dictval cannot be out of range since bitv_strparse() 2N/A * should have caught it. 2N/A /* assemble all the bits for the diagcode */ 2N/A * construct the full diagcode by shifting in information: 2N/A * - 2 bit code type, set to 01 2N/A * - 2 bit size field 2N/A * - the databits of the dictionary code itself 2N/A /* insert zeros for checksum */ 2N/A /* compute checksum */ 2N/A /* insert the computed checksum */ 2N/A /* encode binary values according to alphabet */ 2N/A * code2dictval -- convert a diagcode back to a bit vector 2N/A int numx;
/* number of X's we count */ 2N/A unsigned long ocsum;
/* original checksum in code */ 2N/A unsigned long csum;
/* our computed checksum */ 2N/A int bit;
/* for looping through bits */ 2N/A int limbit;
/* upper bit limit when looping */ 2N/A /* check dictname part of code */ 2N/A /* convert code back to a bit vector */ 2N/A /* we verified it began with dictname and a dash, so skip it */ 2N/A /* be forgiving about misplaced dashes */ 2N/A /* now pull out the csum */ 2N/A /* set the csum bits to zero */ 2N/A /* calculate the checksum and see if it matches */ 2N/A /* code looks okay, just return dictval portion */ 2N/A /* add in the offset appropriate for the length of code being used */ 2N/A * overflow "cannot happen" since we've pulled in 2N/A * a given number of bits from the code and the offset 2N/A * is designed not to overflow... 2N/A * startparse -- record starting of buffer containing name=value pairs 2N/A * nextlhs -- return next left-hand-side of name=value pair, or NULL 2N/A * whitespace around the '=' is allowed for, but not required. the 2N/A * lhs is a simple string that does not contain any whitespace or an 2N/A * embedded equals sign. no escaped characters, quotes, etc. are 2N/A * this routine also parses the rhs and saves a pointer to it 2N/A * in Rhsp so that nextrhs() can return it. if nextrhs() never 2N/A * gets called, we continue looking for the next lhs *after* any 2N/A * rhs that was there. 2N/A /* skip whitespace */ 2N/A /* anything left? */ 2N/A /* remember start of lhs, assume no rhs until we see '=' */ 2N/A /* find end of token, no escaped chars, quotes, etc. on lhs */ 2N/A /* null terminate the token, possibly nuking the '=' itself */ 2N/A /* if we haven't seen an '=', see if it happens after whitespace */ 2N/A /* skip whitespace */ 2N/A /* isolate the rhs if it is there */ 2N/A /* remember the beginning of the rhs */ 2N/A /* now scan to the end of the rhs */ 2N/A break;
/* end of quoted string */ 2N/A break;
/* rhs terminated by whitespace */ 2N/A * nextrhs -- return right-hand-side of name=value pair, or NULL 2N/A * this routine can only be used after a lhs has been found with 2N/A * nextlhs(). the rhs consists of a string with no whitespace in it, 2N/A * unless the whitespace is escaped with a backslash. surrounding 2N/A * a string with double quotes is also supported here, as are the 2N/A * common C escape sequences like \t and \n. 2N/A * nextlhs() actually does all the hard work. we just return any 2N/A * rhs that was found by that routine. 2N/A * private routines to manipulate bit vectors (i.e. large integers) 2N/A * if these bit vector routines are ever supposed to be more 2N/A * general, the desired length should be passed in to bitv_alloc() 2N/A * instead of defining a maximum here. but knowing the max ahead 2N/A * of time allows for simpler code and we know the max that will 2N/A * fit into a diagcode. on the minimum side, the below define 2N/A * must be at least sizeof (unsigned). 2N/A/* data structure used to hold a bit vector */ 2N/A/* allocate a new, zeroed out bit vector */ 2N/A/* free a bit vector that was allocated with bitv_alloc() */ 2N/A/* shift left a bit vector by a given number of bits. fill with zeros. */ 2N/A /* how many bits this iteration? 8 max. */ 2N/A/* force a given number of bits to a specific value */ 2N/A /* assumption: bits * 8 <= sizeof (val) */ 2N/A * the following can't go off end of bv->v[] since 2N/A * BITV_MAX_BYTES is assumed to be at least sizeof 2N/A * unsigned and val can't be more than sizeof unsigned 2N/A/* given a value and number of bits, shift it in from the right */ 2N/A/* given a bit vector and a number of bits, shift it in from the right */ 2N/A /* first handle partial byte shift in */ 2N/A /* now handle any remaining full byte shift ins */ 2N/A/* return the number of bits required to hold the current bit vector's value */ 2N/A /* this can't happen, so do *something* */ 2N/A return ((i +
1) *
8);
2N/A/* extract chunks of bits from bit vector */ 2N/A * entry assumptions: 2N/A * limbit - lobit <= sizeof (unsigned) * 8 2N/A * multiply by a given value 2N/A * on overflow, bit vector will hold least significant BITV_MAX_BYTES, 2N/A * return value will be -1, and errno will be ERANGE. otherwise 2N/A * return is zero and bit vector holds the product. 2N/A /* start with a zeroed out bit vector to hold result */ 2N/A /* from most-significant byte of val to least... */ 2N/A /* from most significant byte of bv to least */ 2N/A * we're not storing digits past 2N/A * BITV_MAX_BYTES, so if they aren't 2N/A * zeros, then signal an overflow. 2N/A /* "carry the 1..." */ 2N/A /* store result in bv */ 2N/A * add in a given value 2N/A * on overflow, bit vector will hold least significant BITV_MAX_BYTES, 2N/A * return value will be -1, and errno will be ERANGE. otherwise 2N/A * return is zero and bit vector holds the sum. 2N/A int cf = 0;
/* carry flag */ 2N/A * subtract out a given value 2N/A * on underflow, bit vector will hold least significant BITV_MAX_BYTES, 2N/A * return value will be -1, and errno will be ERANGE. otherwise 2N/A * return is zero and bit vector holds the difference. 2N/A int bf = 0;
/* borrow flag */ 2N/A * see if bv is greater than or equal to a given value 2N/A int bf = 0;
/* borrow flag */ 2N/A/* parse a string into bit vector, honor leading 0/0x for octal/hex */ 2N/A /* isxdigit() let's in too much, depending on base */ 2N/A if (
base ==
8 && (*s <
'0' || *s >
'7'))
2N/A /* convert the digit to binary */ 2N/A * multiply our big integer by base, 2N/A * add in the most recent digit, 2N/A * and check for overflow 2N/A/* return 0 if two bit vectors represent the same number */ 2N/A 0x04C11DB7,
0x09823B6E,
0x0D4326D9,
0x130476DC,
0x17C56B6B,
2N/A 0x1A864DB2,
0x1E475005,
0x2608EDB8,
0x22C9F00F,
0x2F8AD6D6,
2N/A 0x2B4BCB61,
0x350C9B64,
0x31CD86D3,
0x3C8EA00A,
0x384FBDBD,
2N/A 0x4C11DB70,
0x48D0C6C7,
0x4593E01E,
0x4152FDA9,
0x5F15ADAC,
2N/A 0x5BD4B01B,
0x569796C2,
0x52568B75,
0x6A1936C8,
0x6ED82B7F,
2N/A 0x639B0DA6,
0x675A1011,
0x791D4014,
0x7DDC5DA3,
0x709F7B7A,
2N/A 0x745E66CD,
0x9823B6E0,
0x9CE2AB57,
0x91A18D8E,
0x95609039,
2N/A 0x8B27C03C,
0x8FE6DD8B,
0x82A5FB52,
0x8664E6E5,
0xBE2B5B58,
2N/A 0xBAEA46EF,
0xB7A96036,
0xB3687D81,
0xAD2F2D84,
0xA9EE3033,
2N/A 0xA4AD16EA,
0xA06C0B5D,
0xD4326D90,
0xD0F37027,
0xDDB056FE,
2N/A 0xD9714B49,
0xC7361B4C,
0xC3F706FB,
0xCEB42022,
0xCA753D95,
2N/A 0xF23A8028,
0xF6FB9D9F,
0xFBB8BB46,
0xFF79A6F1,
0xE13EF6F4,
2N/A 0xE5FFEB43,
0xE8BCCD9A,
0xEC7DD02D,
0x34867077,
0x30476DC0,
2N/A 0x3D044B19,
0x39C556AE,
0x278206AB,
0x23431B1C,
0x2E003DC5,
2N/A 0x2AC12072,
0x128E9DCF,
0x164F8078,
0x1B0CA6A1,
0x1FCDBB16,
2N/A 0x018AEB13,
0x054BF6A4,
0x0808D07D,
0x0CC9CDCA,
0x7897AB07,
2N/A 0x7C56B6B0,
0x71159069,
0x75D48DDE,
0x6B93DDDB,
0x6F52C06C,
2N/A 0x6211E6B5,
0x66D0FB02,
0x5E9F46BF,
0x5A5E5B08,
0x571D7DD1,
2N/A 0x53DC6066,
0x4D9B3063,
0x495A2DD4,
0x44190B0D,
0x40D816BA,
2N/A 0xACA5C697,
0xA864DB20,
0xA527FDF9,
0xA1E6E04E,
0xBFA1B04B,
2N/A 0xBB60ADFC,
0xB6238B25,
0xB2E29692,
0x8AAD2B2F,
0x8E6C3698,
2N/A 0x832F1041,
0x87EE0DF6,
0x99A95DF3,
0x9D684044,
0x902B669D,
2N/A 0x94EA7B2A,
0xE0B41DE7,
0xE4750050,
0xE9362689,
0xEDF73B3E,
2N/A 0xF3B06B3B,
0xF771768C,
0xFA325055,
0xFEF34DE2,
0xC6BCF05F,
2N/A 0xC27DEDE8,
0xCF3ECB31,
0xCBFFD686,
0xD5B88683,
0xD1799B34,
2N/A 0xDC3ABDED,
0xD8FBA05A,
0x690CE0EE,
0x6DCDFD59,
0x608EDB80,
2N/A 0x644FC637,
0x7A089632,
0x7EC98B85,
0x738AAD5C,
0x774BB0EB,
2N/A 0x4F040D56,
0x4BC510E1,
0x46863638,
0x42472B8F,
0x5C007B8A,
2N/A 0x58C1663D,
0x558240E4,
0x51435D53,
0x251D3B9E,
0x21DC2629,
2N/A 0x2C9F00F0,
0x285E1D47,
0x36194D42,
0x32D850F5,
0x3F9B762C,
2N/A 0x3B5A6B9B,
0x0315D626,
0x07D4CB91,
0x0A97ED48,
0x0E56F0FF,
2N/A 0x1011A0FA,
0x14D0BD4D,
0x19939B94,
0x1D528623,
0xF12F560E,
2N/A 0xF5EE4BB9,
0xF8AD6D60,
0xFC6C70D7,
0xE22B20D2,
0xE6EA3D65,
2N/A 0xEBA91BBC,
0xEF68060B,
0xD727BBB6,
0xD3E6A601,
0xDEA580D8,
2N/A 0xDA649D6F,
0xC423CD6A,
0xC0E2D0DD,
0xCDA1F604,
0xC960EBB3,
2N/A 0xBD3E8D7E,
0xB9FF90C9,
0xB4BCB610,
0xB07DABA7,
0xAE3AFBA2,
2N/A 0xAAFBE615,
0xA7B8C0CC,
0xA379DD7B,
0x9B3660C6,
0x9FF77D71,
2N/A 0x92B45BA8,
0x9675461F,
0x8832161A,
0x8CF30BAD,
0x81B02D74,
2N/A 0x857130C3,
0x5D8A9099,
0x594B8D2E,
0x5408ABF7,
0x50C9B640,
2N/A 0x4E8EE645,
0x4A4FFBF2,
0x470CDD2B,
0x43CDC09C,
0x7B827D21,
2N/A 0x7F436096,
0x7200464F,
0x76C15BF8,
0x68860BFD,
0x6C47164A,
2N/A 0x61043093,
0x65C52D24,
0x119B4BE9,
0x155A565E,
0x18197087,
2N/A 0x1CD86D30,
0x029F3D35,
0x065E2082,
0x0B1D065B,
0x0FDC1BEC,
2N/A 0x3793A651,
0x3352BBE6,
0x3E119D3F,
0x3AD08088,
0x2497D08D,
2N/A 0x2056CD3A,
0x2D15EBE3,
0x29D4F654,
0xC5A92679,
0xC1683BCE,
2N/A 0xCC2B1D17,
0xC8EA00A0,
0xD6AD50A5,
0xD26C4D12,
0xDF2F6BCB,
2N/A 0xDBEE767C,
0xE3A1CBC1,
0xE760D676,
0xEA23F0AF,
0xEEE2ED18,
2N/A 0xF0A5BD1D,
0xF464A0AA,
0xF9278673,
0xFDE69BC4,
0x89B8FD09,
2N/A 0x8D79E0BE,
0x803AC667,
0x84FBDBD0,
0x9ABC8BD5,
0x9E7D9662,
2N/A 0x933EB0BB,
0x97FFAD0C,
0xAFB010B1,
0xAB710D06,
0xA6322BDF,
2N/A 0xA2F33668,
0xBCB4666D,
0xB8757BDA,
0xB5365D03,
0xB1F740B4