Functions¶
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
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
, .
#
# 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
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, Returns: arc cosine of r, Produces the inverse cosine of , result in .
“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
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
prompt$ unicon -s plot-arccos.icn -x acos
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
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
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
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
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
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
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
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
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
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
prompt$ unicon -s plot-arcfunction.icn -x asin
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
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
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
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
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
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
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
Sample run:
prompt$ unicon -s Bg.icn -x
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
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
Sample run:
Matched: g
Matched: integ
See Break.
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
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
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
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
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
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
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
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/uni72173793
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
Sample run:
prompt$ unicon -s Clip.icn -x
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
Sample run:
prompt$ unicon -s Clone.icn -x
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
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
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
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
Sample run:
prompt$ unicon -s Color.icn -x
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
Sample run:
prompt$ unicon -s ColorValue.icn -x
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
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
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
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
Sample run:
prompt$ unicon -s CopyArea.icn -x
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
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
prompt$ unicon -s plot-function.icn -x cos
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
Sample run:
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
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 crypt
ed 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
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
Sample run:
Wed Dec 31 19:00:00 1969
Sun Oct 27 04:46:12 2019
Tue Oct 29 04:46:12 2019
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
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
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
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
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
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
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
A sample run:
prompt$ unicon -s delay.icn -x
322950
333070
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
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
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:¤t)
: 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
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
Sample run:
prompt$ unicon -s DrawArc.icn -x
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
Sample run:
prompt$ unicon -s DrawCircle.icn -x
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
Sample run:
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
Sample run:
prompt$ unicon -s DrawCurve.icn -x
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
Sample output:
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
Sample output:
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
Sample run:
prompt$ unicon -s DrawImage.icn -x
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
Sample run:
prompt$ unicon -s DrawLine.icn -x
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
With a run sample of:
prompt$ unicon -s linedrawing.icn -x
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
Sample run:
prompt$ unicon -s DrawPoint.icn -x
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
Sample output:
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
Sample run:
prompt$ unicon -s DrawPolygon.icn -x
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
Sample run:
prompt$ unicon -s DrawRectangle.icn -x
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
Sample run:
prompt$ unicon -s DrawSegment.icn -x
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
Sample output:
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
Sample run:
prompt$ unicon -s DrawString.icn -x
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
Sample output:
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
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
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
Sample run:
prompt$ unicon -s EraseArea.icn -x
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
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
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(¤t)))
coex := create(write(image(eventmask(¤t))))
@coex
end
Sample run:
prompt$ unicon -s eventmask.icn -x
in main with eventmask &null
&null
See also
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
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
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
#
# exec-replacement.icn, the program replaced by the exec function demo
#
procedure main(arglist)
write(&progname)
every write(!arglist)
end
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Sample run:
prompt$ unicon -s FillCircle.icn -x
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
Sample run:
prompt$ unicon -s FillPolygon.icn -x
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
Sample run:
prompt$ unicon -s FillRectangle.icn -x
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
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
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
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
Sample run:
prompt$ unicon -s Font.icn -x
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
Sample run:
prompt$ unicon -s fork.icn -x
parent process: 9555, 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
Sample run:
prompt$ unicon -s FreeColor.icn -x
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
Sample run (skipped on this GNU/Linux build machine):
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
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
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
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
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
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
Sample run:
prompt$ unicon -s getenv.icn -x
/bin/bash
See also
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
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
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
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
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
Sample run:
prompt$ unicon -s getpgrp.icn -x
8270
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
Sample run:
prompt$ unicon -s getpid.icn -x
9674
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
Sample run:
prompt$ unicon -s getppid.icn -x
9684
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
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
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 := 4000
R_posix_rusage_1.stime := R_posix_timeval_2 := posix_timeval()
R_posix_timeval_2.sec := 0
R_posix_timeval_2.usec := 4000
R_posix_rusage_1.maxrss := 6456
R_posix_rusage_1.minflt := 569
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,4000),posix_timeval(0,4000),6456,574,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 := 2488
R_posix_rusage_3.minflt := 181
R_posix_rusage_3.majflt := 0
R_posix_rusage_3.inblock := 0
R_posix_rusage_3.oublock := 0
R_posix_rusage_3.nvcsw := 4
R_posix_rusage_3.nivcsw := 1
posix_rusage(posix_timeval(0,0),posix_timeval(0,0),2488,181,0,0,0,4,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
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
Sample run (skipped on this GNU/Linux build machine):
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
Sample run:
prompt$ unicon -s gettimeofday.icn -x
1572165992 seconds since the Unix epoch
828037 microsecond counter
Sun Oct 27 04:46:32 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
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
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.
See also
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
Sample run:
prompt$ unicon -s GotoRC.icn -x
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
Sample run:
prompt$ unicon -s GotoXY.icn -x
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
Sample run:
Thu Jan 1 00:00:00 1970
Sun Oct 27 08:46:34 2019 Greenwich Mean Time
Tue Oct 29 08:46:34 2019
hardlink¶
hardlink(s, s)
: ? [POSIX]
hardlink(src, dst)
creates a hard link on the file system, dst becomes a
directory entry referencing the same file system i-node as src. This creates
a new name for src, and changes to dst will effect src.
#
# hardlink.icn, demonstrate the POSIX hard link() function
#
procedure main()
hardlink("tt.src", "tt.link")
end
Sample run:
prompt$ unicon -s hardlink.icn -x
With that link, if tt.src
started out containing:
tt.src file data
A change to tt.dst
, say with:
prompt$ echo 'tt.dst file data'
The disk data blocks in tt.src
have been changed:
prompt$ cat tt.src
tt.dst file data
See symlink for the more frequently used soft link.
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
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
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
Sample run (not auto captured):
prompt$ unicon -s IdentityMatrix.icn -x
gl_pushmatrix("PopMatrix",224)
See also
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
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
Sample run (skipped on this GNU/Linux build machine):
See also
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
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
Sample run (skipped on this GNU/Linux build machine):
See ipl/procs/io.icn
for an old working example of Int86()
.
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
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
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
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
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
Sample run:
prompt$ unicon -s istate.icn -x
attribute count = 0
attribute ilevel = 1
attribute ipc = 40652992
attribute ipc_offset = 640
attribute sp = 140299240580016
attribute efp = 140299240579880
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
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
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
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:¤t,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", ¤t, 0))
@ce1
write(&line)
@ce1
end
|
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
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
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
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
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
#
# load-module.icn, a demonstration module for use with load sample.
#
procedure main(arglist)
every write(!arglist)
end
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
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);
}
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
Sample run:
prompt$ unicon -s localnames.icn -x
lv
See also
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
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
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
Sample run:
prompt$ unicon -s Lower.icn -x
See also
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
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 := 1572162119
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
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
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
Sample run:
prompt$ unicon -s match.icn -x
5
:this:
:this:
See also
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
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
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
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
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
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
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
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
Sample run:
prompt$ unicon -s mkdir.icn -x
created directory mkdir-sample with 8r755
drwxr-xr-x 2 btiffin btiffin 4096 Oct 27 04:46 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
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
Sample run:
See also
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
Sample run:
prompt$ unicon -s mutex.icn -x
1
10
11
12
x is 12
See also
name¶
name(v, CE:¤t)
: 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
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
Sample run:
prompt$ unicon -s NewColor.icn -x
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
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
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
Sample run:
prompt$ unicon -s Nspan.icn -x
"str"
""
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
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
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
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
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
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
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
Sample run (skipped on this GNU/Linux build machine):
See also
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
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
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
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
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(¤t))
lp := load("load-child")
@lp
end
#
# load-child.icn, a demonstration of the parent function
#
procedure main()
write("in load-child with ", image(¤t))
write("parent is ", image(parent(¤t)))
end
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
Sample run:
prompt$ unicon -s Pattern.icn -x
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
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
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
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
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"
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
Sample run (skipped, you probably wouldn’t hear it from here anyway):
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
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
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
Sample run:
See also
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
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
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
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
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
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
Sample run (skipped):
See also
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
Sample run (not auto generated):
See also
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
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
Sample run:
prompt$ unicon -s QueryPointer.icn -x
mouse cursor relative to window w: 0,0
mouse cursor relative to screen: 819,594
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
Sample run:
prompt$ unicon -s Raise.icn -x
See also
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
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
Sample run:
prompt$ unicon -s ReadImage.icn -x
Art by Serendel Macphereson
See also
readlink¶
-
readlink
(path : string) → string Produces the filename referenced by the symbolic link, path.
Parameters: path – the path to dereference Returns: The linked filename
readlink(s)
: string
readlink(s)
produces the filename referred to by the symbolic link at path
s.
#
# readlink.icn, demonstrate the POSIX readlink() function
#
procedure main()
write(readlink("tt.dst"))
end
Sample run:
prompt$ unicon -s readlink.icn -x
tt.src
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
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
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
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
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
Sample run (not auto captured due to an issue with hidden canvas in 3D):
See also
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
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
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
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
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
Sample run:
prompt$ unicon -s reverse.icn -x
[1,2,3]
[3,2,1]
abc
cba
right¶
right(s1, i:1, s2:" ")
: type
right(s1, i, s2)
formats s1 to be a string of length i. If s1 has
more than i characters, it is truncated (from the left). If s1 has less
than i characters then it is padded to the left with as many copies of s2
needed to increase the length to i. Last copy of s2 is right side
truncated if necessary (“filler” will pad as “fill” for instance).
#
# right.icn, fill out a string to length, truncate or pad fill from left
#
procedure main()
s := "abcdefghij"
write(":", right(s, 5), ":")
write(":", right(s, 10), ":")
write(":", right(s, 20), ":")
write(":", right(s, 20, "filler"), ":")
end
Sample run:
prompt$ unicon -s right.icn -x
:fghij:
:abcdefghij:
: abcdefghij:
:fillerfillabcdefghij:
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
Sample run:
prompt$ unicon -s rmdir.icn -x
failed to remove dir.tt/
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
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
Sample run:
prompt$ unicon -s Rtab.icn -x
"st" 3
See also
rtod¶
rtod()
: real
rtod(radians)
given radians as a Real
value, produces the conversion
to degrees, as a Real
number.
#
# 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
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
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
Sample run:
prompt$ unicon -s save.icn -x
no ExecImage
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
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
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
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
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
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
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
Sample run:
prompt$ unicon -s setenv.icn -x
env value
See also
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
Sample run:
prompt$ unicon -s setgid.icn -x
&null
btiffin
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
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
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:
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
Sample run:
prompt$ unicon -s signal.icn -x
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
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
prompt$ unicon -s plot-function.icn -x sin
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
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
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]]
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
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
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
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
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
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 := 1572162119
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 := 1572162052
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
Sample run:
prompt$ unicon -s staticnames.icn -x
sv
See also
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
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
Sample run (skipped, you probably wouldn’t hear it anyway):
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
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(¤t)))
end
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
See also
cofail, fieldnames, globalnames, keyword, localnames, paramnames, staticnames, variable
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
Sample run (skipped, as this pattern function is a no-win trap):
symlink¶
symlink(s, s)
: ? [POSIX]
symlink(src, dst)
creates a symbolic (soft) file system link dst
pointing to src.
#
# symlink.icn, demonstrate the POSIX symlink() function
#
procedure main()
symlink("tt.src", "tt.dst")
end
Sample run:
prompt$ unicon -s symlink.icn -x
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
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
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
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
Sample run:
prompt$ unicon -s Tab.icn -x
"str" 4
See also
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
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
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
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
prompt$ unicon -s plot-function.icn -x tan
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
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
trailing1
leading0
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
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
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
Sample run:
prompt$ unicon -s trylock.icn -x
locked mtx
type¶
type(x)
: string
Returns the type of .
type(x)
returns a string representation of the type name of .
#
# 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
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
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
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
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
Sample run:
prompt$ unicon -s utime.icn -x
variable¶
variable(s, CE:¤t, 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
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
Sample run:
prompt$ unicon -s wait.icn -x
waiting 968007
no longer waiting 973505
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
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 : 29088
pointery : -22912
size : 40,40
windowlabel : WAttrib
Almost the same image as WFlush, but dx
and dy
are offset a bit on
the blue half circle.
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
Sample run:
prompt$ unicon -s WFlush.icn -x
See also
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
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
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
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
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
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
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:
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
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
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
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
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
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
Sample run:
prompt$ unicon -s WriteImage.icn -x
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
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
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
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
Sample run:
prompt$ unicon -s WSync.icn -x
Index | Previous: Reserved words | Next: Keywords