Plasma GitLab Archive
Projects Blog Knowledge

########################################################################
# Copyright (C) 2003-2007 Jason Hickey and Mojave Group
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this file, to deal in the File without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the File, and to permit persons to whom the File
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the File.
#
# THE FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# FILE OR THE USE OR OTHER DEALINGS IN THE FILE.

########################################################################
# This file defines the Pervasives module--the standard module
# open to every program.  This is a bootstrap file.  The syntax
# here is mainly normal, but it is assumed that the basic classes
# are empty at this point.  You never need to assume this again.
#
class Pervasives

########################################################################
# Common variables and utilities
#
public. =
    declare BUILD_SUMMARY
    declare CWD
    declare FS
    declare GLOB_ALLOW
    declare GLOB_IGNORE
    declare GLOB_OPTIONS
    declare NF
    declare OMAKEPATH
    declare PATH
    declare RS
    declare STDLIB
    declare STDROOT
    declare TARGETS
    declare prompt
    declare EMPTY
    declare EMPTY_ARRAY

const.EMPTY =
const.EMPTY_ARRAY[] =
const.TAB = $'	'
const.false = false
const.true = true

shell-success(argv) =
    try
        value $(equal $(shell-code $(argv)), 0)
    default
        value $(not true)

shell-success-null(argv) =
   # XXX: HACK: Is there a portable /dev/null?
   #            Perhaps we should fix http://bugzilla.metaprl.org/show_bug.cgi?id=619
   #            and use a string out channel?
   tmp = $(tmpfile omake.shell-success-null)
   stdout = $(fopen $(tmp), w)
   stderr = $(stdout)
   res = $(shell-success $(argv))
   close($(stdout))
   rm(-f $(tmp))
   return $(res)

last(array) =
   return $(nth $(sub $(length $(array)), 1), $(array))

Bool(v) =
   value $(not $(not $v))

nonempty(l) =
    gt($(length $l), 0)

# GNU Make - like join function
join(l1, l2) =
    result[] =
    while $(and $(nonempty $(l1)), $(nonempty $(l2)))
        x = $(nth 0, $(l1))
        y = $(nth 0, $(l2))
        l1 = $(nth-tl 1, $(l1))
        l2 = $(nth-tl 1, $(l2))
        result[] += $x$y
    # From GNU Make docs: If one argument has more words that the other,
    # the extra words are copied unchanged into the result
    result[] += $(l1)
    result[] += $(l2)
    value $(result)

# Documented in src/builtin/omake_builtin_sys.ml

xterm-escape(s) =
    if $(xterm-escape-begin)
        value $(xterm-escape-begin)$s$(xterm-escape-end)
    else
        value $(EMPTY)

prompt-invisible(s) =
    value $(prompt-invisible-begin)$s$(prompt-invisible-end)

########################################################################
# \begin{doc}
#
# \chapter{The standard objects}
# \label{chapter:pervasives}
# \cutname{omake-pervasives.html}
#
# \verb+Pervasives+ defines the objects that are defined in all
# programs.  The following objects are defined.
#
# \section{Pervasives objects}
#
# \obj{Object}
#
# Parent objects: none.
#
# The \verb+Object+ object is the root object.
# Every class is a subclass of \verb+Object+.
#
# It provides the following fields:
#
# \begin{itemize}
# \item \verb+$(o.object-length)+: the number of fields and methods in the object.
# \item \verb+$(o.object-mem <var>)+: returns \verb+true+ iff the \verb+<var>+ is a field
#    or method of the object.
# \item \verb+$(o.object-add <var>, <value>)+: adds the field to the object,
#    returning a new object.
# \item \verb+$(o.object-find <var>)+: fetches the field or method from the object;
#    it is equivalent to \verb+$(o.<var>)+, but the variable can be non-constant.
# \item \verb+$(o.object-map <fun>)+: maps a function over the object.  The function
#    should take two arguments; the first is a field name, the second is the
#    value of that field.  The result is a new object constructed from the
#    values returned by the function.
# \item \verb+o.object-foreach+: the \verb+object-foreach+ form is equivalent to \verb+object-map+,
#    but with altered syntax.
#
#    \begin{verbatim}
#    o.object-foreach(<var1>, <var2>) =>
#       <body>
#    \end{verbatim}
#
#    For example, the following function prints all the fields of an
#    object \verb+o+.
#
#    \begin{verbatim}
#    PrintObject(o) =
#       o.object-foreach(v, x) =>
#          println($(v) = $(x))
#    \end{verbatim}
#
#    The \verb+export+ form is valid in a \verb+object-foreach+ body.  The following
#    function collects just the field names of an object.
#
#    \begin{verbatim}
#    FieldNames(o) =
#       names[] =
#       o.object-foreach(v, x) =>
#          names[] += $(v)
#          export
#       return $(names)
#    \end{verbatim}
# \end{itemize}
#
# \end{doc}
#
Object. +=
   class Object

   object-length() =
      return $(obj-length $(this))

   object-mem(v) =
      return $(obj-mem $(this), $(v))

   object-add(v, x) =
      return $(obj-add $(this), $(v), $(x))

   object-find(v) =
      return $(obj-find $(this), $(v))

   object-map(f) =
      return $(obj-map $(this), $(f))

   curry.object-foreach() =
      private.THIS = $(this)
      g(f) =
         export
         obj-map($(THIS), $(f))

   instanceof(v) =
      return $(obj-instanceof $(this), $(v))

