🗐 MACHINE2.E for Euphoria 3.1.1


                 Version 1.08, February/7/2018, by Shian Lee.


                             1. Introduction


 This library provides basic utilities, bitwise operators and machine level
 interface routines, for any platform.

 Version 1.08 includes the new routines: bsearch(), hash() and checksum().

 Tip: in Euphoria 3.1.1 you can use the builtin floor() function to speedup
      'for' loops or any other calculation, for example:

      for i = 1 to floor(15000001 / 2) do ...
       is much faster then:
      for i = 1 to 15000001 / 2 do ...

      floor() converts real numbers to integers which perform *much* faster.

 Note: yesterday (Jan/10/2017) I downloaded the full version of FreeDOS 1.2,
       and it was great to find out that Euphoria 3.1.1 is included with
       FreeDOS 1.2! My favorite programming language with my favorite OS...!


 Disclaimer
 ==========

 Use this library at your own risk. The author will not be responsible for
 any damage or data loss.

 This library is tested and optimized on FreeDOS 1.1 operating system. The
 code or the documentation might still contain errors or mistakes.


 In the descriptions below, to indicate what kind of object may be passed in
 and returned, the following prefixes are used:

 x     - a general object (atom or sequence)

 s     - a sequence

 a     - an atom

 i     - an integer

 fn    - an integer used as a file number

 st    - a string sequence, or single-character atom



                      2. Routines by Application Area


 2.1 Predefined Types
 ====================

 As well as declaring variables with these types, you can also call them just
 like ordinary functions, in order to test if a value is a certain type.

 boolean         - test if an object is a boolean integer

 dwords          - test if an object is a DWORD (32-bit) atom or sequence

 string          - test if an object is a string (a flat sequence)



 2.2 Sequence Manipulation
 =========================

 sum             - calculate the sum of a sequence

 flat            - flatten a sequence, don't add an end-of-string marker

 flatten         - flatten a sequence

 EMPTY           - an empty sequence ({})



 2.3 Searching and Sorting
 =========================

 bsearch         - find an object in a sorted sequence

 hash            - calculate the hash value of an object



 2.4 Math
 ========

 These routines can be applied to individual atoms or to sequences of values.

 abs             - return the absolute value of a number

 fix             - truncate the fractional part of a number

 sign            - return a value indicating the sign of a number, 0 is 0

 psign           - return a value indicating the sign of a number, 0 is 1

 nsign           - return a value indicating the sign of a number, 0 is -1

 zsign           - return a value indicating the sign of a number, 0 is TRUE



 2.5 Bitwise Operations
 ======================

 These routines treat numbers as collections of binary bits, and can be
 applied to individual atoms or to sequences of values. The arguments must be
 representable as 32-bit numbers, either signed or unsigned.

 eqv_bits        - perform logical EQV on corresponding bits

 imp_bits        - perform logical IMP on corresponding bits

 shl_bits        - return the result of shifting bits left

 shr_bits        - return the result of shifting bits right

 rol_bits        - return the result of rotating bits left

 ror_bits        - return the result of rotating bits right

 get_bit         - return the result of getting a bit value

 set_bit         - return the result of setting a bit value

 pack_bits       - convert a sequence of numbers to an integer

 unpack_bits     - convert an integer to a sequence of numbers

 FALSE           - the boolean value 0

 TRUE            - the boolean value 1



 2.6 File and Device I/O
 =======================

 putx            - output an object to a file or device

 get_xkey        - check for key pressed by the user, don't wait, return an
                   object

 wait_xkey       - wait for user to press a key, return an object

 pause           - suspend execution until user press a key

 clear_keyboard  - clear the keyboard buffer

 checksum        - calculate the checksum value of data



 2.7 Operating System
 ====================

 delay           - suspend execution for a period of time

 TIME_SIGN       - return a value indicating the sign of time()



 2.8 Machine Level Interface
 ===========================

 peek2s          - read 2-byte signed values from memory

 peek2u          - read 2-byte unsigned values from memory

 poke2           - write 2-byte values into memory

 bin             - convert an atom or sequence to binary string

 oct             - convert an atom or sequence to octal string

 dec             - convert an atom or sequence to decimal string

 hex             - convert an atom or sequence to hexadecimal string

 int             - convert a string or sequence to an atom

 signed          - convert an atom or sequence to signed number

 unsigned        - convert an atom or sequence to unsigned number

 range_per_bits  - return range of numbers per bits

 crash           - specify a message to be printed and crash your program



 2.9 Misc
 ========

 iif             - return a value according to specified condition




                   3. Alphabetical Listing of all Routines



 -----------------------------------<abs>------------------------------------

 Syntax:      include machine2.e
              x2 = abs(x1)

 Description: Return the absolute value of x1.

 Comments:    This function may be applied to an atom or to all elements of a
              sequence.

 Example:

              y = abs({0.5, -1.6, 9.99, -100, 0})
              -- y is {0.5, 1.6, 9.99, 100, 0}


 See Also:    fix, sign, unsigned
              Euphoria 3.1.1: floor


 -----------------------------------<bin>------------------------------------

 Syntax:      include machine2.e
              s = bin(x)

 Description: Convert an atom or sequence to binary string. Negative numbers
              are returned in two's complement, so -1 will return as
              "0b11111111111111111111111111111111" (#FFFFFFFF). The fractional
              part of x is truncated.

 Comments:    x must be representable as 32-bit number, either signed or
              unsigned.

 Example:

              s = bin(177)
              -- s is "0b10110001"

              s = bin({59, -59})
              -- s is {"0b111011", "0b11111111111111111111111111000101"}


 See Also:    oct, dec, hex, int, dwords
              Euphoria 3.1.1: int_to_bits, sprintf, and_bits


 ---------------------------------<boolean>----------------------------------

 Syntax:      include machine2.e
              i = boolean(x)

 Description: Return 1 if x is 0 (false) or 1 (true). Otherwise return 0.

 Comments:    This serves to define the boolean type. You can also call it
              like an ordinary function to determine if an object is a boolean.

 Example 1:

              boolean z
              z = 1


 Example 2:

              if boolean(y) then
                  puts(SCREEN, "y is 0 or 1")
              end if


 See Also:    dwords, string, FALSE, TRUE, iif
              Euphoria 3.1.1: integer, atom, sequence


 ---------------------------------<bsearch>----------------------------------

 Syntax:      include machine2.e
              i = bsearch(x, s)

 Description: Find x as an element of s. Sequence s must be sorted in ascending
              order. If successful, return the index of the element of s that
              matches. If unsuccessful return the index of the element of s
              that x would have, if inserted now, as a negative number.

 Comments:    bsearch() is using a fast binary search algorithm which is useful
              for finding a record in a large associative array, i.e. a map or
              a dictionary.

              i may or may not point to the first match if the element x
              appears more then once in s.

              bsearch() is faster then find() for lookup in a large sequence.

 Example 1:

              i = bsearch(100, {1, 2, 3, 4, 5, 6, 100, 105, 900})
              -- i is 7


 Example 2:

              s = {"ab", "dc", "qt"}

              i = bsearch("de", s)
              -- i is -3 -- i.e. index 3 if s was {"ab", "dc", "de", "qt"}


 Example 3:

              -- using bsearch() to get value from an associative array (a map)

              constant KEYS = 1, VALUES = 2
              s = {
                  {"basic", "c", "euphoria"}, -- sorted keys
                  {"simple", "hard", "rapid"} -- values
              }

              i = bsearch("euphoria", s[KEYS])
              -- i is 3 -- i.e. the value is s[VALUES][3], "rapid"


 See Also:    hash
              Euphoria 3.1.1: find, match, compare, sort


 --------------------------------<checksum>----------------------------------

 Syntax:      include machine2.e
              a = checksum(fn, i)

 Description: Calculate the checksum value of data from file or device fn.
              When i is 0 (false) a 16-bit integer is returned. When i is 1
              (true) a 32-bit atom is returned.

Comments:     Checksum is useful for verifying data integrity, i.e. for
              verifying that data is not corrupted or accidentally modified, by
              saving an old checksum value and later comparing it to a new
              checksum value of the same data.

              checksum() reads all data from a file or device until it reaches
              the end-of-file byte, control-Z.

              It's much faster to calculate a 16-bit checksum value, yet 32-bit
              checksum value is a bit more reliable, which means that there is
              a lower probability to return the same checksum value for a
              different data.

              checksum() is using the DJB hash algorithm by Daniel J. Bernstein.
              It's not suitable for cryptography.

 Example:

              fn = open("machine2.doc", "rb") -- open binary file for reading
              if fn = -1 then
                  puts(1, "\nCannot open the file for reading!\n")
              else
                  cs = checksum(fn, 0) -- calculate a 16-bit checksum value
                  close(fn)
                  printf(1, "\nThe checksum is: %.0f\n", cs)
              end if


 See Also:    hash


 -----------------------------<clear_keyboard>-------------------------------

 Syntax:      include machine2.e
              clear_keyboard()

 Description: Clear the keyboard buffer.

 Comments:    The operating system can hold a small number of key-hits in its
              keyboard buffer. clear_keyboard() is useful when you want to
              discard any old key-hits and let the user input a new key.

 Example:

              sleep(5) -- press a key -- any key-hit will be discarded

              clear_keyboard()
              puts(1, "\nPress 'y' to continue, or any other key to stop: ")
              key = wait_key()


 See Also:    wait_xkey, get_xkey, pause
              Euphoria 3.1.1: wait_key, get_key


 ----------------------------------<crash>-----------------------------------

 Syntax:      include machine2.e
              crash(s)

 Description: Crash your program. s is a string to be printed on the screen.

 Comments:    crash() is useful when there is no actual run-time error, but
              a programming bug or a critical hardware failure is trapped by
              your program and you must stop your program from running.
              Debugging information will still be stored in ex.err. You won't
              lose any information by doing this.

              s will be passed to crash_message(). You can leave s empty, "",
              if you don't want to print any message, or if you already called
              crash_message() before.

              if crash_routine() is specified then control is passed to that
              routine immediately after crash().

 Example:

              crash("Bad argument in function get_version().\n")


 See Also:    Euphoria 3.1.1: crash_message, crash_routine, crash_file, abort


 -----------------------------------<dec>------------------------------------

 Syntax:      include machine2.e
              s = dec(x)

 Description: Convert an atom or sequence to unsigned decimal string. Negative
              numbers are returned in two's complement, so -1 will return as
              "4294967295" (#FFFFFFFF). The fractional part of x is truncated.

 Comments:    x must be representable as 32-bit number, either signed or
              unsigned.

 Example:

              s = dec(177)
              -- s is "177"

              s = dec({59, -59})
              -- s is {"59", "4294967237"}


 See Also:    bin, oct, hex, int, dwords
              Euphoria 3.1.1: sprintf, value


 ----------------------------------<delay>-----------------------------------

 Syntax:      include machine2.e
              delay(a)

 Description: Suspend execution for a 0.01 seconds.

 Comments:    On delay your program will go into a busy loop for a 0.01
              seconds, during which time other processes may run, but they
              will compete with your process for the CPU.

              Under DOS32 you can improve the time() resolution by calling
              tick_rate(100). On WIN32 and Linux/FreeBSD the time() resolution
              is about 0.01 second.

 Example 1:

              tick_rate(100)            -- set 100 ticks/second for DOS32
              puts(1, "Waiting 0.5 second...\n")
              delay(50)                 -- 50 * 0.01 seconds is 0.5 second
              puts(1, "Done.\n")


 Example 2:

              tick_rate(100)            -- set 100 ticks/second for DOS32
              for char = 33 to 126 do
                 puts(1, char)
                 delay(char / 5)
              end for


 See Also:    pause, TIME_SIGN
              Euphoria 3.1.1: sleep, tick_rate, time


 ---------------------------------<dwords>-----------------------------------

 Syntax:      include machine2.e
              i = dwords(x)

 Description: Return 1 if x is an atom or a sequence of atoms in the range
              -2147483648 to +4294967295 (fractional numbers allowed).
              Otherwise return 0.

 Comments:    This serves to define the dwords type. You can also call it like
              an ordinary function to determine if an object is a dwords
              (DWORD is a 32-bit number, either signed or unsigned).

              Some functions, especially bitwise logical operators such as
              and_bits(), are limited to 32-bit numbers. You can find out if
              an argument is a 32-bit number by calling dwords().

 Example 1:

              dwords y, z
              y = -1
              z = {#FF000002, y}


 Example 2:

              x1 = -1.5
              x2 = #FFFFFFFF

              if dwords({x1, x2}) then
                  puts(1, "x1 and x2 are 32-bit numbers.")
              end if


 See Also:    string, boolean, fix, signed, unsigned, range_per_bits
              Euphoria 3.1.1: atom, sequence, floor


 ----------------------------------<EMPTY>-----------------------------------

 Syntax:      include machine2.e
              EMPTY

 Description: EMPTY ({}) has been defined as a global constant.

 Example:

              x = EMPTY  -- x is {}


 See Also:    flatten, FALSE
              Euphoria 3.1.1: sequence


 ---------------------------------<eqv_bits>---------------------------------

 Syntax:      include machine2.e
              x3 = eqv_bits(x1, x2)

 Description: Perform the logical EQV (Equivalence) operation on corresponding
              bits in x1 and x2. A bit in x3 will be 1 only if the
              corresponding bits in x1 and x2 are both 1 or both 0.

 Comments:    The arguments to this function may be atoms or sequences. The
              rules for operations on sequences apply.

              The arguments must be representable as 32-bit numbers, either
              signed or unsigned.

              If you intend to manipulate full 32-bit values, you should
              declare your variables as atom, rather than integer. Euphoria's
              integer type is limited to 31-bits.

              Results are treated as signed numbers. They will be negative when
              the highest-order bit is 1.

              To understand the binary representation of a number you should
              display it in binary or hexadecimal notation, with bin() or
              hex().

 Example 1:

              a = eqv_bits(#0F0F0000, #12345678)
              -- a is #E2C4A987


 Example 2:

              a = eqv_bits(#FF, {#123456, #876543, #2211})
              -- a is {#FFEDCB56, #FF789A43, #FFFFDD11}


 Example 3:

              a = eqv_bits(#FFFFFFFF, #FFFFFFFF)
              -- a is -1
              -- Note that #FFFFFFFF is a positive number,
              -- but the result of a bitwise logical operation is interpreted
              -- as a signed 32-bit number, so it's negative.


 See Also:    imp_bits, bin, hex, shl_bits
              Euphoria 3.1.1: and_bits, int_to_bits, sprintf


 -----------------------------------<FALSE>----------------------------------

 Syntax:      include machine2.e
              FALSE

 Description: FALSE (0) has been defined as a global constant.

 Example:

              x = FALSE  -- x is 0


 See Also:    TRUE, boolean, bin, EMPTY


 ------------------------------------<fix>-----------------------------------

 Syntax:      include machine2.e
              x2 = fix(x1)

 Description: Return the integer portion of x1. (Truncate the fractional part).

 Comments:    This function may be applied to an atom or to all elements of a
              sequence.

              fix() does not round the number.

 Example:

              y = fix({0.5, -1.6, 9.99, 100})
              -- y is {0, -1, 9, 100}


 See Also:    abs, sign
              Euphoria 3.1.1: floor, remainder, or_bits


 -----------------------------------<flat>-----------------------------------

 Syntax:      include machine2.e
              s2 = flat(s1)

 Description: Flatten the elements of sequence s1.

 Comments:    A new sequence is created without any (sub)sequences within it.

              flat() is faster and more efficient then flatten() and should be
              used instead of flatten() wherever you don't need to specify an
              end-of-string marker.

 Example:

              s = flat({})                 -- {}

              s = flat({99})               -- {99}

              s = flat({1,3,5,7})          -- {1,3,5,7}

              s = flat({{1,2,3}, {4,5,6}}) -- {1,2,3,4,5,6}

              s = flat({0,{1},2,{{3,4,{5.5,6}},{{7,8}}},9,10,{11}})
                -- {0,1,2,3,4,5.5,6,7,8,9,10,11}


 See Also:    flatten, string, EMPTY
              Euphoria 3.1.1: puts, sequence, append


 ---------------------------------<flatten>----------------------------------

 Syntax:      include machine2.e
              s2 = flatten(s1, st)

 Description: Flatten the elements of sequence s1. st is a single atom or a
              sequence of characters for an end-of-string marker.

 Comments:    A new sequence is created without any (sub)sequences within it.

 Example 1:

              s = flatten({1,3,5,7}, "")          -- {1,3,5,7}


 Example 2:

              s = flatten({{1,2,3}, {4,5,6}}, "") -- {1,2,3,4,5,6}

              s = flatten({{1,2,3}, {4,5,6}}, -1) -- {1,2,3,-1,4,5,6,-1}

              s = flatten({{1,2,3}, {4,5,6}}, "$!")
                -- {1,2,3,36,33,4,5,6,36,33}


 Example 3:

              s = flatten({99}, "")               -- {99}


 Example 4:

              s = flatten({}, "")                 -- {}


 Example 5:

              s = flatten({0,{1},2,{{3,4,{5.5,6}},{{7,8}}},9,10,{11}}, "")
                -- {0,1,2,3,4,5.5,6,7,8,9,10,11}

              s = flatten({0,{1},2,{{3,4,{5.5,6}},{{7,8}}},9,10,{11}}, -1)
                -- {0,-1,1,-1,2,-1,3,4,-1,5.5,6,-1,7,8,-1,9,10,-1,11,-1}


 See Also:    flat, string, sum, putx, EMPTY
              Euphoria 3.1.1: append, prepend, repeat, reverse


 ---------------------------------<get_bit>----------------------------------

 Syntax:      include machine2.e
              x2 = get_bit(x1, i)

 Description: Return the result of getting bit-i from x1. x2 will be 0 if
              bit-i is 0 (false). x2 will be non-zero if bit-i is 1 (true).
              i must be in the range 1 to 33.

 Comments:    x1 may be an atom or a sequence. The rules for operations on
              sequences apply.

              x1 must be representable as 32-bit numbers, either signed or
              unsigned.

              If you intend to manipulate full 32-bit values, you should
              declare your variables as atom, rather than integer. Euphoria's
              integer type is limited to 31-bits.

              Results are treated as signed numbers. They will be negative when
              the highest-order bit is 1.

 Example 1:

              a = get_bit(#FF123400, 32)
              -- a is -2147483648 i.e. #80000000 interpreted as negative number


 Example 2:

              a = get_bit({#123456, #876543, #2211}, 5)
              -- a is {#10, #0, #10}


 See Also:    set_bit, shr_bits, unpack_bits, bin, hex
              Euphoria 3.1.1: and_bits, or_bits, int_to_bits


 ---------------------------------<get_xkey>---------------------------------

 Syntax:      include machine2.e
              x = get_xkey()

 Description: Return the key that was pressed by the user, without waiting.
              Return -1 if no key was pressed. Special codes are returned for
              the function keys, arrow keys etc.

 Comments:    Because either a string-sequence or an atom might be returned,
              you should probably assign the result to a variable declared as
              object.

              The operating system can hold a small number of key-hits in its
              keyboard buffer. get_xkey() will return the next one from the
              buffer, or -1 if the buffer is empty.

              get_xkey() is useful for programs that run in Linux terminal or
              in any other environment that may return a sequence of atoms for
              a single key-hit (escape sequence, UTF-8 character, etc).

              Run the xkey.ex program to see what key code is generated for
              each key on your keyboard.

 See Also:    wait_xkey, clear_keyboard, pause
              Euphoria 3.1.1: get_key, wait_key, getc


 -----------------------------------<hash>-----------------------------------

 Syntax:      include machine2.e
              a2 = hash(x, a1)

 Description: Calculate the hash value of x. a2 will be a natural number in the
              range 1 to the absolute value of a1.

 Comments:    You can use hash() to create a hash table (also known as map,
              associative array, dictionary), and to calculate a checksum for
              verifying data integrity of an object.

              When creating a hash table, the hash value returned by hash() is
              used as an index of a record in the hash table, e.g. for
              a hash table of 1000 records: record_number = hash(x, 1000).
              See also the example program demo\hash.ex.

              It's much faster to calculate a hash value when a1 is a 16-bit
              integer, i.e. smaller then 65536. If a1 is fractional, e.g.
              1000.4, the calculation will be slower. If a1 is 0 your program
              will abort with a run-time error message.

              hash() is using the DJB algorithm by Daniel J. Bernstein, which
              is a short algorithm, yet fast and gives a good distribution for
              a hash table. hash() is not suitable for cryptography.

 Example:

              n = hash("ABcdefg", 1000) -- n is 498

              n = hash("BAcdefg", 1000) -- n is 74


              n = hash(-122, 1000) -- n is 452

              n = hash(-123, 1000) -- n is 451


              n = hash({1.5, 1.5}, #FFFF) -- n is 27346

              n = hash({1.5, 1.6}, #FFFF) -- n is 27346

              n = hash({1.6, 1.6}, #FFFF) -- n is 27349


              n = hash({1, {-19.4, 0}, 30}, #FFFFFFFF) -- n is 386733994

              n = hash({1, {-19.4, 0}, 30, {}}, #FFFFFFFF) -- n is 4172292562


 See Also:    checksum, bsearch
              Euphoria 3.1.1 example program: demo\hash.ex


 -----------------------------------<hex>------------------------------------

 Syntax:      include machine2.e
              s = hex(x)

 Description: Convert an atom or sequence to hexadecimal string. Negative
              numbers are returned in two's complement, so -1 will return as
              "#FFFFFFFF". The fractional part of x is truncated.

 Comments:    x must be representable as 32-bit number, either signed or
              unsigned.

 Example:

              s = hex(177)
              -- s is "#B1"

              s = hex({59, -59})
              -- s is {"#3B", "#FFFFFFC5"}


 See Also:    bin, oct, dec, int, dwords
              Euphoria 3.1.1: sprintf, value, and_bits


 -----------------------------------<iif>------------------------------------

 Syntax:      include machine2.e
              x3 = iif(a, x1, x2)

 Description: Test the condition a. If a is non-zero (true) then return x1.
              If a is 0 (false) then return x2.

 Comments:    A typical use for iif() is to assign a value to constant, or
              to make a long code shorter and more readable.

              iif() is slower then an if statement, and both arguments x1 and
              x2 are *always* evaluated, so it's not recommended to use iif()
              where speed and performances are your first priority.

 Example:

              constant SLASH = iif(platform() = LINUX, '/', '\\')


 See Also:    Euphoria 3.1.1: REFMAN.DOC, 2.5.3 if statement


 --------------------------------<imp_bits>----------------------------------

 Syntax:      include machine2.e
              x3 = imp_bits(x1, x2)

 Description: Perform the logical IMP (Implication) operation on corresponding
              bits in x1 and x2. A bit in x3 will be 1 only if the
              corresponding bits in x1 and x2 are both 1 or both 0, or when
              corresponding bits in x1 are 0 and in x2 are 1.

 Comments:    The arguments to this function may be atoms or sequences. The
              rules for operations on sequences apply.

              The arguments must be representable as 32-bit numbers, either
              signed or unsigned.

              If you intend to manipulate full 32-bit values, you should
              declare your variables as atom, rather than integer. Euphoria's
              integer type is limited to 31-bits.

              Results are treated as signed numbers. They will be negative when
              the highest-order bit is 1.


              A summery of bitwise logical operations, and a truth table:

                not_bits()     NOT - Bit-wise complement
                and_bits()     AND - Conjunction
                or_bits()      OR  - Disjunction (inclusive OR)
                xor_bits()     XOR - Exclusive OR
                eqv_bits()     EQV - Equivalence
                imp_bits()     IMP - Implication

                x1  x2  NOT(x1)  AND  OR   XOR  EQV  IMP
                --  --  -------  ---  ---  ---  ---  ---
                1   1   0        1    1    0    1    1
                1   0   0        0    1    1    0    0
                0   1   1        0    1    1    0    1
                0   0   1        0    0    0    1    1

 Example 1:

              a = imp_bits(#0F0F0000, #12345678)
              -- a is #F2F4FFFF


 Example 2:

              a = imp_bits(#FF, {#123456, #876543, #2211})
              -- a is {#FFFFFF56, #FFFFFF43, #FFFFFF11}


 See Also:    eqv_bits, bin, hex, shl_bits
              Euphoria 3.1.1: and_bits, int_to_bits, sprintf


 -----------------------------------<int>------------------------------------

 Syntax:      include machine2.e
              x = int(s)

 Description: Convert a string or sequence to unsigned atom. s may be the
              result of a previous call to bin(), oct(), dec() or hex(); or a
              string representation of an unsigned atom.

              s must start with a prefix (except for decimal representation);
              possible prefixes are:

              "0b" - binary representation (digits 0-1)
              "0o" - octal representation (digits 0-7)
              "0x" or "#" - hexadecimal representation (digits 0-9,A-F)

 Comments:    Numbers returned by int() can be larger then 32-bits.

 Example:

              a = int("177")
              -- a is 177

              a = int({"59", "-59", {" 7", "7z"}})
              -- a is {59, 0, {0, 0}} -- invalid characters return 0

              a = int("0b11110000")
              -- a is 240

              a = int("0o123456")
              -- a is 42798

              a = int({"0xFF35E", "#FF35E"})
              -- a is {1045342, 1045342}

              a = int("#1FFFFFFFF")
              -- a is 8589934591 -- a is larger then 32-bit


 See Also:    bin, oct, dec, hex, dwords, signed
              Euphoria 3.1.1: value, sprintf, bits_to_int


 ---------------------------------<nsign>------------------------------------

 Syntax:      include machine2.e
              x2 = nsign(x1)

 Description: Return a value indicating the sign of x1 (1 if x1 is positive,
              -1 if it is zero, or -1 if it is negative).

 Comments:    This function may be applied to an atom or to all elements of a
              sequence.

 Example:

              y = nsign({0.5, -1.6, 9.99, -100, 0})
              -- y is {1, -1, 1, -1, -1}


 See Also:    sign, psign, zsign, abs, unsigned, signed


 -----------------------------------<oct>------------------------------------

 Syntax:      include machine2.e
              s = oct(x)

 Description: Convert an atom or sequence to octal string. Negative numbers
              are returned in two's complement, so -1 will return as
              "0o37777777777" (#FFFFFFFF). The fractional part of x is
              truncated.

 Comments:    x must be representable as 32-bit number, either signed or
              unsigned.

 Example:

              s = oct(177)
              -- s is "0o261"

              s = oct({59, -59})
              -- s is {"0o73", "0o37777777705"}


 See Also:    bin, dec, hex, int, dwords
              Euphoria 3.1.1: sprintf


 -------------------------------<pack_bits>----------------------------------

 Syntax:      include machine2.e
              a = pack_bits(s1, s2)

 Description: Convert a sequence of numbers s1 to an integer. s2 defines the
              size (in bits) for packing each number in s1, respectively.
              s2 values must be in the range 0 to 32; You can also use negative
              values (0 to -32) to unpack (and pack) signed numbers. The
              (absolute) sum of s2 must be in the range 0 to 32.

 Comments:    s1 must be representable as 32-bit numbers, either signed or
              unsigned.

              If you intend to manipulate full 32-bit values, you should
              declare your variables as atom, rather than integer. Euphoria's
              integer type is limited to 31-bits.

              Result is treated as signed number. It will be negative when the
              highest-order bit is 1.

              pack_bits()/unpack_bits() are useful for packing small numbers
              into integer. e.g. for packing date() sequence into integer.

              range_per_bits() will tell you how many bits are neccessary for
              packing a signed or unsigned number.

 Example 1:

              ints = {#FA3, #8, #12}
              bits = {  12,  4,   8}    -- 12-bits/#FA3, 4-bits/#8, 8-bits/#12

              i = pack_bits(ints, bits) -- i is 16398354 (#FA3812)
              s = unpack_bits(i, bits)  -- s is {4003, 8, 18}; {#FA3, #8, #12}


 Example 2:

              ints = {#40000000, #1}
              bits = {       31,  1}    -- 31-bits/#40000000, 1-bits/#1

              a = pack_bits(ints, bits) -- a is -2147483647 (#80000001)
              s = unpack_bits(a, bits)  -- s is {1073741824,1};{#40000000, #1}


 Example 3:

              ints = {-2000, 8, 18, -15}
              bits = {  -12, 4, -8,  -5} -- 12-bits/-2000 (signed),
                                         --  4-bits/8     (unsigned),
                                         --  8-bits/18    (signed),
                                         --  5-bits/-15   (signed)

              i = pack_bits(ints, bits)  -- i is 274793041
              s = unpack_bits(i, bits)   -- s is {-2000, 8, 18, -15}


 Example 4:

              ints = {-1073741824, 1}
              bits = {      -31,  -1}    -- 31-bits/-1073741824 (signed),
                                         --  1-bits/1 (signed)

              a = pack_bits(ints, bits)  -- a is -2147483647 (#80000001)
              s = unpack_bits(a, bits)   -- s is {-1073741824, -1}
                                         -- (signed range for 1-bits is -1..0)


 Example 5:

              -- pack current date() into 32-bit atom

              ints = date()         -- {year,month,day,hour,minute,second}
              ints = ints[1..6]     -- ints is {117,1,7,15,8,27} for demo

              bits = {7,4,5,5,6,5}  -- 7-bits/year, 4-bits/month, 5-bits/day,
                                    -- 5-bits/hour, 6-bits/minute, 5-bits/sec

              ints[6] /= 2          -- 2-second increments (0-29) saves 1 bit

              a = pack_bits(ints, bits) -- a is -366511859 (#EA27790D)
              s = unpack_bits(a, bits)

              s[6] *= 2             -- (2-second increments)

                -- s is {117,1,7,15,8,26} -- (year is since 1900: 1900+117)


 See Also:    unpack_bits, range_per_bits, shl_bits, bin, hex, sum
              Euphoria 3.1.1: and_bits, int_to_bits, bits_to_int


 ----------------------------------<pause>-----------------------------------

 Syntax:      include machine2.e
              pause()

 Description: Suspend execution until user press a key.

 Comments:    On multi-tasking systems like Windows or Linux/FreeBSD, pause()
              lets the operating system do other useful work while your
              program is waiting for the user to press a key.

 Example 1:

              puts(1, "Press few keys fast...\n\n")
              sleep(2)

              -- pause() clears previous keys pressed by the user
              puts(1, "Program paused, press any key to continue...\n\n")
              pause()
              puts(1, "Program continue.\n")


 Example 2:

              -- pause() is useful for debugging a program
              for row = 1 to 200 do
                 printf(1, "This is line number %d\n", row)
                 if remainder(row, 20) = 0 then
                    pause()     -- pause to see what's on the screen...
                 end if
              end for


 See Also:    delay
              Euphoria 3.1.1: wait_key, sleep


 ---------------------------------<peek2s>-----------------------------------

 Syntax:      include machine2.e
              a2 = peek2s(a1)
              or ...
              s = peek2s({a1, i})

 Description: Return a 2-byte (16-bit) signed value in the range -32768 to
              +32767 from machine address a1, or return a sequence containing
              i consecutive 2-byte signed values starting at address a1 in
              memory.

 Comments:    Since machine addresses are 32-bit numbers, they can be too large
              for Euphoria's integer type. Variables that hold an address
              should therefore be declared as atoms.

              It is faster to read several 2-byte values at once using the
              second form of peek2s() than it is to read one 2-byte value at a
              time in a loop.

              Remember that peek2s() takes just one argument, which in the
              second form is actually a 2-element sequence.

              peek2s() is not as fast as peek() or peek4s().

 Example:     The following are equivalent:


              -- method 1
              s = {peek2s(100), peek2s(102), peek2s(104), peek2s(106)}

              -- method 2
              s = peek2s({100, 4})


 See Also:    peek2u, poke2
              Euphoria 3.1.1: peek4s, peek, poke4


 ---------------------------------<peek2u>-----------------------------------

 Syntax:      include machine2.e
              a2 = peek2u(a1)
              or ...
              s = peek2u({a1, i})

 Description: Return a 2-byte (16-bit) unsigned value in the range 0 to
              65535 from machine address a1, or return a sequence containing
              i consecutive 2-byte unsigned values starting at address a1 in
              memory.

 Comments:    Since machine addresses are 32-bit numbers, they can be too large
              for Euphoria's integer type. Variables that hold an address
              should therefore be declared as atoms.

              It is faster to read several 2-byte values at once using the
              second form of peek2u() than it is to read one 2-byte value at a
              time in a loop.

              Remember that peek2u() takes just one argument, which in the
              second form is actually a 2-element sequence.

              peek2u() is not as fast as peek() or peek4u().

 Example:     The following are equivalent:


              -- method 1
              s = {peek2u(100), peek2u(102), peek2u(104), peek2u(106)}

              -- method 2
              s = peek2u({100, 4})


 See Also:    peek2s, poke2
              Euphoria 3.1.1: peek4u, peek, poke4


 ----------------------------------<poke2>-----------------------------------

 Syntax:      include machine2.e
              poke2(a, x)

 Description: If x is an atom, write a 2-byte (16-bit) value to memory address
              a.

              If x is a sequence, write a sequence of 2-byte values to
              consecutive memory locations starting at location a.

 Comments:    The value or values to be stored must not exceed 16-bits in size.


              It is faster to write several 2-byte values at once by poking a
              sequence of values, than it is to write one 2-byte value at a
              time in a loop.

              The 2-byte values to be stored can be negative or positive. You
              can read them back with either peek2s() or peek2u().

              poke2() is not as fast as poke() or poke4().

 Example:

              a = allocate(100)   -- allocate 100 bytes in memory

              -- poke one 2-byte value at a time:
              poke2(a, 13017)
              poke2(a+2, #FF00)
              poke2(a+4, -12345)

              -- poke 3 2-byte values at once:
              poke2(a, {13017, #FF00, -12345})


 See Also:    peek2s, peek2u
              Euphoria 3.1.1: poke, poke4, peek, peek4u, peek4s


 ----------------------------------<psign>-----------------------------------

 Syntax:      include machine2.e
              x2 = psign(x1)

 Description: Return a value indicating the sign of x1 (1 if x1 is positive,
              1 if it is zero, or -1 if it is negative).

 Comments:    This function may be applied to an atom or to all elements of a
              sequence.

 Example:

              y = psign({0.5, -1.6, 9.99, -100, 0})
              -- y is {1, -1, 1, -1, 1}


 See Also:    sign, nsign, zsign, abs, unsigned, signed


 -----------------------------------<putx>-----------------------------------

 Syntax:      include machine2.e
              putx(fn, x, st)

 Description: This is just a shorthand way of saying: puts(fn, flatten(x, st))
              - i.e. output, to file or device fn, object x.
              st is a single byte (atom) or a sequence of bytes for an
              end-of-string marker (Typically a new-line character, '\n').

 Comments:    putx() is not as fast and efficient as puts().

 Example 1:

              putx(1, {"First name:", " Last name:"}, '\n')


 Example 2:

              putx(out, 'A', "")  -- the single byte 65 will be sent to out


 Example 3:

              x = {{"http",':','/','/'},"www",'.',{{"RapidEuphoria"},'.',"com"}}
              putx(1, x, "")


 Example 4:

              x = bin({#F, #FF, #FFFF, #FFFFFFFF})
              putx(1, x, ",\n")


 See Also:    get_xkey, pause, flat, flatten
              Euphoria 3.1.1: puts, print, printf, gets, open


 ---------------------------<range_per_bits>---------------------------------

 Syntax:      include machine2.e
              s = range_per_bits(x)

 Description: Return a sequence of values describing the range of numbers per
              x bits:
              {minimum value of a signed number,
              maximum value of a signed number,
              maximum value of an unsigned number}

              x must be in the range 0 to 32.

 Comments:    This routine makes it easy for you to find out how many bits
              are neccessary for packing a signed or an unsigned number with
              pack_bits().

              The minimum value of an unsigned number is always 0.

 Example 1:

              s = range_per_bits(32)
              -- s is {-2147483648, 2147483647, 4294967295}
              --  i.e. {-#80000000, #7FFFFFFF, #FFFFFFFF}


 Example 2:

              s = range_per_bits({4, 8, 16, 31})
              -- s is {
              --        {-8, 7, 15},
              --        {-128, 127, 255},
              --        {-32768, 32767, 65535},
              --        {-1073741824, 1073741823, 2147483647}
              --      }


 See Also:    signed, unsigned, pack_bits, peek2s
              Euphoria 3.1.1: integer, peek4s


 --------------------------------<rol_bits>----------------------------------

 Syntax:      include machine2.e
              x2 = rol_bits(x1, i)

 Description: Return the result of rotating the bits of x1 left i number of
              bits. i must be in the range 0 to 32.

 Comments:    x1 may be an atom or a sequence. The rules for operations on
              sequences apply.

              x1 must be representable as 32-bit numbers, either signed or
              unsigned.

              If you intend to manipulate full 32-bit values, you should
              declare your variables as atom, rather than integer. Euphoria's
              integer type is limited to 31-bits.

              Results are treated as signed numbers. They will be negative when
              the highest-order bit is 1.

 Example 1:

              a = rol_bits(#FF123400, 8)
              -- a is 305398015 (i.e. #123400FF interpreted as positive number)


 Example 2:

              a = rol_bits({#123456, #876543, #2211}, 16)
              -- a is {#34560012, #65430087, #22110000}


 See Also:    ror_bits, shl_bits, set_bit, pack_bits, bin, hex
              Euphoria 3.1.1: and_bits, int_to_bits, bits_to_int


 -------------------------------<ror_bits>-----------------------------------

 Syntax:      include machine2.e
              x2 = ror_bits(x1, i)

 Description: Return the result of rotating the bits of x1 right i number of
              bits. i must be in the range 0 to 32.

 Comments:    x1 may be an atom or a sequence. The rules for operations on
              sequences apply.

              x1 must be representable as 32-bit numbers, either signed or
              unsigned.

              If you intend to manipulate full 32-bit values, you should
              declare your variables as atom, rather than integer. Euphoria's
              integer type is limited to 31-bits.

              Results are treated as signed numbers. They will be negative when
              the highest-order bit is 1.

 Example 1:

              a = ror_bits(#FF123400, 8)
              -- a is 16716340 (i.e. #FF1234 interpreted as a positive number)


 Example 2:

              a = ror_bits({#123456, #876543, #2211}, 24)
              -- a is {#12345600, #87654300, #221100}


 See Also:    rol_bits, shr_bits, set_bit, pack_bits, bin, hex
              Euphoria 3.1.1: and_bits, int_to_bits, bits_to_int


 --------------------------------<set_bit>-----------------------------------

 Syntax:      include machine2.e
              x2 = set_bit(x1, i1, i2)

 Description: Return the result of setting bit-i1 in x1 to value i2. If i2 is
              0 bit-i1 will be 0 (false). If i2 is non-zero bit-i1 will be 1
              (true). i1 must be in the range 1 to 33.

 Comments:    x1 may be an atom or a sequence. The rules for operations on
              sequences apply.

              x1 must be representable as 32-bit numbers, either signed or
              unsigned.

              If you intend to manipulate full 32-bit values, you should
              declare your variables as atom, rather than integer. Euphoria's
              integer type is limited to 31-bits.

              Results are treated as signed numbers. They will be negative when
              the highest-order bit is 1.

 Example 1:

              a = set_bit(#FF123400, 2, 1)
              -- a is -15584254 (i.e. #FF123402 interpreted as negative number)


 Example 2:

              a = set_bit({#123456, #876543, #2211}, 5, 0)
              -- a is {#123446, #876543, #2201}


 See Also:    get_bit, shl_bits, pack_bits, bin, hex
              Euphoria 3.1.1: and_bits, or_bits, int_to_bits


 --------------------------------<shl_bits>----------------------------------

 Syntax:      include machine2.e
              x2 = shl_bits(x1, i)

 Description: Return the result of shifting the bits of x1 left i number of
              bits. i must be in the range 0 to 32.

 Comments:    x1 may be an atom or a sequence. The rules for operations on
              sequences apply.

              x1 must be representable as 32-bit numbers, either signed or
              unsigned.

              If you intend to manipulate full 32-bit values, you should
              declare your variables as atom, rather than integer. Euphoria's
              integer type is limited to 31-bits.

              Results are treated as signed numbers. They will be negative when
              the highest-order bit is 1.

 Example 1:

              a = shl_bits(#0FFF1234, 8)
              -- a is -15584256 (i.e. #FF123400 interpreted as negative number)


 Example 2:

              a = shl_bits({#123456, #876543, #2211}, 16)
              -- a is {#34560000, #65430000, #22110000}


 See Also:    shr_bits, rol_bits, set_bit, pack_bits, bin, hex
              Euphoria 3.1.1: and_bits, int_to_bits, bits_to_int


 --------------------------------<shr_bits>----------------------------------

 Syntax:      include machine2.e
              x2 = shr_bits(x1, i)

 Description: Return the result of shifting the bits of x1 right i number of
              bits. i must be in the range 0 to 32.

 Comments:    x1 may be an atom or a sequence. The rules for operations on
              sequences apply.

              x1 must be representable as 32-bit numbers, either signed or
              unsigned.

              If you intend to manipulate full 32-bit values, you should
              declare your variables as atom, rather than integer. Euphoria's
              integer type is limited to 31-bits.

              Results are treated as signed numbers. They will be negative when
              the highest-order bit is 1.

 Example 1:

              a = shr_bits(#FF123400, 8)
              -- a is 16716340 (i.e. #FF1234 interpreted as a positive number)


 Example 2:

              a = shr_bits({#123456, #876543, #2211}, 16)
              -- a is {#12, #87, #0}


 See Also:    shl_bits, ror_bits, set_bit, pack_bits, bin, hex
              Euphoria 3.1.1: and_bits, int_to_bits, bits_to_int


 -----------------------------------<sign>-----------------------------------

 Syntax:      include machine2.e
              x2 = sign(x1)

 Description: Return a value indicating the sign of x1 (1 if x1 is positive,
              0 if it is zero, or -1 if it is negative).

 Comments:    This function may be applied to an atom or to all elements of a
              sequence.

 Example:

              y = sign({0.5, -1.6, 9.99, -100, 0})
              -- y is {1, -1, 1, -1, 0}


 See Also:    psign, nsign, zsign, abs, unsigned, signed
              Euphoria 3.1.1: floor, and_bits


 ---------------------------------<signed>-----------------------------------

 Syntax:      include machine2.e
              x2 = signed(x1, i)

 Description: Return the low-order i bits of x1 as a signed number. i must be
              in the range 0 to 32. The fractional part of x1 is truncated.
              Positive numbers are returned in two's complement, so #FFFFFFFF
              will return as -1.

 Comments:    x1 may be an atom or a sequence. The rules for operations on
              sequences apply.

              x1 must be representable as 32-bit numbers, either signed or
              unsigned.

 Example 1:

              y = signed({0.5, 4294967295, 9.99, -100.6, 0, -#FF}, 32)
              -- y is {0, -1, 9, -100, 0, -255}


 Example 2:

              x = {#FFFFFFFF, #FFFF, #FF, #F}

              y = signed(x, 32)  -- y is {-1, 65535, 255, 15}

              y = signed(x, 16)  -- y is {-1,    -1, 255, 15}

              y = signed(x,  8)  -- y is {-1,    -1,  -1, 15}


 See Also:    unsigned, unpack_bits, range_per_bits, fix, sign, peek2s
              Euphoria 3.1.1: peek4s


 ---------------------------------<string>-----------------------------------

 Syntax:      include machine2.e
              i = string(x)

 Description: Return 1 if x is a string, i.e. a flat sequence without any
              (sub)sequences within it. Otherwise return 0.

 Comments:    This serves to define the string type. You can also call it like
              an ordinary function to determine if an object is a string.

 Example 1:

              string z
              z = {1, 2.5, 3}


 Example 2:

              z = {65.1, 66.9, 67}

              if string(z) then
                  puts(SCREEN, z & " is a string!")
              end if


 Example 3:

              i = string({1, 2.5, 3, ""})  -- i is 0


 See Also:    dwords, boolean, flatten, EMPTY
              Euphoria 3.1.1: sequence, atom


 -----------------------------------<sum>------------------------------------

 Syntax:      include machine2.e
              a = sum(s)

 Description: Return the sum of s. s must be a sequence. An error will occur
              if s is an atom.

 Example 1:

              a = sum({{1,2}, {3,4}, {5,6}})   -- a is 21 (i.e. 1+2+3+4+5+6)


 Example 2:

              a = sum("")   -- a is 0


 Example 3:

              a = sum("12")   -- a is 99 (i.e. ASCII-49 + ASCII-50)


 See Also:    flatten, EMPTY, unpack_bits
              Euphoria 3.1.1: sequence, length


 -------------------------------<TIME_SIGN>----------------------------------

 Syntax:      include machine2.e
              TIME_SIGN

 Description: TIME_SIGN (-1 or 1) has been defined as a global constant.

 Comments:    On some machines, time() can return a negative number. TIME_SIGN
              is -1 if time() return a negative number, or 1 if time() return
              a positive number.

 Example:

              x = TIME_SIGN  -- x is -1 or 1 (depends on your machine)


 See Also:    delay
              Euphoria 3.1.1: time()


 ----------------------------------<TRUE>------------------------------------

 Syntax:      include machine2.e
              TRUE

 Description: TRUE (1) has been defined as a global constant.

 Example:

              x = TRUE  -- x is 1


 See Also:    FALSE, boolean


 ------------------------------<unpack_bits>---------------------------------

 Syntax:      include machine2.e
              s2 = unpack_bits(a, s1)

 Description: Convert integer a to sequence of numbers s2. s1 defines the size
              (in bits) for unpacking each number from a. s1 values must be in
              the range 0 to 32; You can also use negative values (0 to -32)
              to unpack signed numbers. The (absolute) sum of s1 must be in the
              range 0 to 32.

 Comments:    a must be representable as 32-bit number, either signed or
              unsigned.

              If you intend to manipulate full 32-bit values, you should
              declare your variables as atom, rather than integer. Euphoria's
              integer type is limited to 31-bits.

              pack_bits()/unpack_bits() are useful for packing small numbers
              into integer. e.g. for packing date() sequence into integer.

 Example:

              ints = {-2000, 8, 18, -15}
              bits = {  -12, 4, -8,  -5} -- 12-bits/-2000 (signed),
                                         --  4-bits/8     (unsigned),
                                         --  8-bits/18    (signed),
                                         --  5-bits/-15   (signed)

              i = pack_bits(ints, bits)  -- i is 274793041
              s = unpack_bits(i, bits)   -- s is {-2000, 8, 18, -15}


 Examples:    See pack_bits() for more examples.


 See Also:    pack_bits, signed, unsigned, shr_bits, range_per_bits, bin,
              hex, sum
              Euphoria 3.1.1: and_bits, int_to_bits, bits_to_int


 -------------------------------<unsigned>-----------------------------------

 Syntax:      include machine2.e
              x2 = unsigned(x1, i)

 Description: Return the low-order i bits of x1 as an unsigned number. i must
              be in the range 0 to 32. The fractional part of x1 is truncated.
              Negative numbers are returned in two's complement, so -1 will
              return as 4294967295.

 Comments:    x1 may be an atom or a sequence. The rules for operations on
              sequences apply.

              x1 must be representable as 32-bit numbers, either signed or
              unsigned.

 Example 1:

              y = unsigned({0.5, -1, 9.99, -100.6, 0, -#FF}, 32)
              -- y is {0, 4294967295, 9, 4294967196, 0, 4294967041}


 Example 2:

              x = {#FFFFFFFF, #FFFF, #FF, #F}

              y = unsigned(x, 32)  -- y is {4294967295, 65535, 255, 15}

              y = unsigned(x, 16)  -- y is {     65535, 65535, 255, 15}

              y = unsigned(x,  8)  -- y is {       255,   255, 255, 15}


 See Also:    signed, unpack_bits, range_per_bits, fix, sign, peek2u
              Euphoria 3.1.1: int_to_bits, peek4u


 --------------------------------<wait_xkey>---------------------------------

 Syntax:      include machine2.e
              x = wait_xkey()

 Description: Return the next key pressed by the user. Don't return until a key
              is pressed.

 Comments:    Because either a string-sequence or an atom might be returned,
              you should probably assign the result to a variable declared as
              object.

              You could achieve the same result using get_xkey() as follows:

                  object k
                  while 1 do
                      k = get_xkey()
                      if not equal(k, -1) then
                          exit
                      end if
                  end while

              However, on multi-tasking systems like Windows or Linux/FreeBSD,
              this "busy waiting" would tend to slow the system down.
              wait_xkey() lets the operating system do other useful work while
              your program is waiting for the user to press a key.

              wait_xkey() is useful for programs that run in Linux terminal or
              in any other environment that may return a sequence of atoms for
              a single key-hit (escape sequence, UTF-8 character, etc).

 See Also:    get_xkey, clear_keyboard, pause, delay
              Euphoria 3.1.1: wait_key, get_key, getc, sleep


 ----------------------------------<zsign>-----------------------------------

 Syntax:      include machine2.e
              x2 = zsign(x1)

 Description: Return a value indicating the sign of x1 (0 if x1 is positive,
              1 if it is zero, or 0 if it is negative).

 Comments:    This function may be applied to an atom or to all elements of a
              sequence.

 Example:

              y = zsign({0.5, -1.6, 9.99, -100, 0})
              -- y is {0, 0, 0, 0, 1}


 See Also:    sign, psign, nsign, abs, unsigned, signed