REBOL
Docs Blog Get-it

REBOL/Core 2.5 Changes

First Release: March 2001

Back to REBOL Change Logs

Contents

Core 2.5.6
Command Line Startup (Fixes CGI/shell scripts)
Implied Quit
Corrupt Datatype Failure
Help Native! Fixed
Get on NONE
Set-Browser-Path
DO On Command Line
FIND/Any Bug Fixed.
Molding Empty File Names
Core 2.5.5
Main Purpose
New Core License
Startup Files (user.r and rebol.r)
How Scripts are Started
Command Line Terminator (CR)
Changes to SECURE
MOLD/Flat Refinement
Truncation of Series Index (when Past Tail)
AT on PORTs
Added SIXTH Through TENTH Functions
Lines Longer Than 4 KB in Direct/Lines Mode
DECODE-CGI Handles Duplicate Names
ALTER Fixed
Network Errors in TRY (Net-Error Throw)
Extended FTP Directory Paths
STATS for SYSTEM/STATS
PURL Captured
Core 2.5.3
Credits
MAKE-DIR Rewritten
New Bitset Functions: CLEAR, LENGTH?, EMPTY?
Changes to SKIP Function
ARRAYs Initialized with Block Values
Added PARSE BREAK Word
Fix to OPEN on Network Ports
Fixed Crash on Modified Functions
CHANGE Accepts Any Type Value
Unset Object Variables (on Exit)
Added BUILD-MARKUP Function
Revised BUILD-TAG Function
Revised DECODE-CGI Function
UNPROTECT Fixed
ALTER added to Core
SYSTEM Word Protected
Error Message for Word Context
Fixed Crash on Future Dates
Core 2.5.2
CONSTRUCT Object Creator
LOAD Change (Important)
HELP Expanded
SUFFIX? Function Added
SIGN? Function Added
COMPONENT? Function Added
SEND Function Updated
Miscellaneous Fixes
TYPE? (As used in PARSE)
MOLD/ALL
FTP
Core 2.5.1
Source Code Form for Values of NONE, TRUE, etc.
Less Aggressive Evaluation (Important!)
COMPOSE/ONLY Inserts Blocks
REMOVE-EACH - Easy Series Element Removal
ATTEMPT for Error Handling
EXTRACT Function Updated
SAVE to Memory
SEND Refinements /Subject /Attach
Difference for Date/time
System Port Added
Core 2.5.0
New Sort Function
Terminology
Arguments
Comparators
File Modes
Getting Lists of Modes
Modes Available
Using File Forks
Finding All Forks
Serial Port Access
Specifying a Serial Port
Operation
Objects
Make Object Object
Third Object
Mold and Load Changes
File and Port Changes
Network Protocol Change (APOP, IMAP)
Data Series Changes
Math Related Changes
Command Line Changes
Console
Control
Interpreter
Other Changes
Interpreter Fixes
Networking Fixes
Other Function Fixes

Core 2.5.6

Miscellaneous fixes made during the version 2.5.6 releases of the /SDK, /Command, and /SDK/Command products.

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.

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.

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.

Help Native! Fixed

Requesting HELP on NATIVE! has been fixed (the native! word has been restored).

Get on NONE

A GET of NONE is now allowed and will return NONE.

print get 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.

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

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]

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:

find/any next "abc" "d"

returned "c". This problem has been fixed.

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.

Core 2.5.5

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.

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.

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:

  1. Check the current directory first.
  2. 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.

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.

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.

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:

rebol +s script.r

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

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
]
]
]

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

AT on PORTs

The AT function (similar to the SKIP function) now works for the Port datatype.

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"]

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.

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"]]

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.

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.

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:

/home/luke/

but you want to refer to:

/var/log/

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.)

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.

PURL Captured

The variable PURL used in DECODE-URL is now a local variable rather than a global.

Core 2.5.3

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

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.)

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.

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

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.

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]]]

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)
    ]
]

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.

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.

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]

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
]

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>"

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">}

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!

UNPROTECT Fixed

Attempting to UNPROTECT a block containing any value other than a word could cause a crash. Now non-word values are ignored.

ALTER added to Core

The ALTER function found only in View is general purpose and has been made available in all version of REBOL.

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.

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.

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.

Core 2.5.2

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 /WITH refinement. The example below would use an existing object called standard-prefs as the template.

prefs: construct/with 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.

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.

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:

help system

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:

help system/options

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:

help "to-"

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.

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://code.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
    ]
]

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]

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."]

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.

Miscellaneous Fixes

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]

MOLD/ALL

Fixed the problem with function molding when /ALL refinement is provided.

load mold/all context [test: func [arg] [print arg]]

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.

Core 2.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:

load "NONE"

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:

#[datatype value]

Where datatype indicates the datatype and value provides its value. For simple datatypes such as NONE, TRUE, and FALSE the shorthand form:

