996
|
1 <HTML>
|
|
2 <HEAD>
|
|
3 <TITLE>CLC-INTERCAL Reference</TITLE>
|
|
4 </HEAD>
|
|
5 <BODY>
|
|
6 <H1>CLC-INTERCAL Reference</H1>
|
|
7 <H2>... The system call interface</H2>
|
|
8
|
|
9 <P>
|
|
10 Table of contents:
|
|
11 <UL>
|
|
12 <LI><A HREF="index.html">Parent directory</A>
|
|
13 <LI><A HREF="#compiling">Compiling a program with system
|
|
14 call support</A>
|
|
15 <LI><A HREF="#using">Using the system call interface</A>
|
|
16 <LI><A HREF="#list">List of available calls</A>
|
|
17 </UL>
|
|
18 </P>
|
|
19
|
|
20 <H2><A NAME="compiling">Compiling a program with system call support</A></H2>
|
|
21
|
|
22 <P>
|
|
23 Syscall is a standard compiler extension, so programs must include the
|
|
24 appropriate compile option to use it.
|
|
25 </P>
|
|
26
|
|
27 <P>
|
|
28 The command-line compiler tool,
|
|
29 <I>sick</I>, automatically enables the Syscall extension if the program
|
|
30 suffix includes the letter "s".
|
|
31 Alternatively, if you are not relying on <I>sick</I>'s guesses and
|
|
32 are specifying a list of preloads yourself, just add <I>-psyscall</I>
|
|
33 to your command line.
|
|
34 </P>
|
|
35
|
|
36 <P>
|
|
37 Using the INTERCAL Calculator, INTERCALC, you can easily add Syscall
|
|
38 support by selecting "syscall" from the Options menu or by
|
|
39 adding <I>-osyscall</I> to the command line.
|
|
40 </P>
|
|
41
|
|
42 <P>
|
|
43 The <I>syscall</I> compiler object, which implements this extension,
|
|
44 uses direct access to the runtime's internal state and other undocumented
|
|
45 methods to extend the runtime as necessary to support its functions.
|
|
46 If you really want to know, look at the assembler source in
|
|
47 <CODE>INTERCAL/Include/syscall.iasm</CODE> in the CLC-INTERCAL distribution.
|
|
48 </P>
|
|
49
|
|
50 <H2><A NAME="using">Using the system call interface</A></H2>
|
|
51
|
|
52 <P>
|
|
53 The system call interface adds a hidden "DO NEXT FROM (666)"
|
|
54 somewhere in your operating system. This means that when your program
|
|
55 uses label (666) you do a system call as soon as the corresponding
|
|
56 statement is executed.
|
|
57 </P>
|
|
58
|
|
59 <P>
|
|
60 The system call interface will access your program's registers to
|
|
61 execute. All registers accessed this way will have the same number,
|
|
62 for example .1 and ;1 - what number is actually used depends on
|
|
63 the last assignment you've made just before the system call.
|
|
64 For example, the fragment:
|
|
65 <PRE>
|
|
66 DO :6 <- #1
|
|
67 (666) DO READ OUT .1
|
|
68 </PRE>
|
|
69 would use registers with number 6 - because the last register being
|
|
70 assigned to was :6. Since one must always provide a system call
|
|
71 number in a spot register, it is good practice to assign this number
|
|
72 in a statement with label (666) - this will have the side effect
|
|
73 of making sure the last assignment is to the correct register number.
|
|
74 For example:
|
|
75 <PRE>
|
|
76 (666) DO .6 <- #2
|
|
77 DO READ OUT ,6
|
|
78 </PRE>
|
|
79 executes system call #2 (because .6 contains the system call code),
|
|
80 which just happens to store its result in ,6 (because it returns a
|
|
81 tail array, and it would naturally use the tail array with the same
|
|
82 register number). The second statement would therefore produce
|
|
83 "CLC-INTERCAL" as output, since system call #2 returns
|
|
84 the name of the compiler.
|
|
85 </P>
|
|
86
|
|
87 <H2><A NAME="list">List of available calls</A></H2>
|
|
88
|
|
89 <P>
|
|
90 In the following list, we use a cross ("X") instead of a
|
|
91 register number, to remind the reader that the actual number used
|
|
92 depends on the most recent assignment before the system call was
|
|
93 executed. Also remember that the system call number is in the spot
|
|
94 register (.X). After the list of calls, a more extensive description,
|
|
95 or even an example, may follow for some of the calls.
|
|
96 </P>
|
|
97
|
|
98 <TABLE>
|
|
99 <TR>
|
|
100 <TH>Number</TH>
|
|
101 <TH>Description</TH>
|
|
102 <TH>Registers modified</TH>
|
|
103 </TR>
|
|
104 <TR>
|
|
105 <TD>#0</TD>
|
|
106 <TD>No operation</TD>
|
|
107 <TD>-</TD>
|
|
108 </TR>
|
|
109 <TR>
|
|
110 <TD>#1</TD>
|
|
111 <TD>Store version number in ,X</TD>
|
|
112 <TD>,X</TD>
|
|
113 </TR>
|
|
114 <TR>
|
|
115 <TD>#2</TD>
|
|
116 <TD>Store compiler name in ,X</TD>
|
|
117 <TD>,X</TD>
|
|
118 </TR>
|
|
119 <TR>
|
|
120 <TD>#3</TD>
|
|
121 <TD>Open file using path in ,X and mode in :X</TD>
|
|
122 <TD>@X</TD>
|
|
123 </TR>
|
|
124 <TR>
|
|
125 <TD>#4</TD>
|
|
126 <TD>Reset (seek to position 0) file @X</TD>
|
|
127 <TD>@X</TD>
|
|
128 </TR>
|
|
129 <TR>
|
|
130 <TD>#5</TD>
|
|
131 <TD>Seek file @X to position :X</TD>
|
|
132 <TD>@X</TD>
|
|
133 </TR>
|
|
134 <TR>
|
|
135 <TD>#6</TD>
|
|
136 <TD>Open TCP socket using name in ,X and mode in :X</TD>
|
|
137 <TD>@X</TD>
|
|
138 </TR>
|
|
139 <TR>
|
|
140 <TD>#7</TD>
|
|
141 <TD>Toggle newline handling</TD>
|
|
142 <TD>-</TD>
|
|
143 </TR>
|
|
144 </TABLE>
|
|
145
|
|
146 <P>
|
|
147 System calls #3 and #6 take their name from ,X - call #3 interprets
|
|
148 the name as a local file path, while call #6 interprets it as a
|
|
149 SERVER:PORT string, where SERVER can be a DNS name or IP address,
|
|
150 and PORT can be a port number or service name. The file access mode
|
|
151 in :X is one of:
|
|
152 <TABLE>
|
|
153 <TR>
|
|
154 <TH>Mode</TH>
|
|
155 <TH>Meaning</TH>
|
|
156 </TR>
|
|
157 <TR>
|
|
158 <TD ALIGN="RIGHT">#97</TD>
|
|
159 <TD>Appending (like #114, but always at end of file); file is created if it does not exist</TD>
|
|
160 </TR>
|
|
161 <TR>
|
|
162 <TD ALIGN="RIGHT">#114</TD>
|
|
163 <TD>Reading out (that is, output only); file is created or truncated</TD>
|
|
164 </TR>
|
|
165 <TR>
|
|
166 <TD ALIGN="RIGHT">#117</TD>
|
|
167 <TD>Updating (that is, reading in and writing out); file is created if it does not exist</TD>
|
|
168 </TR>
|
|
169 <TR>
|
|
170 <TD ALIGN="RIGHT">#119</TD>
|
|
171 <TD>Writing in (that is, input only); file must already exist</TD>
|
|
172 </TR>
|
|
173 <TR>
|
|
174 <TD ALIGN="RIGHT">#353</TD>
|
|
175 <TD>Appending (like #97)</TD>
|
|
176 </TR>
|
|
177 <TR>
|
|
178 <TD ALIGN="RIGHT">#370</TD>
|
|
179 <TD>Reading out, like #114, but the file is not truncated if it already exists</TD>
|
|
180 </TR>
|
|
181 <TR>
|
|
182 <TD ALIGN="RIGHT">#373</TD>
|
|
183 <TD>Updating; same as #117</TD>
|
|
184 </TR>
|
|
185 <TR>
|
|
186 <TD ALIGN="RIGHT">#375</TD>
|
|
187 <TD>Updating, same as #117</TD>
|
|
188 </TR>
|
|
189 </TABLE>
|
|
190 The resemblance of the first four codes with the ASCII codes for the letters "a",
|
|
191 "r", "u" and "w" is purely coincidental and should not be
|
|
192 construed as having any meaning; likewise, the resemblance of the other four codes with
|
|
193 the first four plus #256.
|
|
194 </P>
|
|
195
|
|
196 <P>
|
|
197 System call #7 affects all alphanumeric READ OUT in <I>sick</I> mode; it is not
|
|
198 localised to a specific filehandle. Normally, after an alphanumeric READ OUT
|
|
199 the runtime adds a newline character; executing system call #7 disables this;
|
|
200 executing the call again re-enables the newline.
|
|
201 </P>
|
|
202
|
|
203 <P>
|
|
204 Here is a simple example of using system calls #1, #2 and #7 to print the
|
|
205 name and version number of the compiler:
|
|
206 <PRE>
|
|
207 (666) DO .1 <- #2
|
|
208 DO ,2 <- #3
|
|
209 DO ,2 SUB #1 <- #91
|
|
210 DO ,2 SUB #2 <- #95
|
|
211 DO ,2 SUB #3 <- #68
|
|
212 (666) DO .3 <- #1
|
|
213 DO ,4 <- #3
|
|
214 DO ,4 SUB #1 <- #91
|
|
215 DO ,4 SUB #2 <- #95
|
|
216 DO ,4 SUB #3 <- #66
|
|
217 (666) DO .1 <- #7
|
|
218 PLEASE READ OUT ,1 + ,2 + ,3 + ,4
|
|
219 PLEASE GIVE UP
|
|
220 </PRE>
|
|
221 The first line uses system call #2 to get the compiler name into ,1; the
|
|
222 next four lines prepare ,2 to contain a single space; after that, system
|
|
223 call #1 provides the compiler version number; then ,4 is prepared to
|
|
224 contain a newline; system call #7 disables the automatic newline.
|
|
225 finally, the four arrays are READ OUT, producing something like
|
|
226 "<I>compiler-name</I> <I>version</I>", or, at the time of writing,
|
|
227 "CLC-INTERCAL 1.-94.-3" - the source for this example can be
|
|
228 found in <CODE>examples/syscall1.si</CODE> in the distribution.
|
|
229 </P>
|
|
230
|
|
231 <P>
|
|
232 A more interesting example (from <CODE>examples/http-get.si</CODE>) shows
|
|
233 how to use system call #6 to obtain a network socket, send a request to it
|
|
234 and print the results. Compile it with:
|
|
235 <PRE>
|
|
236 sick -lObject http-get.si
|
|
237 </PRE>
|
|
238 then run it with (for example)
|
|
239 <PRE>
|
|
240 ./http-get.io
|
|
241 intercal.freeshell.org:80
|
|
242 /index.html
|
|
243 </PRE>
|
|
244 or provide your own input: a SERVER:PORT in the first line, and a path
|
|
245 within the server in the second line.
|
|
246 </P>
|
|
247
|
|
248 <P>
|
|
249 Here follows the source code for this example:
|
|
250 <PRE>
|
|
251 PLEASE NOTE: READING SERVER:PORT
|
|
252 DO ,1 <- #1024
|
|
253 DO WRITE IN ,1
|
|
254
|
|
255 PLEASE NOTE: READING PATH
|
|
256 DO ,2 <- #1024
|
|
257 DO WRITE IN ,2
|
|
258
|
|
259 PLEASE NOTE: OPENING HTTP CONNECTION (OR SPLAT)
|
|
260 DO :1 <- #117
|
|
261 (666) DO .1 <- #6
|
|
262
|
|
263 PLEASE NOTE: SENDING HTTP REQUEST
|
|
264 PLEASE DO ;1 <- #4
|
|
265 DO ;1 SUB #1 <- #18
|
|
266 DO ;1 SUB #2 <- #247
|
|
267 DO ;1 SUB #3 <- #365
|
|
268 DO ;1 SUB #4 <- #277
|
|
269 PLEASE DO ,3 <- #14
|
|
270 DO ,3 SUB #1 <- #91
|
|
271 DO ,3 SUB #2 <- #95
|
|
272 DO ,3 SUB #3 <- #68
|
|
273 DO ,3 SUB #4 <- #84
|
|
274 DO ,3 SUB #5 <- #80
|
|
275 DO ,3 SUB #6 <- #80
|
|
276 DO ,3 SUB #7 <- #86
|
|
277 PLEASE DO ,3 SUB #8 <- #91
|
|
278 DO ,3 SUB #9 <- #93
|
|
279 DO ,3 SUB #10 <- #87
|
|
280 DO ,3 SUB #11 <- #92
|
|
281 DO ,3 SUB #12 <- #86
|
|
282 DO ,3 SUB #13 <- #72
|
|
283 DO ,3 SUB #14 <- #66
|
|
284 (666) DO .1 <- #7
|
|
285 DO READ OUT @1 + ;1 + ,2 + ,3
|
|
286 PLEASE DO ,3 <- #4
|
|
287 DO ,3 SUB #1 <- #91
|
|
288 DO ,3 SUB #2 <- #95
|
|
289 DO ,3 SUB #3 <- #72
|
|
290 DO ,3 SUB #4 <- #66
|
|
291 PLEASE DO ;1 <- #6
|
|
292 DO ;1 SUB #1 <- #29
|
|
293 DO ;1 SUB #2 <- #1098
|
|
294 DO ;1 SUB #3 <- #2574
|
|
295 DO ;1 SUB #4 <- #692
|
|
296 DO ;1 SUB #5 <- #105
|
|
297 DO ;1 SUB #6 <- #213
|
|
298 DO READ OUT @1 + ;1 + ,1 + ,3
|
|
299 DO READ OUT @1 + ,3
|
|
300
|
|
301 PLEASE NOTE: GETTING RESULT AND PRINTING IT
|
|
302 PLEASE DO ;1 <- #1024
|
|
303 PLEASE DO .1 <- #0
|
|
304 DO COME FROM .1
|
|
305 DO WRITE IN @1 + ;1
|
|
306 DO READ OUT @2 + ;1
|
|
307 (1) DO .1 <- ';1 SUB #1 ~ ;1 SUB #1' ~ #1
|
|
308 PLEASE GIVE UP
|
|
309 </PRE>
|
|
310 </P>
|
|
311
|
|
312 <P>
|
|
313 The program is mostly self explanatory, but we'll explain it anyway. The
|
|
314 first few lines get the two lines you type; then system call #6 is
|
|
315 used to open a TCP socket; note that the last assignment is to .1, so
|
|
316 that the access mode is taken from :1 (#117 - reading out and writing in)
|
|
317 and the network address from ,1 (whatever you typed).
|
|
318 </P>
|
|
319
|
|
320 <P>
|
|
321 The next block
|
|
322 creates the string "GET " in ;1 and " HTTP/1.0\r\n"
|
|
323 in ,3 (\r\n represents a carriage return, line feed sequence). A call to
|
|
324 system call #7 disables the automatic newline, which we must do because
|
|
325 network servers expect a carriage return, line feed instead. We are now
|
|
326 ready to send out ;1 + ,2 + ,3 or in other words "GET <I>path</I> HTTP/1.0"
|
|
327 to the server (note that @1 has been connected to the network socket).
|
|
328 </P>
|
|
329
|
|
330 <P>
|
|
331 Following, the carriage return, line feed sequence is stored in ,3 and
|
|
332 the string "Host: " is stored in ;1 - this means that
|
|
333 the next READ OUT sends "Host: <I>server</I>:<I>port</I>" to
|
|
334 the HTTP server, just as it expects to be able to resolve the virtual
|
|
335 host name, if necessary; the READ OUT ,3 just produces a blank line,
|
|
336 to indicate the end of the request.
|
|
337 </P>
|
|
338
|
|
339 <P>
|
|
340 The last block of the program writes the reply from the server in
|
|
341 and reads it out to the user; this is done by dimensioning ;1 to
|
|
342 hold 1024 characters (you can increase the buffer size, of course),
|
|
343 writing that in using the TCP socket filehandle, and reading it
|
|
344 out again using the standard read filehandle (@2); the runtime signals
|
|
345 that a block is less than 1024 characters by filling all unused elements
|
|
346 of ;1 with #0 - at end of file, no elements will be used, so ;1 SUB #1
|
|
347 will be #0 (the runtime guarantees that this element will be nonzero if
|
|
348 there has been any data received from the server). Therefore the
|
|
349 assignment to .1 results in the computed COME FROM a few lines earlier
|
|
350 to execute if there is more data, or to do nothing at end of file.
|
|
351 </P>
|
|
352
|
|
353 <P>
|
|
354 More system calls may be planned for future versions of CLC-INTERCAL,
|
|
355 but we aren't telling at the moment
|
|
356 </P>
|
|
357 </BODY>
|
|
358 </HTML>
|
|
359
|