Annotation of 43BSDReno/contrib/isode-beta/doc/manual/psap.tex, revision 1.1

1.1     ! root        1: % run this through LaTeX with the appropriate wrapper
        !             2: 
        !             3: %%% TODO: document
        !             4: %%%    pe2ssdu, ssdu2pe, pe2text, pe2uvec
        !             5: 
        !             6: \chapter      {Encoding of Data-Structures}\label{libpsap}
        !             7: The \man libpsap(3) library implements presentation syntax abstractions
        !             8: for the machine-independent exchange of data structures.
        !             9: There are two objects which are manipulated:
        !            10: {\em presentation elements},
        !            11: which represent a particular, arbitrarily complex, data structure;
        !            12: and,
        !            13: {\em presentation streams},
        !            14: which represent an I/O path of these data structures.
        !            15: 
        !            16: \section      {Presentation Streams}
        !            17: A presentation stream is an object,
        !            18: similar to a \verb"FILE" object in \man stdio(3s),
        !            19: which is used to read and write {\em presentation elements}.
        !            20: The \verb"PStream" structure contains several elements,
        !            21: only the most interesting are described here:
        !            22: \begin{describe}
        !            23: \item[\verb"ps\_errno":] the latest error to occur on the stream
        !            24: (codes are listed in Table~\ref{PStreamReasons});
        !            25: 
        !            26: \item[\verb"ps\_addr":] the bottom-specific pointer;
        !            27: 
        !            28: \item[\verb"ps\_primeP":] the bottom-specific prime routine;
        !            29: 
        !            30: \item[\verb"ps\_readP":] the bottom-specific read routine;
        !            31: 
        !            32: \item[\verb"ps\_writeP":] the bottom-specific write routine;
        !            33: and,
        !            34: 
        !            35: \item[\verb"ps\_flushP":] the bottom-specific flush routine;
        !            36: and,
        !            37: 
        !            38: \item[\verb"ps\_closeP":] the bottom-specific close routine.
        !            39: \end{describe}
        !            40: \tagtable[tp]{3-1}{Presentation Stream Failure Codes}{PStreamReasons}
        !            41: The typedef \verb"PS" is a pointer to an \verb"PStream" structure.
        !            42: The \verb"ps_errno" element of the \verb"PStream" structure can be given as a
        !            43: parameter to the routine \verb"ps_error" which returns a
        !            44: null-terminated diagnostic string.
        !            45: \begin{quote}\index{ps\_error}\small\begin{verbatim}
        !            46: char   *ps_error (c)
        !            47: int     c;
        !            48: \end{verbatim}\end{quote}
        !            49: 
        !            50: \subsection    {Creating a Stream}
        !            51: A \verb"PStream" structure is created by calling the procedure \verb"ps_alloc",
        !            52: with the address of an integer-valued initialization routine.
        !            53: \begin{quote}\index{ps\_alloc}\small\begin{verbatim}
        !            54: PS      ps_alloc (init)
        !            55: int   (*init) ();
        !            56: \end{verbatim}\end{quote}
        !            57: The \verb"ps_alloc" routine allocates a new structure and then calls the
        !            58: initialization routine passed as a parameter,
        !            59: which should initialize the elements of the structure.
        !            60: The initialization routine should return the manifest constant \verb"OK" if
        !            61: all went well;
        !            62: otherwise it should return the manifest constant \verb"NOTOK" on error,
        !            63: which results in \verb"ps_alloc" freeing the newly allocated structure and
        !            64: then returning the value \verb"NULLPS".
        !            65: 
        !            66: Several standard initialization routines are available:
        !            67: \begin{describe}
        !            68: \item[\verb"std\_open":]  for presentation streams connected to \man stdio(3s)
        !            69: \verb"FILE" objects;
        !            70: \begin{quote}\index{std\_open}\small\begin{verbatim}
        !            71: int     std_open (ps)
        !            72: PS      ps;
        !            73: \end{verbatim}\end{quote}
        !            74: 
        !            75: \item[\verb"str\_open":] for presentation streams connected to string objects.
        !            76: \begin{quote}\index{str\_open}\small\begin{verbatim}
        !            77: int     str_open (ps)
        !            78: PS      ps;
        !            79: \end{verbatim}\end{quote}
        !            80: 
        !            81: \item[\verb"fdx\_open":] for presentation streams connected to full-duplex
        !            82: file descriptors.
        !            83: \begin{quote}\index{fdx\_open}\small\begin{verbatim}
        !            84: int     fdx_open (ps)
        !            85: PS      ps;
        !            86: \end{verbatim}\end{quote}
        !            87: and,
        !            88: 
        !            89: \item[\verb"dg\_open":] for presentation streams connected to datagram-based
        !            90: file descriptors.
        !            91: \begin{quote}\index{dg\_open}\small\begin{verbatim}
        !            92: int     dg_open (ps)
        !            93: PS      ps;
        !            94: \end{verbatim}\end{quote}
        !            95: \end{describe}
        !            96: Presentation streams which have been initialized by these routines will
        !            97: automatically allocate additional resources when necessary,
        !            98: to the limits allowed by the operating system
        !            99: (e.g., repeated writes to a presentation stream connected to a string object
        !           100: will result in additional memory being allocated).
        !           101: In the current implementation,
        !           102: presentation streams which have been initialized by these routines are
        !           103: uni-directional.
        !           104: That is,
        !           105: the presentation stream may be used for reading, or writing, but not both.
        !           106: 
        !           107: After \verb"ps_alloc" successfully returns,
        !           108: final initialization is performed by calling a setup routine, usually either
        !           109: \begin{describe}
        !           110: \item[\verb"std\_setup":] for file objects.
        !           111: \begin{quote}\index{std\_setup}\small\begin{verbatim}
        !           112: int     std_setup (ps, fp)
        !           113: PS      ps;
        !           114: FILE   *fp;
        !           115: \end{verbatim}\end{quote}
        !           116: The parameters to this procedure are:
        !           117: \begin{describe}
        !           118: \item[\verb"ps":] the presentation stream;
        !           119: and,
        !           120: 
        !           121: \item[\verb"fp":] a pointer to the \verb"FILE" object to be bound to the
        !           122: presentation stream.
        !           123: \end{describe}
        !           124: 
        !           125: \item[\verb"str\_setup":] for string objects.
        !           126: \begin{quote}\index{str\_setup}\small\begin{verbatim}
        !           127: int     str_setup (ps, cp, cc, inline)
        !           128: PS      ps;
        !           129: char   *cp;
        !           130: int     cc,
        !           131:        inline;
        !           132: \end{verbatim}\end{quote}
        !           133: The parameters to this procedure are:
        !           134: \begin{describe}
        !           135: \item[\verb"ps":] the presentation stream;
        !           136: 
        !           137: \item[\verb"cp":] a pointer to the string to be bound to the presentation
        !           138: stream
        !           139: (use the manifest constant \verb"NULLCP" if the stream is to be written);
        !           140: 
        !           141: \item[\verb"cc":] the length of the string;
        !           142: and,
        !           143: 
        !           144: \item[\verb"inline":] a magic argument,
        !           145: always use \verb"0" unless you know what you're doing.
        !           146: \end{describe}
        !           147: 
        !           148: \item[\verb"fdx\_setup":] for full-duplex file-descriptor objects.
        !           149: \begin{quote}\index{fdx\_setup}\small\begin{verbatim}
        !           150: int     fdx_setup (ps, fd)
        !           151: PS      ps;
        !           152: int     fd;
        !           153: \end{verbatim}\end{quote}
        !           154: The parameters to this procedure are:
        !           155: \begin{describe}
        !           156: \item[\verb"ps":] the presentation stream;
        !           157: and,
        !           158: 
        !           159: \item[\verb"fd":] the file-descriptor.
        !           160: \end{describe}
        !           161: 
        !           162: \item[\verb"dg\_setup":] for datagram objects.
        !           163: \begin{quote}\index{dg\_setup}\small\begin{verbatim}
        !           164: int     dg_setup (ps, fd, size, rfx, wfx)
        !           165: PS      ps;
        !           166: int     fd,
        !           167:         size;
        !           168: IFP     rfx,
        !           169:         wfx;
        !           170: \end{verbatim}\end{quote}
        !           171: The parameters to this procedure are:
        !           172: \begin{describe}
        !           173: \item[\verb"ps":] the presentation stream;
        !           174: 
        !           175: \item[\verb"fd":] the file-descriptor;
        !           176: 
        !           177: \item[\verb"size":] the maximum datagram size;
        !           178: and,
        !           179: 
        !           180: \item[\verb"rfx"/\verb"wfx":] routines to read and write datagrams.
        !           181: \end{describe}
        !           182: \end{describe}
        !           183: After the setup routine successfully returns
        !           184: (by returning the manifest constant \verb"OK"),
        !           185: the presentation stream is ready for reading or writing.
        !           186: 
        !           187: \subsection    {Stream I/O}
        !           188: Low-level I/O is done from/to the stream by the macros \verb"ps_read" and
        !           189: \verb"ps_write",
        !           190: which behave as if they were defined as:
        !           191: \begin{quote}\index{ps\_read}\index{ps\_write}\small\begin{verbatim}
        !           192: int     ps_read (ps, data, cc, inline)
        !           193: PS      ps;
        !           194: char   *data;
        !           195: int     cc,
        !           196:         inline;
        !           197: 
        !           198: int     ps_write (ps, data, cc, inline)
        !           199: PS      ps;
        !           200: char   *data;
        !           201: int     cc,
        !           202:         inline;
        !           203: \end{verbatim}\end{quote}
        !           204: The parameters to both of these macros are the same:
        !           205: \begin{describe}
        !           206: \item[\verb"ps":] the presentation stream;
        !           207: 
        !           208: \item[\verb"data":] the address of a character buffer;
        !           209: 
        !           210: \item[\verb"cc":] the number of characters to read/write from/to the buffer;
        !           211: and,
        !           212: 
        !           213: \item[\verb"inline":] a magic argument,
        !           214: always use \verb"0" unless you know what you're doing.
        !           215: \end{describe}
        !           216: These both call an internal routine, \verb"ps_io", which switches to the
        !           217: object-specific read or write routine as appropriate.
        !           218: The \verb"ps_io" procedure will call the object-specific routines as many
        !           219: times as required to read/write the full number of \verb"cc" bytes from/to
        !           220: the \verb"data" buffer.
        !           221: 
        !           222: \subsection    {Deleting a Stream}
        !           223: The routine \verb"ps_free" is used to close and deallocate a presentation
        !           224: stream.
        !           225: \begin{quote}\index{ps\_free}\small\begin{verbatim}
        !           226: void    ps_free (ps)
        !           227: PS      ps;
        !           228: \end{verbatim}\end{quote}
        !           229: It takes a single parameter,
        !           230: a pointer to the presentation stream to be freed.
        !           231: This routine first calls the routine specified by the \verb"ps_closeP"
        !           232: element in the \verb"PStream" structure (if any).
        !           233: It then frees the structure itself.
        !           234: 
        !           235: \subsection    {Implementing Other Abstractions}
        !           236: Let us briefly consider the internal protocol and uniform interface used in
        !           237: the implementation of presentation streams.
        !           238: 
        !           239: The initialization routine given as an argument to \verb"ps_alloc" typically
        !           240: initializes only the
        !           241: \begin{quote}\small\begin{verbatim}
        !           242: ps_primeP
        !           243: ps_readP
        !           244: ps_writeP
        !           245: ps_flushP
        !           246: ps_closeP
        !           247: \end{verbatim}\end{quote}
        !           248: elements in the \verb"PStream" structure.
        !           249: 
        !           250: The setup routine is entirely dependent on the particular object used to
        !           251: realize the I/O abstraction for the presentation stream.
        !           252: In most cases, it allocates a structure of its own and sets the
        !           253: \verb"ps_addr" element to the address of the structure.
        !           254: 
        !           255: The \verb"ps_readP" and \verb"ps_writeP" elements of the \verb"PStream"
        !           256: structure are used by the \verb"ps_io" routine as required for reading and
        !           257: writing.
        !           258: \begin{quote}\index{ps\_io}\small\begin{verbatim}
        !           259: int     ps_io (ps, io, data, cc, inline)
        !           260: PS      ps;
        !           261: int   (*io) ();
        !           262: char   *data;
        !           263: int     cc,
        !           264: \end{verbatim}\end{quote}
        !           265: The parameters to these routines are identical to those for their counterpart
        !           266: macros, \verb"ps_read" and \verb"ps_write",
        !           267: with one exception:
        !           268: \begin{describe}
        !           269: \item[\verb"io":] the address of an integer-valued function which does the
        !           270: actual reading or writing.
        !           271: It is invoked as:
        !           272: \begin{quote}\small\begin{verbatim}
        !           273: int     n = (*io) (ps, data, len, inline);
        !           274: \end{verbatim}\end{quote}
        !           275: \end{describe}
        !           276: where a return value of \verb"NOTOK" indicates an error occurred
        !           277: (the routine should set the \verb"ps_errno" element of the presentation
        !           278: stream);
        !           279: \verb"OK" indicates that the end-of-file has been read;
        !           280: and,
        !           281: any other value is the number of bytes actually transferred
        !           282: (which should be greater than \verb"0" but not greater than \verb"len").
        !           283: 
        !           284: For some packet-oriented applications,
        !           285: it may be desirable to do a single ``read from the network'' before
        !           286: reading the components of a presentation element.
        !           287: The routine pointed to by the \verb"ps_primeP" element of the \verb"PStream"
        !           288: structure is called by \verb"ps2pe" (described momentarily)
        !           289: before any parts of the entire presentation element has been read.
        !           290: The routine is invoked as:
        !           291: \begin{quote}\small\begin{verbatim}
        !           292: (*ps -> ps_primeP) (ps, waiting)
        !           293: PS      ps;
        !           294: int    waiting;
        !           295: \end{verbatim}\end{quote}
        !           296: The routine should return \verb"NOTOK" if an error occurred
        !           297: (setting the \verb"ps_errno" element of the presentation stream in the
        !           298: process);
        !           299: otherwise,
        !           300: if  data is already queued and \verb"waiting" is non-zero,
        !           301: then \verb"DONE" is returned.
        !           302: otherwise \verb"OK" is returned.
        !           303: The routine \verb"ps_prime" may be called to explicitly ``prime the pump''
        !           304: associated with a presentation element:
        !           305: \begin{quote}\index{ps\_prime}\small\begin{verbatim}
        !           306: int     ps_prime (ps)
        !           307: PS      ps;
        !           308: \end{verbatim}\end{quote}
        !           309: This routine returns \verb"OK" on success,
        !           310: or \verb"NOTOK" on failure.
        !           311: 
        !           312: In order to improve efficiency,
        !           313: it may be desirable to have \verb"ps_writeP" buffer output.
        !           314: The routine pointed to by the \verb"ps_flushP" element of the \verb"PStream"
        !           315: structure is called by \verb"pe2ps" (described momentarily)
        !           316: after the entire presentation element has been written.
        !           317: The routine is invoked as:
        !           318: \begin{quote}\small\begin{verbatim}
        !           319: (*ps -> ps_flushP) (ps)
        !           320: PS      ps;
        !           321: \end{verbatim}\end{quote}
        !           322: The routine should return \verb"NOTOK" if an error occurred
        !           323: (setting the \verb"ps_errno" element of the presentation stream in the
        !           324: process);
        !           325: or \verb"OK" if everything was fine.
        !           326: The routine \verb"ps_flush" may be called to explicitly flush any buffers
        !           327: associated with a presentation element:
        !           328: \begin{quote}\index{ps\_flush}\small\begin{verbatim}
        !           329: int     ps_flush (ps)
        !           330: PS      ps;
        !           331: \end{verbatim}\end{quote}
        !           332: This routine returns \verb"OK" on success,
        !           333: or \verb"NOTOK" on failure.
        !           334: 
        !           335: Finally,
        !           336: the \verb"ps_closeP" element of the \verb"PStream" structure is used by the
        !           337: \verb"ps_free" routine to release any resources which the setup routine may
        !           338: have allocated.
        !           339: For example,
        !           340: if the setup routine allocated a structure and set the \verb"ps_addr"
        !           341: element of the presentation stream to point to that structure,
        !           342: then the function pointed to by the \verb"ps_closeP" element should free that
        !           343: structure,
        !           344: and, as a matter of good programming practice, set \verb"ps_addr" to
        !           345: \verb"NULL".
        !           346: 
        !           347: \section      {Presentation Stream I/O}
        !           348: The routine \verb"ps2pe" can be used to read the next presentation element
        !           349: from a presentation stream.
        !           350: This routine returns a pointer to the presentation element or the manifest
        !           351: constant \verb"NULLPE" on error.
        !           352: (The typedef \verb"PE" is a pointer to a structure containing a presentation
        !           353: element; presentation elements are described more fully later.)
        !           354: \begin{quote}\index{ps2pe}\small\begin{verbatim}
        !           355: PE      ps2pe (ps)
        !           356: PS      ps;
        !           357: \end{verbatim}\end{quote}
        !           358: Similarly,
        !           359: the routine \verb"pe2ps" can be used to write a presentation element at the end
        !           360: of the presentation stream,
        !           361: returning \verb"OK" if all went well, or \verb"NOTOK" otherwise.
        !           362: \begin{quote}\index{pe2ps}\small\begin{verbatim}
        !           363: int     pe2ps (ps, pe)
        !           364: PS      ps;
        !           365: PE      pe;
        !           366: \end{verbatim}\end{quote}
        !           367: On errors with either routine,
        !           368: the \verb"ps_errno" element of the \verb"PStream" structure can be consulted
        !           369: to see what happened
        !           370: (see Table~\ref{PStreamReasons} on page~\pageref{PStreamReasons}).
        !           371: 
        !           372: When writing to a presentation stream,
        !           373: the variable \verb"ps_len_strategy" controls how lengthy data structures
        !           374: are represented by determining when the ``indefinite form'' is used to encode
        !           375: the length of the data structure.
        !           376: \begin{quote}\index{ps\_len\_strategy}\small\begin{verbatim}
        !           377: int     ps_len_strategy;
        !           378: \end{verbatim}\end{quote}
        !           379: If this variable is equal to \verb"PS_LEN_SPAG" (the default),
        !           380: then the indefinite form is used whenever the length field of the
        !           381: presentation element can not be represented in one octet.
        !           382: If the value instead is \verb"PS_LEN_INDF",
        !           383: then the indefinite form is used regardless of the length of the
        !           384: presentation element.
        !           385: Otherwise,
        !           386: if the value is \verb"PS_LEN_LONG",
        !           387: then the indefinite form is never used.
        !           388: 
        !           389: The routine \verb"ps_get_abs" can be used to determine the total number of
        !           390: octets that will be required to represent the presentation element
        !           391: when written to a presentation stream.
        !           392: This is useful for buffer management purposes.
        !           393: \begin{quote}\index{ps\_get\_abs}\small\begin{verbatim}
        !           394: int     ps_get_abs (pe)
        !           395: PE      pe;
        !           396: \end{verbatim}\end{quote}
        !           397: 
        !           398: \subsection    {Debugging}
        !           399: For debugging purposes,
        !           400: instead of treating a presentation stream as a binary object,
        !           401: the routines \verb"pl2pe" and \verb"pe2pl" can be used.
        !           402: \begin{quote}\index{pl2pe}\index{pe2pl}\small\begin{verbatim}
        !           403: PE      pl2pe (ps)
        !           404: PS      ps;
        !           405: 
        !           406: int     pe2pl (ps, pe)
        !           407: PS      ps;
        !           408: PE      pe;
        !           409: \end{verbatim}\end{quote}
        !           410: These translate between presentation {\em lists\/} and presentation elements.
        !           411: A presentation list is identical to a presentation stream,
        !           412: but instead of using a binary representation,
        !           413: a list uses an ASCII text representation
        !           414: with a simple LISP-like syntax.
        !           415: 
        !           416: \section      {Presentation Elements}
        !           417: A presentation element is an object which is used to represent a
        !           418: data structure in a machine-independent form.
        !           419: The \verb"PElement" structure contains several elements,
        !           420: only the most interesting are described here:
        !           421: \begin{describe}
        !           422: \item[\verb"pe\_errno":] the latest error to occur on the presentation element
        !           423: (codes are listed in Table~\ref{PElementReasons});
        !           424: 
        !           425: \item[\verb"pe\_context":] the presentation context to which the element
        !           426: belongs (consult Section~\ref{psap:context} on page~\pageref{psap:context} of
        !           427: \voltwo/);
        !           428: 
        !           429: \item[\verb"pe\_class":] the class of this presentation element
        !           430: (i.e., one of {\em universal}, {\em application-wide}, {\em context-specific},
        !           431: or {\em private\/});
        !           432: 
        !           433: \item[\verb"pe\_form":] the form taken by this presentation element
        !           434: (i.e., {\em primitive}, or {\em constructed\/});
        !           435: 
        !           436: \item[\verb"pe\_id":] the class-specific code identifying the type of this
        !           437: presentation element;
        !           438: 
        !           439: \item[\verb"pe\_offset":] the offset of this presentation element in a
        !           440: sequence;
        !           441: and,
        !           442: 
        !           443: \item[\verb"pe\_next":] a pointer to the next presentation element in a
        !           444: sequence.
        !           445: \end{describe}
        !           446: \tagtable[tp]{3-2}{Presentation Element Failure Codes}{PElementReasons}
        !           447: As mentioned earlier,
        !           448: the typedef \verb"PE" is a pointer to an \verb"PElement" structure.
        !           449: With the exception of the \verb"pe_errno" element,
        !           450: the elements of the \verb"PElement" structure are largely uninteresting to
        !           451: the user of the \man libpsap(3) library.
        !           452: The element \verb"pe_errno"
        !           453: can be given as a parameter to the routine \verb"pe_error" which returns a
        !           454: null-terminated diagnostic string.
        !           455: \begin{quote}\index{pe\_error}\small\begin{verbatim}
        !           456: char   *pe_error (c)
        !           457: int     c;
        !           458: \end{verbatim}\end{quote}
        !           459: 
        !           460: Once a presentation stream has been initialized and elements are being read,
        !           461: there are several routines which can be used to translate between the
        !           462: machine-independent representation of the element and machine-specific
        !           463: objects such as integers, strings, and the like.
        !           464: It is extremely important that programs use these routines to perform the
        !           465: translation between objects.
        !           466: They have been carefully coded to present a simple, uniform interface between
        !           467: machine-specifics and the machine-independent encoding protocol.
        !           468: 
        !           469: \subsection    {Creating an Element}
        !           470: A \verb"PElement" structure is created by calling the procedure
        !           471: \verb"pe_alloc".
        !           472: \begin{quote}\index{pe\_alloc}\small\begin{verbatim}
        !           473: PE      pe_alloc (class, form, id)
        !           474: PElementClass class;
        !           475: PElementForm form;
        !           476: PElementID id;
        !           477: \end{verbatim}\end{quote}
        !           478: This procedure takes three parameters:
        !           479: \begin{describe}
        !           480: \item[\verb"class":] the class of this presentation element.
        !           481: The codes are:
        !           482: 
        !           483: \begin{tabular}{rp{3.0in}}
        !           484: \tt PE\_CLASS\_UNIV&   Universal\\
        !           485: \tt PE\_CLASS\_APPL&   Application-wide\\
        !           486: \tt PE\_CLASS\_CONT&   Context-specific\\
        !           487: \tt PE\_CLASS\_PRIV&   Private-use
        !           488: \end{tabular}
        !           489: 
        !           490: \item[\verb"form":] the form of this presentation element
        !           491: The codes are:
        !           492: 
        !           493: \begin{tabular}{rp{3.0in}}
        !           494: \tt PE\_FORM\_PRIM&    Primitive\\
        !           495: \tt PE\_FORM\_CONS&    Constructor
        !           496: \end{tabular}
        !           497: 
        !           498: \item[\verb"id":] the class-specific code identifying the type of this
        !           499: presentation element
        !           500: (codes for the ``universal'' class are listed in Table~\ref{PElementIDs}).
        !           501: \end{describe}
        !           502: \tagtable[tp]{3-3}{Presentation Element Identifiers}{PElementIDs}
        !           503: 
        !           504: \subsection    {Deleting an Element}
        !           505: The routine \verb"pe_free" is used to deallocate a presentation element.
        !           506: \begin{quote}\index{pe\_free}\small\begin{verbatim}
        !           507: void    pe_free (pe)
        !           508: PE      pe;
        !           509: \end{verbatim}\end{quote}
        !           510: 
        !           511: \[\fbox{\begin{tabular}{lp{0.8\textwidth}}
        !           512: \bf NOTE:&     When using \verb"pe\_free" on a presentation element,
        !           513:                care must be taken to remove any references to that
        !           514:                presentation element in other structures.
        !           515:                For example, if you have a sequence containing a sequence,
        !           516:                and you free the child sequence,
        !           517:                be sure to zero-out the parent's pointer to the child,
        !           518:                otherwise subsequent calls using the parent will go romping
        !           519:                through hyperspace.
        !           520:                See \verb"pe\_extract" and \verb"pe\_expunge" below.
        !           521: \end{tabular}}\]
        !           522: 
        !           523: \subsection    {Primitive Manipulation of Elements}
        !           524: Two presentation elements can be compared with \verb"pe_cmp",
        !           525: which takes two pointers to \verb"PElement" structures as arguments,
        !           526: and returns \verb"0" if the two structures are identical,
        !           527: \verb"1" otherwise.
        !           528: \begin{quote}\index{pe\_cmp}\small\begin{verbatim}
        !           529: int     pe_cmp (p, q)
        !           530: PE      p,
        !           531:         q;
        !           532: \end{verbatim}\end{quote}
        !           533: Further, an presentation element can be duplicated with \verb"pe_cpy".
        !           534: This routine takes a pointer to an \verb"PElement" structure as an argument,
        !           535: and  returns a pointer to a new \verb"PElement" structure,
        !           536: or \verb"NULLPE" on error.
        !           537: \begin{quote}\index{pe\_cpy}\small\begin{verbatim}
        !           538: PE      pe_cpy (pe)
        !           539: PE      pe;
        !           540: \end{verbatim}\end{quote}
        !           541: 
        !           542: If a presentation element, \verb"pe", has a descendant \verb"r"
        !           543: (which appears below \verb"pe" exactly once),
        !           544: then \verb"pe_extract" can be used to destroy the relationship between
        !           545: the two presentation elements without freeing either element.
        !           546: \begin{quote}\index{pe\_extract}\small\begin{verbatim}
        !           547: int     pe_extract (pe, r)
        !           548: PE      pe,
        !           549:         r;
        !           550: \end{verbatim}\end{quote}
        !           551: This routine returns non-zero if \verb"r" was descended from \verb"pe",
        !           552: otherwise it returns zero.
        !           553: The \verb"pe_expunge" routine is similar to \verb"pe_extract",
        !           554: except that it always deallocates the parent element and returns the child
        !           555: element found, if any.
        !           556: \begin{quote}\index{pe\_expunge}\small\begin{verbatim}
        !           557: PE      pe_expunge (pe, r)
        !           558: PE      pe,
        !           559:         r;
        !           560: \end{verbatim}\end{quote}
        !           561: These two routines are provided primarily for efficiency considerations.
        !           562: They are extremely fragile.
        !           563: Do not use them unless you know what you're doing.
        !           564: 
        !           565: Finally,
        !           566: the \verb"pe_pullup" routine can be used to ``pull-up'' a constructor type
        !           567: into a primitive.
        !           568: \begin{quote}\index{pe\_pullup}\small\begin{verbatim}
        !           569: int     pe_pullup (pe)
        !           570: PE      pe;
        !           571: \end{verbatim}\end{quote}
        !           572: This routine returns \verb"OK" on success;
        !           573: on failure it turns \verb"NOTOK",
        !           574: usually due to a memory allocation failure.
        !           575: 
        !           576: \section      {Presentation Element Transformations}
        !           577: We now discuss how machine-specific objects can be encoded in a
        !           578: machine-independent fashion and vice-versa.
        !           579: Routines of the form \verb"XXX2prim" all return a pointer to a presentation
        !           580: element on success,
        !           581: or \verb"NULLPE" on failure
        !           582: (usually due to a failure in the memory allocator).
        !           583: Routines of the form \verb"prim2XXX" all return an \verb"XXX"-valued object
        !           584: on success,
        !           585: or \verb"NOTOK" or \verb"NULLxxx" on failure
        !           586: (depending on the object the routine normally returns).
        !           587: On failure,
        !           588: the \verb"pe_errno" element of the presentation element can be examined to
        !           589: determine the reason for failure.
        !           590: 
        !           591: \subsection    {Boolean}
        !           592: A {\em boolean\/} is an integer taking on the values \verb"0" or \verb"1".
        !           593: The routine \verb"prim2flag" takes a pointer to an presentation element and
        !           594: returns the boolean value encoded therein.
        !           595: \begin{quote}\index{prim2flag}\small\begin{verbatim}
        !           596: int     prim2flag (pe)
        !           597: PE      pe;
        !           598: \end{verbatim}\end{quote}
        !           599: The routine \verb"bool2prim" is a macro which performs the inverse operation.
        !           600: It behaves as if it was defined as:
        !           601: \begin{quote}\index{bool2prim}\small\begin{verbatim}
        !           602: PE      bool2prim (b)
        !           603: int     b;
        !           604: \end{verbatim}\end{quote}
        !           605: In actuality,
        !           606: \verb"bool2prim" calls the routine \verb"flag2prim" which builds a
        !           607: presentation element containing the boolean value given and sets the
        !           608: \verb"pe_class" and \verb"pe_id" fields of the presentation element to the
        !           609: desired values.
        !           610: \begin{quote}\index{flag2prim}\small\begin{verbatim}
        !           611: PE      flag2prim (b, class, id)
        !           612: int     b;
        !           613: PElementClass class;
        !           614: PElementID id;
        !           615: \end{verbatim}\end{quote}
        !           616: 
        !           617: \subsection    {Integer}
        !           618: An {\em integer\/} is a signed-quantity, whose precision is specific to a
        !           619: particular host.
        !           620: The routine \verb"prim2num" takes a pointer to a presentation element and
        !           621: returns the integer value
        !           622: encoded therein (if the value is \verb"NOTOK", check the \verb"pe_errno"
        !           623: element of the \verb"PElement" structure to see if there really was an error).
        !           624: \begin{quote}\index{prim2num}\small\begin{verbatim}
        !           625: int     prim2num (pe)
        !           626: PE      pe;
        !           627: \end{verbatim}\end{quote}
        !           628: The routine \verb"int2prim" is a macro which performs the inverse operation.
        !           629: It behaves as if it was defined as:
        !           630: \begin{quote}\index{int2prim}\small\begin{verbatim}
        !           631: PE      int2prim (i)
        !           632: int     i;
        !           633: \end{verbatim}\end{quote}
        !           634: In actuality,
        !           635: \verb"int2prim" calls the routine \verb"num2prim" which builds a presentation
        !           636: element containing the numeric value given and sets the \verb"pe_class" and
        !           637: \verb"pe_id" fields of the presentation element to the desired values.
        !           638: \begin{quote}\index{num2prim}\small\begin{verbatim}
        !           639: PE      num2prim (i, class, id)
        !           640: int     i;
        !           641: PElementClass class;
        !           642: PElementID id;
        !           643: \end{verbatim}\end{quote}
        !           644: 
        !           645: \subsection    {Octetstring}
        !           646: An {\em octetstring\/} is a pair of values:
        !           647: a character pointer and an integer length.
        !           648: The pointer addresses the first octet in the string
        !           649: (which need not be null-terminated),
        !           650: the length indicates how many octets are in the string.
        !           651: The routine \verb"prim2str" takes a pointer to a presentation element and
        !           652: allocates a new string (using the \man malloc(3) routine)
        !           653: containing the value encoded therein.
        !           654: \begin{quote}\index{prim2str}\small\begin{verbatim}
        !           655: char   *prim2str (pe, len)
        !           656: PE      pe;
        !           657: int    *len;
        !           658: \end{verbatim}\end{quote}
        !           659: The routine \verb"oct2prim" is a macro which performs the inverse operation,
        !           660: copying the original string (and not de-allocating it).
        !           661: It behaves as if it was defined as:
        !           662: \begin{quote}\index{oct2prim}\small\begin{verbatim}
        !           663: PE      oct2prim (s, len)
        !           664: char   *s;
        !           665: int     len;
        !           666: \end{verbatim}\end{quote}
        !           667: In actuality,
        !           668: \verb"oct2prim" calls the routine \verb"str2prim" which builds a presentation
        !           669: element containing the string value given and sets the \verb"pe_class" and
        !           670: \verb"pe_id" fields of the presentation element to the desired values.
        !           671: \begin{quote}\index{str2prim}\small\begin{verbatim}
        !           672: PE      str2prim (s, len, class, id)
        !           673: char   *s;
        !           674: int     len;
        !           675: PElementClass class;
        !           676: PElementID id;
        !           677: \end{verbatim}\end{quote}
        !           678: 
        !           679: In addition to \verb"oct2prim",
        !           680: there are several macros which manipulate octetstrings,
        !           681: setting the class and id of the presentation element to the
        !           682: appropriate value:
        !           683: \[\begin{tabular}{|l|l|}
        !           684: \hline
        !           685:     \multicolumn{1}{|c|}{\bf Macro}&
        !           686:                \multicolumn{1}{c|}{\bf String}\\
        !           687: \hline
        !           688:     \tt ia5s2prim&     IA5 string\\
        !           689:     \tt nums2prim&     Numeric string\\
        !           690:     \tt prts2prim&     Printable string\\
        !           691:     \tt t61s2prim&     T.61 string\\
        !           692:     \tt vtxs2prim&     Videotex string\\
        !           693:     \tt gfxs2prim&     Graphics string\\
        !           694:     \tt viss2prim&     Visible string\\
        !           695:     \tt gens2prim&     General string\\
        !           696:     \tt chrs2prim&     Character string\\
        !           697:     \tt ode2prim&      Object descriptor\\
        !           698: \hline
        !           699: \end{tabular}\]
        !           700: Each of these macros are defined in a similar manner to the \verb"oct2prim"
        !           701: macro.\index{ia5s2prim}\index{nums2prim}\index{prts2prim}\index{t61s2prim}
        !           702: \index{vtxs2prim}\index{gfxs2prim}\index{viss2prim}\index{gens2prim}   
        !           703: \index{ode2prim}
        !           704: 
        !           705: \subsection    {Octetstrings revisited}\label{psap:qbuf}
        !           706: For efficiency reasons,
        !           707: it is often desirable to represent an octetstring using a \verb"qbuf"
        !           708: structure.
        !           709: Although the format of a \verb"qbuf" is described in Section~\ref{tsap:qbuf}
        !           710: on page~\pageref{tsap:qbuf} of \voltwo/,
        !           711: the \man libpsap(3) library provides several routines for ease of
        !           712: manipulation.
        !           713: 
        !           714: The routine \verb"qb2prim" takes a linked-list of \verb"qbuf"s and builds a
        !           715: presentation element with the \verb"pe_class" and \verb"pe_id" fields of the
        !           716: presentation element set to the desired values:
        !           717: \begin{quote}\index{qb2prim}\small\begin{verbatim}
        !           718: PE      qb2prim (qb, class, id)
        !           719: struct qbuf *qb;
        !           720: PElementClass class;
        !           721: PElementID id;
        !           722: \end{verbatim}\end{quote}
        !           723: \[\fbox{\begin{tabular}{lp{0.8\textwidth}}
        !           724: \bf NOTE:&     The presentation element returned by \verb"qb2prim" contains
        !           725:                pointers into the linked-list of \verb"qbuf"s.
        !           726:                Therefore care must be taken not to delete any of the
        !           727:                \verb"qbuf"s in the linked-list prior to the final use of the
        !           728:                presentation element.  Note however, than the presentation
        !           729:                element may be de-allocated at anytime without affecting
        !           730:                the \verb"qbuf"s in the linked-list.
        !           731: \end{tabular}}\]
        !           732: 
        !           733: 
        !           734: The routine \verb"prim2qb" performs the inverse operation:
        !           735: \begin{quote}\index{prim2qb}\small\begin{verbatim}
        !           736: struct qbuf *prim2qb (pe)
        !           737: PE      pe;
        !           738: \end{verbatim}\end{quote}
        !           739: 
        !           740: When examining the contents of a \verb"qbuf",
        !           741: it is most efficient to examine each \verb"qbuf" in the linked list,
        !           742: as in:
        !           743: \begin{quote}\small\begin{verbatim}
        !           744: register struct qbuf *qp;
        !           745: 
        !           746: for (qp = qb -> qb_forw; qp != qb; qp = qp -> qb_forw)
        !           747:     /* examine qp -> qb_data, qp -> qb_len here */ ;
        !           748: \end{verbatim}\end{quote}
        !           749: However,
        !           750: some applications may wish to simply convert the \verb"qbuf" into one string
        !           751: and examine it without worrying about traversing the linked list.
        !           752: The routine \verb"qb2str" performs this function:
        !           753: \begin{quote}\index{qb2str}\small\begin{verbatim}
        !           754: char   *qb2str (qb)
        !           755: struct qbuf *qb;
        !           756: \end{verbatim}\end{quote}
        !           757: The routine \verb"str2qb" performs the inverse operation,
        !           758: converting a string to a \verb"qbuf".
        !           759: \begin{quote}\index{str2qb}\small\begin{verbatim}
        !           760: struct qbuf *str2qb (s, len, head)
        !           761: char   *s;
        !           762: int     len,
        !           763:        head;
        !           764: \end{verbatim}\end{quote}
        !           765: The \verb"head" parameter indicates whether \verb"str2qb" should allocate a
        !           766: \verb"qbuf" containing both the head of the linked list and one element
        !           767: (\verb"head" is non-zero),
        !           768: or just the element itself (\verb"head" is zero).
        !           769: 
        !           770: The routine \verb"qb_pullup" can be used to compact a linked list of
        !           771: \verb"qbuf"s into a list containing the \verb"qbuf" head and one element:
        !           772: \begin{quote}\index{qb\_pullup}\small\begin{verbatim}
        !           773: int     qb_pullup (qb)
        !           774: struct qbuf *qb;
        !           775: \end{verbatim}\end{quote}
        !           776: This routine returns the manifest constant \verb"NOTOK" on failure,
        !           777: and \verb"OK" otherwise.
        !           778: 
        !           779: The routine \verb"qbuf2pe" is used to set-up a presentation stream which reads
        !           780: from a linked list of \verb"qbuf"s and returns the presentation element
        !           781: encoded therein:
        !           782: \begin{quote}\index{qbuf2pe}\small\begin{verbatim}
        !           783: PE      qbuf2pe (qb, len, result)
        !           784: struct qbuf *qb;
        !           785: int     len,
        !           786:        *result;
        !           787: \end{verbatim}\end{quote}
        !           788: This routine returns a presentation element on success,
        !           789: and \verb"NULLPE" on failure.
        !           790: In the latter case, the parameter \verb"result" is updated to reflect the
        !           791: presentation stream error.
        !           792: 
        !           793: Finally,
        !           794: the routine \verb"qb_free" will deallocate a linked list of \verb"qbuf"s:
        !           795: \begin{quote}\index{qb\_free}\small\begin{verbatim}
        !           796: void    qb_free (qb)
        !           797: \end{verbatim}\end{quote}
        !           798: 
        !           799: \subsection    {Bitvector}\label{psap:bits}
        !           800: A {\em bitvector\/} is an arbitrarily long string of bits
        !           801: (starting with bit \verb"0") with three operations:
        !           802: \begin{describe}
        !           803: \item[\verb"bit\_on":] which turns the indicated bit on;
        !           804: \begin{quote}\index{bit\_on}\small\begin{verbatim}
        !           805: int     bit_on (pe, bitno)
        !           806: PE      pe;
        !           807: int     bitno;
        !           808: \end{verbatim}\end{quote}
        !           809: 
        !           810: \item[\verb"bit\_off":] which turns the indicated bit off;
        !           811: \begin{quote}\index{bit\_off}\small\begin{verbatim}
        !           812: int     bit_off (pe, bitno)
        !           813: PE      pe;
        !           814: int     bitno;
        !           815: \end{verbatim}\end{quote}
        !           816: and,
        !           817: 
        !           818: \item[\verb"bit\_test":] which returns a boolean value telling if the indicated
        !           819: bit was on.
        !           820: \begin{quote}\index{bit\_test}\small\begin{verbatim}
        !           821: int     bit_test (pe, bitno)
        !           822: PE      pe;
        !           823: int     bitno;
        !           824: \end{verbatim}\end{quote}
        !           825: \end{describe}
        !           826: The routine \verb"prim2bit" takes a pointer to a presentation element and
        !           827: builds such an abstraction containing the value encoded therein.
        !           828: \begin{quote}\index{prim2bit}\small\begin{verbatim}
        !           829: PE      prim2bit (pe)
        !           830: PE      pe;
        !           831: \end{verbatim}\end{quote}
        !           832: The routine \verb"bit2prim" performs the inverse operation.
        !           833: \begin{quote}\index{bit2prim}\small\begin{verbatim}
        !           834: PE      bit2prim (pe)
        !           835: PE      pe;
        !           836: \end{verbatim}\end{quote}
        !           837: 
        !           838: There are also some support routines useful mainly with \pgm{pepy}.
        !           839: The routine \verb"strb2bitstr" takes a pointer to a character
        !           840: string and an integer containing the number of bits and constructs
        !           841: a presentation element as described above containing the bits.
        !           842: \begin{quote}\index{strb2bitstr}\small\begin{verbatim}
        !           843: PE      strb2bitstr (cp, length, class, id)
        !           844: char   *cp;
        !           845: int     length;
        !           846: PElementClass class;
        !           847: PElementID id;
        !           848: \end{verbatim}\end{quote}
        !           849: The inverse operation is handled by the function \verb"bitstr2strb".
        !           850: This takes a presentation element containing a bit string and produces
        !           851: a new character string with the appropriate bits set. The second
        !           852: parameter will contain the number of valid bits on return.
        !           853: \begin{quote}\index{bitstr2strb}\small\begin{verbatim}
        !           854: char   *bitstr2strb (pe, length)
        !           855: PE      pe;
        !           856: int    *length;
        !           857: \end{verbatim}\end{quote}
        !           858: Finally, the routines \verb"int2strb" and \verb"strb2int" are provided to
        !           859: convert an integer containing a bit list into a string of bits suitable for
        !           860: input to \verb"strb2bitstr", and to perform the inverse operation
        !           861: \begin{quote}\index{int2strb}\small\begin{verbatim}
        !           862: char   *int2strb (n, length)
        !           863: int     n;
        !           864: int     length;
        !           865: 
        !           866: int     strb2int (cp, length)
        !           867: char   *cp;
        !           868: int     length;
        !           869: \end{verbatim}\end{quote}
        !           870: 
        !           871: \subsection    {Object Identifier}\label{psap:oid}
        !           872: An {\em object identifier\/} represents an ordered set of authoritative
        !           873: designations used for identification.
        !           874: Internally,
        !           875: the \verb"OIDentifier" is used to represent this notion:
        !           876: \begin{quote}\index{OIDentifier}\small\begin{verbatim}
        !           877: typedef struct OIDentifier {
        !           878:     int     oid_nelem;
        !           879: 
        !           880:     unsigned int *oid_elements;
        !           881: }       OIDentifier, *OID;
        !           882: #define NULLOID ((OID) 0)
        !           883: \end{verbatim}\end{quote}
        !           884: This structure contains two elements:
        !           885: \begin{describe}
        !           886: \item[\verb"oid\_elements"/\verb"oid\_nelem":] the (ordered) list of
        !           887: sub-identifiers (and the number of elements in the list).
        !           888: \end{describe}
        !           889: 
        !           890: Two object identifiers can be compared with \verb"oid_cmp",
        !           891: which takes two pointers to \verb"OIDentifier" structures as arguments,
        !           892: and returns \verb"0" if the two structures are identical,
        !           893: \verb"1" otherwise.
        !           894: \begin{quote}\index{oid\_cmp}\small\begin{verbatim}
        !           895: int     oid_cmp (p, q)
        !           896: OID     p,
        !           897:         q;
        !           898: \end{verbatim}\end{quote}
        !           899: Further, an object identifier can be duplicated with \verb"oid_cpy".
        !           900: This routine takes a pointer to an \verb"OIDentifier" structure as an argument,
        !           901: and  returns a pointer to a new \verb"OIDentifier" structure,
        !           902: or \verb"NULLOID" on error.
        !           903: \begin{quote}\index{oid\_cpy}\small\begin{verbatim}
        !           904: OID     oid_cpy (oid)
        !           905: OID     oid;
        !           906: \end{verbatim}\end{quote}
        !           907: Simlarly, the routine \verb"oid_free" can be used to free an object
        !           908: identifier which has been allocated.
        !           909: \begin{quote}\index{oid\_free}\small\begin{verbatim}
        !           910: void    oid_free (oid)
        !           911: OID     oid;
        !           912: \end{verbatim}\end{quote}
        !           913: The routine \verb"sprintoid" can be used to return a null-terminated
        !           914: string describing the object identifier.
        !           915: \begin{quote}\index{sprintoid}\small\begin{verbatim}
        !           916: char   *sprintoid (oid)
        !           917: OID     oid;
        !           918: \end{verbatim}\end{quote}
        !           919: The default routine \verb"oid2ode"\index{oid2ode} is identical to the
        !           920: \verb"sprintoid",
        !           921: but is intended for user customization.
        !           922: For example,
        !           923: whilst \verb"sprintoid" should always be used when an object identifier should
        !           924: be expressed in ``dot notation'',
        !           925: the user may define a new \verb"oid2ode" which returns symbolic names,
        !           926: if so desired.
        !           927: 
        !           928: The routine \verb"str2oid" can be used as the inverse of \verb"sprintoid":
        !           929: \begin{quote}\index{str2oid}\small\begin{verbatim}
        !           930: OID     str2oid (s)
        !           931: char   *s;
        !           932: \end{verbatim}\end{quote}
        !           933: Finally,
        !           934: the routine \verb"ode2oid" can be used to fetch an object identifier from the
        !           935: \man isobjects(5) database described in Chapter~\ref{isobjects}.
        !           936: \begin{quote}\index{oid\_free}\small\begin{verbatim}
        !           937: OID     ode2oid (descriptor)
        !           938: char   *descriptor;
        !           939: \end{verbatim}\end{quote}
        !           940: This routine performs a lookup using the \verb"getisobjectbyname" routine
        !           941: and then returns a pointer to a static \verb"OIDentifier" structure
        !           942: containing the desired information.
        !           943: The routine returns \verb"NULLOID" on failure.
        !           944: 
        !           945: The routines \verb"prim2oid" and \verb"oid2prim" are used to translate
        !           946: between a machine-specific internal form and the machine-independent form.
        !           947: \begin{quote}\index{prim2oid}\index{oid2prim}\small\begin{verbatim}
        !           948: OID     prim2oid (pe)
        !           949: PE      pe;
        !           950: 
        !           951: PE      oid2prim (o)
        !           952: OID     o;
        !           953: \end{verbatim}\end{quote}
        !           954: In actuality,
        !           955: \verb"oid2prim" is really a macro which calls the routine \verb"obj2prim"
        !           956: which builds a presentation element containing the object identifier given
        !           957: and sets the \verb"pe_class" an \verb"pe_id" fields of the presentation element
        !           958: to the desired values.
        !           959: \begin{quote}\index{obj2prim}\small\begin{verbatim}
        !           960: PE      obj2prim (o, class, id)
        !           961: OID     o;
        !           962: PElementClass class;
        !           963: PElementID id;
        !           964: \end{verbatim}\end{quote}
        !           965: 
        !           966: \subsection    {Timestring}
        !           967: A {\em timestring\/} represents a date/time in many forms.
        !           968: Currently, two forms are supported: {\em universal time\/} and
        !           969: {\em generalized time}.
        !           970: Internally,
        !           971: the \verb"UTCtime" structure is used to represent both notions:
        !           972: \begin{quote}\index{UTCtime}\small\begin{verbatim}
        !           973: typedef struct UTCtime {
        !           974:     int     ut_year;
        !           975:     int     ut_mon;
        !           976:     int     ut_mday;
        !           977:     int     ut_hour;
        !           978:     int     ut_min;
        !           979:     int     ut_sec;
        !           980: 
        !           981:     int     ut_msec;
        !           982: 
        !           983:     int     ut_zone;
        !           984: 
        !           985:     int     ut_flags;
        !           986: }       UTCtime, *UTC;
        !           987: #define NULLUTC ((UTC) 0)
        !           988: \end{verbatim}\end{quote}
        !           989: This structure contains several elements:
        !           990: \begin{describe}
        !           991: \item[\verb"ut\_year":] the year,
        !           992: either since the current century (e.g., \verb"86"),
        !           993: or absolute (e.g., \verb"1986");
        !           994: 
        !           995: \item[\verb"ut\_mon":] the month of the year, in the range \verb"1..12";
        !           996: 
        !           997: \item[\verb"ut\_mday":] the day of the month, in the range \verb"1..31";
        !           998: 
        !           999: \item[\verb"ut\_hour":] the hour of the day, in the range \verb"0..23";
        !          1000: 
        !          1001: \item[\verb"ut\_min":] the minute of the hour, in the range \verb"0..59";
        !          1002: 
        !          1003: \item[\verb"ut\_sec":] (optionally) the second of the minute,
        !          1004: in the range \verb"0..59";
        !          1005: 
        !          1006: \item[\verb"ut\_usec":] (optionally) fractions of a second, in microseconds;
        !          1007: 
        !          1008: \item[\verb"ut\_zone":] (optionally) the timezone, expressed as minutes from
        !          1009: UT; and,
        !          1010: 
        !          1011: \item[\verb"ut\_flags":] various flags describing the timestring:
        !          1012:     \begin{describe}
        !          1013:     \item[\verb"UT\_ZONE":] the \verb"ut_zone" element is present; 
        !          1014: 
        !          1015:     \item[\verb"UT\_SEC":] the \verb"ut_sec" element is present; and,
        !          1016: 
        !          1017:     \item[\verb"UT\_USEC":] the \verb"ut_usec" element is present.
        !          1018:     \end{describe}
        !          1019: \end{describe}
        !          1020: 
        !          1021: The routine \verb"prim2utct" takes a pointer to a presentation element and
        !          1022: returns the universal time encoded therein.
        !          1023: \begin{quote}\index{prim2utct}\small\begin{verbatim}
        !          1024: UTC     prim2utct (pe)
        !          1025: PE      pe;
        !          1026: \end{verbatim}
        !          1027: \end{quote}
        !          1028: The routine \verb"utct2prim" is a macro which performs the inverse operatoin.
        !          1029: It behaves as if it was defined as:
        !          1030: \begin{quote}\index{utct2prim}\small\begin{verbatim}
        !          1031: PE      utct2prim (u)
        !          1032: UTC     u;
        !          1033: \end{verbatim}\end{quote}
        !          1034: 
        !          1035: The routine \verb"prim2gent" takes a pointer to a presentation element and
        !          1036: returns the universal time encoded therein.
        !          1037: \begin{quote}\index{prim2gent}\small\begin{verbatim}
        !          1038: UTC     prim2gent (pe)
        !          1039: PE      pe;
        !          1040: \end{verbatim}
        !          1041: \end{quote}
        !          1042: The routine \verb"gent2prim" is a macro which performs the inverse operatoin.
        !          1043: It behaves as if it was defined as:
        !          1044: \begin{quote}\index{gent2prim}\small\begin{verbatim}
        !          1045: PE      gent2prim (u)
        !          1046: UTC     u;
        !          1047: \end{verbatim}\end{quote}
        !          1048: 
        !          1049: In actuality,
        !          1050: both \verb"utct2prim" and \verb"gent2prim" call the routine \verb"time2prim"
        !          1051: which builds a
        !          1052: presentation element containing the universal or general time given and sets
        !          1053: the \verb"pe_class" an \verb"pe_id" fields of the presentation element to the
        !          1054: desired values.
        !          1055: \begin{quote}\index{time2prim}\small\begin{verbatim}
        !          1056: PE      time2prim (ut, generalized, class, id)
        !          1057: UTC     u;
        !          1058: int    generalized;
        !          1059: PElementClass class;
        !          1060: PElementID id;
        !          1061: \end{verbatim}\end{quote}
        !          1062: 
        !          1063: To get a null-terminated string representation of a \verb"UTCtime" structure,
        !          1064: the macros \verb"utct2str" and \verb"gent2str" can be
        !          1065: used.\index{utct2str}\index{gent2str}
        !          1066: Each take a single argument, a pointer to a \verb"UTCtime" structure.
        !          1067: These call the routine \verb"time2str":
        !          1068: \begin{quote}\index{time2str}\small\begin{verbatim}
        !          1069: char   *time2str (ut, generalized)
        !          1070: UTC     u;
        !          1071: int     generalized;
        !          1072: \end{verbatim}\end{quote}
        !          1073: Both call the routine \verb"prim2time":
        !          1074: \begin{quote}\index{prim2time}\small\begin{verbatim}
        !          1075: UTC     prim2time (pe, generalized)
        !          1076: PE      pe;
        !          1077: int     generalized;
        !          1078: \end{verbatim}\end{quote}
        !          1079: 
        !          1080: The routines \verb"str2utct" and \verb"str2gent" perform the inverse
        !          1081: operations:
        !          1082: \begin{quote}\index{str2utct}\index{str2gent}\small\begin{verbatim}
        !          1083: UTC     str2utct (cp, len)
        !          1084: char   *cp;
        !          1085: int     len;
        !          1086: 
        !          1087: UTC     str2gent (cp, len)
        !          1088: char   *cp;
        !          1089: int     len;
        !          1090: \end{verbatim}\end{quote}
        !          1091: Each take a character-pointer and a length-indicator as arguments and return a
        !          1092: \verb"UTCtime" structure on success.
        !          1093: Otherwise, the manifest constant \verb"NULLUTC" is returned.
        !          1094: 
        !          1095: There are also some utility routines to aid in converting between
        !          1096: \verb"UTCtime" and \unix/ \verb"tm" time structures.
        !          1097: The routine \verb"gtime" is the inverse of \man gmtime(3),
        !          1098: it takes a time structure and returns a long-valued number.
        !          1099: \begin{quote}\index{gtime}\small\begin{verbatim}
        !          1100: long    gtime (tm)
        !          1101: struct tm *tm;
        !          1102: \end{verbatim}\end{quote}
        !          1103: The routine \verb"ut2tm" returns a pointer to a static time structure
        !          1104: which has been initialized by its \verb"UTC" argument.
        !          1105: \begin{quote}\index{ut2tm}\small\begin{verbatim}
        !          1106: struct tm *ut2tm (ut)
        !          1107: UTC     ut;
        !          1108: \end{verbatim}\end{quote}
        !          1109: Finally, the routine \verb"tm2ut" performs the inverse operation,
        !          1110: initializing a \verb"UTC" argument by using a time structure argument.
        !          1111: \begin{quote}\index{tm2ut}\small\begin{verbatim}
        !          1112: void     tm2ut (tm, ut)
        !          1113: struct tm *tm;
        !          1114: UTC     ut;
        !          1115: \end{verbatim}\end{quote}
        !          1116: 
        !          1117: \subsection    {Sets and Sequences}
        !          1118: Two list disciplines are implemented:
        !          1119: {\em sets}, in which each member is distinguished by a unique identifier;
        !          1120: and,
        !          1121: {\em sequences}, in which each element is distinguished by its offset from
        !          1122: the head of the list. It should be noted that these definitions of
        !          1123: sets and sequences do not exactly match those defined in ASN.1. In
        !          1124: particular, the ASN.1 structure \verb*"SET OF" must be defined as a
        !          1125: type \verb"SET", but be built up with the \verb"seq_add" construct,
        !          1126: as these elements all have the same type.
        !          1127: On both types of lists,
        !          1128: the macro \verb"first_member" returns the first member in the list,
        !          1129: while \verb"next_member" returns the next member.
        !          1130: These macros behave as if they were defined as:
        !          1131: \begin{quote}\index{first\_member}\index{next\_member}\small\begin{verbatim}
        !          1132: PE      first_member (head)
        !          1133: PE      head;
        !          1134: 
        !          1135: PE      next_member (head, member)
        !          1136: PE      head,
        !          1137:         member;
        !          1138: \end{verbatim}\end{quote}
        !          1139: There are three operations on sets:
        !          1140: \begin{describe}
        !          1141: \item[\verb"set\_add":] adds a new member to the set;
        !          1142: \begin{quote}\index{set\_add}\small\begin{verbatim}
        !          1143: int     set_add (pe, r)
        !          1144: PE      pe,
        !          1145:         r;
        !          1146: \end{verbatim}\end{quote}
        !          1147: The routine \verb"set_addon" is an efficient version of \verb"set_add" that
        !          1148: is used when adding several consecutive members to a set.\index{set\_addon}
        !          1149: 
        !          1150: \item[\verb"set\_del":] removes the identified member from the
        !          1151: set;
        !          1152: \begin{quote}\index{set\_del}\small\begin{verbatim}
        !          1153: int     set_del (pe, class, id)
        !          1154: PE      pe;
        !          1155: PElementClass class;
        !          1156: PElementID id;
        !          1157: \end{verbatim}\end{quote}
        !          1158: and,
        !          1159: 
        !          1160: \item[\verb"set\_find":] locates the identified member.
        !          1161: \begin{quote}\index{set\_find}\small\begin{verbatim}
        !          1162: PE      set_find (pe, class, id)
        !          1163: PE      pe;
        !          1164: PElementClass class;
        !          1165: PElementID id;
        !          1166: \end{verbatim}\end{quote}
        !          1167: \end{describe}
        !          1168: The routines \verb"prim2set" and \verb"set2prim" are used to translate between
        !          1169: presentation elements and sets.
        !          1170: \begin{quote}\index{prim2set}\index{set2prim}\small\begin{verbatim}
        !          1171: PE      prim2set (pe)
        !          1172: PE      pe;
        !          1173: 
        !          1174: PE      set2prim (pe)
        !          1175: PE      pe;
        !          1176: \end{verbatim}\end{quote}
        !          1177: In Figure~\ref{stepTHRUset},
        !          1178: a convenient way of stepping through all the members of a set is presented.
        !          1179: \tagrind[tp]{grind3-1}{Stepping through a Sequence}{stepTHRUset}
        !          1180: 
        !          1181: There are three operations on sequences:
        !          1182: \begin{describe}
        !          1183: \item[\verb"seq\_add":] adds a new member \verb"r" to the sequence
        !          1184: \verb"pe", at the given offset, an offset of \verb"-1" will add the
        !          1185: element to the end of the sequence;
        !          1186: \begin{quote}\index{seq\_add}\small\begin{verbatim}
        !          1187: int     seq_add (pe, r, offset)
        !          1188: PE      pe,
        !          1189:         r;
        !          1190: int     offset;
        !          1191: \end{verbatim}\end{quote}
        !          1192: The routine \verb"seq_addon" is an efficient version of \verb"seq_add" that
        !          1193: is used when adding several consecutive elements to a set.\index{seq\_addon}
        !          1194: 
        !          1195: \item[\verb"seq\_del":] removes the identified member from the
        !          1196: sequence;
        !          1197: \begin{quote}\index{seq\_del}\small\begin{verbatim}
        !          1198: int     seq_del (pe, offset)
        !          1199: PE      pe;
        !          1200: int     offset;
        !          1201: \end{verbatim}\end{quote}
        !          1202: and,
        !          1203: 
        !          1204: \item[\verb"seq\_find":] locates the identified element.
        !          1205: \begin{quote}\index{seq\_find}\small\begin{verbatim}
        !          1206: PE      seq_find (pe, offset)
        !          1207: PE      pe;
        !          1208: int     offset;
        !          1209: \end{verbatim}\end{quote}
        !          1210: \end{describe}
        !          1211: The routines \verb"prim2seq" and \verb"seq2prim" are used to translate between
        !          1212: presentation elements and sequences.
        !          1213: \begin{quote}\index{prim2seq}\index{prim2seq}\small\begin{verbatim}
        !          1214: PE      prim2seq (pe)
        !          1215: PE      pe;
        !          1216: 
        !          1217: PE      seq2prim (pe)
        !          1218: PE      pe;
        !          1219: \end{verbatim}\end{quote}
        !          1220: In Figure~\ref{stepTHRUsequence},
        !          1221: a convenient way of stepping through all the members of a sequence is
        !          1222: presented.
        !          1223: \tagrind[tp]{grind3-2}{Stepping through a Set}{stepTHRUsequence}
        !          1224: 
        !          1225: \section      {Inline CONStructors}
        !          1226: Please read the following important message.
        !          1227: \[\fbox{\begin{tabular}{lp{0.8\textwidth}}
        !          1228: \bf NOTE:&     The facilities described in this section are to be used only
        !          1229:                as a last resort.
        !          1230:                They are provided for compatibility with less-rich systems.
        !          1231: \end{tabular}}\]
        !          1232: 
        !          1233: When interfacing external software on top of various libraries,
        !          1234: such as \man librosap(3n),
        !          1235: the Remote Operations library,
        !          1236: arguments which are expected to be \verb"PElement"s may be available instead
        !          1237: as the raw encoded octets.
        !          1238: It is inefficent to convert this into a \verb"PElement",
        !          1239: pass the structure to the library,
        !          1240: which then just encodes it again.
        !          1241: To avoid this behavior,
        !          1242: the routine, \verb"str2pe", may be used:
        !          1243: \begin{quote}\index{str2pe}\small\begin{verbatim}
        !          1244: PE      str2pe (s, len, advance, result)
        !          1245: char   *s;
        !          1246: int     len,
        !          1247:        *advance,
        !          1248:        *result;
        !          1249: \end{verbatim}\end{quote}
        !          1250: The parameters to this procedure are:
        !          1251: \begin{describe}
        !          1252: \item[\verb"s"/\verb"len":] the encoded string (and its length);
        !          1253: 
        !          1254: \item[\verb"advance":] a pointer to an integer-valued location indicating
        !          1255: how far to advance the string to find the next ASN.1 object
        !          1256: (use the manifest constant \verb"NULLIP" if you aren't interested in this),
        !          1257: and,
        !          1258: 
        !          1259: \item[\verb"result":] a pointer to an integer-valued location which indicates,
        !          1260: if the call fails, the reason for the failure.
        !          1261: \end{describe}
        !          1262: On success,
        !          1263: \verb"str2pe" returns a \verb"PElement" called an {\em Inline CONStructor}.
        !          1264: This is a special kind of \verb"PElement" which really just contains a pointer
        !          1265: to the original string.
        !          1266: The underyling libraries now how to manipulate Inline CONStructors
        !          1267: appropriately,
        !          1268: e.g, when building an SSDU.
        !          1269: On failure,
        !          1270: \verb"str2pe" returns the manifest constant \verb"NULLPE" and the
        !          1271: \verb"result" parameter contains an error code listed in Table
        !          1272: Table~\ref{PStreamReasons} on page~\pageref{PStreamReasons}.
        !          1273: 
        !          1274: For the inverse operation,
        !          1275: the appropriate library must be informed that the ASN.1 objects associated
        !          1276: with incoming indications should be returned in Inline CONStructor form.
        !          1277: This mechanism is still being refined,
        !          1278: and is not currently documented.
        !          1279: 
        !          1280: However, the routine used by the libraries in order to unwrap an encoded
        !          1281: string is available:
        !          1282: \begin{quote}\index{qb2pe}\small\begin{verbatim}
        !          1283: PE      qb2pe (qb, len, depth, result)
        !          1284: struct qbuf *qb
        !          1285: int     len,
        !          1286:         depth,
        !          1287:        *result;
        !          1288: \end{verbatim}\end{quote}
        !          1289: The parameters to this procedure are:
        !          1290: \begin{describe}
        !          1291: \item[\verb"qb"/\verb"len":] a doubly-linked list of \verb"qbuf"s containing,
        !          1292: e.g., an SSDU, and the total length of the data in the \verb"qbuf"s;
        !          1293: 
        !          1294: \item[\verb"depth":] the level of unwrapping to permit;
        !          1295: and,
        !          1296: 
        !          1297: \item[\verb"result":] a pointer to an integer-valued location which indicates,
        !          1298: if the call fails, the reason for the failure.
        !          1299: \end{describe}
        !          1300: On success,
        !          1301: \verb"qb2pe" returns a \verb"PElement" which may ultimately contain
        !          1302: Inline CONStructors.
        !          1303: On failure,
        !          1304: \verb"qb2pe" returns the manifest constant \verb"NULLPE" and the
        !          1305: \verb"result" parameter contains an error code listed in Table
        !          1306: Table~\ref{PStreamReasons}.
        !          1307: 
        !          1308: \section      {Compiling and Loading}
        !          1309: Programs which manipulate presentation streams or presentation elements
        !          1310: should include the header file \verb"<isode/psap.h>".
        !          1311: These programs should also be loaded with \verb"-lpsap" which contains the
        !          1312: routines described in this chapter.
        !          1313: 
        !          1314: \section      {An Example}
        !          1315: Let's consider how one might read a presentation stream 
        !          1316: from the standard input.
        !          1317: The process is simple:
        !          1318: we create a new presentation stream and then start the loop which reads
        !          1319: from the stream until it is exhausted.
        !          1320: This is shown in Figure~\ref{stepTHRUpstream}.
        !          1321: In our example,
        !          1322: we assume that the routine \verb"error" results in the process being
        !          1323: terminated after printing a diagnostic.
        !          1324: \tagrind[tp]{grind3-3}{Stepping through a Presentation Stream}{stepTHRUpstream}
        !          1325: 
        !          1326: \section      {For Further Reading}
        !          1327: The language for the Abstract Syntax Notation One (ASN.1) is specified in
        !          1328: \cite{ISO.PP.Syntax} and \cite{CCITT.PP.Syntax},
        !          1329: while the encoding rules are defined in \cite{ISO.PP.Encoding} and
        !          1330: \cite{CCITT.PP.Syntax}.
        !          1331: The older {\oldstyle 1984} CCITT recommendations,
        !          1332: containing both definitions,
        !          1333: is \cite{MHS.notation},
        !          1334: which is often referred to as X.409.
        !          1335: The ASN.1 is a superset of the X.409.
        !          1336: 
        !          1337: %%% \section  {Changes Since the Last Release}\label{psap:changes}
        !          1338: %%% A brief summary of the major changes between v~\psaprevrsn/ and
        !          1339: %%% v~\psapvrsn/ are now presented.
        !          1340: %%% These are the user-visible changes only;
        !          1341: %%% changes of a strictly internal nature are not discussed.
        !          1342: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.