home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / iclvme2900 / kmt_pp_module < prev    next >
Text File  |  2020-01-01  |  68KB  |  1,790 lines

  1. MODULE KMT_PP_MODULE;
  2.  
  3. @******************************************************************************@
  4. @*                                                                            *@
  5. @* Mode definitions                                                           *@
  6. @*                                                                            *@
  7. @******************************************************************************@
  8.  
  9. MODE
  10. KMT_TRACE_FLAGS_S IS WORD STRUCT (
  11.    BIT    PH_TRACING,
  12.           PP_TRACING,
  13.           FH_TRACING,
  14.           DH_TRACING,
  15.    28-BIT SPARE);
  16.  
  17. MODE
  18. KMT_FH_RECORD_DETAILS_S IS STRUCT (
  19.    BOOL        FILE_OPEN,
  20.                NEW_RECORD,
  21.                END_OF_FILE,
  22.    WORD        TEXT_TYPE,                        @ 0 = EBCDIC                  @
  23.                                                  @ 1 = ASCII                   @
  24.                                                  @ 2 = BINARY                  @
  25.    INT         MAX_RECORD_LENGTH,
  26.                RECORD_LENGTH,
  27.    (4098) BYTE RECORD);                          @ Maximum record size of 4096 @
  28.                                                  @ plus 2 bytes for CRLF pair  @
  29.                                                  @ when constructing output    @
  30.                                                  @ records                     @
  31.  
  32. MODE
  33. KMT_DH_DEVICE_DETAILS_S IS STRUCT (
  34.   BOOL FILE_OPEN,
  35.   WORD MAX_INPUT_LENGTH,
  36.        MAX_OUTPUT_LENGTH,
  37.        INPUT_PARITY,
  38.        OUTPUT_PARITY,
  39.        PAUSE);
  40.  
  41. MODE
  42. KMT_PP_PACKET_DATA_S IS STRUCT (
  43.    INT       DATA_LENGTH,
  44.    (91) BYTE DATA);
  45.  
  46. MODE
  47. KMT_PP_CONFG_PARAMS_S IS STRUCT (
  48.    BYTE   MARK,
  49.           MAXL,
  50.           TIME,
  51.           NPAD,
  52.           PADC,
  53.           EOL,
  54.           QCTL,
  55.           QBIN,
  56.           CHKT,
  57.           REPT,
  58.    4-BYTE CAPAS);
  59.  
  60. MODE
  61. KMT_PP_PACKET_STATISTICS_S IS STRUCT (
  62.    INT INPUT_TOTAL,
  63.        OUTPUT_TOTAL);
  64.  
  65. MODE
  66. KMT_MTM_VALUES IS ANY (
  67.    LONG WORD          LW_VALUE,
  68.    LONG INT           LI_VALUE,
  69.    REF WORD           RW_VALUE,
  70.    REF INT            RI_VALUE,
  71.    REF LONG WORD      RLW_VALUE,
  72.    REF LONG INT       RLI_VALUE,
  73.    REF () BYTE        RVB_VALUE,
  74.    REF () REF () BYTE RVRVB_VALUE);
  75.  
  76. ***PAGE
  77.  
  78. @******************************************************************************@
  79. @*                                                                            *@
  80. @* External procedure references                                              *@
  81. @*                                                                            *@
  82. @******************************************************************************@
  83.  
  84. EXT
  85. PROC
  86.    (REF () BYTE,                                 @ OUTPUT_PACKET               @
  87.     BOOL,                                        @ PROMPT                      @
  88.     RESPONSE                                     @ RESPONSE                    @
  89.    )                                   KMT_DH_OUTPUT;
  90.  
  91. EXT
  92. PROC
  93.    (REF () BYTE,                                 @ INPUT_BUFFER                @
  94.     REF INT,                                     @ INPUT_BUFFER_LENGTH         @
  95.     RESPONSE                                     @ RESPONSE                    @
  96.    )                                   KMT_DH_INPUT;
  97.  
  98. EXT
  99. PROC
  100.    (INT,                                         @ RESULT_CODE                 @
  101.     WORD,                                        @ DESTINATION                 @
  102.     REF () KMT_MTM_VALUES,                       @ PARAMS                      @
  103.     LONG WORD,                                   @ PE_CONTINGENCY_MESSAGE      @
  104.     BOOL,                                        @ DUMP                        @
  105.     BOOL                                         @ UNRECOVERABLE               @
  106.    )                                   KMT_EH_LOG_ERROR;
  107.  
  108. EXT
  109. PROC
  110.    (
  111.     RESPONSE                                     @ RESPONSE                    @
  112.    )                                   KMT_FH_READ;
  113.  
  114. EXT
  115. PROC
  116.    (
  117.     RESPONSE                                     @ RESPONSE                    @
  118.    )                                   KMT_FH_WRITE;
  119.  
  120. EXT
  121. PROC
  122.    (
  123.     WORD,                                        @ CHAR                        @
  124.     WORD,                                        @ I/O FLAG                    @
  125.     RESPONSE                                     @ RESPONSE                    @
  126.    )                                  KMT_SP_CHECK_VME_CHAR;
  127.  
  128. EXT
  129. PROC
  130.    (
  131.     INT,                                         @ TYPE                        @
  132.     REF () KMT_MTM_VALUES                        @ PARAMS                      @
  133.    )                                   KMT_SP_LOG_TRACE_MESSAGE;
  134.  
  135.  
  136. ***PAGE
  137.  
  138. @******************************************************************************@
  139. @*                                                                            *@
  140. @* External data references                                                   *@
  141. @*                                                                            *@
  142. @******************************************************************************@
  143.  
  144. @ Constants: @
  145. @ ********** @
  146.  
  147. EXT (256) BYTE
  148.    EBCDIC_TO_ASCII,                                       @ translation tables @
  149.    ASCII_TO_EBCDIC;
  150.  
  151. EXT (26) INT
  152.    PACKET_CODES;         @ packet codes to protocol handler state table events @
  153.  
  154. EXT INT
  155.    BAD_PKT,INVALID_PKT,UNS_PKT,NON_PKT;
  156.  
  157. ***LINES(4)
  158.  
  159. @ Variables: @
  160. @ ********** @
  161.  
  162. EXT (<CASCADE>)
  163. REF KMT_TRACE_FLAGS_S KMT_TRACE_FLAGS;
  164.  
  165. EXT (<CASCADE>)
  166. REF KMT_FH_RECORD_DETAILS_S KMT_FH_RECORD_DETAILS;
  167.  
  168. EXT (<CASCADE>)
  169. REF KMT_DH_DEVICE_DETAILS_S KMT_DH_DEVICE_DETAILS;
  170.  
  171. EXT (<CASCADE>)
  172. REF KMT_PP_CONFG_PARAMS_S KMT_PP_LOCAL_CONFG_PARAMS;
  173.  
  174. EXT (<CASCADE>)
  175. REF KMT_PP_CONFG_PARAMS_S KMT_PP_REMOTE_CONFG_PARAMS;
  176.  
  177. EXT (<CASCADE>)
  178. REF KMT_PP_PACKET_STATISTICS_S KMT_PP_PACKET_STATISTICS;
  179.  
  180. EXT (<CASCADE>)
  181. REF REF () BYTE KMT_PH_INPUT_PACKET_DATA;
  182.  
  183. ***LINES(4)
  184.  
  185. @ Results: @
  186. @ ******** @
  187.  
  188. ***LINES(4)
  189.  
  190. ***PAGE
  191.  
  192. @******************************************************************************@
  193. @*                                                                            *@
  194. @* Static data declarations.                                                  *@
  195. @*                                                                            *@
  196. @******************************************************************************@
  197.  
  198. @ Constants: @
  199. @ ********** @
  200.  
  201. STATIC WORD
  202.    EBCDIC IS 0,                                               @ transfer codes @
  203.    ASCII  IS 1,
  204.    BINARY IS 2;
  205.  
  206. STATIC INT
  207.    KMT_PP_PACKET_IN_MSG       IS 251,
  208.    KMT_PP_PACKET_OUT_MSG      IS 252,
  209.    KMT_PP_PACKET_DATA_IN_MSG  IS 253,
  210.    KMT_PP_PACKET_DATA_OUT_MSG IS 254,
  211.    KMT_PP_PARAM_OUT_MSG       IS 258,
  212.    KMT_PP_PARAM_IN_MSG        IS 259;
  213.  
  214. ***LINES(4)
  215.  
  216. @ Variables: @
  217. @ ********** @
  218.  
  219. STATIC
  220. KMT_PP_PACKET_DATA_S KMT_PP_INPUT_PACKET_DATA;
  221.  
  222. STATIC
  223. KMT_PP_PACKET_DATA_S KMT_PP_OUTPUT_PACKET_DATA;
  224.  
  225. STATIC
  226. REF () BYTE KMT_PP_RECALL_DATA;
  227.  
  228. ***LINES(4)
  229.  
  230. @ Results: @
  231. @ ******** @
  232.  
  233. ***LINES(4)
  234.  
  235. ***PAGE
  236.  
  237. @******************************************************************************@
  238. @*                                                                            *@
  239. @* Procedure declarations                                                     *@
  240. @*                                                                            *@
  241. @******************************************************************************@
  242.  
  243. STATIC
  244. PROC
  245.    KMT_PP_CHECK_COMPLETE IS (
  246.    INT             DATA_LENGTH,
  247.    REF REF () BYTE BUFFER) BOOL:
  248.  
  249. @******************************************************************************@
  250. @*                                                                            *@
  251. @* This procedure is used to update a buffer pointer and to check if the      *@
  252. @* processing of BUFFER is complete.                                          *@
  253. @* The procedure returns TRUE if the processing of BUFFER has been completed, *@
  254. @* FALSE otherwise.                                                           *@
  255. @*                                                                            *@
  256. @******************************************************************************@
  257.  
  258. BEGIN
  259.    IF
  260.       LENGTH BUFFER GT DATA_LENGTH
  261.  
  262.    THEN                                          @ Incomplete, update pointer  @
  263.       BUFFER := BUFFER(DATA_LENGTH::);
  264.       FALSE
  265.  
  266.    ELSE                                          @ Complete return ZLR         @
  267.       BUFFER := BUFFER(SIZE 0);
  268.       TRUE
  269.    FI
  270. END;                                   @ KMT_PP_CHECK_COMPLETE                 @
  271.  
  272. ***PAGE
  273.  
  274. STATIC
  275. PROC
  276.    KMT_PP_MOVE IS (
  277.    () BYTE         SOURCE,
  278.    REF REF () BYTE DESTINATION,
  279.    REF BOOL        COMPLETE) INT:
  280.  
  281. @******************************************************************************@
  282. @*                                                                            *@
  283. @* This procedure is used to move the source string into the destination      *@
  284. @* buffer and to check if the destination buffer is full.                     *@
  285. @* The procedure returns the number of characters moved.                      *@
  286. @*                                                                            *@
  287. @******************************************************************************@
  288.  
  289. BEGIN
  290.    INT S_LEN IS LENGTH SOURCE,
  291.        D_LEN IS LENGTH DESTINATION;
  292.  
  293.    IF
  294.       S_LEN GT D_LEN
  295.  
  296.    THEN                                          @ Insufficient space in       @
  297.                                                  @ buffer for string           @
  298.       UNLESS
  299.          COMPLETE IS NIL
  300.  
  301.       THEN
  302.          COMPLETE := TRUE;
  303.       FI;
  304.  
  305.       0
  306.    ELSE
  307.       DESTINATION(SIZE S_LEN) := SOURCE;
  308.  
  309.       UNLESS
  310.          COMPLETE IS NIL
  311.  
  312.       THEN
  313.          COMPLETE := KMT_PP_CHECK_COMPLETE (S_LEN,
  314.                                             DESTINATION);
  315.       FI;
  316.  
  317.       S_LEN
  318.    FI
  319. END;                                   @ KMT_PP_MOVE                           @
  320.  
  321. ***PAGE
  322.  
  323. STATIC
  324. PROC
  325.    KMT_PP_GENERATE_CHECKSUM IS (
  326.    REF () BYTE PACKET) BYTE:
  327.  
  328. @******************************************************************************@
  329. @*                                                                            *@
  330. @* This procedure is used to generate a checksum for the data contained in    *@
  331. @* the packet.                                                                *@
  332. @*                                                                            *@
  333. @******************************************************************************@
  334.  
  335. BEGIN
  336.    WORD SUM := 0;
  337.  
  338.    FOR  I
  339.    FROM 1                                        @ 'MARK' character not        @
  340.                                                  @ included in checksum        @
  341.    TO   PACKET(1) - X"20"
  342.    DO
  343.       SUM := SUM + PACKET(I)
  344.    REPEAT;
  345.  
  346.    ((SUM + ((SUM & X'C0') SCALE -6)) & X'3F') + X"20"
  347. END;                                   @ KMT_PP_GENERATE_CHECKSUM              @
  348.  
  349. ***PAGE
  350.  
  351. STATIC
  352. PROC
  353.    KMT_PP_LOG_TRACE_MESSAGE IS (
  354.    INT         TYPE,
  355.    REF () BYTE PACKET):
  356.  
  357. @******************************************************************************@
  358. @*                                                                            *@
  359. @* This procedure is used to log the packet contents to the job journal.      *@
  360. @*                                                                            *@
  361. @******************************************************************************@
  362.  
  363. BEGIN
  364.    INT PACKET_LENGTH IS LENGTH PACKET;
  365.  
  366.    INT LEN := PACKET(1) - X"20",
  367.        SEQ := PACKET(2) - X"20",
  368.        TYP := PACKET_CODES(PACKET(3) - X"41");
  369.  
  370.    () KMT_MTM_VALUES PARAMS := (PACKET           @ COMPLETE PACKET             @
  371.                                 AS KMT_MTM_VALUES.RVB_VALUE,
  372.                                 PACKET(0)        @ MARK                        @
  373.                                 AS KMT_MTM_VALUES.RVB_VALUE,
  374.                                 LEN              @ LEN                         @
  375.                                 AS KMT_MTM_VALUES.RI_VALUE,
  376.                                 SEQ              @ SEQ                         @
  377.                                 AS KMT_MTM_VALUES.RI_VALUE,
  378.                                 TYP              @ TYPE                        @
  379.                                 AS KMT_MTM_VALUES.RI_VALUE,
  380.                                 PACKET(4 SIZE PACKET_LENGTH - 5)
  381.                                                  @ DATA                        @
  382.                                 AS KMT_MTM_VALUES.RVB_VALUE,
  383.                                 PACKET(PACKET_LENGTH - 1)
  384.                                                  @ CHECKSUM                    @
  385.                                 AS KMT_MTM_VALUES.RVB_VALUE);
  386.  
  387.    KMT_SP_LOG_TRACE_MESSAGE (TYPE,
  388.                              PARAMS)
  389. END;                                   @ KMT_PP_LOG_TRACE_MESSAGE              @
  390.  
  391. ***PAGE
  392.  
  393. STATIC
  394. PROC
  395.    KMT_PP_DATA_TRACE_MESSAGE IS (
  396.    INT         TYPE,
  397.    INT         CODE,
  398.    REF () BYTE DATA):
  399.  
  400. @******************************************************************************@
  401. @*                                                                            *@
  402. @* This procedure is used to log the packet data to the job journal.          *@
  403. @*                                                                            *@
  404. @******************************************************************************@
  405.  
  406. BEGIN
  407.    INT CHAR_CODE := CODE;
  408.    () KMT_MTM_VALUES PARAMS := (CHAR_CODE        @ character code of data      @
  409.                                 AS KMT_MTM_VALUES.RI_VALUE,
  410.                                 DATA             @ data                        @
  411.                                 AS KMT_MTM_VALUES.RVB_VALUE);
  412.  
  413.    KMT_SP_LOG_TRACE_MESSAGE (TYPE,
  414.                              PARAMS)
  415. END;                                   @ KMT_PP_DATA_TRACE_MESSAGE             @
  416.  
  417. ***PAGE
  418.  
  419. STATIC
  420. PROC
  421.    KMT_PP_BUILD_PACKET_DATA IS (
  422.                 REF REF () BYTE BUFFER,
  423.                 REF REF () BYTE DATA,
  424.                 WORD            TEXT_TYPE,
  425.                 REF BOOL        BUFFER_COMPLETE) BOOL:
  426.  
  427. @******************************************************************************@
  428. @*                                                                            *@
  429. @* This procedure is used to perform data translation of the data area        *@
  430. @* referenced by BUFFER.                                                      *@
  431. @* If a binary file transfer is requested then the translation process        *@
  432. @* involves control character quoting and 8th bit prefixing. Otherwise (for   *@
  433. @* text files) the translation process involves control character quoting and *@
  434. @* EBCDIC to ASCII data translation.                                          *@
  435. @* If the whole of BUFFER has been translated then BUFFER_COMPLETE is set     *@
  436. @* TRUE and BUFFER is returned referencing a zero length record. Otherwise    *@
  437. @* BUFFER_COMPLETE is returned FALSE and BUFFER is returned referencing the   *@
  438. @* untranslated part of the original buffer.                                  *@
  439. @* The translated data is returned in the area referenced by DATA.            *@
  440. @* The procedure returns TRUE if there is insufficient space in DATA for more *@
  441. @* of the translated data.                                                    *@
  442. @*                                                                            *@
  443. @******************************************************************************@
  444.  
  445. BEGIN
  446.    STATIC BYTE
  447.       SPACE IS X"20",                                            @ ASCII codes @
  448.       DEL   IS X"7F";
  449.  
  450.    BYTE
  451.       QCTL  IS KMT_PP_LOCAL_CONFG_PARAMS.QCTL,
  452.       QBIN  IS KMT_PP_LOCAL_CONFG_PARAMS.QBIN;
  453.  
  454.    () BYTE
  455.       QLF   IS (QCTL,X"4A"),                               @ ASCII quoted LF   @
  456.       QFF   IS (QCTL,X"4C"),                               @ ASCII quoted FF   @
  457.       QCR   IS (QCTL,X"4D"),                               @ ASCII quoted CR   @
  458.       QCRLF IS (QCTL,X"4D",QCTL,X"4A");                    @ ASCII quoted CRLF @
  459.  
  460.    BOOL
  461.       DATA_COMPLETE := FALSE;
  462.  
  463.    SIM PROC PACKETISE IS (() BYTE SOURCE,INT DATA_LENGTH):
  464.       BEGIN
  465.          IF KMT_PP_MOVE(SOURCE,DATA,DATA_COMPLETE) NE 0
  466.          THEN BUFFER_COMPLETE := KMT_PP_CHECK_COMPLETE(DATA_LENGTH,BUFFER)
  467.          FI
  468.       END @ PACKETISE @ ;
  469.  
  470.    BUFFER_COMPLETE := (LENGTH BUFFER LE 0);
  471.  
  472.    UNTIL DATA_COMPLETE OR BUFFER_COMPLETE
  473.    DO
  474.       IF TEXT_TYPE GT EBCDIC
  475.       THEN                                              @ ASCII or binary data @
  476.          INT SEQ_LEN := 0;
  477.          (3) BYTE SEQ;
  478.          BYTE THIS_CHAR := BUFFER(0);
  479.  
  480.          SIM PROC ADD_TO_SEQ IS (BYTE OCTET):
  481.             BEGIN
  482.                SEQ(SEQ_LEN) := OCTET;
  483.                SEQ_LEN := SEQ_LEN+1
  484.             END @ ADD_TO_SEQ @ ;
  485.  
  486.          IF (THIS_CHAR GT DEL) AND (TEXT_TYPE EQ BINARY)
  487.          THEN                                     @ need to add 8th bit prefix @
  488.             ADD_TO_SEQ(QBIN)
  489.          FI;
  490.  
  491.          THIS_CHAR := THIS_CHAR & X"7F";
  492.  
  493.          IF (THIS_CHAR LT SPACE) OR (THIS_CHAR EQ DEL)
  494.          THEN                                              @ control character @
  495.             ADD_TO_SEQ(QCTL);
  496.             THIS_CHAR := THIS_CHAR NEQ X"40"
  497.          ELSF (THIS_CHAR EQ QCTL) OR (THIS_CHAR EQ QBIN AND TEXT_TYPE EQ BINARY)
  498.          THEN                                         @ special char, quote it @
  499.             ADD_TO_SEQ(QCTL)
  500.          FI;
  501.  
  502.          ADD_TO_SEQ(THIS_CHAR);
  503.          PACKETISE(SEQ(SIZE SEQ_LEN),1)
  504.  
  505.       ELSE                                                       @ EBCDIC data @
  506.          BYTE THIS_CHAR IS EBCDIC_TO_ASCII(BUFFER(0));
  507.  
  508.          IF THIS_CHAR GT DEL
  509.          THEN                                                @ Format effector @
  510.             IF (LENGTH BUFFER LT 2) OR (THIS_CHAR EQ X"FB")
  511.             THEN @ Newline FE (1 byte) or FE at end of record with no specifier@
  512.                IF THIS_CHAR EQ X"FB"
  513.                THEN                                  @ End of record so ignore @
  514.                   BUFFER_COMPLETE := KMT_PP_CHECK_COMPLETE(1,BUFFER)
  515.                ELSE                                                  @ Newline @
  516.                   PACKETISE(QCRLF,1)
  517.                FI
  518.             ELSE                                           @ FE with qualifier @
  519.                REF BYTE QUALIFIER IS BUFFER(1);
  520.  
  521.                SIM PROC EXPAND_FE IS (() BYTE EXPANSION):
  522.                   BEGIN
  523.                      IF
  524.                         QUALIFIER :=
  525.                            QUALIFIER - W'(TO QUALIFIER - 1
  526.                                           UNTIL DATA_COMPLETE
  527.                                           DO
  528.                                              KMT_PP_MOVE(EXPANSION,DATA,
  529.                                                               DATA_COMPLETE)
  530.                                           REPEAT);
  531.                         QUALIFIER EQ 0
  532.                      THEN
  533.                         BUFFER_COMPLETE := KMT_PP_CHECK_COMPLETE(2,BUFFER)
  534.                      FI
  535.                   END @ EXPAND_FE @ ;
  536.  
  537.                CASE X"FF" - THIS_CHAR
  538.                THEN                                           @ multiple space @
  539.                   EXPAND_FE(SPACE)
  540.                ELSE                                         @ multiple newline @
  541.                   IF QUALIFIER EQ X"00"
  542.                   THEN                                       @ translate to CR @
  543.                      PACKETISE(QCR,2)
  544.                   ELSE                                  @ expand to CRLF pairs @
  545.                      EXPAND_FE(QCRLF)
  546.                   FI
  547.                ELSE                                        @ vertical position @
  548.                   IF (QUALIFIER EQ X"00")
  549.                   THEN
  550.                      PACKETISE(QFF,2)
  551.                   ELSE
  552.                      PACKETISE(QCRLF,2)
  553.                   FI
  554.                ELSE                                      @ horizontal position @
  555.                   PACKETISE(SPACE,2)
  556.                ESAC
  557.             FI
  558.          ELSF THIS_CHAR EQ QCTL
  559.          THEN                                                @ quote character @
  560.             PACKETISE((QCTL,THIS_CHAR),1)
  561.          ELSF (THIS_CHAR LT SPACE) OR (THIS_CHAR EQ DEL)
  562.          THEN                                              @ control character @
  563.             PACKETISE((QCTL,THIS_CHAR NEQ X"40"),1)
  564.          ELSE                                            @ printable character @
  565.             PACKETISE(THIS_CHAR,1)
  566.          FI
  567.       FI
  568.    REPEAT;
  569.  
  570.    DATA_COMPLETE
  571.  
  572. END @ KMT_PP_BUILD_PACKET_DATA @ ;
  573.  
  574. ***PAGE
  575.  
  576. STATIC
  577. PROC
  578.    KMT_PP_UNQUOTE_CHAR IS (
  579.    REF () BYTE DATA,
  580.    REF BYTE    UNQUOTED_CHAR,
  581.    REF INT     SEQUENCE_LENGTH):
  582.  
  583. @******************************************************************************@
  584. @*                                                                            *@
  585. @* This procedure is used to process a quoted (binary and/or control)         *@
  586. @* character sequence.                                                        *@
  587. @* The area referenced by DATA contains the character sequence to be          *@
  588. @* processed. The area referenced by UNQUOTED_CHAR is returned containing the *@
  589. @* unquoted character (with the control and 8th bit set as appropriate) and   *@
  590. @* the area referenced by SEQUENCE_LENGTH is returned containing the length   *@
  591. @* of the quoted sequence. If the first character in DATA is not a binary or  *@
  592. @* control quote character then UNQUOTED_CHAR is returned containing the      *@
  593. @* character and SEQUENCE_LENGTH is returned containing 1.                    *@
  594. @*                                                                            *@
  595. @******************************************************************************@
  596.  
  597. BEGIN
  598.    WORD TEXT_TYPE IS KMT_FH_RECORD_DETAILS.TEXT_TYPE;
  599.  
  600.    BYTE QCTL IS KMT_PP_REMOTE_CONFG_PARAMS.QCTL,
  601.         QBIN IS KMT_PP_REMOTE_CONFG_PARAMS.QBIN;
  602.  
  603.    BYTE THIS_CHAR := DATA(0);
  604.  
  605.    BYTE OR_MASK IS IF
  606.                       (TEXT_TYPE EQ BINARY)  AND  (THIS_CHAR EQ QBIN)
  607.                    THEN                          @ Binary file and 8th bit     @
  608.                                                  @ quoted character found      @
  609.                       THIS_CHAR := DATA(1);
  610.                       SEQUENCE_LENGTH := 2;
  611.                       X"80"
  612.                    ELSE                          @ Not an 8th bit quoted       @
  613.                                                  @ character                   @
  614.                       SEQUENCE_LENGTH := 1;
  615.                       X"00"
  616.                    FI;
  617.  
  618.    IF
  619.       THIS_CHAR EQ QCTL
  620.  
  621.    THEN                                          @ Control quoted character    @
  622.       THIS_CHAR := DATA(SEQUENCE_LENGTH);
  623.       SEQUENCE_LENGTH := SEQUENCE_LENGTH + 1;
  624.  
  625.       IF
  626.          (THIS_CHAR NE QCTL)  AND  (THIS_CHAR NE QBIN OR TEXT_TYPE NE BINARY)
  627.  
  628.       THEN                                       @ Control character           @
  629.          THIS_CHAR := THIS_CHAR NEQ X"40"
  630.       FI
  631.    FI;
  632.  
  633.    UNQUOTED_CHAR := THIS_CHAR ! OR_MASK
  634. END;                                   @ KMT_PP_UNQUOTE_CHAR                   @
  635.  
  636. ***PAGE
  637.  
  638. GLOBAL
  639. STATIC (<STATUS 5>)
  640. PROC
  641.    KMT_PP_TRANSLATE_TO_EBCDIC IS ():
  642.  
  643. @******************************************************************************@
  644. @*                                                                            *@
  645. @* This procedure is used to translate the packet data from ASCII to EBCDIC   *@
  646. @* and to process any quoted characters.                                      *@
  647. @* The untranslated data is read from, and the translated data is returned in *@
  648. @* the area referenced by KMT_PH_INPUT_PACKET_DATA.                           *@
  649. @*                                                                            *@
  650. @******************************************************************************@
  651.  
  652. BEGIN
  653.    () BYTE UNTRANSLATED_DATA := KMT_PH_INPUT_PACKET_DATA;
  654.                                                  @ Copy untranslated data      @
  655.  
  656.    REF () BYTE DATA := UNTRANSLATED_DATA;
  657.  
  658.    BOOL DATA_COMPLETE := (LENGTH DATA LE 0);
  659.  
  660.    INT T_LEN IS FOR   I
  661.                 UNTIL
  662.                    DATA_COMPLETE
  663.                 DO
  664.                    INT SEQUENCE_LENGTH;
  665.  
  666.                    KMT_PP_UNQUOTE_CHAR (DATA,
  667.                                         KMT_PH_INPUT_PACKET_DATA(I),
  668.                                         SEQUENCE_LENGTH);
  669.                    DATA_COMPLETE := KMT_PP_CHECK_COMPLETE (SEQUENCE_LENGTH,
  670.                                                            DATA)
  671.                 REPEAT;
  672.  
  673.    KMT_PH_INPUT_PACKET_DATA := KMT_PH_INPUT_PACKET_DATA(SIZE T_LEN);
  674.    TRANSLATE (ASCII_TO_EBCDIC,
  675.               KMT_PH_INPUT_PACKET_DATA,
  676.               0,
  677.               NIL);
  678.  
  679.    IF KMT_TRACE_FLAGS.PP_TRACING AND LENGTH KMT_PH_INPUT_PACKET_DATA > 0
  680.    THEN (<RARELY>)
  681.      (
  682.       KMT_PP_DATA_TRACE_MESSAGE(KMT_PP_PACKET_DATA_IN_MSG,
  683.                                 EBCDIC,
  684.                                 KMT_PH_INPUT_PACKET_DATA)
  685.      )
  686.    FI
  687.  
  688. END;                                   @ KMT_PP_TRANSLATE_TO_EBCDIC            @
  689.  
  690. ***PAGE
  691.  
  692. GLOBAL
  693. STATIC (<STATUS 5>)
  694. PROC
  695.    KMT_PP_GET_PACKET IS (
  696.    REF INT     TYPE,
  697.    REF INT     SEQ,
  698.    RESPONSE    RESULT):
  699.  
  700. @******************************************************************************@
  701. @*                                                                            *@
  702. @* This procedure is used to receive a KERMIT packet from the remote end.     *@
  703. @* If a failure is detected whilst attempting to read a packet then TYPE is   *@
  704. @* set to BAD_PKT and the failing resultcode is returned.                     *@
  705. @* If a zero length packet is read or no 'MARK' character is found in the     *@
  706. @* packet then TYPE is set to BAD_PKT and resultcode KMT_PP_NO_INPUT_DATA is  *@
  707. @* returned.                                                                  *@
  708. @* If the checksum validation fails then TYPE is set to BAD_PKT and           *@
  709. @* resultcode KMT_PP_INVALID_CHECKSUM is returned.                            *@
  710. @* In all other cases TYPE will be set to either INVALID_PKT or the packet    *@
  711. @* type. In the case of an invalid packet then a resultcode of either UNS_PKT *@
  712. @* or NON_PKT will be returned.                                               *@
  713. @* The packet sequence number is returned in the area referenced by SEQ and   *@
  714. @* the packet data is returned in the area referenced by                      *@
  715. @* KMT_PH_INPUT_PACKET_DATA.                                                  *@
  716. @*                                                                            *@
  717. @******************************************************************************@
  718.  
  719. BEGIN
  720.    INT KMT_PP_PACKET_IN_MSG           IS 251,
  721.        KMT_PP_NO_INPUT_PACKET         IS -80250,
  722.        KMT_PP_INVALID_CHECKSUM        IS -80253,
  723.        KMT_PP_INVALID_PACKET_LENGTH   IS -80254;
  724.  
  725.    INT INPUT_PACKET_LENGTH,
  726.        INPUT_BUFFER_LENGTH,
  727.        PACKET_POINTER_LENGTH;
  728.  
  729.    INT MAX_INPUT_LENGTH IS KMT_DH_DEVICE_DETAILS.MAX_INPUT_LENGTH;
  730.  
  731.    REF () BYTE INPUT_PACKET,
  732.                PACKET_POINTER;
  733.  
  734.    (MAX_INPUT_LENGTH) BYTE INPUT_BUFFER;         @ Allows for padding and      @
  735.                                                  @ 'noise' characters          @
  736.  
  737.    IF
  738.      (
  739.       KMT_DH_INPUT (INPUT_BUFFER,
  740.                     INPUT_BUFFER_LENGTH,
  741.                     RESULT);
  742.       RESULT GT 0
  743.      )
  744.  
  745.    THEN                                          @ I/O error                   @
  746.       TYPE := BAD_PKT
  747.  
  748.    ELSF
  749.       INPUT_BUFFER_LENGTH EQ 0
  750.  
  751.    OR
  752.      (
  753.       BYTE MARK IS KMT_PP_REMOTE_CONFG_PARAMS.MARK;
  754.  
  755.       REF () BYTE REM := INPUT_BUFFER(SIZE INPUT_BUFFER_LENGTH);
  756.  
  757.       PACKET_POINTER := REM(SIZE 0);
  758.  
  759.       UNTIL                                      @ Skip all but last 'MARK'    @
  760.          SCANUNQ (MARK,                          @ character                   @
  761.                   REM,
  762.                   0,
  763.                   REM)
  764.       DO
  765.          PACKET_POINTER := REM;
  766.          REM := REM(1::)
  767.       REPEAT;
  768.  
  769.       PACKET_POINTER_LENGTH := LENGTH PACKET_POINTER;
  770.       PACKET_POINTER_LENGTH LT 2
  771.      )
  772.  
  773.    OR
  774.      (
  775.       INPUT_PACKET_LENGTH := PACKET_POINTER(1) - X"20" + 2;
  776.       PACKET_POINTER_LENGTH LT INPUT_PACKET_LENGTH
  777.      )
  778.  
  779.    THEN                                          @ Either 'MARK' character not @
  780.                                                  @ found or insufficient data  @
  781.                                                  @ after 'MARK' character or a @
  782.                                                  @ recoverable I/O error       @
  783.                                                  @ occurred.                   @
  784.       TYPE := BAD_PKT;
  785.       RESULT := KMT_PP_NO_INPUT_PACKET
  786.  
  787.    ELSF
  788.      (
  789.       (INPUT_PACKET_LENGTH LT 5)  OR  (INPUT_PACKET_LENGTH GT 96)
  790.      )
  791.  
  792.    THEN                                          @ Packet length invalid       @
  793.       TYPE := BAD_PKT;
  794.       RESULT := KMT_PP_INVALID_PACKET_LENGTH
  795.  
  796.    ELSF
  797.      (
  798.       INPUT_PACKET := PACKET_POINTER(SIZE INPUT_PACKET_LENGTH);
  799.  
  800.       IF
  801.          KMT_TRACE_FLAGS.PP_TRACING
  802.  
  803.       THEN (<RARELY>)
  804.         (
  805.          KMT_PP_LOG_TRACE_MESSAGE (KMT_PP_PACKET_IN_MSG,
  806.                                    INPUT_PACKET)
  807.         )
  808.       FI;
  809.  
  810.       INPUT_PACKET(INPUT_PACKET_LENGTH - 1) NE KMT_PP_GENERATE_CHECKSUM (
  811.                                                   INPUT_PACKET)
  812.      )
  813.  
  814.    THEN                                          @ Checksum error              @
  815.       TYPE := BAD_PKT;
  816.       RESULT := KMT_PP_INVALID_CHECKSUM
  817.  
  818.    ELSE                                          @ Validate packet type        @
  819.       WORD PACKET_TYPE IS INPUT_PACKET(3) - X"41";
  820.  
  821.       IF
  822.          PACKET_TYPE GT 25
  823.  
  824.       THEN                                       @ Not in range A to Z         @
  825.          TYPE := INVALID_PKT;
  826.          RESULT := NON_PKT
  827.  
  828.       ELSF
  829.         (
  830.          TYPE := PACKET_CODES(PACKET_TYPE);
  831.          TYPE LT 0
  832.         )
  833.  
  834.       THEN
  835.          RESULT := TYPE;
  836.          TYPE := INVALID_PKT
  837.  
  838.       ELSE
  839.          REF INT DATA_LENGTH IS KMT_PP_INPUT_PACKET_DATA.DATA_LENGTH;
  840.  
  841.          REF () BYTE DATA IS KMT_PP_INPUT_PACKET_DATA.DATA;
  842.  
  843.          REF INT STATISTICS IS
  844.                     KMT_PP_PACKET_STATISTICS.INPUT_TOTAL;
  845.  
  846.          STATISTICS := STATISTICS + 1;
  847.          SEQ := INPUT_PACKET(2) - X"20";
  848.          DATA_LENGTH := INPUT_PACKET_LENGTH - 5;
  849.          MOVE (INPUT_PACKET(4 SIZE DATA_LENGTH),
  850.                DATA,
  851.                0,
  852.                X"00",
  853.                NIL,
  854.                NIL);
  855.          KMT_PH_INPUT_PACKET_DATA := DATA(SIZE DATA_LENGTH)
  856.       FI
  857.    FI
  858. END;                                   @ KMT_PP_GET_PACKET                     @
  859.  
  860. ***PAGE
  861.  
  862. GLOBAL
  863. STATIC (<STATUS 5>)
  864. PROC
  865.    KMT_PP_SEND_PACKET IS (
  866.    INT         TYPE,
  867.    INT         SEQ,
  868.    BOOL        PROMPT,
  869.    RESPONSE    RESULT):
  870.  
  871. @******************************************************************************@
  872. @*                                                                            *@
  873. @* This procedure is used to frame and send a KERMIT packet to the remote end.*@
  874. @* TYPE and SEQ specify the packet type and sequence number respectively.     *@
  875. @* The packet data and length is read from the areas                          *@
  876. @* KMT_PP_OUTPUT_PACKET_DATA.DATA and KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH   *@
  877. @* respectively.                                                              *@
  878. @* If PROMPT is set TRUE then read interest is set at the PFI for the next    *@
  879. @* input packet.                                                              *@
  880. @*                                                                            *@
  881. @******************************************************************************@
  882.  
  883. BEGIN
  884.    INT KMT_PP_PACKET_OUT_MSG IS 252;
  885.  
  886.    INT DATA_LENGTH IS KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH;
  887.  
  888.    REF () BYTE DATA IS KMT_PP_OUTPUT_PACKET_DATA.DATA;
  889.  
  890.    INT OUTPUT_PACKET_LENGTH IS 5 + DATA_LENGTH;
  891.  
  892.    (OUTPUT_PACKET_LENGTH) BYTE OUTPUT_PACKET;
  893.  
  894.    STATIC () BYTE PACKET_TYPES IS X"00"          @ Not used                    @
  895.                                   X"42"          @ B packet                    @
  896.                                   X"44"          @ D packet                    @
  897.                                   X"45"          @ E packet                    @
  898.                                   X"46"          @ F packet                    @
  899.                                   X"47"          @ G packet                    @
  900.                                   X"49"          @ I packet                    @
  901.                                   X"4B"          @ K packet                    @
  902.                                   X"4E"          @ N packet                    @
  903.                                   X"52"          @ R packet                    @
  904.                                   X"53"          @ S packet                    @
  905.                                   X"59"          @ Y packet                    @
  906.                                   X"5A";         @ Z packet                    @
  907.  
  908.    OUTPUT_PACKET(0) := KMT_PP_LOCAL_CONFG_PARAMS.MARK;
  909.    OUTPUT_PACKET(1) := DATA_LENGTH + 3 + X"20";
  910.    OUTPUT_PACKET(2) := SEQ + X"20";
  911.    OUTPUT_PACKET(3) := PACKET_TYPES(TYPE);
  912.    OUTPUT_PACKET(4 SIZE DATA_LENGTH) := DATA;
  913.    OUTPUT_PACKET(OUTPUT_PACKET_LENGTH - 1) := KMT_PP_GENERATE_CHECKSUM (
  914.                                                  OUTPUT_PACKET);
  915.  
  916.    IF
  917.       KMT_TRACE_FLAGS.PP_TRACING
  918.  
  919.    THEN (<RARELY>)
  920.      (
  921.       KMT_PP_LOG_TRACE_MESSAGE (KMT_PP_PACKET_OUT_MSG,
  922.                                 OUTPUT_PACKET)
  923.      )
  924.    FI;
  925.  
  926.    KMT_DH_OUTPUT (OUTPUT_PACKET,
  927.                   PROMPT,
  928.                   RESULT);
  929.  
  930.    IF
  931.       RESULT LE 0
  932.  
  933.    THEN
  934.       REF INT STATISTICS IS
  935.                  KMT_PP_PACKET_STATISTICS.OUTPUT_TOTAL;
  936.  
  937.       STATISTICS := STATISTICS + 1
  938.    FI
  939. END;                                   @ KMT_PP_SEND_PACKET                    @
  940.  
  941. ***PAGE
  942.  
  943. GLOBAL
  944. STATIC (<STATUS 5>)
  945. PROC
  946.    KMT_PP_BUILD_FILE_PACKET_DATA IS (
  947.    RESPONSE    RESULT):
  948.  
  949. @******************************************************************************@
  950. @*                                                                            *@
  951. @* This procedure is used to read file records and to construct data packets  *@
  952. @* from the record performing data translation, binary and control character  *@
  953. @* character quoting as appropriate.                                          *@
  954. @* The record and length are returned in the data areas                       *@
  955. @* KMT_FH_RECORD_DETAILS.RECORD and KMT_FH_RECORD_DETAILS.RECORD_LENGTH       *@
  956. @* respectively. The processed packet data and length are returned is the     *@
  957. @* data areas                                                                 *@
  958. @* KMT_PP_OUTPUT_PACKET_DATA.DATA and KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH   *@
  959. @* respectively.                                                              *@
  960. @* End of file is indicated by returning resultcode DML_READ_PSEUDO_NODE.     *@
  961. @*                                                                            *@
  962. @******************************************************************************@
  963.  
  964. BEGIN
  965.    INT DML_READ_PSEUDO_NODE IS 9034;
  966.  
  967.    REF BOOL END_OF_FILE IS KMT_FH_RECORD_DETAILS.END_OF_FILE;
  968.  
  969.    REF INT DATA_LENGTH IS KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH;
  970.  
  971.    RESULT := 0;
  972.  
  973.    IF
  974.       END_OF_FILE
  975.  
  976.    THEN                                          @ End of file reached during  @
  977.                                                  @ previous read               @
  978.       DATA_LENGTH := 0;
  979.       RESULT := DML_READ_PSEUDO_NODE
  980.  
  981.    ELSF
  982.      (
  983.       REF BOOL NEW_RECORD IS KMT_FH_RECORD_DETAILS.NEW_RECORD;
  984.  
  985.       WORD TEXT_TYPE IS KMT_FH_RECORD_DETAILS.TEXT_TYPE;
  986.  
  987.       REF INT RECORD_LENGTH IS KMT_FH_RECORD_DETAILS.RECORD_LENGTH;
  988.  
  989.       REF () BYTE RECORD IS KMT_FH_RECORD_DETAILS.RECORD;
  990.  
  991.       BYTE QCTL IS KMT_PP_LOCAL_CONFG_PARAMS.QCTL;
  992.  
  993.       BYTE MAXL IS KMT_PP_REMOTE_CONFG_PARAMS.MAXL;
  994.  
  995.       REF () BYTE DATA IS KMT_PP_OUTPUT_PACKET_DATA.DATA(SIZE MAXL - 5);
  996.  
  997.       () BYTE QCRQLF IS (QCTL, X"4D", QCTL, X"4A");
  998.                                                  @ Quoted CRLF                 @
  999.       INT D_LEN IS LENGTH DATA;
  1000.  
  1001.       REF () BYTE DATA_REM := DATA;
  1002.  
  1003.       (91) BYTE PP_TRACE_BUFFER;                 @ debug trace area            @
  1004.       REF () BYTE PP_TRACE_PTR := PP_TRACE_BUFFER;
  1005.       INT PP_TRACE_COUNT := 0;
  1006.  
  1007.       UNTIL
  1008.         (
  1009.          BOOL DATA_COMPLETE;
  1010.  
  1011.          IF
  1012.             NEW_RECORD
  1013.  
  1014.          AND
  1015.            (
  1016.             KMT_FH_READ (RESULT);
  1017.  
  1018.             IF
  1019.                RESULT LE 0
  1020.  
  1021.             THEN                                 @ Record read successfully    @
  1022.                KMT_PP_RECALL_DATA := RECORD(SIZE RECORD_LENGTH);
  1023.             FI;
  1024.  
  1025.             RESULT GT 0
  1026.            )
  1027.  
  1028.          THEN                                    @ Read error or end of file   @
  1029.             END_OF_FILE := TRUE;
  1030.             DATA_COMPLETE := TRUE
  1031.  
  1032.          ELSE                                    @ Build packet data from      @
  1033.                                                  @ record                      @
  1034.             REF () BYTE TRACE_PTR := KMT_PP_RECALL_DATA;
  1035.             INT TRACE_CT;
  1036.  
  1037.             DATA_COMPLETE := KMT_PP_BUILD_PACKET_DATA (KMT_PP_RECALL_DATA,
  1038.                                                        DATA_REM,
  1039.                                                        TEXT_TYPE,
  1040.                                                        NEW_RECORD);
  1041.  
  1042.                                                  @ copy source to trace buffer @
  1043.             TRACE_CT := LENGTH TRACE_PTR - LENGTH KMT_PP_RECALL_DATA;
  1044.             PP_TRACE_PTR(SIZE TRACE_CT) := TRACE_PTR(SIZE TRACE_CT);
  1045.             PP_TRACE_COUNT := PP_TRACE_COUNT + TRACE_CT;
  1046.             PP_TRACE_PTR := PP_TRACE_BUFFER(PP_TRACE_COUNT::);
  1047.  
  1048.             IF
  1049.                TEXT_TYPE EQ BINARY
  1050.  
  1051.             THEN                                 @ Binary file transfer don't  @
  1052.                                                  @ add CRLF end of record      @
  1053.                                                  @ marker                      @
  1054.                SKIP
  1055.  
  1056.             ELSF
  1057.                NEW_RECORD
  1058.  
  1059.             THEN                                 @ EBCDIC or ASCII file        @
  1060.                                                  @ transfer and end of record. @
  1061.                                                  @ Move in quote CRLF, end of  @
  1062.                                                  @ record marker               @
  1063.                NEW_RECORD := KMT_PP_MOVE (QCRQLF,
  1064.                                           DATA_REM,
  1065.                                           DATA_COMPLETE) NE 0;
  1066.  
  1067.                IF NEW_RECORD                    @ add new record mark to trace @
  1068.                THEN
  1069.                   PP_TRACE_PTR(SIZE 4) := IF TEXT_TYPE = EBCDIC
  1070.                                           THEN " // "
  1071.                                           ELSE X"202F2F20"
  1072.                                           FI;
  1073.                   PP_TRACE_COUNT := PP_TRACE_COUNT + 4;
  1074.                   PP_TRACE_PTR := PP_TRACE_BUFFER(PP_TRACE_COUNT::);
  1075.                FI
  1076.             FI
  1077.          FI;
  1078.  
  1079.          DATA_COMPLETE
  1080.         )
  1081.       DO
  1082.          SKIP
  1083.       REPEAT;
  1084.  
  1085.       DATA_LENGTH := D_LEN - LENGTH DATA_REM;
  1086.  
  1087.       IF KMT_TRACE_FLAGS.PP_TRACING AND PP_TRACE_COUNT > 0
  1088.       THEN (<RARELY>)
  1089.         (
  1090.          IF TEXT_TYPE = ASCII
  1091.          THEN
  1092.             TRANSLATE(ASCII_TO_EBCDIC,
  1093.                       PP_TRACE_BUFFER(SIZE PP_TRACE_COUNT),
  1094.                       0,
  1095.                       NIL)
  1096.          FI;
  1097.  
  1098.          KMT_PP_DATA_TRACE_MESSAGE(KMT_PP_PACKET_DATA_OUT_MSG,
  1099.                                    TEXT_TYPE,
  1100.                                    PP_TRACE_BUFFER(SIZE PP_TRACE_COUNT))
  1101.         )
  1102.       FI;
  1103.  
  1104.       (RESULT EQ DML_READ_PSEUDO_NODE)  AND  (DATA_LENGTH NE 0)
  1105.      )
  1106.  
  1107.    THEN                                          @ End of file reached but     @
  1108.                                                  @ packet data remains.        @
  1109.                                                  @ Return end of file on next  @
  1110.                                                  @ call                        @
  1111.       RESULT := 0
  1112.    FI
  1113. END;                                   @ KMT_PP_BUILD_FILE_PACKET_DATA         @
  1114.  
  1115. ***PAGE
  1116.  
  1117. GLOBAL
  1118. STATIC (<STATUS 5>)
  1119. PROC
  1120.    KMT_PP_BUILD_STRING_PACKET_DATA IS (
  1121.    REF () BYTE STRING,
  1122.    RESPONSE    RESULT):
  1123.  
  1124. @******************************************************************************@
  1125. @*                                                                            *@
  1126. @* This procedure is used to translate the data held in STRING from EBCDIC to *@
  1127. @* ASCII.                                                                     *@
  1128. @* The translated data and length is returned in the area                     *@
  1129. @* KMT_PP_OUTPUT_PACKET_DATA.DATA and KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH   *@
  1130. @* respectively.                                                              *@
  1131. @* If the translated data length exceeds the maximum packet data length then  *@
  1132. @* resultcode KMT_PP_STRING_TOO_BIG is returned.                              *@
  1133. @*                                                                            *@
  1134. @******************************************************************************@
  1135.  
  1136. BEGIN
  1137.    INT KMT_PP_STRING_TOO_BIG IS 80256;
  1138.  
  1139.    INT MAXL IS KMT_PP_REMOTE_CONFG_PARAMS.MAXL;
  1140.  
  1141.    REF INT DATA_LENGTH IS KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH;
  1142.  
  1143.    REF () BYTE DATA IS KMT_PP_OUTPUT_PACKET_DATA.DATA(SIZE MAXL - 5);
  1144.  
  1145.    INT STRING_LENGTH IS IF
  1146.                            STRING IS NIL
  1147.                         THEN
  1148.                            0
  1149.                         ELSE
  1150.                            LENGTH STRING
  1151.                         FI;
  1152.  
  1153.    IF
  1154.       STRING_LENGTH EQ 0
  1155.  
  1156.    THEN                                          @ NIL or ZLR supplied         @
  1157.       DATA_LENGTH := 0;
  1158.       RESULT := 0
  1159.  
  1160.    ELSE
  1161.       () BYTE STRING_COPY := STRING;             @ Don't want to corrupt       @
  1162.                                                  @ original string             @
  1163.  
  1164.       REF () BYTE STRING_POINTER := STRING_COPY,
  1165.                   DATA_REM       := DATA;
  1166.  
  1167.       RESULT := IF
  1168.                   (
  1169.                    BOOL STRING_COMPLETE := TRUE;
  1170.  
  1171.                    KMT_PP_BUILD_PACKET_DATA (STRING_POINTER,
  1172.                                              DATA_REM,
  1173.                                              EBCDIC,
  1174.                                              STRING_COMPLETE);
  1175.                    STRING_COMPLETE
  1176.                   )
  1177.                 THEN
  1178.                    0
  1179.                 ELSE                             @ String too big              @
  1180.                    KMT_PP_STRING_TOO_BIG
  1181.                 FI;
  1182.  
  1183.       DATA_LENGTH := LENGTH DATA - LENGTH DATA_REM;
  1184.  
  1185.       IF KMT_TRACE_FLAGS.PP_TRACING
  1186.       THEN (<RARELY>)
  1187.         (
  1188.          KMT_PP_DATA_TRACE_MESSAGE(KMT_PP_PACKET_DATA_OUT_MSG,EBCDIC,
  1189.                            STRING(SIZE (STRING_LENGTH - LENGTH STRING_POINTER)))
  1190.         )
  1191.       FI
  1192.    FI;
  1193. END;                                   @ KMT_PP_BUILD_STRING_PACKET_DATA       @
  1194.  
  1195. ***PAGE
  1196.  
  1197. GLOBAL
  1198. STATIC (<STATUS 5>)
  1199. PROC
  1200.    KMT_PP_BUILD_FILE_RECORD IS (
  1201.    RESPONSE    RESULT):
  1202.  
  1203. @******************************************************************************@
  1204. @*                                                                            *@
  1205. @* This procedure is used to construct file records from KERMIT data packets  *@
  1206. @* received. For text files control character quoting and data translation    *@
  1207. @* from ASCII to EBCDIC is performed. For binary files control character      *@
  1208. @* quoting and 8th bit quoting is performed.                                  *@
  1209. @* The packet data is read from the area referenced by                        *@
  1210. @* KMT_PH_INPUT_PACKET_DATA. The processed record and length is returned in   *@
  1211. @* the areas KMT_FH_RECORD_DETAILS.RECORD and                                 *@
  1212. @* KMT_FH_RECORD_DETAILS.RECORD.LENGTH respectively.                          *@
  1213. @* When the end of record is detected the record is written to the file.      *@
  1214. @*                                                                            *@
  1215. @******************************************************************************@
  1216.  
  1217. BEGIN
  1218.  
  1219.    INT KMT_PP_RECORD_TOO_BIG IS 80255;
  1220.  
  1221.    REF () BYTE DATA := KMT_PH_INPUT_PACKET_DATA;
  1222.  
  1223.    INT DATA_LENGTH IS LENGTH DATA;
  1224.  
  1225.    REF BOOL NEW_RECORD IS KMT_FH_RECORD_DETAILS.NEW_RECORD;
  1226.  
  1227.    WORD TEXT_TYPE IS KMT_FH_RECORD_DETAILS.TEXT_TYPE;
  1228.  
  1229.    INT MAX_RECORD_LENGTH := KMT_FH_RECORD_DETAILS.MAX_RECORD_LENGTH;
  1230.  
  1231.    REF INT RECORD_LENGTH IS KMT_FH_RECORD_DETAILS.RECORD_LENGTH;
  1232.  
  1233.    INT RECORD_SIZE IS IF
  1234.                           TEXT_TYPE EQ BINARY
  1235.                       THEN                       @ Binary file transfer. CRLF  @
  1236.                                                  @ end of record terminator    @
  1237.                                                  @ not required                @
  1238.                           MAX_RECORD_LENGTH
  1239.                       ELSE                       @ EBCDIC or ASCII file xfer.  @
  1240.                                                  @ Allow for CRLF pair, end of @
  1241.                                                  @ record terminator           @
  1242.                           MAX_RECORD_LENGTH + 2
  1243.                       FI;
  1244.  
  1245.    REF () BYTE RECORD IS KMT_FH_RECORD_DETAILS.RECORD(SIZE RECORD_SIZE);
  1246.  
  1247.    () BYTE LF IS X"0A",                          @ ASCII LF                    @
  1248.            CR IS X"0D";                          @ CR                          @
  1249.  
  1250.    () BYTE CRLF IS (CR,LF);
  1251.  
  1252.    BOOL DATA_COMPLETE := (DATA_LENGTH LE 0);
  1253.  
  1254.    (96) BYTE PP_TRACE_BUFFER;                    @ packet trace variables      @
  1255.    REF () BYTE PP_TRACE_PTR := PP_TRACE_BUFFER,
  1256.                TRACE_PTR := KMT_PP_RECALL_DATA;
  1257.    INT PP_TRACE_COUNT := 0;
  1258.  
  1259.    RESULT := 0;
  1260.  
  1261.    UNTIL
  1262.       DATA_COMPLETE  OR  (RESULT GT 0)
  1263.    DO
  1264.       INT LAST_CHAR_INDEX IS IF
  1265.                                 NEW_RECORD
  1266.                              THEN
  1267.                                 KMT_PP_RECALL_DATA := RECORD;
  1268.                                 TRACE_PTR := RECORD; @ (for trace)             @
  1269.                                 -1
  1270.                              ELSE
  1271.                                 RECORD_SIZE - (LENGTH KMT_PP_RECALL_DATA + 1)
  1272.                              FI;
  1273.  
  1274.       BYTE UNQUOTED_CHAR;
  1275.  
  1276.       INT SEQUENCE_LENGTH;
  1277.  
  1278.       KMT_PP_UNQUOTE_CHAR (DATA,
  1279.                            UNQUOTED_CHAR,
  1280.                            SEQUENCE_LENGTH);
  1281.  
  1282.       IF
  1283.          KMT_PP_MOVE (UNQUOTED_CHAR,
  1284.                       KMT_PP_RECALL_DATA,
  1285.                       NEW_RECORD) NE 0
  1286.  
  1287.       THEN                                       @ Moved in data               @
  1288.          DATA_COMPLETE := KMT_PP_CHECK_COMPLETE (SEQUENCE_LENGTH,
  1289.                                                  DATA);
  1290.       FI;
  1291.  
  1292.       IF
  1293.          TEXT_TYPE EQ BINARY
  1294.  
  1295.       THEN                                       @ Binary file transfer        @
  1296.          RECORD_LENGTH := RECORD_SIZE - LENGTH KMT_PP_RECALL_DATA;
  1297.  
  1298.          IF
  1299.             NEW_RECORD
  1300.  
  1301.          THEN                                    @ Record complete, output it  @
  1302.                                                  @ (obtain trace info)         @
  1303.             INT TRACE_CT := LENGTH TRACE_PTR - LENGTH KMT_PP_RECALL_DATA;
  1304.             PP_TRACE_PTR(SIZE TRACE_CT) := TRACE_PTR(SIZE TRACE_CT);
  1305.             PP_TRACE_COUNT := PP_TRACE_COUNT + TRACE_CT;
  1306.             PP_TRACE_PTR := PP_TRACE_BUFFER(PP_TRACE_COUNT::);
  1307.  
  1308.             KMT_FH_WRITE (RESULT)                @ output record               @
  1309.          FI
  1310.  
  1311.       ELSF
  1312.          (LAST_CHAR_INDEX GE 0)  AND  (RECORD(LAST_CHAR_INDEX SIZE 2) EQ CRLF)
  1313.  
  1314.       THEN                                       @ EBCDIC or ASCII file xfer   @
  1315.                                                  @ end of record, output it    @
  1316.                                                  @ (obtain trace info)         @
  1317.          INT TRACE_CT := LENGTH TRACE_PTR - (LENGTH KMT_PP_RECALL_DATA + 2);
  1318.          IF TRACE_CT = -1                    @ CR LF split between two packets @
  1319.          THEN
  1320.             TRACE_CT := 0
  1321.          ELSE
  1322.             PP_TRACE_PTR(SIZE TRACE_CT) := TRACE_PTR(SIZE TRACE_CT);
  1323.          FI;
  1324.          PP_TRACE_PTR := PP_TRACE_BUFFER((PP_TRACE_COUNT + TRACE_CT)::);
  1325.          PP_TRACE_PTR(SIZE 4) := X"202F2F20";
  1326.          PP_TRACE_COUNT := PP_TRACE_COUNT + TRACE_CT + 4;
  1327.          PP_TRACE_PTR := PP_TRACE_BUFFER(PP_TRACE_COUNT::);
  1328.  
  1329.          RECORD_LENGTH := RECORD_SIZE - (LENGTH KMT_PP_RECALL_DATA + 2);
  1330.                                                  @ Don't want CRLF in file     @
  1331.  
  1332.          IF
  1333.             TEXT_TYPE EQ EBCDIC
  1334.  
  1335.          THEN                                    @ EBCDIC file transfer        @
  1336.             TRANSLATE (ASCII_TO_EBCDIC,
  1337.                        RECORD(SIZE RECORD_LENGTH),
  1338.                        0,
  1339.                        NIL)
  1340.          FI;
  1341.  
  1342.          KMT_FH_WRITE (RESULT);
  1343.          NEW_RECORD := TRUE
  1344.  
  1345.       ELSF
  1346.          (
  1347.           RECORD_LENGTH := RECORD_SIZE - LENGTH KMT_PP_RECALL_DATA;
  1348.           NEW_RECORD
  1349.          )
  1350.  
  1351.       THEN                                       @ EBCDIC or ASCII file xfer   @
  1352.                                                  @ and record buffer full but  @
  1353.                                                  @ no end of record found.     @
  1354.          () KMT_MTM_VALUES PARAMS := DISPLAY(MAX_RECORD_LENGTH
  1355.                                              AS KMT_MTM_VALUES.RI_VALUE);
  1356.  
  1357.          RESULT := KMT_PP_RECORD_TOO_BIG;
  1358.          KMT_EH_LOG_ERROR (RESULT,
  1359.                            2,
  1360.                            PARAMS,
  1361.                            0,
  1362.                            FALSE,
  1363.                            FALSE)
  1364.       FI
  1365.    REPEAT;
  1366.  
  1367.    IF KMT_TRACE_FLAGS.PP_TRACING
  1368.    THEN (<RARELY>)
  1369.      (
  1370.       IF DATA_COMPLETE AND NOT NEW_RECORD       @ (obtain rest of trace info) @
  1371.       THEN
  1372.          INT TRACE_CT := LENGTH TRACE_PTR - LENGTH KMT_PP_RECALL_DATA;
  1373.          PP_TRACE_PTR(SIZE TRACE_CT) := TRACE_PTR(SIZE TRACE_CT);
  1374.          PP_TRACE_COUNT := PP_TRACE_COUNT + TRACE_CT
  1375.       FI;
  1376.  
  1377.       IF PP_TRACE_COUNT > 0
  1378.       THEN
  1379.          IF TEXT_TYPE NE BINARY
  1380.          THEN
  1381.             TRANSLATE(ASCII_TO_EBCDIC,
  1382.                       PP_TRACE_BUFFER(SIZE PP_TRACE_COUNT),
  1383.                       0,
  1384.                       NIL)
  1385.          FI;
  1386.  
  1387.          KMT_PP_DATA_TRACE_MESSAGE(KMT_PP_PACKET_DATA_IN_MSG,
  1388.                                    TEXT_TYPE,
  1389.                                    PP_TRACE_BUFFER(SIZE PP_TRACE_COUNT))
  1390.       FI
  1391.      )
  1392.    FI
  1393.  
  1394. END;                                   @ KMT_PP_BUILD_FILE_RECORD              @
  1395.  
  1396. ***PAGE
  1397.  
  1398. GLOBAL
  1399. STATIC (<STATUS 5>)
  1400. PROC
  1401.    KMT_PP_BUILD_PARAM_PACKET_DATA IS ():
  1402.  
  1403. @******************************************************************************@
  1404. @*                                                                            *@
  1405. @* This procedure is used to construct the packet data from the configuration *@
  1406. @* parameters.                                                                *@
  1407. @* The configuration parameters are read from the area                        *@
  1408. @* KMT_PP_LOCAL_CONFG_PARAMS and the packet data and length is returned in    *@
  1409. @* the areas KMT_PP_OUTPUT_PACKET_DATA.DATA and                               *@
  1410. @* KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH respectively.                        *@
  1411. @*                                                                            *@
  1412. @******************************************************************************@
  1413.  
  1414. BEGIN
  1415.    REF () BYTE DATA IS KMT_PP_OUTPUT_PACKET_DATA.DATA;
  1416.  
  1417.    BYTE N IS X"4E";                             @ ASCII N                     @
  1418.  
  1419.    DATA(0) := KMT_PP_LOCAL_CONFG_PARAMS.MAXL + X"20";
  1420.    DATA(1) := KMT_PP_LOCAL_CONFG_PARAMS.TIME + X"20";
  1421.    DATA(2) := KMT_PP_LOCAL_CONFG_PARAMS.NPAD + X"20";
  1422.    DATA(3) := KMT_PP_LOCAL_CONFG_PARAMS.PADC NEQ X"40";
  1423.    DATA(4) := KMT_PP_LOCAL_CONFG_PARAMS.EOL + X"20";
  1424.    DATA(5) := KMT_PP_LOCAL_CONFG_PARAMS.QCTL;
  1425.    DATA(6) := IF
  1426.                  KMT_FH_RECORD_DETAILS.TEXT_TYPE NE EBCDIC
  1427.               THEN                               @ ASCII or binary file xfer   @
  1428.                                                  @ requested, do 8th bit       @
  1429.                                                  @ quoting                     @
  1430.                  KMT_PP_LOCAL_CONFG_PARAMS.QBIN
  1431.               ELSE                               @ EBCDIC file transfer        @
  1432.                                                  @ requested, donot do 8th bit @
  1433.                                                  @ quoting                     @
  1434.                  N
  1435.               FI;
  1436.                                                  @ We don't support any others @
  1437.                                                  @ so default them             @
  1438.    KMT_PP_OUTPUT_PACKET_DATA.DATA_LENGTH := 7;
  1439.  
  1440.    IF KMT_TRACE_FLAGS.PP_TRACING
  1441.    THEN (<RARELY>)
  1442.      (
  1443.       () INT P := (KMT_PP_LOCAL_CONFG_PARAMS.MAXL,
  1444.                    KMT_PP_LOCAL_CONFG_PARAMS.TIME,
  1445.                    KMT_PP_LOCAL_CONFG_PARAMS.NPAD);
  1446.  
  1447.       () KMT_MTM_VALUES PARAMS := (P(0)
  1448.                                    AS KMT_MTM_VALUES.RI_VALUE,
  1449.                                    P(1)
  1450.                                    AS KMT_MTM_VALUES.RI_VALUE,
  1451.                                    P(2)
  1452.                                    AS KMT_MTM_VALUES.RI_VALUE,
  1453.                                    KMT_PP_LOCAL_CONFG_PARAMS.PADC
  1454.                                    AS KMT_MTM_VALUES.RVB_VALUE,
  1455.                                    KMT_PP_LOCAL_CONFG_PARAMS.EOL
  1456.                                    AS KMT_MTM_VALUES.RVB_VALUE,
  1457.                                    KMT_PP_LOCAL_CONFG_PARAMS.QCTL
  1458.                                    AS KMT_MTM_VALUES.RVB_VALUE,
  1459.                                    DATA(6)
  1460.                                    AS KMT_MTM_VALUES.RVB_VALUE);
  1461.  
  1462.       KMT_SP_LOG_TRACE_MESSAGE(KMT_PP_PARAM_OUT_MSG,PARAMS)
  1463.      )
  1464.    FI
  1465.  
  1466. END;                                   @ KMT_PP_BUILD_PARAM_PACKET_DATA        @
  1467.  
  1468. ***PAGE
  1469.  
  1470. GLOBAL
  1471. STATIC (<STATUS 5>)
  1472. PROC
  1473.    KMT_PP_PROCESS_PARAM_PACKET_DATA IS (
  1474.    RESPONSE RESULT):
  1475.  
  1476. @******************************************************************************@
  1477. @*                                                                            *@
  1478. @* This procedure is used to extract the configuration parameters from the    *@
  1479. @* packet data.                                                               *@
  1480. @* The packet data is read from the area referenced by                        *@
  1481. @* KMT_PH_INPUT_PACKET_DATA and the configuration parameters are returned in  *@
  1482. @* the area KMT_PP_REMOTE_CONFG_PARAMS.                                       *@
  1483. @*                                                                            *@
  1484. @******************************************************************************@
  1485.  
  1486. BEGIN
  1487.  
  1488. ***PAGE
  1489.  
  1490. SIM
  1491. PROC
  1492. KMT_PP_LOG_PARAM_ERROR IS (
  1493.    INT NAME_CODE,
  1494.    REF () BYTE VALUE,
  1495.    INT REASON_CODE,
  1496.    RESPONSE    RESULT):
  1497.  
  1498. @******************************************************************************@
  1499. @*                                                                            *@
  1500. @* This procedure is used to log configuration parameter validation errors to *@
  1501. @* the job journal.                                                           *@
  1502. @*                                                                            *@
  1503. @******************************************************************************@
  1504.  
  1505. BEGIN
  1506.    INT KMT_PP_INVALID_CONFIG_PARAM IS 80257;
  1507.    INT NAME := NAME_CODE,
  1508.        REASON := REASON_CODE;
  1509.  
  1510.    () KMT_MTM_VALUES PARAMS := (NAME
  1511.                                 AS KMT_MTM_VALUES.RI_VALUE,
  1512.                                 VALUE
  1513.                                 AS KMT_MTM_VALUES.RVB_VALUE,
  1514.                                 REASON
  1515.                                 AS KMT_MTM_VALUES.RI_VALUE);
  1516.  
  1517.    RESULT := KMT_PP_INVALID_CONFIG_PARAM;
  1518.  
  1519.    KMT_EH_LOG_ERROR (RESULT,2,PARAMS,0,FALSE,FALSE)
  1520.  
  1521. END;                                   @ KMT_PP_LOG_PARAM_ERROR                @
  1522.  
  1523. ***PAGE
  1524.  
  1525.    INT KMT_PP_QBIN_AND_QCTL_EQUAL IS 80258,
  1526.        KMT_PP_QCTL_WARNING        IS -80259,
  1527.        KMT_PP_QBIN_REJECTED       IS 80260;
  1528.  
  1529.    INT MAXL_CODE IS 0,
  1530.        NPAD_CODE IS 1,
  1531.        PADC_CODE IS 2,
  1532.        EOL_CODE  IS 3,
  1533.        QCTL_CODE IS 4,
  1534.        QBIN_CODE IS 5;
  1535.  
  1536.    INT INFO_LENGTH IS SIZEOF KMT_PP_CONFG_PARAMS_S;
  1537.  
  1538.    (INFO_LENGTH) BYTE PACKET_INFO;
  1539.  
  1540.    WORD MAX_OUTPUT_LENGTH IS KMT_DH_DEVICE_DETAILS.MAX_OUTPUT_LENGTH;
  1541.  
  1542.    WORD TEXT_TYPE IS KMT_FH_RECORD_DETAILS.TEXT_TYPE;
  1543.  
  1544.    WORD MIN_PACKET_LENGTH IS 30;
  1545.  
  1546.    INT DATA_LENGTH IS LENGTH KMT_PH_INPUT_PACKET_DATA;
  1547.  
  1548.    REF BYTE MAXL IS KMT_PP_REMOTE_CONFG_PARAMS.MAXL,
  1549.             TIME IS KMT_PP_REMOTE_CONFG_PARAMS.TIME,
  1550.             NPAD IS KMT_PP_REMOTE_CONFG_PARAMS.NPAD,
  1551.             PADC IS KMT_PP_REMOTE_CONFG_PARAMS.PADC,
  1552.             EOL  IS KMT_PP_REMOTE_CONFG_PARAMS.EOL,
  1553.             QCTL IS KMT_PP_REMOTE_CONFG_PARAMS.QCTL,
  1554.             QBIN IS KMT_PP_REMOTE_CONFG_PARAMS.QBIN,
  1555.             CHKT IS KMT_PP_REMOTE_CONFG_PARAMS.CHKT,
  1556.             REPT IS KMT_PP_REMOTE_CONFG_PARAMS.REPT;
  1557.  
  1558.    REF 4-BYTE CAPAS IS KMT_PP_REMOTE_CONFG_PARAMS.CAPAS;
  1559.  
  1560.    REF BYTE LOCAL_MARK IS KMT_PP_LOCAL_CONFG_PARAMS.MARK,
  1561.             LOCAL_QCTL IS KMT_PP_LOCAL_CONFG_PARAMS.QCTL,
  1562.             LOCAL_QBIN IS KMT_PP_LOCAL_CONFG_PARAMS.QBIN;
  1563.  
  1564.    INT RC;
  1565.  
  1566.    BYTE PARAM;
  1567.  
  1568.    BYTE NUL    IS X"00",                         @ ASCII NUL                   @
  1569.         CR     IS X"0D",                         @ CR                          @
  1570.         SPACE  IS X"20",                         @ Space                       @
  1571.         HASH   IS X"23",                         @ #                           @
  1572.         ONE    IS X"31",                         @ 1                           @
  1573.         RAB    IS X"3E",                         @ >                           @
  1574.         CTLNUL IS X"40",                         @ Controlled NUL              @
  1575.         N      IS X"4E",                         @ N                           @
  1576.         Y      IS X"59",                         @ Y                           @
  1577.         GRAVE  IS X"60",                         @ `                           @
  1578.         TILDE  IS X"7E",                         @ ~                           @
  1579.         DEL    IS X"7F";                         @ DEL                         @
  1580.  
  1581.    RESULT := 0;
  1582.  
  1583.    MOVEBYTE (SPACE,                              @ Set defaults                @
  1584.              PACKET_INFO,
  1585.              0,
  1586.              NIL);
  1587.    PACKET_INFO(3) := CTLNUL;                     @ PADC default                @
  1588.  
  1589.    PACKET_INFO(SIZE DATA_LENGTH) := KMT_PH_INPUT_PACKET_DATA;
  1590.  
  1591.    IF KMT_TRACE_FLAGS.PP_TRACING
  1592.    THEN (<RARELY>)
  1593.      (
  1594.       () INT IP := (PACKET_INFO(0) - X"20",
  1595.                     PACKET_INFO(1) - X"20",
  1596.                     PACKET_INFO(2) - X"20",
  1597.                     PACKET_INFO(7) - X"30");
  1598.  
  1599.       () BYTE BP := (PACKET_INFO(3) NEQ X"40",
  1600.                      PACKET_INFO(4) - X"20");
  1601.  
  1602.       () KMT_MTM_VALUES PARAMS := (IP(0)                               @ MAXL  @
  1603.                                    AS KMT_MTM_VALUES.RI_VALUE,
  1604.                                    IP(1)                               @ TIME  @
  1605.                                    AS KMT_MTM_VALUES.RI_VALUE,
  1606.                                    IP(2)                               @ NPAD  @
  1607.                                    AS KMT_MTM_VALUES.RI_VALUE,
  1608.                                    BP(0)                               @ PADC  @
  1609.                                    AS KMT_MTM_VALUES.RVB_VALUE,
  1610.                                    BP(1)                               @ EOL   @
  1611.                                    AS KMT_MTM_VALUES.RVB_VALUE,
  1612.                                    PACKET_INFO(5)                      @ QBIN  @
  1613.                                    AS KMT_MTM_VALUES.RVB_VALUE,
  1614.                                    PACKET_INFO(6)                      @ QCTL  @
  1615.                                    AS KMT_MTM_VALUES.RVB_VALUE,
  1616.                                    IP(3)                               @ CHKT  @
  1617.                                    AS KMT_MTM_VALUES.RI_VALUE,
  1618.                                    PACKET_INFO(8)                      @ REPT  @
  1619.                                    AS KMT_MTM_VALUES.RVB_VALUE,
  1620.                                    PACKET_INFO(9 SIZE 4)               @ CAPAS @
  1621.                                    AS KMT_MTM_VALUES.RVB_VALUE);
  1622.  
  1623.       KMT_SP_LOG_TRACE_MESSAGE(KMT_PP_PARAM_IN_MSG,PARAMS(SIZE DATA_LENGTH))
  1624.      )
  1625.    FI;
  1626.  
  1627.    PARAM := PACKET_INFO(0) - X"20";
  1628.    MAXL := IF
  1629.               (PARAM EQ 0)
  1630.            OR
  1631.               (PARAM GE MAX_OUTPUT_LENGTH)
  1632.            THEN                                  @ Defaulted or greater than   @
  1633.                                                  @ device line length          @
  1634.                MAX_OUTPUT_LENGTH
  1635.            ELSE
  1636.                PARAM
  1637.            FI;
  1638.  
  1639.    TIME := PACKET_INFO(1) - X"20";
  1640.    NPAD := PACKET_INFO(2) - X"20";
  1641.    PADC := PACKET_INFO(3) NEQ X"40";
  1642.    PARAM := PACKET_INFO(4) - X"20";
  1643.    EOL := IF
  1644.              PARAM EQ 0
  1645.           THEN                                   @ defaulted, set to CR        @
  1646.              CR
  1647.           ELSE
  1648.              PARAM
  1649.           FI;
  1650.  
  1651.    PARAM := PACKET_INFO(5);
  1652.    QCTL := IF
  1653.               PARAM EQ SPACE
  1654.            THEN                                  @ Defaulted, set to #         @
  1655.                HASH
  1656.            ELSE
  1657.                PARAM
  1658.            FI;
  1659.  
  1660.    PARAM := PACKET_INFO(6);
  1661.    QBIN := IF
  1662.               PARAM EQ N                         @ ASCII N                     @
  1663.            THEN                                  @ 8th bit quoting rejected    @
  1664.               SPACE
  1665.            ELSF
  1666.               PARAM EQ Y                         @ ASCII Y                     @
  1667.            THEN                                  @ 8th bit quoting requested   @
  1668.               LOCAL_QBIN
  1669.            ELSE
  1670.               PARAM
  1671.            FI;
  1672.                                                  @ We donot support any others @
  1673.                                                  @ so default them             @
  1674.    CHKT  := ONE;
  1675.    REPT  := NUL;
  1676.    CAPAS := NUL;
  1677.                                                  @ Validate configuration      @
  1678.                                                  @ parameters                  @
  1679.    IF MAXL LT MIN_PACKET_LENGTH
  1680.    THEN                                          @ Invalid MAXL parameter      @
  1681.       KMT_PP_LOG_PARAM_ERROR (MAXL_CODE,MAXL,80270,RESULT)
  1682.    FI;
  1683.  
  1684.    IF (MAXL + NPAD) LE MAX_OUTPUT_LENGTH
  1685.    THEN
  1686.       SKIP
  1687.    ELSF                                          @ Device line length exceeded @
  1688.      (                                           @ Adjust MAXL                 @
  1689.       MAXL := MAX_OUTPUT_LENGTH - NPAD;
  1690.       MAXL LT MIN_PACKET_LENGTH
  1691.      )
  1692.    THEN                                          @ NPAD parameter invalid      @
  1693.       KMT_PP_LOG_PARAM_ERROR (NPAD_CODE,NPAD,80271,RESULT)
  1694.    FI;
  1695.  
  1696.    IF (PADC GT SPACE)  AND  (PADC NE DEL)
  1697.    THEN                                          @ Invalid PADC character      @
  1698.       KMT_PP_LOG_PARAM_ERROR (PADC_CODE,PADC,80272,RESULT)
  1699.    FI;
  1700.  
  1701.    IF EOL = LOCAL_MARK
  1702.    THEN                                          @ EOL conflicts with MARK     @
  1703.       KMT_PP_LOG_PARAM_ERROR (EOL_CODE,EOL,80276,RESULT)
  1704.    ELSF KMT_SP_CHECK_VME_CHAR(EOL,1,RC);
  1705.         RC NE 0
  1706.    THEN                                          @ EOL not acceptable to VME   @
  1707.       KMT_PP_LOG_PARAM_ERROR (EOL_CODE,EOL,80274,RESULT)
  1708.    FI;
  1709.  
  1710.    IF NPAD > 0
  1711.    THEN                                          @ check for PADC conflict     @
  1712.       IF PADC = LOCAL_MARK
  1713.       THEN                                       @ PADC conflicts with MARK    @
  1714.          KMT_PP_LOG_PARAM_ERROR (PADC_CODE,PADC,80276,RESULT)
  1715.       ELSF PADC = EOL
  1716.       THEN                                       @ PADC conflicts with EOL     @
  1717.          KMT_PP_LOG_PARAM_ERROR (PADC_CODE,PADC,80277,RESULT)
  1718.       ELSF KMT_SP_CHECK_VME_CHAR(PADC,1,RC);
  1719.            RC NE 0
  1720.       THEN                                      @ PADC not acceptable to VME   @
  1721.          KMT_PP_LOG_PARAM_ERROR (PADC_CODE,PADC,80274,RESULT)
  1722.       FI
  1723.    FI;
  1724.  
  1725.    IF (QCTL LE SPACE)  OR  (QCTL GE DEL)
  1726.    THEN                                          @ Invalid QCTL character      @
  1727.       KMT_PP_LOG_PARAM_ERROR (QCTL_CODE,QCTL,80273,RESULT)
  1728.    FI;
  1729.  
  1730.    IF (QCTL GT RAB)  AND  (QCTL LT GRAVE)
  1731.    THEN
  1732.       @ KERMIT protocol permits the QCTL character to be any printable         @
  1733.       @ character. However a QCTL character value in the range X3F to X5F may  @
  1734.       @ result in data corruption. A warning message is logged but the choice  @
  1735.       @ of QCTL is permitted as the protocol allows it. eg Consider a QCTL     @
  1736.       @ character of '?' (X3F) and data containing the character DEL (X7F).    @
  1737.       @ The sender encodes this as a two byte sequence: QCTL (DEL XOR X40)     @
  1738.       @ ie '??' (X3F3F). The quoting rule states that QCTL caharacters         @
  1739.       @ appearing in the data must also be prefixed. Therefore the receiver    @
  1740.       @ will decode the sequence as '?' (X3F) not DEL (X7F) as required.       @
  1741.  
  1742.       BYTE CORRUPTED_CHAR := (QCTL NEQ X"40");
  1743.  
  1744.       () KMT_MTM_VALUES PARAMS := (QCTL
  1745.                                    AS KMT_MTM_VALUES.RVB_VALUE,
  1746.                                    CORRUPTED_CHAR
  1747.                                    AS KMT_MTM_VALUES.RVB_VALUE);
  1748.  
  1749.       KMT_EH_LOG_ERROR (KMT_PP_QCTL_WARNING,2,PARAMS,0,FALSE,FALSE)
  1750.    FI;
  1751.  
  1752.    IF                                                         TEXT_TYPE EQ EBCDIC
  1753.    THEN                                          @ EBCDIC file transfer        @
  1754.       SKIP
  1755.    ELSF
  1756.          (QBIN LT SPACE)
  1757.       OR
  1758.          (QBIN GT TILDE)
  1759.       OR
  1760.          ((QBIN GT RAB)  AND  (QBIN LT GRAVE))
  1761.  
  1762.    THEN                                          @ Invalid QBIN character      @
  1763.       KMT_PP_LOG_PARAM_ERROR (QBIN_CODE,QBIN,80275,RESULT)
  1764.    ELSF
  1765.       QBIN EQ SPACE
  1766.    THEN                                          @ QBIN character rejected     @
  1767.       RESULT := KMT_PP_QBIN_REJECTED;
  1768.       KMT_EH_LOG_ERROR (RESULT,2,NIL,0,FALSE,FALSE)
  1769.    ELSF
  1770.       QBIN EQ QCTL  OR  QBIN EQ LOCAL_QCTL
  1771.    THEN                                          @ ASCII or binary file xfer,  @
  1772.                                                  @ but QBIN and QCTL characters@
  1773.                                                  @ are equal                   @
  1774.       () KMT_MTM_VALUES PARAMS := (QBIN
  1775.                                    AS KMT_MTM_VALUES.RVB_VALUE,
  1776.                                    QCTL
  1777.                                    AS KMT_MTM_VALUES.RVB_VALUE,
  1778.                                    LOCAL_QCTL
  1779.                                    AS KMT_MTM_VALUES.RVB_VALUE);
  1780.  
  1781.       RESULT := KMT_PP_QBIN_AND_QCTL_EQUAL;
  1782.       KMT_EH_LOG_ERROR (RESULT,2,PARAMS,0,FALSE,FALSE)
  1783.    ELSE                                          @ IA5 or binary file transfer,@
  1784.                                                  @ and QCTL and QBIN characters@
  1785.                                                  @ are acceptable              @
  1786.       LOCAL_QBIN := QBIN
  1787.    FI
  1788. END;                                   @ KMT_PP_PROCESS_PARAM_PACKET_DATA      @
  1789. ENDMODULE                              @ KMT_PP_MODULE                         @
  1790.