File: external.tex

package info (click to toggle)
form 4.2.1%2Bgit20200217-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 5,500 kB
  • sloc: ansic: 101,613; cpp: 9,375; sh: 1,582; makefile: 505
file content (406 lines) | stat: -rw-r--r-- 16,239 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
\chapter{External communication}
\label{externalcommunication}

To communicate\index{communication!external} with other programs \FORM\ is 
equipped with special commands. One set of commands is rather simple in 
nature: the \#pipe\index{\#pipe} (see section \ref{prepipe}) and 
\#system\index{\#system} (see section \ref{presystem}) instructions allow 
\FORM\ to run programs in the regular command\index{command shell} 
shell\index{shell}. Sometimes however much more sophistication is needed 
because these instructions have a rather large overhead and need to start 
new processes each time they are executed. Hence a second more extensive 
set of instructions was developed that allows the start of an external 
process\index{process!external}, keep it open and maintain a two way 
communication\index{communication!two way} with it. Similarly it is 
possible to start \FORM\ in such a way from other programs. Many details of 
the method of implementation and a number of examples are given in a 
separate paper which can also found in the \FORM\ site 
(http://www.nikhef.nl/$\sim$form) under publications (look for the file 
extform.ps\index{extform.ps} or extform.pdf\index{extform.pdf}). Here we 
will just show the essentials and the syntax.

The basic idea is to open (by means of the preprocessor) a number of 
external channels\index{channel!external} (there is no reason to be 
restricted to just one) by starting the corresponding program in a command 
shell. This program is kept running and a number is assigned to each 
channel. Next we can select a channel and communicate with it. To not run 
into syntactic problems, because the external program may have different 
ideas of what a formula should look like, one may have to install 
filters\index{filter}. These are additional programs that should be 
prepared before the \FORM\ program is started that process the communication 
to convert from one notation to the other.

%--#[ #external :

