1% BEGIN LICENSE BLOCK
2% Version: CMPL 1.1
3%
4% The contents of this file are subject to the Cisco-style Mozilla Public
5% License Version 1.1 (the "License"); you may not use this file except
6% in compliance with the License.  You may obtain a copy of the License
7% at www.eclipse-clp.org/license.
8% 
9% Software distributed under the License is distributed on an "AS IS"
10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11% the License for the specific language governing rights and limitations
12% under the License. 
13% 
14% The Original Code is  The ECLiPSe Constraint Logic Programming System. 
15% The Initial Developer of the Original Code is  Cisco Systems, Inc. 
16% Portions created by the Initial Developer are
17% Copyright (C) 2006 Cisco Systems, Inc.  All Rights Reserved.
18% 
19% Contributor(s): 
20% 
21% END LICENSE BLOCK
22
23:- comment(alias, "Operating System").
24:- comment(summary, "Built-ins to access operating-system services").
25:- comment(categories, ["Built-In Predicates","Interfacing"]).
26
27:- comment(alarm / 1, [
28	summary:"The operating system will send the signal 14 to the ECLiPSe system Clock
29seconds after the command was entered.
30
31",
32	amode:(alarm(+) is det),
33	desc:html("   Used to send the signal 14 (SIGALRM) to the ECLiPSe system Clock seconds
34   after the alarm/1 command is entered.  If there is already a pending
35   alarm, its clock is merely reset, i.e.  there cannot be multiple alarm
36   requests.
37
38<P>
39   If Clock is 0, any pending alarm is cancelled.  If Clock is negative, it
40   is nevertheless interpreted as an unsigned integer.
41
42<P>
43"),
44	args:["Clock" : "Integer"],
45	exceptions:[4 : "Clock is not instantiated.", 5 : "Clock is not an integer."],
46	eg:"
47Success:
48      [eclipse]: alarm(1).
49      yes.
50      [eclipse]: Signal 14         % 1 second later
51
52Error:
53      alarm(I).                    (Error 4).
54      alarm(2.0).                  (Error 5).
55
56
57
58",
59	see_also:[sleep / 1]]).
60
61:- comment(argc / 1, [
62	summary:"Succeeds if Number is the number of arguments given on the command line to
63invoke ECLiPSe .
64
65",
66	amode:(argc(-) is det),
67	desc:html("   Used to find the number of arguments used when invoking ECLiPSe at the
68   operating system prompt, including eclipse itself.
69
70<P>
71"),
72	args:["Number" : "Variable or integer."],
73	exceptions:[5 : "Number is instantiated, but not to an integer."],
74	eg:"
75Success:
76   % eclipse -g 10000
77   [eclipse]: argc(N).
78   N = 3
79   yes.
80
81Fail:
82   % eclipse -g 10000
83   [eclipse]: argc(2).
84   no.
85
86Error:
87   argc('3').             (Error 5).
88
89
90
91",
92	see_also:[argv / 2]]).
93
94:- comment(argv / 2, [
95	summary:"Succeeds if the Nth argument given on the command line when invoking
96ECLiPSe is the string Argument.
97
98",
99	amode:(argv(+,-) is det),
100	desc:html("   Used to find any argument used when invoking ECLiPSe at the operating
101   system prompt.  The zero'th argument is the name of the eclipse binary.
102   When N is the atom all, then a list of all arguments is returned instead
103   of a single argument.  When the command line contains the special
104   argument --, then all arguments before and including that one are
105   suppressed.
106
107<P>
108"),
109	args:["N" : "Integer or the atom all.", "Argument" : "String, List or variable."],
110	exceptions:[4 : "N is not instantiated.", 5 : "N is not an integer or an atom.", 6 : "N is an atom different from all.", 6 : "There was not N arguments when calling ECLiPSe ."],
111	eg:"
112Success:
113   % eclipse hello world
114   [eclipse]: argv(0,A0), argv(1,A1), argv(2,A2).
115   A0 = \"/usr/local/eclipse/bin/sun4/eclipse.exe\"
116   A1 = \"hello\"
117   A2 = \"world\"
118   yes.
119   [eclipse]: argv(all, [_A0|Args]).
120   Args = [\"hello\", \"world\"]
121   yes.
122   % eclipse -e \"argv(all,[_|A]),writeq(A),nl\" -- hello world
123   [\"hello\", \"world\"]
124Error:
125   argv(N,A).                     (Error 4).
126   argv(1.0,A).                   (Error 5).
127   argv(-1,A).                    (Error 6).
128
129
130
131",
132	see_also:[argc / 1]]).
133
134:- comment(cd / 1, [
135	summary:"Directory is made the current working directory.  Equivalent to
136set_flag(cwd, Directory).
137
138",
139	amode:(cd(+) is det),
140	desc:html("   Changes the current working directory to Directory.  Directory may be an
141   absolute or relative pathname.
142
143<P>
144"),
145	args:["Directory" : "Atom or string of any form acceptable to the operating                system."],
146	exceptions:[4 : "Directory is not instantiated.", 5 : "Directory is neither an atom nor a string.", 170 : "Directory doesn't exist."],
147	eg:"
148Success:
149      cd(workdir).
150      cd(\"workdir\").
151      cd('/home/lp/user/workdir').
152      cd('..').
153      cd('../workdir').
154
155Error:
156      cd(Dir).                    (Error 4).
157      cd(20).                     (Error 5).
158      cd('nonexist').             (Error 170).
159
160
161
162",
163	see_also:[getcwd / 1, set_flag / 2]]).
164
165:- comment(delete / 1, [
166	summary:"The file File (with absolute or relative pathname) is deleted.
167
168",
169	amode:(delete(+) is det),
170	desc:html("   Used to delete the file or directory File.  File may be an absolute or
171   relative filename.
172
173<P>
174"),
175	args:["File" : "An atom or a string of a form acceptable to the operating                system."],
176	exceptions:[4 : "File is not instantiated.", 5 : "File is neither an atom nor a string.", 170 : "File does not exist."],
177	eg:"
178Success:
179      [eclipse]: sh('ls file.pl').
180      file.pl
181      yes.
182      [eclipse]: delete('file.pl').
183      yes.
184      [eclipse]: sh('ls file.pl').
185      file.pl not found
186      yes.
187
188Error:
189      delete(File).                  (Error 4).
190      delete([file]).                (Error 5).
191      delete(nofile).                (Error 170).
192
193
194
195",
196	see_also:[sh / 1, system / 1, exists / 1, mkdir / 1]]).
197
198:- comment(getcwd / 1, [
199	summary:"Unifies the current working directory with Cwd.
200
201",
202	amode:(getcwd(-) is det),
203	desc:html("   Cwd is unified with the current working directory including the final
204   \"/\".
205
206<P>
207   Equivalent to get_flag(cwd, Cwd).  To set the current working directory,
208   use set_flag(cwd, Directory) or cd(Directory).
209
210<P>
211"),
212	args:["Cwd" : "String or Variable."],
213	exceptions:[5 : "Cwd is instantiated but not to a string."],
214	eg:"
215Success:
216     [eclipse]: sh(pwd).
217     /home/user/test
218     yes.
219     [eclipse]: getcwd(Cwd).
220     Cwd = \"/home/user/test/\"
221     yes.
222
223Fail:
224    getcwd(\"nodirectory\").
225
226Error:
227      getcwd(1).           (Error 5).
228      getcwd(atom).        (Error 5).
229
230
231
232",
233	see_also:[cd / 1, get_flag / 2, set_flag / 2, mkdir / 1]]).
234
235:- comment(getenv / 2, [
236	summary:"Succeeds if Name is the name of an environment variable or registry entry, and returns the corresponding value.",
237	amode:(getenv(+,-) is semidet),
238	index:[registry,'environment variables'],
239	desc:html("\
240    The first argument must be a string or an atom. The predicate looks
241    up a value which the operating system has stored under this key.
242<P>
243    <B>UNIX</B>:  If Name is the name of a UNIX environment variable, this
244    variable's value is returned.  As an additional feature, if there
245    exists an environment variable whose name is the concatenation of
246    the value of Name and the ECLiPSe version number (e.g. 
247    \"ECLIPSEDIR_4_9\" if Name is \"ECLIPSEDIR\" and the version
248    is 4.9), then this variable's value is returned instead.
249<P>
250   <B>WINDOWS</B>: The name Name is looked up in the registry under the key
251    HKEY_LOCAL_MACHINE\\SOFTWARE\\IC-Parc\\ECLiPSe\\&lt;version&gt;. If there is
252    such an entry, its value is returned. Otherwise, Name is taken as
253    the name of an environment variable, whose value is returned if it
254    exists.
255<P>
256    If the lookup operation is unsuccessful, the predicate fails.
257"),
258	args:["Name" : "String or atom.", "Value" : "String or variable."],
259	fail_if:"Fails if none of the lookup methods yielded any result for the given name",
260	exceptions:[4 : "Name is not instantiated.", 5 : "Name is instantiated, but not to a string or an atom.", 5 : "Value is instantiated, but not to a string."],
261	eg:"
262Success:
263      getenv('HOME',V).    (gives V=\"/home/username\").
264      getenv(\"SHELL\",V).   (gives V=\"/bin/csh\").
265      getenv('TERM',V).    (gives V=\"sun-cmd\").
266      getenv('USER',V).    (gives V=\"username\").
267
268Fail:
269      getenv('HOEM',V).
270
271Error:
272      getenv(TERM,V).               (Error 4).
273      getenv('TERM',atom).          (Error 5).
274      getenv(1,V).                  (Error 5).
275
276
277
278",
279	see_also:[setenv/2, sh / 1, argv / 2, argc / 1]]).
280
281:- comment(setenv / 2, [
282	summary:"Sets the environment variable Name to the given value",
283	amode:(setenv(+,+) is det),
284	index:['environment variables'],
285	desc:html("\
286    The first argument must be a string or an atom and is taken as the
287    name of an operating system environment variable.  The value of this
288    environment variable is set, or changed to, the new value Value.
289<P>
290    When Value is an atom or number, it is first converted to a string,
291    and the environment variable is set to the resulting string value.
292<P>
293    The mechanism can be used to pass information from an eclipse-process
294    to its sub-processes.  Note however, that due to operating system
295    limitations, environment strings cannot contain null characters
296    (unlike ECLiPSe strings).  Also, the strings used as arguments to
297    setenv/2 cannot be garbage collected and will accumulate.
298<P>
299    Operating system dependencies: Because of portability issues, on UNIX
300    there is currently no facility to unset an environment variable
301    completely, but it can set to an empty string. On Windows on the other
302    hand, an environment variable's value cannot be the empty string:
303    setting an environment variable to the empty string makes it
304    indistinguishable from an unset or nonexisting one.
305"),
306	args:["Name" : "String or atom.",
307		"Value" : "String, atom or number."],
308	exceptions:[4 : "Name or Value is not instantiated.",
309		5 : "Name is instantiated, but not to a string or an atom.",
310		5 : "Value is instantiated, but not to a string, atom or number.",
311		170 : "The environment could not be changed"],
312	eg:"
313   ?- setenv(abc, hello), getenv(abc, X).
314   X = \"hello\"
315   Yes (0.00s cpu)
316
317   ?- setenv(\"abc\", \"world\"), getenv(abc, X).
318   X = \"world\"
319   Yes (0.00s cpu)
320
321   ?- setenv(abc, 999), getenv(abc, X).
322   X = \"999\"
323   Yes (0.00s cpu)
324
325   ?-  setenv(abc, data), sh(\"echo $abc\").
326   data
327   Yes (0.00s cpu)
328
329   ?- setenv(abc, data), exec([sh,\"-c\",\"echo $abc\"], []).
330   data
331   Yes (0.00s cpu)
332
333   ?- setenv(abc, data), exec([eclipse,\"-e\",\"getenv(abc,X),writeln(X)\"], []).
334   data
335   Yes (0.00s cpu)
336
337   ?- setenv(abc, \"\"), getenv(abc, X).	% on UNIX
338   X = \"\"
339   Yes (0.00s cpu)
340
341   ?- setenv(abc, \"\"), getenv(abc, X).	% on Windows
342   No (0.00s cpu)
343",
344	see_also:[exec/2, exec/3, getenv/2, sh/1]]).
345
346:- comment(pause / 0, [
347	summary:"The ECLiPSe session is suspended (the same as Control-Z at the top-level
348loop).
349
350",
351	amode:(pause is det),
352	desc:html("   Used to suspend the ECLiPSe session.
353
354<P>
355"),
356	args:[],
357	eg:"
358Success:
359      [eclipse]: [user].
360       w(X) :- write(X).
361       user compiled 92 bytes in 0.02 seconds
362      yes.
363      [eclipse]: w(bird).
364      bird
365      yes.
366      [eclipse]: pause.
367      Stopped (signal)
368      % fg                       % foreground command
369      eclipse
370      yes.
371      [eclipse]: w(duck).
372      duck
373      yes.
374      [eclipse]: ^D
375      bye
376      % eclipse
377      [eclipse]: w(cow).
378      calling an undefined procedure
379
380
381
382",
383	see_also:[halt / 0]]).
384
385:- comment(rename / 2, [
386	summary:"Renames the file OldName to NewName.
387
388",
389	amode:(rename(+,+) is det),
390	desc:html("   OldName and NewName are absolute or relative pathnames of files.  Used
391   to rename the file OldName with the name NewName.
392
393<P>
394"),
395	args:["OldName" : "String or atom.", "NewName" : "String or atom."],
396	exceptions:[4 : "Either OldName or NewName are not instantiated.", 5 : "Either OldName or NewName are neither a string nor an atom.", 190 : "File OldName does not exist."],
397	eg:"
398Success:
399      [eclipse]: sh('ls file1').
400      file1
401      [eclipse]: rename(file1, file2).
402      yes.
403      [eclipse]: sh('ls file1 file2').
404      file1 not found
405      file2
406      yes.
407
408Error:
409      rename(Old, any).             (Error 4).
410      rename(any, New).             (Error 4).
411      rename(1, any).               (Error 5).
412      rename(notfile, newfile).     (Error 190).
413
414
415
416",
417	see_also:[exists / 1, delete / 1, mkdir / 1]]).
418
419:- comment(sleep / 1, [
420	summary:"The execution of ECLiPSe is suspended for Seconds number of seconds.
421
422",
423	amode:(sleep(+) is det),
424	desc:html("   sleep/1 causes the the suspension of execution of ECLiPSe for Seconds
425   number of seconds.
426
427<P>
428   However, ECLiPSe will respond to interrupts while asleep.  On most
429   operating systems, interrupts will terminate the sleep prematurely.
430
431<P>
432"),
433	args:["Seconds" : "Positive number (integer or float)."],
434	exceptions:[4 : "Seconds is uninstantiated.", 5 : "Seconds is not an integer or float."],
435	eg:"
436Success:
437      [eclipse]: sleep(0.3).
438                           % short sleep
439      yes.                 % \"yes\" appears after 0.3 seconds.
440
441      [eclipse]: sleep(63072000).
442                           % long sleep
443      yes.                 % \"yes\" appears after 2 years.
444
445
446
447",
448	see_also:[alarm / 1, pause / 0]]).
449
450:- comment(canonical_path_name / 2, [
451     summary: "Expand a path name into the full `canonical' form.",
452     amode:(canonical_path_name(+,-) is det),
453     args:  ["Path":           "A pathname (atom or string)",
454             "CanonicalPath":  "Canonical pathname for Path"
455	    ],
456     desc:  html("\
457   This predicate expands a given pathname, and converts it into the
458   `canonical' form of the pathname. The following are done to the path:
459
460<UL>
461   <LI> An absolute path is returned. If a relative path is supplied, the
462   path is prefixed with the current working directory. On Windows, a
463   drive name is prefixed, if necessary.
464
465   <LI> Leading '~' and environment variables (such as '$HOME') are
466   substituted by the appropriate value. If this substitution is not
467   possible (e.g. if the environment variable does not exist), nothing
468   is changed.
469
470   <LI> Special sequences such as '.', '..', extra '/' are appropriately
471   removed/replaced. 
472
473   <LI> The non-aliased path is returned, i.e. any symbolic links are
474   replaced by the non-symbolic linked version of the path.
475   
476   <LI> On Windows and Mac OS X, where different cases of letters in
477   path names are allowed but ignored (so e.g. \"foo\" and \"Foo\" are
478   aliases), the `normalised' version of the name, using the letter
479   cases when each file/directory was created, is returned
480   (not supported in older versions of Windows before 2000).
481
482   <LI> If the path denotes an existing directory, the canonical path
483   is terminated with a '/'.
484</UL>
485
486<P>
487   Not all components of Path need to exist.  The removal of aliasing
488   is performed only on the part of the path that does exist.
489
490<P>
491   The type of the returned CanonicalPath is the same as the type of
492   Path (string or atom).  If Path is empty, it is replaced by the
493   current working directory. 
494
495<P>
496    The predicates canonical_path_name/2 and existing_file/4 are intended
497    as replacement for absolute_file_name/2 in previous releases. The
498    functionality of completing an incomplete name and returning an
499    absolute path of absolute_file_name/2 has been separated. The following
500    approximately implements the old absolute_file_name/2:
501
502<PRE>
503    absolute_file_name(Rel, Abs) :-
504	(Rel == user ->
505	    Abs == user  % treat user specially
506	; get_flag(prolog_suffix, Sufs),
507	  (existing_file(Rel, Sufs, [], ExtRel) -> true ; ExtRel = Rel),
508	  canonical_path_name(ExtRel, Abs)
509        ).
510</PRE>
511
512
513"),
514    see_also: [existing_file/4, os_file_name/2, pathname/4],
515    eg:"\
516      [eclipse]: canonical_path_name(\"file\", Full).  %cwd is /homes/tom
517      Full = \"/homes/tom/file\"
518      yes
519
520      [eclipse]: canonical_path_name(file, Full).
521      Full = '/homes/tom/file'
522      yes
523
524      [eclipse]: canonical_path_name(\"~/file\", Full).
525      Full = \"/homes/tom/file\"
526      yes
527
528      [eclipse]: canonical_path_name('file/..', Full).
529      Full = '/homes/tom/'
530
531      [eclipse]: canonical_path_name('/users/tom', Full). 
532      % /users/tom is a symbolic link for /homes/tom
533      Full = '/homes/tom/'
534",
535      exceptions: [5: "Path is not a string or atom."]
536]).
537
538:- comment(existing_file/4, [
539      amode:(existing_file(++,++,++,-) is nondet),
540      args:  ["Base":        "The start of a file or path name (atom or string, possibly with a library/1 wrapper)",
541              "Completions": "Possible completions for Base (list of atomic elements)",
542              "Permissions": "Permissions (list of readable,writable,executable)",
543              "MatchedFile": "An existing file that matches the specification."
544             ],
545      summary: "Finds any existing file subject to the specified conditions.",
546      fail_if: "MatchedFile cannot be found.", 
547      resat: "Succeeds once for every matching file", 
548      exceptions: [5: "Base, Completions, Permissions not of right type.",
549                   6: "Base is an empty atom or string."
550		  ],
551      see_also: [canonical_path_name/2, get_flag/2, os_file_name/2, pathname/4],
552      eg:      "
553Success: 
554
555      % Trying different file extensions, including the empty one:
556      ?- existing_file(\"hello\", [\".ecl\",\".txt\",\"\"], [], File).
557      File = \"hello.txt\"     More? (;) 
558      No (0.00s cpu)         % assuming hello.ecl and hello do not exist
559
560      % Looking for one of several files in the parent directory:
561      ?- existing_file(\"../\", [\"a.txt\",\"b.txt\",\"c.txt\"], [readable], File).
562      File = \"../a.txt\"     More? (;) 
563      File = \"../c.txt\"     More? (;) 
564      No (0.00s cpu)        % assuming b.txt does not exist or is not readable
565
566      % Looking for a precompiled library:
567      ?- existing_file(library(fd), [\".eco\"], [readable], File).
568      File = '/homes/ks15/Eclipse/lib/fd.eco'     More? (;) 
569      No (0.00s cpu)
570
571      % Looking for source files:
572      ?- get_flag(prolog_suffix, Exts),
573         existing_file(\"hello\", Exts, [readable], File).
574      File = \"hello.ecl\"     More? (;) 
575      No (0.00s cpu)
576
577      % Looking for different file names:
578      [eclipse 1]: existing_file(test, [1,2,3], [], File).
579      File = test1     More? (;) 
580      File = test3     More? (;) 
581      No (0.00s cpu)
582
583Failure:
584
585      [eclipse 1]:  existing_file(library(fd), [], [readable], File).
586      % no Completions at all; will always fail
587
588      [eclipse 1]:  existing_file(library(fd), [\"\"], [readable], File).
589      % no library file with just 'fd' as the name (file has a suffix)
590",
591
592      desc: html("\
593    This predicate will search for any existing files that match the
594    specifications given in the first three arguments: the file starts with
595    Base, which is an absolute or relative partial file name.  Possible
596    completions (usually file extensions) given in Completions are appended
597    to Base, in the order they are given, to give a complete name.
598    If a proper file (i.e. non-directory) with this name exists, the
599    ECLiPSe process's permission for this file are checked against the
600    Permissions list (readable, writable, executable).  If the
601    permissions match, then the filename is returned in MatchedFile.
602    
603<P>
604    Base may have a library/1 wrapper around the name.  If this is
605    used, the file is searched for in the directories specified in
606    library path (including any subdirectory with the same name as
607    given in the library/1 wrapper, i.e. we check for both lib/foo.eco
608    and lib/foo/foo.eco).  The search order is the order in which the
609    library directories appear in the library_path flag of get_flag/2,
610    and for each directory, the completions are tried in the order in
611    which they appear in the list Completions.
612
613    All matching files are returned via backtracking.  If only the
614    first one is required, use once/1.
615
616<P>
617    MatchedFile is the same type as Base (atom or string).  Also, if 
618    Base is a relative (absolute) pathname, then so is MatchedFile.
619    If Base starts with '~' or enviroment variables (specified with a
620    leading '$'), these are substituted.  If the library(...) wrapper
621    is used, the proper library path is substituted.
622
623    Note that the executable permission for Windows may be approximate,
624    because Windows (especially Vista) has a different system for
625    dealing with execute permission.
626    
627<P>
628    The predicates canonical_path_name/2 and existing_file/4 are intended
629    as replacement for absolute_file_name/2 in previous releases. The
630    functionality of completing an incomplete name and returning an
631    absolute path of absolute_file_name/2 has been separated. The following
632    approximately implements the old absolute_file_name/2:
633
634<PRE>
635    absolute_file_name(Rel, Abs) :-
636	(Rel == user ->
637	    Abs == user
638	; get_flag(prolog_suffix, Sufs),
639	  (existing_file(Rel, Sufs, [], ExtRel) -> true ; ExtRel = Rel),
640	  canonical_path_name(ExtRel, Abs)
641        ).
642</PRE>
643
644")]).
645
646:- comment(errno_id / 1, [
647	summary:"Message is bound to the message string that corresponds to most recent
648operating system error that occurred during the execution.
649
650",
651	amode:(errno_id(-) is det),
652	desc:html("   This predicate unifies Message with the string that corresponds to the
653   most recent operating system error that occurred during the execution.
654   These messages differ between different operating systems.
655   Operating system interface errors which occur within built-in predicates
656   are normally indicated by the predicate raising event 170
657   \"system interface error\". The event handler then retrieves the
658   error message using errno_id/1. The system remembers the last error
659   message until a new error occurs.
660
661<P>
662"),
663	args:["Message" : "Variable."],
664	exceptions:[5 : "Message is neither variable nor string."],
665	eg:"
666[eclipse 3]: delete(nofile).
667system interface error: No such file or directory in delete(nofile)
668
669[eclipse 4]: errno_id(Msg).
670Msg = \"No such file or directory\"
671yes.
672
673
674
675",
676	see_also:[set_event_handler / 2]]).
677
678:- comment(mkdir / 1, [
679	summary:"Create a directory/folder with the given name.
680
681",
682	amode:(mkdir(+) is det),
683	desc:html("   Used to create directories (folders) in the filesystem.
684   Path may be an absolute or relative name.
685
686<P>
687"),
688	args:["Path" : "An atom or a string."],
689	exceptions:[4 : "Path is not instantiated.", 5 : "Path is neither an atom nor a string."],
690	eg:"
691      [eclipse 1]: mkdir(tmpdir).
692
693      yes.
694      [eclipse 1]: mkdir(tmpdir).
695      system interface error: File exists in mkdir(tmpdir)
696
697
698
699",
700	see_also:[sh / 1, system / 1, exists / 1, delete / 1]]).
701
702:- comment(os_file_name / 2, [
703	summary:"Conversion between internal ECLiPSe file name and Operating
704System file name syntax.
705
706",
707	amode:(os_file_name(+,-) is det),
708	amode:(os_file_name(-,+) is det),
709	desc:html("   This predicate converts between internal (ECLiPSe) and external
710   (operating system) file names. It works in both directions. 
711
712<P>
713   
714
715<P>
716"),
717	args:["InternalName" : "String, atom or variable.", "ExternalName" : "String, atom or variable."],
718	exceptions:[4 : "Neither InternalName nor ExternalName are instantiated.", 5 : "InternalName or ExternalName are instantiated to something other than string or atom.", 5 : "InternalName or ExternalName are instantiated to different types."],
719	eg:"
720Success:
721    On UNIX:
722      [eclipse]: os_file_name(\"//a/b/c.def\", OS).
723      OS = \"//a/b/c.def\"
724      yes
725
726    On Windows:
727      [eclipse]: os_file_name(\"//a/b/c.def\", OS), write(OS).
728      a:\\b\\c.def
729      OS = \"a:\\\\b\\\\c.def\"
730      yes
731
732      [eclipse]: os_file_name(File, \"a:\\\\b\\\\c.def\").
733      File = \"//a/b/c.def\"
734      yes
735
736Error:
737      os_file_name(X, Y).                          (Error 4).
738      os_file_name(4, X).                          (Error 5).
739      os_file_name(\"/home/file\", '/home/file').    (Error 5).
740
741
742
743",
744	see_also:[existing_file / 4, pathname / 4]]).
745
746:- comment(cputime / 1, [
747	summary:"Succeeds if Time is the elapsed user cpu time in seconds.
748
749",
750	amode:(cputime(-) is det),
751	desc:html("   Used to find the elapsed user cpu time in seconds, it is equivalent to
752   statistics(times, [Time|_]).
753
754<P>
755   The cpu time is the `user' time i.e.  the CPU time used while executing
756   instructions in the user space of the calling process.
757
758<P>
759   Note that the granularity of the system clock is usually 1/60 or 1/50 of
760   a second.  Hence if you use cputime/1 to measure runtimes make sure that
761   the measured intervals are long enough.
762
763<P>
764   The time given by the ps command gives the sum of `user' time and
765   `system' time, which is the CPU time used by the system on behalf of the
766   calling process.
767
768<P>
769    Note that (like all predicates that return a number as their last
770    argument), this predicate can be used as a function inside arithmetic
771    expressions.
772"),
773	args:["Time" : "Float number or variable."],
774	exceptions:[5 : "Time is instantiated, but not to a float."],
775	eg:"
776Success:
777   [eclipse]: cputime(T).
778   T = 0.0333333
779   yes.
780
781Fail:
782      cputime(0.000001).
783Error:
784      cputime(2).                    (Error 5).
785
786
787
788",
789	see_also:[statistics / 0, statistics / 2, date / 1, get_flag / 2]]).
790
791:- comment(date / 1, [
792	summary:"Date is bound to the string giving the date and time.
793
794",
795	amode:(date(-) is det),
796	desc:html("   Unifies Date with the current date and time.
797
798<P>
799"),
800	args:["Date" : "Variable or string."],
801	exceptions:[5 : "Date is instantiated, but not to a string."],
802	eg:"
803Success:
804      [eclipse]: date(Date).
805      Date = \"Fri Aug  25 12:00:00 1989\\n\"
806      yes.
807
808Fail:
809      date(\"Fri Aug  24 12:00:00 1989\\n\").
810
811Error:
812      date(thursday).                (Error 5).
813
814
815
816",
817	see_also:[get_flag/2, local_time/8, local_time_string/3, library(calendar)]]).
818
819:- comment(exec / 2, [
820	summary:"A child process Command is forked, its standard streams are connected to
821Streams and the ECLiPSe process waits until it terminates.
822
823",
824	amode:(exec(++,++) is det),
825	desc:html("   This predicate is used to fork a child process and to set up pipes to
826   its standard streams.  After the process is forked, ECLiPSe blocks, i.e.
827   it waits until the child process terminates.
828
829<P>
830   Command should be a list with at least one element: The first list element
831   (a path name in ECLiPSe path name syntax, atom or string) specifies the
832   program to be executed, and the subsequent list elements are its arguments.
833   The arguments can be atoms, strings or numbers.  They are passed to the
834   executed program literally (in particular, no path name syntax conversion
835   is applied).
836
837<P>
838   For backward compatibility, Command can be a simple atom or string, in
839   which case the first word in Command specifies the program to be executed,
840   and the following words are its command-line arguments.
841   This form is deprecated since it creates problems with argument quoting
842   and operating system dependent path name syntax.
843
844<P>
845   By specifying the Streams argument it is possible to control which of
846   the process' standard streams are connected to ECLiPSe streams.  The
847   form of Streams is [Stdin, Stdout, Stderr].  If some of these streams
848   are specified and not null, a pipe is opened which connects the standard
849   stream of the child process with the specified ECLiPSe stream, e.g.
850   Stdin must be an output stream because it is connected to the standard
851   input of the child process.  If the list Streams is shorter, only the
852   specified streams are connected with a pipe.  The streams can be
853   specified like for open/3.  If the stream is a variable, it is bound to
854   the physical stream number, if it is an atom different from null, that
855   symbolic stream is used.  Specifying a null stream means that no pipe is
856   set up for this stream.
857
858<P>
859   Each stream can also be specified as sigio(Stream) (UNIX systems only).
860   In this case a pipe is set up to the stream Stream and in addition the
861   pipe is instructed to send the signal io each time new data appears in
862   it.  In this way the two processes can communicate in a truly
863   asynchronous way.  When one process sends data to the other one, the
864   interrupt handler is invoked and it can read and process the data.  When
865   it finishes, it can continue where it was interrupted.
866
867<P>
868   exec(Command, Streams) is equivalent to
869
870<P>
871   exec(Command, Streams, Pid), wait(Pid, _)
872
873<P>
874   exec(Command, []) is very similar to system(Command).
875
876<P>
877"),
878	args:["Command" : "String, atom or list of atomic terms.", "Streams" : "List of stream ids."],
879	exceptions:[4 : "Command is not instantiated.", 5 : "Command is instantiated, but not to a string or an atom.", 5 : "Streams is instantiated, but not to a list.", 5 : "A stream in Streams is instantiated, but not to an atom.", 170 : "System error, it was not possible to fork the child or the    exec system call in the child failed.", 192 : "The specified stream is not open in the appropriate mode."],
880	eg:"
881Success:
882      % exec/2 wait for the child process
883      [eclipse]: exec(ls, []), write(end_exec).
884      aux.o           coroutine.pl    kegi.pl         sepia.o
885      bsi.pl          cprolog.pl      lint.pl         sorts.pl
886      cio.pl          history.pl      lists.pl        strings.pl
887      cn.pl           k_env.pl        quintus.pl      t_all.pl
888      end_exec
889      yes.
890
891      % exec/3 return immediately
892      [eclipse]: exec(ls, [], Pid), write(end_exec).
893      end_exec
894      Pid = 16054
895      yes.
896      [eclipse]: aux.o  coroutine.pl    kegi.pl         sepia.o
897      bsi.pl          cprolog.pl      lint.pl         sorts.pl
898      cio.pl          history.pl      lists.pl        strings.pl
899      cn.pl           k_env.pl        quintus.pl      t_all.pl
900
901Error:
902      exec(S, [output]).         (Error 4).
903      exec(ls, null).            (Error 5).
904      exec(chipc, [f(output)]).  (Error 5).
905      exec(date, [input]).       (Error 192).
906",
907	see_also:[call_c / 2, exec / 3, exec_group / 3, setenv/2, wait / 2, kill / 2, sh / 1, system / 1, open / 3]]).
908
909:- comment(exec / 3, [
910	summary:"A child process Command is forked, its standard streams are connected to
911Streams and its process ID is Pid.
912
913",
914	amode:(exec(++,++,-) is det),
915	desc:html("   This predicate is used to fork a child process and to set up pipes
916   to its standard streams.  After the process is forked, ECLiPSe
917   continues normally, without waiting for the child to terminate.
918
919<P>
920   Command should be a list with at least one element: The first list element
921   (a path name in ECLiPSe path name syntax, atom or string) specifies the
922   program to be executed, and the subsequent list elements are its arguments.
923   The arguments can be atoms, strings or numbers.  They are passed to the
924   executed program literally (in particular, no path name syntax conversion
925   is applied).
926
927<P>
928   For backward compatibility, Command can be a simple atom or string, in
929   which case the first word in Command specifies the program to be executed,
930   and the following words (separated by blank space) are its command-line
931   arguments.  This form is deprecated since it creates problems with argument
932   quoting and operating system dependent path name syntax.
933
934<P>
935   By specifying the Streams argument it is possible to control which of
936   the process' standard streams are connected to ECLiPSe streams.  The
937   form of Streams is [Stdin, Stdout, Stderr].  If some of these streams
938   are specified and not null, a pipe is opened which connects the standard
939   stream of the child process with the specified ECLiPSe stream, e.g.
940   Stdin must be an output stream because it is connected to the standard
941   input of the child process.  If the list Streams is shorter, only the
942   specified streams are connected with a pipe.  The streams can be
943   specified like for open/3.  If the stream is a variable, it is bound to
944   the physical stream number, if it is an atom different from null, that
945   symbolic stream is used.  Specifying a null stream means that no pipe is
946   set up for this stream.
947
948<P>
949   Each stream can also be specified as sigio(Stream) (UNIX systems only).
950   In this case a pipe is set up to the stream Stream and in addition the
951   pipe is instructed to send the signal io each time new data appears in
952   it.  In this way the two processes can communicate in a truly
953   asynchronous way.  When one process sends data to the other one, the
954   interrupt handler is invoked and it can read and process the data.  When
955   it finishes, it can continue where it was interrupted.
956
957<P>
958   After forking the process, Pid is unified with its process ID, which can
959   be used e.g.  in wait/2 or kill/2.  If the exec system call in the child
960   process failed, the child exits with status 128 + errno (Unix).
961
962<P>
963"),
964	args:["Command" : "String, atom or list of atomic terms.", "Streams" : "List of stream ids.", "Pid" : "Integer or a variable."],
965	exceptions:[4 : "Command is not instantiated.", 5 : "Command is instantiated, but not to a string or an atom.",5 : "Streams is instantiated, but not to a list.", 5 : "A stream in Streams is instantiated, but not to an atom or a    sigio structure.", 5 : "Pid is instantiated.", 170 : "System error, it was not possible to fork the child.", 192 : "The specified stream is not open in the appropriate mode."],
966	eg:"
967% execute an ls-command
968
969    ?- exec([ls,\"-C\"], [null, out], Pid).
970    Pid = 10885
971    yes.
972
973    ?- read_string(out, end_of_file, _, S), write(S).
974    aux.o           coroutine.pl    kegi.pl         sepia.o
975    bsi.pl          cprolog.pl      lint.pl         sorts.pl
976    cio.pl          history.pl      lists.pl        strings.pl
977    cn.pl           k_env.pl        quintus.pl      t_all.pl
978
979    S = \"...\"
980
981    ?- close(out), wait(Pid, S).
982    Pid = 10885
983    S = 0
984    yes.
985
986
987% execute another eclipse
988
989    ?- argv(0,Ecl),	% get name of the eclipse executable
990       exec([Ecl,\"-e\",\"read(X),Y is X*X,printf('%w. %b',[Y])\"], [in,out], P).
991
992    E = \"/usr/local/eclipse/bin/sparc_sunos5/eclipse.exe\"
993    P = 10741
994    yes.
995
996    [eclipse 2]: printf(in, '%w. %b', [12]), read(out, Result).
997    Result = 144
998    yes.
999
1000    [eclipse 3]: close(in), close(out), wait(10741, S).
1001    S = 0
1002    yes.
1003
1004
1005Error:
1006      exec(S, [], Pid).          (Error 4).
1007      exec([ls], null, Pid).       (Error 5).
1008      exec([chipc], [1], P).       (Error 5).
1009      exec([date], [input], P).    (Error 192).
1010",
1011	see_also:[exec / 2, exec_group / 3, setenv/2, wait / 2, kill / 2, sh / 1, system / 1, open / 3]]).
1012
1013:- comment(exec_group / 3, [
1014	summary:"A child process Command is forked in a new process group, its standard
1015streams are connected to Streams and its process ID is Pid.
1016
1017",
1018	amode:(exec_group(++,++,-) is det),
1019	desc:html("\
1020   UNIX:  This predicate is used to fork a child process in its own
1021   process group and to set up pipes to its standard streams.  After
1022   the process is forked, ECLiPSe continues normally, without waiting
1023   for the child to terminate.
1024   
1025<P>
1026   Command should be a list with at least one element: The first list element
1027   (a path name in ECLiPSe path name syntax, atom or string) specifies the
1028   program to be executed, and the subsequent list elements are its arguments.
1029   The arguments can be atoms, strings or numbers.  They are passed to the
1030   executed program literally (in particular, no path name syntax conversion
1031   is applied).
1032
1033<P>
1034   For backward compatibility, Command can be a simple atom or string, in
1035   which case the first word in Command specifies the program to be executed,
1036   and the following words are its command-line arguments.
1037   This form is deprecated since it creates problems with argument quoting
1038   and operating system dependent path name syntax.
1039
1040<P>
1041   By specifying the Streams argument it is possible to control which of
1042   the process' standard streams are connected to ECLiPSe streams.  The
1043   form of Streams is [Stdin, Stdout, Stderr].  If some of these streams
1044   are specified and not null, a pipe is opened which connects the standard
1045   stream of the child process with the specified ECLiPSe stream, e.g.
1046   Stdin must be an output stream because it is connected to the standard
1047   input of the child process.  If the list Streams is shorter, only the
1048   specified streams are connected with a pipe.  The streams can be
1049   specified like for open/3.  If the stream is a variable, it is bound to
1050   the physical stream number, if it is an atom different from null, that
1051   symbolic stream is used.  Specifying a null stream means that no pipe is
1052   set up for this stream.
1053
1054<P>
1055   Each stream can also be specified as sigio(Stream) (UNIX systems only).
1056   In this case a pipe is set up to the stream Stream and in addition the
1057   pipe is instructed to send the signal io each time new data appears in
1058   it.  In this way the two processes can communicate in a truly
1059   asynchronous way.  When one process sends data to the other one, the
1060   interrupt handler is invoked and it can read and process the data.  When
1061   it finishes, it can continue where it was interrupted.
1062
1063<P>
1064   After forking the process, Pid is unified with its process ID, which can
1065   be used e.g.  in wait/2 or kill/2.  If the exec system call in the child
1066   process failed, the child exits with status 128 + errno.
1067
1068<P>
1069   As oppsed to exec/3, the child process is created in a new process group
1070   (UNIX), and as a consequence does not get the interrupt, hangup and kill
1071   signals sent to the parent.  This feature might be needed if e.g. a
1072   separate ECLiPSe process is forked which should not be influenced when
1073   the user types Ctrl-C to the main ECLiPSe process.
1074"),
1075	args:["Command" : "String, atom or list of atomic terms.", "Streams" : "List of stream ids.", "Pid" : "Integer or a variable."],
1076	exceptions:[4 : "Command is not instantiated.", 5 : "Command is instantiated, but not to a string or an atom.", 5 : "Streams is instantiated, but not to a list.", 5 : "A stream in Streams is instantiated, but not to an atom or a    sigio structure.", 5 : "Pid is instantiated, but not to an integer.", 170 : "System error, it was not possible to fork the child.", 192 : "The specified stream is not open in the appropriate mode."],
1077	eg:"
1078Success:
1079      % the child process does not get the signal if ^C is typed
1080      [eclipse]: exec_group(eclipse, [output], Pid).
1081
1082      Pid = 11459
1083      yes.
1084      [eclipse]:
1085      ECLiPSe Constraint Logic Programming System [kernel]
1086      Kernel and basic libraries copyright Cisco Technology Inc
1087      Academic licensing through Imperial College London, see legal/licence_acad.txt
1088      GMP library copyright Free Software Foundation, see legal/lgpl.txt
1089      For other libraries see their individual copyright notices
1090      Version 5.8 #72, Fri Nov 26 00:12 2004
1091      [eclipse]: ^C
1092      interruption: type a, b, c, e, or h for help : ?
1093
1094      % when exec/3 is used, both processes get the signal
1095      [eclipse]: exec(eclipse, [output], Pid).
1096
1097      Pid = 11440
1098      yes.
1099      [eclipse]:
1100      ECLiPSe Constraint Logic Programming System [kernel]
1101      Kernel and basic libraries copyright Cisco Technology Inc
1102      Academic licensing through Imperial College London, see legal/licence_acad.txt
1103      GMP library copyright Free Software Foundation, see legal/lgpl.txt
1104      For other libraries see their individual copyright notices
1105      Version 5.8 #72, Fri Nov 26 00:12 2004
1106      [eclipse]: ^C
1107
1108      interruption: type a, b, c, e, or h for help : ?
1109      interruption: type a, b, c, e, or h for help : ?
1110Error:
1111      exec_group(S, [], Pid).          (Error 4).
1112      exec_group(ls, null, Pid).       (Error 5).
1113      exec_group(chipc, [1], P).       (Error 5).
1114      exec_group(date, [input], P).    (Error 192).
1115
1116
1117
1118",
1119	see_also:[exec / 2, exec / 3, setenv/2, kill / 2, sh / 1, system / 1, open / 3, wait / 2]]).
1120
1121:- comment(exists / 1, [
1122	summary:"Succeeds if the file File (with absolute or relative pathname) exists.
1123File can be a directory.
1124
1125",
1126	amode:(exists(+) is semidet),
1127	desc:html("   Used to see if the file File exists.  File can be a directory.
1128   exists(File) is equivalent to get_file_info(File, mode, _).
1129
1130<P>
1131"),
1132	args:["File" : "Atom or string."],
1133	fail_if:"Fails if the file File (with absolute or relative pathname) does not exist",
1134	exceptions:[4 : "File is not instantiated.", 5 : "File is neither an atom nor a string."],
1135	eg:"
1136Success:
1137   [eclipse]: sh('ls myfile').
1138   myfile
1139   [eclipse]: exists(myfile).
1140   yes.
1141
1142   [eclipse]: sh('ls /home/user/workdir').
1143   myfile
1144   [eclipse]: exists('/home/user/workdir').
1145   yes.
1146
1147Fail:
1148   [eclipse]: sh('ls nofile').
1149   nofile not found
1150   [eclipse]: exists(nofile).
1151   no.
1152
1153Error:
1154   exists(File).                          (Error 4).
1155   exists([file]).                        (Error 5).
1156
1157
1158
1159",
1160	see_also:[existing_file/4, get_file_info / 3, sh / 1, system / 1, delete / 1, mkdir / 1]]).
1161
1162:- comment(exit / 1, [
1163	summary:"The Prolog session is ended and the specified status returned to the
1164operating system.
1165
1166",
1167	amode:(exit(+) is erroneous),
1168	desc:html("   Used to exit from the Prolog session.  If user_end/0 is defined and
1169   global, it is called.  All buffers are flushed, streams are closed and
1170   ECLiPSe exits.  The specified status code is returned to the operating
1171   system.  exit(0) is identical with halt.
1172
1173<P>
1174"),
1175	args:["Status" : "Integer"],
1176	exceptions:[4 : "Status is not instantiated.", 5 : "Status is instantiated to a non-integer."],
1177	eg:"
1178Success:
1179      [eclipse]: exit(5).
1180      csh% echo $status
1181      5
1182      csh%
1183
1184
1185
1186",
1187	see_also:[halt / 0, break / 0, pause / 0]]).
1188
1189:- comment(get_file_info / 3, [
1190	summary:"Succeeds if the file File (with absolute or relative pathname) exists and
1191the value of its attribute Attr unfies with Value.
1192
1193",
1194	amode:(get_file_info(+,-,-) is nondet),
1195	amode:(get_file_info(+,+,-) is semidet),
1196	desc:html("\
1197   This predicate is used to test the properties of a specified file.
1198   If Attr specifies one of the attributes listed below, then Value is
1199   unified with the attribute value on return.
1200   If Attr is a variable, the predicate on backtracking returns all
1201   attribute-value pairs that are relevant for the given file.
1202<P>
1203   The possible attributes and their meanings are:
1204<P>
1205<PRE>
1206    Attribute  Type        Meaning
1207   ---------------------------------------------------------
1208    mode       integer     file mode (see table below)
1209    size       integer     file size in bytes
1210    type       atom        file type: file,directory,link,socket,
1211                           fifo,char_device or block_device
1212
1213    device     integer     device number
1214    inode      integer     inode number (Unix)
1215    nlink      integer     number of links (Unix)
1216    uid        integer     user ID of the owner (Unix)
1217    uname      string      user name of the owner (Unix)
1218    gid        integer     group ID of the owner (Unix)
1219    gname      string      group name of the owner (Unix)
1220
1221    atime      integer     time of last access
1222    mtime      integer     time of last data modification
1223    ctime      integer     time of last status change
1224    adate      string      date of last access (text)
1225    mdate      string      date of last data modification (text)
1226    cdate      string      date of last status change (text)
1227
1228    readable   on/off      file is/isn't readable by this process
1229    writable   on/off      file is/isn't writable by this process
1230    executable on/off      file is/isn't executable by this process
1231</PRE>
1232   The *name attributes are string representation of the corresponding *id
1233   attributes.  The *date attributes are string representation of the
1234   corresponding *time attributes.  The time for the *time attributes is
1235   measured as seconds elapsed since 00:00:00 GMT, Jan 1, 1970.
1236<P>
1237   The flags readable, writable and executable indicate whether the running
1238   ECLiPSe process has the corresponding permissions on the file.  Note that
1239   the executable permission for Windows may be approximate, because Windows
1240   (especially Vista) has a different system for dealing with execute
1241   permission.
1242<P>
1243   The use of the 'mode' attribute and the following numbers is deprecated
1244   in favour of the 'type', 'readable', 'writable' and 'executable'
1245   attributes.  The meaning of the bits in the mode attribute is as follows:
1246<PRE>
1247 Mode     Meaning
1248------------------------------------------------
1249 8'170000 file type
1250 8'040000 directory
1251 8'020000 character special
1252 8'060000 block special
1253 8'100000 normal file
1254 8'120000 symbolic link
1255 8'140000 socket
1256------------------------------------------------
1257 8'004000 set user ID on execution
1258 8'002000 set group ID on execution
1259------------------------------------------------
1260 8'000700 owner access
1261 8'000400 read permission for owner
1262 8'000200 write permission for owner
1263------------------------------------------------
1264 8'000070 group access
1265 8'000040 read permission for group
1266 8'000020 write permission for group
1267------------------------------------------------
1268 8'000007 other access
1269 8'000004 read permission for others
1270 8'000002 write permission for others
1271 8'000001 execute/search permission for others
1272</PRE>
1273"),
1274	args:["File" : "Atom or string.", "Attr" : "Atom or variable.", "Value" : "Constant or variable."],
1275	fail_if:"Fails if the file File does not exist, or doesn't have the attribute Attr",
1276	exceptions:[4 : "File is not instantiated.", 5 : "File is neither an atom nor a string.", 5 : "Attr is instantiated but not to an atom.", 5 : "Value is instantiated but not to a constant."],
1277	eg:"
1278Success:
1279   is_directory(File) :-
1280        get_file_info(File, type, directory),
1281
1282
1283   % the same test via mode bits:
1284   is_directory(File) :-
1285        get_file_info(File, mode, Mode),
1286        Mode /\\ file_type =:= directory_flag.
1287
1288   file_type(8'170000).
1289   directory_flag(8'40000).
1290
1291
1292   % A file is younger if its time is greater
1293   is_younger(File1, File2) :-
1294        get_file_info(File1, mtime) > get_file_info(File2, mtime).
1295
1296Fail:
1297   get_file_info(nofile, mode, Mode).
1298   get_file_info('/', mode, 8'100000).
1299
1300Error:
1301   get_file_info(File, ctime, T).                (Error 4).
1302   get_file_info([file], gid, G).                (Error 5).
1303   get_file_info(file, 1, X).                    (Error 5).
1304
1305
1306
1307",
1308	see_also:[exists / 1, delete / 1, exec / 3, local_time/8, local_time_string/3]]).
1309
1310:- comment(halt / 0, [
1311	summary:"The Prolog session is ended (the same as Control-D at the top-level loop).
1312
1313",
1314	amode:(halt is erroneous),
1315	desc:html("   Used to exit from the Prolog session.  If user_end/0 is defined and
1316   global, it is called.  All buffers are flushed, streams are closed and
1317   ECLiPSe exits.  Zero as status code is returned to the operating system.
1318   halt is identical with exit(0).
1319
1320<P>
1321"),
1322	args:[],
1323	eg:"
1324Success:
1325      [eclipse]: halt.
1326      cygnus% echo $status
1327      0
1328      cygnus%
1329
1330      [eclipse]: [user].
1331       problem_exit :-
1332          writeln(debug_output, 'PROBLEM IN RECOVERY PROCEDURE'),
1333          halt.
1334       user compiled 132 bytes in 0.02 seconds
1335      yes.
1336      [eclipse]: problem_exit.
1337      PROBLEM IN RECOVERY PROCEDURE
1338      %
1339
1340
1341
1342",
1343	see_also:[exit / 1, break / 0, pause / 0]]).
1344
1345:- comment(kill / 2, [
1346	summary:"Send the signal Signal to the process number Pid",
1347	amode:(kill(+,+) is semidet),
1348	desc:html("\
1349    Send the signal Signal to the process with process ID Pid.
1350    If Signal is 0, then only a check for existence of the process
1351    is performed, i.e. kill/2 fails if the process does not exist.
1352    A process ID of 0 can be used as a shorthand for the current process.
1353<P>
1354    This predicate is modelled after the UNIX system call kill(2).
1355    Signal names are derived from their official names by stripping
1356    SIG and using lower case, e.g. 'segv' for SIGSEGV.
1357<P>
1358    On Windows, a subset of the functionality is supported:
1359    <UL>
1360    <LI>Checking for process existence using signal 0</LI>
1361    <LI>Terminating a process using signal 'term'</LI>
1362    <LI>Sending signals 'abrt, 'fpe, 'ill, 'int, 'segv' or 'term'
1363	to the current process/LI>
1364    </UL>
1365<P>
1366"),
1367	args:["Pid" : "Integer", "Signal" : "Atom or Integer"],
1368	fail_if:"Fails if Signal is 0 and process Pid does not exist",
1369	exceptions:[4 : "Pid or Signal are not instantiated.",
1370	    5 : "Pid is instantiated to a non-integer.",
1371	    5 : "Signal is instantiated to neither an integer nor an atom.",
1372	    6 : "Signal is not a signal name or number.",
1373	    170 : "Pid or Signal has an invalid value.",
1374	    170 : "No permission to access process Pid."],
1375	eg:"
1376Success:
1377      [eclipse]: get_flag(pid, Pid), kill(Pid, 31).
1378      Signal 31
1379      Pid = 2929
1380      yes.
1381
1382      [eclipse]: kill(2929, 0)
1383      yes.
1384
1385      [eclipse]: kill(1234, term)
1386      yes.
1387Failure:
1388      [eclipse]: kill(9999, 0)
1389      no.
1390",
1391	see_also:[exec / 2, exec / 3, exec_group / 3, get_flag / 2, wait / 2]]).
1392
1393:- comment(pathname / 3, [
1394	summary:"If FilePath is a pathname of a file, succeed if Path is the pathname of its
1395parent directory and Name is the local file name.
1396
1397",
1398	amode:(pathname(+,-,-) is det),
1399	desc:html("   This predicate is used to decompose FilePath which is either a relative
1400   or absolute pathname of a file, into two components, namely the pathname
1401   of its parent directory including the trailing \"/\" if any, and the plain
1402   name of the file Name.
1403
1404<P>
1405"),
1406	args:["FilePath" : "String or atom.", "Path" : "Variable or string.", "Name" : "Variable or string."],
1407	exceptions:[4 : "FilePath is not instantiated.", 5 : "FilePath is neither a string nor an atom.", 5 : "Path is neither a string nor a variable.", 5 : "Name is neither a string nor a variable."],
1408	eg:"
1409Success:
1410      [eclipse]: pathname(\"/home/user/userfile\", P, F).
1411      P = \"/home/user/\"
1412      F = \"userfile\"
1413      yes.
1414
1415      pathname(\"/home/user\",\"/home/\").
1416      pathname(\"/home/\",\"/home/\",\"\").
1417      pathname(\"home\",\"\",\"home\").
1418
1419Fail:
1420      pathname(\"/home/file\",\"/home\",\"file\").
1421
1422Error:
1423      pathname(F,P,R).                 (Error 4).
1424      pathname(\"/home/file\",P,file)    (Error 5).
1425
1426
1427
1428",
1429	see_also:[pathname/4]]).
1430
1431:- comment(pathname / 4, [
1432	summary:"Decomposes a filename into its directory path, base name and suffix",
1433	amode:(pathname(+,-,-,-) is det),
1434	desc:html("\
1435   This predicate is used to decompose FilePath which is either a relative
1436   or absolute pathname of a file, into three components, namely the pathname
1437   of its parent directory including the trailing \"/\" if any, the `base'
1438   name of the file (the plain file name without the suffix), and the
1439   suffix, if any. The concatenation of Path, BaseName and Suffix yields
1440   the original filename FilePath.
1441"),
1442	args:["FilePath" : "String or atom.", 
1443              "Path" : "Variable or string.", 
1444              "BaseName" : "Variable or string.",
1445              "Suffix" : "Variable or string."],
1446	exceptions:[4 : "FilePath is not instantiated.",
1447	    5 : "FilePath is neither a string nor an atom.",
1448	    5 : "Path, BaseName or Suffix is neither a string nor a variable."],
1449	eg:"
1450Success:
1451
1452     [eclipse]: pathname(\"/home/user/userfile.pl\", P, B, S).
1453
1454     P = \"/home/user/\"
1455     B = \"userfile\"
1456     S = \".pl\"
1457     yes.
1458
1459      [eclipse]: pathname(\"/home/user/userfile\", P, B, S).
1460      P = \"/home/user/\"
1461      B = \"userfile\"
1462      S = \"\"
1463      yes.
1464
1465Fail:
1466      pathname(\"/home/file.pl\",\"/home/\",\"file\", \"pl\").
1467
1468Error:
1469      pathname(F,P,R,S).                 (Error 4).
1470      pathname(\"/home/file.pl\",P,file,'.pl')    (Error 5).
1471
1472
1473
1474",
1475	see_also:[pathname/3, split_string/4, join_string/3, canonical_path_name/2]]).
1476
1477:- comment(read_directory / 4, [
1478	index:[directory,folder],
1479	summary:"Unifies SubdirList with a list of subdirectories and FileList with a list
1480of matching files in the specified directory.
1481
1482",
1483	amode:(read_directory(+,+,-,-) is det),
1484	desc:html("   read_directory/4 scans the directory specified by Directory.  It
1485   collects the names of the subdirectories in SubdirList and the names of
1486   the files matching Pattern in FileList.  SubdirList and FileList are
1487   lists of strings.  Pattern is a string containing a filename
1488   specification similar to the usual UNIX convention.  The metacharacters
1489   recognised are:  * matches an arbitrary sequence of characters, ?
1490   matches any single character, [] matches one of the characters inside
1491   the brackets unless the first one is a ^ in which case it matches any
1492   character but those inside the brackets.
1493
1494<P>
1495   Filenames beginning with a dot are not suppressed by default, but the
1496   directories \".\" and \"..\" are omitted from SubdirList.
1497
1498<P>
1499"),
1500	args:["Directory" : "Atom or String", "Pattern" : "Atom or String", "SubdirList" : "Free variable or (maybe partial) list of strings", "FileList" : "Free variable or (maybe partial) list of strings"],
1501	exceptions:[4 : "Directory or Pattern is not instantiated.", 5 : "Directory or Pattern is neither atom nor string.", 5 : "SubdirList or FileList are instantiated, but not to lists.", 170 : "An error occurred trying to access Directory."],
1502	eg:"
1503   Success:
1504   [eclipse]: read_directory(\"/usr/john\", \"*\", Dirlist, Filelist).
1505   Dirlist = [\"subdir1\", \"subdir2\"]
1506   Filelist = [\"one.c\", \"two.c\", \"three.pl\", \"four.pl\"]
1507   yes.
1508   [eclipse]: read_directory(., \"[^t]*.pl\", Dirlist, Filelist).
1509   Dirlist = [\"subdir1\", \"subdir2\"]
1510   Filelist = [\"four.pl\"]
1511   yes.
1512   Fail:
1513   [eclipse]: read_directory(\".\", \"*.c\", _, [\"one.c\"]).
1514   no.
1515   Error:
1516   read_directory(_, \"*\", Dirs, Files).          (error 4)
1517   read_directory([46], \"*\", Dirs, Files).       (error 5)
1518   read_directory(\".\", _, Dirs, Files).          (error 4)
1519   read_directory(\".\", 3, Dirs, Files).          (error 5)
1520   read_directory(\".\", \"*.pl\", Dirs, file).      (error 5)
1521   read_directory(\"/private\", \"*\", _, Files).    (error 170)
1522
1523
1524    % EXAMPLE: find_tree(+Root, +Pattern, -ListOfRelativeFiles)
1525    % Recursively find all files matching Pattern below the directory
1526    % or list of directories Roots.
1527
1528    find_tree(Root, Pattern, AllFiles) :- (atom(Root);string(Root)), !,
1529	    find_dir(Root, \"\", \"\", Pattern, AllFiles, []).
1530    find_tree(Roots, Pattern, AllFiles) :-
1531	    find_tree(Roots, Pattern, AllFiles, []).
1532
1533    find_tree([], _Pattern, AllFiles, AllFiles).
1534    find_tree([Root|Roots], Pattern, AllFiles, AllFiles0) :-
1535	    find_dir(Root, \"\", \"\", Pattern, AllFiles, AllFiles1),
1536	    find_tree(Roots, Pattern, AllFiles1, AllFiles0).
1537
1538    find_dir(_, _, [], _, AllFiles, AllFiles) :- !.
1539    find_dir(Root, RelPath, [Dir|Dirs], Pattern, AllFiles, AllFiles0) :- !,
1540	    find_dir(Root, RelPath, Dir, Pattern, AllFiles, AllFiles1),
1541	    find_dir(Root, RelPath, Dirs, Pattern, AllFiles1, AllFiles0).
1542    find_dir(Root, RelPath, Dir, Pattern, AllFiles, AllFiles0) :-
1543	    ( RelPath==\"\" -> RelDir=Dir
1544	    ; concat_string([RelPath,/,Dir], RelDir) ),
1545	    ( RelDir==\"\" -> AbsDir=Root
1546	    ; concat_string([Root,/,RelDir], AbsDir) ),
1547	    read_directory(AbsDir, Pattern, SubDirs, Files),
1548	    find_files(Root, RelDir, Files, AllFiles, AllFiles1),
1549	    find_dir(Root, RelDir, SubDirs, Pattern, AllFiles1, AllFiles0).
1550
1551    find_files(_, _, [], AbsFiles, AbsFiles).
1552    find_files(Root, RelDir, [File|Files], [AbsFile|AbsFiles], AbsFiles0) :-
1553	    ( RelDir==\"\" -> concat_string([Root,/,File], AbsFile)
1554	    ; concat_string([Root,/,RelDir,/,File], AbsFile) ),
1555	    find_files(Root, RelDir, Files, AbsFiles, AbsFiles0).
1556",
1557	see_also:[cd / 1, getcwd / 1, get_flag / 2, pathname / 4, existing_file/4, exists / 1, mkdir / 1]]).
1558
1559:- comment(sh / 1, [
1560	summary:"The string or atom ShellCommand is passed as a command to the operating
1561system, and the command is executed there (it is a synonym for system/1).
1562
1563",
1564	amode:(sh(+) is semidet),
1565	desc:html("   Used to send a command ShellCommand to the operating system.  The
1566   command uses the streams input, output and error as the UNIX streams
1567   stdin, stdout and stderr respectively.  ECLiPSe -specific streams, like
1568   null or a string stream, can not be used.
1569
1570<P>
1571"),
1572	args:["ShellCommand" : "String or atom."],
1573	fail_if:"Fails if the Shell couldn't be executed or if the command returned a non-zero status",
1574	exceptions:[4 : "ShellCommand is not instantiated.", 5 : "ShellCommand is instantiated, but not to a string or atom."],
1575	eg:"
1576Success:
1577      [eclipse]: sh('ls -F').
1578      file1       dir1/
1579      yes.
1580
1581      [eclipse]: sh(date).
1582      Fri Aug  25 12:00:00 MET DST 1989
1583      yes.
1584
1585      [eclipse]: sh(\"cd ..\").
1586      yes.
1587
1588      [eclipse]: sh('which eclipse').
1589      /home/user/eclipse
1590      yes.
1591
1592Error:
1593      sh(S).                     (Error 4).
1594      sh(40).                    (Error 5).
1595
1596
1597
1598",
1599	see_also:[exec / 2, exec / 3, exec_group / 3, setenv/2, wait / 2]]).
1600
1601:- comment(system / 1, [
1602	summary:"The string or atom ShellCommand is passed as a command to the operating
1603system, and the command is executed there (it is a synonym for sh/1).
1604
1605",
1606	amode:(system(+) is semidet),
1607	desc:html("   Used to send a command ShellCommand to the operating system.  The
1608   command uses the streams input, output and error as the UNIX streams
1609   stdin, stdout and stderr respectively.  ECLiPSe -specific streams, like
1610   null or a string stream, can not be used.
1611
1612<P>
1613"),
1614	args:["ShellCommand" : "String or atom."],
1615	fail_if:"Fails if the Shell couldn't be executed or if the command returned a non-zero status",
1616	exceptions:[4 : "ShellCommand is not instantiated.", 5 : "ShellCommand is instantiated, but not to a string or atom."],
1617	eg:"
1618Success:
1619      [eclipse]: system('ls -F').
1620      file1       dir1/
1621      yes.
1622
1623      [eclipse]: system(date).
1624      Fri Aug  25 12:00:00 MET DST 1989
1625      yes.
1626
1627      [eclipse]: system(\"cd ..\").
1628      yes.
1629
1630      [eclipse]: system('which eclipse').
1631      /home/user/eclipse
1632      yes.
1633
1634Error:
1635      system(S).                     (Error 4).
1636      system(40).                    (Error 5).
1637
1638
1639
1640",
1641	see_also:[exec / 2, exec / 3, exec_group / 3, setenv/2, sh / 1, wait / 2]]).
1642
1643:- comment(wait / 2, [
1644	summary:"Wait for a child process to terminate and report its process ID and status.",
1645	amode:(wait(+,-) is semidet),
1646	amode:(wait(-,-) is nondet),
1647	desc:html("\
1648   This predicate is used to make the ECLiPSe process wait until a
1649   child process (created e.g. by exec/3 and identified by its process id Pid)
1650   terminates.  Status is unified with the child process exit status.
1651<P>
1652   A child process created with exec/3 still exists in the operating system
1653   even after it exits, as long as it was not waited for.  Therefore it is
1654   advisable to use a wait/2 call after every exec/3 (note that exec/2 waits
1655   for the child process internally).
1656<P>
1657   <B>UNIX specific behaviour:</B>
1658   The predicate can be invoked with Pid uninstantiated. In this case it will
1659   be resatisfiable and succeed once for every child process that terminates,
1660   as soon as a child process terminates, as long as there are child processes.
1661<P>
1662   If the child process created by exec/3 or exec_group/3 could not be
1663   executed, the child exits with status 128 + errno.
1664<P>
1665   When wait/2 is interrupted by a signal, the signal handler will be allowed
1666   to execute, and if it does not abort, wait/2 will be restarted subsequently.
1667<P>
1668   When the child process terminated normally, then Status is the value
1669   that the child process exited with, multiplied by 256 (see wait(2)).
1670<P>
1671   <B>WINDOWS specific behaviour:</B>
1672   The predicate can only be used to wait for one specific process, i.e. the
1673   Pid argument must be instantiated and the predicate is not resatisfiable.
1674<P>
1675   When the child process terminated normally, then Status is the value
1676   that the child process exited with.
1677"),
1678	args:["Pid" : "Integer or variable", "Status" : "Integer or variable"],
1679	fail_if:"Fails if there are no child processes or the specified process does not exist",
1680	exceptions:[5 : "Pid or Status are instantiated to non-integers."],
1681	eg:"
1682Success:
1683    [eclipse]: exec([true], [], Pid), wait(Pid, Status).
1684    Pid = 3417
1685    Status = 0
1686    Yes (0.00s cpu)
1687
1688    [eclipse]: exec([true], [], Pid), exec([date], [], Pid2), wait(Pid2, S2).
1689    Thu May 17 16:58:45 MET DST 1990
1690
1691    Pid = 10617
1692    Pid2 = 10618
1693    S2 = 0
1694    Yes (0.00s cpu)
1695
1696
1697    % Unix only
1698    [eclipse 7]: exec([true],[],Pid1), exec([true],[],Pid2), wait(P,S).
1699
1700    Pid1 = 13718
1701    Pid2 = 13719
1702    P = 13718
1703    S = 0
1704    More (0.00s cpu) ? ;
1705
1706    Pid1 = 13718
1707    Pid2 = 13719
1708    P = 13719
1709    S = 0
1710    More (0.00s cpu) ? ;
1711
1712    No (0.00s cpu)
1713
1714
1715Fail:
1716    [eclipse]: exec(\"true\", [], Pid), wait(1111, S).
1717
1718    No (0.00s cpu)
1719
1720
1721Example (UNIX only):
1722
1723    % Kill the process in case the wait is aborted,
1724    % e.g. due to a timeout or after-event handler
1725
1726    wait_with_cleanup(Pid, Status) :-
1727	catch(
1728	    wait(Pid, Status),
1729	    Tag,
1730	    ( kill(Pid, 2), wait(Pid, _), throw(Tag) )
1731	).
1732",
1733	see_also:[exec / 2, exec / 3, exec_group / 3, kill / 2, sh / 1]]).
1734
1735
1736:- comment(local_time / 8, [
1737    summary:"Conversion between local time and universal time",
1738    amode:(local_time(+,+,+,+,+,+,?,-) is semidet),
1739    amode:(local_time(-,-,-,-,-,-,-,+) is det),
1740    args:[
1741	"Year" : "Integer or variable",
1742	"Month" : "Integer or variable",
1743	"Day" : "Integer or variable",
1744	"Hour" : "Integer or variable",
1745	"Minute" : "Integer or variable",
1746	"Second" : "Integer or variable",
1747	"DST" : "0, 1 or variable (daylight savings time flag)",
1748	"UnixTime" : "Variable or integer (seconds since 1/1/1970)"
1749	],
1750
1751    desc:html("\
1752	This predicate is used to convert between local time (taking
1753	into account time zone and daylight savings time settings) and
1754	UTC (Universal Coordinated Time, represented as 'Unix time', i.e.
1755	in seconds since 1970-01-01, 00:00).
1756	<P>
1757	The conversion works in both directions. If the UnixTime argument
1758	is instantiated, it gets converted to the local date and time, and
1759	the first 6 arguments get unified accordingly.
1760	<P>
1761	If the first 6 (or 7) arguments are instantiated, they will be
1762	interpreted under the current time zone and daylight savings time
1763	rules, and converted into 'Unix time', which is unified with the
1764	last argument.
1765	<P>
1766	In both directions, the DST argument can usually remain uninstantiated,
1767	and will be unified with 1 if the date specified is while daylight
1768	savings time is in effect, and 0 otherwise. Note however, that during
1769	the switch from summer to winter time, there is usually a one hour
1770	overlap, where the same time of day exists twice, once in summer and
1771	once in winter time.  In this case, when converting from local time
1772	to UTC, the caller should instantiate DST in order to disambiguate.
1773	<P>
1774	The predicate can also be used to test for valid local date and time:
1775	If the first 6 (or 7) arguments do not represent a valid date, the
1776	predicate fails.
1777	<P>
1778	This predicate is based on the POSIX localtime() and mktime() functions.
1779"),
1780	fail_if:"The first 7 arguments do not represent a valid date",
1781	exceptions:[
1782	    4 : "The arguments are insufficiently instantiated",
1783	    5 : "Any of the arguments is not of the expected numerical type",
1784	    6 : "UnixTime is out of range"],
1785	eg:"
1786    ?- get_flag(unix_time,T), local_time(Yr,Mo,Dy,Hr,Mi,Sc,Ds,T).
1787    Yr = 2003
1788    Mo = 4
1789    Dy = 4
1790    Hr = 16
1791    Mi = 38
1792    Sc = 30
1793    Ds = 1
1794    T = 1049470710
1795    Yes (0.00s cpu)
1796
1797    ?- local_time(2003,4,4,16,38,30,1,T).
1798    T = 1049470710
1799    Yes (0.00s cpu)
1800
1801    ?- local_time(2003,4,4,16,38,30,_,T).
1802    T = 1049470710
1803    Yes (0.00s cpu)
1804
1805    ?- local_time(2003,1,1,25,0,0,_,_).   % invalid hour
1806    No (0.00s cpu)
1807
1808    ?- local_time(2003,2,29,12,0,0,_,_).  % invalid date (no leap year)
1809    No (0.00s cpu)
1810
1811    % The following examples assume DST rules for Britain
1812    ?- local_time(2003,3,30,1,30,0,_,_).  % invalid time (skipped hour)
1813    No (0.00s cpu)
1814
1815    ?- local_time(2003,10,26,1,0,0,1,T).  % 1h before end of summer time
1816    T = 1067126400
1817    Yes (0.01s cpu)
1818
1819    ?- local_time(2003,10,26,1,0,0,0,T).  % 1 hour later
1820    T = 1067130000
1821    Yes (0.00s cpu)
1822",
1823	see_also:[date/1, local_time_string/3, library(calendar)]]).
1824
1825
1826:- comment(local_time_string / 3, [
1827    summary:"Create a string representation of the local time",
1828    amode:(local_time_string(+,+,-) is det),
1829    args:[
1830	"UnixTime" : "Integer (seconds since 1/1/1970)",
1831	"Format" : "String or Atom",
1832	"TimeString" : "Variable or string"
1833	],
1834
1835    desc:html("\
1836	This predicate converts UTC (Universal Coordinated Time, represented
1837	as 'Unix time', i.e. in seconds since 1970-01-01, 00:00) into a
1838	textual representation of the local time (taking into account time
1839	zone and daylight savings time settings), according to the given
1840	format string.
1841	<P>
1842	The format string is similar to the format string in the printf/2,3
1843	predicate, but accepts different format specifiers. The exact set of
1844	format specifiers available depends on the underlying operating
1845	system (refer to the description of strftime()), but the following
1846	are generally available:
1847	<DL>
1848	<DT><STRONG>%a</STRONG></DT>  <DD>Abbreviated weekday name for current locale
1849
1850	<DT><STRONG>%A</STRONG></DT>  <DD>Full weekday name for current locale
1851
1852	<DT><STRONG>%b</STRONG></DT>  <DD>Abbreviated month name for current locale
1853
1854	<DT><STRONG>%B</STRONG></DT>  <DD>Full month name for current locale
1855
1856	<DT><STRONG>%c</STRONG></DT>  <DD>Preferred date and time representation for current locale
1857
1858	<DT><STRONG>%d</STRONG></DT>  <DD>Day of month as decimal number (01-31)
1859
1860	<DT><STRONG>%H</STRONG></DT>  <DD>Hour in 24-hour format (00-23)
1861
1862	<DT><STRONG>%I</STRONG></DT>  <DD>Hour in 12-hour format (01-12)
1863
1864	<DT><STRONG>%j</STRONG></DT>  <DD>Day of year as decimal number (001-366)
1865
1866	<DT><STRONG>%m</STRONG></DT>  <DD>Month as decimal number (01-12)
1867
1868	<DT><STRONG>%M</STRONG></DT>  <DD>Minute as decimal number (00-59)
1869
1870	<DT><STRONG>%p</STRONG></DT>  <DD>Current locale's A.M./P.M. indicator for 12-hour clock
1871
1872	<DT><STRONG>%S</STRONG></DT>  <DD>Second as decimal number (00-59)
1873
1874	<DT><STRONG>%U</STRONG></DT>  <DD>Week of year (00-53), with first Sunday first day of week 01
1875
1876	<DT><STRONG>%w</STRONG></DT>  <DD>Weekday as decimal number (0-6, Sunday is 0)
1877
1878	<DT><STRONG>%W</STRONG></DT>  <DD>Week of year (00-53), with first Monday first day of week 01
1879
1880	<DT><STRONG>%x</STRONG></DT>  <DD>Date representation for current locale
1881
1882	<DT><STRONG>%X</STRONG></DT>  <DD>Time representation for current locale
1883
1884	<DT><STRONG>%y</STRONG></DT>  <DD>Year without century, as decimal number (00-99)
1885
1886	<DT><STRONG>%Y</STRONG></DT>  <DD>Year with century, as decimal number
1887
1888	<DT><STRONG>%Z</STRONG></DT>  <DD>Time-zone name or abbreviation, empty if time zone is unknown
1889
1890	<DT><STRONG>%%</STRONG></DT>  <DD>Percent sign
1891	</DL>
1892	<P>
1893	This predicate is based on POSIX strftime().
1894"),
1895	exceptions:[
1896	    4 : "UnixTime or Format are uninstantiated",
1897	    5 : "UnixTime, Format or TimeString are instantiated, but not strings"],
1898	eg:"
1899    ?- get_flag(unix_time, T), local_time_string(T, \"%c\", S).
1900    T = 1049564174
1901    S = \"Sat Apr 05 18:36:14 2003\"
1902    Yes (0.00s cpu)
1903
1904    ?- get_flag(unix_time, T),
1905	     local_time_string(T, \"We write the year %Y in time zone %Z\", S).
1906    T = 1049564247
1907    S = \"We write the year 2003 in time zone BST\"
1908    Yes (0.00s cpu)
1909",
1910	see_also:[date/1, local_time/8, library(calendar)]]).
1911
1912
1913
1914