*DECK XDRSTR
USETEXT TEXTXDR 
      PROC XDRSTR (BUFFER, BUFPOS, STRING, STRLEN, OPERATION);
*CALL COPYRITE          CDCNET - COPYRIGHT CONTROL DATA. 1992.
# TITLE XDRSTR  CONVERT BETWEEN DISPLAY AND ASCII IN XDR FORMAT        #
  
      BEGIN                            # XDRSTR                        #
# 
****  XDRSTR - CONVERT BETWEEN DISPLAY AND ASCII IN XDR FORMAT. 
* 
*     THIS PROCEDURE WILL READ DATA OUT OF *BUFFER*, OR WRITE DATA INTO 
*     *BUFFER* DEPENDING ON THE *OPERATION* PARAMETER.  THE DATA IN 
*     *BUFFER* IS IN ASCII CHARACTER XDR (EXTERNAL DATA REPRESENTATION) 
*     FORMAT, PACKED 7.5 CHARACTERS/CYBER WORD.  THE FIRST 4 BYTES
*     CONTAIN THE STRING LENGTH.  IF THE LENGTH IS NOT A MULTIPLE OF
*     BYTES, THEN 0 TO 3 BYTES OF ZEROS ARE ADDED TO THE MESSAGE TO MAKE
*     THE NUMBER OF BYTES A MULTIPLE OF FOUR.  STRING IS A ZERO BYTE
*     TERMINATED STRING.
* 
*     PROC XDRSTR (BUFFER, BUFPOS, STRING, STRLEN, OPERATION) 
* 
*     ENTRY    BUFFER    = INTEGER ARRAY PACKED 7.5 BYTES/WORD. 
*              BUFPOS    = INDEX OF NEXT BYTE TO BE READ OR WRITTEN.
*              STRING    = DISPLAY CHARACTER ARRAY. 
*              OPERATION = EITHER *READ* FROM OR *WRITE* TO *BUFFER*. 
* 
*     EXIT     BUFFER    = DATA READ OUT OR WRITTEN TO. 
*              BUFPOS    = BYTE POSITION IN *BUFFER* AFTER OPERATION. 
*              STRING    = CHARACTERS READ OUT OR WRITTEN TO. 
*              STRLEN    = NUMBER OF CHARACTERS READ FROM *BUFFER* OR 
*                          WRITTEN TO *BUFFER*. 
* 
*     METHOD   IF OPERATION IS *READ*, XDRINT IS CALLED TO DETERMINE THE
*              VALUE OF *STRLEN*.  *STRLEN* CHARACTERS ARE THEN READ FROM 
*              FROM *BUFFER*. 
*              IF THE OPERATION IS *WRITE*, CHARACTERS ARE WRITTEN TO 
*              *STRING* UNTIL A ZERO BYTE IS ENCOUNTERED.  WHEN THE ZERO
*              BYTE IS ENCOUNTERED, *STRLEN* IS DETERMINED AND WRITTEN
*              TO THE BEGINNING OF THE STRING IN *BUFFER*.
*              *BUFPOS* IS UPDATED TO THE NEXT READ/WRITE BYTE POSITION.
*              THE ARITHMETIC MODULO BASE 60 FUNCTION IS PERFORMED ON 
*              *BUFPOS* MULTIPLIED BY EIGHT TO DETERMINE THE BIT
*              POSITION WITHIN BUFFER.  IF THE POSITION IS 56, THE
*              BYTE IS SPLIT ACROSS TWO WORDS.  THE CHARACTERS IN 
*              *BUFFER* ARE 7-BIT ASCII CHARACTERS TERMINATED WITH A
*              ZERO BYTE, THE CHARACTERS IN STRING ARE IN DISPLAY CODE. 
*              IF CONVERTING ASCII TO DISPLAY, THE ASCII INTEGER VALUE
*              IS THE OFFSET INTO THE ASCII TO DISPLAY CONVERSION ARRAY.
*              IF CONVERTING DISPLAY TO ASCII, THE DISPLAY INTEGER VALUE
*              IS USED TO DETERMINE THE WORD AND BIT OFFSET INTO THE
*              DISPLAY TO ASCII ARRAY.
*              THE CALLER IS RESPONSIBLE FOR MAKING SURE THAT THE 
*              DESTINATION ARRAY IS LARGE ENOUGH TO HOLD THE NUMBER 
*              OF VALUES SPECIFIED. 
* 
# 
  
# 
****  PROC XDRSTR - XREF LIST 
# 
      XREF
        BEGIN 
        PROC XDRBYTE;    # CONVERT BYTE TO XDR DATA                    #
        PROC XDRINT;     # CONVERT INTEGER TO XDR DATA                 #
        END 
  