public.Object = $(this.Object)

#
# The runtime doesn't know to include the Object module, so do it now.
#
extends $(Object)

#
# \begin{doc}
# \obj{Map}
#
# Parent objects: \verb+Object+.
#
# A \verb+Map+ object is a dictionary from values to values.  The \verb+<key>+
# values are restricted to simple values: integers, floating-point numbers,
# strings, files, directories, and arrays of simple values.
#
# The Map object provides the following methods.
#
# \begin{itemize}
# \item \verb+$(o.length)+: the number of items in the map.
# \item \verb+$(o.mem <key>)+: returns \verb+true+ iff the \verb+<key>+ is defined
#    in the map.
# \item \verb+$(o.add <key>, <value>)+: adds the field to the map,
#    returning a new map.
# \item \verb+$(o.find <key>)+: fetches the field from the map.
# \item \verb+$(o.keys)+: fetches an array of all the keys in the map, in alphabetical order.
# \item \verb+$(o.values)+: fetches an array of all the values in the map,
#    in the alphabetical order of the corresponding keys.
# \item \verb+$(o.map <fun>)+: maps a function over the map.  The function
#    should take two arguments; the first is a field name, the second is the
#    value of that field.  The result is a new object constructed from the
#    values returned by the function.
# \item \verb+o.foreach+: the \verb+foreach+ form is equivalent to \verb+map+,
#    but with altered syntax.
#
#    \begin{verbatim}
#    o.foreach(<var1>, <var2>) =>
#       <body>
#    \end{verbatim}
#
#    For example, the following function prints all the fields of a
#    map \verb+o+.
#
#    \begin{verbatim}
#    PrintMap(o) =
#       o.foreach(v, x) =>
#          println($(v) = $(x))
#    \end{verbatim}
#
#    The \verb+export+ form is valid in a \verb+foreach+ body.  The following
#    function reimplements the \verb+key+ method.
#
#    \begin{verbatim}
#    FieldNames(o) =
#       names =
#       o.foreach(v, x) =>
#          names += $(v)
#          export
#       return $(names)
#    \end{verbatim}
# \end{itemize}
#
# There is also simpler syntax when the key is a string.  The table can be
# defined using definitions with the form \verb+$|key|+
# (the number of pipe symbols \verb+|+ is allowed to vary).
#
# \begin{verbatim}
#     $|key 1| = value1
#     $||key1|key2|| = value2    # The key is key1|key2
#     X = $|key 1|               # Define X to be the value of field $|key 1|
# \end{verbatim}
#
# The usual modifiers are also allowed.  The expression \verb+$`|key|+ represents
# lazy evaluation of the key, and \verb+$,|key|+ is normal evaluation.
#
# \end{doc}
#
Map. +=
    class Map
    extends $(Object)

    mem(v) =
        return $(map-mem $(this), $(v))

    add(v, x) =
        return $(map-add $(this), $(v), $(x))

    remove(v) =
        return $(map-remove $(this), $(v))

    find(v) =
        return $(map-find $(this), $(v))

    map(f) =
        export
        return $(map-map $(this), $(f))

    curry.foreach() =
        private.THIS = $(this)
        g(f) =
            export
            map-map($(THIS), $f)

    length() =
        return $(map-length $(this))

    keys() =
        return $(map-keys $(this))

    values() =
        return $(map-values $(this))

########################################################################
# \begin{doc}
# \obj{Number}
#
# Parent objects: \verb+Object+.
#
# The \verb+Number+ object is the parent object for integers
# and floating-point numbers.
# \end{doc}
#
Number. +=
   class Number
   extends $(Object)

public.Number = $(Number)

#
# \begin{doc}
# \obj{Int}
#
# Parent objects: \verb+Number+.
#
# The \verb+Int+ object represents integer values.
# \end{doc}
#
Int. +=
   class Int
   extends $(Number)

#
# \begin{doc}
# \obj{Float}
#
# Parent objects: \verb+Number+.
#
# The \verb+Float+ object represents floating-point numbers.
# \end{doc}
#
Float. +=
   class Float
   extends $(Number)

