Functions

_images/unicon.png

Index Unicon

Unicon has a large repertoire of built-in functions.

A function is equivalent to a user defined procedure, in terms of syntax, argument management, and semantics.

Functions cover a wide range of usage; from initializing data structures (list and table, for instance) to adding utility to Unicon (left and right formatting), to supporting Execution Monitoring, and graphics, along with many other operations and system services that make Unicon what it is.

Unicon Functions

There are 310 functions built into Unicon (as of 2016-08-20), but no builds will include all of them, as some few are platform dependent. This list includes all core and all optional functions that can be part of Unicon.

Note

A lot of the reference material here is courtesy of Programming with Unicon, Second edition; by Clinton Jeffery, Shamim Mohamed, Jafar Al Gharaibeh, Ray Pereda, Robert Parlett.

That book ships with the Unicon sources in the doc/book/ subdirectory.

Abort

Abort()
Type:pattern
Versionadded:Unicon 13.

A SNOBOL inspired pattern matching operation. Causes immediate match failure, no further alternatives are attempted.

#
# Abort.icn, demonstrate SNOBOL style pattern match abort
#
procedure main()
    write("match a or b, but abort (fail) if 1 is found first")
    pat := Any("ab") .| "1" || Abort()
    tests := ["ab1", "b1a", "1ab", "xzyab1", "xzy1ba"]
  
    every s := !tests do
        if s ?? pat then
            write(s || " matched") else write(s || " aborted")
end

examples/Abort.icn

Sample run:

match a or b, but abort (fail) if 1 is found first
ab1 matched
b1a matched
1ab aborted
xzyab1 matched
xzy1ba aborted

abs

abs(n : number) → number
Type:number, integer or real
Parameters:n – numeric value
Returns:absolute value

The absolute value function. Produces the maximum of n and -n, |n|.

#
# abs.icn, demonstrate the absolute value function
#
procedure main()
    p := 1
    n := -1
    r := -1.23
    write(p, ", abs(", p, ") = ", abs(p)) 
    write(n, ", abs(", n, ") = ", abs(n)) 
    write(r, ", abs(", r, ") = ", abs(r)) 
end

examples/abs.icn

Sample run:

1, abs(1) = 1
-1, abs(-1) = 1
-1.23, abs(-1.23) = 1.23

acos

acos(r : real) → real
Type:real
Parameters:r – real, -1 \leq r \leq 1
Returns:arc cosine of r, arccos(r)

Produces the inverse cosine of r, result in \mathrm{radians}.

“arc” is an abbreviation of “arcus”, inverse circular.

#
# acos.icn, demonstrate the the arc cosine function
#
procedure main()
    write("Arc Cosine: Domain -1 <= x <= 1; result in radians")
    every r := -1.0 to 1.0 by 0.25 do {
        write(left("acos(" || trim(left(r, 6)) || ")", 12),
              " = ", acos(r))
    }
end

examples/acos.icn

Sample run:

Arc Cosine: Domain -1 <= x <= 1; result in radians
acos(-1.0)   = 3.141592653589793
acos(-0.75)  = 2.418858405776378
acos(-0.5)   = 2.094395102393196
acos(-0.25)  = 1.823476581936975
acos(0.0)    = 1.570796326794897
acos(0.25)   = 1.318116071652818
acos(0.5)    = 1.047197551196598
acos(0.75)   = 0.7227342478134157
acos(1.0)    = 0.0

Todo

fix plot range and domain handling

Graphical plot:

#
# plot-function, trigonometric plotting, function from command line
#
$define points 300
$define xoff   154
$define base   164
$define yscale 60
$define xscale 100

invocable "asin", "acos", "atan"

# plot the given function, default to sine
procedure main(args)
    func := map(args[1]) | "acos"
    if not func == ("asin" | "acos" | "atan") then func := "acos" 

    # range of pixels for 300 points, y scaled at +/- 60, 4 pixel margins
    &window := open("Plotting", "g", "size=308,168", "canvas=hidden")

    # tan may cause runtime errors
    if func == "atan" then &error := 6

    color := "vivid orange"
    Fg(color)
    write(&window, "\n " || func)

    Fg("gray")
    DrawLine(2, base, 306, base)
    DrawLine(xoff, 2, xoff, 164)
    #DrawString(8, 10, "1.5+", 8, 69, "0", 2, 126, "-1.5-")
    DrawString(xscale / 2 + 2, 160, "-1.0")
    DrawString(points - (xscale / 2) - 2, 160, "1.0")

    Fg(color)
    step := 2.0 / points
    every x := -1.0 to 1.0 by step do {
        DrawPoint(xoff + (x * xscale), base - (yscale * func(x)))
    }
    WSync()
    WriteImage("../images/plot-" || func || ".png")
    close(&window)
end

examples/plot-arccos.icn

prompt$ unicon -s plot-arccos.icn -x acos
_images/plot-acos.png

images/plot-acos.png

See also

asin, atan, sin, cos, tan


Active

Active() : window

Active() produces a Window value that has one or more events pending. If there are no events pending, Active() will block and wait. Active() produces different windows on each call to help ensure windows are serviced and don’t starve for attention.

#
# Active.icn, demonstrate active event testing
#
link enqueue, evmux
procedure main()
    window := open("Active sample", "g", "size=90,60", "canvas=hidden")
    Enqueue(window, &lpress, 11, 14, "", 2)
    Enqueue(window, &lrelease, 12, 15, "", 3)
    w := Active()
    write(image(w))
    e := Event(w, 1)
    write("event ", e, " at ", &x, " ", &y)
    e := Event(w, 1)
    write("event ", e, " at ", &x, " ", &y)
    close(window)
end

examples/Active.icn

Sample run:

prompt$ unicon -s Active.icn -x
window_1:1(Active sample)
event -1 at 11 14
event -4 at 12 15

Alert

Alert() → window
Type:window

Produces a visual flash or audible sound to signal notable events.

Alert() : window

Alert() produces a visual flash or audible sound to signal notable events.

#
# Alert.icn, visual/audible alert
#
link ximage
procedure main()

    # Alert needs to have a default window, &window needs to be non null
    write("Expect an error 140")
    &error := 1
    w := Alert()
    write("Error ", &errornumber, ": ", &errortext)

    # now Alert will have a resource to use
    &window := open("title", "g", "canvas=hidden")
    w := Alert()
    write(ximage(w))
    close(&window)
end

examples/Alert.icn

Sample run:

Expect an error 140
Error 140: window expected
window_1:1(title)

any

any(c, s, i, i) : integer or fail

any() is a string scanning function that produces the first index, i1 + 1, if s[i1:i2][1] is in the cset c. It fails otherwise. Match this character to any of the characters in the cset.

s defaults to &subject and the indexes default to the character at &pos.

#
# any.icn, demonstrate string scanning any() function
#
procedure main()
    str := "ABCdef"
    str ? any(&lcase) & write("Match lower case true")
    str ? any(&ucase) & write("Match upper case true")
end

examples/any.icn

Sample run:

Match upper case true

Any

Any(c) : pattern

Any(c) is the SNOBOL pattern that any is based on. Produces a Pattern that matches the next subject character if it appears in the cset.

#
# Any.icn, demonstrate the SNOBOL based pattern Any() function
#
procedure main()
    str := "ABCdef"
    ups := Any(&ucase)
    write("Type of ups: ", type(ups))
    str ?? ups -> intermediate
    write(intermediate)
end

examples/Any.icn

Sample run:

Type of ups: pattern
A

Arb

Arb() : success

Arb() is part of the SNOBOL inspired pattern feature set. Matches an arbitrary number of characters from the subject string. Arb() matches the shortest possible substring, which includes the empty string. Patterns on either side of Arb() determine what is actually matched.

#
# Arb.icn, demonstrate Arb() SNOBOL, always succeeds matching
#
procedure main()
    sub := "This is a test"
    pat := "This" || Arb() -> inter || "a test"
    write(sub ?? pat)
    write((sub[1:-2] ?? pat) | "no match")
    sub ?? pat; write(inter)
end

examples/Arb.icn

Sample run:

This is a test
no match
 is

Arbno

Arbno(pat) : string

Arbno() matches an arbitrary number of the pattern pat, including zero matches.

#
# Arbno.icn, demonstrate Arbno() SNOBOL pattern 
#
procedure main()
    sub := "This is is is a test"
    pat := "This" || Arbno(" is") -> inter || " a test"
    sub ?? pat
    write(inter)
end

examples/Arbno.icn

Sample run:

 is is is

args

args(x, i) : any

args(p) produces the number of arguments expected by procedure p. This is sometimes referred to as the arity of a function. For variable argument prototypes, args(p) will return a negative number, representing the final list argument position. E.g.

procedure sample(x, y, z[])
    write(args(sample))
end

In that case, args(sample) returns -3.

args(C) produces the number of arguments in the current instance of co-expression C. args(C, i) produces the ith argument within co-expression C.

#
# args.icn, Demonstrate the args arity function
#
procedure main()
    write("args for main: ", args(main))
    write("args for subproc: ", args(subproc))
    subproc()
    coex := create subproc()
    write("args for co-expression (subproc): ", args(coex))
    @coex
end

procedure subproc(a:string:"Hello", b:integer:5)
    write(a, ", ", b)
end

examples/args.icn

Sample run:

args for main: 0
args for subproc: 2
Hello, 5
args for co-expression (subproc): 2
Hello, 5

args as common main argument

Of special note with args. Historically, many Unicon programs have defined main as

procedure main(args)

That definition will hide the args built-in function. When maintaining such a program, a developer can either rename the list variable passed into main (and all references), or fallback to using proc to retrieve the built-in function.

procedure main(args)
    write("arity of main: ", proc("args", 0)(main))
end

array

Attention

multi-dimensional array referencing is a pending feature

array() : array

array() produces an efficient list of homogeneous numeric data (integer or real).

#
# array.icn, Demonstrate a single dimensional numeric array allocation
#
link ximage
procedure main()
    # allocate an array of integers, default 42
    a := array(6, 42)
    write(type(a), " is ", ximage(a))
    write("a[5] = ", a[5])
    every i := 1 to 10 do a[i] := i
    write("a[5] = ", a[5])

    r := array(6, 42.0)
    write(type(r), " is ", ximage(r))
    write("r[5] = ", r[5])
    every i := 1 to 10 do r[i] := real(i)
    write("r[5] = ", r[5])
end

examples/array.icn

Sample run:

list is L1 := list(6,42)
a[5] = 42
a[5] = 5
list is L5 := list(6,42.0)
r[5] = 42.0
r[5] = 5.0

asin

asin(r) : real

asin(r) produces the arc sine of the angle r, given in radians as a real.

#
# asin.icn, demonstrate the asine function
#
procedure main()
    write("asin(r): -pi/2 to pi/2, Range: -1.0 <= x <= 1.0")
    every r := -1.0 to 1.0 by 0.25 do {
        write(left("asin(" || r || ")", 24), " = ", asin(r), " radians")
    }
end

examples/asin.icn

Sample run:

asin(r): -pi/2 to pi/2, Range: -1.0 <= x <= 1.0
asin(-1.0)               = -1.570796326794897 radians
asin(-0.75)              = -0.848062078981481 radians
asin(-0.5)               = -0.5235987755982989 radians
asin(-0.25)              = -0.2526802551420786 radians
asin(0.0)                = 0.0 radians
asin(0.25)               = 0.2526802551420786 radians
asin(0.5)                = 0.5235987755982989 radians
asin(0.75)               = 0.848062078981481 radians
asin(1.0)                = 1.570796326794897 radians

Graphical plot:

#
# plot-function, trigonometric plotting, function from command line
#
$define points 300
$define xoff   154
$define base   64
$define yscale 60
$define xscale 100

invocable "asin", "acos", "atan"

# plot the given function, default to sine
procedure main(args)
    func := map(args[1]) | "asin"
    if not func == ("asin" | "acos" | "atan") then func := "asin" 

    # range of pixels for 300 points, y scaled at +/- 60, 4 pixel margins
    &window := open("Plotting", "g", "size=308,128", "canvas=hidden")

    # tan may cause runtime errors
    if func == "atan" then &error := 6

    color := "vivid orange"
    Fg(color)
    write(&window, "\n " || func)

    Fg("gray")
    DrawLine(2, base, 306, base)
    DrawLine(xoff, 2, xoff, 126)
    DrawString(8, 10, "1.5+", 8, 69, "0", 2, 126, "-1.5-")
    DrawString(xscale / 2 + 2, 76, "-1.0")
    DrawString(points - (xscale / 2) - 2, 76, "1.0")

    Fg(color)
    step := 2.0 / points
    every x := -1.0 to 1.0 by step do {
        DrawPoint(xoff + (x * xscale), base - (yscale * func(x)))
    }
    WSync()
    WriteImage("../images/plot-" || func || ".png")
    close(&window)
end

examples/plot-arcfunction.icn

prompt$ unicon -s plot-arcfunction.icn -x asin
_images/plot-asin.png

images/plot-asin.png

See also

acos, atan, sin, cos, tan


atan

atan(r, r:1.0) : real

atan(r) produces the arc tangent of r. atan(r1, r2) produces the arc tangent of r1 and r2. Arguments and given in radians.

#
# atan.icn, demonstrate the atan function
#
procedure main()
    write("atan(r): -pi/2 to pi/2, Range: -1.0 <= x <= 1.0")
    every r := -1.0 to 1.0 by 0.25 do {
        write(left("atan(" || r || ")", 24), " = ", atan(r), " radians")
    }
end

examples/atan.icn

Sample run:

prompt$ unicon -s atan.icn -x
atan(r): -pi/2 to pi/2, Range: -1.0 <= x <= 1.0
atan(-1.0)               = -0.7853981633974483 radians
atan(-0.75)              = -0.6435011087932844 radians
atan(-0.5)               = -0.4636476090008061 radians
atan(-0.25)              = -0.2449786631268641 radians
atan(0.0)                = 0.0 radians
atan(0.25)               = 0.2449786631268641 radians
atan(0.5)                = 0.4636476090008061 radians
atan(0.75)               = 0.6435011087932844 radians
atan(1.0)                = 0.7853981633974483 radians
_images/no-image.png

images/no-image.png


atanh

atanh(r) : real

atanh(r) produces the inverse hyperbolic tangent of r. Argument given in radians.

#
# atanh.icn, demonstrate the atan function
#
procedure main()
    write("atanh(r): -pi/2 to pi/2, Range: -1.0 <= x <= 1.0")
    every r := -1.0 to 1.0 by 0.25 do {
        write(left("atanh(" || r || ")", 24), " = ", atanh(r), " radians")
    }
end

examples/atanh.icn

Sample run:

prompt$ unicon -s atanh.icn -x
atanh(r): -pi/2 to pi/2, Range: -1.0 <= x <= 1.0
atanh(-1.0)              = -inf.0 radians
atanh(-0.75)             = -0.9729550745276566 radians
atanh(-0.5)              = -0.5493061443340548 radians
atanh(-0.25)             = -0.2554128118829954 radians
atanh(0.0)               = 0.0 radians
atanh(0.25)              = 0.2554128118829954 radians
atanh(0.5)               = 0.5493061443340548 radians
atanh(0.75)              = 0.9729550745276566 radians
atanh(1.0)               = inf.0 radians

Todo

plot image of atanh


Attrib

Attrib(T, i, x,...) : any [Concurrency]

Attrib() read/write thread attributes for thread handle T.

#
# Attrib.icn, Demonstrate thread attributes
#
# requires Concurrency build of Unicon
#
$include "threadh.icn"
import threads

global pT, cT

procedure main()
    # spin up the producer, then await completion
    pT := thread producer()
    wait(pT)
    
    # spin up the consumer, then await completion
    cT := thread consumer(pT)
    wait(cT)

    write("main complete")
end

procedure producer()
    write("pT OUTBOX_SIZE: ", Attrib(pT, OUTBOX_SIZE))
    Attrib(pT, OUTBOX_LIMIT, 3)

    # send 10 numbers, but limit is 3, non blocking
    write("producer sending")
    every !10@>
    write("pT OUTBOX_SIZE: ", Attrib(pT, OUTBOX_SIZE))
end

procedure consumer(T)
    write("consumer receiving from producer public outbox")
    while write(<@T)
end

examples/Attrib.icn

Sample run:

pT OUTBOX_SIZE: 0
producer sending
pT OUTBOX_SIZE: 3
consumer receiving from producer public outbox
1
2
3
main complete

Bal

Bal() : type [Patterns]

Bal() SNOBOL style balanced parentheses pattern match

#
# Bal.icn, demonstrate the SNOBOL style balanced parentheses pattern
#
procedure main()
    pat := Len(2) || Bal() -> b || Rem() -> r
    write(image(pat))

    tests := ["a=(b*c)+d", "a=b*c+d", "a=()+d"]
    every subject := !tests do {
        write("Matching     : ", subject)
        subject ?? pat
        write("balanced part: ", b)
        write("remainder    : ", r)
    }
end

examples/Bal.icn

Sample run:

pattern_6(7) = Len(2) || (Bal()) -> b || (Rem()) -> r
Matching     : a=(b*c)+d
balanced part: (b*c)
remainder    : +d
Matching     : a=b*c+d
balanced part: b
remainder    : *c+d
Matching     : a=()+d
balanced part: ()
remainder    : +d

bal

bal(c1:&cset, c2:')', c3:')', s, i1, i2) : integer*

bal() is a string scanning function that generates the integer positions in s where a member of c1 in s[i1:i2] is balanced with respect to c2 and c3.

#
# bal.icn, demonstrate the string scanning bal() function
#
procedure main()
    L := list()
    s := "(1 + 2) * ((3 + 4) * 5) - 6"
    carets := repl(" ", *s)

    # simple
    write("scanning: ", image(s), " with bal()")
    s ? every write(bal())

    # nicely formatted for visual effect
    s ? every carets[bal()] := "^"
    write()
    write(s)
    write(carets)
end

examples/bal.icn

Sample run:

scanning: "(1 + 2) * ((3 + 4) * 5) - 6" with bal()
1
8
9
10
11
24
25
26
27

(1 + 2) * ((3 + 4) * 5) - 6
^      ^^^^            ^^^^

Bg

Bg(w, s) : string

Bg(w) retrieves the background colour of the window, w. Bg(w, s) attempts to set the background colour by name, rgb or mutable colour value. Fails if the background cannot be set to the specified colour.

#
# Bg.icn, demonstrate background colour settings
#
procedure main()
    window := open("Bg example", "g", "size=110,75", "canvas=hidden")
    write(window, Bg(window))
    Bg(window, "vivid orange")
    write(window, Bg(window))
    Bg(window, "10000,20000,30000")
    write(window, Bg(window))
    Bg(window, "transparent green")
    write(window, Bg(window))
    if c := NewColor(window, "40000,50000,60000") then { 
        Bg(window, c)
        write(window, Bg(window))
    }
    else {
        Bg(window, "white")
        write(window, "no mutable colours")
    }
    WSync(window)
    WriteImage(window, "../images/Bg.png")
    FreeColor(\c)
    close(window)
end

examples/Bg.icn

Sample run:

prompt$ unicon -s Bg.icn -x
_images/Bg.png

images/Bg.png


Break

Break(c) : string? [Patterns]

Break(c) matches any characters in the subject string up to but not including any of the characters in the cset c.

#
# Break.icn, demonstrate the Break pattern match
#
procedure main()
    s := "integers"
    s ?? Break('e') -> found
    write("Matched: ", found)
end

examples/Break.icn

Sample run:

Matched: int

See Breakx.


Breakx

Breakx(c) : string?

Breakx(c) is an extended Break. It will match any characters in the subject string up to any of the subject characters in the Cset, c. Breakx will search beyond the break position for any possible longer match if resumed due to subsequent pattern failure. This means that Breakx might return characters in c, unlike the Break that will not.

#
# Breakx.icn, demonstrate the extended Break pattern match
#
procedure main()
    # this Break match stops at the first "e"
    s := "integers"
    s ?? Break("e") -> found || "er"
    write("Matched: ", found)

    # this Breakx match tries twice, a second "e" is followed by "er"
    s ?? Breakx("e") -> found || "er"
    write("Matched: ", found)
end

examples/Breakx.icn

Sample run:

Matched: g
Matched: integ

See Break.


callout

callout() : type

Todo

entry for function callout

callout()

examples/callout.icn

Sample run:


center

center(s, i:1, s2:" ") : string

center() produces a centred string, s within width i, padded on either side by s2. If i is less than the size of s, the centre i characters of s are produced.

#
# center.icn, Demonstrate string centring.
#
procedure main()
    s := " this is a test "
    write(center(s, 64, "="))
    write(center("center(s,8) of " || image(s) || " is " ||
          image(center(s, 8)), 64))
end

examples/center.icn

Sample run:

======================== this is a test ========================
        center(s,8) of " this is a test " is "s is a t"

char

char(i) : string

char() produces a string consisting of the character encoded by the integer i. Unicon is ASCII based. char(0) is the null byte, the first ASCII character, and anything outside of the range 0-255 will cause a runtime error.

#
# char.icn, demonstrate the char() function.
#
procedure main()
    write(image(char(0)))
    write(image(char(1)))
    write(char(65))
    # run-time error, out of range
    write(image(char(257)))
end

examples/char.icn

This sample run fails with a runtime error when asking for char(257), an out of range integer.

"\x00"
"\x01"
A

Run-time error 205
File char.icn; Line 16
invalid value
offending value: 257
Traceback:
   main()
   char(257) from line 16 in char.icn

chdir

chdir(s) : string

chdir(s) changes the current working directory to s. s will be operating system dependent. chdir() produces the current working directory as a string

#
# chdir.icn, change and return current working directory
#
procedure main()
    write(chdir())
    chdir("..")
    write(chdir())
end

examples/chdir.icn

Sample run:

/home/btiffin/wip/writing/unicon/examples
/home/btiffin/wip/writing/unicon

chmod

chmod(f, m) : ?

chmod() changes a file access mode. f can be a string name or open file handle. Mode m is encoded with +/- (permit/deny)

  • r, read
  • w, write
  • x, execute

Who can access is also encoded by

  • u, user, (owner) of the file
  • g, group membership of the file
  • o, other
  • a, all

Mode bits also include

  • s, setuid or setgid for allowing the process to assume a uid/gid when executing the resource
  • t, sticky bit. Asks the kernel to retain the process image in memory when executing the resource terminates. Sticky bits on the directory prevents renaming, moving or deleting the files in the directory if not the owning user.

POSIX also allows a numeric, octal value for mode settings. rwx as bit 2, 1, 0 of an octal value. 8r7 being 2r111, rwx, 8r5 being 2r101, rx, no w, and 8r0 is no permission in that grouping. Values are by owner, group and other, 3 octal digits. 8r707 is rwx for user, no group access, rwx for other. A poor example; not sharing with friends, but allowing outsiders.

#
# chmod.icn, Demonstrate chmod, the file access permission function
#
procedure main()
    # set "other" read permissions
    # others outside owner (u) and group (g)
    file := "chmod.icn"
    write("chmod call: ", image(chmod(file, "o+r")))
    
    write("mode of ", file, " ", stat(file).mode)
end

examples/chmod.icn

Sample run:

chmod call: &null
mode of chmod.icn -rw-rw-r--

chown

chown(f, u, g) : null

chown() change or retrieve (if permitted) the owner/group of the filename f. u and g can be strings or numeric identifiers as known by the operating system.

#
# chown.icn, Demonstrate chown, the file ownership function
#
procedure main()
    file := "chown.icn"
    # Change owner/group of file, usually only superusers can do this
    # so expect failure of this sample, file will remain owned by btiffin
    write(image(chown(file, "nobody", "nobody")))
    write("Owner of ", file, " ", stat(file).uid)
end

examples/chown.icn

Sample run, very likely to fail without permissions.

Owner of chown.icn btiffin

chroot

chroot(s) : null

chroot(f) changes the root directory, /, of the current filesystem to f.

chroot was an early Unix attempt at protecting filesystems. Still in use by some applications, web servers for instance, to ensure that files outside of a permissible tree are inaccessible by normal users. Modern equivalents BSD jails and new LCX/LXD Linux container technology have superseded use of chroot. This is normally a privileged operation.

#
# chroot.icn, Demonstrate chroot, the filesystem root directory function
#
# Seeing as this program is evaluated during document generation it is
# very likely to fail.  The book is never built using root permissions.
#
procedure main()
    # Change filesystem root to protect outside directories
    #  from unprivileged access.  Requires CAP_SYS_CHROOT capabilities.
    if newroot := chroot("/home/btiffin") then {
        write(image(newroot))
        chdir("/")
        write(chdir())
        d := open(".", "r")
        while write(read(d))
        close(d)
    } else write("no permission to set new root directory")
end

examples/chroot.icn

Sample run, very likely to fail without permissions.

no permission to set new root directory

classname

classname(r) : string

classname(r) will produce the name of the class of r.

#
# classname.icn, demonstrate the classname function
#
class sample()
    method inner()
        write("in method inner of class ", classname(self))
    end
end

procedure main()
    r := sample()
    r.inner()
    write("r is of class ", classname(r))
end

examples/classname.icn

This sample run includes the linkage details to give an example of how Unicon classes are managed.

prompt$ unicon classname.icn -x
Parsing classname.icn: ..
/home/btiffin/unicon-git/bin/icont -c   -O classname.icn /tmp/uni12122886
Translating:
classname.icn:
  sample_inner
  sample
  sampleinitialize
  main
No errors
/home/btiffin/unicon-git/bin/icont  classname.u -x
Linking:
Executing:
in method inner of class sample
r is of class sample

Clip

Clip(w:&window, x:0, y:0, wid:0, h:0) : window [graphics]

Clip() sets a clipping rectangle for a window. Top left corner starts at x, y. If width wid is 0, the clipping region extends from x to the right side of the window. When height h is 0, the clip region extends from y to the bottom of the window. Graphic writes outside of the clipping region will not occur.

#
# Clip.icn, demonstrate clipping region
#
procedure main()
    window := open("Clip example", "g", "size=110,75", "canvas=hidden")
    write(window, "Clipping")
    Clip(window, 0, 0, 50, 50)
    Fg(window, "vivid orange")
    FillCircle(window, 50, 50, 30)  
    WSync(window)
    WriteImage(window, "../images/Clip.png")
    close(window)
end

examples/Clip.icn

Sample run:

prompt$ unicon -s Clip.icn -x
_images/Clip.png

images/Clip.png


Clone

Clone(w1, attributes...) : window [graphics]

Clone() creates a window that couples the drawing canvas of w1 with a new graphics context. Attributes from w1 are inherited, overridden by any attributes specified in the Clone() function.

#
# Clone.icn, demonstrate window cloning, canvas coupling
#
procedure main()
    window := open("Clone one", "g", "size=110,60", "canvas=hidden")
    write(window, "Cloning")
    write(window)

    other := Clone(window, "fg=vivid orange", "font=sans")
    write(other, "From the clone")

    WSync(window)
    WriteImage(window, "../images/Clone.png")
    close(other)
    close(window)
end

examples/Clone.icn

Sample run:

prompt$ unicon -s Clone.icn -x
_images/Clone.png

images/Clone.png


close

close(x) : file | integer

close() a file, pipe, window, network, message or database connection. Resources are freed. Closing a window will cause it to disappear, but will remain active until all open bindings are closed. If a pipe or network connection is closed, an integer exit status is returned, otherwise the value produced is the closed file handle.

#
# close.icn, demonstrate the close function
#
procedure main()
    # open the source file resource
    f := open(&file, "r")
    # show the first meaningful comment line
    read(f)
    write(read(f))

    # close the resource, display the expression value
    write(image(close(f)))

    &error := 1
    # next line will cause a runtime error, converted to failure
    write(read(f))
    write("Error: ", &errornumber, " - ", &errortext)

    # open a pipe and check exit status
    write()
    write("open an 'ls' pipe, show first few entries, skip the rest")
    p := open("ls", "p")

    # show first few entries
    every 1 to 6 do write(read(p))
    # spin past the rest
    while read(p)

    # display the close expression value
    write("Exit status from ls pipe: ", image(close(p)))
end

examples/close.icn

Sample run:

# Author: Brian Tiffin
file(close.icn)
Error: 212 - attempt to read file not open for reading

open an 'ls' pipe, show first few entries, skip the rest
1to4
1to4.icn
Abort
Abort.icn
abs
abs.icn
Exit status from ls pipe: 0

cofail

cofail(CE) : any

cofail(ce) activates co-expression ce, transmitting failure instead of a result.

#
# cofail.icn, demonstrate cofail, transmit failure to a co-expression
#
procedure main()
    ce := create 1 to 4

    write(@ce)
    write(@ce)

    cofail(ce)
    # this will cause a runtime error now, the co-expression empty
    write(@ce)
end

examples/cofail.icn

Sample run (ends with an error):

1
2
System error at line 12 in cofail.icn
empty activator stack

collect

collect(i1:0, i2:0) : null

collect() runs the garbage collector to ensure that i2 bytes are available in region i1, where i1 can be:

  • 0, no region in particular
  • 1, static region
  • 2, string region
  • 3, block region
#
# show collections, create and remove a string, reshow collections
#
procedure main()
    collections()
    s := repl(&letters, 1000)
    s := &null
    collect()
    write("\nAfter string create/remove")
    collections()
end

# Display current memory region allocations
procedure collections()
    local collects

    collects := [] ; every put(collects, &collections)

    write("Collections, ", *collects, " values generated")
    write(repl("-", 30 + **collects))
    write("Heap   : ", collects[1])
    write("Static : ", collects[2])
    write("String : ", collects[3])
    write("Block  : ", collects[4])
end

examples/collections.icn

Sample run:

Collections, 4 values generated
-------------------------------
Heap   : 0
Static : 0
String : 0
Block  : 0

After string create/remove
Collections, 4 values generated
-------------------------------
Heap   : 1
Static : 0
String : 0
Block  : 0

Color

Color(w, i, s,...) : window [graphics]

Color(w, i) produces the current setting of mutable colour i. Color(w, i, s,...) set the colour map entries referenced by i[j] to the colours specified by s[j]..

#
# Color.icn, demonstrate colour references and settings
#
procedure main()
    window := open("Color example", "g", "size=200,110", "canvas=hidden")
    write(window, Color(window, 1)) | write(window, "no mutable colours")
    Color(window, 1, "vivid orange")
    write(window, Color(window, 1)) | {
        write(window, "still no colour map")
        write(window)
        write(window, "but don't despair")
        write(window, "colour maps have been superseded")
        write(window, "by display hardware that has")
        write(window, "all the colours, all the time")
    }
    WSync(window)
    WriteImage(window, "../images/Color.png")
    close(window)
end

examples/Color.icn

Sample run:

prompt$ unicon -s Color.icn -x
_images/Color.png

images/Color.png


ColorValue

ColorValue(w, s) : string [graphics]

ColorValue(w, s) converts the string colour name s into a string with three 16-bit integer values representing the RGB components. ColorValue() fails if the string s is not a recognized name, or valid RGB decimal or hex encoded colour.

