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