########################################################################
# \begin{doc}
# \obj{Sequence}
#
# Parent objects: \verb+Object+.
#
# The \verb+Sequence+ object represents a generic object containing
# sequential elements.  It provides the following methods.
#
# \begin{itemize}
# \item \verb+$(s.length)+: the number of elements in the sequence.
# \item \verb+$(s.is-nonempty)+: true iff the expression \verb+$(s.nth 0)+
#    will complete without failure.
# \item \verb+$(s.nth <i>)+: return the n'th element of the sequence.
# \item \verb+$(s.nth-tl <i>)+: return the n'th tail of the sequence.
# \item \verb+$(s.map <fun>)+: maps a function over the fields in the sequence.
#    The function should take one argument. The result is a new sequence
#    constructed from the values returned by the function.
# \item \verb+s.foreach+: the \verb+foreach+ form is equivalent to \verb+map+,
#    but with altered syntax.
#
#    \begin{verbatim}
#    s.foreach(<var>) =>
#       <body>
#    \end{verbatim}
#
#    For example, the following function prints all the elements of the sequence.
#
#    \begin{verbatim}
#    PrintSequence(s) =
#       s.foreach(x) =>
#          println(Elem = $(x))
#    \end{verbatim}
#
#    The \verb+export+ form is valid in a \verb+foreach+ body.  The following
#    function counts the number of zeros in the sequence.
#
#    \begin{verbatim}
#    Zeros(s) =
#       count = $(int 0)
#       s.foreach(v) =>
#          if $(equal $(v), 0)
#             count = $(add $(count), 1)
#             export
#          export
#       return $(count)
#    \end{verbatim}
#
# \item \verb+$(s.forall <fun>)+: tests whether each element of the sequence
#   satifies a predicate.
# \item \verb+$(s.exists <fun>)+: tests whether the sequence contains an element
#   that satisfies a predicate.
# \item \verb+$(s.sort <fun>)+: sorts a sequence.  The \verb+<fun>+ is a comparison
#   function.  It takes two elements \verb+(x, y)+ of the sequence, compares them, and returns
#   a negative number if $x < y$, a positive number if $x > y$, and zero if the two elements
#   are equal.
#
#   \begin{verbatim}
#   osh> items = $(int 0 3 -2)
#   osh> items.forall(x => $(gt $x, 0))
#   - : bool = false
#   osh> items.exists(x => $(gt $x, 0))
#   - : bool = true
#   osh> items.sort($(compare))
#   - : Array = -2 3 0
#   \end{verbatim}
#
# \end{itemize}
# \end{doc}
#
Sequence. +=
   class Sequence
   extends $(Object)

   length() =
      sequence-length($(this))

   is-nonempty() =
      sequence-nonempty($(this))

   nth(i) =
      sequence-nth($(this), $(i))

   nth-tl(i) =
      sequence-nth-tl($(this), $(i))

   sub(off, len) =
      sequence-sub($(this), $(off), $(len))

   rev() =
      sequence-rev($(this))

   map(f) =
      sequence-map($(f), $(this))

   # Note: private exports have no effect
   curry.foreach() =
      private.THIS = $(this)
      g(f) =
         export
         sequence-map($(f), $(THIS))

   forall(f) =
      sequence-forall($f, $(this))

   exists(f) =
      sequence-exists($f, $(this))

   sort(f) =
      sequence-sort($f, $(this))

public.Sequence = $(Sequence)

#
# \begin{doc}
# \obj{Array}
#
# Parent objects: \verb+Sequence+.
#
# The \verb+Array+ is a random-access sequence.
# It provides the following additional methods.
#
# \begin{itemize}
# \item \verb+$(s.nth <i>)+: returns element \verb+i+ of the sequence.
# \item \verb+$(s.rev <i>)+: returns the reversed sequence.
# \end{itemize}
#
# \end{doc}
#
Array. +=
   class Array
   extends $(Sequence)

public.Array = $(Array)

#
# \begin{doc}
# \obj{String}
#
# Parent objects: \verb+Array+.
# \end{doc}
#
String. +=
    class String
    extends $(Array)

########################################################################
# \begin{doc}
# \obj{Fun}
#
# Parent objects: \verb+Object+.
#
# The \verb+Fun+ object provides the following methods.
# \begin{itemize}
# \item \verb+$(f.arity)+: the arity if the function.
# \end{itemize}
# \end{doc}
#
Fun. +=
   class Fun
   extends $(Object)

   arity() =
      return $(sequence-length $(this))

########################################################################
# \begin{doc}
# \obj{Rule}
#
# Parent objects: \verb+Object+.
#
# The \verb+Rule+ object represents a build rule.
# It does not currently have any methods.
# \end{doc}
#
Rule. +=
   class Rule
   extends $(Object)