#[word]

is also allowed. For example:

#[none]

expresses the value NONE, not the word NONE, even with unevaluated code or data. Similarly,

#[true]
#[false]

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 #[???none] in docs/changes-2-5.txt 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.

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:

a: first [b/c/d]
print a

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:

f a/b/c

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:

f test:

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.)

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]]

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"

ATTEMPT for Error Handling

The ATTEMPT function is a shortcut for the common REBOL idiom:

error? try [block]

The format for ATTEMPT is:

attempt [block]

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 [make-dir %fred]

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.

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.

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.

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)]
]

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

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.

Core 2.5.0

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.

Terminology

RecordA 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.
FieldA 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 offsetAn 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.

Arguments

In addition to the series to sort, the new sort action accepts the following refinements. New behavior is marked with New!.

/caseSort case-sensitive. This only has an effect for fields of type string or character.
/skip sizeTreat series as records of fixed size. size is of type integer.
/allUsed 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 comparatorSpecify a custom comparator. This can be a field offset (type integer New!), a comparator function, or a comparator block New!. See below.
/reverseSort in reverse. New!
/part sizeSort only part of a series. (Similar to the use of the /part refinement in copy or change New!).

Comparators

Sorting is performed by comparing and swapping elements, i.e. comparators define the sort order. The following comparators are supported:

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] in docs/changes-2-5.txt 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"]

File Modes

GET-MODES and SET-MODES functions have been added for file and network ports. Two new port actions are introduced:

get-modesReturn current modes for an open port.
set-modesChange 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]

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-modesReturn all modes of the underlying data (typically a file), regardless of how it was opened.
copy-modesSame 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

Modes Available

File-modes

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

Network-modes

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".

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] in docs/changes-2-5.txt would be returned.

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.

Specifying a Serial Port

Serial ports are created in the same manner as other ports within REBOL. The scheme name for serial ports is "seria". 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.

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.

Objects

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.

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

Mold and Load Changes

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] in docs/changes-2-5.txt -- 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] in docs/changes-2-5.txt -- same as load/next but includes the evaluated header object.

       

load/header

yes

[???header-obj] in docs/changes-2-5.txt -- returns the script, starting with the REBOL header as the first value.

       

load/all

no

[???all] in docs/changes-2-5.txt -- 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] in docs/changes-2-5.txt

       

load/header/all

yes

[???header-obj] in docs/changes-2-5.txt

       

load/next/header/all

yes

[???header-obj] in docs/changes-2-5.txt

       

The ALL refinement will be ignored when other refinements are present.

File and Port Changes

Network Protocol Change (APOP, IMAP)

Data Series Changes

minimum-of reduce [pi .099 10 * 100]
== [0.099 1000]   

maximum-of reduce [pi .099 10 * 100]
== [1000]

Math Related Changes

Command Line Changes

Console

Control

Interpreter

Other Changes

Interpreter Fixes

The following internal interpreter problems have been fixed.

  1. 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.
  2. Lit-path! comparison works properly
  3. Time zone bug in date comparison fixed
  4. Handling of "--" in command line arguments
  5. Tab expansion of words in console
  6. Component version numbers added to the boot message
  7. Increased the global word limit to 8000
  8. Potential crash during expansion and recycling of hash! values
  9. Potential crash when recycling open, unreferenced ports
  10. Port cleanup to close ports in the correct order

Networking Fixes

The following fixes were made to networking:

  1. DNS
    Unix only: fixed lockup when DNS helper process dies unexpectedly.
  2. DNS
    Unix only: DNS helper process no longer remains a "zombie" if the main process is killed.
  3. FTP
    conflicts with generic proxy setups fixed
  4. FTP
    allow more response codes from CWD command in FTP
  5. HTTP
    proxy authentication added
  6. HTTP
    POST linefeed conversion problem fixed
  7. HTTP
    forwarding fixed where host name in header was not updated
  8. POP
    will try APOP if port/algorithm is set to 'apop (workaround for bug in some POP servers).
  9. 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.

Other Function Fixes

Fixes to natives and functions include:

  1. COMPRESS/DECOMPRESS
    series offsets are now allowed
  2. DEBASE
    potential crash fixed
  3. DEBASE
    series offsets are now allowed
  4. FIND
    when using bitset with chars greater than 127
  5. FIND/MATCH/CASE
    fixed
  6. LOAD/MARKUP
    potential crash fixed
  7. MAKE
    potential crash with make object! object! fixed
  8. MAKE-DIR/DEEP
    fixed bug
  9. SET-MODES
    fixed file date setting when no time value is provided
  10. SORT
    handles hashed blocks now, and potential crashes fixed
  11. UNION, INTERSECT, etc.
    series offsets are now allowed on the second argument
About | Contact | PrivacyREBOL Technologies 2024