|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.