version 0.7.0

This commit is contained in:
Andreas Rumpf 2008-11-16 22:08:15 +01:00
commit 8b2a9401a1
185 changed files with 21451 additions and 24296 deletions

163
cogapp.py
View file

@ -1,15 +1,17 @@
""" Cog code generation tool. """ Cog code generation tool.
http://nedbatchelder.com/code/cog http://nedbatchelder.com/code/cog
Copyright 2004-2008, Ned Batchelder. Copyright 2004-2008, Ned Batchelder.
""" """
# $Id: cogapp.py 141 2008-05-22 10:56:43Z nedbat $ # $Id: cogapp.py 141 2008-05-22 10:56:43Z nedbat $
# modified to run with Python1.5.2 by Andreas Rumpf
import md5, os, re, string, sys, traceback, types import md5, os, re, string, sys, traceback, types
import imp, compiler import imp
import copy, getopt, shlex import copy, getopt, shlex
from cStringIO import StringIO from cStringIO import StringIO
from string import strip, split, join, replace
__all__ = ['Cog', 'CogUsageError'] __all__ = ['Cog', 'CogUsageError']
@ -56,7 +58,7 @@ class CogError(Exception):
Exception.__init__(self, "%s(%d): %s" % (file, line, msg)) Exception.__init__(self, "%s(%d): %s" % (file, line, msg))
else: else:
Exception.__init__(self, msg) Exception.__init__(self, msg)
class CogUsageError(CogError): class CogUsageError(CogError):
""" An error in usage of command-line arguments in cog. """ An error in usage of command-line arguments in cog.
""" """
@ -78,7 +80,7 @@ class Redirectable:
def __init__(self): def __init__(self):
self.stdout = sys.stdout self.stdout = sys.stdout
self.stderr = sys.stderr self.stderr = sys.stderr
def setOutput(self, stdout=None, stderr=None): def setOutput(self, stdout=None, stderr=None):
""" Assign new files for standard out and/or standard error. """ Assign new files for standard out and/or standard error.
""" """
@ -94,12 +96,16 @@ class CogGenerator(Redirectable):
Redirectable.__init__(self) Redirectable.__init__(self)
self.markers = [] self.markers = []
self.lines = [] self.lines = []
def parseMarker(self, l): def parseMarker(self, l):
self.markers.append(l) self.markers.append(l)
def parseLine(self, l): def parseLine(self, l):
self.lines.append(l.strip('\n')) s = 0
e = len(l)
while s < len(l) and l[s] == '\n': s = s + 1
while e >= 1 and l[e-1] == '\n': e = e - 1
self.lines.append(l[s:e+1])
def getCode(self): def getCode(self):
""" Extract the executable Python code from the generator. """ Extract the executable Python code from the generator.
@ -109,11 +115,17 @@ class CogGenerator(Redirectable):
# then remove it from all the lines. # then remove it from all the lines.
prefIn = commonPrefix(self.markers + self.lines) prefIn = commonPrefix(self.markers + self.lines)
if prefIn: if prefIn:
self.markers = [ l.replace(prefIn, '', 1) for l in self.markers ] tmp = []
self.lines = [ l.replace(prefIn, '', 1) for l in self.lines ] for l in self.markers: tmp.append(replace(l, prefIn, '', 1))
self.markers = tmp
tmp = []
for l in self.lines: tmp.append(replace(l, prefIn, '', 1))
self.lines = tmp
#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, '') return reindentBlock(self.lines, '')
def evaluate(self, cog, globals, fname='cog generator'): def evaluate(self, cog, globals, fname='cog generator'):
# figure out the right whitespace prefix for the output # figure out the right whitespace prefix for the output
prefOut = whitePrefix(self.markers) prefOut = whitePrefix(self.markers)
@ -121,17 +133,22 @@ class CogGenerator(Redirectable):
intext = self.getCode() intext = self.getCode()
if not intext: if not intext:
return '' 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')
# In Python 2.2, the last line has to end in a newline.
intext = "import cog\n" + replace(intext, "\r\n", "\n") + "\n"
code = None
try:
import compiler
except ImportError:
code = compile(intext, str(fname), 'exec')
if code == None:
code = compiler.compile(intext, filename=str(fname), mode='exec')
# Make sure the "cog" module has our state. # Make sure the "cog" module has our state.
cog.cogmodule.msg = self.msg cog.cogmodule.msg = self.msg
cog.cogmodule.out = self.out cog.cogmodule.out = self.out
cog.cogmodule.outl = self.outl cog.cogmodule.outl = self.outl
cog.cogmodule.error = self.error cog.cogmodule.error = self.error
self.outstring = '' self.outstring = ''
eval(code, globals) eval(code, globals)
@ -139,31 +156,31 @@ class CogGenerator(Redirectable):
# ends with a newline, or it will be joined to the # ends with a newline, or it will be joined to the
# end-output line, ruining cog's idempotency. # end-output line, ruining cog's idempotency.
if self.outstring and self.outstring[-1] != '\n': if self.outstring and self.outstring[-1] != '\n':
self.outstring += '\n' self.outstring = self.outstring + '\n'
return reindentBlock(self.outstring, prefOut) return reindentBlock(self.outstring, prefOut)
def msg(self, s): def msg(self, s):
print >>self.stdout, "Message: "+s self.stdout.write("Message: "+s+"\n")
def out(self, sOut='', dedent=False, trimblanklines=False): def out(self, sOut='', dedent=False, trimblanklines=False):
""" The cog.out function. """ The cog.out function.
""" """
if trimblanklines and ('\n' in sOut): if trimblanklines and ('\n' in sOut):
lines = sOut.split('\n') lines = split(sOut, '\n')
if lines[0].strip() == '': if strip(lines[0]) == '':
del lines[0] del lines[0]
if lines and lines[-1].strip() == '': if lines and strip(lines[-1]) == '':
del lines[-1] del lines[-1]
sOut = '\n'.join(lines)+'\n' sOut = join(lines,'\n')+'\n'
if dedent: if dedent:
sOut = reindentBlock(sOut) sOut = reindentBlock(sOut)
self.outstring += sOut self.outstring = self.outstring + sOut
def outl(self, sOut='', **kw): def outl(self, sOut='', dedent=False, trimblanklines=False):
""" The cog.outl function. """ The cog.outl function.
""" """
self.out(sOut, **kw) self.out(sOut, dedent, trimblanklines)
self.out('\n') self.out('\n')
def error(self, msg='Error raised by cog generator.'): def error(self, msg='Error raised by cog generator.'):
@ -185,7 +202,7 @@ class NumberedFileReader:
def readline(self): def readline(self):
l = self.f.readline() l = self.f.readline()
if l: if l:
self.n += 1 self.n = self.n + 1
return l return l
def linenumber(self): def linenumber(self):
@ -211,7 +228,7 @@ class CogOptions:
self.bEofCanBeEnd = False self.bEofCanBeEnd = False
self.sSuffix = None self.sSuffix = None
self.bNewlines = False self.bNewlines = False
def __cmp__(self, other): def __cmp__(self, other):
""" Comparison operator for tests to use. """ Comparison operator for tests to use.
""" """
@ -225,7 +242,7 @@ class CogOptions:
def addToIncludePath(self, dirs): def addToIncludePath(self, dirs):
""" Add directories to the include path. """ Add directories to the include path.
""" """
dirs = dirs.split(os.pathsep) dirs = split(dirs, os.pathsep)
self.includePath.extend(dirs) self.includePath.extend(dirs)
def parseArgs(self, argv): def parseArgs(self, argv):
@ -244,7 +261,7 @@ class CogOptions:
elif o == '-D': elif o == '-D':
if a.count('=') < 1: if a.count('=') < 1:
raise CogUsageError("-D takes a name=value argument") raise CogUsageError("-D takes a name=value argument")
name, value = a.split('=', 1) name, value = split(a, '=', 1)
self.defines[name] = value self.defines[name] = value
elif o == '-e': elif o == '-e':
self.bWarnEmpty = True self.bWarnEmpty = True
@ -281,6 +298,14 @@ class CogOptions:
raise CogUsageError("Can't use -o with -r (they are opposites)") raise CogUsageError("Can't use -o with -r (they are opposites)")
def mydigest(hasher):
result = ""
for c in hasher.digest():
x = hex(ord(c))[2:]
if len(x) == 1: x = "0" + x
result = result + x
return result
class Cog(Redirectable): class Cog(Redirectable):
""" The Cog engine. """ The Cog engine.
""" """
@ -294,19 +319,19 @@ class Cog(Redirectable):
self.options = CogOptions() self.options = CogOptions()
self.sOutputMode = 'w' self.sOutputMode = 'w'
self.installCogModule() self.installCogModule()
def showWarning(self, msg): def showWarning(self, msg):
print >>self.stdout, "Warning:", msg self.stdout.write("Warning: " + msg + "\n")
def isBeginSpecLine(self, s): def isBeginSpecLine(self, s):
return string.find(s, self.sBeginSpec) >= 0 return string.find(s, self.sBeginSpec) >= 0
def isEndSpecLine(self, s): def isEndSpecLine(self, s):
return string.find(s, self.sEndSpec) >= 0 and \ return string.find(s, self.sEndSpec) >= 0 and \
not self.isEndOutputLine(s) not self.isEndOutputLine(s)
def isEndOutputLine(self, s): def isEndOutputLine(self, s):
return string.find(s, self.sEndOutput) >= 0 return string.find(s, self.sEndOutput) >= 0
@ -317,7 +342,7 @@ class Cog(Redirectable):
self.cogmodule = imp.new_module('cog') self.cogmodule = imp.new_module('cog')
self.cogmodule.path = [] self.cogmodule.path = []
sys.modules['cog'] = self.cogmodule sys.modules['cog'] = self.cogmodule
def processFile(self, fIn, fOut, fname=None, globals=None): def processFile(self, fIn, fOut, fname=None, globals=None):
""" Process an input file object to an output file object. """ Process an input file object to an output file object.
fIn and fOut can be file objects, or file names. fIn and fOut can be file objects, or file names.
@ -326,19 +351,19 @@ class Cog(Redirectable):
sFileIn = fname or '' sFileIn = fname or ''
sFileOut = fname or '' sFileOut = fname or ''
# Convert filenames to files. # Convert filenames to files.
if isinstance(fIn, types.StringTypes): if type(fIn) == type(""):
# Open the input file. # Open the input file.
sFileIn = fIn sFileIn = fIn
fIn = open(fIn, 'r') fIn = open(fIn, 'r')
if isinstance(fOut, types.StringTypes): if type(fOut) == type(""):
# Open the output file. # Open the output file.
sFileOut = fOut sFileOut = fOut
fOut = open(fOut, self.sOutputMode) fOut = open(fOut, self.sOutputMode)
fIn = NumberedFileReader(fIn) fIn = NumberedFileReader(fIn)
bSawCog = False bSawCog = False
self.cogmodule.inFile = sFileIn self.cogmodule.inFile = sFileIn
self.cogmodule.outFile = sFileOut self.cogmodule.outFile = sFileOut
@ -383,12 +408,12 @@ class Cog(Redirectable):
raise CogError("Cog code markers inverted", raise CogError("Cog code markers inverted",
file=sFileIn, line=firstLineNum) file=sFileIn, line=firstLineNum)
else: else:
sCode = l[beg+len(self.sBeginSpec):end].strip() sCode = strip(l[beg+len(self.sBeginSpec):end])
gen.parseLine(sCode) gen.parseLine(sCode)
else: else:
# Deal with an ordinary code block. # Deal with an ordinary code block.
l = fIn.readline() l = fIn.readline()
# Get all the lines in the spec # Get all the lines in the spec
while l and not self.isEndSpecLine(l): while l and not self.isEndSpecLine(l):
if self.isBeginSpecLine(l): if self.isBeginSpecLine(l):
@ -409,9 +434,9 @@ class Cog(Redirectable):
if not self.options.bDeleteCode: if not self.options.bDeleteCode:
fOut.write(l) fOut.write(l)
gen.parseMarker(l) gen.parseMarker(l)
l = fIn.readline() l = fIn.readline()
# Eat all the lines in the output section. While reading past # Eat all the lines in the output section. While reading past
# them, compute the md5 hash of the old output. # them, compute the md5 hash of the old output.
hasher = md5.new() hasher = md5.new()
@ -424,14 +449,14 @@ class Cog(Redirectable):
file=sFileIn, line=fIn.linenumber()) file=sFileIn, line=fIn.linenumber())
hasher.update(l) hasher.update(l)
l = fIn.readline() l = fIn.readline()
curHash = hasher.hexdigest() curHash = mydigest(hasher)
if not l and not self.options.bEofCanBeEnd: if not l and not self.options.bEofCanBeEnd:
# We reached end of file before we found the end output line. # We reached end of file before we found the end output line.
raise CogError("Missing '%s' before end of file." % self.sEndOutput, raise CogError("Missing '%s' before end of file." % self.sEndOutput,
file=sFileIn, line=fIn.linenumber()) file=sFileIn, line=fIn.linenumber())
# Write the output of the spec to be the new output if we're # Write the output of the spec to be the new output if we're
# supposed to generate code. # supposed to generate code.
hasher = md5.new() hasher = md5.new()
if not self.options.bNoGenerate: if not self.options.bNoGenerate:
@ -440,10 +465,10 @@ class Cog(Redirectable):
sGen = self.suffixLines(sGen) sGen = self.suffixLines(sGen)
hasher.update(sGen) hasher.update(sGen)
fOut.write(sGen) fOut.write(sGen)
newHash = hasher.hexdigest() newHash = mydigest(hasher)
bSawCog = True bSawCog = True
# Write the ending output line # Write the ending output line
hashMatch = self.reEndOutput.search(l) hashMatch = self.reEndOutput.search(l)
if self.options.bHashOutput: if self.options.bHashOutput:
@ -453,17 +478,17 @@ class Cog(Redirectable):
raise CogError("Output has been edited! Delete old checksum to unprotect.", raise CogError("Output has been edited! Delete old checksum to unprotect.",
file=sFileIn, line=fIn.linenumber()) file=sFileIn, line=fIn.linenumber())
# Create a new end line with the correct hash. # Create a new end line with the correct hash.
endpieces = l.split(hashMatch.group(0), 1) endpieces = split(l, hashMatch.group(0), 1)
else: else:
# There was no old hash, but we want a new hash. # There was no old hash, but we want a new hash.
endpieces = l.split(self.sEndOutput, 1) endpieces = split(l, self.sEndOutput, 1)
l = (self.sEndFormat % newHash).join(endpieces) l = join(endpieces, (self.sEndFormat % newHash))
else: else:
# We don't want hashes output, so if there was one, get rid of # We don't want hashes output, so if there was one, get rid of
# it. # it.
if hashMatch: if hashMatch:
l = l.replace(hashMatch.groupdict()['hashsect'], '', 1) l = replace(l, hashMatch.groupdict()['hashsect'], '', 1)
if not self.options.bDeleteCode: if not self.options.bDeleteCode:
fOut.write(l) fOut.write(l)
l = fIn.readline() l = fIn.readline()
@ -473,14 +498,14 @@ class Cog(Redirectable):
# A regex for non-empty lines, used by suffixLines. # A regex for non-empty lines, used by suffixLines.
reNonEmptyLines = re.compile("^\s*\S+.*$", re.MULTILINE) reNonEmptyLines = re.compile("^\s*\S+.*$", re.MULTILINE)
def suffixLines(self, text): def suffixLines(self, text):
""" Add suffixes to the lines in text, if our options desire it. """ Add suffixes to the lines in text, if our options desire it.
text is many lines, as a single string. text is many lines, as a single string.
""" """
if self.options.sSuffix: if self.options.sSuffix:
# Find all non-blank lines, and add the suffix to the end. # Find all non-blank lines, and add the suffix to the end.
repl = r"\g<0>" + self.options.sSuffix.replace('\\', '\\\\') repl = r"\g<0>" + replace(self.options.sSuffix, '\\', '\\\\')
text = self.reNonEmptyLines.sub(repl, text) text = self.reNonEmptyLines.sub(repl, text)
return text return text
@ -492,7 +517,7 @@ class Cog(Redirectable):
fNew = StringIO() fNew = StringIO()
self.processFile(fOld, fNew, fname=fname) self.processFile(fOld, fNew, fname=fname)
return fNew.getvalue() return fNew.getvalue()
def replaceFile(self, sOldPath, sNewText): def replaceFile(self, sOldPath, sNewText):
""" Replace file sOldPath with the contents sNewText """ Replace file sOldPath with the contents sNewText
""" """
@ -500,7 +525,7 @@ class Cog(Redirectable):
# Need to ensure we can write. # Need to ensure we can write.
if self.options.sMakeWritableCmd: if self.options.sMakeWritableCmd:
# Use an external command to make the file writable. # Use an external command to make the file writable.
cmd = self.options.sMakeWritableCmd.replace('%s', sOldPath) cmd = replace(self.options.sMakeWritableCmd, '%s', sOldPath)
self.stdout.write(os.popen(cmd).read()) self.stdout.write(os.popen(cmd).read())
if not os.access(sOldPath, os.W_OK): if not os.access(sOldPath, os.W_OK):
raise CogError("Couldn't make %s writable" % sOldPath) raise CogError("Couldn't make %s writable" % sOldPath)
@ -541,23 +566,23 @@ class Cog(Redirectable):
self.sOutputMode = 'w' self.sOutputMode = 'w'
if self.options.bNewlines: if self.options.bNewlines:
self.sOutputMode = 'wb' self.sOutputMode = 'wb'
# How we process the file depends on where the output is going. # How we process the file depends on where the output is going.
if self.options.sOutputName: if self.options.sOutputName:
self.processFile(sFile, self.options.sOutputName, sFile) self.processFile(sFile, self.options.sOutputName, sFile)
elif self.options.bReplace: elif self.options.bReplace:
# We want to replace the cog file with the output, # We want to replace the cog file with the output,
# but only if they differ. # but only if they differ.
print >>self.stdout, "Cogging %s" % sFile, self.stdout.write("Cogging %s" % sFile)
bNeedNewline = True bNeedNewline = True
try: try:
fOldFile = open(sFile) fOldFile = open(sFile)
sOldText = fOldFile.read() sOldText = fOldFile.read()
fOldFile.close() fOldFile.close()
sNewText = self.processString(sOldText, fname=sFile) sNewText = self.processString(sOldText, fname=sFile)
if sOldText != sNewText: if sOldText != sNewText:
print >>self.stdout, " (changed)" self.stdout.write(" (changed)\n")
bNeedNewline = False bNeedNewline = False
self.replaceFile(sFile, sNewText) self.replaceFile(sFile, sNewText)
finally: finally:
@ -566,7 +591,7 @@ class Cog(Redirectable):
# same line, but also make sure to break the line before # same line, but also make sure to break the line before
# any traceback. # any traceback.
if bNeedNewline: if bNeedNewline:
print >>self.stdout self.stdout.write('\n')
else: else:
self.processFile(sFile, self.stdout, sFile) self.processFile(sFile, self.stdout, sFile)
finally: finally:
@ -594,7 +619,7 @@ class Cog(Redirectable):
self.options.parseArgs(args[1:]) self.options.parseArgs(args[1:])
self.options.validate() self.options.validate()
if args[0][0] == '@': if args[0][0] == '@':
if self.options.sOutputName: if self.options.sOutputName:
raise CogUsageError("Can't use -o with @file") raise CogUsageError("Can't use -o with @file")
@ -613,22 +638,22 @@ class Cog(Redirectable):
# Provide help if asked for anywhere in the command line. # Provide help if asked for anywhere in the command line.
if '-?' in argv or '-h' in argv: if '-?' in argv or '-h' in argv:
print >>self.stderr, usage, self.stderr.write(usage)
return return
self.options.parseArgs(argv) self.options.parseArgs(argv)
self.options.validate() self.options.validate()
if self.options.bShowVersion: if self.options.bShowVersion:
print >>self.stdout, "Cog version %s" % __version__ self.stdout.write("Cog version %s\n" % __version__)
return return
if self.options.args: if self.options.args:
for a in self.options.args: for a in self.options.args:
self.processArguments([a]) self.processArguments([a])
else: else:
raise CogUsageError("No files to process") raise CogUsageError("No files to process")
def main(self, argv): def main(self, argv):
""" Handle the command-line execution for cog. """ Handle the command-line execution for cog.
""" """
@ -637,14 +662,14 @@ class Cog(Redirectable):
self.callableMain(argv) self.callableMain(argv)
return 0 return 0
except CogUsageError, err: except CogUsageError, err:
print >>self.stderr, err self.stderr.write(err + "\n")
print >>self.stderr, "(for help use -?)" self.stderr.write("(for help use -?)\n")
return 2 return 2
except CogGeneratedError, err: except CogGeneratedError, err:
print >>self.stderr, "Error: %s" % err self.stderr.write("Error: %s\n" % err)
return 3 return 3
except CogError, err: except CogError, err:
print >>self.stderr, err self.stderr.write(err + "\n")
return 1 return 1
except: except:
traceback.print_exc(None, self.stderr) traceback.print_exc(None, self.stderr)

View file

@ -1,291 +0,0 @@
# This is the config file for the documentation generator.
# (c) 2008 Andreas Rumpf
# Feel free to edit the templates as you need.
split.item.toc = "25"
# too long entries in the table of contents get truncated
# after this number of characters
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" ?>
<!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. -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<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: 25em;
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: 25em;
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>
"""

View file

@ -9,12 +9,14 @@
# Environment variables cannot be used in the options, however! # Environment variables cannot be used in the options, however!
# Just call the compiler with several options: # Just call the compiler with several options:
cc = @if unix: gcc @else: vcc @end cc = @if macosx or windows: llvm_gcc @else: gcc @end
lib="$nimrod/lib" lib="$nimrod/lib"
path="$lib/base" path="$lib/base"
path="$lib/base/gtk" path="$lib/base/gtk"
path="$lib/base/cairo" path="$lib/base/cairo"
path="$lib/base/x11" path="$lib/base/x11"
path="$lib/base/sdl"
path="$lib/base/opengl"
path="$lib/windows" path="$lib/windows"
path="$lib/posix" path="$lib/posix"
path="$lib/ecmas" path="$lib/ecmas"
@ -25,20 +27,23 @@ path="$lib/extra"
stacktrace:off stacktrace:off
debugger:off debugger:off
line_dir:off line_dir:off
opt:speed
@end @end
# additional defines: # additional defines:
#define="" #define=""
# additional options always passed to the compiler: # additional options always passed to the compiler:
force_build
line_dir=off line_dir=off
cfilecache=on
# use the new experimental symbol files for speeding up compilation:
#--symbol_files
--verbosity: "1"
hint[LineTooLong]=off hint[LineTooLong]=off
hint[XDeclaredButNotUsed]=off hint[XDeclaredButNotUsed]=off
@if unix: @if unix:
passl= "-ldl" @if not bsd: passl= "-ldl" @end
path = "$lib/base/gtk" path = "$lib/base/gtk"
@end @end
@ -50,10 +55,12 @@ hint[XDeclaredButNotUsed]=off
# Configuration for the LLVM GCC compiler: # Configuration for the LLVM GCC compiler:
@if windows: @if windows:
llvm_gcc.path = r"$nimrod\dist\llvm-gcc4.2\bin" llvm_gcc.path = r"$nimrod\dist\llvm-gcc4.2\bin"
@elif macosx:
llvm_gcc.path = r"/Users/andreasrumpf/download/C/llvm-gcc4.2-2.3-x86-darwin8/bin"
@end @end
llvm_gcc.options.debug = "-g" llvm_gcc.options.debug = "-g"
llvm_gcc.options.always = "-w" llvm_gcc.options.always = "-w"
llvm_gcc.options.speed = "-O3 -ffast-math" llvm_gcc.options.speed = "-O2 -fno-strict-aliasing -ffast-math"
llvm_gcc.options.size = "-Os -ffast-math" llvm_gcc.options.size = "-Os -ffast-math"
# Configuration for the Borland C++ Compiler: # Configuration for the Borland C++ Compiler:
@ -62,23 +69,24 @@ llvm_gcc.options.size = "-Os -ffast-math"
@end @end
bcc.options.debug = "" bcc.options.debug = ""
# turn off warnings about unreachable code and inline procs: # turn off warnings about unreachable code and inline procs:
bcc.options.always = "-w- -H- -q -RT- -a8 -w-8027 -w-8066" bcc.options.always = "-H- -q -RT- -a8 -w-8027 -w-8066 -w-8004"
bcc.options.speed = "-O2 -6" bcc.options.speed = "-O2 -6"
bcc.options.size = "-O1 -6" bcc.options.size = "-O1 -6"
# Configuration for the Visual C/C++ compiler: # Configuration for the Visual C/C++ compiler:
@if vcc: @if vcc:
@prepend_env path r"C:\Eigenes\compiler\vcc2005\Common7\IDE;" @prepend_env path r"C:\Programme\Microsoft Visual Studio 9.0\Common7\IDE;"
@prepend_env INCLUDE r"C:\Eigenes\compiler\vcc2005\VC\include;C:\Eigenes\compiler\vcc2005\VC\ATLMFC\INCLUDE;" @prepend_env INCLUDE r"C:\Programme\Microsoft Visual Studio 9.0\VC\include;C:\Programme\Microsoft Visual Studio 9.0\VC\ATLMFC\INCLUDE;C:\Programme\Microsoft SDKs\Windows\v6.0A\Include;"
@prepend_env LIB r"C:\Eigenes\compiler\vcc2005\VC\lib;C:\Eigenes\compiler\vcc2005\SDK\v2.0\Lib;" @prepend_env LIB r"C:\Programme\Microsoft Visual Studio 9.0\VC\lib;C:\Programme\Microsoft Visual Studio 9.0\SDK\v2.0\Lib;C:\Programme\Microsoft SDKs\Windows\v6.0A\Lib;"
passl: r"/F33554432" # set the stack size to 8 MB
@end @end
@if windows: @if windows:
vcc.path = r"C:\Eigenes\compiler\vcc2005\VC\bin" vcc.path = r"C:\Programme\Microsoft Visual Studio 9.0\VC\bin"
@end @end
vcc.options.debug = "/RTC1 /ZI" vcc.options.debug = "/RTC1 /ZI"
vcc.options.always = "/nologo" vcc.options.always = "/nologo"
vcc.options.speed = "/Ogityb2 /G7 /arch:SSE2" vcc.options.speed = "/Ox /arch:SSE2"
vcc.options.size = "/O1 /G7" vcc.options.size = "/O1"
# Configuration for the Watcom C/C++ compiler: # Configuration for the Watcom C/C++ compiler:
@if windows: @if windows:
@ -122,10 +130,11 @@ lcc.options.size = "-O -p6"
# Configuration for the Tiny C Compiler: # Configuration for the Tiny C Compiler:
@if windows: @if windows:
tcc.path = r"C:\eigenes\compiler\tcc\bin" tcc.path = r"C:\Eigenes\compiler\tcc-0.9.23\tcc"
tcc.options.always = r"-IC:\Eigenes\compiler\tcc-0.9.23\include " &
r"-IC:\Eigenes\compiler\tcc-0.9.23\include\winapi"
@end @end
tcc.options.debug = "-b" tcc.options.debug = ""
tcc.options.always = ""
tcc.options.speed = "" tcc.options.speed = ""
tcc.options.size = "" tcc.options.size = ""
@ -146,7 +155,7 @@ icc.options.always = "-w"
icc.options.speed = "-O3 -ffast-math" icc.options.speed = "-O3 -ffast-math"
icc.options.size = "-Os -ffast-math" icc.options.size = "-Os -ffast-math"
@write "used default config file" @write "used special config file"
@if ecmascript: @if ecmascript:
@write "Target is ECMAScript! No unsafe features are allowed!" @write "Target is ECMAScript! No unsafe features are allowed!"

View file

@ -1,5 +1,4 @@
# Configuration file for the Nimrod Compiler. # Configuration file for the Nimrod Compiler.
# Generated by the koch.py script.
# (c) 2008 Andreas Rumpf # (c) 2008 Andreas Rumpf
# Feel free to edit the default values as you need. # Feel free to edit the default values as you need.
@ -8,38 +7,42 @@
# @putenv "key" "val" # @putenv "key" "val"
# Environment variables cannot be used in the options, however! # Environment variables cannot be used in the options, however!
# Just call the compiler with several options: cc = @if windows: llvm_gcc @else: gcc @end
cc = @if unix: gcc @else: vcc @end
lib="$nimrod/lib" lib="$nimrod/lib"
path="$lib/base" path="$lib/base"
path="$lib/base/gtk" path="$lib/base/gtk"
path="$lib/base/cairo" path="$lib/base/cairo"
path="$lib/base/x11" path="$lib/base/x11"
path="$lib/base/sdl"
path="$lib/base/opengl"
path="$lib/base/zip"
path="$lib/windows" path="$lib/windows"
path="$lib/posix" path="$lib/posix"
path="$lib/ecmas" path="$lib/ecmas"
path="$lib/extra" path="$lib/extra"
@if release: @if release:
checks:off obj_checks:off
field_checks:off
range_checks:off
bound_checks:off
overflow_checks:off
assertions:off
stacktrace:off stacktrace:off
debugger:off debugger:off
line_dir:off line_dir:off
opt:speed
@end @end
# additional defines:
#define=""
# additional options always passed to the compiler: # additional options always passed to the compiler:
force_build --verbosity: "1"
line_dir=off
cfilecache=on
hint[LineTooLong]=off hint[LineTooLong]=off
hint[XDeclaredButNotUsed]=off #hint[XDeclaredButNotUsed]=off
@if unix: @if unix:
passl= "-ldl" @if not bsd: passl= "-ldl" @end
path = "$lib/base/gtk"
@end @end
@if icc: @if icc:
@ -50,107 +53,48 @@ hint[XDeclaredButNotUsed]=off
# Configuration for the LLVM GCC compiler: # Configuration for the LLVM GCC compiler:
@if windows: @if windows:
llvm_gcc.path = r"$nimrod\dist\llvm-gcc4.2\bin" llvm_gcc.path = r"$nimrod\dist\llvm-gcc4.2\bin"
@elif macosx:
llvm_gcc.path =
r"/Users/andreasrumpf/download/C/llvm-gcc4.2-2.3-x86-darwin8/bin"
@end @end
llvm_gcc.options.debug = "-g" llvm_gcc.options.debug = "-g"
llvm_gcc.options.always = "-w" llvm_gcc.options.always = "-w"
llvm_gcc.options.speed = "-O3 -ffast-math" llvm_gcc.options.speed = "-O2"
llvm_gcc.options.size = "-Os -ffast-math" llvm_gcc.options.size = "-Os"
# 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: # Configuration for the Visual C/C++ compiler:
@if vcc: @if vcc:
@prepend_env path r"C:\Programme\Microsoft Visual Studio 9.0\Common7\IDE;"
@prepend_env INCLUDE r"C:\Programme\Microsoft Visual Studio 9.0\VC\include;C:\Programme\Microsoft Visual Studio 9.0\VC\ATLMFC\INCLUDE;C:\Programme\Microsoft SDKs\Windows\v6.0A\Include;"
@prepend_env LIB r"C:\Programme\Microsoft Visual Studio 9.0\VC\lib;C:\Programme\Microsoft Visual Studio 9.0\SDK\v2.0\Lib;C:\Programme\Microsoft SDKs\Windows\v6.0A\Lib;"
passl: r"/F33554432" # set the stack size to 8 MB passl: r"/F33554432" # set the stack size to 8 MB
@end @end
@if windows:
vcc.path = r"C:\Programme\Microsoft Visual Studio 9.0\VC\bin"
@end
vcc.options.debug = "/RTC1 /ZI" vcc.options.debug = "/RTC1 /ZI"
vcc.options.always = "/nologo" vcc.options.always = "/nologo"
vcc.options.speed = "/Ogityb2 /G7 /arch:SSE2" vcc.options.speed = "/Ox /arch:SSE2"
vcc.options.size = "/O1 /G7" vcc.options.size = "/O1"
# 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: # Configuration for the GNU C/C++ compiler:
@if windows: @if windows:
gcc.path = r"C:\eigenes\compiler\mingw\bin" gcc.path = r"C:\eigenes\compiler\mingw\bin"
@end @end
#gcc.exe = "gcc-4.1"
#gcc.linkerExe = "gcc-4.1"
gcc.options.debug = "-g" gcc.options.debug = "-g"
@if macosx: @if macosx:
gcc.options.always = "-w -fasm-blocks" gcc.options.always = "-w -fasm-blocks"
@else: @else:
gcc.options.always = "-w" gcc.options.always = "-w"
@end @end
gcc.options.speed = "-O3 -ffast-math" gcc.options.speed = "-O3 -fno-strict-aliasing"
gcc.options.size = "-Os -ffast-math" gcc.options.size = "-Os"
# Configuration for the Digital Mars C/C++ compiler: # Configuration for the Digital Mars C/C++ compiler:
@if windows: @if windows:
dmc.path = r"C:\eigenes\compiler\d\dm\bin" dmc.path = r"C:\eigenes\compiler\d\dm\bin"
@end @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: # Configuration for the Tiny C Compiler:
@if windows: @if windows:
tcc.path = r"C:\Eigenes\compiler\tcc-0.9.23\tcc" tcc.path = r"C:\Eigenes\compiler\tcc-0.9.23\tcc"
tcc.options.always = r"-IC:\Eigenes\compiler\tcc-0.9.23\include " & tcc.options.always = r"-IC:\Eigenes\compiler\tcc-0.9.23\include " &
r"-IC:\Eigenes\compiler\tcc-0.9.23\include\winapi" r"-IC:\Eigenes\compiler\tcc-0.9.23\include\winapi"
@end @end
tcc.options.debug = "" tcc.options.always = "-w"
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"
@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 special config file"
@if ecmascript:
@write "Target is ECMAScript! No unsafe features are allowed!"
@end

View file

@ -1,287 +0,0 @@
# 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" ?>
<!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. -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<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>
"""

View file

@ -1,165 +0,0 @@
# 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: 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/posix"
path="$lib/ecmas"
path="$lib/extra"
@if release:
checks:off
stacktrace:off
debugger:off
line_dir:off
@end
# additional defines:
#define=""
# additional options always passed to the compiler:
force_build
line_dir=off
cfilecache=on
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 LLVM GCC compiler:
@if windows:
llvm_gcc.path = r"$nimrod\dist\llvm-gcc4.2\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"
# 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
@if vcc:
@prepend_env path r"C:\Programme\Microsoft Visual Studio 9.0\Common7\IDE;"
@prepend_env INCLUDE r"C:\Programme\Microsoft Visual Studio 9.0\VC\include;C:\Programme\Microsoft Visual Studio 9.0\VC\ATLMFC\INCLUDE;C:\Programme\Microsoft SDKs\Windows\v6.0A\Include;"
@prepend_env LIB r"C:\Programme\Microsoft Visual Studio 9.0\VC\lib;C:\Programme\Microsoft Visual Studio 9.0\SDK\v2.0\Lib;C:\Programme\Microsoft SDKs\Windows\v6.0A\Lib;"
passl: r"/F8388608" # set the stack size to 8 MB
@end
@if windows:
vcc.path = r"C:\Programme\Microsoft Visual Studio 9.0\VC\bin"
@end
vcc.options.debug = "/RTC1 /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-0.9.23\tcc"
tcc.options.always = r"-IC:\Eigenes\compiler\tcc-0.9.23\include " &
r"-IC:\Eigenes\compiler\tcc-0.9.23\include\winapi"
@end
tcc.options.debug = ""
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"
@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 special config file"
@if ecmascript:
@write "Target is ECMAScript! No unsafe features are allowed!"
@end

2
configure vendored
View file

@ -1,5 +1,5 @@
#! /usr/bin/env sh #! /usr/bin/env sh
python koch.py $@ configure echo "there is nothing to configure"

View file

@ -4,21 +4,17 @@ Advanced commands::
gen_depend generate a DOT file containing the gen_depend generate a DOT file containing the
module dependency graph module dependency graph
list_def list all defined conditionals and exit list_def list all defined conditionals and exit
rst2html converts a reStructuredText file to HTML
check checks the project for syntax and semantic check checks the project for syntax and semantic
parse parses a single file (for debugging Nimrod) parse parses a single file (for debugging Nimrod)
scan tokenizes a single file (for debugging Nimrod)
debugtrans for debugging the transformation pass
Advanced options: Advanced options:
-w, --warnings:on|off warnings ON|OFF -w, --warnings:on|off warnings ON|OFF
--warning[X]:on|off specific warning X ON|OFF --warning[X]:on|off specific warning X ON|OFF
--hints:on|off hints ON|OFF --hints:on|off hints ON|OFF
--hint[X]:on|off specific hint X 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 --lib:PATH set the system library path
-c, --compile_only compile only; do not assemble or link -c, --compile_only compile only; do not assemble or link
--no_linking compile but do not link --no_linking compile but do not link
--gen_script generate a compile script (in the 'rod_gen' --gen_script generate a compile script (in the 'nimcache'
subdirectory named 'compile_$project$scriptext') subdirectory named 'compile_$project$scriptext')
--os:SYMBOL set the target operating system (cross-compilation) --os:SYMBOL set the target operating system (cross-compilation)
--cpu:SYMBOL set the target processor (cross-compilation) --cpu:SYMBOL set the target processor (cross-compilation)
@ -27,17 +23,13 @@ Advanced options:
-l, --passl:OPTION pass an option to the linker -l, --passl:OPTION pass an option to the linker
--gen_mapping generate a mapping file containing --gen_mapping generate a mapping file containing
(Nimrod, mangled) identifier pairs (Nimrod, mangled) identifier pairs
--merge_output generate only one C output file
--line_dir:on|off generation of #line directive ON|OFF --line_dir:on|off generation of #line directive ON|OFF
--checkpoints:on|off turn on|off checkpoints; for debugging Nimrod --checkpoints:on|off turn on|off checkpoints; for debugging Nimrod
--skip_cfg do not read the general configuration file --skip_cfg do not read the general configuration file
--skip_proj_cfg do not read the project's configuration file --skip_proj_cfg do not read the project's configuration file
--import:MODULE_FILE import the given module implicitly for each module --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 --index:FILE use FILE to generate a documenation index file
--putenv:key=value set an environment variable --putenv:key=value set an environment variable
--list_cmd list the commands used to execute external programs --list_cmd list the commands used to execute external programs
-v, --verbose show what Nimrod is doing --verbosity:0|1|2|3 set Nimrod's verbosity level (0 is default)
--version show detailed version information -v, --version show detailed version information

View file

@ -8,61 +8,52 @@
# #
{ {
'SymFlag': [ # already 32 flags! 'SymFlag': [ # already 26 flags!
'sfTypeCheck', # wether macro parameters should be type checked 'sfUsed', # read access of sym (for warnings) or simply used
'sfStar', # symbol has * visibility
'sfMinus', # symbol has - visibility
'sfInInterface', # symbol is in interface section declared
'sfFromGeneric', # symbol is instantiation of a generic; this is needed
# for symbol file generation; such symbols should always
# be written into the ROD file
'sfGlobal', # symbol is at global scope
'sfForward', # symbol is forward directed 'sfForward', # symbol is forward directed
'sfImportc', # symbol is external; imported 'sfImportc', # symbol is external; imported
'sfExportc', # symbol is exported (under a specified name) 'sfExportc', # symbol is exported (under a specified name)
'sfVolatile', # variable is volatile '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 'sfRegister', # variable should be placed in a register
'sfPure', # object is "pure" that means it has no type-information '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 'sfResult', # variable is 'result' in proc
'sfNoSideEffect', # proc has no side effects 'sfNoSideEffect', # proc has no side effects
'sfMainModule', # module is the main module 'sfMainModule', # module is the main module
'sfSystemModule', # module is the system module 'sfSystemModule', # module is the system module
'sfNoReturn', # proc never returns (an exit proc) 'sfNoReturn', # proc never returns (an exit proc)
'sfAddrTaken', # the variable's address is taken (ex- or implicitely) 'sfAddrTaken', # the variable's address is taken (ex- or implicitely)
'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 'sfCompilerProc', # proc is a compiler proc, that is a C proc that is
# needed for the code generator # needed for the code generator
'sfCppMethod', # proc is a C++ method 'sfCppMethod', # proc is a C++ method (not implemented yet)
'sfDiscriminant', # field is a discriminant in a record/object 'sfDiscriminant', # field is a discriminant in a record/object
'sfDeprecated', # symbol is deprecated 'sfDeprecated', # symbol is deprecated
'sfInClosure', # variable is accessed by a closure 'sfInClosure', # variable is accessed by a closure
'sfIsCopy', # symbol is a copy; needed for proper name mangling 'sfTypeCheck', # wether macro parameters should be type checked
'sfStar', # symbol has * visibility 'sfCompileTime', # proc can be evaluated at compile time
'sfMinus' # symbol has - visibility 'sfThreadVar', # variable is a thread variable
'sfMerge', # proc can be merged with itself
], ],
'TypeFlag': [ '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 'tfVarargs', # procedure has C styled varargs
'tfFinal' # is the object final? 'tfFinal', # is the object final?
'tfAcyclic', # type is acyclic (for GC optimization)
'tfEnumHasWholes' # enum cannot be mapped into a range
], ],
'TypeKind': [ # order is important! 'TypeKind': [ # order is important!
# Don't forget to change hti.nim if you make a change here # Don't forget to change hti.nim if you make a change here
'tyNone', 'tyBool', 'tyChar', 'tyNone', 'tyBool', 'tyChar',
'tyEmptySet', 'tyArrayConstr', 'tyNil', 'tyEmpty', 'tyArrayConstr', 'tyNil',
'tyGeneric', 'tyGeneric',
'tyGenericInst', # instantiated generic type 'tyGenericInst', # instantiated generic type
'tyGenericParam', 'tyGenericParam',
@ -89,7 +80,9 @@
'nfBase2', # nfBase10 is default, so not needed 'nfBase2', # nfBase10 is default, so not needed
'nfBase8', 'nfBase8',
'nfBase16', 'nfBase16',
'nfAllConst' # used to mark complex expressions constant 'nfAllConst', # used to mark complex expressions constant
'nfTransf', # node has been transformed
'nfSem', # node has been checked for semantics
], ],
'NodeKind': [ # these are pure nodes 'NodeKind': [ # these are pure nodes
@ -223,6 +216,8 @@
'nkBlockExpr', # a statement block ending in an expr; this is used 'nkBlockExpr', # a statement block ending in an expr; this is used
# to allowe powerful multi-line templates that open a # to allowe powerful multi-line templates that open a
# temporary scope # temporary scope
'nkStmtListType', # a statement list ending in a type; for macros
'nkBlockType', # a statement block ending in a type; for macros
'nkVm', # indicates a virtual instruction; integer field is 'nkVm', # indicates a virtual instruction; integer field is
# used for the concrete opcode # used for the concrete opcode
@ -264,6 +259,8 @@
'skEnumField', # an identifier in an enum 'skEnumField', # an identifier in an enum
'skForVar', # a for loop variable 'skForVar', # a for loop variable
'skModule', # module identifier 'skModule', # module identifier
'skLabel' # a label (for block statement) 'skLabel', # a label (for block statement)
'skStub' # symbol is a stub and not yet loaded from the ROD
# file (it is loaded on demand, which may mean: never)
] ]
} }

View file

@ -1,12 +1,10 @@
Usage:: Usage::
nimrod command [options] inputfile [arguments] nimrod command [options] inputfile [arguments]
Command:: Command::
compile compile project with default code generator (C) compile, c compile project with default code generator (C)
compile_to_c compile project with C code generator compile_to_c, cc compile project with C code generator
compile_to_cpp compile project with C++ code generator doc generate the documentation for inputfile
compile_to_ecmascript compile project to ECMAScript code (experimental) rst2html converts a reStructuredText file to HTML
doc generate the documentation for inputfile;
with --run switch opens it with $BROWSER
Arguments: Arguments:
arguments are passed to the program being run (if --run option is selected) arguments are passed to the program being run (if --run option is selected)
Options: Options:
@ -14,7 +12,8 @@ Options:
-o, --out:FILE set the output filename -o, --out:FILE set the output filename
-d, --define:SYMBOL define a conditional symbol -d, --define:SYMBOL define a conditional symbol
-u, --undef:SYMBOL undefine a conditional symbol -u, --undef:SYMBOL undefine a conditional symbol
-b, --force_build force rebuilding of all modules -f, --force_build force rebuilding of all modules
--symbol_files:on|off use symbol files to speed up compilation (buggy!)
--stack_trace:on|off code generation for stack trace ON|OFF --stack_trace:on|off code generation for stack trace ON|OFF
--line_trace:on|off code generation for line trace ON|OFF --line_trace:on|off code generation for line trace ON|OFF
--debugger:on|off turn Embedded Nimrod Debugger ON|OFF --debugger:on|off turn Embedded Nimrod Debugger ON|OFF

View file

@ -1,22 +0,0 @@
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

View file

@ -3,16 +3,20 @@
[ [
'None', 'None',
'Defined', 'Defined',
'New',
'NewFinalize',
'Low', 'Low',
'High', 'High',
'SizeOf', 'SizeOf',
'RegisterFinalizer', 'Is',
'Succ', 'Succ',
'Pred', 'Pred',
'Inc', 'Inc',
'Dec', 'Dec',
'Ord',
'New',
'NewFinalize',
'NewSeq',
'RegisterFinalizer',
'LengthOpenArray', 'LengthOpenArray',
'LengthStr', 'LengthStr',
'LengthArray', 'LengthArray',
@ -20,8 +24,9 @@
'Incl', 'Incl',
'Excl', 'Excl',
'Card', 'Card',
'Ord',
'Chr', 'Chr',
'GCref',
'GCunref',
# binary arithmetic with and without overflow checking: # binary arithmetic with and without overflow checking:
'AddI', 'AddI',
@ -161,7 +166,6 @@
'AppendSeqSeq', 'AppendSeqSeq',
'InRange', 'InRange',
'InSet', 'InSet',
'Is',
'Asgn', 'Asgn',
'Repr', 'Repr',
'Exit', 'Exit',
@ -170,15 +174,34 @@
'Assert', 'Assert',
'Swap', 'Swap',
'IsNil', 'IsNil',
'ArrToSeq',
# magic type constructors: # magic types:
'Array', 'Array',
'OpenArray', 'OpenArray',
'Range', 'Range',
'Set', 'Set',
'Seq', 'Seq',
'Int',
'Int8',
'Int16',
'Int32',
'Int64',
'Float',
'Float32',
'Float64',
'Bool',
'Char',
'String',
'Cstring',
'Pointer',
'AnyEnum',
'EmptySet',
'IntSetBaseType',
'Nil',
# magic constants: # magic constants:
'IsMainModule',
'CompileDate', 'CompileDate',
'CompileTime', 'CompileTime',
'NimrodVersion', 'NimrodVersion',

View file

@ -153,7 +153,8 @@
{'errSizeTooBig': "computing the type's size produced an overflow"}, {'errSizeTooBig': "computing the type's size produced an overflow"},
{'errSetTooBig': 'set is too large'}, {'errSetTooBig': 'set is too large'},
{'errBaseTypeMustBeOrdinal': 'base type of a set must be an ordinal'}, {'errBaseTypeMustBeOrdinal': 'base type of a set must be an ordinal'},
{'errInheritanceOnlyWithNonFinalObjects': 'inheritance only works non-final objects'}, {'errInheritanceOnlyWithNonFinalObjects':
'inheritance only works with non-final objects'},
{'errInheritanceOnlyWithEnums': 'inheritance only works with an enum'}, {'errInheritanceOnlyWithEnums': 'inheritance only works with an enum'},
{'errIllegalRecursionInTypeX': "illegal recursion in type '$1'"}, {'errIllegalRecursionInTypeX': "illegal recursion in type '$1'"},
{'errCannotInstantiateX': "cannot instantiate: '$1'"}, {'errCannotInstantiateX': "cannot instantiate: '$1'"},
@ -278,16 +279,17 @@
# hints: # hints:
{'hintSuccess': 'operation successful'}, {'hintSuccess': 'operation successful'},
{'hintSuccessX': 'operation successful ($1 lines compiled; $2 sec total)'},
{'hintLineTooLong': 'line too long'}, {'hintLineTooLong': 'line too long'},
{'hintXDeclaredButNotUsed': "'$1' is declared but not used"}, {'hintXDeclaredButNotUsed': "'$1' is declared but not used"},
{'hintConvToBaseNotNeeded': 'conversion to base object is not needed'}, {'hintConvToBaseNotNeeded': 'conversion to base object is not needed'},
{'hintConvFromXtoItselfNotNeeded': 'conversion from $1 to itself is pointless'}, {'hintConvFromXtoItselfNotNeeded': 'conversion from $1 to itself is pointless'},
{'hintExprAlwaysX': "expression evaluates always to '$1'"}, {'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"},
{'hintQuitCalled': "quit() called"}, {'hintQuitCalled': "quit() called"},
{'hintProcessing': "processing"}, {'hintProcessing': "processing $1"},
{'hintCodeBegin': "generated code listing:"},
{'hintCodeEnd': "end of listing"},
{'hintConf': "used config file '$1'"},
# user hint message: # user hint message:
{'hintUser': '$1'} {'hintUser': '$1'}

View file

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

View file

@ -11,6 +11,7 @@ ast type definitions of the abstract syntax tree (AST) and
node constructors node constructors
astalgo algorithms for containers of AST nodes; converting the astalgo algorithms for containers of AST nodes; converting the
AST to YAML; the symbol table AST to YAML; the symbol table
passes implement the passes managemer for passes over the AST
trees few algorithms for nodes; this module is less important trees few algorithms for nodes; this module is less important
types module for traversing type graphs; also contain several types module for traversing type graphs; also contain several
helpers for dealing with types helpers for dealing with types
@ -23,19 +24,15 @@ semtypes contains the semantic checking phase for types
idents implements a general mapping from identifiers to an internal idents implements a general mapping from identifiers to an internal
representation (``PIdent``) that is used, so that a simple representation (``PIdent``) that is used, so that a simple
pointer comparison suffices to say whether two Nimrod id-comparison suffices to say whether two Nimrod identifiers
identifiers are equivalent are equivalent
ropes implements long strings using represented as trees for ropes implements long strings using represented as trees for
lazy evaluation; used mainly by the code generators lazy evaluation; used mainly by the code generators
ccgobj contains type definitions neeeded for C code generation ccgobj contains type definitions neeeded for C code generation
and some helpers and some helpers
ccgmangl contains the name mangler for converting Nimrod
identifiers to their C counterparts
ccgutils contains helpers for the C code generator 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 ccgtypes the generator for C types
ccgstmts the generator for statements ccgstmts the generator for statements
ccgexprs the generator for expressions ccgexprs the generator for expressions

View file

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

View file

@ -32,7 +32,7 @@ Path Purpose
``config`` configuration files for Nimrod go into here ``config`` configuration files for Nimrod go into here
``lib`` the Nimrod library lives here; ``rod`` depends ``lib`` the Nimrod library lives here; ``rod`` depends
on it! on it!
``web`` website of Nimrod; generated by ``genweb.py`` ``web`` website of Nimrod; generated by ``koch.py``
from the ``*.txt`` and ``*.tmpl`` files from the ``*.txt`` and ``*.tmpl`` files
``koch`` the Koch Build System (written for Nimrod) ``koch`` the Koch Build System (written for Nimrod)
``obj`` generated ``*.obj`` files go into here ``obj`` generated ``*.obj`` files go into here
@ -49,20 +49,19 @@ and Free Pascal can compile the Nimrod compiler.
Requirements for bootstrapping: Requirements for bootstrapping:
- Free Pascal (I used version 2.2); it may not be needed - Free Pascal (I used version 2.2) [optional]
- Python (should work with 2.4 or higher) and the code generator *cog* - Python (should work with version 1.5 or higher)
(included in this distribution!)
- C compiler -- one of: - C compiler -- one of:
* win32-lcc * win32-lcc (currently broken)
* Borland C++ (tested with 5.5) * Borland C++ (tested with 5.5; currently broken)
* Microsoft C++ * Microsoft C++
* Digital Mars C++ * Digital Mars C++
* Watcom C++ (currently broken; a fix is welcome!) * Watcom C++ (currently broken)
* GCC * GCC
* Intel C++ * Intel C++
* Pelles C * Pelles C (currently broken)
* llvm-gcc * llvm-gcc
| Compiling the compiler is a simple matter of running: | Compiling the compiler is a simple matter of running:
@ -75,7 +74,7 @@ If you want to debug the compiler, use the command::
The ``koch.py`` script is Nimrod's maintainance script: Everything that has 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 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. scripting with the advantage that it is more portable.
Coding standards Coding standards
@ -124,7 +123,7 @@ Complex assignments
We already knew the type information as a graph in the compiler. 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. 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. Look at the file ``lib/hti.nim`` for more information.
The Garbage Collector The Garbage Collector
@ -135,18 +134,11 @@ Introduction
We use the term *cell* here to refer to everything that is traced We use the term *cell* here to refer to everything that is traced
(sequences, refs, strings). (sequences, refs, strings).
This section describes how the new GC works. The old algorithms This section describes how the new GC works.
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. The basic algorithm is *Deferrent reference counting* with cycle detection.
References in the stack are not counted for better performance and easier C 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 code generation.
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 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 descriptor. However the program does not know about these, so they are placed at
@ -156,72 +148,44 @@ is extremely important that ``pointer`` is not confused with a ``PCell``
as this would lead to a memory corruption. 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 CellSet data structure
-------------------------- --------------------------
The AT and ZCT depend on an extremely efficient datastructure for storing a The GC depends on an extremely efficient datastructure for storing a
set of pointers - this is called a ``PCellSet`` in the source code. set of pointers - this is called a ``TCellSet`` in the source code.
Inserting, deleting and searching are done in constant time. However, Inserting, deleting and searching are done in constant time. However,
modifying a ``PCellSet`` during traversation leads to undefined behaviour. modifying a ``TCellSet`` during traversation leads to undefined behaviour.
.. code-block:: Nimrod .. code-block:: Nimrod
type type
PCellSet # hidden TCellSet # hidden
proc allocCellSet: PCellSet # make a new set proc CellSetInit(s: var TCellSet) # initialize a new set
proc deallocCellSet(s: PCellSet) # empty the set and free its memory proc CellSetDeinit(s: var TCellSet) # empty the set and free its memory
proc incl(s: PCellSet, elem: PCell) # include an element proc incl(s: var TCellSet, elem: PCell) # include an element
proc excl(s: PCellSet, elem: PCell) # exclude an element proc excl(s: var TCellSet, elem: PCell) # exclude an element
proc `in`(elem: PCell, s: PCellSet): bool proc `in`(elem: PCell, s: TCellSet): bool # tests membership
iterator elements(s: PCellSet): (elem: PCell) iterator elements(s: TCellSet): (elem: PCell)
All the operations have to be performed efficiently. Because a Cellset can All the operations have to be perform efficiently. Because a Cellset can
become huge (the AT contains every allocated cell!) a hash table is not become huge a hash table alone is not suitable for this.
suitable for this.
We use a mixture of bitset and patricia tree for this. One node in the We use a mixture of bitset and hash table for this. The hash table maps *pages*
patricia tree contains a bitset that decribes a page of the operating system to a page descriptor. The page descriptor contains a bit for any possible cell
(not always, but that doesn't matter). address within this page. So including a cell is done as follows:
So including a cell is done as follows:
- Find the page descriptor for the page the cell belongs to. - Find the page descriptor for the page the cell belongs to.
- Set the appropriate bit in the page descriptor indicating that the - Set the appropriate bit in the page descriptor indicating that the
cell points to the start of a memory block. cell points to the start of a memory block.
Removing a cell is analogous - the bit has to be set to zero. 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 Single page descriptors are never deleted from the hash table. This is not
descriptor is only 19 words big, so it does not waste much by not deleting needed as the data structures need to be periodically rebuilt anyway.
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:: Complete traversal is done in this way::
for each page decriptor d: for each page decriptor d:
for each bit in d: for each bit in d:
@ -265,103 +229,12 @@ roughly like this:
Note that for systems with a continous stack (which most systems have) 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 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 comparisons). Another advantage of this scheme is that the code produced is
a tiny bit smaller. smaller.
The algorithm in pseudo-code The algorithm in pseudo-code
---------------------------- ----------------------------
Now we come to the nitty-gritty. The algorithm works in several phases. To be written.
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 The compiler's architecture

View file

@ -1,131 +1,216 @@
======================= =======================
Nimrod Standard Library Nimrod Standard Library
======================= =======================
:Author: Andreas Rumpf :Author: Andreas Rumpf
:Version: |nimrodversion| :Version: |nimrodversion|
Though the Nimrod Standard Library is still evolving, it is already quite Though the Nimrod Standard Library is still evolving, it is already quite
usable. It is divided into basic libraries that contains modules that virtually usable. It is divided into basic libraries that contains modules that virtually
every program will need and advanced libraries which are more heavy weight. every program will need and advanced libraries which are more heavy weight.
Advanced libraries are in the ``lib/base`` directory. Advanced libraries are in the ``lib/base`` directory.
Basic libraries Basic libraries
=============== ===============
* `system <system.html>`_ * `system <system.html>`_
Basic procs and operators that every program needs. It also provides IO Basic procs and operators that every program needs. It also provides IO
facilities for reading and writing text and binary files. It is imported 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 implicitly by the compiler. Do not import it directly. It relies on compiler
magic to work. magic to work.
* `strutils <strutils.html>`_ * `strutils <strutils.html>`_
This module contains common string handling operations like converting a This module contains common string handling operations like converting a
string into uppercase, splitting a string into substrings, searching for string into uppercase, splitting a string into substrings, searching for
substrings, replacing substrings. substrings, replacing substrings.
* `os <os.html>`_ * `os <os.html>`_
Basic operating system facilities like retrieving environment variables, Basic operating system facilities like retrieving environment variables,
reading command line arguments, working with directories, running shell reading command line arguments, working with directories, running shell
commands, etc. This module is -- like any other basic library -- commands, etc. This module is -- like any other basic library --
platform independant. platform independant.
* `math <math.html>`_ * `math <math.html>`_
Mathematical operations like cosine, square root. Mathematical operations like cosine, square root.
* `complex <complex.html>`_ * `complex <complex.html>`_
This module implements complex numbers and their mathematical operations. This module implements complex numbers and their mathematical operations.
* `times <times.html>`_ * `times <times.html>`_
The ``times`` module contains basic support for working with time. The ``times`` module contains basic support for working with time.
* `parseopt <parseopt.html>`_ * `parseopt <parseopt.html>`_
The ``parseopt`` module implements a command line option parser. This The ``parseopt`` module implements a command line option parser. This
supports long and short command options with optional values and command line supports long and short command options with optional values and command line
arguments. arguments.
* `parsecfg <parsecfg.html>`_ * `parsecfg <parsecfg.html>`_
The ``parsecfg`` module implements a high performance configuration file The ``parsecfg`` module implements a high performance configuration file
parser. The configuration file's syntax is similar to the Windows ``.ini`` parser. The configuration file's syntax is similar to the Windows ``.ini``
format, but much more powerful, as it is not a line based parser. String format, but much more powerful, as it is not a line based parser. String
literals, raw string literals and triple quote string literals are supported literals, raw string literals and triple quote string literals are supported
as in the Nimrod programming language. as in the Nimrod programming language.
* `strtabs <strtabs.html>`_ * `strtabs <strtabs.html>`_
The ``strtabs`` module implements an efficient hash table that is a mapping The ``strtabs`` module implements an efficient hash table that is a mapping
from strings to strings. Supports a case-sensitive, case-insensitive and from strings to strings. Supports a case-sensitive, case-insensitive and
style-insensitive mode. An efficient string substitution operator ``%`` style-insensitive mode. An efficient string substitution operator ``%``
for the string table is also provided. for the string table is also provided.
* `hashes <hashes.html>`_ * `streams <streams.html>`_
This module implements efficient computations of hash values for diverse This module provides a stream interface and two implementations thereof:
Nimrod types. the `PFileStream` and the `PStringStream` which implement the stream
interface for Nimrod file objects (`TFile`) and strings. Other modules
* `lexbase <lexbase.html>`_ may provide other implementations for this standard stream interface.
This is a low leve module that implements an extremely efficent buffering
scheme for lexers and parsers. This is used by the ``parsecfg`` module. * `hashes <hashes.html>`_
This module implements efficient computations of hash values for diverse
Nimrod types.
Advanced libaries
================= * `lexbase <lexbase.html>`_
This is a low level module that implements an extremely efficent buffering
* `regexprs <regexprs.html>`_ scheme for lexers and parsers. This is used by the ``parsecfg`` module.
This module contains procedures and operators for handling regular
expressions.
Advanced libaries
* `dialogs <dialogs.html>`_ =================
This module implements portable dialogs for Nimrod; the implementation
builds on the GTK interface. On Windows, native dialogs are shown if * `regexprs <regexprs.html>`_
appropriate. This module contains procedures and operators for handling regular
expressions.
Wrappers * `dialogs <dialogs.html>`_
======== This module implements portable dialogs for Nimrod; the implementation
builds on the GTK interface. On Windows, native dialogs are shown if
Note that the generated HTML for some of these wrappers is so huge, that it is appropriate.
not contained in the distribution. You can then find them on the website.
* `zipfiles <zipfiles.html>`_
* `posix <posix.html>`_ This module implements a zip archive creator/reader/modifier.
Contains a wrapper for the POSIX standard.
* `windows <windows.html>`_ Wrappers
Contains a wrapper for the Win32 API. ========
* `shellapi <shellapi.html>`_
Contains a wrapper for the ``shellapi.h`` header. Note that the generated HTML for some of these wrappers is so huge, that it is
* `shfolder <shfolder.html>`_ not contained in the distribution. You can then find them on the website.
Contains a wrapper for the ``shfolder.h`` header.
* `mmsystem <mmsystem.html>`_ * `posix <posix.html>`_
Contains a wrapper for the ``mmsystem.h`` header. Contains a wrapper for the POSIX standard.
* `ole2 <ole2.html>`_ * `windows <windows.html>`_
Contains GUIDs for OLE2 automation support. Contains a wrapper for the Win32 API.
* `nb30 <nb30.html>`_ * `shellapi <shellapi.html>`_
This module contains the definitions for portable NetBIOS 3.0 support. Contains a wrapper for the ``shellapi.h`` header.
* `cairo <cairo.html>`_ * `shfolder <shfolder.html>`_
Wrapper for the cairo library. Contains a wrapper for the ``shfolder.h`` header.
* `cairoft <cairoft.html>`_ * `mmsystem <mmsystem.html>`_
Wrapper for the cairoft library. Contains a wrapper for the ``mmsystem.h`` header.
* `cairowin32 <cairowin32.html>`_ * `ole2 <ole2.html>`_
Wrapper for the cairowin32 library. Contains GUIDs for OLE2 automation support.
* `cairoxlib <cairoxlib.html>`_ * `nb30 <nb30.html>`_
Wrapper for the cairoxlib library. This module contains the definitions for portable NetBIOS 3.0 support.
* `atk <atk.html>`_ * `cairo <cairo.html>`_
Wrapper for the atk library. Wrapper for the cairo library.
* `gdk2 <gdk2.html>`_ * `cairoft <cairoft.html>`_
Wrapper for the gdk2 library. Wrapper for the cairoft library.
* `gdk2pixbuf <gdk2pixbuf.html>`_ * `cairowin32 <cairowin32.html>`_
Wrapper for the gdk2pixbuf library. Wrapper for the cairowin32 library.
* `gdkglext <gdkglext.html>`_ * `cairoxlib <cairoxlib.html>`_
Wrapper for the gdkglext library. Wrapper for the cairoxlib library.
* `glib2 <glib2.html>`_ * `atk <atk.html>`_
Wrapper for the glib2 library. Wrapper for the atk library.
* `gtk2 <gtk2.html>`_ * `gdk2 <gdk2.html>`_
Wrapper for the gtk2 library. Wrapper for the gdk2 library.
* `gtkglext <gtkglext.html>`_ * `gdk2pixbuf <gdk2pixbuf.html>`_
Wrapper for the gtkglext library. Wrapper for the gdk2pixbuf library.
* `gtkhtml <gtkhtml.html>`_ * `gdkglext <gdkglext.html>`_
Wrapper for the gtkhtml library. Wrapper for the gdkglext library.
* `libglade2 <libglade2.html>`_ * `glib2 <glib2.html>`_
Wrapper for the libglade2 library. Wrapper for the glib2 library.
* `pango <pango.html>`_ * `gtk2 <gtk2.html>`_
Wrapper for the pango library. Wrapper for the gtk2 library.
* `pangoutils <pangoutils.html>`_ * `gtkglext <gtkglext.html>`_
Wrapper for the pangoutils library. Wrapper for the gtkglext library.
* `gtkhtml <gtkhtml.html>`_
Wrapper for the gtkhtml library.
* `libglade2 <libglade2.html>`_
Wrapper for the libglade2 library.
* `pango <pango.html>`_
Wrapper for the pango library.
* `pangoutils <pangoutils.html>`_
Wrapper for the pangoutils library.
* `gl <gl.html>`_
Part of the wrapper for OpenGL.
* `glext <glext.html>`_
Part of the wrapper for OpenGL.
* `glu <glu.html>`_
Part of the wrapper for OpenGL.
* `glut <glut.html>`_
Part of the wrapper for OpenGL.
* `glx <glx.html>`_
Part of the wrapper for OpenGL.
* `wingl <wingl.html>`_
Part of the wrapper for OpenGL.
* `lua <lua.html>`_
Part of the wrapper for Lua.
* `lualib <lualib.html>`_
Part of the wrapper for Lua.
* `lauxlib <lauxlib.html>`_
Part of the wrapper for Lua.
* `odbcsql <odbcsql.nim>`_
interface to the ODBC driver.
* `zlib <zlib.nim>`_
Wrapper for the zlib library.
* `sdl <sdl.html>`_
Part of the wrapper for SDL.
* `sdl_gfx <sdl_gfx.html>`_
Part of the wrapper for SDL.
* `sdl_image <sdl_image.html>`_
Part of the wrapper for SDL.
* `sdl_mixer <sdl_mixer.html>`_
Part of the wrapper for SDL.
* `sdl_net <sdl_net.html>`_
Part of the wrapper for SDL.
* `sdl_ttf <sdl_ttf.html>`_
Part of the wrapper for SDL.
* `smpeg <smpeg.html>`_
Part of the wrapper for SDL.
* `cursorfont <cursorfont.html>`_
Part of the wrapper for X11.
* `keysym <keysym.html>`_
Part of the wrapper for X11.
* `x <x.html>`_
Part of the wrapper for X11.
* `xatom <xatom.html>`_
Part of the wrapper for X11.
* `xcms <xcms.html>`_
Part of the wrapper for X11.
* `xf86dga <xf86dga.html>`_
Part of the wrapper for X11.
* `xf86vmode <xf86vmode.html>`_
Part of the wrapper for X11.
* `xi <xi.html>`_
Part of the wrapper for X11.
* `xinerama <xinerama.html>`_
Part of the wrapper for X11.
* `xkb <xkb.html>`_
Part of the wrapper for X11.
* `xkblib <xkblib.html>`_
Part of the wrapper for X11.
* `xlib <xlib.html>`_
Part of the wrapper for X11.
* `xrandr <xrandr.html>`_
Part of the wrapper for X11.
* `xrender <xrender.html>`_
Part of the wrapper for X11.
* `xresource <xresource.html>`_
Part of the wrapper for X11.
* `xshm <xshm.html>`_
Part of the wrapper for X11.
* `xutil <xutil.html>`_
Part of the wrapper for X11.
* `xv <xv.html>`_
Part of the wrapper for X11.
* `xvlib <xvlib.html>`_
Part of the wrapper for X11.
* `libzip <libzip.html>`_
Interface to the `lib zip <http://www.nih.at/libzip/index.html>`_ library by
Dieter Baron and Thomas Klausner.

View file

@ -160,8 +160,8 @@ case-sensitive and even underscores are ignored:
this is that this allows programmers to use their own prefered spelling style this is that this allows programmers to use their own prefered spelling style
and libraries written by different programmers cannot use incompatible and libraries written by different programmers cannot use incompatible
conventions. The editors or IDE can show the identifiers as preferred. Another conventions. The editors or IDE can show the identifiers as preferred. Another
advantage is that it frees the programmer from remembering the spelling of an advantage is that it frees the programmer from remembering the exact spelling
identifier. of an identifier.
Literal strings Literal strings
@ -601,20 +601,20 @@ Array and sequence types
has the same type. Arrays always have a fixed length which is specified at has the same type. Arrays always have a fixed length which is specified at
compile time (except for open arrays). They can be indexed by any ordinal type. compile time (except for open arrays). They can be indexed by any ordinal type.
A parameter ``A`` may be an *open array*, in which case it is indexed by A parameter ``A`` may be an *open array*, in which case it is indexed by
integers from 0 to ``len(A)-1``. integers from 0 to ``len(A)-1``. An array expression may be constructed by the
array constructor ``[]``.
`Sequences`:idx: are similar to arrays but of dynamic length which may change `Sequences`:idx: are similar to arrays but of dynamic length which may change
during runtime (like strings). A sequence ``S`` is always indexed by integers during runtime (like strings). A sequence ``S`` is always indexed by integers
from 0 to ``len(S)-1`` and its bounds are checked. Sequences can also be from 0 to ``len(S)-1`` and its bounds are checked. Sequences can be
constructed by the array constructor ``[]``. constructed by the array constructor ``[]`` in conjunction with the array to
sequence operator ``@``. Another way to allocate space for a sequence is to
call the built-in ``newSeq`` procedure.
A sequence may be passed to a parameter that is of type *open array*, but A sequence may be passed to a parameter that is of type *open array*, but
not to a multi-dimensional open array, because it is impossible to do so in an not to a multi-dimensional open array, because it is impossible to do so in an
efficient manner. efficient manner.
An array expression may be constructed by the array constructor ``[]``.
A constructed array is assignment compatible to a sequence.
Example: Example:
.. code-block:: nimrod .. code-block:: nimrod
@ -625,13 +625,13 @@ Example:
var var
x: TIntArray x: TIntArray
y: TIntSeq y: TIntSeq
x = [1, 2, 3, 4, 5, 6] # [] this is the array constructor that is compatible x = [1, 2, 3, 4, 5, 6] # [] this is the array constructor
# with arrays, open arrays and y = @[1, 2, 3, 4, 5, 6] # the @ turns the array into a sequence
y = [1, 2, 3, 4, 5, 6] # sequences
The lower bound of an array may be received by the built-in proc The lower bound of an array or sequence may be received by the built-in proc
``low()``, the higher bound by ``high()``. The length may be ``low()``, the higher bound by ``high()``. The length may be
received by ``len()``. received by ``len()``. ``low()`` for a sequence or an open array always returns
0, as this is the first valid index.
Arrays are always bounds checked (at compile-time or at runtime). These Arrays are always bounds checked (at compile-time or at runtime). These
checks can be disabled via pragmas or invoking the compiler with the checks can be disabled via pragmas or invoking the compiler with the
@ -644,15 +644,15 @@ A variable of a `tuple`:idx: or `object`:idx: type is a heterogenous storage
container. container.
A tuple or object defines various named *fields* of a type. A tuple defines an A tuple or object defines various named *fields* of a type. A tuple defines an
*order* of the fields additionally. Tuples are meant for heterogenous storage *order* of the fields additionally. Tuples are meant for heterogenous storage
types with no overhead and few abstraction possibilities. The constructor ``()`` types with no overhead and few abstraction possibilities. The constructor ``()``
can be used to construct tuples. The order of the fields in the constructor can be used to construct tuples. The order of the fields in the constructor
must match the order of the tuple's definition. Different tuple-types are must match the order of the tuple's definition. Different tuple-types are
*equivalent* if they specify the same fields of the same type in the same *equivalent* if they specify the same fields of the same type in the same
order. order.
The assignment operator for tuples copies each component. The assignment operator for tuples copies each component.
The default assignment operator for objects is not defined. The programmer may The default assignment operator for objects is not defined. The programmer may
provide one, however. provide one, however.
.. code-block:: nimrod .. code-block:: nimrod
@ -662,7 +662,7 @@ provide one, however.
# and an age # and an age
var var
person: TPerson person: TPerson
person = (name: "Peter", age: 30) person = (name: "Peter", age: 30)
# the same, but less readable: # the same, but less readable:
person = ("Peter", 30) person = ("Peter", 30)
@ -670,8 +670,8 @@ The implementation aligns the fields for best access performance. The alignment
is done in a way that is compatible the way the C compiler does it. is done in a way that is compatible the way the C compiler does it.
Objects provide many features that tuples do not. Object provide inheritance Objects provide many features that tuples do not. Object provide inheritance
and information hiding. Objects have access to their type at runtime, so that and information hiding. Objects have access to their type at runtime, so that
the ``is`` operator can be used to determine the object's type. the ``is`` operator can be used to determine the object's type.
.. code-block:: nimrod .. code-block:: nimrod
@ -689,9 +689,51 @@ the ``is`` operator can be used to determine the object's type.
assert(student is TStudent) # is true assert(student is TStudent) # is true
Object fields that should be visible outside from the defining module, have to Object fields that should be visible outside from the defining module, have to
marked by ``*``. In contrast to tuples, different object types are marked by ``*``. In contrast to tuples, different object types are
never *equivalent*. never *equivalent*.
Object variants
~~~~~~~~~~~~~~~
Often an object hierarchy is overkill in certain situations where simple
`variant`:idx: types are needed.
An example:
.. code-block:: nimrod
# This is an example how an abstract syntax tree could be modelled in Nimrod
type
TNodeKind = enum # the different node types
nkInt, # a leaf with an integer value
nkFloat, # a leaf with a float value
nkString, # a leaf with a string value
nkAdd, # an addition
nkSub, # a subtraction
nkIf # an if statement
PNode = ref TNode
TNode = object
case kind: TNodeKind # the ``kind`` field is the discriminator
of nkInt: intVal: int
of nkFloat: floavVal: float
of nkString: strVal: string
of nkAdd, nkSub:
leftOp, rightOp: PNode
of nkIf:
condition, thenPart, elsePart: PNode
var
n: PNode
new(n) # creates a new node
n.kind = nkFloat
n.floatVal = 0.0 # valid, because ``n.kind==nkFloat``, so that it fits
# the following statement raises an `EInvalidField` exception, because
# n.kind's value does not fit:
n.strVal = ""
As can been seen from the example, an advantage to an object hierarchy is that
no casting between different object types is needed. Yet, access to invalid
object fields raises an exception.
Set type Set type
~~~~~~~~ ~~~~~~~~
@ -749,7 +791,7 @@ The ``^`` operator can be used to derefer a reference, the ``addr`` procedure
returns the address of an item. An address is always an untraced reference. returns the address of an item. An address is always an untraced reference.
Thus the usage of ``addr`` is an *unsafe* feature. Thus the usage of ``addr`` is an *unsafe* feature.
The ``.`` (access a tuple/object field operator) The ``.`` (access a tuple/object field operator)
and ``[]`` (array/string/sequence index operator) operators perform implicit and ``[]`` (array/string/sequence index operator) operators perform implicit
dereferencing operations for reference types: dereferencing operations for reference types:
@ -773,7 +815,7 @@ further information.
Special care has to be taken if an untraced object contains traced objects like Special care has to be taken if an untraced object contains traced objects like
traced references, strings or sequences: In order to free everything properly, traced references, strings or sequences: In order to free everything properly,
the built-in procedure ``finalize`` has to be called before freeing the the built-in procedure ``GCunref`` has to be called before freeing the
untraced memory manually! untraced memory manually!
.. XXX finalizers for traced objects .. XXX finalizers for traced objects
@ -867,7 +909,7 @@ statement.
Statements are separated into `simple statements`:idx: and Statements are separated into `simple statements`:idx: and
`complex statements`:idx:. `complex statements`:idx:.
Simple statements are statements that cannot contain other statements, like Simple statements are statements that cannot contain other statements like
assignments, calls or the ``return`` statement; complex statements can assignments, calls or the ``return`` statement; complex statements can
contain other statements. To avoid the `dangling else problem`:idx:, complex contain other statements. To avoid the `dangling else problem`:idx:, complex
statements always have to be intended:: statements always have to be intended::
@ -1028,10 +1070,10 @@ Example:
The `case`:idx: statement is similar to the if statement, but it represents The `case`:idx: statement is similar to the if statement, but it represents
a multi-branch selection. The expression after the keyword ``case`` is a multi-branch selection. The expression after the keyword ``case`` is
evaluated and if its value is in a *vallist* the corresponding statements evaluated and if its value is in a *vallist* the corresponding statements
(after the ``of`` keyword) are executed. If the value is no given *vallist* (after the ``of`` keyword) are executed. If the value is not in any
the ``else`` part is executed. If there is no ``else`` part and not all given *slicelist* the ``else`` part is executed. If there is no ``else``
possible values that ``expr`` can hold occur in a ``vallist``, a static part and not all possible values that ``expr`` can hold occur in a ``vallist``,
error is given. This holds only for expressions of ordinal types. a static error is given. This holds only for expressions of ordinal types.
If the expression is not of an ordinal type, and no ``else`` part is If the expression is not of an ordinal type, and no ``else`` part is
given, control just passes after the ``case`` statement. given, control just passes after the ``case`` statement.
@ -1331,10 +1373,8 @@ is used if the caller does not provide a value for this parameter. Example:
`Operators`:idx: are procedures with a special operator symbol as identifier: `Operators`:idx: are procedures with a special operator symbol as identifier:
.. code-block:: nimrod .. code-block:: nimrod
proc `$` (x: int): string = # converts an integer to a string; proc `$` (x: int): string =
# since it has one parameter this is a prefix # converts an integer to a string; this is a prefix operator.
# operator. With two parameters it would be
# an infix operator.
return intToStr(x) return intToStr(x)
Calling a procedure can be done in many different ways: Calling a procedure can be done in many different ways:
@ -1544,7 +1584,7 @@ own file. Modules enable `information hiding`:idx: and
`separate compilation`:idx:. A module may gain access to symbols of another `separate compilation`:idx:. A module may gain access to symbols of another
module by the `import`:idx: statement. `Recursive module dependancies`:idx: are module by the `import`:idx: statement. `Recursive module dependancies`:idx: are
allowed, but slightly subtle. Only top-level symbols that are marked with an allowed, but slightly subtle. Only top-level symbols that are marked with an
asterisk (``*``) are exported. asterisk (``*``) are exported.
The algorithm for compiling modules is: The algorithm for compiling modules is:
@ -1557,8 +1597,8 @@ This is best illustrated by an example:
.. code-block:: nimrod .. code-block:: nimrod
# Module A # Module A
type type
T1* = int T1* = int # Module A exports the type ``T1``
import B # the compiler starts parsing B import B # the compiler starts parsing B
proc main() = proc main() =
var i = p(3) # works because B has been parsed completely here var i = p(3) # works because B has been parsed completely here
@ -1660,12 +1700,19 @@ Nimrod source code. The conditional symbols go into a special symbol table.
The compiler defines the target processor and the target operating The compiler defines the target processor and the target operating
system as conditional symbols. system as conditional symbols.
Warning: The ``define`` pragma is deprecated as it conflicts with separate
compilation! One should use boolean constants as a replacement - this is
cleaner anyway.
undef pragma undef pragma
------------ ------------
The `undef`:idx: pragma the counterpart to the define pragma. It undefines a The `undef`:idx: pragma the counterpart to the define pragma. It undefines a
conditional symbol. conditional symbol.
Warning: The ``undef`` pragma is deprecated as it conflicts with separate
compilation!
error pragma error pragma
------------ ------------

View file

@ -34,8 +34,15 @@ Advanced command line switches are:
Configuration file Configuration file
------------------ ------------------
The ``nimrod`` executable loads the configuration file ``config/nimrod.cfg`` The default configuration file is ``nimrod.cfg``. The ``nimrod`` executable
unless this is suppressed by the ``--skip_cfg`` command line option. looks for it in the following directories (in this order):
1. ``/home/$user/.config/nimrod.cfg`` (UNIX) or ``$APPDATA/nimrod.cfg`` (Windows)
2. ``$nimrod/config/nimrod.cfg`` (UNIX, Windows)
3. ``/etc/nimrod.cfg`` (UNIX)
The search stops as soon as a configuration file has been found. The reading
of ``nimrod.cfg`` can be suppressed by the ``--skip_cfg`` command line option.
Configuration settings can be overwritten in a project specific Configuration settings can be overwritten in a project specific
configuration file that is read automatically. This specific file has to 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 be in the same directory as the project and be of the same name, except
@ -47,11 +54,10 @@ Command line settings have priority over configuration file settings.
Nimrod's directory structure Nimrod's directory structure
---------------------------- ----------------------------
The generated files that Nimrod produces all go into a subdirectory called 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 ``nimcache`` in your project directory. This makes it easy to delete all
files. For example the generated C code for the module ``path/modA.nim`` generated files.
will become ``path/rod_gen/modA.c``.
However, the generated C code is not platform independant! C code generated for 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 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. C file lists the OS, CPU and CC the file has been compiled for.
@ -77,10 +83,46 @@ 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 Thus lots of options and pragmas for tweaking the generated C code are
available. available.
Importc Pragma
~~~~~~~~~~~~~~
The `importc`:idx: pragma provides a means to import a type, a variable, or a
procedure from C. The optional argument is a string containing the C
identifier. If the argument is missing, the C name is the Nimrod
identifier *exactly as spelled*:
.. code-block::
proc printf(formatstr: cstring) {.importc: "printf", varargs.}
Exportc Pragma
~~~~~~~~~~~~~~
The `exportc`:idx: pragma provides a means to export a type, a variable, or a
procedure to C. The optional argument is a string containing the C
identifier. If the argument is missing, the C name is the Nimrod
identifier *exactly as spelled*:
.. code-block:: Nimrod
proc callme(formatstr: cstring) {.exportc: "callMe", varargs.}
Dynlib Pragma
~~~~~~~~~~~~~
With the `dynlib`:idx: pragma a procedure or a variable can be imported from
a dynamic library (``.dll`` files for Windows, ``lib*.so`` files for UNIX). The
non-optional argument has to be the name of the dynamic library:
.. code-block:: Nimrod
proc gtk_image_new(): PGtkWidget {.cdecl, dynlib: "libgtk-x11-2.0.so", importc.}
In general, importing a dynamic library does not require any special linker
options or linking with import libraries. This also
implies that no *devel* packages need to be installed.
No_decl Pragma No_decl Pragma
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
The `no_decl`:idx: pragma can be applied to almost any symbol (variable, proc, 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: type, etc.) and is sometimes useful for interoperability with C:
It tells Nimrod that it should not generate a declaration for the symbol in 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: the C code. Thus it makes the following possible, for example:
@ -89,17 +131,7 @@ the C code. Thus it makes the following possible, for example:
EOF {.importc: "EOF", no_decl.}: cint # pretend EOF was a variable, as EOF {.importc: "EOF", no_decl.}: cint # pretend EOF was a variable, as
# Nimrod does not know its value # Nimrod does not know its value
Varargs Pragma However, the ``header`` pragma is often the better alternative.
~~~~~~~~~~~~~~
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 Header Pragma
@ -119,12 +151,25 @@ in angle brackets: ``<>``. If no angle brackets are given, Nimrod
encloses the header file in ``""`` in the generated C code. encloses the header file in ``""`` in the generated C code.
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
No_static Pragma No_static Pragma
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
The `no_static`:idx: pragma can be applied to almost any symbol and specifies 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 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 symbols in the interface part of a module never get declared ``static``, so
only in special cases is this pragma necessary. only in very special cases this pragma is necessary.
Line_dir Option Line_dir Option
@ -171,8 +216,29 @@ The `register`:idx: pragma is for variables only. It declares the variable as
in a hardware register for faster access. C compilers usually ignore this 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. 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 In highly specific cases (a dispatch loop of an bytecode interpreter for
may provide benefits, though. example) it may provide benefits, though.
Acyclic Pragma
~~~~~~~~~~~~~~
The `acyclic`:idx: pragma can be used for object types to mark them as acyclic
even though they seem to be cyclic. This is an **optimization** for the garbage
collector to not consider objects of this type as part of a cycle::
type
PNode = ref TNode
TNode {.acyclic, final.} = object
left, right: PNode
data: string
In the example a tree structure is declared with the ``TNode`` type. Note that
the type definition is recursive thus the GC has to assume that objects of
this type may form a cyclic graph. The ``acyclic`` pragma passes the
information that this cannot happen to the GC. If the programmer uses the
``acyclic`` pragma for data types that are in reality cyclic, the GC may leak
memory, but nothing worse happens.
Disabling certain messages Disabling certain messages
@ -244,12 +310,17 @@ efficient than any hand-coded scheme.
The ECMAScript code generator The ECMAScript code generator
============================= =============================
Note: As of version 0.7.0 the ECMAScript code generator is not maintained any
longer. Help if you are interested.
Note: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:, since Note: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:, since
it is the proper term. it is the proper term.
The ECMAScript code generator is experimental!
Nimrod targets ECMAScript 1.5 which is supported by any widely used browser. Nimrod targets ECMAScript 1.5 which is supported by any widely used browser.
Since ECMAScript does not have a portable means to include another module, Since ECMAScript does not have a portable means to include another module,
Nimrod just generate a long ``.js`` file. Nimrod just generates a long ``.js`` file.
Features or modules that the ECMAScript platform does not support are not Features or modules that the ECMAScript platform does not support are not
available. This includes: available. This includes:

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,7 @@
# The beginning of an IDE for Nimrod
# (c) 2008 Andreas Rumpf
import glib2, gtk2, libglade2, dialogs import glib2, gtk2, libglade2, dialogs, parseopt
proc on_window_destroy(obj: PGtkObject, data: pointer) {.cdecl.} = proc on_window_destroy(obj: PGtkObject, data: pointer) {.cdecl.} =
gtk_main_quit() gtk_main_quit()

View file

@ -9,18 +9,19 @@ Note:
A C compiler is required - knowledge of C is not! A C compiler is required - knowledge of C is not!
The GNU C Compiler is fully supported, other compilers may work. The C compiler 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 should be in your ``$PATH`` (most likely the case). Note that some few Linux
distributions do not ship with a GCC compiler preinstalled - then you have to distributions do not ship with a GCC compiler preinstalled - then you have to
install it. install it.
After you have made sure that a C compiler is available, install Nimrod Install Nimrod by downloading the appropriate ``.zip`` file and extracting it
by downloading the appropriate ``.zip`` file and extracting it to a to a directory of your choice. The Nimrod Compiler will stay in this
directory of your choice. The Nimrod Compiler will stay in this directory (unless you copy it somewhere else). The compiler does not need
directory; do not use a temporary one! Good choices are ``/opt/nimrod`` or - write access to its directory anymore, so copying the nimrod folder to ``/opt``
if you don't have root access - ``~/programs/nimrod``. does work.
Then run the following command:: Then run the following command::
python koch.py install sh build.sh
Unlike other software, Nimrod does not distribute its files over the whole file 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 hierarchy. This has the advantage that you can deinstall it by just deleting
@ -39,48 +40,26 @@ need to install Apple's developer's tools for the GNU Compiler Collection
though. though.
Installation on Windows - the easy way Installation on Windows
-------------------------------------- -----------------------
Install Nimrod by downloading and running Install Nimrod by downloading and running
the ``nimrod_windows_$version.exe`` file. The installation procedure detects the ``nimrod_$version.exe`` file. As default, the ``LLVM-GCC``
which C compilers are installed and writes the ``config/nimrod.cfg`` file compiler is used that is bundled with this installer. You can change
for you. If no installed C compiler is found, the ``LLVM-GCC`` compiler is the configuration file to use another C compiler.
used that is bundled with this installer. So it should just work.
Currently, the following C compilers are supported under Windows:
Installation on Windows - the hard way
--------------------------------------
Windows does not ship with a C compiler; you have to install one. The
following C compilers are supported under Windows:
- | Microsoft's Visual C++ - | Microsoft's Visual C++
| http://msdn.microsoft.com/visualc | http://msdn.microsoft.com/visualc
| (You may need the SDK too - but not the full one: Essential are only | (You need the SDK too - but not the full one: Essential are only
the win32api header files and import libraries.) the win32api header files and import libraries.)
- | 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.)
- | Gnu C Compiler (the mingw version; the cygwin version has not been tested!) - | Gnu C Compiler (the mingw version; the cygwin version has not been tested!)
| http://www.mingw.org/download.shtml | http://www.mingw.org/download.shtml
- | LLVM with GNU C/C++ frontend - | LLVM with GNU C/C++ frontend
| http://llvm.org/releases/download.html#2.2 | http://llvm.org/releases/download.html#2.2
- | Digital Mars C++ - | Digital Mars C++
| http://www.digitalmars.com/download/freecompiler.html | http://www.digitalmars.com/download/freecompiler.html
- | Pelles C Compiler (bootstrapping does not work with PCC!)
| http://www.smorgasbordet.com/pellesc
- | Lcc-win32 (bootstrapping does not work with LCC!)
| http://www.cs.virginia.edu/~lcc-win32
All of the above compilers are available for free! For faster compile times I recommend Digital Mars C++ -- it is easy to install
(The first three are the easiest to install.) If you want a small download, and a small package.
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 adapt the ``config/nimrod.cfg``
file appropriately. You should add Nimrod to your ``$PATH``.

1599
koch.py

File diff suppressed because it is too large Load diff

View file

@ -1,662 +0,0 @@
# 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.4"
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.
# -----------------------------------------------------------------------------
def FileCmp(filenameA, filenameB):
SIZE = 4096*2
result = True
a = file(filenameA, "rb")
b = file(filenameB, "rb")
while True:
x = a.read(SIZE)
y = b.read(SIZE)
if x != y:
result = False
break
elif len(x) < SIZE: # EOF?
break
a.close()
b.close()
return result
# ---------------- 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])
def SafeSubs(frmt, **substitution):
return string.Template(frmt).safe_substitute(substitution)
_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.")

View file

@ -47,7 +47,7 @@ else:
# only Mac OS X has this shit # only Mac OS X has this shit
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.nodecl, importc: "longjmp".} proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.nodecl, importc: "longjmp".}
proc c_setjmp(jmpb: var C_JmpBuf) {.nodecl, importc: "setjmp".} proc c_setjmp(jmpb: var C_JmpBuf): cint {.nodecl, importc: "setjmp".}
proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {. proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
importc: "signal", header: "<signal.h>".} importc: "signal", header: "<signal.h>".}

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf # (c) Copyright 2008 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -10,11 +10,11 @@
# simple integer arithmetic with overflow checking # simple integer arithmetic with overflow checking
proc raiseOverflow {.exportc: "raiseOverflow".} = proc raiseOverflow {.compilerproc, noinline.} =
# a single proc to reduce code size to a minimum # a single proc to reduce code size to a minimum
raise newException(EOverflow, "over- or underflow") raise newException(EOverflow, "over- or underflow")
proc raiseDivByZero {.exportc: "raiseDivByZero".} = proc raiseDivByZero {.exportc: "raiseDivByZero", noinline.} =
raise newException(EDivByZero, "divison by zero") raise newException(EDivByZero, "divison by zero")
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} = proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
@ -75,9 +75,9 @@ proc mulInt64(a, b: int64): int64 {.compilerproc.} =
var var
resAsFloat, floatProd: float64 resAsFloat, floatProd: float64
result = a *% b result = a *% b
floatProd = float64(a) # conversion floatProd = toBiggestFloat(a) # conversion
floatProd = floatProd * float64(b) floatProd = floatProd * toBiggestFloat(b)
resAsFloat = float64(result) resAsFloat = toBiggestFloat(result)
# Fast path for normal case: small multiplicands, and no info # Fast path for normal case: small multiplicands, and no info
# is lost in either method. # is lost in either method.
@ -101,16 +101,14 @@ proc absInt(a: int): int {.compilerProc, inline.} =
else: return -a else: return -a
raiseOverflow() raiseOverflow()
when defined(I386) and (defined(vcc) or defined(wcc) or defined(dmc)): const
# or defined(gcc)): asmVersion = defined(I386) and (defined(vcc) or defined(wcc) or defined(dmc))
{.define: asmVersion.} # my Version of Borland C++Builder does not have
# my Version of Borland C++Builder does not have # tasm32, which is needed for assembler blocks
# tasm32, which is needed for assembler blocks # this is why Borland is not included in the 'when'
# this is why Borland is not included in the 'when' useInline = not asmVersion
else:
{.define: useInline.}
when defined(asmVersion) and defined(gcc): when asmVersion and defined(gcc):
proc addInt(a, b: int): int {.compilerProc, pure, inline.} proc addInt(a, b: int): int {.compilerProc, pure, inline.}
proc subInt(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 mulInt(a, b: int): int {.compilerProc, pure, inline.}
@ -118,7 +116,7 @@ when defined(asmVersion) and defined(gcc):
proc modInt(a, b: int): int {.compilerProc, pure, inline.} proc modInt(a, b: int): int {.compilerProc, pure, inline.}
proc negInt(a: int): int {.compilerProc, pure, inline.} proc negInt(a: int): int {.compilerProc, pure, inline.}
elif defined(asmVersion): elif asmVersion:
proc addInt(a, b: int): int {.compilerProc, pure.} proc addInt(a, b: int): int {.compilerProc, pure.}
proc subInt(a, b: int): int {.compilerProc, pure.} proc subInt(a, b: int): int {.compilerProc, pure.}
proc mulInt(a, b: int): int {.compilerProc, pure.} proc mulInt(a, b: int): int {.compilerProc, pure.}
@ -126,7 +124,7 @@ elif defined(asmVersion):
proc modInt(a, b: int): int {.compilerProc, pure.} proc modInt(a, b: int): int {.compilerProc, pure.}
proc negInt(a: int): int {.compilerProc, pure.} proc negInt(a: int): int {.compilerProc, pure.}
elif defined(useInline): elif useInline:
proc addInt(a, b: int): int {.compilerProc, inline.} proc addInt(a, b: int): int {.compilerProc, inline.}
proc subInt(a, b: int): int {.compilerProc, inline.} proc subInt(a, b: int): int {.compilerProc, inline.}
proc mulInt(a, b: int): int {.compilerProc.} proc mulInt(a, b: int): int {.compilerProc.}
@ -145,7 +143,7 @@ else:
# implementation: # implementation:
when defined(asmVersion) and not defined(gcc): when asmVersion and not defined(gcc):
# assembler optimized versions for compilers that # assembler optimized versions for compilers that
# have an intel syntax assembler: # have an intel syntax assembler:
proc addInt(a, b: int): int = proc addInt(a, b: int): int =
@ -210,7 +208,7 @@ when defined(asmVersion) and not defined(gcc):
theEnd: theEnd:
""" """
elif defined(asmVersion) and defined(gcc): elif asmVersion and defined(gcc):
proc addInt(a, b: int): int = proc addInt(a, b: int): int =
asm """ "addl %1,%%eax\n" asm """ "addl %1,%%eax\n"
"jno 1\n" "jno 1\n"

View file

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

View file

@ -58,7 +58,7 @@ else:
type type
PByte = cstring PByte = cstring
cairo_status_t* = enum TCairoStatus* = enum
CAIRO_STATUS_SUCCESS = 0, CAIRO_STATUS_NO_MEMORY, CAIRO_STATUS_SUCCESS = 0, CAIRO_STATUS_NO_MEMORY,
CAIRO_STATUS_INVALID_RESTORE, CAIRO_STATUS_INVALID_POP_GROUP, CAIRO_STATUS_INVALID_RESTORE, CAIRO_STATUS_INVALID_POP_GROUP,
CAIRO_STATUS_NO_CURRENT_POINT, CAIRO_STATUS_INVALID_MATRIX, CAIRO_STATUS_NO_CURRENT_POINT, CAIRO_STATUS_INVALID_MATRIX,
@ -69,93 +69,93 @@ type
CAIRO_STATUS_PATTERN_TYPE_MISMATCH, CAIRO_STATUS_INVALID_CONTENT, CAIRO_STATUS_PATTERN_TYPE_MISMATCH, CAIRO_STATUS_INVALID_CONTENT,
CAIRO_STATUS_INVALID_FORMAT, CAIRO_STATUS_INVALID_VISUAL, CAIRO_STATUS_INVALID_FORMAT, CAIRO_STATUS_INVALID_VISUAL,
CAIRO_STATUS_FILE_NOT_FOUND, CAIRO_STATUS_INVALID_DASH CAIRO_STATUS_FILE_NOT_FOUND, CAIRO_STATUS_INVALID_DASH
cairo_operator_t* = enum TCairoOperator* = enum
CAIRO_OPERATOR_CLEAR, CAIRO_OPERATOR_SOURCE, CAIRO_OPERATOR_OVER, CAIRO_OPERATOR_CLEAR, CAIRO_OPERATOR_SOURCE, CAIRO_OPERATOR_OVER,
CAIRO_OPERATOR_IN, CAIRO_OPERATOR_OUT, CAIRO_OPERATOR_ATOP, CAIRO_OPERATOR_IN, CAIRO_OPERATOR_OUT, CAIRO_OPERATOR_ATOP,
CAIRO_OPERATOR_DEST, CAIRO_OPERATOR_DEST_OVER, CAIRO_OPERATOR_DEST_IN, CAIRO_OPERATOR_DEST, CAIRO_OPERATOR_DEST_OVER, CAIRO_OPERATOR_DEST_IN,
CAIRO_OPERATOR_DEST_OUT, CAIRO_OPERATOR_DEST_ATOP, CAIRO_OPERATOR_XOR, CAIRO_OPERATOR_DEST_OUT, CAIRO_OPERATOR_DEST_ATOP, CAIRO_OPERATOR_XOR,
CAIRO_OPERATOR_ADD, CAIRO_OPERATOR_SATURATE CAIRO_OPERATOR_ADD, CAIRO_OPERATOR_SATURATE
cairo_antialias_t* = enum TCairoAntialias* = enum
CAIRO_ANTIALIAS_DEFAULT, CAIRO_ANTIALIAS_NONE, CAIRO_ANTIALIAS_GRAY, CAIRO_ANTIALIAS_DEFAULT, CAIRO_ANTIALIAS_NONE, CAIRO_ANTIALIAS_GRAY,
CAIRO_ANTIALIAS_SUBPIXEL CAIRO_ANTIALIAS_SUBPIXEL
cairo_fill_rule_t* = enum TCairoFillRule* = enum
CAIRO_FILL_RULE_WINDING, CAIRO_FILL_RULE_EVEN_ODD CAIRO_FILL_RULE_WINDING, CAIRO_FILL_RULE_EVEN_ODD
cairo_line_cap_t* = enum TCairoLineCap* = enum
CAIRO_LINE_CAP_BUTT, CAIRO_LINE_CAP_ROUND, CAIRO_LINE_CAP_SQUARE CAIRO_LINE_CAP_BUTT, CAIRO_LINE_CAP_ROUND, CAIRO_LINE_CAP_SQUARE
cairo_line_join_t* = enum TCairoLineJoin* = enum
CAIRO_LINE_JOIN_MITER, CAIRO_LINE_JOIN_ROUND, CAIRO_LINE_JOIN_BEVEL CAIRO_LINE_JOIN_MITER, CAIRO_LINE_JOIN_ROUND, CAIRO_LINE_JOIN_BEVEL
cairo_font_slant_t* = enum TCairoFontSlant* = enum
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_SLANT_ITALIC, CAIRO_FONT_SLANT_OBLIQUE CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_SLANT_ITALIC, CAIRO_FONT_SLANT_OBLIQUE
cairo_font_weight_t* = enum TCairoFontWeight* = enum
CAIRO_FONT_WEIGHT_NORMAL, CAIRO_FONT_WEIGHT_BOLD CAIRO_FONT_WEIGHT_NORMAL, CAIRO_FONT_WEIGHT_BOLD
cairo_subpixel_order_t* = enum TCairoSubpixelOrder* = enum
CAIRO_SUBPIXEL_ORDER_DEFAULT, CAIRO_SUBPIXEL_ORDER_RGB, CAIRO_SUBPIXEL_ORDER_DEFAULT, CAIRO_SUBPIXEL_ORDER_RGB,
CAIRO_SUBPIXEL_ORDER_BGR, CAIRO_SUBPIXEL_ORDER_VRGB, CAIRO_SUBPIXEL_ORDER_BGR, CAIRO_SUBPIXEL_ORDER_VRGB,
CAIRO_SUBPIXEL_ORDER_VBGR CAIRO_SUBPIXEL_ORDER_VBGR
cairo_hint_style_t* = enum TCairoHintStyle* = enum
CAIRO_HINT_STYLE_DEFAULT, CAIRO_HINT_STYLE_NONE, CAIRO_HINT_STYLE_SLIGHT, CAIRO_HINT_STYLE_DEFAULT, CAIRO_HINT_STYLE_NONE, CAIRO_HINT_STYLE_SLIGHT,
CAIRO_HINT_STYLE_MEDIUM, CAIRO_HINT_STYLE_FULL CAIRO_HINT_STYLE_MEDIUM, CAIRO_HINT_STYLE_FULL
cairo_hint_metrics_t* = enum TCairoHintMetrics* = enum
CAIRO_HINT_METRICS_DEFAULT, CAIRO_HINT_METRICS_OFF, CAIRO_HINT_METRICS_ON CAIRO_HINT_METRICS_DEFAULT, CAIRO_HINT_METRICS_OFF, CAIRO_HINT_METRICS_ON
cairo_path_data_type_t* = enum TCairoPathDataType* = enum
CAIRO_PATH_MOVE_TO, CAIRO_PATH_LINE_TO, CAIRO_PATH_CURVE_TO, CAIRO_PATH_MOVE_TO, CAIRO_PATH_LINE_TO, CAIRO_PATH_CURVE_TO,
CAIRO_PATH_CLOSE_PATH CAIRO_PATH_CLOSE_PATH
cairo_content_t* = enum TCairoContent* = enum
CAIRO_CONTENT_COLOR = 0x00001000, CAIRO_CONTENT_ALPHA = 0x00002000, CAIRO_CONTENT_COLOR = 0x00001000, CAIRO_CONTENT_ALPHA = 0x00002000,
CAIRO_CONTENT_COLOR_ALPHA = 0x00003000 CAIRO_CONTENT_COLOR_ALPHA = 0x00003000
cairo_format_t* = enum TCairoFormat* = enum
CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_RGB24, CAIRO_FORMAT_A8, CAIRO_FORMAT_A1 CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_RGB24, CAIRO_FORMAT_A8, CAIRO_FORMAT_A1
cairo_extend_t* = enum TCairoExtend* = enum
CAIRO_EXTEND_NONE, CAIRO_EXTEND_REPEAT, CAIRO_EXTEND_REFLECT, CAIRO_EXTEND_NONE, CAIRO_EXTEND_REPEAT, CAIRO_EXTEND_REFLECT,
CAIRO_EXTEND_PAD CAIRO_EXTEND_PAD
cairo_filter_t* = enum TCairoFilter* = enum
CAIRO_FILTER_FAST, CAIRO_FILTER_GOOD, CAIRO_FILTER_BEST, CAIRO_FILTER_FAST, CAIRO_FILTER_GOOD, CAIRO_FILTER_BEST,
CAIRO_FILTER_NEAREST, CAIRO_FILTER_BILINEAR, CAIRO_FILTER_GAUSSIAN CAIRO_FILTER_NEAREST, CAIRO_FILTER_BILINEAR, CAIRO_FILTER_GAUSSIAN
cairo_font_type_t* = enum TCairoFontType* = enum
CAIRO_FONT_TYPE_TOY, CAIRO_FONT_TYPE_FT, CAIRO_FONT_TYPE_WIN32, CAIRO_FONT_TYPE_TOY, CAIRO_FONT_TYPE_FT, CAIRO_FONT_TYPE_WIN32,
CAIRO_FONT_TYPE_ATSUI CAIRO_FONT_TYPE_ATSUI
cairo_pattern_type_t* = enum TCairoPatternType* = enum
CAIRO_PATTERN_TYPE_SOLID, CAIRO_PATTERN_TYPE_SURFACE, CAIRO_PATTERN_TYPE_SOLID, CAIRO_PATTERN_TYPE_SURFACE,
CAIRO_PATTERN_TYPE_LINEAR, CAIRO_PATTERN_TYPE_RADIAL CAIRO_PATTERN_TYPE_LINEAR, CAIRO_PATTERN_TYPE_RADIAL
cairo_surface_type_t* = enum TCairoSurfaceType* = enum
CAIRO_SURFACE_TYPE_IMAGE, CAIRO_SURFACE_TYPE_PDF, CAIRO_SURFACE_TYPE_PS, 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_XLIB, CAIRO_SURFACE_TYPE_XCB, CAIRO_SURFACE_TYPE_GLITZ,
CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_SURFACE_TYPE_WIN32, CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_SURFACE_TYPE_WIN32,
CAIRO_SURFACE_TYPE_BEOS, CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_SURFACE_TYPE_BEOS, CAIRO_SURFACE_TYPE_DIRECTFB,
CAIRO_SURFACE_TYPE_SVG, CAIRO_SURFACE_TYPE_OS2 CAIRO_SURFACE_TYPE_SVG, CAIRO_SURFACE_TYPE_OS2
cairo_svg_version_t* = enum TCairoSvgVersion* = enum
CAIRO_SVG_VERSION_1_1, CAIRO_SVG_VERSION_1_2 CAIRO_SVG_VERSION_1_1, CAIRO_SVG_VERSION_1_2
Pcairo_surface_t* = ref cairo_surface_t PCairoSurface* = ptr TCairoSurface
PPcairo_surface_t* = ref Pcairo_surface_t PPCairoSurface* = ptr PCairoSurface
Pcairo_t* = ref cairo_t PCairo* = ptr TCairo
Pcairo_pattern_t* = ref cairo_pattern_t PCairoPattern* = ptr TCairoPattern
Pcairo_font_options_t* = ref cairo_font_options_t PCairoFontOptions* = ptr TCairoFontOptions
Pcairo_font_face_t* = ref cairo_font_face_t PCairoFontFace* = ptr TCairoFontFace
Pcairo_scaled_font_t* = ref cairo_scaled_font_t PCairoScaledFont* = ptr TCairoScaledFont
Pcairo_bool_t* = ref cairo_bool_t PCairoBool* = ptr TCairoBool
cairo_bool_t* = int32 TCairoBool* = int32
Pcairo_matrix_t* = ref cairo_matrix_t PCairoMatrix* = ptr TCairoMatrix
Pcairo_user_data_key_t* = ref cairo_user_data_key_t PCairoUserDataKey* = ptr TCairoUserDataKey
Pcairo_glyph_t* = ref cairo_glyph_t PCairoGlyph* = ptr TCairoGlyph
Pcairo_text_extents_t* = ref cairo_text_extents_t PCairoTextExtents* = ptr TCairoTextExtents
Pcairo_font_extents_t* = ref cairo_font_extents_t PCairoFontExtents* = ptr TCairoFontExtents
Pcairo_path_data_type_t* = ref cairo_path_data_type_t PCairoPathDataType* = ptr TCairoPathDataType
Pcairo_path_data_t* = ref cairo_path_data_t PCairoPathData* = ptr TCairoPathData
Pcairo_path_t* = ref cairo_path_t PCairoPath* = ptr TCairoPath
Pcairo_rectangle_t* = ref cairo_rectangle_t PCairoRectangle* = ptr TCairoRectangle
Pcairo_rectangle_list_t* = ref cairo_rectangle_list_t PCairoRectangleList* = ptr TCairoRectangleList
cairo_destroy_func_t* = proc (data: Pointer){.cdecl.} TCairoDestroyFunc* = proc (data: Pointer){.cdecl.}
cairo_write_func_t* = proc (closure: Pointer, data: PByte, len: int32): cairo_status_t{. TCairoWriteFunc* = proc (closure: Pointer, data: PByte, len: int32): TCairoStatus{.
cdecl.} cdecl.}
cairo_read_func_t* = proc (closure: Pointer, data: PByte, len: int32): cairo_status_t{. TCairoReadFunc* = proc (closure: Pointer, data: PByte, len: int32): TCairoStatus{.
cdecl.} cdecl.}
cairo_t* {.final.} = object #OPAQUE TCairo* {.final.} = object #OPAQUE
cairo_surface_t* {.final.} = object #OPAQUE TCairoSurface* {.final.} = object #OPAQUE
cairo_pattern_t* {.final.} = object #OPAQUE TCairoPattern* {.final.} = object #OPAQUE
cairo_scaled_font_t* {.final.} = object #OPAQUE TCairoScaledFont* {.final.} = object #OPAQUE
cairo_font_face_t* {.final.} = object #OPAQUE TCairoFontFace* {.final.} = object #OPAQUE
cairo_font_options_t* {.final.} = object #OPAQUE TCairoFontOptions* {.final.} = object #OPAQUE
cairo_matrix_t* {.final.} = object TCairoMatrix* {.final.} = object
xx: float64 xx: float64
yx: float64 yx: float64
xy: float64 xy: float64
@ -163,15 +163,15 @@ type
x0: float64 x0: float64
y0: float64 y0: float64
cairo_user_data_key_t* {.final.} = object TCairoUserDataKey* {.final.} = object
unused: int32 unused: int32
cairo_glyph_t* {.final.} = object TCairoGlyph* {.final.} = object
index: int32 index: int32
x: float64 x: float64
y: float64 y: float64
cairo_text_extents_t* {.final.} = object TCairoTextExtents* {.final.} = object
x_bearing: float64 x_bearing: float64
y_bearing: float64 y_bearing: float64
width: float64 width: float64
@ -179,30 +179,30 @@ type
x_advance: float64 x_advance: float64
y_advance: float64 y_advance: float64
cairo_font_extents_t* {.final.} = object TCairoFontExtents* {.final.} = object
ascent: float64 ascent: float64
descent: float64 descent: float64
height: float64 height: float64
max_x_advance: float64 max_x_advance: float64
max_y_advance: float64 max_y_advance: float64
cairo_path_data_t* {.final.} = object #* _type : cairo_path_data_type_t; TCairoPathData* {.final.} = object #* _type : TCairoPathDataType;
# length : LongInt; # length : LongInt;
# end # end
x: float64 x: float64
y: float64 y: float64
cairo_path_t* {.final.} = object TCairoPath* {.final.} = object
status: cairo_status_t status: TCairoStatus
data: Pcairo_path_data_t data: PCairoPathData
num_data: int32 num_data: int32
cairo_rectangle_t* {.final.} = object TCairoRectangle* {.final.} = object
x, y, width, height: float64 x, y, width, height: float64
cairo_rectangle_list_t* {.final.} = object TCairoRectangleList* {.final.} = object
status: cairo_status_t status: TCairoStatus
rectangles: Pcairo_rectangle_t rectangles: PCairoRectangle
num_rectangles: int32 num_rectangles: int32
@ -211,480 +211,480 @@ proc cairo_version_string*(): cstring{.cdecl, importc, dynlib: LIB_CAIRO.}
#Helper function to retrieve decoded version #Helper function to retrieve decoded version
proc cairo_version*(major, minor, micro: var int32) proc cairo_version*(major, minor, micro: var int32)
#* Functions for manipulating state objects #* Functions for manipulating state objects
proc cairo_create*(target: Pcairo_surface_t): Pcairo_t{.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_create*(target: PCairoSurface): PCairo{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_reference*(cr: Pcairo_t): Pcairo_t{.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_reference*(cr: PCairo): PCairo{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_destroy*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_destroy*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_reference_count*(cr: Pcairo_t): int32{.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_get_reference_count*(cr: PCairo): int32{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_user_data*(cr: Pcairo_t, key: Pcairo_user_data_key_t): pointer{. proc cairo_get_user_data*(cr: PCairo, key: PCairoUserDataKey): pointer{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_user_data*(cr: PCairo_t, key: Pcairo_user_data_key_t, proc cairo_set_user_data*(cr: PCairo, key: PCairoUserDataKey,
user_data: Pointer, destroy: cairo_destroy_func_t): cairo_status_t{. user_data: Pointer, destroy: TCairoDestroyFunc): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_save*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_save*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_restore*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_restore*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_push_group*(cr: PCairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_push_group*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_push_group_with_content*(cr: PCairo_t, content: cairo_content_t){. proc cairo_push_group_with_content*(cr: PCairo, content: TCairoContent){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pop_group*(cr: PCairo_t): Pcairo_pattern_t{.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_pop_group*(cr: PCairo): PCairoPattern{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pop_group_to_source*(cr: PCairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_pop_group_to_source*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
#* Modify state #* Modify state
proc cairo_set_operator*(cr: Pcairo_t, op: cairo_operator_t){.cdecl, importc, proc cairo_set_operator*(cr: PCairo, op: TCairoOperator){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_source*(cr: Pcairo_t, source: Pcairo_pattern_t){.cdecl, importc, proc cairo_set_source*(cr: PCairo, source: PCairoPattern){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_source_rgb*(cr: Pcairo_t, red, green, blue: float64){.cdecl, importc, proc cairo_set_source_rgb*(cr: PCairo, red, green, blue: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_source_rgba*(cr: Pcairo_t, red, green, blue, alpha: float64){. proc cairo_set_source_rgba*(cr: PCairo, red, green, blue, alpha: float64){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_source_surface*(cr: Pcairo_t, surface: Pcairo_surface_t, proc cairo_set_source_surface*(cr: PCairo, surface: PCairoSurface,
x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.} x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_tolerance*(cr: Pcairo_t, tolerance: float64){.cdecl, importc, proc cairo_set_tolerance*(cr: PCairo, tolerance: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_antialias*(cr: Pcairo_t, antialias: cairo_antialias_t){.cdecl, importc, proc cairo_set_antialias*(cr: PCairo, antialias: TCairoAntialias){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_fill_rule*(cr: Pcairo_t, fill_rule: cairo_fill_rule_t){.cdecl, importc, proc cairo_set_fill_rule*(cr: PCairo, fill_rule: TCairoFillRule){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_line_width*(cr: Pcairo_t, width: float64){.cdecl, importc, proc cairo_set_line_width*(cr: PCairo, width: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_line_cap*(cr: Pcairo_t, line_cap: cairo_line_cap_t){.cdecl, importc, proc cairo_set_line_cap*(cr: PCairo, line_cap: TCairoLineCap){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_line_join*(cr: Pcairo_t, line_join: cairo_line_join_t){.cdecl, importc, proc cairo_set_line_join*(cr: PCairo, line_join: TCairoLineJoin){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_dash*(cr: Pcairo_t, dashes: openarray[float64], proc cairo_set_dash*(cr: PCairo, dashes: openarray[float64],
offset: float64){.cdecl, importc, dynlib: LIB_CAIRO.} offset: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_miter_limit*(cr: Pcairo_t, limit: float64){.cdecl, importc, proc cairo_set_miter_limit*(cr: PCairo, limit: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_translate*(cr: Pcairo_t, tx, ty: float64){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_translate*(cr: PCairo, tx, ty: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scale*(cr: Pcairo_t, sx, sy: float64){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_scale*(cr: PCairo, sx, sy: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rotate*(cr: Pcairo_t, angle: float64){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_rotate*(cr: PCairo, angle: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_transform*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc, proc cairo_transform*(cr: PCairo, matrix: PCairoMatrix){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc, proc cairo_set_matrix*(cr: PCairo, matrix: PCairoMatrix){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_identity_matrix*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_identity_matrix*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_user_to_device*(cr: Pcairo_t, x, y: var float64){.cdecl, importc, proc cairo_user_to_device*(cr: PCairo, x, y: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_user_to_device_distance*(cr: Pcairo_t, dx, dy: var float64){.cdecl, importc, proc cairo_user_to_device_distance*(cr: PCairo, dx, dy: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_device_to_user*(cr: Pcairo_t, x, y: var float64){.cdecl, importc, proc cairo_device_to_user*(cr: PCairo, x, y: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_device_to_user_distance*(cr: Pcairo_t, dx, dy: var float64){.cdecl, importc, proc cairo_device_to_user_distance*(cr: PCairo, dx, dy: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
#* Path creation functions #* Path creation functions
proc cairo_new_path*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_new_path*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_move_to*(cr: Pcairo_t, x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_move_to*(cr: PCairo, x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_new_sub_path*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_new_sub_path*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_line_to*(cr: Pcairo_t, x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_line_to*(cr: PCairo, x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_curve_to*(cr: Pcairo_t, x1, y1, x2, y2, x3, y3: float64){.cdecl, importc, proc cairo_curve_to*(cr: PCairo, x1, y1, x2, y2, x3, y3: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_arc*(cr: Pcairo_t, xc, yc, radius, angle1, angle2: float64){.cdecl, importc, proc cairo_arc*(cr: PCairo, xc, yc, radius, angle1, angle2: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_arc_negative*(cr: Pcairo_t, xc, yc, radius, angle1, angle2: float64){. proc cairo_arc_negative*(cr: PCairo, xc, yc, radius, angle1, angle2: float64){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rel_move_to*(cr: Pcairo_t, dx, dy: float64){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_rel_move_to*(cr: PCairo, 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_line_to*(cr: PCairo, dx, dy: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rel_curve_to*(cr: Pcairo_t, dx1, dy1, dx2, dy2, dx3, dy3: float64){. proc cairo_rel_curve_to*(cr: PCairo, dx1, dy1, dx2, dy2, dx3, dy3: float64){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rectangle*(cr: Pcairo_t, x, y, width, height: float64){.cdecl, importc, proc cairo_rectangle*(cr: PCairo, x, y, width, height: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_close_path*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_close_path*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
#* Painting functions #* Painting functions
proc cairo_paint*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_paint*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_paint_with_alpha*(cr: Pcairo_t, alpha: float64){.cdecl, importc, proc cairo_paint_with_alpha*(cr: PCairo, alpha: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_mask*(cr: Pcairo_t, pattern: Pcairo_pattern_t){.cdecl, importc, proc cairo_mask*(cr: PCairo, pattern: PCairoPattern){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_mask_surface*(cr: Pcairo_t, surface: Pcairo_surface_t, proc cairo_mask_surface*(cr: PCairo, surface: PCairoSurface,
surface_x, surface_y: float64){.cdecl, importc, surface_x, surface_y: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_stroke*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_stroke*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_stroke_preserve*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_stroke_preserve*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_fill*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_fill*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_fill_preserve*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_fill_preserve*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_copy_page*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_copy_page*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_show_page*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_show_page*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
#* Insideness testing #* Insideness testing
proc cairo_in_stroke*(cr: Pcairo_t, x, y: float64): cairo_bool_t{.cdecl, importc, proc cairo_in_stroke*(cr: PCairo, x, y: float64): TCairoBool{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_in_fill*(cr: Pcairo_t, x, y: float64): cairo_bool_t{.cdecl, importc, proc cairo_in_fill*(cr: PCairo, x, y: float64): TCairoBool{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
#* Rectangular extents #* Rectangular extents
proc cairo_stroke_extents*(cr: Pcairo_t, x1, y1, x2, y2: var float64){.cdecl, importc, proc cairo_stroke_extents*(cr: PCairo, x1, y1, x2, y2: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_fill_extents*(cr: Pcairo_t, x1, y1, x2, y2: var float64){.cdecl, importc, proc cairo_fill_extents*(cr: PCairo, x1, y1, x2, y2: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
#* Clipping #* Clipping
proc cairo_reset_clip*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_reset_clip*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_clip*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_clip*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_clip_preserve*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_clip_preserve*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_clip_extents*(cr: Pcairo_t, x1, y1, x2, y2: var float64){.cdecl, importc, proc cairo_clip_extents*(cr: PCairo, x1, y1, x2, y2: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_copy_clip_rectangle_list*(cr: Pcairo_t): Pcairo_rectangle_list_t{. proc cairo_copy_clip_rectangle_list*(cr: PCairo): PCairoRectangleList{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rectangle_list_destroy*(rectangle_list: Pcairo_rectangle_list_t){. proc cairo_rectangle_list_destroy*(rectangle_list: PCairoRectangleList){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
#* Font/Text functions #* Font/Text functions
proc cairo_font_options_create*(): Pcairo_font_options_t{.cdecl, importc, proc cairo_font_options_create*(): PCairoFontOptions{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_font_options_copy*(original: Pcairo_font_options_t): Pcairo_font_options_t{. proc cairo_font_options_copy*(original: PCairoFontOptions): PCairoFontOptions{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_destroy*(options: Pcairo_font_options_t){.cdecl, importc, proc cairo_font_options_destroy*(options: PCairoFontOptions){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_font_options_status*(options: Pcairo_font_options_t): cairo_status_t{. proc cairo_font_options_status*(options: PCairoFontOptions): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_merge*(options, other: Pcairo_font_options_t){.cdecl, importc, proc cairo_font_options_merge*(options, other: PCairoFontOptions){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_font_options_equal*(options, other: Pcairo_font_options_t): cairo_bool_t{. proc cairo_font_options_equal*(options, other: PCairoFontOptions): TCairoBool{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_hash*(options: Pcairo_font_options_t): int32{.cdecl, importc, proc cairo_font_options_hash*(options: PCairoFontOptions): int32{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_font_options_set_antialias*(options: Pcairo_font_options_t, proc cairo_font_options_set_antialias*(options: PCairoFontOptions,
antialias: cairo_antialias_t){.cdecl, importc, antialias: TCairoAntialias){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_font_options_get_antialias*(options: Pcairo_font_options_t): cairo_antialias_t{. proc cairo_font_options_get_antialias*(options: PCairoFontOptions): TCairoAntialias{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_set_subpixel_order*(options: Pcairo_font_options_t, proc cairo_font_options_set_subpixel_order*(options: PCairoFontOptions,
subpixel_order: cairo_subpixel_order_t){.cdecl, importc, dynlib: LIB_CAIRO.} subpixel_order: TCairoSubpixelOrder){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_get_subpixel_order*(options: Pcairo_font_options_t): cairo_subpixel_order_t{. proc cairo_font_options_get_subpixel_order*(options: PCairoFontOptions): TCairoSubpixelOrder{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_set_hint_style*(options: Pcairo_font_options_t, proc cairo_font_options_set_hint_style*(options: PCairoFontOptions,
hint_style: cairo_hint_style_t){.cdecl, importc, hint_style: TCairoHintStyle){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_font_options_get_hint_style*(options: Pcairo_font_options_t): cairo_hint_style_t{. proc cairo_font_options_get_hint_style*(options: PCairoFontOptions): TCairoHintStyle{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_set_hint_metrics*(options: Pcairo_font_options_t, proc cairo_font_options_set_hint_metrics*(options: PCairoFontOptions,
hint_metrics: cairo_hint_metrics_t){.cdecl, importc, dynlib: LIB_CAIRO.} hint_metrics: TCairoHintMetrics){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_get_hint_metrics*(options: Pcairo_font_options_t): cairo_hint_metrics_t{. proc cairo_font_options_get_hint_metrics*(options: PCairoFontOptions): TCairoHintMetrics{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
#* This interface is for dealing with text as text, not caring about the #* This interface is for dealing with text as text, not caring about the
# font object inside the the cairo_t. # font object inside the the TCairo.
proc cairo_select_font_face*(cr: Pcairo_t, family: cstring, proc cairo_select_font_face*(cr: PCairo, family: cstring,
slant: cairo_font_slant_t, slant: TCairoFontSlant,
weight: cairo_font_weight_t){.cdecl, importc, weight: TCairoFontWeight){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_font_size*(cr: Pcairo_t, size: float64){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_set_font_size*(cr: PCairo, size: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_font_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc, proc cairo_set_font_matrix*(cr: PCairo, matrix: PCairoMatrix){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_get_font_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc, proc cairo_get_font_matrix*(cr: PCairo, matrix: PCairoMatrix){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_font_options*(cr: Pcairo_t, options: Pcairo_font_options_t){. proc cairo_set_font_options*(cr: PCairo, options: PCairoFontOptions){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_font_options*(cr: Pcairo_t, options: Pcairo_font_options_t){. proc cairo_get_font_options*(cr: PCairo, options: PCairoFontOptions){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_font_face*(cr: Pcairo_t, font_face: Pcairo_font_face_t){.cdecl, importc, proc cairo_set_font_face*(cr: PCairo, font_face: PCairoFontFace){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_get_font_face*(cr: Pcairo_t): Pcairo_font_face_t{.cdecl, importc, proc cairo_get_font_face*(cr: PCairo): PCairoFontFace{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_set_scaled_font*(cr: PCairo_t, scaled_font: Pcairo_scaled_font_t){. proc cairo_set_scaled_font*(cr: PCairo, scaled_font: PCairoScaledFont){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_scaled_font*(cr: Pcairo_t): Pcairo_scaled_font_t{.cdecl, importc, proc cairo_get_scaled_font*(cr: PCairo): PCairoScaledFont{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_show_text*(cr: Pcairo_t, utf8: cstring){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_show_text*(cr: PCairo, utf8: cstring){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_show_glyphs*(cr: Pcairo_t, glyphs: Pcairo_glyph_t, num_glyphs: int32){. proc cairo_show_glyphs*(cr: PCairo, glyphs: PCairoGlyph, num_glyphs: int32){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_text_path*(cr: Pcairo_t, utf8: cstring){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_text_path*(cr: PCairo, utf8: cstring){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_glyph_path*(cr: Pcairo_t, glyphs: Pcairo_glyph_t, num_glyphs: int32){. proc cairo_glyph_path*(cr: PCairo, glyphs: PCairoGlyph, num_glyphs: int32){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_text_extents*(cr: Pcairo_t, utf8: cstring, proc cairo_text_extents*(cr: PCairo, utf8: cstring,
extents: Pcairo_text_extents_t){.cdecl, importc, extents: PCairoTextExtents){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_glyph_extents*(cr: Pcairo_t, glyphs: Pcairo_glyph_t, proc cairo_glyph_extents*(cr: PCairo, glyphs: PCairoGlyph,
num_glyphs: int32, extents: Pcairo_text_extents_t){. num_glyphs: int32, extents: PCairoTextExtents){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_extents*(cr: Pcairo_t, extents: Pcairo_font_extents_t){.cdecl, importc, proc cairo_font_extents*(cr: PCairo, extents: PCairoFontExtents){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
#* Generic identifier for a font style #* Generic identifier for a font style
proc cairo_font_face_reference*(font_face: Pcairo_font_face_t): Pcairo_font_face_t{. proc cairo_font_face_reference*(font_face: PCairoFontFace): PCairoFontFace{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_face_destroy*(font_face: Pcairo_font_face_t){.cdecl, importc, proc cairo_font_face_destroy*(font_face: PCairoFontFace){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_font_face_get_reference_count*(font_face: Pcairo_font_face_t): int32{. proc cairo_font_face_get_reference_count*(font_face: PCairoFontFace): int32{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_face_status*(font_face: Pcairo_font_face_t): cairo_status_t{. proc cairo_font_face_status*(font_face: PCairoFontFace): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_face_get_type*(font_face: Pcairo_font_face_t): cairo_font_type_t{. proc cairo_font_face_get_type*(font_face: PCairoFontFace): TCairoFontType{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_face_get_user_data*(font_face: Pcairo_font_face_t, proc cairo_font_face_get_user_data*(font_face: PCairoFontFace,
key: Pcairo_user_data_key_t): pointer{. key: PCairoUserDataKey): pointer{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_face_set_user_data*(font_face: Pcairo_font_face_t, proc cairo_font_face_set_user_data*(font_face: PCairoFontFace,
key: Pcairo_user_data_key_t, key: PCairoUserDataKey,
user_data: pointer, user_data: pointer,
destroy: cairo_destroy_func_t): cairo_status_t{. destroy: TCairoDestroyFunc): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
#* Portable interface to general font features #* Portable interface to general font features
proc cairo_scaled_font_create*(font_face: Pcairo_font_face_t, proc cairo_scaled_font_create*(font_face: PCairoFontFace,
font_matrix: Pcairo_matrix_t, font_matrix: PCairoMatrix,
ctm: Pcairo_matrix_t, ctm: PCairoMatrix,
options: Pcairo_font_options_t): Pcairo_scaled_font_t{. options: PCairoFontOptions): PCairoScaledFont{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_reference*(scaled_font: Pcairo_scaled_font_t): Pcairo_scaled_font_t{. proc cairo_scaled_font_reference*(scaled_font: PCairoScaledFont): PCairoScaledFont{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_destroy*(scaled_font: Pcairo_scaled_font_t){.cdecl, importc, proc cairo_scaled_font_destroy*(scaled_font: PCairoScaledFont){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_reference_count*(scaled_font: Pcairo_scaled_font_t): int32{. proc cairo_scaled_font_get_reference_count*(scaled_font: PCairoScaledFont): int32{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_status*(scaled_font: Pcairo_scaled_font_t): cairo_status_t{. proc cairo_scaled_font_status*(scaled_font: PCairoScaledFont): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_type*(scaled_font: Pcairo_scaled_font_t): cairo_font_type_t{. proc cairo_scaled_font_get_type*(scaled_font: PCairoScaledFont): TCairoFontType{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_user_data*(scaled_font: Pcairo_scaled_font_t, proc cairo_scaled_font_get_user_data*(scaled_font: PCairoScaledFont,
key: Pcairo_user_data_key_t): Pointer{. key: PCairoUserDataKey): Pointer{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_set_user_data*(scaled_font: Pcairo_scaled_font_t, proc cairo_scaled_font_set_user_data*(scaled_font: PCairoScaledFont,
key: Pcairo_user_data_key_t, key: PCairoUserDataKey,
user_data: Pointer, user_data: Pointer,
destroy: cairo_destroy_func_t): cairo_status_t{. destroy: TCairoDestroyFunc): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_extents*(scaled_font: Pcairo_scaled_font_t, proc cairo_scaled_font_extents*(scaled_font: PCairoScaledFont,
extents: Pcairo_font_extents_t){.cdecl, importc, extents: PCairoFontExtents){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_scaled_font_text_extents*(scaled_font: Pcairo_scaled_font_t, proc cairo_scaled_font_text_extents*(scaled_font: PCairoScaledFont,
utf8: cstring, utf8: cstring,
extents: Pcairo_text_extents_t){.cdecl, importc, extents: PCairoTextExtents){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_scaled_font_glyph_extents*(scaled_font: Pcairo_scaled_font_t, proc cairo_scaled_font_glyph_extents*(scaled_font: PCairoScaledFont,
glyphs: Pcairo_glyph_t, num_glyphs: int32, glyphs: PCairoGlyph, num_glyphs: int32,
extents: Pcairo_text_extents_t){.cdecl, importc, extents: PCairoTextExtents){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_font_face*(scaled_font: Pcairo_scaled_font_t): Pcairo_font_face_t{. proc cairo_scaled_font_get_font_face*(scaled_font: PCairoScaledFont): PCairoFontFace{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_font_matrix*(scaled_font: Pcairo_scaled_font_t, proc cairo_scaled_font_get_font_matrix*(scaled_font: PCairoScaledFont,
font_matrix: Pcairo_matrix_t){.cdecl, importc, font_matrix: PCairoMatrix){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_ctm*(scaled_font: Pcairo_scaled_font_t, proc cairo_scaled_font_get_ctm*(scaled_font: PCairoScaledFont,
ctm: Pcairo_matrix_t){.cdecl, importc, dynlib: LIB_CAIRO.} ctm: PCairoMatrix){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_font_options*(scaled_font: Pcairo_scaled_font_t, proc cairo_scaled_font_get_font_options*(scaled_font: PCairoScaledFont,
options: Pcairo_font_options_t){.cdecl, importc, dynlib: LIB_CAIRO.} options: PCairoFontOptions){.cdecl, importc, dynlib: LIB_CAIRO.}
#* Query functions #* Query functions
proc cairo_get_operator*(cr: Pcairo_t): cairo_operator_t{.cdecl, importc, proc cairo_get_operator*(cr: PCairo): TCairoOperator{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_get_source*(cr: Pcairo_t): Pcairo_pattern_t{.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_get_source*(cr: PCairo): PCairoPattern{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_tolerance*(cr: Pcairo_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_get_tolerance*(cr: PCairo): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_antialias*(cr: Pcairo_t): cairo_antialias_t{.cdecl, importc, proc cairo_get_antialias*(cr: PCairo): TCairoAntialias{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_get_current_point*(cr: Pcairo_t, x, y: var float64){.cdecl, importc, proc cairo_get_current_point*(cr: PCairo, x, y: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_get_fill_rule*(cr: Pcairo_t): cairo_fill_rule_t{.cdecl, importc, proc cairo_get_fill_rule*(cr: PCairo): TCairoFillRule{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_get_line_width*(cr: Pcairo_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_get_line_width*(cr: PCairo): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_line_cap*(cr: Pcairo_t): cairo_line_cap_t{.cdecl, importc, proc cairo_get_line_cap*(cr: PCairo): TCairoLineCap{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_get_line_join*(cr: Pcairo_t): cairo_line_join_t{.cdecl, importc, proc cairo_get_line_join*(cr: PCairo): TCairoLineJoin{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_get_miter_limit*(cr: Pcairo_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_get_miter_limit*(cr: PCairo): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_dash_count*(cr: Pcairo_t): int32{.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_get_dash_count*(cr: PCairo): int32{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_dash*(cr: Pcairo_t, dashes, offset: var float64){.cdecl, importc, proc cairo_get_dash*(cr: PCairo, dashes, offset: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_get_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc, proc cairo_get_matrix*(cr: PCairo, matrix: PCairoMatrix){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_get_target*(cr: Pcairo_t): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_get_target*(cr: PCairo): PCairoSurface{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_group_target*(cr: Pcairo_t): Pcairo_surface_t{.cdecl, importc, proc cairo_get_group_target*(cr: PCairo): PCairoSurface{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_copy_path*(cr: Pcairo_t): Pcairo_path_t{.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_copy_path*(cr: PCairo): PCairoPath{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_copy_path_flat*(cr: Pcairo_t): Pcairo_path_t{.cdecl, importc, proc cairo_copy_path_flat*(cr: PCairo): PCairoPath{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_append_path*(cr: Pcairo_t, path: Pcairo_path_t){.cdecl, importc, proc cairo_append_path*(cr: PCairo, path: PCairoPath){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_path_destroy*(path: Pcairo_path_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_path_destroy*(path: PCairoPath){.cdecl, importc, dynlib: LIB_CAIRO.}
#* Error status queries #* Error status queries
proc cairo_status*(cr: Pcairo_t): cairo_status_t{.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_status*(cr: PCairo): TCairoStatus{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_status_to_string*(status: cairo_status_t): cstring{.cdecl, importc, proc cairo_status_to_string*(status: TCairoStatus): cstring{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
#* Surface manipulation #* Surface manipulation
proc cairo_surface_create_similar*(other: Pcairo_surface_t, proc cairo_surface_create_similar*(other: PCairoSurface,
content: cairo_content_t, content: TCairoContent,
width, height: int32): Pcairo_surface_t{. width, height: int32): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_reference*(surface: Pcairo_surface_t): Pcairo_surface_t{. proc cairo_surface_reference*(surface: PCairoSurface): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_finish*(surface: Pcairo_surface_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_surface_finish*(surface: PCairoSurface){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_destroy*(surface: Pcairo_surface_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_surface_destroy*(surface: PCairoSurface){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_get_reference_count*(surface: Pcairo_surface_t): int32{. proc cairo_surface_get_reference_count*(surface: PCairoSurface): int32{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_status*(surface: Pcairo_surface_t): cairo_status_t{.cdecl, importc, proc cairo_surface_status*(surface: PCairoSurface): TCairoStatus{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_surface_get_type*(surface: Pcairo_surface_t): cairo_surface_type_t{. proc cairo_surface_get_type*(surface: PCairoSurface): TCairoSurfaceType{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_get_content*(surface: Pcairo_surface_t): cairo_content_t{. proc cairo_surface_get_content*(surface: PCairoSurface): TCairoContent{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_write_to_png*(surface: Pcairo_surface_t, filename: cstring): cairo_status_t{. proc cairo_surface_write_to_png*(surface: PCairoSurface, filename: cstring): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_write_to_png_stream*(surface: Pcairo_surface_t, proc cairo_surface_write_to_png_stream*(surface: PCairoSurface,
write_func: cairo_write_func_t, write_func: TCairoWriteFunc,
closure: pointer): cairo_status_t{. closure: pointer): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_get_user_data*(surface: Pcairo_surface_t, proc cairo_surface_get_user_data*(surface: PCairoSurface,
key: Pcairo_user_data_key_t): pointer{.cdecl, importc, key: PCairoUserDataKey): pointer{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_surface_set_user_data*(surface: Pcairo_surface_t, proc cairo_surface_set_user_data*(surface: PCairoSurface,
key: Pcairo_user_data_key_t, key: PCairoUserDataKey,
user_data: pointer, user_data: pointer,
destroy: cairo_destroy_func_t): cairo_status_t{. destroy: TCairoDestroyFunc): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_get_font_options*(surface: Pcairo_surface_t, proc cairo_surface_get_font_options*(surface: PCairoSurface,
options: Pcairo_font_options_t){.cdecl, importc, options: PCairoFontOptions){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_surface_flush*(surface: Pcairo_surface_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_surface_flush*(surface: PCairoSurface){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_mark_dirty*(surface: Pcairo_surface_t){.cdecl, importc, proc cairo_surface_mark_dirty*(surface: PCairoSurface){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_surface_mark_dirty_rectangle*(surface: Pcairo_surface_t, proc cairo_surface_mark_dirty_rectangle*(surface: PCairoSurface,
x, y, width, height: int32){.cdecl, importc, dynlib: LIB_CAIRO.} x, y, width, height: int32){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_set_device_offset*(surface: Pcairo_surface_t, proc cairo_surface_set_device_offset*(surface: PCairoSurface,
x_offset, y_offset: float64){.cdecl, importc, x_offset, y_offset: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_surface_get_device_offset*(surface: Pcairo_surface_t, proc cairo_surface_get_device_offset*(surface: PCairoSurface,
x_offset, y_offset: var float64){.cdecl, importc, x_offset, y_offset: var float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_surface_set_fallback_resolution*(surface: Pcairo_surface_t, proc cairo_surface_set_fallback_resolution*(surface: PCairoSurface,
x_pixels_per_inch, y_pixels_per_inch: float64){.cdecl, importc, dynlib: LIB_CAIRO.} x_pixels_per_inch, y_pixels_per_inch: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
#* Image-surface functions #* Image-surface functions
proc cairo_image_surface_create*(format: cairo_format_t, width, height: int32): Pcairo_surface_t{. proc cairo_image_surface_create*(format: TCairoFormat, width, height: int32): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_image_surface_create_for_data*(data: Pbyte, format: cairo_format_t, proc cairo_image_surface_create_for_data*(data: Pbyte, format: TCairoFormat,
width, height, stride: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.} width, height, stride: int32): PCairoSurface{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_image_surface_get_data*(surface: Pcairo_surface_t): cstring{.cdecl, importc, proc cairo_image_surface_get_data*(surface: PCairoSurface): cstring{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_image_surface_get_format*(surface: Pcairo_surface_t): cairo_format_t{. proc cairo_image_surface_get_format*(surface: PCairoSurface): TCairoFormat{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_image_surface_get_width*(surface: Pcairo_surface_t): int32{.cdecl, importc, proc cairo_image_surface_get_width*(surface: PCairoSurface): int32{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_image_surface_get_height*(surface: Pcairo_surface_t): int32{.cdecl, importc, proc cairo_image_surface_get_height*(surface: PCairoSurface): int32{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_image_surface_get_stride*(surface: Pcairo_surface_t): int32{.cdecl, importc, proc cairo_image_surface_get_stride*(surface: PCairoSurface): int32{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_image_surface_create_from_png*(filename: cstring): Pcairo_surface_t{. proc cairo_image_surface_create_from_png*(filename: cstring): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_image_surface_create_from_png_stream*(read_func: cairo_read_func_t, proc cairo_image_surface_create_from_png_stream*(read_func: TCairoReadFunc,
closure: pointer): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.} closure: pointer): PCairoSurface{.cdecl, importc, dynlib: LIB_CAIRO.}
#* Pattern creation functions #* Pattern creation functions
proc cairo_pattern_create_rgb*(red, green, blue: float64): Pcairo_pattern_t{. proc cairo_pattern_create_rgb*(red, green, blue: float64): PCairoPattern{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_create_rgba*(red, green, blue, alpha: float64): Pcairo_pattern_t{. proc cairo_pattern_create_rgba*(red, green, blue, alpha: float64): PCairoPattern{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_create_for_surface*(surface: Pcairo_surface_t): Pcairo_pattern_t{. proc cairo_pattern_create_for_surface*(surface: PCairoSurface): PCairoPattern{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_create_linear*(x0, y0, x1, y1: float64): Pcairo_pattern_t{. proc cairo_pattern_create_linear*(x0, y0, x1, y1: float64): PCairoPattern{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_create_radial*(cx0, cy0, radius0, cx1, cy1, radius1: float64): Pcairo_pattern_t{. proc cairo_pattern_create_radial*(cx0, cy0, radius0, cx1, cy1, radius1: float64): PCairoPattern{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_reference*(pattern: Pcairo_pattern_t): Pcairo_pattern_t{. proc cairo_pattern_reference*(pattern: PCairoPattern): PCairoPattern{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_destroy*(pattern: Pcairo_pattern_t){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_pattern_destroy*(pattern: PCairoPattern){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_reference_count*(pattern: Pcairo_pattern_t): int32{. proc cairo_pattern_get_reference_count*(pattern: PCairoPattern): int32{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_status*(pattern: Pcairo_pattern_t): cairo_status_t{.cdecl, importc, proc cairo_pattern_status*(pattern: PCairoPattern): TCairoStatus{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_pattern_get_user_data*(pattern: Pcairo_pattern_t, proc cairo_pattern_get_user_data*(pattern: PCairoPattern,
key: Pcairo_user_data_key_t): Pointer{.cdecl, importc, key: PCairoUserDataKey): Pointer{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_pattern_set_user_data*(pattern: Pcairo_pattern_t, proc cairo_pattern_set_user_data*(pattern: PCairoPattern,
key: Pcairo_user_data_key_t, key: PCairoUserDataKey,
user_data: Pointer, user_data: Pointer,
destroy: cairo_destroy_func_t): cairo_status_t{. destroy: TCairoDestroyFunc): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_type*(pattern: Pcairo_pattern_t): cairo_pattern_type_t{. proc cairo_pattern_get_type*(pattern: PCairoPattern): TCairoPatternType{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_add_color_stop_rgb*(pattern: Pcairo_pattern_t, proc cairo_pattern_add_color_stop_rgb*(pattern: PCairoPattern,
offset, red, green, blue: float64){. offset, red, green, blue: float64){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_add_color_stop_rgba*(pattern: Pcairo_pattern_t, offset, red, proc cairo_pattern_add_color_stop_rgba*(pattern: PCairoPattern, offset, red,
green, blue, alpha: float64){.cdecl, importc, dynlib: LIB_CAIRO.} green, blue, alpha: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_set_matrix*(pattern: Pcairo_pattern_t, proc cairo_pattern_set_matrix*(pattern: PCairoPattern,
matrix: Pcairo_matrix_t){.cdecl, importc, matrix: PCairoMatrix){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_pattern_get_matrix*(pattern: Pcairo_pattern_t, proc cairo_pattern_get_matrix*(pattern: PCairoPattern,
matrix: Pcairo_matrix_t){.cdecl, importc, matrix: PCairoMatrix){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_pattern_set_extend*(pattern: Pcairo_pattern_t, extend: cairo_extend_t){. proc cairo_pattern_set_extend*(pattern: PCairoPattern, extend: TCairoExtend){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_extend*(pattern: Pcairo_pattern_t): cairo_extend_t{. proc cairo_pattern_get_extend*(pattern: PCairoPattern): TCairoExtend{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_set_filter*(pattern: Pcairo_pattern_t, filter: cairo_filter_t){. proc cairo_pattern_set_filter*(pattern: PCairoPattern, filter: TCairoFilter){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_filter*(pattern: Pcairo_pattern_t): cairo_filter_t{. proc cairo_pattern_get_filter*(pattern: PCairoPattern): TCairoFilter{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_rgba*(pattern: Pcairo_pattern_t, proc cairo_pattern_get_rgba*(pattern: PCairoPattern,
red, green, blue, alpha: var float64): cairo_status_t{. red, green, blue, alpha: var float64): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_surface*(pattern: Pcairo_pattern_t, proc cairo_pattern_get_surface*(pattern: PCairoPattern,
surface: PPcairo_surface_t): cairo_status_t{. surface: PPCairoSurface): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_color_stop_rgba*(pattern: Pcairo_pattern_t, index: int32, proc cairo_pattern_get_color_stop_rgba*(pattern: PCairoPattern, index: int32,
offset, red, green, blue, alpha: var float64): cairo_status_t{.cdecl, importc, offset, red, green, blue, alpha: var float64): TCairoStatus{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_pattern_get_color_stop_count*(pattern: Pcairo_pattern_t, proc cairo_pattern_get_color_stop_count*(pattern: PCairoPattern,
count: var int32): cairo_status_t{.cdecl, importc, dynlib: LIB_CAIRO.} count: var int32): TCairoStatus{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_linear_points*(pattern: Pcairo_pattern_t, proc cairo_pattern_get_linear_points*(pattern: PCairoPattern,
x0, y0, x1, y1: var float64): cairo_status_t{. x0, y0, x1, y1: var float64): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_radial_circles*(pattern: Pcairo_pattern_t, proc cairo_pattern_get_radial_circles*(pattern: PCairoPattern,
x0, y0, r0, x1, y1, r1: var float64): cairo_status_t{. x0, y0, r0, x1, y1, r1: var float64): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
#* Matrix functions #* Matrix functions
proc cairo_matrix_init*(matrix: Pcairo_matrix_t, xx, yx, xy, yy, x0, y0: float64){. proc cairo_matrix_init*(matrix: PCairoMatrix, xx, yx, xy, yy, x0, y0: float64){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_matrix_init_identity*(matrix: Pcairo_matrix_t){.cdecl, importc, proc cairo_matrix_init_identity*(matrix: PCairoMatrix){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_matrix_init_translate*(matrix: Pcairo_matrix_t, tx, ty: float64){. proc cairo_matrix_init_translate*(matrix: PCairoMatrix, tx, ty: float64){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_matrix_init_scale*(matrix: Pcairo_matrix_t, sx, sy: float64){.cdecl, importc, proc cairo_matrix_init_scale*(matrix: PCairoMatrix, sx, sy: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_matrix_init_rotate*(matrix: Pcairo_matrix_t, radians: float64){. proc cairo_matrix_init_rotate*(matrix: PCairoMatrix, radians: float64){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_matrix_translate*(matrix: Pcairo_matrix_t, tx, ty: float64){.cdecl, importc, proc cairo_matrix_translate*(matrix: PCairoMatrix, tx, ty: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_matrix_scale*(matrix: Pcairo_matrix_t, sx, sy: float64){.cdecl, importc, proc cairo_matrix_scale*(matrix: PCairoMatrix, sx, sy: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_matrix_rotate*(matrix: Pcairo_matrix_t, radians: float64){.cdecl, importc, proc cairo_matrix_rotate*(matrix: PCairoMatrix, radians: float64){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_matrix_invert*(matrix: Pcairo_matrix_t): cairo_status_t{.cdecl, importc, proc cairo_matrix_invert*(matrix: PCairoMatrix): TCairoStatus{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_matrix_multiply*(result, a, b: Pcairo_matrix_t){.cdecl, importc, proc cairo_matrix_multiply*(result, a, b: PCairoMatrix){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_matrix_transform_distance*(matrix: Pcairo_matrix_t, dx, dy: var float64){. proc cairo_matrix_transform_distance*(matrix: PCairoMatrix, dx, dy: var float64){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_matrix_transform_point*(matrix: Pcairo_matrix_t, x, y: var float64){. proc cairo_matrix_transform_point*(matrix: PCairoMatrix, x, y: var float64){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
#* PDF functions #* PDF functions
proc cairo_pdf_surface_create*(filename: cstring, proc cairo_pdf_surface_create*(filename: cstring,
width_in_points, height_in_points: float64): Pcairo_surface_t{. width_in_points, height_in_points: float64): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pdf_surface_create_for_stream*(write_func: cairo_write_func_t, proc cairo_pdf_surface_create_for_stream*(write_func: TCairoWriteFunc,
closure: Pointer, width_in_points, height_in_points: float64): Pcairo_surface_t{. closure: Pointer, width_in_points, height_in_points: float64): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pdf_surface_set_size*(surface: Pcairo_surface_t, proc cairo_pdf_surface_set_size*(surface: PCairoSurface,
width_in_points, height_in_points: float64){. width_in_points, height_in_points: float64){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
#* PS functions #* PS functions
proc cairo_ps_surface_create*(filename: cstring, proc cairo_ps_surface_create*(filename: cstring,
width_in_points, height_in_points: float64): Pcairo_surface_t{. width_in_points, height_in_points: float64): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ps_surface_create_for_stream*(write_func: cairo_write_func_t, proc cairo_ps_surface_create_for_stream*(write_func: TCairoWriteFunc,
closure: Pointer, width_in_points, height_in_points: float64): Pcairo_surface_t{. closure: Pointer, width_in_points, height_in_points: float64): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ps_surface_set_size*(surface: Pcairo_surface_t, proc cairo_ps_surface_set_size*(surface: PCairoSurface,
width_in_points, height_in_points: float64){. width_in_points, height_in_points: float64){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ps_surface_dsc_comment*(surface: Pcairo_surface_t, comment: cstring){. proc cairo_ps_surface_dsc_comment*(surface: PCairoSurface, comment: cstring){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ps_surface_dsc_begin_setup*(surface: Pcairo_surface_t){.cdecl, importc, proc cairo_ps_surface_dsc_begin_setup*(surface: PCairoSurface){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_ps_surface_dsc_begin_page_setup*(surface: Pcairo_surface_t){.cdecl, importc, proc cairo_ps_surface_dsc_begin_page_setup*(surface: PCairoSurface){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
#* SVG functions #* SVG functions
proc cairo_svg_surface_create*(filename: cstring, proc cairo_svg_surface_create*(filename: cstring,
width_in_points, height_in_points: float64): Pcairo_surface_t{. width_in_points, height_in_points: float64): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_svg_surface_create_for_stream*(write_func: cairo_write_func_t, proc cairo_svg_surface_create_for_stream*(write_func: TCairoWriteFunc,
closure: Pointer, width_in_points, height_in_points: float64): Pcairo_surface_t{. closure: Pointer, width_in_points, height_in_points: float64): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_svg_surface_restrict_to_version*(surface: Pcairo_surface_t, proc cairo_svg_surface_restrict_to_version*(surface: PCairoSurface,
version: cairo_svg_version_t){.cdecl, importc, dynlib: LIB_CAIRO.} version: TCairoSvgVersion){.cdecl, importc, dynlib: LIB_CAIRO.}
#todo: see how translate this #todo: see how translate this
#procedure cairo_svg_get_versions(cairo_svg_version_t const **versions, #procedure cairo_svg_get_versions(TCairoSvgVersion const **versions,
# int *num_versions); # int *num_versions);
proc cairo_svg_version_to_string*(version: cairo_svg_version_t): cstring{.cdecl, importc, proc cairo_svg_version_to_string*(version: TCairoSvgVersion): cstring{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
#* Functions to be used while debugging (not intended for use in production code) #* Functions to be used while debugging (not intended for use in production code)
proc cairo_debug_reset_static_data*(){.cdecl, importc, dynlib: LIB_CAIRO.} proc cairo_debug_reset_static_data*(){.cdecl, importc, dynlib: LIB_CAIRO.}
@ -693,6 +693,6 @@ proc cairo_debug_reset_static_data*(){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_version(major, minor, micro: var int32) = proc cairo_version(major, minor, micro: var int32) =
var version: int32 var version: int32
version = cairo_version() version = cairo_version()
major = version div 10000 major = version div 10000'i32
minor = (version mod (major * 10000)) div 100 minor = (version mod (major * 10000'i32)) div 100'i32
micro = (version mod ((major * 10000) + (minor * 100))) micro = (version mod ((major * 10000'i32) + (minor * 100'i32)))

View file

@ -4,7 +4,7 @@
# updated to version 1.4 by Luiz Américo Pereira Câmara 2007 # updated to version 1.4 by Luiz Américo Pereira Câmara 2007
# #
import Cairo, freetypeh import cairo, freetypeh
#todo: properly define FcPattern: #todo: properly define FcPattern:
#It will require translate FontConfig header #It will require translate FontConfig header
@ -20,17 +20,17 @@ import Cairo, freetypeh
type type
FcPattern* = Pointer FcPattern* = Pointer
PFcPattern* = ref FcPattern PFcPattern* = ptr FcPattern
proc cairo_ft_font_face_create_for_pattern*(pattern: PFcPattern): Pcairo_font_face_t{. proc cairo_ft_font_face_create_for_pattern*(pattern: PFcPattern): PCairoFontFace{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ft_font_options_substitute*(options: Pcairo_font_options_t, proc cairo_ft_font_options_substitute*(options: PCairoFontOptions,
pattern: PFcPattern){.cdecl, importc, pattern: PFcPattern){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_ft_font_face_create_for_ft_face*(face: TFT_Face, proc cairo_ft_font_face_create_for_ft_face*(face: TFT_Face,
load_flags: int32): Pcairo_font_face_t {.cdecl, importc, dynlib: LIB_CAIRO.} load_flags: int32): PCairoFontFace {.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ft_scaled_font_lock_face*( proc cairo_ft_scaled_font_lock_face*(
scaled_font: Pcairo_scaled_font_t): TFT_Face{.cdecl, importc, dynlib: LIB_CAIRO.} scaled_font: PCairoScaledFont): TFT_Face{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ft_scaled_font_unlock_face*( proc cairo_ft_scaled_font_unlock_face*(
scaled_font: Pcairo_scaled_font_t){.cdecl, importc, dynlib: LIB_CAIRO.} scaled_font: PCairoScaledFont){.cdecl, importc, dynlib: LIB_CAIRO.}

View file

@ -7,30 +7,30 @@
import import
Cairo, windows Cairo, windows
proc cairo_win32_surface_create*(hdc: HDC): Pcairo_surface_t{.cdecl, importc, proc cairo_win32_surface_create*(hdc: HDC): PCairoSurface{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_win32_surface_create_with_ddb*(hdc: HDC, format: cairo_format_t, proc cairo_win32_surface_create_with_ddb*(hdc: HDC, format: TCairoFormat,
width, height: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.} width, height: int32): PCairoSurface{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_surface_create_with_dib*(format: cairo_format_t, proc cairo_win32_surface_create_with_dib*(format: TCairoFormat,
width, height: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.} width, height: int32): PCairoSurface{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_surface_get_dc*(surface: pcairo_surface_t): HDC{.cdecl, importc, proc cairo_win32_surface_get_dc*(surface: PCairoSurface): HDC{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_win32_surface_get_image*(surface: pcairo_surface_t): Pcairo_surface_t{. proc cairo_win32_surface_get_image*(surface: PCairoSurface): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_font_face_create_for_logfontw*(logfont: pLOGFONTW): Pcairo_font_face_t{. proc cairo_win32_font_face_create_for_logfontw*(logfont: pLOGFONTW): PCairoFontFace{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_font_face_create_for_hfont*(font: HFONT): Pcairo_font_face_t{. proc cairo_win32_font_face_create_for_hfont*(font: HFONT): PCairoFontFace{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_select_font*(scaled_font: pcairo_scaled_font_t, proc cairo_win32_scaled_font_select_font*(scaled_font: PCairoScaledFont,
hdc: HDC): cairo_status_t{.cdecl, importc, dynlib: LIB_CAIRO.} hdc: HDC): TCairoStatus{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_done_font*(scaled_font: pcairo_scaled_font_t){. proc cairo_win32_scaled_font_done_font*(scaled_font: PCairoScaledFont){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_get_metrics_factor*( proc cairo_win32_scaled_font_get_metrics_factor*(
scaled_font: pcairo_scaled_font_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.} scaled_font: PCairoScaledFont): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_get_logical_to_device*( proc cairo_win32_scaled_font_get_logical_to_device*(
scaled_font: pcairo_scaled_font_t, logical_to_device: pcairo_matrix_t){. scaled_font: PCairoScaledFont, logical_to_device: PCairoMatrix){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_get_device_to_logical*( proc cairo_win32_scaled_font_get_device_to_logical*(
scaled_font: pcairo_scaled_font_t, device_to_logical: pcairo_matrix_t){. scaled_font: PCairoScaledFont, device_to_logical: PCairoMatrix){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
# implementation # implementation

View file

@ -9,32 +9,32 @@ import
Cairo, x, xlib, xrender Cairo, x, xlib, xrender
proc cairo_xlib_surface_create*(dpy: PDisplay, drawable: TDrawable, proc cairo_xlib_surface_create*(dpy: PDisplay, drawable: TDrawable,
visual: PVisual, width, height: int32): Pcairo_surface_t{. visual: PVisual, width, height: int32): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_create_for_bitmap*(dpy: PDisplay, bitmap: TPixmap, proc cairo_xlib_surface_create_for_bitmap*(dpy: PDisplay, bitmap: TPixmap,
screen: PScreen, width, height: int32): Pcairo_surface_t{.cdecl, importc, screen: PScreen, width, height: int32): PCairoSurface{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_create_with_xrender_format*(dpy: PDisplay, proc cairo_xlib_surface_create_with_xrender_format*(dpy: PDisplay,
drawable: TDrawable, screen: PScreen, format: PXRenderPictFormat, drawable: TDrawable, screen: PScreen, format: PXRenderPictFormat,
width, height: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.} width, height: int32): PCairoSurface{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_depth*(surface: Pcairo_surface_t): int32{.cdecl, importc, proc cairo_xlib_surface_get_depth*(surface: PCairoSurface): int32{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_display*(surface: Pcairo_surface_t): PDisplay{. proc cairo_xlib_surface_get_display*(surface: PCairoSurface): PDisplay{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_drawable*(surface: Pcairo_surface_t): TDrawable{. proc cairo_xlib_surface_get_drawable*(surface: PCairoSurface): TDrawable{.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_height*(surface: Pcairo_surface_t): int32{.cdecl, importc, proc cairo_xlib_surface_get_height*(surface: PCairoSurface): int32{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_screen*(surface: Pcairo_surface_t): PScreen{.cdecl, importc, proc cairo_xlib_surface_get_screen*(surface: PCairoSurface): PScreen{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_visual*(surface: Pcairo_surface_t): PVisual{.cdecl, importc, proc cairo_xlib_surface_get_visual*(surface: PCairoSurface): PVisual{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_width*(surface: Pcairo_surface_t): int32{.cdecl, importc, proc cairo_xlib_surface_get_width*(surface: PCairoSurface): int32{.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_set_size*(surface: Pcairo_surface_t, proc cairo_xlib_surface_set_size*(surface: PCairoSurface,
width, height: int32){.cdecl, importc, width, height: int32){.cdecl, importc,
dynlib: LIB_CAIRO.} dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_set_drawable*(surface: Pcairo_surface_t, proc cairo_xlib_surface_set_drawable*(surface: PCairoSurface,
drawable: TDrawable, width, height: int32){. drawable: TDrawable, width, height: int32){.
cdecl, importc, dynlib: LIB_CAIRO.} cdecl, importc, dynlib: LIB_CAIRO.}
# implementation # implementation

View file

@ -90,7 +90,7 @@ proc ChooseFileToOpen*(window: PWindow, root: string = ""): string =
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil)) GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
if root.len > 0: if root.len > 0:
discard gtk_file_chooser_set_current_folder(chooser, root) discard gtk_file_chooser_set_current_folder(chooser, root)
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK: if gtk_dialog_run(chooser) == cint(GTK_RESPONSE_OK):
var x = gtk_file_chooser_get_filename(chooser) var x = gtk_file_chooser_get_filename(chooser)
result = $x result = $x
g_free(x) g_free(x)
@ -99,7 +99,7 @@ proc ChooseFileToOpen*(window: PWindow, root: string = ""): string =
gtk_widget_destroy(chooser) gtk_widget_destroy(chooser)
proc ChooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] = proc ChooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] =
## Opens a dialog that requests filenames from the user. Returns [] ## Opens a dialog that requests filenames from the user. Returns ``@[]``
## if the user closed the dialog without selecting a file. On Windows, ## if the user closed the dialog without selecting a file. On Windows,
## the native dialog is used, else the GTK dialog is used. ## the native dialog is used, else the GTK dialog is used.
when defined(Windows): when defined(Windows):
@ -114,7 +114,7 @@ proc ChooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] =
opf.lpstrFile = buf opf.lpstrFile = buf
opf.nMaxFile = sizeof(buf) opf.nMaxFile = sizeof(buf)
var res = GetOpenFileName(addr(opf)) var res = GetOpenFileName(addr(opf))
result = [] result = @[]
if res != 0: if res != 0:
# parsing the result is horrible: # parsing the result is horrible:
var var
@ -145,8 +145,8 @@ proc ChooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] =
if root.len > 0: if root.len > 0:
discard gtk_file_chooser_set_current_folder(chooser, root) discard gtk_file_chooser_set_current_folder(chooser, root)
gtk_file_chooser_set_select_multiple(chooser, true) gtk_file_chooser_set_select_multiple(chooser, true)
result = [] result = @[]
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK: if gtk_dialog_run(chooser) == cint(GTK_RESPONSE_OK):
var L = gtk_file_chooser_get_filenames(chooser) var L = gtk_file_chooser_get_filenames(chooser)
var it = L var it = L
while it != nil: while it != nil:
@ -187,7 +187,7 @@ proc ChooseFileToSave*(window: PWindow, root: string = ""): string =
if root.len > 0: if root.len > 0:
discard gtk_file_chooser_set_current_folder(chooser, root) discard gtk_file_chooser_set_current_folder(chooser, root)
gtk_file_chooser_set_do_overwrite_confirmation(chooser, true) gtk_file_chooser_set_do_overwrite_confirmation(chooser, true)
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK: if gtk_dialog_run(chooser) == cint(GTK_RESPONSE_OK):
var x = gtk_file_chooser_get_filename(chooser) var x = gtk_file_chooser_get_filename(chooser)
result = $x result = $x
g_free(x) g_free(x)
@ -224,7 +224,7 @@ proc ChooseDir*(window: PWindow, root: string = ""): string =
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil)) GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
if root.len > 0: if root.len > 0:
discard gtk_file_chooser_set_current_folder(chooser, root) discard gtk_file_chooser_set_current_folder(chooser, root)
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK: if gtk_dialog_run(chooser) == cint(GTK_RESPONSE_OK):
var x = gtk_file_chooser_get_filename(chooser) var x = gtk_file_chooser_get_filename(chooser)
result = $x result = $x
g_free(x) g_free(x)

View file

@ -2,7 +2,6 @@ import
glib2 glib2
when defined(windows): when defined(windows):
{.define: atkwin.}
const const
atklib = "libatk-1.0-0.dll" atklib = "libatk-1.0-0.dll"
else: else:

File diff suppressed because it is too large Load diff

View file

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

View file

@ -1,16 +1,16 @@
when defined(windows): when defined(windows):
{.define: gtkwin.}
const const
gliblib = "libglib-2.0-0.dll" gliblib = "libglib-2.0-0.dll"
gthreadlib = "libgthread-2.0-0.dll"
gmodulelib = "libgmodule-2.0-0.dll" gmodulelib = "libgmodule-2.0-0.dll"
gobjectlib = "libgobject-2.0-0.dll" gobjectlib = "libgobject-2.0-0.dll"
else: else:
const const
gliblib = "libglib-2.0.so" gliblib = "libglib-2.0.so"
gthreadlib = "libgthread-2.0.so"
gmodulelib = "libgmodule-2.0.so" gmodulelib = "libgmodule-2.0.so"
gobjectlib = "libgobject-2.0.so" gobjectlib = "libgobject-2.0.so"
# gthreadlib = "libgthread-2.0.so"
type type
PGTypePlugin* = pointer PGTypePlugin* = pointer
PGParamSpecPool* = pointer PGParamSpecPool* = pointer
@ -19,29 +19,29 @@ type
PPPgchar* = ptr PPgchar PPPgchar* = ptr PPgchar
PPgchar* = ptr cstring PPgchar* = ptr cstring
gchar* = char gchar* = char
Pgshort* = ptr gshort
gshort* = cshort gshort* = cshort
Pglong* = ptr glong
glong* = clong glong* = clong
Pgint* = ptr gint
PPgint* = ptr Pgint
gint* = cint gint* = cint
Pgboolean* = ptr gboolean
gboolean* = bool gboolean* = bool
Pguchar* = ptr guchar
PPguchar* = ptr Pguchar
guchar* = char guchar* = char
Pgushort* = ptr gushort
gushort* = int16 gushort* = int16
Pgulong* = ptr gulong
gulong* = int gulong* = int
guint* = cint guint* = cint
Pguint* = ptr guint
gfloat* = cfloat gfloat* = cfloat
Pgfloat* = ptr gfloat
gdouble* = cdouble gdouble* = cdouble
Pgdouble* = ptr gdouble
gpointer* = pointer gpointer* = pointer
Pgshort* = ptr gshort
Pglong* = ptr glong
Pgint* = ptr gint
PPgint* = ptr Pgint
Pgboolean* = ptr gboolean
Pguchar* = ptr guchar
PPguchar* = ptr Pguchar
Pgushort* = ptr gushort
Pgulong* = ptr gulong
Pguint* = ptr guint
Pgfloat* = ptr gfloat
Pgdouble* = ptr gdouble
pgpointer* = ptr gpointer pgpointer* = ptr gpointer
gconstpointer* = pointer gconstpointer* = pointer
PGCompareFunc* = ptr TGCompareFunc PGCompareFunc* = ptr TGCompareFunc
@ -118,8 +118,8 @@ type
g_type*: GType g_type*: GType
data*: array[0..1, gdouble] data*: array[0..1, gdouble]
PPGData* = ptr PGData
PGData* = pointer PGData* = pointer
PPGData* = ptr PGData
PGSList* = ptr TGSList PGSList* = ptr TGSList
PPGSList* = ptr PGSList PPGSList* = ptr PGSList
TGSList* {.final.} = object TGSList* {.final.} = object
@ -132,8 +132,8 @@ type
next*: PGList next*: PGList
prev*: PGList prev*: PGList
PGParamFlags* = ptr TGParamFlags
TGParamFlags* = int32 TGParamFlags* = int32
PGParamFlags* = ptr TGParamFlags
PGParamSpec* = ptr TGParamSpec PGParamSpec* = ptr TGParamSpec
PPGParamSpec* = ptr PGParamSpec PPGParamSpec* = ptr PGParamSpec
TGParamSpec* {.final.} = object TGParamSpec* {.final.} = object
@ -194,7 +194,7 @@ const
G_TYPE_PARAM* = GType(19 shl G_TYPE_FUNDAMENTAL_SHIFT) G_TYPE_PARAM* = GType(19 shl G_TYPE_FUNDAMENTAL_SHIFT)
G_TYPE_OBJECT* = GType(20 shl G_TYPE_FUNDAMENTAL_SHIFT) G_TYPE_OBJECT* = GType(20 shl G_TYPE_FUNDAMENTAL_SHIFT)
proc G_TYPE_MAKE_FUNDAMENTAL*(x: int32): GType proc G_TYPE_MAKE_FUNDAMENTAL*(x: int): GType
const const
G_TYPE_RESERVED_GLIB_FIRST* = 21 G_TYPE_RESERVED_GLIB_FIRST* = 21
G_TYPE_RESERVED_GLIB_LAST* = 31 G_TYPE_RESERVED_GLIB_LAST* = 31
@ -226,8 +226,8 @@ proc G_TYPE_FROM_INSTANCE*(instance: Pointer): GType
proc G_TYPE_FROM_CLASS*(g_class: Pointer): GType proc G_TYPE_FROM_CLASS*(g_class: Pointer): GType
proc G_TYPE_FROM_INTERFACE*(g_iface: Pointer): GType proc G_TYPE_FROM_INTERFACE*(g_iface: Pointer): GType
type type
PGTypeDebugFlags* = ptr TGTypeDebugFlags
TGTypeDebugFlags* = int32 TGTypeDebugFlags* = int32
PGTypeDebugFlags* = ptr TGTypeDebugFlags
const const
G_TYPE_DEBUG_NONE* = 0 G_TYPE_DEBUG_NONE* = 0
@ -296,8 +296,8 @@ const
G_TYPE_FLAG_DEEP_DERIVABLE* = 1 shl 3 G_TYPE_FLAG_DEEP_DERIVABLE* = 1 shl 3
type type
PGTypeFlags* = ptr TGTypeFlags
TGTypeFlags* = int32 TGTypeFlags* = int32
PGTypeFlags* = ptr TGTypeFlags
const const
G_TYPE_FLAG_ABSTRACT* = 1 shl 4 G_TYPE_FLAG_ABSTRACT* = 1 shl 4
@ -562,8 +562,8 @@ proc g_strdup_value_contents*(value: PGValue): cstring{.cdecl,
proc g_value_set_string_take_ownership*(value: PGValue, v_string: cstring){. proc g_value_set_string_take_ownership*(value: PGValue, v_string: cstring){.
cdecl, dynlib: gobjectlib, importc: "g_value_set_string_take_ownership".} cdecl, dynlib: gobjectlib, importc: "g_value_set_string_take_ownership".}
type type
Pgchararray* = ptr Tgchararray
Tgchararray* = gchar Tgchararray* = gchar
Pgchararray* = ptr Tgchararray
proc G_TYPE_IS_PARAM*(theType: GType): bool proc G_TYPE_IS_PARAM*(theType: GType): bool
proc G_PARAM_SPEC*(pspec: Pointer): PGParamSpec proc G_PARAM_SPEC*(pspec: Pointer): PGParamSpec
@ -692,26 +692,26 @@ proc G_CLOSURE_N_NOTIFIERS*(cl: PGClosure): int32
proc G_CCLOSURE_SWAP_DATA*(cclosure: PGClosure): int32 proc G_CCLOSURE_SWAP_DATA*(cclosure: PGClosure): int32
proc G_CALLBACK*(f: pointer): TGCallback proc G_CALLBACK*(f: pointer): TGCallback
const const
bm_TGClosure_ref_count* = 0x00007FFF bm_TGClosure_ref_count* = 0x00007FFF'i32
bp_TGClosure_ref_count* = 0 bp_TGClosure_ref_count* = 0'i32
bm_TGClosure_meta_marshal* = 0x00008000 bm_TGClosure_meta_marshal* = 0x00008000'i32
bp_TGClosure_meta_marshal* = 15 bp_TGClosure_meta_marshal* = 15'i32
bm_TGClosure_n_guards* = 0x00010000 bm_TGClosure_n_guards* = 0x00010000'i32
bp_TGClosure_n_guards* = 16 bp_TGClosure_n_guards* = 16'i32
bm_TGClosure_n_fnotifiers* = 0x00060000 bm_TGClosure_n_fnotifiers* = 0x00060000'i32
bp_TGClosure_n_fnotifiers* = 17 bp_TGClosure_n_fnotifiers* = 17'i32
bm_TGClosure_n_inotifiers* = 0x07F80000 bm_TGClosure_n_inotifiers* = 0x07F80000'i32
bp_TGClosure_n_inotifiers* = 19 bp_TGClosure_n_inotifiers* = 19'i32
bm_TGClosure_in_inotify* = 0x08000000 bm_TGClosure_in_inotify* = 0x08000000'i32
bp_TGClosure_in_inotify* = 27 bp_TGClosure_in_inotify* = 27'i32
bm_TGClosure_floating* = 0x10000000 bm_TGClosure_floating* = 0x10000000'i32
bp_TGClosure_floating* = 28 bp_TGClosure_floating* = 28'i32
bm_TGClosure_derivative_flag* = 0x20000000 bm_TGClosure_derivative_flag* = 0x20000000'i32
bp_TGClosure_derivative_flag* = 29 bp_TGClosure_derivative_flag* = 29'i32
bm_TGClosure_in_marshal* = 0x40000000 bm_TGClosure_in_marshal* = 0x40000000'i32
bp_TGClosure_in_marshal* = 30 bp_TGClosure_in_marshal* = 30'i32
bm_TGClosure_is_invalid* = 0x80000000 bm_TGClosure_is_invalid* = 0x80000000'i32
bp_TGClosure_is_invalid* = 31 bp_TGClosure_is_invalid* = 31'i32
proc ref_count*(a: var TGClosure): guint proc ref_count*(a: var TGClosure): guint
proc set_ref_count*(a: var TGClosure, ref_count: guint) proc set_ref_count*(a: var TGClosure, ref_count: guint)
@ -2061,16 +2061,16 @@ type
TGHookFlagMask* = int TGHookFlagMask* = int
const const
G_HOOK_FLAG_ACTIVE* = 1 shl 0 G_HOOK_FLAG_ACTIVE* = 1'i32 shl 0'i32
G_HOOK_FLAG_IN_CALL* = 1 shl 1 G_HOOK_FLAG_IN_CALL* = 1'i32 shl 1'i32
G_HOOK_FLAG_MASK* = 0x0000000F G_HOOK_FLAG_MASK* = 0x0000000F'i32
const const
G_HOOK_FLAG_USER_SHIFT* = 4 G_HOOK_FLAG_USER_SHIFT* = 4'i32
bm_TGHookList_hook_size* = 0x0000FFFF bm_TGHookList_hook_size* = 0x0000FFFF'i32
bp_TGHookList_hook_size* = 0 bp_TGHookList_hook_size* = 0'i32
bm_TGHookList_is_setup* = 0x00010000 bm_TGHookList_is_setup* = 0x00010000'i32
bp_TGHookList_is_setup* = 16 bp_TGHookList_is_setup* = 16'i32
proc TGHookList_hook_size*(a: var TGHookList): guint proc TGHookList_hook_size*(a: var TGHookList): guint
proc TGHookList_set_hook_size*(a: var TGHookList, `hook_size`: guint) proc TGHookList_set_hook_size*(a: var TGHookList, `hook_size`: guint)
@ -2502,18 +2502,18 @@ type
const const
bm_TGIOChannel_use_buffer* = 0x00000001 bm_TGIOChannel_use_buffer* = 0x00000001'i16
bp_TGIOChannel_use_buffer* = 0 bp_TGIOChannel_use_buffer* = 0'i16
bm_TGIOChannel_do_encode* = 0x00000002 bm_TGIOChannel_do_encode* = 0x00000002'i16
bp_TGIOChannel_do_encode* = 1 bp_TGIOChannel_do_encode* = 1'i16
bm_TGIOChannel_close_on_unref* = 0x00000004 bm_TGIOChannel_close_on_unref* = 0x00000004'i16
bp_TGIOChannel_close_on_unref* = 2 bp_TGIOChannel_close_on_unref* = 2'i16
bm_TGIOChannel_is_readable* = 0x00000008 bm_TGIOChannel_is_readable* = 0x00000008'i16
bp_TGIOChannel_is_readable* = 3 bp_TGIOChannel_is_readable* = 3'i16
bm_TGIOChannel_is_writeable* = 0x00000010 bm_TGIOChannel_is_writeable* = 0x00000010'i16
bp_TGIOChannel_is_writeable* = 4 bp_TGIOChannel_is_writeable* = 4'i16
bm_TGIOChannel_is_seekable* = 0x00000020 bm_TGIOChannel_is_seekable* = 0x00000020'i16
bp_TGIOChannel_is_seekable* = 5 bp_TGIOChannel_is_seekable* = 5'i16
proc TGIOChannel_use_buffer*(a: var TGIOChannel): guint proc TGIOChannel_use_buffer*(a: var TGIOChannel): guint
proc TGIOChannel_set_use_buffer*(a: var TGIOChannel, `use_buffer`: guint) proc TGIOChannel_set_use_buffer*(a: var TGIOChannel, `use_buffer`: guint)
@ -3046,48 +3046,48 @@ const
G_CSET_DIGITS* = "0123456789" G_CSET_DIGITS* = "0123456789"
const const
bm_TGScannerConfig_case_sensitive* = 0x00000001 bm_TGScannerConfig_case_sensitive* = 0x00000001'i32
bp_TGScannerConfig_case_sensitive* = 0 bp_TGScannerConfig_case_sensitive* = 0'i32
bm_TGScannerConfig_skip_comment_multi* = 0x00000002 bm_TGScannerConfig_skip_comment_multi* = 0x00000002'i32
bp_TGScannerConfig_skip_comment_multi* = 1 bp_TGScannerConfig_skip_comment_multi* = 1'i32
bm_TGScannerConfig_skip_comment_single* = 0x00000004 bm_TGScannerConfig_skip_comment_single* = 0x00000004'i32
bp_TGScannerConfig_skip_comment_single* = 2 bp_TGScannerConfig_skip_comment_single* = 2'i32
bm_TGScannerConfig_scan_comment_multi* = 0x00000008 bm_TGScannerConfig_scan_comment_multi* = 0x00000008'i32
bp_TGScannerConfig_scan_comment_multi* = 3 bp_TGScannerConfig_scan_comment_multi* = 3'i32
bm_TGScannerConfig_scan_identifier* = 0x00000010 bm_TGScannerConfig_scan_identifier* = 0x00000010'i32
bp_TGScannerConfig_scan_identifier* = 4 bp_TGScannerConfig_scan_identifier* = 4'i32
bm_TGScannerConfig_scan_identifier_1char* = 0x00000020 bm_TGScannerConfig_scan_identifier_1char* = 0x00000020'i32
bp_TGScannerConfig_scan_identifier_1char* = 5 bp_TGScannerConfig_scan_identifier_1char* = 5'i32
bm_TGScannerConfig_scan_identifier_NULL* = 0x00000040 bm_TGScannerConfig_scan_identifier_NULL* = 0x00000040'i32
bp_TGScannerConfig_scan_identifier_NULL* = 6 bp_TGScannerConfig_scan_identifier_NULL* = 6'i32
bm_TGScannerConfig_scan_symbols* = 0x00000080 bm_TGScannerConfig_scan_symbols* = 0x00000080'i32
bp_TGScannerConfig_scan_symbols* = 7 bp_TGScannerConfig_scan_symbols* = 7'i32
bm_TGScannerConfig_scan_binary* = 0x00000100 bm_TGScannerConfig_scan_binary* = 0x00000100'i32
bp_TGScannerConfig_scan_binary* = 8 bp_TGScannerConfig_scan_binary* = 8'i32
bm_TGScannerConfig_scan_octal* = 0x00000200 bm_TGScannerConfig_scan_octal* = 0x00000200'i32
bp_TGScannerConfig_scan_octal* = 9 bp_TGScannerConfig_scan_octal* = 9'i32
bm_TGScannerConfig_scan_float* = 0x00000400 bm_TGScannerConfig_scan_float* = 0x00000400'i32
bp_TGScannerConfig_scan_float* = 10 bp_TGScannerConfig_scan_float* = 10'i32
bm_TGScannerConfig_scan_hex* = 0x00000800 bm_TGScannerConfig_scan_hex* = 0x00000800'i32
bp_TGScannerConfig_scan_hex* = 11 bp_TGScannerConfig_scan_hex* = 11'i32
bm_TGScannerConfig_scan_hex_dollar* = 0x00001000 bm_TGScannerConfig_scan_hex_dollar* = 0x00001000'i32
bp_TGScannerConfig_scan_hex_dollar* = 12 bp_TGScannerConfig_scan_hex_dollar* = 12'i32
bm_TGScannerConfig_scan_string_sq* = 0x00002000 bm_TGScannerConfig_scan_string_sq* = 0x00002000'i32
bp_TGScannerConfig_scan_string_sq* = 13 bp_TGScannerConfig_scan_string_sq* = 13'i32
bm_TGScannerConfig_scan_string_dq* = 0x00004000 bm_TGScannerConfig_scan_string_dq* = 0x00004000'i32
bp_TGScannerConfig_scan_string_dq* = 14 bp_TGScannerConfig_scan_string_dq* = 14'i32
bm_TGScannerConfig_numbers_2_int* = 0x00008000 bm_TGScannerConfig_numbers_2_int* = 0x00008000'i32
bp_TGScannerConfig_numbers_2_int* = 15 bp_TGScannerConfig_numbers_2_int* = 15'i32
bm_TGScannerConfig_int_2_float* = 0x00010000 bm_TGScannerConfig_int_2_float* = 0x00010000'i32
bp_TGScannerConfig_int_2_float* = 16 bp_TGScannerConfig_int_2_float* = 16'i32
bm_TGScannerConfig_identifier_2_string* = 0x00020000 bm_TGScannerConfig_identifier_2_string* = 0x00020000'i32
bp_TGScannerConfig_identifier_2_string* = 17 bp_TGScannerConfig_identifier_2_string* = 17'i32
bm_TGScannerConfig_char_2_token* = 0x00040000 bm_TGScannerConfig_char_2_token* = 0x00040000'i32
bp_TGScannerConfig_char_2_token* = 18 bp_TGScannerConfig_char_2_token* = 18'i32
bm_TGScannerConfig_symbol_2_token* = 0x00080000 bm_TGScannerConfig_symbol_2_token* = 0x00080000'i32
bp_TGScannerConfig_symbol_2_token* = 19 bp_TGScannerConfig_symbol_2_token* = 19'i32
bm_TGScannerConfig_scope_0_fallback* = 0x00100000 bm_TGScannerConfig_scope_0_fallback* = 0x00100000'i32
bp_TGScannerConfig_scope_0_fallback* = 20 bp_TGScannerConfig_scope_0_fallback* = 20'i32
proc TGScannerConfig_case_sensitive*(a: var TGScannerConfig): guint proc TGScannerConfig_case_sensitive*(a: var TGScannerConfig): guint
proc TGScannerConfig_set_case_sensitive*(a: var TGScannerConfig, proc TGScannerConfig_set_case_sensitive*(a: var TGScannerConfig,
@ -3439,19 +3439,21 @@ proc g_cclosure_marshal_BOOL__FLAGS*(closure: PGClosure, return_value: PGValue,
marshal_data: GPointer){.cdecl, marshal_data: GPointer){.cdecl,
dynlib: gliblib, importc: "g_cclosure_marshal_BOOLEAN__FLAGS".} dynlib: gliblib, importc: "g_cclosure_marshal_BOOLEAN__FLAGS".}
proc GUINT16_SWAP_LE_BE_CONSTANT*(val: guint16): guint16 = proc GUINT16_SWAP_LE_BE_CONSTANT*(val: guint16): guint16 =
Result = ((val and 0x000000FF) shl 8) or ((val and 0x0000FF00) shr 8) Result = ((val and 0x00FF'i16) shl 8'i16) or ((val and 0xFF00'i16) shr 8'i16)
proc GUINT32_SWAP_LE_BE_CONSTANT*(val: guint32): guint32 = proc GUINT32_SWAP_LE_BE_CONSTANT*(val: guint32): guint32 =
Result = ((val and 0x000000FF) shl 24) or ((val and 0x0000FF00) shl 8) or Result = ((val and 0x000000FF'i32) shl 24'i32) or ((val and 0x0000FF00'i32) shl 8'i32) or
((val and 0x00FF0000) shr 8) or ((val and 0xFF000000) shr 24) ((val and 0x00FF0000'i32) shr 8'i32) or ((val and 0xFF000000'i32) shr 24'i32)
proc GUINT_TO_POINTER*(i: guint): pointer = proc GUINT_TO_POINTER*(i: guint): pointer =
Result = cast[Pointer](TAddress(i)) Result = cast[Pointer](TAddress(i))
type
PGArray = pointer
when false: when false:
type
PGArray* = pointer
proc g_array_append_val*(a: PGArray, v: gpointer): PGArray = proc g_array_append_val*(a: PGArray, v: gpointer): PGArray =
result = g_array_append_vals(a, addr(v), 1) result = g_array_append_vals(a, addr(v), 1)
@ -3678,17 +3680,17 @@ proc G_HOOK_FLAGS*(hook: PGHook): guint =
result = hook.flags result = hook.flags
proc G_HOOK_ACTIVE*(hook: PGHook): bool = proc G_HOOK_ACTIVE*(hook: PGHook): bool =
result = (hook.flags and G_HOOK_FLAG_ACTIVE) != 0 result = (hook.flags and G_HOOK_FLAG_ACTIVE) != 0'i32
proc G_HOOK_IN_CALL*(hook: PGHook): bool = proc G_HOOK_IN_CALL*(hook: PGHook): bool =
result = (hook.flags and G_HOOK_FLAG_IN_CALL) != 0 result = (hook.flags and G_HOOK_FLAG_IN_CALL) != 0'i32
proc G_HOOK_IS_VALID*(hook: PGHook): bool = proc G_HOOK_IS_VALID*(hook: PGHook): bool =
result = (hook.hook_id != 0) and G_HOOK_ACTIVE(hook) result = (hook.hook_id != 0) and G_HOOK_ACTIVE(hook)
proc G_HOOK_IS_UNLINKED*(hook: PGHook): bool = proc G_HOOK_IS_UNLINKED*(hook: PGHook): bool =
result = (hook.next == nil) and (hook.prev == nil) and result = (hook.next == nil) and (hook.prev == nil) and
(hook.hook_id == 0) and (hook.ref_count == 0) (hook.hook_id == 0) and (hook.ref_count == 0'i32)
proc g_hook_append*(hook_list: PGHookList, hook: PGHook) = proc g_hook_append*(hook_list: PGHookList, hook: PGHook) =
g_hook_insert_before(hook_list, nil, hook) g_hook_insert_before(hook_list, nil, hook)
@ -3702,7 +3704,7 @@ proc TGIOChannel_use_buffer*(a: var TGIOChannel): guint =
proc TGIOChannel_set_use_buffer*(a: var TGIOChannel, `use_buffer`: guint) = proc TGIOChannel_set_use_buffer*(a: var TGIOChannel, `use_buffer`: guint) =
a.flag0 = a.flag0 or a.flag0 = a.flag0 or
((`use_buffer` shl bp_TGIOChannel_use_buffer) and (int16(`use_buffer` shl bp_TGIOChannel_use_buffer) and
bm_TGIOChannel_use_buffer) bm_TGIOChannel_use_buffer)
proc TGIOChannel_do_encode*(a: var TGIOChannel): guint = proc TGIOChannel_do_encode*(a: var TGIOChannel): guint =
@ -3711,7 +3713,7 @@ proc TGIOChannel_do_encode*(a: var TGIOChannel): guint =
proc TGIOChannel_set_do_encode*(a: var TGIOChannel, `do_encode`: guint) = proc TGIOChannel_set_do_encode*(a: var TGIOChannel, `do_encode`: guint) =
a.flag0 = a.flag0 or a.flag0 = a.flag0 or
((`do_encode` shl bp_TGIOChannel_do_encode) and (int16(`do_encode` shl bp_TGIOChannel_do_encode) and
bm_TGIOChannel_do_encode) bm_TGIOChannel_do_encode)
proc TGIOChannel_close_on_unref*(a: var TGIOChannel): guint = proc TGIOChannel_close_on_unref*(a: var TGIOChannel): guint =
@ -3720,7 +3722,7 @@ proc TGIOChannel_close_on_unref*(a: var TGIOChannel): guint =
proc TGIOChannel_set_close_on_unref*(a: var TGIOChannel, `close_on_unref`: guint) = proc TGIOChannel_set_close_on_unref*(a: var TGIOChannel, `close_on_unref`: guint) =
a.flag0 = a.flag0 or a.flag0 = a.flag0 or
((`close_on_unref` shl bp_TGIOChannel_close_on_unref) and (int16(`close_on_unref` shl bp_TGIOChannel_close_on_unref) and
bm_TGIOChannel_close_on_unref) bm_TGIOChannel_close_on_unref)
proc TGIOChannel_is_readable*(a: var TGIOChannel): guint = proc TGIOChannel_is_readable*(a: var TGIOChannel): guint =
@ -3729,7 +3731,7 @@ proc TGIOChannel_is_readable*(a: var TGIOChannel): guint =
proc TGIOChannel_set_is_readable*(a: var TGIOChannel, `is_readable`: guint) = proc TGIOChannel_set_is_readable*(a: var TGIOChannel, `is_readable`: guint) =
a.flag0 = a.flag0 or a.flag0 = a.flag0 or
((`is_readable` shl bp_TGIOChannel_is_readable) and (int16(`is_readable` shl bp_TGIOChannel_is_readable) and
bm_TGIOChannel_is_readable) bm_TGIOChannel_is_readable)
proc TGIOChannel_is_writeable*(a: var TGIOChannel): guint = proc TGIOChannel_is_writeable*(a: var TGIOChannel): guint =
@ -3738,7 +3740,7 @@ proc TGIOChannel_is_writeable*(a: var TGIOChannel): guint =
proc TGIOChannel_set_is_writeable*(a: var TGIOChannel, `is_writeable`: guint) = proc TGIOChannel_set_is_writeable*(a: var TGIOChannel, `is_writeable`: guint) =
a.flag0 = a.flag0 or a.flag0 = a.flag0 or
((`is_writeable` shl bp_TGIOChannel_is_writeable) and (int16(`is_writeable` shl bp_TGIOChannel_is_writeable) and
bm_TGIOChannel_is_writeable) bm_TGIOChannel_is_writeable)
proc TGIOChannel_is_seekable*(a: var TGIOChannel): guint = proc TGIOChannel_is_seekable*(a: var TGIOChannel): guint =
@ -3747,7 +3749,7 @@ proc TGIOChannel_is_seekable*(a: var TGIOChannel): guint =
proc TGIOChannel_set_is_seekable*(a: var TGIOChannel, `is_seekable`: guint) = proc TGIOChannel_set_is_seekable*(a: var TGIOChannel, `is_seekable`: guint) =
a.flag0 = a.flag0 or a.flag0 = a.flag0 or
((`is_seekable` shl bp_TGIOChannel_is_seekable) and (int16(`is_seekable` shl bp_TGIOChannel_is_seekable) and
bm_TGIOChannel_is_seekable) bm_TGIOChannel_is_seekable)
proc g_utf8_next_char*(p: pguchar): pguchar = proc g_utf8_next_char*(p: pguchar): pguchar =
@ -3816,10 +3818,10 @@ proc g_node_first_child*(node: PGNode): PGNode =
result = nil result = nil
proc g_rand_boolean*(rand: PGRand): gboolean = proc g_rand_boolean*(rand: PGRand): gboolean =
result = ((g_rand_int(rand)) and (1 shl 15)) != 0 result = (int(g_rand_int(rand)) and (1 shl 15)) != 0
proc g_random_boolean*(): gboolean = proc g_random_boolean*(): gboolean =
result = (g_random_int() and (1 shl 15)) != 0 result = (int(g_random_int()) and (1 shl 15)) != 0
proc TGScannerConfig_case_sensitive*(a: var TGScannerConfig): guint = proc TGScannerConfig_case_sensitive*(a: var TGScannerConfig): guint =
result = (a.flag0 and bm_TGScannerConfig_case_sensitive) shr result = (a.flag0 and bm_TGScannerConfig_case_sensitive) shr
@ -4077,7 +4079,7 @@ when false:
proc g_strstrip*(str: cstring): cstring = proc g_strstrip*(str: cstring): cstring =
result = g_strchomp(g_strchug(str)) result = g_strchomp(g_strchug(str))
proc G_TYPE_MAKE_FUNDAMENTAL*(x: int32): GType = proc G_TYPE_MAKE_FUNDAMENTAL*(x: int): GType =
result = GType(x shl G_TYPE_FUNDAMENTAL_SHIFT) result = GType(x shl G_TYPE_FUNDAMENTAL_SHIFT)
proc G_TYPE_IS_FUNDAMENTAL*(theType: GType): bool = proc G_TYPE_IS_FUNDAMENTAL*(theType: GType): bool =
@ -4202,7 +4204,7 @@ proc G_CLOSURE_NEEDS_MARSHAL*(closure: Pointer): bool =
result = cast[PGClosure](closure).marshal == nil result = cast[PGClosure](closure).marshal == nil
proc G_CLOSURE_N_NOTIFIERS*(cl: PGClosure): int32 = proc G_CLOSURE_N_NOTIFIERS*(cl: PGClosure): int32 =
result = ((meta_marshal(cl) + ((n_guards(cl)) shl 1)) + (n_fnotifiers(cl))) + result = ((meta_marshal(cl) + ((n_guards(cl)) shl 1'i32)) + (n_fnotifiers(cl))) +
(n_inotifiers(cl)) (n_inotifiers(cl))
proc G_CCLOSURE_SWAP_DATA*(cclosure: PGClosure): int32 = proc G_CCLOSURE_SWAP_DATA*(cclosure: PGClosure): int32 =

File diff suppressed because it is too large Load diff

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -1,73 +0,0 @@
# Lexer generator for Nimrod
# (c) 2008 Andreas Rumpf
# Stress testing for the macro feature
# the syntax that should be supported is:
# template numpostfix =
# '\'' & 'F'|'f'|'i'|'I' & "32"|"64"|"8"|"16"
# template edigits =
# 'e'|'E' & +digits
# tokens(
# tkIdent: +UniIdentStart & *UniIdentRest,
# tkHexNumber: '0' & ('x'|'X') & +hexDigits & ?( numpostfix ),
# tkOctNumber: '0' & ('c'|'C') & +octDigits & ?( numpostfix ),
# tkBinNumber: '0' & ('b'|'B') & +binDigits & ?( numpostfix ),
# tkIntNumber: +digits & ?( numpostfix ),
# tkFloatNumber: +digits & ('.' & +digits & ?(edigits) | edigits) & ?(numpostfix),
#
# )
# actions(
# tkIdent: lookup
# )
#
#
# match inputstream
# of +('A'..'Z' | '_' | 'a'..'z') *('A'..'Z' | '_' | 'a'..'z' | '0'..'9') :
#
# x = inputstream[pos..length]
# of '0' 'x' +('0'..'9' | 'a'..'f' | '_' | 'A'..'F') :
# y = ...
const
AsciiLetter = {'A'..'Z', 'a'..'z'}
uniLetter = AsciiLetter + {'\128'..'\255'}
digits = {'0'..'9'}
hexDigits = {'0'..'9', 'a'..'f', 'A'..'F'}
octDigits = {'0'..'7'}
binDigits = {'0'..'1'}
AsciiIdentStart = AsciiLetter + {'_'}
AsciiIdentRest = AsciiIdentStart + Digits
UniIdentStart = UniLetter + {'_'}
UniIdentRest = UniIdentStart + Digits
# --> if match(s, +AsciiIdentStart & *AsciiIdentRest):
# 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
# *? prefix is needed
# +? 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 )
macro re(n: expr): expr =
result = newCall("magic_re", x)

View file

@ -1,124 +0,0 @@
# new implementation of regular expressions
type
TRegexKind = enum
regNone,
regChar,
regSet,
regConc,
regAlt,
regStar,
regPlus,
regMN,
regNewline
TRegex = object of TObject
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")

View file

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

View file

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

View file

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

View file

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

View file

@ -1,5 +1,4 @@
# Container library for Nimrod # Container library for Nimrod
# Implemented with macros, because generics sucks in many ways
# Data structures for now: # Data structures for now:
# TTable, TSet, TList # TTable, TSet, TList

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,15 @@
#define USE_DL_PREFIX
#define USE_DL_PREFIX
#define ASSEMBLY_VERSION
/*
#define FOOTERS 1 #define FOOTERS 1
#define DEBUG 1 #define DEBUG 1
/*
#define ABORT_ON_ASSERT_FAILURE 0 #define ABORT_ON_ASSERT_FAILURE 0
*/ */
#define ABORT do { printf("abort was called\n"); abort(); } while (0) #define ABORT do { /*printf("abort was called\n");*/ abort(); } while (0)
/* /*
This is a version (aka dlmalloc) of malloc/free/realloc written by This is a version (aka dlmalloc) of malloc/free/realloc written by
@ -2210,7 +2213,7 @@ static size_t traverse_and_check(mstate m);
#define treebin_at(M,i) (&((M)->treebins[i])) #define treebin_at(M,i) (&((M)->treebins[i]))
/* assign tree index for size S to variable I */ /* assign tree index for size S to variable I */
#if defined(__GNUC__) && defined(i386) #if defined(__GNUC__) && defined(i386) && defined(ASSEMBLY_VERSION)
#define compute_tree_index(S, I)\ #define compute_tree_index(S, I)\
{\ {\
size_t X = S >> TREEBIN_SHIFT;\ size_t X = S >> TREEBIN_SHIFT;\
@ -2275,7 +2278,7 @@ static size_t traverse_and_check(mstate m);
/* index corresponding to given bit */ /* index corresponding to given bit */
#if defined(__GNUC__) && defined(i386) #if defined(__GNUC__) && defined(i386) && defined(ASSEMBLY_VERSION)
#define compute_bit2idx(X, I)\ #define compute_bit2idx(X, I)\
{\ {\
unsigned int J;\ unsigned int J;\

View file

@ -7,25 +7,14 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
#
# This file implements the ability to call native procs from libraries. # This file implements the ability to call native procs from libraries.
# It is not possible to do this in a platform independant way, unfortunately. # It is not possible to do this in a platform independant way, unfortunately.
# However, the interface has been designed to take platform differences into # However, the interface has been designed to take platform differences into
# account and been ported to all major platforms. # account and been ported to all major platforms.
#
# interface
type type
EInvalidLibrary = object of EOS 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 type
TLibHandle = pointer # private type TLibHandle = pointer # private type
TProcAddr = pointer # libary loading and loading of procs: TProcAddr = pointer # libary loading and loading of procs:
@ -37,15 +26,13 @@ proc nimLoadLibrary(path: string): TLibHandle {.compilerproc.}
proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.} proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.}
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.} proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.}
#implementation
# this code was inspired from Lua's source code: # this code was inspired from Lua's source code:
# Lua - An Extensible Extension Language # Lua - An Extensible Extension Language
# Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil # Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
# http://www.lua.org # http://www.lua.org
# mailto:info@lua.org # mailto:info@lua.org
when defined(USE_DLOPEN): when defined(posix):
# #
# ========================================================================= # =========================================================================
# This is an implementation based on the dlfcn interface. # This is an implementation based on the dlfcn interface.
@ -76,7 +63,7 @@ when defined(USE_DLOPEN):
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr = proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
result = dlsym(lib, name) result = dlsym(lib, name)
elif defined(USE_DLL): elif defined(windows) or defined(dos):
# #
# ======================================================================= # =======================================================================
# Native Windows Implementation # Native Windows Implementation
@ -96,13 +83,13 @@ elif defined(USE_DLL):
proc nimLoadLibrary(path: string): TLibHandle = proc nimLoadLibrary(path: string): TLibHandle =
result = cast[TLibHandle](winLoadLibrary(path)) result = cast[TLibHandle](winLoadLibrary(path))
if result == nil: if result == nil:
raise newException(EInvalidLibrary, "could not load: " & path) raise newException(EInvalidLibrary, "could not load: " & path)
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr = proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
result = GetProcAddress(cast[THINSTANCE](lib), name) result = GetProcAddress(cast[THINSTANCE](lib), name)
elif defined(USE_DYLD): elif defined(mac):
# #
# ======================================================================= # =======================================================================
# Native Mac OS X / Darwin Implementation # Native Mac OS X / Darwin Implementation

View file

@ -15,6 +15,7 @@ proc GC_fullCollect() = nil
proc GC_setStrategy(strategy: TGC_Strategy) = nil proc GC_setStrategy(strategy: TGC_Strategy) = nil
proc GC_enableMarkAndSweep() = nil proc GC_enableMarkAndSweep() = nil
proc GC_disableMarkAndSweep() = nil proc GC_disableMarkAndSweep() = nil
proc GC_getStatistics(): string = return ""
proc getOccupiedMem(): int = return -1 proc getOccupiedMem(): int = return -1
proc getFreeMem(): int = return -1 proc getFreeMem(): int = return -1

View file

@ -171,8 +171,7 @@ var
proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} = proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
# print stack trace and quit # print stack trace and quit
var var s = sig
s = int(sig)
GC_disable() GC_disable()
setLen(buf, 0) setLen(buf, 0)
rawWriteStackTrace(buf) rawWriteStackTrace(buf)
@ -199,7 +198,8 @@ proc registerSignalHandler() =
c_signal(SIGILL, signalHandler) c_signal(SIGILL, signalHandler)
c_signal(SIGBUS, signalHandler) c_signal(SIGBUS, signalHandler)
registerSignalHandler() # call it in initialization section when not defined(noSignalHandler):
registerSignalHandler() # call it in initialization section
# for easier debugging of the GC, this memory is only allocated after the # for easier debugging of the GC, this memory is only allocated after the
# signal handlers have been registered # signal handlers have been registered
new(gAssertionFailed) new(gAssertionFailed)
@ -256,3 +256,12 @@ proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} = proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
if a != b: if a != b:
raise newException(EInvalidObjectAssignment, "invalid object assignment") raise newException(EInvalidObjectAssignment, "invalid object assignment")
proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
# checks if obj is of type subclass:
var x = obj
if x == subclass: return true # optimized fast path
while x != subclass:
if x == nil: return false
x = x.base
return true

1154
lib/gc.nim

File diff suppressed because it is too large Load diff

View file

@ -104,8 +104,7 @@ const
growthFactor = 2 # must be power of two growthFactor = 2 # must be power of two
proc init*[TKey, TValue](t: var TTable[TKey, TValue], capacity: natural = 32) = proc init*[TKey, TValue](t: var TTable[TKey, TValue], capacity: natural = 32) =
t.d = [] # XXX newSeq(t.d, capacity)
setLen(t.d, capacity)
proc len*[TKey, TValue](t: TTable[TKey, TValue]): natural = return t.counter proc len*[TKey, TValue](t: TTable[TKey, TValue]): natural = return t.counter
@ -136,8 +135,8 @@ proc TableRawInsert[TKey, TValue](data: var seq[TPair[TKey, TValue]],
data[h].val = val data[h].val = val
proc TableEnlarge[TKey, TValue](t: var TTable[TKey, TValue]) = proc TableEnlarge[TKey, TValue](t: var TTable[TKey, TValue]) =
var n: seq[TPair[TKey,TValue]] = [] var n: seq[TPair[TKey,TValue]]
setLen(n, len(t.d) * growthFactor) # XXX newSeq(n, len(t.d) * growthFactor)
for i in 0..high(t.d): for i in 0..high(t.d):
if not isNil(t.d[i].key): if not isNil(t.d[i].key):
TableRawInsert(n, t.d[i].key, t.d[i].val) TableRawInsert(n, t.d[i].key, t.d[i].val)

View file

@ -1,97 +1,97 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf # (c) Copyright 2008 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## This module implements efficient computations of hash values for diverse ## This module implements efficient computations of hash values for diverse
## Nimrod types. ## Nimrod types.
import import
strutils strutils
type type
THash* = int ## a hash value; hash tables using these values should THash* = int ## a hash value; hash tables using these values should
## always have a size of a power of two and can use the ``and`` ## always have a size of a power of two and can use the ``and``
## operator instead of ``mod`` for truncation of the hash value. ## operator instead of ``mod`` for truncation of the hash value.
proc concHash(h: THash, val: int): THash {.inline.} = proc concHash(h: THash, val: int): THash {.inline.} =
result = h +% val result = h +% val
result = result +% result shl 10 result = result +% result shl 10
result = result xor (result shr 6) result = result xor (result shr 6)
proc finishHash(h: THash): THash {.inline.} = proc finishHash(h: THash): THash {.inline.} =
result = h +% h shl 3 result = h +% h shl 3
result = result xor (result shr 11) result = result xor (result shr 11)
result = result +% result shl 15 result = result +% result shl 15
proc hashData*(Data: Pointer, Size: int): THash = proc hashData*(Data: Pointer, Size: int): THash =
## hashes an array of bytes of size `size` ## hashes an array of bytes of size `size`
var var
h: THash h: THash
p: cstring p: cstring
i, s: int i, s: int
h = 0 h = 0
p = cast[cstring](Data) p = cast[cstring](Data)
i = 0 i = 0
s = size s = size
while s > 0: while s > 0:
h = concHash(h, ord(p[i])) h = concHash(h, ord(p[i]))
Inc(i) Inc(i)
Dec(s) Dec(s)
result = finishHash(h) result = finishHash(h)
proc hash*(x: Pointer): THash {.inline.} = proc hash*(x: Pointer): THash {.inline.} =
## efficient hashing of pointers ## efficient hashing of pointers
result = (cast[THash](x)) shr 3 # skip the alignment result = (cast[THash](x)) shr 3 # skip the alignment
proc hash*(x: int): THash {.inline.} = proc hash*(x: int): THash {.inline.} =
## efficient hashing of integers ## efficient hashing of integers
result = x result = x
proc hash*(x: int64): THash {.inline.} = proc hash*(x: int64): THash {.inline.} =
## efficient hashing of integers ## efficient hashing of integers
result = toU32(x) result = toU32(x)
proc hash*(x: char): THash {.inline.} = proc hash*(x: char): THash {.inline.} =
## efficient hashing of characters ## efficient hashing of characters
result = ord(x) result = ord(x)
proc hash*(x: string): THash = proc hash*(x: string): THash =
## efficient hashing of strings ## efficient hashing of strings
var h: THash var h: THash
h = 0 h = 0
for i in 0..x.len-1: for i in 0..x.len-1:
h = concHash(h, ord(x[i])) h = concHash(h, ord(x[i]))
result = finishHash(h) result = finishHash(h)
proc hashIgnoreStyle*(x: string): THash = proc hashIgnoreStyle*(x: string): THash =
## efficient hashing of strings; style is ignored ## efficient hashing of strings; style is ignored
var var
h: THash h: THash
c: Char c: Char
h = 0 h = 0
for i in 0..x.len-1: for i in 0..x.len-1:
c = x[i] c = x[i]
if c == '_': if c == '_':
continue # skip _ continue # skip _
if c in {'A'..'Z'}: if c in {'A'..'Z'}:
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower() c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
h = concHash(h, ord(c)) h = concHash(h, ord(c))
result = finishHash(h) result = finishHash(h)
proc hashIgnoreCase*(x: string): THash = proc hashIgnoreCase*(x: string): THash =
## efficient hashing of strings; case is ignored ## efficient hashing of strings; case is ignored
var var
h: THash h: THash
c: Char c: Char
h = 0 h = 0
for i in 0..x.len-1: for i in 0..x.len-1:
c = x[i] c = x[i]
if c in {'A'..'Z'}: if c in {'A'..'Z'}:
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower() c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
h = concHash(h, ord(c)) h = concHash(h, ord(c))
result = finishHash(h) result = finishHash(h)

View file

@ -13,7 +13,7 @@ type # This should be he same as ast.TTypeKind
tyNone, # 0 tyNone, # 0
tyBool, # 1 tyBool, # 1
tyChar, # 2 tyChar, # 2
tyEmptySet, # 3 tyEmpty, # 3
tyArrayConstr, # 4 tyArrayConstr, # 4
tyNil, # 5 tyNil, # 5
tyGeneric, # 6 tyGeneric, # 6
@ -49,9 +49,13 @@ type # This should be he same as ast.TTypeKind
len: int len: int
sons: ptr array [0..0x7fff, ptr TNimNode] sons: ptr array [0..0x7fff, ptr TNimNode]
TNimTypeFlag = enum
ntfNoRefs = 0, # type contains no tyRef, tySequence, tyString
ntfAcyclic = 1 # type cannot form a cycle
TNimType {.compilerproc, final.} = object TNimType {.compilerproc, final.} = object
size: int size: int
kind: TNimKind kind: TNimKind
flags: set[TNimTypeFlag]
base: ptr TNimType base: ptr TNimType
node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum
finalizer: pointer # the finalizer for the type finalizer: pointer # the finalizer for the type

View file

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

View file

@ -1,186 +1,167 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2008 Andreas Rumpf # (c) Copyright 2008 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## This module implements a base object of a lexer with efficient buffer ## This module implements a base object of a lexer with efficient buffer
## handling. In fact I believe that this is the most efficient method of ## handling. Only at line endings checks are necessary if the buffer
## buffer handling that exists! Only at line endings checks are necessary ## needs refilling.
## if the buffer needs refilling.
import
import strutils, streams
strutils
const
const EndOfFile* = '\0' ## end of file marker
EndOfFile* = '\0' ## end of file marker NewLines* = {'\c', '\L'}
# A little picture makes everything clear :-)
# buf: # Buffer handling:
# "Example Text\n ha!" bufLen = 17 # buf:
# ^pos = 0 ^ sentinel = 12 # "Example Text\n ha!" bufLen = 17
# # ^pos = 0 ^ sentinel = 12
NewLines* = {'\c', '\L'} #
type type
TBaseLexer* = object of TObject ## the base lexer. Inherit your lexer from TBaseLexer* = object of TObject ## the base lexer. Inherit your lexer from
## this object. ## this object.
bufpos*: int ## the current position within the buffer bufpos*: int ## the current position within the buffer
buf*: cstring ## the buffer itself buf*: cstring ## the buffer itself
bufLen*: int ## length of buffer in characters bufLen*: int ## length of buffer in characters
f*: tfile ## the file that is read input: PStream ## the input stream
LineNumber*: int ## the current line number LineNumber*: int ## the current line number
sentinel: int sentinel: int
lineStart: int # index of last line start in buffer lineStart: int # index of last line start in buffer
fileOpened: bool fileOpened: bool
proc initBaseLexer*(L: var TBaseLexer, filename: string, bufLen: int = 8192): bool proc open*(L: var TBaseLexer, input: PStream, bufLen: int = 8192)
## inits the TBaseLexer object with a file to scan ## inits the TBaseLexer with a stream to read from
proc initBaseLexerFromBuffer*(L: var TBaseLexer, buffer: string) proc close*(L: var TBaseLexer)
## inits the TBaseLexer with a buffer to scan ## closes the base lexer. This closes `L`'s associated stream too.
proc deinitBaseLexer*(L: var TBaseLexer) proc getCurrentLine*(L: TBaseLexer, marker: bool = true): string
## deinitializes the base lexer. This needs to be called to close the file. ## retrieves the current line.
proc getCurrentLine*(L: TBaseLexer, marker: bool = true): string proc getColNumber*(L: TBaseLexer, pos: int): int
## retrieves the current line. ## retrieves the current column.
proc getColNumber*(L: TBaseLexer, pos: int): int proc HandleCR*(L: var TBaseLexer, pos: int): int
## retrieves the current column. ## Call this if you scanned over '\c' in the buffer; it returns the the
## position to continue the scanning from. `pos` must be the position
proc HandleCR*(L: var TBaseLexer, pos: int): int ## of the '\c'.
## Call this if you scanned over '\c' in the buffer; it returns the the proc HandleLF*(L: var TBaseLexer, pos: int): int
## position to continue the scanning from. `pos` must be the position ## Call this if you scanned over '\L' in the buffer; it returns the the
## of the '\c'. ## position to continue the scanning from. `pos` must be the position
proc HandleLF*(L: var TBaseLexer, pos: int): int ## of the '\L'.
## Call this if you scanned over '\L' in the buffer; it returns the the
## position to continue the scanning from. `pos` must be the position # implementation
## of the '\L'.
const
# implementation chrSize = sizeof(char)
const proc close(L: var TBaseLexer) =
chrSize = sizeof(char) dealloc(L.buf)
L.input.close(L.input)
proc deinitBaseLexer(L: var TBaseLexer) =
dealloc(L.buf) proc FillBuffer(L: var TBaseLexer) =
if L.fileOpened: closeFile(L.f) var
charsRead, toCopy, s: int # all are in characters,
proc FillBuffer(L: var TBaseLexer) = # not bytes (in case this
var # is not the same)
charsRead, toCopy, s: int # all are in characters, oldBufLen: int
# not bytes (in case this # we know here that pos == L.sentinel, but not if this proc
# is not the same) # is called the first time by initBaseLexer()
oldBufLen: int assert(L.sentinel < L.bufLen)
# we know here that pos == L.sentinel, but not if this proc toCopy = L.BufLen - L.sentinel - 1
# is called the first time by initBaseLexer() assert(toCopy >= 0)
assert(L.sentinel < L.bufLen) if toCopy > 0:
toCopy = L.BufLen - L.sentinel - 1 MoveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize) # "moveMem" handles overlapping regions
assert(toCopy >= 0) charsRead = L.input.readData(L.input, addr(L.buf[toCopy]),
if toCopy > 0: (L.sentinel + 1) * chrSize) div chrSize
MoveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize) # "moveMem" handles overlapping regions s = toCopy + charsRead
charsRead = ReadBuffer(L.f, addr(L.buf[toCopy]), (L.sentinel + 1) * chrSize) div if charsRead < L.sentinel + 1:
chrSize L.buf[s] = EndOfFile # set end marker
s = toCopy + charsRead L.sentinel = s
if charsRead < L.sentinel + 1: else:
L.buf[s] = EndOfFile # set end marker # compute sentinel:
L.sentinel = s dec(s) # BUGFIX (valgrind)
else: while true:
# compute sentinel: assert(s < L.bufLen)
dec(s) # BUGFIX (valgrind) while (s >= 0) and not (L.buf[s] in NewLines): Dec(s)
while true: if s >= 0:
assert(s < L.bufLen) # we found an appropriate character for a sentinel:
while (s >= 0) and not (L.buf[s] in NewLines): Dec(s) L.sentinel = s
if s >= 0: break
# we found an appropriate character for a sentinel: else:
L.sentinel = s # rather than to give up here because the line is too long,
break # double the buffer's size and try again:
else: oldBufLen = L.BufLen
# rather than to give up here because the line is too long, L.bufLen = L.BufLen * 2
# double the buffer's size and try again: L.buf = cast[cstring](realloc(L.buf, L.bufLen * chrSize))
oldBufLen = L.BufLen assert(L.bufLen - oldBuflen == oldBufLen)
L.bufLen = L.BufLen * 2 charsRead = L.input.ReadData(L.input, addr(L.buf[oldBufLen]),
L.buf = cast[cstring](realloc(L.buf, L.bufLen * chrSize)) oldBufLen * chrSize) div chrSize
assert(L.bufLen - oldBuflen == oldBufLen) if charsRead < oldBufLen:
charsRead = ReadBuffer(L.f, addr(L.buf[oldBufLen]), oldBufLen * chrSize) div L.buf[oldBufLen + charsRead] = EndOfFile
chrSize L.sentinel = oldBufLen + charsRead
if charsRead < oldBufLen: break
L.buf[oldBufLen + charsRead] = EndOfFile s = L.bufLen - 1
L.sentinel = oldBufLen + charsRead
break proc fillBaseLexer(L: var TBaseLexer, pos: int): int =
s = L.bufLen - 1 assert(pos <= L.sentinel)
if pos < L.sentinel:
proc fillBaseLexer(L: var TBaseLexer, pos: int): int = result = pos + 1 # nothing to do
assert(pos <= L.sentinel) else:
if pos < L.sentinel: fillBuffer(L)
result = pos + 1 # nothing to do L.bufpos = 0 # XXX: is this really correct?
else: result = 0
fillBuffer(L) L.lineStart = result
L.bufpos = 0 # XXX: is this really correct?
result = 0 proc HandleCR(L: var TBaseLexer, pos: int): int =
L.lineStart = result assert(L.buf[pos] == '\c')
inc(L.linenumber)
proc HandleCR(L: var TBaseLexer, pos: int): int = result = fillBaseLexer(L, pos)
assert(L.buf[pos] == '\c') if L.buf[result] == '\L':
inc(L.linenumber) result = fillBaseLexer(L, result)
result = fillBaseLexer(L, pos)
if L.buf[result] == '\L': proc HandleLF(L: var TBaseLexer, pos: int): int =
result = fillBaseLexer(L, result) assert(L.buf[pos] == '\L')
inc(L.linenumber)
proc HandleLF(L: var TBaseLexer, pos: int): int = result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result;
assert(L.buf[pos] == '\L')
inc(L.linenumber) proc skip_UTF_8_BOM(L: var TBaseLexer) =
result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result; if (L.buf[0] == '\xEF') and (L.buf[1] == '\xBB') and (L.buf[2] == '\xBF'):
inc(L.bufpos, 3)
proc skip_UTF_8_BOM(L: var TBaseLexer) = inc(L.lineStart, 3)
if (L.buf[0] == '\xEF') and (L.buf[1] == '\xBB') and (L.buf[2] == '\xBF'):
inc(L.bufpos, 3) proc open(L: var TBaseLexer, input: PStream, bufLen: int = 8192) =
inc(L.lineStart, 3) assert(bufLen > 0)
assert(input != nil)
proc initBaseLexer(L: var TBaseLexer, filename: string, bufLen: int = 8192): bool = L.input = input
assert(bufLen > 0) L.bufpos = 0
L.bufpos = 0 L.bufLen = bufLen
L.bufLen = bufLen L.buf = cast[cstring](alloc(bufLen * chrSize))
L.buf = cast[cstring](alloc(bufLen * chrSize)) L.sentinel = bufLen - 1
L.sentinel = bufLen - 1 L.lineStart = 0
L.lineStart = 0 L.linenumber = 1 # lines start at 1
L.linenumber = 1 # lines start at 1 fillBuffer(L)
L.fileOpened = openFile(L.f, filename) skip_UTF_8_BOM(L)
result = L.fileOpened
if result: proc getColNumber(L: TBaseLexer, pos: int): int =
fillBuffer(L) result = pos - L.lineStart
skip_UTF_8_BOM(L) assert(result >= 0)
proc initBaseLexerFromBuffer(L: var TBaseLexer, buffer: string) = proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
L.bufpos = 0 var i: int
L.bufLen = len(buffer) + 1 result = ""
L.buf = cast[cstring](alloc(L.bufLen * chrSize)) i = L.lineStart
L.sentinel = L.bufLen - 1 while not (L.buf[i] in {'\c', '\L', EndOfFile}):
L.lineStart = 0 add(result, L.buf[i])
L.linenumber = 1 # lines start at 1 inc(i)
L.fileOpened = false add(result, "\n")
if L.bufLen > 0: if marker:
copyMem(L.buf, cast[pointer](buffer), L.bufLen) add(result, RepeatChar(getColNumber(L, L.bufpos)) & "^\n")
L.buf[L.bufLen - 1] = EndOfFile
else:
L.buf[0] = EndOfFile
skip_UTF_8_BOM(L)
proc getColNumber(L: TBaseLexer, pos: int): int =
result = pos - L.lineStart
assert(result >= 0)
proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
var i: int
result = ""
i = L.lineStart
while not (L.buf[i] in {'\c', '\L', EndOfFile}):
add(result, L.buf[i])
inc(i)
add(result, "\n")
if marker:
add(result, RepeatChar(getColNumber(L, L.bufpos)) & "^\n")

View file

@ -1,176 +1,175 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf # (c) Copyright 2008 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
## This module contains the interface to the compiler's abstract syntax tree. ## This module contains the interface to the compiler's abstract syntax tree.
## Abstract syntax trees should be modified in macros. ## Abstract syntax trees should be modified in macros.
#[[[cog #[[[cog
#def toEnum(name, elems, prefix): #def toEnum(name, elems):
# body = "" # body = ""
# counter = 0 # counter = 0
# for e in elems: # for e in elems:
# if counter % 4 == 0: p = "\n " # if counter % 4 == 0: p = "\n "
# else: p = "" # else: p = ""
# body += p + prefix + e[2:] + ', ' # body = body + p + 'n' + e + ', '
# counter += 1 # counter = counter + 1
# #
# return " TNimrod%s* = enum%s\n TNim%ss* = set[TNimrod%s]\n" \ # return (" TNimrod%s* = enum%s\n TNim%ss* = set[TNimrod%s]\n" %
# % (name, body.rstrip(", "), name, name) # (name, body[:-2], name, name))
# #
#enums = eval(file("data/ast.yml").read()) #enums = eval(open("data/ast.yml").read())
#cog.out("type\n") #cog.out("type\n")
#i = 0 #for key, val in enums.items():
#for key, val in enums.iteritems(): # if key[-4:] == "Flag": continue
# if key.endswith("Flag"): continue # cog.out(toEnum(key, val))
# cog.out(toEnum(key, val, ["nnk", "nty", "nsk"][i])) #]]]
# i += 1 type
#]]] TNimrodTypeKind* = enum
type ntyNone, ntyBool, ntyChar, ntyEmpty,
TNimrodNodeKind* = enum ntyArrayConstr, ntyNil, ntyGeneric, ntyGenericInst,
nnkNone, nnkEmpty, nnkIdent, nnkSym, ntyGenericParam, ntyEnum, ntyAnyEnum, ntyArray,
nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit, ntyObject, ntyTuple, ntySet, ntyRange,
nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit, ntyPtr, ntyRef, ntyVar, ntySequence,
nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit, ntyProc, ntyPointer, ntyOpenArray, ntyString,
nnkTripleStrLit, nnkMetaNode, nnkNilLit, nnkDotCall, ntyCString, ntyForward, ntyInt, ntyInt8,
nnkCommand, nnkCall, nnkGenericCall, nnkExplicitTypeListCall, ntyInt16, ntyInt32, ntyInt64, ntyFloat,
nnkExprEqExpr, nnkExprColonExpr, nnkIdentDefs, nnkInfix, ntyFloat32, ntyFloat64, ntyFloat128
nnkPrefix, nnkPostfix, nnkPar, nnkCurly, TNimTypeKinds* = set[TNimrodTypeKind]
nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange, TNimrodSymKind* = enum
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr, nskUnknownSym, nskConditional, nskDynLib, nskParam,
nnkElifExpr, nnkElseExpr, nnkLambda, nnkAccQuoted, nskTypeParam, nskTemp, nskType, nskConst,
nnkHeaderQuoted, nnkTableConstr, nnkQualified, nnkHiddenStdConv, nskVar, nskProc, nskIterator, nskConverter,
nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast, nskMacro, nskTemplate, nskField, nskEnumField,
nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv, nskForVar, nskModule, nskLabel, nskStub
nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange, TNimSymKinds* = set[TNimrodSymKind]
nnkStringToCString, nnkCStringToString, nnkPassAsOpenArray, nnkAsgn, TNimrodNodeKind* = enum
nnkDefaultTypeParam, nnkGenericParams, nnkFormalParams, nnkOfInherit, nnkNone, nnkEmpty, nnkIdent, nnkSym,
nnkModule, nnkProcDef, nnkConverterDef, nnkMacroDef, nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit,
nnkTemplateDef, nnkIteratorDef, nnkOfBranch, nnkElifBranch, nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit,
nnkExceptBranch, nnkElse, nnkMacroStmt, nnkAsmStmt, nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit,
nnkPragma, nnkIfStmt, nnkWhenStmt, nnkForStmt, nnkTripleStrLit, nnkMetaNode, nnkNilLit, nnkDotCall,
nnkWhileStmt, nnkCaseStmt, nnkVarSection, nnkConstSection, nnkCommand, nnkCall, nnkGenericCall, nnkExplicitTypeListCall,
nnkConstDef, nnkTypeSection, nnkTypeDef, nnkYieldStmt, nnkExprEqExpr, nnkExprColonExpr, nnkIdentDefs, nnkInfix,
nnkTryStmt, nnkFinally, nnkRaiseStmt, nnkReturnStmt, nnkPrefix, nnkPostfix, nnkPar, nnkCurly,
nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkDiscardStmt, nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
nnkStmtList, nnkImportStmt, nnkFromStmt, nnkImportAs, nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
nnkIncludeStmt, nnkAccessStmt, nnkCommentStmt, nnkStmtListExpr, nnkElifExpr, nnkElseExpr, nnkLambda, nnkAccQuoted,
nnkBlockExpr, nnkVm, nnkTypeOfExpr, nnkObjectTy, nnkHeaderQuoted, nnkTableConstr, nnkQualified, nnkHiddenStdConv,
nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen, nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast,
nnkRefTy, nnkPtrTy, nnkVarTy, nnkProcTy, nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv,
nnkEnumTy, nnkEnumFieldDef, nnkReturnToken nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange,
TNimNodeKinds* = set[TNimrodNodeKind] nnkStringToCString, nnkCStringToString, nnkPassAsOpenArray, nnkAsgn,
TNimrodTypeKind* = enum nnkDefaultTypeParam, nnkGenericParams, nnkFormalParams, nnkOfInherit,
ntyNone, ntyBool, ntyChar, ntyEmptySet, nnkModule, nnkProcDef, nnkConverterDef, nnkMacroDef,
ntyArrayConstr, ntyNil, ntyGeneric, ntyGenericInst, nnkTemplateDef, nnkIteratorDef, nnkOfBranch, nnkElifBranch,
ntyGenericParam, ntyEnum, ntyAnyEnum, ntyArray, nnkExceptBranch, nnkElse, nnkMacroStmt, nnkAsmStmt,
ntyObject, ntyTuple, ntySet, ntyRange, nnkPragma, nnkIfStmt, nnkWhenStmt, nnkForStmt,
ntyPtr, ntyRef, ntyVar, ntySequence, nnkWhileStmt, nnkCaseStmt, nnkVarSection, nnkConstSection,
ntyProc, ntyPointer, ntyOpenArray, ntyString, nnkConstDef, nnkTypeSection, nnkTypeDef, nnkYieldStmt,
ntyCString, ntyForward, ntyInt, ntyInt8, nnkTryStmt, nnkFinally, nnkRaiseStmt, nnkReturnStmt,
ntyInt16, ntyInt32, ntyInt64, ntyFloat, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkDiscardStmt,
ntyFloat32, ntyFloat64, ntyFloat128 nnkStmtList, nnkImportStmt, nnkFromStmt, nnkImportAs,
TNimTypeKinds* = set[TNimrodTypeKind] nnkIncludeStmt, nnkAccessStmt, nnkCommentStmt, nnkStmtListExpr,
TNimrodSymKind* = enum nnkBlockExpr, nnkStmtListType, nnkBlockType, nnkVm,
nskUnknownSym, nskConditional, nskDynLib, nskParam, nnkTypeOfExpr, nnkObjectTy, nnkTupleTy, nnkRecList,
nskTypeParam, nskTemp, nskType, nskConst, nnkRecCase, nnkRecWhen, nnkRefTy, nnkPtrTy,
nskVar, nskProc, nskIterator, nskConverter, nnkVarTy, nnkProcTy, nnkEnumTy, nnkEnumFieldDef,
nskMacro, nskTemplate, nskField, nskEnumField, nnkReturnToken
nskForVar, nskModule, nskLabel TNimNodeKinds* = set[TNimrodNodeKind]
TNimSymKinds* = set[TNimrodSymKind] #[[[end]]]
#[[[end]]]
type
type TNimrodNode {.final.} = object # hidden
TNimrodNode {.final.} = object # hidden TNimrodSymbol {.final.} = object # hidden
TNimrodSymbol {.final.} = object # hidden TNimrodType {.final.} = object # hidden
TNimrodType {.final.} = object # hidden PNimrodType* {.compilerproc.} = ref TNimrodType
PNimrodType* {.compilerproc.} = ref TNimrodType PNimrodSymbol* {.compilerproc.} = ref TNimrodSymbol
PNimrodSymbol* {.compilerproc.} = ref TNimrodSymbol PNimrodNode* {.compilerproc.} = ref TNimrodNode
PNimrodNode* {.compilerproc.} = ref TNimrodNode expr* = PNimrodNode
expr* = PNimrodNode stmt* = PNimrodNode
stmt* = PNimrodNode
# Nodes should be reference counted to make the `copy` operation very fast!
# Nodes should be reference counted to make the `copy` operation very fast! # However, this is difficult to achieve: modify(n[0][1]) should propagate to
# However, this is difficult to achieve: modify(n[0][1]) should propagate to # its father. How to do this without back references?
# its father. How to do this without back references?
proc `[]`* (n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".}
proc `[]`* (n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".} proc `[]=`* (n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".}
proc `[]=`* (n: PNimrodNode, i: int, child: PNimrodNode) {.magic: "NSetChild".} ## provide access to `n`'s children
## provide access to `n`'s children
type
type TNimrodIdent = object of TObject
TNimrodIdent = object of TObject
converter StrToIdent*(s: string): TNimrodIdent {.magic: "StrToIdent".}
converter StrToIdent*(s: string): TNimrodIdent {.magic: "StrToIdent".} proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}
proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".} proc `==`* (a, b: TNimrodIdent): bool {.magic: "EqIdent".}
proc `==`* (a, b: TNimrodIdent): bool {.magic: "EqIdent".}
proc len*(n: PNimrodNode): int {.magic: "NLen".}
proc len*(n: PNimrodNode): int {.magic: "NLen".}
## returns the number of children that a node has
## returns the number of children that a node has proc add*(father, child: PNimrodNode) {.magic: "NAdd".}
proc add*(father, child: PNimrodNode) {.magic: "NAdd".} proc add*(father: PNimrodNode, child: openArray[PNimrodNode]) {.magic: "NAddMultiple".}
proc add*(father: PNimrodNode, child: openArray[PNimrodNode]) {.magic: "NAddMultiple".} proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel".}
proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel".} proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind".}
proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind".}
proc intVal*(n: PNimrodNode): biggestInt {.magic: "NIntVal".}
proc intVal*(n: PNimrodNode): biggestInt {.magic: "NIntVal".} proc floatVal*(n: PNimrodNode): biggestFloat {.magic: "NFloatVal".}
proc floatVal*(n: PNimrodNode): biggestFloat {.magic: "NFloatVal".} proc symbol*(n: PNimrodNode): PNimrodSymbol {.magic: "NSymbol".}
proc symbol*(n: PNimrodNode): PNimrodSymbol {.magic: "NSymbol".} proc ident*(n: PNimrodNode): TNimrodIdent {.magic: "NIdent".}
proc ident*(n: PNimrodNode): TNimrodIdent {.magic: "NIdent".} proc typ*(n: PNimrodNode): PNimrodType {.magic: "NGetType".}
proc typ*(n: PNimrodNode): PNimrodType {.magic: "NGetType".} proc strVal*(n: PNimrodNode): string {.magic: "NStrVal".}
proc strVal*(n: PNimrodNode): string {.magic: "NStrVal".}
proc `intVal=`*(n: PNimrodNode, val: biggestInt) {.magic: "NSetIntVal".}
proc `intVal=`*(n: PNimrodNode, val: biggestInt) {.magic: "NSetIntVal".} proc `floatVal=`*(n: PNimrodNode, val: biggestFloat) {.magic: "NSetFloatVal".}
proc `floatVal=`*(n: PNimrodNode, val: biggestFloat) {.magic: "NSetFloatVal".} proc `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol".}
proc `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol".} proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent".}
proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent".} proc `typ=`*(n: PNimrodNode, typ: PNimrodType) {.magic: "NSetType".}
proc `typ=`*(n: PNimrodNode, typ: PNimrodType) {.magic: "NSetType".} proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".}
proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".}
proc newNimNode*(kind: TNimrodNodeKind,
proc newNimNode*(kind: TNimrodNodeKind, n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".}
n: PNimrodNode=nil): PNimrodNode {.magic: "NNewNimNode".} proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode".}
proc copyNimNode*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimNode".} proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree".}
proc copyNimTree*(n: PNimrodNode): PNimrodNode {.magic: "NCopyNimTree".}
proc error*(msg: string) {.magic: "NError".}
proc error*(msg: string) {.magic: "NError".} proc warning*(msg: string) {.magic: "NWarning".}
proc warning*(msg: string) {.magic: "NWarning".} proc hint*(msg: string) {.magic: "NHint".}
proc hint*(msg: string) {.magic: "NHint".}
proc newStrLitNode*(s: string): PNimrodNode {.compileTime.} =
proc newStrLitNode*(s: string): PNimrodNode {.nodecl.} = result = newNimNode(nnkStrLit)
result = newNimNode(nnkStrLit) result.strVal = s
result.strVal = s
proc newIntLitNode*(i: biggestInt): PNimrodNode {.compileTime.} =
proc newIntLitNode*(i: biggestInt): PNimrodNode {.nodecl.} = result = newNimNode(nnkIntLit)
result = newNimNode(nnkIntLit) result.intVal = i
result.intVal = i
proc newIntLitNode*(f: biggestFloat): PNimrodNode {.compileTime.} =
proc newIntLitNode*(f: biggestFloat): PNimrodNode {.nodecl.} = result = newNimNode(nnkFloatLit)
result = newNimNode(nnkFloatLit) result.floatVal = f
result.floatVal = f
proc newIdentNode*(i: TNimrodIdent): PNimrodNode {.compileTime.} =
proc newIdentNode*(i: TNimrodIdent): PNimrodNode {.nodecl.} = result = newNimNode(nnkIdent)
result = newNimNode(nnkIdent) result.ident = i
result.ident = i
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
proc toStrLit*(n: PNimrodNode): PNimrodNode {.nodecl.} = return newStrLitNode(repr(n))
return newStrLitNode(repr(n))
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.nodecl.} = if n.kind != k: error("macro expects a node of kind: " & repr(k))
if n.kind != k: error("macro expects a node of kind: " & repr(k))
proc expectMinLen*(n: PNimrodNode, min: int) {.compileTime.} =
proc expectMinLen*(n: PNimrodNode, min: int) {.nodecl.} = if n.len < min: error("macro expects a node with " & $min & " children")
if n.len < min: error("macro expects a node with " & $min & " children")
proc newCall*(theProc: TNimrodIdent,
proc newCall*(theProc: TNimrodIdent, args: openArray[PNimrodNode]): PNimrodNode {.compileTime.} =
args: openArray[PNimrodNode]): PNimrodNode {.nodecl.} = ## produces a new call node. `theProc` is the proc that is called with
## produces a new call node. `theProc` is the proc that is called with ## the arguments ``args[0..]``.
## the arguments ``args[0..]``. result = newNimNode(nnkCall)
result = newNimNode(nnkCall) result.add(newIdentNode(theProc))
result.add(newIdentNode(theProc)) result.add(args)
result.add(args)

View file

@ -18,6 +18,10 @@
when defined(Posix): when defined(Posix):
{.passl: "-lm".} {.passl: "-lm".}
const
PI* = 3.1415926535897932384626433 ## the circle constant PI (Ludolph's number)
E* = 2.71828182845904523536028747 ## Euler's number
type type
TFloatClass* = enum ## describes the class a floating point value belongs to. TFloatClass* = enum ## describes the class a floating point value belongs to.
## This is the type that is returned by `classify`. ## This is the type that is returned by `classify`.
@ -35,7 +39,7 @@ proc classify*(x: float): TFloatClass =
# ECMAScript and most C compilers have no classify: # ECMAScript and most C compilers have no classify:
if x == 0.0: if x == 0.0:
if 1.0/x == 1.0/0.0: if 1.0/x == Inf:
return fcZero return fcZero
else: else:
return fcNegZero return fcNegZero
@ -129,7 +133,7 @@ when not defined(ECMAScript):
proc rand(): cint {.importc: "rand", nodecl.} proc rand(): cint {.importc: "rand", nodecl.}
proc randomize() = srand(gettime(nil)) proc randomize() = srand(gettime(nil))
proc random(max: int): int = return rand() mod max proc random(max: int): int = return int(rand()) mod max
else: else:
proc mathrandom(): float {.importc: "Math.random", nodecl.} proc mathrandom(): float {.importc: "Math.random", nodecl.}

View file

@ -164,7 +164,7 @@ else:
# the fact that the OS is likely to give us pages with contingous numbers. # the fact that the OS is likely to give us pages with contingous numbers.
# A page contains either small fixed size objects of the same size or # A page contains either small fixed size objects of the same size or
# variable length objects. An object's size is always aligned at 16 byte # variable length objects. An object's size is always aligned at 16 byte
# boundry. Huge objects are dealt with the TLSF algorithm. # boundary. Huge objects are dealt with the TLSF algorithm.
# The design supports iterating over any object in a fast way. # The design supports iterating over any object in a fast way.
# A bitset contains any page that starts an allocated page. The page may be # A bitset contains any page that starts an allocated page. The page may be
@ -230,6 +230,7 @@ type
zct: TCellArray zct: TCellArray
stackCells: TCellArray stackCells: TCellArray
smallBlocks: array [PageSize div MemAlign, ptr TPageDesc] smallBlocks: array [PageSize div MemAlign, ptr TPageDesc]
freeLists: array [PageSize div MemAlign, ptr TFreeList]
pages: TPageManager pages: TPageManager
usedPages: TPageList usedPages: TPageList
freePages: TPageList freePages: TPageList
@ -237,6 +238,11 @@ type
# small blocks: # small blocks:
proc allocSmall(var h: TGcHeap, size: int): pointer = proc allocSmall(var h: TGcHeap, size: int): pointer =
var s = align(size) var s = align(size)
var f = h.freeLists[s]
if f != nil:
f.prev = f.next # remove from list
f.next.prev = f.prev
return f
var p = h.smallBlocks[s] var p = h.smallBlocks[s]
if p == nil or p.free == nil: if p == nil or p.free == nil:
p = newSmallBlock(s, p) p = newSmallBlock(s, p)

View file

@ -10,6 +10,8 @@
#ifndef NIMBASE_H #ifndef NIMBASE_H
#define NIMBASE_H #define NIMBASE_H
#include <math.h>
/* calling convention mess ----------------------------------------------- */ /* calling convention mess ----------------------------------------------- */
#if defined(__GNUC__) || defined(__LCC__) || defined(__POCC__) \ #if defined(__GNUC__) || defined(__LCC__) || defined(__POCC__) \
|| defined(__TINYC__) || defined(__TINYC__)
@ -37,12 +39,16 @@
#if defined(__POCC__) #if defined(__POCC__)
# define NIM_CONST /* PCC is really picky with const modifiers */ # define NIM_CONST /* PCC is really picky with const modifiers */
# undef _MSC_VER /* Yeah, right PCC defines _MSC_VER even if it is
not that compatible. Well done. */
#elif defined(__cplusplus) #elif defined(__cplusplus)
# define NIM_CONST /* C++ is picky with const modifiers */ # define NIM_CONST /* C++ is picky with const modifiers */
#else #else
# define NIM_CONST const # define NIM_CONST const
#endif #endif
#define NIM_THREADVAR __thread
/* --------------- how int64 constants should be declared: ----------- */ /* --------------- how int64 constants should be declared: ----------- */
#if defined(__GNUC__) || defined(__LCC__) || \ #if defined(__GNUC__) || defined(__LCC__) || \
defined(__POCC__) || defined(__DMC__) defined(__POCC__) || defined(__DMC__)
@ -51,6 +57,14 @@
# define IL64(x) x # define IL64(x) x
#endif #endif
/* ---------------- casting without correct aliasing rules ----------- */
#if defined(__GNUCC__)
# define NIM_CAST(type, ptr) (((union{type __x__;}*)(ptr))->__x__)
#else
# define NIM_CAST(type, ptr) ((type)(ptr))
#endif
/* ------------------------------------------------------------------- */ /* ------------------------------------------------------------------- */
#if defined(WIN32) || defined(_WIN32) /* only Windows has this mess... */ #if defined(WIN32) || defined(_WIN32) /* only Windows has this mess... */
@ -94,6 +108,16 @@
#define N_CLOSURE_PTR(rettype, name) rettype (*name) #define N_CLOSURE_PTR(rettype, name) rettype (*name)
#if defined(__GNUC__) || defined(__ICC__)
# define N_NOINLINE(rettype, name) rettype __attribute__((noinline)) name
#elif defined(_MSC_VER)
# define N_NOINLINE(rettype, name) __declspec(noinline) rettype name
#else
# define N_NOINLINE(rettype, name) rettype name
#endif
#define N_NOINLINE_PTR(rettype, name) rettype (*name)
#if defined(__BORLANDC__) || defined(__WATCOMC__) || \ #if defined(__BORLANDC__) || defined(__WATCOMC__) || \
defined(__POCC__) || defined(_MSC_VER) defined(__POCC__) || defined(_MSC_VER)
/* these compilers have a fastcall so use it: */ /* these compilers have a fastcall so use it: */
@ -164,13 +188,10 @@
# define _ISOC99_SOURCE 1 # define _ISOC99_SOURCE 1
# define __USE_ISOC9X 1 # define __USE_ISOC9X 1
# define __USE_ISOC99 1 # define __USE_ISOC99 1
# include <math.h>
#elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \ #elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
&& !defined(__BORLANDC__) && !defined(__POCC__) && !defined(__BORLANDC__) && !defined(__POCC__)
# include <math.h>
/* Win32 doesn't seem to have these functions. /* Win32 doesn't seem to have these functions.
** Therefore implement inline versions of these functions here. ** Therefore implement inline versions of these functions here.
*/ */
@ -194,8 +215,6 @@ static N_INLINE(long int, lrintf)(float flt) {
#else #else
# include <math.h>
# ifndef lrint # ifndef lrint
# define lrint(dbl) ((long int)(dbl)) # define lrint(dbl) ((long int)(dbl))
# endif # endif
@ -214,11 +233,6 @@ static N_INLINE(long int, lrintf)(float flt) {
#include <signal.h> #include <signal.h>
#include <setjmp.h> #include <setjmp.h>
#ifndef NAN
static unsigned long nimNaN[2]={0xffffffff, 0x7fffffff};
# define NAN (*(double*) nimNaN)
#endif
/* /*
#ifndef INF #ifndef INF
static unsigned long nimInf[2]={0xffffffff, 0x7fffffff}; static unsigned long nimInf[2]={0xffffffff, 0x7fffffff};
@ -241,8 +255,7 @@ __TINYC__
# define HAVE_STDINT_H # define HAVE_STDINT_H
#endif #endif
#if defined(__LCC__) || defined(__GNUC__) || defined(__DMC__) \ #if defined(__LCC__) || defined(__DMC__) || defined(__POCC__)
|| defined(__POCC__)
# define HAVE_STDINT_H # define HAVE_STDINT_H
#endif #endif
@ -328,14 +341,16 @@ static N_INLINE(NI32, float32ToInt32)(float val) {
return float64ToInt32((double)val); return float64ToInt32((double)val);
} }
#define float64ToInt64(x) ((NI64) (x))
#define zeroMem(a, size) memset(a, 0, size) #define zeroMem(a, size) memset(a, 0, size)
#define equalMem(a, b, size) (memcmp(a, b, size) == 0) #define equalMem(a, b, size) (memcmp(a, b, size) == 0)
#define STRING_LITERAL(name, str, length) \ #define STRING_LITERAL(name, str, length) \
static const struct { \ static const struct { \
NI len, space; \ TGenericSeq Sup; \
NIM_CHAR data[length + 1]; \ NIM_CHAR data[length + 1]; \
} name = {length, length, str} } name = {{length, length}, str}
typedef struct TStringDesc* string; typedef struct TStringDesc* string;
@ -343,7 +358,7 @@ typedef struct TStringDesc* string;
#if defined(__GNUC__) #if defined(__GNUC__)
# define SEQ_DECL_SIZE /* empty is correct! */ # define SEQ_DECL_SIZE /* empty is correct! */
#else #else
# define SEQ_DECL_SIZE 1000000 # define SEQ_DECL_SIZE 1000000
#endif #endif
#define ALLOC_0(size) calloc(1, size) #define ALLOC_0(size) calloc(1, size)
@ -352,6 +367,13 @@ typedef struct TStringDesc* string;
#define GenericSeqSize sizeof(TGenericSeq) #define GenericSeqSize sizeof(TGenericSeq)
#define paramCount() cmdCount #define paramCount() cmdCount
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__i386__)
# ifndef NAN
static unsigned long nimNaN[2]={0xffffffff, 0x7fffffff};
# define NAN (*(double*) nimNaN)
# endif
#endif
#ifndef NAN #ifndef NAN
# define NAN (0.0 / 0.0) # define NAN (0.0 / 0.0)
#endif #endif
@ -399,6 +421,7 @@ struct NimException {
}; };
#endif #endif
#if 0
typedef struct TStringDesc { typedef struct TStringDesc {
NI len; NI len;
NI space; NI space;
@ -410,5 +433,6 @@ typedef struct {
} TGenericSeq; } TGenericSeq;
typedef TGenericSeq* PGenericSeq; typedef TGenericSeq* PGenericSeq;
#endif
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,7 @@
import import
hashes, strutils, lexbase hashes, strutils, lexbase, streams
type type
TCfgEventKind* = enum ## enumation of all events that may occur when parsing TCfgEventKind* = enum ## enumation of all events that may occur when parsing
@ -37,7 +37,7 @@ type
TCfgEvent* = object of TObject ## describes a parsing event TCfgEvent* = object of TObject ## describes a parsing event
case kind*: TCfgEventKind ## the kind of the event case kind*: TCfgEventKind ## the kind of the event
of cfgEof: dummy: string of cfgEof: nil
of cfgSectionStart: of cfgSectionStart:
section*: string ## `section` contains the name of the section*: string ## `section` contains the name of the
## parsed section start (syntax: ``[section]``) ## parsed section start (syntax: ``[section]``)
@ -59,21 +59,18 @@ type
literal: string # the parsed (string) literal literal: string # the parsed (string) literal
TParserState = enum TParserState = enum
startState, commaState startState # , commaState # not yet used
TCfgParser* = object of TBaseLexer ## the parser object. TCfgParser* = object of TBaseLexer ## the parser object.
tok: TToken tok: TToken
state: TParserState state: TParserState
filename: string filename: string
proc Open*(c: var TCfgParser, filename: string): bool proc open*(c: var TCfgParser, input: PStream, filename: string)
## initializes the parser, open the file for reading and returns true if ## initializes the parser with an input stream. `Filename` is only used
## successful (the file has been found). ## for nice error messages.
proc OpenFromBuffer*(c: var TCfgParser, buf: string)
## initializes the parser with a buffer. This cannot fail.
proc close*(c: var TCfgParser) proc close*(c: var TCfgParser)
## closes the parser `c`. ## closes the parser `c` and its associated input stream.
proc next*(c: var TCfgParser): TCfgEvent proc next*(c: var TCfgParser): TCfgEvent
## retrieves the first/next event. This controls the parser. ## retrieves the first/next event. This controls the parser.
@ -87,6 +84,10 @@ proc getLine*(c: TCfgParser): int
proc getFilename*(c: TCfgParser): string proc getFilename*(c: TCfgParser): string
## get the filename of the file that the parser processes. ## get the filename of the file that the parser processes.
proc errorStr*(c: TCfgParser, msg: string): string
## returns a properly formated error message containing current line and
## column information.
# implementation # implementation
@ -94,24 +95,16 @@ const
SymChars: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF'} SymChars: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF'}
proc rawGetTok(c: var TCfgParser, tok: var TToken) proc rawGetTok(c: var TCfgParser, tok: var TToken)
proc open(c: var TCfgParser, filename: string): bool = proc open(c: var TCfgParser, input: PStream, filename: string) =
result = initBaseLexer(c, filename) lexbase.open(c, input)
c.filename = filename c.filename = filename
c.state = startState c.state = startState
c.tok.kind = tkInvalid c.tok.kind = tkInvalid
c.tok.literal = "" c.tok.literal = ""
if result: rawGetTok(c, c.tok)
proc openFromBuffer(c: var TCfgParser, buf: string) =
initBaseLexerFromBuffer(c, buf)
c.filename = "buffer"
c.state = startState
c.tok.kind = tkInvalid
c.tok.literal = ""
rawGetTok(c, c.tok) rawGetTok(c, c.tok)
proc close(c: var TCfgParser) = proc close(c: var TCfgParser) =
deinitBaseLexer(c) lexbase.close(c)
proc getColumn(c: TCfgParser): int = proc getColumn(c: TCfgParser): int =
result = getColNumber(c, c.bufPos) result = getColNumber(c, c.bufPos)
@ -285,6 +278,7 @@ proc rawGetTok(c: var TCfgParser, tok: var TToken) =
of '=': of '=':
tok.kind = tkEquals tok.kind = tkEquals
inc(c.bufpos) inc(c.bufpos)
tok.literal = "="
of '-': of '-':
inc(c.bufPos) inc(c.bufPos)
if c.buf[c.bufPos] == '-': inc(c.bufPos) if c.buf[c.bufPos] == '-': inc(c.bufPos)
@ -312,6 +306,7 @@ proc rawGetTok(c: var TCfgParser, tok: var TToken) =
getString(c, tok, false) getString(c, tok, false)
of lexbase.EndOfFile: of lexbase.EndOfFile:
tok.kind = tkEof tok.kind = tkEof
tok.literal = "[EOF]"
else: getSymbol(c, tok) else: getSymbol(c, tok)
proc errorStr(c: TCfgParser, msg: string): string = proc errorStr(c: TCfgParser, msg: string): string =

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf # (c) Copyright 2008 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -20,12 +20,16 @@
## ALL types are named the same as in the POSIX standard except that they start ## ALL types are named the same as in the POSIX standard except that they start
## with 'T' or 'P' (if they are pointers) and without the '_t' prefix to be ## with 'T' or 'P' (if they are pointers) and without the '_t' prefix to be
## consistent with Nimrod conventions. If an identifier is a Nimrod keyword ## consistent with Nimrod conventions. If an identifier is a Nimrod keyword
## the `identifier` notation is used. ## the \`identifier\` notation is used.
## ##
## This library relies on the header files of your C compiler. Thus the ## This library relies on the header files of your C compiler. Thus the
## resulting C code will just include <XYZ.h> and *not* define the ## resulting C code will just include <XYZ.h> and *not* define the
## symbols declared here. ## symbols declared here.
const
hasSpawnH = defined(linux)
hasAioH = defined(linux)
const const
C_IRUSR* = 0c000400 ## Read by owner. C_IRUSR* = 0c000400 ## Read by owner.
C_IWUSR* = 0c000200 ## Write by owner. C_IWUSR* = 0c000200 ## Write by owner.
@ -55,28 +59,19 @@ const
MM_NULLACT* = nil MM_NULLACT* = nil
MM_NULLTAG* = nil MM_NULLTAG* = nil
STDERR_FILENO = 2 ## File number of stderr; STDERR_FILENO* = 2 ## File number of stderr;
STDIN_FILENO = 0 ## File number of stdin; STDIN_FILENO* = 0 ## File number of stdin;
STDOUT_FILENO = 1 ## File number of stdout; STDOUT_FILENO* = 1 ## File number of stdout;
type type
Taiocb* {.importc: "struct aiocb", header: "<aio.h>", final.} = object TDIR* {.importc: "DIR", header: "<dirent.h>", final, pure.} = object
aio_fildes*: cint ## File descriptor.
aio_offset*: TOff ## File offset.
aio_buf*: pointer ## Location of buffer.
aio_nbytes*: int ## Length of transfer.
aio_reqprio*: cint ## Request priority offset.
aio_sigevent*: TSigEvent ## Signal number and value.
aio_lio_opcode: cint ## Operation to be performed.
TDIR* {.importc: "DIR", header: "<dirent.h>", final.} = object
## A type representing a directory stream. ## A type representing a directory stream.
Tdirent* {.importc: "struct dirent", header: "<dirent.h>", final.} = object Tdirent* {.importc: "struct dirent", header: "<dirent.h>", final, pure.} = object
d_ino*: TIno ## File serial number. d_ino*: TIno ## File serial number.
d_name*: array [0..255, char] ## Name of entry. d_name*: array [0..255, char] ## Name of entry.
Tflock* {.importc: "flock", header: "<fcntl>", final.} = object Tflock* {.importc: "flock", header: "<fcntl.h>", final, pure.} = object
l_type*: cshort ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. l_type*: cshort ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK.
l_whence*: cshort ## Flag for starting offset. l_whence*: cshort ## Flag for starting offset.
l_start*: Toff ## Relative offset in bytes. l_start*: Toff ## Relative offset in bytes.
@ -84,12 +79,12 @@ type
l_pid*: TPid ## Process ID of the process holding the lock; l_pid*: TPid ## Process ID of the process holding the lock;
## returned with F_GETLK. ## returned with F_GETLK.
Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final.} = Tfenv* {.importc: "fenv_t", header: "<fenv.h>", final, pure.} =
object ## Represents the entire floating-point environment. The object ## Represents the entire floating-point environment. The
## floating-point environment refers collectively to any ## floating-point environment refers collectively to any
## floating-point status flags and control modes supported ## floating-point status flags and control modes supported
## by the implementation. ## by the implementation.
Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final.} = Tfexcept* {.importc: "fexcept_t", header: "<fenv.h>", final, pure.} =
object ## Represents the floating-point status flags collectively, object ## Represents the floating-point status flags collectively,
## including any status the implementation associates with the ## including any status the implementation associates with the
## flags. A floating-point status flag is a system variable ## flags. A floating-point status flag is a system variable
@ -100,25 +95,25 @@ type
## whose value may be set by the user to affect the subsequent ## whose value may be set by the user to affect the subsequent
## behavior of floating-point arithmetic. ## behavior of floating-point arithmetic.
TFTW* {.importc: "struct FTW", header: "<ftw.h>", final.} = object TFTW* {.importc: "struct FTW", header: "<ftw.h>", final, pure.} = object
base*: cint base*: cint
level*: cint level*: cint
TGlob* {.importc: "glob_t", header: "<glob.h>", final.} = object TGlob* {.importc: "glob_t", header: "<glob.h>", final, pure.} = object
gl_pathc*: int ## Count of paths matched by pattern. gl_pathc*: int ## Count of paths matched by pattern.
gl_pathv*: ptr cstring ## Pointer to a list of matched pathnames. gl_pathv*: ptr cstring ## Pointer to a list of matched pathnames.
gl_offs*: int ## Slots to reserve at the beginning of gl_pathv. gl_offs*: int ## Slots to reserve at the beginning of gl_pathv.
TGroup* {.importc: "struct group", header: "<grp.h>", final.} = object TGroup* {.importc: "struct group", header: "<grp.h>", final, pure.} = object
gr_name*: cstring ## The name of the group. gr_name*: cstring ## The name of the group.
gr_gid*: TGid ## Numerical group ID. gr_gid*: TGid ## Numerical group ID.
gr_mem*: cstringArray ## Pointer to a null-terminated array of character gr_mem*: cstringArray ## Pointer to a null-terminated array of character
## pointers to member names. ## pointers to member names.
Ticonv* {.importc: "iconv_t", header: "<iconv.h>", final.} = Ticonv* {.importc: "iconv_t", header: "<iconv.h>", final, pure.} =
object ## Identifies the conversion from one codeset to another. object ## Identifies the conversion from one codeset to another.
Tlconv* {.importc: "struct lconv", header: "<locale.h>", final.} = object Tlconv* {.importc: "struct lconv", header: "<locale.h>", final, pure.} = object
currency_symbol*: cstring currency_symbol*: cstring
decimal_point*: cstring decimal_point*: cstring
frac_digits*: char frac_digits*: char
@ -144,14 +139,14 @@ type
p_sign_posn*: char p_sign_posn*: char
thousands_sep*: cstring thousands_sep*: cstring
TMqd* {.importc: "mqd_t", header: "<mqueue.h>", final.} = object TMqd* {.importc: "mqd_t", header: "<mqueue.h>", final, pure.} = object
TMqAttr* {.importc: "struct mq_attr", header: "<mqueue.h>", final.} = object TMqAttr* {.importc: "struct mq_attr", header: "<mqueue.h>", final, pure.} = object
mq_flags*: int ## Message queue flags. mq_flags*: int ## Message queue flags.
mq_maxmsg*: int ## Maximum number of messages. mq_maxmsg*: int ## Maximum number of messages.
mq_msgsize*: int ## Maximum message size. mq_msgsize*: int ## Maximum message size.
mq_curmsgs*: int ## Number of messages currently queued. mq_curmsgs*: int ## Number of messages currently queued.
TPasswd* {.importc: "struct passwd", header: "<pwd.h>", final.} = object TPasswd* {.importc: "struct passwd", header: "<pwd.h>", final, pure.} = object
pw_name*: cstring ## User's login name. pw_name*: cstring ## User's login name.
pw_uid*: TUid ## Numerical user ID. pw_uid*: TUid ## Numerical user ID.
pw_gid*: TGid ## Numerical group ID. pw_gid*: TGid ## Numerical group ID.
@ -198,7 +193,7 @@ type
Tuid* {.importc: "uid_t", header: "<sys/types.h>".} = int Tuid* {.importc: "uid_t", header: "<sys/types.h>".} = int
Tuseconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int Tuseconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int
Tutsname* {.importc: "struct utsname", header: "<sys/utsname.h>", final.} = object Tutsname* {.importc: "struct utsname", header: "<sys/utsname.h>", final, pure.} = object
sysname*, ## Name of this implementation of the operating system. sysname*, ## Name of this implementation of the operating system.
nodename*, ## Name of this node within the communications nodename*, ## Name of this node within the communications
## network to which this node is attached, if any. ## network to which this node is attached, if any.
@ -207,15 +202,15 @@ type
machine*: array [0..255, char] ## Name of the hardware type on which the machine*: array [0..255, char] ## Name of the hardware type on which the
## system is running. ## system is running.
TSem* {.importc: "sem_t", header: "<semaphore.h>", final.} = object TSem* {.importc: "sem_t", header: "<semaphore.h>", final, pure.} = object
Tipc_perm* {.importc: "struct ipc_perm", header: "<sys/ipc.h>", final.} = object Tipc_perm* {.importc: "struct ipc_perm", header: "<sys/ipc.h>", final, pure.} = object
uid*: tuid ## Owner's user ID. uid*: tuid ## Owner's user ID.
gid*: tgid ## Owner's group ID. gid*: tgid ## Owner's group ID.
cuid*: Tuid ## Creator's user ID. cuid*: Tuid ## Creator's user ID.
cgid*: Tgid ## Creator's group ID. cgid*: Tgid ## Creator's group ID.
mode*: TMode ## Read/write permission. mode*: TMode ## Read/write permission.
TStat* {.importc: "struct stat", header: "<sys/stat.h>", final.} = object TStat* {.importc: "struct stat", header: "<sys/stat.h>", final, pure.} = object
st_dev*: TDev ## Device ID of device containing file. st_dev*: TDev ## Device ID of device containing file.
st_ino*: TIno ## File serial number. st_ino*: TIno ## File serial number.
st_mode*: TMode ## Mode of file (see below). st_mode*: TMode ## Mode of file (see below).
@ -239,7 +234,7 @@ type
st_blocks*: Tblkcnt ## Number of blocks allocated for this object. st_blocks*: Tblkcnt ## Number of blocks allocated for this object.
TStatvfs* {.importc: "struct statvfs", header: "<sys/statvfs.h>", final.} = object TStatvfs* {.importc: "struct statvfs", header: "<sys/statvfs.h>", final, pure.} = object
f_bsize*: int ## File system block size. f_bsize*: int ## File system block size.
f_frsize*: int ## Fundamental file system block size. f_frsize*: int ## Fundamental file system block size.
f_blocks*: Tfsblkcnt ## Total number of blocks on file system in units of f_frsize. f_blocks*: Tfsblkcnt ## Total number of blocks on file system in units of f_frsize.
@ -255,10 +250,10 @@ type
f_namemax*: int ## Maximum filename length. f_namemax*: int ## Maximum filename length.
Tposix_typed_mem_info* {.importc: "struct posix_typed_mem_info", Tposix_typed_mem_info* {.importc: "struct posix_typed_mem_info",
header: "<sys/mman.h>", final.} = object header: "<sys/mman.h>", final, pure.} = object
posix_tmi_length*: int posix_tmi_length*: int
Ttm* {.importc: "struct tm", header: "<time.h>", final.} = object Ttm* {.importc: "struct tm", header: "<time.h>", final, pure.} = object
tm_sec*: cint ## Seconds [0,60]. tm_sec*: cint ## Seconds [0,60].
tm_min*: cint ## Minutes [0,59]. tm_min*: cint ## Minutes [0,59].
tm_hour*: cint ## Hour [0,23]. tm_hour*: cint ## Hour [0,23].
@ -268,10 +263,10 @@ type
tm_wday*: cint ## Day of week [0,6] (Sunday =0). tm_wday*: cint ## Day of week [0,6] (Sunday =0).
tm_yday*: cint ## Day of year [0,365]. tm_yday*: cint ## Day of year [0,365].
tm_isdst*: cint ## Daylight Savings flag. tm_isdst*: cint ## Daylight Savings flag.
Ttimespec* {.importc: "struct timespec", header: "<time.h>", final.} = object Ttimespec* {.importc: "struct timespec", header: "<time.h>", final, pure.} = object
tv_sec*: Ttime ## Seconds. tv_sec*: Ttime ## Seconds.
tv_nsec*: int ## Nanoseconds. tv_nsec*: int ## Nanoseconds.
titimerspec* {.importc: "struct itimerspec", header: "<time.h>", final.} = object titimerspec* {.importc: "struct itimerspec", header: "<time.h>", final, pure.} = object
it_interval*: ttimespec ## Timer period. it_interval*: ttimespec ## Timer period.
it_value*: ttimespec ## Timer expiration. it_value*: ttimespec ## Timer expiration.
@ -279,19 +274,19 @@ type
## Possibly volatile-qualified integer type of an object that can be ## Possibly volatile-qualified integer type of an object that can be
## accessed as an atomic entity, even in the presence of asynchronous ## accessed as an atomic entity, even in the presence of asynchronous
## interrupts. ## interrupts.
Tsigset* {.importc: "sigset_t", header: "<signal.h>", final.} = object Tsigset* {.importc: "sigset_t", header: "<signal.h>", final, pure.} = object
TsigEvent* {.importc: "struct sigevent", header: "<signal.h>", final.} = object TsigEvent* {.importc: "struct sigevent", header: "<signal.h>", final, pure.} = object
sigev_notify*: cint ## Notification type. sigev_notify*: cint ## Notification type.
sigev_signo*: cint ## Signal number. sigev_signo*: cint ## Signal number.
sigev_value*: Tsigval ## Signal value. sigev_value*: Tsigval ## Signal value.
sigev_notify_function*: proc (x: TSigval) {.noconv.} ## Notification function. sigev_notify_function*: proc (x: TSigval) {.noconv.} ## Notification function.
sigev_notify_attributes*: ptr Tpthreadattr ## Notification attributes. sigev_notify_attributes*: ptr Tpthreadattr ## Notification attributes.
TsigVal* {.importc: "union sigval", header: "<signal.h>", final.} = object TsigVal* {.importc: "union sigval", header: "<signal.h>", final, pure.} = object
sival_ptr*: pointer ## pointer signal value; sival_ptr*: pointer ## pointer signal value;
## integer signal value not defined! ## integer signal value not defined!
TSigaction* {.importc: "struct sigaction", header: "<signal.h>", final.} = object TSigaction* {.importc: "struct sigaction", header: "<signal.h>", final, pure.} = object
sa_handler*: proc (x: cint) {.noconv.} ## Pointer to a signal-catching sa_handler*: proc (x: cint) {.noconv.} ## Pointer to a signal-catching
## function or one of the macros ## function or one of the macros
## SIG_IGN or SIG_DFL. ## SIG_IGN or SIG_DFL.
@ -300,16 +295,16 @@ type
sa_flags*: cint ## Special flags. sa_flags*: cint ## Special flags.
sa_sigaction*: proc (x: cint, y: var TSigInfo, z: pointer) {.noconv.} sa_sigaction*: proc (x: cint, y: var TSigInfo, z: pointer) {.noconv.}
TStack* {.importc: "stack_t", header: "<signal.h>", final.} = object TStack* {.importc: "stack_t", header: "<signal.h>", final, pure.} = object
ss_sp*: pointer ## Stack base or pointer. ss_sp*: pointer ## Stack base or pointer.
ss_size*: int ## Stack size. ss_size*: int ## Stack size.
ss_flags*: cint ## Flags. ss_flags*: cint ## Flags.
TSigStack* {.importc: "struct sigstack", header: "<signal.h>", final.} = object TSigStack* {.importc: "struct sigstack", header: "<signal.h>", final, pure.} = object
ss_onstack*: cint ## Non-zero when signal stack is in use. ss_onstack*: cint ## Non-zero when signal stack is in use.
ss_sp*: pointer ## Signal stack pointer. ss_sp*: pointer ## Signal stack pointer.
TsigInfo* {.importc: "siginfo_t", header: "<signal.h>", final.} = object TsigInfo* {.importc: "siginfo_t", header: "<signal.h>", final, pure.} = object
si_signo*: cint ## Signal number. si_signo*: cint ## Signal number.
si_code*: cint ## Signal code. si_code*: cint ## Signal code.
si_errno*: cint ## If non-zero, an errno value associated with si_errno*: cint ## If non-zero, an errno value associated with
@ -324,7 +319,7 @@ type
Tnl_item* {.importc: "nl_item", header: "<nl_types.h>".} = cint Tnl_item* {.importc: "nl_item", header: "<nl_types.h>".} = cint
Tnl_catd* {.importc: "nl_catd", header: "<nl_types.h>".} = cint Tnl_catd* {.importc: "nl_catd", header: "<nl_types.h>".} = cint
Tsched_param* {.importc: "struct sched_param", header: "<sched.h>", final.} = object Tsched_param* {.importc: "struct sched_param", header: "<sched.h>", final, pure.} = object
sched_priority*: cint sched_priority*: cint
sched_ss_low_priority*: cint ## Low scheduling priority for sched_ss_low_priority*: cint ## Low scheduling priority for
## sporadic server. ## sporadic server.
@ -334,15 +329,12 @@ type
sched_ss_max_repl*: cint ## Maximum pending replenishments for sched_ss_max_repl*: cint ## Maximum pending replenishments for
## sporadic server. ## sporadic server.
Ttimeval* {.importc: "struct timeval", header: "<sys/select.h>", final.} = object Ttimeval* {.importc: "struct timeval", header: "<sys/select.h>", final, pure.} = object
tv_sec*: ttime ## Seconds. tv_sec*: ttime ## Seconds.
tv_usec*: tsuseconds ## Microseconds. tv_usec*: tsuseconds ## Microseconds.
Tfd_set* {.importc: "struct fd_set", header: "<sys/select.h>", final.} = object Tfd_set* {.importc: "struct fd_set", header: "<sys/select.h>", final, pure.} = object
Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>", final, pure.} = object
Tposix_spawnattr* {.importc: "posix_spawnattr_t", header: "<spawn.h>".} = cint Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>", final, pure.} = object
Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", header: "<spawn.h>".} = cint
Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>", final.} = object
Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>", final.} = object
uc_link*: ptr Tucontext ## Pointer to the context that is resumed uc_link*: ptr Tucontext ## Pointer to the context that is resumed
## when this context returns. ## when this context returns.
uc_sigmask*: Tsigset ## The set of signals that are blocked when this uc_sigmask*: Tsigset ## The set of signals that are blocked when this
@ -351,35 +343,52 @@ type
uc_mcontext*: Tmcontext ## A machine-specific representation of the saved uc_mcontext*: Tmcontext ## A machine-specific representation of the saved
## context. ## context.
when hasAioH:
type
Taiocb* {.importc: "struct aiocb", header: "<aio.h>", final, pure.} = object
aio_fildes*: cint ## File descriptor.
aio_offset*: TOff ## File offset.
aio_buf*: pointer ## Location of buffer.
aio_nbytes*: int ## Length of transfer.
aio_reqprio*: cint ## Request priority offset.
aio_sigevent*: TSigEvent ## Signal number and value.
aio_lio_opcode: cint ## Operation to be performed.
when hasSpawnH:
type
Tposix_spawnattr* {.importc: "posix_spawnattr_t", header: "<spawn.h>".} = cint
Tposix_spawn_file_actions* {.importc: "posix_spawn_file_actions_t", header: "<spawn.h>".} = cint
# Constants as variables: # Constants as variables:
var when hasAioH:
AIO_ALLDONE* {.importc, header: "<aio.h>".}: cint var
## A return value indicating that none of the requested operations AIO_ALLDONE* {.importc, header: "<aio.h>".}: cint
## could be canceled since they are already complete. ## A return value indicating that none of the requested operations
AIO_CANCELED* {.importc, header: "<aio.h>".}: cint ## could be canceled since they are already complete.
## A return value indicating that all requested operations have AIO_CANCELED* {.importc, header: "<aio.h>".}: cint
## been canceled. ## A return value indicating that all requested operations have
AIO_NOTCANCELED* {.importc, header: "<aio.h>".}: cint ## been canceled.
## A return value indicating that some of the requested operations could AIO_NOTCANCELED* {.importc, header: "<aio.h>".}: cint
## not be canceled since they are in progress. ## A return value indicating that some of the requested operations could
LIO_NOP* {.importc, header: "<aio.h>".}: cint ## not be canceled since they are in progress.
## A lio_listio() element operation option indicating that no transfer is LIO_NOP* {.importc, header: "<aio.h>".}: cint
## requested. ## A lio_listio() element operation option indicating that no transfer is
LIO_NOWAIT* {.importc, header: "<aio.h>".}: cint ## requested.
## A lio_listio() synchronization operation indicating that the calling LIO_NOWAIT* {.importc, header: "<aio.h>".}: cint
## thread is to continue execution while the lio_listio() operation is ## A lio_listio() synchronization operation indicating that the calling
## being performed, and no notification is given when the operation is ## thread is to continue execution while the lio_listio() operation is
## complete. ## being performed, and no notification is given when the operation is
LIO_READ* {.importc, header: "<aio.h>".}: cint ## complete.
## A lio_listio() element operation option requesting a read. LIO_READ* {.importc, header: "<aio.h>".}: cint
LIO_WAIT* {.importc, header: "<aio.h>".}: cint ## A lio_listio() element operation option requesting a read.
## A lio_listio() synchronization operation indicating that the calling LIO_WAIT* {.importc, header: "<aio.h>".}: cint
## thread is to suspend until the lio_listio() operation is complete. ## A lio_listio() synchronization operation indicating that the calling
LIO_WRITE* {.importc, header: "<aio.h>".}: cint ## thread is to suspend until the lio_listio() operation is complete.
## A lio_listio() element operation option requesting a write. LIO_WRITE* {.importc, header: "<aio.h>".}: cint
## A lio_listio() element operation option requesting a write.
var
RTLD_LAZY* {.importc, header: "<dlfcn.h>".}: cint RTLD_LAZY* {.importc, header: "<dlfcn.h>".}: cint
## Relocations are performed at an implementation-defined time. ## Relocations are performed at an implementation-defined time.
RTLD_NOW* {.importc, header: "<dlfcn.h>".}: cint RTLD_NOW* {.importc, header: "<dlfcn.h>".}: cint
@ -1246,23 +1255,30 @@ var
SCHED_OTHER* {.importc, header: "<sched.h>".}: cint SCHED_OTHER* {.importc, header: "<sched.h>".}: cint
FD_SETSIZE* {.importc, header: "<sys/select.h>".}: cint FD_SETSIZE* {.importc, header: "<sys/select.h>".}: cint
POSIX_SPAWN_RESETIDS* {.importc, header: "<spawn.h>".}: cint SEEK_SET* {.importc, header: "<unistd.h>".}: cint
POSIX_SPAWN_SETPGROUP* {.importc, header: "<spawn.h>".}: cint SEEK_CUR* {.importc, header: "<unistd.h>".}: cint
POSIX_SPAWN_SETSCHEDPARAM* {.importc, header: "<spawn.h>".}: cint SEEK_END* {.importc, header: "<unistd.h>".}: cint
POSIX_SPAWN_SETSCHEDULER* {.importc, header: "<spawn.h>".}: cint
POSIX_SPAWN_SETSIGDEF* {.importc, header: "<spawn.h>".}: cint
POSIX_SPAWN_SETSIGMASK* {.importc, header: "<spawn.h>".}: cint
proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".} when hasSpawnh:
proc aio_error*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".} var
proc aio_fsync*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".} POSIX_SPAWN_RESETIDS* {.importc, header: "<spawn.h>".}: cint
proc aio_read*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".} POSIX_SPAWN_SETPGROUP* {.importc, header: "<spawn.h>".}: cint
proc aio_return*(a1: ptr Taiocb): int {.importc, header: "<aio.h>".} POSIX_SPAWN_SETSCHEDPARAM* {.importc, header: "<spawn.h>".}: cint
proc aio_suspend*(a1: ptr ptr Taiocb, a2: cint, a3: ptr ttimespec): cint {. POSIX_SPAWN_SETSCHEDULER* {.importc, header: "<spawn.h>".}: cint
importc, header: "<aio.h>".} POSIX_SPAWN_SETSIGDEF* {.importc, header: "<spawn.h>".}: cint
proc aio_write*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".} POSIX_SPAWN_SETSIGMASK* {.importc, header: "<spawn.h>".}: cint
proc lio_listio*(a1: cint, a2: ptr ptr Taiocb, a3: cint,
a4: ptr Tsigevent): cint {.importc, header: "<aio.h>".} when hasAioH:
proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
proc aio_error*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".}
proc aio_fsync*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
proc aio_read*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".}
proc aio_return*(a1: ptr Taiocb): int {.importc, header: "<aio.h>".}
proc aio_suspend*(a1: ptr ptr Taiocb, a2: cint, a3: ptr ttimespec): cint {.
importc, header: "<aio.h>".}
proc aio_write*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".}
proc lio_listio*(a1: cint, a2: ptr ptr Taiocb, a3: cint,
a4: ptr Tsigevent): cint {.importc, header: "<aio.h>".}
# arpa/inet.h # arpa/inet.h
proc htonl*(a1: int32): int32 {.importc, header: "<arpa/inet.h>".} proc htonl*(a1: int32): int32 {.importc, header: "<arpa/inet.h>".}
@ -1371,8 +1387,8 @@ proc mq_unlink*(a1: cstring): cint {.importc, header: "<mqueue.h>".}
proc getpwnam*(a1: cstring): ptr TPasswd {.importc, header: "<pwd.h>".} proc getpwnam*(a1: cstring): ptr TPasswd {.importc, header: "<pwd.h>".}
proc getpwuid*(a1: Tuid): ptr TPasswd {.importc, header: "<pwd.h>".} proc getpwuid*(a1: Tuid): ptr TPasswd {.importc, header: "<pwd.h>".}
proc getpwnam_r(a1: cstring, a2: ptr Tpasswd, a3: cstring, a4: int, proc getpwnam_r*(a1: cstring, a2: ptr Tpasswd, a3: cstring, a4: int,
a5: ptr ptr Tpasswd): cint {.importc, header: "<pwd.h>".} a5: ptr ptr Tpasswd): cint {.importc, header: "<pwd.h>".}
proc getpwuid_r*(a1: Tuid, a2: ptr Tpasswd, a3: cstring, proc getpwuid_r*(a1: Tuid, a2: ptr Tpasswd, a3: cstring,
a4: int, a5: ptr ptr Tpasswd): cint {.importc, header: "<pwd.h>".} a4: int, a5: ptr ptr Tpasswd): cint {.importc, header: "<pwd.h>".}
proc endpwent*() {.importc, header: "<pwd.h>".} proc endpwent*() {.importc, header: "<pwd.h>".}
@ -1771,46 +1787,47 @@ proc pselect*(a1: cint, a2, a3, a4: var Tfd_set, a5: var ttimespec,
proc select*(a1: cint, a2, a3, a4: var Tfd_set, a5: var ttimeval): cint {. proc select*(a1: cint, a2, a3, a4: var Tfd_set, a5: var ttimeval): cint {.
importc, header: "<sys/select.h>".} importc, header: "<sys/select.h>".}
proc posix_spawn*(a1: var tpid, a2: cstring, when hasSpawnH:
a3: var Tposix_spawn_file_actions, proc posix_spawn*(a1: var tpid, a2: cstring,
a4: var Tposix_spawnattr, a5, a6: cstringArray): cint {.importc, header: "<spawn.h>".} a3: var Tposix_spawn_file_actions,
proc posix_spawn_file_actions_addclose*(a1: var tposix_spawn_file_actions, a4: var Tposix_spawnattr, a5, a6: cstringArray): cint {.importc, header: "<spawn.h>".}
a2: cint): cint {.importc, header: "<spawn.h>".} proc posix_spawn_file_actions_addclose*(a1: var tposix_spawn_file_actions,
proc posix_spawn_file_actions_adddup2*(a1: var tposix_spawn_file_actions, a2: cint): cint {.importc, header: "<spawn.h>".}
a2, a3: cint): cint {.importc, header: "<spawn.h>".} proc posix_spawn_file_actions_adddup2*(a1: var tposix_spawn_file_actions,
proc posix_spawn_file_actions_addopen*(a1: var tposix_spawn_file_actions, a2, a3: cint): cint {.importc, header: "<spawn.h>".}
a2: cint, a3: cstring, a4: cint, a5: tmode): cint {.importc, header: "<spawn.h>".} proc posix_spawn_file_actions_addopen*(a1: var tposix_spawn_file_actions,
proc posix_spawn_file_actions_destroy*(a1: var tposix_spawn_file_actions): cint {.importc, header: "<spawn.h>".} a2: cint, a3: cstring, a4: cint, a5: tmode): cint {.importc, header: "<spawn.h>".}
proc posix_spawn_file_actions_init*(a1: var tposix_spawn_file_actions): cint {.importc, header: "<spawn.h>".} proc posix_spawn_file_actions_destroy*(a1: var tposix_spawn_file_actions): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_destroy*(a1: var tposix_spawnattr): cint {.importc, header: "<spawn.h>".} proc posix_spawn_file_actions_init*(a1: var tposix_spawn_file_actions): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_getsigdefault*(a1: var tposix_spawnattr, proc posix_spawnattr_destroy*(a1: var tposix_spawnattr): cint {.importc, header: "<spawn.h>".}
a2: var Tsigset): cint {.importc, header: "<spawn.h>".} proc posix_spawnattr_getsigdefault*(a1: var tposix_spawnattr,
proc posix_spawnattr_getflags*(a1: var tposix_spawnattr, a2: var Tsigset): cint {.importc, header: "<spawn.h>".}
a2: var cshort): cint {.importc, header: "<spawn.h>".} proc posix_spawnattr_getflags*(a1: var tposix_spawnattr,
proc posix_spawnattr_getpgroup*(a1: var tposix_spawnattr, a2: var cshort): cint {.importc, header: "<spawn.h>".}
a2: var tpid): cint {.importc, header: "<spawn.h>".} proc posix_spawnattr_getpgroup*(a1: var tposix_spawnattr,
proc posix_spawnattr_getschedparam*(a1: var tposix_spawnattr, a2: var tpid): cint {.importc, header: "<spawn.h>".}
a2: var tsched_param): cint {.importc, header: "<spawn.h>".} proc posix_spawnattr_getschedparam*(a1: var tposix_spawnattr,
proc posix_spawnattr_getschedpolicy*(a1: var tposix_spawnattr, a2: var tsched_param): cint {.importc, header: "<spawn.h>".}
a2: var cint): cint {.importc, header: "<spawn.h>".} proc posix_spawnattr_getschedpolicy*(a1: var tposix_spawnattr,
proc posix_spawnattr_getsigmask*(a1: var tposix_spawnattr, a2: var cint): cint {.importc, header: "<spawn.h>".}
a2: var tsigset): cint {.importc, header: "<spawn.h>".} proc posix_spawnattr_getsigmask*(a1: var tposix_spawnattr,
a2: var tsigset): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_init*(a1: var tposix_spawnattr): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_setsigdefault*(a1: var tposix_spawnattr, proc posix_spawnattr_init*(a1: var tposix_spawnattr): cint {.importc, header: "<spawn.h>".}
a2: var tsigset): cint {.importc, header: "<spawn.h>".} proc posix_spawnattr_setsigdefault*(a1: var tposix_spawnattr,
proc posix_spawnattr_setflags*(a1: var tposix_spawnattr, a2: cshort): cint {.importc, header: "<spawn.h>".} a2: var tsigset): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_setpgroup*(a1: var tposix_spawnattr, a2: tpid): cint {.importc, header: "<spawn.h>".} proc posix_spawnattr_setflags*(a1: var tposix_spawnattr, a2: cshort): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_setpgroup*(a1: var tposix_spawnattr, a2: tpid): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_setschedparam*(a1: var tposix_spawnattr,
a2: var tsched_param): cint {.importc, header: "<spawn.h>".} proc posix_spawnattr_setschedparam*(a1: var tposix_spawnattr,
proc posix_spawnattr_setschedpolicy*(a1: var tposix_spawnattr, a2: cint): cint {.importc, header: "<spawn.h>".} a2: var tsched_param): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_setsigmask*(a1: var tposix_spawnattr, proc posix_spawnattr_setschedpolicy*(a1: var tposix_spawnattr, a2: cint): cint {.importc, header: "<spawn.h>".}
a2: var tsigset): cint {.importc, header: "<spawn.h>".} proc posix_spawnattr_setsigmask*(a1: var tposix_spawnattr,
proc posix_spawnp*(a1: var tpid, a2: cstring, a2: var tsigset): cint {.importc, header: "<spawn.h>".}
a3: var tposix_spawn_file_actions, proc posix_spawnp*(a1: var tpid, a2: cstring,
a4: var tposix_spawnattr, a3: var tposix_spawn_file_actions,
a5, a6: cstringArray): cint {.importc, header: "<spawn.h>".} a4: var tposix_spawnattr,
a5, a6: cstringArray): cint {.importc, header: "<spawn.h>".}
proc getcontext*(a1: var Tucontext): cint {.importc, header: "<ucontext.h>".} proc getcontext*(a1: var Tucontext): cint {.importc, header: "<ucontext.h>".}
proc makecontext*(a1: var Tucontext, a4: proc (){.noconv.}, a3: cint) {.varargs, importc, header: "<ucontext.h>".} proc makecontext*(a1: var Tucontext, a4: proc (){.noconv.}, a3: cint) {.varargs, importc, header: "<ucontext.h>".}

File diff suppressed because it is too large Load diff

View file

@ -85,7 +85,7 @@ proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
else: else:
var a = cast[pbyteArray](p) var a = cast[pbyteArray](p)
for i in 0 .. typ.size*8-1: for i in 0 .. typ.size*8-1:
if (a[i div 8] and (1 shl (i mod 8))) != 0: if (ze(a[i div 8]) and (1 shl (i mod 8))) != 0:
if elemCounter > 0: add result, ", " if elemCounter > 0: add result, ", "
addSetElem(result, i+typ.node.len, typ.base) addSetElem(result, i+typ.node.len, typ.base)
inc(elemCounter) inc(elemCounter)

View file

@ -24,36 +24,36 @@ include cntbits
proc unionSets(res: var TNimSet, a, b: TNimSet, len: int) {. proc unionSets(res: var TNimSet, a, b: TNimSet, len: int) {.
compilerproc, inline.} = compilerproc, inline.} =
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) or ze(b[i])) for i in countup(0, len-1): res[i] = a[i] or b[i]
proc diffSets(res: var TNimSet, a, b: TNimSet, len: int) {. proc diffSets(res: var TNimSet, a, b: TNimSet, len: int) {.
compilerproc, inline.} = compilerproc, inline.} =
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) and not ze(b[i])) for i in countup(0, len-1): res[i] = a[i] and not b[i]
proc intersectSets(res: var TNimSet, a, b: TNimSet, len: int) {. proc intersectSets(res: var TNimSet, a, b: TNimSet, len: int) {.
compilerproc, inline.} = compilerproc, inline.} =
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) and ze(b[i])) for i in countup(0, len-1): res[i] = a[i] and b[i]
proc symdiffSets(res: var TNimSet, a, b: TNimSet, len: int) {. proc symdiffSets(res: var TNimSet, a, b: TNimSet, len: int) {.
compilerproc, inline.} = compilerproc, inline.} =
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) xor ze(b[i])) for i in countup(0, len-1): res[i] = a[i] xor b[i]
proc containsSets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} = proc containsSets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} =
# s1 <= s2 ? # s1 <= s2 ?
for i in countup(0, len-1): for i in countup(0, len-1):
if (ze(a[i]) and not ze(b[i])) != 0: return false if (a[i] and not b[i]) != 0'i8: return false
return true return true
proc containsSubsets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} = proc containsSubsets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} =
# s1 < s2 ? # s1 < s2 ?
result = false # assume they are equal result = false # assume they are equal
for i in countup(0, len-1): for i in countup(0, len-1):
if (ze(a[i]) and not ze(b[i])) != 0: return false if (a[i]) and not b[i]) != 0'i32: return false
if ze(a[i]) != ze(b[i]): result = true # they are not equal if a[i] != b[i]: result = true # they are not equal
proc equalSets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} = proc equalSets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} =
for i in countup(0, len-1): for i in countup(0, len-1):
if ze(a[i]) != ze(b[i]): return false if a[i] != b[i]: return false
return true return true
proc cardSet(s: TNimSet, len: int): int {.compilerproc, inline.} = proc cardSet(s: TNimSet, len: int): int {.compilerproc, inline.} =
@ -68,7 +68,7 @@ proc inSet(s: TNimSet, elem: int): bool {.compilerproc, inline.} =
return (s[elem /% WORD_SIZE] and (1 shl (elem %% WORD_SIZE))) != 0 return (s[elem /% WORD_SIZE] and (1 shl (elem %% WORD_SIZE))) != 0
proc inclSets(s: var TNimSet, e: int) {.compilerproc, inline.} = proc inclSets(s: var TNimSet, e: int) {.compilerproc, inline.} =
s[e /% WORD_SIZE] = toU8(s[e /% WORD_SIZE] or (1 shl (e %% WORD_SIZE))) s[e /% WORD_SIZE] = s[e /% WORD_SIZE] or toU8(1 shl (e %% WORD_SIZE))
proc inclRange(s: var TNimSet, first, last: int) {.compilerproc.} = proc inclRange(s: var TNimSet, first, last: int) {.compilerproc.} =
# not very fast, but it is seldom used # not very fast, but it is seldom used
@ -80,8 +80,8 @@ proc smallInclRange(s: var int, first, last: int) {.compilerproc.} =
s = s or (1 shl (i %% sizeof(int)*8)) s = s or (1 shl (i %% sizeof(int)*8))
proc exclSets(s: var TNimSet, e: int) {.compilerproc, inline.} = proc exclSets(s: var TNimSet, e: int) {.compilerproc, inline.} =
s[e /% WORD_SIZE] = toU8(s[e /% WORD_SIZE] and s[e /% WORD_SIZE] = s[e /% WORD_SIZE] and
not (1 shl (e %% WORD_SIZE))) not toU8(1 shl (e %% WORD_SIZE))
proc smallContainsSubsets(a, b: int): bool {.compilerProc, inline.} = proc smallContainsSubsets(a, b: int): bool {.compilerProc, inline.} =
# not used by new code generator # not used by new code generator

View file

@ -1,19 +0,0 @@
# Handle small allocations efficiently
# We allocate and manage memory by pages. All objects within a page belong to
# the same type. Thus, we safe the type field. Minimum requested block is
# 8 bytes. Alignment is 8 bytes.
type
TChunk {.pure.} = object
kind: TChunkKind
prev, next: ptr TChunk
TSmallChunk = object of TChunk # all objects of the same size
typ: PNimType
free: int
data: array [0.., int]
proc allocSmall(typ: PNimType): pointer =

View file

@ -11,11 +11,11 @@
## from strings to strings. Supports a case-sensitive, case-insensitive and ## from strings to strings. Supports a case-sensitive, case-insensitive and
## style-insensitive mode. An efficient string substitution operator ``%`` ## style-insensitive mode. An efficient string substitution operator ``%``
## for the string table is also provided. ## for the string table is also provided.
import import
os, hashes, strutils os, hashes, strutils
type type
TStringTableMode* = enum # describes the tables operation mode TStringTableMode* = enum # describes the tables operation mode
modeCaseSensitive, # the table is case sensitive modeCaseSensitive, # the table is case sensitive
modeCaseInsensitive, # the table is case insensitive modeCaseInsensitive, # the table is case insensitive
@ -29,16 +29,16 @@ type
PStringTable* = ref TStringTable ## use this type to declare string tables PStringTable* = ref TStringTable ## use this type to declare string tables
proc newStringTable*(keyValuePairs: openarray[string], proc newStringTable*(keyValuePairs: openarray[string],
mode: TStringTableMode = modeCaseSensitive): PStringTable mode: TStringTableMode = modeCaseSensitive): PStringTable
## creates a new string table with given key value pairs. ## creates a new string table with given key value pairs.
## Example:: ## Example::
## var mytab = newStringTable("key1", "val1", "key2", "val2", ## var mytab = newStringTable("key1", "val1", "key2", "val2",
## modeCaseInsensitive) ## modeCaseInsensitive)
proc newStringTable*(mode: TStringTableMode = modeCaseSensitive): PStringTable proc newStringTable*(mode: TStringTableMode = modeCaseSensitive): PStringTable
## creates a new string table that is empty. ## creates a new string table that is empty.
proc `[]=`*(t: PStringTable, key, val: string) proc `[]=`*(t: PStringTable, key, val: string)
## puts a (key, value)-pair into `t`. ## puts a (key, value)-pair into `t`.
@ -54,13 +54,13 @@ proc len*(t: PStringTable): int =
## returns the number of keys in `t`. ## returns the number of keys in `t`.
result = t.counter result = t.counter
iterator pairs*(t: PStringTable): tuple[key, value: string] = iterator pairs*(t: PStringTable): tuple[key, value: string] =
## iterates over any (key, value) pair in the table `t`. ## iterates over any (key, value) pair in the table `t`.
for h in 0..high(t.data): for h in 0..high(t.data):
if not isNil(t.data[h].key): if not isNil(t.data[h].key):
yield (t.data[h].key, t.data[h].val) yield (t.data[h].key, t.data[h].val)
type type
TFormatFlag* = enum # flags for the `%` operator TFormatFlag* = enum # flags for the `%` operator
useEnvironment, # use environment variable if the ``$key`` useEnvironment, # use environment variable if the ``$key``
# is not found in the table # is not found in the table
@ -75,136 +75,131 @@ proc `%`*(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string
# implementation # implementation
const const
growthFactor = 2 growthFactor = 2
startSize = 64 startSize = 64
proc newStringTable(mode: TStringTableMode = modeCaseSensitive): PStringTable = proc newStringTable(mode: TStringTableMode = modeCaseSensitive): PStringTable =
new(result) new(result)
result.mode = mode result.mode = mode
result.counter = 0 result.counter = 0
result.data = [] newSeq(result.data, startSize)
setlen(result.data, startSize) # XXX
proc newStringTable(keyValuePairs: openarray[string], proc newStringTable(keyValuePairs: openarray[string],
mode: TStringTableMode = modeCaseSensitive): PStringTable = mode: TStringTableMode = modeCaseSensitive): PStringTable =
result = newStringTable(mode) result = newStringTable(mode)
var i = 0 var i = 0
while i < high(keyValuePairs): while i < high(keyValuePairs):
result[keyValuePairs[i]] = keyValuePairs[i + 1] result[keyValuePairs[i]] = keyValuePairs[i + 1]
inc(i, 2) inc(i, 2)
proc myhash(t: PStringTable, key: string): THash = proc myhash(t: PStringTable, key: string): THash =
case t.mode case t.mode
of modeCaseSensitive: result = hashes.hash(key) of modeCaseSensitive: result = hashes.hash(key)
of modeCaseInsensitive: result = hashes.hashIgnoreCase(key) of modeCaseInsensitive: result = hashes.hashIgnoreCase(key)
of modeStyleInsensitive: result = hashes.hashIgnoreStyle(key) of modeStyleInsensitive: result = hashes.hashIgnoreStyle(key)
proc myCmp(t: PStringTable, a, b: string): bool = proc myCmp(t: PStringTable, a, b: string): bool =
case t.mode case t.mode
of modeCaseSensitive: result = cmp(a, b) == 0 of modeCaseSensitive: result = cmp(a, b) == 0
of modeCaseInsensitive: result = cmpIgnoreCase(a, b) == 0 of modeCaseInsensitive: result = cmpIgnoreCase(a, b) == 0
of modeStyleInsensitive: result = cmpIgnoreStyle(a, b) == 0 of modeStyleInsensitive: result = cmpIgnoreStyle(a, b) == 0
proc mustRehash(length, counter: int): bool = proc mustRehash(length, counter: int): bool =
assert(length > counter) assert(length > counter)
result = (length * 2 < counter * 3) or (length - counter < 4) result = (length * 2 < counter * 3) or (length - counter < 4)
const proc nextTry(h, maxHash: THash): THash =
EmptySeq = []
proc nextTry(h, maxHash: THash): THash =
result = ((5 * h) + 1) and maxHash # For any initial h in range(maxHash), repeating that maxHash times 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 # generates each int in range(maxHash) exactly once (see any text on
# random-number generation for proof). # random-number generation for proof).
proc RawGet(t: PStringTable, key: string): int = proc RawGet(t: PStringTable, key: string): int =
var h: THash var h: THash
h = myhash(t, key) and high(t.data) # start with real hash value h = myhash(t, key) and high(t.data) # start with real hash value
while not isNil(t.data[h].key): while not isNil(t.data[h].key):
if mycmp(t, t.data[h].key, key): if mycmp(t, t.data[h].key, key):
return h return h
h = nextTry(h, high(t.data)) h = nextTry(h, high(t.data))
result = - 1 result = - 1
proc `[]`(t: PStringTable, key: string): string = proc `[]`(t: PStringTable, key: string): string =
var index: int var index: int
index = RawGet(t, key) index = RawGet(t, key)
if index >= 0: result = t.data[index].val if index >= 0: result = t.data[index].val
else: result = "" else: result = ""
proc hasKey(t: PStringTable, key: string): bool = proc hasKey(t: PStringTable, key: string): bool =
result = rawGet(t, key) >= 0 result = rawGet(t, key) >= 0
proc RawInsert(t: PStringTable, data: var TKeyValuePairSeq, key, val: string) = proc RawInsert(t: PStringTable, data: var TKeyValuePairSeq, key, val: string) =
var h: THash var h: THash
h = myhash(t, key) and high(data) h = myhash(t, key) and high(data)
while not isNil(data[h].key): while not isNil(data[h].key):
h = nextTry(h, high(data)) h = nextTry(h, high(data))
data[h].key = key data[h].key = key
data[h].val = val data[h].val = val
proc Enlarge(t: PStringTable) = proc Enlarge(t: PStringTable) =
var n: TKeyValuePairSeq var n: TKeyValuePairSeq
n = emptySeq newSeq(n, len(t.data) * growthFactor)
setlen(n, len(t.data) * growthFactor) for i in countup(0, high(t.data)):
for i in countup(0, high(t.data)):
if not isNil(t.data[i].key): RawInsert(t, n, t.data[i].key, t.data[i].val) if not isNil(t.data[i].key): RawInsert(t, n, t.data[i].key, t.data[i].val)
swap(t.data, n) swap(t.data, n)
proc `[]=`(t: PStringTable, key, val: string) = proc `[]=`(t: PStringTable, key, val: string) =
var index = RawGet(t, key) var index = RawGet(t, key)
if index >= 0: if index >= 0:
t.data[index].val = val t.data[index].val = val
else: else:
if mustRehash(len(t.data), t.counter): Enlarge(t) if mustRehash(len(t.data), t.counter): Enlarge(t)
RawInsert(t, t.data, key, val) RawInsert(t, t.data, key, val)
inc(t.counter) inc(t.counter)
proc RaiseFormatException(s: string) = proc RaiseFormatException(s: string) =
var e: ref EInvalidValue var e: ref EInvalidValue
new(e) new(e)
e.msg = "format string: key not found: " & s e.msg = "format string: key not found: " & s
raise e raise e
proc getValue(t: PStringTable, flags: set[TFormatFlag], key: string): string = proc getValue(t: PStringTable, flags: set[TFormatFlag], key: string): string =
if hasKey(t, key): return t[key] if hasKey(t, key): return t[key]
if useEnvironment in flags: result = os.getEnv(key) if useEnvironment in flags: result = os.getEnv(key)
else: result = "" else: result = ""
if (result == ""): if (result == ""):
if useKey in flags: result = '$' & key if useKey in flags: result = '$' & key
elif not (useEmpty in flags): raiseFormatException(key) elif not (useEmpty in flags): raiseFormatException(key)
proc `%`(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string = proc `%`(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string =
const const
PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF'} PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF'}
var var
i, j: int i, j: int
key: string key: string
result = "" result = ""
i = strStart i = strStart
while i <= len(f) + strStart - 1: while i <= len(f) + strStart - 1:
if f[i] == '$': if f[i] == '$':
case f[i + 1] case f[i + 1]
of '$': of '$':
add(result, '$') add(result, '$')
inc(i, 2) inc(i, 2)
of '{': of '{':
j = i + 1 j = i + 1
while (j <= len(f) + strStart - 1) and (f[j] != '}'): inc(j) while (j <= len(f) + strStart - 1) and (f[j] != '}'): inc(j)
key = copy(f, i + 2, j - 1) key = copy(f, i + 2, j - 1)
result = result & getValue(t, flags, key) result = result & getValue(t, flags, key)
i = j + 1 i = j + 1
of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_': of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_':
j = i + 1 j = i + 1
while (j <= len(f) + strStart - 1) and (f[j] in PatternChars): inc(j) while (j <= len(f) + strStart - 1) and (f[j] in PatternChars): inc(j)
key = copy(f, i+1, j - 1) key = copy(f, i+1, j - 1)
result = result & getValue(t, flags, key) result = result & getValue(t, flags, key)
i = j i = j
else: else:
add(result, f[i]) add(result, f[i])
inc(i) inc(i)
else: else:
add(result, f[i]) add(result, f[i])
inc(i) inc(i)

View file

@ -24,6 +24,7 @@ template newException(exceptn, message: expr): expr =
e.msg = message e.msg = message
e e
type type
TCharSet* = set[char] # for compability for Nim TCharSet* = set[char] # for compability for Nim
@ -73,6 +74,9 @@ proc findSubStr*(sub: char, s: string, start: int = 0): int {.noSideEffect.}
proc replaceStr*(s, sub, by: string): string {.noSideEffect.} proc replaceStr*(s, sub, by: string): string {.noSideEffect.}
## Replaces `sub` in `s` by the string `by`. ## Replaces `sub` in `s` by the string `by`.
proc replaceStr*(s: string, sub, by: char): string {.noSideEffect.}
## optimized version for characters.
proc deleteStr*(s: var string, first, last: int) proc deleteStr*(s: var string, first, last: int)
## Deletes in `s` the characters at position `first`..`last`. This modifies ## Deletes in `s` the characters at position `first`..`last`. This modifies
## `s` itself, it does not return a copy. ## `s` itself, it does not return a copy.
@ -113,6 +117,43 @@ iterator split*(s: string, seps: set[char] = Whitespace): string =
while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX! while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX!
yield copy(s, first, last-1) yield copy(s, first, last-1)
iterator splitLines*(s: string): string =
## Splits the string `s` into its containing lines. Each newline
## combination (CR, LF, CR-LF) is supported. The result strings contain
## no trailing ``\n``.
##
## Example::
##
## for line in lines("\nthis\nis\nan\n\nexample\n"):
## writeln(stdout, line)
##
## Results in::
##
## ""
## "this"
## "is"
## "an"
## ""
## "example"
## ""
var first = 0
var last = 0
while true:
while s[last] notin {'\0', '\c', '\l'}: inc(last)
yield copy(s, first, last-1)
# skip newlines:
if s[last] == '\l': inc(last)
elif s[last] == '\c':
inc(last)
if s[last] == '\l': inc(last)
else: break # was '\0'
first = last
proc splitLinesSeq*(s: string): seq[string] {.noSideEffect.} =
## The same as `split`, but is a proc that returns a sequence of substrings.
result = @[]
for line in splitLines(s): add(result, line)
proc splitSeq*(s: string, seps: set[char] = Whitespace): seq[string] {. proc splitSeq*(s: string, seps: set[char] = Whitespace): seq[string] {.
noSideEffect.} noSideEffect.}
## The same as `split`, but is a proc that returns a sequence of substrings. ## The same as `split`, but is a proc that returns a sequence of substrings.
@ -159,7 +200,8 @@ proc ParseBiggestInt*(s: string): biggestInt {.noSideEffect.}
proc ParseFloat*(s: string): float {.noSideEffect.} proc ParseFloat*(s: string): float {.noSideEffect.}
## Parses a decimal floating point value contained in `s`. If `s` is not ## Parses a decimal floating point value contained in `s`. If `s` is not
## a valid floating point number, `EInvalidValue` is raised. ## a valid floating point number, `EInvalidValue` is raised. ``NAN``,
## ``INF``, ``-INF`` are also supported (case insensitive comparison).
# XXX: make this biggestfloat. # XXX: make this biggestfloat.
# the stringify and format operators: # the stringify and format operators:
@ -344,7 +386,7 @@ proc cmpIgnoreStyle(a, b: string): int =
# ---------- splitting ----------------------------------------------------- # ---------- splitting -----------------------------------------------------
proc splitSeq(s: string, seps: set[char]): seq[string] = proc splitSeq(s: string, seps: set[char]): seq[string] =
result = [] result = @[]
for sub in split(s, seps): add result, sub for sub in split(s, seps): add result, sub
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -469,6 +511,14 @@ proc replaceStr(s, sub, by: string): string =
# copy the rest: # copy the rest:
add result, copy(s, i) add result, copy(s, i)
proc replaceStr(s: string, sub, by: char): string =
result = newString(s.len)
var i = 0
while i < s.len:
if s[i] == sub: result[i] = by
else: result[i] = s[i]
inc(i)
proc deleteStr(s: var string, first, last: int) = proc deleteStr(s: var string, first, last: int) =
# example: "abc___uvwxyz\0" (___ is to be deleted) # example: "abc___uvwxyz\0" (___ is to be deleted)
# --> first == 3, last == 5 # --> first == 3, last == 5
@ -489,7 +539,7 @@ proc toHex(x: BiggestInt, len: int): string =
shift: BiggestInt shift: BiggestInt
result = newString(len) result = newString(len)
for j in countdown(len-1, 0): for j in countdown(len-1, 0):
result[j] = HexChars[toU32(x shr shift) and 0xF] result[j] = HexChars[toU32(x shr shift) and 0xF'i32]
shift = shift + 4 shift = shift + 4
{.push overflowChecks: on.} {.push overflowChecks: on.}
@ -552,6 +602,16 @@ proc ParseFloat(s: string): float =
elif s[i] == '-': elif s[i] == '-':
sign = -1.0 sign = -1.0
inc(i) inc(i)
if s[i] == 'N' or s[i] == 'n':
if s[i+1] == 'A' or s[i+1] == 'a':
if s[i+2] == 'N' or s[i+2] == 'n':
if s[i+3] == '\0': return NaN
raise newException(EInvalidValue, "invalid float: " & s)
if s[i] == 'I' or s[i] == 'i':
if s[i+1] == 'N' or s[i+1] == 'n':
if s[i+2] == 'F' or s[i+2] == 'f':
if s[i+3] == '\0': return Inf*sign
raise newException(EInvalidValue, "invalid float: " & s)
while s[i] in {'0'..'9'}: while s[i] in {'0'..'9'}:
# Read integer part # Read integer part
flags = flags or 1 flags = flags or 1
@ -572,7 +632,7 @@ proc ParseFloat(s: string): float =
result = result / hd # this complicated way preserves precision result = result / hd # this complicated way preserves precision
# Again, read integer and fractional part # Again, read integer and fractional part
if flags == 0: if flags == 0:
raise newException(EInvalidValue, "invalid float:" & s) raise newException(EInvalidValue, "invalid float: " & s)
# Exponent? # Exponent?
if s[i] in {'e', 'E'}: if s[i] in {'e', 'E'}:
inc(i) inc(i)
@ -624,4 +684,113 @@ proc toBin*(x: BiggestInt, len: int): string =
shift = shift + 1 shift = shift + 1
mask = mask shl 1 mask = mask shl 1
proc escape*(s: string, prefix, suffix = "\""): string =
## Escapes a string `s`. This does these operations (at the same time):
## * replaces any ``\`` by ``\\``
## * replaces any ``'`` by ``\'``
## * replaces any ``"`` by ``\"``
## * replaces any other character in the set ``{'\0'..'\31', '\128'..'\255'}``
## by ``\xHH`` where ``HH`` is its hexadecimal value.
## The procedure has been designed so that its output is usable for many
## different common syntaxes. The resulting string is prefixed with
## ``prefix`` and suffixed with ``suffix``. Both may be empty strings.
result = prefix
for c in items(s):
case c
of '\0'..'\31', '\128'..'\255':
add(result, '\\')
add(result, toHex(ord(c), 2))
of '\\': add(result, "\\\\")
of '\'': add(result, "\\'")
of '\"': add(result, "\\\"")
else: add(result, c)
add(result, suffix)
proc editDistance*(a, b: string): int =
## returns the edit distance between `s` and `t`. This uses the Levenshtein
## distance algorithm with only a linear memory overhead. This implementation
## is highly optimized!
var len1 = a.len
var len2 = b.len
if len1 > len2:
# make `b` the longer string
return editDistance(b, a)
# strip common prefix:
var s = 0
while a[s] == b[s] and a[s] != '\0':
inc(s)
dec(len1)
dec(len2)
# strip common suffix:
while len1 > 0 and len2 > 0 and a[s+len1-1] == b[s+len2-1]:
dec(len1)
dec(len2)
# trivial cases:
if len1 == 0: return len2
if len2 == 0: return len1
# another special case:
if len1 == 1:
for j in s..len2-1:
if a[s] == b[j]: return len2 - 1
return len2
inc(len1)
inc(len2)
var half = len1 shr 1
# initalize first row:
#var row = cast[ptr array[0..high(int) div 8, int]](alloc(len2 * sizeof(int)))
var row: seq[int]
newSeq(row, len2)
var e = s + len2 - 1 # end marker
for i in 1..len2 - half - 1: row[i] = i
row[0] = len1 - half - 1
for i in 1 .. len1 - 1:
var char1 = a[i + s - 1]
var char2p: int
var D, x: int
var p: int
if i >= len1 - half:
# skip the upper triangle:
var offset = i - len1 + half
char2p = offset
p = offset
var c3 = row[p] + ord(char1 != b[s + char2p])
inc(p)
inc(char2p)
x = row[p] + 1
D = x
if x > c3: x = c3
row[p] = x
inc(p)
else:
p = 1
char2p = 0
D = i
x = i
if i <= half + 1:
# skip the lower triangle:
e = len2 + i - half - 2
# main:
while p <= e:
dec(D)
var c3 = D + ord(char1 != b[char2p + s])
inc(char2p)
inc(x)
if x > c3: x = c3
D = row[p] + 1
if x > D: x = D
row[p] = x
inc(p)
# lower triangle sentinel:
if i <= half:
dec(D)
var c3 = D + ord(char1 != b[char2p + s])
inc(x)
if x > c3: x = c3
row[p] = x
result = row[e]
#dealloc(row)
{.pop.} {.pop.}

View file

@ -19,7 +19,7 @@
proc fputs(c: cstring, f: TFile) {.importc: "fputs", noDecl.} proc fputs(c: cstring, f: TFile) {.importc: "fputs", noDecl.}
proc fgets(c: cstring, n: int, f: TFile): cstring {.importc: "fgets", noDecl.} proc fgets(c: cstring, n: int, f: TFile): cstring {.importc: "fgets", noDecl.}
proc fgetc(stream: TFile): int {.importc: "fgetc", nodecl.} proc fgetc(stream: TFile): int {.importc: "fgetc", nodecl.}
proc ungetc(c: int, f: TFile) {.importc: "ungetc", nodecl.} proc ungetc(c: cint, f: TFile) {.importc: "ungetc", nodecl.}
proc putc(c: Char, stream: TFile) {.importc: "putc", nodecl.} proc putc(c: Char, stream: TFile) {.importc: "putc", nodecl.}
proc fprintf(f: TFile, frmt: CString) {.importc: "fprintf", nodecl, varargs.} proc fprintf(f: TFile, frmt: CString) {.importc: "fprintf", nodecl, varargs.}
proc strlen(c: cstring): int {.importc: "strlen", nodecl.} proc strlen(c: cstring): int {.importc: "strlen", nodecl.}
@ -33,7 +33,7 @@ var
IOFBF {.importc: "_IOFBF", nodecl.}: cint IOFBF {.importc: "_IOFBF", nodecl.}: cint
IONBF {.importc: "_IONBF", nodecl.}: cint IONBF {.importc: "_IONBF", nodecl.}: cint
proc rawReadLine(f: TFile, result: var string) {.noStatic.} = proc rawReadLine(f: TFile, result: var string) =
# of course this could be optimized a bit; but IO is slow anyway... # 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 # and it was difficult to get this CORRECT with Ansi C's methods
var var
@ -41,13 +41,11 @@ proc rawReadLine(f: TFile, result: var string) {.noStatic.} =
setLen(result, 0) # reuse the buffer! setLen(result, 0) # reuse the buffer!
while True: while True:
c = fgetc(f) c = fgetc(f)
if c < 0: if c < 0'i32: break # EOF
result = nil if c == 10'i32: break # LF
break # EOF if c == 13'i32: # CR
if c == 10: break # LF
if c == 13: # CR
c = fgetc(f) # is the next char LF? c = fgetc(f) # is the next char LF?
if c != 10: ungetc(c, f) # no, put the character back if c != 10'i32: ungetc(c, f) # no, put the character back
break break
add result, chr(int(c)) add result, chr(int(c))
@ -72,7 +70,7 @@ proc readFile(filename: string): string =
proc write(f: TFile, s: string) = fputs(s, f) proc write(f: TFile, s: string) = fputs(s, f)
proc write(f: TFile, i: int) = fprintf(f, "%ld", i) proc write(f: TFile, i: int) = fprintf(f, "%ld", i)
proc write(f: TFile, b: bool) = proc write(f: TFile, b: bool) =
if b: write(f, "true") if b: write(f, "true")
else: write(f, "false") else: write(f, "false")
proc write(f: TFile, r: float) = fprintf(f, "%g", r) proc write(f: TFile, r: float) = fprintf(f, "%g", r)
@ -117,11 +115,18 @@ proc OpenFile(f: var TFile, filename: string,
result = (p != nil) result = (p != nil)
f = cast[TFile](p) f = cast[TFile](p)
if bufSize > 0: if bufSize > 0:
if setvbuf(f, nil, IOFBF, bufSize) != 0: if setvbuf(f, nil, IOFBF, bufSize) != 0'i32:
raise newException(EOutOfMemory, "out of memory") raise newException(EOutOfMemory, "out of memory")
elif bufSize == 0: elif bufSize == 0:
discard setvbuf(f, nil, IONBF, 0) discard setvbuf(f, nil, IONBF, 0)
proc fdopen(filehandle: TFileHandle, mode: cstring): TFile {.
importc: pccHack & "fdopen", header: "<stdio.h>".}
proc openFile(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
f = fdopen(filehandle, FormatOpen[mode])
result = f != nil
# C routine that is used here: # C routine that is used here:
proc fread(buf: Pointer, size, n: int, f: TFile): int {. proc fread(buf: Pointer, size, n: int, f: TFile): int {.
importc: "fread", noDecl.} importc: "fread", noDecl.}

View file

@ -16,53 +16,55 @@
# the programmer may not want # the programmer may not want
type type
TStringDesc {.importc, nodecl, final.} = object # len and space without counting the terminating zero:
len, space: int # len and space without counting the terminating zero NimStringDesc {.compilerproc, final.} = object of TGenericSeq
data: array[0..0, char] # for the '\0' character data: array[0..100_000_000, char] # for the '\0' character
mstring {.importc: "string".} = ptr TStringDesc NimString = ptr NimStringDesc
# implementation: # implementation:
proc resize(old: int): int {.inline.} = proc resize(old: int): int {.inline.} =
if old <= 0: return 1 if old <= 0: return 4
elif old < 65536: return old * 2 elif old < 65536: return old * 2
else: return old * 3 div 2 # for large arrays * 3/2 is better else: return old * 3 div 2 # for large arrays * 3/2 is better
proc cmpStrings(a, b: mstring): int {.inline, compilerProc.} = proc cmpStrings(a, b: NimString): int {.inline, compilerProc.} =
if a == b: return 0 if a == b: return 0
if a == nil: return -1 if a == nil: return -1
if b == nil: return 1 if b == nil: return 1
return c_strcmp(a.data, b.data) return c_strcmp(a.data, b.data)
proc eqStrings(a, b: mstring): bool {.inline, compilerProc.} = proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
if a == b: return true if a == b: return true
if a == nil or b == nil: return false if a == nil or b == nil: return false
return a.len == b.len and return a.len == b.len and
c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0 c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0'i32
proc rawNewString(space: int): mstring {.compilerProc.} = proc rawNewString(space: int): NimString {.compilerProc.} =
result = cast[mstring](newObj(addr(strDesc), sizeof(TStringDesc) + var s = space
space * sizeof(char))) if s < 8: s = 7
result.len = 0 result = cast[NimString](newObj(addr(strDesc), sizeof(TGenericSeq) +
result.space = space (s+1) * sizeof(char)))
result.data[0] = '\0' #result.len = 0
result.space = s
#result.data[0] = '\0'
proc mnewString(len: int): mstring {.exportc.} = proc mnewString(len: int): NimString {.exportc.} =
result = rawNewString(len) result = rawNewString(len)
result.len = len result.len = len
result.data[len] = '\0' #result.data[len] = '\0'
proc toNimStr(str: CString, len: int): mstring {.compilerProc.} = proc toNimStr(str: CString, len: int): NimString {.compilerProc.} =
result = rawNewString(len) result = rawNewString(len)
result.len = len result.len = len
c_memcpy(result.data, str, (len+1) * sizeof(Char)) c_memcpy(result.data, str, (len+1) * sizeof(Char))
result.data[len] = '\0' # IO.readline relies on this! result.data[len] = '\0' # IO.readline relies on this!
proc cstrToNimstr(str: CString): mstring {.compilerProc.} = proc cstrToNimstr(str: CString): NimString {.compilerProc.} =
return toNimstr(str, c_strlen(str)) return toNimstr(str, c_strlen(str))
proc copyString(src: mstring): mstring {.compilerProc.} = proc copyString(src: NimString): NimString {.compilerProc.} =
if src == nil: return nil if src == nil: return nil
result = rawNewString(src.space) result = rawNewString(src.space)
result.len = src.len result.len = src.len
@ -71,9 +73,7 @@ proc copyString(src: mstring): mstring {.compilerProc.} =
proc hashString(s: string): int {.compilerproc.} = proc hashString(s: string): int {.compilerproc.} =
# the compiler needs exactly the same hash function! # the compiler needs exactly the same hash function!
# this used to be used for efficient generation of string case statements # this used to be used for efficient generation of string case statements
var var h = 0
h: int
h = 0
for i in 0..Len(s)-1: for i in 0..Len(s)-1:
h = h +% Ord(s[i]) h = h +% Ord(s[i])
h = h +% h shl 10 h = h +% h shl 10
@ -91,8 +91,7 @@ proc hashString(s: string): int {.compilerproc.} =
# setLength(var s: string, newlen: int) # setLength(var s: string, newlen: int)
# {.extern: "setLengthStr", noDecl, noSideEffect.} # {.extern: "setLengthStr", noDecl, noSideEffect.}
proc copyStrLast(s: NimString, start, last: int): NimString {.exportc.} =
proc copyStrLast(s: mstring, start, last: int): mstring {.exportc.} =
var var
len: int len: int
if start >= s.len: return mnewString(0) # BUGFIX if start >= s.len: return mnewString(0) # BUGFIX
@ -105,15 +104,19 @@ proc copyStrLast(s: mstring, start, last: int): mstring {.exportc.} =
c_memcpy(result.data, addr(s.data[start]), len * sizeof(Char)) c_memcpy(result.data, addr(s.data[start]), len * sizeof(Char))
result.data[len] = '\0' result.data[len] = '\0'
proc copyStr(s: mstring, start: int): mstring {.exportc.} = proc copyStr(s: NimString, start: int): NimString {.exportc.} =
return copyStrLast(s, start, s.len-1) return copyStrLast(s, start, s.len-1)
proc addChar(s: mstring, c: char): mstring {.compilerProc.} = proc addChar(s: NimString, c: char): NimString {.compilerProc.} =
result = s result = s
if result.len >= result.space: if result.len >= result.space:
result.space = resize(result.space) result.space = resize(result.space)
result = cast[mstring](growObj(result, result = cast[NimString](growObj(result,
sizeof(TStringDesc) + result.space * sizeof(char))) sizeof(TGenericSeq) + (result.space+1) * sizeof(char)))
#var space = resize(result.space)
#result = rawNewString(space)
#copyMem(result, s, s.len * sizeof(char) + sizeof(TGenericSeq))
#result.space = space
result.data[result.len] = c result.data[result.len] = c
result.data[result.len+1] = '\0' result.data[result.len+1] = '\0'
inc(result.len) inc(result.len)
@ -149,27 +152,28 @@ proc addChar(s: mstring, c: char): mstring {.compilerProc.} =
# <generated C code> # <generated C code>
# s = rawNewString(0); # s = rawNewString(0);
proc resizeString(dest: mstring, addlen: int): mstring {.compilerproc.} = proc resizeString(dest: NimString, addlen: int): NimString {.compilerproc.} =
if dest.len + addLen + 1 <= dest.space: # BUGFIX: this is horrible! if dest.len + addLen + 1 <= dest.space: # BUGFIX: this is horrible!
result = dest result = dest
else: # slow path: else: # slow path:
var var sp = max(resize(dest.space), dest.len + addLen + 1)
sp = max(resize(dest.space), dest.len + addLen + 1) result = cast[NimString](growObj(dest, sizeof(TGenericSeq) +
result = cast[mstring](growObj(dest, sizeof(TStringDesc) + (sp+1) * sizeof(Char)))
sp * sizeof(Char)))
# DO NOT UPDATE LEN YET: dest.len = newLen
result.space = sp result.space = sp
#result = rawNewString(sp)
#copyMem(result, dest, dest.len * sizeof(char) + sizeof(TGenericSeq))
# DO NOT UPDATE LEN YET: dest.len = newLen
proc appendString(dest, src: mstring) {.compilerproc, inline.} = proc appendString(dest, src: NimString) {.compilerproc, inline.} =
c_memcpy(addr(dest.data[dest.len]), src.data, (src.len + 1) * sizeof(Char)) c_memcpy(addr(dest.data[dest.len]), src.data, (src.len + 1) * sizeof(Char))
inc(dest.len, src.len) inc(dest.len, src.len)
proc appendChar(dest: mstring, c: char) {.compilerproc, inline.} = proc appendChar(dest: NimString, c: char) {.compilerproc, inline.} =
dest.data[dest.len] = c dest.data[dest.len] = c
dest.data[dest.len+1] = '\0' dest.data[dest.len+1] = '\0'
inc(dest.len) inc(dest.len)
proc setLengthStr(s: mstring, newLen: int): mstring {.compilerProc.} = proc setLengthStr(s: NimString, newLen: int): NimString {.compilerProc.} =
var n = max(newLen, 0) var n = max(newLen, 0)
if n <= s.space: if n <= s.space:
result = s result = s
@ -187,37 +191,54 @@ proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
# add seq x generates: # add seq x generates:
# seq = incrSeq(seq, sizeof(x)); # seq = incrSeq(seq, sizeof(x));
# seq[seq->len-1] = x; # seq[seq->len-1] = x;
result = seq when false:
if result.len >= result.space: # broken version:
var result = seq
s: TAddress if result.len >= result.space:
result.space = resize(result.space) var s = resize(result.space)
result = cast[PGenericSeq](growObj(result, elemSize * result.space + result = cast[PGenericSeq](newSeq(extGetCellType(seq), s))
GenericSeqSize)) genericSeqAssign(result, seq, XXX)
# set new elements to zero: #copyMem(result, seq, seq.len * elemSize + GenericSeqSize)
s = cast[TAddress](result) inc(result.len)
zeroMem(cast[pointer](s + GenericSeqSize + (result.len * elemSize)), else:
(result.space - result.len) * elemSize) result = seq
# for i in len .. space-1: if result.len >= result.space:
# seq->data[i] = 0 result.space = resize(result.space)
inc(result.len) result = cast[PGenericSeq](growObj(result, elemSize * result.space +
GenericSeqSize))
# set new elements to zero:
#var 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 {. proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
compilerProc.} = compilerProc.} =
result = seq when false:
if result.space < newLen: # broken version:
var result = seq
s: TAddress if result.space < newLen:
result.space = max(resize(result.space), newLen) var s = max(resize(result.space), newLen)
result = cast[PGenericSeq](growObj(result, elemSize * result.space + result = cast[PGenericSeq](newSeq(extGetCellType(seq), s))
GenericSeqSize)) result.len = newLen
# set new elements to zero (needed for GC): else:
s = cast[TAddress](result) result = seq
zeroMem(cast[pointer](s + GenericSeqSize + (result.len * elemSize)), if result.space < newLen:
(result.space - result.len) * elemSize) result.space = max(resize(result.space), newLen)
# Else: We could decref references, if we had type information here :-( result = cast[PGenericSeq](growObj(result, elemSize * result.space +
# However, this does not happen often GenericSeqSize))
result.len = newLen elif newLen < result.len:
# we need to decref here, otherwise the GC leaks!
for i in newLen..result.len-1:
forAllChildrenAux(cast[pointer](cast[TAddress](result) +%
GenericSeqSize +% (i*%elemSize)),
extGetCellType(result).base, waZctDecRef)
# and set the memory to nil:
zeroMem(cast[pointer](cast[TAddress](result) +% GenericSeqSize +%
(newLen*%elemSize)), (result.len-%newLen) *% elemSize)
result.len = newLen
# --------------- other string routines ---------------------------------- # --------------- other string routines ----------------------------------
proc nimIntToStr(x: int): string {.compilerproc.} = proc nimIntToStr(x: int): string {.compilerproc.} =

View file

@ -19,6 +19,30 @@
{.push hints: off.} {.push hints: off.}
type
int* {.magic: Int.} ## default integer type; bitwidth depends on
## architecture, but is always the same as a pointer
int8* {.magic: Int8.} ## signed 8 bit integer type
int16* {.magic: Int16.} ## signed 16 bit integer type
int32* {.magic: Int32.} ## signed 32 bit integer type
int64* {.magic: Int64.} ## signed 64 bit integer type
float* {.magic: Float.} ## default floating point type
float32* {.magic: Float32.} ## 32 bit floating point type
float64* {.magic: Float64.} ## 64 bit floating point type
type # we need to start a new type section here, so that ``0`` can have a type
bool* {.magic: Bool.} = enum ## built-in boolean type
false = 0, true = 1
type
char* {.magic: Char.} ## built-in 8 bit character type (unsigned)
string* {.magic: String.} ## built-in string type
cstring* {.magic: Cstring.} ## built-in cstring (*compatible string*) type
pointer* {.magic: Pointer.} ## built-in pointer type
TAnyEnum {.magic: AnyEnum.}
type
`nil` {.magic: "Nil".}
proc defined*[T] (x: T): bool {.magic: "Defined", noSideEffect.} proc defined*[T] (x: T): bool {.magic: "Defined", noSideEffect.}
## Special comile-time procedure that checks whether `x` is ## Special comile-time procedure that checks whether `x` is
## defined. `x` has to be an identifier or a qualified identifier. ## defined. `x` has to be an identifier or a qualified identifier.
@ -30,23 +54,6 @@ proc defined*[T] (x: T): bool {.magic: "Defined", noSideEffect.}
## # provide our own toUpper proc here, because strutils is ## # provide our own toUpper proc here, because strutils is
## # missing it. ## # missing it.
when defined(macosX):
{.define: useDL.}
when defined(linux):
{.define: useDL.}
when defined(unix):
# This may seem strange, but we cannot write "when not defined"
# here, because ``not`` has not been defined yet.
{.hint: "unix is defined".}
else:
{.define: useDL.}
{.hint: "unix is not defined".}
# use Doug Lea's memory allocator; you can undefine it if you
# know that your system uses this library anyway (smaller code) or if
# your malloc() doesn't suck (most systems use it anyway)
# these require compiler magic: # these require compiler magic:
proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.} proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
## Boolean not; returns true iff ``x == false``. ## Boolean not; returns true iff ``x == false``.
@ -98,9 +105,10 @@ type
## is an int type ranging from one to the maximum value ## is an int type ranging from one to the maximum value
## of an int. This type is often useful for documentation and debugging. ## of an int. This type is often useful for documentation and debugging.
TObject* = object ## the root of Nimrod's object hierarchy. Objects should TObject* {.exportc: "TNimObject".} =
## inherit from TObject or one of its descendants. However, object ## the root of Nimrod's object hierarchy. Objects should
## objects that have no ancestor are allowed. ## inherit from TObject or one of its descendants. However,
## objects that have no ancestor are allowed.
PObject* = ref TObject ## reference to TObject PObject* = ref TObject ## reference to TObject
E_Base* {.compilerproc.} = object of TObject ## base exception class; E_Base* {.compilerproc.} = object of TObject ## base exception class;
@ -206,8 +214,14 @@ proc dec*[T](x: var T, y = 1) {.magic: "Dec".}
## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a ## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a
## short notation for: ``x = pred(x, y)``. ## short notation for: ``x = pred(x, y)``.
proc newSeq*[T](s: var seq[T], len: int) {.magic: "NewSeq".}
## creates a new sequence of type ``seq[T]`` with length ``len``.
## This is equivalent to ``s = []; setlen(s, len)``, but more
## efficient since no relocation is needed.
proc len*[T](x: openarray[T]): int {.magic: "LengthOpenArray", noSideEffect.} proc len*[T](x: openarray[T]): int {.magic: "LengthOpenArray", noSideEffect.}
proc len*(x: string): int {.magic: "LengthStr", noSideEffect.} proc len*(x: string): int {.magic: "LengthStr", noSideEffect.}
proc len*(x: cstring): int {.magic: "LengthStr", noSideEffect.}
proc len*[I, T](x: array[I, T]): int {.magic: "LengthArray", noSideEffect.} proc len*[I, T](x: array[I, T]): int {.magic: "LengthArray", noSideEffect.}
proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.} proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.}
## returns the length of an array, a sequence or a string. ## returns the length of an array, a sequence or a string.
@ -236,79 +250,241 @@ proc chr*(u: range[0..255]): char {.magic: "Chr", noSideEffect.}
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# built-in operators # built-in operators
proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect.}
## zero extends a smaller integer type to ``int``. This treats `x` as
## unsigned.
proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect.}
## zero extends a smaller integer type to ``int``. This treats `x` as
## unsigned.
proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned.
proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned.
proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned.
proc ze64*(x: int): int64 {.magic: "ZeIToI64", noDecl, noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned. Does nothing if the size of an ``int`` is the same as ``int64``.
## (This is the case on 64 bit processors.)
proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect.}
## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
## from `x`.
proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect.}
## treats `x` as unsigned and converts it to an ``int16`` by taking the last
## 16 bits from `x`.
proc toU32*(x: int64): int32 {.magic: "ToU32", noSideEffect.}
## treats `x` as unsigned and converts it to an ``int32`` by taking the
## last 32 bits from `x`.
# integer calculations: # integer calculations:
proc `+` *(x: int): int {.magic: "UnaryPlusI", noSideEffect.} proc `+` *(x: int): int {.magic: "UnaryPlusI", noSideEffect.}
proc `+` *(x: int8): int8 {.magic: "UnaryPlusI", noSideEffect.}
proc `+` *(x: int16): int16 {.magic: "UnaryPlusI", noSideEffect.}
proc `+` *(x: int32): int32 {.magic: "UnaryPlusI", noSideEffect.}
proc `+` *(x: int64): int64 {.magic: "UnaryPlusI64", noSideEffect.}
## Unary `+` operator for an integer. Has no effect. ## Unary `+` operator for an integer. Has no effect.
proc `-` *(x: int): int {.magic: "UnaryMinusI", noSideEffect.} proc `-` *(x: int): int {.magic: "UnaryMinusI", noSideEffect.}
proc `-` *(x: int8): int8 {.magic: "UnaryMinusI", noSideEffect.}
proc `-` *(x: int16): int16 {.magic: "UnaryMinusI", noSideEffect.}
proc `-` *(x: int32): int32 {.magic: "UnaryMinusI", noSideEffect.}
proc `-` *(x: int64): int64 {.magic: "UnaryMinusI64", noSideEffect.}
## Unary `-` operator for an integer. Negates `x`. ## Unary `-` operator for an integer. Negates `x`.
proc `not` *(x: int): int {.magic: "BitnotI", noSideEffect.} proc `not` *(x: int): int {.magic: "BitnotI", noSideEffect.}
proc `not` *(x: int8): int8 {.magic: "BitnotI", noSideEffect.}
proc `not` *(x: int16): int16 {.magic: "BitnotI", noSideEffect.}
proc `not` *(x: int32): int32 {.magic: "BitnotI", noSideEffect.}
proc `not` *(x: int64): int64 {.magic: "BitnotI64", noSideEffect.}
## computes the `bitwise complement` of the integer `x`. ## computes the `bitwise complement` of the integer `x`.
proc `+` *(x, y: int): int {.magic: "AddI", noSideEffect.} proc `+` *(x, y: int): int {.magic: "AddI", noSideEffect.}
proc `+` *(x, y: int8): int8 {.magic: "AddI", noSideEffect.}
proc `+` *(x, y: int16): int16 {.magic: "AddI", noSideEffect.}
proc `+` *(x, y: int32): int32 {.magic: "AddI", noSideEffect.}
proc `+` *(x, y: int64): int64 {.magic: "AddI64", noSideEffect.}
## Binary `+` operator for an integer.
proc `-` *(x, y: int): int {.magic: "SubI", noSideEffect.} proc `-` *(x, y: int): int {.magic: "SubI", noSideEffect.}
proc `-` *(x, y: int8): int8 {.magic: "SubI", noSideEffect.}
proc `-` *(x, y: int16): int16 {.magic: "SubI", noSideEffect.}
proc `-` *(x, y: int32): int32 {.magic: "SubI", noSideEffect.}
proc `-` *(x, y: int64): int64 {.magic: "SubI64", noSideEffect.}
## Binary `-` operator for an integer.
proc `*` *(x, y: int): int {.magic: "MulI", noSideEffect.} proc `*` *(x, y: int): int {.magic: "MulI", noSideEffect.}
proc `*` *(x, y: int8): int8 {.magic: "MulI", noSideEffect.}
proc `*` *(x, y: int16): int16 {.magic: "MulI", noSideEffect.}
proc `*` *(x, y: int32): int32 {.magic: "MulI", noSideEffect.}
proc `*` *(x, y: int64): int64 {.magic: "MulI64", noSideEffect.}
## Binary `*` operator for an integer.
proc `div` *(x, y: int): int {.magic: "DivI", noSideEffect.} proc `div` *(x, y: int): int {.magic: "DivI", noSideEffect.}
proc `div` *(x, y: int8): int8 {.magic: "DivI", noSideEffect.}
proc `div` *(x, y: int16): int16 {.magic: "DivI", noSideEffect.}
proc `div` *(x, y: int32): int32 {.magic: "DivI", noSideEffect.}
proc `div` *(x, y: int64): int64 {.magic: "DivI64", noSideEffect.}
## computes the integer division. This is roughly the same as ## computes the integer division. This is roughly the same as
## ``floor(x/y)``. ## ``floor(x/y)``.
proc `mod` *(x, y: int): int {.magic: "ModI", noSideEffect.} proc `mod` *(x, y: int): int {.magic: "ModI", noSideEffect.}
proc `mod` *(x, y: int8): int8 {.magic: "ModI", noSideEffect.}
proc `mod` *(x, y: int16): int16 {.magic: "ModI", noSideEffect.}
proc `mod` *(x, y: int32): int32 {.magic: "ModI", noSideEffect.}
proc `mod` *(x, y: int64): int64 {.magic: "ModI64", noSideEffect.}
## computes the integer modulo operation. This is the same as ## computes the integer modulo operation. This is the same as
## ``x - (x div y) * y``. ## ``x - (x div y) * y``.
proc `shr` *(x, y: int): int {.magic: "ShrI", noSideEffect.} proc `shr` *(x, y: int): int {.magic: "ShrI", noSideEffect.}
## computes the `shift right` operation of `x` and `y`. proc `shr` *(x, y: int8): int8 {.magic: "ShrI", noSideEffect.}
proc `shl` *(x, y: int): int {.magic: "ShlI", noSideEffect.} proc `shr` *(x, y: int16): int16 {.magic: "ShrI", noSideEffect.}
## computes the `shift left` operation of `x` and `y`. proc `shr` *(x, y: int32): int32 {.magic: "ShrI", noSideEffect.}
proc `and` *(x, y: int): int {.magic: "BitandI", noSideEffect.}
## computes the `bitwise and` of numbers `x` and `y`.
proc `or` *(x, y: int): int {.magic: "BitorI", noSideEffect.}
## computes the `bitwise or` of numbers `x` and `y`.
proc `xor` *(x, y: int): int {.magic: "BitxorI", noSideEffect.}
## computes the `bitwise xor` of numbers `x` and `y`.
proc `==` *(x, y: int): bool {.magic: "EqI", noSideEffect.}
proc `<=` *(x, y: int): bool {.magic: "LeI", noSideEffect.}
proc `<` *(x, y: int): bool {.magic: "LtI", noSideEffect.}
proc abs*(x: int): int {.magic: "AbsI", noSideEffect.}
proc min*(x, y: int): int {.magic: "MinI", noSideEffect.}
proc max*(x, y: int): int {.magic: "MaxI", noSideEffect.}
proc `+` *(x: int64): int64 {.magic: "UnaryPlusI64", noSideEffect.}
proc `-` *(x: int64): int64 {.magic: "UnaryMinusI64", noSideEffect.}
proc `not` *(x: int64): int64 {.magic: "BitnotI64", noSideEffect.}
## computes the `bitwise complement` of the integer `x`.
proc `+` *(x, y: int64): int64 {.magic: "AddI64", noSideEffect.}
## Unary `+` operator for an integer. Has no effect.
proc `-` *(x, y: int64): int64 {.magic: "SubI64", noSideEffect.}
## Unary `-` operator for an int64. Negates `x`.
proc `*` *(x, y: int64): int64 {.magic: "MulI64", noSideEffect.}
proc `div` *(x, y: int64): int64 {.magic: "DivI64", noSideEffect.}
## computes the integer division. This is roughly the same as
## ``floor(x/y)``.
proc `mod` *(x, y: int64): int64 {.magic: "ModI64", noSideEffect.}
## computes the integer modulo operation. This is the same as
## ``x - (x div y) * y``.
proc `shr` *(x, y: int64): int64 {.magic: "ShrI64", noSideEffect.} proc `shr` *(x, y: int64): int64 {.magic: "ShrI64", noSideEffect.}
## computes the `shift right` operation of `x` and `y`. ## computes the `shift right` operation of `x` and `y`.
proc `shl` *(x, y: int): int {.magic: "ShlI", noSideEffect.}
proc `shl` *(x, y: int8): int8 {.magic: "ShlI", noSideEffect.}
proc `shl` *(x, y: int16): int16 {.magic: "ShlI", noSideEffect.}
proc `shl` *(x, y: int32): int32 {.magic: "ShlI", noSideEffect.}
proc `shl` *(x, y: int64): int64 {.magic: "ShlI64", noSideEffect.} proc `shl` *(x, y: int64): int64 {.magic: "ShlI64", noSideEffect.}
## computes the `shift left` operation of `x` and `y`. ## computes the `shift left` operation of `x` and `y`.
proc `and` *(x, y: int): int {.magic: "BitandI", noSideEffect.}
proc `and` *(x, y: int8): int8 {.magic: "BitandI", noSideEffect.}
proc `and` *(x, y: int16): int16 {.magic: "BitandI", noSideEffect.}
proc `and` *(x, y: int32): int32 {.magic: "BitandI", noSideEffect.}
proc `and` *(x, y: int64): int64 {.magic: "BitandI64", noSideEffect.} proc `and` *(x, y: int64): int64 {.magic: "BitandI64", noSideEffect.}
## computes the `bitwise and` of numbers `x` and `y`. ## computes the `bitwise and` of numbers `x` and `y`.
proc `or` *(x, y: int): int {.magic: "BitorI", noSideEffect.}
proc `or` *(x, y: int8): int8 {.magic: "BitorI", noSideEffect.}
proc `or` *(x, y: int16): int16 {.magic: "BitorI", noSideEffect.}
proc `or` *(x, y: int32): int32 {.magic: "BitorI", noSideEffect.}
proc `or` *(x, y: int64): int64 {.magic: "BitorI64", noSideEffect.} proc `or` *(x, y: int64): int64 {.magic: "BitorI64", noSideEffect.}
## computes the `bitwise or` of numbers `x` and `y`. ## computes the `bitwise or` of numbers `x` and `y`.
proc `xor` *(x, y: int): int {.magic: "BitxorI", noSideEffect.}
proc `xor` *(x, y: int8): int8 {.magic: "BitxorI", noSideEffect.}
proc `xor` *(x, y: int16): int16 {.magic: "BitxorI", noSideEffect.}
proc `xor` *(x, y: int32): int32 {.magic: "BitxorI", noSideEffect.}
proc `xor` *(x, y: int64): int64 {.magic: "BitxorI64", noSideEffect.} proc `xor` *(x, y: int64): int64 {.magic: "BitxorI64", noSideEffect.}
## computes the `bitwise xor` of numbers `x` and `y`. ## computes the `bitwise xor` of numbers `x` and `y`.
proc `==` *(x, y: int): bool {.magic: "EqI", noSideEffect.}
proc `==` *(x, y: int8): bool {.magic: "EqI", noSideEffect.}
proc `==` *(x, y: int16): bool {.magic: "EqI", noSideEffect.}
proc `==` *(x, y: int32): bool {.magic: "EqI", noSideEffect.}
proc `==` *(x, y: int64): bool {.magic: "EqI64", noSideEffect.} proc `==` *(x, y: int64): bool {.magic: "EqI64", noSideEffect.}
proc `<=` *(x, y: int64): bool {.magic: "LeI64", noSideEffect.} ## Compares two integers for equality.
proc `<` *(x, y: int64): bool {.magic: "LtI64", noSideEffect.}
proc abs*(x: int64): int64 {.magic: "AbsI64", noSideEffect.}
proc min*(x, y: int64): int64 {.magic: "MinI64", noSideEffect.}
proc max*(x, y: int64): int64 {.magic: "MaxI64", noSideEffect.}
# same for floating point: proc `<=` *(x, y: int): bool {.magic: "LeI", noSideEffect.}
proc `<=` *(x, y: int8): bool {.magic: "LeI", noSideEffect.}
proc `<=` *(x, y: int16): bool {.magic: "LeI", noSideEffect.}
proc `<=` *(x, y: int32): bool {.magic: "LeI", noSideEffect.}
proc `<=` *(x, y: int64): bool {.magic: "LeI64", noSideEffect.}
## Returns true iff `x` is less than or equal to `y`.
proc `<` *(x, y: int): bool {.magic: "LtI", noSideEffect.}
proc `<` *(x, y: int8): bool {.magic: "LtI", noSideEffect.}
proc `<` *(x, y: int16): bool {.magic: "LtI", noSideEffect.}
proc `<` *(x, y: int32): bool {.magic: "LtI", noSideEffect.}
proc `<` *(x, y: int64): bool {.magic: "LtI64", noSideEffect.}
## Returns true iff `x` is less than `y`.
proc abs*(x: int): int {.magic: "AbsI", noSideEffect.}
proc abs*(x: int8): int8 {.magic: "AbsI", noSideEffect.}
proc abs*(x: int16): int16 {.magic: "AbsI", noSideEffect.}
proc abs*(x: int32): int32 {.magic: "AbsI", noSideEffect.}
proc abs*(x: int64): int64 {.magic: "AbsI64", noSideEffect.}
## returns the absolute value of `x`. If `x` is ``low(x)`` (that is
## -MININT for its type), an overflow exception is thrown (if overflow
## checking is turned on).
proc min*(x, y: int): int {.magic: "MinI", noSideEffect.}
proc min*(x, y: int8): int8 {.magic: "MinI", noSideEffect.}
proc min*(x, y: int16): int16 {.magic: "MinI", noSideEffect.}
proc min*(x, y: int32): int32 {.magic: "MinI", noSideEffect.}
proc min*(x, y: int64): int64 {.magic: "MinI64", noSideEffect.}
## The minimum value of two integers.
proc max*(x, y: int): int {.magic: "MaxI", noSideEffect.}
proc max*(x, y: int8): int8 {.magic: "MaxI", noSideEffect.}
proc max*(x, y: int16): int16 {.magic: "MaxI", noSideEffect.}
proc max*(x, y: int32): int32 {.magic: "MaxI", noSideEffect.}
proc max*(x, y: int64): int64 {.magic: "MaxI64", noSideEffect.}
## The maximum value of two integers.
proc `+%` *(x, y: int): int {.magic: "AddU", noSideEffect.}
proc `+%` *(x, y: int8): int8 {.magic: "AddU", noSideEffect.}
proc `+%` *(x, y: int16): int16 {.magic: "AddU", noSideEffect.}
proc `+%` *(x, y: int32): int32 {.magic: "AddU", noSideEffect.}
proc `+%` *(x, y: int64): int64 {.magic: "AddU64", noSideEffect.}
## treats `x` and `y` as unsigned and adds them. The result is truncated to
## fit into the result. This implements modulo arithmetic. No overflow
## errors are possible.
proc `-%` *(x, y: int): int {.magic: "SubU", noSideEffect.}
proc `-%` *(x, y: int8): int8 {.magic: "SubU", noSideEffect.}
proc `-%` *(x, y: int16): int16 {.magic: "SubU", noSideEffect.}
proc `-%` *(x, y: int32): int32 {.magic: "SubU", noSideEffect.}
proc `-%` *(x, y: int64): int64 {.magic: "SubU64", noSideEffect.}
## treats `x` and `y` as unsigned and subtracts them. The result is
## truncated to fit into the result. This implements modulo arithmetic.
## No overflow errors are possible.
proc `*%` *(x, y: int): int {.magic: "MulU", noSideEffect.}
proc `*%` *(x, y: int8): int8 {.magic: "MulU", noSideEffect.}
proc `*%` *(x, y: int16): int16 {.magic: "MulU", noSideEffect.}
proc `*%` *(x, y: int32): int32 {.magic: "MulU", noSideEffect.}
proc `*%` *(x, y: int64): int64 {.magic: "MulU64", noSideEffect.}
## treats `x` and `y` as unsigned and multiplies them. The result is
## truncated to fit into the result. This implements modulo arithmetic.
## No overflow errors are possible.
proc `/%` *(x, y: int): int {.magic: "DivU", noSideEffect.}
proc `/%` *(x, y: int8): int8 {.magic: "DivU", noSideEffect.}
proc `/%` *(x, y: int16): int16 {.magic: "DivU", noSideEffect.}
proc `/%` *(x, y: int32): int32 {.magic: "DivU", noSideEffect.}
proc `/%` *(x, y: int64): int64 {.magic: "DivU64", noSideEffect.}
## treats `x` and `y` as unsigned and divides them. The result is
## truncated to fit into the result. This implements modulo arithmetic.
## No overflow errors are possible.
proc `%%` *(x, y: int): int {.magic: "ModU", noSideEffect.}
proc `%%` *(x, y: int8): int8 {.magic: "ModU", noSideEffect.}
proc `%%` *(x, y: int16): int16 {.magic: "ModU", noSideEffect.}
proc `%%` *(x, y: int32): int32 {.magic: "ModU", noSideEffect.}
proc `%%` *(x, y: int64): int64 {.magic: "ModU64", noSideEffect.}
## treats `x` and `y` as unsigned and compute the modulo of `x` and `y`.
## The result is truncated to fit into the result.
## This implements modulo arithmetic.
## No overflow errors are possible.
proc `<=%` *(x, y: int): bool {.magic: "LeU", noSideEffect.}
proc `<=%` *(x, y: int8): bool {.magic: "LeU", noSideEffect.}
proc `<=%` *(x, y: int16): bool {.magic: "LeU", noSideEffect.}
proc `<=%` *(x, y: int32): bool {.magic: "LeU", noSideEffect.}
proc `<=%` *(x, y: int64): bool {.magic: "LeU64", noSideEffect.}
## treats `x` and `y` as unsigned and compares them.
## Returns true iff ``unsigned(x) <= unsigned(y)``.
proc `<%` *(x, y: int): bool {.magic: "LtU", noSideEffect.}
proc `<%` *(x, y: int8): bool {.magic: "LtU", noSideEffect.}
proc `<%` *(x, y: int16): bool {.magic: "LtU", noSideEffect.}
proc `<%` *(x, y: int32): bool {.magic: "LtU", noSideEffect.}
proc `<%` *(x, y: int64): bool {.magic: "LtU64", noSideEffect.}
## treats `x` and `y` as unsigned and compares them.
## Returns true iff ``unsigned(x) < unsigned(y)``.
# floating point operations:
proc `+` *(x: float): float {.magic: "UnaryPlusF64", noSideEffect.} proc `+` *(x: float): float {.magic: "UnaryPlusF64", noSideEffect.}
proc `-` *(x: float): float {.magic: "UnaryMinusF64", noSideEffect.} proc `-` *(x: float): float {.magic: "UnaryMinusF64", noSideEffect.}
proc `+` *(x, y: float): float {.magic: "AddF64", noSideEffect.} proc `+` *(x, y: float): float {.magic: "AddF64", noSideEffect.}
@ -423,11 +599,21 @@ proc cmp*[T](x, y: T): int =
proc cmp*(x, y: string): int {.noSideEffect.} proc cmp*(x, y: string): int {.noSideEffect.}
## Compare proc for strings. More efficient than the generic version. ## Compare proc for strings. More efficient than the generic version.
proc `@` * [IDX, T](a: array[IDX, T]): seq[T] {.
magic: "ArrToSeq", nosideeffect.}
## turns an array into a sequence. This most often useful for constructing
## sequences with the array constructor: ``@[1, 2, 3]`` has the type
## ``seq[int]``, while ``[1, 2, 3]`` has the type ``array[0..2, int]``.
# concat operator: # concat operator:
proc `&` * (x: string, y: char): string {.magic: "ConStrStr", noSideEffect.} proc `&` * (x: string, y: char): string {.
proc `&` * (x: char, y: char): string {.magic: "ConStrStr", noSideEffect.} magic: "ConStrStr", noSideEffect, merge.}
proc `&` * (x, y: string): string {.magic: "ConStrStr", noSideEffect.} proc `&` * (x: char, y: char): string {.
proc `&` * (x: char, y: string): string {.magic: "ConStrStr", noSideEffect.} magic: "ConStrStr", noSideEffect, merge.}
proc `&` * (x, y: string): string {.
magic: "ConStrStr", noSideEffect, merge.}
proc `&` * (x: char, y: string): string {.
magic: "ConStrStr", noSideEffect, merge.}
## is the `concatenation operator`. It concatenates `x` and `y`. ## is the `concatenation operator`. It concatenates `x` and `y`.
proc add * (x: var string, y: char) {.magic: "AppendStrCh".} proc add * (x: var string, y: char) {.magic: "AppendStrCh".}
@ -466,7 +652,7 @@ proc repr*[T](x: T): string {.magic: "Repr", noSideEffect.}
type type
TAddress* = int TAddress* = int
## is the signed integer type that should be used for converting ## is the signed integer type that should be used for converting
## pointers to integer addresses. ## pointers to integer addresses for readability.
type type
BiggestInt* = int64 BiggestInt* = int64
@ -500,7 +686,7 @@ type # these work for most platforms:
## This is the same as the type ``long double`` in *C*. ## This is the same as the type ``long double`` in *C*.
## This C type is not supported by Nimrod's code generator ## This C type is not supported by Nimrod's code generator
cstringArray* {.importc: "char**", nodecl.} = array [0..50_000, cstring] cstringArray* {.importc: "char**", nodecl.} = ptr array [0..50_000, cstring]
## This is the same as the type ``char**`` in *C*. ## This is the same as the type ``char**`` in *C*.
TEndian* = enum ## is a type describing the endianness of a processor. TEndian* = enum ## is a type describing the endianness of a processor.
@ -512,50 +698,49 @@ type # these work for most platforms:
PInt32* = ptr Int32 ## an alias for ``ptr int32`` PInt32* = ptr Int32 ## an alias for ``ptr int32``
const const
QuitSuccess* = 0 isMainModule* {.magic: "IsMainModule".}: bool = false
## is the value that should be passed to ``quit`` to indicate ## is true only when accessed in the main module. This works thanks to
## success. ## compiler magic. It is useful to embed testing code in a module.
QuitFailure* = 1
## is the value that should be passed to ``quit`` to indicate
## failure.
CompileDate* {.magic: "CompileDate"}: string = "0000-00-00" CompileDate* {.magic: "CompileDate"}: string = "0000-00-00"
## is the date of compilation as a string of the form ## is the date of compilation as a string of the form
## ``YYYY-MM-DD``. ## ``YYYY-MM-DD``. This works thanks to compiler magic.
CompileTime* {.magic: "CompileTime"}: string = "00:00:00" CompileTime* {.magic: "CompileTime"}: string = "00:00:00"
## is the time of compilation as a string of the form ## is the time of compilation as a string of the form
## ``HH:MM:SS``. ## ``HH:MM:SS``. This works thanks to compiler magic.
NimrodVersion* {.magic: "NimrodVersion"}: string = "0.0.0" NimrodVersion* {.magic: "NimrodVersion"}: string = "0.0.0"
## is the version of Nimrod as a string. ## is the version of Nimrod as a string.
## This works thanks to compiler magic.
NimrodMajor* {.magic: "NimrodMajor"}: int = 0 NimrodMajor* {.magic: "NimrodMajor"}: int = 0
## is the major number of Nimrod's version. ## is the major number of Nimrod's version.
## This works thanks to compiler magic.
NimrodMinor* {.magic: "NimrodMinor"}: int = 0 NimrodMinor* {.magic: "NimrodMinor"}: int = 0
## is the minor number of Nimrod's version. ## is the minor number of Nimrod's version.
## This works thanks to compiler magic.
NimrodPatch* {.magic: "NimrodPatch"}: int = 0 NimrodPatch* {.magic: "NimrodPatch"}: int = 0
## is the patch number of Nimrod's version. ## is the patch number of Nimrod's version.
## This works thanks to compiler magic.
cpuEndian* {.magic: "CpuEndian"}: TEndian = littleEndian cpuEndian* {.magic: "CpuEndian"}: TEndian = littleEndian
## is the endianness of the target CPU. This is a valuable information ## is the endianness of the target CPU. This is a valuable piece of
## for low-level code only. ## information for low-level code only. This works thanks to compiler magic.
proc toFloat*(i: int): float {. proc toFloat*(i: int): float {.
magic: "ToFloat", noSideEffect, importc: "toFloat".} magic: "ToFloat", noSideEffect, importc: "toFloat".}
## converts an integer `i` into a ``float``. If the conversion ## converts an integer `i` into a ``float``. If the conversion
## fails, `EInvalidValue` is raised. Note that on most platforms the ## fails, `EInvalidValue` is raised. However, on most platforms the
## conversion cannot fail, however. ## conversion cannot fail.
proc toBiggestFloat*(i: biggestint): biggestfloat {. proc toBiggestFloat*(i: biggestint): biggestfloat {.
magic: "ToBiggestFloat", noSideEffect, importc: "toBiggestFloat".} magic: "ToBiggestFloat", noSideEffect, importc: "toBiggestFloat".}
## converts an biggestint `i` into a ``biggestfloat``. If the conversion ## converts an biggestint `i` into a ``biggestfloat``. If the conversion
## fails, `EInvalidValue` is raised. Note that on most platforms the ## fails, `EInvalidValue` is raised. However, on most platforms the
## conversion cannot fail, however. ## conversion cannot fail.
proc toInt*(f: float): int {. proc toInt*(f: float): int {.
magic: "ToInt", noSideEffect, importc: "toInt".} magic: "ToInt", noSideEffect, importc: "toInt".}
@ -569,15 +754,6 @@ proc toBiggestInt*(f: biggestfloat): biggestint {.
## rounds `f` if it does not contain an integer value. If the conversion ## rounds `f` if it does not contain an integer value. If the conversion
## fails (because `f` is infinite for example), `EInvalidValue` is raised. ## fails (because `f` is infinite for example), `EInvalidValue` is raised.
proc quit*(errorcode: int = QuitSuccess) {.
magic: "Exit", importc: "exit", noDecl, noReturn.}
## stops the program immediately; before stopping the program the
## "quit procedures" are called in the opposite order they were added
## with ``addQuitProc``. ``quit`` never returns and ignores any
## exception that may have been raised by the quit procedures.
## It does *not* call the garbage collector to free all the memory,
## unless a quit procedure calls ``GC_collect``.
proc addQuitProc*(QuitProc: proc {.noconv.}) {.importc: "atexit", nodecl.} proc addQuitProc*(QuitProc: proc {.noconv.}) {.importc: "atexit", nodecl.}
## adds/registers a quit procedure. Each call to ``addQuitProc`` ## adds/registers a quit procedure. Each call to ``addQuitProc``
## registers another quit procedure. Up to 30 procedures can be ## registers another quit procedure. Up to 30 procedures can be
@ -636,33 +812,29 @@ proc equalMem*(a, b: Pointer, size: int): bool {.
## *unsafe*. ## *unsafe*.
const const
mallocHeader = if defined(useDL): "dlmalloc.h" else: "<stdlib.h>" mallocHeader = "<stdlib.h>"
proc alloc*(size: int): pointer {. proc alloc*(size: int): pointer {.
importc: if defined(useDL): "dlmalloc" else: "malloc", importc: "malloc", header: mallocHeader, noconv.}
header: mallocHeader, noconv.}
## allocates a new memory block with at least ``size`` bytes. The ## allocates a new memory block with at least ``size`` bytes. The
## block has to be freed with ``realloc(block, 0)`` or ## block has to be freed with ``realloc(block, 0)`` or
## ``dealloc(block)``. The block is not initialized, so reading ## ``dealloc(block)``. The block is not initialized, so reading
## from it before writing to it is undefined behaviour! ## from it before writing to it is undefined behaviour!
proc alloc0*(size: int): pointer {. proc alloc0*(size: int): pointer {.
importc: if defined(useDL): "DL_ALLOC_0" else: "ALLOC_0", importc: "ALLOC_0", header: mallocHeader, noconv.}
header: mallocHeader, noconv.}
## allocates a new memory block with at least ``size`` bytes. The ## allocates a new memory block with at least ``size`` bytes. The
## block has to be freed with ``realloc(block, 0)`` or ## block has to be freed with ``realloc(block, 0)`` or
## ``dealloc(block)``. The block is initialized with all bytes ## ``dealloc(block)``. The block is initialized with all bytes
## containing zero, so it is somewhat safer than ``alloc``. ## containing zero, so it is somewhat safer than ``alloc``.
proc realloc*(p: Pointer, newsize: int): pointer {. proc realloc*(p: Pointer, newsize: int): pointer {.
importc: if defined(useDL): "dlrealloc" else: "realloc", importc: "realloc", header: mallocHeader, noconv.}
header: mallocHeader, noconv.}
## grows or shrinks a given memory block. If p is **nil** then a new ## grows or shrinks a given memory block. If p is **nil** then a new
## memory block is returned. In either way the block has at least ## memory block is returned. In either way the block has at least
## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil** ## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil**
## ``realloc`` calls ``dealloc(p)``. In other cases the block has to ## ``realloc`` calls ``dealloc(p)``. In other cases the block has to
## be freed with ``dealloc``. ## be freed with ``dealloc``.
proc dealloc*(p: Pointer) {. proc dealloc*(p: Pointer) {.
importc: if defined(useDL): "dlfree" else: "free", importc: "free", header: mallocHeader, noconv.}
header: mallocHeader, noconv.}
## frees the memory allocated with ``alloc``, ``alloc0`` or ## frees the memory allocated with ``alloc``, ``alloc0`` or
## ``realloc``. This procedure is dangerous! If one forgets to ## ``realloc``. This procedure is dangerous! If one forgets to
## free the memory a leak occurs; if one tries to access freed ## free the memory a leak occurs; if one tries to access freed
@ -687,79 +859,6 @@ proc swap*[T](a, b: var T) {.magic: "Swap".}
## swaps the values `a` and `b`. This is often more efficient than ## swaps the values `a` and `b`. This is often more efficient than
## ``tmp = a; a = b; b = tmp``. Particularly useful for sorting algorithms. ## ``tmp = a; a = b; b = tmp``. Particularly useful for sorting algorithms.
proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect.}
## zero extends a smaller integer type to ``int``. This treats `x` as
## unsigned.
proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect.}
## zero extends a smaller integer type to ``int``. This treats `x` as
## unsigned.
proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned.
proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned.
proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned.
proc ze64*(x: int): int64 {.magic: "ZeIToI64", noDecl, noSideEffect.}
## zero extends a smaller integer type to ``int64``. This treats `x` as
## unsigned. Does nothing if the size of an ``int`` is the same as ``int64``.
## (This is the case on 64 bit processors.)
proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect.}
## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
## from `x`.
proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect.}
## treats `x` as unsigned and converts it to an ``int16`` by taking the last
## 16 bits from `x`.
proc toU32*(x: int64): int32 {.magic: "ToU32", noSideEffect.}
## treats `x` as unsigned and converts it to an ``int32`` by taking the
## last 32 bits from `x`.
proc `+%` *(x, y: int): int {.magic: "AddU", noSideEffect.}
proc `+%` *(x, y: int64): int64 {.magic: "AddU64", noSideEffect.}
## treats `x` and `y` as unsigned and adds them. The result is truncated to
## fit into the result. This implements modulo arithmetic. No overflow
## errors are possible.
proc `-%` *(x, y: int): int {.magic: "SubU", noSideEffect.}
proc `-%` *(x, y: int64): int64 {.magic: "SubU64", noSideEffect.}
## treats `x` and `y` as unsigned and subtracts them. The result is
## truncated to fit into the result. This implements modulo arithmetic.
## No overflow errors are possible.
proc `*%` *(x, y: int): int {.magic: "MulU", noSideEffect.}
proc `*%` *(x, y: int64): int64 {.magic: "MulU64", noSideEffect.}
## treats `x` and `y` as unsigned and multiplies them. The result is
## truncated to fit into the result. This implements modulo arithmetic.
## No overflow errors are possible.
proc `/%` *(x, y: int): int {.magic: "DivU", noSideEffect.}
proc `/%` *(x, y: int64): int64 {.magic: "DivU64", noSideEffect.}
## treats `x` and `y` as unsigned and divides them. The result is
## truncated to fit into the result. This implements modulo arithmetic.
## No overflow errors are possible.
proc `%%` *(x, y: int): int {.magic: "ModU", noSideEffect.}
proc `%%` *(x, y: int64): int64 {.magic: "ModU64", noSideEffect.}
## treats `x` and `y` as unsigned and compute the modulo of `x` and `y`.
## The result is truncated to fit into the result.
## This implements modulo arithmetic.
## No overflow errors are possible.
proc `<=%` *(x, y: int): bool {.magic: "LeU", noSideEffect.}
proc `<=%` *(x, y: int64): bool {.magic: "LeU64", noSideEffect.}
## treats `x` and `y` as unsigned and compares them.
## Returns true iff ``unsigned(x) <= unsigned(y)``.
proc `<%` *(x, y: int): bool {.magic: "LtU", noSideEffect.}
proc `<%` *(x, y: int64): bool {.magic: "LtU64", noSideEffect.}
## treats `x` and `y` as unsigned and compares them.
## Returns true iff ``unsigned(x) < unsigned(y)``.
template `>=%` *(x, y: expr): expr = y <=% x template `>=%` *(x, y: expr): expr = y <=% x
## treats `x` and `y` as unsigned and compares them. ## treats `x` and `y` as unsigned and compares them.
## Returns true iff ``unsigned(x) >= unsigned(y)``. ## Returns true iff ``unsigned(x) >= unsigned(y)``.
@ -803,17 +902,19 @@ proc getRefcount*[T](x: ref T): int {.importc: "getRefcount".}
## value is implementation-dependant. ## value is implementation-dependant.
#proc writeStackTrace() {.export: "writeStackTrace".} #proc writeStackTrace() {.export: "writeStackTrace".}
proc getCurrentExceptionMsg*(): string {.exportc.}
## retrieves the error message that was attached to the current when not defined(NimrodVM):
## exception; if there is none, "" is returned. proc getCurrentExceptionMsg*(): string {.exportc.}
## retrieves the error message that was attached to the current
## exception; if there is none, "" is returned.
# new constants: # new constants:
const const
inf* {.magic: "Inf".} = 0.0 inf* {.magic: "Inf".} = 1.0 / 0.0
## contains the IEEE floating point value of positive infinity. ## contains the IEEE floating point value of positive infinity.
neginf* {.magic: "NegInf".} = 0.0 neginf* {.magic: "NegInf".} = -inf
## contains the IEEE floating point value of negative infinity. ## contains the IEEE floating point value of negative infinity.
nan* {.magic: "NaN".} = 0.0 nan* {.magic: "NaN".} = 0.0 / 0.0
## contains an IEEE floating point value of *Not A Number*. Note ## contains an IEEE floating point value of *Not A Number*. Note
## that you cannot compare a floating point value to this value ## that you cannot compare a floating point value to this value
## and expect a reasonable result - use the `classify` procedure ## and expect a reasonable result - use the `classify` procedure
@ -826,20 +927,16 @@ var
## Only code compiled with the ``debugger:on`` switch calls this hook. ## Only code compiled with the ``debugger:on`` switch calls this hook.
# GC interface: # GC interface:
when defined(Unix) and not defined(macosX) and not defined(linux):
# BUGFIX for macosX
{.define: nativeDL.}
when defined(useDL) or defined(nativeDL): proc getOccupiedMem*(): int
proc getOccupiedMem*(): int ## returns the number of bytes that are owned by the process and hold data.
## returns the number of bytes that are owned by the process and hold data.
proc getFreeMem*(): int proc getFreeMem*(): int
## returns the number of bytes that are owned by the process, but do not ## returns the number of bytes that are owned by the process, but do not
## hold any meaningful data. ## hold any meaningful data.
proc getTotalMem*(): int proc getTotalMem*(): int
## returns the number of bytes that are owned by the process. ## returns the number of bytes that are owned by the process.
iterator countdown*[T](a, b: T, step = 1): T {.inline.} = iterator countdown*[T](a, b: T, step = 1): T {.inline.} =
@ -906,7 +1003,6 @@ iterator items*(a: cstring): char {.inline.} =
yield a[i] yield a[i]
inc(i) inc(i)
proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil".} proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil".}
proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".} proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil".} proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil".}
@ -922,23 +1018,20 @@ proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".}
# once in the system module. # once in the system module.
proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect.} = proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect.} =
result = [] newSeq(result, x.len + y.len)
setLen(result, x.len + y.len)
for i in 0..x.len-1: for i in 0..x.len-1:
result[i] = x[i] result[i] = x[i]
for i in 0..y.len-1: for i in 0..y.len-1:
result[i] = y[i] result[i] = y[i]
proc `&` *[T](x: seq[T], y: T): seq[T] {.noSideEffect.} = proc `&` *[T](x: seq[T], y: T): seq[T] {.noSideEffect.} =
result = [] newSeq(result, x.len + 1)
setLen(x.len + 1)
for i in 0..x.len-1: for i in 0..x.len-1:
result[i] = x[i] result[i] = x[i]
result[x.len] = y result[x.len] = y
proc `&` *[T](x: T, y: seq[T]): seq[T] {.noSideEffect.} = proc `&` *[T](x: T, y: seq[T]): seq[T] {.noSideEffect.} =
result = [] newSeq(result, y.len + 1)
setLen(y.len + 1)
for i in 0..y.len-1: for i in 0..y.len-1:
result[i] = y[i] result[i] = y[i]
result[y.len] = x result[y.len] = x
@ -946,24 +1039,35 @@ proc `&` *[T](x: T, y: seq[T]): seq[T] {.noSideEffect.} =
proc `&` *[T](x, y: T): seq[T] {.noSideEffect.} = proc `&` *[T](x, y: T): seq[T] {.noSideEffect.} =
return [x, y] return [x, y]
when not defined(ECMAScript): # XXX make this local procs when not defined(NimrodVM):
proc seqToPtr*[T](x: seq[T]): pointer {.inline, nosideeffect.} = when not defined(ECMAScript):
result = cast[pointer](x) # XXX make this local procs
else: proc seqToPtr*[T](x: seq[T]): pointer {.inline, nosideeffect.} =
proc seqToPtr*[T](x: seq[T]): pointer {.pure, nosideeffect.} = result = cast[pointer](x)
asm """return `x`""" else:
proc seqToPtr*[T](x: seq[T]): pointer {.pure, nosideeffect.} =
asm """return `x`"""
proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} =
## Generic equals operator for sequences: relies on a equals operator for
## the element type `T`.
if seqToPtr(x) == seqToPtr(y):
result = true
elif seqToPtr(x) == nil or seqToPtr(y) == nil:
result = false
elif x.len == y.len:
for i in 0..x.len-1:
if x[i] != y[i]: return false
result = true
proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} = proc find*[T, S](a: T, item: S): int {.inline.} =
## Generic equals operator for sequences: relies on a equals operator for ## Returns the first index of `item` in `a` or -1 if not found. This requires
## the element type `T`. ## appropriate `==` and `items` procs to work.
if seqToPtr(x) == seqToPtr(y): result = 0
result = true for i in items(a):
elif seqToPtr(x) == nil or seqToPtr(y) == nil: if i == item: return
result = false inc(result)
elif x.len == y.len: result = -1
for i in 0..x.len-1:
if x[i] != y[i]: return false
result = true
# ----------------- FPU ------------------------------------------------------ # ----------------- FPU ------------------------------------------------------
@ -985,7 +1089,7 @@ proc GC_enable*()
proc GC_fullCollect*() proc GC_fullCollect*()
## forces a full garbage collection pass. ## forces a full garbage collection pass.
## Ordinary code does not need to call this. ## Ordinary code does not need to call this (and should not).
type type
TGC_Strategy* = enum ## the strategy the GC should use for the application TGC_Strategy* = enum ## the strategy the GC should use for the application
@ -1005,12 +1109,28 @@ proc GC_disableMarkAndSweep*()
## does not create cycles. Thus the mark and sweep phase can be deactivated ## does not create cycles. Thus the mark and sweep phase can be deactivated
## and activated separately from the rest of the GC. ## and activated separately from the rest of the GC.
proc GC_getStatistics*(): string
## returns an informative string about the GC's activity. This may be useful
## for tweaking.
proc GC_ref*[T](x: ref T) {.magic: "GCref".}
proc GC_ref*[T](x: seq[T]) {.magic: "GCref".}
proc GC_ref*(x: string) {.magic: "GCref".}
## marks the object `x` as referenced, so that it will not be freed until
## it is unmarked via `GC_unref`. If called n-times for the same object `x`,
## n calls to `GC_unref` are needed to unmark `x`.
proc GC_unref*[T](x: ref T) {.magic: "GCunref".}
proc GC_unref*[T](x: seq[T]) {.magic: "GCunref".}
proc GC_unref*(x: string) {.magic: "GCunref".}
## see the documentation of `GC_ref`.
{.push checks: off, line_dir: off, debugger: off,
assertions: on.} # obviously we cannot generate checking operations here :-) {.push checks: off, line_dir: off, debugger: off.}
# because it would yield into an endless recursion # obviously we cannot generate checking operations here :-)
# however, stack-traces are available for most parts # because it would yield into an endless recursion
# of the code # however, stack-traces are available for most parts
# of the code
proc echo*[Ty](x: Ty) {.inline.} proc echo*[Ty](x: Ty) {.inline.}
## equivalent to ``writeln(stdout, x); flush(stdout)``. BUT: This is ## equivalent to ``writeln(stdout, x); flush(stdout)``. BUT: This is
@ -1025,7 +1145,29 @@ template newException(exceptn, message: expr): expr =
e.msg = message e.msg = message
e e
when not defined(EcmaScript): const
QuitSuccess* = 0
## is the value that should be passed to ``quit`` to indicate
## success.
QuitFailure* = 1
## is the value that should be passed to ``quit`` to indicate
## failure.
proc quit*(errorcode: int = QuitSuccess) {.
magic: "Exit", importc: "exit", noDecl, noReturn.}
## stops the program immediately; before stopping the program the
## "quit procedures" are called in the opposite order they were added
## with ``addQuitProc``. ``quit`` never returns and ignores any
## exception that may have been raised by the quit procedures.
## It does *not* call the garbage collector to free all the memory,
## unless a quit procedure calls ``GC_collect``.
when not defined(EcmaScript) and not defined(NimrodVM):
proc quit*(errormsg: string) {.noReturn.}
## a shorthand for ``echo(errormsg); quit(quitFailure)``.
when not defined(EcmaScript) and not defined(NimrodVM):
include hti include hti
@ -1036,6 +1178,7 @@ when not defined(EcmaScript):
strDesc.size = sizeof(string) strDesc.size = sizeof(string)
strDesc.kind = tyString strDesc.kind = tyString
strDesc.flags = {ntfAcyclic}
initGC() # BUGFIX: need to be called here! initGC() # BUGFIX: need to be called here!
{.push stack_trace: off.} {.push stack_trace: off.}
@ -1043,12 +1186,12 @@ when not defined(EcmaScript):
include ansi_c include ansi_c
proc cmp(x, y: string): int = proc cmp(x, y: string): int =
return c_strcmp(x, y) return int(c_strcmp(x, y))
const pccHack = if defined(pcc): "_" else: "" # Hack for PCC
when defined(windows): when defined(windows):
# work-around C's sucking abstraction: # work-around C's sucking abstraction:
# BUGFIX: stdin and stdout should be binary files! # BUGFIX: stdin and stdout should be binary files!
const pccHack = if defined(pcc): "_" else: "" # Hack for PCC
proc setmode(handle, mode: int) {.importc: pccHack & "setmode", proc setmode(handle, mode: int) {.importc: pccHack & "setmode",
header: "<io.h>".} header: "<io.h>".}
proc fileno(f: C_TextFileStar): int {.importc: pccHack & "fileno", proc fileno(f: C_TextFileStar): int {.importc: pccHack & "fileno",
@ -1082,6 +1225,9 @@ when not defined(EcmaScript):
fmAppend ## Open the file for writing only; append data fmAppend ## Open the file for writing only; append data
## at the end. ## at the end.
TFileHandle* = cint ## type that represents an OS file handle; this is
## useful for low-level file access
# text file handling: # text file handling:
var var
stdin* {.importc: "stdin", noDecl.}: TFile ## The standard input stream. stdin* {.importc: "stdin", noDecl.}: TFile ## The standard input stream.
@ -1106,6 +1252,12 @@ when not defined(EcmaScript):
## that the programmer needs to provide an appropriate error message anyway ## that the programmer needs to provide an appropriate error message anyway
## (yes, even in scripts). ## (yes, even in scripts).
proc OpenFile*(f: var TFile, filehandle: TFileHandle,
mode: TFileMode = fmRead): Bool
## Creates a ``TFile`` from a `filehandle` with given `mode`.
##
## Default mode is readonly. Returns true iff the file could be opened.
proc CloseFile*(f: TFile) {.importc: "fclose", nodecl.} proc CloseFile*(f: TFile) {.importc: "fclose", nodecl.}
## Closes the file. ## Closes the file.
proc EndOfFile*(f: TFile): Bool proc EndOfFile*(f: TFile): Bool
@ -1201,6 +1353,15 @@ when not defined(EcmaScript):
yield res yield res
CloseFile(f) CloseFile(f)
proc fileHandle*(f: TFile): TFileHandle {.importc: "fileno",
header: "<stdio.h>"}
## returns the OS file handle of the file ``f``. This is only useful for
## platform specific programming.
proc quit(errormsg: string) =
echo(errormsg)
quit(quitFailure)
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
include excpt include excpt
@ -1211,10 +1372,10 @@ when not defined(EcmaScript):
# sequence type declarations here because the GC needs them too: # sequence type declarations here because the GC needs them too:
type type
TGenericSeq {.importc, nodecl, final.} = object TGenericSeq {.compilerproc, pure.} = object
len, space: int len, space: int
PGenericSeq {.importc, nodecl.} = ptr TGenericSeq PGenericSeq {.exportc.} = ptr TGenericSeq
const const
GenericSeqSize = (2 * sizeof(int)) GenericSeqSize = (2 * sizeof(int))
@ -1235,10 +1396,32 @@ when not defined(EcmaScript):
{.push stack_trace: off.} {.push stack_trace: off.}
when defined(endb): when defined(endb):
include debugger include debugger
when defined(profiler):
include profiler
{.pop.} # stacktrace {.pop.} # stacktrace
else: elif defined(ecmaScript):
include ecmasys include ecmasys
elif defined(NimrodVM):
# Stubs for the GC interface:
proc GC_disable() = nil
proc GC_enable() = nil
proc GC_fullCollect() = nil
proc GC_setStrategy(strategy: TGC_Strategy) = nil
proc GC_enableMarkAndSweep() = nil
proc GC_disableMarkAndSweep() = nil
proc GC_getStatistics(): string = return ""
proc getOccupiedMem(): int = return -1
proc getFreeMem(): int = return -1
proc getTotalMem(): int = return -1
proc echo[Ty](x: Ty) = nil
proc cmp(x, y: string): int =
if x == y: return 0
if x < y: return -1
return 1
include macros include macros

View file

@ -23,8 +23,8 @@ type
TWeekDay* = enum ## represents a weekday TWeekDay* = enum ## represents a weekday
dMon, dTue, dWed, dThu, dFri, dSat, dSun dMon, dTue, dWed, dThu, dFri, dSat, dSun
TTime* {.importc: "time_t", final.} = object ## abstract type that TTime* {.importc: "time_t", header: "<time.h>", final.} = object ## abstract type that
## represents a time ## represents a time
when defined(ECMAScript): when defined(ECMAScript):
getDay: proc (): int getDay: proc (): int
getFullYear: proc (): int getFullYear: proc (): int
@ -96,11 +96,9 @@ proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime
## them from the other information in the broken-down time structure. ## them from the other information in the broken-down time structure.
proc `$` *(timeInfo: TTimeInfo): string proc `$` *(timeInfo: TTimeInfo): string
## converts a `TTimeInfo` object to a ## converts a `TTimeInfo` object to a string representation.
## string representation.
proc `$` *(time: TTime): string proc `$` *(time: TTime): string
## converts a calendar time to a ## converts a calendar time to a string representation.
## string representation.
proc getDateStr*(): string proc getDateStr*(): string
## gets the current date as a string of the format ## gets the current date as a string of the format
@ -111,6 +109,14 @@ proc getClockStr*(): string
proc `-` *(a, b: TTime): int64 proc `-` *(a, b: TTime): int64
## computes the difference of two calendar times. Result is in seconds. ## computes the difference of two calendar times. Result is in seconds.
proc `<` * (a, b: TTime): bool =
## returns true iff ``a < b``, that is iff a happened before b.
result = a - b < 0
proc `<=` * (a, b: TTime): bool =
## returns true iff ``a <= b``.
result = a - b <= 0
proc getStartMilsecs*(): int proc getStartMilsecs*(): int
## get the miliseconds from the start of the program ## get the miliseconds from the start of the program
@ -162,7 +168,7 @@ when not defined(ECMAScript):
result.hour = int(tm.hour) result.hour = int(tm.hour)
result.monthday = int(tm.monthday) result.monthday = int(tm.monthday)
result.month = TMonth(tm.month) result.month = TMonth(tm.month)
result.year = tm.year + 1900 result.year = tm.year + 1900'i32
result.weekday = weekDays[int(tm.weekDay)] result.weekday = weekDays[int(tm.weekDay)]
result.yearday = int(tm.yearday) result.yearday = int(tm.yearday)
@ -180,8 +186,7 @@ when not defined(ECMAScript):
result.isdst = -1 result.isdst = -1
proc `-` (a, b: TTime): int64 = proc `-` (a, b: TTime): int64 =
return toInt(difftime(a, b)) # XXX: toBiggestInt is needed here, but return toBiggestInt(difftime(a, b))
# Nim does not support it!
proc getStartMilsecs(): int = return clock() div (clocksPerSec div 1000) proc getStartMilsecs(): int = return clock() div (clocksPerSec div 1000)
proc getTime(): TTime = return timec(nil) proc getTime(): TTime = return timec(nil)
@ -202,12 +207,23 @@ when not defined(ECMAScript):
# because the header of mktime is broken in my version of libc # because the header of mktime is broken in my version of libc
return mktime(timeInfoToTM(cTimeInfo)) return mktime(timeInfoToTM(cTimeInfo))
proc toStringTillNL(p: cstring): string =
result = ""
var i = 0
while p[i] != '\0' and p[i] != '\10' and p[i] != '\13':
add(result, p[i])
inc(i)
return result
proc `$`(timeInfo: TTimeInfo): string = proc `$`(timeInfo: TTimeInfo): string =
return $asctime(timeInfoToTM(timeInfo)) # BUGFIX: asctime returns a newline at the end!
var p = asctime(timeInfoToTM(timeInfo))
result = toStringTillNL(p)
proc `$`(time: TTime): string = proc `$`(time: TTime): string =
# BUGFIX: ctime returns a newline at the end!
var a = time var a = time
return $ctime(addr(a)) return toStringTillNL(ctime(addr(a)))
else: else:
proc getTime(): TTime {.importc: "new Date", nodecl.} proc getTime(): TTime {.importc: "new Date", nodecl.}

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf # (c) Copyright 2008 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -9,7 +9,7 @@
type type
TUniChar* = int32 ## type that can hold any Unicode character TUniChar* = int32 ## type that can hold any Unicode character
TUniChar16* = int16 ## TUniChar16* = int16 ## 16 bit Unicode character
template ones(n) = ((1 shl n)-1) template ones(n) = ((1 shl n)-1)

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,13 @@
# Dummy makefile for people who don't read "readme" files, or automated # Dummy makefile for people who don't read "readme" files, or for automated
# installations # installations
# (c) 2007 Andreas Rumpf
.PHONY : all .PHONY : all
all: all:
python koch.py all python koch.py boot -d:release
.PHONY : install .PHONY : install
install: install:
python koch.py install sh install.sh /usr/bin
.PHONY : clean .PHONY : clean
clean: clean:

File diff suppressed because it is too large Load diff

View file

@ -133,7 +133,8 @@ procedure debug(n: PNode); overload;
// --------------------------- ident tables ---------------------------------- // --------------------------- ident tables ----------------------------------
function IdTableGet(const t: TIdTable; key: PIdObj): PObject; function IdTableGet(const t: TIdTable; key: PIdObj): PObject; overload;
function IdTableGet(const t: TIdTable; key: int): PObject; overload;
procedure IdTablePut(var t: TIdTable; key: PIdObj; val: PObject); procedure IdTablePut(var t: TIdTable; key: PIdObj; val: PObject);
function IdTableHasObjectAsKey(const t: TIdTable; key: PIdObj): bool; function IdTableHasObjectAsKey(const t: TIdTable; key: PIdObj): bool;
@ -145,33 +146,6 @@ procedure IdNodeTablePut(var t: TIdNodeTable; key: PIdObj; val: PNode);
procedure writeIdNodeTable(const t: TIdNodeTable); procedure writeIdNodeTable(const t: TIdNodeTable);
// ------------- efficient integer sets -------------------------------------
const
IntsPerTrunk = 8;
InitIntSetSize = 8; // must be a power of two!
BitsPerTrunk = IntsPerTrunk * sizeof(int) * 8;
BitsPerInt = sizeof(int) * 8;
type
PTrunk = ^TTrunk;
TTrunk = record
next: PTrunk; // all nodes are connected with this pointer
key: int; // start address at bit 0
bits: array [0..IntsPerTrunk-1] of int; // a bit vector
end;
TTrunkSeq = array of PTrunk;
TIntSet = record
counter, max: int;
head: PTrunk;
data: TTrunkSeq;
end;
function IntSetContains(const s: TIntSet; key: int): bool;
procedure IntSetIncl(var s: TIntSet; key: int);
procedure IntSetInit(var s: TIntSet);
function IntSetContainsOrIncl(var s: TIntSet; key: int): bool;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function getSymFromList(list: PNode; ident: PIdent; start: int = 0): PSym; function getSymFromList(list: PNode; ident: PIdent; start: int = 0): PSym;
function lookupInRecord(n: PNode; field: PIdent): PSym; function lookupInRecord(n: PNode; field: PIdent): PSym;
@ -181,6 +155,24 @@ function getModule(s: PSym): PSym;
function mustRehash(len, counter: int): bool; function mustRehash(len, counter: int): bool;
function nextTry(h, maxHash: THash): THash; function nextTry(h, maxHash: THash): THash;
// ------------- table[int, int] ---------------------------------------------
const
InvalidKey = low(int);
type
TIIPair = record
key, val: int;
end;
TIIPairSeq = array of TIIPair;
TIITable = record // table[int, int]
counter: int;
data: TIIPairSeq;
end;
procedure initIITable(out x: TIITable);
function IITableGet(const t: TIITable; key: int): int;
procedure IITablePut(var t: TIITable; key, val: int);
implementation implementation
function lookupInRecord(n: PNode; field: PIdent): PSym; function lookupInRecord(n: PNode; field: PIdent): PSym;
@ -281,14 +273,14 @@ begin
result := nil; result := nil;
res := '"' + ''; res := '"' + '';
for i := strStart to length(s)+strStart-1 do begin for i := strStart to length(s)+strStart-1 do begin
if i mod MaxLineLength = 0 then begin if (i-strStart+1) mod MaxLineLength = 0 then begin
res := res +{&} '"' +{&} nl; res := res +{&} '"' +{&} nl;
app(result, toRope(res)); app(result, toRope(res));
res := '"'+''; // reset res := '"'+''; // reset
end; end;
res := res +{&} toYamlChar(s[i]); res := res +{&} toYamlChar(s[i]);
end; end;
res := res + '"'; addChar(res, '"');
app(result, toRope(res)); app(result, toRope(res));
end; end;
@ -349,16 +341,16 @@ begin
toRope(toLinenumber(info)), toRope(toColumn(info))]); toRope(toLinenumber(info)), toRope(toColumn(info))]);
end; end;
function treeToYamlAux(n: PNode; var marker: TObjectSet; function treeToYamlAux(n: PNode; var marker: TIntSet;
indent: int; maxRecDepth: int): PRope; indent: int; maxRecDepth: int): PRope;
forward; forward;
function symToYamlAux(n: PSym; var marker: TObjectSet; function symToYamlAux(n: PSym; var marker: TIntSet;
indent: int; maxRecDepth: int): PRope; forward; indent: int; maxRecDepth: int): PRope; forward;
function typeToYamlAux(n: PType; var marker: TObjectSet; function typeToYamlAux(n: PType; var marker: TIntSet;
indent: int; maxRecDepth: int): PRope; forward; indent: int; maxRecDepth: int): PRope; forward;
function strTableToYaml(const n: TStrTable; var marker: TObjectSet; function strTableToYaml(const n: TStrTable; var marker: TIntSet;
indent: int; maxRecDepth: int): PRope; indent: int; maxRecDepth: int): PRope;
var var
istr: PRope; istr: PRope;
@ -396,14 +388,14 @@ begin
appf(result, '$n$1}', [spaces(indent)]); appf(result, '$n$1}', [spaces(indent)]);
end; end;
function symToYamlAux(n: PSym; var marker: TObjectSet; function symToYamlAux(n: PSym; var marker: TIntSet;
indent: int; maxRecDepth: int): PRope; indent: int; maxRecDepth: int): PRope;
var var
ast: PRope; ast: PRope;
begin begin
if n = nil then if n = nil then
result := toRope('null') result := toRope('null')
else if ObjectSetContainsOrIncl(marker, n) then else if IntSetContainsOrIncl(marker, n.id) then
result := ropef('"$1 @$2"', [ result := ropef('"$1 @$2"', [
toRope(n.name.s), toRope(n.name.s),
toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))]) toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))])
@ -424,12 +416,12 @@ begin
// YYY: backend info? // YYY: backend info?
end; end;
function typeToYamlAux(n: PType; var marker: TObjectSet; function typeToYamlAux(n: PType; var marker: TIntSet;
indent: int; maxRecDepth: int): PRope; indent: int; maxRecDepth: int): PRope;
begin begin
if n = nil then if n = nil then
result := toRope('null') result := toRope('null')
else if objectSetContainsOrIncl(marker, n) then else if intSetContainsOrIncl(marker, n.id) then
result := ropef('"$1 @$2"', [ result := ropef('"$1 @$2"', [
toRope(typeKindToStr[n.kind]), toRope(typeKindToStr[n.kind]),
toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))]) toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))])
@ -446,7 +438,7 @@ begin
end end
end; end;
function treeToYamlAux(n: PNode; var marker: TObjectSet; indent: int; function treeToYamlAux(n: PNode; var marker: TIntSet; indent: int;
maxRecDepth: int): PRope; maxRecDepth: int): PRope;
var var
istr: PRope; istr: PRope;
@ -503,25 +495,25 @@ end;
function treeToYaml(n: PNode; indent: int = 0; maxRecDepth: int = -1): PRope; function treeToYaml(n: PNode; indent: int = 0; maxRecDepth: int = -1): PRope;
var var
marker: TObjectSet; marker: TIntSet;
begin begin
initObjectSet(marker); IntSetInit(marker);
result := treeToYamlAux(n, marker, indent, maxRecDepth) result := treeToYamlAux(n, marker, indent, maxRecDepth)
end; end;
function typeToYaml(n: PType; indent: int = 0; maxRecDepth: int = -1): PRope; function typeToYaml(n: PType; indent: int = 0; maxRecDepth: int = -1): PRope;
var var
marker: TObjectSet; marker: TIntSet;
begin begin
initObjectSet(marker); IntSetInit(marker);
result := typeToYamlAux(n, marker, indent, maxRecDepth) result := typeToYamlAux(n, marker, indent, maxRecDepth)
end; end;
function symToYaml(n: PSym; indent: int = 0; maxRecDepth: int = -1): PRope; function symToYaml(n: PSym; indent: int = 0; maxRecDepth: int = -1): PRope;
var var
marker: TObjectSet; marker: TIntSet;
begin begin
initObjectSet(marker); IntSetInit(marker);
result := symToYamlAux(n, marker, indent, maxRecDepth) result := symToYamlAux(n, marker, indent, maxRecDepth)
end; end;
@ -617,7 +609,7 @@ const
EmptySeq = nil; EmptySeq = nil;
{@emit {@emit
const const
EmptySeq = []; EmptySeq = @[];
} }
function nextTry(h, maxHash: THash): THash; function nextTry(h, maxHash: THash): THash;
@ -661,11 +653,12 @@ var
n: TObjectSeq; n: TObjectSeq;
i: int; i: int;
begin begin
{@ignore}
n := emptySeq; n := emptySeq;
setLength(n, length(t.data) * growthFactor); setLength(n, length(t.data) * growthFactor);
{@ignore}
fillChar(n[0], length(n)*sizeof(n[0]), 0); fillChar(n[0], length(n)*sizeof(n[0]), 0);
{@emit} {@emit
newSeq(n, length(t.data) * growthFactor); }
for i := 0 to high(t.data) do for i := 0 to high(t.data) do
if t.data[i] <> nil then objectSetRawInsert(n, t.data[i]); if t.data[i] <> nil then objectSetRawInsert(n, t.data[i]);
{@ignore} {@ignore}
@ -769,11 +762,12 @@ var
n: TPairSeq; n: TPairSeq;
i: int; i: int;
begin begin
{@ignore}
n := emptySeq; n := emptySeq;
setLength(n, length(t.data) * growthFactor); setLength(n, length(t.data) * growthFactor);
{@ignore}
fillChar(n[0], length(n)*sizeof(n[0]), 0); fillChar(n[0], length(n)*sizeof(n[0]), 0);
{@emit} {@emit
newSeq(n, length(t.data) * growthFactor); }
for i := 0 to high(t.data) do for i := 0 to high(t.data) do
if t.data[i].key <> nil then if t.data[i].key <> nil then
TableRawInsert(n, t.data[i].key, t.data[i].val); TableRawInsert(n, t.data[i].key, t.data[i].val);
@ -833,11 +827,12 @@ var
n: TSymSeq; n: TSymSeq;
i: int; i: int;
begin begin
{@ignore}
n := emptySeq; n := emptySeq;
setLength(n, length(t.data) * growthFactor); setLength(n, length(t.data) * growthFactor);
{@ignore}
fillChar(n[0], length(n)*sizeof(n[0]), 0); fillChar(n[0], length(n)*sizeof(n[0]), 0);
{@emit} {@emit
newSeq(n, length(t.data) * growthFactor); }
for i := 0 to high(t.data) do for i := 0 to high(t.data) do
if t.data[i] <> nil then StrTableRawInsert(n, t.data[i]); if t.data[i] <> nil then StrTableRawInsert(n, t.data[i]);
{@ignore} {@ignore}
@ -1022,13 +1017,13 @@ begin
result := false result := false
end; end;
function IdTableRawGet(const t: TIdTable; key: PIdObj): int; function IdTableRawGet(const t: TIdTable; key: int): int;
var var
h: THash; h: THash;
begin begin
h := key.id and high(t.data); // start with real hash value h := key and high(t.data); // start with real hash value
while t.data[h].key <> nil do begin while t.data[h].key <> nil do begin
if (t.data[h].key.id = key.id) then begin if (t.data[h].key.id = key) then begin
result := h; exit result := h; exit
end; end;
h := nextTry(h, high(t.data)) h := nextTry(h, high(t.data))
@ -1040,12 +1035,21 @@ function IdTableHasObjectAsKey(const t: TIdTable; key: PIdObj): bool;
var var
index: int; index: int;
begin begin
index := IdTableRawGet(t, key); index := IdTableRawGet(t, key.id);
if index >= 0 then result := t.data[index].key = key if index >= 0 then result := t.data[index].key = key
else result := false else result := false
end; end;
function IdTableGet(const t: TIdTable; key: PIdObj): PObject; function IdTableGet(const t: TIdTable; key: PIdObj): PObject;
var
index: int;
begin
index := IdTableRawGet(t, key.id);
if index >= 0 then result := t.data[index].val
else result := nil
end;
function IdTableGet(const t: TIdTable; key: int): PObject;
var var
index: int; index: int;
begin begin
@ -1074,18 +1078,18 @@ var
index, i: int; index, i: int;
n: TIdPairSeq; n: TIdPairSeq;
begin begin
index := IdTableRawGet(t, key); index := IdTableRawGet(t, key.id);
if index >= 0 then begin if index >= 0 then begin
assert(t.data[index].key <> nil); assert(t.data[index].key <> nil);
t.data[index].val := val t.data[index].val := val
end end
else begin else begin
if mustRehash(length(t.data), t.counter) then begin if mustRehash(length(t.data), t.counter) then begin
{@emit n := [];}
setLength(n, length(t.data) * growthFactor);
{@ignore} {@ignore}
setLength(n, length(t.data) * growthFactor);
fillChar(n[0], length(n)*sizeof(n[0]), 0); fillChar(n[0], length(n)*sizeof(n[0]), 0);
{@emit} {@emit
newSeq(n, length(t.data) * growthFactor); }
for i := 0 to high(t.data) do for i := 0 to high(t.data) do
if t.data[i].key <> nil then if t.data[i].key <> nil then
IdTableRawInsert(n, t.data[i].key, t.data[i].val); IdTableRawInsert(n, t.data[i].key, t.data[i].val);
@ -1166,11 +1170,11 @@ begin
end end
else begin else begin
if mustRehash(length(t.data), t.counter) then begin if mustRehash(length(t.data), t.counter) then begin
{@emit n := [];}
setLength(n, length(t.data) * growthFactor);
{@ignore} {@ignore}
setLength(n, length(t.data) * growthFactor);
fillChar(n[0], length(n)*sizeof(n[0]), 0); fillChar(n[0], length(n)*sizeof(n[0]), 0);
{@emit} {@emit
newSeq(n, length(t.data) * growthFactor); }
for i := 0 to high(t.data) do for i := 0 to high(t.data) do
if t.data[i].key <> nil then if t.data[i].key <> nil then
IdNodeTableRawInsert(n, t.data[i].key, t.data[i].val); IdNodeTableRawInsert(n, t.data[i].key, t.data[i].val);
@ -1185,156 +1189,86 @@ begin
end; end;
end; end;
// ---------------- efficient integer sets ---------------------------------- // ------------- int-to-int-mapping ------------------------------------------
// Same algorithm as the one the GC uses
procedure IntSetInit(var s: TIntSet); procedure initIITable(out x: TIITable);
var
i: int;
begin begin
x.counter := 0;
{@ignore} {@ignore}
fillChar(s, sizeof(s), 0); setLength(x.data, startSize);
{@emit {@emit
s.data := []; } newSeq(x.data, startSize); }
setLength(s.data, InitIntSetSize); for i := 0 to startSize-1 do x.data[i].key := InvalidKey;
{@ignore}
fillChar(s.data[0], length(s.data)*sizeof(s.data[0]), 0);
{@emit}
s.max := InitIntSetSize-1;
s.counter := 0;
s.head := nil
end; end;
function IntSetGet(const t: TIntSet; key: int): PTrunk; function IITableRawGet(const t: TIITable; key: int): int;
var var
h: int; h: THash;
begin begin
h := key and t.max; h := key and high(t.data); // start with real hash value
while t.data[h] <> nil do begin while t.data[h].key <> InvalidKey do begin
if t.data[h].key = key then begin if (t.data[h].key = key) then begin
result := t.data[h]; exit result := h; exit
end; end;
h := nextTry(h, t.max) h := nextTry(h, high(t.data))
end; end;
result := nil result := -1
end; end;
procedure IntSetRawInsert(const t: TIntSet; var data: TTrunkSeq; function IITableGet(const t: TIITable; key: int): int;
desc: PTrunk);
var var
h: int; index: int;
begin begin
h := desc.key and t.max; index := IITableRawGet(t, key);
while data[h] <> nil do begin if index >= 0 then result := t.data[index].val
assert(data[h] <> desc); else result := InvalidKey
h := nextTry(h, t.max) end;
procedure IITableRawInsert(var data: TIIPairSeq;
key, val: int);
var
h: THash;
begin
h := key and high(data);
while data[h].key <> InvalidKey do begin
assert(data[h].key <> key);
h := nextTry(h, high(data))
end; end;
assert(data[h] = nil); assert(data[h].key = InvalidKey);
data[h] := desc data[h].key := key;
data[h].val := val;
end; end;
procedure IntSetEnlarge(var t: TIntSet); procedure IITablePut(var t: TIITable; key, val: int);
var var
n: TTrunkSeq; index, i: int;
i, oldMax: int; n: TIIPairSeq;
begin begin
oldMax := t.max; index := IITableRawGet(t, key);
t.max := ((t.max+1)*2)-1; if index >= 0 then begin
{@emit n := []} assert(t.data[index].key <> InvalidKey);
setLength(n, t.max + 1); t.data[index].val := val
{@ignore}
fillChar(n[0], length(n)*sizeof(n[0]), 0);
{@emit}
for i := 0 to oldmax do
if t.data[i] <> nil then
IntSetRawInsert(t, n, t.data[i]);
{@ignore}
t.data := n;
{@emit
swap(t.data, n);
}
end;
function IntSetPut(var t: TIntSet; key: int): PTrunk;
var
h: int;
begin
h := key and t.max;
while t.data[h] <> nil do begin
if t.data[h].key = key then begin
result := t.data[h]; exit
end;
h := nextTry(h, t.max)
end;
if mustRehash(t.max+1, t.counter) then IntSetEnlarge(t);
inc(t.counter);
h := key and t.max;
while t.data[h] <> nil do h := nextTry(h, t.max);
assert(t.data[h] = nil);
new(result);
{@ignore}
fillChar(result^, sizeof(result^), 0);
{@emit}
result.next := t.head;
result.key := key;
t.head := result;
t.data[h] := result;
end;
// ---------- slightly higher level procs ----------------------------------
function transform(key: int): int;
begin
if key < 0 then result := 1000000000 + key // avoid negative numbers!
else result := key
end;
function IntSetContains(const s: TIntSet; key: int): bool;
var
u: int;
t: PTrunk;
begin
u := transform(key);
t := IntSetGet(s, u div BitsPerTrunk);
if t <> nil then begin
u := u mod BitsPerTrunk;
result := (t.bits[u div BitsPerInt]
and (1 shl (u mod BitsPerInt))) <> 0
end
else
result := false
end;
procedure IntSetIncl(var s: TIntSet; key: int);
var
u: int;
t: PTrunk;
begin
u := transform(key);
t := IntSetPut(s, u div BitsPerTrunk);
u := u mod BitsPerTrunk;
t.bits[u div BitsPerInt] := t.bits[u div BitsPerInt]
or (1 shl (u mod BitsPerInt));
end;
function IntSetContainsOrIncl(var s: TIntSet; key: int): bool;
var
u: int;
t: PTrunk;
begin
u := transform(key);
t := IntSetGet(s, u div BitsPerTrunk);
if t <> nil then begin
u := u mod BitsPerTrunk;
result := (t.bits[u div BitsPerInt]
and (1 shl (u mod BitsPerInt))) <> 0;
if not result then
t.bits[u div BitsPerInt] := t.bits[u div BitsPerInt]
or (1 shl (u mod BitsPerInt));
end end
else begin else begin
IntSetIncl(s, key); if mustRehash(length(t.data), t.counter) then begin
result := false {@ignore}
end setLength(n, length(t.data) * growthFactor);
{@emit
newSeq(n, length(t.data) * growthFactor); }
for i := 0 to high(n) do n[i].key := InvalidKey;
for i := 0 to high(t.data) do
if t.data[i].key <> InvalidKey then
IITableRawInsert(n, t.data[i].key, t.data[i].val);
{@ignore}
t.data := n;
{@emit
swap(t.data, n); }
end;
IITableRawInsert(t.data, key, val);
inc(t.counter)
end;
end; end;
end. end.

View file

@ -1,59 +0,0 @@
//
//
// The Nimrod Compiler
// (c) Copyright 2008 Andreas Rumpf
//
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
unit backends;
// This module only contains the PBackend type declaration/interface, each
// backend has to adhere to.
interface
{$include 'config.inc'}
uses
nsystem, idents, ropes, msgs, ast;
type
PBackend = ^TBackend;
TBackendEvent = (eNone, eAfterModule);
TEventMask = set of TBackendEvent;
TBackend = object(NObject)
eventMask: TEventMask;
module: PSym;
filename: string;
backendCreator: function (oldBackend: PBackend; module: PSym;
const filename: string): PBackend;
afterModuleEvent: procedure (b: PBackend; module: PNode);
// triggered AFTER a whole module has been checked for semantics
end;
function backendCreator(b: PBackend; module: PSym;
const filename: string): PBackend;
function newBackend(module: PSym; const filename: string): PBackend;
implementation
function newBackend(module: PSym; const filename: string): PBackend;
begin
new(result);
{@ignore}
fillChar(result^, sizeof(result^), 0);
{@emit}
result.backendCreator := backendCreator;
result.module := module;
result.filename := filename;
end;
function backendCreator(b: PBackend; module: PSym;
const filename: string): PBackend;
begin
result := newBackend(module, filename);
end;
end.

View file

@ -8,7 +8,7 @@
// //
unit bitsets; unit bitsets;
// this unit handles Nimrod sets; it implements symbolic sets // this unit handles Nimrod sets; it implements bit sets
// the code here should be reused in the Nimrod standard library // the code here should be reused in the Nimrod standard library
interface interface
@ -44,57 +44,58 @@ implementation
function BitSetIn(const x: TBitSet; const e: BiggestInt): Boolean; function BitSetIn(const x: TBitSet; const e: BiggestInt): Boolean;
begin begin
result := (x[int(e div ElemSize)] and (1 shl (e mod ElemSize))) <> 0 result := (x[int(e div ElemSize)] and toU8(int(1 shl (e mod ElemSize)))) <> toU8(0)
end; end;
procedure BitSetIncl(var x: TBitSet; const elem: BiggestInt); procedure BitSetIncl(var x: TBitSet; const elem: BiggestInt);
begin begin
assert(elem >= 0); assert(elem >= 0);
x[int(elem div ElemSize)] := toU8(x[int(elem div ElemSize)] or x[int(elem div ElemSize)] := x[int(elem div ElemSize)] or
int(1 shl (elem mod ElemSize))) toU8(int(1 shl (elem mod ElemSize)))
end; end;
procedure BitSetExcl(var x: TBitSet; const elem: BiggestInt); procedure BitSetExcl(var x: TBitSet; const elem: BiggestInt);
begin begin
x[int(elem div ElemSize)] := toU8(x[int(elem div ElemSize)] and x[int(elem div ElemSize)] := x[int(elem div ElemSize)] and
not int(1 shl (elem mod ElemSize))) not toU8(int(1 shl (elem mod ElemSize)))
end; end;
procedure BitSetInit(out b: TBitSet; len: int); procedure BitSetInit(out b: TBitSet; len: int);
begin begin
{@emit b := [];}
setLength(b, len);
{@ignore} {@ignore}
setLength(b, len);
fillChar(b[0], length(b)*sizeof(b[0]), 0); fillChar(b[0], length(b)*sizeof(b[0]), 0);
{@emit} {@emit
newSeq(b, len);
}
end; end;
procedure BitSetUnion(var x: TBitSet; const y: TBitSet); procedure BitSetUnion(var x: TBitSet; const y: TBitSet);
var var
i: int; i: int;
begin begin
for i := 0 to high(x) do x[i] := toU8(x[i] or int(y[i])) for i := 0 to high(x) do x[i] := x[i] or y[i]
end; end;
procedure BitSetDiff(var x: TBitSet; const y: TBitSet); procedure BitSetDiff(var x: TBitSet; const y: TBitSet);
var var
i: int; i: int;
begin begin
for i := 0 to high(x) do x[i] := toU8(x[i] and not int(y[i])) for i := 0 to high(x) do x[i] := x[i] and not y[i]
end; end;
procedure BitSetSymDiff(var x: TBitSet; const y: TBitSet); procedure BitSetSymDiff(var x: TBitSet; const y: TBitSet);
var var
i: int; i: int;
begin begin
for i := 0 to high(x) do x[i] := toU8(x[i] xor int(y[i])) for i := 0 to high(x) do x[i] := x[i] xor y[i]
end; end;
procedure BitSetIntersect(var x: TBitSet; const y: TBitSet); procedure BitSetIntersect(var x: TBitSet; const y: TBitSet);
var var
i: int; i: int;
begin begin
for i := 0 to high(x) do x[i] := toU8(x[i] and int(y[i])) for i := 0 to high(x) do x[i] := x[i] and y[i]
end; end;
function BitSetEquals(const x, y: TBitSet): Boolean; function BitSetEquals(const x, y: TBitSet): Boolean;
@ -102,7 +103,7 @@ var
i: int; i: int;
begin begin
for i := 0 to high(x) do for i := 0 to high(x) do
if (x[i] <> int(y[i])) then begin if x[i] <> y[i] then begin
result := false; exit; result := false; exit;
end; end;
result := true result := true
@ -113,7 +114,7 @@ var
i: int; i: int;
begin begin
for i := 0 to high(x) do for i := 0 to high(x) do
if (x[i] and not int(y[i])) <> 0 then begin if (x[i] and not y[i]) <> byte(0) then begin
result := false; exit; result := false; exit;
end; end;
result := true result := true

File diff suppressed because it is too large Load diff

View file

@ -48,25 +48,16 @@ begin
app(p.s[cpsStmts], 'goto BeforeRet;' + tnl) app(p.s[cpsStmts], 'goto BeforeRet;' + tnl)
end; end;
procedure genObjectInit(p: BProc; sym: PSym);
begin
if containsObject(sym.typ) then begin
useMagic(p.module, 'objectInit');
appf(p.s[cpsInit], 'objectInit($1, $2);$n',
[addrLoc(sym.loc), genTypeInfo(p.module, sym.typ)])
end
end;
procedure initVariable(p: BProc; v: PSym); procedure initVariable(p: BProc; v: PSym);
begin begin
if containsGarbageCollectedRef(v.typ) or (v.ast = nil) then if containsGarbageCollectedRef(v.typ) or (v.ast = nil) then
// Language change: always initialize variables if v.ast == nil! // Language change: always initialize variables if v.ast == nil!
if not (skipVarGenericRange(v.typ).Kind in [tyArray, tyArrayConstr, tySet, if not (skipVarGenericRange(v.typ).Kind in [tyArray, tyArrayConstr, tySet,
tyTuple, tyObject]) then tyTuple, tyObject]) then
appf(p.s[cpsStmts], '$1 = 0;$n', [v.loc.r]) appf(p.s[cpsStmts], '$1 = 0;$n', [rdLoc(v.loc)])
else else
appf(p.s[cpsStmts], 'memset((void*)&$1, 0, sizeof($1));$n', appf(p.s[cpsStmts], 'memset((void*)$1, 0, sizeof($2));$n',
[v.loc.r]) [addrLoc(v.loc), rdLoc(v.loc)])
end; end;
procedure genVarStmt(p: BProc; n: PNode); procedure genVarStmt(p: BProc; n: PNode);
@ -93,7 +84,7 @@ begin
genLineDir(p, a); genLineDir(p, a);
expr(p, a.sons[2], v.loc); expr(p, a.sons[2], v.loc);
end; end;
genObjectInit(p, v); // XXX: correct position? genObjectInit(p, v.typ, v.loc, true); // correct position
end end
end; end;
@ -147,7 +138,7 @@ begin
it := n.sons[i]; it := n.sons[i];
case it.kind of case it.kind of
nkElifBranch: begin nkElifBranch: begin
a := initLocExpr(p, it.sons[0]); initLocExpr(p, it.sons[0], a);
Lelse := getLabel(p); Lelse := getLabel(p);
appf(p.s[cpsStmts], 'if (!$1) goto $2;$n', [rdLoc(a), Lelse]); appf(p.s[cpsStmts], 'if (!$1) goto $2;$n', [rdLoc(a), Lelse]);
freeTemp(p, a); freeTemp(p, a);
@ -177,17 +168,23 @@ begin
genLineDir(p, t); genLineDir(p, t);
assert(sonsLen(t) = 2); assert(sonsLen(t) = 2);
inc(p.labels); inc(p.labels);
Labl := con('L'+'', toRope(p.labels)); Labl := con('LA', toRope(p.labels));
len := length(p.blocks); len := length(p.blocks);
setLength(p.blocks, len+1); setLength(p.blocks, len+1);
p.blocks[len].id := p.labels; // positive because we use it right away: p.blocks[len].id := -p.labels; // negative because it isn't used yet
p.blocks[len].nestedTryStmts := p.nestedTryStmts; p.blocks[len].nestedTryStmts := p.nestedTryStmts;
app(p.s[cpsStmts], 'while (1) {' + tnl); app(p.s[cpsStmts], 'while (1) {' + tnl);
a := initLocExpr(p, t.sons[0]); initLocExpr(p, t.sons[0], a);
appf(p.s[cpsStmts], 'if (!$1) goto $2;$n', [rdLoc(a), Labl]); if (t.sons[0].kind <> nkIntLit) or (t.sons[0].intVal = 0) then begin
p.blocks[len].id := abs(p.blocks[len].id);
appf(p.s[cpsStmts], 'if (!$1) goto $2;$n', [rdLoc(a), Labl]);
end;
freeTemp(p, a); freeTemp(p, a);
genStmts(p, t.sons[1]); genStmts(p, t.sons[1]);
appf(p.s[cpsStmts], '} $1: ;$n', [Labl]); if p.blocks[len].id > 0 then
appf(p.s[cpsStmts], '} $1: ;$n', [Labl])
else
app(p.s[cpsStmts], '}'+tnl);
setLength(p.blocks, length(p.blocks)-1) setLength(p.blocks, length(p.blocks)-1)
end; end;
@ -210,7 +207,7 @@ begin
if t.kind = nkBlockExpr then genStmtListExpr(p, t.sons[1], d) if t.kind = nkBlockExpr then genStmtListExpr(p, t.sons[1], d)
else genStmts(p, t.sons[1]); else genStmts(p, t.sons[1]);
if p.blocks[idx].id > 0 then // label has been used: if p.blocks[idx].id > 0 then // label has been used:
appf(p.s[cpsStmts], 'L$1: ;$n', [toRope(p.blocks[idx].id)]); appf(p.s[cpsStmts], 'LA$1: ;$n', [toRope(p.blocks[idx].id)]);
setLength(p.blocks, idx) setLength(p.blocks, idx)
end; end;
@ -236,7 +233,7 @@ begin
end; end;
p.blocks[idx].id := abs(p.blocks[idx].id); // label is used p.blocks[idx].id := abs(p.blocks[idx].id); // label is used
finishTryStmt(p, p.nestedTryStmts - p.blocks[idx].nestedTryStmts); finishTryStmt(p, p.nestedTryStmts - p.blocks[idx].nestedTryStmts);
appf(p.s[cpsStmts], 'goto L$1;$n', [toRope(p.blocks[idx].id)]) appf(p.s[cpsStmts], 'goto LA$1;$n', [toRope(p.blocks[idx].id)])
end; end;
procedure genAsmStmt(p: BProc; t: PNode); procedure genAsmStmt(p: BProc; t: PNode);
@ -287,7 +284,7 @@ begin
genLineDir(p, t); genLineDir(p, t);
if t.sons[0] <> nil then begin if t.sons[0] <> nil then begin
if gCmd <> cmdCompileToCpp then useMagic(p.module, 'raiseException'); if gCmd <> cmdCompileToCpp then useMagic(p.module, 'raiseException');
a := InitLocExpr(p, t.sons[0]); InitLocExpr(p, t.sons[0], a);
e := rdLoc(a); e := rdLoc(a);
freeTemp(p, a); freeTemp(p, a);
typ := t.sons[0].typ; typ := t.sons[0].typ;
@ -324,15 +321,15 @@ begin
len := sonsLen(b); len := sonsLen(b);
for i := 0 to len - 2 do begin for i := 0 to len - 2 do begin
if b.sons[i].kind = nkRange then begin if b.sons[i].kind = nkRange then begin
x := initLocExpr(p, b.sons[i].sons[0]); initLocExpr(p, b.sons[i].sons[0], x);
y := initLocExpr(p, b.sons[i].sons[1]); initLocExpr(p, b.sons[i].sons[1], y);
freeTemp(p, x); freeTemp(p, x);
freeTemp(p, y); freeTemp(p, y);
appf(p.s[cpsStmts], rangeFormat, appf(p.s[cpsStmts], rangeFormat,
[rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl]) [rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
end end
else begin else begin
x := initLocExpr(p, b.sons[i]); initLocExpr(p, b.sons[i], x);
freeTemp(p, x); freeTemp(p, x);
appf(p.s[cpsStmts], eqFormat, appf(p.s[cpsStmts], eqFormat,
[rdCharLoc(e), rdCharLoc(x), labl]) [rdCharLoc(e), rdCharLoc(x), labl])
@ -347,7 +344,7 @@ var
begin begin
Lend := getLabel(p); Lend := getLabel(p);
for i := 1 to sonsLen(t) - 1 do begin for i := 1 to sonsLen(t) - 1 do begin
appf(p.s[cpsStmts], 'L$1: ;$n', [toRope(labId+i)]); appf(p.s[cpsStmts], 'LA$1: ;$n', [toRope(labId+i)]);
if t.sons[i].kind = nkOfBranch then begin if t.sons[i].kind = nkOfBranch then begin
len := sonsLen(t.sons[i]); len := sonsLen(t.sons[i]);
genStmts(p, t.sons[i].sons[len-1]); genStmts(p, t.sons[i].sons[len-1]);
@ -366,17 +363,17 @@ var
a: TLoc; a: TLoc;
i, labId: int; i, labId: int;
begin begin
a := initLocExpr(p, t.sons[0]); initLocExpr(p, t.sons[0], a);
// fist pass: gnerate ifs+goto: // fist pass: gnerate ifs+goto:
labId := p.labels; labId := p.labels;
for i := 1 to sonsLen(t) - 1 do begin for i := 1 to sonsLen(t) - 1 do begin
inc(p.labels); inc(p.labels);
if t.sons[i].kind = nkOfBranch then if t.sons[i].kind = nkOfBranch then
genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat, genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat,
con('L'+'', toRope(p.labels))) con('LA', toRope(p.labels)))
else else
// else statement // else statement
appf(p.s[cpsStmts], 'goto L$1;$n', [toRope(p.labels)]); appf(p.s[cpsStmts], 'goto LA$1;$n', [toRope(p.labels)]);
end; end;
// second pass: generate statements // second pass: generate statements
genCaseSecondPass(p, t, labId); genCaseSecondPass(p, t, labId);
@ -416,13 +413,13 @@ begin
else begin else begin
a := 0; a := 0;
for i := 0 to Length(s)-1 do begin for i := 0 to Length(s)-1 do begin
a := a +{%} Ord(s[i]); a := a +{%} int32(Ord(s[i]));
a := a +{%} a shl 10; a := a +{%} a shl int32(10);
a := a xor (a shr 6); a := a xor (a shr int32(6));
end; end;
a := a +{%} a shl 3; a := a +{%} a shl int32(3);
a := a xor (a shr 11); a := a xor (a shr int32(11));
a := a +{%} a shl 15; a := a +{%} a shl int32(15);
result := a result := a
end end
end; end;
@ -450,7 +447,7 @@ begin
len := sonsLen(b); len := sonsLen(b);
for i := 0 to len - 2 do begin for i := 0 to len - 2 do begin
assert(b.sons[i].kind <> nkRange); assert(b.sons[i].kind <> nkRange);
x := initLocExpr(p, b.sons[i]); initLocExpr(p, b.sons[i], x);
freeTemp(p, x); freeTemp(p, x);
assert(b.sons[i].kind in [nkStrLit..nkTripleStrLit]); assert(b.sons[i].kind in [nkStrLit..nkTripleStrLit]);
j := int(hashString(b.sons[i].strVal) and high(branches)); j := int(hashString(b.sons[i].strVal) and high(branches));
@ -473,14 +470,16 @@ begin
if strings > stringCaseThreshold then begin if strings > stringCaseThreshold then begin
useMagic(p.module, 'hashString'); useMagic(p.module, 'hashString');
bitMask := nmath.nextPowerOfTwo(strings)-1; bitMask := nmath.nextPowerOfTwo(strings)-1;
{@ignore}
setLength(branches, bitMask+1); setLength(branches, bitMask+1);
a := initLocExpr(p, t.sons[0]); {@emit newSeq(branches, bitMask+1);}
initLocExpr(p, t.sons[0], a);
// fist pass: gnerate ifs+goto: // fist pass: gnerate ifs+goto:
labId := p.labels; labId := p.labels;
for i := 1 to sonsLen(t) - 1 do begin for i := 1 to sonsLen(t) - 1 do begin
inc(p.labels); inc(p.labels);
if t.sons[i].kind = nkOfBranch then if t.sons[i].kind = nkOfBranch then
genCaseStringBranch(p, t.sons[i], a, con('L'+'', toRope(p.labels)), genCaseStringBranch(p, t.sons[i], a, con('LA', toRope(p.labels)),
branches) branches)
else begin else begin
// else statement: nothing to do yet // else statement: nothing to do yet
@ -497,7 +496,7 @@ begin
app(p.s[cpsStmts], '}' + tnl); app(p.s[cpsStmts], '}' + tnl);
// else statement: // else statement:
if t.sons[sonsLen(t)-1].kind <> nkOfBranch then if t.sons[sonsLen(t)-1].kind <> nkOfBranch then
appf(p.s[cpsStmts], 'goto L$1;$n', [toRope(p.labels)]); appf(p.s[cpsStmts], 'goto LA$1;$n', [toRope(p.labels)]);
// third pass: generate statements // third pass: generate statements
genCaseSecondPass(p, t, labId); genCaseSecondPass(p, t, labId);
freeTemp(p, a); freeTemp(p, a);
@ -540,7 +539,7 @@ begin
break break
end; end;
if canGenerateSwitch then begin if canGenerateSwitch then begin
a := initLocExpr(p, t.sons[0]); initLocExpr(p, t.sons[0], a);
appf(p.s[cpsStmts], 'switch ($1) {$n', [rdCharLoc(a)]); appf(p.s[cpsStmts], 'switch ($1) {$n', [rdCharLoc(a)]);
freeTemp(p, a); freeTemp(p, a);
for i := 1 to sonsLen(t)-1 do begin for i := 1 to sonsLen(t)-1 do begin
@ -821,7 +820,7 @@ var
a: TLoc; a: TLoc;
begin begin
genLineDir(p, e); // BUGFIX genLineDir(p, e); // BUGFIX
a := InitLocExpr(p, e.sons[0]); InitLocExpr(p, e.sons[0], a);
assert(a.t <> nil); assert(a.t <> nil);
expr(p, e.sons[1], a); expr(p, e.sons[1], a);
freeTemp(p, a) freeTemp(p, a)
@ -837,10 +836,10 @@ begin
if inCheckpoint(t.info) then if inCheckpoint(t.info) then
MessageOut(renderTree(t)); MessageOut(renderTree(t));
case t.kind of case t.kind of
nkEmpty: begin end; // nothing to do! nkEmpty: begin end; // nothing to do!
nkStmtList: nkStmtList: begin
for i := 0 to sonsLen(t) - 1 do for i := 0 to sonsLen(t)-1 do genStmts(p, t.sons[i]);
genStmts(p, t.sons[i]); end;
nkBlockStmt: genBlock(p, t, a); nkBlockStmt: genBlock(p, t, a);
nkIfStmt: genIfStmt(p, t); nkIfStmt: genIfStmt(p, t);
nkWhileStmt: genWhileStmt(p, t); nkWhileStmt: genWhileStmt(p, t);
@ -852,23 +851,25 @@ begin
nkBreakStmt: genBreakStmt(p, t); nkBreakStmt: genBreakStmt(p, t);
nkCall: begin nkCall: begin
genLineDir(p, t); genLineDir(p, t);
a := initLocExpr(p, t); initLocExpr(p, t, a);
freeTemp(p, a); freeTemp(p, a);
end; end;
nkAsgn: genAsgn(p, t); nkAsgn: genAsgn(p, t);
nkDiscardStmt: begin nkDiscardStmt: begin
genLineDir(p, t); genLineDir(p, t);
a := initLocExpr(p, t.sons[0]); initLocExpr(p, t.sons[0], a);
freeTemp(p, a) freeTemp(p, a)
end; end;
nkAsmStmt: genAsmStmt(p, t); nkAsmStmt: genAsmStmt(p, t);
nkTryStmt: nkTryStmt: begin
if gCmd = cmdCompileToCpp then genTryStmtCpp(p, t) if gCmd = cmdCompileToCpp then genTryStmtCpp(p, t)
else genTryStmt(p, t); else genTryStmt(p, t);
end;
nkRaiseStmt: genRaiseStmt(p, t); nkRaiseStmt: genRaiseStmt(p, t);
nkTypeSection: begin nkTypeSection: begin
// nothing to do: // we have to emit the type information for object types here to support
// we generate only when the symbol is accessed // seperate compilation:
genTypeSection(p.module, t);
end; end;
nkCommentStmt, nkNilLit, nkIteratorDef, nkIncludeStmt, nkImportStmt, nkCommentStmt, nkNilLit, nkIteratorDef, nkIncludeStmt, nkImportStmt,
nkFromStmt, nkTemplateDef, nkMacroDef: begin end; nkFromStmt, nkTemplateDef, nkMacroDef: begin end;

View file

@ -7,16 +7,27 @@
// distribution, for details about the copyright. // distribution, for details about the copyright.
// //
//var
// newDummyVar: int; // just to check the rodgen mechanism
// ------------------------- Name Mangling -------------------------------- // ------------------------- Name Mangling --------------------------------
function mangle(const name: string): string; function mangle(const name: string): string;
var var
i: int; i: int;
begin begin
if name[strStart] in ['A'..'Z', '0'..'9', 'a'..'z'] then case name[strStart] of
result := toUpper(name[strStart])+'' 'a'..'z': begin
else result := '';
result := 'HEX' + toHex(ord(name[strStart]), 2); addChar(result, chr(ord(name[strStart]) - ord('a') + ord('A')));
end;
'0'..'9', 'A'..'Z': begin
result := '';
addChar(result, name[strStart]);
end;
else
result := 'HEX' + toHex(ord(name[strStart]), 2);
end;
for i := strStart+1 to length(name) + strStart-1 do begin for i := strStart+1 to length(name) + strStart-1 do begin
case name[i] of case name[i] of
'A'..'Z': addChar(result, chr(ord(name[i]) - ord('A') + ord('a'))); 'A'..'Z': addChar(result, chr(ord(name[i]) - ord('A') + ord('a')));
@ -29,11 +40,28 @@ end;
function mangleName(s: PSym): PRope; function mangleName(s: PSym): PRope;
begin begin
result := ropef('$1_$2', [toRope(mangle(s.name.s)), toRope(s.id)]); result := s.loc.r;
if optGenMapping in gGlobalOptions then if result = nil then begin
if s.owner <> nil then result := toRope(mangle(s.name.s));
appf(gMapping, '$1.$2 $3$n', app(result, '_'+'');
[toRope(s.owner.Name.s), toRope(s.name.s), result]) app(result, toRope(s.id));
if optGenMapping in gGlobalOptions then
if s.owner <> nil then
appf(gMapping, '"$1.$2": $3$n',
[toRope(s.owner.Name.s), toRope(s.name.s), result]);
s.loc.r := result;
end
end;
function getTypeName(typ: PType): PRope;
begin
if (typ.sym <> nil) and ([sfImportc, sfExportc] * typ.sym.flags <> []) then
result := typ.sym.loc.r
else begin
if typ.loc.r = nil then typ.loc.r := con('TY', toRope(typ.id));
result := typ.loc.r
end;
if result = nil then InternalError('getTypeName: ' + typeKindToStr[typ.kind]);
end; end;
// ------------------------------ C type generator ------------------------ // ------------------------------ C type generator ------------------------
@ -44,7 +72,7 @@ begin
tyNone: result := ctVoid; tyNone: result := ctVoid;
tyBool: result := ctBool; tyBool: result := ctBool;
tyChar: result := ctChar; tyChar: result := ctChar;
tyEmptySet, tySet: begin tySet: begin
case int(getSize(typ)) of case int(getSize(typ)) of
1: result := ctInt8; 1: result := ctInt8;
2: result := ctInt16; 2: result := ctInt16;
@ -90,7 +118,8 @@ begin
end end
end; end;
function getTypeDesc(m: BModule; typ: PType): PRope; forward; function getTypeDescAux(m: BModule; typ: PType;
var check: TIntSet): PRope; forward;
function needsComplexAssignment(typ: PType): bool; function needsComplexAssignment(typ: PType): bool;
begin begin
@ -107,7 +136,8 @@ begin
result := true result := true
else begin else begin
case mapType(rettype) of case mapType(rettype) of
ctArray: result := true; ctArray:
result := not (skipGeneric(rettype).kind in [tyVar, tyRef, tyPtr]);
ctStruct: result := needsComplexAssignment(skipGeneric(rettype)); ctStruct: result := needsComplexAssignment(skipGeneric(rettype));
else result := false; else result := false;
end end
@ -119,18 +149,20 @@ const
'N_STDCALL', 'N_CDECL', 'N_SAFECALL', 'N_SYSCALL', 'N_STDCALL', 'N_CDECL', 'N_SAFECALL', 'N_SYSCALL',
// this is probably not correct for all platforms, // this is probably not correct for all platforms,
// but one can //define it to what you want so there will no problem // but one can //define it to what you want so there will no problem
'N_INLINE', 'N_FASTCALL', 'N_CLOSURE', 'N_NOCONV'); 'N_INLINE', 'N_NOINLINE', 'N_FASTCALL', 'N_CLOSURE', 'N_NOCONV');
function CacheGetType(const tab: TIdTable; key: PType): PRope; function CacheGetType(const tab: TIdTable; key: PType): PRope;
begin begin
// returns nil if we need to declare this type // returns nil if we need to declare this type
result := PRope(TableGetType(tab, key)) // since types are now unique via the ``GetUniqueType`` mechanism, this slow
// linear search is not necessary anymore:
result := PRope(IdTableGet(tab, key))
end; end;
function getTempName(): PRope; function getTempName(): PRope;
begin begin
inc(gUnique); result := con('TMP', toRope(gId));
result := con('T'+'', toRope(gUnique)) inc(gId);
end; end;
function ccgIntroducedPtr(s: PSym): bool; function ccgIntroducedPtr(s: PSym): bool;
@ -166,7 +198,8 @@ begin
end end
end; end;
procedure genProcParams(m: BModule; t: PType; out rettype, params: PRope); procedure genProcParams(m: BModule; t: PType; out rettype, params: PRope;
var check: TIntSet);
var var
i, j: int; i, j: int;
param: PSym; param: PSym;
@ -177,12 +210,12 @@ begin
// C cannot return arrays (what a poor language...) // C cannot return arrays (what a poor language...)
rettype := toRope('void') rettype := toRope('void')
else else
rettype := getTypeDesc(m, t.sons[0]); rettype := getTypeDescAux(m, t.sons[0], check);
for i := 1 to sonsLen(t.n)-1 do begin for i := 1 to sonsLen(t.n)-1 do begin
if t.n.sons[i].kind <> nkSym then InternalError(t.n.info, 'genProcParams'); if t.n.sons[i].kind <> nkSym then InternalError(t.n.info, 'genProcParams');
param := t.n.sons[i].sym; param := t.n.sons[i].sym;
fillLoc(param.loc, locParam, param.typ, mangleName(param), OnStack); fillLoc(param.loc, locParam, param.typ, mangleName(param), OnStack);
app(params, getTypeDesc(m, param.typ)); app(params, getTypeDescAux(m, param.typ, check));
if ccgIntroducedPtr(param) then begin if ccgIntroducedPtr(param) then begin
app(params, '*'+''); app(params, '*'+'');
include(param.loc.flags, lfIndirect); include(param.loc.flags, lfIndirect);
@ -203,7 +236,7 @@ begin
end; end;
if (t.sons[0] <> nil) and isInvalidReturnType(t.sons[0]) then begin if (t.sons[0] <> nil) and isInvalidReturnType(t.sons[0]) then begin
if params <> nil then app(params, ', '); if params <> nil then app(params, ', ');
app(params, getTypeDesc(m, t.sons[0])); app(params, getTypeDescAux(m, t.sons[0], check));
if mapType(t.sons[0]) <> ctArray then app(params, '*'+''); if mapType(t.sons[0]) <> ctArray then app(params, '*'+'');
app(params, ' Result'); app(params, ' Result');
end; end;
@ -227,25 +260,16 @@ begin
result := (t.sym <> nil) and (sfImportc in t.sym.flags) result := (t.sym <> nil) and (sfImportc in t.sym.flags)
end; end;
function getTypeName(typ: PType): PRope; function typeNameOrLiteral(t: PType; const literal: string): PRope;
begin begin
if (typ.sym <> nil) and ([sfImportc, sfExportc] * typ.sym.flags <> []) then if (t.sym <> nil) and (sfImportc in t.sym.flags) and
result := typ.sym.loc.r (t.sym.magic = mNone) then
else begin result := getTypeName(t)
if typ.loc.r = nil then typ.loc.r := con('Ty', toRope(typ.id));
result := typ.loc.r
end
end;
function typeNameOrLiteral(typ: PType; const literal: string): PRope;
begin
if isImportedType(typ) then
result := getTypeName(typ)
else else
result := toRope(literal) result := toRope(literal)
end; end;
function getSimpleTypeDesc(typ: PType): PRope; function getSimpleTypeDesc(m: BModule; typ: PType): PRope;
const const
NumericalTypeToStr: array [tyInt..tyFloat128] of string = ( NumericalTypeToStr: array [tyInt..tyFloat128] of string = (
'NI', 'NI8', 'NI16', 'NI32', 'NI64', 'NF', 'NF32', 'NF64', 'NF128'); 'NI', 'NI8', 'NI16', 'NI32', 'NI64', 'NF', 'NF32', 'NF64', 'NF128');
@ -267,14 +291,17 @@ begin
end end
end end
end; end;
tyString: result := typeNameOrLiteral(typ, 'string'); tyString: begin
useMagic(m, 'NimStringDesc');
result := typeNameOrLiteral(typ, 'NimStringDesc*');
end;
tyCstring: result := typeNameOrLiteral(typ, 'NCSTRING'); tyCstring: result := typeNameOrLiteral(typ, 'NCSTRING');
tyBool: result := typeNameOrLiteral(typ, 'NIM_BOOL'); tyBool: result := typeNameOrLiteral(typ, 'NIM_BOOL');
tyChar: result := typeNameOrLiteral(typ, 'NIM_CHAR'); tyChar: result := typeNameOrLiteral(typ, 'NIM_CHAR');
tyNil: result := typeNameOrLiteral(typ, '0'+''); tyNil: result := typeNameOrLiteral(typ, '0'+'');
tyInt..tyFloat128: tyInt..tyFloat128:
result := typeNameOrLiteral(typ, NumericalTypeToStr[typ.Kind]); result := typeNameOrLiteral(typ, NumericalTypeToStr[typ.Kind]);
tyRange: result := getSimpleTypeDesc(typ.sons[0]); tyRange: result := getSimpleTypeDesc(m, typ.sons[0]);
else result := nil; else result := nil;
end end
end; end;
@ -284,7 +311,7 @@ begin
if typ = nil then if typ = nil then
result := toRope('void') result := toRope('void')
else begin else begin
result := getSimpleTypeDesc(typ); result := getSimpleTypeDesc(m, typ);
if result = nil then if result = nil then
result := CacheGetType(m.typeCache, typ) result := CacheGetType(m.typeCache, typ)
end end
@ -325,7 +352,7 @@ begin
end; end;
function genRecordFieldsAux(m: BModule; n: PNode; accessExpr: PRope; function genRecordFieldsAux(m: BModule; n: PNode; accessExpr: PRope;
rectype: PType): PRope; rectype: PType; var check: TIntSet): PRope;
var var
i: int; i: int;
ae, uname, sname, a: PRope; ae, uname, sname, a: PRope;
@ -336,13 +363,14 @@ begin
case n.kind of case n.kind of
nkRecList: begin nkRecList: begin
for i := 0 to sonsLen(n)-1 do begin for i := 0 to sonsLen(n)-1 do begin
app(result, genRecordFieldsAux(m, n.sons[i], accessExpr, rectype)); app(result, genRecordFieldsAux(m, n.sons[i], accessExpr,
rectype, check));
end end
end; end;
nkRecCase: begin nkRecCase: begin
if (n.sons[0].kind <> nkSym) then if (n.sons[0].kind <> nkSym) then
InternalError(n.info, 'genRecordFieldsAux'); InternalError(n.info, 'genRecordFieldsAux');
app(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype)); app(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype, check));
uname := toRope(mangle(n.sons[0].sym.name.s)+ 'U'); uname := toRope(mangle(n.sons[0].sym.name.s)+ 'U');
if accessExpr <> nil then ae := ropef('$1.$2', [accessExpr, uname]) if accessExpr <> nil then ae := ropef('$1.$2', [accessExpr, uname])
else ae := uname; else ae := uname;
@ -354,14 +382,14 @@ begin
if k.kind <> nkSym then begin if k.kind <> nkSym then begin
sname := con('S'+'', toRope(i)); sname := con('S'+'', toRope(i));
a := genRecordFieldsAux(m, k, ropef('$1.$2', [ae, sname]), a := genRecordFieldsAux(m, k, ropef('$1.$2', [ae, sname]),
rectype); rectype, check);
if a <> nil then begin if a <> nil then begin
app(result, 'struct {'); app(result, 'struct {');
app(result, a); app(result, a);
appf(result, '} $1;$n', [sname]); appf(result, '} $1;$n', [sname]);
end end
end end
else app(result, genRecordFieldsAux(m, k, ae, rectype)); else app(result, genRecordFieldsAux(m, k, ae, rectype, check));
end; end;
else internalError('genRecordFieldsAux(record case branch)'); else internalError('genRecordFieldsAux(record case branch)');
end; end;
@ -375,18 +403,19 @@ begin
if accessExpr <> nil then ae := ropef('$1.$2', [accessExpr, sname]) if accessExpr <> nil then ae := ropef('$1.$2', [accessExpr, sname])
else ae := sname; else ae := sname;
fillLoc(field.loc, locField, field.typ, ae, OnUnknown); fillLoc(field.loc, locField, field.typ, ae, OnUnknown);
appf(result, '$1 $2;$n', [getTypeDesc(m, field.loc.t), sname]) appf(result, '$1 $2;$n', [getTypeDescAux(m, field.loc.t, check), sname])
end; end;
else internalError(n.info, 'genRecordFieldsAux()'); else internalError(n.info, 'genRecordFieldsAux()');
end end
end; end;
function getRecordFields(m: BModule; typ: PType): PRope; function getRecordFields(m: BModule; typ: PType; var check: TIntSet): PRope;
begin begin
result := genRecordFieldsAux(m, typ.n, nil, typ); result := genRecordFieldsAux(m, typ.n, nil, typ, check);
end; end;
function getRecordDesc(m: BModule; typ: PType; name: PRope): PRope; function getRecordDesc(m: BModule; typ: PType; name: PRope;
var check: TIntSet): PRope;
var var
desc: PRope; desc: PRope;
hasField: bool; hasField: bool;
@ -406,18 +435,18 @@ begin
end end
else if gCmd = cmdCompileToCpp then begin else if gCmd = cmdCompileToCpp then begin
result := ropef('struct $1 : public $2 {$n', result := ropef('struct $1 : public $2 {$n',
[name, getTypeDesc(m, typ.sons[0])]); [name, getTypeDescAux(m, typ.sons[0], check)]);
hasField := true hasField := true
end end
else begin else begin
result := ropef('struct $1 {$n $2 Sup;$n', result := ropef('struct $1 {$n $2 Sup;$n',
[name, getTypeDesc(m, typ.sons[0])]); [name, getTypeDescAux(m, typ.sons[0], check)]);
hasField := true hasField := true
end end
end end
else else
result := ropef('struct $1 {$n', [name]); result := ropef('struct $1 {$n', [name]);
desc := getRecordFields(m, typ); desc := getRecordFields(m, typ, check);
if (desc = nil) and not hasField then if (desc = nil) and not hasField then
// no fields in struct are not valid in C, so generate a dummy: // no fields in struct are not valid in C, so generate a dummy:
appf(result, 'char dummy;$n', []) appf(result, 'char dummy;$n', [])
@ -435,7 +464,7 @@ begin
m.typeStack[L] := typ; m.typeStack[L] := typ;
end; end;
function getTypeDesc(m: BModule; typ: PType): PRope; function getTypeDescAux(m: BModule; typ: PType; var check: TIntSet): PRope;
// returns only the type's name // returns only the type's name
var var
name, rettype, desc, recdesc: PRope; name, rettype, desc, recdesc: PRope;
@ -443,12 +472,18 @@ var
t, et: PType; t, et: PType;
begin begin
t := getUniqueType(typ); t := getUniqueType(typ);
if t = nil then InternalError('getTypeDesc: t == nil'); if t = nil then InternalError('getTypeDescAux: t == nil');
if t.sym <> nil then useHeader(m, t.sym); if t.sym <> nil then useHeader(m, t.sym);
result := getTypePre(m, t); result := getTypePre(m, t);
if result <> nil then exit; if result <> nil then exit;
if IntSetContainsOrIncl(check, t.id) then begin
InternalError('cannot generate C type for: ' + typeToString(typ));
// XXX: this BUG is hard to fix -> we need to introduce helper structs,
// but determining when this needs to be done is hard. We should split
// C type generation into an analysis and a code generation phase somehow.
end;
case t.Kind of case t.Kind of
tyRef, tyPtr, tyVar, tyOpenArray: begin tyRef, tyPtr, tyVar: begin
et := getUniqueType(t.sons[0]); et := getUniqueType(t.sons[0]);
if et.kind in [tyArrayConstr, tyArray, tyOpenArray] then if et.kind in [tyArrayConstr, tyArray, tyOpenArray] then
et := getUniqueType(elemType(et)); et := getUniqueType(elemType(et));
@ -469,15 +504,20 @@ begin
end; end;
else begin else begin
// else we have a strong dependency :-( // else we have a strong dependency :-(
result := con(getTypeDesc(m, et), '*'+''); result := con(getTypeDescAux(m, et, check), '*'+'');
IdTablePut(m.typeCache, t, result) IdTablePut(m.typeCache, t, result)
end end
end end
end; end;
tyOpenArray: begin
et := getUniqueType(t.sons[0]);
result := con(getTypeDescAux(m, et, check), '*'+'');
IdTablePut(m.typeCache, t, result)
end;
tyProc: begin tyProc: begin
result := getTypeName(t); result := getTypeName(t);
IdTablePut(m.typeCache, t, result); IdTablePut(m.typeCache, t, result);
genProcParams(m, t, rettype, desc); genProcParams(m, t, rettype, desc, check);
if not isImportedType(t) then begin if not isImportedType(t) then begin
if t.callConv <> ccClosure then if t.callConv <> ccClosure then
appf(m.s[cfsTypes], 'typedef $1_PTR($2, $3) $4;$n', appf(m.s[cfsTypes], 'typedef $1_PTR($2, $3) $4;$n',
@ -501,12 +541,14 @@ begin
end; end;
assert(CacheGetType(m.typeCache, t) = nil); assert(CacheGetType(m.typeCache, t) = nil);
IdTablePut(m.typeCache, t, con(result, '*'+'')); IdTablePut(m.typeCache, t, con(result, '*'+''));
if not isImportedType(t) then if not isImportedType(t) then begin
useMagic(m, 'TGenericSeq');
appf(m.s[cfsSeqTypes], appf(m.s[cfsSeqTypes],
'struct $2 {$n' + 'struct $2 {$n' +
' NI len, space;$n' + ' TGenericSeq Sup;$n' +
' $1 data[SEQ_DECL_SIZE];$n' + ' $1 data[SEQ_DECL_SIZE];$n' +
'};$n', [getTypeDesc(m, t.sons[0]), result]); '};$n', [getTypeDescAux(m, t.sons[0], check), result]);
end;
app(result, '*'+''); app(result, '*'+'');
end; end;
tyArrayConstr, tyArray: begin tyArrayConstr, tyArray: begin
@ -516,7 +558,7 @@ begin
IdTablePut(m.typeCache, t, result); IdTablePut(m.typeCache, t, result);
if not isImportedType(t) then if not isImportedType(t) then
appf(m.s[cfsTypes], 'typedef $1 $2[$3];$n', appf(m.s[cfsTypes], 'typedef $1 $2[$3];$n',
[getTypeDesc(m, t.sons[1]), result, ToRope(n)]) [getTypeDescAux(m, t.sons[1], check), result, ToRope(n)])
end; end;
tyObject, tyTuple: begin tyObject, tyTuple: begin
result := CacheGetType(m.forwTypeCache, t); result := CacheGetType(m.forwTypeCache, t);
@ -528,7 +570,8 @@ begin
IdTablePut(m.forwTypeCache, t, result) IdTablePut(m.forwTypeCache, t, result)
end; end;
IdTablePut(m.typeCache, t, result); IdTablePut(m.typeCache, t, result);
recdesc := getRecordDesc(m, t, result); // always call for sideeffects // always call for sideeffects:
recdesc := getRecordDesc(m, t, result, check);
if not isImportedType(t) then app(m.s[cfsTypes], recdesc); if not isImportedType(t) then app(m.s[cfsTypes], recdesc);
end; end;
tySet: begin tySet: begin
@ -546,14 +589,22 @@ begin
end end
end end
end; end;
tyGenericInst: result := getTypeDesc(m, lastSon(t)); tyGenericInst: result := getTypeDescAux(m, lastSon(t), check);
else begin else begin
InternalError('getTypeDesc(' + typeKindToStr[t.kind] + ')'); InternalError('getTypeDescAux(' + typeKindToStr[t.kind] + ')');
result := nil result := nil
end end
end end
end; end;
function getTypeDesc(m: BModule; typ: PType): PRope;
var
check: TIntSet;
begin
IntSetInit(check);
result := getTypeDescAux(m, typ, check);
end;
procedure finishTypeDescriptions(m: BModule); procedure finishTypeDescriptions(m: BModule);
var var
i: int; i: int;
@ -568,14 +619,16 @@ end;
function genProcHeader(m: BModule; prc: PSym): PRope; function genProcHeader(m: BModule; prc: PSym): PRope;
var var
rettype, params: PRope; rettype, params: PRope;
check: TIntSet;
begin begin
// using static is needed for inline procs // using static is needed for inline procs
if (prc.typ.callConv = ccInline) then if (prc.typ.callConv = ccInline) then
result := toRope('static ') result := toRope('static ')
else else
result := nil; result := nil;
IntSetInit(check);
fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), OnUnknown); fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), OnUnknown);
genProcParams(m, prc.typ, rettype, params); genProcParams(m, prc.typ, rettype, params, check);
appf(result, '$1($2, $3)$4', appf(result, '$1($2, $3)$4',
[toRope(CallingConvToStr[prc.typ.callConv]), [toRope(CallingConvToStr[prc.typ.callConv]),
rettype, prc.loc.r, params]) rettype, prc.loc.r, params])
@ -583,25 +636,33 @@ end;
// ----------------------- type information ---------------------------------- // ----------------------- type information ----------------------------------
var
gTypeInfoGenerated: TIntSet;
function genTypeInfo(m: BModule; typ: PType): PRope; forward; function genTypeInfo(m: BModule; typ: PType): PRope; forward;
procedure allocMemTI(m: BModule; name: PRope); function getNimNode(m: BModule): PRope;
begin
result := ropef('$1[$2]', [m.typeNodesName, toRope(m.typeNodes)]);
inc(m.typeNodes);
end;
function getNimType(m: BModule): PRope;
begin
result := ropef('$1[$2]', [m.nimTypesName, toRope(m.nimTypes)]);
inc(m.nimTypes);
end;
procedure allocMemTI(m: BModule; typ: PType; name: PRope);
var var
tmp: PRope; tmp: PRope;
begin begin
tmp := getTempName(); tmp := getNimType(m);
appf(m.s[cfsTypeInit1], 'static TNimType $1;$n', [tmp]);
appf(m.s[cfsTypeInit2], '$2 = &$1;$n', [tmp, name]); appf(m.s[cfsTypeInit2], '$2 = &$1;$n', [tmp, name]);
end; end;
procedure genTypeInfoAuxBase(m: BModule; typ: PType; name, base: PRope); procedure genTypeInfoAuxBase(m: BModule; typ: PType; name, base: PRope);
var var
nimtypeKind: int; nimtypeKind, flags: int;
begin begin
allocMemTI(m, name); allocMemTI(m, typ, name);
if (typ.kind = tyObject) and (tfFinal in typ.flags) if (typ.kind = tyObject) and (tfFinal in typ.flags)
and (typ.sons[0] = nil) then and (typ.sons[0] = nil) then
nimtypeKind := ord(high(TTypeKind))+1 // tyPureObject nimtypeKind := ord(high(TTypeKind))+1 // tyPureObject
@ -612,7 +673,15 @@ begin
'$1->kind = $3;$n' + '$1->kind = $3;$n' +
'$1->base = $4;$n', [ '$1->base = $4;$n', [
name, getTypeDesc(m, typ), toRope(nimtypeKind), base]); name, getTypeDesc(m, typ), toRope(nimtypeKind), base]);
appf(m.s[cfsVars], 'TNimType* $1;$n', [name]); // compute type flags for GC optimization
flags := 0;
if not containsGarbageCollectedRef(typ) then flags := flags or 1;
if not canFormAcycle(typ) then flags := flags or 2;
//else MessageOut('can contain a cycle: ' + typeToString(typ));
if flags <> 0 then
appf(m.s[cfsTypeInit3], '$1->flags = $2;$n', [name, toRope(flags)]);
appf(m.s[cfsVars], 'TNimType* $1; /* $2 */$n',
[name, toRope(typeToString(typ))]);
end; end;
procedure genTypeInfoAux(m: BModule; typ: PType; name: PRope); procedure genTypeInfoAux(m: BModule; typ: PType; name: PRope);
@ -643,10 +712,8 @@ begin
appf(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n', appf(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n',
[tmp, toRope(len)]); [tmp, toRope(len)]);
for i := 0 to len-1 do begin for i := 0 to len-1 do begin
tmp2 := getTempName(); tmp2 := getNimNode(m);
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp2]); appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n', [tmp, toRope(i), tmp2]);
appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n',
[tmp, toRope(i), tmp2]);
genObjectFields(m, typ, n.sons[i], tmp2); genObjectFields(m, typ, n.sons[i], tmp2);
end; end;
appf(m.s[cfsTypeInit3], appf(m.s[cfsTypeInit3],
@ -676,10 +743,8 @@ begin
[tmp, toRope(lengthOrd(field.typ)+1)]); [tmp, toRope(lengthOrd(field.typ)+1)]);
for i := 1 to len-1 do begin for i := 1 to len-1 do begin
b := n.sons[i]; // branch b := n.sons[i]; // branch
tmp2 := getTempName(); tmp2 := getNimNode(m);
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp2]);
genObjectFields(m, typ, lastSon(b), tmp2); genObjectFields(m, typ, lastSon(b), tmp2);
//writeln(output, renderTree(b.sons[j]));
case b.kind of case b.kind of
nkOfBranch: begin nkOfBranch: begin
if sonsLen(b) < 2 then if sonsLen(b) < 2 then
@ -728,42 +793,54 @@ var
begin begin
if typ.kind = tyObject then genTypeInfoAux(m, typ, name) if typ.kind = tyObject then genTypeInfoAux(m, typ, name)
else genTypeInfoAuxBase(m, typ, name, toRope('0'+'')); else genTypeInfoAuxBase(m, typ, name, toRope('0'+''));
tmp := getTempName(); tmp := getNimNode(m);
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp]);
genObjectFields(m, typ, typ.n, tmp); genObjectFields(m, typ, typ.n, tmp);
appf(m.s[cfsTypeInit3], '$1->node = &$2;$n', [name, tmp]); appf(m.s[cfsTypeInit3], '$1->node = &$2;$n', [name, tmp]);
end; end;
procedure genEnumInfo(m: BModule; typ: PType; name: PRope); procedure genEnumInfo(m: BModule; typ: PType; name: PRope);
var var
tmp, tmp2, tmp3: PRope; nodePtrs, elemNode, enumNames, enumArray, counter, specialCases: PRope;
len, i: int; len, i, firstNimNode: int;
field: PSym; field: PSym;
begin begin
// Type information for enumerations is quite heavy, so we do some
// optimizations here: The ``typ`` field is never set, as it is redundant
// anyway. We generate a cstring array and a loop over it. Exceptional
// positions will be reset after the loop.
genTypeInfoAux(m, typ, name); genTypeInfoAux(m, typ, name);
tmp := getTempName(); nodePtrs := getTempName();
tmp2 := getTempName();
len := sonsLen(typ.n); len := sonsLen(typ.n);
appf(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n' + appf(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n', [nodePtrs, toRope(len)]);
'static TNimNode $3;$n', enumNames := nil;
[tmp, toRope(len), tmp2]); specialCases := nil;
firstNimNode := m.typeNodes;
for i := 0 to len-1 do begin for i := 0 to len-1 do begin
assert(typ.n.sons[i].kind = nkSym); assert(typ.n.sons[i].kind = nkSym);
field := typ.n.sons[i].sym; field := typ.n.sons[i].sym;
tmp3 := getTempName(); elemNode := getNimNode(m);
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp3]); app(enumNames, makeCString(field.name.s));
appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n' + if i < len-1 then app(enumNames, ', '+tnl);
'$3.kind = 1;$n' + if field.position <> i then
'$3.offset = $4;$n' + appf(specialCases, '$1.offset = $2;$n', [elemNode, toRope(field.position)]);
'$3.typ = $5;$n' +
'$3.name = $6;$n',
[tmp, toRope(i), tmp3,
toRope(field.position),
name, makeCString(field.name.s)]);
end; end;
enumArray := getTempName();
counter := getTempName();
appf(m.s[cfsTypeInit1], 'NI $1;$n', [counter]);
appf(m.s[cfsTypeInit1], 'static char* NIM_CONST $1[$2] = {$n$3};$n',
[enumArray, toRope(len), enumNames]);
appf(m.s[cfsTypeInit3], 'for ($1 = 0; $1 < $2; $1++) {$n' +
'$3[$1+$4].kind = 1;$n' +
'$3[$1+$4].offset = $1;$n' +
'$3[$1+$4].name = $5[$1];$n' +
'$6[$1] = &$3[$1+$4];$n' +
'}$n',
[counter, toRope(len), m.typeNodesName, toRope(firstNimNode),
enumArray, nodePtrs]);
app(m.s[cfsTypeInit3], specialCases);
appf(m.s[cfsTypeInit3], appf(m.s[cfsTypeInit3],
'$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n$4->node = &$1;$n', [ '$1.len = $2; $1.kind = 2; $1.sons = &$3[0];$n$4->node = &$1;$n', [
tmp2, toRope(len), tmp, name]); getNimNode(m), toRope(len), nodePtrs, name]);
end; end;
procedure genSetInfo(m: BModule; typ: PType; name: PRope); procedure genSetInfo(m: BModule; typ: PType; name: PRope);
@ -772,8 +849,7 @@ var
begin begin
assert(typ.sons[0] <> nil); assert(typ.sons[0] <> nil);
genTypeInfoAux(m, typ, name); genTypeInfoAux(m, typ, name);
tmp := getTempName(); tmp := getNimNode(m);
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp]);
appf(m.s[cfsTypeInit3], appf(m.s[cfsTypeInit3],
'$1.len = $2; $1.kind = 0;$n' + '$1.len = $2; $1.kind = 0;$n' +
'$3->node = &$1;$n', [tmp, toRope(firstOrd(typ)), name]); '$3->node = &$1;$n', [tmp, toRope(firstOrd(typ)), name]);
@ -784,28 +860,96 @@ begin
genTypeInfoAuxBase(m, typ, name, genTypeInfo(m, typ.sons[1])); genTypeInfoAuxBase(m, typ, name, genTypeInfo(m, typ.sons[1]));
end; end;
var
gToTypeInfoId: TIiTable;
(* // this does not work any longer thanks to separate compilation:
function getTypeInfoName(t: PType): PRope;
begin
result := ropef('NTI$1', [toRope(t.id)]);
end;*)
function genTypeInfo(m: BModule; typ: PType): PRope; function genTypeInfo(m: BModule; typ: PType): PRope;
var var
t: PType; t: PType;
id: int;
dataGen: bool;
begin begin
t := getUniqueType(typ); t := getUniqueType(typ);
result := ropef('NTI$1', [toRope(t.id)]); id := IiTableGet(gToTypeInfoId, t.id);
if id = invalidKey then begin
dataGen := false;
case t.kind of
tyEnum, tyBool: begin
id := t.id;
dataGen := true
end;
tyObject: begin
if sfPure in t.sym.flags then
id := getID()
else begin
id := t.id;
dataGen := true
end
end
else
id := getID();
end;
IiTablePut(gToTypeInfoId, t.id, id);
end
else
dataGen := true;
result := ropef('NTI$1', [toRope(id)]);
if not IntSetContainsOrIncl(m.typeInfoMarker, t.id) then begin if not IntSetContainsOrIncl(m.typeInfoMarker, t.id) then begin
// declare type information structures: // declare type information structures:
useMagic(m, 'TNimType'); useMagic(m, 'TNimType');
useMagic(m, 'TNimNode'); useMagic(m, 'TNimNode');
appf(m.s[cfsVars], 'extern TNimType* $1;$n', [result]); if dataGen then
appf(m.s[cfsVars], 'extern TNimType* $1; /* $2 */$n',
[result, toRope(typeToString(t))]);
end; end;
if IntSetContainsOrIncl(gTypeInfoGenerated, t.id) then exit; if dataGen then exit;
case t.kind of case t.kind of
tyPointer, tyProc, tyBool, tyChar, tyCString, tyString, tyInt..tyFloat128: tyPointer, tyProc, tyBool, tyChar, tyCString, tyString,
tyInt..tyFloat128, tyVar:
genTypeInfoAuxBase(m, t, result, toRope('0'+'')); genTypeInfoAuxBase(m, t, result, toRope('0'+''));
tyRef, tyPtr, tySequence, tyRange: genTypeInfoAux(m, t, result); tyRef, tyPtr, tySequence, tyRange: genTypeInfoAux(m, t, result);
tyArrayConstr, tyArray: genArrayInfo(m, t, result); tyArrayConstr, tyArray: genArrayInfo(m, t, result);
tySet: genSetInfo(m, t, result); tySet: genSetInfo(m, t, result);
tyEnum: genEnumInfo(m, t, result); tyEnum: genEnumInfo(m, t, result);
tyObject, tyTuple: genObjectInfo(m, t, result); tyObject, tyTuple: genObjectInfo(m, t, result);
tyVar: result := genTypeInfo(m, typ.sons[0]);
else InternalError('genTypeInfo(' + typekindToStr[t.kind] + ')'); else InternalError('genTypeInfo(' + typekindToStr[t.kind] + ')');
end end
end; end;
procedure genTypeSection(m: BModule; n: PNode);
var
i: int;
a: PNode;
t: PType;
begin
for i := 0 to sonsLen(n)-1 do begin
a := n.sons[i];
if a.kind = nkCommentStmt then continue;
if (a.sons[0].kind <> nkSym) then InternalError(a.info, 'genTypeSection');
t := a.sons[0].sym.typ;
if (a.sons[2] = nil)
or not (a.sons[2].kind in [nkSym, nkIdent, nkAccQuoted]) then
if t <> nil then
case t.kind of
tyEnum, tyBool: begin
useMagic(m, 'TNimType');
useMagic(m, 'TNimNode');
genEnumInfo(m, t, ropef('NTI$1', [toRope(t.id)]));
end;
tyObject: begin
if not (sfPure in t.sym.flags) then begin
useMagic(m, 'TNimType');
useMagic(m, 'TNimNode');
genObjectInfo(m, t, ropef('NTI$1', [toRope(t.id)]));
end
end
else begin end
end
end
end;

View file

@ -6,7 +6,6 @@
// See the file "copying.txt", included in this // See the file "copying.txt", included in this
// distribution, for details about the copyright. // distribution, for details about the copyright.
// //
unit ccgutils; unit ccgutils;
interface interface
@ -35,21 +34,28 @@ var
t: PType; t: PType;
h: THash; h: THash;
begin begin
// this was a hotspot in the compiler!
result := key; result := key;
if key = nil then exit; if key = nil then exit;
assert(key.kind <> tyForward); case key.Kind of
if key.kind = tyGenericInst then begin tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString,
result := GetUniqueType(lastSon(key)); tyInt..tyFloat128, tyProc, tyEnum, tyObject, tyAnyEnum: begin end;
exit tyNone, tyForward:
InternalError('GetUniqueType: ' + typeToString(key));
tyGenericParam, tyGeneric, tySequence,
tyOpenArray, tySet, tyVar, tyRef, tyPtr, tyArrayConstr,
tyArray, tyTuple, tyRange: begin
// we have to do a slow linear search because types may need
// to be compared by their structure:
if IdTableHasObjectAsKey(gTypeTable, key) then exit;
for h := 0 to high(gTypeTable.data) do begin
t := PType(gTypeTable.data[h].key);
if (t <> nil) and sameType(t, key) then begin result := t; exit end
end;
IdTablePut(gTypeTable, key, key);
end;
tyGenericInst: result := GetUniqueType(lastSon(key));
end; end;
if IdTableHasObjectAsKey(gTypeTable, key) then exit;
// we have to do a slow linear search because types may need
// to be compared by their structure:
for h := 0 to high(gTypeTable.data) do begin
t := PType(gTypeTable.data[h].key);
if (t <> nil) and sameType(t, key) then begin result := t; exit end
end;
IdTablePut(gTypeTable, key, key);
end; end;
function TableGetType(const tab: TIdTable; key: PType): PObject; function TableGetType(const tab: TIdTable; key: PType): PObject;
@ -102,7 +108,7 @@ begin
end; end;
res := res +{&} toCChar(s[i]); res := res +{&} toCChar(s[i]);
end; end;
res := res +{&} '"'+''; addChar(res, '"');
app(result, toRope(res)); app(result, toRope(res));
end; end;

View file

@ -6,7 +6,6 @@
// See the file "copying.txt", included in this // See the file "copying.txt", included in this
// distribution, for details about the copyright. // distribution, for details about the copyright.
// //
unit cgen; unit cgen;
// This is the new C code generator; much cleaner and faster // This is the new C code generator; much cleaner and faster
@ -19,10 +18,10 @@ interface
uses uses
nsystem, ast, astalgo, strutils, hashes, trees, platform, magicsys, nsystem, ast, astalgo, strutils, hashes, trees, platform, magicsys,
extccomp, options, nversion, nimsets, msgs, crc, bitsets, idents, extccomp, options, nversion, nimsets, msgs, crc, bitsets, idents,
lists, types, ccgutils, nos, ntime, ropes, nmath, backends, lists, types, ccgutils, nos, ntime, ropes, nmath, passes, rodread,
wordrecg, rnimsyn; wordrecg, rnimsyn, treetab;
function CBackend(b: PBackend; module: PSym; const filename: string): PBackend; function cgenPass(): TPass;
implementation implementation
@ -95,7 +94,6 @@ type
// (the vars must be volatile then) // (the vars must be volatile then)
labels: Natural; // for generating unique labels in the C proc labels: Natural; // for generating unique labels in the C proc
blocks: array of TBlock; // nested blocks blocks: array of TBlock; // nested blocks
locals: array of TLoc; // locNone means slot is free again
options: TOptions; // options that should be used for code options: TOptions; // options that should be used for code
// generation; this is the same as prc.options // generation; this is the same as prc.options
// unless prc == nil // unless prc == nil
@ -105,7 +103,9 @@ type
module: BModule; // used to prevent excessive parameter passing module: BModule; // used to prevent excessive parameter passing
end; end;
TTypeSeq = array of PType; TTypeSeq = array of PType;
TCGen = object(TBackend) // represents a C source file TCGen = object(TPassContext) // represents a C source file
module: PSym;
filename: string;
s: TCFileSections; // sections of the C file s: TCFileSections; // sections of the C file
cfilename: string; // filename of the module (including path, cfilename: string; // filename of the module (including path,
// without extension) // without extension)
@ -114,18 +114,21 @@ type
declaredThings: TIntSet; // things we have declared in this .c file declaredThings: TIntSet; // things we have declared in this .c file
debugDeclared: TIntSet; // for debugging purposes debugDeclared: TIntSet; // for debugging purposes
headerFiles: TLinkedList; // needed headers to include headerFiles: TLinkedList; // needed headers to include
//unique: Natural; // for generating unique names
typeInfoMarker: TIntSet; // needed for generating type information typeInfoMarker: TIntSet; // needed for generating type information
initProc: BProc; // code for init procedure initProc: BProc; // code for init procedure
typeStack: TTypeSeq; // used for type generation typeStack: TTypeSeq; // used for type generation
dataCache: TNodeTable;
typeNodes, nimTypes: int;// used for type info generation
typeNodesName, nimTypesName: PRope; // used for type info generation
end; end;
var var
gUnique: Natural;
mainModProcs, mainModInit: PRope; // parts of the main module mainModProcs, mainModInit: PRope; // parts of the main module
gMapping: PRope; // the generated mapping file (if requested) gMapping: PRope; // the generated mapping file (if requested)
gProcProfile: Natural; // proc profile counter
function initLoc(k: TLocKind; typ: PType; s: TStorageLoc): TLoc;
procedure initLoc(var result: TLoc; k: TLocKind; typ: PType; s: TStorageLoc);
begin begin
result.k := k; result.k := k;
result.s := s; result.s := s;
@ -162,11 +165,8 @@ begin
result.options := gOptions; result.options := gOptions;
{@ignore} {@ignore}
setLength(result.blocks, 0); setLength(result.blocks, 0);
setLength(result.locals, 0);
{@emit {@emit
result.blocks := [];} result.blocks := @[];}
{@emit
result.locals := [];}
end; end;
function isSimpleConst(typ: PType): bool; function isSimpleConst(typ: PType): bool;
@ -179,15 +179,12 @@ procedure useHeader(m: BModule; sym: PSym);
begin begin
if lfHeader in sym.loc.Flags then begin if lfHeader in sym.loc.Flags then begin
assert(sym.annex <> nil); assert(sym.annex <> nil);
{@discard} lists.IncludeStr(m.headerFiles, PLib(sym.annex).path) {@discard} lists.IncludeStr(m.headerFiles, sym.annex.path)
end end
end; end;
procedure UseMagic(m: BModule; const name: string); forward; procedure UseMagic(m: BModule; const name: string); forward;
// ----------------------------- name mangling
// +++++++++++++++++++++++++++++ type generation
// +++++++++++++++++++++++++++++ type info generation
{$include 'ccgtypes.pas'} {$include 'ccgtypes.pas'}
// ------------------------------ Manager of temporaries ------------------ // ------------------------------ Manager of temporaries ------------------
@ -198,41 +195,20 @@ begin
result := sameType(skipGenericRange(a), skipGenericRange(b)) result := sameType(skipGenericRange(a), skipGenericRange(b))
end; end;
function getTemp(p: BProc; t: PType): TLoc; procedure getTemp(p: BProc; t: PType; var result: TLoc);
var begin
i, index: int; inc(p.labels);
name: PRope; result.r := con('LOC', toRope(p.labels));
begin (* appf(p.s[cpsLocals], '$1 $2;$n', [getTypeDesc(p.module, t), result.r]);
for i := 0 to high(p.locals) do begin result.k := locTemp;
assert(i = p.locals[i].a); result.a := -1;
if (p.locals[i].k = locNone) and beEqualTypes(p.locals[i].t, t) then begin result.t := getUniqueType(t);
// free slot of the appropriate type? result.s := OnStack;
p.locals[i].k := locTemp; // is filled again result.flags := {@set}[];
result := p.locals[i];
exit
end
end; *)
// not found:
index := length(p.locals);
setLength(p.locals, index+1);
// declare the new temporary:
name := con('Loc', toRope(index));
appf(p.s[cpsLocals], '$1 $2; /* temporary */$n',
[getTypeDesc(p.module, t), name]);
p.locals[index].k := locTemp;
p.locals[index].a := index;
p.locals[index].r := name;
p.locals[index].t := getUniqueType(t);
p.locals[index].s := OnStack;
p.locals[index].flags := {@set}[];
result := p.locals[index] // BUGFIX!
end; end;
procedure freeTemp(p: BProc; const temp: TLoc); procedure freeTemp(p: BProc; const temp: TLoc);
begin (* begin
if (temp.a >= 0) and (temp.a < length(p.locals)) and
(p.locals[temp.a].k = locTemp) then
p.locals[temp.a].k := locNone *)
end; end;
// -------------------------- Variable manager ---------------------------- // -------------------------- Variable manager ----------------------------
@ -245,6 +221,8 @@ begin
app(m.s[cfsVars], ' register'); app(m.s[cfsVars], ' register');
if sfVolatile in s.flags then if sfVolatile in s.flags then
app(m.s[cfsVars], ' volatile'); app(m.s[cfsVars], ' volatile');
if sfThreadVar in s.flags then
app(m.s[cfsVars], ' NIM_THREADVAR');
appf(m.s[cfsVars], ' $1;$n', [s.loc.r]) appf(m.s[cfsVars], ' $1;$n', [s.loc.r])
end end
end; end;
@ -314,7 +292,7 @@ end;
function getLabel(p: BProc): TLabel; function getLabel(p: BProc): TLabel;
begin begin
inc(p.labels); inc(p.labels);
result := con('L'+'', toRope(p.labels)) result := con('LA', toRope(p.labels))
end; end;
procedure fixLabel(p: BProc; labl: TLabel); procedure fixLabel(p: BProc; labl: TLabel);
@ -344,10 +322,11 @@ begin
lib.kind := libDynamicGenerated; lib.kind := libDynamicGenerated;
useMagic(m, 'nimLoadLibrary'); useMagic(m, 'nimLoadLibrary');
useMagic(m, 'nimUnloadLibrary'); useMagic(m, 'nimUnloadLibrary');
useMagic(m, 'NimStringDesc');
tmp := getTempName(); tmp := getTempName();
appf(m.s[cfsVars], 'static void* $1;$n', [tmp]); appf(m.s[cfsVars], 'static void* $1;$n', [tmp]);
appf(m.s[cfsDynLibInit], appf(m.s[cfsDynLibInit],
'$1 = nimLoadLibrary((string) &$2);$n', '$1 = nimLoadLibrary((NimStringDesc*) &$2);$n',
[tmp, getStrLit(m, lib.path)]); [tmp, getStrLit(m, lib.path)]);
appf(m.s[cfsDynLibDeinit], appf(m.s[cfsDynLibDeinit],
'if ($1 != NIM_NIL) nimUnloadLibrary($1);$n', [tmp]); 'if ($1 != NIM_NIL) nimUnloadLibrary($1);$n', [tmp]);
@ -361,7 +340,7 @@ var
lib: PLib; lib: PLib;
extname, tmp: PRope; extname, tmp: PRope;
begin begin
lib := PLib(sym.annex); lib := sym.annex;
extname := sym.loc.r; extname := sym.loc.r;
loadDynamicLib(m, lib); loadDynamicLib(m, lib);
useMagic(m, 'nimGetProcAddr'); useMagic(m, 'nimGetProcAddr');
@ -434,7 +413,7 @@ procedure genProc(m: BModule; prc: PSym);
var var
p: BProc; p: BProc;
generatedProc, header, returnStmt: PRope; generatedProc, header, returnStmt: PRope;
i: int; i, profileId: int;
res, param: PSym; res, param: PSym;
begin begin
useHeader(m, prc); useHeader(m, prc);
@ -454,21 +433,20 @@ begin
returnStmt := nil; returnStmt := nil;
assert(prc.ast <> nil); assert(prc.ast <> nil);
if not (sfPure in prc.flags) then begin if not (sfPure in prc.flags) and (prc.typ.sons[0] <> nil) then begin
res := prc.ast.sons[resultPos].sym; // get result symbol
if not isInvalidReturnType(prc.typ.sons[0]) then begin if not isInvalidReturnType(prc.typ.sons[0]) then begin
res := prc.ast.sons[resultPos].sym; // get result symbol
// declare the result symbol: // declare the result symbol:
assignLocalVar(p, res); assignLocalVar(p, res);
assert(res.loc.r <> nil); assert(res.loc.r <> nil);
initVariable(p, res);
genObjectInit(p, res);
returnStmt := ropef('return $1;$n', [rdLoc(res.loc)]); returnStmt := ropef('return $1;$n', [rdLoc(res.loc)]);
end end
else if (prc.typ.sons[0] <> nil) then begin else begin
res := prc.ast.sons[resultPos].sym; // get result symbol
fillResult(res); fillResult(res);
assignParam(p, res) assignParam(p, res);
end end;
initVariable(p, res);
genObjectInit(p, res.typ, res.loc, true);
end; end;
for i := 1 to sonsLen(prc.typ.n)-1 do begin for i := 1 to sonsLen(prc.typ.n)-1 do begin
param := prc.typ.n.sons[i].sym; param := prc.typ.n.sons[i].sym;
@ -492,16 +470,31 @@ begin
[makeCString(prc.owner.name.s +{&} '.' +{&} prc.name.s), [makeCString(prc.owner.name.s +{&} '.' +{&} prc.name.s),
makeCString(toFilename(prc.info))])); makeCString(toFilename(prc.info))]));
end; end;
if optProfiler in prc.options then begin
if gProcProfile >= 64*1024 then // XXX: hard coded value!
InternalError(prc.info, 'too many procedures for profiling');
useMagic(m, 'profileData');
app(p.s[cpsLocals], 'ticks NIM_profilingStart;'+tnl);
if prc.loc.a < 0 then begin
appf(m.s[cfsDebugInit], 'profileData[$1].procname = $2;$n',
[toRope(gProcProfile),
makeCString(prc.owner.name.s +{&} '.' +{&} prc.name.s)]);
prc.loc.a := gProcProfile;
inc(gProcProfile);
end;
prepend(p.s[cpsInit], toRope('NIM_profilingStart = getticks();' + tnl));
end;
app(generatedProc, con(p.s)); app(generatedProc, con(p.s));
if p.beforeRetNeeded then if p.beforeRetNeeded then
app(generatedProc, 'BeforeRet: ;' + tnl); app(generatedProc, 'BeforeRet: ;' + tnl);
if optStackTrace in prc.options then if optStackTrace in prc.options then
app(generatedProc, 'framePtr = framePtr->prev;' + tnl); app(generatedProc, 'framePtr = framePtr->prev;' + tnl);
if optProfiler in prc.options then
appf(generatedProc,
'profileData[$1].total += elapsed(getticks(), NIM_profilingStart);$n',
[toRope(prc.loc.a)]);
app(generatedProc, returnStmt); app(generatedProc, returnStmt);
app(generatedProc, '}' + tnl); app(generatedProc, '}' + tnl);
// only now we can free the syntax tree:
//if prc.typ.callConv <> ccInline then
// prc.ast.sons[codePos] := nil;
end; end;
app(m.s[cfsProcs], generatedProc); app(m.s[cfsProcs], generatedProc);
end end
@ -524,6 +517,8 @@ begin
app(m.s[cfsVars], ' register'); app(m.s[cfsVars], ' register');
if sfVolatile in sym.flags then if sfVolatile in sym.flags then
app(m.s[cfsVars], ' volatile'); app(m.s[cfsVars], ' volatile');
if sfThreadVar in sym.flags then
app(m.s[cfsVars], ' NIM_THREADVAR');
appf(m.s[cfsVars], ' $1;$n', [sym.loc.r]) appf(m.s[cfsVars], ' $1;$n', [sym.loc.r])
end end
end; end;
@ -572,22 +567,28 @@ end;
function getFileHeader(const cfilenoext: string): PRope; function getFileHeader(const cfilenoext: string): PRope;
begin begin
result := ropef( if optCompileOnly in gGlobalOptions then
'/* Generated by the Nimrod Compiler v$1 */$n' + result := ropef(
'/* (c) 2008 Andreas Rumpf */$n' + '/* Generated by the Nimrod Compiler v$1 */$n' +
'/* Compiled for: $2, $3, $4 */$n' + '/* (c) 2008 Andreas Rumpf */$n',
'/* Command for C compiler:$n $5 */$n', [toRope(versionAsString)])
[toRope(versionAsString), toRope(platform.OS[targetOS].name), else
toRope(platform.CPU[targetCPU].name), result := ropef(
toRope(extccomp.CC[extccomp.ccompiler].name), '/* Generated by the Nimrod Compiler v$1 */$n' +
toRope(getCompileCFileCmd(cfilenoext))]); '/* (c) 2008 Andreas Rumpf */$n' +
'/* Compiled for: $2, $3, $4 */$n' +
'/* Command for C compiler:$n $5 */$n',
[toRope(versionAsString), toRope(platform.OS[targetOS].name),
toRope(platform.CPU[targetCPU].name),
toRope(extccomp.CC[extccomp.ccompiler].name),
toRope(getCompileCFileCmd(cfilenoext))]);
case platform.CPU[targetCPU].intSize of case platform.CPU[targetCPU].intSize of
16: appf(result, '$ntypedef short int NI;$n' + 16: appf(result, '$ntypedef short int NI;$n' +
'typedef unsigned short int NU;$n', []); 'typedef unsigned short int NU;$n', []);
32: appf(result, '$ntypedef long int NI;$n' + 32: appf(result, '$ntypedef long int NI;$n' +
'typedef unsigned long int NU;$n', []); 'typedef unsigned long int NU;$n', []);
64: appf(result, '$ntypedef long long int NI;$n' + 64: appf(result, '$ntypedef long long int NI;$n' +
'typedef unsigned long long int NU;$n', []); 'typedef unsigned long long int NU;$n', []);
else begin end else begin end
end end
end; end;
@ -645,18 +646,43 @@ begin
appf(m.s[cfsProcs], frmt, [gBreakpoints, mainModInit]) appf(m.s[cfsProcs], frmt, [gBreakpoints, mainModInit])
end; end;
function getInitName(m: PSym): PRope;
begin
result := con(m.name.s, toRope('Init'));
end;
procedure registerModuleToMain(m: PSym);
var
initname: PRope;
begin
initname := getInitName(m);
appf(mainModProcs, 'N_NOINLINE(void, $1)(void);$n',
[initname]);
if not (sfSystemModule in m.flags) then
appf(mainModInit, '$1();$n', [initname]);
end;
procedure genInitCode(m: BModule); procedure genInitCode(m: BModule);
var var
initname, prc: PRope; initname, prc: PRope;
begin begin
initname := con(m.module.name.s, toRope('Init')); if optProfiler in m.initProc.options then begin
appf(mainModProcs, 'N_NIMCALL(void, $1)(void);$n', // This does not really belong here, but there is no good place for this
[initname]); // code. I don't want to put this to the proc generation as the
if not (sfSystemModule in m.module.flags) then // ``IncludeStr`` call is quite slow.
appf(mainModInit, '$1();$n', [initname]); {@discard} lists.IncludeStr(m.headerFiles, '<cycle.h>');
prc := ropef('N_NIMCALL(void, $1)(void) {$n', [initname]); end;
initname := getInitName(m.module);
registerModuleToMain(m.module);
prc := ropef('N_NOINLINE(void, $1)(void) {$n', [initname]);
if m.typeNodes > 0 then
appf(m.s[cfsTypeInit1], 'static TNimNode $1[$2];$n',
[m.typeNodesName, toRope(m.typeNodes)]);
if m.nimTypes > 0 then
appf(m.s[cfsTypeInit1], 'static TNimType $1[$2];$n',
[m.nimTypesName, toRope(m.nimTypes)]);
if optStackTrace in m.initProc.options then begin if optStackTrace in m.initProc.options then begin
prepend(m.initProc.s[cpsLocals], toRope('volatile TFrame F;' + tnl)); getFrameDecl(m.initProc);
app(prc, m.initProc.s[cpsLocals]); app(prc, m.initProc.s[cpsLocals]);
app(prc, m.s[cfsTypeInit1]); app(prc, m.s[cfsTypeInit1]);
appf(prc, appf(prc,
@ -704,13 +730,42 @@ begin
intSetInit(result.declaredThings); intSetInit(result.declaredThings);
intSetInit(result.debugDeclared); intSetInit(result.debugDeclared);
result.cfilename := filename; result.cfilename := filename;
result.filename := filename;
initIdTable(result.typeCache); initIdTable(result.typeCache);
initIdTable(result.forwTypeCache); initIdTable(result.forwTypeCache);
result.module := module; result.module := module;
intSetInit(result.typeInfoMarker); intSetInit(result.typeInfoMarker);
result.initProc := newProc(nil, result); result.initProc := newProc(nil, result);
result.initProc.options := gOptions; result.initProc.options := gOptions;
{@emit result.typeStack := [];} initNodeTable(result.dataCache);
{@emit result.typeStack := @[];}
result.typeNodesName := getTempName();
result.nimTypesName := getTempName();
end;
function myOpen(module: PSym; const filename: string): PPassContext;
begin
result := newModule(module, filename);
end;
function myOpenCached(module: PSym; const filename: string;
rd: PRodReader): PPassContext;
var
cfile, cfilenoext, objFile: string;
begin
//MessageOut('cgen.myOpenCached has been called ' + filename);
cfile := changeFileExt(completeCFilePath(filename), cExt);
cfilenoext := changeFileExt(cfile, '');
(*
objFile := toObjFile(cfilenoext);
if ExistsFile(objFile) and nos.FileNewer(objFile, cfile) then begin
end
else begin
addFileToCompile(cfilenoext); // is to compile
end; *)
addFileToLink(cfilenoext);
registerModuleToMain(module);
result := nil;
end; end;
function shouldRecompile(code: PRope; const cfile, cfilenoext: string): bool; function shouldRecompile(code: PRope; const cfile, cfilenoext: string): bool;
@ -718,7 +773,7 @@ var
objFile: string; objFile: string;
begin begin
result := true; result := true;
if optCFileCache in gGlobalOptions then begin if not (optForceFullMake in gGlobalOptions) then begin
objFile := toObjFile(cfilenoext); objFile := toObjFile(cfilenoext);
if writeRopeIfNotEqual(code, cfile) then exit; if writeRopeIfNotEqual(code, cfile) then exit;
if ExistsFile(objFile) and nos.FileNewer(objFile, cfile) then if ExistsFile(objFile) and nos.FileNewer(objFile, cfile) then
@ -728,47 +783,57 @@ begin
writeRope(code, cfile); writeRope(code, cfile);
end; end;
procedure finishModule(b: PBackend; n: PNode); function myProcess(b: PPassContext; n: PNode): PNode;
var
m: BModule;
begin
result := n;
if b = nil then exit;
m := BModule(b);
m.initProc.options := gOptions;
genStmts(m.initProc, n);
end;
function myClose(b: PPassContext; n: PNode): PNode;
var var
cfile, cfilenoext: string; cfile, cfilenoext: string;
m: BModule; m: BModule;
code: PRope; code: PRope;
begin begin
result := n;
if b = nil then exit;
m := BModule(b); m := BModule(b);
m.initProc.options := gOptions; if n <> nil then begin
genStmts(m.initProc, n); m.initProc.options := gOptions;
genStmts(m.initProc, n);
end;
// generate code for the init statements of the module: // generate code for the init statements of the module:
genInitCode(m); genInitCode(m);
finishTypeDescriptions(m); finishTypeDescriptions(m);
cfile := completeCFilePath(m.cfilename);
cfilenoext := changeFileExt(cfile, '');
if sfMainModule in m.module.flags then begin if sfMainModule in m.module.flags then begin
// generate mapping file (if requested):
if gMapping <> nil then
WriteRope(gMapping, ChangeFileExt(cfile + '_map', 'txt'));
// generate main file: // generate main file:
app(m.s[cfsProcHeaders], mainModProcs); app(m.s[cfsProcHeaders], mainModProcs);
genMainProc(m); genMainProc(m);
end; end;
cfile := completeCFilePath(m.cfilename);
cfilenoext := changeFileExt(cfile, '');
code := genModule(m, cfilenoext); code := genModule(m, cfilenoext);
if shouldRecompile(code, changeFileExt(cfile, cExt), cfilenoext) then begin if shouldRecompile(code, changeFileExt(cfile, cExt), cfilenoext) then begin
addFileToCompile(cfilenoext); // is to compile addFileToCompile(cfilenoext); // is to compile
end; end;
addFileToLink(cfilenoext); addFileToLink(cfilenoext);
if sfMainModule in m.module.flags then writeMapping(cfile, gMapping);
end; end;
function CBackend(b: PBackend; module: PSym; const filename: string): PBackend; function cgenPass(): TPass;
var
g: BModule;
begin begin
g := newModule(module, filename); initPass(result);
g.backendCreator := CBackend; result.open := myOpen;
g.eventMask := {@set}[eAfterModule]; result.openCached := myOpenCached;
g.afterModuleEvent := finishModule; result.process := myProcess;
result := g; result.close := myClose;
end; end;
initialization initialization
intSetInit(gTypeInfoGenerated); InitIiTable(gToTypeInfoId);
end. end.

View file

@ -16,7 +16,8 @@ interface
{$include 'config.inc'} {$include 'config.inc'}
uses uses
nsystem, charsets, msgs; nsystem, charsets, nos, msgs, options, nversion, condsyms, strutils, extccomp,
platform, lists, wordrecg;
procedure writeCommandLineUsage; procedure writeCommandLineUsage;
@ -33,10 +34,6 @@ procedure processSwitch(const switch, arg: string; pass: TCmdlinePass;
implementation implementation
uses
options, nversion, condsyms, strutils, extccomp, platform, nos, lists,
wordrecg;
{@ignore} {@ignore}
const const
{$ifdef fpc} {$ifdef fpc}
@ -54,19 +51,18 @@ const
const const
Usage = '' Usage = ''
//[[[cog //[[[cog
//def f(x): return "+{&} '" + x.replace("'", "''")[:-1] + "' +{&} nl" //from string import replace
//for line in file("data/basicopt.txt"): //def f(x): return "+{&} '" + replace(x, "'", "''")[:-1] + "' +{&} nl"
//for line in open("data/basicopt.txt").readlines():
// cog.outl(f(line)) // cog.outl(f(line))
//]]] //]]]
+{&} 'Usage::' +{&} nl +{&} 'Usage::' +{&} nl
+{&} ' nimrod command [options] inputfile [arguments]' +{&} nl +{&} ' nimrod command [options] inputfile [arguments]' +{&} nl
+{&} 'Command::' +{&} nl +{&} 'Command::' +{&} nl
+{&} ' compile compile project with default code generator (C)' +{&} nl +{&} ' compile, c compile project with default code generator (C)' +{&} nl
+{&} ' compile_to_c compile project with C code generator' +{&} nl +{&} ' compile_to_c, cc compile project with C code generator' +{&} nl
+{&} ' compile_to_cpp compile project with C++ code generator' +{&} nl +{&} ' doc generate the documentation for inputfile' +{&} nl
+{&} ' compile_to_ecmascript compile project to ECMAScript code (experimental)' +{&} nl +{&} ' rst2html converts a reStructuredText file to HTML' +{&} nl
+{&} ' doc generate the documentation for inputfile;' +{&} nl
+{&} ' with --run switch opens it with $BROWSER' +{&} nl
+{&} 'Arguments:' +{&} nl +{&} 'Arguments:' +{&} nl
+{&} ' arguments are passed to the program being run (if --run option is selected)' +{&} nl +{&} ' arguments are passed to the program being run (if --run option is selected)' +{&} nl
+{&} 'Options:' +{&} nl +{&} 'Options:' +{&} nl
@ -74,7 +70,8 @@ const
+{&} ' -o, --out:FILE set the output filename' +{&} nl +{&} ' -o, --out:FILE set the output filename' +{&} nl
+{&} ' -d, --define:SYMBOL define a conditional symbol' +{&} nl +{&} ' -d, --define:SYMBOL define a conditional symbol' +{&} nl
+{&} ' -u, --undef:SYMBOL undefine a conditional symbol' +{&} nl +{&} ' -u, --undef:SYMBOL undefine a conditional symbol' +{&} nl
+{&} ' -b, --force_build force rebuilding of all modules' +{&} nl +{&} ' -f, --force_build force rebuilding of all modules' +{&} nl
+{&} ' --symbol_files:on|off use symbol files to speed up compilation (buggy!)' +{&} nl
+{&} ' --stack_trace:on|off code generation for stack trace ON|OFF' +{&} nl +{&} ' --stack_trace:on|off code generation for stack trace ON|OFF' +{&} nl
+{&} ' --line_trace:on|off code generation for line trace ON|OFF' +{&} nl +{&} ' --line_trace:on|off code generation for line trace ON|OFF' +{&} nl
+{&} ' --debugger:on|off turn Embedded Nimrod Debugger ON|OFF' +{&} nl +{&} ' --debugger:on|off turn Embedded Nimrod Debugger ON|OFF' +{&} nl
@ -95,7 +92,7 @@ const
AdvancedUsage = '' AdvancedUsage = ''
//[[[cog //[[[cog
//for line in file("data/advopt.txt"): //for line in open("data/advopt.txt").readlines():
// cog.outl(f(line)) // cog.outl(f(line))
//]]] //]]]
+{&} 'Advanced commands::' +{&} nl +{&} 'Advanced commands::' +{&} nl
@ -104,21 +101,17 @@ const
+{&} ' gen_depend generate a DOT file containing the' +{&} nl +{&} ' gen_depend generate a DOT file containing the' +{&} nl
+{&} ' module dependency graph' +{&} nl +{&} ' module dependency graph' +{&} nl
+{&} ' list_def list all defined conditionals and exit' +{&} nl +{&} ' list_def list all defined conditionals and exit' +{&} nl
+{&} ' rst2html converts a reStructuredText file to HTML' +{&} nl
+{&} ' check checks the project for syntax and semantic' +{&} nl +{&} ' check checks the project for syntax and semantic' +{&} nl
+{&} ' parse parses a single file (for debugging Nimrod)' +{&} nl +{&} ' parse parses a single file (for debugging Nimrod)' +{&} nl
+{&} ' scan tokenizes a single file (for debugging Nimrod)' +{&} nl
+{&} ' debugtrans for debugging the transformation pass' +{&} nl
+{&} 'Advanced options:' +{&} nl +{&} 'Advanced options:' +{&} nl
+{&} ' -w, --warnings:on|off warnings ON|OFF' +{&} nl +{&} ' -w, --warnings:on|off warnings ON|OFF' +{&} nl
+{&} ' --warning[X]:on|off specific warning X ON|OFF' +{&} nl +{&} ' --warning[X]:on|off specific warning X ON|OFF' +{&} nl
+{&} ' --hints:on|off hints ON|OFF' +{&} nl +{&} ' --hints:on|off hints ON|OFF' +{&} nl
+{&} ' --hint[X]:on|off specific hint X ON|OFF' +{&} nl +{&} ' --hint[X]:on|off specific hint X ON|OFF' +{&} nl
+{&} ' --cc:C_COMPILER set the C/C++ compiler to use' +{&} nl
+{&} ' --lib:PATH set the system library path' +{&} nl +{&} ' --lib:PATH set the system library path' +{&} nl
+{&} ' -c, --compile_only compile only; do not assemble or link' +{&} nl +{&} ' -c, --compile_only compile only; do not assemble or link' +{&} nl
+{&} ' --no_linking compile but do not link' +{&} nl +{&} ' --no_linking compile but do not link' +{&} nl
+{&} ' --gen_script generate a compile script (in the ''rod_gen''' +{&} nl +{&} ' --gen_script generate a compile script (in the ''nimcache''' +{&} nl
+{&} ' subdirectory named ''compile_$project$scriptext'')' +{&} nl +{&} ' subdirectory named ''compile_$project$scriptext'')' +{&} nl
+{&} ' --os:SYMBOL set the target operating system (cross-compilation)' +{&} nl +{&} ' --os:SYMBOL set the target operating system (cross-compilation)' +{&} nl
+{&} ' --cpu:SYMBOL set the target processor (cross-compilation)' +{&} nl +{&} ' --cpu:SYMBOL set the target processor (cross-compilation)' +{&} nl
@ -127,50 +120,16 @@ const
+{&} ' -l, --passl:OPTION pass an option to the linker' +{&} nl +{&} ' -l, --passl:OPTION pass an option to the linker' +{&} nl
+{&} ' --gen_mapping generate a mapping file containing' +{&} nl +{&} ' --gen_mapping generate a mapping file containing' +{&} nl
+{&} ' (Nimrod, mangled) identifier pairs' +{&} nl +{&} ' (Nimrod, mangled) identifier pairs' +{&} nl
+{&} ' --merge_output generate only one C output file' +{&} nl
+{&} ' --line_dir:on|off generation of #line directive ON|OFF' +{&} nl +{&} ' --line_dir:on|off generation of #line directive ON|OFF' +{&} nl
+{&} ' --checkpoints:on|off turn on|off checkpoints; for debugging Nimrod' +{&} nl +{&} ' --checkpoints:on|off turn on|off checkpoints; for debugging Nimrod' +{&} nl
+{&} ' --skip_cfg do not read the general configuration file' +{&} nl +{&} ' --skip_cfg do not read the general configuration file' +{&} nl
+{&} ' --skip_proj_cfg do not read the project''s configuration file' +{&} nl +{&} ' --skip_proj_cfg do not read the project''s configuration file' +{&} nl
+{&} ' --import:MODULE_FILE import the given module implicitly for each module' +{&} nl +{&} ' --import:MODULE_FILE import the given module implicitly for each module' +{&} nl
+{&} ' --maxerr:NUMBER stop compilation after NUMBER errors; broken!' +{&} nl
+{&} ' --ast_cache:on|off caching of ASTs ON|OFF (default: OFF)' +{&} nl
+{&} ' --c_file_cache:on|off caching of generated C files ON|OFF (default: OFF)' +{&} nl
+{&} ' --index:FILE use FILE to generate a documenation index file' +{&} nl +{&} ' --index:FILE use FILE to generate a documenation index file' +{&} nl
+{&} ' --putenv:key=value set an environment variable' +{&} nl +{&} ' --putenv:key=value set an environment variable' +{&} nl
+{&} ' --list_cmd list the commands used to execute external programs' +{&} nl +{&} ' --list_cmd list the commands used to execute external programs' +{&} nl
+{&} ' -v, --verbose show what Nimrod is doing' +{&} nl +{&} ' --verbosity:0|1|2|3 set Nimrod''s verbosity level (0 is default)' +{&} nl
+{&} ' --version show detailed version information' +{&} nl +{&} ' -v, --version show detailed version information' +{&} nl
//[[[end]]]
;
VersionInformation = ''
//[[[cog
//for line in file("data/changes.txt"):
// cog.outl(f(line))
//]]]
+{&} '0.1.0' +{&} nl
+{&} '* new config system' +{&} nl
+{&} '* new build system' +{&} nl
+{&} '* source renderer' +{&} nl
+{&} '* pas2nim integrated' +{&} nl
+{&} '* support for C++' +{&} nl
+{&} '* local variables are always initialized' +{&} nl
+{&} '* Rod file reader and writer' +{&} nl
+{&} '* new --out, -o command line options' +{&} nl
+{&} '* fixed bug in nimconf.pas: we now have several' +{&} nl
+{&} ' string token types' +{&} nl
+{&} '* changed nkIdentDef to nkIdentDefs' +{&} nl
+{&} '* added type(expr) in the parser and the grammer' +{&} nl
+{&} '* added template' +{&} nl
+{&} '* added command calls' +{&} nl
+{&} '* added case in records/objects' +{&} nl
+{&} '* added --skip_proj_cfg switch for nim.dpr' +{&} nl
+{&} '* added missing features to pasparse' +{&} nl
+{&} '* rewrote the source generator' +{&} nl
+{&} '* ``addr`` and ``cast`` are now keywords; grammar updated' +{&} nl
+{&} '* implemented ` notation; grammar updated' +{&} nl
+{&} '* specification replaced by a manual' +{&} nl
//[[[end]]] //[[[end]]]
; ;
@ -212,7 +171,7 @@ begin
versionWritten := true; versionWritten := true;
helpWritten := true; helpWritten := true;
messageOut(format(HelpMessage, [VersionAsString, platform.os[hostOS].name, messageOut(format(HelpMessage, [VersionAsString, platform.os[hostOS].name,
cpu[hostCPU].name]) +{&} VersionInformation) cpu[hostCPU].name]))
end end
end; end;
@ -378,14 +337,10 @@ begin
if pass in {@set}[passCmd2, passPP] then if pass in {@set}[passCmd2, passPP] then
addFileToLink(arg); addFileToLink(arg);
end; end;
wDebuginfo: wDebuginfo: include(gGlobalOptions, optCDebug);
include(gGlobalOptions, optCDebug); wCompileOnly, wC: include(gGlobalOptions, optCompileOnly);
wCompileOnly, wC: wNoLinking: include(gGlobalOptions, optNoLinking);
include(gGlobalOptions, optCompileOnly); wForceBuild, wF: include(gGlobalOptions, optForceFullMake);
wNoLinking:
include(gGlobalOptions, optNoLinking);
wForceBuild, wF:
include(gGlobalOptions, optForceFullMake);
wGC: begin wGC: begin
case whichKeyword(arg) of case whichKeyword(arg) of
wBoehm: begin wBoehm: begin
@ -406,20 +361,13 @@ begin
liMessage(info, errNoneBoehmRefcExpectedButXFound, arg) liMessage(info, errNoneBoehmRefcExpectedButXFound, arg)
end end
end; end;
wWarnings, wW: wWarnings, wW: ProcessOnOffSwitch({@set}[optWarns], arg, pass, info);
ProcessOnOffSwitch({@set}[optWarns], arg, pass, info); wWarning: ProcessSpecificNote(arg, wWarning, pass, info);
wWarning: wHint: ProcessSpecificNote(arg, wHint, pass, info);
ProcessSpecificNote(arg, wWarning, pass, info); wHints: ProcessOnOffSwitch({@set}[optHints], arg, pass, info);
wHint: wCheckpoints: ProcessOnOffSwitch({@set}[optCheckpoints], arg, pass, info);
ProcessSpecificNote(arg, wHint, pass, info); wStackTrace: ProcessOnOffSwitch({@set}[optStackTrace], arg, pass, info);
wHints: wLineTrace: ProcessOnOffSwitch({@set}[optLineTrace], arg, pass, info);
ProcessOnOffSwitch({@set}[optHints], arg, pass, info);
wCheckpoints:
ProcessOnOffSwitch({@set}[optCheckpoints], arg, pass, info);
wStackTrace:
ProcessOnOffSwitch({@set}[optStackTrace], arg, pass, info);
wLineTrace:
ProcessOnOffSwitch({@set}[optLineTrace], arg, pass, info);
wDebugger: begin wDebugger: begin
ProcessOnOffSwitch({@set}[optEndb], arg, pass, info); ProcessOnOffSwitch({@set}[optEndb], arg, pass, info);
if optEndb in gOptions then if optEndb in gOptions then
@ -427,26 +375,19 @@ begin
else else
UndefSymbol('endb') UndefSymbol('endb')
end; end;
wChecks, wX: wProfiler: begin
ProcessOnOffSwitch(checksOptions, arg, pass, info); ProcessOnOffSwitch({@set}[optProfiler], arg, pass, info);
wObjChecks: if optProfiler in gOptions then DefineSymbol('profiler')
ProcessOnOffSwitch({@set}[optObjCheck], arg, pass, info); else UndefSymbol('profiler')
wFieldChecks: end;
ProcessOnOffSwitch({@set}[optFieldCheck], arg, pass, info); wChecks, wX: ProcessOnOffSwitch(checksOptions, arg, pass, info);
wRangeChecks: wObjChecks: ProcessOnOffSwitch({@set}[optObjCheck], arg, pass, info);
ProcessOnOffSwitch({@set}[optRangeCheck], arg, pass, info); wFieldChecks: ProcessOnOffSwitch({@set}[optFieldCheck], arg, pass, info);
wBoundChecks: wRangeChecks: ProcessOnOffSwitch({@set}[optRangeCheck], arg, pass, info);
ProcessOnOffSwitch({@set}[optBoundsCheck], arg, pass, info); wBoundChecks: ProcessOnOffSwitch({@set}[optBoundsCheck], arg, pass, info);
wOverflowChecks: wOverflowChecks: ProcessOnOffSwitch({@set}[optOverflowCheck], arg, pass, info);
ProcessOnOffSwitch({@set}[optOverflowCheck], arg, pass, info); wLineDir: ProcessOnOffSwitch({@set}[optLineDir], arg, pass, info);
wLineDir: wAssertions, wA: ProcessOnOffSwitch({@set}[optAssert], arg, pass, info);
ProcessOnOffSwitch({@set}[optLineDir], arg, pass, info);
wAssertions, wA:
ProcessOnOffSwitch({@set}[optAssert], arg, pass, info);
wCFileCache:
ProcessOnOffSwitchG({@set}[optCFileCache], arg, pass, info);
wAstCache:
ProcessOnOffSwitchG({@set}[optAstCache], arg, pass, info);
wOpt: begin wOpt: begin
case whichKeyword(arg) of case whichKeyword(arg) of
wSpeed: begin wSpeed: begin
@ -505,10 +446,8 @@ begin
expectArg(switch, arg, pass, info); expectArg(switch, arg, pass, info);
options.addImplicitMod(arg); options.addImplicitMod(arg);
end; end;
wListCmd: wListCmd: include(gGlobalOptions, optListCmd);
include(gGlobalOptions, optListCmd); wGenMapping: include(gGlobalOptions, optGenMapping);
wGenMapping:
include(gGlobalOptions, optGenMapping);
wOS: begin wOS: begin
if (pass = passCmd1) then begin if (pass = passCmd1) then begin
theOS := platform.NameToOS(arg); theOS := platform.NameToOS(arg);
@ -533,26 +472,18 @@ begin
end end
end end
end; end;
wRun, wR: wRun, wR: include(gGlobalOptions, optRun);
include(gGlobalOptions, optRun); wVerbosity: begin
wVerbose, wV: expectArg(switch, arg, pass, info);
include(gGlobalOptions, optVerbose); gVerbosity := parseInt(arg);
wMergeOutput: end;
include(gGlobalOptions, optMergeOutput); wVersion, wV: writeVersionInfo(pass);
wVersion: wAdvanced: writeAdvancedUsage(pass);
writeVersionInfo(pass); wHelp, wH: helpOnError(pass);
wAdvanced: wSymbolFiles: ProcessOnOffSwitchG({@set}[optSymbolFiles], arg, pass, info);
writeAdvancedUsage(pass); wSkipCfg: include(gGlobalOptions, optSkipConfigFile);
wHelp, wH: wSkipProjCfg: include(gGlobalOptions, optSkipProjConfigFile);
helpOnError(pass); wGenScript: include(gGlobalOptions, optGenScript);
wCompileSys:
include(gGlobalOptions, optCompileSys);
wSkipCfg:
include(gGlobalOptions, optSkipConfigFile);
wSkipProjCfg:
include(gGlobalOptions, optSkipProjConfigFile);
wGenScript:
include(gGlobalOptions, optGenScript);
wLib: begin wLib: begin
expectArg(switch, arg, pass, info); expectArg(switch, arg, pass, info);
libpath := processPath(arg) libpath := processPath(arg)

View file

@ -6,7 +6,6 @@
// See the file "copying.txt", included in this // See the file "copying.txt", included in this
// distribution, for details about the copyright. // distribution, for details about the copyright.
// //
unit condsyms; unit condsyms;
// This module handles the conditional symbols. // This module handles the conditional symbols.
@ -16,7 +15,7 @@ unit condsyms;
interface interface
uses uses
ast, astalgo, msgs, hashes, platform, strutils, idents; nsystem, ast, astalgo, msgs, hashes, platform, strutils, idents;
var var
gSymbols: TStrTable; gSymbols: TStrTable;
@ -29,6 +28,8 @@ procedure UndefSymbol(const symbol: string);
function isDefined(symbol: PIdent): Boolean; function isDefined(symbol: PIdent): Boolean;
procedure ListSymbols; procedure ListSymbols;
function countDefinedSymbols: int;
implementation implementation
procedure DefineSymbol(const symbol: string); procedure DefineSymbol(const symbol: string);
@ -39,7 +40,12 @@ begin
i := getIdent(symbol); i := getIdent(symbol);
sym := StrTableGet(gSymbols, i); sym := StrTableGet(gSymbols, i);
if sym = nil then begin if sym = nil then begin
sym := NewSym(skConditional, i, nil); new(sym); // circumvent the ID mechanism
{@ignore}
fillChar(sym^, sizeof(sym^), 0);
{@emit}
sym.kind := skConditional;
sym.name := i;
StrTableAdd(gSymbols, sym); StrTableAdd(gSymbols, sym);
end; end;
sym.position := 1; sym.position := 1;
@ -75,6 +81,19 @@ begin
MessageOut('-- End of list --'); MessageOut('-- End of list --');
end; end;
function countDefinedSymbols: int;
var
it: TTabIter;
s: PSym;
begin
s := InitTabIter(it, gSymbols);
result := 0;
while s <> nil do begin
if s.position = 1 then inc(result);
s := nextIter(it, gSymbols);
end;
end;
procedure InitDefines; procedure InitDefines;
begin begin
initStrTable(gSymbols); initStrTable(gSymbols);
@ -92,7 +111,7 @@ begin
DefineSymbol('win32'); DefineSymbol('win32');
end; end;
osLinux, osMorphOS, osSkyOS, osIrix, osPalmOS, osQNX, osLinux, osMorphOS, osSkyOS, osIrix, osPalmOS, osQNX,
osAtari: begin osAtari, osAix: begin
// these are all 'unix-like' // these are all 'unix-like'
DefineSymbol('unix'); DefineSymbol('unix');
DefineSymbol('posix'); DefineSymbol('posix');

View file

@ -1,18 +0,0 @@
=======================================================
The Nimrod Compiler
Copyright (C) 2004-2008 Andreas Rumpf
=======================================================
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
of the License.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

View file

@ -21,6 +21,8 @@ type
const const
InitCrc32 = TCrc32(-1); InitCrc32 = TCrc32(-1);
InitAdler32 = int32(1);
function updateCrc32(val: Byte; crc: TCrc32): TCrc32; overload; function updateCrc32(val: Byte; crc: TCrc32): TCrc32; overload;
function updateCrc32(val: Char; crc: TCrc32): TCrc32; overload; function updateCrc32(val: Char; crc: TCrc32): TCrc32; overload;
@ -29,6 +31,9 @@ function strCrc32(const s: string): TCrc32;
function crcFromFile(const filename: string): TCrc32; function crcFromFile(const filename: string): TCrc32;
function updateAdler32(adler: int32; buf: pointer; len: int): int32;
implementation implementation
{@ignore} {@ignore}
@ -121,12 +126,12 @@ const
function updateCrc32(val: Byte; crc: TCrc32): TCrc32; overload; function updateCrc32(val: Byte; crc: TCrc32): TCrc32; overload;
begin begin
result := crc32Table[(int(crc) xor val) and $ff] xor (crc shr 8); result := crc32Table[(int(crc) xor (int(val) and $ff)) and $ff] xor (int(crc) shr 8);
end; end;
function updateCrc32(val: Char; crc: TCrc32): TCrc32; overload; function updateCrc32(val: Char; crc: TCrc32): TCrc32; overload;
begin begin
result := updateCrc32(ord(val), crc); result := updateCrc32(byte(ord(val)), crc);
end; end;
function strCrc32(const s: string): TCrc32; function strCrc32(const s: string): TCrc32;
@ -173,6 +178,39 @@ begin
CloseFile(bin); CloseFile(bin);
end; end;
const
base = int32(65521); { largest prime smaller than 65536 }
{NMAX = 5552; original code with unsigned 32 bit integer }
{ NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 }
nmax = 3854; { code with signed 32 bit integer }
{ NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^31-1 }
{ The penalty is the time loss in the extra MOD-calls. }
function updateAdler32(adler: int32; buf: pointer; len: int): int32;
var
s1, s2: int32;
L, k, b: int;
begin
s1 := adler and int32($ffff);
s2 := (adler shr int32(16)) and int32($ffff);
L := len;
b := 0;
while (L > 0) do begin
if L < nmax then k := L
else k := nmax;
dec(L, k);
while (k > 0) do begin
s1 := s1 +{%} int32(({@cast}cstring(buf))[b]);
s2 := s2 +{%} s1;
inc(b); dec(k);
end;
s1 := modu(s1, base);
s2 := modu(s2, base);
end;
result := (s2 shl int32(16)) or s1;
end;
{@ignore} {@ignore}
{$ifdef Q_on} {$ifdef Q_on}
{$undef Q_on} {$undef Q_on}

View file

@ -114,11 +114,11 @@ begin
{@ignore} {@ignore}
fillChar(result^, sizeof(result^), 0); fillChar(result^, sizeof(result^), 0);
{@emit {@emit
result.tocPart := []; result.tocPart := @[];
} }
result.filename := filename; result.filename := filename;
result.id := 100; result.id := 100;
result.splitAfter := 25; result.splitAfter := 20;
s := getConfigVar('split.item.toc'); s := getConfigVar('split.item.toc');
if s <> '' then if s <> '' then
result.splitAfter := parseInt(s); result.splitAfter := parseInt(s);
@ -212,19 +212,51 @@ begin
'&': dest := dest + '&amp;'; '&': dest := dest + '&amp;';
'<': dest := dest + '&lt;'; '<': dest := dest + '&lt;';
'>': dest := dest + '&gt;'; '>': dest := dest + '&gt;';
'"': dest := dest + '&quot;';
else addChar(dest, c) else addChar(dest, c)
end end
end; end;
function toXml(const s: string; splitAfter: int = -1): string; function nextSplitPoint(const s: string; start: int): int;
var var
i: int; i: int;
begin
result := start;
while result < length(s)+strStart do begin
case s[result] of
'_': exit;
'a'..'z': begin
if result+1 < length(s)+strStart then
if s[result+1] in ['A'..'Z'] then exit;
end;
else begin end;
end;
inc(result);
end;
dec(result); // last valid index
end;
function toXml(const s: string; splitAfter: int = -1): string;
var
i, j, k, partLen: int;
begin begin
result := ''; result := '';
for i := strStart to length(s)+strStart-1 do begin if splitAfter >= 0 then begin
if (splitAfter >= 0) and ((i-strStart+1) mod splitAfter = 0) then partLen := 0;
addChar(result, ' '); j := strStart;
addXmlChar(result, s[i]) while j < length(s)+strStart do begin
k := nextSplitPoint(s, j);
if partLen + k - j + 1 > splitAfter then begin
partLen := 0;
addChar(result, ' ');
end;
for i := j to k do addXmlChar(result, s[i]);
inc(partLen, k - j + 1);
j := k+1;
end;
end
else begin
for i := strStart to length(s)+strStart-1 do addXmlChar(result, s[i])
end end
end; end;

View file

@ -19,15 +19,17 @@ interface
uses uses
nsystem, ast, astalgo, strutils, hashes, trees, platform, magicsys, nsystem, ast, astalgo, strutils, hashes, trees, platform, magicsys,
extccomp, options, nversion, nimsets, msgs, crc, bitsets, idents, extccomp, options, nversion, nimsets, msgs, crc, bitsets, idents,
lists, types, nos, ntime, ropes, nmath, backends, ccgutils, wordrecg, rnimsyn; lists, types, nos, ntime, ropes, nmath, passes, ccgutils, wordrecg, rnimsyn,
rodread;
function EcmasBackend(b: PBackend; module: PSym; function ecmasgenPass(): TPass;
const filename: string): PBackend;
implementation implementation
type type
TEcmasGen = object(TBackend) TEcmasGen = object(TPassContext)
filename: string;
module: PSym;
end; end;
BModule = ^TEcmasGen; BModule = ^TEcmasGen;
@ -93,7 +95,7 @@ begin
{@ignore} {@ignore}
fillChar(p, sizeof(p), 0); fillChar(p, sizeof(p), 0);
{@emit {@emit
p.blocks := [];} p.blocks := @[];}
p.options := options; p.options := options;
p.module := module; p.module := module;
p.procDef := procDef; p.procDef := procDef;
@ -103,8 +105,7 @@ end;
const const
MappedToObject = {@set}[tyObject, tyArray, tyArrayConstr, tyTuple, MappedToObject = {@set}[tyObject, tyArray, tyArrayConstr, tyTuple,
tyEmptySet, tyOpenArray, tySet, tyVar, tyOpenArray, tySet, tyVar, tyRef, tyPtr];
tyRef, tyPtr];
function mapType(typ: PType): TEcmasTypeKind; function mapType(typ: PType): TEcmasTypeKind;
begin begin
@ -129,10 +130,10 @@ begin
end; end;
tyString, tySequence: tyString, tySequence:
result := etyInt; // little hack to get the right semantics result := etyInt; // little hack to get the right semantics
tyObject, tyArray, tyArrayConstr, tyTuple, tyEmptySet, tyOpenArray: tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray:
result := etyObject; result := etyObject;
tyNil: result := etyNull; tyNil: result := etyNull;
tyGenericInst, tyGenericParam, tyGeneric, tyNone, tyForward: tyGenericInst, tyGenericParam, tyGeneric, tyNone, tyForward, tyEmpty:
result := etyNone; result := etyNone;
tyProc: result := etyProc; tyProc: result := etyProc;
tyCString: result := etyString; tyCString: result := etyString;
@ -1832,38 +1833,56 @@ begin
end end
end; end;
procedure finishModule(b: PBackend; n: PNode); function myProcess(b: PPassContext; n: PNode): PNode;
var var
m: BModule; m: BModule;
outfile: string;
p: TProc; p: TProc;
r: TCompRes; r: TCompRes;
code: PRope;
begin begin
result := n;
m := BModule(b); m := BModule(b);
if m.module = nil then InternalError(n.info, 'finishModule'); if m.module = nil then InternalError(n.info, 'myProcess');
initProc(p, globals, m, nil, m.module.options); initProc(p, globals, m, nil, m.module.options);
genModule(p, n, r); genModule(p, n, r);
app(p.globals.code, p.data); app(p.globals.code, p.data);
app(p.globals.code, mergeStmt(r)); app(p.globals.code, mergeStmt(r));
if sfMainModule in m.module.flags then begin
// write the file:
code := con(p.globals.typeInfo, p.globals.code);
outfile := changeFileExt(completeCFilePath(m.filename), 'js');
{@discard} writeRopeIfNotEqual(con(genHeader(), code), outfile);
end;
end; end;
function EcmasBackend(b: PBackend; module: PSym; function myClose(b: PPassContext; n: PNode): PNode;
const filename: string): PBackend;
var var
g: BModule; m: BModule;
code: PRope;
outfile: string;
begin begin
g := newModule(module, filename); result := myProcess(b, n);
g.backendCreator := EcmasBackend; m := BModule(b);
g.eventMask := {@set}[eAfterModule]; if sfMainModule in m.module.flags then begin
g.afterModuleEvent := finishModule; // write the file:
result := g; code := con(globals.typeInfo, globals.code);
outfile := changeFileExt(completeCFilePath(m.filename), 'js');
{@discard} writeRopeIfNotEqual(con(genHeader(), code), outfile);
end
end;
function myOpenCached(s: PSym; const filename: string;
rd: PRodReader): PPassContext;
begin
InternalError('symbol files are not possible with the Ecmas code generator');
result := nil;
end;
function myOpen(s: PSym; const filename: string): PPassContext;
begin
result := newModule(s, filename);
end;
function ecmasgenPass(): TPass;
begin
InitPass(result);
result.open := myOpen;
result.close := myClose;
result.openCached := myOpenCached;
result.process := myProcess;
end; end;
end. end.

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,8 @@ interface
{$include 'config.inc'} {$include 'config.inc'}
uses uses
nsystem, nimconf, msgs; nsystem, charsets, lists, ropes, nos, strutils, platform, condsyms, options,
msgs;
// some things are read in from the configuration file // some things are read in from the configuration file
@ -89,7 +90,7 @@ const
optSpeed: ' -O -p6 '; optSpeed: ' -O -p6 ';
optSize: ' -O -p6 '; optSize: ' -O -p6 ';
compilerExe: 'lcc'; compilerExe: 'lcc';
compileTmpl: '-e1 $options $include -Fo$objfile $file'; compileTmpl: '$options $include -Fo$objfile $file';
buildGui: ' -subsystem windows'; buildGui: ' -subsystem windows';
buildDll: ' -dll'; buildDll: ' -dll';
linkerExe: 'lcclnk'; linkerExe: 'lcclnk';
@ -287,13 +288,10 @@ function NameToCC(const name: string): TSystemCC;
procedure initVars; procedure initVars;
procedure setCC(const ccname: string); procedure setCC(const ccname: string);
procedure writeMapping(const cfile: string; gSymbolMapping: PRope);
implementation implementation
uses
charsets,
lists, options, ropes, nos, strutils, platform, condsyms;
var var
toLink, toCompile, externalToCompile: TLinkedList; toLink, toCompile, externalToCompile: TLinkedList;
linkOptions: string = ''; linkOptions: string = '';
@ -301,16 +299,31 @@ var
ccompilerpath: string = ''; ccompilerpath: string = '';
procedure initVars; procedure setCC(const ccname: string);
var
i: TSystemCC;
begin begin
// BUGFIX: '.' forgotten linkOptions := '';
ccompiler := nameToCC(ccname);
if ccompiler = ccNone then rawMessage(errUnknownCcompiler, ccname);
compileOptions := getConfigVar(CC[ccompiler].name + '.options.always'); compileOptions := getConfigVar(CC[ccompiler].name + '.options.always');
// have the variables not been initialized?
ccompilerpath := getConfigVar(CC[ccompiler].name + '.path'); ccompilerpath := getConfigVar(CC[ccompiler].name + '.path');
for i := low(CC) to high(CC) do undefSymbol(CC[i].name);
defineSymbol(CC[ccompiler].name);
end;
procedure initVars;
var
i: TSystemCC;
begin
// we need to define the symbol here, because ``CC`` may have never been set! // we need to define the symbol here, because ``CC`` may have never been set!
setCC(CC[ccompiler].name); for i := low(CC) to high(CC) do undefSymbol(CC[i].name);
defineSymbol(CC[ccompiler].name);
if gCmd = cmdCompileToCpp then if gCmd = cmdCompileToCpp then
cExt := '.cpp'; cExt := '.cpp';
addCompileOption(getConfigVar(CC[ccompiler].name + '.options.always'));
if length(ccompilerPath) = 0 then
ccompilerpath := getConfigVar(CC[ccompiler].name + '.path');
end; end;
function completeCFilePath(const cfile: string; function completeCFilePath(const cfile: string;
@ -331,28 +344,28 @@ begin
end; end;
procedure setCC(const ccname: string); procedure addStr(var dest: string; const src: string);
var
i: TSystemCC;
begin begin
ccompiler := nameToCC(ccname); dest := dest +{&} src;
if ccompiler = ccNone then end;
rawMessage(errUnknownCcompiler, ccname);
for i := low(CC) to high(CC) do procedure addOpt(var dest: string; const src: string);
undefSymbol(CC[i].name); begin
defineSymbol(CC[ccompiler].name) if (length(dest) = 0) or (dest[length(dest)-1+strStart] <> ' ') then
addStr(dest, ' '+'');
addStr(dest, src);
end; end;
procedure addCompileOption(const option: string); procedure addCompileOption(const option: string);
begin begin
if strutils.findSubStr(option, compileOptions, strStart) < strStart then if strutils.findSubStr(option, compileOptions, strStart) < strStart then
compileOptions := compileOptions + ' ' +{&} option addOpt(compileOptions, option)
end; end;
procedure addLinkOption(const option: string); procedure addLinkOption(const option: string);
begin begin
if findSubStr(option, linkOptions, strStart) < strStart then if findSubStr(option, linkOptions, strStart) < strStart then
linkOptions := linkOptions + ' ' +{&} option addOpt(linkOptions, option)
end; end;
function toObjFile(const filenameWithoutExt: string): string; function toObjFile(const filenameWithoutExt: string): string;
@ -378,9 +391,9 @@ end;
procedure execExternalProgram(const cmd: string); procedure execExternalProgram(const cmd: string);
begin begin
if optListCmd in gGlobalOptions then if (optListCmd in gGlobalOptions) or (gVerbosity > 0) then
MessageOut('Executing: ' +{&} nl +{&} cmd); MessageOut('Executing: ' +{&} nl +{&} cmd);
if ExecuteProcess(cmd) <> 0 then if executeShellCommand(cmd) <> 0 then
rawMessage(errExecutionOfProgramFailed); rawMessage(errExecutionOfProgramFailed);
end; end;
@ -391,12 +404,7 @@ begin
splitPath(projectFile, path, scriptname); splitPath(projectFile, path, scriptname);
SplitFilename(scriptname, name, ext); SplitFilename(scriptname, name, ext);
name := appendFileExt('compile_' + name, platform.os[targetOS].scriptExt); name := appendFileExt('compile_' + name, platform.os[targetOS].scriptExt);
WriteRope(script, joinPath([path, genSubDir, name])); WriteRope(script, joinPath(path, name));
end;
procedure addStr(var dest: string; const src: string);
begin
dest := dest +{&} src;
end; end;
function getOptSpeed(c: TSystemCC): string; function getOptSpeed(c: TSystemCC): string;
@ -420,17 +428,51 @@ begin
result := cc[c].optSize // use default settings from this file result := cc[c].optSize // use default settings from this file
end; end;
const
specialFileA = 42;
specialFileB = 42;
var
fileCounter: int;
function getCompileCFileCmd(const cfilename: string; function getCompileCFileCmd(const cfilename: string;
isExternal: bool = false): string; isExternal: bool = false): string;
var var
cfile, objfile, options, includeCmd, compilePattern: string; cfile, objfile, options, includeCmd, compilePattern, key, trunk, exe: string;
c: TSystemCC; // an alias to ccompiler c: TSystemCC; // an alias to ccompiler
begin begin
c := ccompiler; c := ccompiler;
options := compileOptions; options := compileOptions;
if optCDebug in gGlobalOptions then addStr(options, ' ' + getDebug(c)); trunk := getFileTrunk(cfilename);
if optOptimizeSpeed in gOptions then addStr(options, ' ' + getOptSpeed(c)) if optCDebug in gGlobalOptions then begin
else if optOptimizeSize in gOptions then addStr(options, ' ' + getOptSize(c)); key := trunk + '.debug';
if existsConfigVar(key) then
addOpt(options, getConfigVar(key))
else
addOpt(options, getDebug(c))
end;
if (optOptimizeSpeed in gOptions) then begin
//if ((fileCounter >= specialFileA) and (fileCounter <= specialFileB)) then
key := trunk + '.speed';
if existsConfigVar(key) then
addOpt(options, getConfigVar(key))
else
addOpt(options, getOptSpeed(c))
end
else if optOptimizeSize in gOptions then begin
key := trunk + '.size';
if existsConfigVar(key) then
addOpt(options, getConfigVar(key))
else
addOpt(options, getOptSize(c))
end;
key := trunk + '.always';
if existsConfigVar(key) then
addOpt(options, getConfigVar(key));
exe := cc[c].compilerExe;
key := cc[c].name + '.exe';
if existsConfigVar(key) then
exe := getConfigVar(key);
if (optGenDynLib in gGlobalOptions) if (optGenDynLib in gGlobalOptions)
and (ospNeedsPIC in platform.OS[targetOS].props) then and (ospNeedsPIC in platform.OS[targetOS].props) then
@ -441,8 +483,7 @@ begin
includeCmd := cc[c].includeCmd; // this is more complex than needed, but includeCmd := cc[c].includeCmd; // this is more complex than needed, but
// a workaround of a FPC bug... // a workaround of a FPC bug...
addStr(includeCmd, libpath); addStr(includeCmd, libpath);
compilePattern := quoteIfSpaceExists( compilePattern := quoteIfSpaceExists(JoinPath(ccompilerpath, exe));
JoinPath(ccompilerpath, cc[c].compilerExe));
end end
else begin else begin
includeCmd := ''; includeCmd := '';
@ -458,7 +499,7 @@ begin
else else
objfile := completeCFilePath(toObjFile(cfile)); objfile := completeCFilePath(toObjFile(cfile));
result := compilePattern +{&} ' ' +{&} format(cc[c].compileTmpl, result := format(compilePattern +{&} ' ' +{&} cc[c].compileTmpl,
['file', AppendFileExt(cfile, cExt), ['file', AppendFileExt(cfile, cExt),
'objfile', objfile, 'objfile', objfile,
'options', options, 'options', options,
@ -476,6 +517,7 @@ var
begin begin
it := PStrEntry(list.head); it := PStrEntry(list.head);
while it <> nil do begin while it <> nil do begin
inc(fileCounter);
// call the C compiler for the .c file: // call the C compiler for the .c file:
compileCmd := getCompileCFileCmd(it.data, isExternal); compileCmd := getCompileCFileCmd(it.data, isExternal);
if not (optCompileOnly in gGlobalOptions) then if not (optCompileOnly in gGlobalOptions) then
@ -491,16 +533,15 @@ end;
procedure CallCCompiler(const projectfile: string); procedure CallCCompiler(const projectfile: string);
var var
it: PStrEntry; it: PStrEntry;
linkCmd, objfiles, exefile, buildgui, builddll: string; linkCmd, objfiles, exefile, buildgui, builddll, linkerExe: string;
c: TSystemCC; // an alias to ccompiler c: TSystemCC; // an alias to ccompiler
script: PRope; script: PRope;
begin begin
if (gGlobalOptions * [optCompileOnly, optGenScript] = [optCompileOnly]) then if (gGlobalOptions * [optCompileOnly, optGenScript] = [optCompileOnly]) then
exit; // speed up that call if only compiling and no script shall be exit; // speed up that call if only compiling and no script shall be
// generated // generated
initVars();
if (toCompile.head = nil) and (externalToCompile.head = nil) then exit; if (toCompile.head = nil) and (externalToCompile.head = nil) then exit;
//initVars(); fileCounter := 0;
c := ccompiler; c := ccompiler;
script := nil; script := nil;
CompileCFile(toCompile, script, false); CompileCFile(toCompile, script, false);
@ -508,10 +549,13 @@ begin
if not (optNoLinking in gGlobalOptions) then begin if not (optNoLinking in gGlobalOptions) then begin
// call the linker: // call the linker:
linkerExe := getConfigVar(cc[c].name + '.linkerexe');
if length(linkerExe) = 0 then linkerExe := cc[c].linkerExe;
if (hostOS <> targetOS) then if (hostOS <> targetOS) then
linkCmd := cc[c].linkerExe linkCmd := linkerExe
else else
linkCmd := quoteIfSpaceExists(JoinPath(ccompilerpath, cc[c].linkerExe)); linkCmd := quoteIfSpaceExists(JoinPath(ccompilerpath, linkerExe));
if optGenDynLib in gGlobalOptions then if optGenDynLib in gGlobalOptions then
buildDll := cc[c].buildDll buildDll := cc[c].buildDll
@ -546,7 +590,7 @@ begin
it := PStrEntry(it.next); it := PStrEntry(it.next);
end; end;
linkCmd := linkCmd +{&} ' ' +{&} format(cc[c].linkTmpl, [ linkCmd := format(linkCmd +{&} ' ' +{&} cc[c].linkTmpl, [
'builddll', builddll, 'builddll', builddll,
'buildgui', buildgui, 'buildgui', buildgui,
'options', linkOptions, 'options', linkOptions,
@ -567,4 +611,28 @@ begin
end end
end; end;
function genMappingFiles(const list: TLinkedList): PRope;
var
it: PStrEntry;
begin
result := nil;
it := PStrEntry(list.head);
while it <> nil do begin
appf(result, '--file:"$1"$n', [toRope(AppendFileExt(it.data, cExt))]);
it := PStrEntry(it.next);
end;
end;
procedure writeMapping(const cfile: string; gSymbolMapping: PRope);
var
code: PRope;
begin
if not (optGenMapping in gGlobalOptions) then exit;
code := toRope('[C_Files]'+nl);
app(code, genMappingFiles(toCompile));
app(code, genMappingFiles(externalToCompile));
appf(code, '[Symbols]$n$1', [gSymbolMapping]);
WriteRope(code, joinPath(projectPath, 'mapping.txt'));
end;
end. end.

View file

@ -1,493 +0,0 @@
<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head>
<title>GNU General Public License - GNU Project - Free Software Foundation (FSF)</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#1F00FF" alink="#FF0000" vlink="#9900DD">
<h1>GNU General Public License</h1>
<hr>
<h2>Table of Contents</h2>
<ul>
<li><a name="TOC1" href="gpl.html#SEC1">GNU GENERAL PUBLIC LICENSE</a>
<ul>
<li><a name="TOC2" href="gpl.html#SEC2">Preamble</a>
<li><a name="TOC3" href="gpl.html#SEC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</a>
<li><a name="TOC4" href="gpl.html#SEC4">How to Apply These Terms to Your New Programs</a>
</ul>
</ul>
<p>
<hr>
<p>
<h2><a name="SEC1" href="gpl.html#TOC1">GNU GENERAL PUBLIC LICENSE</a></h2>
<p>
Version 2, June 1991
</p>
<pre>
Copyright (C) 1989, 1991 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.
</pre>
<h2><a name="SEC2" href="gpl.html#TOC2">Preamble</a></h2>
<p>
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
</p>
<p>
When we speak of free software, we are referring to freedom, 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 or use pieces of it
in new free programs; and that you know you can do these things.
</p>
<p>
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
</p>
<p>
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
</p>
<p>
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
</p>
<p>
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
</p>
<p>
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
</p>
<p>
The precise terms and conditions for copying, distribution and
modification follow.
</p>
<h2><a name="SEC3" href="gpl.html#TOC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</a></h2>
<p>
<strong>0.</strong>
This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
<p>
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
<p>
<strong>1.</strong>
You may copy and distribute verbatim copies of the Program's
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 give any other recipients of the Program a copy of this License
along with the Program.
<p>
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.
<p>
<strong>2.</strong>
You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
<p>
<ul>
<li><strong>a)</strong>
You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
<p>
<li><strong>b)</strong>
You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
<p>
<li><strong>c)</strong>
If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
</ul>
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
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 Program, 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.
<p>
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 Program.
<p>
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
<p>
<strong>3.</strong>
You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
<!-- we use this doubled UL to get the sub-sections indented, -->
<!-- while making the bullets as unobvious as possible. -->
<ul>
<li><strong>a)</strong>
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; or,
<p>
<li><strong>b)</strong>
Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
<p>
<li><strong>c)</strong>
Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
</ul>
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, 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 executable. However, as a
special exception, the source code 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.
<p>
If distribution of executable or 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 counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
<p>
<strong>4.</strong>
You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program 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.
<p>
<strong>5.</strong>
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 Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
<p>
<strong>6.</strong>
Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program 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 to
this License.
<p>
<strong>7.</strong>
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 Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program 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 Program.
<p>
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.
<p>
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.
<p>
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
<p>
<strong>8.</strong>
If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program 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.
<p>
<strong>9.</strong>
The Free Software Foundation may publish revised and/or new versions
of the 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.
<p>
Each version is given a distinguishing version number. If the Program
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 Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
<p>
<strong>10.</strong>
If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, 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.
<p><strong>NO WARRANTY</strong></p>
<p>
<strong>11.</strong>
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
<p>
<strong>12.</strong>
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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
<p>
<h2>END OF TERMS AND CONDITIONS</h2>
<h2><a name="SEC4" href="gpl.html#TOC4">How to Apply These Terms to Your New Programs</a></h2>
<p>
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
</p>
<p>
To do so, attach the following notices to the program. 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.
</p>
<pre>
<var>one line to give the program's name and an idea of what it does.</var>
Copyright (C) <var>yyyy</var> <var>name of author</var>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
</pre>
<p>
Also add information on how to contact you by electronic and paper mail.
</p>
<p>
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
</p>
<pre>
Gnomovision version 69, Copyright (C) <var>year</var> <var>name of author</var>
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'. This is free software, and you are welcome
to redistribute it under certain conditions; type `show c'
for details.
</pre>
<p>
The hypothetical commands <samp>`show w'</samp> and <samp>`show c'</samp> should show
the appropriate parts of the General Public License. Of course, the
commands you use may be called something other than <samp>`show w'</samp> and
<samp>`show c'</samp>; they could even be mouse-clicks or menu items--whatever
suits your program.
</p>
<p>
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
</p>
<pre>
Yoyodyne, Inc., hereby disclaims all copyright
interest in the program `Gnomovision'
(which makes passes at compilers) written
by James Hacker.
<var>signature of Ty Coon</var>, 1 April 1989
Ty Coon, President of Vice
</pre>
<p>
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
</body></html>

View file

@ -8,6 +8,8 @@
// //
unit hashes; unit hashes;
{$include 'config.inc'}
interface interface
uses uses

View file

@ -358,7 +358,7 @@ begin
end end
end; end;
g.len := pos - g.pos; g.len := pos - g.pos;
assert((g.kind = gtEof) or (g.len > 0)); if (g.kind <> gtEof) and (g.len <= 0) then InternalError('nimNextToken');
g.pos := pos; g.pos := pos;
end; end;
@ -633,7 +633,7 @@ begin
end end
end; end;
g.len := pos - g.pos; g.len := pos - g.pos;
assert((g.kind = gtEof) or (g.len > 0)); if (g.kind <> gtEof) and (g.len <= 0) then InternalError('clikeNextToken');
g.pos := pos; g.pos := pos;
end; end;
@ -711,7 +711,7 @@ begin
langCsharp: csharpNextToken(g); langCsharp: csharpNextToken(g);
langC: cNextToken(g); langC: cNextToken(g);
langJava: javaNextToken(g); langJava: javaNextToken(g);
else assert(false); else InternalError('getNextToken');
end end
end; end;

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