REBOL/Core Changes
Versions 2.5.0 - 2.5.6 Updated August 2003
Contents:
1. Core 2.5.6
1.1 Command Line Startup (Fixes CGI/shell scripts)
1.2 Implied Quit
1.3 Corrupt Datatype Failure
1.4 Help Native! Fixed
1.5 Get on NONE
1.6 Set-Browser-Path
1.7 DO On Command Line
1.8 FIND/Any Bug Fixed.
1.9 Molding Empty File Names
2. Core 2.5.5
2.1 Main Purpose
2.2 New Core License
2.3 Startup Files (user.r and rebol.r)
2.4 How Scripts are Started
2.5 Command Line Terminator (CR)
2.6 Changes to SECURE
2.7 MOLD/Flat Refinement
2.8 Truncation of Series Index (when Past Tail)
2.9 AT on PORTs
2.10 Added SIXTH Through TENTH Functions
2.11 Lines Longer Than 4 KB in Direct/Lines Mode
2.12 DECODE-CGI Handles Duplicate Names
2.13 ALTER Fixed
2.14 Network Errors in TRY (Net-Error Throw)
2.15 Extended FTP Directory Paths
2.16 STATS for SYSTEM/STATS
2.17 PURL Captured
3. Core 2.5.3
3.1 Credits
3.2 MAKE-DIR Rewritten
3.3 New Bitset Functions: CLEAR, LENGTH?, EMPTY?
3.4 Changes to SKIP Function
3.5 ARRAYs Initialized with Block Values
3.6 Added PARSE BREAK Word
3.7 Fix to OPEN on Network Ports
3.8 Fixed Crash on Modified Functions
3.9 CHANGE Accepts Any Type Value
3.10 Unset Object Variables (on Exit)
3.11 Added BUILD-MARKUP Function
3.12 Revised BUILD-TAG Function
3.13 Revised DECODE-CGI Function
3.14 UNPROTECT Fixed
3.15 ALTER added to Core
3.16 SYSTEM Word Protected
3.17 Error Message for Word Context
3.18 Fixed Crash on Future Dates
4. Core 2.5.2
4.1 CONSTRUCT Object Creator
4.2 LOAD Change (Important)
4.3 HELP Expanded
4.4 SUFFIX? Function Added
4.5 SIGN? Function Added
4.6 COMPONENT? Function Added
4.7 SEND Function Updated
4.8 Miscellaneous Fixes
4.8.1 TYPE? (As used in PARSE)
4.8.2 MOLD/ALL
4.8.3 FTP
5. Core 2.5.1
5.1 Source Code Form for Values of NONE, TRUE, etc.
5.2 Less Aggressive Evaluation (Important!)
5.3 COMPOSE/ONLY Inserts Blocks
5.4 REMOVE-EACH - Easy Series Element Removal
5.5 ATTEMPT for Error Handling
5.6 EXTRACT Function Updated
5.7 SAVE to Memory
5.8 SEND Refinements /Subject /Attach
5.9 Difference for Date/time
5.10 System Port Added
6. Core 2.5.0
6.1 New Sort Function
6.1.1 Terminology
6.1.2 Arguments
6.1.3 Comparators
6.2 File Modes
6.2.1 Getting Lists of Modes
6.2.2 Modes Available
6.2.3 Using File Forks
6.2.4 Finding All Forks
6.3 Serial Port Access
6.3.1 Specifying a Serial Port
6.3.2 Operation
6.4 Objects
6.4.1 Make Object Object
6.4.2 Third Object
6.5 Mold and Load Changes
6.6 File and Port Changes
6.7 Network Protocol Change (APOP, IMAP)
6.8 Data Series Changes
6.9 Math Related Changes
6.10 Command Line Changes
6.11 Console
6.12 Control
6.13 Interpreter
6.14 Other Changes
7. Interpreter Fixes
8. Networking Fixes
9. Other Function Fixes
1. Core 2.5.6
Miscellaneous fixes made during the version 2.5.6 releases of the
/SDK, /Command, and /SDK/Command products.
1.1 Command Line Startup (Fixes CGI/shell scripts)
REBOL ignores CR characters (13) in script files, but a problem
occurred if a CR appeared on the command line that started REBOL.
REBOL would display HELP information. This problem has been fixed and
solves the problem that may occur when you used an FTP binary transfer
of a CGI script to your Linux/Unix web server.
1.2 Implied Quit
All REBOL products are now consistent in what they do when a script
has finished running, but did not execute a QUIT. They now now force a
QUIT at the end of the script. If you want to go to the REBOL console,
put a HALT in your script.
1.3 Corrupt Datatype Failure
In some situations REBOL would crash at the end of a script with a
"corrupt datatype" error. This was caused by optimizations made in
2.5.3 that freed unused internal structures. The problem would only
occur when a script caused memory recycling and did not include a QUIT
or HALT at its end. This has been fixed.
1.4 Help Native! Fixed
Requesting HELP on NATIVE! has been fixed (the native! word has been
restored).
1.5 Get on NONE
A GET of NONE is now allowed and will return NONE.
This makes it easier to write code that fetches values from an object
when the word within the object may be missing. For example, the code
below will no longer cause an error if the word is missing from the
object:
value: get in object 'word
|
This makes code simpler for cases like CGI object form values:
cgi: construct decode-cgi read-cgi
name: any [get in cgi 'name "default"]
|
In the example above, if the cgi/name does not exist, the default
string is used. No error will occur if the name is missing from the
CGI object.
1.6 Set-Browser-Path
The SET-BROWSER-PATH function now accepts REBOL filename format. It
will also accept a string that is in local OS file format (when provided
as a string! type). You can also set it to NONE.
The SET-BROWSER-PATH function will also return it's prior setting.
If you wish to disable this function (for security reasons), you can
set it to NONE or unset the function.
set-browser-path: none
unset 'set-browser-path
|
1.7 DO On Command Line
The --do option is processed again on the command line. This allows
you to pass expressions to be executed from the shell command line.
For example:
rebol --do "probe system/options/args"
|
Note that --do now happens after the rebol.r and user.r files are
evaluated (letting you initialize your own custom functions and
values) but before the script on the command line is evaluated.
The --do option can be used to define variables prior to the
execution of your script. For example:
rebol make-website.r --do "verbose: true"
|
would set the VERBOSE variable to TRUE at the start of execution. To
set the default value in the script, you might use code such as:
if not value? 'verbose [verbose: false]
|
1.8 FIND/Any Bug Fixed.
A serious error was reported related to using FIND with the /any
refinement (wildcards). For some cases FIND/any would return a valid
string rather than NONE. For example:
returned "c". This problem has been fixed.
1.9 Molding Empty File Names
MOLDing an empty filename resulted in source code that could not be
loaded. In rare cases, this might case a SAVE to create a file that
LOAD could not handle. Molding an empty file name now outputs the
characters %"" to avoid this problem. This fixes the problem in MOLD,
SAVE, and PROBE.
2. Core 2.5.5
2.1 Main Purpose
The primary purpose of the Core 2.5.5 release is to bring
REBOL/Core into closer compatibility with the new Mac OS X and
REBOL/SDK kernels.
2.2 New Core License
REBOL/Core licensed has changed to allow personal, educational,
or commercial use of the CORE software free of charge.
Note that this license change only applies to REBOL/Core (and
will be added to the next release of REBOL/View), but it does
not apply to REBOL/SDK, /Command, /IOS or other REBOL commercial
products.
2.3 Startup Files (user.r and rebol.r)
Beta V2.5.4 did not evaluate the rebol.r and user.r files.
V2.5.5 evaluates them again, although using a slightly different
method. This should not affect your program. The order is still:
- Check the current directory first.
- Check the system/options/home directory second.
This allows you to have a single standard rebol.r file (and
optionally a user.r file) that is shared by all users on
multiuser systems.
2.4 How Scripts are Started
The method used to start initial scripts has been modified.
This change will have no affect on your programs, but it will
produce a better error message on script errors by eliminating
the error line that refers to the problem being "Near do-boot".
That line was confusing to new users, because do-boot was not
part of their script file.
2.5 Command Line Terminator (CR)
REBOL no longer shows Usage info if a CR char is passed from
a Unix shell on the shell command line.
Although REBOL scripts properly read and load with respect to
the CR (ASCII 13) character, some operating systems will pass
the CR as a command line argument, causing older versions of
REBOL to print its usage help information.
For example, you might see a problem with a CGI shell script
starting with:
#!/home/user/rebol -cs
REBOL [...]
|
that was written on a Windows system and transferred to Linux
without converting line terminators.
This case has been fixed.
2.6 Changes to SECURE
Beta V2.5.4 did not set SECURE prior to running scripts (in
other words, it functioned like REBOL/Base).
With V2.5.5 security is being set again, although with a slight
change: by default you can now write to a script's target
directory. For example, if you run:
REBOL /home/test/script.r
|
REBOL will startup with WRITE access to /home/test. All other
directories will be set to READ only (with WRITE ask).
This change makes it easier for users to write scripts that
write and update local data files without the need to provide a
-S command line option, but it still protects the rest of your
files.
Note that the +S command line option has also been changed.
Previously, +S meant SECURE QUIT, which was almost useless
because your REBOL would QUIT as soon as it tried to read its
rebol.r and user.r files. Now +S means SECURE ASK, so running
with:
Will prompt the user for all READ/WRITE operations for files and
networking. A safe mode of operation, but less strict than
before.
In addition, the --secure options should also work again now:
rebol --secure allow script.r
rebol --secure ask script.r
|
2.7 MOLD/Flat Refinement
The /flat refinement allows you to MOLD code and data without
line indentation, making the resulting string smaller (for sending
over a network, storing as compressed data, encapping, etc.).
For example:
blk: [
name [
first "Bob"
last "Smith"
]
options [
colors [
red
green
blue
]
]
]
>>print mold blk
[
name [
first "Bob"
last "Smith"
]
options [
colors [
red
green
blue
]
]
]
>> print mold/flat blk
[
name [
first "Bob"
last "Smith"
]
options [
colors [
red
green
blue
]
]
]
|
2.8 Truncation of Series Index (when Past Tail)
The handling of an "past the tail" series index has been changed.
In prior versions of REBOL, referring to a series past its tail
would cause an error:
>> a: "ABC"
== "ABC"
>> b: next a
== "BC"
>> clear a
== ""
>> insert b "X"
** Script Error: Out of range or past end
** Near: insert b "X"
|
In some situations, this problem could become difficult to detect,
because nearly any reference to B would cause the error.
>> tail? b
** Script Error: Out of range or past end
** Near: tail? b
|
As a result, the "past end" handling has been relaxed. For many
functions, the index will now truncate to the current tail of
the series:
>> a: "ABC"
== "ABC"
>> b: next a
== "BC"
>> clear a
== ""
>> tail? b
== true
|
2.9 AT on PORTs
The AT function (similar to the SKIP function) now works for the
Port datatype.
2.10 Added SIXTH Through TENTH Functions
Five new ordinal functions have been added:
sixth
seventh
eighth
ninth
tenth
|
The benefit of these function becomes more clear when you
consider using them to pick values from a series (instead of
using an object field).
name-of: :first
age-of: :second
date-of: :third
...
product-of: :ninth
...
if empty? product-of record [print "missing product"]
|
The line above is much more readable than:
if empty? ninth record [print "missing product"]
|
Here's a handy utility function for creating such named
accessors:
ordain: func [
"Defines ordinal accessors (synonyms)."
words [block!] /local ords
][
ords: [first second third fourth fifth
sixth seventh eighth ninth tenth]
foreach word words [
set word get first ords
ords: next ords
]
]
|
The above example would then be simplified to:
ordain [name-of age-of date-of ... product-of]
...
if empty? product-of record [print "missing product"]
|
Question: Would you like to see ordain become a regular
function in REBOL? Tell us via Feedback.
2.11 Lines Longer Than 4 KB in Direct/Lines Mode
Earlier versions of REBOL did not properly expand their internal
line buffers beyond 4 KB for files opened in direct/lines mode.
As a result, lines longer than 4 KB (no line terminators for
more than 4 KB) would not be read correctly and would cause an
end of file. This problem has been fixed in the current release.
2.12 DECODE-CGI Handles Duplicate Names
With increased use of REBOL for CGI scripts, we've expanded
the DECODE-CGI function to handle duplicate name fields.
For example, checklists used in web forms may return multiple
values for a single variable. DECODE-CGI will now make these
multivalued returns into blocks:
>> cgi-str: {name=bob&option=view&option=email&}
>> decode-cgi cgi-str
== [name: "bob" option: ["view" "email"]]
|
2.13 ALTER Fixed
A serious error in the ALTER function (a data set flagging
function, see updated docs in The REBOL
Dictionary) caused it to malfunction. This problem has been
fixed.
2.14 Network Errors in TRY (Net-Error Throw)
The NET-ERROR function used THROW for errors, rather than just
letting the error throw itself. This caused some types of
network errors to bypass a higher level catch when using TRY.
This meant that if you used a TRY around sections of your code,
certain network errors (such as an SMTP problem) may be thrown
past it, which would cause the error to be passed all the way
out to user at the console. This was a problem for SDK scripts,
and has been fixed.
2.15 Extended FTP Directory Paths
When using FTP URLs, there was no easy way to provide a full path
from the root directory.
For example, your logon directory may be:
but you want to refer to:
In the new release, you can use a double slash URL to provide
the absolute directory path:
read ftp://user:pass@host//var/log/messages
|
(Please tell us if you have any problems using this format.)
2.16 STATS for SYSTEM/STATS
The STATS function is now directly accessible. You no longer need
to use SYSTEM/STATS.
In addition, the STATS function now more accurately computes
memory usage.
2.17 PURL Captured
The variable PURL used in DECODE-URL is now a local variable
rather than a global.
3. Core 2.5.3
3.1 Credits
Thanks go to these contributors for their feedback, suggestions, or
solutions:
Andrew Martin
"Anton"
Cal Dixon
Carl Sassenrath
Ernie van der Meer
Gregg Irwin
Ladislav Mecir
Maarten Koopmans
"Mr. Martin Mr. Saint"
Reichart Von Wolfsheild
|
Did we miss your feedback or contribution to fixes or improvements?
If so, tell us at:
http://www.rebol.com/feedback.html.
It is not always possible to get every change into each new
release, but if you have found a bug that's causing you
problems, please let us know and we'll do our best to fix it.
Provide a very short, repeatable example of the problem, and if
you have a fix to the problem, send that along as well. (You'll
see the fix happen much faster that way.)
3.2 MAKE-DIR Rewritten
The MAKE-DIR function has been rewritten and now works
correctly. In addition, it has been relaxed to not cause an
error when the specified directory exists. Use the EXISTS?
function if you need to check that.
3.3 New Bitset Functions: CLEAR, LENGTH?, EMPTY?
Three new functions (actions) have been added to bitsets:
The CLEAR function quickly clears all bits to zero.
The LENGTH? function returns the number of bits in the bitset
(always multiple of 8).
The EMPTY? function returns TRUE if any bit is set, otherwise
it returns FALSE. (Note that EMPTY? is the same function as
TAIL?; therefore, TAIL? also returns the same results, but the
word has no meaning for bitsets.)
Bitsets are used as high performance logic arrays for character
sets and hashes.
Examples:
>> items: make bitset! 40
== make bitset! #{0000000000}
>> length? items
== 40
>> empty? items
== true
>> insert items 10
== make bitset! #{0004000000}
>> empty? items
== false
>> clear items
== make bitset! #{0000000000}
>> empty? items
== true
>> empty? negate items
== false
|
3.4 Changes to SKIP Function
There are three changes to SKIP that you should note:
1. SKIP now handles decimal offsets correctly. Values are
truncated down to lower integer value. (Note that decimal
offsets should be used with caution because 1.9999999 is not the
same as 2.0 when it comes to indexing.)
>> skip "abc" 1.9999999
== "bc"
>> skip "abc" 2.0
== "c"
|
2. SKIP can have a logic offset. It is made consistent with PICK
and AT when used with logic offsets.
>> pick [red green] true
== red
>> skip [red green] true
== [red green]
>> at [red green] true
== [red green]
>> pick [red green] false
== green
>> skip [red green] false
== [green]
>> at [red green] false
== [green]
|
For logic offsets, SKIP is identical to AT.
3. SKIP on images will offset pixels, not RGBA bytes. This is
consistent with AT, PICK, and POKE. If you are currently using
skip on images, this change will affect your code.
3.5 ARRAYs Initialized with Block Values
If a block value is provided as the initial element value in
the ARRAY function, each element should be the block, not the
contents of the block.
In addition, if the initial value is a SERIES of any type (e.g.
string, block, email, url) it will be deep copied into each
array element (that is, the value of each element will be unique,
not shared).
As an example:
>> a: array/initial [2 3] [1 2]
== [[[1 2] [1 2] [1 2]] [[1 2] [1 2] [1 2]]]
>> append a/1/2 3
== [1 2 3]
>> a
== [[[1 2] [1 2 3] [1 2]] [[1 2] [1 2] [1 2]]]
|
3.6 Added PARSE BREAK Word
Within some types of PARSE loops such as ANY and SOME, it can
sometimes be difficult to write rules that terminate the loop.
This happens primarily when using general rules that try to
capture "all other cases" within the loop. For example, code
such as:
parse item [
any [
"word" (print "got word")
| copy value [to "abc" | to end]
(print value)
]
]
|
will end up looping forever because the second rule within the
ANY will always succeed, and the ANY will never terminate.
To help solve this problem, the BREAK keyword was added to the
parse dialect. Its use is simple. When the BREAK word is
encountered within a rule block, the block is immediately
terminated regardless of the current input pointer. Expressions
that follow the BREAK within the same rule block will not be
evaluated.
The above example can now be written as:
parse item [
any [
"word" (print "got word")
| copy value [to "abc" | to end]
(print value) break
]
]
|
The ANY loop will be terminated after the second rule.
Generally, for ANY rule blocks that need to terminate at the end
of the input stream, you can add an END check followed by the
BREAK keyword, such as in this example:
parse item [
any [
end break
| "word" (print "got word")
| copy value [to "abc" | to end]
(print value)
]
]
|
3.7 Fix to OPEN on Network Ports
OPEN on network port under some versions of Windows32 would fail
due to an incorrect error code returned from WinSock library (as
documented by Microsoft). Fixed.
3.8 Fixed Crash on Modified Functions
Fixed the crash that happened when modifying a function's value
while evaluating its arguments. For example, the code below:
a: func [x] [print x]
b: func [] [a: 42]
a b
|
no longer causes a crash.
Note that modifying a function while it is evaluating may
produce odd results that may vary between implementation
versions and should generally be avoided.
3.9 CHANGE Accepts Any Type Value
To be consistent with INSERT, the CHANGE function allows
a new value to be any datatype (ANY-TYPE!).
Users should be aware that a missing value argument will
result in a CHANGE value of UNSET!, not an error.
For example:
>> a: [10]
== [10]
>> do [change a]
== []
>> probe a
[unset]
== [unset]
|
3.10 Unset Object Variables (on Exit)
If exit occurs during object evaluation, unassigned variables
not copied from parent object are unset. Fixes the "end" bug
where the first variable was set to the END! datatype.
>> probe make object! [exit a: b:]
== make object! [
a: unset
b: unset
]
|
3.11 Added BUILD-MARKUP Function
This function was inspired by the EREBOL concept of Maarten
Koopmans and Ernie van der Meer. Essentially, the idea is that
REBOL makes a powerful PHP style markup processor for generating
web pages and other markup text.
The BUILD-MARKUP function has been added to support this
operation, and will become a standard part of every REBOL
implementation.
The BUILD-MARKUP function takes markup text (e.g. HTML) that
contains tags that begin with "<%" and end with "%>". It
evaluates the REBOL code within each tag (as if it were a REBOL
block), and replaces the tag with the result. Any REBOL
expression can be placed within the tag. As PHP has shown, this
is a very useful technique.
For example:
== build-markup "<%1 + 2%>"
>> "3"
== build-markup "<B><%1 + 2%></B>"
>> "<B>3</B>"
== build-markup "<%now%>"
>> "2-Aug-2002/18:01:46-7:00"
== build-markup "<B><%now%></B>"
>> "<B>2-Aug-2002/18:01:46-7:00</B>"
|
Supplying a <%now%> tag to BUILD-MARKUP inserts
the current date/time in the output.
Here's a short example that generates a web page from a template
and a custom name and email address:
template: {<HTML>
<BODY>
Hi <%name%>, your email is <i><%email%></i>.<P>
</BODY>
</HTML>
}
name: "Bob"
email: bob@example.com
page: build-markup template
|
Don't forget the two % characters within the tag. It's a common
mistake.
The value that is returned from the tag code is normally
"joined" into the output. You can also use FORM or MOLD on the
result to get the type of output you require. The example below
loads a list of files from the current directory and displays
them three different ways:
Input: "<PRE><%load %.%></PRE>"
Result: {<PRE>build-markup.rchanges.txt</PRE>}
Input: "<PRE><%form load %.%></PRE>"
Result: {<PRE>build-markup.r changes.txt</PRE>}
Input: "<PRE><%mold load %.%></PRE>"
Result: {<PRE>[%build-markup.r %changes.txt]</PRE>}
|
If the evaluation of a tag does not return a result (for example
using code such as print "test"), then nothing is output. In
this case, the output of PRINT will be sent to the standard
output device.
Input: {<NO-TEXT><%print "test"%></NO-TEXT>}
test
Result: "<NO-TEXT></NO-TEXT>"
|
The BUILD-TAG function can be used within the tag for converting
REBOL values into markup output:
Input: {<%build-tag [font color "red"]%>}
Result: {<font color="red">}
|
Tags can set and use variables in the same way as any REBOL
script. For example, the code below loads a list of files from
the current directory, saves it in a variable, then prints two
file names:
Input: "<PRE><%first files: load %.%></PRE>"
Result: {<PRE>build-markup.r</PRE>}
Input: "<PRE><%second files%></PRE>"
Result: {<PRE>changes.txt</PRE>}
|
Note that variables used within tags are always global variables.
If an error occurs within a tag, an error message will appear
as the tag's result. This allows you to see web page errors
from any HTML browser.
Input: "<EXAMPLE><%cause error%></EXAMPLE>"
Result: {<EXAMPLE>***ERROR no-value in: cause error</EXAMPLE>}
|
If you do not want error messages to be output, use the /QUIET
refinement. The example above would result in:
Result: "<EXAMPLE></EXAMPLE>"
|
3.12 Revised BUILD-TAG Function
The previous version of BUILD-TAG generated poor results for
most input combinations. It has been replaced by a new function
that was contributed by Andrew Martin. This function produces
better results, but ones that are different from the previous
function. If you are currently using BUILD-TAG, you will need to
adjust your code.
In: [input "checked" type "radio" name "Favourite" value "cat"]
Old: {<input="checked" type="radio" name="Favourite" value="cat">}
New: {<input checked type="radio" name="Favourite" value="cat">}
In: [html xml:lang "en"]
Old: {<html="xml:lang"="en">}
New: {<html xml:lang="en">}
In: [body text #FF80CC]
Old: {<body text="FF80CC">}
New: {<body text="#FF80CC">}
In: [a href %Test%20File%20Space.txt]
Old: {<a href="Test File Space.txt">}
New: {<a href="Test%20File%20Space.txt">}
In: [/html gibber %Froth.txt]
Old: {</html gibber="Froth.txt">}
New: "</html>"
In: [?xml version "1.0" encoding "UTF-8"]
Old: {<?xml version="1.0" encoding="UTF-8">}
New: {<?xml version="1.0" encoding="UTF-8"?>}
In: [html xmlns http://w3.org/xhtml xml:lang "en" lang "en"]
Old: {<html xmlns="http://w3.org/xhtml"="xml:lang"="en" lang="en">}
New: {<html xmlns="http://w3.org/xhtml" xml:lang="en" lang="en">}
In: [html xmlns http://w3.org/xhtml/ xml:lang "en" lang "en"]
Old: {<html xmlns="http://w3.org/xhtml/"="xml:lang"="en" lang="en">}
New: {<html xmlns="http://w3.org/xhtml/" xml:lang="en" lang="en">}
|
3.13 Revised DECODE-CGI Function
Several bugs have been fixed in DECODE-CGI. More specifically,
the function handles empty attribute assignments. Here are some
examples:
Input: "name=val1&name=val2"
Decoded: [name: "val1" name: "val2"]
Input: "name1=val1&name2&name3=&name4=val3"
Decoded: [name1: "val1" name2: "" name3: "" name4: "val3"]
Input: "name1="
Decoded: [name1: ""]
Input: "name2&"
Decoded: [name2: ""]
Input: "name3=&"
Decoded: [name3: ""]
Input: "name4=val"
Decoded: [name4: "val"]
Input: "name5=val&"
Decoded: [name5: "val"]
|
The new function is based on Andrew Martin's contribution. Thanks!
3.14 UNPROTECT Fixed
Attempting to UNPROTECT a block containing any value other than
a word could cause a crash. Now non-word values are ignored.
3.15 ALTER added to Core
The ALTER function found only in View is general purpose and has
been made available in all version of REBOL.
3.16 SYSTEM Word Protected
To help prevent an accidental beginner mistake that is difficult
to debug, the SYSTEM and REBOL words are now protected. If you
need to change them, use UNPROTECT first.
3.17 Error Message for Word Context
The error message "word not defined in this context" has been
changed to "word has no context" to better indicate that the
word has never been defined (more precisely, never been bound)
in the context of an object, function, or global environment.
3.18 Fixed Crash on Future Dates
Prevents startup crash caused by error in Microsoft Windows time
functions when running with system date set to greater than 2036.
4. Core 2.5.2
4.1 CONSTRUCT Object Creator
We've added a "light-evaluation" object creator to provide a
higher level of security for imported data objects. The function
is called CONSTRUCT and it makes new objects, but without a
normal evaluation of the object's specification (as is done in
the MAKE and CONTEXT functions).
When you CONSTRUCT an object, only literal types are accepted.
Functional evaluation is not performed. This allows your code to
directly import objects (such as those sent from unsafe external
sources such as email, cgi, etc.) without concern that they may
include "hidden" side effects using executable code.
CONSTRUCT is used in the same way as the CONTEXT function:
obj: construct [
name: "Fred"
age: 27
city: "Ukiah"
]
|
but, no evaluation takes place. That means object
specifications like:
obj: construct [
name: uppercase "Fred"
age: 20 + 7
time: now
]
|
do not produce their evaluated results.
The CONSTRUCT function is useful for importing external
objects. For example, loading preference settings from
a file can done with:
prefs: construct load %prefs.r
|
Similarly, you can use CONSTRUCT to load a CGI or email
response.
To provide a template object that contains default variable
values (similar to MAKE), use the /AS refinement. The example
below would use an existing object called standard-prefs as the
template.
prefs: construct/as load %prefs.r standard-prefs
|
The CONSTRUCT function will perform evaluation on the words
TRUE, FALSE, NONE, ON, and OFF to produce their expected
values. Literal words and paths will also be evaluated
to produce their respective words and paths. For example:
obj: construct [
a: true
b: none
c: 'word
]
|
The obj/a value would be logical TRUE, obj/b would be NONE, and
obj/c would be WORD.
4.2 LOAD Change (Important)
Script header objects are now created by the CONSTRUCT function
and they are no longer evaluated.
This change provides a greater level of default security when
the LOAD function is used to load REBOL data. The change should
affect very few scripts (only those that depend on evaluated
header variables -- rare.)
The LOAD function can be used safely without the need to use
LOAD/ALL to inspect a script header prior to evaluation.
4.3 HELP Expanded
Help can now be used to explore the fields of an object in a
user-friendly format. For example, typing this line at the
prompt:
will produce this result:
SYSTEM is an object of value:
version tuple! 1.0.4.3.1
build date! 1-May-2002/13:31:11-7:00
product word! Link
components block! length: 45
words object! [unset! error! datatype! context! native
license string! {REBOL End User License Agreement IMPORT
options object! [home script path boot args do-arg link-
user object! [name email home words]
script object! [title header parent path args words]
console object! [history keys prompt result escape busy
ports object! [input output echo system serial wait-li
network object! [host host-address]
schemes object! [default Finger Whois Daytime SMTP POP I
error object! [throw note syntax script math access co
standard object! [script port port-flags email face sound
view object! [screen-face focal-face caret highlight-
stats native! System statistics. Default is to return
locale object! [months days]
user-license object! [name email id message]
|
This works for other types of objects as well as user-created
objects. The code below would display the contents of the
text-face object created by a View layout:
out: layout [text-face: text "test"]
help text-face
|
Sub-objects can also be viewed. They are specified as paths.
For example, to see the options object of the system object:
The result would look something like this:
SYSTEM/OPTIONS is an object of value:
home file! %/d/rebol/link/
script file! %/d/rebol/link/ranch/utilities/console.r
path file! %/d/rebol/link/ranch/
boot file! %/d/rebol/link/rebol-link.exe
args none! none
do-arg none! none
link-url string! "tcp://localhost:4028"
server none! none
quiet logic! true
trace logic! false
help logic! false
install logic! false
boot-flags integer! 2064
binary-base integer! 16
cgi object! [server-software server-name gateway-int
|
In addition, the search feature in help now provides more
information about matches that were made. If you type:
You will now see:
Found these words:
caret-to-offset native! Returns the offset position relative to
offset-to-caret native! Returns the offset in the face's text co
to-binary function! Converts to binary value.
to-bitset function! Converts to bitset value.
to-block function! Converts to block value.
to-char function! Converts to char value.
to-date function! Converts to date value.
to-decimal function! Converts to decimal value.
to-email function! Converts to email value.
to-event function! Converts to event value.
to-file function! Converts to file value.
to-get-word function! Converts to get-word value.
to-hash function! Converts to hash value.
to-hex native! Converts an integer to a hex issue!.
to-idate function! Returns a standard Internet date string.
to-image function! Converts to image value.
to-integer function! Converts to integer value.
to-issue function! Converts to issue value.
to-list function! Converts to list value.
to-lit-path function! Converts to lit-path value.
to-lit-word function! Converts to lit-word value.
to-local-file native! Converts a REBOL file path to the local
to-logic function! Converts to logic value.
to-money function! Converts to money value.
to-none function! Converts to none value.
to-pair function! Converts to pair value.
to-paren function! Converts to paren value.
to-path function! Converts to path value.
to-rebol-file native! Converts a local system file path to a R
to-refinement function! Converts to refinement value.
to-set-path function! Converts to set-path value.
to-set-word function! Converts to set-word value.
to-string function! Converts to string value.
to-tag function! Converts to tag value.
to-time function! Converts to time value.
to-tuple function! Converts to tuple value.
to-url function! Converts to url value.
to-word function! Converts to word value.
|
4.4 SUFFIX? Function Added
The SUFFIX? function is a helper function that returns the
file "extension" portion of a filename or URL. For example:
>> suffix? %into.txt
== %.txt
>> suffix? http://www.rebol.com/docs.html
== %.html
>> suffix? %test
== none
>> suffix? %test.it/file
== none
|
SUFFIX? can be useful when selecting files from a directory.
The example below will only select html and htm files:
foreach file load %. [
if find [%.html %.htm] suffix? file [
browse file
]
]
|
4.5 SIGN? Function Added
The SIGN? function returns a positive, zero, or negative integer
based on the sign of its argument.
print sign? 1000
print sign? 0
print sign? -1000
|
The sign is returned as an integer to allow it to be used
as a multiplication term within an expression:
new: 2000 * sign val
if size > 10 [xy: 10x20 * sign num]
|
4.6 COMPONENT? Function Added
COMPONENT? is a helper function that checks for the existence of
a named REBOL component.
if component? 'crypt [print "Encryption available."]
if not component? 'sound [print "No sound."]
|
4.7 SEND Function Updated
The SEND function now includes a /SHOW refinement that will show
all TO recipients in the header. By default, recipients are not
normally shown.
send/show [bob@example.com fred@example.com] message
|
In addition the FROM field will include the sender's name as well
as an email address. The string in system/user/name is used as the
from address. For example, if:
system/user/name: "Fred Reboller"
|
Then when the email is sent, the from field will now appear as:
From: Fred Reboller <fred@example.com>
|
If system/user/name is NONE or empty, it will not be used.
Finally, some problems in the /ATTACH refinement have been
fixed. Attachments of the form:
send/attach user content [[%file.txt "text message"]]
|
should work properly now. See 2.5.1 notes on SEND for more
information about /ATTACH.
4.8 Miscellaneous Fixes
4.8.1 TYPE? (As used in PARSE)
Fixed the problem reported in the TYPE? function that caused the
datatype error in PARSE. Code of the form below will work
properly now:
parse [34] reduce [type? 34]
parse [34.5] reduce [type? 34.5]
|
4.8.2 MOLD/ALL
Fixed the problem with function molding when /ALL refinement is
provided.
load mold/all context [test: func [arg] [print arg]]
|
4.8.3 FTP
Two fixes:
When connecting to a Microsoft IIS based FTP server Rebol did
not recognize folders correctly. They were marked as type
'directory but no slash was appended to the file name as done
with other types of FTP servers.
In FTP soft-links can now be identified. They can now return an
file type of 'LINK.
Thanks: Cal and Reichart at Prolific.com for submitting the
above FTP fixes.
5. Core 2.5.1
5.1 Source Code Form for Values of NONE, TRUE, etc.
To better support persistent values between SAVE, MOLD, and
LOAD, a new syntactic element has been added to REBOL.
In the past, the source code representation of values like NONE
and TRUE required evaluation in order to convert those words
into their actual values. For example:
would return the word NONE, not the value none. This required
that your code either evaluate the result (with DO, REDUCE, or
TRY) or manually convert the NONE word with code such as:
if value = 'none [value: none]
|
Thus, if you were storing REBOL data using MOLD or SAVE
functions, when you read the data back in, you would need to
either evaluate it (e.g. with REDUCE) or add checks for a few
specific types of words (as shown above).
To better handle this situation with the literal expression of
NONE, TRUE, FALSE, and other values that require evaluation, a
new syntactic form has been added to the language:
Where datatype indicates the datatype and value provides its
value. For simple datatypes such as NONE, TRUE, and FALSE the
shorthand form:
is also allowed. For example:
expresses the value NONE, not the word NONE, even with unevaluated
code or data. Similarly,
express the values of TRUE and FALSE within non-evaluated code.
The LOAD, DO, and other source translating functions have been
expanded to accept this new syntax. The example below helps show
the change:
block: load " none #[none] true #[true] "
foreach value block [print type? value]
word
none
word
logic
|
The literal expression of REBOL objects is also allowed by this
new format. For example the non-evaluated expression:
#[object! [name: "Fred" skill: #[true]]]
|
is equivalent evaluating:
make object! [
name: "Fred"
skill: true
]
|
Thus, a persistent (mold/load symmetric) form of objects now
becomes available to programmers.
To create or save source code or data using these new datatype
expressions, the MOLD and SAVE functions have been given a
new refinement called /ALL. This refinement will output the
new #[] format for necessary values. For example:
mold/all reduce ["Example" true none time]
|
word return the string:
["Example" #[true] #[none] 5-May-2002/9:08:04-7:00]
|
Similarly, using SAVE/ALL would store the above expression
to a file.
5.2 Less Aggressive Evaluation (Important!)
Variables are no longer aggressively evaluated.
In pervious versions of REBOL, variables that held set-words,
parens, paths, and other types of evaluative datatypes would be
evaluated on reference. That is no longer the case.
For example, in earlier versions, if you wrote:
the result would be an evaluation of b/c/d. This evaluation
caused problems because it is more common to reference such
data, not evaluate it. For instance, you want to be able
to write:
data: ["test" A: mold/only (10 + 2.5)]
foreach value data [print value]
|
and smoothly traverse the elements of the data block as simple
values. You would not want those values to self evaluate.
This change to evaluation has some deeper implications. For
example, it affects any function that specifies literal values
within arguments. For example, code such as:
f: func ['word] [print word]
|
The REBOL design definition of a literal function argument is to
accept the argument always as a literal value and NOT evaluate
it. However, in the actual implementation it turned out that an
evaluation would normally occur when the variable was referenced.
(As part of the PRINT in this case.)
For instance, if you passed:
within the function, the reference to the word would cause the
path to be evaluated at that point. Hence, if you referred to
the word argument three times, each time it would be evaluated.
This implicit and "aggressive" evaluation, while interesting, was
not intuitive and created to hard to find errors with difficult
to interpret error messages.
Consider the case where the set-word datatype might be passed
as the argument:
The set word is then evaluated where WORD appeared (in the PRINT
line), and it would require an argument. The code would produce
an error message that would tell you that the set required an
argument. Yet, you would see no set within your code. It would
look like an interpreter flaw, when in fact it was doing
precisely what you asked.
Since the vast majority of REBOL programs do not rely on this
type of evaluation, we've taken it out. This cleans up the
semantics of literal arguments, but it also means that where
programs depend on passing non-literals and assume that
evaluation occurs, they do not. That will break some code, but
it is rare. (For example, in the entire source code base of
REBOL Technologies, there was only one such case.)
5.3 COMPOSE/ONLY Inserts Blocks
The COMPOSE function now has an /ONLY refinement similar to the
INSERT/ONLY refinement. When /ONLY is specified, blocks that
are inserted are inserted only as blocks, not as the elements of
the block (the default). A REDUCE on the block is not required.
For example:
>> block: [1 2 3]
>> compose [example (block)]
== [example 1 2 3]
>> compose [example (reduce [block])]
== [example [1 2 3]]
>> compose/only [example (block)]
== [example [1 2 3]]
|
5.4 REMOVE-EACH - Easy Series Element Removal
The new function REMOVE-EACH works in a similar fashion to
FOREACH and makes removing values from strings, blocks, and
other series much easier.
Also, in most cases REMOVE-EACH is many times faster than using
a WHILE loop and the REMOVE function.
The format of REMOVE-EACH is identical to FOREACH except that
it uses the result of the block expression to determine removal.
REMOVE-EACH iterates over one or more elements of a series and
evaluates a block for each. If the block returns FALSE or NONE,
nothing is removed, but if the block returns any other value,
the items or items are removed.
remove-each value series [expression]
|
Similar to FOREACH, REMOVE-EACH can operate on multiple elements
from the series (and uses the appropriate skip to get to the next
set of elements):
remove-each [val1 val2 val3] series [expression]
|
Note that in addition to modifying the series, REMOVE-EACH also
returns the series as its result.
Here are a number of examples.
To remove the odd numbers from block:
>> blk: [1 22 333 43 58]
>> remove-each item blk [odd? item]
== [22 58]
>> probe blk
== [22 58]
|
To remove all numbers greater than 10 from block:
>> blk: [3 4.5 20 34.5 6 50]
>> remove-each item blk [item > 10]
== [3 4.5 6]
>> probe blk
== [3 4.5 6]
|
To remove all directories from a directory listing:
>> dir: load %.
>> remove-each file dir [#"/" = last file]
== [%calculator.r %clock.r %console.r %find-file.r...]
|
To keep only the directories in the listing:
remove-each file load %. [#"/" <> last file]
|
To remove keep only the .doc files from the listing:
remove-each file load %. [not suffix? ".doc"]
|
Here is an example of a block that uses multiple values:
blk: [
1 "use it"
2 "rebol"
3 "great fun"
4 "the amazing bol"
]
remove-each [num str] blk [odd? num]
remove-each [num str] blk [not find str "bol]
|
REMOVE-EACH also removes characters from a string:
>> str: "rebol is fun to use"
>> remove-each chr str [chr = #"e"]
== "rbol is fun to us"
>> remove-each chr str [find "uno " chr]
== "rblisfts"
|
5.5 ATTEMPT for Error Handling
The ATTEMPT function is a shortcut for the common REBOL idiom:
The format for ATTEMPT is:
ATTEMPT is useful in the cases where you either do not care
about the error result or you want to make simple types of
decisions based on the error.
ATTEMPT returns the result of the block if an error did not
occur. If an error did occur, a NONE is returned.
In the line:
value: attempt [load %data]
|
the value may be set to NONE if the %data file cannot be loaded
(e.g. it's missing or contains an error). This allows you to
write conditional code such as:
if not value: attempt [load %data] [alert "Problem"]
|
Or, even simpler:
value: any [attempt [load %data] 1234]
|
In this line, if the file cannot be loaded, then the value is
set to 1234.
5.6 EXTRACT Function Updated
The EXTRACT function now includes an /INDEX refinement to allow
you to specify what "column" you want to extract. For example:
data: [
10 "fred" 1.2
20 "bob" 2.3
30 "ed" 4.5
]
>> probe extract/index data 3 2
== ["fred" "bob" "ed"]
|
If index is not supplied, then the first column is extracted.
In addition, the extract function has been fixed to properly
extract blocks from a block series.
5.7 SAVE to Memory
The SAVE function can now write its results into memory. This is
useful because the SAVE function contains formatting refinements
that are found no where else.
To use SAVE to write to memory, specify a binary value rather
than a file name. For example:
bin: make binary! 20000 ; (auto expands if necessary)
image: load %fred.gif
save/png bin image
|
Now the BIN binary holds the PNG formatted image. It was not
necessary to write it to a file and read it back in.
5.8 SEND Refinements /Subject /Attach
The SEND function used for sending email has been extended to
easily allow a subject line to be specified with a /SUBJECT
refinement. This is a handy shortcut. For example:
letter: read %letter.txt
send/subject luke@rebol.com letter "Here it is!"
|
The above example will send the text of the letter with a
subject line as specified. If the /SUBJECT refinement is
not given, then the first line of the letter would be used
as the subject.
In addition, the SEND function can now include attachment files
by providing an /ATTACH refinement. A single file or multiple
files can be attached. The specified files can be read from disk
or can be provide as a filename and data. The formats are:
send/attach user letter file
send/attach user letter [file1 file2 ...]
send/attach user letter [[%filename data] ...]
|
You can also combine the last two above formats.
Example attachments are:
user: luke@rebol.com
letter: read %letter.txt
send/attach user letter %example.r
send/attach user letter [%file1.txt %file2.jpg]
send/attach user letter compose/deep [
[%options.txt (mold system/options)]
]
|
5.9 Difference for Date/time
The DIFFERENCE function will now provide the time difference
(hours, minutes, seconds) between two date/time values.
>> difference now 1-jan-2000
== 20561:20:26
|
Normally, when you subtract date/time the result is the number
of days, not time:
>> now - 1-jan-2000
== 856
|
5.10 System Port Added
The system port component was added. This component allows
direct access to various OS-specific features. For example, the
system port can catch Unix and Linux termination signals and
perform a controlled shutdown. Under Win32, this port can be
used to access win-messages.
More information about the System Port component will be
provided as a separate document.
6. Core 2.5.0
6.1 New Sort Function
Several changes and additions have been made to SORT to add
functionality, including reverse sorting, hierarchical sorting
(sorting on more than one field), sorting of only part of a
series, stable sorting (items that are "equal" are not swapped
during sorting), and easier specification of sort criteria
(without the need for a custom comparator function). The
new SORT function is fully backward-compatible.
6.1.1 Terminology
| Record | A single logical item in the series to sort. Usually a
character if the series to sort is a string, or a value if the
series to sort is a block. If the /skip refinement is used then
a record consists of multiple, consecutive elements in the
series.
|
| Field | A part of a record. With the /skip refinement and a
skip length of n a field is one of n elements in the record. If
the /skip refinement is not used and the series to sort is a
block which contains sub-blocks, then a field is one item of a
sub-block (NOT the complete sub-block). This allows field-wise
sorting of blocked records. In all other cases a field is
identical to a record (i.e. each record has exactly one field).
|
| Field offset | An integer specifying the offset of a field
within a record. For a record consisting of n fields a field
offset can be between 1 and n.
|
6.1.2 Arguments
In addition to the series to sort, the new sort action accepts
the following refinements. New behavior is marked with [NEW].
| /case | Sort case-sensitive. This only has an effect for fields of type
string or character.
|
| /skip size | Treat series as records of fixed size. size is of type integer.
|
| /all | Used in combination with the /skip refinement. [NEW] By default only a single
field in a record is used for comparison. If the /all refinement is used then
all fields in a record are used for comparison.
|
| /compare comparator | Specify a custom comparator. This can be a field offset
(type integer [NEW]), a comparator function, or a comparator block [NEW]. See
below.
|
| /reverse | Sort in reverse. [NEW]
|
| /part size | Sort only part of a series. (Similar to the use of the /part
refinement in copy or change [NEW]).
|
6.1.3 Comparators
Sorting is performed by comparing and swapping elements, i.e. comparators
define the sort order. The following comparators are supported:
- No comparator (i.e. no /compare refinement).
In this case the first field in each record is used for
comparison. If the /all refinement is used then all fields in each
record are used for comparison. /case and /reverse are observed normally.
- Field offset (integer) [NEW]. Specifies the field to use for comparison. If the
/all refinement is used as well then the specified field is the first field
to use, and all subsequent fields are used as well. /case and /reverse are
observed normally.
- Function. Function called by the sort action to compare two records. The records
are passed as arguments, and the function needs to return -1, 0 or 1, if the
first record is smaller than, equal to or greather than the second record, respectively. [NEW]
For backward compatibility the function may also return true or false, where true indicates
that the first record is less than or equal to the second record, and false indicates
that the first record is greater than the second record. /case is ignored. /reverse is
observed normally, i.e. /reverse inverts the meaning of the comparator function. If the /skip
refinement is used then the argument passed to the comparison function only consists of the
first field in the record, not the complete record. This is for backward compatibility with
the old sort function. In order to pass the complete record, in a block, use the /all
refinement.
- Block [NEW]. Comparison dialect specifying the type of comparison in more detail. See
below.
Comparison Refinements
The following items can appear in a comparison block:
| field offset (integer) | Specifies the offset of the next field to compare.
Fields are compared in the order specified.
|
| reverse (word) | Sets the comparison for all subsequently specified fields to
reverse.
|
| forward (word) | Sets the comparison for all subsequently specified fields to
forward (opposite of reverse).
|
| case (word) | Makes the comparison for all subsequently specified fields
case-sensitive.
|
| no-case (word) | Makes the comparison for all subsequently specified fields
case-insensitive (opposite of case).
|
| to (word) field offset (integer) | Specifies a range of fields to compare,
e.g. [1 to 5] compares fields one to five.
|
With comparison blocks the /all, /case and /reverse refinements slightly change
their behaviors: /all is equivalent to adding "to max-field" to the end of the
comparison block, i.e. when the end of the comparison block is reached comparison
continues until the end of the record is reached. /case specifies that the default
case mode (until a case or no-case word is reached) is case-sensitive. Otherwise
it is case-insensitive. /reverse reverses the resulting list as a whole, and is
independent of the reverse/forward words in the comparison block.
Examples
>> a: [10 "Smith" "Larry" 20 "Smith" "Joe" 80 "Brown" "Harry" 50 "Wood" "Jim"]
>> sort/skip a 3 ; sorts on the first field (number)
== [10 "Smith" "Larry" 20 "Smith" "Joe" 50 "Wood" "Jim" 80 "Brown" "Harry"]
>> sort/skip/compare a 3 2 ; sorts on the second field (last name)
== [80 "Brown" "Harry" 10 "Smith" "Larry" 20 "Smith" "Joe" 50 "Wood" "Jim"]
>> sort/skip/compare/all a 3 2
; sorts on the second field and following fields (last name and first name)
== [80 "Brown" "Harry" 20 "Smith" "Joe" 10 "Smith" "Larry" 50 "Wood" "Jim"]
>> sort/skip/reverse a 3 ; sorts on the first field (number), in reverse
== [80 "Brown" "Harry" 50 "Wood" "Jim" 20 "Smith" "Joe" 10 "Smith" "Larry"]
>> sort/skip/compare a 3 [2 reverse 3]
; sorts on the last name forward, and the first name in reverse
== [80 "Brown" "Harry" 10 "Smith" "Larry" 20 "Smith" "Joe" 50 "Wood" "Jim"]
|
6.2 File Modes
GET-MODES and SET-MODES functions have been added for file and
network ports. Two new port actions are introduced:
| get-modes | Return current modes for an open port.
|
| set-modes | Change modes for an open port.
|
The get-modes function has the following syntax:
get-modes: native [
{Return mode settings for a port}
target [file! url! block! port!]
modes [word! block!]
]
|
The block being passed in consists of words defining which modes should be queried.
Each word corresponds to one mode. get-modes returns a block which contains pairs
of mode names and current mode settings.
Example:
>> get-modes someport [direct binary]
== [direct: true binary: false]
|
indicating that someport is opened in direct and non-binary (text) mode.
Alternatively a single word can be passed in, in which case get-modes returns
the value directly, without putting it into a name-value block.
Example:
>> get-modes someport 'binary
== false
|
As another alternative a name/value-paired block can be passed in, of the
same format as the block get-modes returns. In that case the values are
ignored.
Example:
>> get-modes someport [direct: none binary: none]
== [direct: true binary: false]
|
The set-modes function has the following syntax:
set-modes: native [
{Change mode settings for a port}
target [file! url! block! port!]
modes [block!]
]
|
The block being passed in consists of name-value pairs describing the modes to be
changed. A block returned by get-modes can be passed as an argument to set-modes.
set-modes returns the port that was passed as an argument.
Example:
>> set-modes someport [direct: false binary: false]
|
The mode block accepted by set-modes is actually an object-style initialization
block and allows multiple names to reference the same value.
Example:
>> set-modes someport [direct: binary: false]
|
6.2.1 Getting Lists of Modes
get-modes supports a few "special" modes, which do not return mode settings
for a specific port, but rather a set of modes that is applicable for a file
(or directory, socket etc.). These are "file-modes", "copy-modes", "network-modes"
and "port-modes". If any of these modes are specified in a get-modes request
then the response contains a block of matching modes which are available on the
current filesystem.
>> get-modes somefileordir 'port-modes
== [direct binary lines no-wait (...a few more...) ]
>> get-modes somefileordir 'file-modes
== [file-note creation-date archived script (...a few more...) ]
>> get-modes someudpsocket 'network-modes
== [broadcast multicast-groups type-of-service]
|
The above example is for an Amiga. Note that the mode block returned by
any of these special requests is identical for all files and directories within a
filesystem (and all sockets within a scheme), i.e. it varies per platform and possibly
per filesystem and scheme, but not per file or socket. The purpose of this feature is
only to provide a mechanism to obtain a list of supported modes, not to obtain the
actual mode settings. To obtain the actual mode settings for a port the returned
block has to be used in another call to get-modes:
>> get-modes somefileordir get-modes somefileordir 'file-modes
== [file-note: "cool graphics" creation-date: 1-Jan-2000
archived: true script: false]
|
The difference between "file-modes" and "copy-modes" is:
| file-modes | Return all modes of the underlying data (typically a file),
regardless of how it was opened.
|
| copy-modes | Same as file-modes, but only return those modes which are safe
to copy, i.e. which can (and should) be included in a set-modes call when
creating a new file, in order to create an exact clone of an existing file. If a
platform provides file properties which are not safe to copy or which necessarily
vary on copied files (e.g. Unix inodes) then those modes would show up in the
block returned by file-modes, but not by copy-modes.
|
Copying all file properties from file1 to file2 can be done with the following
call:
>> set-modes file2 get-modes file1 get-modes file1 'copy-modes
|
6.2.2 Modes Available
File-modes
- status-change-date, modification-date, access-date, backup-date,
creation-date: REBOL date. modification-date is available on all platforms.
status-change-date is available in Unix. access-date is available in Unix
and Windows. creation-date is available in Windows and MacOS. backup-date
is available in MacOS. All modes are settable and gettable, except that
modification-date and access-date are not settable in Elate.
- owner-name, group-name: REBOL string (user/group name). Available in Unix.
- owner-id, group-id: REBOL integer (user/group id). Available in Unix and
AmigaOS (>=V39).
- owner-read, owner-write, owner-delete, owner-execute,
group-read, group-write, group-delete, group-execute,
world-read, world-write, world-delete, world-execute: REBOL logic. All
-read, -write and -execute modes are available in Unix, BeOS, QNX and
Elate. owner-read, owner-write, owner-execute and owner-delete are
available in AmigaOS. All group- and world- modes are available in
AmigaOS >=V39. owner-write is also available in Windows (mapped to the
inverse of the Windows "read-only" bit).
- comment: REBOL string (file comment). Available in AmigaOS only.
- script, archived, system, hidden, hold, pure: REBOL logic (additional
flags). Script, hold and pure are available in AmigaOS only. Archived is
available in AmigaOS and Windows. System and hidden are available in
Windows only.
- type, creator: REBOL string. Available in MacOS only.
Platforms which only support a single file date export it via modification-date.
Similarly, platforms which do not support multi-user file access modes make the
file access modes available via owner-read/write/delete/execute.
Port-modes
- read, write, binary, lines, no-wait, direct: REBOL logic. Binary,
lines and no-wait are settable.
Network-modes
- broadcast: REBOL logic. UDP only. Setting this to true allows sending
broadcasts from a socket. All platforms except BeOS.
- multicast-groups: REBOL block of blocks. UDP only, describes which multicast
groups a socket has joined. Each sub-block consists of two IP addresses
(tuples): the multicast group and the IP address of the interface on which
the multicast group was joined. Typically available in MacOS, Windows, most
Unix platforms, QNX and AmigaOS (Miami/MiamiDx only). Availability is
determined at runtime and varies with the OS version and TCP/IP protocol stack
version.
- type-of-service: REBOL integer. UDP and TCP. This is the value of the
8-bit "TOS" field in IP headers. Typical values are 0 (default), 2 (minimize
cost), 4 (maximize reliability), 8 (maximize throughput) and 16 (minimize
latency), but the interpretation of this field is up to the TCP/IP stack and
intermediate routers, and not enforced by REBOL. All platforms except BeOS.
- keep-alive: REBOL logic. TCP only. Setting this to true forces TCP to send
"keep-alive" packets after a certain period of time (typically 4 hours).
All platforms except BeOS.
- receive-buffer-size, send-buffer-size: REBOL integer. UDP and TCP. Size of
receive and send buffer within the TCP/IP stack. Default values and allowed
ranges vary widely between platforms. Primarily useful for UDP. Increasing
this values usually does NOT improve performance. All platforms except BeOS.
- multicast-interface: REBOL string. UDP only. The default interface to use
for multicasting. Same platforms as multicast-groups.
- multicast-ttl: REBOL integer. UDP only. The time-to-live value (maximum
propagation distance) of multicasts. Same platforms as multicast-groups.
- multicast-loopback: REBOL logic. UDP only. If set to true sent multicasts
are looped back to the local socket. Same platforms as multicast-groups.
- no-delay: REBOL logic. TCP only. Disables the Nagle algorithm. Most
protocols perform better if this is set to false. It should only be set to
true if a protocol is interactive in nature AND relies on precise event
timing in combination with queueing (e.g. X11). All platforms except BeOS.
- interfaces: REBOL block of objects. Each object represents one network
interface and currently contains the following fields: "name": interface
name (on some platforms this is a dummy name). "address": local IP address.
"netmask": subnet mask. "broadcast": broadcast address. "remote-address":
remote IP address for point-to-point interfaces. "flags": a block of
words describing interface properties, currently supported words are
"broadcast" (interface supports broadcasting), "multicast" (interface
supports multicasting), "loopback" (interface is the loopback interface)
and "point-to-point" (interface is a point-to-point interface, as opposed
to a multi-drop interface). Some values may be none (e.g. "remote-address"
on a multi-drop interface). In Windows all interfaces appears as multi-drop
(including PPP), with dummy netmasks. Available in all platforms, except
BeOS, Elate, WinCE. Not settable.
6.2.3 Using File Forks
The /custom refinement to read, open and write allows access to different
forks of a file (currently useful for MacOS only).
open/custom %myfile [fork "name"] ; Specify which fork to open.
|
The specified fork name defines which fork to open:
If no fork is specified (no fork specifier in the custom block or none is
passed instead of "name"), then for non-Mac platforms the file is opened
normally. For Mac the data fork is opened. If the /new refinement is used
then the file size is reset to zero bytes. For Mac this means that all forks
are reset to zero bytes. (Note: this behavior has changed from Core 2.3.
Previously open/new on Macintosh would only reset the size of the data fork,
and there was no way to reset the size of the resource fork.)
If a fork is specified by name then that fork is opened. If the /new refinement
is used then the size of only that fork is reset to zero bytes. If the fork does
not exist (and, for write access, cannot be created) on the current filesystem
then an error is thrown.
Non-Mac platforms only have a single fork named "data". Mac platforms have two
forks, named "data" and "resource".
6.2.4 Finding All Forks
This is done using the mode mechanism, in a way similar to finding all supported
modes.
>> get-modes somefile 'forks
== ["data" "resource"]
|
Example above on Mac. For all other platforms only ["data"] would be returned.
6.3 Serial Port Access
This specification describes the creation and operation of
serial communication ports within REBOL. Serial ports were
supported in version 2.3 but were not documented.
6.3.1 Specifying a Serial Port
Serial ports are created in the same manner as other ports within REBOL.
The scheme name for serial ports is "serial:". URL's are encoded with
the different fields separated by slashes. For example,
port: open serial://port1/9600/8/none/1
|
The order of values in the serial URL scheme is not significant, as the
type of field can be determined by the content. (Note, you can also use
a MAKE PORT object rather than a URL to specify a serial port.)
The specification of a serial port may include the device number, the
communication speed, the number of data bits, the parity and number of
stop bits. The specification information can be specified directly by
setting the appropriate fields within the port specification object or
by creating a URL which contains the same information. Any field not
specified will be given a default value.
The default serial port settings are:
device: port1
speed: 9600
data-bits: 8
parity: none
stop-bits: 1
|
Within a port specification, the various parameters are stored in the following
object fields:
host: device
speed: speed
data-bits: data bits
parity: parity
stop-bits: stop bits
|
The portN specification is an indirect reference to the communication device.
It refers to the Nth device defined in the System/ports/serial block.
This block is initialized by default depending on the system being used and
can be modified in user.r to reflect any local requirements.
For example, on Windows the block might be defined as:
System/ports/serial: [ com1 com2 ]
|
or if COM1 is being used by the mouse, it might just be:
System/ports/serial: [ com2 ]
|
On unix-style systems, the block might be defined as:
System/ports/serial: [ ttyS0 ttyS1 ]
|
or if the first device should correspond to COM2:
System/ports/serial: [ ttyS1 ttyS0 ]
|
Thus, the ports can be specified in a machine indpendent manner while the
machine specific definition can be controlled using the serial definition
block in System/ports/serial.
6.3.2 Operation
Serial ports are always opened as direct ports in much the same way as
console and network ports.
They may be opened as either /STRING or /BINARY with the default being
/STRING.
They are opened by default as asynchronous, but may be made synchronous
by using the /WAIT refinement.
When operating asynchronously, any attempts to copy data from the port
will return NONE if no data is present. When operating synchronously,
the copy will block until data is available.
Data can be written to the port using the INSERT native. Data can be read
from the port using the PICK, FIRST or COPY natives with the usual
ramifications. As usual with direct ports, the REMOVE, CLEAR, CHANGE and
FIND functions are not supported.
The UPDATE function can be used to change port parameters. For example,
to change the speed after an initial connection has been established, you could
just do:
ser-port: open serial://9600
ser-port/speed: 2400
update ser-port
|
Changing the device number or the System/ports/serial and calling UPDATE will have
no effect. Once the port has been opened with a particular device, the device
can't be changed.
There are two additional port fields that can't be set with a URL, but can
be set in a port specification block or by manually changing them.
The RTS-CTS field specifies whether hardware handshaking should be used on
the port. The default is ON. To change the default, do:
ser-port/rts-cts: off
update ser-port
|
A timeout value can be specified by modifying the timeout field in the port
structure. The timeout value only applies to serial ports that are opened
with the /wait refinement. When the timeout expires, a serial port timeout
error will be generated. To set the timeout value do:
ser-port/timeout: 10 ; 10 second timeout
|
Serial ports work properly with the WAIT native.
6.4 Objects
- SYSTEM/LOCALE object added. Currently has month and day names.
*Weekdays are separate strings in system/locale/days.
- CONTEXT function added as a shortcut to MAKE object!.
- You can now QUERY an object. QUERY will return a block containing
the fields that have been modified in an object since its creation or
since it was last passed to QUERY/clear. QUERY will return none if
there have not been any changed fields. QUERY/clear will clear the
modified state of all the fields in an object.
- Objects now accept LOGIC! values as arguments for to pick (for
consistency with blocks).
6.4.1 Make Object Object
You can now make an object out of two other objects, a "template
object" and a "spec object". When making a new object out of two other
objects, the bindings of words coming only from the "spec object" will
be maintained, words shared by both the template object and the spec
object will take their values from the spec object. This will cause
some differences in behavior because the block spec approach is
lexical and the object spec approach is definitional.
6.4.2 Third Object
You can use THIRD on the object to get back a block of set-word value
pairs from the object:
z: make object! [a: 99 b: does [a + 1]]
t: third z
== [a: 99 b: func [][a + 1]]
|
The block returned from THIRD on an object is like an object spec
block, however the set-words are bound to their object. This block is
like a snapshot of the object's values at that time. You can also use
the returned block to set values in the object:
set first t 199
z/b
== 200
|
6.5 Mold and Load Changes
- MOLD/only does not produce the outermost [] in the resulting string.
- Molding a recursive block or object will print [...] when on the
second instance of the recursive item. So, you can now PRINT MOLD SYSTEM !
- Molding strings greater that 50 characters containing unbalanced
"{" characters are now reloadable.
- Added /all refinement to LOAD. LOAD/all of a script does not
evaluate the REBOL header. LOAD/all always returns a block.
- LOAD/next/header results in a block with the evaluated header followed
by the rest of the script as a string.
- Loading strings with CTRL chars greater than CTRL-Z now allowed.
- Added script HEADER/CONTENT field. When set TRUE, the script's entire
source text can be accessed from SYSTEM/SCRIPT/HEADER/CONTENT
(when evaluated with DO) or from the header object (when loaded with
LOAD/header or LOAD/next/header). This allows your script to access
other data that may be part of its script file (e.g. the REBOL archive
format, RIP).
LOAD function refinement combinations:
LOAD/Refinement
|
Eval Header?
|
Returns
|
load
|
yes
|
returns script (data). If file contains a single value (like 1234), then
this returns just that value. If there are multiple values, then it
returns a block.
|
load/next
|
no
|
[first-val { rest of script }] -- returns a value followed by a string.
This refinement lets you parse REBOL files, one value at a time (for
operations like pretty printing and colorizing.)
|
load/next/header
|
yes
|
[header-obj {rest of script}] -- same as load/next but includes the
evaluated header object.
|
load/header
|
yes
|
[header-obj rest of script] -- returns the script, starting with the
REBOL header as the first value.
|
load/all
|
no
|
[all of script as data] -- returns the script, always as a block, even
if it's just a single value (very handy for cases where you always want
data as a block, even if it's a single value).
|
load/next/all
|
no
|
[first-val { rest of script }]
|
load/header/all
|
yes
|
[header-obj rest of script]
|
load/next/header/all
|
yes
|
[header-obj {rest of script}]
|
The ALL refinement will be ignored when other refinements are
present.
6.6 File and Port Changes
- Added asynchronous wait-able DNS for Unix and Windows. For example: open
dns:///async, then insert/wait/copy.
- Asynchronous HTTP better supported. You can open/direct/no-wait
an HTTP request and use WAIT and COPY to receive the results as
they arrive.
- WAIT [0 port] now returns the port if it has data, none otherwise.
- Added WAIT/all refinement, which causes wait to return a block of all
ports that have data.
- The /no-wait refinement allows a port to be opened in non-blocking mode.
COPY on a non-blocking port returns an empty string unless the end of the port
has been reached, in which case it returns none.
- WAIT now supports port handlers (http, tcp etc.) in /direct mode.
- Added AWAKE field in port-specs and root protocol to specify a block or
function called when wait is about to wake up. Used to implement
background processing.
- WAIT works correctly on /lines ports opened without /with.
- TO-LOCAL-FILE and TO-REBOL-FILE functions can be used to convert
to and from the local OS file path formats.
- Added local-port, remote-ip and remote-port fields to port spec for
consistent values independent of port creation.
- MAKE-DIR/deep creates all needed directories in a long path.
- CONNECTED? native for most platforms.
- Fixed incorrect port-id assignment on accepted sockets.
- Fixed bug that would prevent UDP listen sockets from responding to
packets from different origins.
- SPLIT-PATH was modified to properly split the path and target of a
file path.
6.7 Network Protocol Change (APOP, IMAP)
- Added APOP - Authentication for pop:// that does not send passwords to
the server in clear text.
- Added imap:// protocol. URL format and behavior identical to pop://,
plus additional URL formats specified in RFC 2192.
- Fixed SEND when /header and no FROM address is given
- Fixed do-send to change email lines with only a single "." to have two
periods so those emails will not blow out anymore.
6.8 Data Series Changes
- HASH! and LIST! datatypes now offer more complete, consistent, reliable,
and faster operation.
- The SELECT, FIND, UNION, INTERSECT, EXCLUDE, DIFFERENCE, and UNIQUE
functions accept a /skip refinement to specify data size.
- UNIQUE accepts the /case refinement.
- TO-BINARY of tuples now uses the tuple values instead of forming the
tuple.
- JOIN on binary values now joins as binaries, not FORMed strings.
- FIND now works on all types of functions properly.
- FIND/REVERSE works for bitsets.
- Pick on objects and functions with negative number fixed.
- Fixed bug in ENBASE that could cause invalid characters to be
inserted into a base-64-encoded string.
- Removed /only refinement from DIFFERENCE (EXCLUDE is equivalent).
- MINIMUM-OF and MAXIMUM-OF series. You can use MINIMUM-OF and
MAXIMUM-OF on a single series argument which will return the series
offset to the least or greatest contained value respectively. Eg:
minimum-of reduce [pi .099 10 * 100]
== [0.099 1000]
maximum-of reduce [pi .099 10 * 100]
== [1000]
|
6.9 Math Related Changes
- Added CHECKSUM/secure and RANDOM/secure, producing cryptographically
secure checksums and random numbers respectively.
- Added CHECKSUM/hash and CHECKSUM/method (same as checksum/secure, but
with a selectable algorithm: 'md5 or 'sha1), and checksum/key
(calculates a keyed message digest). MD5 added as an alternative
checksum algorithm.
- Subtraction of a date! value months bug fixed.
- Time! values can convert to integers and decimals.
- NOW/precise returns greater precision on time. Useful for timing
events.
6.10 Command Line Changes
- REBOL startup command line now accepts "--" to signal the end of startup
switches. Remaining items on the command line are arguments to be
passed to the REBOL script. This also allows REBOL to start without a
script but with arguments passed.
- When starting from the command line, system/script/args == string of
all args, system/options/args == block of separate args. All items
following the specification of the script are considered arguments.
- REBOL now deals with arbitrary amount of command line arguments-- no
fixed size.
6.11 Console
- Console tab completion now completes as much of the defined word or
file path as possible.
- Added proper console reinitialization code when REBOL is woken up
after Ctrl-Z followed by "fg" (for Unix and shells with job control).
- File name completion in the console is now case-insensitive for
operating systems that have case-insensitive file systems (Windows,
AmigaOS etc.)
- Screen now gets cleared on first console output, not signon message.
6.12 Control
- A BREAK used in the first block of a WHILE will cause a BREAK
from the while loop.
- CATCH and THROW work more reliably in more cases.
- FOREACH returns correct value on empty series.
6.13 Interpreter
- Binding speed greatly improved for top-level words.
- Indefinite extent fixed for many cases (the USE function).
6.14 Other Changes
- HAS function added as a shortcut to define functions with local
variables but no arguments.
- Fixed CONFIRM to throw error on bad pick operation.
7. Interpreter Fixes
The following internal interpreter problems have been fixed.
- Series Expansion: Significant performance and memory problem
has been fixed resulting in many times greater speed in some
types of uses. This change speeds up MOLD and SAVE by many
times.
- Lit-path! comparison works properly
- Time zone bug in date comparison fixed
- Handling of "--" in command line arguments
- Tab expansion of words in console
- Component version numbers added to the boot message
- Increased the global word limit to 8000
- Potential crash during expansion and recycling of hash! values
- Potential crash when recycling open, unreferenced ports
- Port cleanup to close ports in the correct order
8. Networking Fixes
The following fixes were made to networking:
- DNS - Unix only: fixed lockup when DNS helper process dies
unexpectedly.
- DNS - Unix only: DNS helper process no longer remains a
"zombie" if the main process is killed.
- FTP - conflicts with generic proxy setups fixed
- FTP - allow more response codes from CWD command in FTP
- HTTP - proxy authentication added
- HTTP - POST linefeed conversion problem fixed
- HTTP - forwarding fixed where host name in header was not updated
- POP - will try APOP if port/algorithm is set to 'apop (workaround for bug in some POP servers).
- TCP - On Windows only: TCP listen sockets no longer allow multiple
listeners on the same port. Workaround for bug in Windows TCP/IP
stack regarding SO_REUSEADDR.
9. Other Function Fixes
Fixes to natives and functions include:
- COMPRESS/DECOMPRESS - series offsets are now allowed
- DEBASE - potential crash fixed
- DEBASE - series offsets are now allowed
- FIND - when using bitset with chars greater than 127
- FIND/MATCH/CASE - fixed
- LOAD/MARKUP - potential crash fixed
- MAKE - potential crash with make object! object! fixed
- MAKE-DIR/DEEP - fixed bug
- SET-MODES - fixed file date setting when no time value is provided
- SORT - handles hashed blocks now, and potential crashes fixed
- UNION, INTERSECT, etc. - series offsets are now allowed on the second argument
| REBOL/MakeDoc 2.0 | REBOL is a registered trademark of REBOL Technologies Copyright 2003 REBOL Technologies | 6-Aug-2003 |
|