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

105
cogapp.py
View file

@ -5,11 +5,13 @@
"""
# $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 imp, compiler
import imp
import copy, getopt, shlex
from cStringIO import StringIO
from string import strip, split, join, replace
__all__ = ['Cog', 'CogUsageError']
@ -99,7 +101,11 @@ class CogGenerator(Redirectable):
self.markers.append(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):
""" Extract the executable Python code from the generator.
@ -109,8 +115,14 @@ class CogGenerator(Redirectable):
# then remove it from all the lines.
prefIn = commonPrefix(self.markers + self.lines)
if prefIn:
self.markers = [ l.replace(prefIn, '', 1) for l in self.markers ]
self.lines = [ l.replace(prefIn, '', 1) for l in self.lines ]
tmp = []
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, '')
@ -123,9 +135,14 @@ class CogGenerator(Redirectable):
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')
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.
cog.cogmodule.msg = self.msg
cog.cogmodule.out = self.out
@ -139,31 +156,31 @@ class CogGenerator(Redirectable):
# ends with a newline, or it will be joined to the
# end-output line, ruining cog's idempotency.
if self.outstring and self.outstring[-1] != '\n':
self.outstring += '\n'
self.outstring = self.outstring + '\n'
return reindentBlock(self.outstring, prefOut)
def msg(self, s):
print >>self.stdout, "Message: "+s
self.stdout.write("Message: "+s+"\n")
def out(self, sOut='', dedent=False, trimblanklines=False):
""" The cog.out function.
"""
if trimblanklines and ('\n' in sOut):
lines = sOut.split('\n')
if lines[0].strip() == '':
lines = split(sOut, '\n')
if strip(lines[0]) == '':
del lines[0]
if lines and lines[-1].strip() == '':
if lines and strip(lines[-1]) == '':
del lines[-1]
sOut = '\n'.join(lines)+'\n'
sOut = join(lines,'\n')+'\n'
if dedent:
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.
"""
self.out(sOut, **kw)
self.out(sOut, dedent, trimblanklines)
self.out('\n')
def error(self, msg='Error raised by cog generator.'):
@ -185,7 +202,7 @@ class NumberedFileReader:
def readline(self):
l = self.f.readline()
if l:
self.n += 1
self.n = self.n + 1
return l
def linenumber(self):
@ -225,7 +242,7 @@ class CogOptions:
def addToIncludePath(self, dirs):
""" Add directories to the include path.
"""
dirs = dirs.split(os.pathsep)
dirs = split(dirs, os.pathsep)
self.includePath.extend(dirs)
def parseArgs(self, argv):
@ -244,7 +261,7 @@ class CogOptions:
elif o == '-D':
if a.count('=') < 1:
raise CogUsageError("-D takes a name=value argument")
name, value = a.split('=', 1)
name, value = split(a, '=', 1)
self.defines[name] = value
elif o == '-e':
self.bWarnEmpty = True
@ -281,6 +298,14 @@ class CogOptions:
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):
""" The Cog engine.
"""
@ -298,7 +323,7 @@ class Cog(Redirectable):
self.installCogModule()
def showWarning(self, msg):
print >>self.stdout, "Warning:", msg
self.stdout.write("Warning: " + msg + "\n")
def isBeginSpecLine(self, s):
return string.find(s, self.sBeginSpec) >= 0
@ -326,11 +351,11 @@ class Cog(Redirectable):
sFileIn = fname or ''
sFileOut = fname or ''
# Convert filenames to files.
if isinstance(fIn, types.StringTypes):
if type(fIn) == type(""):
# Open the input file.
sFileIn = fIn
fIn = open(fIn, 'r')
if isinstance(fOut, types.StringTypes):
if type(fOut) == type(""):
# Open the output file.
sFileOut = fOut
fOut = open(fOut, self.sOutputMode)
@ -383,7 +408,7 @@ class Cog(Redirectable):
raise CogError("Cog code markers inverted",
file=sFileIn, line=firstLineNum)
else:
sCode = l[beg+len(self.sBeginSpec):end].strip()
sCode = strip(l[beg+len(self.sBeginSpec):end])
gen.parseLine(sCode)
else:
# Deal with an ordinary code block.
@ -424,7 +449,7 @@ class Cog(Redirectable):
file=sFileIn, line=fIn.linenumber())
hasher.update(l)
l = fIn.readline()
curHash = hasher.hexdigest()
curHash = mydigest(hasher)
if not l and not self.options.bEofCanBeEnd:
# We reached end of file before we found the end output line.
@ -440,7 +465,7 @@ class Cog(Redirectable):
sGen = self.suffixLines(sGen)
hasher.update(sGen)
fOut.write(sGen)
newHash = hasher.hexdigest()
newHash = mydigest(hasher)
bSawCog = True
@ -453,16 +478,16 @@ class Cog(Redirectable):
raise CogError("Output has been edited! Delete old checksum to unprotect.",
file=sFileIn, line=fIn.linenumber())
# Create a new end line with the correct hash.
endpieces = l.split(hashMatch.group(0), 1)
endpieces = split(l, hashMatch.group(0), 1)
else:
# There was no old hash, but we want a new hash.
endpieces = l.split(self.sEndOutput, 1)
l = (self.sEndFormat % newHash).join(endpieces)
endpieces = split(l, self.sEndOutput, 1)
l = join(endpieces, (self.sEndFormat % newHash))
else:
# We don't want hashes output, so if there was one, get rid of
# it.
if hashMatch:
l = l.replace(hashMatch.groupdict()['hashsect'], '', 1)
l = replace(l, hashMatch.groupdict()['hashsect'], '', 1)
if not self.options.bDeleteCode:
fOut.write(l)
@ -480,7 +505,7 @@ class Cog(Redirectable):
"""
if self.options.sSuffix:
# 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)
return text
@ -500,7 +525,7 @@ class Cog(Redirectable):
# Need to ensure we can write.
if self.options.sMakeWritableCmd:
# Use an external command to make the file writable.
cmd = self.options.sMakeWritableCmd.replace('%s', sOldPath)
cmd = replace(self.options.sMakeWritableCmd, '%s', sOldPath)
self.stdout.write(os.popen(cmd).read())
if not os.access(sOldPath, os.W_OK):
raise CogError("Couldn't make %s writable" % sOldPath)
@ -548,7 +573,7 @@ class Cog(Redirectable):
elif self.options.bReplace:
# We want to replace the cog file with the output,
# but only if they differ.
print >>self.stdout, "Cogging %s" % sFile,
self.stdout.write("Cogging %s" % sFile)
bNeedNewline = True
try:
@ -557,7 +582,7 @@ class Cog(Redirectable):
fOldFile.close()
sNewText = self.processString(sOldText, fname=sFile)
if sOldText != sNewText:
print >>self.stdout, " (changed)"
self.stdout.write(" (changed)\n")
bNeedNewline = False
self.replaceFile(sFile, sNewText)
finally:
@ -566,7 +591,7 @@ class Cog(Redirectable):
# same line, but also make sure to break the line before
# any traceback.
if bNeedNewline:
print >>self.stdout
self.stdout.write('\n')
else:
self.processFile(sFile, self.stdout, sFile)
finally:
@ -613,14 +638,14 @@ class Cog(Redirectable):
# Provide help if asked for anywhere in the command line.
if '-?' in argv or '-h' in argv:
print >>self.stderr, usage,
self.stderr.write(usage)
return
self.options.parseArgs(argv)
self.options.validate()
if self.options.bShowVersion:
print >>self.stdout, "Cog version %s" % __version__
self.stdout.write("Cog version %s\n" % __version__)
return
if self.options.args:
@ -637,14 +662,14 @@ class Cog(Redirectable):
self.callableMain(argv)
return 0
except CogUsageError, err:
print >>self.stderr, err
print >>self.stderr, "(for help use -?)"
self.stderr.write(err + "\n")
self.stderr.write("(for help use -?)\n")
return 2
except CogGeneratedError, err:
print >>self.stderr, "Error: %s" % err
self.stderr.write("Error: %s\n" % err)
return 3
except CogError, err:
print >>self.stderr, err
self.stderr.write(err + "\n")
return 1
except:
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!
# 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"
path="$lib/base"
path="$lib/base/gtk"
path="$lib/base/cairo"
path="$lib/base/x11"
path="$lib/base/sdl"
path="$lib/base/opengl"
path="$lib/windows"
path="$lib/posix"
path="$lib/ecmas"
@ -25,20 +27,23 @@ path="$lib/extra"
stacktrace:off
debugger:off
line_dir:off
opt:speed
@end
# additional defines:
#define=""
# additional options always passed to the compiler:
force_build
line_dir=off
cfilecache=on
# use the new experimental symbol files for speeding up compilation:
#--symbol_files
--verbosity: "1"
hint[LineTooLong]=off
hint[XDeclaredButNotUsed]=off
@if unix:
passl= "-ldl"
@if not bsd: passl= "-ldl" @end
path = "$lib/base/gtk"
@end
@ -50,10 +55,12 @@ hint[XDeclaredButNotUsed]=off
# Configuration for the LLVM GCC compiler:
@if windows:
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
llvm_gcc.options.debug = "-g"
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"
# Configuration for the Borland C++ Compiler:
@ -62,23 +69,24 @@ llvm_gcc.options.size = "-Os -ffast-math"
@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.always = "-H- -q -RT- -a8 -w-8027 -w-8066 -w-8004"
bcc.options.speed = "-O2 -6"
bcc.options.size = "-O1 -6"
# Configuration for the Visual C/C++ compiler:
@if vcc:
@prepend_env path r"C:\Eigenes\compiler\vcc2005\Common7\IDE;"
@prepend_env INCLUDE r"C:\Eigenes\compiler\vcc2005\VC\include;C:\Eigenes\compiler\vcc2005\VC\ATLMFC\INCLUDE;"
@prepend_env LIB r"C:\Eigenes\compiler\vcc2005\VC\lib;C:\Eigenes\compiler\vcc2005\SDK\v2.0\Lib;"
@prepend_env 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
@end
@if windows:
vcc.path = r"C:\Eigenes\compiler\vcc2005\VC\bin"
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"
vcc.options.speed = "/Ox /arch:SSE2"
vcc.options.size = "/O1"
# Configuration for the Watcom C/C++ compiler:
@if windows:
@ -122,10 +130,11 @@ lcc.options.size = "-O -p6"
# Configuration for the Tiny C Compiler:
@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
tcc.options.debug = "-b"
tcc.options.always = ""
tcc.options.debug = ""
tcc.options.speed = ""
tcc.options.size = ""
@ -146,7 +155,7 @@ icc.options.always = "-w"
icc.options.speed = "-O3 -ffast-math"
icc.options.size = "-Os -ffast-math"
@write "used default config file"
@write "used special config file"
@if ecmascript:
@write "Target is ECMAScript! No unsafe features are allowed!"

View file

@ -1,5 +1,4 @@
# 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.
@ -8,38 +7,42 @@
# @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
cc = @if windows: llvm_gcc @else: gcc @end
lib="$nimrod/lib"
path="$lib/base"
path="$lib/base/gtk"
path="$lib/base/cairo"
path="$lib/base/x11"
path="$lib/base/sdl"
path="$lib/base/opengl"
path="$lib/base/zip"
path="$lib/windows"
path="$lib/posix"
path="$lib/ecmas"
path="$lib/extra"
@if release:
checks:off
obj_checks:off
field_checks:off
range_checks:off
bound_checks:off
overflow_checks:off
assertions:off
stacktrace:off
debugger:off
line_dir:off
opt:speed
@end
# additional defines:
#define=""
# additional options always passed to the compiler:
force_build
line_dir=off
cfilecache=on
--verbosity: "1"
hint[LineTooLong]=off
hint[XDeclaredButNotUsed]=off
#hint[XDeclaredButNotUsed]=off
@if unix:
passl= "-ldl"
path = "$lib/base/gtk"
@if not bsd: passl= "-ldl" @end
@end
@if icc:
@ -50,107 +53,48 @@ hint[XDeclaredButNotUsed]=off
# Configuration for the LLVM GCC compiler:
@if windows:
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
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"
llvm_gcc.options.speed = "-O2"
llvm_gcc.options.size = "-Os"
# Configuration for the Visual C/C++ compiler:
@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
@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"
vcc.options.speed = "/Ox /arch:SSE2"
vcc.options.size = "/O1"
# Configuration for the GNU C/C++ compiler:
@if windows:
gcc.path = r"C:\eigenes\compiler\mingw\bin"
@end
#gcc.exe = "gcc-4.1"
#gcc.linkerExe = "gcc-4.1"
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"
gcc.options.speed = "-O3 -fno-strict-aliasing"
gcc.options.size = "-Os"
# 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"
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
tcc.options.always = "-w"

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

View file

