Initial import

This commit is contained in:
Andreas Rumpf
2008-06-22 16:14:11 +02:00
commit 405b86068e
324 changed files with 163599 additions and 0 deletions

17
Nimrod.geany Executable file
View File

@@ -0,0 +1,17 @@
[project]
name=Nimrod
base_path=/media/hda4/nimrod
make_in_base_path=false
description=
run_cmd=python koch.py nim
[files]
current_page=6
FILE_NAME_0=786;20;0;16;0;1;0;/media/hda4/nimrod/todo.txt;
FILE_NAME_1=7567;34;0;16;0;1;0;/media/hda4/nimrod/lib/base/dialogs.nim;
FILE_NAME_2=353;34;0;16;0;1;0;/media/hda4/nimrod/tests/tdialogs.nim;
FILE_NAME_3=1811;9;0;16;0;1;0;/media/hda4/nimrod/nim/ccgexprs.pas;
FILE_NAME_4=119539;0;0;16;0;1;0;/media/hda4/nimrod/lib/rod_gen/system.c;
FILE_NAME_5=192;9;0;16;0;1;0;/media/hda4/nimrod/nim/eval.pas;
FILE_NAME_6=0;34;0;16;0;1;0;/media/hda4/nimrod/lib/unicode.nim;

694
cogapp.py Executable file
View File

@@ -0,0 +1,694 @@
""" Cog code generation tool.
http://nedbatchelder.com/code/cog
Copyright 2004-2008, Ned Batchelder.
"""
# $Id: cogapp.py 141 2008-05-22 10:56:43Z nedbat $
import md5, os, re, string, sys, traceback, types
import imp, compiler
import copy, getopt, shlex
from cStringIO import StringIO
__all__ = ['Cog', 'CogUsageError']
__version__ = '2.1.20080522' # History at the end of the file.
usage = """\
cog - generate code with inlined Python code.
cog [OPTIONS] [INFILE | @FILELIST] ...
INFILE is the name of an input file.
FILELIST is the name of a text file containing file names or
other @FILELISTs.
OPTIONS:
-c Checksum the output to protect it against accidental change.
-d Delete the generator code from the output file.
-D name=val Define a global string available to your generator code.
-e Warn if a file has no cog code in it.
-I PATH Add PATH to the list of directories for data files and modules.
-o OUTNAME Write the output to OUTNAME.
-r Replace the input file with the output.
-s STRING Suffix all generated output lines with STRING.
-U Write the output with Unix newlines (only LF line-endings).
-w CMD Use CMD if the output file needs to be made writable.
A %s in the CMD will be filled with the filename.
-x Excise all the generated output without running the generators.
-z The [[[end]]] marker can be omitted, and is assumed at eof.
-v Print the version of cog and exit.
-h Print this help.
"""
# Get True and False right even if they aren't already defined.
True, False = 0==0, 0==1
# Other package modules
from whiteutils import *
class CogError(Exception):
""" Any exception raised by Cog.
"""
def __init__(self, msg, file='', line=0):
if file:
Exception.__init__(self, "%s(%d): %s" % (file, line, msg))
else:
Exception.__init__(self, msg)
class CogUsageError(CogError):
""" An error in usage of command-line arguments in cog.
"""
pass #pragma: no cover
class CogInternalError(CogError):
""" An error in the coding of Cog. Should never happen.
"""
pass #pragma: no cover
class CogGeneratedError(CogError):
""" An error raised by a user's cog generator.
"""
pass #pragma: no cover
class Redirectable:
""" An object with its own stdout and stderr files.
"""
def __init__(self):
self.stdout = sys.stdout
self.stderr = sys.stderr
def setOutput(self, stdout=None, stderr=None):
""" Assign new files for standard out and/or standard error.
"""
if stdout:
self.stdout = stdout
if stderr:
self.stderr = stderr
class CogGenerator(Redirectable):
""" A generator pulled from a source file.
"""
def __init__(self):
Redirectable.__init__(self)
self.markers = []
self.lines = []
def parseMarker(self, l):
self.markers.append(l)
def parseLine(self, l):
self.lines.append(l.strip('\n'))
def getCode(self):
""" Extract the executable Python code from the generator.
"""
# If the markers and lines all have the same prefix
# (end-of-line comment chars, for example),
# then remove it from all the lines.
prefIn = commonPrefix(self.markers + self.lines)
if prefIn:
self.markers = [ l.replace(prefIn, '', 1) for l in self.markers ]
self.lines = [ l.replace(prefIn, '', 1) for l in self.lines ]
return reindentBlock(self.lines, '')
def evaluate(self, cog, globals, fname='cog generator'):
# figure out the right whitespace prefix for the output
prefOut = whitePrefix(self.markers)
intext = self.getCode()
if not intext:
return ''
# In Python 2.2, the last line has to end in a newline.
intext = "import cog\n" + intext + "\n"
code = compiler.compile(intext, filename=str(fname), mode='exec')
# Make sure the "cog" module has our state.
cog.cogmodule.msg = self.msg
cog.cogmodule.out = self.out
cog.cogmodule.outl = self.outl
cog.cogmodule.error = self.error
self.outstring = ''
eval(code, globals)
# We need to make sure that the last line in the output
# ends with a newline, or it will be joined to the
# end-output line, ruining cog's idempotency.
if self.outstring and self.outstring[-1] != '\n':
self.outstring += '\n'
return reindentBlock(self.outstring, prefOut)
def msg(self, s):
print >>self.stdout, "Message: "+s
def out(self, sOut='', dedent=False, trimblanklines=False):
""" The cog.out function.
"""
if trimblanklines and ('\n' in sOut):
lines = sOut.split('\n')
if lines[0].strip() == '':
del lines[0]
if lines and lines[-1].strip() == '':
del lines[-1]
sOut = '\n'.join(lines)+'\n'
if dedent:
sOut = reindentBlock(sOut)
self.outstring += sOut
def outl(self, sOut='', **kw):
""" The cog.outl function.
"""
self.out(sOut, **kw)
self.out('\n')
def error(self, msg='Error raised by cog generator.'):
""" The cog.error function.
Instead of raising standard python errors, cog generators can use
this function. It will display the error without a scary Python
traceback.
"""
raise CogGeneratedError(msg)
class NumberedFileReader:
""" A decorator for files that counts the readline()'s called.
"""
def __init__(self, f):
self.f = f
self.n = 0
def readline(self):
l = self.f.readline()
if l:
self.n += 1
return l
def linenumber(self):
return self.n
class CogOptions:
""" Options for a run of cog.
"""
def __init__(self):
# Defaults for argument values.
self.args = []
self.includePath = []
self.defines = {}
self.bShowVersion = False
self.sMakeWritableCmd = None
self.bReplace = False
self.bNoGenerate = False
self.sOutputName = None
self.bWarnEmpty = False
self.bHashOutput = False
self.bDeleteCode = False
self.bEofCanBeEnd = False
self.sSuffix = None
self.bNewlines = False
def __cmp__(self, other):
""" Comparison operator for tests to use.
"""
return self.__dict__.__cmp__(other.__dict__)
def clone(self):
""" Make a clone of these options, for further refinement.
"""
return copy.deepcopy(self)
def addToIncludePath(self, dirs):
""" Add directories to the include path.
"""
dirs = dirs.split(os.pathsep)
self.includePath.extend(dirs)
def parseArgs(self, argv):
# Parse the command line arguments.
try:
opts, self.args = getopt.getopt(argv, 'cdD:eI:o:rs:Uvw:xz')
except getopt.error, msg:
raise CogUsageError(msg)
# Handle the command line arguments.
for o, a in opts:
if o == '-c':
self.bHashOutput = True
elif o == '-d':
self.bDeleteCode = True
elif o == '-D':
if a.count('=') < 1:
raise CogUsageError("-D takes a name=value argument")
name, value = a.split('=', 1)
self.defines[name] = value
elif o == '-e':
self.bWarnEmpty = True
elif o == '-I':
self.addToIncludePath(a)
elif o == '-o':
self.sOutputName = a
elif o == '-r':
self.bReplace = True
elif o == '-s':
self.sSuffix = a
elif o == '-U':
self.bNewlines = True
elif o == '-v':
self.bShowVersion = True
elif o == '-w':
self.sMakeWritableCmd = a
elif o == '-x':
self.bNoGenerate = True
elif o == '-z':
self.bEofCanBeEnd = True
else:
# Since getopt.getopt is given a list of possible flags,
# this is an internal error.
raise CogInternalError("Don't understand argument %s" % o)
def validate(self):
""" Does nothing if everything is OK, raises CogError's if it's not.
"""
if self.bReplace and self.bDeleteCode:
raise CogUsageError("Can't use -d with -r (or you would delete all your source!)")
if self.bReplace and self.sOutputName:
raise CogUsageError("Can't use -o with -r (they are opposites)")
class Cog(Redirectable):
""" The Cog engine.
"""
def __init__(self):
Redirectable.__init__(self)
self.sBeginSpec = '[[[cog'
self.sEndSpec = ']]]'
self.sEndOutput = '[[[end]]]'
self.reEndOutput = re.compile(r'\[\[\[end]]](?P<hashsect> *\(checksum: (?P<hash>[a-f0-9]+)\))')
self.sEndFormat = '[[[end]]] (checksum: %s)'
self.options = CogOptions()
self.sOutputMode = 'w'
self.installCogModule()
def showWarning(self, msg):
print >>self.stdout, "Warning:", msg
def isBeginSpecLine(self, s):
return string.find(s, self.sBeginSpec) >= 0
def isEndSpecLine(self, s):
return string.find(s, self.sEndSpec) >= 0 and \
not self.isEndOutputLine(s)
def isEndOutputLine(self, s):
return string.find(s, self.sEndOutput) >= 0
def installCogModule(self):
""" Magic mumbo-jumbo so that imported Python modules
can say "import cog" and get our state.
"""
self.cogmodule = imp.new_module('cog')
self.cogmodule.path = []
sys.modules['cog'] = self.cogmodule
def processFile(self, fIn, fOut, fname=None, globals=None):
""" Process an input file object to an output file object.
fIn and fOut can be file objects, or file names.
"""
sFileIn = fname or ''
sFileOut = fname or ''
# Convert filenames to files.
if isinstance(fIn, types.StringTypes):
# Open the input file.
sFileIn = fIn
fIn = open(fIn, 'r')
if isinstance(fOut, types.StringTypes):
# Open the output file.
sFileOut = fOut
fOut = open(fOut, self.sOutputMode)
fIn = NumberedFileReader(fIn)
bSawCog = False
self.cogmodule.inFile = sFileIn
self.cogmodule.outFile = sFileOut
# The globals dict we'll use for this file.
if globals is None:
globals = {}
# If there are any global defines, put them in the globals.
globals.update(self.options.defines)
# loop over generator chunks
l = fIn.readline()
while l:
# Find the next spec begin
while l and not self.isBeginSpecLine(l):
if self.isEndSpecLine(l):
raise CogError("Unexpected '%s'" % self.sEndSpec,
file=sFileIn, line=fIn.linenumber())
if self.isEndOutputLine(l):
raise CogError("Unexpected '%s'" % self.sEndOutput,
file=sFileIn, line=fIn.linenumber())
fOut.write(l)
l = fIn.readline()
if not l:
break
if not self.options.bDeleteCode:
fOut.write(l)
# l is the begin spec
gen = CogGenerator()
gen.setOutput(stdout=self.stdout)
gen.parseMarker(l)
firstLineNum = fIn.linenumber()
self.cogmodule.firstLineNum = firstLineNum
# If the spec begin is also a spec end, then process the single
# line of code inside.
if self.isEndSpecLine(l):
beg = string.find(l, self.sBeginSpec)
end = string.find(l, self.sEndSpec)
if beg > end:
raise CogError("Cog code markers inverted",
file=sFileIn, line=firstLineNum)
else:
sCode = l[beg+len(self.sBeginSpec):end].strip()
gen.parseLine(sCode)
else:
# Deal with an ordinary code block.
l = fIn.readline()
# Get all the lines in the spec
while l and not self.isEndSpecLine(l):
if self.isBeginSpecLine(l):
raise CogError("Unexpected '%s'" % self.sBeginSpec,
file=sFileIn, line=fIn.linenumber())
if self.isEndOutputLine(l):
raise CogError("Unexpected '%s'" % self.sEndOutput,
file=sFileIn, line=fIn.linenumber())
if not self.options.bDeleteCode:
fOut.write(l)
gen.parseLine(l)
l = fIn.readline()
if not l:
raise CogError(
"Cog block begun but never ended.",
file=sFileIn, line=firstLineNum)
if not self.options.bDeleteCode:
fOut.write(l)
gen.parseMarker(l)
l = fIn.readline()
# Eat all the lines in the output section. While reading past
# them, compute the md5 hash of the old output.
hasher = md5.new()
while l and not self.isEndOutputLine(l):
if self.isBeginSpecLine(l):
raise CogError("Unexpected '%s'" % self.sBeginSpec,
file=sFileIn, line=fIn.linenumber())
if self.isEndSpecLine(l):
raise CogError("Unexpected '%s'" % self.sEndSpec,
file=sFileIn, line=fIn.linenumber())
hasher.update(l)
l = fIn.readline()
curHash = hasher.hexdigest()
if not l and not self.options.bEofCanBeEnd:
# We reached end of file before we found the end output line.
raise CogError("Missing '%s' before end of file." % self.sEndOutput,
file=sFileIn, line=fIn.linenumber())
# Write the output of the spec to be the new output if we're
# supposed to generate code.
hasher = md5.new()
if not self.options.bNoGenerate:
sFile = "%s+%d" % (sFileIn, firstLineNum)
sGen = gen.evaluate(cog=self, globals=globals, fname=sFile)
sGen = self.suffixLines(sGen)
hasher.update(sGen)
fOut.write(sGen)
newHash = hasher.hexdigest()
bSawCog = True
# Write the ending output line
hashMatch = self.reEndOutput.search(l)
if self.options.bHashOutput:
if hashMatch:
oldHash = hashMatch.groupdict()['hash']
if oldHash != curHash:
raise CogError("Output has been edited! Delete old checksum to unprotect.",
file=sFileIn, line=fIn.linenumber())
# Create a new end line with the correct hash.
endpieces = l.split(hashMatch.group(0), 1)
else:
# There was no old hash, but we want a new hash.
endpieces = l.split(self.sEndOutput, 1)
l = (self.sEndFormat % newHash).join(endpieces)
else:
# We don't want hashes output, so if there was one, get rid of
# it.
if hashMatch:
l = l.replace(hashMatch.groupdict()['hashsect'], '', 1)
if not self.options.bDeleteCode:
fOut.write(l)
l = fIn.readline()
if not bSawCog and self.options.bWarnEmpty:
self.showWarning("no cog code found in %s" % sFileIn)
# A regex for non-empty lines, used by suffixLines.
reNonEmptyLines = re.compile("^\s*\S+.*$", re.MULTILINE)
def suffixLines(self, text):
""" Add suffixes to the lines in text, if our options desire it.
text is many lines, as a single string.
"""
if self.options.sSuffix:
# Find all non-blank lines, and add the suffix to the end.
repl = r"\g<0>" + self.options.sSuffix.replace('\\', '\\\\')
text = self.reNonEmptyLines.sub(repl, text)
return text
def processString(self, sInput, fname=None):
""" Process sInput as the text to cog.
Return the cogged output as a string.
"""
fOld = StringIO(sInput)
fNew = StringIO()
self.processFile(fOld, fNew, fname=fname)
return fNew.getvalue()
def replaceFile(self, sOldPath, sNewText):
""" Replace file sOldPath with the contents sNewText
"""
if not os.access(sOldPath, os.W_OK):
# Need to ensure we can write.
if self.options.sMakeWritableCmd:
# Use an external command to make the file writable.
cmd = self.options.sMakeWritableCmd.replace('%s', sOldPath)
self.stdout.write(os.popen(cmd).read())
if not os.access(sOldPath, os.W_OK):
raise CogError("Couldn't make %s writable" % sOldPath)
else:
# Can't write!
raise CogError("Can't overwrite %s" % sOldPath)
f = open(sOldPath, self.sOutputMode)
f.write(sNewText)
f.close()
def saveIncludePath(self):
self.savedInclude = self.options.includePath[:]
self.savedSysPath = sys.path[:]
def restoreIncludePath(self):
self.options.includePath = self.savedInclude
self.cogmodule.path = self.options.includePath
sys.path = self.savedSysPath
def addToIncludePath(self, includePath):
self.cogmodule.path.extend(includePath)
sys.path.extend(includePath)
def processOneFile(self, sFile):
""" Process one filename through cog.
"""
self.saveIncludePath()
try:
self.addToIncludePath(self.options.includePath)
# Since we know where the input file came from,
# push its directory onto the include path.
self.addToIncludePath([os.path.dirname(sFile)])
# Set the file output mode based on whether we want \n or native
# line endings.
self.sOutputMode = 'w'
if self.options.bNewlines:
self.sOutputMode = 'wb'
# How we process the file depends on where the output is going.
if self.options.sOutputName:
self.processFile(sFile, self.options.sOutputName, sFile)
elif self.options.bReplace:
# We want to replace the cog file with the output,
# but only if they differ.
print >>self.stdout, "Cogging %s" % sFile,
bNeedNewline = True
try:
fOldFile = open(sFile)
sOldText = fOldFile.read()
fOldFile.close()
sNewText = self.processString(sOldText, fname=sFile)
if sOldText != sNewText:
print >>self.stdout, " (changed)"
bNeedNewline = False
self.replaceFile(sFile, sNewText)
finally:
# The try-finally block is so we can print a partial line
# with the name of the file, and print (changed) on the
# same line, but also make sure to break the line before
# any traceback.
if bNeedNewline:
print >>self.stdout
else:
self.processFile(sFile, self.stdout, sFile)
finally:
self.restoreIncludePath()
def processFileList(self, sFileList):
""" Process the files in a file list.
"""
for l in open(sFileList).readlines():
# Use shlex to parse the line like a shell.
lex = shlex.shlex(l, posix=True)
lex.whitespace_split = True
lex.commenters = '#'
# No escapes, so that backslash can be part of the path
lex.escape = ''
args = list(lex)
if args:
self.processArguments(args)
def processArguments(self, args):
""" Process one command-line.
"""
saved_options = self.options
self.options = self.options.clone()
self.options.parseArgs(args[1:])
self.options.validate()
if args[0][0] == '@':
if self.options.sOutputName:
raise CogUsageError("Can't use -o with @file")
self.processFileList(args[0][1:])
else:
self.processOneFile(args[0])
self.options = saved_options
def callableMain(self, argv):
""" All of command-line cog, but in a callable form.
This is used by main.
argv is the equivalent of sys.argv.
"""
argv0 = argv.pop(0)
# Provide help if asked for anywhere in the command line.
if '-?' in argv or '-h' in argv:
print >>self.stderr, usage,
return
self.options.parseArgs(argv)
self.options.validate()
if self.options.bShowVersion:
print >>self.stdout, "Cog version %s" % __version__
return
if self.options.args:
for a in self.options.args:
self.processArguments([a])
else:
raise CogUsageError("No files to process")
def main(self, argv):
""" Handle the command-line execution for cog.
"""
try:
self.callableMain(argv)
return 0
except CogUsageError, err:
print >>self.stderr, err
print >>self.stderr, "(for help use -?)"
return 2
except CogGeneratedError, err:
print >>self.stderr, "Error: %s" % err
return 3
except CogError, err:
print >>self.stderr, err
return 1
except:
traceback.print_exc(None, self.stderr)
return 1
# History:
# 20040210: First public version.
# 20040220: Text preceding the start and end marker are removed from Python lines.
# -v option on the command line shows the version.
# 20040311: Make sure the last line of output is properly ended with a newline.
# 20040605: Fixed some blank line handling in cog.
# Fixed problems with assigning to xml elements in handyxml.
# 20040621: Changed all line-ends to LF from CRLF.
# 20041002: Refactor some option handling to simplify unittesting the options.
# 20041118: cog.out and cog.outl have optional string arguments.
# 20041119: File names weren't being properly passed around for warnings, etc.
# 20041122: Added cog.firstLineNum: a property with the line number of the [[[cog line.
# Added cog.inFile and cog.outFile: the names of the input and output file.
# 20041218: Single-line cog generators, with start marker and end marker on
# the same line.
# 20041230: Keep a single globals dict for all the code fragments in a single
# file so they can share state.
# 20050206: Added the -x switch to remove all generated output.
# 20050218: Now code can be on the marker lines as well.
# 20050219: Added -c switch to checksum the output so that edits can be
# detected before they are obliterated.
# 20050521: Added cog.error, contributed by Alexander Belchenko.
# 20050720: Added code deletion and settable globals contributed by Blake Winton.
# 20050724: Many tweaks to improve code coverage.
# 20050726: Error messages are now printed with no traceback.
# Code can no longer appear on the marker lines,
# except for single-line style.
# -z allows omission of the [[[end]]] marker, and it will be assumed
# at the end of the file.
# 20050729: Refactor option parsing into a separate class, in preparation for
# future features.
# 20050805: The cogmodule.path wasn't being properly maintained.
# 20050808: Added the -D option to define a global value.
# 20050810: The %s in the -w command is dealt with more robustly.
# Added the -s option to suffix output lines with a marker.
# 20050817: Now @files can have arguments on each line to change the cog's
# behavior for that line.
# 20051006: Version 2.0
# 20080521: -U options lets you create Unix newlines on Windows. Thanks,
# Alexander Belchenko.
# 20080522: It's now ok to have -d with output to stdout, and now we validate
# the args after each line of an @file.

288
config/doctempl.cfg Executable file
View File

@@ -0,0 +1,288 @@
# This is the config file for the documentation generator.
# (c) 2008 Andreas Rumpf
# Feel free to edit the templates as you need.
doc.section = """
<div class="section" id="$sectionID">
<h1><a class="toc-backref" href="#$sectionTitleID">$sectionTitle</a></h1>
<dl class="item">
$content
</dl></div>
"""
doc.section.toc = """
<li>
<a class="reference" href="#$sectionID" id="$sectionTitleID">$sectionTitle</a>
<ul class="simple">
$content
</ul>
</li>
"""
doc.item = """
<dt id="$itemID"><pre>$header</pre></dt>
<dd>
$desc
</dd>
"""
doc.item.toc = """
<li><a class="reference" href="#$itemID">$name</a></li>
"""
doc.toc = """
<div class="navigation">
<p class="topic-title first">Navigation</p>
<ul class="simple">
$content
</ul>
</div>"""
doc.body_toc = """
$tableofcontents
<div class="content">
$moduledesc
$content
</div>
"""
doc.body_no_toc = """
$moduledesc
$content
"""
doc.file = """<?xml version="1.0" encoding="utf-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- This file is generated by Nimrod. -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>$title</title>
<style type="text/css">
span.DecNumber {color: blue}
span.BinNumber {color: blue}
span.HexNumber {color: blue}
span.OctNumber {color: blue}
span.FloatNumber {color: blue}
span.Identifier {color: black}
span.Keyword {font-weight: bold}
span.StringLit {color: blue}
span.LongStringLit {color: blue}
span.CharLit {color: blue}
span.EscapeSequence {color: black}
span.Operator {color: black}
span.Punctation {color: black}
span.Comment, span.LongComment {font-style:italic; color: green}
span.RegularExpression {color: pink}
span.TagStart {color: yellow}
span.TagEnd {color: yellow}
span.Key {color: blue}
span.Value {color: black}
span.RawData {color: blue}
span.Assembler {color: blue}
span.Preprocessor {color: yellow}
span.Directive {color: yellow}
span.Command, span.Rule, span.Hyperlink, span.Label, span.Reference,
span.Other {color: black}
div.navigation {
float: left; width: 20em;
margin: 0; padding: 0; /*
border: 1px dashed gold; */
outline: 3px outset #99ff99; //gold;
background-color: #99ff99;
}
div.navigation ul {list-style-type: none;}
div.navigation ul li a, div.navigation ul li a:visited {
font-weight: bold;
color: #CC0000;
text-decoration: none;
}
div.navigation ul li a:hover {
font-weight: bold;
text-decoration: none;
outline: 2px outset gold;
background-color: gold; /* #779977;*/
}
div.content {
margin-left: 20em;
padding: 0 1em;
border: 1px dashed gold;
min-width: 16em;
}
dl.item dd, dl.item dd p {
margin-top:3px;
}
dl.item dd pre {
margin-left: 15pt;
border: 0px;
}
dl.item dt, dl.item dt pre {
margin: 20pt 0 0 0;
}
pre, span.tok {
background-color:#F9F9F9;
border:1px dotted #2F6FAB;
color:black;
}
/*
:Author: David Goodger
:Contact: goodger@python.org
:Date: Date: 2006-05-21 22:44:42 +0200 (Sun, 21 May 2006)
:Revision: Revision: 4564
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th { border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first { margin-top: 0 ! important }
.last, .with-subtitle { margin-bottom: 0 ! important }
.hidden { display: none }
a.toc-backref { text-decoration: none ; color: black }
blockquote.epigraph { margin: 2em 5em ; }
dl.docutils dd { margin-bottom: 0.5em }
div.abstract { margin: 2em 5em }
div.abstract p.topic-title { font-weight: bold ; text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ; border: medium outset ; padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title { font-weight: bold ; font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title { color: red ; font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication { margin: 2em 5em ; text-align: center ; font-style: italic }
div.dedication p.topic-title { font-weight: bold ; font-style: normal }
div.figure { margin-left: 2em ; margin-right: 2em }
div.footer, div.header { clear: both; font-size: smaller }
div.line-block { display: block ; margin-top: 1em ; margin-bottom: 1em }
div.line-block div.line-block { margin-top: 0 ; margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar { margin-left: 1em ; border: medium outset ;
padding: 1em ; background-color: #ffffee ; width: 40% ; float: right ;
clear: right }
div.sidebar p.rubric { font-family: sans-serif ; font-size: medium }
div.system-messages { margin: 5em }
div.system-messages h1 { color: red }
div.system-message { border: medium outset ; padding: 1em }
div.system-message p.system-message-title { color: red ; font-weight: bold }
div.topic { margin: 2em;}
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title { text-align: center }
h2.subtitle { text-align: center }
hr.docutils { width: 75% }
img.align-left { clear: left }
img.align-right { clear: right }
ol.simple, ul.simple { margin-bottom: 1em }
ol.arabic { list-style: decimal }
ol.loweralpha { list-style: lower-alpha }
ol.upperalpha { list-style: upper-alpha }
ol.lowerroman { list-style: lower-roman }
ol.upperroman { list-style: upper-roman }
p.attribution { text-align: right ; margin-left: 50% }
p.caption { font-style: italic }
p.credits { font-style: italic ; font-size: smaller }
p.label { white-space: nowrap }
p.rubric { font-weight:bold;font-size:larger;color:maroon;text-align:center}
p.sidebar-title {font-family: sans-serif ;font-weight: bold ;font-size: larger }
p.sidebar-subtitle {font-family: sans-serif ; font-weight: bold }
p.topic-title { font-weight: bold }
pre.address { margin-bottom: 0;margin-top:0;font-family:serif;font-size:100% }
pre.literal-block, pre.doctest-block {margin-left: 2em ;margin-right: 2em }
span.classifier {font-family: sans-serif;font-style: oblique }
span.classifier-delimiter {font-family: sans-serif;font-weight: bold }
span.interpreted {font-family: sans-serif }
span.option {white-space: nowrap }
span.pre {white-space: pre }
span.problematic {color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation { border-left: solid 1px gray; margin-left: 1px }
table.docinfo {margin: 2em 4em }
table.docutils {margin-top: 0.5em;margin-bottom: 0.5em }
table.footnote {border-left: solid 1px black;margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {padding-left: 0.5em;padding-right: 0.5em;
vertical-align: top}
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold;text-align: left;white-space: nowrap;padding-left: 0 }
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {font-size: 100% }
ul.auto-toc { list-style-type: none }
/*a.reference { color: #E00000; font-weight:bold;}
a.reference:hover {color: #E00000;background-color: #ffff00;display: margin;
font-weight:bold;}*/
</style>
<script type="text/javascript">
//<![CDATA[
function toggleElem(id) {
var e = document.getElementById(id);
e.style.display = e.style.display == 'none' ? 'block' : 'none';
}
var gOpen = 'none'
function toggleAll() {
gOpen = gOpen == 'none' ? 'block' : 'none';
var i = 1
while (1) {
var e = document.getElementById("m"+i)
if (!e) break;
e.style.display = gOpen
i++;
}
document.getElementById('toggleButton').value =
gOpen == 'none' ? 'Show Details' : 'Hide Details';
}
//]]>
</script>
</head>
<body>
<div class="document" id="documentId">
<h1 class="title">$title</h1>
$content
<small>Generated: $date $time UTC</small>
</div>
</body>
</html>
"""
@write "used doctempl.cfg"

150
config/nimrod.cfg Executable file
View File

@@ -0,0 +1,150 @@
# Configuration file for the Nimrod Compiler.
# Generated by the koch.py script.
# (c) 2008 Andreas Rumpf
# Feel free to edit the default values as you need.
# You may set environment variables with
# @putenv "key" "val"
# Environment variables cannot be used in the options, however!
# Just call the compiler with several options:
cc = @if unix: gcc @else: bcc @end
lib="$nimrod/lib"
path="$lib/base"
path="$lib/base/gtk"
path="$lib/base/cairo"
path="$lib/base/x11"
path="$lib/windows"
path="$lib/posix"
path="$lib/extra"
# additional defines:
#define=""
# additional options always passed to the compiler:
c_file_cache=on
line_dir=off
hint[LineTooLong]=off
hint[XDeclaredButNotUsed]=off
@if unix:
passl= "-ldl"
path = "$lib/base/gtk"
@end
@if icc:
passl = "-cxxlib"
passc = "-cxxlib"
@end
# Configuration for the Borland C++ Compiler:
@if windows:
bcc.path = r"C:\eigenes\compiler\cbuilder5\bin"
@end
bcc.options.debug = ""
# turn off warnings about unreachable code and inline procs:
bcc.options.always = "-w- -H- -q -RT- -a8 -w-8027 -w-8066"
bcc.options.speed = "-O2 -6"
bcc.options.size = "-O1 -6"
# Configuration for the Visual C/C++ compiler:
@if vcc:
@prepend_env path r"C:\Eigenes\compiler\vcc2005\Common7\IDE;"
@prepend_env INCLUDE r"C:\Eigenes\compiler\vcc2005\VC\include;C:\Eigenes\compiler\vcc2005\VC\ATLMFC\INCLUDE;"
@prepend_env LIB r"C:\Eigenes\compiler\vcc2005\VC\lib;C:\Eigenes\compiler\vcc2005\SDK\v2.0\Lib;"
#~ @prepend_env VSINSTALLDIR C:\eigenes\compiler\vcc2005
#~ @prepend_env VCINSTALLDIR C:\eigenes\compiler\vcc2005\VC
#~ @prepend_env FrameworkDir C:\WINDOWS\Microsoft.NET\Framework
#~ @prepend_env FrameworkVersion v2.0.50727
#~ @prepend_env FrameworkSDKDir C:\eigenes\compiler\vcc2005\SDK\v2.0
#~ @set DevEnvDir=C:\eigenes\compiler\vcc2005\Common7\IDE
#~ @prepend_env PATH %DevEnvDir%;%VCINSTALLDIR%\BIN;%VSINSTALLDIR%\Common7\Tools;%VSINSTALLDIR%\Common7\Tools\bin;%VCINSTALLDIR%\PlatformSDK\bin;%FrameworkSDKDir%\bin;%FrameworkDir%\%FrameworkVersion%;%VCINSTALLDIR%\VCPackages;%PATH%
#~ @prepend_env INCLUDE %VCINSTALLDIR%\ATLMFC\INCLUDE;%VCINSTALLDIR%\INCLUDE;%VCINSTALLDIR%\PlatformSDK\include;%FrameworkSDKDir%\include;%INCLUDE%
#~ @prepend_env LIB %VCINSTALLDIR%\ATLMFC\LIB;%VCINSTALLDIR%\LIB;%VCINSTALLDIR%\PlatformSDK\lib;%FrameworkSDKDir%\lib;%LIB%
#~ @prepend_env LIBPATH %FrameworkDir%\%FrameworkVersion%;%VCINSTALLDIR%\ATLMFC\LIB
@end
@if windows:
vcc.path = r"C:\Eigenes\compiler\vcc2005\VC\bin"
@end
vcc.options.debug = "/GZ /ZI"
vcc.options.always = "/nologo"
vcc.options.speed = "/Ogityb2 /G7 /arch:SSE2"
vcc.options.size = "/O1 /G7"
# Configuration for the Watcom C/C++ compiler:
@if windows:
wcc.path = r"C:\eigenes\compiler\watcom\binnt"
@end
wcc.options.debug = "-d2"
wcc.options.always = "-6 -zw -w-"
wcc.options.speed = "-ox -on -6 -d0 -fp6 -zW"
wcc.options.size = "-ox -on -6 -d0 -fp6 -zW"
# Configuration for the GNU C/C++ compiler:
@if windows:
gcc.path = r"C:\eigenes\compiler\mingw\bin"
@end
gcc.options.debug = "-g"
@if macosx:
gcc.options.always = "-Wall -g -fasm-blocks"
@else:
gcc.options.always = "-Wall -g"
@end
gcc.options.speed = "-O3 -ffast-math"
gcc.options.size = "-Os -ffast-math"
# Configuration for the Digital Mars C/C++ compiler:
@if windows:
dmc.path = r"C:\eigenes\compiler\d\dm\bin"
@end
dmc.options.debug = "-g"
dmc.options.always = "-Jm"
dmc.options.speed = "-ff -o -6"
dmc.options.size = "-ff -o -6"
# Configuration for the LCC compiler:
@if windows:
lcc.path = r"C:\eigenes\compiler\lcc\bin"
@end
lcc.options.debug = "-g5"
lcc.options.always = "-e1"
lcc.options.speed = "-O -p6"
lcc.options.size = "-O -p6"
# Configuration for the Tiny C Compiler:
@if windows:
tcc.path = r"C:\eigenes\compiler\tcc\bin"
@end
tcc.options.debug = "-b"
tcc.options.always = ""
tcc.options.speed = ""
tcc.options.size = ""
# Configuration for the Pelles C compiler:
@if windows:
pcc.path = r"C:\eigenes\compiler\pellesc\bin"
@end
pcc.options.debug = "-Zi"
pcc.options.always = "-Ze"
pcc.options.speed = "-Ox"
pcc.options.size = "-Os"
# Configuration for the LLVM GCC compiler:
@if windows:
llvm_gcc.path = r"c:\eignes\compiler\llvm-gcc\bin"
@end
llvm_gcc.options.debug = "-g"
llvm_gcc.options.always = "-w"
llvm_gcc.options.speed = "-O3 -ffast-math"
llvm_gcc.options.size = "-Os -ffast-math"
@if windows:
icc.path = r"c:\eignes\compiler\icc\bin"
@end
icc.options.debug = "-g"
icc.options.always = "-w"
icc.options.speed = "-O3 -ffast-math"
icc.options.size = "-Os -ffast-math"
@write "used default config file"

5
configure vendored Executable file
View File

@@ -0,0 +1,5 @@
#! /usr/bin/env sh
python koch.py $@ configure

43
data/advopt.txt Executable file
View File

@@ -0,0 +1,43 @@
Advanced commands::
pas convert a Pascal file to Nimrod standard syntax
pretty pretty print the inputfile
gen_depend generate a DOT file containing the
module dependency graph
list_def list all defined conditionals and exit
rst2html converts a reStructuredText file to HTML
check checks the project for syntax and semantic
parse parses a single file (for debugging Nimrod)
scan tokenizes a single file (for debugging Nimrod)
debugtrans for debugging the transformation pass
Advanced options:
-w, --warnings:on|off warnings ON|OFF
--warning[X]:on|off specific warning X ON|OFF
--hints:on|off hints ON|OFF
--hint[X]:on|off specific hint X ON|OFF
--cc:C_COMPILER set the C/C++ compiler to use
--lib:PATH set the system library path
-c, --compile_only compile only; do not assemble or link
--no_linking compile but do not link
--gen_script generate a compile script (in the 'rod_gen'
subdirectory named 'compile_$project$scriptext')
--os:SYMBOL set the target operating system (cross-compilation)
--cpu:SYMBOL set the target processor (cross-compilation)
--debuginfo enables debug information
-t, --passc:OPTION pass an option to the C compiler
-l, --passl:OPTION pass an option to the linker
--gen_mapping generate a mapping file containing
(Nimrod, mangled) identifier pairs
--merge_output generate only one C output file
--line_dir:on|off generation of #line directive ON|OFF
--checkpoints:on|off turn on|off checkpoints; for debugging Nimrod
--skip_cfg do not read the general configuration file
--skip_proj_cfg do not read the project's configuration file
--import:MODULE_FILE import the given module implicitly for each module
--maxerr:NUMBER stop compilation after NUMBER errors; broken!
--ast_cache:on|off caching of ASTs ON|OFF (default: OFF)
--c_file_cache:on|off caching of generated C files ON|OFF (default: OFF)
--index:FILE use FILE to generate a documenation index file
--putenv:key=value set an environment variable
--list_cmd list the commands used to execute external programs
-v, --verbose show what Nimrod is doing
--version show detailed version information

258
data/ast.yml Executable file
View File

@@ -0,0 +1,258 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
{
'SymFlag': [ # already 32 flags!
'sfGeneric', # whether an operator, proc or type is generic
'sfForward', # symbol is forward directed
'sfImportc', # symbol is external; imported
'sfExportc', # symbol is exported (under a specified name)
'sfVolatile', # variable is volatile
'sfUsed', # read access of sym (for warnings) or simply used
'sfWrite', # write access of variable (for hints)
'sfRegister', # variable should be placed in a register
'sfPure', # object is "pure" that means it has no type-information
'sfCodeGenerated', # wether we have already code generated for the proc
'sfPrivate', # symbol should be made private after module compilation
'sfGlobal', # symbol is at global scope
'sfResult', # variable is 'result' in proc
'sfNoSideEffect', # proc has no side effects
'sfMainModule', # module is the main module
'sfSystemModule', # module is the system module
'sfNoReturn', # proc never returns (an exit proc)
'sfReturnsNew', # proc returns new allocated thing (allows optimizations)
'sfInInterface', # symbol is in interface section declared
'sfNoStatic', # symbol is used within an iterator (needed for codegen)
# so it cannot be 'static' in the C code
# this is called 'nostatic' in the pragma section
'sfCompilerProc', # proc is a compiler proc, that is a C proc that is
# needed for the code generator
'sfCppMethod', # proc is a C++ method
'sfDiscriminant', # field is a discriminant in a record/object
'sfDeprecated', # symbol is deprecated
'sfInClosure', # variable is accessed by a closure
'sfIsCopy', # symbol is a copy; needed for proper name mangling
'sfStar', # symbol has * visibility
'sfMinus' # symbol has - visibility
],
'TypeFlag': [
'tfIsDistinct', # better use this flag to make it easier for accessing
# typeKind in the code generators
'tfGeneric', # type is a generic one
'tfExternal', # type is external
'tfImported', # type is imported from C
'tfInfoGenerated', # whether we have generated type information for this type
'tfSemChecked', # used to mark types that's semantic has been checked;
# used to prevend endless loops during semantic checking
'tfHasOutParams', # for a proc or iterator p:
# it indicates that p has out or in out parameters: this
# is used to speed up semantic checking a bit
'tfEnumHasWholes', # enum cannot be mapped into a range
'tfVarargs', # procedure has C styled varargs
'tfAssignable' # can the type be assigned to?
],
'TypeKind': [ # order is important!
# Don't forget to change hti.nim if you make a change here
'tyNone', 'tyBool', 'tyChar',
'tyEmptySet', 'tyArrayConstr', 'tyNil', 'tyRecordConstr',
'tyGeneric',
'tyGenericInst', # instantiated generic type
'tyGenericParam',
'tyEnum', 'tyAnyEnum',
'tyArray',
'tyRecord',
'tyObject',
'tyTuple',
'tySet',
'tyRange',
'tyPtr', 'tyRef',
'tyVar',
'tySequence',
'tyProc',
'tyPointer', 'tyOpenArray',
'tyString', 'tyCString', 'tyForward',
# numerical types:
'tyInt', 'tyInt8', 'tyInt16', 'tyInt32', 'tyInt64', # signed integers
'tyFloat', 'tyFloat32', 'tyFloat64', 'tyFloat128'
],
'NodeKind': [ # these are pure nodes
# order is extremely important, because ranges are used to check whether
# a node belongs to a certain class
'nkNone', # unknown node kind: indicates an error
# Expressions:
# Atoms:
'nkEmpty', # the node is empty
'nkIdent', # node is an identifier
'nkSym', # node is a symbol
'nkType', # node is used for its typ field
'nkCharLit', # a character literal ''
'nkRCharLit', # a raw character literal r''
'nkIntLit', # an integer literal
'nkInt8Lit',
'nkInt16Lit',
'nkInt32Lit',
'nkInt64Lit',
'nkFloatLit', # a floating point literal
'nkFloat32Lit',
'nkFloat64Lit',
'nkStrLit', # a string literal ""
'nkRStrLit', # a raw string literal r""
'nkTripleStrLit', # a triple string literal """
'nkNilLit', # the nil literal
# end of atoms
'nkDotCall', # used to temporarily flag a nkCall node; this is used
# for transforming ``s.len`` to ``len(s)``
'nkCommand', # a call like ``p 2 4`` without parenthesis
'nkCall', # a call like p(x, y) or an operation like +(a, b)
'nkGenericCall', # a call with given type parameters
'nkExplicitTypeListCall', # a call with given explicit typelist
'nkExprEqExpr', # a named parameter with equals: ''expr = expr''
'nkExprColonExpr', # a named parameter with colon: ''expr: expr''
'nkIdentDefs', # a definition like `a, b: typeDesc = expr`
# either typeDesc or expr may be nil; used in
# formal parameters, var statements, etc.
'nkInfix', # a call like (a + b)
'nkPrefix', # a call like !a
'nkPostfix', # something like a! (also used for visibility)
'nkPar', # syntactic ()
'nkCurly', # syntactic {}
'nkBracket', # syntactic []
'nkBracketExpr', # an expression like a[i..j, k]
'nkPragmaExpr', # an expression like a{.pragmas.}
'nkRange', # an expression like i..j
'nkDotExpr', # a.b
'nkCheckedFieldExpr', # a.b, but b is a field that needs to be checked
'nkDerefExpr', # a^
'nkIfExpr', # if as an expression
'nkElifExpr',
'nkElseExpr',
'nkLambda', # lambda expression
'nkAccQuoted', # `a` as a node
'nkHeaderQuoted', # `a(x: int)` as a node
'nkSetConstr', # a set constructor {}
'nkConstSetConstr', # a set constructor with only constant expressions
'nkArrayConstr', # an array constructor []
'nkConstArrayConstr', # an array constructor with only constant expressions
'nkRecordConstr', # a record constructor []
'nkConstRecordConstr', # a record constructor with only constant expressions
'nkTableConstr', # a table constructor {expr: expr}
'nkConstTableConstr', # a table constructor with only constant expressions
'nkQualified', # describes a.b for qualified identifiers
'nkHiddenStdConv', # an implicit standard type conversion
'nkHiddenSubConv', # an implicit type conversion from a subtype
# to a supertype
'nkHiddenCallConv', # an implicit type conversion via a type converter
'nkConv', # a type conversion
'nkCast', # a type cast
'nkAddr', # a addr expression
# end of expressions
'nkAsgn', # a = b
'nkDefaultTypeParam', # `ident = typeDesc` in generic parameters
'nkGenericParams', # generic parameters
'nkFormalParams', # formal parameters
'nkOfInherit', # inherited from symbol
'nkModule', # the syntax tree of a module
'nkProcDef', # a proc
'nkConverterDef', # a converter
'nkMacroDef', # a macro
'nkTemplateDef', # a template
'nkIteratorDef', # an iterator
'nkOfBranch', # used inside case statements for (cond, action)-pairs
'nkElifBranch', # used in if statements
'nkExceptBranch', # an except section
'nkElse', # an else part
'nkMacroStmt', # a macro statement
'nkAsmStmt', # an assembler block
'nkPragma', # a pragma statement
'nkIfStmt', # an if statement
'nkWhenStmt', # a when statement
'nkForStmt', # a for statement
'nkWhileStmt', # a while statement
'nkCaseStmt', # a case statement
'nkVarSection', # a var section
'nkConstSection', # a const section
'nkConstDef', # a const definition
'nkTypeSection', # a type section (consists of type definitions)
'nkTypeDef', # a type definition
'nkYieldStmt', # the yield statement as a tree
'nkTryStmt', # a try statement
'nkFinally', # a finally section
'nkRaiseStmt', # a raise statement
'nkReturnStmt', # a return statement
'nkBreakStmt', # a break statement
'nkContinueStmt', # a continue statement
'nkBlockStmt', # a block statement
'nkGotoStmt', # used by the transformation pass; first son is a sym
# node containing a label
'nkDiscardStmt', # a discard statement
'nkStmtList', # a list of statements
'nkImportStmt', # an import statement
'nkFromStmt', # a from * import statement
'nkImportAs', # an `import xyx as abc` section
'nkIncludeStmt', # an include statement
'nkAccessStmt', # used internally for iterators
'nkCommentStmt', # a comment statement
'nkStmtListExpr', # a statement list followed by an expr; this is used
# to allow powerful multi-line templates
'nkBlockExpr', # a statement block ending in an expr; this is used
# to allowe powerful multi-line templates that open a
# temporary scope
'nkVm', # indicates a virtual instruction; integer field is
# used for the concrete opcode
# types as syntactic trees:
'nkTypeOfExpr',
'nkRecordTy',
'nkObjectTy',
'nkRecList', # list of record/object parts
'nkRecCase', # case section of record/object
'nkRecWhen', # when section of record/object
'nkRefTy',
'nkPtrTy',
'nkVarTy',
'nkProcTy',
'nkEnumTy',
'nkEnumFieldDef' # `ident = expr` in an enumeration
],
'SymKind': [
# the different symbols (start with the prefix sk);
# order is important for the documentation generator!
'skUnknownSym', # unknown symbol: used for parsing assembler blocks
'skConditional', # symbol for the preprocessor (may become obsolete)
'skDynLib', # symbol represents a dynamic library; this is used
# internally; it does not exist in Nimrod code
'skParam', # a parameter
'skTypeParam', # a type parameter; example: proc x[T]() <- `T`
'skTemp', # a temporary variable (introduced by compiler)
'skType', # a type
'skConst', # a constant
'skVar', # a variable
'skProc', # a proc
'skIterator', # an iterator
'skConverter', # a type converter
'skMacro', # a macro
'skTemplate', # a template
'skField', # a field in a record or object
'skEnumField', # an identifier in an enum
'skForVar', # a for loop variable
'skModule', # module identifier
'skLabel' # a label (for block statement)
]
}

29
data/basicopt.txt Executable file
View File

@@ -0,0 +1,29 @@
Usage::
nimrod command [options] inputfile [arguments]
Command::
compile compile project with default code generator (C)
compile_to_c compile project with C code generator
compile_to_cpp compile project with C++ code generator
doc generate the documentation for inputfile;
with --run switch opens it with $BROWSER
Arguments:
arguments are passed to the program being run (if --run option is selected)
Options:
-p, --path:PATH add path to search paths
-o, --out:FILE set the output filename
-d, --define:SYMBOL define a conditional symbol
-u, --undef:SYMBOL undefine a conditional symbol
-b, --force_build force rebuilding of all modules
--stack_trace:on|off code generation for stack trace ON|OFF
--line_trace:on|off code generation for line trace ON|OFF
--debugger:on|off turn Embedded Nimrod Debugger ON|OFF
-x, --checks:on|off code generation for all runtime checks ON|OFF
--range_checks:on|off code generation for range checks ON|OFF
--bound_checks:on|off code generation for bound checks ON|OFF
--overflow_checks:on|off code generation for over-/underflow checks ON|OFF
-a, --assertions:on|off code generation for assertions ON|OFF
--opt:none|speed|size optimize not at all or for speed|size
--app:console|gui|lib generate a console|GUI application or a shared lib
-r, --run run the compiled program with given arguments
--advanced show advanced command line switches
-h, --help show this help

1692
data/ccomps.txt Executable file

File diff suppressed because it is too large Load Diff

22
data/changes.txt Executable file
View File

@@ -0,0 +1,22 @@
0.1.0
* new config system
* new build system
* source renderer
* pas2nim integrated
* support for C++
* local variables are always initialized
* Rod file reader and writer
* new --out, -o command line options
* fixed bug in nimconf.pas: we now have several
string token types
* changed nkIdentDef to nkIdentDefs
* added type(expr) in the parser and the grammer
* added template
* added command calls
* added case in records/objects
* added --skip_proj_cfg switch for nim.dpr
* added missing features to pasparse
* rewrote the source generator
* ``addr`` and ``cast`` are now keywords; grammar updated
* implemented ` notation; grammar updated
* specification replaced by a manual

19
data/keywords.txt Executable file
View File

@@ -0,0 +1,19 @@
addr and as asm
block break
case cast const continue converter
discard div
elif else end enum except exception
finally for from generic
if implies import in include is isnot iterator
lambda
macro method mod
nil not notin
object of or out
proc ptr
raise record ref return
shl shr
template try type
var
when where while with without
xor
yield

176
data/magic.yml Executable file
View File

@@ -0,0 +1,176 @@
# All the magics of the system module:
# order has been changed!
[
'None',
'Defined',
'New',
'NewFinalize',
'Low',
'High',
'SizeOf',
'RegisterFinalizer',
'Succ',
'Pred',
'Inc',
'Dec',
'LengthOpenArray',
'LengthStr',
'LengthArray',
'LengthSeq',
'Incl',
'Excl',
'Card',
'Ord',
'Chr',
# binary arithmetic with and without overflow checking:
'AddI',
'SubI',
'MulI',
'DivI',
'ModI',
'AddI64',
'SubI64',
'MulI64',
'DivI64',
'ModI64',
# other binary arithmetic operators:
'ShrI',
'ShlI',
'BitandI',
'BitorI',
'BitxorI',
'MinI',
'MaxI',
'ShrI64',
'ShlI64',
'BitandI64',
'BitorI64',
'BitxorI64',
'MinI64',
'MaxI64',
'AddF64',
'SubF64',
'MulF64',
'DivF64',
'MinF64',
'MaxF64',
'AddU',
'SubU',
'MulU',
'DivU',
'ModU',
'AddU64',
'SubU64',
'MulU64',
'DivU64',
'ModU64',
# comparison operators:
'EqI',
'LeI',
'LtI',
'EqI64',
'LeI64',
'LtI64',
'EqF64',
'LeF64',
'LtF64',
'LeU',
'LtU',
'LeU64',
'LtU64',
'EqEnum',
'LeEnum',
'LtEnum',
'EqCh',
'LeCh',
'LtCh',
'EqB',
'LeB',
'LtB',
'EqRef',
'EqProc',
'EqUntracedRef',
'LePtr',
'LtPtr',
'EqCString',
'Xor',
# unary arithmetic with and without overflow checking:
'UnaryMinusI',
'UnaryMinusI64',
'AbsI',
'AbsI64',
# other unary operations:
'Not',
'UnaryPlusI',
'BitnotI',
'UnaryPlusI64',
'BitnotI64',
'UnaryPlusF64',
'UnaryMinusF64',
'AbsF64',
'Ze',
'Ze64',
'ToU8',
'ToU16',
'ToU32',
'ToFloat',
'ToBiggestFloat',
'ToInt',
'ToBiggestInt',
# special ones:
'And',
'Or',
'EqStr',
'LeStr',
'LtStr',
'EqSet',
'LeSet',
'LtSet',
'MulSet',
'PlusSet',
'MinusSet',
'SymDiffSet',
'ConStrStr',
'ConArrArr',
'ConArrT',
'ConTArr',
'ConTT',
'Slice',
'AppendStrCh',
'AppendStrStr',
'AppendSeqElem',
'AppendSeqSeq',
'InRange',
'InSet',
'Is',
'Asgn',
'Repr',
'Exit',
'SetLengthStr',
'SetLengthSeq',
'Assert',
'Swap',
# magic type constructors:
'Array',
'OpenArray',
'Range',
'Tuple',
'Set',
'Seq',
# magic constants:
'CompileDate',
'CompileTime',
'NimrodVersion',
'NimrodMajor',
'NimrodMinor',
'NimrodPatch',
'CpuEndian'
]

282
data/messages.yml Executable file
View File

@@ -0,0 +1,282 @@
# This file contains all the messages of the Nimrod compiler
# (c) 2008 Andreas Rumpf
[
# fatal errors:
{'errUnknown': 'unknown error'},
{'errIllFormedAstX': 'illformed AST: $1'},
{'errCannotOpenFile': "cannot open '$1'"},
{'errInternal': 'internal error: $1'},
# other errors:
{'errGenerated': '$1'},
{'errXCompilerDoesNotSupportCpp': "'$1' compiler does not support C++"},
# errors:
{'errStringLiteralExpected': 'string literal expected'},
{'errIntLiteralExpected': 'integer literal expected'},
{'errInvalidCharacterConstant': 'invalid character constant'},
{'errClosingTripleQuoteExpected':
'closing """ expected, but end of file reached'},
{'errClosingQuoteExpected': 'closing " expected'},
{'errTabulatorsAreNotAllowed': 'tabulators are not allowed'},
{'errInvalidToken': 'invalid token: $1'},
{'errLineTooLong': 'line too long'},
{'errInvalidNumber': '$1 is not a valid number'},
{'errNumberOutOfRange': '$1 is too large or too small'},
{'errNnotAllowedInCharacter': '\\n not allowed in character literal'},
{'errClosingBracketExpected': "closing ']' expected, but end of file reached"},
{'errMissingFinalQuote': "missing final '"},
{'errIdentifierExpected': "identifier expected, but found '$1'"},
{'errOperatorExpected': "operator expected, but found '$1'"},
{'errTokenExpected': "'$1' expected"},
{'errStringAfterIncludeExpected': "string after 'include' expected"},
{'errRecursiveInclude': "recursive include file: '$1'"},
{'errAtIfExpected': "'@if' expected"},
{'errAtIfExpectedBeforeElse': "'@if' expected before '@else'"},
{'errAtIfExpectedBeforeElif': "'@if' expected before '@elif'"},
{'errAtEndExpected': "'@end' expected"},
{'errOnOrOffExpected': "'on' or 'off' expected"},
{'errNoneSpeedOrSizeExpected': "'none', 'speed' or 'size' expected"},
{'errInvalidPragma': 'invalid pragma'},
{'errUnknownPragma': "unknown pragma: '$1'"},
{'errPragmaXHereNotAllowed': "pragma '$1' here not allowed"},
{'errUnknownDirective': "unknown directive: '$1'"},
{'errInvalidDirective': 'invalid directive'},
{'errAtPopWithoutPush': "'pop' without a 'push' pragma"},
{'errEmptyAsm': 'empty asm statement makes no sense'},
{'errAsgnInvalidInExpr': "'=' invalid in an expression; probably '==' meant"},
{'errInvalidIndentation': 'invalid indentation'},
{'errExceptionExpected': 'exception expected'},
{'errExceptionAlreadyHandled': 'exception already handled'},
{'errReturnNotAllowedHere': "'return' only allowed in routine"},
{'errYieldNotAllowedHere': "'yield' only allowed in iterator"},
{'errInvalidNumberOfYieldExpr': "invalid number of 'yield' expresions"},
{'errReturnInvalidInIterator': "'return' not allowed in iterator"},
{'errCannotReturnExpr': 'current routine cannot return an expression'},
{'errAttemptToRedefine': "attempt to redefine '$1'"},
{'errStmtInvalidAfterReturn':
"statement not allowed after 'return', 'break' or 'raise'"},
{'errStmtExpected': 'statement expected'},
{'errYieldOnlyInInterators': "'yield' statement is only allowed in iterators"},
{'errInvalidLabel': "'$1' is no label"},
{'errInvalidCmdLineOption': "invalid command line option: '$1'"},
{'errCmdLineArgExpected': "argument for command line option expected: '$1'"},
{'errInvalidVarSubstitution': "invalid variable substitution in '$1'"},
{'errUnknownVar': "unknown variable: '$1'"},
{'errUnknownCcompiler': "unknown C compiler: '$1'"},
{'errOnOrOffExpectedButXFound': "'on' or 'off' expected, but '$1' found"},
{'errNoneBoehmRefcExpectedButXFound':
"'none', 'boehm' or 'refc' expected, but '$1' found"},
{'errNoneSpeedOrSizeExpectedButXFound':
"'none', 'speed' or 'size' expected, but '$1' found"},
{'errGuiConsoleOrLibExpectedButXFound':
"'gui', 'console' or 'lib' expected, but '$1' found"},
{'errUnknownOS': "unknown OS: '$1'"},
{'errUnknownCPU': "unknown CPU: '$1'"},
{'errGenOutExpectedButXFound':
"'c', 'c++' or 'yaml' expected, but '$1' found"},
{'errArgsNeedRunOption':
"arguments can only be given if the '--run' option is selected"},
{'errInvalidMultipleAsgn': 'multiple assignment is not allowed'},
{'errColonOrEqualsExpected': "':' or '=' expected, but found '$1'"},
{'errExprExpected': "expression expected, but found '$1'"},
{'errUndeclaredIdentifier': "undeclared identifier: '$1'"},
{'errUseQualifier': "ambigious identifier: '$1' -- use a qualifier"},
{'errTwiceForwarded': "'$1' is forwarded twice"},
{'errTypeExpected': 'type expected'},
{'errSystemNeeds': "system module needs '$1'"},
{'errExecutionOfProgramFailed': 'execution of an external program failed'},
{'errNotOverloadable': "overloaded '$1' leads to ambigious calls"},
{'errInvalidArgForX': "invalid argument for '$1'"},
{'errStmtHasNoEffect': 'statement has no effect'},
{'errXExpectsTypeOrValue': "'$1' expects a type or value"},
{'errXExpectsArrayType': "'$1' expects an array type"},
{'errIteratorCannotBeInstantiated':
"'$1' cannot be instantiated because its body has not been compiled yet"},
{'errExprWithNoTypeCannotBeConverted':
'expression with no type cannot be converted'},
{'errExprWithNoTypeCannotBeCasted': 'expression with no type cannot be casted'},
{'errConstantDivisionByZero': 'constant division by zero'},
{'errOrdinalTypeExpected': 'ordinal type expected'},
{'errOrdinalOrFloatTypeExpected': 'ordinal or float type expected'},
{'errOverOrUnderflow': 'over- or underflow'},
{'errCannotEvalXBecauseIncompletelyDefined':
"cannot evalutate '$1' because type is not defined completely"},
{'errChrExpectsRange0_255': "'chr' expects an int in the range 0..255"},
{'errStaticAssertFailed': "'staticAssert' failed: condition is false"},
{'errStaticAssertCannotBeEval':
"argument to 'staticAssert' cannot be evaluated at compile time"},
{'errDotRequiresRecordOrObjectType': "'.' requires a record or object type"},
{'errUndeclaredFieldX': "undeclared field: '$1'"},
{'errIndexNoIntType': 'index has to be an integer type'},
{'errIndexOutOfBounds': 'index out of bounds'},
{'errIndexTypesDoNotMatch': 'index types do not match'},
{'errBracketsInvalidForType': "'[]' operator invalid for this type"},
{'errValueOutOfSetBounds': 'value out of set bounds'},
{'errFieldInitTwice': "field initialized twice: '$1'"},
{'errFieldNotInit': "field '$1' not initialized"},
{'errExprCannotBeCalled': 'expression cannot be called'},
{'errExprHasNoType': 'expression has no type'},
{'errExprXHasNoType': "expression '$1' has no type"},
{'errCastNotInSafeMode': "'cast' not allowed in safe mode"},
{'errExprCannotBeCastedToX': 'expression cannot be casted to $1'},
{'errUndefinedPrefixOpr': 'undefined prefix operator: $1'},
{'errCommaOrParRiExpected': "',' or ')' expected"},
{'errCurlyLeOrParLeExpected': "'{' or '(' expected"},
{'errSectionExpected': "section ('type', 'proc', etc.) expected"},
{'errImplemenationExpected': "'implementation' or end of file expected"},
{'errRangeExpected': 'range expected'},
{'errInvalidTypeDescription': 'invalid type description'},
{'errAttemptToRedefineX': "attempt to redefine '$1'"},
{'errMagicOnlyInSystem': "'magic' only allowed in system module"},
{'errUnknownOperatorX': "unkown operator: '$1'"},
{'errPowerOfTwoExpected': 'power of two expected'},
{'errStringMayNotBeEmpty': 'string literal may not be empty'},
{'errCallConvExpected': 'calling convention expected'},
{'errProcOnlyOneCallConv': 'a proc can only have one calling convention'},
{'errSymbolMustBeImported': "symbol must be imported if 'lib' pragma is used"},
{'errExprMustBeBool': "expression must be of type 'bool'"},
{'errConstExprExpected': 'constant expression expected'},
{'errDuplicateCaseLabel': 'duplicate case label'},
{'errRangeIsEmpty': 'range is empty'},
{'errSelectorMustBeOfCertainTypes':
'selector must be of an ordinal type, real or string'},
{'errSelectorMustBeOrdinal':
'selector must be of an ordinal type'},
{'errOrdXMustNotBeNegative': 'ord($1) must not be negative'},
{'errLenXinvalid': 'len($1) must be less than 32768'},
{'errWrongNumberOfLoopVariables': 'wrong number of loop variables'},
{'errExprCannotBeRaised': 'only objects can be raised'},
{'errBreakOnlyInLoop': "'break' only allowed in loop construct"},
{'errTypeXhasUnknownSize': "type '$1' has unknown size"},
{'errConstNeedsConstExpr':
'a constant can only be initialized with a constant expression'},
{'errConstNeedsValue': 'a constant needs a value'},
{'errResultCannotBeOpenArray': 'the result type cannot be on open array'},
{'errSizeTooBig': "computing the type's size produced an overflow"},
{'errSetTooBig': 'set is too large'},
{'errBaseTypeMustBeOrdinal': 'base type of a set must be an ordinal'},
{'errInheritanceOnlyWithObjects': 'inheritance only works with an object'},
{'errInheritanceOnlyWithEnums': 'inheritance only works with an enum'},
{'errIllegalRecursionInTypeX': "illegal recursion in type '$1'"},
{'errCannotInstantiateX': "cannot instantiate: '$1'"},
{'errExprHasNoAddress': 'expression has no address'},
{'errVarForOutParamNeeded':
'to an out parameter a variable needs to be passed'},
{'errPureTypeMismatch': 'type mismatch'},
{'errTypeMismatch': 'type mismatch: got ('},
{'errButExpected': 'but expected one of: '},
{'errButExpectedX': "but expected '$1'"},
{'errAmbigiousCallXYZ': 'ambigious call; both $1 and $2 match for: $3'},
{'errWrongNumberOfTypeParams': 'wrong number of type parameters'},
{'errOutParamNoDefaultValue': 'out parameters cannot have default values'},
{'errInlineProcHasNoAddress': 'an inline proc has no address'},
{'errXCannotBeInParamDecl': '$1 cannot be declared in parameter declaration'},
{'errPragmaOnlyInHeaderOfProc':
'pragmas are only in the header of a proc allowed'},
{'errImportedProcCannotHaveImpl':
'an imported proc cannot have an implementation'},
{'errImplOfXNotAllowed': "implementation of '$1' is not allowed here"},
{'errImplOfXexpected': "implementation of '$1' expected"},
{'errDiscardValue': 'value returned by statement has to be discarded'},
{'errInvalidDiscard': 'statement returns no value that can be discarded'},
{'errUnknownPrecedence':
"unknown precedence for operator; use 'infix: prec' pragma"},
{'errIllegalConvFromXtoY': 'conversion from $1 to $2 is invalid'},
{'errTypeMismatchExpectedXGotY': "type mismatch: expected '$1', but got '$2'"},
{'errCannotBindXTwice': "cannot bind parameter '$1' twice"},
{'errInvalidOrderInEnumX': "invalid order in enum '$1'"},
{'errEnumXHasWholes': "enum '$1' has wholes"},
{'errExceptExpected': "'except' or 'finally' expected"},
{'errInvalidTry': "after catch all 'except' or 'finally' no section may follow"},
{'errEofExpectedButXFound': "end of file expected, but found token '$1'"},
{'errOptionExpected': "option expected, but found '$1'"},
{'errCannotEvaluateForwardConst': 'cannot evaluate forwarded constant'},
{'errXisNoLabel': "'$1' is not a label"},
{'errXNeedsConcreteType': "'$1' needs to be of a non-generic type"},
{'errNotAllCasesCovered': 'not all cases are covered'},
{'errStringRange': 'string range in case statement not allowed'},
{'errUnkownSubstitionVar': "unknown substitution variable: '$1'"},
{'errComplexStmtRequiresInd': 'complex statement requires indentation'},
{'errXisNotCallable': "'$1' is not callable"},
{'errNoPragmasAllowedForX': 'no pragmas allowed for $1'},
{'errNoGenericParamsAllowedForX': 'no generic parameters allowed for $1'},
{'errInvalidParamKindX': "invalid param kind: '$1'"},
{'errDefaultArgumentInvalid': 'default argument invalid'},
{'errNamedParamHasToBeIdent': 'named parameter has to be an identifier'},
{'errNoReturnTypeForX': 'no return type for $1 allowed'},
{'errConvNeedsOneArg': 'a type conversion needs exactly one argument'},
{'errInvalidPragmaX': 'invalid pragma: $1'},
{'errXNotAllowedHere': '$1 here not allowed'},
{'errInvalidControlFlowX': 'invalid control flow: $1'},
{'errATypeHasNoValue': 'a type has no value'},
{'errXisNoType': "'$1' is no type"},
{'errCircumNeedsPointer': "'^' needs a pointer or reference type"},
{'errInvalidContextForBuiltinX': "invalid context for builtin '$1'"},
{'errInvalidExpression': 'invalid expression'},
{'errInvalidExpressionX': "invalid expression: '$1'"},
{'errEnumHasNoValueX': "enum has no value '$1'"},
{'errNamedExprExpected': 'named expression expected'},
{'errNamedExprNotAllowed': 'named expression here not allowed'},
{'errXExpectsOneTypeParam': "'$1' expects one type parameter"},
{'errArrayExpectsTwoTypeParams': 'array expects two type parameters'},
{'errInvalidVisibilityX': "invalid invisibility: '$1'"},
{'errInitHereNotAllowed': 'initialization here not allowed'},
{'errXCannotBeAssignedTo': "'$1' cannot be assigned to"},
{'errIteratorNotAllowed':
"iterators can only be defined at the module's top level"},
{'errIteratorNeedsImplementation': 'iterator needs an implementation'},
{'errIteratorNeedsReturnType': 'iterator needs a return type'},
{'errInvalidCommandX': "invalid command: '$1'"},
{'errXOnlyAtModuleScope': "'$1' is only allowed at top level"},
{'errTypeXNeedsImplementation': "type '$1' needs an implementation"},
{'errTemplateInstantiationTooNested': 'template instantiation too nested'},
{'errInstantiationFrom': 'instantiation from here'},
{'errInvalidIndexValueForTuple': 'invalid index value for tuple subscript'},
{'errCommandExpectsFilename': 'command expects a filename argument'},
{'errXExpected': "'$1' expected"},
{'errInvalidSectionStart': 'invalid section start'},
{'errGridTableNotImplemented': 'grid table is not implemented'},
{'errGeneralParseError': 'general parse error'},
{'errNewSectionExpected': 'new section expected'},
{'errWhitespaceExpected': "whitespace expected, got '$1'"},
{'errXisNoValidIndexFile': "'$1' is no valid index file"},
{'errCannotRenderX': "cannot render reStructuredText element '$1'"},
# user error message:
{'errUser': '$1'},
# warnings:
{'warnCannotOpenFile': "cannot open '$1'"},
{'warnOctalEscape':
'octal escape sequences do not exist; leading zero is ignored'},
{'warnXIsNeverRead': "'$1' is never read"},
{'warnXmightNotBeenInit': "'$1' might not have been initialized"},
{'warnCannotWriteMO2': "cannot write file '$1'"},
{'warnCannotReadMO2': "cannot read file '$1'"},
{'warnDeprecated': "'$1' is deprecated"},
{'warnSmallLshouldNotBeUsed':
"'l' should not be used as an identifier; may look like '1' (one)"},
{'warnUnknownMagic': "unknown magic '$1' might crash the compiler"},
{'warnRedefinitionOfLabel': "redefinition of label '$1'"},
{'warnUnknownSubstitutionX': "unknown substitution '$1'"},
{'warnLanguageXNotSupported': "language '$1' not supported"},
{'warnCommentXIgnored': "comment '$1' ignored"},
# user warning message:
{'warnUser': '$1'},
# hints:
{'hintSuccess': 'operation successful'},
{'hintLineTooLong': 'line too long'},
{'hintXDeclaredButNotUsed': "'$1' is declared but not used"},
{'hintConvToBaseNotNeeded': 'conversion to base object is not needed'},
{'hintConvFromXtoItselfNotNeeded': 'conversion from $1 to itself is pointless'},
{'hintExprAlwaysX': "expression evaluates always to '$1'"},
{'hintMo2FileInvalid': "mo2 file '$1' is invalid"},
{'hintModuleHasChanged': "module '$1' has been changed"},
{'hintCannotOpenMo2File': "mo2 file '$1' does not exist"},
# user hint message:
{'hintUser': '$1'}
]

26
data/pas_keyw.yml Executable file
View File

@@ -0,0 +1,26 @@
# Object Pascal keywords for the Pascal scanner that is part of the
# Nimrod distribution
# (c) Andreas Rumpf 2007
[
"and", "array", "as", "asm",
"begin",
"case", "class", "const", "constructor",
"destructor", "div", "do", "downto",
"else", "end", "except", "exports",
"finalization", "finally", "for", "function",
"goto",
"if", "implementation", "in", "inherited", "initialization", "inline",
"interface", "is",
"label", "library",
"mod",
"nil", "not",
"object", "of", "or", "out",
"packed", "procedure", "program", "property",
"raise", "record", "repeat", "resourcestring",
"set", "shl", "shr",
"then", "threadvar", "to", "try", "type",
"unit", "until", "uses",
"var",
"while", "with",
"xor"
]

5
data/readme.txt Executable file
View File

@@ -0,0 +1,5 @@
This directory contains data files in a format called YAML_. These files
are required for building Nimrod.
.. _YAML: http://www.yaml.org/

1
dist/empty.txt vendored Executable file
View File

@@ -0,0 +1 @@
This file keeps several tools from deleting this subdirectory.

26
doc/docs.txt Executable file
View File

@@ -0,0 +1,26 @@
"Incorrect documentation is often worse than no documentation."
-- Bertrand Meyer
The documentation consists of several documents:
- | `Nimrod manual <manual.html>`_
| Read this to get to know the Nimrod programming system.
- | `User guide for the Nimrod Compiler <nimrodc.html>`_
| The user guide lists command line arguments, Nimrodc's special features, etc.
- | `User guide for the Embedded Nimrod Debugger <endb.html>`_
| This document describes how to use the Embedded debugger. The embedded
debugger currently has no GUI. Please help!
- | `Nimrod library documentation <lib.html>`_
| This document describes Nimrod's standard library.
- | `Nimrod internal documentation <intern.html>`_
| The internal documentation describes how the compiler is implemented. Read
this if you want to hack the compiler or develop advanced macros.
- | `Index <theindex.html>`_
| The generated index. Often the quickest way to find the piece of
information you need.

174
doc/endb.txt Executable file
View File

@@ -0,0 +1,174 @@
===========================================
Embedded Nimrod Debugger User Guide
===========================================
:Author: Andreas Rumpf
:Version: |nimrodversion|
.. contents::
Nimrod comes with a platform independant debugger -
the `Embedded Nimrod Debugger`:idx: (`ENDB`:idx:). The debugger is
*embedded* into your executable if it has been
compiled with the ``--debugger:on`` command line option.
This also defines the conditional symbol ``ENDB`` for you.
Note: You must not compile your program with the ``--app:gui``
command line option because then there is no console
available for the debugger.
If you start your program the debugger will immediately show
a prompt on the console. You can now enter a command. The next sections
deal with the possible commands. As usual for Nimrod for all commands
underscores and case do not matter. Optional components of a command
are listed in brackets ``[...]`` here.
General Commands
================
``h``, ``help``
Display a quick reference of the possible commands.
``q``, ``quit``
Quit the debugger and the program.
<ENTER>
(Without any typed command) repeat the previous debugger command.
If there is no previous command, ``step_into`` is assumed.
Executing Commands
==================
``s``, ``step_into``
Single step, stepping into routine calls.
``n``, ``step_over``
Single step, without stepping into routine calls.
``f``, ``skip_current``
Continue execution until the current routine finishes.
``c``, ``continue``
Continue execution until the next breakpoint.
``i``, ``ignore``
Continue execution, ignore all breakpoints. This is effectively quitting
the debugger and runs the program until it finishes.
Breakpoint Commands
===================
``b``, ``setbreak`` <identifier> [fromline [toline]] [file]
Set a new breakpoint named 'identifier' for the given file
and line numbers. If no file is given, the current execution point's
filename is used. If the filename has no extension, ``.nim`` is
appended for your convenience.
If no line numbers are given, the current execution point's
line is used. If both ``fromline`` and ``toline`` are given the
breakpoint contains a line number range. Some examples if it is still
unclear:
* ``b br1 12 15 thallo`` creates a breakpoint named ``br1`` that
will be triggered if the instruction pointer reaches one of the
lines 12-15 in the file ``thallo.nim``.
* ``b br1 12 thallo`` creates a breakpoint named ``br1`` that
will be triggered if the instruction pointer reaches the
line 12 in the file ``thallo.nim``.
* ``b br1 12`` creates a breakpoint named ``br1`` that
will be triggered if the instruction pointer reaches the
line 12 in the current file.
* ``b br1`` creates a breakpoint named ``br1`` that
will be triggered if the instruction pointer reaches the
current line in the current file again.
``breakpoints``
Display the entire breakpoint list.
``disable`` <identifier>
Disable a breakpoint. It remains disabled until you turn it on again
with the ``enable`` command.
``enable`` <identifier>
Enable a breakpoint.
Often it happens when debugging that you keep retyping the breakpoints again
and again because they are lost when you restart your program. This is not
necessary: A special pragma has been defined for this:
The ``{.breakpoint.}`` pragma
-----------------------------
The `breakpoint`:idx: pragma is syntactically a statement. It can be used
to mark the *following line* as a breakpoint:
.. code-block:: Nimrod
write("1")
{.breakpoint: "before_write_2".}
write("2")
The name of the breakpoint here is ``before_write_2``. Of course the
breakpoint's name is optional - the compiler will generate one for you
if you leave it out.
Code for the ``breakpoint`` pragma is only generated if the debugger
is turned on, so you don't need to remove it from your source code after
debugging.
Data Display Commands
=====================
``e``, ``eval`` <exp>
Evaluate the expression <exp>. Note that ENDB has no full-blown expression
evaluator built-in. So expressions are limited:
* To display global variables prefix their names with their
owning module: ``nim1.globalVar``
* To display local variables or parameters just type in
their name: ``localVar``. If you want to inspect variables that are not
in the current stack frame, use the ``up`` or ``down`` command.
Unfortunately, only inspecting variables is possible at the moment. Maybe
a future version will implement a full-blown Nimrod expression evaluator,
but this is not easy to do and would bloat the debugger's code.
Since displaying the whole data structures is often not needed and
painfully slow, the debugger uses a *maximal display depth* concept for
displaying.
You can alter the *maximal display depth* with the ``maxdisplay``
command.
``maxdisplay`` <natural>
Sets the maximal display depth to the given integer value. A value of 0
means there is no maximal display depth. Default is 3.
``o``, ``out`` <filename> <exp>
Evaluate the expression <exp> and store its string representation into a
file named <filename>. If the file does not exist, it will be created,
otherwise it will be opened for appending.
``w``, ``where``
Display the current execution point.
``u``, ``up``
Go up in the call stack.
``d``, ``down``
Go down in the call stack.
``stackframe`` [file]
Displays the content of the current stack frame in ``stdout`` or
appends it to the file, depending on whether a file is given.
``callstack``
Display the entire call stack (but not its content).
``l``, ``locals``
Display the available local variables in the current stack frame.
``g``, ``globals``
Display all the global variables that are available for inspection.

44
doc/filelist.txt Executable file
View File

@@ -0,0 +1,44 @@
Short description of Nimrod's modules
-------------------------------------
============== ==========================================================
Module Description
============== ==========================================================
lexbase buffer handling of the lexical analyser
scanner lexical analyser
ast type definitions of the abstract syntax tree (AST) and
node constructors
astalgo algorithms for containers of AST nodes; converting the
AST to YAML; the symbol table
trees few algorithms for nodes; this module is less important
types module for traversing type graphs; also contain several
helpers for dealing with types
sigmatch contains the matching algorithm that is used for proc
calls
semexprs contains the semantic checking phase for expressions
semstmts contains the semantic checking phase for statements
semtypes contains the semantic checking phase for types
idents implements a general mapping from identifiers to an internal
representation (``PIdent``) that is used, so that a simple
pointer comparison suffices to say whether two Nimrod
identifiers are equivalent
ropes implements long strings using represented as trees for
lazy evaluation; used mainly by the code generators
ccgobj contains type definitions neeeded for C code generation
and some helpers
ccgmangl contains the name mangler for converting Nimrod
identifiers to their C counterparts
ccgutils contains helpers for the C code generator
ccgtemps contains the handling of temporary variables for the
C code generator
ccgtypes the generator for C types
ccgstmts the generator for statements
ccgexprs the generator for expressions
extccomp this module calls the C compiler and linker; interesting
if you want to add support for a new C compiler
============== ==========================================================

186
doc/grammar.txt Executable file
View File

@@ -0,0 +1,186 @@
module ::= ([COMMENT] [SAD] stmt)*
optComma ::= [ ',' ] [COMMENT] [IND]
operator ::= OP0 | OR | XOR | AND | OP3 | OP4 | OP5 | IS | ISNOT | IN | NOTIN
| OP6 | DIV | MOD | SHL | SHR | OP7 | NOT
prefixOperator ::= OP0 | OP3 | OP4 | OP5 | OP6 | OP7 | NOT
optInd ::= [COMMENT] [IND]
lowestExpr ::= orExpr ( OP0 optInd orExpr )*
orExpr ::= andExpr ( OR | XOR optInd andExpr )*
andExpr ::= cmpExpr ( AND optInd cmpExpr )*
cmpExpr ::= ampExpr ( OP3 | IS | ISNOT | IN | NOTIN optInd ampExpr )*
ampExpr ::= plusExpr ( OP4 optInd plusExpr )*
plusExpr ::= mulExpr ( OP5 optInd mulExpr )*
mulExpr ::= dollarExpr ( OP6 | DIV | MOD | SHL | SHR optInd dollarExpr )*
dollarExpr ::= primary ( OP7 optInd primary )*
namedTypeOrExpr ::=
DOTDOT [expr]
| expr [EQUALS (expr [DOTDOT expr] | typeDescK | DOTDOT [expr] )
| DOTDOT [expr]]
| typeDescK
castExpr ::= CAST BRACKET_LE optInd typeDesc BRACKERT_RI
PAR_LE optInd expr PAR_RI
addrExpr ::= ADDR PAR_LE optInd expr PAR_RI
symbol ::= ACC (KEYWORD | IDENT | operator | PAR_LE PAR_RI
| BRACKET_LE BRACKET_RI) ACC | IDENT
accExpr ::= KEYWORD | IDENT | operator [DOT KEYWORD | IDENT | operator]
paramList
primary ::= ( prefixOperator optInd )* ( IDENT | literal | ACC accExpr ACC
| castExpr | addrExpr ) (
DOT optInd symbol
#| CURLY_LE namedTypeDescList CURLY_RI
| PAR_LE optInd
namedExprList
PAR_RI
| BRACKET_LE optInd
(namedTypeOrExpr optComma)*
BRACKET_RI
| CIRCUM
| pragma )*
literal ::= INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
| FLOAT_LIT | FLOAT32_LIT | FLOAT64_LIT
| STR_LIT | RSTR_LIT | TRIPLESTR_LIT
| CHAR_LIT | RCHAR_LIT
| NIL
| BRACKET_LE optInd (expr [COLON expr] optComma )* BRACKET_RI # []-Constructor
| CURLY_LE optInd (expr [DOTDOT expr] optComma )* CURLY_RI # {}-Constructor
| PAR_LE optInd (expr [COLON expr] optComma )* PAR_RI # ()-Constructor
exprList ::= ( expr optComma )*
namedExpr ::= expr [EQUALS expr] # actually this is symbol EQUALS expr|expr
namedExprList ::= ( namedExpr optComma )*
exprOrSlice ::= expr [ DOTDOT expr ]
sliceList ::= ( exprOrSlice optComma )+
anonymousProc ::= LAMBDA paramList [pragma] EQUALS stmt
expr ::= lowestExpr
| anonymousProc
| IF expr COLON expr
(ELIF expr COLON expr)*
ELSE COLON expr
namedTypeDesc ::= typeDescK | expr [EQUALS (typeDescK | expr)]
namedTypeDescList ::= ( namedTypeDesc optComma )*
qualifiedIdent ::= symbol [ DOT symbol ]
typeDescK ::= VAR typeDesc
| REF typeDesc
| PTR typeDesc
| TYPE expr
| PROC paramList [pragma]
typeDesc ::= typeDescK | primary
optSemicolon ::= [SEMICOLON]
macroStmt ::= COLON [stmt] (OF [sliceList] COLON stmt
| ELIF expr COLON stmt
| EXCEPT exceptList COLON stmt )*
[ELSE COLON stmt]
simpleStmt ::= returnStmt
| yieldStmt
| discardStmt
| raiseStmt
| breakStmt
| continueStmt
| pragma
| importStmt
| fromStmt
| includeStmt
| exprStmt
complexStmt ::= ifStmt | whileStmt | caseStmt | tryStmt | forStmt
| blockStmt | asmStmt
| procDecl | iteratorDecl | macroDecl | templateDecl
| constSection | typeSection | whenStmt | varSection
indPush ::= IND # push
stmt ::= simpleStmt [SAD]
| indPush (complexStmt | simpleStmt)
([SAD] (complexStmt | simpleStmt) )*
DED
exprStmt ::= lowestExpr [EQUALS expr | (expr optComma)* [macroStmt]]
returnStmt ::= RETURN [expr]
yieldStmt ::= YIELD expr
discardStmt ::= DISCARD expr
raiseStmt ::= RAISE [expr]
breakStmt ::= BREAK [symbol]
continueStmt ::= CONTINUE
ifStmt ::= IF expr COLON stmt (ELIF expr COLON stmt)* [ELSE COLON stmt]
whenStmt ::= WHEN expr COLON stmt (ELIF expr COLON stmt)* [ELSE COLON stmt]
caseStmt ::= CASE expr (OF sliceList COLON stmt)*
(ELIF expr COLON stmt)*
[ELSE COLON stmt]
whileStmt ::= WHILE expr COLON stmt
forStmt ::= FOR (symbol optComma)+ IN expr [DOTDOT expr] COLON stmt
exceptList ::= (qualifiedIdent optComma)*
tryStmt ::= TRY COLON stmt
(EXCEPT exceptList COLON stmt)*
[FINALLY COLON stmt]
asmStmt ::= ASM [pragma] (STR_LIT | RSTR_LIT | TRIPLESTR_LIT)
blockStmt ::= BLOCK [symbol] COLON stmt
importStmt ::= IMPORT ((symbol | STR_LIT | RSTR_LIT | TRIPLESTR_LIT) [AS symbol] optComma)+
includeStmt ::= INCLUDE ((symbol | STR_LIT | RSTR_LIT | TRIPLESTR_LIT) optComma)+
fromStmt ::= FROM (symbol | STR_LIT | RSTR_LIT | TRIPLESTR_LIT) IMPORT (symbol optComma)+
pragma ::= CURLYDOT_LE (expr [COLON expr] optComma)+ (CURLYDOT_RI | CURLY_RI)
paramList ::= [PAR_LE ((symbol optComma)+ COLON typeDesc optComma)* PAR_RI] [COLON typeDesc]
genericParams ::= BRACKET_LE (symbol [EQUALS typeDesc] )* BRACKET_RI
procDecl ::= PROC symbol ["*"] [genericParams]
paramList [pragma]
[EQUALS stmt]
macroDecl ::= MACRO symbol ["*"] [genericParams] paramList [pragma]
[EQUALS stmt]
iteratorDecl ::= ITERATOR symbol ["*"] [genericParams] paramList [pragma]
[EQUALS stmt]
templateDecl ::= TEMPLATE symbol ["*"] [genericParams] paramList [pragma]
[EQUALS stmt]
colonAndEquals ::= [COLON typeDesc] EQUALS expr
constDecl ::= symbol ["*"] [pragma] colonAndEquals [COMMENT | IND COMMENT]
| COMMENT
constSection ::= CONST indPush constDecl (SAD constDecl)* DED
typeDef ::= typeDesc | recordDef | objectDef | enumDef
recordIdentPart ::=
(symbol ["*" | "-"] [pragma] optComma)+ COLON typeDesc [COMMENT | IND COMMENT]
recordWhen ::= WHEN expr COLON [COMMENT] recordPart
(ELIF expr COLON [COMMENT] recordPart)*
[ELSE COLON [COMMENT] recordPart]
recordCase ::= CASE expr COLON typeDesc [COMMENT]
(OF sliceList COLON [COMMENT] recordPart)*
[ELSE COLON [COMMENT] recordPart]
recordPart ::= recordWhen | recordCase | recordIdentPart
| indPush recordPart (SAD recordPart)* DED
recordDef ::= RECORD [pragma] recordPart
objectDef ::= OBJECT [pragma] [OF typeDesc] recordPart
enumDef ::= ENUM [OF typeDesc] (symbol [EQUALS expr] optComma [COMMENT | IND COMMENT])+
typeDecl ::= COMMENT
| symbol ["*"] [genericParams] [EQUALS typeDef] [COMMENT | IND COMMENT]
typeSection ::= TYPE indPush typeDecl (SAD typeDecl)* DED
colonOrEquals ::= COLON typeDesc [EQUALS expr] | EQUALS expr
varPart ::= (symbol ["*" | "-"] [pragma] optComma)+ colonOrEquals [COMMENT | IND COMMENT]
varSection ::= VAR (varPart | indPush (COMMENT|varPart) (SAD (COMMENT|varPart))* DED)

1
doc/html/empty.txt Executable file
View File

@@ -0,0 +1 @@
This file keeps several tools from deleting this subdirectory.

575
doc/intern.txt Executable file
View File

@@ -0,0 +1,575 @@
=========================================
Internals of the Nimrod Compiler
=========================================
:Author: Andreas Rumpf
:Version: |nimrodversion|
.. contents::
Directory structure
===================
The Nimrod project's directory structure is:
============ ==============================================
Path Purpose
============ ==============================================
``bin`` binary files go into here
``nim`` Pascal sources of the Nimrod compiler; this
should be modified, not the Nimrod version in
``rod``!
``rod`` Nimrod sources of the Nimrod compiler;
automatically generated from the Pascal
version
``data`` data files that are used for generating source
code go into here
``doc`` the documentation lives here; it is a bunch of
reStructuredText files
``dist`` download packages as zip archives go into here
``config`` configuration files for Nimrod go into here
``lib`` the Nimrod library lives here; ``rod`` depends
on it!
``web`` website of Nimrod; generated by ``genweb.py``
from the ``*.txt`` and ``*.tmpl`` files
``koch`` the Koch Build System (written for Nimrod)
``obj`` generated ``*.obj`` files go into here
============ ==============================================
Bootstrapping the compiler
==========================
The compiler is written in a subset of Pascal with special annotations so
that it can be translated to Nimrod code automatically. This conversion is
done by Nimrod itself via the undocumented ``boot`` command. Thus both Nimrod
and Free Pascal can compile the Nimrod compiler.
Requirements for bootstrapping:
- Free Pascal (I used version 2.2); it may not be needed
- Python (should work with 2.4 or higher) and the code generator *cog*
(included in this distribution!)
- C compiler -- one of:
* win32-lcc
* Borland C++ (tested with 5.5)
* Microsoft C++
* Digital Mars C++
* Watcom C++ (currently broken; a fix is welcome!)
* GCC
* Intel C++
* Pelles C
* llvm-gcc
| Compiling the compiler is a simple matter of running:
| ``koch.py boot``
| Or you can compile by hand, this is not difficult.
If you want to debug the compiler, use the command::
koch.py boot --debugger:on
The ``koch.py`` script is Nimrod's maintainance script: Everything that has
been automated is accessible with it. It is a replacement for make and shell
scripting with the advantage that it is more portable and is easier to read.
Coding standards
================
The compiler is written in a subset of Pascal with special annotations so
that it can be translated to Nimrod code automatically. As a generell rule,
Pascal code that does not translate to Nimrod automatically is forbidden.
Porting to new platforms
========================
Porting Nimrod to a new architecture is pretty easy, since C is the most
portable programming language (within certain limits) and Nimrod generates
C code, porting the code generator is not necessary.
POSIX-compliant systems on conventional hardware are usually pretty easy to
port: Add the platform to ``platform`` (if it is not already listed there),
check that the OS, System modules work and recompile Nimrod.
The only case where things aren't as easy is when the garbage
collector needs some assembler tweaking to work. The standard
version of the GC uses C's ``setjmp`` function to store all registers
on the hardware stack. It may be that the new platform needs to
replace this generic code by some assembler code.
Runtime type information
========================
*Runtime type information* (RTTI) is needed for several aspects of the Nimrod
programming language:
Garbage collection
The most important reason for RTTI. Generating
traversal procedures produces bigger code and is likely to be slower on
modern hardware as dynamic procedure binding is hard to predict.
Complex assignments
Sequences and strings are implemented as
pointers to resizeable buffers, but Nimrod requires copying for
assignments. Apart from RTTI the compiler could generate copy procedures
for any type that needs one. However, this would make the code bigger and
the RTTI is likely already there for the GC.
We already knew the type information as a graph in the compiler.
Thus we need to serialize this graph as RTTI for C code generation.
Look at the files ``lib/typeinfo.nim``, ``lib/hti.nim`` for more information.
However, generating type information proved to be difficult and the format
wastes memory. Variant records make problems too. We use a mix of iterator
procedures and constant data structures:
.. code-block:: Nimrod
type
TNimTypeSlot {.export.} = record
offset: int
typ: int
name: CString
TSlotIterator = proc (obj: pointer, field: int): ptr TNimTypeSlot
TNimType {.export.} = record
Kind: TNimTypeKind
baseType, indexType: int
size, len: int
slots: TSlotIterator # instead of: ptr array [0..10_000, TNimTypeSlot]
This is not easy to understand either. Best is to use just the ``rodgen``
module and store type information as string constants.
After thinking I came to the conclusion that this is again premature
optimization. We should just construct the type graph at runtime. In the init
section new types should be constructed and registered:
.. code-block:: Nimrod
type
TSlotTriple = record
offset: int
typ: PRTL_Type
name: Cstring
PSlots = ptr TSlots
TSlots = record
case kind
of linear:
fields: array [TSlotTriple]
of nested:
discriminant: TSlotTriple
otherSlots: array [discriminant, PSlots]
TTypeKind = enum ...
RTL_Type = record
size: int
base: PRTL_Type
case kind
of tyArray, tySequence:
elemSize: int
of tyRecord, tyObject, tyEnum:
slots: PSlots
The Garbage Collector
=====================
Introduction
------------
We use the term *cell* here to refer to everything that is traced
(sequences, refs, strings).
This section describes how the new GC works. The old algorithms
all had the same problem: Too complex to get them right. This one
tries to find the right compromise.
The basic algorithm is *Deferrent reference counting* with cycle detection.
References in the stack are not counted for better performance and easier C
code generation. The GC starts by traversing the hardware stack and increments
the reference count (RC) of every cell that it encounters. After the GC has
done its work the stack is traversed again and the RC of every cell
that it encounters are decremented again. Thus no marking bits in the RC are
needed. Between these stack traversals the GC has a complete accurate view over
the RCs.
Each cell has a header consisting of a RC and a pointer to its type
descriptor. However the program does not know about these, so they are placed at
negative offsets. In the GC code the type ``PCell`` denotes a pointer
decremented by the right offset, so that the header can be accessed easily. It
is extremely important that ``pointer`` is not confused with a ``PCell``
as this would lead to a memory corruption.
When to trigger a collection
----------------------------
Since there are really two different garbage collectors (reference counting
and mark and sweep) we use two different heuristics when to run the passes.
The RC-GC pass is fairly cheap: Thus we use an additive increase (7 pages)
for the RC_Threshold and a multiple increase for the CycleThreshold.
The AT and ZCT sets
-------------------
The GC maintains two sets throughout the lifetime of
the program (plus two temporary ones). The AT (*any table*) simply contains
every cell. The ZCT (*zero count table*) contains every cell whose RC is
zero. This is used to reclaim most cells fast.
The ZCT contains redundant information -- the AT alone would suffice.
However, traversing the AT and look if the RC is zero would touch every living
cell in the heap! That's why the ZCT is updated whenever a RC drops to zero.
The ZCT is not updated when a RC is incremented from zero to one, as
this would be too costly.
The CellSet data structure
--------------------------
The AT and ZCT depend on an extremely efficient datastructure for storing a
set of pointers - this is called a ``PCellSet`` in the source code.
Inserting, deleting and searching are done in constant time. However,
modifying a ``PCellSet`` during traversation leads to undefined behaviour.
.. code-block:: Nimrod
type
PCellSet # hidden
proc allocCellSet: PCellSet # make a new set
proc deallocCellSet(s: PCellSet) # empty the set and free its memory
proc incl(s: PCellSet, elem: PCell) # include an element
proc excl(s: PCellSet, elem: PCell) # exclude an element
proc `in`(elem: PCell, s: PCellSet): bool
iterator elements(s: PCellSet): (elem: PCell)
All the operations have to be performed efficiently. Because a Cellset can
become huge (the AT contains every allocated cell!) a hash table is not
suitable for this.
We use a mixture of bitset and patricia tree for this. One node in the
patricia tree contains a bitset that decribes a page of the operating system
(not always, but that doesn't matter).
So including a cell is done as follows:
- Find the page descriptor for the page the cell belongs to.
- Set the appropriate bit in the page descriptor indicating that the
cell points to the start of a memory block.
Removing a cell is analogous - the bit has to be set to zero.
Single page descriptors are never deleted from the tree. Typically a page
descriptor is only 19 words big, so it does not waste much by not deleting
it. Apart from that the AT and ZCT are rebuilt frequently, so removing a
single page descriptor from the tree is never necessary.
Complete traversal is done like so::
for each page decriptor d:
for each bit in d:
if bit == 1:
traverse the pointer belonging to this bit
Further complications
---------------------
In Nimrod the compiler cannot always know if a reference
is stored on the stack or not. This is caused by var parameters.
Consider this example:
.. code-block:: Nimrod
proc setRef(r: var ref TNode) =
new(r)
proc usage =
var
r: ref TNode
setRef(r) # here we should not update the reference counts, because
# r is on the stack
setRef(r.left) # here we should update the refcounts!
Though it would be possible to produce code updating the refcounts (if
necessary) before and after the call to ``setRef``, it is a complex task to
do so in the code generator. So we don't and instead decide at runtime
whether the reference is on the stack or not. The generated code looks
roughly like this:
.. code-block:: C
void setref(TNode** ref) {
unsureAsgnRef(ref, newObj(TNode_TI, sizeof(TNode)))
}
void usage(void) {
setRef(&r)
setRef(&r->left)
}
Note that for systems with a continous stack (which most systems have)
the check whether the ref is on the stack is very cheap (only two
comparisons). Another advantage of this scheme is that the code produced is
a tiny bit smaller.
The algorithm in pseudo-code
----------------------------
Now we come to the nitty-gritty. The algorithm works in several phases.
Phase 1 - Consider references from stack
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
for each pointer p in the stack: incRef(p)
This is necessary because references in the hardware stack are not traced for
better performance. After Phase 1 the RCs are accurate.
Phase 2 - Free the ZCT
~~~~~~~~~~~~~~~~~~~~~~
This is how things used to (not) work::
for p in elements(ZCT):
if RC(p) == 0:
call finalizer of p
for c in children(p): decRef(c) # free its children recursively
# if necessary; the childrens RC >= 1, BUT they may still be in the ZCT!
free(p)
else:
remove p from the ZCT
Instead we do it this way. Note that the recursion is gone too!
::
newZCT = nil
for p in elements(ZCT):
if RC(p) == 0:
call finalizer of p
for c in children(p):
assert(RC(c) > 0)
dec(RC(c))
if RC(c) == 0:
if newZCT == nil: newZCT = allocCellSet()
incl(newZCT, c)
free(p)
else:
# nothing to do! We will use the newZCS
deallocCellSet(ZCT)
ZCT = newZCT
This phase is repeated until enough memory is available or the ZCT is nil.
If still not enough memory is available the cyclic detector gets its chance
to do something.
Phase 3 - Cycle detection
~~~~~~~~~~~~~~~~~~~~~~~~~
Cycle detection works by subtracting internal reference counts::
newAT = allocCellSet()
for y in elements(AT):
# pretend that y is dead:
for c in children(y):
dec(RC(c))
# note that this should not be done recursively as we have all needed
# pointers in the AT! This makes it more efficient too!
proc restore(y: PCell) =
# unfortunately, the recursion here cannot be eliminated easily
if y not_in newAT:
incl(newAT, y)
for c in children(y):
inc(RC(c)) # restore proper reference counts!
restore(c)
for y in elements(AT) with rc > 0:
restore(y)
for y in elements(AT) with rc == 0:
free(y) # if pretending worked, it was part of a cycle
AT = newAT
Phase 4 - Ignore references from stack again
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
for each pointer p in the stack:
dec(RC(p))
if RC(p) == 0: incl(ZCT, p)
Now the RCs correctly discard any references from the stack. One can also see
this as a temporary marking operation. Things that are referenced from stack
are marked during the GC's operarion and now have to be unmarked.
The compiler's architecture
===========================
Nimrod uses the classic compiler architecture: A scanner feds tokens to a
parser. The parser builds a syntax tree that is used by the code generator.
This syntax tree is the interface between the parser and the code generator.
It is essential to understand most of the compiler's code.
In order to compile Nimrod correctly, type-checking has to be seperated from
parsing. Otherwise generics would not work. Code generation is done for a
whole module only after it has been checked for semantics.
.. include:: filelist.txt
The first command line argument selects the backend. Thus the backend is
responsible for calling the parser and semantic checker. However, when
compiling ``import`` or ``include`` statements, the semantic checker needs to
call the backend, this is done by embedding a PBackend into a TContext.
The syntax tree
---------------
The synax tree consists of nodes which may have an arbitrary number of
children. Types and symbols are represented by other nodes, because they
may contain cycles. The AST changes its shape after semantic checking. This
is needed to make life easier for the code generators. See the "ast" module
for the type definitions.
We use the notation ``nodeKind(fields, [sons])`` for describing
nodes. ``nodeKind[sons]`` is a short-cut for ``nodeKind([sons])``.
XXX: Description of the language's syntax and the corresponding trees.
How the RTL is compiled
=======================
The system module contains the part of the RTL which needs support by
compiler magic (and the stuff that needs to be in it because the spec
says so). The C code generator generates the C code for it just like any other
module. However, calls to some procedures like ``addInt`` are inserted by
the CCG. Therefore the module ``magicsys`` contains a table
(``compilerprocs``) with all symbols that are marked as ``compilerproc``.
How separate compilation will work
==================================
Soon compiling from scratch every module that's needed will become too slow as
programs grow. For easier cleaning all generated files are generated in the
directory: ``$base/rod_gen``. This cannot be changed. The generated C files
get the names of the modules they result from. A compiled Nimrod module has the
extension ``.rod`` and is a binary file. The format may change from release
to release. The rod-file is mostly a binary representation of the parse trees.
Nimrod currently compiles any module into its own C file. Some things like
type-information, common string literals, common constant sets need to be
shared though. We deal with this problem by writing the shared data
in the main C file. Only "headers" are generated in the other modules. However,
each precompiled Nimrod module lists the shared data it depends on. The same
holds for procedures that have to generated from generics.
A big problem is that the data must get the same name each time it is compiled.
The C compiler is only called for the C files, that changed after the last
compilation (or if their object file does not exist anymore). To work
reliably, in the header comment of the C file these things are listed, so
that the C compiler is called again should they change:
* Nimrod's Version
* the target CC
* the target OS
* the target CPU
The version is questionable: If the resulting C file is the same, it does not
matter that Nimrods's version has increased. We do it anyway to be on the safe
side.
Generation of dynamic link libraries
====================================
Generation of dynamic link libraries or shared libraries is not difficult; the
underlying C compiler already does all the hard work for us. The problem is the
common runtime library, especially the memory manager. Note that Borland's
Delphi had exactly the same problem. The workaround is to not link the GC with
the Dll and provide an extra runtime dll that needs to be initialized.
How to implement closures
=========================
A closure is a record of a proc pointer and a context ref. The context ref
points to a garbage collected record that contains the needed variables.
An example:
.. code-block:: Nimrod
type
TListRec = record
data: string
next: ref TListRec
proc forEach(head: ref TListRec, visitor: proc (s: string) {.closure.}) =
var it = head
while it != nil:
visit(it.data)
it = it.next
proc sayHello() =
var L = new List(["hallo", "Andreas"])
var temp = "jup\xff"
forEach(L, lambda(s: string) =
io.write(temp)
io.write(s)
)
This should become the following in C:
.. code-block:: C
typedef struct ... /* List type */
typedef struct closure {
void (*PrcPart)(string, void*);
void* ClPart;
}
typedef struct Tcl_data {
string temp; // all accessed variables are put in here!
}
void forEach(TListRec* head, const closure visitor) {
TListRec* it = head;
while (it != NIM_NULL) {
visitor.prc(it->data, visitor->cl_data);
it = it->next;
}
}
void printStr(string s, void* cl_data) {
Tcl_data* x = (Tcl_data*) cl_data;
io_write(x->temp);
io_write(s);
}
void sayhello() {
Tcl_data* data = new(...);
asgnRef(&data->temp, "jup\xff");
...
closure cl;
cl.prc = printStr;
cl.cl_data = data;
foreach(L, cl);
}
What about nested closure? - There's not much difference: Just put all used
variables in the data record.

48
doc/lib.txt Executable file
View File

@@ -0,0 +1,48 @@
=======================
Nimrod Standard Library
=======================
:Author: Andreas Rumpf
:Version: |nimrodversion|
Though the Nimrod Standard Library is still evolving, it is already quite
usable. It is divided into basic libraries that contains modules that virtually
every program will need and advanced libraries which are more heavy weight.
Advanced libraries are in the ``lib/base`` directory.
Basic libraries
===============
* `System <system.html>`_
Basic procs and operators that every program needs. It also provides IO
facilities for reading and writing text and binary files. It is imported
implicitly by the compiler. Do not import it directly. It relies on compiler
magic to work.
* `Strutils <strutils.html>`_
This module contains common string handling operations like converting a
string into uppercase, splitting a string into substrings, searching for
substrings, replacing substrings.
* `OS <os.html>`_
Basic operating system facilities like retrieving environment variables,
reading command line arguments, working with directories, running shell
commands, etc. This module is -- like any other basic library --
platform independant.
* `Math <math.html>`_
Mathematical operations like cosine, square root.
* `Complex <complex.html>`_
This module implements complex numbers and their mathematical operations.
* `Times <times.html>`_
The ``times`` module contains basic support for working with time.
Advanced libaries
=================
* `Regexprs <regexprs.html>`_
This module contains procedures and operators for handling regular
expressions.

1742
doc/manual.txt Executable file

File diff suppressed because it is too large Load Diff

295
doc/nimdoc.css Executable file
View File

@@ -0,0 +1,295 @@
/*
:Author: David Goodger
:Contact: goodger@python.org
:Date: $Date: 2006-05-21 22:44:42 +0200 (Sun, 21 May 2006) $
:Revision: $Revision: 4564 $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/*
Modified for the Nimrod Documenation by
Andreas Rumpf
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin-left: 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em;
}
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title { text-align: center }
h2.subtitle { text-align: center }
hr.docutils { width: 75% }
img.align-left { clear: left }
img.align-right { clear: right }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font-family: serif ;
font-size: 100% }
pre, span.pre {
background-color:#F9F9F9;
border:1px dotted #2F6FAB;
color:black;
}
pre {padding:1em;}
pre.literal-block, pre.doctest-block {
margin-left: 2em ;
margin-right: 2em }
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre { white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
a.reference {
color: #E00000;
font-weight:bold;
}
a.reference:hover {
color: #E00000;
background-color: #ffff00;
display: margin;
font-weight:bold;
}
div.topic ul {
list-style-type: none;
}

241
doc/nimrodc.txt Executable file
View File

@@ -0,0 +1,241 @@
===================================
Nimrod Compiler User Guide
===================================
:Author: Andreas Rumpf
:Version: |nimrodversion|
.. contents::
Introduction
============
This document describes the usage of the *Nimrod compiler*
on the different supported platforms. It is not a definition of the Nimrod
programming system (therefore is the Nimrod manual).
Nimrod is free software; it is licensed under the
`GNU General Public License <gpl.html>`_.
Compiler Usage
==============
Command line switches
---------------------
Basis command line switches are:
.. include:: ../data/basicopt.txt
Advanced command line switches are:
.. include:: ../data/advopt.txt
Configuration file
------------------
The ``nimrod`` executable loads the configuration file ``config/nimrod.cfg``
unless this is suppressed by the ``--skip_cfg`` command line option.
Configuration settings can be overwritten in a project specific
configuration file that is read automatically. This specific file has to
be in the same directory as the project and be of the same name, except
that its extension should be ``.cfg``.
Command line settings have priority over configuration file settings.
Nimrod's directory structure
----------------------------
The generated files that Nimrod produces all go into a subdirectory called
``rod_gen``. This makes it easy to write a script that deletes all generated
files. For example the generated C code for the module ``path/modA.nim``
will become ``path/rod_gen/modA.c``.
However, the generated C code is not platform independant! C code generated for
Linux does not compile on Windows, for instance. The comment on top of the
C file lists the OS, CPU and CC the file has been compiled for.
The library lies in ``lib``. Directly in the library directory are essential
Nimrod modules like the ``system`` and ``os`` modules. Under ``lib/base``
are additional specialized libraries or interfaces to foreign libraries which
are included in the standard distribution. The ``lib/extra`` directory is
initially empty. Third party libraries should go there. In the default
configuration the compiler always searches for libraries in ``lib``,
``lib/base`` and ``lib/extra``.
Additional Features
===================
This section describes Nimrod's additional features that are not listed in the
Nimrod manual.
New Pragmas and Options
-----------------------
Because Nimrod generates C code it needs some "red tape" to work properly.
Thus lots of options and pragmas for tweaking the generated C code are
available.
No_decl Pragma
~~~~~~~~~~~~~~
The `no_decl`:idx: pragma can be applied to almost any symbol (variable, proc,
type, etc.) and is one of the most important for interoperability with C:
It tells Nimrod that it should not generate a declaration for the symbol in
the C code. Thus it makes the following possible, for example:
.. code-block:: Nimrod
var
EOF {.import: "EOF", no_decl.}: cint # pretend EOF was a variable, as
# Nimrod does not know its value
Varargs Pragma
~~~~~~~~~~~~~~
The `varargs`:idx: pragma can be applied to procedures only. It tells Nimrod
that the proc can take a variable number of parameters after the last
specified parameter. Nimrod string values will be converted to C
strings automatically:
.. code-block:: Nimrod
proc printf(formatstr: cstring) {.nodecl, varargs.}
printf("hallo %s", "world") # "world" will be passed as C string
Header Pragma
~~~~~~~~~~~~~
The `header`:idx: pragma is very similar to the ``no_decl`` pragma: It can be
applied to almost any symbol and specifies that not only it should not be
declared but also that it leads to the inclusion of a given header file:
.. code-block:: Nimrod
type
PFile {.import: "FILE*", header: "<stdio.h>".} = pointer
# import C's FILE* type; Nimrod will treat it as a new pointer type
The ``header`` pragma expects always a string constant. The string contant
contains the header file: As usual for C, a system header file is enclosed
in angle brackets: ``<>``. If no angle brackets are given, Nimrod
encloses the header file in ``""`` in the generated C code.
No_static Pragma
~~~~~~~~~~~~~~~~
The `no_static`:idx: pragma can be applied to almost any symbol and specifies
that it shall not be declared ``static`` in the generated C code. Note that
symbols in the interface part of a module never get declared ``static``, so
only in special cases is this pragma necessary.
Line_dir Option
~~~~~~~~~~~~~~~
The `line_dir`:idx: option can be turned on or off. If on the generated C code
contains ``#line`` directives.
Stack_trace Option
~~~~~~~~~~~~~~~~~~
If the `stack_trace`:idx: option is turned on, the generated C contains code to
ensure that proper stack traces are given if the program crashes or an
uncaught exception is raised.
Line_trace Option
~~~~~~~~~~~~~~~~~
The `line_trace`:idx: option implies the ``stack_trace`` option. If turned on,
the generated C contains code to ensure that proper stack traces with line
number information are given if the program crashes or an uncaught exception
is raised.
Debugger Option
~~~~~~~~~~~~~~~
The `debugger`:idx: option enables or disables the *Embedded Nimrod Debugger*.
See the documentation of endb_ for further information.
Breakpoint Pragma
~~~~~~~~~~~~~~~~~
The *breakpoint* pragma was specially added for the sake of debugging with
ENDB. See the documentation of `endb <endb.html>`_ for further information.
Volatile Pragma
~~~~~~~~~~~~~~~
The `volatile`:idx: pragma is for variables only. It declares the variable as
``volatile``, whatever that means in C/C++.
Register Pragma
~~~~~~~~~~~~~~~
The `register`:idx: pragma is for variables only. It declares the variable as
``register``, giving the compiler a hint that the variable should be placed
in a hardware register for faster access. C compilers usually ignore this
though and for good reason: Often they do a better job without it anyway.
In highly specific cases (a dispatch loop of interpreters for example) it
may provide benefits, though.
Disabling certain messages
--------------------------
Nimrod generates some warnings and hints ("line too long") that may annoy the
user. Thus a mechanism for disabling certain messages is provided: Each hint
and warning message contains a symbol in brackets. This is the message's
identifier that can be used to enable or disable it:
.. code-block:: Nimrod
{.warning[LineTooLong]: off.} # turn off warning about too long lines
This is often better than disabling all warnings at once.
Debugging with Nimrod
=====================
Nimrod comes with its own *Embedded Nimrod Debugger*. See
the documentation of endb_ for further information.
Optimizing for Nimrod
=====================
Nimrod has no separate optimizer, but the C code that is produced is very
efficient. Most C compilers have excellent optimizers, so usually it is
not needed to optimize one's code. Nimrod has been designed to encourage
efficient code: The most readable code in Nimrod is often the most efficient
too.
However, sometimes one has to optimize. Do it in the following order:
1. switch off the embedded debugger (it is **slow**!)
2. turn on the optimizer and turn off runtime checks
3. profile your code to find where the bottlenecks are
4. try to find a better algorithm
5. do low-level optimizations
This section can only help you with the last item. Note that rewriting parts
of your program in C is *never* necessary to speed up your program, because
everything that can be done in C can be done in Nimrod. Rewriting parts in
assembler *might*.
Optimizing string handling
--------------------------
String assignments are sometimes expensive in Nimrod: They are required to
copy the whole string. However, the compiler is often smart enough to not copy
strings. Due to the argument passing semantics, strings are never copied when
passed to subroutines. The compiler does not copy strings that are returned by
a routine, because a routine returns a new string anyway. Thus it is efficient
to do:
.. code-block:: Nimrod
var s = procA() # assignment will not copy the string; procA allocates a new
# string anyway
However it is not efficient to do:
.. code-block:: Nimrod
var s = varA # assignment has to copy the whole string into a new buffer!
String case statements are optimized too. A hashing scheme is used for them
if several different string constants are used. This is likely to be more
efficient than any hand-coded scheme.

9
doc/overview.txt Executable file
View File

@@ -0,0 +1,9 @@
=============================
Nimrod Documentation Overview
=============================
:Author: Andreas Rumpf
:Version: |nimrodversion|
.. include:: ../doc/docs.txt

220
doc/posix.txt Executable file
View File

@@ -0,0 +1,220 @@
Function POSIX Description
access Tests for file accessibility
alarm Schedules an alarm
asctime Converts a time structure to a string
cfgetispeed Reads terminal input baud rate
cfgetospeed Reads terminal output baud rate
cfsetispeed Sets terminal input baud rate
cfsetospeed Sets terminal output baud rate
chdir Changes current working directory
chmod Changes file mode
chown Changes owner and/or group of a file
close Closes a file
closedir Ends directory read operation
creat Creates a new file or rewrites an existing one
ctermid Generates terminal pathname
cuserid Gets user name
dup Duplicates an open file descriptor
dup2 Duplicates an open file descriptor
execl Executes a file
execle Executes a file
execlp Executes a file
execv Executes a file
execve Executes a file
execvp Executes a file
_exit Terminates a process
fcntl Manipulates an open file descriptor
fdopen Opens a stream on a file descriptor
fork Creates a process
fpathconf Gets configuration variable for an open file
fstat Gets file status
getcwd Gets current working directory
getegid Gets effective group ID
getenv Gets environment variable
geteuid Gets effective user ID
getgid Gets real group ID
getgrgid Reads groups database based on group ID
getgrnam Reads groups database based on group name
getgroups Gets supplementary group IDs
getlogin Gets user name
getpgrp Gets process group ID
getpid Gets process ID
getppid Gets parent process ID
getpwnam Reads user database based on user name
getpwuid Reads user database based on user ID
getuid Gets real user ID
isatty Determines if a file descriptor is associated with a terminal
kill Sends a kill signal to a process
link Creates a link to a file
longjmp Restores the calling environment
lseek Repositions read/write file offset
mkdir Makes a directory
mkfifo Makes a FIFO special file
open Opens a file
opendir Opens a directory
pathconf Gets configuration variables for a path
pause Suspends a process execution
pipe Creates an interprocess channel
read Reads from a file
readdir Reads a directory
rename Renames a file
rewinddir Resets the readdir() pointer
rmdir Removes a directory
setgid Sets group ID
setjmp Saves the calling environment for use by longjmp()
setlocale Sets or queries a program's locale
setpgid Sets a process group ID for job control
setuid Sets the user ID
sigaction Examines and changes signal action
sigaddset Adds a signal to a signal set
sigdelset Removes a signal to a signal set
sigemptyset Creates an empty signal set
sigfillset Creates a full set of signals
sigismember Tests a signal for a selected member
siglongjmp Goes to and restores signal mask
sigpending Examines pending signals
sigprocmask Examines and changes blocked signals
sigsetjmp Saves state for siglongjmp()
sigsuspend Waits for a signal
sleep Delays process execution
stat Gets information about a file
sysconf Gets system configuration information
tcdrain Waits for all output to be transmitted to the terminal
tcflow Suspends/restarts terminal output
tcflush Discards terminal data
tcgetattr Gets terminal attributes
tcgetpgrp Gets foreground process group ID
tcsendbreak Sends a break to a terminal
tcsetattr Sets terminal attributes
tcsetpgrp Sets foreground process group ID
time Determines the current calendar time
times Gets process times
ttyname Determines a terminal pathname
tzset Sets the timezone from environment variables
umask Sets the file creation mask
uname Gets system name
unlink Removes a directory entry
utime Sets file access and modification times
waitpid Waits for process termination
write Writes to a file
POSIX.1b function calls Function POSIX Description
aio_cancel Tries to cancel an asynchronous operation
aio_error Retrieves the error status for an asynchronous operation
aio_read Asynchronously reads from a file
aio_return Retrieves the return status for an asynchronous operation
aio_suspend Waits for an asynchronous operation to complete
aio_write Asynchronously writes to a file
clock_getres Gets resolution of a POSIX.1b clock
clock_gettime Gets the time according to a particular POSIX.1b clock
clock_settime Sets the time according to a particular POSIX.1b clock
fdatasync Synchronizes at least the data part of a file with the underlying media
fsync Synchronizes a file with the underlying media
kill, sigqueue Sends signals to a process
lio_listio Performs a list of I/O operations, synchronously or asynchronously
mlock Locks a range of memory
mlockall Locks the entire memory space down
mmap Maps a shared memory object (or possibly another file) into process's address space
mprotect Changes memory protection on a mapped area
mq_close Terminates access to a POSIX.1b message queue
mq_getattr Gets POSIX.1b message queue attributes
mq_notify Registers a request to be notified when a message arrives on an empty message queue
mq_open Creates/accesses a POSIX.1b message queue
mq_receive Receives a message from a POSIX.1b message queue
mq_send Sends a message on a POSIX.1b message queue
mq_setattr Sets a subset of POSIX.1b message queue attributes
msync Makes a mapping consistent with the underlying object
munlock Unlocks a range of memory
munlockall Unlocks the entire address space
munmap Undo mapping established by mmap
nanosleep Pauses execution for a number of nanoseconds
sched_get_priority_max Gets maximum priority value for a scheduler
sched_get_priority_min Gets minimum priority value for a scheduler
sched_getparam Retrieves scheduling parameters for a particular process
sched_getscheduler Retrieves scheduling algorithm for a particular purpose
sched_rr_get_interval Gets the SCHED_RR interval for the named process
sched_setparam Sets scheduling parameters for a process
sched_setscheduler Sets scheduling algorithm/parameters for a process
sched_yield Yields the processor
sem_close Terminates access to a POSIX.1b semaphore
sem_destroy De-initializes a POSIX.1b unnamed semaphore
sem_getvalue Gets the value of a POSIX.1b semaphore
sem_open Creates/accesses a POSIX.1b named semaphore
sem_post Posts (signal) a POSIX.1b named or unnamed semaphore
sem_unlink Destroys a POSIX.1b named semaphore
sem_wait, sem_trywait Waits on a POSIX.1b named or unnamed semaphore
shm_open Creates/accesses a POSIX.1b shared memory object
shm_unlink Destroys a POSIX.1b shared memory object
sigwaitinfosigtimedwait Synchronously awaits signal arrival; avoid calling handler
timer_create Creates a POSIX.1b timer based on a particular clock
timer_delete Deletes a POSIX.1b timer
timer_gettime Time remaining on a POSIX.1b timer before expiration
timer_settime Sets expiration time/interval for a POSIX.1b timer
wait, waitpid Retrieves status of a terminated process and clean up corpse
POSIX.1c function calls Function POSIX Description
pthread_atfork Declares procedures to be called before and after a fork
pthread_attr_destroy Destroys a thread attribute object
pthread_attr_getdetachstate Obtains the setting of the detached state of a thread
pthread_attr_getinheritsched Obtains the setting of the scheduling inheritance of a thread
pthread_attr_getschedparam Obtains the parameters associated with the scheduling policy attribute of a thread
pthread_attr_getschedpolicy Obtains the setting of the scheduling policy of a thread
pthread_attr_getscope Obtains the setting of the scheduling scope of a thread
pthread_attr_getstackaddr Obtains the stack address of a thread
pthread_attr_getstacksize Obtains the stack size of a thread
pthread_attr_init Initializes a thread attribute object
pthread_attr_setdetachstate Adjusts the detached state of a thread
pthread_attr_setinheritsched Adjusts the scheduling inheritance of a thread
pthread_attr_setschedparam Adjusts the parameters associated with the scheduling policy of a thread
pthread_attr_setschedpolicy Adjusts the scheduling policy of a thread
pthread_attr_setscope Adjusts the scheduling scope of a thread
pthread_attr_setstackaddr Adjusts the stack address of a thread
pthread_attr_setstacksize Adjusts the stack size of a thread
pthread_cancel Cancels the specific thread
pthread_cleanup_pop Removes the routine from the top of a thread's cleanup stack, and if execute is nonzero, runs it
pthread_cleanup_push Places a routine on the top of a thread's cleanup stack
pthread_condattr_destroy Destroys a condition variable attribute object
pthread_condattr_getpshared Obtains the process-shared setting of a condition variable attribute object
pthread_condattr_init Initializes a condition variable attribute object
pthread_condattr_setpshared Sets the process-shared attribute in a condition variable attribute object to either PTHREAD_PROCESS_SHARED or PTHREAD_PROCESS_PRIVATE
pthread_cond_broadcast Unblocks all threads that are waiting on a condition variable
pthread_cond_destroy Destroys a condition variable
pthread_cond_init Initializes a condition variable with the attributes specified in the specified condition variable attribute object
pthread_cond_signal Unblocks at least one thread waiting on a condition variable
pthread_cond_timedwait Automatically unlocks the specified mutex, and places the calling thread into a wait state
pthread_cond_wait Automatically unlocks the specified mutex, and places the calling thread into a wait state
pthread_create Creates a thread with the attributes specified in attr
pthread_detach Marks a threads internal data structures for deletion
pthread_equal Compares one thread handle to another thread handle
pthread_exit Terminates the calling thread
pthread_getschedparam Obtains both scheduling policy and scheduling parameters of an existing thread
pthread_getspecific Obtains the thread specific data value associated with the specific key in the calling thread
pthread_join Causes the calling thread to wait for the specific thread<61>s termination
pthread_key_create Generates a unique thread-specific key that's visible to all threads in a process
pthread_key_delete Deletes a thread specific key
pthread_kill Delivers a signal to the specified thread
pthread_mutexattr_destroy Destroys a mutex attribute object
pthread_mutexattr_getprioceiling Obtains the priority ceiling of a mutex attribute object
pthread_mutexattr_getprotocol Obtains protocol of a mutex attribute object
pthread_mutexattr_getpshared Obtains a process-shared setting of a mutex attribute object
pthread_mutexattr_init Initializes a mutex attribute object
pthread_mutexattr_setprioceiling Sets the priority ceiling attribute of a mutex attribute object
pthread_mutexattr_setprotocol Sets the protocol attribute of a mutex attribute object
pthread_mutexattr_setpshared Sets the process-shared attribute of a mutex attribute object to either PTHREAD_PROCESS_SHARED or PTHREAD_PROCESS_PRIVATE
pthread_mutex_destroy Destroys a mutex
pthread_mutex_init Initializes a mutex with the attributes specified in the specified mutex attribute object
pthread_mutex_lock Locks an unlocked mutex
pthread_mutex_trylock Tries to lock a not tested
pthread_mutex_unlock Unlocks a mutex
pthread_once Ensures that init_routine will run just once regardless of how many threads in the process call it
pthread_self Obtains a thread handle of a calling thread
pthread_setcancelstate Sets a thread's cancelability state
pthread_setcanceltype Sets a thread's cancelability type
pthread_setschedparam Adjusts the scheduling policy and scheduling parameters of an existing thread
pthread_setspecific Sets the thread-specific data value associated with the specific key in the calling thread
pthread_sigmask Examines or changes the calling thread's signal mask
pthread_testcancel Requests that any pending cancellation request be delivered to the calling thread

11
doc/readme.txt Executable file
View File

@@ -0,0 +1,11 @@
============================
Nimrod's documenation system
============================
This folder contains Nimrod's documentation. The documentation
is written in a format called *reStructuredText*, a markup language that reads
like ASCII and can be converted to HTML, Tex and other formats automatically!
Unfortunately reStructuredText does not allow to colorize source code in the
HTML page. Therefore a postprocessor runs over the generated HTML code, looking
for Nimrod code fragments and colorizing them.

296
doc/regexprs.txt Executable file
View File

@@ -0,0 +1,296 @@
Licence of the PCRE library
===========================
PCRE is a library of functions to support regular expressions whose
syntax and semantics are as close as possible to those of the Perl 5
language.
| Written by Philip Hazel
| Copyright (c) 1997-2005 University of Cambridge
----------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of Cambridge nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Regular expression syntax and semantics
=======================================
As the regular expressions supported by this module are enormous,
the reader is referred to http://perldoc.perl.org/perlre.html for the
full documentation of Perl's regular expressions.
Because the backslash ``\`` is a meta character both in the Nimrod
programming language and in regular expressions, it is strongly
recommended that one uses the *raw* strings of Nimrod, so that
backslashes are interpreted by the regular expression engine::
r"\S" # matches any character that is not whitespace
A regular expression is a pattern that is matched against a subject string
from left to right. Most characters stand for themselves in a pattern, and
match the corresponding characters in the subject. As a trivial example,
the pattern::
The quick brown fox
matches a portion of a subject string that is identical to itself.
The power of regular expressions comes from the ability to include
alternatives and repetitions in the pattern. These are encoded in
the pattern by the use of metacharacters, which do not stand for
themselves but instead are interpreted in some special way.
There are two different sets of metacharacters: those that are recognized
anywhere in the pattern except within square brackets, and those that are
recognized in square brackets. Outside square brackets, the metacharacters
are as follows:
============== ============================================================
meta character meaning
============== ============================================================
``\`` general escape character with several uses
``^`` assert start of string (or line, in multiline mode)
``$`` assert end of string (or line, in multiline mode)
``.`` match any character except newline (by default)
``[`` start character class definition
``|`` start of alternative branch
``(`` start subpattern
``)`` end subpattern
``?`` extends the meaning of ``(``
also 0 or 1 quantifier
also quantifier minimizer
``*`` 0 or more quantifier
``+`` 1 or more quantifier
also "possessive quantifier"
``{`` start min/max quantifier
============== ============================================================
Part of a pattern that is in square brackets is called a "character class".
In a character class the only metacharacters are:
============== ============================================================
meta character meaning
============== ============================================================
``\`` general escape character
``^`` negate the class, but only if the first character
``-`` indicates character range
``[`` POSIX character class (only if followed by POSIX syntax)
``]`` terminates the character class
============== ============================================================
The following sections describe the use of each of the metacharacters.
Backslash
---------
The `backslash`:idx: character has several uses. Firstly, if it is followed
by a non-alphanumeric character, it takes away any special meaning that
character may have. This use of backslash as an escape character applies
both inside and outside character classes.
For example, if you want to match a ``*`` character, you write ``\*`` in
the pattern. This escaping action applies whether or not the following
character would otherwise be interpreted as a metacharacter, so it is always
safe to precede a non-alphanumeric with backslash to specify that it stands
for itself. In particular, if you want to match a backslash, you write ``\\``.
Non-printing characters
-----------------------
A second use of backslash provides a way of encoding non-printing characters
in patterns in a visible manner. There is no restriction on the appearance of
non-printing characters, apart from the binary zero that terminates a pattern,
but when a pattern is being prepared by text editing, it is usually easier to
use one of the following escape sequences than the binary character it
represents::
============== ============================================================
character meaning
============== ============================================================
``\a`` alarm, that is, the BEL character (hex 07)
``\e`` escape (hex 1B)
``\f`` formfeed (hex 0C)
``\n`` newline (hex 0A)
``\r`` carriage return (hex 0D)
``\t`` tab (hex 09)
``\ddd`` character with octal code ddd, or backreference
``\xhh`` character with hex code hh
============== ============================================================
After ``\x``, from zero to two hexadecimal digits are read (letters can be in
upper or lower case). In UTF-8 mode, any number of hexadecimal digits may
appear between ``\x{`` and ``}``, but the value of the character code must be
less than 2**31 (that is, the maximum hexadecimal value is 7FFFFFFF). If
characters other than hexadecimal digits appear between ``\x{`` and ``}``, or
if there is no terminating ``}``, this form of escape is not recognized.
Instead, the initial ``\x`` will be interpreted as a basic hexadecimal escape,
with no following digits, giving a character whose value is zero.
After ``\0`` up to two further octal digits are read. In both cases, if there
are fewer than two digits, just those that are present are used. Thus the
sequence ``\0\x\07`` specifies two binary zeros followed by a BEL character
(code value 7). Make sure you supply two digits after the initial zero if
the pattern character that follows is itself an octal digit.
The handling of a backslash followed by a digit other than 0 is complicated.
Outside a character class, PCRE reads it and any following digits as a
decimal number. If the number is less than 10, or if there have been at least
that many previous capturing left parentheses in the expression, the entire
sequence is taken as a back reference. A description of how this works is
given later, following the discussion of parenthesized subpatterns.
Inside a character class, or if the decimal number is greater than 9 and
there have not been that many capturing subpatterns, PCRE re-reads up to
three octal digits following the backslash, and generates a single byte
from the least significant 8 bits of the value. Any subsequent digits stand
for themselves. For example:
============== ============================================================
example meaning
============== ============================================================
``\040`` is another way of writing a space
``\40`` is the same, provided there are fewer than 40 previous
capturing subpatterns
``\7`` is always a back reference
``\11`` might be a back reference, or another way of writing a tab
``\011`` is always a tab
``\0113`` is a tab followed by the character "3"
``\113`` might be a back reference, otherwise the character with
octal code 113
``\377`` might be a back reference, otherwise the byte consisting
entirely of 1 bits
``\81`` is either a back reference, or a binary zero followed by
the two characters "8" and "1"
============== ============================================================
Note that octal values of 100 or greater must not be introduced by a leading
zero, because no more than three octal digits are ever read.
All the sequences that define a single byte value or a single UTF-8 character
(in UTF-8 mode) can be used both inside and outside character classes. In
addition, inside a character class, the sequence ``\b`` is interpreted as the
backspace character (hex 08), and the sequence ``\X`` is interpreted as the
character "X". Outside a character class, these sequences have different
meanings (see below).
Generic character types
-----------------------
The third use of backslash is for specifying `generic character types`:idx:.
The following are always recognized:
============== ============================================================
character type meaning
============== ============================================================
``\d`` any decimal digit
``\D`` any character that is not a decimal digit
``\s`` any whitespace character
``\S`` any character that is not a whitespace character
``\w`` any "word" character
``\W`` any "non-word" character
============== ============================================================
Each pair of escape sequences partitions the complete set of characters into
two disjoint sets. Any given character matches one, and only one, of each pair.
These character type sequences can appear both inside and outside character
classes. They each match one character of the appropriate type. If the
current matching point is at the end of the subject string, all of them fail,
since there is no character to match.
For compatibility with Perl, ``\s`` does not match the VT character (code 11).
This makes it different from the the POSIX "space" class. The ``\s`` characters
are HT (9), LF (10), FF (12), CR (13), and space (32).
A "word" character is an underscore or any character less than 256 that is
a letter or digit. The definition of letters and digits is controlled by
PCRE's low-valued character tables, and may vary if locale-specific matching
is taking place (see "Locale support" in the pcreapi page). For example,
in the "fr_FR" (French) locale, some character codes greater than 128 are
used for accented letters, and these are matched by ``\w``.
In UTF-8 mode, characters with values greater than 128 never match ``\d``,
``\s``, or ``\w``, and always match ``\D``, ``\S``, and ``\W``. This is true
even when Unicode character property support is available.
Simple assertions
-----------------
The fourth use of backslash is for certain `simple assertions`:idx:. An
assertion specifies a condition that has to be met at a particular point in
a match, without consuming any characters from the subject string. The use of
subpatterns for more complicated assertions is described below. The
backslashed assertions are::
============== ============================================================
assertion meaning
============== ============================================================
``\b`` matches at a word boundary
``\B`` matches when not at a word boundary
``\A`` matches at start of subject
``\Z`` matches at end of subject or before newline at end
``\z`` matches at end of subject
``\G`` matches at first matching position in subject
============== ============================================================
These assertions may not appear in character classes (but note that ``\b``
has a different meaning, namely the backspace character, inside a character
class).
A word boundary is a position in the subject string where the current
character and the previous character do not both match ``\w`` or ``\W`` (i.e.
one matches ``\w`` and the other matches ``\W``), or the start or end of the
string if the first or last character matches ``\w``, respectively.
The ``\A``, ``\Z``, and ``\z`` assertions differ from the traditional
circumflex and dollar in that they only ever match at the very start and
end of the subject string, whatever options are set.
The difference between ``\Z`` and ``\z`` is that ``\Z`` matches before
a newline that is the last character of the string as well as at the end
of the string, whereas ``\z`` matches only at the end.
..
Regular expressions in Nimrod itself!
-------------------------------------
'a' -- matches the character a
'a'-'z' -- range operator '-'
'A' | 'B' -- alternative operator |
* 'a' -- prefix * is needed
+ 'a' -- prefix + is needed
? 'a' -- prefix ? is needed
letter -- character classes with real names!
letters
white
whites
any -- any character
() -- are Nimrod syntax
! 'a'-'z'
-- concatentation via proc call:
re('A' 'Z' word * )

111
doc/rst.txt Executable file
View File

@@ -0,0 +1,111 @@
===========================================================================
Nimrod's implementation of |rst|
===========================================================================
:Author: Andreas Rumpf
:Version: |nimrodversion|
.. contents::
Introduction
============
This document describes the subset of `Docutils`_' `reStructuredText`_ as it
has been implemented in the Nimrod compiler for generating documentation.
Elements of |rst| that are not listed here have not been implemented.
Unfortunately, the specification of |rst| is quite vague, so Nimrod is not as
compatible to the original implementation as one would like.
Even though Nimrod's |rst| parser does not parse all constructs, it is pretty
usable. The missing features can easily be circumvented. An indication of this
fact is that Nimrod's
*whole* documentation itself (including this document) is
processed by Nimrod's |rst| parser. (Which is an order of magnitude faster than
Docutils' parser.)
Inline elements
===============
Ordinary text may contain *inline elements*.
Bullet lists
============
*Bullet lists* look like this::
* Item 1
* Item 2 that
spans over multiple lines
* Item 3
* Item 4
- bullet lists may nest
- item 3b
- valid bullet characters are ``+``, ``*`` and ``-``
This results in:
* Item 1
* Item 2 that
spans over multiple lines
* Item 3
* Item 4
- bullet lists may nest
- item 3b
- valid bullet characters are ``+``, ``*`` and ``-``
Enumerated lists
================
*Enumerated lists*
Defintion lists
===============
Save this code to the file "greeting.nim". Now compile and run it:
``nimrod run greeting.nim``
As you see, with the ``run`` command Nimrod executes the file automatically
after compilation. You can even give your program command line arguments by
appending them after the filename that is to be compiled and run:
``nimrod run greeting.nim arg1 arg2``
Tables
======
Nimrod only implements simple tables of the form::
================== =============== ===================
header 1 header 2 header n
================== =============== ===================
Cell 1 Cell 2 Cell 3
Cell 4 Cell 5; any Cell 6
cell that is
not in column 1
may span over
multiple lines
Cell 7 Cell 8 Cell 9
================== =============== ===================
This results in:
================== =============== ===================
header 1 header 2 header n
================== =============== ===================
Cell 1 Cell 2 Cell 3
Cell 4 Cell 5; any Cell 6
cell that is
not in column 1
may span over
multiple lines
Cell 7 Cell 8 Cell 9
================== =============== ===================
.. |rst| replace:: reStructuredText
.. _reStructuredText: http://docutils.sourceforge.net/rst.html#reference-documentation
.. _docutils: http://docutils.sourceforge.net/

1297
doc/spec.txt Executable file

File diff suppressed because it is too large Load Diff

1436
doc/theindex.txt Executable file

File diff suppressed because it is too large Load Diff

215
doc/tutorial.txt Executable file
View File

@@ -0,0 +1,215 @@
===========================================
Tutorial of the Nimrod Programming Language
===========================================
:Author: Andreas Rumpf
Motivation
==========
Why yet another programming language?
Look at the trends behind all the new programming languages:
* They try to be dynamic: Dynamic typing, dynamic method binding, etc.
In my opinion the most things the dynamic features buy could be achieved
with static means in a more efficient and *understandable* way.
* They depend on big runtime environments which you need to
ship with your program as each new version of these may break compability
in subtle ways or you use recently added features - thus forcing your
users to update their runtime environment. Compiled programs where the
executable contains all needed code are simply the better solution.
* They are unsuitable for systems programming: Do you really want to
write an operating system, a device driver or an interpreter in a language
that is just-in-time compiled (or interpreted)?
So what lacks are *good* systems programming languages. Nimrod is such a
language. It offers the following features:
* It is readable: It reads from left to right (unlike the C-syntax
languages).
* It is strongly and statically typed: This enables the compiler to find
more errors. Static typing also makes programs more *readable*.
* It is compiled. (Currently this is done via compilation to C.)
* It is garbage collected. Big systems need garbage collection. Manuell
memory management is also supported through *untraced pointers*.
* It scales because high level features are also available: It has built-in
bit sets, strings, enumerations, objects, arrays and dynamically resizeable
arrays (called *sequences*).
* It has high performance: The current implementation compiles to C
and uses a Deutsch-Bobrow garbage collector together with Christoper's
partial mark-sweep garbage collector leading to excellent execution
speed and a small memory footprint.
* It has real modules with proper interfaces and supports separate
compilation.
* It is portable: It compiles to C and platform specific features have
been separated and documented. So even if your platform is not supported
porting should be easy.
* It is flexible: Although primilarily a procedural language, generic,
functional and object-oriented programming is also supported.
* It is easy to learn, easy to use and leads to elegant programs.
* You can link an embedded debugger to your program (ENDB). ENDB is
very easy to use - there is no need to clutter your code with
``echo`` statements for proper debugging.
Introduction
============
This document is a tutorial for the programming language *Nimrod*. It should
be a readable quick tour through the language instead of a dry specification
(which can be found `here <manual.html>`_). This tutorial assumes that
the reader already knows some other programming language such as Pascal. Thus
it is detailed in cases where Nimrod differs from other programming languages
and kept short where Nimrod is more or less the same.
A quick tour through the language
=================================
The first program
-----------------
We start the tour with a modified "hallo world" program:
.. code-block:: Nimrod
# This is a comment
# Standard IO-routines are always accessible
write(stdout, "What's your name? ")
var name: string = readLine(stdin)
write(stdout, "Hi, " & name & "!\n")
Save this code to the file "greeting.nim". Now compile and run it::
nimrod run greeting.nim
As you see, with the ``run`` command Nimrod executes the file automatically
after compilation. You can even give your program command line arguments by
appending them after the filename that is to be compiled and run::
nimrod run greeting.nim arg1 arg2
Though it should be pretty obvious what the program does, I will explain the
syntax: Statements which are not indented are executed when the program
starts. Indentation is Nimrod's way of grouping statements. String literals
are enclosed in double quotes. The ``var`` statement declares a new variable
named ``name`` of type ``string`` with the value that is returned by the
``readline`` procedure. Since the compiler knows that ``readline`` returns
a string, you can leave out the type in the declaration. So this will work too:
.. code-block:: Nimrod
var name = readline(stdin)
Note that this is the only form of type inference that exists in Nimrod:
This is because it yields a good compromise between brevity and readability.
The ``&`` operator concates strings together. ``\n`` stands for the
new line character(s). On several operating systems ``\n`` is represented by
*two* characters: Linefeed and Carriage Return. That is why
*character literals* cannot contain ``\n``. But since Nimrod handles strings
so well, this is a nonissue.
The "hallo world" program contains several identifiers that are already
known to the compiler: ``write``, ``stdout``, ``readLine``, etc. These
built-in items are declared in the system_ module which is implicitly
imported by any other module.
Lexical elements
----------------
Let us look into Nimrod's lexical elements in more detail: Like other
programming languages Nimrod consists of identifiers, keywords, comments,
operators, and other punctation marks. Case is *insignificant* in Nimrod and
even underscores are ignored: ``This_is_an_identifier`` and this is the same
identifier ``ThisIsAnIdentifier``. This feature enables one to use other
peoples code without bothering about a naming convention that one does not
like.
String literals are enclosed in double quotes, character literals in single
quotes. There exist also *raw* string and character literals:
.. code-block:: Nimrod
r"C:\program files\nim"
In raw literals the backslash is not an escape character, so they fit
the principle *what you see is what you get*. *Long string literals*
are also available (``""" ... """``); they can span over multiple lines
and the ``\`` is not an escape character either. They are very useful
for embedding SQL code templates for example.
Comments start with ``#`` and run till the end of the line. (Well this is not
quite true, but you should read the manual for a proper explanation.)
... XXX number literals
The usual statements - if, while, for, case
-------------------------------------------
In Nimrod indentation is used to group statements.
An example showing the most common statement types:
.. code-block:: Nimrod
var name = readLine(stdin)
if name == "Andreas":
echo("What a nice name!")
elif name == "":
echo("Don't you have a name?")
else:
echo("Boring name...")
for i in 0..length(name)-1:
if name[i] == 'm':
echo("hey, there is an *m* in your name!")
echo("Please give your password: \n")
var pw = readLine(stdin)
while pw != "12345":
echo("Wrong password! Next try: \n")
pw = readLine(stdin)
echo("""Login complete!
What do you want to do?
delete-everything
restart-computer
go-for-a-walk
""")
case readline(stdin)
of "delete-everything", "restart-computer":
echo("permission denied")
of "go-for-a-walk": echo("please yourself")
else: echo("unknown command")
..
Types
-----
Nimrod has a rich type system. This tutorial only gives a few examples. Read
the `manual <manual.html>`_ for further information:
.. code-block:: Nimrod
type
TMyRecord = record
x, y: int
Procedures
----------
Procedures are subroutines. They are declared in this way:
.. code-block:: Nimrod
proc findSubStr(sub: string,
.. _strutils: strutils.html
.. _system: system.html

24
dos2unix.py Executable file
View File

@@ -0,0 +1,24 @@
#! /usr/bin/env python
"Replace CRLF with LF in argument files. Print names of changed files."
import sys, os, glob
def main():
for arg in sys.argv[1:]:
for filename in glob.glob(arg):
if os.path.isdir(filename):
print filename, "Directory!"
continue
data = open(filename, "rb").read()
if '\0' in data:
print filename, "Binary!"
continue
newdata = data.replace("\r\n", "\n")
if newdata != data:
print filename
f = open(filename, "wb")
f.write(newdata)
f.close()
if __name__ == '__main__':
main()

302
gcccpuopt.sh Executable file
View File

@@ -0,0 +1,302 @@
#!/bin/sh
# Print the gcc cpu specific options appropriate for the current CPU
# Author:
# http://www.pixelbeat.org/
# Notes:
# This script currently supports Linux,FreeBSD,Cygwin
# This script is x86 (32 bit) specific
# It should work on any gcc >= 2.95 at least
# It only returns CPU specific options. You probably also want -03 etc.
# Changes:
# V0.1, 12 Mar 2003, Initial release
# V0.2, 01 Jun 2005, Added support for 3.2>=gcc<=4.0
# V0.3, 03 Jun 2005, Added support for pentium-m
# V0.4, 03 Jun 2005, Fix silly bugs
# V0.5, 07 Jun 2005, Clarify/Simplify confusing floating point expr usage
# Print warning when CPU only supported on a newer gcc
# V0.6, 15 Dec 2006, Added support for Intel Core and Core 2 processors
# Added support for 4.1>=gcc<=4.3
# Added support for gcc -msse3 option
# Added support for new gcc -march=native option
# V0.7, 18 Dec 2006, Changes from Conor McDermottroe
# Added support for FreeBSD
# Remove bash specific constructs
# Better error handling
# V0.8, 19 Dec 2006, Give warnings and 32 bit -march on 64 bit platforms.
# Previously it just gave an invalid blank -march.
# Reported and tested by Ewan Oughton.
# V0.9, 30 Apr 2007, Give error if compiler not present.
# Warn about rather than default to -march=native option.
# V0.92, 08 Nov 2007, Change from Krzysztof Jankowski to support Cygwin.
# Added support for AMD family 10 processors.
# Add support for gcc -msse4 & -msse5 options.
# Use "prescott" rather than "pentium4" for all
# models >= 3 in intel family 15, not just model 3.
# V0.93, 13 Nov 2007, Oops, actually not all intel family 15, model >= 3
# are prescotts. Use the sse3 flag to distinguish.
# V0.94, 31 Dec 2007, Oops, actually all intel family 15, model >= 3
# are prescotts. This was indicated by Adam Drzewiecki.
# I was confused by a bug in older linux kernels where pni
# was not reported for my intel "F41" processor at least.
# V0.95, 18 Jan 2008, Changes from Conor McDermottroe
# Support for Mac OS X
# Support for FreeBSD base system
if [ "$1" = "--version" ]; then
echo "0.95" && exit
fi
# This table shows when -march options were introduced into _official_ gcc releases.
# Note there are vendor deviations that complicate this.
# For e.g. redhat introduced the prescott option in 3.3-13.
# gcc-2.95 = i386, i486, i586,pentium, i686,pentiumpro, k6
# gcc-3.0 += athlon
# gcc-3.1 += pentium-mmx, pentium2, pentium3, pentium4, k6-2, k6-3, athlon-{tbird, 4,xp,mp}
# gcc-3.3 += winchip-c6, winchip2, c3
# gcc-3.4.0 += k8,opteron,athlon64,athlon-fx, c3-2
# gcc-3.4.1 += pentium-m, pentium3m, pentium4m, prescott, nocona
# gcc-4.3 += core2, amdfam10
[ -z "$CC" ] && CC=gcc
try_gcc_options() {
$CC $* -S -o /dev/null -xc /dev/null >/dev/null 2>&1
}
if ! try_gcc_options; then
echo "Error: Couldn't execute your compiler ($CC)" >&2
exit 1
fi
if try_gcc_options -march=native; then
echo "Warning: Your compiler supports the -march=native option which you may prefer" >&2
fi
if ! try_gcc_options -march=i386; then
if ! try_gcc_options -m32 -march=i386; then
echo "Error: This script only supports 32 bit x86 architectures" >&2
exit 1
else
echo "Warning: The optimum *32 bit* architecture is reported" >&2
m32="-m32 "
fi
fi
try_line() {
skip=0
for arch in $1; do
if try_gcc_options $m32 -march=$arch; then
echo $arch
return
elif [ "$skip" = "0" ] && [ "$arch" != "native" ]; then
skip=1
echo "Warning: Newer versions of GCC better support your CPU with -march=$arch" >&2
fi
done
return 1
}
read_cpu_data_linux() {
IFS=":"
while read name value; do
unset IFS
name=`echo $name`
value=`echo $value`
IFS=":"
if [ "$name" = "vendor_id" ]; then
vendor_id="$value"
elif [ "$name" = "cpu family" ]; then
cpu_family="$value"
elif [ "$name" = "model" ]; then
cpu_model="$value"
elif [ "$name" = "flags" ]; then
flags="$value"
break #flags last so break early
fi
done < /proc/cpuinfo
unset IFS
}
read_cpu_data_freebsd() {
local _line _cpu_id
if [ ! -r /var/run/dmesg.boot ]; then
echo "/var/run/dmesg.boot does not exist!"
exit 1;
fi
IFS="
"
for _line in `grep -A2 '^CPU: ' /var/run/dmesg.boot`; do
if [ -n "`echo $_line | grep '^ Origin = '`" ]; then
vendor_id="`echo $_line | sed -e 's/^ Origin = .//' -e 's/[^A-Za-z0-9].*$//'`"
_cpu_id="`echo $_line | sed -e 's/^.*Id = //' -e 's/ .*$//' -e 'y/abcdef/ABCDEF/'`"
cpu_family=$((($_cpu_id & 0xF0F) >> 8))
cpu_model=$((($_cpu_id & 0xF0) >> 4))
fi
if [ -n "`echo $_line | grep '^ Features='`" ]; then
flags="`echo $_line | sed -e 's/^.*<//' -e 's/>.*//' -e 's/,/ /g' | tr 'A-Z' 'a-z'`"
fi
done
unset IFS
}
read_cpu_data_darwin() {
vendor_id="`/usr/sbin/sysctl -n machdep.cpu.vendor`"
cpu_family="`/usr/sbin/sysctl -n machdep.cpu.family`"
cpu_model="`/usr/sbin/sysctl -n machdep.cpu.model`"
flags="`/usr/sbin/sysctl -n machdep.cpu.features | tr 'A-Z' 'a-z'`"
}
read_cpu_data() {
# Default values
vendor_id="Unset"
cpu_family="-1"
cpu_model="-1"
flags=""
if [ "`uname`" = "Linux" ]; then
read_cpu_data_linux
elif [ "`uname`" = "FreeBSD" ]; then
read_cpu_data_freebsd
elif [ "`uname | sed 's/\(CYGWIN\).*/\1/'`" = "CYGWIN" ]; then
read_cpu_data_linux
elif [ "`uname`" = "Darwin" ]; then
read_cpu_data_darwin
else
echo "Error: `uname` is not a supported operating system"
exit 1
fi
}
read_cpu_data
if [ "$vendor_id" = "AuthenticAMD" ]; then
if [ $cpu_family -eq 4 ]; then
_CFLAGS="-march=i486"
elif [ $cpu_family -eq 5 ]; then
if [ $cpu_model -lt 4 ]; then
_CFLAGS="-march=pentium"
elif [ \( $cpu_model -eq 6 \) -o \( $cpu_model -eq 7 \) ]; then
_CFLAGS="-march=k6"
elif [ \( $cpu_model -eq 8 \) -o \( $cpu_model -eq 12 \) ]; then
line="k6-2 k6"
elif [ \( $cpu_model -eq 9 \) -o \( $cpu_model -eq 13 \) ]; then
line="k6-3 k6-2 k6"
fi
elif [ $cpu_family -eq 6 ]; then
if [ $cpu_model -le 3 ]; then
line="athlon k6-3 k6-2 k6"
elif [ $cpu_model -eq 4 ]; then
line="athlon-tbird athlon k6-3 k6-2 k6"
elif [ $cpu_model -ge 6 ]; then #athlon-{4,xp,mp}
line="athlon-4 athlon k6-3 k6-2 k6"
fi
elif [ $cpu_family -eq 15 ]; then #k8,opteron,athlon64,athlon-fx
line="k8 athlon-4 athlon k6-3 k6-2 k6"
elif [ $cpu_family -eq 16 ]; then #barcelona,amdfam10
line="amdfam10 k8 athlon-4 athlon k6-3 k6-2 k6"
fi
elif [ "$vendor_id" = "CentaurHauls" ]; then
if [ $cpu_family -eq 5 ]; then
if [ $cpu_model -eq 4 ]; then
line="winchip-c6 pentium"
elif [ $cpu_model -eq 8 ]; then
line="winchip2 winchip-c6 pentium"
elif [ $cpu_model -ge 9 ]; then
line="winchip2 winchip-c6 pentium" #actually winchip3 but gcc doesn't support this currently
fi
elif [ $cpu_family -eq 6 ]; then
if echo "$flags" | grep -q cmov; then
fallback=pentiumpro
else
fallback=pentium #gcc incorrectly assumes i686 always has cmov
fi
if [ $cpu_model -eq 6 ]; then
_CFLAGS="-march=pentium" # ? Cyrix 3 (samuel)
elif [ $cpu_model -eq 7 ] || [ $cpu_model -eq 8 ]; then
line="c3 winchip2 winchip-c6 $fallback"
elif [ $cpu_model -ge 9 ]; then
line="c3-2 c3 winchip2 winchip-c6 $fallback"
fi
fi
elif [ "$vendor_id" = "GenuineIntel" ]; then
if [ $cpu_family -eq 3 ]; then
_CFLAGS="-march=i386"
elif [ $cpu_family -eq 4 ]; then
_CFLAGS="-march=i486"
elif [ $cpu_family -eq 5 ]; then
if [ $cpu_model -ne 4 ]; then
_CFLAGS="-march=pentium"
else
line="pentium-mmx pentium" #No overlap with other vendors
fi
elif [ $cpu_family -eq 6 ]; then
if [ \( $cpu_model -eq 0 \) -o \( $cpu_model -eq 1 \) ]; then
_CFLAGS="-march=pentiumpro"
elif [ \( $cpu_model -ge 3 \) -a \( $cpu_model -le 6 \) ]; then #4=TM5600 at least
line="pentium2 pentiumpro pentium-mmx pentium i486 i386"
elif [ \( $cpu_model -eq 9 \) -o \( $cpu_model -eq 13 \) ]; then #centrino
line="pentium-m pentium4 pentium3 pentium2 pentiumpro pentium-mmx pentium i486 i386"
elif [ $cpu_model -eq 14 ]; then #Core
line="prescott pentium-m pentium4 pentium3 pentium2 pentiumpro pentium-mmx pentium i486 i386"
elif [ $cpu_model -eq 15 ]; then #Core 2
line="core2 pentium-m pentium4 pentium3 pentium2 pentiumpro pentium-mmx pentium i486 i386"
elif [ \( $cpu_model -ge 7 \) -a \( $cpu_model -le 11 \) ]; then
line="pentium3 pentium2 pentiumpro pentium-mmx pentium i486 i386"
fi
elif [ $cpu_family -eq 15 ]; then
line="pentium4 pentium3 pentium2 pentiumpro pentium-mmx pentium i486 i386"
if [ $cpu_model -ge 3 ]; then
line="prescott $line"
fi
fi
else
echo "Unknown CPU Vendor: $vendor_id"
exit 1
fi
[ -z "$_CFLAGS" ] && _CFLAGS="-march=`try_line "$line"`"
#SSE is not used for floating point by default in gcc 32 bit
#so turn that on here.
if echo "$flags" | grep -q "sse"; then
if try_gcc_options "-mfpmath=sse"; then #gcc >= 3.1
_CFLAGS="$_CFLAGS -mfpmath=sse"
fi
fi
#The SSE options are mostly selected automatically
#when a particular march option is selected.
#There are a few exceptions unfortunately, which we handle here.
#Note the sse instruction lines are:
# intel: [sse4.2] [sse4.1] ssse3 sse3 sse2 sse ...
# amd: [sse5] sse4a [sse3] sse2 sse ...
# The bracketed ones are only available on some cpus
# in a particular family and so need to be added explicitly.
if echo "$_CFLAGS" | grep -q "amdfam10"; then
if echo "$flags" | grep -q "sse5"; then
if try_gcc_options "-msse5"; then #gcc >= 4.3
_CFLAGS="$_CFLAGS -msse5"
fi
fi
elif echo "$_CFLAGS" | grep -E -q "(k8|c3-2)"; then
if echo "$flags" | grep -E -q "(sse3|pni)"; then
if try_gcc_options "-msse3"; then #gcc >= 3.3.3
_CFLAGS="$_CFLAGS -msse3"
fi
fi
elif echo "$_CFLAGS" | grep -q "core2"; then
if echo "$flags" | grep -q "sse4_2"; then
if try_gcc_options "-msse4"; then #gcc >= 4.3
_CFLAGS="$_CFLAGS -msse4"
fi
elif echo "$flags" | grep -q "sse4_1"; then
if try_gcc_options "-msse4.1"; then #gcc >= 4.3
_CFLAGS="$_CFLAGS -msse4.1"
fi
fi
fi
echo "$m32$_CFLAGS"

369
ide/main.nim Executable file
View File

@@ -0,0 +1,369 @@
import glib2, gtk2, libglade2
proc on_window_destroy(obj: PGtkObject, data: pointer) {.exportc, cdecl.} =
gtk_main_quit()
const
GuiTemplate = "/media/hda4/nimrod/ide/nimide.glade"
type
TMyTextEditor = record
window: PGtkWindow
statusbar: PGtkStatusBar
textview: PGtkTextview
statusbarContextId: int
filename: string
proc error_message(msg: string) =
var
dialog: PGtkDialog
dialog = GTK_DIALOG(gtk_message_dialog_new(nil,
GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, msg))
gtk_window_set_title(dialog, "Error!")
gtk_dialog_run(dialog)
gtk_widget_destroy(dialog)
proc get_open_filename(e: TMyTextEditor): string =
var
chooser: PGtkDialog
chooser = gtk_file_chooser_dialog_new("Open File...", e.window,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil)
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
result = $gtk_file_chooser_get_filename(chooser)
else:
result = ""
gtk_widget_destroy(chooser)
proc get_save_filename(e: TMyTextEditor): string =
var
chooser: PGtkDialog
chooser = gtk_file_chooser_dialog_new("Save File...", e.window,
GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil)
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
result = $gtk_file_chooser_get_filename(chooser)
else:
result = ""
gtk_widget_destroy(chooser)
proc load_file(e: var TMyTextEditor, filename: string) =
var
err: ptr GError
status: cstring
text: cstring
result: bool
buffer: PGtkTextBuffer
gtk_statusbar_push(e.statusbar, e.statusbar_context_id, "Loading...")
while gtk_events_pending(): gtk_main_iteration()
# get the file contents
result = g_file_get_contents(filename, addr(text), nil, addr(err))
if not result:
error_message("Cannot load file")
g_error_free(err)
# disable the text view while loading the buffer with the text
gtk_widget_set_sensitive(e.text_view, false)
buffer = gtk_text_view_get_buffer(e.text_view)
gtk_text_buffer_set_text(buffer, text, -1)
gtk_text_buffer_set_modified(buffer, false)
gtk_widget_set_sensitive(e.text_view, true)
g_free(text)
e.filename = filename
gtk_statusbar_pop(e.statusbar, e.statusbar_context_id)
reset_default_status(e)
proc write_file(e: var TMyTextEditor, filename: string) =
var
err: ptr GError
status: cstring
text: cstring
result: bool
buffer: PGtkTextBuffer
start, ende: TGtkTextIter
# add Saving message to status bar and ensure GUI is current
gtk_statusbar_push(e.statusbar, e.statusbar_context_id, "Saving....")
while gtk_events_pending(): gtk_main_iteration()
# disable text view and get contents of buffer
gtk_widget_set_sensitive(editor->text_view, FALSE)
buffer = gtk_text_view_get_buffer(e.text_view)
gtk_text_buffer_get_start_iter(buffer, start)
gtk_text_buffer_get_end_iter(buffer, ende)
text = gtk_text_buffer_get_text(buffer, start, ende, FALSE)
gtk_text_buffer_set_modified(buffer, false)
gtk_widget_set_sensitive(e.text_view, true)
# set the contents of the file to the text from the buffer
if filename != "":
result = g_file_set_contents(filename, text, -1, addr(err))
else:
result = g_file_set_contents(editor->filename, text, -1, addr(err))
if not result:
error_message("cannot save")
g_error_free(err)
g_free(text)
if filename != "":
e.filename = filename
gtk_statusbar_pop(e.statusbar, e.statusbar_context_id)
reset_default_status(editor)
proc initApp(e: var TMyTextEditor) =
var
builder: PGladeXML
window: PGtkWidget
fontDesc: PPangoFontDescription
id: int
builder = glade_xml_new(GuiTemplate, nil, nil)
if builder == nil:
error_message("cannot open: " & GuiTemplate)
quit(1)
# get the components:
e.window = GTK_WINDOW(glade_xml_get_widget(builder, "window"))
e.statusbar = GTK_STATUSBAR(glade_xml_get_widget(builder, "statusbar"))
e.textview = GTK_TEXTVIEW(glade_xml_get_widget(builder, "textview"))
# connect the signal handlers:
glade_xml_signal_connect(builder, "on_window_destroy",
cast[TGCallback](on_window_destroy))
font_desc = pango_font_description_from_string("monospace 10")
gtk_widget_modify_font(e.textview, font_desc)
pango_font_description_free(font_desc)
gtk_window_set_default_icon_name(GTK_STOCK_EDIT)
id = gtk_statusbar_get_context_id(e.statusbar, "Nimrod IDE")
e.statusbarContextId = id
reset_default_status(e)
e.filename = ""
proc main() =
var
editor: TMyTextEditor
gtk_nimrod_init()
initApp(editor)
gtk_widget_show(editor.window)
gtk_main()
main()
proc reset_default_status(e: var TMyTextEditor)
gchar *file;
gchar *status;
if e.filename == "":
file = g_strdup("(UNTITLED)")
else:
file = g_path_get_basename(editor->filename)
status = g_strdup_printf("File: %s", file)
gtk_statusbar_pop(e.statusbar,
e.statusbar_context_id)
gtk_statusbar_push(e.statusbar,
e.statusbar_context_id, status)
g_free(status)
g_free(file)
gboolean
check_for_save(e: var TMyTextEditor)
gboolean ret = FALSE;
GtkTextBuffer *buffer;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
if (gtk_text_buffer_get_modified (buffer) == TRUE)
{
GtkWidget *dialog;
const gchar *msg = "Do you want to save the changes you have made?";
dialog = gtk_message_dialog_new (NULL,
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
msg);
gtk_window_set_title (GTK_WINDOW (dialog), "Save?");
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_NO)
{
ret = FALSE;
} else ret = TRUE;
gtk_widget_destroy (dialog);
}
return ret;
/*
When the window is requested to be closed, we need to check if they have
unsaved work. We use this callback to prompt the user to save their work before
they exit the application. From the "delete-event" signal, we can choose to
effectively cancel the close based on the value we return.
*/
gboolean
on_window_delete_event(GtkWidget *widget, GdkEvent *event,
TutorialTextEditor *editor)
{
if (check_for_save (editor) == TRUE)
on_save_menu_item_activate (NULL, editor);
return FALSE; /* propogate event */
}
/*
Called when the user clicks the 'New' menu. We need to prompt for save if the
file has been modified, and then delete the buffer and clear the modified flag.
*/
void on_new_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
GtkTextBuffer *buffer;
if (check_for_save (editor) == TRUE)
{
on_save_menu_item_activate (NULL, editor);
}
/* clear editor for a new file */
editor->filename = NULL;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
gtk_text_buffer_set_text (buffer, "", -1);
gtk_text_buffer_set_modified (buffer, FALSE);
reset_default_status (editor);
}
/*
Called when the user clicks the 'Open' menu. We need to prompt for save if the
file has been modified, allow the user to choose a file to open, and then call
load_file() on that file.
*/
void on_open_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
gchar *filename;
if (check_for_save (editor) == TRUE)
{
on_save_menu_item_activate (NULL, editor);
}
filename = get_open_filename (editor);
if (filename != NULL) load_file (editor, filename);
}
/*
Called when the user clicks the 'Save' menu. We need to allow the user to choose
a file to save if it's an untitled document, and then call write_file() on that
file.
*/
void on_save_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
gchar *filename;
if (editor->filename == NULL)
{
filename = get_save_filename (editor);
if (filename != NULL) write_file (editor, filename);
}
else write_file (editor, NULL);
}
/*
Called when the user clicks the 'Save As' menu. We need to allow the user to
choose a file to save and then call write_file() on that file.
*/
void on_save_as_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
gchar *filename;
filename = get_save_filename (editor);
if (filename != NULL) write_file (editor, filename);
}
/*
Called when the user clicks the 'Quit' menu. We need to prompt for save if the
file has been modified and then break out of the GTK+ main loop.
*/
void on_quit_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
if (check_for_save (editor) == TRUE)
{
on_save_menu_item_activate (NULL, editor);
}
gtk_main_quit();
}
/*
Called when the user clicks the 'Cut' menu.
*/
void on_cut_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
GtkTextBuffer *buffer;
GtkClipboard *clipboard;
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
}
/*
Called when the user clicks the 'Copy' menu.
*/
void on_copy_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
GtkTextBuffer *buffer;
GtkClipboard *clipboard;
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
gtk_text_buffer_copy_clipboard (buffer, clipboard);
}
/*
Called when the user clicks the 'Paste' menu.
*/
void on_paste_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
GtkTextBuffer *buffer;
GtkClipboard *clipboard;
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
}
/*
Called when the user clicks the 'Delete' menu.
*/
void on_delete_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
GtkTextBuffer *buffer;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
gtk_text_buffer_delete_selection (buffer, FALSE, TRUE);
}
void on_about_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
{
static const gchar * const authors[] = {
"Micah Carrick <email@micahcarrick.com>",
NULL
};
static const gchar copyright[] = "Copyright \xc2\xa9 2008 Andreas Rumpf";
static const gchar comments[] = "GTK+ and Glade3 GUI Programming Tutorial";
gtk_show_about_dialog (e.window,
"authors", authors,
"comments", comments,
"copyright", copyright,
"version", "0.1",
"website", "http://www.micahcarrick.com",
"program-name", "GTK+ Text Editor",
"logo-icon-name", GTK_STOCK_EDIT, nil)
}

175
ide/nimide.glade Executable file
View File

@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.2 on Sat Jun 21 14:12:42 2008 -->
<glade-interface>
<widget class="GtkWindow" id="window">
<property name="extension_events">GDK_EXTENSION_EVENTS_ALL</property>
<signal name="destroy" handler="on_window_destroy" object="destroy"/>
<child>
<widget class="GtkVBox" id="mainvbox">
<property name="visible">True</property>
<child>
<widget class="GtkMenuBar" id="menubar">
<property name="visible">True</property>
<child>
<widget class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="label" translatable="yes">_Datei</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menu1">
<property name="visible">True</property>
<child>
<widget class="GtkImageMenuItem" id="new_menu_item">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-new</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="open_menu_item">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-open</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="save_menu_item">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-save</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="save_as_menu_item">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-save-as</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="quit_menu_item">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-quit</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem2">
<property name="visible">True</property>
<property name="label" translatable="yes">_Bearbeiten</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menu2">
<property name="visible">True</property>
<child>
<widget class="GtkImageMenuItem" id="cut_menu_item">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-cut</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="copy_menu_item">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-copy</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="paste_menu_item">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-paste</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="delete_menu_item">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-delete</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem4">
<property name="visible">True</property>
<property name="label" translatable="yes">_Hilfe</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menu3">
<property name="visible">True</property>
<child>
<widget class="GtkImageMenuItem" id="about_menu_item">
<property name="visible">True</property>
<property name="label" translatable="yes">gtk-about</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="extension_events">GDK_EXTENSION_EVENTS_ALL</property>
<property name="border_width">1</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<widget class="GtkTextView" id="textview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="left_margin">2</property>
<property name="right_margin">2</property>
</widget>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkStatusbar" id="statusbar">
<property name="visible">True</property>
<property name="spacing">2</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

101
install.txt Executable file
View File

@@ -0,0 +1,101 @@
Note: Installation does not work yet - you have to bootstrap. Play with the
``koch.py`` script to compile the compiler.
Compile the compiler::
python koch.py nim
To bootstrap (does not work yet)::
python koch.py boot
Installation
============
Note:
A C compiler is required - knowledge of C is not!
Installation on UNIX
--------------------
The GNU C Compiler is fully supported, other compilers may work. The C compiler
should be in your ``$PATH`` (most likely the case). Note that some Linux
distributions do not ship with a C compiler preinstalled - then you have to
install one.
After you have made sure that a C compiler is available, install Nimrod
by downloading the appropriate ``.zip`` file and extracting it to a
directory of your choice. The Nimrod Compiler will stay in this
directory; do not use a temporary one! Good choices are ``/opt/nimrod`` or -
if you don't have root access - ``~/programs/nimrod``.
Then run the following command::
python koch.py install
Unlike other software, Nimrod does not distribute its files over the whole file
hierarchy. This has the advantage that you can deinstall it by just deleting
its folder. The disadvantage is that you have to add it to your ``PATH``
manually. The alternative is to create a symbolic link in ``/usr/bin``::
[sudo] ln -s $your_install_dir/bin/nimrod /usr/bin/nimrod
Installation on the Macintosh
-----------------------------
Only MacOS X is supported.
Since MacOS X is UNIX based too, it works like the installation on UNIX. You
need to install Apple's developer's tools for the GNU Compiler Collection
though.
Installation on Windows
-----------------------
Windows does not ship with a C compiler; you have to install one. The
following C compilers are supported under Windows:
- | Digital Mars C++
| http://www.digitalmars.com/download/freecompiler.html
- | Watcom C++
| http://www.openwatcom.org/ftp/
- | Borland C++ (5.5 or above; including Borland C++Builder)
| http://www.borland.com/downloads/download_cbuilder.html
| (Download the package under "compiler" - this requires registration though.)
- | Microsoft's Visual C++
| http://msdn.microsoft.com/visualc
| (You may need the SDK too - but not the full one: Essential are only
the win32api header files and import libraries.)
- | Gnu C Compiler (the mingw version; the cygwin version has not been tested!)
| http://www.mingw.org/download.shtml
- | LLVM with GNU C/C++ frontend
| http://llvm.org/releases/download.html#2.2
- | Pelles C Compiler
| http://www.smorgasbordet.com/pellesc
- | Lcc-win32
| http://www.cs.virginia.edu/~lcc-win32
All of the above compilers are available for free!
(The first three are the easiest to install.) If you want a small download,
choose Digital Mars C++ -- it is easy to install and only about 3 MB.
If you want the highest possible performance, go for Microsoft's Visual C++ or
LLVM.
After you have made sure that a C compiler is available, install
Nimrod by downloading the appropriate .zip file and extracting it to a
directory of your choice. The Nimrod Compiler will stay in this
directory; do not use a temporary one! Then run ``config.exe`` in the
``bin`` subdirectory. Choose your C compiler and press ``OK``. You should
add Nimrod to your ``$PATH``.
Alternatively, you can install Nimrod with the ``koch.py`` script just like
in the UNIX installation instructions.
Nimrod does not use the Registry and can be removed by just deleting its folder.

982
koch.py Executable file
View File

@@ -0,0 +1,982 @@
#! /usr/bin/env python
##########################################################################
## ##
## Build script of the Nimrod Compiler ##
## (c) 2008 Andreas Rumpf ##
## ##
##########################################################################
import os, os.path, sys, re, zipfile, filecmp, shutil, cPickle, time
import string, getopt, textwrap, glob, shutil, getopt, string
if sys.version_info[0] >= 3: # this script does not work with Python 3.0
sys.exit("wrong python version: use Python 2.x")
from kochmod import *
# --------------------- constants ----------------------------------------
CFLAGS = "" # modify to set flags to the first compilation step
NIMROD_VERSION = '0.2.1'
# This string contains Nimrod's version. It is the only place
# where the version needs to be updated. The rest is done by
# the build process automatically. It is replaced **everywhere**
# automatically!
# Format is: Major.Minor.Patch
# Major part: plan is to use number 1 for the first version that is stable;
# higher versions may be incompatible with previous versions
# Minor part: incremented if new features are added (but is completely
# backwards-compatible)
# Patch level: is increased for every patch
EXPLAIN = True
force = False
INNOSETUP = r"c:\programme\innosetup5\iscc.exe /Q "
ADV_SETUP = r"C:\Programme\AdvancedInstaller6.1\AdvancedInstaller.com " \
r"/build %s -force"
PYINSTALLER = r"C:\Eigenes\DownLoad\Python\pyinstaller-1.3"
# --------------------------------------------------------------------------
def ask():
return sys.stdin.readline().strip("\t \n\r\f").lower()
def CogRule(name, filename, dependson):
def processCog():
from cogapp import Cog
ret = Cog().main([sys.argv[0], "-r", Path(filename)])
return ret
c = Changed(name, filename + " " + dependson, EXPLAIN)
if c or force:
if processCog() == 0:
c.update(filename)
c.success()
_nim_exe = os.path.join(os.getcwd(), "bin", ExeExt("nim"))
_output_obj = os.path.join(os.getcwd(), "obj")
FPC_CMD = (r"fpc -Cs16777216 -gl -bl -Crtoi -Sgidh -vw -Se1 -o%s "
r"-FU%s %s") % (_nim_exe, _output_obj,
os.path.join(os.getcwd(), "nim", "nimrod.pas"))
def buildRod(options):
Exec("nim compile --compile:build/platdef.c %s rod/nimrod" % options)
Move(ExeExt("rod/nimrod"), ExeExt("bin/nimrod"))
def cmd_nim():
CogRule("nversion", "nim/nversion.pas", "koch.py")
CogRule("msgs", "nim/msgs.pas", "data/messages.yml")
CogRule("ast", "nim/ast.pas", "koch.py data/magic.yml data/ast.yml")
CogRule("scanner", "nim/scanner.pas", "data/keywords.txt")
CogRule("paslex", "nim/paslex.pas", "data/pas_keyw.yml")
CogRule("wordrecg", "nim/wordrecg.pas", "data/keywords.txt")
CogRule("commands", "nim/commands.pas",
"data/basicopt.txt data/advopt.txt data/changes.txt")
c = Changed("nim", Glob("nim/*.pas"),
EXPLAIN)
if c or force:
Exec(FPC_CMD)
if Exists(ExeExt("bin/nim")):
c.success()
def cmd_rod(options):
cmd_nim()
prereqs = Glob("lib/*.nim") + Glob("rod/*.nim") + [
"lib/nimbase.h", "lib/dlmalloc.c", "lib/dlmalloc.h",
"config/nimrod.cfg"]
c = Changed("rod", prereqs, EXPLAIN)
if c or force:
buildRod(options)
if Exists(ExeExt("bin/nimrod")):
c.success()
# ------------------- constants -----------------------------------------------
HELP = """\
+-----------------------------------------------------------------+
| Maintenance script for Nimrod |
| Version %s|
| (c) 2008 Andreas Rumpf |
+-----------------------------------------------------------------+
Usage:
koch.py [options] command [options for command]
Options:
--force, -f, -B, -b force rebuild
--help, -h shows this help and quits
Possible Commands:
install [options] installs the Nimrod Compiler: options
are --cc=<compile command>, --ld=<link command>
nim builds the Pascal version of Nimrod
rod [options] builds the Nimrod version of Nimrod (with options)
installer builds the installer (needs Inno Setup 5 on Windows)
configure configures the environment for developing Nimrod
doc builds the documentation in HTML
clean cleans Nimrod project; removes generated files
dist produces a distribution as
nimrod_$target_$version.zip
boot [options] bootstraps with given command line options
tests [options] runs the complete testsuite (with options)
rodsrc generates Nimrod version from Pascal version
web generates the website (requires Cheetah)
""" % (NIMROD_VERSION + ' ' * (44-len(NIMROD_VERSION)))
def main(args):
if len(args) == 0:
print HELP
else:
i = 0
while args[i].startswith("-"):
a = args[i]
if a in ("--force", "-f", "-B", "-b"):
global force
force = True
elif a in ("-h", "--help", "-?"):
print HELP
return
else:
Error("illegal option: " + a)
i += 1
cmd = args[i]
if cmd == "rod": cmd_rod(" ".join(args[i+1:]))
elif cmd == "nim": cmd_nim()
elif cmd == "installer": cmd_installer()
elif cmd == "configure": cmd_configure()
elif cmd == "doc": cmd_doc()
elif cmd == "clean": cmd_clean()
elif cmd == "dist": cmd_dist()
elif cmd == "boot": cmd_boot(" ".join(args[i+1:]))
elif cmd == "tests": cmd_tests(" ".join(args[i+1:]))
elif cmd == "install": cmd_install(args[i+1:])
elif cmd == "rodsrc": cmd_rodsrc()
elif cmd == "web": cmd_web()
else: Error("illegal command: " + cmd)
# -------------------------- bootstrap ----------------------------------------
def cmd_rodsrc():
"converts the src/*.pas files into Nimrod syntax"
PAS_FILES_BLACKLIST = """nsystem nmath nos ntime strutils""".split()
CMD = "nim boot --skip_proj_cfg -o:rod/%s.nim nim/%s"
cmd_nim()
result = False
for fi in Glob("nim/*.pas"):
f = FilenameNoExt(fi)
if f in PAS_FILES_BLACKLIST: continue
c = Changed(f+"__rodsrc", fi, EXPLAIN)
if c or force:
Exec(CMD % (f, f+".pas"))
Exec("nim parse rod/%s.nim" % f)
c.success()
result = True
return result
def cmd_boot(args):
writePlatdefC(getNimrodPath())
d = detect("fpc -h")
if d:
Echo("'%s' detected" % d)
cmd_nim()
compiler = "nim"
else:
Warn("Free Pascal is not installed; skipping Pascal step")
cmd_install(args)
compiler = "nimrod"
cmd_rodsrc() # regenerate nimrod version of the files
# move the new executable to bin directory (is done by cmd_rod())
# use the new executable to compile the files in the bootstrap directory:
Exec("%s compile --compile:build/platdef.c %s rod/nimrod.nim" %
(compiler, args))
# move the new executable to bin directory:
Move(ExeExt("rod/nimrod"), ExeExt("bin/nimrod"))
# compile again and compare:
Exec("nimrod compile --compile:build/platdef.c %s rod/nimrod.nim" % args)
# check if the executables are the same (they should!):
if filecmp.cmp(Path(ExeExt("rod/nimrod")),
Path(ExeExt("bin/nimrod"))):
Echo("files are equal: everything seems fine!")
else:
Warn("files are not equal: cycle once again...")
# move the new executable to bin directory:
Move(ExeExt("rod/nimrod"), ExeExt("bin/nimrod"))
# use the new executable to compile Nimrod:
Exec("nimrod compile %s rod/nimrod.nim" % args)
if filecmp.cmp(Path(ExeExt("rod/nimrod")),
Path(ExeExt("bin/nimrod"))):
Echo("files are equal: everything seems fine!")
else:
Error("files are still not equal")
# ------------------ web ------------------------------------------------------
def buildDoc(destPath):
DOC = "endb intern lib manual nimrodc tutorial overview".split()
SRCDOC = "system os strutils base/regexprs math complex times".split()
# call nim for the documentation:
for d in DOC:
Exec("nim rst2html --putenv:nimrodversion=%s -o:%s/%s.html "
"--index=%s/theindex doc/%s" %
(NIMROD_VERSION, destPath, d, destPath, d))
for d in SRCDOC:
Exec("nim doc --putenv:nimrodversion=%s -o:%s/%s.html "
"--index=%s/theindex lib/%s" %
(NIMROD_VERSION, destPath, FilenameNoExt(d), destPath, d))
Exec("nim rst2html -o:%s/theindex.html %s/theindex" % (destPath, destPath))
def cmd_web():
import Cheetah.Template
TABS = [ # Our tabs: (Menu entry, filename)
("home", "index"),
("documentation", "documentation"),
("download", "download"),
("FAQ", "question"),
("links", "links")
]
TEMPLATE_FILE = "web/sunset.tmpl"
#CMD = "rst2html.py --template=web/docutils.tmpl web/%s.txt web/%s.temp "
CMD = "nim rst2html --compileonly -o:web/%s.temp web/%s.txt"
c = Changed("web", Glob("web/*.txt") + [TEMPLATE_FILE, "koch.py"] +
Glob("doc/*.txt") + Glob("lib/*.txt") + Glob("lib/*.nim")+
Glob("config/*.cfg"),
EXPLAIN)
if c or force:
cmd_nim() # we need Nimrod for processing the documentation
Exec(CMD % ("news","news"))
newsText = file("web/news.temp").read()
for t in TABS:
Exec(CMD % (t[1],t[1]))
tmpl = Cheetah.Template.Template(file=TEMPLATE_FILE)
tmpl.content = file("web/%s.temp" % t[1]).read()
tmpl.news = newsText
tmpl.tab = t[1]
tmpl.tabs = TABS
tmpl.lastupdate = time.strftime("%Y-%m-%d %X", time.gmtime())
f = file("web/%s.html" % t[1], "w+")
f.write(str(tmpl))
f.close()
# remove temporaries:
Remove("web/news.temp")
for t in TABS: Remove("web/%s.temp" % t[1])
buildDoc("web")
if Exists("web/index.html"):
c.success()
# ------------------ doc ------------------------------------------------------
def cmd_doc():
c = Changed("doc", ["koch.py"] +
Glob("doc/*.txt") + Glob("lib/*.txt") + Glob("lib/*.nim")+
Glob("config/*.cfg"),
EXPLAIN)
if c or force:
cmd_nim() # we need Nimrod for processing the documentation
buildDoc("doc")
if Exists("doc/overview.html"):
c.success()
# -----------------------------------------------------------------------------
def getVersion():
return NIMROD_VERSION
# ------------------------------ clean ----------------------------------------
CLEAN_EXT = "ppu o obj dcu ~pas ~inc ~dsk ~dpr map tds err bak pyc exe rod"
def cmd_clean(dir = "."):
extRegEx = re.compile("|".join([r".*\."+ x +"$" for x in CLEAN_EXT.split()]))
Remove("koch.dat")
for f in Glob("web/*.html"): Remove(f)
for f in Glob("doc/html/*.html"): Remove(f)
for f in Glob("doc/*.html"): Remove(f)
for f in Glob("rod/*.nim"): Remove(f) # remove generated source code
for root, dirs, files in os.walk(dir, topdown=False):
for name in files:
if (extRegEx.match(name)
or (root == "tests" and ('.' not in name))):
Remove(os.path.join(root, name))
for name in dirs:
if name == "rod_gen":
shutil.rmtree(path=os.path.join(root, name), ignore_errors=True)
# ----------------- distributions ---------------------------------------------
# Here are listed all files that should be included in the different
# distributions.
distlist = {
'common': (
"copying.txt",
"gpl.html",
"koch.py",
"lib/nimbase.h -> lib/nimbase.h",
"lib/*.nim -> lib",
"rod/*.nim -> rod",
"nim/*.pas -> nim",
"nim/*.txt -> nim",
"data/*.yml -> data",
"data/*.txt -> data",
"config/nimrod.cfg -> config/nimrod.cfg",
# documentation:
"doc/*.txt", # only include the text documentation; saves bandwidth!
# the installation program should generate the HTML
"readme.txt -> readme.txt",
"install.txt -> install.txt",
# library:
"lib/base/pcre_all.c -> lib/base/pcre_all.c",
"lib/base/pcre.nim -> lib/base/pcre.nim",
"lib/base/regexprs.nim -> lib/base/regexprs.nim",
#"lib/windows/winapi.nim -> lib/windows/winapi.nim"
# don't be too clever here; maybe useful on Linux
# for cross-compiling to Windows?
),
'windows': (
"bin/nim.exe -> bin/nim.exe",
"koch.exe -> koch.exe",
"lib/dlmalloc.h -> lib/dlmalloc.h",
"lib/dlmalloc.c -> lib/dlmalloc.c",
),
'linux': (
"lib/rod_gen/*.c -> build",
"rod/rod_gen/*.c -> build",
),
'macosx': (
"lib/rod_gen/*.c -> build",
"rod/rod_gen/*.c -> build",
)
}
def getHost():
if os.name == 'nt': return "windows"
elif "linux" in sys.platform: return "linux"
elif "darwin" in sys.platform: return "macosx" # probably Mac OS X
# a heuristic that could work (most likely not :-):
else: return re.sub(r"[0-9]+$", r"", sys.platform).lower()
def iterInstallFiles(target=getHost()):
for section in ['common', target]:
for rule in distlist[section]:
splittedRule = re.split(r"\s*\-\>\s*", rule)
if len(splittedRule) == 2:
source, dest = splittedRule
if '*' in source:
for f in Glob(source):
yield (Path(f), Path(dest + '/' + os.path.split(f)[1]))
else:
yield (Path(source), Path(dest))
else:
for f in Glob(rule):
yield (Path(f), Path(f))
def cmd_dist(target=getHost()):
from zipfile import ZipFile
distfile = Path('dist/nimrod_%s_%s.zip' % (target, getVersion()))
Echo("creating: %s..." % distfile)
z = ZipFile(distfile, 'w', zipfile.ZIP_DEFLATED)
for source, dest in iterInstallFiles(target):
z.write(source, Path(dest))
z.close()
Echo("... done!")
# ------------------------------ windows installer ----------------------------
WIN_INSTALLER_TEMPLATE = (r"""
; File generated by koch.py
; Template by Andreas Rumpf
[Setup]
AppName=Nimrod Compiler
AppVerName=Nimrod Compiler $version
DefaultDirName={code:GiveMeAPath|nimrod}
DefaultGroupName=Nimrod
AllowNoIcons=yes
LicenseFile=nim\copying.txt
OutputDir=dist
OutputBaseFilename=install_nimrod_$version
Compression=lzma
SolidCompression=yes
PrivilegesRequired=none
[Languages]
Name: english; MessagesFile: compiler:Default.isl
[Files]
$files
[Icons]
Name: {group}\Console for Nimrod; Filename: {cmd}
Name: {group}\Documentation; Filename: {app}\doc\index.html
Name: {group}\{cm:UninstallProgram,Nimrod Compiler}; Filename: {uninstallexe}
[UninstallDelete]
Type: files; Name: "{app}\config\nimrod.cfg"
[Run]
Filename: "{app}\bin\nimconf.exe"; Description: "Launch configuration"; """ +
"""Flags: postinstall nowait skipifsilent
[Code]
function GiveMeAPath(const DefaultPathName: string): string;
begin
if IsAdminLoggedOn then Result := ExpandConstant('{pf}')
else Result := ExpandConstant('{userdocs}');
Result := Result + '\' + DefaultPathName;
end;
function setEnvCmd(const default: string): string;
var
op, app: string;
begin
app := ExpandConstant('{app}');
if IsAdminLoggedOn then op := '' else op := 'u';
result := '"' + app + '\bin\setenv.exe" -' + op + 'a PATH "%' + app + '\bin"'
end;
""")
def makeKochExe():
c = Changed("kochexe",
("docmacro.py kochmod.py koch.py " +
"misc/koch.ico").split(), EXPLAIN)
if c or force:
Exec("python " + Join(PYINSTALLER, "Makespec.py") +
" --onefile --ascii --icon=misc/koch.ico koch.py")
Exec("python " + Join(PYINSTALLER, "Build.py") + " koch.spec")
Remove("koch.spec")
Remove("warnkoch.txt")
RemoveDir("buildkoch")
c.success()
def cmd_wininstaller():
FILENAME = "install_nimrod.iss"
makeKochExe()
# generate an installer file
files = ""
for source, dest in iterInstallFiles("windows"):
files += ("Source: " + source + "; DestDir: {app}\\" +
os.path.split(dest)[0] + "; Flags: ignoreversion\n")
f = file(FILENAME, "w+")
f.write(Subs(WIN_INSTALLER_TEMPLATE, files=files, version=getVersion()))
f.close()
if RawExec(INNOSETUP + FILENAME) == 0:
# we cannot use ``Exec()`` here as this would
# mangle the ``/Q`` switch to ``\Q``
Remove(FILENAME)
# -------------------------- testing the compiler -----------------------------
# This part verifies Nimrod against the testcases.
# The testcases may contain the directives '#ERROR' or '#ERROR_IN'.
# '#ERROR' is used to indicate that the compiler should report
# an error in the marked line (the line that contains the '#ERROR'
# directive.)
# The format for '#ERROR_IN' is:
# #ERROR_IN filename linenumber
# One can omit the extension of the filename ('.nim' is then assumed).
# Tests which contain none of the two directives should compile. Thus they
# are executed after successful compilation and their output is verified
# against the results specified with the '#OUT' directive.
# (Tests which require user interaction are currently not possible.)
# Tests can have an #ERROR_MSG directive specifiying the error message
# Nimrod shall produce.
# The code here needs reworking or at least documentation, but I don't have
# the time and it has been debugged and optimized.
try:
import subprocess
HAS_SUBPROCESS = True
except ImportError:
HAS_SUBPROCESS = False
def runProg(args, inp=None):
"""Executes the program + args given in args and
returns the output of the program as a string."""
if HAS_SUBPROCESS:
process = subprocess.Popen(args, bufsize=0, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=inp,
universal_newlines=True)
standardOut, standardErr = process.communicate(inp)
process.wait() # be on the safe side
return standardOut
else:
if inp:
standardIn = file('buildin.tmp', 'w')
standardIn.write(inp)
standardIn.close()
b = " <buildin.tmp"
else:
b = ""
os.system(args + b + " >build.tmp")
result = file('build.tmp').read()
if not result: result = ""
return result
# system() is not optimal, but every Python version should have it
class Spec(object): pass # specification object
def parseTest(filename):
# spec is a table
reError = re.compile(r"#ERROR$")
reErrorIn = re.compile(r"#ERROR_IN\s*(\S*)\s*(\d*)")
reErrorMsg = re.compile(r"#ERROR_MSG\s*(.*)")
reOut = re.compile(r"#OUT\s*(.*)")
i = 0 # the line counter
spec = Spec()
spec.line = None # line number where compiler should throw an error
spec.file = None # file where compiler should throw an error
spec.err = False # true if the specification says there should be an error
spec.out = None # output that should be produced
for s in file(filename, 'rU'):
# we have to use this inefficient method for getting the current line
i += 1 # our line-counter
obj = reError.search(s)
if obj:
spec.line = i
spec.file = filename
spec.err = True
break
obj = reErrorIn.search(s)
if obj:
spec.file = obj.group(1)
spec.line = int(obj.group(2))
spec.err = True
if '.' not in specfile: specfile += ".nim"
break
obj = reOut.search(s)
if obj:
spec.out = obj.group(1)
break
obj = reErrorMsg.search(s)
if obj:
spec.out = obj.group(1)
spec.err = True
break
return spec
def doTest(filename, spec, options):
# call the compiler
# short filename for messages (better readability):
shortfile = os.path.split(filename)[1]
comp = Spec()
comp.line = 0
comp.file = None
comp.out = None
comp.err = False
# call the compiler and read the compiler message:
results = runProg("nim compile --hints:on " + options + " " + filename)
print results
# compiled regular expressions:
reLineInfoError = re.compile(r"^((.*)\((\d+), \d+\)\s*Error\:\s*(.*))",
re.MULTILINE)
reError = re.compile(r"^Error\:\s*(.*)", re.MULTILINE)
reSuccess = re.compile(r"^Hint\:\s*operation successful", re.MULTILINE)
obj = reLineInfoError.search(results)
if obj:
comp.err = True
comp.file = obj.group(2)
comp.line = int(obj.group(3))
comp.out = obj.group(1)
comp.puremsg = obj.group(4)
else:
comp.puremsg = ''
obj = reError.search(results)
if obj:
comp.err = True
comp.out = results
comp.puremsg = obj.group(1)
comp.line = 1
else:
obj = reSuccess.search(results)
if not obj: comp.err = True
if comp.err and not comp.out:
# the compiler did not say "[Error]" nor "Compilation sucessful"
Echo("[Tester] %s -- FAILED; COMPILER BROKEN" % shortfile)
return False
if (spec.err != comp.err
or (spec.line and (abs(spec.line - comp.line) > 1))
or (spec.file and (spec.file.lower() != comp.file.lower()))
or (spec.out and not (spec.out.strip() in comp.puremsg.strip()))):
if spec.out:
Echo("[Tester] %s -- FAILED\n"
"Compiler says: %s\n"
"But specification says: Error %s"
% (shortfile, comp.out, spec.out) )
elif spec.err:
if spec.file is None: spec.file = filename
if spec.line is None: spec.line = -1
Echo("[Tester] %s -- FAILED\n"
"Compiler says: %s\n"
"But specification says: Error in %s line %d"
% (shortfile, comp.out, spec.file, spec.line) )
else:
Echo("[Tester] %s -- FAILED\n"
"Compiler says: %s\n"
"But specification says: no error"
% (shortfile, comp.out) )
return False
else:
if spec.err:
Echo("[Tester] " + shortfile + ' -- OK') # error correctly reported
return True
else:
# run the compiled program and check if it works
fileNoExt = os.path.splitext(filename)[0]
if os.path.isfile(ExeExt(fileNoExt)):
if spec.out:
buf = runProg(fileNoExt)
if buf.strip() == spec.out.strip():
Echo("[Tester] " + shortfile + " -- compiled program OK")
return True
else:
Echo("[Tester] " + shortfile + " -- compiled program FAILED")
return False
else:
Echo("[Tester] " + shortfile + ' -- OK')
return True
# we have no output to validate against, but compilation succeeded,
# so it's okay
elif '--compile_only' in options:
Echo("[Tester] " + shortfile + ' -- OK')
return True
else:
Echo("[Tester] " + shortfile + " -- FAILED\n"
"no compiled program found")
return False
def cmd_tests(options): # run the testsuite
"""runs the complete testsuite"""
#clean(True) # first clean before running the testsuite
total = 0
passed = 0
for filename in Glob("tests/t*.nim"):
spec = parseTest(filename)
res = doTest(filename, spec, options)
assert(res is not None)
if res: passed += 1
total += 1
break
Echo("[Tester] %d/%d tests passed\n" % (passed, total))
# --------------- install target ----------------------------------------------
CONFIG_TEMPLATE = r"""# Configuration file for the Nimrod Compiler.
# Generated by the koch.py script.
# (c) 2008 Andreas Rumpf
# Feel free to edit the default values as you need.
# You may set environment variables with
# @putenv "key" "val"
# Environment variables cannot be used in the options, however!
# Just call the compiler with several options:
cc = @if unix: %(cc)s @else: vcc @end
lib="$nimrod/lib"
path="$lib/base"
path="$lib/base/gtk"
path="$lib/base/cairo"
path="$lib/base/x11"
path="$lib/windows"
path="$lib/extra"
# additional defines:
#define=""
# additional options always passed to the compiler:
force_build
line_dir=off
hint[LineTooLong]=off
hint[XDeclaredButNotUsed]=off
@if unix:
passl= "-ldl"
path = "$lib/base/gtk"
@end
@if icc:
passl = "-cxxlib"
passc = "-cxxlib"
@end
# Configuration for the Borland C++ Compiler:
@if windows:
bcc.path = r"C:\eigenes\compiler\cbuilder5\bin"
@end
bcc.options.debug = ""
# turn off warnings about unreachable code and inline procs:
bcc.options.always = "-w- -H- -q -RT- -a8 -w-8027 -w-8066"
bcc.options.speed = "-O2 -6"
bcc.options.size = "-O1 -6"
# Configuration for the Visual C/C++ compiler:
@if vcc:
@prepend_env path r"C:\Eigenes\compiler\vcc2005\Common7\IDE;"
@prepend_env INCLUDE r"C:\Eigenes\compiler\vcc2005\VC\include;C:\Eigenes\compiler\vcc2005\VC\ATLMFC\INCLUDE;"
@prepend_env LIB r"C:\Eigenes\compiler\vcc2005\VC\lib;C:\Eigenes\compiler\vcc2005\SDK\v2.0\Lib;"
@end
@if windows:
vcc.path = r"C:\Eigenes\compiler\vcc2005\VC\bin"
@end
vcc.options.debug = "/GZ /ZI"
vcc.options.always = "/nologo"
vcc.options.speed = "/Ogityb2 /G7 /arch:SSE2"
vcc.options.size = "/O1 /G7"
# Configuration for the Watcom C/C++ compiler:
@if windows:
wcc.path = r"C:\eigenes\compiler\watcom\binnt"
@end
wcc.options.debug = "-d2"
wcc.options.always = "-6 -zw -w-"
wcc.options.speed = "-ox -on -6 -d0 -fp6 -zW"
wcc.options.size = "-ox -on -6 -d0 -fp6 -zW"
# Configuration for the GNU C/C++ compiler:
@if windows:
gcc.path = r"C:\eigenes\compiler\mingw\bin"
@end
gcc.options.debug = "-g"
@if macosx:
gcc.options.always = "-w -fasm-blocks"
@else:
gcc.options.always = "-w"
@end
gcc.options.speed = "-O3 -ffast-math"
gcc.options.size = "-Os -ffast-math"
# Configuration for the Digital Mars C/C++ compiler:
@if windows:
dmc.path = r"C:\eigenes\compiler\d\dm\bin"
@end
dmc.options.debug = "-g"
dmc.options.always = "-Jm"
dmc.options.speed = "-ff -o -6"
dmc.options.size = "-ff -o -6"
# Configuration for the LCC compiler:
@if windows:
lcc.path = r"C:\eigenes\compiler\lcc\bin"
@end
lcc.options.debug = "-g5"
lcc.options.always = "-e1"
lcc.options.speed = "-O -p6"
lcc.options.size = "-O -p6"
# Configuration for the Tiny C Compiler:
@if windows:
tcc.path = r"C:\eigenes\compiler\tcc\bin"
@end
tcc.options.debug = "-b"
tcc.options.always = ""
tcc.options.speed = ""
tcc.options.size = ""
# Configuration for the Pelles C compiler:
@if windows:
pcc.path = r"C:\eigenes\compiler\pellesc\bin"
@end
pcc.options.debug = "-Zi"
pcc.options.always = "-Ze"
pcc.options.speed = "-Ox"
pcc.options.size = "-Os"
# Configuration for the LLVM GCC compiler:
@if windows:
llvm_gcc.path = r"c:\eignes\compiler\llvm-gcc\bin"
@end
llvm_gcc.options.debug = "-g"
llvm_gcc.options.always = "-w"
llvm_gcc.options.speed = "-O3 -ffast-math"
llvm_gcc.options.size = "-Os -ffast-math"
@if windows:
icc.path = r"c:\eignes\compiler\icc\bin"
@end
icc.options.debug = "-g"
icc.options.always = "-w"
icc.options.speed = "-O3 -ffast-math"
icc.options.size = "-Os -ffast-math"
@write "used default config file"
"""
def writePlatdefC(nimrodpath):
import os
host = getHost()
if host == "windows": processor = "i386" # BUGFIX
else: processor = os.uname()[4]
if processor.lower() in ("i686", "i586", "i468", "i386"):
processor = "i386"
if "sparc" in processor.lower():
processor = "sparc"
f = file(os.path.join(nimrodpath, "build/platdef.c"), "w+")
f.write('/* Generated by koch.py */\n'
'#include "nimbase.h"\n'
'N_NIMCALL(char*, nimOS)(void) { return "%s"; }\n'
'N_NIMCALL(char*, nimCPU)(void) { return "%s"; }\n'
'\n' % (host, processor))
f.close()
def detect(cmd, lookFor="version"):
pipe = os.popen4(cmd)[1]
result = None
for line in pipe:
if lookFor in line:
result = line[:-1]
break
pipe.close()
return result
def lookForCC():
if "CC" in os.environ:
Echo("using $CC environment variable (%s)" % os.environ["CC"])
return os.environ["CC"]
d = detect("gcc -v")
if d:
Echo("'%s' detected" % d)
return "gcc"
Echo("GCC not found. Testing for generic CC...")
d = detect("cc -v")
if d:
Echo("'%s' detected" % d)
return "ucc"
Echo("...not found!")
Error("No C compiler could be found!")
return ""
def getNimrodPath():
if os.name == "posix":
# Does not work 100% reliably. It is the best solution though.
p = sys.argv[0].replace("./", "")
return os.path.split(os.path.join(os.getcwd(), p))[0]
else: # Windows
return os.path.split(sys.argv[0])[0]
def writeCfg(nimrodpath, ccSymbol=None):
if not ccSymbol:
ccSymbol = lookForCC()
configFile = os.path.join(nimrodpath, "config/nimrod.cfg")
script = CONFIG_TEMPLATE % {'cc': ccSymbol, 'nimrodpath': nimrodpath}
config = file(configFile)
if config:
if config.read().strip() != script.strip():
config.close()
Echo("Configuration file already exists and "
"seems to have been modified.\n"
"Do you want to override it? (y/n) ")
while True:
a = ask()
if a in ("y", "yes"):
f = file(configFile, "w+")
f.write(script)
f.close()
break
elif a in ("n", "no"):
break
else:
Echo("What do you mean? (y/n) ")
else:
config.close()
return ccSymbol
def cmd_install(args):
Echo("Nimrod should be in '%s'" % getNimrodPath())
# We know that the user has already unzipped this archive into the
# final directory. So we just create the config file and build Nimrod.
# write the configuration file, but check if one exists!
nimrodpath = getNimrodPath()
try:
opts, args = getopt.getopt(args, "", ["cc=", "ld="])
except getopt.GetoptError:
# print help information and exit:
Error("Command line contains errors")
ccSymbol = None
ldSymbol = None
for o, a in opts:
if o == "--cc": ccSymbol = a
elif o == "--ld": ldSymbol = a
ccSymbol = writeCfg(nimrodpath, ccSymbol)
if not ldSymbol:
ldSymbol = ccSymbol.split()[0] + " -ldl -o bin/nimrod "
writePlatdefC(nimrodpath)
# build Nimrod
link = "" # store the .o files in here for final linking step
for f in Glob("build/*.c"):
objfile = os.path.splitext(f)[0] + ".o"
link += " " + objfile
# compile only:
if Exec(ccSymbol + " " + CFLAGS + " -c -o " + objfile + " " + f) != 0:
Error("the C compiler did not like: " + f)
if link == "":
Error("could not find Nimrod's sources\n"
" (they should be in the build subdirectory)")
# now link the stuff together:
if Exec(ldSymbol + link) != 0:
Error("the linking step failed!")
# now we have a Nimrod executable :-)
nimrodpath = getNimrodPath()
writeScript(CONFIG_TEMPLATE % {'cc': ccSymbol, 'nimrodpath': nimrodpath},
os.path.join(nimrodpath, "config/nimrod.cfg"))
# remove the generated .o files as they take 1 MB:
for f in Glob("build/*.o"): Remove(f)
Echo("SUCCESS!")
def cmd_installer():
if os.name == "posix":
Echo("Nothing to do")
else: # Windows
cmd_wininstaller()
# ------------------ configure ------------------------------------------------
def writeScript(script, filename):
if os.name != "posix": filename += ".bat"
f = file(filename, "w+")
f.write(script)
f.close()
# make the script executable:
if os.name == "posix":
os.chmod(filename, 493) # 0o755
def cmd_configure():
d = detect("fpc -h")
if d:
Echo("'%s' detected" % d)
else:
Warn("Free Pascal is not installed, bootstrapping may not work properly.")
writeCfg(getNimrodPath())
Echo("Configuration sucessful!")
# ------------------- main ----------------------------------------------------
if __name__ == "__main__":
main(sys.argv[1:])

640
kochmod.py Executable file
View File

@@ -0,0 +1,640 @@
# This is kochmod, a simple module for make-like functionality.
# For further documentation see koch.txt or koch.html.
# (c) 2007 Andreas Rumpf
VERSION = "1.0.3"
import os, os.path, inspect, re, shutil, glob, cPickle, zlib, string, \
getopt, sys
from types import *
def Error(msg): sys.exit("[Koch] *** ERROR: " + msg)
def Warn(msg): print "[Koch] *** WARNING: " + msg
def Echo(msg): print "[Koch] " + msg
def _Info(msg): print "[Koch] " + msg
_FINGERPRINTS_FILE = "koch.dat"
# in this file all the fingerprints are kept to allow recognizing when a file
# has changed. This works reliably, which cannot be said from just taking
# filetime-stamps.
# ---------------- C Compilers ------------------------------------------------
# We support the following C compilers:
C_Compilers = ["gcc", "lcc", "bcc", "dmc", "wcc", "tcc", "pcc", "ucc", "llvm"]
_CC_Info = [
dict(
name = "gcc",
objExt = "o",
optSpeed = " -O3 -ffast-math ",
optSize = " -Os -ffast-math ",
comp = "gcc -c $options $include -o $objfile $file",
buildGui = " -mwindows",
buildDll = " -mdll",
link = "gcc $options $buildgui $builddll -o $exefile $objfiles",
includeCmd = " -I",
debug = "",
defineValue = " -D$name=$value",
define = " -D$name",
undef = " -U$name",
pic = "-fPIC"
), dict(
name = "lcc",
objExt = "obj",
optSpeed = " -O -p6 ",
optSize = " -O -p6 ",
comp = "lcc -e1 $options $include -Fo$objfile $file",
buildGui = " -subsystem windows",
buildDll = " -dll",
link = "lcclnk $options $buildgui $builddll -O $exefile $objfiles",
includeCmd = " -I",
debug = " -g5 ",
defineValue = " -D$name=$value",
define = " -D$name",
undef = " -U$name",
pic = ""
), dict(
name = "bcc",
objExt = "obj",
optSpeed = " -O2 -6 ",
optSize = " -O1 -6 ",
comp = "bcc32 -c -H- -q -RT- -a8 $options $include -o$objfile $file",
buildGui = " -tW",
buildDll = " -tWD",
link = "bcc32 $options $buildgui $builddll -e$exefile $objfiles",
includeCmd = " -I",
debug = "",
defineValue = " -D$name=$value",
define = " -D$name",
undef = " -U$name",
pic = ""
), dict(
name = "dmc",
objExt = "obj",
optSpeed = " -ff -o -6 ",
optSize = " -ff -o -6 ",
comp = "dmc -c -Jm $options $include -o$objfile $file",
buildGui = " -L/exet:nt/su:windows",
buildDll = " -WD",
link = "dmc $options $buildgui $builddll -o$exefile $objfiles",
includeCmd = " -I",
debug = " -g ",
defineValue = " -D$name=$value",
define = " -D$name",
undef = " -U$name", # XXX: dmc does not have -U ?
pic = ""
), dict(
name = "wcc",
objExt = "obj",
optSpeed = " -ox -on -6 -d0 -fp6 -zW ",
optSize = "",
comp = "wcl386 -c -6 -zw $options $include -fo=$objfile $file",
buildGui = " -bw",
buildDll = " -bd",
link = "wcl386 $options $buildgui $builddll -fe=$exefile $objfiles ",
includeCmd = " -i=",
debug = " -d2 ",
defineValue = " -d$name=$value",
define = " -d$name",
undef = " -u$name",
pic = ""
), dict(
name = "vcc",
objExt = "obj",
optSpeed = " /Ogityb2 /G7 /arch:SSE2 ",
optSize = " /O1 /G7 ",
comp = "cl /c $options $include /Fo$objfile $file",
buildGui = " /link /SUBSYSTEM:WINDOWS ",
buildDll = " /LD",
link = "cl $options $builddll /Fe$exefile $objfiles $buildgui",
includeCmd = " /I",
debug = " /GZ /Zi ",
defineValue = " /D$name=$value",
define = " /D$name",
undef = " /U$name",
pic = ""
), dict(
name = "tcc",
objExt = "o",
optSpeed = "", # Tiny C has no optimizer
optSize = "",
comp = "tcc -c $options $include -o $objfile $file",
buildGui = "UNAVAILABLE!",
buildDll = " -shared",
link = "tcc -o $exefile $options $buildgui $builddll $objfiles",
includeCmd = " -I",
debug = " -b ",
defineValue = " -D$name=$value",
define = " -D$name",
undef = " -U$name",
pic = ""
), dict(
name = "pcc", # Pelles C
objExt = "obj",
optSpeed = " -Ox ",
optSize = " -Os ",
comp = "cc -c $options $include -Fo$objfile $file",
buildGui = " -SUBSYSTEM:WINDOWS",
buildDll = " -DLL",
link = "cc $options $buildgui $builddll -OUT:$exefile $objfiles",
includeCmd = " -I",
debug = " -Zi ",
defineValue = " -D$name=$value",
define = " -D$name",
undef = " -U$name",
pic = ""
), dict(
name = "ucc",
objExt = "o",
optSpeed = " -O3 ",
optSize = " -O1 ",
comp = "cc -c $options $include -o $objfile $file",
buildGui = "",
buildDll = " -shared ",
link = "cc -o $exefile $options $buildgui $builddll $objfiles",
includeCmd = " -I",
debug = "",
defineValue = " -D$name=$value",
define = " -D$name",
undef = " -U$name",
pic = ""
), dict(
name = "llvm_gcc", # its options are the same as GCC's
objExt = "o",
optSpeed = " -O3 -ffast-math ",
optSize = " -Os -ffast-math ",
comp = "llvm-gcc -c $options $include -o $objfile $file",
buildGui = " -mwindows",
buildDll = " -mdll",
link = "llvm-gcc $options $buildgui $builddll -o $exefile $objfiles",
includeCmd = " -I",
debug = "",
defineValue = " -D$name=$value",
define = " -D$name",
undef = " -U$name",
pic = "-fPIC"
)
]
# --------------- little helpers ---------------------------------------------
def Subs(frmt, **substitution):
if isinstance(frmt, basestring):
return string.Template(frmt).substitute(substitution)
else:
return tuple([string.Template(x).substitute(substitution) for x in frmt])
_baseDir = os.getcwd()
BaseDir = _baseDir
def Path(a):
# Gets a UNIX like path and converts it to a path on this platform.
# With UNIX like, I mean: slashes, not backslashes, only relative
# paths ('../etc' can be used)
result = a
if os.sep != "/": result = result.replace("/", os.sep)
if os.pardir != "..": result = result.replace("..", os.pardir)
return result
def Join(*args):
result = ""
for a in args[:-1]:
result += a
if result[-1] != "/":
result += "/"
result += args[-1]
return result.replace("//", "/")
def Exec(command):
c = Path(command)
Echo(c)
result = os.system(c)
if result != 0: Error("execution of an external program failed")
return result
def TryExec(command):
c = Path(command)
Echo(c)
result = os.system(c)
return result
def RawExec(command):
Echo(command)
result = os.system(command)
if result != 0: Error("execution of an external program failed")
return result
def Move(src, dest):
s = Path(src)
d = Path(dest)
try:
shutil.move(s, d)
except IOError, OSError:
Warn("could not move %s to %s" % (s, d))
def Copy(src, dest):
s = Path(src)
d = Path(dest)
try:
shutil.copyfile(s, d)
except IOError, OSError:
Warn("could not copy %s to %s" % (s, d))
def Remove(f):
try:
os.remove(Path(f))
except OSError:
Warn("could not remove: %s" % f)
def RemoveDir(f):
try:
shutil.rmtree(Path(f))
except OSError:
Warn("could not remove: %s" % f)
def Exists(f): return os.path.exists(Path(f))
def Chdir(dest):
d = Path(dest)
try:
os.chdir(d)
except OSError:
Warn("could not switch to directory: " + d)
def Mkdir(dest):
d = Path(dest)
try:
os.mkdir(d)
except OSError:
Warn("could not create directory: " + d)
def Glob(pattern): # needed because glob.glob() is buggy on Windows 95:
# things like tests/t*.mor won't work
global _baseDir
(head, tail) = os.path.split(Path(pattern))
try:
os.chdir(os.path.join(_baseDir, head))
result = []
for f in glob.glob(tail):
result.append(os.path.join(head, f))
except OSError:
result = []
finally:
os.chdir(_baseDir)
return result
def FilenameNoExt(f):
return os.path.splitext(os.path.basename(f))[0]
def _Ext(trunc, posixFormat, winFormat):
(head, tail) = os.path.split(Path(trunc))
if os.name == "posix": frmt = posixFormat
else: frmt = winFormat
return os.path.join(head, Subs(frmt, trunc=tail))
def DynExt(trunc):
"""Makes a dynamic library out of a trunc. This means it either
does '${trunc}.dll' or 'lib${trunc}.so'.
"""
return _Ext(trunc, 'lib${trunc}.so', '${trunc}.dll')
def LibExt(trunc):
"""Makes a static library out of a trunc. This means it either
does '${trunc}.lib' or '${trunc}.a'.
"""
return _Ext(trunc, '${trunc}.a', '${trunc}.lib')
def ScriptExt(trunc):
"""Makes a script out of a trunc. This means it either
does '${trunc}.bat' or '${trunc}.sh'.
"""
return _Ext(trunc, '${trunc}.sh', '${trunc}.bat')
def ExeExt(trunc):
"""Makes an executable out of a trunc. This means it either
does '${trunc}.exe' or '${trunc}'.
"""
return _Ext(trunc, '${trunc}', '${trunc}.exe')
def MakeExecutable(file):
os.chmod(file, 493)
# ----------------- Dependency Analyser Core ---------------------------------
# We simply store the rules in a list until building the things. Checking is
# also delayed.
_rules = {}
_importantTargets = [] # used for command line switches
_commands = {} # other commands
# a command is a tuple: (name, description, function, number of arguments)
def Command(name, desc, func, args=0):
"""if args == -1, a variable number of arguments is given to the ``func``
as a list"""
_commands[name] = (desc, func, args)
def _applyPath(x):
if type(x) == ListType:
return map(Path, x)
else:
return Path(x)
def Rule(name = None, desc = "", prereqs = [], cmds = None, outputfile = None,
modifies = []):
"""Defines a rule. Name must be a single word, not a file!"""
if not name:
t = "#" + str(len(_rules.keys()))
else:
t = name
if t in _rules: Error("target '%s' already exists!" % t)
_rules[t] = (_applyPath(prereqs), cmds, outputfile, _applyPath(modifies))
if desc:
_importantTargets.append((t, desc))
class Changed(object):
""" Returns a Changed object. This object evals to true if one of the
given files has changed, false otherwise in a boolean context. You have
to call the object's success() method if the building has been a success.
Example:
c = Changed("unique_name", "file1.pas file2.pas file3.pas")
if c:
Exec("fpc file1.pas")
# Exec raises an exception if it fails, thus if we get to here, it was
# a success:
c.success()
"""
def __init__(self, id, files, explain=False,
fingerprintsfile=_FINGERPRINTS_FILE):
# load the fingerprints file:
# fingerprints is a dict[target, files] where files is a dict[filename, hash]
self.fingers = {} # default value
if Exists(fingerprintsfile):
try:
self.fingers = cPickle.load(file(fingerprintsfile))
except OSError:
Error("Cannot read from " + fingerprintsfile)
self.filename = fingerprintsfile
self.id = id
self.files = files
self._hashStr = zlib.adler32 # our hash function
self.explain = explain
def _hashFile(self, f):
x = file(f)
result = self._hashStr(x.read())
x.close() # for other Python implementations
return result
def __nonzero__(self):
if type(self.files) == type(""):
self.files = self.files.split()
result = False
target = self.id
if not (target in self.fingers):
self.fingers[target] = {}
if self.explain: _Info("no entries for target '%s'" % target)
result = True
for d in self.files:
if Exists(d):
n = self._hashFile(d)
if d not in self.fingers[target] or n != self.fingers[target][d]:
result = True
if self.explain: _Info("'%s' modified since last build" % d)
self.fingers[target][d] = n
else:
Warn("'%s' does not exist!" % d)
result = True
return result
def update(self, filename):
self.fingers[self.id][filename] = self._hashFile(filename)
def success(self):
cPickle.dump(self.fingers, file(self.filename, "w+"))
class _Koch(object):
def _loadFingerprints(self, filename):
# fingerprints is a dict[target, files] where files is a dict[filename, hash]
if Exists(filename):
try:
self.fingers = cPickle.load(file(filename))
except OSError:
Error("Cannot read from " + filename)
else:
self.fingers = {} # we have no fingerprints :-(
def _saveFingerprints(self, filename):
cPickle.dump(self.fingers, file(filename, "w+"))
def __init__(self, options):
self._loadFingerprints(_FINGERPRINTS_FILE)
self.newfingers = {}
self.rules = _rules
self._hashStr = zlib.adler32 # our hash function
self.options = options
def _doRebuild(self, cmd):
if cmd is None: return 0
if type(cmd) is StringType:
if cmd:
c = Path(cmd)
_Info(c)
return os.system(c)
else:
return 0
elif type(cmd) is FunctionType:
return cmd()
elif type(cmd) is ListType:
for c in cmd:
res = self._doRebuild(c)
if res != 0: break
return res
else:
Error("invalid rule: command must be a string or a function")
def _hashFile(self, f):
x = file(f)
result = self._hashStr(x.read())
x.close() # for other Python implementations
return result
def _getDeps(self, target):
depslist = self.rules[target][0]
if type(depslist) is StringType:
result = depslist.split()
elif type(depslist) is FunctionType:
result = depslist()
elif type(depslist) is ListType:
result = []
for d in depslist:
if type(d) is StringType:
result.append(d)
elif type(d) is FunctionType:
result.append(d())
else:
Error("invalid rule: prereqs must be a string, list, or a function")
for i in range(0, len(result)):
result[i] = Path(result[i])
return result
def _hasChanged(self, target, d):
if not (target in self.newfingers):
self.newfingers[target] = {}
if Exists(d):
n = self._hashFile(d)
self.newfingers[target][d] = n
if not (target in self.fingers): return True
if not (d in self.fingers[target]): return True
return n != self.fingers[target][d]
else:
Warn("'%s' does not exist!" % d)
return True
def _makeAux(self, target, callstack={}):
# returns "uptodate", "updated", "failed"
UPTODATE = 1
UPDATED = 2
FAILED = 3
if target in callstack: return callstack[target]
def explain(msg):
if 'explain' in self.options: _Info(msg)
if not (target in self.rules): return UPTODATE # target is up to date
callstack[target] = UPTODATE # assume uptodate until proven otherwise
result = UPTODATE
# retrieve the dependencies:
deps = self._getDeps(target)
for d in deps:
if d[0] == '#':
t = d[1:]
if not (t in self.rules):
Error("reference to unknown target '%s'" % t)
# it is a target!
#callstack[t] = # XXX: prevend endless recursion!
res = self._makeAux(t, callstack)
result = max(result, res)
if res == UPDATED:
explain("will build '%s' because '%s' modified since last build" %
(target, d))
elif res == FAILED:
explain("cannot build '%s' because '%s' failed" %
(target, d))
elif self._hasChanged(target, d):
explain("will build '%s' because '%s' modified since last build" %
(target, d))
result = max(result, UPDATED)
if self.rules[target][2]: # check if output file exists:
if not Exists(self.rules[target][2]):
explain("will build '%s' because output file '%s' does not exist" %
(target, self.rules[target][2]))
result = max(result, UPDATED)
if result == UPTODATE and 'force' in self.options:
explain("will build '%s' because forced" % target)
result = max(result, UPDATED)
if result == UPDATED:
_Info("building target '%s'" % target)
buildRes = self._doRebuild(self.rules[target][1])
if buildRes is None:
Error("builder for target '%s' did not return an int" % target)
result = FAILED
elif buildRes != 0:
result = FAILED
elif result == UPTODATE:
_Info("'%s' is up to date" % target)
callstack[target] = result
if result == UPDATED: # building was successful, so update fingerprints:
if not (target in self.newfingers):
# for phony targets this check is needed
self.newfingers[target] = {}
for m in self.rules[target][3]: # look for changed files
self._hasChanged(target, m) # call for its side-effects
self.fingers[target] = self.newfingers[target]
return result
def make(self, target):
self._makeAux(target)
self._saveFingerprints(_FINGERPRINTS_FILE)
# -----------------------------------------------------------------------------
def SplitArg(s):
if ':' in s: c = ':'
elif '=' in s: c = '='
else: return (s, '')
i = s.find(c)
return (s[:i], s[i+1:])
# -----------------------------------------------------------------------------
def _writeUsage():
print("Usage: koch.py [options] command/target [command/target...]\n"
"Options:\n"
" --force, -b, -f forces rebuilding\n"
" --help, -h shows this help\n"
" --explain, -e explain why a target is built\n"
"Available targets:")
for t in _importantTargets:
print(" " + t[0] + " " * (23-len(t[0])) + t[1])
if len(_commands) > 0:
print("Available commands:")
for k, v in _commands.iteritems():
print(" " + k + " " * (23-len(k)) + v[0])
sys.exit(2)
def Koch(defaultTarget):
argv = sys.argv[1:]
options = {}
i = 0
# process general options:
while i < len(argv):
if argv[i][0] == '-':
if argv[i] in ("-h", "--help"): _writeUsage()
elif argv[i] in ("-b", "-B", "--force", "-f"): options['force'] = True
elif argv[i] in ("--explain", "-e"): options['explain'] = True
else: Error("invalid option: '%s'" % argv[i])
else: break # BUGFIX
i += 1
k = _Koch(options)
# process commands:
i = 0
while i < len(argv):
if argv[i][0] != '-': # process target/command
if argv[i] in _rules:
k.make(argv[i])
elif argv[i] in _commands:
cmd = argv[i]
n = _commands[cmd][2]
args = []
if n < 0: upperBound = len(argv)-1
else: upperBound = i+n
while i+1 <= upperBound:
if i+1 >= len(argv):
Error("command '%s' expects %d arguments" % (cmd, n))
args.append(argv[i+1])
i += 1
if n < 0: _commands[cmd][1](args)
else: _commands[cmd][1](*args)
else:
Error("Invalid target/command: " + argv[i])
i += 1
if len(argv) == 0:
k.make(defaultTarget)
if __name__ == "__main__":
Error("You should execute the file 'koch.py' or consult\n"
"the documentation to see how to build this software.")

39
lib/amd64.asm.in Executable file
View File

@@ -0,0 +1,39 @@
; This contains the CPU-dependant variants of some routines.
; (C) 2005 Andreas Rumpf
; This code was inspired by the Freepascal compiler's sources
; All routines here have the _cdecl calling convention because
; that is the only convention any C compiler supports.
\python{
# as usual I use my own preprocessor :-)
import os
def c(name):
if os.name == 'posix':
return name
else:
return "_" + name
def arg:
if os.name == 'posix':
return 'rdi'
else:
return 'rcx' # on win64 uses its own calling convention; this sucks!
}
segment code
global \c{cpu_inc_locked}
global \c{cpu_dec_locked}
\c{cpu_dec_locked}:
lock
dec [\arg]
setz al
ret
\c{cpu_inc_locked}:
lock
inc [\arg]
setz al
ret

84
lib/ansi_c.nim Executable file
View File

@@ -0,0 +1,84 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# This include file contains headers of Ansi C procs
# and definitions of Ansi C types in Nimrod syntax
# All symbols are prefixed with 'c_' to avoid ambiguities
proc c_strcmp(a, b: CString): cint {.nodecl, importc: "strcmp".}
proc c_memcmp(a, b: CString, size: cint): cint {.nodecl, importc: "memcmp".}
proc c_memcpy(a, b: CString, size: cint) {.nodecl, importc: "memcpy".}
proc c_strlen(a: CString): cint {.nodecl, importc: "strlen".}
type
C_TextFile {.importc: "FILE", nodecl.} = record # empty record for
# data hiding
C_BinaryFile {.importc: "FILE", nodecl.} = record
C_TextFileStar = ptr CTextFile
C_BinaryFileStar = ptr CBinaryFile
C_JmpBuf {.importc: "jmp_buf".} = array[0..31, int]
var
c_stdin {.importc: "stdin", noDecl.}: C_TextFileStar
c_stdout {.importc: "stdout", noDecl.}: C_TextFileStar
c_stderr {.importc: "stderr", noDecl.}: C_TextFileStar
var # constants faked as variables:
SIGINT {.importc: "SIGINT", nodecl.}: cint
SIGSEGV {.importc: "SIGSEGV", nodecl.}: cint
SIGABRT {.importc: "SIGABRT", nodecl.}: cint
SIGFPE {.importc: "SIGFPE", nodecl.}: cint
SIGILL {.importc: "SIGILL", nodecl.}: cint
when defined(macosx):
var
SIGBUS {.importc: "SIGBUS", nodecl.}: cint
# hopefully this does not lead to new bugs
else:
var
SIGBUS {.importc: "SIGSEGV", nodecl.}: cint
# only Mac OS X has this shit
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.nodecl, importc: "longjmp".}
proc c_setjmp(jmpb: var C_JmpBuf) {.nodecl, importc: "setjmp".}
proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
importc: "signal", header: "<signal.h>".}
proc c_raise(sig: cint) {.importc: "raise", header: "<signal.h>".}
proc c_fputs(c: cstring, f: C_TextFileStar) {.importc: "fputs", noDecl.}
proc c_fgets(c: cstring, n: int, f: C_TextFileStar): cstring {.
importc: "fgets", noDecl.}
proc c_fgetc(stream: C_TextFileStar): int {.importc: "fgetc", nodecl.}
proc c_ungetc(c: int, f: C_TextFileStar) {.importc: "ungetc", nodecl.}
proc c_putc(c: Char, stream: C_TextFileStar) {.importc: "putc", nodecl.}
proc c_fprintf(f: C_TextFileStar, frmt: CString) {.
importc: "fprintf", nodecl, varargs.}
proc c_fopen(filename, mode: cstring): C_TextFileStar {.
importc: "fopen", nodecl.}
proc c_fclose(f: C_TextFileStar) {.importc: "fclose", nodecl.}
proc c_sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs.}
# we use it only in a way that cannot lead to security issues
proc c_fread(buf: Pointer, size, n: int, f: C_BinaryFileStar): int {.
importc: "fread", noDecl.}
proc c_fseek(f: C_BinaryFileStar, offset: clong, whence: int): int {.
importc: "fseek", noDecl.}
proc c_fwrite(buf: Pointer, size, n: int, f: C_BinaryFileStar): int {.
importc: "fwrite", noDecl.}
proc c_exit(errorcode: cint) {.importc: "exit", nodecl.}
proc c_ferror(stream: C_TextFileStar): bool {.importc: "ferror", nodecl.}
proc c_fflush(stream: C_TextFileStar) {.importc: "fflush", nodecl.}
proc c_abort() {.importc: "abort", nodecl.}
proc c_feof(stream: C_TextFileStar): bool {.importc: "feof", nodecl.}

347
lib/arithm.nim Executable file
View File

@@ -0,0 +1,347 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# simple integer arithmetic with overflow checking
proc raiseOverflow {.exportc: "raiseOverflow".} =
# a single proc to reduce code size to a minimum
raise newException(EOverflow, "over- or underflow")
proc raiseDivByZero {.exportc: "raiseDivByZero".} =
raise newException(EDivByZero, "divison by zero")
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
result = a + b
if (result xor a) >= int64(0) or (result xor b) >= int64(0):
return result
raiseOverflow()
proc subInt64(a, b: int64): int64 {.compilerProc, inline.} =
result = a - b
if (result xor a) >= int64(0) or (result xor not b) >= int64(0):
return result
raiseOverflow()
proc negInt64(a: int64): int64 {.compilerProc, inline.} =
if a != low(int64): return -a
raiseOverflow()
proc absInt64(a: int64): int64 {.compilerProc, inline.} =
if a != low(int64):
if a >= 0: return a
else: return -a
raiseOverflow()
proc divInt64(a, b: int64): int64 {.compilerProc, inline.} =
if b == int64(0):
raiseDivByZero()
if a == low(int64) and b == int64(-1):
raiseOverflow()
return a div b
proc modInt64(a, b: int64): int64 {.compilerProc, inline.} =
if b == int64(0):
raiseDivByZero()
return a mod b
#
# This code has been inspired by Python's source code.
# The native int product x*y is either exactly right or *way* off, being
# just the last n bits of the true product, where n is the number of bits
# in an int (the delivered product is the true product plus i*2**n for
# some integer i).
#
# The native float64 product x*y is subject to three
# rounding errors: on a sizeof(int)==8 box, each cast to double can lose
# info, and even on a sizeof(int)==4 box, the multiplication can lose info.
# But, unlike the native int product, it's not in *range* trouble: even
# if sizeof(int)==32 (256-bit ints), the product easily fits in the
# dynamic range of a float64. So the leading 50 (or so) bits of the float64
# product are correct.
#
# We check these two ways against each other, and declare victory if they're
# approximately the same. Else, because the native int product is the only
# one that can lose catastrophic amounts of information, it's the native int
# product that must have overflowed.
#
proc mulInt64(a, b: int64): int64 {.compilerproc.} =
var
resAsFloat, floatProd: float64
result = a * b
floatProd = float64(a) # conversion
floatProd = floatProd * float64(b)
resAsFloat = float64(result)
# Fast path for normal case: small multiplicands, and no info
# is lost in either method.
if resAsFloat == floatProd: return result
# Somebody somewhere lost info. Close enough, or way off? Note
# that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
# The difference either is or isn't significant compared to the
# true value (of which floatProd is a good approximation).
# abs(diff)/abs(prod) <= 1/32 iff
# 32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
return result
raiseOverflow()
proc absInt(a: int): int {.compilerProc, inline.} =
if a != low(int):
if a >= 0: return a
else: return -a
raiseOverflow()
when defined(I386) and (defined(vcc) or defined(wcc) or defined(dmc)):
# or defined(gcc)):
{.define: asmVersion.}
# my Version of Borland C++Builder does not have
# tasm32, which is needed for assembler blocks
# this is why Borland is not included in the 'when'
else:
{.define: useInline.}
when defined(asmVersion) and defined(gcc):
proc addInt(a, b: int): int {.compilerProc, pure, inline.}
proc subInt(a, b: int): int {.compilerProc, pure, inline.}
proc mulInt(a, b: int): int {.compilerProc, pure, inline.}
proc divInt(a, b: int): int {.compilerProc, pure, inline.}
proc modInt(a, b: int): int {.compilerProc, pure, inline.}
proc negInt(a: int): int {.compilerProc, pure, inline.}
elif defined(asmVersion):
proc addInt(a, b: int): int {.compilerProc, pure.}
proc subInt(a, b: int): int {.compilerProc, pure.}
proc mulInt(a, b: int): int {.compilerProc, pure.}
proc divInt(a, b: int): int {.compilerProc, pure.}
proc modInt(a, b: int): int {.compilerProc, pure.}
proc negInt(a: int): int {.compilerProc, pure.}
elif defined(useInline):
proc addInt(a, b: int): int {.compilerProc, inline.}
proc subInt(a, b: int): int {.compilerProc, inline.}
proc mulInt(a, b: int): int {.compilerProc.}
# mulInt is to large for inlining?
proc divInt(a, b: int): int {.compilerProc, inline.}
proc modInt(a, b: int): int {.compilerProc, inline.}
proc negInt(a: int): int {.compilerProc, inline.}
else:
proc addInt(a, b: int): int {.compilerProc.}
proc subInt(a, b: int): int {.compilerProc.}
proc mulInt(a, b: int): int {.compilerProc.}
proc divInt(a, b: int): int {.compilerProc.}
proc modInt(a, b: int): int {.compilerProc.}
proc negInt(a: int): int {.compilerProc.}
# implementation:
when defined(asmVersion) and not defined(gcc):
# assembler optimized versions for compilers that
# have an intel syntax assembler:
proc addInt(a, b: int): int =
# a in eax, and b in edx
asm """
mov eax, `a`
add eax, `b`
jno theEnd
call raiseOverflow
theEnd:
"""
proc subInt(a, b: int): int =
asm """
mov eax, `a`
sub eax, `b`
jno theEnd
call raiseOverflow
theEnd:
"""
proc negInt(a: int): int =
asm """
mov eax, `a`
neg eax
jno theEnd
call raiseOverflow
theEnd:
"""
proc divInt(a, b: int): int =
asm """
mov eax, `a`
mov ecx, `b`
xor edx, edx
idiv ecx
jno theEnd
call raiseOverflow
theEnd:
"""
proc modInt(a, b: int): int =
asm """
mov eax, `a`
mov ecx, `b`
xor edx, edx
idiv ecx
jno theEnd
call raiseOverflow
theEnd:
mov eax, edx
"""
proc mulInt(a, b: int): int =
asm """
mov eax, `a`
mov ecx, `b`
xor edx, edx
imul ecx
jno theEnd
call raiseOverflow
theEnd:
"""
elif defined(asmVersion) and defined(gcc):
proc addInt(a, b: int): int =
asm """ "addl %1,%%eax\n"
"jno 1\n"
"call _raiseOverflow\n"
"1: \n"
:"=a"(`a`)
:"a"(`a`), "r"(`b`)
"""
proc subInt(a, b: int): int =
asm """ "subl %1,%%eax\n"
"jno 1\n"
"call _raiseOverflow\n"
"1: \n"
:"=a"(`a`)
:"a"(`a`), "r"(`b`)
"""
proc negInt(a: int): int =
asm """ "negl %%eax\n"
"jno 1\n"
"call _raiseOverflow\n"
"1: \n"
:"=a"(`a`)
:"a"(`a`)
"""
proc divInt(a, b: int): int =
asm """ "xorl %%edx, %%edx\n"
"idivl %%ecx\n"
"jno 1\n"
"call _raiseOverflow\n"
"1: \n"
:"=a"(`a`)
:"a"(`a`), "c"(`b`)
:"%edx"
"""
proc modInt(a, b: int): int =
asm """ "xorl %%edx, %%edx\n"
"idivl %%ecx\n"
"jno 1\n"
"call _raiseOverflow\n"
"1: \n"
"movl %%edx, %%eax"
:"=a"(`a`)
:"a"(`a`), "c"(`b`)
:"%edx"
"""
proc mulInt(a, b: int): int =
asm """ "xorl %%edx, %%edx\n"
"imull %%ecx\n"
"jno 1\n"
"call _raiseOverflow\n"
"1: \n"
:"=a"(`a`)
:"a"(`a`), "c"(`b`)
:"%edx"
"""
else:
# Platform independant versions of the above (slower!)
proc addInt(a, b: int): int =
result = a + b
if (result xor a) >= 0 or (result xor b) >= 0:
return result
raiseOverflow()
proc subInt(a, b: int): int =
result = a - b
if (result xor a) >= 0 or (result xor not b) >= 0:
return result
raiseOverflow()
proc negInt(a: int): int =
if a != low(int): return -a
raiseOverflow()
proc divInt(a, b: int): int =
if b == 0:
raiseDivByZero()
if a == low(int) and b == -1:
raiseOverflow()
return a div b
proc modInt(a, b: int): int =
if b == 0:
raiseDivByZero()
return a mod b
#
# This code has been inspired by Python's source code.
# The native int product x*y is either exactly right or *way* off, being
# just the last n bits of the true product, where n is the number of bits
# in an int (the delivered product is the true product plus i*2**n for
# some integer i).
#
# The native float64 product x*y is subject to three
# rounding errors: on a sizeof(int)==8 box, each cast to double can lose
# info, and even on a sizeof(int)==4 box, the multiplication can lose info.
# But, unlike the native int product, it's not in *range* trouble: even
# if sizeof(int)==32 (256-bit ints), the product easily fits in the
# dynamic range of a float64. So the leading 50 (or so) bits of the float64
# product are correct.
#
# We check these two ways against each other, and declare victory if
# they're approximately the same. Else, because the native int product is
# the only one that can lose catastrophic amounts of information, it's the
# native int product that must have overflowed.
#
proc mulInt(a, b: int): int =
var
resAsFloat, floatProd: float
result = a * b
floatProd = toFloat(a) * toFloat(b)
resAsFloat = toFloat(result)
# Fast path for normal case: small multiplicands, and no info
# is lost in either method.
if resAsFloat == floatProd: return result
# Somebody somewhere lost info. Close enough, or way off? Note
# that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
# The difference either is or isn't significant compared to the
# true value (of which floatProd is a good approximation).
# abs(diff)/abs(prod) <= 1/32 iff
# 32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
return result
raiseOverflow()

118
lib/assign.nim Executable file
View File

@@ -0,0 +1,118 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
#when defined(debugGC):
# {.define: logAssign.}
proc genericAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.}
proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode) =
var
d = cast[TAddress](dest)
s = cast[TAddress](src)
case n.kind
of nkNone: assert(false)
of nkSlot:
genericAssign(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
n.typ)
of nkList:
for i in 0..n.len-1:
genericAssignAux(dest, src, n.sons[i])
of nkCase:
copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
n.typ.size)
var m = selectBranch(src, n)
if m != nil: genericAssignAux(dest, src, m)
proc genericAssign(dest, src: Pointer, mt: PNimType) =
var
d = cast[TAddress](dest)
s = cast[TAddress](src)
assert(mt != nil)
case mt.Kind
of tySequence:
var s2 = cast[ppointer](src)^
var seq = cast[PGenericSeq](s2)
if s2 == nil: # this can happen! nil sequences are allowed
var x = cast[ppointer](dest)
x^ = nil
return
assert(dest != nil)
unsureAsgnRef(cast[ppointer](dest),
newObj(mt, seq.len * mt.base.size + GenericSeqSize))
var dst = cast[taddress](cast[ppointer](dest)^)
for i in 0..seq.len-1:
genericAssign(
cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
cast[pointer](cast[taddress](s2) +% i *% mt.base.size +%
GenericSeqSize),
mt.Base)
var dstseq = cast[PGenericSeq](dst)
dstseq.len = seq.len
dstseq.space = seq.len
of tyRecord, tyObject, tyTuple:
genericAssignAux(dest, src, mt.node)
of tyArray, tyArrayConstr:
for i in 0..(mt.size div mt.base.size)-1:
genericAssign(cast[pointer](d +% i*% mt.base.size),
cast[pointer](s +% i*% mt.base.size), mt.base)
of tyString: # a leaf
var s2 = cast[ppointer](s)^
if s2 != nil: # nil strings are possible!
unsureAsgnRef(cast[ppointer](dest), copyString(cast[mstring](s2)))
else:
var x = cast[ppointer](dest)
x^ = nil
return
of tyRef: # BUGFIX: a long time this has been forgotten!
unsureAsgnRef(cast[ppointer](dest), cast[ppointer](s)^)
else:
copyMem(dest, src, mt.size) # copy raw bits
proc genericSeqAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
genericAssign(dest, addr(src), mt)
proc genericAssignOpenArray(dest, src: pointer, len: int,
mt: PNimType) {.compilerproc.} =
var
d = cast[TAddress](dest)
s = cast[TAddress](src)
for i in 0..len-1:
genericAssign(cast[pointer](d +% i*% mt.base.size),
cast[pointer](s +% i*% mt.base.size), mt.base)
proc objectInit(dest: Pointer, typ: PNimType) {.compilerProc.}
proc objectInitAux(dest: Pointer, n: ptr TNimNode) =
var d = cast[TAddress](dest)
case n.kind
of nkNone: assert(false)
of nkSLot: objectInit(cast[pointer](d +% n.offset), n.typ)
of nkList:
for i in 0..n.len-1:
objectInitAux(dest, n.sons[i])
of nkCase:
var m = selectBranch(dest, n)
if m != nil: objectInitAux(dest, m)
proc objectInit(dest: Pointer, typ: PNimType) =
# the generic init proc that takes care of initialization of complex
# objects on the stack or heap
var d = cast[TAddress](dest)
case typ.kind
of tyObject:
# iterate over any structural type
# here we have to init the type field:
var pint = cast[ptr PNimType](dest)
pint^ = typ
objectInitAux(dest, typ.node)
of tyRecord:
objectInitAux(dest, typ.node)
of tyArray, tyArrayConstr:
for i in 0..(typ.size div typ.base.size)-1:
objectInit(cast[pointer](d +% i * typ.base.size), typ.base)
else: nil # nothing to do

698
lib/base/cairo/cairo.nim Normal file
View File

@@ -0,0 +1,698 @@
#* cairo - a vector graphics library with display and print output
# *
# * Copyright <20> 2002 University of Southern California
# * Copyright <20> 2005 Red Hat, Inc.
# *
# * This library is free software; you can redistribute it and/or
# * modify it either under the terms of the GNU Lesser General Public
# * License version 2.1 as published by the Free Software Foundation
# * (the "LGPL") or, at your option, under the terms of the Mozilla
# * Public License Version 1.1 (the "MPL"). If you do not alter this
# * notice, a recipient may use your version of this file under either
# * the MPL or the LGPL.
# *
# * You should have received a copy of the LGPL along with this library
# * in the file COPYING-LGPL-2.1; if not, write to the Free Software
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# * You should have received a copy of the MPL along with this library
# * in the file COPYING-MPL-1.1
# *
# * The contents of this file are subject to the Mozilla Public License
# * Version 1.1 (the "License"); you may not use this file except in
# * compliance with the License. You may obtain a copy of the License at
# * http://www.mozilla.org/MPL/
# *
# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
# * OF ANY KIND, either express or implied. See the LGPL or the MPL for
# * the specific language governing rights and limitations.
# *
# * The Original Code is the cairo graphics library.
# *
# * The Initial Developer of the Original Code is University of Southern
# * California.
# *
# * Contributor(s):
# * Carl D. Worth <cworth@cworth.org>
# #*
# * This FreePascal binding generated August 26, 2005
# * by Jeffrey Pohlmeyer <yetanothergeek@yahoo.com>
#
#
# - Updated to cairo version 1.4
# - Grouped OS specific fuctions in separated units
# - Organized the functions by group and ordered exactly as the c header
# - Cleared parameter list syntax according to pascal standard
#
# By Luiz Am<41>rico Pereira C<>mara
# October 2007
#
when defined(windows):
const
LIB_CAIRO* = "cairo.dll"
else:
const
LIB_CAIRO* = "libcairo.so"
type
PByte = cstring
cairo_status_t* = enum
CAIRO_STATUS_SUCCESS = 0, CAIRO_STATUS_NO_MEMORY,
CAIRO_STATUS_INVALID_RESTORE, CAIRO_STATUS_INVALID_POP_GROUP,
CAIRO_STATUS_NO_CURRENT_POINT, CAIRO_STATUS_INVALID_MATRIX,
CAIRO_STATUS_INVALID_STATUS, CAIRO_STATUS_NULL_POINTER,
CAIRO_STATUS_INVALID_STRING, CAIRO_STATUS_INVALID_PATH_DATA,
CAIRO_STATUS_READ_ERROR, CAIRO_STATUS_WRITE_ERROR,
CAIRO_STATUS_SURFACE_FINISHED, CAIRO_STATUS_SURFACE_TYPE_MISMATCH,
CAIRO_STATUS_PATTERN_TYPE_MISMATCH, CAIRO_STATUS_INVALID_CONTENT,
CAIRO_STATUS_INVALID_FORMAT, CAIRO_STATUS_INVALID_VISUAL,
CAIRO_STATUS_FILE_NOT_FOUND, CAIRO_STATUS_INVALID_DASH
cairo_operator_t* = enum
CAIRO_OPERATOR_CLEAR, CAIRO_OPERATOR_SOURCE, CAIRO_OPERATOR_OVER,
CAIRO_OPERATOR_IN, CAIRO_OPERATOR_OUT, CAIRO_OPERATOR_ATOP,
CAIRO_OPERATOR_DEST, CAIRO_OPERATOR_DEST_OVER, CAIRO_OPERATOR_DEST_IN,
CAIRO_OPERATOR_DEST_OUT, CAIRO_OPERATOR_DEST_ATOP, CAIRO_OPERATOR_XOR,
CAIRO_OPERATOR_ADD, CAIRO_OPERATOR_SATURATE
cairo_antialias_t* = enum
CAIRO_ANTIALIAS_DEFAULT, CAIRO_ANTIALIAS_NONE, CAIRO_ANTIALIAS_GRAY,
CAIRO_ANTIALIAS_SUBPIXEL
cairo_fill_rule_t* = enum
CAIRO_FILL_RULE_WINDING, CAIRO_FILL_RULE_EVEN_ODD
cairo_line_cap_t* = enum
CAIRO_LINE_CAP_BUTT, CAIRO_LINE_CAP_ROUND, CAIRO_LINE_CAP_SQUARE
cairo_line_join_t* = enum
CAIRO_LINE_JOIN_MITER, CAIRO_LINE_JOIN_ROUND, CAIRO_LINE_JOIN_BEVEL
cairo_font_slant_t* = enum
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_SLANT_ITALIC, CAIRO_FONT_SLANT_OBLIQUE
cairo_font_weight_t* = enum
CAIRO_FONT_WEIGHT_NORMAL, CAIRO_FONT_WEIGHT_BOLD
cairo_subpixel_order_t* = enum
CAIRO_SUBPIXEL_ORDER_DEFAULT, CAIRO_SUBPIXEL_ORDER_RGB,
CAIRO_SUBPIXEL_ORDER_BGR, CAIRO_SUBPIXEL_ORDER_VRGB,
CAIRO_SUBPIXEL_ORDER_VBGR
cairo_hint_style_t* = enum
CAIRO_HINT_STYLE_DEFAULT, CAIRO_HINT_STYLE_NONE, CAIRO_HINT_STYLE_SLIGHT,
CAIRO_HINT_STYLE_MEDIUM, CAIRO_HINT_STYLE_FULL
cairo_hint_metrics_t* = enum
CAIRO_HINT_METRICS_DEFAULT, CAIRO_HINT_METRICS_OFF, CAIRO_HINT_METRICS_ON
cairo_path_data_type_t* = enum
CAIRO_PATH_MOVE_TO, CAIRO_PATH_LINE_TO, CAIRO_PATH_CURVE_TO,
CAIRO_PATH_CLOSE_PATH
cairo_content_t* = enum
CAIRO_CONTENT_COLOR = 0x00001000, CAIRO_CONTENT_ALPHA = 0x00002000,
CAIRO_CONTENT_COLOR_ALPHA = 0x00003000
cairo_format_t* = enum
CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_RGB24, CAIRO_FORMAT_A8, CAIRO_FORMAT_A1
cairo_extend_t* = enum
CAIRO_EXTEND_NONE, CAIRO_EXTEND_REPEAT, CAIRO_EXTEND_REFLECT,
CAIRO_EXTEND_PAD
cairo_filter_t* = enum
CAIRO_FILTER_FAST, CAIRO_FILTER_GOOD, CAIRO_FILTER_BEST,
CAIRO_FILTER_NEAREST, CAIRO_FILTER_BILINEAR, CAIRO_FILTER_GAUSSIAN
cairo_font_type_t* = enum
CAIRO_FONT_TYPE_TOY, CAIRO_FONT_TYPE_FT, CAIRO_FONT_TYPE_WIN32,
CAIRO_FONT_TYPE_ATSUI
cairo_pattern_type_t* = enum
CAIRO_PATTERN_TYPE_SOLID, CAIRO_PATTERN_TYPE_SURFACE,
CAIRO_PATTERN_TYPE_LINEAR, CAIRO_PATTERN_TYPE_RADIAL
cairo_surface_type_t* = enum
CAIRO_SURFACE_TYPE_IMAGE, CAIRO_SURFACE_TYPE_PDF, CAIRO_SURFACE_TYPE_PS,
CAIRO_SURFACE_TYPE_XLIB, CAIRO_SURFACE_TYPE_XCB, CAIRO_SURFACE_TYPE_GLITZ,
CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_SURFACE_TYPE_WIN32,
CAIRO_SURFACE_TYPE_BEOS, CAIRO_SURFACE_TYPE_DIRECTFB,
CAIRO_SURFACE_TYPE_SVG, CAIRO_SURFACE_TYPE_OS2
cairo_svg_version_t* = enum
CAIRO_SVG_VERSION_1_1, CAIRO_SVG_VERSION_1_2
Pcairo_surface_t* = ref cairo_surface_t
PPcairo_surface_t* = ref Pcairo_surface_t
Pcairo_t* = ref cairo_t
Pcairo_pattern_t* = ref cairo_pattern_t
Pcairo_font_options_t* = ref cairo_font_options_t
Pcairo_font_face_t* = ref cairo_font_face_t
Pcairo_scaled_font_t* = ref cairo_scaled_font_t
Pcairo_bool_t* = ref cairo_bool_t
cairo_bool_t* = int32
Pcairo_matrix_t* = ref cairo_matrix_t
Pcairo_user_data_key_t* = ref cairo_user_data_key_t
Pcairo_glyph_t* = ref cairo_glyph_t
Pcairo_text_extents_t* = ref cairo_text_extents_t
Pcairo_font_extents_t* = ref cairo_font_extents_t
Pcairo_path_data_type_t* = ref cairo_path_data_type_t
Pcairo_path_data_t* = ref cairo_path_data_t
Pcairo_path_t* = ref cairo_path_t
Pcairo_rectangle_t* = ref cairo_rectangle_t
Pcairo_rectangle_list_t* = ref cairo_rectangle_list_t
cairo_destroy_func_t* = proc (data: Pointer){.cdecl.}
cairo_write_func_t* = proc (closure: Pointer, data: PByte, len: int32): cairo_status_t{.
cdecl.}
cairo_read_func_t* = proc (closure: Pointer, data: PByte, len: int32): cairo_status_t{.
cdecl.}
cairo_t* = record #OPAQUE
cairo_surface_t* = record #OPAQUE
cairo_pattern_t* = record #OPAQUE
cairo_scaled_font_t* = record #OPAQUE
cairo_font_face_t* = record #OPAQUE
cairo_font_options_t* = record #OPAQUE
cairo_matrix_t* = record
xx: float64
yx: float64
xy: float64
yy: float64
x0: float64
y0: float64
cairo_user_data_key_t* = record
unused: int32
cairo_glyph_t* = record
index: int32
x: float64
y: float64
cairo_text_extents_t* = record
x_bearing: float64
y_bearing: float64
width: float64
height: float64
x_advance: float64
y_advance: float64
cairo_font_extents_t* = record
ascent: float64
descent: float64
height: float64
max_x_advance: float64
max_y_advance: float64
cairo_path_data_t* = record #* _type : cairo_path_data_type_t;
# length : LongInt;
# end
x: float64
y: float64
cairo_path_t* = record
status: cairo_status_t
data: Pcairo_path_data_t
num_data: int32
cairo_rectangle_t* = record
x, y, width, height: float64
cairo_rectangle_list_t* = record
status: cairo_status_t
rectangles: Pcairo_rectangle_t
num_rectangles: int32
proc cairo_version*(): int32{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_version_string*(): cstring{.cdecl, importc, dynlib: LIB_CAIRO.}
#Helper function to retrieve decoded version
proc cairo_version*(major, minor, micro: var int32)
#* Functions for manipulating state objects
proc cairo_create*(target: Pcairo_surface_t): Pcairo_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_reference*(cr: Pcairo_t): Pcairo_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_destroy*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_reference_count*(cr: Pcairo_t): int32{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_user_data*(cr: Pcairo_t, key: Pcairo_user_data_key_t): pointer{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_user_data*(cr: PCairo_t, key: Pcairo_user_data_key_t,
user_data: Pointer, destroy: cairo_destroy_func_t): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_save*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_restore*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_push_group*(cr: PCairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_push_group_with_content*(cr: PCairo_t, content: cairo_content_t){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pop_group*(cr: PCairo_t): Pcairo_pattern_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pop_group_to_source*(cr: PCairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
#* Modify state
proc cairo_set_operator*(cr: Pcairo_t, op: cairo_operator_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_source*(cr: Pcairo_t, source: Pcairo_pattern_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_source_rgb*(cr: Pcairo_t, red, green, blue: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_source_rgba*(cr: Pcairo_t, red, green, blue, alpha: float64){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_source_surface*(cr: Pcairo_t, surface: Pcairo_surface_t,
x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_tolerance*(cr: Pcairo_t, tolerance: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_antialias*(cr: Pcairo_t, antialias: cairo_antialias_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_fill_rule*(cr: Pcairo_t, fill_rule: cairo_fill_rule_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_line_width*(cr: Pcairo_t, width: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_line_cap*(cr: Pcairo_t, line_cap: cairo_line_cap_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_line_join*(cr: Pcairo_t, line_join: cairo_line_join_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_dash*(cr: Pcairo_t, dashes: openarray[float64],
offset: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_miter_limit*(cr: Pcairo_t, limit: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_translate*(cr: Pcairo_t, tx, ty: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scale*(cr: Pcairo_t, sx, sy: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rotate*(cr: Pcairo_t, angle: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_transform*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_identity_matrix*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_user_to_device*(cr: Pcairo_t, x, y: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_user_to_device_distance*(cr: Pcairo_t, dx, dy: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_device_to_user*(cr: Pcairo_t, x, y: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_device_to_user_distance*(cr: Pcairo_t, dx, dy: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
#* Path creation functions
proc cairo_new_path*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_move_to*(cr: Pcairo_t, x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_new_sub_path*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_line_to*(cr: Pcairo_t, x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_curve_to*(cr: Pcairo_t, x1, y1, x2, y2, x3, y3: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_arc*(cr: Pcairo_t, xc, yc, radius, angle1, angle2: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_arc_negative*(cr: Pcairo_t, xc, yc, radius, angle1, angle2: float64){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rel_move_to*(cr: Pcairo_t, dx, dy: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rel_line_to*(cr: Pcairo_t, dx, dy: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rel_curve_to*(cr: Pcairo_t, dx1, dy1, dx2, dy2, dx3, dy3: float64){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rectangle*(cr: Pcairo_t, x, y, width, height: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_close_path*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
#* Painting functions
proc cairo_paint*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_paint_with_alpha*(cr: Pcairo_t, alpha: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_mask*(cr: Pcairo_t, pattern: Pcairo_pattern_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_mask_surface*(cr: Pcairo_t, surface: Pcairo_surface_t,
surface_x, surface_y: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_stroke*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_stroke_preserve*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_fill*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_fill_preserve*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_copy_page*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_show_page*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
#* Insideness testing
proc cairo_in_stroke*(cr: Pcairo_t, x, y: float64): cairo_bool_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_in_fill*(cr: Pcairo_t, x, y: float64): cairo_bool_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
#* Rectangular extents
proc cairo_stroke_extents*(cr: Pcairo_t, x1, y1, x2, y2: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_fill_extents*(cr: Pcairo_t, x1, y1, x2, y2: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
#* Clipping
proc cairo_reset_clip*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_clip*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_clip_preserve*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_clip_extents*(cr: Pcairo_t, x1, y1, x2, y2: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_copy_clip_rectangle_list*(cr: Pcairo_t): Pcairo_rectangle_list_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rectangle_list_destroy*(rectangle_list: Pcairo_rectangle_list_t){.
cdecl, importc, dynlib: LIB_CAIRO.}
#* Font/Text functions
proc cairo_font_options_create*(): Pcairo_font_options_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_font_options_copy*(original: Pcairo_font_options_t): Pcairo_font_options_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_destroy*(options: Pcairo_font_options_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_font_options_status*(options: Pcairo_font_options_t): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_merge*(options, other: Pcairo_font_options_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_font_options_equal*(options, other: Pcairo_font_options_t): cairo_bool_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_hash*(options: Pcairo_font_options_t): int32{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_font_options_set_antialias*(options: Pcairo_font_options_t,
antialias: cairo_antialias_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_font_options_get_antialias*(options: Pcairo_font_options_t): cairo_antialias_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_set_subpixel_order*(options: Pcairo_font_options_t,
subpixel_order: cairo_subpixel_order_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_get_subpixel_order*(options: Pcairo_font_options_t): cairo_subpixel_order_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_set_hint_style*(options: Pcairo_font_options_t,
hint_style: cairo_hint_style_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_font_options_get_hint_style*(options: Pcairo_font_options_t): cairo_hint_style_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_set_hint_metrics*(options: Pcairo_font_options_t,
hint_metrics: cairo_hint_metrics_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_get_hint_metrics*(options: Pcairo_font_options_t): cairo_hint_metrics_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
#* This interface is for dealing with text as text, not caring about the
# font object inside the the cairo_t.
proc cairo_select_font_face*(cr: Pcairo_t, family: cstring,
slant: cairo_font_slant_t,
weight: cairo_font_weight_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_font_size*(cr: Pcairo_t, size: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_font_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_get_font_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_font_options*(cr: Pcairo_t, options: Pcairo_font_options_t){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_font_options*(cr: Pcairo_t, options: Pcairo_font_options_t){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_font_face*(cr: Pcairo_t, font_face: Pcairo_font_face_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_get_font_face*(cr: Pcairo_t): Pcairo_font_face_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_scaled_font*(cr: PCairo_t, scaled_font: Pcairo_scaled_font_t){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_scaled_font*(cr: Pcairo_t): Pcairo_scaled_font_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_show_text*(cr: Pcairo_t, utf8: cstring){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_show_glyphs*(cr: Pcairo_t, glyphs: Pcairo_glyph_t, num_glyphs: int32){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_text_path*(cr: Pcairo_t, utf8: cstring){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_glyph_path*(cr: Pcairo_t, glyphs: Pcairo_glyph_t, num_glyphs: int32){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_text_extents*(cr: Pcairo_t, utf8: cstring,
extents: Pcairo_text_extents_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_glyph_extents*(cr: Pcairo_t, glyphs: Pcairo_glyph_t,
num_glyphs: int32, extents: Pcairo_text_extents_t){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_extents*(cr: Pcairo_t, extents: Pcairo_font_extents_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
#* Generic identifier for a font style
proc cairo_font_face_reference*(font_face: Pcairo_font_face_t): Pcairo_font_face_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_face_destroy*(font_face: Pcairo_font_face_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_font_face_get_reference_count*(font_face: Pcairo_font_face_t): int32{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_face_status*(font_face: Pcairo_font_face_t): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_face_get_type*(font_face: Pcairo_font_face_t): cairo_font_type_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_face_get_user_data*(font_face: Pcairo_font_face_t,
key: Pcairo_user_data_key_t): pointer{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_face_set_user_data*(font_face: Pcairo_font_face_t,
key: Pcairo_user_data_key_t,
user_data: pointer,
destroy: cairo_destroy_func_t): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
#* Portable interface to general font features
proc cairo_scaled_font_create*(font_face: Pcairo_font_face_t,
font_matrix: Pcairo_matrix_t,
ctm: Pcairo_matrix_t,
options: Pcairo_font_options_t): Pcairo_scaled_font_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_reference*(scaled_font: Pcairo_scaled_font_t): Pcairo_scaled_font_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_destroy*(scaled_font: Pcairo_scaled_font_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_reference_count*(scaled_font: Pcairo_scaled_font_t): int32{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_status*(scaled_font: Pcairo_scaled_font_t): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_type*(scaled_font: Pcairo_scaled_font_t): cairo_font_type_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_user_data*(scaled_font: Pcairo_scaled_font_t,
key: Pcairo_user_data_key_t): Pointer{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_set_user_data*(scaled_font: Pcairo_scaled_font_t,
key: Pcairo_user_data_key_t,
user_data: Pointer,
destroy: cairo_destroy_func_t): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_extents*(scaled_font: Pcairo_scaled_font_t,
extents: Pcairo_font_extents_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_scaled_font_text_extents*(scaled_font: Pcairo_scaled_font_t,
utf8: cstring,
extents: Pcairo_text_extents_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_scaled_font_glyph_extents*(scaled_font: Pcairo_scaled_font_t,
glyphs: Pcairo_glyph_t, num_glyphs: int32,
extents: Pcairo_text_extents_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_font_face*(scaled_font: Pcairo_scaled_font_t): Pcairo_font_face_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_font_matrix*(scaled_font: Pcairo_scaled_font_t,
font_matrix: Pcairo_matrix_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_ctm*(scaled_font: Pcairo_scaled_font_t,
ctm: Pcairo_matrix_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_font_options*(scaled_font: Pcairo_scaled_font_t,
options: Pcairo_font_options_t){.cdecl, importc, dynlib: LIB_CAIRO.}
#* Query functions
proc cairo_get_operator*(cr: Pcairo_t): cairo_operator_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_get_source*(cr: Pcairo_t): Pcairo_pattern_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_tolerance*(cr: Pcairo_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_antialias*(cr: Pcairo_t): cairo_antialias_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_get_current_point*(cr: Pcairo_t, x, y: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_get_fill_rule*(cr: Pcairo_t): cairo_fill_rule_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_get_line_width*(cr: Pcairo_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_line_cap*(cr: Pcairo_t): cairo_line_cap_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_get_line_join*(cr: Pcairo_t): cairo_line_join_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_get_miter_limit*(cr: Pcairo_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_dash_count*(cr: Pcairo_t): int32{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_dash*(cr: Pcairo_t, dashes, offset: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_get_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_get_target*(cr: Pcairo_t): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_group_target*(cr: Pcairo_t): Pcairo_surface_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_copy_path*(cr: Pcairo_t): Pcairo_path_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_copy_path_flat*(cr: Pcairo_t): Pcairo_path_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_append_path*(cr: Pcairo_t, path: Pcairo_path_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_path_destroy*(path: Pcairo_path_t){.cdecl, importc, dynlib: LIB_CAIRO.}
#* Error status queries
proc cairo_status*(cr: Pcairo_t): cairo_status_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_status_to_string*(status: cairo_status_t): cstring{.cdecl, importc,
dynlib: LIB_CAIRO.}
#* Surface manipulation
proc cairo_surface_create_similar*(other: Pcairo_surface_t,
content: cairo_content_t,
width, height: int32): Pcairo_surface_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_reference*(surface: Pcairo_surface_t): Pcairo_surface_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_finish*(surface: Pcairo_surface_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_destroy*(surface: Pcairo_surface_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_get_reference_count*(surface: Pcairo_surface_t): int32{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_status*(surface: Pcairo_surface_t): cairo_status_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_surface_get_type*(surface: Pcairo_surface_t): cairo_surface_type_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_get_content*(surface: Pcairo_surface_t): cairo_content_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_write_to_png*(surface: Pcairo_surface_t, filename: cstring): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_write_to_png_stream*(surface: Pcairo_surface_t,
write_func: cairo_write_func_t,
closure: pointer): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_get_user_data*(surface: Pcairo_surface_t,
key: Pcairo_user_data_key_t): pointer{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_surface_set_user_data*(surface: Pcairo_surface_t,
key: Pcairo_user_data_key_t,
user_data: pointer,
destroy: cairo_destroy_func_t): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_get_font_options*(surface: Pcairo_surface_t,
options: Pcairo_font_options_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_surface_flush*(surface: Pcairo_surface_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_mark_dirty*(surface: Pcairo_surface_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_surface_mark_dirty_rectangle*(surface: Pcairo_surface_t,
x, y, width, height: int32){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_set_device_offset*(surface: Pcairo_surface_t,
x_offset, y_offset: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_surface_get_device_offset*(surface: Pcairo_surface_t,
x_offset, y_offset: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_surface_set_fallback_resolution*(surface: Pcairo_surface_t,
x_pixels_per_inch, y_pixels_per_inch: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
#* Image-surface functions
proc cairo_image_surface_create*(format: cairo_format_t, width, height: int32): Pcairo_surface_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_image_surface_create_for_data*(data: Pbyte, format: cairo_format_t,
width, height, stride: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_image_surface_get_data*(surface: Pcairo_surface_t): cstring{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_image_surface_get_format*(surface: Pcairo_surface_t): cairo_format_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_image_surface_get_width*(surface: Pcairo_surface_t): int32{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_image_surface_get_height*(surface: Pcairo_surface_t): int32{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_image_surface_get_stride*(surface: Pcairo_surface_t): int32{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_image_surface_create_from_png*(filename: cstring): Pcairo_surface_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_image_surface_create_from_png_stream*(read_func: cairo_read_func_t,
closure: pointer): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
#* Pattern creation functions
proc cairo_pattern_create_rgb*(red, green, blue: float64): Pcairo_pattern_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_create_rgba*(red, green, blue, alpha: float64): Pcairo_pattern_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_create_for_surface*(surface: Pcairo_surface_t): Pcairo_pattern_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_create_linear*(x0, y0, x1, y1: float64): Pcairo_pattern_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_create_radial*(cx0, cy0, radius0, cx1, cy1, radius1: float64): Pcairo_pattern_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_reference*(pattern: Pcairo_pattern_t): Pcairo_pattern_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_destroy*(pattern: Pcairo_pattern_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_reference_count*(pattern: Pcairo_pattern_t): int32{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_status*(pattern: Pcairo_pattern_t): cairo_status_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_pattern_get_user_data*(pattern: Pcairo_pattern_t,
key: Pcairo_user_data_key_t): Pointer{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_pattern_set_user_data*(pattern: Pcairo_pattern_t,
key: Pcairo_user_data_key_t,
user_data: Pointer,
destroy: cairo_destroy_func_t): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_type*(pattern: Pcairo_pattern_t): cairo_pattern_type_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_add_color_stop_rgb*(pattern: Pcairo_pattern_t,
offset, red, green, blue: float64){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_add_color_stop_rgba*(pattern: Pcairo_pattern_t, offset, red,
green, blue, alpha: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_set_matrix*(pattern: Pcairo_pattern_t,
matrix: Pcairo_matrix_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_pattern_get_matrix*(pattern: Pcairo_pattern_t,
matrix: Pcairo_matrix_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_pattern_set_extend*(pattern: Pcairo_pattern_t, extend: cairo_extend_t){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_extend*(pattern: Pcairo_pattern_t): cairo_extend_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_set_filter*(pattern: Pcairo_pattern_t, filter: cairo_filter_t){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_filter*(pattern: Pcairo_pattern_t): cairo_filter_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_rgba*(pattern: Pcairo_pattern_t,
red, green, blue, alpha: var float64): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_surface*(pattern: Pcairo_pattern_t,
surface: PPcairo_surface_t): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_color_stop_rgba*(pattern: Pcairo_pattern_t, index: int32,
offset, red, green, blue, alpha: var float64): cairo_status_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_pattern_get_color_stop_count*(pattern: Pcairo_pattern_t,
count: var int32): cairo_status_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_linear_points*(pattern: Pcairo_pattern_t,
x0, y0, x1, y1: var float64): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_radial_circles*(pattern: Pcairo_pattern_t,
x0, y0, r0, x1, y1, r1: var float64): cairo_status_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
#* Matrix functions
proc cairo_matrix_init*(matrix: Pcairo_matrix_t, xx, yx, xy, yy, x0, y0: float64){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_matrix_init_identity*(matrix: Pcairo_matrix_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_matrix_init_translate*(matrix: Pcairo_matrix_t, tx, ty: float64){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_matrix_init_scale*(matrix: Pcairo_matrix_t, sx, sy: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_matrix_init_rotate*(matrix: Pcairo_matrix_t, radians: float64){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_matrix_translate*(matrix: Pcairo_matrix_t, tx, ty: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_matrix_scale*(matrix: Pcairo_matrix_t, sx, sy: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_matrix_rotate*(matrix: Pcairo_matrix_t, radians: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_matrix_invert*(matrix: Pcairo_matrix_t): cairo_status_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_matrix_multiply*(result, a, b: Pcairo_matrix_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_matrix_transform_distance*(matrix: Pcairo_matrix_t, dx, dy: var float64){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_matrix_transform_point*(matrix: Pcairo_matrix_t, x, y: var float64){.
cdecl, importc, dynlib: LIB_CAIRO.}
#* PDF functions
proc cairo_pdf_surface_create*(filename: cstring,
width_in_points, height_in_points: float64): Pcairo_surface_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pdf_surface_create_for_stream*(write_func: cairo_write_func_t,
closure: Pointer, width_in_points, height_in_points: float64): Pcairo_surface_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pdf_surface_set_size*(surface: Pcairo_surface_t,
width_in_points, height_in_points: float64){.
cdecl, importc, dynlib: LIB_CAIRO.}
#* PS functions
proc cairo_ps_surface_create*(filename: cstring,
width_in_points, height_in_points: float64): Pcairo_surface_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ps_surface_create_for_stream*(write_func: cairo_write_func_t,
closure: Pointer, width_in_points, height_in_points: float64): Pcairo_surface_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ps_surface_set_size*(surface: Pcairo_surface_t,
width_in_points, height_in_points: float64){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ps_surface_dsc_comment*(surface: Pcairo_surface_t, comment: cstring){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ps_surface_dsc_begin_setup*(surface: Pcairo_surface_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_ps_surface_dsc_begin_page_setup*(surface: Pcairo_surface_t){.cdecl, importc,
dynlib: LIB_CAIRO.}
#* SVG functions
proc cairo_svg_surface_create*(filename: cstring,
width_in_points, height_in_points: float64): Pcairo_surface_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_svg_surface_create_for_stream*(write_func: cairo_write_func_t,
closure: Pointer, width_in_points, height_in_points: float64): Pcairo_surface_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_svg_surface_restrict_to_version*(surface: Pcairo_surface_t,
version: cairo_svg_version_t){.cdecl, importc, dynlib: LIB_CAIRO.}
#todo: see how translate this
#procedure cairo_svg_get_versions(cairo_svg_version_t const **versions,
# int *num_versions);
proc cairo_svg_version_to_string*(version: cairo_svg_version_t): cstring{.cdecl, importc,
dynlib: LIB_CAIRO.}
#* Functions to be used while debugging (not intended for use in production code)
proc cairo_debug_reset_static_data*(){.cdecl, importc, dynlib: LIB_CAIRO.}
# implementation
proc cairo_version(major, minor, micro: var int32) =
var version: int32
version = cairo_version()
major = version div 10000
minor = (version mod (major * 10000)) div 100
micro = (version mod ((major * 10000) + (minor * 100)))

View File

@@ -0,0 +1,36 @@
#
# Translation of cairo-ft.h
# by Jeffrey Pohlmeyer
# updated to version 1.4 by Luiz Am<41>rico Pereira C<>mara 2007
#
import Cairo, freetypeh
#todo: properly define FcPattern:
#It will require translate FontConfig header
#*
#typedef struct _XftPattern {
# int num;
# int size;
# XftPatternElt *elts;
# } XftPattern;
# typedef FcPattern XftPattern;
#
type
FcPattern* = Pointer
PFcPattern* = ref FcPattern
proc cairo_ft_font_face_create_for_pattern*(pattern: PFcPattern): Pcairo_font_face_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ft_font_options_substitute*(options: Pcairo_font_options_t,
pattern: PFcPattern){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_ft_font_face_create_for_ft_face*(face: TFT_Face,
load_flags: int32): Pcairo_font_face_t {.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ft_scaled_font_lock_face*(
scaled_font: Pcairo_scaled_font_t): TFT_Face{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ft_scaled_font_unlock_face*(
scaled_font: Pcairo_scaled_font_t){.cdecl, importc, dynlib: LIB_CAIRO.}

View File

@@ -0,0 +1,36 @@
#
# Translation of cairo-win32.h version 1.4
# by Luiz Am<41>rico Pereira C<>mara 2007
#
import
Cairo, windows
proc cairo_win32_surface_create*(hdc: HDC): Pcairo_surface_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_win32_surface_create_with_ddb*(hdc: HDC, format: cairo_format_t,
width, height: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_surface_create_with_dib*(format: cairo_format_t,
width, height: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_surface_get_dc*(surface: pcairo_surface_t): HDC{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_win32_surface_get_image*(surface: pcairo_surface_t): Pcairo_surface_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_font_face_create_for_logfontw*(logfont: pLOGFONTW): Pcairo_font_face_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_font_face_create_for_hfont*(font: HFONT): Pcairo_font_face_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_select_font*(scaled_font: pcairo_scaled_font_t,
hdc: HDC): cairo_status_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_done_font*(scaled_font: pcairo_scaled_font_t){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_get_metrics_factor*(
scaled_font: pcairo_scaled_font_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_get_logical_to_device*(
scaled_font: pcairo_scaled_font_t, logical_to_device: pcairo_matrix_t){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_get_device_to_logical*(
scaled_font: pcairo_scaled_font_t, device_to_logical: pcairo_matrix_t){.
cdecl, importc, dynlib: LIB_CAIRO.}
# implementation

View File

@@ -0,0 +1,40 @@
#
# Translation of cairo-xlib.h version 1.4
# by Jeffrey Pohlmeyer
# updated to version 1.4 by Luiz Am<41>rico Pereira C<>mara 2007
#
import
Cairo, x, xlib, xrender
proc cairo_xlib_surface_create*(dpy: PDisplay, drawable: TDrawable,
visual: PVisual, width, height: int32): Pcairo_surface_t{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_create_for_bitmap*(dpy: PDisplay, bitmap: TPixmap,
screen: PScreen, width, height: int32): Pcairo_surface_t{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_create_with_xrender_format*(dpy: PDisplay,
drawable: TDrawable, screen: PScreen, format: PXRenderPictFormat,
width, height: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_depth*(surface: Pcairo_surface_t): int32{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_display*(surface: Pcairo_surface_t): PDisplay{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_drawable*(surface: Pcairo_surface_t): TDrawable{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_height*(surface: Pcairo_surface_t): int32{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_screen*(surface: Pcairo_surface_t): PScreen{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_visual*(surface: Pcairo_surface_t): PVisual{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_width*(surface: Pcairo_surface_t): int32{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_set_size*(surface: Pcairo_surface_t,
width, height: int32){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_set_drawable*(surface: Pcairo_surface_t,
drawable: TDrawable, width, height: int32){.
cdecl, importc, dynlib: LIB_CAIRO.}
# implementation

234
lib/base/dialogs.nim Executable file
View File

@@ -0,0 +1,234 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module implements portable dialogs for Nimrod; the implementation
## builds on the GTK interface. On Windows, native dialogs are shown if
## appropriate.
import
glib2, gtk2
when defined(Windows):
import windows, ShellAPI, os
type
PWindow* = PGtkWindow ## A shortcut for a GTK window.
proc info*(window: PWindow, msg: string) =
## Shows an information message to the user. The process waits until the
## user presses the OK button.
when defined(Windows):
discard MessageBoxA(0, msg, "Information", MB_OK or MB_ICONINFORMATION)
else:
var dialog = GTK_DIALOG(gtk_message_dialog_new(window,
GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", cstring(msg)))
gtk_window_set_title(dialog, "Information")
discard gtk_dialog_run(dialog)
gtk_widget_destroy(dialog)
proc warning*(window: PWindow, msg: string) =
## Shows a warning message to the user. The process waits until the user
## presses the OK button.
when defined(Windows):
discard MessageBoxA(0, msg, "Warning", MB_OK or MB_ICONWARNING)
else:
var dialog = GTK_DIALOG(gtk_message_dialog_new(window,
GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", cstring(msg)))
gtk_window_set_title(dialog, "Warning")
discard gtk_dialog_run(dialog)
gtk_widget_destroy(dialog)
proc error*(window: PWindow, msg: string) =
## Shows an error message to the user. The process waits until the user
## presses the OK button.
when defined(Windows):
discard MessageBoxA(0, msg, "Error", MB_OK or MB_ICONERROR)
else:
var dialog = GTK_DIALOG(gtk_message_dialog_new(window,
GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", cstring(msg)))
gtk_window_set_title(dialog, "Error")
discard gtk_dialog_run(dialog)
gtk_widget_destroy(dialog)
proc ChooseFileToOpen*(window: PWindow, root: string = ""): string =
## Opens a dialog that requests a filename from the user. Returns ""
## if the user closed the dialog without selecting a file. On Windows,
## the native dialog is used, else the GTK dialog is used.
when defined(Windows):
var
opf: TOPENFILENAME
buf: array [0..2047, char]
opf.lStructSize = sizeof(opf)
if root.len > 0:
opf.lpstrInitialDir = root
opf.lpstrFilter = "All Files\0*.*\0\0"
opf.flags = OFN_FILEMUSTEXIST
opf.lpstrFile = buf
opf.nMaxFile = sizeof(buf)
var res = GetOpenFileName(addr(opf))
if res != 0:
result = $buf
else:
result = ""
else:
var
chooser: PGtkDialog
chooser = GTK_DIALOG(gtk_file_chooser_dialog_new("Open File", window,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
if root.len > 0:
discard gtk_file_chooser_set_current_folder(chooser, root)
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
var x = gtk_file_chooser_get_filename(chooser)
result = $x
g_free(x)
else:
result = ""
gtk_widget_destroy(chooser)
proc ChooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] =
## Opens a dialog that requests filenames from the user. Returns []
## if the user closed the dialog without selecting a file. On Windows,
## the native dialog is used, else the GTK dialog is used.
when defined(Windows):
var
opf: TOPENFILENAME
buf: array [0..2047*4, char]
opf.lStructSize = sizeof(opf)
if root.len > 0:
opf.lpstrInitialDir = root
opf.lpstrFilter = "All Files\0*.*\0\0"
opf.flags = OFN_FILEMUSTEXIST or OFN_ALLOWMULTISELECT or OFN_EXPLORER
opf.lpstrFile = buf
opf.nMaxFile = sizeof(buf)
var res = GetOpenFileName(addr(opf))
result = []
if res != 0:
# parsing the result is horrible:
var
i = 0
s: string
path = ""
while buf[i] != '\0':
add(path, buf[i])
inc(i)
inc(i)
if buf[i] != '\0':
while true:
s = ""
while buf[i] != '\0':
add(s, buf[i])
inc(i)
add(result, s)
inc(i)
if buf[i] == '\0': break
for i in 0..result.len-1: result[i] = os.joinPath(path, result[i])
else:
var
chooser: PGtkDialog
chooser = GTK_DIALOG(gtk_file_chooser_dialog_new("Open Files", window,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
if root.len > 0:
discard gtk_file_chooser_set_current_folder(chooser, root)
gtk_file_chooser_set_select_multiple(chooser, true)
result = []
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
var L = gtk_file_chooser_get_filenames(chooser)
var it = L
while it != nil:
add(result, $cast[cstring](it.data))
g_free(it.data)
it = it.next
g_slist_free(L)
gtk_widget_destroy(chooser)
proc ChooseFileToSave*(window: PWindow, root: string = ""): string =
## Opens a dialog that requests a filename to save to from the user.
## Returns "" if the user closed the dialog without selecting a file.
## On Windows, the native dialog is used, else the GTK dialog is used.
when defined(Windows):
var
opf: TOPENFILENAME
buf: array [0..2047, char]
opf.lStructSize = sizeof(opf)
if root.len > 0:
opf.lpstrInitialDir = root
opf.lpstrFilter = "All Files\0*.*\0\0"
opf.flags = OFN_OVERWRITEPROMPT
opf.lpstrFile = buf
opf.nMaxFile = sizeof(buf)
var res = GetSaveFileName(addr(opf))
if res != 0:
result = $buf
else:
result = ""
else:
var
chooser: PGtkDialog
chooser = GTK_DIALOG(gtk_file_chooser_dialog_new("Save File", window,
GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
if root.len > 0:
discard gtk_file_chooser_set_current_folder(chooser, root)
gtk_file_chooser_set_do_overwrite_confirmation(chooser, true)
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
var x = gtk_file_chooser_get_filename(chooser)
result = $x
g_free(x)
else:
result = ""
gtk_widget_destroy(chooser)
proc ChooseDir*(window: PWindow, root: string = ""): string =
## Opens a dialog that requests a directory from the user.
## Returns "" if the user closed the dialog without selecting a directory.
## On Windows, the native dialog is used, else the GTK dialog is used.
when defined(Windows):
var
lpItemID: PItemIDList
BrowseInfo: TBrowseInfo
DisplayName: array [0..MAX_PATH, char]
TempPath: array [0..MAX_PATH, char]
Result = ""
#BrowseInfo.hwndOwner = Application.Handle
BrowseInfo.pszDisplayName = DisplayName
BrowseInfo.ulFlags = 1 #BIF_RETURNONLYFSDIRS
lpItemID = SHBrowseForFolder(cast[LPBrowseInfo](addr(BrowseInfo)))
if lpItemId != nil:
discard SHGetPathFromIDList(lpItemID, TempPath)
Result = $TempPath
discard GlobalFreePtr(lpItemID)
else:
var
chooser: PGtkDialog
chooser = GTK_DIALOG(gtk_file_chooser_dialog_new("Select Directory", window,
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
if root.len > 0:
discard gtk_file_chooser_set_current_folder(chooser, root)
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
var x = gtk_file_chooser_get_filename(chooser)
result = $x
g_free(x)
else:
result = ""
gtk_widget_destroy(chooser)

1368
lib/base/gtk/atk.nim Executable file

File diff suppressed because it is too large Load Diff

3957
lib/base/gtk/gdk2.nim Executable file

File diff suppressed because it is too large Load Diff

279
lib/base/gtk/gdk2pixbuf.nim Executable file
View File

@@ -0,0 +1,279 @@
import
glib2
when defined(win32):
{.define: gdkpixbufwin.}
const
gdkpixbuflib = "libgdk_pixbuf-2.0-0.dll"
elif defined(darwin):
const
gdkpixbuflib = "gdk_pixbuf-2.0.0"
# linklib gtk-x11-2.0
# linklib gdk-x11-2.0
# linklib pango-1.0.0
# linklib glib-2.0.0
# linklib gobject-2.0.0
# linklib gdk_pixbuf-2.0.0
# linklib atk-1.0.0
else:
const
gdkpixbuflib = "libgdk_pixbuf-2.0.so"
{.define: HasGTK2_4.}
{.define: HasGTK2_6.}
type
PGdkPixbuf* = pointer
PGdkPixbufAnimation* = pointer
PGdkPixbufAnimationIter* = pointer
PGdkPixbufAlphaMode* = ptr TGdkPixbufAlphaMode
TGdkPixbufAlphaMode* = enum
GDK_PIXBUF_ALPHA_BILEVEL, GDK_PIXBUF_ALPHA_FULL
PGdkColorspace* = ptr TGdkColorspace
TGdkColorspace* = enum
GDK_COLORSPACE_RGB
TGdkPixbufDestroyNotify* = proc (pixels: Pguchar, data: gpointer){.cdecl.}
PGdkPixbufError* = ptr TGdkPixbufError
TGdkPixbufError* = enum
GDK_PIXBUF_ERROR_CORRUPT_IMAGE, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
GDK_PIXBUF_ERROR_BAD_OPTION, GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION, GDK_PIXBUF_ERROR_FAILED
PGdkInterpType* = ptr TGdkInterpType
TGdkInterpType* = enum
GDK_INTERP_NEAREST, GDK_INTERP_TILES, GDK_INTERP_BILINEAR, GDK_INTERP_HYPER
proc GDK_TYPE_PIXBUF*(): GType
proc GDK_PIXBUF*(anObject: pointer): PGdkPixbuf
proc GDK_IS_PIXBUF*(anObject: pointer): bool
proc GDK_TYPE_PIXBUF_ANIMATION*(): GType
proc GDK_PIXBUF_ANIMATION*(anObject: pointer): PGdkPixbufAnimation
proc GDK_IS_PIXBUF_ANIMATION*(anObject: pointer): bool
proc GDK_TYPE_PIXBUF_ANIMATION_ITER*(): GType
proc GDK_PIXBUF_ANIMATION_ITER*(anObject: pointer): PGdkPixbufAnimationIter
proc GDK_IS_PIXBUF_ANIMATION_ITER*(anObject: pointer): bool
proc GDK_PIXBUF_ERROR*(): TGQuark
proc gdk_pixbuf_error_quark*(): TGQuark{.cdecl, dynlib: gdkpixbuflib,
importc: "gdk_pixbuf_error_quark".}
proc gdk_pixbuf_get_type*(): GType{.cdecl, dynlib: gdkpixbuflib,
importc: "gdk_pixbuf_get_type".}
when not defined(GDK_PIXBUF_DISABLE_DEPRECATED):
proc gdk_pixbuf_ref(pixbuf: PGdkPixbuf): PGdkPixbuf{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_ref".}
proc gdk_pixbuf_unref(pixbuf: PGdkPixbuf){.cdecl, dynlib: gdkpixbuflib,
importc: "gdk_pixbuf_unref".}
proc gdk_pixbuf_get_colorspace*(pixbuf: PGdkPixbuf): TGdkColorspace{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_colorspace".}
proc gdk_pixbuf_get_n_channels*(pixbuf: PGdkPixbuf): int32{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_n_channels".}
proc gdk_pixbuf_get_has_alpha*(pixbuf: PGdkPixbuf): gboolean{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_has_alpha".}
proc gdk_pixbuf_get_bits_per_sample*(pixbuf: PGdkPixbuf): int32{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_bits_per_sample".}
proc gdk_pixbuf_get_pixels*(pixbuf: PGdkPixbuf): Pguchar{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_pixels".}
proc gdk_pixbuf_get_width*(pixbuf: PGdkPixbuf): int32{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_width".}
proc gdk_pixbuf_get_height*(pixbuf: PGdkPixbuf): int32{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_height".}
proc gdk_pixbuf_get_rowstride*(pixbuf: PGdkPixbuf): int32{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_rowstride".}
proc gdk_pixbuf_new*(colorspace: TGdkColorspace, has_alpha: gboolean,
bits_per_sample: int32, width: int32, height: int32): PGdkPixbuf{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new".}
proc gdk_pixbuf_copy*(pixbuf: PGdkPixbuf): PGdkPixbuf{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_copy".}
proc gdk_pixbuf_new_subpixbuf*(src_pixbuf: PGdkPixbuf, src_x: int32,
src_y: int32, width: int32, height: int32): PGdkPixbuf{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_subpixbuf".}
proc gdk_pixbuf_new_from_file*(filename: cstring, error: pointer): PGdkPixbuf{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_file".}
proc gdk_pixbuf_new_from_data*(data: Pguchar, colorspace: TGdkColorspace,
has_alpha: gboolean, bits_per_sample: int32,
width: int32, height: int32, rowstride: int32,
destroy_fn: TGdkPixbufDestroyNotify,
destroy_fn_data: gpointer): PGdkPixbuf{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_data".}
proc gdk_pixbuf_new_from_xpm_data*(data: PPchar): PGdkPixbuf{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_xpm_data".}
proc gdk_pixbuf_new_from_inline*(data_length: gint, a: var guint8,
copy_pixels: gboolean, error: pointer): PGdkPixbuf{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_inline".}
when defined(HasGTK2_4):
proc gdk_pixbuf_new_from_file_at_size(filename: cstring, width, height: gint,
error: pointer): PGdkPixbuf{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_file_at_size".}
when defined(HasGTK2_6):
proc gdk_pixbuf_new_from_file_at_scale(filename: cstring, width, height: gint,
preserve_aspect_ratio: gboolean, error: pointer): PGdkPixbuf{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_file_at_scale".}
proc gdk_pixbuf_fill*(pixbuf: PGdkPixbuf, pixel: guint32){.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_fill".}
proc gdk_pixbuf_save*(pixbuf: PGdkPixbuf, filename: cstring, `type`: cstring,
error: pointer): gboolean{.cdecl, varargs,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_save".}
proc gdk_pixbuf_savev*(pixbuf: PGdkPixbuf, filename: cstring, `type`: cstring,
option_keys: PPchar, option_values: PPchar,
error: pointer): gboolean{.cdecl, dynlib: gdkpixbuflib,
importc: "gdk_pixbuf_savev".}
proc gdk_pixbuf_add_alpha*(pixbuf: PGdkPixbuf, substitute_color: gboolean,
r: guchar, g: guchar, b: guchar): PGdkPixbuf{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_add_alpha".}
proc gdk_pixbuf_copy_area*(src_pixbuf: PGdkPixbuf, src_x: int32, src_y: int32,
width: int32, height: int32, dest_pixbuf: PGdkPixbuf,
dest_x: int32, dest_y: int32){.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_copy_area".}
proc gdk_pixbuf_saturate_and_pixelate*(src: PGdkPixbuf, dest: PGdkPixbuf,
saturation: gfloat, pixelate: gboolean){.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_saturate_and_pixelate".}
proc gdk_pixbuf_scale*(src: PGdkPixbuf, dest: PGdkPixbuf, dest_x: int32,
dest_y: int32, dest_width: int32, dest_height: int32,
offset_x: float64, offset_y: float64, scale_x: float64,
scale_y: float64, interp_type: TGdkInterpType){.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_scale".}
proc gdk_pixbuf_composite*(src: PGdkPixbuf, dest: PGdkPixbuf, dest_x: int32,
dest_y: int32, dest_width: int32, dest_height: int32,
offset_x: float64, offset_y: float64,
scale_x: float64, scale_y: float64,
interp_type: TGdkInterpType, overall_alpha: int32){.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_composite".}
proc gdk_pixbuf_composite_color*(src: PGdkPixbuf, dest: PGdkPixbuf,
dest_x: int32, dest_y: int32,
dest_width: int32, dest_height: int32,
offset_x: float64, offset_y: float64,
scale_x: float64, scale_y: float64,
interp_type: TGdkInterpType,
overall_alpha: int32, check_x: int32,
check_y: int32, check_size: int32,
color1: guint32, color2: guint32){.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_composite_color".}
proc gdk_pixbuf_scale_simple*(src: PGdkPixbuf, dest_width: int32,
dest_height: int32, interp_type: TGdkInterpType): PGdkPixbuf{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_scale_simple".}
proc gdk_pixbuf_composite_color_simple*(src: PGdkPixbuf, dest_width: int32,
dest_height: int32,
interp_type: TGdkInterpType,
overall_alpha: int32, check_size: int32,
color1: guint32, color2: guint32): PGdkPixbuf{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_composite_color_simple".}
proc gdk_pixbuf_animation_get_type*(): GType{.cdecl, dynlib: gdkpixbuflib,
importc: "gdk_pixbuf_animation_get_type".}
proc gdk_pixbuf_animation_new_from_file*(filename: cstring, error: pointer): PGdkPixbufAnimation{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_new_from_file".}
when not defined(GDK_PIXBUF_DISABLE_DEPRECATED):
proc gdk_pixbuf_animation_ref(animation: PGdkPixbufAnimation): PGdkPixbufAnimation{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_ref".}
proc gdk_pixbuf_animation_unref(animation: PGdkPixbufAnimation){.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_unref".}
proc gdk_pixbuf_animation_get_width*(animation: PGdkPixbufAnimation): int32{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_get_width".}
proc gdk_pixbuf_animation_get_height*(animation: PGdkPixbufAnimation): int32{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_get_height".}
proc gdk_pixbuf_animation_is_static_image*(animation: PGdkPixbufAnimation): gboolean{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_is_static_image".}
proc gdk_pixbuf_animation_get_static_image*(animation: PGdkPixbufAnimation): PGdkPixbuf{.
cdecl, dynlib: gdkpixbuflib,
importc: "gdk_pixbuf_animation_get_static_image".}
proc gdk_pixbuf_animation_get_iter*(animation: PGdkPixbufAnimation,
e: var TGTimeVal): PGdkPixbufAnimationIter{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_get_iter".}
proc gdk_pixbuf_animation_iter_get_type*(): GType{.cdecl, dynlib: gdkpixbuflib,
importc: "gdk_pixbuf_animation_iter_get_type".}
proc gdk_pixbuf_animation_iter_get_delay_time*(iter: PGdkPixbufAnimationIter): int32{.
cdecl, dynlib: gdkpixbuflib,
importc: "gdk_pixbuf_animation_iter_get_delay_time".}
proc gdk_pixbuf_animation_iter_get_pixbuf*(iter: PGdkPixbufAnimationIter): PGdkPixbuf{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_iter_get_pixbuf".}
proc gdk_pixbuf_animation_iter_on_currently_loading_frame*(
iter: PGdkPixbufAnimationIter): gboolean{.cdecl, dynlib: gdkpixbuflib,
importc: "gdk_pixbuf_animation_iter_on_currently_loading_frame".}
proc gdk_pixbuf_animation_iter_advance*(iter: PGdkPixbufAnimationIter,
e: var TGTimeVal): gboolean{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_iter_advance".}
proc gdk_pixbuf_get_option*(pixbuf: PGdkPixbuf, key: cstring): cstring{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_option".}
type
PGdkPixbufLoader* = ptr TGdkPixbufLoader
TGdkPixbufLoader* = record
parent_instance*: TGObject
priv*: gpointer
PGdkPixbufLoaderClass* = ptr TGdkPixbufLoaderClass
TGdkPixbufLoaderClass* = record
parent_class*: TGObjectClass
area_prepared*: proc (loader: PGdkPixbufLoader){.cdecl.}
area_updated*: proc (loader: PGdkPixbufLoader, x: int32, y: int32,
width: int32, height: int32){.cdecl.}
closed*: proc (loader: PGdkPixbufLoader){.cdecl.}
proc GDK_TYPE_PIXBUF_LOADER*(): GType
proc GDK_PIXBUF_LOADER*(obj: pointer): PGdkPixbufLoader
proc GDK_PIXBUF_LOADER_CLASS*(klass: pointer): PGdkPixbufLoaderClass
proc GDK_IS_PIXBUF_LOADER*(obj: pointer): bool
proc GDK_IS_PIXBUF_LOADER_CLASS*(klass: pointer): bool
proc GDK_PIXBUF_LOADER_GET_CLASS*(obj: pointer): PGdkPixbufLoaderClass
proc gdk_pixbuf_loader_get_type*(): GType{.cdecl, dynlib: gdkpixbuflib,
importc: "gdk_pixbuf_loader_get_type".}
proc gdk_pixbuf_loader_new*(): PGdkPixbufLoader{.cdecl, dynlib: gdkpixbuflib,
importc: "gdk_pixbuf_loader_new".}
proc gdk_pixbuf_loader_new_with_type*(image_type: cstring, error: pointer): PGdkPixbufLoader{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_loader_new_with_type".}
proc gdk_pixbuf_loader_write*(loader: PGdkPixbufLoader, buf: Pguchar,
count: gsize, error: pointer): gboolean{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_loader_write".}
proc gdk_pixbuf_loader_get_pixbuf*(loader: PGdkPixbufLoader): PGdkPixbuf{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_loader_get_pixbuf".}
proc gdk_pixbuf_loader_get_animation*(loader: PGdkPixbufLoader): PGdkPixbufAnimation{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_loader_get_animation".}
proc gdk_pixbuf_loader_close*(loader: PGdkPixbufLoader, error: pointer): gboolean{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_loader_close".}
proc GDK_TYPE_PIXBUF_LOADER*(): GType =
result = gdk_pixbuf_loader_get_type()
proc GDK_PIXBUF_LOADER*(obj: pointer): PGdkPixbufLoader =
result = cast[PGdkPixbufLoader](G_TYPE_CHECK_INSTANCE_CAST(obj,
GDK_TYPE_PIXBUF_LOADER()))
proc GDK_PIXBUF_LOADER_CLASS*(klass: pointer): PGdkPixbufLoaderClass =
result = cast[PGdkPixbufLoaderClass](G_TYPE_CHECK_CLASS_CAST(klass,
GDK_TYPE_PIXBUF_LOADER()))
proc GDK_IS_PIXBUF_LOADER*(obj: pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(obj, GDK_TYPE_PIXBUF_LOADER())
proc GDK_IS_PIXBUF_LOADER_CLASS*(klass: pointer): bool =
result = G_TYPE_CHECK_CLASS_TYPE(klass, GDK_TYPE_PIXBUF_LOADER())
proc GDK_PIXBUF_LOADER_GET_CLASS*(obj: pointer): PGdkPixbufLoaderClass =
result = cast[PGdkPixbufLoaderClass](G_TYPE_INSTANCE_GET_CLASS(obj,
GDK_TYPE_PIXBUF_LOADER()))
proc GDK_TYPE_PIXBUF*(): GType =
result = gdk_pixbuf_get_type()
proc GDK_PIXBUF*(anObject: pointer): PGdkPixbuf =
result = cast[PGdkPixbuf](G_TYPE_CHECK_INSTANCE_CAST(anObject, GDK_TYPE_PIXBUF()))
proc GDK_IS_PIXBUF*(anObject: pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_PIXBUF())
proc GDK_TYPE_PIXBUF_ANIMATION*(): GType =
result = gdk_pixbuf_animation_get_type()
proc GDK_PIXBUF_ANIMATION*(anObject: pointer): PGdkPixbufAnimation =
result = cast[PGdkPixbufAnimation](G_TYPE_CHECK_INSTANCE_CAST(anObject,
GDK_TYPE_PIXBUF_ANIMATION()))
proc GDK_IS_PIXBUF_ANIMATION*(anObject: pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_PIXBUF_ANIMATION())
proc GDK_TYPE_PIXBUF_ANIMATION_ITER*(): GType =
result = gdk_pixbuf_animation_iter_get_type()
proc GDK_PIXBUF_ANIMATION_ITER*(anObject: pointer): PGdkPixbufAnimationIter =
result = cast[PGdkPixbufAnimationIter](G_TYPE_CHECK_INSTANCE_CAST(anObject,
GDK_TYPE_PIXBUF_ANIMATION_ITER()))
proc GDK_IS_PIXBUF_ANIMATION_ITER*(anObject: pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_PIXBUF_ANIMATION_ITER())
proc GDK_PIXBUF_ERROR*(): TGQuark =
result = gdk_pixbuf_error_quark()

562
lib/base/gtk/gdkglext.nim Executable file
View File

@@ -0,0 +1,562 @@
import
Glib2, Gdk2
when defined(WIN32):
const
GdkGLExtLib = "libgdkglext-win32-1.0-0.dll"
else:
const
GdkGLExtLib = "libgdkglext-x11-1.0.so"
type
TGdkGLConfigAttrib* = int32
TGdkGLConfigCaveat* = int32
TGdkGLVisualType* = int32
TGdkGLTransparentType* = int32
TGdkGLDrawableTypeMask* = int32
TGdkGLRenderTypeMask* = int32
TGdkGLBufferMask* = int32
TGdkGLConfigError* = int32
TGdkGLRenderType* = int32
TGdkGLDrawableAttrib* = int32
TGdkGLPbufferAttrib* = int32
TGdkGLEventMask* = int32
TGdkGLEventType* = int32
TGdkGLDrawableType* = int32
TGdkGLProc* = Pointer
PGdkGLConfig* = ptr TGdkGLConfig
PGdkGLContext* = ptr TGdkGLContext
PGdkGLDrawable* = ptr TGdkGLDrawable
PGdkGLPixmap* = ptr TGdkGLPixmap
PGdkGLWindow* = ptr TGdkGLWindow
TGdkGLConfig* = object of TGObject
layer_plane*: gint
n_aux_buffers*: gint
n_sample_buffers*: gint
flag0*: int16
PGdkGLConfigClass* = ptr TGdkGLConfigClass
TGdkGLConfigClass* = object of TGObjectClass
TGdkGLContext* = object of TGObject
PGdkGLContextClass* = ptr TGdkGLContextClass
TGdkGLContextClass* = object of TGObjectClass
TGdkGLDrawable* = object of TGObject
PGdkGLDrawableClass* = ptr TGdkGLDrawableClass
TGdkGLDrawableClass* = object of TGTypeInterface
create_new_context*: proc (gldrawable: PGdkGLDrawable,
share_list: PGdkGLContext, direct: gboolean,
render_type: int32): PGdkGLContext{.cdecl.}
make_context_current*: proc (draw: PGdkGLDrawable, a_read: PGdkGLDrawable,
glcontext: PGdkGLContext): gboolean{.cdecl.}
is_double_buffered*: proc (gldrawable: PGdkGLDrawable): gboolean{.cdecl.}
swap_buffers*: proc (gldrawable: PGdkGLDrawable){.cdecl.}
wait_gl*: proc (gldrawable: PGdkGLDrawable){.cdecl.}
wait_gdk*: proc (gldrawable: PGdkGLDrawable){.cdecl.}
gl_begin*: proc (draw: PGdkGLDrawable, a_read: PGdkGLDrawable,
glcontext: PGdkGLContext): gboolean{.cdecl.}
gl_end*: proc (gldrawable: PGdkGLDrawable){.cdecl.}
get_gl_config*: proc (gldrawable: PGdkGLDrawable): PGdkGLConfig{.cdecl.}
get_size*: proc (gldrawable: PGdkGLDrawable, width, height: PGInt){.cdecl.}
TGdkGLPixmap* = object of TGObject
drawable*: PGdkDrawable
PGdkGLPixmapClass* = ptr TGdkGLPixmapClass
TGdkGLPixmapClass* = object of TGObjectClass
TGdkGLWindow* = object of TGObject
drawable*: PGdkDrawable
PGdkGLWindowClass* = ptr TGdkGLWindowClass
TGdkGLWindowClass* = object of TGObjectClass
const
HEADER_GDKGLEXT_MAJOR_VERSION* = 1
HEADER_GDKGLEXT_MINOR_VERSION* = 0
HEADER_GDKGLEXT_MICRO_VERSION* = 6
HEADER_GDKGLEXT_INTERFACE_AGE* = 4
HEADER_GDKGLEXT_BINARY_AGE* = 6
proc HEADER_GDKGLEXT_CHECK_VERSION*(major, minor, micro: guint): bool
var
gdkglext_major_version*{.importc, dynlib: GdkGLExtLib.}: guint
gdkglext_minor_version*{.importc, dynlib: GdkGLExtLib.}: guint
gdkglext_micro_version*{.importc, dynlib: GdkGLExtLib.}: guint
gdkglext_interface_age*{.importc, dynlib: GdkGLExtLib.}: guint
gdkglext_binary_age*{.importc, dynlib: GdkGLExtLib.}: guint
const
GDK_GL_SUCCESS* = 0
GDK_GL_ATTRIB_LIST_NONE* = 0
GDK_GL_USE_GL* = 1
GDK_GL_BUFFER_SIZE* = 2
GDK_GL_LEVEL* = 3
GDK_GL_RGBA* = 4
GDK_GL_DOUBLEBUFFER* = 5
GDK_GL_STEREO* = 6
GDK_GL_AUX_BUFFERS* = 7
GDK_GL_RED_SIZE* = 8
GDK_GL_GREEN_SIZE* = 9
GDK_GL_BLUE_SIZE* = 10
GDK_GL_ALPHA_SIZE* = 11
GDK_GL_DEPTH_SIZE* = 12
GDK_GL_STENCIL_SIZE* = 13
GDK_GL_ACCUM_RED_SIZE* = 14
GDK_GL_ACCUM_GREEN_SIZE* = 15
GDK_GL_ACCUM_BLUE_SIZE* = 16
GDK_GL_ACCUM_ALPHA_SIZE* = 17
GDK_GL_CONFIG_CAVEAT* = 0x00000020
GDK_GL_X_VISUAL_TYPE* = 0x00000022
GDK_GL_TRANSPARENT_TYPE* = 0x00000023
GDK_GL_TRANSPARENT_INDEX_VALUE* = 0x00000024
GDK_GL_TRANSPARENT_RED_VALUE* = 0x00000025
GDK_GL_TRANSPARENT_GREEN_VALUE* = 0x00000026
GDK_GL_TRANSPARENT_BLUE_VALUE* = 0x00000027
GDK_GL_TRANSPARENT_ALPHA_VALUE* = 0x00000028
GDK_GL_DRAWABLE_TYPE* = 0x00008010
GDK_GL_RENDER_TYPE* = 0x00008011
GDK_GL_X_RENDERABLE* = 0x00008012
GDK_GL_FBCONFIG_ID* = 0x00008013
GDK_GL_MAX_PBUFFER_WIDTH* = 0x00008016
GDK_GL_MAX_PBUFFER_HEIGHT* = 0x00008017
GDK_GL_MAX_PBUFFER_PIXELS* = 0x00008018
GDK_GL_VISUAL_ID* = 0x0000800B
GDK_GL_SCREEN* = 0x0000800C
GDK_GL_SAMPLE_BUFFERS* = 100000
GDK_GL_SAMPLES* = 100001
GDK_GL_DONT_CARE* = 0xFFFFFFFF
GDK_GL_NONE* = 0x00008000
GDK_GL_CONFIG_CAVEAT_DONT_CARE* = 0xFFFFFFFF
GDK_GL_CONFIG_CAVEAT_NONE* = 0x00008000
GDK_GL_SLOW_CONFIG* = 0x00008001
GDK_GL_NON_CONFORMANT_CONFIG* = 0x0000800D
GDK_GL_VISUAL_TYPE_DONT_CARE* = 0xFFFFFFFF
GDK_GL_TRUE_COLOR* = 0x00008002
GDK_GL_DIRECT_COLOR* = 0x00008003
GDK_GL_PSEUDO_COLOR* = 0x00008004
GDK_GL_STATIC_COLOR* = 0x00008005
GDK_GL_GRAY_SCALE* = 0x00008006
GDK_GL_STATIC_GRAY* = 0x00008007
GDK_GL_TRANSPARENT_NONE* = 0x00008000
GDK_GL_TRANSPARENT_RGB* = 0x00008008
GDK_GL_TRANSPARENT_INDEX* = 0x00008009
GDK_GL_WINDOW_BIT* = 1 shl 0
GDK_GL_PIXMAP_BIT* = 1 shl 1
GDK_GL_PBUFFER_BIT* = 1 shl 2
GDK_GL_RGBA_BIT* = 1 shl 0
GDK_GL_COLOR_INDEX_BIT* = 1 shl 1
GDK_GL_FRONT_LEFT_BUFFER_BIT* = 1 shl 0
GDK_GL_FRONT_RIGHT_BUFFER_BIT* = 1 shl 1
GDK_GL_BACK_LEFT_BUFFER_BIT* = 1 shl 2
GDK_GL_BACK_RIGHT_BUFFER_BIT* = 1 shl 3
GDK_GL_AUX_BUFFERS_BIT* = 1 shl 4
GDK_GL_DEPTH_BUFFER_BIT* = 1 shl 5
GDK_GL_STENCIL_BUFFER_BIT* = 1 shl 6
GDK_GL_ACCUM_BUFFER_BIT* = 1 shl 7
GDK_GL_BAD_SCREEN* = 1
GDK_GL_BAD_ATTRIBUTE* = 2
GDK_GL_NO_EXTENSION* = 3
GDK_GL_BAD_VISUAL* = 4
GDK_GL_BAD_CONTEXT* = 5
GDK_GL_BAD_VALUE* = 6
GDK_GL_BAD_ENUM* = 7
GDK_GL_RGBA_TYPE* = 0x00008014
GDK_GL_COLOR_INDEX_TYPE* = 0x00008015
GDK_GL_PRESERVED_CONTENTS* = 0x0000801B
GDK_GL_LARGEST_PBUFFER* = 0x0000801C
GDK_GL_WIDTH* = 0x0000801D
GDK_GL_HEIGHT* = 0x0000801E
GDK_GL_EVENT_MASK* = 0x0000801F
GDK_GL_PBUFFER_PRESERVED_CONTENTS* = 0x0000801B
GDK_GL_PBUFFER_LARGEST_PBUFFER* = 0x0000801C
GDK_GL_PBUFFER_HEIGHT* = 0x00008040
GDK_GL_PBUFFER_WIDTH* = 0x00008041
GDK_GL_PBUFFER_CLOBBER_MASK* = 1 shl 27
GDK_GL_DAMAGED* = 0x00008020
GDK_GL_SAVED* = 0x00008021
GDK_GL_WINDOW_VALUE* = 0x00008022
GDK_GL_PBUFFER* = 0x00008023
proc gdk_gl_config_attrib_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_config_attrib_get_type".}
proc GDK_TYPE_GL_CONFIG_ATTRIB*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_config_attrib_get_type".}
proc gdk_gl_config_caveat_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_config_caveat_get_type".}
proc GDK_TYPE_GL_CONFIG_CAVEAT*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_config_caveat_get_type".}
proc gdk_gl_visual_type_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_visual_type_get_type".}
proc GDK_TYPE_GL_VISUAL_TYPE*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_visual_type_get_type".}
proc gdk_gl_transparent_type_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_transparent_type_get_type".}
proc GDK_TYPE_GL_TRANSPARENT_TYPE*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_transparent_type_get_type".}
proc gdk_gl_drawable_type_mask_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_drawable_type_mask_get_type".}
proc GDK_TYPE_GL_DRAWABLE_TYPE_MASK*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_drawable_type_mask_get_type".}
proc gdk_gl_render_type_mask_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_render_type_mask_get_type".}
proc GDK_TYPE_GL_RENDER_TYPE_MASK*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_render_type_mask_get_type".}
proc gdk_gl_buffer_mask_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_buffer_mask_get_type".}
proc GDK_TYPE_GL_BUFFER_MASK*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_buffer_mask_get_type".}
proc gdk_gl_config_error_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_config_error_get_type".}
proc GDK_TYPE_GL_CONFIG_ERROR*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_config_error_get_type".}
proc gdk_gl_render_type_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_render_type_get_type".}
proc GDK_TYPE_GL_RENDER_TYPE*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_render_type_get_type".}
proc gdk_gl_drawable_attrib_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_drawable_attrib_get_type".}
proc GDK_TYPE_GL_DRAWABLE_ATTRIB*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_drawable_attrib_get_type".}
proc gdk_gl_pbuffer_attrib_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_pbuffer_attrib_get_type".}
proc GDK_TYPE_GL_PBUFFER_ATTRIB*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_pbuffer_attrib_get_type".}
proc gdk_gl_event_mask_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_event_mask_get_type".}
proc GDK_TYPE_GL_EVENT_MASK*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_event_mask_get_type".}
proc gdk_gl_event_type_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_event_type_get_type".}
proc GDK_TYPE_GL_EVENT_TYPE*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_event_type_get_type".}
proc gdk_gl_drawable_type_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_drawable_type_get_type".}
proc GDK_TYPE_GL_DRAWABLE_TYPE*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_drawable_type_get_type".}
proc gdk_gl_config_mode_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_config_mode_get_type".}
proc GDK_TYPE_GL_CONFIG_MODE*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_config_mode_get_type".}
proc gdk_gl_parse_args*(argc: var int32, argv: ptr cstringArray): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_parse_args".}
proc gdk_gl_init_check*(argc: var int32, argv: ptr cstringArray): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_init_check".}
proc gdk_gl_init*(argc: var int32, argv: ptr cstringArray){.
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_init".}
proc gdk_gl_query_gl_extension*(extension: cstring): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_query_gl_extension".}
proc gdk_gl_get_proc_address*(proc_name: cstring): TGdkGLProc{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_get_proc_address".}
const
bm_TGdkGLConfig_is_rgba* = 1 shl 0
bp_TGdkGLConfig_is_rgba* = 0
bm_TGdkGLConfig_is_double_buffered* = 1 shl 1
bp_TGdkGLConfig_is_double_buffered* = 1
bm_TGdkGLConfig_as_single_mode* = 1 shl 2
bp_TGdkGLConfig_as_single_mode* = 2
bm_TGdkGLConfig_is_stereo* = 1 shl 3
bp_TGdkGLConfig_is_stereo* = 3
bm_TGdkGLConfig_has_alpha* = 1 shl 4
bp_TGdkGLConfig_has_alpha* = 4
bm_TGdkGLConfig_has_depth_buffer* = 1 shl 5
bp_TGdkGLConfig_has_depth_buffer* = 5
bm_TGdkGLConfig_has_stencil_buffer* = 1 shl 6
bp_TGdkGLConfig_has_stencil_buffer* = 6
bm_TGdkGLConfig_has_accum_buffer* = 1 shl 7
bp_TGdkGLConfig_has_accum_buffer* = 7
const
GDK_GL_MODE_RGB* = 0
GDK_GL_MODE_RGBA* = 0
GDK_GL_MODE_INDEX* = 1 shl 0
GDK_GL_MODE_SINGLE* = 0
GDK_GL_MODE_DOUBLE* = 1 shl 1
GDK_GL_MODE_STEREO* = 1 shl 2
GDK_GL_MODE_ALPHA* = 1 shl 3
GDK_GL_MODE_DEPTH* = 1 shl 4
GDK_GL_MODE_STENCIL* = 1 shl 5
GDK_GL_MODE_ACCUM* = 1 shl 6
GDK_GL_MODE_MULTISAMPLE* = 1 shl 7
type
TGdkGLConfigMode* = int32
PGdkGLConfigMode* = ptr TGdkGLConfigMode
proc GDK_TYPE_GL_CONFIG*(): GType
proc GDK_GL_CONFIG*(anObject: Pointer): PGdkGLConfig
proc GDK_GL_CONFIG_CLASS*(klass: Pointer): PGdkGLConfigClass
proc GDK_IS_GL_CONFIG*(anObject: Pointer): bool
proc GDK_IS_GL_CONFIG_CLASS*(klass: Pointer): bool
proc GDK_GL_CONFIG_GET_CLASS*(obj: Pointer): PGdkGLConfigClass
proc gdk_gl_config_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_config_get_type".}
proc gdk_gl_config_get_screen*(glconfig: PGdkGLConfig): PGdkScreen{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_screen".}
proc gdk_gl_config_get_attrib*(glconfig: PGdkGLConfig, attribute: int,
value: var cint): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_attrib".}
proc gdk_gl_config_get_colormap*(glconfig: PGdkGLConfig): PGdkColormap{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_colormap".}
proc gdk_gl_config_get_visual*(glconfig: PGdkGLConfig): PGdkVisual{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_visual".}
proc gdk_gl_config_get_depth*(glconfig: PGdkGLConfig): gint{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_depth".}
proc gdk_gl_config_get_layer_plane*(glconfig: PGdkGLConfig): gint{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_layer_plane".}
proc gdk_gl_config_get_n_aux_buffers*(glconfig: PGdkGLConfig): gint{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_n_aux_buffers".}
proc gdk_gl_config_get_n_sample_buffers*(glconfig: PGdkGLConfig): gint{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_n_sample_buffers".}
proc gdk_gl_config_is_rgba*(glconfig: PGdkGLConfig): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_is_rgba".}
proc gdk_gl_config_is_double_buffered*(glconfig: PGdkGLConfig): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_is_double_buffered".}
proc gdk_gl_config_is_stereo*(glconfig: PGdkGLConfig): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_is_stereo".}
proc gdk_gl_config_has_alpha*(glconfig: PGdkGLConfig): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_has_alpha".}
proc gdk_gl_config_has_depth_buffer*(glconfig: PGdkGLConfig): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_has_depth_buffer".}
proc gdk_gl_config_has_stencil_buffer*(glconfig: PGdkGLConfig): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_has_stencil_buffer".}
proc gdk_gl_config_has_accum_buffer*(glconfig: PGdkGLConfig): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_config_has_accum_buffer".}
proc GDK_TYPE_GL_CONTEXT*(): GType
proc GDK_GL_CONTEXT*(anObject: Pointer): PGdkGLContext
proc GDK_GL_CONTEXT_CLASS*(klass: Pointer): PGdkGLContextClass
proc GDK_IS_GL_CONTEXT*(anObject: Pointer): bool
proc GDK_IS_GL_CONTEXT_CLASS*(klass: Pointer): bool
proc GDK_GL_CONTEXT_GET_CLASS*(obj: Pointer): PGdkGLContextClass
proc gdk_gl_context_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_context_get_type".}
proc gdk_gl_context_new*(gldrawable: PGdkGLDrawable, share_list: PGdkGLContext,
direct: gboolean, render_type: int32): PGdkGLContext{.
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_context_new".}
proc gdk_gl_context_destroy*(glcontext: PGdkGLContext){.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_context_destroy".}
proc gdk_gl_context_copy*(glcontext: PGdkGLContext, src: PGdkGLContext,
mask: int32): gboolean{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_context_copy".}
proc gdk_gl_context_get_gl_drawable*(glcontext: PGdkGLContext): PGdkGLDrawable{.
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_context_get_gl_drawable".}
proc gdk_gl_context_get_gl_config*(glcontext: PGdkGLContext): PGdkGLConfig{.
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_context_get_gl_config".}
proc gdk_gl_context_get_share_list*(glcontext: PGdkGLContext): PGdkGLContext{.
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_context_get_share_list".}
proc gdk_gl_context_is_direct*(glcontext: PGdkGLContext): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_context_is_direct".}
proc gdk_gl_context_get_render_type*(glcontext: PGdkGLContext): int32{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_context_get_render_type".}
proc gdk_gl_context_get_current*(): PGdkGLContext{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_context_get_current".}
proc GDK_TYPE_GL_DRAWABLE*(): GType
proc GDK_GL_DRAWABLE*(inst: Pointer): PGdkGLDrawable
proc GDK_GL_DRAWABLE_CLASS*(vtable: Pointer): PGdkGLDrawableClass
proc GDK_IS_GL_DRAWABLE*(inst: Pointer): bool
proc GDK_IS_GL_DRAWABLE_CLASS*(vtable: Pointer): bool
proc GDK_GL_DRAWABLE_GET_CLASS*(inst: Pointer): PGdkGLDrawableClass
proc gdk_gl_drawable_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_drawable_get_type".}
proc gdk_gl_drawable_make_current*(gldrawable: PGdkGLDrawable,
glcontext: PGdkGLContext): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_make_current".}
proc gdk_gl_drawable_is_double_buffered*(gldrawable: PGdkGLDrawable): gboolean{.
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_is_double_buffered".}
proc gdk_gl_drawable_swap_buffers*(gldrawable: PGdkGLDrawable){.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_swap_buffers".}
proc gdk_gl_drawable_wait_gl*(gldrawable: PGdkGLDrawable){.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_wait_gl".}
proc gdk_gl_drawable_wait_gdk*(gldrawable: PGdkGLDrawable){.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_wait_gdk".}
proc gdk_gl_drawable_gl_begin*(gldrawable: PGdkGLDrawable,
glcontext: PGdkGLContext): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_gl_begin".}
proc gdk_gl_drawable_gl_end*(gldrawable: PGdkGLDrawable){.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_gl_end".}
proc gdk_gl_drawable_get_gl_config*(gldrawable: PGdkGLDrawable): PGdkGLConfig{.
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_get_gl_config".}
proc gdk_gl_drawable_get_size*(gldrawable: PGdkGLDrawable, width, height: PGInt){.
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_get_size".}
proc gdk_gl_drawable_get_current*(): PGdkGLDrawable{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_drawable_get_current".}
proc GDK_TYPE_GL_PIXMAP*(): GType
proc GDK_GL_PIXMAP*(anObject: Pointer): PGdkGLPixmap
proc GDK_GL_PIXMAP_CLASS*(klass: Pointer): PGdkGLPixmapClass
proc GDK_IS_GL_PIXMAP*(anObject: Pointer): bool
proc GDK_IS_GL_PIXMAP_CLASS*(klass: Pointer): bool
proc GDK_GL_PIXMAP_GET_CLASS*(obj: Pointer): PGdkGLPixmapClass
proc gdk_gl_pixmap_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_pixmap_get_type".}
proc gdk_gl_pixmap_new*(glconfig: PGdkGLConfig, pixmap: PGdkPixmap,
attrib_list: ptr int32): PGdkGLPixmap{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_pixmap_new".}
proc gdk_gl_pixmap_destroy*(glpixmap: PGdkGLPixmap){.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_pixmap_destroy".}
proc gdk_gl_pixmap_get_pixmap*(glpixmap: PGdkGLPixmap): PGdkPixmap{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_pixmap_get_pixmap".}
proc gdk_pixmap_set_gl_capability*(pixmap: PGdkPixmap, glconfig: PGdkGLConfig,
attrib_list: ptr int32): PGdkGLPixmap{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_pixmap_set_gl_capability".}
proc gdk_pixmap_unset_gl_capability*(pixmap: PGdkPixmap){.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_pixmap_unset_gl_capability".}
proc gdk_pixmap_is_gl_capable*(pixmap: PGdkPixmap): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_pixmap_is_gl_capable".}
proc gdk_pixmap_get_gl_pixmap*(pixmap: PGdkPixmap): PGdkGLPixmap{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_pixmap_get_gl_pixmap".}
proc gdk_pixmap_get_gl_drawable*(pixmap: PGdkPixmap): PGdkGLDrawable
proc GDK_TYPE_GL_WINDOW*(): GType
proc GDK_GL_WINDOW*(anObject: Pointer): PGdkGLWindow
proc GDK_GL_WINDOW_CLASS*(klass: Pointer): PGdkGLWindowClass
proc GDK_IS_GL_WINDOW*(anObject: Pointer): bool
proc GDK_IS_GL_WINDOW_CLASS*(klass: Pointer): bool
proc GDK_GL_WINDOW_GET_CLASS*(obj: Pointer): PGdkGLWindowClass
proc gdk_gl_window_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_window_get_type".}
proc gdk_gl_window_new*(glconfig: PGdkGLConfig, window: PGdkWindow,
attrib_list: ptr int32): PGdkGLWindow{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_window_new".}
proc gdk_gl_window_destroy*(glwindow: PGdkGLWindow){.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_window_destroy".}
proc gdk_gl_window_get_window*(glwindow: PGdkGLWindow): PGdkWindow{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_window_get_window".}
proc gdk_window_set_gl_capability*(window: PGdkWindow, glconfig: PGdkGLConfig,
attrib_list: ptr int32): PGdkGLWindow{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_window_set_gl_capability".}
proc gdk_window_unset_gl_capability*(window: PGdkWindow){.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_window_unset_gl_capability".}
proc gdk_window_is_gl_capable*(window: PGdkWindow): gboolean{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_window_is_gl_capable".}
proc gdk_window_get_gl_window*(window: PGdkWindow): PGdkGLWindow{.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_window_get_gl_window".}
proc gdk_window_get_gl_drawable*(window: PGdkWindow): PGdkGLDrawable
proc gdk_gl_draw_cube*(solid: gboolean, size: float64){.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_draw_cube".}
proc gdk_gl_draw_sphere*(solid: gboolean, radius: float64, slices: int32,
stacks: int32){.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_draw_sphere".}
proc gdk_gl_draw_cone*(solid: gboolean, base: float64, height: float64,
slices: int32, stacks: int32){.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_draw_cone".}
proc gdk_gl_draw_torus*(solid: gboolean, inner_radius: float64,
outer_radius: float64, nsides: int32, rings: int32){.
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_draw_torus".}
proc gdk_gl_draw_tetrahedron*(solid: gboolean){.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_draw_tetrahedron".}
proc gdk_gl_draw_octahedron*(solid: gboolean){.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_draw_octahedron".}
proc gdk_gl_draw_dodecahedron*(solid: gboolean){.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_draw_dodecahedron".}
proc gdk_gl_draw_icosahedron*(solid: gboolean){.cdecl, dynlib: GdkGLExtLib,
importc: "gdk_gl_draw_icosahedron".}
proc gdk_gl_draw_teapot*(solid: gboolean, scale: float64){.cdecl,
dynlib: GdkGLExtLib, importc: "gdk_gl_draw_teapot".}
proc HEADER_GDKGLEXT_CHECK_VERSION*(major, minor, micro: guint): bool =
result = (HEADER_GDKGLEXT_MAJOR_VERSION > major) or
((HEADER_GDKGLEXT_MAJOR_VERSION == major) and
(HEADER_GDKGLEXT_MINOR_VERSION > minor)) or
((HEADER_GDKGLEXT_MAJOR_VERSION == major) and
(HEADER_GDKGLEXT_MINOR_VERSION == minor) and
(HEADER_GDKGLEXT_MICRO_VERSION >= micro))
proc GDK_TYPE_GL_CONFIG*(): GType =
result = gdk_gl_config_get_type()
proc GDK_GL_CONFIG*(anObject: Pointer): PGdkGLConfig =
result = cast[PGdkGLConfig](G_TYPE_CHECK_INSTANCE_CAST(anObject, GDK_TYPE_GL_CONFIG()))
proc GDK_GL_CONFIG_CLASS*(klass: Pointer): PGdkGLConfigClass =
result = cast[PGdkGLConfigClass](G_TYPE_CHECK_CLASS_CAST(klass, GDK_TYPE_GL_CONFIG()))
proc GDK_IS_GL_CONFIG*(anObject: Pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_GL_CONFIG())
proc GDK_IS_GL_CONFIG_CLASS*(klass: Pointer): bool =
result = G_TYPE_CHECK_CLASS_TYPE(klass, GDK_TYPE_GL_CONFIG())
proc GDK_GL_CONFIG_GET_CLASS*(obj: Pointer): PGdkGLConfigClass =
result = cast[PGdkGLConfigClass](G_TYPE_INSTANCE_GET_CLASS(obj, GDK_TYPE_GL_CONFIG()))
proc GDK_TYPE_GL_CONTEXT*(): GType =
result = gdk_gl_context_get_type()
proc GDK_GL_CONTEXT*(anObject: Pointer): PGdkGLContext =
result = cast[PGdkGLContext](G_TYPE_CHECK_INSTANCE_CAST(anObject,
GDK_TYPE_GL_CONTEXT()))
proc GDK_GL_CONTEXT_CLASS*(klass: Pointer): PGdkGLContextClass =
result = cast[PGdkGLContextClass](G_TYPE_CHECK_CLASS_CAST(klass, GDK_TYPE_GL_CONTEXT()))
proc GDK_IS_GL_CONTEXT*(anObject: Pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_GL_CONTEXT())
proc GDK_IS_GL_CONTEXT_CLASS*(klass: Pointer): bool =
result = G_TYPE_CHECK_CLASS_TYPE(klass, GDK_TYPE_GL_CONTEXT())
proc GDK_GL_CONTEXT_GET_CLASS*(obj: Pointer): PGdkGLContextClass =
result = cast[PGdkGLContextClass](G_TYPE_INSTANCE_GET_CLASS(obj, GDK_TYPE_GL_CONTEXT()))
proc GDK_TYPE_GL_DRAWABLE*(): GType =
result = gdk_gl_drawable_get_type()
proc GDK_GL_DRAWABLE*(inst: Pointer): PGdkGLDrawable =
result = cast[PGdkGLDrawable](G_TYPE_CHECK_INSTANCE_CAST(inst, GDK_TYPE_GL_DRAWABLE()))
proc GDK_GL_DRAWABLE_CLASS*(vtable: Pointer): PGdkGLDrawableClass =
result = cast[PGdkGLDrawableClass](G_TYPE_CHECK_CLASS_CAST(vtable,
GDK_TYPE_GL_DRAWABLE()))
proc GDK_IS_GL_DRAWABLE*(inst: Pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(inst, GDK_TYPE_GL_DRAWABLE())
proc GDK_IS_GL_DRAWABLE_CLASS*(vtable: Pointer): bool =
result = G_TYPE_CHECK_CLASS_TYPE(vtable, GDK_TYPE_GL_DRAWABLE())
proc GDK_GL_DRAWABLE_GET_CLASS*(inst: Pointer): PGdkGLDrawableClass =
result = cast[PGdkGLDrawableClass](G_TYPE_INSTANCE_GET_INTERFACE(inst,
GDK_TYPE_GL_DRAWABLE()))
proc GDK_TYPE_GL_PIXMAP*(): GType =
result = gdk_gl_pixmap_get_type()
proc GDK_GL_PIXMAP*(anObject: Pointer): PGdkGLPixmap =
result = cast[PGdkGLPixmap](G_TYPE_CHECK_INSTANCE_CAST(anObject, GDK_TYPE_GL_PIXMAP()))
proc GDK_GL_PIXMAP_CLASS*(klass: Pointer): PGdkGLPixmapClass =
result = cast[PGdkGLPixmapClass](G_TYPE_CHECK_CLASS_CAST(klass, GDK_TYPE_GL_PIXMAP()))
proc GDK_IS_GL_PIXMAP*(anObject: Pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_GL_PIXMAP())
proc GDK_IS_GL_PIXMAP_CLASS*(klass: Pointer): bool =
result = G_TYPE_CHECK_CLASS_TYPE(klass, GDK_TYPE_GL_PIXMAP())
proc GDK_GL_PIXMAP_GET_CLASS*(obj: Pointer): PGdkGLPixmapClass =
result = cast[PGdkGLPixmapClass](G_TYPE_INSTANCE_GET_CLASS(obj, GDK_TYPE_GL_PIXMAP()))
proc gdk_pixmap_get_gl_drawable*(pixmap: PGdkPixmap): PGdkGLDrawable =
result = GDK_GL_DRAWABLE(gdk_pixmap_get_gl_pixmap(pixmap))
proc GDK_TYPE_GL_WINDOW*(): GType =
result = gdk_gl_window_get_type()
proc GDK_GL_WINDOW*(anObject: Pointer): PGdkGLWindow =
result = cast[PGdkGLWindow](G_TYPE_CHECK_INSTANCE_CAST(anObject, GDK_TYPE_GL_WINDOW()))
proc GDK_GL_WINDOW_CLASS*(klass: Pointer): PGdkGLWindowClass =
result = cast[PGdkGLWindowClass](G_TYPE_CHECK_CLASS_CAST(klass, GDK_TYPE_GL_WINDOW()))
proc GDK_IS_GL_WINDOW*(anObject: Pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_GL_WINDOW())
proc GDK_IS_GL_WINDOW_CLASS*(klass: Pointer): bool =
result = G_TYPE_CHECK_CLASS_TYPE(klass, GDK_TYPE_GL_WINDOW())
proc GDK_GL_WINDOW_GET_CLASS*(obj: Pointer): PGdkGLWindowClass =
result = cast[PGdkGLWindowClass](G_TYPE_INSTANCE_GET_CLASS(obj, GDK_TYPE_GL_WINDOW()))
proc gdk_window_get_gl_drawable*(window: PGdkWindow): PGdkGLDrawable =
result = GDK_GL_DRAWABLE(gdk_window_get_gl_window(window))

4498
lib/base/gtk/glib2.nim Executable file

File diff suppressed because it is too large Load Diff

17226
lib/base/gtk/gtk2.nim Executable file

File diff suppressed because it is too large Load Diff

48
lib/base/gtk/gtkglext.nim Executable file
View File

@@ -0,0 +1,48 @@
import
Glib2, Gdk2, Gtk2, GdkGLExt
const
GtkGLExtLib* = if defined(WIN32): "libgtkglext-win32-1.0-0.dll" else: "libgtkglext-x11-1.0.so"
const
HEADER_GTKGLEXT_MAJOR_VERSION* = 1
HEADER_GTKGLEXT_MINOR_VERSION* = 0
HEADER_GTKGLEXT_MICRO_VERSION* = 6
HEADER_GTKGLEXT_INTERFACE_AGE* = 4
HEADER_GTKGLEXT_BINARY_AGE* = 6
proc gtk_gl_parse_args*(argc: Plongint, argv: PPPChar): gboolean{.cdecl,
dynlib: GtkGLExtLib, importc: "gtk_gl_parse_args".}
proc gtk_gl_init_check*(argc: Plongint, argv: PPPChar): gboolean{.cdecl,
dynlib: GtkGLExtLib, importc: "gtk_gl_init_check".}
proc gtk_gl_init*(argc: Plongint, argv: PPPChar){.cdecl, dynlib: GtkGLExtLib,
importc: "gtk_gl_init".}
proc gtk_widget_set_gl_capability*(widget: PGtkWidget, glconfig: PGdkGLConfig,
share_list: PGdkGLContext, direct: gboolean,
render_type: int): gboolean{.cdecl,
dynlib: GtkGLExtLib, importc: "gtk_widget_set_gl_capability".}
proc gtk_widget_is_gl_capable*(widget: PGtkWidget): gboolean{.cdecl,
dynlib: GtkGLExtLib, importc: "gtk_widget_is_gl_capable".}
proc gtk_widget_get_gl_config*(widget: PGtkWidget): PGdkGLConfig{.cdecl,
dynlib: GtkGLExtLib, importc: "gtk_widget_get_gl_config".}
proc gtk_widget_create_gl_context*(widget: PGtkWidget,
share_list: PGdkGLContext, direct: gboolean,
render_type: int): PGdkGLContext{.cdecl,
dynlib: GtkGLExtLib, importc: "gtk_widget_create_gl_context".}
proc gtk_widget_get_gl_context*(widget: PGtkWidget): PGdkGLContext{.cdecl,
dynlib: GtkGLExtLib, importc: "gtk_widget_get_gl_context".}
proc gtk_widget_get_gl_window*(widget: PGtkWidget): PGdkGLWindow{.cdecl,
dynlib: GtkGLExtLib, importc: "gtk_widget_get_gl_window".}
proc gtk_widget_get_gl_drawable*(widget: PGtkWidget): PGdkGLDrawable =
nil
proc HEADER_GTKGLEXT_CHECK_VERSION*(major, minor, micro: guint): bool =
result = (HEADER_GTKGLEXT_MAJOR_VERSION > major) or
((HEADER_GTKGLEXT_MAJOR_VERSION == major) and
(HEADER_GTKGLEXT_MINOR_VERSION > minor)) or
((HEADER_GTKGLEXT_MAJOR_VERSION == major) and
(HEADER_GTKGLEXT_MINOR_VERSION == minor) and
(HEADER_GTKGLEXT_MICRO_VERSION >= micro))
proc gtk_widget_get_gl_drawable*(widget: PGtkWidget): PGdkGLDrawable =
result = GDK_GL_DRAWABLE(gtk_widget_get_gl_window(widget))

497
lib/base/gtk/gtkhtml.nim Executable file
View File

@@ -0,0 +1,497 @@
import
gtk2, glib2, atk, pango, gdk2pixbuf, gdk2
when defined(windows):
{.define: GTK_WINDOWING_WIN32.}
const
gtkhtmllib = "libgtkhtml-win32-2.0-0.dll"
else:
const
gtkhtmllib = "libgtkhtml-2.so"
const
DOM_UNSPECIFIED_EVENT_TYPE_ERR* = 0
DOM_INDEX_SIZE_ERR* = 1
DOM_DOMSTRING_SIZE_ERR* = 2
DOM_HIERARCHY_REQUEST_ERR* = 3
DOM_WRONG_DOCUMENT_ERR* = 4
DOM_INVALID_CHARACTER_ERR* = 5
DOM_NO_DATA_ALLOWED_ERR* = 6
DOM_NO_MODIFICATION_ALLOWED_ERR* = 7
DOM_NOT_FOUND_ERR* = 8
DOM_NOT_SUPPORTED_ERR* = 9
DOM_INUSE_ATTRIBUTE_ERR* = 10
DOM_INVALID_STATE_ERR* = 11
DOM_SYNTAX_ERR* = 12
DOM_INVALID_MODIFICATION_ERR* = 13
DOM_NAMESPACE_ERR* = 14
DOM_INVALID_ACCESS_ERR* = 15
DOM_NO_EXCEPTION* = 255
DOM_ELEMENT_NODE* = 1
DOM_ATTRIBUTE_NODE* = 2
DOM_TEXT_NODE* = 3
DOM_CDATA_SECTION_NODE* = 4
DOM_ENTITY_REFERENCE_NODE* = 5
DOM_ENTITY_NODE* = 6
DOM_PROCESSING_INSTRUCTION_NODE* = 7
DOM_COMMENT_NODE* = 8
DOM_DOCUMENT_NODE* = 9
DOM_DOCUMENT_TYPE_NODE* = 10
DOM_DOCUMENT_FRAGMENT_NODE* = 11
DOM_NOTATION_NODE* = 12
bm__HtmlFontSpecification_weight* = 0x0000000F
bp__HtmlFontSpecification_weight* = 0
bm__HtmlFontSpecification_style* = 0x00000030
bp__HtmlFontSpecification_style* = 4
bm__HtmlFontSpecification_variant* = 0x000000C0
bp__HtmlFontSpecification_variant* = 6
bm__HtmlFontSpecification_stretch* = 0x00000F00
bp__HtmlFontSpecification_stretch* = 8
bm__HtmlFontSpecification_decoration* = 0x00007000
bp__HtmlFontSpecification_decoration* = 12
type
TDomString* = gchar
TDomBoolean* = gboolean
TDomException* = gushort
TDomTimeStamp* = guint64
PDomNode* = ptr TDomNode
TDomNode* = object of TGObject
xmlnode*: pointer
style*: pointer
PDomNodeClass* = ptr TDomNodeClass
TDomNodeClass* = object of TGObjectClass
`get_nodeName`*: proc (node: PDomNode): PDomString{.cdecl.}
`get_nodeValue`*: proc (node: PDomNode, exc: PDomException): PDomString {.
cdecl.}
`set_nodeValue`*: proc (node: PDomNode, value: PDomString,
exc: PDomException): PDomString{.cdecl.}
PDomDocument* = ptr TDomDocument
TDomDocument* = record
parent*: PDomNode
iterators*: PGSList
PDomDocumentClass* = ptr TDomDocumentClass
TDomDocumentClass* = record
parent_class*: PDomNodeClass
PHtmlFocusIterator* = ptr THtmlFocusIterator
THtmlFocusIterator* = object of TGObject
document*: PDomDocument
current_node*: PDomNode
PHtmlFocusIteratorClass* = ptr THtmlFocusIteratorClass
THtmlFocusIteratorClass* = object of TGObjectClass
THtmlParserType* = enum
HTML_PARSER_TYPE_HTML, HTML_PARSER_TYPE_XML
PHtmlParser* = ptr THtmlParser
THtmlParser* = object of TGObject
parser_type*: THtmlParserType
document*: PHtmlDocument
stream*: PHtmlStream
xmlctxt*: xmlParserCtxtPtr
res*: int32
chars*: array[0..9, char]
blocking*: gboolean
blocking_node*: PDomNode
PHtmlParserClass* = ptr THtmlParserClass
THtmlParserClass* = object of TGtkObjectClass
done_parsing*: proc (parser: PHtmlParser){.cdecl.}
new_node*: proc (parser: PHtmlParser, node: PDomNode)
parsed_document_node*: proc (parser: PHtmlParser, document: PDomDocument)
PHtmlStream* = ptr THtmlStream
THtmlStreamCloseFunc* = proc (stream: PHtmlStream, user_data: gpointer){.cdecl.}
THtmlStreamWriteFunc* = proc (stream: PHtmlStream, buffer: Pgchar,
size: guint, user_data: gpointer){.cdecl.}
THtmlStreamCancelFunc* = proc (stream: PHtmlStream, user_data: gpointer,
cancel_data: gpointer){.cdecl.}
THtmlStream* = object of TGObject
write_func*: THtmlStreamWriteFunc
close_func*: THtmlStreamCloseFunc
cancel_func*: THtmlStreamCancelFunc
user_data*: gpointer
cancel_data*: gpointer
written*: gint
mime_type*: cstring
PHtmlStreamClass* = ptr THtmlStreamClass
THtmlStreamClass* = object of TGObjectClass
THtmlStreamBufferCloseFunc* = proc (str: Pgchar, len: gint,
user_data: gpointer){.cdecl.}
PGtkHtmlContext* = ptr TGtkHtmlContext
TGtkHtmlContext* = object of TGObject
documents*: PGSList
standard_font*: PHtmlFontSpecification
fixed_font*: PHtmlFontSpecification
debug_painting*: gboolean
PGtkHtmlContextClass* = ptr TGtkHtmlContextClass
TGtkHtmlContextClass* = object of TGObjectClass
THtmlDocumentState* = enum
HTML_DOCUMENT_STATE_DONE, HTML_DOCUMENT_STATE_PARSING
PHtmlDocument* = ptr THtmlDocument
THtmlDocument* = object of TGObject
stylesheets*: PGSList
current_stream*: PHtmlStream
state*: THtmlDocumentState
PHtmlDocumentClass* = ptr THtmlDocumentClass
THtmlDocumentClass* = object of TGObjectClass
request_url*: proc (document: PHtmlDocument, url: Pgchar,
stream: PHtmlStream){.cdecl.}
link_clicked*: proc (document: PHtmlDocument, url: Pgchar){.cdecl.}
set_base*: proc (document: PHtmlDocument, url: Pgchar){.cdecl.}
title_changed*: proc (document: PHtmlDocument, new_title: Pgchar){.cdecl.}
submit*: proc (document: PHtmlDocument, `method`: Pgchar, url: Pgchar,
encoding: Pgchar){.cdecl.}
PHtmlView* = ptr THtmlView
THtmlView* = object of TGtkLayout
document*: PHtmlDocument
node_table*: PGHashTable
relayout_idle_id*: guint
relayout_timeout_id*: guint
mouse_down_x*: gint
mouse_down_y*: gint
mouse_detail*: gint
sel_start_ypos*: gint
sel_start_index*: gint
sel_end_ypos*: gint
sel_end_index*: gint
sel_flag*: gboolean
sel_backwards*: gboolean
sel_start_found*: gboolean
sel_list*: PGSList
jump_to_anchor*: pgchar
magnification*: gdouble
magnification_modified*: gboolean
on_url*: gboolean
PHtmlViewClass* = ptr THtmlViewClass
THtmlViewClass* = object of TGtkLayoutClass
move_cursor*: proc (html_view: PHtmlView, step: TGtkMovementStep,
count: gint, extend_selection: gboolean){.cdecl.}
on_url*: proc (html_view: PHtmlView, url: Pgchar)
activate*: proc (html_view: PHtmlView)
move_focus_out*: proc (html_view: PHtmlView, direction: TGtkDirectionType)
proc DOM_TYPE_NODE*(): GType
proc DOM_NODE*(theobject: pointer): PDomNode
proc DOM_NODE_CLASS*(klass: pointer): PDomNodeClass
proc DOM_IS_NODE*(theobject: pointer): bool
proc DOM_IS_NODE_CLASS*(klass: pointer): bool
proc DOM_NODE_GET_CLASS*(obj: pointer): int32
proc dom_node_get_type*(): GType{.cdecl, dynlib: gtkhtmllib,
importc: "dom_node_get_type".}
proc dom_Node_mkref*(node: pointer): PDomNode{.cdecl, dynlib: gtkhtmllib,
importc: "dom_Node_mkref".}
proc dom_Node__get_childNodes*(node: PDomNode): PDomNodeList{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node__get_childNodes".}
proc dom_Node_removeChild*(node: PDomNode, oldChild: PDomNode,
exc: PDomException): PDomNode{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node_removeChild".}
proc dom_Node__get_nodeValue*(node: PDomNode, exc: PDomException): PDomString{.
cdecl, dynlib: gtkhtmllib, importc: "dom_Node__get_nodeValue".}
proc dom_Node__get_firstChild*(node: PDomNode): PDomNode{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node__get_firstChild".}
proc dom_Node__get_nodeName*(node: PDomNode): PDomString{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node__get_nodeName".}
proc dom_Node__get_attributes*(node: PDomNode): PDomNamedNodeMap{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node__get_attributes".}
proc dom_Document__get_doctype*(doc: PDomDocument): PDomDocumentType{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Document__get_doctype".}
proc dom_Node_hasChildNodes*(node: PDomNode): DomBoolean{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node_hasChildNodes".}
proc dom_Node__get_parentNode*(node: PDomNode): PDomNode{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node__get_parentNode".}
proc dom_Node__get_nextSibling*(node: PDomNode): PDomNode{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node__get_nextSibling".}
proc dom_Node__get_nodeType*(node: PDomNode): gushort{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node__get_nodeType".}
proc dom_Node_hasAttributes*(node: PDomNode): DomBoolean{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node_hasAttributes".}
proc dom_Node_cloneNode*(node: PDomNode, deep: DomBoolean): PDomNode{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node_cloneNode".}
proc dom_Node_appendChild*(node: PDomNode, newChild: PDomNode,
exc: PDomException): PDomNode{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node_appendChild".}
proc dom_Node__get_localName*(node: PDomNode): PDomString{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node__get_localName".}
proc dom_Node__get_namespaceURI*(node: PDomNode): PDomString{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node__get_namespaceURI".}
proc dom_Node__get_previousSibling*(node: PDomNode): PDomNode{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node__get_previousSibling".}
proc dom_Node__get_lastChild*(node: PDomNode): PDomNode{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node__get_lastChild".}
proc dom_Node__set_nodeValue*(node: PDomNode, value: PDomString,
exc: PDomException){.cdecl, dynlib: gtkhtmllib,
importc: "dom_Node__set_nodeValue".}
proc dom_Node__get_ownerDocument*(node: PDomNode): PDomDocument{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node__get_ownerDocument".}
proc dom_Node_hasAttributes*(node: PDomNode): gboolean{.cdecl,
dynlib: gtkhtmllib, importc: "dom_Node_hasAttributes".}
proc DOM_TYPE_DOCUMENT*(): GType
proc DOM_DOCUMENT*(theobject: pointer): PDomDocument
proc DOM_DOCUMENT_CLASS*(klass: pointer): PDomDocumentClass
proc DOM_IS_DOCUMENT*(theobject: pointer): bool
proc DOM_IS_DOCUMENT_CLASS*(klass: pointer): bool
proc DOM_DOCUMENT_GET_CLASS*(obj: pointer): PDomDocumentClass
proc dom_document_get_type*(): GType
proc dom_Document__get_documentElement*(doc: PDomDocument): PDomElement
proc dom_Document_createElement*(doc: PDomDocument, tagName: PDomString): PDomElement
proc dom_Document_createTextNode*(doc: PDomDocument, data: PDomString): PDomText
proc dom_Document_createComment*(doc: PDomDocument, data: PDomString): PDomComment
proc dom_Document_importNode*(doc: PDomDocument, importedNode: PDomNode,
deep: DomBoolean, exc: PDomException): PDomNode
proc HTML_TYPE_FOCUS_ITERATOR*(): GType
proc HTML_FOCUS_ITERATOR*(theobject: pointer): PHtmlFocusIterator
proc HTML_FOCUS_ITERATOR_CLASS*(klass: pointer): PHtmlFocusIteratorClass
proc HTML_IS_FOCUS_ITERATOR*(theobject: pointer): bool
proc HTML_IS_FOCUS_ITERATOR_CLASS*(klass: pointer): bool
proc HTML_FOCUS_ITERATOR_GET_CLASS*(obj: pointer): PHtmlFocusIteratorClass
proc html_focus_iterator_next_element*(document: PDomDocument,
element: PDomElement): PDomElement{.
cdecl, dynlib: gtkhtmllib, importc: "html_focus_iterator_next_element".}
proc html_focus_iterator_prev_element*(document: PDomDocument,
element: PDomElement): PDomElement{.
cdecl, dynlib: gtkhtmllib, importc: "html_focus_iterator_prev_element".}
proc HTML_PARSER_TYPE*(): GType
proc HTML_PARSER*(obj: pointer): PHtmlParser
proc HTML_PARSER_CLASS*(klass: pointer): PHtmlParserClass
proc HTML_IS_PARSER*(obj: pointer): bool
proc html_parser_get_type*(): GType
proc html_parser_new*(document: PHtmlDocument, parser_type: THtmlParserType): PHtmlParser
proc HTML_TYPE_STREAM*(): GType
proc HTML_STREAM*(obj: pointer): PHtmlStream
proc HTML_STREAM_CLASS*(klass: pointer): PHtmlStreamClass
proc HTML_IS_STREAM*(obj: pointer): bool
proc HTML_IS_STREAM_CLASS*(klass: pointer): bool
proc HTML_STREAM_GET_CLASS*(obj: pointer): PHtmlStreamClass
proc html_stream_get_type*(): GType{.cdecl, dynlib: gtkhtmllib,
importc: "html_stream_get_type".}
proc html_stream_new*(write_func: THtmlStreamWriteFunc,
close_func: THtmlStreamCloseFunc, user_data: gpointer): PHtmlStream{.
cdecl, dynlib: gtkhtmllib, importc: "html_stream_new".}
proc html_stream_write*(stream: PHtmlStream, buffer: Pgchar, size: guint){.
cdecl, dynlib: gtkhtmllib, importc: "html_stream_write".}
proc html_stream_close*(stream: PHtmlStream){.cdecl, dynlib: gtkhtmllib,
importc: "html_stream_close".}
proc html_stream_destroy*(stream: PHtmlStream){.cdecl, dynlib: gtkhtmllib,
importc: "html_stream_destroy".}
proc html_stream_get_written*(stream: PHtmlStream): gint{.cdecl,
dynlib: gtkhtmllib, importc: "html_stream_get_written".}
proc html_stream_cancel*(stream: PHtmlStream){.cdecl, dynlib: gtkhtmllib,
importc: "html_stream_cancel".}
proc html_stream_set_cancel_func*(stream: PHtmlStream,
abort_func: THtmlStreamCancelFunc,
cancel_data: gpointer){.cdecl,
dynlib: gtkhtmllib, importc: "html_stream_set_cancel_func".}
proc html_stream_get_mime_type*(stream: PHtmlStream): cstring{.cdecl,
dynlib: gtkhtmllib, importc: "html_stream_get_mime_type".}
proc html_stream_set_mime_type*(stream: PHtmlStream, mime_type: cstring){.cdecl,
dynlib: gtkhtmllib, importc: "html_stream_set_mime_type".}
proc html_stream_buffer_new*(close_func: THtmlStreamBufferCloseFunc,
user_data: gpointer): PHtmlStream{.cdecl,
dynlib: gtkhtmllib, importc: "html_stream_buffer_new".}
proc html_event_mouse_move*(view: PHtmlView, event: PGdkEventMotion){.cdecl,
dynlib: gtkhtmllib, importc: "html_event_mouse_move".}
proc html_event_button_press*(view: PHtmlView, button: PGdkEventButton){.cdecl,
dynlib: gtkhtmllib, importc: "html_event_button_press".}
proc html_event_button_release*(view: PHtmlView, event: PGdkEventButton){.cdecl,
dynlib: gtkhtmllib, importc: "html_event_button_release".}
proc html_event_activate*(view: PHtmlView){.cdecl, dynlib: gtkhtmllib,
importc: "html_event_activate".}
proc html_event_key_press*(view: PHtmlView, event: PGdkEventKey): gboolean{.
cdecl, dynlib: gtkhtmllib, importc: "html_event_key_press".}
proc html_event_find_root_box*(self: PHtmlBox, x: gint, y: gint): PHtmlBox{.
cdecl, dynlib: gtkhtmllib, importc: "html_event_find_root_box".}
proc html_selection_start*(view: PHtmlView, event: PGdkEventButton){.cdecl,
dynlib: gtkhtmllib, importc: "html_selection_start".}
proc html_selection_end*(view: PHtmlView, event: PGdkEventButton){.cdecl,
dynlib: gtkhtmllib, importc: "html_selection_end".}
proc html_selection_update*(view: PHtmlView, event: PGdkEventMotion){.cdecl,
dynlib: gtkhtmllib, importc: "html_selection_update".}
proc html_selection_clear*(view: PHtmlView){.cdecl, dynlib: gtkhtmllib,
importc: "html_selection_clear".}
proc html_selection_set*(view: PHtmlView, start: PDomNode, offset: int32,
len: int32){.cdecl, dynlib: gtkhtmllib,
importc: "html_selection_set".}
proc GTK_HTML_CONTEXT_TYPE*(): GType
proc GTK_HTML_CONTEXT*(obj: pointer): PGtkHtmlContext
proc GTK_HTML_CONTEXT_CLASS*(klass: pointer): PGtkHtmlContextClass
proc GTK_HTML_IS_CONTEXT*(obj: pointer): bool
proc GTK_HTML_IS_CONTEXT_CLASS*(klass: pointer): bool
proc gtk_html_context_get_type*(): GType
proc gtk_html_context_get*(): PGtkHtmlContext
proc HTML_TYPE_DOCUMENT*(): GType
proc HTML_DOCUMENT*(obj: pointer): PHtmlDocument
proc HTML_DOCUMENT_CLASS*(klass: pointer): PHtmlDocumentClass
proc HTML_IS_DOCUMENT*(obj: pointer): bool
proc html_document_get_type*(): GType{.cdecl, dynlib: gtkhtmllib,
importc: "html_document_get_type".}
proc html_document_new*(): PHtmlDocument{.cdecl, dynlib: gtkhtmllib,
importc: "html_document_new".}
proc html_document_open_stream*(document: PHtmlDocument, mime_type: Pgchar): gboolean{.
cdecl, dynlib: gtkhtmllib, importc: "html_document_open_stream".}
proc html_document_write_stream*(document: PHtmlDocument, buffer: Pgchar,
len: gint){.cdecl, dynlib: gtkhtmllib,
importc: "html_document_write_stream".}
proc html_document_close_stream*(document: PHtmlDocument){.cdecl,
dynlib: gtkhtmllib, importc: "html_document_close_stream".}
proc html_document_clear*(document: PHtmlDocument){.cdecl, dynlib: gtkhtmllib,
importc: "html_document_clear".}
proc HTML_TYPE_VIEW*(): GType
proc HTML_VIEW*(obj: pointer): PHtmlView
proc HTML_VIEW_CLASS*(klass: pointer): PHtmlViewClass
proc HTML_IS_VIEW*(obj: pointer): bool
proc html_view_get_type*(): GType{.cdecl, dynlib: gtkhtmllib,
importc: "html_view_get_type".}
proc html_view_new*(): PGtkWidget{.cdecl, dynlib: gtkhtmllib,
importc: "html_view_new".}
proc html_view_set_document*(view: PHtmlView, document: PHtmlDocument){.cdecl,
dynlib: gtkhtmllib, importc: "html_view_set_document".}
proc html_view_jump_to_anchor*(view: PHtmlView, anchor: Pgchar){.cdecl,
dynlib: gtkhtmllib, importc: "html_view_jump_to_anchor".}
proc html_view_get_magnification*(view: PHtmlView): gdouble{.cdecl,
dynlib: gtkhtmllib, importc: "html_view_get_magnification".}
proc html_view_set_magnification*(view: PHtmlView, magnification: gdouble){.
cdecl, dynlib: gtkhtmllib, importc: "html_view_set_magnification".}
proc html_view_zoom_in*(view: PHtmlView){.cdecl, dynlib: gtkhtmllib,
importc: "html_view_zoom_in".}
proc html_view_zoom_out*(view: PHtmlView){.cdecl, dynlib: gtkhtmllib,
importc: "html_view_zoom_out".}
proc html_view_zoom_reset*(view: PHtmlView){.cdecl, dynlib: gtkhtmllib,
importc: "html_view_zoom_reset".}
proc DOM_TYPE_NODE*(): GType =
result = dom_node_get_type()
proc DOM_NODE*(theobject: pointer): PDomNode =
result = G_TYPE_CHECK_INSTANCE_CAST(theobject, DOM_TYPE_NODE(), TDomNode)
proc DOM_NODE_CLASS*(klass: pointer): PDomNodeClass =
result = G_TYPE_CHECK_CLASS_CAST(klass, DOM_TYPE_NODE(), TDomNodeClass)
proc DOM_IS_NODE*(theobject: pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(theobject, DOM_TYPE_NODE())
proc DOM_IS_NODE_CLASS*(klass: pointer): bool =
result = G_TYPE_CHECK_CLASS_TYPE(klass, DOM_TYPE_NODE())
proc DOM_NODE_GET_CLASS*(obj: pointer): PDomNodeClass =
result = G_TYPE_INSTANCE_GET_CLASS(obj, DOM_TYPE_NODE(), TDomNodeClass)
proc DOM_TYPE_DOCUMENT*(): GType =
result = dom_document_get_type()
proc DOM_DOCUMENT*(theobject: pointer): PDomDocument =
result = G_TYPE_CHECK_INSTANCE_CAST(theobject, DOM_TYPE_DOCUMENT(), TDomDocument)
proc DOM_DOCUMENT_CLASS*(klass: pointer): PDomDocumentClass =
result = G_TYPE_CHECK_CLASS_CAST(klass, DOM_TYPE_DOCUMENT(), TDomDocumentClass)
proc DOM_IS_DOCUMENT*(theobject: pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(theobject, DOM_TYPE_DOCUMENT())
proc DOM_IS_DOCUMENT_CLASS*(klass: pointer): bool =
result = G_TYPE_CHECK_CLASS_TYPE(klass, DOM_TYPE_DOCUMENT())
proc DOM_DOCUMENT_GET_CLASS*(obj: pointer): PDomDocumentClass =
result = G_TYPE_INSTANCE_GET_CLASS(obj, DOM_TYPE_DOCUMENT(), TDomDocumentClass)
proc HTML_TYPE_FOCUS_ITERATOR*(): GType =
result = html_focus_iterator_get_type()
proc HTML_FOCUS_ITERATOR*(theobject: pointer): PHtmlFocusIterator =
result = G_TYPE_CHECK_INSTANCE_CAST(theobject, HTML_TYPE_FOCUS_ITERATOR(),
HtmlFocusIterator)
proc HTML_FOCUS_ITERATOR_CLASS*(klass: pointer): PHtmlFocusIteratorClass =
result = G_TYPE_CHECK_CLASS_CAST(klass, HTML_TYPE_FOCUS_ITERATOR(),
HtmlFocusIteratorClass)
proc HTML_IS_FOCUS_ITERATOR*(theobject: pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(theobject, HTML_TYPE_FOCUS_ITERATOR())
proc HTML_IS_FOCUS_ITERATOR_CLASS*(klass: pointer): bool =
result = G_TYPE_CHECK_CLASS_TYPE(klass, HTML_TYPE_FOCUS_ITERATOR())
proc HTML_FOCUS_ITERATOR_GET_CLASS*(obj: pointer): PHtmlFocusIteratorClass =
result = G_TYPE_INSTANCE_GET_CLASS(obj, HTML_TYPE_FOCUS_ITERATOR(),
HtmlFocusIteratorClass)
proc HTML_PARSER_TYPE*(): GType =
result = html_parser_get_type()
proc HTML_PARSER*(obj: pointer): PHtmlParser =
result = GTK_CHECK_CAST(obj, HTML_PARSER_TYPE(), THtmlParser)
proc HTML_PARSER_CLASS*(klass: pointer): PHtmlParserClass =
result = GTK_CHECK_CLASS_CAST(klass, HTML_PARSER_TYPE(), THtmlParserClass)
proc HTML_IS_PARSER*(obj: pointer): bool =
result = GTK_CHECK_TYPE(obj, HTML_PARSER_TYPE())
proc HTML_TYPE_STREAM*(): GType =
result = html_stream_get_type()
proc HTML_STREAM*(obj: pointer): PHtmlStream =
result = PHtmlStream(G_TYPE_CHECK_INSTANCE_CAST(obj, HTML_TYPE_STREAM()))
proc HTML_STREAM_CLASS*(klass: pointer): PHtmlStreamClass =
result = G_TYPE_CHECK_CLASS_CAST(klass, HTML_TYPE_STREAM())
proc HTML_IS_STREAM*(obj: pointer): bool =
result = G_TYPE_CHECK_INSTANCE_TYPE(obj, HTML_TYPE_STREAM())
proc HTML_IS_STREAM_CLASS*(klass: pointer): bool =
result = G_TYPE_CHECK_CLASS_TYPE(klass, HTML_TYPE_STREAM())
proc HTML_STREAM_GET_CLASS*(obj: pointer): PHtmlStreamClass =
result = PHtmlStreamClass(G_TYPE_INSTANCE_GET_CLASS(obj, HTML_TYPE_STREAM()))
proc GTK_HTML_CONTEXT_TYPE*(): GType =
result = gtk_html_context_get_type()
proc GTK_HTML_CONTEXT*(obj: pointer): PGtkHtmlContext =
result = GTK_CHECK_CAST(obj, GTK_HTML_CONTEXT_TYPE(), TGtkHtmlContext)
proc GTK_HTML_CONTEXT_CLASS*(klass: pointer): PGtkHtmlContextClass =
result = GTK_CHECK_CLASS_CAST(klass, GTK_HTML_CONTEXT_TYPE(),
TGtkHtmlContextClass)
proc GTK_HTML_IS_CONTEXT*(obj: pointer): bool =
result = GTK_CHECK_TYPE(obj, GTK_HTML_CONTEXT_TYPE())
proc GTK_HTML_IS_CONTEXT_CLASS*(klass: pointer): bool =
result = GTK_CHECK_CLASS_TYPE(klass, GTK_HTML_CONTEXT_TYPE())
proc HTML_TYPE_DOCUMENT*(): GType =
result = html_document_get_type()
proc HTML_DOCUMENT*(obj: pointer): PHtmlDocument =
result = PHtmlDocument(GTK_CHECK_CAST(obj, HTML_TYPE_DOCUMENT()))
proc HTML_DOCUMENT_CLASS*(klass: pointer): PHtmlDocumentClass =
result = GTK_CHECK_CLASS_CAST(klass, HTML_TYPE_DOCUMENT())
proc HTML_IS_DOCUMENT*(obj: pointer): bool =
result = GTK_CHECK_TYPE(obj, HTML_TYPE_DOCUMENT())
proc HTML_TYPE_VIEW*(): GType =
result = html_view_get_type()
proc HTML_VIEW*(obj: pointer): PHtmlView =
result = PHtmlView(GTK_CHECK_CAST(obj, HTML_TYPE_VIEW()))
proc HTML_VIEW_CLASS*(klass: pointer): PHtmlViewClass =
result = PHtmlViewClass(GTK_CHECK_CLASS_CAST(klass, HTML_TYPE_VIEW()))
proc HTML_IS_VIEW*(obj: pointer): bool =
result = GTK_CHECK_TYPE(obj, HTML_TYPE_VIEW())

117
lib/base/gtk/libglade2.nim Executable file
View File

@@ -0,0 +1,117 @@
import
glib2, gtk2
when defined(win32):
{.define: gtkwin.}
const
LibGladeLib = "libglade-2.0-0.dll"
else:
const
LibGladeLib = "libglade-2.0.so"
type
PLongint* = ptr int32
PSmallInt* = ptr int16
PByte* = ptr int8
PWord* = ptr int16
PDWord* = ptr int32
PDouble* = ptr float64
proc glade_init*(){.cdecl, dynlib: LibGladeLib, importc: "glade_init".}
proc glade_require*(TheLibrary: cstring){.cdecl, dynlib: LibGladeLib,
importc: "glade_require".}
proc glade_provide*(TheLibrary: cstring){.cdecl, dynlib: LibGladeLib,
importc: "glade_provide".}
type
PGladeXMLPrivate* = pointer
PGladeXML* = ptr TGladeXML
TGladeXML* = object of TGObject
filename*: cstring
priv*: PGladeXMLPrivate
PGladeXMLClass* = ptr TGladeXMLClass
TGladeXMLClass* = object of TGObjectClass
TGladeXMLConnectFunc* = proc (handler_name: cstring, anObject: PGObject,
signal_name: cstring, signal_data: cstring,
connect_object: PGObject, after: gboolean,
user_data: gpointer){.cdecl.}
proc GLADE_TYPE_XML*(): GType
proc GLADE_XML*(obj: pointer): PGladeXML
proc GLADE_XML_CLASS*(klass: pointer): PGladeXMLClass
proc GLADE_IS_XML*(obj: pointer): gboolean
proc GLADE_IS_XML_CLASS*(klass: pointer): gboolean
proc GLADE_XML_GET_CLASS*(obj: pointer): PGladeXMLClass
proc glade_xml_get_type*(): GType{.cdecl, dynlib: LibGladeLib,
importc: "glade_xml_get_type".}
proc glade_xml_new*(fname: cstring, root: cstring, domain: cstring): PGladeXML{.
cdecl, dynlib: LibGladeLib, importc: "glade_xml_new".}
proc glade_xml_new_from_buffer*(buffer: cstring, size: int32, root: cstring,
domain: cstring): PGladeXML{.cdecl,
dynlib: LibGladeLib, importc: "glade_xml_new_from_buffer".}
proc glade_xml_construct*(self: PGladeXML, fname: cstring, root: cstring,
domain: cstring): gboolean{.cdecl,
dynlib: LibGladeLib, importc: "glade_xml_construct".}
proc glade_xml_signal_connect*(self: PGladeXML, handlername: cstring,
func: TGCallback){.cdecl, dynlib: LibGladeLib,
importc: "glade_xml_signal_connect".}
proc glade_xml_signal_connect_data*(self: PGladeXML, handlername: cstring,
func: TGCallback, user_data: gpointer){.
cdecl, dynlib: LibGladeLib, importc: "glade_xml_signal_connect_data".}
proc glade_xml_signal_autoconnect*(self: PGladeXML){.cdecl, dynlib: LibGladeLib,
importc: "glade_xml_signal_autoconnect".}
proc glade_xml_signal_connect_full*(self: PGladeXML, handler_name: cstring,
func: TGladeXMLConnectFunc,
user_data: gpointer){.cdecl,
dynlib: LibGladeLib, importc: "glade_xml_signal_connect_full".}
proc glade_xml_signal_autoconnect_full*(self: PGladeXML,
func: TGladeXMLConnectFunc,
user_data: gpointer){.cdecl,
dynlib: LibGladeLib, importc: "glade_xml_signal_autoconnect_full".}
proc glade_xml_get_widget*(self: PGladeXML, name: cstring): PGtkWidget{.cdecl,
dynlib: LibGladeLib, importc: "glade_xml_get_widget".}
proc glade_xml_get_widget_prefix*(self: PGladeXML, name: cstring): PGList{.
cdecl, dynlib: LibGladeLib, importc: "glade_xml_get_widget_prefix".}
proc glade_xml_relative_file*(self: PGladeXML, filename: cstring): cstring{.cdecl,
dynlib: LibGladeLib, importc: "glade_xml_relative_file".}
proc glade_get_widget_name*(widget: PGtkWidget): cstring{.cdecl,
dynlib: LibGladeLib, importc: "glade_get_widget_name".}
proc glade_get_widget_tree*(widget: PGtkWidget): PGladeXML{.cdecl,
dynlib: LibGladeLib, importc: "glade_get_widget_tree".}
type
PGladeXMLCustomWidgetHandler* = ptr TGladeXMLCustomWidgetHandler
TGladeXMLCustomWidgetHandler* = TGtkWidget
proc glade_set_custom_handler*(handler: TGladeXMLCustomWidgetHandler,
user_data: gpointer){.cdecl, dynlib: LibGladeLib,
importc: "glade_set_custom_handler".}
proc glade_gnome_init*() =
glade_init()
proc glade_bonobo_init*() =
glade_init()
proc glade_xml_new_with_domain*(fname: cstring, root: cstring, domain: cstring): PGladeXML =
result = glade_xml_new(fname, root, domain)
proc glade_xml_new_from_memory*(buffer: cstring, size: int32, root: cstring,
domain: cstring): PGladeXML =
result = glade_xml_new_from_buffer(buffer, size, root, domain)
proc GLADE_TYPE_XML*(): GType =
result = glade_xml_get_type()
proc GLADE_XML*(obj: pointer): PGladeXML =
result = cast[PGladeXML](G_TYPE_CHECK_INSTANCE_CAST(obj, GLADE_TYPE_XML()))
proc GLADE_XML_CLASS*(klass: pointer): PGladeXMLClass =
result = cast[PGladeXMLClass](G_TYPE_CHECK_CLASS_CAST(klass, GLADE_TYPE_XML()))
proc GLADE_IS_XML*(obj: pointer): gboolean =
result = G_TYPE_CHECK_INSTANCE_TYPE(obj, GLADE_TYPE_XML())
proc GLADE_IS_XML_CLASS*(klass: pointer): gboolean =
result = G_TYPE_CHECK_CLASS_TYPE(klass, GLADE_TYPE_XML())
proc GLADE_XML_GET_CLASS*(obj: pointer): PGladeXMLClass =
result = cast[PGladeXMLClass](G_TYPE_INSTANCE_GET_CLASS(obj, GLADE_TYPE_XML()))

1209
lib/base/gtk/pango.nim Executable file

File diff suppressed because it is too large Load Diff

46
lib/base/gtk/pangoutils.nim Executable file
View File

@@ -0,0 +1,46 @@
import
glib2, pango
type
pint32* = ptr int32
proc pango_split_file_list*(str: cstring): PPchar{.cdecl, dynlib: pangolib,
importc: "pango_split_file_list".}
proc pango_trim_string*(str: cstring): cstring{.cdecl, dynlib: pangolib,
importc: "pango_trim_string".}
proc pango_read_line*(stream: TFile, str: PGString): gint{.cdecl,
dynlib: pangolib, importc: "pango_read_line".}
proc pango_skip_space*(pos: PPchar): gboolean{.cdecl, dynlib: pangolib,
importc: "pango_skip_space".}
proc pango_scan_word*(pos: PPchar, OutStr: PGString): gboolean{.cdecl,
dynlib: pangolib, importc: "pango_scan_word".}
proc pango_scan_string*(pos: PPchar, OutStr: PGString): gboolean{.cdecl,
dynlib: pangolib, importc: "pango_scan_string".}
proc pango_scan_int*(pos: PPchar, OutInt: pint32): gboolean{.cdecl,
dynlib: pangolib, importc: "pango_scan_int".}
when defined(PANGO_ENABLE_BACKEND):
proc pango_config_key_get(key: cstring): cstring{.cdecl, dynlib: pangolib,
importc: "pango_config_key_get".}
proc pango_lookup_aliases(fontname: cstring, families: PPPchar,
n_families: pint32){.cdecl, dynlib: pangolib,
importc: "pango_lookup_aliases".}
proc pango_parse_style*(str: cstring, style: PPangoStyle, warn: gboolean): gboolean{.
cdecl, dynlib: pangolib, importc: "pango_parse_style".}
proc pango_parse_variant*(str: cstring, variant: PPangoVariant, warn: gboolean): gboolean{.
cdecl, dynlib: pangolib, importc: "pango_parse_variant".}
proc pango_parse_weight*(str: cstring, weight: PPangoWeight, warn: gboolean): gboolean{.
cdecl, dynlib: pangolib, importc: "pango_parse_weight".}
proc pango_parse_stretch*(str: cstring, stretch: PPangoStretch, warn: gboolean): gboolean{.
cdecl, dynlib: pangolib, importc: "pango_parse_stretch".}
when defined(PANGO_ENABLE_BACKEND):
proc pango_get_sysconf_subdirectory(): cstring{.cdecl, dynlib: pangolib,
importc: "pango_get_sysconf_subdirectory".}
proc pango_get_lib_subdirectory(): cstring{.cdecl, dynlib: pangolib,
importc: "pango_get_lib_subdirectory".}
proc pango_log2vis_get_embedding_levels*(str: Pgunichar, len: int32,
pbase_dir: PPangoDirection, embedding_level_list: Pguint8): gboolean{.cdecl,
dynlib: pangolib, importc: "pango_log2vis_get_embedding_levels".}
proc pango_get_mirror_char*(ch: gunichar, mirrored_ch: Pgunichar): gboolean{.
cdecl, dynlib: pangolib, importc: "pango_get_mirror_char".}
proc pango_language_get_sample_string*(language: PPangoLanguage): cstring{.
cdecl, dynlib: pangolib, importc: "pango_language_get_sample_string".}

124
lib/base/nregex.nim Executable file
View File

@@ -0,0 +1,124 @@
# new implementation of regular expressions
type
TRegexKind = enum
regNone,
regChar,
regSet,
regConc,
regAlt,
regStar,
regPlus,
regMN,
regNewline
TRegex = record
case kind: TRegexKind
of regChar: c: char
of regSet: s: ref set[char]
else: a, b: PRegEx
PRegEx* = ref TRegEx
TRegExFlag* = enum ## Flags concerning the semantics of regular expressions
reCaseInsensitive, ## case insensitive match
reStyleInsensitive ## style insensitive match
TRegExFlags* = set[TRegExFlag]
## Flags concerning the semantics of regular expressions
proc raiseRegex(msg: string) {.noreturn.} =
var e: ref Exception
new(e)
e.msg = msg
raise e
proc compileAux(i: int, s: string, r: PRegEx): int
proc compileBackslash(i: int, s: string, r: PRegEx): int =
var i = i
inc(i)
case s[i]
of 'A'..'Z':
of 'a'..'z':
of '0':
of '1'..'9':
else:
r.kind = regChar
r.c = s[i]
inc(i)
result = i
proc compileAtom(i: int, s: string, r: PRegEx): int =
var i = i
case s[i]
of '[':
inc(i)
var inverse = s[i] == '^'
if inverse: inc(i)
r.kind = regSet
new(r.s)
while true:
case s[i]
of '\\': i = compileBackslash(i, s, r)
of ']':
inc(i)
break
of '\0':
raiseRegex("']' expected")
elif s[i+1] == '-':
var x = s[i]
inc(i, 2)
var y = s[i]
inc(i)
r.s = r.s + {x..y}
else:
incl(r.s, s[i])
inc(i)
if inverse:
r.s = {'\0'..'\255'} - r.s
of '\\':
inc(i)
i = compileBackslash(i, s, r)
of '.':
r.kind = regAny
inc(i)
of '(':
inc(i)
i = compileAux(i, s, r)
if s[i] = ')': inc(i)
else: raiseRegex("')' expected")
of '\0': nil # do nothing
else:
r.kind = regChar
r.c = s[i]
inc(i)
result = i
proc compilePostfix(i: int, s: string, r: PRegEx): int =
var i = compileAtom(i, s, r)
var a: PRegEx
case s[i]
of '*':
of '+':
of '?':
else: nil
proc compileAux(i: int, s: string, r: PRegEx): int =
var i = i
i = compileAtom(i, s, r)
while s[i] != '\0':
result = i
proc compile*(regex: string, flags: TRegExFlags = {}): PRegEx =
## Compiles the string `regex` that represents a regular expression into
## an internal data structure that can be used for matching.
new(result)
var i = compileAux(0, regex, result)
if i < len(regex)-1:
# not all characters used for the regular expression?
raiseRegEx("invalid regular expression")

296
lib/base/pcre.nim Executable file
View File

@@ -0,0 +1,296 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# This file was created by a complicated procedure which saved me a considerable
# amount of time: the pcre.h header was converted to modpcre.h by hand, so that
# h2pas could handle it. Then I used pas2mor to generate a Morpork binding.
# Unfortunately, I had to fix some things later on; thus don't do all this
# again! My manual changes will be lost!
# Converted by Pas2mor v1.37
#
# Automatically converted by H2Pas 0.99.16 from modpcre.h
# The following command line parameters were used:
# -D -c -l pcre.lib -T modpcre.h
{.compile: "pcre_all.c" .}
type
Pbyte = ptr byte
Pchar = CString
PPchar = ptr PChar
Pint = ptr cint
Ppcre* = ptr TPcre
Ppcre_callout_block = ptr tpcre_callout_block
Ppcre_extra = ptr Tpcre_extra
#************************************************
#* Perl-Compatible Regular Expressions *
#************************************************
#
# Modified by Andreas Rumpf for h2pas.
# In its original form, this is the .in file that is transformed by
# "configure" into pcre.h.
#
# Copyright (c) 1997-2005 University of Cambridge
#
# -----------------------------------------------------------------------------
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the name of the University of Cambridge nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# -----------------------------------------------------------------------------
# The file pcre.h is build by "configure". Do not edit it; instead
# make changes to pcre.in.
const
PCRE_MAJOR* = 6
PCRE_MINOR* = 3
PCRE_DATE* = "2005/11/29"
# Options
PCRE_CASELESS* = 0x00000001
PCRE_MULTILINE* = 0x00000002
PCRE_DOTALL* = 0x00000004
PCRE_EXTENDED* = 0x00000008
PCRE_ANCHORED* = 0x00000010
PCRE_DOLLAR_ENDONLY* = 0x00000020
PCRE_EXTRA* = 0x00000040
PCRE_NOTBOL* = 0x00000080
PCRE_NOTEOL* = 0x00000100
PCRE_UNGREEDY* = 0x00000200
PCRE_NOTEMPTY* = 0x00000400
PCRE_UTF8* = 0x00000800
PCRE_NO_AUTO_CAPTURE* = 0x00001000
PCRE_NO_UTF8_CHECK* = 0x00002000
PCRE_AUTO_CALLOUT* = 0x00004000
PCRE_PARTIAL* = 0x00008000
PCRE_DFA_SHORTEST* = 0x00010000
PCRE_DFA_RESTART* = 0x00020000
PCRE_FIRSTLINE* = 0x00040000
# Exec-time and get/set-time error codes
PCRE_ERROR_NOMATCH* = -(1)
PCRE_ERROR_NULL* = -(2)
PCRE_ERROR_BADOPTION* = -(3)
PCRE_ERROR_BADMAGIC* = -(4)
PCRE_ERROR_UNKNOWN_NODE* = -(5)
PCRE_ERROR_NOMEMORY* = -(6)
PCRE_ERROR_NOSUBSTRING* = -(7)
PCRE_ERROR_MATCHLIMIT* = -(8)
# Never used by PCRE itself
PCRE_ERROR_CALLOUT* = -(9)
PCRE_ERROR_BADUTF8* = -(10)
PCRE_ERROR_BADUTF8_OFFSET* = -(11)
PCRE_ERROR_PARTIAL* = -(12)
PCRE_ERROR_BADPARTIAL* = -(13)
PCRE_ERROR_INTERNAL* = -(14)
PCRE_ERROR_BADCOUNT* = -(15)
PCRE_ERROR_DFA_UITEM* = -(16)
PCRE_ERROR_DFA_UCOND* = -(17)
PCRE_ERROR_DFA_UMLIMIT* = -(18)
PCRE_ERROR_DFA_WSSIZE* = -(19)
PCRE_ERROR_DFA_RECURSE* = -(20)
# Request types for pcre_fullinfo()
PCRE_INFO_OPTIONS* = 0
PCRE_INFO_SIZE* = 1
PCRE_INFO_CAPTURECOUNT* = 2
PCRE_INFO_BACKREFMAX* = 3
PCRE_INFO_FIRSTBYTE* = 4
# For backwards compatibility
PCRE_INFO_FIRSTCHAR* = 4
PCRE_INFO_FIRSTTABLE* = 5
PCRE_INFO_LASTLITERAL* = 6
PCRE_INFO_NAMEENTRYSIZE* = 7
PCRE_INFO_NAMECOUNT* = 8
PCRE_INFO_NAMETABLE* = 9
PCRE_INFO_STUDYSIZE* = 10
PCRE_INFO_DEFAULT_TABLES* = 11
# Request types for pcre_config()
PCRE_CONFIG_UTF8* = 0
PCRE_CONFIG_NEWLINE* = 1
PCRE_CONFIG_LINK_SIZE* = 2
PCRE_CONFIG_POSIX_MALLOC_THRESHOLD* = 3
PCRE_CONFIG_MATCH_LIMIT* = 4
PCRE_CONFIG_STACKRECURSE* = 5
PCRE_CONFIG_UNICODE_PROPERTIES* = 6
# Bit flags for the pcre_extra structure
PCRE_EXTRA_STUDY_DATA* = 0x0001
PCRE_EXTRA_MATCH_LIMIT* = 0x0002
PCRE_EXTRA_CALLOUT_DATA* = 0x0004
PCRE_EXTRA_TABLES* = 0x0008
# Types
type
TPcre = record
#undefined structure
# The structure for passing additional data to pcre_exec(). This is defined
# in such as way as to be extensible. Always add new fields at the end,
# in order to remain compatible.
# Bits for which fields are set
# Opaque data from pcre_study()
# Maximum number of calls to match()
# Data passed back in callouts
# Const before type ignored
# Pointer to character tables
Tpcre_extra* = record
flags: cuint
study_data: pointer
match_limit: cuint
callout_data: pointer
tables: ptr byte
# The structure for passing out data via the pcre_callout_function. We use a
# structure so that new fields can be added on the end in future versions,
# without changing the API of the function, thereby allowing old clients to
# work without modification.
# Identifies version of block
# ------------------------ Version 0 -------------------------------
# Number compiled into pattern
# The offset vector
# Const before type ignored
# The subject being matched
# The length of the subject
# Offset to start of this match attempt
# Where we currently are in the subject
# Max current capture
# Most recently closed capture
# Data passed in with the call
# ------------------- Added for Version 1 --------------------------
# Offset to next item in the pattern
# Length of next item in the pattern
# ------------------------------------------------------------------
TPcre_callout_block* = record
version: cint
callout_number: cint
offset_vector: ptr cint
subject: ptr char
subject_length: cint
start_match: cint
current_position: cint
capture_top: cint
capture_last: cint
callout_data: pointer
pattern_position: cint
next_item_length: cint
# Exported PCRE functions
proc pcre_compile*(para1: Pchar, para2: cint, para3: ptr Pchar,
para4: Pint, para5: Pbyte): Ppcre {.
importc: "pcre_compile", noconv.}
proc pcre_compile2*(para1: Pchar, para2: cint, para3: Pint, para4: PPchar,
para5: Pint, para6: Pbyte): Ppcre {.
importc: "pcre_compile2", noconv.}
proc pcre_config*(para1: cint, para2: pointer): cint {.
importc: "pcre_config", noconv.}
proc pcre_copy_named_substring*(para1: Ppcre, para2: Pchar, para3: Pint,
para4: cint, para5: Pchar, para6: Pchar,
para7: cint): cint {.
importc: "pcre_copy_named_substring", noconv.}
proc pcre_copy_substring*(para1: Pchar, para2: Pint, para3: cint, para4: cint,
para5: Pchar, para6: cint): cint {.
importc: "pcre_copy_substring", noconv.}
proc pcre_dfa_exec*(para1: Ppcre, para2: Ppcre_extra, para3: Pchar,
para4: cint, para5: cint, para6: cint, para7: Pint,
para8: cint, para9: Pint, para10: cint): cint {.
importc: "pcre_dfa_exec", noconv.}
proc pcre_exec*(para1: Ppcre, para2: Ppcre_extra, para3: Pchar,
para4: cint, para5: cint, para6: cint, para7: Pint,
para8: cint): cint {.importc: "pcre_exec", noconv.}
proc pcre_free_substring*(para1: Pchar) {.
importc: "pcre_free_substring", noconv.}
proc pcre_free_substring_list*(para1: PPchar) {.
importc: "pcre_free_substring_list", noconv.}
proc pcre_fullinfo*(para1: Ppcre, para2: Ppcre_extra, para3: cint,
para4: pointer): cint {.importc: "pcre_fullinfo", noconv.}
proc pcre_get_named_substring*(para1: Ppcre, para2: Pchar, para3: Pint,
para4: cint, para5: Pchar, para6: PPchar): cint {.
importc: "pcre_get_named_substring", noconv.}
proc pcre_get_stringnumber*(para1: Ppcre, para2: Pchar): cint {.
importc: "pcre_get_stringnumber", noconv.}
proc pcre_get_substring*(para1: Pchar, para2: Pint, para3: cint,
para4: cint, para5: PPchar): cint {.
importc: "pcre_get_substring", noconv.}
proc pcre_get_substring_list*(para1: Pchar, para2: Pint, para3: cint,
para4: ptr PPchar): cint {.
importc: "pcre_get_substring_list", noconv.}
proc pcre_info*(para1: Ppcre, para2: Pint, para3: Pint): cint {.
importc: "pcre_info", noconv.}
proc pcre_maketables*: ptr byte {.
importc: "pcre_maketables", noconv.}
proc pcre_refcount*(para1: Ppcre, para2: cint): cint {.
importc: "pcre_refcount", noconv.}
proc pcre_study*(para1: Ppcre, para2: cint,
para3: ptr CString): Ppcre_extra {.importc, noconv.}
proc pcre_version*: CString {.importc: "pcre_version", noconv.}
# Indirection for store get and free functions. These can be set to
# alternative malloc/free functions if required. Special ones are used in the
# non-recursive case for "frames". There is also an optional callout function
# that is triggered by the (?) regex item.
#
# we use Nimrod's memory manager (but not GC!) for these functions:
var
pcre_malloc {.importc: "pcre_malloc".}: proc (para1: int): pointer {.noconv.}
pcre_free {.importc: "pcre_free".}: proc (para1: pointer) {.noconv.}
pcre_stack_malloc {.importc: "pcre_stack_malloc".}:
proc (para1: int): pointer {.noconv.}
pcre_stack_free {.importc: "pcre_stack_free".}:
proc (para1: pointer) {.noconv.}
pcre_callout {.importc: "pcre_callout".}:
proc (para1: Ppcre_callout_block): cint {.noconv.}
pcre_malloc = system.alloc
pcre_free = system.dealloc
pcre_stack_malloc = system.alloc
pcre_stack_free = system.dealloc
pcre_callout = nil

30072
lib/base/pcre_all.c Executable file

File diff suppressed because it is too large Load Diff

114
lib/base/regexprs.nim Executable file
View File

@@ -0,0 +1,114 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Regular expression support for Nimrod.
## Currently this module is implemented by providing a wrapper around the
## `PRCE (Perl-Compatible Regular Expressions) <http://www.pcre.org>`_
## C library. This means that your application will depend on the PRCE
## library's licence when using this module, which should not be a problem
## though.
## PRCE's licence follows:
##
## .. include:: ../doc/regexprs.txt
##
# This is not just a convenient wrapper for the pcre library; the
# API will stay the same if the implementation should change.
import
pcre, strutils
type
EInvalidRegEx* = object of EInvalidValue
## is raised if the pattern is no valid regular expression.
const
MaxSubpatterns* = 10
## defines the maximum number of subpatterns that can be captured.
## More subpatterns cannot be captured!
proc match*(s, pattern: string, substrs: var openarray[string],
start: int = 0): bool
## returns ``true`` if ``s`` matches the ``pattern[start..]`` and
## the captured substrings in the array ``substrs``. If it does not
## match, nothing is written into ``substrs`` and ``false`` is
## returned.
proc match*(s, pattern: string, start: int = 0): bool
## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``.
proc matchLen*(s, pattern: string, substrs: var openarray[string],
start: int = 0): int
## the same as ``match``, but it returns the length of the match,
## if there is no match, -1 is returned. Note that a match length
## of zero can happen.
proc find*(s, pattern: string, substrs: var openarray[string],
start: int = 0): bool
## returns ``true`` if ``pattern`` occurs in ``s`` and the captured
## substrings in the array ``substrs``. If it does not match, nothing
## is written into ``substrs``.
proc find*(s, pattern: string, start: int = 0): bool
## returns ``true`` if ``pattern`` occurs in ``s``.
proc rawCompile(pattern: string, flags: cint): PPcre =
var
msg: CString
offset: cint
com = pcreCompile(pattern, flags, addr(msg), addr(offset), nil)
if com == nil:
var e: ref EInvalidRegEx
new(e)
e.msg = $msg & "\n" & pattern & "\n" & repeatChar(offset) & "^\n"
raise e
return com
proc matchOrFind(s: string, pattern: PPcre, substrs: var openarray[string],
start: cint): cint =
var
rawMatches: array [0..maxSubpatterns * 3 - 1, cint]
res = int(pcreExec(pattern, nil, s, length(s), start, 0,
cast[pint](addr(rawMatches)), maxSubpatterns * 3))
dealloc(pattern)
if res < 0: return res
for i in 0..res-1:
var
a = rawMatches[i * 3]
b = rawMatches[i * 3 + 1]
if a >= 0: substrs[i] = copy(s, a, b)
else: substrs[i] = ""
return res
proc matchOrFind(s: string, pattern: PPcre, start: cint): cint =
var
rawMatches: array [0..maxSubpatterns * 3 - 1, cint]
res = pcreExec(pattern, nil, s, length(s), start, 0,
cast[pint](addr(rawMatches)), maxSubpatterns * 3)
dealloc(pattern)
return res
proc match(s, pattern: string, substrs: var openarray[string],
start: int = 0): bool =
return matchOrFind(s, rawCompile(pattern, PCRE_ANCHORED),
substrs, start) >= 0
proc matchLen(s, pattern: string, substrs: var openarray[string],
start: int = 0): int =
return matchOrFind(s, rawCompile(pattern, PCRE_ANCHORED), substrs, start)
proc find(s, pattern: string, substrs: var openarray[string],
start: int = 0): bool =
return matchOrFind(s, rawCompile(pattern, 0), substrs, start) >= 0
proc match(s, pattern: string, start: int = 0): bool =
return matchOrFind(s, rawCompile(pattern, PCRE_ANCHORED), start) >= 0
proc find(s, pattern: string, start: int = 0): bool =
return matchOrFind(s, rawCompile(pattern, 0), start) >= 0

20
lib/cntbits.nim Executable file
View File

@@ -0,0 +1,20 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
proc population16(a: int): int {.inline.} =
var x = a
x = ((x and 0xAAAA) shr 1) + (x and 0x5555)
x = ((x and 0xCCCC) shr 2) + (x and 0x3333)
x = ((x and 0xF0F0) shr 4) + (x and 0x0F0F)
x = ((x and 0xFF00) shr 8) + (x and 0x00FF)
return x
proc countBits(n: int32): int =
result = population16(n and 0xffff) + population16(n shr 16)

108
lib/complex.nim Executable file
View File

@@ -0,0 +1,108 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module implements complex numbers.
{.push checks:off, line_dir:off, stack_trace:off, debugger:off.}
# the user does not want to trace a part
# of the standard library!
import
math
type
TComplex* = record ## a complex number, consisting of a real and an
## imaginary part
re*: float ## real part of the complex number
im*: float ## imarginary part of the complex number
proc `==` *(x, y: TComplex): bool =
## Compare two complex numbers `x` and `y` for equality.
result = x.re == y.re and x.im == y.im
proc `+` *(x, y: TComplex): TComplex =
## Add two complex numbers.
result.re = x.re + y.re
result.im = x.im + y.im
proc `-` *(x, y: TComplex): TComplex =
## Subtract two complex numbers.
result.re = x.re - y.re
result.im = x.im - y.im
proc `-` *(z: TComplex): TComplex =
## Unary minus for complex numbers.
result.re = -z.re
result.im = -z.im
proc `/` *(x, y: TComplex): TComplex =
## Divide `x` by `y`.
var
r, den: float
if abs(y.re) < abs(y.im):
r = y.re / y.im
den = y.im + r * y.re
result.re = (x.re * r + x.im) / den
result.im = (x.im * r - x.re) / den
else:
r = y.im / y.re
den = y.re + r * y.im
result.re = (x.re + r * x.im) / den
result.im = (x.im - r * x.re) / den
proc `*` *(x, y: TComplex): TComplex =
## Multiply `x` with `y`.
result.re = x.re * y.re - x.im * y.im
result.im = x.im * y.re + x.re * y.im
proc abs*(z: TComplex): float =
## Return the distance from (0,0) to `z`.
# optimized by checking special cases (sqrt is expensive)
var x, y, temp: float
x = abs(z.re)
y = abs(z.im)
if x == 0.0:
result = y
elif y == 0.0:
result = x
elif x > y:
temp = y / x
result = x * sqrt(1.0 + temp * temp)
else:
temp = x / y
result = y * sqrt(1.0 + temp * temp)
proc sqrt*(z: TComplex): TComplex =
## Square root for a complex number `z`.
var x, y, w, r: float
if z.re == 0.0 and z.im == 0.0:
result = z
else:
x = abs(z.re)
y = abs(z.im)
if x >= y:
r = y / x
w = sqrt(x) * sqrt(0.5 * (1.0 + sqrt(1.0 + r * r)))
else:
r = x / y
w = sqrt(y) * sqrt(0.5 * (r + sqrt(1.0 + r * r)))
if z.re >= 0.0:
result.re = w
result.im = z.im / (w * 2)
else:
if z.im >= 0.0: result.im = w
else: result.im = -w
result.re = z.im / (c.im + c.im)
{.pop.}

29
lib/copying.txt Executable file
View File

@@ -0,0 +1,29 @@
=======================================================
The Nimrod Runtime Library
Copyright (C) 2004-2007 Andreas Rumpf
=======================================================
This is the file copying.txt, it applies to the Nimrod Run-Time Library
(lib) and base packages (base) distributed by members of the Nimrod
Development Team.
The source code of the Nimrod Runtime Libraries and packages are
distributed under the Library GNU General Public License
(see the file lgpl.txt) with the following modification:
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent modules,
and to copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the terms
and conditions of the license of that module. An independent module is a module
which is not derived from or based on this library. If you modify this
library, you may extend this exception to your version of the library, but
you are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version.
If you didn't receive a copy of the file lgpl.txt, contact:
Free Software Foundation
675 Mass Ave
Cambridge, MA 02139
USA

499
lib/debugger.nim Executable file
View File

@@ -0,0 +1,499 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# This file implements the embedded debugger that can be linked
# with the application. We should not use dynamic memory here as that
# would interfere with the GC and trigger ON/OFF errors if the
# user program corrupts memory. Unfortunately, for dispaying
# variables we use the system.repr() proc which uses Nimrod
# strings and thus allocates memory from the heap. Pity, but
# I do not want to implement repr() twice. We also cannot deactivate
# the GC here as that might run out of memory too quickly...
type
TDbgState = enum
dbOff, # debugger is turned off
dbStepInto, # debugger is in tracing mode
dbStepOver,
dbSkipCurrent,
dbQuiting, # debugger wants to quit
dbBreakpoints # debugger is only interested in breakpoints
TDbgBreakpoint = record
low, high: int # range from low to high; if disabled
# both low and high are set to their negative values
# this makes the check faster and safes memory
filename: string
name: string # name of breakpoint
TVarSlot {.compilerproc.} = record # variable slots used for debugger:
address: pointer
typ: PNimType
name: cstring # for globals this is "module.name"
PExtendedFrame = ptr TExtendedFrame
TExtendedFrame = record # If the debugger is enabled the compiler provides
# an extended frame. Of course only slots that are
# needed are allocated and not 10_000, except for
# the global data description.
f: TFrame
slots: array[0..10_000, TVarSlot]
var
dbgInSignal: bool # wether the debugger is in the signal handler
dbgIn: TFile # debugger input stream
dbgUser: string = "s" # buffer for user input; first command is ``step_into``
# needs to be global cause we store the last command
# in it
dbgState: TDbgState = dbStepInto # state of debugger
dbgBP: array[0..127, TDbgBreakpoint] # breakpoints
dbgBPlen: int = 0
dbgSkipToFrame: PFrame # frame to be skipped to
dbgGlobalData: TExtendedFrame # this reserves much space, but
# for now it is the most practical way
maxDisplayRecDepth: int = 5 # do not display too much data!
proc findBreakpoint(name: string): int =
# returns -1 if not found
for i in countdown(dbgBPlen-1, 0):
if name == dbgBP[i].name: return i
return -1
proc ListBreakPoints() =
write(stdout, "*** emdb| Breakpoints:\n")
for i in 0 .. dbgBPlen-1:
write(stdout, dbgBP[i].name & ": " & $abs(dbgBP[i].low) & ".." &
$abs(dbgBP[i].high) & dbgBP[i].filename)
if dbgBP[i].low < 0:
write(stdout, " [disabled]\n")
else:
write(stdout, "\n")
write(stdout, "***\n")
proc openAppend(filename: string): TFile =
if openFile(result, filename, fmAppend):
write(result, "----------------------------------------\n")
proc dbgRepr(p: pointer, typ: PNimType): string =
var
cl: TReprClosure
initReprClosure(cl)
cl.recDepth = maxDisplayRecDepth
# locks for the GC turned out to be a bad idea...
# inc(recGcLock)
result = ""
reprAux(result, p, typ, cl)
# dec(recGcLock)
deinitReprClosure(cl)
proc writeVariable(stream: TFile, slot: TVarSlot) =
write(stream, slot.name)
write(stream, " = ")
writeln(stream, dbgRepr(slot.address, slot.typ))
proc ListFrame(stream: TFile, f: PExtendedFrame) =
write(stream, "*** emdb| Frame (" & $f.f.len & " slots):\n")
for i in 0 .. f.f.len-1:
writeVariable(stream, f.slots[i])
write(stream, "***\n")
proc ListVariables(stream: TFile, f: PExtendedFrame) =
write(stream, "*** emdb| Frame (" & $f.f.len & " slots):\n")
for i in 0 .. f.f.len-1:
writeln(stream, f.slots[i].name)
write(stream, "***\n")
proc debugOut(msg: cstring) =
# the *** *** markers are for easy recognition of debugger
# output for external frontends.
write(stdout, "*** emdb| ")
write(stdout, msg)
write(stdout, "***\n")
proc dbgFatal(msg: cstring) =
debugOut(msg)
dbgAborting = True # the debugger wants to abort
quit(1)
proc findVariable(frame: PExtendedFrame, varname: cstring): int =
for i in 0 .. frame.f.len - 1:
if c_strcmp(frame.slots[i].name, varname) == 0: return i
return -1
proc dbgShowCurrentProc(dbgFramePointer: PFrame) =
if dbgFramePointer != nil:
write(stdout, "*** emdb| now in proc: ")
write(stdout, dbgFramePointer.procname)
write(stdout, " ***\n")
else:
write(stdout, "*** emdb| (procedure name not available) ***\n")
proc dbgShowExecutionPoint() =
write(stdout, "*** emdb| " & $framePtr.filename & "(" & $framePtr.line &
") " & $framePtr.procname & " ***\n")
when defined(windows) or defined(dos) or defined(os2):
{.define: FileSystemCaseInsensitive.}
proc fileMatches(c, bp: cstring): bool =
# bp = breakpoint filename
# c = current filename
# we consider it a match if bp is a suffix of c
# and the character for the suffix does not exist or
# is one of: \ / :
# depending on the OS case does not matter!
var blen: int = c_strlen(bp)
var clen: int = c_strlen(c)
if blen > clen: return false
# check for \ / :
if clen-blen-1 >= 0 and c[clen-blen-1] notin {'\\', '/', ':'}:
return false
var i = 0
while i < blen:
var x, y: char
x = bp[i]
y = c[i+clen-blen]
when defined(FileSystemCaseInsensitive):
if x >= 'A' and x <= 'Z': x = chr(ord(x) - ord('A') + ord('a'))
if y >= 'A' and y <= 'Z': y = chr(ord(y) - ord('A') + ord('a'))
if x != y: return false
inc(i)
return true
proc dbgBreakpointReached(line: int): int =
for i in 0..dbgBPlen-1:
if line >= dbgBP[i].low and line <= dbgBP[i].high and
fileMatches(framePtr.filename, dbgBP[i].filename): return i
return -1
proc scanAndAppendWord(src: string, a: var string, start: int): int =
result = start
# skip whitespace:
while src[result] in {'\t', ' '}: inc(result)
while True:
case src[result]
of 'a'..'z', '0'..'9': add(a, src[result])
of '_': nil # just skip it
of 'A'..'Z': add(a, chr(ord(src[result]) - ord('A') + ord('a')))
else: break
inc(result)
proc scanWord(src: string, a: var string, start: int): int =
a = ""
result = scanAndAppendWord(src, a, start)
proc scanFilename(src: string, a: var string, start: int): int =
result = start
a = ""
# skip whitespace:
while src[result] in {'\t', ' '}: inc(result)
while src[result] notin {'\t', ' ', '\0'}:
add(a, src[result])
inc(result)
proc scanNumber(src: string, a: var int, start: int): int =
result = start
a = 0
while src[result] in {'\t', ' '}: inc(result)
while true:
case src[result]
of '0'..'9': a = a * 10 + ord(src[result]) - ord('0')
of '_': nil # skip underscores (nice for long line numbers)
else: break
inc(result)
proc dbgHelp() =
debugOut("""
list of commands (see the manual for further help):
GENERAL
h, help display this help message
q, quit quit the debugger and the program
<ENTER> repeat the previous debugger command
EXECUTING
s, stepinto single step, stepping into routine calls
n, stepover single step, without stepping into routine calls
f, skipcurrent continue execution until the current routine finishes
c, continue continue execution until the next breakpoint
i, ignore continue execution, ignore all breakpoints
BREAKPOINTS
b, setbreak <name> [fromline [toline]] [file]
set a new breakpoint named 'name' for line and file
if line or file are omitted the current one is used
breakpoints display the entire breakpoint list
disable <name> disable a breakpoint
enable <name> enable a breakpoint
DATA DISPLAY
e, eval <exp> evaluate the expression <exp>
o, out <file> <exp> evaluate <exp> and write it to <file>
w, where display the current execution point
stackframe [file] display current stack frame [and write it to file]
u, up go up in the call stack
d, down go down in the call stack
callstack display the entire call stack
l, locals display available local variables
g, globals display available global variables
maxdisplay <integer> set the display's recursion maximum
""")
proc InvalidCommand() =
debugOut("[Warning] invalid command ignored (type 'h' for help) ")
proc hasExt(s: string): bool =
# returns true if s has a filename extension
for i in countdown(len(s)-1, 0):
if s[i] == '.': return true
return false
proc setBreakPoint(s: string, start: int) =
var dbgTemp: string
var i = scanWord(s, dbgTemp, start)
if i <= start:
InvalidCommand()
return
if dbgBPlen >= high(dbgBP):
debugOut("[Warning] no breakpoint could be set; out of breakpoint space ")
return
var x = dbgBPlen
inc(dbgBPlen)
dbgBP[x].name = dbgTemp
i = scanNumber(s, dbgBP[x].low, i)
if dbgBP[x].low == 0:
# set to current line:
dbgBP[x].low = framePtr.line
i = scanNumber(s, dbgBP[x].high, i)
if dbgBP[x].high == 0: # set to low:
dbgBP[x].high = dbgBP[x].low
i = scanFilename(s, dbgTemp, i)
if not (dbgTemp.len == 0):
if not hasExt(dbgTemp): add(dbgTemp, ".nim")
dbgBP[x].filename = dbgTemp
else: # use current filename
dbgBP[x].filename = $framePtr.filename
# skip whitespace:
while s[i] in {' ', '\t'}: inc(i)
if s[i] != '\0':
dec(dbgBPLen) # remove buggy breakpoint
InvalidCommand()
proc BreakpointSetEnabled(s: string, start, enabled: int) =
var dbgTemp: string
var i = scanWord(s, dbgTemp, start)
if i <= start:
InvalidCommand()
return
var x = findBreakpoint(dbgTemp)
if x < 0: debugOut("[Warning] breakpoint does not exist ")
elif enabled * dbgBP[x].low < 0: # signs are different?
dbgBP[x].low = -dbgBP[x].low
dbgBP[x].high = -dbgBP[x].high
proc dbgEvaluate(stream: TFile, s: string, start: int,
currFrame: PExtendedFrame) =
var dbgTemp: string
var i = scanWord(s, dbgTemp, start)
while s[i] in {' ', '\t'}: inc(i)
var f = currFrame
if s[i] == '.':
inc(i) # skip '.'
add(dbgTemp, '.')
i = scanAndAppendWord(s, dbgTemp, i)
# search for global var:
f = addr(dbgGlobalData)
if s[i] != '\0':
debugOut("[Warning] could not parse expr ")
return
var j = findVariable(f, dbgTemp)
if j < 0:
debugOut("[Warning] could not find variable ")
return
writeVariable(stream, f.slots[j])
proc dbgOut(s: string, start: int, currFrame: PExtendedFrame) =
var dbgTemp: string
var i = scanFilename(s, dbgTemp, start)
if dbgTemp.len == 0:
InvalidCommand()
return
var stream = openAppend(dbgTemp)
if stream == nil:
debugOut("[Warning] could not open or create file ")
return
dbgEvaluate(stream, s, i, currFrame)
closeFile(stream)
proc dbgStackFrame(s: string, start: int, currFrame: PExtendedFrame) =
var dbgTemp: string
var i = scanFilename(s, dbgTemp, start)
if dbgTemp.len == 0:
# just write it to stdout:
ListFrame(stdout, currFrame)
else:
var stream = openAppend(dbgTemp)
if stream == nil:
debugOut("[Warning] could not open or create file ")
return
ListFrame(stream, currFrame)
closeFile(stream)
proc CommandPrompt() =
# if we return from this routine, user code executes again
var
again: bool = True
dbgFramePtr = framePtr # for going down and up the stack
dbgDown: int = 0 # how often we did go down
while again:
write(stdout, "*** emdb| >>")
var tmp = readLine(stdin)
if tmp.len > 0: dbgUser = tmp
# now look what we have to do:
var dbgTemp: string
var i = scanWord(dbgUser, dbgTemp, 0)
case dbgTemp
of "": InvalidCommand()
of "s", "stepinto":
dbgState = dbStepInto
again = false
of "n", "stepover":
dbgState = dbStepOver
dbgSkipToFrame = framePtr
again = false
of "f", "skipcurrent":
dbgState = dbSkipCurrent
dbgSkipToFrame = framePtr.prev
again = false
of "c", "continue":
dbgState = dbBreakpoints
again = false
of "i", "ignore":
dbgState = dbOff
again = false
of "h", "help":
dbgHelp()
of "q", "quit":
dbgState = dbQuiting
dbgAborting = True
again = false
quit(1) # BUGFIX: quit with error code > 0
of "e", "eval":
dbgEvaluate(stdout, dbgUser, i, cast[PExtendedFrame](dbgFramePtr))
of "o", "out":
dbgOut(dbgUser, i, cast[PExtendedFrame](dbgFramePtr))
of "stackframe":
dbgStackFrame(dbgUser, i, cast[PExtendedFrame](dbgFramePtr))
of "w", "where":
dbgShowExecutionPoint()
of "l", "locals":
ListVariables(stdout, cast[PExtendedFrame](dbgFramePtr))
of "g", "globals":
ListVariables(stdout, addr(dbgGlobalData))
of "u", "up":
if dbgDown <= 0:
debugOut("[Warning] cannot go up any further ")
else:
dbgFramePtr = framePtr
for j in 0 .. dbgDown-2: # BUGFIX
dbgFramePtr = dbgFramePtr.prev
dec(dbgDown)
dbgShowCurrentProc(dbgFramePtr)
of "d", "down":
if dbgFramePtr != nil:
inc(dbgDown)
dbgFramePtr = dbgFramePtr.prev
dbgShowCurrentProc(dbgFramePtr)
else:
debugOut("[Warning] cannot go down any further ")
of "callstack":
WriteStackTrace()
of "b", "setbreak":
setBreakPoint(dbgUser, i)
of "breakpoints":
ListBreakPoints()
of "disable":
BreakpointSetEnabled(dbgUser, i, -1)
of "enable":
BreakpointSetEnabled(dbgUser, i, +1)
of "maxdisplay":
var parsed: int
i = scanNumber(dbgUser, parsed, i)
if dbgUser[i-1] in {'0'..'9'}:
if parsed == 0: maxDisplayRecDepth = -1
else: maxDisplayRecDepth = parsed
else:
InvalidCommand()
else:
InvalidCommand()
proc endbStep() =
# we get into here if an unhandled exception has been raised
# XXX: do not allow the user to run the program any further?
# XXX: BUG: the frame is lost here!
dbgShowExecutionPoint()
CommandPrompt()
proc checkForBreakpoint() =
var i = dbgBreakpointReached(framePtr.line)
if i >= 0:
write(stdout, "*** emdb| reached ")
write(stdout, dbgBP[i].name)
write(stdout, " in ")
write(stdout, framePtr.filename)
write(stdout, "(")
write(stdout, framePtr.line)
write(stdout, ") ")
write(stdout, framePtr.procname)
write(stdout, " ***\n")
CommandPrompt()
# interface to the user program:
proc dbgRegisterBreakpoint(line: int,
filename, name: cstring) {.compilerproc.} =
var x = dbgBPlen
inc(dbgBPlen)
dbgBP[x].name = $name
dbgBP[x].filename = $filename
dbgBP[x].low = line
dbgBP[x].high = line
proc dbgRegisterGlobal(name: cstring, address: pointer,
typ: PNimType) {.compilerproc.} =
var i = dbgGlobalData.f.len
if i >= high(dbgGlobalData.slots):
debugOut("[Warning] cannot register global ")
return
dbgGlobalData.slots[i].name = name
dbgGlobalData.slots[i].typ = typ
dbgGlobalData.slots[i].address = address
inc(dbgGlobalData.f.len)
proc endb(line: int) {.compilerproc.} =
# This proc is called before any Nimrod code line!
# Thus, it must have as few parameters as possible to keep the
# code size small!
# check if we are at an enabled breakpoint or "in the mood"
framePtr.line = line # this is done here for smaller code size!
if dbgLineHook != nil: dbgLineHook()
case dbgState
of dbStepInto:
# we really want the command prompt here:
dbgShowExecutionPoint()
CommandPrompt()
of dbSkipCurrent, dbStepOver: # skip current routine
if framePtr == dbgSkipToFrame:
dbgShowExecutionPoint()
CommandPrompt()
else: # breakpoints are wanted though (I guess)
checkForBreakpoint()
of dbBreakpoints: # debugger is only interested in breakpoints
checkForBreakpoint()
else: nil

5071
lib/dlmalloc.c Executable file

File diff suppressed because it is too large Load Diff

1143
lib/dlmalloc.h Executable file

File diff suppressed because it is too large Load Diff

143
lib/dyncalls.nim Executable file
View File

@@ -0,0 +1,143 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
#
# This file implements the ability to call native procs from libraries.
# It is not possible to do this in a platform independant way, unfortunately.
# However, the interface has been designed to take platform differences into
# account and been ported to all major platforms.
#
# interface
type
EInvalidLibrary = object of EOS
when defined(windows) or defined(dos):
{.define: USE_DLL.}
elif defined(posix):
{.define: USE_DLOPEN.}
elif defined(mac):
{.define: USE_DYLD.}
type
TLibHandle = pointer # private type
TProcAddr = pointer # libary loading and loading of procs:
const
NilLibHandle: TLibHandle = nil
proc nimLoadLibrary(path: string): TLibHandle {.compilerproc.}
proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.}
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.}
#implementation
# this code was inspired from Lua's source code:
# Lua - An Extensible Extension Language
# Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
# http://www.lua.org
# mailto:info@lua.org
when defined(USE_DLOPEN):
#
# =========================================================================
# This is an implementation based on the dlfcn interface.
# The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
# NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
# as an emulation layer on top of native functions.
# =========================================================================
#
# c stuff:
var
RTLD_NOW {.importc: "RTLD_NOW", header: "<dlfcn.h>".}: int
proc dlclose(lib: TLibHandle) {.importc, header: "<dlfcn.h>".}
proc dlopen(path: CString, mode: int): TLibHandle {.
importc, header: "<dlfcn.h>".}
proc dlsym(lib: TLibHandle, name: cstring): TProcAddr {.
importc, header: "<dlfcn.h>".}
proc nimUnloadLibrary(lib: TLibHandle) =
dlclose(lib)
proc nimLoadLibrary(path: string): TLibHandle =
result = dlopen(path, RTLD_NOW)
if result == nil:
raise newException(EInvalidLibrary, "could not load: " & path)
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
result = dlsym(lib, name)
elif defined(USE_DLL):
#
# =======================================================================
# Native Windows Implementation
# =======================================================================
#
type
THINSTANCE {.importc: "HINSTANCE".} = pointer
proc FreeLibrary(lib: THINSTANCE) {.importc, header: "<windows.h>", stdcall.}
proc winLoadLibrary(path: cstring): THINSTANCE {.
importc: "LoadLibraryA", header: "<windows.h>", stdcall.}
proc GetProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
importc: "GetProcAddress", header: "<windows.h>", stdcall.}
proc nimUnloadLibrary(lib: TLibHandle) =
FreeLibrary(cast[THINSTANCE](lib))
proc nimLoadLibrary(path: string): TLibHandle =
result = cast[TLibHandle](winLoadLibrary(path))
if result == nil:
raise newException(EInvalidLibrary, "could not load: " & path)
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
result = GetProcAddress(cast[THINSTANCE](lib), name)
elif defined(USE_DYLD):
#
# =======================================================================
# Native Mac OS X / Darwin Implementation
# =======================================================================
#
{.error: "no implementation for dyncalls yet".}
proc nimUnloadLibrary(lib: TLibHandle) =
NSUnLinkModule(NSModule(lib), NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES)
var
dyld_present {.importc: "_dyld_present", header: "<dyld.h>".}: int
proc nimLoadLibrary(path: string): TLibHandle =
var
img: NSObjectFileImage
ret: NSObjectFileImageReturnCode
modul: NSModule
# this would be a rare case, but prevents crashing if it happens
result = nil
if dyld_present != 0:
ret = NSCreateObjectFileImageFromFile(path, addr(img))
if ret == NSObjectFileImageSuccess:
modul = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE or
NSLINKMODULE_OPTION_RETURN_ON_ERROR)
NSDestroyObjectFileImage(img)
result = TLibHandle(modul)
if result == nil:
raise newException(EInvalidLibrary, "could not load: " & path)
proc nimGetProcAddr(lib: TLibHandle, cname: string): TProcAddr =
var
nss: NSSymbol
nss = NSLookupSymbolInModule(NSModule(lib), name)
result = TProcAddr(NSAddressOfSymbol(nss))
else: # workaround a newly introduced bug :-(
{.error: "no implementation for dyncalls".}

251
lib/excpt.nim Executable file
View File

@@ -0,0 +1,251 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# Exception handling code. This is difficult because it has
# to work if there is no more memory. Thus we have to use
# a static string. Do not use ``sprintf``, etc. as they are
# unsafe!
when not defined(windows) or not defined(guiapp):
proc writeToStdErr(msg: CString) = write(stdout, msg)
else:
proc MessageBoxA(hWnd: cint, lpText, lpCaption: cstring, uType: int): int32 {.
header: "<windows.h>", nodecl.}
proc writeToStdErr(msg: CString) =
discard MessageBoxA(0, msg, nil, 0)
proc raiseException(e: ref E_Base, ename: CString) {.compilerproc.}
proc reraiseException() {.compilerproc.}
proc registerSignalHandler() {.compilerproc.}
proc chckIndx(i, a, b: int): int {.inline, compilerproc.}
proc chckRange(i, a, b: int): int {.inline, compilerproc.}
proc chckRangeF(x, a, b: float): float {.inline, compilerproc.}
proc chckNil(p: pointer) {.inline, compilerproc.}
type
PSafePoint = ptr TSafePoint
TSafePoint {.compilerproc.} = record
prev: PSafePoint # points to next safe point ON THE STACK
exc: ref E_Base
status: int
context: C_JmpBuf
var
excHandler {.compilerproc, volatile.}: PSafePoint = nil
# list of exception handlers
# a global variable for the root of all try blocks
proc reraiseException() =
if excHandler != nil:
raise newException(ENoExceptionToReraise, "no exception to reraise")
else:
c_longjmp(excHandler.context, 1)
type
PFrame = ptr TFrame
TFrame {.importc, nodecl.} = record
prev: PFrame
procname: CString
line: int # current line number
filename: CString
len: int # length of slots (when not debugging always zero)
TTempFrame = record # used for recursion elimination in WriteStackTrace
procname: CString
line: int
var
buf: string # cannot be allocated on the stack!
assertBuf: string # we need a different buffer for
# assert, as it raises an exception and
# exception handler needs the buffer too
framePtr {.exportc, volatile.}: PFrame
tempFrames: array [0..255, TTempFrame] # cannot be allocated
# on the stack!
proc auxWriteStackTrace(f: PFrame, s: var string) =
var
it = f
i = 0
total = 0
while it != nil and i <= high(tempFrames):
tempFrames[i].procname = it.procname
tempFrames[i].line = it.line
inc(i)
inc(total)
it = it.prev
while it != nil:
inc(total)
it = it.prev
# if the buffer overflowed print '...':
if total != i:
add(s, "(")
add(s, $(total-i))
add(s, " calls omitted) ...\n")
for j in countdown(i-1, 0):
add(s, $tempFrames[j].procname)
if tempFrames[j].line > 0:
add(s, ", line: ")
add(s, $tempFrames[j].line)
add(s, "\n")
proc rawWriteStackTrace(s: var string) =
if framePtr == nil:
add(s, "No stack traceback available\n")
else:
add(s, "Traceback (most recent call last)\n")
auxWriteStackTrace(framePtr, s)
proc quitOrDebug() {.inline.} =
when not defined(emdb):
quit(1)
else:
emdbStep() # call the debugger
proc raiseException(e: ref E_Base, ename: CString) =
GC_disable() # a bad thing is an error in the GC while raising an exception
e.name = ename
if excHandler != nil:
excHandler.exc = e
c_longjmp(excHandler.context, 1)
else:
if cast[pointer](buf) != nil:
setLen(buf, 0)
rawWriteStackTrace(buf)
if e.msg != nil and e.msg[0] != '\0':
add(buf, "Error: unhandled exception: ")
add(buf, $e.msg)
else:
add(buf, "Error: unhandled exception")
add(buf, " [")
add(buf, $ename)
add(buf, "]\n")
writeToStdErr(buf)
else:
writeToStdErr("*** FATAL ERROR *** ")
writeToStdErr(ename)
writeToStdErr("\n")
quitOrDebug()
GC_enable()
var
gAssertionFailed: ref EAssertionFailed
proc internalAssert(file: cstring, line: int, cond: bool) {.compilerproc.} =
if not cond:
GC_disable() # BUGFIX: `$` allocates a new string object!
if cast[pointer](assertBuf) != nil: # BUGFIX: when debugging the GC, assertBuf may be nil
setLen(assertBuf, 0)
add(assertBuf, "[Assertion failure] file: ")
add(assertBuf, file)
add(assertBuf, " line: ")
add(assertBuf, $line)
add(assertBuf, "\n")
gAssertionFailed.msg = assertBuf
GC_enable()
raise gAssertionFailed # newException(EAssertionFailed, assertBuf)
proc WriteStackTrace() =
var
s: string = ""
rawWriteStackTrace(s)
writeToStdErr(s)
var
dbgAborting: bool # whether the debugger wants to abort
proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
# print stack trace and quit
var
s = int(sig)
setLen(buf, 0)
rawWriteStackTrace(buf)
if s == SIGINT: add(buf, "SIGINT: Interrupted by Ctrl-C.\n")
elif s == SIGSEGV: add(buf, "SIGSEGV: Illegal storage access.\n")
elif s == SIGABRT:
if dbgAborting: return # the debugger wants to abort
add(buf, "SIGABRT: Abnormal termination.\n")
elif s == SIGFPE: add(buf, "SIGFPE: Arithmetic error.\n")
elif s == SIGILL: add(buf, "SIGILL: Illegal operation.\n")
elif s == SIGBUS: add(buf, "SIGBUS: Illegal storage access.\n")
else: add(buf, "unknown signal\n")
writeToStdErr(buf)
dbgAborting = True # play safe here...
quit(1) # always quit when SIGABRT
proc registerSignalHandler() =
c_signal(SIGINT, signalHandler)
c_signal(SIGSEGV, signalHandler)
c_signal(SIGABRT, signalHandler)
c_signal(SIGFPE, signalHandler)
c_signal(SIGILL, signalHandler)
c_signal(SIGBUS, signalHandler)
registerSignalHandler() # call it in initialization section
# for easier debugging of the GC, this memory is only allocated after the
# signal handlers have been registered
new(gAssertionFailed)
buf = newString(2048)
assertBuf = newString(2048)
setLen(buf, 0)
setLen(assertBuf, 0)
proc raiseRangeError() {.compilerproc, noreturn.} =
raise newException(EOutOfRange, "value out of range")
proc raiseIndexError() {.compilerproc, noreturn.} =
raise newException(EInvalidIndex, "index out of bounds")
proc chckIndx(i, a, b: int): int =
if i >= a and i <= b:
return i
else:
raiseIndexError()
proc chckRange(i, a, b: int): int =
if i >= a and i <= b:
return i
else:
raiseRangeError()
proc chckRange64(i, a, b: int64): int64 {.compilerproc.} =
if i >= a and i <= b:
return i
else:
raiseRangeError()
proc chckRangeF(x, a, b: float): float =
if x >= a and x <= b:
return x
else:
raiseRangeError()
proc chckNil(p: pointer) =
if p == nil: c_raise(SIGSEGV)
proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
# checks if obj is of type subclass:
var x = obj
if x == subclass: return # optimized fast path
while x != subclass:
if x == nil:
raise newException(EInvalidObjectConversion, "invalid object conversion")
x = x.base
proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
if a != b:
raise newException(EInvalidObjectAssignment, "invalid object assignment")

897
lib/gc.nim Executable file
View File

@@ -0,0 +1,897 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# Garbage Collector
# For a description of the algorithms used here see:
# intern.html
#{.define: debugGC.} # we wish to debug the GC...
#when defined(debugGC):
# {.define: logGC.} # define if the GC should log some of its activities
{.define: cycleGC.}
# Guess the page size of the system; if it is the
# wrong value, performance may be worse (this is not
# for sure though), but GC still works; must be a power of two!
const
PageSize = 1024 * sizeof(int)
RC_Increase = 7 * PageSize # is an additive increase
CycleIncrease = 2 # is a multiplicative increase
when defined(debugGC):
const InitialThreshold = 64*1024
const stressGC = True # GC is debugged; no need to stress it
else:
const stressGC = False
const InitialThreshold = RC_Increase
# this may need benchmarking...
# things the System module thinks should be available:
when defined(useDL) or defined(nativeDL):
type
TMallocInfo {.importc: "struct mallinfo", nodecl.} = record
arena: cint # non-mmapped space allocated from system
ordblks: cint # number of free chunks
smblks: cint # number of fastbin blocks
hblks: cint # number of mmapped regions
hblkhd: cint # space in mmapped regions
usmblks: cint # maximum total allocated space
fsmblks: cint # space available in freed fastbin blocks
uordblks: cint # total allocated space
fordblks: cint # total free space
keepcost: cint # top-most, releasable (via malloc_trim) space
when defined(useDL):
proc mallinfo: TMallocInfo {.importc: "dlmallinfo", nodecl.}
elif defined(nativeDL):
proc mallinfo: TMallocInfo {.importc: "mallinfo", nodecl.}
when defined(useDL) or defined(nativeDL):
proc getOccupiedMem(): int = return mallinfo().uordblks
proc getFreeMem(): int = return mallinfo().fordblks
proc getTotalMem(): int =
var m = mallinfo()
return int(m.hblkhd) + int(m.arena)
else: # not available:
proc getOccupiedMem(): int = return -1
proc getFreeMem(): int = return -1
proc getTotalMem(): int = return -1
var
rcThreshold: int = InitialThreshold
cycleThreshold: int = InitialThreshold
memUsed: int = 0 # we have to keep track how much we have allocated
recGcLock: int = 0
# we use a lock to prevend the garbage collector to
# be triggered in a finalizer; the collector should not call
# itself this way! Thus every object allocated by a finalizer
# will not trigger a garbage collection. This is wasteful but safe.
# This is a lock against recursive garbage collection, not a lock for
# threads!
when defined(useDL) and not defined(nativeDL):
{.compile: "dlmalloc.c".}
type
TFinalizer {.compilerproc.} = proc (self: pointer)
# A ref type can have a finalizer that is called before the object's
# storage is freed.
PPointer = ptr pointer
proc asgnRef(dest: ppointer, src: pointer) {.compilerproc.}
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc.}
# unsureAsgnRef updates the reference counters only if dest is not on the
# stack. It is used by the code generator if it cannot decide wether a
# reference is in the stack or not (this can happen for out/var parameters).
proc growObj(old: pointer, newsize: int): pointer {.compilerproc.}
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.}
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.}
# implementation:
when defined(useDL):
proc nimSize(p: pointer): int {.
importc: "dlmalloc_usable_size", header: "dlmalloc.h".}
elif defined(nativeDL):
proc nimSize(p: pointer): int {.
importc: "malloc_usable_size", header: "<malloc.h>".}
type
TWalkOp = enum
waNone, waRelease, waZctDecRef, waCycleDecRef, waCycleIncRef, waDebugIncRef
TCollectorData = int
TCell = record
refcount: TCollectorData # the refcount and bit flags
typ: PNimType
stackcount: int # stack counter for debugging
drefc: int # real reference counter for debugging
PCell = ptr TCell
var
gOutOfMem: ref EOutOfMemory
proc raiseOutOfMem() {.noreturn.} =
if gOutOfMem == nil:
writeToStdErr("out of memory; cannot even throw an exception")
quit(1)
gOutOfMem.msg = "out of memory"
raise gOutOfMem
proc cellToUsr(cell: PCell): pointer {.inline.} =
# convert object (=pointer to refcount) to pointer to userdata
result = cast[pointer](cast[TAddress](cell)+%TAddress(sizeof(TCell)))
proc usrToCell(usr: pointer): PCell {.inline.} =
# convert pointer to userdata to object (=pointer to refcount)
result = cast[PCell](cast[TAddress](usr)-%TAddress(sizeof(TCell)))
proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
# used for code generation concerning debugging
result = usrToCell(c).typ
proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =
result = int(usrToCell(p).refcount)
proc gcAlloc(size: int): pointer =
result = alloc0(size)
if result == nil: raiseOutOfMem()
proc GC_disable() = inc(recGcLock)
proc GC_enable() =
if recGcLock > 0: dec(recGcLock)
proc GC_setStrategy(strategy: TGC_Strategy) =
case strategy
of gcThroughput: nil
of gcResponsiveness: nil
of gcOptimizeSpace: nil
of gcOptimizeTime: nil
proc GC_enableMarkAndSweep() =
cycleThreshold = InitialThreshold
proc GC_disableMarkAndSweep() =
cycleThreshold = high(cycleThreshold)-1
# set to the max value to suppress the cycle detector
proc nextTry(h, maxHash: int): int {.inline.} =
result = ((5*h) + 1) and maxHash
# For any initial h in range(maxHash), repeating that maxHash times
# generates each int in range(maxHash) exactly once (see any text on
# random-number generation for proof).
# ------------------ Zero count table (ZCT) and any table (AT) -------------
# these values are for DL-malloc known for sure (and other allocators
# can only be worse):
when defined(useDL) or not defined(bcc):
const MemAlignment = 8 # minimal memory block that can be allocated
else:
const MemAlignment = 4 # Borland's memory manager is terrible!
const
BitsPerUnit = sizeof(int)*8
# a "unit" is a word, i.e. 4 bytes
# on a 32 bit system; I do not use the term "word" because under 32-bit
# Windows it is sometimes only 16 bits
BitsPerPage = PageSize div MemAlignment
UnitsPerPage = BitsPerPage div BitsPerUnit
# how many units do we need to describe a page:
# on 32 bit systems this is only 16 (!)
# this that has to equals zero, otherwise we have to round up UnitsPerPage:
when BitsPerPage mod BitsPerUnit != 0:
{.error: "(BitsPerPage mod BitsPerUnit) should be zero!".}
# ------------------- cell set handling ------------------------------
# A cellset consists of a hash table of page descriptors. A page
# descriptor has a bit for
# every Memalignment'th byte in the page.
# However, only bits corresponding to addresses that start memory blocks
# are set.
# Page descriptors are also linked to a list; the list
# is used for easy traversing of all page descriptors; this allows a
# fast iterator.
# We use a specialized hashing scheme; the formula is :
# hash = Page bitand max
# We use linear probing with the formular: (5*h)+1
# Thus we likely get no collisions at all if the pages are given us
# sequentially by the operating system!
type
PPageDesc = ptr TPageDesc
TBitIndex = range[0..UnitsPerPage-1]
TPageDesc = record
next: PPageDesc # all nodes are connected with this pointer
key: TAddress # start address at bit 0
bits: array[TBitIndex, int] # a bit vector
PPageDescArray = ptr array[0..1000_000, PPageDesc]
TCellSet = record
counter, max: int
head: PPageDesc
data: PPageDescArray
const
InitCellSetSize = 1024 # must be a power of two!
proc CellSetInit(s: var TCellSet) =
s.data = cast[PPageDescArray](gcAlloc(InitCellSetSize * sizeof(PPageDesc)))
s.max = InitCellSetSize-1
s.counter = 0
s.head = nil
proc CellSetDeinit(s: var TCellSet) =
var it = s.head
while it != nil:
var n = it.next
dealloc(it)
it = n
s.head = nil # play it safe here
dealloc(s.data)
s.data = nil
s.counter = 0
proc CellSetGet(t: TCellSet, key: TAddress): PPageDesc =
var h = cast[int](key) and t.max
while t.data[h] != nil:
if t.data[h].key == key: return t.data[h]
h = nextTry(h, t.max)
return nil
proc CellSetRawInsert(t: TCellSet, data: PPageDescArray,
desc: PPageDesc) =
var h = cast[int](desc.key) and t.max
while data[h] != nil:
assert(data[h] != desc)
h = nextTry(h, t.max)
assert(data[h] == nil)
data[h] = desc
proc CellSetEnlarge(t: var TCellSet) =
var
n: PPageDescArray
oldMax = t.max
t.max = ((t.max+1)*2)-1
n = cast[PPageDescArray](gcAlloc((t.max + 1) * sizeof(PPageDesc)))
for i in 0 .. oldmax:
if t.data[i] != nil:
CellSetRawInsert(t, n, t.data[i])
dealloc(t.data)
t.data = n
proc CellSetPut(t: var TCellSet, key: TAddress): PPageDesc =
var h = cast[int](key) and t.max
while true:
var x = t.data[h]
if x == nil: break
if x.key == key: return x
h = nextTry(h, t.max)
if (t.max+1) * 2 < t.counter * 3: CellSetEnlarge(t)
inc(t.counter)
h = cast[int](key) and t.max
while t.data[h] != nil: h = nextTry(h, t.max)
assert(t.data[h] == nil)
# the new page descriptor goes into result
result = cast[PPageDesc](gcAlloc(sizeof(TPageDesc)))
result.next = t.head
result.key = key
t.head = result
t.data[h] = result
# ---------- slightly higher level procs ----------------------------------
proc in_Operator(s: TCellSet, cell: PCell): bool =
var
u: TAddress
t: PPageDesc
u = cast[TAddress](cell)
t = CellSetGet(s, u /% PageSize)
if t != nil:
u = (u %% PageSize) /% MemAlignment
result = (t.bits[u /% BitsPerUnit] and (1 shl (u %% BitsPerUnit))) != 0
else:
result = false
proc incl(s: var TCellSet, cell: PCell) =
var
u: TAddress
t: PPageDesc
u = cast[TAddress](cell)
t = CellSetPut(s, u /% PageSize)
u = (u %% PageSize) /% MemAlignment
t.bits[u /% BitsPerUnit] = t.bits[u /% BitsPerUnit] or
(1 shl (u %% BitsPerUnit))
proc excl(s: var TCellSet, cell: PCell) =
var
u: TAddress
t: PPageDesc
u = cast[TAddress](cell)
t = CellSetGet(s, u /% PageSize)
if t != nil:
u = (u %% PageSize) /% MemAlignment
t.bits[u /% BitsPerUnit] = (t.bits[u /% BitsPerUnit] and
not (1 shl (u %% BitsPerUnit)))
iterator elements(t: TCellSet): PCell {.inline.} =
# while traversing it is forbidden to add pointers to the tree!
var r = t.head
while r != nil:
var i = 0
while i <= high(r.bits):
var w = r.bits[i] # taking a copy of r.bits[i] here is correct, because
# modifying operations are not allowed during traversation
var j = 0
while w != 0: # test all remaining bits for zero
if (w and 1) != 0: # the bit is set!
yield cast[PCell]((r.key *% PageSize) +%
(i*%BitsPerUnit+%j) *% MemAlignment)
inc(j)
w = w shr 1
inc(i)
r = r.next
# --------------- end of Cellset routines -------------------------------------
proc testPageDescs() =
var root: TCellSet
CellSetInit(root)
var u = 10_000
while u <= 20_000:
incl(root, cast[PCell](u))
inc(u, 8)
for cell in elements(root):
c_fprintf(c_stdout, "%ld\n", cast[int](cell))
# testPageDescs()
when defined(debugGC):
proc writeCell(msg: CString, c: PCell) =
c_fprintf(c_stdout, "%s: %p\n", msg, c)
proc writePtr(msg: CString, p: Pointer) =
c_fprintf(c_stdout, "%s: %p\n", msg, p)
# -------------------------------------------------------------------------
type
PStackCells = ptr array[0..1000_0000, PCell]
TCountTables = record # this contains the zero count and
# non-zero count table
mask: TAddress # mask for fast pointer detection
zct: TCellSet # the zero count table
at: TCellSet # a table that contains all references
newAT: TCellSet
newZCT: TCellSet
stackCells: PStackCells # cells that need to be decremented because they
# are in the hardware stack; a cell may occur
# several times in this data structure
stackLen, stackMax: int # for managing the stack cells
proc addStackCell(ct: var TCountTables, cell: PCell) =
if ct.stackLen >= ct.stackMax:
ct.stackMax = ct.stackMax * 3 div 2
ct.stackCells = cast[PStackCells](realloc(ct.stackCells, ct.stackMax *
sizeof(PCell)))
if ct.stackCells == nil: raiseOutOfMem()
ct.stackCells[ct.stackLen] = cell
inc(ct.stackLen)
var
stackBottom: pointer
ct: TCountTables
proc GC_invariant(): bool =
result = True
when stressGC:
if recGcLock == 0:
GC_disable()
for cell in elements(ct.at):
var t = cell.typ # getCellType(cell)
if t == nil or t.kind notin {tySequence, tyString, tyRef}:
writeCell("corrupt cell?", cell)
result = false
GC_enable()
when stressGC:
proc GCdebugHook() =
if not GC_invariant():
assert(false)
dbgLineHook = GCdebugHook
proc prepareDealloc(cell: PCell) =
if cell.typ.finalizer != nil:
# the finalizer could invoke something that
# allocates memory; this could trigger a garbage
# collection. Since we are already collecting we
# prevend recursive entering here by a lock.
# XXX: we should set the cell's children to nil!
inc(recGcLock)
(cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
dec(recGcLock)
when defined(nimSize):
memUsed = memUsed - nimSize(cell)
else:
memUsed = memUsed - cell.typ.size
proc setStackBottom(theStackBottom: pointer) {.compilerproc.} =
stackBottom = theStackBottom
proc initGC() =
# init the rt
CellSetInit(ct.zct)
CellSetInit(ct.at)
ct.stackLen = 0
ct.stackMax = 255
ct.stackCells = cast[PStackCells](gcAlloc((ct.stackMax+1) * sizeof(PCell)))
ct.mask = 0
new(gOutOfMem) # reserve space for the EOutOfMemory exception here!
assert(GC_invariant())
# forward declarations:
proc collectCT(ct: var TCountTables)
proc IsOnStack(p: pointer): bool
proc forAllChildren(cell: PCell, op: TWalkOp)
proc collectCycles()
proc reprAny(p: pointer, typ: PNimType): string {.compilerproc.}
# we need the prototype here for debugging purposes
proc outputCell(c: PCell) =
inc(recGcLock)
write(stdout, reprAny(cellToUsr(c), c.typ))
dec(recGcLock)
proc writeGraph() =
{.checkpoint.}
block:
inc(recGcLock)
for c in elements(ct.AT): outputCell(c)
dec(recGcLock)
proc checkRefc(): bool =
if recGcLock >= 1: return true # prevent endless recursion
inc(recGcLock)
result = True
# set counters back to zero:
for c in elements(ct.AT):
c.drefc = 0
for c in elements(ct.AT):
forAllChildren(c, waDebugIncRef)
for c in elements(ct.AT):
if c.drefc > c.refcount - c.stackcount:
result = false # failed
c_fprintf(c_stdout,
"broken cell: %p, refc: %ld, stack: %ld, real: %ld\n",
c, c.refcount, c.stackcount, c.drefc)
dec(recGcLock)
proc seqCheck(cell: PCell): bool =
assert(cell.typ != nil)
if cell.typ.kind in {tySequence, tyString}:
result = cell.refcount - cell.stackcount <= 1
else:
result = true
proc decRef(cell: PCell) {.inline.} =
assert(cell in ct.AT)
when defined(debugGC):
if cell.refcount == 0:
writePtr("decref broken", cellToUsr(cell))
assert(cell.refcount > 0) # this should be the case!
assert(seqCheck(cell))
dec(cell.refcount)
if cell.refcount == 0:
incl(ct.zct, cell)
proc incRef(cell: PCell) {.inline.} =
assert(seqCheck(cell))
inc(cell.refcount)
proc asgnRef(dest: ppointer, src: pointer) =
# the code generator calls this proc!
assert(not isOnStack(dest))
# BUGFIX: first incRef then decRef!
if src != nil: incRef(usrToCell(src))
if dest^ != nil: decRef(usrToCell(dest^))
dest^ = src
#assert(checkRefc())
proc unsureAsgnRef(dest: ppointer, src: pointer) =
if not IsOnStack(dest):
if src != nil: incRef(usrToCell(src))
if dest^ != nil: decRef(usrToCell(dest^))
dest^ = src
#assert(checkRefc())
proc restore(cell: PCell) =
if cell notin ct.newAT:
incl(ct.newAT, Cell)
forAllChildren(cell, waCycleIncRef)
proc doOperation(p: pointer, op: TWalkOp) =
if p == nil: return
var cell: PCell = usrToCell(p)
assert(cell != nil)
case op # faster than function pointers because of easy prediction
of waNone: assert(false)
of waRelease: decRef(cell) # DEAD CODE!
of waZctDecRef:
assert(cell.refcount > 0)
assert(seqCheck(cell))
dec(cell.refcount)
if cell.refcount == 0:
incl(ct.newZCT, cell)
of waCycleDecRef:
assert(cell.refcount != 0)
dec(cell.refcount)
of waCycleIncRef:
inc(cell.refcount) # restore proper reference counts!
restore(cell)
of waDebugIncRef:
inc(cell.drefc)
type
TByteArray = array[0..1000_0000, byte]
PByte = ptr TByteArray
PString = ptr string
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp)
proc getDiscriminant(aa: Pointer, n: ptr TNimNode): int =
assert(n.kind == nkCase)
var d: int32
var a = cast[TAddress](aa)
case n.typ.size
of 1: d = toU32(cast[ptr int8](a +% n.offset)^)
of 2: d = toU32(cast[ptr int16](a +% n.offset)^)
of 4: d = toU32(cast[ptr int32](a +% n.offset)^)
else: assert(false)
return int(d)
proc selectBranch(aa: Pointer, n: ptr TNimNode): ptr TNimNode =
var discr = getDiscriminant(aa, n)
if discr <% n.len:
result = n.sons[discr]
if result == nil: result = n.sons[n.len]
# n.sons[n.len] contains the ``else`` part (but may be nil)
else:
result = n.sons[n.len]
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
var
d = cast[TAddress](dest)
case n.kind
of nkNone: assert(false)
of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
of nkList:
for i in 0..n.len-1: forAllSlotsAux(dest, n.sons[i], op)
of nkCase:
var m = selectBranch(dest, n)
if m != nil: forAllSlotsAux(dest, m, op)
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
var
d = cast[TAddress](dest)
if dest == nil: return # nothing to do
case mt.Kind
of tyArray, tyArrayConstr, tyOpenArray:
for i in 0..(mt.size div mt.base.size)-1:
forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
of tyRef, tyString, tySequence: # leaf:
doOperation(cast[ppointer](d)^, op)
of tyRecord, tyObject, tyTuple:
forAllSlotsAux(dest, mt.node, op)
else: nil
proc forAllChildren(cell: PCell, op: TWalkOp) =
assert(cell != nil)
when defined(debugGC):
if cell.typ == nil:
writeCell("cell has no type descriptor", cell)
assert(cell.typ != nil)
case cell.typ.Kind
of tyRef: # common case
forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
of tySequence:
var d = cast[TAddress](cellToUsr(cell))
var s = cast[PGenericSeq](d)
if s != nil: # BUGFIX
for i in 0..s.len-1:
forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +%
GenericSeqSize), cell.typ.base, op)
of tyString: nil
else: assert(false)
proc checkCollection() {.inline.} =
# checks if a collection should be done
if recGcLock == 0:
if memUsed >= rcThreshold or stressGC:
collectCT(ct)
when defined(debugGC):
write(stdout, "threshold is now: ")
writeln(stdout, rcThreshold)
proc newObj(typ: PNimType, size: int): pointer =
# generates a new object and sets its reference counter to 0
var
res: PCell
assert(typ.kind in {tyRef, tyString, tySequence})
# check if we have to collect:
checkCollection()
res = cast[PCell](Alloc0(size + sizeof(TCell)))
if res == nil: raiseOutOfMem()
when defined(nimSize):
memUsed = memUsed + nimSize(res)
else:
memUsed = memUsed + size
res.refcount = 0
# now it is buffered in the ZCT
res.typ = typ
incl(ct.zct, res) # its refcount is zero, so add it to the ZCT
incl(ct.at, res) # add it to the any table too
ct.mask = ct.mask or cast[TAddress](res)
when defined(debugGC):
writeCell("new cell", res)
assert(gcInvariant())
result = cellToUsr(res)
proc newSeq(typ: PNimType, len: int): pointer =
# XXX: overflow checks!
result = newObj(typ, len * typ.base.size + GenericSeqSize)
cast[PGenericSeq](result).len = len
cast[PGenericSeq](result).space = len
proc growObj(old: pointer, newsize: int): pointer =
var
res, ol: PCell
checkCollection()
ol = usrToCell(old)
assert(ol.typ.kind in {tyString, tySequence})
assert(seqCheck(ol))
when defined(nimSize):
memUsed = memUsed - nimSize(ol)
else:
memUsed = memUsed - ol.size # this is not exact
# pity that we don't know the old size
res = cast[PCell](realloc(ol, newsize + sizeof(TCell)))
when defined(nimSize):
memUsed = memUsed + nimSize(res)
else:
memUsed = memUsed + newsize
if res != ol:
if res == nil: raiseOutOfMem()
excl(ct.zct, ol) # remove old pointer in any case:
# It may have a refcount > 0 and is still in the ZCT.
# So do it safe here and remove it anyway.
excl(ct.at, ol)
if res.refcount == 0:
# store new pointer in ZCT, if refcount == 0:
incl(ct.zct, res)
incl(ct.at, res)
ct.mask = ct.mask or cast[TAddress](res)
when defined(debugGC):
writeCell("growObj old cell", ol)
writeCell("growObj new cell", res)
result = cellToUsr(res)
#assert(checkRefc())
proc collectCycles() =
when defined(debugGC):
echo("collecting cycles!\n")
# step 1: pretend that any node is dead
for c in elements(ct.at):
forallChildren(c, waCycleDecRef)
CellSetInit(ct.newAt)
# step 2: restore life cells
for c in elements(ct.at):
if c.refcount > 0: restore(c)
# step 3: free dead cells:
for cell in elements(ct.at):
if cell.refcount == 0:
assert(cell notin ct.zct)
# We free an object that is part of a cycle here. Its children
# may have been freed already. Thus the finalizer could access
# garbage. To handle this case properly we need two passes for
# freeing here which is too expensive. We just don't call the
# finalizer for now. YYY: Any better ideas?
prepareDealloc(cell)
dealloc(cell)
when defined(debugGC):
writeCell("cycle collector dealloc cell", cell)
CellSetDeinit(ct.at)
ct.at = ct.newAt
#ct.newAt = nil
proc gcMark(p: pointer) =
# the addresses are not as objects on the stack, so turn them to objects:
var cell = usrToCell(p)
var c = cast[TAddress](cell)
if ((c and ct.mask) == c) and cell in ct.at:
# is the page that p "points to" in the AT? (All allocated pages are
# always in the AT)
inc(cell.refcount)
inc(cell.stackcount)
addStackCell(ct, cell)
proc unmarkStackAndRegisters() =
for i in 0 .. ct.stackLen-1:
var cell = ct.stackCells[i]
assert(cell.refcount > 0)
when defined(debugGC):
if cell.stackcount == 0:
writeGraph()
writePtr("broken stackcount", cellToUsr(cell))
assert(cell.stackcount > 0)
dec(cell.refcount)
dec(cell.stackcount)
if cell.refcount == 0:
incl(ct.zct, cell)
ct.stackLen = 0 # reset to zero
# ----------------- stack management --------------------------------------
# inspired from Smart Eiffel (c)
proc stackSize(): int =
var stackTop: array[0..1, pointer]
result = abs(cast[int](addr(stackTop[0])) - cast[int](stackBottom))
when defined(sparc): # For SPARC architecture.
proc isOnStack(p: pointer): bool =
var
stackTop: array[0..1, pointer]
result = p >= addr(stackTop[0]) and p <= stackBottom
proc markStackAndRegisters() =
when defined(sparcv9):
asm " flushw"
else:
asm " ta 0x3 ! ST_FLUSH_WINDOWS"
var
max = stackBottom
sp: PPointer
stackTop: array[0..1, pointer]
stackTop[0] = nil
stackTop[1] = nil
sp = addr(stackTop[0])
# Addresses decrease as the stack grows.
while sp <= max:
gcMark(sp^)
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
elif defined(ELATE):
{.error: "stack marking code has to be written for this architecture".}
elif defined(hppa) or defined(hp9000) or defined(hp9000s300) or
defined(hp9000s700) or defined(hp9000s800) or defined(hp9000s820):
# ---------------------------------------------------------------------------
# Generic code for architectures where addresses increase as the stack grows.
# ---------------------------------------------------------------------------
proc isOnStack(p: pointer): bool =
var
stackTop: array[0..1, pointer]
result = p <= addr(stackTop[0]) and p >= stackBottom
var
jmpbufSize {.importc: "sizeof(jmp_buf)".}: int
# a little hack to get the size of a TJmpBuf in the generated C code
# in a platform independant way
proc markStackAndRegisters() =
var
max = stackBottom
registers: C_JmpBuf # The jmp_buf buffer is in the C stack.
sp: PPointer # Used to traverse the stack and registers assuming
# that `setjmp' will save registers in the C stack.
c_setjmp(registers) # To fill the C stack with registers.
sp = cast[ppointer](cast[TAddress](addr(registers)) +%
jmpbufSize -% sizeof(pointer))
# sp will traverse the JMP_BUF as well (jmp_buf size is added,
# otherwise sp would be below the registers structure).
while sp >= max:
gcMark(sp^)
sp = cast[ppointer](cast[TAddress](sp) -% sizeof(pointer))
else:
# ---------------------------------------------------------------------------
# Generic code for architectures where addresses decrease as the stack grows.
# ---------------------------------------------------------------------------
proc isOnStack(p: pointer): bool =
var
stackTop: array [0..1, pointer]
result = p >= addr(stackTop[0]) and p <= stackBottom
proc markStackAndRegisters() =
var
max = stackBottom
registers: C_JmpBuf # The jmp_buf buffer is in the C stack.
sp: PPointer # Used to traverse the stack and registers assuming
# that `setjmp' will save registers in the C stack.
c_setjmp(registers) # To fill the C stack with registers.
sp = cast[ppointer](addr(registers))
while sp <= max:
gcMark(sp^)
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
# ----------------------------------------------------------------------------
# end of non-portable code
# ----------------------------------------------------------------------------
proc CollectZCT =
CellSetInit(ct.newZCT)
for c in elements(ct.zct):
if c.refcount == 0:
# if != 0 the reference count has been increased, so this does not
# belong to the ZCT. We simply do nothing - it won't appear in the newZCT
# anyway.
# We are about to free the object, call the finalizer BEFORE its
# children are deleted as well, because otherwise the finalizer may
# access invalid memory. This is done by prepareDealloc():
prepareDealloc(c)
forAllChildren(c, waZctDecRef)
assert(c.refcount == 0) # should still be zero
excl(ct.at, c)
excl(ct.newZCT, c) # BUGFIX
when defined(debugGC):
writeCell("zct dealloc cell", c)
dealloc(c)
CellSetDeinit(ct.zct)
ct.zct = ct.newZCT
#ct.newZCT = nil
proc collectCT(ct: var TCountTables) =
when defined(debugGC):
c_fprintf(c_stdout, "collecting zero count table; stack size: %ld\n",
stackSize())
markStackAndRegisters()
assert(GC_invariant())
while True:
collectZCT()
if ct.zct.counter == 0: break
# ``counter`` counts the pages, but zero pages means zero cells
when defined(cycleGC):
# still over the cycle threshold?
if memUsed >= cycleThreshold or stressGC:
# collect the cyclic things:
assert(ct.zct.counter == 0)
assert(GC_invariant())
collectCycles()
# recompute the thresholds:
rcThreshold = (memUsed div RC_increase + 1) * RC_Increase
cycleThreshold = memUsed * cycleIncrease
assert(GC_invariant())
unmarkStackAndRegisters()
proc GC_fullCollect() =
var oldThreshold = cycleThreshold
cycleThreshold = 0 # forces cycle collection
collectCT(ct)
cycleThreshold = oldThreshold

51
lib/hti.nim Executable file
View File

@@ -0,0 +1,51 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
type # This should be he same as ast.TTypeKind
# some enum fields are not used at runtime
TNimKind = enum
tyNone, tyBool, tyChar,
tyEmptySet, tyArrayConstr, tyNil, tyRecordConstr,
tyGeneric,
tyGenericInst,
tyGenericParam,
tyEnum, tyAnyEnum,
tyArray,
tyRecord,
tyObject,
tyTuple,
tySet,
tyRange,
tyPtr, tyRef,
tyVar,
tySequence,
tyProc,
tyPointer, tyOpenArray,
tyString, tyCString, tyForward,
tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
tyFloat, tyFloat32, tyFloat64, tyFloat128
TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase
TNimNode {.compilerproc.} = record
kind: TNimNodeKind
offset: int
typ: ptr TNimType
name: Cstring
len: int
sons: ptr array [0..0x7fff, ptr TNimNode]
TNimType {.compilerproc.} = record
size: int
kind: TNimKind
base: ptr TNimType
node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum
finalizer: pointer # the finalizer for the type
PNimType = ptr TNimType
# node.len may be the ``first`` element of a set

70
lib/i386.asm.in Executable file
View File

@@ -0,0 +1,70 @@
; This contains the CPU-dependant variants of some routines.
; (C) 2005 Andreas Rumpf
; This code was inspired by the Freepascal compiler's sources
; All routines here have the _cdecl calling convention because
; that is the only convention any C compiler supports.
\python{
# as usual I use my own preprocessor :-)
import os
def c(name):
if os.name == 'posix':
return name
else:
return "_" + name
}
segment code
global \c{cpu_inc_locked}
global \c{cpu_dec_locked}
global \c{cpu_lock}
global \c{cpu_unlock}
\c{cpu_dec_locked}:
push ebp
mov ebp,esp
mov eax,[ebp+8] ; first parameter to function
lock dec dword [eax]
setz al
mov esp,ebp
pop ebp
ret
\c{cpu_inc_locked}:
push ebp
mov ebp,esp
mov eax,[ebp+8] ; first parameter to function
lock inc dword [eax]
mov esp,ebp
pop ebp
ret
; This code uses the highest bit of the RC to indicate that the RC is
; locked (spinlock).
\c{cpu_lock}
push ebp
mov ebp, esp
mov eax, [ebp+8] ; first parameter to function
mov edx, [eax] ; load RC
or edx, 0x80000000 ; set highest bit
spin:
xchg [eax], edx ; atomic instruction!
pause ; wait a few cycles
and edx, 0x80000000 ; mask highest bit
jnz spin
mov esp, ebp
pop ebp
ret
\c{cpu_unlock}
push ebp
mov ebp, esp
mov eax, [ebp+8] ; first parameter to function
mov edx, [eax] ; load RC
and edx, 0x7FFFFFFF ; unset highest bit
xchg [eax], edx ; atomic instruction!
mov esp, ebp
pop ebp
ret

72
lib/int64s.nim Executable file
View File

@@ -0,0 +1,72 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# 64 bit integers for platforms that don't have those
type
IInt64 = record # "internal" int64
lo, hi: int32
proc cmpI64(x, y: IInt64): int32 {.compilerproc.} =
result = x.hi -% y.hi
if result == 0: result = x.lo -% y.lo
proc addI64(x, y: IInt64): IInt64 {.compilerproc.} =
result = x
result.lo = result.lo +% y.lo
result.hi = result.hi +% y.hi
if y.lo > 0 and result.lo < y.lo:
inc(result.hi)
elif y.lo < 0 and result.lo > y.lo:
dec(result.hi)
proc subI64(x, y: IInt64): IInt64 {.compilerproc.} =
result = x
result.lo = result.lo -% y.lo
result.hi = result.hi -% y.hi
if y.lo > 0 and result.lo < y.lo:
inc(result.hi)
elif y.lo < 0 and result.lo > y.lo:
dec(result.hi)
proc mulI64(x, y: IInt64): IInt64 {.compilerproc.} =
result.lo = x.lo *% y.lo
result.hi = y.hi *% y.hi
if y.lo > 0 and result.lo < y.lo:
inc(result.hi)
elif y.lo < 0 and result.lo > y.lo:
dec(result.hi)
proc divI64(x, y: IInt64): IInt64 {.compilerproc.} =
# XXX: to implement
proc modI64(x, y: IInt64): IInt64 {.compilerproc.} =
# XXX: to implement
proc bitandI64(x, y: IInt64): IInt64 {.compilerproc.} =
result.hi = x.hi and y.hi
result.lo = x.lo and y.lo
proc bitorI64(x, y: IInt64): IInt64 {.compilerproc.} =
result.hi = x.hi or y.hi
result.lo = x.lo or y.lo
proc bitxorI64(x, y: IInt64): IInt64 {.compilerproc.} =
result.hi = x.hi xor y.hi
result.lo = x.lo xor y.lo
proc bitnotI64(x: IInt64): IInt64 {.compilerproc.} =
result.lo = not x.lo
result.hi = not x.hi
proc shlI64(x, y: IInt64): IInt64 {.compilerproc.} =
# XXX: to implement
proc shrI64(x, y: IInt64): IInt64 {.compilerproc.} =
# XXX: to implement

502
lib/lgpl.txt Executable file
View File

@@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

18
lib/locks.nim Executable file
View File

@@ -0,0 +1,18 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# Simple platform dependant lock implementation
type
TSimpleLock = pointer
proc initLock(s: TSimpleLock)
proc deinitLock(s: TSimpleLock)
proc lock(s: TSimpleLock)
proc unlock(s: TSimpleLock)

131
lib/math.nim Executable file
View File

@@ -0,0 +1,131 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# math routines
# interface
{.push debugger:off .} # the user does not want to trace a part
# of the standard library!
{.push checks:off, line_dir:off, stack_trace:off.}
proc nextPowerOfTwo*(x: int): int
## returns the nearest power of two, so that
## result**2 >= x > (result-1)**2.
proc isPowerOfTwo*(x: int): bool {.noSideEffect.}
## returns true, if x is a power of two, false otherwise.
## Negative numbers are not a power of two.
proc countBits*(n: int32): int {.noSideEffect.}
## counts the set bits in `n`.
proc random*(max: int): int
## returns a random number in the range 0..max-1. The sequence of
## random number is always the same, unless `randomize` is called
## which initializes the random number generator with a "random"
## number, i.e. a tickcount.
proc randomize*()
## initializes the random number generator with a "random"
## number, i.e. a tickcount.
proc sqrt*(x: float): float {.importc: "sqrt", header: "<math.h>".}
## computes the square root of `x`.
proc ln*(x: float): float {.importc: "log", header: "<math.h>".}
## computes ln(x).
proc exp*(x: float): float {.importc: "exp", header: "<math.h>".}
## computes e**x.
proc frexp*(x: float, exponent: var int): float {.
importc: "frexp", header: "<math.h>".}
## Split a number into mantissa and exponent.
## `frexp` calculates the mantissa m (a float greater than or equal to 0.5
## and less than 1) and the integer value n such that `x` (the original
## float value) equals m * 2**n. frexp stores n in `exponent` and returns
## m.
proc arccos*(x: float): float {.importc: "acos", header: "<math.h>".}
proc arcsin*(x: float): float {.importc: "asin", header: "<math.h>".}
proc arctan*(x: float): float {.importc: "atan", header: "<math.h>".}
proc arctan2*(y, x: float): float {.importc: "atan2", header: "<math.h>".}
## Calculate the arc tangent of `y` / `x`.
## `atan2` returns the arc tangent of `y` / `x`; it produces correct
## results even when the resulting angle is near pi/2 or -pi/2
## (`x` near 0).
proc cos*(x: float): float {.importc: "cos", header: "<math.h>".}
proc cosh*(x: float): float {.importc: "cosh", header: "<math.h>".}
proc hypot*(x: float): float {.importc: "hypot", header: "<math.h>".}
proc log10*(x: float): float {.importc: "log10", header: "<math.h>".}
proc sinh*(x: float): float {.importc: "sinh", header: "<math.h>".}
proc tan*(x: float): float {.importc: "tan", header: "<math.h>".}
proc tanh*(x: float): float {.importc: "tanh", header: "<math.h>".}
proc pow*(x, y: float): float {.importc: "pos", header: "<math.h>".}
## computes x to power raised of y.
type
TFloatClass* = enum ## describes the class a floating point value belongs to.
## This is the type that is returned by `classify`.
fcNormal, ## value is an ordinary nonzero floating point value
fcSubnormal, ## value is a subnormal (a very small) floating point value
fcZero, ## value is zero
fcNegZero, ## value is the negative zero
fcNan, ## value is Not-A-Number (NAN)
fcInf, ## value is positive infinity
fcNegInf ## value is negative infinity
proc classify*(x: float): TFloatClass
## classifies a floating point value. Returns `x`'s class as specified by
## `TFloatClass`
# implementation
include cntbits
proc nextPowerOfTwo(x: int): int =
result = x - 1
when defined(cpu64):
result = result or (result shr 32)
result = result or (result shr 16)
result = result or (result shr 8)
result = result or (result shr 4)
result = result or (result shr 2)
result = result or (result shr 1)
Inc(result)
# C procs:
proc gettime(dummy: ptr cint): cint {.
importc: "time", header: "<time.h>".}
proc srand(seed: cint) {.
importc: "srand", nodecl.}
proc rand(): cint {.importc: "rand", nodecl.}
# most C compilers have no classify:
proc classify(x: float): TFloatClass =
if x == 0.0:
if 1.0/x == 1.0/0.0:
return fcZero
else:
return fcNegZero
if x*0.5 == x:
if x > 0.0: return fcInf
else: return fcNegInf
if x != x: return fcNan
return fcNormal
# XXX: fcSubnormal is not detected!
proc randomize() = srand(gettime(nil))
proc random(max: int): int = return rand() mod max
proc isPowerOfTwo(x: int): bool = return (x and -x) == x
{.pop.}
{.pop.}

599
lib/memman.nim Executable file
View File

@@ -0,0 +1,599 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# Memory manager. Based on:
# Two Levels Segregate Fit memory allocator (TLSF)
# Version 2.4.2
#
# Written by Miguel Masmano Tello <mimastel@doctor.upv.es>
#
# Thanks to Ismael Ripoll for his suggestions and reviews
#
# Copyright (C) 2008, 2007, 2006, 2005, 2004
#
# This code is released using a dual license strategy: GPL/LGPL
# You can choose the licence that better fits your requirements.
#
# Released under the terms of the GNU General Public License Version 2.0
# Released under the terms of the GNU Lesser General Public License Version 2.1
# Some IMPORTANT TLSF parameters
const
blockAlign = sizeof(pointer) * 2
maxFli = 30
maxLog2Sli = 5
maxSli = 1 shl maxLog2Sli
fliOffset = 6 # tlsf structure just will manage blocks bigger than 128 bytes
smallBlock = 128
realFli = MaxFli - fliOffset
type
TFreePtr = record
prev, next: PBhdr
Pbhdr = ptr Tbhdr
Tbhdr = record
prevHdr: Pbhdr # this is just valid if the first bit of size is set
size: int # the size is stored in bytes
# bit 0 indicates whether the block is used and
# bit 1 allows to know whether the previous block is free
freePtr: TFreePtr # at this offset bhdr.buffer starts (was a union in the
# C version)
TAreaInfo = record # This structure is embedded at the beginning of each
# area, giving us enough information to cope with a set
# of areas
theEnd: Pbhdr
next: PAreaInfo
PAreaInfo = ptr TAreaInfo
TLSF = record
tlsf_signature: int32 # the TLSF's structure signature
usedSize, maxSize: int
areaHead: PAreaInfo # A linked list holding all the existing areas
flBitmap: int32 # the first-level bitmap
# This array should have a size of REAL_FLI bits
slBitmap: array[0..realFli, int32] # the second-level bitmap
matrix: array [0..realFli, array[0..maxSli, PBhdr]]
const
minBlockSize = sizeof(TFreePtr)
bhdrOverhead = sizeof(Tbhdr) - minBlockSize
tlsfSignature = 0x2A59FA59
ptrMask = sizeof(pointer) - 1
blockSize = 0xFFFFFFFF - ptrMask
memAlign = blockAlign - 1
blockState = 0x1
prevState = 0x2
freeBlock = 0x1 # bit 0 of the block size
usedBlock = 0x0
prevFree = 0x2 # bit 1 of the block size
prevUsed = 0x0
defaultAreaSize = 64*1024 # 1024*10
pageSize = if defined(cpu32): 4096 else: 4096*2
proc getNextBlock(adr: pointer, r: int): PBhdr {.inline.} =
return cast[PBhdr](cast[TAddress](adr) +% r)
proc roundupSize(r: int): int = return (r +% memAlign) and not memAlign
proc rounddownSize(r: int): int = return r and not memAlign
proc roundup(x, v: int): int = return (((not x)+%1) and (v-%1)) +% x
proc addSize(s: PTLSF, b: Pbhdr) =
inc(s.usedSize, (b.size and blockSize) + bhdrOverhead)
s.maxSize = max(s.maxSize, s.usedSize)
proc removeSize(s: PTLSF, b: Pbhdr) =
dec(s.usedSize, (b.size and blockSize) + bhdrOverhead)
# ------------ platform specific code -----------------------------------------
when defined(posix):
const # XXX: make these variables for portability?
PROT_READ = 1 # page can be read
PROT_WRITE = 2 # page can be written
PROT_EXEC = 4 # page can be executed
PROT_NONE = 0 # page can not be accessed
MAP_SHARED = 1 # Share changes
MAP_PRIVATE = 2 # Changes are private
MAP_TYPE = 0xf # Mask for type of mapping
MAP_FIXED = 0x10 # Interpret addr exactly
MAP_ANONYMOUS = 0x20 # don't use a file
MAP_GROWSDOWN = 0x100 # stack-like segment
MAP_DENYWRITE = 0x800 # ETXTBSY
MAP_EXECUTABLE = 0x1000 # mark it as an executable
MAP_LOCKED = 0x2000 # pages are locked
MAP_NORESERVE = 0x4000 # don't check for reservations
proc mmap(adr: pointer, len: int, prot, flags, fildes: cint,
off: int): pointer {.header: "<sys/mman.h>".}
proc getNewArea(size: var int): pointer {.inline.} =
size = roundup(size, PageSize)
result = mmap(0, size, PROT_READ or PROT_WRITE,
MAP_PRIVATE or MAP_ANONYMOUS, -1, 0)
if result == nil or result == cast[pointer](-1):
raiseOutOfMem()
elif defined(windows):
const
MEM_RESERVE = 0x2000
MEM_COMMIT = 0x1000
MEM_TOP_DOWN = 0x100000
PAGE_READWRITE = 0x04
proc VirtualAlloc(lpAddress: pointer, dwSize: int, flAllocationType,
flProtect: int32): pointer {.
header: "<windows.h>", stdcall.}
proc getNewArea(size: var int): pointer {.inline.} =
size = roundup(size, PageSize)
result = VirtualAlloc(nil, size, MEM_RESERVE or MEM_COMMIT or MEM_TOP_DOWN,
PAGE_READWRITE)
if result == nil: raiseOutOfMem()
else:
# generic implementation relying on malloc:
proc malloc(size: int): pointer {.nodecl, importc.}
proc getNewArea(size: var int): pointer {.inline.} =
size = roundup(size, PageSize)
result = malloc(size)
if result == nil: raiseOutOfMem()
# ----------------------------------------------------------------------------
# helpers
const
table: array[0..255, int8] = [
-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7
]
proc ls_bit(i: int32): int {.inline.} =
var
a: int = 0
x: int = i and -i
if x <=% 0xffff:
if x <=% ff: a = 0
else: a = 8
elif x <=% 0xffffff: a = 16
else: a = 24
return table[x shr a] + a
proc ms_bit(i: int): int {.inline.} =
var
a = if i <=% 0xffff: (if i <=% 0xff: 0 else: 8) elif
i <=% 0xffffff: 16 else: 24
return table[i shr a] + a
proc set_bit[IX](nr: int, adr: var array[IX, int32]) {.inline.} =
adr[nr shr 5] = adr[nr shr 5] or (1 shl (nr and 0x1f))
proc clear_bit[IX](nr: int, adr: var array[IX, int32]) {.inline.} =
adr[nr shr 5] = adr[nr shr 5] and not (1 shl (nr and 0x1f))
proc mappingSearch(r, fl, sl: var int) {.inline.} =
if r < smallBlock:
fl = 0
sl = r div (smallBlock div maxSli)
else:
var t = (1 shl (ms_bit(r) - maxLog2Sli)) - 1
r = r + t
fl = ms_bit(r)
sl = (r shl (fl - maxLog2Sli)) - maxSli
fl = fl - fliOffset
r = r and not t
proc mappingInsert(r: int, fl, sl: var int) {.inline.} =
if r < smallBlock:
fl = 0
sl = r div (smallBlock div maxSli)
else:
fl = ms_bit(r)
sl = (r shr (fl - maxLog2Sli)) - maxSli
fl = fl - fliOffset
proc findSuitableBlock(t: var TLSF, fl, sl: var int): Pbhdr =
var tmp = t.slBitmap[fl] and ((not 0) shl sl)
if tmp != 0:
sl = ls_bit(tmp)
result = t.matrix[fl][sl]
else:
fl = ls_bit(t.flBitmap and (not 0 shl (fl + 1)))
if fl > 0: # likely
sl = ls_bit(t.slBitmap[fl])
result = t.matrix[fl][sl]
proc extractBlockHdr(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} =
t.matrix[fl][sl] = b.freePtr.next
if t.matrix[fl][sl] != 0:
t.matrix[fl][sl].freePtr.prev = nil
else:
clear_bit(sl, t.slBitmap[fl])
if t.slBitmap[fl] == 0:
clear_bit(fl, t.flBitmap)
b.freePtr.prev = nil
b.freePtr.next = nil
proc extractBlock(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} =
if b.freePtr.next != nil:
b.freePtr.next.freePtr.prev = b.freePtr.prev
if b.freePtr.prev != nil:
b.freePtr.prev.freePtr.next = b.freePtr.next
if t.matrix[fl][sl] == b:
t.matrix[fl][sl] = b.freePtr.next
if t.matrix[fl][sl] == nil:
clear_bit(sl, t.slBitmap[fl])
if t.slBitmap[fl] == 0:
clear_bit(fl, t.flBitmap)
b.freePtr.prev = nil
b.freePtr.next = nil
proc insertBlock(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} =
b.freePtr.prev = nil
b.freePtr.next = t.matrix[fl][sl]
if t.matrix[fl][sl] != 0:
t.matrix[fl][sl].freePtr.prev = b
t.matrix[fl][sl] = b
set_bit(sl, t.slBitmap[fl])
set_bit(fl, t.flBitmap)
proc getBuffer(b: Pbhdr): pointer {.inline.} =
result = cast[pointer](addr(b.freePtr))
proc processArea(area: pointer, size: int): Pbhdr =
var
b, lb, ib: Pbhdr
ai: PAreaInfo
ib = cast[Pbhdr](area)
if sizeof(TAreaInfo) < minBlockSize:
ib.size = minBlockSize or usedBlock or prevUsed
else
ib.size = roundupSize(sizeof(TAreaInfo)) or usedBlock or prevUsed
b = getNextBlock(getBuffer(ib), ib.size and blockSize)
b.size = rounddownSize(size - 3 * bhdrOverhead - (ib.size and blockSize)) or
usedBlock or prevUsed
b.freePtr.prev = nil
b.freePtr.next = nil
lb = getNextBlock(getBuffer(b), b.size and blockSize)
lb.prevHdr = b
lb.size = 0 or usedBlock or prevFree
ai = cast[PAreaInfo](getBuffer(ib))
ai.next = nil
ai.theEnd = lb
return ib
# ----------------------------------------------------------------------------
# Begin of the allocator code
var
mp: pointer # default memory pool.
proc initMemoryPool(memPoolSize: int, memPool: pointer): int =
var
t: PLSF
b, ib: Pbhdr
if memPool == nil or memPoolSize < sizeof(TLSF) + bhdrOverhead * 8:
writeToStdErr("initMemoryPool(): memory_pool invalid\n")
return -1
if (memPool and ptrMask) != 0:
writeToStdErr("initMemoryPool(): memPool must be aligned to a word\n")
return -1
t = cast[PLSF](memPool)
# Check if already initialised
if t.signature == tlsfSignature:
mp = memPool
b = getNextBlock(mp, roundupSize(sizeof(TLSF)))
return b.size and blockSize
mp = memPool
zeroMem(memPool, sizeof(TLSF))
t.signature = tlsfSignature
ib = processArea(getNextBlock(memPool, roundupSize(sizeof(TLSF))),
rounddownSize(memPoolSize - sizeof(TLSF)))
b = getNextBlock(getBuffer(ib), ib.size and blockSize)
freeEx(getBuffer(b), t)
t.areaHead = cast[PAreaInfo](getBuffer(ib))
t.used_size = memPoolSize - (b.size and blockSize)
t.max_size = t.used_size
return b.size and blockSize
proc addNewArea(area: pointer, areaSize: int, t: var TLSF): int =
var
p, ptrPrev, ai: PAreaInfo
ib0, b0, lb0, ib1, b1, lb1, nextB: Pbhdr
zeroMem(area, areaSize)
p = t.areaHead
ptrPrev = 0
ib0 = processArea(area, areaSize)
b0 = getNextBlock(getBuffer(ib0), ib0.size and blockSize)
lb0 = getNextBlock(getBuffer(b0), b0.size and blockSize)
# Before inserting the new area, we have to merge this area with the
# already existing ones
while p != nil:
ib1 = cast[Pbhdr](cast[TAddress](p) -% bhdrOverhead)
b1 = getNextBlock(getBuffer(ib1), ib1.size and blockSize)
lb1 = p.theEnd
# Merging the new area with the next physically contigous one
if cast[TAddress](ib1) == cast[TAddress](lb0) +% bhdrOverhead:
if t.areaHead == p:
t.areaHead = p.next
p = p.next
else:
ptrPrev.next = p.next
p = p.next
b0.size = rounddownSize((b0.size and blockSize) +
(ib1.size and blockSize) + 2 * bhdrOverhead) or
usedBlock or prevUsed
b1.prevHdr = b0
lb0 = lb1
continue
# Merging the new area with the previous physically contigous one
if getBuffer(lb1) == pointer(ib0):
if t.areaHead == p:
t.areaHead = p.next
p = p.next
else:
ptrPrev.next = p.next
p = p.next
lb1->size = rounddownSize((b0.size and blockSize) +
(ib0.size and blockSize) + 2 * bhdrOverhead) or
usedBlock or (lb1.size and prevState)
nextB = getNextBlock(getBuffer(lb1), lb1.size and blockSize)
nextB.prevHdr = lb1
b0 = lb1
ib0 = ib1
continue
ptrPrev = p
p = p.next
# Inserting the area in the list of linked areas
ai = cast[PAreaInfo](getBuffer(ib0))
ai.next = t.areaHead
ai.theEnd = lb0
t.areaHead = ai
freeEx(getBuffer(b0), memPool)
return (b0.size and blockSize)
proc mallocEx(asize: int, t: var TLSF): pointer =
var
b, b2, nextB: Pbhdr
fl, sl, tmpSize, size: int
size = if asize < minBlockSize: minBlockSize else: roundupSize(asize)
# Rounding up the requested size and calculating fl and sl
mappingSearch(size, fl, sl)
# Searching a free block, recall that this function changes the values
# of fl and sl, so they are not longer valid when the function fails
b = findSuitableBlock(tlsf, fl, sl)
if b == nil:
# Growing the pool size when needed
# size plus enough room for the required headers:
var areaSize = max(size + bhdrOverhead * 8, defaultAreaSize)
var area = getNewArea(areaSize)
addNewArea(area, areaSize, t)
# Rounding up the requested size and calculating fl and sl
mappingSearch(size, fl, sl)
# Searching a free block
b = findSuitableBlock(t, fl, sl)
if b == nil:
raiseOutOfMem()
extractBlockHdr(b, t, fl, sl)
#-- found:
nextB = getNextBlock(getBuffer(b), b.size and blockSize)
# Should the block be split?
tmpSize = (b.size and blockSize) - size
if tmpSize >= sizeof(Tbhdr):
dec(tmpSize, bhdrOverhead)
b2 = getNextBlock(getBuffer(b), size)
b2.size = tmpSize or freeBlock or prevUsed
nextB.prevHdr = b2
mappingInsert(tmpSize, fl, sl)
insertBlock(b2, t, fl, sl)
b.size = size or (b.size and prevState)
else:
nextB.size = nextB.size and not prevFree
b.size = b.size and not freeBlock # Now it's used
addSize(t, b)
return getBuffer(b)
proc freeEx(p: pointer, t: var TLSF) =
var
fl = 0
sl = 0
b, tmpB: Pbhdr
assert(p != nil)
b = cast[Pbhdr](cast[TAddress](p) -% bhdrOverhead)
b.size = b.size or freeBlock
removeSize(t, b)
b.freePtr.prev = nil
b.freePtr.next = nil
tmpB = getNextBlock(getBuffer(b), b.size and blockSize)
if tmpB.size and freeBlock != 0:
mappingInsert(tmpB.size and blockSize, fl, sl)
extractBlock(tmpB, t, fl, sl)
inc(b.size, (tmpB.size and blockSize) + bhdrOverhead)
if (b.size and prevFree) != 0:
tmpB = b.prevHdr
mappingInsert(tmpB.size and blockSize, fl, sl)
extractBlock(tmpB, t, fl, sl)
inc(tmpB.size, (b.size and blockSize) + bhdrOverhead)
b = tmpB
mappingInsert(b.size and blockSize, fl, sl)
insertBlock(b, t, fl, sl)
tmpB = getNextBlock(getBuffer(b), b.size and blockSize)
tmpB.size = tmpB.size or prevFree
tmpB.prevHdr = b
proc reallocEx(p: pointer, newSize: int, t: var TLSF): pointer =
var
cpsize, fl, sl, tmpSize: int
b, tmpB, nextB: Pbhdr
assert(p != nil)
assert(newSize > 0)
b = cast[Pbhdr](cast[TAddress](p) -% bhdrOverhead)
nextB = getNextBlock(getBuffer(b), b.size and blockSize)
newSize = if newSize < minBlockSize: minBlockSize else: roundupSize(newSize)
tmpSize = b.size and blockSize
if newSize <= tmpSize:
removeSize(t, b)
if (nextB.size and freeBlock) != 0:
mappingInsert(nextB.size and blockSize, fl, sl)
extractBlock(nextB, t, fl, sl)
inc(tmpSize, (nextB.size and blockSize) + bhdrOverhead)
nextB = getNextBlock(getBuffer(nextB), nextB.size and blockSize)
# We always reenter this free block because tmpSize will
# be greater then sizeof(Tbhdr)
dec(tmpSize, newSize)
if tmpSize >= sizeof(Tbhdr):
dec(tmpSize, bhdrOverhead)
tmpB = getNextBlock(getBuffer(b), newSize)
tmpB.size = tmpSize or freeBlock or prevUsed
nextB.prevHdr = tmpB
nextB.size = nextB.size or prevFree
mappingInsert(tmpSize, fl, sl)
insertBlock(tmpB, t, fl, sl)
b.size = newSize or (b.size and prevState)
addSize(t, b)
return getBuffer(b)
if (nextB.size and freeBlock) != 0:
if newSize <= tmpSize + (nextB.size and blockSize):
removeSize(t, b)
mappingInsert(nextB.size and blockSize, fl, sl)
extractBlock(nextB, t, fl, sl)
inc(b.size, (nextB.size and blockSize) + bhdrOverhead)
nextB = getNextBlock(getBuffer(b), b.size and blockSize)
nextB.prevHdr = b
nextB.size = nextB.size and not prevFree
tmpSize = (b.size and blockSize) - newSize
if tmpSize >= sizeof(Tbhdr):
dec(tmpSize, bhdrOverhead)
tmpB = getNextBlock(getBuffer(b), newSize)
tmpB.size = tmpSize or freeBlock or prevUsed
nextB.prevHdr = tmpB
nextB.size = nextB.size or prevFree
mappingInsert(tmpSize, fl, sl)
insertBlock(tmpB, t, fl, sl)
b.size = newSize or (b.size and prevState)
addSize(t, b)
return getBuffer(b)
var ptrAux = mallocEx(newSize, t)
cpsize = if (b.size and blockSize) > newSize: newSize else:
(b.size and blockSize)
copyMem(ptrAux, p, cpsize)
freeEx(p, memPool)
return ptrAux
proc ansiCrealloc(p: pointer, newSize: int, t: var TLSF): pointer =
if p == nil:
if newSize > 0:
result = mallocEx(newSize, t)
else:
result = nil
elif newSize <= 0:
freeEx(p, t)
result = nil
else:
result = reallocEx(p, newSize, t)
void *tlsf_malloc(size_t size)
{
void *ret
#if USE_MMAP || USE_SBRK
if (!mp) {
size_t areaSize
void *area
areaSize = sizeof(tlsf_t) + BHDR_OVERHEAD * 8 # Just a safety constant
areaSize = (areaSize > DEFAULT_areaSize) ? areaSize : DEFAULT_areaSize
area = get_new_area(&areaSize)
if (area == ((void *) ~0))
return NULL # Not enough system memory
initMemoryPool(areaSize, area)
}
#endif
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock)
ret = malloc_ex(size, mp)
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock)
return ret
}
void tlsf_free(void *p)
{
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock)
free_ex(p, mp)
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock)
}
void *tlsf_realloc(void *p, size_t size)
{
void *ret
#if USE_MMAP || USE_SBRK
if (!mp) {
return tlsf_malloc(size)
}
#endif
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock)
ret = realloc_ex(p, size, mp)
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock)
return ret
}

403
lib/nimbase.h Executable file
View File

@@ -0,0 +1,403 @@
/*
Nimrod's Runtime Library
(c) Copyright 2006 Andreas Rumpf
See the file "copying.txt", included in this
distribution, for details about the copyright.
*/
#ifndef NIMBASE_H
#define NIMBASE_H
/* calling convention mess ----------------------------------------------- */
#if defined(__GNUC__) || defined(__LCC__) || defined(__POCC__)
/* these should support C99's inline */
/* the test for __POCC__ has to come before the test for _MSC_VER,
because PellesC defines _MSC_VER too. This is brain-dead. */
# define N_INLINE(rettype, name) inline rettype name
#elif defined(__BORLANDC__) || defined(_MSC_VER)
/* Borland's compiler is really STRANGE here; note that the __fastcall
keyword cannot be before the return type, but __inline cannot be after
the return type, so we do not handle this mess in the code generator
but rather here. */
# define N_INLINE(rettype, name) __inline rettype name
#elif defined(__DMC__)
# define N_INLINE(rettype, name) inline rettype name
#elif defined(__WATCOMC__)
# define N_INLINE(rettype, name) __inline rettype name
#else /* others are less picky: */
# define N_INLINE(rettype, name) rettype __inline name
#endif
#if defined(_MSC_VER)
# define HAVE_LRINT 1
#endif
/* --------------- how int64 constants should be declared: ----------- */
#if defined(__GNUC__) || defined(__LCC__) || \
defined(__POCC__) || defined(__DMC__)
# define IL64(x) x##LL
#else /* works only without LL */
# define IL64(x) x
#endif
/* ------------------------------------------------------------------- */
#if defined(WIN32) || defined(_WIN32) /* only Windows has this mess... */
# define N_CDECL(rettype, name) rettype __cdecl name
# define N_STDCALL(rettype, name) rettype __stdcall name
# define N_SYSCALL(rettype, name) rettype __syscall name
# define N_FASTCALL(rettype, name) rettype __fastcall name
# define N_SAFECALL(rettype, name) rettype __safecall name
/* function pointers with calling convention: */
# define N_CDECL_PTR(rettype, name) rettype (__cdecl *name)
# define N_STDCALL_PTR(rettype, name) rettype (__stdcall *name)
# define N_SYSCALL_PTR(rettype, name) rettype (__syscall *name)
# define N_FASTCALL_PTR(rettype, name) rettype (__fastcall *name)
# define N_SAFECALL_PTR(rettype, name) rettype (__safecall *name)
# define N_LIB_EXPORT __declspec(dllexport)
# define N_LIB_IMPORT __declspec(dllimport)
#else
# define N_CDECL(rettype, name) rettype name
# define N_STDCALL(rettype, name) rettype name
# define N_SYSCALL(rettype, name) rettype name
# define N_FASTCALL(rettype, name) rettype name
# define N_SAFECALL(rettype, name) rettype name
/* function pointers with calling convention: */
# define N_CDECL_PTR(rettype, name) rettype (*name)
# define N_STDCALL_PTR(rettype, name) rettype (*name)
# define N_SYSCALL_PTR(rettype, name) rettype (*name)
# define N_FASTCALL_PTR(rettype, name) rettype (*name)
# define N_SAFECALL_PTR(rettype, name) rettype (*name)
# define N_LIB_EXPORT
# define N_LIB_IMPORT extern
#endif
#define N_NOCONV(rettype, name) rettype name
/* specify no calling convention */
#define N_NOCONV_PTR(rettype, name) rettype (*name)
#define N_CLOSURE(rettype, name) rettype name
/* specify no calling convention */
#define N_CLOSURE_PTR(rettype, name) rettype (*name)
#if defined(__BORLANDC__) || defined(__WATCOMC__) || \
defined(__POCC__) || defined(_MSC_VER)
/* these compilers have a fastcall so use it: */
# define N_NIMCALL(rettype, name) rettype __fastcall name
# define N_NIMCALL_PTR(rettype, name) rettype (__fastcall *name)
#else
# define N_NIMCALL(rettype, name) rettype name /* no modifier */
# define N_NIMCALL_PTR(rettype, name) rettype (*name)
#endif
/* ----------------------------------------------------------------------- */
/* from float_cast.h: */
/*
** Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
**
** Permission to use, copy, modify, distribute, and sell this file for any
** purpose is hereby granted without fee, provided that the above copyright
** and this permission notice appear in all copies. No representations are
** made about the suitability of this software for any purpose. It is
** provided "as is" without express or implied warranty.
*/
/* Version 1.1 */
/*============================================================================
** On Intel Pentium processors (especially PIII and probably P4), converting
** from float to int is very slow. To meet the C specs, the code produced by
** most C compilers targeting Pentium needs to change the FPU rounding mode
** before the float to int conversion is performed.
**
** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
** is this flushing of the pipeline which is so slow.
**
** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
** llrint and llrintf which fix this problem as a side effect.
**
** On Unix-like systems, the configure process should have detected the
** presence of these functions. If they weren't found we have to replace them
** here with a standard C cast.
*/
/*
** The C99 prototypes for lrint and lrintf are as follows:
**
** long int lrintf (float x);
** long int lrint (double x);
*/
#if defined(__LCC__) || defined(__POCC__) \
|| (defined(__GNUC__) && defined(WIN32))
/* Linux' GCC does not seem to have these. Why? */
# define HAVE_LRINT
# define HAVE_LRINTF
#endif
#if defined(HAVE_LRINT) && defined(HAVE_LRINTF)
/* These defines enable functionality introduced with the 1999 ISO C
** standard. They must be defined before the inclusion of math.h to
** engage them. If optimisation is enabled, these functions will be
** inlined. With optimisation switched off, you have to link in the
** maths library using -lm.
*/
# define _ISOC9X_SOURCE 1
# define _ISOC99_SOURCE 1
# define __USE_ISOC9X 1
# define __USE_ISOC99 1
# include <math.h>
#elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
&& !defined(__BORLANDC__)
# include <math.h>
/* Win32 doesn't seem to have these functions.
** Therefore implement inline versions of these functions here.
*/
static N_INLINE(long int, lrint)(double flt) {
long int intgr;
_asm {
fld flt
fistp intgr
};
return intgr;
}
static N_INLINE(long int, lrintf)(float flt) {
long int intgr;
_asm {
fld flt
fistp intgr
};
return intgr;
}
#else
# include <math.h>
# ifndef lrint
# define lrint(dbl) ((long int)(dbl))
# endif
# ifndef lrintf
# define lrintf(flt) ((long int)(flt))
# endif
#endif /* defined(HAVE_LRINT) && defined(HAVE_LRINTF) */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <stddef.h>
#include <signal.h>
#include <setjmp.h>
/* compiler symbols:
__BORLANDC__
_MSC_VER
__WATCOMC__
__LCC__
__GNUC__
__DMC__
__POCC__
*/
/* C99 compiler? */
#if (defined(__STD_VERSION__) && (__STD_VERSION__ >= 199901))
# define HAVE_STDINT_H
#endif
#if defined(__LCC__) || defined(__GNUC__) || defined(__DMC__) \
|| defined(__POCC__)
# define HAVE_STDINT_H
#endif
/* bool types (C++ has it): */
#ifdef __cplusplus
# ifndef NIM_TRUE
# define NIM_TRUE true
# endif
# ifndef NIM_FALSE
# define NIM_FALSE false
# endif
# define NIM_BOOL bool
#else
# ifdef bool
# define NIM_BOOL bool
# else
typedef unsigned char NIM_BOOL;
# endif
# ifndef NIM_TRUE
# define NIM_TRUE ((NIM_BOOL) 1)
# endif
# ifndef NIM_FALSE
# define NIM_FALSE ((NIM_BOOL) 0)
# endif
#endif
#define NIM_NIL ((void*)0) /* C's NULL is fucked up in some C compilers, so
the generated code does not rely on it anymore */
#if defined(HAVE_STDINT_H)
# include <stdint.h>
typedef int8_t NS8;
typedef int16_t NS16;
typedef int32_t NS32;
typedef int64_t NS64;
typedef uint64_t NU64;
typedef uint8_t NU8;
typedef uint16_t NU16;
typedef uint32_t NU32;
#elif defined(__BORLANDC__) || defined(__DMC__) \
|| defined(__WATCOMC__) || defined(_MSC_VER)
typedef signed char NS8;
typedef signed short int NS16;
typedef signed int NS32;
/* XXX: Float128? */
typedef unsigned char NU8;
typedef unsigned short int NU16;
typedef unsigned __int64 NU64;
typedef __int64 NS64;
typedef unsigned int NU32;
#else
typedef signed char NS8;
typedef signed short int NS16;
typedef signed int NS32;
/* XXX: Float128? */
typedef unsigned char NU8;
typedef unsigned short int NU16;
typedef unsigned long long int NU64;
typedef long long int NS64;
typedef unsigned int NU32;
#endif
#if defined(_MSC_VER) && (defined(AMD64) || defined(_M_AMD64))
/* Microsoft C is brain-dead in this case; long is still not an int64 */
typedef unsigned long long int NU;
typedef signed long long int NS;
#else
typedef unsigned long int NU; /* note: int would be wrong for AMD64 */
typedef signed long int NS;
#endif
typedef float NF32;
typedef double NF64;
typedef double NF;
typedef char NIM_CHAR;
typedef char* NCSTRING;
#ifdef NIM_BIG_ENDIAN
# define NIM_IMAN 1
#else
# define NIM_IMAN 0
#endif
static N_INLINE(NS32, float64ToInt32)(double val) {
val = val + 68719476736.0*1.5;
/* 2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor */
return ((NS32*)&val)[NIM_IMAN] >> 16; /* 16.16 fixed point representation */
}
static N_INLINE(NS32, float32ToInt32)(float val) {
return float64ToInt32((double)val);
}
#define zeroMem(a, size) memset(a, 0, size)
#define equalMem(a, b, size) (memcmp(a, b, size) == 0)
#define STRING_LITERAL(name, str, length) \
static const struct { \
NS len, space; \
NIM_CHAR data[length + 1]; \
} name = {length, length, str}
typedef struct TStringDesc* string;
/* declared size of a sequence: */
#if defined(__GNUC__)
# define SEQ_DECL_SIZE /* empty is correct! */
#else
# define SEQ_DECL_SIZE 1000000
#endif
#define ALLOC_0(size) calloc(1, size)
#define DL_ALLOC_0(size) dlcalloc(1, size)
#define GenericSeqSize sizeof(TGenericSeq)
#define paramCount() cmdCount
#ifndef NAN
# define NAN (0.0 / 0.0)
#endif
#ifndef INF
# ifdef INFINITY
# define INF INFINITY
# elif defined(HUGE_VAL)
# define INF HUGE_VAL
# else
# define INF (1.0 / 0.0)
# endif
#endif
/*
typedef struct TSafePoint TSafePoint;
struct TSafePoint {
NS exc;
NCSTRING excname;
NCSTRING msg;
TSafePoint* prev;
jmp_buf context;
}; */
typedef struct TFrame TFrame;
struct TFrame {
TFrame* prev;
NCSTRING procname;
NS line;
NCSTRING filename;
NS len;
};
extern TFrame* volatile framePtr;
/*extern TSafePoint* volatile excHandler; */
#if defined(__cplusplus)
struct NimException {
TSafePoint sp;
NimException(NS aExc, NCSTRING aExcname, NCSTRING aMsg) {
sp.exc = aExc; sp.excname = aExcname; sp.msg = aMsg;
sp.prev = excHandler;
excHandler = &sp;
}
};
#endif
typedef struct TStringDesc {
NS len;
NS space;
NIM_CHAR data[1]; /* SEQ_DECL_SIZE]; */
} TStringDesc;
typedef struct {
NS len, space;
} TGenericSeq;
typedef TGenericSeq* PGenericSeq;
#endif

39
lib/optparse.nim Executable file
View File

@@ -0,0 +1,39 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module provides a command line parser.
## It supports one iterator over all command line options.
#interface
{.push debugger: off.}
import
os
proc findSep(s: string): int {.nostatic.} =
for i in 0 .. high(s)-1:
if s[i] in {'=', ':'}: return i
return high(s)+1
iterator getopt*(): tuple[string, string] =
# returns a (cmd, arg) tuple.
for k in 1 .. ParamCount():
var param = paramStr(k)
if param[0] == '-':
var j = findSep(param)
cmd = copy(param, 0, j-1)
arg = copy(param, j+1)
else:
cmd = ""
arg = param
yield cmd, arg
{.pop.}

939
lib/os.nim Executable file
View File

@@ -0,0 +1,939 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Basic operating system facilities like retrieving environment variables,
## reading command line arguments, working with directories, running shell
## commands, etc. This module is -- like any other basic library --
## platform independant.
{.push debugger:off.}
import
strutils, times
# copied from excpt.nim, because I don't want to make this template public
template newException(exceptn, message: expr): expr =
block: # open a new scope
var
e: ref exceptn
new(e)
e.msg = message
e
when defined(windows) or defined(OS2) or defined(DOS):
{.define: doslike.} # DOS-like filesystem
when defined(Nimdoc): # only for proper documentation:
const
CurDir* = '.'
## The constant string used by the operating system to refer to the
## current directory.
##
## For example: '.' for POSIX or ':' for the classic Macintosh.
ParDir* = ".."
## The constant string used by the operating system to refer to the parent
## directory.
##
## For example: ".." for POSIX or "::" for the classic Macintosh.
DirSep* = '/'
## The character used by the operating system to separate pathname
## components, for example, '/' for POSIX or ':' for the classic
## Macintosh.
##
## Note that knowing this is not sufficient to be able to parse or
## concatenate pathnames -- use `splitPath` and `joinPath` instead --
## but it is occasionally useful.
AltSep* = '/'
## An alternative character used by the operating system to separate
## pathname components, or the same as `DirSep` if only one separator
## character exists. This is set to '/' on Windows systems where `DirSep`
## is a backslash.
PathSep* = ':'
## The character conventionally used by the operating system to separate
## search patch components (as in PATH), such as ':' for POSIX or ';' for
## Windows.
FileSystemCaseSensitive* = True
## True if the file system is case sensitive, false otherwise. Used by
## `cmpPaths` to compare filenames properly.
elif defined(macos):
const
curdir* = ':'
pardir* = "::"
dirsep* = ':'
altsep* = dirsep
pathsep* = ','
FileSystemCaseSensitive* = false
# MacOS paths
# ===========
# MacOS directory separator is a colon ":" which is the only character not
# allowed in filenames.
#
# A path containing no colon or which begins with a colon is a partial path.
# E.g. ":kalle:petter" ":kalle" "kalle"
#
# All other paths are full (absolute) paths. E.g. "HD:kalle:" "HD:"
# When generating paths, one is safe if one ensures that all partial paths
# begin with a colon, and all full paths end with a colon.
# In full paths the first name (e g HD above) is the name of a mounted
# volume.
# These names are not unique, because, for instance, two diskettes with the
# same names could be inserted. This means that paths on MacOS is not
# waterproof. In case of equal names the first volume found will do.
# Two colons "::" are the relative path to the parent. Three is to the
# grandparent etc.
elif defined(doslike):
const
curdir* = '.'
pardir* = ".."
dirsep* = '\\' # seperator within paths
altsep* = '/'
pathSep* = ';' # seperator between paths
FileSystemCaseSensitive* = false
elif defined(PalmOS) or defined(MorphOS):
const
dirsep* = '/'
altsep* = dirsep
PathSep* = ';'
pardir* = ".."
FileSystemCaseSensitive* = false
elif defined(RISCOS):
const
dirsep* = '.'
altsep* = '.'
pardir* = ".." # is this correct?
pathSep* = ','
FileSystemCaseSensitive* = true
else: # UNIX-like operating system
const
curdir* = '.'
pardir* = ".."
dirsep* = '/'
altsep* = dirsep
pathSep* = ':'
FileSystemCaseSensitive* = true
const
ExtSep* = '.'
## The character which separates the base filename from the extension;
## for example, the '.' in ``os.nim``.
proc getApplicationDir*(): string {.noSideEffect.}
## Gets the directory of the application's executable.
proc getApplicationFilename*(): string {.noSideEffect.}
## Gets the filename of the application's executable.
proc getCurrentDir*(): string {.noSideEffect.}
## Gets the current working directory.
proc setCurrentDir*(newDir: string) {.inline.}
## Sets the current working directory; `EOS` is raised if
## `newDir` cannot been set.
proc getHomeDir*(): string {.noSideEffect.}
## Gets the home directory of the current user.
proc getConfigDir*(): string {.noSideEffect.}
## Gets the config directory of the current user for applications.
proc expandFilename*(filename: string): string
## Returns the full path of `filename`, "" on error.
proc ExistsFile*(filename: string): bool
## Returns true if the file exists, false otherwise.
proc JoinPath*(head, tail: string): string {.noSideEffect.}
## Joins two directory names to one.
##
## For example on Unix::
##
## JoinPath("usr", "lib")
##
## results in::
##
## "usr/lib"
##
## If head is the empty string, tail is returned.
## If tail is the empty string, head is returned.
proc `/` * (head, tail: string): string {.noSideEffect.} =
## The same as ``joinPath(head, tail)``
return joinPath(head, tail)
proc JoinPath*(parts: openarray[string]): string {.noSideEffect.}
## The same as `JoinPath(head, tail)`, but works with any number
## of directory parts.
proc SplitPath*(path: string, head, tail: var string) {.noSideEffect.}
## Splits a directory into (head, tail), so that
## ``JoinPath(head, tail) == path``.
##
## Example: After ``SplitPath("usr/local/bin", head, tail)``,
## `head` is "usr/local" and `tail` is "bin".
## Example: After ``SplitPath("usr/local/bin/", head, tail)``,
## `head` is "usr/local/bin" and `tail` is "".
proc parentDir*(path: string): string {.noSideEffect.}
## Returns the parent directory of `path`.
##
## This is often the same as the ``head`` result of ``splitPath``.
## If there is no parent, ``path`` is returned.
## Example: ``parentDir("/usr/local/bin") == "/usr/local"``.
## Example: ``parentDir("/usr/local/bin/") == "/usr/local"``.
proc `/../` * (head, tail: string): string {.noSideEffect.} =
## The same as ``parentDir(head) / tail``
return parentDir(head) / tail
proc UnixToNativePath*(path: string): string {.noSideEffect.}
## Converts an UNIX-like path to a native one.
##
## On an UNIX system this does nothing. Else it converts
## '/', '.', '..' to the appropriate things.
proc SplitFilename*(filename: string, name, extension: var string) {.
noSideEffect.}
## Splits a filename into (name, extension), so that
## ``name & extension == filename``.
##
## Example: After ``SplitFilename("usr/local/nimrodc.html", name, ext)``,
## `name` is "usr/local/nimrodc" and `ext` is ".html".
## It the file has no extension, extention is the empty string.
proc extractDir*(path: string): string {.noSideEffect.}
## Extracts the directory of a given path. This is the `head`
## result of `splitPath`.
proc extractFilename*(path: string): string {.noSideEffect.}
## Extracts the filename of a given `path`. This the the `tail`
## result of `splitPath`.
# XXX: this is not true: /usr/lib/ --> filename should be empty!
proc cmpPaths*(pathA, pathB: string): int {.noSideEffect.}
## Compares two paths.
##
## On a case-sensitive filesystem this is done
## case-sensitively otherwise case-insensitively. Returns:
##
## | 0 iff pathA == pathB
## | < 0 iff pathA < pathB
## | > 0 iff pathA > pathB
proc AppendFileExt*(filename, ext: string): string {.noSideEffect.}
## Appends the file extension `ext` to the `filename`, even if
## the `filename` already has an extension.
##
## `Ext` should be given without the leading '.', because some
## filesystems may use a different character.
## (Although I know of none such beast.)
proc ChangeFileExt*(filename, ext: string): string {.noSideEffect.}
## Changes the file extension to `ext`.
##
## If the `filename` has no extension, `ext` will be added.
## If `ext` == "" then the filename will get no extension.
## `Ext` should be given without the leading '.', because some
## filesystems may use a different character. (Although I know
## of none such beast.)
# procs dealing with processes:
proc executeProcess*(command: string): int
## Executes a process.
##
## Command has the form 'program args' where args are the command
## line arguments given to program. The proc returns the error code
## of the process when it has finished. The proc does not return
## until the process has finished.
proc executeShellCommand*(command: string): int
## Executes a shell command.
##
## The syntax of the command is unspecified and depends on the used
## shell. The proc returns the error code of the shell when it has finished.
# procs operating on a high level for files:
proc copyFile*(dest, source: string)
## Copies a file from `dest` to `source`. If this fails,
## `EOS` is raised.
proc moveFile*(dest, source: string)
## Moves a file from `dest` to `source`. If this fails, `EOS` is raised.
proc removeFile*(file: string)
## Removes the `file`. If this fails, `EOS` is raised.
proc removeDir*(dir: string)
## Removes the directory `dir` including all subdirectories or files
## in `dir` (recursively). If this fails, `EOS` is raised.
proc createDir*(dir: string)
## Creates the directory `dir`.
##
## The directory may contain several
## subdirectories that do not exist yet. The full path is created. If this
## fails, `EOS` is raised. It does NOT fail if the path already exists
## because for most usages this does not indicate an error.
proc existsDir*(dir: string): bool
## Returns true iff the directory `dir` exists. If `dir` is a file, false
## is returned.
proc getLastModificationTime*(file: string): TTime
## Gets the time of the `file`'s last modification.
# procs dealing with environment variables:
proc putEnv*(key, val: string)
## Sets the value of the environment variable named `key` to `val`.
## If an error occurs, `EInvalidEnvVar` is raised.
proc getEnv*(key: string): string
## Gets the value of the environment variable named `key`.
##
## If the variable does not exist, "" is returned. To distinguish
## whether a variable exists or it's value is just "", call
## `existsEnv(key)`.
proc existsEnv*(key: string): bool
## Checks whether the environment variable named `key` exists.
## Returns true if it exists, false otherwise.
# procs dealing with command line arguments:
proc paramCount*(): int
## Returns the number of command line arguments given to the
## application.
proc paramStr*(i: int): string
## Returns the `i`-th command line arguments given to the
## application.
##
## `i` should be in the range `1..paramCount()`, else
## the `EOutOfIndex` exception is raised.
# implementation
proc UnixToNativePath(path: string): string =
when defined(unix):
result = path
else:
var start: int
if path[0] == '/':
# an absolute path
when defined(doslike):
result = r"C:\"
elif defined(macos):
result = "" # must not start with ':'
else:
result = $dirSep
start = 1
elif path[0] == '.' and path[1] == '/':
# current directory
result = $curdir
start = 2
else:
result = ""
start = 0
var i = start
while i < len(path): # ../../../ --> ::::
if path[i] == '.' and path[i+1] == '.' and path[i+2] == '/':
# parent directory
when defined(macos):
if result[high(result)] == ':':
add result, ':'
else:
add result, pardir
else:
add result, pardir & dirSep
inc(i, 3)
elif path[i] == '/':
add result, dirSep
inc(i)
else:
add result, $path[i]
inc(i)
# interface to C library:
type
TStat {.importc: "struct stat".} = record
st_dev: int16
st_ino: int16
st_mode: int16
st_nlink: int16
st_uid: int16
st_gid: int16
st_rdev: int32
st_size: int32
st_atime: TTime
st_mtime: TTime
st_ctime: TTime
var
errno {.importc: "errno", header: "<errno.h>".}: cint
EEXIST {.importc: "EEXIST", header: "<errno.h>".}: cint
when defined(unix):
const dirHeader = "<sys/stat.h>"
elif defined(windows):
const dirHeader = "<direct.h>"
else:
{.error: "os library not ported to your OS. Please help!".}
proc chdir(path: CString): cint {.importc: "chdir", header: dirHeader.}
when defined(unix):
proc mkdir(dir: CString, theAccess: cint): cint {.
importc: "mkdir", header: dirHeader.}
proc realpath(name, resolved: CString): CString {.
importc: "realpath", header: "<stdlib.h>".}
proc getcwd(buf: CString, buflen: cint): CString {.
importc: "getcwd", header: "<unistd.h>".}
elif defined(windows):
proc mkdir(dir: CString): cint {.
importc: "mkdir", header: dirHeader.}
proc fullpath(buffer, file: CString, size: int): CString {.
importc: "_fullpath", header: "<stdlib.h>".}
proc getcwd(buf: CString, buflen: cint): CString {.
importc: "getcwd", header: "<direct.h>".}
proc CreateDirectory(pathName: cstring, security: Pointer): cint {.
importc: "CreateDirectory", header: "<windows.h>".}
proc GetLastError(): cint {.importc, header: "<windows.h>".}
else:
{.error: "os library not ported to your OS. Please help!".}
proc rmdir(dir: CString): cint {.importc: "rmdir", header: "<time.h>".}
# rmdir is of course in ``dirHeader``, but we check here to include
# time.h which is needed for stat(). stat() needs time.h and
# sys/stat.h; we workaround a C library issue here.
proc free(c: cstring) {.importc: "free", nodecl.}
# some C procs return a buffer that has to be freed with free(),
# so we define it here
proc strlen(str: CString): int {.importc: "strlen", nodecl.}
proc stat(f: CString, res: var TStat): cint {.
importc: "stat", header: "<sys/stat.h>".}
proc sameFile*(path1, path2: string): bool =
## Returns True if both pathname arguments refer to the same file or
## directory (as indicated by device number and i-node number).
## Raises an exception if an os.stat() call on either pathname fails.
var
a, b: TStat
if stat(path1, a) < 0 or stat(path2, b) < 0:
raise newException(EOS, "stat() call failed")
return int(a.st_dev) == b.st_dev and int(a.st_ino) == b.st_ino
when defined(windows):
proc getModuleFilename(handle: int32, buf: CString, size: int32): int32 {.
importc: "GetModuleFileName", header: "<windows.h>".}
proc getLastModificationTime(file: string): TTime =
var
res: TStat
discard stat(file, res)
return res.st_mtime
proc setCurrentDir(newDir: string) =
if chdir(newDir) != 0:
raise newException(EOS, "cannot change the working directory to '$1'" %
newDir)
when defined(linux) or defined(solaris) or defined(bsd):
proc readlink(link, buf: cstring, size: int): int {.
header: "<unistd.h>", cdecl.}
proc getApplAux(procPath: string): string =
result = newString(256)
var len = readlink(procPath, result, 256)
if len > 256:
result = newString(len+1)
len = readlink(procPath, result, len)
setlen(result, len)
when defined(solaris) or defined(bsd):
proc getpid(): int {.importc, header: "<unistd.h>", cdecl.}
proc getApplicationFilename(): string =
# Linux: /proc/<pid>/exe
# Solaris:
# /proc/<pid>/object/a.out (filename only)
# /proc/<pid>/path/a.out (complete pathname)
# *BSD (and maybe Darwing too):
# /proc/<pid>/file
when defined(windows):
result = newString(256)
var len = getModuleFileName(0, result, 256)
setlen(result, int(len))
elif defined(linux):
result = getApplAux("/proc/self/exe")
elif defined(solaris):
result = getApplAux("/proc/" & $getpid() & "/path/a.out")
elif defined(bsd):
result = getApplAux("/proc/" & $getpid() & "file")
else:
# little heuristic that may work on other POSIX-like systems:
result = getEnv("_")
if len(result) == 0:
result = ParamStr(0) # POSIX guaranties that this contains the executable
# as it has been executed by the calling process
if len(result) > 0 and result[0] != DirSep: # not an absolute path?
# iterate over any path in the $PATH environment variable
for p in split(getEnv("PATH"), {PathSep}):
var x = joinPath(p, result)
if ExistsFile(x): return x
{.push warnings: off.}
proc getApplicationDir(): string =
var tail: string
splitPath(getApplicationFilename(), result, tail)
{.pop.}
proc getCurrentDir(): string =
const
bufsize = 512 # should be enough
result = newString(bufsize)
if getcwd(result, bufsize) != nil:
setlen(result, strlen(result))
else:
raise newException(EOS, "getcwd failed")
proc JoinPath(head, tail: string): string =
if len(head) == 0:
result = tail
elif head[len(head)-1] in {DirSep, AltSep}:
if tail[0] in {DirSep, AltSep}:
result = head & copy(tail, 1)
else:
result = head & tail
else:
if tail[0] in {DirSep, AltSep}:
result = head & tail
else:
result = head & DirSep & tail
proc JoinPath(parts: openarray[string]): string =
result = parts[0]
for i in 1..high(parts):
result = JoinPath(result, parts[i])
proc parentDir(path: string): string =
var
sepPos = -1
q = 1
if path[len(path)-1] in {dirsep, altsep}:
q = 2
for i in countdown(len(path)-q, 0):
if path[i] in {dirsep, altsep}:
sepPos = i
break
if sepPos >= 0:
result = copy(path, 0, sepPos-1)
else:
result = path
proc SplitPath(path: string, head, tail: var string) =
var
sepPos = -1
for i in countdown(len(path)-1, 0):
if path[i] in {dirsep, altsep}:
sepPos = i
break
if sepPos >= 0:
head = copy(path, 0, sepPos-1)
tail = copy(path, sepPos+1)
else:
head = ""
tail = path # make a string copy here
# helper:
proc searchExtPos(s: string): int =
result = -1
for i in countdown(len(s)-1, 0):
if s[i] == extsep:
result = i
break
elif s[i] in {dirsep, altsep}:
break # do not skip over path
proc SplitFilename(filename: string, name, extension: var string) =
var
extPos = searchExtPos(filename)
if extPos >= 0:
name = copy(filename, 0, extPos-1)
extension = copy(filename, extPos)
else:
name = filename # make a string copy here
extension = ""
proc normExt(ext: string): string =
if ext == "" or ext[0] == extSep: result = ext # no copy needed here
else: result = extSep & ext
proc ChangeFileExt(filename, ext: string): string =
var
extPos = searchExtPos(filename)
if extPos < 0: result = filename & normExt(ext)
else: result = copy(filename, 0, extPos-1) & normExt(ext)
proc AppendFileExt(filename, ext: string): string =
var
extPos = searchExtPos(filename)
if extPos < 0: result = filename & normExt(ext)
else: result = filename #make a string copy here
# some more C things:
proc csystem(cmd: CString): cint {.importc: "system", noDecl.}
# is in <stdlib.h>!
when defined(wcc):
# everywhere it is in <stdlib.h>, except for Watcom C ...
proc cputenv(env: CString): cint {.importc: "putenv", header: "<process.h>".}
else: # is in <stdlib.h>
proc cputenv(env: CString): cint {.importc: "putenv", noDecl.}
proc cgetenv(env: CString): CString {.importc: "getenv", noDecl.}
#long _findfirst(char *, struct _finddata_t *);
#int _findnext(long, struct _finddata_t *);
#int _findclose(long);
when defined(windows):
type
TFindData {.importc: "struct _finddata_t".} = record
attrib {.importc: "attrib".}: cint
time_create {.importc: "time_create".}: cint
time_access {.importc: "time_access".}: cint
time_write {.importc: "time_write".}: cint
size {.importc: "size".}: cint
name {.importc: "name".}: array[0..259, char]
proc findfirst(pathname: CString, f: ptr TFindData): cint {.
importc: "_findfirst", header: "<io.h>".}
proc findnext(handle: cint, f: ptr TFindData): cint {.
importc: "_findnext", header: "<io.h>".}
proc findclose(handle: cint) {.importc: "_findclose", header: "<io.h>".}
else:
type
TFindData {.importc: "glob_t".} = record
gl_pathc: int # count of paths matched by pattern
gl_pathv: ptr array[0..1000_000, CString] # list of matched path names
gl_offs: int # slots to reserve at beginning of gl_pathv
PFindData = ptr TFindData
proc glob(pattern: cstring, flags: cint, errfunc: pointer,
pglob: PFindData): cint {.
importc: "glob", header: "<glob.h>".}
proc globfree(pglob: PFindData) {.
importc: "globfree", header: "<glob.h>".}
proc cremove(filename: CString): cint {.importc: "remove", noDecl.}
proc crename(oldname, newname: CString): cint {.importc: "rename", noDecl.}
when defined(Windows):
proc cCopyFile(lpExistingFileName, lpNewFileName: CString,
bFailIfExists: cint): cint {.
importc: "CopyFile", header: "<windows.h>".}
# cMoveFile(lpExistingFileName, lpNewFileName: CString): int
# {.importc: "MoveFile", noDecl, header: "<winbase.h>".}
# cRemoveFile(filename: CString, cmo: int)
# {.importc: "DeleteFile", noDecl, header: "<winbase.h>".}
else:
# generic version of cCopyFile which works for any platform:
proc cCopyFile(lpExistingFileName, lpNewFileName: CString,
bFailIfExists: cint): cint =
const
bufSize = 8192 # 8K buffer
var
dest, src: TFile
if not openFile(src, $lpExistingFilename): return -1
if not openFile(dest, $lpNewFilename, fmWrite):
closeFile(src)
return -1
var
buf: Pointer = alloc(bufsize)
bytesread, byteswritten: int
while True:
bytesread = readBuffer(src, buf, bufsize)
byteswritten = writeBuffer(dest, buf, bytesread)
if bytesread != bufSize: break
if byteswritten == bytesread: result = 0
else: result = -1
dealloc(buf)
closeFile(src)
closeFile(dest)
proc moveFile(dest, source: string) =
if crename(source, dest) != 0:
raise newException(EOS, "cannot move file from '$1' to '$2'" %
[source, dest])
proc copyFile(dest, source: string) =
if cCopyFile(source, dest, 0) != 0:
raise newException(EOS, "cannot copy file from '$1' to '$2'" %
[source, dest])
proc removeFile(file: string) =
if cremove(file) != 0:
raise newException(EOS, "cannot remove file '$1'" % file)
proc removeDir(dir: string) =
if rmdir(dir) != 0:
raise newException(EOS, "cannot remove directory '$1'" % dir)
proc createDir(dir: string) =
when defined(unix):
if mkdir(dir, 0o711) != 0 and int(errno) != EEXIST:
raise newException(EOS, "cannot create directory '$1'" % dir)
else:
if CreateDirectory(dir, nil) == 0 and GetLastError() != 183:
raise newException(EOS, "cannot create directory '$1'" % dir)
proc existsDir(dir: string): bool =
var safe = getCurrentDir()
# just try to set the current dir to dir; if it works, it must exist:
result = chdir(dir) == 0
if result:
setCurrentDir(safe) # set back to the old working directory
proc executeProcess(command: string): int =
return csystem(command) # XXX: do this without shell
proc executeShellCommand(command: string): int =
return csystem(command)
var
envComputed: bool = false
environment {.noStatic.}: seq[string] = []
when defined(windows):
# because we support Windows GUI applications, things get really
# messy here...
proc GetEnvironmentStrings(): Pointer {.
importc: "GetEnvironmentStrings", header: "<windows.h>".}
proc FreeEnvironmentStrings(env: Pointer) {.
importc: "FreeEnvironmentStrings", header: "<windows.h>".}
proc strEnd(cstr: CString, c = 0): CString {.importc: "strchr", nodecl.}
proc getEnvVarsC() {.noStatic.} =
if not envComputed:
var
env = cast[CString](getEnvironmentStrings())
e = env
if e == nil: return # an error occured
while True:
var eend = strEnd(e)
add environment, $e
e = cast[CString](cast[TAddress](eend)+1)
if eend[1] == '\0': break
envComputed = true
FreeEnvironmentStrings(env)
else:
var
gEnv {.importc: "gEnv".}: ptr array [0..10_000, CString]
proc getEnvVarsC() {.noStatic.} =
# retrieves the variables of char** env of C's main proc
if not envComputed:
var
i: int = 0
while True:
if gEnv[i] == nil: break
add environment, $gEnv[i]
inc(i)
envComputed = true
proc findEnvVar(key: string): int =
getEnvVarsC()
var temp = key & '='
for i in 0..high(environment):
if findSubStr(temp, environment[i]) == 0: return i
return -1
proc getEnv(key: string): string =
var i = findEnvVar(key)
if i >= 0:
return copy(environment[i], findSubStr("=", environment[i])+1)
else:
var env = cgetenv(key)
if env == nil: return ""
result = $env
proc existsEnv(key: string): bool =
if cgetenv(key) != nil: return true
else: return findEnvVar(key) >= 0
iterator iterOverEnvironment*(): tuple[string, string] =
## Iterate over all environments varialbes. In the first component of the
## tuple is the name of the current variable stored, in the second its value.
getEnvVarsC()
for i in 0..high(environment):
var p = findSubStr("=", environment[i])
yield (copy(environment[i], 0, p-1), copy(environment[i], p+1))
proc putEnv(key, val: string) =
# Note: by storing the string in the environment sequence,
# we gurantee that we don't free the memory before the program
# ends (this is needed for POSIX compliance). It is also needed so that
# the process itself may access its modified environment variables!
var indx = findEnvVar(key)
if indx >= 0:
environment[indx] = key & '=' & val
else:
add environment, (key & '=' & val)
indx = high(environment)
if cputenv(environment[indx]) != 0:
raise newException(EOS, "attempt to set an invalid environment variable")
iterator walkFiles*(pattern: string): string =
## Iterate over all the files that match the `pattern`.
##
## `pattern` is OS dependant, but at least the "\*.ext"
## notation is supported.
when defined(windows):
var
f: TFindData
res: int
res = findfirst(pattern, addr(f))
if res != -1:
while true:
yield $f.name
if int(findnext(res, addr(f))) == -1: break
findclose(res)
else: # here we use glob
var
f: TFindData
res: int
f.gl_offs = 0
f.gl_pathc = 0
f.gl_pathv = nil
res = glob(pattern, 0, nil, addr(f))
if res != 0: raise newException(EOS, "walkFiles() failed")
for i in 0.. f.gl_pathc - 1:
assert(f.gl_pathv[i] != nil)
yield $f.gl_pathv[i]
globfree(addr(f))
{.push warnings:off.}
proc ExistsFile(filename: string): bool =
var
res: TStat
return stat(filename, res) >= 0
{.pop.}
proc cmpPaths(pathA, pathB: string): int =
if FileSystemCaseSensitive:
result = cmp(pathA, pathB)
else:
result = cmpIgnoreCase(pathA, pathB)
proc extractDir(path: string): string =
var
tail: string
splitPath(path, result, tail)
proc extractFilename(path: string): string =
var
head: string
splitPath(path, head, result)
proc expandFilename(filename: string): string =
# returns the full path of 'filename'; "" on error
var
res: CString
when defined(unix):
res = realpath(filename, nil)
else:
res = fullpath(nil, filename, 0)
if res == nil:
result = "" # an error occured
else:
result = $res
free(res)
when defined(windows):
proc GetHomeDir(): string = return getEnv("USERPROFILE") & "\\"
proc GetConfigDir(): string = return getEnv("APPDATA") & "\\"
# Since we support GUI applications with Nimrod, we sometimes generate
# a WinMain entry proc. But a WinMain proc has no access to the parsed
# command line arguments. The way to get them differs. Thus we parse them
# ourselves. This has the additional benefit that the program's behaviour
# is always the same -- independent of the used C compiler.
proc GetCommandLine(): CString {.
importc: "GetCommandLine", header: "<windows.h>".}
var
ownArgc: int = -1
ownArgv: seq[string] = []
proc parseCmdLine() =
if ownArgc != -1: return # already processed
var
i = 0
j = 0
c = getCommandLine()
ownArgc = 0
while c[i] != '\0':
var a = ""
while c[i] >= '\1' and c[i] <= ' ': inc(i) # skip whitespace
case c[i]
of '\'', '\"':
var delim = c[i]
inc(i) # skip ' or "
while c[i] != '\0' and c[i] != delim:
add a, c[i]
inc(i)
if c[i] != '\0': inc(i)
else:
while c[i] > ' ':
add a, c[i]
inc(i)
add ownArgv, a
inc(ownArgc)
proc paramStr(i: int): string =
parseCmdLine()
if i < ownArgc and i >= 0:
return ownArgv[i]
raise newException(EInvalidIndex, "invalid index")
proc paramCount(): int =
parseCmdLine()
result = ownArgc-1
else:
proc GetHomeDir(): string = return getEnv("HOME") & "/"
proc GetConfigDir(): string = return getEnv("HOME") & "/"
var
cmdCount {.importc: "cmdCount".}: int
cmdLine {.importc: "cmdLine".}: cstringArray
proc paramStr(i: int): string =
if i < cmdCount and i >= 0: return $cmdLine[i]
raise newException(EInvalidIndex, "invalid index")
proc paramCount(): int = return cmdCount-1
{.pop.}

1818
lib/posix/posix.nim Executable file

File diff suppressed because it is too large Load Diff

35
lib/powerpc.asm.in Executable file
View File

@@ -0,0 +1,35 @@
; This contains the CPU-dependant variants of some routines.
; (C) 2005 Andreas Rumpf
; This code was inspired by the Freepascal compiler's sources
; All routines here have the _cdecl calling convention because
; that is the only convention any C compiler supports.
\python{
def c(name):
if os.name == 'posix':
return name
else:
return "_" + name
}
segment code
global \c{cpu_inc_locked}
global \c{cpu_dec_locked}
\c{cpu_dec_locked}:
; input: address of arg in r3
.LDecLockedLoop:
lwarx r10,0,r3
subi r10,r10,1
stwcx. r10,0,r3
bne- .LDecLockedLoop
cntlzw r3,r10
srwi r3,r3,5
\c{cpu_inc_locked}:
.LIncLockedLoop:
lwarx r10,0,r3
addi r10,r10,1
stwcx. r10,0,r3
bne- .LIncLockedLoop

1009
lib/process.nim Executable file

File diff suppressed because it is too large Load Diff

205
lib/ptrset.nim Executable file
View File

@@ -0,0 +1,205 @@
# This implements a new pointer set. Access time O(1). For 32 bit systems, we
# currently need 3 memory accesses.
const
PageSize = 1024 * sizeof(int)
MemAlignment = 8 # minimal memory block that can be allocated
BitsPerUnit = sizeof(int)*8
# a "unit" is a word, i.e. 4 bytes
# on a 32 bit system; I do not use the term "word" because under 32-bit
# Windows it is sometimes only 16 bits
BitsPerPage = PageSize div MemAlignment
UnitsPerPage = BitsPerPage div BitsPerUnit
# how many units do we need to describe a page:
# on 32 bit systems this is only 16 (!)
type
PPointer = ptr pointer
TCollectorData = int
TCell = record
refcount: TCollectorData # the refcount and bit flags
typ: PNimType
stackcount: int # stack counter for debugging
drefc: int # real reference counter for debugging
PCell = ptr TCell
proc cellToUsr(cell: PCell): pointer {.inline.} =
# convert object (=pointer to refcount) to pointer to userdata
result = cast[pointer](cast[TAddress](cell)+%TAddress(sizeof(TCell)))
proc usrToCell(usr: pointer): PCell {.inline.} =
# convert pointer to userdata to object (=pointer to refcount)
result = cast[PCell](cast[TAddress](usr)-%TAddress(sizeof(TCell)))
proc gcAlloc(size: int): pointer =
result = alloc0(size)
if result == nil: raiseOutOfMem()
# ------------------ Zero count table (ZCT) and any table (AT) -------------
# this that has to equals zero, otherwise we have to round up UnitsPerPage:
when BitsPerPage mod BitsPerUnit != 0:
{.error: "(BitsPerPage mod BitsPerUnit) should be zero!".}
# ------------------- cell set handling ------------------------------
# A cellset consists of a hash table of page descriptors. A page
# descriptor has a bit for
# every Memalignment'th byte in the page.
# However, only bits corresponding to addresses that start memory blocks
# are set.
# Page descriptors are also linked to a list; the list
# is used for easy traversing of all page descriptors; this allows a
# fast iterator.
# We use a specialized hashing scheme; the formula is :
# hash = Page bitand max
# We use linear probing with the formular: (5*h)+1
# Thus we likely get no collisions at all if the pages are given to us
# in a sequential manner by the operating system!
const
bitsPerNode = 10 # we use 10 bits per node; this means 3 memory accesses on
# 32 bit systems
type
PPageDesc = ptr TPageDesc
TBitIndex = range[0..UnitsPerPage-1]
TPageDesc = record
next: PPageDesc # all nodes are connected with this pointer
key: TAddress # start address at bit 0
bits: array[TBitIndex, int] # a bit vector
PPageDescArray = ptr array[0..1000_000, PPageDesc]
TCellSet = record
counter, max: int
head: PPageDesc
data: PPageDescArray
TSetNode = record
n: array[0.. (1 shl bitsPerNode)-1, PSetNode]
PSetNode = ptr TSetNode
const
InitCellSetSize = 1024 # must be a power of two!
proc CellSetInit(s: var TCellSet) =
s.data = gcAlloc(InitCellSetSize * sizeof(PPageDesc))
s.max = InitCellSetSize-1
s.counter = 0
s.head = nil
proc CellSetDeinit(s: var TCellSet) =
var it = s.head
while it != nil:
var n = it.next
dealloc(it)
it = n
s.head = nil # play it safe here
dealloc(s.data)
s.data = nil
s.counter = 0
proc CellSetGet(t: TCellSet, key: TAddress): PPageDesc =
var h = cast[int](key) and t.max
while t.data[h] != nil:
if t.data[h].key == key: return t.data[h]
h = nextTry(h, t.max)
return nil
proc CellSetRawInsert(t: TCellSet, data: PPageDescArray,
desc: PPageDesc) =
var h = cast[int](desc.key) and t.max
while data[h] != nil:
assert(data[h] != desc)
h = nextTry(h, t.max)
assert(data[h] == nil)
data[h] = desc
proc CellSetEnlarge(t: var TCellSet) =
var
n: PPageDescArray
oldMax = t.max
t.max = ((t.max+1)*2)-1
n = gcAlloc((t.max + 1) * sizeof(PPageDesc))
for i in 0 .. oldmax:
if t.data[i] != nil:
CellSetRawInsert(t, n, t.data[i])
dealloc(t.data)
t.data = n
proc CellSetPut(t: var TCellSet, key: TAddress): PPageDesc =
var h = cast[int](key) and t.max
while true:
var x = t.data[h]
if x == nil: break
if x.key == key: return x
h = nextTry(h, t.max)
if (t.max+1) * 2 < t.counter * 3: CellSetEnlarge(t)
inc(t.counter)
h = cast[int](key) and t.max
while t.data[h] != nil: h = nextTry(h, t.max)
assert(t.data[h] == nil)
# the new page descriptor goes into result
result = gcAlloc(sizeof(TPageDesc))
result.next = t.head
result.key = key
t.head = result
t.data[h] = result
# ---------- slightly higher level procs ----------------------------------
proc in_Operator(s: TCellSet, cell: PCell): bool =
var
u: TAddress
t: PPageDesc
u = cast[TAddress](cell)
t = CellSetGet(s, u /% PageSize)
if t != nil:
u = (u %% PageSize) /% MemAlignment
result = (t.bits[u /% BitsPerUnit] and (1 shl (u %% BitsPerUnit))) != 0
else:
result = false
proc incl(s: var TCellSet, cell: PCell) =
var
u: TAddress
t: PPageDesc
u = cast[TAddress](cell)
t = CellSetPut(s, u /% PageSize)
u = (u %% PageSize) /% MemAlignment
t.bits[u /% BitsPerUnit] = t.bits[u /% BitsPerUnit] or
(1 shl (u %% BitsPerUnit))
proc excl(s: var TCellSet, cell: PCell) =
var
u: TAddress
t: PPageDesc
u = cast[TAddress](cell)
t = CellSetGet(s, u /% PageSize)
if t != nil:
u = (u %% PageSize) /% MemAlignment
t.bits[u %% BitsPerUnit] = (t.bits[u /% BitsPerUnit] and
not (1 shl (u %% BitsPerUnit)))
iterator elements(t: TCellSet): PCell {.inline.} =
# while traversing it is forbidden to add pointers to the tree!
var r = t.head
while r != nil:
var i = 0
while i <= high(r.bits):
var w = r.bits[i] # taking a copy of r.bits[i] here is correct, because
# modifying operations are not allowed during traversation
var j = 0
while w != 0: # test all remaining bits for zero
if (w and 1) != 0: # the bit is set!
yield cast[PCell]((r.key *% PageSize) +%
(i*%BitsPerUnit+%j) *% MemAlignment)
inc(j)
w = w shr 1
inc(i)
r = r.next

233
lib/repr.nim Executable file
View File

@@ -0,0 +1,233 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# The generic ``repr`` procedure. It is an invaluable debugging tool.
#proc cstrToNimStrDummy(s: cstring): string {.inline.} =
# result = cast[string](cstrToNimStr(s))
proc reprInt(x: int64): string {.compilerproc.} = return $x
proc reprFloat(x: float): string {.compilerproc.} = return $x
proc reprPointer(x: pointer): string {.compilerproc.} =
var buf: array [0..59, char]
c_sprintf(buf, "%p", x)
return $buf
proc reprStrAux(result: var string, s: string) =
if cast[pointer](s) == nil:
add result "nil"
return
add result, reprPointer(cast[pointer](s)) & "\""
for c in items(s):
case c
of '"': add result "\\\""
of '\\': add result, "\\\\" # BUGFIX: forgotten
of '\10': add result, "\\10\"\n\"" # " \n " # better readability
of '\128' .. '\255', '\0'..'\9', '\11'..'\31':
add result, "\\" & reprInt(ord(c))
else: result.add(c)
add result, "\""
proc reprStr(s: string): string {.compilerproc.} =
result = ""
reprStrAux(result, s)
proc reprBool(x: bool): string {.compilerproc.} =
if x: result = "true"
else: result = "false"
proc reprChar(x: char): string {.compilerproc.} =
result = "\'"
case x
of '"': add result, "\\\""
of '\\': add result, "\\\\"
of '\128' .. '\255', '\0'..'\31': add result, "\\" & reprInt(ord(x))
else: add result, x
add result, "\'"
proc reprEnum(e: int, typ: PNimType): string {.compilerproc.} =
if e <% typ.node.len: # BUGFIX
result = $typ.node.sons[e].name
else:
result = $e & " (invalid data!)"
type
pbyteArray = ptr array[0.. 0xffff, byte]
proc addSetElem(result: var string, elem: int, typ: PNimType) =
case typ.kind
of tyEnum: add result, reprEnum(elem, typ)
of tyBool: add result, reprBool(bool(elem))
of tyChar: add result, reprChar(chr(elem))
of tyRange: addSetElem(result, elem, typ.base)
of tyInt..tyInt64: add result, reprInt(elem)
else: # data corrupt --> inform the user
add result, " (invalid data!)"
proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
# "typ.slots.len" field is for sets the "first" field
var elemCounter = 0 # we need this flag for adding the comma at
# the right places
add result, "{"
var u: int64
case typ.size
of 1: u = ze64(cast[ptr int8](p)^)
of 2: u = ze64(cast[ptr int16](p)^)
of 4: u = ze64(cast[ptr int32](p)^)
of 8: u = ze64(cast[ptr int64](p)^)
else:
var a = cast[pbyteArray](p)^
for i in 0 .. typ.size*8-1:
if (a[i div 8] and (1 shl (i mod 8))) != 0:
if elemCounter > 0: add result, ", "
addSetElem(result, i+typ.node.len, typ.base)
inc(elemCounter)
if typ.size <= 8:
for i in 0..sizeof(int64)*8-1:
if (u and (1 shl i)) != 0:
if elemCounter > 0: add result, ", "
addSetElem(result, i+typ.node.len, typ.base)
inc(elemCounter)
add result, "}"
proc reprSet(p: pointer, typ: PNimType): string {.compilerproc.} =
result = ""
reprSetAux(result, p, typ)
type
TReprClosure = record # we cannot use a global variable here
# as this wouldn't be thread-safe
marked: TCellSet
recdepth: int # do not recurse endless
indent: int # indentation
proc initReprClosure(cl: var TReprClosure) =
CellSetInit(cl.marked)
cl.recdepth = -1 # default is to display everything!
cl.indent = 0
proc deinitReprClosure(cl: var TReprClosure) =
CellSetDeinit(cl.marked)
proc reprBreak(result: var string, cl: TReprClosure) =
add result, "\n"
for i in 0..cl.indent-1: add result, ' '
proc reprAux(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure)
proc reprArray(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
add result, "["
var bs = typ.base.size
for i in 0..typ.size div bs - 1:
if i > 0: add result, ", "
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), typ.base, cl)
add result, "]"
proc reprSequence(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
if p == nil:
add result, "nil"
return
result.add(reprPointer(p) & "[")
var bs = typ.base.size
for i in 0..cast[PGenericSeq](p).len-1:
if i > 0: add result, ", "
reprAux(result, cast[pointer](cast[TAddress](p) + GenericSeqSize + i*bs),
typ.Base, cl)
add result, "]"
proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
cl: var TReprClosure) =
case n.kind
of nkNone: assert(false)
of nkSlot:
add result, $n.name
add result, " = "
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
of nkList:
for i in 0..n.len-1:
if i > 0: add result, ",\n"
reprRecordAux(result, p, n.sons[i], cl)
of nkCase:
var m = selectBranch(p, n)
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
if m != nil: reprRecordAux(result, p, m, cl)
proc reprRecord(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
add result, "["
reprRecordAux(result, p, typ.node, cl)
add result, "]"
proc reprRef(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
# we know that p is not nil here:
var cell = usrToCell(p)
add result, "ref " & reprPointer(p)
if cell notin cl.marked:
# only the address is shown:
incl(cl.marked, cell)
add result, " --> "
reprAux(result, p, typ.base, cl)
proc reprAux(result: var string, p: pointer, typ: PNimType,
cl: var TReprClosure) =
if cl.recdepth == 0:
add result, "..."
return
dec(cl.recdepth)
case typ.kind
of tySet: reprSetAux(result, p, typ)
of tyArray: reprArray(result, p, typ, cl)
of tyRecord: reprRecord(result, p, typ, cl)
of tyObject: # result = reprRecord(p, typ, cl)
var t = cast[ptr PNimType](p)^
reprRecord(result, p, t, cl)
of tyRef, tyPtr:
assert(p != nil)
if cast[ppointer](p)^ == nil: add result, "nil"
else: reprRef(result, cast[ppointer](p)^, typ, cl)
of tySequence:
reprSequence(result, cast[ppointer](p)^, typ, cl)
of tyInt: add result, $(cast[ptr int](p)^)
of tyInt8: add result, $int(cast[ptr Int8](p)^)
of tyInt16: add result, $int(cast[ptr Int16](p)^)
of tyInt32: add result, $int(cast[ptr Int32](p)^)
of tyInt64: add result, $(cast[ptr Int64](p)^)
of tyFloat: add result, $(cast[ptr float](p)^)
of tyFloat32: add result, $(cast[ptr float32](p)^)
of tyFloat64: add result, $(cast[ptr float64](p)^)
of tyEnum: add result, reprEnum(cast[ptr int](p)^, typ)
of tyBool: add result, reprBool(cast[ptr bool](p)^)
of tyChar: add result, reprChar(cast[ptr char](p)^)
of tyString: reprStrAux(result, cast[ptr string](p)^)
of tyCString: reprStrAux(result, $(cast[ptr cstring](p)^))
of tyRange: reprAux(result, p, typ.base, cl)
of tyProc, tyPointer:
if cast[ppointer](p)^ == nil: add result, "nil"
else: add result, reprPointer(cast[ppointer](p)^)
else:
add result, "(invalid data!)"
inc(cl.recdepth)
proc reprAny(p: pointer, typ: PNimType): string =
var
cl: TReprClosure
initReprClosure(cl)
result = ""
if typ.kind in {tyObject, tyRecord, tyArray, tySet}:
reprAux(result, p, typ, cl)
else:
reprAux(result, addr(p), typ, cl)
add result, "\n"
deinitReprClosure(cl)

88
lib/sets.nim Executable file
View File

@@ -0,0 +1,88 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# set handling
type
TMyByte = int8
TNimSet = array [0..4*2048-1, TMyByte]
# implementation:
proc countBits(n: int32): int {.exportc: "countBits".}
# We use a prototype here, not in "cntbits.nim", because that is included
# in math.nim too. So when linking with math.nim it'd give a duplicated
# symbol error which we avoid by renaming here.
include cntbits
proc unionSets(res: var TNimSet, a, b: TNimSet, len: int) {.
compilerproc, inline.} =
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) or ze(b[i]))
proc diffSets(res: var TNimSet, a, b: TNimSet, len: int) {.
compilerproc, inline.} =
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) and not ze(b[i]))
proc intersectSets(res: var TNimSet, a, b: TNimSet, len: int) {.
compilerproc, inline.} =
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) and ze(b[i]))
proc symdiffSets(res: var TNimSet, a, b: TNimSet, len: int) {.
compilerproc, inline.} =
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) xor ze(b[i]))
proc containsSets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} =
# s1 <= s2 ?
for i in countup(0, len-1):
if (ze(a[i]) and not ze(b[i])) != 0: return false
return true
proc containsSubsets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} =
# s1 < s2 ?
result = false # assume they are equal
for i in countup(0, len-1):
if (ze(a[i]) and not ze(b[i])) != 0: return false
if ze(a[i]) != ze(b[i]): result = true # they are not equal
proc equalSets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} =
for i in countup(0, len-1):
if ze(a[i]) != ze(b[i]): return false
return true
proc cardSet(s: TNimSet, len: int): int {.compilerproc, inline.} =
result = 0
for i in countup(0, len-1):
inc(result, countBits(ze(s[i])))
const
WORD_SIZE = sizeof(TMyByte)*8
proc inSet(s: TNimSet, elem: int): bool {.compilerproc, inline.} =
return (s[elem /% WORD_SIZE] and (1 shl (elem %% WORD_SIZE))) != 0
proc inclSets(s: var TNimSet, e: int) {.compilerproc, inline.} =
s[e /% WORD_SIZE] = toU8(s[e /% WORD_SIZE] or (1 shl (e %% WORD_SIZE)))
proc inclRange(s: var TNimSet, first, last: int) {.compilerproc.} =
# not very fast, but it is seldom used
for i in countup(first, last): inclSets(s, i)
proc smallInclRange(s: var int, first, last: int) {.compilerproc.} =
# not very fast, but it is seldom used
for i in countup(first, last):
s = s or (1 shl (i %% sizeof(int)*8))
proc exclSets(s: var TNimSet, e: int) {.compilerproc, inline.} =
s[e /% WORD_SIZE] = toU8(s[e /% WORD_SIZE] and
not (1 shl (e %% WORD_SIZE)))
proc smallContainsSubsets(a, b: int): bool {.compilerProc, inline.} =
# not used by new code generator
return ((a and not b) != 0) and (a != b)

627
lib/strutils.nim Executable file
View File

@@ -0,0 +1,627 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module contains various string utility routines.
## See the module `regexprs` for regular expression support.
{.push debugger:off .} # the user does not want to trace a part
# of the standard library!
# copied from excpt.nim, because I don't want to make this template public
template newException(exceptn, message: expr): expr =
block: # open a new scope
var
e: ref exceptn
new(e)
e.msg = message
e
type
TCharSet* = set[char] # for compability for Nim
const
Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'}
## All the characters that count as whitespace.
strStart* = 0 # this is only for bootstraping
# XXX: remove this someday
nl* = "\n" # this is only for bootstraping XXX: remove this somehow
proc strip*(s: string): string {.noSideEffect.}
## Strips leading and trailing whitespace from `s`.
proc toLower*(s: string): string {.noSideEffect.}
## Converts `s` into lower case. This works only for the letters A-Z.
## See `charsets.nativeToLower` for a version that is locale-dependant.
proc toLower*(c: Char): Char {.noSideEffect.}
## Converts `c` into lower case. This works only for the letters A-Z.
## See `charsets.nativeToLower()` for a version that is locale-dependant.
proc toUpper*(s: string): string {.noSideEffect.}
## Converts `s` into upper case. This works only for the letters a-z.
## See `charsets.nativeToUpper()` for a version that is locale-dependant.
proc toUpper*(c: Char): Char {.noSideEffect.}
## Converts `c` into upper case. This works only for the letters a-z.
## See `charsets.nativeToUpper()` for a version that is locale-dependant.
proc capitalize*(s: string): string {.noSideEffect.}
## Converts the first character of `s` into upper case.
## This works only for the letters a-z.
proc normalize*(s: string): string {.noSideEffect.}
## Normalizes the string `s`. That means to convert it to lower case and
## remove any '_'. This is needed for Nimrod identifiers for example.
proc findSubStr*(sub, s: string, start: int = 0): int {.noSideEffect.}
## Searches for `sub` in `s` starting at position `start`. Searching is
## case-sensitive. If `sub` is not in `s`, -1 is returned.
proc findSubStr*(sub: char, s: string, start: int = 0): int {.noSideEffect.}
## Searches for `sub` in `s` starting at position `start`. Searching is
## case-sensitive. If `sub` is not in `s`, -1 is returned.
proc replaceStr*(s, sub, by: string): string {.noSideEffect.}
## Replaces `sub` in `s` by the string `by`.
proc deleteStr*(s: var string, first, last: int)
## Deletes in `s` the characters at position `first`..`last`. This modifies
## `s` itself, it does not return a copy.
proc toOctal*(c: char): string
## Converts a character `c` to its octal representation. The resulting
## string may not have a leading zero. Its length is always exactly 3.
iterator split*(s: string, seps: set[char] = Whitespace): string =
## Splits the string `s` into substrings.
##
## Substrings are separated by a substring containing only `seps`.
## The seperator substrings are not returned in `sub`, nor are they part
## of `sub`.
## Examples::
##
## for word in split(" this is an example "):
## writeln(stdout, word)
##
## Results in::
##
## "this"
## "is"
## "an"
## "example"
##
## for word in split(";;this;is;an;;example;;;", {';'}):
## writeln(stdout, word)
##
## produces in the same output.
var
first: int = 0
last: int = 0
assert(not ('\0' in seps))
while last < len(s):
while s[last] in seps: inc(last)
first = last
while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX!
yield copy(s, first, last-1)
proc splitSeq*(s: string, seps: set[char] = Whitespace): seq[string] {.
noSideEffect.}
## The same as `split`, but is a proc that returns a sequence of substrings.
proc cmpIgnoreCase*(a, b: string): int {.noSideEffect.}
## Compares two strings in a case insensitive manner. Returns:
##
## | 0 iff a == b
## | < 0 iff a < b
## | > 0 iff a > b
proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect.}
## Compares two strings normalized (i.e. case and
## underscores do not matter). Returns:
##
## | 0 iff a == b
## | < 0 iff a < b
## | > 0 iff a > b
proc in_Operator*(s: string, c: char): bool {.noSideEffect.}
## Same as `findSubStr(c, s) >= 0`.
proc in_Operator*(s, sub: string): bool {.noSideEffect.}
## Same as `findSubStr(sub, s) >= 0`.
proc toHex*(x: BiggestInt, len: int): string {.noSideEffect.}
## Converts `x` to its hexadecimal representation. The resulting string
## will be exactly `len` characters long. No prefix like ``0x``
## is generated. `x` is treated as unsigned value.
proc intToStr*(x: int, minchars: int = 1): string
## Converts `x` to its decimal representation. The resulting string
## will be minimally `minchars` characters long. This is achieved by
## adding leading zeros.
proc ParseInt*(s: string): int {.noSideEffect.}
## Parses a decimal integer value contained in `s`. If `s` is not
## a valid integer, `EInvalidValue` is raised.
# XXX: make this biggestint!
proc ParseFloat*(s: string): float {.noSideEffect.}
## Parses a decimal floating point value contained in `s`. If `s` is not
## a valid floating point number, `EInvalidValue` is raised.
# XXX: make this biggestfloat.
# the stringify and format operators:
proc toString*[Ty](x: Ty): string
## This generic proc is the same as the stringify operator `$`.
proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect.}
## The substitution operator performs string substitutions in `formatstr`
## and returns the modified `formatstr`.
##
## This is best explained by an example::
##
## "$1 eats $2." % ["The cat", "fish"]
##
## Results in::
##
## "The cat eats fish."
##
## The substitution variables (the thing after the ``$``)
## are enumerated from 1 to 9.
## Substitution variables can also be words (that is
## ``[A-Za-z_]+[A-Za-z0-9_]*``) in which case the arguments in `a` with even
## indices are keys and with odd indices are the corresponding values. Again
## an example::
##
## "$animal eats $food." % ["animal", "The cat", "food", "fish"]
##
## Results in::
##
## "The cat eats fish."
##
## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is
## raised if an ill-formed format string has been passed to the `%` operator.
proc `%` *(formatstr, a: string): string {.noSideEffect.}
## This is the same as `formatstr % [a]`.
proc repeatChar*(count: int, c: Char = ' '): string
## Returns a string of length `count` consisting only of
## the character `c`.
proc startsWith*(s, prefix: string): bool {.noSideEffect.}
## Returns true iff ``s`` starts with ``prefix``.
## If ``prefix == ""`` true is returned.
proc endsWith*(s, suffix: string): bool {.noSideEffect.}
## Returns true iff ``s`` ends with ``suffix``.
## If ``suffix == ""`` true is returned.
# implementation
proc allCharsInSet*(s: string, theSet: TCharSet): bool =
## returns true iff each character of `s` is in the set `theSet`.
for c in items(s):
if not (c in theSet): return false
return true
proc c_strcmp(a, b: CString): int {.importc: "strcmp", nodecl.}
proc startsWith(s, prefix: string): bool =
var i = 0
while true:
if prefix[i] == '\0': return true
if s[i] != prefix[i]: return false
inc(i)
proc endsWith(s, suffix: string): bool =
var
i = 0
j = len(s) - len(suffix)
while true:
if suffix[i] == '\0': return true
if s[i+j] != suffix[i]: return false
inc(i)
proc repeatChar(count: int, c: Char = ' '): string =
result = newString(count)
for i in 0..count-1:
result[i] = c
proc intToStr(x: int, minchars: int = 1): string =
result = $abs(x)
for i in 1 .. minchars - len(result):
result = '0' & result
if x < 0:
result = '-' & result
proc toString[Ty](x: Ty): string = return $x
proc toOctal(c: char): string =
var
val: int
result = newString(3)
val = ord(c)
for i in countdown(2, 0):
result[i] = Chr(val mod 8 + ord('0'))
val = val div 8
proc `%`(formatstr: string, a: string): string =
return formatstr % [a]
proc findNormalized(x: string, inArray: openarray[string]): int =
var i = 0
while i < high(inArray):
if cmpIgnoreStyle(x, inArray[i]) == 0: return i
inc(i, 2) # incrementing by 1 would probably result in a
# security whole ...
return -1
proc `%`(formatstr: string, a: openarray[string]): string =
# the format operator
const
PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\128'..'\255', '_'}
result = ""
var i = 0
while i < len(formatstr):
if formatstr[i] == '$':
case formatstr[i+1] # again we use the fact that strings
# are zero-terminated here
of '$':
add result, '$'
inc(i, 2)
of '1'..'9':
var j = 0
inc(i) # skip $
while formatstr[i] in {'0'..'9'}:
j = j * 10 + ord(formatstr[i]) - ord('0')
inc(i)
add result, a[j - 1]
of '{':
var j = i+1
while formatstr[j] notin {'\0', '}'}: inc(j)
var x = findNormalized(copy(formatstr, i+2, j-1), a)
if x >= 0 and x < high(a): add result, a[x+1]
else: raise newException(EInvalidValue, "invalid format string")
i = j+1
of 'a'..'z', 'A'..'Z', '\128'..'\255', '_':
var j = i+1
while formatstr[j] in PatternChars: inc(j)
var x = findNormalized(copy(formatstr, i+1, j-1), a)
if x >= 0 and x < high(a): add result, a[x+1]
else: raise newException(EInvalidValue, "invalid format string")
i = j
else: raise newException(EInvalidValue, "invalid format string")
else:
add result, formatstr[i]
inc(i)
proc cmpIgnoreCase(a, b: string): int =
# makes usage of the fact that strings are zero-terminated
var
aa, bb: char
for i in 0..len(a)-1:
aa = toLower(a[i])
bb = toLower(b[i])
result = ord(aa) - ord(bb)
if result != 0: break
{.push checks: off, line_trace: off .} # this is a hot-spot in the compiler!
# thus we compile without checks here
proc cmpIgnoreStyle(a, b: string): int =
var
aa, bb: char
i = 0
j = 0
while True:
while a[i] == '_': inc(i)
while b[j] == '_': inc(j) # BUGFIX: typo
aa = toLower(a[i])
bb = toLower(b[j])
result = ord(aa) - ord(bb)
if result != 0 or aa == '\0': break
inc(i)
inc(j)
{.pop.}
# ---------- splitting -----------------------------------------------------
proc splitSeq(s: string, seps: set[char]): seq[string] =
result = []
for sub in split(s, seps): add result, sub
# ---------------------------------------------------------------------------
proc strip(s: string): string =
const
chars: set[Char] = Whitespace
var
first = 0
last = len(s)-1
while s[first] in chars: inc(first)
while last >= 0 and s[last] in chars: dec(last)
result = copy(s, first, last)
proc toLower(c: Char): Char =
if c in {'A'..'Z'}:
result = chr(ord(c) + (ord('a') - ord('A')))
else:
result = c
proc toLower(s: string): string =
result = newString(len(s))
for i in 0..len(s) - 1:
result[i] = toLower(s[i])
proc toUpper(c: Char): Char =
if c in {'a'..'z'}:
result = Chr(Ord(c) - (Ord('a') - Ord('A')))
else:
result = c
proc toUpper(s: string): string =
result = newString(len(s))
for i in 0..len(s) - 1:
result[i] = toUpper(s[i])
proc capitalize(s: string): string =
result = toUpper(s[0]) & copy(s, 1)
proc normalize(s: string): string =
result = ""
for i in 0..len(s) - 1:
if s[i] in {'A'..'Z'}:
add result, Chr(Ord(s[i]) + (Ord('a') - Ord('A')))
elif s[i] != '_':
add result, s[i]
type
TSkipTable = array[Char, int]
proc preprocessSub(sub: string, a: var TSkipTable) =
var m = len(sub)
for i in 0..0xff: a[chr(i)] = m+1
for i in 0..m-1: a[sub[i]] = m-i
proc findSubStrAux(sub, s: string, start: int, a: TSkipTable): int =
# fast "quick search" algorithm:
var
m = len(sub)
n = len(s)
# search:
var j = start
while j <= n - m:
block match:
for k in 0..m-1:
if sub[k] != s[k+j]: break match
return j
inc(j, a[s[j+m]])
return -1
proc findSubStr(sub, s: string, start: int = 0): int =
var a: TSkipTable
preprocessSub(sub, a)
result = findSubStrAux(sub, s, start, a)
# slow linear search:
#var
# i, j, M, N: int
#M = len(sub)
#N = len(s)
#i = start
#j = 0
#if i >= N:
# result = -1
#else:
# while True:
# if s[i] == sub[j]:
# Inc(i)
# Inc(j)
# else:
# i = i - j + 1
# j = 0
# if (j >= M):
# return i - M
# elif (i >= N):
# return -1
proc findSubStr(sub: char, s: string, start: int = 0): int =
for i in start..len(s)-1:
if sub == s[i]: return i
return -1
proc in_Operator(s: string, c: char): bool =
return findSubStr(c, s) >= 0
proc in_Operator(s, sub: string): bool =
return findSubStr(sub, s) >= 0
proc replaceStr(s, sub, by: string): string =
var
i, j: int
a: TSkipTable
result = ""
preprocessSub(sub, a)
i = 0
while true:
j = findSubStrAux(sub, s, i, a)
if j < 0: break
add result, copy(s, i, j - 1)
add result, by
i = j + len(sub)
# copy the rest:
add result, copy(s, i)
proc deleteStr(s: var string, first, last: int) =
# example: "abc___uvwxyz\0" (___ is to be deleted)
# --> first == 3, last == 5
# s[first..] = s[last+1..]
var
i = first
while last+i+1 < len(s):
s[i] = s[last+i+1]
inc(i)
setlen(s, len(s)-(last-first+1))
# parsing numbers:
proc sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs.}
proc toHex(x: BiggestInt, len: int): string =
const
HexChars = "0123456789ABCDEF"
var
shift: BiggestInt
result = newString(len)
shift = 0
for j in countdown(len-1, 0):
result[j] = HexChars[toU32(x shr shift) and 0xF]
shift = shift + 4
{.push overflowChecks: on.}
# this must be compiled with overflow checking turned on:
proc rawParseInt(s: string, index: var int): BiggestInt =
# index contains the start position at proc entry; end position will be
# an index before the proc returns; index = -1 on error (no number at all)
# the problem here is that integers have an asymmetrical range: there is
# one more valid negative than prositive integer. Thus we perform the
# computation as a negative number and then change the sign at the end.
var
i: int
sign: BiggestInt
i = index
# a local i is more efficient than accessing an in out parameter
sign = -1
if s[i] == '+':
inc(i)
elif s[i] == '-':
inc(i)
sign = 1
if s[i] in {'0'..'9'}:
result = 0
while s[i] in {'0'..'9'}:
result = result * 10 - (ord(s[i]) - ord('0'))
inc(i)
while s[i] == '_':
inc(i) # underscores are allowed and ignored
result = result * sign
index = i # store index back
else:
index = -1
{.pop.} # overflowChecks
proc parseInt(s: string): int =
var
index: int
res: BiggestInt
index = strStart
res = rawParseInt(s, index)
if index == -1:
raise newException(EInvalidValue, "invalid integer: " & s)
elif (sizeof(int) <= 4) and
((res < low(int)) or (res > high(int))):
raise newException(EOverflow, "overflow")
else:
result = int(res) # convert to smaller integer type
proc ParseFloat(s: string): float =
var
hd, esign, sign: float
exponent, i: int
flags: int
result = 0.0
i = 0
exponent = 0
esign = 1.0
flags = 0
sign = 1.0
if s[i] == '+': inc(i)
elif s[i] == '-':
sign = -1.0
inc(i)
while s[i] in {'0'..'9'}:
# Read integer part
flags = flags or 1
result = result * 10.0 + toFloat(ord(s[i]) - ord('0'))
inc(i)
while s[i] == '_': inc(i)
# Decimal?
if s[i] == '.':
hd = 1.0
inc(i)
while s[i] in {'0'..'9'}:
# Read fractional part
flags = flags or 2
result = result * 10.0 + toFloat(ord(s[i]) - ord('0'))
hd = hd * 10.0
inc(i)
while s[i] == '_': inc(i)
result = result / hd # this complicated way preserves precision
# Again, read integer and fractional part
if flags == 0:
raise newException(EInvalidValue, "invalid float:" & s)
# Exponent?
if s[i] in {'e', 'E'}:
inc(i)
if s[i] == '+':
inc(i)
elif s[i] == '-':
esign = -1.0
inc(i)
if s[i] notin {'0'..'9'}:
raise newException(EInvalidValue, "invalid float: " & s)
while s[i] in {'0'..'9'}:
exponent = exponent * 10 + ord(s[i]) - ord('0')
inc(i)
while s[i] == '_': inc(i)
# Calculate Exponent
hd = 1.0
for j in 1..exponent:
hd = hd * 10.0
if esign > 0.0: result = result * hd
else: result = result / hd
# Not all characters are read?
if s[i] != '\0': raise newException(EInvalidValue, "invalid float: " & s)
# evaluate sign
result = result * sign
proc toOct*(x: BiggestInt, len: int): string =
## converts `x` into its octal representation. The resulting string is
## always `len` characters long. No leading ``0c`` prefix is generated.
var
mask, shift: BiggestInt
assert(len > 0)
result = newString(len)
mask = 7
shift = 0
for j in countdown(len-1, 0):
result[j] = chr(int((x and mask) shr shift) + ord('0'))
shift = shift + 3
mask = mask shl 3
proc toBin*(x: BiggestInt, len: int): string =
## converts `x` into its binary representation. The resulting string is
## always `len` characters long. No leading ``0b`` prefix is generated.
var
mask, shift: BiggestInt
assert(len > 0)
result = newString(len)
mask = 1
shift = 0
for j in countdown(len-1, 0):
result[j] = chr(int((x and mask) shr shift) + ord('0'))
shift = shift + 1
mask = mask shl 1
{.pop.}

163
lib/sysio.nim Executable file
View File

@@ -0,0 +1,163 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Nimrod's standard IO library. It contains high-performance
## routines for reading and writing data to (buffered) files or
## TTYs.
{.push debugger:off .} # the user does not want to trace a part
# of the standard library!
proc fputs(c: cstring, f: TFile) {.importc: "fputs", noDecl.}
proc fgets(c: cstring, n: int, f: TFile): cstring {.importc: "fgets", noDecl.}
proc fgetc(stream: TFile): int {.importc: "fgetc", nodecl.}
proc ungetc(c: int, f: TFile) {.importc: "ungetc", nodecl.}
proc putc(c: Char, stream: TFile) {.importc: "putc", nodecl.}
proc fprintf(f: TFile, frmt: CString) {.importc: "fprintf", nodecl, varargs.}
proc strlen(c: cstring): int {.importc: "strlen", nodecl.}
proc setvbuf(stream: TFile, buf: pointer, typ, size: cint): cint {.
importc, nodecl.}
proc write(f: TFile, c: cstring) = fputs(c, f)
var
IOFBF {.importc: "_IOFBF", nodecl.}: cint
IONBF {.importc: "_IONBF", nodecl.}: cint
# copied here to remove dependancy on strutils:
#proc toNimstr(x: Cstring, len: int): string {.
# noSideEffect, importc: "toNimStr".}
proc rawReadLine(f: TFile, result: var string) {.noStatic.} =
# of course this could be optimized a bit; but IO is slow anyway...
# and it was difficult to get this CORRECT with Ansi C's methods
var
c: cint
setLen(result, 0) # reuse the buffer!
while True:
c = fgetc(f)
if c < 0:
result = nil
break # EOF
if c == 10: break # LF
if c == 13: # CR
c = fgetc(f) # is the next char LF?
if c != 10: ungetc(c, f) # no, put the character back
break
add result, chr(int(c))
proc readLine(f: TFile): string =
result = ""
rawReadLine(f, result)
proc readFile(filename: string): string =
var f: TFile
try:
if openFile(f, filename):
var len = getFileSize(f)
if len < high(int):
result = newString(int(len))
if readBuffer(f, addr(result[0]), int(len)) != len:
result = nil
closeFile(f)
else:
result = nil
except EIO:
result = nil
proc write(f: TFile, s: string) = fputs(s, f)
proc write(f: TFile, i: int) = fprintf(f, "%ld", i)
proc write(f: TFile, b: bool) =
if b: write(f, "true")
else: write(f, "false")
proc write(f: TFile, r: float) = fprintf(f, "%g", r)
proc write(f: TFile, c: Char) = putc(c, f)
proc EndOfFile(f: TFile): bool =
# do not blame me; blame the ANSI C standard this is so brain-damaged
var
c: int
c = fgetc(f)
ungetc(c, f)
return c == -1
proc writeln[Ty](f: TFile, x: Ty) =
write(f, x)
write(f, "\n")
proc echo[Ty](x: Ty) = writeln(stdout, x)
# interface to the C procs:
proc fopen(filename, mode: CString): pointer {.importc: "fopen", noDecl.}
const
FormatOpen: array [TFileMode, string] = ["rb", "wb", "w+b", "r+b", "ab"]
#"rt", "wt", "w+t", "r+t", "at"
# we always use binary here as for Nimrod the OS line ending
# should not be translated.
proc OpenFile(f: var TFile, filename: string,
mode: TFileMode = fmRead,
bufSize: int = -1): Bool =
var
p: pointer
p = fopen(filename, FormatOpen[mode])
result = (p != nil)
f = cast[TFile](p)
if bufSize > 0:
if setvbuf(f, nil, IOFBF, bufSize) != 0:
raise newException(EOutOfMemory, "out of memory")
elif bufSize == 0:
discard setvbuf(f, nil, IONBF, 0)
# C routine that is used here:
proc fread(buf: Pointer, size, n: int, f: TFile): int {.
importc: "fread", noDecl.}
proc fseek(f: TFile, offset: clong, whence: int): int {.
importc: "fseek", noDecl.}
proc ftell(f: TFile): int {.importc: "ftell", noDecl.}
proc fwrite(buf: Pointer, size, n: int, f: TFile): int {.
importc: "fwrite", noDecl.}
# size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);
proc readBuffer(f: TFile, buffer: pointer, len: int): int =
result = fread(buffer, 1, len, f)
proc ReadBytes(f: TFile, a: var openarray[byte], start, len: int): int =
result = readBuffer(f, addr(a[start]), len)
proc ReadChars(f: TFile, a: var openarray[char], start, len: int): int =
result = readBuffer(f, addr(a[start]), len)
proc writeBytes(f: TFile, a: openarray[byte], start, len: int): int =
result = writeBuffer(f, addr(a[start]), len)
proc writeChars(f: TFile, a: openarray[char], start, len: int): int =
result = writeBuffer(f, addr(a[start]), len)
proc writeBuffer(f: TFile, buffer: pointer, len: int): int =
result = fwrite(buffer, 1, len, f)
proc setFilePos(f: TFile, pos: int64) =
if fseek(f, clong(pos), 0) != 0:
raise newException(EIO, "cannot set file position")
proc getFilePos(f: TFile): int64 =
result = ftell(f)
if result < 0: raise newException(EIO, "cannot retrieve file position")
proc getFileSize(f: TFile): int64 =
var oldPos = getFilePos(f)
discard fseek(f, 0, 2) # seek the end of the file
result = getFilePos(f)
setFilePos(f, oldPos)
{.pop.}

294
lib/sysstr.nim Executable file
View File

@@ -0,0 +1,294 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# string & sequence handling procedures needed by the code generator
# strings are dynamically resized, have a length field
# and are zero-terminated, so they can be casted to C
# strings easily
# we don't use refcounts because that's a behaviour
# the programmer may not want
type
TStringDesc {.importc, nodecl.} = record
len, space: int # len and space without counting the terminating zero
data: array[0..0, char] # for the '\0' character
mstring {.importc: "string".} = ptr TStringDesc
# implementation:
proc resize(old: int): int {.inline.} =
assert(old < 65536 * 4)
if old <= 0: return 1
elif old < 65536: return old * 2
else: return old * 3 div 2 # for large arrays * 3/2 is better
proc cmpStrings(a, b: mstring): int {.inline, compilerProc.} =
if a == b: return 0
if a == nil: return -1
if b == nil: return 1
return c_strcmp(a.data, b.data)
proc eqStrings(a, b: mstring): bool {.inline, compilerProc.} =
if a == b: return true
if a == nil or b == nil: return false
return a.len == b.len and
c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0
proc rawNewString(space: int): mstring {.compilerProc.} =
result = cast[mstring](newObj(addr(strDesc), sizeof(TStringDesc) +
space * sizeof(char)))
result.len = 0
result.space = space
result.data[0] = '\0'
proc mnewString(len: int): mstring {.exportc.} =
result = rawNewString(len)
result.len = len
result.data[len] = '\0'
proc toNimStr(str: CString, len: int): mstring {.compilerProc.} =
result = rawNewString(len)
result.len = len
c_memcpy(result.data, str, (len+1) * sizeof(Char))
result.data[len] = '\0' # IO.readline relies on this!
proc cstrToNimstr(str: CString): mstring {.compilerProc.} =
return toNimstr(str, c_strlen(str))
proc copyString(src: mstring): mstring {.compilerProc.} =
result = rawNewString(src.space)
result.len = src.len
c_memcpy(result.data, src.data, (src.len + 1) * sizeof(Char))
proc hashString(s: string): int {.compilerproc.} =
# the compiler needs exactly the same hash function!
# this used to be used for efficient generation of string case statements
var
h: int
h = 0
for i in 0..Len(s)-1:
h = h +% Ord(s[i])
h = h +% h shl 10
h = h xor (h shr 6)
h = h +% h shl 3
h = h xor (h shr 11)
h = h +% h shl 15
result = h
# copy(s: string, start = 0): string
# {.extern: "copyStr", noDecl, noSideEffect.}
# copy(s: string, start, len: int): string
# {.extern: "copyStrLen", noDecl, noSideEffect.}
#
# setLength(var s: string, newlen: int)
# {.extern: "setLengthStr", noDecl, noSideEffect.}
proc copyStrLast(s: mstring, start, last: int): mstring {.exportc.} =
var
len: int
if start >= s.len: return mnewString(0) # BUGFIX
if last >= s.len:
len = s.len - start # - 1 + 1
else:
len = last - start + 1
result = rawNewString(len)
result.len = len
c_memcpy(result.data, addr(s.data[start]), len * sizeof(Char))
result.data[len] = '\0'
proc copyStr(s: mstring, start: int): mstring {.exportc.} =
return copyStrLast(s, start, s.len-1)
proc addChar(s: mstring, c: char): mstring {.compilerProc.} =
result = s
if result.len >= result.space:
result.space = resize(result.space)
result = cast[mstring](growObj(result,
sizeof(TStringDesc) + result.space * sizeof(char)))
result.data[result.len] = c
result.data[result.len+1] = '\0'
inc(result.len)
# These routines should be used like following:
# <Nimrod code>
# s &= "hallo " & name & " how do you feel?"
#
# <generated C code>
# {
# s = resizeString(s, 6 + name->len + 17);
# appendString(s, strLit1);
# appendString(s, strLit2);
# appendString(s, strLit3);
# }
#
# <Nimrod code>
# s = "hallo " & name & " how do you feel?"
#
# <generated C code>
# {
# string tmp0;
# tmp0 = rawNewString(6 + name->len + 17);
# appendString(s, strLit1);
# appendString(s, strLit2);
# appendString(s, strLit3);
# s = tmp0;
# }
#
# <Nimrod code>
# s = ""
#
# <generated C code>
# s = rawNewString(0);
proc resizeString(dest: mstring, addlen: int): mstring {.compilerproc.} =
if dest.len + addLen + 1 <= dest.space: # BUGFIX: this is horrible!
result = dest
else: # slow path:
var
sp = max(resize(dest.space), dest.len + addLen + 1)
result = cast[mstring](growObj(dest, sizeof(TStringDesc) +
sp * sizeof(Char)))
# DO NOT UPDATE LEN YET: dest.len = newLen
result.space = sp
proc appendString(dest, src: mstring) {.compilerproc, inline.} =
c_memcpy(addr(dest.data[dest.len]), src.data, (src.len + 1) * sizeof(Char))
inc(dest.len, src.len)
proc appendChar(dest: mstring, c: char) {.compilerproc, inline.} =
dest.data[dest.len] = c
dest.data[dest.len+1] = '\0'
inc(dest.len)
proc setLengthStr(s: mstring, newLen: int): mstring {.compilerProc.} =
var n = max(newLen, 0)
if n <= s.space:
result = s
else:
result = resizeString(s, n)
result.len = n
result.data[n] = '\0'
# ----------------- sequences ----------------------------------------------
proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
# increments the length by one:
# this is needed for supporting the &= operator;
#
# add seq x generates:
# seq = incrSeq(seq, sizeof(x));
# seq[seq->len-1] = x;
result = seq
if result.len >= result.space:
var
s: TAddress
result.space = resize(result.space)
result = cast[PGenericSeq](growObj(result, elemSize * result.space +
GenericSeqSize))
# set new elements to zero:
s = cast[TAddress](result)
zeroMem(cast[pointer](s + GenericSeqSize + (result.len * elemSize)),
(result.space - result.len) * elemSize)
# for i in len .. space-1:
# seq->data[i] = 0
inc(result.len)
proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
compilerProc.} =
result = seq
if result.space < newLen:
var
s: TAddress
result.space = max(resize(result.space), newLen)
result = cast[PGenericSeq](growObj(result, elemSize * result.space +
GenericSeqSize))
# set new elements to zero (needed for GC):
s = cast[TAddress](result)
zeroMem(cast[pointer](s + GenericSeqSize + (result.len * elemSize)),
(result.space - result.len) * elemSize)
# Else: We could decref references, if we had type information here :-(
# However, this does not happen often
result.len = newLen
# --------------- other string routines ----------------------------------
proc `$`(x: int): string =
result = newString(sizeof(x)*4)
var i = 0
var y = x
while True:
var d = y div 10
result[i] = chr(abs(int(y - d*10)) + ord('0'))
inc(i)
y = d
if y == 0: break
if x < 0:
result[i] = '-'
inc(i)
setLen(result, i)
# mirror the string:
for j in 0..i div 2 - 1:
swap(result[j], result[i-j-1])
{.push warnings: off.}
proc `$`(x: float): string =
var buf: array [0..59, char]
c_sprintf(buf, "%#g", x)
return $buf
{.pop.}
proc `$`(x: int64): string =
# we don't rely on C's runtime here as some C compiler's
# int64 support is weak
result = newString(sizeof(x)*4)
var i = 0
var y = x
while True:
var d = y div 10
result[i] = chr(abs(int(y - d*10)) + ord('0'))
inc(i)
y = d
if y == 0: break
if x < 0:
result[i] = '-'
inc(i)
setLen(result, i)
# mirror the string:
for j in 0..i div 2 - 1:
swap(result[j], result[i-j-1])
proc `$`(x: bool): string =
if x: result = "true"
else: result = "false"
proc `$`(x: char): string =
result = newString(1)
result[0] = x
proc `$`(x: string): string =
# this is useful for generic code!
return x
proc binaryStrSearch(x: openarray[string], y: string): int {.compilerproc.} =
var
a = 0
b = len(x)
while a < b:
var mid = (a + b) div 2
if x[mid] < y:
a = mid + 1
else:
b = mid
if (a < len(x)) and (x[a] == y):
return a
else:
return -1

1184
lib/system.nim Executable file

File diff suppressed because it is too large Load Diff

179
lib/times.nim Executable file
View File

@@ -0,0 +1,179 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module contains routines and types for dealing with time.
{.push debugger:off .} # the user does not want to trace a part
# of the standard library!
import
strutils
type
TMonth* = enum ## represents a month
mJan, mFeb, mMar, mApr, mMay, mJun, mJul, mAug, mSep, mOct, mNov, mDec
TWeekDay* = enum ## represents a weekday
dMon, dTue, dWed, dThu, dFri, dSat, dSun
TTime* {.importc: "time_t".} = record ## abstract type that represents a time
TTimeInfo* = record ## represents a time in different parts
second*: range[0..61] ## The number of seconds after the minute,
## normally in the range 0 to 59, but can
## be up to 61 to allow for leap seconds.
minute*: range[0..59] ## The number of minutes after the hour,
## in the range 0 to 59.
hour*: range[0..23] ## The number of hours past midnight,
## in the range 0 to 23.
monthday*: range[1..31] ## The day of the month, in the range 1 to 31.
month*: TMonth ## The current month.
year*: int ## The current year.
weekday*: TWeekDay ## The current day of the week.
yearday*: range[0..365] ## The number of days since January 1,
## in the range 0 to 365.
proc getTime*(): TTime ## gets the current calendar time
proc getLocalTime*(t: TTime): TTimeInfo
## converts the calendar time `t` to broken-time representation,
## expressed relative to the user's specified time zone.
proc getGMTime*(t: TTime): TTimeInfo
## converts the calendar time `t` to broken-down time representation,
## expressed in Coordinated Universal Time (UTC).
proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime
## converts a broken-down time structure, expressed as local time, to
## calendar time representation. The function ignores the specified
## contents of the structure members `weekday` and `yearday` and recomputes
## them from the other information in the broken-down time structure.
proc `$` *(timeInfo: TTimeInfo): string
## converts a `TTimeInfo` record to a
## string representation.
proc `$` *(time: TTime): string
## converts a calendar time to a
## string representation.
proc getDateStr*(): string
## gets the current date as a string of the format
## ``YYYY-MM-DD``.
proc getClockStr*(): string
## gets the current clock time as a string of the format ``HH:MM:SS``.
proc `-` *(a, b: TTime): int64
## computes the difference of two calendar times. Result is in seconds.
proc getStartMilsecs*(): int
## get the miliseconds from the start of the program
#implementation
# C wrapper:
type
structTM {.importc: "struct tm".} = record
second {.importc: "tm_sec".},
minute {.importc: "tm_min".},
hour {.importc: "tm_hour".},
monthday {.importc: "tm_mday".},
month {.importc: "tm_mon".},
year {.importc: "tm_year".},
weekday {.importc: "tm_wday".},
yearday {.importc: "tm_yday".},
isdst {.importc: "tm_isdst".}: cint
PTimeInfo = ptr structTM
PTime = ptr TTime
TClock {.importc: "clock_t".} = range[low(int)..high(int)]
proc localtime(timer: PTime): PTimeInfo {.
importc: "localtime", header: "<time.h>".}
proc gmtime(timer: PTime): PTimeInfo {.importc: "gmtime", header: "<time.h>".}
proc timec(timer: PTime): TTime {.importc: "time", header: "<time.h>".}
proc mktime(t: structTM): TTime {.importc: "mktime", header: "<time.h>".}
proc asctime(tblock: structTM): CString {.
importc: "asctime", header: "<time.h>".}
proc ctime(time: PTime): CString {.importc: "ctime", header: "<time.h>".}
# strftime(s: CString, maxsize: int, fmt: CString, t: tm): int {.
# importc: "strftime", header: "<time.h>".}
proc clock(): TClock {.importc: "clock", header: "<time.h>".}
proc difftime(a, b: TTime): float {.importc: "difftime", header: "<time.h>".}
var
clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
# our own procs on top of that:
proc tmToTimeInfo(tm: structTM): TTimeInfo =
const
weekDays: array [0..6, TWeekDay] = [
dSun, dMon, dTue, dWed, dThu, dFri, dSat]
result.second = int(tm.second)
result.minute = int(tm.minute)
result.hour = int(tm.hour)
result.monthday = int(tm.monthday)
result.month = TMonth(tm.month)
result.year = tm.year + 1900
result.weekday = weekDays[int(tm.weekDay)]
result.yearday = int(tm.yearday)
proc timeInfoToTM(t: TTimeInfo): structTM =
const
weekDays: array [TWeekDay, int] = [1, 2, 3, 4, 5, 6, 0]
result.second = t.second
result.minute = t.minute
result.hour = t.hour
result.monthday = t.monthday
result.month = ord(t.month)
result.year = t.year - 1900
result.weekday = weekDays[t.weekDay]
result.yearday = t.yearday
result.isdst = -1
proc `-` (a, b: TTime): int64 =
return toInt(difftime(a, b)) # XXX: toBiggestInt is needed here, but
# Nim does not support it!
proc getStartMilsecs(): int = return clock() div (clocksPerSec div 1000)
proc getTime(): TTime = return timec(nil)
proc getLocalTime(t: TTime): TTimeInfo =
var a = t
result = tmToTimeInfo(localtime(addr(a))^)
# copying is needed anyway to provide reentrancity; thus
# the convertion is not expensive
proc getGMTime(t: TTime): TTimeInfo =
var a = t
result = tmToTimeInfo(gmtime(addr(a))^)
# copying is needed anyway to provide reentrancity; thus
# the convertion is not expensive
proc TimeInfoToTime(timeInfo: TTimeInfo): TTime =
var cTimeInfo = timeInfo # for C++ we have to make a copy,
# because the header of mktime is broken in my version of libc
return mktime(timeInfoToTM(cTimeInfo))
proc getDateStr(): string =
var ti = getLocalTime(getTime())
result = $ti.year & "-" & intToStr(ord(ti.month)+1, 2) &
"-" & intToStr(ti.monthDay, 2)
proc getClockStr(): string =
var ti = getLocalTime(getTime())
result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 2) &
':' & intToStr(ti.second, 2)
proc `$`(timeInfo: TTimeInfo): string =
return $asctime(timeInfoToTM(timeInfo))
proc `$`(time: TTime): string =
var a = time
return $ctime(addr(a))
{.pop.}

221
lib/typeinfo.nim Executable file
View File

@@ -0,0 +1,221 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# type-info module for Nimrod
include hti
proc typeid(x: any): PNimType
type
Variant = opaque record
# contains the address and a typeinfo
a: pointer # an address
k: TNimTypeKind
# conversions to any and from any are inserted by the compiler!
# x.attr is supported, as well as x[]!
# here is a special iterator for variants:
iterator fields(x: variant): (fieldname: string, value: variant) =
proc setField(structure: variant, fieldname: string, value: variant)
proc getField(structure: variant, fieldname: string)
# any is implemented as a pair (val: pointer, info: PTypeInfo)
# val is for:
# an array - its address
# a record - its address
# an object - its address
# a string - the address of the pointer to the string data
# a sequence - the address of the pointer to the sequence data
# a float - the address of a memory location where the float is stored
# this is a given address; storage comes from compiler or is
# already there (in a container)
# an int - the address of a memory location where the int is stored
# storage comes from compiler or is
# already there (in a container)
# a cstring - the address of an address of an array of chars
# a ref - the address of the ref! (not the ref itself!)
# But this does not work too well...
# Better: any is a ref to Object; than we define intObj, floatObj,
# etc.; for strings this not needed as they already fit into the
# scheme!
#
type
TAnyImpl {.exportc: "TAnyImpl".} = record
typ {.exportc: "info".}: PNimType
val {.exportc: "val".}: pointer
proc
typeKind(p: PNimType): TTypeKind {.inline.}
getAnyLength(x: any): int
isContainer(x: any): bool
writeAny(container: any, index: int, val: any)
readAny(container: any, index: int): any
writeAny(container: any, name: string, val: any)
readAny(container: any, name: string): any
getAttr(container: any, index: int, out name: string, out val: any)
getEnumStrings(enumeration: any): sequence of string
anyToInt(x: any): biggestint
anyToFloat(x: any): biggestfloat
anyToString(x: any): string
anyToChar(x: any): char
anyToBool(x: any): bool
#anyToT{T}(x: any, out result: T)
# etc...
#write(a: array of any) # also possible!
#generic proc
# deepCopy{T}(x: T): T
import
strutils
proc anyToImpl(a: any): TAnyImpl {.inline.} =
result = cast{TAnyImpl}(a)
proc typeKind(p: PNimType): TTypeKind =
result = p.typeKind
type
Pint = untraced ref int
Pint8 = untraced ref int8
Pint16 = untraced ref int16
Pint32 = untraced ref int32
Pint64 = untraced ref int64
Puint = untraced ref uint
Puint8 = untraced ref uint8
Puint16 = untraced ref uint16
Puint32 = untraced ref uint32
Puint64 = untraced ref uint64
Pfloat = untraced ref float
Pfloat32 = untraced ref float32
Pfloat64 = untraced ref float64
Pstring = untraced ref string
Pbool = untraced ref bool
Pchar = untraced ref char
proc anyToInt(x: any): biggestint =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyInt, tyEnum: result = cast{pint}(x.val)^
of tySInt8: result = cast{pint8}(x.val)^
of tySInt16: result = cast{pint16}(x.val)^
of tySInt32: result = cast{pint32}(x.val)^
of tySInt64: result = cast{pint64}(x.val)^
of tyUInt: result = cast{puint}(x.val)^
of tyUInt8: result = cast{puint8}(x.val)^
of tyUInt16: result = cast{puint16}(x.val)^
of tyUInt32: result = cast{puint32}(x.val)^
of tyUInt64: result = cast{puint64}(x.val)^
else: raise EConvertError
proc anyToFloat(x: any): biggestfloat =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyReal: result = cast{pfloat}(x.val)^
of tyReal32: result = cast{pfloat32}(x.val)^
of tyReal64: result = cast{pfloat64}(x.val)^
# of tyReal128:
else: raise EConvertError
proc anyToString(x: any): string =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyString: result = cast{pstring}(x.val)^
else: raise EConvertError
proc anyToChar(x: any): char =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyChar: result = cast{pchar}(x.val)^
else: raise EConvertError
proc anyToBool(x: any): bool =
var impl = anyToImpl(x)
case impl.typ.typeKind
of tyBool: result = cast{pbool}(x.val)^
else: raise EConvertError
proc getAnyLength(x: any): int =
result = anyToImpl(x).typ.len
const
ContainerSet = {tyArray, tyRecord, tyObject, tyOpenArray, tySequence, tyTable}
proc isContainer(x: any): bool =
result = anyToImpl(x).typ.typeKind in ContainerSet
proc strcmp(a, b: cstring): int {.external: "strcmp", nodecl.}
proc strToIndex(info: PTypeInfo, str: string): int =
for i in 0..typ.len-1:
if strcmp(info.slots[i].name, str) == 0:
return i
raise EConvertError
proc writeAny(container: any, index: int, val: any) =
var x = anyToImpl(container)
if index >= 0 and index < container.len:
case x.typ.typeKind
of tySequence:
var u = cast{TAddress}(x.val)
genericAssignAux(cast{pointer}(u) +% x.typ.slots[index].offset +%
GenericSeqSize,
anyToImpl(val).val, u.typ.baseType)
of tyArray:
of tyRecord, tyObject:
else: raise EConvertError
else:
raise EIndexError
proc readAny(container: any, index: int): any =
var x = anyToImpl(container)
if x.typ.typeKind in ContainerSet:
if index >= 0 and index < container.len:
# XXX
else:
raise EIndexError
else:
raise EConvertError
proc writeAny(container: any, name: string, val: any) =
result = writeAny(container, strToIndex(anyToImpl(container).typ), val)
proc readAny(container: any, name: string): any =
result = readAny(container, strToIndex(anyToImpl(container).typ))
proc getAttr(container: any, index: int, out name: string, out val: any) =
var x = anyToImpl(container)
if x.typ.typeKind in ContainerSet:
val = readAny(container, index)
name = $x.typ.slots[index].name
else:
raise EConvertError
proc getEnumStrings(enumeration: any): sequence of string =
result = []
var x = anyToImpl(enumeration)
if x.typ.typekind == tyEnum:
for i in 0 .. x.typ.len-1:
result &= $x.typ.slots[i].name
else:
raise EConvertError

103
lib/unicode.nim Executable file
View File

@@ -0,0 +1,103 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
type
TUniChar* = int32 ## type that can hold any Unicode character
TUniChar16* = int16 ##
template ones(n) = ((1 shl n)-1)
proc uniCharLen*(s: string): int =
## returns the number of Unicode characters of the string `s`.
var i = 0
while i < len(s):
if ord(s[i]) <= 127:
inc(i)
elif ord(s[i]) shr 5 == 0b110:
inc(i, 2)
elif ord(s[i]) shr 4 == 0b1110:
inc(i, 3)
elif ord(s[i]) shr 3 == 0b11110:
inc(i, 4)
else:
assert(false)
inc(result)
proc uniCharAt*(s: string, i: int): TUniChar =
if ord(s[i]) <= 127:
result = ord(s[i])
elif ord(s[i]) shr 5 == 0b110:
assert(ord(s[i+1]) shr 6 == 0b10)
result = (ord(s[i]) and ones(5)) shl 6 or (ord(s[i+1]) and ones(6))
elif ord(s[i]) shr 4 == 0b1110:
assert(ord(s[i+1]) shr 6 == 0b10)
assert(ord(s[i+2]) shr 6 == 0b10)
result = (ord(s[i]) and ones(4)) shl 12 or
(ord(s[i+1]) and ones(6)) shl 6 or
(ord(s[i+2]) and ones(6))
elif ord(s[i]) shr 3 == 0b11110:
assert(ord(s[i+1]) shr 6 == 0b10)
assert(ord(s[i+2]) shr 6 == 0b10)
assert(ord(s[i+3]) shr 6 == 0b10)
result = (ord(s[i]) and ones(3)) shl 18 or
(ord(s[i+1]) and ones(6)) shl 12 or
(ord(s[i+2]) and ones(6)) shl 6 or
(ord(s[i+3]) and ones(6))
else:
assert(false)
iterator unichars*(s: string): TUniChar =
## iterates over any unicode character of the string `s`. Fastest possible
## method.
var
i = 0
result: TUniChar
while i < len(s):
if ord(s[i]) <= 127:
result = ord(s[i])
inc(i)
elif ord(s[i]) shr 5 == 0b110:
result = (ord(s[i]) and ones(5)) shl 6 or (ord(s[i+1]) and ones(6))
inc(i, 2)
elif ord(s[i]) shr 4 == 0b1110:
result = (ord(s[i]) and ones(4)) shl 12 or
(ord(s[i+1]) and ones(6)) shl 6 or
(ord(s[i+2]) and ones(6))
inc(i, 3)
elif ord(s[i]) shr 3 == 0b11110:
result = (ord(s[i]) and ones(3)) shl 18 or
(ord(s[i+1]) and ones(6)) shl 12 or
(ord(s[i+2]) and ones(6)) shl 6 or
(ord(s[i+3]) and ones(6))
inc(i, 4)
else:
assert(false)
yield result
proc utf8toLocale*(s: string): string
proc localeToUtf8*(s: string): string
proc utf8toUtf16*(s: string): seq[TUniChar16]
proc utf8toUcs4*(s: string): seq[TUniChar] =
result = []
for u in unichars(s):
proc ucs4ToUtf8(s: seq[TUnichar]): string
proc utf16ToUtf8(s: seq[TUnichar16]): string
proc ucs4toUft16(s: seq[TUnichar]): seq[TUnichar16]
proc uft16toUcs4(s: seq[Tunichar16]): seq[TUnichar]
proc cmpUnicode*(a, b: string): int =
## treats `a` and `b` as UTF-8 strings and compares them. Returns:
## | < 0 iff a < b
## | > 0 iff a > b
## | == 0 iff a == b
## This routine is useful for sorting UTF-8 strings.
return -1

2656
lib/windows/mmsystem.nim Executable file

File diff suppressed because it is too large Load Diff

230
lib/windows/nb30.nim Executable file
View File

@@ -0,0 +1,230 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# NetBIOS 3.0 interface unit
# This unit contains the definitions for portable NetBIOS 3.0 support.
import # Data structure templates
Windows
const
NCBNAMSZ* = 16 # absolute length of a net name
MAX_LANA* = 254 # lana's in range 0 to MAX_LANA inclusive
type # Network Control Block
PNCB* = ptr TNCB
TNCBPostProc* = proc (P: PNCB)
TNCB* = record # Structure returned to the NCB command NCBASTAT is ADAPTER_STATUS followed
# by an array of NAME_BUFFER structures.
ncb_command*: Char # command code
ncb_retcode*: Char # return code
ncb_lsn*: Char # local session number
ncb_num*: Char # number of our network name
ncb_buffer*: cstring # address of message buffer
ncb_length*: int16 # size of message buffer
ncb_callname*: array[0..NCBNAMSZ - 1, char] # blank-padded name of remote
ncb_name*: array[0..NCBNAMSZ - 1, char] # our blank-padded netname
ncb_rto*: Char # rcv timeout/retry count
ncb_sto*: Char # send timeout/sys timeout
ncb_post*: TNCBPostProc # POST routine address
ncb_lana_num*: Char # lana (adapter) number
ncb_cmd_cplt*: Char # 0xff => commmand pending
ncb_reserve*: array[0..9, Char] # reserved, used by BIOS
ncb_event*: THandle # HANDLE to Win32 event which
# will be set to the signalled
# state when an ASYNCH command
# completes
PAdapterStatus* = ptr TAdapterStatus
TAdapterStatus* = record
adapter_address*: array[0..5, Char]
rev_major*: Char
reserved0*: Char
adapter_type*: Char
rev_minor*: Char
duration*: int16
frmr_recv*: int16
frmr_xmit*: int16
iframe_recv_err*: int16
xmit_aborts*: int16
xmit_success*: DWORD
recv_success*: DWORD
iframe_xmit_err*: int16
recv_buff_unavail*: int16
t1_timeouts*: int16
ti_timeouts*: int16
reserved1*: DWORD
free_ncbs*: int16
max_cfg_ncbs*: int16
max_ncbs*: int16
xmit_buf_unavail*: int16
max_dgram_size*: int16
pending_sess*: int16
max_cfg_sess*: int16
max_sess*: int16
max_sess_pkt_size*: int16
name_count*: int16
PNameBuffer* = ptr TNameBuffer
TNameBuffer* = record
name*: array[0..NCBNAMSZ - 1, Char]
name_num*: Char
name_flags*: Char
const # values for name_flags bits.
NAME_FLAGS_MASK* = 0x00000087
GROUP_NAME* = 0x00000080
UNIQUE_NAME* = 0x00000000
REGISTERING* = 0x00000000
REGISTERED* = 0x00000004
DEREGISTERED* = 0x00000005
DUPLICATE* = 0x00000006
DUPLICATE_DEREG* = 0x00000007
type # Structure returned to the NCB command NCBSSTAT is SESSION_HEADER followed
# by an array of SESSION_BUFFER structures. If the NCB_NAME starts with an
# asterisk then an array of these structures is returned containing the
# status for all names.
PSessionHeader* = ptr TSessionHeader
TSessionHeader* = record
sess_name*: Char
num_sess*: Char
rcv_dg_outstanding*: Char
rcv_any_outstanding*: Char
PSessionBuffer* = ptr TSessionBuffer
TSessionBuffer* = record
lsn*: Char
state*: Char
local_name*: array[0..NCBNAMSZ - 1, Char]
remote_name*: array[0..NCBNAMSZ - 1, Char]
rcvs_outstanding*: Char
sends_outstanding*: Char
const # Values for state
LISTEN_OUTSTANDING* = 0x00000001
CALL_PENDING* = 0x00000002
SESSION_ESTABLISHED* = 0x00000003
HANGUP_PENDING* = 0x00000004
HANGUP_COMPLETE* = 0x00000005
SESSION_ABORTED* = 0x00000006
type # Structure returned to the NCB command NCBENUM.
# On a system containing lana's 0, 2 and 3, a structure with
# length =3, lana[0]=0, lana[1]=2 and lana[2]=3 will be returned.
PLanaEnum* = ptr TLanaEnum
TLanaEnum* = record # Structure returned to the NCB command NCBFINDNAME is FIND_NAME_HEADER followed
# by an array of FIND_NAME_BUFFER structures.
len*: Char # Number of valid entries in lana[]
lana*: array[0..MAX_LANA, Char]
PFindNameHeader* = ptr TFindNameHeader
TFindNameHeader* = record
node_count*: int16
reserved*: Char
unique_group*: Char
PFindNameBuffer* = ptr TFindNameBuffer
TFindNameBuffer* = record # Structure provided with NCBACTION. The purpose of NCBACTION is to provide
# transport specific extensions to netbios.
len*: Char
access_control*: Char
frame_control*: Char
destination_addr*: array[0..5, Char]
source_addr*: array[0..5, Char]
routing_info*: array[0..17, Char]
PActionHeader* = ptr TActionHeader
TActionHeader* = record
transport_id*: int32
action_code*: int16
reserved*: int16
const # Values for transport_id
ALL_TRANSPORTS* = "M\0\0\0"
MS_NBF* = "MNBF" # Special values and constants
const # NCB Command codes
NCBCALL* = 0x00000010 # NCB CALL
NCBLISTEN* = 0x00000011 # NCB LISTEN
NCBHANGUP* = 0x00000012 # NCB HANG UP
NCBSEND* = 0x00000014 # NCB SEND
NCBRECV* = 0x00000015 # NCB RECEIVE
NCBRECVANY* = 0x00000016 # NCB RECEIVE ANY
NCBCHAINSEND* = 0x00000017 # NCB CHAIN SEND
NCBDGSEND* = 0x00000020 # NCB SEND DATAGRAM
NCBDGRECV* = 0x00000021 # NCB RECEIVE DATAGRAM
NCBDGSENDBC* = 0x00000022 # NCB SEND BROADCAST DATAGRAM
NCBDGRECVBC* = 0x00000023 # NCB RECEIVE BROADCAST DATAGRAM
NCBADDNAME* = 0x00000030 # NCB ADD NAME
NCBDELNAME* = 0x00000031 # NCB DELETE NAME
NCBRESET* = 0x00000032 # NCB RESET
NCBASTAT* = 0x00000033 # NCB ADAPTER STATUS
NCBSSTAT* = 0x00000034 # NCB SESSION STATUS
NCBCANCEL* = 0x00000035 # NCB CANCEL
NCBADDGRNAME* = 0x00000036 # NCB ADD GROUP NAME
NCBENUM* = 0x00000037 # NCB ENUMERATE LANA NUMBERS
NCBUNLINK* = 0x00000070 # NCB UNLINK
NCBSENDNA* = 0x00000071 # NCB SEND NO ACK
NCBCHAINSENDNA* = 0x00000072 # NCB CHAIN SEND NO ACK
NCBLANSTALERT* = 0x00000073 # NCB LAN STATUS ALERT
NCBACTION* = 0x00000077 # NCB ACTION
NCBFINDNAME* = 0x00000078 # NCB FIND NAME
NCBTRACE* = 0x00000079 # NCB TRACE
ASYNCH* = 0x00000080 # high bit set = asynchronous
# NCB Return codes
NRC_GOODRET* = 0x00000000 # good return
# also returned when ASYNCH request accepted
NRC_BUFLEN* = 0x00000001 # illegal buffer length
NRC_ILLCMD* = 0x00000003 # illegal command
NRC_CMDTMO* = 0x00000005 # command timed out
NRC_INCOMP* = 0x00000006 # message incomplete, issue another command
NRC_BADDR* = 0x00000007 # illegal buffer address
NRC_SNUMOUT* = 0x00000008 # session number out of range
NRC_NORES* = 0x00000009 # no resource available
NRC_SCLOSED* = 0x0000000A # session closed
NRC_CMDCAN* = 0x0000000B # command cancelled
NRC_DUPNAME* = 0x0000000D # duplicate name
NRC_NAMTFUL* = 0x0000000E # name table full
NRC_ACTSES* = 0x0000000F # no deletions, name has active sessions
NRC_LOCTFUL* = 0x00000011 # local session table full
NRC_REMTFUL* = 0x00000012 # remote session table full
NRC_ILLNN* = 0x00000013 # illegal name number
NRC_NOCALL* = 0x00000014 # no callname
NRC_NOWILD* = 0x00000015 # cannot put * in NCB_NAME
NRC_INUSE* = 0x00000016 # name in use on remote adapter
NRC_NAMERR* = 0x00000017 # name deleted
NRC_SABORT* = 0x00000018 # session ended abnormally
NRC_NAMCONF* = 0x00000019 # name conflict detected
NRC_IFBUSY* = 0x00000021 # interface busy, IRET before retrying
NRC_TOOMANY* = 0x00000022 # too many commands outstanding, retry later
NRC_BRIDGE* = 0x00000023 # NCB_lana_num field invalid
NRC_CANOCCR* = 0x00000024 # command completed while cancel occurring
NRC_CANCEL* = 0x00000026 # command not valid to cancel
NRC_DUPENV* = 0x00000030 # name defined by anther local process
NRC_ENVNOTDEF* = 0x00000034 # environment undefined. RESET required
NRC_OSRESNOTAV* = 0x00000035 # required OS resources exhausted
NRC_MAXAPPS* = 0x00000036 # max number of applications exceeded
NRC_NOSAPS* = 0x00000037 # no saps available for netbios
NRC_NORESOURCES* = 0x00000038 # requested resources are not available
NRC_INVADDRESS* = 0x00000039 # invalid ncb address or length > segment
NRC_INVDDID* = 0x0000003B # invalid NCB DDID
NRC_LOCKFAIL* = 0x0000003C # lock of user area failed
NRC_OPENERR* = 0x0000003F # NETBIOS not loaded
NRC_SYSTEM* = 0x00000040 # system error
NRC_PENDING* = 0x000000FF # asynchronous command is not yet finished
# main user entry point for NetBIOS 3.0
# Usage: Result = Netbios( pncb );
proc Netbios*(P: PNCB): Char{.stdcall, dynlib: "netapi32.dll",
importc: "Netbios".}
# implementation

208
lib/windows/ole2.nim Executable file
View File

@@ -0,0 +1,208 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import
windows
const
GUID_NULL*: TGUID = (D1: 0x00000000, D2: 0x00000000, D3: 0x00000000, D4: [
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000])
IID_IUnknown*: TGUID = (D1: 0x00000000, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IClassFactory*: TGUID = (D1: 0x00000001, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IMarshal*: TGUID = (D1: 0x00000003, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IMalloc*: TGUID = (D1: 0x00000002, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IStdMarshalInfo*: TGUID = (D1: 0x00000018, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IExternalConnection*: TGUID = (D1: 0x00000019, D2: 0x00000000,
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000046])
IID_IEnumUnknown*: TGUID = (D1: 0x00000100, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IBindCtx*: TGUID = (D1: 0x0000000E, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IEnumMoniker*: TGUID = (D1: 0x00000102, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IRunnableObject*: TGUID = (D1: 0x00000126, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IRunningObjectTable*: TGUID = (D1: 0x00000010, D2: 0x00000000,
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000046])
IID_IPersist*: TGUID = (D1: 0x0000010C, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IPersistStream*: TGUID = (D1: 0x00000109, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IMoniker*: TGUID = (D1: 0x0000000F, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IEnumString*: TGUID = (D1: 0x00000101, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IStream*: TGUID = (D1: 0x0000000C, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IEnumStatStg*: TGUID = (D1: 0x0000000D, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IStorage*: TGUID = (D1: 0x0000000B, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IPersistFile*: TGUID = (D1: 0x0000010B, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IPersistStorage*: TGUID = (D1: 0x0000010A, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_ILockBytes*: TGUID = (D1: 0x0000000A, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IEnumFormatEtc*: TGUID = (D1: 0x00000103, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IEnumStatData*: TGUID = (D1: 0x00000105, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IRootStorage*: TGUID = (D1: 0x00000012, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IAdviseSink*: TGUID = (D1: 0x0000010F, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IAdviseSink2*: TGUID = (D1: 0x00000125, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IDataObject*: TGUID = (D1: 0x0000010E, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IDataAdviseHolder*: TGUID = (D1: 0x00000110, D2: 0x00000000,
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000046])
IID_IMessageFilter*: TGUID = (D1: 0x00000016, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IRpcChannelBuffer*: TGUID = (D1: 0xD5F56B60, D2: 0x0000593B,
D3: 0x0000101A, D4: [0x000000B5, 0x00000069, 0x00000008, 0x00000000,
0x0000002B, 0x0000002D, 0x000000BF, 0x0000007A])
IID_IRpcProxyBuffer*: TGUID = (D1: 0xD5F56A34, D2: 0x0000593B, D3: 0x0000101A, D4: [
0x000000B5, 0x00000069, 0x00000008, 0x00000000, 0x0000002B, 0x0000002D,
0x000000BF, 0x0000007A])
IID_IRpcStubBuffer*: TGUID = (D1: 0xD5F56AFC, D2: 0x0000593B, D3: 0x0000101A, D4: [
0x000000B5, 0x00000069, 0x00000008, 0x00000000, 0x0000002B, 0x0000002D,
0x000000BF, 0x0000007A])
IID_IPSFactoryBuffer*: TGUID = (D1: 0xD5F569D0, D2: 0x0000593B,
D3: 0x0000101A, D4: [0x000000B5, 0x00000069, 0x00000008, 0x00000000,
0x0000002B, 0x0000002D, 0x000000BF, 0x0000007A])
IID_ICreateTypeInfo*: TGUID = (D1: 0x00020405, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_ICreateTypeLib*: TGUID = (D1: 0x00020406, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IDispatch*: TGUID = (D1: 0x00020400, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IEnumVariant*: TGUID = (D1: 0x00020404, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_ITypeComp*: TGUID = (D1: 0x00020403, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_ITypeInfo*: TGUID = (D1: 0x00020401, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_ITypeLib*: TGUID = (D1: 0x00020402, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IErrorInfo*: TGUID = (D1: 0x1CF2B120, D2: 0x0000547D, D3: 0x0000101B, D4: [
0x0000008E, 0x00000065, 0x00000008, 0x00000000, 0x0000002B, 0x0000002B,
0x000000D1, 0x00000019])
IID_ICreateErrorInfo*: TGUID = (D1: 0x22F03340, D2: 0x0000547D,
D3: 0x0000101B, D4: [0x0000008E, 0x00000065, 0x00000008, 0x00000000,
0x0000002B, 0x0000002B, 0x000000D1, 0x00000019])
IID_ISupportErrorInfo*: TGUID = (D1: 0xDF0B3D60, D2: 0x0000548F,
D3: 0x0000101B, D4: [0x0000008E, 0x00000065, 0x00000008, 0x00000000,
0x0000002B, 0x0000002B, 0x000000D1, 0x00000019])
IID_IOleAdviseHolder*: TGUID = (D1: 0x00000111, D2: 0x00000000,
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000046])
IID_IOleCache*: TGUID = (D1: 0x0000011E, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IOleCache2*: TGUID = (D1: 0x00000128, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IOleCacheControl*: TGUID = (D1: 0x00000129, D2: 0x00000000,
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000046])
IID_IParseDisplayName*: TGUID = (D1: 0x0000011A, D2: 0x00000000,
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000046])
IID_IOleContainer*: TGUID = (D1: 0x0000011B, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IOleClientSite*: TGUID = (D1: 0x00000118, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IOleObject*: TGUID = (D1: 0x00000112, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IOleWindow*: TGUID = (D1: 0x00000114, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IOleLink*: TGUID = (D1: 0x0000011D, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IOleItemContainer*: TGUID = (D1: 0x0000011C, D2: 0x00000000,
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000046])
IID_IOleInPlaceUIWindow*: TGUID = (D1: 0x00000115, D2: 0x00000000,
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000046])
IID_IOleInPlaceActiveObject*: TGUID = (D1: 0x00000117, D2: 0x00000000,
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000046])
IID_IOleInPlaceFrame*: TGUID = (D1: 0x00000116, D2: 0x00000000,
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000046])
IID_IOleInPlaceObject*: TGUID = (D1: 0x00000113, D2: 0x00000000,
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000046])
IID_IOleInPlaceSite*: TGUID = (D1: 0x00000119, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IViewObject*: TGUID = (D1: 0x0000010D, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IViewObject2*: TGUID = (D1: 0x00000127, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IDropSource*: TGUID = (D1: 0x00000121, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IDropTarget*: TGUID = (D1: 0x00000122, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])
IID_IEnumOleVerb*: TGUID = (D1: 0x00000104, D2: 0x00000000, D3: 0x00000000, D4: [
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000046])

Some files were not shown because too many files have changed in this diff Show More