#
# ColorValue.icn, demonstrate colour name to value
#
procedure main()
    window := open("ColorValue example", "g", "size=240,80", "canvas=hidden")
    write(window, right("vivid orange is ", 20),
          ColorValue(window, "vivid orange")) |
        write(window, "invalid colour name")
    write(window, right("1,2,3 is ", 20),
          ColorValue(window, "1,2,3")) |
        write(window, "invalid colour encoding")
    write(window, right("#aaaabbbbcccc is ", 20),
          ColorValue(window, "#aaaabbbbcccc")) |
        write(window, "invalid colour hex encoding")
    writes(window, right("made up colour is ", 20))
    write(window, ColorValue(window, "made up colour")) |
        write(window, "invalid colour name")
    WSync(window)
    WriteImage(window, "../images/ColorValue.png")
    close(window)
end

examples/ColorValue.icn

Sample run:

prompt$ unicon -s ColorValue.icn -x
_images/ColorValue.png

images/ColorValue.png


condvar

condvar(mutex) : condition variable

condvar() creates a new condition variable for use with wait or signal. The optional mutex argument associated the condition variable with the mutually exclusive lock.

The returned variable can be used with wait(cv) to block the current thread until a signal(cv) is invoked (from another thread).

#
# condvar.icn, demonstrate a threading condition variable
#

# taken from the Programming with Unicon book, page 146
procedure main()
    mtx := mutex()
    L := mutex([], mtx)
    cv := condvar(mtx)
    p := thread produce(L, cv)
    c := thread consume(L, cv)
    every wait(p | c)
end

procedure produce(L, cv)
    every put(L, !10) & *L=1 & signal(cv)
end

procedure consume(L, cv)
    i := 0
    while i < 10 do
        if x := get(L) then
             i +:= 1 & write(x)
        else
            critical cv: until *L>0 do wait(cv)
end

examples/condvar.icn

Sample run:

1
2
3
4
5
6
7
8
9
10

constructor

constructor(s, ...) : procedure

constructor(label, field, field, ...) creates a new record type, named label with fields named from the subsequent arguments (as strings). A constructor procedure is returned for creating records of this type.

#
# constructor.icn, Create a constructor procedure for a new record type
#
link ximage

record one(a,b,c)

procedure main()
    # start with a pre-compiled record
    r1 := one(1,2,3)
    write("r1.a ", r1.a)

    # add a new record type at runtime
    rc := constructor("newrec", "d", "e", "f")
    r2 := rc(4,5,6)
    write("r2.d ", r2.d)
    write(ximage(r2))
end

examples/constructor.icn

Sample run:

r1.a 1
r2.d 4
R_newrec_1 := newrec()
   R_newrec_1.d := 4
   R_newrec_1.e := 5
   R_newrec_1.f := 6

copy

copy(any) : any

copy(x) produces a copy of x. For immutable types, this is a no-op. For structures, a one-level deep copy of the object is made.

The IPL contains a deepcopy procedure when a nested structure needs to be copied.

#
# copy.icn, Demonstrate the one-level copy function
#
link ximage

record newrec(a,b,c)
procedure main()
    i := copy(5)
    write("copy(5) is ", i)
    L := [[1,2], 3, 4]
    L2 := copy(L)
    write(ximage(L2))

    write()
    write("Only one level copied:")
    R := newrec(1, 2, L)
    R2 := copy(R)
    write(ximage(R))
    write()
    write("The inner list is a reference")
    write("Changing the original, changes the copy")
    L[1] := 5
    write(ximage(R))
end

examples/copy.icn

Sample run:

copy(5) is 5
L3 := list(3)
   L3[1] := L1 := list(2)
      L1[1] := 1
      L1[2] := 2
   L3[2] := 3
   L3[3] := 4

Only one level copied:
R_newrec_1 := newrec()
   R_newrec_1.a := 1
   R_newrec_1.b := 2
   R_newrec_1.c := L2 := list(3)
      L2[1] := L1 := list(2)
         L1[1] := 1
         L1[2] := 2
      L2[2] := 3
      L2[3] := 4

The inner list is a reference
Changing the original, changes the copy
R_newrec_1 := newrec()
   R_newrec_1.a := 1
   R_newrec_1.b := 2
   R_newrec_1.c := L2 := list(3)
      L2[1] := 5
      L2[2] := 3
      L2[3] := 4

CopyArea

CopyArea(w1, w2, x:0, y:0, wid:0, h:0, x2:0, y2:0) : window [graphics]

CopyArea() copies the rectangle x,y,wid,h from w1 to x2,y2 of w2.

#
# CopyArea.icn, demonstrate graphic area copy
#
procedure main()
    window := open("CopyArea example", "g", "size=150,125", "canvas=hidden")
    write(window, "CopyArea")
    Fg(window, "vivid orange")
    FillCircle(window, 50, 50, 30)
    CopyArea(window, window, 20,20,50,50, 60,60)
    WSync(window)
    WriteImage(window, "../images/CopyArea.png")
    close(window)
end

examples/CopyArea.icn

Sample run:

prompt$ unicon -s CopyArea.icn -x
_images/CopyArea.png

images/CopyArea.png


cos

cos(r) : real

cos(r) returns the Cosine of the given angle, r (in radians)

#
# cos.icn, demonstrate the the Cosine function
#
procedure main()
    write("cos(r): Domain all real repeating within 0 <= r <= 2pi (in radians), Range: -1 <= x <= 1")
    every r := 0.0 to &pi * 2 by &pi/4 do {
        write(left("cos(" || r || ")", 24), " radians = ", cos(r))
    }
end

examples/cos.icn

Sample run:

cos(r): Domain all real repeating within 0 <= r <= 2pi (in radians), Range: -1 <= x <= 1
cos(0.0)                 radians = 1.0
cos(0.7853981633974483)  radians = 0.7071067811865476
cos(1.570796326794897)   radians = 6.123233995736766e-17
cos(2.356194490192345)   radians = -0.7071067811865475
cos(3.141592653589793)   radians = -1.0
cos(3.926990816987241)   radians = -0.7071067811865477
cos(4.71238898038469)    radians = -1.83697019872103e-16
cos(5.497787143782138)   radians = 0.7071067811865474
cos(6.283185307179586)   radians = 1.0

Graphical plot:

#
# plot-function, trigonometric plotting, function from command line
#
$define points 300
$define xoff   4
$define base   64
$define yscale 60
$define xscale 100

invocable "sin", "cos", "tan"

# plot the given function, default to sine
procedure main(args)
    func := map(args[1]) | "sin"
    if not func == ("sin" | "cos" | "tan") then func := "sin" 

    # range of pixels for 300 points, y scaled at +/- 60, 4 pixel margins
    &window := open("Plotting", "g", "size=308,128", "canvas=hidden")

    # tan may cause runtime errors
    if func == "tan" then &error := 6

    color := "vivid orange"
    Fg(color)
    write(&window, "\n " || func)

    Fg("gray")
    DrawLine(2, 64, 306, 64)
    DrawLine(2, 2, 2, 126)
    DrawString(8, 10, "1", 8, 69, "0", 2, 126, "-1")
    DrawString(270, 76, left(points * 2 * &pi / 100, 6))

    Fg(color)
    every x := 0 to points do
        DrawPoint(xoff + x, base + yscale * func((2 * &pi * x) / xscale))

    WSync()
    WriteImage("../images/plot-" || func || ".png")
    close(&window)
end

examples/plot-function.icn

prompt$ unicon -s plot-function.icn -x cos
_images/plot-cos.png

images/plot-cos.png


Couple

Couple(w1, w2) : window [graphics]

Couple(w1, w2) produces a new value that binds the window associated with w1 to the graphics context of w2.

#
# Couple.icn, demonstrate w1 coupling
#
procedure main()
    w1 := open("window 1", "g", "size=110,60", "canvas=hidden")
    write(w1, "Couple 1")
    write(w1)

    w2 := open("window 2", "g", "size=110,60", "canvas=hidden")
    Fg(w2, "vivid orange")
    write(w2, "Couple 2")

    other := Couple(w1, w2)
    write(other, "From the Couple")

    # save image of w1
    WSync(other)
    WriteImage(other, "../images/Couple.png")
    close(other, w2, w1)
end

examples/Couple.icn

Sample run:

_images/Couple.png

images/Couple.png


crypt

crypt(s1, s2) : string [POSIX]

crypt(s1, s2) encrypts the password s1 using the salt s2. The first two characters of the result string will be the salt.

#
# crypt.icn, Demonstrate the POSIX crypt function
#
procedure main()
    password := "#secretpassword!"
    salt := "SV"
    write(image(p := crypt(password, salt)))

    # input routine would get user password
    # compare both encrypted values
    attempt := crypt(password, salt)
    if attempt == p then
        write("User verified by password")
end

examples/crypt.icn

Sample run:

"SVI6LCAF1jj.6"
User verified by password

A word of warning. Modern computers are fast. Short passwords are very susceptible to brute force trials, especially when a bad actor gets hold of a copy of the encrypted form. It makes it easy to run through millions of attempts, comparing guesses that are crypted to the encrypted form.

Do yourself a favour and use strong passwords. Every letter and symbol makes it 96 times harder[1] to guess (assuming printable ASCII character codes are used). One character, 96 tries maximum, two characters, 96 * 96 tries. When you get to eight, the numbers start to be reasonable for thwarting casual bad actors. 7,213,895,789,838,336 potential combinations.

Modern machines can attempt millions of brute force guesses per second.

[1]That’s over simplifying the issue. There are highly sophisticated algorithms in play now, with many common human behavioural aspects programmed in. And machines are fast.

cset

cset(any) : cset?

cset(x) attempts to convert x to a cset. Fails if the conversion can not be performed.

#
# cset-function.icn, Demonstrate the convert to cset function
#
record makefail(a,b,c)
procedure main()

   # convert a string
   write("convert \"xyzzy\" to cset")
   write(cset("xyzzy"))

   # convert a number
   write("convert 3.141 to cset")
   write(cset(3.141))

   # attempt to convert a record
   R := makefail(1,2,3.0)
   if not write(cset(R)) then write("record cannot be converted")
end

examples/cset-function.icn

Sample run:

convert "xyzzy" to cset
xyz
convert 3.141 to cset
.134
record cannot be converted

ctime

ctime(i) : string

ctime(i) converts the integer time i, given in seconds since the epoch of Jan 1st, 1970 00:00:00 Greenwich Mean Time, into a string using the local timezone.

#
# ctime.icn, Demonstrate the ctime function
#
procedure main()
    # convert epoch start to a formatted time
    write(ctime(0))

    # convert time of run to formatted time
    write(ctime(&now))

    # two days in the future (relative to time of run)
    write(ctime(&now + 48 * 60 * 60))
end

examples/ctime.icn

Sample run:

Wed Dec 31 19:00:00 1969
Fri Oct 25 13:21:47 2019
Sun Oct 27 13:21:47 2019

See also

&clock, &dateline, gtime, &now


dbcolumns

dbcolumns(D, s) : list

dbcolumns(db, tablename) returns a List (arrays) of record data.

#
# dbcolumns.icn, ODBC table column information
#
# tectonics: ~/.odbc.ini setup required for [unicon] 
#            assuming the [unicon] ODBC setup, SQLite3
#
link ximage

procedure main()
    # mode 'o' open, ODBC SQL, default table and connection at defaults 
    db := open("unicon", "o", "", "") | stop("no ODBC for \"unicon\"")

    # Information below was created as part of examples/odbc.icn
    # sql(db, "create table contacts (id integer primary key, name, phone)")

    # display ODBC view of table schema
    write("\ndbtables:")     
    every write(ximage(dbtables(db)))

    # show dbcolumns information from first table
    tables := dbtables(db)
    write("\ndbcolumns.", tables[1].name, ":")     
    every write(ximage(dbcolumns(db, tables[1].name)))

    # access some of the reflective record data
    write()
    write("First column")
    dbc := dbcolumns(db, tables[1].name)
    write("tablename: ", dbc[1].tablename,
          ", colname: ", dbc[1].colname,
          ", type: ", dbc[1].typename)

    write("Second column")
    write("tablename: ", dbc[2].tablename,
          ", colname: ", dbc[2].colname)

    # generate a query
    write()
    write("Query for ", dbc[2].colname, " (using dbc[2].colname)")
    sql(db, "select " || dbc[2].colname || " from " || dbc[2].tablename)

    # I know my name is first, but Jafar deserves the press
    rec := fetch(db)
    rec := fetch(db)

    # skipping generic info now, the column is known and it is 'name'  
    write("Access name field from fetched record")
    write("Name: ", rec.name)
    
    close(db)
end

examples/dbcolumns.icn

Sample run:

dbtables:
L1 := list(1)
   L1[1] := R__1 := ()
      R__1.qualifier := ""
      R__1.owner := ""
      R__1.name := "contacts"
      R__1.type := ""
      R__1.remarks := ""

dbcolumns.contacts:
L6 := list(3)
   L6[1] := R__1 := ()
      R__1.catalog := ""
      R__1.schema := ""
      R__1.tablename := "contacts"
      R__1.colname := "id"
      R__1.datatype := 4
      R__1.typename := "integer"
      R__1.colsize := 9
      R__1.buflen := 10
      R__1.decdigits := 10
      R__1.numprecradix := 0
      R__1.nullable := 1
      R__1.remarks := ""
   L6[2] := R__2 := ()
      R__2.catalog := ""
      R__2.schema := ""
      R__2.tablename := "contacts"
      R__2.colname := "name"
      R__2.datatype := 12
      R__2.typename := ""
      R__2.colsize := 0
      R__2.buflen := 255
      R__2.decdigits := 10
      R__2.numprecradix := 0
      R__2.nullable := 1
      R__2.remarks := ""
   L6[3] := R__3 := ()
      R__3.catalog := ""
      R__3.schema := ""
      R__3.tablename := "contacts"
      R__3.colname := "phone"
      R__3.datatype := 12
      R__3.typename := ""
      R__3.colsize := 0
      R__3.buflen := 255
      R__3.decdigits := 10
      R__3.numprecradix := 0
      R__3.nullable := 1
      R__3.remarks := ""

First column
tablename: contacts, colname: id, type: integer
Second column
tablename: contacts, colname: name

Query for name (using dbc[2].colname)
Access name field from fetched record
Name: jafar

dbcolumns is one of the reflective ODBC functions available to a Unicon programmer. As can be seen in the example above, it can be used for self-documenting purposes (make a run to get all the record fields, then code to suit), or for writing utility applications with user defined naming.

See ODBC for details on the example setup.


dbdriver

dbdriver(D) : record

dbdriver(db) produces a record of current ODBC driver information:

record driver(name, ver, odbcver, connections, statements, dsn)

Or, write a program and look at the data fields using the reflective properties inherent in Unicon.

#
# dbdriver.icn, ODBC table column information
#
# tectonics: ~/.odbc.ini setup required for [unicon] 
#            assuming the [unicon] ODBC setup, SQLite3
#
link ximage

procedure main()
    # mode 'o' open, ODBC SQL, default table and connection at defaults 
    db := open("unicon", "o", "", "") | stop("no ODBC for \"unicon\"")

    # Information below was created as part of examples/odbc.icn
    # sql(db, "create table contacts (id integer primary key, name, phone)")

    # display ODBC driver info
    write("\nODBC driver information:")     
    write(ximage(dbdriver(db)))

    # and a direct field access, (hint: "unicon")
    write("Data Source Name: ", dbdriver(db).dsn)

    close(db)
end

examples/dbdriver.icn

Sample run:

prompt$ unicon -s dbdriver.icn -x

ODBC driver information:
R__1 := ()
   R__1.name := "sqlite3odbc.so"
   R__1.ver := "0.9992"
   R__1.odbcver := "03.00"
   R__1.connections := 0
   R__1.statements := ""
   R__1.dsn := "unicon"
Data Source Name: unicon

See ODBC for details on the example ODBC setup.


dbkeys

dbkeys(D, string) : list [ODBC]

dbkeys(db, tablename) produces a list of record pairs (col, seq) containing information about the primary keys in the given table.

#
# dbkeys.icn, ODBC table column information
#
# tectonics: ~/.odbc.ini setup required for [unicon] 
#            assuming the [unicon] ODBC setup, SQLite3
#
link ximage

procedure main()
    # mode 'o' open, ODBC SQL, default table and connection at defaults 
    db := open("unicon", "o", "", "") | stop("no ODBC for \"unicon\"")

    # Information below was created as part of examples/odbc.icn
    # sql(db, "create table contacts (id integer primary key, name, phone)")

    # display table key information
    write("\nODBC table contacts key information:")     
    write(ximage(dbkeys(db, "contacts")))

    write("contacts first key: ", dbkeys(db, "contacts")[1].col)

    close(db)
end

examples/dbkeys.icn

Sample run:

prompt$ unicon -s dbkeys.icn -x

ODBC table contacts key information:
L1 := list(1)
   L1[1] := R__1 := ()
      R__1.col := "id"
      R__1.seq := 1
contacts first key: id

dblimits

dblimits(D) : record [ODBC]

dblimits(db) produces a record that contains the upper bounds of many parameters associated with the given database.

#
# dblimits.icn, ODBC internal limit information
#
# tectonics: ~/.odbc.ini setup required for [unicon] 
#            assuming the [unicon] ODBC setup, SQLite3
#
link ximage

procedure main()
    # mode 'o' open, ODBC SQL, default table and connection at defaults 
    db := open("unicon", "o", "", "") | stop("no ODBC for \"unicon\"")

    # Information below was created as part of examples/odbc.icn
    # sql(db, "create table contacts (id integer primary key, name, phone)")

    # display ODBC limit info
    write("\nODBC limit information:")     
    write(ximage(dblimits(db)))

    # and a direct field access
    write("Max SQL statement length: ", dblimits(db).maxstmtlen)

    close(db)
end

examples/dblimits.icn

Sample run:

prompt$ unicon -s dblimits.icn -x

ODBC limit information:
R__1 := ()
   R__1.maxbinlitlen := 0
   R__1.maxcharlitlen := 0
   R__1.maxcolnamelen := 255
   R__1.maxgroupbycols := 0
   R__1.maxorderbycols := 0
   R__1.maxindexcols := 0
   R__1.maxselectcols := 0
   R__1.maxtblcols := 0
   R__1.maxcursnamelen := 255
   R__1.maxindexsize := 0
   R__1.maxownnamelen := 255
   R__1.maxprocnamelen := 0
   R__1.maxqualnamelen := 255
   R__1.maxrowsize := 0
   R__1.maxrowsizelong := "N"
   R__1.maxstmtlen := 16384
   R__1.maxtblnamelen := 255
   R__1.maxselecttbls := 0
   R__1.maxusernamelen := 16
Max SQL statement length: 16384

dbproduct

dbproduct(D) : record [ODBC]

dbproduct(db) produces a record the gives the name and version of the DBMS product containing the given database.

#
# dbproduct.icn, ODBC product and version information
#
# tectonics: ~/.odbc.ini setup required for [unicon] 
#            assuming the [unicon] ODBC setup, SQLite3
#
link ximage

procedure main()
    # mode 'o' open, ODBC SQL, default table and connection at defaults 
    db := open("unicon", "o", "", "") | stop("no ODBC for \"unicon\"")

    # Information below was created as part of examples/odbc.icn
    # sql(db, "create table contacts (id integer primary key, name, phone)")

    write("\nODBC product information:")     
    write(ximage(dbproduct(db)))

    # and a direct field access
    write("ODBC version: ", dbproduct(db).ver)

    close(db)
end

examples/dbproduct.icn

Sample run:

prompt$ unicon -s dbproduct.icn -x

ODBC product information:
R__1 := ()
   R__1.name := "SQLite"
   R__1.ver := "3.9.2"
ODBC version: 3.9.2

dbtables

dbtables(D) : list [ODBC]

dbtables(db) returns a list of records that describe all the tables in the given database.

#
# dbtables.icn, ODBC table list
#
# tectonics: ~/.odbc.ini setup required for [unicon] 
#            assuming the [unicon] ODBC setup, SQLite3
#
link ximage

procedure main()
    # mode 'o' open, ODBC SQL, default table and connection at defaults 
    db := open("unicon", "o", "", "") | stop("no ODBC for \"unicon\"")

    # Information below was created as part of examples/odbc.icn
    # sql(db, "create table contacts (id integer primary key, name, phone)")

    # display ODBC table list
    write("\nODBC table list:")     
    write(ximage(dbtables(db)))

    # and a direct field access, (hint: "contacts")
    write("First table name: ", dbtables(db)[1].name)

    close(db)
end

examples/dbtables.icn

Sample run:

prompt$ unicon -s dbtables.icn -x

ODBC table list:
L1 := list(1)
   L1[1] := R__1 := ()
      R__1.qualifier := ""
      R__1.owner := ""
      R__1.name := "contacts"
      R__1.type := ""
      R__1.remarks := ""
First table name: contacts

delay

delay(i) : null

delay(i) pauses a program for at least i milliseconds.

#
# delay.icn, demontrate the millisecond delay function
#
procedure main()
    # retrieve a microsecond clock value (millionths)
    write(gettimeofday().usec)
    # pause for 10 (or more) milliseconds (thousandths)
    delay(10)
    write(gettimeofday().usec)
end

examples/delay.icn

A sample run:

prompt$ unicon -s delay.icn -x
45815
55951

delete

delete(x1, x2,...) : x1

delete(x1, x2,...) removes one or more elements x2, [x3....] from structure x1. x1 can be list, set, table, DBM database, or POP connection.

#
# delete.icn, demonstrate delete from structure
#
link fullimag, ximage

procedure main()
    L := [1,2,"abc"]
    write("delete element 3 from list")
    write("Before: ", fullimage(L))
    write("After : ", fullimage(delete(L, 3)))

    T := table()
    T["abc"] := "xyz"
    T["xyz"] := "abc"
    write("delete key abc from table")
    write("Before: ", ximage(T))
    write("After : ", ximage(delete(T, "abc")))
end

examples/delete.icn

Sample run:

prompt$ unicon -s delete.icn -x
delete element 3 from list
Before: [1,2,"abc"]
After : [1,2]
delete key abc from table
Before: T5 := table(&null)
   T5["abc"] := "xyz"
   T5["xyz"] := "abc"
After : T5 := table(&null)
   T5["xyz"] := "abc"

detab

detab(string, i:9,...) : string

detab(s, i,...) replaces tabs with spaces with stops are columns indicated by the second and following arguments, which must be integers. Tabs stops are extended using the interval between the last two specified stops.

#
# detab.icn, demonstrate tabs to spaces
#
procedure main()
    write("detab with stops at 4, 8, 12")
    s := "\t\t\tThree tabs in\n\t\tTwo tabs in\n\tOne tab in\nNo tabs"
    write(detab(s, 4,8,12))
end

examples/detab.icn

Sample run:

prompt$ unicon -s detab.icn -x
detab with stops at 4, 8, 12
           Three tabs in
       Two tabs in
   One tab in
No tabs

display

display(i:&level, f:&errout, CE:&current) : null

display() writes the local variables of the i most recent procedure activations from co-expression CE, plus all global variables, to the file f

#
# display.icn, demonstrate the display debugging aid 
#
global g,h
procedure main()
    local i,j,k
    g := "a global"
    i := 0
    j := 2
    k := 4
    subproc(i,j,k)
end

procedure subproc(l, m, n)
    display()
end 

examples/display.icn

Sample run:

prompt$ unicon -s display.icn -x
co-expression_1(1)

subproc local identifiers:
   l = 0
   m = 2
   n = 4
main local identifiers:
   i = 0
   j = 2
   k = 4

global identifiers:
   display = function display
   g = "a global"
   main = procedure main
   subproc = procedure subproc

DrawArc

DrawArc(w, x, y, wid, h, a1:0.0, a2:&pi*2, ...) : window [graphics]