@ -8,61 +8,52 @@
#
{
'SymFlag': [ # already 32 flags!
'sfTypeCheck', # wether macro parameters should be type checked
'SymFlag': [ # already 26 flags!
'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
'sfImportc', # symbol is external; imported
'sfExportc', # symbol is exported (under a specified name)
'sfVolatile', # variable is volatile
'sfUsed', # read access of sym (for warnings) or simply used
'sfWrite', # write access of variable (for hints)
'sfRegister', # variable should be placed in a register
'sfPure', # object is "pure" that means it has no type-information
'sfCodeGenerated', # wether we have already code generated for the proc
'sfPrivate', # symbol should be made private after module compilation
'sfGlobal', # symbol is at global scope
'sfResult', # variable is 'result' in proc
'sfNoSideEffect', # proc has no side effects
'sfMainModule', # module is the main module
'sfSystemModule', # module is the system module
'sfNoReturn', # proc never returns (an exit proc)
'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
# 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
'sfDeprecated', # symbol is deprecated
'sfInClosure', # variable is accessed by a closure
'sfIsCopy', # symbol is a copy; needed for proper name mangling
'sfStar', # symbol has * visibility
'sfMinus' # symbol has - visibility
'sfTypeCheck', # wether macro parameters should be type checked
'sfCompileTime', # proc can be evaluated at compile time
'sfThreadVar', # variable is a thread variable
'sfMerge', # proc can be merged with itself
],
'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
'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!
# Don't forget to change hti.nim if you make a change here
'tyNone', 'tyBool', 'tyChar',
'tyEmptySet', 'tyArrayConstr', 'tyNil',
'tyEmpty', 'tyArrayConstr', 'tyNil',
'tyGeneric',
'tyGenericInst', # instantiated generic type
'tyGenericParam',
@ -89,7 +80,9 @@
'nfBase2', # nfBase10 is default, so not needed
'nfBase8',
'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
@ -223,6 +216,8 @@
'nkBlockExpr', # a statement block ending in an expr; this is used
# to allowe powerful multi-line templates that open a
# 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
# used for the concrete opcode
@ -264,6 +259,8 @@
'skEnumField', # an identifier in an enum
'skForVar', # a for loop variable
'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::
nimrod command [options] inputfile [arguments]
Command::
compile compile project with default code generator (C)
compile_to_c compile project with C code generator
compile_to_cpp compile project with C++ code generator
compile_to_ecmascript compile project to ECMAScript code (experimental)
doc generate the documentation for inputfile;
with --run switch opens it with $BROWSER
compile, c compile project with default code generator (C)
compile_to_c, cc compile project with C code generator
doc generate the documentation for inputfile
rst2html converts a reStructuredText file to HTML
Arguments:
arguments are passed to the program being run (if --run option is selected)
Options:
@ -14,7 +12,8 @@ Options:
-o, --out:FILE set the output filename
-d, --define:SYMBOL define a conditional symbol
-u, --undef:SYMBOL undefine a conditional symbol
-b, --force_build force rebuilding of all modules
-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
--line_trace:on|off code generation for line trace 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',
'Defined',
'New',
'NewFinalize',
'Low',
'High',
'SizeOf',
'RegisterFinalizer',
'Is',
'Succ',
'Pred',
'Inc',
'Dec',
'Ord',
'New',
'NewFinalize',
'NewSeq',
'RegisterFinalizer',
'LengthOpenArray',
'LengthStr',
'LengthArray',
@ -20,8 +24,9 @@
'Incl',
'Excl',
'Card',
'Ord',
'Chr',
'GCref',
'GCunref',
# binary arithmetic with and without overflow checking:
'AddI',
@ -161,7 +166,6 @@
'AppendSeqSeq',
'InRange',
'InSet',
'Is',
'Asgn',
'Repr',
'Exit',
@ -170,15 +174,34 @@
'Assert',
'Swap',
'IsNil',
'ArrToSeq',
# magic type constructors:
# magic types:
'Array',
'OpenArray',
'Range',
'Set',
'Seq',
'Int',
'Int8',
'Int16',
'Int32',
'Int64',
'Float',
'Float32',
'Float64',
'Bool',
'Char',
'String',
'Cstring',
'Pointer',
'AnyEnum',
'EmptySet',
'IntSetBaseType',
'Nil',
# magic constants:
'IsMainModule',
'CompileDate',
'CompileTime',
'NimrodVersion',

View file

@ -153,7 +153,8 @@
{'errSizeTooBig': "computing the type's size produced an overflow"},
{'errSetTooBig': 'set is too large'},
{'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'},
{'errIllegalRecursionInTypeX': "illegal recursion in type '$1'"},
{'errCannotInstantiateX': "cannot instantiate: '$1'"},
@ -278,16 +279,17 @@
# hints:
{'hintSuccess': 'operation successful'},
{'hintSuccessX': 'operation successful ($1 lines compiled; $2 sec total)'},
{'hintLineTooLong': 'line too long'},
{'hintXDeclaredButNotUsed': "'$1' is declared but not used"},
{'hintConvToBaseNotNeeded': 'conversion to base object is not needed'},
{'hintConvFromXtoItselfNotNeeded': 'conversion from $1 to itself is pointless'},
{'hintExprAlwaysX': "expression evaluates always to '$1'"},
{'hintMo2FileInvalid': "mo2 file '$1' is invalid"},
{'hintModuleHasChanged': "module '$1' has been changed"},
{'hintCannotOpenMo2File': "mo2 file '$1' does not exist"},
{'hintQuitCalled': "quit() called"},
{'hintProcessing': "processing"},
{'hintProcessing': "processing $1"},
{'hintCodeBegin': "generated code listing:"},
{'hintCodeEnd': "end of listing"},
{'hintConf': "used config file '$1'"},
# user hint message:
{'hintUser': '$1'}

View file

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

View file

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

View file

@ -28,11 +28,10 @@ castExpr ::= CAST BRACKET_LE optInd typeDesc BRACKERT_RI
PAR_LE optInd expr PAR_RI
addrExpr ::= ADDR PAR_LE optInd expr PAR_RI
symbol ::= ACC (KEYWORD | IDENT | operator | PAR_LE PAR_RI
| BRACKET_LE BRACKET_RI) ACC | IDENT
accExpr ::= KEYWORD | IDENT | operator [DOT KEYWORD | IDENT | operator]
paramList
primary ::= ( prefixOperator optInd )* ( IDENT | literal | ACC accExpr ACC
| castExpr | addrExpr ) (
| BRACKET_LE BRACKET_RI | EQUALS | literal )+ ACC
| IDENT
primary ::= ( prefixOperator optInd )* ( symbol | constructor |
| castExpr | addrExpr ) (
DOT optInd symbol
#| CURLY_LE namedTypeDescList CURLY_RI
| PAR_LE optInd
@ -49,11 +48,12 @@ literal ::= INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
| STR_LIT | RSTR_LIT | TRIPLESTR_LIT
| CHAR_LIT | RCHAR_LIT
| NIL
constructor ::= literal
| BRACKET_LE optInd (expr [COLON expr] optComma )* BRACKET_RI # []-Constructor
| CURLY_LE optInd (expr [DOTDOT expr] optComma )* CURLY_RI # {}-Constructor
| PAR_LE optInd (expr [COLON expr] optComma )* PAR_RI # ()-Constructor
exprList ::= ( expr optComma )*
namedExpr ::= expr [EQUALS expr] # actually this is symbol EQUALS expr|expr
@ -170,7 +170,7 @@ objectCase ::= CASE expr COLON typeDesc [COMMENT]
(OF sliceList COLON [COMMENT] objectPart)*
[ELSE COLON [COMMENT] objectPart]
objectPart ::= objectWhen | objectCase | objectIdentPart
objectPart ::= objectWhen | objectCase | objectIdentPart | NIL
| indPush objectPart (SAD objectPart)* DED
tupleDesc ::= BRACKET_LE optInd ((symbol optComma)+ COLON typeDesc optComma)* BRACKET_RI

View file

@ -32,7 +32,7 @@ Path Purpose
``config`` configuration files for Nimrod go into here
``lib`` the Nimrod library lives here; ``rod`` depends
on it!
``web`` website of Nimrod; generated by ``genweb.py``
``web`` website of Nimrod; generated by ``koch.py``
from the ``*.txt`` and ``*.tmpl`` files
``koch`` the Koch Build System (written for Nimrod)
``obj`` generated ``*.obj`` files go into here
@ -49,20 +49,19 @@ and Free Pascal can compile the Nimrod compiler.
Requirements for bootstrapping:
- Free Pascal (I used version 2.2); it may not be needed
- Python (should work with 2.4 or higher) and the code generator *cog*
(included in this distribution!)
- Free Pascal (I used version 2.2) [optional]
- Python (should work with version 1.5 or higher)
- C compiler -- one of:
* win32-lcc
* Borland C++ (tested with 5.5)
* win32-lcc (currently broken)
* Borland C++ (tested with 5.5; currently broken)
* Microsoft C++
* Digital Mars C++
* Watcom C++ (currently broken; a fix is welcome!)
* Watcom C++ (currently broken)
* GCC
* Intel C++
* Pelles C
* Pelles C (currently broken)
* llvm-gcc
| 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
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
@ -124,7 +123,7 @@ Complex assignments
We already knew the type information as a graph in the compiler.
Thus we need to serialize this graph as RTTI for C code generation.
Look at the files ``lib/typeinfo.nim``, ``lib/hti.nim`` for more information.
Look at the file ``lib/hti.nim`` for more information.
The Garbage Collector
@ -135,18 +134,11 @@ Introduction
We use the term *cell* here to refer to everything that is traced
(sequences, refs, strings).
This section describes how the new GC works. The old algorithms
all had the same problem: Too complex to get them right. This one
tries to find the right compromise.
This section describes how the new GC works.
The basic algorithm is *Deferrent reference counting* with cycle detection.
References in the stack are not counted for better performance and easier C
code generation. The GC starts by traversing the hardware stack and increments
the reference count (RC) of every cell that it encounters. After the GC has
done its work the stack is traversed again and the RC of every cell
that it encounters are decremented again. Thus no marking bits in the RC are
needed. Between these stack traversals the GC has a complete accurate view over
the RCs.
code generation.
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
@ -156,72 +148,44 @@ is extremely important that ``pointer`` is not confused with a ``PCell``
as this would lead to a memory corruption.
When to trigger a collection
----------------------------
Since there are really two different garbage collectors (reference counting
and mark and sweep) we use two different heuristics when to run the passes.
The RC-GC pass is fairly cheap: Thus we use an additive increase (7 pages)
for the RC_Threshold and a multiple increase for the CycleThreshold.
The AT and ZCT sets
-------------------
The GC maintains two sets throughout the lifetime of
the program (plus two temporary ones). The AT (*any table*) simply contains
every cell. The ZCT (*zero count table*) contains every cell whose RC is
zero. This is used to reclaim most cells fast.
The ZCT contains redundant information -- the AT alone would suffice.
However, traversing the AT and look if the RC is zero would touch every living
cell in the heap! That's why the ZCT is updated whenever a RC drops to zero.
The ZCT is not updated when a RC is incremented from zero to one, as
this would be too costly.
The CellSet data structure
--------------------------
The AT and ZCT depend on an extremely efficient datastructure for storing a
set of pointers - this is called a ``PCellSet`` in the source code.
The GC depends on an extremely efficient datastructure for storing a
set of pointers - this is called a ``TCellSet`` in the source code.
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
type
PCellSet # hidden
TCellSet # hidden
proc allocCellSet: PCellSet # make a new set
proc deallocCellSet(s: PCellSet) # empty the set and free its memory
proc incl(s: PCellSet, elem: PCell) # include an element
proc excl(s: PCellSet, elem: PCell) # exclude an element
proc CellSetInit(s: var TCellSet) # initialize a new set
proc CellSetDeinit(s: var TCellSet) # empty the set and free its memory
proc incl(s: var TCellSet, elem: PCell) # include 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
become huge (the AT contains every allocated cell!) a hash table is not
suitable for this.
All the operations have to be perform efficiently. Because a Cellset can
become huge a hash table alone is not suitable for this.
We use a mixture of bitset and patricia tree for this. One node in the
patricia tree contains a bitset that decribes a page of the operating system
(not always, but that doesn't matter).
So including a cell is done as follows:
We use a mixture of bitset and hash table for this. The hash table maps *pages*
to a page descriptor. The page descriptor contains a bit for any possible cell
address within this page. So including a cell is done as follows:
- Find the page descriptor for the page the cell belongs to.
- Set the appropriate bit in the page descriptor indicating that the
cell points to the start of a memory block.
Removing a cell is analogous - the bit has to be set to zero.
Single page descriptors are never deleted from the tree. Typically a page
descriptor is only 19 words big, so it does not waste much by not deleting
it. Apart from that the AT and ZCT are rebuilt frequently, so removing a
single page descriptor from the tree is never necessary.
Single page descriptors are never deleted from the hash table. This is not
needed as the data structures need to be periodically rebuilt anyway.
Complete traversal is done like so::
Complete traversal is done in this way::
for each page decriptor 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)
the check whether the ref is on the stack is very cheap (only two
comparisons). Another advantage of this scheme is that the code produced is
a tiny bit smaller.
smaller.
The algorithm in pseudo-code
----------------------------
Now we come to the nitty-gritty. The algorithm works in several phases.
Phase 1 - Consider references from stack
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
for each pointer p in the stack: incRef(p)
This is necessary because references in the hardware stack are not traced for
better performance. After Phase 1 the RCs are accurate.
Phase 2 - Free the ZCT
~~~~~~~~~~~~~~~~~~~~~~
This is how things used to (not) work::
for p in elements(ZCT):
if RC(p) == 0:
call finalizer of p
for c in children(p): decRef(c) # free its children recursively
# if necessary; the childrens RC >= 1, BUT they may still be in the ZCT!
free(p)
else:
remove p from the ZCT
Instead we do it this way. Note that the recursion is gone too!
::
newZCT = nil
for p in elements(ZCT):
if RC(p) == 0:
call finalizer of p
for c in children(p):
assert(RC(c) > 0)
dec(RC(c))
if RC(c) == 0:
if newZCT == nil: newZCT = allocCellSet()
incl(newZCT, c)
free(p)
else:
# nothing to do! We will use the newZCS
deallocCellSet(ZCT)
ZCT = newZCT
This phase is repeated until enough memory is available or the ZCT is nil.
If still not enough memory is available the cyclic detector gets its chance
to do something.
Phase 3 - Cycle detection
~~~~~~~~~~~~~~~~~~~~~~~~~
Cycle detection works by subtracting internal reference counts::
newAT = allocCellSet()
for y in elements(AT):
# pretend that y is dead:
for c in children(y):
dec(RC(c))
# note that this should not be done recursively as we have all needed
# pointers in the AT! This makes it more efficient too!
proc restore(y: PCell) =
# unfortunately, the recursion here cannot be eliminated easily
if y not_in newAT:
incl(newAT, y)
for c in children(y):
inc(RC(c)) # restore proper reference counts!
restore(c)
for y in elements(AT) with rc > 0:
restore(y)
for y in elements(AT) with rc == 0:
free(y) # if pretending worked, it was part of a cycle
AT = newAT
Phase 4 - Ignore references from stack again
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
for each pointer p in the stack:
dec(RC(p))
if RC(p) == 0: incl(ZCT, p)
Now the RCs correctly discard any references from the stack. One can also see
this as a temporary marking operation. Things that are referenced from stack
are marked during the GC's operarion and now have to be unmarked.
To be written.
The compiler's architecture

View file

@ -57,12 +57,18 @@ Basic libraries
style-insensitive mode. An efficient string substitution operator ``%``
for the string table is also provided.
* `streams <streams.html>`_
This module provides a stream interface and two implementations thereof:
the `PFileStream` and the `PStringStream` which implement the stream
interface for Nimrod file objects (`TFile`) and strings. Other modules
may provide other implementations for this standard stream interface.
* `hashes <hashes.html>`_
This module implements efficient computations of hash values for diverse
Nimrod types.
* `lexbase <lexbase.html>`_
This is a low leve module that implements an extremely efficent buffering
This is a low level module that implements an extremely efficent buffering
scheme for lexers and parsers. This is used by the ``parsecfg`` module.
@ -78,6 +84,8 @@ Advanced libaries
builds on the GTK interface. On Windows, native dialogs are shown if
appropriate.
* `zipfiles <zipfiles.html>`_
This module implements a zip archive creator/reader/modifier.
Wrappers
========
@ -129,3 +137,80 @@ not contained in the distribution. You can then find them on the website.
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
and libraries written by different programmers cannot use incompatible
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
identifier.
advantage is that it frees the programmer from remembering the exact spelling
of an identifier.
Literal strings
@ -601,20 +601,20 @@ Array and sequence types
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.
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
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
constructed by the array constructor ``[]``.
from 0 to ``len(S)-1`` and its bounds are checked. Sequences can be
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
not to a multi-dimensional open array, because it is impossible to do so in an
efficient manner.
An array expression may be constructed by the array constructor ``[]``.
A constructed array is assignment compatible to a sequence.
Example:
.. code-block:: nimrod
@ -625,13 +625,13 @@ Example:
var
x: TIntArray
y: TIntSeq
x = [1, 2, 3, 4, 5, 6] # [] this is the array constructor that is compatible
# with arrays, open arrays and
y = [1, 2, 3, 4, 5, 6] # sequences
x = [1, 2, 3, 4, 5, 6] # [] this is the array constructor
y = @[1, 2, 3, 4, 5, 6] # the @ turns the array into a sequence
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
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
checks can be disabled via pragmas or invoking the compiler with the
@ -692,6 +692,48 @@ Object fields that should be visible outside from the defining module, have to
marked by ``*``. In contrast to tuples, different object types are
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
~~~~~~~~
@ -773,7 +815,7 @@ further information.
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,
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!
.. XXX finalizers for traced objects
@ -867,7 +909,7 @@ statement.
Statements are separated into `simple statements`:idx: and
`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
contain other statements. To avoid the `dangling else problem`:idx:, complex
statements always have to be intended::
@ -1028,10 +1070,10 @@ Example:
The `case`:idx: statement is similar to the if statement, but it represents
a multi-branch selection. The expression after the keyword ``case`` is
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*
the ``else`` part is executed. If there is no ``else`` part and not all
possible values that ``expr`` can hold occur in a ``vallist``, a static
error is given. This holds only for expressions of ordinal types.
(after the ``of`` keyword) are executed. If the value is not in any
given *slicelist* the ``else`` part is executed. If there is no ``else``
part and not all possible values that ``expr`` can hold occur in a ``vallist``,
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
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:
.. code-block:: nimrod
proc `$` (x: int): string = # converts an integer to a string;
# since it has one parameter this is a prefix
# operator. With two parameters it would be
# an infix operator.
proc `$` (x: int): string =
# converts an integer to a string; this is a prefix operator.
return intToStr(x)
Calling a procedure can be done in many different ways:
@ -1557,8 +1597,8 @@ This is best illustrated by an example:
.. code-block:: nimrod
# Module A
type
T1* = int
import B # the compiler starts parsing B
T1* = int # Module A exports the type ``T1``
import B # the compiler starts parsing B
proc main() =
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
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
------------
The `undef`:idx: pragma the counterpart to the define pragma. It undefines a
conditional symbol.
Warning: The ``undef`` pragma is deprecated as it conflicts with separate
compilation!
error pragma
------------

View file

@ -34,8 +34,15 @@ Advanced command line switches are:
Configuration file
------------------
The ``nimrod`` executable loads the configuration file ``config/nimrod.cfg``
unless this is suppressed by the ``--skip_cfg`` command line option.
The default configuration file is ``nimrod.cfg``. The ``nimrod`` executable
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 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
@ -47,11 +54,10 @@ Command line settings have priority over configuration file settings.
Nimrod's directory structure
----------------------------
The generated files that Nimrod produces all go into a subdirectory called
``rod_gen``. This makes it easy to write a script that deletes all generated
files. For example the generated C code for the module ``path/modA.nim``
will become ``path/rod_gen/modA.c``.
``nimcache`` in your project directory. This makes it easy to delete all
generated files.
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
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
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
~~~~~~~~~~~~~~
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
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
# Nimrod does not know its value
Varargs Pragma
~~~~~~~~~~~~~~
The `varargs`:idx: pragma can be applied to procedures only. It tells Nimrod
that the proc can take a variable number of parameters after the last
specified parameter. Nimrod string values will be converted to C
strings automatically:
.. code-block:: Nimrod
proc printf(formatstr: cstring) {.nodecl, varargs.}
printf("hallo %s", "world") # "world" will be passed as C string
However, the ``header`` pragma is often the better alternative.
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.
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
~~~~~~~~~~~~~~~~
The `no_static`:idx: pragma can be applied to almost any symbol and specifies
that it shall not be declared ``static`` in the generated C code. Note that
symbols in the interface part of a module never get declared ``static``, so
only in special cases is this pragma necessary.
only in very special cases this pragma is necessary.
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
though and for good reason: Often they do a better job without it anyway.
In highly specific cases (a dispatch loop of interpreters for example) it
may provide benefits, though.
In highly specific cases (a dispatch loop of an bytecode interpreter for
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
@ -244,12 +310,17 @@ efficient than any hand-coded scheme.
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
it is the proper term.
The ECMAScript code generator is experimental!
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,
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
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.} =
gtk_main_quit()

View file

@ -9,18 +9,19 @@ Note:
A C compiler is required - knowledge of C is not!
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
install it.
After you have made sure that a C compiler is available, install Nimrod
by downloading the appropriate ``.zip`` file and extracting it to a
directory of your choice. The Nimrod Compiler will stay in this
directory; do not use a temporary one! Good choices are ``/opt/nimrod`` or -
if you don't have root access - ``~/programs/nimrod``.
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 (unless you copy it somewhere else). The compiler does not need
write access to its directory anymore, so copying the nimrod folder to ``/opt``
does work.
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
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.
Installation on Windows - the easy way
--------------------------------------
Installation on Windows
-----------------------
Install Nimrod by downloading and running
the ``nimrod_windows_$version.exe`` file. The installation procedure detects
which C compilers are installed and writes the ``config/nimrod.cfg`` file
for you. If no installed C compiler is found, the ``LLVM-GCC`` compiler is
used that is bundled with this installer. So it should just work.
the ``nimrod_$version.exe`` file. As default, the ``LLVM-GCC``
compiler is used that is bundled with this installer. You can change
the configuration file to use another C compiler.
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:
Currently, the following C compilers are supported under Windows:
- | Microsoft's Visual C++
| 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.)
- | 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!)
| http://www.mingw.org/download.shtml
- | LLVM with GNU C/C++ frontend
| http://llvm.org/releases/download.html#2.2
- | Digital Mars C++
| 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!
(The first three are the easiest to install.) If you want a small download,
choose Digital Mars C++ -- it is easy to install and only about 3 MB.
If you want the highest possible performance, go for Microsoft's Visual C++ or
LLVM.
After you have made sure that a C compiler is available, install
Nimrod by downloading the appropriate .zip file and extracting it to a
directory of your choice. The Nimrod Compiler will stay in this
directory; do not use a temporary one! Then adapt the ``config/nimrod.cfg``
file appropriately. You should add Nimrod to your ``$PATH``.
For faster compile times I recommend Digital Mars C++ -- it is easy to install
and a small package.

1595
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
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.}) {.
importc: "signal", header: "<signal.h>".}

View file

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

View file

@ -65,7 +65,7 @@ proc genericAssign(dest, src: Pointer, mt: PNimType) =
of tyString: # a leaf
var s2 = cast[ppointer](s)^
if s2 != nil: # nil strings are possible!
unsureAsgnRef(cast[ppointer](dest), copyString(cast[mstring](s2)))
unsureAsgnRef(cast[ppointer](dest), copyString(cast[NimString](s2)))
else:
var x = cast[ppointer](dest)
x^ = nil

View file

@ -58,7 +58,7 @@ else:
type
PByte = cstring
cairo_status_t* = enum
TCairoStatus* = enum
CAIRO_STATUS_SUCCESS = 0, CAIRO_STATUS_NO_MEMORY,
CAIRO_STATUS_INVALID_RESTORE, CAIRO_STATUS_INVALID_POP_GROUP,
CAIRO_STATUS_NO_CURRENT_POINT, CAIRO_STATUS_INVALID_MATRIX,
@ -69,93 +69,93 @@ type
CAIRO_STATUS_PATTERN_TYPE_MISMATCH, CAIRO_STATUS_INVALID_CONTENT,
CAIRO_STATUS_INVALID_FORMAT, CAIRO_STATUS_INVALID_VISUAL,
CAIRO_STATUS_FILE_NOT_FOUND, CAIRO_STATUS_INVALID_DASH
cairo_operator_t* = enum
TCairoOperator* = enum
CAIRO_OPERATOR_CLEAR, CAIRO_OPERATOR_SOURCE, CAIRO_OPERATOR_OVER,
CAIRO_OPERATOR_IN, CAIRO_OPERATOR_OUT, CAIRO_OPERATOR_ATOP,
CAIRO_OPERATOR_DEST, CAIRO_OPERATOR_DEST_OVER, CAIRO_OPERATOR_DEST_IN,
CAIRO_OPERATOR_DEST_OUT, CAIRO_OPERATOR_DEST_ATOP, CAIRO_OPERATOR_XOR,
CAIRO_OPERATOR_ADD, CAIRO_OPERATOR_SATURATE
cairo_antialias_t* = enum
TCairoAntialias* = enum
CAIRO_ANTIALIAS_DEFAULT, CAIRO_ANTIALIAS_NONE, CAIRO_ANTIALIAS_GRAY,
CAIRO_ANTIALIAS_SUBPIXEL
cairo_fill_rule_t* = enum
TCairoFillRule* = enum
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_join_t* = enum
TCairoLineJoin* = enum
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_weight_t* = enum
TCairoFontWeight* = enum
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_BGR, CAIRO_SUBPIXEL_ORDER_VRGB,
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_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_path_data_type_t* = enum
TCairoPathDataType* = enum
CAIRO_PATH_MOVE_TO, CAIRO_PATH_LINE_TO, CAIRO_PATH_CURVE_TO,
CAIRO_PATH_CLOSE_PATH
cairo_content_t* = enum
TCairoContent* = enum
CAIRO_CONTENT_COLOR = 0x00001000, CAIRO_CONTENT_ALPHA = 0x00002000,
CAIRO_CONTENT_COLOR_ALPHA = 0x00003000
cairo_format_t* = enum
TCairoFormat* = enum
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_PAD
cairo_filter_t* = enum
TCairoFilter* = enum
CAIRO_FILTER_FAST, CAIRO_FILTER_GOOD, CAIRO_FILTER_BEST,
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_ATSUI
cairo_pattern_type_t* = enum
TCairoPatternType* = enum
CAIRO_PATTERN_TYPE_SOLID, CAIRO_PATTERN_TYPE_SURFACE,
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_XLIB, CAIRO_SURFACE_TYPE_XCB, CAIRO_SURFACE_TYPE_GLITZ,
CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_SURFACE_TYPE_WIN32,
CAIRO_SURFACE_TYPE_BEOS, CAIRO_SURFACE_TYPE_DIRECTFB,
CAIRO_SURFACE_TYPE_SVG, CAIRO_SURFACE_TYPE_OS2
cairo_svg_version_t* = enum
TCairoSvgVersion* = enum
CAIRO_SVG_VERSION_1_1, CAIRO_SVG_VERSION_1_2
Pcairo_surface_t* = ref cairo_surface_t
PPcairo_surface_t* = ref Pcairo_surface_t
Pcairo_t* = ref cairo_t
Pcairo_pattern_t* = ref cairo_pattern_t
Pcairo_font_options_t* = ref cairo_font_options_t
Pcairo_font_face_t* = ref cairo_font_face_t
Pcairo_scaled_font_t* = ref cairo_scaled_font_t
Pcairo_bool_t* = ref cairo_bool_t
cairo_bool_t* = int32
Pcairo_matrix_t* = ref cairo_matrix_t
Pcairo_user_data_key_t* = ref cairo_user_data_key_t
Pcairo_glyph_t* = ref cairo_glyph_t
Pcairo_text_extents_t* = ref cairo_text_extents_t
Pcairo_font_extents_t* = ref cairo_font_extents_t
Pcairo_path_data_type_t* = ref cairo_path_data_type_t
Pcairo_path_data_t* = ref cairo_path_data_t
Pcairo_path_t* = ref cairo_path_t
Pcairo_rectangle_t* = ref cairo_rectangle_t
Pcairo_rectangle_list_t* = ref cairo_rectangle_list_t
cairo_destroy_func_t* = proc (data: Pointer){.cdecl.}
cairo_write_func_t* = proc (closure: Pointer, data: PByte, len: int32): cairo_status_t{.
PCairoSurface* = ptr TCairoSurface
PPCairoSurface* = ptr PCairoSurface
PCairo* = ptr TCairo
PCairoPattern* = ptr TCairoPattern
PCairoFontOptions* = ptr TCairoFontOptions
PCairoFontFace* = ptr TCairoFontFace
PCairoScaledFont* = ptr TCairoScaledFont
PCairoBool* = ptr TCairoBool
TCairoBool* = int32
PCairoMatrix* = ptr TCairoMatrix
PCairoUserDataKey* = ptr TCairoUserDataKey
PCairoGlyph* = ptr TCairoGlyph
PCairoTextExtents* = ptr TCairoTextExtents
PCairoFontExtents* = ptr TCairoFontExtents
PCairoPathDataType* = ptr TCairoPathDataType
PCairoPathData* = ptr TCairoPathData
PCairoPath* = ptr TCairoPath
PCairoRectangle* = ptr TCairoRectangle
PCairoRectangleList* = ptr TCairoRectangleList
TCairoDestroyFunc* = proc (data: Pointer){.cdecl.}
TCairoWriteFunc* = proc (closure: Pointer, data: PByte, len: int32): TCairoStatus{.
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.}
cairo_t* {.final.} = object #OPAQUE
cairo_surface_t* {.final.} = object #OPAQUE
cairo_pattern_t* {.final.} = object #OPAQUE
cairo_scaled_font_t* {.final.} = object #OPAQUE
cairo_font_face_t* {.final.} = object #OPAQUE
cairo_font_options_t* {.final.} = object #OPAQUE
cairo_matrix_t* {.final.} = object
TCairo* {.final.} = object #OPAQUE
TCairoSurface* {.final.} = object #OPAQUE
TCairoPattern* {.final.} = object #OPAQUE
TCairoScaledFont* {.final.} = object #OPAQUE
TCairoFontFace* {.final.} = object #OPAQUE
TCairoFontOptions* {.final.} = object #OPAQUE
TCairoMatrix* {.final.} = object
xx: float64
yx: float64
xy: float64
@ -163,15 +163,15 @@ type
x0: float64
y0: float64
cairo_user_data_key_t* {.final.} = object
TCairoUserDataKey* {.final.} = object
unused: int32
cairo_glyph_t* {.final.} = object
TCairoGlyph* {.final.} = object
index: int32
x: float64
y: float64
cairo_text_extents_t* {.final.} = object
TCairoTextExtents* {.final.} = object
x_bearing: float64
y_bearing: float64
width: float64
@ -179,30 +179,30 @@ type
x_advance: float64
y_advance: float64
cairo_font_extents_t* {.final.} = object
TCairoFontExtents* {.final.} = object
ascent: float64
descent: float64
height: float64
max_x_advance: float64
max_y_advance: float64
cairo_path_data_t* {.final.} = object #* _type : cairo_path_data_type_t;
# length : LongInt;
# end
TCairoPathData* {.final.} = object #* _type : TCairoPathDataType;
# length : LongInt;
# end
x: float64
y: float64
cairo_path_t* {.final.} = object
status: cairo_status_t
data: Pcairo_path_data_t
TCairoPath* {.final.} = object
status: TCairoStatus
data: PCairoPathData
num_data: int32
cairo_rectangle_t* {.final.} = object
TCairoRectangle* {.final.} = object
x, y, width, height: float64
cairo_rectangle_list_t* {.final.} = object
status: cairo_status_t
rectangles: Pcairo_rectangle_t
TCairoRectangleList* {.final.} = object
status: TCairoStatus
rectangles: PCairoRectangle
num_rectangles: int32
@ -211,480 +211,480 @@ proc cairo_version_string*(): cstring{.cdecl, importc, dynlib: LIB_CAIRO.}
#Helper function to retrieve decoded version
proc cairo_version*(major, minor, micro: var int32)
#* Functions for manipulating state objects
proc cairo_create*(target: Pcairo_surface_t): Pcairo_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_reference*(cr: Pcairo_t): Pcairo_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_destroy*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_reference_count*(cr: Pcairo_t): int32{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_user_data*(cr: Pcairo_t, key: Pcairo_user_data_key_t): pointer{.
proc cairo_create*(target: PCairoSurface): PCairo{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_reference*(cr: PCairo): PCairo{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_destroy*(cr: PCairo){.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, key: PCairoUserDataKey): pointer{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_user_data*(cr: PCairo_t, key: Pcairo_user_data_key_t,
user_data: Pointer, destroy: cairo_destroy_func_t): cairo_status_t{.
proc cairo_set_user_data*(cr: PCairo, key: PCairoUserDataKey,
user_data: Pointer, destroy: TCairoDestroyFunc): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_save*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_restore*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_push_group*(cr: PCairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_push_group_with_content*(cr: PCairo_t, content: cairo_content_t){.
proc cairo_save*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_restore*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_push_group*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_push_group_with_content*(cr: PCairo, content: TCairoContent){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pop_group*(cr: PCairo_t): Pcairo_pattern_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pop_group_to_source*(cr: PCairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pop_group*(cr: PCairo): PCairoPattern{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pop_group_to_source*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
#* 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.}
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.}
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.}
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.}
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.}
proc cairo_set_tolerance*(cr: Pcairo_t, tolerance: float64){.cdecl, importc,
proc cairo_set_tolerance*(cr: PCairo, tolerance: float64){.cdecl, importc,
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.}
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.}
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.}
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.}
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.}
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.}
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.}
proc cairo_translate*(cr: Pcairo_t, tx, ty: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scale*(cr: Pcairo_t, sx, sy: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rotate*(cr: Pcairo_t, angle: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_transform*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc,
proc cairo_translate*(cr: PCairo, tx, ty: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scale*(cr: PCairo, sx, sy: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rotate*(cr: PCairo, angle: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_transform*(cr: PCairo, matrix: PCairoMatrix){.cdecl, importc,
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.}
proc cairo_identity_matrix*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_user_to_device*(cr: Pcairo_t, x, y: var float64){.cdecl, importc,
proc cairo_identity_matrix*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_user_to_device*(cr: PCairo, x, y: var float64){.cdecl, importc,
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.}
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.}
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.}
#* Path creation functions
proc cairo_new_path*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_move_to*(cr: Pcairo_t, x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_new_sub_path*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_line_to*(cr: Pcairo_t, x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_curve_to*(cr: Pcairo_t, x1, y1, x2, y2, x3, y3: float64){.cdecl, importc,
proc cairo_new_path*(cr: PCairo){.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){.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, x1, y1, x2, y2, x3, y3: float64){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_arc*(cr: Pcairo_t, xc, yc, radius, angle1, angle2: float64){.cdecl, importc,
proc cairo_arc*(cr: PCairo, xc, yc, radius, angle1, angle2: float64){.cdecl, importc,
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.}
proc cairo_rel_move_to*(cr: Pcairo_t, dx, dy: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rel_line_to*(cr: Pcairo_t, dx, dy: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rel_curve_to*(cr: Pcairo_t, dx1, dy1, dx2, dy2, dx3, dy3: float64){.
proc cairo_rel_move_to*(cr: PCairo, 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, dx1, dy1, dx2, dy2, dx3, dy3: float64){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_rectangle*(cr: Pcairo_t, x, y, width, height: float64){.cdecl, importc,
proc cairo_rectangle*(cr: PCairo, x, y, width, height: float64){.cdecl, importc,
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
proc cairo_paint*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_paint_with_alpha*(cr: Pcairo_t, alpha: float64){.cdecl, importc,
proc cairo_paint*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_paint_with_alpha*(cr: PCairo, alpha: float64){.cdecl, importc,
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.}
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,
dynlib: LIB_CAIRO.}
proc cairo_stroke*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_stroke_preserve*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_fill*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_fill_preserve*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_copy_page*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_show_page*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_stroke*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_stroke_preserve*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_fill*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_fill_preserve*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_copy_page*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_show_page*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
#* 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.}
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.}
#* 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.}
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.}
#* Clipping
proc cairo_reset_clip*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_clip*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_clip_preserve*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_clip_extents*(cr: Pcairo_t, x1, y1, x2, y2: var float64){.cdecl, importc,
proc cairo_reset_clip*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_clip*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_clip_preserve*(cr: PCairo){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_clip_extents*(cr: PCairo, x1, y1, x2, y2: var float64){.cdecl, importc,
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.}
proc cairo_rectangle_list_destroy*(rectangle_list: Pcairo_rectangle_list_t){.
proc cairo_rectangle_list_destroy*(rectangle_list: PCairoRectangleList){.
cdecl, importc, dynlib: LIB_CAIRO.}
#* 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.}
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.}
proc cairo_font_options_destroy*(options: Pcairo_font_options_t){.cdecl, importc,
proc cairo_font_options_destroy*(options: PCairoFontOptions){.cdecl, importc,
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.}
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.}
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.}
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.}
proc cairo_font_options_set_antialias*(options: Pcairo_font_options_t,
antialias: cairo_antialias_t){.cdecl, importc,
proc cairo_font_options_set_antialias*(options: PCairoFontOptions,
antialias: TCairoAntialias){.cdecl, importc,
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.}
proc cairo_font_options_set_subpixel_order*(options: Pcairo_font_options_t,
subpixel_order: cairo_subpixel_order_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_get_subpixel_order*(options: Pcairo_font_options_t): cairo_subpixel_order_t{.
proc cairo_font_options_set_subpixel_order*(options: PCairoFontOptions,
subpixel_order: TCairoSubpixelOrder){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_get_subpixel_order*(options: PCairoFontOptions): TCairoSubpixelOrder{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_set_hint_style*(options: Pcairo_font_options_t,
hint_style: cairo_hint_style_t){.cdecl, importc,
proc cairo_font_options_set_hint_style*(options: PCairoFontOptions,
hint_style: TCairoHintStyle){.cdecl, importc,
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.}
proc cairo_font_options_set_hint_metrics*(options: Pcairo_font_options_t,
hint_metrics: cairo_hint_metrics_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_get_hint_metrics*(options: Pcairo_font_options_t): cairo_hint_metrics_t{.
proc cairo_font_options_set_hint_metrics*(options: PCairoFontOptions,
hint_metrics: TCairoHintMetrics){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_options_get_hint_metrics*(options: PCairoFontOptions): TCairoHintMetrics{.
cdecl, importc, dynlib: LIB_CAIRO.}
#* This interface is for dealing with text as text, not caring about the
# font object inside the the cairo_t.
proc cairo_select_font_face*(cr: Pcairo_t, family: cstring,
slant: cairo_font_slant_t,
weight: cairo_font_weight_t){.cdecl, importc,
# font object inside the the TCairo.
proc cairo_select_font_face*(cr: PCairo, family: cstring,
slant: TCairoFontSlant,
weight: TCairoFontWeight){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_set_font_size*(cr: Pcairo_t, size: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_font_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc,
proc cairo_set_font_size*(cr: PCairo, size: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_set_font_matrix*(cr: PCairo, matrix: PCairoMatrix){.cdecl, importc,
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.}
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.}
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.}
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.}
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.}
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.}
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.}
proc cairo_show_text*(cr: Pcairo_t, utf8: cstring){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_show_glyphs*(cr: Pcairo_t, glyphs: Pcairo_glyph_t, num_glyphs: int32){.
proc cairo_show_text*(cr: PCairo, utf8: cstring){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_show_glyphs*(cr: PCairo, glyphs: PCairoGlyph, num_glyphs: int32){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_text_path*(cr: Pcairo_t, utf8: cstring){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_glyph_path*(cr: Pcairo_t, glyphs: Pcairo_glyph_t, num_glyphs: int32){.
proc cairo_text_path*(cr: PCairo, utf8: cstring){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_glyph_path*(cr: PCairo, glyphs: PCairoGlyph, num_glyphs: int32){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_text_extents*(cr: Pcairo_t, utf8: cstring,
extents: Pcairo_text_extents_t){.cdecl, importc,
proc cairo_text_extents*(cr: PCairo, utf8: cstring,
extents: PCairoTextExtents){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_glyph_extents*(cr: Pcairo_t, glyphs: Pcairo_glyph_t,
num_glyphs: int32, extents: Pcairo_text_extents_t){.
proc cairo_glyph_extents*(cr: PCairo, glyphs: PCairoGlyph,
num_glyphs: int32, extents: PCairoTextExtents){.
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.}
#* 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.}
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.}
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.}
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.}
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.}
proc cairo_font_face_get_user_data*(font_face: Pcairo_font_face_t,
key: Pcairo_user_data_key_t): pointer{.
proc cairo_font_face_get_user_data*(font_face: PCairoFontFace,
key: PCairoUserDataKey): pointer{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_font_face_set_user_data*(font_face: Pcairo_font_face_t,
key: Pcairo_user_data_key_t,
proc cairo_font_face_set_user_data*(font_face: PCairoFontFace,
key: PCairoUserDataKey,
user_data: pointer,
destroy: cairo_destroy_func_t): cairo_status_t{.
destroy: TCairoDestroyFunc): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.}
#* Portable interface to general font features
proc cairo_scaled_font_create*(font_face: Pcairo_font_face_t,
font_matrix: Pcairo_matrix_t,
ctm: Pcairo_matrix_t,
options: Pcairo_font_options_t): Pcairo_scaled_font_t{.
proc cairo_scaled_font_create*(font_face: PCairoFontFace,
font_matrix: PCairoMatrix,
ctm: PCairoMatrix,
options: PCairoFontOptions): PCairoScaledFont{.
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.}
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.}
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.}
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.}
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.}
proc cairo_scaled_font_get_user_data*(scaled_font: Pcairo_scaled_font_t,
key: Pcairo_user_data_key_t): Pointer{.
proc cairo_scaled_font_get_user_data*(scaled_font: PCairoScaledFont,
key: PCairoUserDataKey): Pointer{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_set_user_data*(scaled_font: Pcairo_scaled_font_t,
key: Pcairo_user_data_key_t,
proc cairo_scaled_font_set_user_data*(scaled_font: PCairoScaledFont,
key: PCairoUserDataKey,
user_data: Pointer,
destroy: cairo_destroy_func_t): cairo_status_t{.
destroy: TCairoDestroyFunc): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_extents*(scaled_font: Pcairo_scaled_font_t,
extents: Pcairo_font_extents_t){.cdecl, importc,
proc cairo_scaled_font_extents*(scaled_font: PCairoScaledFont,
extents: PCairoFontExtents){.cdecl, importc,
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,
extents: Pcairo_text_extents_t){.cdecl, importc,
extents: PCairoTextExtents){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_scaled_font_glyph_extents*(scaled_font: Pcairo_scaled_font_t,
glyphs: Pcairo_glyph_t, num_glyphs: int32,
extents: Pcairo_text_extents_t){.cdecl, importc,
proc cairo_scaled_font_glyph_extents*(scaled_font: PCairoScaledFont,
glyphs: PCairoGlyph, num_glyphs: int32,
extents: PCairoTextExtents){.cdecl, importc,
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.}
proc cairo_scaled_font_get_font_matrix*(scaled_font: Pcairo_scaled_font_t,
font_matrix: Pcairo_matrix_t){.cdecl, importc,
proc cairo_scaled_font_get_font_matrix*(scaled_font: PCairoScaledFont,
font_matrix: PCairoMatrix){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_ctm*(scaled_font: Pcairo_scaled_font_t,
ctm: Pcairo_matrix_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_font_options*(scaled_font: Pcairo_scaled_font_t,
options: Pcairo_font_options_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_ctm*(scaled_font: PCairoScaledFont,
ctm: PCairoMatrix){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_scaled_font_get_font_options*(scaled_font: PCairoScaledFont,
options: PCairoFontOptions){.cdecl, importc, dynlib: LIB_CAIRO.}
#* 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.}
proc cairo_get_source*(cr: Pcairo_t): Pcairo_pattern_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_tolerance*(cr: Pcairo_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_antialias*(cr: Pcairo_t): cairo_antialias_t{.cdecl, importc,
proc cairo_get_source*(cr: PCairo): PCairoPattern{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_tolerance*(cr: PCairo): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_antialias*(cr: PCairo): TCairoAntialias{.cdecl, importc,
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.}
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.}
proc cairo_get_line_width*(cr: Pcairo_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_line_cap*(cr: Pcairo_t): cairo_line_cap_t{.cdecl, importc,
proc cairo_get_line_width*(cr: PCairo): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_line_cap*(cr: PCairo): TCairoLineCap{.cdecl, importc,
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.}
proc cairo_get_miter_limit*(cr: Pcairo_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_dash_count*(cr: Pcairo_t): int32{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_dash*(cr: Pcairo_t, dashes, offset: var float64){.cdecl, importc,
proc cairo_get_miter_limit*(cr: PCairo): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_dash_count*(cr: PCairo): int32{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_dash*(cr: PCairo, dashes, offset: var float64){.cdecl, importc,
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.}
proc cairo_get_target*(cr: Pcairo_t): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_group_target*(cr: Pcairo_t): Pcairo_surface_t{.cdecl, importc,
proc cairo_get_target*(cr: PCairo): PCairoSurface{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_get_group_target*(cr: PCairo): PCairoSurface{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_copy_path*(cr: Pcairo_t): Pcairo_path_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_copy_path_flat*(cr: Pcairo_t): Pcairo_path_t{.cdecl, importc,
proc cairo_copy_path*(cr: PCairo): PCairoPath{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_copy_path_flat*(cr: PCairo): PCairoPath{.cdecl, importc,
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.}
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
proc cairo_status*(cr: Pcairo_t): cairo_status_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_status_to_string*(status: cairo_status_t): cstring{.cdecl, importc,
proc cairo_status*(cr: PCairo): TCairoStatus{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_status_to_string*(status: TCairoStatus): cstring{.cdecl, importc,
dynlib: LIB_CAIRO.}
#* Surface manipulation
proc cairo_surface_create_similar*(other: Pcairo_surface_t,
content: cairo_content_t,
width, height: int32): Pcairo_surface_t{.
proc cairo_surface_create_similar*(other: PCairoSurface,
content: TCairoContent,
width, height: int32): PCairoSurface{.
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.}
proc cairo_surface_finish*(surface: Pcairo_surface_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_destroy*(surface: Pcairo_surface_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_get_reference_count*(surface: Pcairo_surface_t): int32{.
proc cairo_surface_finish*(surface: PCairoSurface){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_destroy*(surface: PCairoSurface){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_get_reference_count*(surface: PCairoSurface): int32{.
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.}
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.}
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.}
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.}
proc cairo_surface_write_to_png_stream*(surface: Pcairo_surface_t,
write_func: cairo_write_func_t,
closure: pointer): cairo_status_t{.
proc cairo_surface_write_to_png_stream*(surface: PCairoSurface,
write_func: TCairoWriteFunc,
closure: pointer): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_get_user_data*(surface: Pcairo_surface_t,
key: Pcairo_user_data_key_t): pointer{.cdecl, importc,
proc cairo_surface_get_user_data*(surface: PCairoSurface,
key: PCairoUserDataKey): pointer{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_surface_set_user_data*(surface: Pcairo_surface_t,
key: Pcairo_user_data_key_t,
proc cairo_surface_set_user_data*(surface: PCairoSurface,
key: PCairoUserDataKey,
user_data: pointer,
destroy: cairo_destroy_func_t): cairo_status_t{.
destroy: TCairoDestroyFunc): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_get_font_options*(surface: Pcairo_surface_t,
options: Pcairo_font_options_t){.cdecl, importc,
proc cairo_surface_get_font_options*(surface: PCairoSurface,
options: PCairoFontOptions){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_surface_flush*(surface: Pcairo_surface_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_mark_dirty*(surface: Pcairo_surface_t){.cdecl, importc,
proc cairo_surface_flush*(surface: PCairoSurface){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_surface_mark_dirty*(surface: PCairoSurface){.cdecl, importc,
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.}
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,
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,
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.}
#* 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.}
proc cairo_image_surface_create_for_data*(data: Pbyte, format: cairo_format_t,
width, height, stride: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_image_surface_get_data*(surface: Pcairo_surface_t): cstring{.cdecl, importc,
proc cairo_image_surface_create_for_data*(data: Pbyte, format: TCairoFormat,
width, height, stride: int32): PCairoSurface{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_image_surface_get_data*(surface: PCairoSurface): cstring{.cdecl, importc,
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.}
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.}
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.}
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.}
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.}
proc cairo_image_surface_create_from_png_stream*(read_func: cairo_read_func_t,
closure: pointer): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_image_surface_create_from_png_stream*(read_func: TCairoReadFunc,
closure: pointer): PCairoSurface{.cdecl, importc, dynlib: LIB_CAIRO.}
#* 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.}
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.}
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.}
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.}
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.}
proc cairo_pattern_reference*(pattern: Pcairo_pattern_t): Pcairo_pattern_t{.
proc cairo_pattern_reference*(pattern: PCairoPattern): PCairoPattern{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_destroy*(pattern: Pcairo_pattern_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_reference_count*(pattern: Pcairo_pattern_t): int32{.
proc cairo_pattern_destroy*(pattern: PCairoPattern){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_reference_count*(pattern: PCairoPattern): int32{.
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.}
proc cairo_pattern_get_user_data*(pattern: Pcairo_pattern_t,
key: Pcairo_user_data_key_t): Pointer{.cdecl, importc,
proc cairo_pattern_get_user_data*(pattern: PCairoPattern,
key: PCairoUserDataKey): Pointer{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_pattern_set_user_data*(pattern: Pcairo_pattern_t,
key: Pcairo_user_data_key_t,
proc cairo_pattern_set_user_data*(pattern: PCairoPattern,
key: PCairoUserDataKey,
user_data: Pointer,
destroy: cairo_destroy_func_t): cairo_status_t{.
destroy: TCairoDestroyFunc): TCairoStatus{.
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.}
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){.
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.}
proc cairo_pattern_set_matrix*(pattern: Pcairo_pattern_t,
matrix: Pcairo_matrix_t){.cdecl, importc,
proc cairo_pattern_set_matrix*(pattern: PCairoPattern,
matrix: PCairoMatrix){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_pattern_get_matrix*(pattern: Pcairo_pattern_t,
matrix: Pcairo_matrix_t){.cdecl, importc,
proc cairo_pattern_get_matrix*(pattern: PCairoPattern,
matrix: PCairoMatrix){.cdecl, importc,
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.}
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.}
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.}
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.}
proc cairo_pattern_get_rgba*(pattern: Pcairo_pattern_t,
red, green, blue, alpha: var float64): cairo_status_t{.
proc cairo_pattern_get_rgba*(pattern: PCairoPattern,
red, green, blue, alpha: var float64): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_surface*(pattern: Pcairo_pattern_t,
surface: PPcairo_surface_t): cairo_status_t{.
proc cairo_pattern_get_surface*(pattern: PCairoPattern,
surface: PPCairoSurface): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_color_stop_rgba*(pattern: Pcairo_pattern_t, index: int32,
offset, red, green, blue, alpha: var float64): cairo_status_t{.cdecl, importc,
proc cairo_pattern_get_color_stop_rgba*(pattern: PCairoPattern, index: int32,
offset, red, green, blue, alpha: var float64): TCairoStatus{.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_pattern_get_color_stop_count*(pattern: Pcairo_pattern_t,
count: var int32): cairo_status_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_linear_points*(pattern: Pcairo_pattern_t,
x0, y0, x1, y1: var float64): cairo_status_t{.
proc cairo_pattern_get_color_stop_count*(pattern: PCairoPattern,
count: var int32): TCairoStatus{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_linear_points*(pattern: PCairoPattern,
x0, y0, x1, y1: var float64): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_pattern_get_radial_circles*(pattern: Pcairo_pattern_t,
x0, y0, r0, x1, y1, r1: var float64): cairo_status_t{.
proc cairo_pattern_get_radial_circles*(pattern: PCairoPattern,
x0, y0, r0, x1, y1, r1: var float64): TCairoStatus{.
cdecl, importc, dynlib: LIB_CAIRO.}
#* 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.}
proc cairo_matrix_init_identity*(matrix: Pcairo_matrix_t){.cdecl, importc,
proc cairo_matrix_init_identity*(matrix: PCairoMatrix){.cdecl, importc,
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.}
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.}
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.}
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.}
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.}
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.}
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.}
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.}
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.}
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.}
#* PDF functions
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.}
proc cairo_pdf_surface_create_for_stream*(write_func: cairo_write_func_t,
closure: Pointer, width_in_points, height_in_points: float64): Pcairo_surface_t{.
proc cairo_pdf_surface_create_for_stream*(write_func: TCairoWriteFunc,
closure: Pointer, width_in_points, height_in_points: float64): PCairoSurface{.
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){.
cdecl, importc, dynlib: LIB_CAIRO.}
#* PS functions
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.}
proc cairo_ps_surface_create_for_stream*(write_func: cairo_write_func_t,
closure: Pointer, width_in_points, height_in_points: float64): Pcairo_surface_t{.
proc cairo_ps_surface_create_for_stream*(write_func: TCairoWriteFunc,
closure: Pointer, width_in_points, height_in_points: float64): PCairoSurface{.
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){.
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.}
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.}
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.}
#* SVG functions
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.}
proc cairo_svg_surface_create_for_stream*(write_func: cairo_write_func_t,
closure: Pointer, width_in_points, height_in_points: float64): Pcairo_surface_t{.
proc cairo_svg_surface_create_for_stream*(write_func: TCairoWriteFunc,
closure: Pointer, width_in_points, height_in_points: float64): PCairoSurface{.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_svg_surface_restrict_to_version*(surface: Pcairo_surface_t,
version: cairo_svg_version_t){.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_svg_surface_restrict_to_version*(surface: PCairoSurface,
version: TCairoSvgVersion){.cdecl, importc, dynlib: LIB_CAIRO.}
#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);
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.}
#* Functions to be used while debugging (not intended for use in production code)
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) =
var version: int32
version = cairo_version()
major = version div 10000
minor = (version mod (major * 10000)) div 100
micro = (version mod ((major * 10000) + (minor * 100)))
major = version div 10000'i32
minor = (version mod (major * 10000'i32)) div 100'i32
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
#
import Cairo, freetypeh
import cairo, freetypeh
#todo: properly define FcPattern:
#It will require translate FontConfig header
@ -20,17 +20,17 @@ import Cairo, freetypeh
type
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.}
proc cairo_ft_font_options_substitute*(options: Pcairo_font_options_t,
proc cairo_ft_font_options_substitute*(options: PCairoFontOptions,
pattern: PFcPattern){.cdecl, importc,
dynlib: LIB_CAIRO.}
proc cairo_ft_font_face_create_for_ft_face*(face: TFT_Face,
load_flags: int32): Pcairo_font_face_t {.cdecl, importc, dynlib: LIB_CAIRO.}
load_flags: int32): PCairoFontFace {.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ft_scaled_font_lock_face*(
scaled_font: Pcairo_scaled_font_t): TFT_Face{.cdecl, importc, dynlib: LIB_CAIRO.}
scaled_font: PCairoScaledFont): TFT_Face{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_ft_scaled_font_unlock_face*(
scaled_font: Pcairo_scaled_font_t){.cdecl, importc, dynlib: LIB_CAIRO.}
scaled_font: PCairoScaledFont){.cdecl, importc, dynlib: LIB_CAIRO.}

View file

@ -7,30 +7,30 @@
import
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.}
proc cairo_win32_surface_create_with_ddb*(hdc: HDC, format: cairo_format_t,
width, height: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_surface_create_with_dib*(format: cairo_format_t,
width, height: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_surface_get_dc*(surface: pcairo_surface_t): HDC{.cdecl, importc,
proc cairo_win32_surface_create_with_ddb*(hdc: HDC, format: TCairoFormat,
width, height: int32): PCairoSurface{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_surface_create_with_dib*(format: TCairoFormat,
width, height: int32): PCairoSurface{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_surface_get_dc*(surface: PCairoSurface): HDC{.cdecl, importc,
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.}
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.}
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.}
proc cairo_win32_scaled_font_select_font*(scaled_font: pcairo_scaled_font_t,
hdc: HDC): cairo_status_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_done_font*(scaled_font: pcairo_scaled_font_t){.
proc cairo_win32_scaled_font_select_font*(scaled_font: PCairoScaledFont,
hdc: HDC): TCairoStatus{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_done_font*(scaled_font: PCairoScaledFont){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_get_metrics_factor*(
scaled_font: pcairo_scaled_font_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
scaled_font: PCairoScaledFont): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_get_logical_to_device*(
scaled_font: pcairo_scaled_font_t, logical_to_device: pcairo_matrix_t){.
scaled_font: PCairoScaledFont, logical_to_device: PCairoMatrix){.
cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_win32_scaled_font_get_device_to_logical*(
scaled_font: pcairo_scaled_font_t, device_to_logical: pcairo_matrix_t){.
scaled_font: PCairoScaledFont, device_to_logical: PCairoMatrix){.
cdecl, importc, dynlib: LIB_CAIRO.}
# implementation

View file

@ -9,32 +9,32 @@ import
Cairo, x, xlib, xrender
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.}
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.}
proc cairo_xlib_surface_create_with_xrender_format*(dpy: PDisplay,
drawable: TDrawable, screen: PScreen, format: PXRenderPictFormat,
width, height: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_depth*(surface: Pcairo_surface_t): int32{.cdecl, importc,
width, height: int32): PCairoSurface{.cdecl, importc, dynlib: LIB_CAIRO.}
proc cairo_xlib_surface_get_depth*(surface: PCairoSurface): int32{.cdecl, importc,
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.}
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.}
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.}
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.}
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.}
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.}
proc cairo_xlib_surface_set_size*(surface: Pcairo_surface_t,
proc cairo_xlib_surface_set_size*(surface: PCairoSurface,
width, height: int32){.cdecl, importc,
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){.
cdecl, importc, dynlib: LIB_CAIRO.}
# implementation

View file

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

View file

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

View file

@ -2,7 +2,6 @@ import
glib2, gdk2pixbuf, pango
when defined(win32):
{.define: GDK_WINDOWING_WIN32.}
const
gdklib = "libgdk-win32-2.0-0.dll"
GDK_HAVE_WCHAR_H = 1
@ -3183,14 +3182,14 @@ proc GDK_IS_WINDOW_CLASS*(klass: Pointer): bool
proc GDK_WINDOW_GET_CLASS*(obj: Pointer): PGdkWindowObjectClass
proc GDK_WINDOW_OBJECT*(anObject: Pointer): PGdkWindowObject
const
bm_TGdkWindowObject_guffaw_gravity* = 0x00000001
bp_TGdkWindowObject_guffaw_gravity* = 0
bm_TGdkWindowObject_input_only* = 0x00000002
bp_TGdkWindowObject_input_only* = 1
bm_TGdkWindowObject_modal_hint* = 0x00000004
bp_TGdkWindowObject_modal_hint* = 2
bm_TGdkWindowObject_destroyed* = 0x00000018
bp_TGdkWindowObject_destroyed* = 3
bm_TGdkWindowObject_guffaw_gravity* = 0x00000001'i16
bp_TGdkWindowObject_guffaw_gravity* = 0'i16
bm_TGdkWindowObject_input_only* = 0x00000002'i16
bp_TGdkWindowObject_input_only* = 1'i16
bm_TGdkWindowObject_modal_hint* = 0x00000004'i16
bp_TGdkWindowObject_modal_hint* = 2'i16
bm_TGdkWindowObject_destroyed* = 0x00000018'i16
bp_TGdkWindowObject_destroyed* = 3'i16
proc GdkWindowObject_guffaw_gravity*(a: var TGdkWindowObject): guint
proc GdkWindowObject_set_guffaw_gravity*(a: var TGdkWindowObject,
@ -3417,7 +3416,7 @@ proc gdk_init*(argc: Pgint, v: var PPgchar){.cdecl, dynlib: gdklib,
proc gdk_init_check*(argc: Pgint, v: var PPgchar): gboolean{.cdecl,
dynlib: gdklib, importc: "gdk_init_check".}
when not defined(GDK_DISABLE_DEPRECATED):
proc gdk_exit(error_code: gint){.cdecl, dynlib: gdklib, importc: "gdk_exit".}
proc gdk_exit*(error_code: gint){.cdecl, dynlib: gdklib, importc: "gdk_exit".}
proc gdk_set_locale*(): cstring{.cdecl, dynlib: gdklib, importc: "gdk_set_locale".}
proc gdk_get_program_class*(): cstring{.cdecl, dynlib: gdklib,
importc: "gdk_get_program_class".}
@ -3428,23 +3427,23 @@ proc gdk_error_trap_push*(){.cdecl, dynlib: gdklib,
proc gdk_error_trap_pop*(): gint{.cdecl, dynlib: gdklib,
importc: "gdk_error_trap_pop".}
when not defined(GDK_DISABLE_DEPRECATED):
proc gdk_set_use_xshm(use_xshm: gboolean){.cdecl, dynlib: gdklib,
proc gdk_set_use_xshm*(use_xshm: gboolean){.cdecl, dynlib: gdklib,
importc: "gdk_set_use_xshm".}
proc gdk_get_use_xshm(): gboolean{.cdecl, dynlib: gdklib,
proc gdk_get_use_xshm*(): gboolean{.cdecl, dynlib: gdklib,
importc: "gdk_get_use_xshm".}
proc gdk_get_display*(): cstring{.cdecl, dynlib: gdklib,
importc: "gdk_get_display".}
proc gdk_get_display_arg_name*(): cstring{.cdecl, dynlib: gdklib,
importc: "gdk_get_display_arg_name".}
when not defined(GDK_DISABLE_DEPRECATED):
proc gdk_input_add_full(source: gint, condition: TGdkInputCondition,
proc gdk_input_add_full*(source: gint, condition: TGdkInputCondition,
`function`: TGdkInputFunction, data: gpointer,
destroy: TGdkDestroyNotify): gint{.cdecl,
dynlib: gdklib, importc: "gdk_input_add_full".}
proc gdk_input_add(source: gint, condition: TGdkInputCondition,
proc gdk_input_add*(source: gint, condition: TGdkInputCondition,
`function`: TGdkInputFunction, data: gpointer): gint{.
cdecl, dynlib: gdklib, importc: "gdk_input_add".}
proc gdk_input_remove(tag: gint){.cdecl, dynlib: gdklib,
proc gdk_input_remove*(tag: gint){.cdecl, dynlib: gdklib,
importc: "gdk_input_remove".}
proc gdk_pointer_grab*(window: PGdkWindow, owner_events: gboolean,
event_mask: TGdkEventMask, confine_to: PGdkWindow,
@ -3454,24 +3453,24 @@ proc gdk_keyboard_grab*(window: PGdkWindow, owner_events: gboolean,
time: guint32): TGdkGrabStatus{.cdecl, dynlib: gdklib,
importc: "gdk_keyboard_grab".}
when not defined(GDK_MULTIHEAD_SAFE):
proc gdk_pointer_ungrab(time: guint32){.cdecl, dynlib: gdklib,
proc gdk_pointer_ungrab*(time: guint32){.cdecl, dynlib: gdklib,
importc: "gdk_pointer_ungrab".}
proc gdk_keyboard_ungrab(time: guint32){.cdecl, dynlib: gdklib,
proc gdk_keyboard_ungrab*(time: guint32){.cdecl, dynlib: gdklib,
importc: "gdk_keyboard_ungrab".}
proc gdk_pointer_is_grabbed(): gboolean{.cdecl, dynlib: gdklib,
proc gdk_pointer_is_grabbed*(): gboolean{.cdecl, dynlib: gdklib,
importc: "gdk_pointer_is_grabbed".}
proc gdk_screen_width(): gint{.cdecl, dynlib: gdklib,
proc gdk_screen_width*(): gint{.cdecl, dynlib: gdklib,
importc: "gdk_screen_width".}
proc gdk_screen_height(): gint{.cdecl, dynlib: gdklib,
proc gdk_screen_height*(): gint{.cdecl, dynlib: gdklib,
importc: "gdk_screen_height".}
proc gdk_screen_width_mm(): gint{.cdecl, dynlib: gdklib,
proc gdk_screen_width_mm*(): gint{.cdecl, dynlib: gdklib,
importc: "gdk_screen_width_mm".}
proc gdk_screen_height_mm(): gint{.cdecl, dynlib: gdklib,
proc gdk_screen_height_mm*(): gint{.cdecl, dynlib: gdklib,
importc: "gdk_screen_height_mm".}
proc gdk_beep(){.cdecl, dynlib: gdklib, importc: "gdk_beep".}
proc gdk_beep*(){.cdecl, dynlib: gdklib, importc: "gdk_beep".}
proc gdk_flush*(){.cdecl, dynlib: gdklib, importc: "gdk_flush".}
when not defined(GDK_MULTIHEAD_SAFE):
proc gdk_set_double_click_time(msec: guint){.cdecl, dynlib: gdklib,
proc gdk_set_double_click_time*(msec: guint){.cdecl, dynlib: gdklib,
importc: "gdk_set_double_click_time".}
proc gdk_rectangle_intersect*(src1: PGdkRectangle, src2: PGdkRectangle,
dest: PGdkRectangle): gboolean{.cdecl,
@ -3487,9 +3486,9 @@ proc gdk_wcstombs*(src: PGdkWChar): cstring{.cdecl, dynlib: gdklib,
proc gdk_mbstowcs*(dest: PGdkWChar, src: cstring, dest_max: gint): gint{.cdecl,
dynlib: gdklib, importc: "gdk_mbstowcs".}
when not defined(GDK_MULTIHEAD_SAFE):
proc gdk_event_send_client_message(event: PGdkEvent, xid: guint32): gboolean{.
proc gdk_event_send_client_message*(event: PGdkEvent, xid: guint32): gboolean{.
cdecl, dynlib: gdklib, importc: "gdk_event_send_client_message".}
proc gdk_event_send_clientmessage_toall(event: PGdkEvent){.cdecl,
proc gdk_event_send_clientmessage_toall*(event: PGdkEvent){.cdecl,
dynlib: gdklib, importc: "gdk_event_send_clientmessage_toall".}
proc gdk_event_send_client_message_for_display*(display: PGdkDisplay,
event: PGdkEvent, xid: guint32): gboolean{.cdecl, dynlib: gdklib,
@ -3550,27 +3549,27 @@ proc GDK_DRAG_CONTEXT_GET_CLASS*(obj: Pointer): PGdkDragContextClass =
GDK_TYPE_DRAG_CONTEXT()))
proc gdkregion_EXTENTCHECK*(r1, r2: PGdkRegionBox): bool =
result = (int(r1.x2) > r2.x1) and (int(r1.x1) < r2.x2) and
(int(r1.y2) > r2.y1) and (int(r1.y1) < r2.y2)
result = ((r1.x2) > r2.x1) and ((r1.x1) < r2.x2) and
((r1.y2) > r2.y1) and ((r1.y1) < r2.y2)
proc gdkregion_EXTENTS*(r: PGdkRegionBox, idRect: PGdkRegion) =
if (int(r.x1) < idRect.extents.x1):
if ((r.x1) < idRect.extents.x1):
idRect.extents.x1 = r.x1
if int(r.y1) < idRect.extents.y1:
if (r.y1) < idRect.extents.y1:
idRect.extents.y1 = r.y1
if int(r.x2) > idRect.extents.x2:
if (r.x2) > idRect.extents.x2:
idRect.extents.x2 = r.x2
proc gdkregion_MEMCHECK*(reg: PGdkRegion, ARect, firstrect: var PGdkRegionBox): bool =
nil
assert(false) # to implement
proc gdkregion_CHECK_PREVIOUS*(Reg: PGdkRegion, R: PGdkRegionBox,
Rx1, Ry1, Rx2, Ry2: gint): bool =
nil
assert(false) # to implement
proc gdkregion_ADDRECT*(reg: PGdkRegion, r: PGdkRegionBox,
rx1, ry1, rx2, ry2: gint) =
if ((int(rx1) < rx2) and (int(ry1) < ry2) and
if (((rx1) < rx2) and ((ry1) < ry2) and
gdkregion_CHECK_PREVIOUS(reg, r, rx1, ry1, rx2, ry2)):
r.x1 = rx1
r.y1 = ry1
@ -3579,7 +3578,7 @@ proc gdkregion_ADDRECT*(reg: PGdkRegion, r: PGdkRegionBox,
proc gdkregion_ADDRECTNOX*(reg: PGdkRegion, r: PGdkRegionBox,
rx1, ry1, rx2, ry2: gint) =
if ((int(rx1) < rx2) and (int(ry1) < ry2) and
if (((rx1) < rx2) and ((ry1) < ry2) and
gdkregion_CHECK_PREVIOUS(reg, r, rx1, ry1, rx2, ry2)):
r.x1 = rx1
r.y1 = ry1
@ -3588,14 +3587,14 @@ proc gdkregion_ADDRECTNOX*(reg: PGdkRegion, r: PGdkRegionBox,
inc(reg . numRects)
proc gdkregion_EMPTY_REGION*(pReg: PGdkRegion): bool =
result = pReg.numRects == 0
result = pReg.numRects == 0'i32
proc gdkregion_REGION_NOT_EMPTY*(pReg: PGdkRegion): bool =
result = pReg.numRects != 0
result = pReg.numRects != 0'i32
proc gdkregion_INBOX*(r: TGdkRegionBox, x, y: gint): bool =
result = (((int(r.x2) > x) and (int(r.x1) <= x)) and
(int(r.y2) > y)) and (int(r.y1) <= y)
result = ((((r.x2) > x) and ((r.x1) <= x)) and
((r.y2) > y)) and ((r.y1) <= y)
proc GDK_TYPE_DRAWABLE*(): GType =
result = gdk_drawable_get_type()
@ -3894,7 +3893,7 @@ proc GdkWindowObject_guffaw_gravity*(a: var TGdkWindowObject): guint =
proc GdkWindowObject_set_guffaw_gravity*(a: var TGdkWindowObject,
`guffaw_gravity`: guint) =
a.flag0 = a.flag0 or
((`guffaw_gravity` shl bp_TGdkWindowObject_guffaw_gravity) and
(int16(`guffaw_gravity` shl bp_TGdkWindowObject_guffaw_gravity) and
bm_TGdkWindowObject_guffaw_gravity)
proc GdkWindowObject_input_only*(a: var TGdkWindowObject): guint =
@ -3904,7 +3903,7 @@ proc GdkWindowObject_input_only*(a: var TGdkWindowObject): guint =
proc GdkWindowObject_set_input_only*(a: var TGdkWindowObject,
`input_only`: guint) =
a.flag0 = a.flag0 or
((`input_only` shl bp_TGdkWindowObject_input_only) and
(int16(`input_only` shl bp_TGdkWindowObject_input_only) and
bm_TGdkWindowObject_input_only)
proc GdkWindowObject_modal_hint*(a: var TGdkWindowObject): guint =
@ -3914,7 +3913,7 @@ proc GdkWindowObject_modal_hint*(a: var TGdkWindowObject): guint =
proc GdkWindowObject_set_modal_hint*(a: var TGdkWindowObject,
`modal_hint`: guint) =
a.flag0 = a.flag0 or
((`modal_hint` shl bp_TGdkWindowObject_modal_hint) and
(int16(`modal_hint` shl bp_TGdkWindowObject_modal_hint) and
bm_TGdkWindowObject_modal_hint)
proc GdkWindowObject_destroyed*(a: var TGdkWindowObject): guint =
@ -3923,7 +3922,7 @@ proc GdkWindowObject_destroyed*(a: var TGdkWindowObject): guint =
proc GdkWindowObject_set_destroyed*(a: var TGdkWindowObject, `destroyed`: guint) =
a.flag0 = a.flag0 or
((`destroyed` shl bp_TGdkWindowObject_destroyed) and
(int16(`destroyed` shl bp_TGdkWindowObject_destroyed) and
bm_TGdkWindowObject_destroyed)
proc GDK_ROOT_PARENT*(): PGdkWindow =

View file

@ -2,7 +2,6 @@ import
glib2
when defined(win32):
{.define: gdkpixbufwin.}
const
gdkpixbuflib = "libgdk_pixbuf-2.0-0.dll"
elif defined(darwin):
@ -18,8 +17,7 @@ elif defined(darwin):
else:
const
gdkpixbuflib = "libgdk_pixbuf-2.0.so"
{.define: HasGTK2_4.}
{.define: HasGTK2_6.}
type
PGdkPixbuf* = pointer
PGdkPixbufAnimation* = pointer
@ -55,9 +53,9 @@ proc gdk_pixbuf_error_quark*(): TGQuark{.cdecl, dynlib: gdkpixbuflib,
proc gdk_pixbuf_get_type*(): GType{.cdecl, dynlib: gdkpixbuflib,
importc: "gdk_pixbuf_get_type".}
when not defined(GDK_PIXBUF_DISABLE_DEPRECATED):
proc gdk_pixbuf_ref(pixbuf: PGdkPixbuf): PGdkPixbuf{.cdecl,
proc gdk_pixbuf_ref*(pixbuf: PGdkPixbuf): PGdkPixbuf{.cdecl,
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".}
proc gdk_pixbuf_get_colorspace*(pixbuf: PGdkPixbuf): TGdkColorspace{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_colorspace".}
@ -96,14 +94,12 @@ proc gdk_pixbuf_new_from_xpm_data*(data: PPchar): PGdkPixbuf{.cdecl,
proc gdk_pixbuf_new_from_inline*(data_length: gint, a: var guint8,
copy_pixels: gboolean, error: pointer): PGdkPixbuf{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_inline".}
when defined(HasGTK2_4):
proc gdk_pixbuf_new_from_file_at_size(filename: cstring, width, height: gint,
error: pointer): PGdkPixbuf{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_file_at_size".}
when defined(HasGTK2_6):
proc gdk_pixbuf_new_from_file_at_scale(filename: cstring, width, height: gint,
preserve_aspect_ratio: gboolean, error: pointer): PGdkPixbuf{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_file_at_scale".}
proc gdk_pixbuf_new_from_file_at_size*(filename: cstring, width, height: gint,
error: pointer): PGdkPixbuf{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_file_at_size".}
proc gdk_pixbuf_new_from_file_at_scale*(filename: cstring, width, height: gint,
preserve_aspect_ratio: gboolean, error: pointer): PGdkPixbuf{.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_file_at_scale".}
proc gdk_pixbuf_fill*(pixbuf: PGdkPixbuf, pixel: guint32){.cdecl,
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_fill".}
proc gdk_pixbuf_save*(pixbuf: PGdkPixbuf, filename: cstring, `type`: cstring,
@ -158,9 +154,9 @@ proc gdk_pixbuf_animation_get_type*(): GType{.cdecl, dynlib: gdkpixbuflib,
proc gdk_pixbuf_animation_new_from_file*(filename: cstring, error: pointer): PGdkPixbufAnimation{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_new_from_file".}
when not defined(GDK_PIXBUF_DISABLE_DEPRECATED):
proc gdk_pixbuf_animation_ref(animation: PGdkPixbufAnimation): PGdkPixbufAnimation{.
proc gdk_pixbuf_animation_ref*(animation: PGdkPixbufAnimation): PGdkPixbufAnimation{.
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".}
proc gdk_pixbuf_animation_get_width*(animation: PGdkPixbufAnimation): int32{.
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_get_width".}

View file

@ -1,16 +1,16 @@
when defined(windows):
{.define: gtkwin.}
const
gliblib = "libglib-2.0-0.dll"
gthreadlib = "libgthread-2.0-0.dll"
gmodulelib = "libgmodule-2.0-0.dll"
gobjectlib = "libgobject-2.0-0.dll"
else:
const
gliblib = "libglib-2.0.so"
gthreadlib = "libgthread-2.0.so"
gmodulelib = "libgmodule-2.0.so"
gobjectlib = "libgobject-2.0.so"
# gthreadlib = "libgthread-2.0.so"
type
PGTypePlugin* = pointer
PGParamSpecPool* = pointer
@ -19,29 +19,29 @@ type
PPPgchar* = ptr PPgchar
PPgchar* = ptr cstring
gchar* = char
Pgshort* = ptr gshort
gshort* = cshort
Pglong* = ptr glong
glong* = clong
Pgint* = ptr gint
PPgint* = ptr Pgint
gint* = cint
Pgboolean* = ptr gboolean
gboolean* = bool
Pguchar* = ptr guchar
PPguchar* = ptr Pguchar
guchar* = char
Pgushort* = ptr gushort
gushort* = int16
Pgulong* = ptr gulong
gulong* = int
guint* = cint
Pguint* = ptr guint
gfloat* = cfloat
Pgfloat* = ptr gfloat
gdouble* = cdouble
Pgdouble* = ptr gdouble
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
gconstpointer* = pointer
PGCompareFunc* = ptr TGCompareFunc
@ -118,8 +118,8 @@ type
g_type*: GType
data*: array[0..1, gdouble]
PPGData* = ptr PGData
PGData* = pointer
PPGData* = ptr PGData
PGSList* = ptr TGSList
PPGSList* = ptr PGSList
TGSList* {.final.} = object
@ -132,8 +132,8 @@ type
next*: PGList
prev*: PGList
PGParamFlags* = ptr TGParamFlags
TGParamFlags* = int32
PGParamFlags* = ptr TGParamFlags
PGParamSpec* = ptr TGParamSpec
PPGParamSpec* = ptr PGParamSpec
TGParamSpec* {.final.} = object
@ -194,7 +194,7 @@ const
G_TYPE_PARAM* = GType(19 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
G_TYPE_RESERVED_GLIB_FIRST* = 21
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_INTERFACE*(g_iface: Pointer): GType
type
PGTypeDebugFlags* = ptr TGTypeDebugFlags
TGTypeDebugFlags* = int32
PGTypeDebugFlags* = ptr TGTypeDebugFlags
const
G_TYPE_DEBUG_NONE* = 0
@ -296,8 +296,8 @@ const
G_TYPE_FLAG_DEEP_DERIVABLE* = 1 shl 3
type
PGTypeFlags* = ptr TGTypeFlags
TGTypeFlags* = int32
PGTypeFlags* = ptr TGTypeFlags
const
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){.
cdecl, dynlib: gobjectlib, importc: "g_value_set_string_take_ownership".}
type
Pgchararray* = ptr Tgchararray
Tgchararray* = gchar
Pgchararray* = ptr Tgchararray
proc G_TYPE_IS_PARAM*(theType: GType): bool
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_CALLBACK*(f: pointer): TGCallback
const
bm_TGClosure_ref_count* = 0x00007FFF
bp_TGClosure_ref_count* = 0
bm_TGClosure_meta_marshal* = 0x00008000
bp_TGClosure_meta_marshal* = 15
bm_TGClosure_n_guards* = 0x00010000
bp_TGClosure_n_guards* = 16
bm_TGClosure_n_fnotifiers* = 0x00060000
bp_TGClosure_n_fnotifiers* = 17
bm_TGClosure_n_inotifiers* = 0x07F80000
bp_TGClosure_n_inotifiers* = 19
bm_TGClosure_in_inotify* = 0x08000000
bp_TGClosure_in_inotify* = 27
bm_TGClosure_floating* = 0x10000000
bp_TGClosure_floating* = 28
bm_TGClosure_derivative_flag* = 0x20000000
bp_TGClosure_derivative_flag* = 29
bm_TGClosure_in_marshal* = 0x40000000
bp_TGClosure_in_marshal* = 30
bm_TGClosure_is_invalid* = 0x80000000
bp_TGClosure_is_invalid* = 31
bm_TGClosure_ref_count* = 0x00007FFF'i32
bp_TGClosure_ref_count* = 0'i32
bm_TGClosure_meta_marshal* = 0x00008000'i32
bp_TGClosure_meta_marshal* = 15'i32
bm_TGClosure_n_guards* = 0x00010000'i32
bp_TGClosure_n_guards* = 16'i32
bm_TGClosure_n_fnotifiers* = 0x00060000'i32
bp_TGClosure_n_fnotifiers* = 17'i32
bm_TGClosure_n_inotifiers* = 0x07F80000'i32
bp_TGClosure_n_inotifiers* = 19'i32
bm_TGClosure_in_inotify* = 0x08000000'i32
bp_TGClosure_in_inotify* = 27'i32
bm_TGClosure_floating* = 0x10000000'i32
bp_TGClosure_floating* = 28'i32
bm_TGClosure_derivative_flag* = 0x20000000'i32
bp_TGClosure_derivative_flag* = 29'i32
bm_TGClosure_in_marshal* = 0x40000000'i32
bp_TGClosure_in_marshal* = 30'i32
bm_TGClosure_is_invalid* = 0x80000000'i32
bp_TGClosure_is_invalid* = 31'i32
proc ref_count*(a: var TGClosure): guint
proc set_ref_count*(a: var TGClosure, ref_count: guint)
@ -2061,16 +2061,16 @@ type
TGHookFlagMask* = int
const
G_HOOK_FLAG_ACTIVE* = 1 shl 0
G_HOOK_FLAG_IN_CALL* = 1 shl 1
G_HOOK_FLAG_MASK* = 0x0000000F
G_HOOK_FLAG_ACTIVE* = 1'i32 shl 0'i32
G_HOOK_FLAG_IN_CALL* = 1'i32 shl 1'i32
G_HOOK_FLAG_MASK* = 0x0000000F'i32
const
G_HOOK_FLAG_USER_SHIFT* = 4
bm_TGHookList_hook_size* = 0x0000FFFF
bp_TGHookList_hook_size* = 0
bm_TGHookList_is_setup* = 0x00010000
bp_TGHookList_is_setup* = 16
G_HOOK_FLAG_USER_SHIFT* = 4'i32
bm_TGHookList_hook_size* = 0x0000FFFF'i32
bp_TGHookList_hook_size* = 0'i32
bm_TGHookList_is_setup* = 0x00010000'i32
bp_TGHookList_is_setup* = 16'i32
proc TGHookList_hook_size*(a: var TGHookList): guint
proc TGHookList_set_hook_size*(a: var TGHookList, `hook_size`: guint)
@ -2502,18 +2502,18 @@ type
const
bm_TGIOChannel_use_buffer* = 0x00000001
bp_TGIOChannel_use_buffer* = 0
bm_TGIOChannel_do_encode* = 0x00000002
bp_TGIOChannel_do_encode* = 1
bm_TGIOChannel_close_on_unref* = 0x00000004
bp_TGIOChannel_close_on_unref* = 2
bm_TGIOChannel_is_readable* = 0x00000008
bp_TGIOChannel_is_readable* = 3
bm_TGIOChannel_is_writeable* = 0x00000010
bp_TGIOChannel_is_writeable* = 4
bm_TGIOChannel_is_seekable* = 0x00000020
bp_TGIOChannel_is_seekable* = 5
bm_TGIOChannel_use_buffer* = 0x00000001'i16
bp_TGIOChannel_use_buffer* = 0'i16
bm_TGIOChannel_do_encode* = 0x00000002'i16
bp_TGIOChannel_do_encode* = 1'i16
bm_TGIOChannel_close_on_unref* = 0x00000004'i16
bp_TGIOChannel_close_on_unref* = 2'i16
bm_TGIOChannel_is_readable* = 0x00000008'i16
bp_TGIOChannel_is_readable* = 3'i16
bm_TGIOChannel_is_writeable* = 0x00000010'i16
bp_TGIOChannel_is_writeable* = 4'i16
bm_TGIOChannel_is_seekable* = 0x00000020'i16
bp_TGIOChannel_is_seekable* = 5'i16
proc TGIOChannel_use_buffer*(a: var TGIOChannel): guint
proc TGIOChannel_set_use_buffer*(a: var TGIOChannel, `use_buffer`: guint)
@ -3046,48 +3046,48 @@ const
G_CSET_DIGITS* = "0123456789"
const
bm_TGScannerConfig_case_sensitive* = 0x00000001
bp_TGScannerConfig_case_sensitive* = 0
bm_TGScannerConfig_skip_comment_multi* = 0x00000002
bp_TGScannerConfig_skip_comment_multi* = 1
bm_TGScannerConfig_skip_comment_single* = 0x00000004
bp_TGScannerConfig_skip_comment_single* = 2
bm_TGScannerConfig_scan_comment_multi* = 0x00000008
bp_TGScannerConfig_scan_comment_multi* = 3
bm_TGScannerConfig_scan_identifier* = 0x00000010
bp_TGScannerConfig_scan_identifier* = 4
bm_TGScannerConfig_scan_identifier_1char* = 0x00000020
bp_TGScannerConfig_scan_identifier_1char* = 5
bm_TGScannerConfig_scan_identifier_NULL* = 0x00000040
bp_TGScannerConfig_scan_identifier_NULL* = 6
bm_TGScannerConfig_scan_symbols* = 0x00000080
bp_TGScannerConfig_scan_symbols* = 7
bm_TGScannerConfig_scan_binary* = 0x00000100
bp_TGScannerConfig_scan_binary* = 8
bm_TGScannerConfig_scan_octal* = 0x00000200
bp_TGScannerConfig_scan_octal* = 9
bm_TGScannerConfig_scan_float* = 0x00000400
bp_TGScannerConfig_scan_float* = 10
bm_TGScannerConfig_scan_hex* = 0x00000800
bp_TGScannerConfig_scan_hex* = 11
bm_TGScannerConfig_scan_hex_dollar* = 0x00001000
bp_TGScannerConfig_scan_hex_dollar* = 12
bm_TGScannerConfig_scan_string_sq* = 0x00002000
bp_TGScannerConfig_scan_string_sq* = 13
bm_TGScannerConfig_scan_string_dq* = 0x00004000
bp_TGScannerConfig_scan_string_dq* = 14
bm_TGScannerConfig_numbers_2_int* = 0x00008000
bp_TGScannerConfig_numbers_2_int* = 15
bm_TGScannerConfig_int_2_float* = 0x00010000
bp_TGScannerConfig_int_2_float* = 16
bm_TGScannerConfig_identifier_2_string* = 0x00020000
bp_TGScannerConfig_identifier_2_string* = 17
bm_TGScannerConfig_char_2_token* = 0x00040000
bp_TGScannerConfig_char_2_token* = 18
bm_TGScannerConfig_symbol_2_token* = 0x00080000
bp_TGScannerConfig_symbol_2_token* = 19
bm_TGScannerConfig_scope_0_fallback* = 0x00100000
bp_TGScannerConfig_scope_0_fallback* = 20
bm_TGScannerConfig_case_sensitive* = 0x00000001'i32
bp_TGScannerConfig_case_sensitive* = 0'i32
bm_TGScannerConfig_skip_comment_multi* = 0x00000002'i32
bp_TGScannerConfig_skip_comment_multi* = 1'i32
bm_TGScannerConfig_skip_comment_single* = 0x00000004'i32
bp_TGScannerConfig_skip_comment_single* = 2'i32
bm_TGScannerConfig_scan_comment_multi* = 0x00000008'i32
bp_TGScannerConfig_scan_comment_multi* = 3'i32
bm_TGScannerConfig_scan_identifier* = 0x00000010'i32
bp_TGScannerConfig_scan_identifier* = 4'i32
bm_TGScannerConfig_scan_identifier_1char* = 0x00000020'i32
bp_TGScannerConfig_scan_identifier_1char* = 5'i32
bm_TGScannerConfig_scan_identifier_NULL* = 0x00000040'i32
bp_TGScannerConfig_scan_identifier_NULL* = 6'i32
bm_TGScannerConfig_scan_symbols* = 0x00000080'i32
bp_TGScannerConfig_scan_symbols* = 7'i32
bm_TGScannerConfig_scan_binary* = 0x00000100'i32
bp_TGScannerConfig_scan_binary* = 8'i32
bm_TGScannerConfig_scan_octal* = 0x00000200'i32
bp_TGScannerConfig_scan_octal* = 9'i32
bm_TGScannerConfig_scan_float* = 0x00000400'i32
bp_TGScannerConfig_scan_float* = 10'i32
bm_TGScannerConfig_scan_hex* = 0x00000800'i32
bp_TGScannerConfig_scan_hex* = 11'i32
bm_TGScannerConfig_scan_hex_dollar* = 0x00001000'i32
bp_TGScannerConfig_scan_hex_dollar* = 12'i32
bm_TGScannerConfig_scan_string_sq* = 0x00002000'i32
bp_TGScannerConfig_scan_string_sq* = 13'i32
bm_TGScannerConfig_scan_string_dq* = 0x00004000'i32
bp_TGScannerConfig_scan_string_dq* = 14'i32
bm_TGScannerConfig_numbers_2_int* = 0x00008000'i32
bp_TGScannerConfig_numbers_2_int* = 15'i32
bm_TGScannerConfig_int_2_float* = 0x00010000'i32
bp_TGScannerConfig_int_2_float* = 16'i32
bm_TGScannerConfig_identifier_2_string* = 0x00020000'i32
bp_TGScannerConfig_identifier_2_string* = 17'i32
bm_TGScannerConfig_char_2_token* = 0x00040000'i32
bp_TGScannerConfig_char_2_token* = 18'i32
bm_TGScannerConfig_symbol_2_token* = 0x00080000'i32
bp_TGScannerConfig_symbol_2_token* = 19'i32
bm_TGScannerConfig_scope_0_fallback* = 0x00100000'i32
bp_TGScannerConfig_scope_0_fallback* = 20'i32
proc TGScannerConfig_case_sensitive*(a: var TGScannerConfig): guint
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,
dynlib: gliblib, importc: "g_cclosure_marshal_BOOLEAN__FLAGS".}
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 =
Result = ((val and 0x000000FF) shl 24) or ((val and 0x0000FF00) shl 8) or
((val and 0x00FF0000) shr 8) or ((val and 0xFF000000) shr 24)
Result = ((val and 0x000000FF'i32) shl 24'i32) or ((val and 0x0000FF00'i32) shl 8'i32) or
((val and 0x00FF0000'i32) shr 8'i32) or ((val and 0xFF000000'i32) shr 24'i32)
proc GUINT_TO_POINTER*(i: guint): pointer =
Result = cast[Pointer](TAddress(i))
type
PGArray = pointer
when false:
type
PGArray* = pointer
proc g_array_append_val*(a: PGArray, v: gpointer): PGArray =
result = g_array_append_vals(a, addr(v), 1)
@ -3678,17 +3680,17 @@ proc G_HOOK_FLAGS*(hook: PGHook): guint =
result = hook.flags
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 =
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 =
result = (hook.hook_id != 0) and G_HOOK_ACTIVE(hook)
proc G_HOOK_IS_UNLINKED*(hook: PGHook): bool =
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) =
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) =
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)
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) =
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)
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) =
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)
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) =
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)
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) =
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)
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) =
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)
proc g_utf8_next_char*(p: pguchar): pguchar =
@ -3816,10 +3818,10 @@ proc g_node_first_child*(node: PGNode): PGNode =
result = nil
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 =
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 =
result = (a.flag0 and bm_TGScannerConfig_case_sensitive) shr
@ -4077,7 +4079,7 @@ when false:
proc g_strstrip*(str: cstring): cstring =
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)
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
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))
proc G_CCLOSURE_SWAP_DATA*(cclosure: PGClosure): int32 =

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,6 @@ import
glib2, gtk2
when defined(win32):
{.define: gtkwin.}
const
LibGladeLib = "libglade-2.0-0.dll"
else:

View file

@ -1,10 +1,7 @@
import
glib2
{.define: PANGO_ENABLE_ENGINE.}
{.define: PANGO_ENABLE_BACKEND.}
when defined(win32):
{.define: pangowin.}
const
pangolib* = "libpango-1.0-0.dll"
else:
@ -381,26 +378,26 @@ proc pango_parse_markup*(markup_text: cstring, length: int32,
text: PPchar, accel_char: Pgunichar, error: pointer): gboolean{.
cdecl, dynlib: pangolib, importc: "pango_parse_markup".}
const
bm_TPangoLogAttr_is_line_break* = 0x00000001
bp_TPangoLogAttr_is_line_break* = 0
bm_TPangoLogAttr_is_mandatory_break* = 0x00000002
bp_TPangoLogAttr_is_mandatory_break* = 1
bm_TPangoLogAttr_is_char_break* = 0x00000004
bp_TPangoLogAttr_is_char_break* = 2
bm_TPangoLogAttr_is_white* = 0x00000008
bp_TPangoLogAttr_is_white* = 3
bm_TPangoLogAttr_is_cursor_position* = 0x00000010
bp_TPangoLogAttr_is_cursor_position* = 4
bm_TPangoLogAttr_is_word_start* = 0x00000020
bp_TPangoLogAttr_is_word_start* = 5
bm_TPangoLogAttr_is_word_end* = 0x00000040
bp_TPangoLogAttr_is_word_end* = 6
bm_TPangoLogAttr_is_sentence_boundary* = 0x00000080
bp_TPangoLogAttr_is_sentence_boundary* = 7
bm_TPangoLogAttr_is_sentence_start* = 0x00000100
bp_TPangoLogAttr_is_sentence_start* = 8
bm_TPangoLogAttr_is_sentence_end* = 0x00000200
bp_TPangoLogAttr_is_sentence_end* = 9
bm_TPangoLogAttr_is_line_break* = 0x00000001'i16
bp_TPangoLogAttr_is_line_break* = 0'i16
bm_TPangoLogAttr_is_mandatory_break* = 0x00000002'i16
bp_TPangoLogAttr_is_mandatory_break* = 1'i16
bm_TPangoLogAttr_is_char_break* = 0x00000004'i16
bp_TPangoLogAttr_is_char_break* = 2'i16
bm_TPangoLogAttr_is_white* = 0x00000008'i16
bp_TPangoLogAttr_is_white* = 3'i16
bm_TPangoLogAttr_is_cursor_position* = 0x00000010'i16
bp_TPangoLogAttr_is_cursor_position* = 4'i16
bm_TPangoLogAttr_is_word_start* = 0x00000020'i16
bp_TPangoLogAttr_is_word_start* = 5'i16
bm_TPangoLogAttr_is_word_end* = 0x00000040'i16
bp_TPangoLogAttr_is_word_end* = 6'i16
bm_TPangoLogAttr_is_sentence_boundary* = 0x00000080'i16
bp_TPangoLogAttr_is_sentence_boundary* = 7'i16
bm_TPangoLogAttr_is_sentence_start* = 0x00000100'i16
bp_TPangoLogAttr_is_sentence_start* = 8'i16
bm_TPangoLogAttr_is_sentence_end* = 0x00000200'i16
bp_TPangoLogAttr_is_sentence_end* = 9'i16
proc is_line_break*(a: var TPangoLogAttr): guint
proc set_is_line_break*(a: var TPangoLogAttr, `is_line_break`: guint)
@ -687,8 +684,8 @@ proc pango_font_map_list_families*(fontmap: PPangoFontMap,
families: var openarray[ptr PPangoFontFamily]){.cdecl,
dynlib: pangolib, importc: "pango_font_map_list_families".}
const
bm_TPangoGlyphVisAttr_is_cluster_start* = 0x00000001
bp_TPangoGlyphVisAttr_is_cluster_start* = 0
bm_TPangoGlyphVisAttr_is_cluster_start* = 0x00000001'i16
bp_TPangoGlyphVisAttr_is_cluster_start* = 0'i16
proc is_cluster_start*(a: var TPangoGlyphVisAttr): guint
proc set_is_cluster_start*(a: var TPangoGlyphVisAttr, `is_cluster_start`: guint)
@ -931,7 +928,7 @@ proc PANGO_LBEARING*(rect: TPangoRectangle): int32 =
result = rect.x
proc PANGO_RBEARING*(rect: TPangoRectangle): int32 =
result = int(rect.x) + (rect.width)
result = (rect.x) + (rect.width)
proc PANGO_TYPE_LANGUAGE*(): GType =
result = pango_language_get_type()
@ -957,7 +954,7 @@ proc is_line_break*(a: var TPangoLogAttr): guint =
proc set_is_line_break*(a: var TPangoLogAttr, `is_line_break`: guint) =
a.flag0 = a.flag0 or
((`is_line_break` shl bp_TPangoLogAttr_is_line_break) and
(int16(`is_line_break` shl bp_TPangoLogAttr_is_line_break) and
bm_TPangoLogAttr_is_line_break)
proc is_mandatory_break*(a: var TPangoLogAttr): guint =
@ -966,7 +963,7 @@ proc is_mandatory_break*(a: var TPangoLogAttr): guint =
proc set_is_mandatory_break*(a: var TPangoLogAttr, `is_mandatory_break`: guint) =
a.flag0 = a.flag0 or
((`is_mandatory_break` shl bp_TPangoLogAttr_is_mandatory_break) and
(int16(`is_mandatory_break` shl bp_TPangoLogAttr_is_mandatory_break) and
bm_TPangoLogAttr_is_mandatory_break)
proc is_char_break*(a: var TPangoLogAttr): guint =
@ -975,7 +972,7 @@ proc is_char_break*(a: var TPangoLogAttr): guint =
proc set_is_char_break*(a: var TPangoLogAttr, `is_char_break`: guint) =
a.flag0 = a.flag0 or
((`is_char_break` shl bp_TPangoLogAttr_is_char_break) and
(int16(`is_char_break` shl bp_TPangoLogAttr_is_char_break) and
bm_TPangoLogAttr_is_char_break)
proc is_white*(a: var TPangoLogAttr): guint =
@ -984,7 +981,7 @@ proc is_white*(a: var TPangoLogAttr): guint =
proc set_is_white*(a: var TPangoLogAttr, `is_white`: guint) =
a.flag0 = a.flag0 or
((`is_white` shl bp_TPangoLogAttr_is_white) and
(int16(`is_white` shl bp_TPangoLogAttr_is_white) and
bm_TPangoLogAttr_is_white)
proc is_cursor_position*(a: var TPangoLogAttr): guint =
@ -993,7 +990,7 @@ proc is_cursor_position*(a: var TPangoLogAttr): guint =
proc set_is_cursor_position*(a: var TPangoLogAttr, `is_cursor_position`: guint) =
a.flag0 = a.flag0 or
((`is_cursor_position` shl bp_TPangoLogAttr_is_cursor_position) and
(int16(`is_cursor_position` shl bp_TPangoLogAttr_is_cursor_position) and
bm_TPangoLogAttr_is_cursor_position)
proc is_word_start*(a: var TPangoLogAttr): guint =
@ -1002,7 +999,7 @@ proc is_word_start*(a: var TPangoLogAttr): guint =
proc set_is_word_start*(a: var TPangoLogAttr, `is_word_start`: guint) =
a.flag0 = a.flag0 or
((`is_word_start` shl bp_TPangoLogAttr_is_word_start) and
(int16(`is_word_start` shl bp_TPangoLogAttr_is_word_start) and
bm_TPangoLogAttr_is_word_start)
proc is_word_end*(a: var TPangoLogAttr): guint =
@ -1011,7 +1008,7 @@ proc is_word_end*(a: var TPangoLogAttr): guint =
proc set_is_word_end*(a: var TPangoLogAttr, `is_word_end`: guint) =
a.flag0 = a.flag0 or
((`is_word_end` shl bp_TPangoLogAttr_is_word_end) and
(int16(`is_word_end` shl bp_TPangoLogAttr_is_word_end) and
bm_TPangoLogAttr_is_word_end)
proc is_sentence_boundary*(a: var TPangoLogAttr): guint =
@ -1021,7 +1018,7 @@ proc is_sentence_boundary*(a: var TPangoLogAttr): guint =
proc set_is_sentence_boundary*(a: var TPangoLogAttr,
`is_sentence_boundary`: guint) =
a.flag0 = a.flag0 or
((`is_sentence_boundary` shl bp_TPangoLogAttr_is_sentence_boundary) and
(int16(`is_sentence_boundary` shl bp_TPangoLogAttr_is_sentence_boundary) and
bm_TPangoLogAttr_is_sentence_boundary)
proc is_sentence_start*(a: var TPangoLogAttr): guint =
@ -1030,7 +1027,7 @@ proc is_sentence_start*(a: var TPangoLogAttr): guint =
proc set_is_sentence_start*(a: var TPangoLogAttr, `is_sentence_start`: guint) =
a.flag0 = a.flag0 or
((`is_sentence_start` shl bp_TPangoLogAttr_is_sentence_start) and
(int16(`is_sentence_start` shl bp_TPangoLogAttr_is_sentence_start) and
bm_TPangoLogAttr_is_sentence_start)
proc is_sentence_end*(a: var TPangoLogAttr): guint =
@ -1039,7 +1036,7 @@ proc is_sentence_end*(a: var TPangoLogAttr): guint =
proc set_is_sentence_end*(a: var TPangoLogAttr, `is_sentence_end`: guint) =
a.flag0 = a.flag0 or
((`is_sentence_end` shl bp_TPangoLogAttr_is_sentence_end) and
(int16(`is_sentence_end` shl bp_TPangoLogAttr_is_sentence_end) and
bm_TPangoLogAttr_is_sentence_end)
proc PANGO_TYPE_CONTEXT*(): GType =
@ -1181,7 +1178,7 @@ proc is_cluster_start*(a: var TPangoGlyphVisAttr): guint =
proc set_is_cluster_start*(a: var TPangoGlyphVisAttr, `is_cluster_start`: guint) =
a.flag0 = a.flag0 or
((`is_cluster_start` shl bp_TPangoGlyphVisAttr_is_cluster_start) and
(int16(`is_cluster_start` shl bp_TPangoGlyphVisAttr_is_cluster_start) and
bm_TPangoGlyphVisAttr_is_cluster_start)
proc PANGO_TYPE_GLYPH_STRING*(): GType =

View file

@ -18,12 +18,11 @@ proc pango_scan_string*(pos: PPchar, OutStr: PGString): gboolean{.cdecl,
dynlib: pangolib, importc: "pango_scan_string".}
proc pango_scan_int*(pos: PPchar, OutInt: pint32): gboolean{.cdecl,
dynlib: pangolib, importc: "pango_scan_int".}
when defined(PANGO_ENABLE_BACKEND):
proc pango_config_key_get(key: cstring): cstring{.cdecl, dynlib: pangolib,
importc: "pango_config_key_get".}
proc pango_lookup_aliases(fontname: cstring, families: PPPchar,
n_families: pint32){.cdecl, dynlib: pangolib,
importc: "pango_lookup_aliases".}
proc pango_config_key_get(key: cstring): cstring{.cdecl, dynlib: pangolib,
importc: "pango_config_key_get".}
proc pango_lookup_aliases(fontname: cstring, families: PPPchar,
n_families: pint32){.cdecl, dynlib: pangolib,
importc: "pango_lookup_aliases".}
proc pango_parse_style*(str: cstring, style: PPangoStyle, warn: gboolean): gboolean{.
cdecl, dynlib: pangolib, importc: "pango_parse_style".}
proc pango_parse_variant*(str: cstring, variant: PPangoVariant, warn: gboolean): gboolean{.
@ -32,11 +31,10 @@ proc pango_parse_weight*(str: cstring, weight: PPangoWeight, warn: gboolean): gb
cdecl, dynlib: pangolib, importc: "pango_parse_weight".}
proc pango_parse_stretch*(str: cstring, stretch: PPangoStretch, warn: gboolean): gboolean{.
cdecl, dynlib: pangolib, importc: "pango_parse_stretch".}
when defined(PANGO_ENABLE_BACKEND):
proc pango_get_sysconf_subdirectory(): cstring{.cdecl, dynlib: pangolib,
importc: "pango_get_sysconf_subdirectory".}
proc pango_get_lib_subdirectory(): cstring{.cdecl, dynlib: pangolib,
importc: "pango_get_lib_subdirectory".}
proc pango_get_sysconf_subdirectory(): cstring{.cdecl, dynlib: pangolib,
importc: "pango_get_sysconf_subdirectory".}
proc pango_get_lib_subdirectory(): cstring{.cdecl, dynlib: pangolib,
importc: "pango_get_lib_subdirectory".}
proc pango_log2vis_get_embedding_levels*(str: Pgunichar, len: int32,
pbase_dir: PPangoDirection, embedding_level_list: Pguint8): gboolean{.cdecl,
dynlib: pangolib, importc: "pango_log2vis_get_embedding_levels".}

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

@ -9,7 +9,7 @@
# This file was created by a complicated procedure which saved me a considerable
# amount of time: the pcre.h header was converted to modpcre.h by hand, so that
# h2pas could handle it. Then I used pas2mor to generate a Morpork binding.
# 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
# again! My manual changes will be lost!
@ -23,12 +23,62 @@
type
Pbyte = ptr byte
Pchar = CString
PPchar = ptr PChar
PPchar = ptr cstring
Pint = ptr cint
Ppcre* = ptr TPcre
Ppcre_callout_block = ptr tpcre_callout_block
Ppcre_extra = ptr Tpcre_extra
Ppcre_callout_block* = ptr tpcre_callout_block
Ppcre_extra* = ptr Tpcre_extra
TPcre {.final, pure.} = object
# The structure for passing additional data to pcre_exec(). This is defined
# in such as way as to be extensible.
# Bits for which fields are set
# Opaque data from pcre_study()
# Maximum number of calls to match()
# Data passed back in callouts
# Const before type ignored
# Pointer to character tables
Tpcre_extra* {.final, pure.} = object
flags: cint
study_data: pointer
match_limit: cint
callout_data: pointer
tables: ptr byte
# The structure for passing out data via the pcre_callout_function. We use a
# structure so that new fields can be added on the end in future versions,
# without changing the API of the function, thereby allowing old clients to
# work without modification.
# Identifies version of block
# ------------------------ Version 0 -------------------------------
# Number compiled into pattern
# The offset vector
# Const before type ignored
# The subject being matched
# The length of the subject
# Offset to start of this match attempt
# Where we currently are in the subject
# Max current capture
# Most recently closed capture
# Data passed in with the call
# ------------------- Added for Version 1 --------------------------
# Offset to next item in the pattern
# Length of next item in the pattern
# ------------------------------------------------------------------
TPcre_callout_block* {.final, pure.} = object
version: cint
callout_number: cint
offset_vector: ptr cint
subject: ptr char
subject_length: cint
start_match: cint
current_position: cint
capture_top: cint
capture_last: cint
callout_data: pointer
pattern_position: cint
next_item_length: cint
#************************************************
#* Perl-Compatible Regular Expressions *
@ -146,95 +196,39 @@ const
PCRE_EXTRA_MATCH_LIMIT* = 0x0002
PCRE_EXTRA_CALLOUT_DATA* = 0x0004
PCRE_EXTRA_TABLES* = 0x0008
# Types
type
TPcre = record
#undefined structure
# The structure for passing additional data to pcre_exec(). This is defined
# in such as way as to be extensible. Always add new fields at the end,
# in order to remain compatible.
# Bits for which fields are set
# Opaque data from pcre_study()
# Maximum number of calls to match()
# Data passed back in callouts
# Const before type ignored
# Pointer to character tables
Tpcre_extra* {.final.} = object
flags: cuint
study_data: pointer
match_limit: cuint
callout_data: pointer
tables: ptr byte
# The structure for passing out data via the pcre_callout_function. We use a
# structure so that new fields can be added on the end in future versions,
# without changing the API of the function, thereby allowing old clients to
# work without modification.
# Identifies version of block
# ------------------------ Version 0 -------------------------------
# Number compiled into pattern
# The offset vector
# Const before type ignored
# The subject being matched
# The length of the subject
# Offset to start of this match attempt
# Where we currently are in the subject
# Max current capture
# Most recently closed capture
# Data passed in with the call
# ------------------- Added for Version 1 --------------------------
# Offset to next item in the pattern
# Length of next item in the pattern
# ------------------------------------------------------------------
TPcre_callout_block* {.final.} = object
version: cint
callout_number: cint
offset_vector: ptr cint
subject: ptr char
subject_length: cint
start_match: cint
current_position: cint
capture_top: cint
capture_last: cint
callout_data: pointer
pattern_position: cint
next_item_length: cint
# Exported PCRE functions
proc pcre_compile*(para1: Pchar, para2: cint, para3: ptr Pchar,
para4: Pint, para5: Pbyte): Ppcre {.
proc pcre_compile*(para1: cstring, para2: cint, para3: ptr cstring,
para4: ptr int, para5: Pbyte): Ppcre {.
importc: "pcre_compile", noconv.}
proc pcre_compile2*(para1: Pchar, para2: cint, para3: Pint, para4: PPchar,
para5: Pint, para6: Pbyte): Ppcre {.
proc pcre_compile2*(para1: cstring, para2: cint, para3: Pint, para4: PPchar,
para5: ptr int, para6: Pbyte): Ppcre {.
importc: "pcre_compile2", noconv.}
proc pcre_config*(para1: cint, para2: pointer): cint {.
importc: "pcre_config", noconv.}
proc pcre_copy_named_substring*(para1: Ppcre, para2: Pchar, para3: Pint,
para4: cint, para5: Pchar, para6: Pchar,
proc pcre_copy_named_substring*(para1: Ppcre, para2: cstring, para3: Pint,
para4: cint, para5: cstring, para6: cstring,
para7: cint): cint {.
importc: "pcre_copy_named_substring", noconv.}
proc pcre_copy_substring*(para1: Pchar, para2: Pint, para3: cint, para4: cint,
para5: Pchar, para6: cint): cint {.
proc pcre_copy_substring*(para1: cstring, para2: Pint, para3: cint, para4: cint,
para5: cstring, para6: cint): cint {.
importc: "pcre_copy_substring", noconv.}
proc pcre_dfa_exec*(para1: Ppcre, para2: Ppcre_extra, para3: Pchar,
proc pcre_dfa_exec*(para1: Ppcre, para2: Ppcre_extra, para3: cstring,
para4: cint, para5: cint, para6: cint, para7: Pint,
para8: cint, para9: Pint, para10: cint): cint {.
importc: "pcre_dfa_exec", noconv.}
proc pcre_exec*(para1: Ppcre, para2: Ppcre_extra, para3: Pchar,
proc pcre_exec*(para1: Ppcre, para2: Ppcre_extra, para3: cstring,
para4: cint, para5: cint, para6: cint, para7: Pint,
para8: cint): cint {.importc: "pcre_exec", noconv.}
proc pcre_free_substring*(para1: Pchar) {.
proc pcre_free_substring*(para1: cstring) {.
importc: "pcre_free_substring", noconv.}
proc pcre_free_substring_list*(para1: PPchar) {.
@ -243,18 +237,18 @@ proc pcre_free_substring_list*(para1: PPchar) {.
proc pcre_fullinfo*(para1: Ppcre, para2: Ppcre_extra, para3: cint,
para4: pointer): cint {.importc: "pcre_fullinfo", noconv.}
proc pcre_get_named_substring*(para1: Ppcre, para2: Pchar, para3: Pint,
para4: cint, para5: Pchar, para6: PPchar): cint {.
proc pcre_get_named_substring*(para1: Ppcre, para2: cstring, para3: Pint,
para4: cint, para5: cstring, para6: PPchar): cint {.
importc: "pcre_get_named_substring", noconv.}
proc pcre_get_stringnumber*(para1: Ppcre, para2: Pchar): cint {.
proc pcre_get_stringnumber*(para1: Ppcre, para2: cstring): cint {.
importc: "pcre_get_stringnumber", noconv.}
proc pcre_get_substring*(para1: Pchar, para2: Pint, para3: cint,
proc pcre_get_substring*(para1: cstring, para2: Pint, para3: cint,
para4: cint, para5: PPchar): cint {.
importc: "pcre_get_substring", noconv.}
proc pcre_get_substring_list*(para1: Pchar, para2: Pint, para3: cint,
proc pcre_get_substring_list*(para1: cstring, para2: Pint, para3: cint,
para4: ptr PPchar): cint {.
importc: "pcre_get_substring_list", noconv.}
@ -279,18 +273,19 @@ proc pcre_version*: CString {.importc: "pcre_version", noconv.}
#
# we use Nimrod's memory manager (but not GC!) for these functions:
type
TMalloc = proc (para1: int): pointer {.noconv.}
TFree = proc (para1: pointer) {.noconv.}
var
pcre_malloc {.importc: "pcre_malloc".}: proc (para1: int): pointer {.noconv.}
pcre_free {.importc: "pcre_free".}: proc (para1: pointer) {.noconv.}
pcre_stack_malloc {.importc: "pcre_stack_malloc".}:
proc (para1: int): pointer {.noconv.}
pcre_stack_free {.importc: "pcre_stack_free".}:
proc (para1: pointer) {.noconv.}
pcre_malloc {.importc: "pcre_malloc".}: TMalloc
pcre_free {.importc: "pcre_free".}: TFree
pcre_stack_malloc {.importc: "pcre_stack_malloc".}: TMalloc
pcre_stack_free {.importc: "pcre_stack_free".}: TFree
pcre_callout {.importc: "pcre_callout".}:
proc (para1: Ppcre_callout_block): cint {.noconv.}
pcre_malloc = system.alloc
pcre_free = system.dealloc
pcre_stack_malloc = system.alloc
pcre_stack_free = system.dealloc
pcre_malloc = cast[TMalloc](system.alloc)
pcre_free = cast[TFree](system.dealloc)
pcre_stack_malloc = cast[TMalloc](system.alloc)
pcre_stack_free = cast[TFree](system.dealloc)
pcre_callout = nil

View file

@ -33,27 +33,27 @@ const
## defines the maximum number of subpatterns that can 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
## returns ``true`` if ``s`` matches the ``pattern[start..]`` and
## the captured substrings in the array ``substrs``. If it does not
## match, nothing is written into ``substrs`` and ``false`` is
## the captured substrings in the array ``matches``. If it does not
## match, nothing is written into ``matches`` and ``false`` is
## returned.
proc match*(s, pattern: string, start: int = 0): bool
## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``.
proc matchLen*(s, pattern: string, substrs: var openarray[string],
proc matchLen*(s, pattern: string, matches: var openarray[string],
start: int = 0): int
## the same as ``match``, but it returns the length of the match,
## if there is no match, -1 is returned. Note that a match length
## of zero can happen.
proc find*(s, pattern: string, substrs: var openarray[string],
proc find*(s, pattern: string, matches: var openarray[string],
start: int = 0): bool
## returns ``true`` if ``pattern`` occurs in ``s`` and the captured
## substrings in the array ``substrs``. If it does not match, nothing
## is written into ``substrs``.
## substrings in the array ``matches``. If it does not match, nothing
## is written into ``matches``.
proc find*(s, pattern: string, start: int = 0): bool
## returns ``true`` if ``pattern`` occurs in ``s``.
@ -61,7 +61,7 @@ proc find*(s, pattern: string, start: int = 0): bool
proc rawCompile(pattern: string, flags: cint): PPcre =
var
msg: CString
offset: cint
offset: int
com = pcreCompile(pattern, flags, addr(msg), addr(offset), nil)
if com == nil:
var e: ref EInvalidRegEx
@ -70,45 +70,46 @@ proc rawCompile(pattern: string, flags: cint): PPcre =
raise e
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 =
var
rawMatches: array [0..maxSubpatterns * 3 - 1, cint]
res = int(pcreExec(pattern, nil, s, length(s), start, 0,
cast[pint](addr(rawMatches)), maxSubpatterns * 3))
res = int(pcreExec(pattern, nil, s, len(s), start, 0,
cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3))
dealloc(pattern)
if res < 0: return res
for i in 0..res-1:
var
a = rawMatches[i * 3]
b = rawMatches[i * 3 + 1]
if a >= 0: substrs[i] = copy(s, a, b)
else: substrs[i] = ""
a = rawMatches[i * 2]
b = rawMatches[i * 2 + 1]
if a >= 0'i32: matches[i] = copy(s, a, int(b)-1)
else: matches[i] = ""
return res
proc matchOrFind(s: string, pattern: PPcre, start: cint): cint =
var
rawMatches: array [0..maxSubpatterns * 3 - 1, cint]
res = pcreExec(pattern, nil, s, length(s), start, 0,
cast[pint](addr(rawMatches)), maxSubpatterns * 3)
res = pcreExec(pattern, nil, s, len(s), start, 0,
cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3)
dealloc(pattern)
return res
proc match(s, pattern: string, substrs: var openarray[string],
proc match(s, pattern: string, matches: var openarray[string],
start: int = 0): bool =
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 =
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 =
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
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
return matchOrFind(s, rawCompile(pattern, PCRE_MULTILINE), start) >= 0'i32

View file

@ -17,4 +17,4 @@ proc population16(a: int): int {.inline.} =
return x
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,5 +1,4 @@
# Container library for Nimrod
# Implemented with macros, because generics sucks in many ways
# Data structures for now:
# TTable, TSet, TList

View file

@ -1,12 +1,15 @@
#define USE_DL_PREFIX
#define USE_DL_PREFIX
#define ASSEMBLY_VERSION
/*
#define FOOTERS 1
#define DEBUG 1
/*
#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
@ -2210,7 +2213,7 @@ static size_t traverse_and_check(mstate m);
#define treebin_at(M,i) (&((M)->treebins[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)\
{\
size_t X = S >> TREEBIN_SHIFT;\
@ -2275,7 +2278,7 @@ static size_t traverse_and_check(mstate m);
/* index corresponding to given bit */
#if defined(__GNUC__) && defined(i386)
#if defined(__GNUC__) && defined(i386) && defined(ASSEMBLY_VERSION)
#define compute_bit2idx(X, I)\
{\
unsigned int J;\

View file

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

View file

@ -171,8 +171,7 @@ var
proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
# print stack trace and quit
var
s = int(sig)
var s = sig
GC_disable()
setLen(buf, 0)
rawWriteStackTrace(buf)
@ -199,7 +198,8 @@ proc registerSignalHandler() =
c_signal(SIGILL, 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
# signal handlers have been registered
new(gAssertionFailed)
@ -256,3 +256,12 @@ proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
if a != b:
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

1152
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
proc init*[TKey, TValue](t: var TTable[TKey, TValue], capacity: natural = 32) =
t.d = [] # XXX
setLen(t.d, capacity)
newSeq(t.d, capacity)
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
proc TableEnlarge[TKey, TValue](t: var TTable[TKey, TValue]) =
var n: seq[TPair[TKey,TValue]] = []
setLen(n, len(t.d) * growthFactor) # XXX
var n: seq[TPair[TKey,TValue]]
newSeq(n, len(t.d) * growthFactor)
for i in 0..high(t.d):
if not isNil(t.d[i].key):
TableRawInsert(n, t.d[i].key, t.d[i].val)

View file

@ -13,7 +13,7 @@ type # This should be he same as ast.TTypeKind
tyNone, # 0
tyBool, # 1
tyChar, # 2
tyEmptySet, # 3
tyEmpty, # 3
tyArrayConstr, # 4
tyNil, # 5
tyGeneric, # 6
@ -49,9 +49,13 @@ type # This should be he same as ast.TTypeKind
len: int
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
size: int
kind: TNimKind
flags: set[TNimTypeFlag]
base: ptr TNimType
node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum
finalizer: pointer # the finalizer for the type

View file

@ -8,42 +8,39 @@
#
## 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
## buffer handling that exists! Only at line endings checks are necessary
## if the buffer needs refilling.
## handling. Only at line endings checks are necessary if the buffer
## needs refilling.
import
strutils
strutils, streams
const
EndOfFile* = '\0' ## end of file marker
# A little picture makes everything clear :-)
# buf:
# "Example Text\n ha!" bufLen = 17
# ^pos = 0 ^ sentinel = 12
#
NewLines* = {'\c', '\L'}
# Buffer handling:
# buf:
# "Example Text\n ha!" bufLen = 17
# ^pos = 0 ^ sentinel = 12
#
type
TBaseLexer* = object of TObject ## the base lexer. Inherit your lexer from
## this object.
bufpos*: int ## the current position within the buffer
buf*: cstring ## the buffer itself
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
sentinel: int
lineStart: int # index of last line start in buffer
fileOpened: bool
proc initBaseLexer*(L: var TBaseLexer, filename: string, bufLen: int = 8192): bool
## inits the TBaseLexer object with a file to scan
proc open*(L: var TBaseLexer, input: PStream, bufLen: int = 8192)
## inits the TBaseLexer with a stream to read from
proc initBaseLexerFromBuffer*(L: var TBaseLexer, buffer: string)
## inits the TBaseLexer with a buffer to scan
proc deinitBaseLexer*(L: var TBaseLexer)
## deinitializes the base lexer. This needs to be called to close the file.
proc close*(L: var TBaseLexer)
## closes the base lexer. This closes `L`'s associated stream too.
proc getCurrentLine*(L: TBaseLexer, marker: bool = true): string
## retrieves the current line.
@ -65,9 +62,9 @@ proc HandleLF*(L: var TBaseLexer, pos: int): int
const
chrSize = sizeof(char)
proc deinitBaseLexer(L: var TBaseLexer) =
proc close(L: var TBaseLexer) =
dealloc(L.buf)
if L.fileOpened: closeFile(L.f)
L.input.close(L.input)
proc FillBuffer(L: var TBaseLexer) =
var
@ -82,8 +79,8 @@ proc FillBuffer(L: var TBaseLexer) =
assert(toCopy >= 0)
if toCopy > 0:
MoveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize) # "moveMem" handles overlapping regions
charsRead = ReadBuffer(L.f, addr(L.buf[toCopy]), (L.sentinel + 1) * chrSize) div
chrSize
charsRead = L.input.readData(L.input, addr(L.buf[toCopy]),
(L.sentinel + 1) * chrSize) div chrSize
s = toCopy + charsRead
if charsRead < L.sentinel + 1:
L.buf[s] = EndOfFile # set end marker
@ -105,8 +102,8 @@ proc FillBuffer(L: var TBaseLexer) =
L.bufLen = L.BufLen * 2
L.buf = cast[cstring](realloc(L.buf, L.bufLen * chrSize))
assert(L.bufLen - oldBuflen == oldBufLen)
charsRead = ReadBuffer(L.f, addr(L.buf[oldBufLen]), oldBufLen * chrSize) div
chrSize
charsRead = L.input.ReadData(L.input, addr(L.buf[oldBufLen]),
oldBufLen * chrSize) div chrSize
if charsRead < oldBufLen:
L.buf[oldBufLen + charsRead] = EndOfFile
L.sentinel = oldBufLen + charsRead
@ -140,33 +137,17 @@ proc skip_UTF_8_BOM(L: var TBaseLexer) =
inc(L.bufpos, 3)
inc(L.lineStart, 3)
proc initBaseLexer(L: var TBaseLexer, filename: string, bufLen: int = 8192): bool =
proc open(L: var TBaseLexer, input: PStream, bufLen: int = 8192) =
assert(bufLen > 0)
assert(input != nil)
L.input = input
L.bufpos = 0
L.bufLen = bufLen
L.buf = cast[cstring](alloc(bufLen * chrSize))
L.sentinel = bufLen - 1
L.lineStart = 0
L.linenumber = 1 # lines start at 1
L.fileOpened = openFile(L.f, filename)
result = L.fileOpened
if result:
fillBuffer(L)
skip_UTF_8_BOM(L)
proc initBaseLexerFromBuffer(L: var TBaseLexer, buffer: string) =
L.bufpos = 0
L.bufLen = len(buffer) + 1
L.buf = cast[cstring](alloc(L.bufLen * chrSize))
L.sentinel = L.bufLen - 1
L.lineStart = 0
L.linenumber = 1 # lines start at 1
L.fileOpened = false
if L.bufLen > 0:
copyMem(L.buf, cast[pointer](buffer), L.bufLen)
L.buf[L.bufLen - 1] = EndOfFile
else:
L.buf[0] = EndOfFile
fillBuffer(L)
skip_UTF_8_BOM(L)
proc getColNumber(L: TBaseLexer, pos: int): int =

View file

@ -12,27 +12,43 @@
## Abstract syntax trees should be modified in macros.
#[[[cog
#def toEnum(name, elems, prefix):
#def toEnum(name, elems):
# body = ""
# counter = 0
# for e in elems:
# if counter % 4 == 0: p = "\n "
# else: p = ""
# body += p + prefix + e[2:] + ', '
# counter += 1
# body = body + p + 'n' + e + ', '
# counter = counter + 1
#
# return " TNimrod%s* = enum%s\n TNim%ss* = set[TNimrod%s]\n" \
# % (name, body.rstrip(", "), name, name)
# return (" TNimrod%s* = enum%s\n TNim%ss* = set[TNimrod%s]\n" %
# (name, body[:-2], name, name))
#
#enums = eval(file("data/ast.yml").read())
#enums = eval(open("data/ast.yml").read())
#cog.out("type\n")
#i = 0
#for key, val in enums.iteritems():
# if key.endswith("Flag"): continue
# cog.out(toEnum(key, val, ["nnk", "nty", "nsk"][i]))
# i += 1
#for key, val in enums.items():
# if key[-4:] == "Flag": continue
# cog.out(toEnum(key, val))
#]]]
type
TNimrodTypeKind* = enum
ntyNone, ntyBool, ntyChar, ntyEmpty,
ntyArrayConstr, ntyNil, ntyGeneric, ntyGenericInst,
ntyGenericParam, ntyEnum, ntyAnyEnum, ntyArray,
ntyObject, ntyTuple, ntySet, ntyRange,
ntyPtr, ntyRef, ntyVar, ntySequence,
ntyProc, ntyPointer, ntyOpenArray, ntyString,
ntyCString, ntyForward, ntyInt, ntyInt8,
ntyInt16, ntyInt32, ntyInt64, ntyFloat,
ntyFloat32, ntyFloat64, ntyFloat128
TNimTypeKinds* = set[TNimrodTypeKind]
TNimrodSymKind* = enum
nskUnknownSym, nskConditional, nskDynLib, nskParam,
nskTypeParam, nskTemp, nskType, nskConst,
nskVar, nskProc, nskIterator, nskConverter,
nskMacro, nskTemplate, nskField, nskEnumField,
nskForVar, nskModule, nskLabel, nskStub
TNimSymKinds* = set[TNimrodSymKind]
TNimrodNodeKind* = enum
nnkNone, nnkEmpty, nnkIdent, nnkSym,
nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit,
@ -61,29 +77,12 @@ type
nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkDiscardStmt,
nnkStmtList, nnkImportStmt, nnkFromStmt, nnkImportAs,
nnkIncludeStmt, nnkAccessStmt, nnkCommentStmt, nnkStmtListExpr,
nnkBlockExpr, nnkVm, nnkTypeOfExpr, nnkObjectTy,
nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen,
nnkRefTy, nnkPtrTy, nnkVarTy, nnkProcTy,
nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
nnkBlockExpr, nnkStmtListType, nnkBlockType, nnkVm,
nnkTypeOfExpr, nnkObjectTy, nnkTupleTy, nnkRecList,
nnkRecCase, nnkRecWhen, nnkRefTy, nnkPtrTy,
nnkVarTy, nnkProcTy, nnkEnumTy, nnkEnumFieldDef,
nnkReturnToken
TNimNodeKinds* = set[TNimrodNodeKind]
TNimrodTypeKind* = enum
ntyNone, ntyBool, ntyChar, ntyEmptySet,
ntyArrayConstr, ntyNil, ntyGeneric, ntyGenericInst,
ntyGenericParam, ntyEnum, ntyAnyEnum, ntyArray,
ntyObject, ntyTuple, ntySet, ntyRange,
ntyPtr, ntyRef, ntyVar, ntySequence,
ntyProc, ntyPointer, ntyOpenArray, ntyString,
ntyCString, ntyForward, ntyInt, ntyInt8,
ntyInt16, ntyInt32, ntyInt64, ntyFloat,
ntyFloat32, ntyFloat64, ntyFloat128
TNimTypeKinds* = set[TNimrodTypeKind]
TNimrodSymKind* = enum
nskUnknownSym, nskConditional, nskDynLib, nskParam,
nskTypeParam, nskTemp, nskType, nskConst,
nskVar, nskProc, nskIterator, nskConverter,
nskMacro, nskTemplate, nskField, nskEnumField,
nskForVar, nskModule, nskLabel
TNimSymKinds* = set[TNimrodSymKind]
#[[[end]]]
type
@ -142,33 +141,33 @@ proc error*(msg: string) {.magic: "NError".}
proc warning*(msg: string) {.magic: "NWarning".}
proc hint*(msg: string) {.magic: "NHint".}
proc newStrLitNode*(s: string): PNimrodNode {.nodecl.} =
proc newStrLitNode*(s: string): PNimrodNode {.compileTime.} =
result = newNimNode(nnkStrLit)
result.strVal = s
proc newIntLitNode*(i: biggestInt): PNimrodNode {.nodecl.} =
proc newIntLitNode*(i: biggestInt): PNimrodNode {.compileTime.} =
result = newNimNode(nnkIntLit)
result.intVal = i
proc newIntLitNode*(f: biggestFloat): PNimrodNode {.nodecl.} =
proc newIntLitNode*(f: biggestFloat): PNimrodNode {.compileTime.} =
result = newNimNode(nnkFloatLit)
result.floatVal = f
proc newIdentNode*(i: TNimrodIdent): PNimrodNode {.nodecl.} =
proc newIdentNode*(i: TNimrodIdent): PNimrodNode {.compileTime.} =
result = newNimNode(nnkIdent)
result.ident = i
proc toStrLit*(n: PNimrodNode): PNimrodNode {.nodecl.} =
proc toStrLit*(n: PNimrodNode): PNimrodNode {.compileTime.} =
return newStrLitNode(repr(n))
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.nodecl.} =
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
if n.kind != k: error("macro expects a node of kind: " & repr(k))
proc expectMinLen*(n: PNimrodNode, min: int) {.nodecl.} =
proc expectMinLen*(n: PNimrodNode, min: int) {.compileTime.} =
if n.len < min: error("macro expects a node with " & $min & " children")
proc newCall*(theProc: TNimrodIdent,
args: openArray[PNimrodNode]): PNimrodNode {.nodecl.} =
args: openArray[PNimrodNode]): PNimrodNode {.compileTime.} =
## produces a new call node. `theProc` is the proc that is called with
## the arguments ``args[0..]``.
result = newNimNode(nnkCall)

View file

@ -18,6 +18,10 @@
when defined(Posix):
{.passl: "-lm".}
const
PI* = 3.1415926535897932384626433 ## the circle constant PI (Ludolph's number)
E* = 2.71828182845904523536028747 ## Euler's number
type
TFloatClass* = enum ## describes the class a floating point value belongs to.
## 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:
if x == 0.0:
if 1.0/x == 1.0/0.0:
if 1.0/x == Inf:
return fcZero
else:
return fcNegZero
@ -129,7 +133,7 @@ when not defined(ECMAScript):
proc rand(): cint {.importc: "rand", nodecl.}
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:
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.
# 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
# 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.
# A bitset contains any page that starts an allocated page. The page may be
@ -230,6 +230,7 @@ type
zct: TCellArray
stackCells: TCellArray
smallBlocks: array [PageSize div MemAlign, ptr TPageDesc]
freeLists: array [PageSize div MemAlign, ptr TFreeList]
pages: TPageManager
usedPages: TPageList
freePages: TPageList
@ -237,6 +238,11 @@ type
# small blocks:
proc allocSmall(var h: TGcHeap, size: int): pointer =
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]
if p == nil or p.free == nil:
p = newSmallBlock(s, p)

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -1,7 +1,7 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# 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
## 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
## the `identifier` notation is used.
## the \`identifier\` notation is used.
##
## 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
## symbols declared here.
const
hasSpawnH = defined(linux)
hasAioH = defined(linux)
const
C_IRUSR* = 0c000400 ## Read by owner.
C_IWUSR* = 0c000200 ## Write by owner.
@ -55,28 +59,19 @@ const
MM_NULLACT* = nil
MM_NULLTAG* = nil
STDERR_FILENO = 2 ## File number of stderr;
STDIN_FILENO = 0 ## File number of stdin;
STDOUT_FILENO = 1 ## File number of stdout;
STDERR_FILENO* = 2 ## File number of stderr;
STDIN_FILENO* = 0 ## File number of stdin;
STDOUT_FILENO* = 1 ## File number of stdout;
type
Taiocb* {.importc: "struct aiocb", header: "<aio.h>", final.} = 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
TDIR* {.importc: "DIR", header: "<dirent.h>", final, pure.} = object
## 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_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_whence*: cshort ## Flag for starting offset.
l_start*: Toff ## Relative offset in bytes.
@ -84,12 +79,12 @@ type
l_pid*: TPid ## Process ID of the process holding the lock;
## 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
## floating-point environment refers collectively to any
## floating-point status flags and control modes supported
## 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,
## including any status the implementation associates with the
## 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
## 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
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_pathv*: ptr cstring ## Pointer to a list of matched pathnames.
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_gid*: TGid ## Numerical group ID.
gr_mem*: cstringArray ## Pointer to a null-terminated array of character
## 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.
Tlconv* {.importc: "struct lconv", header: "<locale.h>", final.} = object
Tlconv* {.importc: "struct lconv", header: "<locale.h>", final, pure.} = object
currency_symbol*: cstring
decimal_point*: cstring
frac_digits*: char
@ -144,14 +139,14 @@ type
p_sign_posn*: char
thousands_sep*: cstring
TMqd* {.importc: "mqd_t", header: "<mqueue.h>", final.} = object
TMqAttr* {.importc: "struct mq_attr", header: "<mqueue.h>", final.} = object
TMqd* {.importc: "mqd_t", header: "<mqueue.h>", final, pure.} = object
TMqAttr* {.importc: "struct mq_attr", header: "<mqueue.h>", final, pure.} = object
mq_flags*: int ## Message queue flags.
mq_maxmsg*: int ## Maximum number of messages.
mq_msgsize*: int ## Maximum message size.
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_uid*: TUid ## Numerical user ID.
pw_gid*: TGid ## Numerical group ID.
@ -198,7 +193,7 @@ type
Tuid* {.importc: "uid_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.
nodename*, ## Name of this node within the communications
## 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
## system is running.
TSem* {.importc: "sem_t", header: "<semaphore.h>", final.} = object
Tipc_perm* {.importc: "struct ipc_perm", header: "<sys/ipc.h>", final.} = object
TSem* {.importc: "sem_t", header: "<semaphore.h>", final, pure.} = object
Tipc_perm* {.importc: "struct ipc_perm", header: "<sys/ipc.h>", final, pure.} = object
uid*: tuid ## Owner's user ID.
gid*: tgid ## Owner's group ID.
cuid*: Tuid ## Creator's user ID.
cgid*: Tgid ## Creator's group ID.
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_ino*: TIno ## File serial number.
st_mode*: TMode ## Mode of file (see below).
@ -239,7 +234,7 @@ type
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_frsize*: int ## Fundamental file system block size.
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.
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
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_min*: cint ## Minutes [0,59].
tm_hour*: cint ## Hour [0,23].
@ -268,10 +263,10 @@ type
tm_wday*: cint ## Day of week [0,6] (Sunday =0).
tm_yday*: cint ## Day of year [0,365].
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_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_value*: ttimespec ## Timer expiration.
@ -279,19 +274,19 @@ type
## Possibly volatile-qualified integer type of an object that can be
## accessed as an atomic entity, even in the presence of asynchronous
## 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_signo*: cint ## Signal number.
sigev_value*: Tsigval ## Signal value.
sigev_notify_function*: proc (x: TSigval) {.noconv.} ## Notification function.
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;
## 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
## function or one of the macros
## SIG_IGN or SIG_DFL.
@ -300,16 +295,16 @@ type
sa_flags*: cint ## Special flags.
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_size*: int ## Stack size.
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_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_code*: cint ## Signal code.
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_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_ss_low_priority*: cint ## Low scheduling priority for
## sporadic server.
@ -334,15 +329,12 @@ type
sched_ss_max_repl*: cint ## Maximum pending replenishments for
## 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_usec*: tsuseconds ## Microseconds.
Tfd_set* {.importc: "struct fd_set", header: "<sys/select.h>", final.} = object
Tposix_spawnattr* {.importc: "posix_spawnattr_t", header: "<spawn.h>".} = cint
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
Tfd_set* {.importc: "struct fd_set", header: "<sys/select.h>", final, pure.} = object
Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>", final, pure.} = object
Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>", final, pure.} = object
uc_link*: ptr Tucontext ## Pointer to the context that is resumed
## when this context returns.
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
## 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:
var
AIO_ALLDONE* {.importc, header: "<aio.h>".}: cint
## A return value indicating that none of the requested operations
## could be canceled since they are already complete.
AIO_CANCELED* {.importc, header: "<aio.h>".}: cint
## A return value indicating that all requested operations have
## been canceled.
AIO_NOTCANCELED* {.importc, header: "<aio.h>".}: cint
## A return value indicating that some of the requested operations could
## not be canceled since they are in progress.
LIO_NOP* {.importc, header: "<aio.h>".}: cint
## A lio_listio() element operation option indicating that no transfer is
## requested.
LIO_NOWAIT* {.importc, header: "<aio.h>".}: cint
## A lio_listio() synchronization operation indicating that the calling
## thread is to continue execution while the lio_listio() operation is
## being performed, and no notification is given when the operation is
## complete.
LIO_READ* {.importc, header: "<aio.h>".}: cint
## A lio_listio() element operation option requesting a read.
LIO_WAIT* {.importc, header: "<aio.h>".}: cint
## A lio_listio() synchronization operation indicating that the calling
## thread is to suspend until the lio_listio() operation is complete.
LIO_WRITE* {.importc, header: "<aio.h>".}: cint
## A lio_listio() element operation option requesting a write.
when hasAioH:
var
AIO_ALLDONE* {.importc, header: "<aio.h>".}: cint
## A return value indicating that none of the requested operations
## could be canceled since they are already complete.
AIO_CANCELED* {.importc, header: "<aio.h>".}: cint
## A return value indicating that all requested operations have
## been canceled.
AIO_NOTCANCELED* {.importc, header: "<aio.h>".}: cint
## A return value indicating that some of the requested operations could
## not be canceled since they are in progress.
LIO_NOP* {.importc, header: "<aio.h>".}: cint
## A lio_listio() element operation option indicating that no transfer is
## requested.
LIO_NOWAIT* {.importc, header: "<aio.h>".}: cint
## A lio_listio() synchronization operation indicating that the calling
## thread is to continue execution while the lio_listio() operation is
## being performed, and no notification is given when the operation is
## complete.
LIO_READ* {.importc, header: "<aio.h>".}: cint
## A lio_listio() element operation option requesting a read.
LIO_WAIT* {.importc, header: "<aio.h>".}: cint
## A lio_listio() synchronization operation indicating that the calling
## thread is to suspend until the lio_listio() operation is complete.
LIO_WRITE* {.importc, header: "<aio.h>".}: cint
## A lio_listio() element operation option requesting a write.
var
RTLD_LAZY* {.importc, header: "<dlfcn.h>".}: cint
## Relocations are performed at an implementation-defined time.
RTLD_NOW* {.importc, header: "<dlfcn.h>".}: cint
@ -1246,23 +1255,30 @@ var
SCHED_OTHER* {.importc, header: "<sched.h>".}: cint
FD_SETSIZE* {.importc, header: "<sys/select.h>".}: cint
POSIX_SPAWN_RESETIDS* {.importc, header: "<spawn.h>".}: cint
POSIX_SPAWN_SETPGROUP* {.importc, header: "<spawn.h>".}: cint
POSIX_SPAWN_SETSCHEDPARAM* {.importc, header: "<spawn.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
SEEK_SET* {.importc, header: "<unistd.h>".}: cint
SEEK_CUR* {.importc, header: "<unistd.h>".}: cint
SEEK_END* {.importc, header: "<unistd.h>".}: cint
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>".}
when hasSpawnh:
var
POSIX_SPAWN_RESETIDS* {.importc, header: "<spawn.h>".}: cint
POSIX_SPAWN_SETPGROUP* {.importc, header: "<spawn.h>".}: cint
POSIX_SPAWN_SETSCHEDPARAM* {.importc, header: "<spawn.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
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
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 getpwuid*(a1: Tuid): ptr TPasswd {.importc, header: "<pwd.h>".}
proc getpwnam_r(a1: cstring, a2: ptr Tpasswd, a3: cstring, a4: int,
a5: ptr ptr Tpasswd): cint {.importc, header: "<pwd.h>".}
proc getpwnam_r*(a1: cstring, a2: ptr Tpasswd, a3: cstring, a4: int,
a5: ptr ptr Tpasswd): cint {.importc, header: "<pwd.h>".}
proc getpwuid_r*(a1: Tuid, a2: ptr Tpasswd, a3: cstring,
a4: int, a5: ptr ptr Tpasswd): cint {.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 {.
importc, header: "<sys/select.h>".}
proc posix_spawn*(a1: var tpid, a2: cstring,
a3: var Tposix_spawn_file_actions,
a4: var Tposix_spawnattr, a5, a6: cstringArray): cint {.importc, header: "<spawn.h>".}
proc posix_spawn_file_actions_addclose*(a1: var tposix_spawn_file_actions,
a2: cint): cint {.importc, header: "<spawn.h>".}
proc posix_spawn_file_actions_adddup2*(a1: var tposix_spawn_file_actions,
a2, a3: cint): cint {.importc, header: "<spawn.h>".}
proc posix_spawn_file_actions_addopen*(a1: var tposix_spawn_file_actions,
a2: cint, a3: cstring, a4: cint, a5: tmode): cint {.importc, header: "<spawn.h>".}
proc posix_spawn_file_actions_destroy*(a1: var tposix_spawn_file_actions): 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_destroy*(a1: var tposix_spawnattr): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_getsigdefault*(a1: var tposix_spawnattr,
a2: var Tsigset): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_getflags*(a1: var tposix_spawnattr,
a2: var cshort): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_getpgroup*(a1: var tposix_spawnattr,
a2: var tpid): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_getschedparam*(a1: var tposix_spawnattr,
a2: var tsched_param): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_getschedpolicy*(a1: var tposix_spawnattr,
a2: var cint): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_getsigmask*(a1: var tposix_spawnattr,
a2: var tsigset): cint {.importc, header: "<spawn.h>".}
when hasSpawnH:
proc posix_spawn*(a1: var tpid, a2: cstring,
a3: var Tposix_spawn_file_actions,
a4: var Tposix_spawnattr, a5, a6: cstringArray): cint {.importc, header: "<spawn.h>".}
proc posix_spawn_file_actions_addclose*(a1: var tposix_spawn_file_actions,
a2: cint): cint {.importc, header: "<spawn.h>".}
proc posix_spawn_file_actions_adddup2*(a1: var tposix_spawn_file_actions,
a2, a3: cint): cint {.importc, header: "<spawn.h>".}
proc posix_spawn_file_actions_addopen*(a1: var tposix_spawn_file_actions,
a2: cint, a3: cstring, a4: cint, a5: tmode): cint {.importc, header: "<spawn.h>".}
proc posix_spawn_file_actions_destroy*(a1: var tposix_spawn_file_actions): 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_destroy*(a1: var tposix_spawnattr): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_getsigdefault*(a1: var tposix_spawnattr,
a2: var Tsigset): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_getflags*(a1: var tposix_spawnattr,
a2: var cshort): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_getpgroup*(a1: var tposix_spawnattr,
a2: var tpid): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_getschedparam*(a1: var tposix_spawnattr,
a2: var tsched_param): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_getschedpolicy*(a1: var tposix_spawnattr,
a2: var cint): 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,
a2: var tsigset): 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_init*(a1: var tposix_spawnattr): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_setsigdefault*(a1: var tposix_spawnattr,
a2: var tsigset): 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_setschedpolicy*(a1: var tposix_spawnattr, a2: cint): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_setsigmask*(a1: var tposix_spawnattr,
a2: var tsigset): cint {.importc, header: "<spawn.h>".}
proc posix_spawnp*(a1: var tpid, a2: cstring,
a3: var tposix_spawn_file_actions,
a4: var tposix_spawnattr,
a5, a6: cstringArray): 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_setschedpolicy*(a1: var tposix_spawnattr, a2: cint): cint {.importc, header: "<spawn.h>".}
proc posix_spawnattr_setsigmask*(a1: var tposix_spawnattr,
a2: var tsigset): cint {.importc, header: "<spawn.h>".}
proc posix_spawnp*(a1: var tpid, a2: cstring,
a3: var tposix_spawn_file_actions,
a4: var tposix_spawnattr,
a5, a6: cstringArray): cint {.importc, header: "<spawn.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>".}

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:
var a = cast[pbyteArray](p)
for i in 0 .. typ.size*8-1:
if (a[i div 8] and (1 shl (i mod 8))) != 0:
if (ze(a[i div 8]) and (1 shl (i mod 8))) != 0:
if elemCounter > 0: add result, ", "
addSetElem(result, i+typ.node.len, typ.base)
inc(elemCounter)

View file

@ -24,36 +24,36 @@ include cntbits
proc unionSets(res: var TNimSet, a, b: TNimSet, len: int) {.
compilerproc, inline.} =
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) or ze(b[i]))
for i in countup(0, len-1): res[i] = a[i] or b[i]
proc diffSets(res: var TNimSet, a, b: TNimSet, len: int) {.
compilerproc, inline.} =
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) and not ze(b[i]))
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) {.
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) {.
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.} =
# s1 <= s2 ?
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
proc containsSubsets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} =
# s1 < s2 ?
result = false # assume they are equal
for i in countup(0, len-1):
if (ze(a[i]) and not ze(b[i])) != 0: return false
if ze(a[i]) != ze(b[i]): result = true # they are not equal
if (a[i]) and not b[i]) != 0'i32: return false
if a[i] != b[i]: result = true # they are not equal
proc equalSets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} =
for i in countup(0, len-1):
if ze(a[i]) != ze(b[i]): return false
if a[i] != b[i]: return false
return true
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
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.} =
# 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))
proc exclSets(s: var TNimSet, e: int) {.compilerproc, inline.} =
s[e /% WORD_SIZE] = toU8(s[e /% WORD_SIZE] and
not (1 shl (e %% WORD_SIZE)))
s[e /% WORD_SIZE] = s[e /% WORD_SIZE] and
not toU8(1 shl (e %% WORD_SIZE))
proc smallContainsSubsets(a, b: int): bool {.compilerProc, inline.} =
# 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

@ -83,8 +83,7 @@ proc newStringTable(mode: TStringTableMode = modeCaseSensitive): PStringTable =
new(result)
result.mode = mode
result.counter = 0
result.data = []
setlen(result.data, startSize) # XXX
newSeq(result.data, startSize)
proc newStringTable(keyValuePairs: openarray[string],
mode: TStringTableMode = modeCaseSensitive): PStringTable =
@ -110,9 +109,6 @@ proc mustRehash(length, counter: int): bool =
assert(length > counter)
result = (length * 2 < counter * 3) or (length - counter < 4)
const
EmptySeq = []
proc nextTry(h, maxHash: THash): THash =
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
@ -146,8 +142,7 @@ proc RawInsert(t: PStringTable, data: var TKeyValuePairSeq, key, val: string) =
proc Enlarge(t: PStringTable) =
var n: TKeyValuePairSeq
n = emptySeq
setlen(n, len(t.data) * growthFactor)
newSeq(n, len(t.data) * growthFactor)
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)
swap(t.data, n)

View file

@ -24,6 +24,7 @@ template newException(exceptn, message: expr): expr =
e.msg = message
e
type
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.}
## 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)
## Deletes in `s` the characters at position `first`..`last`. This modifies
## `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!
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] {.
noSideEffect.}
## 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.}
## 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.
# the stringify and format operators:
@ -344,7 +386,7 @@ proc cmpIgnoreStyle(a, b: string): int =
# ---------- splitting -----------------------------------------------------
proc splitSeq(s: string, seps: set[char]): seq[string] =
result = []
result = @[]
for sub in split(s, seps): add result, sub
# ---------------------------------------------------------------------------
@ -469,6 +511,14 @@ proc replaceStr(s, sub, by: string): string =
# copy the rest:
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) =
# example: "abc___uvwxyz\0" (___ is to be deleted)
# --> first == 3, last == 5
@ -489,7 +539,7 @@ proc toHex(x: BiggestInt, len: int): string =
shift: BiggestInt
result = newString(len)
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
{.push overflowChecks: on.}
@ -552,6 +602,16 @@ proc ParseFloat(s: string): float =
elif s[i] == '-':
sign = -1.0
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'}:
# Read integer part
flags = flags or 1
@ -572,7 +632,7 @@ proc ParseFloat(s: string): float =
result = result / hd # this complicated way preserves precision
# Again, read integer and fractional part
if flags == 0:
raise newException(EInvalidValue, "invalid float:" & s)
raise newException(EInvalidValue, "invalid float: " & s)
# Exponent?
if s[i] in {'e', 'E'}:
inc(i)
@ -624,4 +684,113 @@ proc toBin*(x: BiggestInt, len: int): string =
shift = shift + 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.}