# 
**
# 
      DEF CHARNUL$       # 0 #;        # NULL CHARACTER                #
  
      ARRAY BUFFER [0:0] S(1);         # ARRAY OF DATA, 7.5 BYTES/WORD #
        ITEM BUF$WRD  U(00,00,60);     # WORD REFERENCE                #
      ITEM BUFPOS            I;        # CUR BYTE POSITION IN BUFFER   #
      ARRAY STRING [0:0] S(240);
        ITEM STR$CHAR C(00,00,240);    # CHARACTER REFERENCE           #
      ITEM STRLEN            I;        # NUMBER OF CHARS TO BE PROCESSD#
      ITEM OPERATION S:XDROPER;        # OPERATION TO PERFORM ON BUFFER#
  
      ITEM ARRAYBIT          I;        # BIT OFFSET INTO *DACONVER* WRD#
      ITEM ARRAYWRD          I;        # WORD OFFSET INTO *DACONVER*   #
      ITEM BITPOS            I;        # BIT POSITION IN BUFFER        #
      ITEM INDEX             I;        # NUMBER OF CHARACTERS READ     #
      ITEM LENPOS            I;        # STRING LENGTH POSITION IN BUF #
      ITEM SRCHAR            I;        # INPUT SOURCE CHARACTER        #
      ITEM WORDPOS           I;        # WORD POSITION IN BUFFER       #
      ITEM ZEROBYTE          I;        # NUMBER OF ZERO BYTES TO ADD   #
  
# 
****  ARRAY THAT DEFINES THE ASCII TO DISPLAY CODE CONVERSION TABLE 
# 
      ARRAY ADCONVER [00:12] S(1);
        BEGIN                          # ASCII TO DISPLAY CONVERSION   #
        ITEM AD$CHAR     C(00,00,127); #  CHARACTER REFERENCE          #
        ITEM AD$WORD     U(00,00,60) =
          [O"00000000000000000000",    # 00,01,02,03,04,05,06,07,08,09 #
           O"00000000000000000000",    # 0A,0B,0C,0D,0E,0F,10,11,12,13 #
           O"00000000000000000000",    # 14,15,16,17,18,19,1A,1B,1C,1D #
           O"00005566646053636770",    # 1E,1F,20,21,22,23,24,25,26,27 #
           O"51524745564657503334",    # 28,29,2A,2B,2C,2D,2E,2F,30,31 #
           O"35363740414243440077",    # 32,33,34,35,36,37,38,39,3A,3B #
           O"72547371740102030405",    # 3C,3D,3E,3F,40,41,42,43,44,45 #
           O"06071011121314151617",    # 46,47,48,49,4A,4B,4C,4D,4E,4F #
           O"20212223242526273031",    # 50,51,52,53,54,55,56,57,58,59 #
           O"32617562766500010203",    # 5A,5B,5C,5D,5E,5F,60,61,62,63 #
           O"04050607101112131415",    # 64,65,66,67,68,69,6A,6B,6C,6D #
           O"16172021222324252627",    # 6E,6F,70,71,72,73,74,75,76,77 #
           O"30313200000000000000"];   # 78,79,7A,7B,7C,7D,7E,7F       #
        END 
# 
****  ARRAYS THAT DEFINES THE DISPLAY TO ASCII CONVERSION 
# 
  
      ARRAY DACONVER [00:12] S(1);
        BEGIN                          # DISPLAY TO ASCII CONVERSION   #
        ITEM DA$WORD     U(00,00,60) =
          [X"03A041042043044",         # 00,01,02,03,04  :  A  B  C  D #
           X"045046047048049",         # 05,06,07,10,11  E  F  G  H  I #
           X"04A04B04C04D04E",         # 12,13,14,15,16  J  K  L  M  N #
           X"04F050051052053",         # 17,20,21,22,23  O  P  Q  R  S #
           X"054055056057058",         # 24,25,26,27,30  T  U  V  W  X #
           X"05905A030031032",         # 31,32,33,34,35  Y  Z  0  1  2 #
           X"033034035036037",         # 36,37,40,41,42  3  4  5  6  7 #
           X"03803902B02D02A",         # 43,44,45,46,47  8  9  +  -  * #
           X"02F02802902403D",         # 50,51,52,53,54  /  (  )  $  = #
           X"02002C02E02305B",         # 55,56,57,60,61     ,  .  PD [ #
           X"05D02502205F021",         # 62,63,64,65,66  ]  %  "  _  ! #
           X"02602703F03C03E",         # 67,70,71,72,73  &  '  ?  <  > #
           X"04005C05E03B000"];        # 74,75,76,77     AT \  CF SC   #
        END 
      CONTROL EJECT;