DrawArc(w, x, y, width, height, a1, a2, ...) draws arcs or ellipses. Each arc is defined by 4 given and 2 derived coordinates. x, y, width, *height define a bounding rectangle around the arc; the centre of the arc is the point (x+(width)/2, y+(height)/2. Angle a1 is the starting position of the arc. The angle a2 is not an end position but specifies the direction and extent of the arc. Angles are given in radians. Multiple arcs can be drawn with one call to the function.

#
# DrawArc.icn, demonstrate drawing an Arc
#
procedure main()
    &window := open("DrawArc", "g",
                    "size=65,40", "canvas=hidden")
    # An arc 
    Fg(&window, "vivid orange")
    DrawArc(&window, 10, 10, 40, 20)

    Fg(&window, "blue")
    DrawArc(&window, 26, 15, 10, 10, 0.0, &pi)

    # save image for the document
    WSync()
    WriteImage("../images/DrawArc.png")
    close(&window)
end

examples/DrawArc.icn

Sample run:

prompt$ unicon -s DrawArc.icn -x
_images/DrawArc.png

images/DrawArc.png


DrawCircle

DrawCircle(w, x, y, radius, a1:0.0, a2:&pi*2, ...) : window [graphics]

DrawCircle(w, x, y, r, a1, a2) draws a circle centred at x,y. Otherwise similar to DrawArc with width equal to height.

#
# DrawCircle.icn, demonstrate drawing a circle
#
procedure main()
    w := open("DrawCircle", "g", "size=40,40", "canvas=hidden")

    # A full circle
    Fg(w, "vivid orange")
    DrawCircle(w, 20, 20, 18)

    # A partial circle
    Fg(w, "blue")
    DrawCircle(w, 20, 20, 9, 0.0, &pi)

    # save image for the document
    WSync(w)
    WriteImage(w, "../images/DrawCircle.png")
    close(w)
end

examples/DrawCircle.icn

Sample run:

prompt$ unicon -s DrawCircle.icn -x
_images/DrawCircle.png

images/DrawCircle.png


DrawCube

DrawCube(w, x, y, z, len, ...) : record [3D graphics]

DrawCube(w, x, y, z, len) draws a cube with sides of length len at the position x, y, z on the 3D window w. The display list element is returned. This procedure fails if the graphic context attribute dim is set to 2.

Todo

Not working

#
# DrawCube.icn, demonstrate drawing a cube
#
procedure main()
    window := open("DrawCube", "gl", "bg=black", "buffer=on",
                    "size=400,400", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")

    # A cube 
    DrawCube(window, 0.0, 0.0, -2.0, 0.6)

    # save image for the document
    Refresh(window)
    WSync(window)
    WriteImage(window, "../images/DrawCube.png")
    close(window)
end

examples/DrawCube.icn

Sample run:

_images/DrawCube.png

images/DrawCube.png


DrawCurve

DrawCurve(w, x1, y1, ...) : window

DrawCurve(w, x1,y1, x2,y2, x3,y3, ...) draws a smooth curve between each x,y pair in the argument list. If the first and last point are the same, the curve is smoothed and closed at that point.

#
# DrawCurve.icn, demonstrate drawing an Arc
#
procedure main()
    w := open("DrawCurve", "g", "size=65,40", "canvas=hidden")

    # Some curves
    Fg(w, "vivid orange")
    DrawCurve(w, 10,10, 15,25, 35,20)

    Fg(w, "blue")
    DrawCurve(w, 30,30, 15,20, 40,10)

    # save image for the document
    WSync(w)
    WriteImage(w, "../images/DrawCurve.png")
    close(w)
end

examples/DrawCurve.icn

Sample run:

prompt$ unicon -s DrawCurve.icn -x
_images/DrawCurve.png

images/DrawCurve.png


DrawCylinder

DrawCylinder(w, x,y,z, h, r1,r2,...) : record [3D graphics]

DrawCylinder(w, x,y,z, h, rt,rb) draws a cylinder with a top radius rt, a bottom with radius rb, a height h centred at x,y,z on window w. A display list element is returned. DrawCylinder fails if window attribute dim is set to 2.

#
# DrawCylinder.icn, demonstrate drawing a cylinder
#
procedure main()
    window := open("DrawCylinder", "gl", "bg=black", "buffer=on",
                    "size=400,260", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")
    # A cube 
    DrawCylinder(window, 0.0, 0.19, -2.2, 0.3, 0.4, 0.5)

    # save image for the document
    Refresh(window)
    WSync(window)
    WriteImage(window, "../images/DrawCylinder.png")
    close(window)
end

examples/DrawCylinder.icn

Sample output:

_images/DrawCylinder.png

images/DrawCylinder.png


DrawDisk

DrawDisk(w, x,y,z, r1,r2, a1,a2,...) : record

DrawDisk(w, x,y,z, ri, ro, astart, asweep) draws a (partial) disk centred at x,y,z, with an inner circle of radius ri, an outer circle of radius ro, a starting angle of astart, and a sweeping angle of asweep, on window w. The parameters a1 and a2 are optional, and a full disk is rendered if they are not provided. The display list element is returned.

#
# DrawDisk.icn, demonstrate drawing a Disk
#
procedure main()
    window := open("DrawDisk", "gl", "bg=black", "buffer=on",
                    "size=400,260", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")

    # A disk 
    DrawDisk(window, 0.0,0.19,-2.2, 0.3,0.4)

    # save image for the document
    Refresh(window)
    WSync(window)
    WriteImage(window, "../images/DrawDisk.png")
    close(window)
end

examples/DrawDisk.icn

Sample output:

_images/DrawDisk.png

images/DrawDisk.png


DrawImage

DrawImage(w, x, y, s) : window

DrawImage(w, x, y, s) draws image string s at x,y in window w.

Unicon image strings are of the form “width, palette, pixels”.

#
# DrawImage.icn, demonstrate drawing image strings
#
link cardbits
procedure main()
    &window := open("DrawImage", "g", "size=85,40", "canvas=hidden")

    # image data is "width, palette, pixels"
    img := cardbits()
    DrawImage(0, 0, img)

    # save image for the document
    WSync()
    WriteImage("../images/DrawImage.png")
    close(&window)
end

examples/DrawImage.icn

Sample run:

prompt$ unicon -s DrawImage.icn -x
_images/DrawImage.png

images/DrawImage.png


DrawLine

DrawLine(w, x1, y1, z1, ...) : window | list [graphics/3D graphics]

DrawLine(w, x1, y1,...,xn,yn) draws lines between each adjacent x, y pair of arguments. In 3D, DrawLine takes from 2-4 coordinate per vertex and returns a list the represents the lines on the display list for refresh purposes.

#
# DrawLine.icn, demonstrate drawing a line
#
procedure main()
    &window := open("DrawLine", "g",
                    "size=70,40", "canvas=hidden")
    # An Line 
    Fg("vivid orange")
    DrawLine(11,10, 60,10, 60,30)

    Fg("blue")
    DrawLine(10,10, 10,30, 59,30)

    Fg("green")
    DrawLine(11,11, 59,29)

    # save image for the document
    WSync()
    WriteImage("../images/DrawLine.png")
    close(&window)
end

examples/DrawLine.icn

Sample run:

prompt$ unicon -s DrawLine.icn -x
_images/DrawLine.png

images/DrawLine.png

A more sophisticated line drawing example is in the Graphics Programming in Icon book, pages 73-75. Using DrawLine to produce polygons (see also DrawPolygon) and star shapes; with a single function that depends on a skip value to draw the stars.

#
# linedrawing.icn, from the Graphics Programming in Icon book
#
# Draw a regular polygon with the specified number of vertices and
# radius, centered at (cx,cy).
#
procedure main()
    &window := open("linedrawing", "g", "size=200,200", "canvas=hidden") | 
               stop("Cannot open graphics window")
   
    Fg("vivid orange")
    rpolystars(100, 100, 90, 8)

    Fg("blue")
    rpolystars(100, 100, 90, 8, 3)

    WSync()
    WriteImage("../images/linedrawing.png")
    close(&window)
end    

procedure rpolystars(cx, cy, radius, vertices, skips)
    local theta, incr, xprev, yprev, x, y

    theta := 0                             # initial angle
    /skips := 1
    incr := skips * 2 * &pi / vertices
    xprev := cx + radius * cos(theta)      # initial position
    yprev := cy + radius * sin(theta)

    every 1 to vertices do {
        theta +:= incr
        x := cx + radius * cos(theta)      # new position
        y := cy + radius * sin(theta)
        DrawLine(xprev, yprev, x, y)
        xprev:= x                          # update old position
        yprev:= y
    }

    return
end

examples/linedrawing.icn

With a run sample of:

prompt$ unicon -s linedrawing.icn -x
_images/linedrawing.png

images/linedrawing.png


DrawPoint

DrawPoint(w, x1,y1, ...) : window [list]

DrawPoint(w, x1,y1,...,xn,yn) draws points given by x,y pairs on window w. With 3D graphics, DrawPoint() takes from 2 to 4 coordinates per vertex and returns the list that represents the points on the display list for refresh purposes.

#
# DrawPoint.icn, demonstrate drawing points in 2D
#
procedure main()
    &window := open("DrawPoint", "g", "size=45,30", "canvas=hidden")

    # Some points
    Fg("vivid orange")
    every x := 10 to 22 by 4 do
        every y := 10 to 16 do
            DrawPoint(x,y)
    # and a crossing line
    DrawLine(8,12, 24,14)

    # save image for the document
    WSync()
    WriteImage("../images/DrawPoint.png")
    close(&window)
end

examples/DrawPoint.icn

Sample run:

prompt$ unicon -s DrawPoint.icn -x
_images/DrawPoint.png

images/DrawPoint.png

Todo

3D points

With 3D graphics, points are x,y,z

#
# DrawPoint-3D.icn, demonstrate drawing points in 3D
#
link ximage
procedure main()
    &window := open("DrawPoint-3D","gl", "bg=white", "fg=orange",
                    "buffer=on", "size=400,200") #, "canvas=hidden")

    # Some 3D points    
    every x := 0 to 0.3 by 0.05 do 
        every y := 0.1 to 0.3 by 0.1 do
            every z := -2.0 to -1.8 by 0.005 do
                DrawPoint(x,y,z)

    # save image for the document
    Refresh()
    WSync()
    WriteImage("../images/DrawPoint-3D.png")
    close(&window)
end

examples/DrawPoint-3D.icn

Sample output:

_images/DrawPoint-3D.png

images/DrawPoint-3D.png


DrawPolygon

DrawPolygon(w, x1,y1[,z1], ..., xn,yn[,zn]) : window | list

DrawPolygon(w, x1,y1, x2,y2, xn,yn) draws a polygon connecting each x,y pair (in 2D). In 3D, DrawPolygon() takes from 2 to 4 coordinates per vertex and returns the list that represents the polygon on the display list.

#
# DrawPolygon.icn, demonstrate drawing polygons
#
procedure main()
    &window := open("DrawPolygon", "g", "size=45,30", "canvas=hidden")

    # a polygon using the procedural apply operator
    Fg("vivid orange")
    points := [5,5, 17,17, 5,17, 5,5]
    DrawPolygon!points

    # save image for the document
    WSync()
    WriteImage("../images/DrawPolygon.png")
    close(&window)
end

examples/DrawPolygon.icn

Sample run:

prompt$ unicon -s DrawPolygon.icn -x
_images/DrawPolygon.png

images/DrawPolygon.png

Todo

3D polygons


DrawRectangle

DrawRectangle(w, x1,y1, wid1, h1, ...) : window

DrawRectangle(w, x, y, width, hieght) draws a rectangle with a top right corner of x,y and a perceived width and height. Actual rectangle is width+1 pixels wide, and height+1 pixels high.

#
# DrawRectangle.icn, demonstrate drawing polygons
#
procedure main()
    &window := open("DrawRectangle", "g", "size=45,40", "canvas=hidden")

    Fg("vivid orange")
    DrawRectangle(10,10, 20, 10)

    # save image for the document
    WSync()
    WriteImage("../images/DrawRectangle.png")
    close(&window)
end

examples/DrawRectangle.icn

Sample run:

prompt$ unicon -s DrawRectangle.icn -x
_images/DrawRectangle.png

images/DrawRectangle.png


DrawSegment

DrawSegment(w, x1,y1[,z1], x2,y2[,z2],...) : window|list

DrawSegment(w, x1,y1, x2,y2,...) draws lines between alternating x,y pairs in the argument list. In 3D, DrawSegment takes from 2 to 4 coordinates per vertex and returns the list that represents the segments.

#
# DrawSegment.icn, demonstrate drawing points in 2D
#
procedure main()
    &window := open("DrawSegment", "g", "size=45,30", "canvas=hidden")

    Fg("vivid orange")
    every x := 10 to 22 by 4 do
        every y := 10 to 16 do
            DrawSegment(x,y, x+5,y-5)

    # save image for the document
    WSync()
    WriteImage("../images/DrawSegment.png")
    close(&window)
end

examples/DrawSegment.icn

Sample run:

prompt$ unicon -s DrawSegment.icn -x
_images/DrawSegment.png

images/DrawSegment.png


DrawSphere

DrawSphere(w, x,y,z, r,...) : record [Graphics, 3D]

DrawSphere(w, x,y,z, r,...) draws a sphere with radius r centred at (x,y,z) on 3D window w. The display list is returned. Fails when used on windows with WAttrib “dim=2”.

#
# DrawSphere.icn, demonstrate drawing a sphere
#
procedure main()
    window := open("DrawSphere", "gl", "bg=black", "buffer=on",
                    "size=400,240", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")

    # A sphere 
    DrawSphere(window, 0.0, 0.19, -2.2, 0.3)

    # save image for the document
    Refresh(window)
    WSync(window)
    WriteImage(window, "../images/DrawSphere.png")
    close(window)
end

examples/DrawSphere.icn

Sample output:

_images/DrawSphere.png

images/DrawSphere.png


DrawString

DrawString(w, x1, y1, s1,...) : window

DrawString(w, x, y, s) draws string s on window w at x, y, without effecting the current text cursor position. When used with drawop=reverse it is possible to draw erasable test. No background is drawn, only the actual pixels of the characters.

#
# DrawString.icn, demonstrate a boxed string
#
procedure main()
    w := open("DrawString", "g", "size=162,30",
              "linestyle=solid", "canvas=hidden")
    Font(w, "Liberation Mono")

    text := "Important message"
    fh := WAttrib(w, "fheight")
    tw := TextWidth(w, text)

    Fg(w, "purple")
    DrawString(w, 10, 20, text)
    Fg(w, "black")
    DrawRectangle(w, 5, 5, tw + 8, fh + 6)

    WSync(w)
    WriteImage(w, "../images/DrawString.png")
    close(w)
end

examples/DrawString.icn

Sample run:

prompt$ unicon -s DrawString.icn -x
_images/DrawString.png

images/DrawString.png


DrawTorus

DrawTorus(w, x,y,z, r1,r2,...) : record

DrawTorus(w, x,y,z, ri, ro) draws a torus with inner radius ri, outside radius r2, centred at x,y,z on 3D window w. The display list element is returned. DrawTorus fails if the window attribute dim is set to 2.

#
# DrawTorus.icn, demonstrate drawing a Torus
#
procedure main()
    window := open("DrawTorus", "gl", "bg=black", "buffer=on",
                    "size=400,260", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")

    # A torus 
    DrawTorus(window, 0.0,0.19,-2.2, 0.3,0.4)

    # save image for the document
    Refresh(window)
    WSync(window)
    WriteImage(window, "../images/DrawTorus.png")
    close(window)
end

examples/DrawTorus.icn

Sample output:

_images/DrawTorus.png

images/DrawTorus.png


dtor

dtor(r) : real

dtor(r) produces the equivalent of r degrees, in radians.

#
# dtor.icn, demonstrate degrees to radians
#
link numbers

# uses decipos from numbers, align decimal within field
procedure main()
    write("Degrees Radians")
    every r := 0.0 to 360.0 by 45.0 do
        write(decipos(r, 4, 8), decipos(dtor(r), 2, 20))
end

examples/dtor.icn

Sample run:

prompt$ unicon -s dtor.icn -x
Degrees Radians
  0.0   0.0                 
 45.0   0.7853981633974483  
 90.0   1.570796326794897   
135.0   2.356194490192345   
180.0   3.141592653589793   
225.0   3.926990816987241   
270.0   4.71238898038469    
315.0   5.497787143782138   
360.0   6.283185307179586

entab

entab(s, i:9,...) : string

entab(s, i,...) replaces spaces with tabs, with stops at the columns indicated. Tab stops are extended using the interval between the last two specified stops. Defaults give 8 space tabs, with stops at 1, 9, 17, etcetera.

#
# entab.icn, demonstrate spaces to tabs
#
procedure main()
    write("entab with stops at 4, 8, 12")
    s := repl(" ", 12) || "Three tabs in\n" ||
         repl(" ", 8) || "Two tabs in\n" ||
         "    One tab in\nNo tabs"
    write(entab(s, 4,8,12))
end

examples/entab.icn

Sample run:

prompt$ unicon -s entab.icn -x | cat -T
entab with stops at 4, 8, 12
^I^I^I Three tabs in
^I^I Two tabs in
^I One tab in
No tabs

EraseArea

EraseArea(w, x:0,y:0, wid:0, h:0, ...) : window

EraseArea(w, x,y, width,height) erases a rectangular area to the background colour. If width is 0, the region extends from x to the right. If height is 0, the region extends from y to the bottom. In 3D, EraseArea(w) clears the contents of the entire window.

#
# EraseArea.icn, demonstrate erasing part of a window
#
link cardbits
procedure main()
    &window := open("EraseArea", "g", "size=85,40", "canvas=hidden")

    # image data is "width, palette, pixels"
    img := cardbits()
    DrawImage(&window, 0, 0, img)
    EraseArea(&window, 10,10, 20,20)
    Bg("green")
    EraseArea(&window, 60,10, 20,20)

    # save image for the document
    WSync()
    WriteImage("../images/EraseArea.png")
    close(&window)
end

examples/EraseArea.icn

Sample run:

prompt$ unicon -s EraseArea.icn -x
_images/EraseArea.png

images/EraseArea.png


errorclear

errorclear() : null

errorclear() resets the keywords &errornumber, &errortext, &errorvalue to indicate that no error is present.

#
# errorclear.icn, Demonstrate error keyword condition reset 
#
link printf
procedure main()
    &error := 1
    nonexistent()

    # source line tracking not optimal here
    if &errornumber ~= 0 then
        write(printf("%s:%d Runtime error %d:%s", &file, &line-5,
                                    &errornumber, &errortext))

    errorclear()
    if &errornumber ~= 0 then
        write(printf("%s:%d Runtime error %d:%s", &file, &line-9,
                                    &errornumber, &errortext))
end

examples/errorclear.icn

A contrived example:

prompt$ unicon -s errorclear.icn -x
errorclear.icn:13 Runtime error 106:procedure or integer expected

Event

Event(w, i:infinity) : string|integer

Event(w, i) produces the next event available for window w. If no events are available, Event() waits i milliseconds. Keyboard events are returned as String while mouse events are returned as Integer. When an event is retrieved the keywords &x, &y, &row, &col, &interval, &control, &shift, and &meta are also set. If the 3D attribute “pick=on” is active, &pick is also set. Event() fails is there is a timeout before an event is available.

#
# Event.icn, demonstrate event returns
#
link enqueue, evmux
procedure main()
    window := open("Event", "g", "size=20,20", "canvas=hidden")

    # insert an event into the queue, left press, control and shift
    Enqueue(window, &lpress, 11, 14, "cs", 2)
    e := Event(window)
    write(image(e))

    # a side effect of the Event function is keywords settings
    write("&x:", &x)
    write("&y:", &y)
    write("&row:", &row)
    write("&col:", &col)
    write("&interval:", &interval)
    write("&control:", &control)
    write("&shift:", &shift)
    write("&meta:", &meta)
    
    close(window)
end

examples/Event.icn

Sample run, right-click while holding down shift and control keys:

prompt$ unicon -s Event.icn -x
-1
&x:11
&y:14
&row:2
&col:2
&interval:2
&control:
&shift:

eventmask

eventmask(CE, cset, T) : cset | null

eventmask(ce) returns the event mask associated with the program that created ce, or &null if there is no event mask. eventmask(ce, cs) sets that program’s event mask to cs. These settings control the Unicon monitoring triggers of a running program. A third Table argument, T, specifies a different value mask for each event code in the table; handy for filtering virtual machine instructions (which is event code E_Opcode as defined in evdefs.icn). Individual instruction codes are defined in opdefs.icn a file designed to be used with $include.

#
# eventmask.icn, display default execution monitor eventmask
#
procedure main()
    write("in main with eventmask ", image(eventmask(&current)))
    coex := create(write(image(eventmask(&current))))
    @coex
end

examples/eventmask.icn

Sample run:

prompt$ unicon -s eventmask.icn -x
in main with eventmask &null
&null

EvGet

EvGet(c, flag) : string [Execution Monitoring]

EvGet(c, flag) activates a program being monitored until an event in cset mask c occurs. Normally EvGet() returns a one character event code. c default is all events encoded in eventmask. flag controls the handling of out-of-band data, a null flag rejects out-of-band event data.

#
# EvGet.icn, demonstrate Execution Monitoring event get
# Needs 1to4.icn as the monitoring target
#

$include "evdefs.icn"
link evinit, printf

procedure main()
    # initialize the Target Process (a loaded task co-expression)
    EvInit("1to4")

    # loop across events until the task completes
    perline := 0
    while ec := EvGet() do {
        # keep the event code display all lined up
        if (perline +:= 1) > 16 then write() & perline := 1
        if ec == E_Fret then perline := 1
        # event code display in octal, to match evdefs.icn defines
        printf("%03o ", ord(ec))
    }
    write()
end

examples/EvGet.icn

Sample run:

prompt$ unicon -s EvGet.icn -x
275 271 240 240 272 103 274 273 240 240 242 241 274 273 240 241 
240 240 240 277 240 240 277 240 240 277 240 273 240 260 275 271 
263 273 240 260 111 113 116 111 113 163 163 261 273 240 272 363 
143 252 111 113 116 
1
255 240 240 251 264 276 271 275 271 263 273 240 260 111 113 116 
111 113 163 163 261 273 240 272 363 143 252 111 113 116 
2
255 240 240 251 264 276 271 275 271 263 273 240 260 111 113 116 
111 113 163 163 261 273 240 272 363 143 252 111 113 116 
3
255 240 240 251 264 276 271 275 271 263 273 240 260 111 113 116 
111 113 163 163 261 273 240 272 363 143 252 111 113 116 
4
255 240 240 251 264 276 271 262 251 273 240 274 273 240 246 240 
130

EvSend

EvSend(i, x, CE) : any

EvSend(c, v, ce) transmits event code c with value v to a monitored co-expression ce.

#
# EvSend.icn, demonstrate Execution Monitoring event send
# Needs 1to4.icn as the monitoring target
#
# WARNING: This is not a safe example, still learning
#

$include "evdefs.icn"
link evinit, printf

procedure main()
    # initialize the Target Process
    EvInit("1to4")

    # loop across the execution events
    perline := 0
    while ec := EvGet() do {
        # keep a neat event code display
        if (perline +:= 1) > 16 then write() & perline := 1
        if ec == E_Fret then perline := 1
        # event code display in octal to match evdefs defines
        printf("%03o ", ord(ec))

        #
        # DON'T DO THIS AT HOME
        #
        # if the current event is a conversion attempt for the 3
        # being working on in 1to4, tell the co-expression the
        # the conversion failed, (this skips over a conversion target
        # event) probably bugging out the VM
        #
        if ec == E_Aconv & &eventvalue === 3 then {
            writes("sending a conversion fail event, returned: ")
            write(image(EvSend(E_Fconv, &eventvalue, &eventsource)))
        }
    }
    write()
end

examples/EvSend.icn

Sample run (DANGEROUS, as this author doesn’t get the whole picture yet):

prompt$ unicon -s EvSend.icn -x
275 271 240 240 272 103 274 273 240 240 242 241 274 273 240 241 
240 240 240 277 240 240 277 240 240 277 240 273 240 260 275 271 
263 273 240 260 111 113 116 111 113 163 163 261 273 240 272 363 
143 252 111 113 116 
1
255 240 240 251 264 276 271 275 271 263 273 240 260 111 113 116 
111 113 163 163 261 273 240 272 363 143 252 111 113 116 
2
255 240 240 251 264 276 271 275 271 263 273 240 260 111 113 116 
111 sending a conversion fail event, returned: "K"
163 163 261 273 240 272 363 143 252 111 113 116 
3
255 240 240 251 264 276 271 275 271 263 273 240 260 111 113 116 
111 113 163 163 261 273 240 272 363 143 252 111 113 116 
4
255 240 240 251 264 276 271 262 251 273 240 274 273 240 246 240 
130

exec

exec(string, string,...) : null [POSIX]

exec(s, arg0, arg1,...) replaces the currently executing Unicon program with a new program, named s. Other arguments are passed to the program as the argument list. s must be a path to a binary executable program. To evaluate scripts, the s should be a shell such as /bin/sh.

#
# exec.icn, demonstrate the POSIX exec function
#
procedure main()
    exec("./exec-replacement", "argv0", "arglist[1]", "arglist[2]")
end

examples/exec.icn

#
# exec-replacement.icn, the program replaced by the exec function demo
#
procedure main(arglist)
    write(&progname)
    every write(!arglist)
end

examples/exec-replacement.icn

Sample run:

prompt$ unicon -s -C exec-replacement.icn
prompt$ unicon -s exec.icn -x
argv0
arglist[1]
arglist[2]

exit

exit(i)

exit() terminates the current program execution, returning a normal termination status code to the operating system (which will be system dependent, normally zero). exit(i) returns status code i.

#
# exit.icn, demonstrate shell exit status
#
procedure main()
    exit(42)
end

examples/exit.icn

Sample run:

prompt$ unicon -s exit.icn ; ./exit ; echo $?
42

exp

exp(r) : real

exp(r) returns &e raised to the power r.

#
# exp.icn, demonstrate the natural exponential function
#
procedure main()
    every r := 0 | 1 | 2 | &e do write("exp(", r, ") ", exp(r))
end

examples/exp.icn

Sample run:

prompt$ unicon -s exp.icn -x
exp(0) 1.0
exp(1) 2.718281828459045
exp(2) 7.38905609893065
exp(2.718281828459045) 15.15426224147926

Eye

Eye(w, s) : window

Eye(w) retrieves the current 3D eye parameters. Eye(w, s) sets the eyedir (direction), eyepos (position), eyeup (up vector) graphic attributes. Each of these is an x,y,z coordinate; defaulting to “0,0,0,0,0,-1,0,1,0”. For a 3D scene, changing the Eye() values will cause the entire window to be rendered from the new point of view.

  • eyepos, where the eye (camera) is located in x,y,z. Default is 0,0,0.
  • eyedir, where the eye is looking, defaults to looking into the negative z axis. 0,0,-1.
  • eyeup, what point in the 3D space is the up direction, defaults to the positive y axis. 0,1,0.
#
# Eye.icn, display the viewport reference
#
procedure main()
    w := open("Eye", "gl", "bg=red",
                    "size=400,300")#, "canvas=hidden")
    WAttrib(w,"light0=on, ambient blue-green","bg=white", "fg=ambient yellow")
    # A disk 
    DrawDisk(w, 0.4,-0.5,-4.0, 0.3,1.0)
    write(Eye(w))
    # save image for the document
    WSync(w)
    Refresh(w)
    WAttrib(w, "eyepos=4,-4,8.0")
    WSync(w)
    Refresh(w)
    write(Eye(w))
    WAttrib(w, "eyedir=1,0,0.4")
    Refresh(w)
    write(Eye(w))
    WriteImage(w, "../images/Eye.png")
    close(w)
end

examples/Eye.icn

Sample run (not auto captured):

prompt$ unicon -s Eye.icn -x
0.00,0.00,0.00,0.00,0.00,-100.00,0.00,1.00,0.00
4.00,-4.00,8.00,0.00,0.00,-100.00,0.00,1.00,0.00
4.00,-4.00,8.00,1.00,0.00,0.40,0.00,1.00,0.00

See also

WAttrib


Fail

Fail() : fail [Patterns]

The Fail() pattern signals a failure in a local portion of a pattern match. It causes the goal-directed evaluation engine to backtrack and seek alternatives. This is different from Abort which stops pattern matching, Fail() tells the system to back and try alternatives.

#
# Fail.icn, demonstrate Fail() SNOBOL pattern, forces backtracking
#
# Display one character per line by forcing alternatives for Len()
procedure main()
    sub := "Force backtrack"
    out := &output
    sub ?? Len(1) => out || Fail()
end

examples/Fail.icn

Sample run (taken from Unicon Technical Report 18, page 15):

prompt$ unicon -s Fail.icn -x
F
o
r
c
e
 
b
a
c
k
t
r
a
c
k

fcntl

fcntl(f, s, s) : integer|string|record [POSIX]

fcntl(file, cmd, arg) performs miscellaneous operations on the open file file. Directories and DBM files cannot be arguments to fcntl(). See fcntl(2).

The following characters are possible values for cmd:

  • f, Get flags (F_GETFL)
  • F, Set flags (F_SETFL)
  • x, Get close on exec flags (F_GETFD)
  • X, Set close on exec flags (F_SETFD)
  • l, Get file lock (F_GETLK)
  • L, Set file lock (F_SETLK)
  • W, Set file lock and wait (F_SETLKW)
  • o, Get file owner or process group (F_GETOWN)
  • O, Set file owner or process group (F_SETOWN)

In the case of L, the arg value should be a string that describes the lock, otherwise arg value is an Integer.

The lock string consists of three parts separated by commas:

  • the type of lock (r, w, or u)
  • the starting position
  • the length

The starting position can be an offset from the beginning of the file, n, the end of the file -n, or a relative position +n. A length of 0 means lock till EOF. These characters represent the file flags set by F_SETFL and retrieved with F_SETFL:

  • d, FNDELAY
  • s, FASYNC
  • a, FAPPEND
#
# fcntl.icn, demonstrate the POSIX fcntl function
#
link ximage
procedure main()
    f := open(&file, "r") | stop("Cannot open " || &file)
    every cmd := "f" | "x" | "o" do
        write(image(fcntl(f, cmd, 0)))
    write(ximage(fcntl(f, "l", "r,0,0")))
    close(f)
end

examples/fcntl.icn

Sample run:

prompt$ unicon -s fcntl.icn -x
""
0
0
R_posix_lock_1 := posix_lock()
   R_posix_lock_1.value := "u,0,0"
   R_posix_lock_1.pid := ""

fdup

fdup(f, f) : ? [POSIX]

fdup(src, dst) duplicates a file descriptor, by closing dst and setting src to that file descriptor; the dst fd is replaced by the src fd. See dup2(2). Commonly used with exec to manage standard in and standard out streams.

#
# fdup.icn, duplicate a POSIX file descriptor
#
procedure main()
    src := open("oldfile.txt", "r") #| stop("cannot open oldfile.txt")
    dst := open("newfile.txt", "r") #| stop("cannot open newfile.txt")
    write("org newfile: ", read(dst))
    if fdup(src, dst) then {
        write("read from newfile.txt will now look like oldfile.txt")
        write("dup newfile: ", read(dst))
        write("dup newfile: ", read(dst))
    }
    else
        write("fdup(src, dst) failed")
    close(src)
    close(dst)
end

examples/fdup.icn

Sample run:

prompt$ unicon -s fdup.icn -x
org newfile: newfile line 1
read from newfile.txt will now look like oldfile.txt
dup newfile: oldfile line 1
dup newfile: oldfile line 2

Fence

Fence() : type

Todo

entry for function Fence

Fence()

examples/Fence.icn

Sample run:


fetch

fetch(D, s) : string | row?

fetch(db, k) fetches the value corresponding to key k from a DBM or SQL database db. The result is a String for DBM or a row for SQL. If the key k is omitted for a current SQL query, fetch(db) produces the next row of the selection and advances the cursor to the next row. A row is a record where the field names and types are determined by the current query. fetch will fail if there are no more rows. Typically a call to sql will be followed by a while loop that calls fetch(db) until it fails.

#
# fetch.icn, demonstrate retrieving rows from ODBC
#
# tectonics: ~/.odbc.ini setup required for [unicon] 
#            assuming the [unicon] ODBC setup, SQLite3
#
procedure main()
    # mode 'o' open, ODBC SQL, default table and connection at defaults 
    db := open("unicon", "o", "", "") | stop("no ODBC for \"unicon\"")

    # Information below was created as part of examples/odbc.icn
    # sql(db, "create table contacts (id integer primary key, name, phone)")

    # make a query
    sql(db, "SELECT name, phone FROM contacts")

    while row := fetch(db) do {
        write("Contact: ", row.name, ", ", row.phone)
    }

    close(db)
end

examples/fetch.icn

Sample run:

prompt$ unicon -s fetch.icn -x
Contact: brian, 613-555-1212
Contact: jafar, 615-555-1213
Contact: brian, 615-555-1214
Contact: clint, 615-555-1215
Contact: nico, 615-555-1216

Fg

Fg(w, s) : string [graphics]

Fg(w) retrieves the current foreground colour. Fg(w, s) sets the foreground colour by name or value. Fg() fails if the foreground cannot be set to the given colour.

In 3D graphics, Fg(w, s) changes the material properties of subsequently drawn objects to those requested by s. The string s must be a semi-colon separated list of material properties. A material property is of the form:

diffuse | ambient | specular | emission | colour name | shininess n

Where shininess values range from 0 thru 128. Fg(w) retrieves the current values of the material properties.

#
# Fg.icn, demonstrate foreground colour settings
#
procedure main()
    window := open("Fg example", "g", "size=110,75", "canvas=hidden")
    write(window, Fg(window))

    Fg(window, "vivid orange")
    write(window, Fg(window))

    Fg(window, "10000,20000,30000")
    write(window, Fg(window))

    Bg(window, "black")
    Fg(window, "transparent green")
    write(window, Fg(window))
    Bg(window, "white")

    if c := NewColor(window, "40000,50000,60000") then {
        Fg(window, c)
        write(window, Fg(window))
    }
    else {
        Fg(window, "black")
        write(window, "no mutable colours")
    }

    WSync(window)
    WriteImage(window, "../images/Fg.png")
    FreeColor(\c)
    close(window)
end

examples/Fg.icn

Sample run:

prompt$ unicon -s Fg.icn -x

fieldnames

fieldnames(R) : strings*

fieldnames(r) generates the names of the fields in the record r.

#
# fieldnames.icn, demonstrate reflective fieldnames function
#

record sample(a,b,c,thing, other)

procedure main()
    R := sample(1,2,3,"xyz", [1,2,3])
    every write(fieldnames(R))
end

examples/fieldnames.icn

Sample run:

prompt$ unicon -s fieldnames.icn -x
a
b
c
thing
other

filepair

filepair() : list [POSIX]

filepair() creates a bi-directional pair of file, analogous to the POSIX socketpair(2) function. It returns a list of two indistinguishable files. Writes on one will be avaialable on the other. The connection is bi-directional, unlike that of the pipe function.

File pairs are typically created just before a fork operation. After forking, one process should close L[1] and the other should close L[2] for end of file notifications to work properly.

#
# filepair.icn, connected file streams
#
link ximage

procedure main()
    pair := filepair() | stop("filepair failed: ", sys_errstr(&errno))
    
    pid := fork() | stop("fork failed")
    if pid < 0 then stop("fork failed: ", pid)
    if pid = 0 then {
        close(pair[2])
        child(pair[1])
    } else {
        close(pair[1])
        parent(pair[2])
    }
    write("both: ", pid) 
end

#
# child, writer half
#
procedure child(out)
    write("Child ", image(out))
    every i := 1 to 10 do {
        write(out, "this is filepair write test ", i) | 
            stop("failed write")
        flush(out)
    }
    close(out)
end

#
# parent, reader half
#
procedure parent(in)
    write("Parent ", image(in))
    # needs to be a non-blocking read
    fcntl(in, "F", "d")

    limiter := 0
    until (limiter +:=1) > 200 do {
        if result := ready(in) then {
            write("parent received: ", image(result))
            break
        } else {
            delay(10)
        }
    }
    close(in)        
end

examples/filepair.icn

Sample run (skipped, bug report pending):


FillArc

FillArc(w, x, y, wid, h, a1:0.0, a2:&pi*2, ...) : window [graphics]

FillArc(w, x, y, width, height, a1, a2, ...) draws filled arcs or ellipses. Each arc is defined by 4 given and 2 derived coordinates. x, y, width, *height define a bounding rectangle around the arc; the centre of the arc is the point (x+(width)/2, y+(height)/2. Angle a1 is the starting position of the arc. The angle a2 is not an end position but specifies the direction and extent of the arc. Angles are given in radians. Multiple arcs can be drawn with one call to the function.

#
# FillArc.icn, demonstrate drawing a filled Arc
#
procedure main()
    &window := open("FillArc", "g",
                    "size=65,40", "canvas=hidden")
    # A filled arc, as ellipse
    Fg(&window, "vivid orange")
    FillArc(&window, 10, 10, 40, 20)

    # A partial arc, half ellipse
    Fg(&window, "blue")
    FillArc(&window, 26, 15, 10, 10, 0.0, &pi)

    # save image for the document
    WSync()
    WriteImage("../images/FillArc.png")
    close(&window)
end

examples/FillArc.icn

Sample run:

prompt$ unicon -s FillArc.icn -x

FillCircle

FillCircle(w, x, y, radius, a1:0.0, a2:&pi*2, ...) : window [graphics]

FillCircle(w, x, y, r, a1, a2) fills a circle centred at x,y. Otherwise similar to FillArc with width equal to height.

#
# FillCircle.icn, demonstrate drawing a filled circle
#
procedure main()
    w := open("FillCircle", "g", "size=40,40", "canvas=hidden")

    # A full circle, filled
    Fg(w, "vivid orange")
    FillCircle(w, 20, 20, 18)

    # A partial circle, filled
    Fg(w, "blue")
    FillCircle(w, 20, 20, 9, 0.0, &pi)

    # save image for the document
    WSync(w)
    WriteImage(w, "../images/FillCircle.png")
    close(w)
end

examples/FillCircle.icn

Sample run:

prompt$ unicon -s FillCircle.icn -x
_images/FillCircle.png

images/FillCircle.png


FillPolygon

FillPolygon(w, x1,y1[,z1], ..., xn,yn[,zn]) : window | list

FillPolygon(w, x1,y1, x2,y2, xn,yn) draws a filled polygon connecting each x,y pair (in 2D). In 3D, FillPolygon() takes from 2 to 4 coordinates per vertex and returns the list that represents the polygon on the display list.

#
# FillPolygon.icn, demonstrate drawing filled polygons
#
procedure main()
    &window := open("FillPolygon", "g", "size=45,30", "canvas=hidden")

    # a polygon using the procedural apply operator
    Fg("vivid orange")
    points := [5,5, 17,17, 5,17, 5,5]
    FillPolygon!points

    # save image for the document
    WSync()
    WriteImage("../images/FillPolygon.png")
    close(&window)
end

examples/FillPolygon.icn

Sample run:

prompt$ unicon -s FillPolygon.icn -x
_images/FillPolygon.png

images/FillPolygon.png


FillRectangle

FillRectangle(w, x1,y1, wid1, h1, ...) : window

FillRectangle(w, x, y, width, hieght) fills a rectangle with a top right corner of x,y and a perceived width and height. Actual rectangle is width+1 pixels wide, and height+1 pixels high.

#
# FillRectangle.icn, demonstrate drawing filled rectangles
#
procedure main()
    &window := open("FillRectangle", "g", "size=45,40", "canvas=hidden")

    Fg("vivid orange")
    FillRectangle(10,10, 20, 10)

    # save image for the document
    WSync()
    WriteImage("../images/FillRectangle.png")
    close(&window)
end

examples/FillRectangle.icn

Sample run:

prompt$ unicon -s FillRectangle.icn -x
_images/FillRectangle.png

images/DrawRectangle.png


find

find(s, s:&subject, i:&pos, i:0) : integer*

The string scanning function find(s1, s2, i1, i2) generates the positions where s1 occurs within s2[i1:i2]

#
# find.icn, demonstrate the find string scanning position generator
#
procedure main()
    if (p := find("xyz", "abc xyz def ghi xyz", 1, 0)) > 5 then write(p) 

    write()
    s := "The rain in Spain stays mainly in the plain"
    write("Subject: ", s)
    write("substring: in")
    s ? every write(find("in"))
end

examples/find.icn

Sample run:

prompt$ unicon -s find.icn -x
17

Subject: The rain in Spain stays mainly in the plain
substring: in
7
10
16
27
32
42

flock

flock(f, s) : ?

flock(f, s) applies an advisory lock to file f, given options s. Advisory locks can be shared or exclusive, but do not enforce exclusive access. The options can be

  • “s”, shared lock
  • “x”, exclusive lock
  • “b”, don’t block when locking
  • “u”, unlock

flock() cannot be used with window, directory or database files. See flock(2) for more information.

#
# flock.icn, demonstrate the POSIX flock advisory file locking function
#
procedure main()
    fn := "newfile.txt"
    f := open(fn, "r")
    write("requesting lock for ", fn)
    if flock(f, "xb") then
        write("got exclusive lock on ", fn)
    else
        write("lock attempt on ", fn, " failed")
    flock(f, "u")
    close(f)
end

examples/flock.icn

Sample run:

prompt$ unicon -s flock.icn -x
requesting lock for newfile.txt
got exclusive lock on newfile.txt

flush

flush(f) : file

flush(f) flushes all pending or buffered output to file f.

This will be hard to demonstrate in a document, but flushing output buffers can help with keeping full lines of output in synch on screen when threading, mixing I/O models or other times when buffering would get in the way of application goals.

#
# flush.icn, demonstrate flush of buffer output streams
#
procedure main()
    writes("flushing")
    flush(&output)
end

examples/flush.icn

Sample run:

prompt$ unicon -s flush.icn -x
flushing

Font

Font(w, s) : string

Font(w) produces the name of the current font for window w.

Font(w, s) sets the font to s for window w and produces the name, or fails if the font name is invalid.

Unicon ships with four portable fonts:

  • sans, proportional font without serifs
  • serif, proportional font with serifs
  • mono (or fixed), mono spaced font without serifs
  • typewriter, mono spaced font with serifs

Most other font names are system-dependent, and follow the format family[,styles],size. Styles can optionally add bold and/or italic. Font() fails if the requested font name does not exist.

#
# Font.icn, demonstrate Font setting and retrieval
#
procedure main()
    w := open("Font", "g", "size=666,160",
              "linestyle=solid", "canvas=hidden")
    write(w, "Default font: " || Font(w))

    # the Unicon portable fonts
    every font := "sans" | "serif" | "mono" | "typewriter" do {
        Font(w, font)
        write(w, font || ": " || &letters || &digits)
    }
    write(w)
    # Some specific GNU/Linux X11 fonts
    every font := "courier" | "r14" | "rk16" do {
        Font(w, font)
        write(w, font || ": " || &letters || &digits)
    }

    WSync(w)
    WriteImage(w, "../images/Font.png")
    close(w)
end

examples/Font.icn

Sample run:

prompt$ unicon -s Font.icn -x
_images/Font.png

images/Font.png


fork

fork() : integer

fork() creates a new process that is effectively identical to the current process except in the return value from fork (and some small amount of operating system “paperwork”). The current process will receive the PID (see getpid) of the child process. The forked process will receive a 0. Negative return values denote an error, a failure when the operating system attempted to create a new process.

#
# fork.icn, demonstrate process forking
#
procedure main()
    local sharedvar := 42

    # parent process
    i := fork() | stop("fork() fail")
    if i < 0 then stop("fork fail with ", i) 

    # at this point, two nearly identical processes are running
    # each will have a unique pid and "i" result
    # the variable "sharedvar" will be a copy. Both processes will
    # see it as 42 at first.  Child divides to 21, parent doubles to 84
    if i = 0 then {
        write("child process: ", right(i, 6), ", ", sharedvar)
        sharedvar /:= 2
    } else {
        write("parent process: ", right(i, 5), ", ", sharedvar)
        sharedvar *:= 2
    }
    # both processes will display this line and then end   
    write("sharedvar for ", if i = 0 then "child " else "parent",
          " process is now: ", sharedvar)
end

examples/fork.icn

Sample run:

prompt$ unicon -s fork.icn -x
parent process:  7754, 42
sharedvar for parent process is now: 84
child process:      0, 42
sharedvar for child  process is now: 21

FreeColor

FreeColor(w, s,...) : window

FreeColor(w, s) release colour s from the window system color map entries. If a colour is still in use when it is freed, unpredictable results will occur.

This is not deprecated, but is unnecessary with modern display technology. NewColor and FreeColor were initially developed at a time when display screens and graphics cards could only handle a limited palette of colours at any one time. A feature not required with monitors and cards that can handle millions of simultaneous colours.

#
# FreeColor.icn, demonstrate freeing created colours
#
procedure main()
    window := open("FreeColor", "g", "size=110,24", "canvas=hidden")
    if c := NewColor(window, "40000,50000,60000") then {
        Fg(window, c)
        write(window, Fg(window))
    }
    else {
        Fg(window, "black")
        write(window, "no mutable colours")
    }

    WSync(window)
    WriteImage(window, "../images/FreeColor.png")
    FreeColor(\c)
    close(window)
end

examples/FreeColor.icn

Sample run:

prompt$ unicon -s FreeColor.icn -x
_images/FreeColor.png

images/FreeColor.png


FreeSpace

FreeSpace(A) : null [MS-DOS]

This is an outdated MS-DOS specific feature of Unicon.

FreeSpace(A) frees an allocated memory block returned from GetSpace.

#
# FreeSpace.icn, an MS-DOS specific free a memory region
#
# This sample is UNTESTED, which means it counts as broken.
#
procedure main()
    s := "Hello, distant past"
    mem := GetSpace(*s)
    Poke(mem, s)
    from := Peek(mem, *s)
    write(image(from))
    # free the memory region
    FreeSpace(mem)
end

examples/FreeSpace.icn

Sample run (skipped on this GNU/Linux build machine):

See also

GetSpace, Peek, Poke, Int86


function

function() : string*

function() generates the names of the built-in functions.

#
# function.icn, demontrate the function() list of built-ins generator
#
link wrap
procedure main()
    write("Functions built into ", &version)
    write()
    wrap()
    every write(wrap(function() || ", ", 72))
    write(wrap()[1:-2])
end

examples/function.icn

Sample run:

prompt$ unicon -s function.icn -x
Functions built into Unicon Version 13.1.  August 19, 2019

Abort, Active, Alert, Any, Arb, Arbno, Attrib, Bal, Bg, Break, Breakx, 
Clip, Clone, Color, ColorValue, CopyArea, Couple, DrawArc, DrawCircle, 
DrawCube, DrawCurve, DrawCylinder, DrawDisk, DrawImage, DrawLine, 
DrawPoint, DrawPolygon, DrawRectangle, DrawSegment, DrawSphere, 
DrawString, DrawTorus, EraseArea, EvGet, EvSend, Event, Eye, Fail, 
Fence, Fg, FillArc, FillCircle, FillPolygon, FillRectangle, Font, 
FreeColor, GotoRC, GotoXY, IdentityMatrix, Len, Lower, MatrixMode, 
MultMatrix, NewColor, Normals, NotAny, Nspan, PaletteChars, 
PaletteColor, PaletteKey, Pattern, Pending, Pixel, PlayAudio, 
PopMatrix, Pos, PushMatrix, PushRotate, PushScale, PushTranslate, 
QueryPointer, Raise, ReadImage, Refresh, Rem, Rotate, Rpos, Rtab, 
Scale, Span, StopAudio, Succeed, Tab, Texcoord, TextWidth, Texture, 
Translate, Uncouple, VAttrib, WAttrib, WDefault, WFlush, WSection, 
WSync, WinAssociate, WinButton, WinColorDialog, WinEditRegion, 
WinFontDialog, WinMenuBar, WinOpenDialog, WinPlayMedia, WinSaveDialog, 
WinScrollBar, WinSelectDialog, WindowContents, WriteImage, abs, acos, 
any, args, array, asin, atan, atanh, bal, callout, center, char, chdir, 
chmod, chown, chroot, classname, close, cofail, collect, condvar, 
constructor, copy, cos, crypt, cset, ctime, dbcolumns, dbdriver, 
dbkeys, dblimits, dbproduct, dbtables, delay, delete, detab, display, 
dtor, entab, errorclear, eventmask, exec, exit, exp, fcntl, fdup, 
fetch, fieldnames, filepair, find, flock, flush, fork, function, get, 
getch, getche, getegid, getenv, geteuid, getgid, getgr, gethost, 
getpgrp, getpid, getppid, getpw, getrusage, getserv, gettimeofday, 
getuid, globalnames, gtime, hardlink, iand, icom, image, insert, 
integer, ioctl, ior, ishift, istate, ixor, kbhit, key, keyword, kill, 
left, list, load, loadfunc, localnames, lock, log, lstat, many, map, 
match, max, member, membernames, methodnames, methods, min, mkdir, 
move, mutex, name, numeric, open, oprec, ord, paramnames, parent, 
pattern_alternate, pattern_assign_immediate, pattern_assign_onmatch, 
pattern_boolfunccall, pattern_boolmethodcall, pattern_concat, 
pattern_match, pattern_setcur, pattern_stringfunccall, 
pattern_stringmethodcall, pattern_unevalvar, pindex_image, pipe, pop, 
pos, proc, pull, push, put, read, readlink, reads, ready, real, 
receive, remove, rename, repl, reverse, right, rmdir, rtod, runerr, 
seek, select, send, seq, serial, set, setenv, setgid, setgrent, 
sethostent, setpgrp, setpwent, setservent, setuid, signal, sin, sort, 
sortf, spawn, sql, sqrt, stat, staticnames, stop, string, structure, 
symlink, sys_errstr, system, syswrite, tab, table, tan, trap, trim, 
truncate, trylock, type, umask, unlock, upto, utime, variable, wait, 
where, write, writes

get

get(L, i:1) : any?

get(L) returns an element, which is removed from the head of the queue L. get(L, i) removes the first i elements, returning the last one removed.

#
# get.icn, demonstrate the queue get from head function
#
link lists
procedure main()
    L := []
    put(L, 1, 2, 3)
    item := get(L)
    write(item)
    write(limage(L))
end

examples/get.icn

Sample run:

prompt$ unicon -s get.icn -x
1
[2,3]

getch

getch() : string?

getch() waits (if necessary) for a character types at the console keyboard, even if standard input is redirected. The character is not echoed.

Note

On GNU/Linux getch doesn’t wait when stdin redirected

#
# getch.icn, wait for a keystroke
#
procedure main()
    writes("read: ")
    line := read()
    write(line)
    writes("getch: ")
    ch := getch()
    write()
    write("line from &input: ", line)
    write("character from getch(): ", image(ch))
end

examples/getch.icn

A sample run (captured outside document generation in this case)

prompt$ unicon -s getch.icn -x
read: stdin data
stdin data
getch:
line from &input: stdin data
character from getch(): "w"

getche

getche() : type

getche() waits (if necessary) for a character types at the console keyboard, even if standard input is redirected. The character is echoed.

Note

On GNU/Linux getche doesn’t wait when redirected, fails if no keypresses are pending

#
# getche.icn, wait for a keystroke, with echo
#
procedure main()
    writes("read: ")
    line := read()
    write(line)
    writes("getche: ")
    ch := getche()
    write()
    write("line from &input: ", line)
    write("character from getche(): ", image(ch))
end

examples/getche.icn

A sample run (captured outside document generation in this case)

read: typed from stdin
typed from stdin
getche: g
line from &input: typed from stdin
character from getche(): "g"

getegid

getegid() : string

getegid() produces the effective group identity of the current process. A name is returned if available, otherwise the numeric code is returned.

#
# getegid.icn, display the effective group identity
#
procedure main()
    write(getegid())
end

examples/getegid.icn

Sample run:

prompt$ unicon -s getegid.icn -x
btiffin

getenv

getenv(s) : string

getenv(s) retrieves the value of the environment variable s from the current process space.

#
# getenv.icn, demonstrate retrieving an environment variable
#
procedure main()
    write(getenv("SHELL"))
end

examples/getenv.icn

Sample run:

prompt$ unicon -s getenv.icn -x
/bin/bash

See also

setenv


geteuid

geteuid() : string

geteuid() returns the effective user identity for the current process. A name is returned if available, otherwise the numeric code is returned.

#
# geteuid.icn, display the effective user identity
#
procedure main()
    write(geteuid())
end

examples/geteuid.icn

Sample run:

prompt$ unicon -s geteuid.icn -x
btiffin

getgid

getgid() : string

getgid() produces the current group identity for the current process. A name is returned if available, otherwise a numeric code is produced.

#
# getgid.icn, display the current group identity
#
procedure main()
    write(getgid())
end

examples/getgid.icn

Sample run:

prompt$ unicon -s getgid.icn -x
btiffin

getgr

getgr(g) : record

getgr(g) produces a record the contains group file information for group g, a string group name of the integer group code. If g is null, each successive call to getgr() returns the next entry. As in read this value is given with return and is not a generator suspend.

Record is record posix_group(name, passwd, gid, members)

#
# getgr.icn, display the group file information
#
link fullimag, ximage

procedure main()
    limiter := 0
    #write(ximage(getgr("nobody")))
    while (limiter +:= 1) <= 10 & write(fullimage(getgr()))
end

examples/getgr.icn

Sample run:

prompt$ unicon -s getgr.icn -x
posix_group("root","x",0,"")
posix_group("daemon","x",1,"")
posix_group("bin","x",2,"")
posix_group("sys","x",3,"")
posix_group("adm","x",4,"syslog,btiffin")
posix_group("tty","x",5,"")
posix_group("disk","x",6,"")
posix_group("lp","x",7,"")
posix_group("mail","x",8,"")
posix_group("news","x",9,"")

gethost

gethost(x) : record|string

gethost(n) for network connection n produces a string containing the IP address and port number this machine is using for the connection. gethost(s) returns a record that contains the host information for the name s. If s is null, each successive call to gethost() returns the next entry. sethostent resets the sequence to the beginning. Aliases and addressed are comma separated lists (in a.b.c.d format).

The record type returned is record posix_hostent(name, aliases, addresses).

As in read this value is given with return and is not a generator suspend.

#
# gethost.icn, display host entities.
#
link fullimag, ximage

procedure main()
    limiter := 0
    write(ximage(gethost("localhost")))
    while (limiter +:= 1) <= 10 & write(fullimage(gethost()))
end

examples/gethost.icn

Sample run:

prompt$ unicon -s gethost.icn -x
R_posix_hostent_1 := posix_hostent()
   R_posix_hostent_1.name := "localhost"
   R_posix_hostent_1.aliases := "localhost"
   R_posix_hostent_1.addresses := "127.0.0.1"
posix_hostent("localhost","","127.0.0.1")
posix_hostent("btiffin-CM1745","","127.0.1.1")
posix_hostent("ip6-localhost","ip6-loopback","127.0.0.1")

getpgrp

getpgrp() : integer

getpgrp() produces the process group of the current process.

#
# getpgrp.icn, display the process group
#
procedure main()
    write(getpgrp())
end

examples/getpgrp.icn

Sample run:

prompt$ unicon -s getpgrp.icn -x
6468

getpid

getpid() : integer

getpid() produces the process identification (pid) of the current process.

#
# getpid.icn, display the current process identifier
#
procedure main()
    write(getpid())
end

examples/getpid.icn

Sample run:

prompt$ unicon -s getpid.icn -x
7872

getppid

getppid() : integer?

getppid() produces the process id of the parent of the current process.

#
# getppid.icn, display the parent process identification
#
procedure main()
    write(getppid())
end

examples/getppid.icn

Sample run:

prompt$ unicon -s getppid.icn -x
7882

getpw

getpw(u) : record

getpw(u) produces a record that contains account password file information. u can be a numeric uid or a user name. If u is null, each successive call to getpw() returns the next entry. As in read this value is given with return and is not a generator suspend. setpwent resets the sequence to the beginning.

Record type is:

record posix_password(name, passwd, uid, gid, age,
                      comment, gecos, dir, shell)

Most systems now contain a special marker x for the passwd field and the actual data is saved in a shadow file, safe from prying eyes. Even with access to the shadow data, the password is stored using crypt. The encrypted form makes it just that little bit easier to brute force guess the original password so the shadow data file was developed, with more restrictive permissions than the global passwd file that getpw accesses.

#
# getpw.icn, display passwd records.
#
link fullimag, ximage

procedure main()
    limiter := 0
    write(ximage(getpw("nobody")))
    # not showing this data
    #while write(fullimage(getpw()))
end

examples/getpw.icn

Sample run:

prompt$ unicon -s getpw.icn -x
R_posix_passwd_1 := posix_passwd()
   R_posix_passwd_1.name := "nobody"
   R_posix_passwd_1.passwd := "x"
   R_posix_passwd_1.uid := 65534
   R_posix_passwd_1.gid := 65534
   R_posix_passwd_1.gecos := "nobody"
   R_posix_passwd_1.dir := "/nonexistent"
   R_posix_passwd_1.shell := "/usr/sbin/nologin"

getrusage

getrusage(s) : record

getrusage(s) produces resource usage for s, where s can be “self”, “thread” or “children”. getrusage fails if resource usage cannot be retrieved for s.

Record type is:

record posix_rusage(utime, stime, maxrss, minflt, majflt,
                    inblock, oublock, nvcsw, nivcsw)

The utime and stime fields are record posix_timeval(sec, usec).

From getruage(2):

struct rusage {
    struct timeval ru_utime; /* user CPU time used */
    struct timeval ru_stime; /* system CPU time used */
    long   ru_maxrss;        /* maximum resident set size */
    long   ru_ixrss;         /* integral shared memory size */
    long   ru_idrss;         /* integral unshared data size */
    long   ru_isrss;         /* integral unshared stack size */
    long   ru_minflt;        /* page reclaims (soft page faults) */
    long   ru_majflt;        /* page faults (hard page faults) */
    long   ru_nswap;         /* swaps */
    long   ru_inblock;       /* block input operations */
    long   ru_oublock;       /* block output operations */
    long   ru_msgsnd;        /* IPC messages sent */
    long   ru_msgrcv;        /* IPC messages received */
    long   ru_nsignals;      /* signals received */
    long   ru_nvcsw;         /* voluntary context switches */
    long   ru_nivcsw;        /* involuntary context switches */
};                           /**/
#
# getrusage.icn, retrieve resource usage.
#
link fullimag, ximage

procedure main()
    every who := "self" | "thread" | "children" | "random" do {
        write(who)
        write(ximage(getrusage(who)))
        write(fullimage(getrusage(who)))
        write()
    }
end

examples/getrusage.icn

Sample run:

prompt$ unicon -s getrusage.icn -x
self
R_posix_rusage_1 := posix_rusage()
   R_posix_rusage_1.utime := R_posix_timeval_1 := posix_timeval()
      R_posix_timeval_1.sec := 0
      R_posix_timeval_1.usec := 8000
   R_posix_rusage_1.stime := R_posix_timeval_2 := posix_timeval()
      R_posix_timeval_2.sec := 0
      R_posix_timeval_2.usec := 0
   R_posix_rusage_1.maxrss := 6456
   R_posix_rusage_1.minflt := 570
   R_posix_rusage_1.majflt := 0
   R_posix_rusage_1.inblock := 0
   R_posix_rusage_1.oublock := 56
   R_posix_rusage_1.nvcsw := 2
   R_posix_rusage_1.nivcsw := 4
posix_rusage(posix_timeval(0,8000),posix_timeval(0,0),6456,575,0,0,56,2,4)

thread

children
R_posix_rusage_3 := posix_rusage()
   R_posix_rusage_3.utime := R_posix_timeval_5 := posix_timeval()
      R_posix_timeval_5.sec := 0
      R_posix_timeval_5.usec := 0
   R_posix_rusage_3.stime := R_posix_timeval_6 := posix_timeval()
      R_posix_timeval_6.sec := 0
      R_posix_timeval_6.usec := 0
   R_posix_rusage_3.maxrss := 2484
   R_posix_rusage_3.minflt := 176
   R_posix_rusage_3.majflt := 0
   R_posix_rusage_3.inblock := 0
   R_posix_rusage_3.oublock := 0
   R_posix_rusage_3.nvcsw := 5
   R_posix_rusage_3.nivcsw := 1
posix_rusage(posix_timeval(0,0),posix_timeval(0,0),2484,176,0,0,0,5,1)

random

getserv

getserv(s, s) : record

getserv(service, proto) retrieves the service database entry named s using protocol proto.

If s is null, each successive call to getserv() returns the next entry. setservent resets the sequence to the beginning.

As in read these values are given with return and not a generator suspend.

The record type returned is record posix_servent(name, aliases, port, proto).

#
# getserv.icn, display service information.
#
link fullimag, ximage

procedure main()
    limiter := 0
    write(ximage(getserv("echo", "udp")))
    write(ximage(getserv("echo", "tcp")))
    while sr := getserv() do if (limiter +:= 1) < 10 then
        write(fullimage(sr))
    write(limiter, " services in the database")
end

examples/getserv.icn

Sample run:

prompt$ unicon -s getserv.icn -x
R_posix_servent_1 := posix_servent()
   R_posix_servent_1.name := "echo"
   R_posix_servent_1.aliases := ""
   R_posix_servent_1.port := 7
   R_posix_servent_1.proto := "udp"
R_posix_servent_2 := posix_servent()
   R_posix_servent_2.name := "echo"
   R_posix_servent_2.aliases := ""
   R_posix_servent_2.port := 7
   R_posix_servent_2.proto := "tcp"
posix_servent("tcpmux","",1,"tcp")
posix_servent("echo","",7,"tcp")
posix_servent("echo","",7,"udp")
posix_servent("discard","sink,null",9,"tcp")
posix_servent("discard","sink,null",9,"udp")
posix_servent("systat","users",11,"tcp")
posix_servent("daytime","",13,"tcp")
posix_servent("daytime","",13,"udp")
posix_servent("netstat","",15,"tcp")
557 services in the database

For GNU/Linux the services data set is usually a plain text file, /etc/services.


GetSpace

GetSpace(i) : A [MSDOS]

This is an outdated MS-DOS specific feature of Unicon.

GetSpace(i) retrieves i bytes of memory outside normal Unicon control and garbage collection. The return value is an “address”, effectively a long integer.

#
# GetSpace.icn, an MS-DOS specific memory region allocator
#
# This sample is UNTESTED, which means it counts as broken.
#
procedure main()
    s := "Hello, distant past"
    # get some memory, the size of s
    mem := GetSpace(*s)
    Poke(mem, s)
    from := Peek(mem, *s)
    write(image(from))
    FreeSpace(mem)
end

examples/GetSpace.icn

Sample run (skipped on this GNU/Linux build machine):

See also

FreeSpace, Peek, Poke, Int86


gettimeofday

gettimeofday() : record

gettimeofday() returns the current time in seconds and microseconds since the epoch, January 1st, 1970 at 00:00:00, Greenwich Mean Time. The sec field may be converted to a date string with the ctime or gtime functions.

Returns record posix_timeval(sec, usec).

#
# gettimeofday.icn, retrieve the second and microsecond clock values
#
procedure main()
    R := gettimeofday()
    write(R.sec," seconds since the Unix epoch")
    write(R.usec, " microsecond counter")
    write(ctime(R.sec))
end

examples/gettimeofday.icn

Sample run:

prompt$ unicon -s gettimeofday.icn -x
1572024127 seconds since the Unix epoch
729956 microsecond counter
Fri Oct 25 13:22:07 2019

getuid

getuid() : string [POSIX]

getuid() produces the real user identity of the current process.

#
# getuid.icn, display the current user identity
#
procedure main()
    write(getuid())
end

examples/getuid.icn

Sample run:

prompt$ unicon -s getuid.icn -x
btiffin

globalnames

globalnames(CE) : string*

globalnames(ce) generates the names of the global variable in the program that create the co-expression ce.

#
# globalnames.icn, generate globalnames
#
global var, other
procedure main()
    local lv
    static sv
    lv := 1
    sv := 1
    var := 1
    every write(globalnames(&main))
end

examples/globalnames.icn

Sample run:

prompt$ unicon -s globalnames.icn -x
main
var
write
globalnames

Note how other isn’t listed. It would need to be set to show up.


GotoRC

GotoRC(w, row:1, col:1) : window [Graphics]

GotoRC(w, r, c) moves the text cursor to row r, column c, on window w. Row and column are given in character positions. The upper left is (1,1). The column is calculated using the pixel width of the widest character in the current font. Works best with fixed width fonts. Row is determined by the height of the current font.

#
# GotoRC.icn, set graphic text cursor to row and column
#
procedure main()
    w := open("GotoRC", "g", "size=130,60", "canvas=hidden")
    text := "Initial message"
    write(w, text)

    text := "Placed message"
    GotoRC(w, 3,5)
    Fg(w, "purple")
    write(w, text)

    WSync(w)
    WriteImage(w, "../images/GotoRC.png")
    close(w)
end

examples/GotoRC.icn

Sample run:

prompt$ unicon -s GotoRC.icn -x
_images/GotoRC.png

images/GotoRC.png


GotoXY

GotoXY(w:&window, x:0, y:0) : window [Graphics]

GotoXY(w, x, y) moves the text cursor to a specific cursor location, x, y (given in pixels) on window w.

#
# GotoXY.icn, set graphic text cursor to x,y
#
procedure main()
    w := open("GotoXY", "g", "size=130,60", "canvas=hidden")
    text := "Initial message"
    write(w, text)

    text := "Placed message"
    GotoXY(w, 10,40)
    Fg(w, "purple")
    write(w, text)

    WSync(w)
    WriteImage(w, "../images/GotoXY.png")
    close(w)
end

examples/GotoXY.icn

Sample run:

prompt$ unicon -s GotoXY.icn -x
_images/GotoXY.png

images/GotoXY.png


gtime

gtime(i) : string

gtime(i) converts the integer time i, given in seconds since the epoch of Jan 1st, 1970 00:00:00 Greenwich Mean Time, into a string, based on GMT.

#
# gtime.icn, Demonstrate the gtime function
#
procedure main()
    # convert epoch start to a formatted time
    write(gtime(0))

    # convert time of run to formatted time
    write(gtime(&now), " Greenwich Mean Time")

    # two days in the future (relative to time of run)
    write(gtime(&now + 48 * 60 * 60))
end

examples/gtime.icn

Sample run:

Thu Jan  1 00:00:00 1970
Fri Oct 25 17:22:09 2019 Greenwich Mean Time
Sun Oct 27 17:22:09 2019

See also

&clock, ctime, &dateline, &now


iand

iand(i, i) : integer

iand(i1, i2) produces the bitwise AND of i1 and i2.

#
# iand.icn, bitwise AND of two integers
#
link printf
procedure main()
    i1 := 7
    i2 := 3
    write(printf("iand(%d, %d) = %d", i1, i2, iand(i1, i2)))

    # create some large integers
    i1 := 2^66 + 7
    i2 := 2^67 + 2^66 + 3
    write(printf("iand(%d, %d) = %d", i1, i2, iand(i1, i2)))
end

examples/iand.icn

Sample run:

prompt$ unicon -s iand.icn -x
iand(7, 3) = 3
iand(73786976294838206471, 221360928884514619395) = 73786976294838206467

icom

icom(i) : integer

icom(i) produces the bitwise one’s complement of i.

#
# icom.icn, bitwise one's complements of integer
#
link printf
procedure main()
    i := 7
    write(printf("icom(%d) = %d", i, icom(i)))

    # create a large integers
    i := 2^66 + 7
    write(printf("icom(%d) = %d", i, icom(i)))
end

examples/icom.icn

Sample run:

prompt$ unicon -s icom.icn -x
icom(7) = -8
icom(73786976294838206471) = -73786976294838206472

IdentityMatrix

IdentityMatrix(window) → record
Type:pattern
Requires:3D graphics

Replaces the current 3D graphic matrix to the identity matrix. Returns the display list element.

#
# IdentityMatrix.icn, demonstrate matrix transforms
# Curerntly a work in progress
#
link fullimag
procedure main()
    window := open("IdentityMatrix", "gl", "bg=black", "buffer=on",
                    "size=400,260", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")

    # A torus 
    DrawTorus(window, 0.0,0.19,-2.2, 0.3,0.4)
    Refresh(window)
    MatrixMode(window, "projection")
    PushMatrix(window)
    
    write(image(IdentityMatrix(window)))
    write(fullimage(PopMatrix(window)))
    
    # save image for the document
    Refresh(window)
    WSync(window)
    WriteImage(window, "../images/IdentityMatrix.png")
    close(window)
end

examples/IdentityMatrix.icn

Sample run (not auto captured):

prompt$ unicon -s IdentityMatrix.icn -x
gl_pushmatrix("PopMatrix",224)

See also

PushMatrix, PopMatrix, Eye


image

image(x) : string

image(x) produces a string image of x.

#
# image.icn, demonstrate string image function
#
link ximage, fullimag
procedure main()
    s := "abc"
    cs := 'cba'
    L := [1,2,3]

    write("s is ", s, " image is ", image(s))
    write("cs is ", cs, " image is ", image(cs))
    write("list L image is ", image(L))
    write("fullimage(L) is ", fullimage(L))
    write("ximage(L) is ", ximage(L))
end

examples/image.icn

Sample run:

prompt$ unicon -s image.icn -x
s is abc image is "abc"
cs is abc image is 'abc'
list L image is list_1(3)
fullimage(L) is [1,2,3]
ximage(L) is L1 := list(3)
   L1[1] := 1
   L1[2] := 2
   L1[3] := 3

InPort

InPort(i) : integer [MS-DOS]

InPort(i) will read a byte value from port i. This is an MS-DOS specific feature of Unicon.

#
# InPort.icn, read a value from an MS-DOS port
#
procedure main()
    write(InPort(1))
end

examples/InPort.icn

Sample run (skipped on this GNU/Linux build machine):

See also

OutPort


insert

insert(x1, x2, x3:&null, ...) : x1

insert(x1, x2, x3) inserts element x2 into List (arrays), Set, Table or DBM database x1, if it is not already a member.

For lists, tables and databases the assigned value for x2 is x3. For lists, x2 is an integer index, and for other types x2 is a key. For sets, x3 is taken as another element to insert. insert() always succeeds and returns x1. In Unicon, multiple elements can be inserted in one call.

#
# insert.icn, demonstrate element insert function
#
link fullimag
procedure main()
    L := list()
    S := set()
    T := table()
    k := 1
    v := 2
   
    insert(L, k, v, 3, 4)
    insert(S, k, v, 3, 4)
    insert(T, k, v, 3, 4)

    write(fullimage(L))
    write(fullimage(S))
    write(fullimage(T))
end

examples/insert.icn

Sample run:

prompt$ unicon -s insert.icn -x
[2]
set(1,2,3,4)
table(1->2,3->4)

Int86

Int86(list) : list [MS-DOS]

This is an MS-DOS specific Unicon feature.

Int86(L) performs an MS-DOS interrupt routine. The list L must contain nine integer values. The first value is a flag value, the rest will be stored in ax,bx,cx,dx,si,di,es,ds CPU registers, in that order. After the dispatch to the interrupt vector in flag, via the int386x C library function, the returned list will be set with the cflag and register values as set by DOS.

Attention

This feature is specific to MS-DOS on Intel chips and is relatively dangerous. A programmer must know what are safe values for the registers before using this, now mostly outdated, feature.

#
# Int86.icn, perform an MS-DOS interrupt 21h support routine.
#
# This sample is UNTESTED, and the feature itself is outdated.
#
procedure main()
    # Get disk transfer address
    flag := 16r21
    ax := 16r2f00
    result := Int86([flag, ax] ||| list(7, 0))
    # filename location is 16 * es + cx (result[8], [3]) + 30
    # further access will require use of GetSpace, Peek and Poke
end

examples/Int86.icn

Sample run (skipped on this GNU/Linux build machine):

See ipl/procs/io.icn for an old working example of Int86().

See also

GetSpace, Peek, Poke


integer

integer(any) : integer?

integer(x) converts the value x to an integer, or fails if the conversion cannot be performed.

#
# integer.icn, convert to integer
#
procedure main()
    every x := 123 | "123" | "abc" | 123.123 do
        write("integer(", image(x), ") is ", integer(x) | "not converted")
end

examples/integer.icn

Sample run:

prompt$ unicon -s integer.icn -x
integer(123) is 123
integer("123") is 123
integer("abc") is not converted
integer(123.123) is 123

ioctl

ioctl(f, i, s) : integer

ioctl(f, i, s) passes the options in s to the open special device file channel f, given an integer action specified in i.

#
# ioctl.icn, special device, driver contol function
#
# ** work in progress **
procedure main()
    action := 12345
    options := "option block"
    f := open("/dev/null", "r")
    ioctl(f, action, options)
    close(f)
end

examples/ioctl.icn

Todo

ioctl demo

Sample run (pending):


ior

ior(i, i) : integer

ior(i1, i2) produces the bitwise OR of i1 and i2.

#
# ior.icn, bitwise OR of two integers
#
link printf
procedure main()
    i1 := 7
    i2 := 3
    write(printf("ior(%d, %d) = %d", i1, i2, ior(i1, i2)))

    # create some large integers
    i1 := 2^66 + 7
    i2 := 2^67 + 2^66 + 3
    write(printf("ior(%d, %d) = %d", i1, i2, ior(i1, i2)))
end

examples/ior.icn

Sample run:

prompt$ unicon -s ior.icn -x
ior(7, 3) = 7
ior(73786976294838206471, 221360928884514619395) = 221360928884514619399

ishift

ishift(i, i) : integer

ishift(i, j) produces the value from shifting i by j bit positions. Shift left for positive j and shift right for negative j. Zero bits are shifted in.

#
# ishift.icn, bitwise shift
#
link printf
procedure main()
    shift := 3
    every i := 7 | -7 do {
        # shift right, low bit zero fill
        write(printf("ishift(%d, %d) = %d", i, shift, ishift(i, shift)))
    }

    # shift left, high bit zero fill
    shift := -3
    every i := 7 | -7 do {
        # shift right, low bit zero fill
        write(printf("ishift(%d, %d) = %d", i, shift, ishift(i, shift)))
    }

    # using large integer
    i := 2^66 + 7
    write(printf("ishift(%d, %d) = %d", i, shift, ishift(i, shift)))
end

examples/ishift.icn

Sample run:

prompt$ unicon -s ishift.icn -x
ishift(7, 3) = 56
ishift(-7, 3) = -56
ishift(7, -3) = 0
ishift(-7, -3) = -1
ishift(73786976294838206471, -3) = 9223372036854775808

istate

istate(CE, s) : integer

istate(ce, attrib) reports selected virtual machine interpreter state information for ce. Used by monitors. attrib must be one of:

  • “count”
  • “ilevel”
  • “ipc”
  • “ipc_offset”
  • “sp”
  • “efp”
  • “gfp”

Todo

what do the attribute fields actually mean

#
# istate.icn, report selected vm interpreter state information
#
procedure main()
    every attr := "count" | "ilevel" | "ipc" | "ipc_offset" |
                  "sp" | "efp" | "gfp" do {
        write("attribute ", attr, " = ", istate(&main, attr))
    }
end

examples/istate.icn

Sample run:

prompt$ unicon -s istate.icn -x
attribute count = 0
attribute ilevel = 1
attribute ipc = 36077760
attribute ipc_offset = 640
attribute sp = 140215531963312
attribute efp = 140215531963176
attribute gfp = 0

ixor

ixor(i, i) : integer

ixor() produces the bitwise exclusive OR (XOR) of i1 and i2.

#
# ixor.icn, bitwise XOR of two integers
#
link printf
procedure main()
    i1 := 7
    i2 := 3
    write(printf("ixor(%d, %d) = %d", i1, i2, ixor(i1, i2)))

    # create some large integers
    i1 := 2^66 + 7
    i2 := 2^67 + 2^66 + 3
    write(printf("ixor(%d, %d) = %d", i1, i2, ixor(i1, i2)))
end

examples/ixor.icn

Sample run:

prompt$ unicon -s ixor.icn -x
ixor(7, 3) = 4
ixor(73786976294838206471, 221360928884514619395) = 147573952589676412932

kbhit

kbhit() : ?

kbhit() checks to see if there is a keyboard character waiting to be read. Returns null or fails when no events are pending.

#
# kbhit.icn, see if there is a keyboard event pending
#
procedure main()
    # eat any stray characters
    while kbhit() do getch()

    delay(1000)
    write()

    if kbhit() then write("key press pending:", image(getch()))
    else write("no keys pressed during delay")
end

examples/kbhit.icn

Sample run (captured outside documentation generation)

prompt$ unicon -s kbhit.icn -x
a
key press pending:"a"

The echo of a (tapped during the delay) was from the GNU/Linux console, stty set to echo.


key

key(x) : any*

key(T) generates the key values from Table T. key(L) generates the indices from 1 to *L in List (arrays) L. key(R) generates the string field names of record R.

#
# key.icn, generate the keys of a structure
#
link wrap
record sample(x,y,z)
procedure main()
    L := [1,2,3]
    R := sample(1,2,3)
    T := table()
    insert(T, "a", 1, "b", 2, "c", 3)

    write("keys of list L, record R, table T")
    wrap()
    every f := L | R | T do { 
        every writes(wrap(key(f) || ", "))
        write(wrap()[1:-2])
    }
end

examples/key.icn

Sample run:

prompt$ unicon -s key.icn -x
keys of list L, record R, table T
1, 2, 3
x, y, z
c, b, a

keyword

keyword(s, CE:&current,i:0) : any*

keyword(s, ce, i) produces the value(s) of keyword s in the context of ce execution, i levels up the stack from the current point of execution. Used in execution monitors

 8
 9
10
11
12
13
14
15
16
#
# keyword.icn, retrieve value(s) of keywords from co-expressions
#
procedure main()
    ce1 := create |write(keyword("&line", &current, 0))
    @ce1
    write(&line)
    @ce1
end

examples/keyword.icn

Sample run:

prompt$ unicon -s keyword.icn -x
12
14
12

kill

kill(i, x) : ? [POSIX]

kill(pid, signal) sends a signal to the process specified by pid. The signal parameter can be a string name or the integer code for the signal to be sent.

From src/runtime/rposix.r

stringint signalnames[] = {
   { 0,         40 },
   { "SIGABRT",     SIGABRT },
   { "SIGALRM",         SIGALRM },
   { "SIGBREAK",        SIGBREAK },
   { "SIGBUS",          SIGBUS },
   { "SIGCHLD",         SIGCHLD },
   { "SIGCLD",      SIGCLD },
   { "SIGCONT",         SIGCONT },
   { "SIGEMT",          SIGEMT },
   { "SIGFPE",          SIGFPE },
   { "SIGFREEZE",   SIGFREEZE },
   { "SIGHUP",          SIGHUP },
   { "SIGILL",          SIGILL },
   { "SIGINT",          SIGINT },
   { "SIGIO",           SIGIO },
   { "SIGIOT",          SIGIOT },
   { "SIGKILL",         SIGKILL },
   { "SIGLOST",         SIGLOST },
   { "SIGLWP",      SIGLWP },
   { "SIGPIPE",         SIGPIPE },
   { "SIGPOLL",     SIGPOLL },
   { "SIGPROF",         SIGPROF },
   { "SIGPWR",          SIGPWR },
   { "SIGQUIT",         SIGQUIT },
   { "SIGSEGV",         SIGSEGV },
   { "SIGSTOP",         SIGSTOP },
   { "SIGSYS",          SIGSYS },
   { "SIGTERM",         SIGTERM },
   { "SIGTHAW",     SIGTHAW },
   { "SIGTRAP",         SIGTRAP },
   { "SIGTSTP",         SIGTSTP },
   { "SIGTTIN",         SIGTTIN },
   { "SIGTTOU",         SIGTTOU },
   { "SIGURG",          SIGURG },
   { "SIGUSR1",         SIGUSR1 },
   { "SIGUSR2",         SIGUSR2 },
   { "SIGVTALRM",       SIGVTALRM },
   { "SIGWAITING",  SIGWAITING },
   { "SIGWINCH",        SIGWINCH },
   { "SIGXCPU",         SIGXCPU },
   { "SIGXFSZ",         SIGXFSZ },
};
#
# kill.icn, send signal to PID
#
procedure main()
    write("send signal to kill current process")
    kill(getpid(), "SIGKILL")
    write("won't get here")
end

examples/kill.icn

Sample run (with error termination code, due to kill):

prompt$ unicon -s kill.icn -x
send signal to kill current process
Killed

left

left(s, i:1, s:" ") : string

left(s1, i, s2) formats s1 to be a string of length i. If s1 has more than i characters, it is truncated. If s1 has less than i characters then it is padded to the right with as many copies of s2 needed to increase the length to i. Last copy of s2 is left side truncated if necessary (“filler” will pad as “ller” for instance).

#
# left.icn, fill out a string to length, truncate or pad fill on right
#
procedure main()
    s := "abcdefghij"
    write(":", left(s, 5), ":")
    write(":", left(s, 10), ":")
    write(":", left(s, 20), ":")
    write(":", left(s, 20, "filler"), ":")
end

examples/left.icn

Sample run:

prompt$ unicon -s left.icn -x
:abcde:
:abcdefghij:
:abcdefghij          :
:abcdefghijllerfiller:

Len

Len(i) : string [Patterns]

Len(n) is a SNOBOL pattern that matches the next n characters, or fails if not enough characters remain in the subject. Len(0) matches the empty string.

#
# Len.icn, demonstrate Len() SNOBOL pattern matching n characters
#
# Display the first 12 characters of subject
procedure main()
    sub := "IMPORTANT   Message for tag"
    sub ?? Len(12) => tag
    write(":", tag, ": ", *tag)
end

examples/Len.icn

Sample run:

prompt$ unicon -s Len.icn -x
:IMPORTANT   : 12

list

list(i:0, any:&null) : list

list(i, x) creates a list of size i, with all initial values set to x. If x is a mutable value, such as a list, all elements refer to the same value, not a separate copy.

#
# list.icn, demonstrate the list creation function
#
link lists
procedure main()
    L1 := [1,2,3]
    L2 := list(5, L1)
    every Lt := !L2 do write(limage(Lt))
    delete(L1, 2)
    every Lt := !L2 do write(limage(Lt))
end

examples/list.icn

Sample run:

prompt$ unicon -s list.icn -x
[1,2,3]
[1,2,3]
[1,2,3]
[1,2,3]
[1,2,3]
[1,3]
[1,3]
[1,3]
[1,3]
[1,3]

load

load(s, L, f:&input, f:&output, f:&errout,i,i,i) : co-expression

load(s, arglist, input, output, error, block, string, stack) loads the icode file named s and returns the program as a co-expression, ready to start in the loaded main() procedure with arglist as the command line arguments. The three file parameters are used as the &input, &output and &errout for the program co-expression. The three integers are used to set initial memory region sizes for block, string, and stack.

#
# load.icn, demonstrate loading icode files into the multitasker
#
procedure main()
    write("Loading ./load-module")
    lp := load("load-module", ["a", "b", "c"])
    write("Evaluating main of load-module")
    @lp
    write("Back in initial program")
end

examples/load.icn

#
# load-module.icn, a demonstration module for use with load sample.
#
procedure main(arglist)
    every write(!arglist)
end

examples/load-module.icn

Sample run:

prompt$ unicon -s load-module.icn
prompt$ unicon -s load.icn -x
Loading ./load-module
Evaluating main of load-module
a
b
c
Back in initial program

loadfunc

loadfunc(libname:string, funcname:string) → procedure

loadfunc() reads libname to load a C foreign function funcname returning a procedure value. Uses the IPL support file, icall.h.

#
# loadfunc.icn, demonstrate loadfunc
#
procedure main(arglist)
    ffi := loadfunc("./loaded.so", "loaded")
    write("Type of ffi: ", type(ffi))
   
    # default arg of 21, half of the ultimate answer
    param := arglist[1] | 21
    write("loaded function mutiply by two, ffi(", param, ") = ",
          ffi(param))
end

examples/loadfunc.icn

All loadable functions require a Unicon compatible prototype:

int cfunction(int argc, descriptor *argv)

or, equivalent

int cfunction(int argc, struct descriptor argv[])

That is, a function returning an integer that accepts a count of arguments and a pointer to a special array of structures that hold encoded argument values.

The C function is expected to return an integer, 0 for success, -1 for failure with positive values being error codes.

Arguments are marshalled to and from Icon with a special bit encoded structure with slots for data or pointer to data. Unicon Integer, Real, String and List data can be encoded for passing between C and Unicon.

descriptor

A descriptor is an opaque internal data structure.

typedef long word;
typedef struct descrip {
   word dword;
   union {
      word integr;              /*   integer value */
#if defined(DescriptorDouble)
      double realval;
#endif
      char *sptr;               /*   pointer to character string */
      union block *bptr;        /*   pointer to a block */
      struct descrip *descptr;  /*   pointer to a descriptor */
      } vword;
} descriptor, *dptr;            /**/

argv[0] is reserved for the actual value delivered to Unicon on return from the external C function.

/*
 loaded.c, a Unicon loadable external function
 tectonics: gcc -shared -fpic -o loaded.so loaded.c
 icall.h copied from unicon tree ipl/cfuncs
*/

#include <stdio.h>
#include "icall.h"

int
loaded(int argc, descriptor *argv)
{
#ifdef DEBUG
    /* look at count and the pointer */
    printf("argc: %d, argv: %p\n", argc, argv);
    fflush(stdout);
#endif

    /* Ensure an integer arg 1 */
    if (argc < 1) {
        ArgError(argc, 101);
    }

    ArgInteger(1);

#ifdef DEBUG
    /* show the operational step */
    printf("argv[argc]: %ld\n", IntegerVal(argv[argc])); 
#endif

    RetInteger(IntegerVal(argv[argc]) * 2);
}

examples/loaded.c

That code exercises some of the helper macros defined in icall.h.

void ArgInteger(int index)

ArgInteger ensures the argument at argv[index] is an native integer, or fails and returns an errorcode. Marked void as ArgInteger is actually a code fragment macro, not an actual function.

void ArgError(int index, int errorcode)

ArgError returns argv[index] as an offending value, with errorcode. Marked void as ArgError is actually a code fragment macro, not an actual function.

int RetInteger(int result)

RetInteger returns an integer for use as a Unicon function result.

Sample run:

prompt$ gcc -shared -fpic -o loaded.so loaded.c
prompt$ unicon -s loadfunc.icn -x
Type of ffi: procedure
loaded function mutiply by two, ffi(21) = 42

Sample with an erroneous value passed:

prompt$ unicon -s loadfunc.icn -x "abc"
Type of ffi: procedure

Run-time error 101
File loadfunc.icn; Line 17
integer expected or out of range
offending value: "abc"
Traceback:
   main(list_1 = ["abc"])
   loaded("abc") from line 17 in loadfunc.icn

See Programs for some examples of loading scripting engines, like Ruby, S-Lang and Javascript, into Unicon and integration with other languages, like GnuCOBOL.


localnames

localnames(C:co-expression, i:integer:0) : string*

localnames(C, i) generates the names of local variables in co-expression C, i levels up from the current procedure invocation. The default, level 0, generates names in the currently active procedure inside C.

#
# localnames.icn, generate local names
#
global var, other
procedure main(arglist)
    local lv
    static sv
    lv := 1
    sv := 1
    var := 1
    every write(localnames(&main))
end

examples/localnames.icn

Sample run:

prompt$ unicon -s localnames.icn -x
lv

lock

lock(x) : x

lock(x) locks the mutex x, or the mutex associated with the thread-safe object x.

#
# lock.icn, demonstrate mutual exclusive region locking
#
global x

procedure main()
    mx := mutex()
    x := 0
    t1 := thread incrementor(mx)
    t2 := thread incrementor(mx)
    every wait(t1 | t2)
    write("x = ", x)
end

procedure incrementor(m)
    lock(m)
    # a non atomic increment expression; fetch x,  add to x, store x
    x := x + 1
    unlock(m)
end

examples/lock.icn

Sample run:

prompt$ unicon -s lock.icn -x
x = 2

log

log(r, r:&e) : real

log(r, b) generates the logarithm of r in base b.

#
# log.icn, return a logarithm in a given base, default natural logarithm
#
procedure main()
    write("log(10) base &e default: ", log(10))
    write("log(10, 10) ", log(10, 10))
    write("log(100, 10) ", log(100, 10))
end

examples/log.icn

Sample run:

prompt$ unicon -s log.icn -x
log(10) base &e default: 2.302585092994046
log(10, 10) 1.0
log(100, 10) 2.0

Lower

Lower(w) : window

Lower(w) moves window w to the bottom of the window stack. The window may end up obscured, hidden behind other windows.

#
# Lower.icn, lower a window to the bottom of the window stack
#
procedure main()
    w := open("main", "g", "size=150,50", "canvas=hidden")
    lower := open("Lower", "g", "size=200,100", "canvas=hidden")
    Lower(lower)
    WSync(w, lower)
    close(lower, w)
end

examples/Lower.icn

Sample run:

prompt$ unicon -s Lower.icn -x
_images/Lower.png

images/Lower.png

See also

Raise


lstat

lstat(f) : record? [POSIX]

lstat(f) returns a record of filesystem information for file (or path) f. Does not follow symbolic links, if f is a symlink, then information about the symlink is returned. See stat.

Return record is:

record posix_stat(dev, ino, mode, nlink, gid, rdev, size,
                  atime, mtime, ctime, blksize, blocks, symlink)

The atime, ctime, and mtime fields may be formatted with the ctime() and gtime() functions. mode is a string form similar to the output of ls -l. lstat() will fail if the file or path f does not exist.

#
# lstat.icn, File status information, does not follow symbolic links.
#
link ximage
procedure main()
    fn := "/usr/bin/cc"
    write("lstat(", fn, "): ", ximage(lstat(fn)))
end

examples/lstat.icn

Sample run:

prompt$ unicon -s lstat.icn -x
lstat(/usr/bin/cc): R_posix_stat_1 := posix_stat()
   R_posix_stat_1.dev := 2049
   R_posix_stat_1.ino := 4325501
   R_posix_stat_1.mode := "lrwxrwxrwx"
   R_posix_stat_1.nlink := 1
   R_posix_stat_1.uid := "root"
   R_posix_stat_1.gid := "root"
   R_posix_stat_1.rdev := 0
   R_posix_stat_1.size := 20
   R_posix_stat_1.atime := 1571985764
   R_posix_stat_1.mtime := 1452760995
   R_posix_stat_1.ctime := 1452760995
   R_posix_stat_1.blksize := 4096
   R_posix_stat_1.blocks := 0

many

many(c, s, i, i) : integer?

many(c, s, i1, i2) produces the position in s after the longest initial sequence of members of c within s[i1:i2]. A goal directed generator, but returns after the first match.

#
# many.icn, string scanning function scans for matches of many characters
#
procedure main()
    cs := &lcase
    s := "this is abcde of fghijklmnop"
    s ? write(many(cs))
end

examples/many.icn

Sample run:

prompt$ unicon -s many.icn -x
5

map

map(s, s:&ucase, s:&lcase) : string

map(s1, s2, s3) maps s1 using s2 and s3. The resulting string will be a copy of s1 with any characters that appear in s2 replaced by characters in the position from s3. The defaults allow for upper case to lower case conversions of s1.

Map transforms are a powerful feature of Unicon. Permutations are possible when map() is called with s1 and s2 as constants and s3 being a transform target.

#
# map.icn, demonstrate map and tranform
#
procedure main()
    # upper to lower case mapping
    up := "This is a TEST"
    write(map(up))

    # permutation mapping, allowing s3 to be the variable
    # s2 and s3 must be equal length
    s3 := "abcde"
    # '0' in s1 (index 1) maps to '0' in s2, (index 5)
    write("01234 43210: ", s3, " to ", map("01234", "43210", s3))
    write("Multiple s1: ", s3, " to ", map("012343210", "43210", s3))
end

examples/map.icn

Sample run:

prompt$ unicon -s map.icn -x
this is a test
01234 43210: abcde to edcba
Multiple s1: abcde to edcbabcde

map() is usually thought of as source, what-to-change, to-what. When the to-what is changed to be a variable, Unicon returns a string where character markers in s1 are replaced by positionally matched characters from s2. Characters of the variable s3 are sourced to feed an s1 s2 positional transform.

Characters of s3 mapped by positional matches between s1 and s2.


match

match(s, s:&subject, i:&pos, i:0 : integer

match(s1, s2, i1, i2) produces i1+*s1 if s1 == s2[i1 +: *s1] but fails otherwise. A string scanning function that returns the index at the end of a match starting at current position (by default).

#
# match.icn, demonstrate string scanning match
#
procedure main()
    s := "this is a test"
    # match will return the index after the matched string
    s ? this := match("this")
    write(this)

    # no match, variable that remains null, no write
    s ? that := match("that")
    write(\that)

    # match is built into the unary equal operator as tab(match(s))
    s ? data := ="this"
    write(":", data, ":")
    # equivalent to
    s ? data := tab(match("this"))
    write(":", data, ":")
end

examples/match.icn

Sample run:

prompt$ unicon -s match.icn -x
5
:this:
:this:

MatrixMode

MatrixMode(w, s) → record
Argument:window
Argument:string, “projection” or “modelview”
Returns:display list record

Sets the current matrix stack mode. The “projection” stack can hold 2 matrices, the “modelview” stack can hold 32 matrices.

#
# MatrixMode.icn, demonstrate the two matrix modes 
# Curerntly a work in progress
#
link fullimag
procedure main()
    window := open("MatrixMode", "gl", "bg=black", "buffer=on",
                    "size=400,260", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")

    # A torus 
    DrawTorus(window, 0.0,0.19,-2.2, 0.3,0.4)
    Refresh(window)
    MatrixMode(window, "projection")
    PushMatrix(window)
    write(image(IdentityMatrix(window)))
    write(fullimage(PopMatrix(window)))
    
    MatrixMode(window, "modelview")
    PushMatrix(window)
    write(image(IdentityMatrix(window)))
    write(fullimage(PopMatrix(window)))
    
    # save image for the document
    Refresh(window)
    WSync(window)
    WriteImage(window, "../images/MatrixMode.png")
    close(window)
end

examples/MatrixMode.icn

Sample run (not auto captured):


max

max(n, ...) : number

max() returns the largest value from the list of arguments. The arguments do not need to be numeric, but reasoning about comparison rules between different structures of possibly different types can be quite tricky.

#
# max.icn, demonstrate the maximum value function
#
link fullimag
procedure main()
    write(max(1,2,3))
    write()

    # using the apply operator comes in handy for max
    L := [1,2,3,4,5]
    write(max!L)
    # equivalent to
    write(max(1,2,3,4,5))
    write()

    # max also accepts structures directly
    write(max(L))

    # although max accepts structures, results are somewhat "fuzzy"
    L1 := ["abc", "def"]
    L2 := ["uvw", "xyz", "123"]
    L3 := ["UVW", "XYZ"]
    L4 := ["ZZZ", "457", "002"]
    L5 := ["YYY", "456", "001"]
    write(fullimage(max(L1, L2, L3, L4, L5)))
end

examples/max.icn

Sample run:

prompt$ unicon -s max.icn -x
3

5
5

5
["YYY","456","001"]

member

member(x, ...) : x?

member(x, ...) returns x if all other arguments are members of the Set, cset, list, or table x, but fails otherwise. If x is a cset all of the characters in subsequent string arguments must be present in x in order to succeed.

#
# member.icn, demonstrate structure membership test
#
procedure main()
    S := [1,2,3,4]
    if member(S, 1,2,3) then write("all members of set")

    T := table()
    insert(T, "key1", "abc", "key2", "def")
    if member(T, "key1") then write("have key key1")

    # this test will fail, table membership is by key
    if member(T, "abc") then write("have value abc")

    cs := 'abcde'
    if member(cs, "a","b","c") then write("all members of cset")
end

examples/member.icn

Sample run:

prompt$ unicon -s member.icn -x
all members of set
have key key1
all members of cset

membernames

membernames(x) : list

membernames(x) produces a list containing the string names of the fields of x, where x is either an object or a string name of a class.

#
# membernames.icn, demonstrate class/object membernames
#
link fullimag

class sample(a,b,c,d)
end

procedure main()
    # this initial write fails if sample is never instantiated
    write(fullimage(membernames("sample")))

    c := sample(1,2,3,4)
    write(fullimage(membernames(c)))
end

examples/membernames.icn

Sample run:

prompt$ unicon -s membernames.icn -x
["a","b","c","d"]
["__s","__m","a","b","c","d"]

methodnames

methodnames() : type

methodnames(x) produces a list containing the string names of the fields of x, where x is either an object or a string name of a class.

#
# methodnames.icn, demonstrate class/object methodnames
#
link fullimag

class sample(a,b,c,d)
    method one()
    end
    method two()
    end
end

procedure main()
    # this initial write is an empty list if sample is never instantiated
    write(fullimage(methodnames("sample")))

    c := sample(1,2,3,4)
    write(fullimage(methodnames(c)))
end

examples/methodnames.icn

Sample run:

prompt$ unicon -s methodnames.icn -x
["sample_one","sample_two"]
["sample_one","sample_two"]

methods

methods(x) : list

methods(x) produces a list containing the procedure values of the methods of x, where x is either an object or the string name of a class.

#
# methods.icn, demonstrate class/object procedure values of methods list
#
link fullimag

class sample(a,b,c,d)
    method one()
    end
    method two()
    end
end

procedure main()
    # this initial write is an empty list if sample is never instantiated
    write(fullimage(methods("sample")))

    c := sample(1,2,3,4)
    write(fullimage(methods(c)))
end

examples/methods.icn

Sample run:

prompt$ unicon -s methods.icn -x
[procedure sample_one,procedure sample_two]
[procedure sample_one,procedure sample_two]

min

min(n, ...) : number

min() returns the smallest value from the list of arguments, which must be numeric.

#
# min.icn, demonstrate the minimum value function
#
link fullimag
procedure main()
    write(min(1,2,3))
    write()

    # using the apply operator comes in handy for min
    L := [1,2,3,4,5]
    write(min!L)
    # equivalent to
    write(min(1,2,3,4,5))
    write()

    # min also accepts structures directly
    write(min(L))

    # although min accepts structures, results are somewhat "fuzzy"
    L1 := ["abc", "def"]
    L2 := ["uvw", "xyz", "123"]
    L3 := ["UVW", "XYZ"]
    L4 := ["ZZZ", "457", "002"]
    L5 := ["YYY", "456", "001"]
    write(fullimage(min(L1, L2, L3, L4, L5)))
end

examples/min.icn

Sample run:

prompt$ unicon -s min.icn -x
1

1
1

1
["abc","def"]

mkdir

mkdir(s, x) : ?

mkdir(path, mode) attempts to create directory path with permissions mode. mode can be an integer or a string of the form:

[ugoa]*[+-=][rwxRWXstugo]*

See chmod for more details on mode values.

Getting the normal 8r755 value used for most directories is difficult with the mode string, as you need to set u=rwx but go=rx. It is easiest to leave mode as a default, or use the octal notation.

#
# mkdir.icn, demonstrate the create directory function
#
link convert
procedure main()
    path := "mkdir-sample"
    mode := 8r755 # rwxr-xr-x
    if mkdir(path, mode) then {
        write("created directory ", path,
              " with 8r", exbase10(mode, 8))
        system("ls -ld " || path)
        rmdir(path)
    }
    else
        write("directory create ", path,
              " with 8r", exbase10(mode, 8), " failed")
end

examples/mkdir.icn

Sample run:

prompt$ unicon -s mkdir.icn -x
created directory mkdir-sample with 8r755
drwxr-xr-x 2 btiffin btiffin 4096 Oct 25 13:22 mkdir-sample

move

move(i:1) : string

move(i) moves the string scanning position &pos i characters from the current position and returns the substring of &subject between the old and new positions. This function will reset an old value if it is resumed during goal-directed evaluation.

The move() function makes little sense outside a string scanning environment but will effect &pos and read any explicitly set &subject.

#
# move.icn, demonstrate the string scanning move function
#
procedure main()
    # display first letter of each word, using counted moves
    s := "this is a test"
    s ? {
        write(move(1), " ", &pos)
        move(4)
        write(move(1), " ", &pos)
        move(2)
        write(move(1), " ", &pos)
        move(1)
        write(move(1), " ", &pos)
    }

    # outside of string scanning, move makes little sense
    # but can be used by explicitly setting &pos and &subject
    &pos := 1
    &subject := "not scanning"
    write(move(3))
end

examples/move.icn

Sample run:

prompt$ unicon -s move.icn -x
t 2
i 7
a 10
t 12
not

MultMatrix

MultMatrix(w, L) → record
Returns:Transformation matrix record.

Multiplies the current transformation matrix used in 3D window w by the 4x4 matrix represented as a list of 16 values in L.

#
# MultMatrix.icn, demonstrate matrix transforms
# Curerntly a work in progress
#
link fullimag
procedure main()
    window := open("MultMatrix", "gl", "bg=black", "buffer=on",
                    "size=400,260", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")

    # A torus 
    DrawTorus(window, 0.0,0.19,-2.2, 0.3,0.4)
    Refresh(window)
    MatrixMode(window, "projection")
    PushMatrix(window)

    MultMatrix(window, [[0,0,0,1], [0,0,1,0], [0,1,0,0], [1,0,0,0]])    
    write(fullimage(PopMatrix(window)))
    
    # save image for the document
    Refresh(window)
    WSync(window)
    WriteImage(window, "../images/MultMatrix.png")
    close(window)
end

examples/MultMatrix.icn

Sample run:


mutex

mutex(x, y) : x

mutex(x) creates a new mutual exclusion control variable for structure x, which can be a list, set or table. mutex(x, y) associates an existing mutex y (or mutex associated with protecting resoure y) with structure x. mutex() returns a new non-associated control variable, which can be used with critical.

#
# mutex.icn, Demonstrate mutually exclusive gating variables.
#
global x

procedure main()
    x := 0

    mtx := mutex()
    T1 := thread report(mtx)
    T2 := thread other(mtx)

    # due to the nature of threading
    # the values displayed in report
    # might be 1,2,3,4 or 1,10,11,12 or 1,2,11,12 etc
    wait(T1 | T2)

    # final result will always be 12
    write("x is ", x)
end

# increment and report
procedure report(mtx)
    every 1 to 4 do {
        critical mtx : x := x + 1
        write(x)
    }
end

# just increment
procedure other(mtx)
    every 1 to 8 do
        critical mtx : x := x + 1
end

examples/mutex.icn

Sample run:

prompt$ unicon -s mutex.icn -x
1
10
11
12
x is 12

See also

critical


name

name(v, CE:&current) : type

name(v, ce) returns the name of variable v within the program that created co-expression ce . Keyword variables are recognized. name() returns the base type and subscript or field information for variables that are elements within other values, but the returned string will unlikely match the source code for such variables.

#
# filename.icn, purpose
#
procedure main()
    a := 1
    write(name(a), " is ", a)

    L := [[1], ["abc"]]
    write(name(L[2]))

    # a dereferenced value will cause a runtime error
    write(name(.a))
end

examples/name.icn

Sample run (ends with error):

prompt$ unicon -s name.icn -x
a is 1
list_3[2]

Run-time error 111
File name.icn; Line 19
variable expected
offending value: 1
Traceback:
   main()
   name(1,&null) from line 19 in name.icn

NewColor

NewColor(w, s) : integer [Graphics]

NewColor(w, s) allocates a mutable colour entry in the palette map for the current windowing system, initializing the colour to s, and returns a small negative integer for this entry. The colour integer can be used as a colour specification. NewColor() fails if the entry cannot be allocated/

This is not deprecated, but mostly unnecessary with modern display hardware. Most current graphic displays can handle millions of simultaneous colours, something not possible when older graphics programs had a limited palette of colours to use at any given time, limited by the electronics of the day.

#
# NewColor.icn, demonstrate creating colour map entries.
#
procedure main()
    window := open("NewColor", "g", "size=110,24", "canvas=hidden")
    # RGB values can be from 0 to 65535
    if c := NewColor(window, "40000,50000,60000") then {
        Fg(window, c)
        write(window, Fg(window))
    }
    else {
        Fg(window, "black")
        write(window, "no mutable colours")
    }

    WSync(window)
    WriteImage(window, "../images/NewColor.png")
    FreeColor(\c)
    close(window)
end

examples/NewColor.icn

Sample run:

prompt$ unicon -s NewColor.icn -x
_images/NewColor.png

images/NewColor.png


Normals

Normals(w, s|l) → *List*
Returns:Element display list
Requires:3D graphics

Sets texture coordinates to those defined in the argument list or string.

#
# Normals.icn, demonstrate texture mapping coordinate setting
#
procedure main()
    &window := open("Normals", "gl", "size=200,200")

    
    close(&window)
end

examples/Normals.icn

Sample run (pending):


NotAny

NotAny(c) : [Pattern]

NotAny(c) is a SNOBOL based pattern that matches any single character not contained in the character set c, appearing in the subject string.

#
# NotAny.icn, demonstrate the SNOBOL based pattern NotAny() function
#
procedure main()
    str := "ABCdef"
    ups := NotAny(&lcase)
    write("Type of ups: ", type(ups))
    str ?? ups -> intermediate
    write(intermediate)
end

examples/NotAny.icn

Sample run:

prompt$ unicon -s NotAny.icn -x
Type of ups: pattern
A

Nspan

Nspan(cset) : string

A SNOBOL inspired pattern matching function.

Nspan(cs) will match zero or more subject characters from the cset cs. It is equivalent to the pattern Span(cs) .| "" (matching the empty string after failing to span across any of the available characters).

#
# Nspan.icn, pattern matching function, zero or more characters
#
procedure main()
    "string" ?? Nspan('pqrstuv') => result
    write(image(result))

    # Nspan requires no anchor, it will match to zero occurrences
    "no character match at start of string" ?? Nspan('pqrstuv') => second
    write(image(second))
end

examples/Nspan.icn

Sample run:

prompt$ unicon -s Nspan.icn -x
"str"
""

See also

Span, break.


numeric

numeric(any) : number

numeric(x) produces an integer or real number resulting from type conversion of x, or fails if the conversion is not possible.

#
# numeric.icn, produce an integer or real from type conversion
#
procedure main()
    i := 123
    r := 123.123
    s := 123.0
    b := "36rXYZ"
    e := "abc"

    write(numeric(i) * 2)
    write(numeric(r) * 2)
    write(numeric(s) * 2)
    write(numeric(b) * 2)

    # no write occurs as e is not numeric, conversion fails
    write(numeric(e) * 2)

end

examples/numeric.icn

Sample run:

prompt$ unicon -s numeric.icn -x
246
246.246
246.0
88054

open

open(s, s:"rt", ...) : file?

open(s1, s2, ...) opens a resource named s1 with mode s2 and attributes given in trailing arguments. open() recognizes the following resource type:

  • file
  • socket
  • tcp, mode “n” for network
  • udp, mode “nu” for UDP network
  • http, mode “m” for messaging
  • https, mode “m-” (be forgiving with certificate authentication)
  • https, mode “m” (authenticated)
  • smtp, mode “m”
  • pop, mode “m”
  • finger, mode “m”
  • mailto, mode “m” with email header fields as attribute arguments

Todo

a constant todo item is keeping this list up to date

The mode in s2 can be

  • “a” append; write after current contents
  • “b” open for both reading and writing (b does not mean binary mode!)
  • “c” create a new file and open it
  • “d” open a [NG]DBM database
  • “g” create a 2D graphics window
  • “gl” create a 3D graphics window
  • “n” connect to a remote TCP network socket
  • “na” accept a connection from a TCP network socket
  • “nau” accept a connection from a UDP network socket
  • “nl” listen on a TCP network socket
  • “nu” connect to a UDP network socket
  • “m” connect to a messaging server (HTTP, SMTP, POP, ...)
  • “m-” connect to secure HTTPS, unauthenticated certificates allowed
  • “o” open an ODBC connection to a (typically SQL) database
  • “p” execute a program given by command line s1 and open a pipe to it
  • “prw” open an asynchronous pseudo terminal connection
  • “r” read
  • “t” use text mode, with newlines translated
  • “u” use a binary untranslated mode
  • “w” write
  • “x” DEPRECATED, old X11 mode, use “g”
  • “z” libz compressed modifier
#
# open.icn, demonstrate the open function
#
procedure main()
    f := open(&file) | stop("Cannot open ", &file, " for read")
    every write(!f)
    close(f)
end

examples/open.icn

Sample run:

prompt$ unicon -s open.icn -x
##-
# Author: Brian Tiffin
# Dedicated to the public domain
#
# Date: October 2016
# Modified: 2016-10-12/01:11-0400
##+
#
# open.icn, demonstrate the open function
#
procedure main()
    f := open(&file) | stop("Cannot open ", &file, " for read")
    every write(!f)
    close(f)
end

See also

close, read, reads


opencl

opencl(list) : integer

An experimental Unicon interface to the Open Computing Language. Integrating CPU, GPU and other auxiliary hardware in a single framework with a backing programming language based on C99. The specification of OpenCL is royalty free, but there will be vendor specific portions, possibly non-free.

https://en.wikipedia.org/wiki/OpenCL by the Khronos Group.

Attention

Not yet officially part of Unicon release 13.

opencl(L) will display information and properties of the given list of devices.

#
# opencl.icn, an experimental Unicon interface to Open Computing Language
#
# not yet fully implemented in Unicon, this sample is wrong, and untested 
#
procedure main()
    i := opencl(["GPU"])
end

examples/opencl.icn

Sample run (skipped for now):


oprec

oprec(x) : record

oprec(r) produces a variable reference for the class method vector of r.

#
# oprec.icn, reference to class method vector
#
link ximage

class sample(a,b,c)
    method one(a)
        write("in method a: ", type(a), ":, ", a)
    end
    initially 
        a := 1
        b := 2
        c := 3
        write(a, ", ", b, ", ", c)
end

procedure main()
    c := sample(1,2,3)
    write(type(oprec(c)))
    write(ximage(oprec(c)))

    cmv := oprec(c)

    # too new to know what the first agrument is supposed to be
    # a self reference likely, not sure it that is the same as c
    cmv["initially"](c)
    cmv["one"](c,42)
    cmv["one"](c,"abc")
    cmv["one"](c)
end

examples/oprec.icn

Sample run:

prompt$ unicon -s oprec.icn -x
1, 2, 3
sample__methods
R_sample__methods_1 := sample__methods()
   R_sample__methods_1.one := procedure sample_one
   R_sample__methods_1.initially := procedure sample_initially
1, 2, 3
in method a: integer:, 42
in method a: string:, abc
in method a: null:,

ord

ord(s) : integer

ord(s) produces the character ordinal of the one character string s. The ASCII value of the byte.

#
# ord.icn, ordinal value of a one character string
#
procedure main()
    write("ord(A) is ", ord("A"))
    write("ord(\\n) is ", ord("\n")) 
end

examples/ord.icn

Sample run:

prompt$ unicon -s ord.icn -x
ord(A) is 65
ord(\n) is 10

OutPort

OutPort(i1, i2) : null [MS-DOS]

OutPort(i1, i2) will write i2 to port i1. This is an MS-DOS specific feature of Unicon. i2 in the range 0-255, a byte value.

#
# OutPort.icn, send a value to an MS-DOS port
#
procedure main()
    OutPort(1, 1)
end

examples/OutPort.icn

Sample run (skipped on this GNU/Linux build machine):

See also

InPort


PaletteChars

PaletteChars(w, s) → *string*
Returns:String
Requires:Graphics

Produces a string containing each of the letters in palette s. The palettes c1 through c6 define different colour encodings of images represented as string data.

#
# PaletteChars.icn, demonstrate drawing image strings
#
procedure main()
    &window := open("PaletteChars", "g", "size=85,40", "canvas=hidden")

    # colour palettes are encoded as character data
    write("PaletteChars(\"c1\") is ", PaletteChars("c1"))

    # save image for the document
    WSync()
    WriteImage("../images/PaletteChars.png")
    close(&window)
end

examples/PaletteChars.icn

Sample run:

prompt$ unicon -s PaletteChars.icn -x | par
PaletteChars("c1") is
0123456789?!nNAa#@oOBb$%pPCc&|qQDd,.rREe;:sSFf+-tTGg*/uUHh`'vVIi<>wWJj()
xXKk[]yYLl{}zZMm^=

PaletteColor

PaletteColor(w, p, s) → *string*
Returns:the colour key s in palette p from window w.

Returns the colour of key s in “r,g,b” form.

#
# PaletteColor.icn, demonstrate drawing image strings
#
procedure main()
    &window := open("PaletteColor", "g", "size=85,40", "canvas=hidden")

    # colour palettes are mapped using character data keys 
    write("PaletteColor(\"c1\", \"9\") is ", PaletteColor("c1", "9"))

    # save image for the document
    WSync()
    WriteImage("../images/PaletteColor.png")
    close(&window)
end

examples/PaletteColor.icn

Sample run:

prompt$ unicon -s PaletteColor.icn -x
PaletteColor("c1", "9") is 65535,49151,32767

PaletteKey

PaletteKey(w, p, s) → *string*
Returns:the colour key of the closet colour to s in palette p.

Returns the colour of key s in “r,g,b” form.

#
# PaletteKey.icn, demonstrate getting colour mapping key
#
procedure main()
    &window := open("PaletteKey", "g", "size=85,40", "canvas=hidden")

    # colour palettes are mapped using character data keys 
    write(PaletteKey("c1", "blue"))

    # save image for the document
    WSync()
    WriteImage("../images/PaletteKey.png")
    close(&window)
end

examples/PaletteKey.icn

Sample run:

prompt$ unicon -s PaletteKey.icn -x
J

paramnames

paramnames(CE, i:0) : string

paramnames(ce, i) produces the names of the parameters in the procedure activation i levels above the current activation in ce.

#
# paramnames.icn, parameter names from co-expression stack
#
link ximage
procedure main(arglist)
    ce := create 1 to 3
    write(ximage(paramnames(ce)))
end

examples/paramnames.icn

Sample run:

prompt$ unicon -s paramnames.icn -x
"arglist"

parent

parent(CE) → co-expression

parent(ce) returns the co-expression that created ce. Useful with load.

#
# parent.icn, co-expression of parent
#
# unicon load-child.icn to get a loadable file first
#
procedure main()
    write("Loading ./load-child from ", image(&current))
    lp := load("load-child")
    @lp
end

examples/parent.icn

#
# load-child.icn, a demonstration of the parent function
#
procedure main()
    write("in load-child with ", image(&current))
    write("parent is ", image(parent(&current)))
end

examples/load-child.icn

Sample run:

prompt$ unicon -s load-child.icn
prompt$ unicon -s parent.icn -x
Loading ./load-child from co-expression_1(1)
in load-child with co-expression_1(0)
parent is co-expression_1(1)

Pattern

Pattern(w, s) : window

Pattern(w, s) selects a stipple pattern s for use during draw and fill operations. s may be the name of a system-dependent pattern or a literal, in the form "width,bits". Patterns are only used when the fillstyle attribute is stippled, opaquestippled or textured. Pattern() fails if a named pattern is not defined. An error occurs if s is a malformed literal.

#
# Pattern.icn, demonstrate stippled Pattern fill
#
procedure main()
    &window := open("Pattern", "g",
                    "fillstyle=stippled",
                    "size=85,40", "canvas=hidden")
    # A width 4 pattern, with bit patterns of 2, 8, 2, 8
    Pattern(&window, "4,2,8,2,8")
    Fg(&window, "red")
    FillRectangle(&window, 0, 0, 40, 40)

    # built in checker board pattern
    Pattern("checkers")
    Fg("black")
    FillRectangle(45, 0, 40, 40)

    # save image for the document
    WSync()
    WriteImage("../images/Pattern.png")
    close(&window)
end

examples/Pattern.icn

Sample run:

prompt$ unicon -s Pattern.icn -x
_images/Pattern.png

images/Pattern.png


Peek

Peek(A, i) : string [MS-DOS]

This is an MS-DOS specific Unicon feature, now outdated.

Peek(A, i) builds a string from an “address” A (returned from GetSpace, memory outside of Unicon control and not garbage collected), of length i.

#
# Peek.icn, an MS-DOS specific memory region copy to string
#
# This sample is UNTESTED, which means it counts as broken.
#
procedure main()
    mem := GetSpace(32)
    s := Peek(mem, 32)
    write(image(s))
    FreeSpace(mem)
end

examples/Peek.icn

Sample run (skipped on this GNU/Linux machine):


Pending

Pending(w : window='&window'[, x, ...]) → list

Produce the list of pending events for window w, adding optional events x, to the end of the list, in a guaranteed order.

Pending(w) produces the list of events waiting on window w. Pending(w, x1,...,xn) adds x1 through xn to the end of w‘s pending list in the given order.

#
# Pending.icn, demonstrate pending event test
#
link enqueue, evmux, ximage
procedure main()
    window := open("Event", "g", "size=20,20", "canvas=hidden")

    # insert an event into the queue, left press, control and shift
    Enqueue(window, &lpress, 11, 14, "cs", 2)
    L := Pending(window)
    write(ximage(L))

    e := Event(window)
    write(image(e))

    # a side effect of the Event function is keywords settings
    write("&x:", &x)
    write("&y:", &y)
    write("&row:", &row)
    write("&col:", &col)
    write("&interval:", &interval)
    write("&control:", &control)
    write("&shift:", &shift)
    write("&meta:", &meta)
    
    close(window)
end

examples/Pending.icn

Sample run:

prompt$ unicon -s Pending.icn -x
L1 := list(3)
   L1[1] := -1
   L1[2] := 327691
   L1[3] := 131086
-1
&x:11
&y:14
&row:2
&col:2
&interval:2
&control:
&shift:

pipe

pipe() → list

pipe() creates a pipe and returns a list of two file objects. The first is for reading, the second is for writing.

#
# pipe.icn, demonstrate pipe operation
#
# tectonics:
#
#
procedure main()
    #pipes := pipe()
    #write(read(pipes[1]
    # too new, need better example
end

examples/pipe.icn

Sample run:

prompt$ unicon -s pipe.icn -x

Pixel

Pixel(w, ix, iy, iw, ih) : integer* [Graphics]

Pixel(w, x,y, wid,hgt) generates pixel contents from a rectangular area within window w. Top left corner is x.y and pixel colours are generated in the wid,hgt rectangle down each column, from left to right. Pixel values are returned as 16bit RGB values, with mutable colours being negative integers, as returned by NewColor().

Pixel() fails if part of the requested rectangle extends beyond the canvas.

#
# Pixel.icn, demonstrate the Pixel value generator
#
procedure main()
    &window := open("Pixel", "g", "size=45,40", "canvas=hidden")

    # Some lines 
    Fg("vivid orange")
    DrawLine(1,0, 30,10, 30,15)

    Fg("blue")
    DrawLine(0,0, 10,15, 14,15)

    Fg("green")
    DrawLine(1,1, 29,14)

    # generate the top corner pixel values, down and then to the right
    every write(image(Pixel(0, 0, 4, 4)))

    # save image for the document
    WSync()
    WriteImage("../images/Pixel.png")
    close(&window)
end

examples/Pixel.icn

Sample run:

prompt$ unicon -s Pixel.icn -x
"0,0,65535"
"65535,16382,0"
"65535,16382,0"
"65535,65535,65535"
"65535,65535,65535"
"0,65535,0"
"0,65535,0"
"65535,16382,0"
"65535,65535,65535"
"0,0,65535"
"0,65535,0"
"0,65535,0"
"65535,65535,65535"
"65535,65535,65535"
"0,0,65535"
"65535,65535,65535"
_images/Pixel.png

images/Pixel.png


PlayAudio

PlayAudio(s) : integer [Audio]

PlayAudio(s) will attempt to start an audio thread and play the filename s. Accepts .wav and .ogg files when Unicon if built with OpenAL and/or Vorbis support. Returns an integer from 0 to 15, representing the thread stream, or fails if the filename cannot be read, is an invalid format, too many channels are already in play, or there are problems with the sound equipment.

#
# PlayAudio.icn, play an audio file
#
procedure main()
    channel := PlayAudio("/home/btiffin/unicon/tests/unicon/handclap.ogg")
    write("Audio channel: ", channel)
    delay(300)
    StopAudio(channel)

    channel := PlayAudio("/home/btiffin/unicon/tests/unicon/alert.wav")
    write("Audio channel: ", channel)
    delay(500)
    StopAudio(channel)
end

examples/PlayAudio.icn

Sample run (skipped, you probably wouldn’t hear it from here anyway):

See also

StopAudio, VAttrib


Poke

Poke(A, s) : null

This is an outdated MS-DOS specific feature of Unicon.

Poke(A, s) will replace the memory at “address” A, with the contents of string s. The “address” A is usually from GetSpace outside of Unicon control and garbage collection.

#
# Poke.icn, an MS-DOS specific string to memory region copy
#
# This sample is UNTESTED, which means it counts as broken.
#
procedure main()
    s := "Hello, distant past"
    mem := GetSpace(*s)
    Poke(mem, s)
    from := Peek(mem, *s)
    write(image(from))
    FreeSpace(mem)
end

examples/Poke.icn

Sample run (skipped on this GNU/Linux build machine):


pop

pop(L | Message) : any?

pop(L) remove an element from the top of the stack L[1], and return the value. pop(M) removes and returns the first message in a POP mailbox connection M. The actual delete occurs on close.

#
# pop.icn, demonstrate pop from stack
#
procedure main()
    L := [42, 43, 44]
    write(*L, " ", pop(L), " ", *L)
end

examples/pop.icn

Sample run:

prompt$ unicon -s pop.icn -x
3 42 2

PopMatrix

PopMatrix(w) → *record*
Returns:Display list element record

PopMatrix(w) pops the top matrix from the either the “projection” or “modelview” matrix stack. The function fails if there is only element on the current matrix stack.

#
# PopMatrix.icn, demonstrate matrix stack
# Curerntly a work in progress
#
link fullimag
procedure main()
    window := open("PopMatrix", "gl", "bg=black", "buffer=on",
                    "size=400,260", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")

    # A torus 
    DrawTorus(window, 0.0,0.19,-2.2, 0.3,0.4)
    Refresh(window)
    MatrixMode(window, "projection")
    PushMatrix(window)
    
    write(fullimage(PopMatrix(window)))
    
    # save image for the document
    Refresh(window)
    WSync(window)
    WriteImage(window, "../images/PopMatrix.png")
    close(window)
end

examples/PopMatrix.icn

Sample run:


Pos

Pos(i) : null

A SNOBOL based pattern matching function, positional test.

Pos(i) will ensure the scanning position is at i or will fail.

Good for ensuring anchored match strategies along with other position verification uses when validating pattern matches.

#
# Pos.icn, SNOBOL pattern matching function, test position
#
procedure main()
    # Pattern matching positional test
    "string" ?? Span('pqrstuv') => first || Pos(4) || Tab(0) => rest
    write(image(first), " ", image(rest))

    # enforce anchored pattern matching with unachored Span
    "no match at start of string" ?? Pos(1) || Span('rst') => second
    # second will be unset
    write(image(second))

    # same again, without positional test, Span allowed to scan forward
    "ok, no match at start of string" ?? Span('rst') => third
    write(image(third))
end

examples/Pos.icn

Sample run:

prompt$ unicon -s Pos.icn -x
"str" "ing"
&null
"t"

pos

pos(i) : integer?

pos(i) tests whether &pos is at position i in &subject.

#
# &pos, string scanning position
#
# demonstrate how negative position indexes are set to actual
#
procedure main()
    str := &letters
    str ? {
        first := &pos
        &pos := 0
        last := &pos
        &pos := -10
        back10 := &pos
    }    
    write("first: ", first, ", last: ", last, ", -10: ", back10)
end

examples/pos.icn

Sample run:

prompt$ unicon -s pos.icn -x
first: 1, last: 53, -10: 43

proc

proc(any, i:1, CE) : procedure

proc(s, i) converts s to a procedure, if possible. The parameter i is used to resolve ambiguous names by argument count.

  • 0, built-in (for when the procedure name is overridden by a user program)
  • 1, signature has 1 parameter
  • 2, procedure has 2 parameters
  • 3, procedure has 3 parameters

proc can also resolve procedure names in co-expression CE, i levels up.

#
# proc.icn, convert to procedure if possible
#
procedure main()
     # lookup write builtin
     s := "write"
     p := proc(s, 0) | stop("builtin lookup fail for " || s)

     # and use the default built-in
     p("Hello, world")

     # the global name "write" is overriden by the next procedure
     write("Does nothing now, no output will occur")
end

procedure write(s)
    # sophisticated override
    # ...
end

examples/proc.icn

Sample run:

prompt$ unicon -s proc.icn -x
Hello, world

pull

pull(L, i:1) : any?

pull(L) removes and produces an element from the end of the non-empty list L. pull(L, i) removes i elements, producing the last one removed.

#
# pull.icn, remove from end of list and return value
#
procedure main()
    L := [41, 42, 43]
    write(*L, " ", pull(L, 2), " ", *L)
end

examples/pull.icn

Sample run:

prompt$ unicon -s pull.icn -x
3 42 1

push

push(L, any, ...) : list

push(L, x1, ..., xn) pushes elements onto the beginning of list, L. The order added to the list is the reverse order they are supplied as parameters to the call to push(). push() returns the list that is passed as the first parameter, with the new elements added.

#
# push.icn, push elements to front of list
#
link lists
procedure main()
    L := [1,2,3]
    L2 := push(L, 43, 42, 41)
    write("last parameter is pushed last, head: ", L2[1])

    every L3 := push(L2, 41 to 43) 
    write("after 41 to 43 separate, head: ", L3[1])
    write(limage(L3)) 
end

examples/push.icn

Sample run:

prompt$ unicon -s push.icn -x
last parameter is pushed last, head: 41
after 41 to 43 separate, head: 43
[43,42,41,41,42,43,1,2,3]

PushMatrix

PushMatrix(w) → *record*
Returns:Display list element record

PushMatrix(w) the current matrix to either the “projection” or “modelview” matrix stack. The function fails if current stack is full, 2 items for “projection” and 32 for “modelview”.

#
# PushMatrix.icn, demonstrate matrix stack
# Currently a work in progress
#
link fullimag
procedure main()
    window := open("PushMatrix", "gl", "bg=black", "buffer=on",
                    "size=400,260", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")

    # A torus 
    DrawTorus(window, 0.0,0.19,-2.2, 0.3,0.4)
    Refresh(window)
    MatrixMode(window, "projection")
    PushMatrix(window)
    
    write(fullimage(PopMatrix(window)))
    
    # save image for the document
    Refresh(window)
    WSync(window)
    WriteImage(window, "../images/PushMatrix.png")
    close(window)
end

examples/PushMatrix.icn

Sample run (skipped):

See also

PopMatrix, MatrixMode


PushRotate

#
# PushRotate.icn, demonstrate matrix push with rotatation
# Currently a work in progress
#
link fullimag
procedure main()
    window := open("PushRotate", "gl", "bg=black", "buffer=on",
                    "size=400,260", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")

    # A torus 
    DrawTorus(window, 0.0,0.19,-2.2, 0.3,0.4)
    Refresh(window)
    MatrixMode(window, "projection")
    PushRotate(window, 90, 0, 1, 1)
    
    write(fullimage(PopMatrix(window)))
    
    # save image for the document
    Refresh(window)
    WSync(window)
    WriteImage(window, "../images/PushRotate.png")
    close(window)
end

examples/PushRotate.icn

Sample run (not auto generated):

See also

PushMatrix, Rotate


PushScale

PushScale() : type

Todo

entry for function PushScale

PushScale()

examples/PushScale.icn

Sample run:


PushTranslate

PushTranslate() : type

Todo

entry for function PushTranslate

PushTranslate()

examples/PushTranslate.icn

Sample run:


put

put(L, x1,...,xn) : list

put(L, x1,..., xn) puts elements on the end of list L. Returns the list L, with elements added.

#
# put.icn, put elements to front of list
#
link lists
procedure main()
    L := [1,2,3]
    L2 := put(L, 43, 42, 41)
    write(*L2, " ", L2[-1])
    write(limage(L3)) 

    every L3 := put(L2, 41 to 43) 
    write(*L3, " ", L3[-1])
    write(limage(L3))

    # L, L2, L3 all reference the same list
    write(*L, " ", *L2, " ", *L3) 
end

examples/put.icn

Sample run:

prompt$ unicon -s put.icn -x
6 41
9 43
[1,2,3,43,42,41,41,42,43]
9 9 9

QueryPointer

QueryPointer(w) : x,y

QueryPointer(w) generates x then y of the mouse cursor position relative to window w. QueryPointer() generates x then y of the mouse position relative to the display screen.

#
# QueryPointer.icn, generate x,y position of mouse cursor
#
procedure main()
    w := open("main", "g", "size=150,50", "canvas=hidden")
    writes("mouse cursor relative to window w: ")
    pos := ""
    every pos ||:= QueryPointer(w) || ","
    write(pos[1:-1])

    writes("mouse cursor relative to screen: ")
    pos := ""
    every pos ||:= QueryPointer() || ","
    write(pos[1:-1])
    close(w)
end

examples/QueryPointer.icn

Sample run:

prompt$ unicon -s QueryPointer.icn -x
mouse cursor relative to window w: 0,0
mouse cursor relative to screen: 371,512

Raise

Raise(w) : window [Graphics]

Raise(w) raises window w to the top of the window stack, making it fully visible. Makes the window the active window.

#
# raise.icn, raise a window to the top of the window stack
#
procedure main()
    raise := open("raise", "g", "size=150,50", "canvas=hidden")
    w := open("main", "g", "size=200,100", "canvas=hidden")
    Raise(raise)
    WSync(w, raise)
    close(raise, w)
end

examples/Raise.icn

Sample run:

prompt$ unicon -s Raise.icn -x
_images/Raise.png

images/Raise.png

See also

Lower


read

read(f:&input) : string?

read(f) reads a line from file f. The end of line marker is discarded. Fails on end of file.

#
# read.icn, read a record
#
procedure main()
    f := open(&file, "r") | stop("cannot open ", &file, " for read")
    while write(read(f))
    close(f)
end

examples/read.icn

Sample run:

prompt$ unicon -s read.icn -x
##-
# Author: Brian Tiffin
# Dedicated to the public domain
#
# Date: October 2016
# Modified: 2016-10-12/04:29-0400
##+
#
# read.icn, read a record
#
procedure main()
    f := open(&file, "r") | stop("cannot open ", &file, " for read")
    while write(read(f))
    close(f)
end

ReadImage

ReadImage(w, s, x:0, y:0) : integer

ReadImage(w, s, x, y) loads an image from file s into window (or texture) w, at offset x,y. Returns an integer 0 for no errors, or a non zero indicating errors occurred. ReadImage() fails if s could not be read or is an invalid image format.

#
# ReadImage.icn, load an image from file into a window (or texture)
#
procedure main()
    w := open("ReadImage", "g", "size=327,420", "canvas=hidden")
    result := ReadImage(w, "../images/uniconart-orange.png")
    DrawString(w, 5, 405, "Result from ReadImage: " || image(result))
    WSync(w)
    WriteImage(w, "../images/ReadImage.png")
    close(w)
end

examples/ReadImage.icn

Sample run:

prompt$ unicon -s ReadImage.icn -x
_images/ReadImage.png

images/ReadImage.png

Art by Serendel Macphereson

See also

WriteImage


reads

reads(f : file='&input', i : integer='1') → string

Reads up to i characters from file f.

Returns:string

reads(f:&input, i:1) : string?

reads(f, i) reads up to i characters from f. It fails on end of file. If f is a network connection, reads() returns as soon as has input available, even if shorter than i. If i is -1, reads() produces the entire file as a string.

#
# reads.icn, read a given number of bytes, untranslated.
#
procedure main()
    f := open(&file, "r") | stop("cannot open ", &file, " for read")
    s := reads(f, -1)
    write(&file, " ", *s)
    p := find("procedure main", s)
    writes(s[p:0])
    close(f)
end

examples/reads.icn

Sample run:

prompt$ unicon -s reads.icn -x
reads.icn 387
procedure main()
    f := open(&file, "r") | stop("cannot open ", &file, " for read")
    s := reads(f, -1)
    write(&file, " ", *s)
    p := find("procedure main", s)
    writes(s[p:0])
    close(f)
end

ready

ready(f:&input, i:0) : string?

ready(f, i) reads up to i characters from the file f. It returns immediately with available data or fails otherwise. If i is 0, ready() returns all available input. Not implemented for window values.

#
# ready.icn, read a given number of bytes, untranslated.
#
link ximage

procedure main()
    f := open(&file, "r") | stop("cannot open ", &file, " for read")
    s := ready(f, 0)
    write(&file, " ", ximage(s))
    /s := "none\n"
    p := find("procedure main", s)
    /p := 1
    writes(s[p:0])
    close(f)
end

examples/ready.icn

Sample run:

prompt$ unicon -s ready.icn -x
ready.icn &null
none

real

real(any) : real?

real(x) converts x to a real, or fails if the conversion cannot be performed.

#
# real.icn, convert to real if possible
#
procedure main()
    write(real(1))
    write(real("2E10"))
    write(real("123.123"))
    write(real("abc") | "not real")
end

examples/real.icn

Sample run:

prompt$ unicon -s real.icn -x
1.0
20000000000.0
123.123
not real

receive

receive(f) : record

receive(f) reads a datagram addressed to the port associated with f, waiting if necessary. The returned record is: record posix_message(addr, msg) containing the address of the sender and the contents of the message.

#
# receive.icn, read a datagran from a UDP network
#
link ximage
procedure main()
    f := open(":1025", "nua")
    #while r := receive(f) do {
    #    write(ximage(r))
        # Process the request in r.msg
        # ...
        #    send(r.addr, reply)
    #    break
    #}
    write(ximage(f))
    close(f)
end

examples/receive.icn

No sample run, document generator doesn’t like to wait.


Refresh

Refresh(w) : window [3D Graphics]

Refresh(w) redraws the contents of window w. For use when objects have been moved in a 3D scene. Returns the window w.

This is similar to the 2D graphic WSync function, but causes a redraw of cached 3D graphics, independent of any server side cache that may be in play.

#
# Refresh.icn, demonstrate 3D redraw
#
procedure main()
    window := open("Refresh", "gl", "bg=black", "buffer=on",
                    "size=400,240", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")

    # A sphere 
    DrawSphere(window, 0.0, 0.19, -2.2, 0.3)

    # save image for the document, refresh is required for the WriteImage
    # but there is a bug with Unicon opengl hidden canvas on GNU/Linux
    Refresh(window)
    WriteImage(window, "../images/Refresh.png")
    close(window)
end

examples/Refresh.icn

Sample run (not auto captured due to an issue with hidden canvas in 3D):

_images/Refresh.png

images/Refresh.png

See also

WSync


Rem

Rem() : string

A SNOBOL pattern match function.

Rem() returns the remaining characters from the current position to the end of the subject string. This function won’t ever fail.

#
# Rem.icn, SNOBOL pattern, return characters from current to end
#
procedure main()
    "string" ?? Tab(4) || Rem() => result || .> curs
     write(image(result), " ", curs)
end

examples/Rem.icn

Sample run:

prompt$ unicon -s Rem.icn -x
"ing" 7

remove

remove(s) : ?

remove(s) removes the file named s, or fails.

#
# remove.icn, remove a file
#
procedure main()
    if remove("test.tt") then write("removed test.tt")
    else write("did not remove test.tt")
end

examples/remove.icn

Sample run:

prompt$ unicon -s remove.icn -x
did not remove test.tt

rename

rename(s, s) : ?

rename(s1, s2) renames file s1 to the name s2.

#
# rename.icn, rename files
#
procedure main()
    if rename("was-here.txt", "now-here.txt") then
        write("renamed file")
    else
        write("rename failed")
end

examples/rename.icn

Sample run:

prompt$ unicon -s rename.icn -x
rename failed

repl

repl(x, i) : x

repl(x, i) concatenates i copies of the string x. As of Unicon revision 4608, repl(L, n) can be used to replicate n copies of the list L.

#
# repl.icn, demonstrate element replication
#
link lists
procedure main()
    write(repl("*", 24), " stars ", repl("*", 24))

    r := 0
    every feat := &features do {
        if find("Revision", feat) then {
            feat ? {
                ="Revision"
                tab(many(' '))
                r := integer(tab(0))
            }
            # for Unicon builds after 4608, repl works with lists
            if r > 4607 then {
                L := [1,2,3]
                write(limage(L))
                write(limage(repl(L, 3)))
            }
        }
    } 
end

examples/repl.icn

Sample run:

prompt$ unicon -s repl.icn -x
************************ stars ************************

reverse

reverse(x) : x

reverse(x) returns the reverse of the string or list x.

#
# reverse.icn, reverse a string or list
#
link lists
procedure main()
    L := [1,2,3]
    write(limage(L))
    write(limage(reverse(L)))

    s := "abc"
    write(s)
    write(reverse(s))
end

examples/reverse.icn

Sample run:

prompt$ unicon -s reverse.icn -x
[1,2,3]
[3,2,1]
abc
cba

rmdir

rmdir(s) : ?

rmdir(d) removes the directory named d. rmdir() fails if d is not empty, or does not exist.

#
# rmdir.icn, remove a non-empty directory
#
procedure main()
    if rmdir("dir.tt") then write("removed dir.tt/")
    else write("failed to remove dir.tt/")
end

examples/rmdir.icn

Sample run:

prompt$ unicon -s rmdir.icn -x
failed to remove dir.tt/

Rotate

Rotate() : type

Todo

entry for function Rotate

Rotate()

examples/Rotate.icn

Sample run:


Rpos

Rpos(i) : null

A SNOBOL pattern function. Like pos counted back from the end.

Rpos(i) will test if the current scanning position is equal to i position back from the end of the subject string. Fails if not.

#
# Rpos.icn, SNOBOL pattern function, test position counted from end
#
procedure main()
    # Pattern matching positional test, counted back from end
    "string" ?? Span('pqrstuv') => first || Rpos(3) || Tab(0) => rest
    write(image(first), " ", image(rest))
end

examples/Rpos.icn

Sample run:

prompt$ unicon -s Rpos.icn -x
"str" "ing"

Rtab

Rtab(i) : string

A SNOBOL inspired pattern matching function.

Rtab(i) causes the cursor to be placed i positions back from the end of the subject, and returns the characters between the current position and this new position.

#
# Rtab.icn, SNOBOL pattern return characters, current to count from end
#
procedure main()
    # match characters from current to new cursor, set back from end
    # Rtab counts backwards from end 
    # returns characters from position 1,2 with cursor now at 3
    "string" ?? Rtab(4) => result || .> curs
    write(image(result), " ", curs)
end

examples/Rtab.icn

Sample run:

prompt$ unicon -s Rtab.icn -x
"st" 3

See also

tab


rtod

rtod() : real

rtod(radians) given radians as a Real value, produces the conversion to degrees, as a Real number.

d^{\circ} = r\frac{180^{\circ}}{\pi}

#
# rtod.icn, demonstrate radians to degrees
#
link numbers

# uses decipos from numbers, align decimal within field
procedure main()
    write("Radians Degrees")
    every r := 0 to 2 * &pi by 0.25 do
        write(decipos(r, 4, 8), decipos(rtod(r), 4, 8))
end

examples/rtod.icn

Sample run:

prompt$ unicon -s rtod.icn -x
Radians Degrees
  0.0     0.0   
  0.25   14.3239
  0.5    28.6478
  0.75   42.9718
  1.0    57.2957
  1.25   71.6197
  1.5    85.9436
  1.75  100.2676
  2.0   114.5915
  2.25  128.9155
  2.5   143.2394
  2.75  157.5633
  3.0   171.8873
  3.25  186.2112
  3.5   200.5352
  3.75  214.8591
  4.0   229.1831
  4.25  243.5070
  4.5   257.8310
  4.75  272.1549
  5.0   286.4788
  5.25  300.8028
  5.5   315.1267
  5.75  329.4507
  6.0   343.7746
  6.25  358.0986

runerr

runerr(i, any)

runerr(i, x) produces a runtime error i with value x. Program execution is terminated.

#
# runerr.icn, terminate a run with an error code and value
#
procedure main()
    x := "abc"
    runerr(102, x)
    write("doesn't get here")
end

examples/runerr.icn

Sample run:

prompt$ unicon -s runerr.icn
prompt$ ./runerr

Run-time error 102
File runerr.icn; Line 13
numeric expected
offending value: "abc"
Traceback:
   main()
   runerr(102,"abc") from line 13 in runerr.icn

save

save(s) : ?

save(s) saves the run-time system in file s.

#
# save.icn, save the run-time system to a file
#
procedure main()
    if &features == "ExecImage" then
        save("save-runtime.tt")
    else
        write("no ExecImage")
end

examples/save.icn

Sample run:

prompt$ unicon -s save.icn -x
no ExecImage

Scale

Scale() : type

Todo

entry for function Scale

Scale()

examples/Scale.icn

Sample run:


seek

seek(f, any) : file?

seek(f, i) seeks to offset i in file f, if it is possible. If f is a regular file, i must be an integer. If f is a database, i seeks a position within the current set of selected rows. The position is selected numerically if i is convertible to an integer, otherwise i must be convertible to a string, and the position is selected associatively by the primary key.

#
# seek.icn, seek to position within file, database set
#
procedure main()
    fn := "newfile.txt"
    f := open(fn, "r")
    # skip to position 4, "newfile line 1" to "file line 1"
    seek(f, 4)
    write(read(f))
    close(f)
end

examples/seek.icn

Sample run:

prompt$ unicon -s seek.icn -x
file line 1

select

select(x1, x2, ?) : list

select(files?, timeout) waits for input to become available on any of several file resources, typically network connections or windows. The arguments may be files, or lists of files, ending with an optional integer timeout in milliseconds. It returns a list of the files from the input list that have input waiting.

If the final argument to select() is an integer, it acts as a timeout forcing a select return. A timeout of 0 causes select() to return immediately with a list of files (if any). If no files are given, select() will wait for the timeout. If no timeout is given select() waits forever for available input on one of the arguments.

Directories and databases cannot be arguments for select()

#
# select.icn, demonstrate select (input available) function
#
procedure main()
    res := select(&input, 1)
    write(image(*res), " ", image(res))
end

examples/select.icn

Sample run:

prompt$ unicon -s select.icn -x
0 list_2(0)

send

send(s, s) : ?

send(s1, s2) sends a UDP datagram to the address s1 (in host:port format) with message contents s2.

#
# send.icn, send a datagran to a UDP connection
#
link ximage
procedure main()
    #f := open(":1025", "nu")
        # Process the request in r.msg
        # ...
    #r := send(":1025", "test")
    #write(ximage(r))
    #close(f)
end

examples/send.icn

Sample run:

prompt$ unicon -s send.icn -x

seq

seq(i:1, i:1) : integer*

seq(i, j) generates an infinite sequence i, i+j, i+2j, .... j may not be 0.

#
# seq.icn, infinite sequence generator
#
procedure main()
    # infinite sequence, with limitation operator
    every write(seq(5, 5)\4)
end

examples/seq.icn

Sample run:

prompt$ unicon -s seq.icn -x
5
10
15
20

serial

serial(x) : integer

serial(x) returns the serial number for structure x, if it has one. Serial numbers uniquely identify structure values.

#
# serial.icn, serial number of structure
#
procedure main()
    L := [1,2,3]
    S := [1,1,1]
    write("L: ", serial(L))
    write("S: ", serial(S))
    S := [1,2,3]
    write("S: ", serial(S))
    insert(S, 4)
    write("S: ", serial(S))
end

examples/serial.icn

Sample run:

prompt$ unicon -s serial.icn -x
L: 1
S: 2
S: 3
S: 3

set

set(x, ...) : set

set() create a set. Arguments are inserted into the new set, with the exception of lists. set(L) creates a set with members taken from the elements of list L.

#
# set.icn, create a new set
#
link fullimag
procedure main()
    S := set()
    write(fullimage(S))
    S := set(1,3,5)
    write(fullimage(S))
    S := set([1,2,3,4,5,5,4,3,2,1])
    write(fullimage(S))
end

examples/set.icn

Sample run:

prompt$ unicon -s set.icn -x
set()
set(1,3,5)
set(1,2,3,4,5)

setenv

setenv(s, s) : ?

setenv(s1, s2) sets environment variable s1 to the value s2.

#
# setenv.icn, demonstrate setting an environment variable
#
procedure main()
    # note that children cannot set parent environment strings
    # processes inherit from parents, but can't effect parent space
    if setenv("UNICONTEST", "env value") then
        write(getenv("UNICONTEST"))
end

examples/setenv.icn

Sample run:

prompt$ unicon -s setenv.icn -x
env value

See also

getenv


setgid

setgid(i) : null [POSIX]

setgid(i) will attempt to set the current process group id. Usually requires permissions.

#
# setgid.icn, change the current group identity
#
link ximage
procedure main()
    # set group to a safe group for demonstration
    write(ximage(setgid(getgr("btiffin").gid)))
    write(getgid())
end

examples/setgid.icn

Sample run:

prompt$ unicon -s setgid.icn -x
&null
btiffin

See also

getgid, getgr


setgrent

setgrent() : null [POSIX]

setgrent() resets and rewinds the implicit context used by getgr to read through the operating system group entities when getgr() is given no explicit key value.

#
# setgrent.icn, reset and rewind the group file offset used by getgr()
#
link fullimag
procedure main()
    # reset group file reader, returns &null
    write(fullimage(getgr()))
    write(fullimage(getgr()))
    write("reset the group entity context")
    setgrent()
    write(fullimage(getgr()))
end

examples/setgrent.icn

Sample run:

prompt$ unicon -s setgrent.icn -x
posix_group("root","x",0,"")
posix_group("daemon","x",1,"")
reset the group entity context
posix_group("root","x",0,"")

See also

getgr


sethostent

sethostent() : type

Todo

entry for function sethostent

sethostent()

examples/sethostent.icn

Sample run:


setpgrp

setpgrp() : type

Todo

entry for function setpgrp

setpgrp()

examples/setpgrp.icn

Sample run:


setpwent

setpwent() : type

Todo

entry for function setpwent

setpwent()

examples/setpwent.icn

Sample run:


setservent

setservent() : type

Todo

entry for function setservent

setservent()

examples/setservent.icn

Sample run:


setuid

setuid() : type

Todo

entry for function setuid

setuid()

examples/setuid.icn

Sample run:


signal

signal(cv, i:1) : ?

signal(x, y) signals the condition variable x. If y is supplied, the condition variable is signalled y times. If y is 0, a broadcast signal is sent, waking up all threads waiting on x.

#
# signal.icn, send threading signals
#
procedure main()

end

examples/signal.icn

Sample run:

prompt$ unicon -s signal.icn -x

See also

condvar, wait


sin

sin(r) : real

sin(r) returns the sine value of the given angle, r (in radians)

#
# sin.icn, demonstrate the sine function
#
procedure main()
    write("sin(r): Domain all real repeating within 0 <= r <= 2pi (in radians), Range: -1 <= x <= 1")
    every r := 0.0 to &pi * 2 by &pi/4 do {
        write(left("sin(" || r || ")", 24), " radians = ", sin(r))
    }
end

examples/sin.icn

Sample run:

prompt$ unicon -s sin.icn -x
sin(r): Domain all real repeating within 0 <= r <= 2pi (in radians), Range: -1 <= x <= 1
sin(0.0)                 radians = 0.0
sin(0.7853981633974483)  radians = 0.7071067811865475
sin(1.570796326794897)   radians = 1.0
sin(2.356194490192345)   radians = 0.7071067811865476
sin(3.141592653589793)   radians = 1.224646799147353e-16
sin(3.926990816987241)   radians = -0.7071067811865475
sin(4.71238898038469)    radians = -1.0
sin(5.497787143782138)   radians = -0.7071067811865477
sin(6.283185307179586)   radians = -2.449293598294706e-16

Graphical plot:

#
# plot-function, trigonometric plotting, function from command line
#
$define points 300
$define xoff   4
$define base   64
$define yscale 60
$define xscale 100

invocable "sin", "cos", "tan"

# plot the given function, default to sine
procedure main(args)
    func := map(args[1]) | "sin"
    if not func == ("sin" | "cos" | "tan") then func := "sin" 

    # range of pixels for 300 points, y scaled at +/- 60, 4 pixel margins
    &window := open("Plotting", "g", "size=308,128", "canvas=hidden")

    # tan may cause runtime errors
    if func == "tan" then &error := 6

    color := "vivid orange"
    Fg(color)
    write(&window, "\n " || func)

    Fg("gray")
    DrawLine(2, 64, 306, 64)
    DrawLine(2, 2, 2, 126)
    DrawString(8, 10, "1", 8, 69, "0", 2, 126, "-1")
    DrawString(270, 76, left(points * 2 * &pi / 100, 6))

    Fg(color)
    every x := 0 to points do
        DrawPoint(xoff + x, base + yscale * func((2 * &pi * x) / xscale))

    WSync()
    WriteImage("../images/plot-" || func || ".png")
    close(&window)
end

examples/plot-function.icn

prompt$ unicon -s plot-function.icn -x sin
_images/plot-sin.png

images/plot-sin.png

See also

acos, atan, asin, cos, tan


sort

sort(x, i:1) : list

sort(x) sorts the structure x in ascending order.

If x is a table, sort(x, i) uses i as a sort method indicator. If i is 1 or 2, the table is sorted into a list of lists [[key, value], ...]. If i is 3 or 4 then the table is sorted into a single list of alternating keys and values. Sorting is by keys for odd values of i and element values for even values of i.

#
# sort.icn, sort a structure
#
link fullimag
procedure main()
    T := table()
    insert(T, "3", "x", "2", "y", "1", "z")
    write(fullimage(sort(T, 1)))
    write(fullimage(sort(T, 2)))
    write(fullimage(sort(T, 3)))
    write(fullimage(sort(T, 4)))
end

examples/sort.icn

Sample run:

prompt$ unicon -s sort.icn -x
[["1","z"],<3>["2","y"],<4>["3","x"]]
[["3","x"],<3>["2","y"],<4>["1","z"]]
["1","z","2","y","3","x"]
["3","x","2","y","1","z"]

sortf

sortf(x, i:1) : list

sortf(x, i) sorts a list, record or set x using field i of each elements that has one. Elements that don’t have and ith field are sorted in standard order, coming before elements that do have an ith field.

#
# sortf.icn, sort a structure by subfield index
#
link fullimag
procedure main()
    L := [[9,3,6], [4,2,7], [3,9,1], []]
    write("original: ", fullimage(L))
    write("field 1 : ", fullimage(sortf(L, 1)))
    write("field 2 : ", fullimage(sortf(L, 2)))
    write("field 3 : ", fullimage(sortf(L, 3)))
end

examples/sortf.icn

Sample run:

prompt$ unicon -s sortf.icn -x
original: [[9,3,6],[4,2,7],[3,9,1],[]]
field 1 : [[],[3,9,1],[4,2,7],[9,3,6]]
field 2 : [[],[4,2,7],[9,3,6],[3,9,1]]
field 3 : [[],[3,9,1],[9,3,6],[4,2,7]]

Span

Span() : type

Todo

entry for function Span

Span()

examples/Span.icn

Sample run:


spawn

spawn(CE, i, i) : thread

spawn(ce) launches co-expression ce as an asynchronous thread, executed concurrently with the current co-expression. The two optional integers specify the thread’s block and string region allocations. The defaults are 10% of the main thread head size.

#
# thread.icn, Demonstrate thread messaging
#
# requires Concurrency build of Unicon
#
procedure main()
    pr := create producerRace()
    cr := create consumerRace(pr)
    pTr := spawn(pr)
    cTr := spawn(cr)
    every wait(pTr | cTr)
    write("racing producer/consumer complete")
    write()

    p := create producer()
    c := create consumer(p)
    pT := spawn(p)
    cT := spawn(c)
    every wait(pT | cT)
    write("main complete")
end

#
# This code can easily trigger incorrect results due to a race condition
#

# send messages to the thread out-box
procedure producerRace()
    write("producer entry")
    every !6@>
end

# receive messages from the out-box of the producer thread
procedure consumerRace(T)
    write("consumer entry")
    while write(<@T)
end

# What follows is the suggested update from Jafar
# It alleviates the race condition where consumerRace
# can complete before the producerRace even starts
#
# an original capture:
#
# JMBPro:proj jafar$ ./thrd
# producer entry
# consumer entry
# racing producer/consumer complete

#
# This is the better code...
#
 
# send messages to the thread out-box
procedure producer()
    write("synch producer entry")
    every !6@>
    # produce &null (&null@>)  to signal the end
    @>
end

# receive messages from the out-box of the producer thread
procedure consumer(T)
    write("blocking consumer entry")
    # blocking receive. 
    while write(\<<@T)
end

examples/spawn.icn

Sample run:

prompt$ unicon -s spawn.icn -x
consumer entry
producer entry
racing producer/consumer complete

synch producer entry
blocking consumer entry
1
2
3
4
5
6
main complete

See also

create, thread, wait


sql

sql(D, s) : integer

sql(db, query) executes arbitrary SQL code on db. The query will be handled by vendor-specific features of the ODBC engine in use.

sql() is a power function that can leave a database in any state, as specified by the given SQL statement(s). Use care when feeding user entered query strings to the sql() function.

#
# sql.icn, demonstrate SQL statements passed to a ODBC database
#
# tectonics: ~/.odbc.ini setup required for [unicon] 
#            assuming the [unicon] ODBC setup, SQLite3
#
procedure main()
    # mode 'o' open, ODBC SQL, default table and connection at defaults 
    db := open("unicon", "o", "", "") | stop("no ODBC for \"unicon\"")

    # Information below was created as part of examples/odbc.icn
    # sql(db, "create table contacts (id integer primary key, name, phone)")

    # make a query
    write("SELECT name, phone")
    sql(db, "SELECT name, phone FROM contacts")

    while row := fetch(db) do {
        write("Contact: ", row.name, ", ", row.phone)
    }

    # make an ordered query
    write()
    write("ORDER BY name")
    sql(db, "SELECT name, phone FROM contacts ORDER BY name")

    while row := fetch(db) do {
        write("Contact: ", row.name, ", ", row.phone)
    }
    close(db)
end

examples/sql.icn

Sample run:

prompt$ unicon -s sql.icn -x
SELECT name, phone
Contact: brian, 613-555-1212
Contact: jafar, 615-555-1213
Contact: brian, 615-555-1214
Contact: clint, 615-555-1215
Contact: nico, 615-555-1216

ORDER BY name
Contact: brian, 613-555-1212
Contact: brian, 615-555-1214
Contact: clint, 615-555-1215
Contact: jafar, 615-555-1213
Contact: nico, 615-555-1216

sqrt

sqrt(r) : real

sqrt(r) produces the square root of r. Will raise a runtime error for negative values of r.

#
# sqrt.icn, demonstrate square root function
#
procedure main()
    every r := 4 | 2 | 1 | 0.5 | 0.25 | 0 | -1 do
        write(r, " ", sqrt(r))
end

examples/sqrt.icn

Sample run (ends with error demonstration):

prompt$ unicon -s sqrt.icn -x
4 2.0
2 1.414213562373095
1 1.0
0.5 0.7071067811865476
0.25 0.5
0 0.0

Run-time error 205
File sqrt.icn; Line 13
invalid value
offending value: -1.0
Traceback:
   main()
   sqrt(-1) from line 13 in sqrt.icn

stat

stat(s) : record

stat(f) returns a record of filesystem information for file (or path) f. See lstat.

Return record is:

record posix_stat(dev, ino, mode, nlink, gid, rdev, size,
                  atime, mtime, ctime, blksize, blocks, symlink)

The atime, ctime, and mtime fields may be formatted with the ctime() and gtime() functions. mode is a string form similar to the output of ls -l. stat() will fail if the file or path f does not exist.

#
# stat.icn, File status information, follows symbolic links.
#
link ximage
procedure main()
    every fn := "/usr/bin/cc" | "/usr/bin/gcc" do
        write("stat(", fn, "): ", ximage(stat(fn)))
end

examples/stat.icn

Sample run:

prompt$ unicon -s stat.icn -x
stat(/usr/bin/cc): R_posix_stat_1 := posix_stat()
   R_posix_stat_1.dev := 2049
   R_posix_stat_1.ino := 4325501
   R_posix_stat_1.mode := "lrwxrwxrwx"
   R_posix_stat_1.nlink := 1
   R_posix_stat_1.uid := "root"
   R_posix_stat_1.gid := "root"
   R_posix_stat_1.rdev := 0
   R_posix_stat_1.size := 20
   R_posix_stat_1.atime := 1571985764
   R_posix_stat_1.mtime := 1452760995
   R_posix_stat_1.ctime := 1452760995
   R_posix_stat_1.blksize := 4096
   R_posix_stat_1.blocks := 0
   R_posix_stat_1.symlink := "/etc/alternatives/cc"
stat(/usr/bin/gcc): R_posix_stat_2 := posix_stat()
   R_posix_stat_2.dev := 2049
   R_posix_stat_2.ino := 4338962
   R_posix_stat_2.mode := "lrwxrwxrwx"
   R_posix_stat_2.nlink := 1
   R_posix_stat_2.uid := "root"
   R_posix_stat_2.gid := "root"
   R_posix_stat_2.rdev := 0
   R_posix_stat_2.size := 5
   R_posix_stat_2.atime := 1571985754
   R_posix_stat_2.mtime := 1455184062
   R_posix_stat_2.ctime := 1468380583
   R_posix_stat_2.blksize := 4096
   R_posix_stat_2.blocks := 0
   R_posix_stat_2.symlink := "gcc-5"

staticnames

staticnames(CE, i) : string*

staticnames(ce, i) generates the names of local variables in co-expression ce, i levels up from the current procedure invocation. The default, level 0, generates names in the currently active procedure inside ce.

#
# staticames.icn, generate static variable names
#
global var, other
procedure main(arglist)
    static sv
    lv := 1
    var := 1
    every write(staticnames(&main))
end

examples/staticnames.icn

Sample run:

prompt$ unicon -s staticnames.icn -x
sv

stop

stop(s|f, ...)

stop(args) halts execution after writing out string arguments, followed by a newline, to &errout. If any argument is a file, subsequent string arguments are written to that file instead of &errout. The program exit status indicates that an error occurred.

#
# stop.icn, demonstrate program halt with message
#
procedure main()
    stop(&output, "stdout", &errout, "stderr")
end

examples/stop.icn

Sample run:

prompt$ unicon -s stop.icn
prompt$ ./stop ; echo $?
stdout
stderr
1

StopAudio

StopAudio(i) : integer [Audio]

StopAudio(i) stops the thread playing audio on channel i. Returns 1 or triggers an error if i is not an integer. Attempting to stop non running channel numbers will be gracefully ignored.

#
# StopAudio.icn, terminates an audio stream playback.
#
procedure main()
    channel := PlayAudio("/home/btiffin/unicon/tests/unicon/handclap.ogg")
    write("Audio channel: ", channel)
    # handclap gets 1/3 of a second to complete
    delay(300)
    StopAudio(channel)

    channel := PlayAudio("/home/btiffin/unicon/tests/unicon/alert.wav")
    write("Audio channel: ", channel)
    # alert gets cut off after 1/2 second
    delay(500)
    StopAudio(channel)
end

examples/StopAudio.icn

Sample run (skipped, you probably wouldn’t hear it anyway):

See also

PlayAudio, VAttrib


string

string(x) : string?

string(x) converts x to a string and returns the result, or fails if the conversion is not possible.

#
# string.icn, demonstrate convert to string
#
procedure main()
    write(image(string(123)))
    write(image(string(123.123)))
    write(image(string('abbracadabra')))
    # this last one fails, no write occurs
    write(image(string([1,2,3])))
end

examples/string.icn

Sample run:

prompt$ unicon -s string.icn -x
"123"
"123.123"
"abcdr"

structure

structure(CE) : any*

structure(ce) generates the values in the block region of ce. This heap holds structure types such as lists and tables.

#
# structure.icn, demonstrate looking in the heap for structure data
#
link ximage
procedure main()
    T := table(1, 2, 3, 4)
    L := [1,3]
    every write(ximage(structure(&current)))
end

examples/structure.icn

Sample run:

prompt$ unicon -s structure.icn -x
L-1 := list(0)
L-2 := list(0)
L-3 := list(0)
T1 := table(&null)
   T1[1] := 2
   T1[3] := 4
L1 := list(2)
   L1[1] := 1
   L1[2] := 3

Succeed

Succeed() : empty string

Succeed() places a fence on pattern matching, by matching the empty string when going left to right, and forcing the scanner to reverse direction forwards during backtracking.

Attention

This function will almost always cause an endless loop and should NOT be used. Except for wasting CPU when the pattern is known to match on a first pass, or endlessly spinning when the pattern matcher needs to backtrack. Use Fence (or possibly fail) instead.

#
# Succeed.icn, an anti-example, FOR WARNING PURPOSES ONLY
#
procedure main()
    # DON'T DO THIS, it causes an endless loop
    # result := "sstring" ?? Any('rst') || Succeed() || Span('rt') || "ing"

    # Do this instead
    result := "sstring" ?? Any('rst') || Fence() || Span('rt') || "ing"
    write(image(result))

    # the short of it is, DON'T USE Succeed()
end

examples/Succeed.icn

Sample run (skipped, as this pattern function is a no-win trap):

See also

fail, Fence


Swi

Swi() : type

An unsupported Archimedes specific feature.

Swi()

Sample run:


sys_errstr

sys_errstr(i) : string

sys_errstr(i) produces the error string corresponding to code i, or if not given, a code obtained from &errno.

#
# sys_errstr.icn, get string from system error code
#
procedure main()
    write(sys_errstr(1))
    write(sys_errstr(2))
    # errno will be 0, which is Success
    write(sys_errstr(&errno))
end

examples/sys_errstr.icn

Sample run:

prompt$ unicon -s sys_errstr.icn -x
Operation not permitted
No such file or directory
Success

system

system(x, f:&input, f:&output, f:&errout, s) : integer

system(x, f1, f2, f3, waitflag) executes a program in a separate process. x can be a string or a list of strings. For a single string, the command is processed by the platform’s command interpreter. For a list, each member is a separate argument, the first is the program and all subsequent parameters are passed as arguments to the command. The file arguments are used for standard in, standard out and standard error for the new process. If the waitflag is "nowait", then system() returns immediately and the result is the new process id. Otherwise Unicon will wait for the new program to finish and the result is a status value.

#
# system.icn, execute an external program
#
procedure main()
    r := system("ls -l nonexistent-file system.icn")
    write(r)
end

examples/system.icn

Sample run:

prompt$ unicon -s system.icn -x
ls: cannot access 'nonexistent-file': No such file or directory
-rw-rw-r-- 1 btiffin btiffin 255 Oct 14  2016 system.icn
2

syswrite

syswrite(f, s) : integer

syswrite(f, s) causes a low level unbuffered write of the string s to file f.

#
# syswrite.icn, demonstrate low level write
#
procedure main()
    r := syswrite(&output, "testing ")
    write(r)
end

examples/syswrite.icn

Sample run:

prompt$ unicon -s syswrite.icn -x
testing 8

Tab

Tab(i) : string

A SNOBOL inspired pattern matching function.

Tab(i) places the cursor at position i, and returns the characters between the current position and the new position.

#
# Tab.icn, SNOBOL pattern return characters, current to position 
#
procedure main()
    # match characters from current (1) to new cursor, set at 4.
    # returns characters from position 1,2,3 with cursor now at 4.
    "string" ?? Tab(4) => result || .> curs
    write(image(result), " ", curs)
end

examples/Tab.icn

Sample run:

prompt$ unicon -s Tab.icn -x
"str" 4

See also

Rtab


tab

tab(i:0) : string?

tab(i) sets &pos to i and returns the substring of &subject between the old and new positions. tab(0) moves the position to the end of the string. This function reverts settings the position to its old value if it is resumed.

#
# tab.icn, demonstrate string scanning position change tab function
#
procedure main()
    s := "this is a test"
    s ? out := tab(5)
    write(":", out, ":")
end

examples/tab.icn

Sample run:

prompt$ unicon -s tab.icn -x
:this:

table

table(k, v, ..., x) : table

table(x) creates a table with default value x. If x is a structure, all references to the default value refers to the same same value, not a separate copy for each key. Given more than one argument, table(k,v,...,x) takes alternating keys and values to initialize the table.

#
# table.icn, demonstrate creation of table function
#
procedure main()
    # set initial keys and values
    T := table(1, "a", 2, "b", c, "3")
    write(T[1])
    # create with default value
    T := table(42)
    write(T[1])
end

examples/table.icn

Sample run:

prompt$ unicon -s table.icn -x
a
42

tan

tan(r) : real

tan(r) returns the Tangent of the given angle, r (in radians). Tangent is the ratio of the Opposite/Adjacent lines of a right angle triangle. tan(r) will cause a runtime error for r values that are multiples of &pi / 2 radians, the result being imaginary infinity.

#
# tan.icn, demonstrate the the Tangent function
#
procedure main()
    write("tan(r): Domain: -2 * &pi <= r <= &pi * 2, Range: all real, imaginary at &pi/2 * i") 
    every r := 0.0 to &pi * 2 by &pi/4 do {
        write(left("tan(" || r || ")", 24), " radians = ", tan(r))
    }
end

examples/tan.icn

Sample run:

prompt$ unicon -s tan.icn -x
tan(r): Domain: -2 * &pi <= r <= &pi * 2, Range: all real, imaginary at &pi/2 * i
tan(0.0)                 radians = 0.0
tan(0.7853981633974483)  radians = 0.9999999999999999
tan(1.570796326794897)   radians = 1.633123935319537e+16
tan(2.356194490192345)   radians = -1.0
tan(3.141592653589793)   radians = -1.224646799147353e-16
tan(3.926990816987241)   radians = 0.9999999999999997
tan(4.71238898038469)    radians = 5443746451065123.0
tan(5.497787143782138)   radians = -1.0
tan(6.283185307179586)   radians = -2.449293598294706e-16

Graphical plot:

#
# plot-function, trigonometric plotting, function from command line
#
$define points 300
$define xoff   4
$define base   64
$define yscale 60
$define xscale 100

invocable "sin", "cos", "tan"

# plot the given function, default to sine
procedure main(args)
    func := map(args[1]) | "sin"
    if not func == ("sin" | "cos" | "tan") then func := "sin" 

    # range of pixels for 300 points, y scaled at +/- 60, 4 pixel margins
    &window := open("Plotting", "g", "size=308,128", "canvas=hidden")

    # tan may cause runtime errors
    if func == "tan" then &error := 6

    color := "vivid orange"
    Fg(color)
    write(&window, "\n " || func)

    Fg("gray")
    DrawLine(2, 64, 306, 64)
    DrawLine(2, 2, 2, 126)
    DrawString(8, 10, "1", 8, 69, "0", 2, 126, "-1")
    DrawString(270, 76, left(points * 2 * &pi / 100, 6))

    Fg(color)
    every x := 0 to points do
        DrawPoint(xoff + x, base + yscale * func((2 * &pi * x) / xscale))

    WSync()
    WriteImage("../images/plot-" || func || ".png")
    close(&window)
end

examples/plot-function.icn

prompt$ unicon -s plot-function.icn -x tan
_images/plot-tan.png

images/plot-tan.png


Texcoord

Texcoord() : type

Todo

entry for function Texcoord

Texcoord()

examples/Texcoord.icn

Sample run:


Texture

Texture() : type

Todo

entry for function Texture

Texture()

examples/Texture.icn

Sample run:


TextWidth

TextWidth() : type

Todo

entry for function TextWidth

TextWidth()

examples/TextWidth.icn

Sample run:


Translate

Translate() : type

Todo

entry for function Translate

Translate()

examples/Translate.icn

Sample run:


trap

trap(s, p) : procedure

trap(s, proc) sets up a signal handler for the signal s (by name). The old handler, if any, is returned. If proc is null, then handler is reset to a default value.

#
# trap.icn, set signal handlers
#
procedure main()
    p := trap("SIGINT", gotint)
    write(image(p))
    p := trap("SIGINT")
    write(image(p))
end

procedure gotint(a)
    write(image(a))
    write("^C captured")
end

examples/trap.icn

Sample run:

prompt$ unicon -s trap.icn -x
&null
procedure gotint

trim

trim(s, c:' ', i:-1) : string

trim(s, c, i) removes any of the characters in c from the ends of s. i specifies from where:

  • -1 trailing
  • 1 leading
  • 0 both ends.
#
# trim.icn, demonstrate the trim function
#
procedure main()
    s := "  this is a test  "
    write(":", trim(s), ":")
    write(":", trim(s,,1), ":")

    # note, not \t, but "t", trim leading and trailing ts and spaces
    write(":", trim(s,' t',0), ":")
end

examples/trim.icn

Sample run:

prompt$ unicon -s trim.icn -x
:  this is a test:
:this is a test  :
:his is a tes:

truncate

truncate(f, i) : ?

truncate(f, len) changes the file f which may be a filename or an open file, to be no longer than length len. truncate() does not work on database, network connection, pipe, or window resources. Files already shorter than i will be filled with padding, usually zero bytes.

#
# truncate.icn, truncate a file to a given length
#
procedure main()
    if truncate("tt.tt", 256) then
        writes("did") else writes("didn't")
    write(" truncate")
end

examples/truncate.icn

Sample run:

prompt$ unicon -s truncate.icn -x
didn't truncate

trylock

trylock(x) : x?

trylock(m) locks the mutex x or the mutex associated with the thread-safe object x, if it is not already locked.

#
# trylock.icn, lock a mutex if not already locked
#
procedure main()
    x := 1
    mtx := mutex()
    if trylock(mtx) then {
        write("locked mtx")
        x := x + 1
        unlock(mtx)
    }
end

examples/trylock.icn

Sample run:

prompt$ unicon -s trylock.icn -x
locked mtx

type

type(x) : string

Returns the type of x.

type(x) returns a string representation of the type name of x.

#
# type.icn, demonstrate the type() function
#
procedure main()
    # list of expressions to evaluate
    types := [
        "type(1)",
        "type(type(1))",
        "type(\"abc\")",
        "type(L)",
        "type(T)",
        "type(S)",
        "type(R)",
        "type(C)",
        "type(&window)",
        "type(file)"
    ]

    # generate some code to evaluate the expressions
    prog := "generated-type-program.icn"
    tmp := open(prog, "w") | stop("Can't open " || prog || " for writing")
    write(tmp, "record rec(a,b)")
    write(tmp, "procedure main()")
    write(tmp, "    L := []")
    write(tmp, "    T := table()")
    write(tmp, "    S := set()")
    write(tmp, "    R := rec(1,2)")
    write(tmp, "    C := create 1")
    write(tmp, "    &window := open(\"window\", \"g\", \"canvas=hidden\")")
    write(tmp, "    file := open(&file, \"r\")")
    every t := !types do {
        write(tmp, "    write(right(", image(t), " || \": \"", ",16), ", t, ")")
    }
    write(tmp, "    close(file)")
    write(tmp, "    close(&window)")
    write(tmp, "end")
    close(tmp)

    # pipe in the results
    p := open("unicon -quiet -s -v0 " || prog || " -x", "p")
    while write(read(p))
    close(p)

    # get rid of the generated source and executable
    remove(prog)
    remove(prog[1:-4])
end

examples/type.icn

Sample run:

prompt$ unicon -s type.icn -x
       type(1): integer
 type(type(1)): string
   type("abc"): string
       type(L): list
       type(T): table
       type(S): set
       type(R): rec
       type(C): co-expression
 type(&window): window
    type(file): file

umask

umask(integer) : integer [POSIX]

umask(u) sets the umask for the current process to u, a nine bit encoding of read, write, execute permissions for user, group and world access. Each bit of umask turns off that access, by default, for newly created files. umask(u) returns the old value.

#
# umask.icn, set default file permission mask
#
procedure main()
    write(umask(0))
end

examples/umask.icn

Sample run:

prompt$ unicon -s umask.icn -x
2

Uncouple

Uncouple() : type

Todo

entry for function Uncouple

Uncouple()

examples/Uncouple.icn

Sample run:


unlock

unlock(x) : x

unlock(m) unlocks the mutex m or the mutex associated with the thread-safe object x

#
# unlock.icn, unlock a mutex
#
procedure main()
    x := 1
    mtx := mutex()
    if trylock(mtx) then {
        write("locked mtx")
        x := x + 1
        unlock(mtx)
    }
end

examples/unlock.icn

Sample run:

prompt$ unicon -s unlock.icn -x
locked mtx

upto

upto(c, s:&subject, i:1, i:0) : integer*

String scanning function upto(c, s, i1, i2) generates the sequence of integer positions in s scanning forward for characters in the cset c between indexes i1 and i2. upto() fails if there is not such position.

#
# upto.icn, demonstrate the string scanning upto generator
#
procedure main()
    s := "  this is a test  "
    write(s)
    s ? every i := upto('st') do write(i, " ", &subject[i])
end

examples/upto.icn

Sample run:

prompt$ unicon -s upto.icn -x
  this is a test  
3 t
6 s
9 s
13 t
15 s
16 t

utime

utime(s, i, i) : null

utime(f, atime, mtime) sets the access and modification time of filename f to atime and mtime respectively. ctime is set to the current time.

#
# utime.icn, demonstrate setting file access times
#
procedure main()
    atime := &now
    mtime := &now - 4
    utime("newfile.txt", atime, mtime)
end

examples/utime.icn

Sample run:

prompt$ unicon -s utime.icn -x

variable

variable(s, CE:&current, i:0) : any?

variable(s, ce, i) returns a reference to the variable name s from the co-expression ce, i levels up from the current procedure frame. Name search is local to ce then global to the program that created ce.

#
# variable.icn, demonstrate reflective variable name lookup
#
procedure main()
    this := 42
    v := variable("this")
    write(v)

    # assignment made a copy of the integer
    this := 44
    write(v)

    # structures stay as references during assignment
    L := [1,2,3]
    l := variable("L")
    L[2] := 4
    write(l[2])
end

examples/variable.icn

Sample run:

prompt$ unicon -s variable.icn -x
42
42
4

VAttrib

VAttrib() : type

Todo

entry for function VAttrib

VAttrib()

examples/VAttrib.icn

Sample run:


wait

wait(x) : ?

wait(x) waits for x. If x is a thread, wait() waits for x to finish. If x is a condition variable, condvar, then wait() waits until that variable is signalled from another thread.

#
# wait.icn, demonstrate thread and condvar wait
#
procedure main()
    write("waiting ", gettimeofday().usec)
    th := thread(every 1 to 100000)
    wait(th)
    write("no longer waiting ", gettimeofday().usec)
end

examples/wait.icn

Sample run:

prompt$ unicon -s wait.icn -x
waiting 902855
no longer waiting 908490

WAttrib

WAttrib(w, x, ...) → x

WAttrib(w, s, w2, s2) will change the attribute of window w to the value specified in s and the attribute of window w2 to the pair specified in s2. WAttrib(w, s) will retrieve the given attribute if no “set” operation is specified, “dy” versus “dy=yoffset” in the string s.

Todo

this graphics section is woefully incomplete

Attributes include:

Canvas Attributes

  • size=wid,hgt
  • pos=x,y
  • canvas=normal|hidden
  • windowlabel=string
  • inputmask=string
  • pointer=arrow,clock,etc
  • pointerx=x
  • pointery=y
  • display=device (X11)
  • depth=integer (# of bits)
  • displaywidth=x
  • displayheight=y
  • image=string

Graphics contexts

  • fg=colour
  • bg=colour
  • font=name
  • fheight=integer
  • fwidth=integer
  • leading=integer (vertical pixels between lines)
  • ascent=integer
  • descent=integer
  • drawop=operation (copy, reverse)
  • fillstyle=type (stippled, opaquestippled)
  • pattern=pattern (bits,#hex)
  • linestyle=style (onoff, doubledash)
  • linewidth=integer
  • clipx=integer
  • clipy=integer
  • clipw=integer
  • cliph=integer
  • dx=integer (coordinate translation)
  • dy=integer (coordinate translation)

3D attributes

  • dim=
  • pick=
  • texmode=
  • slices=
  • rings=
  • normode=

Example:

#
# WAttrib, demonstrate window attribute control
#
procedure main()
    w := open("WAttrib", "g", "size=40,40", "canvas=hidden")

    write("Default Attributes (given size=40,40)")
    write("-------------------------------------")
    alist := ["fg", "bg", "size", "pos", "canvas", "windowlabel",
              "inputmask", "pointer", "pointerx", "pointery",
              "display", "depth", "displaywidth", "displayheight",
              "font", "fheight", "fwidth", 
              "leading", "ascent", "descent", "drawop", 
              "fillstyle", "pattern", "linestyle", "linewidth", 
              "clipx", "clipy", "clipw", "cliph", "dx", "dy"]
    every a := !sort(alist) do write(left(a, 16), ": ", WAttrib(w, a))

    WAttrib(w, "fg=vivid orange")
    DrawCircle(w, 20, 20, 18)
    WFlush(w)

    # change the display offsets along with colour
    WAttrib(w, "dx=5", "dy=5", "fg=blue")
    DrawCircle(w, 20, 20, 9, 0.0, &pi)
    WSync(w)

    # save image for the document
    WriteImage(w, "../images/WAttrib.png")
    close(w)
end

examples/WAttrib.icn

Sample run:

prompt$ unicon -s WAttrib.icn -x
Default Attributes (given size=40,40)
-------------------------------------
ascent          : 11
bg              : white
canvas          : hidden
cliph           : 
clipw           : 
clipx           : 
clipy           : 
depth           : 24
descent         : 2
display         : localhost:10.0
displayheight   : 900
displaywidth    : 1600
drawop          : copy
dx              : 0
dy              : 0
fg              : black
fheight         : 13
fillstyle       : solid
font            : fixed
fwidth          : 6
inputmask       : 
leading         : 13
linestyle       : solid
linewidth       : 1
pattern         : black
pointer         : left ptr
pointerx        : 17456
pointery        : -741
size            : 40,40
windowlabel     : WAttrib

Almost the same image as WFlush, but dx and dy are offset a bit on the blue half circle.

_images/WAttrib.png

images/WAttrib.png

See also

WSync, Graphics


WDefault

WDefault() : type

Todo

entry for function WDefault

WDefault()

examples/WDefault.icn

Sample run:


WFlush

WFlush(w) → window

WFlush(w) flushes window w output on window systems that buffer text and graphic output, without waiting for all pending events. Window data is automatically flushed during events that block. This function is a no-op on systems that do not buffer graphical output.

#
# WFlush, demonstrate windowing buffer flush
#
procedure main()
    w := open("WFlush", "g", "size=40,40", "canvas=hidden")

    Fg(w, "vivid orange")
    DrawCircle(w, 20, 20, 18)
    WFlush(w)

    Fg(w, "blue")
    DrawCircle(w, 20, 20, 9, 0.0, &pi)
    WFlush(w)

    # save image for the document
    WriteImage(w, "../images/WFlush.png")
    close(w)
end

examples/WFlush.icn

Sample run:

prompt$ unicon -s WFlush.icn -x
_images/WFlush.png

images/WFlush.png

See also

WSync


where

where(f) : integer

where(f) returns the current offset position in file f. where() fails for window and network resources. The beginning of a file is offset 1.

#
# where.icn, demonstrate file offset reporting
#
procedure main()
    f := open("newfile.txt", "r")
    read(f)
    write(where(f))
    close(f)
end

examples/where.icn

Sample run:

prompt$ unicon -s where.icn -x
16

WinAssociate

WinAssociate(s) : string [Windows]

WinAssociate(s) returns the application name associated with the string file extension s. Requires Unicon for Windows, non-portable.

#
# WinAssociate.icn, return the application name associated with extension
# Requires Unicon for Windows
#
procedure main()
    write(WinAssociate("test"))
end

examples/WinAssociate.icn

Sample run: (not supported on the OS that builds this document)

prompt$ unicon -s WinAssociate.icn -x

Run-time error 121
File WinAssociate.icn; Line 13
function not supported
Traceback:
   main()
   WinAssociate("test") from line 13 in WinAssociate.icn

See Unicon Technical Report 7, http://unicon.org/utr/utr7.html

The Windows only functions are no longer recommended for new Unicon developments. The VIB and GUI class library should be used to create cross platform programs.


WinButton

WinButton(w, s, x,y, wd,ht) : string [Windows]

WinButton(w, s, x, y, wd, ht) installs a pushbutton with label s at x,y, wd pixels wide and ht pixels high, on window w. When pressed the button label s is placed on the event queue. Non-portable.

#
# WinButton.icn, install a pushbutton, with label, on window
# only works on supported systems
#
link enqueue, evmux
procedure main()
    window := open("WinButton", "g", "size=90,60", "canvas=hidden")
    WinButton(window, "Button", 5,5, 30,15)
    Enqueue(window, &lpress, 11, 14, "", 2)
    e := Event(w, 1)
    write("event at mouse position (", &x, ",", &y, ")")
    close(window)
end

examples/WinButton.icn

Sample run (not supported on the OS that builds this document):

prompt$ unicon -s WinButton.icn -x

Run-time error 121
File WinButton.icn; Line 15
function not supported
Traceback:
   main()
   WinButton(window_1:1(WinButton),"Button",5,5,30,15) from line 15 in WinButton.icn

See Unicon Technical Report 7, http://unicon.org/utr/utr7.html.

The Windows only functions are no longer recommended for new Unicon developments. The VIB and GUI class library can and should be used to create cross platform programs.

See also

Event


WinColorDialog

WinColorDialog() : type

Todo

entry for function WinColorDialog

WinColorDialog()

examples/WinColorDialog.icn

Sample run:


WindowContents

WindowContents(w) : list [3D graphics]

WindowContents(w) returns a List (arrays) of current 3D window w contents.

#
# WindowContents.icn, demonstrate WindowContents list
#
link ximage
procedure main()
    window := open("WindowContents", "gl", "bg=black", "buffer=on",
                    "size=400,260", "dim=3")#, "canvas=hidden")
    WAttrib(window,"light0=on, ambient blue-green","fg=specular white")

    # A torus 
    DrawTorus(window, 0.0,0.19,-2.2, 0.3,0.4)

    # show the window contents list
    Refresh(window)
    write(ximage(WindowContents(window)))

    # save the image
    WriteImage(window, "../images/WindowContents.png")

    close(window)
end

examples/WindowContents.icn

Sample run:

prompt$ unicon -s WindowContents.icn -x
L2 := list(3)
   L2[1] := L3 := list(3)
      L3[1] := "dim"
      L3[2] := 336
      L3[3] := 3
   L2[2] := L4 := list(7,65535)
      L4[1] := "Fg"
      L4[2] := 160
      L4[3] := "specular"
   L2[3] := R_gl_torus_1 := gl_torus()
      R_gl_torus_1.name := "DrawTorus"
      R_gl_torus_1.code := 149
      R_gl_torus_1.x := 0.0
      R_gl_torus_1.y := 0.19
      R_gl_torus_1.z := -2.2
      R_gl_torus_1.radius1 := 0.3
      R_gl_torus_1.radius2 := 0.4
_images/WindowContents.png

images/WindowContents.png


WinEditRegion

WinEditRegion(s, s2, x,y, wd,ht) : string

WinEditRegion(w, s, s2, x,y, wd,ht) manipulates a Windows edit region named s. This flexible editor is limited to text that is < 32Kbytes in length. The operation performed depends on argument s2. If argument s2 is omitted, WinEditRegion(s) returns a string containing the current contents of region s. If s2 is supplied and does not start with a !, it is a string to be edited; lines are separated by rn. s2 strings starting with ! are commands:

  • WinEditRegion(s, ”!clear”) clears the current selection.
  • WinEditRegion(s, ”!copy”) copies the current selection.
  • WinEditRegion(s, ”!cut”) cuts the current selection.
  • WinEditRegion(s, ”!paste”) pastes the current selection.
  • WinEditRegion(s, ”!modified”) succeeds if region s has been modified since last assigned.
  • WinEditRegion(s, ”!setsel”) sets the selection using parameters x and y as indices..
  • WinEditRegion(s, ”!undo”) undoes the previous operation, if possible.

examples/WinEditRegion.icn

Sample run:


WinFontDialog

WinFontDialog() : type

Todo

entry for function WinFontDialog

WinFontDialog()

examples/WinFontDialog.icn

Sample run:


WinMenuBar

WinMenuBar() : type

Todo

entry for function WinMenuBar

WinMenuBar()

examples/WinMenuBar.icn

Sample run:


WinOpenDialog

WinOpenDialog(w, s1, s2, i, s3,j, s4) : string

WinOpenDialog(w, s1, s2, i, s3,j, s4) displays a typical open dialog to perform file selection for reading. s1 is the caption, s2 the default value and i is the text entry field size. s3 and j specify the filter string and its index. s3 is a string of alternating names and filters, separated and ending in |, of the form "name1|filter1|name2|filter2|...|". s3 defaults to "All Files(*.*)|*.*|". j supplies the default extension index within s3; it defaults to first pair in filter string. s4 is the directory to show when the dialog is opened; it defaults to use Windows version-specific rules. Returns the file name chosen. Fails if the user selects Cancel.

#
# WinOpenDialog.icn, open a native Windows file open dialog box.
#
#
procedure main()
    w := open("WinOpenDialog", "g")
    fn := WinSaveDiaglog(w, "Open", "SomeData.dat", 24,
                            "Dat files(*.dat)|*.dat|All (*.*)|*.*|", 1
                            "../data")
    close(w)
end

examples/WinOpenDialog.icn

Sample run not available, code untested.


WinPlayMedia

WinPlayMedia(w, s1,...) : null

WinPlayMedia(w, s1, s2) plays media file s1 followed by s2 for each argument. Media can be .wav, .mdi, .rmi or if unrecognized the string passed to MCI for supported media files.

Fails on the first media file that cannot be played.

#
# WinPlayMedia.icn, play media files with native Windows
#
#
procedure main()
    w := open("WinPlayMedia", "g")
    WinPlayMedia(w, "alert.wav", "relax.mdi")
    close(w)
end

examples/WinPlayMedia.icn

Sample run not available, code untested.

Deprecated, see PlayAudio for the recommended cross-platform solution.


WinSaveDialog

WinSaveDialog(w, s1, s2, i, s3,j, s4) : string

WinSaveDialog(w, s1, s2, i, s3,j, s4) opens a typical save dialog to perform file selection for writing. s1 is the caption, s2 the default value and i is the text entry field size. s3 and j specify the filter string and its index. s3 is a string of alternating names and filters, separated and ending in |, of the form "name1|filter1|name2|filter2|...|". s3 defaults to "All Files(*.*)|*.*|". j supplies the default extension index within s3; it defaults to first pair in filter string. s4 is the directory to show when the dialog is opened; it defaults to use Windows version-specific rules. Returns the file name chosen. Fails if the user selects Cancel.

#
# WinSaveDialog.icn, open a native Windows file save dialog box.
#
#
procedure main()
    w := open("WinSaveDialog", "g")
    fn := WinSaveDiaglog(w, "Save to", "NewFile.dat", 24,
                            "Dat files(*.dat)|*.dat|All (*.*)|*.*|", 1
                            "../data")
    close(w)
end

examples/WinSaveDialog.icn

Sample run not available, code untested.


WinScrollBar

WinScrollBar() : type

Todo

entry for function WinScrollBar

WinScrollBar()

examples/WinScrollBar.icn

Sample run:


WinSelectDialog

WinSelectDialog(w, s1, buttons) : string [Windows Unicon]

WinSelectDialog(w, title, L) displays a Windows native dialog box on window w, labelled title, offering a selection from a set of choices in the form of buttons, [“choice1”, “choice2”] (as list of strings). Event() will return the choice as a string.

#
# WinSelectDialog.icn, a Windows native choice selection dialog
#
# Deprecated in favour of the cross-platform Unicon GUI classes
#
procedure main()
    w := open("WinSelectDialog", "g", "size=400,300")
    choice := WinSelectDialog(w, "choices", "Choice A", "Choice B")
    close(w)
end

examples/WinSelectDialog.icn

Sample run not available.

Deprecated. The native Windows procedures are now deprecated in favour of the cross-platform Unicon gui classes.


write

write(s|f, ...) : string|file

write(arglist) outputs strings, followed by a newline to a file or files. Strings are written to the closest preceding file argument, defaulting to &output. A newline is written whenever a non-initial file arguments directs output to a different file, or after the last argument. write() returns the last argument.

#
# write.icn, demonstrate write (adds newline)
#
procedure main()
    write("first", &errout, "std err", &output, "back to std out")
end

examples/write.icn

Sample run:

prompt$ unicon -s write.icn -x
first
std err
back to std out

WriteImage

WriteImage(w, s, x:0, y:0, wid:0, h:0) : window [Graphics]

WriteImage(w, s, x, y, wid, h) saves an image of dimensions wid, h from window w (defaults to &window), at offset x, y to a file named s. The default is to save the entire window. The output format is written according the extension, GIF, JPG, BMP, PNG (depending on available library during Unicon build). Platform specific formats, such as XBM or XPM may also be supported. WriteImage() fails if s cannot be opened for writing.

Almost all included graphics are generated during the builds of this documentation and saved with WriteImage(), even the “no-image” image.

Only the canvas image is included, window decorations (as provided by desktop window managers) are not part of images saved by WriteImage().

#
# WriteImage.icn, demonstrate saving images
#
procedure main()
    &window := open("Pattern", "g",
                    "fillstyle=stippled",
                    "size=85,40", "canvas=hidden")
    # A width 4 pattern, with bit patterns of 2, 8, 2, 8
    Pattern(&window, "4,2,8,2,8")
    Fg(&window, "red")
    FillRectangle(&window, 0, 0, 40, 40)

    # built in checker board pattern
    Pattern("checkers")
    Fg("black")
    FillRectangle(45, 0, 40, 40)

    # save image for the document
    WSync()
    WriteImage("../images/WriteImage.png")
    close(&window)
end

examples/WriteImage.icn

Sample run:

prompt$ unicon -s WriteImage.icn -x
_images/WriteImage.png

images/WriteImage.png


writes

writes(s|f, ...) : string|file

writes(arglist) outputs strings to a file or files. Strings are written to the closest preceding file argument, defaulting to &output. write() returns the last argument.

#
# writes.icn, demonstrate writes
#
procedure main()
    # first to default &output, then a string to &errout, then &output
    # stream buffers for output and error can cause random display order 
    writes("first ", &errout, " to std err ", &output, " to std out ")
end

examples/writes.icn

Sample run: standard stream buffering might cause &errout to display separately from &output.

prompt$ unicon -s writes.icn -x
first  to std out  to std err

WSection

WSection(w, s) : record

WSection(w, s) starts a new window section named s on 3D window w. Returns a display list section marker record. During window Refresh, if the section marker’s skip field is 1, the section is skipped. The section name s is produced by &pick is the graphic object in the block is clicked on when the attribute "pick=on" is set. WSection(w) marks the end of a named section. WSection blocks can be nested.

#
# WSection.icn, demonstrate 3D pick object ID during windowing event
#
link enqueue, evmux
procedure main()
    window := open("WSection", "gl", "size=90,60")
    WAttrib(window, "pick=on")

    # mark a named 3D object
    write(image(WSection(window, "sphere")))
    DrawSphere(window, 0.0, 0.19, -2.2, 0.3)
    Refresh(window)
    WSection(window)

    # insert an event into the queue, left press, 2ms interval, on sphere
    #Enqueue(window, &lpress, 45,20, "", 2)
    
    e := Event(window)
    write(image(e))

    # a side effect of the Event function is keywords settings
    write("&x:", &x)
    write("&y:", &y)
    write("&row:", &row)
    write("&col:", &col)
    every write("&pick:", &pick)

    WriteImage(window, "../images/WSection.png")
    close(window)
end

examples/WSection.icn

Sample output, having clicked on the small sphere:

prompt$ unicon -s WSection -x
record gl_mark_1(7)
-1
&x:43
&y:21
&row:2
&col:8
&pick:sphere
_images/WSection.png

images/WSection.png


WSync

WSync(w, s) : w

WSync(w, s) synchronizes the program with the server attached to window w on systems that employ a client-server model. Output to the window is flushed, and WSync() waits for a reply from the server indicating that all output has been processed. If s is "yes", all pending events on w are discarded. WSync() is a no-op on windowing systems that do not use a client-server model.

#
# WSync.icn, demonstrate window buffer sync
#
procedure main()
    w := open("WSync", "g", "size=40,40", "canvas=hidden")

    Fg(w, "vivid orange")
    DrawCircle(w, 20, 20, 18)
    WSync()

    Fg(w, "blue")
    DrawCircle(w, 20, 20, 9, 0.0, &pi)
    # sync windowing system and discard all pending events
    WSync(w, "yes")

    # save image for the document
    WriteImage(w, "../images/WSync.png")
    close(w)
end

examples/WSync.icn

Sample run:

prompt$ unicon -s WSync.icn -x
_images/WSync.png

images/WSync.png

See also

Refresh, WFlush


Index | Previous: Reserved words | Next: Keywords