Compare commits
488 Commits
srfi13and1
...
main
Author | SHA1 | Date |
---|---|---|
![]() |
9d89a7d69c | |
![]() |
3ba6ea5e66 | |
![]() |
635dfce646 | |
![]() |
be5b6b6d89 | |
![]() |
0671cdc0a8 | |
![]() |
83f6511386 | |
![]() |
14ad4d6e15 | |
![]() |
34898c9b91 | |
![]() |
a05217d045 | |
![]() |
cc84656633 | |
![]() |
a4727055dd | |
![]() |
df37fa6cae | |
![]() |
9c560cf537 | |
![]() |
0fb3d6da8e | |
![]() |
878e0399f0 | |
![]() |
0910ddd0c8 | |
![]() |
5a137fe9db | |
![]() |
a140727528 | |
![]() |
6219322ca8 | |
![]() |
7584f719cc | |
![]() |
baa65dee1d | |
![]() |
a40ff4b314 | |
![]() |
fae64212c8 | |
![]() |
ec5011339c | |
![]() |
9c57c12e53 | |
![]() |
2ff38c84a3 | |
![]() |
4306bc0899 | |
![]() |
cb6fb0d3cd | |
![]() |
24182ecc89 | |
![]() |
78acb87825 | |
![]() |
f900059893 | |
![]() |
f80604aeab | |
![]() |
1b0a6684c0 | |
![]() |
e4e3b0fd3d | |
![]() |
1602f0d114 | |
![]() |
32b0c4bea5 | |
![]() |
85003bce1d | |
![]() |
904e665772 | |
![]() |
c6974d921b | |
![]() |
ff9ab43494 | |
![]() |
32297ca3c9 | |
![]() |
d28653add1 | |
![]() |
dd46b8fa14 | |
![]() |
43f92bb30b | |
![]() |
2b1f26613a | |
![]() |
34b543229d | |
![]() |
b8d83b88b1 | |
![]() |
dae01f4eb7 | |
![]() |
1b0da3dba8 | |
![]() |
4dc199868e | |
![]() |
c1b9253b70 | |
![]() |
d17b4b675e | |
![]() |
daaa9c74fb | |
![]() |
0ec41adb9c | |
![]() |
beaaa677d3 | |
![]() |
99ddaa2744 | |
![]() |
a67626ddca | |
![]() |
89c1f4b11b | |
![]() |
92e4737c44 | |
![]() |
eb80e59280 | |
![]() |
8d5d52eefa | |
![]() |
66b041ddde | |
![]() |
bae0215386 | |
![]() |
7a078988b8 | |
![]() |
ed86561eb1 | |
![]() |
983662c680 | |
![]() |
bdf729c8a4 | |
![]() |
8af328d695 | |
![]() |
400bc57c41 | |
![]() |
294994dcf2 | |
![]() |
85630af86a | |
![]() |
3f23ce432c | |
![]() |
16e0fd5535 | |
![]() |
f65a314430 | |
![]() |
27e7fe6aff | |
![]() |
1feaae4536 | |
![]() |
2851172981 | |
![]() |
0f632e013b | |
![]() |
232ab91be9 | |
![]() |
86300b9693 | |
![]() |
d5b9761283 | |
![]() |
aaf66a22d8 | |
![]() |
76dd7b8b07 | |
![]() |
cd5b6280db | |
![]() |
92f61b75da | |
![]() |
7246ebf7b8 | |
![]() |
3c71783b76 | |
![]() |
f26c821aa2 | |
![]() |
c354a077ad | |
![]() |
a46c405889 | |
![]() |
cd47ff6c12 | |
![]() |
e13e0c7648 | |
![]() |
be633b2c6f | |
![]() |
3ad841660d | |
![]() |
b202a059d2 | |
![]() |
402082fc77 | |
![]() |
82bacc1e75 | |
![]() |
a0a785bdea | |
![]() |
0dab46ab66 | |
![]() |
7e82845fb8 | |
![]() |
90d43117bf | |
![]() |
64613d96db | |
![]() |
0d3f69124f | |
![]() |
239592923f | |
![]() |
05b0dc388c | |
![]() |
ab6acc957f | |
![]() |
42bd0f8c8b | |
![]() |
2ca8040914 | |
![]() |
f0e9ece68e | |
![]() |
7e1ad158c7 | |
![]() |
442db87f66 | |
![]() |
4c333f278b | |
![]() |
acc4ec41cb | |
![]() |
ebdb86c060 | |
![]() |
e0b3287da7 | |
![]() |
2413f9c763 | |
![]() |
96d9b0e068 | |
![]() |
1bb7a2e494 | |
![]() |
48a5f0516c | |
![]() |
0a0dd89ee7 | |
![]() |
8db3509687 | |
![]() |
3039de6af6 | |
![]() |
14fe107a7e | |
![]() |
c23ba5b0cb | |
![]() |
a195317fc8 | |
![]() |
eb65bdec23 | |
![]() |
9ceb9cf99a | |
![]() |
3997793299 | |
![]() |
67c5ae72a6 | |
![]() |
17695ee207 | |
![]() |
54ca902c67 | |
![]() |
ec63c53ee6 | |
![]() |
c266ffbf46 | |
![]() |
269b603081 | |
![]() |
3239ff9076 | |
![]() |
21ac090065 | |
![]() |
b24c0182c8 | |
![]() |
675bf91911 | |
![]() |
878c07f4c1 | |
![]() |
29c3ebf99a | |
![]() |
c55ec06130 | |
![]() |
65f6bdd35a | |
![]() |
a5f1300753 | |
![]() |
c7344577f3 | |
![]() |
7463169adf | |
![]() |
acb29ac3bc | |
![]() |
75dbb6c4bb | |
![]() |
6011c98e03 | |
![]() |
3d91476f54 | |
![]() |
2baee835a2 | |
![]() |
61cdf20586 | |
![]() |
cdfa775de7 | |
![]() |
b4c84222e7 | |
![]() |
2df502cd0a | |
![]() |
1eecb9c9c5 | |
![]() |
38c76cdf84 | |
![]() |
ff5d65fc30 | |
![]() |
1b7292cab3 | |
![]() |
402c617ec5 | |
![]() |
13dbef06b1 | |
![]() |
88aaa91880 | |
![]() |
4703ce142a | |
![]() |
0f1f30eaa1 | |
![]() |
ec30e65f2d | |
![]() |
178cfa8e2e | |
![]() |
0705774634 | |
![]() |
8764714a07 | |
![]() |
7f05d6d427 | |
![]() |
aff343acf5 | |
![]() |
0e3db5eab6 | |
![]() |
7c80405943 | |
![]() |
33c91d854d | |
![]() |
5b5f58bd70 | |
![]() |
41bf8dad3f | |
![]() |
5c5ae4dc99 | |
![]() |
aa5c661421 | |
![]() |
a304e9b7f9 | |
![]() |
1a2d8690ce | |
![]() |
73844bc6ee | |
![]() |
a4bbf1d2f6 | |
![]() |
b352d0e825 | |
![]() |
f30435d56f | |
![]() |
b0ea9017eb | |
![]() |
14869a846e | |
![]() |
8f6a17af48 | |
![]() |
9dddad54c3 | |
![]() |
b684a0e621 | |
![]() |
184ecf2ff8 | |
![]() |
032e9d099b | |
![]() |
906fceb86f | |
![]() |
0a32248ba8 | |
![]() |
0eb62ab5c5 | |
![]() |
0b4cfa8d21 | |
![]() |
0b90a5a030 | |
![]() |
33e3bc8c62 | |
![]() |
18e8530076 | |
![]() |
459658efa6 | |
![]() |
c89fb29390 | |
![]() |
0225bb0bf3 | |
![]() |
bf28f0aa86 | |
![]() |
4c26efe136 | |
![]() |
494787705d | |
![]() |
8233556820 | |
![]() |
db69cd677b | |
![]() |
1a1950d2f5 | |
![]() |
70679cd247 | |
![]() |
934905ed57 | |
![]() |
ddddd1d31b | |
![]() |
8c65247c28 | |
![]() |
0e28399b12 | |
![]() |
5e85d401b9 | |
![]() |
230263ee0d | |
![]() |
8d7dee0bfa | |
![]() |
417b6046f8 | |
![]() |
8d6805a733 | |
![]() |
2773441f05 | |
![]() |
101a61082f | |
![]() |
e989a744e4 | |
![]() |
6a7ecc38a1 | |
![]() |
b980922f0d | |
![]() |
0229b80a6c | |
![]() |
b02ac4dc83 | |
![]() |
66735d9c9e | |
![]() |
9ccd709a52 | |
![]() |
630f678236 | |
![]() |
bad528299e | |
![]() |
bf449b53b7 | |
![]() |
06eb60980d | |
![]() |
25aa2b845a | |
![]() |
a8e25a6827 | |
![]() |
14559b2b4a | |
![]() |
ae81b06f85 | |
![]() |
a620b7592a | |
![]() |
4ba01266de | |
![]() |
9f7d624413 | |
![]() |
ae7f18480d | |
![]() |
e945b99adf | |
![]() |
faa08159d0 | |
![]() |
1cdcaaee53 | |
![]() |
2f7c39be3f | |
![]() |
47c2eea2dd | |
![]() |
4dd24741a8 | |
![]() |
c0ab08bd2c | |
![]() |
d9bf36e0bd | |
![]() |
8e3073352a | |
![]() |
454808a9cd | |
![]() |
ea9745ee2f | |
![]() |
7e66a68afa | |
![]() |
52cd685e9a | |
![]() |
f96eafa42b | |
![]() |
02dd0ebf8d | |
![]() |
d4219d0d69 | |
![]() |
59f44e1e1f | |
![]() |
c92057dbdf | |
![]() |
5761b6ce03 | |
![]() |
cfdc457e2a | |
![]() |
1fb6c3634b | |
![]() |
1f8e0b5b2d | |
![]() |
6093fc8de2 | |
![]() |
85d516da9b | |
![]() |
afdeb4e958 | |
![]() |
f9cf771947 | |
![]() |
d6c2965b79 | |
![]() |
322ffcc8c8 | |
![]() |
8a8d647f69 | |
![]() |
122ab69030 | |
![]() |
d0fef5a49c | |
![]() |
2fe3ec94a7 | |
![]() |
99b82763bb | |
![]() |
a7e3221b90 | |
![]() |
5d8c6318a2 | |
![]() |
98af814b97 | |
![]() |
988940561b | |
![]() |
fd00b3e501 | |
![]() |
0d6cbfb5fa | |
![]() |
55a65c1b64 | |
![]() |
26b8de258e | |
![]() |
e45e9a6b0d | |
![]() |
3d90d39924 | |
![]() |
47fe4b82ae | |
![]() |
e73f5b04a7 | |
![]() |
81c9cebfc1 | |
![]() |
14f8b65a74 | |
![]() |
6f951db725 | |
![]() |
49c350a807 | |
![]() |
89f6fed034 | |
![]() |
c4c6a28385 | |
![]() |
871cfe32b5 | |
![]() |
7223f37439 | |
![]() |
16ec4521b5 | |
![]() |
78e07c9296 | |
![]() |
2deadc5f66 | |
![]() |
00b7fcaa3d | |
![]() |
0e67214944 | |
![]() |
7033702b2b | |
![]() |
4e05a0aaf1 | |
![]() |
d5b9e978b6 | |
![]() |
38ac713c41 | |
![]() |
5b10faa3a1 | |
![]() |
4fbb8e217f | |
![]() |
a06f2a9e34 | |
![]() |
a61145fa6a | |
![]() |
31e3c2e522 | |
![]() |
759e929fa8 | |
![]() |
2ecccd3546 | |
![]() |
d15cfee879 | |
![]() |
28f054b439 | |
![]() |
a91a7b8c4a | |
![]() |
4dc9707d7b | |
![]() |
912bf51c24 | |
![]() |
b64ae78af7 | |
![]() |
241fe9c520 | |
![]() |
391365171f | |
![]() |
2a34e9d53a | |
![]() |
c36b4abf3f | |
![]() |
6e52fcbdee | |
![]() |
c50650d7eb | |
![]() |
8fc03c01c8 | |
![]() |
894d4c32e9 | |
![]() |
5aa87bc9fe | |
![]() |
a44f8882e6 | |
![]() |
b4909649d4 | |
![]() |
b48e4874c5 | |
![]() |
0716fc06cd | |
![]() |
8adc0d3f5b | |
![]() |
f948e51831 | |
![]() |
e84440fecd | |
![]() |
70a1342cef | |
![]() |
aed6c163b8 | |
![]() |
dfda637610 | |
![]() |
ae2b8700e5 | |
![]() |
d16ad942c0 | |
![]() |
9610aeab66 | |
![]() |
46aa9a9424 | |
![]() |
d8d1758d11 | |
![]() |
0d7befeb82 | |
![]() |
aabe436bef | |
![]() |
4961de1b9b | |
![]() |
b5a653f1f3 | |
![]() |
d472115b34 | |
![]() |
75bad52dfe | |
![]() |
996ee5db33 | |
![]() |
060badffa7 | |
![]() |
c4927cc255 | |
![]() |
3b0a2e2fa5 | |
![]() |
1df0338fb0 | |
![]() |
464f44f2a3 | |
![]() |
975278b58b | |
![]() |
84c705fcc7 | |
![]() |
509fb5c6d1 | |
![]() |
e124c6906c | |
![]() |
66be6be3d5 | |
![]() |
6ea9a75721 | |
![]() |
6d8929b608 | |
![]() |
3595da3986 | |
![]() |
dd40a220df | |
![]() |
7a1e5a6da7 | |
![]() |
7e184be69d | |
![]() |
f1dc00dcf6 | |
![]() |
bcdc349bcf | |
![]() |
c34f9d6882 | |
![]() |
ea45fca8ef | |
![]() |
6b42e9d7aa | |
![]() |
1a0d6a2af4 | |
![]() |
16c0d2ef3f | |
![]() |
2c9e06d6ae | |
![]() |
acaaedd035 | |
![]() |
755913967b | |
![]() |
30ed9fdf0c | |
![]() |
702f0126c5 | |
![]() |
4a47a768c6 | |
![]() |
66cd45fa90 | |
![]() |
1265c62db8 | |
![]() |
7e41e4e5ad | |
![]() |
7d1bb41214 | |
![]() |
12d37bc045 | |
![]() |
772f47e595 | |
![]() |
4da524bd96 | |
![]() |
7ff0032887 | |
![]() |
87a9656f48 | |
![]() |
ef895cd9e3 | |
![]() |
97449f46e0 | |
![]() |
59ed6e6363 | |
![]() |
183446fd84 | |
![]() |
829514e091 | |
![]() |
0dd77af844 | |
![]() |
3cc0d1c5d7 | |
![]() |
ac54f7bf2c | |
![]() |
1f30a16c07 | |
![]() |
6167c04378 | |
![]() |
e43cea328d | |
![]() |
aa6ab5ae2c | |
![]() |
32452a37a9 | |
![]() |
eaa1802624 | |
![]() |
b62f12fe25 | |
![]() |
e075c5369c | |
![]() |
507631b689 | |
![]() |
6ed1d26e9d | |
![]() |
b8d0448d5e | |
![]() |
17041342f7 | |
![]() |
dc90559747 | |
![]() |
25916aa161 | |
![]() |
d30d0480f7 | |
![]() |
f9436a7dbf | |
![]() |
c749104691 | |
![]() |
1965c0f4b4 | |
![]() |
79f2098c6f | |
![]() |
77f1244a17 | |
![]() |
f471aa500d | |
![]() |
5d8af0d1f5 | |
![]() |
f872a245b5 | |
![]() |
d6991813b7 | |
![]() |
eed17d276f | |
![]() |
f83504cc00 | |
![]() |
fd3c209841 | |
![]() |
31f91e754b | |
![]() |
3a6b33db27 | |
![]() |
12874c0edd | |
![]() |
965a0da2f1 | |
![]() |
675f4c7746 | |
![]() |
37a38ee185 | |
![]() |
9e39aeaae4 | |
![]() |
b3dc61dae4 | |
![]() |
946798634a | |
![]() |
a84e466c05 | |
![]() |
93647a41c2 | |
![]() |
2f89a2be7d | |
![]() |
02f9587e06 | |
![]() |
27602d21de | |
![]() |
6e92a37c81 | |
![]() |
619c1adf2f | |
![]() |
4c2184f0a5 | |
![]() |
6f41ddcc98 | |
![]() |
611ac55bb7 | |
![]() |
846439590d | |
![]() |
ddf13b9e3d | |
![]() |
417048b418 | |
![]() |
9835f88c66 | |
![]() |
01fa9d6074 | |
![]() |
e6bdd7a001 | |
![]() |
278322565a | |
![]() |
5c383bb241 | |
![]() |
5f0c2bbf38 | |
![]() |
eab12ccf2c | |
![]() |
4de6752f24 | |
![]() |
00af71f77d | |
![]() |
579ee12924 | |
![]() |
737ebc5afe | |
![]() |
28ab57259a | |
![]() |
dce0dc36cd | |
![]() |
05df0d4773 | |
![]() |
325407b9fb | |
![]() |
8e510db64c | |
![]() |
79ee1de13c | |
![]() |
bd91c003cc | |
![]() |
abe91e9fd9 | |
![]() |
52061b82bd | |
![]() |
a991a0a4e6 | |
![]() |
6ff4d51074 | |
![]() |
b453a05b92 | |
![]() |
16a701b470 | |
![]() |
112a51bd10 | |
![]() |
e7460b6e74 | |
![]() |
80adbe0761 | |
![]() |
ef473e636e | |
![]() |
4b080b5a28 | |
![]() |
f244b7532f | |
![]() |
4ae0a89c53 | |
![]() |
bc338f2d53 | |
![]() |
d6c6a3030f | |
![]() |
17bca3eceb | |
![]() |
2ccc95ff78 | |
![]() |
7d810091d8 | |
![]() |
7c90829350 | |
![]() |
bd33154d9a | |
![]() |
1d62cb2182 | |
![]() |
7d2447407a | |
![]() |
b7bdb8528f | |
![]() |
083b345c2e | |
![]() |
3e52c5100b | |
![]() |
241344c36b | |
![]() |
0644d18c53 | |
![]() |
92b6357605 | |
![]() |
195691c438 | |
![]() |
9f189dde81 | |
![]() |
0ae16c8daa | |
![]() |
0f0db549f5 | |
![]() |
f927914f52 |
145
RELEASE
145
RELEASE
|
@ -9,12 +9,6 @@ release 0.5.3. (Emacs should display this document is in outline mode. Say
|
|||
c-h m for instructions on how to move through it by sections (e.g., c-c c-n,
|
||||
c-c c-p).)
|
||||
|
||||
This release is the first new release of scsh in over a year. We've been
|
||||
using it, and have had no problems. However, we only recommend eager users
|
||||
download it. We'll upgrade it to a 0.5.3 release after a week or two, when
|
||||
this release has been shaken out.
|
||||
|
||||
|
||||
* Contents
|
||||
==========
|
||||
What is scsh
|
||||
|
@ -27,6 +21,7 @@ The World-Wide What?
|
|||
New in this release
|
||||
Scsh is now "open source."
|
||||
Scsh is now on Win32
|
||||
Scsh is now on Mac OS X
|
||||
CVS repository will be public-readable
|
||||
New char-sets and char-set operations
|
||||
New regular expression system
|
||||
|
@ -39,7 +34,8 @@ Thanks
|
|||
* What is scsh
|
||||
==============
|
||||
Scsh is a broad-spectrum systems-programming environment for Unix embedded
|
||||
in R4RS Scheme.
|
||||
in R4RS Scheme. It has an open-source copyright, and runs on most major
|
||||
Unix systems.
|
||||
|
||||
** Scsh as a scripting language
|
||||
-------------------------------
|
||||
|
@ -107,11 +103,11 @@ Unix platforms. We currently have scsh implementations for:
|
|||
IRIX
|
||||
Linux
|
||||
NetBSD
|
||||
NeXTStep
|
||||
Solaris
|
||||
SunOS
|
||||
Ultrix
|
||||
Win32
|
||||
Darwin/Mac OS X
|
||||
|
||||
Scsh code should run without change across these systems.
|
||||
Porting to new platforms is usually not difficult.
|
||||
|
@ -153,74 +149,56 @@ at MIT.
|
|||
|
||||
Bugs can be reported to
|
||||
scsh-bugs@zurich.ai.mit.edu
|
||||
or via the Scsh project's bugs section on SourceForge:
|
||||
http://sourceforge.net/projects/scsh/
|
||||
|
||||
If you do not receive the alt netnews hierarchy, or wish to join the mailing
|
||||
If you do not netnews hierarchy, or wish to join the mailing
|
||||
list for other reasons, send mail to
|
||||
scsh-request@zurich.ai.mit.edu
|
||||
|
||||
|
||||
* The World-Wide What?
|
||||
======================
|
||||
We even have one of those URL things:
|
||||
http://www-swiss.ai.mit.edu/scsh/
|
||||
|
||||
We even have one of those dot-com cyberweb things:
|
||||
http://www.swiss.ai.mit.edu/ftpdir/scsh/
|
||||
We now manage the project using SourceForge:
|
||||
http://sourceforge.net/projects/scsh/
|
||||
|
||||
* New in this release
|
||||
=====================
|
||||
** Scsh is now "open source."
|
||||
We finally got around to tacking an ideologically hip copyright
|
||||
onto the source. (Not that we ever cared before what you did with
|
||||
the system...) The Scheme 48 authors have also graciously retrofitted
|
||||
a BSD-style open-source copyright onto the underlying Scheme 48 0.36
|
||||
platform for us. The whole system is now open source, top-to-bottom.
|
||||
|
||||
Take all the code you like; we'll just write more.
|
||||
|
||||
** Scsh is now on Win32
|
||||
Scsh will now build and run using Cygwin B20.1. This was only tested
|
||||
on Windows NT 4.0, but presumably things could work on other Cygwin
|
||||
platforms such as Win95 or Win98. Cygwin is available from:
|
||||
Scsh will now build and run using Cygwin 1.1. This was tested
|
||||
on Windows NT 4.0 and Windows 2000, but presumably things could work
|
||||
on other Cygwin platforms such as Win95 or Win98. Cygwin is available
|
||||
from:
|
||||
http://sourceware.cygnus.com/cygwin/
|
||||
|
||||
** CVS repository will be public-readable
|
||||
We will add further information to the web-site as soon as possible.
|
||||
** Scsh is now on Mac OS X
|
||||
Scsh does now support Darwin and thus Mac OS X. This was simply
|
||||
achived by treating Darwin as a BSD platform.
|
||||
|
||||
** New char-sets and char-set operations
|
||||
See the manual for more information on using character sets
|
||||
for text processing. Also, see the ccp package in scsh/scsh/lib
|
||||
for a new library providing character->character partial maps,
|
||||
which are also useful for general string processing.
|
||||
** CVS repository is now publically accessable
|
||||
The scsh sources have moved to scsh.sourceforge.net, and the
|
||||
the CVS repository is publically readable. Here's the magic:
|
||||
|
||||
** New regular expression system
|
||||
There's a whole new regexp package in scsh. There's a new,
|
||||
s-expression-based notation for regexps, called SRE's. The new
|
||||
notation has been integrated into the AWK macro and field-parser functions.
|
||||
The older Posix notation is still supported for backwards compatibility.
|
||||
cvs -d:pserver:anonymous@cvs.scsh.sourceforge.net:/cvsroot/scsh co scsh
|
||||
cvs -d:pserver:anonymous@cvs.scsh.sourceforge.net:/cvsroot/scsh co scsh-0.6
|
||||
|
||||
There's a whole chapter on regexps in the new manual; it has full details.
|
||||
|
||||
The previous AWK and field-reader system is provided in a
|
||||
backwards-compatibility package. See package obsolete-awk-package
|
||||
in scsh-package.scm.
|
||||
(The 0.6 source tree builds with a modern Scheme 48 and thread support.
|
||||
It has not been released.)
|
||||
|
||||
** New libraries
|
||||
The SRFI-1 list library is available, in the list-lib package.
|
||||
There is a large, powerful string-processing library available
|
||||
in the string-lib package. See the directory scsh/scsh/lib/ for
|
||||
documentation and source.
|
||||
Scsh now provides the SRFI-1, SRFI-13 and SRFI-14 libraries, giving
|
||||
portable support for list, string and character-set operations.
|
||||
|
||||
These libraries make basic list and string hacking very straightforward.
|
||||
|
||||
** Renaming
|
||||
We are shifting from a reduce-foo convention to a more standard
|
||||
foo-fold convention. This has caused the following renamings:
|
||||
reduce-char-set => char-set-fold
|
||||
reduce-port => port-fold
|
||||
The older names are still bound, but are deprecated and will likely
|
||||
go away in a future release.
|
||||
|
||||
String utilities INDEX and RINDEX are gone. Use the string-lib procedures
|
||||
instead.
|
||||
** Database access via ODBC
|
||||
Brian Carlstrom, Sam Thiebault and Olin Shivers have designed and
|
||||
implemented a portable interface to relational databases. The code
|
||||
back-ends to ODBC drivers for portability.
|
||||
|
||||
** Bugfixes
|
||||
Over a year's worth of bug fixes. In particular, the old problems with the
|
||||
|
@ -235,54 +213,25 @@ We would like to thank the members of local-resistance cells for the
|
|||
Underground everywhere for bug reports, bug fixes, design review and comments
|
||||
that were incorporated into this release. We really appreciate their help,
|
||||
particularly in the task of porting scsh to new platforms.
|
||||
|
||||
Alan Bawden
|
||||
Jim Blandy
|
||||
Per Bothner
|
||||
Tom Breton
|
||||
Christopher Browne
|
||||
Sean Doran
|
||||
Ray Dillinger
|
||||
Allyn Dimock
|
||||
Scott Draves
|
||||
Lutz Euler
|
||||
Kevin Esler
|
||||
Jeremy Fitzhardinge
|
||||
Noah Friedman
|
||||
Martin Gasbichler
|
||||
Andy Gaynor
|
||||
Ian Grant
|
||||
Eric Hanchrow
|
||||
Karl Hegbloom
|
||||
Johann Hibschman
|
||||
Ian Horswill & the Northwestern Scheme wizards
|
||||
Gary Houston
|
||||
Graham Hughes
|
||||
Jarmo Hurri
|
||||
Lars Kellogg-Stedman
|
||||
Andre Koehoerst
|
||||
Hannu Koivisto
|
||||
Shriram Krishnamurthi
|
||||
Jakob Lichtenberg
|
||||
Eric Marsden
|
||||
Peter C. Olsen
|
||||
Willliam Pippin
|
||||
David Rush
|
||||
Michael Schinz
|
||||
Manuel Serrano
|
||||
Mark Shirle
|
||||
Bill Somerfeld
|
||||
Mike Sperber
|
||||
Harvey J. Stein
|
||||
Pawel Turnau
|
||||
Rob Warnock
|
||||
Kenneth R. Westerback
|
||||
Friedrich Dominicus
|
||||
Jay Nietling
|
||||
Tim Bradshaw
|
||||
Robert Brown
|
||||
Eric Marsden
|
||||
Paul Emsley
|
||||
Pawel Turnau
|
||||
Hannu Koivisto
|
||||
Andy Gaynor
|
||||
Francisco Vides Fernandez
|
||||
Tim Burgess
|
||||
Brian Denheyer
|
||||
Harvey Stein
|
||||
Eric Hilsdale
|
||||
|
||||
We'd like to thank everyone else for their patience; this release seemed like
|
||||
a long time coming.
|
||||
|
||||
Brought to you by the Scheme Underground. Go forth and write elegant systems
|
||||
programs.
|
||||
-Olin Shivers, Brian Carlstrom & Martin Gasbichler
|
||||
Cambridge
|
||||
29 September 1999
|
||||
-Olin Shivers, Brian Carlstrom, Martin Gasbichler & Mike Sperber
|
||||
|
||||
|
|
3
Thanks
3
Thanks
|
@ -10,3 +10,6 @@ Post-0.5.2-release bug reports:
|
|||
Andy Gaynor
|
||||
Francisco Vides Fernandez
|
||||
Tim Burgess
|
||||
Brian Denheyer
|
||||
Harvey Stein
|
||||
Eric Hilsdale
|
||||
|
|
|
@ -16,10 +16,11 @@
|
|||
# rm /zu/bdc/ftp/scsh/README~
|
||||
#
|
||||
VERSION=-0.5.3
|
||||
FTPDIR=${HOME}/ftp/users/bdc
|
||||
FTPDIR=${HOME}/ftp/pub/scsh
|
||||
FTPDIR=${HOME}/ftp/pub/users/bdc
|
||||
|
||||
CVSROOT=/projects/express/scsh-cvs
|
||||
export CVSROOT
|
||||
#CVSROOT=/projects/express/scsh-cvs
|
||||
#export CVSROOT
|
||||
|
||||
TMPSPACE=${HOME}/tmp
|
||||
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,10 @@
|
|||
#! /bin/sh
|
||||
# Configuration validation subroutine script, version 1.1.
|
||||
# Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2001-03-09'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
# can handle that machine. It does not imply ALL GNU software can.
|
||||
|
@ -25,6 +29,8 @@
|
|||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Please send patches to <config-patches@gnu.org>.
|
||||
#
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
# If it is invalid, we print an error message on stderr and exit with code 1.
|
||||
|
@ -45,30 +51,73 @@
|
|||
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
|
||||
# It is wrong to echo any other type of specification.
|
||||
|
||||
if [ x$1 = x ]
|
||||
then
|
||||
echo Configuration name missing. 1>&2
|
||||
echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
|
||||
echo "or $0 ALIAS" 1>&2
|
||||
echo where ALIAS is a recognized configuration type. 1>&2
|
||||
exit 1
|
||||
fi
|
||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||
|
||||
# First pass through any local machine types.
|
||||
case $1 in
|
||||
*local*)
|
||||
echo $1
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
usage="\
|
||||
Usage: $0 [OPTION] CPU-MFR-OPSYS
|
||||
$0 [OPTION] ALIAS
|
||||
|
||||
Canonicalize a configuration name.
|
||||
|
||||
Operation modes:
|
||||
-h, --help print this help, then exit
|
||||
-t, --time-stamp print date of last modification, then exit
|
||||
-v, --version print version number, then exit
|
||||
|
||||
Report bugs and patches to <config-patches@gnu.org>."
|
||||
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
|
||||
help="
|
||||
Try \`$me --help' for more information."
|
||||
|
||||
# Parse command line
|
||||
while test $# -gt 0 ; do
|
||||
case $1 in
|
||||
--time-stamp | --time* | -t )
|
||||
echo "$timestamp" ; exit 0 ;;
|
||||
--version | -v )
|
||||
echo "$version" ; exit 0 ;;
|
||||
--help | --h* | -h )
|
||||
echo "$usage"; exit 0 ;;
|
||||
-- ) # Stop option processing
|
||||
shift; break ;;
|
||||
- ) # Use stdin as input.
|
||||
break ;;
|
||||
-* )
|
||||
echo "$me: invalid option $1$help"
|
||||
exit 1 ;;
|
||||
|
||||
*local*)
|
||||
# First pass through any local machine types.
|
||||
echo $1
|
||||
exit 0;;
|
||||
|
||||
* )
|
||||
break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
case $# in
|
||||
0) echo "$me: missing argument$help" >&2
|
||||
exit 1;;
|
||||
1) ;;
|
||||
*) echo "$me: too many arguments$help" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
|
||||
# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
linux-gnu*)
|
||||
nto-qnx* | linux-gnu* | storm-chaos* | os2-emx*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
|
@ -94,15 +143,25 @@ case $os in
|
|||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||
-apple)
|
||||
-apple | -axis)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
-sim | -cisco | -oki | -wec | -winbond)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
-scout)
|
||||
;;
|
||||
-wrs)
|
||||
os=-vxworks
|
||||
basic_machine=$1
|
||||
;;
|
||||
-hiux*)
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
-sco5)
|
||||
os=sco3.2v5
|
||||
os=-sco3.2v5
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-sco4)
|
||||
|
@ -121,6 +180,9 @@ case $os in
|
|||
os=-sco3.2v2
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-udk*)
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-isc)
|
||||
os=-isc2.2
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
|
@ -143,50 +205,101 @@ case $os in
|
|||
-psos*)
|
||||
os=-psos
|
||||
;;
|
||||
-mint | -mint[0-9]*)
|
||||
basic_machine=m68k-atari
|
||||
os=-mint
|
||||
;;
|
||||
esac
|
||||
|
||||
# Decode aliases for certain CPU-COMPANY combinations.
|
||||
case $basic_machine in
|
||||
# Recognize the basic CPU types without company name.
|
||||
# Some are omitted here because they have special meanings below.
|
||||
tahoe | i860 | m68k | m68000 | m88k | ns32k | arm \
|
||||
| arme[lb] | pyramid \
|
||||
| tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \
|
||||
| alpha | we32k | ns16k | clipper | i370 | sh \
|
||||
| powerpc | powerpcle | 1750a | dsp16xx | mips64 | mipsel \
|
||||
| pdp11 | mips64el | mips64orion | mips64orionel \
|
||||
| sparc | sparclet | sparclite | sparc64)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc \
|
||||
| arm | arme[lb] | arm[bl]e | armv[2345] | armv[345][lb] | strongarm | xscale \
|
||||
| pyramid | mn10200 | mn10300 | tron | a29k \
|
||||
| 580 | i960 | h8300 \
|
||||
| x86 | ppcbe | mipsbe | mipsle | shbe | shle \
|
||||
| hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
|
||||
| hppa64 \
|
||||
| alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \
|
||||
| alphaev6[78] \
|
||||
| we32k | ns16k | clipper | i370 | sh | sh[34] \
|
||||
| powerpc | powerpcle \
|
||||
| 1750a | dsp16xx | pdp10 | pdp11 \
|
||||
| mips16 | mips64 | mipsel | mips64el \
|
||||
| mips64orion | mips64orionel | mipstx39 | mipstx39el \
|
||||
| mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
|
||||
| mips64vr5000 | miprs64vr5000el | mcore | s390 | s390x \
|
||||
| sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \
|
||||
| thumb | d10v | d30v | fr30 | avr | openrisc)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12)
|
||||
# Motorola 68HC11/12.
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65 | pj | pjl)
|
||||
;;
|
||||
|
||||
# We use `pc' rather than `unknown'
|
||||
# because (1) that's what they normally are, and
|
||||
# (2) the word "unknown" tends to confuse beginning users.
|
||||
i[3456]86)
|
||||
i[234567]86 | x86_64)
|
||||
basic_machine=$basic_machine-pc
|
||||
;;
|
||||
# Object if more than one company name word.
|
||||
*-*-*)
|
||||
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
|
||||
exit 1
|
||||
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
|
||||
exit 1
|
||||
;;
|
||||
# Recognize the basic CPU types with company name.
|
||||
vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \
|
||||
| sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
|
||||
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
|
||||
| none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
|
||||
| hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
|
||||
| pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
|
||||
| pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \
|
||||
| mips64el-* | mips64orion-* | mips64orionel-*)
|
||||
# FIXME: clean up the formatting here.
|
||||
vax-* | tahoe-* | i[234567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \
|
||||
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | c[123]* \
|
||||
| arm-* | armbe-* | armle-* | armv*-* | strongarm-* | xscale-* \
|
||||
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
|
||||
| power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
|
||||
| xmp-* | ymp-* \
|
||||
| x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* \
|
||||
| hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \
|
||||
| hppa2.0n-* | hppa64-* \
|
||||
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \
|
||||
| alphaev6[78]-* \
|
||||
| we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
|
||||
| clipper-* | orion-* \
|
||||
| sparclite-* | pdp10-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
|
||||
| sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \
|
||||
| mips64el-* | mips64orion-* | mips64orionel-* \
|
||||
| mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
|
||||
| mipstx39-* | mipstx39el-* | mcore-* \
|
||||
| f30[01]-* | f700-* | s390-* | s390x-* | sv1-* | t3e-* \
|
||||
| [cjt]90-* \
|
||||
| m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
|
||||
| thumb-* | v850-* | d30v-* | tic30-* | c30-* | fr30-* \
|
||||
| bs2000-* | tic54x-* | c54x-* | x86_64-*)
|
||||
;;
|
||||
# Recognize the various machine names and aliases which stand
|
||||
# for a CPU type and a company and sometimes even an OS.
|
||||
386bsd)
|
||||
basic_machine=i386-unknown
|
||||
os=-bsd
|
||||
;;
|
||||
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
|
||||
basic_machine=m68000-att
|
||||
;;
|
||||
3b*)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
a29khif)
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
adobe68k)
|
||||
basic_machine=m68010-adobe
|
||||
os=-scout
|
||||
;;
|
||||
alliant | fx80)
|
||||
basic_machine=fx80-alliant
|
||||
;;
|
||||
|
@ -202,20 +315,24 @@ case $basic_machine in
|
|||
os=-sysv
|
||||
;;
|
||||
amiga | amiga-*)
|
||||
basic_machine=m68k-cbm
|
||||
basic_machine=m68k-unknown
|
||||
;;
|
||||
amigados)
|
||||
basic_machine=m68k-cbm
|
||||
os=-amigados
|
||||
amigaos | amigados)
|
||||
basic_machine=m68k-unknown
|
||||
os=-amigaos
|
||||
;;
|
||||
amigaunix | amix)
|
||||
basic_machine=m68k-cbm
|
||||
basic_machine=m68k-unknown
|
||||
os=-sysv4
|
||||
;;
|
||||
apollo68)
|
||||
basic_machine=m68k-apollo
|
||||
os=-sysv
|
||||
;;
|
||||
apollo68bsd)
|
||||
basic_machine=m68k-apollo
|
||||
os=-bsd
|
||||
;;
|
||||
aux)
|
||||
basic_machine=m68k-apple
|
||||
os=-aux
|
||||
|
@ -252,13 +369,16 @@ case $basic_machine in
|
|||
basic_machine=cray2-cray
|
||||
os=-unicos
|
||||
;;
|
||||
[ctj]90-cray)
|
||||
basic_machine=c90-cray
|
||||
[cjt]90)
|
||||
basic_machine=${basic_machine}-cray
|
||||
os=-unicos
|
||||
;;
|
||||
crds | unos)
|
||||
basic_machine=m68k-crds
|
||||
;;
|
||||
cris | cris-* | etrax*)
|
||||
basic_machine=cris-axis
|
||||
;;
|
||||
da30 | da30-*)
|
||||
basic_machine=m68k-da30
|
||||
;;
|
||||
|
@ -292,6 +412,10 @@ case $basic_machine in
|
|||
encore | umax | mmax)
|
||||
basic_machine=ns32k-encore
|
||||
;;
|
||||
es1800 | OSE68k | ose68k | ose | OSE)
|
||||
basic_machine=m68k-ericsson
|
||||
os=-ose
|
||||
;;
|
||||
fx2800)
|
||||
basic_machine=i860-alliant
|
||||
;;
|
||||
|
@ -302,6 +426,10 @@ case $basic_machine in
|
|||
basic_machine=tron-gmicro
|
||||
os=-sysv
|
||||
;;
|
||||
go32)
|
||||
basic_machine=i386-pc
|
||||
os=-go32
|
||||
;;
|
||||
h3050r* | hiux*)
|
||||
basic_machine=hppa1.1-hitachi
|
||||
os=-hiuxwe2
|
||||
|
@ -310,6 +438,14 @@ case $basic_machine in
|
|||
basic_machine=h8300-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
h8300xray)
|
||||
basic_machine=h8300-hitachi
|
||||
os=-xray
|
||||
;;
|
||||
h8500hms)
|
||||
basic_machine=h8500-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
harris)
|
||||
basic_machine=m88k-harris
|
||||
os=-sysv3
|
||||
|
@ -325,39 +461,74 @@ case $basic_machine in
|
|||
basic_machine=m68k-hp
|
||||
os=-hpux
|
||||
;;
|
||||
hp3k9[0-9][0-9] | hp9[0-9][0-9])
|
||||
basic_machine=hppa1.0-hp
|
||||
;;
|
||||
hp9k2[0-9][0-9] | hp9k31[0-9])
|
||||
basic_machine=m68000-hp
|
||||
;;
|
||||
hp9k3[2-9][0-9])
|
||||
basic_machine=m68k-hp
|
||||
;;
|
||||
hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
|
||||
hp9k6[0-9][0-9] | hp6[0-9][0-9])
|
||||
basic_machine=hppa1.0-hp
|
||||
;;
|
||||
hp9k7[0-79][0-9] | hp7[0-79][0-9])
|
||||
basic_machine=hppa1.1-hp
|
||||
;;
|
||||
hp9k78[0-9] | hp78[0-9])
|
||||
# FIXME: really hppa2.0-hp
|
||||
basic_machine=hppa1.1-hp
|
||||
;;
|
||||
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
|
||||
# FIXME: really hppa2.0-hp
|
||||
basic_machine=hppa1.1-hp
|
||||
;;
|
||||
hp9k8[0-9][13679] | hp8[0-9][13679])
|
||||
basic_machine=hppa1.1-hp
|
||||
;;
|
||||
hp9k8[0-9][0-9] | hp8[0-9][0-9])
|
||||
basic_machine=hppa1.0-hp
|
||||
;;
|
||||
hppa-next)
|
||||
os=-nextstep3
|
||||
;;
|
||||
hppaosf)
|
||||
basic_machine=hppa1.1-hp
|
||||
os=-osf
|
||||
;;
|
||||
hppro)
|
||||
basic_machine=hppa1.1-hp
|
||||
os=-proelf
|
||||
;;
|
||||
i370-ibm* | ibm*)
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
;;
|
||||
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
|
||||
i[3456]86v32)
|
||||
i[34567]86v32)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv32
|
||||
;;
|
||||
i[3456]86v4*)
|
||||
i[34567]86v4*)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv4
|
||||
;;
|
||||
i[3456]86v)
|
||||
i[34567]86v)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv
|
||||
;;
|
||||
i[3456]86sol2)
|
||||
i[34567]86sol2)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-solaris2
|
||||
;;
|
||||
i386mach)
|
||||
basic_machine=i386-mach
|
||||
os=-mach
|
||||
;;
|
||||
i386-vsta | vsta)
|
||||
basic_machine=i386-unknown
|
||||
os=-vsta
|
||||
;;
|
||||
iris | iris4d)
|
||||
basic_machine=mips-sgi
|
||||
case $os in
|
||||
|
@ -383,19 +554,59 @@ case $basic_machine in
|
|||
basic_machine=ns32k-utek
|
||||
os=-sysv
|
||||
;;
|
||||
mingw32)
|
||||
basic_machine=i386-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
miniframe)
|
||||
basic_machine=m68000-convergent
|
||||
;;
|
||||
*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
|
||||
basic_machine=m68k-atari
|
||||
os=-mint
|
||||
;;
|
||||
mipsel*-linux*)
|
||||
basic_machine=mipsel-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
mips*-linux*)
|
||||
basic_machine=mips-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
mips3*-*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
|
||||
;;
|
||||
mips3*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
||||
;;
|
||||
mmix*)
|
||||
basic_machine=mmix-knuth
|
||||
os=-mmixware
|
||||
;;
|
||||
monitor)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
;;
|
||||
msdos)
|
||||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
;;
|
||||
mvs)
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
;;
|
||||
ncr3000)
|
||||
basic_machine=i486-ncr
|
||||
os=-sysv4
|
||||
;;
|
||||
netbsd386)
|
||||
basic_machine=i386-unknown
|
||||
os=-netbsd
|
||||
;;
|
||||
netwinder)
|
||||
basic_machine=armv4l-rebel
|
||||
os=-linux
|
||||
;;
|
||||
news | news700 | news800 | news900)
|
||||
basic_machine=m68k-sony
|
||||
os=-newsos
|
||||
|
@ -408,6 +619,10 @@ case $basic_machine in
|
|||
basic_machine=mips-sony
|
||||
os=-newsos
|
||||
;;
|
||||
necv70)
|
||||
basic_machine=v70-nec
|
||||
os=-sysv
|
||||
;;
|
||||
next | m*-next )
|
||||
basic_machine=m68k-next
|
||||
case $os in
|
||||
|
@ -433,9 +648,32 @@ case $basic_machine in
|
|||
basic_machine=i960-intel
|
||||
os=-nindy
|
||||
;;
|
||||
mon960)
|
||||
basic_machine=i960-intel
|
||||
os=-mon960
|
||||
;;
|
||||
nonstopux)
|
||||
basic_machine=mips-compaq
|
||||
os=-nonstopux
|
||||
;;
|
||||
np1)
|
||||
basic_machine=np1-gould
|
||||
;;
|
||||
nsr-tandem)
|
||||
basic_machine=nsr-tandem
|
||||
;;
|
||||
op50n-* | op60c-*)
|
||||
basic_machine=hppa1.1-oki
|
||||
os=-proelf
|
||||
;;
|
||||
OSE68000 | ose68000)
|
||||
basic_machine=m68000-ericsson
|
||||
os=-ose
|
||||
;;
|
||||
os68k)
|
||||
basic_machine=m68k-none
|
||||
os=-os68k
|
||||
;;
|
||||
pa-hitachi)
|
||||
basic_machine=hppa1.1-hitachi
|
||||
os=-hiuxwe2
|
||||
|
@ -453,30 +691,28 @@ case $basic_machine in
|
|||
pc532 | pc532-*)
|
||||
basic_machine=ns32k-pc532
|
||||
;;
|
||||
pentium | p5)
|
||||
basic_machine=i586-intel
|
||||
pentium | p5 | k5 | k6 | nexgen)
|
||||
basic_machine=i586-pc
|
||||
;;
|
||||
pentiumpro | p6)
|
||||
basic_machine=i686-intel
|
||||
pentiumpro | p6 | 6x86 | athlon)
|
||||
basic_machine=i686-pc
|
||||
;;
|
||||
pentium-* | p5-*)
|
||||
pentiumii | pentium2)
|
||||
basic_machine=i686-pc
|
||||
;;
|
||||
pentium-* | p5-* | k5-* | k6-* | nexgen-*)
|
||||
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumpro-* | p6-*)
|
||||
pentiumpro-* | p6-* | 6x86-* | athlon-*)
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
k5)
|
||||
# We don't have specific support for AMD's K5 yet, so just call it a Pentium
|
||||
basic_machine=i586-amd
|
||||
;;
|
||||
nexen)
|
||||
# We don't have specific support for Nexgen yet, so just call it a Pentium
|
||||
basic_machine=i586-nexgen
|
||||
pentiumii-* | pentium2-*)
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pn)
|
||||
basic_machine=pn-gould
|
||||
;;
|
||||
power) basic_machine=rs6000-ibm
|
||||
power) basic_machine=power-ibm
|
||||
;;
|
||||
ppc) basic_machine=powerpc-unknown
|
||||
;;
|
||||
|
@ -491,12 +727,24 @@ case $basic_machine in
|
|||
ps2)
|
||||
basic_machine=i386-ibm
|
||||
;;
|
||||
pw32)
|
||||
basic_machine=i586-unknown
|
||||
os=-pw32
|
||||
;;
|
||||
rom68k)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
;;
|
||||
rm[46]00)
|
||||
basic_machine=mips-siemens
|
||||
;;
|
||||
rtpc | rtpc-*)
|
||||
basic_machine=romp-ibm
|
||||
;;
|
||||
sa29200)
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
sequent)
|
||||
basic_machine=i386-sequent
|
||||
;;
|
||||
|
@ -504,6 +752,10 @@ case $basic_machine in
|
|||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sparclite-wrs)
|
||||
basic_machine=sparclite-wrs
|
||||
os=-vxworks
|
||||
;;
|
||||
sps7)
|
||||
basic_machine=m68k-bull
|
||||
os=-sysv2
|
||||
|
@ -511,6 +763,13 @@ case $basic_machine in
|
|||
spur)
|
||||
basic_machine=spur-unknown
|
||||
;;
|
||||
st2000)
|
||||
basic_machine=m68k-tandem
|
||||
;;
|
||||
stratus)
|
||||
basic_machine=i860-stratus
|
||||
os=-sysv4
|
||||
;;
|
||||
sun2)
|
||||
basic_machine=m68000-sun
|
||||
;;
|
||||
|
@ -551,10 +810,28 @@ case $basic_machine in
|
|||
sun386 | sun386i | roadrunner)
|
||||
basic_machine=i386-sun
|
||||
;;
|
||||
sv1)
|
||||
basic_machine=sv1-cray
|
||||
os=-unicos
|
||||
;;
|
||||
symmetry)
|
||||
basic_machine=i386-sequent
|
||||
os=-dynix
|
||||
;;
|
||||
t3e)
|
||||
basic_machine=t3e-cray
|
||||
os=-unicos
|
||||
;;
|
||||
tic54x | c54x*)
|
||||
basic_machine=tic54x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tx39)
|
||||
basic_machine=mipstx39-unknown
|
||||
;;
|
||||
tx39el)
|
||||
basic_machine=mipstx39el-unknown
|
||||
;;
|
||||
tower | tower-32)
|
||||
basic_machine=m68k-ncr
|
||||
;;
|
||||
|
@ -566,6 +843,10 @@ case $basic_machine in
|
|||
basic_machine=a29k-nyu
|
||||
os=-sym1
|
||||
;;
|
||||
v810 | necv810)
|
||||
basic_machine=v810-nec
|
||||
os=-none
|
||||
;;
|
||||
vaxv)
|
||||
basic_machine=vax-dec
|
||||
os=-sysv
|
||||
|
@ -574,6 +855,9 @@ case $basic_machine in
|
|||
basic_machine=vax-dec
|
||||
os=-vms
|
||||
;;
|
||||
vpp*|vx|vx-*)
|
||||
basic_machine=f301-fujitsu
|
||||
;;
|
||||
vxworks960)
|
||||
basic_machine=i960-wrs
|
||||
os=-vxworks
|
||||
|
@ -586,6 +870,14 @@ case $basic_machine in
|
|||
basic_machine=a29k-wrs
|
||||
os=-vxworks
|
||||
;;
|
||||
w65*)
|
||||
basic_machine=w65-wdc
|
||||
os=-none
|
||||
;;
|
||||
w89k-*)
|
||||
basic_machine=hppa1.1-winbond
|
||||
os=-proelf
|
||||
;;
|
||||
xmp)
|
||||
basic_machine=xmp-cray
|
||||
os=-unicos
|
||||
|
@ -593,6 +885,10 @@ case $basic_machine in
|
|||
xps | xps100)
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
z8k-*-coff)
|
||||
basic_machine=z8k-unknown
|
||||
os=-sim
|
||||
;;
|
||||
none)
|
||||
basic_machine=none-none
|
||||
os=-none
|
||||
|
@ -600,8 +896,21 @@ case $basic_machine in
|
|||
|
||||
# Here we handle the default manufacturer of certain CPU types. It is in
|
||||
# some cases the only manufacturer, in others, it is the most popular.
|
||||
w89k)
|
||||
basic_machine=hppa1.1-winbond
|
||||
;;
|
||||
op50n)
|
||||
basic_machine=hppa1.1-oki
|
||||
;;
|
||||
op60c)
|
||||
basic_machine=hppa1.1-oki
|
||||
;;
|
||||
mips)
|
||||
basic_machine=mips-mips
|
||||
if [ x$os = x-linux-gnu ]; then
|
||||
basic_machine=mips-unknown
|
||||
else
|
||||
basic_machine=mips-mips
|
||||
fi
|
||||
;;
|
||||
romp)
|
||||
basic_machine=romp-ibm
|
||||
|
@ -612,13 +921,20 @@ case $basic_machine in
|
|||
vax)
|
||||
basic_machine=vax-dec
|
||||
;;
|
||||
pdp10)
|
||||
# there are many clones, so DEC is not a safe bet
|
||||
basic_machine=pdp10-unknown
|
||||
;;
|
||||
pdp11)
|
||||
basic_machine=pdp11-dec
|
||||
;;
|
||||
we32k)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
sparc)
|
||||
sh3 | sh4)
|
||||
basic_machine=sh-unknown
|
||||
;;
|
||||
sparc | sparcv9)
|
||||
basic_machine=sparc-sun
|
||||
;;
|
||||
cydra)
|
||||
|
@ -630,6 +946,16 @@ case $basic_machine in
|
|||
orion105)
|
||||
basic_machine=clipper-highlevel
|
||||
;;
|
||||
mac | mpw | mac-mpw)
|
||||
basic_machine=m68k-apple
|
||||
;;
|
||||
pmac | pmac-mpw)
|
||||
basic_machine=powerpc-apple
|
||||
;;
|
||||
c4x*)
|
||||
basic_machine=c4x-none
|
||||
os=-coff
|
||||
;;
|
||||
*)
|
||||
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
|
||||
exit 1
|
||||
|
@ -662,9 +988,12 @@ case $os in
|
|||
-solaris)
|
||||
os=-solaris2
|
||||
;;
|
||||
-unixware* | svr4*)
|
||||
-svr4*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-unixware*)
|
||||
os=-sysv4.2uw
|
||||
;;
|
||||
-gnu/linux*)
|
||||
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
|
||||
;;
|
||||
|
@ -675,17 +1004,40 @@ case $os in
|
|||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
|
||||
| -amigados* | -msdos* | -newsos* | -unicos* | -aof* | -aos* \
|
||||
| -nindy* | -vxworks* | -ebmon* | -hms* | -mvs* | -clix* \
|
||||
| -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -netbsd* | -freebsd* | -riscix* \
|
||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
|
||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -cygwin32* | -pe* | -psos* | -moss* | -proelf* \
|
||||
| -linux-gnu*)
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* | -os2*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
case $basic_machine in
|
||||
x86-* | i[34567]86-*)
|
||||
;;
|
||||
*)
|
||||
os=-nto$os
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-nto*)
|
||||
os=-nto-qnx
|
||||
;;
|
||||
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
|
||||
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
|
||||
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
|
||||
;;
|
||||
-mac*)
|
||||
os=`echo $os | sed -e 's|mac|macos|'`
|
||||
;;
|
||||
-linux*)
|
||||
os=`echo $os | sed -e 's|linux|linux-gnu|'`
|
||||
;;
|
||||
|
@ -695,6 +1047,12 @@ case $os in
|
|||
-sunos6*)
|
||||
os=`echo $os | sed -e 's|sunos6|solaris3|'`
|
||||
;;
|
||||
-opened*)
|
||||
os=-openedition
|
||||
;;
|
||||
-wince*)
|
||||
os=-wince
|
||||
;;
|
||||
-osfrose*)
|
||||
os=-osfrose
|
||||
;;
|
||||
|
@ -710,12 +1068,18 @@ case $os in
|
|||
-acis*)
|
||||
os=-aos
|
||||
;;
|
||||
-386bsd)
|
||||
os=-bsd
|
||||
;;
|
||||
-ctix* | -uts*)
|
||||
os=-sysv
|
||||
;;
|
||||
-ns2 )
|
||||
os=-nextstep2
|
||||
;;
|
||||
-nsk*)
|
||||
os=-nsk
|
||||
;;
|
||||
# Preserve the version number of sinix5.
|
||||
-sinix5.*)
|
||||
os=`echo $os | sed -e 's|sinix|sysv|'`
|
||||
|
@ -741,9 +1105,18 @@ case $os in
|
|||
# This must come after -sysvr4.
|
||||
-sysv*)
|
||||
;;
|
||||
-ose*)
|
||||
os=-ose
|
||||
;;
|
||||
-es1800*)
|
||||
os=-ose
|
||||
;;
|
||||
-xenix)
|
||||
os=-xenix
|
||||
;;
|
||||
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
|
||||
os=-mint
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
|
@ -769,9 +1142,15 @@ case $basic_machine in
|
|||
*-acorn)
|
||||
os=-riscix1.2
|
||||
;;
|
||||
arm*-rebel)
|
||||
os=-linux
|
||||
;;
|
||||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
pdp10-*)
|
||||
os=-tops20
|
||||
;;
|
||||
pdp11-*)
|
||||
os=-none
|
||||
;;
|
||||
|
@ -790,15 +1169,36 @@ case $basic_machine in
|
|||
# default.
|
||||
# os=-sunos4
|
||||
;;
|
||||
m68*-cisco)
|
||||
os=-aout
|
||||
;;
|
||||
mips*-cisco)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-*)
|
||||
os=-elf
|
||||
;;
|
||||
*-tti) # must be before sparc entry or we get the wrong os.
|
||||
os=-sysv3
|
||||
;;
|
||||
sparc-* | *-sun)
|
||||
os=-sunos4.1.1
|
||||
;;
|
||||
*-be)
|
||||
os=-beos
|
||||
;;
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
*-wec)
|
||||
os=-proelf
|
||||
;;
|
||||
*-winbond)
|
||||
os=-proelf
|
||||
;;
|
||||
*-oki)
|
||||
os=-proelf
|
||||
;;
|
||||
*-hp)
|
||||
os=-hpux
|
||||
;;
|
||||
|
@ -809,7 +1209,7 @@ case $basic_machine in
|
|||
os=-sysv
|
||||
;;
|
||||
*-cbm)
|
||||
os=-amigados
|
||||
os=-amigaos
|
||||
;;
|
||||
*-dg)
|
||||
os=-dgux
|
||||
|
@ -859,6 +1259,21 @@ case $basic_machine in
|
|||
*-masscomp)
|
||||
os=-rtu
|
||||
;;
|
||||
f30[01]-fujitsu | f700-fujitsu)
|
||||
os=-uxpv
|
||||
;;
|
||||
*-rom68k)
|
||||
os=-coff
|
||||
;;
|
||||
*-*bug)
|
||||
os=-coff
|
||||
;;
|
||||
*-apple)
|
||||
os=-macos
|
||||
;;
|
||||
*-atari*)
|
||||
os=-mint
|
||||
;;
|
||||
*)
|
||||
os=-none
|
||||
;;
|
||||
|
@ -877,15 +1292,18 @@ case $basic_machine in
|
|||
-sunos*)
|
||||
vendor=sun
|
||||
;;
|
||||
-lynxos*)
|
||||
vendor=lynx
|
||||
;;
|
||||
-aix*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-beos*)
|
||||
vendor=be
|
||||
;;
|
||||
-hpux*)
|
||||
vendor=hp
|
||||
;;
|
||||
-mpeix*)
|
||||
vendor=hp
|
||||
;;
|
||||
-hiux*)
|
||||
vendor=hitachi
|
||||
;;
|
||||
|
@ -901,21 +1319,38 @@ case $basic_machine in
|
|||
-genix*)
|
||||
vendor=ns
|
||||
;;
|
||||
-mvs*)
|
||||
-mvs* | -opened*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-ptx*)
|
||||
vendor=sequent
|
||||
;;
|
||||
-vxworks*)
|
||||
-vxsim* | -vxworks*)
|
||||
vendor=wrs
|
||||
;;
|
||||
-aux*)
|
||||
vendor=apple
|
||||
;;
|
||||
-hms*)
|
||||
vendor=hitachi
|
||||
;;
|
||||
-mpw* | -macos*)
|
||||
vendor=apple
|
||||
;;
|
||||
-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
|
||||
vendor=atari
|
||||
;;
|
||||
esac
|
||||
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
|
||||
;;
|
||||
esac
|
||||
|
||||
echo $basic_machine$os
|
||||
exit 0
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "timestamp='"
|
||||
# time-stamp-format: "%:y-%02m-%02d"
|
||||
# time-stamp-end: "'"
|
||||
# End:
|
||||
|
|
|
@ -1294,7 +1294,7 @@ fi
|
|||
;;
|
||||
|
||||
## NetBSD and FreeBSD ( and maybe 386BSD also)
|
||||
*-*-*bsd* )
|
||||
*-*-*bsd*|*-*-darwin* )
|
||||
dir=bsd
|
||||
|
||||
echo $ac_n "checking for ELF""... $ac_c" 1>&6
|
||||
|
@ -1375,8 +1375,8 @@ EOF
|
|||
|
||||
;;
|
||||
|
||||
## NT - cygwin32
|
||||
*-*-cygwin32* )
|
||||
## NT - cygwin
|
||||
*-*-cygwin* )
|
||||
dir=cygwin32
|
||||
;;
|
||||
|
||||
|
|
|
@ -292,7 +292,7 @@ case "$host" in
|
|||
;;
|
||||
|
||||
## NetBSD and FreeBSD ( and maybe 386BSD also)
|
||||
*-*-*bsd* )
|
||||
*-*-*bsd*|*-*-darwin* )
|
||||
dir=bsd
|
||||
SCSH_ELF
|
||||
;;
|
||||
|
@ -322,8 +322,8 @@ case "$host" in
|
|||
AC_DEFINE(HAVE_NLIST)
|
||||
;;
|
||||
|
||||
## NT - cygwin32
|
||||
*-*-cygwin32* )
|
||||
## NT - cygwin
|
||||
*-*-cygwin* )
|
||||
dir=cygwin32
|
||||
;;
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
html
|
|
@ -19,12 +19,15 @@ man.ind: man.idx
|
|||
|
||||
clean:
|
||||
-rm *.log
|
||||
rm -rf html
|
||||
|
||||
INSTALL_DATA= install -c -m 644
|
||||
|
||||
tar:
|
||||
tar cf - *.tex sty | gzip > man.tar.gz
|
||||
|
||||
html: $(TEX)
|
||||
tex2page man && tex2page man
|
||||
|
||||
install: man.ps
|
||||
@echo WARNING:
|
||||
|
|
|
@ -76,6 +76,7 @@ characters.
|
|||
|
||||
|
||||
\subsection{Parsing fields}
|
||||
\label{sec:field-splitter}
|
||||
|
||||
\defun {field-splitter} {[field num-fields]} \proc
|
||||
\defunx {infix-splitter} {[delim num-fields handle-delim]} \proc
|
||||
|
|
|
@ -1,297 +0,0 @@
|
|||
%&latex -*- latex -*-
|
||||
|
||||
\chapter{Changes from previous releases}
|
||||
\label{sec:changes}
|
||||
|
||||
\newcommand{\itam}[1]{\item {#1} \\}
|
||||
|
||||
\section{Changes from the previous release}
|
||||
|
||||
This section details changes that have been made in scsh since
|
||||
the previous release.
|
||||
|
||||
Scsh is now much more robust.
|
||||
All known bugs have been fixed.
|
||||
There have been many improvements and extensions made.
|
||||
These new features and changes are listed below, in no particular order;
|
||||
the relevant sections of the manual give the full details.
|
||||
|
||||
Scsh now supports complete {\Posix}, including signal handlers.
|
||||
Early autoreaping of child processes is now handled by a \ex{SIGCHLD}
|
||||
signal handler, so children are reaped as early as possible with no
|
||||
user intervention required.
|
||||
|
||||
A functional static heap linker is included in this release.
|
||||
It is ugly, limited in functionality, and extremely slow, but it works.
|
||||
It can be used to build scsh binaries that start up instantly.
|
||||
|
||||
The regular expression system has been sped up.
|
||||
Regular-expression compilation is now provided,
|
||||
and the \ex{awk} macro has been rewritten to pre-compile
|
||||
regexps used in rules outside the loop.
|
||||
It is still, however, slower than it should be.
|
||||
|
||||
Execing programs should be faster in this release, since we now use the
|
||||
\ex{CLOEXEC} status bit to get automatic closing of unrevealed
|
||||
port file descriptors.
|
||||
|
||||
{scm}'s floating point support was inadvertently omitted from the last
|
||||
release. It has been reinstated.
|
||||
|
||||
There is now a new command-line switch, \ex{-sfd \var{num}},
|
||||
which causes scsh to read its script from file descriptor \var{num}.
|
||||
|
||||
|
||||
\section{Changes from the penultimate release}
|
||||
|
||||
This section details changes that have been made in scsh since
|
||||
the penultimate release.
|
||||
|
||||
Scsh is now much more robust.
|
||||
All known bugs have been fixed.
|
||||
There have been many improvements and extensions made.
|
||||
We have also made made some incompatible changes.
|
||||
|
||||
The sections below briefly describe these new features and changes;
|
||||
the relevant sections of the manual give the full details.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{New features}
|
||||
This release incorporates several new features into scsh.
|
||||
|
||||
\begin{itemize}
|
||||
\itam{Control of buffered I/O}
|
||||
Scsh now allows you to control the buffering policy used for doing I/O
|
||||
on a Scheme port.
|
||||
|
||||
\itam{Here-strings}
|
||||
Scsh now has a new lexical feature, \verb|#<<|, that provides
|
||||
the ability to enter long, multi-line string constants in scsh programs.
|
||||
Such a string is called a ``here string,'' by analogy to the common
|
||||
shell ``here document'' \ex{<<} redirection.
|
||||
|
||||
\itam{Delimited readers and read-line}
|
||||
Scsh now has a powerful set of delimited readers.
|
||||
These can be used to read input delimited by
|
||||
a newline character (\ex{read-line}),
|
||||
a blank line (\ex{read-paragraph}),
|
||||
or the occurrence of any character in an arbitrary set (\ex{read-delimited}).
|
||||
|
||||
While these procedures can be applied to any Scheme input port,
|
||||
there is native-code support for performing delimited reads on
|
||||
Unix input sources, so doing block input with these procedures should be
|
||||
much faster than the equivalent character-at-a-time Scheme code.
|
||||
|
||||
\itam{New system calls}
|
||||
With the sole exception of signal handlers, scsh now has all of {\Posix}.
|
||||
This release introduces
|
||||
\begin{itemize}
|
||||
\item \ex{select},
|
||||
\item full terminal device control,
|
||||
\item support for pseudo-terminal ``pty'' devices,
|
||||
\item file locking,
|
||||
\item process timing,
|
||||
\item \ex{set-file-times},
|
||||
\item \ex{seek} and \ex{tell}.
|
||||
\end{itemize}
|
||||
|
||||
Note that having \ex{select}, pseudo-terminals, and tty device control means
|
||||
that it is now possible to implement interesting network protocols, such as
|
||||
telnet servers and clients, directly in Scheme.
|
||||
|
||||
\itam{New command-line switches}
|
||||
There is a new set of command-line switches that make it possible
|
||||
to write shell scripts using the {\scm} module system.
|
||||
Scripts can use the new command-line switches to open dependent
|
||||
modules and load dependent source code.
|
||||
Scripts can also be written in the {\scm} module language,
|
||||
which allows you to use it both as a standalone shell script,
|
||||
and as a code module that can be loaded and used by other Scheme programs.
|
||||
|
||||
\itam{Static heap linking}
|
||||
There is a new facility that allows you to compile a heap image
|
||||
to a \ex{.o} file that can be linked with the scsh virtual machine.
|
||||
This produces a standalone executable binary, makes startup time
|
||||
near-instantaneous, and greatly improves memory performance---the
|
||||
initial heap image is placed in the process' text pages,
|
||||
where it is shared by different scsh processes, and does not occupy
|
||||
space in the run-time heap.
|
||||
|
||||
\oops{The static heap linker was not documented and installed in time
|
||||
for this release.}
|
||||
|
||||
|
||||
\end{itemize}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{Incompatible improvements}
|
||||
Some features of scsh have been improved in ways that are
|
||||
not backwards-compatible with previous releases.
|
||||
These changes should not affect most code;
|
||||
however, please note the changes and modify your code accordingly.
|
||||
|
||||
\begin{itemize}
|
||||
\itam{New process-object data-type returned by \ex{fork}}
|
||||
Previous releases were prone to fill up the kernel's process table
|
||||
if a program forked large numbers of processes and subsequently failed
|
||||
to use \ex{wait} to reclaim the entries in the kernel's process table.
|
||||
(This is a problem in standard C environments, as well.)
|
||||
|
||||
Scsh 0.4 introduces a new mechanism for automatically managing subprocesses.
|
||||
Processes are no longer represented by an integer process id,
|
||||
which is impossible to garbage-collect, but by an
|
||||
abstract process data type that encapsulates the process id.
|
||||
All processes are represented using the new data structures;
|
||||
see the relevant section of the manual for further details.
|
||||
|
||||
\itam{Better stdio/current-port synchronisation}
|
||||
The \ex{(begin \ldots)} process form now does a \ex{stdio->stdports}
|
||||
call before executing its body.
|
||||
This means that the Scheme code in the body ``sees'' any external
|
||||
redirections.
|
||||
For example, it means that if a \ex{begin} form in the middle of a pipeline
|
||||
performs I/O on the current input and output ports, it will be communicating
|
||||
with its upstream and downstream pipes.
|
||||
\Eg, this code works as intended without the need for explicit synchronisation:
|
||||
\begin{verbatim}
|
||||
(run (| (gunzip)
|
||||
;; Kill line 1 and insert doubled-sided
|
||||
;; code at head of Postscript.
|
||||
(begin (read-line) ; Eat first line.
|
||||
(display "%!PS-Adobe-2.0\\n")
|
||||
(display "statusdict /setduplexmode known ")
|
||||
(display "{statusdict begin true ")
|
||||
(display "setduplexmode end} if\n")
|
||||
(exec-epf (cat)))
|
||||
(lpr))
|
||||
(< paper.ps))\end{verbatim}
|
||||
Arranging for the \ex{begin} process form to synchronise
|
||||
the current I/O ports with stdio means that all process forms now
|
||||
see their epf's redirections.
|
||||
|
||||
\itam{\ex{file-match} more robust}
|
||||
The \ex{file-match} procedure now catches any error condition
|
||||
signalled by a match procedure,
|
||||
and treats it as if the procedure had simply returned {\sharpf},
|
||||
\ie, match failure.
|
||||
This means \ex{file-match} no longer gets blown out of the water by
|
||||
trying to apply a function like \ex{file-directory?} to a dangling symlink,
|
||||
and other related OS errors.
|
||||
|
||||
\itam{Standard input now unbuffered}
|
||||
Scsh's startup code now makes the initial current input port
|
||||
(corresponding to file descriptor 0) unbuffered.
|
||||
This keeps the shell from ``stealing'' input meant for subprocesses.
|
||||
However, it does slow down character-at-a-time input processing.
|
||||
If you are writing a program that is tolerant of buffered input,
|
||||
and wish the efficiency gains, you can reset the buffering policy
|
||||
yourself.
|
||||
|
||||
\itam{``writeable'' now spelled ``writable''}
|
||||
We inconsistently spelled \ex{file-writable?} and \ex{file-not-writable?}
|
||||
in the manual and the implementation.
|
||||
We have now standardised on the common spelling ``writable'' in both.
|
||||
The older bindings still exist in release 0.4, but will go away in future
|
||||
releases.
|
||||
|
||||
\itam{\protect\ex{char-set-member?} replaced}
|
||||
We have de-released the \ex{char-set-member?} procedure.
|
||||
The scsh 0.3 version of this procedure took arguments
|
||||
in the following order:
|
||||
\codex{(char-set-member? \var{char} \var{char-set})}
|
||||
This argument order is in accordance with standard mathematical useage
|
||||
(\ie, $x \in S$), and also consistent with the R4RS
|
||||
\ex{member}, \ex{memq} and \ex{memv} procedures.
|
||||
It is, however, exactly opposite from the argument order
|
||||
used by the \ex{char-set-member?} in MIT Scheme's character-set library.
|
||||
If we left things as they were, we risked problems with code
|
||||
ported over from MIT Scheme.
|
||||
On the other hand, changing to conformance with MIT Scheme meant
|
||||
inconsistency with common mathematical notation and other long-standing
|
||||
Scheme procedures.
|
||||
Either way was bound to introduce confusion.
|
||||
|
||||
We've taken the approach of simply removing the \ex{char-set-member?}
|
||||
procedure altogether, and replacing it with a new procedure:
|
||||
\codex{(char-set-contains? \var{cset} \var{char})}
|
||||
Note that the argument order is consistent with the name.
|
||||
|
||||
\itam{\ex{file-attributes} now \ex{file-info}}
|
||||
In keeping with the general convention in scsh of naming procedures
|
||||
that retrieve information about system resources \ex{\ldots-info}
|
||||
(\eg, \ex{tty-info}, \ex{user-info}, \ex{group-info}),
|
||||
the \ex{file-attributes} procedure is now named \ex{file-info}.
|
||||
|
||||
We continue to export a \ex{file-attributes} binding for the current
|
||||
release, but it will go away in future releases.
|
||||
|
||||
\itam{Renaming of I/O synchronisation procedures}
|
||||
The \ex{(stdio->stdports \var{thunk})} procedure has been
|
||||
renamed \ex{with-stdio-ports*};
|
||||
there is now a corresponding \ex{with-stdio-ports} special form.
|
||||
The \ex{stdio->stdports} procedure is now a nullary procedure
|
||||
that side-effects the current set of current I/O port bindings.
|
||||
|
||||
\itam{New meta-arg line-two syntax}
|
||||
Scsh now uses a simplified grammar for describing command-line
|
||||
arguments read by the ``meta-arg'' switch from line two of a shell script.
|
||||
If you were using this feature in previous releases, the three incompatible
|
||||
changes of which to be aware are:
|
||||
(1) tab is no longer allowed as an argument delimiter,
|
||||
(2) a run of space characters is not equivalent to a single space,
|
||||
(3) empty arguments are written a different way.
|
||||
\end{itemize}
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{Backwards-compatible improvements}
|
||||
|
||||
Some existing features in scsh have been improved in ways that will
|
||||
not effect existing code.
|
||||
|
||||
\begin{itemize}
|
||||
\itam{Improved error reporting}
|
||||
Exception handlers that print out error messages and warnings now
|
||||
print their messages on the error output port,
|
||||
instead of the current output port.
|
||||
Previous releases used the current output port,
|
||||
a problem inherited from Scheme 48.
|
||||
|
||||
Previous scsh releases flushed the Scheme 48 debugging tables when
|
||||
creating the standard scsh heap image.
|
||||
This trimmed the size of the heap image, but made error messages much
|
||||
less comprehensible.
|
||||
We now retain the debugging tables.
|
||||
This bloats the heap image up by about 600kb. And worth it, too.
|
||||
|
||||
(We also have some new techniques for eliminating the run-time memory
|
||||
penalty imposed by these large heap images.
|
||||
Scsh's new static-heap technology allows for this data to be linked
|
||||
into the text pages of the vm's binary, where it will not be touched
|
||||
by the GC or otherwise affect the memory system until it is referenced.)
|
||||
|
||||
Finally, scsh now generates more informative error messages for syscall
|
||||
errors.
|
||||
For example, a file-open error previously told you what the error was
|
||||
(\eg, ``Permission denied,'' or ``No such file or directory''),
|
||||
but not which file you had tried to open.
|
||||
We've improved this.
|
||||
|
||||
\itam{Closing a port twice allowed}
|
||||
Scsh used to generate an error if you attempted to close a port
|
||||
that had already been closed.
|
||||
This is now allowed.
|
||||
The close procedure returns a boolean to indicate whether the port had
|
||||
already been closed or not.
|
||||
|
||||
\itam{Better time precision}
|
||||
The \ex{time+ticks} procedure now returns sub-second precision on OS's
|
||||
that support it.
|
||||
|
||||
\itam{Nicer print-methods for basic data-types}
|
||||
Scsh's standard record types now print more informatively.
|
||||
For example, a process object includes the process id in its
|
||||
printed representation: the process object for process id 2653
|
||||
prints as \verb|#{proc 2653}|.
|
||||
|
||||
\end{itemize}
|
|
@ -0,0 +1,105 @@
|
|||
% css.t2p
|
||||
% Dorai Sitaram
|
||||
% 19 Jan 2001
|
||||
% A basic style for HTML documents generated
|
||||
% with tex2page.
|
||||
|
||||
\cssblock
|
||||
|
||||
body {
|
||||
color: black;
|
||||
background-color: #e5e5e5;
|
||||
/*background-color: beige;*/
|
||||
margin-top: 2em;
|
||||
margin-left: 8%;
|
||||
margin-right: 8%;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
margin-top: .5em;
|
||||
}
|
||||
|
||||
.partheading {
|
||||
font-size: 70%;
|
||||
}
|
||||
|
||||
.chapterheading {
|
||||
font-size: 70%;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
ol ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
ol ol ol {
|
||||
list-style-type: lower-roman;
|
||||
}
|
||||
|
||||
ol ol ol ol {
|
||||
list-style-type: upper-alpha;
|
||||
}
|
||||
|
||||
.scheme {
|
||||
color: brown;
|
||||
}
|
||||
|
||||
.scheme .keyword {
|
||||
color: #990000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.scheme .builtin {
|
||||
color: #990000;
|
||||
}
|
||||
|
||||
.scheme .variable {
|
||||
color: navy;
|
||||
}
|
||||
|
||||
.scheme .global {
|
||||
color: purple;
|
||||
}
|
||||
|
||||
.scheme .selfeval {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.scheme .comment {
|
||||
color: teal;
|
||||
}
|
||||
|
||||
.navigation {
|
||||
color: red;
|
||||
text-align: right;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.disable {
|
||||
/* color: #e5e5e5; */
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.smallcaps {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
.smallprint {
|
||||
color: gray;
|
||||
font-size: 75%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.smallprint hr {
|
||||
text-align: left;
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
\endcssblock
|
|
@ -23,6 +23,8 @@
|
|||
\def\maketildeactive{\catcode`\~=13}
|
||||
\def\~{\char`\~}
|
||||
|
||||
\newcommand{\evalsto}{\ensuremath{\Rightarrow}}
|
||||
|
||||
% One-line code examples
|
||||
%\newcommand{\codex}[1]% One line, centred. Tight spacing.
|
||||
% {$$\abovedisplayskip=.75ex plus 1ex minus .5ex%
|
||||
|
|
|
@ -3,11 +3,17 @@
|
|||
\title{Scsh Reference Manual}
|
||||
\subtitle{For scsh release 0.5.3}
|
||||
\author{Olin Shivers and Brian D.~Carlstrom}
|
||||
\date{September 1999}
|
||||
\date{June 2001}
|
||||
|
||||
\maketitle
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Some code-changes for tex2page and latex output. NF
|
||||
\texonly
|
||||
\chapter*{Acknowledgements}
|
||||
\endtexonly
|
||||
\htmlonly
|
||||
\\ \ex{Acknowledgements} \\ \\
|
||||
\endhtmlonly
|
||||
|
||||
Who should I thank?
|
||||
My so-called ``colleagues,'' who laugh at me behind my back,
|
||||
|
|
|
@ -18,6 +18,30 @@ This manual gives a complete description of scsh.
|
|||
A general discussion of the design principles behind scsh can be found
|
||||
in a companion paper, ``A Scheme Shell.''
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Copyright \& source-code license}
|
||||
Scsh is open source. The complete sources come with the standard
|
||||
distribution, which can be downloaded off the net.
|
||||
|
||||
For years, scsh's underlying Scheme implementation, Scheme 48, did not have an
|
||||
open-source copyright. However, around 1999/2000, the Scheme 48 authors
|
||||
graciously retrofitted a BSD-style open-source copyright onto the system.
|
||||
Swept up by the fervor, we tacked an ideologically hip license onto scsh
|
||||
source, ourselves (BSD-style, as well). Not that we ever cared before what you
|
||||
did with the system.
|
||||
|
||||
As a result, the whole system is now open source, top-to-bottom.
|
||||
|
||||
We note that the code is a rich source for other Scheme implementations
|
||||
to mine. Not only the \emph{code}, but the \emph{APIs} are available
|
||||
for implementors working on Scheme environments for systems programming.
|
||||
These APIs represent years of work, and should provide a big head-start
|
||||
on any related effort. (Just don't call it ``scsh,'' unless it's
|
||||
\emph{exactly} compliant with the scsh interfaces.)
|
||||
|
||||
Take all the code you like; we'll just write more.
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Obtaining scsh}
|
||||
Scsh is distributed via net publication.
|
||||
|
@ -25,9 +49,9 @@ We place new releases at well-known network sites,
|
|||
and allow them to propagate from there.
|
||||
We currently release scsh to the following Internet sites:
|
||||
\begin{inset}\begin{flushleft}
|
||||
\ex{ftp://ftp-swiss.ai.mit.edu/pub/su/} \\
|
||||
\ex{http://www-swiss.ai.mit.edu/scsh/scsh.html}
|
||||
\ex{http://www.cs.indiana.edu/scheme-repository/} \\
|
||||
\ex{\urlh{ftp://ftp-swiss.ai.mit.edu/pub/su/}{ftp://ftp-swiss.ai.mit.edu/pub/su/}} \\
|
||||
\ex{\urlh{http://www-swiss.ai.mit.edu/scsh/scsh.html}{http://www-swiss.ai.mit.edu/scsh/scsh.html}} \\
|
||||
\ex{\urlh{http://www.cs.indiana.edu/scheme-repository/}{http://www.cs.indiana.edu/scheme-repository/}} \\
|
||||
\end{flushleft}
|
||||
\end{inset}
|
||||
These sites are
|
||||
|
@ -100,14 +124,11 @@ but the system as-released does not currently provide these features.
|
|||
|
||||
In the current release, the system has some rough edges.
|
||||
It is quite slow to start up---loading the initial image into the
|
||||
{\scm} virtual machine takes about a cpu second.
|
||||
{\scm} virtual machine induces a noticeable delay.
|
||||
This can be fixed with the static heap linker provided with this release.
|
||||
|
||||
This manual is very, very rough.
|
||||
At some point, we hope to polish it up, finish it off, and re-typeset it
|
||||
using markup, so we can generate html, info nodes, and {\TeX} output from
|
||||
the single source without having to deal with Texinfo.
|
||||
But it's all there is, for now.
|
||||
We welcome parties interested in porting the manual to a more portable
|
||||
XML or SGML format; please contact us if you are interested in doing so.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Naming conventions}
|
||||
|
@ -375,11 +396,17 @@ All told, the \ex{define-record} form above defines the following procedures:
|
|||
(ship:size \var{ship}) & Retrieve the \var{size} field. \\
|
||||
\hline
|
||||
(set-ship:x \var{ship} \var{new-x}) & Assign the \var{x} field. \\
|
||||
(set-ship:y \var{ship} \var{new-y}) & Assign the \var{x} field. \\
|
||||
(set-ship:y \var{ship} \var{new-y}) & Assign the \var{y} field. \\
|
||||
(set-ship:size \var{ship} \var{new-size}) & Assign the \var{size} field. \\
|
||||
\hline
|
||||
(modify-ship:x \var{ship} \var{xfun}) & Modify \var{x} field with \var{xfun}. \\
|
||||
(modify-ship:y \var{ship} \var{yfun}) & Modify \var{y} field with \var{yfun}. \\
|
||||
(modify-ship:size \var{ship} \var{sizefun}) & Modify \var{size} field with \var{sizefun}. \\
|
||||
\hline
|
||||
(ship? \var{object}) & Type predicate. \\
|
||||
\hline
|
||||
(copy-ship \var{ship}) & Shallow-copy of the record. \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
%
|
||||
|
@ -388,6 +415,8 @@ An implementation of \ex{define-record} is available as a macro for Scheme
|
|||
programmers to define their own record types;
|
||||
the syntax is accessed by opening the package \ex{defrec-package}, which
|
||||
exports the single syntax form \ex{define-record}.
|
||||
See the source code for the \ex{defrec-package} module
|
||||
for further details of the macro.
|
||||
|
||||
You must open this package to access the form.
|
||||
Scsh does not export a record-definition package by default as there are
|
||||
|
@ -417,21 +446,9 @@ you could not read and internalise such a twisted account without
|
|||
bleeding from the nose and ears.
|
||||
|
||||
However, you might keep in mind the following simple fact: of all the
|
||||
standards, {\Posix}, as far as I have been able to determine,
|
||||
is the least common denominator.
|
||||
standards, {\Posix} is the least common denominator.
|
||||
So when this manual repeatedly refers to {\Posix}, the point is ``the
|
||||
thing we are describing should be portable just about anywhere.''
|
||||
Scsh sticks to {\Posix} when at all possible; it's major departure is
|
||||
Scsh sticks to {\Posix} when at all possible; its major departure is
|
||||
symbolic links, which aren't in {\Posix} (see---it
|
||||
really \emph{is} a least common denominator).
|
||||
|
||||
However, just because {\Posix} is the l.c.d. standard doesn't mean everyone
|
||||
supports all of it.
|
||||
The guerilla PC {\Unix} implementations that have been springing up on
|
||||
the net (\eg, NetBSD, Linux, FreeBSD, and so forth) are only recently coming
|
||||
into compliance with the standard---although they are getting there.
|
||||
We have been able to implement scsh completely on all of these systems,
|
||||
however---the single exception is NeXTSTEP, whose buggy {\Posix} libraries
|
||||
restricts us to partial support (these lacunae are indicated where relevant
|
||||
in the rest of the manual).\footnote{Feel like porting scsh from {\Posix} to
|
||||
NeXT's BSD API? Send us your fixes; we'll fold them in.}
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
% man.t2p
|
||||
% Dorai Sitaram
|
||||
% Feb 6, 2000
|
||||
|
||||
% This file contains the tex2page macros needed to process
|
||||
% the scsh LaTeX document scsh-n.n.n/doc/scsh-manual/man.tex.
|
||||
% Copy (or link) this file alongside man.tex and run
|
||||
%
|
||||
% tex2page man
|
||||
|
||||
\input css.t2p
|
||||
\dontuseimgforhtmlmath
|
||||
|
||||
\let\pagebreak\relax
|
||||
|
||||
\let\small\relax
|
||||
|
||||
%\let\PRIMtableofcontents\tableofcontents
|
||||
%\def\tableofcontents{\chapter*{Contents}\PRIMtableofcontents}
|
||||
|
||||
\def\subtitle#1{\def\savesubtitle{#1}}
|
||||
|
||||
\def\maketitle{
|
||||
\subject{\TIIPtitle}
|
||||
{\bf \hr}
|
||||
\rightline{\savesubtitle}
|
||||
\bigskip\bigskip
|
||||
\bigskip\bigskip
|
||||
{\bf\TIIPauthor}
|
||||
{\bf\hr}
|
||||
}
|
||||
|
||||
\let\PRIMdocument\document
|
||||
|
||||
\def\document{\PRIMdocument
|
||||
|
||||
\let\ttchars\relax
|
||||
\let\ttt\tt
|
||||
|
||||
%\def\~{\rawhtml~\endrawhtml}
|
||||
\def\~{\char`\~}
|
||||
\def\cd#1{{\tt\def\\{\char`\\}\defcsactive\${\char`\$}\defcsactive\&{\char`\&}#1}}
|
||||
\def\cddollar{\undefcsactive\$}
|
||||
\def\cdmath{\undefcsactive\$}
|
||||
\def\codeallowbreaks{\relax}
|
||||
\def\defvarx#1#2{\index{#1}\leftline{{\tt #1} \qquad #2}}
|
||||
|
||||
\let\PRIMflushright\flushright
|
||||
|
||||
\def\flushright{\PRIMflushright\TIIPtabularborder=0 }
|
||||
|
||||
\let\PRIMfigure\figure
|
||||
\let\PRIMendfigure\endfigure
|
||||
|
||||
\def\figure{\par\hrule\PRIMfigure}
|
||||
\def\endfigure{\PRIMendfigure\hrule\par}
|
||||
|
||||
\let\PRIMtable\table
|
||||
\let\PRIMendtable\endtable
|
||||
|
||||
\def\table{\par\hrule\PRIMtable}
|
||||
\def\endtable{\PRIMendtable\hrule\par}
|
||||
|
||||
\imgdef\vdots{\bf.\par.\par.}
|
||||
|
||||
\evalh{
|
||||
|
||||
(define all-blanks?
|
||||
(lambda (s)
|
||||
(andmap
|
||||
char-whitespace?
|
||||
(string->list s))))
|
||||
|
||||
}
|
||||
|
||||
|
||||
\def\spaceifnotempty{\evalh{
|
||||
|
||||
(let ((x (ungroup (get-token))))
|
||||
(unless (all-blanks? x)
|
||||
(emit #\space)))
|
||||
|
||||
}}
|
||||
|
||||
\def\dfnix#1#2#3#4{\leftline{{\tt(#1\spaceifnotempty{#2}{\it#2})} \quad $\longrightarrow$ \quad {\it #3} \qquad (#4)} \index}
|
||||
|
||||
\def\ex#1{{\tt #1}}
|
||||
\def\l#1{lambda (#1)}
|
||||
\def\lx#1{lambda {#1}}
|
||||
%\def\notenum#1{}
|
||||
%\def\project#1{}
|
||||
\def\var#1{{\it #1\/}}
|
||||
\def\vari#1#2{\mbox{{\it #1\/}\undefcsactive\$$_{#2}$}}
|
||||
|
||||
\renewenvironment{boxedfigure}{\def\srecomment#1{\\#1\\}%
|
||||
\begin{figure}\pagestyle}{\end{figure}}
|
||||
|
||||
\newenvironment{centercode}{\begin{code}}{\end{code}}
|
||||
|
||||
\def\setupcode{\tt%
|
||||
\def\\{\char`\\}%
|
||||
\defcsactive\${\$}%
|
||||
\def\evalto{==> }%
|
||||
\defcsactive\%{\%}\obeywhitespace}
|
||||
|
||||
\newenvironment{code}{\begin{quote}\bgroup\setupcode\GOBBLEOPTARG}
|
||||
{\egroup\end{quote}}
|
||||
|
||||
\newenvironment{codebox}{\begin{tableplain}\bgroup\setupcode\GOBBLEOPTARG}
|
||||
{\egroup\end{tableplain}}
|
||||
|
||||
\renewenvironment{desc}{\begin{quote}}{\end{quote}}
|
||||
|
||||
\renewenvironment{exampletable}{%
|
||||
\def\header#1{\\\leftline{#1}\\}%
|
||||
\def\splitline#1#2{\\\leftline{#1}\\\leftline{#2}}%
|
||||
\begin{tabular}{}}{\end{tabular}}
|
||||
|
||||
\newenvironment{tightcode}{\begin{code}}{\end{code}}
|
||||
\renewenvironment{widecode}{\begin{code}}{\end{code}}
|
||||
|
||||
\renewenvironment{inset}{\begin{quote}}{\end{quote}}
|
||||
\renewenvironment{leftinset}{\begin{quote}}{\end{quote}}
|
||||
\renewenvironment{tightinset}{\begin{quote}}{\end{quote}}
|
||||
\renewenvironment{tightleftinset}{\begin{quote}}{\end{quote}}
|
||||
}
|
|
@ -1,16 +1,19 @@
|
|||
%&latex -*- latex -*-
|
||||
% -*- latex -*-
|
||||
|
||||
% This is the reference manual for the Scheme Shell.
|
||||
|
||||
\documentclass[twoside]{report}
|
||||
\usepackage{code,boxedminipage,makeidx,palatino,ct,
|
||||
headings,mantitle,array,matter,mysize10}
|
||||
headings,mantitle,array,matter,mysize10,tex2page}
|
||||
|
||||
\texonly
|
||||
\let\url\relax
|
||||
\usepackage[dvipdfm,hyperindex,hypertex,
|
||||
pdftitle={scsh manual, release 0.5.3},
|
||||
pdfauthor={Olin Shivers and Brian D.~Carlstrom}
|
||||
colorlinks=true,linkcolor=blue,pagecolor=blue,urlcolor=blue,
|
||||
pdfstartview=FitH,pdfview=FitH]{hyperref}
|
||||
pdftitle={scsh manual, release 0.5.3},
|
||||
pdfauthor={Olin Shivers and Brian D.~Carlstrom}
|
||||
colorlinks=true,linkcolor=blue,pagecolor=blue,urlcolor=blue,
|
||||
pdfstartview=FitH,pdfview=FitH]{hyperref}
|
||||
\endtexonly
|
||||
|
||||
% These fonts are good choices for screen-readable pdf, but the man needs
|
||||
% a pass over the layout, since the this tt font will blow out the width
|
||||
|
@ -47,7 +50,6 @@
|
|||
\include{awk}
|
||||
\include{miscprocs}
|
||||
\include{running}
|
||||
\include{changes}
|
||||
\include{todo}
|
||||
|
||||
\backmatter
|
||||
|
|
|
@ -50,7 +50,8 @@
|
|||
\vskip -0.3\baselineskip
|
||||
\wideline{\leaders\hrule height 4pt\hfill}
|
||||
\wideline{\hfill\subtitlefont\begin{tabular}[t]{@{}r@{}}\@subtitle%
|
||||
\end{tabular}\hskip 1in} % subtitle
|
||||
\\\@date%
|
||||
\end{tabular}} % subtitle
|
||||
%
|
||||
% author
|
||||
\vskip 0pt plus 1filll
|
||||
|
|
|
@ -11,7 +11,7 @@ The basic elements of this notation are \emph{process forms},
|
|||
\section{Extended process forms and i/o redirections}
|
||||
An \emph{extended process form} is a specification of a {\Unix} process to
|
||||
run, in a particular I/O environment:
|
||||
\codex{\var{epf} {\synteq} (\var{pf} $\var{redir}_1$ {\ldots} $\var{redir}_n$)}
|
||||
\codex{\var{epf} {\synteq} (\var{pf} $ \var{redir}_1$ {\ldots} $ \var{redir}_n $)}
|
||||
where \var{pf} is a process form and the $\var{redir}_i$ are redirection specs.
|
||||
A \emph{redirection spec} is one of:
|
||||
\begin{inset}
|
||||
|
@ -140,7 +140,7 @@ That is, it is equivalent to:
|
|||
%
|
||||
\codex{(begin (apply exec-path `(\var{prog} \vari{arg}1 {\ldots} \vari{arg}n)))}
|
||||
%
|
||||
\ex{Exec-path} is the version of the \ex{exec()} system call that
|
||||
\ex{Exec-path} is the version of the \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec()}} system call that
|
||||
uses scsh's path list to search for an executable.
|
||||
The program and the arguments must be either strings, symbols, or integers.
|
||||
Symbols and integers are coerced to strings.
|
||||
|
@ -438,7 +438,7 @@ Our scsh programmer decides to run \ex{myprog} with stdout and stderr redirected
|
|||
\emph{via {\Unix} pipes} to the ports \ex{port1} and \ex{port2}, respectively.
|
||||
He gets into trouble when he subsequently says \ex{(read port2)}.
|
||||
The {\Scheme} \ex{read} routine reads the open paren, and then hangs in a
|
||||
\ex{read()} system call trying to read a matching close paren.
|
||||
\ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=read&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{read()}} system call trying to read a matching close paren.
|
||||
But before \ex{myprog} sends the close paren down the stderr
|
||||
pipe, it first tries to write a megabyte of data to the stdout pipe.
|
||||
However, {\Scheme} is not reading that pipe---it's stuck waiting for input on
|
||||
|
|
|
@ -398,7 +398,7 @@ would implement a simple-minded version of the Unix \ex{echo} program:
|
|||
%
|
||||
The idea would be that the command
|
||||
\codex{ekko Hi there.}
|
||||
would by expanded by the \ex{exec(2)} kernel call into
|
||||
would by expanded by the \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec(2)}} kernel call into
|
||||
%
|
||||
\begin{code}
|
||||
/usr/local/bin/scsh -e main -s ekko Hi there.\end{code}
|
||||
|
@ -408,7 +408,7 @@ call the entry point on the command-line list
|
|||
\codex{(main '("ekko" "Hi" "there."))}
|
||||
and exit.
|
||||
|
||||
Unfortunately, the {\Unix} \ex{exec(2)} syscall's support for scripts is
|
||||
Unfortunately, the {\Unix} \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec(2)}} syscall's support for scripts is
|
||||
not very general or well-designed.
|
||||
It will not handle multiple arguments;
|
||||
the \ex{\#!} line is usually required to contain no more than 32 characters;
|
||||
|
@ -555,7 +555,7 @@ Writing it this way makes it possible to compile the program
|
|||
(for-each (\l{arg} (display arg) (display " "))
|
||||
(cdr args)))\end{code}
|
||||
%
|
||||
The \ex{exec(2)} expansion of the \ex{\#!} line together with
|
||||
The \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec(2)}} expansion of the \ex{\#!} line together with
|
||||
the scsh expansion of the ``\verb|\ ekko|'' meta-argument
|
||||
(see section~\ref{sec:meta-arg}) gives the following command-line expansion:
|
||||
\begin{code}
|
||||
|
|
|
@ -1,27 +1,71 @@
|
|||
% -*- latex -*-
|
||||
\chapter{Strings and characters}
|
||||
|
||||
Scsh provides a set of procedures for processing strings and characters.
|
||||
The procedures provided match regular expressions, search strings,
|
||||
parse file-names, and manipulate sets of characters.
|
||||
|
||||
Also see chapters \ref{chapt:sre}, \ref{chapt:rdelim} and \ref{chapt:fr-awk}
|
||||
on regular-expressions, record I/O, field parsing, and the awk loop.
|
||||
The procedures documented there allow you to search and pattern-match strings,
|
||||
read character-delimited records from ports,
|
||||
use regular expressions to split the records into fields
|
||||
(for example, splitting a string at every occurrence of colon or white-space),
|
||||
and loop over streams of these records in a convenient way.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{String manipulation}
|
||||
\label{sec:stringmanip}
|
||||
|
||||
Strings are the basic communication medium for {\Unix} processes, so a
|
||||
shell language must have reasonable facilities for manipulating them.
|
||||
Unix programming environment must have reasonable facilities for manipulating
|
||||
them.
|
||||
Scsh provides a powerful set of procedures for processing strings and
|
||||
characters.
|
||||
Besides the the facilities described in this chapter, scsh also provides
|
||||
\begin{itemize}
|
||||
\itum{Regular expressions (chapter~\ref{chapt:sre})}
|
||||
A complete regular-expression system.
|
||||
|
||||
\itum{Field parsing, delimited record I/O and the awk loop
|
||||
(chapter~\ref{chapt:fr-awk})}
|
||||
These procedures let you read in chunks of text delimited by selected
|
||||
characters, and
|
||||
parse each record into fields based on regular expressions
|
||||
(for example, splitting a string at every occurrence of colon or
|
||||
white-space).
|
||||
The \ex{awk} form allows you to loop over streams of these records
|
||||
in a convenient way.
|
||||
|
||||
\itum{The SRFI-13 string libraries}
|
||||
This pair of libraries contains procedures that create, fold, iterate over,
|
||||
search, compare, assemble, cut, hash, case-map, and otherwise manipulate
|
||||
strings.
|
||||
They are provided by the \ex{string-lib} and \ex{string-lib-internals}
|
||||
packages, and are also available in the default \ex{scsh} package.
|
||||
|
||||
More documentation on these procedures can be found at URLs
|
||||
\begin{tightinset}
|
||||
% The gratuitous mbox makes xdvi render the hyperlinks better.
|
||||
\texonly
|
||||
\mbox{\url{http://srfi.schemers.org/srfi-13/srfi-13.html}}\\
|
||||
\url{http://srfi.schemers.org/srfi-13/srfi-13.txt}
|
||||
\endtexonly
|
||||
% Changed the \mbox into \urlh for tex2page to avoid problems runing tex2page
|
||||
\htmlonly
|
||||
\urlh{http://srfi.schemers.org/srfi-13/srfi-13.html}{http://srfi.schemers.org/srfi-13/srfi-13.html}\\
|
||||
\urlh{http://srfi.schemers.org/srfi-13/srfi-13.txt}{http://srfi.schemers.org/srfi-13/srfi-13.txt}
|
||||
\endhtmlonly
|
||||
\end{tightinset}
|
||||
|
||||
\itum{The SRFI-14 character-set library}
|
||||
This library provides a set-of-characters abstraction, which is frequently
|
||||
useful when searching, parsing, filtering or otherwise operating on
|
||||
strings and character data. The SRFI is provided by the \ex{char-set-lib}
|
||||
package; it's bindings are also available in the default \ex{scsh} package.
|
||||
|
||||
More documentation on this library can be found at URLs
|
||||
\begin{tightinset}
|
||||
% The gratuitous mbox makes xdvi render the hyperlinks better.
|
||||
\texonly
|
||||
\mbox{\url{http://srfi.schemers.org/srfi-14/srfi-14.html}}\\
|
||||
\url{http://srfi.schemers.org/srfi-14/srfi-14.txt}
|
||||
\endtexonly
|
||||
% Changed the \mbox into \urlh for tex2page to avoid problems runing tex2page
|
||||
\htmlonly
|
||||
\urlh{http://srfi.schemers.org/srfi-14/srfi-14.html}{http://srfi.schemers.org/srfi-14/srfi-14.html}\\
|
||||
\urlh{http://srfi.schemers.org/srfi-14/srfi-14.txt}{http://srfi.schemers.org/srfi-14/srfi-14.txt}
|
||||
\endhtmlonly
|
||||
\end{tightinset}
|
||||
|
||||
\end{itemize}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{Manipulating file-names}
|
||||
\section{Manipulating file names}
|
||||
\label{sec:filenames}
|
||||
|
||||
These procedures do not access the file-system at all; they merely operate
|
||||
|
@ -30,7 +74,7 @@ design. Perhaps a more sophisticated system would be better, something
|
|||
like the pathname abstractions of {\CommonLisp} or MIT Scheme. However,
|
||||
being {\Unix}-specific, we can be a little less general.
|
||||
|
||||
\subsubsection{Terminology}
|
||||
\subsection{Terminology}
|
||||
These procedures carefully adhere to the {\Posix} standard for file-name
|
||||
resolution, which occasionally entails some slightly odd things.
|
||||
This section will describe these rules, and give some basic terminology.
|
||||
|
@ -95,7 +139,7 @@ interpreted in file-name form, \ie, as root.
|
|||
|
||||
|
||||
|
||||
\subsubsection{Procedures}
|
||||
\subsection{Procedures}
|
||||
|
||||
\defun {file-name-directory?} {fname} \boolean
|
||||
\defunx {file-name-non-directory?} {fname} \boolean
|
||||
|
@ -355,38 +399,7 @@ is also frequently useful for expanding file-names.
|
|||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{Other string manipulation facilities}
|
||||
|
||||
\defun {index} {string char [start]} {{\fixnum} or false}
|
||||
\defunx {rindex} {string char [start]} {{\fixnum} or false}
|
||||
\begin{desc}
|
||||
These procedures search through \var{string} looking for an occurrence
|
||||
of character \var{char}. \ex{index} searches left-to-right; \ex{rindex}
|
||||
searches right-to-left.
|
||||
|
||||
\ex{index} returns the smallest index $i$ of \var{string} greater
|
||||
than or equal to \var{start} such that $\var{string}[i] = \var{char}$.
|
||||
The default for \var{start} is zero. If there is no such match,
|
||||
\ex{index} returns false.
|
||||
|
||||
\ex{rindex} returns the largest index $i$ of \var{string} less than
|
||||
\var{start} such that $\var{string}[i] = \var{char}$.
|
||||
The default for \var{start} is \ex{(string-length \var{string})}.
|
||||
If there is no such match, \ex{rindex} returns false.
|
||||
\end{desc}
|
||||
|
||||
I should probably snarf all the MIT Scheme string functions, and stick them
|
||||
in a package. {\Unix} programs need to mung character strings a lot.
|
||||
|
||||
MIT string match commands:
|
||||
\begin{tightcode}
|
||||
[sub]string-match-{forward,backward}[-ci]
|
||||
[sub]string-{prefix,suffix}[-ci]?
|
||||
[sub]string-find-{next,previous}-char[-ci]
|
||||
[sub]string-find-{next,previous}-char-in-set
|
||||
[sub]string-replace[!]
|
||||
\ldots\etc\end{tightcode}
|
||||
These are not currently provided.
|
||||
\section{Other string manipulation facilities}
|
||||
|
||||
\begin{defundesc} {substitute-env-vars} {fname} \str
|
||||
Replace occurrences of environment variables with their values.
|
||||
|
@ -412,315 +425,72 @@ These are not currently provided.
|
|||
\end{desc}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Character sets}
|
||||
\label{sec:char-sets}
|
||||
\section{Character predicates}
|
||||
|
||||
Scsh provides a \ex{char-set} type for expressing sets of characters.
|
||||
These sets are used by some of the delimited-input procedures
|
||||
(section~\ref{sec:field-reader}).
|
||||
Scsh's character set package was adapted and extended from
|
||||
Project Mac's MIT Scheme package.
|
||||
Note that the character type used in the current implementation corresponds
|
||||
to the ASCII character set---but you would be wise not to build this
|
||||
assumption into your code if you can help it.\footnote{
|
||||
Actually, it's slightly uglier than that, albeit somewhat more
|
||||
useful. The current character type corresponds to an eight-bit
|
||||
superset of ASCII. The \ex{ascii->char} and \ex{char->ascii}
|
||||
functions will preserve this eighth bit. However, none of the
|
||||
the high 128 characters appear in any of the standard character
|
||||
sets defined in section~\ref{sec:std-csets}, except for
|
||||
\ex{char-set:full}. If someone would email the authors a listing
|
||||
of the full Latin-1 definition, we'll be happy to upgrade these
|
||||
sets' definitions to make them Latin-1 compliant.}
|
||||
|
||||
\defun{char-set?}{x}\boolean
|
||||
\begin{desc}
|
||||
Is the object \var{x} a character set?
|
||||
\end{desc}
|
||||
|
||||
\defun{char-set=}{\vari{cs}1 \vari{cs}2\ldots}\boolean
|
||||
\begin{desc}
|
||||
Are the character sets equal?
|
||||
\end{desc}
|
||||
|
||||
\defun{char-set<=}{\vari{cs}1 \vari{cs}2\ldots}\boolean
|
||||
\begin{desc}
|
||||
Returns true if every character set \vari{cs}{i} is
|
||||
a subset of character set \vari{cs}{i+1}.
|
||||
\end{desc}
|
||||
|
||||
\defun{char-set-fold}{kons knil cs}\object
|
||||
\begin{desc}
|
||||
This is the fundamental iterator for character sets.
|
||||
Applies the function \var{kons} across the character set \var{cs} using
|
||||
initial state value \var{knil}.
|
||||
That is, if \var{cs} is the empty set, the procedure returns \var{knil}.
|
||||
Otherwise, some element \var{c} of \var{cs} is chosen; let \var{cs'} be
|
||||
the remaining, unchosen characters.
|
||||
The procedure returns
|
||||
\begin{tightcode}
|
||||
(char-set-fold \var{kons} (\var{kons} \var{c} \var{knil}) \var{cs'})\end{tightcode}
|
||||
For example, we could define \ex{char-set-members} (see below)
|
||||
as
|
||||
\begin{tightcode}
|
||||
(lambda (cs) (char-set-fold cons '() cs))\end{tightcode}
|
||||
|
||||
\remark{This procedure was formerly named \texttt{\indx{reduce-char-set}}.
|
||||
The old binding is still provided, but is deprecated and will
|
||||
probably vanish in a future release.}
|
||||
\end{desc}
|
||||
|
||||
\defun{char-set-for-each}{p cs}{\undefined}
|
||||
\begin{desc}
|
||||
Apply procedure \var{p} to each character in the character set \var{cs}.
|
||||
Note that the order in which \var{p} is applied to the characters in the
|
||||
set is not specified, and may even change from application to application.
|
||||
\end{desc}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{Creating character sets}
|
||||
|
||||
\defun{char-set}{\vari{char}1\ldots}{char-set}
|
||||
\begin{desc}
|
||||
Return a character set containing the given characters.
|
||||
\end{desc}
|
||||
|
||||
\defun{chars->char-set}{chars}{char-set}
|
||||
\begin{desc}
|
||||
Return a character set containing the characters in the list \var{chars}.
|
||||
\end{desc}
|
||||
|
||||
\defun{string->char-set}{s}{char-set}
|
||||
\begin{desc}
|
||||
Return a character set containing the characters in the string \var{s}.
|
||||
\end{desc}
|
||||
|
||||
\defun{predicate->char-set}{pred}{char-set}
|
||||
\begin{desc}
|
||||
Returns a character set containing every character \var{c} such that
|
||||
\ex{(\var{pred} \var{c})} returns true.
|
||||
\end{desc}
|
||||
|
||||
\defun{ascii-range->char-set}{lower upper}{char-set}
|
||||
\begin{desc}
|
||||
Returns a character set containing every character whose {\Ascii}
|
||||
code lies in the half-open range $[\var{lower},\var{upper})$.
|
||||
\end{desc}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{Querying character sets}
|
||||
\defun {char-set-members}{char-set}{character-list}
|
||||
\begin{desc}
|
||||
This procedure returns a list of the members of \var{char-set}.
|
||||
\end{desc}
|
||||
|
||||
\defunx{char-set-contains?}{char-set char}\boolean
|
||||
\begin{desc}
|
||||
This procedure tests \var{char} for membership in set \var{char-set}.
|
||||
\remark{Previous releases of scsh called this procedure \ex{char-set-member?},
|
||||
reversing the order of the arguments.
|
||||
This made sense, but was unfortunately the reverse order in which the
|
||||
arguments appear in MIT Scheme.
|
||||
A reasonable argument order was not backwards-compatible with MIT Scheme;
|
||||
on the other hand, the MIT Scheme argument order was counter-intuitive
|
||||
and at odds with common mathematical notation and the \ex{member} family
|
||||
of R4RS procedures.
|
||||
|
||||
We sought to escape the dilemma by shifting to a new name.}
|
||||
\end{desc}
|
||||
|
||||
\defun{char-set-size}{cs}\integer
|
||||
\begin{desc}
|
||||
Returns the number of elements in character set \var{cs}.
|
||||
\end{desc}
|
||||
|
||||
\defun{char-set-every?}{pred cs}\boolean
|
||||
\defunx{char-set-any?}{pred cs}\object
|
||||
\begin{desc}
|
||||
The \ex{char-set-every?} procedure returns true if predicate \var{pred}
|
||||
returns true of every character in the character set \var{cs}.
|
||||
|
||||
Likewise, \ex{char-set-any?} applies \var{pred} to every character in
|
||||
character set \var{cs}, and returns the first true value it finds.
|
||||
If no character produces a true value, it returns false.
|
||||
|
||||
The order in which these procedures sequence through the elements of
|
||||
\var{cs} is not specified.
|
||||
\end{desc}
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{Character-set algebra}
|
||||
\defun {char-set-invert}{char-set}{char-set}
|
||||
\defunx{char-set-union}{\vari{char-set}1\ldots}{char-set}
|
||||
\defunx{char-set-intersection}{\vari{char-set}1 \vari{char-set}2\ldots}{char-set}
|
||||
\defunx{char-set-difference}{\vari{char-set}1 \vari{char-set}2\ldots}{char-set}
|
||||
\begin{desc}
|
||||
These procedures implement set complement, union, intersection, and difference
|
||||
for character sets.
|
||||
The union, intersection, and difference operations are n-ary, associating
|
||||
to the left; the difference function requires at least one argument, while
|
||||
union and intersection may be applied to zero arguments.
|
||||
\end{desc}
|
||||
|
||||
\defun {char-set-adjoin}{cs \vari{char}1\ldots}{char-set}
|
||||
\defunx{char-set-delete}{cs \vari{char}1\ldots}{char-set}
|
||||
\begin{desc}
|
||||
Add/delete the \vari{char}i characters to/from character set \var{cs}.
|
||||
\end{desc}
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{Standard character sets}
|
||||
\label{sec:std-csets}
|
||||
Several character sets are predefined for convenience:
|
||||
|
||||
\begin{center}
|
||||
\newcommand{\entry}[1]{\ex{#1}\index{#1}}
|
||||
\begin{tabular}{|ll|}
|
||||
\hline
|
||||
\entry{char-set:lower-case} & Lower-case alphabetic chars \\
|
||||
\entry{char-set:upper-case} & Upper-case alphabetic chars \\
|
||||
\entry{char-set:alphabetic} & Alphabetic chars \\
|
||||
\entry{char-set:numeric} & Decimal digits: 0--9 \\
|
||||
\entry{char-set:alphanumeric} & Alphabetic or numeric \\
|
||||
\entry{char-set:graphic} & Printing characters except space \\
|
||||
\entry{char-set:printing} & Printing characters including space \\
|
||||
\entry{char-set:whitespace} & Whitespace characters \\
|
||||
\entry{char-set:control} & Control characters \\
|
||||
\entry{char-set:punctuation} & Punctuation characters \\
|
||||
\entry{char-set:hex-digit} & A hexadecimal digit: 0--9, A--F, a--f \\
|
||||
\entry{char-set:blank} & Blank characters \\
|
||||
\entry{char-set:ascii} & A character in the ASCII set. \\
|
||||
\entry{char-set:empty} & Empty set \\
|
||||
\entry{char-set:full} & All characters \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
The first eleven of these correspond to the character classes defined in
|
||||
Posix.
|
||||
Note that there may be characters in \ex{char-set:alphabetic} that are
|
||||
neither upper or lower case---this might occur in implementations that
|
||||
use a character type richer than ASCII, such as Unicode.
|
||||
A ``graphic character'' is one that would put ink on your page.
|
||||
While the exact composition of these sets may vary depending upon the
|
||||
character type provided by the Scheme system upon which scsh is running,
|
||||
here are the definitions for some of the sets in an ASCII character set:
|
||||
\begin{center}
|
||||
\newcommand{\entry}[1]{\ex{#1}\index{#1}}
|
||||
\begin{tabular}{|ll|}
|
||||
\hline
|
||||
char-set:alphabetic & A--Z and a--z \\
|
||||
char-set:lower-case & a--z \\
|
||||
char-set:upper-case & A--Z \\
|
||||
char-set:graphic & Alphanumeric + punctuation \\
|
||||
char-set:whitespace & Space, newline, tab, page,
|
||||
vertical tab, carriage return \\
|
||||
char-set:blank & Space and tab \\
|
||||
char-set:control & ASCII 0--31 and 127 \\
|
||||
char-set:punctuation & \verb|!"#$%&'()*+,-./:;<=>|\verb#?@[\]^_`{|}~# \\
|
||||
\hline
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
|
||||
\defun {char-alphabetic?}\character\boolean
|
||||
\defun {char-letter?}\character\boolean
|
||||
\defunx{char-lower-case?}\character\boolean
|
||||
\defunx{char-upper-case?}\character\boolean
|
||||
\defunx{char-numeric? }\character\boolean
|
||||
\defunx{char-alphanumeric?}\character\boolean
|
||||
\defunx{char-title-case?}\character\boolean
|
||||
\defunx{char-digit?}\character\boolean
|
||||
\defunx{char-letter+digit?}\character\boolean
|
||||
\defunx{char-graphic?}\character\boolean
|
||||
\defunx{char-printing?}\character\boolean
|
||||
\defunx{char-whitespace?}\character\boolean
|
||||
\defunx{char-blank?}\character\boolean
|
||||
\defunx{char-control?}\character\boolean
|
||||
\defunx{char-iso-control?}\character\boolean
|
||||
\defunx{char-punctuation?}\character\boolean
|
||||
\defunx{char-hex-digit?}\character\boolean
|
||||
\defunx{char-ascii?}\character\boolean
|
||||
\begin{desc}
|
||||
These predicates are defined in terms of the above character sets.
|
||||
Each of these predicates tests for membership in one of the standard
|
||||
character sets provided by the SRFI-14 character-set library.
|
||||
Additionally, the following redundant bindings are provided for {R5RS}
|
||||
compatibility:
|
||||
\begin{inset}
|
||||
\begin{tabular}{ll}
|
||||
{R5RS} name & scsh definition \\ \hline
|
||||
\ex{char-alphabetic?} & \ex{char-letter+digit?} \\
|
||||
\ex{char-numeric?} & \ex{char-digit?} \\
|
||||
\ex{char-alphanumeric?} & \ex{char-letter+digit?}
|
||||
\end{tabular}
|
||||
\end{inset}
|
||||
\end{desc}
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\subsection{Linear-update character-set operations}
|
||||
These procedures have a hybrid pure-functional/side-effecting semantics:
|
||||
they are allowed, but not required, to side-effect one of their parameters
|
||||
in order to construct their result.
|
||||
An implementation may legally implement these procedures as pure,
|
||||
side-effect-free functions, or it may implement them using side effects,
|
||||
depending upon the details of what is the most efficient or simple to
|
||||
implement in terms of the underlying representation.
|
||||
\section{Deprecated character-set procedures}
|
||||
\label{sec:char-sets}
|
||||
|
||||
What this means is that clients of these procedures \emph{may not} rely
|
||||
upon these procedures working by side effect.
|
||||
For example, this is not guaranteed to work:
|
||||
\begin{verbatim}
|
||||
(let ((cs (char-set #\a #\b #\c)))
|
||||
(char-set-adjoin! cs #\d)
|
||||
cs) ; Could be either {a,b,c} or {a,b,c,d}.
|
||||
\end{verbatim}
|
||||
However, this is well-defined:
|
||||
\begin{verbatim}
|
||||
(let ((cs (char-set #\a #\b #\c)))
|
||||
(char-set-adjoin! cs #\d)) ; {a,b,c,d}
|
||||
\end{verbatim}
|
||||
So clients of these procedures write in a functional style, but must
|
||||
additionally be sure that, when the procedure is called, there are no
|
||||
other live pointers to the potentially-modified character set (hence the term
|
||||
``linear update'').
|
||||
The SRFI-13 character-set library grew out of an earlier library developed
|
||||
for scsh.
|
||||
However, the SRFI standardisation process introduced incompatibilities with
|
||||
the original scsh bindings.
|
||||
The current version of scsh provides the library
|
||||
\ex{obsolete-char-set-lib}, which contains the old bindings found in
|
||||
previous releases of scsh.
|
||||
The following table lists the members of this library, along with
|
||||
the equivalent SRFI-13 binding. This obsolete library is deprecated and
|
||||
\emph{not} open by default in the standard \ex{scsh} environment;
|
||||
new code should use the SRFI-13 bindings.
|
||||
\begin{inset}
|
||||
\begin{tabular}{ll}
|
||||
Old \ex{obsolete-char-set-lib} & SRFI-13 \ex{char-set-lib} \\ \hline
|
||||
|
||||
There are two benefits to this convention:
|
||||
\begin{itemize}
|
||||
\item Implementations are free to provide the most efficient possible
|
||||
implementation, either functional or side-effecting.
|
||||
\item Programmers may nonetheless continue to assume that character sets
|
||||
are purely functional data structures: they may be reliably shared
|
||||
without needing to be copied, uniquified, and so forth.
|
||||
\end{itemize}
|
||||
|
||||
In practice, these procedures are most useful for efficiently constructing
|
||||
character sets in a side-effecting manner, in some limited local context,
|
||||
before passing the character set outside the local construction scope to be
|
||||
used in a functional manner.
|
||||
|
||||
Scsh provides no assistance in checking the linearity of the potentially
|
||||
side-effected parameters passed to these functions --- there's no linear
|
||||
type checker or run-time mechanism for detecting violations.
|
||||
|
||||
\defun{char-set-copy}{cs}{char-set}
|
||||
\begin{desc}
|
||||
Returns a copy of the character set \var{cs}.
|
||||
``Copy'' means that if either the input parameter or the
|
||||
result value of this procedure is passed to one of the linear-update
|
||||
procedures described below, the other character set is guaranteed
|
||||
not to be altered.
|
||||
(A system that provides pure-functional implementations of the rest of
|
||||
the linear-operator suite could implement this procedure as the
|
||||
identity function.)
|
||||
\end{desc}
|
||||
|
||||
\defun{char-set-adjoin!}{cs \vari{char}1\ldots}{char-set}
|
||||
\begin{desc}
|
||||
Add the \vari{char}i characters to character set \var{cs}, and
|
||||
return the result.
|
||||
This procedure is allowed, but not required, to side-effect \var{cs}.
|
||||
\end{desc}
|
||||
|
||||
\defun{char-set-delete!}{cs \vari{char}1\ldots}{char-set}
|
||||
\begin{desc}
|
||||
Remove the \vari{char}i characters to character set \var{cs}, and
|
||||
return the result.
|
||||
This procedure is allowed, but not required, to side-effect \var{cs}.
|
||||
\end{desc}
|
||||
|
||||
\defun {char-set-invert!}{char-set}{char-set}
|
||||
\defunx{char-set-union!}{\vari{char-set}1 \vari{char-set}2\ldots}{char-set}
|
||||
\defunx{char-set-intersection!}{\vari{char-set}1 \vari{char-set}2\ldots}{char-set}
|
||||
\defunx{char-set-difference!}{\vari{char-set}1 \vari{char-set}2\ldots}{char-set}
|
||||
\begin{desc}
|
||||
These procedures implement set complement, union, intersection, and difference
|
||||
for character sets.
|
||||
They are allowed, but not required, to side-effect their first parameter.
|
||||
The union, intersection, and difference operations are n-ary, associating
|
||||
to the left.
|
||||
\end{desc}
|
||||
\ex{char-set-members} & \ex{char-set->list} \\
|
||||
\ex{chars->char-set} & \ex{list->char-set} \\
|
||||
\ex{ascii-range->char-set} & \ex{ucs-range->char-set} (not exact) \\
|
||||
\ex{predicate->char-set} & \ex{char-set-filter} (not exact) \\
|
||||
\ex{char-set-every}? & \ex{char-set-every} \\
|
||||
\ex{char-set-any}? & \ex{char-set-any} \\
|
||||
\\
|
||||
\ex{char-set-invert} & \ex{char-set-complement} \\
|
||||
\ex{char-set-invert}! & \ex{char-set-complement!} \\
|
||||
\\
|
||||
\ex{char-set:alphabetic} & \ex{char-set:letter} \\
|
||||
\ex{char-set:numeric} & \ex{char-set:digit} \\
|
||||
\ex{char-set:alphanumeric} & \ex{char-set:letter+digit} \\
|
||||
\ex{char-set:control} & \ex{char-set:iso-control}
|
||||
\end{tabular}
|
||||
\end{inset}
|
||||
Note also that the \ex{->char-set} procedure no longer handles a predicate
|
||||
argument.
|
||||
|
|
|
@ -49,7 +49,7 @@ Programs can use \ex{with-errno-handler*} to establish
|
|||
handlers for these exceptions.
|
||||
|
||||
If a {\Unix} error arises while \var{thunk} is executing,
|
||||
\var{handler} is called on two arguments:
|
||||
\var{handler} is called on two arguments like this:
|
||||
\codex{(\var{handler} \var{errno} \var{packet})}
|
||||
\var{packet} is a list of the form
|
||||
$$\var{packet} = \ex{(\var{errno-msg} \var{syscall} . \var{data})},$$
|
||||
|
@ -375,7 +375,7 @@ descriptor to a port with \ex{fdes->outport} or \ex{fdes->inport}, the port
|
|||
has its revealed field incremented.
|
||||
|
||||
Not all file descriptors are created by requests to make ports. Some are
|
||||
inherited on process invocation via \ex{exec(2)}, and are simply part of the
|
||||
inherited on process invocation via \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec(2)}}, and are simply part of the
|
||||
global environment. Subprocesses may depend upon them, so if a port is later
|
||||
allocated for these file descriptors, is should be considered as a revealed
|
||||
port. For example, when the {\Scheme} shell's process starts up, it opens ports
|
||||
|
@ -388,7 +388,7 @@ port.
|
|||
|
||||
Unrevealed file ports have the nice property that they can be closed when all
|
||||
pointers to the port are dropped. This can happen during gc, or at an
|
||||
\ex{exec()}---since all memory is dropped at an \ex{exec()}. No one knows the
|
||||
\ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec()}}---since all memory is dropped at an \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec()}}. No one knows the
|
||||
file descriptor associated with the port, so the exec'd process certainly
|
||||
can't refer to it.
|
||||
|
||||
|
@ -399,11 +399,11 @@ the garbage collector. This is critical, since shell programming
|
|||
absolutely requires access to the {\Unix} file descriptors, as their
|
||||
numerical values are a critical part of the process interface.
|
||||
|
||||
A port's underlying file descriptor can be shifted around with \ex{dup(2)}
|
||||
A port's underlying file descriptor can be shifted around with \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup(2)}}
|
||||
when convenient. That is, the actual file descriptor on top of which a port is
|
||||
constructed can be shifted around underneath the port by the scsh kernel when
|
||||
necessary. This is important, because when the user is setting up file
|
||||
descriptors prior to a \ex{exec(2)}, he may explicitly use a file descriptor
|
||||
descriptors prior to a \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec(2)}}, he may explicitly use a file descriptor
|
||||
that has already been allocated to some port. In this case, the scsh kernel
|
||||
just shifts the port's file descriptor to some new location with \ex{dup},
|
||||
freeing up its old descriptor. This prevents errors from happening in the
|
||||
|
@ -431,8 +431,8 @@ alive and well so that it can subsequently be dup'd into descriptor 0 for
|
|||
\ex{prog}'s stdin.
|
||||
|
||||
The port-shifting machinery makes the following guarantee: a port is only
|
||||
moved when the underlying file descriptor is closed, either by a \ex{close()}
|
||||
or a \ex{dup2()} operation. Otherwise a port/file-descriptor association is
|
||||
moved when the underlying file descriptor is closed, either by a \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=close&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{close()}}
|
||||
or a \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup2&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup2()}} operation. Otherwise a port/file-descriptor association is
|
||||
stable.
|
||||
|
||||
Under normal circumstances, all this machinery just works behind the scenes to
|
||||
|
@ -524,17 +524,17 @@ Decrement the port's revealed count.
|
|||
\defunx{dup->outport} {fd/port [newfd]} {port}
|
||||
\defunx{dup->fdes} {fd/port [newfd]} {fd}
|
||||
\begin{desc}
|
||||
These procedures provide the functionality of C's \ex{dup()} and \ex{dup2()}.
|
||||
These procedures provide the functionality of C's \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup()}} and \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup2&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup2()}}.
|
||||
The different routines return different types of values:
|
||||
\ex{dup->inport}, \ex{dup->outport}, and \ex{dup->fdes} return
|
||||
input ports, output ports, and integer file descriptors, respectively.
|
||||
\ex{dup}'s return value depends on on the type of
|
||||
\var{fd/port}---it maps fd$\rightarrow$fd and port$\rightarrow$port.
|
||||
|
||||
These procedures use the {\Unix} \ex{dup()} syscall to replicate
|
||||
These procedures use the {\Unix} \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup()}} syscall to replicate
|
||||
the file descriptor or file port \var{fd/port}.
|
||||
If a \var{newfd} file descriptor is given, it is used as the target of
|
||||
the dup operation, \ie, the operation is a \ex{dup2()}.
|
||||
the dup operation, \ie, the operation is a \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup2&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup2()}}.
|
||||
In this case, procedures that return a port (such as \ex{dup->inport})
|
||||
will return one with the revealed count set to one.
|
||||
For example, \ex{(dup (current-input-port) 5)} produces
|
||||
|
@ -646,8 +646,8 @@ These procedures allow reading and writing of an open file's status flags
|
|||
%
|
||||
\begin{tabular}[t]{@{}>{\ttfamily}l@{}}
|
||||
%% These are gettable and settable
|
||||
open/append \\
|
||||
open/non-blocking \\
|
||||
open/append \\
|
||||
open/non-blocking \\
|
||||
open/async \textrm{(Non-\Posix)} \\
|
||||
open/fsync \textrm{(Non-\Posix)}
|
||||
\end{tabular}
|
||||
|
@ -659,9 +659,9 @@ These procedures allow reading and writing of an open file's status flags
|
|||
%
|
||||
\begin{tabular}[t]{@{}>{\ttfamily}l@{}}
|
||||
%% These are gettable, not settable
|
||||
open/read \\
|
||||
open/write \\
|
||||
open/read+write \\
|
||||
open/read \\
|
||||
open/write \\
|
||||
open/read+write \\
|
||||
open/access-mask
|
||||
\end{tabular}
|
||||
\\\cline{2-3}
|
||||
|
@ -673,21 +673,21 @@ These procedures allow reading and writing of an open file's status flags
|
|||
%
|
||||
\begin{tabular}[t]{@{}>{\ttfamily}l@{}}
|
||||
%% These are neither gettable nor settable.
|
||||
open/create \\
|
||||
open/exclusive \\
|
||||
open/no-control-tty \\
|
||||
open/create \\
|
||||
open/exclusive \\
|
||||
open/no-control-tty \\
|
||||
open/truncate
|
||||
\end{tabular}
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\caption{Status flags for \texttt{open-file},
|
||||
\texttt{fdes-status} and \texttt{set-fdes-status}.
|
||||
Only {\Posix} flags are guaranteed to be present;
|
||||
your operating system may define others.
|
||||
The \texttt{open/access-mask} value is not an actual flag,
|
||||
but a bit mask used to select the field for the \texttt{open/read},
|
||||
\texttt{open/write} and \texttt{open/read+write} bits.
|
||||
}
|
||||
\texttt{fdes-status} and \texttt{set-fdes-status}.
|
||||
Only {\Posix} flags are guaranteed to be present;
|
||||
your operating system may define others.
|
||||
The \texttt{open/access-mask} value is not an actual flag,
|
||||
but a bit mask used to select the field for the \texttt{open/read},
|
||||
\texttt{open/write} and \texttt{open/read+write} bits.
|
||||
}
|
||||
\label{table:fdes-status-flags}
|
||||
\end{table}
|
||||
|
||||
|
@ -703,7 +703,7 @@ Returns two ports, the read and write end-points of a {\Unix} pipe.
|
|||
|
||||
\defun{read-string}{nbytes [fd/port]} {{\str} or \sharpf}
|
||||
\dfnix{read-string!} {str [fd/port start end]} {nread or \sharpf}{procedure}
|
||||
{read-string"!@\texttt{read-string"!}}
|
||||
{read-string"!@\texttt{read-string"!}}
|
||||
\begin{desc}
|
||||
These calls read exactly as much data as you requested, unless
|
||||
there is not enough data (eof).
|
||||
|
@ -731,7 +731,7 @@ Returns two ports, the read and write end-points of a {\Unix} pipe.
|
|||
|
||||
\defun {read-string/partial} {nbytes [fd/port]} {{\str} or \sharpf}
|
||||
\dfnix{read-string!/partial} {str [fd/port start end]} {nread or \sharpf}
|
||||
{procedure}{read-string"!/partial@\texttt{read-string"!/partial}}
|
||||
{procedure}{read-string"!/partial@\texttt{read-string"!/partial}}
|
||||
\begin{desc}
|
||||
%
|
||||
These are atomic best-effort/forward-progress calls.
|
||||
|
@ -816,7 +816,7 @@ allowed to contain {\sharpf} values as well as integers and ports.
|
|||
|
||||
\remark{I have found the \ex{select!} interface to be the more
|
||||
useful of the two. After the system call, it allows you
|
||||
to check a specific I/O channel in constant time.}
|
||||
to check a specific I/O channel in constant time.}
|
||||
\end{desc}
|
||||
|
||||
|
||||
|
@ -901,13 +901,13 @@ This procedure allows the programmer to assign a particular I/O buffering
|
|||
policy to a port, and to choose the size of the associated buffer.
|
||||
It may only be used on new ports, \ie, before I/O is performed on the port.
|
||||
There are three buffering policies that may be chosen:
|
||||
\begin{inset}
|
||||
\begin{tabular}{l@{\qquad}l}
|
||||
\ex{bufpol/block} & General block buffering (general default) \\
|
||||
\ex{bufpol/line} & Line buffering (tty default) \\
|
||||
\ex{bufpol/none} & Direct I/O---no buffering
|
||||
\end{tabular}
|
||||
\end{inset}
|
||||
\begin{inset}
|
||||
\begin{tabular}{l@{\qquad}l}
|
||||
\ex{bufpol/block} & General block buffering (general default) \\
|
||||
\ex{bufpol/line} & Line buffering (tty default) \\
|
||||
\ex{bufpol/none} & Direct I/O---no buffering
|
||||
\end{tabular}
|
||||
\end{inset}
|
||||
The line buffering policy flushes output whenever a newline is output;
|
||||
whenever the buffer is full; or whenever an input is read from stdin.
|
||||
Line buffering is the default for ports open on terminal devices.
|
||||
|
@ -953,21 +953,16 @@ It is not without reason that the FreeBSD man pages refer to {\Posix}
|
|||
file locking as ``completely stupid.''
|
||||
|
||||
Scsh moves Scheme ports from file descriptor to file descriptor with
|
||||
\ex{dup()} and \ex{close()} as required by the runtime,
|
||||
\ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup()}} and \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=close&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{close()}} as required by the runtime,
|
||||
so it is impossible to keep file locks open across one of these shifts.
|
||||
Hence we can only offer {\Posix} advisory file locking directly on raw
|
||||
integer file descriptors;
|
||||
regrettably, there are no facilities for locking Scheme ports.
|
||||
|
||||
Note that once a Scheme port is revealed in scsh, the runtime will not
|
||||
shift the port around with \ex{dup()} and \ex{close()}.
|
||||
shift the port around with \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=dup&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{dup()}} and \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=close&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{close()}}.
|
||||
This means the file-locking procedures can then be applied to the port's
|
||||
associated file descriptor.
|
||||
|
||||
NeXTSTEP users should also note that even minimalist {\Posix} file locking
|
||||
is not supported for NFS-mounted files in NeXTSTEP; NeXT claims they will
|
||||
fix this in NS release 4.
|
||||
We'd appreciate hearing from users when and if this happens.
|
||||
}
|
||||
|
||||
{\Posix} allows the user to lock a region of a file with either
|
||||
|
@ -1122,7 +1117,7 @@ while \ex{delete-filesys-object} simply returns.
|
|||
If you override an existing object, then \var{old-fname}
|
||||
and \var{new-fname} must type-match---either both directories,
|
||||
or both non-directories.
|
||||
This is required by the semantics of {\Unix} \ex{rename()}.
|
||||
This is required by the semantics of {\Unix} \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=rename&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{rename()}}.
|
||||
|
||||
\remark{
|
||||
There is an unfortunate atomicity problem with the \ex{rename-file}
|
||||
|
@ -1130,7 +1125,7 @@ while \ex{delete-filesys-object} simply returns.
|
|||
specify no-override, but create file \ex{new-fname} sometime between
|
||||
\ex{rename-file}'s existence check and the actual rename operation,
|
||||
your file will be clobbered with \ex{old-fname}. There is no way to fix
|
||||
this problem, given the semantics of {\Unix} \ex{rename()};
|
||||
this problem, given the semantics of {\Unix} \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=rename&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{rename()}};
|
||||
at least it is highly unlikely to occur in practice.
|
||||
}
|
||||
\end{defundescx}
|
||||
|
@ -1170,7 +1165,7 @@ while \ex{delete-filesys-object} simply returns.
|
|||
These procedures are not {\Posix}.
|
||||
Interestingly enough, \ex{sync\=file\=system} doesn't actually
|
||||
do what it is claimed to do. We just threw it in for humor value.
|
||||
See the \ex{sync(2)} man page for {\Unix} enlightenment.
|
||||
See the \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=sync&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{sync(2)}} man page for {\Unix} enlightenment.
|
||||
\end{desc}
|
||||
|
||||
\begin{defundesc} {truncate-file} {fname/fd/port len} \undefined
|
||||
|
@ -1242,12 +1237,12 @@ Example:
|
|||
|
||||
\remark{\ex{file-info} was named \ex{file-attributes} in releases of scsh
|
||||
prior to release 0.4. We changed the name to \ex{file-info} for
|
||||
consistency with the other information-retrieval procedures in
|
||||
scsh: \ex{user-info}, \ex{group-info}, \ex{host-info},
|
||||
\ex{network-info }, \ex{service-info}, and \ex{protocol-info}.
|
||||
consistency with the other information-retrieval procedures in
|
||||
scsh: \ex{user-info}, \ex{group-info}, \ex{host-info},
|
||||
\ex{network-info }, \ex{service-info}, and \ex{protocol-info}.
|
||||
|
||||
The \ex{file-attributes} binding is still supported in the current
|
||||
release of scsh, but is deprecated, and may go away in a future
|
||||
The \ex{file-attributes} binding is still supported in the current
|
||||
release of scsh, but is deprecated, and may go away in a future
|
||||
release.}
|
||||
\end{defundesc}
|
||||
|
||||
|
@ -1295,7 +1290,7 @@ For example,
|
|||
calls do not take a \var{chase?} flag.
|
||||
|
||||
Note that these procedures use the process' \emph{effective} user
|
||||
and group ids for permission checking. {\Posix} defines an \ex{access()}
|
||||
and group ids for permission checking. {\Posix} defines an \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=access&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{access()}}
|
||||
function that uses the process' real uid and gids. This is handy
|
||||
for setuid programs that would like to find out if the actual user
|
||||
has specific rights; scsh ought to provide this functionality (but doesn't
|
||||
|
@ -1315,7 +1310,7 @@ For example,
|
|||
These should be disentangled.
|
||||
|
||||
Some of these problems could be avoided if {\Posix} had a real-uid
|
||||
variant of the \ex{access()} call we could use, but the atomicity
|
||||
variant of the \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=access&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{access()}} call we could use, but the atomicity
|
||||
issue is still a problem. In the final analysis, the only way to
|
||||
find out if you have the right to perform an operation on a file
|
||||
is to try and open it for the desired operation. These permission-checking
|
||||
|
@ -1392,8 +1387,8 @@ Returns:
|
|||
|
||||
Note that the rules of backslash for {\Scheme} strings and glob patterns
|
||||
work together to require four backslashes in a row to specify a
|
||||
single literal backslash. Fortunately, this should be a rare
|
||||
occurrence.
|
||||
single literal backslash. Fortunately, it is very rare that a backslash
|
||||
occurs in a Unix file name.
|
||||
|
||||
A glob subpattern will not match against dot files unless the first
|
||||
character of the subpattern is a literal ``\ex{.}''.
|
||||
|
@ -1465,14 +1460,14 @@ All wild-card characters in \var{str} are quoted with a backslash.
|
|||
|
||||
\begin{defundesc}{file-match}{root dot-files? \vari{pat}1 \vari{pat}2 {\ldots} \vari{pat}n}{string list}
|
||||
\note{This procedure is deprecated, and will probably either go away or
|
||||
be substantially altered in a future release. New code should not
|
||||
call this procedure. The problem is that it relies upon
|
||||
Posix-notation regular expressions; the rest of scsh has been
|
||||
converted over to the new SRE notation.}
|
||||
be substantially altered in a future release. New code should not
|
||||
call this procedure. The problem is that it relies upon
|
||||
Posix-notation regular expressions; the rest of scsh has been
|
||||
converted over to the new SRE notation.}
|
||||
|
||||
\ex{file-match} provides a more powerful file-matching service, at the
|
||||
expense of a less convenient notation. It is intermediate in
|
||||
power between most shell matching machinery and recursive \ex{find(1)}.
|
||||
power between most shell matching machinery and recursive \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=find&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{find(1)}}.
|
||||
|
||||
Each pattern is a regexp. The procedure searches from \var{root},
|
||||
matching the first-level files against pattern \vari{pat}1, the
|
||||
|
@ -1721,7 +1716,7 @@ a slash character---it is used directly. So a program with a name like
|
|||
\ex{"bin/prog"} always executes the program \ex{bin/prog} in the current working
|
||||
directory. See \verb|$path| and \verb|exec-path-list|, below.
|
||||
|
||||
Note that there is no analog to the C function \ex{execv()}.
|
||||
Note that there is no analog to the C function \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=execv&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{execv()}}.
|
||||
To get the effect just do
|
||||
\codex{(apply exec prog arglist)}
|
||||
|
||||
|
@ -1729,7 +1724,7 @@ All of these procedures flush buffered output and close unrevealed ports
|
|||
before executing the new binary.
|
||||
To avoid flushing buffered output, see \verb|%exec| below.
|
||||
|
||||
Note that the C \ex{exec()} procedure allows the zeroth element of the
|
||||
Note that the C \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec()}} procedure allows the zeroth element of the
|
||||
argument vector to be different from the file being executed, \eg
|
||||
%
|
||||
\begin{inset}
|
||||
|
@ -1807,7 +1802,7 @@ Suspend the current process with a SIGSTOP signal.
|
|||
\defun {fork} {[thunk]} {proc or \sharpf}
|
||||
\defunx {\%fork} {[thunk]} {proc or \sharpf}
|
||||
\begin{desc}
|
||||
\ex{fork} with no arguments is like C \ex{fork()}.
|
||||
\ex{fork} with no arguments is like C \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=fork&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{fork()}}.
|
||||
In the parent process, it returns the child's \emph{process object}
|
||||
(see below for more information on process objects).
|
||||
In the child process, it returns {\sharpf}.
|
||||
|
@ -1874,7 +1869,7 @@ Suspend the current process with a SIGSTOP signal.
|
|||
(display "Hello, world.\\n"))))
|
||||
|
||||
(set-current-input-port! (fdes->inport 0)
|
||||
(read-line) ; Read the string output by the child.\end{code}
|
||||
(read-line) ; Read the string output by the child.\end{code}
|
||||
None of this is necessary when the I/O is performed by an exec'd
|
||||
program in the child or parent process, only when the pipe will
|
||||
be referenced by Scheme code through one of the default current I/O
|
||||
|
@ -1898,7 +1893,7 @@ They are created by the \ex{fork} procedure, and have the following
|
|||
exposed structure:
|
||||
\begin{code}
|
||||
(define-record proc
|
||||
pid)\end{code}
|
||||
pid)\end{code}
|
||||
\index{proc}\index{proc?}\index{proc:pid}
|
||||
The only exposed slot in a proc record is the process' pid,
|
||||
the integer id assigned by Unix to the process.
|
||||
|
@ -1916,10 +1911,10 @@ If there is no process object in the system indexed by the given pid,
|
|||
\begin{center}
|
||||
\begin{tabular}{|l|l|}
|
||||
\hline
|
||||
\var{probe?} & Return \\ \hline\hline
|
||||
\sharpf & \emph{signal error condition.} \\ \hline
|
||||
\ex{'create} & Create new proc object. \\ \hline
|
||||
True value & \sharpf \\ \hline
|
||||
\var{probe?} & Return \\ \hline\hline
|
||||
\sharpf & \emph{signal error condition.} \\ \hline
|
||||
\ex{'create} & Create new proc object. \\ \hline
|
||||
True value & \sharpf \\ \hline
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{defundesc}
|
||||
|
@ -1975,29 +1970,29 @@ The policy is determined by applying this procedure to one of the
|
|||
values \ex{'early}, \ex{'late}, or {\sharpf} (\ie, no autoreap).
|
||||
\begin{description}
|
||||
\item [early]
|
||||
The child is reaped from the {\Unix} kernel's process table
|
||||
into scsh as soon as it dies. This is done by having a
|
||||
The child is reaped from the {\Unix} kernel's process table
|
||||
into scsh as soon as it dies. This is done by having a
|
||||
signal handler for the \ex{SIGCHLD} signal reap the process.
|
||||
\emph{
|
||||
If a scsh program sets its own handler for the \ex{SIGCHLD}
|
||||
signal, the handler must reap dead children
|
||||
by calling \ex{wait}, \ex{wait-any}, or \ex{reap-zombies}.}
|
||||
We deprecate interrupt-driven code, and hope to provide
|
||||
alternative tools in a future, multi-threaded release of scsh.
|
||||
\emph{
|
||||
If a scsh program sets its own handler for the \ex{SIGCHLD}
|
||||
signal, the handler must reap dead children
|
||||
by calling \ex{wait}, \ex{wait-any}, or \ex{reap-zombies}.}
|
||||
We deprecate interrupt-driven code, and hope to provide
|
||||
alternative tools in a future, multi-threaded release of scsh.
|
||||
|
||||
\item [late]
|
||||
The child is not autoreaped until it dies \emph{and} the scsh program
|
||||
drops all pointers to its process object. That is, the process
|
||||
table is cleaned out during garbage collection.
|
||||
\oops{The \ex{late} policy is not supported under the current
|
||||
release of scsh. It requires more sophisticated gc hooks than
|
||||
we can get from the release of {\scm} that we use.}
|
||||
The child is not autoreaped until it dies \emph{and} the scsh program
|
||||
drops all pointers to its process object. That is, the process
|
||||
table is cleaned out during garbage collection.
|
||||
\oops{The \ex{late} policy is not supported under the current
|
||||
release of scsh. It requires more sophisticated gc hooks than
|
||||
we can get from the release of {\scm} that we use.}
|
||||
|
||||
\item [\sharpf]
|
||||
If autoreaping is turned off, process reaping is completely under
|
||||
control of the programmer, who can force outstanding zombies to
|
||||
be reaped by manually calling the \ex{reap-zombies} procedure
|
||||
(see below).
|
||||
If autoreaping is turned off, process reaping is completely under
|
||||
control of the programmer, who can force outstanding zombies to
|
||||
be reaped by manually calling the \ex{reap-zombies} procedure
|
||||
(see below).
|
||||
\end{description}
|
||||
Note that under any of the autoreap policies, a particular process $p$ can
|
||||
be manually reaped into scsh by simply calling \ex{(wait $p$)}.
|
||||
|
@ -2077,34 +2072,34 @@ forms, or use \ex{wait-any} to wait for the children to exit.
|
|||
The \var{flags} argument is an integer whose bits specify
|
||||
additional options. It is composed by or'ing together the following
|
||||
flags:
|
||||
\begin{center}
|
||||
\begin{tabular}{|l|l|}
|
||||
\hline
|
||||
Flag & Meaning \\ \hline \hline
|
||||
\ex{wait/poll} & Return {\sharpf} immediately if
|
||||
child still active. \\ \hline
|
||||
\ex{wait/stopped-children} & Wait for suspend as well as exit. \\ \hline
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\begin{center}
|
||||
\begin{tabular}{|l|l|}
|
||||
\hline
|
||||
Flag & Meaning \\ \hline \hline
|
||||
\ex{wait/poll} & Return {\sharpf} immediately if
|
||||
child still active. \\ \hline
|
||||
\ex{wait/stopped-children} & Wait for suspend as well as exit. \\ \hline
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\end{desc}
|
||||
|
||||
\begin{defundesc} {wait-any} {[flags]} {[proc status]}
|
||||
The optional \var{flags} argument is as for \ex{wait}.
|
||||
This procedure waits for any child process to exit (or stop, if the
|
||||
\ex{wait/stopped-children} flag is used)
|
||||
\ex{wait/stopped-children} flag is used)
|
||||
It returns the process' process object and status code.
|
||||
If there are no children left for which to wait, the two values
|
||||
\ex{[{\sharpf} {\sharpt}]} are returned.
|
||||
\ex{[{\sharpf} {\sharpt}]} are returned.
|
||||
If the \ex{wait/poll} flag is used, and none of the children
|
||||
are immediately eligble for waiting,
|
||||
then the values \ex{[{\sharpf} {\sharpf}]} are returned:
|
||||
\begin{center}
|
||||
\begin{tabular}{|l|l|}
|
||||
\hline
|
||||
[{\sharpf} {\sharpf}] & Poll, none ready \\ \hline
|
||||
[{\sharpf} {\sharpt}] & No children \\ \hline
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
then the values \ex{[{\sharpf} {\sharpf}]} are returned:
|
||||
\begin{center}
|
||||
\begin{tabular}{|l|l|}
|
||||
\hline
|
||||
[{\sharpf} {\sharpf}] & Poll, none ready \\ \hline
|
||||
[{\sharpf} {\sharpt}] & No children \\ \hline
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\ex{Wait-any} will not return a process that has been previously waited
|
||||
by any other process-wait procedure (\ex{wait}, \ex{wait-any},
|
||||
|
@ -2172,7 +2167,7 @@ Otherwise, this function returns false.
|
|||
%This procedure, ported from early T implementations,
|
||||
%returns true iff \ex{(\var{proc})} returns at all.
|
||||
%\remark{The current implementation is a constant function returning {\sharpt},
|
||||
% which suffices for all {\Unix} implementations of which we are aware.}
|
||||
% which suffices for all {\Unix} implementations of which we are aware.}
|
||||
%\end{desc}
|
||||
|
||||
\section{Process state}
|
||||
|
@ -2247,7 +2242,7 @@ I can't remember how \ex{set-priority} and \ex{priority} work, so no
|
|||
\begin{desc}
|
||||
These routines get and set the effective and real user and group ids.
|
||||
The \ex{set-uid} and \ex{set-gid} routines correspond to the {\Posix}
|
||||
\ex{setuid()} and \ex{setgid()} procedures.
|
||||
\ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=setuid&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{setuid()}} and \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=setgid&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{setgid()}} procedures.
|
||||
\end{desc}
|
||||
|
||||
|
||||
|
@ -2458,39 +2453,39 @@ asynchronous {\Unix} signals (table~\ref{table:signals-and-interrupts}).
|
|||
\begin{tabular}{lll}\hline
|
||||
Interrupt & Unix signal & OS Variant \\ \hline\hline
|
||||
\kwd{interrupt/alrm}\footnote{Also bound to {\scm} interrupt
|
||||
\kwd{interrupt/alarm}.}
|
||||
& \kwd{signal/alrm} & \Posix \\
|
||||
\kwd{interrupt/alarm}.}
|
||||
& \kwd{signal/alrm} & \Posix \\
|
||||
%
|
||||
\kwd{interrupt/int}\footnote{Also bound to {\scm} interrupt
|
||||
\kwd{interrupt/keyboard}.}
|
||||
& \kwd{signal/int} & \Posix \\
|
||||
\kwd{interrupt/keyboard}.}
|
||||
& \kwd{signal/int} & \Posix \\
|
||||
%
|
||||
\kwd{interrupt/memory-shortage} & N/A & \\
|
||||
\kwd{interrupt/chld} & \kwd{signal/chld} & \Posix \\
|
||||
\kwd{interrupt/cont} & \kwd{signal/cont} & \Posix \\
|
||||
\kwd{interrupt/hup} & \kwd{signal/hup} & \Posix \\
|
||||
\kwd{interrupt/quit} & \kwd{signal/quit} & \Posix \\
|
||||
\kwd{interrupt/term} & \kwd{signal/term} & \Posix \\
|
||||
\kwd{interrupt/tstp} & \kwd{signal/tstp} & \Posix \\
|
||||
\kwd{interrupt/usr1} & \kwd{signal/usr1} & \Posix \\
|
||||
\kwd{interrupt/usr2} & \kwd{signal/usr2} & \Posix \\
|
||||
\kwd{interrupt/memory-shortage} & N/A & \\
|
||||
\kwd{interrupt/chld} & \kwd{signal/chld} & \Posix \\
|
||||
\kwd{interrupt/cont} & \kwd{signal/cont} & \Posix \\
|
||||
\kwd{interrupt/hup} & \kwd{signal/hup} & \Posix \\
|
||||
\kwd{interrupt/quit} & \kwd{signal/quit} & \Posix \\
|
||||
\kwd{interrupt/term} & \kwd{signal/term} & \Posix \\
|
||||
\kwd{interrupt/tstp} & \kwd{signal/tstp} & \Posix \\
|
||||
\kwd{interrupt/usr1} & \kwd{signal/usr1} & \Posix \\
|
||||
\kwd{interrupt/usr2} & \kwd{signal/usr2} & \Posix \\
|
||||
\\
|
||||
\kwd{interrupt/info} & \kwd{signal/info} & BSD only \\
|
||||
\kwd{interrupt/io} & \kwd{signal/io} & BSD + SVR4 \\
|
||||
\kwd{interrupt/poll} & \kwd{signal/poll} & SVR4 only \\
|
||||
\kwd{interrupt/prof} & \kwd{signal/prof} & BSD + SVR4 \\
|
||||
\kwd{interrupt/pwr} & \kwd{signal/pwr} & SVR4 only \\
|
||||
\kwd{interrupt/urg} & \kwd{signal/urg} & BSD + SVR4 \\
|
||||
\kwd{interrupt/vtalrm} & \kwd{signal/vtalrm} & BSD + SVR4 \\
|
||||
\kwd{interrupt/winch} & \kwd{signal/winch} & BSD + SVR4 \\
|
||||
\kwd{interrupt/xcpu} & \kwd{signal/xcpu} & BSD + SVR4 \\
|
||||
\kwd{interrupt/xfsz} & \kwd{signal/xfsz} & BSD + SVR4 \\
|
||||
\kwd{interrupt/info} & \kwd{signal/info} & BSD only \\
|
||||
\kwd{interrupt/io} & \kwd{signal/io} & BSD + SVR4 \\
|
||||
\kwd{interrupt/poll} & \kwd{signal/poll} & SVR4 only \\
|
||||
\kwd{interrupt/prof} & \kwd{signal/prof} & BSD + SVR4 \\
|
||||
\kwd{interrupt/pwr} & \kwd{signal/pwr} & SVR4 only \\
|
||||
\kwd{interrupt/urg} & \kwd{signal/urg} & BSD + SVR4 \\
|
||||
\kwd{interrupt/vtalrm} & \kwd{signal/vtalrm} & BSD + SVR4 \\
|
||||
\kwd{interrupt/winch} & \kwd{signal/winch} & BSD + SVR4 \\
|
||||
\kwd{interrupt/xcpu} & \kwd{signal/xcpu} & BSD + SVR4 \\
|
||||
\kwd{interrupt/xfsz} & \kwd{signal/xfsz} & BSD + SVR4 \\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\caption{{\scm} virtual-machine interrupts and related {\Unix} signals.
|
||||
Only the {\Posix} signals are guaranteed to be defined; however,
|
||||
your implementation and OS may define other signals and
|
||||
interrupts not listed here.}
|
||||
Only the {\Posix} signals are guaranteed to be defined; however,
|
||||
your implementation and OS may define other signals and
|
||||
interrupts not listed here.}
|
||||
\end{minipage}
|
||||
\label{table:signals-and-interrupts}
|
||||
\end{table}
|
||||
|
@ -2500,31 +2495,31 @@ Interrupt & Unix signal & OS Variant \\ \hline\hline
|
|||
\begin{center}
|
||||
\begin{tabular}{lll}\hline
|
||||
Unix signal & Type & OS Variant \\ \hline\hline
|
||||
\kwd{signal/stop} & Uncatchable & \Posix \\
|
||||
\kwd{signal/kill} & Uncatchable & \Posix \\
|
||||
\kwd{signal/stop} & Uncatchable & \Posix \\
|
||||
\kwd{signal/kill} & Uncatchable & \Posix \\
|
||||
\\
|
||||
\kwd{signal/abrt} & Synchronous & \Posix \\
|
||||
\kwd{signal/fpe} & Synchronous & \Posix \\
|
||||
\kwd{signal/ill} & Synchronous & \Posix \\
|
||||
\kwd{signal/pipe} & Synchronous & \Posix \\
|
||||
\kwd{signal/segv} & Synchronous & \Posix \\
|
||||
\kwd{signal/ttin} & Synchronous & \Posix \\
|
||||
\kwd{signal/ttou} & Synchronous & \Posix \\
|
||||
\kwd{signal/abrt} & Synchronous & \Posix \\
|
||||
\kwd{signal/fpe} & Synchronous & \Posix \\
|
||||
\kwd{signal/ill} & Synchronous & \Posix \\
|
||||
\kwd{signal/pipe} & Synchronous & \Posix \\
|
||||
\kwd{signal/segv} & Synchronous & \Posix \\
|
||||
\kwd{signal/ttin} & Synchronous & \Posix \\
|
||||
\kwd{signal/ttou} & Synchronous & \Posix \\
|
||||
\\
|
||||
\kwd{signal/bus} & Synchronous & BSD + SVR4 \\
|
||||
\kwd{signal/emt} & Synchronous & BSD + SVR4 \\
|
||||
\kwd{signal/iot} & Synchronous & BSD + SVR4 \\
|
||||
\kwd{signal/sys} & Synchronous & BSD + SVR4 \\
|
||||
\kwd{signal/trap} & Synchronous & BSD + SVR4 \\
|
||||
\kwd{signal/bus} & Synchronous & BSD + SVR4 \\
|
||||
\kwd{signal/emt} & Synchronous & BSD + SVR4 \\
|
||||
\kwd{signal/iot} & Synchronous & BSD + SVR4 \\
|
||||
\kwd{signal/sys} & Synchronous & BSD + SVR4 \\
|
||||
\kwd{signal/trap} & Synchronous & BSD + SVR4 \\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
\caption{Uncatchable and synchronous {\Unix} signals. While these signals
|
||||
may be sent with \texttt{signal-process} or
|
||||
\texttt{signal-process-group},
|
||||
\texttt{signal-process-group},
|
||||
there are no corresponding scsh interrupt handlers.
|
||||
Only the {\Posix} signals are guaranteed to be defined; however,
|
||||
your implementation and OS may define other signals not listed
|
||||
here.}
|
||||
your implementation and OS may define other signals not listed
|
||||
here.}
|
||||
\label{table:uncatchable-signals}
|
||||
\end{table}
|
||||
Note that scsh does \emph{not} support signal handlers for ``synchronous''
|
||||
|
@ -2609,8 +2604,8 @@ A handler is either \ex{\#f} (ignore), \ex{\#t} (default), or a
|
|||
procedure taking an integer argument.
|
||||
\end{defundesc}
|
||||
|
||||
% %set-unix-signal-handler
|
||||
% %unix-signal-handler
|
||||
% %set-unix-signal-handler
|
||||
% %unix-signal-handler
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Time}
|
||||
|
@ -2623,9 +2618,6 @@ all of the complexity is optional,
|
|||
and defaulting all the optional arguments reduces the system
|
||||
to a simple interface.
|
||||
|
||||
\remark{This time package does not currently work with NeXTSTEP, as NeXTSTEP
|
||||
does not provide a {\Posix}-compliant time library that will even link.}
|
||||
|
||||
\subsection{Terminology}
|
||||
``UTC'' and ``UCT'' stand for ``universal coordinated time,'' which is the
|
||||
official name for what is colloquially referred to as ``Greenwich Mean
|
||||
|
@ -2722,13 +2714,13 @@ This is described for each procedure below.
|
|||
can be one of:
|
||||
\begin{inset}
|
||||
\begin{tabular}{lp{0.7\linewidth}}
|
||||
\ex{\#f} & Local time \\
|
||||
Integer & Seconds of offset from UTC. For example,
|
||||
New York City is -18000 (-5 hours), San Francisco
|
||||
is -28800 (-8 hours). \\
|
||||
String & A {\Posix} time zone string understood by the OS
|
||||
(\ie., the sort of time zone assigned to the \ex{\$TZ}
|
||||
environment variable).
|
||||
\ex{\#f} & Local time \\
|
||||
Integer & Seconds of offset from UTC. For example,
|
||||
New York City is -18000 (-5 hours), San Francisco
|
||||
is -28800 (-8 hours). \\
|
||||
String & A {\Posix} time zone string understood by the OS
|
||||
(\ie., the sort of time zone assigned to the \ex{\$TZ}
|
||||
environment variable).
|
||||
\end{tabular}
|
||||
\end{inset}
|
||||
An integer time zone gives the number of seconds you must add to UTC
|
||||
|
@ -2758,25 +2750,25 @@ String & A {\Posix} time zone string understood by the OS
|
|||
is always 0, and \ex{(ticks/sec)} returns 1.
|
||||
|
||||
\begin{remarkenv}
|
||||
I chose to represent system clock resolution as ticks/sec
|
||||
instead of sec/tick to increase the odds that the value could
|
||||
be represented as an exact integer, increasing efficiency and
|
||||
I chose to represent system clock resolution as ticks/sec
|
||||
instead of sec/tick to increase the odds that the value could
|
||||
be represented as an exact integer, increasing efficiency and
|
||||
making it easier for Scheme implementations that don't have
|
||||
sophisticated numeric support to deal with the quantity.
|
||||
sophisticated numeric support to deal with the quantity.
|
||||
|
||||
You can convert seconds and ticks to seconds with the expression
|
||||
\codex{(+ \var{secs} (/ \var{ticks} (ticks/sec)))}
|
||||
Given that, why not have the fine-grain time procedure just
|
||||
return a non-integer real for time? Following Common Lisp, I chose to
|
||||
allow the system clock to report sub-second time in its own units to
|
||||
lower the overhead of determining the time. This would be important
|
||||
for a system that wanted to precisely time the duration of some
|
||||
event. Time stamps could be collected with little overhead, deferring
|
||||
the overhead of precisely calculating with them until after collection.
|
||||
You can convert seconds and ticks to seconds with the expression
|
||||
\codex{(+ \var{secs} (/ \var{ticks} (ticks/sec)))}
|
||||
Given that, why not have the fine-grain time procedure just
|
||||
return a non-integer real for time? Following Common Lisp, I chose to
|
||||
allow the system clock to report sub-second time in its own units to
|
||||
lower the overhead of determining the time. This would be important
|
||||
for a system that wanted to precisely time the duration of some
|
||||
event. Time stamps could be collected with little overhead, deferring
|
||||
the overhead of precisely calculating with them until after collection.
|
||||
|
||||
This is all a bit academic for the {\scm} implementation, where
|
||||
we determine time with a heavyweight system call, but it's nice
|
||||
to plan for the future.
|
||||
This is all a bit academic for the {\scm} implementation, where
|
||||
we determine time with a heavyweight system call, but it's nice
|
||||
to plan for the future.
|
||||
\end{remarkenv}
|
||||
\end{desc}
|
||||
|
||||
|
@ -2795,13 +2787,13 @@ String & A {\Posix} time zone string understood by the OS
|
|||
``\ex{UTC+\emph{hh}:\emph{mm}:\emph{ss}}'';
|
||||
the trailing \ex{:\emph{mm}:\emph{ss}} portion is deleted if it is zeroes.
|
||||
|
||||
\oops{The Posix facility for converting dates to times, \ex{mktime()},
|
||||
\oops{The Posix facility for converting dates to times, \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=mktime&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{mktime()}},
|
||||
has a broken design: it indicates an error by returning -1, which
|
||||
is also a legal return value (for date 23:59:59 UCT, 12/31/1969).
|
||||
Scsh resolves the ambiguity in a paranoid fashion: it always
|
||||
reports an error if the underlying Unix facility returns -1.
|
||||
We feel your pain.
|
||||
}
|
||||
We feel your pain.
|
||||
}
|
||||
\end{desc}
|
||||
|
||||
\defun {time} {} \integer
|
||||
|
@ -2823,8 +2815,8 @@ String & A {\Posix} time zone string understood by the OS
|
|||
\ex{summer?} field is used to resolve ambiguities:
|
||||
\begin{tightinset}
|
||||
\begin{tabular}{ll}
|
||||
\ex{\#f} & Resolve an ambiguous time in favor of non-summer time. \\
|
||||
true & Resolve an ambiguous time in favor of summer time.
|
||||
\ex{\#f} & Resolve an ambiguous time in favor of non-summer time. \\
|
||||
true & Resolve an ambiguous time in favor of summer time.
|
||||
\end{tabular}
|
||||
\end{tightinset}
|
||||
This is useful in boundary cases during the change-over. For example,
|
||||
|
@ -2866,28 +2858,28 @@ true & Resolve an ambiguous time in favor of summer time.
|
|||
\verb|~b| & abbreviated month name \\
|
||||
\verb|~B| & full month name \\
|
||||
\verb|~c| & time and date using the time and date representation
|
||||
for the locale (\verb|~X ~x|) \\
|
||||
for the locale (\verb|~X ~x|) \\
|
||||
\verb|~d| & day of the month as a decimal number (01-31) \\
|
||||
\verb|~H| & hour based on a 24-hour clock
|
||||
as a decimal number (00-23) \\
|
||||
as a decimal number (00-23) \\
|
||||
\verb|~I| & hour based on a 12-hour clock
|
||||
as a decimal number (01-12) \\
|
||||
as a decimal number (01-12) \\
|
||||
\verb|~j| & day of the year as a decimal number (001-366) \\
|
||||
\verb|~m| & month as a decimal number (01-12) \\
|
||||
\verb|~M| & minute as a decimal number (00-59) \\
|
||||
\verb|~p| & AM/PM designation associated with a 12-hour clock \\
|
||||
\verb|~S| & second as a decimal number (00-61) \\
|
||||
\verb|~U| & week number of the year;
|
||||
Sunday is first day of week (00-53) \\
|
||||
Sunday is first day of week (00-53) \\
|
||||
\verb|~w| & weekday as a decimal number (0-6), where Sunday is 0 \\
|
||||
\verb|~W| & week number of the year;
|
||||
Monday is first day of week (00-53) \\
|
||||
Monday is first day of week (00-53) \\
|
||||
\verb|~x| & date using the date representation for the locale \\
|
||||
\verb|~X| & time using the time representation for the locale \\
|
||||
\verb|~y| & year without century (00-99) \\
|
||||
\verb|~Y| & year with century (\eg 1990) \\
|
||||
\verb|~Z| & time zone name or abbreviation, or no characters
|
||||
if no time zone is determinable
|
||||
if no time zone is determinable
|
||||
\end{tabular}
|
||||
|
||||
\caption{\texttt{format-date} conversion specifiers}
|
||||
|
@ -2917,10 +2909,10 @@ true & Resolve an ambiguous time in favor of summer time.
|
|||
% (\eg, ``EST'' and ``EDT'')\@. \var{Summer?} is interpreted as follows:
|
||||
% \begin{inset}
|
||||
% \begin{tabular}{lp{0.7\linewidth}}
|
||||
% Integer & A time value.
|
||||
% The variant in use at that time is returned. \\
|
||||
% \ex{\#f} & The standard time name is returned. \\
|
||||
% \emph{Otherwise} & The summer time name is returned.
|
||||
% Integer & A time value.
|
||||
% The variant in use at that time is returned. \\
|
||||
% \ex{\#f} & The standard time name is returned. \\
|
||||
% \emph{Otherwise} & The summer time name is returned.
|
||||
% \end{tabular}
|
||||
% \end{inset}
|
||||
% \ex{Summer?} defaults to the case that pertains at the time of the call.
|
||||
|
@ -2928,7 +2920,7 @@ true & Resolve an ambiguous time in favor of summer time.
|
|||
%\end{desc}
|
||||
|
||||
\dfni {fill-in-date!}{date}{date}{procedure}
|
||||
{fill-in-date"!@\texttt{fill-in-date"!}}
|
||||
{fill-in-date"!@\texttt{fill-in-date"!}}
|
||||
\begin{desc}
|
||||
This procedure fills in missing, redundant slots in a date record.
|
||||
In decreasing order of priority:
|
||||
|
@ -2992,7 +2984,8 @@ If \var{val} is {\sharpf}, then any entry for \var{var} is deleted.
|
|||
an alist, \eg,
|
||||
\begin{code}
|
||||
(("TERM" . "vt100")
|
||||
("SHELL" . "/bin/csh")
|
||||
("SHELL" . "/usr/local/bin/scsh")
|
||||
("PATH" . "/sbin:/usr/sbin:/bin:/usr/bin")
|
||||
("EDITOR" . "emacs")
|
||||
\ldots)\end{code}
|
||||
\end{desc}
|
||||
|
@ -3005,6 +2998,21 @@ If \var{val} is {\sharpf}, then any entry for \var{var} is deleted.
|
|||
environment (\ie, converted to a null-terminated C vector of
|
||||
\ex{"\var{var}=\var{val}"} strings which is assigned to the global
|
||||
\ex{char **environ}).
|
||||
|
||||
\begin{code}
|
||||
;;; Note $PATH entry is converted
|
||||
;;; to /sbin:/usr/sbin:/bin:/usr/bin.
|
||||
(alist->env '(("TERM" . "vt100")
|
||||
("PATH" "/sbin" "/usr/sbin" "/bin")
|
||||
("SHELL" . "/usr/local/bin/scsh")))
|
||||
\end{code}
|
||||
|
||||
Note that \ex{env->alist} and \ex{alist->env} are not exact
|
||||
inverses---\ex{alist->env} will convert a list value into a single
|
||||
colon-separated string, but \ex{env->alist} will not parse colon-separated
|
||||
values into lists. (See the \ex{\$PATH} element in the examples given for
|
||||
each procedure.)
|
||||
|
||||
\end{desc}
|
||||
|
||||
The following three functions help the programmer manipulate alist
|
||||
|
@ -3082,18 +3090,30 @@ Example: These four pieces of code all run the mailer with special
|
|||
|
||||
\subsection{Path lists and colon lists}
|
||||
|
||||
Environment variables such as \ex{\$PATH} encode a list of strings
|
||||
by separating the list elements with colon delimiters.
|
||||
Once parsed into actual lists, these ordered lists can be manipulated
|
||||
with the following two functions.
|
||||
When environment variables such as \ex{\$PATH} need to encode a list of
|
||||
strings (such as a list of directories to be searched),
|
||||
the common Unix convention is to separate the list elements with
|
||||
colon delimiters.\footnote{\ldots and hope the individual list elements
|
||||
don't contain colons themselves.}
|
||||
To convert between the colon-separated string encoding and the
|
||||
list-of-strings representation, see the \ex{field-reader} and
|
||||
\ex{join-strings} functions in section~\ref{sec:field-reader}.
|
||||
\remark{An earlier release of scsh provided the \ex{split-colon-list}
|
||||
and \ex{string-list->colon-list} functions. These have been
|
||||
removed from scsh, and are replaced by the more general
|
||||
parsers and unparsers of the field-reader module.}
|
||||
list-of-strings representation, see the \ex{infix-splitter} function
|
||||
(section~\ref{sec:field-splitter}) and the string library's
|
||||
\ex{string-join} function.
|
||||
For example,
|
||||
\begin{code}
|
||||
(define split (infix-splitter (rx ":")))
|
||||
(split "/sbin:/bin::/usr/bin") {\evalsto}
|
||||
'("/sbin" "/bin" "" "/usr/bin")
|
||||
(string-join ":" '("/sbin" "/bin" "" "/usr/bin")) {\evalsto}
|
||||
"/sbin:/bin::/usr/bin"\end{code}
|
||||
The following two functions are useful for manipulating these ordered lists,
|
||||
once they have been parsed from their colon-separated form.
|
||||
|
||||
%\remark{An earlier release of scsh provided the \ex{split-colon-list}
|
||||
% and \ex{string-list->colon-list} functions. These have been
|
||||
% removed from scsh, and are replaced by the more general
|
||||
% parsers and unparsers of the field-reader module.}
|
||||
%
|
||||
%\defun {split-colon-list} {string} {{\str} list}
|
||||
%\defunx {string-list->colon-list} {string-list} \str
|
||||
%\begin{desc}
|
||||
|
@ -3146,15 +3166,18 @@ Scsh never uses \cd{$USER} at all.
|
|||
It computes \ex{(user-login-name)} from the system call \ex{(user-uid)}.
|
||||
|
||||
\defvar {home-directory} \str
|
||||
\defvarx {exec-path-list} {{\str} list}
|
||||
\defvarx {exec-path-list} {{\str} list fluid}
|
||||
\begin{desc}
|
||||
Scsh accesses \cd{$HOME} at start-up time, and stores the value in the
|
||||
global variable \ex{home-directory}. It uses this value for \ex{\~}
|
||||
lookups and for returning to home on \ex{(chdir)}.
|
||||
|
||||
Scsh accesses \cd{$PATH} at start-up time, colon-splits the path list, and
|
||||
stores the value in the global variable \ex{exec-path-list}. This list is
|
||||
stores the value in the fluid \ex{exec-path-list}. This list is
|
||||
used for \ex{exec-path} and \ex{exec-path/env} searches.
|
||||
|
||||
To access, rebind or side-effect fluid cells, you must open
|
||||
the \ex{fluids} package.
|
||||
\end{desc}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
% tex2page.sty
|
||||
% Dorai Sitaram
|
||||
|
||||
% Loading this file in a LaTeX document
|
||||
% gives it all the macros of tex2page.tex,
|
||||
% but via a more LaTeX-convenient filename.
|
||||
|
||||
\input{tex2page}
|
||||
|
|
@ -7,8 +7,10 @@ made to scsh.
|
|||
We invite interested hackers to do any of them, and send us the code;
|
||||
we'll put you on the team.
|
||||
Visit the Scheme Underground Web page for more information on good hacks at
|
||||
\begin{tightinset}\verb|http://www.ai.mit.edu/projects/su/|
|
||||
\end{tightinset}
|
||||
\begin{inset} \begin{flushleft}
|
||||
\ex{\urlh{http://www.ai.mit.edu/projects/su/}{http://www.ai.mit.edu/projects/su/}}
|
||||
\end{flushleft}
|
||||
\end{inset}
|
||||
Scsh is a tool that lets you write fun programs that do real things in
|
||||
an elegant language; go wild.
|
||||
|
||||
|
@ -17,19 +19,8 @@ an elegant language; go wild.
|
|||
\item An X gui interface. (Needs threads.)
|
||||
\item A better C function/data-structure interface. This is not easy.
|
||||
\item More network protocols. Telnet and ftp would be the most important.
|
||||
\item An ILU interface.
|
||||
\item An RPC system, with ``tail-recursion.''
|
||||
\item Interfaces to relational db's.
|
||||
This would be quite useful for Web servers.
|
||||
An s-expression embedding of SQL would be a key design component
|
||||
of such a system, along the lines of scsh's process notation or
|
||||
\ex{awk} notation.
|
||||
\item Port Edwin, and emacs text editor written in MIT Scheme, to scsh.
|
||||
Combine it with scsh's OS interfaces to make a visual shell.
|
||||
\item An \ex{expect} knock-off.
|
||||
\item A \ex{make} replacement, using scsh's process notation in the build
|
||||
rules.
|
||||
|
||||
\item Manual hacking.
|
||||
\begin{itemize}
|
||||
\item The {\LaTeX} hackery needs yet another serious pass. Most importantly,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
\documentclass[twoside]{report}
|
||||
\usepackage{code,boxedminipage,draftfooters,makeidx,palatino,ct,
|
||||
headings,mantitle,array,matter,a4}
|
||||
headings,mantitle,array,matter,a4,tex2page}
|
||||
|
||||
% Style issues
|
||||
\parskip = 3pt plus 3pt
|
||||
|
|
14
scsh.man
14
scsh.man
|
@ -1,4 +1,4 @@
|
|||
.TH LS48 1
|
||||
.TH LSCSH 1
|
||||
.\" File scsh.man: Manual page template for scsh.
|
||||
.\" Replace LSCSH with the name of your default image and LLIB with the
|
||||
.\" directory containing scshvm and default image.
|
||||
|
@ -22,8 +22,7 @@ The
|
|||
.B LSCSH
|
||||
command loop reads Scheme expressions,
|
||||
evaluates them, and prints their results.
|
||||
The Scheme 48 system is an R4RS system, and also provides features from
|
||||
the draft R5RS standard.
|
||||
The Scheme 48 system is an R5RS system.
|
||||
It also executes commands, which are identified by an initial comma character.
|
||||
Type the command
|
||||
.I ,help
|
||||
|
@ -42,7 +41,7 @@ argument can be one of
|
|||
Either of these switches terminates argument parsing; following arguments
|
||||
are available from scsh as the string list produced by
|
||||
.nf
|
||||
(command-line-arguments)
|
||||
(command-line)
|
||||
.fi
|
||||
The
|
||||
.B \-s
|
||||
|
@ -63,9 +62,12 @@ The
|
|||
.B \-\-
|
||||
switch is used to pass arguments to an interactive scsh.
|
||||
It simply terminates argument parsing, causing following
|
||||
arguments to be bound to
|
||||
arguments to be made available by
|
||||
.nf
|
||||
(command-line-arguments)
|
||||
(command-line)
|
||||
|
||||
There are other command-line switches. For detailed documentation,
|
||||
see the manual, which comes with the distribution.
|
||||
|
||||
.SH FILES
|
||||
.TP
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
/* Exports from signals1.c */
|
||||
|
||||
const int sig2int[];
|
||||
const int max_sig;
|
|
@ -1,6 +1,2 @@
|
|||
/* Cygwin seems to have TZNAME but they forgot to define it */
|
||||
#define HAVE_TZNAME
|
||||
#define tzname _tzname
|
||||
|
||||
/* Cygwin's adds _'s but making configure.in know about dlltool seemed evil */
|
||||
#define DLSYM_ADDS_USCORE
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
(let ((uid (user-effective-uid)))
|
||||
(with-errno-handler ((err data)
|
||||
((errno/acces) 'search-denied)
|
||||
((errno/notdir) 'not-directory)
|
||||
((errno/notdir) 'no-directory)
|
||||
|
||||
;; If the file doesn't exist, we usually return
|
||||
;; 'nonexistent, but we special-case writability
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
|
||||
(define (->delim-matcher x)
|
||||
(if (procedure? x) x ; matcher proc
|
||||
(let ((re (cond ((string? x) (re-string x))
|
||||
(let ((re (cond ((string? x) (posix-string->regexp x))
|
||||
((char-set? x) (re-char-set x))
|
||||
((char? x) (re-string (string x)))
|
||||
((regexp? x) x)
|
||||
|
|
|
@ -122,10 +122,9 @@
|
|||
(cons re-any (str-cons chars res))
|
||||
i))
|
||||
|
||||
((#\[) (receive (cset i) (parse-glob-bracket pat i)
|
||||
((#\[) (receive (re i) (parse-glob-bracket pat i)
|
||||
(lp '()
|
||||
(cons (re-char-set cset)
|
||||
(str-cons chars res))
|
||||
(cons re (str-cons chars res))
|
||||
i)))
|
||||
|
||||
(else (lp (cons c chars) res i))))))))))
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
;;; These defs are things for characters *not* in SRFIs 13 & 14.
|
||||
;;; It includes some R5RS defs that are not correct in S48 in a Latin-1 world.
|
||||
|
||||
(define-interface char-set-predicates-interface
|
||||
(define-interface char-predicates-interface
|
||||
(export
|
||||
((char-lower-case? ; R5RS
|
||||
char-upper-case? ; R5RS
|
||||
|
@ -24,7 +24,7 @@
|
|||
char-ascii?) (proc (:char) :boolean))))
|
||||
|
||||
|
||||
(define-structure char-set-predicates-lib char-set-predicates-interface
|
||||
(define-structure char-predicates-lib char-predicates-interface
|
||||
(open error-package ; ERROR
|
||||
scsh-utilities ; DEPRECATED-PROC
|
||||
char-set-lib
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
chars->char-set ; list->char-set
|
||||
ascii-range->char-set ; ucs-range->char-set (not exact)
|
||||
predicate->char-set ; char-set-filter (not exact)
|
||||
->char-set ; no longer handles a predicate
|
||||
;->char-set ; no longer handles a predicate
|
||||
char-set-every? ; char-set-every
|
||||
char-set-any? ; char-set-any
|
||||
|
||||
char-set-invert ; char-set-complement
|
||||
char-set-invert! ; char-set-complement!
|
||||
|
@ -38,13 +39,16 @@
|
|||
"Change code to use CHAR-SET-FILTER."))
|
||||
(define char-set-every?
|
||||
(deprecated-proc char-set-every 'char-set-every?
|
||||
"Use CHAR-SET-EVERYyn instead."))
|
||||
"Use CHAR-SET-EVERY instead."))
|
||||
(define char-set-any?
|
||||
(deprecated-proc char-set-every 'char-set-any?
|
||||
"Use CHAR-SET-ANY instead."))
|
||||
(define char-set-invert
|
||||
(deprecated-proc char-set-complement 'char-set-invert
|
||||
"Use CHAR-SET-COMPLEMENTyn instead."))
|
||||
"Use CHAR-SET-COMPLEMENT instead."))
|
||||
(define char-set-invert!
|
||||
(deprecated-proc char-set-complement! 'char-set-invert!
|
||||
"Use CHAR-SET-COMPLEMENT!yn instead."))
|
||||
"Use CHAR-SET-COMPLEMENT! instead."))
|
||||
|
||||
(define char-set:alphabetic char-set:letter)
|
||||
(define char-set:numeric char-set:digit)
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
|
||||
(char-set-size (proc (:value) :exact-integer))
|
||||
(char-set-count (proc ((proc (:char) :boolean) :value) :exact-integer))
|
||||
(char-set-contains? (proc (:char :value) :boolean))
|
||||
(char-set-contains? (proc (:value :value) :boolean))
|
||||
|
||||
(char-set-every (proc ((proc (:char) :boolean) :value) :boolean))
|
||||
(char-set-any (proc ((proc (:char) :boolean) :value) :value))
|
||||
|
|
|
@ -1130,7 +1130,7 @@
|
|||
;;; string-index-right string char/char-set/pred [start end]
|
||||
;;; string-skip string char/char-set/pred [start end]
|
||||
;;; string-skip-right string char/char-set/pred [start end]
|
||||
;;; string-count char/char-set/pred string [start end]
|
||||
;;; string-count string char/char-set/pred [start end]
|
||||
;;; There's a lot of replicated code here for efficiency.
|
||||
;;; For example, the char/char-set/pred discrimination has
|
||||
;;; been lifted above the inner loop of each proc.
|
||||
|
@ -1220,7 +1220,7 @@
|
|||
string-skip-right criterion)))))
|
||||
|
||||
|
||||
(define (string-count criterion s . maybe-start+end)
|
||||
(define (string-count s criterion . maybe-start+end)
|
||||
(let-string-start+end (start end) string-count s maybe-start+end
|
||||
(cond ((char? criterion)
|
||||
(do ((i start (+ i 1))
|
||||
|
|
|
@ -0,0 +1,315 @@
|
|||
;;; string-lib
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; string-map string-map!
|
||||
;;; string-fold string-fold-right
|
||||
;;; string-unfold string-tabulate
|
||||
;;; string-for-each string-iter
|
||||
;;; string-every string-any
|
||||
;;; string-compare string-compare-ci
|
||||
;;; substring-compare substring-compare-ci
|
||||
;;; string= string< string> string<= string>= string<>
|
||||
;;; string-ci= string-ci< string-ci> string-ci<= string-ci>= string-ci<>
|
||||
;;; substring= substring<> substring-ci= substring-ci<>
|
||||
;;; substring< substring> substring-ci< substring-ci>
|
||||
;;; substring<= substring>= substring-ci<= substring-ci>=
|
||||
;;; string-upper-case? string-lower-case?
|
||||
;;; capitalize-string capitalize-words string-downcase string-upcase
|
||||
;;; capitalize-string! capitalize-words! string-downcase! string-upcase!
|
||||
;;; string-take string-drop
|
||||
;;; string-pad string-pad-right
|
||||
;;; string-trim string-trim-right string-trim-both
|
||||
;;; string-filter string-delete
|
||||
;;; string-index string-index-right string-skip string-skip-right
|
||||
;;; string-prefix-count string-prefix-count-ci
|
||||
;;; string-suffix-count string-suffix-count-ci
|
||||
;;; substring-prefix-count substring-prefix-count-ci
|
||||
;;; substring-suffix-count substring-suffix-count-ci
|
||||
;;; string-prefix? string-prefix-ci?
|
||||
;;; string-suffix? string-suffix-ci?
|
||||
;;; substring-prefix? substring-prefix-ci?
|
||||
;;; substring-suffix? substring-suffix-ci?
|
||||
;;; substring? substring-ci?
|
||||
;;; string-fill! string-copy! string-copy substring
|
||||
;;; string-reverse string-reverse! reverse-list->string
|
||||
;;; string->list
|
||||
;;; string-concat string-concat/shared string-append/shared
|
||||
;;; xsubstring string-xcopy!
|
||||
;;; string-null?
|
||||
;;; join-strings
|
||||
;;;
|
||||
;;; string? make-string string string-length string-ref string-set!
|
||||
;;; string-append list->string
|
||||
|
||||
(define-interface string-lib-interface
|
||||
(export
|
||||
;; string-map proc s [start end] -> s
|
||||
(string-map (proc ((proc (:char) :char)
|
||||
:string
|
||||
&opt :exact-integer :exact-integer)
|
||||
:string))
|
||||
|
||||
;; string-map! proc s [start end] -> unspecific
|
||||
(string-map! (proc ((proc (:char) :values)
|
||||
:string
|
||||
&opt :exact-integer :exact-integer)
|
||||
:unspecific))
|
||||
|
||||
;; string-fold kons knil s [start end] -> value
|
||||
;; string-fold-right kons knil s [start end] -> value
|
||||
((string-fold string-fold-right)
|
||||
(proc ((proc (:char :value) :value)
|
||||
:value :string
|
||||
&opt :exact-integer :exact-integer)
|
||||
:value))
|
||||
|
||||
;; string-unfold p f g seed -> string
|
||||
(string-unfold (proc ((proc (:value) :boolean)
|
||||
(proc (:value) :char)
|
||||
(proc (:value) :value)
|
||||
:value)
|
||||
:string))
|
||||
|
||||
; Enough is enough.
|
||||
; ;; string-unfoldn p f g seed ... -> string
|
||||
; (string-unfoldn (proc ((procedure :values :boolean)
|
||||
; (procedure :values :char)
|
||||
; (procedure :values :values)
|
||||
; &rest :value)
|
||||
; :string))
|
||||
|
||||
;; string-tabulate proc len -> string
|
||||
(string-tabulate (proc ((proc (:exact-integer) :char) :exact-integer)
|
||||
:string))
|
||||
|
||||
;; string-for-each proc s [start end] -> unspecific
|
||||
;; string-iter proc s [start end] -> unspecific
|
||||
((string-for-each string-iter)
|
||||
(proc ((proc (:char) :values) :string &opt :exact-integer :exact-integer)
|
||||
:unspecific))
|
||||
|
||||
;; string-every pred s [start end]
|
||||
;; string-any pred s [start end]
|
||||
(string-every
|
||||
(proc ((proc (:char) :boolean) :string &opt :exact-integer :exact-integer)
|
||||
:boolean))
|
||||
(string-any
|
||||
(proc ((proc (:char) :boolean) :string &opt :exact-integer :exact-integer)
|
||||
:value))
|
||||
|
||||
;; string-compare string1 string2 lt-proc eq-proc gt-proc
|
||||
;; string-compare-ci string1 string2 lt-proc eq-proc gt-proc
|
||||
((string-compare string-compare-ci)
|
||||
(proc (:string :string (proc (:exact-integer) :values)
|
||||
(proc (:exact-integer) :values)
|
||||
(proc (:exact-integer) :values))
|
||||
:values))
|
||||
|
||||
;; substring-compare string1 start1 end1 string2 start2 end2 lt eq gt
|
||||
;; substring-compare-ci string1 start1 end1 string2 start2 end2 lt eq gt
|
||||
((substring-compare substring-compare-ci)
|
||||
(proc (:string :exact-integer :exact-integer
|
||||
:string :exact-integer :exact-integer
|
||||
(proc (:exact-integer) :values)
|
||||
(proc (:exact-integer) :values)
|
||||
(proc (:exact-integer) :values))
|
||||
:values))
|
||||
|
||||
;; string< string1 string2
|
||||
((string= string< string> string<= string>= string<>
|
||||
string-ci= string-ci< string-ci> string-ci<= string-ci>= string-ci<>)
|
||||
(proc (&rest :string) :value))
|
||||
|
||||
;; substring< string1 start1 end1 string2 start2 end2
|
||||
((substring= substring<> substring-ci= substring-ci<>
|
||||
substring< substring> substring-ci< substring-ci>
|
||||
substring<= substring>= substring-ci<= substring-ci>=)
|
||||
(proc (:string :exact-integer :exact-integer
|
||||
:string :exact-integer :exact-integer)
|
||||
:value))
|
||||
|
||||
;; string-upper-case? string [start end]
|
||||
;; string-lower-case? string [start end]
|
||||
((string-upper-case? string-lower-case?)
|
||||
(proc (:string &opt :exact-integer :exact-integer) :boolean))
|
||||
|
||||
;; capitalize-string string [start end]
|
||||
;; capitalize-words string [start end]
|
||||
;; string-downcase string [start end]
|
||||
;; string-upcase string [start end]
|
||||
;; capitalize-string! string [start end]
|
||||
;; capitalize-words! string [start end]
|
||||
;; string-downcase! string [start end]
|
||||
;; string-upcase! string [start end]
|
||||
((capitalize-string capitalize-words string-downcase string-upcase)
|
||||
(proc (:string &opt :exact-integer :exact-integer) :string))
|
||||
((capitalize-string! capitalize-words! string-downcase! string-upcase!)
|
||||
(proc (:string &opt :exact-integer :exact-integer) :unspecific))
|
||||
|
||||
;; string-take string nchars
|
||||
;; string-drop string nchars
|
||||
((string-take string-drop) (proc (:string :exact-integer) :string))
|
||||
|
||||
;; string-pad string k [char start end]
|
||||
;; string-pad-right string k [char start end]
|
||||
((string-pad string-pad-right)
|
||||
(proc (:string :exact-integer &opt :char :exact-integer :exact-integer)
|
||||
:string))
|
||||
|
||||
;; string-trim string [char/char-set/pred start end]
|
||||
;; string-trim-right string [char/char-set/pred start end]
|
||||
;; string-trim-both string [char/char-set/pred start end]
|
||||
((string-trim string-trim-right string-trim-both)
|
||||
(proc (:string &opt :value :exact-integer :exact-integer)
|
||||
:string))
|
||||
|
||||
;; string-filter char/char-set/pred string [start end]
|
||||
;; string-delete char/char-set/pred string [start end]
|
||||
((string-filter string-delete)
|
||||
(proc (:value :string &opt :exact-integer :exact-integer) :string))
|
||||
|
||||
;; string-index string char/char-set/pred [start end]
|
||||
;; string-index-right string char/char-set/pred [end start]
|
||||
;; string-skip string char/char-set/pred [start end]
|
||||
;; string-skip-right string char/char-set/pred [end start]
|
||||
((string-index string-index-right string-skip string-skip-right)
|
||||
(proc (:string :value &opt :exact-integer :exact-integer)
|
||||
:value))
|
||||
|
||||
;; string-prefix-count string1 string2
|
||||
;; string-suffix-count string1 string2
|
||||
;; string-prefix-count-ci string1 string2
|
||||
;; string-suffix-count-ci string1 string2
|
||||
((string-prefix-count string-prefix-count-ci
|
||||
string-suffix-count string-suffix-count-ci)
|
||||
(proc (:string :string) :exact-integer))
|
||||
|
||||
;; substring-prefix-count string1 start1 end1 string2 start2 end2
|
||||
;; substring-suffix-count string1 start1 end1 string2 start2 end2
|
||||
;; substring-prefix-count-ci string1 start1 end1 string2 start2 end2
|
||||
;; substring-suffix-count-ci string1 start1 end1 string2 start2 end2
|
||||
((substring-prefix-count substring-prefix-count-ci
|
||||
substring-suffix-count substring-suffix-count-ci)
|
||||
(proc (:string :exact-integer :exact-integer
|
||||
:string :exact-integer :exact-integer)
|
||||
:exact-integer))
|
||||
|
||||
|
||||
;; string-prefix? string1 string2
|
||||
;; string-suffix? string1 string2
|
||||
;; string-prefix-ci? string1 string2
|
||||
;; string-suffix-ci? string1 string2
|
||||
((string-prefix? string-prefix-ci?
|
||||
string-suffix? string-suffix-ci?)
|
||||
(proc (:string :string) :boolean))
|
||||
|
||||
;; substring-prefix? string1 start1 end1 string2 start2 end2
|
||||
;; substring-suffix? string1 start1 end1 string2 start2 end2
|
||||
;; substring-prefix-ci? string1 start1 end1 string2 start2 end2
|
||||
;; substring-suffix-ci? string1 start1 end1 string2 start2 end2
|
||||
((substring-prefix? substring-prefix-ci?
|
||||
substring-suffix? substring-suffix-ci?)
|
||||
(proc (:string :exact-integer :exact-integer
|
||||
:string :exact-integer :exact-integer)
|
||||
:boolean))
|
||||
|
||||
;; substring? pattern string [start end]
|
||||
;; substring-ci? pattern string [start end]
|
||||
((substring? substring-ci?)
|
||||
(proc (:string :string &opt :exact-integer :exact-integer)
|
||||
:value))
|
||||
|
||||
;; string-fill! string char [start end]
|
||||
(string-fill! (proc (:string :char &opt :exact-integer :exact-integer)
|
||||
:unspecific))
|
||||
|
||||
;; string-copy! to tstart from [fstart fend]
|
||||
(string-copy! (proc (:string :exact-integer :string
|
||||
&opt :exact-integer :exact-integer)
|
||||
:unspecific))
|
||||
|
||||
;; string-copy s [start end] -> string
|
||||
;; substring s start [end] -> string
|
||||
(string-copy (proc (:string &opt :exact-integer :exact-integer) :string))
|
||||
(substring (proc (:string :exact-integer &opt :exact-integer) :string))
|
||||
|
||||
;; string-reverse s [start end]
|
||||
;; string-reverse! s [start end]
|
||||
(string-reverse (proc (:string &opt :exact-integer :exact-integer) :string))
|
||||
(string-reverse! (proc (:string &opt :exact-integer :exact-integer) :unspecific))
|
||||
|
||||
;; reverse-list->string char-list
|
||||
;; string->list s [start end]
|
||||
;; string-concat string-list
|
||||
;; string-concat/shared string-list
|
||||
;; string-append/shared s ...
|
||||
(reverse-list->string (proc (:value) :string))
|
||||
(string->list (proc (:string &opt :exact-integer :exact-integer) :value))
|
||||
((string-concat string-concat/shared) (proc (:value) :string))
|
||||
(string-append/shared (proc (&rest :string) :string))
|
||||
|
||||
;; xsubstring s from [to start end]
|
||||
;; string-xcopy! target tstart s from [to start end]
|
||||
(xsubstring (proc (:string :exact-integer &opt
|
||||
:exact-integer :exact-integer :exact-integer)
|
||||
:string))
|
||||
(string-xcopy! (proc (:string :exact-integer :string :exact-integer &opt
|
||||
:exact-integer :exact-integer :exact-integer)
|
||||
:unspecific))
|
||||
|
||||
;; string-null? s
|
||||
(string-null? (proc (:string) :boolean))
|
||||
|
||||
(join-strings (proc (:value &opt :string :symbol) :string))
|
||||
|
||||
;; Here are the R4RS procs
|
||||
(string? (proc (:value) :boolean))
|
||||
(make-string (proc (:exact-integer &opt :char) :string))
|
||||
(string (proc (&rest :char) :string))
|
||||
(string-length (proc (:string) :exact-integer))
|
||||
(string-ref (proc (:string :exact-integer) :char))
|
||||
(string-set! (proc (:string :exact-integer :char) :unspecific))
|
||||
|
||||
; Not provided by string-lib.
|
||||
;((string=? string-ci=? string<? string-ci<?
|
||||
; string>? string-ci>? string<=? string-ci<=?
|
||||
; string>=? string-ci>=?) (proc (:string :string) :boolean))
|
||||
|
||||
;; These are the R4RS types for SUBSTRING, STRING-COPY, STRING-FILL!,
|
||||
;; and STRING->LIST. The string-lib types are different -- extended.
|
||||
;(substring (proc (:string :exact-integer :exact-integer) :string))
|
||||
;(string-copy (proc (:string) :string))
|
||||
;(string-fill! (proc (:string :char) :unspecific))
|
||||
;(string->list (proc (:string) :value))
|
||||
|
||||
(string-append (proc (&rest :string) :string))
|
||||
(list->string (proc (:value) :string))
|
||||
))
|
||||
|
||||
|
||||
;;; make-kmp-restart-vector
|
||||
;;; parse-final-start+end
|
||||
;;; parse-start+end
|
||||
;;; check-substring-spec
|
||||
|
||||
(define-interface string-lib-internals-interface
|
||||
(export
|
||||
(parse-final-start+end (proc ((procedure :values :values) :string :value)
|
||||
(some-values :exact-integer :exact-integer)))
|
||||
(parse-start+end (proc ((procedure :values :values) :string :value)
|
||||
(some-values :exact-integer :exact-integer :value)))
|
||||
(check-substring-spec (proc ((procedure :values :values) :string :exact-integer :exact-integer)
|
||||
:unspecific))
|
||||
(make-kmp-restart-vector (proc (:string (proc (:char :char) :boolean))
|
||||
:vector))))
|
||||
|
||||
|
||||
(define-structures ((string-lib string-lib-interface)
|
||||
(string-lib-internals string-lib-internals-interface))
|
||||
(access scheme) ; Get at R5RS SUBSTRING
|
||||
(open receiving ; RECEIVE
|
||||
char-set-package; Various
|
||||
error-package ; ERROR
|
||||
let-opt ; LET-OPTIONALS :OPTIONAL
|
||||
structure-refs ; STRUCTURE-REF
|
||||
scheme)
|
||||
(files string-lib))
|
|
@ -1,578 +0,0 @@
|
|||
Todo:
|
||||
parse-start+end parse-final-start+end need "string" in the name
|
||||
Also, export macro binder.
|
||||
What's up w/quotient? (quotient -1 3) = 0.
|
||||
regexp-foldl
|
||||
type regexp interface
|
||||
land*
|
||||
Let-optional:
|
||||
A let-optional that parses a prefix of the args.
|
||||
Arg checking forms that get used if it parses, but are not
|
||||
applied to the default.
|
||||
|
||||
The Scheme Underground string library includes a rich set of operations
|
||||
for manipulating strings. These are frequently useful for scripting and
|
||||
other text-manipulation applications.
|
||||
|
||||
The library's design was influenced by the string libraries found in MIT
|
||||
Scheme, Gambit, RScheme, MzScheme, slib, Common Lisp, Bigloo, guile, APL and
|
||||
the SML standard basis. Some of the code bears a distant family relation to
|
||||
the MIT Scheme implementation, and being derived from that code, is covered by
|
||||
the MIT Scheme copyright (which is a fairly generic "free" copyright -- see
|
||||
the source file for details). The fast KMP string-search code used in
|
||||
SUBSTRING? was loosely adapted from old slib code by Stephen Bevan.
|
||||
|
||||
The library has the following design principles:
|
||||
- *All* procedures involving character comparison are available in
|
||||
both case-sensitive and case-insensitive forms.
|
||||
|
||||
- *All* functionality is available in substring and full-string forms.
|
||||
|
||||
- The procedures are spec'd so as to permit efficient implementation in a
|
||||
Scheme that provided shared-text substrings (e.g., guile). This means that
|
||||
you should not rely on many of the substring-selecting procedures to return
|
||||
freshly-allocated strings. Careful attention is paid to the issue of which
|
||||
procedures allocate fresh storage, and which are permitted to return results
|
||||
that share storage with the arguments.
|
||||
|
||||
- Common Lisp theft:
|
||||
+ inequality functions return mismatch index.
|
||||
I generalised this so that this "protocol" is extended even to
|
||||
the equality functions. This means that clients can be handed any generic
|
||||
string-comparison function and rely on the meaning of the true value.
|
||||
|
||||
+ Common Lisp capitalisation definition
|
||||
|
||||
The library addresses some problems with the R5RS string procedures:
|
||||
- Question marks after string-comparison functions (string=?, etc.)
|
||||
This is inconsistent with numeric comparison functions, and ugly, too.
|
||||
- String-comparison functions do not provide useful true value.
|
||||
- STRING-COPY should have optional start/end args;
|
||||
SUBSTRING shouldn't specify if it copies or returns shared bits.
|
||||
- STRING-FILL! and STRING->LIST should take optional start/end args.
|
||||
- No <> function provided.
|
||||
|
||||
In the following procedure specifications:
|
||||
- Any S parameter is a string;
|
||||
|
||||
- START and END parameters are half-open string indices specifying
|
||||
a substring within a string parameter; when optional, they default
|
||||
to 0 and the length of the string, respectively. When specified, it
|
||||
must be the case that 0 <= START <= END <= (string-length S), for
|
||||
the corresponding parameter S. They typically restrict a procedure's
|
||||
action to the indicated substring.
|
||||
|
||||
- A CHAR/CHAR-SET/PRED parameter is a value used to select/search
|
||||
for a character in a string. If it is a character, it is used in
|
||||
an equality test; if it is a character set, it is used as a
|
||||
membership test; if it is a procedure, it is applied to the
|
||||
characters as a test predicate.
|
||||
|
||||
This library contains a large number of procedures, but they follow
|
||||
a consistent naming scheme. The names are composed of smaller lexemes
|
||||
in a regular way that exposes the structure and relationships between the
|
||||
procedures. This should help the programmer to recall or reconstitute the name
|
||||
of the particular procedure that he needs when writing his own code. In
|
||||
particular
|
||||
- Procedures whose names end in "-ci" are case-insensitive variants.
|
||||
- Procedures whose names end in "!" are side-effecting variants.
|
||||
These procedures generally return an unspecified value.
|
||||
- The order of common parameters is fairly consistent across the
|
||||
different procedures.
|
||||
|
||||
For more text-manipulation functionality, see also the regular expression,
|
||||
file-name, character set, and character->character partial map packages.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
* R4RS/R5RS procedures
|
||||
|
||||
The R4RS and R5RS reports define 22 string procedures. The string-lib
|
||||
package includes 8 of these exactly as defined, 4 in an extended,
|
||||
backwards-compatible way, and drops the remaining 10 (whose functionality
|
||||
is available via other bindings).
|
||||
|
||||
The 8 procedures provided exactly as documented in the reports are
|
||||
string?
|
||||
make-string
|
||||
string
|
||||
string-length
|
||||
string-ref
|
||||
string-set!
|
||||
string-append
|
||||
list->string
|
||||
|
||||
The ten functions not included are the R4RS string-comparison functions:
|
||||
string=? string-ci=?
|
||||
string<? string-ci<?
|
||||
string>? string-ci>?
|
||||
string<=? string-ci<=?
|
||||
string>=? string-ci>=?
|
||||
The string-lib package provides alternate bindings.
|
||||
|
||||
Additionally, the four extended procedures are
|
||||
|
||||
string-fill! s char [start end] -> unspecific
|
||||
string->list s [start end] -> char-list
|
||||
substring s start [end] -> string
|
||||
string-copy s [start end] -> string
|
||||
|
||||
These procedures are documented in the following section. In brief, they are
|
||||
extended to take optional start/end parameters specifying substring ranges;
|
||||
Additionally, SUBSTRING is allowed to return a value that shares storage with
|
||||
its argument.
|
||||
|
||||
|
||||
* Procedures
|
||||
|
||||
These procedures are contained in the Scheme 48 package "string-lib",
|
||||
which is open in the default user package. They are not found in the
|
||||
"scsh" package; script writers and other programmers that use the Scheme
|
||||
48 module system must open string-lib explicitly.
|
||||
|
||||
string-map proc s [start end] -> string
|
||||
string-map! proc s [start end] -> unspecified
|
||||
PROC is a char->char procedure; it is mapped over S.
|
||||
Note: no sequence order is specified.
|
||||
|
||||
string-fold kons knil s [start end] -> value
|
||||
string-fold-right kons knil s [start end] -> value
|
||||
These are the fundamental iterators for strings.
|
||||
The left-fold operator maps the KONS procedure across the
|
||||
string from left to right
|
||||
(... (kons s[2] (kons s[1] (kons s[0] knil))))
|
||||
In other words, string-fold obeys the recursion
|
||||
(string-fold kons knil s start end) =
|
||||
(string-fold kons (kons s[start] knil) start+1 end)
|
||||
|
||||
The right-fold operator maps the KONS procedure across the
|
||||
string from right to left
|
||||
(kons s[0] (... (kons s[end-3] (kons s[end-2] (kons s[end-1] knil)))))
|
||||
obeying the recursion
|
||||
(string-fold-right kons knil s start end) =
|
||||
(string-fold-right kons (kons s[end-1] knil) start end-1)
|
||||
|
||||
Examples:
|
||||
To convert a string to a list of chars:
|
||||
(string-fold-right cons '() s)
|
||||
|
||||
To count the number of lower-case characters in a string:
|
||||
(string-fold (lambda (c count)
|
||||
(if (char-set-contains? char-set:lower c)
|
||||
(+ count 1)
|
||||
count))
|
||||
0
|
||||
s)
|
||||
|
||||
string-unfold p f g seed -> string
|
||||
This is the fundamental constructor for strings.
|
||||
- G is used to generate a series of "seed" values from the initial seed:
|
||||
SEED, (G SEED), (G^2 SEED), (G^3 SEED), ...
|
||||
- P tells us when to stop -- when it returns true when applied to one
|
||||
of these seed values.
|
||||
- F maps each seed value to the corresponding character
|
||||
in the result string.
|
||||
|
||||
More precisely, the following (simple, inefficient) definition holds:
|
||||
(define (string-unfold p f g seed)
|
||||
(if (p seed) ""
|
||||
(string-append (string (f seed))
|
||||
(string-unfold p f g (g seed)))))
|
||||
|
||||
STRING-UNFOLD is a fairly powerful constructor -- you can use it to
|
||||
reverse a string, copy a string, convert a list to a string, read
|
||||
a port into a string, and so forth. Examples:
|
||||
(port->string p) = (string-unfold eof-object? values
|
||||
(lambda (x) (read-char p))
|
||||
(read-char p))
|
||||
|
||||
(list->string lis) = (string-unfold null? car cdr lis)
|
||||
|
||||
(tabulate-string f size) = (string-unfold (lambda (i) (= i size)) f add1 0)
|
||||
|
||||
To map F over a list LIS, producing a string:
|
||||
(string-unfold null? (compose f car) cdr lis)
|
||||
|
||||
string-tabulate proc len -> string
|
||||
PROC is an integer->char procedure. Construct a string of size LEN
|
||||
by applying PROC to each index to produce the corresponding string
|
||||
element. The order in which PROC is applied to the indices is not
|
||||
specified.
|
||||
|
||||
string-for-each proc s [start end] -> unspecified
|
||||
string-iter proc s [start end] -> unspecified
|
||||
Apply PROC to each character in S.
|
||||
STRING-FOR-EACH has no specified iteration order.
|
||||
STRING-ITER is required to iterate from START to END
|
||||
in increasing order.
|
||||
|
||||
string-every? pred s [start end] -> boolean
|
||||
string-any? pred s [start end] -> value
|
||||
Note: no sequence order specified.
|
||||
Checks to see if predicate PRED is true of every / any character in S.
|
||||
STRING-ANY? is witness-generating -- it applies PRED to the elements
|
||||
of S, returning the first true value it finds, otherwise false.
|
||||
|
||||
string-compare s1 s2 lt-proc eq-proc gt-proc -> values
|
||||
string-compare-ci s1 s2 lt-proc eq-proc gt-proc -> values
|
||||
Apply LT-PROC, EQ-PROC, GT-PROC to the mismatch index, depending
|
||||
upon whether S1 is less than, equal to, or greater than S2.
|
||||
The "mismatch index" is the largest index i such that for
|
||||
every 0 <= j < i, s1[j] = s2[j] -- that is, I is the first
|
||||
position that doesn't match. If S1 = S2, the mismatch index
|
||||
is simply the length of the strings; we observe the protocol
|
||||
in this redundant case for uniformity.
|
||||
|
||||
substring-compare s1 start1 end1 s2 start2 end2 lt-proc eq-proc gt-proc -> values
|
||||
substring-compare-ci s1 start1 end1 s2 start2 end2 lt-proc eq-proc gt-proc -> values
|
||||
The continuation procedures are applied to S1's mismatch index (as defined
|
||||
above). In the case of EQ-PROC, this is always END1.
|
||||
|
||||
string= s1 s2 -> #f or integer
|
||||
string<> s1 s2 -> #f or integer
|
||||
string< s1 s2 -> #f or integer
|
||||
string> s1 s2 -> #f or integer
|
||||
string<= s1 s2 -> #f or integer
|
||||
string>= s1 s2 -> #f or integer
|
||||
If the comparison operation is true, the function returns the
|
||||
mismatch index (as defined for the previous comparator functions).
|
||||
|
||||
string-ci= s1 s2 -> #f or integer
|
||||
string-ci<> s1 s2 -> #f or integer
|
||||
string-ci< s1 s2 -> #f or integer
|
||||
string-ci> s1 s2 -> #f or integer
|
||||
string-ci<= s1 s2 -> #f or integer
|
||||
string-ci>= s1 s2 -> #f or integer
|
||||
Case-insensitive variants.
|
||||
|
||||
substring= s1 start1 end1 s2 start2 end2 -> #f or integer
|
||||
substring<> s1 start1 end1 s2 start2 end2 -> #f or integer
|
||||
substring< s1 start1 end1 s2 start2 end2 -> #f or integer
|
||||
substring> s1 start1 end1 s2 start2 end2 -> #f or integer
|
||||
substring<= s1 start1 end1 s2 start2 end2 -> #f or integer
|
||||
substring>= s1 start1 end1 s2 start2 end2 -> #f or integer
|
||||
|
||||
substring-ci= s1 start1 end1 s2 start2 end2 -> #f or integer
|
||||
substring-ci<> s1 start1 end1 s2 start2 end2 -> #f or integer
|
||||
substring-ci< s1 start1 end1 s2 start2 end2 -> #f or integer
|
||||
substring-ci> s1 start1 end1 s2 start2 end2 -> #f or integer
|
||||
substring-ci<= s1 start1 end1 s2 start2 end2 -> #f or integer
|
||||
substring-ci>= s1 start1 end1 s2 start2 end2 -> #f or integer
|
||||
These variants restrict the comparison to the indicated
|
||||
substrings of S1 and S2.
|
||||
|
||||
string-upper-case? s [start end] -> boolean
|
||||
string-lower-case? s [start end] -> boolean
|
||||
STRING-UPPER-CASE? returns true iff the string contains
|
||||
no lower-case characters. STRING-LOWER-CASE returns true
|
||||
iff the string contains no upper-case characters.
|
||||
(string-upper-case? "") => #t
|
||||
(string-lower-case? "") => #t
|
||||
(string-upper-case? "FOOb") => #f
|
||||
(string-upper-case? "U.S.A.") => #t
|
||||
|
||||
capitalize-string s [start end] -> string
|
||||
capitalize-string! s [start end] -> unspecified
|
||||
Capitalize the string: upcase the first alphanumeric character,
|
||||
and downcase the rest of the string. CAPITALIZE-STRING returns
|
||||
a freshly allocated string.
|
||||
|
||||
(capitalize-string "--capitalize tHIS sentence.") =>
|
||||
"--Capitalize this sentence."
|
||||
|
||||
(capitalize-string "see Spot run. see Nix run.") =>
|
||||
"See spot run. see nix run."
|
||||
|
||||
(capitalize-string "3com makes routers.") =>
|
||||
"3com makes routers."
|
||||
|
||||
capitalize-words s [start end] -> string
|
||||
capitalize-words! s [start end] -> unspecified
|
||||
A "word" is a maximal contiguous sequence of alphanumeric characters.
|
||||
Upcase the first character of every word; downcase the rest of the word.
|
||||
CAPITALIZE-WORDS returns a freshly allocated string.
|
||||
|
||||
(capitalize-words "HELLO, 3THErE, my nAME IS olin") =>
|
||||
"Hello, 3there, My Name Is Olin"
|
||||
|
||||
More sophisticated capitalisation procedures can be synthesized
|
||||
using CAPITALIZE-STRING and pattern matchers. In this context,
|
||||
the REGEXP-SUBSTITUTE/GLOBAL procedure may be useful for picking
|
||||
out the units to be capitalised and applying CAPITALIZE-STRING to
|
||||
their components.
|
||||
|
||||
string-upcase s [start end] -> string
|
||||
string-upcase! s [start end] -> unspecified
|
||||
string-downcase s [start end] -> string
|
||||
string-downcase! s [start end] -> unspecified
|
||||
Raise or lower the case of the alphabetic characters in the string.
|
||||
STRING-UPCASE and STRING-DOWNCASE return freshly allocated strings.
|
||||
|
||||
string-take s nchars -> string
|
||||
string-drop s nchars -> string
|
||||
string-take-right s nchars -> string
|
||||
string-drop-right s nchars -> string
|
||||
STRING-TAKE returns the first NCHARS of STRING;
|
||||
STRING-DROP returns all but the first NCHARS of STRING.
|
||||
STRING-TAKE-RIGHT returns the last NCHARS of STRING;
|
||||
STRING-DROP-RIGHT returns all but the last NCHARS of STRING.
|
||||
These generalise MIT Scheme's HEAD & TAIL functions.
|
||||
If these procedures produce the entire string, they may return either
|
||||
S or a copy of S; in some implementations, proper substrings may share
|
||||
memory with S.
|
||||
|
||||
string-pad s k [char start end] -> string
|
||||
string-pad-right s k [char start end] -> string
|
||||
Build a string of length K comprised of S padded on the left (right)
|
||||
by as many occurences of the character CHAR as needed. If S has more
|
||||
than K chars, it is truncated on the left (right) to length k. CHAR
|
||||
defaults to #\space.
|
||||
|
||||
If K is exactly the length of S, these functions may return
|
||||
either S or a copy of S.
|
||||
|
||||
string-trim s [char/char-set/pred start end] -> string
|
||||
string-trim-right s [char/char-set/pred start end] -> string
|
||||
string-trim-both s [char/char-set/pred start end] -> string
|
||||
Trim S by skipping over all characters on the left / on the right /
|
||||
on both sides that satisfy the second parameter CHAR/CHAR-SET/PRED:
|
||||
- If it is a character CHAR, characters equal to CHAR are trimmed.
|
||||
- If it is a char set CHAR-SET, characters contained in CHAR-SET
|
||||
are trimmed.
|
||||
- If it is a predicate PRED, it is a test predicate that is applied
|
||||
to the characters in S; a character causing it to return true
|
||||
is skipped.
|
||||
CHAR/CHAR/SET-PRED defaults to CHAR-SET:WHITESPACE.
|
||||
|
||||
If no trimming occurs, these functions may return either S or a copy of S;
|
||||
in some implementations, proper substrings may share memory with S.
|
||||
|
||||
(string-trim-both " The outlook wasn't brilliant, \n\r")
|
||||
=> "The outlook wasn't brilliant,"
|
||||
|
||||
string-filter s char/char-set/pred [start end] -> string
|
||||
string-delete s char/char-set/pred [start end] -> string
|
||||
Filter the string S, retaining only those characters that
|
||||
satisfy / do not satisfy the CHAR/CHAR-SET/PRED argument. If
|
||||
this argument is a procedure, it is applied to the character
|
||||
as a predicate; if it is a char-set, the character is tested
|
||||
for membership; if it is a character, it is used in an equality test.
|
||||
|
||||
If the string is unaltered by the filtering operation, these
|
||||
functions may return either S or a copy of S.
|
||||
|
||||
string-index s char/char-set/pred [start end] -> integer or #f
|
||||
string-index-right s char/char-set/pred [end start] -> integer or #f
|
||||
string-skip s char/char-set/pred [start end] -> integer or #f
|
||||
string-skip-right s char/char-set/pred [end start] -> integer or #f
|
||||
Note the inverted start/end ordering of index-right and skip-right's
|
||||
parameters.
|
||||
|
||||
Index (index-right) searches through the string from the left (right),
|
||||
returning the index of the first occurence of a character which
|
||||
- equals CHAR/CHAR-SET/PRED (if it is a character);
|
||||
- is in CHAR/CHAR-SET/PRED (if it is a char-set);
|
||||
- satisfies the predicate CHAR/CHAR-SET/PRED (if it is a procedure).
|
||||
If no match is found, the functions return false.
|
||||
|
||||
The skip functions are similar, but use the complement of the criteria:
|
||||
they search for the first char that *doesn't* satisfy the test. E.g.,
|
||||
to skip over initial whitespace, say
|
||||
(cond ((string-skip s char-set:whitespace) =>
|
||||
(lambda (i)
|
||||
;; (string-ref s i) is not whitespace.
|
||||
...)))
|
||||
|
||||
string-prefix-count s1 s2 -> integer
|
||||
string-suffix-count s1 s2 -> integer
|
||||
string-prefix-count-ci s1 s2 -> integer
|
||||
string-suffix-count-ci s1 s2 -> integer
|
||||
Return the length of the longest common prefix/suffix of the two strings.
|
||||
This is equivalent to the "mismatch index" for the strings.
|
||||
|
||||
substring-prefix-count s1 start1 end1 s2 start2 end2 -> integer
|
||||
substring-suffix-count s1 start1 end1 s2 start2 end2 -> integer
|
||||
substring-prefix-count-ci s1 start1 end1 s2 start2 end2 -> integer
|
||||
substring-suffix-count-ci s1 start1 end1 s2 start2 end2 -> integer
|
||||
Substring variants.
|
||||
|
||||
string-prefix? s1 s2 -> boolean
|
||||
string-suffix? s1 s2 -> boolean
|
||||
string-prefix-ci? s1 s2 -> boolean
|
||||
string-suffix-ci? s1 s2 -> boolean
|
||||
Is S1 a prefix/suffix of S2?
|
||||
|
||||
substring-prefix? s1 start1 end1 s2 start2 end2 -> boolean
|
||||
substring-suffix? s1 start1 end1 s2 start2 end2 -> boolean
|
||||
substring-prefix-ci? s1 start1 end1 s2 start2 end2 -> boolean
|
||||
substring-suffix-ci? s1 start1 end1 s2 start2 end2 -> boolean
|
||||
Substring variants.
|
||||
|
||||
substring? s1 s2 [start end] -> integer or false
|
||||
substring-ci? s1 s2 [start end] -> integer or false
|
||||
Return the index in S2 where S1 occurs as a substring, or false.
|
||||
The returned index is in the range [start,end).
|
||||
The current implementation uses the Knuth-Morris-Pratt algorithm.
|
||||
|
||||
string-fill! s char [start end] -> unspecified
|
||||
Store CHAR into the elements of S.
|
||||
This is the R4RS procedure extended to have optional START/END parameters.
|
||||
|
||||
string-copy! target tstart s [start end] -> unspecified
|
||||
Copy the sequence of characters from index range [START,END) in
|
||||
string S to string TARGET, beginning at index TSTART. The characters
|
||||
are copied left-to-right or right-to-left as needed -- the copy is
|
||||
guaranteed to work, even if TARGET and S are the same string.
|
||||
|
||||
substring s start [end] -> string
|
||||
string-copy s [start end] -> string
|
||||
These R4RS procedures are extended to have optional START/END parameters.
|
||||
Use STRING-COPY when you want to indicate explicitly in your code that you
|
||||
wish to allocate new storage; use SUBSTRING when you don't care if you
|
||||
get a fresh copy or share storage with the original string.
|
||||
E.g.:
|
||||
(string-copy "Beta substitution") => "Beta substitution"
|
||||
(string-copy "Beta substitution" 1 10)
|
||||
=> "eta subst"
|
||||
(string-copy "Beta substitution" 5) => "substitution"
|
||||
|
||||
SUBSTRING may return a value with shares memory with S.
|
||||
|
||||
string-reverse s [start end] -> string
|
||||
string-reverse! s [start end] -> unspecific
|
||||
Reverse the string.
|
||||
|
||||
reverse-list->string char-list -> string
|
||||
An efficient implementation of (compose string->list reverse):
|
||||
(reverse-list->string '(#\a #\B #\c)) -> "cBa"
|
||||
This is a common idiom in the epilog of string-processing loops
|
||||
that accumulate an answer in a reverse-order list.
|
||||
|
||||
string-concat string-list -> string
|
||||
Append the elements of STRING-LIST together into a single list.
|
||||
Guaranteed to return a freshly allocated list. Appears sufficiently
|
||||
often as to warrant being named.
|
||||
|
||||
string-concat/shared string-list -> string
|
||||
string-append/shared s ... -> string
|
||||
These two procedures are variants of STRING-CONCAT and STRING-APPEND
|
||||
that are permitted to return results that share storage with their
|
||||
parameters. In particular, if STRING-APPEND/SHARED is applied to just
|
||||
one argument, it may return exactly that argument, whereas STRING-APPEND
|
||||
is required to allocate a fresh string.
|
||||
|
||||
string->list s [start end] -> char-list
|
||||
The R5RS STRING->LIST procedure is extended to take optional START/END
|
||||
arguments.
|
||||
|
||||
string-null? s -> bool
|
||||
Is S the empty string?
|
||||
|
||||
xsubstring s from [to start end] -> string
|
||||
This is the "extended substring" procedure that implements replicated
|
||||
copying of a substring of some string.
|
||||
|
||||
S is a string; START and END are optional arguments that demarcate
|
||||
a substring of S, defaulting to 0 and the length of S (e.g., the whole
|
||||
string). Replicate this substring up and down index space, in both the
|
||||
positive and negative directions. For example, if S = "abcdefg", START=3,
|
||||
and END=6, then we have the conceptual bidirectionally-infinite string
|
||||
... d e f d e f d e f d e f d e f d e f d e f ...
|
||||
... -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 ...
|
||||
XSUBSTRING returns the substring of this string beginning at index FROM,
|
||||
and ending at TO (which defaults to FROM+(END-START)).
|
||||
|
||||
You can use XSUBSTRING to perform a variety of tasks:
|
||||
- To rotate a string left: (xsubstring "abcdef" 2) => "cdefab"
|
||||
- To rotate a string right: (xsubstring "abcdef" -2) => "efabcd"
|
||||
- To replicate a string: (xsubstring "abc" 0 7) => "abcabca"
|
||||
|
||||
Note that
|
||||
- The FROM/TO indices give a half-open range -- the characters from
|
||||
index FROM up to, but not including, index TO.
|
||||
- The FROM/TO indices are not in terms of the index space for string S.
|
||||
They are in terms of the replicated index space of the substring
|
||||
defined by S, START, and END.
|
||||
|
||||
It is an error if START=END -- although this is allowed by special
|
||||
dispensation when FROM=TO.
|
||||
|
||||
string-xcopy! target tstart s sfrom [sto start end] -> unspecific
|
||||
Exactly the same as XSUBSTRING, but the extracted text is written
|
||||
into the string TARGET starting at index TSTART.
|
||||
This operation is not defined if (EQ? TARGET S) -- you cannot copy
|
||||
a string on top of itself.
|
||||
|
||||
|
||||
* Lower-level procedures
|
||||
|
||||
The following procedures are useful for writing other string-processing
|
||||
functions, and are contained in the string-lib-internals package.
|
||||
|
||||
parse-start+end proc s args -> [start end rest]
|
||||
parse-final-start+end proc s args -> [start end]
|
||||
PARSE-START+END may be used to parse a pair of optional START/END arguments
|
||||
from an argument list, defaulting them to 0 and the length of some string
|
||||
S, respectively. Let the length of string S be SLEN.
|
||||
- If ARGS = (), the function returns (values 0 slen '())
|
||||
- If ARGS = (i), I is checked to ensure it is an integer, and
|
||||
that 0 <= i <= slen. Returns (values i slen (cdr rest)).
|
||||
- If ARGS = (i j ...), I and J are checked to ensure they are
|
||||
integers, and that 0 <= i <= j <= slen. Returns (values i j (cddr rest)).
|
||||
If any of the checks fail, an error condition is raised, and PROC is used
|
||||
as part of the error condition -- it should be the name of the client
|
||||
procedure whose argument list PARSE-START+END is parsing.
|
||||
|
||||
parse-final-start+end is exactly the same, except that the args list
|
||||
passed to it is required to be of length two or less; if it is longer,
|
||||
an error condition is raised. It may be used when the optional START/END
|
||||
parameters are final arguments to the procedure.
|
||||
|
||||
check-substring-spec proc s start end -> unspecific
|
||||
Check values START and END to ensure they specify a valid substring
|
||||
in S. This means that START and END are exact integers, and
|
||||
0 <= START <= END <= (STRING-LENGTH S)
|
||||
If this is not the case, an error condition is raised. PROC is used
|
||||
as part of error condition, and should be the procedure whose START/END
|
||||
parameters we are checking.
|
||||
|
||||
make-kmp-restart-vector s c= -> vector
|
||||
Build the Knuth-Morris-Pratt "restart vector," which is useful
|
||||
for quickly searching character sequences for the occurrence of
|
||||
string S. C= is a character-equality function used to construct
|
||||
the restart vector; it is usefully CHAR=? or CHAR-CI=?.
|
||||
|
||||
The definition of the restart vector RV for string S is:
|
||||
If we have matched chars 0..i-1 of S against some search string SS, and
|
||||
S[i] doesn't match SS[k], then reset i := RV[i], and try again to
|
||||
match SS[k]. If RV[i] = -1, then punt SS[k] completely, and move on to
|
||||
SS[k+1] and S[0].
|
||||
|
||||
In other words, if you have matched the first i chars of S, but
|
||||
the i+1'th char doesn't match, RV[i] tells you what the next-longest
|
||||
prefix of PATTERN is that you have matched.
|
||||
|
||||
The following string-search function shows how a restart vector
|
||||
is used to search. It can be easily adapted to search other character
|
||||
sequences (such as ports).
|
||||
|
||||
(define (find-substring pattern source start end)
|
||||
(let ((plen (string-length pattern))
|
||||
(rv (make-kmp-restart-vector pattern char=?)))
|
||||
|
||||
;; The search loop. SJ & PJ are redundant state.
|
||||
(let lp ((si start) (pi 0)
|
||||
(sj (- end start)) ; (- end si) -- how many chars left.
|
||||
(pj plen)) ; (- plen pi) -- how many chars left.
|
||||
|
||||
(if (= pi plen) (- si plen) ; Win.
|
||||
|
||||
(and (<= pj sj) ; Lose.
|
||||
|
||||
(if (char=? (string-ref source si) ; Search.
|
||||
(string-ref pattern pi))
|
||||
(lp (+ 1 si) (+ 1 pi) (- sj 1) (- pj 1)) ; Advance.
|
||||
|
||||
(let ((pi (vector-ref rv pi))) ; Retreat.
|
||||
(if (= pi -1)
|
||||
(lp (+ si 1) 0 (- sj 1) plen) ; Punt.
|
||||
(lp si pi sj (- plen pi))))))))))
|
|
@ -80,9 +80,23 @@
|
|||
(set-socket-option sock level/socket socket/reuse-address #t)
|
||||
(bind-socket sock addr)
|
||||
(listen-socket sock 5)
|
||||
(let loop ()
|
||||
(call-with-values (lambda () (accept-connection sock)) proc)
|
||||
(loop))))
|
||||
(with-handler
|
||||
(lambda (condition more)
|
||||
(with-handler
|
||||
(lambda (condition ignore) (more))
|
||||
(lambda () (close-socket sock)))
|
||||
(more))
|
||||
(lambda ()
|
||||
(let loop ()
|
||||
(with-errno-handler
|
||||
;; ECONNABORTED we just ignore
|
||||
((errno packet)
|
||||
((errno/connaborted) (loop)))
|
||||
(call-with-values
|
||||
(lambda () (accept-connection sock))
|
||||
proc)
|
||||
(loop)))))))
|
||||
|
||||
|
||||
;;;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
;;; Socket Record Structure
|
||||
|
@ -407,8 +421,9 @@
|
|||
reader sockfd flags
|
||||
s start end from))
|
||||
(let ((addr (make-addr from)))
|
||||
(let loop ((i start))
|
||||
(if (>= i end) (- i start)
|
||||
(let loop ((i start) (remote #f))
|
||||
(if (>= i end)
|
||||
(values (- i start) remote)
|
||||
(receive (err nread)
|
||||
(reader sockfd flags s i end addr)
|
||||
(cond (err (if (= err errno/intr) (loop i)
|
||||
|
@ -421,7 +436,7 @@
|
|||
(let ((result (- i start)))
|
||||
(and (not (zero? result)) result))
|
||||
from))
|
||||
(else (loop (+ i nread)))))))))
|
||||
(else (loop (+ i nread) from))))))))
|
||||
|
||||
(define (receive-message/partial socket len . maybe-flags)
|
||||
(let ((flags (:optional maybe-flags 0)))
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
/* Make sure our exports match up w/the implementation: */
|
||||
#include "network1.h"
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
#if !defined(__CYGWIN__) && !defined(_AIX)
|
||||
extern int h_errno;
|
||||
#endif
|
||||
|
||||
|
@ -43,6 +43,8 @@ int scheme_bind(int sockfd, int family, scheme_value scheme_name)
|
|||
struct sockaddr_un name;
|
||||
int scheme_length=STRING_LENGTH(scheme_name);
|
||||
|
||||
memset(&name, 0, sizeof(name));
|
||||
|
||||
name.sun_family=AF_UNIX;
|
||||
if (scheme_length>=(108-1)) /* save space for \0 */
|
||||
return(-1);
|
||||
|
@ -60,6 +62,9 @@ int scheme_bind(int sockfd, int family, scheme_value scheme_name)
|
|||
|
||||
u_long addr=GET_LONG(scheme_name,0);
|
||||
u_short port=htons((u_short)ntohl(GET_LONG(scheme_name,1)));
|
||||
|
||||
memset(&name, 0, sizeof(name));
|
||||
|
||||
name.sin_family=AF_INET;
|
||||
name.sin_addr.s_addr=addr;
|
||||
name.sin_port=port;
|
||||
|
@ -82,6 +87,8 @@ int scheme_connect(int sockfd, int family, scheme_value scheme_name)
|
|||
struct sockaddr_un name;
|
||||
int scheme_length=STRING_LENGTH(scheme_name);
|
||||
|
||||
memset(&name, 0, sizeof(name));
|
||||
|
||||
name.sun_family=AF_UNIX;
|
||||
if (scheme_length>=(108-1)) /* save space for \0 */
|
||||
return(-1);
|
||||
|
@ -100,6 +107,8 @@ int scheme_connect(int sockfd, int family, scheme_value scheme_name)
|
|||
u_long addr=GET_LONG(scheme_name,0);
|
||||
u_short port=htons((u_short)ntohl(GET_LONG(scheme_name,1)));
|
||||
|
||||
memset(&name, 0, sizeof(name));
|
||||
|
||||
name.sin_family=AF_INET;
|
||||
name.sin_addr.s_addr=addr;
|
||||
name.sin_port=port;
|
||||
|
@ -270,6 +279,8 @@ int send_substring(int s,
|
|||
struct sockaddr_un name;
|
||||
int scheme_length=STRING_LENGTH(scheme_name);
|
||||
|
||||
memset(&name, 0, sizeof(name));
|
||||
|
||||
name.sun_family=AF_UNIX;
|
||||
if (scheme_length>=(108-1)) /* save space for \0 */
|
||||
return(-1);
|
||||
|
@ -289,6 +300,9 @@ int send_substring(int s,
|
|||
struct sockaddr_in name;
|
||||
u_long addr=GET_LONG(scheme_name,0);
|
||||
u_short port=htons((u_short)ntohl(GET_LONG(scheme_name,1)));
|
||||
|
||||
memset(&name, 0, sizeof(name));
|
||||
|
||||
name.sin_family=AF_INET;
|
||||
name.sin_addr.s_addr=addr;
|
||||
name.sin_port=port;
|
||||
|
|
|
@ -0,0 +1,568 @@
|
|||
;;; Field and record parsing utilities for scsh.
|
||||
;;; Copyright (c) 1994 by Olin Shivers.
|
||||
|
||||
;;; Notes:
|
||||
;;; - Comment on the dependencies here...
|
||||
;;; - Redefine READ-LINE using READ-DELIMITED.
|
||||
;;; - Awk should deal with case-insensitivity.
|
||||
;;; - Should I change the field-splitters to return lists? It's the
|
||||
;;; right thing, and costs nothing in terms of efficiency.
|
||||
|
||||
;;; Looping primitives:
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; It is nicer for loops that loop over a bunch of different things
|
||||
;;; if you can encapsulate the idea of iterating over a data structure
|
||||
;;; with a
|
||||
;;; (next-element state) -> elt next-state
|
||||
;;; (more-elements? state) -? #t/#f
|
||||
;;; generator/termination-test pair. You can use the generator with REDUCE
|
||||
;;; to make a list; you can stick it into a loop macro to loop over the
|
||||
;;; elements. For example, if we had an extensible Yale-loop style loop macro,
|
||||
;;; we could have a loop clause like
|
||||
;;;
|
||||
;;; (loop (for field in-infix-delimited-string ":" path)
|
||||
;;; (do (display field) (newline)))
|
||||
;;;
|
||||
;;; and it would be simple to expand this into code using the generator.
|
||||
;;; With procedural inlining, you can get pretty optimal loops over data
|
||||
;;; structures this way.
|
||||
;;;
|
||||
;;; As of now, you are forced to parse fields into a buffer, and loop
|
||||
;;; over that. This is inefficient of time and space. If I ever manage to do
|
||||
;;; an extensible loop macro for Scheme 48, I'll have to come back to this
|
||||
;;; package and rethink how to provide this functionality.
|
||||
|
||||
;;; Forward-progress guarantees and empty string matches.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; A loop that pulls text off a string by matching a regexp against
|
||||
;;; that string can conceivably get stuck in an infinite loop if the
|
||||
;;; regexp matches the empty string. For example, the regexps
|
||||
;;; ^, $, .*, foo|[^f]* can all match the empty string.
|
||||
;;;
|
||||
;;; The regexp-loop routines in this code are careful to handle this case.
|
||||
;;; If a regexp matches the empty string, the next search starts, not from
|
||||
;;; the end of the match (which in the empty string case is also the
|
||||
;;; beginning -- there's the rub), but from the next character over.
|
||||
;;; This is the correct behaviour. Regexps match the longest possible
|
||||
;;; string at a given location, so if the regexp matched the empty string
|
||||
;;; at location i, then it is guaranteed they could not have matched
|
||||
;;; a longer pattern starting with character #i. So we can safely begin
|
||||
;;; our search for the next match at char i+1.
|
||||
;;;
|
||||
;;; So every iteration through the loop makes some forward progress,
|
||||
;;; and the loop is guaranteed to terminate.
|
||||
;;;
|
||||
;;; This has the effect you want with field parsing. For example, if you split
|
||||
;;; a string with the empty pattern, you will explode the string into its
|
||||
;;; individual characters:
|
||||
;;; ((suffix-splitter "") "foo") -> #("" "f" "o" "o")
|
||||
;;; However, even though this boundary case is handled correctly, we don't
|
||||
;;; recommend using it. Say what you mean -- just use a field splitter:
|
||||
;;; ((field-splitter ".") "foo") -> #("f" "o" "o")
|
||||
|
||||
|
||||
|
||||
;;; (join-strings string-list [delimiter grammar]) => string
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; Paste strings together using the delimiter string.
|
||||
;;;
|
||||
;;; (join-strings '("foo" "bar" "baz") ":") => "foo:bar:baz"
|
||||
;;;
|
||||
;;; DELIMITER defaults to a single space " "
|
||||
;;; GRAMMAR is one of the symbols {infix, suffix} and defaults to 'infix.
|
||||
|
||||
;;; (join-strings strings [delim grammar])
|
||||
|
||||
(define (join-strings strings . args)
|
||||
(if (pair? strings)
|
||||
(receive (delim grammar) (parse-optionals args " " 'infix)
|
||||
(check-arg string? delim join-strings)
|
||||
(let ((strings (reverse strings)))
|
||||
(let lp ((strings (cdr strings))
|
||||
(ans (case grammar
|
||||
((infix) (list (car strings)))
|
||||
((suffix) (list (car strings) delim))
|
||||
(else (error "Illegal grammar" grammar)))))
|
||||
(if (pair? strings)
|
||||
(lp (cdr strings)
|
||||
(cons (car strings) (cons delim ans)))
|
||||
|
||||
; All done
|
||||
(apply string-append ans)))))
|
||||
|
||||
"")) ; Special-cased for infix grammar.
|
||||
|
||||
;;; FIELD PARSERS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; This section defines routines to split a string into fields.
|
||||
;;; You can parse by specifying a pattern that *separates* fields,
|
||||
;;; a pattern that *terminates* fields, or a pattern that *matches*
|
||||
;;; fields.
|
||||
|
||||
(define (->delim-matcher x)
|
||||
(if (procedure? x) x ; matcher proc
|
||||
(let ((re (cond ((regexp? x) x) ; regexp pattern
|
||||
((string? x) (make-regexp x)) ; regexp string
|
||||
(else (error "Illegal pattern/parser" x)))))
|
||||
|
||||
;; The matcher proc.
|
||||
(lambda (s i)
|
||||
(cond ((regexp-exec re s i) =>
|
||||
(lambda (m) (values (match:start m 0) (match:end m 0))))
|
||||
(else (values #f #f)))))))
|
||||
|
||||
;;; (infix-splitter [re num-fields handle-delim]) -> parser
|
||||
;;; (suffix-splitter [re num-fields handle-delim]) -> parser
|
||||
;;; (sloppy-suffix-splitter [re num-fields handle-delim]) -> parser
|
||||
;;; (field-splitter [re num-fields]) -> parser
|
||||
;;;
|
||||
;;; (parser string [start]) -> string-list
|
||||
|
||||
(define (make-field-parser-generator default-delim-matcher loop-proc)
|
||||
;; This is the parser-generator
|
||||
(lambda args
|
||||
(receive (delim-spec num-fields handle-delim)
|
||||
(parse-optionals args default-delim-matcher #f 'trim)
|
||||
|
||||
;; Process and error-check the args
|
||||
(let ((match-delim (->delim-matcher delim-spec))
|
||||
(cons-field (case handle-delim ; Field is s[i,j).
|
||||
((trim) ; Delimiter is s[j,k).
|
||||
(lambda (s i j k fields)
|
||||
(cons (substring s i j) fields)))
|
||||
((split)
|
||||
(lambda (s i j k fields)
|
||||
(cons (substring s j k)
|
||||
(cons (substring s i j) fields))))
|
||||
((concat)
|
||||
(lambda (s i j k fields)
|
||||
(cons (substring s i k)
|
||||
fields)))
|
||||
(else
|
||||
(error "Illegal handle-delim spec"
|
||||
handle-delim)))))
|
||||
|
||||
(receive (num-fields nfields-exact?)
|
||||
(cond ((not num-fields) (values #f #f))
|
||||
((not (integer? num-fields))
|
||||
(error "Illegal NUM-FIELDS value" num-fields))
|
||||
((<= num-fields 0) (values (- num-fields) #f))
|
||||
(else (values num-fields #t)))
|
||||
|
||||
;; This is the parser.
|
||||
(lambda (s . maybe-start)
|
||||
(reverse (loop-proc s (optional-arg maybe-start 0)
|
||||
match-delim cons-field
|
||||
num-fields nfields-exact?))))))))
|
||||
|
||||
(define default-field-matcher (->delim-matcher "[^ \t\n]+"))
|
||||
|
||||
;;; (field-splitter [field-spec num-fields])
|
||||
|
||||
(define (field-splitter . args)
|
||||
(receive (field-spec num-fields)
|
||||
(parse-optionals args default-field-matcher #f)
|
||||
|
||||
;; Process and error-check the args
|
||||
(let ((match-field (->delim-matcher field-spec)))
|
||||
(receive (num-fields nfields-exact?)
|
||||
(cond ((not num-fields) (values #f #f))
|
||||
((not (integer? num-fields))
|
||||
(error "Illegal NUM-FIELDS value"
|
||||
field-splitter num-fields))
|
||||
((<= num-fields 0) (values (- num-fields) #f))
|
||||
(else (values num-fields #t)))
|
||||
|
||||
;; This is the parser procedure.
|
||||
(lambda (s . maybe-start)
|
||||
(reverse (fieldspec-field-loop s (optional-arg maybe-start 0)
|
||||
match-field num-fields nfields-exact?)))))))
|
||||
|
||||
|
||||
;;; These four procedures implement the guts of each parser
|
||||
;;; (field, infix, suffix, and sloppy-suffix).
|
||||
;;;
|
||||
;;; The CONS-FIELD argument is a procedure that parameterises the
|
||||
;;; HANDLE-DELIM action for the field parser.
|
||||
;;;
|
||||
;;; The MATCH-DELIM argument is used to match a delimiter.
|
||||
;;; (MATCH-DELIM S I) returns two integers [start, end] marking
|
||||
;;; the next delimiter after index I in string S. If no delimiter is
|
||||
;;; found, it returns [#f #f].
|
||||
|
||||
;;; In the main loop of each parser, the loop variable LAST-NULL? tells if the
|
||||
;;; previous delimiter-match matched the empty string. If it did, we start our
|
||||
;;; next delimiter search one character to the right of the match, so we won't
|
||||
;;; loop forever. This means that an empty delimiter regexp "" simply splits
|
||||
;;; the string at each character, which is the correct thing to do.
|
||||
;;;
|
||||
;;; These routines return the answer as a reversed list.
|
||||
|
||||
|
||||
(define (fieldspec-field-loop s start match-field num-fields nfields-exact?)
|
||||
(let ((end (string-length s)))
|
||||
(let lp ((i start) (nfields 0) (fields '()) (last-null? #f))
|
||||
(let ((j (if last-null? (+ i 1) i)) ; Where to start next delim search.
|
||||
|
||||
;; Check to see if we made our quota before returning answer.
|
||||
(finish-up (lambda ()
|
||||
(if (and num-fields (< nfields num-fields))
|
||||
(error "Too few fields in record." num-fields s)
|
||||
fields))))
|
||||
|
||||
(cond ((> j end) (finish-up)) ; We are done. Finish up.
|
||||
|
||||
;; Read too many fields. Bomb out.
|
||||
((and nfields-exact? (> nfields num-fields))
|
||||
(error "Too many fields in record." num-fields s))
|
||||
|
||||
;; Made our lower-bound quota. Quit early.
|
||||
((and num-fields (= nfields num-fields) (not nfields-exact?))
|
||||
(if (= i end) fields ; Special case hackery.
|
||||
(cons (substring s i end) fields)))
|
||||
|
||||
;; Match off another field & loop.
|
||||
(else (receive (m0 m1) (match-field s j)
|
||||
(if m0 (lp m1 (+ nfields 1)
|
||||
(cons (substring s m0 m1) fields)
|
||||
(= m0 m1))
|
||||
(finish-up))))))))) ; No more matches. Finish up.
|
||||
|
||||
|
||||
(define (infix-field-loop s start match-delim cons-field
|
||||
num-fields nfields-exact?)
|
||||
(let ((end (string-length s)))
|
||||
(if (= start end) '() ; Specially hack empty string.
|
||||
|
||||
(let lp ((i start) (nfields 0) (fields '()) (last-null? #f))
|
||||
(let ((finish-up (lambda ()
|
||||
;; s[i,end) is the last field. Terminate the loop.
|
||||
(cond ((and num-fields (< (+ nfields 1) num-fields))
|
||||
(error "Too few fields in record."
|
||||
num-fields s))
|
||||
|
||||
((and nfields-exact?
|
||||
(>= nfields num-fields))
|
||||
(error "Too many fields in record."
|
||||
num-fields s))
|
||||
|
||||
(else
|
||||
(cons (substring s i end) fields)))))
|
||||
|
||||
(j (if last-null? (+ i 1) i))) ; Where to start next search.
|
||||
|
||||
(cond
|
||||
;; If we've read NUM-FIELDS fields, quit early .
|
||||
((and num-fields (= nfields num-fields))
|
||||
(if nfields-exact?
|
||||
(error "Too many fields in record." num-fields s)
|
||||
(cons (substring s i end) fields)))
|
||||
|
||||
|
||||
((<= j end) ; Match off another field.
|
||||
(receive (m0 m1) (match-delim s j)
|
||||
(if m0
|
||||
(lp m1 (+ nfields 1)
|
||||
(cons-field s i m0 m1 fields)
|
||||
(= m0 m1))
|
||||
(finish-up)))) ; No more delimiters - finish up.
|
||||
|
||||
;; We've run off the end of the string. This is a weird
|
||||
;; boundary case occuring with empty-string delimiters.
|
||||
(else (finish-up))))))))
|
||||
|
||||
|
||||
|
||||
;;; Match off an optional initial delimiter,
|
||||
;;; then jump off to the suffix parser.
|
||||
|
||||
(define (sloppy-suffix-field-loop s start match-delim cons-field
|
||||
num-fields nfields-exact?)
|
||||
;; If sloppy-suffix, skip an initial delimiter if it's there.
|
||||
(let ((start (receive (i j) (match-delim s start)
|
||||
(if (and i (zero? i)) j start))))
|
||||
(suffix-field-loop s start match-delim cons-field
|
||||
num-fields nfields-exact?)))
|
||||
|
||||
|
||||
(define (suffix-field-loop s start match-delim cons-field
|
||||
num-fields nfields-exact?)
|
||||
(let ((end (string-length s)))
|
||||
|
||||
(let lp ((i start) (nfields 0) (fields '()) (last-null? #f))
|
||||
(let ((j (if last-null? (+ i 1) i))) ; Where to start next delim search.
|
||||
(cond ((= i end) ; We are done.
|
||||
(if (and num-fields (< nfields num-fields)) ; Didn't make quota.
|
||||
(error "Too few fields in record." num-fields s)
|
||||
fields))
|
||||
|
||||
;; Read too many fields. Bomb out.
|
||||
((and nfields-exact? (= nfields num-fields))
|
||||
(error "Too many fields in record." num-fields s))
|
||||
|
||||
;; Made our lower-bound quota. Quit early.
|
||||
((and num-fields (= nfields num-fields) (not nfields-exact?))
|
||||
(cons (substring s i end) fields))
|
||||
|
||||
(else ; Match off another field.
|
||||
(receive (m0 m1) (match-delim s j)
|
||||
(if m0 (lp m1 (+ nfields 1)
|
||||
(cons-field s i m0 m1 fields)
|
||||
(= m0 m1))
|
||||
(error "Missing field terminator" s)))))))))
|
||||
|
||||
|
||||
;;; Now, build the exported procedures: {infix,suffix,sloppy-suffix}-splitter.
|
||||
|
||||
(define default-suffix-matcher (->delim-matcher "[ \t\n]+|$"))
|
||||
(define default-infix-matcher (->delim-matcher "[ \t\n]+"))
|
||||
|
||||
(define infix-splitter
|
||||
(make-field-parser-generator default-infix-matcher infix-field-loop))
|
||||
(define suffix-splitter
|
||||
(make-field-parser-generator default-suffix-matcher suffix-field-loop))
|
||||
(define sloppy-suffix-splitter
|
||||
(make-field-parser-generator default-suffix-matcher sloppy-suffix-field-loop))
|
||||
|
||||
|
||||
|
||||
;;; Delimited readers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; We repeatedly allocate a buffer and fill it with READ-DELIMITED!
|
||||
;;; until we hit a delimiter or EOF. Each time through the loop, we
|
||||
;;; double the total buffer space, so the loop terminates with a log
|
||||
;;; number of reads, but uses at most double the optimal buffer space.
|
||||
|
||||
(define (read-delimited delims . maybe-port)
|
||||
(let ((smart-substring (lambda (s end)
|
||||
(if (= end (string-length s)) s
|
||||
(substring s 0 end))))
|
||||
(delims (->char-set delims)))
|
||||
|
||||
;; BUFLEN is total amount of buffer space allocated to date.
|
||||
(let lp ((strs '()) (buflen 80) (buf (make-string 80)))
|
||||
(cond ((apply read-delimited! delims buf maybe-port) =>
|
||||
(lambda (i)
|
||||
(if (null? strs) ; Gratuitous optimisation.
|
||||
(smart-substring buf i)
|
||||
(apply string-append
|
||||
(reverse (if (eof-object? i)
|
||||
strs
|
||||
(cons (smart-substring buf i)
|
||||
strs)))))))
|
||||
|
||||
(else (lp (cons buf strs)
|
||||
(+ buflen buflen)
|
||||
(make-string buflen)))))))
|
||||
|
||||
|
||||
;;; (read-delimited! delims buf [port start end])
|
||||
|
||||
(define (read-delimited! delims buf . args) ; [port start end]
|
||||
(receive (port start end)
|
||||
(parse-optionals args (current-input-port) 0 (string-length buf))
|
||||
(check-arg input-port? port read-delimited!)
|
||||
(let ((delims (->char-set delims)))
|
||||
; (if (fd-inport? port) ; ???
|
||||
;
|
||||
; ;; Handle fdports in C code for speed.
|
||||
; (receive (err val)
|
||||
; (%read-delimited-fdport!/errno delims buf port start end)
|
||||
; (if err
|
||||
; (errno-error err read-delimited!)
|
||||
; val))
|
||||
|
||||
;; This is the code for other kinds of ports.
|
||||
(let lp ((i start))
|
||||
(and (< i end)
|
||||
(let ((c (peek-char port)))
|
||||
(if (or (eof-object? c)
|
||||
(char-set-contains? delims c))
|
||||
(- i start)
|
||||
(begin (string-set! buf i (read-char port))
|
||||
(lp (+ i 1))))))))))
|
||||
;)
|
||||
|
||||
;(define-foreign %read-delimited-fdport!/errno (read_delim (string-desc delims)
|
||||
; (string-desc buf)
|
||||
; (desc port) ;???
|
||||
; (fixnum start)
|
||||
; (fixnum end))
|
||||
; desc ; errno or #f
|
||||
; desc) ; nread or #f or eof-object
|
||||
|
||||
(define (skip-char-set cset . maybe-port)
|
||||
(let ((port (optional-arg maybe-port (current-input-port))))
|
||||
(let lp ()
|
||||
(let ((c (peek-char port)))
|
||||
(cond ((and (char? c) (char-set-contains? cset c))
|
||||
(read-char port)
|
||||
(lp))
|
||||
(else c))))))
|
||||
|
||||
|
||||
|
||||
;;; Reading records
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define default-record-delims (char-set #\newline))
|
||||
|
||||
;;; (record-reader [delims elide? handle-delim]) -> reader
|
||||
;;; (reader [port]) -> string or eof
|
||||
|
||||
(define (record-reader . args)
|
||||
(receive (delims elide? handle-delim)
|
||||
(parse-optionals args default-record-delims #f 'trim)
|
||||
(let ((delims (->char-set delims)))
|
||||
|
||||
(case handle-delim
|
||||
((trim) ; TRIM-delimiter reader.
|
||||
(lambda maybe-port
|
||||
(let ((s (apply read-delimited delims maybe-port)))
|
||||
(if (not (eof-object? s))
|
||||
(if elide?
|
||||
(apply skip-char-set delims maybe-port) ; Snarf delims.
|
||||
(apply read-char maybe-port))) ; Just snarf one.
|
||||
s)))
|
||||
|
||||
((concat split) ; CONCAT-delimiter & SPLIT-delimiter reader.
|
||||
(let ((not-delims (char-set-invert delims)))
|
||||
(lambda maybe-port
|
||||
(let ((s (apply read-delimited delims maybe-port)))
|
||||
(if (eof-object? s) s
|
||||
(let ((delim (if elide?
|
||||
(apply read-delimited not-delims maybe-port)
|
||||
(string (apply read-char maybe-port)))))
|
||||
(if (eq? handle-delim 'split)
|
||||
(values s delim)
|
||||
(if (eof-object? delim) s
|
||||
(string-append s delim)))))))))
|
||||
|
||||
(else
|
||||
(error "Illegal delimiter-action" handle-delim))))))
|
||||
|
||||
|
||||
;;; {string, char, char-set, char predicate} -> char-set
|
||||
|
||||
(define (->char-set x)
|
||||
(cond ((char-set? x) x)
|
||||
((string? x) (string->char-set x))
|
||||
((char? x) (char-set x))
|
||||
((procedure? x) (predicate->char-set x))
|
||||
(else (error "->char-set: Not a charset, string, char, or predicate."
|
||||
x))))
|
||||
|
||||
|
||||
|
||||
(define blank-line-regexp (make-regexp "^[ \t]*\n$"))
|
||||
|
||||
;;; (read-paragraph [port])
|
||||
(define (read-paragraph . maybe-port)
|
||||
(let ((port (optional-arg maybe-port (current-input-port))))
|
||||
|
||||
;; First, skip all blank lines.
|
||||
(let lp ()
|
||||
(let ((line (read-line port #t)))
|
||||
(cond ((eof-object? line) line)
|
||||
((regexp-exec blank-line-regexp line) (lp))
|
||||
|
||||
;; Then, read in non-blank lines.
|
||||
(else (let ((lines (let lp ((lines (list line)))
|
||||
(let ((line (read-line port #t)))
|
||||
(cond ((or (eof-object? line)
|
||||
(regexp-exec blank-line-regexp
|
||||
line))
|
||||
lines)
|
||||
(else (lp (cons line lines))))))))
|
||||
|
||||
;; Return the paragraph
|
||||
(apply string-append (reverse lines)))))))))
|
||||
|
||||
;;; Reading and parsing records
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; (field-reader [field-parser rec-reader]) -> reader
|
||||
;;; (reader [port]) -> [raw-record parsed-record] or [eof #()]
|
||||
;;;
|
||||
;;; This is the field reader, which is basically just a composition of
|
||||
;;; RECORD-READER and FIELD-PARSER.
|
||||
|
||||
(define default-field-parser (field-splitter))
|
||||
|
||||
(define (field-reader . args)
|
||||
(receive (parser rec-reader)
|
||||
(parse-optionals args default-field-parser read-line)
|
||||
(lambda maybe-port
|
||||
(let ((record (apply rec-reader maybe-port)))
|
||||
(if (eof-object? record)
|
||||
(values record '#())
|
||||
(values record (parser record)))))))
|
||||
|
||||
|
||||
|
||||
;;; Parse fields by regexp
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;; This code parses up a record into fields by matching a regexp specifying
|
||||
;;; the field against the record. The regexp describes the *field*. In the
|
||||
;;; other routines, the regexp describes the *delimiters*. They are
|
||||
;;; complimentary.
|
||||
|
||||
;;; Repeatedly do (APPLY PROC M STATE) to generate new state values,
|
||||
;;; where M is a regexp match structure made from matching against STRING.
|
||||
|
||||
;(define (regexp-reduce string start regexp proc . state)
|
||||
; (let ((end (string-length string))
|
||||
; (regexp (if (string? regexp)
|
||||
; (make-regexp regexp)
|
||||
; regexp)))
|
||||
;
|
||||
; (let lp ((i start) (state state) (last-null? #f))
|
||||
; (let ((j (if last-null? (+ i 1) i)))
|
||||
; (cond ((and (<= j end) (regexp-exec regexp string j)) =>
|
||||
; (lambda (m)
|
||||
; (receive state (apply proc m state)
|
||||
; (lp (match:end m) state (= (match:start m) (match:end m))))))
|
||||
; (else (apply values state)))))))
|
||||
;
|
||||
;(define (all-regexp-matches regexp string)
|
||||
; (reverse (regexp-reduce string 0 regexp
|
||||
; (lambda (m ans) (cons (match:substring m 0) ans))
|
||||
; '())))
|
||||
|
||||
;;; Previously in newports.scm
|
||||
|
||||
;;; Read in a line of data. Input is terminated by either a newline or EOF.
|
||||
;;; The newline is trimmed from the string.
|
||||
|
||||
(define (read-line . rest)
|
||||
(let ((port (if (null? rest) (current-input-port) (car rest))) ; Optional arg
|
||||
(retain-newline? (and (not (null? rest)) ; parsing.
|
||||
(not (null? (cdr rest)))
|
||||
(cadr rest)))
|
||||
|
||||
;; S[I] := C. If this overflows S, grow it.
|
||||
(deposit (lambda (s i c)
|
||||
(let ((s (if (< i (string-length s)) s
|
||||
(string-append s s)))) ; doubling hack
|
||||
(string-set! s i c)
|
||||
s)))
|
||||
|
||||
;; Precisely resize S to size NUMCHARS.
|
||||
(trim (lambda (s numchars)
|
||||
(if (= numchars (string-length s)) s
|
||||
(substring s 0 numchars)))))
|
||||
|
||||
(let lp ((s (make-string 81)) (numchars 0))
|
||||
(let ((c (read-char port)))
|
||||
(cond ((eof-object? c)
|
||||
(if (zero? numchars) c
|
||||
(trim s numchars)))
|
||||
|
||||
((char=? c #\newline)
|
||||
(if retain-newline?
|
||||
(trim (deposit s numchars c)
|
||||
(+ numchars 1))
|
||||
(trim s numchars)))
|
||||
|
||||
(else (lp (deposit s numchars c)
|
||||
(+ numchars 1))))))))
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
;;; Here documents in Scheme for scsh scripts.
|
||||
;;; These are like "here documents" for sh and csh shell scripts
|
||||
;;; (i.e., the <<EOF redirection).
|
||||
;;; Copyright (c) 1995 by Olin Shivers.
|
||||
|
||||
;;; #<EOF
|
||||
;;; Hello, there.
|
||||
;;; This is read by Scheme as a string,
|
||||
;;; terminated by the first occurrence
|
||||
;;; of newline-E-O-F.
|
||||
;;; EOF
|
||||
|
||||
;;; Thus,
|
||||
;;; #<foo
|
||||
;;; Hello, world.
|
||||
;;; foo
|
||||
;;; is the same thing as
|
||||
;;; "Hello, world."
|
||||
|
||||
;;; These are useful for writing down long, constant strings -- such
|
||||
;;; as long, multi-line FORMAT strings, or arguments to Unix programs, e.g.
|
||||
;;; ;; Free up some disk space for my netnews files.
|
||||
;;; (run (csh -c #<EOF
|
||||
;;; cd ~bdc
|
||||
;;; rm -rf .
|
||||
;;; echo All done.
|
||||
;;;
|
||||
;;; EOF))
|
||||
|
||||
;;; The syntax is as follows: the three characters "#<" introduce the
|
||||
;;; here-string. The characters between the second "<" and the next newline
|
||||
;;; are the *delimiter word." *All* chars between the second "<" and the next
|
||||
;;; newline comprise the delimiter word -- including any white space. The
|
||||
;;; newline char separates the delimiter word from the body of the string. The
|
||||
;;; string body is terminated by a newline followed by the delimiter string.
|
||||
;;; Absolutely *no* interpretation is done on the input string, except for
|
||||
;;; scanning for the terminating delimiter word. Control chars, white space,
|
||||
;;; quotes, backslash chars -- everything is copied as-is.
|
||||
;;;
|
||||
;;; If EOF is encountered before reading the end of the here string, an
|
||||
;;; error is signalled.
|
||||
|
||||
(define (read-here-string port)
|
||||
;; First, read in the delimiter.
|
||||
(let ((delim (read-line port)))
|
||||
(cond ((eof-object? delim)
|
||||
(reading-error port "EOF while reading #< here-string delimiter."))
|
||||
((zero? (string-length delim))
|
||||
(reading-error port "#< here-string empty delimiter"))
|
||||
|
||||
;; This loop works as follows. We enter the loop after having
|
||||
;; read a newline. We scan into the text until we discover
|
||||
;; delimiter match/no-match. If match, we exit the loop;
|
||||
;; if no match, we read in the rest of the line and iterate.
|
||||
;; TEXT is the text we've read so far -- a list of strings in
|
||||
;; reverse order.
|
||||
(else
|
||||
(let lp ((text '()))
|
||||
(cond ((delimiter-scan delim port) =>
|
||||
(lambda (line-start)
|
||||
(let ((text (cons line-start text))
|
||||
(ls-len (string-length line-start)))
|
||||
(lp (if (char=? #\newline (string-ref line-start
|
||||
(- ls-len 1)))
|
||||
text
|
||||
(let ((line-rest (read-line port 'concat)))
|
||||
(if (eof-object? line-rest)
|
||||
(reading-error port
|
||||
"EOF while reading #< here-string.")
|
||||
(cons line-rest text))))))))
|
||||
|
||||
;; We're done. The last line, tho, needs its newline
|
||||
;; stripped off.
|
||||
((null? text) "")
|
||||
(else (let* ((last-chunk (car text))
|
||||
(lc-len (string-length last-chunk))
|
||||
(last-chunk (substring last-chunk 0 (- lc-len 1)))
|
||||
(text (cons last-chunk (cdr text))))
|
||||
(make-immutable! (apply string-append
|
||||
(reverse text)))))))))))
|
||||
|
||||
|
||||
;;; If the next chars read from PORT match DELIM, return false.
|
||||
;;; Otherwise, return the string you read from PORT to determine the non-match.
|
||||
;;; If EOF is encountered, report an error.
|
||||
|
||||
(define (delimiter-scan delim port)
|
||||
(let ((len (string-length delim)))
|
||||
(let lp ((i 0))
|
||||
(and (< i len)
|
||||
(let ((c (read-char port)))
|
||||
(cond ((eof-object? c)
|
||||
(reading-error port "EOF while reading #< here string."))
|
||||
((char=? c (string-ref delim i))
|
||||
(lp (+ i 1)))
|
||||
(else (string-append (substring delim 0 i)
|
||||
(string c)))))))))
|
||||
|
||||
;(define-sharp-macro #\<
|
||||
; (lambda (c port) (read-here-string port)))
|
|
@ -301,7 +301,7 @@
|
|||
(cons wptr result)
|
||||
result)))
|
||||
'()
|
||||
list))
|
||||
lis))
|
||||
|
||||
;;; Add a newly-reaped proc to the list.
|
||||
(define (add-reaped-proc! pid status)
|
||||
|
|
|
@ -150,12 +150,12 @@
|
|||
&opt (proc (:exact-integer :value) :value)
|
||||
:exact-integer)
|
||||
:value))
|
||||
(regexp-fold (proc (:value (proc (:value :exact-integer :value) :value)
|
||||
:value
|
||||
:string
|
||||
&opt (proc (:exact-integer :value) :value)
|
||||
:exact-integer)
|
||||
:value))
|
||||
(regexp-fold-right (proc (:value (proc (:value :exact-integer :value) :value)
|
||||
:value
|
||||
:string
|
||||
&opt (proc (:exact-integer :value) :value)
|
||||
:exact-integer)
|
||||
:value))
|
||||
(regexp-for-each (proc (:value (proc (:value) :unspecific)
|
||||
:string &opt :exact-integer)
|
||||
:unspecific))))
|
||||
|
@ -164,9 +164,9 @@
|
|||
(compound-interface posix-re-interface
|
||||
basic-re-interface
|
||||
(export (regexp-match? (proc (:value) :boolean))
|
||||
(match:start (proc (:value :exact-integer) :value))
|
||||
(match:end (proc (:value :exact-integer) :value))
|
||||
(match:substring (proc (:value :exact-integer) :value))
|
||||
(match:start (proc (:value &opt :exact-integer) :value))
|
||||
(match:end (proc (:value &opt :exact-integer) :value))
|
||||
(match:substring (proc (:value &opt :exact-integer) :value))
|
||||
(clean-up-cres (proc () :unspecific))
|
||||
(regexp-search (proc (:value :string &opt :exact-integer)
|
||||
:value))
|
||||
|
|
|
@ -162,138 +162,149 @@
|
|||
((c sre %word) (non-cset) re-word)
|
||||
|
||||
((pair? sre)
|
||||
(case (car sre)
|
||||
((*) (non-cset) (re-repeat 0 #f (parse-seq (cdr sre))))
|
||||
((+) (non-cset) (re-repeat 1 #f (parse-seq (cdr sre))))
|
||||
((?) (non-cset) (re-repeat 0 1 (parse-seq (cdr sre))))
|
||||
((=) (non-cset) (let ((n (cadr sre)))
|
||||
(re-repeat n n (parse-seq (cddr sre)))))
|
||||
((>=) (non-cset) (re-repeat (cadr sre) #f (parse-seq (cddr sre))))
|
||||
((**) (non-cset) (re-repeat (cadr sre) (caddr sre)
|
||||
(parse-seq (cdddr sre))))
|
||||
(let ((hygn-eq? (lambda (the-sym) (c (car sre) (r the-sym)))))
|
||||
(cond
|
||||
((hygn-eq? '*) (non-cset) (re-repeat 0 #f (parse-seq (cdr sre))))
|
||||
((hygn-eq? '+) (non-cset) (re-repeat 1 #f (parse-seq (cdr sre))))
|
||||
((hygn-eq? '?) (non-cset) (re-repeat 0 1 (parse-seq (cdr sre))))
|
||||
((hygn-eq? '=) (non-cset) (let ((n (cadr sre)))
|
||||
(re-repeat n n (parse-seq (cddr sre)))))
|
||||
((hygn-eq? '>=) (non-cset) (re-repeat (cadr sre) #f (parse-seq (cddr sre))))
|
||||
((hygn-eq? '**) (non-cset) (re-repeat (cadr sre) (caddr sre)
|
||||
(parse-seq (cdddr sre))))
|
||||
|
||||
;; Choice is special wrt cset? because it's "polymorphic".
|
||||
;; Note that RE-CHOICE guarantees to construct a char-set
|
||||
;; or single-char string regexp if all of its args are char
|
||||
;; classes.
|
||||
((| or) (let ((elts (map (lambda (sre)
|
||||
(recur sre case-sensitive? cset?))
|
||||
(cdr sre))))
|
||||
(if cset?
|
||||
(assoc-cset-op char-set-union 'char-set-union elts r)
|
||||
(re-choice elts))))
|
||||
;; Choice is special wrt cset? because it's "polymorphic".
|
||||
;; Note that RE-CHOICE guarantees to construct a char-set
|
||||
;; or single-char string regexp if all of its args are char
|
||||
;; classes.
|
||||
((or (hygn-eq? '|)
|
||||
(hygn-eq? 'or))
|
||||
(let ((elts (map (lambda (sre)
|
||||
(recur sre case-sensitive? cset?))
|
||||
(cdr sre))))
|
||||
(if cset?
|
||||
(assoc-cset-op char-set-union 'char-set-union elts r)
|
||||
(re-choice elts))))
|
||||
|
||||
((: seq) (non-cset) (parse-seq (cdr sre)))
|
||||
((or (hygn-eq? ':)
|
||||
(hygn-eq? 'seq))
|
||||
(non-cset) (parse-seq (cdr sre)))
|
||||
|
||||
((word) (non-cset) (parse-seq `(,%bow ,@(cdr sre) ,%eow)))
|
||||
((word+)
|
||||
(recur `(,(r 'word) (,(r '+) (,(r '&) (,(r '|) ,(r 'alphanum) "_")
|
||||
(,(r '|) . ,(cdr sre)))))
|
||||
case-sensitive?
|
||||
cset?))
|
||||
((hygn-eq? 'word) (non-cset) (parse-seq `(,%bow ,@(cdr sre) ,%eow)))
|
||||
((hygn-eq? 'word+)
|
||||
(recur `(,(r 'word) (,(r '+) (,(r '&) (,(r '|) ,(r 'alphanum) "_")
|
||||
(,(r '|) . ,(cdr sre)))))
|
||||
case-sensitive?
|
||||
cset?))
|
||||
|
||||
((submatch) (non-cset) (re-submatch (parse-seq (cdr sre))))
|
||||
((dsm) (non-cset) (re-dsm (parse-seq (cdddr sre))
|
||||
(cadr sre)
|
||||
(caddr sre)))
|
||||
((hygn-eq? 'submatch) (non-cset) (re-submatch (parse-seq (cdr sre))))
|
||||
((hygn-eq? 'dsm) (non-cset) (re-dsm (parse-seq (cdddr sre))
|
||||
(cadr sre)
|
||||
(caddr sre)))
|
||||
|
||||
;; We could be more aggressive and push the uncase op down into
|
||||
;; partially-static regexps, but enough is enough.
|
||||
((uncase)
|
||||
(let ((re-or-cset (parse-seq (cdr sre)))) ; Depending on CSET?.
|
||||
(if cset?
|
||||
;; We could be more aggressive and push the uncase op down into
|
||||
;; partially-static regexps, but enough is enough.
|
||||
((hygn-eq? 'uncase)
|
||||
(let ((re-or-cset (parse-seq (cdr sre)))) ; Depending on CSET?.
|
||||
(if cset?
|
||||
|
||||
(if (re-char-set? re-or-cset) ; A char set or code
|
||||
(uncase-char-set re-or-cset) ; producing a char set.
|
||||
`(,(r 'uncase) ,re-or-cset))
|
||||
(if (re-char-set? re-or-cset) ; A char set or code
|
||||
(uncase-char-set re-or-cset) ; producing a char set.
|
||||
`(,(r 'uncase) ,re-or-cset))
|
||||
|
||||
(if (static-regexp? re-or-cset) ; A regexp or code
|
||||
(uncase re-or-cset) ; producing a regexp.
|
||||
`(,(r 'uncase)
|
||||
,(regexp->scheme (simplify-regexp re-or-cset) r))))))
|
||||
(if (static-regexp? re-or-cset) ; A regexp or code
|
||||
(uncase re-or-cset) ; producing a regexp.
|
||||
`(,(r 'uncase)
|
||||
,(regexp->scheme (simplify-regexp re-or-cset) r))))))
|
||||
|
||||
;; These just change the lexical case-sensitivity context.
|
||||
((w/nocase) (parse-seq/context (cdr sre) #f))
|
||||
((w/case) (parse-seq/context (cdr sre) #t))
|
||||
;; These just change the lexical case-sensitivity context.
|
||||
((hygn-eq? 'w/nocase) (parse-seq/context (cdr sre) #f))
|
||||
((hygn-eq? 'w/case) (parse-seq/context (cdr sre) #t))
|
||||
|
||||
;; ,<exp> and ,@<exp>
|
||||
((unquote)
|
||||
;; ,<exp> and ,@<exp>
|
||||
((hygn-eq? 'unquote)
|
||||
(let ((exp (cadr sre)))
|
||||
(if cset?
|
||||
`(,%coerce-dynamic-charset ,exp)
|
||||
`(,%flush-submatches (,%coerce-dynamic-regexp ,exp)))))
|
||||
((unquote-splicing)
|
||||
(let ((exp (cadr sre)))
|
||||
(if cset?
|
||||
`(,%coerce-dynamic-charset ,exp)
|
||||
`(,%coerce-dynamic-regexp ,exp))))
|
||||
((hygn-eq? 'unquote-splicing)
|
||||
(let ((exp (cadr sre)))
|
||||
(if cset?
|
||||
`(,%coerce-dynamic-charset ,exp)
|
||||
`(,%coerce-dynamic-regexp ,exp))))
|
||||
|
||||
((~) (let* ((cs (assoc-cset-op char-set-union 'char-set-union
|
||||
(map parse-char-class (cdr sre))
|
||||
r))
|
||||
(cs (if (char-set? cs)
|
||||
((hygn-eq? '~) (let* ((cs (assoc-cset-op char-set-union 'char-set-union
|
||||
(map parse-char-class (cdr sre))
|
||||
r))
|
||||
(cs (if (char-set? cs)
|
||||
(char-set-complement cs)
|
||||
`(,(r 'char-set-complement) ,cs))))
|
||||
(if cset? cs (make-re-char-set cs))))
|
||||
(if cset? cs (make-re-char-set cs))))
|
||||
|
||||
((&) (let ((cs (assoc-cset-op char-set-intersection 'char-set-intersection
|
||||
(map parse-char-class (cdr sre))
|
||||
r)))
|
||||
(if cset? cs (make-re-char-set cs))))
|
||||
((hygn-eq? '&) (let ((cs (assoc-cset-op char-set-intersection 'char-set-intersection
|
||||
(map parse-char-class (cdr sre))
|
||||
r)))
|
||||
(if cset? cs (make-re-char-set cs))))
|
||||
|
||||
((-) (if (pair? (cdr sre))
|
||||
(let* ((cs1 (parse-char-class (cadr sre)))
|
||||
(cs2 (assoc-cset-op char-set-union 'char-set-union
|
||||
((hygn-eq? '-) (if (pair? (cdr sre))
|
||||
(let* ((cs1 (parse-char-class (cadr sre)))
|
||||
(cs2 (assoc-cset-op char-set-union 'char-set-union
|
||||
(map parse-char-class (cddr sre))
|
||||
r))
|
||||
(cs (if (and (char-set? cs1) (char-set? cs2))
|
||||
(char-set-difference cs1 cs2)
|
||||
`(,(r 'char-set-difference)
|
||||
,(if (char-set? cs1)
|
||||
(char-set->scheme cs1 r)
|
||||
(cs (if (and (char-set? cs1) (char-set? cs2))
|
||||
(char-set-difference cs1 cs2)
|
||||
`(,(r 'char-set-difference)
|
||||
,(if (char-set? cs1)
|
||||
(char-set->scheme cs1 r)
|
||||
cs1)
|
||||
. ,(if (char-set? cs2)
|
||||
(list (char-set->scheme cs2 r))
|
||||
(cdr cs2))))))
|
||||
(if cset? cs (make-re-char-set cs)))
|
||||
(error "SRE set-difference operator (- ...) requires at least one argument")))
|
||||
. ,(if (char-set? cs2)
|
||||
(list (char-set->scheme cs2 r))
|
||||
(cdr cs2))))))
|
||||
(if cset? cs (make-re-char-set cs)))
|
||||
(error "SRE set-difference operator (- ...) requires at least one argument")))
|
||||
|
||||
((/) (let ((cset (range-class->char-set (cdr sre) case-sensitive?)))
|
||||
((hygn-eq? '/) (let ((cset (range-class->char-set (cdr sre) case-sensitive?)))
|
||||
(if cset? cset (make-re-char-set cset))))
|
||||
|
||||
((posix-string)
|
||||
((hygn-eq? 'posix-string)
|
||||
(if (and (= 1 (length (cdr sre)))
|
||||
(string? (cadr sre)))
|
||||
(posix-string->regexp (cadr sre))
|
||||
(error "Illegal (posix-string ...) SRE body." sre)))
|
||||
|
||||
(else (if (every string? sre) ; A set spec -- ("wxyz").
|
||||
(let* ((cs (apply char-set-union
|
||||
(map string->char-set sre)))
|
||||
(cs (if case-sensitive? cs (uncase-char-set cs))))
|
||||
(if cset? cs (make-re-char-set cs)))
|
||||
(else (if (every string? sre) ; A set spec -- ("wxyz").
|
||||
(let* ((cs (apply char-set-union
|
||||
(map string->char-set sre)))
|
||||
(cs (if case-sensitive? cs (uncase-char-set cs))))
|
||||
(if cset? cs (make-re-char-set cs)))
|
||||
|
||||
(error "Illegal SRE" sre)))))
|
||||
(error "Illegal SRE" sre))))))
|
||||
|
||||
;; It must be a char-class name (ANY, ALPHABETIC, etc.)
|
||||
(else (let ((cs (case sre
|
||||
((any) char-set:full)
|
||||
((nonl) nonl-chars)
|
||||
((lower-case lower) char-set:lower-case)
|
||||
((upper-case upper) char-set:upper-case)
|
||||
((alphabetic alpha) char-set:letter)
|
||||
((numeric digit num) char-set:digit)
|
||||
((alphanumeric alnum alphanum) char-set:letter+digit)
|
||||
((punctuation punct) char-set:punctuation)
|
||||
((graphic graph) char-set:graphic)
|
||||
((blank) char-set:blank)
|
||||
((whitespace space white) char-set:whitespace)
|
||||
((printing print) char-set:printing)
|
||||
((control cntrl) char-set:iso-control)
|
||||
((hex-digit xdigit hex) char-set:hex-digit)
|
||||
((ascii) char-set:ascii)
|
||||
(else (error "Illegal regular expression" sre)))))
|
||||
(if cset? cs (make-re-char-set cs))))))))
|
||||
(else
|
||||
(letrec ((hygn-memq? (lambda (sym-list)
|
||||
(if (null? sym-list)
|
||||
#f
|
||||
(or (c sre (r (car sym-list)))
|
||||
(hygn-memq? (cdr sym-list)))))))
|
||||
(let ((cs (cond
|
||||
((hygn-memq? '(any)) char-set:full)
|
||||
((hygn-memq? '(nonl)) nonl-chars)
|
||||
((hygn-memq? '(lower-case lower)) char-set:lower-case)
|
||||
((hygn-memq? '(upper-case upper)) char-set:upper-case)
|
||||
((hygn-memq? '(alphabetic alpha)) char-set:letter)
|
||||
((hygn-memq? '(numeric digit num)) char-set:digit)
|
||||
((hygn-memq? '(alphanumeric alnum alphanum)) char-set:letter+digit)
|
||||
((hygn-memq? '(punctuation punct)) char-set:punctuation)
|
||||
((hygn-memq? '(graphic graph)) char-set:graphic)
|
||||
((hygn-memq? '(blank)) char-set:blank)
|
||||
((hygn-memq? '(whitespace space white)) char-set:whitespace)
|
||||
((hygn-memq? '(printing print)) char-set:printing)
|
||||
((hygn-memq? '(control cntrl)) char-set:iso-control)
|
||||
((hygn-memq? '(hex-digit xdigit hex)) char-set:hex-digit)
|
||||
((hygn-memq? '(ascii)) char-set:ascii)
|
||||
(else (error "Illegal regular expression" sre)))))
|
||||
(if cset? cs (make-re-char-set cs)))))))))
|
||||
|
||||
|
||||
;;; In a CSET? true context, S must be a 1-char string; convert to a char set
|
||||
|
|
|
@ -498,7 +498,7 @@
|
|||
(values re #f))))
|
||||
|
||||
((re-submatch? re)
|
||||
(receive (new-body body-changed?) (recur (re-submatch? re))
|
||||
(receive (new-body body-changed?) (recur (re-submatch:body re))
|
||||
(if body-changed?
|
||||
(values (%make-re-submatch new-body
|
||||
(re-submatch:pre-dsm re)
|
||||
|
|
|
@ -140,7 +140,8 @@
|
|||
|
||||
;; Regular letter -- either alone, or startpoint of a range.
|
||||
(else (if (and (< (+ i1 1) len)
|
||||
(char=? #\- (string-ref s i1)))
|
||||
(char=? #\- (string-ref s i1))
|
||||
(not (char=? #\] (string-ref s (+ i1 1)))))
|
||||
|
||||
;; Range
|
||||
(let* ((i-tochar (+ i1 1))
|
||||
|
|
|
@ -171,7 +171,8 @@
|
|||
|
||||
string-lib
|
||||
|
||||
loopholes ; For my bogus CALL-TERMINALLY implementation.
|
||||
fluids ; For exec-path-list
|
||||
loopholes ; For my bogus CALL-TERMINALLY implementation.
|
||||
|
||||
scheme
|
||||
)
|
||||
|
@ -247,6 +248,8 @@
|
|||
command-processor ; command-output
|
||||
filenames ; translate
|
||||
scheme-level-2-internal ; usual-resumer
|
||||
package-commands-internal ;user-environment
|
||||
environments ; with-interaction-environment
|
||||
scheme)
|
||||
(files startup)
|
||||
(optimize auto-integrate)
|
||||
|
@ -356,7 +359,7 @@
|
|||
(export repl)
|
||||
awk-interface
|
||||
odbc-interface
|
||||
char-set-predicates-interface; Urk -- Some of this is R5RS!
|
||||
char-predicates-interface; Urk -- Some of this is R5RS!
|
||||
obsolete-char-set-interface
|
||||
)
|
||||
|
||||
|
@ -372,7 +375,7 @@
|
|||
awk-package
|
||||
odbc-package
|
||||
field-reader-package
|
||||
char-set-predicates-lib ; Urk -- Some of this is R5RS!
|
||||
char-predicates-lib ; Urk -- Some of this is R5RS!
|
||||
scheme)
|
||||
|
||||
(access scsh-top-package)
|
||||
|
|
|
@ -297,7 +297,8 @@
|
|||
(close-fdes (open-fdes fname oflags #o600))
|
||||
fname)
|
||||
(if (null? maybe-prefix) '()
|
||||
(list (string-append (car maybe-prefix) ".~a"))))))
|
||||
(list (string-append (constant-format-string (car maybe-prefix))
|
||||
".~a"))))))
|
||||
|
||||
(define *temp-file-template*
|
||||
(make-fluid (string-append "/usr/tmp/" (number->string (pid)) ".~a")))
|
||||
|
@ -316,6 +317,23 @@
|
|||
(loop (+ i 1)))))))))
|
||||
|
||||
|
||||
;; Double tildes in S.
|
||||
;; Using the return value as a format string will output exactly S.
|
||||
(define (constant-format-string s) ; Ugly code. Would be much clearer
|
||||
(let* ((len (string-length s)) ; if written with string SRFI.
|
||||
(tilde? (lambda (s i) (char=? #\~ (string-ref s i))))
|
||||
(newlen (do ((i (- len 1) (- i 1))
|
||||
(ans 0 (+ ans (if (tilde? s i) 2 1))))
|
||||
((< i 0) ans)))
|
||||
(fs (make-string newlen)))
|
||||
(let lp ((i 0) (j 0))
|
||||
(cond ((< i len)
|
||||
(let ((j (cond ((tilde? s i) (string-set! fs j #\~) (+ j 1))
|
||||
(else j))))
|
||||
(string-set! fs j (string-ref s i))
|
||||
(lp (+ i 1) (+ j 1))))))
|
||||
fs))
|
||||
|
||||
|
||||
;;; Roughly equivalent to (pipe).
|
||||
;;; Returns two file ports [iport oport] open on a temp file.
|
||||
|
@ -664,7 +682,7 @@
|
|||
(%exec prog (cons prog arglist) env))
|
||||
|
||||
;(define (exec-path/env prog env . arglist)
|
||||
; (cond ((exec-path-search (stringify prog) exec-path-list) =>
|
||||
; (cond ((exec-path-search (stringify prog) (fluid exec-path-list)) =>
|
||||
; (lambda (binary)
|
||||
; (apply exec/env binary env arglist)))
|
||||
; (else (error "No executable found." prog arglist))))
|
||||
|
@ -686,7 +704,7 @@
|
|||
(for-each (lambda (dir)
|
||||
(let ((binary (string-append dir "/" prog)))
|
||||
(%%exec/errno binary argv env)))
|
||||
exec-path-list))))
|
||||
(fluid exec-path-list)))))
|
||||
|
||||
(error "No executable found." prog arglist))
|
||||
|
||||
|
@ -746,7 +764,7 @@
|
|||
|
||||
;;; Some globals:
|
||||
(define home-directory "")
|
||||
(define exec-path-list '())
|
||||
(define exec-path-list (make-fluid '()))
|
||||
|
||||
(define (init-scsh-vars quietly?)
|
||||
(set! home-directory
|
||||
|
@ -754,11 +772,11 @@
|
|||
(else (if (not quietly?)
|
||||
(warn "Starting up with no home directory ($HOME)."))
|
||||
"/")))
|
||||
(set! exec-path-list
|
||||
(cond ((getenv "PATH") => split-colon-list)
|
||||
(else (if (not quietly?)
|
||||
(warn "Starting up with no path ($PATH)."))
|
||||
'()))))
|
||||
(set-fluid! exec-path-list
|
||||
(cond ((getenv "PATH") => split-colon-list)
|
||||
(else (if (not quietly?)
|
||||
(warn "Starting up with no path ($PATH)."))
|
||||
'()))))
|
||||
|
||||
|
||||
; SIGTSTP blows s48 away. ???
|
||||
|
|
|
@ -42,10 +42,20 @@
|
|||
;;; This is what we export to the user for his programs.
|
||||
|
||||
(define (dump-scsh-program start filename)
|
||||
(really-dump-scsh-program (lambda (args)
|
||||
(init-scsh-vars #t) ; Do it quietly.
|
||||
(start args))
|
||||
filename))
|
||||
(let ((context (user-context)))
|
||||
(really-dump-scsh-program
|
||||
(lambda (args)
|
||||
(with-new-session context ; "Log in" user.
|
||||
(current-input-port) (current-output-port)
|
||||
args
|
||||
#f
|
||||
(lambda ()
|
||||
(with-interaction-environment
|
||||
(user-environment) ; <-- from CONTEXT.
|
||||
(lambda ()
|
||||
(init-scsh-vars #t) ; Do it quietly.
|
||||
(start args))))))
|
||||
filename)))
|
||||
|
||||
|
||||
(define (scsh-stand-alone-resumer start)
|
||||
|
|
|
@ -891,7 +891,10 @@
|
|||
|
||||
(define (alist->env-vec alist)
|
||||
(list->vector (map (lambda (var.val)
|
||||
(string-append (car var.val) "=" (cdr var.val)))
|
||||
(string-append (car var.val) "="
|
||||
(let ((val (cdr var.val)))
|
||||
(if (string? val) val
|
||||
(string-join val ":")))))
|
||||
alist)))
|
||||
|
||||
;;; ENV->ALIST
|
||||
|
|
|
@ -217,7 +217,7 @@ scheme_value date2time(int sec, int min, int hour,
|
|||
|
||||
d.tm_sec = sec; d.tm_min = min; d.tm_hour = hour;
|
||||
d.tm_mday = mday; d.tm_mon = month; d.tm_year = year;
|
||||
d.tm_wday = 0; d.tm_yday = 0; d.tm_isdst = summer;
|
||||
d.tm_wday = 0; d.tm_yday = 0;
|
||||
|
||||
if( FIXNUMP(tz_secs) ) { /* Offset from GMT in seconds. */
|
||||
char **oldenv = environ; /* Set TZ to UTC */
|
||||
|
@ -232,12 +232,16 @@ scheme_value date2time(int sec, int min, int hour,
|
|||
environ = oldenv;
|
||||
}
|
||||
|
||||
/* ### Note that we *still* don't implement the manual paragraph
|
||||
with "When calcultating with time-zones, the date's SUMMER?
|
||||
field is used to resolve ambiguities. */
|
||||
else if( STRINGP(tz_name) ) { /* Time zone */
|
||||
char *newenv[2];
|
||||
char **oldenv = make_newenv(tz_name, newenv);
|
||||
if( !oldenv ) return ENTER_FIXNUM(errno);
|
||||
tzset(); /* NetBSD, SunOS POSIX-noncompliance requires this. */
|
||||
errno = 0;
|
||||
d.tm_isdst = -1;
|
||||
t = mktime(&d);
|
||||
if( t == -1 ) return ENTER_FIXNUM(errno ? errno : -1);
|
||||
revert_env(oldenv);
|
||||
|
@ -246,6 +250,7 @@ scheme_value date2time(int sec, int min, int hour,
|
|||
else { /* Local time */
|
||||
tzset(); /* NetBSD, SunOS POSIX-noncompliance requires this. */
|
||||
errno = 0;
|
||||
d.tm_isdst = -1;
|
||||
t = mktime(&d);
|
||||
if( t == -1) return ENTER_FIXNUM(errno ? errno : -1);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue