home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / b / vmsfil.bli < prev    next >
Text File  |  2020-01-01  |  57KB  |  2,722 lines

  1. MODULE KERFIL (IDENT = '3.3.119',
  2.     ADDRESSING_MODE(EXTERNAL = GENERAL, NONEXTERNAL = GENERAL)) =
  3. BEGIN
  4. !<BLF/WIDTH:90>
  5.  
  6. !++
  7. ! FACILITY:
  8. !    KERMIT-32 Microcomputer to mainframe file transfer utility.
  9. !
  10. ! ABSTRACT:
  11. !    KERFIL contains all of the file processing for KERMIT-32.  This
  12. !    module contains the routines to input/output characters to files
  13. !    and to open and close the files.
  14. !
  15. ! ENVIRONMENT:
  16. !    VAX/VMS user mode.
  17. !
  18. ! AUTHOR: Robert C. McQueen, CREATION DATE: 28-March-1983
  19. !
  20. !--
  21.  
  22. %SBTTL 'Table of Contents'
  23. %SBTTL 'Revision History'
  24.  
  25. !++
  26. !
  27. ! 1.0.000    By: Robert C. McQueen        On: 28-March-1983
  28. !        Create this module.
  29. ! 1.0.001    By: Robert C. McQueen        On: 4-April-1983
  30. !        Remove checks for <FF> in the input data stream.
  31. !
  32. ! 1.0.002    By: Robert C. McQueen        On: 31-May-1983
  33. !        Fix a bad check in wildcard processing.
  34. !
  35. ! 1.0.003    By: Nick Bush            On: 13-June-1983
  36. !        Add default file spec of .;0 so that wild-carded
  37. !        file types don't cause all version of a file to
  38. !        be transferred.
  39. !
  40. ! 1.0.004    By: Robert C. McQueen        On: 20-July-1983
  41. !        Strip off the parity bit on the compares for incoming ASCII
  42. !        files.
  43. !
  44. ! 1.2.005    By: Robert C. McQueen        On: 15-August-1983
  45. !        Attempt to improve the GET%FILE and make it smaller.
  46. !        Also start the implementation of the BLOCK file processing.
  47. !
  48. ! 2.0.006    Release VAX/VMS Kermit-32 version 2.0
  49. !
  50. ! 2.0.016    By: Nick Bush            On: 4-Dec-1983
  51. !        Change how binary files are written to (hopefully) improve
  52. !        the performance.  We will now use 510 records and only
  53. !        write out the record when it is filled (instead of writing
  54. !        one record per packet).  This should cut down on the overhead
  55. !        substantially.
  56. !
  57. ! 2.0.017    By: Nick Bush            On: 9-Dec-1983
  58. !        Fix processing for VFC format files.  Also fix GET_ASCII
  59. !        for PRN and FTN record types.  Change GET_ASCII so that
  60. !        'normal' CR records get sent with trailing CRLF's instead
  61. !        of <LF>record<CR>.  That was confusing too many people.
  62. !
  63. ! 2.0.022    By: Nick Bush            On: 15-Dec-1983
  64. !        Add Fixed record size (512 byte) format for writing files.
  65. !        This can be used for .EXE files.  Also clean up writing
  66. !        ASCII files so that we don't lose any characters.
  67. !
  68. ! 2.0.024    By: Robert C. McQueen        On: 19-Dec-1983
  69. !        Delete FILE_DUMP.
  70. !
  71. ! 2.0.026    By: Nick Bush            On: 3-Jan-1983
  72. !        Add options for format of file specification to be
  73. !        sent in file header packets.  Also type out full file
  74. !        specification being sent/received instead of just
  75. !        the name we are telling the other end to use.
  76. !
  77. ! 2.0.030    By: Nick Bush            On: 3-Feb-1983
  78. !        Add the capability of receiving a file with a different
  79. !        name than given by KERMSG.  The RECEIVE and GET commands
  80. !        now really are different.
  81. !
  82. ! 2.0.035    By: Nick Bush                On: 8-March-1984
  83. !        Add LOG SESSION command to set a log file for CONNECT.
  84. !        While we are doing so, clean up the command parsing a little
  85. !        so that we don't have as many COPY_xxx routines.
  86. !
  87. ! 2.0.036    By: Nick Bush                On: 15-March-1984
  88. !        Fix PUT_FILE to correctly handle carriage returns which are
  89. !        not followed by line feeds.  Count was being decremented
  90. !        Instead of incremented.
  91. !
  92. ! 2.0.040    By: Nick Bush                On: 22-March-1984
  93. !        Fix processing of FORTRAN carriage control to handle lines
  94. !        which do not contain the carriage control character (i.e., zero
  95. !        length records).  Previously, this type of record was sending
  96. !        infinite nulls.
  97. !
  98. ! 3.0.045    Start of version 3.
  99. !
  100. ! 3.0.046    By: Nick Bush                On: 29-March-1984
  101. !        Fix debugging log file to correctly set/clear file open
  102. !        flag.  Also make log files default to .LOG.
  103. !
  104. ! 3.0.050    By: Nick Bush                On: 2-April-1984
  105. !        Add SET SERVER_TIMER to determine period between idle naks.
  106. !        Also allow for a routine to process file specs before
  107. !        FILE_OPEN uses them.  This allows individual sites to
  108. !        restrict the format of file specifications used by Kermit.
  109. !
  110. ! 3.1.053    By: Robert C. McQueen            On: 9-July-1984
  111. !        Fix FORTRAN carriage control processing to pass along
  112. !        any character from the carriage control column that is
  113. !        not really carriage control.
  114. !
  115. ! Start version 3.2
  116. !
  117. ! 3.2.067    By: Robert C. McQueen            On: 8-May-1985
  118. !        Use $GETDVIW instead of $GETDVI.
  119. !
  120. ! 3.2.070    By: David Stevens            On: 16-July-1985
  121. !        Put "Sending: " prompt into NEXT_FILE routine, to make
  122. !        VMS KERMIT similar to KERMIT-10.
  123. !
  124. ! 3.2.077    By: Robert McQueen            On: 8-May-1986
  125. !        Fix FORTRAN CC once and for all (I hope).
  126. !
  127. ! Start of version 3.3
  128. !
  129. ! 3.3.105    By: Robert McQueen            On: 8-July-1986
  130. !        Do some clean up and attempt to fix LINK-W-TRUNC errors
  131. !        from a BLISS-32 bug.
  132. !
  133. ! 3.3.106    By: Robert McQueen            On: 8-July-1986
  134. !        Fix problem of closing a fixed file and losing data.
  135. !
  136. ! 3.3.111    By: Robert McQueen            On: 2-Oct-1986
  137. !        Make Kermit-32 not eat the parity from a CR if a LF doesn't
  138. !        follow it when writing an ASCII file.
  139. !
  140. ! 3.3.112    JHW0001        Jonathan H. Welch,     28-Apr-1988 12:11
  141. !        Fix the message generated in NEXT_FILE so that the
  142. !        filenames displayed (i.e. Sending: foo.bar;1 as foo.bar)
  143. !        are always terminated by a null (ASCIZ).
  144. !
  145. ! 3.3.117    JHW006        Jonathan H. Welch,    12-May-1988
  146. !        Calls to LIB$SIGNAL with multiple arguments were
  147. !        not coded correctly.  For calls with multiple arguments
  148. !        an argument count was added.
  149. !        Minor changes to KERM_HANDLER to make use of the changed
  150. !        argument passing method.
  151. !
  152. ! 3.3.118    JHW010        Jonathan H. Welch,    23-Apr-1990 09:42
  153. !        Added SET FILE BLOCKSIZE nnn (where nnn is the record size
  154. !        in bytes) command for incoming BINARY and FIXED file transfers.
  155. !        If no blocksize has been specified the old behavior (510 byte
  156. !        records plus 2 bytes (for CR/LF) for BINARY files and 512
  157. !        byte records for FIXED files will be used.
  158. !        Also modified SHOW FILE to display record size when appropriate.
  159. !
  160. ! 3.3.119    JHW015        Jonathan H. Welch,    16-Jul-1990 15:30
  161. !        Fixed the logic in GET_ASCII which was causing an infinite
  162. !        loop for files with print file carriage control.
  163. !--
  164.  
  165. %SBTTL 'Forward definitions'
  166.  
  167. FORWARD ROUTINE
  168.     LOG_PUT,                    ! Write a buffer out
  169.     DUMP_BUFFER,                ! Worker routine for FILE_DUMP.
  170.     GET_BUFFER,                    ! Routine to do $GET
  171.     GET_ASCII,                    ! Get an ASCII character
  172.     GET_BLOCK,                    ! Get a block character
  173.     FILE_ERROR : NOVALUE;            ! Error processing routine
  174.  
  175. %SBTTL 'Require/Library files'
  176. !
  177. ! INCLUDE FILES:
  178. !
  179.  
  180. LIBRARY 'SYS$LIBRARY:STARLET';
  181.  
  182. REQUIRE 'KERCOM.REQ';
  183.  
  184. %SBTTL 'Macro definitions'
  185. !
  186. ! MACROS:
  187. !
  188. %SBTTL 'Literal symbol definitions'
  189. !
  190. ! EQUATED SYMBOLS:
  191. !
  192. !
  193. ! Various states for reading the data from the file
  194. !
  195.  
  196. LITERAL
  197.     F_STATE_PRE = 0,                ! Prefix state
  198.     F_STATE_PRE1 = 1,                ! Other prefix state
  199.     F_STATE_DATA = 2,                ! Data processing state
  200.     F_STATE_POST = 3,                ! Postfix processing state
  201.     F_STATE_POST1 = 4,                ! Secondary postfix processing state
  202.     F_STATE_MIN = 0,                ! Min state number
  203.     F_STATE_MAX = 4;                ! Max state number
  204.  
  205. !
  206. ! Buffer size for log file
  207. !
  208.  
  209. LITERAL
  210.     LOG_BUFF_SIZE = 256;            ! Number of bytes in log file buffer
  211.  
  212. %SBTTL 'Local storage'
  213. !
  214. ! OWN STORAGE:
  215. !
  216.  
  217. OWN
  218.     SEARCH_FLAG,                ! Can/cannot do $SEARCH
  219.     DEV_CLASS,                    ! Type of device we are reading
  220.     EOF_FLAG,                    ! End of file reached.
  221.     FILE_FAB : $FAB_DECL,            ! FAB for file processing
  222.     FILE_NAM : $NAM_DECL,            ! NAM for file processing
  223.     FILE_RAB : $RAB_DECL,            ! RAB for file processing
  224.     FILE_XABFHC : $XABFHC_DECL,            ! XAB for file processing
  225.     FILE_MODE,                    ! Mode of file (reading/writing)
  226.     FILE_REC_POINTER,                ! Pointer to the record information
  227.     FILE_REC_COUNT,                ! Count of the number of bytes
  228.     REC_SIZE : LONG,                ! Record size
  229.     REC_ADDRESS : LONG,                ! Record address
  230.     FIX_SIZE : LONG,                ! Fixed control region size
  231.     FIX_ADDRESS : LONG,            ! Address of buffer for fixed control region
  232.     EXP_STR : VECTOR [CH$ALLOCATION (NAM$C_MAXRSS)],
  233.     RES_STR : VECTOR [CH$ALLOCATION (NAM$C_MAXRSS)],
  234.     RES_STR_D : BLOCK [8, BYTE];        ! Descriptor for the string
  235.  
  236. %SBTTL 'Global storage'
  237. !
  238. ! Global storage:
  239. !
  240.  
  241. GLOBAL
  242.  
  243.     file_blocksize,                ! Block size of for BINARY and FIXED files.
  244.     file_blocksize_set,                ! 0=user has not specified a blocksize, 1=user has specified a blocksize
  245.     FILE_TYPE,                    ! Type of file being xfered
  246.     FILE_DESC : BLOCK [8, BYTE];        ! File name descriptor
  247.  
  248. %SBTTL 'External routines and storage'
  249. !
  250. ! EXTERNAL REFERENCES:
  251. !
  252. !
  253. ! Storage in KERMSG
  254. !
  255.  
  256. EXTERNAL
  257.     ALT_FILE_SIZE,                ! Number of characters in FILE_NAME
  258.     ALT_FILE_NAME : VECTOR [CH$ALLOCATION (MAX_FILE_NAME)],    ! Storage
  259.     FILE_SIZE,                    ! Number of characters in FILE_NAME
  260.     FILE_NAME : VECTOR [CH$ALLOCATION (MAX_FILE_NAME)],
  261.     TY_FIL,                ! Flag that file names are being typed
  262.     CONNECT_FLAG,    ! Indicator of whether we have a terminal to type on
  263.     FIL_NORMAL_FORM;                ! File specification type
  264.  
  265. !
  266. !  Routines in KERTT
  267. !
  268.  
  269. EXTERNAL ROUTINE
  270.     TT_OUTPUT : NOVALUE;    ! Force buffered output
  271.  
  272. !
  273. ! System libraries
  274. !
  275.  
  276. EXTERNAL ROUTINE
  277.     LIB$GET_VM : ADDRESSING_MODE (GENERAL),
  278.     LIB$FREE_VM : ADDRESSING_MODE (GENERAL),
  279.     LIB$SIGNAL : ADDRESSING_MODE (GENERAL) NOVALUE;
  280.  
  281. %SBTTL 'File processing -- FILE_INIT - Initialization'
  282.  
  283. GLOBAL ROUTINE FILE_INIT : NOVALUE =
  284.  
  285. !++
  286. ! FUNCTIONAL DESCRIPTION:
  287. !
  288. !    This routine will initialize some of the storage in the file processing
  289. !    module.
  290. !
  291. ! CALLING SEQUENCE:
  292. !
  293. !    FILE_INIT();
  294. !
  295. ! INPUT PARAMETERS:
  296. !
  297. !    None.
  298. !
  299. ! IMPLICIT INPUTS:
  300. !
  301. !    None.
  302. !
  303. ! OUTPUT PARAMETERS:
  304. !
  305. !    None.
  306. !
  307. ! IMPLICIT OUTPUTS:
  308. !
  309. !    None.
  310. !
  311. ! COMPLETION CODES:
  312. !
  313. !    None.
  314. !
  315. ! SIDE EFFECTS:
  316. !
  317. !    None.
  318. !
  319. !--
  320.  
  321.     BEGIN
  322.     FILE_TYPE = FILE_ASC;
  323.     file_blocksize = 512;
  324.     file_blocksize_set = 0;
  325.  
  326. ! Now set up the file specification descriptor
  327.     FILE_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
  328.     FILE_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
  329.     FILE_DESC [DSC$A_POINTER] = FILE_NAME;
  330.     FILE_DESC [DSC$W_LENGTH] = 0;
  331.     EOF_FLAG = FALSE;
  332.     END;                    ! End of FILE_INIT
  333.  
  334. %SBTTL 'GET_FILE'
  335.  
  336. GLOBAL ROUTINE GET_FILE (CHARACTER) =
  337.  
  338. !++
  339. ! FUNCTIONAL DESCRIPTION:
  340. !
  341. !    This routine will return a character from the input file.
  342. !    The character will be stored into the location specified by
  343. !    CHARACTER.
  344. !
  345. ! CALLING SEQUENCE:
  346. !
  347. !    GET_FILE (LOCATION_TO_STORE_CHAR);
  348. !
  349. ! INPUT PARAMETERS:
  350. !
  351. !    LOCATION_TO_STORE_CHAR - This is the address to store the character
  352. !        into.
  353. !
  354. ! IMPLICIT INPUTS:
  355. !
  356. !    None.
  357. !
  358. ! OUTPUT PARAMETERS:
  359. !
  360. !    Character stored into the location specified.
  361. !
  362. ! IMPLICIT OUTPUTS:
  363. !
  364. !    None.
  365. !
  366. ! COMPLETION CODES:
  367. !
  368. !    True - Character stored into the location specified.
  369. !    False - End of file reached.
  370. !
  371. ! SIDE EFFECTS:
  372. !
  373. !    None.
  374. !
  375. !--
  376.  
  377.     BEGIN
  378. !
  379. ! Define the various condition codes that we check for in this routine
  380. !
  381.     EXTERNAL LITERAL
  382.     KER_EOF;                ! End of file
  383.  
  384.     LOCAL
  385.     STATUS;                    ! Random status values
  386.  
  387.     IF .EOF_FLAG THEN RETURN KER_EOF;
  388.  
  389.     SELECTONE .FILE_TYPE OF
  390.     SET
  391.  
  392.     [FILE_ASC, FILE_BIN, FILE_FIX] :
  393.         STATUS = GET_ASCII (.CHARACTER);
  394.  
  395.     [FILE_BLK] :
  396.         STATUS = GET_BLOCK (.CHARACTER);
  397.     TES;
  398.  
  399.     RETURN .STATUS;
  400.     END;                    ! End of GET_FILE
  401. %SBTTL 'GET_ASCII - Get a character from an ASCII file'
  402. ROUTINE GET_ASCII (CHARACTER) =
  403.  
  404. !++
  405. ! FUNCTIONAL DESCRIPTION:
  406. !
  407. ! CALLING SEQUENCE:
  408. !
  409. ! INPUT PARAMETERS:
  410. !
  411. !    None.
  412. !
  413. ! IMPLICIT INPUTS:
  414. !
  415. !    None.
  416. !
  417. ! OUPTUT PARAMETERS:
  418. !
  419. !    None.
  420. !
  421. ! IMPLICIT OUTPUTS:
  422. !
  423. !    None.
  424. !
  425. ! COMPLETION CODES:
  426. !
  427. !   KER_EOF -  End of file encountered
  428. !   KER_ILLFILTYP - Illegal file type
  429. !   KER_NORMAL - Normal return
  430. !
  431. ! SIDE EFFECTS:
  432. !
  433. !    None.
  434. !
  435. !--
  436.  
  437.     BEGIN
  438. !
  439. ! Status codes that are returned by this module
  440. !
  441.     EXTERNAL LITERAL
  442.     KER_EOF,            ! End of file encountered
  443.     KER_ILLFILTYP,            ! Illegal file type
  444.     KER_NORMAL;            ! Normal return
  445.  
  446.     OWN
  447.     CC_COUNT,            ! Count of the number of CC things to output
  448.     CC_TYPE;            ! Type of carriage control being processed.
  449.  
  450.     LOCAL
  451.     STATUS,                    ! For status values
  452.     RAT;
  453. %SBTTL 'GET_FTN_FILE_CHARACTER - Get a character from an Fortran carriage control file'
  454. ROUTINE GET_FTN_FILE_CHARACTER (CHARACTER) = 
  455. !++
  456. ! FUNCTIONAL DESCRIPTION:
  457. !
  458. !   This routine will get a character from a FORTRAN carriage control file.
  459. !   A FORTRAN carriage control file is one with FAB$M_FTN on in the FAB$B_RAT
  460. !   field.
  461. !
  462. ! FORMAL PARAMETERS:
  463. !
  464. !   CHARACTER - Address of where to store the character
  465. !
  466. ! IMPLICIT INPUTS:
  467. !
  468. !   CC_TYPE - Carriage control type
  469. !
  470. ! IMPLICIT OUTPUTS:
  471. !
  472. !   CC_TYPE - Updated if this is the first characte of the record
  473. !
  474. ! COMPLETION_CODES:
  475. !
  476. !   System service or Kermit status code
  477. !
  478. ! SIDE EFFECTS:
  479. !
  480. !   Next buffer can be read from the data file.
  481. !--
  482.     BEGIN
  483. !
  484. ! Dispatch according to the state of the file being read.  Beginning of
  485. ! record, middle of record, end of record
  486. !
  487.     WHILE TRUE DO
  488.     CASE .FILE_FAB[FAB$L_CTX] FROM F_STATE_MIN TO F_STATE_MAX OF
  489.         SET
  490. !
  491. ! Here at the beginning of a record.  We must read the buffer from the file
  492. ! at this point.  Once the buffer is read we must then determine what to do
  493. ! with the FORTRAN carriage control that at the beginning of the buffer.
  494. !
  495.         [F_STATE_PRE ]:
  496.         BEGIN    
  497. !
  498. ! Local variables
  499. !
  500.         LOCAL
  501.             STATUS;                ! Status returned by the
  502.                             !  GET_BUFFER routine
  503. !
  504. ! Get the buffer
  505. !
  506.         STATUS = GET_BUFFER ();            ! Get a buffer from the system
  507.         IF (NOT .STATUS)            ! If this call failed
  508.             OR (.STATUS EQL KER_EOF)        !  or we got an EOF
  509.         THEN
  510.             RETURN .STATUS;            ! Just return the status
  511. !
  512. ! Here with a valid buffer full of data all set to be decoded
  513. !
  514.         IF .FILE_REC_COUNT LEQ 0        ! If nothing, use a space
  515.         THEN                    !  for the carriage control
  516.             CC_TYPE = %C' '
  517.         ELSE
  518.             BEGIN
  519.             CC_TYPE = CH$RCHAR_A (FILE_REC_POINTER);
  520.             FILE_REC_COUNT = .FILE_REC_COUNT - 1;
  521.             END;
  522. !
  523. ! Dispatch on the type of carriage control that we are processing
  524. !
  525.         SELECTONE .CC_TYPE OF
  526.             SET
  527. !
  528. ! All of these just output:
  529. !   <DATA> <Carriage-control>
  530. !
  531.             [CHR_NUL, %C'+'] :
  532.             BEGIN
  533.             FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  534.             END;
  535. !
  536. ! This outputs:
  537. !   <LF><DATA><CR>
  538. !
  539.             [%C'$', %C' '] :
  540.             BEGIN
  541.             .CHARACTER = CHR_LFD;
  542.             FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  543.             RETURN KER_NORMAL;
  544.             END;
  545. !
  546. ! This outputs:
  547. !   <LF><LF><DATA><CR>
  548. !
  549.             [%C'0'] :
  550.             BEGIN
  551.             .CHARACTER = CHR_LFD;
  552.             FILE_FAB [FAB$L_CTX] = F_STATE_PRE1;
  553.             RETURN KER_NORMAL;
  554.             END;
  555. !
  556. ! This outputs:
  557. !   <FORM FEED><DATA><CR>
  558. !
  559.             [%C'1'] :
  560.             BEGIN
  561.             .CHARACTER = CHR_FFD;
  562.             FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  563.             RETURN KER_NORMAL;
  564.             END;
  565. !
  566. ! If we don't know the type of carriage control, then just return the
  567. ! character we read as data and set the carriage control to be space
  568. ! to fool the post processing of the record
  569. !
  570.             [OTHERWISE] :
  571.             BEGIN
  572.             .CHARACTER = .CC_TYPE;        ! Return the character
  573.             CC_TYPE = %C' ';        ! Treat as space
  574.             FILE_REC_POINTER = CH$PLUS(.FILE_REC_POINTER,-1);
  575.             FILE_REC_COUNT = .FILE_REC_COUNT + 1;
  576.             FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  577.             RETURN KER_NORMAL
  578.             END;
  579.             TES;
  580.  
  581.         END;
  582. !
  583. ! Here to add the second LF for the double spacing FORTRAN carriage control
  584. !
  585.         [F_STATE_PRE1 ]:
  586.         BEGIN
  587.         .CHARACTER = CHR_LFD;
  588.         FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  589.         RETURN KER_NORMAL;
  590.         END;
  591. !
  592. ! Here to read the data of the record
  593. !
  594.         [F_STATE_DATA]:
  595.         BEGIN
  596. !
  597. ! Here to read the data of the record and return it to the caller
  598. ! This section can only return KER_NORMAL to the caller
  599. !
  600.         IF .FILE_REC_COUNT LEQ 0        ! Anything left in the buffer
  601.         THEN
  602.             FILE_FAB [FAB$L_CTX] = F_STATE_POST    ! No, do post processing
  603.         ELSE
  604.             BEGIN
  605.             .CHARACTER = CH$RCHAR_A (FILE_REC_POINTER);    ! Get a character
  606.             FILE_REC_COUNT = .FILE_REC_COUNT - 1;   ! Decrement the count
  607.             RETURN KER_NORMAL;            ! Give a good return
  608.             END;
  609.         END;
  610. !
  611. ! Here to do post processing of the record.  At this point we are going
  612. ! to store either nothing as the post fix, a carriage return for overprinting
  613. ! or a carriage return and then a line feed in the POST1 state.
  614. !
  615.         [F_STATE_POST ]:
  616.         BEGIN
  617.         SELECTONE .CC_TYPE OF
  618.             SET
  619. !
  620. ! This stat is for no carriage control on the record.  This is for
  621. ! 'null' carriage control (VMS manual states: "Null carriage control 
  622. ! (print buffer contents.)" and for prompt carriage control.
  623. !
  624.             [CHR_NUL, %C'$' ]:
  625.             BEGIN
  626.             FILE_FAB [FAB$L_CTX] = F_STATE_PRE
  627.             END;
  628. !
  629. ! This is the normal state, that causes the postfix for the data to be
  630. ! a line feed.  
  631. !
  632.             [%C'0', %C'1', %C' ', %C'+' ]:
  633.             BEGIN
  634.             .CHARACTER = CHR_CRT;
  635.             FILE_FAB [FAB$L_CTX] = F_STATE_PRE;
  636.             RETURN KER_NORMAL
  637.             END;
  638.             TES;
  639.  
  640.         END;
  641. !
  642. ! Here if we are in a state that this routine doesn't set.  Just assume that
  643. ! something screwed up and give an illegal file type return to the caller
  644. !
  645.         [INRANGE, OUTRANGE]:
  646.         RETURN KER_ILLFILTYP;
  647.  
  648.         TES
  649.     END;
  650. %SBTTL 'GET_ASCII - Main logic'
  651.     RAT = .FILE_FAB [FAB$B_RAT] AND ( NOT FAB$M_BLK);
  652.  
  653.     IF .DEV_CLASS EQL DC$_MAILBOX THEN RAT = FAB$M_CR;    ! Mailbox needs CR's
  654.  
  655.     WHILE TRUE DO
  656.     BEGIN
  657.  
  658.     SELECTONE .RAT OF
  659.         SET
  660.         
  661.         [FAB$M_FTN ]:
  662.         BEGIN
  663.         RETURN GET_FTN_FILE_CHARACTER (.CHARACTER)
  664.         END;
  665.  
  666.         [FAB$M_PRN, FAB$M_CR] :
  667.  
  668.         CASE .FILE_FAB [FAB$L_CTX] FROM F_STATE_MIN TO F_STATE_MAX OF
  669.             SET
  670.  
  671.             [F_STATE_PRE] :
  672.             BEGIN
  673.             STATUS = GET_BUFFER ();
  674.  
  675.             IF NOT .STATUS OR .STATUS EQL KER_EOF THEN RETURN .STATUS;
  676.  
  677.             SELECTONE .RAT OF
  678.                 SET
  679.  
  680.                 [FAB$M_CR] :
  681.                 BEGIN
  682.                 FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  683.                 END;
  684.  
  685.                 [FAB$M_PRN] :
  686.                 BEGIN
  687.  
  688.                 LOCAL
  689.                     TEMP_POINTER;
  690.  
  691.                 TEMP_POINTER = CH$PTR (.FILE_RAB [RAB$L_RHB]);
  692.                 CC_COUNT = CH$RCHAR_A (TEMP_POINTER);
  693.                 CC_TYPE = CH$RCHAR_A (TEMP_POINTER);
  694.  
  695.                 IF .CC_COUNT<7, 1> EQL 0
  696.                 THEN
  697.                     BEGIN
  698.  
  699.                     IF .CC_COUNT<0, 7> NEQ 0
  700.                     THEN
  701.                     BEGIN
  702.                     .CHARACTER = CHR_LFD;
  703.                     CC_COUNT = .CC_COUNT - 1;
  704.  
  705.                     IF .CC_COUNT GTR 0
  706.                     THEN
  707.                         FILE_FAB [FAB$L_CTX] = F_STATE_PRE1
  708.                     ELSE
  709.                         FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  710.  
  711.                     RETURN KER_NORMAL;
  712.                     END
  713.                     ELSE
  714.                     FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  715.  
  716.                     END
  717.                 ELSE
  718.                     BEGIN
  719.  
  720.                     SELECTONE .CC_COUNT<5, 2> OF
  721.                     SET
  722.  
  723.                     [%B'00'] :
  724.                         BEGIN
  725.                         .CHARACTER = .CC_COUNT<0, 5>;
  726.                         FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  727.                         RETURN KER_NORMAL;
  728.                         END;
  729.  
  730.                     [%B'10'] :
  731.                         BEGIN
  732.                         .CHARACTER = .CC_COUNT<0, 5> + 128;
  733.                         FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  734.                         RETURN KER_NORMAL;
  735.                         END;
  736.  
  737.                     [OTHERWISE, %B'11'] :
  738.                         RETURN KER_ILLFILTYP;
  739.                     TES;
  740.                     END;
  741.                 END;
  742.                 TES;
  743.  
  744.             END;
  745.  
  746.             [F_STATE_PRE1] :
  747.  
  748.             IF .RAT EQL FAB$M_PRN
  749.             THEN
  750.                 BEGIN
  751.                 .CHARACTER = CHR_LFD;
  752.                 CC_COUNT = .CC_COUNT - 1;
  753.  
  754.                 IF .CC_COUNT LEQ 0 THEN FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  755.  
  756.                 RETURN KER_NORMAL;
  757.                 END
  758.             ELSE
  759.                 RETURN KER_ILLFILTYP;
  760.  
  761.             [F_STATE_DATA] :
  762.             BEGIN
  763.  
  764.             IF .FILE_REC_COUNT LEQ 0
  765.             THEN
  766.                 FILE_FAB [FAB$L_CTX] = F_STATE_POST
  767.             ELSE
  768.                 BEGIN
  769.                 .CHARACTER = CH$RCHAR_A (FILE_REC_POINTER);
  770.                 FILE_REC_COUNT = .FILE_REC_COUNT - 1;
  771.                 RETURN KER_NORMAL;
  772.                 END;
  773.  
  774.             END;
  775.  
  776.             [F_STATE_POST] :
  777.             BEGIN
  778.  
  779.             SELECTONE .RAT OF
  780.                 SET
  781.  
  782.                 [FAB$M_CR] :
  783.                 BEGIN
  784.                 .CHARACTER = CHR_CRT;
  785.                 FILE_FAB [FAB$L_CTX] = F_STATE_POST1;
  786.                         ! So we get a line feed
  787.                 RETURN KER_NORMAL;
  788.                 END;
  789.  
  790.  
  791.                 [FAB$M_PRN] :
  792.                 BEGIN
  793.  
  794.                 IF .CC_TYPE<7, 1> EQL 0
  795.                 THEN
  796.                     BEGIN
  797.  
  798.                     IF .CC_TYPE<0, 7> NEQ 0
  799.                     THEN
  800.                     BEGIN
  801.                     .CHARACTER = CHR_LFD;
  802.                     CC_COUNT = .CC_TYPE;
  803.                     FILE_FAB [FAB$L_CTX] = F_STATE_POST1;
  804.                                         RETURN KER_NORMAL;
  805.                     END
  806.                     ELSE
  807.                     FILE_FAB [FAB$L_CTX] = F_STATE_PRE;
  808.                     END
  809.                 ELSE
  810.                     BEGIN
  811.  
  812.                     SELECTONE .CC_TYPE<5, 2> OF
  813.                     SET
  814.  
  815.                     [%B'00'] :
  816.                         BEGIN
  817.                         .CHARACTER = .CC_TYPE<0, 5>;
  818.                         FILE_FAB [FAB$L_CTX] = F_STATE_PRE;
  819.                         RETURN KER_NORMAL;
  820.                         END;
  821.  
  822.                     [%B'10'] :
  823.                         BEGIN
  824.                         .CHARACTER = .CC_TYPE<0, 5> + 128;
  825.                         FILE_FAB [FAB$L_CTX] = F_STATE_PRE;
  826.                         RETURN KER_NORMAL;
  827.                         END;
  828.  
  829.                     [OTHERWISE, %B'11'] :
  830.                         RETURN KER_ILLFILTYP;
  831.                     TES;
  832.  
  833.                     END;
  834.  
  835.                 END;
  836.                 TES;        ! End SELECTONE .RAT
  837.  
  838.             END;
  839.  
  840.             [F_STATE_POST1] :
  841.  
  842.             IF .RAT EQL FAB$M_PRN
  843.             THEN
  844.                 BEGIN
  845.                 .CHARACTER = CHR_LFD;
  846.                 CC_COUNT = .CC_COUNT - 1;
  847.  
  848.                 IF .CC_COUNT LEQ -1
  849.                 THEN
  850.                 BEGIN
  851.                 .CHARACTER = CHR_CRT;
  852. !                FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  853.                 FILE_FAB [FAB$L_CTX] = F_STATE_PRE;
  854.                 END;
  855.  
  856.                 RETURN KER_NORMAL;
  857.                 END
  858.             ELSE
  859. !
  860. ! Generate line feed after CR for funny files
  861. !
  862.  
  863.                 IF (.RAT EQL FAB$M_CR)
  864.                 THEN
  865.                 BEGIN
  866.                 .CHARACTER = CHR_LFD;    ! Return a line feed
  867.                 FILE_FAB [FAB$L_CTX] = F_STATE_PRE;
  868.                         ! Next we get data
  869.                 RETURN KER_NORMAL;
  870.                 END
  871.                 ELSE
  872.                 RETURN KER_ILLFILTYP;
  873.  
  874.             TES;            ! End of CASE .STATE
  875.  
  876.         [OTHERWISE] :
  877.         BEGIN
  878.  
  879.         WHILE .FILE_REC_COUNT LEQ 0 DO
  880.             BEGIN
  881.             STATUS = GET_BUFFER ();
  882.  
  883.             IF NOT .STATUS OR .STATUS EQL KER_EOF THEN RETURN .STATUS;
  884.  
  885.             END;
  886.  
  887.         FILE_REC_COUNT = .FILE_REC_COUNT - 1;
  888.         .CHARACTER = CH$RCHAR_A (FILE_REC_POINTER);
  889.         RETURN KER_NORMAL;
  890.         END;
  891.         TES;                ! End of SELECTONE .RAT
  892.  
  893.     END;                    ! End WHILE TRUE DO loop
  894.  
  895.     RETURN KER_ILLFILTYP;            ! Shouldn't get here
  896.     END;                    ! End of GET_ASCII
  897. %SBTTL 'GET_BLOCK - Get a character from a BLOCKed file'
  898. ROUTINE GET_BLOCK (CHARACTER) =
  899.  
  900. !++
  901. ! FUNCTIONAL DESCRIPTION:
  902. !
  903. !    This routine will return the next byte from a blocked file.  This
  904. !    routine will use the $READ RMS call to get the next byte from the
  905. !    file.  This way all RMS header information can be passed to the
  906. !    other file system.
  907. !
  908. ! CALLING SEQUENCE:
  909. !
  910. !    STATUS = GET_BLOCK(CHARACTER);
  911. !
  912. ! INPUT PARAMETERS:
  913. !
  914. !    CHARACTER - Address to store the character in.
  915. !
  916. ! IMPLICIT INPUTS:
  917. !
  918. !    REC_POINTER - Pointer into the record.
  919. !    REC_ADDRESS - Address of the record.
  920. !    REC_COUNT - Count of the number of bytes left in the record.
  921. !
  922. ! OUPTUT PARAMETERS:
  923. !
  924. !    None.
  925. !
  926. ! IMPLICIT OUTPUTS:
  927. !
  928. !    None.
  929. !
  930. ! COMPLETION CODES:
  931. !
  932. !   KER_NORMAL - Got a byte
  933. !   KER_EOF - End of file gotten.
  934. !   KER_RMS32 - RMS error
  935. !
  936. ! SIDE EFFECTS:
  937. !
  938. !    None.
  939. !
  940. !--
  941.  
  942.     BEGIN
  943. !
  944. ! Status codes returned by this module
  945. !
  946.     EXTERNAL LITERAL
  947.     KER_RMS32,                ! RMS error encountered
  948.     KER_EOF,                ! End of file encountered
  949.     KER_NORMAL;                ! Normal return
  950.  
  951.     LOCAL
  952.     STATUS;                    ! Random status values
  953.  
  954.     WHILE .FILE_REC_COUNT LEQ 0 DO
  955.     BEGIN
  956.     STATUS = $READ (RAB = FILE_RAB);
  957.  
  958.     IF NOT .STATUS
  959.     THEN
  960.  
  961.         IF .STATUS EQL RMS$_EOF
  962.         THEN
  963.         BEGIN
  964.         EOF_FLAG = TRUE;
  965.         RETURN KER_EOF;
  966.         END
  967.         ELSE
  968.         BEGIN
  969.         FILE_ERROR (.STATUS);
  970.         EOF_FLAG = TRUE;
  971.         RETURN KER_RMS32;
  972.         END;
  973.  
  974.     FILE_REC_POINTER = CH$PTR (.REC_ADDRESS);
  975.     FILE_REC_COUNT = .FILE_RAB [RAB$W_RSZ];
  976.     END;
  977.  
  978.     FILE_REC_COUNT = .FILE_REC_COUNT - 1;
  979.     .CHARACTER = CH$RCHAR_A (FILE_REC_POINTER);
  980.     RETURN KER_NORMAL;
  981.     END;                    ! End of GET_BLOCK
  982. %SBTTL 'GET_BUFFER - Routine to read a buffer.'
  983. ROUTINE GET_BUFFER =
  984.  
  985. !++
  986. ! FUNCTIONAL DESCRIPTION:
  987. !
  988. !    This routine will read a buffer from the disk file.  It will
  989. !    return various status depending if there was an error reading
  990. !    the disk file or if the end of file is reached.
  991. !
  992. ! CALLING SEQUENCE:
  993. !
  994. !    STATUS = GET_BUFFER ();
  995. !
  996. ! INPUT PARAMETERS:
  997. !
  998. !    None.
  999. !
  1000. ! IMPLICIT INPUTS:
  1001. !
  1002. !    None.
  1003. !
  1004. ! OUTPUT PARAMETERS:
  1005. !
  1006. !    None.
  1007. !
  1008. ! IMPLICIT OUTPUTS:
  1009. !
  1010. !    FILE_REC_POINTER - Pointer into the record.
  1011. !    FILE_REC_COUNT - Count of the number of bytes in the record.
  1012. !
  1013. ! COMPLETION CODES:
  1014. !
  1015. !    KER_NORMAL - Got a buffer
  1016. !    KER_EOF - End of file reached.
  1017. !    KER_RMS32 - RMS error
  1018. !
  1019. ! SIDE EFFECTS:
  1020. !
  1021. !    None.
  1022. !
  1023. !--
  1024.  
  1025.     BEGIN
  1026. !
  1027. ! The following are the various status values returned by this routien
  1028. !
  1029.     EXTERNAL LITERAL
  1030.     KER_NORMAL,                ! Normal return
  1031.     KER_EOF,                ! End of file
  1032.     KER_RMS32;                ! RMS error encountered
  1033.  
  1034.     LOCAL
  1035.     STATUS;                    ! Random status values
  1036.  
  1037.     STATUS = $GET (RAB = FILE_RAB);
  1038.  
  1039.     IF NOT .STATUS
  1040.     THEN
  1041.  
  1042.     IF .STATUS EQL RMS$_EOF
  1043.     THEN
  1044.         BEGIN
  1045.         EOF_FLAG = TRUE;
  1046.         RETURN KER_EOF;
  1047.         END
  1048.     ELSE
  1049.         BEGIN
  1050.         FILE_ERROR (.STATUS);
  1051.         EOF_FLAG = TRUE;
  1052.         RETURN KER_RMS32;
  1053.         END;
  1054.  
  1055.     FILE_REC_POINTER = CH$PTR (.REC_ADDRESS);
  1056.     FILE_REC_COUNT = .FILE_RAB [RAB$W_RSZ];
  1057.     RETURN KER_NORMAL;
  1058.     END;
  1059. %SBTTL 'PUT_FILE'
  1060.  
  1061. GLOBAL ROUTINE PUT_FILE (CHARACTER) =
  1062.  
  1063. !++
  1064. ! FUNCTIONAL DESCRIPTION:
  1065. !
  1066. !    This routine will store a character into the record buffer
  1067. !    that we are building.  It will output the buffer to disk
  1068. !    when the end of line characters are found.
  1069. !
  1070. ! CALLING SEQUENCE:
  1071. !
  1072. !    STATUS = PUT_FILE(Character);
  1073. !
  1074. ! INPUT PARAMETERS:
  1075. !
  1076. !    Character - Address of the character to output in the file.
  1077. !
  1078. ! IMPLICIT INPUTS:
  1079. !
  1080. !    None.
  1081. !
  1082. ! OUTPUT PARAMETERS:
  1083. !
  1084. !    Status - True if no problems writing the character
  1085. !         False if there were problems writing the character.
  1086. !
  1087. ! IMPLICIT OUTPUTS:
  1088. !
  1089. !    None.
  1090. !
  1091. ! COMPLETION CODES:
  1092. !
  1093. !    None.
  1094. !
  1095. ! SIDE EFFECTS:
  1096. !
  1097. !    None.
  1098. !
  1099. !--
  1100.  
  1101.     BEGIN
  1102. !
  1103. ! Completion codes
  1104. !
  1105.     EXTERNAL LITERAL
  1106.     KER_REC_TOO_BIG,            ! Record too big
  1107.     KER_NORMAL;                ! Normal return
  1108. !
  1109. ! Local variables
  1110. !
  1111.     OWN
  1112.     SAVED_CHARACTER : UNSIGNED BYTE;    ! Character we may have to
  1113.                         !  write later on
  1114.     LOCAL
  1115.     STATUS;                    ! Random status values
  1116.  
  1117.     SELECTONE .FILE_TYPE OF
  1118.     SET
  1119.  
  1120.     [FILE_ASC] :
  1121.         BEGIN
  1122. !
  1123. ! If the last character was a carriage return and this is a line feed,
  1124. ! we will just dump the record.  Otherwise, if the last character was
  1125. ! a carriage return, output both it and the current one.
  1126. !
  1127.  
  1128.         IF .FILE_FAB [FAB$L_CTX] NEQ F_STATE_DATA
  1129.         THEN
  1130.         BEGIN
  1131.  
  1132.         IF (.CHARACTER AND %O'177') EQL CHR_LFD
  1133.         THEN
  1134.             BEGIN
  1135.             FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  1136.             RETURN DUMP_BUFFER ();
  1137.             END
  1138.         ELSE
  1139.             BEGIN
  1140.  
  1141.             IF .FILE_REC_COUNT GEQ .REC_SIZE
  1142.             THEN
  1143.             BEGIN
  1144.             LIB$SIGNAL (KER_REC_TOO_BIG);
  1145.             RETURN KER_REC_TOO_BIG;
  1146.             END;
  1147.  
  1148.             CH$WCHAR_A (.SAVED_CHARACTER, FILE_REC_POINTER);
  1149.                         ! Store the carriage return we deferred
  1150.             FILE_REC_COUNT = .FILE_REC_COUNT + 1;
  1151.             FILE_FAB [FAB$L_CTX] = F_STATE_DATA;    ! Back to normal data
  1152.             END;
  1153.  
  1154.         END;
  1155.  
  1156. !
  1157. ! Here when last character was written to the file normally.  Check if
  1158. ! this character might be the end of a record (or at least the start of
  1159. ! end.
  1160. !
  1161.  
  1162.         IF (.CHARACTER AND %O'177') EQL CHR_CRT
  1163.         THEN
  1164.         BEGIN
  1165.         SAVED_CHARACTER = .CHARACTER;        ! Save the character for later
  1166.         FILE_FAB [FAB$L_CTX] = F_STATE_POST;    ! Remember we saw this
  1167.         RETURN KER_NORMAL;        ! And delay until next character
  1168.         END;
  1169.  
  1170.         IF .FILE_REC_COUNT GEQ .REC_SIZE
  1171.         THEN
  1172.         BEGIN
  1173.         LIB$SIGNAL (KER_REC_TOO_BIG);
  1174.         RETURN KER_REC_TOO_BIG;
  1175.         END;
  1176.  
  1177.         FILE_REC_COUNT = .FILE_REC_COUNT + 1;
  1178.         CH$WCHAR_A (.CHARACTER, FILE_REC_POINTER);
  1179.         END;
  1180.  
  1181.     [FILE_BIN, FILE_FIX] :
  1182.         BEGIN
  1183.  
  1184.         IF .FILE_REC_COUNT GEQ .REC_SIZE
  1185.         THEN
  1186.         BEGIN
  1187.         STATUS = DUMP_BUFFER ();
  1188.  
  1189.         IF NOT .STATUS
  1190.         THEN
  1191.             BEGIN
  1192.             LIB$SIGNAL (.STATUS);
  1193.             RETURN .STATUS;
  1194.             END;
  1195.  
  1196.         END;
  1197.  
  1198.         FILE_REC_COUNT = .FILE_REC_COUNT + 1;
  1199.         CH$WCHAR_A (.CHARACTER, FILE_REC_POINTER);
  1200.         END;
  1201.  
  1202.     [FILE_BLK] :
  1203.         BEGIN
  1204.  
  1205.         IF .FILE_REC_COUNT GEQ .REC_SIZE
  1206.         THEN
  1207.         BEGIN
  1208.         FILE_RAB [RAB$W_RSZ] = .FILE_REC_COUNT;
  1209.         STATUS = $WRITE (RAB = FILE_RAB);
  1210.         FILE_REC_COUNT = 0;
  1211.         FILE_REC_POINTER = CH$PTR (.REC_ADDRESS);
  1212.         END;
  1213.  
  1214.         FILE_REC_COUNT = .FILE_REC_COUNT + 1;
  1215.         CH$WCHAR_A (.CHARACTER, FILE_REC_POINTER);
  1216.         END;
  1217.     TES;
  1218.  
  1219.     RETURN KER_NORMAL;
  1220.     END;                    ! End of PUT_FILE
  1221.  
  1222. %SBTTL 'DUMP_BUFFER - Dump the current record to disk'
  1223. ROUTINE DUMP_BUFFER =
  1224.  
  1225. !++
  1226. ! FUNCTIONAL DESCRIPTION:
  1227. !
  1228. !    This routine will dump the current record to disk.  It doesn't
  1229. !    care what type of file you are writing, unlike FILE_DUMP.
  1230. !
  1231. ! CALLING SEQUENCE:
  1232. !
  1233. !    STATUS = DUMP_BUFFER();
  1234. !
  1235. ! INPUT PARAMETERS:
  1236. !
  1237. !    None.
  1238. !
  1239. ! IMPLICIT INPUTS:
  1240. !
  1241. !    None.
  1242. !
  1243. ! OUTPUT PARAMETERS:
  1244. !
  1245. !    None.
  1246. !
  1247. ! IMPLICIT OUTPUTS:
  1248. !
  1249. !    None.
  1250. !
  1251. ! COMPLETION CODES:
  1252. !
  1253. !    KER_NORMAL - Output went ok.
  1254. !    KER_RMS32 - RMS-32 error.
  1255. !
  1256. ! SIDE EFFECTS:
  1257. !
  1258. !    None.
  1259. !
  1260. !--
  1261.  
  1262.     BEGIN
  1263. !
  1264. ! Completion codes returned:
  1265. !
  1266.     EXTERNAL LITERAL
  1267.     KER_NORMAL,                ! Normal return
  1268.     KER_RMS32;                ! RMS-32 error
  1269. !
  1270. ! Local variables
  1271. !
  1272.     LOCAL
  1273.     STATUS;                    ! Random status values
  1274.  
  1275. !
  1276. ! First update the record length
  1277. !
  1278.     FILE_RAB [RAB$W_RSZ] = .FILE_REC_COUNT;
  1279. !
  1280. ! Now output the record to the file
  1281. !
  1282.     STATUS = $PUT (RAB = FILE_RAB);
  1283. !
  1284. ! Update the pointers first
  1285. !
  1286.     FILE_REC_COUNT = 0;
  1287.     FILE_REC_POINTER = CH$PTR (.REC_ADDRESS);
  1288. !
  1289. ! Now determine if we failed attempting to write the record
  1290. !
  1291.  
  1292.     IF NOT .STATUS
  1293.     THEN
  1294.     BEGIN
  1295.     FILE_ERROR (.STATUS);
  1296.     RETURN KER_RMS32
  1297.     END;
  1298.  
  1299.     RETURN KER_NORMAL
  1300.     END;                    ! End of DUMP_BUFFER
  1301. %SBTTL 'OPEN_READING'
  1302. ROUTINE OPEN_READING =
  1303.  
  1304. !++
  1305. ! FUNCTIONAL DESCRIPTION:
  1306. !
  1307. !    This routine will open a file for reading.  It will return either
  1308. !    true or false to the called depending on the success of the
  1309. !    operation.
  1310. !
  1311. ! CALLING SEQUENCE:
  1312. !
  1313. !    status = OPEN_READING();
  1314. !
  1315. ! INPUT PARAMETERS:
  1316. !
  1317. !    None.
  1318. !
  1319. ! IMPLICIT INPUTS:
  1320. !
  1321. !    None.
  1322. !
  1323. ! OUTPUT PARAMETERS:
  1324. !
  1325. !    None.
  1326. !
  1327. ! IMPLICIT OUTPUTS:
  1328. !
  1329. !    None.
  1330. !
  1331. ! COMPLETION CODES:
  1332. !
  1333. !   KER_NORMAL - Normal return
  1334. !   KER_RMS32 - RMS error encountered
  1335. !
  1336. ! SIDE EFFECTS:
  1337. !
  1338. !    None.
  1339. !
  1340. !--
  1341.  
  1342.     BEGIN
  1343. !
  1344. ! Completion codes returned:
  1345. !
  1346.     EXTERNAL LITERAL
  1347.     KER_NORMAL,                ! Normal return
  1348.     KER_RMS32;                ! RMS-32 error
  1349.  
  1350.     LOCAL
  1351.     STATUS;                    ! Random status values
  1352.  
  1353. !
  1354. ! We now have an expanded file specification that we can use to process
  1355. ! the file.
  1356. !
  1357.  
  1358.     IF .FILE_TYPE NEQ FILE_BLK
  1359.     THEN
  1360.     BEGIN
  1361.     $FAB_INIT (FAB = FILE_FAB, FAC = GET, FOP = NAM, RFM = STM, NAM = FILE_NAM,
  1362.         XAB = FILE_XABFHC);
  1363.     END
  1364.     ELSE
  1365.     BEGIN
  1366.     $FAB_INIT (FAB = FILE_FAB, FAC = (GET, BIO), FOP = NAM, RFM = STM,
  1367.         NAM = FILE_NAM, XAB = FILE_XABFHC);
  1368.     END;
  1369.  
  1370.     $XABFHC_INIT (XAB = FILE_XABFHC);
  1371.     STATUS = $OPEN (FAB = FILE_FAB);
  1372.  
  1373.     IF (.STATUS NEQ RMS$_NORMAL AND .STATUS NEQ RMS$_KFF)
  1374.     THEN
  1375.     BEGIN
  1376.     FILE_ERROR (.STATUS);
  1377.     RETURN KER_RMS32;
  1378.     END;
  1379.  
  1380. !
  1381. ! Now allocate a buffer for the records
  1382. !
  1383.     REC_SIZE = (IF .FILE_TYPE EQL FILE_BLK THEN 512 ELSE .FILE_XABFHC [XAB$W_LRL]);
  1384.  
  1385.     IF .REC_SIZE EQL 0 THEN REC_SIZE = MAX_REC_LENGTH;
  1386.  
  1387.     STATUS = LIB$GET_VM (REC_SIZE, REC_ADDRESS);
  1388. !
  1389. ! Determine if we need a buffer for the fixed control area
  1390. !
  1391.     FIX_SIZE = .FILE_FAB [FAB$B_FSZ];
  1392.  
  1393.     IF .FIX_SIZE NEQ 0
  1394.     THEN
  1395.     BEGIN
  1396.     STATUS = LIB$GET_VM (FIX_SIZE, FIX_ADDRESS);
  1397.     END;
  1398.  
  1399. !
  1400. ! Initialize the RAB for the $CONNECT RMS call
  1401. !
  1402.     $RAB_INIT (RAB = FILE_RAB, FAB = FILE_FAB, RAC = SEQ, ROP = NLK, UBF = .REC_ADDRESS,
  1403.     USZ = .REC_SIZE);
  1404.  
  1405.     IF .FIX_SIZE NEQ 0 THEN FILE_RAB [RAB$L_RHB] = .FIX_ADDRESS;
  1406.  
  1407.                         ! Store header address
  1408.     STATUS = $CONNECT (RAB = FILE_RAB);
  1409.  
  1410.     IF NOT .STATUS
  1411.     THEN
  1412.     BEGIN
  1413.     FILE_ERROR (.STATUS);
  1414.     RETURN KER_RMS32;
  1415.     END;
  1416.  
  1417.     FILE_REC_COUNT = -1;
  1418.     FILE_FAB [FAB$L_CTX] = F_STATE_PRE;
  1419.     RETURN KER_NORMAL;
  1420.     END;                    ! End of OPEN_READING
  1421. %SBTTL 'FILE_OPEN'
  1422.  
  1423. GLOBAL ROUTINE FILE_OPEN (FUNCTION) =
  1424.  
  1425. !++
  1426. ! FUNCTIONAL DESCRIPTION:
  1427. !
  1428. !    This routine will open a file for reading or writing depending on
  1429. !    the function that is passed this routine.  It will handle wildcards
  1430. !    on the read function.
  1431. !
  1432. ! CALLING SEQUENCE:
  1433. !
  1434. !    status = FILE_OPEN(FUNCTION);
  1435. !
  1436. ! INPUT PARAMETERS:
  1437. !
  1438. !    FUNCTION - Function to do.  Either FNC_READ or FNC_WRITE.
  1439. !
  1440. ! IMPLICIT INPUTS:
  1441. !
  1442. !    FILE_NAME and FILE_SIZE set up with the file name and the length
  1443. !    of the name.
  1444. !
  1445. ! OUTPUT PARAMETERS:
  1446. !
  1447. !    None.
  1448. !
  1449. ! IMPLICIT OUTPUTS:
  1450. !
  1451. !    FILE_NAME and FILE_SIZE set up with the file name and the length
  1452. !    of the name.
  1453. !
  1454. ! COMPLETION CODES:
  1455. !
  1456. !   KER_NORMAL - File opened correctly.
  1457. !   KER_RMS32 - Problem processing the file.
  1458. !   KER_INTERNALERR - Internal Kermit-32 error.
  1459. !
  1460. ! SIDE EFFECTS:
  1461. !
  1462. !    None.
  1463. !
  1464. !--
  1465.  
  1466.     BEGIN
  1467. !
  1468. ! Completion codes returned:
  1469. !
  1470.     EXTERNAL LITERAL
  1471.     KER_NORMAL,                ! Normal return
  1472.     KER_INTERNALERR,            ! Internal error
  1473.     KER_RMS32;                ! RMS-32 error
  1474.  
  1475.     EXTERNAL ROUTINE
  1476.     TT_TEXT : NOVALUE;    ! Output an ASCIZ string
  1477.  
  1478.     EXTERNAL ROUTINE
  1479. !
  1480. ! This external routine is called to perform any checks on the file
  1481. ! specification that the user wishes.  It must return a true value
  1482. ! if the access is to be allowed, and a false value (error code) if
  1483. ! access is to be denied.  The error code may be any valid system wide
  1484. ! error code, any Kermit-32 error code (KER_xxx) or a user specific code,
  1485. ! provided a message file defining the error code is loaded with Kermit-32.
  1486. !
  1487. ! The routine is called as:
  1488. !
  1489. !    STATUS = USER_FILE_CHECK ( FILE NAME DESCRIPTOR, READ/WRITE FLAG)
  1490. !
  1491. ! The file name descriptor points to the file specification supplied by
  1492. ! the user.  The read/write flag is TRUE if the file is being read, and
  1493. ! false if it is being written.
  1494. !
  1495.     USER_FILE_CHECK : ADDRESSING_MODE(GENERAL) WEAK;
  1496.  
  1497.     LOCAL
  1498.     STATUS,                    ! Random status values
  1499.     ITMLST : VECTOR [4, LONG],        ! For GETDVI call
  1500.     SIZE : WORD;                ! Size of resulting file name
  1501.  
  1502. !
  1503. ! Assume we can do searches
  1504. !
  1505.     SEARCH_FLAG = TRUE;
  1506.     DEV_CLASS = DC$_DISK;            ! Assume disk file
  1507. !
  1508. ! Now do the function dependent processing
  1509. !
  1510.     FILE_MODE = .FUNCTION;
  1511.     FILE_DESC [DSC$W_LENGTH] = .FILE_SIZE;    ! Length of file name
  1512. !
  1513. ! Call user routine (if any)
  1514. !
  1515.     IF USER_FILE_CHECK NEQ 0
  1516.     THEN
  1517.     BEGIN
  1518.     STATUS = USER_FILE_CHECK (FILE_DESC, %REF (.FILE_MODE EQL FNC_READ));
  1519.     IF NOT .STATUS
  1520.     THEN
  1521.         BEGIN
  1522.         LIB$SIGNAL (.STATUS);
  1523.         RETURN .STATUS;
  1524.         END;
  1525.     END;
  1526. !
  1527. ! Select the correct routine depending on if we are reading or writing.
  1528. !
  1529.  
  1530.     SELECTONE .FUNCTION OF
  1531.     SET
  1532.  
  1533.     [FNC_READ] :
  1534.         BEGIN
  1535. !
  1536. ! Determine device type
  1537. !
  1538.         ITMLST [0] = DVI$_DEVCLASS^16 + 4;    ! Want device class
  1539.         ITMLST [1] = DEV_CLASS;        ! Put it there
  1540.         ITMLST [2] = ITMLST [2];        ! Put the size here
  1541.         ITMLST [3] = 0;            ! End the list
  1542.         STATUS = $GETDVIW (DEVNAM = FILE_DESC, ITMLST = ITMLST);
  1543. !
  1544. ! If not a disk, can't do search
  1545. !
  1546.         IF .STATUS AND .DEV_CLASS NEQ DC$_DISK THEN SEARCH_FLAG = FALSE;
  1547.  
  1548. !
  1549. ! Now set up the FAB with the information it needs.
  1550. !
  1551.         $FAB_INIT (FAB = FILE_FAB, FOP = NAM, FNA = FILE_NAME, FNS = .FILE_SIZE,
  1552.         NAM = FILE_NAM, DNM = '.;0');
  1553. !
  1554. ! Now initialize the NAM block
  1555. !
  1556.         $NAM_INIT (NAM = FILE_NAM, RSA = RES_STR, RSS = NAM$C_MAXRSS, ESA = EXP_STR,
  1557.         ESS = NAM$C_MAXRSS);
  1558. !
  1559. ! First parse the file specification.
  1560. !
  1561.         STATUS = $PARSE (FAB = FILE_FAB);
  1562.  
  1563.         IF NOT .STATUS
  1564.         THEN
  1565.         BEGIN
  1566.         FILE_ERROR (.STATUS);
  1567.         RETURN KER_RMS32;
  1568.         END;
  1569.  
  1570.         IF .SEARCH_FLAG
  1571.         THEN
  1572.         BEGIN
  1573.         STATUS = $SEARCH (FAB = FILE_FAB);
  1574.  
  1575.         IF NOT .STATUS
  1576.         THEN
  1577.             BEGIN
  1578.             FILE_ERROR (.STATUS);
  1579.             RETURN KER_RMS32;
  1580.             END;
  1581.  
  1582.         END;
  1583.  
  1584. !
  1585. ! We now have an expanded file specification that we can use to process
  1586. ! the file.
  1587. !
  1588.         STATUS = OPEN_READING ();        ! Open the file
  1589.  
  1590.         IF NOT .STATUS THEN RETURN .STATUS;    ! If we couldn't, pass error back
  1591.  
  1592. !
  1593. ! Tell user what name we ended up with for storing the file
  1594. !
  1595.  
  1596.         IF ( NOT .CONNECT_FLAG) AND .TY_FIL
  1597.         THEN
  1598.         BEGIN
  1599.  
  1600.         IF .FILE_NAM [NAM$B_RSS] GTR 0
  1601.         THEN
  1602.             BEGIN
  1603.             CH$WCHAR (CHR_NUL,
  1604.             CH$PTR (.FILE_NAM [NAM$L_RSA],
  1605.                 .FILE_NAM [NAM$B_RSL]));
  1606.             TT_TEXT (.FILE_NAM [NAM$L_RSA]);
  1607.             END
  1608.         ELSE
  1609.             BEGIN
  1610.             CH$WCHAR (CHR_NUL,
  1611.             CH$PTR (.FILE_NAM [NAM$L_ESA],
  1612.                 .FILE_NAM [NAM$B_ESL]));
  1613.             TT_TEXT (.FILE_NAM [NAM$L_ESA]);
  1614.             END;
  1615.  
  1616.         TT_TEXT (UPLIT (%ASCIZ' as '));
  1617.         END;
  1618.  
  1619.         END;                ! End of [FNC_READ]
  1620.  
  1621.     [FNC_WRITE] :
  1622.         BEGIN
  1623.  
  1624.         SELECTONE .FILE_TYPE OF
  1625.         SET
  1626.  
  1627.         [FILE_ASC] :
  1628.             BEGIN
  1629.             $FAB_INIT (FAB = FILE_FAB, FAC = PUT, FNA = FILE_NAME,
  1630.             FNS = .FILE_SIZE, FOP = (MXV, CBT, SQO, TEF), NAM = FILE_NAM,
  1631.             ORG = SEQ, RFM = VAR, RAT = CR);
  1632.             END;
  1633.  
  1634.         [FILE_BIN] :
  1635.             BEGIN
  1636.             $FAB_INIT (FAB = FILE_FAB, FAC = PUT, FNA = FILE_NAME,
  1637.             FNS = .FILE_SIZE, FOP = (MXV, CBT, SQO, TEF), NAM = FILE_NAM,
  1638.             ORG = SEQ, RFM = VAR);
  1639.             END;
  1640.  
  1641.         [FILE_FIX] :
  1642.             BEGIN
  1643.             $FAB_INIT (FAB = FILE_FAB, FAC = PUT, FNA = FILE_NAME,
  1644.             FNS = .FILE_SIZE, FOP = (MXV, CBT, SQO, TEF), NAM = FILE_NAM,
  1645.             ORG = SEQ, RFM = FIX, MRS = (IF .file_blocksize_set 
  1646.                                                        THEN .file_blocksize
  1647.                                                        ELSE 512));
  1648.             END;
  1649.  
  1650.         [FILE_BLK] :
  1651.             BEGIN
  1652.             $FAB_INIT (FAB = FILE_FAB, FAC = (PUT, BIO), FNA = FILE_NAME,
  1653.             FNS = .FILE_SIZE, FOP = (MXV, CBT, SQO, TEF), NAM = FILE_NAM);
  1654.             END;
  1655.         TES;
  1656.  
  1657. !
  1658. ! If we had an alternate file name from the receive command, use it
  1659. ! instead of what KERMSG has told us.
  1660. !
  1661.  
  1662.         IF .ALT_FILE_SIZE GTR 0
  1663.         THEN
  1664.         BEGIN
  1665.         LOCAL
  1666.             ALT_FILE_DESC : BLOCK [8, BYTE];
  1667.  
  1668.         ALT_FILE_DESC = .FILE_DESC;
  1669.         ALT_FILE_DESC [DSC$W_LENGTH] = .ALT_FILE_SIZE;
  1670.         ALT_FILE_DESC [DSC$A_POINTER] = ALT_FILE_NAME;
  1671.         IF USER_FILE_CHECK NEQ 0
  1672.         THEN
  1673.             BEGIN
  1674.             STATUS = USER_FILE_CHECK (ALT_FILE_DESC, %REF (.FILE_MODE EQL FNC_READ));
  1675.             IF NOT .STATUS
  1676.             THEN
  1677.             BEGIN
  1678.             LIB$SIGNAL (.STATUS);
  1679.             RETURN .STATUS;
  1680.             END;
  1681.             END;
  1682.         FILE_FAB [FAB$L_FNA] = ALT_FILE_NAME;
  1683.         FILE_FAB [FAB$B_FNS] = .ALT_FILE_SIZE;
  1684.         END;
  1685.  
  1686.         $NAM_INIT (NAM = FILE_NAM, ESA = EXP_STR, ESS = NAM$C_MAXRSS, RSA = RES_STR,
  1687.         RSS = NAM$C_MAXRSS);
  1688. !
  1689. ! Now allocate a buffer for the records
  1690. !
  1691. ! Determine correct buffer size
  1692.  
  1693.         SELECTONE .FILE_TYPE OF
  1694.         SET
  1695.  
  1696.         [FILE_ASC] :
  1697.             REC_SIZE = MAX_REC_LENGTH;
  1698.  
  1699.         [FILE_BIN] :
  1700.             REC_SIZE = (IF .file_blocksize_set THEN .file_blocksize
  1701.                                                        ELSE 510);
  1702.  
  1703.         [FILE_BLK] :
  1704.             REC_SIZE = 512;
  1705.  
  1706.                 [FILE_FIX] :
  1707.                     REC_SIZE =  (IF .file_blocksize_set THEN .file_blocksize
  1708.                                                         ELSE 512);
  1709.  
  1710.         TES;
  1711.  
  1712.         STATUS = LIB$GET_VM (REC_SIZE, REC_ADDRESS);
  1713. !
  1714. ! Now create the file
  1715. !
  1716.         STATUS = $CREATE (FAB = FILE_FAB);
  1717.  
  1718.         IF NOT .STATUS
  1719.         THEN
  1720.         BEGIN
  1721.         FILE_ERROR (.STATUS);
  1722.         RETURN KER_RMS32;
  1723.         END;
  1724.  
  1725.         $RAB_INIT (RAB = FILE_RAB, FAB = FILE_FAB, RAC = SEQ, RBF = .REC_ADDRESS,
  1726.         ROP = <NLK, WAT>);
  1727.         STATUS = $CONNECT (RAB = FILE_RAB);
  1728.  
  1729.         IF NOT .STATUS
  1730.         THEN
  1731.         BEGIN
  1732.         FILE_ERROR (.STATUS);
  1733.         RETURN KER_RMS32;
  1734.         END;
  1735.  
  1736. !
  1737. ! Set the initial state into the FAB field.  This is used to remember
  1738. ! whether we need to ignore the line feed which follows a carriage return.
  1739. !
  1740.         FILE_FAB [FAB$L_CTX] = F_STATE_DATA;
  1741.         FILE_REC_COUNT = 0;
  1742.         FILE_REC_POINTER = CH$PTR (.REC_ADDRESS);
  1743. !
  1744. ! Tell user what name we ended up with for storing the file
  1745. !
  1746.  
  1747.         IF ( NOT .CONNECT_FLAG) AND .TY_FIL
  1748.         THEN
  1749.         BEGIN
  1750.         TT_TEXT (UPLIT (%ASCIZ' as '));
  1751.  
  1752.         IF .FILE_NAM [NAM$B_RSL] GTR 0
  1753.         THEN
  1754.             BEGIN
  1755.             CH$WCHAR (CHR_NUL,
  1756.             CH$PTR (.FILE_NAM [NAM$L_RSA],
  1757.                 .FILE_NAM [NAM$B_RSL]));
  1758.             TT_TEXT (.FILE_NAM [NAM$L_RSA]);
  1759.             END
  1760.         ELSE
  1761.             BEGIN
  1762.             CH$WCHAR (CHR_NUL,
  1763.             CH$PTR (.FILE_NAM [NAM$L_ESA],
  1764.                 .FILE_NAM [NAM$B_ESL]));
  1765.             TT_TEXT (.FILE_NAM [NAM$L_ESA]);
  1766.             END;
  1767.  
  1768.         TT_OUTPUT ();
  1769.         END;
  1770.  
  1771.         END;
  1772.  
  1773.     [OTHERWISE] :
  1774.         RETURN KER_INTERNALERR;
  1775.     TES;
  1776.  
  1777. !
  1778. ! Copy the file name based on the type of file name we are to use.
  1779. ! The possibilities are:
  1780. !        Normal - Just copy name and type
  1781. !        Full - Copy entire name string (either resultant or expanded)
  1782. !        Untranslated - Copy string from name on (includes version, etc.)
  1783.  
  1784.     IF .DEV_CLASS EQL DC$_MAILBOX
  1785.     THEN
  1786.     BEGIN
  1787.     SIZE = 0;
  1788.     FILE_NAME = 0;
  1789.     END
  1790.     ELSE
  1791.  
  1792.     SELECTONE .FIL_NORMAL_FORM OF
  1793.         SET
  1794.  
  1795.         [FNM_FULL] :
  1796.         BEGIN
  1797.  
  1798.         IF .FILE_NAM [NAM$B_RSL] GTR 0
  1799.         THEN
  1800.             BEGIN
  1801.             CH$COPY (.FILE_NAM [NAM$B_RSL], CH$PTR (.FILE_NAM [NAM$L_RSA]),
  1802.             CHR_NUL, MAX_FILE_NAME, CH$PTR (FILE_NAME));
  1803.             SIZE = .FILE_NAM [NAM$B_RSL];
  1804.             END
  1805.         ELSE
  1806.             BEGIN
  1807.             CH$COPY (.FILE_NAM [NAM$B_ESL], CH$PTR (.FILE_NAM [NAM$L_ESA]),
  1808.             CHR_NUL, MAX_FILE_NAME, CH$PTR (FILE_NAME));
  1809.             SIZE = .FILE_NAM [NAM$B_ESL];
  1810.             END
  1811.  
  1812.         END;
  1813.  
  1814.         [FNM_NORMAL, FNM_UNTRAN] :
  1815.         BEGIN
  1816.         CH$COPY (.FILE_NAM [NAM$B_NAME], CH$PTR (.FILE_NAM [NAM$L_NAME]),
  1817.             .FILE_NAM [NAM$B_TYPE], CH$PTR (.FILE_NAM [NAM$L_TYPE]), CHR_NUL,
  1818.             MAX_FILE_NAME, CH$PTR (FILE_NAME));
  1819.         SIZE = .FILE_NAM [NAM$B_NAME] + .FILE_NAM [NAM$B_TYPE];
  1820.         END;
  1821.         TES;
  1822.  
  1823.     IF .SIZE GTR MAX_FILE_NAME THEN FILE_SIZE = MAX_FILE_NAME ELSE FILE_SIZE = .SIZE;
  1824.  
  1825.     RETURN KER_NORMAL;
  1826.     END;                    ! End of FILE_OPEN
  1827.  
  1828. %SBTTL 'FILE_CLOSE'
  1829.  
  1830. GLOBAL ROUTINE FILE_CLOSE (ABORT_FLAG) =
  1831.  
  1832. !++
  1833. ! FUNCTIONAL DESCRIPTION:
  1834. !
  1835. !    This routine will close a file that was opened by FILE_OPEN.
  1836. !    It assumes any data associated with the file is stored in this
  1837. !    module, since this routine is called by KERMSG.
  1838. !
  1839. ! CALLING SEQUENCE:
  1840. !
  1841. !    FILE_CLOSE();
  1842. !
  1843. ! INPUT PARAMETERS:
  1844. !
  1845. !    ABORT_FLAG - True if file should not be saved.
  1846. !
  1847. ! IMPLICIT INPUTS:
  1848. !
  1849. !    None.
  1850. !
  1851. ! OUTPUT PARAMETERS:
  1852. !
  1853. !    None.
  1854. !
  1855. ! IMPLICIT OUTPUTS:
  1856. !
  1857. !    None.
  1858. !
  1859. ! COMPLETION CODES:
  1860. !
  1861. !    None.
  1862. !
  1863. ! SIDE EFFECTS:
  1864. !
  1865. !    None.
  1866. !
  1867. !--
  1868.  
  1869.     BEGIN
  1870. !
  1871. ! Completion codes returned:
  1872. !
  1873.     EXTERNAL LITERAL
  1874.     KER_NORMAL,                ! Normal return
  1875.     KER_RMS32;                ! RMS-32 error
  1876.  
  1877.     LOCAL
  1878.     STATUS;                    ! Random status values
  1879.  
  1880. !
  1881. ! If there might be something left to write
  1882.  
  1883. !
  1884.  
  1885.     IF .FILE_MODE EQL FNC_WRITE AND (.FILE_REC_COUNT GTR 0 OR .FILE_FAB [FAB$L_CTX] NEQ
  1886.     F_STATE_DATA)
  1887.     THEN
  1888.     BEGIN
  1889.  
  1890.     SELECTONE .FILE_TYPE OF
  1891.         SET
  1892.  
  1893.         [FILE_FIX] :
  1894.         BEGIN
  1895.  
  1896.         INCR I FROM .FILE_REC_COUNT TO .REC_SIZE - 1 DO
  1897.             CH$WCHAR_A (CHR_NUL, FILE_REC_POINTER);
  1898.         FILE_REC_COUNT = .REC_SIZE;            ! Store the byte count
  1899.         STATUS = DUMP_BUFFER ();
  1900.         END;
  1901.  
  1902.         [FILE_ASC, FILE_BIN] :
  1903.         STATUS = DUMP_BUFFER ();
  1904.  
  1905.         [FILE_BLK] :
  1906.         BEGIN
  1907.         FILE_RAB [RAB$W_RSZ] = .FILE_REC_COUNT;
  1908.         STATUS = $WRITE (RAB = FILE_RAB);
  1909.  
  1910.         IF NOT .STATUS
  1911.         THEN
  1912.             BEGIN
  1913.             FILE_ERROR (.STATUS);
  1914.             STATUS = KER_RMS32;
  1915.             END
  1916.         ELSE
  1917.             STATUS = KER_NORMAL;
  1918.  
  1919.         END;
  1920.         TES;
  1921.  
  1922.     IF NOT .STATUS THEN RETURN .STATUS;
  1923.  
  1924.     END;
  1925.  
  1926. !
  1927. ! If reading from a mailbox, read until EOF to allow the process on the other
  1928. ! end to terminal gracefully.
  1929. !
  1930.  
  1931.     IF .FILE_MODE EQL FNC_READ AND .DEV_CLASS EQL DC$_MAILBOX AND NOT .EOF_FLAG
  1932.     THEN
  1933.  
  1934.     DO
  1935.         STATUS = GET_BUFFER ()
  1936.     UNTIL ( NOT .STATUS) OR .EOF_FLAG;
  1937.  
  1938.     STATUS = LIB$FREE_VM (REC_SIZE, REC_ADDRESS);
  1939.  
  1940.     IF .FIX_SIZE NEQ 0 THEN STATUS = LIB$FREE_VM (FIX_SIZE, FIX_ADDRESS);
  1941.  
  1942.     IF .ABORT_FLAG AND .FILE_MODE EQL FNC_WRITE
  1943.     THEN
  1944.     FILE_FAB [FAB$V_DLT] = TRUE
  1945.     ELSE
  1946.     FILE_FAB [FAB$V_DLT] = FALSE;
  1947.  
  1948.     STATUS = $CLOSE (FAB = FILE_FAB);
  1949.     EOF_FLAG = FALSE;
  1950.  
  1951.     IF NOT .STATUS
  1952.     THEN
  1953.     BEGIN
  1954.     FILE_ERROR (.STATUS);
  1955.     RETURN KER_RMS32;
  1956.     END
  1957.     ELSE
  1958.     RETURN KER_NORMAL;
  1959.  
  1960.     END;                    ! End of FILE_CLOSE
  1961.  
  1962. %SBTTL 'NEXT_FILE'
  1963.  
  1964. GLOBAL ROUTINE NEXT_FILE =
  1965.  
  1966. !++
  1967. ! FUNCTIONAL DESCRIPTION:
  1968. !
  1969. !    This routine will cause the next file to be opened.  It will
  1970. !    call the RMS-32 routine $SEARCH and $OPEN for the file.
  1971. !
  1972. ! CALLING SEQUENCE:
  1973. !
  1974. !    STATUS = NEXT_FILE;
  1975. !
  1976. ! INPUT PARAMETERS:
  1977. !
  1978. !    None.
  1979. !
  1980. ! IMPLICIT INPUTS:
  1981. !
  1982. !    FAB/NAM blocks set up from previous processing.
  1983. !
  1984. ! OUTPUT PARAMETERS:
  1985. !
  1986. !    None.
  1987. !
  1988. ! IMPLICIT OUTPUTS:
  1989. !
  1990. !    FAB/NAM blocks set up for the next file.
  1991. !
  1992. ! COMPLETION CODES:
  1993. !
  1994. !    TRUE - There is a next file.
  1995. !    KER_RMS32 - No next file.
  1996. !
  1997. ! SIDE EFFECTS:
  1998. !
  1999. !    None.
  2000. !
  2001. !--
  2002.  
  2003.     BEGIN
  2004. !
  2005. ! Completion codes returned:
  2006. !
  2007.     EXTERNAL LITERAL
  2008.     KER_NORMAL,                ! Normal return
  2009.     KER_NOMORFILES,                ! No more files to read
  2010.     KER_RMS32;                ! RMS-32 error
  2011.  
  2012.     EXTERNAL ROUTINE
  2013.     TT_TEXT : NOVALUE;            ! Output an ASCIZ string
  2014.  
  2015.     LOCAL
  2016.     SIZE : WORD,                ! Size of the $FAO string
  2017.     STATUS;                    ! Random status values
  2018.  
  2019. !
  2020. ! If we can't do a search, just return no more files
  2021. !
  2022.  
  2023.     IF NOT .SEARCH_FLAG THEN RETURN KER_NOMORFILES;
  2024.  
  2025. !
  2026. ! Now search for the next file that we want to process.
  2027. !
  2028.     STATUS = $SEARCH (FAB = FILE_FAB);
  2029.  
  2030.     IF .STATUS EQL RMS$_NMF THEN RETURN KER_NOMORFILES;
  2031.  
  2032.     IF NOT .STATUS
  2033.     THEN
  2034.     BEGIN
  2035.     FILE_ERROR (.STATUS);
  2036.     RETURN KER_RMS32;
  2037.     END;
  2038.  
  2039. !
  2040. ! Now we have the new file name.  All that we have to do is open the file
  2041. ! for reading now.
  2042. !
  2043.     STATUS = OPEN_READING ();
  2044.  
  2045.     IF NOT .STATUS THEN RETURN .STATUS;
  2046.  
  2047. !
  2048. ! Copy the file name based on the type of file name we are to use.
  2049. ! The possibilities are:
  2050. !        Normal - Just copy name and type
  2051. !        Full - Copy entire name string (either resultant or expanded)
  2052. !        Untranslated - Copy string from name on (includes version, etc.)
  2053.  
  2054.     SELECTONE .FIL_NORMAL_FORM OF
  2055.     SET
  2056.  
  2057.     [FNM_FULL] :
  2058.         BEGIN
  2059.  
  2060.         IF .FILE_NAM [NAM$B_RSL] GTR 0
  2061.         THEN
  2062.         BEGIN
  2063.         CH$COPY (.FILE_NAM [NAM$B_RSL], CH$PTR (.FILE_NAM [NAM$L_RSA]), CHR_NUL,
  2064.             MAX_FILE_NAME, CH$PTR (FILE_NAME));
  2065.         SIZE = .FILE_NAM [NAM$B_RSL];
  2066.         END
  2067.         ELSE
  2068.         BEGIN
  2069.         CH$COPY (.FILE_NAM [NAM$B_ESL], CH$PTR (.FILE_NAM [NAM$L_ESA]), CHR_NUL,
  2070.             MAX_FILE_NAME, CH$PTR (FILE_NAME));
  2071.         SIZE = .FILE_NAM [NAM$B_ESL];
  2072.         END
  2073.  
  2074.         END;
  2075.  
  2076.     [FNM_NORMAL, FNM_UNTRAN] :
  2077.         BEGIN
  2078.         CH$COPY (.FILE_NAM [NAM$B_NAME], CH$PTR (.FILE_NAM [NAM$L_NAME]),
  2079.         .FILE_NAM [NAM$B_TYPE], CH$PTR (.FILE_NAM [NAM$L_TYPE]), CHR_NUL,
  2080.         MAX_FILE_NAME, CH$PTR (FILE_NAME));
  2081.         SIZE = .FILE_NAM [NAM$B_NAME] + .FILE_NAM [NAM$B_TYPE];
  2082.         END;
  2083.     TES;
  2084.  
  2085.     IF .SIZE GTR MAX_FILE_NAME THEN FILE_SIZE = MAX_FILE_NAME ELSE FILE_SIZE = .SIZE;
  2086.  
  2087. !
  2088. ! Put prompt for NEXT_FILE sending in here
  2089. !
  2090.     IF ( NOT .CONNECT_FLAG) AND .TY_FIL
  2091.     THEN
  2092.         BEGIN
  2093.         TT_TEXT (UPLIT (%ASCIZ 'Sending: '));
  2094.         .FILE_NAM [NAM$L_RSA] + .FILE_NAM [NAM$B_RSL] = 0;
  2095.         TT_TEXT (.FILE_NAM [NAM$L_RSA]);
  2096.         TT_TEXT (UPLIT (%ASCIZ ' as '));
  2097.         TT_OUTPUT ();
  2098.         END;
  2099.  
  2100.     RETURN KER_NORMAL;
  2101.     END;                    ! End of NEXT_FILE
  2102.  
  2103. %SBTTL 'LOG_OPEN - Open a log file'
  2104.  
  2105. GLOBAL ROUTINE LOG_OPEN (LOG_DESC, LOG_FAB, LOG_RAB) =
  2106.  
  2107. !++
  2108. ! FUNCTIONAL DESCRIPTION:
  2109. !
  2110. ! CALLING SEQUENCE:
  2111. !
  2112. !    STATUS = LOG_OPEN (LOG_DESC, LOG_FAB, LOG_RAB)
  2113. !
  2114. ! INPUT PARAMETERS:
  2115. !
  2116. !    LOG_DESC - Address of descriptor for file name to be opened
  2117. !
  2118. !    LOG_FAB - Address of FAB for file
  2119. !
  2120. !    LOG_RAB - Address of RAB for file
  2121. !
  2122. ! IMPLICIT INPUTS:
  2123. !
  2124. !    None.
  2125. !
  2126. ! OUPTUT PARAMETERS:
  2127. !
  2128. !    LOG_FAB and LOG_RAB updated.
  2129. !
  2130. ! IMPLICIT OUTPUTS:
  2131. !
  2132. !    None.
  2133. !
  2134. ! COMPLETION CODES:
  2135. !
  2136. !    Error code or true.
  2137. !
  2138. ! SIDE EFFECTS:
  2139. !
  2140. !    None.
  2141. !
  2142. !--
  2143.  
  2144.     BEGIN
  2145. !
  2146. ! Completion codes returned:
  2147. !
  2148.     EXTERNAL LITERAL
  2149.     KER_NORMAL,                ! Normal return
  2150.     KER_RMS32;                ! RMS-32 error
  2151.  
  2152.     MAP
  2153.     LOG_DESC : REF BLOCK [8, BYTE],        ! Name descriptor
  2154.     LOG_FAB : REF $FAB_DECL,        ! FAB for file
  2155.     LOG_RAB : REF $RAB_DECL;        ! RAB for file
  2156.  
  2157.     LOCAL
  2158.     STATUS,                    ! Random status values
  2159.     REC_ADDRESS,                ! Address of record buffer
  2160.     REC_SIZE;                ! Size of record buffer
  2161.  
  2162. !
  2163. ! Get memory for records
  2164. !
  2165.     REC_SIZE = LOG_BUFF_SIZE;
  2166.     STATUS = LIB$GET_VM (REC_SIZE, REC_ADDRESS);
  2167.  
  2168.     IF NOT .STATUS
  2169.     THEN
  2170.     BEGIN
  2171.     LIB$SIGNAL (.STATUS);
  2172.     RETURN .STATUS;
  2173.     END;
  2174.  
  2175. !
  2176. ! Initialize the FAB and RAB
  2177. !
  2178.     $FAB_INIT (FAB = .LOG_FAB, FAC = PUT, FNA = .LOG_DESC [DSC$A_POINTER],
  2179.     FNS = .LOG_DESC [DSC$W_LENGTH], FOP = (MXV, CBT, SQO, TEF), ORG = SEQ, RFM = VAR,
  2180.     RAT = CR, CTX = 0, DNA = UPLIT (%ASCII'.LOG'), DNS = 4);
  2181.     STATUS = $CREATE (FAB = .LOG_FAB);
  2182.  
  2183.     IF NOT .STATUS
  2184.     THEN
  2185.     BEGIN
  2186.     FILE_ERROR (.STATUS);
  2187.     LIB$FREE_VM (REC_SIZE, REC_ADDRESS);    ! Dump record buffer
  2188.     RETURN KER_RMS32;
  2189.     END;
  2190.  
  2191.     $RAB_INIT (RAB = .LOG_RAB, FAB = .LOG_FAB, RAC = SEQ, RBF = .REC_ADDRESS,
  2192.     RSZ = .REC_SIZE, UBF = .REC_ADDRESS, USZ = .REC_SIZE, ROP = <NLK, WAT>, CTX = 0);
  2193.     STATUS = $CONNECT (RAB = .LOG_RAB);
  2194.  
  2195.     IF NOT .STATUS
  2196.     THEN
  2197.     BEGIN
  2198.     FILE_ERROR (.STATUS);
  2199.     LIB$FREE_VM (REC_SIZE, REC_ADDRESS);
  2200.     $CLOSE (FAB = .LOG_FAB);
  2201.     RETURN KER_RMS32;
  2202.     END
  2203.     ELSE
  2204.     RETURN .STATUS;
  2205.  
  2206.     END;                    ! End of LOG_OPEN
  2207.  
  2208. %SBTTL 'LOG_CLOSE - Close a log file'
  2209.  
  2210. GLOBAL ROUTINE LOG_CLOSE (LOG_FAB, LOG_RAB) =
  2211.  
  2212. !++
  2213. ! FUNCTIONAL DESCRIPTION:
  2214. !
  2215. ! This routine will close an open log file.  It will also ensure that
  2216. !the last buffer gets dumped.
  2217. !
  2218. ! CALLING SEQUENCE:
  2219. !
  2220. !    STATUS = LOG_CLOSE (LOG_FAB, LOG_RAB);
  2221. !
  2222. ! INPUT PARAMETERS:
  2223. !
  2224. !    LOG_FAB - Address of log file FAB
  2225. !
  2226. !    LOG_RAB - Address of log file RAB
  2227. !
  2228. ! IMPLICIT INPUTS:
  2229. !
  2230. !    None.
  2231. !
  2232. ! OUPTUT PARAMETERS:
  2233. !
  2234. !    None.
  2235. !
  2236. ! IMPLICIT OUTPUTS:
  2237. !
  2238. !    None.
  2239. !
  2240. ! COMPLETION CODES:
  2241. !
  2242. !    Resulting status.
  2243. !
  2244. ! SIDE EFFECTS:
  2245. !
  2246. !    None.
  2247. !
  2248. !--
  2249.  
  2250.     BEGIN
  2251. !
  2252. ! Completion codes returned:
  2253. !
  2254.     EXTERNAL LITERAL
  2255.     KER_RMS32;                ! RMS-32 error
  2256.  
  2257.     MAP
  2258.     LOG_FAB : REF $FAB_DECL,        ! FAB for log file
  2259.     LOG_RAB : REF $RAB_DECL;        ! RAB for log file
  2260.  
  2261.     LOCAL
  2262.     STATUS,                    ! Random status values
  2263.     REC_ADDRESS,                ! Address of record buffer
  2264.     REC_SIZE;                ! Size of record buffer
  2265.  
  2266. !
  2267. ! First write out any outstanding data
  2268. !
  2269.  
  2270.     IF .LOG_RAB [RAB$L_CTX] GTR 0 THEN LOG_PUT (.LOG_RAB);    ! Dump current buffer
  2271.  
  2272. !
  2273. ! Return the buffer
  2274. !
  2275.     REC_SIZE = LOG_BUFF_SIZE;            ! Get size of buffer
  2276.     REC_ADDRESS = .LOG_RAB [RAB$L_RBF];        ! And address
  2277.     LIB$FREE_VM (REC_SIZE, REC_ADDRESS);
  2278. !
  2279. ! Now disconnect the RAB
  2280. !
  2281.     STATUS = $DISCONNECT (RAB = .LOG_RAB);
  2282.  
  2283.     IF NOT .STATUS
  2284.     THEN
  2285.     BEGIN
  2286.     FILE_ERROR (.STATUS);
  2287.     RETURN KER_RMS32;
  2288.     END;
  2289.  
  2290. !
  2291. ! Now we can close the file
  2292. !
  2293.     STATUS = $CLOSE (FAB = .LOG_FAB);
  2294.  
  2295.     IF NOT .STATUS THEN FILE_ERROR (.STATUS);
  2296.  
  2297. !
  2298. ! And return the result
  2299. !
  2300.     RETURN .STATUS;
  2301.     END;                    ! End of LOG_CLOSE
  2302.  
  2303. %SBTTL 'LOG_CHAR - Log a character to a file'
  2304.  
  2305. GLOBAL ROUTINE LOG_CHAR (CH, LOG_RAB) =
  2306.  
  2307. !++
  2308. ! FUNCTIONAL DESCRIPTION:
  2309. !
  2310. ! This routine will write one character to an open log file.
  2311. !If the buffer becomes filled, it will dump it.  It will also
  2312. !dump the buffer if a carriage return line feed is seen.
  2313. !
  2314. ! CALLING SEQUENCE:
  2315. !
  2316. !    STATUS = LOG_CHAR (.CH, LOG_RAB);
  2317. !
  2318. ! INPUT PARAMETERS:
  2319. !
  2320. !    CH - The character to write to the file.
  2321. !
  2322. !    LOG_RAB - The address of the log file RAB.
  2323. !
  2324. ! IMPLICIT INPUTS:
  2325. !
  2326. !    None.
  2327. !
  2328. ! OUPTUT PARAMETERS:
  2329. !
  2330. !    None.
  2331. !
  2332. ! IMPLICIT OUTPUTS:
  2333. !
  2334. !    None.
  2335. !
  2336. ! COMPLETION CODES:
  2337. !
  2338. !    Any error returned by LOG_PUT, else TRUE.
  2339. !
  2340. ! SIDE EFFECTS:
  2341. !
  2342. !    None.
  2343. !
  2344. !--
  2345.  
  2346.     BEGIN
  2347. !
  2348. ! Completion codes returned:
  2349. !
  2350.     EXTERNAL LITERAL
  2351.     KER_NORMAL;                ! Normal return
  2352.  
  2353.     MAP
  2354.     LOG_RAB : REF $RAB_DECL;        ! Log file RAB
  2355.  
  2356.     LOCAL
  2357.     STATUS;                    ! Random status value
  2358.  
  2359. !
  2360. ! If this character is a line feed, and previous was a carriage return, then
  2361. ! dump the buffer and return.
  2362. !
  2363.  
  2364.     IF .CH EQL CHR_LFD
  2365.     THEN
  2366.     BEGIN
  2367. !
  2368. ! If we seem to have overfilled the buffer, that is because we saw a CR
  2369. ! last, and had no place to put it.  Just reset the size and dump the buffer.
  2370. !
  2371.  
  2372.     IF .LOG_RAB [RAB$L_CTX] GTR LOG_BUFF_SIZE
  2373.     THEN
  2374.         BEGIN
  2375.         LOG_RAB [RAB$L_CTX] = LOG_BUFF_SIZE;
  2376.         RETURN LOG_PUT (.LOG_RAB);
  2377.         END;
  2378.  
  2379. !
  2380. ! If last character in buffer is a CR, then dump buffer without the CR
  2381. !
  2382.  
  2383.     IF CH$RCHAR (CH$PTR (.LOG_RAB [RAB$L_RBF], .LOG_RAB [RAB$L_CTX] - 1)) EQL CHR_CRT
  2384.     THEN
  2385.         BEGIN
  2386.         LOG_RAB [RAB$L_CTX] = .LOG_RAB [RAB$L_CTX] - 1;
  2387.         RETURN LOG_PUT (.LOG_RAB);
  2388.         END;
  2389.  
  2390.     END;
  2391.  
  2392. !
  2393. ! Don't need to dump buffer because of end of line problems.  Check if
  2394. ! the buffer is full.
  2395. !
  2396.  
  2397.     IF .LOG_RAB [RAB$L_CTX] GEQ LOG_BUFF_SIZE
  2398.     THEN
  2399.     BEGIN
  2400. !
  2401. ! If character we want to store is a carriage return, then just count it and
  2402. ! don't dump the buffer yet.
  2403. !
  2404.  
  2405.     IF .CH EQL CHR_CRT
  2406.     THEN
  2407.         BEGIN
  2408.         LOG_RAB [RAB$L_CTX] = .LOG_RAB [RAB$L_CTX] + 1;
  2409.         RETURN KER_NORMAL;
  2410.         END;
  2411.  
  2412. !
  2413. ! We must dump the buffer to make room for more characters
  2414. !
  2415.     STATUS = LOG_PUT (.LOG_RAB);
  2416.  
  2417.     IF NOT .STATUS THEN RETURN .STATUS;
  2418.  
  2419.     END;
  2420.  
  2421. !
  2422. ! Here when we have some room to store the character
  2423. !
  2424.     CH$WCHAR (.CH, CH$PTR (.LOG_RAB [RAB$L_RBF], .LOG_RAB [RAB$L_CTX]));
  2425.     LOG_RAB [RAB$L_CTX] = .LOG_RAB [RAB$L_CTX] + 1;
  2426.     RETURN KER_NORMAL;
  2427.     END;                    ! End of LOG_CHAR
  2428.  
  2429. %SBTTL 'LOG_LINE - Log a line to a log file'
  2430.  
  2431. GLOBAL ROUTINE LOG_LINE (LINE_DESC, LOG_RAB) =
  2432.  
  2433. !++
  2434. ! FUNCTIONAL DESCRIPTION:
  2435. !
  2436. ! This routine will write an entire line to a log file.  And previously
  2437. ! written characters will be dumped first.
  2438. !
  2439. ! CALLING SEQUENCE:
  2440. !
  2441. !    STATUS = LOG_LINE (LINE_DESC, LOG_RAB);
  2442. !
  2443. ! INPUT PARAMETERS:
  2444. !
  2445. !    LINE_DESC - Address of descriptor for string to be written
  2446. !
  2447. !    LOG_RAB - RAB for log file
  2448. !
  2449. ! IMPLICIT INPUTS:
  2450. !
  2451. !    None.
  2452. !
  2453. ! OUPTUT PARAMETERS:
  2454. !
  2455. !    None.
  2456. !
  2457. ! IMPLICIT OUTPUTS:
  2458. !
  2459. !    None.
  2460. !
  2461. ! COMPLETION CODES:
  2462. !
  2463. !   KER_NORMAL or LOG_PUT error code.
  2464. !
  2465. ! SIDE EFFECTS:
  2466. !
  2467. !    None.
  2468. !
  2469. !--
  2470.  
  2471.     BEGIN
  2472.  
  2473.     MAP
  2474.     LINE_DESC : REF BLOCK [8, BYTE],    ! Descriptor for string
  2475.     LOG_RAB : REF $RAB_DECL;        ! RAB for file
  2476.  
  2477.     LOCAL
  2478.     STATUS;                    ! Random status value
  2479.  
  2480. !
  2481. ! First check if anything is already in the buffer
  2482. !
  2483.  
  2484.     IF .LOG_RAB [RAB$L_CTX] GTR 0
  2485.     THEN
  2486.     BEGIN
  2487.     STATUS = LOG_PUT (.LOG_RAB);        ! Yes, write it out
  2488.  
  2489.     IF NOT .STATUS THEN RETURN .STATUS;    ! Pass back any errors
  2490.  
  2491.     END;
  2492.  
  2493. !
  2494. ! Copy the data to the buffer
  2495. !
  2496.     CH$COPY (.LINE_DESC [DSC$W_LENGTH], CH$PTR (.LINE_DESC [DSC$A_POINTER]), CHR_NUL,
  2497.     LOG_BUFF_SIZE, CH$PTR (.LOG_RAB [RAB$L_RBF]));
  2498.  
  2499.     IF .LINE_DESC [DSC$W_LENGTH] GTR LOG_BUFF_SIZE
  2500.     THEN
  2501.     LOG_RAB [RAB$L_CTX] = LOG_BUFF_SIZE
  2502.     ELSE
  2503.     LOG_RAB [RAB$L_CTX] = .LINE_DESC [DSC$W_LENGTH];
  2504.  
  2505. !
  2506. ! Now just dump the buffer
  2507. !
  2508.     RETURN LOG_PUT (.LOG_RAB);
  2509.     END;                    ! End of LOG_LINE
  2510. %SBTTL 'LOG_FAOL - Log an FAO string to the log file'
  2511.  
  2512. GLOBAL ROUTINE LOG_FAOL (FAOL_DESC, FAOL_PARAMS, LOG_RAB) =
  2513.  
  2514. !++
  2515. ! FUNCTIONAL DESCRIPTION:
  2516. !
  2517. ! This routine will write an FAOL string to the output file.
  2518. !
  2519. ! CALLING SEQUENCE:
  2520. !
  2521. !    STATUS = LOG_FAOL (FAOL_DESC, FAOL_PARAMS, LOG_RAB);
  2522. !
  2523. ! INPUT PARAMETERS:
  2524. !
  2525. !    FAOL_DESC - Address of descriptor for string to be written
  2526. !
  2527. !    FAOL_PARAMS - Parameter list for FAOL call
  2528. !
  2529. !    LOG_RAB - RAB for log file
  2530. !
  2531. ! IMPLICIT INPUTS:
  2532. !
  2533. !    None.
  2534. !
  2535. ! OUPTUT PARAMETERS:
  2536. !
  2537. !    None.
  2538. !
  2539. ! IMPLICIT OUTPUTS:
  2540. !
  2541. !    None.
  2542. !
  2543. ! COMPLETION CODES:
  2544. !
  2545. !    KER_NORMAL or $FAOL or LOG_PUT error code.
  2546. !
  2547. ! SIDE EFFECTS:
  2548. !
  2549. !    None.
  2550. !
  2551. !--
  2552.  
  2553.     BEGIN
  2554. !
  2555. ! Completion codes returned:
  2556. !
  2557.     EXTERNAL LITERAL
  2558.     KER_NORMAL;                ! Normal return
  2559.  
  2560.     MAP
  2561.     FAOL_DESC : REF BLOCK [8, BYTE],    ! Descriptor for string
  2562.     LOG_RAB : REF $RAB_DECL;        ! RAB for file
  2563.  
  2564.     LITERAL
  2565.     FAOL_BUFSIZ = 256;            ! Length of buffer
  2566.  
  2567.     LOCAL
  2568.     FAOL_BUFFER : VECTOR [FAOL_BUFSIZ, BYTE], ! Buffer for FAOL output
  2569.     FAOL_BUF_DESC : BLOCK [8, BYTE],    ! Descriptor for buffer
  2570.     STATUS;                    ! Random status value
  2571.  
  2572. !
  2573. ! Initialize descriptor for buffer
  2574. !
  2575.     FAOL_BUF_DESC [DSC$B_CLASS] = DSC$K_CLASS_S;
  2576.     FAOL_BUF_DESC [DSC$B_DTYPE] = DSC$K_DTYPE_T;
  2577.     FAOL_BUF_DESC [DSC$A_POINTER] = FAOL_BUFFER;
  2578.     FAOL_BUF_DESC [DSC$W_LENGTH] = FAOL_BUFSIZ;
  2579. !
  2580. ! Now do the FAOL to generate the full text
  2581. !
  2582.     STATUS = $FAOL (CTRSTR = .FAOL_DESC, OUTBUF = FAOL_BUF_DESC,
  2583.     OUTLEN = FAOL_BUF_DESC [DSC$W_LENGTH], PRMLST = .FAOL_PARAMS);
  2584.     IF NOT .STATUS THEN RETURN .STATUS;
  2585. !
  2586. ! Dump the text into the file
  2587. !
  2588.     INCR I FROM 1 TO .FAOL_BUF_DESC [DSC$W_LENGTH] DO
  2589.     BEGIN
  2590.     STATUS = LOG_CHAR ( .FAOL_BUFFER [.I - 1], .LOG_RAB);
  2591.     IF NOT .STATUS THEN RETURN .STATUS;
  2592.     END;
  2593.  
  2594.     RETURN KER_NORMAL;
  2595.  
  2596.     END;                    ! End of LOG_FAOL
  2597.  
  2598. %SBTTL 'LOG_PUT - Write a record buffer for a log file'
  2599. ROUTINE LOG_PUT (LOG_RAB) =
  2600.  
  2601. !++
  2602. ! FUNCTIONAL DESCRIPTION:
  2603. !
  2604. ! This routine will output one buffer for a log file.
  2605. !
  2606. ! CALLING SEQUENCE:
  2607. !
  2608. !    STATUS = LOG_PUT (LOG_RAB);
  2609. !
  2610. ! INPUT PARAMETERS:
  2611. !
  2612. !    LOG_RAB - RAB for log file.
  2613. !
  2614. ! IMPLICIT INPUTS:
  2615. !
  2616. !    None.
  2617. !
  2618. ! OUPTUT PARAMETERS:
  2619. !
  2620. !    None.
  2621. !
  2622. ! IMPLICIT OUTPUTS:
  2623. !
  2624. !    None.
  2625. !
  2626. ! COMPLETION CODES:
  2627. !
  2628. !    Status value from RMS
  2629. !
  2630. ! SIDE EFFECTS:
  2631. !
  2632. !    None.
  2633. !
  2634. !--
  2635.  
  2636.     BEGIN
  2637.  
  2638.     MAP
  2639.     LOG_RAB : REF $RAB_DECL;        ! RAB for file
  2640.  
  2641. !
  2642. ! Calculate record size
  2643. !
  2644.     LOG_RAB [RAB$W_RSZ] = .LOG_RAB [RAB$L_CTX];
  2645.     LOG_RAB [RAB$W_USZ] = .LOG_RAB [RAB$W_RSZ];
  2646. !
  2647. ! Buffer will be empty when we finish
  2648. !
  2649.     LOG_RAB [RAB$L_CTX] = 0;
  2650. !
  2651. ! And call RMS to write the buffer
  2652. !
  2653.     RETURN $PUT (RAB = .LOG_RAB);
  2654.     END;                    ! End of LOG_PUT
  2655. %SBTTL 'FILE_ERROR - Error processing for all RMS errors'
  2656. ROUTINE FILE_ERROR (STATUS) : NOVALUE =
  2657.  
  2658. !++
  2659. ! FUNCTIONAL DESCRIPTION:
  2660. !
  2661. !    This routine will process all of the RMS-32 error returns.  It will
  2662. !    get the text for the error and then it will issue a KER_ERROR for
  2663. !    the RMS failure.
  2664. !
  2665. ! CALLING SEQUENCE:
  2666. !
  2667. !    FILE_ERROR();
  2668. !
  2669. ! INPUT PARAMETERS:
  2670. !
  2671. !    None.
  2672. !
  2673. ! IMPLICIT INPUTS:
  2674. !
  2675. !    STATUS - RMS error status.
  2676. !    FILE_NAME - File name and extension.
  2677. !    FILE_SIZE - Size of the thing in FILE_NAME.
  2678. !
  2679. ! OUTPUT PARAMETERS:
  2680. !
  2681. !    None.
  2682. !
  2683. ! IMPLICIT OUTPUTS:
  2684. !
  2685. !    None.
  2686. !
  2687. ! COMPLETION CODES:
  2688. !
  2689. !    None.
  2690. !
  2691. ! SIDE EFFECTS:
  2692. !
  2693. !    None.
  2694. !
  2695. !--
  2696.  
  2697.     BEGIN
  2698. !
  2699. ! KERMIT completion codes 
  2700. !
  2701.     EXTERNAL LITERAL
  2702.     KER_RMS32;                ! RMS-32 error
  2703.  
  2704.     LOCAL
  2705.     ERR_BUFFER : VECTOR [CH$ALLOCATION (MAX_MSG)],
  2706.     ERR_DESC : BLOCK [8, BYTE] PRESET    ! String descriptor to
  2707.            ([DSC$B_CLASS ] = DSC$K_CLASS_S,    !  the error buffer
  2708.         [DSC$B_DTYPE ] = DSC$K_DTYPE_T,    !  standard string
  2709.         [DSC$W_LENGTH ] = MAX_MSG,    !  descriptor
  2710.         [DSC$A_POINTER ] = ERR_BUFFER);
  2711.  
  2712.     $GETMSG (MSGID = .STATUS,
  2713.              MSGLEN = ERR_DESC [DSC$W_LENGTH],
  2714.              BUFADR = ERR_DESC, 
  2715.              FLAGS = 1);
  2716.     LIB$SIGNAL (KER_RMS32, 2, ERR_DESC, FILE_DESC);
  2717.     END;                    ! End of FILE_ERROR
  2718. %SBTTL 'End of KERFIL'
  2719. END                        ! End of module
  2720.  
  2721. ELUDOM
  2722.