\section{\#external}
\label{external}

\noindent Syntax:

\#external ["prevar"] systemcommand

\noindent See also

\noindent Starts\index{\#external} the command in the background, 
connecting to its standard input and output. By default, the external 
command has no controlling terminal, the standard error stream is 
redirected to \verb|/dev/null| and the command is run in a subshell in a 
new session and in a new process group (see the preprocessor instruction 
\verb|#setexternalattr|).

The optional parameter ``prevar'' is the name of a preprocessor variable 
placed between double quotes. If it is present, the ``descriptor'' (small 
positive integer number) of the external command is stored into this 
variable and can be used for references to this external command (if there 
is more than one external command running simultaneously).

The external command that is started last becomes the ``current'' (active) 
external command.  All further instructions 
\#fromexternal\index{\#fromexternal} and \#toexternal\index{\#toexternal} 
deal with the current external command.

%--#] #external :
%--#[ #toexternal :

\section{\#toexternal}
\label{toexternalcommunication}

\noindent Syntax:

\#toexternal "formatstring" [,variables]

\noindent See also

\noindent Sends\index{\#toexternal} the output to the current 
external\index{\#external} command. The semantics of the 
\verb|"formatstring"| and the \verb|[,variables]| is the same as for the 
\#write\index{\#write} instruction, except for the trailing end-of-line symbol. In 
contrast to the \#write instruction, the \#toexternal instruction does not 
append any newline\index{newline} symbol to the end of its output.

%--#] #toexternal :
%--#[ #fromexternal :

\section{\#fromexternal}
\label{fromexternalcommunication}

\noindent Syntax:

\#fromexternal[$+-$] ["[\$]varname" [maxlength]]

\noindent Appends\index{\#fromexternal} the output of the current 
external\index{\#external} 
command to the \FORM\ program. The semantics differ depending on the optional 
arguments. After the external command sends the prompt, \FORM\ will continue 
with a next line after the line containing the \#fromexternal instruction. 
The prompt string is not appended. The optional + or - sign after the name 
has influence on the listing of the content. The varieties are:
                                                           
\#fromexternal[$+-$]

\noindent The semantics is similar to the \#include\index{\#include} 
instruction but folders\index{folders} are not supported. 

\#fromexternal[$+-$] "[\$]varname"

\noindent is used to read the text from the running external command into 
the preprocessor variable varname, or into the dollar variable \$varname if 
the name of the variable starts with the dollar sign ``\$''.

\#fromexternal[$+-$] "[\$]varname" maxlength

\noindent is used to read the text from the running external command into 
the preprocessor (or dollar) variable varname. Only the first maxlength 
characters are stored.

%--#] #fromexternal :
%--#[ #prompt :

\section{\#prompt}
\label{promptcommunication}

\noindent Syntax:

\#prompt [newprompt]

\noindent Sets\index{\#prompt} a new prompt for the current external 
command (if present) and all further (newly started) external commands.

If newprompt is an empty string, the default prompt (an empty line) will be 
used.

The prompt is a line consisting of a single prompt string. By default, this 
is an empty string.

%--#] #prompt :
%--#[ #setexternal :

\section{\#setexternal}
\label{setexternalcommunication}

\noindent Syntax:

\#setexternal n

\noindent Sets the ``current'' external\index{\#setexternal} command. The 
instructions \#toexternal\index{\#toexternal} and 
\#fromexternal\index{\#fromexternal} deal with the current external 
command.  The integer number n must be the descriptor of a running external 
command.

%--#] #setexternal :
%--#[ #rmexternal :

\section{\#rmexternal}
\label{rmexternalcommunication}

\noindent Syntax:

\#rmexternal [n]

\noindent Terminates an external\index{\#rmexternal} command. The integer 
number n must be either the descriptor of a running external command, or 0.

If n is 0, then all external programs will be terminated.

If n is not specified, the current external command will be terminated.

The action of this instruction depends on the attributes of the external 
channel (see the \#setexternalattr\index{\#setexternalattr} (section 
\ref{setexternalcommunication}) instruction). By default, the instruction 
closes the commands' IO channels, sends a KILL\index{KILL signal} signal to 
every process in its process group and waits for the external command to be 
finished.

%--#] #rmexternal :
%--#[ #setexternalattr :

\section{\#setexternalattr}
\label{setexternalattrcommunication}

\noindent Syntax:

\#setexternalattr list\_of\_attributes

\noindent sets\index{\#setexternalattr} attributes for {\em newly started} 
external commands. Already running external commands are not affected. The 
list of attributes is a comma separated list of pairs attribute=value, 
e.g.:
\begin{verbatim}
   #setexternalattr shell=noshell,kill=9,killall=false
\end{verbatim}
Possible attributes are:
\begin{description}
\item[kill\index{kill}]
Specifies which signal is to be sent to the external command either before 
the termination of the \FORM\ program or by the preprocessor instruction 
\#rmexternal\index{\#rmexternal}. By default this is 9 
(SIGKILL\index{SIGKILL signal}). Number 0 means that no signal will be 
sent.
\item[killall\index{killall}] Indicates whether the KILL\index{KILL signal} 
signal will be sent to the whole group or only to the initial process. 
Possible values are ``\verb|true|'' and ``\verb|false|''. By default, the 
kill signal will be sent to the whole group.
\item[daemon\index{daemon}]
Indicates whether the command should be ``daemonized'', i.e. 
the initial process will be passed to the init process and will belong
to the new process group in the new session.  
Possible values are ``\verb|true|'' and ``\verb|false|''. By default, 
``\verb|true|''.
\item[shell\index{shell}]
specifies which shell\index{shell} is used to run a command. (Starting an 
external command in a subshell permits to start not only executable files 
but also scripts and pipelined jobs. The disadvantage is that there is no 
way to detect failure upon startup since usually the shell is started 
successfully.) By default this is ``\verb|/bin/sh -c|''.  If set 
\verb|shell=noshell|, the command will be started by the instruction 
\#external\index{\#external} directly but not in a subshell, so the command 
should be a name of the executable file rather than a system command. The 
instruction \#external will duplicate the actions of the shell in searching 
for an executable file if the specified file name does not contain a slash 
(/) character.  The search path\index{path!search} is the path specified in 
the environment by the PATH\index{PATH} variable.  If this variable isn't 
specified, the default path ``\verb|:/bin:/usr/bin|'' is used.
\item[stderr\index{stderr}]
specifies a file to redirect the standard error\index{error stream} stream 
to. By default it is ``\verb|/dev/null|''. If set \verb|stderr=terminal|,
no redirection occurs.
\end{description}
Only attributes that are explicitly mentioned are changed, all others remain 
unchanged. Note, changing attributes should be done with care. For example,
\begin{verbatim}
   #setexternalattr daemon=false
\end{verbatim}
starts a command in the subshell within the current process group with
default attributes kill=9 and killall=true.
The instruction \#rmexternal\index{\#rmexternal} sends the
KILL\index{KILL signal} signal to the whole group, which means that also 
\FORM\ itself will be killed.

%--#] #setexternalattr :
%--#[ An example :

\section{An example}
 
An example of the above instructions could be:
% THIS EXAMPLE IS PART OF THE TESTSUITE. CHANGES HERE SHOULD BE APPLIED THERE AS
% WELL!
\begin{verbatim}
 1  symbol a,b;
 2
 3  #external "n1" cat -u
 4
 5  #external "n2" cat -u
 6
 7  *  cat simply repeats its input. The default prompt is an
 8  *  empty line. So we use "\n\n" here -- one "\n" is to finish
 9  *  the line, and the next "\n" is the prompt:
10  #toexternal "(a+b)^2\n\n"
11
12  #setexternal `n1'
13  *  For this channel the prompt will be "READY\n":
14  #toexternal "(a+b)^3\nREADY\n"
15
16  #setexternal `n2'
17  *  Set the default prompt:
18  #prompt
19  Local aPLUSbTO2=
20  #fromexternal
21         ;
22
23  #setexternal `n1'
24  #prompt READY
25  Local aPLUSbTO3=
26  #fromexternal
27         ;
28
29  #rmexternal `n1'
30  #rmexternal `n2'
31
32  Print;
33  .end
\end{verbatim}

Two external channels are opened in lines 3 and 5. The UNIX\index{UNIX} 
utility ``\verb|cat|'' simply repeats its input.
The option ``\verb|-u|'' is used to prevent the output buffering. The 
option is ignored by the GNU\index{GNU} \verb|cat| utility but is mandatory 
for non-GNU versions of \verb|cat|.

After line 5 the current external channel is `\verb|n2|'. The default 
prompt is an empty line so in line 10 ``\verb|\n\n|'' is used -- 
one``\verb|\n|'' is to finish the line, and the next ``\verb|\n|'' is the 
prompt.

Line 12 switches the current channel to `\verb|n1|'. For this channel
the prompt will be ``\verb|READY|'', see line 24, hence the expression is
finished by ``\verb|\nREADY\n|''.

Line 16 switches to the `\verb|n2|' external channel and line 18 sets
the default prompt (which is extra in this example since the default
prompt was not changed up to now).

Results (just a literal repetition of the sent expressions) are read
in lines 20 and 26.

Lines 29 and 30 close the external channels.

%--#] An example :
%--#[ Embedding :

\section{Embedding FORM in other applications}
\label{embeddingcommunication}

The external channel instructions permit \FORM\ to swallow an external 
program. The same mechanism can be used in order to {\em 
embed\index{embed}} \FORM\ in other applications.

There is a possibility to start \FORM\ from another program providing
one (or more) communication channels (see below). These channels will be 
visible from a \FORM\ program as
``pre-opened''\index{pre-opened external channels} external channels 
existing after \FORM\ starts. There is no need to open them with the 
\#external\index{\#external} instruction.
In this case, the preprocessor variable ``PIPES\_''\index{PIPES\_} is 
defined and is equal to the total number of the pre-opened external 
channels. Pre-opened external channel descriptors are contained in the 
preprocessor 
variables ``PIPE1\_''\index{PIPE1\_}, ``PIPE2\_''\index{PIPE2\_}, etc.
For example, if `PIPES\_'\index{PIPES\_} is 3 then there are 3 
pre-opened external channels with the descriptors `PIPE1\_',
`PIPE2\_' and `PIPE3\_' so e.g. the following instruction could
be used:
\begin{verbatim}
   #setexternal `PIPE2_'
\end{verbatim}
without 
\begin{verbatim}
   #external "PIPE2_"
\end{verbatim}

The external channel attributes make no sense for the pre-opened channel 
(see the \#setexternalattr\index{\#setexternalattr} instruction (section 
\ref{setexternalattrcommunication})).
Formally, they are as follows:
\begin{verbatim}
   kill=0,
   killall=false,
   daemon=false,
   stderr=/dev/tty,
   shell=noshell
\end{verbatim}

In order to activate the pre-opened external channels, the parent
application must follow some standards. Here we describe a low-level 
protocol\index{protocol!lowlevel}, the corresponding 
C-interface\index{C-interface} is available from the \FORM\ distribution site 
under packages and then externalchannels.

Before starting \FORM, the parent application must create one or more pairs 
of pipes. A pipe\index{pipe} is a pair of file descriptors, one is for 
reading and another is for writing. In LINUX\index{LINUX}, see ``man 2 
pipe''. The read-only descriptor of the first pipe in the pair and the 
write-only descriptor of the second pipe must be passed to \FORM\ as an 
argument of a command line option ``\verb|-pipe|'' in ASCII decimal format. 
The argument of the option is a comma-separated list of pairs
``\verb|r#,w#|'' where ``\verb|r#|'' is a read-only descriptor and 
``\verb|w#|'' is a write-only descriptor; alternatively, an environment 
variable FORM\_PIPES\index{FORM\_PIPES} containing this list can be used 
(the command line option overrides the environment variable). For example, 
to start \FORM\ with two pre-opened external channels the parent application 
has to create first four pipes. Lets us suppose the first pipe was created 
with the descriptors 5 and 6, the second pipe has the descriptors 7 and 8, 
the third pipe has the descriptors 9 and 10 and the fourth pipe has the 
descriptors 11 and 12. The descriptors 5 and 8 will be used by \FORM\ as the 
input and the output for the first pre-opened external channel while the 
descriptors 9 and 12 will be used by \FORM\ as the input and the output for 
the second pre-opened external channel.

Then the parent application must start \FORM\ with the following 
command line option:
\begin{verbatim}
   -pipe 5,8,9,12
\end{verbatim}

Upon startup, \FORM\ sends its PID\index{PID} (the Process Identifier) in 
ASCIIdecimal format with an appended newline character to the descriptor 8 
and then \FORM\ will wait for the answer from the descriptor 5. The answer 
must be two comma-separated integers in ASCII decimal format followed by a 
newline character. The first integer corresponds to the \FORM\ PID while the 
second one is the parent process PID. If the answer is not obtained after 
some timeout, or if it is not correct (i.e. it is not a list of two 
integers or the first integer is not the \FORM\ PID) then \FORM\ fails. If 
everything is correct, \FORM\ creates the pre-opened channel and puts its 
descriptor in the preprocessor variable ``PIPE1\_''.

Then \FORM\ processes the second pair of arguments, ``\verb|9,12|''.

After all pairs have been processed \FORM\ creates the preprocessor variable 
``PIPES\_'' and puts into this variable the total number of created 
pre-opened external channels.

The order of processing the pairs of numbers in the argument is fixed 
exactly as it was described above i.e. from the left to the right.

%--#] Embedding :