Update of /cvsroot/linux-atm/linux-atm/src/ilmid/asn1 In directory usw-pr-cvs1:/tmp/cvs-serv10656/ilmid/asn1 Added Files: Tag: V2_4_0 str_stk.c str_stk.h exp_buf.c exp_buf.h README asn_bits.c asn_bits.h min_buf.h asn_incl.h asn_config.h asn_list.c asn_list.h asn_octs.c asn_octs.h asn_null.c asn_null.h nibble_alloc.c nibble_alloc.h asn_int.c asn_int.h asn_len.c asn_len.h asn_oid.c asn_oid.h asn_tag.c asn_tag.h Makefile.am sbuf.h print.c print.h Log Message: --- NEW FILE: str_stk.c --- /* * str_stk.c - maintains a stack of the components of a bit string * or octet string so they can be copied into a single chunk * * Copyright (C) 1992 Michael Sample and the University of British Columbia * * This library is free software; you can redistribute it and/or * modify it provided that this copyright/license information is retained * in original form. * * If you modify this file, you must clearly indicate your changes. * * This source code is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #if HAVE_CONFIG_H #include <config.h> #endif #include "asn_config.h" #include "str_stk.h" /* global for use by AsnBits and AsnOcts */ StrStk strStkG = { NULL, 128, 0, 64, 0, 0 }; --- NEW FILE: str_stk.h --- /* * str_stk.h - maintains a stack of the components of a bit string * or octet string so they can be copied into a single chunk * * * CONSTRUCTED BIT AND OCTET STRINGS SUCK. They should be * specified in the application's ASN.1 spec as SEQUENCE OF OCTET STRING * * this stack stuff is for decoding constructed bit/octet strings * so the user gets a single contiguous bit/octet str instead of * irritating little pieces. This does not cost a lot more than * a linked octet/bit string type since we're copying from the * buffer anyway, not referencing it directly (even in simple case). * It will cost more if the string stk overflows and * needs to be enlarged via realloc - set the values of * initialStkSizeG, and stkGrowSize carefully for your application. * Once the StkSize grows, it doesn't shrink back ever. * * Only three routine use/deal with this stack garbage * BDecConsAsnOcts * BDecConsAsnBits * SetupConsBitsOctsStringStk * * Copyright (C) 1992 Michael Sample and the University of British Columbia * * This library is free software; you can redistribute it and/or * modify it provided that this copyright/license information is retained * in original form. * * If you modify this file, you must clearly indicate your changes. * * This source code is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ typedef struct StrStkElmt { char* str; unsigned long int len; } StrStkElmt; typedef struct StrStk { StrStkElmt* stk; /* ptr to array of SSElmts with 'size' elmts */ unsigned long int initialNumElmts; unsigned long int numElmts; /* total # of elements in str stk */ unsigned long int growElmts; /* # elmts to increase size by when nec */ unsigned long int nextFreeElmt; /* index of next free element */ unsigned long int totalByteLen; /* octet len of string stored in stk */ } StrStk; extern StrStk strStkG; /* * initializes stk (Allocates if nec.) * once stk is enlarged, it doesn't shrink */ #define RESET_STR_STK()\ {\ strStkG.nextFreeElmt = 0;\ strStkG.totalByteLen = 0;\ if (strStkG.stk == NULL){\ strStkG.stk = (StrStkElmt*) malloc((strStkG.initialNumElmts) *sizeof(StrStkElmt));\ strStkG.numElmts = strStkG.initialNumElmts;}\ } /* * add a char*,len pair to top of stack. * grows stack if necessary using realloc (!) */ #define PUSH_STR(strPtr, strsLen, env)\ {\ if (strStkG.nextFreeElmt >= strStkG.numElmts)\ {\ strStkG.stk = (StrStkElmt*) realloc(strStkG.stk, (strStkG.numElmts + strStkG.growElmts) *sizeof(StrStkElmt));\ strStkG.numElmts += strStkG.growElmts;\ }\ strStkG.totalByteLen += strsLen;\ strStkG.stk[strStkG.nextFreeElmt].str = strPtr;\ strStkG.stk[strStkG.nextFreeElmt].len = strsLen;\ strStkG.nextFreeElmt++;\ } /* * Set up size values for the stack that is used for merging constructed * octet or bit string into single strings. * **** Call this before decoding anything. ***** * Note: you don't have to call this if the default values * for initialStkSizeG and stkGrowSizeG are acceptable */ #define SetupConsBitsOctsStringStk (initialNumberOfElmts, numberOfElmtsToGrowBy)\ {\ strStkG.initialNumElmts = initialNumberOfElmts; \ strStkG.growElmts = numberOfElmtsToGrowBy;\ } --- NEW FILE: exp_buf.c --- /* * exp_buf.c - buffer routines for the buffer structure * * * --------- ---------- * | ExpBuf |<------>| ExpBuf |<------> ...ExpBufs * | |--- | |--- * ---------- | ---------- | * V V * -------- -------- * | DATA | | DATA | * | BLK | | BLK | * -------- -------- * * * ExpBuf * -------------- * | readError | * | writeError | * | dataStart |----------- * | dataEnd |-------- | * | curr |------ | | * | next | | | | * | prev | | | | data * | blkStart |=====|=|==|==>-------------------------- * | blkEnd |--- | | | | | (each line * -------------- | | | | | | reps a byte * | | | |-->| - - - - - - - - - - - -| diff in addr) * | | | | valid | * | |-|----->| | * | | | data | * | | | | * | | | - - - - - - - - - - - -| * | |----->|(one byte after last valid data byte) * | | | * | -------------------------- * |-----------> (one byte after last byte in data blk) * * * readError - set to non-zero to indicate attempt to read past end of * of data * writeError- set to non-zero to indicate write error. * Set if Alloc of new buf fails * dataStart - pts to first VALID data byte ie *dataStart is first byte * dataEnd - pts to byte AFTER last VALID byte *dataEnd is not in the data * but *(dataEnd -1) is in the data * curr - used for current read ptr - points to next byte to be read * so *curr is the next byte to be read. * next - pts to next BUF in list, NULL for last BUF in list * prev - pts to prev BUF in list, NULL for first BUF in list * blkStart - pts to start of the data blk. *blkStart is first byte * in the buffer's data blk. * blkEnd - pts to byte AFTER last writable byte of the dataBlk. * *(blkEnd-1) is the last byte in the buffer's data blk. * * NOTES: * - dataEnd is currently always the same as blkEnd * - at End Of Data (EOD) (no more data to be read) * if (curr == dataEnd) * - buffer has no valid data if (dataStart == dataEnd) * - number of valid data bytes = (dataEnd - dataStart) * - size of the data block = (blkEnd - blkStart) * * - the write reverse routines modify dataStart * - the read routines modify the curr ptr. * - there are no 'forward' write routines at the moment * (if there were they would adjust dataEnd) * * * Copyright (C) 1992 Michael Sample and the University of British Columbia * * This library is free software; you can redistribute it and/or * modify it provided that this copyright/license information is retained * in original form. * * If you modify this file, you must clearly indicate your changes. * * This source code is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * */ #if HAVE_CONFIG_H #include <config.h> #endif #include "asn_config.h" #include "exp_buf.h" /* default buffer data block size (used when allocating) */ unsigned long expBufDataBlkSizeG = 1024; #ifdef DEBUG /* otherwise macros */ /* * sets the size of the data block to attach to * an ExpBuf when allocating a new one */ void ExpBufInit PARAMS((dataBlkSize), unsigned long dataBlkSize) { expBufDataBlkSizeG = dataBlkSize; } /* InitBuffers */ /* * Allocates and returns an uninitialized ExpBuf with * no a data attached. */ ExpBuf* ExpBufAllocBuf() { return ((ExpBuf*)malloc(sizeof(ExpBuf))); } void ExpBufFreeBuf PARAMS( (ptr), ExpBuf* ptr) { free(ptr); } char* ExpBufAllocData() { return((char*)malloc(expBufDataBlkSizeG)); } void ExpBufFreeData PARAMS( (ptr), char* ptr) { free( ptr); } ExpBuf* ExpBufNext PARAMS( (b), ExpBuf* b) { return(b->next); } ExpBuf* ExpBufPrev PARAMS( (b), ExpBuf* b) { return(b->prev); } /* * set curr ptr used in reads to the first byte * to be read */ void ExpBufResetInReadMode PARAMS((b), ExpBuf* b) { b->curr = b->dataStart; b->readError = 0; b->writeError = 1; /* catch wrong mode errors */ } /* * sets dataStart to end of buffer * so following writes (backward) * over-write any existing data associated with * the buffer */ void ExpBufResetInWriteRvsMode PARAMS((b), ExpBuf* b) { b->dataEnd = b->dataStart = b->blkEnd; b->writeError = 0; b->readError = 1; /* catch wrong mode errors */ } /* * returns true if no more data can be read from * the given buffer. only valid when buffer in read (fwd) * mode. */ int ExpBufAtEod PARAMS((b), ExpBuf* b) { return(b->curr == b->dataEnd); } /* * returns true if no more reverse writes can be done * to the buffer. Only valid when buffers in reverse * write mode */ int ExpBufFull PARAMS((b), ExpBuf* b) { return((b)->dataStart == (b)->blkStart); } /* * returns true if the given buffer has no * valid data in it's data block */ int ExpBufHasNoData PARAMS((b), ExpBuf* b) { return(b->dataStart == b->dataEnd); } /* * returns the number of valid data bytes in the * given buffer's data block */ unsigned long ExpBufDataSize PARAMS((b), ExpBuf* b) { return(b->dataEnd - b->dataStart); } /* * returns size of data block that is attached to * the given buffer. */ unsigned long ExpBufDataBlkSize PARAMS((b), ExpBuf* b) { return(b->blkEnd - b->blkStart); } /* * returns a ptr the beginning of the valid data of * the given buffer. * returns NULL is there is no valid data. */ char* ExpBufDataPtr PARAMS((b), ExpBuf* b) { if (ExpBufHasNoData(b)) return(NULL); else return(b->dataStart); } #endif /* DEBUG */ /* * returns last ExpBuf in a list of bufs. * The given buf can be any buf in the list. */ ExpBuf* ExpBufListLastBuf PARAMS((b), ExpBuf* b) { for (; b->next != NULL; b = b->next); return(b); } /* * returns first buf in a list of bufs . * The given buf can be any buf in the list */ ExpBuf* ExpBufListFirstBuf PARAMS((b), ExpBuf* b) { for (; b->prev != NULL; b = b->prev); return(b); } /* * Allocates a Buf and allocates an attaches a * data block of expBufDataBlkSizeG to that buffer. * sets up the blk for writing in that the data start * and data end point to the byte after the data blk. */ ExpBuf* ExpBufAllocBufAndData() { ExpBuf* retVal; retVal = ExpBufAllocBuf(); if (retVal == NULL) return(NULL); retVal->readError = 0; retVal->writeError = 0; retVal->blkStart = ExpBufAllocData(); if (retVal->blkStart == NULL) { ExpBufFreeBuf(retVal); return(NULL); } retVal->next = NULL; retVal->prev = NULL; retVal->curr = retVal->blkEnd = retVal->dataStart = retVal->dataEnd = retVal->blkStart + expBufDataBlkSizeG; return(retVal); } /* ExpBufAllocBufAndData */ /* * Frees ExpBuf's and associated data blocks after * after (next ptr) and including the given buffer, b. */ void ExpBufFreeBufAndDataList PARAMS( (b), ExpBuf* b) { ExpBuf* tmp; for(; b != NULL;) { tmp = b->next; ExpBufFreeBufAndData(b); b = tmp; } } /* ExpBufFreeBufAndDataList */ /* * puts the given data in a buffer and sets it up for reading * the data. This results in a "full" buffer with a data * blk size of given data's len */ void ExpBufInstallDataInBuf PARAMS( ( buf, data, len), ExpBuf* buf _AND_ char* data _AND_ unsigned long int len) { buf->readError = 0; buf->writeError = 0; buf->blkStart = buf->dataStart = buf->curr = data; buf->next = NULL; buf->prev = NULL; buf->blkEnd = buf->dataEnd = data + len; } /* ExpBufInstallDataInBuf */ /* Buf reading and writing routines follow */ /* READ * returns the next byte to be read without * advancing the pointer. No check for end of * data - this is lame */ unsigned char ExpBufPeekByte PARAMS( (b), ExpBuf** b) { if ((*b)->curr == (*b)->dataEnd) (*b)->readError = 1; return(*(*b)->curr); } /* ExpBufPeek */ /* READ * copy the next len chars in the buffer to the given * dst char string. The curr ptr in the buffer is advanced * appropriately */ int ExpBufCopy PARAMS( (dst, b, len), char* dst _AND_ ExpBuf** b _AND_ unsigned long int len) { unsigned long int gotLen; int totalGotLen = 0; char* srcPtr; gotLen = len; while (1) /* optimize std path - eg only one ExpBufGetSeg needed */ { srcPtr = ExpBufGetSeg(b, &gotLen); memcpy(dst + totalGotLen, srcPtr, gotLen); totalGotLen += gotLen; if (totalGotLen >= len) return(totalGotLen); if (gotLen == 0) /* eod */ { (*b)->readError = 1; return(totalGotLen); } gotLen = len - totalGotLen; } /* not reached */ } /* ExpBufCopy */ /* * advance the curr ptr in the given buffer over the next * len bytes */ void ExpBufSkip PARAMS( (b, len), ExpBuf** b _AND_ unsigned long int len) { unsigned long int lenRemaining; lenRemaining = len; while ((len > 0) && ExpBufGetSeg(b, &lenRemaining)) { len -= lenRemaining; if (lenRemaining == 0) { (*b)->readError = 1; return; } lenRemaining = len; } } /* ExpBufSkip */ /* READ * returns a ptr to the next "len" bytes (contiguous). * if "len" is greater than the available contiguous bytes * len is set the the number of contig. bytes the returned * ptr references. Subsequent call to ExpBufGetSeg or other ExpBufGet * routines will return ptrs to the following bytes (ie curr is advanced). * Changes *b to pt to the next buffer and sets curr for the * that buffer to dataStart if the current one has been totally read. * * if the value returned in the len param is zero or the * returned char* is NULL then at end of data (eod) * */ char* ExpBufGetSeg PARAMS( (b, len), ExpBuf** b _AND_ unsigned long int* len) { int bytesLeft; char* retVal; if (ExpBufAtEod(*b)) { *len = 0; return(NULL); } bytesLeft = (*b)->dataEnd - (*b)->curr; retVal = (*b)->curr; /* check for "buffer fault" */ if ( bytesLeft <= *len) { *len = bytesLeft; if ((*b)->next != NULL) { *b = (*b)->next; /* get next buffer with valid data */ while ( ((*b)->next != NULL) && ExpBufHasNoData(*b) ) *b = (*b)->next; /* reset current pointer to beggining of data if nec */ (*b)->curr = (*b)->dataStart; } else (*b)->curr += *len; } else (*b)->curr += *len; return(retVal); } /* ExpBufGetSeg */ /* * WRITE * Copies len bytes from the data pointer into the given buffer * * FILLS EXP_BUFFERS BACKWARDS! from the end of the data to the beginning * LINKS BUFFERS BACKWARDS! if a buf is full it allocs another an * puts it at the HEAD of the buffer list * * changes *b to pt to the new "prev" buffer if the current one * has been totally filled * Rvs is for REVERSE! * * modifies the dataStart pointer to reflect the new data */ void ExpBufPutSegRvs PARAMS( (b, data, len), ExpBuf** b _AND_ char* data _AND_ unsigned long int len) { int bytesLeft; ExpBuf* buf; char* dataPtr; buf = *b; if (buf->writeError) return; bytesLeft = buf->dataStart - buf->blkStart; dataPtr = data + len; /* pts to end of data to be written */ /* optimize fast path */ do { if (bytesLeft > len) /* enough room in this buffer for write */ { buf->dataStart -= len; memcpy(buf->dataStart, data, len); break; /* this is the normal exit from this loop */ } else { /* * going to fill this buffer completely, * so alloc other one (only if one is not * already linked in) */ dataPtr = dataPtr - bytesLeft; buf->dataStart = buf->blkStart; memcpy(buf->dataStart, dataPtr, bytesLeft); len -= bytesLeft; if (buf->prev == NULL) { /* alloc & insert new buf at head of buffer list */ buf = ExpBufAllocBufAndData(); if (buf == NULL) { (*b)->writeError = 1; return; } buf->next = *b; (*b)->prev = buf; } else buf = buf->prev; *b = buf; /* update head of list */ bytesLeft = buf->dataStart - buf->blkStart; } } while (1); /* not reached */ } /* ExpBufPutSegRvs */ /* * returns the next byte and advances the curr ptr by one. * sets the readError flag if there is no byte to read * (ie at end of data) */ unsigned char ExpBufGetByte PARAMS( (b), ExpBuf** b) { unsigned char retVal; if (ExpBufAtEod(*b)) { (*b)->readError = 1; return((unsigned char)0); } retVal = *(*b)->curr++; /* "buffer fault" - if end of this buf, go on to next, if any */ if ( ExpBufAtEod(*b) && ((*b)->next != NULL)) { *b = (*b)->next; /* get next buffer with valid data */ while ( ((*b)->next != NULL) && ExpBufHasNoData(*b) ) *b = (*b)->next; /* reset current pointer to beggining of data if nec */ (*b)->curr = (*b)->dataStart; } return(retVal); } /* ExpBufGetByte */ /* WRITE * Puts a single octet into the buffer * writes in reverse. * allocates new buffers as nec - may change * (*b) to new buffer since writing backwards */ void ExpBufPutByteRvs PARAMS( (b, byte), ExpBuf** b _AND_ unsigned char byte) { ExpBuf* new; if ((*b)->writeError) return; *(--(*b)->dataStart) = byte; /* * check if buffer is full and alloc new one if nec * and insert it before this one since writing backwards */ if (ExpBufFull(*b)) { if ((*b)->prev == NULL) { /* * no prev buf so alloc & insert * new buf as head of buffer list */ new = ExpBufAllocBufAndData(); if (new == NULL) { (*b)->writeError = 1; return; } new->next = *b; (*b)->prev = new; *b = new; } else { (*b) = (*b)->prev; ExpBufResetInWriteRvsMode(*b); } } } /* ExpBufPutByteRvs */ --- NEW FILE: exp_buf.h --- /* * exp_buf.h - read/write/alloc/free routines for a simple buffer structure * * MACROS are gross but execution speed is important * * NOTE: replacing the malloc and free with a allocs/frees * from/to buffer pools or similar tuned/fixed size * mem mgmt will improve performance. * * You should tune the buffer management to your environment * for best results * * MS 91 * Copyright (C) 1992 Michael Sample and the University of British Columbia * * This library is free software; you can redistribute it and/or * modify it provided that this copyright/license information is retained * in original form. * * If you modify this file, you must clearly indicate your changes. * * This source code is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef _exp_buf_h_ #define _exp_buf_h_ typedef struct ExpBuf { char* dataStart; /* points to first valid data byte */ /* when empty, 1 byte past blk end (rvs write)*/ char* dataEnd; /* pts to first byte AFTER last valid data byte*/ char* curr; /* current location to read form */ /* points to next byte to read */ struct ExpBuf* next; /* next buf (NULL if no next buffer)*/ struct ExpBuf* prev; /* prev buf (NULL if no prev buffer)*/ char* blkStart; /* points to first byte of the blk */ char* blkEnd; /* points the first byte AFTER blks last byte */ int readError; /* non-zero is attempt to read past end of data*/ int writeError;/* non-zero is attempt write fails (no mor bufs)*/ } ExpBuf; /* init, alloc and free routines */ #ifdef DEBUG /* use fcns when debugging/macros later */ void ExpBufInit PROTO((unsigned long dataBlkSize)); ExpBuf* ExpBufAllocBuf(); void ExpBufFreeBuf PROTO((ExpBuf* ptr)); char* ExpBufAllocData(); void ExpBufFreeData PROTO((char* ptr)); void ExpBufFreeBufAndData PROTO(( ExpBuf* b)); ExpBuf* ExpBufNext PROTO((ExpBuf* b)); ExpBuf* ExpBufPrev PROTO((ExpBuf* b)); void ExpBufResetInReadMode PROTO((ExpBuf* b)); void ExpBufResetInWriteRvsMode PROTO((ExpBuf* b)); int ExpBufAtEod PROTO((ExpBuf* b)); int ExpBufFull PROTO((ExpBuf* b)); int ExpBufHasNoData PROTO((ExpBuf* b)); unsigned long ExpBufDataSize PROTO((ExpBuf* b)); unsigned long ExpBufDataBlkSize PROTO((ExpBuf* b)); char* ExpBufDataPtr PROTO((ExpBuf* b)); #else extern unsigned long expBufDataBlkSizeG; #define ExpBufInit(size) expBufDataBlkSizeG = size; #define ExpBufAllocBuf() ((ExpBuf*)malloc(sizeof(ExpBuf))) #define ExpBufFreeBuf(ptr) free(ptr) #define ExpBufAllocData() ((void*)malloc(expBufDataBlkSizeG)) #define ExpBufFreeData( ptr) free(ptr) #define ExpBufFreeBufAndData(b) { ExpBufFreeData((b)->blkStart);\ ExpBufFreeBuf(b);} #define ExpBufNext(b) ((b)->next) #define ExpBufPrev(b) ((b)->prev) #define ExpBufResetInReadMode(b) {(b)->curr = (b)->dataStart; (b)->readError = 0; (b)->writeError = 1;} #define ExpBufResetInWriteRvsMode(b) {(b)->dataStart = (b)->dataEnd = (b)->blkEnd; (b)->writeError = 0; (b)->readError = 1;} /* ExpBufAtEod only valid during reads (fwd) */ #define ExpBufAtEod(b) ((b)->curr == (b)->dataEnd) /* ExpBufFull only valid during write (reverse) */ #define ExpBufFull(b) ((b)->dataStart == (b)->blkStart) #define ExpBufHasNoData(b) ((b)->dataStart == (b)->dataEnd) #define ExpBufDataSize(b) ((b)->dataEnd - (b)->dataStart) #define ExpBufDataBlkSize(b) ((b)->blkEnd - (b)->blkStart) #define ExpBufDataPtr(b) (ExpBufHasNoData(b)? NULL: (b)->dataStart) #endif /* DEBUG */ #define ExpBufReadError(b) ((*b)->readError) #define ExpBufWriteError(b) ((*b)->writeError) ExpBuf* ExpBufAllocBufAndData(); void ExpBufInstallDataInBuf PROTO((ExpBuf* b, char* data, unsigned long int len)); void ExpBufFreeBufAndDataList PROTO(( ExpBuf* b)); ExpBuf* ExpBufListLastBuf PROTO((ExpBuf* b)); ExpBuf* ExpBufListFirstBuf PROTO((ExpBuf* b)); /* reading and writing routines */ void ExpBufSkip PROTO(( ExpBuf**, unsigned long len)); int ExpBufCopy PROTO(( char* dst, ExpBuf** b, unsigned long len)); unsigned char ExpBufPeekByte PROTO(( ExpBuf** b)); char* ExpBufGetSeg PROTO((ExpBuf** b, unsigned long* len)); void ExpBufPutSegRvs PROTO((ExpBuf** b, char* data, unsigned long len)); unsigned char ExpBufGetByte PROTO((ExpBuf** b)); void ExpBufPutByteRvs PROTO((ExpBuf** b, unsigned char byte)); #endif /* conditional include */ --- NEW FILE: README --- snacc ASN.1 Compiler Release 1.1 - (updated Jul 93) ----------------------------------------------------- This package provides the C/yacc/lex source code for snacc, an ASN.1 to C or C++ compiler. Snacc is short for "Sample Neufeld Asn.1 to C Compiler" and ASN.1 stands for Abstract Syntax Notation One (CCITT X.208/ ISO 8824). See the COPYRIGHT file for copyright information. What It Does ------------ Given an ASN.1 source file(s) snacc can produce: 1. C routines for BER encoding, decoding, printing and freeing. 2. C++ routines for BER encoding, decoding, and printing. 3. A type table that can be used with C driver routines for BER encoding, decoding, printing and freeing. 4. if you are really lucky, a core dump! :) Snacc produces reasonably efficient C or C++ routines and data structures to support BER encoding and decoding values of the given ASN.1 data structures. Printing routines for the decoded values are also generated. For C only, hierarchical freeing routines are generated (but are not recommended for efficiency reasons). When using the C or C++ (not table) options, snacc creates the following C files for each ASN.1 source file (module): 1. .h file for the C/C++ translation of the ASN.1 data structure and prototypes for the generated routines. 2. .c/.C file for the C/C++ encode, decode, print and free routines. When using the table option, snacc produces a type table file (a BER encoding) that can later be loaded at runtime by the table driven encoding and decoding routines. See the latex or PostScript version of the documentation in the snacc/doc directory for indepth information on this tool. For a quick introduction, look at the examples in snacc/c_examples, snacc/c++_examples and snacc/tbl_example. Features of ASN.1 Supported --------------------------- - parses ASN.1 '90 (subtype notation etc.) - macro definitions do not generate syntax errors but are are not processed. (retained as string) - value notation is parsed and for OBJECT IDENTIFIERs, INTEGERs and BOOLEANS (any other value in { }'s is currently kept as a string) - handles multiple ASN.1 module compiling/linking (IMPORTS/EXPORTS) - some X.400 and SNMP macros are parsed - supports ";" separted type or value definitions in the ASN.1 source. This is useful when dealing with some macros that introduce parsing problems. Does not require the ";"'s though. - ANY DEFINED BY types are handled using the SNMP OBJECT-TYPE macro to define the identifier to type mapping. Bugs are still quite likely even though this is the second release of snacc. if you find any or have other comments please email: sna...@cs... To Install It ------------- By default, the snacc makefile uses GNU bison and GNU flex (instead of yacc and lex). If you do not have these installed, see the snacc/src/README and snacc/src/makefile. Otherwise, type "make" in this directory. Hopefully this will put the snacc binary in the snacc/bin directory and build the C runtime library, the table library and the table tools. Alternatively, type "make all" to install these and the C++ library. Compiling problems may occurr on different flavours of UNIX but they should not be too difficult fix. Likely sources of problems include non-standard include files and lex, yacc and cc idiosyncrasies. If your yacc croaks with a message about too many productions use bison. Same thing with lex -> use flex. Bison and flex are both freely available from numerous ftp sites. (even cs.ubc.ca in /mirror2/gnu) The snacc compiler and the generated code will compile under ANSI and non-ANSI C compilers. See the README and the makefile in the snacc/src directory for more compiling information. Snacc has been successfully installed on Sun SPARCs, HP700s, IBM RS 6000s, MIPS, i486/Linux, and many other machines. --- NEW FILE: asn_bits.c --- /* * asn_bits.c - BER encode, decode, print and free routines for ASN.1 * BIT STRING type * * MS 92 * Copyright (C) 1992 Michael Sample and the University of British Columbia * * This library is free software; you can redistribute it and/or * modify it provided that this copyright/license information is retained * in original form. * * If you modify this file, you must clearly indicate your changes. * * This source code is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * */ #if HAVE_CONFIG_H #include <config.h> #endif #include "asn_config.h" #include "asn_len.h" #include "asn_tag.h" #include "str_stk.h" #include "asn_bits.h" static unsigned short int unusedBitsG; char numToHexCharTblG[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd' ,'e', 'f'}; /* * encodes universal TAG LENGTH and Contents of and ASN.1 BIT STRING */ AsnLen BEncAsnBits PARAMS((b, data), BUF_TYPE b _AND_ AsnBits* data) { AsnLen len; len = BEncAsnBitsContent(b, data); len += BEncDefLen(b, len); len += BEncTag1(b, UNIV, PRIM, BITSTRING_TAG_CODE); return(len); } /* BEncAsnInt */ /* * decodes universal TAG LENGTH and Contents of and ASN.1 BIT STRING */ void BDecAsnBits PARAMS((b, result, bytesDecoded, env), BUF_TYPE b _AND_ AsnBits* result _AND_ AsnLen* bytesDecoded _AND_ jmp_buf env) { AsnTag tag; AsnLen elmtLen; if (((tag =BDecTag(b, bytesDecoded, env)) != MAKE_TAG_ID(UNIV, PRIM, BITSTRING_TAG_CODE)) && (tag != MAKE_TAG_ID(UNIV, CONS, BITSTRING_TAG_CODE))) { Asn1Error("BDecAsnBits: ERROR - wrong tag on BIT STRING.\n"); longjmp(env, -40); } elmtLen = BDecLen (b, bytesDecoded, env); BDecAsnBitsContent( b, tag, elmtLen, result, bytesDecoded, env); } /* BDecAsnBits */ /* * Encodes the BIT STRING value (including the unused bits * byte) to the given buffer. */ AsnLen BEncAsnBitsContent PARAMS((b, bits), BUF_TYPE b _AND_ AsnBits* bits) { unsigned long int unusedBits; unsigned long int byteLen; if (bits->bitLen == 0) byteLen = 0; else byteLen = ((bits->bitLen-1) / 8) + 1; BufPutSegRvs(b, bits->bits, byteLen); unusedBits = (bits->bitLen % 8); if (unusedBits != 0) unusedBits = 8 - unusedBits; BufPutByteRvs(b, unusedBits); return(byteLen + 1); } /* BEncAsnBitsContent */ /* * Used when decoding to combine constructed pieces into one * contiguous block. * Fills string stack with references to the pieces of a * construced bit string. sets unusedBitsG appropriately. * and strStkG.totalByteLenG to bytelen needed to hold the bitstring */ static void FillBitStringStk PARAMS((b, elmtLen0, bytesDecoded, env), BUF_TYPE b _AND_ AsnLen elmtLen0 _AND_ AsnLen* bytesDecoded _AND_ jmp_buf env) { unsigned long int refdLen; unsigned long int totalRefdLen; char* strPtr; unsigned long int totalElmtsLen1 = 0; unsigned long int tagId1; unsigned long int elmtLen1; unsigned long int lenToRef; unsigned long int unusedBits; for ( ; (totalElmtsLen1 < elmtLen0) || (elmtLen0 == INDEFINITE_LEN);) { tagId1 = BDecTag(b, &totalElmtsLen1, env); if ( (tagId1 == EOC_TAG_ID) && (elmtLen0 == INDEFINITE_LEN)) { BDEC_2ND_EOC_OCTET(b, &totalElmtsLen1, env); break; } elmtLen1 = BDecLen (b, &totalElmtsLen1, env); if ( tagId1 == MAKE_TAG_ID( UNIV, PRIM, BITSTRING_TAG_CODE)) { /* * primitive part of string, put references to piece(s) in * str stack */ /* * get unused bits octet */ if (unusedBitsG != 0) { /* * whoa - only allowed non-octet aligned bits on * on last piece of bits string */ Asn1Error("FillBitStringStk: ERROR - a component of a constructed BIT STRING that is not the last has non-zero unused bits\n"); longjmp(env, -1); } if (elmtLen1 != 0) unusedBitsG = BufGetByte(b); totalRefdLen = 0; lenToRef =elmtLen1-1; /* remove one octet for the unused bits oct*/ refdLen = lenToRef; while (1) { strPtr = BufGetSeg( b, &refdLen); PUSH_STR(strPtr, refdLen, env); totalRefdLen += refdLen; if (totalRefdLen == lenToRef) break; /* exit this while loop */ if (refdLen == 0) /* end of data */ { Asn1Error("FillBitStringStk: ERROR - expecting more data\n"); longjmp(env, -2); } refdLen = lenToRef - totalRefdLen; } totalElmtsLen1 += elmtLen1; } else if ( tagId1 == MAKE_TAG_ID( UNIV, CONS, BITSTRING_TAG_CODE)) { /* * constructed octets string embedding in this constructed * octet string. decode it. */ FillBitStringStk( b, elmtLen1, &totalElmtsLen1, env); } else /* wrong tag */ { Asn1Error("FillBitStringStk: ERROR - decoded non-BIT STRING tag inside a constructed BIT STRING\n"); longjmp(env, -3); } } /* end of for */ (*bytesDecoded) += totalElmtsLen1; } /* FillBitStringStk */ /* * Decodes a seq of universally tagged bits until either EOC is * encountered or the given len decoded. Returns them in a * single concatenated bit string */ static void BDecConsAsnBits PARAMS((b, len, result, bytesDecoded, env), BUF_TYPE b _AND_ AsnLen len _AND_ AsnBits* result _AND_ AsnLen* bytesDecoded _AND_ jmp_buf env) { char* bufCurr; unsigned long int curr; RESET_STR_STK(); /* * decode each piece of the octet string, puting * an entry in the octet/bit string stack for each */ FillBitStringStk(b, len, bytesDecoded, env); /* alloc single str long enough for combined bitstring */ result->bitLen = strStkG.totalByteLen*8 - unusedBitsG; bufCurr = result->bits = Asn1Alloc(strStkG.totalByteLen); /* copy bit string pieces (buffer refs) into single block */ for (curr = 0; curr < strStkG.nextFreeElmt; curr++) { memcpy(bufCurr, strStkG.stk[curr].str, strStkG.stk[curr].len); bufCurr += strStkG.stk[curr].len; } } /* BDecConsAsnBits */ /* * Decodes the content of a BIT STRING (including the unused bits octet) * Always returns a single contiguous bit string */ void BDecAsnBitsContent PARAMS((b, tagId, len, result, bytesDecoded, env), BUF_TYPE b _AND_ AsnTag tagId _AND_ AsnLen len _AND_ AsnBits* result _AND_ AsnLen* bytesDecoded _AND_ jmp_buf env) { char* tmp; /* * tagId is encoded tag shifted into long int. * if CONS bit is set then constructed bit string */ if (TAG_IS_CONS(tagId)) BDecConsAsnBits(b, len, result, bytesDecoded, env); else /* primitive octet string */ { (*bytesDecoded) += len; len--; result->bitLen = (len * 8) - (unsigned int)BufGetByte(b); result->bits = Asn1Alloc(len); BufCopy( result->bits, b, len); if (BufReadError(b)) { Asn1Error("BDecAsnBitsContent: ERROR - decoded past end of data\n"); longjmp(env, -4); } } } /* BDecAsnBitsContent */ /* * Frees the string part of a BIT STRING */ void FreeAsnBits PARAMS((v), AsnBits* v) { Asn1Free(v->bits); } /* FreeAsnBits */ /* * Prints the contents of the given BIT STRING to the * given file. indent is ignored. Always uses ASN.1 Value Notaion * Hex format. (Should be binary versions in some cases) */ void PrintAsnBits PARAMS((f,v, indent), FILE* f _AND_ AsnBits* v _AND_ unsigned short indent) { int i; unsigned long int octetLen; if (v->bitLen == 0) octetLen = 0; else octetLen = (v->bitLen-1)/8 +1; fprintf(f,"'"); for(i = 0; i < octetLen; i++) fprintf(f,"%c%c", TO_HEX(v->bits[i] >> 4), TO_HEX(v->bits[i])); fprintf(f,"'H"); } /* PrintAsnBits */ /* * Returns TRUE if the given BIT STRINGs are identical. * Otherwise returns FALSE. */ int AsnBitsEquiv PARAMS((b1, b2), AsnBits* b1 _AND_ AsnBits* b2) { int octetsLessOne; int octetBits; if ((b1->bitLen == 0) && (b2->bitLen == 0)) return(TRUE); octetsLessOne = (b1->bitLen-1)/8; octetBits = 7 - (b1->bitLen % 8); /* trailing bits may not be significant */ return ( (b1->bitLen == b2->bitLen) && (memcmp(b1->bits, b2->bits, octetsLessOne) == 0) && (( b1->bits[octetsLessOne] & (0xFF << octetBits)) == ( b1->bits[octetsLessOne] & (0xFF << octetBits)))); } /* AsnBitsEquiv */ /* * Set given bit to 1. Most significant bit is bit 0, least significant * is bit (v1->bitLen -1) */ void SetAsnBit PARAMS((b1, bit), AsnBits* b1 _AND_ unsigned long int bit) { unsigned long int octet; unsigned long int octetsBit; if (bit < b1->bitLen) { octet = bit/8; octetsBit = 7 - (bit % 8);/* bit zero is first/most sig bit in octet */ b1->bits[octet] |= 1 << octetsBit; } } /* SetAsnBit */ /* * Set given bit to 0. Most significant bit is bit 0, least significant * is bit (v1->bitLen -1) */ void ClrAsnBit PARAMS((b1, bit), AsnBits* b1 _AND_ unsigned long int bit) { unsigned long int octet; unsigned long int octetsBit; if (bit < b1->bitLen) { octet = bit/8; octetsBit = 7 - (bit % 8);/* bit zero is first/most sig bit in octet */ b1->bits[octet] &= ~(1 << octetsBit); } } /* ClrAsnBit */ /* * Get given bit. Most significant bit is bit 0, least significant * is bit (v1->bitLen -1). Returns TRUE if the bit is 1. Returns FALSE * if the bit is 0. if the bit is out of range then returns 0. */ int GetAsnBit PARAMS((b1, bit), AsnBits* b1 _AND_ unsigned long int bit) { unsigned long int octet; unsigned long int octetsBit; if (bit < b1->bitLen) { octet = bit/8; octetsBit = 7 - (bit % 8); /* bit zero is first/most sig bit in octet*/ return (b1->bits[octet] & (1 << octetsBit)); } return(0); } /* AsnBits::GetBit */ --- NEW FILE: asn_bits.h --- /* * asn_bits.h * * MS 92 * Copyright (C) 1992 Michael Sample and the University of British Columbia * * This library is free software; you can redistribute it and/or * modify it provided that this copyright/license information is retained * in original form. * * If you modify this file, you must clearly indicate your changes. * * This source code is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * */ #ifndef _asn_bits_h_ #define _asn_bits_h_ typedef struct AsnBits { int bitLen; char* bits; } AsnBits; extern char numToHexCharTblG[]; #define TO_HEX(fourBits) (numToHexCharTblG[(fourBits) & 0x0f]) #define ASNBITS_PRESENT(abits) ((abits)->bits != NULL) AsnLen BEncAsnBits PROTO((BUF_TYPE b, AsnBits* data)); void BDecAsnBits PROTO((BUF_TYPE b, AsnBits* result, AsnLen* bytesDecoded, ENV_TYPE env)); AsnLen BEncAsnBitsContent PROTO((BUF_TYPE b, AsnBits* bits)); void BDecAsnBitsContent PROTO((BUF_TYPE b, AsnLen len, AsnTag tagId, AsnBits* result, AsnLen* bytesDecoded, ENV_TYPE env)); void FreeAsnBits PROTO((AsnBits* v)); void PrintAsnBits PROTO((FILE* f, AsnBits* b, unsigned short int indent)); int AsnBitsEquiv PROTO((AsnBits* b1, AsnBits* b2)); void SetAsnBit PROTO((AsnBits* b1, unsigned long int bit)); void ClrAsnBit PROTO((AsnBits* b1, unsigned long int bit)); int GetAsnBit PROTO((AsnBits* b1, unsigned long int bit)); #endif /* conditional include */ --- NEW FILE: min_buf.h --- /* * min_buf.h - trivial buffer routines. * only use these for * encoding - if you know you 'buffer' is big enough * to hold the encoded value * * decoding - if you know that the encoding is error * free. * * * The minimal buffer is simply a block of mem referenced * by a char** (ie BUF_TYPE char**). These are very efficient * but should only be used when it is safe (see above) or you're * willing to risk reading past the end of the buffer or writing * 'past' the beginning (segmentation faults/bus errors etc). * * No checks for reading or writing past the buffer are done. * every operation is assumed to succeed. * MS 92 * * Copyright (C) 1992 Michael Sample and the University of British Columbia * * This library is free software; you can redistribute it and/or * modify it provided that this copyright/license information is retained * in original form. * * If you modify this file, you must clearly indicate your changes. * * This source code is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef _min_buf_h_ #define _min_buf_h_ #define MinBufGetByte(b)\ (unsigned char)(*((*(b))++)) #define MinBufGetSeg( b, lenPtr)\ *(b);\ (*b) += *lenPtr; #define MinBufCopy( dst, b, len)\ memcpy((dst), *(b), (len));\ (*(b)) += (len); #define MinBufSkip( b, len) ((*(b)) += len) #define MinBufPeekByte( b) (**(b)) #define MinBufPutByteRvs( b, byte)\ (*(--(*(b))) = (byte)) #define MinBufPutSegRvs( b, data, len)\ ((*(b)) = (*(b)) - (len));\ memcpy(*(b), (data), (len)); #define MinBufReadError(b) 0 /* always false */ #define MinBufWriteError(b) 0 /* always false */ #endif /* conditional include */ --- NEW FILE: asn_incl.h --- /* * asn_incl.h * includes hdr files nec for a user prg that calls the generated * encoding/decoding routines. * * Copyright (C) 1992 Michael Sample and the University of British Columbia * * This library is free software; you can redistribute it and/or * modify it provided that this copyright/license information is retained * in original form. * * If you modify this file, you must clearly indicate your changes. * * This source code is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * */ #include "asn_config.h" #include "asn_len.h" #include "asn_tag.h" #include "asn_int.h" #include "asn_octs.h" #include "asn_bits.h" #include "asn_oid.h" #include "asn_null.h" #include "asn_list.h" --- NEW FILE: asn_config.h --- /* * asn_config.h - configures the ANSI/non ansi, defines * decoder alloc routines and buffer routines * * MS 91 * Copyright (C) 1992 Michael Sample and the University of British Columbia * * This library is free software; you can redistribute it and/or * modify it provided that this copyright/license information is retained * in original form. * * If you modify this file, you must clearly indicate your changes. * * This source code is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * */ #ifndef _asn_config_h_ #define _asn_config_h_ #include <stdio.h> #include <ctype.h> /* for isprint() in asn_octs.c */ #include <setjmp.h> /* for jmp_buf type, setjmp and longjmp */ /* for pow() used in asn_real.c - must include to avoid casting err on pow */ #include <math.h> /* * define IEEE_REAL_FMT if your system/compiler uses the native ieee double * this should improve the performance of encoding reals. * If your system has the IEEE library routines (iszero, isinf etc) * then define IEEE_REAL_LIB. If neither are defined then * frexp is used. Performance is probaby best for IEEE_REAL_FMT. * * #define IEEE_REAL_FMT * #define IEEE_REAL_LIB */ /* * define __USE_ANSI_C__ if your compiler supports it */ #define __USE_ANSI_C__ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef NULL #define NULL 0 #endif /* * Inspired by gdb 4.0, for better or worse... * (grabbed from Barry Brachman - MS) * * These macros munge C routine declarations such * that they work for ANSI or non-ANSI C compilers */ #ifdef __USE_ANSI_C__ #define PROTO(X) X #define PARAMS(arglist, args) (args) #define NOPARAMS() (void) #define _AND_ , #define DOTS , ... #else #define PROTO(X) () #define PARAMS(arglist, args) arglist args; #define NOPARAMS() () #define _AND_ ; #define DOTS #define void char #endif /* used to test if optionals are present */ #define NOT_NULL(ptr) ((ptr) != NULL) /* * Asn1Error(char* str) - configure error handler */ #define Asn1Error(str) fprintf(stderr,"%s", str); /* * Asn1Warning(char* str) - configure warning mechanism * (currently never called) */ #define Asn1Warning(str) fprintf(stderr,"%s", str); /* * configure memory scheme used by decoder to allocate memory * for the decoded value. * The Asn1Free will be called in the optionally generated * hierachical free routines. * * nibble_alloc allocs from a single buffer and EVERYTHING * is freed by a single fcn call. Individual elmts cannot be freed */ #include "nibble_alloc.h" #define Asn1Alloc(size) NibbleAlloc(size) #define Asn1Free(ptr) /* empty */ #define CheckAsn1Alloc(ptr, env)\ if ((ptr) == NULL)\ longjmp(env, -27); #define ENV_TYPE jmp_buf /* * configure buffer routines that the encoders (write) * and decoders(read) use. This config technique kind * of bites but is allows efficient macro calls. The * Generated code & lib routines call/use the "Buf????" * version of the macro - you define their meaning here. */ #ifdef USE_EXP_BUF #include "exp_buf.h" #define BUF_TYPE ExpBuf** #define BufGetByte(b) ExpBufGetByte(b) #define BufGetSeg(b, lenPtr) ExpBufGetSeg(b, lenPtr) #define BufCopy(dst, b, len) ExpBufCopy( dst, b, len) #define BufSkip(b, len) ExpBufSkip(b, len) #define BufPeekByte(b) ExpBufPeekByte( b) #define BufPutByteRvs(b, byte) ExpBufPutByteRvs( b, byte) #define BufPutSegRvs(b, data, len) ExpBufPutSegRvs( b, data, len) #define BufReadError(b) ExpBufReadError(b) #define BufWriteError(b) ExpBufWriteError(b) #else /* SBUF or MIN_BUF */ #ifdef USE_MIN_BUF #include "min_buf.h" #define BUF_TYPE char** #define BufGetByte(b) MinBufGetByte(b) #define BufGetSeg(b, lenPtr) MinBufGetSeg(b, lenPtr) #define BufCopy(dst, b, len) MinBufCopy(dst, b, len) #define BufSkip(b, len) MinBufSkip(b, len) #define BufPeekByte(b) MinBufPeekByte(b) #define BufPutByteRvs(b, byte) MinBufPutByteRvs(b, byte) #define BufPutSegRvs(b, data, len) MinBufPutSegRvs(b, data, len) #define BufReadError(b) MinBufReadError(b) #define BufWriteError(b) MinBufWriteError(b) #else /* SBUF */ #include "sbuf.h" #define BUF_TYPE SBuf* #define BufGetByte(b) SBufGetByte(b) #define BufGetSeg(b, lenPtr) SBufGetSeg(b, lenPtr) #define BufCopy(dst, b, len) SBufCopy(dst, b, len) #define BufSkip(b, len) SBufSkip(b, len) #define BufPeekByte(b) SBufPeekByte(b) #define BufPutByteRvs(b, byte) SBufPutByteRvs(b, byte) #define BufPutSegRvs(b, data, len) SBufPutSegRvs(b, data, len) #define BufReadError(b) SBufReadError(b) #define BufWriteError(b) SBufWriteError(b) #endif #endif #include "print.h" /* for printing set up */ #endif /* conditional include */ --- NEW FILE: asn_list.c --- /* * asn_list.c - borrowed from Murray Goldberg * * the following routines implement the list data structure * * Copyright (C) 1992 the University of British Columbia * * This library is free software; you can redistribute it and/or * modify it provided that this copyright/license information is retained * in original form. * * If you modify this file, you must clearly indicate your changes. * * This source code is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #if HAVE_CONFIG_H #include <config.h> #endif #include "asn_config.h" #include "asn_list.h" /* * this routine removes the current node from the list. After removal the * current pointer will point to the next node in line, or NULL if the * removed item was at the tail of the list. */ void AsnListRemove PARAMS( (list), AsnList* list ) { AsnListNode* node; if( list->curr ) { if( list->curr->next ) list->curr->next->prev = list->curr->prev; else list->last = list->curr->prev; if( list->curr->prev ) list->curr->prev->next = list->curr->next; else list->first = list->curr->next; node = list->curr; list->curr = list->curr->next; list->count--; free( node ); } } /* * this creates a new node after the current node and returns the * address of the memory allocated for data. The current pointer is changed * to point to the newly added node in the list. If the current pointer is * initially off the list then this operation fails. */ void* AsnListAdd PARAMS((list), AsnList* list ) { AsnListNode* newNode; void* dataAddr; if( list->curr ) { newNode = (AsnListNode *) Asn1Alloc( sizeof(AsnListNode) + list->dataSize ); dataAddr = (void *) &(newNode->data); newNode->next = list->curr->next; newNode->prev = list->curr; if( list->curr->next ) list->curr->next->prev = newNode; else list->last = newNode; list->curr->next = newNode; list->curr = newNode; list->count++; } else dataAddr = NULL; return( dataAddr ); } /* * this creates a new node before the current node and returns the * address of the memory allocated for data. The current pointer is changed * to point to the newly added node in the list. If the current pointer is * initially off the list then this operation fails. */ void* AsnListInsert PARAMS( (list), AsnList* list ) { AsnListNode* newNode; void* dataAddr; if( list->curr ) { newNode = (AsnListNode *) Asn1Alloc( sizeof(AsnListNode) + list->dataSize ); dataAddr = (void *) &(newNode->data); newNode->next = list->curr; newNode->prev = list->curr->prev; if( list->curr->prev ) list->curr->prev->next = newNode; else list->first = newNode; list->curr->prev = newNode; list->curr = newNode; list->count++; } else dataAddr = NULL; return( dataAddr ); } void AsnListInit PARAMS((list, dataSize), AsnList* list _AND_ int dataSize) { list->first = list->last = list->curr = NULL; list->count = 0; list->dataSize = dataSize; } /* AsnListInit */ AsnList* AsnListNew PARAMS( (dataSize), int dataSize ) { AsnList* list; list = (AsnList *) Asn1Alloc( sizeof(AsnList) ); list->first = list->last = list->curr = NULL; list->count = 0; list->dataSize = dataSize; return( list ); } /* * backs up the current pointer by one and returns the data address of the new * current node. If the current pointer is off the list, the new current node * will be the last node of the list (unless the list is empty). */ void* AsnListPrev PARAMS( (list), AsnList* list ) { void* retVal; if( list->curr == NULL ) list->curr = list->last; else list->curr = list->curr->prev; if( list->curr == NULL ) retVal = NULL; else retVal = (void *) &(list->curr->data); return( retVal ); } /* * advances the current pointer by one and returns the data address of the new * current node. If the current pointer is off the list, the new current node * will be the first node of the list (unless the list is empty). */ void* AsnListNext PARAMS( (list), AsnList* list ) { void* retVal; if( list->curr == NULL ) list->curr = list->first; else list->curr = list->curr->next; if( list->curr == NULL ) retVal = NULL; else retVal = (void *) &(list->curr->data); return( retVal ); } /* * returns the data address of the last node (if there is one) and sets the * current pointer to this node. */ void* AsnListLast PARAMS((list), AsnList* list ) { void* retVal; list->curr = list->last; if( list->curr == NULL ) retVal = NULL; else retVal = (void *) &(list->curr->data); return( retVal ); } /* * returns the data address of the first node (if there is one) and sets the * current pointer to this node. */ void* AsnListFirst PARAMS( (list), AsnList* list ) { void* retVal; list->curr = list->first; if( list->curr == NULL ) retVal = NULL; else retVal = (void *) &(list->curr->data); return( retVal ); } /* * this creates a new node at the beginning of the list and returns the * address of the memory allocated for data. The current pointer is changed * to point to the newly added node in the list. */ void* AsnListPrepend PARAMS( (list), AsnList* list ) { AsnListNode* newNode; void* dataAddr; newNode = (AsnListNode *) Asn1Alloc( sizeof(AsnListNode) + list->dataSize ); dataAddr = (void *) &(newNode->data); newNode->prev = NULL; if( list->first == NULL ) { newNode->next = NULL; list->first = list->last = newNode; } else { newNode->next = list->first; list->first->prev = newNode; list->first = newNode; } list->curr = newNode; list->count++; return( dataAddr ); } /* * this creates a new node at the end of the list and returns the * address of the memory allocated for data. The current pointer is changed * to point to the newly added node in the list. */ void* AsnListAppend PARAMS( (list), AsnList* list ) { AsnListNode* newNode; void* dataAddr; newNode = (AsnListNode *) Asn1Alloc( sizeof(AsnListNode) + list->dataSize ); dataAddr = (void *) &(newNode->data); newNode->next = NULL; if( list->last == NULL ) { newNode->prev = NULL; list->first = list->last = newNode; } else { newNode->prev = list->last; list->last->next = newNode; list->last = newNode; } list->curr = newNode; list->count++; return( dataAddr ); } void* AsnListCurr PARAMS( (list), AsnList* list ) { void* retVal; if( list->curr ) retVal = (void *) &(list->curr->data); else retVal = NULL; return( retVal ); } int AsnListCount PARAMS( (list), AsnList* list ) { return( list->count ); } --- NEW FILE: asn_list.h --- /* * asn_list.h * * --------- * | AsnList | * | last |-------------------------------------------| * | curr |--------------------------| | * | first|--------| | | * --------- | | | * V V V * --------- --------- --------- * |AsnListNode |AsnListNode |AsnListNode * | next |---...->| next |--...-->| next |-----|i. * .i|----| prev |<--...--| prev |<--...--| prev | * | data | | data | | data | * --------- --------- --------- * * Originally by Murray Goldberg * Modified for ASN.1 use. * MS 92 * Copyright (C) 1992 the University of British Columbia * * This library is free software; you can redistribute it and/or * modify it provided that this copyright/license information is retained * in original form. * * If you modify this file, you must clearly indicate your changes. * * This source code is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef _asn_list_h_ #define _asn_list_h_ typedef struct AsnListNode { struct AsnListNode *prev; struct AsnListNode *next; void *data; /* this must be the last field of this structure */ } AsnListNode; typedef struct AsnList { AsnListNode *first; AsnListNode *last; AsnListNode *curr; int count; /* number of elements in list */ int dataSize; /* space required in each node for the data */ } AsnList; #define FOR_EACH_LIST_ELMT( elmt, al)\ if ((al) != NULL)\ for ((al)->curr = (al)->first;\ ((al)->curr != NULL) && (((elmt) =(void*)(al)->curr->data) != NULL);\ (al)->curr = (al)->curr->next ) #define FOR_EACH_LIST_ELMT_RVS( elmt, al)\ if ((al) != NULL)\ for ((al)->curr = (al)->last;\ (((al)->curr != NULL)) && (((elmt) =(void*)(al)->curr->data) != NULL);\ (al)->curr = (al)->curr->prev ) #define FOR_REST_LIST_ELMT( elmt, al)\ if ((al) != NULL)\ for (; (((al)->curr != NULL)) && (((elmt) =(void*)(al)->curr->data) != NULL);\ (al)->curr = (al)->curr->next ) /* * The following macros return the pointer stored in the * data part of the listNode. The do not change the current * list pointer. */ #define CURR_LIST_ELMT(al) ((al)->curr->data) #define NEXT_LIST_ELMT(al) ((al)->curr->next->data) #define PREV_LIST_ELMT(al) ((al)->curr->prev->data) #define LAST_LIST_ELMT(al) ((al)->last->data) #define FIRST_LIST_ELMT(al) ((al)->first->data) #define LIST_EMPTY(al) ((al)->count == 0) #define LIST_COUNT(al) ((al)->count) /* * list nodes are the parts of the list that contain ptrs/data * to/of the list elmts. */ #define CURR_LIST_NODE(al) ((al)->curr) #define FIRST_LIST_NODE(al) ((al)->first) #define LAST_LIST_NODE(al) ((al)->last) #define PREV_LIST_NODE(al) ((al)->curr->prev) #define NEXT_LIST_NODE(al) ((al)->curr->next) #define SET_CURR_LIST_NODE(al, listNode) ((al)->curr = (listNode)) void AsnListRemove PROTO(( AsnList * )); void *AsnListAdd PROTO(( AsnList * )); void *AsnListInsert PROTO(( AsnList * )); void AsnListInit PROTO((AsnList* list, int dataSize)); AsnList *AsnListNew PROTO(( int )); void *AsnListPrev PROTO(( AsnList * )); void *AsnListNext PROTO(( AsnList * )); void *AsnListLast PROTO(( AsnList * )); void *AsnListFirst PROTO(( AsnList * )); void *AsnListPrepend PROTO(( AsnList * )); void *AsnListAppend PROTO(( AsnList * )); void *AsnListCurr PROTO(( AsnList * )); int AsnListCount PROTO(( AsnList * )); AsnList* AsnListConcat PROTO((AsnList*, AsnList*)); #endif /* conditional include */ --- NEW FILE: asn_octs.c --- /* * asn_octs.c - BER encode, decode, print and free routines for the * ASN.1 OCTET STRING type. * * MS 92 * Copyright (C) 1992 Michael Sample and the University of British Columbia * * This library is free software; you can redistribute it and/or * modify it provided that this copyright/license information is retained * in original form. * * If you modify this file, you must clearly indicate your changes. * * This source code is distributed in the hope that it will be * usefu... [truncated message content] |