View file

@ -19,7 +19,7 @@
proc fputs(c: cstring, f: TFile) {.importc: "fputs", noDecl.}
proc fgets(c: cstring, n: int, f: TFile): cstring {.importc: "fgets", noDecl.}
proc fgetc(stream: TFile): int {.importc: "fgetc", nodecl.}
proc ungetc(c: int, f: TFile) {.importc: "ungetc", nodecl.}
proc ungetc(c: cint, f: TFile) {.importc: "ungetc", nodecl.}
proc putc(c: Char, stream: TFile) {.importc: "putc", nodecl.}
proc fprintf(f: TFile, frmt: CString) {.importc: "fprintf", nodecl, varargs.}
proc strlen(c: cstring): int {.importc: "strlen", nodecl.}
@ -33,7 +33,7 @@ var
IOFBF {.importc: "_IOFBF", 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...
# and it was difficult to get this CORRECT with Ansi C's methods
var
@ -41,13 +41,11 @@ proc rawReadLine(f: TFile, result: var string) {.noStatic.} =
setLen(result, 0) # reuse the buffer!
while True:
c = fgetc(f)
if c < 0:
result = nil
break # EOF
if c == 10: break # LF
if c == 13: # CR
if c < 0'i32: break # EOF
if c == 10'i32: break # LF
if c == 13'i32: # CR
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
add result, chr(int(c))
@ -117,11 +115,18 @@ proc OpenFile(f: var TFile, filename: string,
result = (p != nil)
f = cast[TFile](p)
if bufSize > 0:
if setvbuf(f, nil, IOFBF, bufSize) != 0:
if setvbuf(f, nil, IOFBF, bufSize) != 0'i32:
raise newException(EOutOfMemory, "out of memory")
elif bufSize == 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:
proc fread(buf: Pointer, size, n: int, f: TFile): int {.
importc: "fread", noDecl.}

View file

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

View file

@ -19,6 +19,30 @@
{.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.}
## Special comile-time procedure that checks whether `x` is
## 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
## # 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:
proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
## Boolean not; returns true iff ``x == false``.
@ -98,9 +105,10 @@ type
## is an int type ranging from one to the maximum value
## of an int. This type is often useful for documentation and debugging.
TObject* = object ## the root of Nimrod's object hierarchy. Objects should
## inherit from TObject or one of its descendants. However,
## objects that have no ancestor are allowed.
TObject* {.exportc: "TNimObject".} =
object ## the root of Nimrod's object hierarchy. Objects should
## inherit from TObject or one of its descendants. However,
## objects that have no ancestor are allowed.
PObject* = ref TObject ## reference to TObject
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
## 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*(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*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.}
## 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
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:
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.
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`.
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`.
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: 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: 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: 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
## ``floor(x/y)``.
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
## ``x - (x div y) * y``.
proc `shr` *(x, y: int): int {.magic: "ShrI", noSideEffect.}
## computes the `shift right` operation of `x` and `y`.
proc `shl` *(x, y: int): int {.magic: "ShlI", noSideEffect.}
## computes the `shift left` operation of `x` and `y`.
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: int8): int8 {.magic: "ShrI", noSideEffect.}
proc `shr` *(x, y: int16): int16 {.magic: "ShrI", noSideEffect.}
proc `shr` *(x, y: int32): int32 {.magic: "ShrI", noSideEffect.}
proc `shr` *(x, y: int64): int64 {.magic: "ShrI64", noSideEffect.}
## 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.}
## 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.}
## 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.}
## 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.}
## 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: "LeI64", noSideEffect.}
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.}
## Compares two integers for equality.
# 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: "UnaryMinusF64", 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.}
## 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:
proc `&` * (x: string, y: char): string {.magic: "ConStrStr", noSideEffect.}
proc `&` * (x: char, y: char): string {.magic: "ConStrStr", noSideEffect.}
proc `&` * (x, y: string): string {.magic: "ConStrStr", noSideEffect.}
proc `&` * (x: char, y: string): string {.magic: "ConStrStr", noSideEffect.}
proc `&` * (x: string, y: char): string {.
magic: "ConStrStr", noSideEffect, merge.}
proc `&` * (x: char, y: char): string {.
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`.
proc add * (x: var string, y: char) {.magic: "AppendStrCh".}
@ -466,7 +652,7 @@ proc repr*[T](x: T): string {.magic: "Repr", noSideEffect.}
type
TAddress* = int
## is the signed integer type that should be used for converting
## pointers to integer addresses.
## pointers to integer addresses for readability.
type
BiggestInt* = int64
@ -500,7 +686,7 @@ type # these work for most platforms:
## This is the same as the type ``long double`` in *C*.
## 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*.
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``
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.
isMainModule* {.magic: "IsMainModule".}: bool = false
## is true only when accessed in the main module. This works thanks to
## compiler magic. It is useful to embed testing code in a module.
CompileDate* {.magic: "CompileDate"}: string = "0000-00-00"
## 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"
## 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"
## is the version of Nimrod as a string.
## This works thanks to compiler magic.
NimrodMajor* {.magic: "NimrodMajor"}: int = 0
## is the major number of Nimrod's version.
## This works thanks to compiler magic.
NimrodMinor* {.magic: "NimrodMinor"}: int = 0
## is the minor number of Nimrod's version.
## This works thanks to compiler magic.
NimrodPatch* {.magic: "NimrodPatch"}: int = 0
## is the patch number of Nimrod's version.
## This works thanks to compiler magic.
cpuEndian* {.magic: "CpuEndian"}: TEndian = littleEndian
## is the endianness of the target CPU. This is a valuable information
## for low-level code only.
## is the endianness of the target CPU. This is a valuable piece of
## information for low-level code only. This works thanks to compiler magic.
proc toFloat*(i: int): float {.
magic: "ToFloat", noSideEffect, importc: "toFloat".}
## converts an integer `i` into a ``float``. If the conversion
## fails, `EInvalidValue` is raised. Note that on most platforms the
## conversion cannot fail, however.
## fails, `EInvalidValue` is raised. However, on most platforms the
## conversion cannot fail.
proc toBiggestFloat*(i: biggestint): biggestfloat {.
magic: "ToBiggestFloat", noSideEffect, importc: "toBiggestFloat".}
## converts an biggestint `i` into a ``biggestfloat``. If the conversion
## fails, `EInvalidValue` is raised. Note that on most platforms the
## conversion cannot fail, however.
## fails, `EInvalidValue` is raised. However, on most platforms the
## conversion cannot fail.
proc toInt*(f: float): int {.
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
## 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.}
## adds/registers a quit procedure. Each call to ``addQuitProc``
## registers another quit procedure. Up to 30 procedures can be
@ -636,33 +812,29 @@ proc equalMem*(a, b: Pointer, size: int): bool {.
## *unsafe*.
const
mallocHeader = if defined(useDL): "dlmalloc.h" else: "<stdlib.h>"
mallocHeader = "<stdlib.h>"
proc alloc*(size: int): pointer {.
importc: if defined(useDL): "dlmalloc" else: "malloc",
header: mallocHeader, noconv.}
importc: "malloc", header: mallocHeader, noconv.}
## allocates a new memory block with at least ``size`` bytes. The
## block has to be freed with ``realloc(block, 0)`` or
## ``dealloc(block)``. The block is not initialized, so reading
## from it before writing to it is undefined behaviour!
proc alloc0*(size: int): pointer {.
importc: if defined(useDL): "DL_ALLOC_0" else: "ALLOC_0",
header: mallocHeader, noconv.}
importc: "ALLOC_0", header: mallocHeader, noconv.}
## allocates a new memory block with at least ``size`` bytes. The
## block has to be freed with ``realloc(block, 0)`` or
## ``dealloc(block)``. The block is initialized with all bytes
## containing zero, so it is somewhat safer than ``alloc``.
proc realloc*(p: Pointer, newsize: int): pointer {.
importc: if defined(useDL): "dlrealloc" else: "realloc",
header: mallocHeader, noconv.}
importc: "realloc", header: mallocHeader, noconv.}
## 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
## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil**
## ``realloc`` calls ``dealloc(p)``. In other cases the block has to
## be freed with ``dealloc``.
proc dealloc*(p: Pointer) {.
importc: if defined(useDL): "dlfree" else: "free",
header: mallocHeader, noconv.}
importc: "free", header: mallocHeader, noconv.}
## frees the memory allocated with ``alloc``, ``alloc0`` or
## ``realloc``. This procedure is dangerous! If one forgets to
## 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
## ``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
## treats `x` and `y` as unsigned and compares them.
## Returns true iff ``unsigned(x) >= unsigned(y)``.
@ -803,17 +902,19 @@ proc getRefcount*[T](x: ref T): int {.importc: "getRefcount".}
## value is implementation-dependant.
#proc writeStackTrace() {.export: "writeStackTrace".}
proc getCurrentExceptionMsg*(): string {.exportc.}
## retrieves the error message that was attached to the current
## exception; if there is none, "" is returned.
when not defined(NimrodVM):
proc getCurrentExceptionMsg*(): string {.exportc.}
## retrieves the error message that was attached to the current
## exception; if there is none, "" is returned.
# new constants:
const
inf* {.magic: "Inf".} = 0.0
inf* {.magic: "Inf".} = 1.0 / 0.0
## 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.
nan* {.magic: "NaN".} = 0.0
nan* {.magic: "NaN".} = 0.0 / 0.0
## contains an IEEE floating point value of *Not A Number*. Note
## that you cannot compare a floating point value to this value
## 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.
# 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
## returns the number of bytes that are owned by the process and hold data.
proc getOccupiedMem*(): int
## returns the number of bytes that are owned by the process and hold data.
proc getFreeMem*(): int
## returns the number of bytes that are owned by the process, but do not
## hold any meaningful data.
proc getFreeMem*(): int
## returns the number of bytes that are owned by the process, but do not
## hold any meaningful data.
proc getTotalMem*(): int
## returns the number of bytes that are owned by the process.
proc getTotalMem*(): int
## returns the number of bytes that are owned by the process.
iterator countdown*[T](a, b: T, step = 1): T {.inline.} =
@ -906,7 +1003,6 @@ iterator items*(a: cstring): char {.inline.} =
yield a[i]
inc(i)
proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil".}
proc isNil*[T](x: ref T): 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.
proc `&` *[T](x, y: seq[T]): seq[T] {.noSideEffect.} =
result = []
setLen(result, x.len + y.len)
newSeq(result, x.len + y.len)
for i in 0..x.len-1:
result[i] = x[i]
for i in 0..y.len-1:
result[i] = y[i]
proc `&` *[T](x: seq[T], y: T): seq[T] {.noSideEffect.} =
result = []
setLen(x.len + 1)
newSeq(result, x.len + 1)
for i in 0..x.len-1:
result[i] = x[i]
result[x.len] = y
proc `&` *[T](x: T, y: seq[T]): seq[T] {.noSideEffect.} =
result = []
setLen(y.len + 1)
newSeq(result, y.len + 1)
for i in 0..y.len-1:
result[i] = y[i]
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.} =
return [x, y]
when not defined(ECMAScript): # XXX make this local procs
proc seqToPtr*[T](x: seq[T]): pointer {.inline, nosideeffect.} =
result = cast[pointer](x)
else:
proc seqToPtr*[T](x: seq[T]): pointer {.pure, nosideeffect.} =
asm """return `x`"""
when not defined(NimrodVM):
when not defined(ECMAScript):
# XXX make this local procs
proc seqToPtr*[T](x: seq[T]): pointer {.inline, nosideeffect.} =
result = cast[pointer](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.} =
## 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 find*[T, S](a: T, item: S): int {.inline.} =
## Returns the first index of `item` in `a` or -1 if not found. This requires
## appropriate `==` and `items` procs to work.
result = 0
for i in items(a):
if i == item: return
inc(result)
result = -1
# ----------------- FPU ------------------------------------------------------
@ -985,7 +1089,7 @@ proc GC_enable*()
proc GC_fullCollect*()
## 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
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
## 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.
{.push checks: off, line_dir: off, debugger: off,
assertions: on.} # obviously we cannot generate checking operations here :-)
# because it would yield into an endless recursion
# however, stack-traces are available for most parts
# of the code
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.}
# obviously we cannot generate checking operations here :-)
# because it would yield into an endless recursion
# however, stack-traces are available for most parts
# of the code
proc echo*[Ty](x: Ty) {.inline.}
## equivalent to ``writeln(stdout, x); flush(stdout)``. BUT: This is
@ -1025,7 +1145,29 @@ template newException(exceptn, message: expr): expr =
e.msg = message
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
@ -1036,6 +1178,7 @@ when not defined(EcmaScript):
strDesc.size = sizeof(string)
strDesc.kind = tyString
strDesc.flags = {ntfAcyclic}
initGC() # BUGFIX: need to be called here!
{.push stack_trace: off.}
@ -1043,12 +1186,12 @@ when not defined(EcmaScript):
include ansi_c
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):
# work-around C's sucking abstraction:
# 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",
header: "<io.h>".}
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
## at the end.
TFileHandle* = cint ## type that represents an OS file handle; this is
## useful for low-level file access
# text file handling:
var
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
## (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.}
## Closes the file.
proc EndOfFile*(f: TFile): Bool
@ -1201,6 +1353,15 @@ when not defined(EcmaScript):
yield res
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
@ -1211,10 +1372,10 @@ when not defined(EcmaScript):
# sequence type declarations here because the GC needs them too:
type
TGenericSeq {.importc, nodecl, final.} = object
TGenericSeq {.compilerproc, pure.} = object
len, space: int
PGenericSeq {.importc, nodecl.} = ptr TGenericSeq
PGenericSeq {.exportc.} = ptr TGenericSeq
const
GenericSeqSize = (2 * sizeof(int))
@ -1235,10 +1396,32 @@ when not defined(EcmaScript):
{.push stack_trace: off.}
when defined(endb):
include debugger
when defined(profiler):
include profiler
{.pop.} # stacktrace
else:
elif defined(ecmaScript):
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

View file

@ -23,8 +23,8 @@ type
TWeekDay* = enum ## represents a weekday
dMon, dTue, dWed, dThu, dFri, dSat, dSun
TTime* {.importc: "time_t", final.} = object ## abstract type that
## represents a time
TTime* {.importc: "time_t", header: "<time.h>", final.} = object ## abstract type that
## represents a time
when defined(ECMAScript):
getDay: 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.
proc `$` *(timeInfo: TTimeInfo): string
## converts a `TTimeInfo` object to a
## string representation.
## converts a `TTimeInfo` object to a string representation.
proc `$` *(time: TTime): string
## converts a calendar time to a
## string representation.
## converts a calendar time to a string representation.
proc getDateStr*(): string
## gets the current date as a string of the format
@ -111,6 +109,14 @@ proc getClockStr*(): string
proc `-` *(a, b: TTime): int64
## 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
## get the miliseconds from the start of the program
@ -162,7 +168,7 @@ when not defined(ECMAScript):
result.hour = int(tm.hour)
result.monthday = int(tm.monthday)
result.month = TMonth(tm.month)
result.year = tm.year + 1900
result.year = tm.year + 1900'i32
result.weekday = weekDays[int(tm.weekDay)]
result.yearday = int(tm.yearday)
@ -180,8 +186,7 @@ when not defined(ECMAScript):
result.isdst = -1
proc `-` (a, b: TTime): int64 =
return toInt(difftime(a, b)) # XXX: toBiggestInt is needed here, but
# Nim does not support it!
return toBiggestInt(difftime(a, b))
proc getStartMilsecs(): int = return clock() div (clocksPerSec div 1000)
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
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 =
return $asctime(timeInfoToTM(timeInfo))
# BUGFIX: asctime returns a newline at the end!
var p = asctime(timeInfoToTM(timeInfo))
result = toStringTillNL(p)
proc `$`(time: TTime): string =
# BUGFIX: ctime returns a newline at the end!
var a = time
return $ctime(addr(a))
return toStringTillNL(ctime(addr(a)))
else:
proc getTime(): TTime {.importc: "new Date", nodecl.}

View file

@ -1,7 +1,7 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2006 Andreas Rumpf
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@ -9,7 +9,7 @@
type
TUniChar* = int32 ## type that can hold any Unicode character
TUniChar16* = int16 ##
TUniChar16* = int16 ## 16 bit Unicode character
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
# (c) 2007 Andreas Rumpf
.PHONY : all
all:
python koch.py all
python koch.py boot -d:release
.PHONY : install
install:
python koch.py install
sh install.sh /usr/bin
.PHONY : 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 ----------------------------------
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);
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);
// ------------- 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 lookupInRecord(n: PNode; field: PIdent): PSym;
@ -181,6 +155,24 @@ function getModule(s: PSym): PSym;
function mustRehash(len, counter: int): bool;
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
function lookupInRecord(n: PNode; field: PIdent): PSym;
@ -281,14 +273,14 @@ begin
result := nil;
res := '"' + '';
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;
app(result, toRope(res));
res := '"'+''; // reset
end;
res := res +{&} toYamlChar(s[i]);
end;
res := res + '"';
addChar(res, '"');
app(result, toRope(res));
end;
@ -349,16 +341,16 @@ begin
toRope(toLinenumber(info)), toRope(toColumn(info))]);
end;
function treeToYamlAux(n: PNode; var marker: TObjectSet;
function treeToYamlAux(n: PNode; var marker: TIntSet;
indent: int; maxRecDepth: int): PRope;
forward;
function symToYamlAux(n: PSym; var marker: TObjectSet;
function symToYamlAux(n: PSym; var marker: TIntSet;
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;
function strTableToYaml(const n: TStrTable; var marker: TObjectSet;
function strTableToYaml(const n: TStrTable; var marker: TIntSet;
indent: int; maxRecDepth: int): PRope;
var
istr: PRope;
@ -396,14 +388,14 @@ begin
appf(result, '$n$1}', [spaces(indent)]);
end;
function symToYamlAux(n: PSym; var marker: TObjectSet;
function symToYamlAux(n: PSym; var marker: TIntSet;
indent: int; maxRecDepth: int): PRope;
var
ast: PRope;
begin
if n = nil then
result := toRope('null')
else if ObjectSetContainsOrIncl(marker, n) then
else if IntSetContainsOrIncl(marker, n.id) then
result := ropef('"$1 @$2"', [
toRope(n.name.s),
toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))])
@ -424,12 +416,12 @@ begin
// YYY: backend info?
end;
function typeToYamlAux(n: PType; var marker: TObjectSet;
function typeToYamlAux(n: PType; var marker: TIntSet;
indent: int; maxRecDepth: int): PRope;
begin
if n = nil then
result := toRope('null')
else if objectSetContainsOrIncl(marker, n) then
else if intSetContainsOrIncl(marker, n.id) then
result := ropef('"$1 @$2"', [
toRope(typeKindToStr[n.kind]),
toRope(strutils.toHex({@cast}TAddress(n), sizeof(n)*2))])
@ -446,7 +438,7 @@ begin
end
end;
function treeToYamlAux(n: PNode; var marker: TObjectSet; indent: int;
function treeToYamlAux(n: PNode; var marker: TIntSet; indent: int;
maxRecDepth: int): PRope;
var
istr: PRope;
@ -503,25 +495,25 @@ end;
function treeToYaml(n: PNode; indent: int = 0; maxRecDepth: int = -1): PRope;
var
marker: TObjectSet;
marker: TIntSet;
begin
initObjectSet(marker);
IntSetInit(marker);
result := treeToYamlAux(n, marker, indent, maxRecDepth)
end;
function typeToYaml(n: PType; indent: int = 0; maxRecDepth: int = -1): PRope;
var
marker: TObjectSet;
marker: TIntSet;
begin
initObjectSet(marker);
IntSetInit(marker);
result := typeToYamlAux(n, marker, indent, maxRecDepth)
end;
function symToYaml(n: PSym; indent: int = 0; maxRecDepth: int = -1): PRope;
var
marker: TObjectSet;
marker: TIntSet;
begin
initObjectSet(marker);
IntSetInit(marker);
result := symToYamlAux(n, marker, indent, maxRecDepth)
end;
@ -617,7 +609,7 @@ const
EmptySeq = nil;
{@emit
const
EmptySeq = [];
EmptySeq = @[];
}
function nextTry(h, maxHash: THash): THash;
@ -661,11 +653,12 @@ var
n: TObjectSeq;
i: int;
begin
{@ignore}
n := emptySeq;
setLength(n, length(t.data) * growthFactor);
{@ignore}
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
if t.data[i] <> nil then objectSetRawInsert(n, t.data[i]);
{@ignore}
@ -769,11 +762,12 @@ var
n: TPairSeq;
i: int;
begin
{@ignore}
n := emptySeq;
setLength(n, length(t.data) * growthFactor);
{@ignore}
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
if t.data[i].key <> nil then
TableRawInsert(n, t.data[i].key, t.data[i].val);
@ -833,11 +827,12 @@ var
n: TSymSeq;
i: int;
begin
{@ignore}
n := emptySeq;
setLength(n, length(t.data) * growthFactor);
{@ignore}
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
if t.data[i] <> nil then StrTableRawInsert(n, t.data[i]);
{@ignore}
@ -1022,13 +1017,13 @@ begin
result := false
end;
function IdTableRawGet(const t: TIdTable; key: PIdObj): int;
function IdTableRawGet(const t: TIdTable; key: int): int;
var
h: THash;
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
if (t.data[h].key.id = key.id) then begin
if (t.data[h].key.id = key) then begin
result := h; exit
end;
h := nextTry(h, high(t.data))
@ -1040,12 +1035,21 @@ function IdTableHasObjectAsKey(const t: TIdTable; key: PIdObj): bool;
var
index: int;
begin
index := IdTableRawGet(t, key);
index := IdTableRawGet(t, key.id);
if index >= 0 then result := t.data[index].key = key
else result := false
end;
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
index: int;
begin
@ -1074,18 +1078,18 @@ var
index, i: int;
n: TIdPairSeq;
begin
index := IdTableRawGet(t, key);
index := IdTableRawGet(t, key.id);
if index >= 0 then begin
assert(t.data[index].key <> nil);
t.data[index].val := val
end
else begin
if mustRehash(length(t.data), t.counter) then begin
{@emit n := [];}
setLength(n, length(t.data) * growthFactor);
{@ignore}
setLength(n, length(t.data) * growthFactor);
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
if t.data[i].key <> nil then
IdTableRawInsert(n, t.data[i].key, t.data[i].val);
@ -1166,11 +1170,11 @@ begin
end
else begin
if mustRehash(length(t.data), t.counter) then begin
{@emit n := [];}
setLength(n, length(t.data) * growthFactor);
{@ignore}
setLength(n, length(t.data) * growthFactor);
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
if t.data[i].key <> nil then
IdNodeTableRawInsert(n, t.data[i].key, t.data[i].val);
@ -1185,156 +1189,86 @@ begin
end;
end;
// ---------------- efficient integer sets ----------------------------------
// Same algorithm as the one the GC uses
// ------------- int-to-int-mapping ------------------------------------------
procedure IntSetInit(var s: TIntSet);
procedure initIITable(out x: TIITable);
var
i: int;
begin
x.counter := 0;
{@ignore}
fillChar(s, sizeof(s), 0);
setLength(x.data, startSize);
{@emit
s.data := []; }
setLength(s.data, InitIntSetSize);
{@ignore}
fillChar(s.data[0], length(s.data)*sizeof(s.data[0]), 0);
{@emit}
s.max := InitIntSetSize-1;
s.counter := 0;
s.head := nil
newSeq(x.data, startSize); }
for i := 0 to startSize-1 do x.data[i].key := InvalidKey;
end;
function IntSetGet(const t: TIntSet; key: int): PTrunk;
function IITableRawGet(const t: TIITable; key: int): int;
var
h: int;
h: THash;
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
h := key and high(t.data); // start with real hash value
while t.data[h].key <> InvalidKey do begin
if (t.data[h].key = key) then begin
result := h; exit
end;
h := nextTry(h, t.max)
h := nextTry(h, high(t.data))
end;
result := nil
result := -1
end;
procedure IntSetRawInsert(const t: TIntSet; var data: TTrunkSeq;
desc: PTrunk);
function IITableGet(const t: TIITable; key: int): int;
var
h: int;
index: int;
begin
h := desc.key and t.max;
while data[h] <> nil do begin
assert(data[h] <> desc);
h := nextTry(h, t.max)
index := IITableRawGet(t, key);
if index >= 0 then result := t.data[index].val
else result := InvalidKey
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;
assert(data[h] = nil);
data[h] := desc
assert(data[h].key = InvalidKey);
data[h].key := key;
data[h].val := val;
end;
procedure IntSetEnlarge(var t: TIntSet);
procedure IITablePut(var t: TIITable; key, val: int);
var
n: TTrunkSeq;
i, oldMax: int;
index, i: int;
n: TIIPairSeq;
begin
oldMax := t.max;
t.max := ((t.max+1)*2)-1;
{@emit n := []}
setLength(n, t.max + 1);
{@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));
index := IITableRawGet(t, key);
if index >= 0 then begin
assert(t.data[index].key <> InvalidKey);
t.data[index].val := val
end
else begin
IntSetIncl(s, key);
result := false
end
if mustRehash(length(t.data), t.counter) then begin
{@ignore}
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.

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

View file

@ -7,16 +7,27 @@
// distribution, for details about the copyright.
//
//var
// newDummyVar: int; // just to check the rodgen mechanism
// ------------------------- Name Mangling --------------------------------
function mangle(const name: string): string;
var
i: int;
begin
if name[strStart] in ['A'..'Z', '0'..'9', 'a'..'z'] then
result := toUpper(name[strStart])+''
else
result := 'HEX' + toHex(ord(name[strStart]), 2);
case name[strStart] of
'a'..'z': begin
result := '';
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
case name[i] of
'A'..'Z': addChar(result, chr(ord(name[i]) - ord('A') + ord('a')));
@ -29,11 +40,28 @@ end;
function mangleName(s: PSym): PRope;
begin
result := ropef('$1_$2', [toRope(mangle(s.name.s)), 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])
result := s.loc.r;
if result = nil then begin
result := toRope(mangle(s.name.s));
app(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;
// ------------------------------ C type generator ------------------------
@ -44,7 +72,7 @@ begin
tyNone: result := ctVoid;
tyBool: result := ctBool;
tyChar: result := ctChar;
tyEmptySet, tySet: begin
tySet: begin
case int(getSize(typ)) of
1: result := ctInt8;
2: result := ctInt16;
@ -90,7 +118,8 @@ begin
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;
begin
@ -107,7 +136,8 @@ begin
result := true
else begin
case mapType(rettype) of
ctArray: result := true;
ctArray:
result := not (skipGeneric(rettype).kind in [tyVar, tyRef, tyPtr]);
ctStruct: result := needsComplexAssignment(skipGeneric(rettype));
else result := false;
end
@ -119,18 +149,20 @@ const
'N_STDCALL', 'N_CDECL', 'N_SAFECALL', 'N_SYSCALL',
// this is probably not correct for all platforms,
// 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;
begin
// 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;
function getTempName(): PRope;
begin
inc(gUnique);
result := con('T'+'', toRope(gUnique))
result := con('TMP', toRope(gId));
inc(gId);
end;
function ccgIntroducedPtr(s: PSym): bool;
@ -166,7 +198,8 @@ begin
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
i, j: int;
param: PSym;
@ -177,12 +210,12 @@ begin
// C cannot return arrays (what a poor language...)
rettype := toRope('void')
else
rettype := getTypeDesc(m, t.sons[0]);
rettype := getTypeDescAux(m, t.sons[0], check);
for i := 1 to sonsLen(t.n)-1 do begin
if t.n.sons[i].kind <> nkSym then InternalError(t.n.info, 'genProcParams');
param := t.n.sons[i].sym;
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
app(params, '*'+'');
include(param.loc.flags, lfIndirect);
@ -203,7 +236,7 @@ begin
end;
if (t.sons[0] <> nil) and isInvalidReturnType(t.sons[0]) then begin
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, '*'+'');
app(params, ' Result');
end;
@ -227,25 +260,16 @@ begin
result := (t.sym <> nil) and (sfImportc in t.sym.flags)
end;
function getTypeName(typ: PType): PRope;
function typeNameOrLiteral(t: PType; const literal: string): 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
end;
function typeNameOrLiteral(typ: PType; const literal: string): PRope;
begin
if isImportedType(typ) then
result := getTypeName(typ)
if (t.sym <> nil) and (sfImportc in t.sym.flags) and
(t.sym.magic = mNone) then
result := getTypeName(t)
else
result := toRope(literal)
end;
function getSimpleTypeDesc(typ: PType): PRope;
function getSimpleTypeDesc(m: BModule; typ: PType): PRope;
const
NumericalTypeToStr: array [tyInt..tyFloat128] of string = (
'NI', 'NI8', 'NI16', 'NI32', 'NI64', 'NF', 'NF32', 'NF64', 'NF128');
@ -267,14 +291,17 @@ begin
end
end
end;
tyString: result := typeNameOrLiteral(typ, 'string');
tyString: begin
useMagic(m, 'NimStringDesc');
result := typeNameOrLiteral(typ, 'NimStringDesc*');
end;
tyCstring: result := typeNameOrLiteral(typ, 'NCSTRING');
tyBool: result := typeNameOrLiteral(typ, 'NIM_BOOL');
tyChar: result := typeNameOrLiteral(typ, 'NIM_CHAR');
tyNil: result := typeNameOrLiteral(typ, '0'+'');
tyInt..tyFloat128:
result := typeNameOrLiteral(typ, NumericalTypeToStr[typ.Kind]);
tyRange: result := getSimpleTypeDesc(typ.sons[0]);
tyRange: result := getSimpleTypeDesc(m, typ.sons[0]);
else result := nil;
end
end;
@ -284,7 +311,7 @@ begin
if typ = nil then
result := toRope('void')
else begin
result := getSimpleTypeDesc(typ);
result := getSimpleTypeDesc(m, typ);
if result = nil then
result := CacheGetType(m.typeCache, typ)
end
@ -325,7 +352,7 @@ begin
end;
function genRecordFieldsAux(m: BModule; n: PNode; accessExpr: PRope;
rectype: PType): PRope;
rectype: PType; var check: TIntSet): PRope;
var
i: int;
ae, uname, sname, a: PRope;
@ -336,13 +363,14 @@ begin
case n.kind of
nkRecList: 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;
nkRecCase: begin
if (n.sons[0].kind <> nkSym) then
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');
if accessExpr <> nil then ae := ropef('$1.$2', [accessExpr, uname])
else ae := uname;
@ -354,14 +382,14 @@ begin
if k.kind <> nkSym then begin
sname := con('S'+'', toRope(i));
a := genRecordFieldsAux(m, k, ropef('$1.$2', [ae, sname]),
rectype);
rectype, check);
if a <> nil then begin
app(result, 'struct {');
app(result, a);
appf(result, '} $1;$n', [sname]);
end
end
else app(result, genRecordFieldsAux(m, k, ae, rectype));
else app(result, genRecordFieldsAux(m, k, ae, rectype, check));
end;
else internalError('genRecordFieldsAux(record case branch)');
end;
@ -375,18 +403,19 @@ begin
if accessExpr <> nil then ae := ropef('$1.$2', [accessExpr, sname])
else ae := sname;
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;
else internalError(n.info, 'genRecordFieldsAux()');
end
end;
function getRecordFields(m: BModule; typ: PType): PRope;
function getRecordFields(m: BModule; typ: PType; var check: TIntSet): PRope;
begin
result := genRecordFieldsAux(m, typ.n, nil, typ);
result := genRecordFieldsAux(m, typ.n, nil, typ, check);
end;
function getRecordDesc(m: BModule; typ: PType; name: PRope): PRope;
function getRecordDesc(m: BModule; typ: PType; name: PRope;
var check: TIntSet): PRope;
var
desc: PRope;
hasField: bool;
@ -406,18 +435,18 @@ begin
end
else if gCmd = cmdCompileToCpp then begin
result := ropef('struct $1 : public $2 {$n',
[name, getTypeDesc(m, typ.sons[0])]);
[name, getTypeDescAux(m, typ.sons[0], check)]);
hasField := true
end
else begin
result := ropef('struct $1 {$n $2 Sup;$n',
[name, getTypeDesc(m, typ.sons[0])]);
[name, getTypeDescAux(m, typ.sons[0], check)]);
hasField := true
end
end
else
result := ropef('struct $1 {$n', [name]);
desc := getRecordFields(m, typ);
desc := getRecordFields(m, typ, check);
if (desc = nil) and not hasField then
// no fields in struct are not valid in C, so generate a dummy:
appf(result, 'char dummy;$n', [])
@ -435,7 +464,7 @@ begin
m.typeStack[L] := typ;
end;
function getTypeDesc(m: BModule; typ: PType): PRope;
function getTypeDescAux(m: BModule; typ: PType; var check: TIntSet): PRope;
// returns only the type's name
var
name, rettype, desc, recdesc: PRope;
@ -443,12 +472,18 @@ var
t, et: PType;
begin
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);
result := getTypePre(m, t);
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
tyRef, tyPtr, tyVar, tyOpenArray: begin
tyRef, tyPtr, tyVar: begin
et := getUniqueType(t.sons[0]);
if et.kind in [tyArrayConstr, tyArray, tyOpenArray] then
et := getUniqueType(elemType(et));
@ -469,15 +504,20 @@ begin
end;
else begin
// else we have a strong dependency :-(
result := con(getTypeDesc(m, et), '*'+'');
result := con(getTypeDescAux(m, et, check), '*'+'');
IdTablePut(m.typeCache, t, result)
end
end
end;
tyOpenArray: begin
et := getUniqueType(t.sons[0]);
result := con(getTypeDescAux(m, et, check), '*'+'');
IdTablePut(m.typeCache, t, result)
end;
tyProc: begin
result := getTypeName(t);
IdTablePut(m.typeCache, t, result);
genProcParams(m, t, rettype, desc);
genProcParams(m, t, rettype, desc, check);
if not isImportedType(t) then begin
if t.callConv <> ccClosure then
appf(m.s[cfsTypes], 'typedef $1_PTR($2, $3) $4;$n',
@ -501,12 +541,14 @@ begin
end;
assert(CacheGetType(m.typeCache, t) = nil);
IdTablePut(m.typeCache, t, con(result, '*'+''));
if not isImportedType(t) then
if not isImportedType(t) then begin
useMagic(m, 'TGenericSeq');
appf(m.s[cfsSeqTypes],
'struct $2 {$n' +
' NI len, space;$n' +
' TGenericSeq Sup;$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, '*'+'');
end;
tyArrayConstr, tyArray: begin
@ -516,7 +558,7 @@ begin
IdTablePut(m.typeCache, t, result);
if not isImportedType(t) then
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;
tyObject, tyTuple: begin
result := CacheGetType(m.forwTypeCache, t);
@ -528,7 +570,8 @@ begin
IdTablePut(m.forwTypeCache, t, result)
end;
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);
end;
tySet: begin
@ -546,14 +589,22 @@ begin
end
end
end;
tyGenericInst: result := getTypeDesc(m, lastSon(t));
tyGenericInst: result := getTypeDescAux(m, lastSon(t), check);
else begin
InternalError('getTypeDesc(' + typeKindToStr[t.kind] + ')');
InternalError('getTypeDescAux(' + typeKindToStr[t.kind] + ')');
result := nil
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);
var
i: int;
@ -568,14 +619,16 @@ end;
function genProcHeader(m: BModule; prc: PSym): PRope;
var
rettype, params: PRope;
check: TIntSet;
begin
// using static is needed for inline procs
if (prc.typ.callConv = ccInline) then
result := toRope('static ')
else
result := nil;
IntSetInit(check);
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',
[toRope(CallingConvToStr[prc.typ.callConv]),
rettype, prc.loc.r, params])
@ -583,25 +636,33 @@ end;
// ----------------------- type information ----------------------------------
var
gTypeInfoGenerated: TIntSet;
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
tmp: PRope;
begin
tmp := getTempName();
appf(m.s[cfsTypeInit1], 'static TNimType $1;$n', [tmp]);
tmp := getNimType(m);
appf(m.s[cfsTypeInit2], '$2 = &$1;$n', [tmp, name]);
end;
procedure genTypeInfoAuxBase(m: BModule; typ: PType; name, base: PRope);
var
nimtypeKind: int;
nimtypeKind, flags: int;
begin
allocMemTI(m, name);
allocMemTI(m, typ, name);
if (typ.kind = tyObject) and (tfFinal in typ.flags)
and (typ.sons[0] = nil) then
nimtypeKind := ord(high(TTypeKind))+1 // tyPureObject
@ -612,7 +673,15 @@ begin
'$1->kind = $3;$n' +
'$1->base = $4;$n', [
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;
procedure genTypeInfoAux(m: BModule; typ: PType; name: PRope);
@ -643,10 +712,8 @@ begin
appf(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n',
[tmp, toRope(len)]);
for i := 0 to len-1 do begin
tmp2 := getTempName();
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp2]);
appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n',
[tmp, toRope(i), tmp2]);
tmp2 := getNimNode(m);
appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n', [tmp, toRope(i), tmp2]);
genObjectFields(m, typ, n.sons[i], tmp2);
end;
appf(m.s[cfsTypeInit3],
@ -676,10 +743,8 @@ begin
[tmp, toRope(lengthOrd(field.typ)+1)]);
for i := 1 to len-1 do begin
b := n.sons[i]; // branch
tmp2 := getTempName();
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp2]);
tmp2 := getNimNode(m);
genObjectFields(m, typ, lastSon(b), tmp2);
//writeln(output, renderTree(b.sons[j]));
case b.kind of
nkOfBranch: begin
if sonsLen(b) < 2 then
@ -728,42 +793,54 @@ var
begin
if typ.kind = tyObject then genTypeInfoAux(m, typ, name)
else genTypeInfoAuxBase(m, typ, name, toRope('0'+''));
tmp := getTempName();
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp]);
tmp := getNimNode(m);
genObjectFields(m, typ, typ.n, tmp);
appf(m.s[cfsTypeInit3], '$1->node = &$2;$n', [name, tmp]);
end;
procedure genEnumInfo(m: BModule; typ: PType; name: PRope);
var
tmp, tmp2, tmp3: PRope;
len, i: int;
nodePtrs, elemNode, enumNames, enumArray, counter, specialCases: PRope;
len, i, firstNimNode: int;
field: PSym;
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);
tmp := getTempName();
tmp2 := getTempName();
nodePtrs := getTempName();
len := sonsLen(typ.n);
appf(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n' +
'static TNimNode $3;$n',
[tmp, toRope(len), tmp2]);
appf(m.s[cfsTypeInit1], 'static TNimNode* $1[$2];$n', [nodePtrs, toRope(len)]);
enumNames := nil;
specialCases := nil;
firstNimNode := m.typeNodes;
for i := 0 to len-1 do begin
assert(typ.n.sons[i].kind = nkSym);
field := typ.n.sons[i].sym;
tmp3 := getTempName();
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp3]);
appf(m.s[cfsTypeInit3], '$1[$2] = &$3;$n' +
'$3.kind = 1;$n' +
'$3.offset = $4;$n' +
'$3.typ = $5;$n' +
'$3.name = $6;$n',
[tmp, toRope(i), tmp3,
toRope(field.position),
name, makeCString(field.name.s)]);
elemNode := getNimNode(m);
app(enumNames, makeCString(field.name.s));
if i < len-1 then app(enumNames, ', '+tnl);
if field.position <> i then
appf(specialCases, '$1.offset = $2;$n', [elemNode, toRope(field.position)]);
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],
'$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;
procedure genSetInfo(m: BModule; typ: PType; name: PRope);
@ -772,8 +849,7 @@ var
begin
assert(typ.sons[0] <> nil);
genTypeInfoAux(m, typ, name);
tmp := getTempName();
appf(m.s[cfsTypeInit1], 'static TNimNode $1;$n', [tmp]);
tmp := getNimNode(m);
appf(m.s[cfsTypeInit3],
'$1.len = $2; $1.kind = 0;$n' +
'$3->node = &$1;$n', [tmp, toRope(firstOrd(typ)), name]);
@ -784,28 +860,96 @@ begin
genTypeInfoAuxBase(m, typ, name, genTypeInfo(m, typ.sons[1]));
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;
var
t: PType;
id: int;
dataGen: bool;
begin
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
// declare type information structures:
useMagic(m, 'TNimType');
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;
if IntSetContainsOrIncl(gTypeInfoGenerated, t.id) then exit;
if dataGen then exit;
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'+''));
tyRef, tyPtr, tySequence, tyRange: genTypeInfoAux(m, t, result);
tyArrayConstr, tyArray: genArrayInfo(m, t, result);
tySet: genSetInfo(m, t, result);
tyEnum: genEnumInfo(m, t, result);
tyObject, tyTuple: genObjectInfo(m, t, result);
tyVar: result := genTypeInfo(m, typ.sons[0]);
else InternalError('genTypeInfo(' + typekindToStr[t.kind] + ')');
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
// distribution, for details about the copyright.
//
unit ccgutils;
interface
@ -35,21 +34,28 @@ var
t: PType;
h: THash;
begin
// this was a hotspot in the compiler!
result := key;
if key = nil then exit;
assert(key.kind <> tyForward);
if key.kind = tyGenericInst then begin
result := GetUniqueType(lastSon(key));
exit
case key.Kind of
tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString,
tyInt..tyFloat128, tyProc, tyEnum, tyObject, tyAnyEnum: begin end;
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;
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;
function TableGetType(const tab: TIdTable; key: PType): PObject;
@ -102,7 +108,7 @@ begin
end;
res := res +{&} toCChar(s[i]);
end;
res := res +{&} '"'+'';
addChar(res, '"');
app(result, toRope(res));
end;

View file

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

View file

@ -16,7 +16,8 @@ interface
{$include 'config.inc'}
uses
nsystem, charsets, msgs;
nsystem, charsets, nos, msgs, options, nversion, condsyms, strutils, extccomp,
platform, lists, wordrecg;
procedure writeCommandLineUsage;
@ -33,10 +34,6 @@ procedure processSwitch(const switch, arg: string; pass: TCmdlinePass;
implementation
uses
options, nversion, condsyms, strutils, extccomp, platform, nos, lists,
wordrecg;
{@ignore}
const
{$ifdef fpc}
@ -54,19 +51,18 @@ const
const
Usage = ''
//[[[cog
//def f(x): return "+{&} '" + x.replace("'", "''")[:-1] + "' +{&} nl"
//for line in file("data/basicopt.txt"):
//from string import replace
//def f(x): return "+{&} '" + replace(x, "'", "''")[:-1] + "' +{&} nl"
//for line in open("data/basicopt.txt").readlines():
// cog.outl(f(line))
//]]]
+{&} 'Usage::' +{&} nl
+{&} ' nimrod command [options] inputfile [arguments]' +{&} nl
+{&} 'Command::' +{&} nl
+{&} ' compile compile project with default code generator (C)' +{&} nl
+{&} ' compile_to_c compile project with C code generator' +{&} nl
+{&} ' compile_to_cpp compile project with C++ code generator' +{&} nl
+{&} ' compile_to_ecmascript compile project to ECMAScript code (experimental)' +{&} nl
+{&} ' doc generate the documentation for inputfile;' +{&} nl
+{&} ' with --run switch opens it with $BROWSER' +{&} nl
+{&} ' compile, c compile project with default code generator (C)' +{&} nl
+{&} ' compile_to_c, cc compile project with C code generator' +{&} nl
+{&} ' doc generate the documentation for inputfile' +{&} nl
+{&} ' rst2html converts a reStructuredText file to HTML' +{&} nl
+{&} 'Arguments:' +{&} nl
+{&} ' arguments are passed to the program being run (if --run option is selected)' +{&} nl
+{&} 'Options:' +{&} nl
@ -74,7 +70,8 @@ const
+{&} ' -o, --out:FILE set the output filename' +{&} nl
+{&} ' -d, --define:SYMBOL define 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
+{&} ' --line_trace:on|off code generation for line trace ON|OFF' +{&} nl
+{&} ' --debugger:on|off turn Embedded Nimrod Debugger ON|OFF' +{&} nl
@ -95,7 +92,7 @@ const
AdvancedUsage = ''
//[[[cog
//for line in file("data/advopt.txt"):
//for line in open("data/advopt.txt").readlines():
// cog.outl(f(line))
//]]]
+{&} 'Advanced commands::' +{&} nl
@ -104,21 +101,17 @@ const
+{&} ' gen_depend generate a DOT file containing the' +{&} nl
+{&} ' module dependency graph' +{&} 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
+{&} ' 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
+{&} ' -w, --warnings:on|off warnings ON|OFF' +{&} nl
+{&} ' --warning[X]:on|off specific warning X ON|OFF' +{&} nl
+{&} ' --hints:on|off hints 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
+{&} ' -c, --compile_only compile only; do not assemble or 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
+{&} ' --os:SYMBOL set the target operating system (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
+{&} ' --gen_mapping generate a mapping file containing' +{&} 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
+{&} ' --checkpoints:on|off turn on|off checkpoints; for debugging Nimrod' +{&} nl
+{&} ' --skip_cfg do not read the general 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
+{&} ' --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
+{&} ' --putenv:key=value set an environment variable' +{&} nl
+{&} ' --list_cmd list the commands used to execute external programs' +{&} nl
+{&} ' -v, --verbose show what Nimrod is doing' +{&} nl
+{&} ' --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
+{&} ' --verbosity:0|1|2|3 set Nimrod''s verbosity level (0 is default)' +{&} nl
+{&} ' -v, --version show detailed version information' +{&} nl
//[[[end]]]
;
@ -212,7 +171,7 @@ begin
versionWritten := true;
helpWritten := true;
messageOut(format(HelpMessage, [VersionAsString, platform.os[hostOS].name,
cpu[hostCPU].name]) +{&} VersionInformation)
cpu[hostCPU].name]))
end
end;
@ -378,14 +337,10 @@ begin
if pass in {@set}[passCmd2, passPP] then
addFileToLink(arg);
end;
wDebuginfo:
include(gGlobalOptions, optCDebug);
wCompileOnly, wC:
include(gGlobalOptions, optCompileOnly);
wNoLinking:
include(gGlobalOptions, optNoLinking);
wForceBuild, wF:
include(gGlobalOptions, optForceFullMake);
wDebuginfo: include(gGlobalOptions, optCDebug);
wCompileOnly, wC: include(gGlobalOptions, optCompileOnly);
wNoLinking: include(gGlobalOptions, optNoLinking);
wForceBuild, wF: include(gGlobalOptions, optForceFullMake);
wGC: begin
case whichKeyword(arg) of
wBoehm: begin
@ -406,20 +361,13 @@ begin
liMessage(info, errNoneBoehmRefcExpectedButXFound, arg)
end
end;
wWarnings, wW:
ProcessOnOffSwitch({@set}[optWarns], arg, pass, info);
wWarning:
ProcessSpecificNote(arg, wWarning, pass, info);
wHint:
ProcessSpecificNote(arg, wHint, pass, info);
wHints:
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);
wWarnings, wW: ProcessOnOffSwitch({@set}[optWarns], arg, pass, info);
wWarning: ProcessSpecificNote(arg, wWarning, pass, info);
wHint: ProcessSpecificNote(arg, wHint, pass, info);
wHints: 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
ProcessOnOffSwitch({@set}[optEndb], arg, pass, info);
if optEndb in gOptions then
@ -427,26 +375,19 @@ begin
else
UndefSymbol('endb')
end;
wChecks, wX:
ProcessOnOffSwitch(checksOptions, arg, pass, info);
wObjChecks:
ProcessOnOffSwitch({@set}[optObjCheck], arg, pass, info);
wFieldChecks:
ProcessOnOffSwitch({@set}[optFieldCheck], arg, pass, info);
wRangeChecks:
ProcessOnOffSwitch({@set}[optRangeCheck], arg, pass, info);
wBoundChecks:
ProcessOnOffSwitch({@set}[optBoundsCheck], arg, pass, info);
wOverflowChecks:
ProcessOnOffSwitch({@set}[optOverflowCheck], arg, pass, info);
wLineDir:
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);
wProfiler: begin
ProcessOnOffSwitch({@set}[optProfiler], arg, pass, info);
if optProfiler in gOptions then DefineSymbol('profiler')
else UndefSymbol('profiler')
end;
wChecks, wX: ProcessOnOffSwitch(checksOptions, arg, pass, info);
wObjChecks: ProcessOnOffSwitch({@set}[optObjCheck], arg, pass, info);
wFieldChecks: ProcessOnOffSwitch({@set}[optFieldCheck], arg, pass, info);
wRangeChecks: ProcessOnOffSwitch({@set}[optRangeCheck], arg, pass, info);
wBoundChecks: ProcessOnOffSwitch({@set}[optBoundsCheck], arg, pass, info);
wOverflowChecks: ProcessOnOffSwitch({@set}[optOverflowCheck], arg, pass, info);
wLineDir: ProcessOnOffSwitch({@set}[optLineDir], arg, pass, info);
wAssertions, wA: ProcessOnOffSwitch({@set}[optAssert], arg, pass, info);
wOpt: begin
case whichKeyword(arg) of
wSpeed: begin
@ -505,10 +446,8 @@ begin
expectArg(switch, arg, pass, info);
options.addImplicitMod(arg);
end;
wListCmd:
include(gGlobalOptions, optListCmd);
wGenMapping:
include(gGlobalOptions, optGenMapping);
wListCmd: include(gGlobalOptions, optListCmd);
wGenMapping: include(gGlobalOptions, optGenMapping);
wOS: begin
if (pass = passCmd1) then begin
theOS := platform.NameToOS(arg);
@ -533,26 +472,18 @@ begin
end
end
end;
wRun, wR:
include(gGlobalOptions, optRun);
wVerbose, wV:
include(gGlobalOptions, optVerbose);
wMergeOutput:
include(gGlobalOptions, optMergeOutput);
wVersion:
writeVersionInfo(pass);
wAdvanced:
writeAdvancedUsage(pass);
wHelp, wH:
helpOnError(pass);
wCompileSys:
include(gGlobalOptions, optCompileSys);
wSkipCfg:
include(gGlobalOptions, optSkipConfigFile);
wSkipProjCfg:
include(gGlobalOptions, optSkipProjConfigFile);
wGenScript:
include(gGlobalOptions, optGenScript);
wRun, wR: include(gGlobalOptions, optRun);
wVerbosity: begin
expectArg(switch, arg, pass, info);
gVerbosity := parseInt(arg);
end;
wVersion, wV: writeVersionInfo(pass);
wAdvanced: writeAdvancedUsage(pass);
wHelp, wH: helpOnError(pass);
wSymbolFiles: ProcessOnOffSwitchG({@set}[optSymbolFiles], arg, pass, info);
wSkipCfg: include(gGlobalOptions, optSkipConfigFile);
wSkipProjCfg: include(gGlobalOptions, optSkipProjConfigFile);
wGenScript: include(gGlobalOptions, optGenScript);
wLib: begin
expectArg(switch, arg, pass, info);
libpath := processPath(arg)

View file

@ -6,7 +6,6 @@
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
unit condsyms;
// This module handles the conditional symbols.
@ -16,7 +15,7 @@ unit condsyms;
interface
uses
ast, astalgo, msgs, hashes, platform, strutils, idents;
nsystem, ast, astalgo, msgs, hashes, platform, strutils, idents;
var
gSymbols: TStrTable;
@ -29,6 +28,8 @@ procedure UndefSymbol(const symbol: string);
function isDefined(symbol: PIdent): Boolean;
procedure ListSymbols;
function countDefinedSymbols: int;
implementation
procedure DefineSymbol(const symbol: string);
@ -39,7 +40,12 @@ begin
i := getIdent(symbol);
sym := StrTableGet(gSymbols, i);
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);
end;
sym.position := 1;
@ -75,6 +81,19 @@ begin
MessageOut('-- End of list --');
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;
begin
initStrTable(gSymbols);
@ -92,7 +111,7 @@ begin
DefineSymbol('win32');
end;
osLinux, osMorphOS, osSkyOS, osIrix, osPalmOS, osQNX,
osAtari: begin
osAtari, osAix: begin
// these are all 'unix-like'
DefineSymbol('unix');
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
InitCrc32 = TCrc32(-1);
InitAdler32 = int32(1);
function updateCrc32(val: Byte; 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 updateAdler32(adler: int32; buf: pointer; len: int): int32;
implementation
{@ignore}
@ -121,12 +126,12 @@ const
function updateCrc32(val: Byte; crc: TCrc32): TCrc32; overload;
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;
function updateCrc32(val: Char; crc: TCrc32): TCrc32; overload;
begin
result := updateCrc32(ord(val), crc);
result := updateCrc32(byte(ord(val)), crc);
end;
function strCrc32(const s: string): TCrc32;
@ -173,6 +178,39 @@ begin
CloseFile(bin);
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}
{$ifdef Q_on}
{$undef Q_on}

View file

@ -114,11 +114,11 @@ begin
{@ignore}
fillChar(result^, sizeof(result^), 0);
{@emit
result.tocPart := [];
result.tocPart := @[];
}
result.filename := filename;
result.id := 100;
result.splitAfter := 25;
result.splitAfter := 20;
s := getConfigVar('split.item.toc');
if s <> '' then
result.splitAfter := parseInt(s);
@ -212,19 +212,51 @@ begin
'&': dest := dest + '&amp;';
'<': dest := dest + '&lt;';
'>': dest := dest + '&gt;';
'"': dest := dest + '&quot;';
else addChar(dest, c)
end
end;
function toXml(const s: string; splitAfter: int = -1): string;
function nextSplitPoint(const s: string; start: int): int;
var
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
result := '';
for i := strStart to length(s)+strStart-1 do begin
if (splitAfter >= 0) and ((i-strStart+1) mod splitAfter = 0) then
addChar(result, ' ');
addXmlChar(result, s[i])
if splitAfter >= 0 then begin
partLen := 0;
j := strStart;
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;

View file

@ -19,15 +19,17 @@ interface
uses
nsystem, ast, astalgo, strutils, hashes, trees, platform, magicsys,
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;
const filename: string): PBackend;
function ecmasgenPass(): TPass;
implementation
type
TEcmasGen = object(TBackend)
TEcmasGen = object(TPassContext)
filename: string;
module: PSym;
end;
BModule = ^TEcmasGen;
@ -93,7 +95,7 @@ begin
{@ignore}
fillChar(p, sizeof(p), 0);
{@emit
p.blocks := [];}
p.blocks := @[];}
p.options := options;
p.module := module;
p.procDef := procDef;
@ -103,8 +105,7 @@ end;
const
MappedToObject = {@set}[tyObject, tyArray, tyArrayConstr, tyTuple,
tyEmptySet, tyOpenArray, tySet, tyVar,
tyRef, tyPtr];
tyOpenArray, tySet, tyVar, tyRef, tyPtr];
function mapType(typ: PType): TEcmasTypeKind;
begin
@ -129,10 +130,10 @@ begin
end;
tyString, tySequence:
result := etyInt; // little hack to get the right semantics
tyObject, tyArray, tyArrayConstr, tyTuple, tyEmptySet, tyOpenArray:
tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray:
result := etyObject;
tyNil: result := etyNull;
tyGenericInst, tyGenericParam, tyGeneric, tyNone, tyForward:
tyGenericInst, tyGenericParam, tyGeneric, tyNone, tyForward, tyEmpty:
result := etyNone;
tyProc: result := etyProc;
tyCString: result := etyString;
@ -1832,38 +1833,56 @@ begin
end
end;
procedure finishModule(b: PBackend; n: PNode);
function myProcess(b: PPassContext; n: PNode): PNode;
var
m: BModule;
outfile: string;
p: TProc;
r: TCompRes;
code: PRope;
begin
result := n;
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);
genModule(p, n, r);
app(p.globals.code, p.data);
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;
function EcmasBackend(b: PBackend; module: PSym;
const filename: string): PBackend;
function myClose(b: PPassContext; n: PNode): PNode;
var
g: BModule;
m: BModule;
code: PRope;
outfile: string;
begin
g := newModule(module, filename);
g.backendCreator := EcmasBackend;
g.eventMask := {@set}[eAfterModule];
g.afterModuleEvent := finishModule;
result := g;
result := myProcess(b, n);
m := BModule(b);
if sfMainModule in m.module.flags then begin
// write the file:
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.

File diff suppressed because it is too large Load diff

View file

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

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;
{$include 'config.inc'}
interface
uses

View file

@ -358,7 +358,7 @@ begin
end
end;
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;
end;
@ -633,7 +633,7 @@ begin
end
end;
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;
end;
@ -711,7 +711,7 @@ begin
langCsharp: csharpNextToken(g);
langC: cNextToken(g);
langJava: javaNextToken(g);
else assert(false);
else InternalError('getNextToken');
end
end;

View file

@ -30,7 +30,7 @@ type
s: string;
next: PIdent; // for hash-table chaining
h: THash; // hash value of s
end;
end {@acyclic};
function getIdent(const identifier: string): PIdent; overload;
function getIdent(const identifier: string; h: THash): PIdent; overload;

View file

@ -6,9 +6,26 @@
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
unit importer;
// This module implements the symbol importing mechanism.
interface
{$include 'config.inc'}
uses
nsystem, charsets, strutils, nos,
ast, astalgo, msgs, options, idents, rodread, lookups, semdata, passes;
function evalImport(c: PContext; n: PNode): PNode;
function evalFrom(c: PContext; n: PNode): PNode;
procedure importAllSymbols(c: PContext; fromMod: PSym);
function getModuleFile(n: PNode): string;
implementation
function findModule(const info: TLineInfo; const modulename: string): string;
// returns path to module
begin
@ -41,32 +58,45 @@ var
check, copy, e: PSym;
j: int;
etyp: PType; // enumeration type
it: TIdentIter;
begin
//copy := copySym(s, true);
//copy.ast := s.ast;
// This does not handle stubs, because otherwise loading on demand would be
// basically pointless. So importing stubs is fine here!
copy := s; // do not copy symbols when importing!
// check if we have already a symbol of the same name:
check := StrTableGet(c.tab.stack[importTablePos], s.name);
if check <> nil then begin
if (check <> nil) and (check.id <> copy.id) then begin
if not (s.kind in OverloadableSyms) then begin
{@discard} StrTableIncl(c.AmbigiousSymbols, copy);
{@discard} StrTableIncl(c.AmbigiousSymbols, check);
// s and check need to be qualified
// s and check need to be qualified:
IntSetIncl(c.AmbigiousSymbols, copy.id);
IntSetIncl(c.AmbigiousSymbols, check.id);
end
end;
StrTableAdd(c.tab.stack[importTablePos], copy);
if s.kind = skType then begin
etyp := s.typ;
if etyp.kind = tyEnum then begin
if etyp.kind in [tyBool, tyEnum] then begin
for j := 0 to sonsLen(etyp.n)-1 do begin
e := etyp.n.sons[j].sym;
if (e.Kind = skEnumField) then rawImportSymbol(c, e)
else InternalError(s.info, 'rawImportSymbol');
if (e.Kind <> skEnumField) then
InternalError(s.info, 'rawImportSymbol');
// BUGFIX: because of aliases for enums the symbol may already
// have been put into the symbol table
// BUGFIX: but only iff they are the same symbols!
check := InitIdentIter(it, c.tab.stack[importTablePos], e.name);
while check <> nil do begin
if check.id = e.id then begin e := nil; break end;
check := NextIdentIter(it, c.tab.stack[importTablePos]);
end;
if e <> nil then rawImportSymbol(c, e);
//check := StrTableGet(c.tab.stack[importTablePos], e.name);
//if (check = nil) or (check.id <> e.id) then
// rawImportSymbol(c, e)
end
end
end
else if s.kind = skConverter then
addConverter(c, s);
addConverter(c, s); // rodgen assures that converters are no stubs
end;
procedure importSymbol(c: PContext; ident: PNode; fromMod: PSym);
@ -78,6 +108,7 @@ begin
s := StrTableGet(fromMod.tab, ident.ident);
if s = nil then
liMessage(ident.info, errUndeclaredIdentifier, ident.ident.s);
if s.kind = skStub then loadStub(s);
if not (s.Kind in ExportableSymKinds) then
InternalError(ident.info, 'importSymbol: 2');
// for an enumeration we have to add all identifiers
@ -106,7 +137,7 @@ begin
if s.kind <> skModule then begin
if s.kind <> skEnumField then begin
if not (s.Kind in ExportableSymKinds) then
InternalError(s.info, 'importAllSymbols');
InternalError(s.info, 'importAllSymbols: ' + symKindToStr[s.kind]);
rawImportSymbol(c, s); // this is correct!
end
end;
@ -118,14 +149,15 @@ function evalImport(c: PContext; n: PNode): PNode;
var
m: PSym;
i: int;
f: string;
begin
result := copyNode(n);
result := n;
for i := 0 to sonsLen(n)-1 do begin
m := c.ImportModule(getModuleFile(n.sons[i]), c.b);
f := getModuleFile(n.sons[i]);
m := gImportModule(f);
// ``addDecl`` needs to be done before ``importAllSymbols``!
addDecl(c, m); // add symbol to symbol table of module
importAllSymbols(c, m);
addSon(result, newSymNode(m));
end;
end;
@ -133,24 +165,15 @@ function evalFrom(c: PContext; n: PNode): PNode;
var
m: PSym;
i: int;
f: string;
begin
result := n;
checkMinSonsLen(n, 2);
m := c.ImportModule(getModuleFile(n.sons[0]), c.b);
f := getModuleFile(n.sons[0]);
m := gImportModule(f);
n.sons[0] := newSymNode(m);
addDecl(c, m); // add symbol to symbol table of module
for i := 1 to sonsLen(n)-1 do importSymbol(c, n.sons[i], m);
end;
function evalInclude(c: PContext; n: PNode): PNode;
var
i: int;
x: PNode;
begin
result := newNodeI(nkStmtList, n.info);
for i := 0 to sonsLen(n)-1 do begin
x := c.includeFile(getModuleFile(n.sons[i]));
x := semStmt(c, x);
addSon(result, x);
end;
end;
end.

View file

@ -1,267 +0,0 @@
//
//
// The Nimrod Compiler
// (c) Copyright 2008 Andreas Rumpf
//
// See the file "copying.txt", included in this
// distribution, for details about the copyright.
//
// This module does the instantiation of generic procs and types.
function generateInstance(c: PContext; fn: PSym; const pt: TIdTable;
const instantiator: TLineInfo): PSym; forward;
// generates an instantiated proc
type
TInstantiateClosure = object(NObject)
mapping: TIdTable; // map {ptype, psym} to {ptype, psym}
fn: PSym;
module: PSym;
newOwner: PSym;
instantiator: TLineInfo;
end;
PInstantiateClosure = ^TInstantiateClosure;
PInstClosure = PInstantiateClosure;
function instantiateTree(c: PInstantiateClosure; t: PNode): PNode; forward;
function instantiateSym(c: PInstantiateClosure; sym: PSym): PSym; forward;
function instantiateType(c: PInstantiateClosure; typ: PType): PType; forward;
function containsGenericTypeIter(t: PType; closure: PObject): bool;
begin
result := t.kind in GenericTypes;
end;
function containsGenericType(t: PType): bool;
begin
result := iterOverType(t, containsGenericTypeIter, nil);
end;
function instTypeNode(c: PInstantiateClosure; n: PNode): PNode;
var
i: int;
begin
result := nil;
if n <> nil then begin
result := copyNode(n);
result.typ := instantiateType(c, n.typ);
case n.kind of
nkNone..nkNilLit: begin // a leaf
end;
else begin
for i := 0 to sonsLen(n)-1 do
addSon(result, instTypeNode(c, n.sons[i]));
end
end
end
end;
function instantiateType(c: PInstantiateClosure; typ: PType): PType;
var
i: int;
begin
result := PType(idTableGet(c.mapping, typ));
if result <> nil then exit;
if containsGenericType(typ) then begin
result := copyType(typ, c.newOwner);
idTablePut(c.mapping, typ, result); // to avoid cycles
for i := 0 to sonsLen(result)-1 do
result.sons[i] := instantiateType(c, result.sons[i]);
if result.n <> nil then
result.n := instTypeNode(c, result.n);
end
else
result := typ;
if result.Kind in GenericTypes then begin
liMessage(c.instantiator, errCannotInstantiateX,
TypeToString(typ, preferName));
end
else if result.kind = tyVar then begin
if result.sons[0].kind = tyVar then
liMessage(c.instantiator, errVarVarTypeNotAllowed);
end;
end;
function instantiateSym(c: PInstantiateClosure; sym: PSym): PSym;
begin
if sym = nil then begin result := nil; exit end; // BUGFIX
result := PSym(idTableGet(c.mapping, sym));
if (result = nil) then begin
if (sym.owner.id = c.fn.id) or (sym.id = c.fn.id) then begin
result := copySym(sym);
if sym.id = c.fn.id then c.newOwner := result;
include(result.flags, sfIsCopy);
idTablePut(c.mapping, sym, result); // BUGFIX
result.typ := instantiateType(c, sym.typ);
if (result.owner <> nil) and (result.owner.kind = skModule) then
result.owner := c.module // BUGFIX
else
result.owner := instantiateSym(c, result.owner);
if sym.ast <> nil then begin
result.ast := instantiateTree(c, sym.ast);
end
end
else
result := sym // do not copy t!
end
end;
function instantiateTree(c: PInstantiateClosure; t: PNode): PNode;
var
len, i: int;
begin
if t = nil then begin result := nil; exit end;
result := copyNode(t);
if result.typ <> nil then result.typ := instantiateType(c, result.typ);
case t.kind of
nkNone..pred(nkSym), succ(nkSym)..nkNilLit: begin end;
nkSym: begin
if result.sym <> nil then result.sym := instantiateSym(c, result.sym);
end
else begin
len := sonsLen(t);
if len > 0 then begin
newSons(result, len);
for i := 0 to len-1 do
result.sons[i] := instantiateTree(c, t.sons[i]);
end
end
end
end;
procedure instantiateGenericParamList(c: PContext; n: PNode;
const pt: TIdTable);
var
i: int;
s, q: PSym;
t: PType;
begin
assert(n.kind = nkGenericParams);
for i := 0 to sonsLen(n)-1 do begin
if n.sons[i].kind = nkDefaultTypeParam then begin
internalError(n.sons[i].info,
'instantiateGenericParamList() to implement');
// XXX
end;
assert(n.sons[i].kind = nkSym);
q := n.sons[i].sym;
s := newSym(skType, q.name, getCurrOwner(c));
t := PType(IdTableGet(pt, q.typ));
if t = nil then
liMessage(n.sons[i].info, errCannotInstantiateX, s.name.s);
assert(t.kind <> tyGenericParam);
s.typ := t;
addDecl(c, s);
end
end;
function GenericCacheGet(c: PContext; genericSym, instSym: PSym): PSym;
var
i: int;
a, b: PSym;
begin
result := nil;
for i := 0 to sonsLen(c.generics)-1 do begin
if c.generics.sons[i].kind <> nkExprEqExpr then
InternalError(genericSym.info, 'GenericCacheGet');
a := c.generics.sons[i].sons[0].sym;
if genericSym.id = a.id then begin
b := c.generics.sons[i].sons[1].sym;
if equalParams(b.typ.n, instSym.typ.n) = paramsEqual then begin
result := b; exit
end
end
end
end;
procedure GenericCacheAdd(c: PContext; genericSym, instSym: PSym);
var
n: PNode;
begin
n := newNode(nkExprEqExpr);
addSon(n, newSymNode(genericSym));
addSon(n, newSymNode(instSym));
addSon(c.generics, n);
end;
procedure semParamList(c: PContext; n: PNode; s: PSym); forward;
procedure addParams(c: PContext; n: PNode); forward;
procedure addResult(c: PContext; t: PType; const info: TLineInfo); forward;
procedure addResultNode(c: PContext; n: PNode); forward;
function generateInstance(c: PContext; fn: PSym; const pt: TIdTable;
const instantiator: TLineInfo): PSym;
// generates an instantiated proc
var
oldPrc: PSym;
oldP: PProcCon;
n: PNode;
begin
oldP := c.p; // restore later
result := copySym(fn);
result.owner := getCurrOwner(c);
n := copyTree(fn.ast);
result.ast := n;
pushOwner(c, result);
openScope(c.tab);
assert(n.sons[genericParamsPos] <> nil);
n.sons[namePos] := newSymNode(result);
pushInfoContext(instantiator);
instantiateGenericParamList(c, n.sons[genericParamsPos], pt);
n.sons[genericParamsPos] := nil;
// semantic checking for the parameters:
if n.sons[paramsPos] <> nil then begin
semParamList(c, n.sons[ParamsPos], result);
addParams(c, result.typ.n);
end
else begin
result.typ := newTypeS(tyProc, c);
addSon(result.typ, nil);
end;
// now check if we have already such a proc generated
oldPrc := GenericCacheGet(c, fn, result);
if oldPrc = nil then begin
// add it here, so that recursive generic procs are possible:
addDecl(c, result);
if n.sons[codePos] <> nil then begin
c.p := newProcCon(result);
if result.kind in [skProc, skConverter] then begin
addResult(c, result.typ.sons[0], n.info);
addResultNode(c, n);
end;
n.sons[codePos] := semStmtScope(c, n.sons[codePos]);
end;
GenericCacheAdd(c, fn, result);
end
else
result := oldPrc;
popInfoContext();
closeScope(c.tab); // close scope for parameters
popOwner(c);
c.p := oldP; // restore
end;
function generateTypeInstance(p: PContext; const pt: TIdTable;
const instantiator: TLineInfo; t: PType): PType;
var
c: PInstantiateClosure;
begin
new(c);
{@ignore}
fillChar(c^, sizeof(c^), 0);
{@emit}
c.mapping := pt; // making a copy is not necessary
c.fn := nil;
c.instantiator := instantiator;
c.module := p.module;
c.newOwner := getCurrOwner(p);
result := instantiateType(c, t);
end;
function partialSpecialization(c: PContext; n: PNode; s: PSym): PNode;
begin
result := n;
end;

View file

@ -16,7 +16,7 @@ unit lexbase;
interface
uses
nsystem, charsets, strutils;
nsystem, llstream, charsets, strutils;
{@emit
const
@ -44,25 +44,21 @@ const
type
TBaseLexer = object(NObject)
bufpos: int;
buf: PChar; // NOT zero terminated!
buf: PChar;
bufLen: int; // length of buffer in characters
f: TBinaryFile; // we use a binary file here for efficiency
stream: PLLStream; // we read from this stream
LineNumber: int; // the current line number
// private data:
sentinel: int;
lineStart: int; // index of last line start in buffer
fileOpened: boolean;
end;
function initBaseLexer(out L: TBaseLexer;
const filename: string;
bufLen: int = 8192): boolean;
procedure openBaseLexer(out L: TBaseLexer;
inputstream: PLLStream;
bufLen: int = 8192);
// 8K is a reasonable buffer size
procedure initBaseLexerFromBuffer(out L: TBaseLexer;
const buffer: string);
procedure deinitBaseLexer(var L: TBaseLexer);
procedure closeBaseLexer(var L: TBaseLexer);
function getCurrentLine(const L: TBaseLexer; marker: boolean = true): string;
function getColNumber(const L: TBaseLexer; pos: int): int;
@ -82,10 +78,10 @@ implementation
const
chrSize = sizeof(char);
procedure deinitBaseLexer(var L: TBaseLexer);
procedure closeBaseLexer(var L: TBaseLexer);
begin
dealloc(L.buf);
if L.fileOpened then closeFile(L.f);
LLStreamClose(L.stream);
end;
{@ignore}
@ -119,8 +115,8 @@ begin
if toCopy > 0 then
MoveMem(L.buf, addr(L.buf[L.sentinel+1]), toCopy * chrSize);
// "moveMem" handles overlapping regions
charsRead := ReadBuffer(L.f, addr(L.buf[toCopy]), (L.sentinel+1) * chrSize)
div chrSize;
charsRead := LLStreamRead(L.stream, addr(L.buf[toCopy]),
(L.sentinel+1) * chrSize) div chrSize;
s := toCopy + charsRead;
if charsRead < L.sentinel+1 then begin
L.buf[s] := EndOfFile; // set end marker
@ -144,8 +140,8 @@ begin
L.bufLen := L.BufLen * 2;
L.buf := {@cast}PChar(realloc(L.buf, L.bufLen*chrSize));
assert(L.bufLen - oldBuflen = oldBufLen);
charsRead := ReadBuffer(L.f, addr(L.buf[oldBufLen]), oldBufLen*chrSize)
div chrSize;
charsRead := LLStreamRead(L.stream, addr(L.buf[oldBufLen]),
oldBufLen*chrSize) div chrSize;
if charsRead < oldBufLen then begin
L.buf[oldBufLen+charsRead] := EndOfFile;
L.sentinel := oldBufLen+charsRead;
@ -198,8 +194,8 @@ begin
end
end;
function initBaseLexer(out L: TBaseLexer; const filename: string;
bufLen: int = 8192): boolean;
procedure openBaseLexer(out L: TBaseLexer; inputstream: PLLStream;
bufLen: int = 8192);
begin
assert(bufLen > 0);
L.bufpos := 0;
@ -208,30 +204,8 @@ begin
L.sentinel := bufLen-1;
L.lineStart := 0;
L.linenumber := 1; // lines start at 1
L.fileOpened := openFile(L.f, filename);
result := L.fileOpened;
if result then begin
fillBuffer(L);
skip_UTF_8_BOM(L)
end;
end;
procedure initBaseLexerFromBuffer(out L: TBaseLexer;
const buffer: string);
begin
L.bufpos := 0;
L.bufLen := length(buffer)+1;
L.buf := {@cast}PChar(alloc(L.bufLen * chrSize));
L.sentinel := L.bufLen-1;
L.lineStart := 0;
L.linenumber := 1; // lines start at 1
L.fileOpened := false;
if L.bufLen > 0 then begin
copyMem(L.buf, {@cast}pointer(buffer), L.bufLen);
L.buf[L.bufLen-1] := EndOfFile;
end
else
L.buf[0] := EndOfFile;
L.stream := inputstream;
fillBuffer(L);
skip_UTF_8_BOM(L);
end;

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