;;; -*- Fonts: CPTFONTB -*- ;;; $Header: /ct/interp/textio.l,v 1.28 84/09/10 16:10:45 alex Exp $ ;;; $Log: ;;; ;;; -*- mode:lisp;package:user;base:10.;fonts:(cptfontb) -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; TEXTIO ;;; ;;; John Shelton ;;; ;;; Alex C. Meng ;;; ;;; ;;; ;;; Thisfile is part of a proprietary software project. Source ;;; ;;; code and documentation describing implementation details are ;;; ;;; available on a confidential, non-disclosure basis only. These ;;; ;;; materials, including this file in particular, are trade secrets ;;; ;;; of Computer * Thought Corporation. ;;; ;;; ;;; ;;; (c) Copyright 1982 and 1983, Computer * Thought Corporation. ;;; ;;; All Rights Reserved. ;;; ;;; ;;; ;;; Reference materials: ;;; ;;; Foderaro and Sklower, The FRANZ LISP Manual, September 1981. ;;; ;;; Weinreb and Moon, LISP MACHINE MANUAL, Symbolics, July 1981. ;;; ;;; Charniak et al., 1980. Artificial Intelligence Programming. ;;; ;;; Miller, 1982. The C*T Ada Tutor: Guide to the Implementation. ;;; ;;; AJPO, Feb 1983. ANSI/MIL-STD-1815A Ada Reference Manual. ;;; ;;; The following code assumes familiarity with these materials. ;;; ;;; ;;; ;;; ASSUMES CT_LOAD AND SUITABLE FILEMAP ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; #+franz (declare (macros t)) ; This file contains code to implement "top_level" functions that will be ; written to directly interpret ADA functions and procedures for textio. (eval-when (compile load eval) (ct_load 'charmac));CT char set extensions. (eval-when (compile load eval) (ct_load 'aip)) ;AIP macros pkg. (eval-when (compile load eval) (ct_load 'compat)) ;Franz/LM compat pkg. (eval-when (compile load eval) (ct_load 'ctflav));Compatible flavors. (eval-when (compile load eval) (ct_load 'iocompat)) (eval-when (compile load eval) (ct_load 'diana)) ; diana structure (eval-when (compile load eval) (ct_load 'ioflav)) (eval-when (compile load eval) ;With_ada_parameters macro. (ct_load 'bifmacs)) (eval-when (compile load eval) ;For ada_raise. (ct_load 'dsmacs)) (eval-when (compile load eval) ;For string package (ct_load 'ctstrl)) ; **************************************************************** ; Notes about procedures. ; **************************************************************** ; Procedures of N parameters (in ADA) will be simulated in LISP by ; passing in N arguments, and returning a list of N items corresponding ; to the parameters. If there are additional arguments that need ; be supplied the function, they will not be returned. These arguments ; typically are used to simulate a specific, instantiated procedure for ; a particular sub_type. ; Some procedures and functions may accept optional arguments. These ; are not truly optional, but do allow the user of this package to specify ; nil to request a DEFAULT value, rather than explicitly providing a value. ; **************************************************************** ; Functions ; **************************************************************** ; ada_create_file creates and opens a file. It is ; not clear what to do when an existing file is asked to be created in INPUT ; mode. We detect a file's already being open by the non_nil file slot. We don't ;;; do anything with the FORM input. (defun ada_create_file (file mode name form) (cond (file ; If there is already a file obj, (ada_raise '|status_error| "File object already exists.")) ((eq mode 'input) ; If mode is INPUT, then open (let ((fileo (errset (open_for_input name) nil))) (ct_if (null fileo) (ada_raise '|name_error| "cannot create the input file") (setq file (car fileo ))))) (t (let* ((fname (ct_if (equal name "") (ct_string_append "#junk" (#+lispm string #+franz get_pname (gensym))) name)) (fileo (errset (open_for_output fname) nil))) (ct_if (null fileo) (ada_raise '|name_error| "cannot create the output file") (setq file (car fileo))) (ct_if (equal name "") (setq *textio_temp_file_list* (cons file *textio_temp_file_list*)))))) (list file mode name form)) ; ada_open_file establishes a port for reading or writing. No file reading ; or writing can occur without a file being open. Note the subtle ; difference with ada_create_file. Also note that for output mode, this ; function requires that the file already exists, even though it will just ; write over it anyway. (defun ada_open_file (file mode name form) (cond ((not (ct_probef name)) ; If file doesn't exist (ada_raise '|name_error| "File does not exist.")) ((and file (eq (get_status file) 'open)) (ada_raise '|status_error| "File is already open.")) ; complain. ((eq mode 'input) (let ((fileo (errset (open_for_input name) nil))) (ct_if (null fileo) (ada_raise '|name_error| "cannot open the input file") (setq file (car fileo))))) (t (let ((fileo (errset (open_for_output name) nil))) (ct_if (null fileo) (ada_raise '|name_error| "cannot open the output file") (setq file (car fileo)))))) (list file mode name form)) ; ada_close_file closes a file. STATUS_ERROR is raised if the file is not ; open. (defun ada_close_file (file) (cond ((or (eq file *ada_default_original_input*) (eq file *ada_default_input*) (eq file *ada_default_original_output*) (eq file *ada_default_output*)) (ada_raise '|status_error| "Attempt to close standard stream.")) ((and file (eq (get_status file) 'open)) (ct_send file 'close)) ; close the file (t (ada_raise '|status_error| "Attempt to close non_open stream"))) (list file)) ; ada_delete_file closes and deletes an open file. STATUS_ERROR is raised ; if the file is not open. (defun ada_delete_file (file) (cond ((or (eq file *ada_default_original_input*) (eq file *ada_default_input*) (eq file *ada_default_original_output*) (eq file *ada_default_output*)) (ada_raise '|status_error| "Attempt to close standard stream.")) ((and file (eq (get_status file) 'open)) (ct_send file 'delete) (setq file nil)) (t (ada_raise '|status_error| "Attempt to close non_open stream."))) (list file)) ; ada_reset_file will reset the file so that reading or writing starts from ; the beginning of the file. A mode may be specified (IN, OUT) to change ; the current mode, if desired. This can be accomplished by closing the ; file and then opening it again. (Use NIL to specify no particular mode.) (defun ada_reset_file ( filenum file mode) (cond ((or (eq file *ada_default_original_input*) (eq file *ada_default_input*) (eq file *ada_default_original_output*) (eq file *ada_default_output*)) (ada_raise '|status_error| "Attempt to close standard stream.")) ((and file (eq (get_status file) 'open)) (let ((cur_mode (get_mode file)) (cur_name (get_name file))) (ada_close_file file) (ct_if (not mode) (setq mode cur_mode)) (setq file (car (ada_open_file file mode cur_name ""))))) (t (ada_raise '|status_error| "File is not open."))) (setq **text_file_list** (replace_nth filenum file **text_file_list** ))) ; ada_file_mode (FUNCTION) returns the current mode of the given file. ; status_error is raised if the file is not open. (returns 'input or 'output) (defun ada_file_mode (file) (ct_if (and file (eq (get_status file) 'open)) (get_mode file) (ada_raise '|status_error| "File is not open."))) ; ada_file_name (FUNCTION) returns the name of the open file. status_error ; is raised if the file is not open. (defun ada_file_name (file) (ct_if (and file (eq (get_status file) 'open)) (get_name file) (ada_raise '|status_error| "File is not open."))) ; ada_file_form (FUNCTION) returns as a string the form of the file. Right ; now, form is undefined. (defun ada_file_form (file) (ct_if file "" (ada_raise '|status_error| "No file object."))) ; ada_file_is_open (FUNCTION) returns a boolean indicating whether or not ; the file is open. (defun ada_file_is_open (file) (ct_if file (eq (get_status file) 'open) nil)) ; ada_set_default_input sets the current default input file to FILE. (defun ada_set_default_input (file) (cond ((not file) (ada_raise '|status_error| "Not a valid file object.")) ((not (eq (get_status file) 'open)) (ada_raise '|status_error| "Supplied file is not open.")) ((not (eq (ct_typep file) 'ada_input_stream)) (ada_raise '|mode_error| "File sould be a in_file"))) file) ; ada_set_default_output sets the current default output file to FILE. (defun ada_set_default_output (file) (cond ((not file) (ada_raise '|status_error| "Must supply a file.")) ((not (eq (get_status file) 'open)) (ada_raise '|status_error| "File must be open.")) ((not (eq (ct_typep file) 'ada_output_stream)) (ada_raise '|mode_error| "File sould be a out_file"))) file) ; ada_standard_input (FUNCTION) returns the file provided at the beginning of ; program execution as a default input file. (defun ada_standard_input () *ada_default_original_output*) ; ada_standard_output (FUNCTION) returns the file provided at the beginning ; of program execution as a default output file. (defun ada_standard_output () *ada_default_original_output*) ; ada_current_input (FUNCTION) returns the current default input file. (defun ada_current_input () *ada_default_input*) ; ada_current_output (FUNCTION) returns the current default output file. (defun ada_current_output () *ada_default_output*) ; **************************************************************** ; Dealing with lines and pages. ; **************************************************************** ; ada_set_line_length sets the maximum line length of an open file. The ; file parameter is optional, and defaults to the default output file. ; MODE_ERROR is raised if the mode is not OUT_FILE. USE_ERROR is raised if ; the line length is not appropriate. A line length of 0 indicates an ; unbounded line length. (defun ada_set_line_length (length file) (ct_if (not file) (setq file *ada_default_output*)) (cond ((not (eq (get_mode file) 'output)) (ada_raise '|mode_error| "File must be open for output.")) ((< length 0) (ada_raise '|use_error| "Line length shoule be positive")) (t (set-iv ada_output_stream file 'max_column length))) ;;;(ct_send file 'set-max_column length) (list length file)) ; ada_set_page_length is similar to ada_set_line_length. (defun ada_set_page_length (length file) (ct_if (not file) (setq file *ada_default_output*)) (cond ((not (eq (get_mode file) 'output)) (ada_raise '|mode_error| "File must be open for output.")) ((< length 0) (ada_raise '|constraint_error| "page length shoule be positive")) (t (set-iv ada_output_stream file 'max_line length))) ;;;(ct_send file 'set-max_line length) (list length file)) ; ada_line_length (FUNCTION) returns the maximum line length for the ; specified file, which defaults to the default output file. Raises ; MODE_ERROR if the mode is not OUT_FILE. (defun ada_line_length (file) (ct_if (not file) (setq file *ada_default_output*)) (cond ((not (eq (get_mode file) 'output)) (ada_raise '|mode_error| "File must be open for output."))) (get-iv ada_output_stream file 'max_column)) ;;;;(ct_send file 'max_column) ; ada_page_length is similar to ada_line_length (defun ada_page_length (file) (ct_if (not file) (setq file *ada_default_output*)) (cond ((not (eq (get_mode file) 'output)) (ada_raise '|mode_error| "File must be open for output."))) (get-iv ada_output_stream file 'max_line)) ;;;;(ct_send file 'max_line) ; ada_new_line outputs an EOL, possibly N times. N defaults to 1. The ; output file defaults to the default output file. Works on OUT_FILEs only. (defun ada_new_line (file n) (ct_if (not n) (setq n 1)) (ct_if (not file) (setq file *ada_default_output*)) (ct_if (not (eq (get_mode file) 'output)) (ada_raise '|mode_error| "File must be open for output")) (ct_send file 'flush_line_buf) (ct_if (greaterp n 0) (ct_dotimes n (ct_send file 'print_char *ada_eol*)) (ada_raise '|constraint_error| "Spacing number should be positive")) (list file n)) ; ada_skip_line "Reads and discards all characters until a line terminator ; has been read, and then sets the current column number to one. If the ; line terminator is not immediately followed by a page terminator, the ; current line number is incremented. Otherwise, if the line terminator is ; immediately followed by a page terminator, then the page terminator is ; skipped, the current page number is incremented by one, and the current ; line number is set to one." If the spacing N is greater than one, the ; above is done N times. Works on IN_FILEs only. (defun ada_skip_line (spacing file) (ct_if (not file) (setq file *ada_default_input*)) (ct_if (not spacing) (setq spacing 1)) (ct_if (eq (get_mode file) 'input) (ct_if (greaterp spacing 0) (ct_send file 'skip_line spacing) (ada_raise '|constraint_error| "Spacing number should be positive")) (ada_raise '|mode_error| "File must be open for input.")) (list spacing file)) ; ada_end_of_line (FUNCTION) returns true if a line terminator or a file ; terminator is next. MODE_ERROR is raised if the mode is not IN_FILE. ; File defaults to the default input file. (defun ada_end_of_line (file) (ct_if (not file) (setq file *ada_default_input*)) (ct_if (eq (get_mode file) 'input) (ct_send file 'end_of_line_p) (ada_raise '|mode_error| "File must be open for input."))) ; ada_new_page. If the current line is not terminated, and likewise if the ; current page is terminated, outputs a line terminator. Then outputs a ; page terminator, which terminates the current page. Adds one to the ; current page number, and sets the column and line numbers to 1. ; MODE_ERROR is raised if the mode is not OUT_FILE. File defaults to the ; current default output file. (defun ada_new_page (file) (ct_if (not file) (setq file *ada_default_output*)) (ct_if (eq (get_mode file) 'output) (progn (ct_send file 'flush_line_buf) (ct_send file 'print_end_of_page)) (ada_raise '|mode_error| "File must be open for output.")) (list file)) ; ada_skip_page. reads and discards all characters and line terminators ; until a page terminator has been read. Then adds one to the current page ; number, and sets the current column and line numbers to one. MODE_ERROR ; is raised if the mode is not IN_FILE. END_ERROR is raised if an attempt ; is made to read the EOF terminator. (defun ada_skip_page (file) (ct_if (not file) (setq file *ada_default_input*)) (ct_if (eq (get_mode file) 'input) (ct_send file 'skip_page 1) (ada_raise '|mode_error| "File must be open for input.")) (list file)) ; ada_end_of_page (FUNCTION) returns TRUE if the combination of a line ; terminator and a page terminator is next, or if a file terminator is next. ; Raises MODE_ERROR if mode is not IN_FILE. (defun ada_end_of_page (file) (ct_if (not file) (setq file *ada_default_input*)) (ct_if (eq (get_mode file) 'input) (ct_send file 'end_of_page_p) (ada_raise '|mode_error| "File must be open for input."))) ; ada_end_of_file (FUNCTION) returns TRUE if a file terminator (EOF) is ; next, or if the combination of a line, page, and file terminator is next. (defun ada_end_of_file (file) (let (ans) (ct_if (not file) (setq file *ada_default_input*)) (ct_if (eq (get_mode file) 'input) (setq ans (ct_send file 'end_of_file_p)) (ada_raise '|mode_error| "File must be open for input.")) #| #+(or 3600 cadr) (let* ((real_stream (ct_send file 'real_stream)) (terminal_style_io (ct_send file 'terminal_style_io)) char) (cond (terminal_style_io (cond ((ct_send real_stream ':listen) (setq char (ct_send real_stream ':tyi)) (ct_if (member char *keyboard_eof*) ans (ct_send real_stream ':untyi char))) (t nil))) )) |# ans)) ; ada_set_col ; FOR OUTPUT FILES: If the value specified by TO is greater than the current ; column number, outputs spaces, adding one to the current column number ; after each space, until the current column number equals the specified ; value. If the value specified by TO is equal to the current column ; number, there is no effect. If the value specified by TO is less than the ; current column number, has the effect of calling NEW_LINE with a spacing ; of one, then outputs TO-1 spaces, and sets the current column number to ; the specified value. Raises LAYOUT_ERROR if TO exceeds LINE_LENGTH. If ; TO is zero, just causes a new_line. ; FOR INPUT FILES: Performs GET operations for characters (which are ; discarded) until the current column number equals the value specified by ; TO. If the current column number already equals the specified calue of ; TO, there is no effect. END_ERROR is raised if an attempt is made to read ; a file terminator. This definition implies that for input files with no ; line terminator, you could read to the end of the file on a simple error. (defun ada_set_col (col file) (ct_if (not file) (setq file *ada_default_output*)) (cond ((eq (get_mode file) 'input) (do () ((= (get-iv ada_input_stream file 'current_column) col)) (ct_send file 'get_char))) ; it will raise end_error if necessary ; discard (t ; otherwise, must be output mode (let ((cur_col (get-iv ada_output_stream file 'current_column)) (splist nil) (line_length (get-iv ada_output_stream file 'max_column))) (cond ((<= col 0) (ada_raise '|constraint_error| "Non-positive column number in SET-COL")) ((greaterp line_length 0) (ct_if (greaterp col line_length) (ada_raise '|layout_error| "Col number exceed the line length")))) (cond ((= cur_col col)) ; if equal, do nothing. ((> cur_col col) ; if greater, (ct_send file 'print_end_of_line) (ct_dotimes (sub1 col) (setq splist (cons *ada_space* splist))) (ct_send file 'print_char_list splist)) (t (ct_dotimes (- col cur_col) (setq splist (cons *ada_space* splist))) (ct_send file 'print_char_list splist)))))) (list col file)) ; ada_set_line ; FOR OUTPUT FILES: If the value specified by TO is greater than the ; current lien number, repeatedly calls NEW_LINE until the current line ; number is equal to the specified value. If TO is equal to the current ; line number, no effect. If TO is less than the current line number, calls ; NEW_PAGE, and then NEW_LINE with spacing TO-1. LAYOUT_ERROR is raised if ; the value specified by TO exceeds the page length maximum. ; FOR INPUT FILES: calls skip_line until the current line number equals the ; specified value of TO. If the current line number already equals the ; specified value of TO, there is no effect. END_ERROR is raised if the ; EOF terminator is read. (defun ada_set_line (line file) (ct_if (not file) (setq file *ada_default_output*)) (let ((page_length (ct_send file 'max_line))) (cond ((lessp line 0) (ada_raise '|constraint_error| "Negative line number in SET-LINE")) ((greaterp page_length 0) (ct_if (greaterp line page_length) (ada_raise '|layout_error| "LINE number exceed the page length"))))) (cond ((eq (get_mode file) 'input) ; if INPUT mode, (do () ; do skiplines for a while. ((= (get-iv ada_input_stream file 'current_line) line)) (ct_send file 'skip_line))) (t ; otherwise, must be OUTPUT (let ((cur_line (get-iv ada_output_stream file 'current_line))) (cond ((= cur_line line)) ; if equal, do nothing. ((> cur_line line) (ct_send file 'print_end_of_page) (ct_dotimes (max 0 (1- line)) (ct_send file 'print_end_of_line))) (t (ct_dotimes (- line cur_line) (ct_send file 'print_end_of_line))))))) (list line file)) ; ada_col (FUNCTION) returns the current column number. If this number ; is bigger than *ada_max_integer*, LAYOUT_ERROR is raised. (defun ada_col (file) (ct_send (or file *ada_default_output*) 'find_current_column)) ; ada_line (FUNCTION) returns the current line number. If this number is ; bigger than *ada_max_integer*, LAYOUT_ERROR is raised. (defun ada_line (file) (ct_send (or file *ada_default_output*) 'find_current_line)) ; ada_page (FUNCTION) returns the current page number. If this number is ; bigger than *ada_max_integer*, LAYOUT_ERROR is raised. (defun ada_page (file) (ct_send (or file *ada_default_output*) 'find_current_page)) ; **************************************************************** ; string and character manipulation ; **************************************************************** ; ada_get_character reads one character from the input file. Any line ; terminators and page terminators are skipped. END_ERROR is raised if an ; attempt is made to read the EOF. (defun ada_get_character (file) (prog (char) (ct_if (not file) (setq file *ada_default_input*)) (ct_if (eq (get_mode file) 'input) (let* ((stdout (ct_nth **standard_output** **text_file_list**)) (goflush (ct_send file 'terminal_style_io))) (ct_if goflush (ct_send stdout 'flush_line_buf)) (setq char (ct_send file 'get_char))) (ada_raise '|mode_error| "File must be open for input.")) (return (list char file)))) ; ada_put_character outputs one character. WIll not exceed the maximum ; line or page lengths. (defun ada_put_character (char file) (ct_if (not file) (setq file *ada_default_output*)) (ct_if (eq (get_mode file) 'output) (ct_if (> (setq char (map_ascii_to_lispm char)) 0) (ct_send file 'print_char char)) (ada_raise '|mode_error| "File must be open for output.")) (list char file)) ; ada_get_string reads a string of N characters, where N is the length of ; the string passed as a parameter. Reads N characters by doing get_char ; operations, thus ignoring line boundaries. Attempting to read past the ; end of file will cause an END_ERROR. (defun ada_get_string (len file) (prog (string) (ct_if (not file) (setq file *ada_default_input*)) (ct_if (eq (get_mode file) 'input) (let* ((stdout (ct_nth **standard_output** **text_file_list**)) (goflush (get-iv ada_input_stream file 'terminal_style_io))) (ct_if goflush (ct_send stdout 'flush_line_buf)) (setq string (ct_send file 'get_string len))) (ada_raise '|mode_error| "File must be open for input.")) (return (list string file)))) ; ADA_PUT_STRing will put_char the characters of the char list. (defun ada_put_string (charl file) (ct_if (not file) (setq file *ada_default_output*)) (ct_if (eq (get_mode file) 'output) (ada_put_string_aux charl file) (ada_raise '|mode_error| "File must be open for output.")) (CT_IF (EQUAL (GET_STATUS FILE) 'CLOSED) (ADA_RAISE '|status_error| "File is closed")) (list charl file)) ;;;the aux function for ada_put_string, check if there is a control char embeded ;;;in the char list, break the char list if necessary (defun ada_put_string_aux (charl file) (do ((ll charl (cdr ll)) (ans nil)) ((null ll) (ct_send file 'print_char_list (nreverse ans))) (ct_if (is_control_char (car ll)) (ct_if (null ans) (progn (ct_send file 'flush_line_buf) (ct_send file 'print_char (car ll))) (progn (ct_send file 'print_char_list (nreverse ans)) (ct_send file 'flush_line_buf) (setq ans nil) (ct_send file 'print_char (car ll)))) (setq ans (cons (car ll) ans))) )) ; **************************************************************** ; Line manipulation ; **************************************************************** ; ada_get_line If at the end of the line, calls SKIP_LINE 1. Then, ; replaces successive characters of the specified string by successive ; characters read from the specified file, stopping when wither the end of ; the string or the end of the line is met. The ADA Ref. Man. says that ; characters in the string that are not replaced are left undefined. This ; procedure will replace those characters with spaces. The LAST parameter ; is an index value specifying the last character replaced, or 0 if no ; characters are read. END_ERROR is raised if EOF is read. (defun ada_get_line (len file last) (prog (chlist) (ct_if (not file) (setq file *ada_default_input*)) (cond ((eq (get_mode file) 'input) (let* ((stdout (ct_nth **standard_output** **text_file_list**)) (goflush (get-iv ada_input_stream file 'terminal_style_io))) (ct_if goflush (ct_send stdout 'flush_line_buf))) (ct_if (ct_send file 'end_of_line_p) (ct_send file 'skip_line 1)) (setq chlist (ct_send file 'get_line len)) (setq last (1- (+ last (length chlist)))) (setq chlist (pad_right_charl chlist len *ada_space*))) (t (ada_raise '|mode_error| "File must be open for input."))) (return (list chlist file last)))) ; ada_put_line Calls put_char_list, then new_line. (defun ada_put_line (charl file) (ct_if (not file) (setq file *ada_default_output*)) (cond ((eq (get_mode file) 'output) (ct_send file 'flush_line_buf) ;(ct_send file 'print_char_list charl) (ada_put_string_aux charl file) (ct_send file 'flush_line_buf) (ct_send file 'print_end_of_line)) (t (ada_raise '|mode_error| "File must be open for output."))) (list charl file)) ; **************************************************************** ; integer input output ; **************************************************************** ; These routines behave differently depending upon the type of integer used. ; ADA expects these to be generic routines, instantiated for each variety. ; To accomplish variations here, the integer routines expect to be supplied ; with a WIDTH parameter for that number type, and a RANGE parameter, which ; specifies the allowed range of values. Numbers read that are outside of ; these values will raise DATA_ERROR. ; ada_get_integer Skips leading blanks, line terms, and page terms. Then ; reads an integer, stopping if a non-meaningful character is read, or if ; (non-zero) width chars are read. Width defaults to zero on input. ; DATA_ERROR is raised for non-syntactic input, or out-of-range numbers. ; RANGE must be specified-- it is a list of two numbers. Width and file are ; both optional. Width defaults to 0, ; which means that reading stops only when a lexical item has been read. ; file defaults to the default input. ; delete number arg. -- no way to pass by reference. ++am+ ; delete the range argument ++AM++ (defun ada_get_integer (width file) (prog (number base ibase) (setq base 10. ibase 10.) (ct_if (not width) (setq width 0)) (ct_if (not file) (setq file *ada_default_input*)) (ct_if (not (eq (get_mode file) 'input)) (ada_raise '|mode_error| "File must be open for input.")) (let* ((stdout (ct_nth **standard_output** **text_file_list**)) (goflush (get-iv ada_input_stream file 'terminal_style_io))) (ct_if goflush (ct_send stdout 'flush_line_buf))) (setq number (ct_send file 'get_integer width)) (setq *io_get_integer* t) (return (list number width file)))) ; ada_put_integer Outputs the value of the supplied integer with NO ; UNDERSCORES, no exponent, and no leading zeros. If the resulting output ; will have less than WIDTH characters, leading spaces make up the ; difference. If a base other than 10 is specified, uses based number ; syntax. File, width, and base may be defaulted. (defun ada_put_integer ( integer file width ebase) (let ((base 10.) (ibase 10.) (*nopoint nil)) (ct_if (not file) (setq file *ada_default_output*)) (ct_if (not (eq (get_mode file) 'output)) (ada_raise '|mode_error| "File must be open for output.")) (ct_send file 'put_integer integer width ebase) (list integer file width ebase))) ;;; These functions do not use file objects. ;;; ada_get_integer_from_string will read an integer from a string instead ;;; of from a file. The caller must provide RANGE and String. A useful number ;;; is returned in number, and the last character index read from the string is ;;; return in last. (defun ada_get_integer_from_string (string last) (let (ans (base 10.) (ibase 10.)) (setq ans (string_fsm *integer_table* string)) (list (car ans) string (+ last (cadr ans))))) ;; (ct_if (<= (first range) (car ans) (second range)) ;; (list (car ans) string (cadr ans)) ;; (ada_raise '|data_error| "Integer out of range from string.")))) ;;; ada_put_integer_to_string will place the integer, right justified, in the ;;; string, unless the string is too short, in which case LAYOUT_ERROR will ;;; be raised. ;;; This version works by binding base, which fails in franzlisp. #+lispm (defun ada_put_integer_to_string (integer len ebase) (let (list basen (width len) (base 10.) (ibase 10.) (*nopoint t)) (cond ((= ebase 10.) (setq list (exploden integer))) (t (setq basen (exploden ebase) list (fix_hex_chars (append (butlast basen) '(35) (let ((base ebase)) (exploden integer)) '(35)))))) (list integer (implode (cond ((< (length list) width) (append (firstn (- width (length list)) (circular-list *ada_space*)) list)) ((> (length list) width) (ada_raise '|layout_error| "Integer too big to fit in string.")) (t list))) ebase))) #+franz (defun ada_put_integer_to_string (integer len ebase) (let (list (neg nil) (width len) (base 10.) (ibase 10.)) (ct_if (< integer 0) (setq integer (- integer) neg t)) (setq list (do ((num integer) (rems (ct_if (not (= ebase 10)) (list #/#) nil))) ((< num ebase) (fix_hex_chars (cons (+ #/0 num) rems))) (setq rems (cons (+ #/0 (mod num ebase)) rems) num (*quo num ebase)))) (ct_if neg (setq list (cons #/- list))) (ct_if (not (= ebase 10)) (setq list (append (exploden ebase) (list #/#) list))) (maknam (ct_if (< (length list) width) (append (firstn (- width (length list)) (circular-list *ada_space*)) list) list)))) ; **************************************************************** ; input-output for reals ; **************************************************************** ; ada_get_real. Skips leading blanks, lineterms, and page terms. Reads a ; real number, stopping if a (non-zero) width has happened, or if a ; non-meaningful character is read. DATA_ERROR is raised if the sequence ; read is not a real, or if the value returned is not of the right type. ; The number may be based. Width defaults to 0; file defaults to the ; default input. ; delete the restriction argument . ++AM++ (defun ada_get_real (number width file) (let ((base 10.) (ibase 10.)) (ct_if (lessp width 0) (ada_raise '|constraint_error| "Negative width parm")) (ct_if (not file) (setq file *ada_default_input*)) (ct_if (not (eq (get_mode file) 'input)) (ada_raise '|mode_error| "File must be open for input.")) (let* ((stdout (ct_nth **standard_output** **text_file_list**)) (goflush (get-iv ada_input_stream file 'terminal_style_io))) (ct_if goflush (ct_send stdout 'flush_line_buf))) (setq number (ct_send file 'get_real width)) (setq *io_get_float* t) (list number width file))) ; ada_put_real. Outputs the value of the ITEM parameter as a decimal ; number, using FORE, AFT, and EXP widths for formatting. Read ARM, 14.3.8 ; for full details. (defun ada_put_real (number file fore aft exp) (let ((base 10.) (ibase 10.)) (ct_if (not file) (setq file *ada_default_output*)) (ct_if (not (eq (get_mode file) 'output)) (ada_raise '|mode_error| "File must be open for output.")) (ct_send file 'put_real number fore aft exp) (list number file fore aft exp))) ;;; Gets a real number from a string. (defun ada_get_real_from_string (string last) (let (ans (base 10.) (ibase 10.)) (setq ans (string_fsm *real_table* string)) (list (car ans) string (+ last (cadr ans))))) ;; (ct_if (<= (first restriction) (car ans) (second restriction)) ;; (list (car ans) string (cadr ans)) ;; (ada_raise '|data_error| "Real out of range from string.")))) ;;; Puts a real number in a string, right justified. (defun ada_put_real_to_string (number len aft exp) (let ((fore (ct_if (zerop exp) (- len aft 1) (- len aft exp 2))) (string nil) (base 10.) (ibase 10.) (*nopoint t)) (setq string (ct_if (zerop exp) (real_charl_sans_exp number fore aft) (real_charl number fore aft exp))) (ct_if (> (length string) len) (ada_raise '|layout_error| "Real number is too long for string.")) (list number (apply 'ct_string_append string) ;;(ct_format nil "~A" (implode string)) aft exp))) ; **************************************************************** ; input-output for enumerated types ; **************************************************************** ; ada_get_enum AFter skipping leading blanks, EOLs, and EOPs, reads an ; identifier according to the syntax of this lexical element. (Lower and ; upper case are considered identical.) Raises DATA_ERROR if the sequence ; does not have the required syntax or if the identifier is not of the right ; type. (defun ada_get_enum (values item file) (ct_if (not file) (setq file *ada_default_input*)) (ct_if (not (eq (get_mode file) 'input)) (ada_raise '|mode_error| "File must be open for input.")) (let* ((stdout (ct_nth **standard_output** **text_file_list**)) (goflush (get-iv ada_input_stream file 'terminal_style_io))) (ct_if goflush (ct_send stdout 'flush_line_buf))) (setq item (ct_send file 'get_enum values)) (setq *io_get_enum* t) (list item file)) ; ada_put_enum. Outputs the item. If LC is specified TRUE, the item is ; printed in all lower case. If a width is specified, then spaces are used ; to fill on the right. (defun ada_put_enum (default_width item file width lc) (ct_if (not file) (setq file *ada_default_output*)) (ct_if (not (eq (get_mode file) 'output)) (ada_raise '|mode_error| "File must be open for output.")) (ct_if (lessp width 0) (ada_raise '|constraint_error| "Negative width parm")) (ct_if (eq 0 width) (setq width default_width)) (ct_send file 'put_enum item width lc)) (defun ada_get_enum_from_string (values str last) (ct_if (equal str "") (ada_raise '|end_error| "Null string been given") (prog (string index len ch ans) (setq string "" index -1 len (ct_string_length str)) loop1 (setq index (1+ index) ch (ct_nth_char str index)) (ct_if (= index (1- len)) (ada_raise '|data_error| "No item found; all spaces.")) (ct_if (eq ch *ada_space*) (go loop1)) loop2 (setq string (ct_string_append string ch)) (setq index (1+ index) ch (ct_nth_char str index)) (ct_if (and (memq ch *item_chars*) (< index (1- len))) (go loop2)) (ct_if (= index (1- len)) (setq string (ct_string_append string ch))) (setq ans (list (implode (exploden (ct_string_downcase string))) (+ last index))) (ct_if (memq (car ans) values) (return ans) (ada_raise '|data_error| "Item not in data range."))))) (defun ada_put_enum_to_string (tolen str lc) (let ((len (ct_string_length str))) (ct_if lc (setq str (ct_string_downcase str)) (setq str (ct_string_upcase str))) (ct_if (> len tolen) (ada_raise '|layout_error| "Enumerated item too long for string.")) (list str (pad_right_str str tolen *ada_space*) lc)))