I'd like to contribute the two attached files to the gnu-apl project.
Quad_FIO.tc includes test cases for FIO∆pipeto and FIO∆pipefrom, while
FILE_IO.apl has a revised version of FIO∆pipeto discovered during testing.
Bill Daly
#!/usr/local/bin/apl --script --
⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
⍝
⍝ ⎕FIO.apl 2014-07-29 15:40:42 (GMT+2)
⍝
⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝⍝
⍝ Copyright (C) 2008-2019 Dr. Jürgen Sauermann
⍝ Copyright (C) 2017 Christian Robert
⍝ Copyright (C) 2020 Bill Daly
⍝ This library contains APL wrapper functions the system function ⎕FIO
⍝
⍝ The purpose is to give functions for file I/O meaningful names instead
⍝ of difficult-to-remember numbers. The function name is normally the name
⍝ of the C-function that is called by the native function.
⍝
⍝ Legend: d - table of dirent structs
⍝ e - error code
⍝ i - integer
⍝ h - file handle (integer)
⍝ n - names (nested vector of strings)
⍝ s - string
⍝ A1, A2, ... nested vector with elements A1, A2, ...
∇Zi ← FIO∆errno
⍝⍝ errno (of last call)
Zi ← ⎕FIO[1] ''
∇
∇Zs ← FIO∆strerror Be
⍝⍝ strerror(Be)
Zs ← ⎕FIO[2] Be
∇
∇Zh ← As FIO∆fopen Bs
⍝⍝ fopen(Bs, As) filename Bs
Zh ← As ⎕FIO[3] Bs
∇
∇Zh ← FIO∆fopen_ro Bs
⍝⍝ fopen(Bs, "r") filename Bs
Zh ← ⎕FIO[3] Bs
∇
∇Ze ← FIO∆fclose Bh
⍝⍝ fclose(Bh)
Ze ← ⎕FIO[4] Bh
∇
∇Ze ← FIO∆file_errno Bh
⍝⍝ errno (of last call on Bh)
Ze ← ⎕FIO[5] Bh
∇
∇Zi ← Ai FIO∆fread Bh
⍝⍝ fread(Zi, 1, Ai, Bh) 1 byte per Zi
⍝⍝ read (at most) 5000 items if Ai is not defined
→(0≠⎕NC 'Ai')/↑⎕LC+1 ◊ Ai←5000
Zi ← Ai ⎕FIO[ 6] Bh
∇
∇Zi ← Ai FIO∆fwrite Bh
⍝⍝ fwrite(Ai, 1, ⍴Ai, Bh) 1 byte per Ai
Zi ← Ai ⎕FIO[7] Bh
∇
∇Zi ← Ai FIO∆fgets Bh
⍝⍝ fgets(Zi, Ai, Bh) 1 byte per Zi
⍝⍝ read (at most) 5000 items unless Ai is defined
→(0≠⎕NC 'Ai')/↑⎕LC+1 ◊ Ai←5000
Zi ← Ai ⎕FIO[8] Bh
∇
∇Zi ← FIO∆fgetc Bh
⍝⍝ fgetc(Zi, Bh) 1 byte per Zi
Zi ← ⎕FIO[9] Bh
∇
∇Zi ← FIO∆feof Bh
⍝⍝ feof(Bh)
Zi ← ⎕FIO[10] Bh
∇
∇Zi ← FIO∆ferror Bh
⍝⍝ ferror(Bh)
Zi ← ⎕FIO[11] Bh
∇
∇Zi ← FIO∆ftell Bh
⍝⍝ ftell(Bh)
Zi ← ⎕FIO[12] Bh
∇
∇Zi ← Ai FIO∆fseek_cur Bh
⍝⍝ fseek(Bh, Ai, SEEK_SET)
Zi ← Ai ⎕FIO[13] Bh
∇
∇Zi ← Ai FIO∆fseek_set Bh
⍝⍝ fseek(Bh, Ai, SEEK_CUR)
Zi ← Ai ⎕FIO[14] Bh
∇
∇Zi ← Ai FIO∆fseek_end Bh
⍝⍝ fseek(Bh, Ai, SEEK_END)
Zi ← Ai ⎕FIO[15] Bh
∇
∇Zi ← FIO∆fflush Bh
⍝⍝ fflush(Bh)
Zi ← ⎕FIO[16] Bh
∇
∇Zi ← FIO∆fsync Bh
⍝⍝ fsync(Bh)
Zi ← ⎕FIO[17] Bh
∇
∇Zi ← FIO∆fstat Bh
⍝⍝ fstat(Bh)
Zi ← ⎕FIO[18] Bh
∇
∇Zi ← FIO∆unlink Bh
⍝⍝ unlink(Bc)
Zi ← ⎕FIO[19] Bh
∇
∇Zi ← FIO∆mkdir_777 Bh
⍝⍝ mkdir(Bc, 0777)
Zi ← ⎕FIO[20] Bh
∇
∇Zi ← Ai FIO∆mkdir Bh
⍝⍝ mkdir(Bc, Ai)
Zi ← Ai ⎕FIO[20] Bh
∇
∇Zi ← FIO∆rmdir Bh
⍝⍝ rmdir(Bc)
Zi ← ⎕FIO[21] Bh
∇
∇Zi ← FIO∆printf B
⍝⍝ printf(B1, B2...) format B1
Zi ← B ⎕FIO[22] 1
∇
∇Zi ← FIO∆fprintf_stderr B
⍝⍝ fprintf(stderr, B1, B2...) format B1
Zi ← B ⎕FIO[22] 2
∇
∇Zi ← Ah FIO∆fprintf B
⍝⍝ fprintf(Ah, Bf, B2...) format Bf
Zi ← B ⎕FIO[22] Ah
∇
∇Zi ← Ac FIO∆fwrite_utf8 Bh
⍝⍝ fwrite(Ac, 1, ⍴Ac, Bh) Unicode Ac Output UTF-8
Zi ← Ac ⎕FIO[23] Bh
∇
∇Zh ← As FIO∆popen Bs
⍝⍝ popen(Bs, As) command Bs mode As
Zh ← As ⎕FIO[24] Bs
∇
∇Zh ← FIO∆popen_ro Bs
⍝⍝ popen(Bs, "r") command Bs
Zh ← ⎕FIO[24] Bs
∇
∇Ze ← FIO∆pclose Bh
⍝⍝ pclose(Bh)
Ze ← ⎕FIO[25] Bh
∇
∇Ze←txt FIO∆pipeto cmd;ph
⍝⍝ Function pipes txt to shell command cmd
ph←'w' FIO∆popen cmd
Z1←(⎕ucs txt) FIO∆fwrite ph
Ze←FIO∆pclose ph
→(Z1≥0)/0
Ze←Z1
∇
∇txt←FIO∆pipefrom cmd;ph;Ze
⍝⍝ Function to pipe text from a shell command. Generally the function
⍝⍝ returns the stdout of the command. If error occur it returns an
⍝⍝ integer FIO∆strerror will give a hint of what went wrong.
ph←'r' ⎕FIO[24] cmd
txt←⍬
st: →(0=⍴sink←5000 ⎕fio[41] ph)/end
txt←txt,sink
→st
end: txt←⎕ucs txt
Ze←⎕fio[25] ph
⍎(0≠Ze)/'txt←Ze'
∇
∇Zs ← FIO∆read_file Bs
⍝⍝ return entire file Bs as byte vector
Zs ← ⎕FIO[26] Bs
∇
∇Zs ← As FIO∆rename Bs
⍝⍝ rename file As to Bs
Zs ← As ⎕FIO[27] Bs
∇
∇Zd ← FIO∆read_directory Bs
⍝⍝ return content of directory Bs
Zd ← ⎕FIO[28] Bs
∇
∇Zn ← FIO∆files_in_directory Bs
⍝⍝ return file names in directory Bs
Zn ← ⎕FIO[29] Bs
∇
∇Zs ← FIO∆getcwd
⍝⍝ getcwd()
Zs ← ⎕FIO 30
∇
∇Zn ← As FIO∆access Bs
⍝⍝ access(As, Bs) As ∈ 'RWXF'
Zn ← As ⎕FIO[31] Bs
∇
∇Zh ← FIO∆socket Bi
⍝⍝ socket(Bi). Bi is domain, type, protocol, e.g.
⍝⍝ Zh ← FIO∆socket 2 1 0 for an IPv4 TCP socket
Zh ← ⎕FIO[32] Bi
∇
∇Zi ← Ai FIO∆bind Bh
⍝⍝ bind(Bh, Ai). Ai is domain, local IPv4-address, local port, e.g.
⍝⍝ 2 (256⊥127 0 0 1) 80 bind Bh binds socket Bh to port 80 on
⍝⍝ localhost 127.0.0.1 (web server)
Zi ← Ai ⎕FIO[33] Bh
∇
∇Zi ← Ai FIO∆listen Bh
⍝⍝ listen(Bh, Ai).
Zi ← Ai ⎕FIO[34] Bh
∇
∇Zh ← FIO∆accept Bh
⍝⍝ accept(Bh).
⍝⍝ Return errno or 4 integers: handle, domain, remote IPv4-address, remote port
Zh ← ⎕FIO[35] Bh
∇
∇Zh ← Aa FIO∆connect Bh
⍝⍝ connect(Bh, Aa). Aa is domain, remote IPv4-address, remote port, e.g.
⍝⍝ 2 (256⊥127 0 0 1) 80 connects to port 80 on localhost 127.0.0.1 (web server)
Zh ← Aa ⎕FIO[36] Bh
∇
∇Zi ← Ai FIO∆recv Bh
⍝⍝ return (at most) Ai bytes from socket Bh
Zi←Ai ⎕FIO[37] Bh
∇
∇Zi ← Ai FIO∆send Bh
⍝⍝ send bytes Ai on socket Bh
Zi←Ai ⎕FIO[38] Bh
∇
∇Zi ← Ai FIO∆send_utf8 Bh
⍝⍝ send Unicode characters Ai on socket Bh
Zi←Ai ⎕FIO[39] Bh
∇
∇Z ← FIO∆select B
⍝⍝ perform select() on handles in B
⍝⍝ B = Br [Bw [Be [Bt]]] is a (nested) vector of 1, 2, 3, or 4 items:
⍝⍝ Bt: timeout in milliseconds
⍝⍝ Be: handles with exceptions
⍝⍝ Bw: handles ready for writing
⍝⍝ Br: handles ready for reading
⍝⍝
⍝⍝ Z = Zc Zr Zw Ze Zt is a (nested) 5-item vector:
⍝⍝ Zc: number of handles in Zr, Zw, and Ze, or -errno
⍝⍝ Zr, Zw, Ze: handles ready for reading, writing, and exceptions respectively
⍝⍝ Zt: timeout remaining
Z←⎕FIO[40] B
∇
∇Zi ← Ai FIO∆read Bh
⍝⍝ read (at most) Ai bytes from file descriptor Bh
Zi←Ai ⎕FIO[41] Bh
∇
∇Zi ← Ai FIO∆write Bh
⍝⍝ write bytes Ai on file descriptor Bh
Zi←Ai ⎕FIO[42] Bh
∇
∇Zi ← Ai FIO∆write_utf8 Bh
⍝⍝ write Unicode characters Ai on file descriptor Bh
Zi←Ai ⎕FIO[43] Bh
∇
∇Za ← FIO∆getsockname Bh
⍝⍝ get socket address (address family, ip address, port)
Zi←⎕FIO[44] Bh
∇
∇Za ← FIO∆getpeername Bh
⍝⍝ get socket address (address family, ip address, port) of peer
Zi←⎕FIO[45] Bh
∇
∇Zi ← Ai FIO∆getsockopt Bh
⍝⍝ get socket option from socket Bh
⍝⍝ Ai is socket-level, option-name
Zi←Ai ⎕FIO[46] Bh
∇
∇Zi ← Ai FIO∆setsockopt Bh
⍝⍝ set socket option from socket Bh
⍝⍝ Ai is socket-level, option-name, option-value
Zi←Ai ⎕FIO[47] Bh
∇
∇Z ← As FIO∆fscanf Bh
⍝⍝ fscanf from a file Bh
⍝⍝ As is the format string
Z←As ⎕FIO[48] Bh
∇
∇Z← FIO∆read_lines Bs
⍝⍝ return Z with Z[i] ← line i of the file named Bs
Z←⎕FIO[49] Bs
∇
∇Z← (LO FIO∆transform_lines) Bs
⍝⍝ return Z with Z[i] ← LO (line i of the file named Bs)
Z←LO ⎕FIO[49] Bs
∇
∇Zi ← FIO∆gettimeofday Bu
⍝⍝ return time of day in unit Bu (1 = seconds, 1000 = ms, or 1000000 = μs)
Zi←⎕FIO[50] Bu
∇
∇Zy4 ← FIO∆mktime By67
⍝⍝ return seconds since Jan 1, 1970 for broken down calender time By67
Zy4←⎕FIO[51] By67
∇
∇Zy9 ← FIO∆localtime Bi
⍝⍝ return broken down calender time Zy9 for Bi seconds since Jan 1, 1970
Zy9←⎕FIO[52] Bi
∇
∇Zy9 ← FIO∆gmtime Bi
⍝⍝ return broken down calender time Zy9 for Bi seconds since Jan 1, 1970
Zy9←⎕FIO[53] Bi
∇
∇Z ← FIO∆chdir Bs
⍝⍝ chdir to string from Bs
Z← ⎕FIO[54] Bs
∇
∇Z ← As FIO∆sscanf Bs
⍝⍝ sscanf from a string Bs
⍝⍝ As is the format string
Z←As ⎕FIO[55] Bs
∇
∇Z ← As FIO∆write_lines Bs
⍝⍝ write the strings in the (nested) As to file Bs. As is expected to be a
⍝⍝ vector of lines. Every line A[n] is expected to be a simple character
⍝⍝ vector. A newline (ASCII 10i aka. LF) is appended to every A[n] before it
⍝⍝ is written to the file As
Z←As ⎕FIO[56] Bs
∇
∇Z ← FIO∆execve Bs
⍝⍝ start program Bs with opening a connection between GNU APL and the new
⍝⍝ program. The return value of FIO∆execve Bs is a handle (a file descriptor)
⍝⍝ that can be used with FIO∆fread and FIO∆fwrite for receiving data from and
⍝⍝ for sending data to the new program. The other end of the communition link
⍝⍝ (in the new program) is file descriptor 3 (STERR + 1). The new program has
⍝⍝ stdin closed (so that the program cannot steal keyboard input) but stdout
⍝⍝ left open. It is possible (although asking for trouble) for the new program
⍝⍝ to write to its stdout or stderr.
⍝⍝
⍝⍝ FIO∆execve is quite similar to FIO∆popen. The difference is that FIO∆popen
⍝⍝ connects to either stdin or to stdout of the new program, but not both,
⍝⍝ while FIO∆execve uses only one file descriptor (3) and the communication
⍝⍝ over that file descriptor is bidirectional.
⍝⍝
⍝⍝ The GNU APL end of the connection is supposed to use FIO∆fread and
⍝⍝ and FIO∆fwrite, but not FIO∆read or FIO∆write (otherwise bad things will
⍝⍝ happen).
⍝⍝
Z←⎕FIO[57] Bs
∇
∇Z ← Af FIO∆sprintf Bs
⍝⍝ sprintf( Af, B1...) format Af and data B1, ...
Z←Af ⎕FIO[58] Bs
∇
∇FIO∆clear_statistics Bi
⍝⍝ clear performance statistics with ID Bi
⊣ ⎕FIO[200] Bi
∇
∇Z ← FIO∆get_statistics Bi
⍝⍝ read performance statistics with ID Bi
⍝⍝ Z[1] statistics type
⍝⍝ Z[2] statistics name
⍝⍝ Z[3 4 5] first pass (or only statistics): count/sum/sun2
⍝⍝ Z[6 7 8] optional subsequent pass statistics: count/sum/sun2
Z ← ⎕FIO[201] Bi
∇
∇Z ← FIO∆get_monadic_threshold Bc
⍝⍝ read the monadic parallel execution threshold for primitive Bc
Z ← ⎕FIO[202] Bc
∇
∇Z ← Ai FIO∆set_monadic_threshold Bc
⍝⍝ set the monadic parallel execution threshold for primitive Bc
Z ← Ai ⎕FIO[202] Bc
∇
∇Z ← FIO∆get_dyadic_threshold Bc
⍝⍝ read the dyadic parallel execution threshold for primitive Bc
Z ← ⎕FIO[203] Bc
∇
∇Z ← Ai FIO∆set_dyadic_threshold Bc
⍝⍝ set the dyadic parallel execution threshold for primitive Bc
Z ← Ai ⎕FIO[203] Bc
∇
⍝ a function allowing the numeric arguments of socket functions to be
⍝ specified as strings. For example, instead of:
⍝
⍝ sock ← FIO∆socket 2 1 6
⍝
⍝ you can write:
⍝
⍝ sock ← FIO∆socket FIO∆SockHelper 'AF_INET' 'SOCK_STREAM' 'IPPROTO_TCP'
⍝
⍝ kindly sent by Christian Robert to [email protected] on April 25, 2015
⍝
∇z←FIO∆SockHelper what;this;t
→((≡what)<2)/Single
z←FIO∆SockHelper ¨ what
→(∧/1=,⊃⍴¨,¨z)/FinalDisclose
⎕ES 'Error: Problem converting at least one of the parameters'
→0
FinalDisclose:
z←,⊃⊃¨z ⍝ Be sure we return a vector of hopefully integers
→0
Single:
⍝
⍝ Most useful socket constants (generated by sockconst in the tools directory)
⍝
t←0 2⍴'' 0
t←t⍪'AF_UNSPEC' 0
t←t⍪'AF_LOCAL' 1
t←t⍪'AF_UNIX' 1
t←t⍪'AF_INET' 2
t←t⍪'AF_SNA' 22
t←t⍪'AF_DECnet' 12
t←t⍪'AF_APPLETALK' 5
t←t⍪'AF_ROUTE' 16
t←t⍪'AF_IPX' 4
t←t⍪'AF_ISDN' 34
t←t⍪'AF_INET6' 10
t←t⍪'AF_BLUETOOTH' 31
t←t⍪'AF_MAX' 41
t←t⍪'PF_INET' 2
t←t⍪'PF_LOCAL' 1
t←t⍪'PF_UNIX' 1
t←t⍪'SOCK_STREAM' 1
t←t⍪'SOCK_DGRAM' 2
t←t⍪'SOCK_RAW' 3
t←t⍪'SOCK_RDM' 4
t←t⍪'SOCK_SEQPACKET' 5
t←t⍪'SOCK_DCCP' 6
t←t⍪'SOCK_PACKET' 10
t←t⍪'SOCK_CLOEXEC' 524288
t←t⍪'SOCK_NONBLOCK' 2048
t←t⍪'IPPROTO_IP' 0
t←t⍪'IPPROTO_ICMP' 1
t←t⍪'IPPROTO_IPIP' 4
t←t⍪'IPPROTO_TCP' 6
t←t⍪'IPPROTO_PUP' 12
t←t⍪'IPPROTO_UDP' 17
t←t⍪'IPPROTO_IDP' 22
t←t⍪'IPPROTO_TP' 29
t←t⍪'IPPROTO_DCCP' 33
t←t⍪'IPPROTO_IPV6' 41
t←t⍪'IPPROTO_ROUTING' 43
t←t⍪'IPPROTO_FRAGMENT' 44
t←t⍪'IPPROTO_RSVP' 46
t←t⍪'IPPROTO_GRE' 47
t←t⍪'IPPROTO_ESP' 50
t←t⍪'IPPROTO_AH' 51
t←t⍪'IPPROTO_ICMPV6' 58
t←t⍪'IPPROTO_NONE' 59
t←t⍪'IPPROTO_DSTOPTS' 60
t←t⍪'IPPROTO_MTP' 92
t←t⍪'IPPROTO_ENCAP' 98
t←t⍪'IPPROTO_PIM' 103
t←t⍪'IPPROTO_COMP' 108
t←t⍪'IPPROTO_SCTP' 132
t←t⍪'IPPROTO_UDPLITE' 136
t←t⍪'IPPROTO_RAW' 255
t←t⍪'SOL_SOCKET' 1
t←t⍪'SO_BINDTODEVICE' 25
t←t⍪'SO_REUSEADDR' 2
t←t⍪'SO_BROADCAST' 6
t←t⍪'INADDR_ANY' 0
⍝
⍝ (end of generated code)
⍝
⍝ Replace thoses I recognize by their value
⍝ leaving the rest as they were
⍝
→(0=↑0⍴what)/NotSpecial ⍝ can't be an IP
→(3≠+/'.'=,what)/NotSpecial ⍝ can't be an IP
this←,what ⍝ an IP address
(('.'=this)/this)←' ' ⍝ DOT to space
z←(4⍴256)⊥⍎this ⍝ change this IP to integer
→0
NotSpecial:
this←⊂what ⍝ enclose the input for dyadic '⍳'
z←(,t[;1]) ⍳ this ⍝ search for recognized constants into 't'
→(z>↑⍴t)/ReturnAsis ⍝ no match
z←t[z;2] ⍝ do the substitution
→0
ReturnAsis: z←what ⍝ return original parameter unchanged
∇
⍝ meta data for this library...
⍝
∇Z←FIO⍙metadata
Z←0 2⍴⍬
Z←Z⍪'Author' 'Jürgen Sauermann'
Z←Z⍪'BugEmail' '[email protected]'
Z←Z⍪'Documentation' ''
Z←Z⍪'Download'
'http://svn.savannah.gnu.org/viewvc/trunk/wslib5/Makefile.in?root=apl'
Z←Z⍪'License' 'LGPL'
Z←Z⍪'Portability' 'L3'
Z←Z⍪'Provides' 'file-io'
Z←Z⍪'Requires' ''
Z←Z⍪'Version' '1.0'
∇
⍝ A function that allows you to specify ⎕FIO functions as strings instead
⍝ of numbers:
⍝
⍝ kindly sent by Christian Robert to [email protected] on Jan. 6, 2017
⍝
∇z←L FIO[X] R;a;x
→(2≠⎕nc 'X')/Noaxis
→(0=↑0⍴X)/Number
a← ('errno' 1) ('strerror' 2) ('fopen' 3) ('fclose' 4)
a←a, ('ferrno' 5) ('fread' 6) ('fwrite' 7) ('fgets' 8)
a←a, ('fgetc' 9) ('feof' 10) ('ferror' 11) ('ftell' 12)
a←a, ('fseek_set' 13) ('fseek_cur' 14) ('fseek_end' 15) ('fflush' 16)
a←a, ('fsync' 17) ('fstat' 18) ('unlink' 19) ('mkdir' 20)
a←a, ('rmdir' 21) ('printf' 22) ('fwrite' 23) ('popen' 24)
a←a, ('pclose' 25) ('readfile' 26) ('rename' 27) ('dir' 28)
a←a, ('ls' 29) ('getcwd' 30) ('access' 31) ('socket' 32)
a←a, ('bind' 33) ('listen' 34) ('accept' 35) ('connect' 36)
a←a, ('recv' 37) ('send' 38) ('usend' 39) ('select' 40)
a←a, ('read' 41) ('write' 42) ('uwrite' 43) ('getsockname' 44)
a←a, ('getpeername' 45) ('getsockopt' 46) ('setsockopt' 47) ('fscanf' 48)
a←a, ('readlines' 49) ('gettimeofday' 50) ('mktime' 51) ('localtime' 52)
a←a, ('gmtime' 53) ('chdir' 54) ('sscanf' 55) ('write_lines' 56)
a←a, ('execve' 57) ('sprintf' 58)
a←a, ('open' 3) ('close' 4) ⍝ And some handy aliases
→(0=↑⍴x←,⊃((⊂X) ≡¨↑¨a)/a)/Nomatch
X←¯1↑x
→(30≠X)/Number ⍝ Not a Special case
R←X ◊ →NoaxisMonadic ⍝ Special case for getpwd, should be called with a
dummy right arg.
⍝
⍝ possible cases ..
⍝
Number: →(2≠⎕nc 'L')/Monadic
Diadic: z← L ⎕FIO[X] R ◊ →0
Monadic: z← ⎕FIO[X] R ◊ →0
Nomatch: "Unknown function: ", X ◊ →0
Noaxis: →(2≠⎕nc 'L')/NoaxisMonadic
NoaxisDiadic: z←L ⎕FIO R ◊ →0
NoaxisMonadic:z← ⎕FIO R ◊ →0
∇
⍝ Quad_FIO.tc
⍝ ----------------------------------
⍝ same as File_IO_1.tc but using FILE_IO.apl library
⍝ This is the recommeded way to use file_io.so
⍝
⍝ This file demonstrates the use of the FILE_IO.apl library
⍝ and checks that the wrapper functions in FILE_IO.apl are working
⍝
⍝⍝⍝
⍝⍝⍝ If this segfaults then re-install GNU APL !!!
⍝⍝⍝
)COPY 5 FILE_IO.apl
DUMPED ³
⍝ fopen this file readonly
⍝
Filename←'testcases/File_IO_1.tc'
⎕←Handle←FIO∆fopen_ro Filename
⁰
⍝ get statistics
⍝
⎕←FIO∆fstat Handle
⁰ ⁰ ⁰ ⁰ ⁰ ⁰ ⁰ ⁰ ⁰ ⁰ ⁰ ⁰ ⁰
⍝ close this file
⍝
⎕←FIO∆fclose Handle
0
⍝ close this file again (which is an error)
⍝
FIO∆fclose Handle
DOMAIN ERROR+
FIO∆fclose[2] Ze←⎕FIO[4]Bh
^ ^
→
⍝ create new file
⍝
Filename← "FILE_IO.test"
⎕←Handle←'w' FIO∆fopen Filename
⁰
FIO∆errno
0
FIO∆strerror FIO∆errno
Success
⍝ write 3 lines
⍝
⎕←(⎕UCS "Hello\n") FIO∆fwrite Handle
6
⎕←(⎕UCS "World\n") FIO∆fwrite Handle
6
⎕←(⎕UCS "Line 3...\n") FIO∆fwrite Handle
10
⍝ close the file
⍝
FIO∆fclose Handle
0
⍝ print the file
⍝
)HOST cat FILE_IO.test
Hello
World
Line 3...
0
⍝ open file again for reading
⍝
⎕←Handle← FIO∆fopen_ro Filename
⁰
⍝ read one line (default max_len)
⍝
Z← FIO∆fgets Handle
⎕UCS Z
Hello
⍝ read another line (max_len 200)
⍝
Z←200 FIO∆fgets Handle
⎕UCS Z
World
⍴Z
6
⍝ end of file ? (no)
⍝
FIO∆feof Handle
0
⍝ read more bytes
⍝
Z←200 FIO∆fread Handle
⍴Z
10
⍝ end of file ? (yes)
⍝
FIO∆feof Handle
1
⍝ get statistics
⍝
⎕←FSTAT←FIO∆fstat Handle ◊ 0 8 8 8 ⊤ FSTAT[3]
⁰ ⁰ ⁰ 1 ⁰ ⁰ 0 22 ⁰ ⁰ ⁰ ⁰ ⁰
64 6 ⁰ ⁰
⍝ close the file
⍝
FIO∆fclose Handle
0
⍝ delete the file
⍝
FIO∆unlink Filename
0
⍝ delete the file again (should fail)
⍝
Error←-FIO∆unlink Filename
FIO∆strerror Error
No such file or directory
⎕FIO['strerror'] Error ⍝ monadic with axis string
No such file or directory
⍝ printf
⍝
)ERASE FORMAT
FORMAT←⊂"⎕everything %d Pi %e String %s\n"
FIO∆printf FORMAT, 42 (○1) 'Hello'
44
⍝ fwrite with UCS in UTF8 out
⍝
Filename← 'FILE_IO.test1'
⎕←Handle←'w' FIO∆fopen Filename
⁰
'HELLO ⍋ ⌽ ⍒ ⍴ ⍵' FIO∆fwrite_utf8 Handle
25
FIO∆fclose Handle ⍝ close file
0
)HOST cat FILE_IO.test1
HELLO ⍋ ⌽ ⍒ ⍴ ⍵
0
⍝ popen "r"
⍝
Command←'ls FILE_IO*'
Handle← FIO∆popen_ro Command
Z←20000 FIO∆fread Handle
⍴Z
⁰
FIO∆pclose Handle ⍝ close command (returning its exit code)
0
⍝ read entire file
⍝
⎕UCS FIO∆read_file 'FILE_IO.test1'
72 69 76 76 79 32 226 141 139 32 226 140 189 32 226 141 146 32 226 141 180 32
226 141 181
⍝ socket communication: send 'Hello' from one socket to another socket
⍝ and send 'World!' back.
⍝
AF_INET ← 2 ⍝ see /usr/include/.../bits/socket.h
SOCK_STREAM ← 1 ⍝ see /usr/include/.../bits/socket_type.h
IPPROTO_IP ← 0 ⍝ see /usr/include/netinet/in.h
LOCALHOST←256⊥127 0 0 1 ⍝ 127.0.0.1 in host byte order
Port ← 22222
Server←AF_INET, LOCALHOST, Port
⍝ socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
⍝
3 ≤ Handle←FIO∆socket AF_INET, SOCK_STREAM, IPPROTO_IP
1
⍝ setsockopt(Handle, SOL_SOCKET, SO_REUSEADDR, 1)
⍝
SOL_SOCKET←1 ⍝ see /usr/include/asm-generic/socket.h
SO_REUSEADDR←2 ⍝ see /usr/include/asm-generic/socket.h
(SOL_SOCKET, SO_REUSEADDR, 1) FIO∆setsockopt Handle
0
⍝ bind(AF_INET, LOCALHOST, Port)
⍝
Server FIO∆bind Handle
0
⍝ listen(10)
⍝
10 FIO∆listen Handle
0
⍝ socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
⍝
4 ≤ Handle1←FIO∆socket AF_INET, SOCK_STREAM, IPPROTO_IP
1
⍝ connect() Handle1 to Handle
⍝
Server FIO∆connect Handle1
0
⍝ accept() returns Handle, remote address
⍝
Handle2 ← ↑ FIO∆accept Handle
⍝ send("Hello")
⍝
'Hello' FIO∆send_utf8 Handle2
5
⍝ recv()
⍝
⎕UCS 200 FIO∆recv Handle1
Hello
⍝ send("World!")
⍝
'World!' FIO∆send_utf8 Handle1
6
⍝ recv()
⍝
⎕UCS 200 FIO∆recv Handle2
World!
⎕←FIO∆fclose Handle2
0
⎕←FIO∆fclose Handle1
0
⎕←FIO∆fclose Handle
0
⍝ fscanf
⍝
Filename← 'FILE_IO.test1'
⎕←Handle←'w' FIO∆fopen Filename
⁰
⍴DATA←'int 22 perc % doub 3.14 char C chars DEFGH qqq str st⍴ing'
57
FMT←'int %d perc %% doub %f char %c chars %5c qqq str %s %n'
DATA FIO∆fwrite_utf8 Handle
59
FIO∆fclose Handle ⍝ close file
0
⎕←Handle←'r' FIO∆fopen Filename
⁰
FMT FIO∆fscanf Handle
22 3.14 C DEFGH st⍴ing 59
FIO∆fclose Handle ⍝ close file
0
⍝ sscanf
⍝
⍴DATA←'int 22 perc % doub 3.14 char C chars DEFGH qqq str st⍴ing'
57
FMT←'int %d perc %% doub %f char %c chars %5c qqq str %s %n'
FMT FIO∆sscanf DATA
22 3.14 C DEFGH st⍴ing 57
FMT ⎕FIO['sscanf'] DATA ⍝ dyadic with axis string
22 3.14 C DEFGH st⍴ing 57
⍝ execve
⍝
⍝Filename←'/usr/local/lib/apl/TLV_server' ⍝ whereever TLV_server lives
Filename←'../tools/TLV_server'
Handle ← FIO∆execve Filename ⍝ start & connect TLV_server
TLV ← 33 ⎕CR 42,'Forty-Two' ⍝ encode a TLV buffer, Tag 42
⊣TLV ⎕FIO[43] Handle ⍝ send TLV buffer to TLV_server
TL ← 8 ⎕FIO[6] Handle ⍝ read tag/lenght from TLV_server
Value ← (256⊥4↓TL) ⎕FIO[6] Handle ⍝ read value from TLV_server
34 ⎕CR TL,Value ⍝ display response tag and value
¯42 owT-ytroF
TLV ← 33 ⎕CR 99,'quit' ⍝ encode stop command, Tag 99
⊣TLV ⎕FIO[43] Handle ⍝ send TLV buffer to TLV_server
⊣(⎕FIO[4] Handle) ⍝ close connection (stops TLV_server)
FIO∆mkdir_777 FIO∆getcwd,'/test_data'
0
DATA←'Kiss,n. A word invented by poets as a rhyme for bliss.'
DATA FIO∆pipeto 'wc>test_data/wc.txt'
0
FIO∆read_file 'test_data/wc.txt'
0 11 54
FIO∆pipefrom 'ls test_data'
wc.txt
FIO∆unlink 'test_data/wc.txt'
0
FIO∆rmdir 'test_data'
0
)ERASE FORMAT Handle Handle1 Handle2 Command AF_INET SOCK_STREAM
)ERASE Error FSTAT Filename LOCALHOST Port Z Server IPPROTO_IP
)ERASE FMT DATA TL TLV Value
⍝ )VARS
⍝ ==================================