#
# \begin{doc}
# \obj{Target}
#
# Parent object: \verb+Object+.
#
# The \verb+Target+ object contains information collected for
# a specific target file.
#
# \begin{itemize}
# \item \verb+target+: the target file.
# \item \verb+effects+: the files that may be modified by a
#    side-effect when this target is built.
# \item \verb+scanner_deps+: static dependencies that must be built
#    before this target can be scanned.
# \item \verb+static-deps+: statically-defined build dependencies
#    of this target.
# \item \verb+build-deps+: all the build dependencies for the target,
#    including static and scanned dependencies.
# \item \verb+build-values+: all the value dependencies associated
#    with the build.
# \item \verb+build-commands+: the commands to build the target.
# \item \verb+output-file+: if output was diverted to a file,
#    with one of the \verb+--output-*+ options~\ref{chapter:options},
#    this field names that file.  Otherwise it is \verb+false+.
# \end{itemize}
#
# The object supports the following methods.
#
# \begin{itemize}
# \item \verb+find(file)+: returns a Target object for the given file.
#    Raises a \verb+RuntimeException+ if the specified target is
#    not part of the project.
# \item \verb+find-optional(file)+: returns a \verb+Target+ object
#    for the given file, or \verb+false+ if the file is not
#    part of the project.
# \end{itemize}
#
# NOTE: the information for a target is constructed dynamically,
# so it is possible that the \verb+Target+ object for a node will
# contain different values in different contexts.  The easiest way
# to make sure that the \verb+Target+ information is complete is
# to compute it within a rule body, where the rule depends on
# the target file, or the dependencies of the target file.
# \end{doc}
#
Target. +=
   class Target
   extends $(Object)

   target =
   effects =
   scanner-deps =
   static-deps =
   build-deps =
   build-values =
   build-commands =
   output-file = false

   find(file) =
      return $(target $(file))

   find-optional(file) =
      return $(target-optional $(file))

########################################################################
# \begin{doc}
# \obj{Node}
#
# Parent objects: \verb+Object+.
#
# The \verb+Node+ object is the parent object for files and directories.
# It supports the following operations.
# \begin{itemize}
# \end{doc}
#
Node. +=
    class Node
    extends $(Object)

    #
    # \begin{doc}
    # \item \verb+$(node.stat)+: returns a \verb+stat+ object for the file.  If the
    # file is a symbolic link, the \verb+stat+ information is for the destination of
    # the link, not the link itself.
    #
    #
    # \item \verb+$(node.lstat)+: returns a \verb+stat+ object for the file or symbolic link.
    # \end{doc}
    #
    stat() =
       return $(public.stat $(this))

    lstat() =
       return $(public.lstat $(this))

    #
    # \begin{doc}
    # \item \verb+$(node.unlink)+: removes the file.
    # \item \verb+$(node.rename <file>)+: renames the file.
    # \item \verb+$(node.link <file>)+: creates a hard link \verb+<dst>+ to this file.
    # \item \verb+$(node.symlink <file>)+: create a symbolic link \verb+<dst>+ to this file.
    # \end{doc}
    #
    unlink() =
       return $(public.unlink $(this))

    rename(file) =
       return $(public.rename $(this), $(file))

    link(file) =
       return $(public.link $(this), $(file))

    symlink(file) =
       return $(public.symlink $(this), $(file))

    #
    # \begin{doc}
    # \item \verb+$(node.chmod <perm>)+: change the permission of this file.
    # \item \verb+$(node.chown <uid>, <gid>)+: change the owner and group id of this file.
    # \end{doc}
    #
    chmod(perm) =
       return $(public.chmod $(this), $(perm))

    chown(uid, gid) =
       return $(public.chown $(this), $(uid), $(gid))

public.Node = $(Node)

#
# \begin{doc}
# \end{itemize}
# \end{doc}
#

#
# \begin{doc}
# \obj{File}
#
# Parent objects: \verb+Node+.
#
# The file object represents the name of a file.
# \end{doc}
#
File. +=
    class File
    extends $(Node)

#
# \begin{doc}
# \obj{Dir}
#
# Parent objects: \verb+Node+.
#
# The \verb+Dir+ object represents the name of a directory.
# \end{doc}
#
Dir. +=
    class Dir
    extends $(Node)

########################################################################
# \begin{doc}
# \obj{Channel}
#
# Parent objects: \verb+Object+.
#
# A \verb+Channel+ is a generic IO channel.
# It provides the following methods.
# \begin{itemize}
# \end{doc}
Channel. +=
    class Channel
    extends $(Object)

    #
    # \begin{doc}
    # \item \verb+$(o.close)+: close the channel.
    # \end{doc}
    #
    close() =
       public.close($(this))

    #
    # \begin{doc}
    # \item \verb+$(o.name)+: returns the file name associated with the channel.
    # \end{doc}
    #
    name() =
       return $(public.channel-name $(this))

public.Channel = $(this.Channel)
#
# \begin{doc}
# \end{itemize}
# \end{doc}
#

