## winix-text-file-for-os--premicrothread.api
#
# Here we define the API for our platform-specific
# file I/O support. The API is cross-platform, the
# implementations are platform-specific.
# Compiled by:
#
src/lib/std/src/standard-core.sublib# Compare with:
#
src/lib/std/src/winix/winix-file.apistipulate
package ns = number_string; # number_string is from
src/lib/std/src/number-string.pkgherein
# This api is implemented in:
#
#
src/lib/std/src/posix/file--premicrothread.pkg #
api Winix_Text_File_For_Os__Premicrothread {
#
Vector = String;
Element = Char;
# XXX BUGGO FIXME
# (?) Should maybe implement vanilla/conventional/expected
# io_stream = fopen ("foo.txt", "r");
# io_stream = fopen ("foo.txt", "w");
# io_stream = fopen ("foo.txt", "a");
# Then we can handle binary files as
# io_stream = fopen ("foo.txt", "rb");
# per standard practice. This will also let us
# support read+write mode to a file, which the
# existing model here really cannot support
# gracefully.
#
# To make this work, we'll probably need a
# Io_Stream = INPUT_STREAM Input_Streamn
#
| OUTPUT_STREAM Output_Stream;
# type, at least transitionally. Then we
# can have an fclose() that closes input
# and output streams without caring about
# the difference.
#
# (We can retain the current calls for the
# benefit of those who need/want the type
# safety of having Input_Stream and
# Output_Stream type-distinct.)
#
#
#
# LATER: Better is most likely a phantom type
# along the lines of
#
# Stream (Can_Read, Can_Write, Can_Seek)
#
# so that read* can support both read/write and read/only streams, *tc.
# This way we can have an option to open in read/write mode
# without having to have a complete new set of read functions,
#
# E.g., read* could accept a stream of type Stream(Can_Read, X, Y),
# write* could accept a stream of type Stream(X, Can_Write, Y),
# seek* could accept a stream of type Stream(X, Y, Can_Seek),
#
# We can then have open_for_read: String -> Stream( Can_Read, Cannot_Write, Can_Seek),
# open_for_write: String -> Stream(Cannot_Read, Can_Write, Can_Seek),
# open_for_update: String -> Stream( Can_Read, Can_Write, Can_Seek),
# whilst still preserving enough typesafety to catch at compiletime
# attempts to write to a read-only file etc.
# This does mean that we can't have fopen("foo.txt", "r") etc,
# since the Mythryl return type cannot vary according to argument value. Owell.
#
# STILL LATER: Michele Bini was getting unpleasant type errors when using
# phantom-typed sockets at scripting top level where type
# generalization is not (and cannot be) done; maybe using
# phantom types here is not such a cool idea after all.
#
# Hrm...
Input_Stream;
Output_Stream;
read: Input_Stream -> Vector;
read_one: Input_Stream -> Null_Or( Element );
read_n: (Input_Stream, Int) -> Vector;
read_all: Input_Stream -> Vector;
peek: Input_Stream -> Null_Or( Element ); # Return next element in stream (if any) without actually advancing the file pointer.
close_input: Input_Stream -> Void;
end_of_stream: Input_Stream -> Bool;
write: (Output_Stream, Vector) -> Void;
write_one: (Output_Stream, Element) -> Void;
flush: Output_Stream -> Void;
close_output: Output_Stream -> Void;
package pur # "pur" == "pure" (I/O).
:
Winix_Pure_Text_File_For_Os__Premicrothread # Winix_Pure_Text_File_For_Os__Premicrothread is from
src/lib/std/src/io/winix-pure-text-file-for-os--premicrothread.api where Vector == String
also Element == Char;
make_instream: pur::Input_Stream -> Input_Stream;
get_instream: Input_Stream -> pur::Input_Stream;
set_instream: (Input_Stream, pur::Input_Stream) -> Void;
get_output_position: Output_Stream -> pur::Out_Position;
set_output_position: (Output_Stream, pur::Out_Position) -> Void;
make_outstream: pur::Output_Stream -> Output_Stream;
get_outstream: Output_Stream -> pur::Output_Stream;
set_outstream: (Output_Stream, pur::Output_Stream) -> Void;
read_line: Input_Stream -> Null_Or( String );
read_lines: Input_Stream -> List( String );
as_lines: String -> List( String );
write_substring: (Output_Stream, Substring) -> Void;
from_lines: String -> List(String) -> Void; # filename -> file_lines -> ().
exists: String -> Bool; # Returns TRUE iff 'stat' succeeds on the given filepath.
open_for_read: String -> Input_Stream;
open_string: String -> Input_Stream;
open_for_write: String -> Output_Stream;
open_for_append: String -> Output_Stream;
stdin: Input_Stream;
stdout: Output_Stream;
stderr: Output_Stream;
print: String -> Void;
scan_stream :
( ns::Reader (Element, pur::Input_Stream)
->
ns::Reader (X, pur::Input_Stream)
)
->
Input_Stream
->
Null_Or(X);
say: (Void -> String) -> Void;
note: (Void -> String) -> Void; # These three log to disk (typically).
warn: (Void -> String) -> Void;
fatal: String -> X; # Never returns.
note_in_ramlog: (Void -> String) -> Void; # 'String' should contain no newlines or nuls.
# Ramlog is circular; most recent entries can be viewed in gdb via debug_ramlog(<linecount>).
# Stuff from
src/lib/src/lib/thread-kit/src/lib/logger.api exception NO_SUCH_LOGTREE_NODE;
#
Logtree_Node
=
LOGTREE_NODE
{
parent: Null_Or (Logtree_Node), # NULL only on root node of tree.
name: String,
#
logging: Ref( Bool ),
children: Ref( List( Logtree_Node ) )
};
# Where log output goes:
#
Log_To
#
= LOG_TO_STDOUT
| LOG_TO_STDERR
| LOG_TO_NULL
| LOG_TO_FILE String
| LOG_TO_STREAM Output_Stream
;
logger_cleanup: Ref( Void -> Void );
set_logger_to: Log_To -> Void;
#
# Set log output destination.
#
# LOG_TO_STREAM can only be specified
# as a destination if threadkit is running.
#
# NOTE: This call does NOT close the previous
# output stream, if any, since the caller
# may not want that. If you want the
# previous log stream closed, do it
# yourself (see next).
logger_is_set_to: Void -> Log_To;
#
# Mainly so caller can do
#
# logging_to = logger_is_set_to ();
#
# set_logger_to LOG_TO_STDERR;
#
# case logging_to
# #
# LOG_TO_STREAM stream => file::close_output stream;
# _ => ();
# esac;
#
# to close the logstream cleanly.
#
# NOTE: It is a poor idea to close the current
# logstream before switching logging to
# another stream, since there may be threads
# logging at unexpected moments!
all_logging: Logtree_Node;
#
# Root node of the logtree. Doing
# enable all_logging;
# will enable all registered log_if calls.
standardlib_logging: Logtree_Node;
compiler_logging: Logtree_Node;
make_logtree_leaf
:
{ parent: Logtree_Node,
name: String,
default: Bool
}
->
Logtree_Node;
name_of_logtree_node: Logtree_Node -> String;
#
# Return node name.
parent_of_logtree_node: Logtree_Node -> Null_Or( Logtree_Node ); # NULL only for root node.
#
# Return node parent.
enable: Logtree_Node -> Void;
#
# Turn on all logging controlled by given subtree
# of all_logging.
disable: Logtree_Node -> Void;
#
# Turn off all logging controlled by given subtree
# of all_logging.
enable_node: Logtree_Node -> Void;
#
# Turn on logging controlled by given logtree node
# (i.e., ignoring any children of that node).
am_logging: Logtree_Node -> Bool;
#
# Return TRUE if this node is being logged.
subtree_nodes_and_log_flags: Logtree_Node -> List( (Logtree_Node, Bool) );
#
# Return a list of the registered logtree nodes
# in subtree rooted at given node, along with logging
# status (TRUE/FALSE) of each node.
ancestors_of_logtree_node: Logtree_Node -> List(String);
#
# Return names of all ancestors of node.
#
# First element of list (if nonempty)
# will always be the root node, all_logging.
#
# This is the list of logtree nodes which
# may be used to 'disable' a given log
# message.
find_logtree_node_by_name: String -> Logtree_Node;
#
# Search logtree for a node with given name.
# Raise exception NO_SUCH_LOGTREE_NODE if not found.
print_logtree: Void -> Void;
#
# As an interactive convenience,
# print complete logtree indented:
#
# linux% my
# eval: make "src/lib/x-kit/x-kit.lib";
# eval: logger::print_logtree logger::all_logging;
# FALSE logger::all_logging
# FALSE xlogger::xkit_logging
# FALSE xlogger::widgets_logging
# FALSE xlogger::lib_logging
# FALSE xlogger::selection_logging
# FALSE xlogger::graphics_context_logging
# FALSE xlogger::toplevel_logging
# FALSE xlogger::winreg_logging
# FALSE xlogger::dm_logging
# FALSE xlogger::draw_logging
# FALSE xlogger::color_logging
# FALSE xlogger::font_logging
# FALSE xlogger::io_logging
# FALSE xlogger::make_thread_logging
# TRUE xlogger::error_logging
# TRUE thread_deathwatch::tracing
logprint: String -> Void;
#
# This is not intended for end-user use,
# but rather for
src/lib/src/lib/thread-kit/src/lib/logger.pkg log_if: Logtree_Node -> Int -> (Void -> String) -> Void;
#
# Conditionally generate logging output. Int is severity: 0==note 5==warn 9==fatal.
current_thread_info__hook: Ref(Null_Or( Void -> (Int, String, Int) ));
#
# Horrible internal kludge -- please ignore and forgive! :-)
# (Needed to log thread id; provided by threadkit once it boots.)
};
end;
## COPYRIGHT (c) 1995 AT&T Bell Laboratories.
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.