home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / gened10.zip / SAMPLE2.C < prev    next >
Text File  |  1996-04-03  |  33KB  |  906 lines

  1. /*
  2.  *      Created 1993  IBM Corp.                                            *
  3.  *                                                                         *
  4.  *      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is        *
  5.  *      sample code created by IBM Corporation. This sample code is not    *
  6.  *      part of any standard or IBM product and is provided to you solely  *
  7.  *      for  the purpose of assisting you in the development of your       *
  8.  *      applications.  The code is provided "AS IS", without               *
  9.  *      warranty of any kind.  IBM shall not be liable for any damages     *
  10.  *      arising out of your use of the sample code, even if they have been *
  11.  *      advised of the possibility of such damages.                        *
  12.  */
  13. /**************************************************************************
  14.  * encode/decode sample program for TEST2.ASN. It uses:
  15.  * - the encoding user exit
  16.  * - the GDS tree pointers-array
  17.  * - the BER type of encoding (with definite length form)
  18.  * - content user-exits for some fields
  19.  *
  20.  * ARGUMENTS:
  21.  * 1. the path and name of the .DAT file
  22.  * 2. the input buffer length
  23.  * 3. the output buffer length
  24.  *
  25.  * This program encodes and decodes a data stream on the basis of TEST2.ASN
  26.  * definitions. The data stream is written/read in/from the file: STREAM4.OUT.
  27.  * Two traces file are generated:
  28.  * 1.enctrace4.out, for the trace of the encoded GDS tree
  29.  * 2.dectrace4.out, for the trace of the decoded GDS tree
  30.  **************************************************************************
  31.  */
  32.  
  33. /*
  34.  * The following are needed to compile this program.  Note that the
  35.  * order of the header files is important.
  36.  */
  37.  
  38. #include <stdlib.h>
  39. #include <stdio.h>
  40. #include <ctype.h>
  41. #include <string.h>
  42. #include "gdstypes.h"
  43. #include "gdsrcods.h"
  44. #include "gdsproto.h"
  45. #include "sample2.h"
  46. #include "test2ndx.h"
  47.  
  48. main(int argc, char **argv)
  49. {
  50.    int                   rc;
  51.    char                  savmodname[50], *ModName, *out_buff, *in_buff, alldata;
  52.    unsigned long         EncBytes;     /* number of encoded bytes */
  53.    unsigned long         DecBytes;     /* number of decoded bytes */
  54.    unsigned long         inbuflen;     /* input buffer length (bytes) */
  55.    unsigned long         outbuflen;    /* output buffer length (bytes) */
  56.    unsigned short        Typ;          /* type index */
  57.    void                 *Mod;          /* module pointer */
  58.    void                 *env;          /* environment pointer */
  59.    struct gds           *p1;           /* GDS structure tree pointer */
  60.    struct usrpstruct     usrp;         /* user parms */
  61.    enum TypOfEnc         enctype;      /* encoding type */
  62.    FILE                 *trace_enc;    /* file for encoded GDS tree trace */
  63.    FILE                 *trace_dec;    /* file for decoded GDS tree trace */
  64.    FILE                 *EncStream;    /* output file */
  65.    FILE                 *usrdecfile;   /* user-exit decoding routine output
  66.                                         * file */
  67.  
  68.  
  69. /*
  70.  * check if the number of arguments is correct
  71.  */
  72.    if (argc < 4) {
  73.       exit(0);
  74.    }
  75.  
  76. /*
  77.  * set the type of encoding
  78.  */
  79.    enctype = ber;
  80.  
  81.    inbuflen = atol(argv[2]);           /* set the length of the input buffer */
  82.    outbuflen = atol(argv[3]);          /* set the length of output buffer */
  83.  
  84.  
  85. /*
  86.  * open the trace file for the encoded gds tree
  87.  */
  88.    trace_enc = fopen("enctrace4.out","w");
  89.    if (trace_enc == NULL) {            /* open file failed */
  90.      printf("open enc trace file failed\n");
  91.      exit(-1);
  92.    } /* endif */
  93.  
  94. /*
  95.  * open the trace file for the decoded gds tree
  96.  */
  97.    trace_dec = fopen("dectrace4.out","w");
  98.    if (trace_dec == NULL) {            /* open file failed */
  99.      printf("open dec trace file failed\n");
  100.      exit(-1);
  101.    } /* endif */
  102.  
  103. /*
  104.  * open the input/output file that will contain the encoded data stream
  105.  */
  106.    EncStream = fopen("stream4.out","wb");
  107.    if (EncStream == NULL) {            /* open file failed */
  108.      printf("open input/output file failed\n");
  109.      exit(-1);
  110.    } /* endif */
  111.  
  112.  
  113. /****************************
  114.  * INITIALIZE the environment
  115.  ****************************
  116.  */
  117.  
  118. /*
  119.  * Call the library routine, GDSinitEnvironment, to initialize the environment.
  120.  * Each application program has to do this before calling any routine to
  121.  * read .dat files, encode or decode GDSs.
  122.  */
  123.    GDSinitEnvironment(&env);      /* initialize environment for modules */
  124.  
  125. /*
  126.  * Call the library routine, GDSreaddatfile, to read a .dat file containing
  127.  * the metatables and symbol tables for one or more ASN.1 module.  Note that
  128.  * references between ASN.1 modules (imported and exported symbols) are *not*
  129.  * resolved by GDSreaddatfile.
  130.  */
  131.    rc = GDSreaddatfile(argv[1], env);  /* first parm should be a readable data
  132.                                         * file */
  133.    if (rc != READ_DAT_OK) {
  134.      printf("GDSreaddatfile return code: %i\n", rc);
  135.      exit(rc);
  136.    }
  137.  
  138. /*
  139.  * Call the library routine, GDSsetUsrWrite, to set the user exit routine for
  140.  * writing buffer.
  141.  */
  142.    GDSsetUsrWrite(mywrite, env);
  143.  
  144. /*
  145.  * Call the library routine, GDSsetUsrRead, to set the user exit routine for
  146.  * reading buffer.
  147.  */
  148.    GDSsetUsrRead(myread, env);
  149.  
  150. /*
  151.  * Call the library routine, GDSsetUsrEnc, to set the user exit routine for
  152.  * encoding.  In this program, it is set to encMIU the first time. However,
  153.  * it is called many times later, to change the encoding routine.
  154.  */
  155.    GDSsetUsrEnc(encMIU, env);
  156.  
  157.  
  158. /*
  159.  * Call the library routine, GDSfindmodule, to find the moddef structure
  160.  * corresponding to the "Miu" module.
  161.  */
  162.    Mod = GDSfindmodule("Miu", env);
  163.    if (Mod == NULL) {             /* if module not found */
  164.      printf("\nModule not found\n");
  165.      exit(-1);
  166.    }
  167.  
  168.    printf("\nInitialization OK\n");
  169.  
  170. /****************************
  171.  * ENCODING
  172.  ****************************
  173.  */
  174.    printf("\nStart Encoding\n");
  175.  
  176.    usrp.env = env;                /* set the user parm */
  177.  
  178.    Typ = Miu_MIU;                 /* the type to be encoded */
  179. /*
  180.  * Call the library routine, GDSencode, to create one or more GDS structures
  181.  * that represent a value for Mod.Typ.  The user encode exit is called
  182.  * during this process to provide the necessary values for the
  183.  * ASN.1 type. The last parm is the address of a structure with data
  184.  * to be passed to the user encode exit.  Applications
  185.  * use this to pass local parameters to the user encode routine.  This is
  186.  * useful when the the User Application Program (this routine) and the exit
  187.  * routine must share data.
  188.  *
  189.  * Note that the GDSencode function does *not* create the BER encoded
  190.  * data.  The GDS structures contain the information needed to
  191.  * encode the data, but the actual encoding is a secondary step.  This
  192.  * allows other encoding techniques besides BER to be used.  The
  193.  * log component of the GDS structure is computed by GDSencode assuming
  194.  * BER rules (this is a slight optimization that prevents traversing
  195.  * the GDS structure tree another time); if GDSencber is not used to encode
  196.  * the data, the log component should not be used.
  197.  */
  198.    rc = GDSencode(Mod,            /* moddef module where type occurs */
  199.                   &Typ,           /* metatable index where type occurs */
  200.                   NULL,           /* pointer to Contents Array, not used */
  201.                   &p1,            /* returned GDS structure */
  202.                   enctype,        /* type of encoding */
  203.                   env,            /* environment */
  204.                   &usrp           /* parms to pass to the user encode
  205.                                    * routine */
  206.                  );
  207.  
  208.    if (rc != ENCODE_MATCH) {      /* if the encoding failed */
  209.      printf("\nGDSencode return code: %i\n", rc);
  210.      printf("\nmetatable type index where error occurred: %i\n", Typ);
  211.      exit(rc);
  212.    }    /* endif */
  213.  
  214. /*
  215.  * Call the library routine, GDSencber, to encode the GDS structure tree
  216.  * using BER rules.
  217.  */
  218.    rc = GDSencber(&p1,            /* the GDS structure tree to be encoded */
  219.                   outbuflen,      /* the length of the output buffer */
  220.                   &out_buff,      /* output buffer pointer */
  221.                   &EncBytes,      /* the number of encoded bytes */
  222.                   0,              /* definite length form */
  223.                   env,            /* environment */
  224.                   (void *) EncStream /* pointer to the output file. It will
  225.                                    * be passed by GDSencber to the writing
  226.                                    * user-exit */
  227.                   );
  228.  
  229.    if (rc != ENCBER_OK) {         /* if encoding was unsuccessful */
  230.      printf("\nGDSencber return code: %i\n", rc);
  231.      printf("module name: %s\n", p1->modname);
  232.      printf("type name: %s\n", p1->name);
  233.      GDSfreegds(p1, env);         /* reclaim space for encoded GDS struct */
  234.      exit(rc);
  235.    }  /* endif */
  236.  
  237.    printf("\nnumber of encoded bytes: %lu\n", EncBytes);
  238.  
  239.  
  240. /*
  241.  * Call the library routine, GDSprintgds, to print the encoded GDS
  242.  * structure and its contents.
  243.  */
  244.    rc = GDSprintgds(p1,           /* ptr to root GDS structure */
  245.                     0,            /* number of spaces to indent */
  246.                     300,          /* max content length */
  247.                     80,           /* number of characters for row */
  248.                     trace_enc,    /* gds tree trace file */
  249.                     enctype       /* type of encoding */
  250.                    );
  251.  
  252.    if (rc != PRINT_GDS_OK) {      /* if the printing failed */
  253.       printf("\nGDSprintgds return code: %i\n", rc);
  254.       GDSfreegds(p1, env);        /* reclaim space for encoded GDS struct */
  255.       exit(rc);
  256.    }    /* endif */
  257.  
  258.    fclose(trace_enc);             /* close the trace file */
  259.  
  260.    fclose(EncStream);
  261.  
  262.    if (out_buff != NULL) free(out_buff);
  263.  
  264.    EncStream = fopen("stream4.out","rb"); /*  reopen the file for reading */
  265.    if (EncStream == NULL) {       /* open file failed */
  266.      printf("\nopen input/output file failed\n");
  267.      exit(-1);
  268.    } /* endif */
  269.  
  270. /*
  271.  * Call the library routine, GDSfreegds, to reclaim the storage occupied by
  272.  * the GDS structures headed by p1 which are marked as allocated.  Note
  273.  * that some GDSs may be marked as static, which prevents them from
  274.  * being freed.
  275.  */
  276.    GDSfreegds(p1, env);
  277.  
  278.    printf("\nEnd Encoding\n");
  279.  
  280. /****************************
  281.  * DECODING
  282.  ****************************
  283.  */
  284.  
  285.    printf("\nStart Decoding\n");
  286. /*
  287.  * Call the library routine, GDSdecber, to decode encoded data in the
  288.  * buffer we just built. The result should be a tree of GDS structures
  289.  * topped by p1 which matches the original structure created by the
  290.  * encode library routine.
  291.  */
  292.    alldata = 0;
  293.    in_buff = &alldata;
  294.    rc = GDSdecber(&p1,            /* pointer to the root of the GDS tree */
  295.                   inbuflen,       /* the length of the input buffer */
  296.                   &DecBytes,      /* number of decoded bytes */
  297.                   &in_buff,       /* data buffered indicator */
  298.                   env,            /* environment */
  299.                   (void *) EncStream /* pointer to the input file. It will
  300.                                    * be passed by GDSdecber to the writing
  301.                                    * user-exit */
  302.                   );
  303.  
  304.    if (rc != DECBER_OK) {         /* if decoding failed */
  305.      printf("\nGDSdecber return code: %i\n", rc);
  306.      printf("\nnumber of decoded bytes: %u\n", DecBytes);
  307.      GDSfreegds(p1, env);         /* reclaim space for encoded GDS struct */
  308.      exit(rc);
  309.    }
  310.  
  311.    printf("\nnumber of decoded bytes: %u\n", DecBytes);
  312.  
  313. /*
  314.  * Call the library routine, GDSprintgds, to print the structure and
  315.  * content of the decoded GDS. At this point, before GDSdecode call,
  316.  * the GDS structure tree is missing of some information (names,
  317.  * base types...) and it is not matched with the ASN.1 type.
  318.  */
  319.    rc = GDSprintgds(p1,           /* ptr to root GDS structure */
  320.                     0,            /* number of spaces to indent */
  321.                     300,          /* max content length */
  322.                     80,           /* number of characters for row */
  323.                     trace_dec,    /* gds tree trace file */
  324.                     enctype       /* type of encoding */
  325.                    );
  326.  
  327.    if (rc != PRINT_GDS_OK) {      /* if the printing failed */
  328.      printf("\nGDSprintgds return code: %i\n", rc);
  329.      GDSfreegds(p1, env);         /* reclaim space for encoded GDS struct */
  330.      exit(rc);
  331.    }    /* endif */
  332.  
  333. /*
  334.  * Call the library routine, GDSdecode, to match the GDS structure tree
  335.  * created by GDSdecber with the ASN.1 type referenced by Mod and Typ.
  336.  * If successful, the GDS structures will have name information set.
  337.  */
  338.    Typ = Miu_MIU;                 /* the type to be decoded */
  339.  
  340.    rc = GDSdecode(Mod,            /* module where type occurs */
  341.                   &Typ,           /* Metatable index where type occurs */
  342.                   &p1,            /* root of GDS structure tree */
  343.                   NULL,           /* pointer to the GDS tree pointers array */
  344.                   env,            /* environment */
  345.                   NULL            /* user parms, not used in this case */
  346.                   );
  347.  
  348.    if (rc != DECODE_MATCH) {      /* if decoding didn't go ok */
  349.      printf("\nGDSdecode return code: %i\n", rc);
  350.      printf("Metatable type index where error occurred: %i\n", Typ);
  351.      printf("module name: %s\n", p1->modname);
  352.      printf("type name: %s\n", p1->name);
  353.      GDSfreegds(p1, env);         /* reclaim space for encoded GDS struct */
  354.      exit(rc);
  355.    }   /* endif */
  356.  
  357. /*
  358.  * Call the library routine, GDSprintgds, to print the structure and
  359.  * content of the decoded GDS tree.
  360.  */
  361.    rc = GDSprintgds(p1,             /* ptr to root GDS structure */
  362.                     0,              /* number of spaces to indent */
  363.                     300,            /* max content length */
  364.                     80,             /* number of characters for row */
  365.                     trace_dec,      /* gds tree trace file */
  366.                     enctype         /* type of encoding */
  367.                    );
  368.  
  369.    if (rc != PRINT_GDS_OK) {        /* if the printing failed */
  370.      printf("\nGDSprintgds return code: %i\n", rc);
  371.      GDSfreegds(p1, env);
  372.      exit(rc);
  373.    }    /* endif */
  374.  
  375.    fclose(EncStream);
  376.  
  377. /*
  378.  * Call the library routine to free the GDS structures in the tree rooted
  379.  * by *p1.
  380.  */
  381.    GDSfreegds(p1, env);
  382.  
  383.    printf("\nEnd Decoding\n");
  384.  
  385. /****************************
  386.  * CLEAN UP the environment
  387.  ****************************
  388.  */
  389. /*
  390.  * Clean up the environment by unloading all modules by calling
  391.  * GDSunloadmodule for each module in the environment.  NOTE:
  392.  * the GDSunloadmodule function should only be called for modules which
  393.  * were loaded by the GDSreaddatfile function or which have allocated
  394.  * storage in the heap like the GDSreaddatfile function.
  395.  */
  396.  
  397.    for (GDSfirstmodule(&Mod, &ModName, env); Mod != NULL;
  398.         GDSfirstmodule(&Mod, &ModName, env)) {
  399.       GDSunloadmodule(Mod, env);
  400.    } /* endfor */
  401.  
  402. /*
  403.  * Call the library routine GDSfreeEnvironment to free the storage
  404.  * allocated for the current environment
  405.  */
  406.    GDSfreeEnvironment(env);
  407.  
  408.    return 0;
  409. }  /* end main */
  410.  
  411.  
  412. /*
  413.  * writing user-exit
  414.  */
  415. unsigned long mywrite(char *buf, unsigned long buflen, void *usrparms)
  416. {
  417.   FILE *EncStream;
  418.  
  419.   EncStream = (FILE *) usrparms;
  420.   return (unsigned long) (fwrite(buf,sizeof(unsigned char),buflen,EncStream));
  421. }
  422.  
  423. /*
  424.  * reading user-exit
  425.  */
  426. unsigned long myread(char *buf, unsigned long buflen, void *usrparms)
  427. {
  428.   FILE *EncStream;
  429.  
  430.   EncStream = (FILE *) usrparms;
  431.   return (unsigned long) (fread(buf,sizeof(unsigned char),buflen,EncStream));
  432. }
  433.  
  434. /*
  435.  * encMIU encoding user exit, the first to be called
  436.  */
  437. int
  438. encMIU(struct encinh ia,               /* inherited attrs */
  439.       struct encinhsyn *sa,            /* synthesized and inherited attrs */
  440.       enum tagclass cls,               /* class of item to encode */
  441.       long id,                         /* id of class to encode */
  442.       enum frm form,                   /* form (prim or constr) of data to encode */
  443.       char *encsubs                    /* set to !0 to encode contained types */
  444.       )
  445. {
  446.   int                rc;
  447.   struct usrpstruct *usrparms;
  448.  
  449.   rc = ENCODE_MATCH;
  450.   usrparms = (struct usrpstruct *) ia.usrparms;
  451.   *encsubs = 1;                   /* encode contained types */
  452.   switch (sa->ndx) {
  453.   case Miu_MIU_SEQUENCE:
  454.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  455.                    form, NULL, 0L, allocd, NULL, usrparms->env);
  456.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  457.     break;
  458.   case Miu_ALH:
  459.     GDSsetUsrEnc(encALH, usrparms->env);  /* set the encoding user-exit for ALH */
  460.     break;
  461.   case Miu_RSH:
  462.     GDSsetUsrEnc(encRSH, usrparms->env);  /* set the encoding user-exit for RSH */
  463.     break;
  464.   case Miu_CSH:
  465.     rc = ENCODE_NO_MATCH;         /* don't encode CSH */
  466.     break;
  467.   case Miu_AGD:
  468.     GDSsetUsrEnc(encAGD, usrparms->env);  /* set the encoding user-exit for AGD */
  469.     break;
  470.   case Miu_APD:
  471.     rc = ENCODE_NO_MATCH;         /* don't encode APD */
  472.     break;
  473.   }  /* endswitch */
  474.   return rc;
  475. }  /* end encMIU */
  476.  
  477. /*
  478.  * encALH encoding user exit, for ALH type
  479.  */
  480. int
  481. encALH(struct encinh ia,           /* inherited attrs */
  482.        struct encinhsyn *sa,       /* synthesized and inherited attrs */
  483.        enum tagclass cls,          /* class of item to encode */
  484.        long id,                    /* id of class to encode */
  485.        enum frm form,              /* form (prim or constr) of data to encode */
  486.        char *encsubs               /* set to !0 to encode contained types */
  487.        )
  488. {
  489.   int                rc;
  490.   char              *contents;
  491.   static int         pass = 0;
  492.   struct usrpstruct *usrparms;
  493.  
  494.   usrparms = (struct usrpstruct *) ia.usrparms;
  495.   *encsubs = 1;                        /* encode contained types */
  496.   rc = ENCODE_MATCH;
  497.   contents = NEW(char);
  498.   switch (sa->ndx) {
  499.   case Miu_ALH_SEQUENCE:
  500.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  501.                    form, NULL, 0L, allocd, NULL, usrparms->env);
  502.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  503.     break;
  504.   case Miu_BYTES_OCTET_STRING:
  505.     if (pass)                          /* globalcsid: 'BB'H */
  506.       GDSstr2hex(contents, 1, "BB", 2);
  507.     else                               /* archlevel: 'AA'H */
  508.       GDSstr2hex(contents, 1, "AA", 2);
  509.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  510.                    form, contents, 1L, allocd, NULL, usrparms->env);
  511.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  512.     pass++;
  513.     break;
  514.   default:
  515.    break;
  516.   } /* endswitch */
  517.   return rc;
  518. }  /* encALH */
  519.  
  520. /*
  521.  * encRSH encoding user exit, for RSH type
  522.  */
  523. int
  524. encRSH(struct encinh ia,           /* inherited attrs */
  525.        struct encinhsyn *sa,       /* synthesized and inherited attrs */
  526.        enum tagclass cls,          /* class of item to encode */
  527.        long id,                    /* id of class to encode */
  528.        enum frm form,              /* form (prim or constr) of data to encode */
  529.        char *encsubs               /* set to !0 to encode contained types */
  530.        )
  531. {
  532.   int                rc;
  533.   char              *contents;
  534.   static int         pass = 0;
  535.   struct usrpstruct *usrparms;
  536.  
  537.   usrparms = (struct usrpstruct *) ia.usrparms;
  538.   *encsubs = 1;                        /* encode contained types */
  539.   rc = ENCODE_MATCH;
  540.   contents = NEW(char);
  541.   switch (sa->ndx) {
  542.   case Miu_RSH_SEQUENCE:
  543.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  544.                    form, NULL, 0L, allocd, NULL, usrparms->env);
  545.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  546.     break;
  547.   case Miu_BYTES_OCTET_STRING:
  548.     switch(pass) {
  549.     case 0:                            /* msflags: '00'H */
  550.       GDSstr2hex(contents, 1, "00", 2);
  551.       break;
  552.     case 1:                            /* ssflags: '01'H */
  553.       GDSstr2hex(contents, 1, "01", 2);
  554.       break;
  555.     case 2:                            /* mshopcount: '02'H */
  556.       GDSstr2hex(contents, 1, "02", 2);
  557.       break;
  558.     case 3:                            /* swhopcount:  */
  559.       rc = ENCODE_NO_MATCH;            /* don't encode it */
  560.       break;
  561.     } /* endswitch */
  562.     if (rc == ENCODE_MATCH) {
  563.       rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  564.                      form, contents, 1L, allocd, NULL, usrparms->env);
  565.       rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  566.     } /* endif */
  567.     pass++;
  568.     break;
  569.   case Miu_MSGCLASS:
  570.     GDSsetUsrEnc(encMSGCLASS, usrparms->env); /* set encoding user-exit for MSGCLASS */
  571.     break;
  572.   case Miu_NAPS:
  573.     GDSsetUsrEnc(encDESTNAPS, usrparms->env); /* set the encoding user-exit for DESTNAPS */
  574.     break;
  575.   case Miu_AGENT:
  576.     rc = ENCODE_NO_MATCH;           /* don't encode MONITORAGENT */
  577.     break;
  578.   default:
  579.    break;
  580.   } /* endswitch */
  581.   return rc;
  582. }  /* encRSH */
  583.  
  584. /*
  585.  * encAGD encoding user exit, for AGD
  586.  */
  587. int
  588. encAGD(struct encinh ia,           /* inherited attrs */
  589.        struct encinhsyn *sa,       /* synthesized and inherited attrs */
  590.        enum tagclass cls,          /* class of item to encode */
  591.        long id,                    /* id of class to encode */
  592.        enum frm form,              /* form (prim or constr) of data to encode */
  593.        char *encsubs               /* set to !0 to encode contained types */
  594.        )
  595. {
  596.   int                rc;
  597.   char              *contents;
  598.   static int         pass = 0;
  599.   struct usrpstruct *usrparms;
  600.  
  601.   usrparms = (struct usrpstruct *) ia.usrparms;
  602.   *encsubs = 1;                        /* encode contained types */
  603.   rc = ENCODE_MATCH;
  604.   contents = NEW2(8, char);
  605.   switch (sa->ndx) {
  606.   case Miu_AGD_SEQUENCE:
  607.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  608.                    form, NULL, 0L, allocd, NULL, usrparms->env);
  609.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  610.     break;
  611.   case Miu_BYTES_OCTET_STRING:
  612.     if (!pass) {                       /* mapname: '0011223344'H */
  613.       GDSstr2hex(contents, 5, "0011223344", 10);
  614.       rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  615.                      form, contents, 5L, allocd, NULL, usrparms->env);
  616.     } else {                              /* agentdata: 'AA'H */
  617.       /* use the agentdata_cont user-exit */
  618.       rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  619.                      form, NULL, 5000L, allocd, agentdata_cont, usrparms->env);
  620.     } /* endif */
  621.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  622.     pass++;
  623.     break;
  624.   default:
  625.    break;
  626.   } /* endswitch */
  627.   return rc;
  628. }  /* encAGD */
  629.  
  630. /*
  631.  * encMSGCLASS encoding user exit, for MSGCLASS
  632.  */
  633. int
  634. encMSGCLASS(struct encinh ia,         /* inherited attrs */
  635.             struct encinhsyn *sa,     /* synthesized and inherited attrs */
  636.             enum tagclass cls,        /* class of item to encode */
  637.             long id,                  /* id of class to encode */
  638.             enum frm form,            /* form (prim or constr) of data to encode */
  639.             char *encsubs             /* set to !0 to encode contained types */
  640.             )
  641. {
  642.   int                rc;
  643.   char               *contents;
  644.   static int         pass = 0;
  645.   int                contlen;
  646.   struct usrpstruct *usrparms;
  647.  
  648.   usrparms = (struct usrpstruct *) ia.usrparms;
  649.   *encsubs = 1;                        /* encode contained types */
  650.   rc = ENCODE_MATCH;
  651.   contents = NEW2(8, char);
  652.   switch (sa->ndx) {
  653.   case Miu_NAME8_SEQUENCE:
  654.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  655.                    form, NULL, 0L, allocd, NULL, usrparms->env);
  656.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  657.     break;
  658.   case Miu_BYTES_OCTET_STRING:
  659.     switch(pass) {
  660.     case 0:                            /* nametype: '001122'H */
  661.       GDSstr2hex(contents, 3, "001122", 6);
  662.       contlen = 3;
  663.       break;
  664.     case 1:                            /* namestring: '0011223344556677'H */
  665.       GDSstr2hex(contents, 8, "0011223344556677", 16);
  666.       contlen = 8;
  667.       break;
  668.     } /* endswitch */
  669.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  670.                    form, contents, contlen, allocd, NULL, usrparms->env);
  671.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  672.     pass++;
  673.     break;
  674.   default:
  675.    break;
  676.   } /* endswitch */
  677.   return rc;
  678. }  /* encMSGCLASS */
  679.  
  680. /*
  681.  * encDESTNAPS encoding user exit, for DESTNAPS
  682.  */
  683. int
  684. encDESTNAPS(struct encinh ia,         /* inherited attrs */
  685.         struct encinhsyn *sa,     /* synthesized and inherited attrs */
  686.         enum tagclass cls,        /* class of item to encode */
  687.         long id,                  /* id of class to encode */
  688.         enum frm form,            /* form (prim or constr) of data to encode */
  689.         char *encsubs             /* set to !0 to encode contained types */
  690.         )
  691. {
  692.   int                rc;
  693.   struct usrpstruct *usrparms;
  694.  
  695.   usrparms = (struct usrpstruct *) ia.usrparms;
  696.   *encsubs = 1;                        /* encode contained types */
  697.   rc = ENCODE_MATCH;
  698.   switch (sa->ndx) {
  699.   case Miu_NAPS_SEQUENCE:
  700.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  701.                    form, NULL, 0L, allocd, NULL, usrparms->env);
  702.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  703.     break;
  704.   case Miu_NODE:
  705.     GDSsetUsrEnc(encNODENAME, usrparms->env); /* set encoding user-exit for NODENAME */
  706.     break;
  707.   case Miu_AGENT:
  708.     GDSsetUsrEnc(encAGENTNAME, usrparms->env); /* set the encoding user-exit for AGENTNAME */
  709.     break;
  710.   case Miu_NAPS:
  711.     rc = ENCODE_NO_MATCH;          /* don't encode TRAILER */
  712.     break;
  713.   default:
  714.    break;
  715.   } /* endswitch */
  716.   return rc;
  717. }  /* encDESTNAPS */
  718.  
  719. /*
  720.  * encNODENAME encoding user exit, for NODENAME
  721.  */
  722. int
  723. encNODENAME(struct encinh ia,    /* inherited attrs */
  724.        struct encinhsyn *sa,     /* synthesized and inherited attrs */
  725.        enum tagclass cls,        /* class of item to encode */
  726.        long id,                  /* id of class to encode */
  727.        enum frm form,            /* form (prim or constr) of data to encode */
  728.        char *encsubs             /* set to !0 to encode contained types */
  729.        )
  730. {
  731.   int                rc;
  732.   char              *contents;
  733.   static int         pass = 0;
  734.   int                contlen;
  735.   struct usrpstruct *usrparms;
  736.  
  737.   usrparms = (struct usrpstruct *) ia.usrparms;
  738.   *encsubs = 1;                        /* encode contained types */
  739.   rc = ENCODE_MATCH;
  740.   contents = NEW2(20, char);
  741.   switch (sa->ndx) {
  742.   case Miu_NAME64_SEQUENCE:
  743.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  744.                    form, NULL, 0L, allocd, NULL, usrparms->env);
  745.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  746.     break;
  747.   case Miu_BYTES_OCTET_STRING:
  748.     switch(pass) {
  749.     case 0:                            /* nametype: '001122'H */
  750.       GDSstr2hex(contents, 3, "001122", 6);
  751.       contlen = 3;
  752.       break;
  753.     case 1:                        /* namestring: '00112233445566778899...'H */
  754.       GDSstr2hex(contents, 20, "0011223344556677889900112233445566778899", 40);
  755.       contlen = 20;
  756.       break;
  757.     } /* endswitch */
  758.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  759.                    form, contents, contlen, allocd, NULL, usrparms->env);
  760.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  761.     pass++;
  762.     break;
  763.   default:
  764.    break;
  765.   } /* endswitch */
  766.   return rc;
  767. }  /* encNODENAME */
  768.  
  769. /*
  770.  * encAGENTNAME encoding user exit, for AGENTNAME
  771.  */
  772. int
  773. encAGENTNAME(struct encinh ia,   /* inherited attrs */
  774.        struct encinhsyn *sa,     /* synthesized and inherited attrs */
  775.        enum tagclass cls,        /* class of item to encode */
  776.        long id,                  /* id of class to encode */
  777.        enum frm form,            /* form (prim or constr) of data to encode */
  778.        char *encsubs             /* set to !0 to encode contained types */
  779.        )
  780. {
  781.   int                rc;
  782.   struct usrpstruct *usrparms;
  783.  
  784.   usrparms = (struct usrpstruct *) ia.usrparms;
  785.   *encsubs = 1;                        /* encode contained types */
  786.   rc = ENCODE_MATCH;
  787.   switch (sa->ndx) {
  788.   case Miu_AGENT_SEQUENCE:
  789.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  790.                    form, NULL, 0L, allocd, NULL, usrparms->env);
  791.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  792.     break;
  793.   case Miu_NAME64:                 /* agentname */
  794.     GDSsetUsrEnc(encNAME64, usrparms->env);  /* set the encoding user-exit for NAME64 */
  795.     break;
  796.   case Miu_BYTES_OCTET_STRING:     /* agentparm */
  797.     rc = ENCODE_NO_MATCH;          /* don't encode it */
  798.     break;
  799.   default:
  800.    break;
  801.   } /* endswitch */
  802.   return rc;
  803. }  /* encAGENTNAME */
  804.  
  805. /*
  806.  * encNAME64 encoding user exit, for NAME64
  807.  */
  808. int
  809. encNAME64(struct encinh ia,        /* inherited attrs */
  810.        struct encinhsyn *sa,     /* synthesized and inherited attrs */
  811.        enum tagclass cls,        /* class of item to encode */
  812.        long id,                  /* id of class to encode */
  813.        enum frm form,            /* form (prim or constr) of data to encode */
  814.        char *encsubs             /* set to !0 to encode contained types */
  815.        )
  816. {
  817.   int                rc;
  818.   char              *contents;
  819.   static int         pass = 0;
  820.   int                contlen;
  821.   struct usrpstruct *usrparms;
  822.  
  823.   usrparms = (struct usrpstruct *) ia.usrparms;
  824.   *encsubs = 1;                        /* encode contained types */
  825.   rc = ENCODE_MATCH;
  826.   contents = NEW2(20, char);
  827.   switch (sa->ndx) {
  828.   case Miu_NAME64_SEQUENCE:
  829.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  830.                    form, NULL, 0L, allocd, NULL, usrparms->env);
  831.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  832.     break;
  833.   case Miu_BYTES_OCTET_STRING:
  834.     switch(pass) {
  835.     case 0:                        /* nametype: '334455'H */
  836.       GDSstr2hex(contents, 3, "334455", 6);
  837.       contlen = 3;
  838.       break;
  839.     case 1:                        /* namestring: '00112233445566778899'H */
  840.       GDSstr2hex(contents, 10, "00112233445566778899", 20);
  841.       contlen = 10;
  842.       break;
  843.     } /* endswitch */
  844.     rc = GDSnewgds(&(sa->p), ia.modname, ia.symname, ia.it, cls, id,
  845.                    form, contents, contlen, allocd, NULL, usrparms->env);
  846.     rc = (rc != NEWGDS_OK) ? rc : ENCODE_MATCH;
  847.     pass++;
  848.     break;
  849.   default:
  850.    break;
  851.   } /* endswitch */
  852.   return rc;
  853. }  /* encNAME64 */
  854.  
  855. /*
  856.  * content user-exit, agentdata_cont
  857.  */
  858. int agentdata_cont (char **buff, unsigned long *buflen, enum lastflag *lastf)
  859. {
  860.   unsigned char buffer[2000];
  861.   static unsigned char hexbuff[1000];
  862.   int rc = 0, i;
  863.   static int  pass = 0;
  864.  
  865.   /* pass the 5000 bytes of the content of AGD.agentdata in pieces of 1000
  866.    * bytes. This is only an example, a content user-exit could be get
  867.    * the data from any other places.
  868.    */
  869.   *buflen = 1000;
  870.   *lastf = NO;
  871.   switch (pass) {
  872.   case 0:                       /* first piece */
  873.     for (i=0;i<2000;i++) {
  874.       buffer[i] = 'A';
  875.     } /* endfor */
  876.     break;
  877.   case 1:                       /* second piece */
  878.     for (i=0;i<2000;i++) {
  879.       buffer[i] = 'B';
  880.     } /* endfor */
  881.     break;
  882.   case 2:                       /* third piece */
  883.     for (i=0;i<2000;i++) {
  884.       buffer[i] = 'C';
  885.     } /* endfor */
  886.     break;
  887.   case 3:                       /* fourth piece */
  888.     for (i=0;i<2000;i++) {
  889.       buffer[i] = 'D';
  890.     } /* endfor */
  891.     break;
  892.   case 4:                       /* fifth piece */
  893.     for (i=0;i<2000;i++) {
  894.       buffer[i] = 'E';
  895.     } /* endfor */
  896.     *lastf = YES;
  897.     break;
  898.   default:
  899.    break;
  900.   } /* endswitch */
  901.   GDSstr2hex(hexbuff, 1000, buffer, 2000);
  902.   *buff = hexbuff;
  903.   pass++;
  904.   return rc;
  905. }
  906.