% File : FILES.PL % Author : Lawrence Byrd + Richard A. O'Keefe % Updated: 21 August 1984 % Purpose: Routines for playing with files. % Converted for NIP Ken Johnson 23-6-87 % NIP does not support opening files in Append mode % Check to see if a file exists and produce % an error message if it doesn't. check_exists(File) :- file_exists(File), !. check_exists(File) :- message_to_user(['! File ', File, ' cannot be opened for input.']), !, fail. % Succeed if a file exists, otherwise fail file_exists(File) :- atom(File), seeing(OldSee), ( nofileerrors, see(File), !, fileerrors, seen, see(OldSee) ; fileerrors, fail ). % Open a file, checking that it exists open(File) :- check_exists(File), see(File). % Open a file and return current file % This is seeing/2 in C Prolog. open(Old, File) :- seeing(Old), open(File). % Close file and see old file again close(File, Old) :- close(File), see(Old). % This looks unlikely but it works delete(File) :- rename(File, []). /* append(File) is supposed to open the file in "append" mode, that is for output, with the new output going at the end of the old contents instead of replacing them entirely as tell/1 would. However, Bottoms-10 does not provide this facility the way UNIX does, so the simplest way of implementing the operation is to rename the old file File.EXT to File.BAK, to copy the contents of File.BAK into a new version of File.EXT, and to leave this new file open. As far as Prolog is concerned, you can use this predicate exactly as you use append/1 in C Prolog, that is, you can use it to open the file instead of tell and thereafter use tell to switch to it. (The other pattern which C Prolog permits, which is using append/1 all the time instead of tell/1, will NOT work.) However, as far as the operating system is concernd they are not equivalent, as the File.BAK will be left lying around which we don't really want, and in some cases involving path names Bottoms-10 won't get the rename right. Also, any existing File.BAK will be deleted. */ append(File) :- seeing(Old), see(File), name(File, Chars), ( append(Prefix, [0'.|Suffix], Chars) ; Prefix = Chars ), !, append(Prefix, ".BAK", BackupChars), name(Backup, BackupChars), nofileerrors, ( see(Backup), rename(Backup, []) ; true % Delete the backup file ),fileerrors, see(File), rename(File, Backup), see(Backup), tell(File), repeat,get0(Ch), ( Ch = 26 ; put(Ch), fail ), !, seen, see(Old). % File : /usr/lib/prolog/open % Author : R. A. O'Keefe % Updated: 17 October 1984 % Purpose: open files with error messages and failure. /* The problem with nofileerrors mode is that when a see or tell or whatever fails, it does so quietly, without an intimation that this has happened. The trouble with fileerrors mode is that if see or tell fails, it aborts, and the program cannot recover. Dec-10 Prolog I/O, which C Prolog copies with only minor changes, is generally admitted to be an unsatisfactory makeshift. It has not been improved because the feeling is that it needs to be replaced (revolution not evolution) and in the mean-time one can actually program around most of its problems. You have to be subtle, though. This file defines three commands: open_file(File, Mode, Action) tries to open File in (read, write) Mode. If it can't, it will print an error message, and call Action. The error message will always go to the terminal. open_file(File, Mode) is shorthand for open(File, Mode, fail) open_file(File) is shorthand for open(File, read, fail) */ open_file(File) :- open_file(File, read, fail). open_file(File, Mode) :- open_file(File, Mode, fail). open_file(File, _, Action) :- \+ atom(File), !, message_to_user(['! Bad file name ', File, ' in call to open_file.' ]), call(Action). open_file(_, Mode, Action) :- \+ (atom(Mode), (Mode == read ; Mode == write)), !, message_to_user(['! Bad mode ', Mode, ' in call to open_file.']), call(Action). open_file(File, Mode, Action) :- nofileerrors, ( open_file_1(Mode, File), !, fileerrors ; fileerrors, message_to_user(['! Can''t open file', File, ' in ', Mode, ' mode.']), call(Action) ). open_file_1(read, File) :- see(File). open_file_1(write, File) :- tell(File). message_to_user(Stuff) :- telling(Where), tell(user), message_to_user_1(Stuff), told, tell(Where). message_to_user_1([]) :- nl, !. message_to_user_1([H|T]) :- write(H), message_to_user_1(T).