home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / zip21.zip / vms / vms_im.c < prev    next >
C/C++ Source or Header  |  1996-04-01  |  19KB  |  759 lines

  1. /*************************************************************************
  2.  *                                                                       *
  3.  * VMS portions copyright (C) 1993 Igor Mandrichenko.                    *
  4.  * Permission is granted to any individual or institution to use, copy,  *
  5.  * or redistribute this software so long as all of the original files    *
  6.  * are included, that it is not sold for profit, and that this copyright *
  7.  * notice is retained.                                                   *
  8.  *                                                                       *
  9.  *************************************************************************/
  10.  
  11. /*
  12.  *  vms_im.c (zip) by Igor Mandrichenko    Version 2.2-2
  13.  *
  14.  *  Revision history:
  15.  *  ...
  16.  *  2.1-1       16-feb-1993     I.Mandrichenko
  17.  *      Get file size from XABFHC and check bytes rest in file before
  18.  *      reading.
  19.  *  2.1-2       2-mar-1993      I.Mandrichenko
  20.  *      Make code more standard
  21.  *  2.2         21-jun-1993     I.Mandrichenko
  22.  *      Free all allocated space, use more static storage.
  23.  *      Use memcompress() from bits.c (deflation) for block compression.
  24.  *      To revert to old compression method #define OLD_COMPRESS
  25.  *  2.2-2       28-sep-1995     C.Spieler
  26.  *      Reorganized code for easier maintance of the two incompatible
  27.  *      flavours (IM style and PK style) VMS attribute support.
  28.  *      Generic functions (common to both flavours) are now collected
  29.  *      in a `wrapper' source file that includes one of the VMS attribute
  30.  *      handlers.
  31.  */
  32.  
  33. #ifdef VMS                      /* For VMS only ! */
  34.  
  35. #define OLD_COMPRESS            /*To use old compression method define it.*/
  36.  
  37. #ifdef VMS_ZIP
  38. #undef VMS_ZIP                  /* do NOT include PK style Zip definitions */
  39. #endif
  40. #include "vms.h"
  41.  
  42. #ifndef __LIB$ROUTINES_LOADED
  43. #include <lib$routines.h>
  44. #endif
  45.  
  46. #ifndef UTIL
  47.  
  48. #define RET_ERROR 1
  49. #define RET_SUCCESS 0
  50. #define RET_EOF 0
  51.  
  52. #define Kbyte 1024
  53.  
  54. typedef struct XAB *xabptr;
  55.  
  56. /*
  57.  *   Block sizes
  58.  */
  59.  
  60. #define EXTL0   ((FABL + EXTHL)+        \
  61.                 (XFHCL + EXTHL)+        \
  62.                 (XPROL + EXTHL)+        \
  63.                 (XDATL + EXTHL)+        \
  64.                 (XRDTL + EXTHL))
  65.  
  66. #ifdef OLD_COMPRESS
  67. #define PAD     sizeof(uch)
  68. #else
  69. #define PAD     10*sizeof(ush)          /* Two extra bytes for compr. header */
  70. #endif
  71.  
  72. #define PAD0    (5*PAD)                 /* Reserve space for the case when
  73.                                          *  compression fails */
  74. static int _compress(uch *from, uch *to, int size);
  75. #ifdef DEBUG
  76. static void dump_rms_block(uch *p);
  77. #endif /* DEBUG */
  78.  
  79. /********************************
  80.  *   Function set_extra_field   *
  81.  ********************************/
  82.  
  83. static uch *_compress_block(register struct IZ_block *to,
  84.                             uch *from, int size, char *sig);
  85. static int get_vms_version(char *verbuf, int len);
  86.  
  87. int set_extra_field(z, z_utim)
  88.   struct zlist far *z;
  89.   ztimbuf *z_utim;
  90. /*
  91.  *      Get file VMS file attributes and store them into extent fields.
  92.  *      Store VMS version also.
  93.  *      On error leave z intact.
  94.  */
  95. {
  96.     int status;
  97.     uch *extra=(uch*)NULL, *scan;
  98.     extent extra_l;
  99.     static struct FAB fab;
  100.     static struct XABSUM xabsum;
  101.     static struct XABFHC xabfhc;
  102.     static struct XABDAT xabdat;
  103.     static struct XABPRO xabpro;
  104.     static struct XABRDT xabrdt;
  105.     xabptr x = (xabptr)NULL, xab_chain = (xabptr)NULL, last_xab = (xabptr)NULL;
  106.     int nk, na;
  107.     int i;
  108.     int rc=RET_ERROR;
  109.     char verbuf[80];
  110.     int verlen = 0;
  111.  
  112.     if (!vms_native)
  113.     {
  114. #ifdef USE_EF_UX_TIME
  115.        /*
  116.         *  A `portable' zipfile entry is created. Create an "UX" extra block
  117.         *  containing UNIX style time stamps, which helps maintaining the
  118.         *  `real' "last modified" time when the archive is tranported
  119.         *  across time zone boundaries.
  120.         */
  121.        if ((extra = (uch *)malloc(EB_HEADSIZE+EB_UX_MINLEN)) == NULL)
  122.            return ZE_MEM;
  123.  
  124.        extra[0]  = 'U';
  125.        extra[1]  = 'X';
  126.        extra[2]  = EB_UX_MINLEN;          /* length of data part of e.f. */
  127.        extra[3]  = 0;
  128.        extra[4]  = (uch)(z_utim->actime);
  129.        extra[5]  = (uch)(z_utim->actime >> 8);
  130.        extra[6]  = (uch)(z_utim->actime >> 16);
  131.        extra[7]  = (uch)(z_utim->actime >> 24);
  132.        extra[8]  = (uch)(z_utim->modtime);
  133.        extra[9]  = (uch)(z_utim->modtime >> 8);
  134.        extra[10] = (uch)(z_utim->modtime >> 16);
  135.        extra[11] = (uch)(z_utim->modtime >> 24);
  136.  
  137.        z->cext = z->ext = (EB_HEADSIZE+EB_UX_MINLEN);
  138.        z->cextra = z->extra = (char*)extra;
  139. #endif /* USE_EF_UX_TIME */
  140.  
  141.        return RET_SUCCESS;
  142.     }
  143.  
  144.     /*
  145.      *  Initialize RMS control blocks and link them
  146.      */
  147.  
  148.     fab =    cc$rms_fab;
  149.     xabsum = cc$rms_xabsum;
  150.     xabdat = cc$rms_xabdat;
  151.     xabfhc = cc$rms_xabfhc;
  152.     xabpro = cc$rms_xabpro;
  153.     xabrdt = cc$rms_xabrdt;
  154.  
  155.  
  156.     fab.fab$l_xab = (char*)&xabsum;
  157.     /*
  158.      *  Open the file and read summary information.
  159.      */
  160.     fab.fab$b_fns = strlen(z->name);
  161.     fab.fab$l_fna = z->name;
  162.  
  163.     status = sys$open(&fab);
  164.     if (ERR(status))
  165.     {
  166. #ifdef DEBUG
  167.         printf("set_extra_field: sys$open for file %s:\n  error status = %d\n",
  168.                z->name, status);
  169. #endif
  170.         goto err_exit;
  171.     }
  172.  
  173.     nk = xabsum.xab$b_nok;
  174.     na = xabsum.xab$b_noa;
  175. #ifdef DEBUG
  176.     printf("%d keys, %d alls\n", nk, na);
  177. #endif
  178.  
  179.     /*
  180.      *  Allocate XABKEY and XABALL blocks and link them
  181.      */
  182.  
  183.     xabfhc.xab$l_nxt = (char*)&xabdat;
  184.     xabdat.xab$l_nxt = (char*)&xabpro;
  185.     xabpro.xab$l_nxt = (char*)&xabrdt;
  186.     xabrdt.xab$l_nxt = NULL;
  187.  
  188.     xab_chain = (xabptr)(&xabfhc);
  189.     last_xab  = (xabptr)(&xabrdt);
  190.  
  191. #define INIT(ptr,size,type,init)     \
  192.         if ( (ptr = (type *)malloc(size)) == NULL )     \
  193.         {                                               \
  194.               printf( "set_extra_field: Insufficient memory.\n" );   \
  195.                       goto err_exit;                    \
  196.         }                                               \
  197.         *(ptr) = (init);
  198.     /*
  199.      *  Allocate and initialize all needed XABKEYs and XABALLs
  200.      */
  201.     for (i = 0; i < nk; i++)
  202.     {
  203.         struct XABKEY *k;
  204.         INIT(k, XKEYL, struct XABKEY, cc$rms_xabkey);
  205.         k->xab$b_ref = i;
  206.         if (last_xab != NULL)
  207.             last_xab->xab$l_nxt = (char*)k;
  208.         last_xab = (xabptr)k;
  209.     }
  210.     for (i = 0; i < na; i++)
  211.     {
  212.         struct XABALL *a;
  213.         INIT(a, XALLL, struct XABALL, cc$rms_xaball);
  214.         a->xab$b_aid = i;
  215.         if (last_xab != NULL)
  216.             last_xab->xab$l_nxt = (char*)a;
  217.         last_xab = (xabptr)a;
  218.     }
  219.  
  220.     fab.fab$l_xab = (char*)xab_chain;
  221. #ifdef DEBUG
  222.     printf("Dump of XAB chain before $DISPLAY:\n");
  223.     for (x = xab_chain; x != NULL; x = x->xab$l_nxt)
  224.         dump_rms_block((uch *)x);
  225. #endif
  226.     /*
  227.      *  Get information on the file structure etc.
  228.      */
  229.     status = sys$display(&fab, 0, 0);
  230.     if (ERR(status))
  231.     {
  232. #ifdef DEBUG
  233.         printf("set_extra_field: sys$display for file %s:\n  error status = %d\n",
  234.                z->name, status);
  235. #endif
  236.         goto err_exit;
  237.     }
  238.  
  239. #ifdef DEBUG
  240.     printf("\nDump of XAB chain after $DISPLAY:\n");
  241.     for (x = xab_chain; x != NULL; x = x->xab$l_nxt)
  242.         dump_rms_block((uch *)x);
  243. #endif
  244.  
  245.     fab.fab$l_xab = NULL;  /* Keep XABs */
  246.     status = sys$close(&fab);
  247.     if (ERR(status))
  248.     {
  249. #ifdef DEBUG
  250.         printf("set_extra_field: sys$close for file %s:\n  error status = %d\n",
  251.                z->name, status);
  252. #endif
  253.         goto err_exit;
  254.     }
  255.  
  256.     extra_l = EXTL0 + nk * (XKEYL + EXTHL) + na * (XALLL + EXTHL);
  257. #ifndef OLD_COMPRESS
  258.     extra_l += PAD0 + (nk+na) * PAD;
  259. #endif
  260.  
  261.     if ( (verlen = get_vms_version(verbuf, sizeof(verbuf))) > 0 )
  262.     {
  263.         extra_l += verlen + EXTHL;
  264. #ifndef OLD_COMPRESS
  265.         extra_l += PAD;
  266. #endif
  267.     }
  268.  
  269.     if ((scan = extra = (uch *) malloc(extra_l)) == (uch*)NULL)
  270.     {
  271. #ifdef DEBUG
  272.         printf("set_extra_field: Insufficient memory to allocate extra buffer\n");
  273. #endif
  274.         goto err_exit;
  275.     }
  276.  
  277.  
  278.     if (verlen > 0)
  279.         scan = _compress_block((struct IZ_block *)scan, (uch *)verbuf,
  280.                                verlen, VERSIG);
  281.  
  282.     /*
  283.      *  Zero all unusable fields to improve compression
  284.      */
  285.     fab.fab$b_fns = fab.fab$b_shr = fab.fab$b_dns = fab.fab$b_fac = 0;
  286.     fab.fab$w_ifi = 0;
  287.     fab.fab$l_stv = fab.fab$l_sts = fab.fab$l_ctx = 0;
  288.     fab.fab$l_fna = NULL;
  289.     fab.fab$l_nam = NULL;
  290.     fab.fab$l_xab = NULL;
  291.     fab.fab$l_dna = NULL;
  292.  
  293. #ifdef DEBUG
  294.     dump_rms_block( (uch *)&fab );
  295. #endif
  296.     scan = _compress_block((struct IZ_block *)scan, (uch *)&fab, FABL, FABSIG);
  297.     for (x = xab_chain; x != NULL;)
  298.     {
  299.         int bln;
  300.         char *sig;
  301.         xabptr next;
  302.  
  303.         next = (xabptr)(x->xab$l_nxt);
  304.         x->xab$l_nxt = 0;
  305.  
  306.         switch (x->xab$b_cod)
  307.         {
  308.             case XAB$C_ALL:
  309.                 bln = XALLL;
  310.                 sig = XALLSIG;
  311.                 break;
  312.             case XAB$C_KEY:
  313.                 bln = XKEYL;
  314.                 sig = XKEYSIG;
  315.                 break;
  316.             case XAB$C_PRO:
  317.                 bln = XPROL;
  318.                 sig = XPROSIG;
  319.                 break;
  320.             case XAB$C_FHC:
  321.                 bln = XFHCL;
  322.                 sig = XFHCSIG;
  323.                 break;
  324.             case XAB$C_DAT:
  325.                 bln = XDATL;
  326.                 sig = XDATSIG;
  327.                 break;
  328.             case XAB$C_RDT:
  329.                 bln = XRDTL;
  330.                 sig = XRDTSIG;
  331.                 break;
  332.             default:
  333.                 bln = 0;
  334.                 sig = 0L;
  335.                 break;
  336.         }
  337.         if (bln > 0)
  338.             scan = _compress_block((struct IZ_block *)scan, (uch *)x,
  339.                                    bln, sig);
  340.         x = next;
  341.     }
  342.  
  343.     z->ext = z->cext = scan-extra;
  344.     z->extra = z->cextra = (char*)extra;
  345.     rc = RET_SUCCESS;
  346.  
  347. err_exit:
  348.     /*
  349.      *  Give up all allocated blocks
  350.      */
  351.     for (x = (struct XAB *)xab_chain; x != NULL; )
  352.     {
  353.         struct XAB *next;
  354.         next = (xabptr)(x->xab$l_nxt);
  355.         if (x->xab$b_cod == XAB$C_ALL || x->xab$b_cod == XAB$C_KEY)
  356.             free(x);
  357.         x = next;
  358.     }
  359.     return rc;
  360. }
  361.  
  362. static int get_vms_version(verbuf, len)
  363. char *verbuf;
  364. int len;
  365. {
  366.     int i = SYI$_VERSION;
  367.     int verlen = 0;
  368.     struct dsc$descriptor version;
  369.     char *m;
  370.  
  371.     version.dsc$a_pointer = verbuf;
  372.     version.dsc$w_length  = len - 1;
  373.     version.dsc$b_dtype   = DSC$K_DTYPE_B;
  374.     version.dsc$b_class   = DSC$K_CLASS_S;
  375.  
  376.     if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)
  377.         return 0;
  378.  
  379.     /* Cut out trailing spaces "V5.4-3   " -> "V5.4-3" */
  380.     for (m = verbuf + verlen, i = verlen - 1; i > 0 && verbuf[i] == ' '; --i)
  381.         --m;
  382.     *m = 0;
  383.  
  384.     /* Cut out release number "V5.4-3" -> "V5.4" */
  385.     if ((m = strrchr(verbuf, '-')) != NULL)
  386.         *m = 0;
  387.     return strlen(verbuf) + 1;  /* Transmit ending 0 too */
  388. }
  389.  
  390. #define CTXSIG ((ulg)('CtXx'))
  391.  
  392. typedef struct user_context
  393. {
  394.     ulg sig;
  395.     struct FAB *fab;
  396.     struct RAB *rab;
  397.     ulg size,rest;
  398.     int status;
  399. } Ctx, *Ctxptr;
  400.  
  401. Ctx init_ctx =
  402. {
  403.         CTXSIG,
  404.         NULL,
  405.         NULL,
  406.         0L,
  407.         0L,
  408.         0
  409. };
  410.  
  411. #define CTXL    sizeof(Ctx)
  412. #define CHECK_RAB(_r) ( (_r) != NULL &&                         \
  413.                         (_r) -> rab$b_bid == RAB$C_BID &&       \
  414.                         (_r) -> rab$b_bln == RAB$C_BLN &&       \
  415.                         (_r) -> rab$l_ctx != 0         &&       \
  416.                         (_r) -> rab$l_fab != NULL )
  417.  
  418. /**************************
  419.  *   Function vms_open    *
  420.  **************************/
  421. struct RAB *vms_open(name)
  422.     char *name;
  423. {
  424.     struct RAB *rab;
  425.     struct FAB *fab;
  426.     struct XABFHC *fhc;
  427.     Ctxptr ctx;
  428.  
  429.     if ((fab = (struct FAB *) malloc(FABL)) == (struct FAB *)NULL)
  430.         return NULL;
  431.     if ((rab = (struct RAB *) malloc(RABL)) == (struct RAB *)NULL)
  432.     {
  433.         free(fab);
  434.         return (struct RAB *)NULL;
  435.     }
  436.     if ((fhc = (struct XABFHC *) malloc(XFHCL)) == (struct XABFHC *)NULL)
  437.     {
  438.         free(rab);
  439.         free(fab);
  440.         return (struct RAB *)NULL;
  441.     }
  442.     if ((ctx = (Ctxptr) malloc(CTXL)) == (Ctxptr)NULL)
  443.     {
  444.         free(fhc);
  445.         free(fab);
  446.         free(rab);
  447.         return (struct RAB *)NULL;
  448.     }
  449.     *fab = cc$rms_fab;
  450.     *rab = cc$rms_rab;
  451.     *fhc = cc$rms_xabfhc;
  452.  
  453.     fab->fab$l_fna = name;
  454.     fab->fab$b_fns = strlen(name);
  455.     fab->fab$b_fac = FAB$M_GET | FAB$M_BIO;
  456.     fab->fab$l_xab = (char*)fhc;
  457.  
  458.     if (ERR(sys$open(fab)))
  459.     {
  460.         sys$close(fab);
  461.         free(fhc);
  462.         free(fab);
  463.         free(rab);
  464.         free(ctx);
  465.         return (struct RAB *)NULL;
  466.     }
  467.  
  468.     rab->rab$l_fab = fab;
  469.     rab->rab$l_rop = RAB$M_BIO;
  470.  
  471.     if (ERR(sys$connect(rab)))
  472.     {
  473.         sys$close(fab);
  474.         free(fab);
  475.         free(rab);
  476.         free(ctx);
  477.         return (struct RAB *)NULL;
  478.     }
  479.  
  480.     *ctx = init_ctx;
  481.     ctx->rab = rab;
  482.     ctx->fab = fab;
  483.  
  484.     if (fhc->xab$l_ebk > 0)
  485.         ctx->size = ctx->rest = ( fhc->xab$l_ebk-1 ) * 512 + fhc->xab$w_ffb;
  486.     else if ( fab->fab$b_org == FAB$C_IDX
  487.              || fab->fab$b_org == FAB$C_REL
  488.              || fab->fab$b_org == FAB$C_HSH )
  489.                 /* Special case, when ebk=0: save entire allocated space */
  490.         ctx->size = ctx->rest = fhc->xab$l_hbk * 512;
  491.     else
  492.         ctx->size = ctx->rest = fhc->xab$w_ffb;
  493.  
  494.     free(fhc);
  495.     fab->fab$l_xab = NULL;
  496.     rab->rab$l_ctx = (unsigned) ctx;
  497.     return rab;
  498. }
  499.  
  500. /**************************
  501.  *   Function vms_close   *
  502.  **************************/
  503. int vms_close(rab)
  504.     struct RAB *rab;
  505. {
  506.     struct FAB *fab;
  507.     Ctxptr ctx;
  508.  
  509.     if (!CHECK_RAB(rab))
  510.         return RET_ERROR;
  511.     fab = (ctx = (Ctxptr)(rab->rab$l_ctx))->fab;
  512.     sys$close(fab);
  513.  
  514.     free(fab);
  515.     free(rab);
  516.     free(ctx);
  517.  
  518.     return RET_SUCCESS;
  519. }
  520.  
  521. /**************************
  522.  *   Function vms_rewind  *
  523.  **************************/
  524. int vms_rewind(rab)
  525.     struct RAB *rab;
  526. {
  527.     Ctxptr ctx;
  528.  
  529.     int status;
  530.     if (!CHECK_RAB(rab))
  531.         return RET_ERROR;
  532.  
  533.     ctx = (Ctxptr) (rab->rab$l_ctx);
  534.     if (ERR(status = sys$rewind(rab)))
  535.     {
  536.         ctx->status = status;
  537.         return RET_ERROR;
  538.     }
  539.  
  540.     ctx->status = 0;
  541.     ctx->rest = ctx->size;
  542.  
  543.     return RET_SUCCESS;
  544. }
  545.  
  546. /**************************
  547.  *   Function vms_read    *
  548.  **************************/
  549. int vms_read(rab, buf, size)
  550.     struct RAB *rab;
  551. char *buf;
  552. int size;
  553. /*
  554.  *      size must be greater or equal to 512 !
  555.  */
  556. {
  557.     int status;
  558.     Ctxptr ctx;
  559.  
  560.     ctx = (Ctxptr)rab->rab$l_ctx;
  561.  
  562.     if (!CHECK_RAB(rab))
  563.         return 0;
  564.  
  565.     if (ctx -> rest <= 0)
  566.         return 0;               /* Eof */
  567.  
  568.     if (size > 16*Kbyte)        /* RMS can not read too much */
  569.         size = 16*Kbyte;
  570.     else
  571.         size &= ~511L;
  572.  
  573.     rab->rab$l_ubf = buf;
  574.     rab->rab$w_usz = size;
  575.     status = sys$read(rab);
  576.     if (!ERR(status) && rab->rab$w_rsz > 0)
  577.     {
  578.         ctx -> status = 0;
  579.         ctx -> rest -= rab->rab$w_rsz;
  580.         return rab->rab$w_rsz;
  581.     }
  582.     else
  583.     {
  584.         ctx->status = (status==RMS$_EOF ? 0:status);
  585.         if (status == RMS$_EOF)
  586.                 ctx -> rest = 0L;
  587.         return 0;
  588.     }
  589. }
  590.  
  591. /**************************
  592.  *   Function vms_error   *
  593.  **************************/
  594. int vms_error(rab)
  595.     struct RAB *rab;
  596. {
  597.     if (!CHECK_RAB(rab))
  598.         return RET_ERROR;
  599.     return ((Ctxptr) (rab->rab$l_ctx))->status;
  600. }
  601.  
  602.  
  603. #ifdef DEBUG
  604. static void dump_rms_block(p)
  605.     uch *p;
  606. {
  607.     uch bid, len;
  608.     int err;
  609.     char *type;
  610.     char buf[132];
  611.     int i;
  612.  
  613.     err = 0;
  614.     bid = p[0];
  615.     len = p[1];
  616.     switch (bid)
  617.     {
  618.         case FAB$C_BID:
  619.             type = "FAB";
  620.             break;
  621.         case XAB$C_ALL:
  622.             type = "xabALL";
  623.             break;
  624.         case XAB$C_KEY:
  625.             type = "xabKEY";
  626.             break;
  627.         case XAB$C_DAT:
  628.             type = "xabDAT";
  629.             break;
  630.         case XAB$C_RDT:
  631.             type = "xabRDT";
  632.             break;
  633.         case XAB$C_FHC:
  634.             type = "xabFHC";
  635.             break;
  636.         case XAB$C_PRO:
  637.             type = "xabPRO";
  638.             break;
  639.         default:
  640.             type = "Unknown";
  641.             err = 1;
  642.             break;
  643.     }
  644.     printf("Block @%08X of type %s (%d).", p, type, bid);
  645.     if (err)
  646.     {
  647.         printf("\n");
  648.         return;
  649.     }
  650.     printf(" Size = %d\n", len);
  651.     printf(" Offset - Hex - Dec\n");
  652.     for (i = 0; i < len; i += 8)
  653.     {
  654.         int j;
  655.  
  656.         printf("%3d - ", i);
  657.         for (j = 0; j < 8; j++)
  658.             if (i + j < len)
  659.                 printf("%02X ", p[i + j]);
  660.             else
  661.                 printf("   ");
  662.         printf(" - ");
  663.         for (j = 0; j < 8; j++)
  664.             if (i + j < len)
  665.                 printf("%03d ", p[i + j]);
  666.             else
  667.                 printf("    ");
  668.         printf("\n");
  669.     }
  670. }
  671. #endif /* DEBUG */
  672.  
  673. #ifdef OLD_COMPRESS
  674. # define BC_METHOD      BC_00
  675. # define        COMP_BLK(to,tos,from,froms) _compress( from,to,froms )
  676. #else
  677. # define BC_METHOD      BC_DEFL
  678. # define        COMP_BLK(to,tos,from,froms) memcompress(to,tos,from,froms)
  679. #endif
  680.  
  681. static uch *_compress_block(to,from,size,sig)
  682. register struct IZ_block *to;
  683. uch *from;
  684. int size;
  685. char *sig;
  686. {
  687.         ulg cl;
  688.         to -> sig =  *(ush*)IZ_SIGNATURE;
  689.         to -> bid =       *(ulg*)(sig);
  690.         to -> flags =           BC_METHOD;
  691.         to -> length =  size;
  692. #ifdef DEBUG
  693.         printf("\nmemcompr(%d,%d,%d,%d)\n",&(to->body[0]),size+PAD,from,size);
  694. #endif
  695.         cl = COMP_BLK( &(to->body[0]), size+PAD, from, size );
  696. #ifdef DEBUG
  697.         printf("Compressed to %d\n",cl);
  698. #endif
  699.         if (cl >= size)
  700.         {
  701.                 memcpy(&(to->body[0]), from, size);
  702.                 to->flags = BC_STORED;
  703.                 cl = size;
  704. #ifdef DEBUG
  705.                 printf("Storing block...\n");
  706. #endif
  707.         }
  708.         return (uch*)(to) + (to->size = cl + EXTBSL + RESL) + EB_HEADSIZE;
  709. }
  710.  
  711. #define NBITS 32
  712.  
  713. static int _compress(from,to,size)
  714. uch *from,*to;
  715. int size;
  716. {
  717.     int off=0;
  718.     ulg bitbuf=0;
  719.     int bitcnt=0;
  720.     int i;
  721.  
  722. #define _BIT(val,len)   {                       \
  723.         if (bitcnt + (len) > NBITS)             \
  724.             while(bitcnt >= 8)                  \
  725.             {                                   \
  726.                 to[off++] = (uch)bitbuf;        \
  727.                 bitbuf >>= 8;                   \
  728.                 bitcnt -= 8;                    \
  729.             }                                   \
  730.         bitbuf |= ((ulg)(val))<<bitcnt;         \
  731.         bitcnt += len;                          \
  732.     }
  733.  
  734. #define _FLUSH  {                               \
  735.             while(bitcnt>0)                     \
  736.             {                                   \
  737.                 to[off++] = (uch)bitbuf;        \
  738.                 bitbuf >>= 8;                   \
  739.                 bitcnt -= 8;                    \
  740.             }                                   \
  741.         }
  742.  
  743.     for (i=0; i<size; i++)
  744.     {
  745.         if (from[i])
  746.         {
  747.                 _BIT(1,1);
  748.                 _BIT(from[i],8);
  749.         }
  750.         else
  751.             _BIT(0,1);
  752.     }
  753.     _FLUSH;
  754.     return off;
  755. }
  756.  
  757. #endif /* !UTIL */
  758. #endif /* VMS */
  759.