home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / Programming / Source / WAIS / ir / zutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-02  |  21.0 KB  |  990 lines

  1. /* WIDE AREA INFORMATION SERVER SOFTWARE:
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.    
  4.   
  5.    3.26.90    Harry Morris, morris@think.com
  6.    3.30.90  Harry Morris - Changed any->bits to any->bytes
  7.    4.11.90  HWM - fixed include file names, changed 
  8.                    - writeCompressedIntegerWithPadding() to
  9.                   writeCompressedIntWithPadding()
  10.                 - generalized conditional includes (see c-dialect.h)
  11.    3.7.91   Jonny Goldman.  Replaced "short" in makeBitMap with "int" line 632.
  12. */
  13.  
  14. #define _C_utils_Z39_50_
  15.  
  16. #include "zutil.h"
  17.  
  18. #include <math.h>
  19. #include <string.h>
  20.  
  21. #ifdef ANSI_LIKE
  22. #include <stdarg.h>
  23. #else
  24. #include "ustubs.h"
  25. #include <varargs.h>
  26. #endif
  27.  
  28. char* readErrorPosition = NULL; /* pos where buf stoped making sense */
  29.  
  30. /*----------------------------------------------------------------------*/
  31. /* A note on error handling 
  32.    read - these are low level routines, they do not check the type tags
  33.    which (sometimes) preceed the data (this is done by the higher
  34.    level functions which call these functions).  There is no 
  35.    attempt made to check that the reading does not exceed the read
  36.    buffer.  Such cases should be very rare and usually will be 
  37.    caught by the calling functions. (note - it is unlikely that 
  38.    a series of low level reads will go far off the edge without
  39.    triggering a type error.  However, it is possible for a single
  40.    bad read in an array function (eg. readAny) to attempt to read a 
  41.    large ammount, possibly causing a segmentation violation or out
  42.    of memory condition.
  43.  */
  44. /*----------------------------------------------------------------------*/
  45.  
  46. diagnosticRecord* 
  47. makeDiag(surrogate,code,addInfo)
  48. boolean surrogate;
  49. char* code;
  50. char* addInfo;
  51. {
  52.   diagnosticRecord* diag = 
  53.     (diagnosticRecord*)s_malloc((size_t)sizeof(diagnosticRecord));
  54.   
  55.   diag->SURROGATE = surrogate;
  56.   memcpy(diag->DIAG,code,DIAGNOSTIC_CODE_SIZE);
  57.   diag->ADDINFO = s_strdup(addInfo); 
  58.  
  59.   return(diag);
  60. }
  61.  
  62. /*----------------------------------------------------------------------*/
  63.  
  64. void 
  65. freeDiag(diag)
  66. diagnosticRecord* diag;
  67.   if (diag != NULL)
  68.     { if (diag->ADDINFO != NULL)
  69.     s_free(diag->ADDINFO);
  70.     s_free(diag);
  71.       }
  72. }
  73.  
  74. /*----------------------------------------------------------------------*/
  75.  
  76. #define END_OF_RECORD    0x1D
  77.  
  78. char* 
  79. writeDiag(diag,buffer,len)
  80. diagnosticRecord* diag;
  81. char* buffer;
  82. long* len;
  83. /* diagnostics (as per Appendix D) have a very weird format - this changes
  84.    in SR-1
  85.  */
  86. {
  87.   char* buf = buffer;
  88.   long  length;
  89.   
  90.   if (diag == NULL)        /* handle unspecified optional args */
  91.     return(buf);
  92.  
  93.   buf = writeTag(DT_DatabaseDiagnosticRecords,buf,len);
  94.   CHECK_FOR_SPACE_LEFT(0L,len);
  95.   
  96.   length = 3; 
  97.   if (diag->ADDINFO != NULL)
  98.     length += strlen(diag->ADDINFO);
  99.     
  100.   if (length >= 0xFFFF )    /* make sure the length is reasonable */
  101.     { length = 0xFFFF - 1;
  102.       diag->ADDINFO[0xFFFF - 3 - 1] = '\0';
  103.     }
  104.    
  105.   buf = writeBinaryInteger(length,2L,buf,len);
  106.  
  107.   CHECK_FOR_SPACE_LEFT(1L,len);
  108.   buf[0] = diag->DIAG[0]; 
  109.   buf++;
  110.   
  111.   CHECK_FOR_SPACE_LEFT(1L,len);
  112.   buf[0] = diag->DIAG[1];
  113.   buf++;
  114.   
  115.   if (length > 3)
  116.     { CHECK_FOR_SPACE_LEFT(3L,len);
  117.       memcpy(buf,diag->ADDINFO,(size_t)length - 3);
  118.       buf += length - 3;
  119.     }
  120.    
  121.   CHECK_FOR_SPACE_LEFT(1L,len);
  122.   buf[0] = diag->SURROGATE;
  123.   buf++;
  124.   
  125.   CHECK_FOR_SPACE_LEFT(1L,len);
  126.   buf[0] = END_OF_RECORD;
  127.   buf++;
  128.  
  129.   return(buf);
  130. }
  131.  
  132. /*----------------------------------------------------------------------*/
  133.  
  134. char* 
  135. readDiag(diag,buffer)
  136. diagnosticRecord** diag;
  137. char* buffer;
  138. {
  139.   char* buf = buffer;
  140.   diagnosticRecord* d 
  141.     = (diagnosticRecord*)s_malloc((size_t)sizeof(diagnosticRecord));
  142.   data_tag tag;
  143.   long len;
  144.   
  145.   buf = readTag(&tag,buf);
  146.   
  147.   buf = readBinaryInteger(&len,2L,buf);
  148.   
  149.   d->DIAG[0] = buf[0];
  150.   d->DIAG[1] = buf[1];
  151.   d->DIAG[2] = '\0';
  152.     
  153.   if (len > 3)
  154.     { d->ADDINFO = (char*)s_malloc((size_t)(len - 3 + 1));
  155.       memcpy(d->ADDINFO,(char*)(buf + 2),(size_t)(len - 3));
  156.       d->ADDINFO[len - 3] = '\0';
  157.     }
  158.   else
  159.     d->ADDINFO = NULL;
  160.     
  161.   d->SURROGATE = buf[len - 1];
  162.   
  163.   *diag = d;
  164.  
  165.   return(buf + len + 1);
  166. }
  167.  
  168. /*----------------------------------------------------------------------*/
  169.  
  170. #define continueBit    0x80
  171. #define dataMask    0x7F
  172. #define dataBits    7
  173.  
  174. char*
  175. writeCompressedInteger(num,buf,len)
  176. unsigned long num;
  177. char* buf;
  178. long* len;
  179. /* write a binary integer in the format described on p. 40.
  180.    this might be sped up 
  181. */
  182. {
  183.   char byte;
  184.   long i;
  185.   unsigned long size;
  186.   
  187.   size = writtenCompressedIntSize(num);
  188.   CHECK_FOR_SPACE_LEFT(size,len);
  189.   
  190.   for (i = size - 1; i >= 0; i--)
  191.     { byte = num & dataMask;
  192.       if (i != (size-1))    /* turn on continue bit */
  193.     byte = (char)(byte | continueBit);
  194.       buf[i] = byte;
  195.       num = num >> dataBits;    /* don't and here */
  196.     }
  197.    
  198.   return(buf + size);
  199.  
  200. /*----------------------------------------------------------------------*/
  201.  
  202. char*
  203. readCompressedInteger(num,buf)
  204. unsigned long *num;
  205. char* buf;
  206. /* read a binary integer in the format described on p. 40.
  207.    this might be sped up 
  208. */
  209. {
  210.   long i = 0;
  211.   unsigned char byte;
  212.  
  213.   *num = 0;
  214.   
  215.   do 
  216.     { byte = buf[i++];
  217.       *num = *num << dataBits;
  218.       *num += (byte & dataMask);
  219.     }
  220.   while (byte & continueBit);
  221.  
  222.   return(buf + i);
  223.  
  224. /*----------------------------------------------------------------------*/
  225.  
  226. #define pad    128 /* high bit is set */
  227.  
  228. char*
  229. writeCompressedIntWithPadding(num,size,buffer,len)
  230. unsigned long num;
  231. unsigned long size;
  232. char* buffer;
  233. long* len;
  234. /* Like writeCompressedInteger, except writes padding (128) to make
  235.    sure that size bytes are used.  This can be read correctly by 
  236.    readCompressedInteger()
  237. */
  238. {
  239.   char* buf = buffer;
  240.   unsigned long needed,padding;
  241.   long i;
  242.     
  243.   CHECK_FOR_SPACE_LEFT(size,len);
  244.   
  245.   needed = writtenCompressedIntSize(num);
  246.   padding = size - needed;
  247.   i = padding - 1;
  248.  
  249.   for (i = padding - 1;i >= 0;i--)
  250.     { buf[i] = pad;
  251.     }
  252.   
  253.   buf = writeCompressedInteger(num,buf + padding,len);
  254.   
  255.   return(buf);
  256.  
  257. /*----------------------------------------------------------------------*/
  258.  
  259. unsigned long
  260. writtenCompressedIntSize(num)
  261. unsigned long num;
  262. /* return the number of bytes needed to represnet the value num in
  263.    compressed format.  curently limited to 4 bytes
  264.  */
  265. {
  266.   if (num < CompressedInt1Byte) 
  267.     return(1);
  268.   else if (num < CompressedInt2Byte) 
  269.     return(2);
  270.   else if (num < CompressedInt3Byte)
  271.     return(3);
  272.   else
  273.     return(4);    
  274. }
  275.  
  276. /*----------------------------------------------------------------------*/
  277.  
  278. char*
  279. writeTag(tag,buf,len)
  280. data_tag tag;
  281. char* buf;
  282. long* len;
  283. /* write out a data tag */
  284.   return(writeCompressedInteger(tag,buf,len));
  285.  
  286. /*----------------------------------------------------------------------*/
  287.  
  288. char*
  289. readTag(tag,buf)
  290. data_tag* tag;
  291. char* buf;
  292. /* read a data tag */
  293.   return(readCompressedInteger(tag,buf));
  294.  
  295. /*----------------------------------------------------------------------*/
  296.  
  297. unsigned long 
  298. writtenTagSize(tag)
  299. data_tag tag;
  300.   return(writtenCompressedIntSize(tag));
  301. }
  302.  
  303. /*----------------------------------------------------------------------*/
  304.  
  305. data_tag
  306. peekTag(buf)
  307. char* buf;
  308. /* read a data tag without advancing the buffer */
  309. {
  310.   data_tag tag;
  311.   readTag(&tag,buf);
  312.   return(tag);
  313.  
  314. /*----------------------------------------------------------------------*/
  315.  
  316. any* 
  317. makeAny(size,data)
  318. unsigned long size;
  319. char* data;
  320. {
  321.   any* a = (any*)s_malloc((size_t)sizeof(any));
  322.   a->size = size;
  323.   a->bytes = data;
  324.   return(a);
  325. }
  326.  
  327. /*----------------------------------------------------------------------*/
  328.  
  329. void
  330. freeAny(a)
  331. any* a;
  332. /* destroy an any and its associated data. Assumes a->bytes was
  333.    allocated using the s_malloc family of libraries 
  334.  */
  335. {
  336.   if (a != NULL)
  337.     { if (a->bytes != NULL)
  338.     s_free(a->bytes);
  339.       s_free(a);
  340.     }
  341. }
  342.  
  343. /*----------------------------------------------------------------------*/
  344.  
  345. any* 
  346. duplicateAny(a)
  347. any* a;
  348. {
  349.   any* copy = NULL;
  350.  
  351.   if (a == NULL)
  352.     return(NULL);
  353.  
  354.   copy = (any*)s_malloc((size_t)sizeof(any));
  355.   copy->size = a->size;
  356.   if (a->bytes == NULL)
  357.     copy->bytes = NULL;
  358.   else
  359.     { copy->bytes = (char*)s_malloc((size_t)copy->size);
  360.       memcpy(copy->bytes,a->bytes,(size_t)copy->size);
  361.     }
  362.   return(copy);
  363. }
  364.  
  365. /*----------------------------------------------------------------------*/
  366.  
  367. char* 
  368. writeAny(a,tag,buffer,len)
  369. any* a;
  370. data_tag tag;
  371. char* buffer;
  372. long* len;
  373. /* write an any + tag and size info */
  374. {
  375.   char* buf = buffer;
  376.  
  377.   if (a == NULL)        /* handle unspecified optional args */
  378.     return(buf);
  379.   
  380.   /* write the tags */
  381.   buf = writeTag(tag,buf,len);
  382.   buf = writeCompressedInteger(a->size,buf,len);
  383.  
  384.   /* write the bytes */
  385.   CHECK_FOR_SPACE_LEFT(a->size,len);
  386.   memcpy(buf,a->bytes,(size_t)a->size);
  387.  
  388.   return(buf+a->size);
  389. }
  390.  
  391. /*----------------------------------------------------------------------*/
  392.  
  393. char* 
  394. readAny(anAny,buffer)
  395. any** anAny;
  396. char* buffer;
  397. /* read an any + tag and size info */
  398. {
  399.   char* buf = buffer;
  400.   any* a = (any*)s_malloc((size_t)sizeof(any));
  401.   data_tag tag;
  402.   
  403.   buf = readTag(&tag,buf);
  404.   buf = readCompressedInteger(&a->size,buf);
  405.   /* now simply copy the bytes */
  406.   a->bytes = (char*)s_malloc((size_t)a->size);
  407.   memcpy(a->bytes,buf,(size_t)a->size);
  408.   *anAny = a;
  409.   return(buf+a->size);
  410. }
  411.  
  412. /*----------------------------------------------------------------------*/
  413.  
  414. unsigned long 
  415. writtenAnySize(tag,a)
  416. data_tag tag;
  417. any* a;
  418. {
  419.   unsigned long size;
  420.  
  421.   if (a == NULL)
  422.     return(0);
  423.  
  424.   size = writtenTagSize(tag);
  425.   size += writtenCompressedIntSize(a->size);
  426.   size += a->size;
  427.   return(size);
  428. }
  429.  
  430. /*----------------------------------------------------------------------*/
  431.  
  432. any*
  433. stringToAny(s)
  434. char* s;
  435. {
  436.   any* a = NULL;
  437.   
  438.   if (s == NULL)
  439.     return(NULL);
  440.     
  441.   a = (any*)s_malloc((size_t)sizeof(any));
  442.   a->size = strlen(s);
  443.   a->bytes = (char*)s_malloc((size_t)a->size);
  444.   memcpy(a->bytes,s,(size_t)a->size);
  445.   return(a);
  446. }
  447.  
  448. /*----------------------------------------------------------------------*/
  449.  
  450. char*
  451. anyToString(a)
  452. any* a;
  453. {
  454.   char* s = NULL;
  455.   
  456.   if (a == NULL)
  457.     return(NULL);
  458.     
  459.   s = s_malloc((size_t)(a->size + 1));
  460.   memcpy(s,a->bytes,(size_t)a->size);
  461.   s[a->size] = '\0';
  462.   return(s);
  463. }
  464.  
  465. /*----------------------------------------------------------------------*/
  466.  
  467. char* 
  468. writeString(s,tag,buffer,len)
  469. char* s;
  470. data_tag tag;
  471. char* buffer;
  472. long* len;
  473. /* Write a C style string.  The terminating null is not written. 
  474.    This function is not part of the Z39.50 spec.  It is provided
  475.    for the convienience of those wishing to pass C strings in 
  476.    the place of an any.
  477.  */
  478. {
  479.   char* buf = buffer;
  480.   any* data = NULL;
  481.   if (s == NULL)
  482.     return(buffer);        /* handle unused optional item before making an any */
  483.   data = (any*)s_malloc((size_t)sizeof(any)); 
  484.   data->size = strlen(s);
  485.   data->bytes = s;        /* save a copy here by not using stringToAny() */
  486.   buf = writeAny(data,tag,buf,len);
  487.   s_free(data);            /* don't use freeAny() since it will free s too */
  488.   return(buf);
  489. }
  490.  
  491. /*----------------------------------------------------------------------*/
  492.  
  493. char* 
  494. readString(s ,buffer)
  495. char** s ;
  496. char* buffer;
  497. /* Read an any and convert it into a C style string.
  498.    This function is not part of the Z39.50 spec.  It is provided
  499.    for the convienience of those wishing to pass C strings in 
  500.    the place of an any. 
  501.  */
  502. {
  503.   any* data = NULL;
  504.   char* buf = readAny(&data,buffer);
  505.   *s = anyToString(data);
  506.   freeAny(data);
  507.   return(buf);
  508. }
  509.  
  510. /*----------------------------------------------------------------------*/
  511.  
  512. unsigned long 
  513. writtenStringSize(tag,s)
  514. data_tag tag;
  515. char* s;
  516. {
  517.   unsigned long size;
  518.  
  519.   if (s == NULL)
  520.    return(0);
  521.  
  522.   size = writtenTagSize(tag);
  523.   size += writtenCompressedIntSize(size);
  524.   size += strlen(s);
  525.   return(size);
  526. }
  527.  
  528. /*----------------------------------------------------------------------*/
  529.  
  530. any* 
  531. longToAny(num)
  532. long num;
  533. /* a convienience function */
  534. {
  535.   char s[40];
  536.  
  537.   sprintf(s,"%ld",num);
  538.   
  539.   return(stringToAny(s));
  540. }
  541.  
  542. /*----------------------------------------------------------------------*/
  543.  
  544. long
  545. anyToLong(a)
  546. any* a;
  547. /* a convienience function */
  548. {
  549.   long num;
  550.   char* str = NULL;
  551.   str = anyToString(a);
  552.   sscanf(str,"%ld",&num);    /* could check the result and return
  553.                    an error */
  554.   s_free(str);
  555.   return(num);
  556. }
  557.  
  558. /*----------------------------------------------------------------------*/
  559.  
  560. #define bitsPerByte    8
  561.  
  562. #ifdef ANSI_LIKE /* use ansi */
  563.  
  564. bit_map*
  565. makeBitMap(numBits)
  566. unsigned long numBits;
  567. /* construct and return a bitmap with numBits elements */
  568. {
  569.   va_list ap;
  570.   long i,j;
  571.   bit_map* bm = NULL;
  572.  
  573.   va_start(ap,numBits);
  574.   
  575.   bm = (bit_map*)s_malloc((size_t)sizeof(bit_map));
  576.   bm->size = (unsigned long)ceil((double)numBits / bitsPerByte); 
  577.   bm->bytes = (char*)s_malloc((size_t)bm->size);
  578.   
  579.   /* fill up the bits */
  580.   for (i = 0; i < bm->size; i++) /* iterate over bytes */
  581.     { char byte = 0;
  582.       for (j = 0; j < bitsPerByte; j++) /* iterate over bits */
  583.     { if ((i * bitsPerByte + j) < numBits)
  584.         { boolean bit = false;
  585.           bit = (boolean)va_arg(ap,boolean); 
  586.           if (bit)
  587.             { byte = byte | (1 << (bitsPerByte - j - 1));
  588.             }
  589.         }
  590.       }
  591.       bm->bytes[i] = byte;
  592.     }
  593.  
  594.   va_end(ap);
  595.   return(bm);
  596. }
  597.  
  598. #else /* use K & R */
  599.  
  600. bit_map*
  601. makeBitMap(va_alist)
  602. va_dcl
  603. /* construct and return a bitmap with numBits elements */
  604. {
  605.   va_list ap;
  606.   long i,j;
  607.   unsigned long numBits;
  608.   bit_map* bm = (bit_map*)s_malloc((size_t)sizeof(bit_map));
  609.  
  610.   va_start(ap);
  611.   
  612.   numBits = va_arg(ap,unsigned long);
  613.  
  614.   bm->size = (unsigned long)ceil((double)numBits / bitsPerByte);
  615.   
  616.   bm->bytes = (char*)s_malloc((size_t)bm->size);
  617.   
  618.   /* fill up the bits */
  619.   for (i = 0; i < bm->size; i++) /* iterate over bytes */
  620.     { char byte = 0;
  621.       for (j = 0; j < bitsPerByte; j++) /* iterate over bits */
  622.     { if ((i * bitsPerByte + j) < numBits)
  623.         { boolean bit;
  624.           bit = (boolean)va_arg(ap,int); /* really boolean, but this 
  625.                         is how it is passed on stack */
  626.           if (bit)
  627.             { byte = byte | (1 << (bitsPerByte - j - 1));
  628.             }
  629.         }
  630.       }
  631.       bm->bytes[i] = byte;
  632.     }
  633.  
  634.   va_end(ap);
  635.  
  636.   return(bm);
  637. }
  638.  
  639. #endif 
  640.  
  641. /*----------------------------------------------------------------------*/
  642.  
  643. void
  644. freeBitMap(bm)
  645. bit_map* bm;
  646. /* destroy a bit map created by makeBitMap() */
  647. {
  648.   s_free(bm->bytes);
  649.   s_free(bm);
  650. }
  651.  
  652. /*----------------------------------------------------------------------*/
  653.  
  654. /* use this routine to interpret a bit map.  pos specifies the bit 
  655.    number.  bit 0 is the Leftmost bit of the first byte.  
  656.    Could do bounds checking.
  657.  */
  658.  
  659. boolean
  660. bitAtPos(pos,bm)
  661. long pos;
  662. bit_map* bm;
  663. {
  664.   if (pos > bm->size*bitsPerByte)
  665.     return false;
  666.   else
  667.     return((bm->bytes[(pos / bitsPerByte)] & 
  668.         (0x80>>(pos % bitsPerByte))) ?
  669.        true : false);
  670. }
  671.  
  672. /*----------------------------------------------------------------------*/
  673.  
  674. char*
  675. writeBitMap(bm,tag,buffer,len)
  676. bit_map* bm;
  677. data_tag tag;
  678. char* buffer;
  679. long* len;
  680. /* write a bitmap + type and size info */
  681.   return(writeAny((any*)bm,tag,buffer,len));
  682. }
  683.  
  684. /*----------------------------------------------------------------------*/
  685.  
  686. char*
  687. readBitMap(bm,buffer)
  688. bit_map** bm;
  689. char* buffer;
  690. /* read a bitmap + type and size info */
  691.   return(readAny((any**)bm,buffer));
  692. }
  693.  
  694. /*----------------------------------------------------------------------*/
  695.  
  696. char* 
  697. writeByte(byte,buf,len)
  698. unsigned long byte;
  699. char* buf;
  700. long* len;
  701. {
  702.   CHECK_FOR_SPACE_LEFT(1L,len);
  703.   buf[0] = byte & 0xFF; /* we really only want the first byte */
  704.   return(buf + 1);
  705. }
  706.  
  707. /*----------------------------------------------------------------------*/
  708.  
  709. char* 
  710. readByte(byte,buf)
  711. unsigned char* byte;
  712. char* buf;
  713. {
  714.   *byte = buf[0];
  715.   return(buf + 1);
  716. }
  717.  
  718. /*----------------------------------------------------------------------*/
  719.  
  720. char* 
  721. writeBoolean(flag,buf,len)
  722. boolean flag;
  723. char* buf;
  724. long* len;
  725. {
  726.   return(writeByte(flag,buf,len));
  727. }
  728.  
  729. /*----------------------------------------------------------------------*/
  730.  
  731. char* 
  732. readBoolean(flag,buffer)
  733. boolean* flag;
  734. char* buffer;
  735. {
  736.   unsigned char byte;
  737.   char* buf = readByte(&byte,buffer);
  738.   *flag = (byte == true) ? true : false;
  739.   return(buf);
  740. }
  741.  
  742. /*----------------------------------------------------------------------*/
  743.  
  744. char*
  745. writePDUType(pduType,buf,len)
  746. pdu_type pduType;
  747. char* buf;
  748. long* len;
  749. /* PDUType is a single byte */
  750. {
  751.   return(writeBinaryInteger((long)pduType,(unsigned long)1,buf,len));
  752.  
  753. /*----------------------------------------------------------------------*/
  754.  
  755. char*
  756. readPDUType(pduType,buf)
  757. pdu_type* pduType;
  758. char* buf;
  759. /* PDUType is a single byte */
  760. {
  761.   return(readBinaryInteger((long*)pduType,(unsigned long)1,buf));
  762.  
  763. /*----------------------------------------------------------------------*/
  764.  
  765. pdu_type
  766. peekPDUType(buf)
  767. char* buf;
  768. /* read the next pdu without advancing the buffer, Note that this 
  769.    function is to be used on a buffer that is known to contain an
  770.    APDU.  The pdu_type is written HEADER_LEN bytes into the buffer
  771.  */
  772. {
  773.   pdu_type pdu;
  774.   readPDUType(&pdu,buf + HEADER_LEN);
  775.   return(pdu);
  776. }
  777.  
  778. /*----------------------------------------------------------------------*/
  779.  
  780. #define BINARY_INTEGER_BYTES    sizeof(long) /* the number of bytes used by
  781.                         a "binary integer" */
  782. char*
  783. writeBinaryInteger(num,size,buf,len)
  784. long num;
  785. unsigned long size;
  786. char* buf;
  787. long* len;
  788. /* write out first size bytes of num - no type info
  789.   XXX should this take unsigned longs instead ???  */
  790. {
  791.   long i;
  792.   char byte;
  793.  
  794.   if (size < 1 || size > BINARY_INTEGER_BYTES)
  795.     return(NULL);        /* error */
  796.  
  797.   CHECK_FOR_SPACE_LEFT(size,len);
  798.  
  799.   for (i = size - 1; i >= 0; i--)
  800.     { byte = (char)(num & 255);
  801.       buf[i] = byte;
  802.       num = num >> bitsPerByte; /* don't and here */
  803.     }
  804.  
  805.   return(buf + size);
  806. }
  807.  
  808. /*----------------------------------------------------------------------*/
  809.  
  810. char*
  811. readBinaryInteger(num,size,buf)
  812. long* num;
  813. unsigned long size;
  814. char* buf;
  815. /* read in first size bytes of num - no type info
  816.   XXX this should take unsigned longs instead !!! */
  817. {
  818.   long i;
  819.   unsigned char byte;
  820.   if (size < 1 || size > BINARY_INTEGER_BYTES)
  821.     return(buf);        /* error */
  822.   *num = 0;
  823.   for (i = 0; i < size; i++)
  824.     { byte = buf[i];
  825.       *num = *num << bitsPerByte;
  826.       *num += byte;
  827.     }
  828.   return(buf + size);
  829. }
  830.  
  831. /*----------------------------------------------------------------------*/
  832.  
  833. unsigned long 
  834. writtenCompressedBinIntSize(num)
  835. long num;
  836. /* return the number of bytes needed to represent the value num.
  837.    currently limited to max of 4 bytes 
  838.    Only compresses for positive nums - negatives get whole 4 bytes
  839.  */
  840. {
  841.   if (num < 0L)
  842.     return(4);
  843.   else if (num < 256L)        /* 2**8 */
  844.     return(1);
  845.   else if (num < 65536L)    /* 2**16 */
  846.     return(2);
  847.   else if (num < 16777216L)    /* 2**24 */
  848.     return(3);
  849.   else
  850.     return(4);
  851. }
  852.  
  853. /*----------------------------------------------------------------------*/
  854.  
  855. char*
  856. writeNum(num,tag,buffer,len)
  857. long num;
  858. data_tag tag;
  859. char* buffer;
  860. long* len;
  861. /* write a binary integer + size and tag info */
  862. {
  863.   char* buf = buffer;
  864.   long size = writtenCompressedBinIntSize(num);
  865.   
  866.   if (num == UNUSED)
  867.     return(buffer);
  868.     
  869.   buf = writeTag(tag,buf,len);
  870.   buf = writeCompressedInteger(size,buf,len); 
  871.   buf = writeBinaryInteger(num,(unsigned long)size,buf,len); 
  872.   return(buf);
  873. }
  874.  
  875. /*----------------------------------------------------------------------*/
  876.  
  877. char*
  878. readNum(num,buffer)
  879. long* num;
  880. char* buffer;
  881. /* read a binary integer + size and tag info */
  882. {
  883.   char* buf = buffer;
  884.   data_tag tag;
  885.   unsigned long size;
  886.   unsigned long val;
  887.   
  888.   buf = readTag(&tag,buf);
  889.   buf = readCompressedInteger(&val,buf);
  890.   size = (unsigned long)val;
  891.   buf = readBinaryInteger(num,size,buf);
  892.   return(buf);
  893. }
  894.  
  895. /*----------------------------------------------------------------------*/
  896.  
  897. unsigned long 
  898. writtenNumSize(tag,num)
  899. data_tag tag;
  900. long num;
  901. {
  902.   long dataSize = writtenCompressedBinIntSize(num);
  903.   long size;
  904.   
  905.   size = writtenTagSize(tag); /* space for the tag */
  906.   size += writtenCompressedIntSize(dataSize); /* space for the size */
  907.   size += dataSize; /* space for the data */
  908.   
  909.   return(size);
  910. }
  911.  
  912. /*----------------------------------------------------------------------*/
  913.  
  914. typedef void (voidfunc)();
  915.  
  916. void
  917. doList(list,func)
  918. void** list;
  919. voidfunc *func;
  920. /* call func on each element of the NULL terminated list of pointers */
  921. {
  922.   register long i;
  923.   register void* ptr = NULL;
  924.   if (list == NULL)
  925.     return;
  926.   for (i = 0,ptr = list[i]; ptr != NULL; ptr = list[++i])
  927.     (*func)(ptr);
  928. }
  929.  
  930. /*----------------------------------------------------------------------*/
  931.  
  932. char* 
  933. writeProtocolVersion(buf,len)
  934. char* buf;
  935. long* len;
  936. /* write a bitmap describing the protocols available */
  937. {
  938.   static bit_map* version = NULL;
  939.  
  940.   if (version == NULL)
  941.    { version = makeBitMap((unsigned long)1,true); /* version 1! */
  942.    }
  943.     
  944.   return(writeBitMap(version,DT_ProtocolVersion,buf,len));
  945. }
  946.  
  947. /*----------------------------------------------------------------------*/
  948.  
  949. char*
  950. defaultImplementationID()
  951. {
  952.   static char    ImplementationID[] = "TMC";
  953.   return(ImplementationID);
  954. }
  955.  
  956. /*----------------------------------------------------------------------*/
  957.  
  958. char*
  959. defaultImplementationName()
  960. {
  961.   static char ImplementationName[] = "Thinking Machines Corporation Z39.50";
  962.   return(ImplementationName);
  963. }
  964.  
  965. /*----------------------------------------------------------------------*/
  966.  
  967. char*
  968. defaultImplementationVersion()
  969. {
  970.   static char    ImplementationVersion[] = "2.0A";
  971.   return(ImplementationVersion);
  972. }
  973.  
  974. /*----------------------------------------------------------------------*/
  975.  
  976.