about summary refs log tree commit diff stats
path: root/html/subx/examples/ex1.subx.html
diff options
context:
space:
mode:
Diffstat (limited to 'html/subx/examples/ex1.subx.html')
-rw-r--r--html/subx/examples/ex1.subx.html79
1 files changed, 79 insertions, 0 deletions
diff --git a/html/subx/examples/ex1.subx.html b/html/subx/examples/ex1.subx.html
new file mode 100644
index 00000000..4ed9359e
--- /dev/null
+++ b/html/subx/examples/ex1.subx.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>Mu - subx/examples/ex1.subx</title>
+<meta name="Generator" content="Vim/8.0">
+<meta name="plugin-version" content="vim7.4_v2">
+<meta name="syntax" content="none">
+<meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy=">
+<meta name="colorscheme" content="minimal">
+<style type="text/css">
+<!--
+pre { white-space: pre-wrap; font-family: monospace; color: #aaaaaa; background-color: #080808; }
+body { font-size: 12pt; font-family: monospace; color: #aaaaaa; background-color: #080808; }
+a { color:#eeeeee; text-decoration: none; }
+a:hover { text-decoration: underline; }
+* { font-size: 12pt; font-size: 1em; }
+.LineNr { color: #444444; }
+.Comment { color: #9090ff; }
+.Comment a { color:#0000ee; text-decoration:underline; }
+.SalientComment { color: #00ffff; }
+-->
+</style>
+
+<script type='text/javascript'>
+<!--
+
+/* function to open any folds containing a jumped-to line before jumping to it */
+function JumpToLine()
+{
+  var lineNum;
+  lineNum = window.location.hash;
+  lineNum = lineNum.substr(1); /* strip off '#' */
+
+  if (lineNum.indexOf('L') == -1) {
+    lineNum = 'L'+lineNum;
+  }
+  lineElem = document.getElementById(lineNum);
+  /* Always jump to new location even if the line was hidden inside a fold, or
+   * we corrected the raw number to a line ID.
+   */
+  if (lineElem) {
+    lineElem.scrollIntoView(true);
+  }
+  return true;
+}
+if ('onhashchange' in window) {
+  window.onhashchange = JumpToLine;
+}
+
+-->
+</script>
+</head>
+<body onload='JumpToLine();'>
+<pre id='vimCodeElement'>
+<span id="L1" class="LineNr"> 1 </span><span class="SalientComment">## first program: same as <a href="https://www.muppetlabs.com/~breadbox/software/tiny/teensy.html">https://www.muppetlabs.com/~breadbox/software/tiny/teensy.html</a></span>
+<span id="L2" class="LineNr"> 2 </span><span class="Comment"># Just return 42.</span>
+<span id="L3" class="LineNr"> 3 </span><span class="Comment">#</span>
+<span id="L4" class="LineNr"> 4 </span><span class="Comment"># To run (from the subx directory):</span>
+<span id="L5" class="LineNr"> 5 </span><span class="Comment">#   $ subx translate examples/ex1.2.subx -o examples/ex1</span>
+<span id="L6" class="LineNr"> 6 </span><span class="Comment">#   $ subx run examples/ex1</span>
+<span id="L7" class="LineNr"> 7 </span><span class="Comment"># Expected result:</span>
+<span id="L8" class="LineNr"> 8 </span><span class="Comment">#   $ echo $?</span>
+<span id="L9" class="LineNr"> 9 </span><span class="Comment">#   42</span>
+<span id="L10" class="LineNr">10 </span>
+<span id="L11" class="LineNr">11 </span>== code
+<span id="L12" class="LineNr">12 </span><span class="Comment"># instruction                     effective address                                                   operand     displacement    immediate</span>
+<span id="L13" class="LineNr">13 </span><span class="Comment"># op          subop               mod             rm32          base        index         scale       r32</span>
+<span id="L14" class="LineNr">14 </span><span class="Comment"># 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes</span>
+<span id="L15" class="LineNr">15 </span>  bb/copy                                                                                                                         2a/imm32          <span class="Comment"># copy 42 to EBX</span>
+<span id="L16" class="LineNr">16 </span>  <span class="Comment"># exit(EBX)</span>
+<span id="L17" class="LineNr">17 </span>  b8/copy                                                                                                                         1/imm32           <span class="Comment"># copy to EAX</span>
+<span id="L18" class="LineNr">18 </span>  cd/syscall  0x80/imm8
+<span id="L19" class="LineNr">19 </span>
+<span id="L20" class="LineNr">20 </span><span class="Comment"># vim&#0058;ft=subx</span>
+</pre>
+</body>
+</html>
+<!-- vim: set foldmethod=manual : -->
n294'>294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
#
#
#            Nim's Runtime Library
#        (c) Copyright 2016 Eugene Kabanov
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## This module allows high-level and efficient I/O multiplexing.
##
## Supported OS primitives: ``epoll``, ``kqueue``, ``poll`` and
## Windows ``select``.
##
## To use threadsafe version of this module, it needs to be compiled
## with both ``-d:threadsafe`` and ``--threads:on`` options.
##
## Supported features: files, sockets, pipes, timers, processes, signals
## and user events.
##
## Fully supported OS: MacOSX, FreeBSD, OpenBSD, NetBSD, Linux (except
## for Android).
##
## Partially supported OS: Windows (only sockets and user events),
## Solaris (files, sockets, handles and user events).
## Android (files, sockets, handles and user events).
##
## TODO: ``/dev/poll``, ``event ports`` and filesystem events.

import os, strutils, nativesockets

const hasThreadSupport = compileOption("threads") and defined(threadsafe)

const ioselSupportedPlatform* = defined(macosx) or defined(freebsd) or
                                defined(netbsd) or defined(openbsd) or
                                defined(dragonfly) or
                                (defined(linux) and not defined(android))
  ## This constant is used to determine whether the destination platform is
  ## fully supported by ``ioselectors`` module.

const bsdPlatform = defined(macosx) or defined(freebsd) or
                    defined(netbsd) or defined(openbsd) or
                    defined(dragonfly)

when defined(nimdoc):
  type
    Selector*[T] = ref object
      ## An object which holds descriptors to be checked for read/write status

    Event* {.pure.} = enum
      ## An enum which hold event types
      Read,        ## Descriptor is available for read
      Write,       ## Descriptor is available for write
      Timer,       ## Timer descriptor is completed
      Signal,      ## Signal is raised
      Process,     ## Process is finished
      Vnode,       ## BSD specific file change
      User,        ## User event is raised
      Error,       ## Error occurred while waiting for descriptor
      VnodeWrite,  ## NOTE_WRITE (BSD specific, write to file occurred)
      VnodeDelete, ## NOTE_DELETE (BSD specific, unlink of file occurred)
      VnodeExtend, ## NOTE_EXTEND (BSD specific, file extended)
      VnodeAttrib, ## NOTE_ATTRIB (BSD specific, file attributes changed)
      VnodeLink,   ## NOTE_LINK (BSD specific, file link count changed)
      VnodeRename, ## NOTE_RENAME (BSD specific, file renamed)
      VnodeRevoke  ## NOTE_REVOKE (BSD specific, file revoke occurred)

    ReadyKey* = object
      ## An object which holds result for descriptor
      fd* : int ## file/socket descriptor
      events*: set[Event] ## set of events
      errorCode*: OSErrorCode ## additional error code information for
                              ## Error events

    SelectEvent* = object
      ## An object which holds user defined event

  proc newSelector*[T](): Selector[T] =
    ## Creates a new selector

  proc close*[T](s: Selector[T]) =
    ## Closes the selector.

  proc registerHandle*[T](s: Selector[T], fd: int | SocketHandle,
                          events: set[Event], data: T) =
    ## Registers file/socket descriptor ``fd`` to selector ``s``
    ## with events set in ``events``. The ``data`` is application-defined
    ## data, which will be passed when an event is triggered.

  proc updateHandle*[T](s: Selector[T], fd: int | SocketHandle,
                        events: set[Event]) =
    ## Update file/socket descriptor ``fd``, registered in selector
    ## ``s`` with new events set ``event``.

  proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool,
                         data: T): int {.discardable.} =
    ## Registers timer notification with ``timeout`` (in milliseconds)
    ## to selector ``s``.
    ##
    ## If ``oneshot`` is ``true``, timer will be notified only once.
    ##
    ## Set ``oneshot`` to ``false`` if you want periodic notifications.
    ##
    ## The ``data`` is application-defined data, which will be passed, when
    ## the timer is triggered.
    ##
    ## Returns the file descriptor for the registered timer.

  proc registerSignal*[T](s: Selector[T], signal: int,
                          data: T): int {.discardable.} =
    ## Registers Unix signal notification with ``signal`` to selector
    ## ``s``.
    ##
    ## The ``data`` is application-defined data, which will be
    ## passed when signal raises.
    ##
    ## Returns the file descriptor for the registered signal.
    ##
    ## **Note:** This function is not supported on ``Windows``.

  proc registerProcess*[T](s: Selector[T], pid: int,
                           data: T): int {.discardable.} =
    ## Registers a process id (pid) notification (when process has
    ## exited) in selector ``s``.
    ##
    ## The ``data`` is application-defined data, which will be passed when
    ## process with ``pid`` has exited.
    ##
    ## Returns the file descriptor for the registered signal.

  proc registerEvent*[T](s: Selector[T], ev: SelectEvent, data: T) =
    ## Registers selector event ``ev`` in selector ``s``.
    ##
    ## The ``data`` is application-defined data, which will be passed when
    ## ``ev`` happens.

  proc registerVnode*[T](s: Selector[T], fd: cint, events: set[Event],
                         data: T) =
    ## Registers selector BSD/MacOSX specific vnode events for file
    ## descriptor ``fd`` and events ``events``.
    ## ``data`` application-defined data, which to be passed, when
    ## vnode event happens.
    ##
    ## **Note:** This function is supported only by BSD and MacOSX.

  proc newSelectEvent*(): SelectEvent =
    ## Creates a new user-defined event.

  proc trigger*(ev: SelectEvent) =
    ## Trigger event ``ev``.

  proc close*(ev: SelectEvent) =
    ## Closes user-defined event ``ev``.

  proc unregister*[T](s: Selector[T], ev: SelectEvent) =
    ## Unregisters user-defined event ``ev`` from selector ``s``.

  proc unregister*[T](s: Selector[T], fd: int|SocketHandle|cint) =
    ## Unregisters file/socket descriptor ``fd`` from selector ``s``.

  proc selectInto*[T](s: Selector[T], timeout: int,
                      results: var openarray[ReadyKey]): int =
    ## Waits for events registered in selector ``s``.
    ##
    ## The ``timeout`` argument specifies the maximum number of milliseconds
    ## the function will be blocked for if no events are ready. Specifying a
    ## timeout of ``-1`` causes the function to block indefinitely.
    ## All available events will be stored in ``results`` array.
    ##
    ## Returns number of triggered events.

  proc select*[T](s: Selector[T], timeout: int): seq[ReadyKey] =
    ## Waits for events registered in selector ``s``.
    ##
    ## The ``timeout`` argument specifies the maximum number of milliseconds
    ## the function will be blocked for if no events are ready. Specifying a
    ## timeout of ``-1`` causes the function to block indefinitely.
    ##
    ## Returns a list of triggered events.

  proc getData*[T](s: Selector[T], fd: SocketHandle|int): var T =
    ## Retrieves application-defined ``data`` associated with descriptor ``fd``.
    ## If specified descriptor ``fd`` is not registered, empty/default value
    ## will be returned.

  proc setData*[T](s: Selector[T], fd: SocketHandle|int, data: var T): bool =
    ## Associate application-defined ``data`` with descriptor ``fd``.
    ##
    ## Returns ``true``, if data was successfully updated, ``false`` otherwise.

  template isEmpty*[T](s: Selector[T]): bool = # TODO: Why is this a template?
    ## Returns ``true``, if there are no registered events or descriptors
    ## in selector.

  template withData*[T](s: Selector[T], fd: SocketHandle|int, value,
                        body: untyped) =
    ## Retrieves the application-data assigned with descriptor ``fd``
    ## to ``value``. This ``value`` can be modified in the scope of
    ## the ``withData`` call.
    ##
    ## .. code-block:: nim
    ##
    ##   s.withData(fd, value) do:
    ##     # block is executed only if ``fd`` registered in selector ``s``
    ##     value.uid = 1000
    ##

  template withData*[T](s: Selector[T], fd: SocketHandle|int, value,
                        body1, body2: untyped) =
    ## Retrieves the application-data assigned with descriptor ``fd``
    ## to ``value``. This ``value`` can be modified in the scope of
    ## the ``withData`` call.
    ##
    ## .. code-block:: nim
    ##
    ##   s.withData(fd, value) do:
    ##     # block is executed only if ``fd`` registered in selector ``s``.
    ##     value.uid = 1000
    ##   do:
    ##     # block is executed if ``fd`` not registered in selector ``s``.
    ##     raise
    ##

  proc contains*[T](s: Selector[T], fd: SocketHandle|int): bool {.inline.} =
    ## Determines whether selector contains a file descriptor.

  proc getFd*[T](s: Selector[T]): int =
    ## Retrieves the underlying selector's file descriptor.
    ##
    ## For *poll* and *select* selectors ``-1`` is returned.

else:
  when hasThreadSupport:
    import locks

    type
      SharedArray[T] = UncheckedArray[T]

    proc allocSharedArray[T](nsize: int): ptr SharedArray[T] =
      result = cast[ptr SharedArray[T]](allocShared0(sizeof(T) * nsize))

    proc reallocSharedArray[T](sa: ptr SharedArray[T], nsize: int): ptr SharedArray[T] =
      result = cast[ptr SharedArray[T]](reallocShared(sa, sizeof(T) * nsize))

    proc deallocSharedArray[T](sa: ptr SharedArray[T]) =
      deallocShared(cast[pointer](sa))
  type
    Event* {.pure.} = enum
      Read, Write, Timer, Signal, Process, Vnode, User, Error, Oneshot,
      Finished, VnodeWrite, VnodeDelete, VnodeExtend, VnodeAttrib, VnodeLink,
      VnodeRename, VnodeRevoke

  type
    IOSelectorsException* = object of Exception

    ReadyKey* = object
      fd* : int
      events*: set[Event]
      errorCode*: OSErrorCode

    SelectorKey[T] = object
      ident: int
      events: set[Event]
      param: int
      data: T

  const
    InvalidIdent = -1

  proc raiseIOSelectorsError[T](message: T) =
    var msg = ""
    when T is string:
      msg.add(message)
    elif T is OSErrorCode:
      msg.add(osErrorMsg(message) & " (code: " & $int(message) & ")")
    else:
      msg.add("Internal Error\n")
    var err = newException(IOSelectorsException, msg)
    raise err

  proc setNonBlocking(fd: cint) {.inline.} =
    setBlocking(fd.SocketHandle, false)

  when not defined(windows):
    import posix

    template setKey(s, pident, pevents, pparam, pdata: untyped) =
      var skey = addr(s.fds[pident])
      skey.ident = pident
      skey.events = pevents
      skey.param = pparam
      skey.data = data

  when ioselSupportedPlatform:
    template blockSignals(newmask: var Sigset, oldmask: var Sigset) =
      when hasThreadSupport:
        if posix.pthread_sigmask(SIG_BLOCK, newmask, oldmask) == -1:
          raiseIOSelectorsError(osLastError())
      else:
        if posix.sigprocmask(SIG_BLOCK, newmask, oldmask) == -1:
          raiseIOSelectorsError(osLastError())

    template unblockSignals(newmask: var Sigset, oldmask: var Sigset) =
      when hasThreadSupport:
        if posix.pthread_sigmask(SIG_UNBLOCK, newmask, oldmask) == -1:
          raiseIOSelectorsError(osLastError())
      else:
        if posix.sigprocmask(SIG_UNBLOCK, newmask, oldmask) == -1:
          raiseIOSelectorsError(osLastError())

  template clearKey[T](key: ptr SelectorKey[T]) =
    var empty: T
    key.ident = InvalidIdent
    key.events = {}
    key.data = empty

  proc verifySelectParams(timeout: int) =
    # Timeout of -1 means: wait forever
    # Anything higher is the time to wait in milliseconds.
    doAssert(timeout >= -1, "Cannot select with a negative value, got " & $timeout)

  when defined(linux):
    include ioselects/ioselectors_epoll
  elif bsdPlatform:
    include ioselects/ioselectors_kqueue
  elif defined(windows):
    include ioselects/ioselectors_select
  elif defined(solaris):
    include ioselects/ioselectors_poll # need to replace it with event ports
  elif defined(genode):
    include ioselects/ioselectors_select # TODO: use the native VFS layer
  elif defined(nintendoswitch):
    include ioselects/ioselectors_select
  else:
    include ioselects/ioselectors_poll

proc register*[T](s: Selector[T], fd: int | SocketHandle,
                  events: set[Event], data: T) {.deprecated: "use registerHandle instead".} =
  ## **Deprecated since v0.18.0:** Use ``registerHandle`` instead.
  s.registerHandle(fd, events, data)

proc setEvent*(ev: SelectEvent) {.deprecated: "use trigger instead".} =
  ## Trigger event ``ev``.
  ##
  ## **Deprecated since v0.18.0:** Use ``trigger`` instead.
  ev.trigger()

proc update*[T](s: Selector[T], fd: int | SocketHandle,
                events: set[Event]) {.deprecated: "use updateHandle instead".} =
  ## Update file/socket descriptor ``fd``, registered in selector
  ## ``s`` with new events set ``event``.
  ##
  ## **Deprecated since v0.18.0:** Use ``updateHandle`` instead.
  s.updateHandle()