diff options
Diffstat (limited to 'vms/vms_im.c')
-rw-r--r-- | vms/vms_im.c | 926 |
1 files changed, 926 insertions, 0 deletions
diff --git a/vms/vms_im.c b/vms/vms_im.c new file mode 100644 index 0000000..001088b --- /dev/null +++ b/vms/vms_im.c @@ -0,0 +1,926 @@ +/* + Copyright (c) 1990-2007 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2007-Mar-4 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html +*/ +/* + * vms_im.c (zip) by Igor Mandrichenko Version 2.2-2 + * + * Revision history: + * ... + * 2.1-1 16-feb-1993 I.Mandrichenko + * Get file size from XABFHC and check bytes rest in file before + * reading. + * 2.1-2 2-mar-1993 I.Mandrichenko + * Make code more standard + * 2.2 21-jun-1993 I.Mandrichenko + * Free all allocated space, use more static storage. + * Use memcompress() from bits.c (deflation) for block compression. + * To revert to old compression method #define OLD_COMPRESS + * 2.2-2 28-sep-1995 C.Spieler + * Reorganized code for easier maintance of the two incompatible + * flavours (IM style and PK style) VMS attribute support. + * Generic functions (common to both flavours) are now collected + * in a `wrapper' source file that includes one of the VMS attribute + * handlers. + * 3.0 23-Oct-2004 Steven Schweda + * Changed to maintain compatibility with VMS_PK.C. Note that + * reading with sys$read() prevents getting any data past EOF, + * regardless of appearances. Moved the VMS_PK_EXTRA test into + * here from VMS.C to allow more general automatic dependency + * generation. + * 17-Feb-2005 Steven Schweda + * Added support for ODS5 extended names. + */ + +#ifdef VMS /* For VMS only ! */ + +#ifndef VMS_PK_EXTRA + +#define OLD_COMPRESS /*To use old compression method define it.*/ + +#ifdef VMS_ZIP +#undef VMS_ZIP /* do NOT include PK style Zip definitions */ +#endif + +#include "vms.h" + +#ifndef __LIB$ROUTINES_LOADED +#include <lib$routines.h> +#endif + +#ifndef UTIL + +#define RET_ERROR 1 +#define RET_SUCCESS 0 +#define RET_EOF 0 + +#define Kbyte 1024 + +typedef struct XAB *xabptr; + +/* + * Block sizes + */ + +#define EXTL0 ((FABL + EXTHL)+ \ + (XFHCL + EXTHL)+ \ + (XPROL + EXTHL)+ \ + (XDATL + EXTHL)+ \ + (XRDTL + EXTHL)) + +#ifdef OLD_COMPRESS +#define PAD sizeof(uch) +#else +#define PAD 10*sizeof(ush) /* Two extra bytes for compr. header */ +#endif + +#define PAD0 (5*PAD) /* Reserve space for the case when + * compression fails */ +static int _compress(uch *from, uch *to, int size); +#ifdef DEBUG +static void dump_rms_block(uch *p); +#endif /* DEBUG */ + +/******************************** + * Function set_extra_field * + ********************************/ +/* + | 2004-11-11 SMS. + | Changed to use separate storage for ->extra and ->cextra. Zip64 + | processing may move (reallocate) one and not the other. + */ + +static uch *_compress_block(register struct IZ_block *to, + uch *from, int size, char *sig); +static int get_vms_version(char *verbuf, int len); + +int set_extra_field(z, z_utim) + struct zlist far *z; + iztimes *z_utim; +/* + * Get file VMS file attributes and store them into extent fields. + * Store VMS version also. + * On error leave z intact. + */ +{ + int status; + uch *xtra; + uch *cxtra; + uch *scan; + extent extra_l; + static struct FAB fab; + static struct NAM_STRUCT nam; + static struct XABSUM xabsum; + static struct XABFHC xabfhc; + static struct XABDAT xabdat; + static struct XABPRO xabpro; + static struct XABRDT xabrdt; + xabptr x = (xabptr)NULL, xab_chain = (xabptr)NULL, last_xab = (xabptr)NULL; + int nk, na; + int i; + int rc=RET_ERROR; + char verbuf[80]; + int verlen = 0; + + if (!vms_native) + { +#ifdef USE_EF_UT_TIME + /* + * A `portable' zipfile entry is created. Create an "UT" extra block + * containing UNIX style modification time stamp in UTC, which helps + * maintaining the `real' "last modified" time when the archive is + * transfered across time zone boundaries. + */ +# ifdef IZ_CHECK_TZ + if (!zp_tz_is_valid) + return ZE_OK; /* skip silently if no valid TZ info */ +# endif + if ((xtra = (uch *) malloc( EB_HEADSIZE+ EB_UT_LEN( 1))) == NULL) + return ZE_MEM; + + if ((cxtra = (uch *) malloc( EB_HEADSIZE+ EB_UT_LEN( 1))) == NULL) + return ZE_MEM; + + /* Fill xtra[] with data. */ + xtra[ 0] = 'U'; + xtra[ 1] = 'T'; + xtra[ 2] = EB_UT_LEN(1); /* length of data part of e.f. */ + xtra[ 3] = 0; + xtra[ 4] = EB_UT_FL_MTIME; + xtra[ 5] = (uch) (z_utim->mtime); + xtra[ 6] = (uch) (z_utim->mtime >> 8); + xtra[ 7] = (uch) (z_utim->mtime >> 16); + xtra[ 8] = (uch) (z_utim->mtime >> 24); + + /* Copy xtra[] data into cxtra[]. */ + memcpy( cxtra, xtra, (EB_HEADSIZE+ EB_UT_LEN( 1))); + + /* Set sizes and pointers. */ + z->cext = z->ext = (EB_HEADSIZE+ EB_UT_LEN( 1)); + z->extra = (char *) xtra; + z->cextra = (char *) cxtra; + +#endif /* USE_EF_UT_TIME */ + + return RET_SUCCESS; + } + + /* + * Initialize RMS control blocks and link them + */ + + fab = cc$rms_fab; + nam = CC_RMS_NAM; + xabsum = cc$rms_xabsum; + xabdat = cc$rms_xabdat; + xabfhc = cc$rms_xabfhc; + xabpro = cc$rms_xabpro; + xabrdt = cc$rms_xabrdt; + + fab.FAB_NAM = &nam; + fab.fab$l_xab = (char*)&xabsum; + /* + * Open the file and read summary information. + */ + +#ifdef NAML$C_MAXRSS + + fab.fab$l_dna = (char *) -1; /* Using NAML for default name. */ + fab.fab$l_fna = (char *) -1; /* Using NAML for file name. */ + +#endif /* def NAML$C_MAXRSS */ + + FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNA = z->name; + FAB_OR_NAML( fab, nam).FAB_OR_NAML_FNS = strlen( z->name); + +#ifdef NAML$M_OPEN_SPECIAL + /* 2007-02-28 SMS. + * If processing symlinks as symlinks ("-y"), then $OPEN the + * link, not the target file. + * + * (nam.naml$v_open_special gets us the symlink itself instead of + * its target. fab.fab$v_bio is necessary to allow sys$open() to + * work. Without it, you get status %x0001860c, "%RMS-F-ORG, + * invalid file organization value".) + */ + if (linkput) + { + nam.naml$v_open_special = 1; + fab.fab$v_bio = 1; + } +#endif /* def NAML$M_OPEN_SPECIAL */ + + status = sys$open(&fab); + if (ERR(status)) + { +#ifdef DEBUG + printf("set_extra_field: sys$open for file %s:\n error status = %d\n", + z->name, status); +#endif + goto err_exit; + } + + nk = xabsum.xab$b_nok; + na = xabsum.xab$b_noa; +#ifdef DEBUG + printf("%d keys, %d alls\n", nk, na); +#endif + + /* + * Allocate XABKEY and XABALL blocks and link them + */ + + xabfhc.xab$l_nxt = (char*)&xabdat; + xabdat.xab$l_nxt = (char*)&xabpro; + xabpro.xab$l_nxt = (char*)&xabrdt; + xabrdt.xab$l_nxt = NULL; + + xab_chain = (xabptr)(&xabfhc); + last_xab = (xabptr)(&xabrdt); + +#define INIT(ptr,size,type,init) \ + if ( (ptr = (type *)malloc(size)) == NULL ) \ + { \ + printf( "set_extra_field: Insufficient memory.\n" ); \ + goto err_exit; \ + } \ + *(ptr) = (init); + /* + * Allocate and initialize all needed XABKEYs and XABALLs + */ + for (i = 0; i < nk; i++) + { + struct XABKEY *k; + INIT(k, XKEYL, struct XABKEY, cc$rms_xabkey); + k->xab$b_ref = i; + if (last_xab != NULL) + last_xab->xab$l_nxt = (char*)k; + last_xab = (xabptr)k; + } + for (i = 0; i < na; i++) + { + struct XABALL *a; + INIT(a, XALLL, struct XABALL, cc$rms_xaball); + a->xab$b_aid = i; + if (last_xab != NULL) + last_xab->xab$l_nxt = (char*)a; + last_xab = (xabptr)a; + } + + fab.fab$l_xab = (char*)xab_chain; +#ifdef DEBUG + printf("Dump of XAB chain before $DISPLAY:\n"); + for (x = xab_chain; x != NULL; x = x->xab$l_nxt) + dump_rms_block((uch *)x); +#endif + /* + * Get information on the file structure etc. + */ + status = sys$display(&fab, 0, 0); + if (ERR(status)) + { +#ifdef DEBUG + printf("set_extra_field: sys$display for file %s:\n error status = %d\n", + z->name, status); +#endif + goto err_exit; + } + +#ifdef DEBUG + printf("\nDump of XAB chain after $DISPLAY:\n"); + for (x = xab_chain; x != NULL; x = x->xab$l_nxt) + dump_rms_block((uch *)x); +#endif + + fab.fab$l_xab = NULL; /* Keep XABs */ + status = sys$close(&fab); + if (ERR(status)) + { +#ifdef DEBUG + printf("set_extra_field: sys$close for file %s:\n error status = %d\n", + z->name, status); +#endif + goto err_exit; + } + + extra_l = EXTL0 + nk * (XKEYL + EXTHL) + na * (XALLL + EXTHL); +#ifndef OLD_COMPRESS + extra_l += PAD0 + (nk+na) * PAD; +#endif + + if ( (verlen = get_vms_version(verbuf, sizeof(verbuf))) > 0 ) + { + extra_l += verlen + EXTHL; +#ifndef OLD_COMPRESS + extra_l += PAD; +#endif + } + + if ((scan = xtra = (uch *) malloc( extra_l)) == (uch*)NULL) + { +#ifdef DEBUG + printf( + "set_extra_field: Insufficient memory to allocate extra L buffer\n"); +#endif + goto err_exit; + } + + if ((cxtra = (uch *) malloc( extra_l)) == (uch*)NULL) + { +#ifdef DEBUG + printf( + "set_extra_field: Insufficient memory to allocate extra C buffer\n"); +#endif + goto err_exit; + } + + if (verlen > 0) + scan = _compress_block((struct IZ_block *)scan, (uch *)verbuf, + verlen, VERSIG); + + /* + * Zero all unusable fields to improve compression + */ + fab.fab$b_fns = fab.fab$b_shr = fab.fab$b_dns = fab.fab$b_fac = 0; + fab.fab$w_ifi = 0; + fab.fab$l_stv = fab.fab$l_sts = fab.fab$l_ctx = 0; + fab.fab$l_dna = NULL; + fab.fab$l_fna = NULL; + fab.fab$l_nam = NULL; +#ifdef NAML$C_MAXRSS + fab.fab$l_naml = NULL; +#endif /* def NAML$C_MAXRSS */ + fab.fab$l_xab = NULL; + +#ifdef DEBUG + dump_rms_block( (uch *)&fab ); +#endif + scan = _compress_block((struct IZ_block *)scan, (uch *)&fab, FABL, FABSIG); + for (x = xab_chain; x != NULL;) + { + int bln; + char *sig; + xabptr next; + + next = (xabptr)(x->xab$l_nxt); + x->xab$l_nxt = 0; + + switch (x->xab$b_cod) + { + case XAB$C_ALL: + bln = XALLL; + sig = XALLSIG; + break; + case XAB$C_KEY: + bln = XKEYL; + sig = XKEYSIG; + break; + case XAB$C_PRO: + bln = XPROL; + sig = XPROSIG; + break; + case XAB$C_FHC: + bln = XFHCL; + sig = XFHCSIG; + break; + case XAB$C_DAT: + bln = XDATL; + sig = XDATSIG; + break; + case XAB$C_RDT: + bln = XRDTL; + sig = XRDTSIG; + break; + default: + bln = 0; + sig = 0L; + break; + } + if (bln > 0) + scan = _compress_block((struct IZ_block *)scan, (uch *)x, + bln, sig); + x = next; + } + + /* Copy xtra[] data into cxtra[]. */ + memcpy( cxtra, xtra, (scan- xtra)); + + /* Set sizes and pointers. */ + z->cext = z->ext = scan- xtra; + z->extra = (char*) xtra; + z->cextra = (char*) cxtra; + + rc = RET_SUCCESS; + +err_exit: + /* + * Give up all allocated blocks + */ + for (x = (struct XAB *)xab_chain; x != NULL; ) + { + struct XAB *next; + next = (xabptr)(x->xab$l_nxt); + if (x->xab$b_cod == XAB$C_ALL || x->xab$b_cod == XAB$C_KEY) + free(x); + x = next; + } + return rc; +} + +static int get_vms_version(verbuf, len) +char *verbuf; +int len; +{ + int i = SYI$_VERSION; + int verlen = 0; + struct dsc$descriptor version; + char *m; + + version.dsc$a_pointer = verbuf; + version.dsc$w_length = len - 1; + version.dsc$b_dtype = DSC$K_DTYPE_B; + version.dsc$b_class = DSC$K_CLASS_S; + + if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0) + return 0; + + /* Cut out trailing spaces "V5.4-3 " -> "V5.4-3" */ + for (m = verbuf + verlen, i = verlen - 1; i > 0 && verbuf[i] == ' '; --i) + --m; + *m = 0; + + /* Cut out release number "V5.4-3" -> "V5.4" */ + if ((m = strrchr(verbuf, '-')) != NULL) + *m = 0; + return strlen(verbuf) + 1; /* Transmit ending 0 too */ +} + +#define CTXSIG ((ulg)('CtXx')) + +typedef struct user_context +{ + ulg sig; + struct FAB *fab; + struct NAM_STRUCT *nam; + struct RAB *rab; + uzoff_t size; + uzoff_t rest; + int status; +} Ctx, *Ctxptr; + +Ctx init_ctx = +{ + CTXSIG, + NULL, + NULL, + NULL, + 0L, + 0L, + 0 +}; + +#define CTXL sizeof(Ctx) +#define CHECK_RAB(_r) ( (_r) != NULL && \ + (_r) -> rab$b_bid == RAB$C_BID && \ + (_r) -> rab$b_bln == RAB$C_BLN && \ + (_r) -> rab$l_ctx != 0 && \ + (_r) -> rab$l_fab != NULL ) + + +#define BLOCK_BYTES 512 + +/************************** + * Function vms_open * + **************************/ +struct RAB *vms_open(name) + char *name; +{ + struct FAB *fab; + struct NAM_STRUCT *nam; + struct RAB *rab; + struct XABFHC *fhc; + Ctxptr ctx; + + if ((fab = (struct FAB *) malloc(FABL)) == NULL) + return NULL; + + if ((nam = + (struct NAM_STRUCT *) malloc( sizeof( struct NAM_STRUCT))) == NULL) + { + free(fab); + return NULL; + } + + if ((rab = (struct RAB *) malloc(RABL)) == NULL) + { + free(fab); + free(nam); + return NULL; + } + + if ((fhc = (struct XABFHC *) malloc(XFHCL)) == (struct XABFHC *)NULL) + { + free(fab); + free(nam); + free(rab); + return (struct RAB *)NULL; + } + if ((ctx = (Ctxptr) malloc(CTXL)) == (Ctxptr)NULL) + { + free(fab); + free(nam); + free(rab); + free(fhc); + return (struct RAB *)NULL; + } + *fab = cc$rms_fab; + *nam = CC_RMS_NAM; + *rab = cc$rms_rab; + *fhc = cc$rms_xabfhc; + + fab->FAB_NAM = nam; + +#ifdef NAML$C_MAXRSS + + fab->fab$l_dna = (char *) -1; /* Using NAML for default name. */ + fab->fab$l_fna = (char *) -1; /* Using NAML for file name. */ + +#endif /* def NAML$C_MAXRSS */ + + FAB_OR_NAML( fab, nam)->FAB_OR_NAML_FNA = name; + FAB_OR_NAML( fab, nam)->FAB_OR_NAML_FNS = strlen( name); + + fab->fab$b_fac = FAB$M_GET | FAB$M_BIO; + fab->fab$l_xab = (char*)fhc; + +#ifdef NAML$M_OPEN_SPECIAL + /* 2007-02-28 SMS. + * If processing symlinks as symlinks ("-y"), then $OPEN the + * link, not the target file. (Note that here the required + * fab->fab$v_bio flag was set above.) + */ + if (linkput) + { + nam->naml$v_open_special = 1; + } +#endif /* def NAML$M_OPEN_SPECIAL */ + + if (ERR(sys$open(fab))) + { + sys$close(fab); + free(fab); + free(nam); + free(rab); + free(fhc); + free(ctx); + return (struct RAB *)NULL; + } + + rab->rab$l_fab = fab; + rab->rab$l_rop = RAB$M_BIO; + + if (ERR(sys$connect(rab))) + { + sys$close(fab); + free(fab); + free(nam); + free(rab); + free(ctx); + return (struct RAB *)NULL; + } + + *ctx = init_ctx; + ctx->fab = fab; + ctx->nam = nam; + ctx->rab = rab; + + if (fhc->xab$l_ebk == 0) + { + /* Only known size is all allocated blocks. + (This occurs with a zero-length file, for example.) + */ + ctx->size = + ctx->rest = ((uzoff_t) fhc->xab$l_hbk)* BLOCK_BYTES; + } + else + { + /* Store normal (used) size in ->size. + If only one -V, store normal (used) size in ->rest. + If -VV, store allocated-blocks size in ->rest. + */ + ctx->size = + (((uzoff_t) fhc->xab$l_ebk)- 1)* BLOCK_BYTES+ fhc->xab$w_ffb; + if (vms_native < 2) + ctx->rest = ctx->size; + else + ctx->rest = ((uzoff_t) fhc->xab$l_hbk)* BLOCK_BYTES; + } + + free(fhc); + fab->fab$l_xab = NULL; + rab->rab$l_ctx = (unsigned) ctx; + return rab; +} + +/************************** + * Function vms_close * + **************************/ +int vms_close(rab) + struct RAB *rab; +{ + struct FAB *fab; + struct NAM_STRUCT *nam; + Ctxptr ctx; + + if (!CHECK_RAB(rab)) + return RET_ERROR; + fab = (ctx = (Ctxptr)(rab->rab$l_ctx))->fab; + nam = (ctx = (Ctxptr)(rab->rab$l_ctx))->nam; + sys$close(fab); + + free(fab); + free(nam); + free(rab); + free(ctx); + + return RET_SUCCESS; +} + +/************************** + * Function vms_rewind * + **************************/ +int vms_rewind(rab) + struct RAB *rab; +{ + Ctxptr ctx; + + int status; + if (!CHECK_RAB(rab)) + return RET_ERROR; + + ctx = (Ctxptr) (rab->rab$l_ctx); + if (ERR(status = sys$rewind(rab))) + { + ctx->status = status; + return RET_ERROR; + } + + ctx->status = 0; + ctx->rest = ctx->size; + + return RET_SUCCESS; +} + + +#define KByte (2* BLOCK_BYTES) +#define MAX_READ_BYTES (32* KByte) + +/************************** + * Function vms_read * + **************************/ +size_t vms_read(rab, buf, size) +struct RAB *rab; +char *buf; +size_t size; +/* + * size must be greater or equal to 512 ! + */ +{ + int status; + Ctxptr ctx; + + ctx = (Ctxptr)rab->rab$l_ctx; + + if (!CHECK_RAB(rab)) + return 0; + + if (ctx -> rest == 0) + return 0; /* Eof */ + + /* If request is smaller than a whole block, fail. + This really should never happen. (assert()?) + */ + if (size < BLOCK_BYTES) + return 0; + + /* 2004-09-27 SMS. + Code here now resembles low-level QIO code in VMS_PK.C, but I + doubt that sys$read() will actually get past the official EOF. + */ + + /* Adjust request size as appropriate. */ + if (size > MAX_READ_BYTES) + { + /* Restrict request to MAX_READ_BYTES. */ + size = MAX_READ_BYTES; + } + else + { + /* Round odd-ball request up to the next whole block. + This really should never happen. (assert()?) + */ + size = (size+ BLOCK_BYTES- 1)& ~(BLOCK_BYTES- 1); + } + + /* Reduce "size" when next (last) read would overrun the EOF, + but never below one byte (so we'll always get a nice EOF). + */ + if (size > ctx->rest) + size = ctx->rest; + if (size == 0) + size = 1; + + rab->rab$l_ubf = buf; + rab->rab$w_usz = size; + status = sys$read(rab); + + if (!ERR(status) && rab->rab$w_rsz > 0) + { + ctx -> status = 0; + ctx -> rest -= rab->rab$w_rsz; + return rab->rab$w_rsz; + } + else + { + ctx->status = (status==RMS$_EOF ? 0:status); + if (status == RMS$_EOF) + ctx -> rest = 0; + return 0; + } +} + +/************************** + * Function vms_error * + **************************/ +int vms_error(rab) + struct RAB *rab; +{ + if (!CHECK_RAB(rab)) + return RET_ERROR; + return ((Ctxptr) (rab->rab$l_ctx))->status; +} + + +#ifdef DEBUG +static void dump_rms_block(p) + uch *p; +{ + uch bid, len; + int err; + char *type; + char buf[132]; + int i; + + err = 0; + bid = p[0]; + len = p[1]; + switch (bid) + { + case FAB$C_BID: + type = "FAB"; + break; + case XAB$C_ALL: + type = "xabALL"; + break; + case XAB$C_KEY: + type = "xabKEY"; + break; + case XAB$C_DAT: + type = "xabDAT"; + break; + case XAB$C_RDT: + type = "xabRDT"; + break; + case XAB$C_FHC: + type = "xabFHC"; + break; + case XAB$C_PRO: + type = "xabPRO"; + break; + default: + type = "Unknown"; + err = 1; + break; + } + printf("Block @%08X of type %s (%d).", p, type, bid); + if (err) + { + printf("\n"); + return; + } + printf(" Size = %d\n", len); + printf(" Offset - Hex - Dec\n"); + for (i = 0; i < len; i += 8) + { + int j; + + printf("%3d - ", i); + for (j = 0; j < 8; j++) + if (i + j < len) + printf("%02X ", p[i + j]); + else + printf(" "); + printf(" - "); + for (j = 0; j < 8; j++) + if (i + j < len) + printf("%03d ", p[i + j]); + else + printf(" "); + printf("\n"); + } +} +#endif /* DEBUG */ + +#ifdef OLD_COMPRESS +# define BC_METHOD EB_IZVMS_BC00 +# define COMP_BLK(to,tos,from,froms) _compress( from,to,froms ) +#else +# define BC_METHOD EB_IZVMS_BCDEFL +# define COMP_BLK(to,tos,from,froms) memcompress(to,tos,from,froms) +#endif + +static uch *_compress_block(to,from,size,sig) +register struct IZ_block *to; +uch *from; +int size; +char *sig; +{ + ulg cl; + to -> sig = *(ush*)IZ_SIGNATURE; + to -> bid = *(ulg*)(sig); + to -> flags = BC_METHOD; + to -> length = size; +#ifdef DEBUG + printf("\nmemcompr(%d,%d,%d,%d)\n",&(to->body[0]),size+PAD,from,size); +#endif + cl = COMP_BLK( &(to->body[0]), size+PAD, from, size ); +#ifdef DEBUG + printf("Compressed to %d\n",cl); +#endif + if (cl >= size) + { + memcpy(&(to->body[0]), from, size); + to->flags = EB_IZVMS_BCSTOR; + cl = size; +#ifdef DEBUG + printf("Storing block...\n"); +#endif + } + return (uch*)(to) + (to->size = cl + EXTBSL + RESL) + EB_HEADSIZE; +} + +#define NBITS 32 + +static int _compress(from,to,size) +uch *from,*to; +int size; +{ + int off=0; + ulg bitbuf=0; + int bitcnt=0; + int i; + +#define _BIT(val,len) { \ + if (bitcnt + (len) > NBITS) \ + while(bitcnt >= 8) \ + { \ + to[off++] = (uch)bitbuf; \ + bitbuf >>= 8; \ + bitcnt -= 8; \ + } \ + bitbuf |= ((ulg)(val))<<bitcnt; \ + bitcnt += len; \ + } + +#define _FLUSH { \ + while(bitcnt>0) \ + { \ + to[off++] = (uch)bitbuf; \ + bitbuf >>= 8; \ + bitcnt -= 8; \ + } \ + } + + for (i=0; i<size; i++) + { + if (from[i]) + { + _BIT(1,1); + _BIT(from[i],8); + } + else + _BIT(0,1); + } + _FLUSH; + return off; +} + +#endif /* !UTIL */ + +#endif /* ndef VMS_PK_EXTRA */ + +#endif /* VMS */ |