########################################################################
# \begin{doc}
# \obj{InChannel}
#
# Parent objects: \verb+Channel+.
#
# A \verb+InChannel+ is an input channel.  The variable \verb+stdin+ is the
# standard input channel.
#
# It provides the following methods.
# \begin{itemize}
# \end{doc}
#
InChannel. +=
    class InChannel
    extends $(Channel)

    #
    # \begin{doc}
    # \item \verb+$(InChannel.fopen <file>)+: open a new input channel.
    # \end{doc}
    #
    fopen(file) =
       return $(public.fopen $(file), r)

    #
    # \begin{doc}
    # \item \verb+$(InChannel.of-string <string>)+: open a new input channel,
    # using a string as input.
    # \end{doc}
    of-string = $(open-in-string)

    #
    # \begin{doc}
    # \item \verb+$(o.read <number>)+: reads the given number of characters from the channel
    # \end{doc}
    read(amount) =
        return $(public.read $(this), $(amount))
       
    #
    # \begin{doc}
    # \item \verb+$(o.readln)+: reads a line from the channel
    # \end{doc}
    readln() =
        return $(public.input-line $(this))
       
#
# \begin{doc}
# \end{itemize}
# \end{doc}
#

########################################################################
# \begin{doc}
# \obj{OutChannel}
#
# Parent object: \verb+Channel+.
#
# A \verb+OutChannel+ is an output channel.  The variables \verb+stdout+
# and \verb+stderr+ are the standard output and error channels.
#
# It provides the following methods.
# \begin{itemize}
# \end{doc}
#
OutChannel. +=
    class OutChannel
    extends $(Channel)

    #
    # \begin{doc}
    # \item \verb+$(OutChannel.fopen <file>)+: open a new output channel.
    # \end{doc}
    #
    fopen(file) =
       return $(public.fopen $(file), w)

    #
    # \begin{doc}
    # \item \verb+$(OutChannel.string)+: open a new output channel,
    # writing to a string.
    # \end{doc}
    #
    to-string() =
       return $(public.open-out-string)

    #
    # \begin{doc}
    # \item \verb+$(OutChannel.to-string)+: get the current string of
    # output, for an output channel created as \verb+OutChannel.open-string+.
    # \end{doc}
    #
    contents() =
       return $(public.out-contents $(this))

    #
    # \begin{doc}
    # \item \verb+$(OutChannel.append <file>)+: opens a new output channel,
    # appending to the file.
    # \end{doc}
    #
    append(file) =
       return $(public.fopen $(file), a)

    #
    # \begin{doc}
    # \item \verb+$(c.flush)+: flush the output channel.
    # \end{doc}
    #
    flush() =
        return $(public.flush $(this))

    #
    # \begin{doc}
    # \item \verb+$(c.print <string>)+: print a string to the channel.
    # \end{doc}
    #
    print(s) =
        return $(public.fprint $(this), $(s))

    #
    # \begin{doc}
    # \item \verb+$(c.println <string>)+: print a string to the channel,
    # followed by a line terminator.
    # \end{doc}
    #
    println(s) =
        return $(public.fprintln $(this), $(s))
#
# \begin{doc}
# \end{itemize}
# \end{doc}
#

########################################################################
# \begin{doc}
# \obj{Location}
#
# Parent objects: \verb+Location+.
#
# The \verb+Location+ object represents a location in a file.
# \end{doc}
#
Location. +=
    class Location
    extends $(Object)

    to-string() =
        string-of-location($(this))

########################################################################
# \begin{doc}
# \obj{Exception}
#
# Parent objects: \verb+Object+.
#
# The \verb+Exception+ object is used as the base object for exceptions.
# It has no fields.
# \end{doc}
#
Exception. +=
    class Exception
    extends $(Object)

public.Exception = $(Exception)

#
# \begin{doc}
# \obj{RuntimeException}
#
# Parent objects: \verb+Exception+.
#
# The \verb+RuntimeException+ object represents an exception from the
# runtime system.  It has the following fields.
#
# \begin{itemize}
# \item \verb+position+: a string representing the location where the
#    exception was raised.
# \item \verb+message+: a string containing the exception message.
# \end{itemize}
# \end{doc}
#
RuntimeException. +=
    class RuntimeException
    extends $(Exception)

    position = no position
    message = no message

#
# \begin{doc}
# \obj{UnbuildableException}
#
# Parent objects: \verb+Exception+.
#
# The \verb+UnbuildableException+ object should be used to signal that a target
# is not buildable. It will be caught by functions such as
# \hyperfunn{target-exists}.
# This exception has the following fields:
#
# \begin{itemize}
# \item \verb+target+: indicates which target is not buildable.
# \item \verb+message+: a string containing the exception message.
# \end{itemize}
# \end{doc}
#
UnbuildableException. +=
    class UnbuildableException
    extends $(Exception)

    message = no message
    target = no target

########################################################################
# System objects.
#
Select. +=
   class Select
   extends $(Object)

Pipe. +=
   class Pipe
   extends $(Object)

Stat. +=
   class Stat
   extends $(Object)

Passwd. +=
   class Passwd
   extends $(Object)