# 
****  START MAIN PROCEDURE
# 
  
      SWITCH OPER$:XDROPER  OPER$READ:READ, 
                           OPER$WRITE:WRITE;
  
      GOTO OPER$ [OPERATION]; 
        BEGIN                          # OPERATION TYPE                #
  
    OPER$READ:  
  
        INDEX = 1;                     # READ/WRITE ONE INTEGER        #
        XDRINT (BUFFER, BUFPOS, STRLEN, INDEX, OPERATION);
        ZEROBYTE = XDRMODU (STRLEN, 4); 
        IF ZEROBYTE NQ 0
        THEN
          BEGIN                        # ACTUAL NUMBER OF ZERO BYTES   #
          ZEROBYTE = 4 - ZEROBYTE;
          END 
  
        BITPOS = XDRMODU (BUFPOS * 8, 60);# INITIAL BIT POSITION IN BUF#
        WORDPOS = (BUFPOS * 2) / 15;   # INITIAL WORD INDEX WITHIN BUF #
  
        FOR INDEX = 0 STEP 1 UNTIL (STRLEN - 1) 
        DO
          BEGIN                        # LOOP THROUGH REQUESTED CHARS  #
          IF BITPOS EQ 56 
          THEN
            BEGIN                      # BYTE SPLIT BETWEEN WORDS      #
            SRCHAR = B<56,4>BUF$WRD [WORDPOS] * 16 +
                     B<0,4>BUF$WRD [WORDPOS +1];
            WORDPOS = WORDPOS + 1;
            BITPOS = 4; 
            END 
          ELSE
            BEGIN                      # BYTE IN SINGLE CM WORD        #
            SRCHAR = B<BITPOS,8>BUF$WRD [WORDPOS];
            BITPOS = BITPOS + 8;
            IF BITPOS GQ 60 
            THEN
              BEGIN 
              BITPOS = 0; 
              WORDPOS = WORDPOS + 1;
              END 
            END 
  
          SRCHAR = SRCHAR LAN X"7F";   # MASK UPPER BIT, ONLY 127 CHARS#
          C<INDEX,1>STR$CHAR [0] = C<SRCHAR,1>AD$CHAR [0];
          END                          # LOOP THROUGH REQUESTED CHARS  #
  
        BUFPOS = BUFPOS + STRLEN + ZEROBYTE;# NEXT READ POSITION       #
        C<STRLEN,1>STR$CHAR [0] = CHARNUL$; 
  
        GOTO OPER$END;
  
    OPER$WRITE: 
  
        LENPOS = BUFPOS;
        BUFPOS = BUFPOS + 4;
        BITPOS = XDRMODU (BUFPOS * 8, 60);# INITIAL BIT POSITION IN BUF#
        WORDPOS = (BUFPOS * 2) / 15;   # INITIAL WORD INDEX WITHIN BUF #
  
        SRCHAR = C<0,1>STR$CHAR [0];   # DISPLAY CHAR TO CONVERT       #
  
        FOR STRLEN = 1 STEP 1 
        WHILE SRCHAR NQ CHARNUL$
        DO
          BEGIN                        # LOOP THROUGH REQUESTED CHARS  #
          ARRAYWRD = SRCHAR / 5;       # WORD OFFSET IN *DACONVER*     #
          ARRAYBIT = XDRMODU (SRCHAR * 12, 60) + 4; # BIT OFFSET IN WRD#
  
          IF BITPOS EQ 56 
          THEN
            BEGIN                      # BYTE SPLIT BETWEEN WORDS      #
            B<56,4>BUF$WRD [WORDPOS] = B<ARRAYBIT,4>DA$WORD [ARRAYWRD]; 
            B<0,4>BUF$WRD [WORDPOS + 1] = 
                B<ARRAYBIT + 4,4>DA$WORD [ARRAYWRD];
            WORDPOS = WORDPOS + 1;
            BITPOS = 4; 
            END 
          ELSE
            BEGIN                      # BYTE IN SINGLE CM WORD        #
            B<BITPOS,8>BUF$WRD [WORDPOS] =
                B<ARRAYBIT,8>DA$WORD [ARRAYWRD];
            BITPOS = BITPOS + 8;
            IF BITPOS GQ 60 
            THEN
              BEGIN 
              BITPOS = 0; 
              WORDPOS = WORDPOS + 1;
              END 
            END 
          SRCHAR = C<STRLEN,1>STR$CHAR [0];# DISPLAY CHAR TO CONVERT   #
          END                          # LOOP THROUGH REQUESTED CHARS  #
  
        INDEX = 1;
        STRLEN = STRLEN - 1;
        XDRINT (BUFFER, LENPOS, STRLEN, INDEX, OPERATION);
  
        BUFPOS = BUFPOS + STRLEN;      # NEXT BUFFER LOCATION          #
        ZEROBYTE = XDRMODU (STRLEN, 4); 
        IF ZEROBYTE NQ 0
        THEN
          BEGIN                        # ACTUAL NUMBER OF ZERO BYTES   #
          ZEROBYTE = 4 - ZEROBYTE;
          END 
        XDRBYTE (BUFFER, BUFPOS, ADCONVER, ZEROBYTE, XDROPER"WRITE"); 
  
        GOTO OPER$END;
  
        END                            # OPERATION TYPE                #
  
  OPER$END: 
  
      RETURN;                          # RETURN TO CALLER              #
  
      END                              # XDRSTR                        #
  
      TERM
*WEOR 