Group. +=
   class Group
   extends $(Object)

Tm. +=
   class Tm
   extends $(Object)
   tm_sec = $(int 0)
   tm_min = $(int 0)
   tm_hour = $(int 0)
   tm_mday = $(int 0)
   tm_mon = $(int 0)
   tm_year = $(int 0)
   tm_wday = $(int 0)
   tm_yday = $(int 0)
   tm_isdst = false

########################################################################
# The shell object.
#
# \begin{doc}
# \obj{Shell}
#
# Parent objects: \verb+Object+.
#
# The \verb+Shell+ object contains the collection of builtin functions
# available as shell commands.
#
# You can define aliases by extending this object with additional methods.
# All methods in this class are called with one argument: a single array
# containing an argument list.
#
# \begin{itemize}
# \end{doc}
#
Shell. +=
   class Shell
   extends $(Object)

   #
   # \begin{doc}
   # \itemidx{echo}
   #
   # The \verb+echo+ function prints its arguments to the standard output channel.
   # \end{doc}
   #
   echo = $(echo)

   #
   # \begin{doc}
   # \itemidx{jobs}
   #
   # The \verb+jobs+ method prints the status of currently running commands.
   # \end{doc}
   #
   jobs = $(jobs)

   getpwnam = $(getpwnam)
   getpwuid = $(getpwuid)
   getgrnam = $(getgrnam)
   getgrgid = $(getgrgid)

   #
   # \begin{doc}
   # \itemidx{cd}
   #
   # The \verb+cd+ function changes the current directory.
   # Note that the current directory follows the usual scoping
   # rules.  For example, the following program lists the
   # files in the \verb+foo+ directory, but the current
   # directory is not changed.
   #
   # \begin{verbatim}
   #    section
   #       echo Listing files in the foo directory...
   #       cd foo
   #       ls
   #
   #    echo Listing files in the current directory...
   #    ls
   # \end{verbatim}
   # \end{doc}
   #
   cd = $(cd)

   #
   # \begin{doc}
   # \itemidx{bg}
   #
   # The \verb+bg+ method places a job in the background.
   # The job is resumed if it has been suspended.
   # \end{doc}
   #
   bg = $(bg)

   #
   # \begin{doc}
   # \itemidx{fg}
   #
   # The \verb+fg+ method brings a job to the foreground.
   # The job is resumed if it has been suspended.
   # \end{doc}
   #
   fg = $(fg)

   #
   # \begin{doc}
   # \itemidx{stop}
   #
   # The \verb+stop+ method suspends a running job.
   # \end{doc}
   #
   stop = $(stop)

   #
   # \begin{doc}
   # \itemidx{wait}
   #
   # The \verb+wait+ function waits for a running job to terminate.
   # It is not possible to wait for a suspended job.
   #
   # The job is not brought to the foreground.  If the \verb+wait+
   # is interrupted, the job continues to run in the background.
   # \end{doc}
   #
   wait = $(wait)

   #
   # \begin{doc}
   # \itemidx{kill}
   #
   # The \verb+kill+ function signal a job.
   #
   # \verb+kill [signal] <pid...>+.
   #
   # The signals are either numeric, or symbolic.
   # The symbolic signals are named as follows.
   #
   # ABRT, ALRM, HUP, ILL, KILL, QUIT, SEGV, TERM, USR1,
   # USR2, CHLD, STOP, TSTP, TTIN, TTOU, VTALRM, PROF.
   # \end{doc}
   #
   kill = $(kill)

   #
   # \begin{doc}
   # \itemidx{exit}
   #
   # The \verb+exit+ function terminates the current session.
   # \end{doc}
   #
   exit = $(exit-parent)

   #
   # \begin{doc}
   # \itemtwoidx{which}{where}
   #
   # See the documentation for the corresponding functions.
   # \end{doc}
   which(argv) =
      println($(which $(argv)))

   where(argv) =
      res[] = $(where $(argv))
      res.map($(println))
      return $(int 0)

   #
   # \begin{doc}
   # \itemidx{rehash}
   #
   # Reset the search path.
   # \end{doc}
   #
   rehash(argv) =
      rehash()

   #
   # \begin{doc}
   # \itemidx{ln-or-cp} \em{src} \em{dst}
   #
   # Links or copies \em{src} to \em{dst}, overwriting \em{dst}. Namely, \verb+ln-or-cp+ would first
   # delete the \em{dst} file (unless it is a directory), if it exists. Next it would try to create
   # a symbolic link \em{dst} poiting to \em{src} (it will make all the necessary adjustmnents of
   # relative paths). If symbolic link can not be created (\emph{e.g.} the OS or the filesystem does
   # not support symbolic links), it will try to create a hard link. If that fails too, it will try
   # to forcibly copy \em{src} to \em{dst}.
   # \end{doc}
   #
   ln-or-cp(argv) =
      if $(not $(eq $(length $(argv)), 2))
         eprintln($"Shell.ln-or-cp: expected 2 arguments, received $(length $(argv)) arguments")
         exit(1)
      src = $(file $"$(nth 0, $(argv))")
      dst = $(file $"$(nth 1, $(argv))")
      if $(and $(test -e $(dst)), $(not $(test -d $(dst))))
         rm($(array -f, $(dst)))
         if $(test -e $(dst))
            # The dst might be read-only; on Windows this will prevent deletion.
            # Will try to fix the permissions and rm again.
            # If dst and src are already hardliked, this will break
            # the permissions on src, so we will try to restore them.
            src_was_ro = $(not $(test -w $(src)))
            chmod -f -m u+w $(dst)
            rm($(array -f, $(dst)))
            if $(and $(src_was_ro), $(test -w $(src)))
                chmod -f -m u-w $(src)
      try
         symlink($(src), $(dst))
      default
         try
            link($(src), $(dst))
         default
            if $(and $(test -e $(dst)), $(not $(test -d $(dst))))
                # NB: $(dst) might already be a hardlink and we failed to delete it
                # Trying to cp in that case might cause both $(src) and $(dst) to
                # get truncated!
                eprintln($"ln-or-cp: failed to remove the destination file $(dst) before overwriting; giving up.")
                exit(1)
            return $(cp $(array -f, $(src), $(dst)))

   #
   # \begin{doc}
   # \itemidx{history}
   #
   # Print the current command-line history.
   # \end{doc}
   #
   history(argv) =
      lines = $(public.history)
      lines.map($(println))
      return $(int 0)

   #
   # \begin{doc}
   # \itemidx{digest}
   #
   # Print the digests of the given files.
   # \end{doc}
   #
   digest(argv) =
       foreach(n => ..., $(argv))
           println($"$n: $(digest $n)")
       value

   #
   # \begin{doc}
   # \item Win32 functions.
   #
   #     Win32 doesn't provide very many programs for scripting, except
   #     for the functions that are builtin to the DOS \verb+cmd.exe+.
   #     The following functions are defined on Win32 and only on Win32.
   #     On other systems, it is expected that these programs already
   #     exist.
   #
   # \begin{itemize}
   # \end{doc}
   #
   if $(equal $(OSTYPE), Win32)
       #
       # \begin{doc}
       # \itemidx{grep}
       #
       # \begin{verbatim}
       #    grep [-q] [-n] [-v] [-h] pattern files...
       # \end{verbatim}
       #
       # The \verb+grep+ alias calls the \Prog{omake}'s internal \hyperfun{grep}.
       # \end{doc}
       #
       grep = $(builtin-grep)

       export
   #
   # \begin{doc}
   # \end{itemize}
   # \end{doc}
   #

   #
   # \begin{doc} Internal versions of standard system commands.
   #
   # By default, \Prog{omake} uses internal versions of the following commands:
   # \verb+cp+, \verb+mv+, \verb+cat+, \verb+rm+, \verb+mkdir+, \verb+chmod+,
   # \verb+test+, \verb+find+.
   # If you really want to use the standard system versions of these
   # commands, set the \verb+USE_SYSTEM_COMMANDS+ as one of the first
   # definitions in your \verb+OMakeroot+ file.
   #
   # \begin{itemize}
   # \end{doc}
   #
   declare [
   declare true
   if $(not $(defined USE_SYSTEM_COMMANDS))
       #
       # \begin{doc}
       # \itemidx{pwd}
       #
       # \begin{verbatim}
       #     pwd
       # \end{verbatim}
       #
       # The \verb+pwd+ alias would print the absolute path to current directory.
       # \end{doc}
       #
       pwd(argv) =
           println($(absname .))

       #
       # \begin{doc}
       # \itemidx{mkdir}
       #
       # \begin{verbatim}
       #     mkdir [-m <mode>] [-p] files
       # \end{verbatim}
       #
       # The \verb+mkdir+ function is used to create directories.
       # The -verb+-m+ option can be used to specify the permission
       # mode of the created directory.  If the \verb+-p+ option
       # is specified, the full path is created.
       # \end{doc}
       #
       mkdir = $(mkdir)

       #
       # \begin{doc}
       # \itemtwoidx{cp}{mv}
       #
       # \begin{verbatim}
       #     cp [-f] [-i] [-v] src dst
       #     cp [-f] [-i] [-v] files dst
       #     mv [-f] [-i] [-v] src dst
       #     mv [-f] [-i] [-v] files dst
       # \end{verbatim}
       #
       # The \verb+cp+ function copies a \verb+src+ file to
       # a \verb+dst+ file, overwriting it if it already exists.
       # If more than one source file is specified, the final file
       # must be a directory, and the source files are copied
       # into the directory.
       #
       # \begin{description}
       # \item[-f] Copy files forcibly, do not prompt.
       # \item[-i] Prompt before removing destination files.
       # \item[-v] Explain what is happening.
       # \end{description}
       # \end{doc}
       #
       cp = $(cp)
       mv = $(mv)

       #
       # \begin{doc}
       # \itemidx{rm}
       #
       # \begin{verbatim}
       #    rm [-f] [-i] [-v] [-r] files
       #    rmdir [-f] [-i] [-v] [-r] dirs
       # \end{verbatim}
       #
       # The \verb+rm+ function removes a set of files.
       # No warnings are issued if the files do not exist, or if
       # they cannot be removed.
       #
       # Options:
       # \begin{description}
       # \item[-f] Forcibly remove files, do not prompt.
       # \item[-i] Prompt before removal.
       # \item[-v] Explain what is happening.
       # \item[-r] Remove contents of directories recursively.
       # \end{description}
       # \end{doc}
       #
       rm = $(rm)
       rmdir = $(rmdir)

       #
       # \begin{doc}
       # \itemidx{chmod}
       #
       # \begin{verbatim}
       #     chmod [-r] [-v] [-f] mode files
       # \end{verbatim}
       #
       # The \verb+chmod+ function changes the permissions on a set of
       # files or directories.  This function does nothing on Win32.
       # The \verb+mode+ may be specified as an octal number,
       # or in symbolic form \verb+[ugoa]*[+-=][rwxXstugo]+.
       # See the man page for \verb+chmod+ for details.
       #
       # Options:
       # \begin{description}
       # \item[-r] Change permissions of all files in a directory recursively.
       # \item[-v] Explain what is happening.
       # \item[-f] Continue on errors.
       # \end{description}
       # \end{doc}
       #
       chmod = $(chmod)

       #
       # \begin{doc}
       # \itemidx{cat}
       #
       # \begin{verbatim}
       #    cat files...
       # \end{verbatim}
       #
       # The \verb+cat+ function prints the contents of the files to stdout
       # \end{doc}
       #
       cat(argv)=
           print($(cat $(argv)))

       #
       # \begin{doc}
       # \itemidx{test}
       #
       #    \verb+test+ \emph{expression}\\
       #    \verb+[+ \emph{expression} +]+\\
       #    \verb+[ --help+\\
       #    \verb+[ --version+\\
       #
       # See the documentation for the \hyperfun{test}.
       #
       # \end{doc}
       #
       test = $(builtin-test)
       [ = $(builtin-test-brack)

       #
       # \begin{doc}
       # \itemidx{find}
       #
       #    \verb+find+ \emph{expression}
       #
       # See the documentation for the \hyperfun{find}.
       #
       # \end{doc}
       #
       find = $(builtin-find)

       true(argv) =
          return true

       export

   #
   # \begin{doc}
   # \end{itemize}
   # \end{doc}
   #

#
# \begin{doc}
# \end{itemize}
# \end{doc}
#

#
# These are all documented in Omake_builtin_io_fun.
#
declare parse-loc

Token. =
   class Token

   loc =
   name =
   val =

   unit(name) =
      this.loc = $(parse-loc)
      this.name = $(name)
      return $(this)

   pair(name, val) =
      this.loc = $(parse-loc)
      this.name = $(name)
      this.val = $(val)
      return $(this)

   rename(name) =
      this.name = $(name)
      return $(this)

Lexer. +=
   class Lexer
   extends $(Object)

   declare channel

   #
   # For interpreting the rules
   #
   rule = $(lex-rule)

   #
   # To use a lexer, you would normally hand it a channel
   #
   from-channel(channel) =
      this.channel = $(channel)
      return $(this)

   lex() =
      return $(lex-engine $(this.channel))

   lex-channel(channel) =
      this.channel = $(channel)
      return $(lex-engine $(channel))

   set-line(filename, line) =
      set-channel-line($(channel), $(filename), $(line))

Parser. +=
   class Parser
   extends $(Object)

   #
   # For interpreting the rules
   #
   rule         = $(parse-rule)

   #
   # You must set the lexer
   #
   lexer =

   #
   # Start symbols
   #
   start        = $(parse-start)

   #
   # Precedence operations
   #
   left         = $(parse-left)
   right        = $(parse-right)
   nonassoc     = $(parse-nonassoc)

   #
   # Manipulating the current precedence level
   #
   prec-min     = $".min"
   prec-max     = $".max"
   current-prec = $".min"

   #
   # Build the parser
   #
   build        = $(parse-build)

   #
   # Main parsing function
   #
   parse(sym) =
      return $(parse-engine $(sym))

   parse-channel(sym, channel) =
      lexer = $(lexer.from-channel $(channel))
      return $(parse-engine $(sym))

   parse-file(sym, file) =
      channel = $(fopen $(file), r)
      lexer = $(lexer.from-channel $(channel))
      result = $(parse-engine $(sym))
      close($(channel))
      return $(result)

This web site is published by Informatikbüro Gerd Stolpmann
Powered by Caml