mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 21:40:32 +00:00
Initial import
This commit is contained in:
17
Nimrod.geany
Executable file
17
Nimrod.geany
Executable file
@@ -0,0 +1,17 @@
|
||||
|
||||
[project]
|
||||
name=Nimrod
|
||||
base_path=/media/hda4/nimrod
|
||||
make_in_base_path=false
|
||||
description=
|
||||
run_cmd=python koch.py nim
|
||||
|
||||
[files]
|
||||
current_page=6
|
||||
FILE_NAME_0=786;20;0;16;0;1;0;/media/hda4/nimrod/todo.txt;
|
||||
FILE_NAME_1=7567;34;0;16;0;1;0;/media/hda4/nimrod/lib/base/dialogs.nim;
|
||||
FILE_NAME_2=353;34;0;16;0;1;0;/media/hda4/nimrod/tests/tdialogs.nim;
|
||||
FILE_NAME_3=1811;9;0;16;0;1;0;/media/hda4/nimrod/nim/ccgexprs.pas;
|
||||
FILE_NAME_4=119539;0;0;16;0;1;0;/media/hda4/nimrod/lib/rod_gen/system.c;
|
||||
FILE_NAME_5=192;9;0;16;0;1;0;/media/hda4/nimrod/nim/eval.pas;
|
||||
FILE_NAME_6=0;34;0;16;0;1;0;/media/hda4/nimrod/lib/unicode.nim;
|
||||
694
cogapp.py
Executable file
694
cogapp.py
Executable file
@@ -0,0 +1,694 @@
|
||||
""" Cog code generation tool.
|
||||
http://nedbatchelder.com/code/cog
|
||||
|
||||
Copyright 2004-2008, Ned Batchelder.
|
||||
"""
|
||||
|
||||
# $Id: cogapp.py 141 2008-05-22 10:56:43Z nedbat $
|
||||
|
||||
import md5, os, re, string, sys, traceback, types
|
||||
import imp, compiler
|
||||
import copy, getopt, shlex
|
||||
from cStringIO import StringIO
|
||||
|
||||
__all__ = ['Cog', 'CogUsageError']
|
||||
|
||||
__version__ = '2.1.20080522' # History at the end of the file.
|
||||
|
||||
usage = """\
|
||||
cog - generate code with inlined Python code.
|
||||
|
||||
cog [OPTIONS] [INFILE | @FILELIST] ...
|
||||
|
||||
INFILE is the name of an input file.
|
||||
FILELIST is the name of a text file containing file names or
|
||||
other @FILELISTs.
|
||||
|
||||
OPTIONS:
|
||||
-c Checksum the output to protect it against accidental change.
|
||||
-d Delete the generator code from the output file.
|
||||
-D name=val Define a global string available to your generator code.
|
||||
-e Warn if a file has no cog code in it.
|
||||
-I PATH Add PATH to the list of directories for data files and modules.
|
||||
-o OUTNAME Write the output to OUTNAME.
|
||||
-r Replace the input file with the output.
|
||||
-s STRING Suffix all generated output lines with STRING.
|
||||
-U Write the output with Unix newlines (only LF line-endings).
|
||||
-w CMD Use CMD if the output file needs to be made writable.
|
||||
A %s in the CMD will be filled with the filename.
|
||||
-x Excise all the generated output without running the generators.
|
||||
-z The [[[end]]] marker can be omitted, and is assumed at eof.
|
||||
-v Print the version of cog and exit.
|
||||
-h Print this help.
|
||||
"""
|
||||
|
||||
# Get True and False right even if they aren't already defined.
|
||||
True, False = 0==0, 0==1
|
||||
|
||||
# Other package modules
|
||||
from whiteutils import *
|
||||
|
||||
class CogError(Exception):
|
||||
""" Any exception raised by Cog.
|
||||
"""
|
||||
def __init__(self, msg, file='', line=0):
|
||||
if file:
|
||||
Exception.__init__(self, "%s(%d): %s" % (file, line, msg))
|
||||
else:
|
||||
Exception.__init__(self, msg)
|
||||
|
||||
class CogUsageError(CogError):
|
||||
""" An error in usage of command-line arguments in cog.
|
||||
"""
|
||||
pass #pragma: no cover
|
||||
|
||||
class CogInternalError(CogError):
|
||||
""" An error in the coding of Cog. Should never happen.
|
||||
"""
|
||||
pass #pragma: no cover
|
||||
|
||||
class CogGeneratedError(CogError):
|
||||
""" An error raised by a user's cog generator.
|
||||
"""
|
||||
pass #pragma: no cover
|
||||
|
||||
class Redirectable:
|
||||
""" An object with its own stdout and stderr files.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.stdout = sys.stdout
|
||||
self.stderr = sys.stderr
|
||||
|
||||
def setOutput(self, stdout=None, stderr=None):
|
||||
""" Assign new files for standard out and/or standard error.
|
||||
"""
|
||||
if stdout:
|
||||
self.stdout = stdout
|
||||
if stderr:
|
||||
self.stderr = stderr
|
||||
|
||||
class CogGenerator(Redirectable):
|
||||
""" A generator pulled from a source file.
|
||||
"""
|
||||
def __init__(self):
|
||||
Redirectable.__init__(self)
|
||||
self.markers = []
|
||||
self.lines = []
|
||||
|
||||
def parseMarker(self, l):
|
||||
self.markers.append(l)
|
||||
|
||||
def parseLine(self, l):
|
||||
self.lines.append(l.strip('\n'))
|
||||
|
||||
def getCode(self):
|
||||
""" Extract the executable Python code from the generator.
|
||||
"""
|
||||
# If the markers and lines all have the same prefix
|
||||
# (end-of-line comment chars, for example),
|
||||
# then remove it from all the lines.
|
||||
prefIn = commonPrefix(self.markers + self.lines)
|
||||
if prefIn:
|
||||
self.markers = [ l.replace(prefIn, '', 1) for l in self.markers ]
|
||||
self.lines = [ l.replace(prefIn, '', 1) for l in self.lines ]
|
||||
|
||||
return reindentBlock(self.lines, '')
|
||||
|
||||
def evaluate(self, cog, globals, fname='cog generator'):
|
||||
# figure out the right whitespace prefix for the output
|
||||
prefOut = whitePrefix(self.markers)
|
||||
|
||||
intext = self.getCode()
|
||||
if not intext:
|
||||
return ''
|
||||
|
||||
# In Python 2.2, the last line has to end in a newline.
|
||||
intext = "import cog\n" + intext + "\n"
|
||||
code = compiler.compile(intext, filename=str(fname), mode='exec')
|
||||
|
||||
# Make sure the "cog" module has our state.
|
||||
cog.cogmodule.msg = self.msg
|
||||
cog.cogmodule.out = self.out
|
||||
cog.cogmodule.outl = self.outl
|
||||
cog.cogmodule.error = self.error
|
||||
|
||||
self.outstring = ''
|
||||
eval(code, globals)
|
||||
|
||||
# We need to make sure that the last line in the output
|
||||
# ends with a newline, or it will be joined to the
|
||||
# end-output line, ruining cog's idempotency.
|
||||
if self.outstring and self.outstring[-1] != '\n':
|
||||
self.outstring += '\n'
|
||||
|
||||
return reindentBlock(self.outstring, prefOut)
|
||||
|
||||
def msg(self, s):
|
||||
print >>self.stdout, "Message: "+s
|
||||
|
||||
def out(self, sOut='', dedent=False, trimblanklines=False):
|
||||
""" The cog.out function.
|
||||
"""
|
||||
if trimblanklines and ('\n' in sOut):
|
||||
lines = sOut.split('\n')
|
||||
if lines[0].strip() == '':
|
||||
del lines[0]
|
||||
if lines and lines[-1].strip() == '':
|
||||
del lines[-1]
|
||||
sOut = '\n'.join(lines)+'\n'
|
||||
if dedent:
|
||||
sOut = reindentBlock(sOut)
|
||||
self.outstring += sOut
|
||||
|
||||
def outl(self, sOut='', **kw):
|
||||
""" The cog.outl function.
|
||||
"""
|
||||
self.out(sOut, **kw)
|
||||
self.out('\n')
|
||||
|
||||
def error(self, msg='Error raised by cog generator.'):
|
||||
""" The cog.error function.
|
||||
Instead of raising standard python errors, cog generators can use
|
||||
this function. It will display the error without a scary Python
|
||||
traceback.
|
||||
"""
|
||||
raise CogGeneratedError(msg)
|
||||
|
||||
|
||||
class NumberedFileReader:
|
||||
""" A decorator for files that counts the readline()'s called.
|
||||
"""
|
||||
def __init__(self, f):
|
||||
self.f = f
|
||||
self.n = 0
|
||||
|
||||
def readline(self):
|
||||
l = self.f.readline()
|
||||
if l:
|
||||
self.n += 1
|
||||
return l
|
||||
|
||||
def linenumber(self):
|
||||
return self.n
|
||||
|
||||
|
||||
class CogOptions:
|
||||
""" Options for a run of cog.
|
||||
"""
|
||||
def __init__(self):
|
||||
# Defaults for argument values.
|
||||
self.args = []
|
||||
self.includePath = []
|
||||
self.defines = {}
|
||||
self.bShowVersion = False
|
||||
self.sMakeWritableCmd = None
|
||||
self.bReplace = False
|
||||
self.bNoGenerate = False
|
||||
self.sOutputName = None
|
||||
self.bWarnEmpty = False
|
||||
self.bHashOutput = False
|
||||
self.bDeleteCode = False
|
||||
self.bEofCanBeEnd = False
|
||||
self.sSuffix = None
|
||||
self.bNewlines = False
|
||||
|
||||
def __cmp__(self, other):
|
||||
""" Comparison operator for tests to use.
|
||||
"""
|
||||
return self.__dict__.__cmp__(other.__dict__)
|
||||
|
||||
def clone(self):
|
||||
""" Make a clone of these options, for further refinement.
|
||||
"""
|
||||
return copy.deepcopy(self)
|
||||
|
||||
def addToIncludePath(self, dirs):
|
||||
""" Add directories to the include path.
|
||||
"""
|
||||
dirs = dirs.split(os.pathsep)
|
||||
self.includePath.extend(dirs)
|
||||
|
||||
def parseArgs(self, argv):
|
||||
# Parse the command line arguments.
|
||||
try:
|
||||
opts, self.args = getopt.getopt(argv, 'cdD:eI:o:rs:Uvw:xz')
|
||||
except getopt.error, msg:
|
||||
raise CogUsageError(msg)
|
||||
|
||||
# Handle the command line arguments.
|
||||
for o, a in opts:
|
||||
if o == '-c':
|
||||
self.bHashOutput = True
|
||||
elif o == '-d':
|
||||
self.bDeleteCode = True
|
||||
elif o == '-D':
|
||||
if a.count('=') < 1:
|
||||
raise CogUsageError("-D takes a name=value argument")
|
||||
name, value = a.split('=', 1)
|
||||
self.defines[name] = value
|
||||
elif o == '-e':
|
||||
self.bWarnEmpty = True
|
||||
elif o == '-I':
|
||||
self.addToIncludePath(a)
|
||||
elif o == '-o':
|
||||
self.sOutputName = a
|
||||
elif o == '-r':
|
||||
self.bReplace = True
|
||||
elif o == '-s':
|
||||
self.sSuffix = a
|
||||
elif o == '-U':
|
||||
self.bNewlines = True
|
||||
elif o == '-v':
|
||||
self.bShowVersion = True
|
||||
elif o == '-w':
|
||||
self.sMakeWritableCmd = a
|
||||
elif o == '-x':
|
||||
self.bNoGenerate = True
|
||||
elif o == '-z':
|
||||
self.bEofCanBeEnd = True
|
||||
else:
|
||||
# Since getopt.getopt is given a list of possible flags,
|
||||
# this is an internal error.
|
||||
raise CogInternalError("Don't understand argument %s" % o)
|
||||
|
||||
def validate(self):
|
||||
""" Does nothing if everything is OK, raises CogError's if it's not.
|
||||
"""
|
||||
if self.bReplace and self.bDeleteCode:
|
||||
raise CogUsageError("Can't use -d with -r (or you would delete all your source!)")
|
||||
|
||||
if self.bReplace and self.sOutputName:
|
||||
raise CogUsageError("Can't use -o with -r (they are opposites)")
|
||||
|
||||
|
||||
class Cog(Redirectable):
|
||||
""" The Cog engine.
|
||||
"""
|
||||
def __init__(self):
|
||||
Redirectable.__init__(self)
|
||||
self.sBeginSpec = '[[[cog'
|
||||
self.sEndSpec = ']]]'
|
||||
self.sEndOutput = '[[[end]]]'
|
||||
self.reEndOutput = re.compile(r'\[\[\[end]]](?P<hashsect> *\(checksum: (?P<hash>[a-f0-9]+)\))')
|
||||
self.sEndFormat = '[[[end]]] (checksum: %s)'
|
||||
|
||||
self.options = CogOptions()
|
||||
self.sOutputMode = 'w'
|
||||
|
||||
self.installCogModule()
|
||||
|
||||
def showWarning(self, msg):
|
||||
print >>self.stdout, "Warning:", msg
|
||||
|
||||
def isBeginSpecLine(self, s):
|
||||
return string.find(s, self.sBeginSpec) >= 0
|
||||
|
||||
def isEndSpecLine(self, s):
|
||||
return string.find(s, self.sEndSpec) >= 0 and \
|
||||
not self.isEndOutputLine(s)
|
||||
|
||||
def isEndOutputLine(self, s):
|
||||
return string.find(s, self.sEndOutput) >= 0
|
||||
|
||||
def installCogModule(self):
|
||||
""" Magic mumbo-jumbo so that imported Python modules
|
||||
can say "import cog" and get our state.
|
||||
"""
|
||||
self.cogmodule = imp.new_module('cog')
|
||||
self.cogmodule.path = []
|
||||
sys.modules['cog'] = self.cogmodule
|
||||
|
||||
def processFile(self, fIn, fOut, fname=None, globals=None):
|
||||
""" Process an input file object to an output file object.
|
||||
fIn and fOut can be file objects, or file names.
|
||||
"""
|
||||
|
||||
sFileIn = fname or ''
|
||||
sFileOut = fname or ''
|
||||
# Convert filenames to files.
|
||||
if isinstance(fIn, types.StringTypes):
|
||||
# Open the input file.
|
||||
sFileIn = fIn
|
||||
fIn = open(fIn, 'r')
|
||||
if isinstance(fOut, types.StringTypes):
|
||||
# Open the output file.
|
||||
sFileOut = fOut
|
||||
fOut = open(fOut, self.sOutputMode)
|
||||
|
||||
fIn = NumberedFileReader(fIn)
|
||||
|
||||
bSawCog = False
|
||||
|
||||
self.cogmodule.inFile = sFileIn
|
||||
self.cogmodule.outFile = sFileOut
|
||||
|
||||
# The globals dict we'll use for this file.
|
||||
if globals is None:
|
||||
globals = {}
|
||||
|
||||
# If there are any global defines, put them in the globals.
|
||||
globals.update(self.options.defines)
|
||||
|
||||
# loop over generator chunks
|
||||
l = fIn.readline()
|
||||
while l:
|
||||
# Find the next spec begin
|
||||
while l and not self.isBeginSpecLine(l):
|
||||
if self.isEndSpecLine(l):
|
||||
raise CogError("Unexpected '%s'" % self.sEndSpec,
|
||||
file=sFileIn, line=fIn.linenumber())
|
||||
if self.isEndOutputLine(l):
|
||||
raise CogError("Unexpected '%s'" % self.sEndOutput,
|
||||
file=sFileIn, line=fIn.linenumber())
|
||||
fOut.write(l)
|
||||
l = fIn.readline()
|
||||
if not l:
|
||||
break
|
||||
if not self.options.bDeleteCode:
|
||||
fOut.write(l)
|
||||
|
||||
# l is the begin spec
|
||||
gen = CogGenerator()
|
||||
gen.setOutput(stdout=self.stdout)
|
||||
gen.parseMarker(l)
|
||||
firstLineNum = fIn.linenumber()
|
||||
self.cogmodule.firstLineNum = firstLineNum
|
||||
|
||||
# If the spec begin is also a spec end, then process the single
|
||||
# line of code inside.
|
||||
if self.isEndSpecLine(l):
|
||||
beg = string.find(l, self.sBeginSpec)
|
||||
end = string.find(l, self.sEndSpec)
|
||||
if beg > end:
|
||||
raise CogError("Cog code markers inverted",
|
||||
file=sFileIn, line=firstLineNum)
|
||||
else:
|
||||
sCode = l[beg+len(self.sBeginSpec):end].strip()
|
||||
gen.parseLine(sCode)
|
||||
else:
|
||||
# Deal with an ordinary code block.
|
||||
l = fIn.readline()
|
||||
|
||||
# Get all the lines in the spec
|
||||
while l and not self.isEndSpecLine(l):
|
||||
if self.isBeginSpecLine(l):
|
||||
raise CogError("Unexpected '%s'" % self.sBeginSpec,
|
||||
file=sFileIn, line=fIn.linenumber())
|
||||
if self.isEndOutputLine(l):
|
||||
raise CogError("Unexpected '%s'" % self.sEndOutput,
|
||||
file=sFileIn, line=fIn.linenumber())
|
||||
if not self.options.bDeleteCode:
|
||||
fOut.write(l)
|
||||
gen.parseLine(l)
|
||||
l = fIn.readline()
|
||||
if not l:
|
||||
raise CogError(
|
||||
"Cog block begun but never ended.",
|
||||
file=sFileIn, line=firstLineNum)
|
||||
|
||||
if not self.options.bDeleteCode:
|
||||
fOut.write(l)
|
||||
gen.parseMarker(l)
|
||||
|
||||
l = fIn.readline()
|
||||
|
||||
# Eat all the lines in the output section. While reading past
|
||||
# them, compute the md5 hash of the old output.
|
||||
hasher = md5.new()
|
||||
while l and not self.isEndOutputLine(l):
|
||||
if self.isBeginSpecLine(l):
|
||||
raise CogError("Unexpected '%s'" % self.sBeginSpec,
|
||||
file=sFileIn, line=fIn.linenumber())
|
||||
if self.isEndSpecLine(l):
|
||||
raise CogError("Unexpected '%s'" % self.sEndSpec,
|
||||
file=sFileIn, line=fIn.linenumber())
|
||||
hasher.update(l)
|
||||
l = fIn.readline()
|
||||
curHash = hasher.hexdigest()
|
||||
|
||||
if not l and not self.options.bEofCanBeEnd:
|
||||
# We reached end of file before we found the end output line.
|
||||
raise CogError("Missing '%s' before end of file." % self.sEndOutput,
|
||||
file=sFileIn, line=fIn.linenumber())
|
||||
|
||||
# Write the output of the spec to be the new output if we're
|
||||
# supposed to generate code.
|
||||
hasher = md5.new()
|
||||
if not self.options.bNoGenerate:
|
||||
sFile = "%s+%d" % (sFileIn, firstLineNum)
|
||||
sGen = gen.evaluate(cog=self, globals=globals, fname=sFile)
|
||||
sGen = self.suffixLines(sGen)
|
||||
hasher.update(sGen)
|
||||
fOut.write(sGen)
|
||||
newHash = hasher.hexdigest()
|
||||
|
||||
bSawCog = True
|
||||
|
||||
# Write the ending output line
|
||||
hashMatch = self.reEndOutput.search(l)
|
||||
if self.options.bHashOutput:
|
||||
if hashMatch:
|
||||
oldHash = hashMatch.groupdict()['hash']
|
||||
if oldHash != curHash:
|
||||
raise CogError("Output has been edited! Delete old checksum to unprotect.",
|
||||
file=sFileIn, line=fIn.linenumber())
|
||||
# Create a new end line with the correct hash.
|
||||
endpieces = l.split(hashMatch.group(0), 1)
|
||||
else:
|
||||
# There was no old hash, but we want a new hash.
|
||||
endpieces = l.split(self.sEndOutput, 1)
|
||||
l = (self.sEndFormat % newHash).join(endpieces)
|
||||
else:
|
||||
# We don't want hashes output, so if there was one, get rid of
|
||||
# it.
|
||||
if hashMatch:
|
||||
l = l.replace(hashMatch.groupdict()['hashsect'], '', 1)
|
||||
|
||||
if not self.options.bDeleteCode:
|
||||
fOut.write(l)
|
||||
l = fIn.readline()
|
||||
|
||||
if not bSawCog and self.options.bWarnEmpty:
|
||||
self.showWarning("no cog code found in %s" % sFileIn)
|
||||
|
||||
# A regex for non-empty lines, used by suffixLines.
|
||||
reNonEmptyLines = re.compile("^\s*\S+.*$", re.MULTILINE)
|
||||
|
||||
def suffixLines(self, text):
|
||||
""" Add suffixes to the lines in text, if our options desire it.
|
||||
text is many lines, as a single string.
|
||||
"""
|
||||
if self.options.sSuffix:
|
||||
# Find all non-blank lines, and add the suffix to the end.
|
||||
repl = r"\g<0>" + self.options.sSuffix.replace('\\', '\\\\')
|
||||
text = self.reNonEmptyLines.sub(repl, text)
|
||||
return text
|
||||
|
||||
def processString(self, sInput, fname=None):
|
||||
""" Process sInput as the text to cog.
|
||||
Return the cogged output as a string.
|
||||
"""
|
||||
fOld = StringIO(sInput)
|
||||
fNew = StringIO()
|
||||
self.processFile(fOld, fNew, fname=fname)
|
||||
return fNew.getvalue()
|
||||
|
||||
def replaceFile(self, sOldPath, sNewText):
|
||||
""" Replace file sOldPath with the contents sNewText
|
||||
"""
|
||||
if not os.access(sOldPath, os.W_OK):
|
||||
# Need to ensure we can write.
|
||||
if self.options.sMakeWritableCmd:
|
||||
# Use an external command to make the file writable.
|
||||
cmd = self.options.sMakeWritableCmd.replace('%s', sOldPath)
|
||||
self.stdout.write(os.popen(cmd).read())
|
||||
if not os.access(sOldPath, os.W_OK):
|
||||
raise CogError("Couldn't make %s writable" % sOldPath)
|
||||
else:
|
||||
# Can't write!
|
||||
raise CogError("Can't overwrite %s" % sOldPath)
|
||||
f = open(sOldPath, self.sOutputMode)
|
||||
f.write(sNewText)
|
||||
f.close()
|
||||
|
||||
def saveIncludePath(self):
|
||||
self.savedInclude = self.options.includePath[:]
|
||||
self.savedSysPath = sys.path[:]
|
||||
|
||||
def restoreIncludePath(self):
|
||||
self.options.includePath = self.savedInclude
|
||||
self.cogmodule.path = self.options.includePath
|
||||
sys.path = self.savedSysPath
|
||||
|
||||
def addToIncludePath(self, includePath):
|
||||
self.cogmodule.path.extend(includePath)
|
||||
sys.path.extend(includePath)
|
||||
|
||||
def processOneFile(self, sFile):
|
||||
""" Process one filename through cog.
|
||||
"""
|
||||
|
||||
self.saveIncludePath()
|
||||
|
||||
try:
|
||||
self.addToIncludePath(self.options.includePath)
|
||||
# Since we know where the input file came from,
|
||||
# push its directory onto the include path.
|
||||
self.addToIncludePath([os.path.dirname(sFile)])
|
||||
|
||||
# Set the file output mode based on whether we want \n or native
|
||||
# line endings.
|
||||
self.sOutputMode = 'w'
|
||||
if self.options.bNewlines:
|
||||
self.sOutputMode = 'wb'
|
||||
|
||||
# How we process the file depends on where the output is going.
|
||||
if self.options.sOutputName:
|
||||
self.processFile(sFile, self.options.sOutputName, sFile)
|
||||
elif self.options.bReplace:
|
||||
# We want to replace the cog file with the output,
|
||||
# but only if they differ.
|
||||
print >>self.stdout, "Cogging %s" % sFile,
|
||||
bNeedNewline = True
|
||||
|
||||
try:
|
||||
fOldFile = open(sFile)
|
||||
sOldText = fOldFile.read()
|
||||
fOldFile.close()
|
||||
sNewText = self.processString(sOldText, fname=sFile)
|
||||
if sOldText != sNewText:
|
||||
print >>self.stdout, " (changed)"
|
||||
bNeedNewline = False
|
||||
self.replaceFile(sFile, sNewText)
|
||||
finally:
|
||||
# The try-finally block is so we can print a partial line
|
||||
# with the name of the file, and print (changed) on the
|
||||
# same line, but also make sure to break the line before
|
||||
# any traceback.
|
||||
if bNeedNewline:
|
||||
print >>self.stdout
|
||||
else:
|
||||
self.processFile(sFile, self.stdout, sFile)
|
||||
finally:
|
||||
self.restoreIncludePath()
|
||||
|
||||
def processFileList(self, sFileList):
|
||||
""" Process the files in a file list.
|
||||
"""
|
||||
for l in open(sFileList).readlines():
|
||||
# Use shlex to parse the line like a shell.
|
||||
lex = shlex.shlex(l, posix=True)
|
||||
lex.whitespace_split = True
|
||||
lex.commenters = '#'
|
||||
# No escapes, so that backslash can be part of the path
|
||||
lex.escape = ''
|
||||
args = list(lex)
|
||||
if args:
|
||||
self.processArguments(args)
|
||||
|
||||
def processArguments(self, args):
|
||||
""" Process one command-line.
|
||||
"""
|
||||
saved_options = self.options
|
||||
self.options = self.options.clone()
|
||||
|
||||
self.options.parseArgs(args[1:])
|
||||
self.options.validate()
|
||||
|
||||
if args[0][0] == '@':
|
||||
if self.options.sOutputName:
|
||||
raise CogUsageError("Can't use -o with @file")
|
||||
self.processFileList(args[0][1:])
|
||||
else:
|
||||
self.processOneFile(args[0])
|
||||
|
||||
self.options = saved_options
|
||||
|
||||
def callableMain(self, argv):
|
||||
""" All of command-line cog, but in a callable form.
|
||||
This is used by main.
|
||||
argv is the equivalent of sys.argv.
|
||||
"""
|
||||
argv0 = argv.pop(0)
|
||||
|
||||
# Provide help if asked for anywhere in the command line.
|
||||
if '-?' in argv or '-h' in argv:
|
||||
print >>self.stderr, usage,
|
||||
return
|
||||
|
||||
self.options.parseArgs(argv)
|
||||
self.options.validate()
|
||||
|
||||
if self.options.bShowVersion:
|
||||
print >>self.stdout, "Cog version %s" % __version__
|
||||
return
|
||||
|
||||
if self.options.args:
|
||||
for a in self.options.args:
|
||||
self.processArguments([a])
|
||||
else:
|
||||
raise CogUsageError("No files to process")
|
||||
|
||||
def main(self, argv):
|
||||
""" Handle the command-line execution for cog.
|
||||
"""
|
||||
|
||||
try:
|
||||
self.callableMain(argv)
|
||||
return 0
|
||||
except CogUsageError, err:
|
||||
print >>self.stderr, err
|
||||
print >>self.stderr, "(for help use -?)"
|
||||
return 2
|
||||
except CogGeneratedError, err:
|
||||
print >>self.stderr, "Error: %s" % err
|
||||
return 3
|
||||
except CogError, err:
|
||||
print >>self.stderr, err
|
||||
return 1
|
||||
except:
|
||||
traceback.print_exc(None, self.stderr)
|
||||
return 1
|
||||
|
||||
# History:
|
||||
# 20040210: First public version.
|
||||
# 20040220: Text preceding the start and end marker are removed from Python lines.
|
||||
# -v option on the command line shows the version.
|
||||
# 20040311: Make sure the last line of output is properly ended with a newline.
|
||||
# 20040605: Fixed some blank line handling in cog.
|
||||
# Fixed problems with assigning to xml elements in handyxml.
|
||||
# 20040621: Changed all line-ends to LF from CRLF.
|
||||
# 20041002: Refactor some option handling to simplify unittesting the options.
|
||||
# 20041118: cog.out and cog.outl have optional string arguments.
|
||||
# 20041119: File names weren't being properly passed around for warnings, etc.
|
||||
# 20041122: Added cog.firstLineNum: a property with the line number of the [[[cog line.
|
||||
# Added cog.inFile and cog.outFile: the names of the input and output file.
|
||||
# 20041218: Single-line cog generators, with start marker and end marker on
|
||||
# the same line.
|
||||
# 20041230: Keep a single globals dict for all the code fragments in a single
|
||||
# file so they can share state.
|
||||
# 20050206: Added the -x switch to remove all generated output.
|
||||
# 20050218: Now code can be on the marker lines as well.
|
||||
# 20050219: Added -c switch to checksum the output so that edits can be
|
||||
# detected before they are obliterated.
|
||||
# 20050521: Added cog.error, contributed by Alexander Belchenko.
|
||||
# 20050720: Added code deletion and settable globals contributed by Blake Winton.
|
||||
# 20050724: Many tweaks to improve code coverage.
|
||||
# 20050726: Error messages are now printed with no traceback.
|
||||
# Code can no longer appear on the marker lines,
|
||||
# except for single-line style.
|
||||
# -z allows omission of the [[[end]]] marker, and it will be assumed
|
||||
# at the end of the file.
|
||||
# 20050729: Refactor option parsing into a separate class, in preparation for
|
||||
# future features.
|
||||
# 20050805: The cogmodule.path wasn't being properly maintained.
|
||||
# 20050808: Added the -D option to define a global value.
|
||||
# 20050810: The %s in the -w command is dealt with more robustly.
|
||||
# Added the -s option to suffix output lines with a marker.
|
||||
# 20050817: Now @files can have arguments on each line to change the cog's
|
||||
# behavior for that line.
|
||||
# 20051006: Version 2.0
|
||||
# 20080521: -U options lets you create Unix newlines on Windows. Thanks,
|
||||
# Alexander Belchenko.
|
||||
# 20080522: It's now ok to have -d with output to stdout, and now we validate
|
||||
# the args after each line of an @file.
|
||||
288
config/doctempl.cfg
Executable file
288
config/doctempl.cfg
Executable file
@@ -0,0 +1,288 @@
|
||||
# This is the config file for the documentation generator.
|
||||
# (c) 2008 Andreas Rumpf
|
||||
# Feel free to edit the templates as you need.
|
||||
|
||||
doc.section = """
|
||||
<div class="section" id="$sectionID">
|
||||
<h1><a class="toc-backref" href="#$sectionTitleID">$sectionTitle</a></h1>
|
||||
<dl class="item">
|
||||
$content
|
||||
</dl></div>
|
||||
"""
|
||||
|
||||
doc.section.toc = """
|
||||
<li>
|
||||
<a class="reference" href="#$sectionID" id="$sectionTitleID">$sectionTitle</a>
|
||||
<ul class="simple">
|
||||
$content
|
||||
</ul>
|
||||
</li>
|
||||
"""
|
||||
|
||||
doc.item = """
|
||||
<dt id="$itemID"><pre>$header</pre></dt>
|
||||
<dd>
|
||||
$desc
|
||||
</dd>
|
||||
"""
|
||||
|
||||
doc.item.toc = """
|
||||
<li><a class="reference" href="#$itemID">$name</a></li>
|
||||
"""
|
||||
|
||||
doc.toc = """
|
||||
<div class="navigation">
|
||||
<p class="topic-title first">Navigation</p>
|
||||
<ul class="simple">
|
||||
$content
|
||||
</ul>
|
||||
</div>"""
|
||||
|
||||
doc.body_toc = """
|
||||
$tableofcontents
|
||||
<div class="content">
|
||||
$moduledesc
|
||||
$content
|
||||
</div>
|
||||
"""
|
||||
|
||||
doc.body_no_toc = """
|
||||
$moduledesc
|
||||
$content
|
||||
"""
|
||||
|
||||
doc.file = """<?xml version="1.0" encoding="utf-8" ?>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<!-- This file is generated by Nimrod. -->
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>$title</title>
|
||||
<style type="text/css">
|
||||
|
||||
span.DecNumber {color: blue}
|
||||
span.BinNumber {color: blue}
|
||||
span.HexNumber {color: blue}
|
||||
span.OctNumber {color: blue}
|
||||
span.FloatNumber {color: blue}
|
||||
span.Identifier {color: black}
|
||||
span.Keyword {font-weight: bold}
|
||||
span.StringLit {color: blue}
|
||||
span.LongStringLit {color: blue}
|
||||
span.CharLit {color: blue}
|
||||
span.EscapeSequence {color: black}
|
||||
span.Operator {color: black}
|
||||
span.Punctation {color: black}
|
||||
span.Comment, span.LongComment {font-style:italic; color: green}
|
||||
span.RegularExpression {color: pink}
|
||||
span.TagStart {color: yellow}
|
||||
span.TagEnd {color: yellow}
|
||||
span.Key {color: blue}
|
||||
span.Value {color: black}
|
||||
span.RawData {color: blue}
|
||||
span.Assembler {color: blue}
|
||||
span.Preprocessor {color: yellow}
|
||||
span.Directive {color: yellow}
|
||||
span.Command, span.Rule, span.Hyperlink, span.Label, span.Reference,
|
||||
span.Other {color: black}
|
||||
|
||||
div.navigation {
|
||||
float: left; width: 20em;
|
||||
margin: 0; padding: 0; /*
|
||||
border: 1px dashed gold; */
|
||||
outline: 3px outset #99ff99; //gold;
|
||||
background-color: #99ff99;
|
||||
}
|
||||
|
||||
div.navigation ul {list-style-type: none;}
|
||||
div.navigation ul li a, div.navigation ul li a:visited {
|
||||
font-weight: bold;
|
||||
color: #CC0000;
|
||||
text-decoration: none;
|
||||
}
|
||||
div.navigation ul li a:hover {
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
outline: 2px outset gold;
|
||||
background-color: gold; /* #779977;*/
|
||||
}
|
||||
|
||||
div.content {
|
||||
margin-left: 20em;
|
||||
padding: 0 1em;
|
||||
border: 1px dashed gold;
|
||||
min-width: 16em;
|
||||
}
|
||||
|
||||
dl.item dd, dl.item dd p {
|
||||
margin-top:3px;
|
||||
}
|
||||
dl.item dd pre {
|
||||
margin-left: 15pt;
|
||||
border: 0px;
|
||||
}
|
||||
dl.item dt, dl.item dt pre {
|
||||
margin: 20pt 0 0 0;
|
||||
}
|
||||
|
||||
pre, span.tok {
|
||||
background-color:#F9F9F9;
|
||||
border:1px dotted #2F6FAB;
|
||||
color:black;
|
||||
}
|
||||
|
||||
/*
|
||||
:Author: David Goodger
|
||||
:Contact: goodger@python.org
|
||||
:Date: Date: 2006-05-21 22:44:42 +0200 (Sun, 21 May 2006)
|
||||
:Revision: Revision: 4564
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
|
||||
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th { border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first { margin-top: 0 ! important }
|
||||
.last, .with-subtitle { margin-bottom: 0 ! important }
|
||||
.hidden { display: none }
|
||||
a.toc-backref { text-decoration: none ; color: black }
|
||||
blockquote.epigraph { margin: 2em 5em ; }
|
||||
dl.docutils dd { margin-bottom: 0.5em }
|
||||
div.abstract { margin: 2em 5em }
|
||||
div.abstract p.topic-title { font-weight: bold ; text-align: center }
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ; border: medium outset ; padding: 1em }
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title { font-weight: bold ; font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title { color: red ; font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication { margin: 2em 5em ; text-align: center ; font-style: italic }
|
||||
div.dedication p.topic-title { font-weight: bold ; font-style: normal }
|
||||
div.figure { margin-left: 2em ; margin-right: 2em }
|
||||
div.footer, div.header { clear: both; font-size: smaller }
|
||||
div.line-block { display: block ; margin-top: 1em ; margin-bottom: 1em }
|
||||
div.line-block div.line-block { margin-top: 0 ; margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
div.sidebar { margin-left: 1em ; border: medium outset ;
|
||||
padding: 1em ; background-color: #ffffee ; width: 40% ; float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric { font-family: sans-serif ; font-size: medium }
|
||||
div.system-messages { margin: 5em }
|
||||
div.system-messages h1 { color: red }
|
||||
div.system-message { border: medium outset ; padding: 1em }
|
||||
div.system-message p.system-message-title { color: red ; font-weight: bold }
|
||||
div.topic { margin: 2em;}
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
h1.title { text-align: center }
|
||||
h2.subtitle { text-align: center }
|
||||
hr.docutils { width: 75% }
|
||||
img.align-left { clear: left }
|
||||
img.align-right { clear: right }
|
||||
ol.simple, ul.simple { margin-bottom: 1em }
|
||||
ol.arabic { list-style: decimal }
|
||||
ol.loweralpha { list-style: lower-alpha }
|
||||
ol.upperalpha { list-style: upper-alpha }
|
||||
ol.lowerroman { list-style: lower-roman }
|
||||
ol.upperroman { list-style: upper-roman }
|
||||
p.attribution { text-align: right ; margin-left: 50% }
|
||||
p.caption { font-style: italic }
|
||||
p.credits { font-style: italic ; font-size: smaller }
|
||||
p.label { white-space: nowrap }
|
||||
p.rubric { font-weight:bold;font-size:larger;color:maroon;text-align:center}
|
||||
p.sidebar-title {font-family: sans-serif ;font-weight: bold ;font-size: larger }
|
||||
p.sidebar-subtitle {font-family: sans-serif ; font-weight: bold }
|
||||
p.topic-title { font-weight: bold }
|
||||
pre.address { margin-bottom: 0;margin-top:0;font-family:serif;font-size:100% }
|
||||
pre.literal-block, pre.doctest-block {margin-left: 2em ;margin-right: 2em }
|
||||
span.classifier {font-family: sans-serif;font-style: oblique }
|
||||
span.classifier-delimiter {font-family: sans-serif;font-weight: bold }
|
||||
span.interpreted {font-family: sans-serif }
|
||||
span.option {white-space: nowrap }
|
||||
span.pre {white-space: pre }
|
||||
span.problematic {color: red }
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation { border-left: solid 1px gray; margin-left: 1px }
|
||||
table.docinfo {margin: 2em 4em }
|
||||
table.docutils {margin-top: 0.5em;margin-bottom: 0.5em }
|
||||
table.footnote {border-left: solid 1px black;margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {padding-left: 0.5em;padding-right: 0.5em;
|
||||
vertical-align: top}
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold;text-align: left;white-space: nowrap;padding-left: 0 }
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {font-size: 100% }
|
||||
ul.auto-toc { list-style-type: none }
|
||||
/*a.reference { color: #E00000; font-weight:bold;}
|
||||
a.reference:hover {color: #E00000;background-color: #ffff00;display: margin;
|
||||
font-weight:bold;}*/
|
||||
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
function toggleElem(id) {
|
||||
var e = document.getElementById(id);
|
||||
e.style.display = e.style.display == 'none' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
var gOpen = 'none'
|
||||
function toggleAll() {
|
||||
gOpen = gOpen == 'none' ? 'block' : 'none';
|
||||
var i = 1
|
||||
while (1) {
|
||||
var e = document.getElementById("m"+i)
|
||||
if (!e) break;
|
||||
e.style.display = gOpen
|
||||
i++;
|
||||
}
|
||||
document.getElementById('toggleButton').value =
|
||||
gOpen == 'none' ? 'Show Details' : 'Hide Details';
|
||||
}
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="documentId">
|
||||
<h1 class="title">$title</h1>
|
||||
$content
|
||||
<small>Generated: $date $time UTC</small>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
@write "used doctempl.cfg"
|
||||
150
config/nimrod.cfg
Executable file
150
config/nimrod.cfg
Executable file
@@ -0,0 +1,150 @@
|
||||
# Configuration file for the Nimrod Compiler.
|
||||
# Generated by the koch.py script.
|
||||
# (c) 2008 Andreas Rumpf
|
||||
|
||||
# Feel free to edit the default values as you need.
|
||||
|
||||
# You may set environment variables with
|
||||
# @putenv "key" "val"
|
||||
# Environment variables cannot be used in the options, however!
|
||||
|
||||
# Just call the compiler with several options:
|
||||
cc = @if unix: gcc @else: bcc @end
|
||||
lib="$nimrod/lib"
|
||||
path="$lib/base"
|
||||
path="$lib/base/gtk"
|
||||
path="$lib/base/cairo"
|
||||
path="$lib/base/x11"
|
||||
path="$lib/windows"
|
||||
path="$lib/posix"
|
||||
path="$lib/extra"
|
||||
|
||||
# additional defines:
|
||||
#define=""
|
||||
# additional options always passed to the compiler:
|
||||
c_file_cache=on
|
||||
line_dir=off
|
||||
|
||||
hint[LineTooLong]=off
|
||||
hint[XDeclaredButNotUsed]=off
|
||||
|
||||
@if unix:
|
||||
passl= "-ldl"
|
||||
path = "$lib/base/gtk"
|
||||
@end
|
||||
|
||||
@if icc:
|
||||
passl = "-cxxlib"
|
||||
passc = "-cxxlib"
|
||||
@end
|
||||
|
||||
# Configuration for the Borland C++ Compiler:
|
||||
@if windows:
|
||||
bcc.path = r"C:\eigenes\compiler\cbuilder5\bin"
|
||||
@end
|
||||
bcc.options.debug = ""
|
||||
# turn off warnings about unreachable code and inline procs:
|
||||
bcc.options.always = "-w- -H- -q -RT- -a8 -w-8027 -w-8066"
|
||||
bcc.options.speed = "-O2 -6"
|
||||
bcc.options.size = "-O1 -6"
|
||||
|
||||
# Configuration for the Visual C/C++ compiler:
|
||||
@if vcc:
|
||||
@prepend_env path r"C:\Eigenes\compiler\vcc2005\Common7\IDE;"
|
||||
@prepend_env INCLUDE r"C:\Eigenes\compiler\vcc2005\VC\include;C:\Eigenes\compiler\vcc2005\VC\ATLMFC\INCLUDE;"
|
||||
@prepend_env LIB r"C:\Eigenes\compiler\vcc2005\VC\lib;C:\Eigenes\compiler\vcc2005\SDK\v2.0\Lib;"
|
||||
#~ @prepend_env VSINSTALLDIR C:\eigenes\compiler\vcc2005
|
||||
#~ @prepend_env VCINSTALLDIR C:\eigenes\compiler\vcc2005\VC
|
||||
#~ @prepend_env FrameworkDir C:\WINDOWS\Microsoft.NET\Framework
|
||||
#~ @prepend_env FrameworkVersion v2.0.50727
|
||||
#~ @prepend_env FrameworkSDKDir C:\eigenes\compiler\vcc2005\SDK\v2.0
|
||||
#~ @set DevEnvDir=C:\eigenes\compiler\vcc2005\Common7\IDE
|
||||
#~ @prepend_env PATH %DevEnvDir%;%VCINSTALLDIR%\BIN;%VSINSTALLDIR%\Common7\Tools;%VSINSTALLDIR%\Common7\Tools\bin;%VCINSTALLDIR%\PlatformSDK\bin;%FrameworkSDKDir%\bin;%FrameworkDir%\%FrameworkVersion%;%VCINSTALLDIR%\VCPackages;%PATH%
|
||||
#~ @prepend_env INCLUDE %VCINSTALLDIR%\ATLMFC\INCLUDE;%VCINSTALLDIR%\INCLUDE;%VCINSTALLDIR%\PlatformSDK\include;%FrameworkSDKDir%\include;%INCLUDE%
|
||||
#~ @prepend_env LIB %VCINSTALLDIR%\ATLMFC\LIB;%VCINSTALLDIR%\LIB;%VCINSTALLDIR%\PlatformSDK\lib;%FrameworkSDKDir%\lib;%LIB%
|
||||
#~ @prepend_env LIBPATH %FrameworkDir%\%FrameworkVersion%;%VCINSTALLDIR%\ATLMFC\LIB
|
||||
@end
|
||||
@if windows:
|
||||
vcc.path = r"C:\Eigenes\compiler\vcc2005\VC\bin"
|
||||
@end
|
||||
vcc.options.debug = "/GZ /ZI"
|
||||
vcc.options.always = "/nologo"
|
||||
vcc.options.speed = "/Ogityb2 /G7 /arch:SSE2"
|
||||
vcc.options.size = "/O1 /G7"
|
||||
|
||||
# Configuration for the Watcom C/C++ compiler:
|
||||
@if windows:
|
||||
wcc.path = r"C:\eigenes\compiler\watcom\binnt"
|
||||
@end
|
||||
wcc.options.debug = "-d2"
|
||||
wcc.options.always = "-6 -zw -w-"
|
||||
wcc.options.speed = "-ox -on -6 -d0 -fp6 -zW"
|
||||
wcc.options.size = "-ox -on -6 -d0 -fp6 -zW"
|
||||
|
||||
# Configuration for the GNU C/C++ compiler:
|
||||
@if windows:
|
||||
gcc.path = r"C:\eigenes\compiler\mingw\bin"
|
||||
@end
|
||||
gcc.options.debug = "-g"
|
||||
@if macosx:
|
||||
gcc.options.always = "-Wall -g -fasm-blocks"
|
||||
@else:
|
||||
gcc.options.always = "-Wall -g"
|
||||
@end
|
||||
gcc.options.speed = "-O3 -ffast-math"
|
||||
gcc.options.size = "-Os -ffast-math"
|
||||
|
||||
# Configuration for the Digital Mars C/C++ compiler:
|
||||
@if windows:
|
||||
dmc.path = r"C:\eigenes\compiler\d\dm\bin"
|
||||
@end
|
||||
dmc.options.debug = "-g"
|
||||
dmc.options.always = "-Jm"
|
||||
dmc.options.speed = "-ff -o -6"
|
||||
dmc.options.size = "-ff -o -6"
|
||||
|
||||
# Configuration for the LCC compiler:
|
||||
@if windows:
|
||||
lcc.path = r"C:\eigenes\compiler\lcc\bin"
|
||||
@end
|
||||
lcc.options.debug = "-g5"
|
||||
lcc.options.always = "-e1"
|
||||
lcc.options.speed = "-O -p6"
|
||||
lcc.options.size = "-O -p6"
|
||||
|
||||
# Configuration for the Tiny C Compiler:
|
||||
@if windows:
|
||||
tcc.path = r"C:\eigenes\compiler\tcc\bin"
|
||||
@end
|
||||
tcc.options.debug = "-b"
|
||||
tcc.options.always = ""
|
||||
tcc.options.speed = ""
|
||||
tcc.options.size = ""
|
||||
|
||||
# Configuration for the Pelles C compiler:
|
||||
@if windows:
|
||||
pcc.path = r"C:\eigenes\compiler\pellesc\bin"
|
||||
@end
|
||||
pcc.options.debug = "-Zi"
|
||||
pcc.options.always = "-Ze"
|
||||
pcc.options.speed = "-Ox"
|
||||
pcc.options.size = "-Os"
|
||||
|
||||
# Configuration for the LLVM GCC compiler:
|
||||
@if windows:
|
||||
llvm_gcc.path = r"c:\eignes\compiler\llvm-gcc\bin"
|
||||
@end
|
||||
llvm_gcc.options.debug = "-g"
|
||||
llvm_gcc.options.always = "-w"
|
||||
llvm_gcc.options.speed = "-O3 -ffast-math"
|
||||
llvm_gcc.options.size = "-Os -ffast-math"
|
||||
|
||||
@if windows:
|
||||
icc.path = r"c:\eignes\compiler\icc\bin"
|
||||
@end
|
||||
icc.options.debug = "-g"
|
||||
icc.options.always = "-w"
|
||||
icc.options.speed = "-O3 -ffast-math"
|
||||
icc.options.size = "-Os -ffast-math"
|
||||
|
||||
@write "used default config file"
|
||||
5
configure
vendored
Executable file
5
configure
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
#! /usr/bin/env sh
|
||||
|
||||
python koch.py $@ configure
|
||||
|
||||
|
||||
43
data/advopt.txt
Executable file
43
data/advopt.txt
Executable file
@@ -0,0 +1,43 @@
|
||||
Advanced commands::
|
||||
pas convert a Pascal file to Nimrod standard syntax
|
||||
pretty pretty print the inputfile
|
||||
gen_depend generate a DOT file containing the
|
||||
module dependency graph
|
||||
list_def list all defined conditionals and exit
|
||||
rst2html converts a reStructuredText file to HTML
|
||||
check checks the project for syntax and semantic
|
||||
parse parses a single file (for debugging Nimrod)
|
||||
scan tokenizes a single file (for debugging Nimrod)
|
||||
debugtrans for debugging the transformation pass
|
||||
Advanced options:
|
||||
-w, --warnings:on|off warnings ON|OFF
|
||||
--warning[X]:on|off specific warning X ON|OFF
|
||||
--hints:on|off hints ON|OFF
|
||||
--hint[X]:on|off specific hint X ON|OFF
|
||||
--cc:C_COMPILER set the C/C++ compiler to use
|
||||
--lib:PATH set the system library path
|
||||
-c, --compile_only compile only; do not assemble or link
|
||||
--no_linking compile but do not link
|
||||
--gen_script generate a compile script (in the 'rod_gen'
|
||||
subdirectory named 'compile_$project$scriptext')
|
||||
--os:SYMBOL set the target operating system (cross-compilation)
|
||||
--cpu:SYMBOL set the target processor (cross-compilation)
|
||||
--debuginfo enables debug information
|
||||
-t, --passc:OPTION pass an option to the C compiler
|
||||
-l, --passl:OPTION pass an option to the linker
|
||||
--gen_mapping generate a mapping file containing
|
||||
(Nimrod, mangled) identifier pairs
|
||||
--merge_output generate only one C output file
|
||||
--line_dir:on|off generation of #line directive ON|OFF
|
||||
--checkpoints:on|off turn on|off checkpoints; for debugging Nimrod
|
||||
--skip_cfg do not read the general configuration file
|
||||
--skip_proj_cfg do not read the project's configuration file
|
||||
--import:MODULE_FILE import the given module implicitly for each module
|
||||
--maxerr:NUMBER stop compilation after NUMBER errors; broken!
|
||||
--ast_cache:on|off caching of ASTs ON|OFF (default: OFF)
|
||||
--c_file_cache:on|off caching of generated C files ON|OFF (default: OFF)
|
||||
--index:FILE use FILE to generate a documenation index file
|
||||
--putenv:key=value set an environment variable
|
||||
--list_cmd list the commands used to execute external programs
|
||||
-v, --verbose show what Nimrod is doing
|
||||
--version show detailed version information
|
||||
258
data/ast.yml
Executable file
258
data/ast.yml
Executable file
@@ -0,0 +1,258 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
{
|
||||
'SymFlag': [ # already 32 flags!
|
||||
'sfGeneric', # whether an operator, proc or type is generic
|
||||
'sfForward', # symbol is forward directed
|
||||
'sfImportc', # symbol is external; imported
|
||||
'sfExportc', # symbol is exported (under a specified name)
|
||||
'sfVolatile', # variable is volatile
|
||||
'sfUsed', # read access of sym (for warnings) or simply used
|
||||
'sfWrite', # write access of variable (for hints)
|
||||
'sfRegister', # variable should be placed in a register
|
||||
'sfPure', # object is "pure" that means it has no type-information
|
||||
'sfCodeGenerated', # wether we have already code generated for the proc
|
||||
'sfPrivate', # symbol should be made private after module compilation
|
||||
'sfGlobal', # symbol is at global scope
|
||||
'sfResult', # variable is 'result' in proc
|
||||
'sfNoSideEffect', # proc has no side effects
|
||||
'sfMainModule', # module is the main module
|
||||
'sfSystemModule', # module is the system module
|
||||
'sfNoReturn', # proc never returns (an exit proc)
|
||||
'sfReturnsNew', # proc returns new allocated thing (allows optimizations)
|
||||
'sfInInterface', # symbol is in interface section declared
|
||||
'sfNoStatic', # symbol is used within an iterator (needed for codegen)
|
||||
# so it cannot be 'static' in the C code
|
||||
# this is called 'nostatic' in the pragma section
|
||||
'sfCompilerProc', # proc is a compiler proc, that is a C proc that is
|
||||
# needed for the code generator
|
||||
'sfCppMethod', # proc is a C++ method
|
||||
'sfDiscriminant', # field is a discriminant in a record/object
|
||||
'sfDeprecated', # symbol is deprecated
|
||||
'sfInClosure', # variable is accessed by a closure
|
||||
'sfIsCopy', # symbol is a copy; needed for proper name mangling
|
||||
'sfStar', # symbol has * visibility
|
||||
'sfMinus' # symbol has - visibility
|
||||
],
|
||||
|
||||
'TypeFlag': [
|
||||
'tfIsDistinct', # better use this flag to make it easier for accessing
|
||||
# typeKind in the code generators
|
||||
'tfGeneric', # type is a generic one
|
||||
'tfExternal', # type is external
|
||||
'tfImported', # type is imported from C
|
||||
'tfInfoGenerated', # whether we have generated type information for this type
|
||||
'tfSemChecked', # used to mark types that's semantic has been checked;
|
||||
# used to prevend endless loops during semantic checking
|
||||
'tfHasOutParams', # for a proc or iterator p:
|
||||
# it indicates that p has out or in out parameters: this
|
||||
# is used to speed up semantic checking a bit
|
||||
'tfEnumHasWholes', # enum cannot be mapped into a range
|
||||
'tfVarargs', # procedure has C styled varargs
|
||||
'tfAssignable' # can the type be assigned to?
|
||||
],
|
||||
|
||||
'TypeKind': [ # order is important!
|
||||
# Don't forget to change hti.nim if you make a change here
|
||||
'tyNone', 'tyBool', 'tyChar',
|
||||
'tyEmptySet', 'tyArrayConstr', 'tyNil', 'tyRecordConstr',
|
||||
'tyGeneric',
|
||||
'tyGenericInst', # instantiated generic type
|
||||
'tyGenericParam',
|
||||
'tyEnum', 'tyAnyEnum',
|
||||
'tyArray',
|
||||
'tyRecord',
|
||||
'tyObject',
|
||||
'tyTuple',
|
||||
'tySet',
|
||||
'tyRange',
|
||||
'tyPtr', 'tyRef',
|
||||
'tyVar',
|
||||
'tySequence',
|
||||
'tyProc',
|
||||
'tyPointer', 'tyOpenArray',
|
||||
'tyString', 'tyCString', 'tyForward',
|
||||
# numerical types:
|
||||
'tyInt', 'tyInt8', 'tyInt16', 'tyInt32', 'tyInt64', # signed integers
|
||||
'tyFloat', 'tyFloat32', 'tyFloat64', 'tyFloat128'
|
||||
],
|
||||
|
||||
'NodeKind': [ # these are pure nodes
|
||||
# order is extremely important, because ranges are used to check whether
|
||||
# a node belongs to a certain class
|
||||
'nkNone', # unknown node kind: indicates an error
|
||||
|
||||
# Expressions:
|
||||
# Atoms:
|
||||
'nkEmpty', # the node is empty
|
||||
'nkIdent', # node is an identifier
|
||||
'nkSym', # node is a symbol
|
||||
'nkType', # node is used for its typ field
|
||||
|
||||
'nkCharLit', # a character literal ''
|
||||
'nkRCharLit', # a raw character literal r''
|
||||
|
||||
'nkIntLit', # an integer literal
|
||||
'nkInt8Lit',
|
||||
'nkInt16Lit',
|
||||
'nkInt32Lit',
|
||||
'nkInt64Lit',
|
||||
'nkFloatLit', # a floating point literal
|
||||
'nkFloat32Lit',
|
||||
'nkFloat64Lit',
|
||||
'nkStrLit', # a string literal ""
|
||||
'nkRStrLit', # a raw string literal r""
|
||||
'nkTripleStrLit', # a triple string literal """
|
||||
'nkNilLit', # the nil literal
|
||||
# end of atoms
|
||||
'nkDotCall', # used to temporarily flag a nkCall node; this is used
|
||||
# for transforming ``s.len`` to ``len(s)``
|
||||
'nkCommand', # a call like ``p 2 4`` without parenthesis
|
||||
'nkCall', # a call like p(x, y) or an operation like +(a, b)
|
||||
'nkGenericCall', # a call with given type parameters
|
||||
'nkExplicitTypeListCall', # a call with given explicit typelist
|
||||
'nkExprEqExpr', # a named parameter with equals: ''expr = expr''
|
||||
'nkExprColonExpr', # a named parameter with colon: ''expr: expr''
|
||||
'nkIdentDefs', # a definition like `a, b: typeDesc = expr`
|
||||
# either typeDesc or expr may be nil; used in
|
||||
# formal parameters, var statements, etc.
|
||||
'nkInfix', # a call like (a + b)
|
||||
'nkPrefix', # a call like !a
|
||||
'nkPostfix', # something like a! (also used for visibility)
|
||||
'nkPar', # syntactic ()
|
||||
'nkCurly', # syntactic {}
|
||||
'nkBracket', # syntactic []
|
||||
'nkBracketExpr', # an expression like a[i..j, k]
|
||||
'nkPragmaExpr', # an expression like a{.pragmas.}
|
||||
'nkRange', # an expression like i..j
|
||||
'nkDotExpr', # a.b
|
||||
'nkCheckedFieldExpr', # a.b, but b is a field that needs to be checked
|
||||
'nkDerefExpr', # a^
|
||||
'nkIfExpr', # if as an expression
|
||||
'nkElifExpr',
|
||||
'nkElseExpr',
|
||||
'nkLambda', # lambda expression
|
||||
'nkAccQuoted', # `a` as a node
|
||||
'nkHeaderQuoted', # `a(x: int)` as a node
|
||||
|
||||
'nkSetConstr', # a set constructor {}
|
||||
'nkConstSetConstr', # a set constructor with only constant expressions
|
||||
'nkArrayConstr', # an array constructor []
|
||||
'nkConstArrayConstr', # an array constructor with only constant expressions
|
||||
'nkRecordConstr', # a record constructor []
|
||||
'nkConstRecordConstr', # a record constructor with only constant expressions
|
||||
'nkTableConstr', # a table constructor {expr: expr}
|
||||
'nkConstTableConstr', # a table constructor with only constant expressions
|
||||
'nkQualified', # describes a.b for qualified identifiers
|
||||
'nkHiddenStdConv', # an implicit standard type conversion
|
||||
'nkHiddenSubConv', # an implicit type conversion from a subtype
|
||||
# to a supertype
|
||||
'nkHiddenCallConv', # an implicit type conversion via a type converter
|
||||
'nkConv', # a type conversion
|
||||
'nkCast', # a type cast
|
||||
'nkAddr', # a addr expression
|
||||
# end of expressions
|
||||
|
||||
'nkAsgn', # a = b
|
||||
'nkDefaultTypeParam', # `ident = typeDesc` in generic parameters
|
||||
'nkGenericParams', # generic parameters
|
||||
'nkFormalParams', # formal parameters
|
||||
'nkOfInherit', # inherited from symbol
|
||||
|
||||
'nkModule', # the syntax tree of a module
|
||||
'nkProcDef', # a proc
|
||||
'nkConverterDef', # a converter
|
||||
'nkMacroDef', # a macro
|
||||
'nkTemplateDef', # a template
|
||||
'nkIteratorDef', # an iterator
|
||||
|
||||
'nkOfBranch', # used inside case statements for (cond, action)-pairs
|
||||
'nkElifBranch', # used in if statements
|
||||
'nkExceptBranch', # an except section
|
||||
'nkElse', # an else part
|
||||
'nkMacroStmt', # a macro statement
|
||||
'nkAsmStmt', # an assembler block
|
||||
'nkPragma', # a pragma statement
|
||||
'nkIfStmt', # an if statement
|
||||
'nkWhenStmt', # a when statement
|
||||
'nkForStmt', # a for statement
|
||||
'nkWhileStmt', # a while statement
|
||||
'nkCaseStmt', # a case statement
|
||||
'nkVarSection', # a var section
|
||||
'nkConstSection', # a const section
|
||||
'nkConstDef', # a const definition
|
||||
'nkTypeSection', # a type section (consists of type definitions)
|
||||
'nkTypeDef', # a type definition
|
||||
'nkYieldStmt', # the yield statement as a tree
|
||||
'nkTryStmt', # a try statement
|
||||
'nkFinally', # a finally section
|
||||
'nkRaiseStmt', # a raise statement
|
||||
'nkReturnStmt', # a return statement
|
||||
'nkBreakStmt', # a break statement
|
||||
'nkContinueStmt', # a continue statement
|
||||
'nkBlockStmt', # a block statement
|
||||
'nkGotoStmt', # used by the transformation pass; first son is a sym
|
||||
# node containing a label
|
||||
'nkDiscardStmt', # a discard statement
|
||||
'nkStmtList', # a list of statements
|
||||
'nkImportStmt', # an import statement
|
||||
'nkFromStmt', # a from * import statement
|
||||
'nkImportAs', # an `import xyx as abc` section
|
||||
'nkIncludeStmt', # an include statement
|
||||
'nkAccessStmt', # used internally for iterators
|
||||
'nkCommentStmt', # a comment statement
|
||||
'nkStmtListExpr', # a statement list followed by an expr; this is used
|
||||
# to allow powerful multi-line templates
|
||||
'nkBlockExpr', # a statement block ending in an expr; this is used
|
||||
# to allowe powerful multi-line templates that open a
|
||||
# temporary scope
|
||||
'nkVm', # indicates a virtual instruction; integer field is
|
||||
# used for the concrete opcode
|
||||
|
||||
# types as syntactic trees:
|
||||
'nkTypeOfExpr',
|
||||
'nkRecordTy',
|
||||
'nkObjectTy',
|
||||
'nkRecList', # list of record/object parts
|
||||
'nkRecCase', # case section of record/object
|
||||
'nkRecWhen', # when section of record/object
|
||||
'nkRefTy',
|
||||
'nkPtrTy',
|
||||
'nkVarTy',
|
||||
'nkProcTy',
|
||||
'nkEnumTy',
|
||||
'nkEnumFieldDef' # `ident = expr` in an enumeration
|
||||
],
|
||||
|
||||
'SymKind': [
|
||||
# the different symbols (start with the prefix sk);
|
||||
# order is important for the documentation generator!
|
||||
'skUnknownSym', # unknown symbol: used for parsing assembler blocks
|
||||
'skConditional', # symbol for the preprocessor (may become obsolete)
|
||||
'skDynLib', # symbol represents a dynamic library; this is used
|
||||
# internally; it does not exist in Nimrod code
|
||||
'skParam', # a parameter
|
||||
'skTypeParam', # a type parameter; example: proc x[T]() <- `T`
|
||||
'skTemp', # a temporary variable (introduced by compiler)
|
||||
'skType', # a type
|
||||
'skConst', # a constant
|
||||
'skVar', # a variable
|
||||
'skProc', # a proc
|
||||
'skIterator', # an iterator
|
||||
'skConverter', # a type converter
|
||||
'skMacro', # a macro
|
||||
'skTemplate', # a template
|
||||
'skField', # a field in a record or object
|
||||
'skEnumField', # an identifier in an enum
|
||||
'skForVar', # a for loop variable
|
||||
'skModule', # module identifier
|
||||
'skLabel' # a label (for block statement)
|
||||
]
|
||||
}
|
||||
29
data/basicopt.txt
Executable file
29
data/basicopt.txt
Executable file
@@ -0,0 +1,29 @@
|
||||
Usage::
|
||||
nimrod command [options] inputfile [arguments]
|
||||
Command::
|
||||
compile compile project with default code generator (C)
|
||||
compile_to_c compile project with C code generator
|
||||
compile_to_cpp compile project with C++ code generator
|
||||
doc generate the documentation for inputfile;
|
||||
with --run switch opens it with $BROWSER
|
||||
Arguments:
|
||||
arguments are passed to the program being run (if --run option is selected)
|
||||
Options:
|
||||
-p, --path:PATH add path to search paths
|
||||
-o, --out:FILE set the output filename
|
||||
-d, --define:SYMBOL define a conditional symbol
|
||||
-u, --undef:SYMBOL undefine a conditional symbol
|
||||
-b, --force_build force rebuilding of all modules
|
||||
--stack_trace:on|off code generation for stack trace ON|OFF
|
||||
--line_trace:on|off code generation for line trace ON|OFF
|
||||
--debugger:on|off turn Embedded Nimrod Debugger ON|OFF
|
||||
-x, --checks:on|off code generation for all runtime checks ON|OFF
|
||||
--range_checks:on|off code generation for range checks ON|OFF
|
||||
--bound_checks:on|off code generation for bound checks ON|OFF
|
||||
--overflow_checks:on|off code generation for over-/underflow checks ON|OFF
|
||||
-a, --assertions:on|off code generation for assertions ON|OFF
|
||||
--opt:none|speed|size optimize not at all or for speed|size
|
||||
--app:console|gui|lib generate a console|GUI application or a shared lib
|
||||
-r, --run run the compiled program with given arguments
|
||||
--advanced show advanced command line switches
|
||||
-h, --help show this help
|
||||
1692
data/ccomps.txt
Executable file
1692
data/ccomps.txt
Executable file
File diff suppressed because it is too large
Load Diff
22
data/changes.txt
Executable file
22
data/changes.txt
Executable file
@@ -0,0 +1,22 @@
|
||||
0.1.0
|
||||
* new config system
|
||||
* new build system
|
||||
* source renderer
|
||||
* pas2nim integrated
|
||||
* support for C++
|
||||
* local variables are always initialized
|
||||
* Rod file reader and writer
|
||||
* new --out, -o command line options
|
||||
* fixed bug in nimconf.pas: we now have several
|
||||
string token types
|
||||
* changed nkIdentDef to nkIdentDefs
|
||||
* added type(expr) in the parser and the grammer
|
||||
* added template
|
||||
* added command calls
|
||||
* added case in records/objects
|
||||
* added --skip_proj_cfg switch for nim.dpr
|
||||
* added missing features to pasparse
|
||||
* rewrote the source generator
|
||||
* ``addr`` and ``cast`` are now keywords; grammar updated
|
||||
* implemented ` notation; grammar updated
|
||||
* specification replaced by a manual
|
||||
19
data/keywords.txt
Executable file
19
data/keywords.txt
Executable file
@@ -0,0 +1,19 @@
|
||||
addr and as asm
|
||||
block break
|
||||
case cast const continue converter
|
||||
discard div
|
||||
elif else end enum except exception
|
||||
finally for from generic
|
||||
if implies import in include is isnot iterator
|
||||
lambda
|
||||
macro method mod
|
||||
nil not notin
|
||||
object of or out
|
||||
proc ptr
|
||||
raise record ref return
|
||||
shl shr
|
||||
template try type
|
||||
var
|
||||
when where while with without
|
||||
xor
|
||||
yield
|
||||
176
data/magic.yml
Executable file
176
data/magic.yml
Executable file
@@ -0,0 +1,176 @@
|
||||
# All the magics of the system module:
|
||||
# order has been changed!
|
||||
[
|
||||
'None',
|
||||
'Defined',
|
||||
'New',
|
||||
'NewFinalize',
|
||||
'Low',
|
||||
'High',
|
||||
'SizeOf',
|
||||
'RegisterFinalizer',
|
||||
'Succ',
|
||||
'Pred',
|
||||
'Inc',
|
||||
'Dec',
|
||||
'LengthOpenArray',
|
||||
'LengthStr',
|
||||
'LengthArray',
|
||||
'LengthSeq',
|
||||
'Incl',
|
||||
'Excl',
|
||||
'Card',
|
||||
'Ord',
|
||||
'Chr',
|
||||
|
||||
# binary arithmetic with and without overflow checking:
|
||||
'AddI',
|
||||
'SubI',
|
||||
'MulI',
|
||||
'DivI',
|
||||
'ModI',
|
||||
'AddI64',
|
||||
'SubI64',
|
||||
'MulI64',
|
||||
'DivI64',
|
||||
'ModI64',
|
||||
|
||||
# other binary arithmetic operators:
|
||||
'ShrI',
|
||||
'ShlI',
|
||||
'BitandI',
|
||||
'BitorI',
|
||||
'BitxorI',
|
||||
'MinI',
|
||||
'MaxI',
|
||||
'ShrI64',
|
||||
'ShlI64',
|
||||
'BitandI64',
|
||||
'BitorI64',
|
||||
'BitxorI64',
|
||||
'MinI64',
|
||||
'MaxI64',
|
||||
'AddF64',
|
||||
'SubF64',
|
||||
'MulF64',
|
||||
'DivF64',
|
||||
'MinF64',
|
||||
'MaxF64',
|
||||
'AddU',
|
||||
'SubU',
|
||||
'MulU',
|
||||
'DivU',
|
||||
'ModU',
|
||||
'AddU64',
|
||||
'SubU64',
|
||||
'MulU64',
|
||||
'DivU64',
|
||||
'ModU64',
|
||||
|
||||
# comparison operators:
|
||||
'EqI',
|
||||
'LeI',
|
||||
'LtI',
|
||||
'EqI64',
|
||||
'LeI64',
|
||||
'LtI64',
|
||||
'EqF64',
|
||||
'LeF64',
|
||||
'LtF64',
|
||||
'LeU',
|
||||
'LtU',
|
||||
'LeU64',
|
||||
'LtU64',
|
||||
'EqEnum',
|
||||
'LeEnum',
|
||||
'LtEnum',
|
||||
'EqCh',
|
||||
'LeCh',
|
||||
'LtCh',
|
||||
'EqB',
|
||||
'LeB',
|
||||
'LtB',
|
||||
'EqRef',
|
||||
'EqProc',
|
||||
'EqUntracedRef',
|
||||
'LePtr',
|
||||
'LtPtr',
|
||||
'EqCString',
|
||||
'Xor',
|
||||
|
||||
# unary arithmetic with and without overflow checking:
|
||||
'UnaryMinusI',
|
||||
'UnaryMinusI64',
|
||||
'AbsI',
|
||||
'AbsI64',
|
||||
|
||||
# other unary operations:
|
||||
'Not',
|
||||
'UnaryPlusI',
|
||||
'BitnotI',
|
||||
'UnaryPlusI64',
|
||||
'BitnotI64',
|
||||
'UnaryPlusF64',
|
||||
'UnaryMinusF64',
|
||||
'AbsF64',
|
||||
'Ze',
|
||||
'Ze64',
|
||||
'ToU8',
|
||||
'ToU16',
|
||||
'ToU32',
|
||||
'ToFloat',
|
||||
'ToBiggestFloat',
|
||||
'ToInt',
|
||||
'ToBiggestInt',
|
||||
|
||||
# special ones:
|
||||
'And',
|
||||
'Or',
|
||||
'EqStr',
|
||||
'LeStr',
|
||||
'LtStr',
|
||||
'EqSet',
|
||||
'LeSet',
|
||||
'LtSet',
|
||||
'MulSet',
|
||||
'PlusSet',
|
||||
'MinusSet',
|
||||
'SymDiffSet',
|
||||
'ConStrStr',
|
||||
'ConArrArr',
|
||||
'ConArrT',
|
||||
'ConTArr',
|
||||
'ConTT',
|
||||
'Slice',
|
||||
'AppendStrCh',
|
||||
'AppendStrStr',
|
||||
'AppendSeqElem',
|
||||
'AppendSeqSeq',
|
||||
'InRange',
|
||||
'InSet',
|
||||
'Is',
|
||||
'Asgn',
|
||||
'Repr',
|
||||
'Exit',
|
||||
'SetLengthStr',
|
||||
'SetLengthSeq',
|
||||
'Assert',
|
||||
'Swap',
|
||||
|
||||
# magic type constructors:
|
||||
'Array',
|
||||
'OpenArray',
|
||||
'Range',
|
||||
'Tuple',
|
||||
'Set',
|
||||
'Seq',
|
||||
|
||||
# magic constants:
|
||||
'CompileDate',
|
||||
'CompileTime',
|
||||
'NimrodVersion',
|
||||
'NimrodMajor',
|
||||
'NimrodMinor',
|
||||
'NimrodPatch',
|
||||
'CpuEndian'
|
||||
]
|
||||
282
data/messages.yml
Executable file
282
data/messages.yml
Executable file
@@ -0,0 +1,282 @@
|
||||
# This file contains all the messages of the Nimrod compiler
|
||||
# (c) 2008 Andreas Rumpf
|
||||
|
||||
[
|
||||
# fatal errors:
|
||||
{'errUnknown': 'unknown error'},
|
||||
{'errIllFormedAstX': 'illformed AST: $1'},
|
||||
{'errCannotOpenFile': "cannot open '$1'"},
|
||||
{'errInternal': 'internal error: $1'},
|
||||
|
||||
# other errors:
|
||||
{'errGenerated': '$1'},
|
||||
{'errXCompilerDoesNotSupportCpp': "'$1' compiler does not support C++"},
|
||||
|
||||
# errors:
|
||||
{'errStringLiteralExpected': 'string literal expected'},
|
||||
{'errIntLiteralExpected': 'integer literal expected'},
|
||||
{'errInvalidCharacterConstant': 'invalid character constant'},
|
||||
{'errClosingTripleQuoteExpected':
|
||||
'closing """ expected, but end of file reached'},
|
||||
{'errClosingQuoteExpected': 'closing " expected'},
|
||||
{'errTabulatorsAreNotAllowed': 'tabulators are not allowed'},
|
||||
{'errInvalidToken': 'invalid token: $1'},
|
||||
{'errLineTooLong': 'line too long'},
|
||||
{'errInvalidNumber': '$1 is not a valid number'},
|
||||
{'errNumberOutOfRange': '$1 is too large or too small'},
|
||||
{'errNnotAllowedInCharacter': '\\n not allowed in character literal'},
|
||||
{'errClosingBracketExpected': "closing ']' expected, but end of file reached"},
|
||||
{'errMissingFinalQuote': "missing final '"},
|
||||
{'errIdentifierExpected': "identifier expected, but found '$1'"},
|
||||
{'errOperatorExpected': "operator expected, but found '$1'"},
|
||||
{'errTokenExpected': "'$1' expected"},
|
||||
{'errStringAfterIncludeExpected': "string after 'include' expected"},
|
||||
{'errRecursiveInclude': "recursive include file: '$1'"},
|
||||
{'errAtIfExpected': "'@if' expected"},
|
||||
{'errAtIfExpectedBeforeElse': "'@if' expected before '@else'"},
|
||||
{'errAtIfExpectedBeforeElif': "'@if' expected before '@elif'"},
|
||||
{'errAtEndExpected': "'@end' expected"},
|
||||
{'errOnOrOffExpected': "'on' or 'off' expected"},
|
||||
{'errNoneSpeedOrSizeExpected': "'none', 'speed' or 'size' expected"},
|
||||
{'errInvalidPragma': 'invalid pragma'},
|
||||
{'errUnknownPragma': "unknown pragma: '$1'"},
|
||||
{'errPragmaXHereNotAllowed': "pragma '$1' here not allowed"},
|
||||
{'errUnknownDirective': "unknown directive: '$1'"},
|
||||
{'errInvalidDirective': 'invalid directive'},
|
||||
{'errAtPopWithoutPush': "'pop' without a 'push' pragma"},
|
||||
{'errEmptyAsm': 'empty asm statement makes no sense'},
|
||||
{'errAsgnInvalidInExpr': "'=' invalid in an expression; probably '==' meant"},
|
||||
{'errInvalidIndentation': 'invalid indentation'},
|
||||
{'errExceptionExpected': 'exception expected'},
|
||||
{'errExceptionAlreadyHandled': 'exception already handled'},
|
||||
{'errReturnNotAllowedHere': "'return' only allowed in routine"},
|
||||
{'errYieldNotAllowedHere': "'yield' only allowed in iterator"},
|
||||
{'errInvalidNumberOfYieldExpr': "invalid number of 'yield' expresions"},
|
||||
{'errReturnInvalidInIterator': "'return' not allowed in iterator"},
|
||||
{'errCannotReturnExpr': 'current routine cannot return an expression'},
|
||||
{'errAttemptToRedefine': "attempt to redefine '$1'"},
|
||||
{'errStmtInvalidAfterReturn':
|
||||
"statement not allowed after 'return', 'break' or 'raise'"},
|
||||
{'errStmtExpected': 'statement expected'},
|
||||
{'errYieldOnlyInInterators': "'yield' statement is only allowed in iterators"},
|
||||
{'errInvalidLabel': "'$1' is no label"},
|
||||
{'errInvalidCmdLineOption': "invalid command line option: '$1'"},
|
||||
{'errCmdLineArgExpected': "argument for command line option expected: '$1'"},
|
||||
{'errInvalidVarSubstitution': "invalid variable substitution in '$1'"},
|
||||
{'errUnknownVar': "unknown variable: '$1'"},
|
||||
{'errUnknownCcompiler': "unknown C compiler: '$1'"},
|
||||
{'errOnOrOffExpectedButXFound': "'on' or 'off' expected, but '$1' found"},
|
||||
{'errNoneBoehmRefcExpectedButXFound':
|
||||
"'none', 'boehm' or 'refc' expected, but '$1' found"},
|
||||
{'errNoneSpeedOrSizeExpectedButXFound':
|
||||
"'none', 'speed' or 'size' expected, but '$1' found"},
|
||||
{'errGuiConsoleOrLibExpectedButXFound':
|
||||
"'gui', 'console' or 'lib' expected, but '$1' found"},
|
||||
{'errUnknownOS': "unknown OS: '$1'"},
|
||||
{'errUnknownCPU': "unknown CPU: '$1'"},
|
||||
{'errGenOutExpectedButXFound':
|
||||
"'c', 'c++' or 'yaml' expected, but '$1' found"},
|
||||
{'errArgsNeedRunOption':
|
||||
"arguments can only be given if the '--run' option is selected"},
|
||||
{'errInvalidMultipleAsgn': 'multiple assignment is not allowed'},
|
||||
{'errColonOrEqualsExpected': "':' or '=' expected, but found '$1'"},
|
||||
{'errExprExpected': "expression expected, but found '$1'"},
|
||||
{'errUndeclaredIdentifier': "undeclared identifier: '$1'"},
|
||||
{'errUseQualifier': "ambigious identifier: '$1' -- use a qualifier"},
|
||||
{'errTwiceForwarded': "'$1' is forwarded twice"},
|
||||
{'errTypeExpected': 'type expected'},
|
||||
{'errSystemNeeds': "system module needs '$1'"},
|
||||
{'errExecutionOfProgramFailed': 'execution of an external program failed'},
|
||||
{'errNotOverloadable': "overloaded '$1' leads to ambigious calls"},
|
||||
{'errInvalidArgForX': "invalid argument for '$1'"},
|
||||
{'errStmtHasNoEffect': 'statement has no effect'},
|
||||
{'errXExpectsTypeOrValue': "'$1' expects a type or value"},
|
||||
{'errXExpectsArrayType': "'$1' expects an array type"},
|
||||
{'errIteratorCannotBeInstantiated':
|
||||
"'$1' cannot be instantiated because its body has not been compiled yet"},
|
||||
{'errExprWithNoTypeCannotBeConverted':
|
||||
'expression with no type cannot be converted'},
|
||||
{'errExprWithNoTypeCannotBeCasted': 'expression with no type cannot be casted'},
|
||||
{'errConstantDivisionByZero': 'constant division by zero'},
|
||||
{'errOrdinalTypeExpected': 'ordinal type expected'},
|
||||
{'errOrdinalOrFloatTypeExpected': 'ordinal or float type expected'},
|
||||
{'errOverOrUnderflow': 'over- or underflow'},
|
||||
{'errCannotEvalXBecauseIncompletelyDefined':
|
||||
"cannot evalutate '$1' because type is not defined completely"},
|
||||
{'errChrExpectsRange0_255': "'chr' expects an int in the range 0..255"},
|
||||
{'errStaticAssertFailed': "'staticAssert' failed: condition is false"},
|
||||
{'errStaticAssertCannotBeEval':
|
||||
"argument to 'staticAssert' cannot be evaluated at compile time"},
|
||||
{'errDotRequiresRecordOrObjectType': "'.' requires a record or object type"},
|
||||
{'errUndeclaredFieldX': "undeclared field: '$1'"},
|
||||
{'errIndexNoIntType': 'index has to be an integer type'},
|
||||
{'errIndexOutOfBounds': 'index out of bounds'},
|
||||
{'errIndexTypesDoNotMatch': 'index types do not match'},
|
||||
{'errBracketsInvalidForType': "'[]' operator invalid for this type"},
|
||||
{'errValueOutOfSetBounds': 'value out of set bounds'},
|
||||
{'errFieldInitTwice': "field initialized twice: '$1'"},
|
||||
{'errFieldNotInit': "field '$1' not initialized"},
|
||||
{'errExprCannotBeCalled': 'expression cannot be called'},
|
||||
{'errExprHasNoType': 'expression has no type'},
|
||||
{'errExprXHasNoType': "expression '$1' has no type"},
|
||||
{'errCastNotInSafeMode': "'cast' not allowed in safe mode"},
|
||||
{'errExprCannotBeCastedToX': 'expression cannot be casted to $1'},
|
||||
{'errUndefinedPrefixOpr': 'undefined prefix operator: $1'},
|
||||
{'errCommaOrParRiExpected': "',' or ')' expected"},
|
||||
{'errCurlyLeOrParLeExpected': "'{' or '(' expected"},
|
||||
{'errSectionExpected': "section ('type', 'proc', etc.) expected"},
|
||||
{'errImplemenationExpected': "'implementation' or end of file expected"},
|
||||
{'errRangeExpected': 'range expected'},
|
||||
{'errInvalidTypeDescription': 'invalid type description'},
|
||||
{'errAttemptToRedefineX': "attempt to redefine '$1'"},
|
||||
{'errMagicOnlyInSystem': "'magic' only allowed in system module"},
|
||||
{'errUnknownOperatorX': "unkown operator: '$1'"},
|
||||
{'errPowerOfTwoExpected': 'power of two expected'},
|
||||
{'errStringMayNotBeEmpty': 'string literal may not be empty'},
|
||||
{'errCallConvExpected': 'calling convention expected'},
|
||||
{'errProcOnlyOneCallConv': 'a proc can only have one calling convention'},
|
||||
{'errSymbolMustBeImported': "symbol must be imported if 'lib' pragma is used"},
|
||||
{'errExprMustBeBool': "expression must be of type 'bool'"},
|
||||
{'errConstExprExpected': 'constant expression expected'},
|
||||
{'errDuplicateCaseLabel': 'duplicate case label'},
|
||||
{'errRangeIsEmpty': 'range is empty'},
|
||||
{'errSelectorMustBeOfCertainTypes':
|
||||
'selector must be of an ordinal type, real or string'},
|
||||
{'errSelectorMustBeOrdinal':
|
||||
'selector must be of an ordinal type'},
|
||||
{'errOrdXMustNotBeNegative': 'ord($1) must not be negative'},
|
||||
{'errLenXinvalid': 'len($1) must be less than 32768'},
|
||||
{'errWrongNumberOfLoopVariables': 'wrong number of loop variables'},
|
||||
{'errExprCannotBeRaised': 'only objects can be raised'},
|
||||
{'errBreakOnlyInLoop': "'break' only allowed in loop construct"},
|
||||
{'errTypeXhasUnknownSize': "type '$1' has unknown size"},
|
||||
{'errConstNeedsConstExpr':
|
||||
'a constant can only be initialized with a constant expression'},
|
||||
{'errConstNeedsValue': 'a constant needs a value'},
|
||||
{'errResultCannotBeOpenArray': 'the result type cannot be on open array'},
|
||||
{'errSizeTooBig': "computing the type's size produced an overflow"},
|
||||
{'errSetTooBig': 'set is too large'},
|
||||
{'errBaseTypeMustBeOrdinal': 'base type of a set must be an ordinal'},
|
||||
{'errInheritanceOnlyWithObjects': 'inheritance only works with an object'},
|
||||
{'errInheritanceOnlyWithEnums': 'inheritance only works with an enum'},
|
||||
{'errIllegalRecursionInTypeX': "illegal recursion in type '$1'"},
|
||||
{'errCannotInstantiateX': "cannot instantiate: '$1'"},
|
||||
{'errExprHasNoAddress': 'expression has no address'},
|
||||
{'errVarForOutParamNeeded':
|
||||
'to an out parameter a variable needs to be passed'},
|
||||
{'errPureTypeMismatch': 'type mismatch'},
|
||||
{'errTypeMismatch': 'type mismatch: got ('},
|
||||
{'errButExpected': 'but expected one of: '},
|
||||
{'errButExpectedX': "but expected '$1'"},
|
||||
{'errAmbigiousCallXYZ': 'ambigious call; both $1 and $2 match for: $3'},
|
||||
{'errWrongNumberOfTypeParams': 'wrong number of type parameters'},
|
||||
{'errOutParamNoDefaultValue': 'out parameters cannot have default values'},
|
||||
{'errInlineProcHasNoAddress': 'an inline proc has no address'},
|
||||
{'errXCannotBeInParamDecl': '$1 cannot be declared in parameter declaration'},
|
||||
{'errPragmaOnlyInHeaderOfProc':
|
||||
'pragmas are only in the header of a proc allowed'},
|
||||
{'errImportedProcCannotHaveImpl':
|
||||
'an imported proc cannot have an implementation'},
|
||||
{'errImplOfXNotAllowed': "implementation of '$1' is not allowed here"},
|
||||
{'errImplOfXexpected': "implementation of '$1' expected"},
|
||||
{'errDiscardValue': 'value returned by statement has to be discarded'},
|
||||
{'errInvalidDiscard': 'statement returns no value that can be discarded'},
|
||||
{'errUnknownPrecedence':
|
||||
"unknown precedence for operator; use 'infix: prec' pragma"},
|
||||
{'errIllegalConvFromXtoY': 'conversion from $1 to $2 is invalid'},
|
||||
{'errTypeMismatchExpectedXGotY': "type mismatch: expected '$1', but got '$2'"},
|
||||
{'errCannotBindXTwice': "cannot bind parameter '$1' twice"},
|
||||
{'errInvalidOrderInEnumX': "invalid order in enum '$1'"},
|
||||
{'errEnumXHasWholes': "enum '$1' has wholes"},
|
||||
{'errExceptExpected': "'except' or 'finally' expected"},
|
||||
{'errInvalidTry': "after catch all 'except' or 'finally' no section may follow"},
|
||||
{'errEofExpectedButXFound': "end of file expected, but found token '$1'"},
|
||||
{'errOptionExpected': "option expected, but found '$1'"},
|
||||
{'errCannotEvaluateForwardConst': 'cannot evaluate forwarded constant'},
|
||||
{'errXisNoLabel': "'$1' is not a label"},
|
||||
{'errXNeedsConcreteType': "'$1' needs to be of a non-generic type"},
|
||||
{'errNotAllCasesCovered': 'not all cases are covered'},
|
||||
{'errStringRange': 'string range in case statement not allowed'},
|
||||
{'errUnkownSubstitionVar': "unknown substitution variable: '$1'"},
|
||||
{'errComplexStmtRequiresInd': 'complex statement requires indentation'},
|
||||
{'errXisNotCallable': "'$1' is not callable"},
|
||||
{'errNoPragmasAllowedForX': 'no pragmas allowed for $1'},
|
||||
{'errNoGenericParamsAllowedForX': 'no generic parameters allowed for $1'},
|
||||
{'errInvalidParamKindX': "invalid param kind: '$1'"},
|
||||
{'errDefaultArgumentInvalid': 'default argument invalid'},
|
||||
{'errNamedParamHasToBeIdent': 'named parameter has to be an identifier'},
|
||||
{'errNoReturnTypeForX': 'no return type for $1 allowed'},
|
||||
{'errConvNeedsOneArg': 'a type conversion needs exactly one argument'},
|
||||
{'errInvalidPragmaX': 'invalid pragma: $1'},
|
||||
{'errXNotAllowedHere': '$1 here not allowed'},
|
||||
{'errInvalidControlFlowX': 'invalid control flow: $1'},
|
||||
{'errATypeHasNoValue': 'a type has no value'},
|
||||
{'errXisNoType': "'$1' is no type"},
|
||||
{'errCircumNeedsPointer': "'^' needs a pointer or reference type"},
|
||||
{'errInvalidContextForBuiltinX': "invalid context for builtin '$1'"},
|
||||
{'errInvalidExpression': 'invalid expression'},
|
||||
{'errInvalidExpressionX': "invalid expression: '$1'"},
|
||||
{'errEnumHasNoValueX': "enum has no value '$1'"},
|
||||
{'errNamedExprExpected': 'named expression expected'},
|
||||
{'errNamedExprNotAllowed': 'named expression here not allowed'},
|
||||
{'errXExpectsOneTypeParam': "'$1' expects one type parameter"},
|
||||
{'errArrayExpectsTwoTypeParams': 'array expects two type parameters'},
|
||||
{'errInvalidVisibilityX': "invalid invisibility: '$1'"},
|
||||
{'errInitHereNotAllowed': 'initialization here not allowed'},
|
||||
{'errXCannotBeAssignedTo': "'$1' cannot be assigned to"},
|
||||
{'errIteratorNotAllowed':
|
||||
"iterators can only be defined at the module's top level"},
|
||||
{'errIteratorNeedsImplementation': 'iterator needs an implementation'},
|
||||
{'errIteratorNeedsReturnType': 'iterator needs a return type'},
|
||||
{'errInvalidCommandX': "invalid command: '$1'"},
|
||||
{'errXOnlyAtModuleScope': "'$1' is only allowed at top level"},
|
||||
{'errTypeXNeedsImplementation': "type '$1' needs an implementation"},
|
||||
{'errTemplateInstantiationTooNested': 'template instantiation too nested'},
|
||||
{'errInstantiationFrom': 'instantiation from here'},
|
||||
{'errInvalidIndexValueForTuple': 'invalid index value for tuple subscript'},
|
||||
{'errCommandExpectsFilename': 'command expects a filename argument'},
|
||||
{'errXExpected': "'$1' expected"},
|
||||
{'errInvalidSectionStart': 'invalid section start'},
|
||||
{'errGridTableNotImplemented': 'grid table is not implemented'},
|
||||
{'errGeneralParseError': 'general parse error'},
|
||||
{'errNewSectionExpected': 'new section expected'},
|
||||
{'errWhitespaceExpected': "whitespace expected, got '$1'"},
|
||||
{'errXisNoValidIndexFile': "'$1' is no valid index file"},
|
||||
{'errCannotRenderX': "cannot render reStructuredText element '$1'"},
|
||||
|
||||
# user error message:
|
||||
{'errUser': '$1'},
|
||||
|
||||
# warnings:
|
||||
{'warnCannotOpenFile': "cannot open '$1'"},
|
||||
{'warnOctalEscape':
|
||||
'octal escape sequences do not exist; leading zero is ignored'},
|
||||
{'warnXIsNeverRead': "'$1' is never read"},
|
||||
{'warnXmightNotBeenInit': "'$1' might not have been initialized"},
|
||||
{'warnCannotWriteMO2': "cannot write file '$1'"},
|
||||
{'warnCannotReadMO2': "cannot read file '$1'"},
|
||||
{'warnDeprecated': "'$1' is deprecated"},
|
||||
{'warnSmallLshouldNotBeUsed':
|
||||
"'l' should not be used as an identifier; may look like '1' (one)"},
|
||||
{'warnUnknownMagic': "unknown magic '$1' might crash the compiler"},
|
||||
{'warnRedefinitionOfLabel': "redefinition of label '$1'"},
|
||||
{'warnUnknownSubstitutionX': "unknown substitution '$1'"},
|
||||
{'warnLanguageXNotSupported': "language '$1' not supported"},
|
||||
{'warnCommentXIgnored': "comment '$1' ignored"},
|
||||
# user warning message:
|
||||
{'warnUser': '$1'},
|
||||
|
||||
# hints:
|
||||
{'hintSuccess': 'operation successful'},
|
||||
{'hintLineTooLong': 'line too long'},
|
||||
{'hintXDeclaredButNotUsed': "'$1' is declared but not used"},
|
||||
{'hintConvToBaseNotNeeded': 'conversion to base object is not needed'},
|
||||
{'hintConvFromXtoItselfNotNeeded': 'conversion from $1 to itself is pointless'},
|
||||
{'hintExprAlwaysX': "expression evaluates always to '$1'"},
|
||||
{'hintMo2FileInvalid': "mo2 file '$1' is invalid"},
|
||||
{'hintModuleHasChanged': "module '$1' has been changed"},
|
||||
{'hintCannotOpenMo2File': "mo2 file '$1' does not exist"},
|
||||
|
||||
# user hint message:
|
||||
{'hintUser': '$1'}
|
||||
]
|
||||
26
data/pas_keyw.yml
Executable file
26
data/pas_keyw.yml
Executable file
@@ -0,0 +1,26 @@
|
||||
# Object Pascal keywords for the Pascal scanner that is part of the
|
||||
# Nimrod distribution
|
||||
# (c) Andreas Rumpf 2007
|
||||
[
|
||||
"and", "array", "as", "asm",
|
||||
"begin",
|
||||
"case", "class", "const", "constructor",
|
||||
"destructor", "div", "do", "downto",
|
||||
"else", "end", "except", "exports",
|
||||
"finalization", "finally", "for", "function",
|
||||
"goto",
|
||||
"if", "implementation", "in", "inherited", "initialization", "inline",
|
||||
"interface", "is",
|
||||
"label", "library",
|
||||
"mod",
|
||||
"nil", "not",
|
||||
"object", "of", "or", "out",
|
||||
"packed", "procedure", "program", "property",
|
||||
"raise", "record", "repeat", "resourcestring",
|
||||
"set", "shl", "shr",
|
||||
"then", "threadvar", "to", "try", "type",
|
||||
"unit", "until", "uses",
|
||||
"var",
|
||||
"while", "with",
|
||||
"xor"
|
||||
]
|
||||
5
data/readme.txt
Executable file
5
data/readme.txt
Executable file
@@ -0,0 +1,5 @@
|
||||
This directory contains data files in a format called YAML_. These files
|
||||
are required for building Nimrod.
|
||||
|
||||
|
||||
.. _YAML: http://www.yaml.org/
|
||||
1
dist/empty.txt
vendored
Executable file
1
dist/empty.txt
vendored
Executable file
@@ -0,0 +1 @@
|
||||
This file keeps several tools from deleting this subdirectory.
|
||||
26
doc/docs.txt
Executable file
26
doc/docs.txt
Executable file
@@ -0,0 +1,26 @@
|
||||
"Incorrect documentation is often worse than no documentation."
|
||||
-- Bertrand Meyer
|
||||
|
||||
The documentation consists of several documents:
|
||||
|
||||
- | `Nimrod manual <manual.html>`_
|
||||
| Read this to get to know the Nimrod programming system.
|
||||
|
||||
- | `User guide for the Nimrod Compiler <nimrodc.html>`_
|
||||
| The user guide lists command line arguments, Nimrodc's special features, etc.
|
||||
|
||||
- | `User guide for the Embedded Nimrod Debugger <endb.html>`_
|
||||
| This document describes how to use the Embedded debugger. The embedded
|
||||
debugger currently has no GUI. Please help!
|
||||
|
||||
- | `Nimrod library documentation <lib.html>`_
|
||||
| This document describes Nimrod's standard library.
|
||||
|
||||
- | `Nimrod internal documentation <intern.html>`_
|
||||
| The internal documentation describes how the compiler is implemented. Read
|
||||
this if you want to hack the compiler or develop advanced macros.
|
||||
|
||||
- | `Index <theindex.html>`_
|
||||
| The generated index. Often the quickest way to find the piece of
|
||||
information you need.
|
||||
|
||||
174
doc/endb.txt
Executable file
174
doc/endb.txt
Executable file
@@ -0,0 +1,174 @@
|
||||
===========================================
|
||||
Embedded Nimrod Debugger User Guide
|
||||
===========================================
|
||||
|
||||
:Author: Andreas Rumpf
|
||||
:Version: |nimrodversion|
|
||||
|
||||
.. contents::
|
||||
|
||||
Nimrod comes with a platform independant debugger -
|
||||
the `Embedded Nimrod Debugger`:idx: (`ENDB`:idx:). The debugger is
|
||||
*embedded* into your executable if it has been
|
||||
compiled with the ``--debugger:on`` command line option.
|
||||
This also defines the conditional symbol ``ENDB`` for you.
|
||||
|
||||
Note: You must not compile your program with the ``--app:gui``
|
||||
command line option because then there is no console
|
||||
available for the debugger.
|
||||
|
||||
If you start your program the debugger will immediately show
|
||||
a prompt on the console. You can now enter a command. The next sections
|
||||
deal with the possible commands. As usual for Nimrod for all commands
|
||||
underscores and case do not matter. Optional components of a command
|
||||
are listed in brackets ``[...]`` here.
|
||||
|
||||
|
||||
General Commands
|
||||
================
|
||||
|
||||
``h``, ``help``
|
||||
Display a quick reference of the possible commands.
|
||||
|
||||
``q``, ``quit``
|
||||
Quit the debugger and the program.
|
||||
|
||||
<ENTER>
|
||||
(Without any typed command) repeat the previous debugger command.
|
||||
If there is no previous command, ``step_into`` is assumed.
|
||||
|
||||
Executing Commands
|
||||
==================
|
||||
|
||||
``s``, ``step_into``
|
||||
Single step, stepping into routine calls.
|
||||
|
||||
``n``, ``step_over``
|
||||
Single step, without stepping into routine calls.
|
||||
|
||||
``f``, ``skip_current``
|
||||
Continue execution until the current routine finishes.
|
||||
|
||||
``c``, ``continue``
|
||||
Continue execution until the next breakpoint.
|
||||
|
||||
``i``, ``ignore``
|
||||
Continue execution, ignore all breakpoints. This is effectively quitting
|
||||
the debugger and runs the program until it finishes.
|
||||
|
||||
|
||||
Breakpoint Commands
|
||||
===================
|
||||
|
||||
``b``, ``setbreak`` <identifier> [fromline [toline]] [file]
|
||||
Set a new breakpoint named 'identifier' for the given file
|
||||
and line numbers. If no file is given, the current execution point's
|
||||
filename is used. If the filename has no extension, ``.nim`` is
|
||||
appended for your convenience.
|
||||
If no line numbers are given, the current execution point's
|
||||
line is used. If both ``fromline`` and ``toline`` are given the
|
||||
breakpoint contains a line number range. Some examples if it is still
|
||||
unclear:
|
||||
|
||||
* ``b br1 12 15 thallo`` creates a breakpoint named ``br1`` that
|
||||
will be triggered if the instruction pointer reaches one of the
|
||||
lines 12-15 in the file ``thallo.nim``.
|
||||
* ``b br1 12 thallo`` creates a breakpoint named ``br1`` that
|
||||
will be triggered if the instruction pointer reaches the
|
||||
line 12 in the file ``thallo.nim``.
|
||||
* ``b br1 12`` creates a breakpoint named ``br1`` that
|
||||
will be triggered if the instruction pointer reaches the
|
||||
line 12 in the current file.
|
||||
* ``b br1`` creates a breakpoint named ``br1`` that
|
||||
will be triggered if the instruction pointer reaches the
|
||||
current line in the current file again.
|
||||
|
||||
``breakpoints``
|
||||
Display the entire breakpoint list.
|
||||
|
||||
``disable`` <identifier>
|
||||
Disable a breakpoint. It remains disabled until you turn it on again
|
||||
with the ``enable`` command.
|
||||
|
||||
``enable`` <identifier>
|
||||
Enable a breakpoint.
|
||||
|
||||
Often it happens when debugging that you keep retyping the breakpoints again
|
||||
and again because they are lost when you restart your program. This is not
|
||||
necessary: A special pragma has been defined for this:
|
||||
|
||||
|
||||
The ``{.breakpoint.}`` pragma
|
||||
-----------------------------
|
||||
|
||||
The `breakpoint`:idx: pragma is syntactically a statement. It can be used
|
||||
to mark the *following line* as a breakpoint:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
write("1")
|
||||
{.breakpoint: "before_write_2".}
|
||||
write("2")
|
||||
|
||||
The name of the breakpoint here is ``before_write_2``. Of course the
|
||||
breakpoint's name is optional - the compiler will generate one for you
|
||||
if you leave it out.
|
||||
|
||||
Code for the ``breakpoint`` pragma is only generated if the debugger
|
||||
is turned on, so you don't need to remove it from your source code after
|
||||
debugging.
|
||||
|
||||
|
||||
Data Display Commands
|
||||
=====================
|
||||
|
||||
``e``, ``eval`` <exp>
|
||||
Evaluate the expression <exp>. Note that ENDB has no full-blown expression
|
||||
evaluator built-in. So expressions are limited:
|
||||
|
||||
* To display global variables prefix their names with their
|
||||
owning module: ``nim1.globalVar``
|
||||
* To display local variables or parameters just type in
|
||||
their name: ``localVar``. If you want to inspect variables that are not
|
||||
in the current stack frame, use the ``up`` or ``down`` command.
|
||||
|
||||
Unfortunately, only inspecting variables is possible at the moment. Maybe
|
||||
a future version will implement a full-blown Nimrod expression evaluator,
|
||||
but this is not easy to do and would bloat the debugger's code.
|
||||
|
||||
Since displaying the whole data structures is often not needed and
|
||||
painfully slow, the debugger uses a *maximal display depth* concept for
|
||||
displaying.
|
||||
|
||||
You can alter the *maximal display depth* with the ``maxdisplay``
|
||||
command.
|
||||
|
||||
``maxdisplay`` <natural>
|
||||
Sets the maximal display depth to the given integer value. A value of 0
|
||||
means there is no maximal display depth. Default is 3.
|
||||
|
||||
``o``, ``out`` <filename> <exp>
|
||||
Evaluate the expression <exp> and store its string representation into a
|
||||
file named <filename>. If the file does not exist, it will be created,
|
||||
otherwise it will be opened for appending.
|
||||
|
||||
``w``, ``where``
|
||||
Display the current execution point.
|
||||
|
||||
``u``, ``up``
|
||||
Go up in the call stack.
|
||||
|
||||
``d``, ``down``
|
||||
Go down in the call stack.
|
||||
|
||||
``stackframe`` [file]
|
||||
Displays the content of the current stack frame in ``stdout`` or
|
||||
appends it to the file, depending on whether a file is given.
|
||||
|
||||
``callstack``
|
||||
Display the entire call stack (but not its content).
|
||||
|
||||
``l``, ``locals``
|
||||
Display the available local variables in the current stack frame.
|
||||
|
||||
``g``, ``globals``
|
||||
Display all the global variables that are available for inspection.
|
||||
44
doc/filelist.txt
Executable file
44
doc/filelist.txt
Executable file
@@ -0,0 +1,44 @@
|
||||
Short description of Nimrod's modules
|
||||
-------------------------------------
|
||||
|
||||
============== ==========================================================
|
||||
Module Description
|
||||
============== ==========================================================
|
||||
lexbase buffer handling of the lexical analyser
|
||||
scanner lexical analyser
|
||||
|
||||
ast type definitions of the abstract syntax tree (AST) and
|
||||
node constructors
|
||||
astalgo algorithms for containers of AST nodes; converting the
|
||||
AST to YAML; the symbol table
|
||||
trees few algorithms for nodes; this module is less important
|
||||
types module for traversing type graphs; also contain several
|
||||
helpers for dealing with types
|
||||
|
||||
sigmatch contains the matching algorithm that is used for proc
|
||||
calls
|
||||
semexprs contains the semantic checking phase for expressions
|
||||
semstmts contains the semantic checking phase for statements
|
||||
semtypes contains the semantic checking phase for types
|
||||
|
||||
idents implements a general mapping from identifiers to an internal
|
||||
representation (``PIdent``) that is used, so that a simple
|
||||
pointer comparison suffices to say whether two Nimrod
|
||||
identifiers are equivalent
|
||||
|
||||
ropes implements long strings using represented as trees for
|
||||
lazy evaluation; used mainly by the code generators
|
||||
|
||||
ccgobj contains type definitions neeeded for C code generation
|
||||
and some helpers
|
||||
ccgmangl contains the name mangler for converting Nimrod
|
||||
identifiers to their C counterparts
|
||||
ccgutils contains helpers for the C code generator
|
||||
ccgtemps contains the handling of temporary variables for the
|
||||
C code generator
|
||||
ccgtypes the generator for C types
|
||||
ccgstmts the generator for statements
|
||||
ccgexprs the generator for expressions
|
||||
extccomp this module calls the C compiler and linker; interesting
|
||||
if you want to add support for a new C compiler
|
||||
============== ==========================================================
|
||||
186
doc/grammar.txt
Executable file
186
doc/grammar.txt
Executable file
@@ -0,0 +1,186 @@
|
||||
module ::= ([COMMENT] [SAD] stmt)*
|
||||
|
||||
optComma ::= [ ',' ] [COMMENT] [IND]
|
||||
operator ::= OP0 | OR | XOR | AND | OP3 | OP4 | OP5 | IS | ISNOT | IN | NOTIN
|
||||
| OP6 | DIV | MOD | SHL | SHR | OP7 | NOT
|
||||
|
||||
prefixOperator ::= OP0 | OP3 | OP4 | OP5 | OP6 | OP7 | NOT
|
||||
|
||||
optInd ::= [COMMENT] [IND]
|
||||
|
||||
|
||||
lowestExpr ::= orExpr ( OP0 optInd orExpr )*
|
||||
orExpr ::= andExpr ( OR | XOR optInd andExpr )*
|
||||
andExpr ::= cmpExpr ( AND optInd cmpExpr )*
|
||||
cmpExpr ::= ampExpr ( OP3 | IS | ISNOT | IN | NOTIN optInd ampExpr )*
|
||||
ampExpr ::= plusExpr ( OP4 optInd plusExpr )*
|
||||
plusExpr ::= mulExpr ( OP5 optInd mulExpr )*
|
||||
mulExpr ::= dollarExpr ( OP6 | DIV | MOD | SHL | SHR optInd dollarExpr )*
|
||||
dollarExpr ::= primary ( OP7 optInd primary )*
|
||||
|
||||
namedTypeOrExpr ::=
|
||||
DOTDOT [expr]
|
||||
| expr [EQUALS (expr [DOTDOT expr] | typeDescK | DOTDOT [expr] )
|
||||
| DOTDOT [expr]]
|
||||
| typeDescK
|
||||
|
||||
castExpr ::= CAST BRACKET_LE optInd typeDesc BRACKERT_RI
|
||||
PAR_LE optInd expr PAR_RI
|
||||
addrExpr ::= ADDR PAR_LE optInd expr PAR_RI
|
||||
symbol ::= ACC (KEYWORD | IDENT | operator | PAR_LE PAR_RI
|
||||
| BRACKET_LE BRACKET_RI) ACC | IDENT
|
||||
accExpr ::= KEYWORD | IDENT | operator [DOT KEYWORD | IDENT | operator]
|
||||
paramList
|
||||
primary ::= ( prefixOperator optInd )* ( IDENT | literal | ACC accExpr ACC
|
||||
| castExpr | addrExpr ) (
|
||||
DOT optInd symbol
|
||||
#| CURLY_LE namedTypeDescList CURLY_RI
|
||||
| PAR_LE optInd
|
||||
namedExprList
|
||||
PAR_RI
|
||||
| BRACKET_LE optInd
|
||||
(namedTypeOrExpr optComma)*
|
||||
BRACKET_RI
|
||||
| CIRCUM
|
||||
| pragma )*
|
||||
|
||||
literal ::= INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
|
||||
| FLOAT_LIT | FLOAT32_LIT | FLOAT64_LIT
|
||||
| STR_LIT | RSTR_LIT | TRIPLESTR_LIT
|
||||
| CHAR_LIT | RCHAR_LIT
|
||||
| NIL
|
||||
| BRACKET_LE optInd (expr [COLON expr] optComma )* BRACKET_RI # []-Constructor
|
||||
| CURLY_LE optInd (expr [DOTDOT expr] optComma )* CURLY_RI # {}-Constructor
|
||||
| PAR_LE optInd (expr [COLON expr] optComma )* PAR_RI # ()-Constructor
|
||||
|
||||
|
||||
exprList ::= ( expr optComma )*
|
||||
|
||||
namedExpr ::= expr [EQUALS expr] # actually this is symbol EQUALS expr|expr
|
||||
namedExprList ::= ( namedExpr optComma )*
|
||||
|
||||
exprOrSlice ::= expr [ DOTDOT expr ]
|
||||
sliceList ::= ( exprOrSlice optComma )+
|
||||
|
||||
anonymousProc ::= LAMBDA paramList [pragma] EQUALS stmt
|
||||
expr ::= lowestExpr
|
||||
| anonymousProc
|
||||
| IF expr COLON expr
|
||||
(ELIF expr COLON expr)*
|
||||
ELSE COLON expr
|
||||
|
||||
namedTypeDesc ::= typeDescK | expr [EQUALS (typeDescK | expr)]
|
||||
namedTypeDescList ::= ( namedTypeDesc optComma )*
|
||||
|
||||
qualifiedIdent ::= symbol [ DOT symbol ]
|
||||
|
||||
typeDescK ::= VAR typeDesc
|
||||
| REF typeDesc
|
||||
| PTR typeDesc
|
||||
| TYPE expr
|
||||
| PROC paramList [pragma]
|
||||
|
||||
typeDesc ::= typeDescK | primary
|
||||
|
||||
optSemicolon ::= [SEMICOLON]
|
||||
|
||||
macroStmt ::= COLON [stmt] (OF [sliceList] COLON stmt
|
||||
| ELIF expr COLON stmt
|
||||
| EXCEPT exceptList COLON stmt )*
|
||||
[ELSE COLON stmt]
|
||||
|
||||
simpleStmt ::= returnStmt
|
||||
| yieldStmt
|
||||
| discardStmt
|
||||
| raiseStmt
|
||||
| breakStmt
|
||||
| continueStmt
|
||||
| pragma
|
||||
| importStmt
|
||||
| fromStmt
|
||||
| includeStmt
|
||||
| exprStmt
|
||||
complexStmt ::= ifStmt | whileStmt | caseStmt | tryStmt | forStmt
|
||||
| blockStmt | asmStmt
|
||||
| procDecl | iteratorDecl | macroDecl | templateDecl
|
||||
| constSection | typeSection | whenStmt | varSection
|
||||
|
||||
indPush ::= IND # push
|
||||
stmt ::= simpleStmt [SAD]
|
||||
| indPush (complexStmt | simpleStmt)
|
||||
([SAD] (complexStmt | simpleStmt) )*
|
||||
DED
|
||||
|
||||
exprStmt ::= lowestExpr [EQUALS expr | (expr optComma)* [macroStmt]]
|
||||
returnStmt ::= RETURN [expr]
|
||||
yieldStmt ::= YIELD expr
|
||||
discardStmt ::= DISCARD expr
|
||||
raiseStmt ::= RAISE [expr]
|
||||
breakStmt ::= BREAK [symbol]
|
||||
continueStmt ::= CONTINUE
|
||||
ifStmt ::= IF expr COLON stmt (ELIF expr COLON stmt)* [ELSE COLON stmt]
|
||||
whenStmt ::= WHEN expr COLON stmt (ELIF expr COLON stmt)* [ELSE COLON stmt]
|
||||
caseStmt ::= CASE expr (OF sliceList COLON stmt)*
|
||||
(ELIF expr COLON stmt)*
|
||||
[ELSE COLON stmt]
|
||||
whileStmt ::= WHILE expr COLON stmt
|
||||
forStmt ::= FOR (symbol optComma)+ IN expr [DOTDOT expr] COLON stmt
|
||||
exceptList ::= (qualifiedIdent optComma)*
|
||||
|
||||
tryStmt ::= TRY COLON stmt
|
||||
(EXCEPT exceptList COLON stmt)*
|
||||
[FINALLY COLON stmt]
|
||||
asmStmt ::= ASM [pragma] (STR_LIT | RSTR_LIT | TRIPLESTR_LIT)
|
||||
blockStmt ::= BLOCK [symbol] COLON stmt
|
||||
importStmt ::= IMPORT ((symbol | STR_LIT | RSTR_LIT | TRIPLESTR_LIT) [AS symbol] optComma)+
|
||||
includeStmt ::= INCLUDE ((symbol | STR_LIT | RSTR_LIT | TRIPLESTR_LIT) optComma)+
|
||||
fromStmt ::= FROM (symbol | STR_LIT | RSTR_LIT | TRIPLESTR_LIT) IMPORT (symbol optComma)+
|
||||
|
||||
pragma ::= CURLYDOT_LE (expr [COLON expr] optComma)+ (CURLYDOT_RI | CURLY_RI)
|
||||
|
||||
paramList ::= [PAR_LE ((symbol optComma)+ COLON typeDesc optComma)* PAR_RI] [COLON typeDesc]
|
||||
|
||||
genericParams ::= BRACKET_LE (symbol [EQUALS typeDesc] )* BRACKET_RI
|
||||
|
||||
procDecl ::= PROC symbol ["*"] [genericParams]
|
||||
paramList [pragma]
|
||||
[EQUALS stmt]
|
||||
macroDecl ::= MACRO symbol ["*"] [genericParams] paramList [pragma]
|
||||
[EQUALS stmt]
|
||||
iteratorDecl ::= ITERATOR symbol ["*"] [genericParams] paramList [pragma]
|
||||
[EQUALS stmt]
|
||||
templateDecl ::= TEMPLATE symbol ["*"] [genericParams] paramList [pragma]
|
||||
[EQUALS stmt]
|
||||
|
||||
colonAndEquals ::= [COLON typeDesc] EQUALS expr
|
||||
|
||||
constDecl ::= symbol ["*"] [pragma] colonAndEquals [COMMENT | IND COMMENT]
|
||||
| COMMENT
|
||||
constSection ::= CONST indPush constDecl (SAD constDecl)* DED
|
||||
typeDef ::= typeDesc | recordDef | objectDef | enumDef
|
||||
|
||||
recordIdentPart ::=
|
||||
(symbol ["*" | "-"] [pragma] optComma)+ COLON typeDesc [COMMENT | IND COMMENT]
|
||||
|
||||
recordWhen ::= WHEN expr COLON [COMMENT] recordPart
|
||||
(ELIF expr COLON [COMMENT] recordPart)*
|
||||
[ELSE COLON [COMMENT] recordPart]
|
||||
recordCase ::= CASE expr COLON typeDesc [COMMENT]
|
||||
(OF sliceList COLON [COMMENT] recordPart)*
|
||||
[ELSE COLON [COMMENT] recordPart]
|
||||
|
||||
recordPart ::= recordWhen | recordCase | recordIdentPart
|
||||
| indPush recordPart (SAD recordPart)* DED
|
||||
recordDef ::= RECORD [pragma] recordPart
|
||||
|
||||
objectDef ::= OBJECT [pragma] [OF typeDesc] recordPart
|
||||
enumDef ::= ENUM [OF typeDesc] (symbol [EQUALS expr] optComma [COMMENT | IND COMMENT])+
|
||||
|
||||
typeDecl ::= COMMENT
|
||||
| symbol ["*"] [genericParams] [EQUALS typeDef] [COMMENT | IND COMMENT]
|
||||
|
||||
typeSection ::= TYPE indPush typeDecl (SAD typeDecl)* DED
|
||||
|
||||
colonOrEquals ::= COLON typeDesc [EQUALS expr] | EQUALS expr
|
||||
varPart ::= (symbol ["*" | "-"] [pragma] optComma)+ colonOrEquals [COMMENT | IND COMMENT]
|
||||
varSection ::= VAR (varPart | indPush (COMMENT|varPart) (SAD (COMMENT|varPart))* DED)
|
||||
1
doc/html/empty.txt
Executable file
1
doc/html/empty.txt
Executable file
@@ -0,0 +1 @@
|
||||
This file keeps several tools from deleting this subdirectory.
|
||||
575
doc/intern.txt
Executable file
575
doc/intern.txt
Executable file
@@ -0,0 +1,575 @@
|
||||
=========================================
|
||||
Internals of the Nimrod Compiler
|
||||
=========================================
|
||||
|
||||
|
||||
:Author: Andreas Rumpf
|
||||
:Version: |nimrodversion|
|
||||
|
||||
.. contents::
|
||||
|
||||
|
||||
Directory structure
|
||||
===================
|
||||
|
||||
The Nimrod project's directory structure is:
|
||||
|
||||
============ ==============================================
|
||||
Path Purpose
|
||||
============ ==============================================
|
||||
``bin`` binary files go into here
|
||||
``nim`` Pascal sources of the Nimrod compiler; this
|
||||
should be modified, not the Nimrod version in
|
||||
``rod``!
|
||||
``rod`` Nimrod sources of the Nimrod compiler;
|
||||
automatically generated from the Pascal
|
||||
version
|
||||
``data`` data files that are used for generating source
|
||||
code go into here
|
||||
``doc`` the documentation lives here; it is a bunch of
|
||||
reStructuredText files
|
||||
``dist`` download packages as zip archives go into here
|
||||
``config`` configuration files for Nimrod go into here
|
||||
``lib`` the Nimrod library lives here; ``rod`` depends
|
||||
on it!
|
||||
``web`` website of Nimrod; generated by ``genweb.py``
|
||||
from the ``*.txt`` and ``*.tmpl`` files
|
||||
``koch`` the Koch Build System (written for Nimrod)
|
||||
``obj`` generated ``*.obj`` files go into here
|
||||
============ ==============================================
|
||||
|
||||
|
||||
Bootstrapping the compiler
|
||||
==========================
|
||||
|
||||
The compiler is written in a subset of Pascal with special annotations so
|
||||
that it can be translated to Nimrod code automatically. This conversion is
|
||||
done by Nimrod itself via the undocumented ``boot`` command. Thus both Nimrod
|
||||
and Free Pascal can compile the Nimrod compiler.
|
||||
|
||||
Requirements for bootstrapping:
|
||||
|
||||
- Free Pascal (I used version 2.2); it may not be needed
|
||||
- Python (should work with 2.4 or higher) and the code generator *cog*
|
||||
(included in this distribution!)
|
||||
|
||||
- C compiler -- one of:
|
||||
|
||||
* win32-lcc
|
||||
* Borland C++ (tested with 5.5)
|
||||
* Microsoft C++
|
||||
* Digital Mars C++
|
||||
* Watcom C++ (currently broken; a fix is welcome!)
|
||||
* GCC
|
||||
* Intel C++
|
||||
* Pelles C
|
||||
* llvm-gcc
|
||||
|
||||
| Compiling the compiler is a simple matter of running:
|
||||
| ``koch.py boot``
|
||||
| Or you can compile by hand, this is not difficult.
|
||||
|
||||
If you want to debug the compiler, use the command::
|
||||
|
||||
koch.py boot --debugger:on
|
||||
|
||||
The ``koch.py`` script is Nimrod's maintainance script: Everything that has
|
||||
been automated is accessible with it. It is a replacement for make and shell
|
||||
scripting with the advantage that it is more portable and is easier to read.
|
||||
|
||||
|
||||
Coding standards
|
||||
================
|
||||
|
||||
The compiler is written in a subset of Pascal with special annotations so
|
||||
that it can be translated to Nimrod code automatically. As a generell rule,
|
||||
Pascal code that does not translate to Nimrod automatically is forbidden.
|
||||
|
||||
|
||||
Porting to new platforms
|
||||
========================
|
||||
|
||||
Porting Nimrod to a new architecture is pretty easy, since C is the most
|
||||
portable programming language (within certain limits) and Nimrod generates
|
||||
C code, porting the code generator is not necessary.
|
||||
|
||||
POSIX-compliant systems on conventional hardware are usually pretty easy to
|
||||
port: Add the platform to ``platform`` (if it is not already listed there),
|
||||
check that the OS, System modules work and recompile Nimrod.
|
||||
|
||||
The only case where things aren't as easy is when the garbage
|
||||
collector needs some assembler tweaking to work. The standard
|
||||
version of the GC uses C's ``setjmp`` function to store all registers
|
||||
on the hardware stack. It may be that the new platform needs to
|
||||
replace this generic code by some assembler code.
|
||||
|
||||
|
||||
Runtime type information
|
||||
========================
|
||||
|
||||
*Runtime type information* (RTTI) is needed for several aspects of the Nimrod
|
||||
programming language:
|
||||
|
||||
Garbage collection
|
||||
The most important reason for RTTI. Generating
|
||||
traversal procedures produces bigger code and is likely to be slower on
|
||||
modern hardware as dynamic procedure binding is hard to predict.
|
||||
|
||||
Complex assignments
|
||||
Sequences and strings are implemented as
|
||||
pointers to resizeable buffers, but Nimrod requires copying for
|
||||
assignments. Apart from RTTI the compiler could generate copy procedures
|
||||
for any type that needs one. However, this would make the code bigger and
|
||||
the RTTI is likely already there for the GC.
|
||||
|
||||
We already knew the type information as a graph in the compiler.
|
||||
Thus we need to serialize this graph as RTTI for C code generation.
|
||||
Look at the files ``lib/typeinfo.nim``, ``lib/hti.nim`` for more information.
|
||||
|
||||
However, generating type information proved to be difficult and the format
|
||||
wastes memory. Variant records make problems too. We use a mix of iterator
|
||||
procedures and constant data structures:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
type
|
||||
TNimTypeSlot {.export.} = record
|
||||
offset: int
|
||||
typ: int
|
||||
name: CString
|
||||
TSlotIterator = proc (obj: pointer, field: int): ptr TNimTypeSlot
|
||||
TNimType {.export.} = record
|
||||
Kind: TNimTypeKind
|
||||
baseType, indexType: int
|
||||
size, len: int
|
||||
slots: TSlotIterator # instead of: ptr array [0..10_000, TNimTypeSlot]
|
||||
|
||||
This is not easy to understand either. Best is to use just the ``rodgen``
|
||||
module and store type information as string constants.
|
||||
|
||||
After thinking I came to the conclusion that this is again premature
|
||||
optimization. We should just construct the type graph at runtime. In the init
|
||||
section new types should be constructed and registered:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
type
|
||||
TSlotTriple = record
|
||||
offset: int
|
||||
typ: PRTL_Type
|
||||
name: Cstring
|
||||
PSlots = ptr TSlots
|
||||
TSlots = record
|
||||
case kind
|
||||
of linear:
|
||||
fields: array [TSlotTriple]
|
||||
of nested:
|
||||
discriminant: TSlotTriple
|
||||
otherSlots: array [discriminant, PSlots]
|
||||
|
||||
TTypeKind = enum ...
|
||||
RTL_Type = record
|
||||
size: int
|
||||
base: PRTL_Type
|
||||
case kind
|
||||
of tyArray, tySequence:
|
||||
elemSize: int
|
||||
of tyRecord, tyObject, tyEnum:
|
||||
slots: PSlots
|
||||
|
||||
|
||||
The Garbage Collector
|
||||
=====================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
We use the term *cell* here to refer to everything that is traced
|
||||
(sequences, refs, strings).
|
||||
This section describes how the new GC works. The old algorithms
|
||||
all had the same problem: Too complex to get them right. This one
|
||||
tries to find the right compromise.
|
||||
|
||||
The basic algorithm is *Deferrent reference counting* with cycle detection.
|
||||
References in the stack are not counted for better performance and easier C
|
||||
code generation. The GC starts by traversing the hardware stack and increments
|
||||
the reference count (RC) of every cell that it encounters. After the GC has
|
||||
done its work the stack is traversed again and the RC of every cell
|
||||
that it encounters are decremented again. Thus no marking bits in the RC are
|
||||
needed. Between these stack traversals the GC has a complete accurate view over
|
||||
the RCs.
|
||||
|
||||
Each cell has a header consisting of a RC and a pointer to its type
|
||||
descriptor. However the program does not know about these, so they are placed at
|
||||
negative offsets. In the GC code the type ``PCell`` denotes a pointer
|
||||
decremented by the right offset, so that the header can be accessed easily. It
|
||||
is extremely important that ``pointer`` is not confused with a ``PCell``
|
||||
as this would lead to a memory corruption.
|
||||
|
||||
|
||||
When to trigger a collection
|
||||
----------------------------
|
||||
|
||||
Since there are really two different garbage collectors (reference counting
|
||||
and mark and sweep) we use two different heuristics when to run the passes.
|
||||
The RC-GC pass is fairly cheap: Thus we use an additive increase (7 pages)
|
||||
for the RC_Threshold and a multiple increase for the CycleThreshold.
|
||||
|
||||
|
||||
The AT and ZCT sets
|
||||
-------------------
|
||||
|
||||
The GC maintains two sets throughout the lifetime of
|
||||
the program (plus two temporary ones). The AT (*any table*) simply contains
|
||||
every cell. The ZCT (*zero count table*) contains every cell whose RC is
|
||||
zero. This is used to reclaim most cells fast.
|
||||
|
||||
The ZCT contains redundant information -- the AT alone would suffice.
|
||||
However, traversing the AT and look if the RC is zero would touch every living
|
||||
cell in the heap! That's why the ZCT is updated whenever a RC drops to zero.
|
||||
The ZCT is not updated when a RC is incremented from zero to one, as
|
||||
this would be too costly.
|
||||
|
||||
|
||||
The CellSet data structure
|
||||
--------------------------
|
||||
|
||||
The AT and ZCT depend on an extremely efficient datastructure for storing a
|
||||
set of pointers - this is called a ``PCellSet`` in the source code.
|
||||
Inserting, deleting and searching are done in constant time. However,
|
||||
modifying a ``PCellSet`` during traversation leads to undefined behaviour.
|
||||
|
||||
.. code-block:: Nimrod
|
||||
type
|
||||
PCellSet # hidden
|
||||
|
||||
proc allocCellSet: PCellSet # make a new set
|
||||
proc deallocCellSet(s: PCellSet) # empty the set and free its memory
|
||||
proc incl(s: PCellSet, elem: PCell) # include an element
|
||||
proc excl(s: PCellSet, elem: PCell) # exclude an element
|
||||
|
||||
proc `in`(elem: PCell, s: PCellSet): bool
|
||||
|
||||
iterator elements(s: PCellSet): (elem: PCell)
|
||||
|
||||
|
||||
All the operations have to be performed efficiently. Because a Cellset can
|
||||
become huge (the AT contains every allocated cell!) a hash table is not
|
||||
suitable for this.
|
||||
|
||||
We use a mixture of bitset and patricia tree for this. One node in the
|
||||
patricia tree contains a bitset that decribes a page of the operating system
|
||||
(not always, but that doesn't matter).
|
||||
So including a cell is done as follows:
|
||||
|
||||
- Find the page descriptor for the page the cell belongs to.
|
||||
- Set the appropriate bit in the page descriptor indicating that the
|
||||
cell points to the start of a memory block.
|
||||
|
||||
Removing a cell is analogous - the bit has to be set to zero.
|
||||
Single page descriptors are never deleted from the tree. Typically a page
|
||||
descriptor is only 19 words big, so it does not waste much by not deleting
|
||||
it. Apart from that the AT and ZCT are rebuilt frequently, so removing a
|
||||
single page descriptor from the tree is never necessary.
|
||||
|
||||
Complete traversal is done like so::
|
||||
|
||||
for each page decriptor d:
|
||||
for each bit in d:
|
||||
if bit == 1:
|
||||
traverse the pointer belonging to this bit
|
||||
|
||||
|
||||
Further complications
|
||||
---------------------
|
||||
|
||||
In Nimrod the compiler cannot always know if a reference
|
||||
is stored on the stack or not. This is caused by var parameters.
|
||||
Consider this example:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
proc setRef(r: var ref TNode) =
|
||||
new(r)
|
||||
|
||||
proc usage =
|
||||
var
|
||||
r: ref TNode
|
||||
setRef(r) # here we should not update the reference counts, because
|
||||
# r is on the stack
|
||||
setRef(r.left) # here we should update the refcounts!
|
||||
|
||||
Though it would be possible to produce code updating the refcounts (if
|
||||
necessary) before and after the call to ``setRef``, it is a complex task to
|
||||
do so in the code generator. So we don't and instead decide at runtime
|
||||
whether the reference is on the stack or not. The generated code looks
|
||||
roughly like this:
|
||||
|
||||
.. code-block:: C
|
||||
void setref(TNode** ref) {
|
||||
unsureAsgnRef(ref, newObj(TNode_TI, sizeof(TNode)))
|
||||
}
|
||||
void usage(void) {
|
||||
setRef(&r)
|
||||
setRef(&r->left)
|
||||
}
|
||||
|
||||
Note that for systems with a continous stack (which most systems have)
|
||||
the check whether the ref is on the stack is very cheap (only two
|
||||
comparisons). Another advantage of this scheme is that the code produced is
|
||||
a tiny bit smaller.
|
||||
|
||||
|
||||
The algorithm in pseudo-code
|
||||
----------------------------
|
||||
Now we come to the nitty-gritty. The algorithm works in several phases.
|
||||
|
||||
Phase 1 - Consider references from stack
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
::
|
||||
|
||||
for each pointer p in the stack: incRef(p)
|
||||
|
||||
This is necessary because references in the hardware stack are not traced for
|
||||
better performance. After Phase 1 the RCs are accurate.
|
||||
|
||||
|
||||
Phase 2 - Free the ZCT
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
This is how things used to (not) work::
|
||||
|
||||
for p in elements(ZCT):
|
||||
if RC(p) == 0:
|
||||
call finalizer of p
|
||||
for c in children(p): decRef(c) # free its children recursively
|
||||
# if necessary; the childrens RC >= 1, BUT they may still be in the ZCT!
|
||||
free(p)
|
||||
else:
|
||||
remove p from the ZCT
|
||||
|
||||
Instead we do it this way. Note that the recursion is gone too!
|
||||
::
|
||||
|
||||
newZCT = nil
|
||||
for p in elements(ZCT):
|
||||
if RC(p) == 0:
|
||||
call finalizer of p
|
||||
for c in children(p):
|
||||
assert(RC(c) > 0)
|
||||
dec(RC(c))
|
||||
if RC(c) == 0:
|
||||
if newZCT == nil: newZCT = allocCellSet()
|
||||
incl(newZCT, c)
|
||||
free(p)
|
||||
else:
|
||||
# nothing to do! We will use the newZCS
|
||||
|
||||
deallocCellSet(ZCT)
|
||||
ZCT = newZCT
|
||||
|
||||
This phase is repeated until enough memory is available or the ZCT is nil.
|
||||
If still not enough memory is available the cyclic detector gets its chance
|
||||
to do something.
|
||||
|
||||
|
||||
Phase 3 - Cycle detection
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Cycle detection works by subtracting internal reference counts::
|
||||
|
||||
newAT = allocCellSet()
|
||||
|
||||
for y in elements(AT):
|
||||
# pretend that y is dead:
|
||||
for c in children(y):
|
||||
dec(RC(c))
|
||||
# note that this should not be done recursively as we have all needed
|
||||
# pointers in the AT! This makes it more efficient too!
|
||||
|
||||
proc restore(y: PCell) =
|
||||
# unfortunately, the recursion here cannot be eliminated easily
|
||||
if y not_in newAT:
|
||||
incl(newAT, y)
|
||||
for c in children(y):
|
||||
inc(RC(c)) # restore proper reference counts!
|
||||
restore(c)
|
||||
|
||||
for y in elements(AT) with rc > 0:
|
||||
restore(y)
|
||||
|
||||
for y in elements(AT) with rc == 0:
|
||||
free(y) # if pretending worked, it was part of a cycle
|
||||
|
||||
AT = newAT
|
||||
|
||||
|
||||
Phase 4 - Ignore references from stack again
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
::
|
||||
|
||||
for each pointer p in the stack:
|
||||
dec(RC(p))
|
||||
if RC(p) == 0: incl(ZCT, p)
|
||||
|
||||
Now the RCs correctly discard any references from the stack. One can also see
|
||||
this as a temporary marking operation. Things that are referenced from stack
|
||||
are marked during the GC's operarion and now have to be unmarked.
|
||||
|
||||
|
||||
|
||||
The compiler's architecture
|
||||
===========================
|
||||
|
||||
Nimrod uses the classic compiler architecture: A scanner feds tokens to a
|
||||
parser. The parser builds a syntax tree that is used by the code generator.
|
||||
This syntax tree is the interface between the parser and the code generator.
|
||||
It is essential to understand most of the compiler's code.
|
||||
|
||||
In order to compile Nimrod correctly, type-checking has to be seperated from
|
||||
parsing. Otherwise generics would not work. Code generation is done for a
|
||||
whole module only after it has been checked for semantics.
|
||||
|
||||
.. include:: filelist.txt
|
||||
|
||||
The first command line argument selects the backend. Thus the backend is
|
||||
responsible for calling the parser and semantic checker. However, when
|
||||
compiling ``import`` or ``include`` statements, the semantic checker needs to
|
||||
call the backend, this is done by embedding a PBackend into a TContext.
|
||||
|
||||
|
||||
The syntax tree
|
||||
---------------
|
||||
The synax tree consists of nodes which may have an arbitrary number of
|
||||
children. Types and symbols are represented by other nodes, because they
|
||||
may contain cycles. The AST changes its shape after semantic checking. This
|
||||
is needed to make life easier for the code generators. See the "ast" module
|
||||
for the type definitions.
|
||||
|
||||
We use the notation ``nodeKind(fields, [sons])`` for describing
|
||||
nodes. ``nodeKind[sons]`` is a short-cut for ``nodeKind([sons])``.
|
||||
XXX: Description of the language's syntax and the corresponding trees.
|
||||
|
||||
|
||||
How the RTL is compiled
|
||||
=======================
|
||||
|
||||
The system module contains the part of the RTL which needs support by
|
||||
compiler magic (and the stuff that needs to be in it because the spec
|
||||
says so). The C code generator generates the C code for it just like any other
|
||||
module. However, calls to some procedures like ``addInt`` are inserted by
|
||||
the CCG. Therefore the module ``magicsys`` contains a table
|
||||
(``compilerprocs``) with all symbols that are marked as ``compilerproc``.
|
||||
|
||||
|
||||
How separate compilation will work
|
||||
==================================
|
||||
|
||||
Soon compiling from scratch every module that's needed will become too slow as
|
||||
programs grow. For easier cleaning all generated files are generated in the
|
||||
directory: ``$base/rod_gen``. This cannot be changed. The generated C files
|
||||
get the names of the modules they result from. A compiled Nimrod module has the
|
||||
extension ``.rod`` and is a binary file. The format may change from release
|
||||
to release. The rod-file is mostly a binary representation of the parse trees.
|
||||
|
||||
Nimrod currently compiles any module into its own C file. Some things like
|
||||
type-information, common string literals, common constant sets need to be
|
||||
shared though. We deal with this problem by writing the shared data
|
||||
in the main C file. Only "headers" are generated in the other modules. However,
|
||||
each precompiled Nimrod module lists the shared data it depends on. The same
|
||||
holds for procedures that have to generated from generics.
|
||||
|
||||
A big problem is that the data must get the same name each time it is compiled.
|
||||
|
||||
The C compiler is only called for the C files, that changed after the last
|
||||
compilation (or if their object file does not exist anymore). To work
|
||||
reliably, in the header comment of the C file these things are listed, so
|
||||
that the C compiler is called again should they change:
|
||||
|
||||
* Nimrod's Version
|
||||
* the target CC
|
||||
* the target OS
|
||||
* the target CPU
|
||||
|
||||
The version is questionable: If the resulting C file is the same, it does not
|
||||
matter that Nimrods's version has increased. We do it anyway to be on the safe
|
||||
side.
|
||||
|
||||
|
||||
Generation of dynamic link libraries
|
||||
====================================
|
||||
|
||||
Generation of dynamic link libraries or shared libraries is not difficult; the
|
||||
underlying C compiler already does all the hard work for us. The problem is the
|
||||
common runtime library, especially the memory manager. Note that Borland's
|
||||
Delphi had exactly the same problem. The workaround is to not link the GC with
|
||||
the Dll and provide an extra runtime dll that needs to be initialized.
|
||||
|
||||
|
||||
|
||||
How to implement closures
|
||||
=========================
|
||||
|
||||
A closure is a record of a proc pointer and a context ref. The context ref
|
||||
points to a garbage collected record that contains the needed variables.
|
||||
An example:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
|
||||
type
|
||||
TListRec = record
|
||||
data: string
|
||||
next: ref TListRec
|
||||
|
||||
proc forEach(head: ref TListRec, visitor: proc (s: string) {.closure.}) =
|
||||
var it = head
|
||||
while it != nil:
|
||||
visit(it.data)
|
||||
it = it.next
|
||||
|
||||
proc sayHello() =
|
||||
var L = new List(["hallo", "Andreas"])
|
||||
var temp = "jup\xff"
|
||||
forEach(L, lambda(s: string) =
|
||||
io.write(temp)
|
||||
io.write(s)
|
||||
)
|
||||
|
||||
|
||||
This should become the following in C:
|
||||
|
||||
.. code-block:: C
|
||||
typedef struct ... /* List type */
|
||||
|
||||
typedef struct closure {
|
||||
void (*PrcPart)(string, void*);
|
||||
void* ClPart;
|
||||
}
|
||||
|
||||
typedef struct Tcl_data {
|
||||
string temp; // all accessed variables are put in here!
|
||||
}
|
||||
|
||||
void forEach(TListRec* head, const closure visitor) {
|
||||
TListRec* it = head;
|
||||
while (it != NIM_NULL) {
|
||||
visitor.prc(it->data, visitor->cl_data);
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
|
||||
void printStr(string s, void* cl_data) {
|
||||
Tcl_data* x = (Tcl_data*) cl_data;
|
||||
io_write(x->temp);
|
||||
io_write(s);
|
||||
}
|
||||
|
||||
void sayhello() {
|
||||
Tcl_data* data = new(...);
|
||||
asgnRef(&data->temp, "jup\xff");
|
||||
...
|
||||
|
||||
closure cl;
|
||||
cl.prc = printStr;
|
||||
cl.cl_data = data;
|
||||
foreach(L, cl);
|
||||
}
|
||||
|
||||
|
||||
What about nested closure? - There's not much difference: Just put all used
|
||||
variables in the data record.
|
||||
48
doc/lib.txt
Executable file
48
doc/lib.txt
Executable file
@@ -0,0 +1,48 @@
|
||||
=======================
|
||||
Nimrod Standard Library
|
||||
=======================
|
||||
|
||||
:Author: Andreas Rumpf
|
||||
:Version: |nimrodversion|
|
||||
|
||||
Though the Nimrod Standard Library is still evolving, it is already quite
|
||||
usable. It is divided into basic libraries that contains modules that virtually
|
||||
every program will need and advanced libraries which are more heavy weight.
|
||||
Advanced libraries are in the ``lib/base`` directory.
|
||||
|
||||
Basic libraries
|
||||
===============
|
||||
|
||||
* `System <system.html>`_
|
||||
Basic procs and operators that every program needs. It also provides IO
|
||||
facilities for reading and writing text and binary files. It is imported
|
||||
implicitly by the compiler. Do not import it directly. It relies on compiler
|
||||
magic to work.
|
||||
|
||||
* `Strutils <strutils.html>`_
|
||||
This module contains common string handling operations like converting a
|
||||
string into uppercase, splitting a string into substrings, searching for
|
||||
substrings, replacing substrings.
|
||||
|
||||
* `OS <os.html>`_
|
||||
Basic operating system facilities like retrieving environment variables,
|
||||
reading command line arguments, working with directories, running shell
|
||||
commands, etc. This module is -- like any other basic library --
|
||||
platform independant.
|
||||
|
||||
* `Math <math.html>`_
|
||||
Mathematical operations like cosine, square root.
|
||||
|
||||
* `Complex <complex.html>`_
|
||||
This module implements complex numbers and their mathematical operations.
|
||||
|
||||
* `Times <times.html>`_
|
||||
The ``times`` module contains basic support for working with time.
|
||||
|
||||
|
||||
Advanced libaries
|
||||
=================
|
||||
|
||||
* `Regexprs <regexprs.html>`_
|
||||
This module contains procedures and operators for handling regular
|
||||
expressions.
|
||||
1742
doc/manual.txt
Executable file
1742
doc/manual.txt
Executable file
File diff suppressed because it is too large
Load Diff
295
doc/nimdoc.css
Executable file
295
doc/nimdoc.css
Executable file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
:Author: David Goodger
|
||||
:Contact: goodger@python.org
|
||||
:Date: $Date: 2006-05-21 22:44:42 +0200 (Sun, 21 May 2006) $
|
||||
:Revision: $Revision: 4564 $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
|
||||
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
|
||||
/*
|
||||
Modified for the Nimrod Documenation by
|
||||
Andreas Rumpf
|
||||
*/
|
||||
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th {
|
||||
border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first {
|
||||
/* Override more specific margin styles with "! important". */
|
||||
margin-top: 0 ! important }
|
||||
|
||||
.last, .with-subtitle {
|
||||
margin-bottom: 0 ! important }
|
||||
|
||||
.hidden {
|
||||
display: none }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
||||
blockquote.epigraph {
|
||||
margin: 2em 5em ; }
|
||||
|
||||
dl.docutils dd {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
/* Uncomment (and remove this text!) to get bold-faced definition list terms
|
||||
dl.docutils dt {
|
||||
font-weight: bold }
|
||||
*/
|
||||
|
||||
div.abstract {
|
||||
margin: 2em 5em }
|
||||
|
||||
div.abstract p.topic-title {
|
||||
font-weight: bold ;
|
||||
text-align: center }
|
||||
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ;
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title {
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title {
|
||||
color: red ;
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication {
|
||||
margin: 2em 5em ;
|
||||
text-align: center ;
|
||||
font-style: italic }
|
||||
|
||||
div.dedication p.topic-title {
|
||||
font-weight: bold ;
|
||||
font-style: normal }
|
||||
|
||||
div.figure {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
div.footer, div.header {
|
||||
clear: both;
|
||||
font-size: smaller }
|
||||
|
||||
div.line-block {
|
||||
display: block ;
|
||||
margin-top: 1em ;
|
||||
margin-bottom: 1em }
|
||||
|
||||
div.line-block div.line-block {
|
||||
margin-top: 0 ;
|
||||
margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
|
||||
div.sidebar {
|
||||
margin-left: 1em ;
|
||||
border: medium outset ;
|
||||
padding: 1em ;
|
||||
background-color: #ffffee ;
|
||||
width: 40% ;
|
||||
float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric {
|
||||
font-family: sans-serif ;
|
||||
font-size: medium }
|
||||
|
||||
div.system-messages {
|
||||
margin: 5em }
|
||||
|
||||
div.system-messages h1 {
|
||||
color: red }
|
||||
|
||||
div.system-message {
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.system-message p.system-message-title {
|
||||
color: red ;
|
||||
font-weight: bold }
|
||||
|
||||
div.topic {
|
||||
margin: 2em;
|
||||
}
|
||||
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
|
||||
h1.title { text-align: center }
|
||||
h2.subtitle { text-align: center }
|
||||
hr.docutils { width: 75% }
|
||||
img.align-left { clear: left }
|
||||
img.align-right { clear: right }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal }
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha }
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha }
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman }
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman }
|
||||
|
||||
p.attribution {
|
||||
text-align: right ;
|
||||
margin-left: 50% }
|
||||
|
||||
p.caption {
|
||||
font-style: italic }
|
||||
|
||||
p.credits {
|
||||
font-style: italic ;
|
||||
font-size: smaller }
|
||||
|
||||
p.label {
|
||||
white-space: nowrap }
|
||||
|
||||
p.rubric {
|
||||
font-weight: bold ;
|
||||
font-size: larger ;
|
||||
color: maroon ;
|
||||
text-align: center }
|
||||
|
||||
p.sidebar-title {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold ;
|
||||
font-size: larger }
|
||||
|
||||
p.sidebar-subtitle {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold }
|
||||
|
||||
pre.address {
|
||||
margin-bottom: 0 ;
|
||||
margin-top: 0 ;
|
||||
font-family: serif ;
|
||||
font-size: 100% }
|
||||
|
||||
pre, span.pre {
|
||||
background-color:#F9F9F9;
|
||||
border:1px dotted #2F6FAB;
|
||||
color:black;
|
||||
}
|
||||
|
||||
pre {padding:1em;}
|
||||
|
||||
pre.literal-block, pre.doctest-block {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
span.classifier {
|
||||
font-family: sans-serif ;
|
||||
font-style: oblique }
|
||||
|
||||
span.classifier-delimiter {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
span.interpreted {
|
||||
font-family: sans-serif }
|
||||
|
||||
span.option {
|
||||
white-space: nowrap }
|
||||
|
||||
span.pre { white-space: pre }
|
||||
|
||||
span.problematic {
|
||||
color: red }
|
||||
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docinfo {
|
||||
margin: 2em 4em }
|
||||
|
||||
table.docutils {
|
||||
margin-top: 0.5em ;
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
table.footnote {
|
||||
border-left: solid 1px black;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {
|
||||
padding-left: 0.5em ;
|
||||
padding-right: 0.5em ;
|
||||
vertical-align: top }
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold ;
|
||||
text-align: left ;
|
||||
white-space: nowrap ;
|
||||
padding-left: 0 }
|
||||
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
|
||||
font-size: 100% }
|
||||
|
||||
ul.auto-toc {
|
||||
list-style-type: none }
|
||||
|
||||
a.reference {
|
||||
color: #E00000;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
a.reference:hover {
|
||||
color: #E00000;
|
||||
background-color: #ffff00;
|
||||
display: margin;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
div.topic ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
241
doc/nimrodc.txt
Executable file
241
doc/nimrodc.txt
Executable file
@@ -0,0 +1,241 @@
|
||||
===================================
|
||||
Nimrod Compiler User Guide
|
||||
===================================
|
||||
|
||||
:Author: Andreas Rumpf
|
||||
:Version: |nimrodversion|
|
||||
|
||||
.. contents::
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document describes the usage of the *Nimrod compiler*
|
||||
on the different supported platforms. It is not a definition of the Nimrod
|
||||
programming system (therefore is the Nimrod manual).
|
||||
|
||||
Nimrod is free software; it is licensed under the
|
||||
`GNU General Public License <gpl.html>`_.
|
||||
|
||||
|
||||
Compiler Usage
|
||||
==============
|
||||
|
||||
Command line switches
|
||||
---------------------
|
||||
Basis command line switches are:
|
||||
|
||||
.. include:: ../data/basicopt.txt
|
||||
|
||||
Advanced command line switches are:
|
||||
|
||||
.. include:: ../data/advopt.txt
|
||||
|
||||
|
||||
Configuration file
|
||||
------------------
|
||||
The ``nimrod`` executable loads the configuration file ``config/nimrod.cfg``
|
||||
unless this is suppressed by the ``--skip_cfg`` command line option.
|
||||
Configuration settings can be overwritten in a project specific
|
||||
configuration file that is read automatically. This specific file has to
|
||||
be in the same directory as the project and be of the same name, except
|
||||
that its extension should be ``.cfg``.
|
||||
|
||||
Command line settings have priority over configuration file settings.
|
||||
|
||||
|
||||
Nimrod's directory structure
|
||||
----------------------------
|
||||
The generated files that Nimrod produces all go into a subdirectory called
|
||||
``rod_gen``. This makes it easy to write a script that deletes all generated
|
||||
files. For example the generated C code for the module ``path/modA.nim``
|
||||
will become ``path/rod_gen/modA.c``.
|
||||
|
||||
However, the generated C code is not platform independant! C code generated for
|
||||
Linux does not compile on Windows, for instance. The comment on top of the
|
||||
C file lists the OS, CPU and CC the file has been compiled for.
|
||||
|
||||
The library lies in ``lib``. Directly in the library directory are essential
|
||||
Nimrod modules like the ``system`` and ``os`` modules. Under ``lib/base``
|
||||
are additional specialized libraries or interfaces to foreign libraries which
|
||||
are included in the standard distribution. The ``lib/extra`` directory is
|
||||
initially empty. Third party libraries should go there. In the default
|
||||
configuration the compiler always searches for libraries in ``lib``,
|
||||
``lib/base`` and ``lib/extra``.
|
||||
|
||||
|
||||
Additional Features
|
||||
===================
|
||||
|
||||
This section describes Nimrod's additional features that are not listed in the
|
||||
Nimrod manual.
|
||||
|
||||
New Pragmas and Options
|
||||
-----------------------
|
||||
|
||||
Because Nimrod generates C code it needs some "red tape" to work properly.
|
||||
Thus lots of options and pragmas for tweaking the generated C code are
|
||||
available.
|
||||
|
||||
No_decl Pragma
|
||||
~~~~~~~~~~~~~~
|
||||
The `no_decl`:idx: pragma can be applied to almost any symbol (variable, proc,
|
||||
type, etc.) and is one of the most important for interoperability with C:
|
||||
It tells Nimrod that it should not generate a declaration for the symbol in
|
||||
the C code. Thus it makes the following possible, for example:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
var
|
||||
EOF {.import: "EOF", no_decl.}: cint # pretend EOF was a variable, as
|
||||
# Nimrod does not know its value
|
||||
|
||||
Varargs Pragma
|
||||
~~~~~~~~~~~~~~
|
||||
The `varargs`:idx: pragma can be applied to procedures only. It tells Nimrod
|
||||
that the proc can take a variable number of parameters after the last
|
||||
specified parameter. Nimrod string values will be converted to C
|
||||
strings automatically:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
proc printf(formatstr: cstring) {.nodecl, varargs.}
|
||||
|
||||
printf("hallo %s", "world") # "world" will be passed as C string
|
||||
|
||||
|
||||
Header Pragma
|
||||
~~~~~~~~~~~~~
|
||||
The `header`:idx: pragma is very similar to the ``no_decl`` pragma: It can be
|
||||
applied to almost any symbol and specifies that not only it should not be
|
||||
declared but also that it leads to the inclusion of a given header file:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
type
|
||||
PFile {.import: "FILE*", header: "<stdio.h>".} = pointer
|
||||
# import C's FILE* type; Nimrod will treat it as a new pointer type
|
||||
|
||||
The ``header`` pragma expects always a string constant. The string contant
|
||||
contains the header file: As usual for C, a system header file is enclosed
|
||||
in angle brackets: ``<>``. If no angle brackets are given, Nimrod
|
||||
encloses the header file in ``""`` in the generated C code.
|
||||
|
||||
|
||||
No_static Pragma
|
||||
~~~~~~~~~~~~~~~~
|
||||
The `no_static`:idx: pragma can be applied to almost any symbol and specifies
|
||||
that it shall not be declared ``static`` in the generated C code. Note that
|
||||
symbols in the interface part of a module never get declared ``static``, so
|
||||
only in special cases is this pragma necessary.
|
||||
|
||||
|
||||
Line_dir Option
|
||||
~~~~~~~~~~~~~~~
|
||||
The `line_dir`:idx: option can be turned on or off. If on the generated C code
|
||||
contains ``#line`` directives.
|
||||
|
||||
|
||||
Stack_trace Option
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
If the `stack_trace`:idx: option is turned on, the generated C contains code to
|
||||
ensure that proper stack traces are given if the program crashes or an
|
||||
uncaught exception is raised.
|
||||
|
||||
|
||||
Line_trace Option
|
||||
~~~~~~~~~~~~~~~~~
|
||||
The `line_trace`:idx: option implies the ``stack_trace`` option. If turned on,
|
||||
the generated C contains code to ensure that proper stack traces with line
|
||||
number information are given if the program crashes or an uncaught exception
|
||||
is raised.
|
||||
|
||||
Debugger Option
|
||||
~~~~~~~~~~~~~~~
|
||||
The `debugger`:idx: option enables or disables the *Embedded Nimrod Debugger*.
|
||||
See the documentation of endb_ for further information.
|
||||
|
||||
|
||||
Breakpoint Pragma
|
||||
~~~~~~~~~~~~~~~~~
|
||||
The *breakpoint* pragma was specially added for the sake of debugging with
|
||||
ENDB. See the documentation of `endb <endb.html>`_ for further information.
|
||||
|
||||
|
||||
Volatile Pragma
|
||||
~~~~~~~~~~~~~~~
|
||||
The `volatile`:idx: pragma is for variables only. It declares the variable as
|
||||
``volatile``, whatever that means in C/C++.
|
||||
|
||||
Register Pragma
|
||||
~~~~~~~~~~~~~~~
|
||||
The `register`:idx: pragma is for variables only. It declares the variable as
|
||||
``register``, giving the compiler a hint that the variable should be placed
|
||||
in a hardware register for faster access. C compilers usually ignore this
|
||||
though and for good reason: Often they do a better job without it anyway.
|
||||
|
||||
In highly specific cases (a dispatch loop of interpreters for example) it
|
||||
may provide benefits, though.
|
||||
|
||||
|
||||
Disabling certain messages
|
||||
--------------------------
|
||||
Nimrod generates some warnings and hints ("line too long") that may annoy the
|
||||
user. Thus a mechanism for disabling certain messages is provided: Each hint
|
||||
and warning message contains a symbol in brackets. This is the message's
|
||||
identifier that can be used to enable or disable it:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
{.warning[LineTooLong]: off.} # turn off warning about too long lines
|
||||
|
||||
This is often better than disabling all warnings at once.
|
||||
|
||||
|
||||
Debugging with Nimrod
|
||||
=====================
|
||||
|
||||
Nimrod comes with its own *Embedded Nimrod Debugger*. See
|
||||
the documentation of endb_ for further information.
|
||||
|
||||
|
||||
Optimizing for Nimrod
|
||||
=====================
|
||||
|
||||
Nimrod has no separate optimizer, but the C code that is produced is very
|
||||
efficient. Most C compilers have excellent optimizers, so usually it is
|
||||
not needed to optimize one's code. Nimrod has been designed to encourage
|
||||
efficient code: The most readable code in Nimrod is often the most efficient
|
||||
too.
|
||||
|
||||
However, sometimes one has to optimize. Do it in the following order:
|
||||
|
||||
1. switch off the embedded debugger (it is **slow**!)
|
||||
2. turn on the optimizer and turn off runtime checks
|
||||
3. profile your code to find where the bottlenecks are
|
||||
4. try to find a better algorithm
|
||||
5. do low-level optimizations
|
||||
|
||||
This section can only help you with the last item. Note that rewriting parts
|
||||
of your program in C is *never* necessary to speed up your program, because
|
||||
everything that can be done in C can be done in Nimrod. Rewriting parts in
|
||||
assembler *might*.
|
||||
|
||||
Optimizing string handling
|
||||
--------------------------
|
||||
|
||||
String assignments are sometimes expensive in Nimrod: They are required to
|
||||
copy the whole string. However, the compiler is often smart enough to not copy
|
||||
strings. Due to the argument passing semantics, strings are never copied when
|
||||
passed to subroutines. The compiler does not copy strings that are returned by
|
||||
a routine, because a routine returns a new string anyway. Thus it is efficient
|
||||
to do:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
var s = procA() # assignment will not copy the string; procA allocates a new
|
||||
# string anyway
|
||||
|
||||
However it is not efficient to do:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
var s = varA # assignment has to copy the whole string into a new buffer!
|
||||
|
||||
String case statements are optimized too. A hashing scheme is used for them
|
||||
if several different string constants are used. This is likely to be more
|
||||
efficient than any hand-coded scheme.
|
||||
9
doc/overview.txt
Executable file
9
doc/overview.txt
Executable file
@@ -0,0 +1,9 @@
|
||||
=============================
|
||||
Nimrod Documentation Overview
|
||||
=============================
|
||||
|
||||
:Author: Andreas Rumpf
|
||||
:Version: |nimrodversion|
|
||||
|
||||
.. include:: ../doc/docs.txt
|
||||
|
||||
220
doc/posix.txt
Executable file
220
doc/posix.txt
Executable file
@@ -0,0 +1,220 @@
|
||||
Function POSIX Description
|
||||
access Tests for file accessibility
|
||||
alarm Schedules an alarm
|
||||
asctime Converts a time structure to a string
|
||||
cfgetispeed Reads terminal input baud rate
|
||||
cfgetospeed Reads terminal output baud rate
|
||||
cfsetispeed Sets terminal input baud rate
|
||||
cfsetospeed Sets terminal output baud rate
|
||||
chdir Changes current working directory
|
||||
chmod Changes file mode
|
||||
chown Changes owner and/or group of a file
|
||||
close Closes a file
|
||||
closedir Ends directory read operation
|
||||
creat Creates a new file or rewrites an existing one
|
||||
ctermid Generates terminal pathname
|
||||
cuserid Gets user name
|
||||
dup Duplicates an open file descriptor
|
||||
dup2 Duplicates an open file descriptor
|
||||
execl Executes a file
|
||||
execle Executes a file
|
||||
execlp Executes a file
|
||||
execv Executes a file
|
||||
execve Executes a file
|
||||
execvp Executes a file
|
||||
_exit Terminates a process
|
||||
fcntl Manipulates an open file descriptor
|
||||
fdopen Opens a stream on a file descriptor
|
||||
fork Creates a process
|
||||
fpathconf Gets configuration variable for an open file
|
||||
fstat Gets file status
|
||||
getcwd Gets current working directory
|
||||
getegid Gets effective group ID
|
||||
getenv Gets environment variable
|
||||
geteuid Gets effective user ID
|
||||
getgid Gets real group ID
|
||||
getgrgid Reads groups database based on group ID
|
||||
getgrnam Reads groups database based on group name
|
||||
getgroups Gets supplementary group IDs
|
||||
getlogin Gets user name
|
||||
getpgrp Gets process group ID
|
||||
getpid Gets process ID
|
||||
getppid Gets parent process ID
|
||||
getpwnam Reads user database based on user name
|
||||
getpwuid Reads user database based on user ID
|
||||
getuid Gets real user ID
|
||||
isatty Determines if a file descriptor is associated with a terminal
|
||||
kill Sends a kill signal to a process
|
||||
link Creates a link to a file
|
||||
longjmp Restores the calling environment
|
||||
lseek Repositions read/write file offset
|
||||
mkdir Makes a directory
|
||||
mkfifo Makes a FIFO special file
|
||||
open Opens a file
|
||||
opendir Opens a directory
|
||||
pathconf Gets configuration variables for a path
|
||||
pause Suspends a process execution
|
||||
pipe Creates an interprocess channel
|
||||
read Reads from a file
|
||||
readdir Reads a directory
|
||||
rename Renames a file
|
||||
rewinddir Resets the readdir() pointer
|
||||
rmdir Removes a directory
|
||||
setgid Sets group ID
|
||||
setjmp Saves the calling environment for use by longjmp()
|
||||
setlocale Sets or queries a program's locale
|
||||
setpgid Sets a process group ID for job control
|
||||
setuid Sets the user ID
|
||||
sigaction Examines and changes signal action
|
||||
sigaddset Adds a signal to a signal set
|
||||
sigdelset Removes a signal to a signal set
|
||||
sigemptyset Creates an empty signal set
|
||||
sigfillset Creates a full set of signals
|
||||
sigismember Tests a signal for a selected member
|
||||
siglongjmp Goes to and restores signal mask
|
||||
sigpending Examines pending signals
|
||||
sigprocmask Examines and changes blocked signals
|
||||
sigsetjmp Saves state for siglongjmp()
|
||||
sigsuspend Waits for a signal
|
||||
sleep Delays process execution
|
||||
stat Gets information about a file
|
||||
sysconf Gets system configuration information
|
||||
tcdrain Waits for all output to be transmitted to the terminal
|
||||
tcflow Suspends/restarts terminal output
|
||||
tcflush Discards terminal data
|
||||
tcgetattr Gets terminal attributes
|
||||
tcgetpgrp Gets foreground process group ID
|
||||
tcsendbreak Sends a break to a terminal
|
||||
tcsetattr Sets terminal attributes
|
||||
tcsetpgrp Sets foreground process group ID
|
||||
time Determines the current calendar time
|
||||
times Gets process times
|
||||
ttyname Determines a terminal pathname
|
||||
tzset Sets the timezone from environment variables
|
||||
umask Sets the file creation mask
|
||||
uname Gets system name
|
||||
unlink Removes a directory entry
|
||||
utime Sets file access and modification times
|
||||
waitpid Waits for process termination
|
||||
write Writes to a file
|
||||
|
||||
|
||||
POSIX.1b function calls Function POSIX Description
|
||||
aio_cancel Tries to cancel an asynchronous operation
|
||||
aio_error Retrieves the error status for an asynchronous operation
|
||||
aio_read Asynchronously reads from a file
|
||||
aio_return Retrieves the return status for an asynchronous operation
|
||||
aio_suspend Waits for an asynchronous operation to complete
|
||||
aio_write Asynchronously writes to a file
|
||||
clock_getres Gets resolution of a POSIX.1b clock
|
||||
clock_gettime Gets the time according to a particular POSIX.1b clock
|
||||
clock_settime Sets the time according to a particular POSIX.1b clock
|
||||
fdatasync Synchronizes at least the data part of a file with the underlying media
|
||||
fsync Synchronizes a file with the underlying media
|
||||
kill, sigqueue Sends signals to a process
|
||||
lio_listio Performs a list of I/O operations, synchronously or asynchronously
|
||||
mlock Locks a range of memory
|
||||
mlockall Locks the entire memory space down
|
||||
mmap Maps a shared memory object (or possibly another file) into process's address space
|
||||
mprotect Changes memory protection on a mapped area
|
||||
mq_close Terminates access to a POSIX.1b message queue
|
||||
mq_getattr Gets POSIX.1b message queue attributes
|
||||
mq_notify Registers a request to be notified when a message arrives on an empty message queue
|
||||
mq_open Creates/accesses a POSIX.1b message queue
|
||||
mq_receive Receives a message from a POSIX.1b message queue
|
||||
mq_send Sends a message on a POSIX.1b message queue
|
||||
mq_setattr Sets a subset of POSIX.1b message queue attributes
|
||||
msync Makes a mapping consistent with the underlying object
|
||||
munlock Unlocks a range of memory
|
||||
munlockall Unlocks the entire address space
|
||||
munmap Undo mapping established by mmap
|
||||
nanosleep Pauses execution for a number of nanoseconds
|
||||
sched_get_priority_max Gets maximum priority value for a scheduler
|
||||
sched_get_priority_min Gets minimum priority value for a scheduler
|
||||
sched_getparam Retrieves scheduling parameters for a particular process
|
||||
sched_getscheduler Retrieves scheduling algorithm for a particular purpose
|
||||
sched_rr_get_interval Gets the SCHED_RR interval for the named process
|
||||
sched_setparam Sets scheduling parameters for a process
|
||||
sched_setscheduler Sets scheduling algorithm/parameters for a process
|
||||
sched_yield Yields the processor
|
||||
sem_close Terminates access to a POSIX.1b semaphore
|
||||
sem_destroy De-initializes a POSIX.1b unnamed semaphore
|
||||
sem_getvalue Gets the value of a POSIX.1b semaphore
|
||||
sem_open Creates/accesses a POSIX.1b named semaphore
|
||||
sem_post Posts (signal) a POSIX.1b named or unnamed semaphore
|
||||
sem_unlink Destroys a POSIX.1b named semaphore
|
||||
sem_wait, sem_trywait Waits on a POSIX.1b named or unnamed semaphore
|
||||
shm_open Creates/accesses a POSIX.1b shared memory object
|
||||
shm_unlink Destroys a POSIX.1b shared memory object
|
||||
sigwaitinfosigtimedwait Synchronously awaits signal arrival; avoid calling handler
|
||||
timer_create Creates a POSIX.1b timer based on a particular clock
|
||||
timer_delete Deletes a POSIX.1b timer
|
||||
timer_gettime Time remaining on a POSIX.1b timer before expiration
|
||||
timer_settime Sets expiration time/interval for a POSIX.1b timer
|
||||
wait, waitpid Retrieves status of a terminated process and clean up corpse
|
||||
|
||||
|
||||
POSIX.1c function calls Function POSIX Description
|
||||
pthread_atfork Declares procedures to be called before and after a fork
|
||||
pthread_attr_destroy Destroys a thread attribute object
|
||||
pthread_attr_getdetachstate Obtains the setting of the detached state of a thread
|
||||
pthread_attr_getinheritsched Obtains the setting of the scheduling inheritance of a thread
|
||||
pthread_attr_getschedparam Obtains the parameters associated with the scheduling policy attribute of a thread
|
||||
pthread_attr_getschedpolicy Obtains the setting of the scheduling policy of a thread
|
||||
pthread_attr_getscope Obtains the setting of the scheduling scope of a thread
|
||||
pthread_attr_getstackaddr Obtains the stack address of a thread
|
||||
pthread_attr_getstacksize Obtains the stack size of a thread
|
||||
pthread_attr_init Initializes a thread attribute object
|
||||
pthread_attr_setdetachstate Adjusts the detached state of a thread
|
||||
pthread_attr_setinheritsched Adjusts the scheduling inheritance of a thread
|
||||
pthread_attr_setschedparam Adjusts the parameters associated with the scheduling policy of a thread
|
||||
pthread_attr_setschedpolicy Adjusts the scheduling policy of a thread
|
||||
pthread_attr_setscope Adjusts the scheduling scope of a thread
|
||||
pthread_attr_setstackaddr Adjusts the stack address of a thread
|
||||
pthread_attr_setstacksize Adjusts the stack size of a thread
|
||||
pthread_cancel Cancels the specific thread
|
||||
pthread_cleanup_pop Removes the routine from the top of a thread's cleanup stack, and if execute is nonzero, runs it
|
||||
pthread_cleanup_push Places a routine on the top of a thread's cleanup stack
|
||||
pthread_condattr_destroy Destroys a condition variable attribute object
|
||||
pthread_condattr_getpshared Obtains the process-shared setting of a condition variable attribute object
|
||||
pthread_condattr_init Initializes a condition variable attribute object
|
||||
pthread_condattr_setpshared Sets the process-shared attribute in a condition variable attribute object to either PTHREAD_PROCESS_SHARED or PTHREAD_PROCESS_PRIVATE
|
||||
pthread_cond_broadcast Unblocks all threads that are waiting on a condition variable
|
||||
pthread_cond_destroy Destroys a condition variable
|
||||
pthread_cond_init Initializes a condition variable with the attributes specified in the specified condition variable attribute object
|
||||
pthread_cond_signal Unblocks at least one thread waiting on a condition variable
|
||||
pthread_cond_timedwait Automatically unlocks the specified mutex, and places the calling thread into a wait state
|
||||
pthread_cond_wait Automatically unlocks the specified mutex, and places the calling thread into a wait state
|
||||
pthread_create Creates a thread with the attributes specified in attr
|
||||
pthread_detach Marks a threads internal data structures for deletion
|
||||
pthread_equal Compares one thread handle to another thread handle
|
||||
pthread_exit Terminates the calling thread
|
||||
pthread_getschedparam Obtains both scheduling policy and scheduling parameters of an existing thread
|
||||
pthread_getspecific Obtains the thread specific data value associated with the specific key in the calling thread
|
||||
pthread_join Causes the calling thread to wait for the specific thread<61>s termination
|
||||
pthread_key_create Generates a unique thread-specific key that's visible to all threads in a process
|
||||
pthread_key_delete Deletes a thread specific key
|
||||
pthread_kill Delivers a signal to the specified thread
|
||||
pthread_mutexattr_destroy Destroys a mutex attribute object
|
||||
pthread_mutexattr_getprioceiling Obtains the priority ceiling of a mutex attribute object
|
||||
pthread_mutexattr_getprotocol Obtains protocol of a mutex attribute object
|
||||
pthread_mutexattr_getpshared Obtains a process-shared setting of a mutex attribute object
|
||||
pthread_mutexattr_init Initializes a mutex attribute object
|
||||
pthread_mutexattr_setprioceiling Sets the priority ceiling attribute of a mutex attribute object
|
||||
pthread_mutexattr_setprotocol Sets the protocol attribute of a mutex attribute object
|
||||
pthread_mutexattr_setpshared Sets the process-shared attribute of a mutex attribute object to either PTHREAD_PROCESS_SHARED or PTHREAD_PROCESS_PRIVATE
|
||||
pthread_mutex_destroy Destroys a mutex
|
||||
pthread_mutex_init Initializes a mutex with the attributes specified in the specified mutex attribute object
|
||||
pthread_mutex_lock Locks an unlocked mutex
|
||||
pthread_mutex_trylock Tries to lock a not tested
|
||||
pthread_mutex_unlock Unlocks a mutex
|
||||
pthread_once Ensures that init_routine will run just once regardless of how many threads in the process call it
|
||||
pthread_self Obtains a thread handle of a calling thread
|
||||
pthread_setcancelstate Sets a thread's cancelability state
|
||||
pthread_setcanceltype Sets a thread's cancelability type
|
||||
pthread_setschedparam Adjusts the scheduling policy and scheduling parameters of an existing thread
|
||||
pthread_setspecific Sets the thread-specific data value associated with the specific key in the calling thread
|
||||
pthread_sigmask Examines or changes the calling thread's signal mask
|
||||
pthread_testcancel Requests that any pending cancellation request be delivered to the calling thread
|
||||
|
||||
|
||||
11
doc/readme.txt
Executable file
11
doc/readme.txt
Executable file
@@ -0,0 +1,11 @@
|
||||
============================
|
||||
Nimrod's documenation system
|
||||
============================
|
||||
|
||||
This folder contains Nimrod's documentation. The documentation
|
||||
is written in a format called *reStructuredText*, a markup language that reads
|
||||
like ASCII and can be converted to HTML, Tex and other formats automatically!
|
||||
|
||||
Unfortunately reStructuredText does not allow to colorize source code in the
|
||||
HTML page. Therefore a postprocessor runs over the generated HTML code, looking
|
||||
for Nimrod code fragments and colorizing them.
|
||||
296
doc/regexprs.txt
Executable file
296
doc/regexprs.txt
Executable file
@@ -0,0 +1,296 @@
|
||||
Licence of the PCRE library
|
||||
===========================
|
||||
|
||||
PCRE is a library of functions to support regular expressions whose
|
||||
syntax and semantics are as close as possible to those of the Perl 5
|
||||
language.
|
||||
|
||||
| Written by Philip Hazel
|
||||
| Copyright (c) 1997-2005 University of Cambridge
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the University of Cambridge nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
Regular expression syntax and semantics
|
||||
=======================================
|
||||
|
||||
As the regular expressions supported by this module are enormous,
|
||||
the reader is referred to http://perldoc.perl.org/perlre.html for the
|
||||
full documentation of Perl's regular expressions.
|
||||
|
||||
Because the backslash ``\`` is a meta character both in the Nimrod
|
||||
programming language and in regular expressions, it is strongly
|
||||
recommended that one uses the *raw* strings of Nimrod, so that
|
||||
backslashes are interpreted by the regular expression engine::
|
||||
|
||||
r"\S" # matches any character that is not whitespace
|
||||
|
||||
A regular expression is a pattern that is matched against a subject string
|
||||
from left to right. Most characters stand for themselves in a pattern, and
|
||||
match the corresponding characters in the subject. As a trivial example,
|
||||
the pattern::
|
||||
|
||||
The quick brown fox
|
||||
|
||||
matches a portion of a subject string that is identical to itself.
|
||||
The power of regular expressions comes from the ability to include
|
||||
alternatives and repetitions in the pattern. These are encoded in
|
||||
the pattern by the use of metacharacters, which do not stand for
|
||||
themselves but instead are interpreted in some special way.
|
||||
|
||||
There are two different sets of metacharacters: those that are recognized
|
||||
anywhere in the pattern except within square brackets, and those that are
|
||||
recognized in square brackets. Outside square brackets, the metacharacters
|
||||
are as follows:
|
||||
|
||||
============== ============================================================
|
||||
meta character meaning
|
||||
============== ============================================================
|
||||
``\`` general escape character with several uses
|
||||
``^`` assert start of string (or line, in multiline mode)
|
||||
``$`` assert end of string (or line, in multiline mode)
|
||||
``.`` match any character except newline (by default)
|
||||
``[`` start character class definition
|
||||
``|`` start of alternative branch
|
||||
``(`` start subpattern
|
||||
``)`` end subpattern
|
||||
``?`` extends the meaning of ``(``
|
||||
also 0 or 1 quantifier
|
||||
also quantifier minimizer
|
||||
``*`` 0 or more quantifier
|
||||
``+`` 1 or more quantifier
|
||||
also "possessive quantifier"
|
||||
``{`` start min/max quantifier
|
||||
============== ============================================================
|
||||
|
||||
|
||||
Part of a pattern that is in square brackets is called a "character class".
|
||||
In a character class the only metacharacters are:
|
||||
|
||||
============== ============================================================
|
||||
meta character meaning
|
||||
============== ============================================================
|
||||
``\`` general escape character
|
||||
``^`` negate the class, but only if the first character
|
||||
``-`` indicates character range
|
||||
``[`` POSIX character class (only if followed by POSIX syntax)
|
||||
``]`` terminates the character class
|
||||
============== ============================================================
|
||||
|
||||
|
||||
The following sections describe the use of each of the metacharacters.
|
||||
|
||||
|
||||
Backslash
|
||||
---------
|
||||
The `backslash`:idx: character has several uses. Firstly, if it is followed
|
||||
by a non-alphanumeric character, it takes away any special meaning that
|
||||
character may have. This use of backslash as an escape character applies
|
||||
both inside and outside character classes.
|
||||
|
||||
For example, if you want to match a ``*`` character, you write ``\*`` in
|
||||
the pattern. This escaping action applies whether or not the following
|
||||
character would otherwise be interpreted as a metacharacter, so it is always
|
||||
safe to precede a non-alphanumeric with backslash to specify that it stands
|
||||
for itself. In particular, if you want to match a backslash, you write ``\\``.
|
||||
|
||||
|
||||
Non-printing characters
|
||||
-----------------------
|
||||
A second use of backslash provides a way of encoding non-printing characters
|
||||
in patterns in a visible manner. There is no restriction on the appearance of
|
||||
non-printing characters, apart from the binary zero that terminates a pattern,
|
||||
but when a pattern is being prepared by text editing, it is usually easier to
|
||||
use one of the following escape sequences than the binary character it
|
||||
represents::
|
||||
|
||||
============== ============================================================
|
||||
character meaning
|
||||
============== ============================================================
|
||||
``\a`` alarm, that is, the BEL character (hex 07)
|
||||
``\e`` escape (hex 1B)
|
||||
``\f`` formfeed (hex 0C)
|
||||
``\n`` newline (hex 0A)
|
||||
``\r`` carriage return (hex 0D)
|
||||
``\t`` tab (hex 09)
|
||||
``\ddd`` character with octal code ddd, or backreference
|
||||
``\xhh`` character with hex code hh
|
||||
============== ============================================================
|
||||
|
||||
After ``\x``, from zero to two hexadecimal digits are read (letters can be in
|
||||
upper or lower case). In UTF-8 mode, any number of hexadecimal digits may
|
||||
appear between ``\x{`` and ``}``, but the value of the character code must be
|
||||
less than 2**31 (that is, the maximum hexadecimal value is 7FFFFFFF). If
|
||||
characters other than hexadecimal digits appear between ``\x{`` and ``}``, or
|
||||
if there is no terminating ``}``, this form of escape is not recognized.
|
||||
Instead, the initial ``\x`` will be interpreted as a basic hexadecimal escape,
|
||||
with no following digits, giving a character whose value is zero.
|
||||
|
||||
After ``\0`` up to two further octal digits are read. In both cases, if there
|
||||
are fewer than two digits, just those that are present are used. Thus the
|
||||
sequence ``\0\x\07`` specifies two binary zeros followed by a BEL character
|
||||
(code value 7). Make sure you supply two digits after the initial zero if
|
||||
the pattern character that follows is itself an octal digit.
|
||||
|
||||
The handling of a backslash followed by a digit other than 0 is complicated.
|
||||
Outside a character class, PCRE reads it and any following digits as a
|
||||
decimal number. If the number is less than 10, or if there have been at least
|
||||
that many previous capturing left parentheses in the expression, the entire
|
||||
sequence is taken as a back reference. A description of how this works is
|
||||
given later, following the discussion of parenthesized subpatterns.
|
||||
|
||||
Inside a character class, or if the decimal number is greater than 9 and
|
||||
there have not been that many capturing subpatterns, PCRE re-reads up to
|
||||
three octal digits following the backslash, and generates a single byte
|
||||
from the least significant 8 bits of the value. Any subsequent digits stand
|
||||
for themselves. For example:
|
||||
|
||||
============== ============================================================
|
||||
example meaning
|
||||
============== ============================================================
|
||||
``\040`` is another way of writing a space
|
||||
``\40`` is the same, provided there are fewer than 40 previous
|
||||
capturing subpatterns
|
||||
``\7`` is always a back reference
|
||||
``\11`` might be a back reference, or another way of writing a tab
|
||||
``\011`` is always a tab
|
||||
``\0113`` is a tab followed by the character "3"
|
||||
``\113`` might be a back reference, otherwise the character with
|
||||
octal code 113
|
||||
``\377`` might be a back reference, otherwise the byte consisting
|
||||
entirely of 1 bits
|
||||
``\81`` is either a back reference, or a binary zero followed by
|
||||
the two characters "8" and "1"
|
||||
============== ============================================================
|
||||
|
||||
Note that octal values of 100 or greater must not be introduced by a leading
|
||||
zero, because no more than three octal digits are ever read.
|
||||
|
||||
All the sequences that define a single byte value or a single UTF-8 character
|
||||
(in UTF-8 mode) can be used both inside and outside character classes. In
|
||||
addition, inside a character class, the sequence ``\b`` is interpreted as the
|
||||
backspace character (hex 08), and the sequence ``\X`` is interpreted as the
|
||||
character "X". Outside a character class, these sequences have different
|
||||
meanings (see below).
|
||||
|
||||
Generic character types
|
||||
-----------------------
|
||||
The third use of backslash is for specifying `generic character types`:idx:.
|
||||
The following are always recognized:
|
||||
|
||||
============== ============================================================
|
||||
character type meaning
|
||||
============== ============================================================
|
||||
``\d`` any decimal digit
|
||||
``\D`` any character that is not a decimal digit
|
||||
``\s`` any whitespace character
|
||||
``\S`` any character that is not a whitespace character
|
||||
``\w`` any "word" character
|
||||
``\W`` any "non-word" character
|
||||
============== ============================================================
|
||||
|
||||
Each pair of escape sequences partitions the complete set of characters into
|
||||
two disjoint sets. Any given character matches one, and only one, of each pair.
|
||||
|
||||
These character type sequences can appear both inside and outside character
|
||||
classes. They each match one character of the appropriate type. If the
|
||||
current matching point is at the end of the subject string, all of them fail,
|
||||
since there is no character to match.
|
||||
|
||||
For compatibility with Perl, ``\s`` does not match the VT character (code 11).
|
||||
This makes it different from the the POSIX "space" class. The ``\s`` characters
|
||||
are HT (9), LF (10), FF (12), CR (13), and space (32).
|
||||
|
||||
A "word" character is an underscore or any character less than 256 that is
|
||||
a letter or digit. The definition of letters and digits is controlled by
|
||||
PCRE's low-valued character tables, and may vary if locale-specific matching
|
||||
is taking place (see "Locale support" in the pcreapi page). For example,
|
||||
in the "fr_FR" (French) locale, some character codes greater than 128 are
|
||||
used for accented letters, and these are matched by ``\w``.
|
||||
|
||||
In UTF-8 mode, characters with values greater than 128 never match ``\d``,
|
||||
``\s``, or ``\w``, and always match ``\D``, ``\S``, and ``\W``. This is true
|
||||
even when Unicode character property support is available.
|
||||
|
||||
Simple assertions
|
||||
-----------------
|
||||
The fourth use of backslash is for certain `simple assertions`:idx:. An
|
||||
assertion specifies a condition that has to be met at a particular point in
|
||||
a match, without consuming any characters from the subject string. The use of
|
||||
subpatterns for more complicated assertions is described below. The
|
||||
backslashed assertions are::
|
||||
|
||||
============== ============================================================
|
||||
assertion meaning
|
||||
============== ============================================================
|
||||
``\b`` matches at a word boundary
|
||||
``\B`` matches when not at a word boundary
|
||||
``\A`` matches at start of subject
|
||||
``\Z`` matches at end of subject or before newline at end
|
||||
``\z`` matches at end of subject
|
||||
``\G`` matches at first matching position in subject
|
||||
============== ============================================================
|
||||
|
||||
These assertions may not appear in character classes (but note that ``\b``
|
||||
has a different meaning, namely the backspace character, inside a character
|
||||
class).
|
||||
|
||||
A word boundary is a position in the subject string where the current
|
||||
character and the previous character do not both match ``\w`` or ``\W`` (i.e.
|
||||
one matches ``\w`` and the other matches ``\W``), or the start or end of the
|
||||
string if the first or last character matches ``\w``, respectively.
|
||||
|
||||
The ``\A``, ``\Z``, and ``\z`` assertions differ from the traditional
|
||||
circumflex and dollar in that they only ever match at the very start and
|
||||
end of the subject string, whatever options are set.
|
||||
The difference between ``\Z`` and ``\z`` is that ``\Z`` matches before
|
||||
a newline that is the last character of the string as well as at the end
|
||||
of the string, whereas ``\z`` matches only at the end.
|
||||
|
||||
..
|
||||
Regular expressions in Nimrod itself!
|
||||
-------------------------------------
|
||||
|
||||
'a' -- matches the character a
|
||||
'a'-'z' -- range operator '-'
|
||||
'A' | 'B' -- alternative operator |
|
||||
* 'a' -- prefix * is needed
|
||||
+ 'a' -- prefix + is needed
|
||||
? 'a' -- prefix ? is needed
|
||||
letter -- character classes with real names!
|
||||
letters
|
||||
white
|
||||
whites
|
||||
any -- any character
|
||||
() -- are Nimrod syntax
|
||||
! 'a'-'z'
|
||||
|
||||
-- concatentation via proc call:
|
||||
|
||||
re('A' 'Z' word * )
|
||||
111
doc/rst.txt
Executable file
111
doc/rst.txt
Executable file
@@ -0,0 +1,111 @@
|
||||
===========================================================================
|
||||
Nimrod's implementation of |rst|
|
||||
===========================================================================
|
||||
|
||||
:Author: Andreas Rumpf
|
||||
:Version: |nimrodversion|
|
||||
|
||||
.. contents::
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document describes the subset of `Docutils`_' `reStructuredText`_ as it
|
||||
has been implemented in the Nimrod compiler for generating documentation.
|
||||
Elements of |rst| that are not listed here have not been implemented.
|
||||
Unfortunately, the specification of |rst| is quite vague, so Nimrod is not as
|
||||
compatible to the original implementation as one would like.
|
||||
|
||||
Even though Nimrod's |rst| parser does not parse all constructs, it is pretty
|
||||
usable. The missing features can easily be circumvented. An indication of this
|
||||
fact is that Nimrod's
|
||||
*whole* documentation itself (including this document) is
|
||||
processed by Nimrod's |rst| parser. (Which is an order of magnitude faster than
|
||||
Docutils' parser.)
|
||||
|
||||
|
||||
Inline elements
|
||||
===============
|
||||
|
||||
Ordinary text may contain *inline elements*.
|
||||
|
||||
|
||||
Bullet lists
|
||||
============
|
||||
|
||||
*Bullet lists* look like this::
|
||||
|
||||
* Item 1
|
||||
* Item 2 that
|
||||
spans over multiple lines
|
||||
* Item 3
|
||||
* Item 4
|
||||
- bullet lists may nest
|
||||
- item 3b
|
||||
- valid bullet characters are ``+``, ``*`` and ``-``
|
||||
|
||||
This results in:
|
||||
* Item 1
|
||||
* Item 2 that
|
||||
spans over multiple lines
|
||||
* Item 3
|
||||
* Item 4
|
||||
- bullet lists may nest
|
||||
- item 3b
|
||||
- valid bullet characters are ``+``, ``*`` and ``-``
|
||||
|
||||
|
||||
Enumerated lists
|
||||
================
|
||||
|
||||
*Enumerated lists*
|
||||
|
||||
|
||||
Defintion lists
|
||||
===============
|
||||
|
||||
Save this code to the file "greeting.nim". Now compile and run it:
|
||||
|
||||
``nimrod run greeting.nim``
|
||||
|
||||
As you see, with the ``run`` command Nimrod executes the file automatically
|
||||
after compilation. You can even give your program command line arguments by
|
||||
appending them after the filename that is to be compiled and run:
|
||||
|
||||
``nimrod run greeting.nim arg1 arg2``
|
||||
|
||||
|
||||
Tables
|
||||
======
|
||||
|
||||
Nimrod only implements simple tables of the form::
|
||||
|
||||
================== =============== ===================
|
||||
header 1 header 2 header n
|
||||
================== =============== ===================
|
||||
Cell 1 Cell 2 Cell 3
|
||||
Cell 4 Cell 5; any Cell 6
|
||||
cell that is
|
||||
not in column 1
|
||||
may span over
|
||||
multiple lines
|
||||
Cell 7 Cell 8 Cell 9
|
||||
================== =============== ===================
|
||||
|
||||
This results in:
|
||||
================== =============== ===================
|
||||
header 1 header 2 header n
|
||||
================== =============== ===================
|
||||
Cell 1 Cell 2 Cell 3
|
||||
Cell 4 Cell 5; any Cell 6
|
||||
cell that is
|
||||
not in column 1
|
||||
may span over
|
||||
multiple lines
|
||||
Cell 7 Cell 8 Cell 9
|
||||
================== =============== ===================
|
||||
|
||||
|
||||
.. |rst| replace:: reStructuredText
|
||||
.. _reStructuredText: http://docutils.sourceforge.net/rst.html#reference-documentation
|
||||
.. _docutils: http://docutils.sourceforge.net/
|
||||
1297
doc/spec.txt
Executable file
1297
doc/spec.txt
Executable file
File diff suppressed because it is too large
Load Diff
1436
doc/theindex.txt
Executable file
1436
doc/theindex.txt
Executable file
File diff suppressed because it is too large
Load Diff
215
doc/tutorial.txt
Executable file
215
doc/tutorial.txt
Executable file
@@ -0,0 +1,215 @@
|
||||
===========================================
|
||||
Tutorial of the Nimrod Programming Language
|
||||
===========================================
|
||||
|
||||
:Author: Andreas Rumpf
|
||||
|
||||
Motivation
|
||||
==========
|
||||
|
||||
Why yet another programming language?
|
||||
|
||||
Look at the trends behind all the new programming languages:
|
||||
|
||||
* They try to be dynamic: Dynamic typing, dynamic method binding, etc.
|
||||
In my opinion the most things the dynamic features buy could be achieved
|
||||
with static means in a more efficient and *understandable* way.
|
||||
|
||||
* They depend on big runtime environments which you need to
|
||||
ship with your program as each new version of these may break compability
|
||||
in subtle ways or you use recently added features - thus forcing your
|
||||
users to update their runtime environment. Compiled programs where the
|
||||
executable contains all needed code are simply the better solution.
|
||||
|
||||
* They are unsuitable for systems programming: Do you really want to
|
||||
write an operating system, a device driver or an interpreter in a language
|
||||
that is just-in-time compiled (or interpreted)?
|
||||
|
||||
|
||||
So what lacks are *good* systems programming languages. Nimrod is such a
|
||||
language. It offers the following features:
|
||||
|
||||
* It is readable: It reads from left to right (unlike the C-syntax
|
||||
languages).
|
||||
* It is strongly and statically typed: This enables the compiler to find
|
||||
more errors. Static typing also makes programs more *readable*.
|
||||
* It is compiled. (Currently this is done via compilation to C.)
|
||||
* It is garbage collected. Big systems need garbage collection. Manuell
|
||||
memory management is also supported through *untraced pointers*.
|
||||
* It scales because high level features are also available: It has built-in
|
||||
bit sets, strings, enumerations, objects, arrays and dynamically resizeable
|
||||
arrays (called *sequences*).
|
||||
* It has high performance: The current implementation compiles to C
|
||||
and uses a Deutsch-Bobrow garbage collector together with Christoper's
|
||||
partial mark-sweep garbage collector leading to excellent execution
|
||||
speed and a small memory footprint.
|
||||
* It has real modules with proper interfaces and supports separate
|
||||
compilation.
|
||||
* It is portable: It compiles to C and platform specific features have
|
||||
been separated and documented. So even if your platform is not supported
|
||||
porting should be easy.
|
||||
* It is flexible: Although primilarily a procedural language, generic,
|
||||
functional and object-oriented programming is also supported.
|
||||
* It is easy to learn, easy to use and leads to elegant programs.
|
||||
* You can link an embedded debugger to your program (ENDB). ENDB is
|
||||
very easy to use - there is no need to clutter your code with
|
||||
``echo`` statements for proper debugging.
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document is a tutorial for the programming language *Nimrod*. It should
|
||||
be a readable quick tour through the language instead of a dry specification
|
||||
(which can be found `here <manual.html>`_). This tutorial assumes that
|
||||
the reader already knows some other programming language such as Pascal. Thus
|
||||
it is detailed in cases where Nimrod differs from other programming languages
|
||||
and kept short where Nimrod is more or less the same.
|
||||
|
||||
|
||||
A quick tour through the language
|
||||
=================================
|
||||
|
||||
The first program
|
||||
-----------------
|
||||
|
||||
We start the tour with a modified "hallo world" program:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
# This is a comment
|
||||
# Standard IO-routines are always accessible
|
||||
write(stdout, "What's your name? ")
|
||||
var name: string = readLine(stdin)
|
||||
write(stdout, "Hi, " & name & "!\n")
|
||||
|
||||
|
||||
Save this code to the file "greeting.nim". Now compile and run it::
|
||||
|
||||
nimrod run greeting.nim
|
||||
|
||||
As you see, with the ``run`` command Nimrod executes the file automatically
|
||||
after compilation. You can even give your program command line arguments by
|
||||
appending them after the filename that is to be compiled and run::
|
||||
|
||||
nimrod run greeting.nim arg1 arg2
|
||||
|
||||
Though it should be pretty obvious what the program does, I will explain the
|
||||
syntax: Statements which are not indented are executed when the program
|
||||
starts. Indentation is Nimrod's way of grouping statements. String literals
|
||||
are enclosed in double quotes. The ``var`` statement declares a new variable
|
||||
named ``name`` of type ``string`` with the value that is returned by the
|
||||
``readline`` procedure. Since the compiler knows that ``readline`` returns
|
||||
a string, you can leave out the type in the declaration. So this will work too:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
var name = readline(stdin)
|
||||
|
||||
Note that this is the only form of type inference that exists in Nimrod:
|
||||
This is because it yields a good compromise between brevity and readability.
|
||||
|
||||
The ``&`` operator concates strings together. ``\n`` stands for the
|
||||
new line character(s). On several operating systems ``\n`` is represented by
|
||||
*two* characters: Linefeed and Carriage Return. That is why
|
||||
*character literals* cannot contain ``\n``. But since Nimrod handles strings
|
||||
so well, this is a nonissue.
|
||||
|
||||
The "hallo world" program contains several identifiers that are already
|
||||
known to the compiler: ``write``, ``stdout``, ``readLine``, etc. These
|
||||
built-in items are declared in the system_ module which is implicitly
|
||||
imported by any other module.
|
||||
|
||||
|
||||
Lexical elements
|
||||
----------------
|
||||
|
||||
Let us look into Nimrod's lexical elements in more detail: Like other
|
||||
programming languages Nimrod consists of identifiers, keywords, comments,
|
||||
operators, and other punctation marks. Case is *insignificant* in Nimrod and
|
||||
even underscores are ignored: ``This_is_an_identifier`` and this is the same
|
||||
identifier ``ThisIsAnIdentifier``. This feature enables one to use other
|
||||
peoples code without bothering about a naming convention that one does not
|
||||
like.
|
||||
|
||||
String literals are enclosed in double quotes, character literals in single
|
||||
quotes. There exist also *raw* string and character literals:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
r"C:\program files\nim"
|
||||
|
||||
In raw literals the backslash is not an escape character, so they fit
|
||||
the principle *what you see is what you get*. *Long string literals*
|
||||
are also available (``""" ... """``); they can span over multiple lines
|
||||
and the ``\`` is not an escape character either. They are very useful
|
||||
for embedding SQL code templates for example.
|
||||
|
||||
Comments start with ``#`` and run till the end of the line. (Well this is not
|
||||
quite true, but you should read the manual for a proper explanation.)
|
||||
|
||||
... XXX number literals
|
||||
|
||||
|
||||
The usual statements - if, while, for, case
|
||||
-------------------------------------------
|
||||
|
||||
In Nimrod indentation is used to group statements.
|
||||
An example showing the most common statement types:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
var name = readLine(stdin)
|
||||
|
||||
if name == "Andreas":
|
||||
echo("What a nice name!")
|
||||
elif name == "":
|
||||
echo("Don't you have a name?")
|
||||
else:
|
||||
echo("Boring name...")
|
||||
|
||||
for i in 0..length(name)-1:
|
||||
if name[i] == 'm':
|
||||
echo("hey, there is an *m* in your name!")
|
||||
|
||||
echo("Please give your password: \n")
|
||||
var pw = readLine(stdin)
|
||||
|
||||
while pw != "12345":
|
||||
echo("Wrong password! Next try: \n")
|
||||
pw = readLine(stdin)
|
||||
|
||||
echo("""Login complete!
|
||||
What do you want to do?
|
||||
delete-everything
|
||||
restart-computer
|
||||
go-for-a-walk
|
||||
""")
|
||||
|
||||
case readline(stdin)
|
||||
of "delete-everything", "restart-computer":
|
||||
echo("permission denied")
|
||||
of "go-for-a-walk": echo("please yourself")
|
||||
else: echo("unknown command")
|
||||
|
||||
|
||||
..
|
||||
Types
|
||||
-----
|
||||
|
||||
Nimrod has a rich type system. This tutorial only gives a few examples. Read
|
||||
the `manual <manual.html>`_ for further information:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
type
|
||||
TMyRecord = record
|
||||
x, y: int
|
||||
|
||||
|
||||
Procedures
|
||||
----------
|
||||
|
||||
Procedures are subroutines. They are declared in this way:
|
||||
|
||||
.. code-block:: Nimrod
|
||||
proc findSubStr(sub: string,
|
||||
|
||||
|
||||
.. _strutils: strutils.html
|
||||
.. _system: system.html
|
||||
24
dos2unix.py
Executable file
24
dos2unix.py
Executable file
@@ -0,0 +1,24 @@
|
||||
#! /usr/bin/env python
|
||||
"Replace CRLF with LF in argument files. Print names of changed files."
|
||||
|
||||
import sys, os, glob
|
||||
|
||||
def main():
|
||||
for arg in sys.argv[1:]:
|
||||
for filename in glob.glob(arg):
|
||||
if os.path.isdir(filename):
|
||||
print filename, "Directory!"
|
||||
continue
|
||||
data = open(filename, "rb").read()
|
||||
if '\0' in data:
|
||||
print filename, "Binary!"
|
||||
continue
|
||||
newdata = data.replace("\r\n", "\n")
|
||||
if newdata != data:
|
||||
print filename
|
||||
f = open(filename, "wb")
|
||||
f.write(newdata)
|
||||
f.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
302
gcccpuopt.sh
Executable file
302
gcccpuopt.sh
Executable file
@@ -0,0 +1,302 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Print the gcc cpu specific options appropriate for the current CPU
|
||||
|
||||
# Author:
|
||||
# http://www.pixelbeat.org/
|
||||
# Notes:
|
||||
# This script currently supports Linux,FreeBSD,Cygwin
|
||||
# This script is x86 (32 bit) specific
|
||||
# It should work on any gcc >= 2.95 at least
|
||||
# It only returns CPU specific options. You probably also want -03 etc.
|
||||
# Changes:
|
||||
# V0.1, 12 Mar 2003, Initial release
|
||||
# V0.2, 01 Jun 2005, Added support for 3.2>=gcc<=4.0
|
||||
# V0.3, 03 Jun 2005, Added support for pentium-m
|
||||
# V0.4, 03 Jun 2005, Fix silly bugs
|
||||
# V0.5, 07 Jun 2005, Clarify/Simplify confusing floating point expr usage
|
||||
# Print warning when CPU only supported on a newer gcc
|
||||
# V0.6, 15 Dec 2006, Added support for Intel Core and Core 2 processors
|
||||
# Added support for 4.1>=gcc<=4.3
|
||||
# Added support for gcc -msse3 option
|
||||
# Added support for new gcc -march=native option
|
||||
# V0.7, 18 Dec 2006, Changes from Conor McDermottroe
|
||||
# Added support for FreeBSD
|
||||
# Remove bash specific constructs
|
||||
# Better error handling
|
||||
# V0.8, 19 Dec 2006, Give warnings and 32 bit -march on 64 bit platforms.
|
||||
# Previously it just gave an invalid blank -march.
|
||||
# Reported and tested by Ewan Oughton.
|
||||
# V0.9, 30 Apr 2007, Give error if compiler not present.
|
||||
# Warn about rather than default to -march=native option.
|
||||
# V0.92, 08 Nov 2007, Change from Krzysztof Jankowski to support Cygwin.
|
||||
# Added support for AMD family 10 processors.
|
||||
# Add support for gcc -msse4 & -msse5 options.
|
||||
# Use "prescott" rather than "pentium4" for all
|
||||
# models >= 3 in intel family 15, not just model 3.
|
||||
# V0.93, 13 Nov 2007, Oops, actually not all intel family 15, model >= 3
|
||||
# are prescotts. Use the sse3 flag to distinguish.
|
||||
# V0.94, 31 Dec 2007, Oops, actually all intel family 15, model >= 3
|
||||
# are prescotts. This was indicated by Adam Drzewiecki.
|
||||
# I was confused by a bug in older linux kernels where pni
|
||||
# was not reported for my intel "F41" processor at least.
|
||||
# V0.95, 18 Jan 2008, Changes from Conor McDermottroe
|
||||
# Support for Mac OS X
|
||||
# Support for FreeBSD base system
|
||||
|
||||
if [ "$1" = "--version" ]; then
|
||||
echo "0.95" && exit
|
||||
fi
|
||||
|
||||
# This table shows when -march options were introduced into _official_ gcc releases.
|
||||
# Note there are vendor deviations that complicate this.
|
||||
# For e.g. redhat introduced the prescott option in 3.3-13.
|
||||
# gcc-2.95 = i386, i486, i586,pentium, i686,pentiumpro, k6
|
||||
# gcc-3.0 += athlon
|
||||
# gcc-3.1 += pentium-mmx, pentium2, pentium3, pentium4, k6-2, k6-3, athlon-{tbird, 4,xp,mp}
|
||||
# gcc-3.3 += winchip-c6, winchip2, c3
|
||||
# gcc-3.4.0 += k8,opteron,athlon64,athlon-fx, c3-2
|
||||
# gcc-3.4.1 += pentium-m, pentium3m, pentium4m, prescott, nocona
|
||||
# gcc-4.3 += core2, amdfam10
|
||||
|
||||
[ -z "$CC" ] && CC=gcc
|
||||
|
||||
try_gcc_options() {
|
||||
$CC $* -S -o /dev/null -xc /dev/null >/dev/null 2>&1
|
||||
}
|
||||
|
||||
if ! try_gcc_options; then
|
||||
echo "Error: Couldn't execute your compiler ($CC)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if try_gcc_options -march=native; then
|
||||
echo "Warning: Your compiler supports the -march=native option which you may prefer" >&2
|
||||
fi
|
||||
|
||||
if ! try_gcc_options -march=i386; then
|
||||
if ! try_gcc_options -m32 -march=i386; then
|
||||
echo "Error: This script only supports 32 bit x86 architectures" >&2
|
||||
exit 1
|
||||
else
|
||||
echo "Warning: The optimum *32 bit* architecture is reported" >&2
|
||||
m32="-m32 "
|
||||
fi
|
||||
fi
|
||||
|
||||
try_line() {
|
||||
skip=0
|
||||
for arch in $1; do
|
||||
if try_gcc_options $m32 -march=$arch; then
|
||||
echo $arch
|
||||
return
|
||||
elif [ "$skip" = "0" ] && [ "$arch" != "native" ]; then
|
||||
skip=1
|
||||
echo "Warning: Newer versions of GCC better support your CPU with -march=$arch" >&2
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
read_cpu_data_linux() {
|
||||
IFS=":"
|
||||
while read name value; do
|
||||
unset IFS
|
||||
name=`echo $name`
|
||||
value=`echo $value`
|
||||
IFS=":"
|
||||
if [ "$name" = "vendor_id" ]; then
|
||||
vendor_id="$value"
|
||||
elif [ "$name" = "cpu family" ]; then
|
||||
cpu_family="$value"
|
||||
elif [ "$name" = "model" ]; then
|
||||
cpu_model="$value"
|
||||
elif [ "$name" = "flags" ]; then
|
||||
flags="$value"
|
||||
break #flags last so break early
|
||||
fi
|
||||
done < /proc/cpuinfo
|
||||
unset IFS
|
||||
}
|
||||
|
||||
read_cpu_data_freebsd() {
|
||||
local _line _cpu_id
|
||||
|
||||
if [ ! -r /var/run/dmesg.boot ]; then
|
||||
echo "/var/run/dmesg.boot does not exist!"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
IFS="
|
||||
"
|
||||
for _line in `grep -A2 '^CPU: ' /var/run/dmesg.boot`; do
|
||||
if [ -n "`echo $_line | grep '^ Origin = '`" ]; then
|
||||
vendor_id="`echo $_line | sed -e 's/^ Origin = .//' -e 's/[^A-Za-z0-9].*$//'`"
|
||||
_cpu_id="`echo $_line | sed -e 's/^.*Id = //' -e 's/ .*$//' -e 'y/abcdef/ABCDEF/'`"
|
||||
cpu_family=$((($_cpu_id & 0xF0F) >> 8))
|
||||
cpu_model=$((($_cpu_id & 0xF0) >> 4))
|
||||
fi
|
||||
if [ -n "`echo $_line | grep '^ Features='`" ]; then
|
||||
flags="`echo $_line | sed -e 's/^.*<//' -e 's/>.*//' -e 's/,/ /g' | tr 'A-Z' 'a-z'`"
|
||||
fi
|
||||
done
|
||||
unset IFS
|
||||
}
|
||||
|
||||
read_cpu_data_darwin() {
|
||||
vendor_id="`/usr/sbin/sysctl -n machdep.cpu.vendor`"
|
||||
cpu_family="`/usr/sbin/sysctl -n machdep.cpu.family`"
|
||||
cpu_model="`/usr/sbin/sysctl -n machdep.cpu.model`"
|
||||
flags="`/usr/sbin/sysctl -n machdep.cpu.features | tr 'A-Z' 'a-z'`"
|
||||
}
|
||||
|
||||
read_cpu_data() {
|
||||
# Default values
|
||||
vendor_id="Unset"
|
||||
cpu_family="-1"
|
||||
cpu_model="-1"
|
||||
flags=""
|
||||
if [ "`uname`" = "Linux" ]; then
|
||||
read_cpu_data_linux
|
||||
elif [ "`uname`" = "FreeBSD" ]; then
|
||||
read_cpu_data_freebsd
|
||||
elif [ "`uname | sed 's/\(CYGWIN\).*/\1/'`" = "CYGWIN" ]; then
|
||||
read_cpu_data_linux
|
||||
elif [ "`uname`" = "Darwin" ]; then
|
||||
read_cpu_data_darwin
|
||||
else
|
||||
echo "Error: `uname` is not a supported operating system"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
read_cpu_data
|
||||
|
||||
if [ "$vendor_id" = "AuthenticAMD" ]; then
|
||||
if [ $cpu_family -eq 4 ]; then
|
||||
_CFLAGS="-march=i486"
|
||||
elif [ $cpu_family -eq 5 ]; then
|
||||
if [ $cpu_model -lt 4 ]; then
|
||||
_CFLAGS="-march=pentium"
|
||||
elif [ \( $cpu_model -eq 6 \) -o \( $cpu_model -eq 7 \) ]; then
|
||||
_CFLAGS="-march=k6"
|
||||
elif [ \( $cpu_model -eq 8 \) -o \( $cpu_model -eq 12 \) ]; then
|
||||
line="k6-2 k6"
|
||||
elif [ \( $cpu_model -eq 9 \) -o \( $cpu_model -eq 13 \) ]; then
|
||||
line="k6-3 k6-2 k6"
|
||||
fi
|
||||
elif [ $cpu_family -eq 6 ]; then
|
||||
if [ $cpu_model -le 3 ]; then
|
||||
line="athlon k6-3 k6-2 k6"
|
||||
elif [ $cpu_model -eq 4 ]; then
|
||||
line="athlon-tbird athlon k6-3 k6-2 k6"
|
||||
elif [ $cpu_model -ge 6 ]; then #athlon-{4,xp,mp}
|
||||
line="athlon-4 athlon k6-3 k6-2 k6"
|
||||
fi
|
||||
elif [ $cpu_family -eq 15 ]; then #k8,opteron,athlon64,athlon-fx
|
||||
line="k8 athlon-4 athlon k6-3 k6-2 k6"
|
||||
elif [ $cpu_family -eq 16 ]; then #barcelona,amdfam10
|
||||
line="amdfam10 k8 athlon-4 athlon k6-3 k6-2 k6"
|
||||
fi
|
||||
elif [ "$vendor_id" = "CentaurHauls" ]; then
|
||||
if [ $cpu_family -eq 5 ]; then
|
||||
if [ $cpu_model -eq 4 ]; then
|
||||
line="winchip-c6 pentium"
|
||||
elif [ $cpu_model -eq 8 ]; then
|
||||
line="winchip2 winchip-c6 pentium"
|
||||
elif [ $cpu_model -ge 9 ]; then
|
||||
line="winchip2 winchip-c6 pentium" #actually winchip3 but gcc doesn't support this currently
|
||||
fi
|
||||
elif [ $cpu_family -eq 6 ]; then
|
||||
if echo "$flags" | grep -q cmov; then
|
||||
fallback=pentiumpro
|
||||
else
|
||||
fallback=pentium #gcc incorrectly assumes i686 always has cmov
|
||||
fi
|
||||
if [ $cpu_model -eq 6 ]; then
|
||||
_CFLAGS="-march=pentium" # ? Cyrix 3 (samuel)
|
||||
elif [ $cpu_model -eq 7 ] || [ $cpu_model -eq 8 ]; then
|
||||
line="c3 winchip2 winchip-c6 $fallback"
|
||||
elif [ $cpu_model -ge 9 ]; then
|
||||
line="c3-2 c3 winchip2 winchip-c6 $fallback"
|
||||
fi
|
||||
fi
|
||||
elif [ "$vendor_id" = "GenuineIntel" ]; then
|
||||
if [ $cpu_family -eq 3 ]; then
|
||||
_CFLAGS="-march=i386"
|
||||
elif [ $cpu_family -eq 4 ]; then
|
||||
_CFLAGS="-march=i486"
|
||||
elif [ $cpu_family -eq 5 ]; then
|
||||
if [ $cpu_model -ne 4 ]; then
|
||||
_CFLAGS="-march=pentium"
|
||||
else
|
||||
line="pentium-mmx pentium" #No overlap with other vendors
|
||||
fi
|
||||
elif [ $cpu_family -eq 6 ]; then
|
||||
if [ \( $cpu_model -eq 0 \) -o \( $cpu_model -eq 1 \) ]; then
|
||||
_CFLAGS="-march=pentiumpro"
|
||||
elif [ \( $cpu_model -ge 3 \) -a \( $cpu_model -le 6 \) ]; then #4=TM5600 at least
|
||||
line="pentium2 pentiumpro pentium-mmx pentium i486 i386"
|
||||
elif [ \( $cpu_model -eq 9 \) -o \( $cpu_model -eq 13 \) ]; then #centrino
|
||||
line="pentium-m pentium4 pentium3 pentium2 pentiumpro pentium-mmx pentium i486 i386"
|
||||
elif [ $cpu_model -eq 14 ]; then #Core
|
||||
line="prescott pentium-m pentium4 pentium3 pentium2 pentiumpro pentium-mmx pentium i486 i386"
|
||||
elif [ $cpu_model -eq 15 ]; then #Core 2
|
||||
line="core2 pentium-m pentium4 pentium3 pentium2 pentiumpro pentium-mmx pentium i486 i386"
|
||||
elif [ \( $cpu_model -ge 7 \) -a \( $cpu_model -le 11 \) ]; then
|
||||
line="pentium3 pentium2 pentiumpro pentium-mmx pentium i486 i386"
|
||||
fi
|
||||
elif [ $cpu_family -eq 15 ]; then
|
||||
line="pentium4 pentium3 pentium2 pentiumpro pentium-mmx pentium i486 i386"
|
||||
if [ $cpu_model -ge 3 ]; then
|
||||
line="prescott $line"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Unknown CPU Vendor: $vendor_id"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ -z "$_CFLAGS" ] && _CFLAGS="-march=`try_line "$line"`"
|
||||
|
||||
#SSE is not used for floating point by default in gcc 32 bit
|
||||
#so turn that on here.
|
||||
if echo "$flags" | grep -q "sse"; then
|
||||
if try_gcc_options "-mfpmath=sse"; then #gcc >= 3.1
|
||||
_CFLAGS="$_CFLAGS -mfpmath=sse"
|
||||
fi
|
||||
fi
|
||||
|
||||
#The SSE options are mostly selected automatically
|
||||
#when a particular march option is selected.
|
||||
#There are a few exceptions unfortunately, which we handle here.
|
||||
#Note the sse instruction lines are:
|
||||
# intel: [sse4.2] [sse4.1] ssse3 sse3 sse2 sse ...
|
||||
# amd: [sse5] sse4a [sse3] sse2 sse ...
|
||||
# The bracketed ones are only available on some cpus
|
||||
# in a particular family and so need to be added explicitly.
|
||||
if echo "$_CFLAGS" | grep -q "amdfam10"; then
|
||||
if echo "$flags" | grep -q "sse5"; then
|
||||
if try_gcc_options "-msse5"; then #gcc >= 4.3
|
||||
_CFLAGS="$_CFLAGS -msse5"
|
||||
fi
|
||||
fi
|
||||
elif echo "$_CFLAGS" | grep -E -q "(k8|c3-2)"; then
|
||||
if echo "$flags" | grep -E -q "(sse3|pni)"; then
|
||||
if try_gcc_options "-msse3"; then #gcc >= 3.3.3
|
||||
_CFLAGS="$_CFLAGS -msse3"
|
||||
fi
|
||||
fi
|
||||
elif echo "$_CFLAGS" | grep -q "core2"; then
|
||||
if echo "$flags" | grep -q "sse4_2"; then
|
||||
if try_gcc_options "-msse4"; then #gcc >= 4.3
|
||||
_CFLAGS="$_CFLAGS -msse4"
|
||||
fi
|
||||
elif echo "$flags" | grep -q "sse4_1"; then
|
||||
if try_gcc_options "-msse4.1"; then #gcc >= 4.3
|
||||
_CFLAGS="$_CFLAGS -msse4.1"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "$m32$_CFLAGS"
|
||||
369
ide/main.nim
Executable file
369
ide/main.nim
Executable file
@@ -0,0 +1,369 @@
|
||||
|
||||
import glib2, gtk2, libglade2
|
||||
|
||||
proc on_window_destroy(obj: PGtkObject, data: pointer) {.exportc, cdecl.} =
|
||||
gtk_main_quit()
|
||||
|
||||
const
|
||||
GuiTemplate = "/media/hda4/nimrod/ide/nimide.glade"
|
||||
|
||||
type
|
||||
TMyTextEditor = record
|
||||
window: PGtkWindow
|
||||
statusbar: PGtkStatusBar
|
||||
textview: PGtkTextview
|
||||
statusbarContextId: int
|
||||
filename: string
|
||||
|
||||
proc error_message(msg: string) =
|
||||
var
|
||||
dialog: PGtkDialog
|
||||
dialog = GTK_DIALOG(gtk_message_dialog_new(nil,
|
||||
GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, msg))
|
||||
|
||||
gtk_window_set_title(dialog, "Error!")
|
||||
gtk_dialog_run(dialog)
|
||||
gtk_widget_destroy(dialog)
|
||||
|
||||
|
||||
proc get_open_filename(e: TMyTextEditor): string =
|
||||
var
|
||||
chooser: PGtkDialog
|
||||
chooser = gtk_file_chooser_dialog_new("Open File...", e.window,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil)
|
||||
|
||||
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
|
||||
result = $gtk_file_chooser_get_filename(chooser)
|
||||
else:
|
||||
result = ""
|
||||
gtk_widget_destroy(chooser)
|
||||
|
||||
|
||||
proc get_save_filename(e: TMyTextEditor): string =
|
||||
var
|
||||
chooser: PGtkDialog
|
||||
chooser = gtk_file_chooser_dialog_new("Save File...", e.window,
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil)
|
||||
|
||||
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
|
||||
result = $gtk_file_chooser_get_filename(chooser)
|
||||
else:
|
||||
result = ""
|
||||
gtk_widget_destroy(chooser)
|
||||
|
||||
proc load_file(e: var TMyTextEditor, filename: string) =
|
||||
var
|
||||
err: ptr GError
|
||||
status: cstring
|
||||
text: cstring
|
||||
result: bool
|
||||
buffer: PGtkTextBuffer
|
||||
gtk_statusbar_push(e.statusbar, e.statusbar_context_id, "Loading...")
|
||||
while gtk_events_pending(): gtk_main_iteration()
|
||||
|
||||
# get the file contents
|
||||
result = g_file_get_contents(filename, addr(text), nil, addr(err))
|
||||
if not result:
|
||||
error_message("Cannot load file")
|
||||
g_error_free(err)
|
||||
|
||||
# disable the text view while loading the buffer with the text
|
||||
gtk_widget_set_sensitive(e.text_view, false)
|
||||
buffer = gtk_text_view_get_buffer(e.text_view)
|
||||
gtk_text_buffer_set_text(buffer, text, -1)
|
||||
gtk_text_buffer_set_modified(buffer, false)
|
||||
gtk_widget_set_sensitive(e.text_view, true)
|
||||
g_free(text)
|
||||
|
||||
e.filename = filename
|
||||
gtk_statusbar_pop(e.statusbar, e.statusbar_context_id)
|
||||
reset_default_status(e)
|
||||
|
||||
proc write_file(e: var TMyTextEditor, filename: string) =
|
||||
var
|
||||
err: ptr GError
|
||||
status: cstring
|
||||
text: cstring
|
||||
result: bool
|
||||
buffer: PGtkTextBuffer
|
||||
start, ende: TGtkTextIter
|
||||
# add Saving message to status bar and ensure GUI is current
|
||||
gtk_statusbar_push(e.statusbar, e.statusbar_context_id, "Saving....")
|
||||
while gtk_events_pending(): gtk_main_iteration()
|
||||
|
||||
# disable text view and get contents of buffer
|
||||
gtk_widget_set_sensitive(editor->text_view, FALSE)
|
||||
buffer = gtk_text_view_get_buffer(e.text_view)
|
||||
gtk_text_buffer_get_start_iter(buffer, start)
|
||||
gtk_text_buffer_get_end_iter(buffer, ende)
|
||||
text = gtk_text_buffer_get_text(buffer, start, ende, FALSE)
|
||||
gtk_text_buffer_set_modified(buffer, false)
|
||||
gtk_widget_set_sensitive(e.text_view, true)
|
||||
# set the contents of the file to the text from the buffer
|
||||
if filename != "":
|
||||
result = g_file_set_contents(filename, text, -1, addr(err))
|
||||
else:
|
||||
result = g_file_set_contents(editor->filename, text, -1, addr(err))
|
||||
if not result:
|
||||
error_message("cannot save")
|
||||
g_error_free(err)
|
||||
g_free(text)
|
||||
if filename != "":
|
||||
e.filename = filename
|
||||
gtk_statusbar_pop(e.statusbar, e.statusbar_context_id)
|
||||
reset_default_status(editor)
|
||||
|
||||
|
||||
proc initApp(e: var TMyTextEditor) =
|
||||
var
|
||||
builder: PGladeXML
|
||||
window: PGtkWidget
|
||||
fontDesc: PPangoFontDescription
|
||||
id: int
|
||||
builder = glade_xml_new(GuiTemplate, nil, nil)
|
||||
if builder == nil:
|
||||
error_message("cannot open: " & GuiTemplate)
|
||||
quit(1)
|
||||
# get the components:
|
||||
e.window = GTK_WINDOW(glade_xml_get_widget(builder, "window"))
|
||||
e.statusbar = GTK_STATUSBAR(glade_xml_get_widget(builder, "statusbar"))
|
||||
e.textview = GTK_TEXTVIEW(glade_xml_get_widget(builder, "textview"))
|
||||
|
||||
# connect the signal handlers:
|
||||
glade_xml_signal_connect(builder, "on_window_destroy",
|
||||
cast[TGCallback](on_window_destroy))
|
||||
|
||||
font_desc = pango_font_description_from_string("monospace 10")
|
||||
gtk_widget_modify_font(e.textview, font_desc)
|
||||
pango_font_description_free(font_desc)
|
||||
gtk_window_set_default_icon_name(GTK_STOCK_EDIT)
|
||||
|
||||
id = gtk_statusbar_get_context_id(e.statusbar, "Nimrod IDE")
|
||||
e.statusbarContextId = id
|
||||
reset_default_status(e)
|
||||
|
||||
e.filename = ""
|
||||
|
||||
|
||||
proc main() =
|
||||
var
|
||||
editor: TMyTextEditor
|
||||
|
||||
gtk_nimrod_init()
|
||||
initApp(editor)
|
||||
gtk_widget_show(editor.window)
|
||||
gtk_main()
|
||||
|
||||
main()
|
||||
|
||||
|
||||
proc reset_default_status(e: var TMyTextEditor)
|
||||
gchar *file;
|
||||
gchar *status;
|
||||
|
||||
if e.filename == "":
|
||||
file = g_strdup("(UNTITLED)")
|
||||
else:
|
||||
file = g_path_get_basename(editor->filename)
|
||||
|
||||
status = g_strdup_printf("File: %s", file)
|
||||
gtk_statusbar_pop(e.statusbar,
|
||||
e.statusbar_context_id)
|
||||
gtk_statusbar_push(e.statusbar,
|
||||
e.statusbar_context_id, status)
|
||||
g_free(status)
|
||||
g_free(file)
|
||||
|
||||
|
||||
gboolean
|
||||
check_for_save(e: var TMyTextEditor)
|
||||
gboolean ret = FALSE;
|
||||
GtkTextBuffer *buffer;
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
|
||||
if (gtk_text_buffer_get_modified (buffer) == TRUE)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
const gchar *msg = "Do you want to save the changes you have made?";
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_QUESTION,
|
||||
GTK_BUTTONS_YES_NO,
|
||||
msg);
|
||||
gtk_window_set_title (GTK_WINDOW (dialog), "Save?");
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_NO)
|
||||
{
|
||||
ret = FALSE;
|
||||
} else ret = TRUE;
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
return ret;
|
||||
|
||||
|
||||
/*
|
||||
When the window is requested to be closed, we need to check if they have
|
||||
unsaved work. We use this callback to prompt the user to save their work before
|
||||
they exit the application. From the "delete-event" signal, we can choose to
|
||||
effectively cancel the close based on the value we return.
|
||||
*/
|
||||
gboolean
|
||||
on_window_delete_event(GtkWidget *widget, GdkEvent *event,
|
||||
TutorialTextEditor *editor)
|
||||
{
|
||||
if (check_for_save (editor) == TRUE)
|
||||
on_save_menu_item_activate (NULL, editor);
|
||||
return FALSE; /* propogate event */
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'New' menu. We need to prompt for save if the
|
||||
file has been modified, and then delete the buffer and clear the modified flag.
|
||||
*/
|
||||
void on_new_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
|
||||
if (check_for_save (editor) == TRUE)
|
||||
{
|
||||
on_save_menu_item_activate (NULL, editor);
|
||||
}
|
||||
|
||||
/* clear editor for a new file */
|
||||
editor->filename = NULL;
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
|
||||
gtk_text_buffer_set_text (buffer, "", -1);
|
||||
gtk_text_buffer_set_modified (buffer, FALSE);
|
||||
|
||||
reset_default_status (editor);
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Open' menu. We need to prompt for save if the
|
||||
file has been modified, allow the user to choose a file to open, and then call
|
||||
load_file() on that file.
|
||||
*/
|
||||
void on_open_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
gchar *filename;
|
||||
|
||||
if (check_for_save (editor) == TRUE)
|
||||
{
|
||||
on_save_menu_item_activate (NULL, editor);
|
||||
}
|
||||
|
||||
filename = get_open_filename (editor);
|
||||
if (filename != NULL) load_file (editor, filename);
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Save' menu. We need to allow the user to choose
|
||||
a file to save if it's an untitled document, and then call write_file() on that
|
||||
file.
|
||||
*/
|
||||
void on_save_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
gchar *filename;
|
||||
|
||||
if (editor->filename == NULL)
|
||||
{
|
||||
filename = get_save_filename (editor);
|
||||
if (filename != NULL) write_file (editor, filename);
|
||||
}
|
||||
else write_file (editor, NULL);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Save As' menu. We need to allow the user to
|
||||
choose a file to save and then call write_file() on that file.
|
||||
*/
|
||||
void on_save_as_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
gchar *filename;
|
||||
|
||||
filename = get_save_filename (editor);
|
||||
if (filename != NULL) write_file (editor, filename);
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Quit' menu. We need to prompt for save if the
|
||||
file has been modified and then break out of the GTK+ main loop.
|
||||
*/
|
||||
void on_quit_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
if (check_for_save (editor) == TRUE)
|
||||
{
|
||||
on_save_menu_item_activate (NULL, editor);
|
||||
}
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Cut' menu.
|
||||
*/
|
||||
void on_cut_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
GtkClipboard *clipboard;
|
||||
|
||||
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
|
||||
gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Copy' menu.
|
||||
*/
|
||||
void on_copy_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
GtkClipboard *clipboard;
|
||||
|
||||
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
|
||||
gtk_text_buffer_copy_clipboard (buffer, clipboard);
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Paste' menu.
|
||||
*/
|
||||
void on_paste_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
GtkClipboard *clipboard;
|
||||
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
|
||||
gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
Called when the user clicks the 'Delete' menu.
|
||||
*/
|
||||
void on_delete_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->text_view));
|
||||
gtk_text_buffer_delete_selection (buffer, FALSE, TRUE);
|
||||
}
|
||||
|
||||
void on_about_menu_item_activate (GtkMenuItem *menuitem, TutorialTextEditor *editor)
|
||||
{
|
||||
static const gchar * const authors[] = {
|
||||
"Micah Carrick <email@micahcarrick.com>",
|
||||
NULL
|
||||
};
|
||||
static const gchar copyright[] = "Copyright \xc2\xa9 2008 Andreas Rumpf";
|
||||
static const gchar comments[] = "GTK+ and Glade3 GUI Programming Tutorial";
|
||||
gtk_show_about_dialog (e.window,
|
||||
"authors", authors,
|
||||
"comments", comments,
|
||||
"copyright", copyright,
|
||||
"version", "0.1",
|
||||
"website", "http://www.micahcarrick.com",
|
||||
"program-name", "GTK+ Text Editor",
|
||||
"logo-icon-name", GTK_STOCK_EDIT, nil)
|
||||
}
|
||||
175
ide/nimide.glade
Executable file
175
ide/nimide.glade
Executable file
@@ -0,0 +1,175 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<!--Generated with glade3 3.4.2 on Sat Jun 21 14:12:42 2008 -->
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="window">
|
||||
<property name="extension_events">GDK_EXTENSION_EVENTS_ALL</property>
|
||||
<signal name="destroy" handler="on_window_destroy" object="destroy"/>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="mainvbox">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenuBar" id="menubar">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Datei</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu1">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="new_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-new</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="open_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-open</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="save_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-save</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="save_as_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-save-as</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="quit_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-quit</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Bearbeiten</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="cut_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-cut</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="copy_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-copy</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="paste_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-paste</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="delete_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-delete</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkMenuItem" id="menuitem4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Hilfe</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="about_menu_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">gtk-about</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="extension_events">GDK_EXTENSION_EVENTS_ALL</property>
|
||||
<property name="border_width">1</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
|
||||
<child>
|
||||
<widget class="GtkTextView" id="textview">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="left_margin">2</property>
|
||||
<property name="right_margin">2</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkStatusbar" id="statusbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">2</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
||||
101
install.txt
Executable file
101
install.txt
Executable file
@@ -0,0 +1,101 @@
|
||||
Note: Installation does not work yet - you have to bootstrap. Play with the
|
||||
``koch.py`` script to compile the compiler.
|
||||
Compile the compiler::
|
||||
|
||||
python koch.py nim
|
||||
|
||||
To bootstrap (does not work yet)::
|
||||
|
||||
python koch.py boot
|
||||
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
Note:
|
||||
A C compiler is required - knowledge of C is not!
|
||||
|
||||
Installation on UNIX
|
||||
--------------------
|
||||
|
||||
The GNU C Compiler is fully supported, other compilers may work. The C compiler
|
||||
should be in your ``$PATH`` (most likely the case). Note that some Linux
|
||||
distributions do not ship with a C compiler preinstalled - then you have to
|
||||
install one.
|
||||
|
||||
After you have made sure that a C compiler is available, install Nimrod
|
||||
by downloading the appropriate ``.zip`` file and extracting it to a
|
||||
directory of your choice. The Nimrod Compiler will stay in this
|
||||
directory; do not use a temporary one! Good choices are ``/opt/nimrod`` or -
|
||||
if you don't have root access - ``~/programs/nimrod``.
|
||||
Then run the following command::
|
||||
|
||||
python koch.py install
|
||||
|
||||
Unlike other software, Nimrod does not distribute its files over the whole file
|
||||
hierarchy. This has the advantage that you can deinstall it by just deleting
|
||||
its folder. The disadvantage is that you have to add it to your ``PATH``
|
||||
manually. The alternative is to create a symbolic link in ``/usr/bin``::
|
||||
|
||||
[sudo] ln -s $your_install_dir/bin/nimrod /usr/bin/nimrod
|
||||
|
||||
|
||||
Installation on the Macintosh
|
||||
-----------------------------
|
||||
|
||||
Only MacOS X is supported.
|
||||
Since MacOS X is UNIX based too, it works like the installation on UNIX. You
|
||||
need to install Apple's developer's tools for the GNU Compiler Collection
|
||||
though.
|
||||
|
||||
|
||||
Installation on Windows
|
||||
-----------------------
|
||||
|
||||
Windows does not ship with a C compiler; you have to install one. The
|
||||
following C compilers are supported under Windows:
|
||||
|
||||
- | Digital Mars C++
|
||||
| http://www.digitalmars.com/download/freecompiler.html
|
||||
|
||||
- | Watcom C++
|
||||
| http://www.openwatcom.org/ftp/
|
||||
|
||||
- | Borland C++ (5.5 or above; including Borland C++Builder)
|
||||
| http://www.borland.com/downloads/download_cbuilder.html
|
||||
| (Download the package under "compiler" - this requires registration though.)
|
||||
|
||||
- | Microsoft's Visual C++
|
||||
| http://msdn.microsoft.com/visualc
|
||||
| (You may need the SDK too - but not the full one: Essential are only
|
||||
the win32api header files and import libraries.)
|
||||
|
||||
- | Gnu C Compiler (the mingw version; the cygwin version has not been tested!)
|
||||
| http://www.mingw.org/download.shtml
|
||||
|
||||
- | LLVM with GNU C/C++ frontend
|
||||
| http://llvm.org/releases/download.html#2.2
|
||||
|
||||
- | Pelles C Compiler
|
||||
| http://www.smorgasbordet.com/pellesc
|
||||
|
||||
- | Lcc-win32
|
||||
| http://www.cs.virginia.edu/~lcc-win32
|
||||
|
||||
All of the above compilers are available for free!
|
||||
(The first three are the easiest to install.) If you want a small download,
|
||||
choose Digital Mars C++ -- it is easy to install and only about 3 MB.
|
||||
If you want the highest possible performance, go for Microsoft's Visual C++ or
|
||||
LLVM.
|
||||
|
||||
After you have made sure that a C compiler is available, install
|
||||
Nimrod by downloading the appropriate .zip file and extracting it to a
|
||||
directory of your choice. The Nimrod Compiler will stay in this
|
||||
directory; do not use a temporary one! Then run ``config.exe`` in the
|
||||
``bin`` subdirectory. Choose your C compiler and press ``OK``. You should
|
||||
add Nimrod to your ``$PATH``.
|
||||
|
||||
Alternatively, you can install Nimrod with the ``koch.py`` script just like
|
||||
in the UNIX installation instructions.
|
||||
|
||||
Nimrod does not use the Registry and can be removed by just deleting its folder.
|
||||
982
koch.py
Executable file
982
koch.py
Executable file
@@ -0,0 +1,982 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
##########################################################################
|
||||
## ##
|
||||
## Build script of the Nimrod Compiler ##
|
||||
## (c) 2008 Andreas Rumpf ##
|
||||
## ##
|
||||
##########################################################################
|
||||
|
||||
import os, os.path, sys, re, zipfile, filecmp, shutil, cPickle, time
|
||||
import string, getopt, textwrap, glob, shutil, getopt, string
|
||||
|
||||
|
||||
if sys.version_info[0] >= 3: # this script does not work with Python 3.0
|
||||
sys.exit("wrong python version: use Python 2.x")
|
||||
|
||||
from kochmod import *
|
||||
|
||||
# --------------------- constants ----------------------------------------
|
||||
|
||||
CFLAGS = "" # modify to set flags to the first compilation step
|
||||
|
||||
NIMROD_VERSION = '0.2.1'
|
||||
# This string contains Nimrod's version. It is the only place
|
||||
# where the version needs to be updated. The rest is done by
|
||||
# the build process automatically. It is replaced **everywhere**
|
||||
# automatically!
|
||||
# Format is: Major.Minor.Patch
|
||||
# Major part: plan is to use number 1 for the first version that is stable;
|
||||
# higher versions may be incompatible with previous versions
|
||||
# Minor part: incremented if new features are added (but is completely
|
||||
# backwards-compatible)
|
||||
# Patch level: is increased for every patch
|
||||
|
||||
|
||||
EXPLAIN = True
|
||||
force = False
|
||||
|
||||
INNOSETUP = r"c:\programme\innosetup5\iscc.exe /Q "
|
||||
ADV_SETUP = r"C:\Programme\AdvancedInstaller6.1\AdvancedInstaller.com " \
|
||||
r"/build %s -force"
|
||||
PYINSTALLER = r"C:\Eigenes\DownLoad\Python\pyinstaller-1.3"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
def ask():
|
||||
return sys.stdin.readline().strip("\t \n\r\f").lower()
|
||||
|
||||
def CogRule(name, filename, dependson):
|
||||
def processCog():
|
||||
from cogapp import Cog
|
||||
ret = Cog().main([sys.argv[0], "-r", Path(filename)])
|
||||
return ret
|
||||
|
||||
c = Changed(name, filename + " " + dependson, EXPLAIN)
|
||||
if c or force:
|
||||
if processCog() == 0:
|
||||
c.update(filename)
|
||||
c.success()
|
||||
|
||||
_nim_exe = os.path.join(os.getcwd(), "bin", ExeExt("nim"))
|
||||
_output_obj = os.path.join(os.getcwd(), "obj")
|
||||
FPC_CMD = (r"fpc -Cs16777216 -gl -bl -Crtoi -Sgidh -vw -Se1 -o%s "
|
||||
r"-FU%s %s") % (_nim_exe, _output_obj,
|
||||
os.path.join(os.getcwd(), "nim", "nimrod.pas"))
|
||||
|
||||
def buildRod(options):
|
||||
Exec("nim compile --compile:build/platdef.c %s rod/nimrod" % options)
|
||||
Move(ExeExt("rod/nimrod"), ExeExt("bin/nimrod"))
|
||||
|
||||
def cmd_nim():
|
||||
CogRule("nversion", "nim/nversion.pas", "koch.py")
|
||||
CogRule("msgs", "nim/msgs.pas", "data/messages.yml")
|
||||
CogRule("ast", "nim/ast.pas", "koch.py data/magic.yml data/ast.yml")
|
||||
CogRule("scanner", "nim/scanner.pas", "data/keywords.txt")
|
||||
CogRule("paslex", "nim/paslex.pas", "data/pas_keyw.yml")
|
||||
CogRule("wordrecg", "nim/wordrecg.pas", "data/keywords.txt")
|
||||
CogRule("commands", "nim/commands.pas",
|
||||
"data/basicopt.txt data/advopt.txt data/changes.txt")
|
||||
c = Changed("nim", Glob("nim/*.pas"),
|
||||
EXPLAIN)
|
||||
if c or force:
|
||||
Exec(FPC_CMD)
|
||||
if Exists(ExeExt("bin/nim")):
|
||||
c.success()
|
||||
|
||||
def cmd_rod(options):
|
||||
cmd_nim()
|
||||
prereqs = Glob("lib/*.nim") + Glob("rod/*.nim") + [
|
||||
"lib/nimbase.h", "lib/dlmalloc.c", "lib/dlmalloc.h",
|
||||
"config/nimrod.cfg"]
|
||||
c = Changed("rod", prereqs, EXPLAIN)
|
||||
if c or force:
|
||||
buildRod(options)
|
||||
if Exists(ExeExt("bin/nimrod")):
|
||||
c.success()
|
||||
|
||||
# ------------------- constants -----------------------------------------------
|
||||
|
||||
HELP = """\
|
||||
+-----------------------------------------------------------------+
|
||||
| Maintenance script for Nimrod |
|
||||
| Version %s|
|
||||
| (c) 2008 Andreas Rumpf |
|
||||
+-----------------------------------------------------------------+
|
||||
|
||||
Usage:
|
||||
koch.py [options] command [options for command]
|
||||
Options:
|
||||
--force, -f, -B, -b force rebuild
|
||||
--help, -h shows this help and quits
|
||||
Possible Commands:
|
||||
install [options] installs the Nimrod Compiler: options
|
||||
are --cc=<compile command>, --ld=<link command>
|
||||
nim builds the Pascal version of Nimrod
|
||||
rod [options] builds the Nimrod version of Nimrod (with options)
|
||||
installer builds the installer (needs Inno Setup 5 on Windows)
|
||||
configure configures the environment for developing Nimrod
|
||||
doc builds the documentation in HTML
|
||||
clean cleans Nimrod project; removes generated files
|
||||
dist produces a distribution as
|
||||
nimrod_$target_$version.zip
|
||||
boot [options] bootstraps with given command line options
|
||||
tests [options] runs the complete testsuite (with options)
|
||||
rodsrc generates Nimrod version from Pascal version
|
||||
web generates the website (requires Cheetah)
|
||||
""" % (NIMROD_VERSION + ' ' * (44-len(NIMROD_VERSION)))
|
||||
|
||||
def main(args):
|
||||
if len(args) == 0:
|
||||
print HELP
|
||||
else:
|
||||
i = 0
|
||||
while args[i].startswith("-"):
|
||||
a = args[i]
|
||||
if a in ("--force", "-f", "-B", "-b"):
|
||||
global force
|
||||
force = True
|
||||
elif a in ("-h", "--help", "-?"):
|
||||
print HELP
|
||||
return
|
||||
else:
|
||||
Error("illegal option: " + a)
|
||||
i += 1
|
||||
cmd = args[i]
|
||||
if cmd == "rod": cmd_rod(" ".join(args[i+1:]))
|
||||
elif cmd == "nim": cmd_nim()
|
||||
elif cmd == "installer": cmd_installer()
|
||||
elif cmd == "configure": cmd_configure()
|
||||
elif cmd == "doc": cmd_doc()
|
||||
elif cmd == "clean": cmd_clean()
|
||||
elif cmd == "dist": cmd_dist()
|
||||
elif cmd == "boot": cmd_boot(" ".join(args[i+1:]))
|
||||
elif cmd == "tests": cmd_tests(" ".join(args[i+1:]))
|
||||
elif cmd == "install": cmd_install(args[i+1:])
|
||||
elif cmd == "rodsrc": cmd_rodsrc()
|
||||
elif cmd == "web": cmd_web()
|
||||
else: Error("illegal command: " + cmd)
|
||||
|
||||
# -------------------------- bootstrap ----------------------------------------
|
||||
|
||||
def cmd_rodsrc():
|
||||
"converts the src/*.pas files into Nimrod syntax"
|
||||
PAS_FILES_BLACKLIST = """nsystem nmath nos ntime strutils""".split()
|
||||
CMD = "nim boot --skip_proj_cfg -o:rod/%s.nim nim/%s"
|
||||
cmd_nim()
|
||||
result = False
|
||||
for fi in Glob("nim/*.pas"):
|
||||
f = FilenameNoExt(fi)
|
||||
if f in PAS_FILES_BLACKLIST: continue
|
||||
c = Changed(f+"__rodsrc", fi, EXPLAIN)
|
||||
if c or force:
|
||||
Exec(CMD % (f, f+".pas"))
|
||||
Exec("nim parse rod/%s.nim" % f)
|
||||
c.success()
|
||||
result = True
|
||||
return result
|
||||
|
||||
def cmd_boot(args):
|
||||
writePlatdefC(getNimrodPath())
|
||||
d = detect("fpc -h")
|
||||
if d:
|
||||
Echo("'%s' detected" % d)
|
||||
cmd_nim()
|
||||
compiler = "nim"
|
||||
else:
|
||||
Warn("Free Pascal is not installed; skipping Pascal step")
|
||||
cmd_install(args)
|
||||
compiler = "nimrod"
|
||||
|
||||
cmd_rodsrc() # regenerate nimrod version of the files
|
||||
|
||||
# move the new executable to bin directory (is done by cmd_rod())
|
||||
# use the new executable to compile the files in the bootstrap directory:
|
||||
Exec("%s compile --compile:build/platdef.c %s rod/nimrod.nim" %
|
||||
(compiler, args))
|
||||
# move the new executable to bin directory:
|
||||
Move(ExeExt("rod/nimrod"), ExeExt("bin/nimrod"))
|
||||
# compile again and compare:
|
||||
Exec("nimrod compile --compile:build/platdef.c %s rod/nimrod.nim" % args)
|
||||
|
||||
# check if the executables are the same (they should!):
|
||||
if filecmp.cmp(Path(ExeExt("rod/nimrod")),
|
||||
Path(ExeExt("bin/nimrod"))):
|
||||
Echo("files are equal: everything seems fine!")
|
||||
else:
|
||||
Warn("files are not equal: cycle once again...")
|
||||
# move the new executable to bin directory:
|
||||
Move(ExeExt("rod/nimrod"), ExeExt("bin/nimrod"))
|
||||
# use the new executable to compile Nimrod:
|
||||
Exec("nimrod compile %s rod/nimrod.nim" % args)
|
||||
if filecmp.cmp(Path(ExeExt("rod/nimrod")),
|
||||
Path(ExeExt("bin/nimrod"))):
|
||||
Echo("files are equal: everything seems fine!")
|
||||
else:
|
||||
Error("files are still not equal")
|
||||
|
||||
# ------------------ web ------------------------------------------------------
|
||||
|
||||
def buildDoc(destPath):
|
||||
DOC = "endb intern lib manual nimrodc tutorial overview".split()
|
||||
SRCDOC = "system os strutils base/regexprs math complex times".split()
|
||||
# call nim for the documentation:
|
||||
for d in DOC:
|
||||
Exec("nim rst2html --putenv:nimrodversion=%s -o:%s/%s.html "
|
||||
"--index=%s/theindex doc/%s" %
|
||||
(NIMROD_VERSION, destPath, d, destPath, d))
|
||||
for d in SRCDOC:
|
||||
Exec("nim doc --putenv:nimrodversion=%s -o:%s/%s.html "
|
||||
"--index=%s/theindex lib/%s" %
|
||||
(NIMROD_VERSION, destPath, FilenameNoExt(d), destPath, d))
|
||||
Exec("nim rst2html -o:%s/theindex.html %s/theindex" % (destPath, destPath))
|
||||
|
||||
|
||||
def cmd_web():
|
||||
import Cheetah.Template
|
||||
TABS = [ # Our tabs: (Menu entry, filename)
|
||||
("home", "index"),
|
||||
("documentation", "documentation"),
|
||||
("download", "download"),
|
||||
("FAQ", "question"),
|
||||
("links", "links")
|
||||
]
|
||||
TEMPLATE_FILE = "web/sunset.tmpl"
|
||||
#CMD = "rst2html.py --template=web/docutils.tmpl web/%s.txt web/%s.temp "
|
||||
CMD = "nim rst2html --compileonly -o:web/%s.temp web/%s.txt"
|
||||
|
||||
c = Changed("web", Glob("web/*.txt") + [TEMPLATE_FILE, "koch.py"] +
|
||||
Glob("doc/*.txt") + Glob("lib/*.txt") + Glob("lib/*.nim")+
|
||||
Glob("config/*.cfg"),
|
||||
EXPLAIN)
|
||||
if c or force:
|
||||
cmd_nim() # we need Nimrod for processing the documentation
|
||||
Exec(CMD % ("news","news"))
|
||||
newsText = file("web/news.temp").read()
|
||||
for t in TABS:
|
||||
Exec(CMD % (t[1],t[1]))
|
||||
|
||||
tmpl = Cheetah.Template.Template(file=TEMPLATE_FILE)
|
||||
tmpl.content = file("web/%s.temp" % t[1]).read()
|
||||
tmpl.news = newsText
|
||||
tmpl.tab = t[1]
|
||||
tmpl.tabs = TABS
|
||||
tmpl.lastupdate = time.strftime("%Y-%m-%d %X", time.gmtime())
|
||||
f = file("web/%s.html" % t[1], "w+")
|
||||
f.write(str(tmpl))
|
||||
f.close()
|
||||
# remove temporaries:
|
||||
Remove("web/news.temp")
|
||||
for t in TABS: Remove("web/%s.temp" % t[1])
|
||||
buildDoc("web")
|
||||
if Exists("web/index.html"):
|
||||
c.success()
|
||||
|
||||
# ------------------ doc ------------------------------------------------------
|
||||
|
||||
def cmd_doc():
|
||||
c = Changed("doc", ["koch.py"] +
|
||||
Glob("doc/*.txt") + Glob("lib/*.txt") + Glob("lib/*.nim")+
|
||||
Glob("config/*.cfg"),
|
||||
EXPLAIN)
|
||||
if c or force:
|
||||
cmd_nim() # we need Nimrod for processing the documentation
|
||||
buildDoc("doc")
|
||||
if Exists("doc/overview.html"):
|
||||
c.success()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def getVersion():
|
||||
return NIMROD_VERSION
|
||||
|
||||
# ------------------------------ clean ----------------------------------------
|
||||
|
||||
CLEAN_EXT = "ppu o obj dcu ~pas ~inc ~dsk ~dpr map tds err bak pyc exe rod"
|
||||
|
||||
def cmd_clean(dir = "."):
|
||||
extRegEx = re.compile("|".join([r".*\."+ x +"$" for x in CLEAN_EXT.split()]))
|
||||
Remove("koch.dat")
|
||||
for f in Glob("web/*.html"): Remove(f)
|
||||
for f in Glob("doc/html/*.html"): Remove(f)
|
||||
for f in Glob("doc/*.html"): Remove(f)
|
||||
for f in Glob("rod/*.nim"): Remove(f) # remove generated source code
|
||||
|
||||
for root, dirs, files in os.walk(dir, topdown=False):
|
||||
for name in files:
|
||||
if (extRegEx.match(name)
|
||||
or (root == "tests" and ('.' not in name))):
|
||||
Remove(os.path.join(root, name))
|
||||
for name in dirs:
|
||||
if name == "rod_gen":
|
||||
shutil.rmtree(path=os.path.join(root, name), ignore_errors=True)
|
||||
|
||||
# ----------------- distributions ---------------------------------------------
|
||||
|
||||
# Here are listed all files that should be included in the different
|
||||
# distributions.
|
||||
|
||||
distlist = {
|
||||
'common': (
|
||||
"copying.txt",
|
||||
"gpl.html",
|
||||
"koch.py",
|
||||
|
||||
"lib/nimbase.h -> lib/nimbase.h",
|
||||
"lib/*.nim -> lib",
|
||||
|
||||
"rod/*.nim -> rod",
|
||||
"nim/*.pas -> nim",
|
||||
"nim/*.txt -> nim",
|
||||
|
||||
"data/*.yml -> data",
|
||||
"data/*.txt -> data",
|
||||
|
||||
"config/nimrod.cfg -> config/nimrod.cfg",
|
||||
# documentation:
|
||||
"doc/*.txt", # only include the text documentation; saves bandwidth!
|
||||
# the installation program should generate the HTML
|
||||
"readme.txt -> readme.txt",
|
||||
"install.txt -> install.txt",
|
||||
|
||||
# library:
|
||||
"lib/base/pcre_all.c -> lib/base/pcre_all.c",
|
||||
"lib/base/pcre.nim -> lib/base/pcre.nim",
|
||||
"lib/base/regexprs.nim -> lib/base/regexprs.nim",
|
||||
#"lib/windows/winapi.nim -> lib/windows/winapi.nim"
|
||||
# don't be too clever here; maybe useful on Linux
|
||||
# for cross-compiling to Windows?
|
||||
),
|
||||
'windows': (
|
||||
"bin/nim.exe -> bin/nim.exe",
|
||||
"koch.exe -> koch.exe",
|
||||
"lib/dlmalloc.h -> lib/dlmalloc.h",
|
||||
"lib/dlmalloc.c -> lib/dlmalloc.c",
|
||||
),
|
||||
'linux': (
|
||||
"lib/rod_gen/*.c -> build",
|
||||
"rod/rod_gen/*.c -> build",
|
||||
),
|
||||
'macosx': (
|
||||
"lib/rod_gen/*.c -> build",
|
||||
"rod/rod_gen/*.c -> build",
|
||||
)
|
||||
}
|
||||
|
||||
def getHost():
|
||||
if os.name == 'nt': return "windows"
|
||||
elif "linux" in sys.platform: return "linux"
|
||||
elif "darwin" in sys.platform: return "macosx" # probably Mac OS X
|
||||
# a heuristic that could work (most likely not :-):
|
||||
else: return re.sub(r"[0-9]+$", r"", sys.platform).lower()
|
||||
|
||||
def iterInstallFiles(target=getHost()):
|
||||
for section in ['common', target]:
|
||||
for rule in distlist[section]:
|
||||
splittedRule = re.split(r"\s*\-\>\s*", rule)
|
||||
if len(splittedRule) == 2:
|
||||
source, dest = splittedRule
|
||||
if '*' in source:
|
||||
for f in Glob(source):
|
||||
yield (Path(f), Path(dest + '/' + os.path.split(f)[1]))
|
||||
else:
|
||||
yield (Path(source), Path(dest))
|
||||
else:
|
||||
for f in Glob(rule):
|
||||
yield (Path(f), Path(f))
|
||||
|
||||
def cmd_dist(target=getHost()):
|
||||
from zipfile import ZipFile
|
||||
distfile = Path('dist/nimrod_%s_%s.zip' % (target, getVersion()))
|
||||
Echo("creating: %s..." % distfile)
|
||||
z = ZipFile(distfile, 'w', zipfile.ZIP_DEFLATED)
|
||||
for source, dest in iterInstallFiles(target):
|
||||
z.write(source, Path(dest))
|
||||
z.close()
|
||||
Echo("... done!")
|
||||
|
||||
# ------------------------------ windows installer ----------------------------
|
||||
|
||||
WIN_INSTALLER_TEMPLATE = (r"""
|
||||
; File generated by koch.py
|
||||
; Template by Andreas Rumpf
|
||||
[Setup]
|
||||
AppName=Nimrod Compiler
|
||||
AppVerName=Nimrod Compiler $version
|
||||
DefaultDirName={code:GiveMeAPath|nimrod}
|
||||
DefaultGroupName=Nimrod
|
||||
AllowNoIcons=yes
|
||||
LicenseFile=nim\copying.txt
|
||||
OutputDir=dist
|
||||
OutputBaseFilename=install_nimrod_$version
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
PrivilegesRequired=none
|
||||
|
||||
[Languages]
|
||||
Name: english; MessagesFile: compiler:Default.isl
|
||||
|
||||
[Files]
|
||||
$files
|
||||
|
||||
[Icons]
|
||||
Name: {group}\Console for Nimrod; Filename: {cmd}
|
||||
Name: {group}\Documentation; Filename: {app}\doc\index.html
|
||||
Name: {group}\{cm:UninstallProgram,Nimrod Compiler}; Filename: {uninstallexe}
|
||||
|
||||
[UninstallDelete]
|
||||
Type: files; Name: "{app}\config\nimrod.cfg"
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\bin\nimconf.exe"; Description: "Launch configuration"; """ +
|
||||
"""Flags: postinstall nowait skipifsilent
|
||||
|
||||
[Code]
|
||||
function GiveMeAPath(const DefaultPathName: string): string;
|
||||
begin
|
||||
if IsAdminLoggedOn then Result := ExpandConstant('{pf}')
|
||||
else Result := ExpandConstant('{userdocs}');
|
||||
Result := Result + '\' + DefaultPathName;
|
||||
end;
|
||||
|
||||
function setEnvCmd(const default: string): string;
|
||||
var
|
||||
op, app: string;
|
||||
begin
|
||||
app := ExpandConstant('{app}');
|
||||
if IsAdminLoggedOn then op := '' else op := 'u';
|
||||
result := '"' + app + '\bin\setenv.exe" -' + op + 'a PATH "%' + app + '\bin"'
|
||||
end;
|
||||
""")
|
||||
|
||||
def makeKochExe():
|
||||
c = Changed("kochexe",
|
||||
("docmacro.py kochmod.py koch.py " +
|
||||
"misc/koch.ico").split(), EXPLAIN)
|
||||
if c or force:
|
||||
Exec("python " + Join(PYINSTALLER, "Makespec.py") +
|
||||
" --onefile --ascii --icon=misc/koch.ico koch.py")
|
||||
Exec("python " + Join(PYINSTALLER, "Build.py") + " koch.spec")
|
||||
Remove("koch.spec")
|
||||
Remove("warnkoch.txt")
|
||||
RemoveDir("buildkoch")
|
||||
c.success()
|
||||
|
||||
def cmd_wininstaller():
|
||||
FILENAME = "install_nimrod.iss"
|
||||
makeKochExe()
|
||||
|
||||
# generate an installer file
|
||||
files = ""
|
||||
for source, dest in iterInstallFiles("windows"):
|
||||
files += ("Source: " + source + "; DestDir: {app}\\" +
|
||||
os.path.split(dest)[0] + "; Flags: ignoreversion\n")
|
||||
f = file(FILENAME, "w+")
|
||||
f.write(Subs(WIN_INSTALLER_TEMPLATE, files=files, version=getVersion()))
|
||||
f.close()
|
||||
if RawExec(INNOSETUP + FILENAME) == 0:
|
||||
# we cannot use ``Exec()`` here as this would
|
||||
# mangle the ``/Q`` switch to ``\Q``
|
||||
Remove(FILENAME)
|
||||
|
||||
# -------------------------- testing the compiler -----------------------------
|
||||
|
||||
# This part verifies Nimrod against the testcases.
|
||||
# The testcases may contain the directives '#ERROR' or '#ERROR_IN'.
|
||||
# '#ERROR' is used to indicate that the compiler should report
|
||||
# an error in the marked line (the line that contains the '#ERROR'
|
||||
# directive.)
|
||||
# The format for '#ERROR_IN' is:
|
||||
# #ERROR_IN filename linenumber
|
||||
# One can omit the extension of the filename ('.nim' is then assumed).
|
||||
# Tests which contain none of the two directives should compile. Thus they
|
||||
# are executed after successful compilation and their output is verified
|
||||
# against the results specified with the '#OUT' directive.
|
||||
# (Tests which require user interaction are currently not possible.)
|
||||
# Tests can have an #ERROR_MSG directive specifiying the error message
|
||||
# Nimrod shall produce.
|
||||
# The code here needs reworking or at least documentation, but I don't have
|
||||
# the time and it has been debugged and optimized.
|
||||
|
||||
try:
|
||||
import subprocess
|
||||
HAS_SUBPROCESS = True
|
||||
except ImportError:
|
||||
HAS_SUBPROCESS = False
|
||||
|
||||
def runProg(args, inp=None):
|
||||
"""Executes the program + args given in args and
|
||||
returns the output of the program as a string."""
|
||||
if HAS_SUBPROCESS:
|
||||
process = subprocess.Popen(args, bufsize=0, shell=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=inp,
|
||||
universal_newlines=True)
|
||||
standardOut, standardErr = process.communicate(inp)
|
||||
process.wait() # be on the safe side
|
||||
return standardOut
|
||||
else:
|
||||
if inp:
|
||||
standardIn = file('buildin.tmp', 'w')
|
||||
standardIn.write(inp)
|
||||
standardIn.close()
|
||||
b = " <buildin.tmp"
|
||||
else:
|
||||
b = ""
|
||||
os.system(args + b + " >build.tmp")
|
||||
result = file('build.tmp').read()
|
||||
if not result: result = ""
|
||||
return result
|
||||
# system() is not optimal, but every Python version should have it
|
||||
|
||||
class Spec(object): pass # specification object
|
||||
|
||||
def parseTest(filename):
|
||||
# spec is a table
|
||||
reError = re.compile(r"#ERROR$")
|
||||
reErrorIn = re.compile(r"#ERROR_IN\s*(\S*)\s*(\d*)")
|
||||
reErrorMsg = re.compile(r"#ERROR_MSG\s*(.*)")
|
||||
reOut = re.compile(r"#OUT\s*(.*)")
|
||||
|
||||
i = 0 # the line counter
|
||||
spec = Spec()
|
||||
spec.line = None # line number where compiler should throw an error
|
||||
spec.file = None # file where compiler should throw an error
|
||||
spec.err = False # true if the specification says there should be an error
|
||||
spec.out = None # output that should be produced
|
||||
|
||||
for s in file(filename, 'rU'):
|
||||
# we have to use this inefficient method for getting the current line
|
||||
i += 1 # our line-counter
|
||||
obj = reError.search(s)
|
||||
if obj:
|
||||
spec.line = i
|
||||
spec.file = filename
|
||||
spec.err = True
|
||||
break
|
||||
obj = reErrorIn.search(s)
|
||||
if obj:
|
||||
spec.file = obj.group(1)
|
||||
spec.line = int(obj.group(2))
|
||||
spec.err = True
|
||||
if '.' not in specfile: specfile += ".nim"
|
||||
break
|
||||
obj = reOut.search(s)
|
||||
if obj:
|
||||
spec.out = obj.group(1)
|
||||
break
|
||||
obj = reErrorMsg.search(s)
|
||||
if obj:
|
||||
spec.out = obj.group(1)
|
||||
spec.err = True
|
||||
break
|
||||
|
||||
return spec
|
||||
|
||||
def doTest(filename, spec, options):
|
||||
# call the compiler
|
||||
# short filename for messages (better readability):
|
||||
shortfile = os.path.split(filename)[1]
|
||||
|
||||
comp = Spec()
|
||||
comp.line = 0
|
||||
comp.file = None
|
||||
comp.out = None
|
||||
comp.err = False
|
||||
# call the compiler and read the compiler message:
|
||||
results = runProg("nim compile --hints:on " + options + " " + filename)
|
||||
print results
|
||||
# compiled regular expressions:
|
||||
reLineInfoError = re.compile(r"^((.*)\((\d+), \d+\)\s*Error\:\s*(.*))",
|
||||
re.MULTILINE)
|
||||
reError = re.compile(r"^Error\:\s*(.*)", re.MULTILINE)
|
||||
reSuccess = re.compile(r"^Hint\:\s*operation successful", re.MULTILINE)
|
||||
obj = reLineInfoError.search(results)
|
||||
if obj:
|
||||
comp.err = True
|
||||
comp.file = obj.group(2)
|
||||
comp.line = int(obj.group(3))
|
||||
comp.out = obj.group(1)
|
||||
comp.puremsg = obj.group(4)
|
||||
else:
|
||||
comp.puremsg = ''
|
||||
obj = reError.search(results)
|
||||
if obj:
|
||||
comp.err = True
|
||||
comp.out = results
|
||||
comp.puremsg = obj.group(1)
|
||||
comp.line = 1
|
||||
else:
|
||||
obj = reSuccess.search(results)
|
||||
if not obj: comp.err = True
|
||||
|
||||
if comp.err and not comp.out:
|
||||
# the compiler did not say "[Error]" nor "Compilation sucessful"
|
||||
Echo("[Tester] %s -- FAILED; COMPILER BROKEN" % shortfile)
|
||||
return False
|
||||
|
||||
if (spec.err != comp.err
|
||||
or (spec.line and (abs(spec.line - comp.line) > 1))
|
||||
or (spec.file and (spec.file.lower() != comp.file.lower()))
|
||||
or (spec.out and not (spec.out.strip() in comp.puremsg.strip()))):
|
||||
if spec.out:
|
||||
Echo("[Tester] %s -- FAILED\n"
|
||||
"Compiler says: %s\n"
|
||||
"But specification says: Error %s"
|
||||
% (shortfile, comp.out, spec.out) )
|
||||
elif spec.err:
|
||||
if spec.file is None: spec.file = filename
|
||||
if spec.line is None: spec.line = -1
|
||||
Echo("[Tester] %s -- FAILED\n"
|
||||
"Compiler says: %s\n"
|
||||
"But specification says: Error in %s line %d"
|
||||
% (shortfile, comp.out, spec.file, spec.line) )
|
||||
else:
|
||||
Echo("[Tester] %s -- FAILED\n"
|
||||
"Compiler says: %s\n"
|
||||
"But specification says: no error"
|
||||
% (shortfile, comp.out) )
|
||||
return False
|
||||
else:
|
||||
if spec.err:
|
||||
Echo("[Tester] " + shortfile + ' -- OK') # error correctly reported
|
||||
return True
|
||||
else:
|
||||
# run the compiled program and check if it works
|
||||
fileNoExt = os.path.splitext(filename)[0]
|
||||
if os.path.isfile(ExeExt(fileNoExt)):
|
||||
if spec.out:
|
||||
buf = runProg(fileNoExt)
|
||||
if buf.strip() == spec.out.strip():
|
||||
Echo("[Tester] " + shortfile + " -- compiled program OK")
|
||||
return True
|
||||
else:
|
||||
Echo("[Tester] " + shortfile + " -- compiled program FAILED")
|
||||
return False
|
||||
else:
|
||||
Echo("[Tester] " + shortfile + ' -- OK')
|
||||
return True
|
||||
# we have no output to validate against, but compilation succeeded,
|
||||
# so it's okay
|
||||
elif '--compile_only' in options:
|
||||
Echo("[Tester] " + shortfile + ' -- OK')
|
||||
return True
|
||||
else:
|
||||
Echo("[Tester] " + shortfile + " -- FAILED\n"
|
||||
"no compiled program found")
|
||||
return False
|
||||
|
||||
def cmd_tests(options): # run the testsuite
|
||||
"""runs the complete testsuite"""
|
||||
#clean(True) # first clean before running the testsuite
|
||||
total = 0
|
||||
passed = 0
|
||||
for filename in Glob("tests/t*.nim"):
|
||||
spec = parseTest(filename)
|
||||
res = doTest(filename, spec, options)
|
||||
assert(res is not None)
|
||||
if res: passed += 1
|
||||
total += 1
|
||||
break
|
||||
Echo("[Tester] %d/%d tests passed\n" % (passed, total))
|
||||
|
||||
# --------------- install target ----------------------------------------------
|
||||
|
||||
CONFIG_TEMPLATE = r"""# Configuration file for the Nimrod Compiler.
|
||||
# Generated by the koch.py script.
|
||||
# (c) 2008 Andreas Rumpf
|
||||
|
||||
# Feel free to edit the default values as you need.
|
||||
|
||||
# You may set environment variables with
|
||||
# @putenv "key" "val"
|
||||
# Environment variables cannot be used in the options, however!
|
||||
|
||||
# Just call the compiler with several options:
|
||||
cc = @if unix: %(cc)s @else: vcc @end
|
||||
lib="$nimrod/lib"
|
||||
path="$lib/base"
|
||||
path="$lib/base/gtk"
|
||||
path="$lib/base/cairo"
|
||||
path="$lib/base/x11"
|
||||
path="$lib/windows"
|
||||
path="$lib/extra"
|
||||
|
||||
# additional defines:
|
||||
#define=""
|
||||
# additional options always passed to the compiler:
|
||||
force_build
|
||||
line_dir=off
|
||||
|
||||
hint[LineTooLong]=off
|
||||
hint[XDeclaredButNotUsed]=off
|
||||
|
||||
@if unix:
|
||||
passl= "-ldl"
|
||||
path = "$lib/base/gtk"
|
||||
@end
|
||||
|
||||
@if icc:
|
||||
passl = "-cxxlib"
|
||||
passc = "-cxxlib"
|
||||
@end
|
||||
|
||||
# Configuration for the Borland C++ Compiler:
|
||||
@if windows:
|
||||
bcc.path = r"C:\eigenes\compiler\cbuilder5\bin"
|
||||
@end
|
||||
bcc.options.debug = ""
|
||||
# turn off warnings about unreachable code and inline procs:
|
||||
bcc.options.always = "-w- -H- -q -RT- -a8 -w-8027 -w-8066"
|
||||
bcc.options.speed = "-O2 -6"
|
||||
bcc.options.size = "-O1 -6"
|
||||
|
||||
# Configuration for the Visual C/C++ compiler:
|
||||
@if vcc:
|
||||
@prepend_env path r"C:\Eigenes\compiler\vcc2005\Common7\IDE;"
|
||||
@prepend_env INCLUDE r"C:\Eigenes\compiler\vcc2005\VC\include;C:\Eigenes\compiler\vcc2005\VC\ATLMFC\INCLUDE;"
|
||||
@prepend_env LIB r"C:\Eigenes\compiler\vcc2005\VC\lib;C:\Eigenes\compiler\vcc2005\SDK\v2.0\Lib;"
|
||||
@end
|
||||
@if windows:
|
||||
vcc.path = r"C:\Eigenes\compiler\vcc2005\VC\bin"
|
||||
@end
|
||||
vcc.options.debug = "/GZ /ZI"
|
||||
vcc.options.always = "/nologo"
|
||||
vcc.options.speed = "/Ogityb2 /G7 /arch:SSE2"
|
||||
vcc.options.size = "/O1 /G7"
|
||||
|
||||
# Configuration for the Watcom C/C++ compiler:
|
||||
@if windows:
|
||||
wcc.path = r"C:\eigenes\compiler\watcom\binnt"
|
||||
@end
|
||||
wcc.options.debug = "-d2"
|
||||
wcc.options.always = "-6 -zw -w-"
|
||||
wcc.options.speed = "-ox -on -6 -d0 -fp6 -zW"
|
||||
wcc.options.size = "-ox -on -6 -d0 -fp6 -zW"
|
||||
|
||||
# Configuration for the GNU C/C++ compiler:
|
||||
@if windows:
|
||||
gcc.path = r"C:\eigenes\compiler\mingw\bin"
|
||||
@end
|
||||
gcc.options.debug = "-g"
|
||||
@if macosx:
|
||||
gcc.options.always = "-w -fasm-blocks"
|
||||
@else:
|
||||
gcc.options.always = "-w"
|
||||
@end
|
||||
gcc.options.speed = "-O3 -ffast-math"
|
||||
gcc.options.size = "-Os -ffast-math"
|
||||
|
||||
# Configuration for the Digital Mars C/C++ compiler:
|
||||
@if windows:
|
||||
dmc.path = r"C:\eigenes\compiler\d\dm\bin"
|
||||
@end
|
||||
dmc.options.debug = "-g"
|
||||
dmc.options.always = "-Jm"
|
||||
dmc.options.speed = "-ff -o -6"
|
||||
dmc.options.size = "-ff -o -6"
|
||||
|
||||
# Configuration for the LCC compiler:
|
||||
@if windows:
|
||||
lcc.path = r"C:\eigenes\compiler\lcc\bin"
|
||||
@end
|
||||
lcc.options.debug = "-g5"
|
||||
lcc.options.always = "-e1"
|
||||
lcc.options.speed = "-O -p6"
|
||||
lcc.options.size = "-O -p6"
|
||||
|
||||
# Configuration for the Tiny C Compiler:
|
||||
@if windows:
|
||||
tcc.path = r"C:\eigenes\compiler\tcc\bin"
|
||||
@end
|
||||
tcc.options.debug = "-b"
|
||||
tcc.options.always = ""
|
||||
tcc.options.speed = ""
|
||||
tcc.options.size = ""
|
||||
|
||||
# Configuration for the Pelles C compiler:
|
||||
@if windows:
|
||||
pcc.path = r"C:\eigenes\compiler\pellesc\bin"
|
||||
@end
|
||||
pcc.options.debug = "-Zi"
|
||||
pcc.options.always = "-Ze"
|
||||
pcc.options.speed = "-Ox"
|
||||
pcc.options.size = "-Os"
|
||||
|
||||
# Configuration for the LLVM GCC compiler:
|
||||
@if windows:
|
||||
llvm_gcc.path = r"c:\eignes\compiler\llvm-gcc\bin"
|
||||
@end
|
||||
llvm_gcc.options.debug = "-g"
|
||||
llvm_gcc.options.always = "-w"
|
||||
llvm_gcc.options.speed = "-O3 -ffast-math"
|
||||
llvm_gcc.options.size = "-Os -ffast-math"
|
||||
|
||||
@if windows:
|
||||
icc.path = r"c:\eignes\compiler\icc\bin"
|
||||
@end
|
||||
icc.options.debug = "-g"
|
||||
icc.options.always = "-w"
|
||||
icc.options.speed = "-O3 -ffast-math"
|
||||
icc.options.size = "-Os -ffast-math"
|
||||
|
||||
@write "used default config file"
|
||||
"""
|
||||
|
||||
def writePlatdefC(nimrodpath):
|
||||
import os
|
||||
host = getHost()
|
||||
if host == "windows": processor = "i386" # BUGFIX
|
||||
else: processor = os.uname()[4]
|
||||
if processor.lower() in ("i686", "i586", "i468", "i386"):
|
||||
processor = "i386"
|
||||
if "sparc" in processor.lower():
|
||||
processor = "sparc"
|
||||
f = file(os.path.join(nimrodpath, "build/platdef.c"), "w+")
|
||||
f.write('/* Generated by koch.py */\n'
|
||||
'#include "nimbase.h"\n'
|
||||
'N_NIMCALL(char*, nimOS)(void) { return "%s"; }\n'
|
||||
'N_NIMCALL(char*, nimCPU)(void) { return "%s"; }\n'
|
||||
'\n' % (host, processor))
|
||||
f.close()
|
||||
|
||||
def detect(cmd, lookFor="version"):
|
||||
pipe = os.popen4(cmd)[1]
|
||||
result = None
|
||||
for line in pipe:
|
||||
if lookFor in line:
|
||||
result = line[:-1]
|
||||
break
|
||||
pipe.close()
|
||||
return result
|
||||
|
||||
def lookForCC():
|
||||
if "CC" in os.environ:
|
||||
Echo("using $CC environment variable (%s)" % os.environ["CC"])
|
||||
return os.environ["CC"]
|
||||
d = detect("gcc -v")
|
||||
if d:
|
||||
Echo("'%s' detected" % d)
|
||||
return "gcc"
|
||||
Echo("GCC not found. Testing for generic CC...")
|
||||
d = detect("cc -v")
|
||||
if d:
|
||||
Echo("'%s' detected" % d)
|
||||
return "ucc"
|
||||
Echo("...not found!")
|
||||
Error("No C compiler could be found!")
|
||||
return ""
|
||||
|
||||
def getNimrodPath():
|
||||
if os.name == "posix":
|
||||
# Does not work 100% reliably. It is the best solution though.
|
||||
p = sys.argv[0].replace("./", "")
|
||||
return os.path.split(os.path.join(os.getcwd(), p))[0]
|
||||
else: # Windows
|
||||
return os.path.split(sys.argv[0])[0]
|
||||
|
||||
def writeCfg(nimrodpath, ccSymbol=None):
|
||||
if not ccSymbol:
|
||||
ccSymbol = lookForCC()
|
||||
configFile = os.path.join(nimrodpath, "config/nimrod.cfg")
|
||||
script = CONFIG_TEMPLATE % {'cc': ccSymbol, 'nimrodpath': nimrodpath}
|
||||
config = file(configFile)
|
||||
if config:
|
||||
if config.read().strip() != script.strip():
|
||||
config.close()
|
||||
Echo("Configuration file already exists and "
|
||||
"seems to have been modified.\n"
|
||||
"Do you want to override it? (y/n) ")
|
||||
while True:
|
||||
a = ask()
|
||||
if a in ("y", "yes"):
|
||||
f = file(configFile, "w+")
|
||||
f.write(script)
|
||||
f.close()
|
||||
break
|
||||
elif a in ("n", "no"):
|
||||
break
|
||||
else:
|
||||
Echo("What do you mean? (y/n) ")
|
||||
else:
|
||||
config.close()
|
||||
return ccSymbol
|
||||
|
||||
def cmd_install(args):
|
||||
Echo("Nimrod should be in '%s'" % getNimrodPath())
|
||||
# We know that the user has already unzipped this archive into the
|
||||
# final directory. So we just create the config file and build Nimrod.
|
||||
|
||||
# write the configuration file, but check if one exists!
|
||||
nimrodpath = getNimrodPath()
|
||||
try:
|
||||
opts, args = getopt.getopt(args, "", ["cc=", "ld="])
|
||||
except getopt.GetoptError:
|
||||
# print help information and exit:
|
||||
Error("Command line contains errors")
|
||||
ccSymbol = None
|
||||
ldSymbol = None
|
||||
for o, a in opts:
|
||||
if o == "--cc": ccSymbol = a
|
||||
elif o == "--ld": ldSymbol = a
|
||||
|
||||
ccSymbol = writeCfg(nimrodpath, ccSymbol)
|
||||
if not ldSymbol:
|
||||
ldSymbol = ccSymbol.split()[0] + " -ldl -o bin/nimrod "
|
||||
|
||||
writePlatdefC(nimrodpath)
|
||||
|
||||
# build Nimrod
|
||||
link = "" # store the .o files in here for final linking step
|
||||
for f in Glob("build/*.c"):
|
||||
objfile = os.path.splitext(f)[0] + ".o"
|
||||
link += " " + objfile
|
||||
# compile only:
|
||||
if Exec(ccSymbol + " " + CFLAGS + " -c -o " + objfile + " " + f) != 0:
|
||||
Error("the C compiler did not like: " + f)
|
||||
if link == "":
|
||||
Error("could not find Nimrod's sources\n"
|
||||
" (they should be in the build subdirectory)")
|
||||
# now link the stuff together:
|
||||
if Exec(ldSymbol + link) != 0:
|
||||
Error("the linking step failed!")
|
||||
# now we have a Nimrod executable :-)
|
||||
|
||||
nimrodpath = getNimrodPath()
|
||||
writeScript(CONFIG_TEMPLATE % {'cc': ccSymbol, 'nimrodpath': nimrodpath},
|
||||
os.path.join(nimrodpath, "config/nimrod.cfg"))
|
||||
|
||||
# remove the generated .o files as they take 1 MB:
|
||||
for f in Glob("build/*.o"): Remove(f)
|
||||
Echo("SUCCESS!")
|
||||
|
||||
def cmd_installer():
|
||||
if os.name == "posix":
|
||||
Echo("Nothing to do")
|
||||
else: # Windows
|
||||
cmd_wininstaller()
|
||||
|
||||
|
||||
# ------------------ configure ------------------------------------------------
|
||||
|
||||
def writeScript(script, filename):
|
||||
if os.name != "posix": filename += ".bat"
|
||||
f = file(filename, "w+")
|
||||
f.write(script)
|
||||
f.close()
|
||||
# make the script executable:
|
||||
if os.name == "posix":
|
||||
os.chmod(filename, 493) # 0o755
|
||||
|
||||
def cmd_configure():
|
||||
d = detect("fpc -h")
|
||||
if d:
|
||||
Echo("'%s' detected" % d)
|
||||
else:
|
||||
Warn("Free Pascal is not installed, bootstrapping may not work properly.")
|
||||
writeCfg(getNimrodPath())
|
||||
Echo("Configuration sucessful!")
|
||||
|
||||
# ------------------- main ----------------------------------------------------
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
||||
640
kochmod.py
Executable file
640
kochmod.py
Executable file
@@ -0,0 +1,640 @@
|
||||
# This is kochmod, a simple module for make-like functionality.
|
||||
# For further documentation see koch.txt or koch.html.
|
||||
# (c) 2007 Andreas Rumpf
|
||||
|
||||
VERSION = "1.0.3"
|
||||
|
||||
import os, os.path, inspect, re, shutil, glob, cPickle, zlib, string, \
|
||||
getopt, sys
|
||||
from types import *
|
||||
|
||||
def Error(msg): sys.exit("[Koch] *** ERROR: " + msg)
|
||||
def Warn(msg): print "[Koch] *** WARNING: " + msg
|
||||
def Echo(msg): print "[Koch] " + msg
|
||||
def _Info(msg): print "[Koch] " + msg
|
||||
|
||||
_FINGERPRINTS_FILE = "koch.dat"
|
||||
# in this file all the fingerprints are kept to allow recognizing when a file
|
||||
# has changed. This works reliably, which cannot be said from just taking
|
||||
# filetime-stamps.
|
||||
|
||||
# ---------------- C Compilers ------------------------------------------------
|
||||
|
||||
# We support the following C compilers:
|
||||
C_Compilers = ["gcc", "lcc", "bcc", "dmc", "wcc", "tcc", "pcc", "ucc", "llvm"]
|
||||
|
||||
_CC_Info = [
|
||||
dict(
|
||||
name = "gcc",
|
||||
objExt = "o",
|
||||
optSpeed = " -O3 -ffast-math ",
|
||||
optSize = " -Os -ffast-math ",
|
||||
comp = "gcc -c $options $include -o $objfile $file",
|
||||
buildGui = " -mwindows",
|
||||
buildDll = " -mdll",
|
||||
link = "gcc $options $buildgui $builddll -o $exefile $objfiles",
|
||||
includeCmd = " -I",
|
||||
debug = "",
|
||||
defineValue = " -D$name=$value",
|
||||
define = " -D$name",
|
||||
undef = " -U$name",
|
||||
pic = "-fPIC"
|
||||
), dict(
|
||||
name = "lcc",
|
||||
objExt = "obj",
|
||||
optSpeed = " -O -p6 ",
|
||||
optSize = " -O -p6 ",
|
||||
comp = "lcc -e1 $options $include -Fo$objfile $file",
|
||||
buildGui = " -subsystem windows",
|
||||
buildDll = " -dll",
|
||||
link = "lcclnk $options $buildgui $builddll -O $exefile $objfiles",
|
||||
includeCmd = " -I",
|
||||
debug = " -g5 ",
|
||||
defineValue = " -D$name=$value",
|
||||
define = " -D$name",
|
||||
undef = " -U$name",
|
||||
pic = ""
|
||||
), dict(
|
||||
name = "bcc",
|
||||
objExt = "obj",
|
||||
optSpeed = " -O2 -6 ",
|
||||
optSize = " -O1 -6 ",
|
||||
comp = "bcc32 -c -H- -q -RT- -a8 $options $include -o$objfile $file",
|
||||
buildGui = " -tW",
|
||||
buildDll = " -tWD",
|
||||
link = "bcc32 $options $buildgui $builddll -e$exefile $objfiles",
|
||||
includeCmd = " -I",
|
||||
debug = "",
|
||||
defineValue = " -D$name=$value",
|
||||
define = " -D$name",
|
||||
undef = " -U$name",
|
||||
pic = ""
|
||||
), dict(
|
||||
name = "dmc",
|
||||
objExt = "obj",
|
||||
optSpeed = " -ff -o -6 ",
|
||||
optSize = " -ff -o -6 ",
|
||||
comp = "dmc -c -Jm $options $include -o$objfile $file",
|
||||
buildGui = " -L/exet:nt/su:windows",
|
||||
buildDll = " -WD",
|
||||
link = "dmc $options $buildgui $builddll -o$exefile $objfiles",
|
||||
includeCmd = " -I",
|
||||
debug = " -g ",
|
||||
defineValue = " -D$name=$value",
|
||||
define = " -D$name",
|
||||
undef = " -U$name", # XXX: dmc does not have -U ?
|
||||
pic = ""
|
||||
), dict(
|
||||
name = "wcc",
|
||||
objExt = "obj",
|
||||
optSpeed = " -ox -on -6 -d0 -fp6 -zW ",
|
||||
optSize = "",
|
||||
comp = "wcl386 -c -6 -zw $options $include -fo=$objfile $file",
|
||||
buildGui = " -bw",
|
||||
buildDll = " -bd",
|
||||
link = "wcl386 $options $buildgui $builddll -fe=$exefile $objfiles ",
|
||||
includeCmd = " -i=",
|
||||
debug = " -d2 ",
|
||||
defineValue = " -d$name=$value",
|
||||
define = " -d$name",
|
||||
undef = " -u$name",
|
||||
pic = ""
|
||||
), dict(
|
||||
name = "vcc",
|
||||
objExt = "obj",
|
||||
optSpeed = " /Ogityb2 /G7 /arch:SSE2 ",
|
||||
optSize = " /O1 /G7 ",
|
||||
comp = "cl /c $options $include /Fo$objfile $file",
|
||||
buildGui = " /link /SUBSYSTEM:WINDOWS ",
|
||||
buildDll = " /LD",
|
||||
link = "cl $options $builddll /Fe$exefile $objfiles $buildgui",
|
||||
includeCmd = " /I",
|
||||
debug = " /GZ /Zi ",
|
||||
defineValue = " /D$name=$value",
|
||||
define = " /D$name",
|
||||
undef = " /U$name",
|
||||
pic = ""
|
||||
), dict(
|
||||
name = "tcc",
|
||||
objExt = "o",
|
||||
optSpeed = "", # Tiny C has no optimizer
|
||||
optSize = "",
|
||||
comp = "tcc -c $options $include -o $objfile $file",
|
||||
buildGui = "UNAVAILABLE!",
|
||||
buildDll = " -shared",
|
||||
link = "tcc -o $exefile $options $buildgui $builddll $objfiles",
|
||||
includeCmd = " -I",
|
||||
debug = " -b ",
|
||||
defineValue = " -D$name=$value",
|
||||
define = " -D$name",
|
||||
undef = " -U$name",
|
||||
pic = ""
|
||||
), dict(
|
||||
name = "pcc", # Pelles C
|
||||
objExt = "obj",
|
||||
optSpeed = " -Ox ",
|
||||
optSize = " -Os ",
|
||||
comp = "cc -c $options $include -Fo$objfile $file",
|
||||
buildGui = " -SUBSYSTEM:WINDOWS",
|
||||
buildDll = " -DLL",
|
||||
link = "cc $options $buildgui $builddll -OUT:$exefile $objfiles",
|
||||
includeCmd = " -I",
|
||||
debug = " -Zi ",
|
||||
defineValue = " -D$name=$value",
|
||||
define = " -D$name",
|
||||
undef = " -U$name",
|
||||
pic = ""
|
||||
), dict(
|
||||
name = "ucc",
|
||||
objExt = "o",
|
||||
optSpeed = " -O3 ",
|
||||
optSize = " -O1 ",
|
||||
comp = "cc -c $options $include -o $objfile $file",
|
||||
buildGui = "",
|
||||
buildDll = " -shared ",
|
||||
link = "cc -o $exefile $options $buildgui $builddll $objfiles",
|
||||
includeCmd = " -I",
|
||||
debug = "",
|
||||
defineValue = " -D$name=$value",
|
||||
define = " -D$name",
|
||||
undef = " -U$name",
|
||||
pic = ""
|
||||
), dict(
|
||||
name = "llvm_gcc", # its options are the same as GCC's
|
||||
objExt = "o",
|
||||
optSpeed = " -O3 -ffast-math ",
|
||||
optSize = " -Os -ffast-math ",
|
||||
comp = "llvm-gcc -c $options $include -o $objfile $file",
|
||||
buildGui = " -mwindows",
|
||||
buildDll = " -mdll",
|
||||
link = "llvm-gcc $options $buildgui $builddll -o $exefile $objfiles",
|
||||
includeCmd = " -I",
|
||||
debug = "",
|
||||
defineValue = " -D$name=$value",
|
||||
define = " -D$name",
|
||||
undef = " -U$name",
|
||||
pic = "-fPIC"
|
||||
)
|
||||
]
|
||||
|
||||
# --------------- little helpers ---------------------------------------------
|
||||
|
||||
def Subs(frmt, **substitution):
|
||||
if isinstance(frmt, basestring):
|
||||
return string.Template(frmt).substitute(substitution)
|
||||
else:
|
||||
return tuple([string.Template(x).substitute(substitution) for x in frmt])
|
||||
|
||||
_baseDir = os.getcwd()
|
||||
BaseDir = _baseDir
|
||||
|
||||
def Path(a):
|
||||
# Gets a UNIX like path and converts it to a path on this platform.
|
||||
# With UNIX like, I mean: slashes, not backslashes, only relative
|
||||
# paths ('../etc' can be used)
|
||||
result = a
|
||||
if os.sep != "/": result = result.replace("/", os.sep)
|
||||
if os.pardir != "..": result = result.replace("..", os.pardir)
|
||||
return result
|
||||
|
||||
def Join(*args):
|
||||
result = ""
|
||||
for a in args[:-1]:
|
||||
result += a
|
||||
if result[-1] != "/":
|
||||
result += "/"
|
||||
result += args[-1]
|
||||
return result.replace("//", "/")
|
||||
|
||||
def Exec(command):
|
||||
c = Path(command)
|
||||
Echo(c)
|
||||
result = os.system(c)
|
||||
if result != 0: Error("execution of an external program failed")
|
||||
return result
|
||||
|
||||
def TryExec(command):
|
||||
c = Path(command)
|
||||
Echo(c)
|
||||
result = os.system(c)
|
||||
return result
|
||||
|
||||
def RawExec(command):
|
||||
Echo(command)
|
||||
result = os.system(command)
|
||||
if result != 0: Error("execution of an external program failed")
|
||||
return result
|
||||
|
||||
def Move(src, dest):
|
||||
s = Path(src)
|
||||
d = Path(dest)
|
||||
try:
|
||||
shutil.move(s, d)
|
||||
except IOError, OSError:
|
||||
Warn("could not move %s to %s" % (s, d))
|
||||
|
||||
def Copy(src, dest):
|
||||
s = Path(src)
|
||||
d = Path(dest)
|
||||
try:
|
||||
shutil.copyfile(s, d)
|
||||
except IOError, OSError:
|
||||
Warn("could not copy %s to %s" % (s, d))
|
||||
|
||||
def Remove(f):
|
||||
try:
|
||||
os.remove(Path(f))
|
||||
except OSError:
|
||||
Warn("could not remove: %s" % f)
|
||||
|
||||
def RemoveDir(f):
|
||||
try:
|
||||
shutil.rmtree(Path(f))
|
||||
except OSError:
|
||||
Warn("could not remove: %s" % f)
|
||||
|
||||
def Exists(f): return os.path.exists(Path(f))
|
||||
|
||||
def Chdir(dest):
|
||||
d = Path(dest)
|
||||
try:
|
||||
os.chdir(d)
|
||||
except OSError:
|
||||
Warn("could not switch to directory: " + d)
|
||||
|
||||
def Mkdir(dest):
|
||||
d = Path(dest)
|
||||
try:
|
||||
os.mkdir(d)
|
||||
except OSError:
|
||||
Warn("could not create directory: " + d)
|
||||
|
||||
def Glob(pattern): # needed because glob.glob() is buggy on Windows 95:
|
||||
# things like tests/t*.mor won't work
|
||||
global _baseDir
|
||||
(head, tail) = os.path.split(Path(pattern))
|
||||
try:
|
||||
os.chdir(os.path.join(_baseDir, head))
|
||||
result = []
|
||||
for f in glob.glob(tail):
|
||||
result.append(os.path.join(head, f))
|
||||
except OSError:
|
||||
result = []
|
||||
finally:
|
||||
os.chdir(_baseDir)
|
||||
return result
|
||||
|
||||
def FilenameNoExt(f):
|
||||
return os.path.splitext(os.path.basename(f))[0]
|
||||
|
||||
def _Ext(trunc, posixFormat, winFormat):
|
||||
(head, tail) = os.path.split(Path(trunc))
|
||||
if os.name == "posix": frmt = posixFormat
|
||||
else: frmt = winFormat
|
||||
return os.path.join(head, Subs(frmt, trunc=tail))
|
||||
|
||||
def DynExt(trunc):
|
||||
"""Makes a dynamic library out of a trunc. This means it either
|
||||
does '${trunc}.dll' or 'lib${trunc}.so'.
|
||||
"""
|
||||
return _Ext(trunc, 'lib${trunc}.so', '${trunc}.dll')
|
||||
|
||||
def LibExt(trunc):
|
||||
"""Makes a static library out of a trunc. This means it either
|
||||
does '${trunc}.lib' or '${trunc}.a'.
|
||||
"""
|
||||
return _Ext(trunc, '${trunc}.a', '${trunc}.lib')
|
||||
|
||||
def ScriptExt(trunc):
|
||||
"""Makes a script out of a trunc. This means it either
|
||||
does '${trunc}.bat' or '${trunc}.sh'.
|
||||
"""
|
||||
return _Ext(trunc, '${trunc}.sh', '${trunc}.bat')
|
||||
|
||||
def ExeExt(trunc):
|
||||
"""Makes an executable out of a trunc. This means it either
|
||||
does '${trunc}.exe' or '${trunc}'.
|
||||
"""
|
||||
return _Ext(trunc, '${trunc}', '${trunc}.exe')
|
||||
|
||||
def MakeExecutable(file):
|
||||
os.chmod(file, 493)
|
||||
|
||||
# ----------------- Dependency Analyser Core ---------------------------------
|
||||
# We simply store the rules in a list until building the things. Checking is
|
||||
# also delayed.
|
||||
_rules = {}
|
||||
_importantTargets = [] # used for command line switches
|
||||
_commands = {} # other commands
|
||||
# a command is a tuple: (name, description, function, number of arguments)
|
||||
|
||||
def Command(name, desc, func, args=0):
|
||||
"""if args == -1, a variable number of arguments is given to the ``func``
|
||||
as a list"""
|
||||
_commands[name] = (desc, func, args)
|
||||
|
||||
def _applyPath(x):
|
||||
if type(x) == ListType:
|
||||
return map(Path, x)
|
||||
else:
|
||||
return Path(x)
|
||||
|
||||
def Rule(name = None, desc = "", prereqs = [], cmds = None, outputfile = None,
|
||||
modifies = []):
|
||||
"""Defines a rule. Name must be a single word, not a file!"""
|
||||
if not name:
|
||||
t = "#" + str(len(_rules.keys()))
|
||||
else:
|
||||
t = name
|
||||
if t in _rules: Error("target '%s' already exists!" % t)
|
||||
_rules[t] = (_applyPath(prereqs), cmds, outputfile, _applyPath(modifies))
|
||||
if desc:
|
||||
_importantTargets.append((t, desc))
|
||||
|
||||
|
||||
class Changed(object):
|
||||
""" Returns a Changed object. This object evals to true if one of the
|
||||
given files has changed, false otherwise in a boolean context. You have
|
||||
to call the object's success() method if the building has been a success.
|
||||
|
||||
Example:
|
||||
|
||||
c = Changed("unique_name", "file1.pas file2.pas file3.pas")
|
||||
if c:
|
||||
Exec("fpc file1.pas")
|
||||
# Exec raises an exception if it fails, thus if we get to here, it was
|
||||
# a success:
|
||||
c.success()
|
||||
"""
|
||||
def __init__(self, id, files, explain=False,
|
||||
fingerprintsfile=_FINGERPRINTS_FILE):
|
||||
# load the fingerprints file:
|
||||
# fingerprints is a dict[target, files] where files is a dict[filename, hash]
|
||||
self.fingers = {} # default value
|
||||
if Exists(fingerprintsfile):
|
||||
try:
|
||||
self.fingers = cPickle.load(file(fingerprintsfile))
|
||||
except OSError:
|
||||
Error("Cannot read from " + fingerprintsfile)
|
||||
self.filename = fingerprintsfile
|
||||
self.id = id
|
||||
self.files = files
|
||||
self._hashStr = zlib.adler32 # our hash function
|
||||
self.explain = explain
|
||||
|
||||
def _hashFile(self, f):
|
||||
x = file(f)
|
||||
result = self._hashStr(x.read())
|
||||
x.close() # for other Python implementations
|
||||
return result
|
||||
|
||||
def __nonzero__(self):
|
||||
if type(self.files) == type(""):
|
||||
self.files = self.files.split()
|
||||
result = False
|
||||
target = self.id
|
||||
if not (target in self.fingers):
|
||||
self.fingers[target] = {}
|
||||
if self.explain: _Info("no entries for target '%s'" % target)
|
||||
result = True
|
||||
for d in self.files:
|
||||
if Exists(d):
|
||||
n = self._hashFile(d)
|
||||
if d not in self.fingers[target] or n != self.fingers[target][d]:
|
||||
result = True
|
||||
if self.explain: _Info("'%s' modified since last build" % d)
|
||||
self.fingers[target][d] = n
|
||||
else:
|
||||
Warn("'%s' does not exist!" % d)
|
||||
result = True
|
||||
return result
|
||||
|
||||
def update(self, filename):
|
||||
self.fingers[self.id][filename] = self._hashFile(filename)
|
||||
|
||||
def success(self):
|
||||
cPickle.dump(self.fingers, file(self.filename, "w+"))
|
||||
|
||||
|
||||
class _Koch(object):
|
||||
def _loadFingerprints(self, filename):
|
||||
# fingerprints is a dict[target, files] where files is a dict[filename, hash]
|
||||
if Exists(filename):
|
||||
try:
|
||||
self.fingers = cPickle.load(file(filename))
|
||||
except OSError:
|
||||
Error("Cannot read from " + filename)
|
||||
else:
|
||||
self.fingers = {} # we have no fingerprints :-(
|
||||
|
||||
def _saveFingerprints(self, filename):
|
||||
cPickle.dump(self.fingers, file(filename, "w+"))
|
||||
|
||||
def __init__(self, options):
|
||||
self._loadFingerprints(_FINGERPRINTS_FILE)
|
||||
self.newfingers = {}
|
||||
self.rules = _rules
|
||||
self._hashStr = zlib.adler32 # our hash function
|
||||
self.options = options
|
||||
|
||||
def _doRebuild(self, cmd):
|
||||
if cmd is None: return 0
|
||||
if type(cmd) is StringType:
|
||||
if cmd:
|
||||
c = Path(cmd)
|
||||
_Info(c)
|
||||
return os.system(c)
|
||||
else:
|
||||
return 0
|
||||
elif type(cmd) is FunctionType:
|
||||
return cmd()
|
||||
elif type(cmd) is ListType:
|
||||
for c in cmd:
|
||||
res = self._doRebuild(c)
|
||||
if res != 0: break
|
||||
return res
|
||||
else:
|
||||
Error("invalid rule: command must be a string or a function")
|
||||
|
||||
def _hashFile(self, f):
|
||||
x = file(f)
|
||||
result = self._hashStr(x.read())
|
||||
x.close() # for other Python implementations
|
||||
return result
|
||||
|
||||
def _getDeps(self, target):
|
||||
depslist = self.rules[target][0]
|
||||
if type(depslist) is StringType:
|
||||
result = depslist.split()
|
||||
elif type(depslist) is FunctionType:
|
||||
result = depslist()
|
||||
elif type(depslist) is ListType:
|
||||
result = []
|
||||
for d in depslist:
|
||||
if type(d) is StringType:
|
||||
result.append(d)
|
||||
elif type(d) is FunctionType:
|
||||
result.append(d())
|
||||
else:
|
||||
Error("invalid rule: prereqs must be a string, list, or a function")
|
||||
for i in range(0, len(result)):
|
||||
result[i] = Path(result[i])
|
||||
return result
|
||||
|
||||
def _hasChanged(self, target, d):
|
||||
if not (target in self.newfingers):
|
||||
self.newfingers[target] = {}
|
||||
if Exists(d):
|
||||
n = self._hashFile(d)
|
||||
self.newfingers[target][d] = n
|
||||
if not (target in self.fingers): return True
|
||||
if not (d in self.fingers[target]): return True
|
||||
return n != self.fingers[target][d]
|
||||
else:
|
||||
Warn("'%s' does not exist!" % d)
|
||||
return True
|
||||
|
||||
def _makeAux(self, target, callstack={}):
|
||||
# returns "uptodate", "updated", "failed"
|
||||
UPTODATE = 1
|
||||
UPDATED = 2
|
||||
FAILED = 3
|
||||
|
||||
if target in callstack: return callstack[target]
|
||||
|
||||
def explain(msg):
|
||||
if 'explain' in self.options: _Info(msg)
|
||||
|
||||
if not (target in self.rules): return UPTODATE # target is up to date
|
||||
callstack[target] = UPTODATE # assume uptodate until proven otherwise
|
||||
result = UPTODATE
|
||||
|
||||
# retrieve the dependencies:
|
||||
deps = self._getDeps(target)
|
||||
for d in deps:
|
||||
if d[0] == '#':
|
||||
t = d[1:]
|
||||
if not (t in self.rules):
|
||||
Error("reference to unknown target '%s'" % t)
|
||||
# it is a target!
|
||||
#callstack[t] = # XXX: prevend endless recursion!
|
||||
res = self._makeAux(t, callstack)
|
||||
result = max(result, res)
|
||||
if res == UPDATED:
|
||||
explain("will build '%s' because '%s' modified since last build" %
|
||||
(target, d))
|
||||
elif res == FAILED:
|
||||
explain("cannot build '%s' because '%s' failed" %
|
||||
(target, d))
|
||||
elif self._hasChanged(target, d):
|
||||
explain("will build '%s' because '%s' modified since last build" %
|
||||
(target, d))
|
||||
result = max(result, UPDATED)
|
||||
if self.rules[target][2]: # check if output file exists:
|
||||
if not Exists(self.rules[target][2]):
|
||||
explain("will build '%s' because output file '%s' does not exist" %
|
||||
(target, self.rules[target][2]))
|
||||
result = max(result, UPDATED)
|
||||
|
||||
if result == UPTODATE and 'force' in self.options:
|
||||
explain("will build '%s' because forced" % target)
|
||||
result = max(result, UPDATED)
|
||||
|
||||
if result == UPDATED:
|
||||
_Info("building target '%s'" % target)
|
||||
buildRes = self._doRebuild(self.rules[target][1])
|
||||
if buildRes is None:
|
||||
Error("builder for target '%s' did not return an int" % target)
|
||||
result = FAILED
|
||||
elif buildRes != 0:
|
||||
result = FAILED
|
||||
elif result == UPTODATE:
|
||||
_Info("'%s' is up to date" % target)
|
||||
callstack[target] = result
|
||||
if result == UPDATED: # building was successful, so update fingerprints:
|
||||
if not (target in self.newfingers):
|
||||
# for phony targets this check is needed
|
||||
self.newfingers[target] = {}
|
||||
for m in self.rules[target][3]: # look for changed files
|
||||
self._hasChanged(target, m) # call for its side-effects
|
||||
self.fingers[target] = self.newfingers[target]
|
||||
return result
|
||||
|
||||
def make(self, target):
|
||||
self._makeAux(target)
|
||||
self._saveFingerprints(_FINGERPRINTS_FILE)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def SplitArg(s):
|
||||
if ':' in s: c = ':'
|
||||
elif '=' in s: c = '='
|
||||
else: return (s, '')
|
||||
i = s.find(c)
|
||||
return (s[:i], s[i+1:])
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def _writeUsage():
|
||||
print("Usage: koch.py [options] command/target [command/target...]\n"
|
||||
"Options:\n"
|
||||
" --force, -b, -f forces rebuilding\n"
|
||||
" --help, -h shows this help\n"
|
||||
" --explain, -e explain why a target is built\n"
|
||||
"Available targets:")
|
||||
for t in _importantTargets:
|
||||
print(" " + t[0] + " " * (23-len(t[0])) + t[1])
|
||||
if len(_commands) > 0:
|
||||
print("Available commands:")
|
||||
for k, v in _commands.iteritems():
|
||||
print(" " + k + " " * (23-len(k)) + v[0])
|
||||
sys.exit(2)
|
||||
|
||||
def Koch(defaultTarget):
|
||||
argv = sys.argv[1:]
|
||||
|
||||
options = {}
|
||||
i = 0
|
||||
# process general options:
|
||||
while i < len(argv):
|
||||
if argv[i][0] == '-':
|
||||
if argv[i] in ("-h", "--help"): _writeUsage()
|
||||
elif argv[i] in ("-b", "-B", "--force", "-f"): options['force'] = True
|
||||
elif argv[i] in ("--explain", "-e"): options['explain'] = True
|
||||
else: Error("invalid option: '%s'" % argv[i])
|
||||
else: break # BUGFIX
|
||||
i += 1
|
||||
|
||||
k = _Koch(options)
|
||||
|
||||
# process commands:
|
||||
i = 0
|
||||
while i < len(argv):
|
||||
if argv[i][0] != '-': # process target/command
|
||||
if argv[i] in _rules:
|
||||
k.make(argv[i])
|
||||
elif argv[i] in _commands:
|
||||
cmd = argv[i]
|
||||
n = _commands[cmd][2]
|
||||
args = []
|
||||
if n < 0: upperBound = len(argv)-1
|
||||
else: upperBound = i+n
|
||||
while i+1 <= upperBound:
|
||||
if i+1 >= len(argv):
|
||||
Error("command '%s' expects %d arguments" % (cmd, n))
|
||||
args.append(argv[i+1])
|
||||
i += 1
|
||||
if n < 0: _commands[cmd][1](args)
|
||||
else: _commands[cmd][1](*args)
|
||||
else:
|
||||
Error("Invalid target/command: " + argv[i])
|
||||
|
||||
i += 1
|
||||
if len(argv) == 0:
|
||||
k.make(defaultTarget)
|
||||
|
||||
if __name__ == "__main__":
|
||||
Error("You should execute the file 'koch.py' or consult\n"
|
||||
"the documentation to see how to build this software.")
|
||||
|
||||
|
||||
39
lib/amd64.asm.in
Executable file
39
lib/amd64.asm.in
Executable file
@@ -0,0 +1,39 @@
|
||||
; This contains the CPU-dependant variants of some routines.
|
||||
; (C) 2005 Andreas Rumpf
|
||||
; This code was inspired by the Freepascal compiler's sources
|
||||
; All routines here have the _cdecl calling convention because
|
||||
; that is the only convention any C compiler supports.
|
||||
|
||||
\python{
|
||||
# as usual I use my own preprocessor :-)
|
||||
import os
|
||||
|
||||
def c(name):
|
||||
if os.name == 'posix':
|
||||
return name
|
||||
else:
|
||||
return "_" + name
|
||||
|
||||
def arg:
|
||||
if os.name == 'posix':
|
||||
return 'rdi'
|
||||
else:
|
||||
return 'rcx' # on win64 uses its own calling convention; this sucks!
|
||||
}
|
||||
|
||||
segment code
|
||||
|
||||
global \c{cpu_inc_locked}
|
||||
global \c{cpu_dec_locked}
|
||||
|
||||
\c{cpu_dec_locked}:
|
||||
lock
|
||||
dec [\arg]
|
||||
setz al
|
||||
ret
|
||||
|
||||
\c{cpu_inc_locked}:
|
||||
lock
|
||||
inc [\arg]
|
||||
setz al
|
||||
ret
|
||||
84
lib/ansi_c.nim
Executable file
84
lib/ansi_c.nim
Executable file
@@ -0,0 +1,84 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# This include file contains headers of Ansi C procs
|
||||
# and definitions of Ansi C types in Nimrod syntax
|
||||
# All symbols are prefixed with 'c_' to avoid ambiguities
|
||||
|
||||
proc c_strcmp(a, b: CString): cint {.nodecl, importc: "strcmp".}
|
||||
proc c_memcmp(a, b: CString, size: cint): cint {.nodecl, importc: "memcmp".}
|
||||
proc c_memcpy(a, b: CString, size: cint) {.nodecl, importc: "memcpy".}
|
||||
proc c_strlen(a: CString): cint {.nodecl, importc: "strlen".}
|
||||
|
||||
type
|
||||
C_TextFile {.importc: "FILE", nodecl.} = record # empty record for
|
||||
# data hiding
|
||||
C_BinaryFile {.importc: "FILE", nodecl.} = record
|
||||
C_TextFileStar = ptr CTextFile
|
||||
C_BinaryFileStar = ptr CBinaryFile
|
||||
|
||||
C_JmpBuf {.importc: "jmp_buf".} = array[0..31, int]
|
||||
|
||||
var
|
||||
c_stdin {.importc: "stdin", noDecl.}: C_TextFileStar
|
||||
c_stdout {.importc: "stdout", noDecl.}: C_TextFileStar
|
||||
c_stderr {.importc: "stderr", noDecl.}: C_TextFileStar
|
||||
|
||||
var # constants faked as variables:
|
||||
SIGINT {.importc: "SIGINT", nodecl.}: cint
|
||||
SIGSEGV {.importc: "SIGSEGV", nodecl.}: cint
|
||||
SIGABRT {.importc: "SIGABRT", nodecl.}: cint
|
||||
SIGFPE {.importc: "SIGFPE", nodecl.}: cint
|
||||
SIGILL {.importc: "SIGILL", nodecl.}: cint
|
||||
|
||||
when defined(macosx):
|
||||
var
|
||||
SIGBUS {.importc: "SIGBUS", nodecl.}: cint
|
||||
# hopefully this does not lead to new bugs
|
||||
else:
|
||||
var
|
||||
SIGBUS {.importc: "SIGSEGV", nodecl.}: cint
|
||||
# only Mac OS X has this shit
|
||||
|
||||
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.nodecl, importc: "longjmp".}
|
||||
proc c_setjmp(jmpb: var C_JmpBuf) {.nodecl, importc: "setjmp".}
|
||||
|
||||
proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
|
||||
importc: "signal", header: "<signal.h>".}
|
||||
proc c_raise(sig: cint) {.importc: "raise", header: "<signal.h>".}
|
||||
|
||||
proc c_fputs(c: cstring, f: C_TextFileStar) {.importc: "fputs", noDecl.}
|
||||
proc c_fgets(c: cstring, n: int, f: C_TextFileStar): cstring {.
|
||||
importc: "fgets", noDecl.}
|
||||
proc c_fgetc(stream: C_TextFileStar): int {.importc: "fgetc", nodecl.}
|
||||
proc c_ungetc(c: int, f: C_TextFileStar) {.importc: "ungetc", nodecl.}
|
||||
proc c_putc(c: Char, stream: C_TextFileStar) {.importc: "putc", nodecl.}
|
||||
proc c_fprintf(f: C_TextFileStar, frmt: CString) {.
|
||||
importc: "fprintf", nodecl, varargs.}
|
||||
|
||||
proc c_fopen(filename, mode: cstring): C_TextFileStar {.
|
||||
importc: "fopen", nodecl.}
|
||||
proc c_fclose(f: C_TextFileStar) {.importc: "fclose", nodecl.}
|
||||
|
||||
proc c_sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs.}
|
||||
# we use it only in a way that cannot lead to security issues
|
||||
|
||||
proc c_fread(buf: Pointer, size, n: int, f: C_BinaryFileStar): int {.
|
||||
importc: "fread", noDecl.}
|
||||
proc c_fseek(f: C_BinaryFileStar, offset: clong, whence: int): int {.
|
||||
importc: "fseek", noDecl.}
|
||||
|
||||
proc c_fwrite(buf: Pointer, size, n: int, f: C_BinaryFileStar): int {.
|
||||
importc: "fwrite", noDecl.}
|
||||
|
||||
proc c_exit(errorcode: cint) {.importc: "exit", nodecl.}
|
||||
proc c_ferror(stream: C_TextFileStar): bool {.importc: "ferror", nodecl.}
|
||||
proc c_fflush(stream: C_TextFileStar) {.importc: "fflush", nodecl.}
|
||||
proc c_abort() {.importc: "abort", nodecl.}
|
||||
proc c_feof(stream: C_TextFileStar): bool {.importc: "feof", nodecl.}
|
||||
347
lib/arithm.nim
Executable file
347
lib/arithm.nim
Executable file
@@ -0,0 +1,347 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
# simple integer arithmetic with overflow checking
|
||||
|
||||
proc raiseOverflow {.exportc: "raiseOverflow".} =
|
||||
# a single proc to reduce code size to a minimum
|
||||
raise newException(EOverflow, "over- or underflow")
|
||||
|
||||
proc raiseDivByZero {.exportc: "raiseDivByZero".} =
|
||||
raise newException(EDivByZero, "divison by zero")
|
||||
|
||||
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
||||
result = a + b
|
||||
if (result xor a) >= int64(0) or (result xor b) >= int64(0):
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
proc subInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
||||
result = a - b
|
||||
if (result xor a) >= int64(0) or (result xor not b) >= int64(0):
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
proc negInt64(a: int64): int64 {.compilerProc, inline.} =
|
||||
if a != low(int64): return -a
|
||||
raiseOverflow()
|
||||
|
||||
proc absInt64(a: int64): int64 {.compilerProc, inline.} =
|
||||
if a != low(int64):
|
||||
if a >= 0: return a
|
||||
else: return -a
|
||||
raiseOverflow()
|
||||
|
||||
proc divInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
||||
if b == int64(0):
|
||||
raiseDivByZero()
|
||||
if a == low(int64) and b == int64(-1):
|
||||
raiseOverflow()
|
||||
return a div b
|
||||
|
||||
proc modInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
||||
if b == int64(0):
|
||||
raiseDivByZero()
|
||||
return a mod b
|
||||
|
||||
#
|
||||
# This code has been inspired by Python's source code.
|
||||
# The native int product x*y is either exactly right or *way* off, being
|
||||
# just the last n bits of the true product, where n is the number of bits
|
||||
# in an int (the delivered product is the true product plus i*2**n for
|
||||
# some integer i).
|
||||
#
|
||||
# The native float64 product x*y is subject to three
|
||||
# rounding errors: on a sizeof(int)==8 box, each cast to double can lose
|
||||
# info, and even on a sizeof(int)==4 box, the multiplication can lose info.
|
||||
# But, unlike the native int product, it's not in *range* trouble: even
|
||||
# if sizeof(int)==32 (256-bit ints), the product easily fits in the
|
||||
# dynamic range of a float64. So the leading 50 (or so) bits of the float64
|
||||
# product are correct.
|
||||
#
|
||||
# We check these two ways against each other, and declare victory if they're
|
||||
# approximately the same. Else, because the native int product is the only
|
||||
# one that can lose catastrophic amounts of information, it's the native int
|
||||
# product that must have overflowed.
|
||||
#
|
||||
proc mulInt64(a, b: int64): int64 {.compilerproc.} =
|
||||
var
|
||||
resAsFloat, floatProd: float64
|
||||
result = a * b
|
||||
floatProd = float64(a) # conversion
|
||||
floatProd = floatProd * float64(b)
|
||||
resAsFloat = float64(result)
|
||||
|
||||
# Fast path for normal case: small multiplicands, and no info
|
||||
# is lost in either method.
|
||||
if resAsFloat == floatProd: return result
|
||||
|
||||
# Somebody somewhere lost info. Close enough, or way off? Note
|
||||
# that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
|
||||
# The difference either is or isn't significant compared to the
|
||||
# true value (of which floatProd is a good approximation).
|
||||
|
||||
# abs(diff)/abs(prod) <= 1/32 iff
|
||||
# 32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
|
||||
if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
|
||||
proc absInt(a: int): int {.compilerProc, inline.} =
|
||||
if a != low(int):
|
||||
if a >= 0: return a
|
||||
else: return -a
|
||||
raiseOverflow()
|
||||
|
||||
when defined(I386) and (defined(vcc) or defined(wcc) or defined(dmc)):
|
||||
# or defined(gcc)):
|
||||
{.define: asmVersion.}
|
||||
# my Version of Borland C++Builder does not have
|
||||
# tasm32, which is needed for assembler blocks
|
||||
# this is why Borland is not included in the 'when'
|
||||
else:
|
||||
{.define: useInline.}
|
||||
|
||||
when defined(asmVersion) and defined(gcc):
|
||||
proc addInt(a, b: int): int {.compilerProc, pure, inline.}
|
||||
proc subInt(a, b: int): int {.compilerProc, pure, inline.}
|
||||
proc mulInt(a, b: int): int {.compilerProc, pure, inline.}
|
||||
proc divInt(a, b: int): int {.compilerProc, pure, inline.}
|
||||
proc modInt(a, b: int): int {.compilerProc, pure, inline.}
|
||||
proc negInt(a: int): int {.compilerProc, pure, inline.}
|
||||
|
||||
elif defined(asmVersion):
|
||||
proc addInt(a, b: int): int {.compilerProc, pure.}
|
||||
proc subInt(a, b: int): int {.compilerProc, pure.}
|
||||
proc mulInt(a, b: int): int {.compilerProc, pure.}
|
||||
proc divInt(a, b: int): int {.compilerProc, pure.}
|
||||
proc modInt(a, b: int): int {.compilerProc, pure.}
|
||||
proc negInt(a: int): int {.compilerProc, pure.}
|
||||
|
||||
elif defined(useInline):
|
||||
proc addInt(a, b: int): int {.compilerProc, inline.}
|
||||
proc subInt(a, b: int): int {.compilerProc, inline.}
|
||||
proc mulInt(a, b: int): int {.compilerProc.}
|
||||
# mulInt is to large for inlining?
|
||||
proc divInt(a, b: int): int {.compilerProc, inline.}
|
||||
proc modInt(a, b: int): int {.compilerProc, inline.}
|
||||
proc negInt(a: int): int {.compilerProc, inline.}
|
||||
|
||||
else:
|
||||
proc addInt(a, b: int): int {.compilerProc.}
|
||||
proc subInt(a, b: int): int {.compilerProc.}
|
||||
proc mulInt(a, b: int): int {.compilerProc.}
|
||||
proc divInt(a, b: int): int {.compilerProc.}
|
||||
proc modInt(a, b: int): int {.compilerProc.}
|
||||
proc negInt(a: int): int {.compilerProc.}
|
||||
|
||||
# implementation:
|
||||
|
||||
when defined(asmVersion) and not defined(gcc):
|
||||
# assembler optimized versions for compilers that
|
||||
# have an intel syntax assembler:
|
||||
proc addInt(a, b: int): int =
|
||||
# a in eax, and b in edx
|
||||
asm """
|
||||
mov eax, `a`
|
||||
add eax, `b`
|
||||
jno theEnd
|
||||
call raiseOverflow
|
||||
theEnd:
|
||||
"""
|
||||
|
||||
proc subInt(a, b: int): int =
|
||||
asm """
|
||||
mov eax, `a`
|
||||
sub eax, `b`
|
||||
jno theEnd
|
||||
call raiseOverflow
|
||||
theEnd:
|
||||
"""
|
||||
|
||||
proc negInt(a: int): int =
|
||||
asm """
|
||||
mov eax, `a`
|
||||
neg eax
|
||||
jno theEnd
|
||||
call raiseOverflow
|
||||
theEnd:
|
||||
"""
|
||||
|
||||
proc divInt(a, b: int): int =
|
||||
asm """
|
||||
mov eax, `a`
|
||||
mov ecx, `b`
|
||||
xor edx, edx
|
||||
idiv ecx
|
||||
jno theEnd
|
||||
call raiseOverflow
|
||||
theEnd:
|
||||
"""
|
||||
|
||||
proc modInt(a, b: int): int =
|
||||
asm """
|
||||
mov eax, `a`
|
||||
mov ecx, `b`
|
||||
xor edx, edx
|
||||
idiv ecx
|
||||
jno theEnd
|
||||
call raiseOverflow
|
||||
theEnd:
|
||||
mov eax, edx
|
||||
"""
|
||||
|
||||
proc mulInt(a, b: int): int =
|
||||
asm """
|
||||
mov eax, `a`
|
||||
mov ecx, `b`
|
||||
xor edx, edx
|
||||
imul ecx
|
||||
jno theEnd
|
||||
call raiseOverflow
|
||||
theEnd:
|
||||
"""
|
||||
|
||||
elif defined(asmVersion) and defined(gcc):
|
||||
proc addInt(a, b: int): int =
|
||||
asm """ "addl %1,%%eax\n"
|
||||
"jno 1\n"
|
||||
"call _raiseOverflow\n"
|
||||
"1: \n"
|
||||
:"=a"(`a`)
|
||||
:"a"(`a`), "r"(`b`)
|
||||
"""
|
||||
|
||||
proc subInt(a, b: int): int =
|
||||
asm """ "subl %1,%%eax\n"
|
||||
"jno 1\n"
|
||||
"call _raiseOverflow\n"
|
||||
"1: \n"
|
||||
:"=a"(`a`)
|
||||
:"a"(`a`), "r"(`b`)
|
||||
"""
|
||||
|
||||
proc negInt(a: int): int =
|
||||
asm """ "negl %%eax\n"
|
||||
"jno 1\n"
|
||||
"call _raiseOverflow\n"
|
||||
"1: \n"
|
||||
:"=a"(`a`)
|
||||
:"a"(`a`)
|
||||
"""
|
||||
|
||||
proc divInt(a, b: int): int =
|
||||
asm """ "xorl %%edx, %%edx\n"
|
||||
"idivl %%ecx\n"
|
||||
"jno 1\n"
|
||||
"call _raiseOverflow\n"
|
||||
"1: \n"
|
||||
:"=a"(`a`)
|
||||
:"a"(`a`), "c"(`b`)
|
||||
:"%edx"
|
||||
"""
|
||||
|
||||
proc modInt(a, b: int): int =
|
||||
asm """ "xorl %%edx, %%edx\n"
|
||||
"idivl %%ecx\n"
|
||||
"jno 1\n"
|
||||
"call _raiseOverflow\n"
|
||||
"1: \n"
|
||||
"movl %%edx, %%eax"
|
||||
:"=a"(`a`)
|
||||
:"a"(`a`), "c"(`b`)
|
||||
:"%edx"
|
||||
"""
|
||||
|
||||
proc mulInt(a, b: int): int =
|
||||
asm """ "xorl %%edx, %%edx\n"
|
||||
"imull %%ecx\n"
|
||||
"jno 1\n"
|
||||
"call _raiseOverflow\n"
|
||||
"1: \n"
|
||||
:"=a"(`a`)
|
||||
:"a"(`a`), "c"(`b`)
|
||||
:"%edx"
|
||||
"""
|
||||
|
||||
else:
|
||||
# Platform independant versions of the above (slower!)
|
||||
|
||||
proc addInt(a, b: int): int =
|
||||
result = a + b
|
||||
if (result xor a) >= 0 or (result xor b) >= 0:
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
proc subInt(a, b: int): int =
|
||||
result = a - b
|
||||
if (result xor a) >= 0 or (result xor not b) >= 0:
|
||||
return result
|
||||
raiseOverflow()
|
||||
|
||||
proc negInt(a: int): int =
|
||||
if a != low(int): return -a
|
||||
raiseOverflow()
|
||||
|
||||
proc divInt(a, b: int): int =
|
||||
if b == 0:
|
||||
raiseDivByZero()
|
||||
if a == low(int) and b == -1:
|
||||
raiseOverflow()
|
||||
return a div b
|
||||
|
||||
proc modInt(a, b: int): int =
|
||||
if b == 0:
|
||||
raiseDivByZero()
|
||||
return a mod b
|
||||
|
||||
#
|
||||
# This code has been inspired by Python's source code.
|
||||
# The native int product x*y is either exactly right or *way* off, being
|
||||
# just the last n bits of the true product, where n is the number of bits
|
||||
# in an int (the delivered product is the true product plus i*2**n for
|
||||
# some integer i).
|
||||
#
|
||||
# The native float64 product x*y is subject to three
|
||||
# rounding errors: on a sizeof(int)==8 box, each cast to double can lose
|
||||
# info, and even on a sizeof(int)==4 box, the multiplication can lose info.
|
||||
# But, unlike the native int product, it's not in *range* trouble: even
|
||||
# if sizeof(int)==32 (256-bit ints), the product easily fits in the
|
||||
# dynamic range of a float64. So the leading 50 (or so) bits of the float64
|
||||
# product are correct.
|
||||
#
|
||||
# We check these two ways against each other, and declare victory if
|
||||
# they're approximately the same. Else, because the native int product is
|
||||
# the only one that can lose catastrophic amounts of information, it's the
|
||||
# native int product that must have overflowed.
|
||||
#
|
||||
proc mulInt(a, b: int): int =
|
||||
var
|
||||
resAsFloat, floatProd: float
|
||||
|
||||
result = a * b
|
||||
floatProd = toFloat(a) * toFloat(b)
|
||||
resAsFloat = toFloat(result)
|
||||
|
||||
# Fast path for normal case: small multiplicands, and no info
|
||||
# is lost in either method.
|
||||
if resAsFloat == floatProd: return result
|
||||
|
||||
# Somebody somewhere lost info. Close enough, or way off? Note
|
||||
# that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
|
||||
# The difference either is or isn't significant compared to the
|
||||
# true value (of which floatProd is a good approximation).
|
||||
|
||||
# abs(diff)/abs(prod) <= 1/32 iff
|
||||
# 32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
|
||||
if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
|
||||
return result
|
||||
raiseOverflow()
|
||||
118
lib/assign.nim
Executable file
118
lib/assign.nim
Executable file
@@ -0,0 +1,118 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
#when defined(debugGC):
|
||||
# {.define: logAssign.}
|
||||
proc genericAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.}
|
||||
proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode) =
|
||||
var
|
||||
d = cast[TAddress](dest)
|
||||
s = cast[TAddress](src)
|
||||
case n.kind
|
||||
of nkNone: assert(false)
|
||||
of nkSlot:
|
||||
genericAssign(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
|
||||
n.typ)
|
||||
of nkList:
|
||||
for i in 0..n.len-1:
|
||||
genericAssignAux(dest, src, n.sons[i])
|
||||
of nkCase:
|
||||
copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
|
||||
n.typ.size)
|
||||
var m = selectBranch(src, n)
|
||||
if m != nil: genericAssignAux(dest, src, m)
|
||||
|
||||
proc genericAssign(dest, src: Pointer, mt: PNimType) =
|
||||
var
|
||||
d = cast[TAddress](dest)
|
||||
s = cast[TAddress](src)
|
||||
|
||||
assert(mt != nil)
|
||||
case mt.Kind
|
||||
of tySequence:
|
||||
var s2 = cast[ppointer](src)^
|
||||
var seq = cast[PGenericSeq](s2)
|
||||
if s2 == nil: # this can happen! nil sequences are allowed
|
||||
var x = cast[ppointer](dest)
|
||||
x^ = nil
|
||||
return
|
||||
assert(dest != nil)
|
||||
unsureAsgnRef(cast[ppointer](dest),
|
||||
newObj(mt, seq.len * mt.base.size + GenericSeqSize))
|
||||
var dst = cast[taddress](cast[ppointer](dest)^)
|
||||
for i in 0..seq.len-1:
|
||||
genericAssign(
|
||||
cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
|
||||
cast[pointer](cast[taddress](s2) +% i *% mt.base.size +%
|
||||
GenericSeqSize),
|
||||
mt.Base)
|
||||
var dstseq = cast[PGenericSeq](dst)
|
||||
dstseq.len = seq.len
|
||||
dstseq.space = seq.len
|
||||
of tyRecord, tyObject, tyTuple:
|
||||
genericAssignAux(dest, src, mt.node)
|
||||
of tyArray, tyArrayConstr:
|
||||
for i in 0..(mt.size div mt.base.size)-1:
|
||||
genericAssign(cast[pointer](d +% i*% mt.base.size),
|
||||
cast[pointer](s +% i*% mt.base.size), mt.base)
|
||||
of tyString: # a leaf
|
||||
var s2 = cast[ppointer](s)^
|
||||
if s2 != nil: # nil strings are possible!
|
||||
unsureAsgnRef(cast[ppointer](dest), copyString(cast[mstring](s2)))
|
||||
else:
|
||||
var x = cast[ppointer](dest)
|
||||
x^ = nil
|
||||
return
|
||||
of tyRef: # BUGFIX: a long time this has been forgotten!
|
||||
unsureAsgnRef(cast[ppointer](dest), cast[ppointer](s)^)
|
||||
else:
|
||||
copyMem(dest, src, mt.size) # copy raw bits
|
||||
|
||||
proc genericSeqAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
|
||||
genericAssign(dest, addr(src), mt)
|
||||
|
||||
proc genericAssignOpenArray(dest, src: pointer, len: int,
|
||||
mt: PNimType) {.compilerproc.} =
|
||||
var
|
||||
d = cast[TAddress](dest)
|
||||
s = cast[TAddress](src)
|
||||
for i in 0..len-1:
|
||||
genericAssign(cast[pointer](d +% i*% mt.base.size),
|
||||
cast[pointer](s +% i*% mt.base.size), mt.base)
|
||||
|
||||
proc objectInit(dest: Pointer, typ: PNimType) {.compilerProc.}
|
||||
proc objectInitAux(dest: Pointer, n: ptr TNimNode) =
|
||||
var d = cast[TAddress](dest)
|
||||
case n.kind
|
||||
of nkNone: assert(false)
|
||||
of nkSLot: objectInit(cast[pointer](d +% n.offset), n.typ)
|
||||
of nkList:
|
||||
for i in 0..n.len-1:
|
||||
objectInitAux(dest, n.sons[i])
|
||||
of nkCase:
|
||||
var m = selectBranch(dest, n)
|
||||
if m != nil: objectInitAux(dest, m)
|
||||
|
||||
proc objectInit(dest: Pointer, typ: PNimType) =
|
||||
# the generic init proc that takes care of initialization of complex
|
||||
# objects on the stack or heap
|
||||
var d = cast[TAddress](dest)
|
||||
case typ.kind
|
||||
of tyObject:
|
||||
# iterate over any structural type
|
||||
# here we have to init the type field:
|
||||
var pint = cast[ptr PNimType](dest)
|
||||
pint^ = typ
|
||||
objectInitAux(dest, typ.node)
|
||||
of tyRecord:
|
||||
objectInitAux(dest, typ.node)
|
||||
of tyArray, tyArrayConstr:
|
||||
for i in 0..(typ.size div typ.base.size)-1:
|
||||
objectInit(cast[pointer](d +% i * typ.base.size), typ.base)
|
||||
else: nil # nothing to do
|
||||
698
lib/base/cairo/cairo.nim
Normal file
698
lib/base/cairo/cairo.nim
Normal file
@@ -0,0 +1,698 @@
|
||||
|
||||
#* cairo - a vector graphics library with display and print output
|
||||
# *
|
||||
# * Copyright <20> 2002 University of Southern California
|
||||
# * Copyright <20> 2005 Red Hat, Inc.
|
||||
# *
|
||||
# * This library is free software; you can redistribute it and/or
|
||||
# * modify it either under the terms of the GNU Lesser General Public
|
||||
# * License version 2.1 as published by the Free Software Foundation
|
||||
# * (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
# * Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
# * notice, a recipient may use your version of this file under either
|
||||
# * the MPL or the LGPL.
|
||||
# *
|
||||
# * You should have received a copy of the LGPL along with this library
|
||||
# * in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
# * You should have received a copy of the MPL along with this library
|
||||
# * in the file COPYING-MPL-1.1
|
||||
# *
|
||||
# * The contents of this file are subject to the Mozilla Public License
|
||||
# * Version 1.1 (the "License"); you may not use this file except in
|
||||
# * compliance with the License. You may obtain a copy of the License at
|
||||
# * http://www.mozilla.org/MPL/
|
||||
# *
|
||||
# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
# * OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
# * the specific language governing rights and limitations.
|
||||
# *
|
||||
# * The Original Code is the cairo graphics library.
|
||||
# *
|
||||
# * The Initial Developer of the Original Code is University of Southern
|
||||
# * California.
|
||||
# *
|
||||
# * Contributor(s):
|
||||
# * Carl D. Worth <cworth@cworth.org>
|
||||
# #*
|
||||
# * This FreePascal binding generated August 26, 2005
|
||||
# * by Jeffrey Pohlmeyer <yetanothergeek@yahoo.com>
|
||||
#
|
||||
|
||||
#
|
||||
# - Updated to cairo version 1.4
|
||||
# - Grouped OS specific fuctions in separated units
|
||||
# - Organized the functions by group and ordered exactly as the c header
|
||||
# - Cleared parameter list syntax according to pascal standard
|
||||
#
|
||||
# By Luiz Am<41>rico Pereira C<>mara
|
||||
# October 2007
|
||||
#
|
||||
|
||||
when defined(windows):
|
||||
const
|
||||
LIB_CAIRO* = "cairo.dll"
|
||||
else:
|
||||
const
|
||||
LIB_CAIRO* = "libcairo.so"
|
||||
|
||||
type
|
||||
PByte = cstring
|
||||
cairo_status_t* = enum
|
||||
CAIRO_STATUS_SUCCESS = 0, CAIRO_STATUS_NO_MEMORY,
|
||||
CAIRO_STATUS_INVALID_RESTORE, CAIRO_STATUS_INVALID_POP_GROUP,
|
||||
CAIRO_STATUS_NO_CURRENT_POINT, CAIRO_STATUS_INVALID_MATRIX,
|
||||
CAIRO_STATUS_INVALID_STATUS, CAIRO_STATUS_NULL_POINTER,
|
||||
CAIRO_STATUS_INVALID_STRING, CAIRO_STATUS_INVALID_PATH_DATA,
|
||||
CAIRO_STATUS_READ_ERROR, CAIRO_STATUS_WRITE_ERROR,
|
||||
CAIRO_STATUS_SURFACE_FINISHED, CAIRO_STATUS_SURFACE_TYPE_MISMATCH,
|
||||
CAIRO_STATUS_PATTERN_TYPE_MISMATCH, CAIRO_STATUS_INVALID_CONTENT,
|
||||
CAIRO_STATUS_INVALID_FORMAT, CAIRO_STATUS_INVALID_VISUAL,
|
||||
CAIRO_STATUS_FILE_NOT_FOUND, CAIRO_STATUS_INVALID_DASH
|
||||
cairo_operator_t* = enum
|
||||
CAIRO_OPERATOR_CLEAR, CAIRO_OPERATOR_SOURCE, CAIRO_OPERATOR_OVER,
|
||||
CAIRO_OPERATOR_IN, CAIRO_OPERATOR_OUT, CAIRO_OPERATOR_ATOP,
|
||||
CAIRO_OPERATOR_DEST, CAIRO_OPERATOR_DEST_OVER, CAIRO_OPERATOR_DEST_IN,
|
||||
CAIRO_OPERATOR_DEST_OUT, CAIRO_OPERATOR_DEST_ATOP, CAIRO_OPERATOR_XOR,
|
||||
CAIRO_OPERATOR_ADD, CAIRO_OPERATOR_SATURATE
|
||||
cairo_antialias_t* = enum
|
||||
CAIRO_ANTIALIAS_DEFAULT, CAIRO_ANTIALIAS_NONE, CAIRO_ANTIALIAS_GRAY,
|
||||
CAIRO_ANTIALIAS_SUBPIXEL
|
||||
cairo_fill_rule_t* = enum
|
||||
CAIRO_FILL_RULE_WINDING, CAIRO_FILL_RULE_EVEN_ODD
|
||||
cairo_line_cap_t* = enum
|
||||
CAIRO_LINE_CAP_BUTT, CAIRO_LINE_CAP_ROUND, CAIRO_LINE_CAP_SQUARE
|
||||
cairo_line_join_t* = enum
|
||||
CAIRO_LINE_JOIN_MITER, CAIRO_LINE_JOIN_ROUND, CAIRO_LINE_JOIN_BEVEL
|
||||
cairo_font_slant_t* = enum
|
||||
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_SLANT_ITALIC, CAIRO_FONT_SLANT_OBLIQUE
|
||||
cairo_font_weight_t* = enum
|
||||
CAIRO_FONT_WEIGHT_NORMAL, CAIRO_FONT_WEIGHT_BOLD
|
||||
cairo_subpixel_order_t* = enum
|
||||
CAIRO_SUBPIXEL_ORDER_DEFAULT, CAIRO_SUBPIXEL_ORDER_RGB,
|
||||
CAIRO_SUBPIXEL_ORDER_BGR, CAIRO_SUBPIXEL_ORDER_VRGB,
|
||||
CAIRO_SUBPIXEL_ORDER_VBGR
|
||||
cairo_hint_style_t* = enum
|
||||
CAIRO_HINT_STYLE_DEFAULT, CAIRO_HINT_STYLE_NONE, CAIRO_HINT_STYLE_SLIGHT,
|
||||
CAIRO_HINT_STYLE_MEDIUM, CAIRO_HINT_STYLE_FULL
|
||||
cairo_hint_metrics_t* = enum
|
||||
CAIRO_HINT_METRICS_DEFAULT, CAIRO_HINT_METRICS_OFF, CAIRO_HINT_METRICS_ON
|
||||
cairo_path_data_type_t* = enum
|
||||
CAIRO_PATH_MOVE_TO, CAIRO_PATH_LINE_TO, CAIRO_PATH_CURVE_TO,
|
||||
CAIRO_PATH_CLOSE_PATH
|
||||
cairo_content_t* = enum
|
||||
CAIRO_CONTENT_COLOR = 0x00001000, CAIRO_CONTENT_ALPHA = 0x00002000,
|
||||
CAIRO_CONTENT_COLOR_ALPHA = 0x00003000
|
||||
cairo_format_t* = enum
|
||||
CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_RGB24, CAIRO_FORMAT_A8, CAIRO_FORMAT_A1
|
||||
cairo_extend_t* = enum
|
||||
CAIRO_EXTEND_NONE, CAIRO_EXTEND_REPEAT, CAIRO_EXTEND_REFLECT,
|
||||
CAIRO_EXTEND_PAD
|
||||
cairo_filter_t* = enum
|
||||
CAIRO_FILTER_FAST, CAIRO_FILTER_GOOD, CAIRO_FILTER_BEST,
|
||||
CAIRO_FILTER_NEAREST, CAIRO_FILTER_BILINEAR, CAIRO_FILTER_GAUSSIAN
|
||||
cairo_font_type_t* = enum
|
||||
CAIRO_FONT_TYPE_TOY, CAIRO_FONT_TYPE_FT, CAIRO_FONT_TYPE_WIN32,
|
||||
CAIRO_FONT_TYPE_ATSUI
|
||||
cairo_pattern_type_t* = enum
|
||||
CAIRO_PATTERN_TYPE_SOLID, CAIRO_PATTERN_TYPE_SURFACE,
|
||||
CAIRO_PATTERN_TYPE_LINEAR, CAIRO_PATTERN_TYPE_RADIAL
|
||||
cairo_surface_type_t* = enum
|
||||
CAIRO_SURFACE_TYPE_IMAGE, CAIRO_SURFACE_TYPE_PDF, CAIRO_SURFACE_TYPE_PS,
|
||||
CAIRO_SURFACE_TYPE_XLIB, CAIRO_SURFACE_TYPE_XCB, CAIRO_SURFACE_TYPE_GLITZ,
|
||||
CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_SURFACE_TYPE_WIN32,
|
||||
CAIRO_SURFACE_TYPE_BEOS, CAIRO_SURFACE_TYPE_DIRECTFB,
|
||||
CAIRO_SURFACE_TYPE_SVG, CAIRO_SURFACE_TYPE_OS2
|
||||
cairo_svg_version_t* = enum
|
||||
CAIRO_SVG_VERSION_1_1, CAIRO_SVG_VERSION_1_2
|
||||
Pcairo_surface_t* = ref cairo_surface_t
|
||||
PPcairo_surface_t* = ref Pcairo_surface_t
|
||||
Pcairo_t* = ref cairo_t
|
||||
Pcairo_pattern_t* = ref cairo_pattern_t
|
||||
Pcairo_font_options_t* = ref cairo_font_options_t
|
||||
Pcairo_font_face_t* = ref cairo_font_face_t
|
||||
Pcairo_scaled_font_t* = ref cairo_scaled_font_t
|
||||
Pcairo_bool_t* = ref cairo_bool_t
|
||||
cairo_bool_t* = int32
|
||||
Pcairo_matrix_t* = ref cairo_matrix_t
|
||||
Pcairo_user_data_key_t* = ref cairo_user_data_key_t
|
||||
Pcairo_glyph_t* = ref cairo_glyph_t
|
||||
Pcairo_text_extents_t* = ref cairo_text_extents_t
|
||||
Pcairo_font_extents_t* = ref cairo_font_extents_t
|
||||
Pcairo_path_data_type_t* = ref cairo_path_data_type_t
|
||||
Pcairo_path_data_t* = ref cairo_path_data_t
|
||||
Pcairo_path_t* = ref cairo_path_t
|
||||
Pcairo_rectangle_t* = ref cairo_rectangle_t
|
||||
Pcairo_rectangle_list_t* = ref cairo_rectangle_list_t
|
||||
cairo_destroy_func_t* = proc (data: Pointer){.cdecl.}
|
||||
cairo_write_func_t* = proc (closure: Pointer, data: PByte, len: int32): cairo_status_t{.
|
||||
cdecl.}
|
||||
cairo_read_func_t* = proc (closure: Pointer, data: PByte, len: int32): cairo_status_t{.
|
||||
cdecl.}
|
||||
cairo_t* = record #OPAQUE
|
||||
cairo_surface_t* = record #OPAQUE
|
||||
cairo_pattern_t* = record #OPAQUE
|
||||
cairo_scaled_font_t* = record #OPAQUE
|
||||
cairo_font_face_t* = record #OPAQUE
|
||||
cairo_font_options_t* = record #OPAQUE
|
||||
cairo_matrix_t* = record
|
||||
xx: float64
|
||||
yx: float64
|
||||
xy: float64
|
||||
yy: float64
|
||||
x0: float64
|
||||
y0: float64
|
||||
|
||||
cairo_user_data_key_t* = record
|
||||
unused: int32
|
||||
|
||||
cairo_glyph_t* = record
|
||||
index: int32
|
||||
x: float64
|
||||
y: float64
|
||||
|
||||
cairo_text_extents_t* = record
|
||||
x_bearing: float64
|
||||
y_bearing: float64
|
||||
width: float64
|
||||
height: float64
|
||||
x_advance: float64
|
||||
y_advance: float64
|
||||
|
||||
cairo_font_extents_t* = record
|
||||
ascent: float64
|
||||
descent: float64
|
||||
height: float64
|
||||
max_x_advance: float64
|
||||
max_y_advance: float64
|
||||
|
||||
cairo_path_data_t* = record #* _type : cairo_path_data_type_t;
|
||||
# length : LongInt;
|
||||
# end
|
||||
x: float64
|
||||
y: float64
|
||||
|
||||
cairo_path_t* = record
|
||||
status: cairo_status_t
|
||||
data: Pcairo_path_data_t
|
||||
num_data: int32
|
||||
|
||||
cairo_rectangle_t* = record
|
||||
x, y, width, height: float64
|
||||
|
||||
cairo_rectangle_list_t* = record
|
||||
status: cairo_status_t
|
||||
rectangles: Pcairo_rectangle_t
|
||||
num_rectangles: int32
|
||||
|
||||
|
||||
proc cairo_version*(): int32{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_version_string*(): cstring{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#Helper function to retrieve decoded version
|
||||
proc cairo_version*(major, minor, micro: var int32)
|
||||
#* Functions for manipulating state objects
|
||||
proc cairo_create*(target: Pcairo_surface_t): Pcairo_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_reference*(cr: Pcairo_t): Pcairo_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_destroy*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_reference_count*(cr: Pcairo_t): int32{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_user_data*(cr: Pcairo_t, key: Pcairo_user_data_key_t): pointer{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_user_data*(cr: PCairo_t, key: Pcairo_user_data_key_t,
|
||||
user_data: Pointer, destroy: cairo_destroy_func_t): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_save*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_restore*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_push_group*(cr: PCairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_push_group_with_content*(cr: PCairo_t, content: cairo_content_t){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pop_group*(cr: PCairo_t): Pcairo_pattern_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pop_group_to_source*(cr: PCairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* Modify state
|
||||
proc cairo_set_operator*(cr: Pcairo_t, op: cairo_operator_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_source*(cr: Pcairo_t, source: Pcairo_pattern_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_source_rgb*(cr: Pcairo_t, red, green, blue: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_source_rgba*(cr: Pcairo_t, red, green, blue, alpha: float64){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_source_surface*(cr: Pcairo_t, surface: Pcairo_surface_t,
|
||||
x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_tolerance*(cr: Pcairo_t, tolerance: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_antialias*(cr: Pcairo_t, antialias: cairo_antialias_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_fill_rule*(cr: Pcairo_t, fill_rule: cairo_fill_rule_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_line_width*(cr: Pcairo_t, width: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_line_cap*(cr: Pcairo_t, line_cap: cairo_line_cap_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_line_join*(cr: Pcairo_t, line_join: cairo_line_join_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_dash*(cr: Pcairo_t, dashes: openarray[float64],
|
||||
offset: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_miter_limit*(cr: Pcairo_t, limit: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_translate*(cr: Pcairo_t, tx, ty: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_scale*(cr: Pcairo_t, sx, sy: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_rotate*(cr: Pcairo_t, angle: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_transform*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_identity_matrix*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_user_to_device*(cr: Pcairo_t, x, y: var float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_user_to_device_distance*(cr: Pcairo_t, dx, dy: var float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_device_to_user*(cr: Pcairo_t, x, y: var float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_device_to_user_distance*(cr: Pcairo_t, dx, dy: var float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
#* Path creation functions
|
||||
proc cairo_new_path*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_move_to*(cr: Pcairo_t, x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_new_sub_path*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_line_to*(cr: Pcairo_t, x, y: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_curve_to*(cr: Pcairo_t, x1, y1, x2, y2, x3, y3: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_arc*(cr: Pcairo_t, xc, yc, radius, angle1, angle2: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_arc_negative*(cr: Pcairo_t, xc, yc, radius, angle1, angle2: float64){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_rel_move_to*(cr: Pcairo_t, dx, dy: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_rel_line_to*(cr: Pcairo_t, dx, dy: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_rel_curve_to*(cr: Pcairo_t, dx1, dy1, dx2, dy2, dx3, dy3: float64){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_rectangle*(cr: Pcairo_t, x, y, width, height: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_close_path*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* Painting functions
|
||||
proc cairo_paint*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_paint_with_alpha*(cr: Pcairo_t, alpha: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_mask*(cr: Pcairo_t, pattern: Pcairo_pattern_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_mask_surface*(cr: Pcairo_t, surface: Pcairo_surface_t,
|
||||
surface_x, surface_y: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_stroke*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_stroke_preserve*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_fill*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_fill_preserve*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_copy_page*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_show_page*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* Insideness testing
|
||||
proc cairo_in_stroke*(cr: Pcairo_t, x, y: float64): cairo_bool_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_in_fill*(cr: Pcairo_t, x, y: float64): cairo_bool_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
#* Rectangular extents
|
||||
proc cairo_stroke_extents*(cr: Pcairo_t, x1, y1, x2, y2: var float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_fill_extents*(cr: Pcairo_t, x1, y1, x2, y2: var float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
#* Clipping
|
||||
proc cairo_reset_clip*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_clip*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_clip_preserve*(cr: Pcairo_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_clip_extents*(cr: Pcairo_t, x1, y1, x2, y2: var float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_copy_clip_rectangle_list*(cr: Pcairo_t): Pcairo_rectangle_list_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_rectangle_list_destroy*(rectangle_list: Pcairo_rectangle_list_t){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* Font/Text functions
|
||||
proc cairo_font_options_create*(): Pcairo_font_options_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_copy*(original: Pcairo_font_options_t): Pcairo_font_options_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_destroy*(options: Pcairo_font_options_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_status*(options: Pcairo_font_options_t): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_merge*(options, other: Pcairo_font_options_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_equal*(options, other: Pcairo_font_options_t): cairo_bool_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_hash*(options: Pcairo_font_options_t): int32{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_set_antialias*(options: Pcairo_font_options_t,
|
||||
antialias: cairo_antialias_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_get_antialias*(options: Pcairo_font_options_t): cairo_antialias_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_set_subpixel_order*(options: Pcairo_font_options_t,
|
||||
subpixel_order: cairo_subpixel_order_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_get_subpixel_order*(options: Pcairo_font_options_t): cairo_subpixel_order_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_set_hint_style*(options: Pcairo_font_options_t,
|
||||
hint_style: cairo_hint_style_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_get_hint_style*(options: Pcairo_font_options_t): cairo_hint_style_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_set_hint_metrics*(options: Pcairo_font_options_t,
|
||||
hint_metrics: cairo_hint_metrics_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_options_get_hint_metrics*(options: Pcairo_font_options_t): cairo_hint_metrics_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* This interface is for dealing with text as text, not caring about the
|
||||
# font object inside the the cairo_t.
|
||||
proc cairo_select_font_face*(cr: Pcairo_t, family: cstring,
|
||||
slant: cairo_font_slant_t,
|
||||
weight: cairo_font_weight_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_font_size*(cr: Pcairo_t, size: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_font_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_font_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_font_options*(cr: Pcairo_t, options: Pcairo_font_options_t){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_font_options*(cr: Pcairo_t, options: Pcairo_font_options_t){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_font_face*(cr: Pcairo_t, font_face: Pcairo_font_face_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_font_face*(cr: Pcairo_t): Pcairo_font_face_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_set_scaled_font*(cr: PCairo_t, scaled_font: Pcairo_scaled_font_t){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_scaled_font*(cr: Pcairo_t): Pcairo_scaled_font_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_show_text*(cr: Pcairo_t, utf8: cstring){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_show_glyphs*(cr: Pcairo_t, glyphs: Pcairo_glyph_t, num_glyphs: int32){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_text_path*(cr: Pcairo_t, utf8: cstring){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_glyph_path*(cr: Pcairo_t, glyphs: Pcairo_glyph_t, num_glyphs: int32){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_text_extents*(cr: Pcairo_t, utf8: cstring,
|
||||
extents: Pcairo_text_extents_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_glyph_extents*(cr: Pcairo_t, glyphs: Pcairo_glyph_t,
|
||||
num_glyphs: int32, extents: Pcairo_text_extents_t){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_extents*(cr: Pcairo_t, extents: Pcairo_font_extents_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
#* Generic identifier for a font style
|
||||
proc cairo_font_face_reference*(font_face: Pcairo_font_face_t): Pcairo_font_face_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_face_destroy*(font_face: Pcairo_font_face_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_face_get_reference_count*(font_face: Pcairo_font_face_t): int32{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_face_status*(font_face: Pcairo_font_face_t): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_face_get_type*(font_face: Pcairo_font_face_t): cairo_font_type_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_face_get_user_data*(font_face: Pcairo_font_face_t,
|
||||
key: Pcairo_user_data_key_t): pointer{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_font_face_set_user_data*(font_face: Pcairo_font_face_t,
|
||||
key: Pcairo_user_data_key_t,
|
||||
user_data: pointer,
|
||||
destroy: cairo_destroy_func_t): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* Portable interface to general font features
|
||||
proc cairo_scaled_font_create*(font_face: Pcairo_font_face_t,
|
||||
font_matrix: Pcairo_matrix_t,
|
||||
ctm: Pcairo_matrix_t,
|
||||
options: Pcairo_font_options_t): Pcairo_scaled_font_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_reference*(scaled_font: Pcairo_scaled_font_t): Pcairo_scaled_font_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_destroy*(scaled_font: Pcairo_scaled_font_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_get_reference_count*(scaled_font: Pcairo_scaled_font_t): int32{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_status*(scaled_font: Pcairo_scaled_font_t): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_get_type*(scaled_font: Pcairo_scaled_font_t): cairo_font_type_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_get_user_data*(scaled_font: Pcairo_scaled_font_t,
|
||||
key: Pcairo_user_data_key_t): Pointer{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_set_user_data*(scaled_font: Pcairo_scaled_font_t,
|
||||
key: Pcairo_user_data_key_t,
|
||||
user_data: Pointer,
|
||||
destroy: cairo_destroy_func_t): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_extents*(scaled_font: Pcairo_scaled_font_t,
|
||||
extents: Pcairo_font_extents_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_text_extents*(scaled_font: Pcairo_scaled_font_t,
|
||||
utf8: cstring,
|
||||
extents: Pcairo_text_extents_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_glyph_extents*(scaled_font: Pcairo_scaled_font_t,
|
||||
glyphs: Pcairo_glyph_t, num_glyphs: int32,
|
||||
extents: Pcairo_text_extents_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_get_font_face*(scaled_font: Pcairo_scaled_font_t): Pcairo_font_face_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_get_font_matrix*(scaled_font: Pcairo_scaled_font_t,
|
||||
font_matrix: Pcairo_matrix_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_get_ctm*(scaled_font: Pcairo_scaled_font_t,
|
||||
ctm: Pcairo_matrix_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_scaled_font_get_font_options*(scaled_font: Pcairo_scaled_font_t,
|
||||
options: Pcairo_font_options_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* Query functions
|
||||
proc cairo_get_operator*(cr: Pcairo_t): cairo_operator_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_source*(cr: Pcairo_t): Pcairo_pattern_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_tolerance*(cr: Pcairo_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_antialias*(cr: Pcairo_t): cairo_antialias_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_current_point*(cr: Pcairo_t, x, y: var float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_fill_rule*(cr: Pcairo_t): cairo_fill_rule_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_line_width*(cr: Pcairo_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_line_cap*(cr: Pcairo_t): cairo_line_cap_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_line_join*(cr: Pcairo_t): cairo_line_join_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_miter_limit*(cr: Pcairo_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_dash_count*(cr: Pcairo_t): int32{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_dash*(cr: Pcairo_t, dashes, offset: var float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_matrix*(cr: Pcairo_t, matrix: Pcairo_matrix_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_target*(cr: Pcairo_t): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_get_group_target*(cr: Pcairo_t): Pcairo_surface_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_copy_path*(cr: Pcairo_t): Pcairo_path_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_copy_path_flat*(cr: Pcairo_t): Pcairo_path_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_append_path*(cr: Pcairo_t, path: Pcairo_path_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_path_destroy*(path: Pcairo_path_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* Error status queries
|
||||
proc cairo_status*(cr: Pcairo_t): cairo_status_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_status_to_string*(status: cairo_status_t): cstring{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
#* Surface manipulation
|
||||
proc cairo_surface_create_similar*(other: Pcairo_surface_t,
|
||||
content: cairo_content_t,
|
||||
width, height: int32): Pcairo_surface_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_reference*(surface: Pcairo_surface_t): Pcairo_surface_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_finish*(surface: Pcairo_surface_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_destroy*(surface: Pcairo_surface_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_get_reference_count*(surface: Pcairo_surface_t): int32{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_status*(surface: Pcairo_surface_t): cairo_status_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_get_type*(surface: Pcairo_surface_t): cairo_surface_type_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_get_content*(surface: Pcairo_surface_t): cairo_content_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_write_to_png*(surface: Pcairo_surface_t, filename: cstring): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_write_to_png_stream*(surface: Pcairo_surface_t,
|
||||
write_func: cairo_write_func_t,
|
||||
closure: pointer): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_get_user_data*(surface: Pcairo_surface_t,
|
||||
key: Pcairo_user_data_key_t): pointer{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_set_user_data*(surface: Pcairo_surface_t,
|
||||
key: Pcairo_user_data_key_t,
|
||||
user_data: pointer,
|
||||
destroy: cairo_destroy_func_t): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_get_font_options*(surface: Pcairo_surface_t,
|
||||
options: Pcairo_font_options_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_flush*(surface: Pcairo_surface_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_mark_dirty*(surface: Pcairo_surface_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_mark_dirty_rectangle*(surface: Pcairo_surface_t,
|
||||
x, y, width, height: int32){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_set_device_offset*(surface: Pcairo_surface_t,
|
||||
x_offset, y_offset: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_get_device_offset*(surface: Pcairo_surface_t,
|
||||
x_offset, y_offset: var float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_surface_set_fallback_resolution*(surface: Pcairo_surface_t,
|
||||
x_pixels_per_inch, y_pixels_per_inch: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* Image-surface functions
|
||||
proc cairo_image_surface_create*(format: cairo_format_t, width, height: int32): Pcairo_surface_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_image_surface_create_for_data*(data: Pbyte, format: cairo_format_t,
|
||||
width, height, stride: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_image_surface_get_data*(surface: Pcairo_surface_t): cstring{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_image_surface_get_format*(surface: Pcairo_surface_t): cairo_format_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_image_surface_get_width*(surface: Pcairo_surface_t): int32{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_image_surface_get_height*(surface: Pcairo_surface_t): int32{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_image_surface_get_stride*(surface: Pcairo_surface_t): int32{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_image_surface_create_from_png*(filename: cstring): Pcairo_surface_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_image_surface_create_from_png_stream*(read_func: cairo_read_func_t,
|
||||
closure: pointer): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* Pattern creation functions
|
||||
proc cairo_pattern_create_rgb*(red, green, blue: float64): Pcairo_pattern_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_create_rgba*(red, green, blue, alpha: float64): Pcairo_pattern_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_create_for_surface*(surface: Pcairo_surface_t): Pcairo_pattern_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_create_linear*(x0, y0, x1, y1: float64): Pcairo_pattern_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_create_radial*(cx0, cy0, radius0, cx1, cy1, radius1: float64): Pcairo_pattern_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_reference*(pattern: Pcairo_pattern_t): Pcairo_pattern_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_destroy*(pattern: Pcairo_pattern_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_get_reference_count*(pattern: Pcairo_pattern_t): int32{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_status*(pattern: Pcairo_pattern_t): cairo_status_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_get_user_data*(pattern: Pcairo_pattern_t,
|
||||
key: Pcairo_user_data_key_t): Pointer{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_set_user_data*(pattern: Pcairo_pattern_t,
|
||||
key: Pcairo_user_data_key_t,
|
||||
user_data: Pointer,
|
||||
destroy: cairo_destroy_func_t): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_get_type*(pattern: Pcairo_pattern_t): cairo_pattern_type_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_add_color_stop_rgb*(pattern: Pcairo_pattern_t,
|
||||
offset, red, green, blue: float64){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_add_color_stop_rgba*(pattern: Pcairo_pattern_t, offset, red,
|
||||
green, blue, alpha: float64){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_set_matrix*(pattern: Pcairo_pattern_t,
|
||||
matrix: Pcairo_matrix_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_get_matrix*(pattern: Pcairo_pattern_t,
|
||||
matrix: Pcairo_matrix_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_set_extend*(pattern: Pcairo_pattern_t, extend: cairo_extend_t){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_get_extend*(pattern: Pcairo_pattern_t): cairo_extend_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_set_filter*(pattern: Pcairo_pattern_t, filter: cairo_filter_t){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_get_filter*(pattern: Pcairo_pattern_t): cairo_filter_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_get_rgba*(pattern: Pcairo_pattern_t,
|
||||
red, green, blue, alpha: var float64): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_get_surface*(pattern: Pcairo_pattern_t,
|
||||
surface: PPcairo_surface_t): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_get_color_stop_rgba*(pattern: Pcairo_pattern_t, index: int32,
|
||||
offset, red, green, blue, alpha: var float64): cairo_status_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_get_color_stop_count*(pattern: Pcairo_pattern_t,
|
||||
count: var int32): cairo_status_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_get_linear_points*(pattern: Pcairo_pattern_t,
|
||||
x0, y0, x1, y1: var float64): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pattern_get_radial_circles*(pattern: Pcairo_pattern_t,
|
||||
x0, y0, r0, x1, y1, r1: var float64): cairo_status_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* Matrix functions
|
||||
proc cairo_matrix_init*(matrix: Pcairo_matrix_t, xx, yx, xy, yy, x0, y0: float64){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_matrix_init_identity*(matrix: Pcairo_matrix_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_matrix_init_translate*(matrix: Pcairo_matrix_t, tx, ty: float64){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_matrix_init_scale*(matrix: Pcairo_matrix_t, sx, sy: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_matrix_init_rotate*(matrix: Pcairo_matrix_t, radians: float64){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_matrix_translate*(matrix: Pcairo_matrix_t, tx, ty: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_matrix_scale*(matrix: Pcairo_matrix_t, sx, sy: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_matrix_rotate*(matrix: Pcairo_matrix_t, radians: float64){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_matrix_invert*(matrix: Pcairo_matrix_t): cairo_status_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_matrix_multiply*(result, a, b: Pcairo_matrix_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_matrix_transform_distance*(matrix: Pcairo_matrix_t, dx, dy: var float64){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_matrix_transform_point*(matrix: Pcairo_matrix_t, x, y: var float64){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* PDF functions
|
||||
proc cairo_pdf_surface_create*(filename: cstring,
|
||||
width_in_points, height_in_points: float64): Pcairo_surface_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pdf_surface_create_for_stream*(write_func: cairo_write_func_t,
|
||||
closure: Pointer, width_in_points, height_in_points: float64): Pcairo_surface_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_pdf_surface_set_size*(surface: Pcairo_surface_t,
|
||||
width_in_points, height_in_points: float64){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#* PS functions
|
||||
proc cairo_ps_surface_create*(filename: cstring,
|
||||
width_in_points, height_in_points: float64): Pcairo_surface_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_ps_surface_create_for_stream*(write_func: cairo_write_func_t,
|
||||
closure: Pointer, width_in_points, height_in_points: float64): Pcairo_surface_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_ps_surface_set_size*(surface: Pcairo_surface_t,
|
||||
width_in_points, height_in_points: float64){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_ps_surface_dsc_comment*(surface: Pcairo_surface_t, comment: cstring){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_ps_surface_dsc_begin_setup*(surface: Pcairo_surface_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_ps_surface_dsc_begin_page_setup*(surface: Pcairo_surface_t){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
#* SVG functions
|
||||
proc cairo_svg_surface_create*(filename: cstring,
|
||||
width_in_points, height_in_points: float64): Pcairo_surface_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_svg_surface_create_for_stream*(write_func: cairo_write_func_t,
|
||||
closure: Pointer, width_in_points, height_in_points: float64): Pcairo_surface_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_svg_surface_restrict_to_version*(surface: Pcairo_surface_t,
|
||||
version: cairo_svg_version_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
#todo: see how translate this
|
||||
#procedure cairo_svg_get_versions(cairo_svg_version_t const **versions,
|
||||
# int *num_versions);
|
||||
proc cairo_svg_version_to_string*(version: cairo_svg_version_t): cstring{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
#* Functions to be used while debugging (not intended for use in production code)
|
||||
proc cairo_debug_reset_static_data*(){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
# implementation
|
||||
|
||||
proc cairo_version(major, minor, micro: var int32) =
|
||||
var version: int32
|
||||
version = cairo_version()
|
||||
major = version div 10000
|
||||
minor = (version mod (major * 10000)) div 100
|
||||
micro = (version mod ((major * 10000) + (minor * 100)))
|
||||
36
lib/base/cairo/cairoft.nim
Normal file
36
lib/base/cairo/cairoft.nim
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# Translation of cairo-ft.h
|
||||
# by Jeffrey Pohlmeyer
|
||||
# updated to version 1.4 by Luiz Am<41>rico Pereira C<>mara 2007
|
||||
#
|
||||
|
||||
import Cairo, freetypeh
|
||||
|
||||
#todo: properly define FcPattern:
|
||||
#It will require translate FontConfig header
|
||||
|
||||
#*
|
||||
#typedef struct _XftPattern {
|
||||
# int num;
|
||||
# int size;
|
||||
# XftPatternElt *elts;
|
||||
# } XftPattern;
|
||||
# typedef FcPattern XftPattern;
|
||||
#
|
||||
|
||||
type
|
||||
FcPattern* = Pointer
|
||||
PFcPattern* = ref FcPattern
|
||||
|
||||
proc cairo_ft_font_face_create_for_pattern*(pattern: PFcPattern): Pcairo_font_face_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_ft_font_options_substitute*(options: Pcairo_font_options_t,
|
||||
pattern: PFcPattern){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_ft_font_face_create_for_ft_face*(face: TFT_Face,
|
||||
load_flags: int32): Pcairo_font_face_t {.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_ft_scaled_font_lock_face*(
|
||||
scaled_font: Pcairo_scaled_font_t): TFT_Face{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_ft_scaled_font_unlock_face*(
|
||||
scaled_font: Pcairo_scaled_font_t){.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
|
||||
36
lib/base/cairo/cairowin32.nim
Normal file
36
lib/base/cairo/cairowin32.nim
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
#
|
||||
# Translation of cairo-win32.h version 1.4
|
||||
# by Luiz Am<41>rico Pereira C<>mara 2007
|
||||
#
|
||||
|
||||
import
|
||||
Cairo, windows
|
||||
|
||||
proc cairo_win32_surface_create*(hdc: HDC): Pcairo_surface_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_win32_surface_create_with_ddb*(hdc: HDC, format: cairo_format_t,
|
||||
width, height: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_win32_surface_create_with_dib*(format: cairo_format_t,
|
||||
width, height: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_win32_surface_get_dc*(surface: pcairo_surface_t): HDC{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_win32_surface_get_image*(surface: pcairo_surface_t): Pcairo_surface_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_win32_font_face_create_for_logfontw*(logfont: pLOGFONTW): Pcairo_font_face_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_win32_font_face_create_for_hfont*(font: HFONT): Pcairo_font_face_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_win32_scaled_font_select_font*(scaled_font: pcairo_scaled_font_t,
|
||||
hdc: HDC): cairo_status_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_win32_scaled_font_done_font*(scaled_font: pcairo_scaled_font_t){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_win32_scaled_font_get_metrics_factor*(
|
||||
scaled_font: pcairo_scaled_font_t): float64{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_win32_scaled_font_get_logical_to_device*(
|
||||
scaled_font: pcairo_scaled_font_t, logical_to_device: pcairo_matrix_t){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_win32_scaled_font_get_device_to_logical*(
|
||||
scaled_font: pcairo_scaled_font_t, device_to_logical: pcairo_matrix_t){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
# implementation
|
||||
40
lib/base/cairo/cairoxlib.nim
Normal file
40
lib/base/cairo/cairoxlib.nim
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
#
|
||||
# Translation of cairo-xlib.h version 1.4
|
||||
# by Jeffrey Pohlmeyer
|
||||
# updated to version 1.4 by Luiz Am<41>rico Pereira C<>mara 2007
|
||||
#
|
||||
|
||||
import
|
||||
Cairo, x, xlib, xrender
|
||||
|
||||
proc cairo_xlib_surface_create*(dpy: PDisplay, drawable: TDrawable,
|
||||
visual: PVisual, width, height: int32): Pcairo_surface_t{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_xlib_surface_create_for_bitmap*(dpy: PDisplay, bitmap: TPixmap,
|
||||
screen: PScreen, width, height: int32): Pcairo_surface_t{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_xlib_surface_create_with_xrender_format*(dpy: PDisplay,
|
||||
drawable: TDrawable, screen: PScreen, format: PXRenderPictFormat,
|
||||
width, height: int32): Pcairo_surface_t{.cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_xlib_surface_get_depth*(surface: Pcairo_surface_t): int32{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_xlib_surface_get_display*(surface: Pcairo_surface_t): PDisplay{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_xlib_surface_get_drawable*(surface: Pcairo_surface_t): TDrawable{.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
proc cairo_xlib_surface_get_height*(surface: Pcairo_surface_t): int32{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_xlib_surface_get_screen*(surface: Pcairo_surface_t): PScreen{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_xlib_surface_get_visual*(surface: Pcairo_surface_t): PVisual{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_xlib_surface_get_width*(surface: Pcairo_surface_t): int32{.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_xlib_surface_set_size*(surface: Pcairo_surface_t,
|
||||
width, height: int32){.cdecl, importc,
|
||||
dynlib: LIB_CAIRO.}
|
||||
proc cairo_xlib_surface_set_drawable*(surface: Pcairo_surface_t,
|
||||
drawable: TDrawable, width, height: int32){.
|
||||
cdecl, importc, dynlib: LIB_CAIRO.}
|
||||
# implementation
|
||||
234
lib/base/dialogs.nim
Executable file
234
lib/base/dialogs.nim
Executable file
@@ -0,0 +1,234 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
## This module implements portable dialogs for Nimrod; the implementation
|
||||
## builds on the GTK interface. On Windows, native dialogs are shown if
|
||||
## appropriate.
|
||||
|
||||
import
|
||||
glib2, gtk2
|
||||
|
||||
when defined(Windows):
|
||||
import windows, ShellAPI, os
|
||||
|
||||
type
|
||||
PWindow* = PGtkWindow ## A shortcut for a GTK window.
|
||||
|
||||
proc info*(window: PWindow, msg: string) =
|
||||
## Shows an information message to the user. The process waits until the
|
||||
## user presses the OK button.
|
||||
when defined(Windows):
|
||||
discard MessageBoxA(0, msg, "Information", MB_OK or MB_ICONINFORMATION)
|
||||
else:
|
||||
var dialog = GTK_DIALOG(gtk_message_dialog_new(window,
|
||||
GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", cstring(msg)))
|
||||
gtk_window_set_title(dialog, "Information")
|
||||
discard gtk_dialog_run(dialog)
|
||||
gtk_widget_destroy(dialog)
|
||||
|
||||
proc warning*(window: PWindow, msg: string) =
|
||||
## Shows a warning message to the user. The process waits until the user
|
||||
## presses the OK button.
|
||||
when defined(Windows):
|
||||
discard MessageBoxA(0, msg, "Warning", MB_OK or MB_ICONWARNING)
|
||||
else:
|
||||
var dialog = GTK_DIALOG(gtk_message_dialog_new(window,
|
||||
GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "%s", cstring(msg)))
|
||||
gtk_window_set_title(dialog, "Warning")
|
||||
discard gtk_dialog_run(dialog)
|
||||
gtk_widget_destroy(dialog)
|
||||
|
||||
proc error*(window: PWindow, msg: string) =
|
||||
## Shows an error message to the user. The process waits until the user
|
||||
## presses the OK button.
|
||||
when defined(Windows):
|
||||
discard MessageBoxA(0, msg, "Error", MB_OK or MB_ICONERROR)
|
||||
else:
|
||||
var dialog = GTK_DIALOG(gtk_message_dialog_new(window,
|
||||
GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", cstring(msg)))
|
||||
gtk_window_set_title(dialog, "Error")
|
||||
discard gtk_dialog_run(dialog)
|
||||
gtk_widget_destroy(dialog)
|
||||
|
||||
|
||||
proc ChooseFileToOpen*(window: PWindow, root: string = ""): string =
|
||||
## Opens a dialog that requests a filename from the user. Returns ""
|
||||
## if the user closed the dialog without selecting a file. On Windows,
|
||||
## the native dialog is used, else the GTK dialog is used.
|
||||
when defined(Windows):
|
||||
var
|
||||
opf: TOPENFILENAME
|
||||
buf: array [0..2047, char]
|
||||
opf.lStructSize = sizeof(opf)
|
||||
if root.len > 0:
|
||||
opf.lpstrInitialDir = root
|
||||
opf.lpstrFilter = "All Files\0*.*\0\0"
|
||||
opf.flags = OFN_FILEMUSTEXIST
|
||||
opf.lpstrFile = buf
|
||||
opf.nMaxFile = sizeof(buf)
|
||||
var res = GetOpenFileName(addr(opf))
|
||||
if res != 0:
|
||||
result = $buf
|
||||
else:
|
||||
result = ""
|
||||
else:
|
||||
var
|
||||
chooser: PGtkDialog
|
||||
chooser = GTK_DIALOG(gtk_file_chooser_dialog_new("Open File", window,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
|
||||
if root.len > 0:
|
||||
discard gtk_file_chooser_set_current_folder(chooser, root)
|
||||
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
|
||||
var x = gtk_file_chooser_get_filename(chooser)
|
||||
result = $x
|
||||
g_free(x)
|
||||
else:
|
||||
result = ""
|
||||
gtk_widget_destroy(chooser)
|
||||
|
||||
proc ChooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] =
|
||||
## Opens a dialog that requests filenames from the user. Returns []
|
||||
## if the user closed the dialog without selecting a file. On Windows,
|
||||
## the native dialog is used, else the GTK dialog is used.
|
||||
when defined(Windows):
|
||||
var
|
||||
opf: TOPENFILENAME
|
||||
buf: array [0..2047*4, char]
|
||||
opf.lStructSize = sizeof(opf)
|
||||
if root.len > 0:
|
||||
opf.lpstrInitialDir = root
|
||||
opf.lpstrFilter = "All Files\0*.*\0\0"
|
||||
opf.flags = OFN_FILEMUSTEXIST or OFN_ALLOWMULTISELECT or OFN_EXPLORER
|
||||
opf.lpstrFile = buf
|
||||
opf.nMaxFile = sizeof(buf)
|
||||
var res = GetOpenFileName(addr(opf))
|
||||
result = []
|
||||
if res != 0:
|
||||
# parsing the result is horrible:
|
||||
var
|
||||
i = 0
|
||||
s: string
|
||||
path = ""
|
||||
while buf[i] != '\0':
|
||||
add(path, buf[i])
|
||||
inc(i)
|
||||
inc(i)
|
||||
if buf[i] != '\0':
|
||||
while true:
|
||||
s = ""
|
||||
while buf[i] != '\0':
|
||||
add(s, buf[i])
|
||||
inc(i)
|
||||
add(result, s)
|
||||
inc(i)
|
||||
if buf[i] == '\0': break
|
||||
for i in 0..result.len-1: result[i] = os.joinPath(path, result[i])
|
||||
else:
|
||||
var
|
||||
chooser: PGtkDialog
|
||||
chooser = GTK_DIALOG(gtk_file_chooser_dialog_new("Open Files", window,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
|
||||
if root.len > 0:
|
||||
discard gtk_file_chooser_set_current_folder(chooser, root)
|
||||
gtk_file_chooser_set_select_multiple(chooser, true)
|
||||
result = []
|
||||
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
|
||||
var L = gtk_file_chooser_get_filenames(chooser)
|
||||
var it = L
|
||||
while it != nil:
|
||||
add(result, $cast[cstring](it.data))
|
||||
g_free(it.data)
|
||||
it = it.next
|
||||
g_slist_free(L)
|
||||
gtk_widget_destroy(chooser)
|
||||
|
||||
|
||||
proc ChooseFileToSave*(window: PWindow, root: string = ""): string =
|
||||
## Opens a dialog that requests a filename to save to from the user.
|
||||
## Returns "" if the user closed the dialog without selecting a file.
|
||||
## On Windows, the native dialog is used, else the GTK dialog is used.
|
||||
when defined(Windows):
|
||||
var
|
||||
opf: TOPENFILENAME
|
||||
buf: array [0..2047, char]
|
||||
opf.lStructSize = sizeof(opf)
|
||||
if root.len > 0:
|
||||
opf.lpstrInitialDir = root
|
||||
opf.lpstrFilter = "All Files\0*.*\0\0"
|
||||
opf.flags = OFN_OVERWRITEPROMPT
|
||||
opf.lpstrFile = buf
|
||||
opf.nMaxFile = sizeof(buf)
|
||||
var res = GetSaveFileName(addr(opf))
|
||||
if res != 0:
|
||||
result = $buf
|
||||
else:
|
||||
result = ""
|
||||
else:
|
||||
var
|
||||
chooser: PGtkDialog
|
||||
chooser = GTK_DIALOG(gtk_file_chooser_dialog_new("Save File", window,
|
||||
GTK_FILE_CHOOSER_ACTION_SAVE,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
|
||||
if root.len > 0:
|
||||
discard gtk_file_chooser_set_current_folder(chooser, root)
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(chooser, true)
|
||||
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
|
||||
var x = gtk_file_chooser_get_filename(chooser)
|
||||
result = $x
|
||||
g_free(x)
|
||||
else:
|
||||
result = ""
|
||||
gtk_widget_destroy(chooser)
|
||||
|
||||
|
||||
proc ChooseDir*(window: PWindow, root: string = ""): string =
|
||||
## Opens a dialog that requests a directory from the user.
|
||||
## Returns "" if the user closed the dialog without selecting a directory.
|
||||
## On Windows, the native dialog is used, else the GTK dialog is used.
|
||||
when defined(Windows):
|
||||
var
|
||||
lpItemID: PItemIDList
|
||||
BrowseInfo: TBrowseInfo
|
||||
DisplayName: array [0..MAX_PATH, char]
|
||||
TempPath: array [0..MAX_PATH, char]
|
||||
Result = ""
|
||||
#BrowseInfo.hwndOwner = Application.Handle
|
||||
BrowseInfo.pszDisplayName = DisplayName
|
||||
BrowseInfo.ulFlags = 1 #BIF_RETURNONLYFSDIRS
|
||||
lpItemID = SHBrowseForFolder(cast[LPBrowseInfo](addr(BrowseInfo)))
|
||||
if lpItemId != nil:
|
||||
discard SHGetPathFromIDList(lpItemID, TempPath)
|
||||
Result = $TempPath
|
||||
discard GlobalFreePtr(lpItemID)
|
||||
else:
|
||||
var
|
||||
chooser: PGtkDialog
|
||||
chooser = GTK_DIALOG(gtk_file_chooser_dialog_new("Select Directory", window,
|
||||
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_OK, nil))
|
||||
if root.len > 0:
|
||||
discard gtk_file_chooser_set_current_folder(chooser, root)
|
||||
if gtk_dialog_run(chooser) == GTK_RESPONSE_OK:
|
||||
var x = gtk_file_chooser_get_filename(chooser)
|
||||
result = $x
|
||||
g_free(x)
|
||||
else:
|
||||
result = ""
|
||||
gtk_widget_destroy(chooser)
|
||||
|
||||
1368
lib/base/gtk/atk.nim
Executable file
1368
lib/base/gtk/atk.nim
Executable file
File diff suppressed because it is too large
Load Diff
3957
lib/base/gtk/gdk2.nim
Executable file
3957
lib/base/gtk/gdk2.nim
Executable file
File diff suppressed because it is too large
Load Diff
279
lib/base/gtk/gdk2pixbuf.nim
Executable file
279
lib/base/gtk/gdk2pixbuf.nim
Executable file
@@ -0,0 +1,279 @@
|
||||
import
|
||||
glib2
|
||||
|
||||
when defined(win32):
|
||||
{.define: gdkpixbufwin.}
|
||||
const
|
||||
gdkpixbuflib = "libgdk_pixbuf-2.0-0.dll"
|
||||
elif defined(darwin):
|
||||
const
|
||||
gdkpixbuflib = "gdk_pixbuf-2.0.0"
|
||||
# linklib gtk-x11-2.0
|
||||
# linklib gdk-x11-2.0
|
||||
# linklib pango-1.0.0
|
||||
# linklib glib-2.0.0
|
||||
# linklib gobject-2.0.0
|
||||
# linklib gdk_pixbuf-2.0.0
|
||||
# linklib atk-1.0.0
|
||||
else:
|
||||
const
|
||||
gdkpixbuflib = "libgdk_pixbuf-2.0.so"
|
||||
{.define: HasGTK2_4.}
|
||||
{.define: HasGTK2_6.}
|
||||
type
|
||||
PGdkPixbuf* = pointer
|
||||
PGdkPixbufAnimation* = pointer
|
||||
PGdkPixbufAnimationIter* = pointer
|
||||
PGdkPixbufAlphaMode* = ptr TGdkPixbufAlphaMode
|
||||
TGdkPixbufAlphaMode* = enum
|
||||
GDK_PIXBUF_ALPHA_BILEVEL, GDK_PIXBUF_ALPHA_FULL
|
||||
PGdkColorspace* = ptr TGdkColorspace
|
||||
TGdkColorspace* = enum
|
||||
GDK_COLORSPACE_RGB
|
||||
TGdkPixbufDestroyNotify* = proc (pixels: Pguchar, data: gpointer){.cdecl.}
|
||||
PGdkPixbufError* = ptr TGdkPixbufError
|
||||
TGdkPixbufError* = enum
|
||||
GDK_PIXBUF_ERROR_CORRUPT_IMAGE, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
|
||||
GDK_PIXBUF_ERROR_BAD_OPTION, GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
|
||||
GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION, GDK_PIXBUF_ERROR_FAILED
|
||||
PGdkInterpType* = ptr TGdkInterpType
|
||||
TGdkInterpType* = enum
|
||||
GDK_INTERP_NEAREST, GDK_INTERP_TILES, GDK_INTERP_BILINEAR, GDK_INTERP_HYPER
|
||||
|
||||
proc GDK_TYPE_PIXBUF*(): GType
|
||||
proc GDK_PIXBUF*(anObject: pointer): PGdkPixbuf
|
||||
proc GDK_IS_PIXBUF*(anObject: pointer): bool
|
||||
proc GDK_TYPE_PIXBUF_ANIMATION*(): GType
|
||||
proc GDK_PIXBUF_ANIMATION*(anObject: pointer): PGdkPixbufAnimation
|
||||
proc GDK_IS_PIXBUF_ANIMATION*(anObject: pointer): bool
|
||||
proc GDK_TYPE_PIXBUF_ANIMATION_ITER*(): GType
|
||||
proc GDK_PIXBUF_ANIMATION_ITER*(anObject: pointer): PGdkPixbufAnimationIter
|
||||
proc GDK_IS_PIXBUF_ANIMATION_ITER*(anObject: pointer): bool
|
||||
proc GDK_PIXBUF_ERROR*(): TGQuark
|
||||
proc gdk_pixbuf_error_quark*(): TGQuark{.cdecl, dynlib: gdkpixbuflib,
|
||||
importc: "gdk_pixbuf_error_quark".}
|
||||
proc gdk_pixbuf_get_type*(): GType{.cdecl, dynlib: gdkpixbuflib,
|
||||
importc: "gdk_pixbuf_get_type".}
|
||||
when not defined(GDK_PIXBUF_DISABLE_DEPRECATED):
|
||||
proc gdk_pixbuf_ref(pixbuf: PGdkPixbuf): PGdkPixbuf{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_ref".}
|
||||
proc gdk_pixbuf_unref(pixbuf: PGdkPixbuf){.cdecl, dynlib: gdkpixbuflib,
|
||||
importc: "gdk_pixbuf_unref".}
|
||||
proc gdk_pixbuf_get_colorspace*(pixbuf: PGdkPixbuf): TGdkColorspace{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_colorspace".}
|
||||
proc gdk_pixbuf_get_n_channels*(pixbuf: PGdkPixbuf): int32{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_n_channels".}
|
||||
proc gdk_pixbuf_get_has_alpha*(pixbuf: PGdkPixbuf): gboolean{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_has_alpha".}
|
||||
proc gdk_pixbuf_get_bits_per_sample*(pixbuf: PGdkPixbuf): int32{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_bits_per_sample".}
|
||||
proc gdk_pixbuf_get_pixels*(pixbuf: PGdkPixbuf): Pguchar{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_pixels".}
|
||||
proc gdk_pixbuf_get_width*(pixbuf: PGdkPixbuf): int32{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_width".}
|
||||
proc gdk_pixbuf_get_height*(pixbuf: PGdkPixbuf): int32{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_height".}
|
||||
proc gdk_pixbuf_get_rowstride*(pixbuf: PGdkPixbuf): int32{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_rowstride".}
|
||||
proc gdk_pixbuf_new*(colorspace: TGdkColorspace, has_alpha: gboolean,
|
||||
bits_per_sample: int32, width: int32, height: int32): PGdkPixbuf{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new".}
|
||||
proc gdk_pixbuf_copy*(pixbuf: PGdkPixbuf): PGdkPixbuf{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_copy".}
|
||||
proc gdk_pixbuf_new_subpixbuf*(src_pixbuf: PGdkPixbuf, src_x: int32,
|
||||
src_y: int32, width: int32, height: int32): PGdkPixbuf{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_subpixbuf".}
|
||||
proc gdk_pixbuf_new_from_file*(filename: cstring, error: pointer): PGdkPixbuf{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_file".}
|
||||
proc gdk_pixbuf_new_from_data*(data: Pguchar, colorspace: TGdkColorspace,
|
||||
has_alpha: gboolean, bits_per_sample: int32,
|
||||
width: int32, height: int32, rowstride: int32,
|
||||
destroy_fn: TGdkPixbufDestroyNotify,
|
||||
destroy_fn_data: gpointer): PGdkPixbuf{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_data".}
|
||||
proc gdk_pixbuf_new_from_xpm_data*(data: PPchar): PGdkPixbuf{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_xpm_data".}
|
||||
proc gdk_pixbuf_new_from_inline*(data_length: gint, a: var guint8,
|
||||
copy_pixels: gboolean, error: pointer): PGdkPixbuf{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_inline".}
|
||||
when defined(HasGTK2_4):
|
||||
proc gdk_pixbuf_new_from_file_at_size(filename: cstring, width, height: gint,
|
||||
error: pointer): PGdkPixbuf{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_file_at_size".}
|
||||
when defined(HasGTK2_6):
|
||||
proc gdk_pixbuf_new_from_file_at_scale(filename: cstring, width, height: gint,
|
||||
preserve_aspect_ratio: gboolean, error: pointer): PGdkPixbuf{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_new_from_file_at_scale".}
|
||||
proc gdk_pixbuf_fill*(pixbuf: PGdkPixbuf, pixel: guint32){.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_fill".}
|
||||
proc gdk_pixbuf_save*(pixbuf: PGdkPixbuf, filename: cstring, `type`: cstring,
|
||||
error: pointer): gboolean{.cdecl, varargs,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_save".}
|
||||
proc gdk_pixbuf_savev*(pixbuf: PGdkPixbuf, filename: cstring, `type`: cstring,
|
||||
option_keys: PPchar, option_values: PPchar,
|
||||
error: pointer): gboolean{.cdecl, dynlib: gdkpixbuflib,
|
||||
importc: "gdk_pixbuf_savev".}
|
||||
proc gdk_pixbuf_add_alpha*(pixbuf: PGdkPixbuf, substitute_color: gboolean,
|
||||
r: guchar, g: guchar, b: guchar): PGdkPixbuf{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_add_alpha".}
|
||||
proc gdk_pixbuf_copy_area*(src_pixbuf: PGdkPixbuf, src_x: int32, src_y: int32,
|
||||
width: int32, height: int32, dest_pixbuf: PGdkPixbuf,
|
||||
dest_x: int32, dest_y: int32){.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_copy_area".}
|
||||
proc gdk_pixbuf_saturate_and_pixelate*(src: PGdkPixbuf, dest: PGdkPixbuf,
|
||||
saturation: gfloat, pixelate: gboolean){.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_saturate_and_pixelate".}
|
||||
proc gdk_pixbuf_scale*(src: PGdkPixbuf, dest: PGdkPixbuf, dest_x: int32,
|
||||
dest_y: int32, dest_width: int32, dest_height: int32,
|
||||
offset_x: float64, offset_y: float64, scale_x: float64,
|
||||
scale_y: float64, interp_type: TGdkInterpType){.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_scale".}
|
||||
proc gdk_pixbuf_composite*(src: PGdkPixbuf, dest: PGdkPixbuf, dest_x: int32,
|
||||
dest_y: int32, dest_width: int32, dest_height: int32,
|
||||
offset_x: float64, offset_y: float64,
|
||||
scale_x: float64, scale_y: float64,
|
||||
interp_type: TGdkInterpType, overall_alpha: int32){.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_composite".}
|
||||
proc gdk_pixbuf_composite_color*(src: PGdkPixbuf, dest: PGdkPixbuf,
|
||||
dest_x: int32, dest_y: int32,
|
||||
dest_width: int32, dest_height: int32,
|
||||
offset_x: float64, offset_y: float64,
|
||||
scale_x: float64, scale_y: float64,
|
||||
interp_type: TGdkInterpType,
|
||||
overall_alpha: int32, check_x: int32,
|
||||
check_y: int32, check_size: int32,
|
||||
color1: guint32, color2: guint32){.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_composite_color".}
|
||||
proc gdk_pixbuf_scale_simple*(src: PGdkPixbuf, dest_width: int32,
|
||||
dest_height: int32, interp_type: TGdkInterpType): PGdkPixbuf{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_scale_simple".}
|
||||
proc gdk_pixbuf_composite_color_simple*(src: PGdkPixbuf, dest_width: int32,
|
||||
dest_height: int32,
|
||||
interp_type: TGdkInterpType,
|
||||
overall_alpha: int32, check_size: int32,
|
||||
color1: guint32, color2: guint32): PGdkPixbuf{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_composite_color_simple".}
|
||||
proc gdk_pixbuf_animation_get_type*(): GType{.cdecl, dynlib: gdkpixbuflib,
|
||||
importc: "gdk_pixbuf_animation_get_type".}
|
||||
proc gdk_pixbuf_animation_new_from_file*(filename: cstring, error: pointer): PGdkPixbufAnimation{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_new_from_file".}
|
||||
when not defined(GDK_PIXBUF_DISABLE_DEPRECATED):
|
||||
proc gdk_pixbuf_animation_ref(animation: PGdkPixbufAnimation): PGdkPixbufAnimation{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_ref".}
|
||||
proc gdk_pixbuf_animation_unref(animation: PGdkPixbufAnimation){.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_unref".}
|
||||
proc gdk_pixbuf_animation_get_width*(animation: PGdkPixbufAnimation): int32{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_get_width".}
|
||||
proc gdk_pixbuf_animation_get_height*(animation: PGdkPixbufAnimation): int32{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_get_height".}
|
||||
proc gdk_pixbuf_animation_is_static_image*(animation: PGdkPixbufAnimation): gboolean{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_is_static_image".}
|
||||
proc gdk_pixbuf_animation_get_static_image*(animation: PGdkPixbufAnimation): PGdkPixbuf{.
|
||||
cdecl, dynlib: gdkpixbuflib,
|
||||
importc: "gdk_pixbuf_animation_get_static_image".}
|
||||
proc gdk_pixbuf_animation_get_iter*(animation: PGdkPixbufAnimation,
|
||||
e: var TGTimeVal): PGdkPixbufAnimationIter{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_get_iter".}
|
||||
proc gdk_pixbuf_animation_iter_get_type*(): GType{.cdecl, dynlib: gdkpixbuflib,
|
||||
importc: "gdk_pixbuf_animation_iter_get_type".}
|
||||
proc gdk_pixbuf_animation_iter_get_delay_time*(iter: PGdkPixbufAnimationIter): int32{.
|
||||
cdecl, dynlib: gdkpixbuflib,
|
||||
importc: "gdk_pixbuf_animation_iter_get_delay_time".}
|
||||
proc gdk_pixbuf_animation_iter_get_pixbuf*(iter: PGdkPixbufAnimationIter): PGdkPixbuf{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_iter_get_pixbuf".}
|
||||
proc gdk_pixbuf_animation_iter_on_currently_loading_frame*(
|
||||
iter: PGdkPixbufAnimationIter): gboolean{.cdecl, dynlib: gdkpixbuflib,
|
||||
importc: "gdk_pixbuf_animation_iter_on_currently_loading_frame".}
|
||||
proc gdk_pixbuf_animation_iter_advance*(iter: PGdkPixbufAnimationIter,
|
||||
e: var TGTimeVal): gboolean{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_animation_iter_advance".}
|
||||
proc gdk_pixbuf_get_option*(pixbuf: PGdkPixbuf, key: cstring): cstring{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_get_option".}
|
||||
type
|
||||
PGdkPixbufLoader* = ptr TGdkPixbufLoader
|
||||
TGdkPixbufLoader* = record
|
||||
parent_instance*: TGObject
|
||||
priv*: gpointer
|
||||
|
||||
PGdkPixbufLoaderClass* = ptr TGdkPixbufLoaderClass
|
||||
TGdkPixbufLoaderClass* = record
|
||||
parent_class*: TGObjectClass
|
||||
area_prepared*: proc (loader: PGdkPixbufLoader){.cdecl.}
|
||||
area_updated*: proc (loader: PGdkPixbufLoader, x: int32, y: int32,
|
||||
width: int32, height: int32){.cdecl.}
|
||||
closed*: proc (loader: PGdkPixbufLoader){.cdecl.}
|
||||
|
||||
|
||||
proc GDK_TYPE_PIXBUF_LOADER*(): GType
|
||||
proc GDK_PIXBUF_LOADER*(obj: pointer): PGdkPixbufLoader
|
||||
proc GDK_PIXBUF_LOADER_CLASS*(klass: pointer): PGdkPixbufLoaderClass
|
||||
proc GDK_IS_PIXBUF_LOADER*(obj: pointer): bool
|
||||
proc GDK_IS_PIXBUF_LOADER_CLASS*(klass: pointer): bool
|
||||
proc GDK_PIXBUF_LOADER_GET_CLASS*(obj: pointer): PGdkPixbufLoaderClass
|
||||
proc gdk_pixbuf_loader_get_type*(): GType{.cdecl, dynlib: gdkpixbuflib,
|
||||
importc: "gdk_pixbuf_loader_get_type".}
|
||||
proc gdk_pixbuf_loader_new*(): PGdkPixbufLoader{.cdecl, dynlib: gdkpixbuflib,
|
||||
importc: "gdk_pixbuf_loader_new".}
|
||||
proc gdk_pixbuf_loader_new_with_type*(image_type: cstring, error: pointer): PGdkPixbufLoader{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_loader_new_with_type".}
|
||||
proc gdk_pixbuf_loader_write*(loader: PGdkPixbufLoader, buf: Pguchar,
|
||||
count: gsize, error: pointer): gboolean{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_loader_write".}
|
||||
proc gdk_pixbuf_loader_get_pixbuf*(loader: PGdkPixbufLoader): PGdkPixbuf{.cdecl,
|
||||
dynlib: gdkpixbuflib, importc: "gdk_pixbuf_loader_get_pixbuf".}
|
||||
proc gdk_pixbuf_loader_get_animation*(loader: PGdkPixbufLoader): PGdkPixbufAnimation{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_loader_get_animation".}
|
||||
proc gdk_pixbuf_loader_close*(loader: PGdkPixbufLoader, error: pointer): gboolean{.
|
||||
cdecl, dynlib: gdkpixbuflib, importc: "gdk_pixbuf_loader_close".}
|
||||
proc GDK_TYPE_PIXBUF_LOADER*(): GType =
|
||||
result = gdk_pixbuf_loader_get_type()
|
||||
|
||||
proc GDK_PIXBUF_LOADER*(obj: pointer): PGdkPixbufLoader =
|
||||
result = cast[PGdkPixbufLoader](G_TYPE_CHECK_INSTANCE_CAST(obj,
|
||||
GDK_TYPE_PIXBUF_LOADER()))
|
||||
|
||||
proc GDK_PIXBUF_LOADER_CLASS*(klass: pointer): PGdkPixbufLoaderClass =
|
||||
result = cast[PGdkPixbufLoaderClass](G_TYPE_CHECK_CLASS_CAST(klass,
|
||||
GDK_TYPE_PIXBUF_LOADER()))
|
||||
|
||||
proc GDK_IS_PIXBUF_LOADER*(obj: pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(obj, GDK_TYPE_PIXBUF_LOADER())
|
||||
|
||||
proc GDK_IS_PIXBUF_LOADER_CLASS*(klass: pointer): bool =
|
||||
result = G_TYPE_CHECK_CLASS_TYPE(klass, GDK_TYPE_PIXBUF_LOADER())
|
||||
|
||||
proc GDK_PIXBUF_LOADER_GET_CLASS*(obj: pointer): PGdkPixbufLoaderClass =
|
||||
result = cast[PGdkPixbufLoaderClass](G_TYPE_INSTANCE_GET_CLASS(obj,
|
||||
GDK_TYPE_PIXBUF_LOADER()))
|
||||
|
||||
proc GDK_TYPE_PIXBUF*(): GType =
|
||||
result = gdk_pixbuf_get_type()
|
||||
|
||||
proc GDK_PIXBUF*(anObject: pointer): PGdkPixbuf =
|
||||
result = cast[PGdkPixbuf](G_TYPE_CHECK_INSTANCE_CAST(anObject, GDK_TYPE_PIXBUF()))
|
||||
|
||||
proc GDK_IS_PIXBUF*(anObject: pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_PIXBUF())
|
||||
|
||||
proc GDK_TYPE_PIXBUF_ANIMATION*(): GType =
|
||||
result = gdk_pixbuf_animation_get_type()
|
||||
|
||||
proc GDK_PIXBUF_ANIMATION*(anObject: pointer): PGdkPixbufAnimation =
|
||||
result = cast[PGdkPixbufAnimation](G_TYPE_CHECK_INSTANCE_CAST(anObject,
|
||||
GDK_TYPE_PIXBUF_ANIMATION()))
|
||||
|
||||
proc GDK_IS_PIXBUF_ANIMATION*(anObject: pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_PIXBUF_ANIMATION())
|
||||
|
||||
proc GDK_TYPE_PIXBUF_ANIMATION_ITER*(): GType =
|
||||
result = gdk_pixbuf_animation_iter_get_type()
|
||||
|
||||
proc GDK_PIXBUF_ANIMATION_ITER*(anObject: pointer): PGdkPixbufAnimationIter =
|
||||
result = cast[PGdkPixbufAnimationIter](G_TYPE_CHECK_INSTANCE_CAST(anObject,
|
||||
GDK_TYPE_PIXBUF_ANIMATION_ITER()))
|
||||
|
||||
proc GDK_IS_PIXBUF_ANIMATION_ITER*(anObject: pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_PIXBUF_ANIMATION_ITER())
|
||||
|
||||
proc GDK_PIXBUF_ERROR*(): TGQuark =
|
||||
result = gdk_pixbuf_error_quark()
|
||||
562
lib/base/gtk/gdkglext.nim
Executable file
562
lib/base/gtk/gdkglext.nim
Executable file
@@ -0,0 +1,562 @@
|
||||
import
|
||||
Glib2, Gdk2
|
||||
|
||||
when defined(WIN32):
|
||||
const
|
||||
GdkGLExtLib = "libgdkglext-win32-1.0-0.dll"
|
||||
else:
|
||||
const
|
||||
GdkGLExtLib = "libgdkglext-x11-1.0.so"
|
||||
type
|
||||
TGdkGLConfigAttrib* = int32
|
||||
TGdkGLConfigCaveat* = int32
|
||||
TGdkGLVisualType* = int32
|
||||
TGdkGLTransparentType* = int32
|
||||
TGdkGLDrawableTypeMask* = int32
|
||||
TGdkGLRenderTypeMask* = int32
|
||||
TGdkGLBufferMask* = int32
|
||||
TGdkGLConfigError* = int32
|
||||
TGdkGLRenderType* = int32
|
||||
TGdkGLDrawableAttrib* = int32
|
||||
TGdkGLPbufferAttrib* = int32
|
||||
TGdkGLEventMask* = int32
|
||||
TGdkGLEventType* = int32
|
||||
TGdkGLDrawableType* = int32
|
||||
TGdkGLProc* = Pointer
|
||||
PGdkGLConfig* = ptr TGdkGLConfig
|
||||
PGdkGLContext* = ptr TGdkGLContext
|
||||
PGdkGLDrawable* = ptr TGdkGLDrawable
|
||||
PGdkGLPixmap* = ptr TGdkGLPixmap
|
||||
PGdkGLWindow* = ptr TGdkGLWindow
|
||||
TGdkGLConfig* = object of TGObject
|
||||
layer_plane*: gint
|
||||
n_aux_buffers*: gint
|
||||
n_sample_buffers*: gint
|
||||
flag0*: int16
|
||||
|
||||
PGdkGLConfigClass* = ptr TGdkGLConfigClass
|
||||
TGdkGLConfigClass* = object of TGObjectClass
|
||||
|
||||
TGdkGLContext* = object of TGObject
|
||||
|
||||
PGdkGLContextClass* = ptr TGdkGLContextClass
|
||||
TGdkGLContextClass* = object of TGObjectClass
|
||||
|
||||
TGdkGLDrawable* = object of TGObject
|
||||
|
||||
PGdkGLDrawableClass* = ptr TGdkGLDrawableClass
|
||||
TGdkGLDrawableClass* = object of TGTypeInterface
|
||||
create_new_context*: proc (gldrawable: PGdkGLDrawable,
|
||||
share_list: PGdkGLContext, direct: gboolean,
|
||||
render_type: int32): PGdkGLContext{.cdecl.}
|
||||
make_context_current*: proc (draw: PGdkGLDrawable, a_read: PGdkGLDrawable,
|
||||
glcontext: PGdkGLContext): gboolean{.cdecl.}
|
||||
is_double_buffered*: proc (gldrawable: PGdkGLDrawable): gboolean{.cdecl.}
|
||||
swap_buffers*: proc (gldrawable: PGdkGLDrawable){.cdecl.}
|
||||
wait_gl*: proc (gldrawable: PGdkGLDrawable){.cdecl.}
|
||||
wait_gdk*: proc (gldrawable: PGdkGLDrawable){.cdecl.}
|
||||
gl_begin*: proc (draw: PGdkGLDrawable, a_read: PGdkGLDrawable,
|
||||
glcontext: PGdkGLContext): gboolean{.cdecl.}
|
||||
gl_end*: proc (gldrawable: PGdkGLDrawable){.cdecl.}
|
||||
get_gl_config*: proc (gldrawable: PGdkGLDrawable): PGdkGLConfig{.cdecl.}
|
||||
get_size*: proc (gldrawable: PGdkGLDrawable, width, height: PGInt){.cdecl.}
|
||||
|
||||
TGdkGLPixmap* = object of TGObject
|
||||
drawable*: PGdkDrawable
|
||||
|
||||
PGdkGLPixmapClass* = ptr TGdkGLPixmapClass
|
||||
TGdkGLPixmapClass* = object of TGObjectClass
|
||||
|
||||
TGdkGLWindow* = object of TGObject
|
||||
drawable*: PGdkDrawable
|
||||
|
||||
PGdkGLWindowClass* = ptr TGdkGLWindowClass
|
||||
TGdkGLWindowClass* = object of TGObjectClass
|
||||
|
||||
|
||||
const
|
||||
HEADER_GDKGLEXT_MAJOR_VERSION* = 1
|
||||
HEADER_GDKGLEXT_MINOR_VERSION* = 0
|
||||
HEADER_GDKGLEXT_MICRO_VERSION* = 6
|
||||
HEADER_GDKGLEXT_INTERFACE_AGE* = 4
|
||||
HEADER_GDKGLEXT_BINARY_AGE* = 6
|
||||
|
||||
proc HEADER_GDKGLEXT_CHECK_VERSION*(major, minor, micro: guint): bool
|
||||
var
|
||||
gdkglext_major_version*{.importc, dynlib: GdkGLExtLib.}: guint
|
||||
gdkglext_minor_version*{.importc, dynlib: GdkGLExtLib.}: guint
|
||||
gdkglext_micro_version*{.importc, dynlib: GdkGLExtLib.}: guint
|
||||
gdkglext_interface_age*{.importc, dynlib: GdkGLExtLib.}: guint
|
||||
gdkglext_binary_age*{.importc, dynlib: GdkGLExtLib.}: guint
|
||||
|
||||
const
|
||||
GDK_GL_SUCCESS* = 0
|
||||
GDK_GL_ATTRIB_LIST_NONE* = 0
|
||||
GDK_GL_USE_GL* = 1
|
||||
GDK_GL_BUFFER_SIZE* = 2
|
||||
GDK_GL_LEVEL* = 3
|
||||
GDK_GL_RGBA* = 4
|
||||
GDK_GL_DOUBLEBUFFER* = 5
|
||||
GDK_GL_STEREO* = 6
|
||||
GDK_GL_AUX_BUFFERS* = 7
|
||||
GDK_GL_RED_SIZE* = 8
|
||||
GDK_GL_GREEN_SIZE* = 9
|
||||
GDK_GL_BLUE_SIZE* = 10
|
||||
GDK_GL_ALPHA_SIZE* = 11
|
||||
GDK_GL_DEPTH_SIZE* = 12
|
||||
GDK_GL_STENCIL_SIZE* = 13
|
||||
GDK_GL_ACCUM_RED_SIZE* = 14
|
||||
GDK_GL_ACCUM_GREEN_SIZE* = 15
|
||||
GDK_GL_ACCUM_BLUE_SIZE* = 16
|
||||
GDK_GL_ACCUM_ALPHA_SIZE* = 17
|
||||
GDK_GL_CONFIG_CAVEAT* = 0x00000020
|
||||
GDK_GL_X_VISUAL_TYPE* = 0x00000022
|
||||
GDK_GL_TRANSPARENT_TYPE* = 0x00000023
|
||||
GDK_GL_TRANSPARENT_INDEX_VALUE* = 0x00000024
|
||||
GDK_GL_TRANSPARENT_RED_VALUE* = 0x00000025
|
||||
GDK_GL_TRANSPARENT_GREEN_VALUE* = 0x00000026
|
||||
GDK_GL_TRANSPARENT_BLUE_VALUE* = 0x00000027
|
||||
GDK_GL_TRANSPARENT_ALPHA_VALUE* = 0x00000028
|
||||
GDK_GL_DRAWABLE_TYPE* = 0x00008010
|
||||
GDK_GL_RENDER_TYPE* = 0x00008011
|
||||
GDK_GL_X_RENDERABLE* = 0x00008012
|
||||
GDK_GL_FBCONFIG_ID* = 0x00008013
|
||||
GDK_GL_MAX_PBUFFER_WIDTH* = 0x00008016
|
||||
GDK_GL_MAX_PBUFFER_HEIGHT* = 0x00008017
|
||||
GDK_GL_MAX_PBUFFER_PIXELS* = 0x00008018
|
||||
GDK_GL_VISUAL_ID* = 0x0000800B
|
||||
GDK_GL_SCREEN* = 0x0000800C
|
||||
GDK_GL_SAMPLE_BUFFERS* = 100000
|
||||
GDK_GL_SAMPLES* = 100001
|
||||
GDK_GL_DONT_CARE* = 0xFFFFFFFF
|
||||
GDK_GL_NONE* = 0x00008000
|
||||
GDK_GL_CONFIG_CAVEAT_DONT_CARE* = 0xFFFFFFFF
|
||||
GDK_GL_CONFIG_CAVEAT_NONE* = 0x00008000
|
||||
GDK_GL_SLOW_CONFIG* = 0x00008001
|
||||
GDK_GL_NON_CONFORMANT_CONFIG* = 0x0000800D
|
||||
GDK_GL_VISUAL_TYPE_DONT_CARE* = 0xFFFFFFFF
|
||||
GDK_GL_TRUE_COLOR* = 0x00008002
|
||||
GDK_GL_DIRECT_COLOR* = 0x00008003
|
||||
GDK_GL_PSEUDO_COLOR* = 0x00008004
|
||||
GDK_GL_STATIC_COLOR* = 0x00008005
|
||||
GDK_GL_GRAY_SCALE* = 0x00008006
|
||||
GDK_GL_STATIC_GRAY* = 0x00008007
|
||||
GDK_GL_TRANSPARENT_NONE* = 0x00008000
|
||||
GDK_GL_TRANSPARENT_RGB* = 0x00008008
|
||||
GDK_GL_TRANSPARENT_INDEX* = 0x00008009
|
||||
GDK_GL_WINDOW_BIT* = 1 shl 0
|
||||
GDK_GL_PIXMAP_BIT* = 1 shl 1
|
||||
GDK_GL_PBUFFER_BIT* = 1 shl 2
|
||||
GDK_GL_RGBA_BIT* = 1 shl 0
|
||||
GDK_GL_COLOR_INDEX_BIT* = 1 shl 1
|
||||
GDK_GL_FRONT_LEFT_BUFFER_BIT* = 1 shl 0
|
||||
GDK_GL_FRONT_RIGHT_BUFFER_BIT* = 1 shl 1
|
||||
GDK_GL_BACK_LEFT_BUFFER_BIT* = 1 shl 2
|
||||
GDK_GL_BACK_RIGHT_BUFFER_BIT* = 1 shl 3
|
||||
GDK_GL_AUX_BUFFERS_BIT* = 1 shl 4
|
||||
GDK_GL_DEPTH_BUFFER_BIT* = 1 shl 5
|
||||
GDK_GL_STENCIL_BUFFER_BIT* = 1 shl 6
|
||||
GDK_GL_ACCUM_BUFFER_BIT* = 1 shl 7
|
||||
GDK_GL_BAD_SCREEN* = 1
|
||||
GDK_GL_BAD_ATTRIBUTE* = 2
|
||||
GDK_GL_NO_EXTENSION* = 3
|
||||
GDK_GL_BAD_VISUAL* = 4
|
||||
GDK_GL_BAD_CONTEXT* = 5
|
||||
GDK_GL_BAD_VALUE* = 6
|
||||
GDK_GL_BAD_ENUM* = 7
|
||||
GDK_GL_RGBA_TYPE* = 0x00008014
|
||||
GDK_GL_COLOR_INDEX_TYPE* = 0x00008015
|
||||
GDK_GL_PRESERVED_CONTENTS* = 0x0000801B
|
||||
GDK_GL_LARGEST_PBUFFER* = 0x0000801C
|
||||
GDK_GL_WIDTH* = 0x0000801D
|
||||
GDK_GL_HEIGHT* = 0x0000801E
|
||||
GDK_GL_EVENT_MASK* = 0x0000801F
|
||||
GDK_GL_PBUFFER_PRESERVED_CONTENTS* = 0x0000801B
|
||||
GDK_GL_PBUFFER_LARGEST_PBUFFER* = 0x0000801C
|
||||
GDK_GL_PBUFFER_HEIGHT* = 0x00008040
|
||||
GDK_GL_PBUFFER_WIDTH* = 0x00008041
|
||||
GDK_GL_PBUFFER_CLOBBER_MASK* = 1 shl 27
|
||||
GDK_GL_DAMAGED* = 0x00008020
|
||||
GDK_GL_SAVED* = 0x00008021
|
||||
GDK_GL_WINDOW_VALUE* = 0x00008022
|
||||
GDK_GL_PBUFFER* = 0x00008023
|
||||
|
||||
proc gdk_gl_config_attrib_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_config_attrib_get_type".}
|
||||
proc GDK_TYPE_GL_CONFIG_ATTRIB*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_config_attrib_get_type".}
|
||||
proc gdk_gl_config_caveat_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_config_caveat_get_type".}
|
||||
proc GDK_TYPE_GL_CONFIG_CAVEAT*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_config_caveat_get_type".}
|
||||
proc gdk_gl_visual_type_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_visual_type_get_type".}
|
||||
proc GDK_TYPE_GL_VISUAL_TYPE*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_visual_type_get_type".}
|
||||
proc gdk_gl_transparent_type_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_transparent_type_get_type".}
|
||||
proc GDK_TYPE_GL_TRANSPARENT_TYPE*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_transparent_type_get_type".}
|
||||
proc gdk_gl_drawable_type_mask_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_drawable_type_mask_get_type".}
|
||||
proc GDK_TYPE_GL_DRAWABLE_TYPE_MASK*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_drawable_type_mask_get_type".}
|
||||
proc gdk_gl_render_type_mask_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_render_type_mask_get_type".}
|
||||
proc GDK_TYPE_GL_RENDER_TYPE_MASK*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_render_type_mask_get_type".}
|
||||
proc gdk_gl_buffer_mask_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_buffer_mask_get_type".}
|
||||
proc GDK_TYPE_GL_BUFFER_MASK*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_buffer_mask_get_type".}
|
||||
proc gdk_gl_config_error_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_config_error_get_type".}
|
||||
proc GDK_TYPE_GL_CONFIG_ERROR*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_config_error_get_type".}
|
||||
proc gdk_gl_render_type_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_render_type_get_type".}
|
||||
proc GDK_TYPE_GL_RENDER_TYPE*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_render_type_get_type".}
|
||||
proc gdk_gl_drawable_attrib_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_drawable_attrib_get_type".}
|
||||
proc GDK_TYPE_GL_DRAWABLE_ATTRIB*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_drawable_attrib_get_type".}
|
||||
proc gdk_gl_pbuffer_attrib_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_pbuffer_attrib_get_type".}
|
||||
proc GDK_TYPE_GL_PBUFFER_ATTRIB*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_pbuffer_attrib_get_type".}
|
||||
proc gdk_gl_event_mask_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_event_mask_get_type".}
|
||||
proc GDK_TYPE_GL_EVENT_MASK*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_event_mask_get_type".}
|
||||
proc gdk_gl_event_type_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_event_type_get_type".}
|
||||
proc GDK_TYPE_GL_EVENT_TYPE*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_event_type_get_type".}
|
||||
proc gdk_gl_drawable_type_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_drawable_type_get_type".}
|
||||
proc GDK_TYPE_GL_DRAWABLE_TYPE*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_drawable_type_get_type".}
|
||||
proc gdk_gl_config_mode_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_config_mode_get_type".}
|
||||
proc GDK_TYPE_GL_CONFIG_MODE*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_config_mode_get_type".}
|
||||
proc gdk_gl_parse_args*(argc: var int32, argv: ptr cstringArray): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_parse_args".}
|
||||
proc gdk_gl_init_check*(argc: var int32, argv: ptr cstringArray): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_init_check".}
|
||||
proc gdk_gl_init*(argc: var int32, argv: ptr cstringArray){.
|
||||
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_init".}
|
||||
proc gdk_gl_query_gl_extension*(extension: cstring): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_query_gl_extension".}
|
||||
proc gdk_gl_get_proc_address*(proc_name: cstring): TGdkGLProc{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_get_proc_address".}
|
||||
const
|
||||
bm_TGdkGLConfig_is_rgba* = 1 shl 0
|
||||
bp_TGdkGLConfig_is_rgba* = 0
|
||||
bm_TGdkGLConfig_is_double_buffered* = 1 shl 1
|
||||
bp_TGdkGLConfig_is_double_buffered* = 1
|
||||
bm_TGdkGLConfig_as_single_mode* = 1 shl 2
|
||||
bp_TGdkGLConfig_as_single_mode* = 2
|
||||
bm_TGdkGLConfig_is_stereo* = 1 shl 3
|
||||
bp_TGdkGLConfig_is_stereo* = 3
|
||||
bm_TGdkGLConfig_has_alpha* = 1 shl 4
|
||||
bp_TGdkGLConfig_has_alpha* = 4
|
||||
bm_TGdkGLConfig_has_depth_buffer* = 1 shl 5
|
||||
bp_TGdkGLConfig_has_depth_buffer* = 5
|
||||
bm_TGdkGLConfig_has_stencil_buffer* = 1 shl 6
|
||||
bp_TGdkGLConfig_has_stencil_buffer* = 6
|
||||
bm_TGdkGLConfig_has_accum_buffer* = 1 shl 7
|
||||
bp_TGdkGLConfig_has_accum_buffer* = 7
|
||||
|
||||
const
|
||||
GDK_GL_MODE_RGB* = 0
|
||||
GDK_GL_MODE_RGBA* = 0
|
||||
GDK_GL_MODE_INDEX* = 1 shl 0
|
||||
GDK_GL_MODE_SINGLE* = 0
|
||||
GDK_GL_MODE_DOUBLE* = 1 shl 1
|
||||
GDK_GL_MODE_STEREO* = 1 shl 2
|
||||
GDK_GL_MODE_ALPHA* = 1 shl 3
|
||||
GDK_GL_MODE_DEPTH* = 1 shl 4
|
||||
GDK_GL_MODE_STENCIL* = 1 shl 5
|
||||
GDK_GL_MODE_ACCUM* = 1 shl 6
|
||||
GDK_GL_MODE_MULTISAMPLE* = 1 shl 7
|
||||
|
||||
type
|
||||
TGdkGLConfigMode* = int32
|
||||
PGdkGLConfigMode* = ptr TGdkGLConfigMode
|
||||
|
||||
proc GDK_TYPE_GL_CONFIG*(): GType
|
||||
proc GDK_GL_CONFIG*(anObject: Pointer): PGdkGLConfig
|
||||
proc GDK_GL_CONFIG_CLASS*(klass: Pointer): PGdkGLConfigClass
|
||||
proc GDK_IS_GL_CONFIG*(anObject: Pointer): bool
|
||||
proc GDK_IS_GL_CONFIG_CLASS*(klass: Pointer): bool
|
||||
proc GDK_GL_CONFIG_GET_CLASS*(obj: Pointer): PGdkGLConfigClass
|
||||
proc gdk_gl_config_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_config_get_type".}
|
||||
proc gdk_gl_config_get_screen*(glconfig: PGdkGLConfig): PGdkScreen{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_screen".}
|
||||
proc gdk_gl_config_get_attrib*(glconfig: PGdkGLConfig, attribute: int,
|
||||
value: var cint): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_attrib".}
|
||||
proc gdk_gl_config_get_colormap*(glconfig: PGdkGLConfig): PGdkColormap{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_colormap".}
|
||||
proc gdk_gl_config_get_visual*(glconfig: PGdkGLConfig): PGdkVisual{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_visual".}
|
||||
proc gdk_gl_config_get_depth*(glconfig: PGdkGLConfig): gint{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_depth".}
|
||||
proc gdk_gl_config_get_layer_plane*(glconfig: PGdkGLConfig): gint{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_layer_plane".}
|
||||
proc gdk_gl_config_get_n_aux_buffers*(glconfig: PGdkGLConfig): gint{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_n_aux_buffers".}
|
||||
proc gdk_gl_config_get_n_sample_buffers*(glconfig: PGdkGLConfig): gint{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_get_n_sample_buffers".}
|
||||
proc gdk_gl_config_is_rgba*(glconfig: PGdkGLConfig): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_is_rgba".}
|
||||
proc gdk_gl_config_is_double_buffered*(glconfig: PGdkGLConfig): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_is_double_buffered".}
|
||||
proc gdk_gl_config_is_stereo*(glconfig: PGdkGLConfig): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_is_stereo".}
|
||||
proc gdk_gl_config_has_alpha*(glconfig: PGdkGLConfig): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_has_alpha".}
|
||||
proc gdk_gl_config_has_depth_buffer*(glconfig: PGdkGLConfig): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_has_depth_buffer".}
|
||||
proc gdk_gl_config_has_stencil_buffer*(glconfig: PGdkGLConfig): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_has_stencil_buffer".}
|
||||
proc gdk_gl_config_has_accum_buffer*(glconfig: PGdkGLConfig): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_config_has_accum_buffer".}
|
||||
proc GDK_TYPE_GL_CONTEXT*(): GType
|
||||
proc GDK_GL_CONTEXT*(anObject: Pointer): PGdkGLContext
|
||||
proc GDK_GL_CONTEXT_CLASS*(klass: Pointer): PGdkGLContextClass
|
||||
proc GDK_IS_GL_CONTEXT*(anObject: Pointer): bool
|
||||
proc GDK_IS_GL_CONTEXT_CLASS*(klass: Pointer): bool
|
||||
proc GDK_GL_CONTEXT_GET_CLASS*(obj: Pointer): PGdkGLContextClass
|
||||
proc gdk_gl_context_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_context_get_type".}
|
||||
proc gdk_gl_context_new*(gldrawable: PGdkGLDrawable, share_list: PGdkGLContext,
|
||||
direct: gboolean, render_type: int32): PGdkGLContext{.
|
||||
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_context_new".}
|
||||
proc gdk_gl_context_destroy*(glcontext: PGdkGLContext){.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_context_destroy".}
|
||||
proc gdk_gl_context_copy*(glcontext: PGdkGLContext, src: PGdkGLContext,
|
||||
mask: int32): gboolean{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_context_copy".}
|
||||
proc gdk_gl_context_get_gl_drawable*(glcontext: PGdkGLContext): PGdkGLDrawable{.
|
||||
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_context_get_gl_drawable".}
|
||||
proc gdk_gl_context_get_gl_config*(glcontext: PGdkGLContext): PGdkGLConfig{.
|
||||
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_context_get_gl_config".}
|
||||
proc gdk_gl_context_get_share_list*(glcontext: PGdkGLContext): PGdkGLContext{.
|
||||
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_context_get_share_list".}
|
||||
proc gdk_gl_context_is_direct*(glcontext: PGdkGLContext): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_context_is_direct".}
|
||||
proc gdk_gl_context_get_render_type*(glcontext: PGdkGLContext): int32{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_context_get_render_type".}
|
||||
proc gdk_gl_context_get_current*(): PGdkGLContext{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_context_get_current".}
|
||||
proc GDK_TYPE_GL_DRAWABLE*(): GType
|
||||
proc GDK_GL_DRAWABLE*(inst: Pointer): PGdkGLDrawable
|
||||
proc GDK_GL_DRAWABLE_CLASS*(vtable: Pointer): PGdkGLDrawableClass
|
||||
proc GDK_IS_GL_DRAWABLE*(inst: Pointer): bool
|
||||
proc GDK_IS_GL_DRAWABLE_CLASS*(vtable: Pointer): bool
|
||||
proc GDK_GL_DRAWABLE_GET_CLASS*(inst: Pointer): PGdkGLDrawableClass
|
||||
proc gdk_gl_drawable_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_drawable_get_type".}
|
||||
proc gdk_gl_drawable_make_current*(gldrawable: PGdkGLDrawable,
|
||||
glcontext: PGdkGLContext): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_make_current".}
|
||||
proc gdk_gl_drawable_is_double_buffered*(gldrawable: PGdkGLDrawable): gboolean{.
|
||||
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_is_double_buffered".}
|
||||
proc gdk_gl_drawable_swap_buffers*(gldrawable: PGdkGLDrawable){.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_swap_buffers".}
|
||||
proc gdk_gl_drawable_wait_gl*(gldrawable: PGdkGLDrawable){.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_wait_gl".}
|
||||
proc gdk_gl_drawable_wait_gdk*(gldrawable: PGdkGLDrawable){.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_wait_gdk".}
|
||||
proc gdk_gl_drawable_gl_begin*(gldrawable: PGdkGLDrawable,
|
||||
glcontext: PGdkGLContext): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_gl_begin".}
|
||||
proc gdk_gl_drawable_gl_end*(gldrawable: PGdkGLDrawable){.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_gl_end".}
|
||||
proc gdk_gl_drawable_get_gl_config*(gldrawable: PGdkGLDrawable): PGdkGLConfig{.
|
||||
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_get_gl_config".}
|
||||
proc gdk_gl_drawable_get_size*(gldrawable: PGdkGLDrawable, width, height: PGInt){.
|
||||
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_drawable_get_size".}
|
||||
proc gdk_gl_drawable_get_current*(): PGdkGLDrawable{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_drawable_get_current".}
|
||||
proc GDK_TYPE_GL_PIXMAP*(): GType
|
||||
proc GDK_GL_PIXMAP*(anObject: Pointer): PGdkGLPixmap
|
||||
proc GDK_GL_PIXMAP_CLASS*(klass: Pointer): PGdkGLPixmapClass
|
||||
proc GDK_IS_GL_PIXMAP*(anObject: Pointer): bool
|
||||
proc GDK_IS_GL_PIXMAP_CLASS*(klass: Pointer): bool
|
||||
proc GDK_GL_PIXMAP_GET_CLASS*(obj: Pointer): PGdkGLPixmapClass
|
||||
proc gdk_gl_pixmap_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_pixmap_get_type".}
|
||||
proc gdk_gl_pixmap_new*(glconfig: PGdkGLConfig, pixmap: PGdkPixmap,
|
||||
attrib_list: ptr int32): PGdkGLPixmap{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_pixmap_new".}
|
||||
proc gdk_gl_pixmap_destroy*(glpixmap: PGdkGLPixmap){.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_pixmap_destroy".}
|
||||
proc gdk_gl_pixmap_get_pixmap*(glpixmap: PGdkGLPixmap): PGdkPixmap{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_pixmap_get_pixmap".}
|
||||
proc gdk_pixmap_set_gl_capability*(pixmap: PGdkPixmap, glconfig: PGdkGLConfig,
|
||||
attrib_list: ptr int32): PGdkGLPixmap{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_pixmap_set_gl_capability".}
|
||||
proc gdk_pixmap_unset_gl_capability*(pixmap: PGdkPixmap){.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_pixmap_unset_gl_capability".}
|
||||
proc gdk_pixmap_is_gl_capable*(pixmap: PGdkPixmap): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_pixmap_is_gl_capable".}
|
||||
proc gdk_pixmap_get_gl_pixmap*(pixmap: PGdkPixmap): PGdkGLPixmap{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_pixmap_get_gl_pixmap".}
|
||||
proc gdk_pixmap_get_gl_drawable*(pixmap: PGdkPixmap): PGdkGLDrawable
|
||||
proc GDK_TYPE_GL_WINDOW*(): GType
|
||||
proc GDK_GL_WINDOW*(anObject: Pointer): PGdkGLWindow
|
||||
proc GDK_GL_WINDOW_CLASS*(klass: Pointer): PGdkGLWindowClass
|
||||
proc GDK_IS_GL_WINDOW*(anObject: Pointer): bool
|
||||
proc GDK_IS_GL_WINDOW_CLASS*(klass: Pointer): bool
|
||||
proc GDK_GL_WINDOW_GET_CLASS*(obj: Pointer): PGdkGLWindowClass
|
||||
proc gdk_gl_window_get_type*(): GType{.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_window_get_type".}
|
||||
proc gdk_gl_window_new*(glconfig: PGdkGLConfig, window: PGdkWindow,
|
||||
attrib_list: ptr int32): PGdkGLWindow{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_window_new".}
|
||||
proc gdk_gl_window_destroy*(glwindow: PGdkGLWindow){.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_window_destroy".}
|
||||
proc gdk_gl_window_get_window*(glwindow: PGdkGLWindow): PGdkWindow{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_window_get_window".}
|
||||
proc gdk_window_set_gl_capability*(window: PGdkWindow, glconfig: PGdkGLConfig,
|
||||
attrib_list: ptr int32): PGdkGLWindow{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_window_set_gl_capability".}
|
||||
proc gdk_window_unset_gl_capability*(window: PGdkWindow){.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_window_unset_gl_capability".}
|
||||
proc gdk_window_is_gl_capable*(window: PGdkWindow): gboolean{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_window_is_gl_capable".}
|
||||
proc gdk_window_get_gl_window*(window: PGdkWindow): PGdkGLWindow{.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_window_get_gl_window".}
|
||||
proc gdk_window_get_gl_drawable*(window: PGdkWindow): PGdkGLDrawable
|
||||
proc gdk_gl_draw_cube*(solid: gboolean, size: float64){.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_draw_cube".}
|
||||
proc gdk_gl_draw_sphere*(solid: gboolean, radius: float64, slices: int32,
|
||||
stacks: int32){.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_draw_sphere".}
|
||||
proc gdk_gl_draw_cone*(solid: gboolean, base: float64, height: float64,
|
||||
slices: int32, stacks: int32){.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_draw_cone".}
|
||||
proc gdk_gl_draw_torus*(solid: gboolean, inner_radius: float64,
|
||||
outer_radius: float64, nsides: int32, rings: int32){.
|
||||
cdecl, dynlib: GdkGLExtLib, importc: "gdk_gl_draw_torus".}
|
||||
proc gdk_gl_draw_tetrahedron*(solid: gboolean){.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_draw_tetrahedron".}
|
||||
proc gdk_gl_draw_octahedron*(solid: gboolean){.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_draw_octahedron".}
|
||||
proc gdk_gl_draw_dodecahedron*(solid: gboolean){.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_draw_dodecahedron".}
|
||||
proc gdk_gl_draw_icosahedron*(solid: gboolean){.cdecl, dynlib: GdkGLExtLib,
|
||||
importc: "gdk_gl_draw_icosahedron".}
|
||||
proc gdk_gl_draw_teapot*(solid: gboolean, scale: float64){.cdecl,
|
||||
dynlib: GdkGLExtLib, importc: "gdk_gl_draw_teapot".}
|
||||
proc HEADER_GDKGLEXT_CHECK_VERSION*(major, minor, micro: guint): bool =
|
||||
result = (HEADER_GDKGLEXT_MAJOR_VERSION > major) or
|
||||
((HEADER_GDKGLEXT_MAJOR_VERSION == major) and
|
||||
(HEADER_GDKGLEXT_MINOR_VERSION > minor)) or
|
||||
((HEADER_GDKGLEXT_MAJOR_VERSION == major) and
|
||||
(HEADER_GDKGLEXT_MINOR_VERSION == minor) and
|
||||
(HEADER_GDKGLEXT_MICRO_VERSION >= micro))
|
||||
|
||||
proc GDK_TYPE_GL_CONFIG*(): GType =
|
||||
result = gdk_gl_config_get_type()
|
||||
|
||||
proc GDK_GL_CONFIG*(anObject: Pointer): PGdkGLConfig =
|
||||
result = cast[PGdkGLConfig](G_TYPE_CHECK_INSTANCE_CAST(anObject, GDK_TYPE_GL_CONFIG()))
|
||||
|
||||
proc GDK_GL_CONFIG_CLASS*(klass: Pointer): PGdkGLConfigClass =
|
||||
result = cast[PGdkGLConfigClass](G_TYPE_CHECK_CLASS_CAST(klass, GDK_TYPE_GL_CONFIG()))
|
||||
|
||||
proc GDK_IS_GL_CONFIG*(anObject: Pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_GL_CONFIG())
|
||||
|
||||
proc GDK_IS_GL_CONFIG_CLASS*(klass: Pointer): bool =
|
||||
result = G_TYPE_CHECK_CLASS_TYPE(klass, GDK_TYPE_GL_CONFIG())
|
||||
|
||||
proc GDK_GL_CONFIG_GET_CLASS*(obj: Pointer): PGdkGLConfigClass =
|
||||
result = cast[PGdkGLConfigClass](G_TYPE_INSTANCE_GET_CLASS(obj, GDK_TYPE_GL_CONFIG()))
|
||||
|
||||
proc GDK_TYPE_GL_CONTEXT*(): GType =
|
||||
result = gdk_gl_context_get_type()
|
||||
|
||||
proc GDK_GL_CONTEXT*(anObject: Pointer): PGdkGLContext =
|
||||
result = cast[PGdkGLContext](G_TYPE_CHECK_INSTANCE_CAST(anObject,
|
||||
GDK_TYPE_GL_CONTEXT()))
|
||||
|
||||
proc GDK_GL_CONTEXT_CLASS*(klass: Pointer): PGdkGLContextClass =
|
||||
result = cast[PGdkGLContextClass](G_TYPE_CHECK_CLASS_CAST(klass, GDK_TYPE_GL_CONTEXT()))
|
||||
|
||||
proc GDK_IS_GL_CONTEXT*(anObject: Pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_GL_CONTEXT())
|
||||
|
||||
proc GDK_IS_GL_CONTEXT_CLASS*(klass: Pointer): bool =
|
||||
result = G_TYPE_CHECK_CLASS_TYPE(klass, GDK_TYPE_GL_CONTEXT())
|
||||
|
||||
proc GDK_GL_CONTEXT_GET_CLASS*(obj: Pointer): PGdkGLContextClass =
|
||||
result = cast[PGdkGLContextClass](G_TYPE_INSTANCE_GET_CLASS(obj, GDK_TYPE_GL_CONTEXT()))
|
||||
|
||||
proc GDK_TYPE_GL_DRAWABLE*(): GType =
|
||||
result = gdk_gl_drawable_get_type()
|
||||
|
||||
proc GDK_GL_DRAWABLE*(inst: Pointer): PGdkGLDrawable =
|
||||
result = cast[PGdkGLDrawable](G_TYPE_CHECK_INSTANCE_CAST(inst, GDK_TYPE_GL_DRAWABLE()))
|
||||
|
||||
proc GDK_GL_DRAWABLE_CLASS*(vtable: Pointer): PGdkGLDrawableClass =
|
||||
result = cast[PGdkGLDrawableClass](G_TYPE_CHECK_CLASS_CAST(vtable,
|
||||
GDK_TYPE_GL_DRAWABLE()))
|
||||
|
||||
proc GDK_IS_GL_DRAWABLE*(inst: Pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(inst, GDK_TYPE_GL_DRAWABLE())
|
||||
|
||||
proc GDK_IS_GL_DRAWABLE_CLASS*(vtable: Pointer): bool =
|
||||
result = G_TYPE_CHECK_CLASS_TYPE(vtable, GDK_TYPE_GL_DRAWABLE())
|
||||
|
||||
proc GDK_GL_DRAWABLE_GET_CLASS*(inst: Pointer): PGdkGLDrawableClass =
|
||||
result = cast[PGdkGLDrawableClass](G_TYPE_INSTANCE_GET_INTERFACE(inst,
|
||||
GDK_TYPE_GL_DRAWABLE()))
|
||||
|
||||
proc GDK_TYPE_GL_PIXMAP*(): GType =
|
||||
result = gdk_gl_pixmap_get_type()
|
||||
|
||||
proc GDK_GL_PIXMAP*(anObject: Pointer): PGdkGLPixmap =
|
||||
result = cast[PGdkGLPixmap](G_TYPE_CHECK_INSTANCE_CAST(anObject, GDK_TYPE_GL_PIXMAP()))
|
||||
|
||||
proc GDK_GL_PIXMAP_CLASS*(klass: Pointer): PGdkGLPixmapClass =
|
||||
result = cast[PGdkGLPixmapClass](G_TYPE_CHECK_CLASS_CAST(klass, GDK_TYPE_GL_PIXMAP()))
|
||||
|
||||
proc GDK_IS_GL_PIXMAP*(anObject: Pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_GL_PIXMAP())
|
||||
|
||||
proc GDK_IS_GL_PIXMAP_CLASS*(klass: Pointer): bool =
|
||||
result = G_TYPE_CHECK_CLASS_TYPE(klass, GDK_TYPE_GL_PIXMAP())
|
||||
|
||||
proc GDK_GL_PIXMAP_GET_CLASS*(obj: Pointer): PGdkGLPixmapClass =
|
||||
result = cast[PGdkGLPixmapClass](G_TYPE_INSTANCE_GET_CLASS(obj, GDK_TYPE_GL_PIXMAP()))
|
||||
|
||||
proc gdk_pixmap_get_gl_drawable*(pixmap: PGdkPixmap): PGdkGLDrawable =
|
||||
result = GDK_GL_DRAWABLE(gdk_pixmap_get_gl_pixmap(pixmap))
|
||||
|
||||
proc GDK_TYPE_GL_WINDOW*(): GType =
|
||||
result = gdk_gl_window_get_type()
|
||||
|
||||
proc GDK_GL_WINDOW*(anObject: Pointer): PGdkGLWindow =
|
||||
result = cast[PGdkGLWindow](G_TYPE_CHECK_INSTANCE_CAST(anObject, GDK_TYPE_GL_WINDOW()))
|
||||
|
||||
proc GDK_GL_WINDOW_CLASS*(klass: Pointer): PGdkGLWindowClass =
|
||||
result = cast[PGdkGLWindowClass](G_TYPE_CHECK_CLASS_CAST(klass, GDK_TYPE_GL_WINDOW()))
|
||||
|
||||
proc GDK_IS_GL_WINDOW*(anObject: Pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(anObject, GDK_TYPE_GL_WINDOW())
|
||||
|
||||
proc GDK_IS_GL_WINDOW_CLASS*(klass: Pointer): bool =
|
||||
result = G_TYPE_CHECK_CLASS_TYPE(klass, GDK_TYPE_GL_WINDOW())
|
||||
|
||||
proc GDK_GL_WINDOW_GET_CLASS*(obj: Pointer): PGdkGLWindowClass =
|
||||
result = cast[PGdkGLWindowClass](G_TYPE_INSTANCE_GET_CLASS(obj, GDK_TYPE_GL_WINDOW()))
|
||||
|
||||
proc gdk_window_get_gl_drawable*(window: PGdkWindow): PGdkGLDrawable =
|
||||
result = GDK_GL_DRAWABLE(gdk_window_get_gl_window(window))
|
||||
4498
lib/base/gtk/glib2.nim
Executable file
4498
lib/base/gtk/glib2.nim
Executable file
File diff suppressed because it is too large
Load Diff
17226
lib/base/gtk/gtk2.nim
Executable file
17226
lib/base/gtk/gtk2.nim
Executable file
File diff suppressed because it is too large
Load Diff
48
lib/base/gtk/gtkglext.nim
Executable file
48
lib/base/gtk/gtkglext.nim
Executable file
@@ -0,0 +1,48 @@
|
||||
import
|
||||
Glib2, Gdk2, Gtk2, GdkGLExt
|
||||
|
||||
const
|
||||
GtkGLExtLib* = if defined(WIN32): "libgtkglext-win32-1.0-0.dll" else: "libgtkglext-x11-1.0.so"
|
||||
|
||||
const
|
||||
HEADER_GTKGLEXT_MAJOR_VERSION* = 1
|
||||
HEADER_GTKGLEXT_MINOR_VERSION* = 0
|
||||
HEADER_GTKGLEXT_MICRO_VERSION* = 6
|
||||
HEADER_GTKGLEXT_INTERFACE_AGE* = 4
|
||||
HEADER_GTKGLEXT_BINARY_AGE* = 6
|
||||
|
||||
proc gtk_gl_parse_args*(argc: Plongint, argv: PPPChar): gboolean{.cdecl,
|
||||
dynlib: GtkGLExtLib, importc: "gtk_gl_parse_args".}
|
||||
proc gtk_gl_init_check*(argc: Plongint, argv: PPPChar): gboolean{.cdecl,
|
||||
dynlib: GtkGLExtLib, importc: "gtk_gl_init_check".}
|
||||
proc gtk_gl_init*(argc: Plongint, argv: PPPChar){.cdecl, dynlib: GtkGLExtLib,
|
||||
importc: "gtk_gl_init".}
|
||||
proc gtk_widget_set_gl_capability*(widget: PGtkWidget, glconfig: PGdkGLConfig,
|
||||
share_list: PGdkGLContext, direct: gboolean,
|
||||
render_type: int): gboolean{.cdecl,
|
||||
dynlib: GtkGLExtLib, importc: "gtk_widget_set_gl_capability".}
|
||||
proc gtk_widget_is_gl_capable*(widget: PGtkWidget): gboolean{.cdecl,
|
||||
dynlib: GtkGLExtLib, importc: "gtk_widget_is_gl_capable".}
|
||||
proc gtk_widget_get_gl_config*(widget: PGtkWidget): PGdkGLConfig{.cdecl,
|
||||
dynlib: GtkGLExtLib, importc: "gtk_widget_get_gl_config".}
|
||||
proc gtk_widget_create_gl_context*(widget: PGtkWidget,
|
||||
share_list: PGdkGLContext, direct: gboolean,
|
||||
render_type: int): PGdkGLContext{.cdecl,
|
||||
dynlib: GtkGLExtLib, importc: "gtk_widget_create_gl_context".}
|
||||
proc gtk_widget_get_gl_context*(widget: PGtkWidget): PGdkGLContext{.cdecl,
|
||||
dynlib: GtkGLExtLib, importc: "gtk_widget_get_gl_context".}
|
||||
proc gtk_widget_get_gl_window*(widget: PGtkWidget): PGdkGLWindow{.cdecl,
|
||||
dynlib: GtkGLExtLib, importc: "gtk_widget_get_gl_window".}
|
||||
proc gtk_widget_get_gl_drawable*(widget: PGtkWidget): PGdkGLDrawable =
|
||||
nil
|
||||
|
||||
proc HEADER_GTKGLEXT_CHECK_VERSION*(major, minor, micro: guint): bool =
|
||||
result = (HEADER_GTKGLEXT_MAJOR_VERSION > major) or
|
||||
((HEADER_GTKGLEXT_MAJOR_VERSION == major) and
|
||||
(HEADER_GTKGLEXT_MINOR_VERSION > minor)) or
|
||||
((HEADER_GTKGLEXT_MAJOR_VERSION == major) and
|
||||
(HEADER_GTKGLEXT_MINOR_VERSION == minor) and
|
||||
(HEADER_GTKGLEXT_MICRO_VERSION >= micro))
|
||||
|
||||
proc gtk_widget_get_gl_drawable*(widget: PGtkWidget): PGdkGLDrawable =
|
||||
result = GDK_GL_DRAWABLE(gtk_widget_get_gl_window(widget))
|
||||
497
lib/base/gtk/gtkhtml.nim
Executable file
497
lib/base/gtk/gtkhtml.nim
Executable file
@@ -0,0 +1,497 @@
|
||||
import
|
||||
gtk2, glib2, atk, pango, gdk2pixbuf, gdk2
|
||||
|
||||
when defined(windows):
|
||||
{.define: GTK_WINDOWING_WIN32.}
|
||||
const
|
||||
gtkhtmllib = "libgtkhtml-win32-2.0-0.dll"
|
||||
else:
|
||||
const
|
||||
gtkhtmllib = "libgtkhtml-2.so"
|
||||
const
|
||||
DOM_UNSPECIFIED_EVENT_TYPE_ERR* = 0
|
||||
DOM_INDEX_SIZE_ERR* = 1
|
||||
DOM_DOMSTRING_SIZE_ERR* = 2
|
||||
DOM_HIERARCHY_REQUEST_ERR* = 3
|
||||
DOM_WRONG_DOCUMENT_ERR* = 4
|
||||
DOM_INVALID_CHARACTER_ERR* = 5
|
||||
DOM_NO_DATA_ALLOWED_ERR* = 6
|
||||
DOM_NO_MODIFICATION_ALLOWED_ERR* = 7
|
||||
DOM_NOT_FOUND_ERR* = 8
|
||||
DOM_NOT_SUPPORTED_ERR* = 9
|
||||
DOM_INUSE_ATTRIBUTE_ERR* = 10
|
||||
DOM_INVALID_STATE_ERR* = 11
|
||||
DOM_SYNTAX_ERR* = 12
|
||||
DOM_INVALID_MODIFICATION_ERR* = 13
|
||||
DOM_NAMESPACE_ERR* = 14
|
||||
DOM_INVALID_ACCESS_ERR* = 15
|
||||
DOM_NO_EXCEPTION* = 255
|
||||
DOM_ELEMENT_NODE* = 1
|
||||
DOM_ATTRIBUTE_NODE* = 2
|
||||
DOM_TEXT_NODE* = 3
|
||||
DOM_CDATA_SECTION_NODE* = 4
|
||||
DOM_ENTITY_REFERENCE_NODE* = 5
|
||||
DOM_ENTITY_NODE* = 6
|
||||
DOM_PROCESSING_INSTRUCTION_NODE* = 7
|
||||
DOM_COMMENT_NODE* = 8
|
||||
DOM_DOCUMENT_NODE* = 9
|
||||
DOM_DOCUMENT_TYPE_NODE* = 10
|
||||
DOM_DOCUMENT_FRAGMENT_NODE* = 11
|
||||
DOM_NOTATION_NODE* = 12
|
||||
bm__HtmlFontSpecification_weight* = 0x0000000F
|
||||
bp__HtmlFontSpecification_weight* = 0
|
||||
bm__HtmlFontSpecification_style* = 0x00000030
|
||||
bp__HtmlFontSpecification_style* = 4
|
||||
bm__HtmlFontSpecification_variant* = 0x000000C0
|
||||
bp__HtmlFontSpecification_variant* = 6
|
||||
bm__HtmlFontSpecification_stretch* = 0x00000F00
|
||||
bp__HtmlFontSpecification_stretch* = 8
|
||||
bm__HtmlFontSpecification_decoration* = 0x00007000
|
||||
bp__HtmlFontSpecification_decoration* = 12
|
||||
|
||||
type
|
||||
TDomString* = gchar
|
||||
TDomBoolean* = gboolean
|
||||
TDomException* = gushort
|
||||
TDomTimeStamp* = guint64
|
||||
PDomNode* = ptr TDomNode
|
||||
TDomNode* = object of TGObject
|
||||
xmlnode*: pointer
|
||||
style*: pointer
|
||||
|
||||
PDomNodeClass* = ptr TDomNodeClass
|
||||
TDomNodeClass* = object of TGObjectClass
|
||||
`get_nodeName`*: proc (node: PDomNode): PDomString{.cdecl.}
|
||||
`get_nodeValue`*: proc (node: PDomNode, exc: PDomException): PDomString {.
|
||||
cdecl.}
|
||||
`set_nodeValue`*: proc (node: PDomNode, value: PDomString,
|
||||
exc: PDomException): PDomString{.cdecl.}
|
||||
|
||||
PDomDocument* = ptr TDomDocument
|
||||
TDomDocument* = record
|
||||
parent*: PDomNode
|
||||
iterators*: PGSList
|
||||
|
||||
PDomDocumentClass* = ptr TDomDocumentClass
|
||||
TDomDocumentClass* = record
|
||||
parent_class*: PDomNodeClass
|
||||
|
||||
PHtmlFocusIterator* = ptr THtmlFocusIterator
|
||||
THtmlFocusIterator* = object of TGObject
|
||||
document*: PDomDocument
|
||||
current_node*: PDomNode
|
||||
|
||||
PHtmlFocusIteratorClass* = ptr THtmlFocusIteratorClass
|
||||
THtmlFocusIteratorClass* = object of TGObjectClass
|
||||
|
||||
THtmlParserType* = enum
|
||||
HTML_PARSER_TYPE_HTML, HTML_PARSER_TYPE_XML
|
||||
PHtmlParser* = ptr THtmlParser
|
||||
THtmlParser* = object of TGObject
|
||||
parser_type*: THtmlParserType
|
||||
document*: PHtmlDocument
|
||||
stream*: PHtmlStream
|
||||
xmlctxt*: xmlParserCtxtPtr
|
||||
res*: int32
|
||||
chars*: array[0..9, char]
|
||||
blocking*: gboolean
|
||||
blocking_node*: PDomNode
|
||||
|
||||
PHtmlParserClass* = ptr THtmlParserClass
|
||||
THtmlParserClass* = object of TGtkObjectClass
|
||||
done_parsing*: proc (parser: PHtmlParser){.cdecl.}
|
||||
new_node*: proc (parser: PHtmlParser, node: PDomNode)
|
||||
parsed_document_node*: proc (parser: PHtmlParser, document: PDomDocument)
|
||||
|
||||
PHtmlStream* = ptr THtmlStream
|
||||
THtmlStreamCloseFunc* = proc (stream: PHtmlStream, user_data: gpointer){.cdecl.}
|
||||
THtmlStreamWriteFunc* = proc (stream: PHtmlStream, buffer: Pgchar,
|
||||
size: guint, user_data: gpointer){.cdecl.}
|
||||
THtmlStreamCancelFunc* = proc (stream: PHtmlStream, user_data: gpointer,
|
||||
cancel_data: gpointer){.cdecl.}
|
||||
THtmlStream* = object of TGObject
|
||||
write_func*: THtmlStreamWriteFunc
|
||||
close_func*: THtmlStreamCloseFunc
|
||||
cancel_func*: THtmlStreamCancelFunc
|
||||
user_data*: gpointer
|
||||
cancel_data*: gpointer
|
||||
written*: gint
|
||||
mime_type*: cstring
|
||||
|
||||
PHtmlStreamClass* = ptr THtmlStreamClass
|
||||
THtmlStreamClass* = object of TGObjectClass
|
||||
|
||||
THtmlStreamBufferCloseFunc* = proc (str: Pgchar, len: gint,
|
||||
user_data: gpointer){.cdecl.}
|
||||
PGtkHtmlContext* = ptr TGtkHtmlContext
|
||||
TGtkHtmlContext* = object of TGObject
|
||||
documents*: PGSList
|
||||
standard_font*: PHtmlFontSpecification
|
||||
fixed_font*: PHtmlFontSpecification
|
||||
debug_painting*: gboolean
|
||||
|
||||
PGtkHtmlContextClass* = ptr TGtkHtmlContextClass
|
||||
TGtkHtmlContextClass* = object of TGObjectClass
|
||||
|
||||
THtmlDocumentState* = enum
|
||||
HTML_DOCUMENT_STATE_DONE, HTML_DOCUMENT_STATE_PARSING
|
||||
PHtmlDocument* = ptr THtmlDocument
|
||||
THtmlDocument* = object of TGObject
|
||||
stylesheets*: PGSList
|
||||
current_stream*: PHtmlStream
|
||||
state*: THtmlDocumentState
|
||||
|
||||
PHtmlDocumentClass* = ptr THtmlDocumentClass
|
||||
THtmlDocumentClass* = object of TGObjectClass
|
||||
request_url*: proc (document: PHtmlDocument, url: Pgchar,
|
||||
stream: PHtmlStream){.cdecl.}
|
||||
link_clicked*: proc (document: PHtmlDocument, url: Pgchar){.cdecl.}
|
||||
set_base*: proc (document: PHtmlDocument, url: Pgchar){.cdecl.}
|
||||
title_changed*: proc (document: PHtmlDocument, new_title: Pgchar){.cdecl.}
|
||||
submit*: proc (document: PHtmlDocument, `method`: Pgchar, url: Pgchar,
|
||||
encoding: Pgchar){.cdecl.}
|
||||
|
||||
PHtmlView* = ptr THtmlView
|
||||
THtmlView* = object of TGtkLayout
|
||||
document*: PHtmlDocument
|
||||
node_table*: PGHashTable
|
||||
relayout_idle_id*: guint
|
||||
relayout_timeout_id*: guint
|
||||
mouse_down_x*: gint
|
||||
mouse_down_y*: gint
|
||||
mouse_detail*: gint
|
||||
sel_start_ypos*: gint
|
||||
sel_start_index*: gint
|
||||
sel_end_ypos*: gint
|
||||
sel_end_index*: gint
|
||||
sel_flag*: gboolean
|
||||
sel_backwards*: gboolean
|
||||
sel_start_found*: gboolean
|
||||
sel_list*: PGSList
|
||||
jump_to_anchor*: pgchar
|
||||
magnification*: gdouble
|
||||
magnification_modified*: gboolean
|
||||
on_url*: gboolean
|
||||
|
||||
PHtmlViewClass* = ptr THtmlViewClass
|
||||
THtmlViewClass* = object of TGtkLayoutClass
|
||||
move_cursor*: proc (html_view: PHtmlView, step: TGtkMovementStep,
|
||||
count: gint, extend_selection: gboolean){.cdecl.}
|
||||
on_url*: proc (html_view: PHtmlView, url: Pgchar)
|
||||
activate*: proc (html_view: PHtmlView)
|
||||
move_focus_out*: proc (html_view: PHtmlView, direction: TGtkDirectionType)
|
||||
|
||||
|
||||
proc DOM_TYPE_NODE*(): GType
|
||||
proc DOM_NODE*(theobject: pointer): PDomNode
|
||||
proc DOM_NODE_CLASS*(klass: pointer): PDomNodeClass
|
||||
proc DOM_IS_NODE*(theobject: pointer): bool
|
||||
proc DOM_IS_NODE_CLASS*(klass: pointer): bool
|
||||
proc DOM_NODE_GET_CLASS*(obj: pointer): int32
|
||||
proc dom_node_get_type*(): GType{.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "dom_node_get_type".}
|
||||
proc dom_Node_mkref*(node: pointer): PDomNode{.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "dom_Node_mkref".}
|
||||
proc dom_Node__get_childNodes*(node: PDomNode): PDomNodeList{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node__get_childNodes".}
|
||||
proc dom_Node_removeChild*(node: PDomNode, oldChild: PDomNode,
|
||||
exc: PDomException): PDomNode{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node_removeChild".}
|
||||
proc dom_Node__get_nodeValue*(node: PDomNode, exc: PDomException): PDomString{.
|
||||
cdecl, dynlib: gtkhtmllib, importc: "dom_Node__get_nodeValue".}
|
||||
proc dom_Node__get_firstChild*(node: PDomNode): PDomNode{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node__get_firstChild".}
|
||||
proc dom_Node__get_nodeName*(node: PDomNode): PDomString{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node__get_nodeName".}
|
||||
proc dom_Node__get_attributes*(node: PDomNode): PDomNamedNodeMap{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node__get_attributes".}
|
||||
proc dom_Document__get_doctype*(doc: PDomDocument): PDomDocumentType{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Document__get_doctype".}
|
||||
proc dom_Node_hasChildNodes*(node: PDomNode): DomBoolean{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node_hasChildNodes".}
|
||||
proc dom_Node__get_parentNode*(node: PDomNode): PDomNode{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node__get_parentNode".}
|
||||
proc dom_Node__get_nextSibling*(node: PDomNode): PDomNode{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node__get_nextSibling".}
|
||||
proc dom_Node__get_nodeType*(node: PDomNode): gushort{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node__get_nodeType".}
|
||||
proc dom_Node_hasAttributes*(node: PDomNode): DomBoolean{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node_hasAttributes".}
|
||||
proc dom_Node_cloneNode*(node: PDomNode, deep: DomBoolean): PDomNode{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node_cloneNode".}
|
||||
proc dom_Node_appendChild*(node: PDomNode, newChild: PDomNode,
|
||||
exc: PDomException): PDomNode{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node_appendChild".}
|
||||
proc dom_Node__get_localName*(node: PDomNode): PDomString{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node__get_localName".}
|
||||
proc dom_Node__get_namespaceURI*(node: PDomNode): PDomString{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node__get_namespaceURI".}
|
||||
proc dom_Node__get_previousSibling*(node: PDomNode): PDomNode{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node__get_previousSibling".}
|
||||
proc dom_Node__get_lastChild*(node: PDomNode): PDomNode{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node__get_lastChild".}
|
||||
proc dom_Node__set_nodeValue*(node: PDomNode, value: PDomString,
|
||||
exc: PDomException){.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "dom_Node__set_nodeValue".}
|
||||
proc dom_Node__get_ownerDocument*(node: PDomNode): PDomDocument{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node__get_ownerDocument".}
|
||||
proc dom_Node_hasAttributes*(node: PDomNode): gboolean{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "dom_Node_hasAttributes".}
|
||||
proc DOM_TYPE_DOCUMENT*(): GType
|
||||
proc DOM_DOCUMENT*(theobject: pointer): PDomDocument
|
||||
proc DOM_DOCUMENT_CLASS*(klass: pointer): PDomDocumentClass
|
||||
proc DOM_IS_DOCUMENT*(theobject: pointer): bool
|
||||
proc DOM_IS_DOCUMENT_CLASS*(klass: pointer): bool
|
||||
proc DOM_DOCUMENT_GET_CLASS*(obj: pointer): PDomDocumentClass
|
||||
proc dom_document_get_type*(): GType
|
||||
proc dom_Document__get_documentElement*(doc: PDomDocument): PDomElement
|
||||
proc dom_Document_createElement*(doc: PDomDocument, tagName: PDomString): PDomElement
|
||||
proc dom_Document_createTextNode*(doc: PDomDocument, data: PDomString): PDomText
|
||||
proc dom_Document_createComment*(doc: PDomDocument, data: PDomString): PDomComment
|
||||
proc dom_Document_importNode*(doc: PDomDocument, importedNode: PDomNode,
|
||||
deep: DomBoolean, exc: PDomException): PDomNode
|
||||
proc HTML_TYPE_FOCUS_ITERATOR*(): GType
|
||||
proc HTML_FOCUS_ITERATOR*(theobject: pointer): PHtmlFocusIterator
|
||||
proc HTML_FOCUS_ITERATOR_CLASS*(klass: pointer): PHtmlFocusIteratorClass
|
||||
proc HTML_IS_FOCUS_ITERATOR*(theobject: pointer): bool
|
||||
proc HTML_IS_FOCUS_ITERATOR_CLASS*(klass: pointer): bool
|
||||
proc HTML_FOCUS_ITERATOR_GET_CLASS*(obj: pointer): PHtmlFocusIteratorClass
|
||||
proc html_focus_iterator_next_element*(document: PDomDocument,
|
||||
element: PDomElement): PDomElement{.
|
||||
cdecl, dynlib: gtkhtmllib, importc: "html_focus_iterator_next_element".}
|
||||
proc html_focus_iterator_prev_element*(document: PDomDocument,
|
||||
element: PDomElement): PDomElement{.
|
||||
cdecl, dynlib: gtkhtmllib, importc: "html_focus_iterator_prev_element".}
|
||||
proc HTML_PARSER_TYPE*(): GType
|
||||
proc HTML_PARSER*(obj: pointer): PHtmlParser
|
||||
proc HTML_PARSER_CLASS*(klass: pointer): PHtmlParserClass
|
||||
proc HTML_IS_PARSER*(obj: pointer): bool
|
||||
proc html_parser_get_type*(): GType
|
||||
proc html_parser_new*(document: PHtmlDocument, parser_type: THtmlParserType): PHtmlParser
|
||||
proc HTML_TYPE_STREAM*(): GType
|
||||
proc HTML_STREAM*(obj: pointer): PHtmlStream
|
||||
proc HTML_STREAM_CLASS*(klass: pointer): PHtmlStreamClass
|
||||
proc HTML_IS_STREAM*(obj: pointer): bool
|
||||
proc HTML_IS_STREAM_CLASS*(klass: pointer): bool
|
||||
proc HTML_STREAM_GET_CLASS*(obj: pointer): PHtmlStreamClass
|
||||
proc html_stream_get_type*(): GType{.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_stream_get_type".}
|
||||
proc html_stream_new*(write_func: THtmlStreamWriteFunc,
|
||||
close_func: THtmlStreamCloseFunc, user_data: gpointer): PHtmlStream{.
|
||||
cdecl, dynlib: gtkhtmllib, importc: "html_stream_new".}
|
||||
proc html_stream_write*(stream: PHtmlStream, buffer: Pgchar, size: guint){.
|
||||
cdecl, dynlib: gtkhtmllib, importc: "html_stream_write".}
|
||||
proc html_stream_close*(stream: PHtmlStream){.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_stream_close".}
|
||||
proc html_stream_destroy*(stream: PHtmlStream){.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_stream_destroy".}
|
||||
proc html_stream_get_written*(stream: PHtmlStream): gint{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_stream_get_written".}
|
||||
proc html_stream_cancel*(stream: PHtmlStream){.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_stream_cancel".}
|
||||
proc html_stream_set_cancel_func*(stream: PHtmlStream,
|
||||
abort_func: THtmlStreamCancelFunc,
|
||||
cancel_data: gpointer){.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_stream_set_cancel_func".}
|
||||
proc html_stream_get_mime_type*(stream: PHtmlStream): cstring{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_stream_get_mime_type".}
|
||||
proc html_stream_set_mime_type*(stream: PHtmlStream, mime_type: cstring){.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_stream_set_mime_type".}
|
||||
proc html_stream_buffer_new*(close_func: THtmlStreamBufferCloseFunc,
|
||||
user_data: gpointer): PHtmlStream{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_stream_buffer_new".}
|
||||
proc html_event_mouse_move*(view: PHtmlView, event: PGdkEventMotion){.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_event_mouse_move".}
|
||||
proc html_event_button_press*(view: PHtmlView, button: PGdkEventButton){.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_event_button_press".}
|
||||
proc html_event_button_release*(view: PHtmlView, event: PGdkEventButton){.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_event_button_release".}
|
||||
proc html_event_activate*(view: PHtmlView){.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_event_activate".}
|
||||
proc html_event_key_press*(view: PHtmlView, event: PGdkEventKey): gboolean{.
|
||||
cdecl, dynlib: gtkhtmllib, importc: "html_event_key_press".}
|
||||
proc html_event_find_root_box*(self: PHtmlBox, x: gint, y: gint): PHtmlBox{.
|
||||
cdecl, dynlib: gtkhtmllib, importc: "html_event_find_root_box".}
|
||||
proc html_selection_start*(view: PHtmlView, event: PGdkEventButton){.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_selection_start".}
|
||||
proc html_selection_end*(view: PHtmlView, event: PGdkEventButton){.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_selection_end".}
|
||||
proc html_selection_update*(view: PHtmlView, event: PGdkEventMotion){.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_selection_update".}
|
||||
proc html_selection_clear*(view: PHtmlView){.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_selection_clear".}
|
||||
proc html_selection_set*(view: PHtmlView, start: PDomNode, offset: int32,
|
||||
len: int32){.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_selection_set".}
|
||||
proc GTK_HTML_CONTEXT_TYPE*(): GType
|
||||
proc GTK_HTML_CONTEXT*(obj: pointer): PGtkHtmlContext
|
||||
proc GTK_HTML_CONTEXT_CLASS*(klass: pointer): PGtkHtmlContextClass
|
||||
proc GTK_HTML_IS_CONTEXT*(obj: pointer): bool
|
||||
proc GTK_HTML_IS_CONTEXT_CLASS*(klass: pointer): bool
|
||||
proc gtk_html_context_get_type*(): GType
|
||||
proc gtk_html_context_get*(): PGtkHtmlContext
|
||||
proc HTML_TYPE_DOCUMENT*(): GType
|
||||
proc HTML_DOCUMENT*(obj: pointer): PHtmlDocument
|
||||
proc HTML_DOCUMENT_CLASS*(klass: pointer): PHtmlDocumentClass
|
||||
proc HTML_IS_DOCUMENT*(obj: pointer): bool
|
||||
proc html_document_get_type*(): GType{.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_document_get_type".}
|
||||
proc html_document_new*(): PHtmlDocument{.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_document_new".}
|
||||
proc html_document_open_stream*(document: PHtmlDocument, mime_type: Pgchar): gboolean{.
|
||||
cdecl, dynlib: gtkhtmllib, importc: "html_document_open_stream".}
|
||||
proc html_document_write_stream*(document: PHtmlDocument, buffer: Pgchar,
|
||||
len: gint){.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_document_write_stream".}
|
||||
proc html_document_close_stream*(document: PHtmlDocument){.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_document_close_stream".}
|
||||
proc html_document_clear*(document: PHtmlDocument){.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_document_clear".}
|
||||
proc HTML_TYPE_VIEW*(): GType
|
||||
proc HTML_VIEW*(obj: pointer): PHtmlView
|
||||
proc HTML_VIEW_CLASS*(klass: pointer): PHtmlViewClass
|
||||
proc HTML_IS_VIEW*(obj: pointer): bool
|
||||
proc html_view_get_type*(): GType{.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_view_get_type".}
|
||||
proc html_view_new*(): PGtkWidget{.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_view_new".}
|
||||
proc html_view_set_document*(view: PHtmlView, document: PHtmlDocument){.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_view_set_document".}
|
||||
proc html_view_jump_to_anchor*(view: PHtmlView, anchor: Pgchar){.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_view_jump_to_anchor".}
|
||||
proc html_view_get_magnification*(view: PHtmlView): gdouble{.cdecl,
|
||||
dynlib: gtkhtmllib, importc: "html_view_get_magnification".}
|
||||
proc html_view_set_magnification*(view: PHtmlView, magnification: gdouble){.
|
||||
cdecl, dynlib: gtkhtmllib, importc: "html_view_set_magnification".}
|
||||
proc html_view_zoom_in*(view: PHtmlView){.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_view_zoom_in".}
|
||||
proc html_view_zoom_out*(view: PHtmlView){.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_view_zoom_out".}
|
||||
proc html_view_zoom_reset*(view: PHtmlView){.cdecl, dynlib: gtkhtmllib,
|
||||
importc: "html_view_zoom_reset".}
|
||||
proc DOM_TYPE_NODE*(): GType =
|
||||
result = dom_node_get_type()
|
||||
|
||||
proc DOM_NODE*(theobject: pointer): PDomNode =
|
||||
result = G_TYPE_CHECK_INSTANCE_CAST(theobject, DOM_TYPE_NODE(), TDomNode)
|
||||
|
||||
proc DOM_NODE_CLASS*(klass: pointer): PDomNodeClass =
|
||||
result = G_TYPE_CHECK_CLASS_CAST(klass, DOM_TYPE_NODE(), TDomNodeClass)
|
||||
|
||||
proc DOM_IS_NODE*(theobject: pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(theobject, DOM_TYPE_NODE())
|
||||
|
||||
proc DOM_IS_NODE_CLASS*(klass: pointer): bool =
|
||||
result = G_TYPE_CHECK_CLASS_TYPE(klass, DOM_TYPE_NODE())
|
||||
|
||||
proc DOM_NODE_GET_CLASS*(obj: pointer): PDomNodeClass =
|
||||
result = G_TYPE_INSTANCE_GET_CLASS(obj, DOM_TYPE_NODE(), TDomNodeClass)
|
||||
|
||||
proc DOM_TYPE_DOCUMENT*(): GType =
|
||||
result = dom_document_get_type()
|
||||
|
||||
proc DOM_DOCUMENT*(theobject: pointer): PDomDocument =
|
||||
result = G_TYPE_CHECK_INSTANCE_CAST(theobject, DOM_TYPE_DOCUMENT(), TDomDocument)
|
||||
|
||||
proc DOM_DOCUMENT_CLASS*(klass: pointer): PDomDocumentClass =
|
||||
result = G_TYPE_CHECK_CLASS_CAST(klass, DOM_TYPE_DOCUMENT(), TDomDocumentClass)
|
||||
|
||||
proc DOM_IS_DOCUMENT*(theobject: pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(theobject, DOM_TYPE_DOCUMENT())
|
||||
|
||||
proc DOM_IS_DOCUMENT_CLASS*(klass: pointer): bool =
|
||||
result = G_TYPE_CHECK_CLASS_TYPE(klass, DOM_TYPE_DOCUMENT())
|
||||
|
||||
proc DOM_DOCUMENT_GET_CLASS*(obj: pointer): PDomDocumentClass =
|
||||
result = G_TYPE_INSTANCE_GET_CLASS(obj, DOM_TYPE_DOCUMENT(), TDomDocumentClass)
|
||||
|
||||
proc HTML_TYPE_FOCUS_ITERATOR*(): GType =
|
||||
result = html_focus_iterator_get_type()
|
||||
|
||||
proc HTML_FOCUS_ITERATOR*(theobject: pointer): PHtmlFocusIterator =
|
||||
result = G_TYPE_CHECK_INSTANCE_CAST(theobject, HTML_TYPE_FOCUS_ITERATOR(),
|
||||
HtmlFocusIterator)
|
||||
|
||||
proc HTML_FOCUS_ITERATOR_CLASS*(klass: pointer): PHtmlFocusIteratorClass =
|
||||
result = G_TYPE_CHECK_CLASS_CAST(klass, HTML_TYPE_FOCUS_ITERATOR(),
|
||||
HtmlFocusIteratorClass)
|
||||
|
||||
proc HTML_IS_FOCUS_ITERATOR*(theobject: pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(theobject, HTML_TYPE_FOCUS_ITERATOR())
|
||||
|
||||
proc HTML_IS_FOCUS_ITERATOR_CLASS*(klass: pointer): bool =
|
||||
result = G_TYPE_CHECK_CLASS_TYPE(klass, HTML_TYPE_FOCUS_ITERATOR())
|
||||
|
||||
proc HTML_FOCUS_ITERATOR_GET_CLASS*(obj: pointer): PHtmlFocusIteratorClass =
|
||||
result = G_TYPE_INSTANCE_GET_CLASS(obj, HTML_TYPE_FOCUS_ITERATOR(),
|
||||
HtmlFocusIteratorClass)
|
||||
|
||||
proc HTML_PARSER_TYPE*(): GType =
|
||||
result = html_parser_get_type()
|
||||
|
||||
proc HTML_PARSER*(obj: pointer): PHtmlParser =
|
||||
result = GTK_CHECK_CAST(obj, HTML_PARSER_TYPE(), THtmlParser)
|
||||
|
||||
proc HTML_PARSER_CLASS*(klass: pointer): PHtmlParserClass =
|
||||
result = GTK_CHECK_CLASS_CAST(klass, HTML_PARSER_TYPE(), THtmlParserClass)
|
||||
|
||||
proc HTML_IS_PARSER*(obj: pointer): bool =
|
||||
result = GTK_CHECK_TYPE(obj, HTML_PARSER_TYPE())
|
||||
|
||||
proc HTML_TYPE_STREAM*(): GType =
|
||||
result = html_stream_get_type()
|
||||
|
||||
proc HTML_STREAM*(obj: pointer): PHtmlStream =
|
||||
result = PHtmlStream(G_TYPE_CHECK_INSTANCE_CAST(obj, HTML_TYPE_STREAM()))
|
||||
|
||||
proc HTML_STREAM_CLASS*(klass: pointer): PHtmlStreamClass =
|
||||
result = G_TYPE_CHECK_CLASS_CAST(klass, HTML_TYPE_STREAM())
|
||||
|
||||
proc HTML_IS_STREAM*(obj: pointer): bool =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(obj, HTML_TYPE_STREAM())
|
||||
|
||||
proc HTML_IS_STREAM_CLASS*(klass: pointer): bool =
|
||||
result = G_TYPE_CHECK_CLASS_TYPE(klass, HTML_TYPE_STREAM())
|
||||
|
||||
proc HTML_STREAM_GET_CLASS*(obj: pointer): PHtmlStreamClass =
|
||||
result = PHtmlStreamClass(G_TYPE_INSTANCE_GET_CLASS(obj, HTML_TYPE_STREAM()))
|
||||
|
||||
proc GTK_HTML_CONTEXT_TYPE*(): GType =
|
||||
result = gtk_html_context_get_type()
|
||||
|
||||
proc GTK_HTML_CONTEXT*(obj: pointer): PGtkHtmlContext =
|
||||
result = GTK_CHECK_CAST(obj, GTK_HTML_CONTEXT_TYPE(), TGtkHtmlContext)
|
||||
|
||||
proc GTK_HTML_CONTEXT_CLASS*(klass: pointer): PGtkHtmlContextClass =
|
||||
result = GTK_CHECK_CLASS_CAST(klass, GTK_HTML_CONTEXT_TYPE(),
|
||||
TGtkHtmlContextClass)
|
||||
|
||||
proc GTK_HTML_IS_CONTEXT*(obj: pointer): bool =
|
||||
result = GTK_CHECK_TYPE(obj, GTK_HTML_CONTEXT_TYPE())
|
||||
|
||||
proc GTK_HTML_IS_CONTEXT_CLASS*(klass: pointer): bool =
|
||||
result = GTK_CHECK_CLASS_TYPE(klass, GTK_HTML_CONTEXT_TYPE())
|
||||
|
||||
proc HTML_TYPE_DOCUMENT*(): GType =
|
||||
result = html_document_get_type()
|
||||
|
||||
proc HTML_DOCUMENT*(obj: pointer): PHtmlDocument =
|
||||
result = PHtmlDocument(GTK_CHECK_CAST(obj, HTML_TYPE_DOCUMENT()))
|
||||
|
||||
proc HTML_DOCUMENT_CLASS*(klass: pointer): PHtmlDocumentClass =
|
||||
result = GTK_CHECK_CLASS_CAST(klass, HTML_TYPE_DOCUMENT())
|
||||
|
||||
proc HTML_IS_DOCUMENT*(obj: pointer): bool =
|
||||
result = GTK_CHECK_TYPE(obj, HTML_TYPE_DOCUMENT())
|
||||
|
||||
proc HTML_TYPE_VIEW*(): GType =
|
||||
result = html_view_get_type()
|
||||
|
||||
proc HTML_VIEW*(obj: pointer): PHtmlView =
|
||||
result = PHtmlView(GTK_CHECK_CAST(obj, HTML_TYPE_VIEW()))
|
||||
|
||||
proc HTML_VIEW_CLASS*(klass: pointer): PHtmlViewClass =
|
||||
result = PHtmlViewClass(GTK_CHECK_CLASS_CAST(klass, HTML_TYPE_VIEW()))
|
||||
|
||||
proc HTML_IS_VIEW*(obj: pointer): bool =
|
||||
result = GTK_CHECK_TYPE(obj, HTML_TYPE_VIEW())
|
||||
117
lib/base/gtk/libglade2.nim
Executable file
117
lib/base/gtk/libglade2.nim
Executable file
@@ -0,0 +1,117 @@
|
||||
import
|
||||
glib2, gtk2
|
||||
|
||||
when defined(win32):
|
||||
{.define: gtkwin.}
|
||||
const
|
||||
LibGladeLib = "libglade-2.0-0.dll"
|
||||
else:
|
||||
const
|
||||
LibGladeLib = "libglade-2.0.so"
|
||||
type
|
||||
PLongint* = ptr int32
|
||||
PSmallInt* = ptr int16
|
||||
PByte* = ptr int8
|
||||
PWord* = ptr int16
|
||||
PDWord* = ptr int32
|
||||
PDouble* = ptr float64
|
||||
|
||||
proc glade_init*(){.cdecl, dynlib: LibGladeLib, importc: "glade_init".}
|
||||
proc glade_require*(TheLibrary: cstring){.cdecl, dynlib: LibGladeLib,
|
||||
importc: "glade_require".}
|
||||
proc glade_provide*(TheLibrary: cstring){.cdecl, dynlib: LibGladeLib,
|
||||
importc: "glade_provide".}
|
||||
type
|
||||
PGladeXMLPrivate* = pointer
|
||||
PGladeXML* = ptr TGladeXML
|
||||
TGladeXML* = object of TGObject
|
||||
filename*: cstring
|
||||
priv*: PGladeXMLPrivate
|
||||
|
||||
PGladeXMLClass* = ptr TGladeXMLClass
|
||||
TGladeXMLClass* = object of TGObjectClass
|
||||
|
||||
TGladeXMLConnectFunc* = proc (handler_name: cstring, anObject: PGObject,
|
||||
signal_name: cstring, signal_data: cstring,
|
||||
connect_object: PGObject, after: gboolean,
|
||||
user_data: gpointer){.cdecl.}
|
||||
|
||||
proc GLADE_TYPE_XML*(): GType
|
||||
proc GLADE_XML*(obj: pointer): PGladeXML
|
||||
proc GLADE_XML_CLASS*(klass: pointer): PGladeXMLClass
|
||||
proc GLADE_IS_XML*(obj: pointer): gboolean
|
||||
proc GLADE_IS_XML_CLASS*(klass: pointer): gboolean
|
||||
proc GLADE_XML_GET_CLASS*(obj: pointer): PGladeXMLClass
|
||||
proc glade_xml_get_type*(): GType{.cdecl, dynlib: LibGladeLib,
|
||||
importc: "glade_xml_get_type".}
|
||||
proc glade_xml_new*(fname: cstring, root: cstring, domain: cstring): PGladeXML{.
|
||||
cdecl, dynlib: LibGladeLib, importc: "glade_xml_new".}
|
||||
proc glade_xml_new_from_buffer*(buffer: cstring, size: int32, root: cstring,
|
||||
domain: cstring): PGladeXML{.cdecl,
|
||||
dynlib: LibGladeLib, importc: "glade_xml_new_from_buffer".}
|
||||
proc glade_xml_construct*(self: PGladeXML, fname: cstring, root: cstring,
|
||||
domain: cstring): gboolean{.cdecl,
|
||||
dynlib: LibGladeLib, importc: "glade_xml_construct".}
|
||||
proc glade_xml_signal_connect*(self: PGladeXML, handlername: cstring,
|
||||
func: TGCallback){.cdecl, dynlib: LibGladeLib,
|
||||
importc: "glade_xml_signal_connect".}
|
||||
proc glade_xml_signal_connect_data*(self: PGladeXML, handlername: cstring,
|
||||
func: TGCallback, user_data: gpointer){.
|
||||
cdecl, dynlib: LibGladeLib, importc: "glade_xml_signal_connect_data".}
|
||||
proc glade_xml_signal_autoconnect*(self: PGladeXML){.cdecl, dynlib: LibGladeLib,
|
||||
importc: "glade_xml_signal_autoconnect".}
|
||||
proc glade_xml_signal_connect_full*(self: PGladeXML, handler_name: cstring,
|
||||
func: TGladeXMLConnectFunc,
|
||||
user_data: gpointer){.cdecl,
|
||||
dynlib: LibGladeLib, importc: "glade_xml_signal_connect_full".}
|
||||
proc glade_xml_signal_autoconnect_full*(self: PGladeXML,
|
||||
func: TGladeXMLConnectFunc,
|
||||
user_data: gpointer){.cdecl,
|
||||
dynlib: LibGladeLib, importc: "glade_xml_signal_autoconnect_full".}
|
||||
proc glade_xml_get_widget*(self: PGladeXML, name: cstring): PGtkWidget{.cdecl,
|
||||
dynlib: LibGladeLib, importc: "glade_xml_get_widget".}
|
||||
proc glade_xml_get_widget_prefix*(self: PGladeXML, name: cstring): PGList{.
|
||||
cdecl, dynlib: LibGladeLib, importc: "glade_xml_get_widget_prefix".}
|
||||
proc glade_xml_relative_file*(self: PGladeXML, filename: cstring): cstring{.cdecl,
|
||||
dynlib: LibGladeLib, importc: "glade_xml_relative_file".}
|
||||
proc glade_get_widget_name*(widget: PGtkWidget): cstring{.cdecl,
|
||||
dynlib: LibGladeLib, importc: "glade_get_widget_name".}
|
||||
proc glade_get_widget_tree*(widget: PGtkWidget): PGladeXML{.cdecl,
|
||||
dynlib: LibGladeLib, importc: "glade_get_widget_tree".}
|
||||
type
|
||||
PGladeXMLCustomWidgetHandler* = ptr TGladeXMLCustomWidgetHandler
|
||||
TGladeXMLCustomWidgetHandler* = TGtkWidget
|
||||
|
||||
proc glade_set_custom_handler*(handler: TGladeXMLCustomWidgetHandler,
|
||||
user_data: gpointer){.cdecl, dynlib: LibGladeLib,
|
||||
importc: "glade_set_custom_handler".}
|
||||
proc glade_gnome_init*() =
|
||||
glade_init()
|
||||
|
||||
proc glade_bonobo_init*() =
|
||||
glade_init()
|
||||
|
||||
proc glade_xml_new_with_domain*(fname: cstring, root: cstring, domain: cstring): PGladeXML =
|
||||
result = glade_xml_new(fname, root, domain)
|
||||
|
||||
proc glade_xml_new_from_memory*(buffer: cstring, size: int32, root: cstring,
|
||||
domain: cstring): PGladeXML =
|
||||
result = glade_xml_new_from_buffer(buffer, size, root, domain)
|
||||
|
||||
proc GLADE_TYPE_XML*(): GType =
|
||||
result = glade_xml_get_type()
|
||||
|
||||
proc GLADE_XML*(obj: pointer): PGladeXML =
|
||||
result = cast[PGladeXML](G_TYPE_CHECK_INSTANCE_CAST(obj, GLADE_TYPE_XML()))
|
||||
|
||||
proc GLADE_XML_CLASS*(klass: pointer): PGladeXMLClass =
|
||||
result = cast[PGladeXMLClass](G_TYPE_CHECK_CLASS_CAST(klass, GLADE_TYPE_XML()))
|
||||
|
||||
proc GLADE_IS_XML*(obj: pointer): gboolean =
|
||||
result = G_TYPE_CHECK_INSTANCE_TYPE(obj, GLADE_TYPE_XML())
|
||||
|
||||
proc GLADE_IS_XML_CLASS*(klass: pointer): gboolean =
|
||||
result = G_TYPE_CHECK_CLASS_TYPE(klass, GLADE_TYPE_XML())
|
||||
|
||||
proc GLADE_XML_GET_CLASS*(obj: pointer): PGladeXMLClass =
|
||||
result = cast[PGladeXMLClass](G_TYPE_INSTANCE_GET_CLASS(obj, GLADE_TYPE_XML()))
|
||||
1209
lib/base/gtk/pango.nim
Executable file
1209
lib/base/gtk/pango.nim
Executable file
File diff suppressed because it is too large
Load Diff
46
lib/base/gtk/pangoutils.nim
Executable file
46
lib/base/gtk/pangoutils.nim
Executable file
@@ -0,0 +1,46 @@
|
||||
import
|
||||
glib2, pango
|
||||
|
||||
type
|
||||
pint32* = ptr int32
|
||||
|
||||
proc pango_split_file_list*(str: cstring): PPchar{.cdecl, dynlib: pangolib,
|
||||
importc: "pango_split_file_list".}
|
||||
proc pango_trim_string*(str: cstring): cstring{.cdecl, dynlib: pangolib,
|
||||
importc: "pango_trim_string".}
|
||||
proc pango_read_line*(stream: TFile, str: PGString): gint{.cdecl,
|
||||
dynlib: pangolib, importc: "pango_read_line".}
|
||||
proc pango_skip_space*(pos: PPchar): gboolean{.cdecl, dynlib: pangolib,
|
||||
importc: "pango_skip_space".}
|
||||
proc pango_scan_word*(pos: PPchar, OutStr: PGString): gboolean{.cdecl,
|
||||
dynlib: pangolib, importc: "pango_scan_word".}
|
||||
proc pango_scan_string*(pos: PPchar, OutStr: PGString): gboolean{.cdecl,
|
||||
dynlib: pangolib, importc: "pango_scan_string".}
|
||||
proc pango_scan_int*(pos: PPchar, OutInt: pint32): gboolean{.cdecl,
|
||||
dynlib: pangolib, importc: "pango_scan_int".}
|
||||
when defined(PANGO_ENABLE_BACKEND):
|
||||
proc pango_config_key_get(key: cstring): cstring{.cdecl, dynlib: pangolib,
|
||||
importc: "pango_config_key_get".}
|
||||
proc pango_lookup_aliases(fontname: cstring, families: PPPchar,
|
||||
n_families: pint32){.cdecl, dynlib: pangolib,
|
||||
importc: "pango_lookup_aliases".}
|
||||
proc pango_parse_style*(str: cstring, style: PPangoStyle, warn: gboolean): gboolean{.
|
||||
cdecl, dynlib: pangolib, importc: "pango_parse_style".}
|
||||
proc pango_parse_variant*(str: cstring, variant: PPangoVariant, warn: gboolean): gboolean{.
|
||||
cdecl, dynlib: pangolib, importc: "pango_parse_variant".}
|
||||
proc pango_parse_weight*(str: cstring, weight: PPangoWeight, warn: gboolean): gboolean{.
|
||||
cdecl, dynlib: pangolib, importc: "pango_parse_weight".}
|
||||
proc pango_parse_stretch*(str: cstring, stretch: PPangoStretch, warn: gboolean): gboolean{.
|
||||
cdecl, dynlib: pangolib, importc: "pango_parse_stretch".}
|
||||
when defined(PANGO_ENABLE_BACKEND):
|
||||
proc pango_get_sysconf_subdirectory(): cstring{.cdecl, dynlib: pangolib,
|
||||
importc: "pango_get_sysconf_subdirectory".}
|
||||
proc pango_get_lib_subdirectory(): cstring{.cdecl, dynlib: pangolib,
|
||||
importc: "pango_get_lib_subdirectory".}
|
||||
proc pango_log2vis_get_embedding_levels*(str: Pgunichar, len: int32,
|
||||
pbase_dir: PPangoDirection, embedding_level_list: Pguint8): gboolean{.cdecl,
|
||||
dynlib: pangolib, importc: "pango_log2vis_get_embedding_levels".}
|
||||
proc pango_get_mirror_char*(ch: gunichar, mirrored_ch: Pgunichar): gboolean{.
|
||||
cdecl, dynlib: pangolib, importc: "pango_get_mirror_char".}
|
||||
proc pango_language_get_sample_string*(language: PPangoLanguage): cstring{.
|
||||
cdecl, dynlib: pangolib, importc: "pango_language_get_sample_string".}
|
||||
124
lib/base/nregex.nim
Executable file
124
lib/base/nregex.nim
Executable file
@@ -0,0 +1,124 @@
|
||||
# new implementation of regular expressions
|
||||
|
||||
type
|
||||
TRegexKind = enum
|
||||
regNone,
|
||||
regChar,
|
||||
regSet,
|
||||
regConc,
|
||||
regAlt,
|
||||
regStar,
|
||||
regPlus,
|
||||
regMN,
|
||||
regNewline
|
||||
|
||||
TRegex = record
|
||||
case kind: TRegexKind
|
||||
of regChar: c: char
|
||||
of regSet: s: ref set[char]
|
||||
else: a, b: PRegEx
|
||||
|
||||
PRegEx* = ref TRegEx
|
||||
|
||||
TRegExFlag* = enum ## Flags concerning the semantics of regular expressions
|
||||
reCaseInsensitive, ## case insensitive match
|
||||
reStyleInsensitive ## style insensitive match
|
||||
|
||||
|
||||
TRegExFlags* = set[TRegExFlag]
|
||||
## Flags concerning the semantics of regular expressions
|
||||
|
||||
proc raiseRegex(msg: string) {.noreturn.} =
|
||||
var e: ref Exception
|
||||
new(e)
|
||||
e.msg = msg
|
||||
raise e
|
||||
|
||||
proc compileAux(i: int, s: string, r: PRegEx): int
|
||||
|
||||
proc compileBackslash(i: int, s: string, r: PRegEx): int =
|
||||
var i = i
|
||||
inc(i)
|
||||
case s[i]
|
||||
of 'A'..'Z':
|
||||
of 'a'..'z':
|
||||
of '0':
|
||||
of '1'..'9':
|
||||
|
||||
else:
|
||||
r.kind = regChar
|
||||
r.c = s[i]
|
||||
inc(i)
|
||||
result = i
|
||||
|
||||
proc compileAtom(i: int, s: string, r: PRegEx): int =
|
||||
var i = i
|
||||
case s[i]
|
||||
of '[':
|
||||
inc(i)
|
||||
var inverse = s[i] == '^'
|
||||
if inverse: inc(i)
|
||||
r.kind = regSet
|
||||
new(r.s)
|
||||
while true:
|
||||
case s[i]
|
||||
of '\\': i = compileBackslash(i, s, r)
|
||||
of ']':
|
||||
inc(i)
|
||||
break
|
||||
of '\0':
|
||||
raiseRegex("']' expected")
|
||||
elif s[i+1] == '-':
|
||||
var x = s[i]
|
||||
inc(i, 2)
|
||||
var y = s[i]
|
||||
inc(i)
|
||||
r.s = r.s + {x..y}
|
||||
else:
|
||||
incl(r.s, s[i])
|
||||
inc(i)
|
||||
if inverse:
|
||||
r.s = {'\0'..'\255'} - r.s
|
||||
of '\\':
|
||||
inc(i)
|
||||
i = compileBackslash(i, s, r)
|
||||
of '.':
|
||||
r.kind = regAny
|
||||
inc(i)
|
||||
of '(':
|
||||
inc(i)
|
||||
i = compileAux(i, s, r)
|
||||
if s[i] = ')': inc(i)
|
||||
else: raiseRegex("')' expected")
|
||||
of '\0': nil # do nothing
|
||||
else:
|
||||
r.kind = regChar
|
||||
r.c = s[i]
|
||||
inc(i)
|
||||
result = i
|
||||
|
||||
proc compilePostfix(i: int, s: string, r: PRegEx): int =
|
||||
var i = compileAtom(i, s, r)
|
||||
var a: PRegEx
|
||||
case s[i]
|
||||
of '*':
|
||||
of '+':
|
||||
of '?':
|
||||
else: nil
|
||||
|
||||
proc compileAux(i: int, s: string, r: PRegEx): int =
|
||||
var i = i
|
||||
i = compileAtom(i, s, r)
|
||||
|
||||
while s[i] != '\0':
|
||||
|
||||
result = i
|
||||
|
||||
proc compile*(regex: string, flags: TRegExFlags = {}): PRegEx =
|
||||
## Compiles the string `regex` that represents a regular expression into
|
||||
## an internal data structure that can be used for matching.
|
||||
new(result)
|
||||
var i = compileAux(0, regex, result)
|
||||
if i < len(regex)-1:
|
||||
# not all characters used for the regular expression?
|
||||
raiseRegEx("invalid regular expression")
|
||||
296
lib/base/pcre.nim
Executable file
296
lib/base/pcre.nim
Executable file
@@ -0,0 +1,296 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# This file was created by a complicated procedure which saved me a considerable
|
||||
# amount of time: the pcre.h header was converted to modpcre.h by hand, so that
|
||||
# h2pas could handle it. Then I used pas2mor to generate a Morpork binding.
|
||||
# Unfortunately, I had to fix some things later on; thus don't do all this
|
||||
# again! My manual changes will be lost!
|
||||
|
||||
# Converted by Pas2mor v1.37
|
||||
#
|
||||
# Automatically converted by H2Pas 0.99.16 from modpcre.h
|
||||
# The following command line parameters were used:
|
||||
# -D -c -l pcre.lib -T modpcre.h
|
||||
|
||||
{.compile: "pcre_all.c" .}
|
||||
|
||||
type
|
||||
Pbyte = ptr byte
|
||||
Pchar = CString
|
||||
PPchar = ptr PChar
|
||||
Pint = ptr cint
|
||||
Ppcre* = ptr TPcre
|
||||
Ppcre_callout_block = ptr tpcre_callout_block
|
||||
Ppcre_extra = ptr Tpcre_extra
|
||||
|
||||
#************************************************
|
||||
#* Perl-Compatible Regular Expressions *
|
||||
#************************************************
|
||||
#
|
||||
# Modified by Andreas Rumpf for h2pas.
|
||||
|
||||
# In its original form, this is the .in file that is transformed by
|
||||
# "configure" into pcre.h.
|
||||
#
|
||||
# Copyright (c) 1997-2005 University of Cambridge
|
||||
#
|
||||
# -----------------------------------------------------------------------------
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# * Neither the name of the University of Cambridge nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# The file pcre.h is build by "configure". Do not edit it; instead
|
||||
# make changes to pcre.in.
|
||||
|
||||
const
|
||||
PCRE_MAJOR* = 6
|
||||
PCRE_MINOR* = 3
|
||||
PCRE_DATE* = "2005/11/29"
|
||||
# Options
|
||||
PCRE_CASELESS* = 0x00000001
|
||||
PCRE_MULTILINE* = 0x00000002
|
||||
PCRE_DOTALL* = 0x00000004
|
||||
PCRE_EXTENDED* = 0x00000008
|
||||
PCRE_ANCHORED* = 0x00000010
|
||||
PCRE_DOLLAR_ENDONLY* = 0x00000020
|
||||
PCRE_EXTRA* = 0x00000040
|
||||
PCRE_NOTBOL* = 0x00000080
|
||||
PCRE_NOTEOL* = 0x00000100
|
||||
PCRE_UNGREEDY* = 0x00000200
|
||||
PCRE_NOTEMPTY* = 0x00000400
|
||||
PCRE_UTF8* = 0x00000800
|
||||
PCRE_NO_AUTO_CAPTURE* = 0x00001000
|
||||
PCRE_NO_UTF8_CHECK* = 0x00002000
|
||||
PCRE_AUTO_CALLOUT* = 0x00004000
|
||||
PCRE_PARTIAL* = 0x00008000
|
||||
PCRE_DFA_SHORTEST* = 0x00010000
|
||||
PCRE_DFA_RESTART* = 0x00020000
|
||||
PCRE_FIRSTLINE* = 0x00040000
|
||||
# Exec-time and get/set-time error codes
|
||||
PCRE_ERROR_NOMATCH* = -(1)
|
||||
PCRE_ERROR_NULL* = -(2)
|
||||
PCRE_ERROR_BADOPTION* = -(3)
|
||||
PCRE_ERROR_BADMAGIC* = -(4)
|
||||
PCRE_ERROR_UNKNOWN_NODE* = -(5)
|
||||
PCRE_ERROR_NOMEMORY* = -(6)
|
||||
PCRE_ERROR_NOSUBSTRING* = -(7)
|
||||
PCRE_ERROR_MATCHLIMIT* = -(8)
|
||||
# Never used by PCRE itself
|
||||
PCRE_ERROR_CALLOUT* = -(9)
|
||||
PCRE_ERROR_BADUTF8* = -(10)
|
||||
PCRE_ERROR_BADUTF8_OFFSET* = -(11)
|
||||
PCRE_ERROR_PARTIAL* = -(12)
|
||||
PCRE_ERROR_BADPARTIAL* = -(13)
|
||||
PCRE_ERROR_INTERNAL* = -(14)
|
||||
PCRE_ERROR_BADCOUNT* = -(15)
|
||||
PCRE_ERROR_DFA_UITEM* = -(16)
|
||||
PCRE_ERROR_DFA_UCOND* = -(17)
|
||||
PCRE_ERROR_DFA_UMLIMIT* = -(18)
|
||||
PCRE_ERROR_DFA_WSSIZE* = -(19)
|
||||
PCRE_ERROR_DFA_RECURSE* = -(20)
|
||||
# Request types for pcre_fullinfo()
|
||||
PCRE_INFO_OPTIONS* = 0
|
||||
PCRE_INFO_SIZE* = 1
|
||||
PCRE_INFO_CAPTURECOUNT* = 2
|
||||
PCRE_INFO_BACKREFMAX* = 3
|
||||
PCRE_INFO_FIRSTBYTE* = 4
|
||||
# For backwards compatibility
|
||||
PCRE_INFO_FIRSTCHAR* = 4
|
||||
PCRE_INFO_FIRSTTABLE* = 5
|
||||
PCRE_INFO_LASTLITERAL* = 6
|
||||
PCRE_INFO_NAMEENTRYSIZE* = 7
|
||||
PCRE_INFO_NAMECOUNT* = 8
|
||||
PCRE_INFO_NAMETABLE* = 9
|
||||
PCRE_INFO_STUDYSIZE* = 10
|
||||
PCRE_INFO_DEFAULT_TABLES* = 11
|
||||
# Request types for pcre_config()
|
||||
PCRE_CONFIG_UTF8* = 0
|
||||
PCRE_CONFIG_NEWLINE* = 1
|
||||
PCRE_CONFIG_LINK_SIZE* = 2
|
||||
PCRE_CONFIG_POSIX_MALLOC_THRESHOLD* = 3
|
||||
PCRE_CONFIG_MATCH_LIMIT* = 4
|
||||
PCRE_CONFIG_STACKRECURSE* = 5
|
||||
PCRE_CONFIG_UNICODE_PROPERTIES* = 6
|
||||
# Bit flags for the pcre_extra structure
|
||||
PCRE_EXTRA_STUDY_DATA* = 0x0001
|
||||
PCRE_EXTRA_MATCH_LIMIT* = 0x0002
|
||||
PCRE_EXTRA_CALLOUT_DATA* = 0x0004
|
||||
PCRE_EXTRA_TABLES* = 0x0008
|
||||
# Types
|
||||
|
||||
type
|
||||
TPcre = record
|
||||
#undefined structure
|
||||
|
||||
|
||||
# The structure for passing additional data to pcre_exec(). This is defined
|
||||
# in such as way as to be extensible. Always add new fields at the end,
|
||||
# in order to remain compatible.
|
||||
# Bits for which fields are set
|
||||
# Opaque data from pcre_study()
|
||||
# Maximum number of calls to match()
|
||||
# Data passed back in callouts
|
||||
# Const before type ignored
|
||||
# Pointer to character tables
|
||||
Tpcre_extra* = record
|
||||
flags: cuint
|
||||
study_data: pointer
|
||||
match_limit: cuint
|
||||
callout_data: pointer
|
||||
tables: ptr byte
|
||||
|
||||
# The structure for passing out data via the pcre_callout_function. We use a
|
||||
# structure so that new fields can be added on the end in future versions,
|
||||
# without changing the API of the function, thereby allowing old clients to
|
||||
# work without modification.
|
||||
# Identifies version of block
|
||||
# ------------------------ Version 0 -------------------------------
|
||||
# Number compiled into pattern
|
||||
# The offset vector
|
||||
# Const before type ignored
|
||||
# The subject being matched
|
||||
# The length of the subject
|
||||
# Offset to start of this match attempt
|
||||
# Where we currently are in the subject
|
||||
# Max current capture
|
||||
# Most recently closed capture
|
||||
# Data passed in with the call
|
||||
# ------------------- Added for Version 1 --------------------------
|
||||
# Offset to next item in the pattern
|
||||
# Length of next item in the pattern
|
||||
# ------------------------------------------------------------------
|
||||
TPcre_callout_block* = record
|
||||
version: cint
|
||||
callout_number: cint
|
||||
offset_vector: ptr cint
|
||||
subject: ptr char
|
||||
subject_length: cint
|
||||
start_match: cint
|
||||
current_position: cint
|
||||
capture_top: cint
|
||||
capture_last: cint
|
||||
callout_data: pointer
|
||||
pattern_position: cint
|
||||
next_item_length: cint
|
||||
|
||||
# Exported PCRE functions
|
||||
|
||||
proc pcre_compile*(para1: Pchar, para2: cint, para3: ptr Pchar,
|
||||
para4: Pint, para5: Pbyte): Ppcre {.
|
||||
importc: "pcre_compile", noconv.}
|
||||
|
||||
proc pcre_compile2*(para1: Pchar, para2: cint, para3: Pint, para4: PPchar,
|
||||
para5: Pint, para6: Pbyte): Ppcre {.
|
||||
importc: "pcre_compile2", noconv.}
|
||||
|
||||
proc pcre_config*(para1: cint, para2: pointer): cint {.
|
||||
importc: "pcre_config", noconv.}
|
||||
|
||||
proc pcre_copy_named_substring*(para1: Ppcre, para2: Pchar, para3: Pint,
|
||||
para4: cint, para5: Pchar, para6: Pchar,
|
||||
para7: cint): cint {.
|
||||
importc: "pcre_copy_named_substring", noconv.}
|
||||
|
||||
proc pcre_copy_substring*(para1: Pchar, para2: Pint, para3: cint, para4: cint,
|
||||
para5: Pchar, para6: cint): cint {.
|
||||
importc: "pcre_copy_substring", noconv.}
|
||||
|
||||
proc pcre_dfa_exec*(para1: Ppcre, para2: Ppcre_extra, para3: Pchar,
|
||||
para4: cint, para5: cint, para6: cint, para7: Pint,
|
||||
para8: cint, para9: Pint, para10: cint): cint {.
|
||||
importc: "pcre_dfa_exec", noconv.}
|
||||
|
||||
proc pcre_exec*(para1: Ppcre, para2: Ppcre_extra, para3: Pchar,
|
||||
para4: cint, para5: cint, para6: cint, para7: Pint,
|
||||
para8: cint): cint {.importc: "pcre_exec", noconv.}
|
||||
|
||||
proc pcre_free_substring*(para1: Pchar) {.
|
||||
importc: "pcre_free_substring", noconv.}
|
||||
|
||||
proc pcre_free_substring_list*(para1: PPchar) {.
|
||||
importc: "pcre_free_substring_list", noconv.}
|
||||
|
||||
proc pcre_fullinfo*(para1: Ppcre, para2: Ppcre_extra, para3: cint,
|
||||
para4: pointer): cint {.importc: "pcre_fullinfo", noconv.}
|
||||
|
||||
proc pcre_get_named_substring*(para1: Ppcre, para2: Pchar, para3: Pint,
|
||||
para4: cint, para5: Pchar, para6: PPchar): cint {.
|
||||
importc: "pcre_get_named_substring", noconv.}
|
||||
|
||||
proc pcre_get_stringnumber*(para1: Ppcre, para2: Pchar): cint {.
|
||||
importc: "pcre_get_stringnumber", noconv.}
|
||||
|
||||
proc pcre_get_substring*(para1: Pchar, para2: Pint, para3: cint,
|
||||
para4: cint, para5: PPchar): cint {.
|
||||
importc: "pcre_get_substring", noconv.}
|
||||
|
||||
proc pcre_get_substring_list*(para1: Pchar, para2: Pint, para3: cint,
|
||||
para4: ptr PPchar): cint {.
|
||||
importc: "pcre_get_substring_list", noconv.}
|
||||
|
||||
proc pcre_info*(para1: Ppcre, para2: Pint, para3: Pint): cint {.
|
||||
importc: "pcre_info", noconv.}
|
||||
|
||||
proc pcre_maketables*: ptr byte {.
|
||||
importc: "pcre_maketables", noconv.}
|
||||
|
||||
proc pcre_refcount*(para1: Ppcre, para2: cint): cint {.
|
||||
importc: "pcre_refcount", noconv.}
|
||||
|
||||
proc pcre_study*(para1: Ppcre, para2: cint,
|
||||
para3: ptr CString): Ppcre_extra {.importc, noconv.}
|
||||
|
||||
proc pcre_version*: CString {.importc: "pcre_version", noconv.}
|
||||
|
||||
# Indirection for store get and free functions. These can be set to
|
||||
# alternative malloc/free functions if required. Special ones are used in the
|
||||
# non-recursive case for "frames". There is also an optional callout function
|
||||
# that is triggered by the (?) regex item.
|
||||
#
|
||||
|
||||
# we use Nimrod's memory manager (but not GC!) for these functions:
|
||||
var
|
||||
pcre_malloc {.importc: "pcre_malloc".}: proc (para1: int): pointer {.noconv.}
|
||||
pcre_free {.importc: "pcre_free".}: proc (para1: pointer) {.noconv.}
|
||||
pcre_stack_malloc {.importc: "pcre_stack_malloc".}:
|
||||
proc (para1: int): pointer {.noconv.}
|
||||
pcre_stack_free {.importc: "pcre_stack_free".}:
|
||||
proc (para1: pointer) {.noconv.}
|
||||
pcre_callout {.importc: "pcre_callout".}:
|
||||
proc (para1: Ppcre_callout_block): cint {.noconv.}
|
||||
|
||||
pcre_malloc = system.alloc
|
||||
pcre_free = system.dealloc
|
||||
pcre_stack_malloc = system.alloc
|
||||
pcre_stack_free = system.dealloc
|
||||
pcre_callout = nil
|
||||
30072
lib/base/pcre_all.c
Executable file
30072
lib/base/pcre_all.c
Executable file
File diff suppressed because it is too large
Load Diff
114
lib/base/regexprs.nim
Executable file
114
lib/base/regexprs.nim
Executable file
@@ -0,0 +1,114 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Regular expression support for Nimrod.
|
||||
## Currently this module is implemented by providing a wrapper around the
|
||||
## `PRCE (Perl-Compatible Regular Expressions) <http://www.pcre.org>`_
|
||||
## C library. This means that your application will depend on the PRCE
|
||||
## library's licence when using this module, which should not be a problem
|
||||
## though.
|
||||
## PRCE's licence follows:
|
||||
##
|
||||
## .. include:: ../doc/regexprs.txt
|
||||
##
|
||||
|
||||
# This is not just a convenient wrapper for the pcre library; the
|
||||
# API will stay the same if the implementation should change.
|
||||
|
||||
import
|
||||
pcre, strutils
|
||||
|
||||
type
|
||||
EInvalidRegEx* = object of EInvalidValue
|
||||
## is raised if the pattern is no valid regular expression.
|
||||
|
||||
const
|
||||
MaxSubpatterns* = 10
|
||||
## defines the maximum number of subpatterns that can be captured.
|
||||
## More subpatterns cannot be captured!
|
||||
|
||||
proc match*(s, pattern: string, substrs: var openarray[string],
|
||||
start: int = 0): bool
|
||||
## returns ``true`` if ``s`` matches the ``pattern[start..]`` and
|
||||
## the captured substrings in the array ``substrs``. If it does not
|
||||
## match, nothing is written into ``substrs`` and ``false`` is
|
||||
## returned.
|
||||
|
||||
proc match*(s, pattern: string, start: int = 0): bool
|
||||
## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``.
|
||||
|
||||
proc matchLen*(s, pattern: string, substrs: var openarray[string],
|
||||
start: int = 0): int
|
||||
## the same as ``match``, but it returns the length of the match,
|
||||
## if there is no match, -1 is returned. Note that a match length
|
||||
## of zero can happen.
|
||||
|
||||
proc find*(s, pattern: string, substrs: var openarray[string],
|
||||
start: int = 0): bool
|
||||
## returns ``true`` if ``pattern`` occurs in ``s`` and the captured
|
||||
## substrings in the array ``substrs``. If it does not match, nothing
|
||||
## is written into ``substrs``.
|
||||
proc find*(s, pattern: string, start: int = 0): bool
|
||||
## returns ``true`` if ``pattern`` occurs in ``s``.
|
||||
|
||||
|
||||
proc rawCompile(pattern: string, flags: cint): PPcre =
|
||||
var
|
||||
msg: CString
|
||||
offset: cint
|
||||
com = pcreCompile(pattern, flags, addr(msg), addr(offset), nil)
|
||||
if com == nil:
|
||||
var e: ref EInvalidRegEx
|
||||
new(e)
|
||||
e.msg = $msg & "\n" & pattern & "\n" & repeatChar(offset) & "^\n"
|
||||
raise e
|
||||
return com
|
||||
|
||||
proc matchOrFind(s: string, pattern: PPcre, substrs: var openarray[string],
|
||||
start: cint): cint =
|
||||
var
|
||||
rawMatches: array [0..maxSubpatterns * 3 - 1, cint]
|
||||
res = int(pcreExec(pattern, nil, s, length(s), start, 0,
|
||||
cast[pint](addr(rawMatches)), maxSubpatterns * 3))
|
||||
dealloc(pattern)
|
||||
if res < 0: return res
|
||||
for i in 0..res-1:
|
||||
var
|
||||
a = rawMatches[i * 3]
|
||||
b = rawMatches[i * 3 + 1]
|
||||
if a >= 0: substrs[i] = copy(s, a, b)
|
||||
else: substrs[i] = ""
|
||||
return res
|
||||
|
||||
proc matchOrFind(s: string, pattern: PPcre, start: cint): cint =
|
||||
var
|
||||
rawMatches: array [0..maxSubpatterns * 3 - 1, cint]
|
||||
res = pcreExec(pattern, nil, s, length(s), start, 0,
|
||||
cast[pint](addr(rawMatches)), maxSubpatterns * 3)
|
||||
dealloc(pattern)
|
||||
return res
|
||||
|
||||
proc match(s, pattern: string, substrs: var openarray[string],
|
||||
start: int = 0): bool =
|
||||
return matchOrFind(s, rawCompile(pattern, PCRE_ANCHORED),
|
||||
substrs, start) >= 0
|
||||
|
||||
proc matchLen(s, pattern: string, substrs: var openarray[string],
|
||||
start: int = 0): int =
|
||||
return matchOrFind(s, rawCompile(pattern, PCRE_ANCHORED), substrs, start)
|
||||
|
||||
proc find(s, pattern: string, substrs: var openarray[string],
|
||||
start: int = 0): bool =
|
||||
return matchOrFind(s, rawCompile(pattern, 0), substrs, start) >= 0
|
||||
|
||||
proc match(s, pattern: string, start: int = 0): bool =
|
||||
return matchOrFind(s, rawCompile(pattern, PCRE_ANCHORED), start) >= 0
|
||||
|
||||
proc find(s, pattern: string, start: int = 0): bool =
|
||||
return matchOrFind(s, rawCompile(pattern, 0), start) >= 0
|
||||
20
lib/cntbits.nim
Executable file
20
lib/cntbits.nim
Executable file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
proc population16(a: int): int {.inline.} =
|
||||
var x = a
|
||||
x = ((x and 0xAAAA) shr 1) + (x and 0x5555)
|
||||
x = ((x and 0xCCCC) shr 2) + (x and 0x3333)
|
||||
x = ((x and 0xF0F0) shr 4) + (x and 0x0F0F)
|
||||
x = ((x and 0xFF00) shr 8) + (x and 0x00FF)
|
||||
return x
|
||||
|
||||
proc countBits(n: int32): int =
|
||||
result = population16(n and 0xffff) + population16(n shr 16)
|
||||
108
lib/complex.nim
Executable file
108
lib/complex.nim
Executable file
@@ -0,0 +1,108 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
|
||||
## This module implements complex numbers.
|
||||
|
||||
{.push checks:off, line_dir:off, stack_trace:off, debugger:off.}
|
||||
# the user does not want to trace a part
|
||||
# of the standard library!
|
||||
|
||||
import
|
||||
math
|
||||
|
||||
type
|
||||
TComplex* = record ## a complex number, consisting of a real and an
|
||||
## imaginary part
|
||||
re*: float ## real part of the complex number
|
||||
im*: float ## imarginary part of the complex number
|
||||
|
||||
proc `==` *(x, y: TComplex): bool =
|
||||
## Compare two complex numbers `x` and `y` for equality.
|
||||
result = x.re == y.re and x.im == y.im
|
||||
|
||||
proc `+` *(x, y: TComplex): TComplex =
|
||||
## Add two complex numbers.
|
||||
result.re = x.re + y.re
|
||||
result.im = x.im + y.im
|
||||
|
||||
proc `-` *(x, y: TComplex): TComplex =
|
||||
## Subtract two complex numbers.
|
||||
result.re = x.re - y.re
|
||||
result.im = x.im - y.im
|
||||
|
||||
proc `-` *(z: TComplex): TComplex =
|
||||
## Unary minus for complex numbers.
|
||||
result.re = -z.re
|
||||
result.im = -z.im
|
||||
|
||||
proc `/` *(x, y: TComplex): TComplex =
|
||||
## Divide `x` by `y`.
|
||||
var
|
||||
r, den: float
|
||||
if abs(y.re) < abs(y.im):
|
||||
r = y.re / y.im
|
||||
den = y.im + r * y.re
|
||||
result.re = (x.re * r + x.im) / den
|
||||
result.im = (x.im * r - x.re) / den
|
||||
else:
|
||||
r = y.im / y.re
|
||||
den = y.re + r * y.im
|
||||
result.re = (x.re + r * x.im) / den
|
||||
result.im = (x.im - r * x.re) / den
|
||||
|
||||
proc `*` *(x, y: TComplex): TComplex =
|
||||
## Multiply `x` with `y`.
|
||||
result.re = x.re * y.re - x.im * y.im
|
||||
result.im = x.im * y.re + x.re * y.im
|
||||
|
||||
proc abs*(z: TComplex): float =
|
||||
## Return the distance from (0,0) to `z`.
|
||||
|
||||
# optimized by checking special cases (sqrt is expensive)
|
||||
var x, y, temp: float
|
||||
|
||||
x = abs(z.re)
|
||||
y = abs(z.im)
|
||||
if x == 0.0:
|
||||
result = y
|
||||
elif y == 0.0:
|
||||
result = x
|
||||
elif x > y:
|
||||
temp = y / x
|
||||
result = x * sqrt(1.0 + temp * temp)
|
||||
else:
|
||||
temp = x / y
|
||||
result = y * sqrt(1.0 + temp * temp)
|
||||
|
||||
proc sqrt*(z: TComplex): TComplex =
|
||||
## Square root for a complex number `z`.
|
||||
var x, y, w, r: float
|
||||
|
||||
if z.re == 0.0 and z.im == 0.0:
|
||||
result = z
|
||||
else:
|
||||
x = abs(z.re)
|
||||
y = abs(z.im)
|
||||
if x >= y:
|
||||
r = y / x
|
||||
w = sqrt(x) * sqrt(0.5 * (1.0 + sqrt(1.0 + r * r)))
|
||||
else:
|
||||
r = x / y
|
||||
w = sqrt(y) * sqrt(0.5 * (r + sqrt(1.0 + r * r)))
|
||||
if z.re >= 0.0:
|
||||
result.re = w
|
||||
result.im = z.im / (w * 2)
|
||||
else:
|
||||
if z.im >= 0.0: result.im = w
|
||||
else: result.im = -w
|
||||
result.re = z.im / (c.im + c.im)
|
||||
|
||||
{.pop.}
|
||||
29
lib/copying.txt
Executable file
29
lib/copying.txt
Executable file
@@ -0,0 +1,29 @@
|
||||
=======================================================
|
||||
The Nimrod Runtime Library
|
||||
Copyright (C) 2004-2007 Andreas Rumpf
|
||||
=======================================================
|
||||
|
||||
This is the file copying.txt, it applies to the Nimrod Run-Time Library
|
||||
(lib) and base packages (base) distributed by members of the Nimrod
|
||||
Development Team.
|
||||
|
||||
The source code of the Nimrod Runtime Libraries and packages are
|
||||
distributed under the Library GNU General Public License
|
||||
(see the file lgpl.txt) with the following modification:
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent modules,
|
||||
and to copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the terms
|
||||
and conditions of the license of that module. An independent module is a module
|
||||
which is not derived from or based on this library. If you modify this
|
||||
library, you may extend this exception to your version of the library, but
|
||||
you are not obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
If you didn't receive a copy of the file lgpl.txt, contact:
|
||||
Free Software Foundation
|
||||
675 Mass Ave
|
||||
Cambridge, MA 02139
|
||||
USA
|
||||
499
lib/debugger.nim
Executable file
499
lib/debugger.nim
Executable file
@@ -0,0 +1,499 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# This file implements the embedded debugger that can be linked
|
||||
# with the application. We should not use dynamic memory here as that
|
||||
# would interfere with the GC and trigger ON/OFF errors if the
|
||||
# user program corrupts memory. Unfortunately, for dispaying
|
||||
# variables we use the system.repr() proc which uses Nimrod
|
||||
# strings and thus allocates memory from the heap. Pity, but
|
||||
# I do not want to implement repr() twice. We also cannot deactivate
|
||||
# the GC here as that might run out of memory too quickly...
|
||||
|
||||
type
|
||||
TDbgState = enum
|
||||
dbOff, # debugger is turned off
|
||||
dbStepInto, # debugger is in tracing mode
|
||||
dbStepOver,
|
||||
dbSkipCurrent,
|
||||
dbQuiting, # debugger wants to quit
|
||||
dbBreakpoints # debugger is only interested in breakpoints
|
||||
|
||||
TDbgBreakpoint = record
|
||||
low, high: int # range from low to high; if disabled
|
||||
# both low and high are set to their negative values
|
||||
# this makes the check faster and safes memory
|
||||
filename: string
|
||||
name: string # name of breakpoint
|
||||
|
||||
TVarSlot {.compilerproc.} = record # variable slots used for debugger:
|
||||
address: pointer
|
||||
typ: PNimType
|
||||
name: cstring # for globals this is "module.name"
|
||||
|
||||
PExtendedFrame = ptr TExtendedFrame
|
||||
TExtendedFrame = record # If the debugger is enabled the compiler provides
|
||||
# an extended frame. Of course only slots that are
|
||||
# needed are allocated and not 10_000, except for
|
||||
# the global data description.
|
||||
f: TFrame
|
||||
slots: array[0..10_000, TVarSlot]
|
||||
|
||||
var
|
||||
dbgInSignal: bool # wether the debugger is in the signal handler
|
||||
dbgIn: TFile # debugger input stream
|
||||
dbgUser: string = "s" # buffer for user input; first command is ``step_into``
|
||||
# needs to be global cause we store the last command
|
||||
# in it
|
||||
dbgState: TDbgState = dbStepInto # state of debugger
|
||||
dbgBP: array[0..127, TDbgBreakpoint] # breakpoints
|
||||
dbgBPlen: int = 0
|
||||
|
||||
dbgSkipToFrame: PFrame # frame to be skipped to
|
||||
|
||||
dbgGlobalData: TExtendedFrame # this reserves much space, but
|
||||
# for now it is the most practical way
|
||||
|
||||
maxDisplayRecDepth: int = 5 # do not display too much data!
|
||||
|
||||
proc findBreakpoint(name: string): int =
|
||||
# returns -1 if not found
|
||||
for i in countdown(dbgBPlen-1, 0):
|
||||
if name == dbgBP[i].name: return i
|
||||
return -1
|
||||
|
||||
proc ListBreakPoints() =
|
||||
write(stdout, "*** emdb| Breakpoints:\n")
|
||||
for i in 0 .. dbgBPlen-1:
|
||||
write(stdout, dbgBP[i].name & ": " & $abs(dbgBP[i].low) & ".." &
|
||||
$abs(dbgBP[i].high) & dbgBP[i].filename)
|
||||
if dbgBP[i].low < 0:
|
||||
write(stdout, " [disabled]\n")
|
||||
else:
|
||||
write(stdout, "\n")
|
||||
write(stdout, "***\n")
|
||||
|
||||
proc openAppend(filename: string): TFile =
|
||||
if openFile(result, filename, fmAppend):
|
||||
write(result, "----------------------------------------\n")
|
||||
|
||||
proc dbgRepr(p: pointer, typ: PNimType): string =
|
||||
var
|
||||
cl: TReprClosure
|
||||
initReprClosure(cl)
|
||||
cl.recDepth = maxDisplayRecDepth
|
||||
# locks for the GC turned out to be a bad idea...
|
||||
# inc(recGcLock)
|
||||
result = ""
|
||||
reprAux(result, p, typ, cl)
|
||||
# dec(recGcLock)
|
||||
deinitReprClosure(cl)
|
||||
|
||||
proc writeVariable(stream: TFile, slot: TVarSlot) =
|
||||
write(stream, slot.name)
|
||||
write(stream, " = ")
|
||||
writeln(stream, dbgRepr(slot.address, slot.typ))
|
||||
|
||||
proc ListFrame(stream: TFile, f: PExtendedFrame) =
|
||||
write(stream, "*** emdb| Frame (" & $f.f.len & " slots):\n")
|
||||
for i in 0 .. f.f.len-1:
|
||||
writeVariable(stream, f.slots[i])
|
||||
write(stream, "***\n")
|
||||
|
||||
proc ListVariables(stream: TFile, f: PExtendedFrame) =
|
||||
write(stream, "*** emdb| Frame (" & $f.f.len & " slots):\n")
|
||||
for i in 0 .. f.f.len-1:
|
||||
writeln(stream, f.slots[i].name)
|
||||
write(stream, "***\n")
|
||||
|
||||
proc debugOut(msg: cstring) =
|
||||
# the *** *** markers are for easy recognition of debugger
|
||||
# output for external frontends.
|
||||
write(stdout, "*** emdb| ")
|
||||
write(stdout, msg)
|
||||
write(stdout, "***\n")
|
||||
|
||||
proc dbgFatal(msg: cstring) =
|
||||
debugOut(msg)
|
||||
dbgAborting = True # the debugger wants to abort
|
||||
quit(1)
|
||||
|
||||
proc findVariable(frame: PExtendedFrame, varname: cstring): int =
|
||||
for i in 0 .. frame.f.len - 1:
|
||||
if c_strcmp(frame.slots[i].name, varname) == 0: return i
|
||||
return -1
|
||||
|
||||
proc dbgShowCurrentProc(dbgFramePointer: PFrame) =
|
||||
if dbgFramePointer != nil:
|
||||
write(stdout, "*** emdb| now in proc: ")
|
||||
write(stdout, dbgFramePointer.procname)
|
||||
write(stdout, " ***\n")
|
||||
else:
|
||||
write(stdout, "*** emdb| (procedure name not available) ***\n")
|
||||
|
||||
proc dbgShowExecutionPoint() =
|
||||
write(stdout, "*** emdb| " & $framePtr.filename & "(" & $framePtr.line &
|
||||
") " & $framePtr.procname & " ***\n")
|
||||
|
||||
when defined(windows) or defined(dos) or defined(os2):
|
||||
{.define: FileSystemCaseInsensitive.}
|
||||
|
||||
proc fileMatches(c, bp: cstring): bool =
|
||||
# bp = breakpoint filename
|
||||
# c = current filename
|
||||
# we consider it a match if bp is a suffix of c
|
||||
# and the character for the suffix does not exist or
|
||||
# is one of: \ / :
|
||||
# depending on the OS case does not matter!
|
||||
var blen: int = c_strlen(bp)
|
||||
var clen: int = c_strlen(c)
|
||||
if blen > clen: return false
|
||||
# check for \ / :
|
||||
if clen-blen-1 >= 0 and c[clen-blen-1] notin {'\\', '/', ':'}:
|
||||
return false
|
||||
var i = 0
|
||||
while i < blen:
|
||||
var x, y: char
|
||||
x = bp[i]
|
||||
y = c[i+clen-blen]
|
||||
when defined(FileSystemCaseInsensitive):
|
||||
if x >= 'A' and x <= 'Z': x = chr(ord(x) - ord('A') + ord('a'))
|
||||
if y >= 'A' and y <= 'Z': y = chr(ord(y) - ord('A') + ord('a'))
|
||||
if x != y: return false
|
||||
inc(i)
|
||||
return true
|
||||
|
||||
proc dbgBreakpointReached(line: int): int =
|
||||
for i in 0..dbgBPlen-1:
|
||||
if line >= dbgBP[i].low and line <= dbgBP[i].high and
|
||||
fileMatches(framePtr.filename, dbgBP[i].filename): return i
|
||||
return -1
|
||||
|
||||
proc scanAndAppendWord(src: string, a: var string, start: int): int =
|
||||
result = start
|
||||
# skip whitespace:
|
||||
while src[result] in {'\t', ' '}: inc(result)
|
||||
while True:
|
||||
case src[result]
|
||||
of 'a'..'z', '0'..'9': add(a, src[result])
|
||||
of '_': nil # just skip it
|
||||
of 'A'..'Z': add(a, chr(ord(src[result]) - ord('A') + ord('a')))
|
||||
else: break
|
||||
inc(result)
|
||||
|
||||
proc scanWord(src: string, a: var string, start: int): int =
|
||||
a = ""
|
||||
result = scanAndAppendWord(src, a, start)
|
||||
|
||||
proc scanFilename(src: string, a: var string, start: int): int =
|
||||
result = start
|
||||
a = ""
|
||||
# skip whitespace:
|
||||
while src[result] in {'\t', ' '}: inc(result)
|
||||
while src[result] notin {'\t', ' ', '\0'}:
|
||||
add(a, src[result])
|
||||
inc(result)
|
||||
|
||||
proc scanNumber(src: string, a: var int, start: int): int =
|
||||
result = start
|
||||
a = 0
|
||||
while src[result] in {'\t', ' '}: inc(result)
|
||||
while true:
|
||||
case src[result]
|
||||
of '0'..'9': a = a * 10 + ord(src[result]) - ord('0')
|
||||
of '_': nil # skip underscores (nice for long line numbers)
|
||||
else: break
|
||||
inc(result)
|
||||
|
||||
proc dbgHelp() =
|
||||
debugOut("""
|
||||
list of commands (see the manual for further help):
|
||||
GENERAL
|
||||
h, help display this help message
|
||||
q, quit quit the debugger and the program
|
||||
<ENTER> repeat the previous debugger command
|
||||
EXECUTING
|
||||
s, stepinto single step, stepping into routine calls
|
||||
n, stepover single step, without stepping into routine calls
|
||||
f, skipcurrent continue execution until the current routine finishes
|
||||
c, continue continue execution until the next breakpoint
|
||||
i, ignore continue execution, ignore all breakpoints
|
||||
BREAKPOINTS
|
||||
b, setbreak <name> [fromline [toline]] [file]
|
||||
set a new breakpoint named 'name' for line and file
|
||||
if line or file are omitted the current one is used
|
||||
breakpoints display the entire breakpoint list
|
||||
disable <name> disable a breakpoint
|
||||
enable <name> enable a breakpoint
|
||||
DATA DISPLAY
|
||||
e, eval <exp> evaluate the expression <exp>
|
||||
o, out <file> <exp> evaluate <exp> and write it to <file>
|
||||
w, where display the current execution point
|
||||
stackframe [file] display current stack frame [and write it to file]
|
||||
u, up go up in the call stack
|
||||
d, down go down in the call stack
|
||||
callstack display the entire call stack
|
||||
l, locals display available local variables
|
||||
g, globals display available global variables
|
||||
maxdisplay <integer> set the display's recursion maximum
|
||||
""")
|
||||
|
||||
proc InvalidCommand() =
|
||||
debugOut("[Warning] invalid command ignored (type 'h' for help) ")
|
||||
|
||||
proc hasExt(s: string): bool =
|
||||
# returns true if s has a filename extension
|
||||
for i in countdown(len(s)-1, 0):
|
||||
if s[i] == '.': return true
|
||||
return false
|
||||
|
||||
proc setBreakPoint(s: string, start: int) =
|
||||
var dbgTemp: string
|
||||
var i = scanWord(s, dbgTemp, start)
|
||||
if i <= start:
|
||||
InvalidCommand()
|
||||
return
|
||||
if dbgBPlen >= high(dbgBP):
|
||||
debugOut("[Warning] no breakpoint could be set; out of breakpoint space ")
|
||||
return
|
||||
var x = dbgBPlen
|
||||
inc(dbgBPlen)
|
||||
dbgBP[x].name = dbgTemp
|
||||
i = scanNumber(s, dbgBP[x].low, i)
|
||||
if dbgBP[x].low == 0:
|
||||
# set to current line:
|
||||
dbgBP[x].low = framePtr.line
|
||||
i = scanNumber(s, dbgBP[x].high, i)
|
||||
if dbgBP[x].high == 0: # set to low:
|
||||
dbgBP[x].high = dbgBP[x].low
|
||||
i = scanFilename(s, dbgTemp, i)
|
||||
if not (dbgTemp.len == 0):
|
||||
if not hasExt(dbgTemp): add(dbgTemp, ".nim")
|
||||
dbgBP[x].filename = dbgTemp
|
||||
else: # use current filename
|
||||
dbgBP[x].filename = $framePtr.filename
|
||||
# skip whitespace:
|
||||
while s[i] in {' ', '\t'}: inc(i)
|
||||
if s[i] != '\0':
|
||||
dec(dbgBPLen) # remove buggy breakpoint
|
||||
InvalidCommand()
|
||||
|
||||
proc BreakpointSetEnabled(s: string, start, enabled: int) =
|
||||
var dbgTemp: string
|
||||
var i = scanWord(s, dbgTemp, start)
|
||||
if i <= start:
|
||||
InvalidCommand()
|
||||
return
|
||||
var x = findBreakpoint(dbgTemp)
|
||||
if x < 0: debugOut("[Warning] breakpoint does not exist ")
|
||||
elif enabled * dbgBP[x].low < 0: # signs are different?
|
||||
dbgBP[x].low = -dbgBP[x].low
|
||||
dbgBP[x].high = -dbgBP[x].high
|
||||
|
||||
proc dbgEvaluate(stream: TFile, s: string, start: int,
|
||||
currFrame: PExtendedFrame) =
|
||||
var dbgTemp: string
|
||||
var i = scanWord(s, dbgTemp, start)
|
||||
while s[i] in {' ', '\t'}: inc(i)
|
||||
var f = currFrame
|
||||
if s[i] == '.':
|
||||
inc(i) # skip '.'
|
||||
add(dbgTemp, '.')
|
||||
i = scanAndAppendWord(s, dbgTemp, i)
|
||||
# search for global var:
|
||||
f = addr(dbgGlobalData)
|
||||
if s[i] != '\0':
|
||||
debugOut("[Warning] could not parse expr ")
|
||||
return
|
||||
var j = findVariable(f, dbgTemp)
|
||||
if j < 0:
|
||||
debugOut("[Warning] could not find variable ")
|
||||
return
|
||||
writeVariable(stream, f.slots[j])
|
||||
|
||||
proc dbgOut(s: string, start: int, currFrame: PExtendedFrame) =
|
||||
var dbgTemp: string
|
||||
var i = scanFilename(s, dbgTemp, start)
|
||||
if dbgTemp.len == 0:
|
||||
InvalidCommand()
|
||||
return
|
||||
var stream = openAppend(dbgTemp)
|
||||
if stream == nil:
|
||||
debugOut("[Warning] could not open or create file ")
|
||||
return
|
||||
dbgEvaluate(stream, s, i, currFrame)
|
||||
closeFile(stream)
|
||||
|
||||
proc dbgStackFrame(s: string, start: int, currFrame: PExtendedFrame) =
|
||||
var dbgTemp: string
|
||||
var i = scanFilename(s, dbgTemp, start)
|
||||
if dbgTemp.len == 0:
|
||||
# just write it to stdout:
|
||||
ListFrame(stdout, currFrame)
|
||||
else:
|
||||
var stream = openAppend(dbgTemp)
|
||||
if stream == nil:
|
||||
debugOut("[Warning] could not open or create file ")
|
||||
return
|
||||
ListFrame(stream, currFrame)
|
||||
closeFile(stream)
|
||||
|
||||
proc CommandPrompt() =
|
||||
# if we return from this routine, user code executes again
|
||||
var
|
||||
again: bool = True
|
||||
dbgFramePtr = framePtr # for going down and up the stack
|
||||
dbgDown: int = 0 # how often we did go down
|
||||
|
||||
while again:
|
||||
write(stdout, "*** emdb| >>")
|
||||
var tmp = readLine(stdin)
|
||||
if tmp.len > 0: dbgUser = tmp
|
||||
# now look what we have to do:
|
||||
var dbgTemp: string
|
||||
var i = scanWord(dbgUser, dbgTemp, 0)
|
||||
case dbgTemp
|
||||
of "": InvalidCommand()
|
||||
of "s", "stepinto":
|
||||
dbgState = dbStepInto
|
||||
again = false
|
||||
of "n", "stepover":
|
||||
dbgState = dbStepOver
|
||||
dbgSkipToFrame = framePtr
|
||||
again = false
|
||||
of "f", "skipcurrent":
|
||||
dbgState = dbSkipCurrent
|
||||
dbgSkipToFrame = framePtr.prev
|
||||
again = false
|
||||
of "c", "continue":
|
||||
dbgState = dbBreakpoints
|
||||
again = false
|
||||
of "i", "ignore":
|
||||
dbgState = dbOff
|
||||
again = false
|
||||
of "h", "help":
|
||||
dbgHelp()
|
||||
of "q", "quit":
|
||||
dbgState = dbQuiting
|
||||
dbgAborting = True
|
||||
again = false
|
||||
quit(1) # BUGFIX: quit with error code > 0
|
||||
of "e", "eval":
|
||||
dbgEvaluate(stdout, dbgUser, i, cast[PExtendedFrame](dbgFramePtr))
|
||||
of "o", "out":
|
||||
dbgOut(dbgUser, i, cast[PExtendedFrame](dbgFramePtr))
|
||||
of "stackframe":
|
||||
dbgStackFrame(dbgUser, i, cast[PExtendedFrame](dbgFramePtr))
|
||||
of "w", "where":
|
||||
dbgShowExecutionPoint()
|
||||
of "l", "locals":
|
||||
ListVariables(stdout, cast[PExtendedFrame](dbgFramePtr))
|
||||
of "g", "globals":
|
||||
ListVariables(stdout, addr(dbgGlobalData))
|
||||
of "u", "up":
|
||||
if dbgDown <= 0:
|
||||
debugOut("[Warning] cannot go up any further ")
|
||||
else:
|
||||
dbgFramePtr = framePtr
|
||||
for j in 0 .. dbgDown-2: # BUGFIX
|
||||
dbgFramePtr = dbgFramePtr.prev
|
||||
dec(dbgDown)
|
||||
dbgShowCurrentProc(dbgFramePtr)
|
||||
of "d", "down":
|
||||
if dbgFramePtr != nil:
|
||||
inc(dbgDown)
|
||||
dbgFramePtr = dbgFramePtr.prev
|
||||
dbgShowCurrentProc(dbgFramePtr)
|
||||
else:
|
||||
debugOut("[Warning] cannot go down any further ")
|
||||
of "callstack":
|
||||
WriteStackTrace()
|
||||
of "b", "setbreak":
|
||||
setBreakPoint(dbgUser, i)
|
||||
of "breakpoints":
|
||||
ListBreakPoints()
|
||||
of "disable":
|
||||
BreakpointSetEnabled(dbgUser, i, -1)
|
||||
of "enable":
|
||||
BreakpointSetEnabled(dbgUser, i, +1)
|
||||
of "maxdisplay":
|
||||
var parsed: int
|
||||
i = scanNumber(dbgUser, parsed, i)
|
||||
if dbgUser[i-1] in {'0'..'9'}:
|
||||
if parsed == 0: maxDisplayRecDepth = -1
|
||||
else: maxDisplayRecDepth = parsed
|
||||
else:
|
||||
InvalidCommand()
|
||||
else:
|
||||
InvalidCommand()
|
||||
|
||||
proc endbStep() =
|
||||
# we get into here if an unhandled exception has been raised
|
||||
# XXX: do not allow the user to run the program any further?
|
||||
# XXX: BUG: the frame is lost here!
|
||||
dbgShowExecutionPoint()
|
||||
CommandPrompt()
|
||||
|
||||
proc checkForBreakpoint() =
|
||||
var i = dbgBreakpointReached(framePtr.line)
|
||||
if i >= 0:
|
||||
write(stdout, "*** emdb| reached ")
|
||||
write(stdout, dbgBP[i].name)
|
||||
write(stdout, " in ")
|
||||
write(stdout, framePtr.filename)
|
||||
write(stdout, "(")
|
||||
write(stdout, framePtr.line)
|
||||
write(stdout, ") ")
|
||||
write(stdout, framePtr.procname)
|
||||
write(stdout, " ***\n")
|
||||
CommandPrompt()
|
||||
|
||||
# interface to the user program:
|
||||
|
||||
proc dbgRegisterBreakpoint(line: int,
|
||||
filename, name: cstring) {.compilerproc.} =
|
||||
var x = dbgBPlen
|
||||
inc(dbgBPlen)
|
||||
dbgBP[x].name = $name
|
||||
dbgBP[x].filename = $filename
|
||||
dbgBP[x].low = line
|
||||
dbgBP[x].high = line
|
||||
|
||||
proc dbgRegisterGlobal(name: cstring, address: pointer,
|
||||
typ: PNimType) {.compilerproc.} =
|
||||
var i = dbgGlobalData.f.len
|
||||
if i >= high(dbgGlobalData.slots):
|
||||
debugOut("[Warning] cannot register global ")
|
||||
return
|
||||
dbgGlobalData.slots[i].name = name
|
||||
dbgGlobalData.slots[i].typ = typ
|
||||
dbgGlobalData.slots[i].address = address
|
||||
inc(dbgGlobalData.f.len)
|
||||
|
||||
proc endb(line: int) {.compilerproc.} =
|
||||
# This proc is called before any Nimrod code line!
|
||||
# Thus, it must have as few parameters as possible to keep the
|
||||
# code size small!
|
||||
# check if we are at an enabled breakpoint or "in the mood"
|
||||
framePtr.line = line # this is done here for smaller code size!
|
||||
if dbgLineHook != nil: dbgLineHook()
|
||||
case dbgState
|
||||
of dbStepInto:
|
||||
# we really want the command prompt here:
|
||||
dbgShowExecutionPoint()
|
||||
CommandPrompt()
|
||||
of dbSkipCurrent, dbStepOver: # skip current routine
|
||||
if framePtr == dbgSkipToFrame:
|
||||
dbgShowExecutionPoint()
|
||||
CommandPrompt()
|
||||
else: # breakpoints are wanted though (I guess)
|
||||
checkForBreakpoint()
|
||||
of dbBreakpoints: # debugger is only interested in breakpoints
|
||||
checkForBreakpoint()
|
||||
else: nil
|
||||
5071
lib/dlmalloc.c
Executable file
5071
lib/dlmalloc.c
Executable file
File diff suppressed because it is too large
Load Diff
1143
lib/dlmalloc.h
Executable file
1143
lib/dlmalloc.h
Executable file
File diff suppressed because it is too large
Load Diff
143
lib/dyncalls.nim
Executable file
143
lib/dyncalls.nim
Executable file
@@ -0,0 +1,143 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# This file implements the ability to call native procs from libraries.
|
||||
# It is not possible to do this in a platform independant way, unfortunately.
|
||||
# However, the interface has been designed to take platform differences into
|
||||
# account and been ported to all major platforms.
|
||||
#
|
||||
# interface
|
||||
|
||||
type
|
||||
EInvalidLibrary = object of EOS
|
||||
|
||||
when defined(windows) or defined(dos):
|
||||
{.define: USE_DLL.}
|
||||
elif defined(posix):
|
||||
{.define: USE_DLOPEN.}
|
||||
elif defined(mac):
|
||||
{.define: USE_DYLD.}
|
||||
|
||||
type
|
||||
TLibHandle = pointer # private type
|
||||
TProcAddr = pointer # libary loading and loading of procs:
|
||||
|
||||
const
|
||||
NilLibHandle: TLibHandle = nil
|
||||
|
||||
proc nimLoadLibrary(path: string): TLibHandle {.compilerproc.}
|
||||
proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.}
|
||||
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.}
|
||||
|
||||
#implementation
|
||||
|
||||
# this code was inspired from Lua's source code:
|
||||
# Lua - An Extensible Extension Language
|
||||
# Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
|
||||
# http://www.lua.org
|
||||
# mailto:info@lua.org
|
||||
|
||||
when defined(USE_DLOPEN):
|
||||
#
|
||||
# =========================================================================
|
||||
# This is an implementation based on the dlfcn interface.
|
||||
# The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
|
||||
# NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least
|
||||
# as an emulation layer on top of native functions.
|
||||
# =========================================================================
|
||||
#
|
||||
|
||||
# c stuff:
|
||||
var
|
||||
RTLD_NOW {.importc: "RTLD_NOW", header: "<dlfcn.h>".}: int
|
||||
|
||||
proc dlclose(lib: TLibHandle) {.importc, header: "<dlfcn.h>".}
|
||||
proc dlopen(path: CString, mode: int): TLibHandle {.
|
||||
importc, header: "<dlfcn.h>".}
|
||||
proc dlsym(lib: TLibHandle, name: cstring): TProcAddr {.
|
||||
importc, header: "<dlfcn.h>".}
|
||||
|
||||
proc nimUnloadLibrary(lib: TLibHandle) =
|
||||
dlclose(lib)
|
||||
|
||||
proc nimLoadLibrary(path: string): TLibHandle =
|
||||
result = dlopen(path, RTLD_NOW)
|
||||
if result == nil:
|
||||
raise newException(EInvalidLibrary, "could not load: " & path)
|
||||
|
||||
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
|
||||
result = dlsym(lib, name)
|
||||
|
||||
elif defined(USE_DLL):
|
||||
#
|
||||
# =======================================================================
|
||||
# Native Windows Implementation
|
||||
# =======================================================================
|
||||
#
|
||||
type
|
||||
THINSTANCE {.importc: "HINSTANCE".} = pointer
|
||||
|
||||
proc FreeLibrary(lib: THINSTANCE) {.importc, header: "<windows.h>", stdcall.}
|
||||
proc winLoadLibrary(path: cstring): THINSTANCE {.
|
||||
importc: "LoadLibraryA", header: "<windows.h>", stdcall.}
|
||||
proc GetProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
|
||||
importc: "GetProcAddress", header: "<windows.h>", stdcall.}
|
||||
|
||||
proc nimUnloadLibrary(lib: TLibHandle) =
|
||||
FreeLibrary(cast[THINSTANCE](lib))
|
||||
|
||||
proc nimLoadLibrary(path: string): TLibHandle =
|
||||
result = cast[TLibHandle](winLoadLibrary(path))
|
||||
if result == nil:
|
||||
raise newException(EInvalidLibrary, "could not load: " & path)
|
||||
|
||||
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
|
||||
result = GetProcAddress(cast[THINSTANCE](lib), name)
|
||||
|
||||
elif defined(USE_DYLD):
|
||||
#
|
||||
# =======================================================================
|
||||
# Native Mac OS X / Darwin Implementation
|
||||
# =======================================================================
|
||||
#
|
||||
{.error: "no implementation for dyncalls yet".}
|
||||
|
||||
proc nimUnloadLibrary(lib: TLibHandle) =
|
||||
NSUnLinkModule(NSModule(lib), NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES)
|
||||
|
||||
var
|
||||
dyld_present {.importc: "_dyld_present", header: "<dyld.h>".}: int
|
||||
|
||||
proc nimLoadLibrary(path: string): TLibHandle =
|
||||
var
|
||||
img: NSObjectFileImage
|
||||
ret: NSObjectFileImageReturnCode
|
||||
modul: NSModule
|
||||
# this would be a rare case, but prevents crashing if it happens
|
||||
result = nil
|
||||
if dyld_present != 0:
|
||||
ret = NSCreateObjectFileImageFromFile(path, addr(img))
|
||||
if ret == NSObjectFileImageSuccess:
|
||||
modul = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE or
|
||||
NSLINKMODULE_OPTION_RETURN_ON_ERROR)
|
||||
NSDestroyObjectFileImage(img)
|
||||
result = TLibHandle(modul)
|
||||
if result == nil:
|
||||
raise newException(EInvalidLibrary, "could not load: " & path)
|
||||
|
||||
proc nimGetProcAddr(lib: TLibHandle, cname: string): TProcAddr =
|
||||
var
|
||||
nss: NSSymbol
|
||||
nss = NSLookupSymbolInModule(NSModule(lib), name)
|
||||
result = TProcAddr(NSAddressOfSymbol(nss))
|
||||
|
||||
else: # workaround a newly introduced bug :-(
|
||||
{.error: "no implementation for dyncalls".}
|
||||
251
lib/excpt.nim
Executable file
251
lib/excpt.nim
Executable file
@@ -0,0 +1,251 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
# Exception handling code. This is difficult because it has
|
||||
# to work if there is no more memory. Thus we have to use
|
||||
# a static string. Do not use ``sprintf``, etc. as they are
|
||||
# unsafe!
|
||||
|
||||
when not defined(windows) or not defined(guiapp):
|
||||
proc writeToStdErr(msg: CString) = write(stdout, msg)
|
||||
|
||||
else:
|
||||
proc MessageBoxA(hWnd: cint, lpText, lpCaption: cstring, uType: int): int32 {.
|
||||
header: "<windows.h>", nodecl.}
|
||||
|
||||
proc writeToStdErr(msg: CString) =
|
||||
discard MessageBoxA(0, msg, nil, 0)
|
||||
|
||||
proc raiseException(e: ref E_Base, ename: CString) {.compilerproc.}
|
||||
proc reraiseException() {.compilerproc.}
|
||||
|
||||
proc registerSignalHandler() {.compilerproc.}
|
||||
|
||||
proc chckIndx(i, a, b: int): int {.inline, compilerproc.}
|
||||
proc chckRange(i, a, b: int): int {.inline, compilerproc.}
|
||||
proc chckRangeF(x, a, b: float): float {.inline, compilerproc.}
|
||||
proc chckNil(p: pointer) {.inline, compilerproc.}
|
||||
|
||||
type
|
||||
PSafePoint = ptr TSafePoint
|
||||
TSafePoint {.compilerproc.} = record
|
||||
prev: PSafePoint # points to next safe point ON THE STACK
|
||||
exc: ref E_Base
|
||||
status: int
|
||||
context: C_JmpBuf
|
||||
|
||||
var
|
||||
excHandler {.compilerproc, volatile.}: PSafePoint = nil
|
||||
# list of exception handlers
|
||||
# a global variable for the root of all try blocks
|
||||
|
||||
proc reraiseException() =
|
||||
if excHandler != nil:
|
||||
raise newException(ENoExceptionToReraise, "no exception to reraise")
|
||||
else:
|
||||
c_longjmp(excHandler.context, 1)
|
||||
|
||||
type
|
||||
PFrame = ptr TFrame
|
||||
TFrame {.importc, nodecl.} = record
|
||||
prev: PFrame
|
||||
procname: CString
|
||||
line: int # current line number
|
||||
filename: CString
|
||||
len: int # length of slots (when not debugging always zero)
|
||||
|
||||
TTempFrame = record # used for recursion elimination in WriteStackTrace
|
||||
procname: CString
|
||||
line: int
|
||||
|
||||
var
|
||||
buf: string # cannot be allocated on the stack!
|
||||
assertBuf: string # we need a different buffer for
|
||||
# assert, as it raises an exception and
|
||||
# exception handler needs the buffer too
|
||||
|
||||
framePtr {.exportc, volatile.}: PFrame
|
||||
|
||||
tempFrames: array [0..255, TTempFrame] # cannot be allocated
|
||||
# on the stack!
|
||||
|
||||
proc auxWriteStackTrace(f: PFrame, s: var string) =
|
||||
var
|
||||
it = f
|
||||
i = 0
|
||||
total = 0
|
||||
while it != nil and i <= high(tempFrames):
|
||||
tempFrames[i].procname = it.procname
|
||||
tempFrames[i].line = it.line
|
||||
inc(i)
|
||||
inc(total)
|
||||
it = it.prev
|
||||
while it != nil:
|
||||
inc(total)
|
||||
it = it.prev
|
||||
# if the buffer overflowed print '...':
|
||||
if total != i:
|
||||
add(s, "(")
|
||||
add(s, $(total-i))
|
||||
add(s, " calls omitted) ...\n")
|
||||
for j in countdown(i-1, 0):
|
||||
add(s, $tempFrames[j].procname)
|
||||
if tempFrames[j].line > 0:
|
||||
add(s, ", line: ")
|
||||
add(s, $tempFrames[j].line)
|
||||
add(s, "\n")
|
||||
|
||||
proc rawWriteStackTrace(s: var string) =
|
||||
if framePtr == nil:
|
||||
add(s, "No stack traceback available\n")
|
||||
else:
|
||||
add(s, "Traceback (most recent call last)\n")
|
||||
auxWriteStackTrace(framePtr, s)
|
||||
|
||||
proc quitOrDebug() {.inline.} =
|
||||
when not defined(emdb):
|
||||
quit(1)
|
||||
else:
|
||||
emdbStep() # call the debugger
|
||||
|
||||
proc raiseException(e: ref E_Base, ename: CString) =
|
||||
GC_disable() # a bad thing is an error in the GC while raising an exception
|
||||
e.name = ename
|
||||
if excHandler != nil:
|
||||
excHandler.exc = e
|
||||
c_longjmp(excHandler.context, 1)
|
||||
else:
|
||||
if cast[pointer](buf) != nil:
|
||||
setLen(buf, 0)
|
||||
rawWriteStackTrace(buf)
|
||||
if e.msg != nil and e.msg[0] != '\0':
|
||||
add(buf, "Error: unhandled exception: ")
|
||||
add(buf, $e.msg)
|
||||
else:
|
||||
add(buf, "Error: unhandled exception")
|
||||
add(buf, " [")
|
||||
add(buf, $ename)
|
||||
add(buf, "]\n")
|
||||
writeToStdErr(buf)
|
||||
else:
|
||||
writeToStdErr("*** FATAL ERROR *** ")
|
||||
writeToStdErr(ename)
|
||||
writeToStdErr("\n")
|
||||
quitOrDebug()
|
||||
GC_enable()
|
||||
|
||||
var
|
||||
gAssertionFailed: ref EAssertionFailed
|
||||
|
||||
proc internalAssert(file: cstring, line: int, cond: bool) {.compilerproc.} =
|
||||
if not cond:
|
||||
GC_disable() # BUGFIX: `$` allocates a new string object!
|
||||
if cast[pointer](assertBuf) != nil: # BUGFIX: when debugging the GC, assertBuf may be nil
|
||||
setLen(assertBuf, 0)
|
||||
add(assertBuf, "[Assertion failure] file: ")
|
||||
add(assertBuf, file)
|
||||
add(assertBuf, " line: ")
|
||||
add(assertBuf, $line)
|
||||
add(assertBuf, "\n")
|
||||
gAssertionFailed.msg = assertBuf
|
||||
GC_enable()
|
||||
raise gAssertionFailed # newException(EAssertionFailed, assertBuf)
|
||||
|
||||
proc WriteStackTrace() =
|
||||
var
|
||||
s: string = ""
|
||||
rawWriteStackTrace(s)
|
||||
writeToStdErr(s)
|
||||
|
||||
var
|
||||
dbgAborting: bool # whether the debugger wants to abort
|
||||
|
||||
proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
|
||||
# print stack trace and quit
|
||||
var
|
||||
s = int(sig)
|
||||
setLen(buf, 0)
|
||||
rawWriteStackTrace(buf)
|
||||
|
||||
if s == SIGINT: add(buf, "SIGINT: Interrupted by Ctrl-C.\n")
|
||||
elif s == SIGSEGV: add(buf, "SIGSEGV: Illegal storage access.\n")
|
||||
elif s == SIGABRT:
|
||||
if dbgAborting: return # the debugger wants to abort
|
||||
add(buf, "SIGABRT: Abnormal termination.\n")
|
||||
elif s == SIGFPE: add(buf, "SIGFPE: Arithmetic error.\n")
|
||||
elif s == SIGILL: add(buf, "SIGILL: Illegal operation.\n")
|
||||
elif s == SIGBUS: add(buf, "SIGBUS: Illegal storage access.\n")
|
||||
else: add(buf, "unknown signal\n")
|
||||
writeToStdErr(buf)
|
||||
dbgAborting = True # play safe here...
|
||||
quit(1) # always quit when SIGABRT
|
||||
|
||||
proc registerSignalHandler() =
|
||||
c_signal(SIGINT, signalHandler)
|
||||
c_signal(SIGSEGV, signalHandler)
|
||||
c_signal(SIGABRT, signalHandler)
|
||||
c_signal(SIGFPE, signalHandler)
|
||||
c_signal(SIGILL, signalHandler)
|
||||
c_signal(SIGBUS, signalHandler)
|
||||
|
||||
registerSignalHandler() # call it in initialization section
|
||||
# for easier debugging of the GC, this memory is only allocated after the
|
||||
# signal handlers have been registered
|
||||
new(gAssertionFailed)
|
||||
buf = newString(2048)
|
||||
assertBuf = newString(2048)
|
||||
setLen(buf, 0)
|
||||
setLen(assertBuf, 0)
|
||||
|
||||
proc raiseRangeError() {.compilerproc, noreturn.} =
|
||||
raise newException(EOutOfRange, "value out of range")
|
||||
|
||||
proc raiseIndexError() {.compilerproc, noreturn.} =
|
||||
raise newException(EInvalidIndex, "index out of bounds")
|
||||
|
||||
proc chckIndx(i, a, b: int): int =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseIndexError()
|
||||
|
||||
proc chckRange(i, a, b: int): int =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseRangeError()
|
||||
|
||||
proc chckRange64(i, a, b: int64): int64 {.compilerproc.} =
|
||||
if i >= a and i <= b:
|
||||
return i
|
||||
else:
|
||||
raiseRangeError()
|
||||
|
||||
proc chckRangeF(x, a, b: float): float =
|
||||
if x >= a and x <= b:
|
||||
return x
|
||||
else:
|
||||
raiseRangeError()
|
||||
|
||||
proc chckNil(p: pointer) =
|
||||
if p == nil: c_raise(SIGSEGV)
|
||||
|
||||
proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
|
||||
# checks if obj is of type subclass:
|
||||
var x = obj
|
||||
if x == subclass: return # optimized fast path
|
||||
while x != subclass:
|
||||
if x == nil:
|
||||
raise newException(EInvalidObjectConversion, "invalid object conversion")
|
||||
x = x.base
|
||||
|
||||
proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
|
||||
if a != b:
|
||||
raise newException(EInvalidObjectAssignment, "invalid object assignment")
|
||||
897
lib/gc.nim
Executable file
897
lib/gc.nim
Executable file
@@ -0,0 +1,897 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
# Garbage Collector
|
||||
|
||||
# For a description of the algorithms used here see:
|
||||
# intern.html
|
||||
|
||||
#{.define: debugGC.} # we wish to debug the GC...
|
||||
|
||||
#when defined(debugGC):
|
||||
# {.define: logGC.} # define if the GC should log some of its activities
|
||||
|
||||
{.define: cycleGC.}
|
||||
|
||||
# Guess the page size of the system; if it is the
|
||||
# wrong value, performance may be worse (this is not
|
||||
# for sure though), but GC still works; must be a power of two!
|
||||
const
|
||||
PageSize = 1024 * sizeof(int)
|
||||
RC_Increase = 7 * PageSize # is an additive increase
|
||||
CycleIncrease = 2 # is a multiplicative increase
|
||||
|
||||
when defined(debugGC):
|
||||
const InitialThreshold = 64*1024
|
||||
const stressGC = True # GC is debugged; no need to stress it
|
||||
else:
|
||||
const stressGC = False
|
||||
const InitialThreshold = RC_Increase
|
||||
# this may need benchmarking...
|
||||
|
||||
# things the System module thinks should be available:
|
||||
when defined(useDL) or defined(nativeDL):
|
||||
type
|
||||
TMallocInfo {.importc: "struct mallinfo", nodecl.} = record
|
||||
arena: cint # non-mmapped space allocated from system
|
||||
ordblks: cint # number of free chunks
|
||||
smblks: cint # number of fastbin blocks
|
||||
hblks: cint # number of mmapped regions
|
||||
hblkhd: cint # space in mmapped regions
|
||||
usmblks: cint # maximum total allocated space
|
||||
fsmblks: cint # space available in freed fastbin blocks
|
||||
uordblks: cint # total allocated space
|
||||
fordblks: cint # total free space
|
||||
keepcost: cint # top-most, releasable (via malloc_trim) space
|
||||
|
||||
when defined(useDL):
|
||||
proc mallinfo: TMallocInfo {.importc: "dlmallinfo", nodecl.}
|
||||
elif defined(nativeDL):
|
||||
proc mallinfo: TMallocInfo {.importc: "mallinfo", nodecl.}
|
||||
|
||||
when defined(useDL) or defined(nativeDL):
|
||||
proc getOccupiedMem(): int = return mallinfo().uordblks
|
||||
proc getFreeMem(): int = return mallinfo().fordblks
|
||||
proc getTotalMem(): int =
|
||||
var m = mallinfo()
|
||||
return int(m.hblkhd) + int(m.arena)
|
||||
else: # not available:
|
||||
proc getOccupiedMem(): int = return -1
|
||||
proc getFreeMem(): int = return -1
|
||||
proc getTotalMem(): int = return -1
|
||||
|
||||
var
|
||||
rcThreshold: int = InitialThreshold
|
||||
cycleThreshold: int = InitialThreshold
|
||||
|
||||
memUsed: int = 0 # we have to keep track how much we have allocated
|
||||
|
||||
recGcLock: int = 0
|
||||
# we use a lock to prevend the garbage collector to
|
||||
# be triggered in a finalizer; the collector should not call
|
||||
# itself this way! Thus every object allocated by a finalizer
|
||||
# will not trigger a garbage collection. This is wasteful but safe.
|
||||
# This is a lock against recursive garbage collection, not a lock for
|
||||
# threads!
|
||||
|
||||
when defined(useDL) and not defined(nativeDL):
|
||||
{.compile: "dlmalloc.c".}
|
||||
|
||||
type
|
||||
TFinalizer {.compilerproc.} = proc (self: pointer)
|
||||
# A ref type can have a finalizer that is called before the object's
|
||||
# storage is freed.
|
||||
PPointer = ptr pointer
|
||||
|
||||
proc asgnRef(dest: ppointer, src: pointer) {.compilerproc.}
|
||||
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc.}
|
||||
# unsureAsgnRef updates the reference counters only if dest is not on the
|
||||
# stack. It is used by the code generator if it cannot decide wether a
|
||||
# reference is in the stack or not (this can happen for out/var parameters).
|
||||
proc growObj(old: pointer, newsize: int): pointer {.compilerproc.}
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.}
|
||||
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.}
|
||||
|
||||
# implementation:
|
||||
|
||||
when defined(useDL):
|
||||
proc nimSize(p: pointer): int {.
|
||||
importc: "dlmalloc_usable_size", header: "dlmalloc.h".}
|
||||
elif defined(nativeDL):
|
||||
proc nimSize(p: pointer): int {.
|
||||
importc: "malloc_usable_size", header: "<malloc.h>".}
|
||||
|
||||
type
|
||||
TWalkOp = enum
|
||||
waNone, waRelease, waZctDecRef, waCycleDecRef, waCycleIncRef, waDebugIncRef
|
||||
|
||||
TCollectorData = int
|
||||
TCell = record
|
||||
refcount: TCollectorData # the refcount and bit flags
|
||||
typ: PNimType
|
||||
stackcount: int # stack counter for debugging
|
||||
drefc: int # real reference counter for debugging
|
||||
|
||||
PCell = ptr TCell
|
||||
|
||||
var
|
||||
gOutOfMem: ref EOutOfMemory
|
||||
|
||||
proc raiseOutOfMem() {.noreturn.} =
|
||||
if gOutOfMem == nil:
|
||||
writeToStdErr("out of memory; cannot even throw an exception")
|
||||
quit(1)
|
||||
gOutOfMem.msg = "out of memory"
|
||||
raise gOutOfMem
|
||||
|
||||
proc cellToUsr(cell: PCell): pointer {.inline.} =
|
||||
# convert object (=pointer to refcount) to pointer to userdata
|
||||
result = cast[pointer](cast[TAddress](cell)+%TAddress(sizeof(TCell)))
|
||||
|
||||
proc usrToCell(usr: pointer): PCell {.inline.} =
|
||||
# convert pointer to userdata to object (=pointer to refcount)
|
||||
result = cast[PCell](cast[TAddress](usr)-%TAddress(sizeof(TCell)))
|
||||
|
||||
proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
|
||||
# used for code generation concerning debugging
|
||||
result = usrToCell(c).typ
|
||||
|
||||
proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =
|
||||
result = int(usrToCell(p).refcount)
|
||||
|
||||
proc gcAlloc(size: int): pointer =
|
||||
result = alloc0(size)
|
||||
if result == nil: raiseOutOfMem()
|
||||
|
||||
proc GC_disable() = inc(recGcLock)
|
||||
proc GC_enable() =
|
||||
if recGcLock > 0: dec(recGcLock)
|
||||
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) =
|
||||
case strategy
|
||||
of gcThroughput: nil
|
||||
of gcResponsiveness: nil
|
||||
of gcOptimizeSpace: nil
|
||||
of gcOptimizeTime: nil
|
||||
|
||||
proc GC_enableMarkAndSweep() =
|
||||
cycleThreshold = InitialThreshold
|
||||
|
||||
proc GC_disableMarkAndSweep() =
|
||||
cycleThreshold = high(cycleThreshold)-1
|
||||
# set to the max value to suppress the cycle detector
|
||||
|
||||
proc nextTry(h, maxHash: int): int {.inline.} =
|
||||
result = ((5*h) + 1) and maxHash
|
||||
# For any initial h in range(maxHash), repeating that maxHash times
|
||||
# generates each int in range(maxHash) exactly once (see any text on
|
||||
# random-number generation for proof).
|
||||
|
||||
# ------------------ Zero count table (ZCT) and any table (AT) -------------
|
||||
|
||||
# these values are for DL-malloc known for sure (and other allocators
|
||||
# can only be worse):
|
||||
when defined(useDL) or not defined(bcc):
|
||||
const MemAlignment = 8 # minimal memory block that can be allocated
|
||||
else:
|
||||
const MemAlignment = 4 # Borland's memory manager is terrible!
|
||||
|
||||
const
|
||||
BitsPerUnit = sizeof(int)*8
|
||||
# a "unit" is a word, i.e. 4 bytes
|
||||
# on a 32 bit system; I do not use the term "word" because under 32-bit
|
||||
# Windows it is sometimes only 16 bits
|
||||
|
||||
BitsPerPage = PageSize div MemAlignment
|
||||
UnitsPerPage = BitsPerPage div BitsPerUnit
|
||||
# how many units do we need to describe a page:
|
||||
# on 32 bit systems this is only 16 (!)
|
||||
|
||||
# this that has to equals zero, otherwise we have to round up UnitsPerPage:
|
||||
when BitsPerPage mod BitsPerUnit != 0:
|
||||
{.error: "(BitsPerPage mod BitsPerUnit) should be zero!".}
|
||||
|
||||
# ------------------- cell set handling ------------------------------
|
||||
# A cellset consists of a hash table of page descriptors. A page
|
||||
# descriptor has a bit for
|
||||
# every Memalignment'th byte in the page.
|
||||
# However, only bits corresponding to addresses that start memory blocks
|
||||
# are set.
|
||||
# Page descriptors are also linked to a list; the list
|
||||
# is used for easy traversing of all page descriptors; this allows a
|
||||
# fast iterator.
|
||||
# We use a specialized hashing scheme; the formula is :
|
||||
# hash = Page bitand max
|
||||
# We use linear probing with the formular: (5*h)+1
|
||||
# Thus we likely get no collisions at all if the pages are given us
|
||||
# sequentially by the operating system!
|
||||
type
|
||||
PPageDesc = ptr TPageDesc
|
||||
|
||||
TBitIndex = range[0..UnitsPerPage-1]
|
||||
|
||||
TPageDesc = record
|
||||
next: PPageDesc # all nodes are connected with this pointer
|
||||
key: TAddress # start address at bit 0
|
||||
bits: array[TBitIndex, int] # a bit vector
|
||||
|
||||
PPageDescArray = ptr array[0..1000_000, PPageDesc]
|
||||
TCellSet = record
|
||||
counter, max: int
|
||||
head: PPageDesc
|
||||
data: PPageDescArray
|
||||
|
||||
const
|
||||
InitCellSetSize = 1024 # must be a power of two!
|
||||
|
||||
proc CellSetInit(s: var TCellSet) =
|
||||
s.data = cast[PPageDescArray](gcAlloc(InitCellSetSize * sizeof(PPageDesc)))
|
||||
s.max = InitCellSetSize-1
|
||||
s.counter = 0
|
||||
s.head = nil
|
||||
|
||||
proc CellSetDeinit(s: var TCellSet) =
|
||||
var it = s.head
|
||||
while it != nil:
|
||||
var n = it.next
|
||||
dealloc(it)
|
||||
it = n
|
||||
s.head = nil # play it safe here
|
||||
dealloc(s.data)
|
||||
s.data = nil
|
||||
s.counter = 0
|
||||
|
||||
proc CellSetGet(t: TCellSet, key: TAddress): PPageDesc =
|
||||
var h = cast[int](key) and t.max
|
||||
while t.data[h] != nil:
|
||||
if t.data[h].key == key: return t.data[h]
|
||||
h = nextTry(h, t.max)
|
||||
return nil
|
||||
|
||||
proc CellSetRawInsert(t: TCellSet, data: PPageDescArray,
|
||||
desc: PPageDesc) =
|
||||
var h = cast[int](desc.key) and t.max
|
||||
while data[h] != nil:
|
||||
assert(data[h] != desc)
|
||||
h = nextTry(h, t.max)
|
||||
assert(data[h] == nil)
|
||||
data[h] = desc
|
||||
|
||||
proc CellSetEnlarge(t: var TCellSet) =
|
||||
var
|
||||
n: PPageDescArray
|
||||
oldMax = t.max
|
||||
t.max = ((t.max+1)*2)-1
|
||||
n = cast[PPageDescArray](gcAlloc((t.max + 1) * sizeof(PPageDesc)))
|
||||
for i in 0 .. oldmax:
|
||||
if t.data[i] != nil:
|
||||
CellSetRawInsert(t, n, t.data[i])
|
||||
dealloc(t.data)
|
||||
t.data = n
|
||||
|
||||
proc CellSetPut(t: var TCellSet, key: TAddress): PPageDesc =
|
||||
var h = cast[int](key) and t.max
|
||||
while true:
|
||||
var x = t.data[h]
|
||||
if x == nil: break
|
||||
if x.key == key: return x
|
||||
h = nextTry(h, t.max)
|
||||
|
||||
if (t.max+1) * 2 < t.counter * 3: CellSetEnlarge(t)
|
||||
inc(t.counter)
|
||||
h = cast[int](key) and t.max
|
||||
while t.data[h] != nil: h = nextTry(h, t.max)
|
||||
assert(t.data[h] == nil)
|
||||
# the new page descriptor goes into result
|
||||
result = cast[PPageDesc](gcAlloc(sizeof(TPageDesc)))
|
||||
result.next = t.head
|
||||
result.key = key
|
||||
t.head = result
|
||||
t.data[h] = result
|
||||
|
||||
# ---------- slightly higher level procs ----------------------------------
|
||||
|
||||
proc in_Operator(s: TCellSet, cell: PCell): bool =
|
||||
var
|
||||
u: TAddress
|
||||
t: PPageDesc
|
||||
u = cast[TAddress](cell)
|
||||
t = CellSetGet(s, u /% PageSize)
|
||||
if t != nil:
|
||||
u = (u %% PageSize) /% MemAlignment
|
||||
result = (t.bits[u /% BitsPerUnit] and (1 shl (u %% BitsPerUnit))) != 0
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc incl(s: var TCellSet, cell: PCell) =
|
||||
var
|
||||
u: TAddress
|
||||
t: PPageDesc
|
||||
u = cast[TAddress](cell)
|
||||
t = CellSetPut(s, u /% PageSize)
|
||||
u = (u %% PageSize) /% MemAlignment
|
||||
t.bits[u /% BitsPerUnit] = t.bits[u /% BitsPerUnit] or
|
||||
(1 shl (u %% BitsPerUnit))
|
||||
|
||||
proc excl(s: var TCellSet, cell: PCell) =
|
||||
var
|
||||
u: TAddress
|
||||
t: PPageDesc
|
||||
u = cast[TAddress](cell)
|
||||
t = CellSetGet(s, u /% PageSize)
|
||||
if t != nil:
|
||||
u = (u %% PageSize) /% MemAlignment
|
||||
t.bits[u /% BitsPerUnit] = (t.bits[u /% BitsPerUnit] and
|
||||
not (1 shl (u %% BitsPerUnit)))
|
||||
|
||||
iterator elements(t: TCellSet): PCell {.inline.} =
|
||||
# while traversing it is forbidden to add pointers to the tree!
|
||||
var r = t.head
|
||||
while r != nil:
|
||||
var i = 0
|
||||
while i <= high(r.bits):
|
||||
var w = r.bits[i] # taking a copy of r.bits[i] here is correct, because
|
||||
# modifying operations are not allowed during traversation
|
||||
var j = 0
|
||||
while w != 0: # test all remaining bits for zero
|
||||
if (w and 1) != 0: # the bit is set!
|
||||
yield cast[PCell]((r.key *% PageSize) +%
|
||||
(i*%BitsPerUnit+%j) *% MemAlignment)
|
||||
inc(j)
|
||||
w = w shr 1
|
||||
inc(i)
|
||||
r = r.next
|
||||
|
||||
# --------------- end of Cellset routines -------------------------------------
|
||||
|
||||
proc testPageDescs() =
|
||||
var root: TCellSet
|
||||
CellSetInit(root)
|
||||
var u = 10_000
|
||||
while u <= 20_000:
|
||||
incl(root, cast[PCell](u))
|
||||
inc(u, 8)
|
||||
for cell in elements(root):
|
||||
c_fprintf(c_stdout, "%ld\n", cast[int](cell))
|
||||
|
||||
# testPageDescs()
|
||||
|
||||
when defined(debugGC):
|
||||
proc writeCell(msg: CString, c: PCell) =
|
||||
c_fprintf(c_stdout, "%s: %p\n", msg, c)
|
||||
proc writePtr(msg: CString, p: Pointer) =
|
||||
c_fprintf(c_stdout, "%s: %p\n", msg, p)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
type
|
||||
PStackCells = ptr array[0..1000_0000, PCell]
|
||||
TCountTables = record # this contains the zero count and
|
||||
# non-zero count table
|
||||
mask: TAddress # mask for fast pointer detection
|
||||
zct: TCellSet # the zero count table
|
||||
at: TCellSet # a table that contains all references
|
||||
newAT: TCellSet
|
||||
newZCT: TCellSet
|
||||
stackCells: PStackCells # cells that need to be decremented because they
|
||||
# are in the hardware stack; a cell may occur
|
||||
# several times in this data structure
|
||||
stackLen, stackMax: int # for managing the stack cells
|
||||
|
||||
proc addStackCell(ct: var TCountTables, cell: PCell) =
|
||||
if ct.stackLen >= ct.stackMax:
|
||||
ct.stackMax = ct.stackMax * 3 div 2
|
||||
ct.stackCells = cast[PStackCells](realloc(ct.stackCells, ct.stackMax *
|
||||
sizeof(PCell)))
|
||||
if ct.stackCells == nil: raiseOutOfMem()
|
||||
ct.stackCells[ct.stackLen] = cell
|
||||
inc(ct.stackLen)
|
||||
|
||||
var
|
||||
stackBottom: pointer
|
||||
ct: TCountTables
|
||||
|
||||
proc GC_invariant(): bool =
|
||||
result = True
|
||||
when stressGC:
|
||||
if recGcLock == 0:
|
||||
GC_disable()
|
||||
for cell in elements(ct.at):
|
||||
var t = cell.typ # getCellType(cell)
|
||||
if t == nil or t.kind notin {tySequence, tyString, tyRef}:
|
||||
writeCell("corrupt cell?", cell)
|
||||
result = false
|
||||
GC_enable()
|
||||
|
||||
when stressGC:
|
||||
proc GCdebugHook() =
|
||||
if not GC_invariant():
|
||||
assert(false)
|
||||
|
||||
dbgLineHook = GCdebugHook
|
||||
|
||||
proc prepareDealloc(cell: PCell) =
|
||||
if cell.typ.finalizer != nil:
|
||||
# the finalizer could invoke something that
|
||||
# allocates memory; this could trigger a garbage
|
||||
# collection. Since we are already collecting we
|
||||
# prevend recursive entering here by a lock.
|
||||
# XXX: we should set the cell's children to nil!
|
||||
inc(recGcLock)
|
||||
(cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
|
||||
dec(recGcLock)
|
||||
|
||||
when defined(nimSize):
|
||||
memUsed = memUsed - nimSize(cell)
|
||||
else:
|
||||
memUsed = memUsed - cell.typ.size
|
||||
|
||||
proc setStackBottom(theStackBottom: pointer) {.compilerproc.} =
|
||||
stackBottom = theStackBottom
|
||||
|
||||
proc initGC() =
|
||||
# init the rt
|
||||
CellSetInit(ct.zct)
|
||||
CellSetInit(ct.at)
|
||||
ct.stackLen = 0
|
||||
ct.stackMax = 255
|
||||
ct.stackCells = cast[PStackCells](gcAlloc((ct.stackMax+1) * sizeof(PCell)))
|
||||
ct.mask = 0
|
||||
new(gOutOfMem) # reserve space for the EOutOfMemory exception here!
|
||||
assert(GC_invariant())
|
||||
|
||||
# forward declarations:
|
||||
proc collectCT(ct: var TCountTables)
|
||||
proc IsOnStack(p: pointer): bool
|
||||
proc forAllChildren(cell: PCell, op: TWalkOp)
|
||||
proc collectCycles()
|
||||
|
||||
proc reprAny(p: pointer, typ: PNimType): string {.compilerproc.}
|
||||
# we need the prototype here for debugging purposes
|
||||
|
||||
proc outputCell(c: PCell) =
|
||||
inc(recGcLock)
|
||||
write(stdout, reprAny(cellToUsr(c), c.typ))
|
||||
dec(recGcLock)
|
||||
|
||||
proc writeGraph() =
|
||||
{.checkpoint.}
|
||||
block:
|
||||
inc(recGcLock)
|
||||
for c in elements(ct.AT): outputCell(c)
|
||||
dec(recGcLock)
|
||||
|
||||
proc checkRefc(): bool =
|
||||
if recGcLock >= 1: return true # prevent endless recursion
|
||||
inc(recGcLock)
|
||||
result = True
|
||||
# set counters back to zero:
|
||||
for c in elements(ct.AT):
|
||||
c.drefc = 0
|
||||
for c in elements(ct.AT):
|
||||
forAllChildren(c, waDebugIncRef)
|
||||
for c in elements(ct.AT):
|
||||
if c.drefc > c.refcount - c.stackcount:
|
||||
result = false # failed
|
||||
c_fprintf(c_stdout,
|
||||
"broken cell: %p, refc: %ld, stack: %ld, real: %ld\n",
|
||||
c, c.refcount, c.stackcount, c.drefc)
|
||||
dec(recGcLock)
|
||||
|
||||
proc seqCheck(cell: PCell): bool =
|
||||
assert(cell.typ != nil)
|
||||
if cell.typ.kind in {tySequence, tyString}:
|
||||
result = cell.refcount - cell.stackcount <= 1
|
||||
else:
|
||||
result = true
|
||||
|
||||
proc decRef(cell: PCell) {.inline.} =
|
||||
assert(cell in ct.AT)
|
||||
when defined(debugGC):
|
||||
if cell.refcount == 0:
|
||||
writePtr("decref broken", cellToUsr(cell))
|
||||
assert(cell.refcount > 0) # this should be the case!
|
||||
assert(seqCheck(cell))
|
||||
dec(cell.refcount)
|
||||
if cell.refcount == 0:
|
||||
incl(ct.zct, cell)
|
||||
|
||||
proc incRef(cell: PCell) {.inline.} =
|
||||
assert(seqCheck(cell))
|
||||
inc(cell.refcount)
|
||||
|
||||
proc asgnRef(dest: ppointer, src: pointer) =
|
||||
# the code generator calls this proc!
|
||||
assert(not isOnStack(dest))
|
||||
# BUGFIX: first incRef then decRef!
|
||||
if src != nil: incRef(usrToCell(src))
|
||||
if dest^ != nil: decRef(usrToCell(dest^))
|
||||
dest^ = src
|
||||
#assert(checkRefc())
|
||||
|
||||
proc unsureAsgnRef(dest: ppointer, src: pointer) =
|
||||
if not IsOnStack(dest):
|
||||
if src != nil: incRef(usrToCell(src))
|
||||
if dest^ != nil: decRef(usrToCell(dest^))
|
||||
dest^ = src
|
||||
#assert(checkRefc())
|
||||
|
||||
proc restore(cell: PCell) =
|
||||
if cell notin ct.newAT:
|
||||
incl(ct.newAT, Cell)
|
||||
forAllChildren(cell, waCycleIncRef)
|
||||
|
||||
proc doOperation(p: pointer, op: TWalkOp) =
|
||||
if p == nil: return
|
||||
var cell: PCell = usrToCell(p)
|
||||
assert(cell != nil)
|
||||
case op # faster than function pointers because of easy prediction
|
||||
of waNone: assert(false)
|
||||
of waRelease: decRef(cell) # DEAD CODE!
|
||||
of waZctDecRef:
|
||||
assert(cell.refcount > 0)
|
||||
assert(seqCheck(cell))
|
||||
dec(cell.refcount)
|
||||
if cell.refcount == 0:
|
||||
incl(ct.newZCT, cell)
|
||||
of waCycleDecRef:
|
||||
assert(cell.refcount != 0)
|
||||
dec(cell.refcount)
|
||||
of waCycleIncRef:
|
||||
inc(cell.refcount) # restore proper reference counts!
|
||||
restore(cell)
|
||||
of waDebugIncRef:
|
||||
inc(cell.drefc)
|
||||
|
||||
type
|
||||
TByteArray = array[0..1000_0000, byte]
|
||||
PByte = ptr TByteArray
|
||||
PString = ptr string
|
||||
|
||||
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp)
|
||||
|
||||
proc getDiscriminant(aa: Pointer, n: ptr TNimNode): int =
|
||||
assert(n.kind == nkCase)
|
||||
var d: int32
|
||||
var a = cast[TAddress](aa)
|
||||
case n.typ.size
|
||||
of 1: d = toU32(cast[ptr int8](a +% n.offset)^)
|
||||
of 2: d = toU32(cast[ptr int16](a +% n.offset)^)
|
||||
of 4: d = toU32(cast[ptr int32](a +% n.offset)^)
|
||||
else: assert(false)
|
||||
return int(d)
|
||||
|
||||
proc selectBranch(aa: Pointer, n: ptr TNimNode): ptr TNimNode =
|
||||
var discr = getDiscriminant(aa, n)
|
||||
if discr <% n.len:
|
||||
result = n.sons[discr]
|
||||
if result == nil: result = n.sons[n.len]
|
||||
# n.sons[n.len] contains the ``else`` part (but may be nil)
|
||||
else:
|
||||
result = n.sons[n.len]
|
||||
|
||||
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
|
||||
var
|
||||
d = cast[TAddress](dest)
|
||||
case n.kind
|
||||
of nkNone: assert(false)
|
||||
of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
|
||||
of nkList:
|
||||
for i in 0..n.len-1: forAllSlotsAux(dest, n.sons[i], op)
|
||||
of nkCase:
|
||||
var m = selectBranch(dest, n)
|
||||
if m != nil: forAllSlotsAux(dest, m, op)
|
||||
|
||||
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
|
||||
var
|
||||
d = cast[TAddress](dest)
|
||||
if dest == nil: return # nothing to do
|
||||
case mt.Kind
|
||||
of tyArray, tyArrayConstr, tyOpenArray:
|
||||
for i in 0..(mt.size div mt.base.size)-1:
|
||||
forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
|
||||
of tyRef, tyString, tySequence: # leaf:
|
||||
doOperation(cast[ppointer](d)^, op)
|
||||
of tyRecord, tyObject, tyTuple:
|
||||
forAllSlotsAux(dest, mt.node, op)
|
||||
else: nil
|
||||
|
||||
proc forAllChildren(cell: PCell, op: TWalkOp) =
|
||||
assert(cell != nil)
|
||||
when defined(debugGC):
|
||||
if cell.typ == nil:
|
||||
writeCell("cell has no type descriptor", cell)
|
||||
assert(cell.typ != nil)
|
||||
case cell.typ.Kind
|
||||
of tyRef: # common case
|
||||
forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
|
||||
of tySequence:
|
||||
var d = cast[TAddress](cellToUsr(cell))
|
||||
var s = cast[PGenericSeq](d)
|
||||
if s != nil: # BUGFIX
|
||||
for i in 0..s.len-1:
|
||||
forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +%
|
||||
GenericSeqSize), cell.typ.base, op)
|
||||
of tyString: nil
|
||||
else: assert(false)
|
||||
|
||||
proc checkCollection() {.inline.} =
|
||||
# checks if a collection should be done
|
||||
if recGcLock == 0:
|
||||
if memUsed >= rcThreshold or stressGC:
|
||||
collectCT(ct)
|
||||
when defined(debugGC):
|
||||
write(stdout, "threshold is now: ")
|
||||
writeln(stdout, rcThreshold)
|
||||
|
||||
proc newObj(typ: PNimType, size: int): pointer =
|
||||
# generates a new object and sets its reference counter to 0
|
||||
var
|
||||
res: PCell
|
||||
assert(typ.kind in {tyRef, tyString, tySequence})
|
||||
# check if we have to collect:
|
||||
checkCollection()
|
||||
res = cast[PCell](Alloc0(size + sizeof(TCell)))
|
||||
if res == nil: raiseOutOfMem()
|
||||
when defined(nimSize):
|
||||
memUsed = memUsed + nimSize(res)
|
||||
else:
|
||||
memUsed = memUsed + size
|
||||
|
||||
res.refcount = 0
|
||||
# now it is buffered in the ZCT
|
||||
res.typ = typ
|
||||
incl(ct.zct, res) # its refcount is zero, so add it to the ZCT
|
||||
incl(ct.at, res) # add it to the any table too
|
||||
ct.mask = ct.mask or cast[TAddress](res)
|
||||
when defined(debugGC):
|
||||
writeCell("new cell", res)
|
||||
assert(gcInvariant())
|
||||
result = cellToUsr(res)
|
||||
|
||||
proc newSeq(typ: PNimType, len: int): pointer =
|
||||
# XXX: overflow checks!
|
||||
result = newObj(typ, len * typ.base.size + GenericSeqSize)
|
||||
cast[PGenericSeq](result).len = len
|
||||
cast[PGenericSeq](result).space = len
|
||||
|
||||
proc growObj(old: pointer, newsize: int): pointer =
|
||||
var
|
||||
res, ol: PCell
|
||||
checkCollection()
|
||||
ol = usrToCell(old)
|
||||
assert(ol.typ.kind in {tyString, tySequence})
|
||||
assert(seqCheck(ol))
|
||||
when defined(nimSize):
|
||||
memUsed = memUsed - nimSize(ol)
|
||||
else:
|
||||
memUsed = memUsed - ol.size # this is not exact
|
||||
# pity that we don't know the old size
|
||||
res = cast[PCell](realloc(ol, newsize + sizeof(TCell)))
|
||||
when defined(nimSize):
|
||||
memUsed = memUsed + nimSize(res)
|
||||
else:
|
||||
memUsed = memUsed + newsize
|
||||
|
||||
if res != ol:
|
||||
if res == nil: raiseOutOfMem()
|
||||
excl(ct.zct, ol) # remove old pointer in any case:
|
||||
# It may have a refcount > 0 and is still in the ZCT.
|
||||
# So do it safe here and remove it anyway.
|
||||
excl(ct.at, ol)
|
||||
if res.refcount == 0:
|
||||
# store new pointer in ZCT, if refcount == 0:
|
||||
incl(ct.zct, res)
|
||||
incl(ct.at, res)
|
||||
ct.mask = ct.mask or cast[TAddress](res)
|
||||
when defined(debugGC):
|
||||
writeCell("growObj old cell", ol)
|
||||
writeCell("growObj new cell", res)
|
||||
result = cellToUsr(res)
|
||||
#assert(checkRefc())
|
||||
|
||||
proc collectCycles() =
|
||||
when defined(debugGC):
|
||||
echo("collecting cycles!\n")
|
||||
|
||||
# step 1: pretend that any node is dead
|
||||
for c in elements(ct.at):
|
||||
forallChildren(c, waCycleDecRef)
|
||||
CellSetInit(ct.newAt)
|
||||
# step 2: restore life cells
|
||||
for c in elements(ct.at):
|
||||
if c.refcount > 0: restore(c)
|
||||
# step 3: free dead cells:
|
||||
for cell in elements(ct.at):
|
||||
if cell.refcount == 0:
|
||||
assert(cell notin ct.zct)
|
||||
# We free an object that is part of a cycle here. Its children
|
||||
# may have been freed already. Thus the finalizer could access
|
||||
# garbage. To handle this case properly we need two passes for
|
||||
# freeing here which is too expensive. We just don't call the
|
||||
# finalizer for now. YYY: Any better ideas?
|
||||
prepareDealloc(cell)
|
||||
dealloc(cell)
|
||||
when defined(debugGC):
|
||||
writeCell("cycle collector dealloc cell", cell)
|
||||
CellSetDeinit(ct.at)
|
||||
ct.at = ct.newAt
|
||||
#ct.newAt = nil
|
||||
|
||||
proc gcMark(p: pointer) =
|
||||
# the addresses are not as objects on the stack, so turn them to objects:
|
||||
var cell = usrToCell(p)
|
||||
var c = cast[TAddress](cell)
|
||||
if ((c and ct.mask) == c) and cell in ct.at:
|
||||
# is the page that p "points to" in the AT? (All allocated pages are
|
||||
# always in the AT)
|
||||
inc(cell.refcount)
|
||||
inc(cell.stackcount)
|
||||
addStackCell(ct, cell)
|
||||
|
||||
proc unmarkStackAndRegisters() =
|
||||
for i in 0 .. ct.stackLen-1:
|
||||
var cell = ct.stackCells[i]
|
||||
assert(cell.refcount > 0)
|
||||
when defined(debugGC):
|
||||
if cell.stackcount == 0:
|
||||
writeGraph()
|
||||
writePtr("broken stackcount", cellToUsr(cell))
|
||||
assert(cell.stackcount > 0)
|
||||
dec(cell.refcount)
|
||||
dec(cell.stackcount)
|
||||
if cell.refcount == 0:
|
||||
incl(ct.zct, cell)
|
||||
ct.stackLen = 0 # reset to zero
|
||||
|
||||
# ----------------- stack management --------------------------------------
|
||||
# inspired from Smart Eiffel (c)
|
||||
|
||||
proc stackSize(): int =
|
||||
var stackTop: array[0..1, pointer]
|
||||
result = abs(cast[int](addr(stackTop[0])) - cast[int](stackBottom))
|
||||
|
||||
when defined(sparc): # For SPARC architecture.
|
||||
|
||||
proc isOnStack(p: pointer): bool =
|
||||
var
|
||||
stackTop: array[0..1, pointer]
|
||||
result = p >= addr(stackTop[0]) and p <= stackBottom
|
||||
|
||||
proc markStackAndRegisters() =
|
||||
when defined(sparcv9):
|
||||
asm " flushw"
|
||||
else:
|
||||
asm " ta 0x3 ! ST_FLUSH_WINDOWS"
|
||||
|
||||
var
|
||||
max = stackBottom
|
||||
sp: PPointer
|
||||
stackTop: array[0..1, pointer]
|
||||
stackTop[0] = nil
|
||||
stackTop[1] = nil
|
||||
sp = addr(stackTop[0])
|
||||
# Addresses decrease as the stack grows.
|
||||
while sp <= max:
|
||||
gcMark(sp^)
|
||||
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
|
||||
|
||||
elif defined(ELATE):
|
||||
{.error: "stack marking code has to be written for this architecture".}
|
||||
|
||||
elif defined(hppa) or defined(hp9000) or defined(hp9000s300) or
|
||||
defined(hp9000s700) or defined(hp9000s800) or defined(hp9000s820):
|
||||
# ---------------------------------------------------------------------------
|
||||
# Generic code for architectures where addresses increase as the stack grows.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
proc isOnStack(p: pointer): bool =
|
||||
var
|
||||
stackTop: array[0..1, pointer]
|
||||
result = p <= addr(stackTop[0]) and p >= stackBottom
|
||||
|
||||
var
|
||||
jmpbufSize {.importc: "sizeof(jmp_buf)".}: int
|
||||
# a little hack to get the size of a TJmpBuf in the generated C code
|
||||
# in a platform independant way
|
||||
|
||||
proc markStackAndRegisters() =
|
||||
var
|
||||
max = stackBottom
|
||||
registers: C_JmpBuf # The jmp_buf buffer is in the C stack.
|
||||
sp: PPointer # Used to traverse the stack and registers assuming
|
||||
# that `setjmp' will save registers in the C stack.
|
||||
c_setjmp(registers) # To fill the C stack with registers.
|
||||
sp = cast[ppointer](cast[TAddress](addr(registers)) +%
|
||||
jmpbufSize -% sizeof(pointer))
|
||||
# sp will traverse the JMP_BUF as well (jmp_buf size is added,
|
||||
# otherwise sp would be below the registers structure).
|
||||
while sp >= max:
|
||||
gcMark(sp^)
|
||||
sp = cast[ppointer](cast[TAddress](sp) -% sizeof(pointer))
|
||||
|
||||
else:
|
||||
# ---------------------------------------------------------------------------
|
||||
# Generic code for architectures where addresses decrease as the stack grows.
|
||||
# ---------------------------------------------------------------------------
|
||||
proc isOnStack(p: pointer): bool =
|
||||
var
|
||||
stackTop: array [0..1, pointer]
|
||||
result = p >= addr(stackTop[0]) and p <= stackBottom
|
||||
|
||||
proc markStackAndRegisters() =
|
||||
var
|
||||
max = stackBottom
|
||||
registers: C_JmpBuf # The jmp_buf buffer is in the C stack.
|
||||
sp: PPointer # Used to traverse the stack and registers assuming
|
||||
# that `setjmp' will save registers in the C stack.
|
||||
c_setjmp(registers) # To fill the C stack with registers.
|
||||
sp = cast[ppointer](addr(registers))
|
||||
while sp <= max:
|
||||
gcMark(sp^)
|
||||
sp = cast[ppointer](cast[TAddress](sp) +% sizeof(pointer))
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# end of non-portable code
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
proc CollectZCT =
|
||||
CellSetInit(ct.newZCT)
|
||||
for c in elements(ct.zct):
|
||||
if c.refcount == 0:
|
||||
# if != 0 the reference count has been increased, so this does not
|
||||
# belong to the ZCT. We simply do nothing - it won't appear in the newZCT
|
||||
# anyway.
|
||||
# We are about to free the object, call the finalizer BEFORE its
|
||||
# children are deleted as well, because otherwise the finalizer may
|
||||
# access invalid memory. This is done by prepareDealloc():
|
||||
prepareDealloc(c)
|
||||
forAllChildren(c, waZctDecRef)
|
||||
assert(c.refcount == 0) # should still be zero
|
||||
excl(ct.at, c)
|
||||
excl(ct.newZCT, c) # BUGFIX
|
||||
when defined(debugGC):
|
||||
writeCell("zct dealloc cell", c)
|
||||
dealloc(c)
|
||||
CellSetDeinit(ct.zct)
|
||||
ct.zct = ct.newZCT
|
||||
#ct.newZCT = nil
|
||||
|
||||
proc collectCT(ct: var TCountTables) =
|
||||
when defined(debugGC):
|
||||
c_fprintf(c_stdout, "collecting zero count table; stack size: %ld\n",
|
||||
stackSize())
|
||||
markStackAndRegisters()
|
||||
assert(GC_invariant())
|
||||
while True:
|
||||
collectZCT()
|
||||
if ct.zct.counter == 0: break
|
||||
# ``counter`` counts the pages, but zero pages means zero cells
|
||||
|
||||
when defined(cycleGC):
|
||||
# still over the cycle threshold?
|
||||
if memUsed >= cycleThreshold or stressGC:
|
||||
# collect the cyclic things:
|
||||
assert(ct.zct.counter == 0)
|
||||
assert(GC_invariant())
|
||||
collectCycles()
|
||||
|
||||
# recompute the thresholds:
|
||||
rcThreshold = (memUsed div RC_increase + 1) * RC_Increase
|
||||
cycleThreshold = memUsed * cycleIncrease
|
||||
|
||||
assert(GC_invariant())
|
||||
unmarkStackAndRegisters()
|
||||
|
||||
proc GC_fullCollect() =
|
||||
var oldThreshold = cycleThreshold
|
||||
cycleThreshold = 0 # forces cycle collection
|
||||
collectCT(ct)
|
||||
cycleThreshold = oldThreshold
|
||||
51
lib/hti.nim
Executable file
51
lib/hti.nim
Executable file
@@ -0,0 +1,51 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
type # This should be he same as ast.TTypeKind
|
||||
# some enum fields are not used at runtime
|
||||
TNimKind = enum
|
||||
tyNone, tyBool, tyChar,
|
||||
tyEmptySet, tyArrayConstr, tyNil, tyRecordConstr,
|
||||
tyGeneric,
|
||||
tyGenericInst,
|
||||
tyGenericParam,
|
||||
tyEnum, tyAnyEnum,
|
||||
tyArray,
|
||||
tyRecord,
|
||||
tyObject,
|
||||
tyTuple,
|
||||
tySet,
|
||||
tyRange,
|
||||
tyPtr, tyRef,
|
||||
tyVar,
|
||||
tySequence,
|
||||
tyProc,
|
||||
tyPointer, tyOpenArray,
|
||||
tyString, tyCString, tyForward,
|
||||
tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
|
||||
tyFloat, tyFloat32, tyFloat64, tyFloat128
|
||||
|
||||
TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase
|
||||
TNimNode {.compilerproc.} = record
|
||||
kind: TNimNodeKind
|
||||
offset: int
|
||||
typ: ptr TNimType
|
||||
name: Cstring
|
||||
len: int
|
||||
sons: ptr array [0..0x7fff, ptr TNimNode]
|
||||
|
||||
TNimType {.compilerproc.} = record
|
||||
size: int
|
||||
kind: TNimKind
|
||||
base: ptr TNimType
|
||||
node: ptr TNimNode # valid for tyRecord, tyObject, tyTuple, tyEnum
|
||||
finalizer: pointer # the finalizer for the type
|
||||
PNimType = ptr TNimType
|
||||
|
||||
# node.len may be the ``first`` element of a set
|
||||
70
lib/i386.asm.in
Executable file
70
lib/i386.asm.in
Executable file
@@ -0,0 +1,70 @@
|
||||
; This contains the CPU-dependant variants of some routines.
|
||||
; (C) 2005 Andreas Rumpf
|
||||
; This code was inspired by the Freepascal compiler's sources
|
||||
; All routines here have the _cdecl calling convention because
|
||||
; that is the only convention any C compiler supports.
|
||||
|
||||
\python{
|
||||
# as usual I use my own preprocessor :-)
|
||||
import os
|
||||
|
||||
def c(name):
|
||||
if os.name == 'posix':
|
||||
return name
|
||||
else:
|
||||
return "_" + name
|
||||
}
|
||||
|
||||
segment code
|
||||
|
||||
global \c{cpu_inc_locked}
|
||||
global \c{cpu_dec_locked}
|
||||
global \c{cpu_lock}
|
||||
global \c{cpu_unlock}
|
||||
|
||||
\c{cpu_dec_locked}:
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
mov eax,[ebp+8] ; first parameter to function
|
||||
lock dec dword [eax]
|
||||
setz al
|
||||
mov esp,ebp
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
\c{cpu_inc_locked}:
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
mov eax,[ebp+8] ; first parameter to function
|
||||
lock inc dword [eax]
|
||||
mov esp,ebp
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
; This code uses the highest bit of the RC to indicate that the RC is
|
||||
; locked (spinlock).
|
||||
\c{cpu_lock}
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, [ebp+8] ; first parameter to function
|
||||
mov edx, [eax] ; load RC
|
||||
or edx, 0x80000000 ; set highest bit
|
||||
spin:
|
||||
xchg [eax], edx ; atomic instruction!
|
||||
pause ; wait a few cycles
|
||||
and edx, 0x80000000 ; mask highest bit
|
||||
jnz spin
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
\c{cpu_unlock}
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, [ebp+8] ; first parameter to function
|
||||
mov edx, [eax] ; load RC
|
||||
and edx, 0x7FFFFFFF ; unset highest bit
|
||||
xchg [eax], edx ; atomic instruction!
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
72
lib/int64s.nim
Executable file
72
lib/int64s.nim
Executable file
@@ -0,0 +1,72 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# 64 bit integers for platforms that don't have those
|
||||
|
||||
type
|
||||
IInt64 = record # "internal" int64
|
||||
lo, hi: int32
|
||||
|
||||
proc cmpI64(x, y: IInt64): int32 {.compilerproc.} =
|
||||
result = x.hi -% y.hi
|
||||
if result == 0: result = x.lo -% y.lo
|
||||
|
||||
proc addI64(x, y: IInt64): IInt64 {.compilerproc.} =
|
||||
result = x
|
||||
result.lo = result.lo +% y.lo
|
||||
result.hi = result.hi +% y.hi
|
||||
if y.lo > 0 and result.lo < y.lo:
|
||||
inc(result.hi)
|
||||
elif y.lo < 0 and result.lo > y.lo:
|
||||
dec(result.hi)
|
||||
|
||||
proc subI64(x, y: IInt64): IInt64 {.compilerproc.} =
|
||||
result = x
|
||||
result.lo = result.lo -% y.lo
|
||||
result.hi = result.hi -% y.hi
|
||||
if y.lo > 0 and result.lo < y.lo:
|
||||
inc(result.hi)
|
||||
elif y.lo < 0 and result.lo > y.lo:
|
||||
dec(result.hi)
|
||||
|
||||
proc mulI64(x, y: IInt64): IInt64 {.compilerproc.} =
|
||||
result.lo = x.lo *% y.lo
|
||||
result.hi = y.hi *% y.hi
|
||||
if y.lo > 0 and result.lo < y.lo:
|
||||
inc(result.hi)
|
||||
elif y.lo < 0 and result.lo > y.lo:
|
||||
dec(result.hi)
|
||||
|
||||
proc divI64(x, y: IInt64): IInt64 {.compilerproc.} =
|
||||
# XXX: to implement
|
||||
|
||||
proc modI64(x, y: IInt64): IInt64 {.compilerproc.} =
|
||||
# XXX: to implement
|
||||
|
||||
proc bitandI64(x, y: IInt64): IInt64 {.compilerproc.} =
|
||||
result.hi = x.hi and y.hi
|
||||
result.lo = x.lo and y.lo
|
||||
|
||||
proc bitorI64(x, y: IInt64): IInt64 {.compilerproc.} =
|
||||
result.hi = x.hi or y.hi
|
||||
result.lo = x.lo or y.lo
|
||||
|
||||
proc bitxorI64(x, y: IInt64): IInt64 {.compilerproc.} =
|
||||
result.hi = x.hi xor y.hi
|
||||
result.lo = x.lo xor y.lo
|
||||
|
||||
proc bitnotI64(x: IInt64): IInt64 {.compilerproc.} =
|
||||
result.lo = not x.lo
|
||||
result.hi = not x.hi
|
||||
|
||||
proc shlI64(x, y: IInt64): IInt64 {.compilerproc.} =
|
||||
# XXX: to implement
|
||||
|
||||
proc shrI64(x, y: IInt64): IInt64 {.compilerproc.} =
|
||||
# XXX: to implement
|
||||
502
lib/lgpl.txt
Executable file
502
lib/lgpl.txt
Executable file
@@ -0,0 +1,502 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
18
lib/locks.nim
Executable file
18
lib/locks.nim
Executable file
@@ -0,0 +1,18 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# Simple platform dependant lock implementation
|
||||
|
||||
type
|
||||
TSimpleLock = pointer
|
||||
|
||||
proc initLock(s: TSimpleLock)
|
||||
proc deinitLock(s: TSimpleLock)
|
||||
proc lock(s: TSimpleLock)
|
||||
proc unlock(s: TSimpleLock)
|
||||
131
lib/math.nim
Executable file
131
lib/math.nim
Executable file
@@ -0,0 +1,131 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
|
||||
# math routines
|
||||
|
||||
# interface
|
||||
|
||||
{.push debugger:off .} # the user does not want to trace a part
|
||||
# of the standard library!
|
||||
|
||||
{.push checks:off, line_dir:off, stack_trace:off.}
|
||||
|
||||
proc nextPowerOfTwo*(x: int): int
|
||||
## returns the nearest power of two, so that
|
||||
## result**2 >= x > (result-1)**2.
|
||||
proc isPowerOfTwo*(x: int): bool {.noSideEffect.}
|
||||
## returns true, if x is a power of two, false otherwise.
|
||||
## Negative numbers are not a power of two.
|
||||
proc countBits*(n: int32): int {.noSideEffect.}
|
||||
## counts the set bits in `n`.
|
||||
|
||||
proc random*(max: int): int
|
||||
## returns a random number in the range 0..max-1. The sequence of
|
||||
## random number is always the same, unless `randomize` is called
|
||||
## which initializes the random number generator with a "random"
|
||||
## number, i.e. a tickcount.
|
||||
proc randomize*()
|
||||
## initializes the random number generator with a "random"
|
||||
## number, i.e. a tickcount.
|
||||
|
||||
proc sqrt*(x: float): float {.importc: "sqrt", header: "<math.h>".}
|
||||
## computes the square root of `x`.
|
||||
|
||||
proc ln*(x: float): float {.importc: "log", header: "<math.h>".}
|
||||
## computes ln(x).
|
||||
proc exp*(x: float): float {.importc: "exp", header: "<math.h>".}
|
||||
## computes e**x.
|
||||
|
||||
proc frexp*(x: float, exponent: var int): float {.
|
||||
importc: "frexp", header: "<math.h>".}
|
||||
## Split a number into mantissa and exponent.
|
||||
## `frexp` calculates the mantissa m (a float greater than or equal to 0.5
|
||||
## and less than 1) and the integer value n such that `x` (the original
|
||||
## float value) equals m * 2**n. frexp stores n in `exponent` and returns
|
||||
## m.
|
||||
|
||||
proc arccos*(x: float): float {.importc: "acos", header: "<math.h>".}
|
||||
proc arcsin*(x: float): float {.importc: "asin", header: "<math.h>".}
|
||||
proc arctan*(x: float): float {.importc: "atan", header: "<math.h>".}
|
||||
proc arctan2*(y, x: float): float {.importc: "atan2", header: "<math.h>".}
|
||||
## Calculate the arc tangent of `y` / `x`.
|
||||
## `atan2` returns the arc tangent of `y` / `x`; it produces correct
|
||||
## results even when the resulting angle is near pi/2 or -pi/2
|
||||
## (`x` near 0).
|
||||
|
||||
proc cos*(x: float): float {.importc: "cos", header: "<math.h>".}
|
||||
proc cosh*(x: float): float {.importc: "cosh", header: "<math.h>".}
|
||||
proc hypot*(x: float): float {.importc: "hypot", header: "<math.h>".}
|
||||
proc log10*(x: float): float {.importc: "log10", header: "<math.h>".}
|
||||
proc sinh*(x: float): float {.importc: "sinh", header: "<math.h>".}
|
||||
proc tan*(x: float): float {.importc: "tan", header: "<math.h>".}
|
||||
proc tanh*(x: float): float {.importc: "tanh", header: "<math.h>".}
|
||||
proc pow*(x, y: float): float {.importc: "pos", header: "<math.h>".}
|
||||
## computes x to power raised of y.
|
||||
|
||||
type
|
||||
TFloatClass* = enum ## describes the class a floating point value belongs to.
|
||||
## This is the type that is returned by `classify`.
|
||||
fcNormal, ## value is an ordinary nonzero floating point value
|
||||
fcSubnormal, ## value is a subnormal (a very small) floating point value
|
||||
fcZero, ## value is zero
|
||||
fcNegZero, ## value is the negative zero
|
||||
fcNan, ## value is Not-A-Number (NAN)
|
||||
fcInf, ## value is positive infinity
|
||||
fcNegInf ## value is negative infinity
|
||||
|
||||
proc classify*(x: float): TFloatClass
|
||||
## classifies a floating point value. Returns `x`'s class as specified by
|
||||
## `TFloatClass`
|
||||
|
||||
# implementation
|
||||
|
||||
include cntbits
|
||||
|
||||
proc nextPowerOfTwo(x: int): int =
|
||||
result = x - 1
|
||||
when defined(cpu64):
|
||||
result = result or (result shr 32)
|
||||
result = result or (result shr 16)
|
||||
result = result or (result shr 8)
|
||||
result = result or (result shr 4)
|
||||
result = result or (result shr 2)
|
||||
result = result or (result shr 1)
|
||||
Inc(result)
|
||||
|
||||
# C procs:
|
||||
proc gettime(dummy: ptr cint): cint {.
|
||||
importc: "time", header: "<time.h>".}
|
||||
proc srand(seed: cint) {.
|
||||
importc: "srand", nodecl.}
|
||||
proc rand(): cint {.importc: "rand", nodecl.}
|
||||
|
||||
# most C compilers have no classify:
|
||||
proc classify(x: float): TFloatClass =
|
||||
if x == 0.0:
|
||||
if 1.0/x == 1.0/0.0:
|
||||
return fcZero
|
||||
else:
|
||||
return fcNegZero
|
||||
if x*0.5 == x:
|
||||
if x > 0.0: return fcInf
|
||||
else: return fcNegInf
|
||||
if x != x: return fcNan
|
||||
return fcNormal
|
||||
# XXX: fcSubnormal is not detected!
|
||||
|
||||
proc randomize() = srand(gettime(nil))
|
||||
proc random(max: int): int = return rand() mod max
|
||||
|
||||
proc isPowerOfTwo(x: int): bool = return (x and -x) == x
|
||||
|
||||
{.pop.}
|
||||
{.pop.}
|
||||
599
lib/memman.nim
Executable file
599
lib/memman.nim
Executable file
@@ -0,0 +1,599 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
# Memory manager. Based on:
|
||||
# Two Levels Segregate Fit memory allocator (TLSF)
|
||||
# Version 2.4.2
|
||||
#
|
||||
# Written by Miguel Masmano Tello <mimastel@doctor.upv.es>
|
||||
#
|
||||
# Thanks to Ismael Ripoll for his suggestions and reviews
|
||||
#
|
||||
# Copyright (C) 2008, 2007, 2006, 2005, 2004
|
||||
#
|
||||
# This code is released using a dual license strategy: GPL/LGPL
|
||||
# You can choose the licence that better fits your requirements.
|
||||
#
|
||||
# Released under the terms of the GNU General Public License Version 2.0
|
||||
# Released under the terms of the GNU Lesser General Public License Version 2.1
|
||||
|
||||
|
||||
# Some IMPORTANT TLSF parameters
|
||||
const
|
||||
blockAlign = sizeof(pointer) * 2
|
||||
maxFli = 30
|
||||
maxLog2Sli = 5
|
||||
maxSli = 1 shl maxLog2Sli
|
||||
|
||||
fliOffset = 6 # tlsf structure just will manage blocks bigger than 128 bytes
|
||||
smallBlock = 128
|
||||
realFli = MaxFli - fliOffset
|
||||
|
||||
type
|
||||
TFreePtr = record
|
||||
prev, next: PBhdr
|
||||
Pbhdr = ptr Tbhdr
|
||||
Tbhdr = record
|
||||
prevHdr: Pbhdr # this is just valid if the first bit of size is set
|
||||
size: int # the size is stored in bytes
|
||||
# bit 0 indicates whether the block is used and
|
||||
# bit 1 allows to know whether the previous block is free
|
||||
freePtr: TFreePtr # at this offset bhdr.buffer starts (was a union in the
|
||||
# C version)
|
||||
TAreaInfo = record # This structure is embedded at the beginning of each
|
||||
# area, giving us enough information to cope with a set
|
||||
# of areas
|
||||
theEnd: Pbhdr
|
||||
next: PAreaInfo
|
||||
PAreaInfo = ptr TAreaInfo
|
||||
|
||||
TLSF = record
|
||||
tlsf_signature: int32 # the TLSF's structure signature
|
||||
usedSize, maxSize: int
|
||||
areaHead: PAreaInfo # A linked list holding all the existing areas
|
||||
|
||||
flBitmap: int32 # the first-level bitmap
|
||||
# This array should have a size of REAL_FLI bits
|
||||
slBitmap: array[0..realFli, int32] # the second-level bitmap
|
||||
matrix: array [0..realFli, array[0..maxSli, PBhdr]]
|
||||
|
||||
const
|
||||
minBlockSize = sizeof(TFreePtr)
|
||||
bhdrOverhead = sizeof(Tbhdr) - minBlockSize
|
||||
tlsfSignature = 0x2A59FA59
|
||||
ptrMask = sizeof(pointer) - 1
|
||||
blockSize = 0xFFFFFFFF - ptrMask
|
||||
memAlign = blockAlign - 1
|
||||
blockState = 0x1
|
||||
prevState = 0x2
|
||||
|
||||
freeBlock = 0x1 # bit 0 of the block size
|
||||
usedBlock = 0x0
|
||||
|
||||
prevFree = 0x2 # bit 1 of the block size
|
||||
prevUsed = 0x0
|
||||
|
||||
defaultAreaSize = 64*1024 # 1024*10
|
||||
pageSize = if defined(cpu32): 4096 else: 4096*2
|
||||
|
||||
|
||||
proc getNextBlock(adr: pointer, r: int): PBhdr {.inline.} =
|
||||
return cast[PBhdr](cast[TAddress](adr) +% r)
|
||||
|
||||
proc roundupSize(r: int): int = return (r +% memAlign) and not memAlign
|
||||
proc rounddownSize(r: int): int = return r and not memAlign
|
||||
proc roundup(x, v: int): int = return (((not x)+%1) and (v-%1)) +% x
|
||||
|
||||
proc addSize(s: PTLSF, b: Pbhdr) =
|
||||
inc(s.usedSize, (b.size and blockSize) + bhdrOverhead)
|
||||
s.maxSize = max(s.maxSize, s.usedSize)
|
||||
|
||||
proc removeSize(s: PTLSF, b: Pbhdr) =
|
||||
dec(s.usedSize, (b.size and blockSize) + bhdrOverhead)
|
||||
|
||||
# ------------ platform specific code -----------------------------------------
|
||||
|
||||
when defined(posix):
|
||||
const # XXX: make these variables for portability?
|
||||
PROT_READ = 1 # page can be read
|
||||
PROT_WRITE = 2 # page can be written
|
||||
PROT_EXEC = 4 # page can be executed
|
||||
PROT_NONE = 0 # page can not be accessed
|
||||
|
||||
MAP_SHARED = 1 # Share changes
|
||||
MAP_PRIVATE = 2 # Changes are private
|
||||
MAP_TYPE = 0xf # Mask for type of mapping
|
||||
MAP_FIXED = 0x10 # Interpret addr exactly
|
||||
MAP_ANONYMOUS = 0x20 # don't use a file
|
||||
|
||||
MAP_GROWSDOWN = 0x100 # stack-like segment
|
||||
MAP_DENYWRITE = 0x800 # ETXTBSY
|
||||
MAP_EXECUTABLE = 0x1000 # mark it as an executable
|
||||
MAP_LOCKED = 0x2000 # pages are locked
|
||||
MAP_NORESERVE = 0x4000 # don't check for reservations
|
||||
|
||||
proc mmap(adr: pointer, len: int, prot, flags, fildes: cint,
|
||||
off: int): pointer {.header: "<sys/mman.h>".}
|
||||
|
||||
proc getNewArea(size: var int): pointer {.inline.} =
|
||||
size = roundup(size, PageSize)
|
||||
result = mmap(0, size, PROT_READ or PROT_WRITE,
|
||||
MAP_PRIVATE or MAP_ANONYMOUS, -1, 0)
|
||||
if result == nil or result == cast[pointer](-1):
|
||||
raiseOutOfMem()
|
||||
|
||||
elif defined(windows):
|
||||
const
|
||||
MEM_RESERVE = 0x2000
|
||||
MEM_COMMIT = 0x1000
|
||||
MEM_TOP_DOWN = 0x100000
|
||||
PAGE_READWRITE = 0x04
|
||||
|
||||
proc VirtualAlloc(lpAddress: pointer, dwSize: int, flAllocationType,
|
||||
flProtect: int32): pointer {.
|
||||
header: "<windows.h>", stdcall.}
|
||||
|
||||
proc getNewArea(size: var int): pointer {.inline.} =
|
||||
size = roundup(size, PageSize)
|
||||
result = VirtualAlloc(nil, size, MEM_RESERVE or MEM_COMMIT or MEM_TOP_DOWN,
|
||||
PAGE_READWRITE)
|
||||
if result == nil: raiseOutOfMem()
|
||||
|
||||
else:
|
||||
# generic implementation relying on malloc:
|
||||
proc malloc(size: int): pointer {.nodecl, importc.}
|
||||
|
||||
proc getNewArea(size: var int): pointer {.inline.} =
|
||||
size = roundup(size, PageSize)
|
||||
result = malloc(size)
|
||||
if result == nil: raiseOutOfMem()
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# helpers
|
||||
|
||||
const
|
||||
table: array[0..255, int8] = [
|
||||
-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7
|
||||
]
|
||||
|
||||
proc ls_bit(i: int32): int {.inline.} =
|
||||
var
|
||||
a: int = 0
|
||||
x: int = i and -i
|
||||
if x <=% 0xffff:
|
||||
if x <=% ff: a = 0
|
||||
else: a = 8
|
||||
elif x <=% 0xffffff: a = 16
|
||||
else: a = 24
|
||||
return table[x shr a] + a
|
||||
|
||||
proc ms_bit(i: int): int {.inline.} =
|
||||
var
|
||||
a = if i <=% 0xffff: (if i <=% 0xff: 0 else: 8) elif
|
||||
i <=% 0xffffff: 16 else: 24
|
||||
return table[i shr a] + a
|
||||
|
||||
proc set_bit[IX](nr: int, adr: var array[IX, int32]) {.inline.} =
|
||||
adr[nr shr 5] = adr[nr shr 5] or (1 shl (nr and 0x1f))
|
||||
|
||||
proc clear_bit[IX](nr: int, adr: var array[IX, int32]) {.inline.} =
|
||||
adr[nr shr 5] = adr[nr shr 5] and not (1 shl (nr and 0x1f))
|
||||
|
||||
proc mappingSearch(r, fl, sl: var int) {.inline.} =
|
||||
if r < smallBlock:
|
||||
fl = 0
|
||||
sl = r div (smallBlock div maxSli)
|
||||
else:
|
||||
var t = (1 shl (ms_bit(r) - maxLog2Sli)) - 1
|
||||
r = r + t
|
||||
fl = ms_bit(r)
|
||||
sl = (r shl (fl - maxLog2Sli)) - maxSli
|
||||
fl = fl - fliOffset
|
||||
r = r and not t
|
||||
|
||||
proc mappingInsert(r: int, fl, sl: var int) {.inline.} =
|
||||
if r < smallBlock:
|
||||
fl = 0
|
||||
sl = r div (smallBlock div maxSli)
|
||||
else:
|
||||
fl = ms_bit(r)
|
||||
sl = (r shr (fl - maxLog2Sli)) - maxSli
|
||||
fl = fl - fliOffset
|
||||
|
||||
proc findSuitableBlock(t: var TLSF, fl, sl: var int): Pbhdr =
|
||||
var tmp = t.slBitmap[fl] and ((not 0) shl sl)
|
||||
if tmp != 0:
|
||||
sl = ls_bit(tmp)
|
||||
result = t.matrix[fl][sl]
|
||||
else:
|
||||
fl = ls_bit(t.flBitmap and (not 0 shl (fl + 1)))
|
||||
if fl > 0: # likely
|
||||
sl = ls_bit(t.slBitmap[fl])
|
||||
result = t.matrix[fl][sl]
|
||||
|
||||
proc extractBlockHdr(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} =
|
||||
t.matrix[fl][sl] = b.freePtr.next
|
||||
if t.matrix[fl][sl] != 0:
|
||||
t.matrix[fl][sl].freePtr.prev = nil
|
||||
else:
|
||||
clear_bit(sl, t.slBitmap[fl])
|
||||
if t.slBitmap[fl] == 0:
|
||||
clear_bit(fl, t.flBitmap)
|
||||
b.freePtr.prev = nil
|
||||
b.freePtr.next = nil
|
||||
|
||||
proc extractBlock(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} =
|
||||
if b.freePtr.next != nil:
|
||||
b.freePtr.next.freePtr.prev = b.freePtr.prev
|
||||
if b.freePtr.prev != nil:
|
||||
b.freePtr.prev.freePtr.next = b.freePtr.next
|
||||
if t.matrix[fl][sl] == b:
|
||||
t.matrix[fl][sl] = b.freePtr.next
|
||||
if t.matrix[fl][sl] == nil:
|
||||
clear_bit(sl, t.slBitmap[fl])
|
||||
if t.slBitmap[fl] == 0:
|
||||
clear_bit(fl, t.flBitmap)
|
||||
b.freePtr.prev = nil
|
||||
b.freePtr.next = nil
|
||||
|
||||
proc insertBlock(b: Pbhdr, t: var TLSF, fl, sl: int) {.inline.} =
|
||||
b.freePtr.prev = nil
|
||||
b.freePtr.next = t.matrix[fl][sl]
|
||||
if t.matrix[fl][sl] != 0:
|
||||
t.matrix[fl][sl].freePtr.prev = b
|
||||
t.matrix[fl][sl] = b
|
||||
set_bit(sl, t.slBitmap[fl])
|
||||
set_bit(fl, t.flBitmap)
|
||||
|
||||
proc getBuffer(b: Pbhdr): pointer {.inline.} =
|
||||
result = cast[pointer](addr(b.freePtr))
|
||||
|
||||
proc processArea(area: pointer, size: int): Pbhdr =
|
||||
var
|
||||
b, lb, ib: Pbhdr
|
||||
ai: PAreaInfo
|
||||
ib = cast[Pbhdr](area)
|
||||
if sizeof(TAreaInfo) < minBlockSize:
|
||||
ib.size = minBlockSize or usedBlock or prevUsed
|
||||
else
|
||||
ib.size = roundupSize(sizeof(TAreaInfo)) or usedBlock or prevUsed
|
||||
b = getNextBlock(getBuffer(ib), ib.size and blockSize)
|
||||
b.size = rounddownSize(size - 3 * bhdrOverhead - (ib.size and blockSize)) or
|
||||
usedBlock or prevUsed
|
||||
b.freePtr.prev = nil
|
||||
b.freePtr.next = nil
|
||||
lb = getNextBlock(getBuffer(b), b.size and blockSize)
|
||||
lb.prevHdr = b
|
||||
lb.size = 0 or usedBlock or prevFree
|
||||
ai = cast[PAreaInfo](getBuffer(ib))
|
||||
ai.next = nil
|
||||
ai.theEnd = lb
|
||||
return ib
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Begin of the allocator code
|
||||
|
||||
var
|
||||
mp: pointer # default memory pool.
|
||||
|
||||
proc initMemoryPool(memPoolSize: int, memPool: pointer): int =
|
||||
var
|
||||
t: PLSF
|
||||
b, ib: Pbhdr
|
||||
|
||||
if memPool == nil or memPoolSize < sizeof(TLSF) + bhdrOverhead * 8:
|
||||
writeToStdErr("initMemoryPool(): memory_pool invalid\n")
|
||||
return -1
|
||||
|
||||
if (memPool and ptrMask) != 0:
|
||||
writeToStdErr("initMemoryPool(): memPool must be aligned to a word\n")
|
||||
return -1
|
||||
t = cast[PLSF](memPool)
|
||||
# Check if already initialised
|
||||
if t.signature == tlsfSignature:
|
||||
mp = memPool
|
||||
b = getNextBlock(mp, roundupSize(sizeof(TLSF)))
|
||||
return b.size and blockSize
|
||||
mp = memPool
|
||||
zeroMem(memPool, sizeof(TLSF))
|
||||
|
||||
t.signature = tlsfSignature
|
||||
ib = processArea(getNextBlock(memPool, roundupSize(sizeof(TLSF))),
|
||||
rounddownSize(memPoolSize - sizeof(TLSF)))
|
||||
b = getNextBlock(getBuffer(ib), ib.size and blockSize)
|
||||
freeEx(getBuffer(b), t)
|
||||
t.areaHead = cast[PAreaInfo](getBuffer(ib))
|
||||
|
||||
t.used_size = memPoolSize - (b.size and blockSize)
|
||||
t.max_size = t.used_size
|
||||
return b.size and blockSize
|
||||
|
||||
|
||||
proc addNewArea(area: pointer, areaSize: int, t: var TLSF): int =
|
||||
var
|
||||
p, ptrPrev, ai: PAreaInfo
|
||||
ib0, b0, lb0, ib1, b1, lb1, nextB: Pbhdr
|
||||
|
||||
zeroMem(area, areaSize)
|
||||
p = t.areaHead
|
||||
ptrPrev = 0
|
||||
|
||||
ib0 = processArea(area, areaSize)
|
||||
b0 = getNextBlock(getBuffer(ib0), ib0.size and blockSize)
|
||||
lb0 = getNextBlock(getBuffer(b0), b0.size and blockSize)
|
||||
|
||||
# Before inserting the new area, we have to merge this area with the
|
||||
# already existing ones
|
||||
while p != nil:
|
||||
ib1 = cast[Pbhdr](cast[TAddress](p) -% bhdrOverhead)
|
||||
b1 = getNextBlock(getBuffer(ib1), ib1.size and blockSize)
|
||||
lb1 = p.theEnd
|
||||
|
||||
# Merging the new area with the next physically contigous one
|
||||
if cast[TAddress](ib1) == cast[TAddress](lb0) +% bhdrOverhead:
|
||||
if t.areaHead == p:
|
||||
t.areaHead = p.next
|
||||
p = p.next
|
||||
else:
|
||||
ptrPrev.next = p.next
|
||||
p = p.next
|
||||
b0.size = rounddownSize((b0.size and blockSize) +
|
||||
(ib1.size and blockSize) + 2 * bhdrOverhead) or
|
||||
usedBlock or prevUsed
|
||||
b1.prevHdr = b0
|
||||
lb0 = lb1
|
||||
continue
|
||||
|
||||
# Merging the new area with the previous physically contigous one
|
||||
if getBuffer(lb1) == pointer(ib0):
|
||||
if t.areaHead == p:
|
||||
t.areaHead = p.next
|
||||
p = p.next
|
||||
else:
|
||||
ptrPrev.next = p.next
|
||||
p = p.next
|
||||
lb1->size = rounddownSize((b0.size and blockSize) +
|
||||
(ib0.size and blockSize) + 2 * bhdrOverhead) or
|
||||
usedBlock or (lb1.size and prevState)
|
||||
nextB = getNextBlock(getBuffer(lb1), lb1.size and blockSize)
|
||||
nextB.prevHdr = lb1
|
||||
b0 = lb1
|
||||
ib0 = ib1
|
||||
continue
|
||||
ptrPrev = p
|
||||
p = p.next
|
||||
|
||||
# Inserting the area in the list of linked areas
|
||||
ai = cast[PAreaInfo](getBuffer(ib0))
|
||||
ai.next = t.areaHead
|
||||
ai.theEnd = lb0
|
||||
t.areaHead = ai
|
||||
freeEx(getBuffer(b0), memPool)
|
||||
return (b0.size and blockSize)
|
||||
|
||||
proc mallocEx(asize: int, t: var TLSF): pointer =
|
||||
var
|
||||
b, b2, nextB: Pbhdr
|
||||
fl, sl, tmpSize, size: int
|
||||
|
||||
size = if asize < minBlockSize: minBlockSize else: roundupSize(asize)
|
||||
|
||||
# Rounding up the requested size and calculating fl and sl
|
||||
mappingSearch(size, fl, sl)
|
||||
|
||||
# Searching a free block, recall that this function changes the values
|
||||
# of fl and sl, so they are not longer valid when the function fails
|
||||
b = findSuitableBlock(tlsf, fl, sl)
|
||||
if b == nil:
|
||||
# Growing the pool size when needed
|
||||
# size plus enough room for the required headers:
|
||||
var areaSize = max(size + bhdrOverhead * 8, defaultAreaSize)
|
||||
var area = getNewArea(areaSize)
|
||||
addNewArea(area, areaSize, t)
|
||||
# Rounding up the requested size and calculating fl and sl
|
||||
mappingSearch(size, fl, sl)
|
||||
# Searching a free block
|
||||
b = findSuitableBlock(t, fl, sl)
|
||||
if b == nil:
|
||||
raiseOutOfMem()
|
||||
|
||||
extractBlockHdr(b, t, fl, sl)
|
||||
|
||||
#-- found:
|
||||
nextB = getNextBlock(getBuffer(b), b.size and blockSize)
|
||||
# Should the block be split?
|
||||
tmpSize = (b.size and blockSize) - size
|
||||
if tmpSize >= sizeof(Tbhdr):
|
||||
dec(tmpSize, bhdrOverhead)
|
||||
b2 = getNextBlock(getBuffer(b), size)
|
||||
b2.size = tmpSize or freeBlock or prevUsed
|
||||
nextB.prevHdr = b2
|
||||
mappingInsert(tmpSize, fl, sl)
|
||||
insertBlock(b2, t, fl, sl)
|
||||
|
||||
b.size = size or (b.size and prevState)
|
||||
else:
|
||||
nextB.size = nextB.size and not prevFree
|
||||
b.size = b.size and not freeBlock # Now it's used
|
||||
|
||||
addSize(t, b)
|
||||
return getBuffer(b)
|
||||
|
||||
|
||||
proc freeEx(p: pointer, t: var TLSF) =
|
||||
var
|
||||
fl = 0
|
||||
sl = 0
|
||||
b, tmpB: Pbhdr
|
||||
|
||||
assert(p != nil)
|
||||
b = cast[Pbhdr](cast[TAddress](p) -% bhdrOverhead)
|
||||
b.size = b.size or freeBlock
|
||||
|
||||
removeSize(t, b)
|
||||
b.freePtr.prev = nil
|
||||
b.freePtr.next = nil
|
||||
tmpB = getNextBlock(getBuffer(b), b.size and blockSize)
|
||||
if tmpB.size and freeBlock != 0:
|
||||
mappingInsert(tmpB.size and blockSize, fl, sl)
|
||||
extractBlock(tmpB, t, fl, sl)
|
||||
inc(b.size, (tmpB.size and blockSize) + bhdrOverhead)
|
||||
if (b.size and prevFree) != 0:
|
||||
tmpB = b.prevHdr
|
||||
mappingInsert(tmpB.size and blockSize, fl, sl)
|
||||
extractBlock(tmpB, t, fl, sl)
|
||||
inc(tmpB.size, (b.size and blockSize) + bhdrOverhead)
|
||||
b = tmpB
|
||||
mappingInsert(b.size and blockSize, fl, sl)
|
||||
insertBlock(b, t, fl, sl)
|
||||
|
||||
tmpB = getNextBlock(getBuffer(b), b.size and blockSize)
|
||||
tmpB.size = tmpB.size or prevFree
|
||||
tmpB.prevHdr = b
|
||||
|
||||
proc reallocEx(p: pointer, newSize: int, t: var TLSF): pointer =
|
||||
var
|
||||
cpsize, fl, sl, tmpSize: int
|
||||
b, tmpB, nextB: Pbhdr
|
||||
|
||||
assert(p != nil)
|
||||
assert(newSize > 0)
|
||||
|
||||
b = cast[Pbhdr](cast[TAddress](p) -% bhdrOverhead)
|
||||
nextB = getNextBlock(getBuffer(b), b.size and blockSize)
|
||||
newSize = if newSize < minBlockSize: minBlockSize else: roundupSize(newSize)
|
||||
tmpSize = b.size and blockSize
|
||||
if newSize <= tmpSize:
|
||||
removeSize(t, b)
|
||||
if (nextB.size and freeBlock) != 0:
|
||||
mappingInsert(nextB.size and blockSize, fl, sl)
|
||||
extractBlock(nextB, t, fl, sl)
|
||||
inc(tmpSize, (nextB.size and blockSize) + bhdrOverhead)
|
||||
nextB = getNextBlock(getBuffer(nextB), nextB.size and blockSize)
|
||||
# We always reenter this free block because tmpSize will
|
||||
# be greater then sizeof(Tbhdr)
|
||||
dec(tmpSize, newSize)
|
||||
if tmpSize >= sizeof(Tbhdr):
|
||||
dec(tmpSize, bhdrOverhead)
|
||||
tmpB = getNextBlock(getBuffer(b), newSize)
|
||||
tmpB.size = tmpSize or freeBlock or prevUsed
|
||||
nextB.prevHdr = tmpB
|
||||
nextB.size = nextB.size or prevFree
|
||||
mappingInsert(tmpSize, fl, sl)
|
||||
insertBlock(tmpB, t, fl, sl)
|
||||
b.size = newSize or (b.size and prevState)
|
||||
addSize(t, b)
|
||||
return getBuffer(b)
|
||||
|
||||
if (nextB.size and freeBlock) != 0:
|
||||
if newSize <= tmpSize + (nextB.size and blockSize):
|
||||
removeSize(t, b)
|
||||
mappingInsert(nextB.size and blockSize, fl, sl)
|
||||
extractBlock(nextB, t, fl, sl)
|
||||
inc(b.size, (nextB.size and blockSize) + bhdrOverhead)
|
||||
nextB = getNextBlock(getBuffer(b), b.size and blockSize)
|
||||
nextB.prevHdr = b
|
||||
nextB.size = nextB.size and not prevFree
|
||||
tmpSize = (b.size and blockSize) - newSize
|
||||
if tmpSize >= sizeof(Tbhdr):
|
||||
dec(tmpSize, bhdrOverhead)
|
||||
tmpB = getNextBlock(getBuffer(b), newSize)
|
||||
tmpB.size = tmpSize or freeBlock or prevUsed
|
||||
nextB.prevHdr = tmpB
|
||||
nextB.size = nextB.size or prevFree
|
||||
mappingInsert(tmpSize, fl, sl)
|
||||
insertBlock(tmpB, t, fl, sl)
|
||||
b.size = newSize or (b.size and prevState)
|
||||
addSize(t, b)
|
||||
return getBuffer(b)
|
||||
|
||||
var ptrAux = mallocEx(newSize, t)
|
||||
cpsize = if (b.size and blockSize) > newSize: newSize else:
|
||||
(b.size and blockSize)
|
||||
copyMem(ptrAux, p, cpsize)
|
||||
freeEx(p, memPool)
|
||||
return ptrAux
|
||||
|
||||
|
||||
proc ansiCrealloc(p: pointer, newSize: int, t: var TLSF): pointer =
|
||||
if p == nil:
|
||||
if newSize > 0:
|
||||
result = mallocEx(newSize, t)
|
||||
else:
|
||||
result = nil
|
||||
elif newSize <= 0:
|
||||
freeEx(p, t)
|
||||
result = nil
|
||||
else:
|
||||
result = reallocEx(p, newSize, t)
|
||||
|
||||
|
||||
void *tlsf_malloc(size_t size)
|
||||
{
|
||||
void *ret
|
||||
|
||||
#if USE_MMAP || USE_SBRK
|
||||
if (!mp) {
|
||||
size_t areaSize
|
||||
void *area
|
||||
|
||||
areaSize = sizeof(tlsf_t) + BHDR_OVERHEAD * 8 # Just a safety constant
|
||||
areaSize = (areaSize > DEFAULT_areaSize) ? areaSize : DEFAULT_areaSize
|
||||
area = get_new_area(&areaSize)
|
||||
if (area == ((void *) ~0))
|
||||
return NULL # Not enough system memory
|
||||
initMemoryPool(areaSize, area)
|
||||
}
|
||||
#endif
|
||||
|
||||
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock)
|
||||
|
||||
ret = malloc_ex(size, mp)
|
||||
|
||||
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
void tlsf_free(void *p)
|
||||
{
|
||||
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock)
|
||||
free_ex(p, mp)
|
||||
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock)
|
||||
}
|
||||
|
||||
void *tlsf_realloc(void *p, size_t size)
|
||||
{
|
||||
void *ret
|
||||
#if USE_MMAP || USE_SBRK
|
||||
if (!mp) {
|
||||
return tlsf_malloc(size)
|
||||
}
|
||||
#endif
|
||||
TLSF_ACQUIRE_LOCK(&((tlsf_t *)mp)->lock)
|
||||
ret = realloc_ex(p, size, mp)
|
||||
TLSF_RELEASE_LOCK(&((tlsf_t *)mp)->lock)
|
||||
return ret
|
||||
}
|
||||
403
lib/nimbase.h
Executable file
403
lib/nimbase.h
Executable file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
|
||||
Nimrod's Runtime Library
|
||||
(c) Copyright 2006 Andreas Rumpf
|
||||
|
||||
See the file "copying.txt", included in this
|
||||
distribution, for details about the copyright.
|
||||
*/
|
||||
|
||||
#ifndef NIMBASE_H
|
||||
#define NIMBASE_H
|
||||
|
||||
/* calling convention mess ----------------------------------------------- */
|
||||
#if defined(__GNUC__) || defined(__LCC__) || defined(__POCC__)
|
||||
/* these should support C99's inline */
|
||||
/* the test for __POCC__ has to come before the test for _MSC_VER,
|
||||
because PellesC defines _MSC_VER too. This is brain-dead. */
|
||||
# define N_INLINE(rettype, name) inline rettype name
|
||||
#elif defined(__BORLANDC__) || defined(_MSC_VER)
|
||||
/* Borland's compiler is really STRANGE here; note that the __fastcall
|
||||
keyword cannot be before the return type, but __inline cannot be after
|
||||
the return type, so we do not handle this mess in the code generator
|
||||
but rather here. */
|
||||
# define N_INLINE(rettype, name) __inline rettype name
|
||||
#elif defined(__DMC__)
|
||||
# define N_INLINE(rettype, name) inline rettype name
|
||||
#elif defined(__WATCOMC__)
|
||||
# define N_INLINE(rettype, name) __inline rettype name
|
||||
#else /* others are less picky: */
|
||||
# define N_INLINE(rettype, name) rettype __inline name
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define HAVE_LRINT 1
|
||||
#endif
|
||||
|
||||
/* --------------- how int64 constants should be declared: ----------- */
|
||||
#if defined(__GNUC__) || defined(__LCC__) || \
|
||||
defined(__POCC__) || defined(__DMC__)
|
||||
# define IL64(x) x##LL
|
||||
#else /* works only without LL */
|
||||
# define IL64(x) x
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32) /* only Windows has this mess... */
|
||||
# define N_CDECL(rettype, name) rettype __cdecl name
|
||||
# define N_STDCALL(rettype, name) rettype __stdcall name
|
||||
# define N_SYSCALL(rettype, name) rettype __syscall name
|
||||
# define N_FASTCALL(rettype, name) rettype __fastcall name
|
||||
# define N_SAFECALL(rettype, name) rettype __safecall name
|
||||
/* function pointers with calling convention: */
|
||||
# define N_CDECL_PTR(rettype, name) rettype (__cdecl *name)
|
||||
# define N_STDCALL_PTR(rettype, name) rettype (__stdcall *name)
|
||||
# define N_SYSCALL_PTR(rettype, name) rettype (__syscall *name)
|
||||
# define N_FASTCALL_PTR(rettype, name) rettype (__fastcall *name)
|
||||
# define N_SAFECALL_PTR(rettype, name) rettype (__safecall *name)
|
||||
|
||||
# define N_LIB_EXPORT __declspec(dllexport)
|
||||
# define N_LIB_IMPORT __declspec(dllimport)
|
||||
#else
|
||||
# define N_CDECL(rettype, name) rettype name
|
||||
# define N_STDCALL(rettype, name) rettype name
|
||||
# define N_SYSCALL(rettype, name) rettype name
|
||||
# define N_FASTCALL(rettype, name) rettype name
|
||||
# define N_SAFECALL(rettype, name) rettype name
|
||||
/* function pointers with calling convention: */
|
||||
# define N_CDECL_PTR(rettype, name) rettype (*name)
|
||||
# define N_STDCALL_PTR(rettype, name) rettype (*name)
|
||||
# define N_SYSCALL_PTR(rettype, name) rettype (*name)
|
||||
# define N_FASTCALL_PTR(rettype, name) rettype (*name)
|
||||
# define N_SAFECALL_PTR(rettype, name) rettype (*name)
|
||||
|
||||
# define N_LIB_EXPORT
|
||||
# define N_LIB_IMPORT extern
|
||||
#endif
|
||||
|
||||
#define N_NOCONV(rettype, name) rettype name
|
||||
/* specify no calling convention */
|
||||
#define N_NOCONV_PTR(rettype, name) rettype (*name)
|
||||
|
||||
#define N_CLOSURE(rettype, name) rettype name
|
||||
/* specify no calling convention */
|
||||
#define N_CLOSURE_PTR(rettype, name) rettype (*name)
|
||||
|
||||
|
||||
#if defined(__BORLANDC__) || defined(__WATCOMC__) || \
|
||||
defined(__POCC__) || defined(_MSC_VER)
|
||||
/* these compilers have a fastcall so use it: */
|
||||
# define N_NIMCALL(rettype, name) rettype __fastcall name
|
||||
# define N_NIMCALL_PTR(rettype, name) rettype (__fastcall *name)
|
||||
#else
|
||||
# define N_NIMCALL(rettype, name) rettype name /* no modifier */
|
||||
# define N_NIMCALL_PTR(rettype, name) rettype (*name)
|
||||
#endif
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
/* from float_cast.h: */
|
||||
|
||||
/*
|
||||
** Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
**
|
||||
** Permission to use, copy, modify, distribute, and sell this file for any
|
||||
** purpose is hereby granted without fee, provided that the above copyright
|
||||
** and this permission notice appear in all copies. No representations are
|
||||
** made about the suitability of this software for any purpose. It is
|
||||
** provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
/* Version 1.1 */
|
||||
|
||||
|
||||
/*============================================================================
|
||||
** On Intel Pentium processors (especially PIII and probably P4), converting
|
||||
** from float to int is very slow. To meet the C specs, the code produced by
|
||||
** most C compilers targeting Pentium needs to change the FPU rounding mode
|
||||
** before the float to int conversion is performed.
|
||||
**
|
||||
** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
|
||||
** is this flushing of the pipeline which is so slow.
|
||||
**
|
||||
** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
|
||||
** llrint and llrintf which fix this problem as a side effect.
|
||||
**
|
||||
** On Unix-like systems, the configure process should have detected the
|
||||
** presence of these functions. If they weren't found we have to replace them
|
||||
** here with a standard C cast.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The C99 prototypes for lrint and lrintf are as follows:
|
||||
**
|
||||
** long int lrintf (float x);
|
||||
** long int lrint (double x);
|
||||
*/
|
||||
|
||||
#if defined(__LCC__) || defined(__POCC__) \
|
||||
|| (defined(__GNUC__) && defined(WIN32))
|
||||
/* Linux' GCC does not seem to have these. Why? */
|
||||
# define HAVE_LRINT
|
||||
# define HAVE_LRINTF
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LRINT) && defined(HAVE_LRINTF)
|
||||
|
||||
/* These defines enable functionality introduced with the 1999 ISO C
|
||||
** standard. They must be defined before the inclusion of math.h to
|
||||
** engage them. If optimisation is enabled, these functions will be
|
||||
** inlined. With optimisation switched off, you have to link in the
|
||||
** maths library using -lm.
|
||||
*/
|
||||
|
||||
# define _ISOC9X_SOURCE 1
|
||||
# define _ISOC99_SOURCE 1
|
||||
# define __USE_ISOC9X 1
|
||||
# define __USE_ISOC99 1
|
||||
# include <math.h>
|
||||
|
||||
#elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
|
||||
&& !defined(__BORLANDC__)
|
||||
|
||||
# include <math.h>
|
||||
|
||||
/* Win32 doesn't seem to have these functions.
|
||||
** Therefore implement inline versions of these functions here.
|
||||
*/
|
||||
static N_INLINE(long int, lrint)(double flt) {
|
||||
long int intgr;
|
||||
_asm {
|
||||
fld flt
|
||||
fistp intgr
|
||||
};
|
||||
return intgr;
|
||||
}
|
||||
|
||||
static N_INLINE(long int, lrintf)(float flt) {
|
||||
long int intgr;
|
||||
_asm {
|
||||
fld flt
|
||||
fistp intgr
|
||||
};
|
||||
return intgr;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# include <math.h>
|
||||
|
||||
# ifndef lrint
|
||||
# define lrint(dbl) ((long int)(dbl))
|
||||
# endif
|
||||
# ifndef lrintf
|
||||
# define lrintf(flt) ((long int)(flt))
|
||||
# endif
|
||||
|
||||
#endif /* defined(HAVE_LRINT) && defined(HAVE_LRINTF) */
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
/* compiler symbols:
|
||||
__BORLANDC__
|
||||
_MSC_VER
|
||||
__WATCOMC__
|
||||
__LCC__
|
||||
__GNUC__
|
||||
__DMC__
|
||||
__POCC__
|
||||
*/
|
||||
|
||||
/* C99 compiler? */
|
||||
#if (defined(__STD_VERSION__) && (__STD_VERSION__ >= 199901))
|
||||
# define HAVE_STDINT_H
|
||||
#endif
|
||||
|
||||
#if defined(__LCC__) || defined(__GNUC__) || defined(__DMC__) \
|
||||
|| defined(__POCC__)
|
||||
# define HAVE_STDINT_H
|
||||
#endif
|
||||
|
||||
/* bool types (C++ has it): */
|
||||
#ifdef __cplusplus
|
||||
# ifndef NIM_TRUE
|
||||
# define NIM_TRUE true
|
||||
# endif
|
||||
# ifndef NIM_FALSE
|
||||
# define NIM_FALSE false
|
||||
# endif
|
||||
# define NIM_BOOL bool
|
||||
#else
|
||||
# ifdef bool
|
||||
# define NIM_BOOL bool
|
||||
# else
|
||||
typedef unsigned char NIM_BOOL;
|
||||
# endif
|
||||
# ifndef NIM_TRUE
|
||||
# define NIM_TRUE ((NIM_BOOL) 1)
|
||||
# endif
|
||||
# ifndef NIM_FALSE
|
||||
# define NIM_FALSE ((NIM_BOOL) 0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define NIM_NIL ((void*)0) /* C's NULL is fucked up in some C compilers, so
|
||||
the generated code does not rely on it anymore */
|
||||
|
||||
#if defined(HAVE_STDINT_H)
|
||||
# include <stdint.h>
|
||||
typedef int8_t NS8;
|
||||
typedef int16_t NS16;
|
||||
typedef int32_t NS32;
|
||||
typedef int64_t NS64;
|
||||
typedef uint64_t NU64;
|
||||
typedef uint8_t NU8;
|
||||
typedef uint16_t NU16;
|
||||
typedef uint32_t NU32;
|
||||
#elif defined(__BORLANDC__) || defined(__DMC__) \
|
||||
|| defined(__WATCOMC__) || defined(_MSC_VER)
|
||||
typedef signed char NS8;
|
||||
typedef signed short int NS16;
|
||||
typedef signed int NS32;
|
||||
/* XXX: Float128? */
|
||||
typedef unsigned char NU8;
|
||||
typedef unsigned short int NU16;
|
||||
typedef unsigned __int64 NU64;
|
||||
typedef __int64 NS64;
|
||||
typedef unsigned int NU32;
|
||||
#else
|
||||
typedef signed char NS8;
|
||||
typedef signed short int NS16;
|
||||
typedef signed int NS32;
|
||||
/* XXX: Float128? */
|
||||
typedef unsigned char NU8;
|
||||
typedef unsigned short int NU16;
|
||||
typedef unsigned long long int NU64;
|
||||
typedef long long int NS64;
|
||||
typedef unsigned int NU32;
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (defined(AMD64) || defined(_M_AMD64))
|
||||
/* Microsoft C is brain-dead in this case; long is still not an int64 */
|
||||
typedef unsigned long long int NU;
|
||||
typedef signed long long int NS;
|
||||
#else
|
||||
typedef unsigned long int NU; /* note: int would be wrong for AMD64 */
|
||||
typedef signed long int NS;
|
||||
#endif
|
||||
|
||||
typedef float NF32;
|
||||
typedef double NF64;
|
||||
typedef double NF;
|
||||
|
||||
typedef char NIM_CHAR;
|
||||
typedef char* NCSTRING;
|
||||
|
||||
#ifdef NIM_BIG_ENDIAN
|
||||
# define NIM_IMAN 1
|
||||
#else
|
||||
# define NIM_IMAN 0
|
||||
#endif
|
||||
|
||||
static N_INLINE(NS32, float64ToInt32)(double val) {
|
||||
val = val + 68719476736.0*1.5;
|
||||
/* 2^36 * 1.5, (52-_shiftamt=36) uses limited precisicion to floor */
|
||||
return ((NS32*)&val)[NIM_IMAN] >> 16; /* 16.16 fixed point representation */
|
||||
}
|
||||
|
||||
static N_INLINE(NS32, float32ToInt32)(float val) {
|
||||
return float64ToInt32((double)val);
|
||||
}
|
||||
|
||||
#define zeroMem(a, size) memset(a, 0, size)
|
||||
#define equalMem(a, b, size) (memcmp(a, b, size) == 0)
|
||||
|
||||
#define STRING_LITERAL(name, str, length) \
|
||||
static const struct { \
|
||||
NS len, space; \
|
||||
NIM_CHAR data[length + 1]; \
|
||||
} name = {length, length, str}
|
||||
|
||||
typedef struct TStringDesc* string;
|
||||
|
||||
/* declared size of a sequence: */
|
||||
#if defined(__GNUC__)
|
||||
# define SEQ_DECL_SIZE /* empty is correct! */
|
||||
#else
|
||||
# define SEQ_DECL_SIZE 1000000
|
||||
#endif
|
||||
|
||||
#define ALLOC_0(size) calloc(1, size)
|
||||
#define DL_ALLOC_0(size) dlcalloc(1, size)
|
||||
|
||||
#define GenericSeqSize sizeof(TGenericSeq)
|
||||
#define paramCount() cmdCount
|
||||
|
||||
#ifndef NAN
|
||||
# define NAN (0.0 / 0.0)
|
||||
#endif
|
||||
|
||||
#ifndef INF
|
||||
# ifdef INFINITY
|
||||
# define INF INFINITY
|
||||
# elif defined(HUGE_VAL)
|
||||
# define INF HUGE_VAL
|
||||
# else
|
||||
# define INF (1.0 / 0.0)
|
||||
# endif
|
||||
#endif
|
||||
/*
|
||||
typedef struct TSafePoint TSafePoint;
|
||||
struct TSafePoint {
|
||||
NS exc;
|
||||
NCSTRING excname;
|
||||
NCSTRING msg;
|
||||
TSafePoint* prev;
|
||||
jmp_buf context;
|
||||
}; */
|
||||
|
||||
typedef struct TFrame TFrame;
|
||||
struct TFrame {
|
||||
TFrame* prev;
|
||||
NCSTRING procname;
|
||||
NS line;
|
||||
NCSTRING filename;
|
||||
NS len;
|
||||
};
|
||||
|
||||
extern TFrame* volatile framePtr;
|
||||
/*extern TSafePoint* volatile excHandler; */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
struct NimException {
|
||||
TSafePoint sp;
|
||||
|
||||
NimException(NS aExc, NCSTRING aExcname, NCSTRING aMsg) {
|
||||
sp.exc = aExc; sp.excname = aExcname; sp.msg = aMsg;
|
||||
sp.prev = excHandler;
|
||||
excHandler = &sp;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct TStringDesc {
|
||||
NS len;
|
||||
NS space;
|
||||
NIM_CHAR data[1]; /* SEQ_DECL_SIZE]; */
|
||||
} TStringDesc;
|
||||
|
||||
typedef struct {
|
||||
NS len, space;
|
||||
} TGenericSeq;
|
||||
|
||||
typedef TGenericSeq* PGenericSeq;
|
||||
|
||||
#endif
|
||||
39
lib/optparse.nim
Executable file
39
lib/optparse.nim
Executable file
@@ -0,0 +1,39 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
## This module provides a command line parser.
|
||||
## It supports one iterator over all command line options.
|
||||
|
||||
#interface
|
||||
|
||||
{.push debugger: off.}
|
||||
|
||||
import
|
||||
os
|
||||
|
||||
proc findSep(s: string): int {.nostatic.} =
|
||||
for i in 0 .. high(s)-1:
|
||||
if s[i] in {'=', ':'}: return i
|
||||
return high(s)+1
|
||||
|
||||
iterator getopt*(): tuple[string, string] =
|
||||
# returns a (cmd, arg) tuple.
|
||||
for k in 1 .. ParamCount():
|
||||
var param = paramStr(k)
|
||||
if param[0] == '-':
|
||||
var j = findSep(param)
|
||||
cmd = copy(param, 0, j-1)
|
||||
arg = copy(param, j+1)
|
||||
else:
|
||||
cmd = ""
|
||||
arg = param
|
||||
yield cmd, arg
|
||||
|
||||
{.pop.}
|
||||
939
lib/os.nim
Executable file
939
lib/os.nim
Executable file
@@ -0,0 +1,939 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Basic operating system facilities like retrieving environment variables,
|
||||
## reading command line arguments, working with directories, running shell
|
||||
## commands, etc. This module is -- like any other basic library --
|
||||
## platform independant.
|
||||
|
||||
{.push debugger:off.}
|
||||
|
||||
import
|
||||
strutils, times
|
||||
|
||||
# copied from excpt.nim, because I don't want to make this template public
|
||||
template newException(exceptn, message: expr): expr =
|
||||
block: # open a new scope
|
||||
var
|
||||
e: ref exceptn
|
||||
new(e)
|
||||
e.msg = message
|
||||
e
|
||||
|
||||
when defined(windows) or defined(OS2) or defined(DOS):
|
||||
{.define: doslike.} # DOS-like filesystem
|
||||
|
||||
when defined(Nimdoc): # only for proper documentation:
|
||||
const
|
||||
CurDir* = '.'
|
||||
## The constant string used by the operating system to refer to the
|
||||
## current directory.
|
||||
##
|
||||
## For example: '.' for POSIX or ':' for the classic Macintosh.
|
||||
|
||||
ParDir* = ".."
|
||||
## The constant string used by the operating system to refer to the parent
|
||||
## directory.
|
||||
##
|
||||
## For example: ".." for POSIX or "::" for the classic Macintosh.
|
||||
|
||||
DirSep* = '/'
|
||||
## The character used by the operating system to separate pathname
|
||||
## components, for example, '/' for POSIX or ':' for the classic
|
||||
## Macintosh.
|
||||
##
|
||||
## Note that knowing this is not sufficient to be able to parse or
|
||||
## concatenate pathnames -- use `splitPath` and `joinPath` instead --
|
||||
## but it is occasionally useful.
|
||||
|
||||
AltSep* = '/'
|
||||
## An alternative character used by the operating system to separate
|
||||
## pathname components, or the same as `DirSep` if only one separator
|
||||
## character exists. This is set to '/' on Windows systems where `DirSep`
|
||||
## is a backslash.
|
||||
|
||||
PathSep* = ':'
|
||||
## The character conventionally used by the operating system to separate
|
||||
## search patch components (as in PATH), such as ':' for POSIX or ';' for
|
||||
## Windows.
|
||||
|
||||
FileSystemCaseSensitive* = True
|
||||
## True if the file system is case sensitive, false otherwise. Used by
|
||||
## `cmpPaths` to compare filenames properly.
|
||||
|
||||
elif defined(macos):
|
||||
const
|
||||
curdir* = ':'
|
||||
pardir* = "::"
|
||||
dirsep* = ':'
|
||||
altsep* = dirsep
|
||||
pathsep* = ','
|
||||
FileSystemCaseSensitive* = false
|
||||
|
||||
# MacOS paths
|
||||
# ===========
|
||||
# MacOS directory separator is a colon ":" which is the only character not
|
||||
# allowed in filenames.
|
||||
#
|
||||
# A path containing no colon or which begins with a colon is a partial path.
|
||||
# E.g. ":kalle:petter" ":kalle" "kalle"
|
||||
#
|
||||
# All other paths are full (absolute) paths. E.g. "HD:kalle:" "HD:"
|
||||
# When generating paths, one is safe if one ensures that all partial paths
|
||||
# begin with a colon, and all full paths end with a colon.
|
||||
# In full paths the first name (e g HD above) is the name of a mounted
|
||||
# volume.
|
||||
# These names are not unique, because, for instance, two diskettes with the
|
||||
# same names could be inserted. This means that paths on MacOS is not
|
||||
# waterproof. In case of equal names the first volume found will do.
|
||||
# Two colons "::" are the relative path to the parent. Three is to the
|
||||
# grandparent etc.
|
||||
elif defined(doslike):
|
||||
const
|
||||
curdir* = '.'
|
||||
pardir* = ".."
|
||||
dirsep* = '\\' # seperator within paths
|
||||
altsep* = '/'
|
||||
pathSep* = ';' # seperator between paths
|
||||
FileSystemCaseSensitive* = false
|
||||
elif defined(PalmOS) or defined(MorphOS):
|
||||
const
|
||||
dirsep* = '/'
|
||||
altsep* = dirsep
|
||||
PathSep* = ';'
|
||||
pardir* = ".."
|
||||
FileSystemCaseSensitive* = false
|
||||
elif defined(RISCOS):
|
||||
const
|
||||
dirsep* = '.'
|
||||
altsep* = '.'
|
||||
pardir* = ".." # is this correct?
|
||||
pathSep* = ','
|
||||
FileSystemCaseSensitive* = true
|
||||
else: # UNIX-like operating system
|
||||
const
|
||||
curdir* = '.'
|
||||
pardir* = ".."
|
||||
dirsep* = '/'
|
||||
altsep* = dirsep
|
||||
pathSep* = ':'
|
||||
FileSystemCaseSensitive* = true
|
||||
|
||||
const
|
||||
ExtSep* = '.'
|
||||
## The character which separates the base filename from the extension;
|
||||
## for example, the '.' in ``os.nim``.
|
||||
|
||||
proc getApplicationDir*(): string {.noSideEffect.}
|
||||
## Gets the directory of the application's executable.
|
||||
|
||||
proc getApplicationFilename*(): string {.noSideEffect.}
|
||||
## Gets the filename of the application's executable.
|
||||
|
||||
proc getCurrentDir*(): string {.noSideEffect.}
|
||||
## Gets the current working directory.
|
||||
|
||||
proc setCurrentDir*(newDir: string) {.inline.}
|
||||
## Sets the current working directory; `EOS` is raised if
|
||||
## `newDir` cannot been set.
|
||||
|
||||
proc getHomeDir*(): string {.noSideEffect.}
|
||||
## Gets the home directory of the current user.
|
||||
|
||||
proc getConfigDir*(): string {.noSideEffect.}
|
||||
## Gets the config directory of the current user for applications.
|
||||
|
||||
proc expandFilename*(filename: string): string
|
||||
## Returns the full path of `filename`, "" on error.
|
||||
|
||||
proc ExistsFile*(filename: string): bool
|
||||
## Returns true if the file exists, false otherwise.
|
||||
|
||||
proc JoinPath*(head, tail: string): string {.noSideEffect.}
|
||||
## Joins two directory names to one.
|
||||
##
|
||||
## For example on Unix::
|
||||
##
|
||||
## JoinPath("usr", "lib")
|
||||
##
|
||||
## results in::
|
||||
##
|
||||
## "usr/lib"
|
||||
##
|
||||
## If head is the empty string, tail is returned.
|
||||
## If tail is the empty string, head is returned.
|
||||
|
||||
proc `/` * (head, tail: string): string {.noSideEffect.} =
|
||||
## The same as ``joinPath(head, tail)``
|
||||
return joinPath(head, tail)
|
||||
|
||||
proc JoinPath*(parts: openarray[string]): string {.noSideEffect.}
|
||||
## The same as `JoinPath(head, tail)`, but works with any number
|
||||
## of directory parts.
|
||||
|
||||
proc SplitPath*(path: string, head, tail: var string) {.noSideEffect.}
|
||||
## Splits a directory into (head, tail), so that
|
||||
## ``JoinPath(head, tail) == path``.
|
||||
##
|
||||
## Example: After ``SplitPath("usr/local/bin", head, tail)``,
|
||||
## `head` is "usr/local" and `tail` is "bin".
|
||||
## Example: After ``SplitPath("usr/local/bin/", head, tail)``,
|
||||
## `head` is "usr/local/bin" and `tail` is "".
|
||||
|
||||
proc parentDir*(path: string): string {.noSideEffect.}
|
||||
## Returns the parent directory of `path`.
|
||||
##
|
||||
## This is often the same as the ``head`` result of ``splitPath``.
|
||||
## If there is no parent, ``path`` is returned.
|
||||
## Example: ``parentDir("/usr/local/bin") == "/usr/local"``.
|
||||
## Example: ``parentDir("/usr/local/bin/") == "/usr/local"``.
|
||||
|
||||
proc `/../` * (head, tail: string): string {.noSideEffect.} =
|
||||
## The same as ``parentDir(head) / tail``
|
||||
return parentDir(head) / tail
|
||||
|
||||
proc UnixToNativePath*(path: string): string {.noSideEffect.}
|
||||
## Converts an UNIX-like path to a native one.
|
||||
##
|
||||
## On an UNIX system this does nothing. Else it converts
|
||||
## '/', '.', '..' to the appropriate things.
|
||||
|
||||
proc SplitFilename*(filename: string, name, extension: var string) {.
|
||||
noSideEffect.}
|
||||
## Splits a filename into (name, extension), so that
|
||||
## ``name & extension == filename``.
|
||||
##
|
||||
## Example: After ``SplitFilename("usr/local/nimrodc.html", name, ext)``,
|
||||
## `name` is "usr/local/nimrodc" and `ext` is ".html".
|
||||
## It the file has no extension, extention is the empty string.
|
||||
|
||||
proc extractDir*(path: string): string {.noSideEffect.}
|
||||
## Extracts the directory of a given path. This is the `head`
|
||||
## result of `splitPath`.
|
||||
|
||||
proc extractFilename*(path: string): string {.noSideEffect.}
|
||||
## Extracts the filename of a given `path`. This the the `tail`
|
||||
## result of `splitPath`.
|
||||
# XXX: this is not true: /usr/lib/ --> filename should be empty!
|
||||
|
||||
proc cmpPaths*(pathA, pathB: string): int {.noSideEffect.}
|
||||
## Compares two paths.
|
||||
##
|
||||
## On a case-sensitive filesystem this is done
|
||||
## case-sensitively otherwise case-insensitively. Returns:
|
||||
##
|
||||
## | 0 iff pathA == pathB
|
||||
## | < 0 iff pathA < pathB
|
||||
## | > 0 iff pathA > pathB
|
||||
|
||||
proc AppendFileExt*(filename, ext: string): string {.noSideEffect.}
|
||||
## Appends the file extension `ext` to the `filename`, even if
|
||||
## the `filename` already has an extension.
|
||||
##
|
||||
## `Ext` should be given without the leading '.', because some
|
||||
## filesystems may use a different character.
|
||||
## (Although I know of none such beast.)
|
||||
|
||||
proc ChangeFileExt*(filename, ext: string): string {.noSideEffect.}
|
||||
## Changes the file extension to `ext`.
|
||||
##
|
||||
## If the `filename` has no extension, `ext` will be added.
|
||||
## If `ext` == "" then the filename will get no extension.
|
||||
## `Ext` should be given without the leading '.', because some
|
||||
## filesystems may use a different character. (Although I know
|
||||
## of none such beast.)
|
||||
|
||||
# procs dealing with processes:
|
||||
proc executeProcess*(command: string): int
|
||||
## Executes a process.
|
||||
##
|
||||
## Command has the form 'program args' where args are the command
|
||||
## line arguments given to program. The proc returns the error code
|
||||
## of the process when it has finished. The proc does not return
|
||||
## until the process has finished.
|
||||
|
||||
proc executeShellCommand*(command: string): int
|
||||
## Executes a shell command.
|
||||
##
|
||||
## The syntax of the command is unspecified and depends on the used
|
||||
## shell. The proc returns the error code of the shell when it has finished.
|
||||
|
||||
# procs operating on a high level for files:
|
||||
proc copyFile*(dest, source: string)
|
||||
## Copies a file from `dest` to `source`. If this fails,
|
||||
## `EOS` is raised.
|
||||
|
||||
proc moveFile*(dest, source: string)
|
||||
## Moves a file from `dest` to `source`. If this fails, `EOS` is raised.
|
||||
|
||||
proc removeFile*(file: string)
|
||||
## Removes the `file`. If this fails, `EOS` is raised.
|
||||
|
||||
proc removeDir*(dir: string)
|
||||
## Removes the directory `dir` including all subdirectories or files
|
||||
## in `dir` (recursively). If this fails, `EOS` is raised.
|
||||
|
||||
proc createDir*(dir: string)
|
||||
## Creates the directory `dir`.
|
||||
##
|
||||
## The directory may contain several
|
||||
## subdirectories that do not exist yet. The full path is created. If this
|
||||
## fails, `EOS` is raised. It does NOT fail if the path already exists
|
||||
## because for most usages this does not indicate an error.
|
||||
|
||||
proc existsDir*(dir: string): bool
|
||||
## Returns true iff the directory `dir` exists. If `dir` is a file, false
|
||||
## is returned.
|
||||
|
||||
proc getLastModificationTime*(file: string): TTime
|
||||
## Gets the time of the `file`'s last modification.
|
||||
|
||||
# procs dealing with environment variables:
|
||||
proc putEnv*(key, val: string)
|
||||
## Sets the value of the environment variable named `key` to `val`.
|
||||
## If an error occurs, `EInvalidEnvVar` is raised.
|
||||
|
||||
proc getEnv*(key: string): string
|
||||
## Gets the value of the environment variable named `key`.
|
||||
##
|
||||
## If the variable does not exist, "" is returned. To distinguish
|
||||
## whether a variable exists or it's value is just "", call
|
||||
## `existsEnv(key)`.
|
||||
|
||||
proc existsEnv*(key: string): bool
|
||||
## Checks whether the environment variable named `key` exists.
|
||||
## Returns true if it exists, false otherwise.
|
||||
|
||||
# procs dealing with command line arguments:
|
||||
proc paramCount*(): int
|
||||
## Returns the number of command line arguments given to the
|
||||
## application.
|
||||
|
||||
proc paramStr*(i: int): string
|
||||
## Returns the `i`-th command line arguments given to the
|
||||
## application.
|
||||
##
|
||||
## `i` should be in the range `1..paramCount()`, else
|
||||
## the `EOutOfIndex` exception is raised.
|
||||
|
||||
# implementation
|
||||
|
||||
proc UnixToNativePath(path: string): string =
|
||||
when defined(unix):
|
||||
result = path
|
||||
else:
|
||||
var start: int
|
||||
if path[0] == '/':
|
||||
# an absolute path
|
||||
when defined(doslike):
|
||||
result = r"C:\"
|
||||
elif defined(macos):
|
||||
result = "" # must not start with ':'
|
||||
else:
|
||||
result = $dirSep
|
||||
start = 1
|
||||
elif path[0] == '.' and path[1] == '/':
|
||||
# current directory
|
||||
result = $curdir
|
||||
start = 2
|
||||
else:
|
||||
result = ""
|
||||
start = 0
|
||||
|
||||
var i = start
|
||||
while i < len(path): # ../../../ --> ::::
|
||||
if path[i] == '.' and path[i+1] == '.' and path[i+2] == '/':
|
||||
# parent directory
|
||||
when defined(macos):
|
||||
if result[high(result)] == ':':
|
||||
add result, ':'
|
||||
else:
|
||||
add result, pardir
|
||||
else:
|
||||
add result, pardir & dirSep
|
||||
inc(i, 3)
|
||||
elif path[i] == '/':
|
||||
add result, dirSep
|
||||
inc(i)
|
||||
else:
|
||||
add result, $path[i]
|
||||
inc(i)
|
||||
|
||||
# interface to C library:
|
||||
|
||||
type
|
||||
TStat {.importc: "struct stat".} = record
|
||||
st_dev: int16
|
||||
st_ino: int16
|
||||
st_mode: int16
|
||||
st_nlink: int16
|
||||
st_uid: int16
|
||||
st_gid: int16
|
||||
st_rdev: int32
|
||||
st_size: int32
|
||||
st_atime: TTime
|
||||
st_mtime: TTime
|
||||
st_ctime: TTime
|
||||
|
||||
var
|
||||
errno {.importc: "errno", header: "<errno.h>".}: cint
|
||||
EEXIST {.importc: "EEXIST", header: "<errno.h>".}: cint
|
||||
|
||||
when defined(unix):
|
||||
const dirHeader = "<sys/stat.h>"
|
||||
elif defined(windows):
|
||||
const dirHeader = "<direct.h>"
|
||||
else:
|
||||
{.error: "os library not ported to your OS. Please help!".}
|
||||
|
||||
|
||||
proc chdir(path: CString): cint {.importc: "chdir", header: dirHeader.}
|
||||
|
||||
when defined(unix):
|
||||
proc mkdir(dir: CString, theAccess: cint): cint {.
|
||||
importc: "mkdir", header: dirHeader.}
|
||||
proc realpath(name, resolved: CString): CString {.
|
||||
importc: "realpath", header: "<stdlib.h>".}
|
||||
proc getcwd(buf: CString, buflen: cint): CString {.
|
||||
importc: "getcwd", header: "<unistd.h>".}
|
||||
elif defined(windows):
|
||||
proc mkdir(dir: CString): cint {.
|
||||
importc: "mkdir", header: dirHeader.}
|
||||
proc fullpath(buffer, file: CString, size: int): CString {.
|
||||
importc: "_fullpath", header: "<stdlib.h>".}
|
||||
proc getcwd(buf: CString, buflen: cint): CString {.
|
||||
importc: "getcwd", header: "<direct.h>".}
|
||||
|
||||
proc CreateDirectory(pathName: cstring, security: Pointer): cint {.
|
||||
importc: "CreateDirectory", header: "<windows.h>".}
|
||||
proc GetLastError(): cint {.importc, header: "<windows.h>".}
|
||||
else:
|
||||
{.error: "os library not ported to your OS. Please help!".}
|
||||
|
||||
|
||||
proc rmdir(dir: CString): cint {.importc: "rmdir", header: "<time.h>".}
|
||||
# rmdir is of course in ``dirHeader``, but we check here to include
|
||||
# time.h which is needed for stat(). stat() needs time.h and
|
||||
# sys/stat.h; we workaround a C library issue here.
|
||||
|
||||
proc free(c: cstring) {.importc: "free", nodecl.}
|
||||
# some C procs return a buffer that has to be freed with free(),
|
||||
# so we define it here
|
||||
proc strlen(str: CString): int {.importc: "strlen", nodecl.}
|
||||
|
||||
proc stat(f: CString, res: var TStat): cint {.
|
||||
importc: "stat", header: "<sys/stat.h>".}
|
||||
|
||||
proc sameFile*(path1, path2: string): bool =
|
||||
## Returns True if both pathname arguments refer to the same file or
|
||||
## directory (as indicated by device number and i-node number).
|
||||
## Raises an exception if an os.stat() call on either pathname fails.
|
||||
var
|
||||
a, b: TStat
|
||||
if stat(path1, a) < 0 or stat(path2, b) < 0:
|
||||
raise newException(EOS, "stat() call failed")
|
||||
return int(a.st_dev) == b.st_dev and int(a.st_ino) == b.st_ino
|
||||
|
||||
when defined(windows):
|
||||
proc getModuleFilename(handle: int32, buf: CString, size: int32): int32 {.
|
||||
importc: "GetModuleFileName", header: "<windows.h>".}
|
||||
|
||||
proc getLastModificationTime(file: string): TTime =
|
||||
var
|
||||
res: TStat
|
||||
discard stat(file, res)
|
||||
return res.st_mtime
|
||||
|
||||
proc setCurrentDir(newDir: string) =
|
||||
if chdir(newDir) != 0:
|
||||
raise newException(EOS, "cannot change the working directory to '$1'" %
|
||||
newDir)
|
||||
|
||||
when defined(linux) or defined(solaris) or defined(bsd):
|
||||
proc readlink(link, buf: cstring, size: int): int {.
|
||||
header: "<unistd.h>", cdecl.}
|
||||
|
||||
proc getApplAux(procPath: string): string =
|
||||
result = newString(256)
|
||||
var len = readlink(procPath, result, 256)
|
||||
if len > 256:
|
||||
result = newString(len+1)
|
||||
len = readlink(procPath, result, len)
|
||||
setlen(result, len)
|
||||
|
||||
when defined(solaris) or defined(bsd):
|
||||
proc getpid(): int {.importc, header: "<unistd.h>", cdecl.}
|
||||
|
||||
proc getApplicationFilename(): string =
|
||||
# Linux: /proc/<pid>/exe
|
||||
# Solaris:
|
||||
# /proc/<pid>/object/a.out (filename only)
|
||||
# /proc/<pid>/path/a.out (complete pathname)
|
||||
# *BSD (and maybe Darwing too):
|
||||
# /proc/<pid>/file
|
||||
when defined(windows):
|
||||
result = newString(256)
|
||||
var len = getModuleFileName(0, result, 256)
|
||||
setlen(result, int(len))
|
||||
elif defined(linux):
|
||||
result = getApplAux("/proc/self/exe")
|
||||
elif defined(solaris):
|
||||
result = getApplAux("/proc/" & $getpid() & "/path/a.out")
|
||||
elif defined(bsd):
|
||||
result = getApplAux("/proc/" & $getpid() & "file")
|
||||
else:
|
||||
# little heuristic that may work on other POSIX-like systems:
|
||||
result = getEnv("_")
|
||||
if len(result) == 0:
|
||||
result = ParamStr(0) # POSIX guaranties that this contains the executable
|
||||
# as it has been executed by the calling process
|
||||
if len(result) > 0 and result[0] != DirSep: # not an absolute path?
|
||||
# iterate over any path in the $PATH environment variable
|
||||
for p in split(getEnv("PATH"), {PathSep}):
|
||||
var x = joinPath(p, result)
|
||||
if ExistsFile(x): return x
|
||||
|
||||
{.push warnings: off.}
|
||||
proc getApplicationDir(): string =
|
||||
var tail: string
|
||||
splitPath(getApplicationFilename(), result, tail)
|
||||
{.pop.}
|
||||
|
||||
proc getCurrentDir(): string =
|
||||
const
|
||||
bufsize = 512 # should be enough
|
||||
result = newString(bufsize)
|
||||
if getcwd(result, bufsize) != nil:
|
||||
setlen(result, strlen(result))
|
||||
else:
|
||||
raise newException(EOS, "getcwd failed")
|
||||
|
||||
proc JoinPath(head, tail: string): string =
|
||||
if len(head) == 0:
|
||||
result = tail
|
||||
elif head[len(head)-1] in {DirSep, AltSep}:
|
||||
if tail[0] in {DirSep, AltSep}:
|
||||
result = head & copy(tail, 1)
|
||||
else:
|
||||
result = head & tail
|
||||
else:
|
||||
if tail[0] in {DirSep, AltSep}:
|
||||
result = head & tail
|
||||
else:
|
||||
result = head & DirSep & tail
|
||||
|
||||
proc JoinPath(parts: openarray[string]): string =
|
||||
result = parts[0]
|
||||
for i in 1..high(parts):
|
||||
result = JoinPath(result, parts[i])
|
||||
|
||||
proc parentDir(path: string): string =
|
||||
var
|
||||
sepPos = -1
|
||||
q = 1
|
||||
if path[len(path)-1] in {dirsep, altsep}:
|
||||
q = 2
|
||||
for i in countdown(len(path)-q, 0):
|
||||
if path[i] in {dirsep, altsep}:
|
||||
sepPos = i
|
||||
break
|
||||
if sepPos >= 0:
|
||||
result = copy(path, 0, sepPos-1)
|
||||
else:
|
||||
result = path
|
||||
|
||||
proc SplitPath(path: string, head, tail: var string) =
|
||||
var
|
||||
sepPos = -1
|
||||
for i in countdown(len(path)-1, 0):
|
||||
if path[i] in {dirsep, altsep}:
|
||||
sepPos = i
|
||||
break
|
||||
if sepPos >= 0:
|
||||
head = copy(path, 0, sepPos-1)
|
||||
tail = copy(path, sepPos+1)
|
||||
else:
|
||||
head = ""
|
||||
tail = path # make a string copy here
|
||||
|
||||
# helper:
|
||||
proc searchExtPos(s: string): int =
|
||||
result = -1
|
||||
for i in countdown(len(s)-1, 0):
|
||||
if s[i] == extsep:
|
||||
result = i
|
||||
break
|
||||
elif s[i] in {dirsep, altsep}:
|
||||
break # do not skip over path
|
||||
|
||||
proc SplitFilename(filename: string, name, extension: var string) =
|
||||
var
|
||||
extPos = searchExtPos(filename)
|
||||
if extPos >= 0:
|
||||
name = copy(filename, 0, extPos-1)
|
||||
extension = copy(filename, extPos)
|
||||
else:
|
||||
name = filename # make a string copy here
|
||||
extension = ""
|
||||
|
||||
proc normExt(ext: string): string =
|
||||
if ext == "" or ext[0] == extSep: result = ext # no copy needed here
|
||||
else: result = extSep & ext
|
||||
|
||||
proc ChangeFileExt(filename, ext: string): string =
|
||||
var
|
||||
extPos = searchExtPos(filename)
|
||||
if extPos < 0: result = filename & normExt(ext)
|
||||
else: result = copy(filename, 0, extPos-1) & normExt(ext)
|
||||
|
||||
proc AppendFileExt(filename, ext: string): string =
|
||||
var
|
||||
extPos = searchExtPos(filename)
|
||||
if extPos < 0: result = filename & normExt(ext)
|
||||
else: result = filename #make a string copy here
|
||||
|
||||
# some more C things:
|
||||
|
||||
proc csystem(cmd: CString): cint {.importc: "system", noDecl.}
|
||||
# is in <stdlib.h>!
|
||||
|
||||
when defined(wcc):
|
||||
# everywhere it is in <stdlib.h>, except for Watcom C ...
|
||||
proc cputenv(env: CString): cint {.importc: "putenv", header: "<process.h>".}
|
||||
|
||||
else: # is in <stdlib.h>
|
||||
proc cputenv(env: CString): cint {.importc: "putenv", noDecl.}
|
||||
|
||||
proc cgetenv(env: CString): CString {.importc: "getenv", noDecl.}
|
||||
|
||||
#long _findfirst(char *, struct _finddata_t *);
|
||||
#int _findnext(long, struct _finddata_t *);
|
||||
#int _findclose(long);
|
||||
when defined(windows):
|
||||
type
|
||||
TFindData {.importc: "struct _finddata_t".} = record
|
||||
attrib {.importc: "attrib".}: cint
|
||||
time_create {.importc: "time_create".}: cint
|
||||
time_access {.importc: "time_access".}: cint
|
||||
time_write {.importc: "time_write".}: cint
|
||||
size {.importc: "size".}: cint
|
||||
name {.importc: "name".}: array[0..259, char]
|
||||
|
||||
proc findfirst(pathname: CString, f: ptr TFindData): cint {.
|
||||
importc: "_findfirst", header: "<io.h>".}
|
||||
proc findnext(handle: cint, f: ptr TFindData): cint {.
|
||||
importc: "_findnext", header: "<io.h>".}
|
||||
proc findclose(handle: cint) {.importc: "_findclose", header: "<io.h>".}
|
||||
else:
|
||||
type
|
||||
TFindData {.importc: "glob_t".} = record
|
||||
gl_pathc: int # count of paths matched by pattern
|
||||
gl_pathv: ptr array[0..1000_000, CString] # list of matched path names
|
||||
gl_offs: int # slots to reserve at beginning of gl_pathv
|
||||
PFindData = ptr TFindData
|
||||
|
||||
proc glob(pattern: cstring, flags: cint, errfunc: pointer,
|
||||
pglob: PFindData): cint {.
|
||||
importc: "glob", header: "<glob.h>".}
|
||||
|
||||
proc globfree(pglob: PFindData) {.
|
||||
importc: "globfree", header: "<glob.h>".}
|
||||
|
||||
proc cremove(filename: CString): cint {.importc: "remove", noDecl.}
|
||||
proc crename(oldname, newname: CString): cint {.importc: "rename", noDecl.}
|
||||
|
||||
when defined(Windows):
|
||||
proc cCopyFile(lpExistingFileName, lpNewFileName: CString,
|
||||
bFailIfExists: cint): cint {.
|
||||
importc: "CopyFile", header: "<windows.h>".}
|
||||
# cMoveFile(lpExistingFileName, lpNewFileName: CString): int
|
||||
# {.importc: "MoveFile", noDecl, header: "<winbase.h>".}
|
||||
# cRemoveFile(filename: CString, cmo: int)
|
||||
# {.importc: "DeleteFile", noDecl, header: "<winbase.h>".}
|
||||
else:
|
||||
# generic version of cCopyFile which works for any platform:
|
||||
proc cCopyFile(lpExistingFileName, lpNewFileName: CString,
|
||||
bFailIfExists: cint): cint =
|
||||
const
|
||||
bufSize = 8192 # 8K buffer
|
||||
var
|
||||
dest, src: TFile
|
||||
if not openFile(src, $lpExistingFilename): return -1
|
||||
if not openFile(dest, $lpNewFilename, fmWrite):
|
||||
closeFile(src)
|
||||
return -1
|
||||
var
|
||||
buf: Pointer = alloc(bufsize)
|
||||
bytesread, byteswritten: int
|
||||
while True:
|
||||
bytesread = readBuffer(src, buf, bufsize)
|
||||
byteswritten = writeBuffer(dest, buf, bytesread)
|
||||
if bytesread != bufSize: break
|
||||
if byteswritten == bytesread: result = 0
|
||||
else: result = -1
|
||||
dealloc(buf)
|
||||
closeFile(src)
|
||||
closeFile(dest)
|
||||
|
||||
|
||||
proc moveFile(dest, source: string) =
|
||||
if crename(source, dest) != 0:
|
||||
raise newException(EOS, "cannot move file from '$1' to '$2'" %
|
||||
[source, dest])
|
||||
|
||||
proc copyFile(dest, source: string) =
|
||||
if cCopyFile(source, dest, 0) != 0:
|
||||
raise newException(EOS, "cannot copy file from '$1' to '$2'" %
|
||||
[source, dest])
|
||||
|
||||
proc removeFile(file: string) =
|
||||
if cremove(file) != 0:
|
||||
raise newException(EOS, "cannot remove file '$1'" % file)
|
||||
|
||||
proc removeDir(dir: string) =
|
||||
if rmdir(dir) != 0:
|
||||
raise newException(EOS, "cannot remove directory '$1'" % dir)
|
||||
|
||||
proc createDir(dir: string) =
|
||||
when defined(unix):
|
||||
if mkdir(dir, 0o711) != 0 and int(errno) != EEXIST:
|
||||
raise newException(EOS, "cannot create directory '$1'" % dir)
|
||||
else:
|
||||
if CreateDirectory(dir, nil) == 0 and GetLastError() != 183:
|
||||
raise newException(EOS, "cannot create directory '$1'" % dir)
|
||||
|
||||
proc existsDir(dir: string): bool =
|
||||
var safe = getCurrentDir()
|
||||
# just try to set the current dir to dir; if it works, it must exist:
|
||||
result = chdir(dir) == 0
|
||||
if result:
|
||||
setCurrentDir(safe) # set back to the old working directory
|
||||
|
||||
proc executeProcess(command: string): int =
|
||||
return csystem(command) # XXX: do this without shell
|
||||
|
||||
proc executeShellCommand(command: string): int =
|
||||
return csystem(command)
|
||||
|
||||
var
|
||||
envComputed: bool = false
|
||||
environment {.noStatic.}: seq[string] = []
|
||||
|
||||
when defined(windows):
|
||||
# because we support Windows GUI applications, things get really
|
||||
# messy here...
|
||||
proc GetEnvironmentStrings(): Pointer {.
|
||||
importc: "GetEnvironmentStrings", header: "<windows.h>".}
|
||||
proc FreeEnvironmentStrings(env: Pointer) {.
|
||||
importc: "FreeEnvironmentStrings", header: "<windows.h>".}
|
||||
proc strEnd(cstr: CString, c = 0): CString {.importc: "strchr", nodecl.}
|
||||
|
||||
proc getEnvVarsC() {.noStatic.} =
|
||||
if not envComputed:
|
||||
var
|
||||
env = cast[CString](getEnvironmentStrings())
|
||||
e = env
|
||||
if e == nil: return # an error occured
|
||||
while True:
|
||||
var eend = strEnd(e)
|
||||
add environment, $e
|
||||
e = cast[CString](cast[TAddress](eend)+1)
|
||||
if eend[1] == '\0': break
|
||||
envComputed = true
|
||||
FreeEnvironmentStrings(env)
|
||||
|
||||
else:
|
||||
var
|
||||
gEnv {.importc: "gEnv".}: ptr array [0..10_000, CString]
|
||||
|
||||
proc getEnvVarsC() {.noStatic.} =
|
||||
# retrieves the variables of char** env of C's main proc
|
||||
if not envComputed:
|
||||
var
|
||||
i: int = 0
|
||||
while True:
|
||||
if gEnv[i] == nil: break
|
||||
add environment, $gEnv[i]
|
||||
inc(i)
|
||||
envComputed = true
|
||||
|
||||
proc findEnvVar(key: string): int =
|
||||
getEnvVarsC()
|
||||
var temp = key & '='
|
||||
for i in 0..high(environment):
|
||||
if findSubStr(temp, environment[i]) == 0: return i
|
||||
return -1
|
||||
|
||||
proc getEnv(key: string): string =
|
||||
var i = findEnvVar(key)
|
||||
if i >= 0:
|
||||
return copy(environment[i], findSubStr("=", environment[i])+1)
|
||||
else:
|
||||
var env = cgetenv(key)
|
||||
if env == nil: return ""
|
||||
result = $env
|
||||
|
||||
proc existsEnv(key: string): bool =
|
||||
if cgetenv(key) != nil: return true
|
||||
else: return findEnvVar(key) >= 0
|
||||
|
||||
iterator iterOverEnvironment*(): tuple[string, string] =
|
||||
## Iterate over all environments varialbes. In the first component of the
|
||||
## tuple is the name of the current variable stored, in the second its value.
|
||||
getEnvVarsC()
|
||||
for i in 0..high(environment):
|
||||
var p = findSubStr("=", environment[i])
|
||||
yield (copy(environment[i], 0, p-1), copy(environment[i], p+1))
|
||||
|
||||
proc putEnv(key, val: string) =
|
||||
# Note: by storing the string in the environment sequence,
|
||||
# we gurantee that we don't free the memory before the program
|
||||
# ends (this is needed for POSIX compliance). It is also needed so that
|
||||
# the process itself may access its modified environment variables!
|
||||
var indx = findEnvVar(key)
|
||||
if indx >= 0:
|
||||
environment[indx] = key & '=' & val
|
||||
else:
|
||||
add environment, (key & '=' & val)
|
||||
indx = high(environment)
|
||||
if cputenv(environment[indx]) != 0:
|
||||
raise newException(EOS, "attempt to set an invalid environment variable")
|
||||
|
||||
iterator walkFiles*(pattern: string): string =
|
||||
## Iterate over all the files that match the `pattern`.
|
||||
##
|
||||
## `pattern` is OS dependant, but at least the "\*.ext"
|
||||
## notation is supported.
|
||||
when defined(windows):
|
||||
var
|
||||
f: TFindData
|
||||
res: int
|
||||
res = findfirst(pattern, addr(f))
|
||||
if res != -1:
|
||||
while true:
|
||||
yield $f.name
|
||||
if int(findnext(res, addr(f))) == -1: break
|
||||
findclose(res)
|
||||
else: # here we use glob
|
||||
var
|
||||
f: TFindData
|
||||
res: int
|
||||
f.gl_offs = 0
|
||||
f.gl_pathc = 0
|
||||
f.gl_pathv = nil
|
||||
res = glob(pattern, 0, nil, addr(f))
|
||||
if res != 0: raise newException(EOS, "walkFiles() failed")
|
||||
for i in 0.. f.gl_pathc - 1:
|
||||
assert(f.gl_pathv[i] != nil)
|
||||
yield $f.gl_pathv[i]
|
||||
globfree(addr(f))
|
||||
|
||||
{.push warnings:off.}
|
||||
proc ExistsFile(filename: string): bool =
|
||||
var
|
||||
res: TStat
|
||||
return stat(filename, res) >= 0
|
||||
{.pop.}
|
||||
|
||||
proc cmpPaths(pathA, pathB: string): int =
|
||||
if FileSystemCaseSensitive:
|
||||
result = cmp(pathA, pathB)
|
||||
else:
|
||||
result = cmpIgnoreCase(pathA, pathB)
|
||||
|
||||
proc extractDir(path: string): string =
|
||||
var
|
||||
tail: string
|
||||
splitPath(path, result, tail)
|
||||
|
||||
proc extractFilename(path: string): string =
|
||||
var
|
||||
head: string
|
||||
splitPath(path, head, result)
|
||||
|
||||
proc expandFilename(filename: string): string =
|
||||
# returns the full path of 'filename'; "" on error
|
||||
var
|
||||
res: CString
|
||||
when defined(unix):
|
||||
res = realpath(filename, nil)
|
||||
else:
|
||||
res = fullpath(nil, filename, 0)
|
||||
if res == nil:
|
||||
result = "" # an error occured
|
||||
else:
|
||||
result = $res
|
||||
free(res)
|
||||
|
||||
when defined(windows):
|
||||
proc GetHomeDir(): string = return getEnv("USERPROFILE") & "\\"
|
||||
proc GetConfigDir(): string = return getEnv("APPDATA") & "\\"
|
||||
|
||||
# Since we support GUI applications with Nimrod, we sometimes generate
|
||||
# a WinMain entry proc. But a WinMain proc has no access to the parsed
|
||||
# command line arguments. The way to get them differs. Thus we parse them
|
||||
# ourselves. This has the additional benefit that the program's behaviour
|
||||
# is always the same -- independent of the used C compiler.
|
||||
proc GetCommandLine(): CString {.
|
||||
importc: "GetCommandLine", header: "<windows.h>".}
|
||||
|
||||
var
|
||||
ownArgc: int = -1
|
||||
ownArgv: seq[string] = []
|
||||
|
||||
proc parseCmdLine() =
|
||||
if ownArgc != -1: return # already processed
|
||||
var
|
||||
i = 0
|
||||
j = 0
|
||||
c = getCommandLine()
|
||||
ownArgc = 0
|
||||
while c[i] != '\0':
|
||||
var a = ""
|
||||
while c[i] >= '\1' and c[i] <= ' ': inc(i) # skip whitespace
|
||||
case c[i]
|
||||
of '\'', '\"':
|
||||
var delim = c[i]
|
||||
inc(i) # skip ' or "
|
||||
while c[i] != '\0' and c[i] != delim:
|
||||
add a, c[i]
|
||||
inc(i)
|
||||
if c[i] != '\0': inc(i)
|
||||
else:
|
||||
while c[i] > ' ':
|
||||
add a, c[i]
|
||||
inc(i)
|
||||
add ownArgv, a
|
||||
inc(ownArgc)
|
||||
|
||||
proc paramStr(i: int): string =
|
||||
parseCmdLine()
|
||||
if i < ownArgc and i >= 0:
|
||||
return ownArgv[i]
|
||||
raise newException(EInvalidIndex, "invalid index")
|
||||
|
||||
proc paramCount(): int =
|
||||
parseCmdLine()
|
||||
result = ownArgc-1
|
||||
|
||||
else:
|
||||
proc GetHomeDir(): string = return getEnv("HOME") & "/"
|
||||
proc GetConfigDir(): string = return getEnv("HOME") & "/"
|
||||
|
||||
var
|
||||
cmdCount {.importc: "cmdCount".}: int
|
||||
cmdLine {.importc: "cmdLine".}: cstringArray
|
||||
|
||||
proc paramStr(i: int): string =
|
||||
if i < cmdCount and i >= 0: return $cmdLine[i]
|
||||
raise newException(EInvalidIndex, "invalid index")
|
||||
|
||||
proc paramCount(): int = return cmdCount-1
|
||||
|
||||
{.pop.}
|
||||
1818
lib/posix/posix.nim
Executable file
1818
lib/posix/posix.nim
Executable file
File diff suppressed because it is too large
Load Diff
35
lib/powerpc.asm.in
Executable file
35
lib/powerpc.asm.in
Executable file
@@ -0,0 +1,35 @@
|
||||
; This contains the CPU-dependant variants of some routines.
|
||||
; (C) 2005 Andreas Rumpf
|
||||
; This code was inspired by the Freepascal compiler's sources
|
||||
; All routines here have the _cdecl calling convention because
|
||||
; that is the only convention any C compiler supports.
|
||||
|
||||
\python{
|
||||
def c(name):
|
||||
if os.name == 'posix':
|
||||
return name
|
||||
else:
|
||||
return "_" + name
|
||||
}
|
||||
|
||||
segment code
|
||||
|
||||
global \c{cpu_inc_locked}
|
||||
global \c{cpu_dec_locked}
|
||||
|
||||
\c{cpu_dec_locked}:
|
||||
; input: address of arg in r3
|
||||
.LDecLockedLoop:
|
||||
lwarx r10,0,r3
|
||||
subi r10,r10,1
|
||||
stwcx. r10,0,r3
|
||||
bne- .LDecLockedLoop
|
||||
cntlzw r3,r10
|
||||
srwi r3,r3,5
|
||||
|
||||
\c{cpu_inc_locked}:
|
||||
.LIncLockedLoop:
|
||||
lwarx r10,0,r3
|
||||
addi r10,r10,1
|
||||
stwcx. r10,0,r3
|
||||
bne- .LIncLockedLoop
|
||||
1009
lib/process.nim
Executable file
1009
lib/process.nim
Executable file
File diff suppressed because it is too large
Load Diff
205
lib/ptrset.nim
Executable file
205
lib/ptrset.nim
Executable file
@@ -0,0 +1,205 @@
|
||||
# This implements a new pointer set. Access time O(1). For 32 bit systems, we
|
||||
# currently need 3 memory accesses.
|
||||
|
||||
const
|
||||
PageSize = 1024 * sizeof(int)
|
||||
MemAlignment = 8 # minimal memory block that can be allocated
|
||||
BitsPerUnit = sizeof(int)*8
|
||||
# a "unit" is a word, i.e. 4 bytes
|
||||
# on a 32 bit system; I do not use the term "word" because under 32-bit
|
||||
# Windows it is sometimes only 16 bits
|
||||
|
||||
BitsPerPage = PageSize div MemAlignment
|
||||
UnitsPerPage = BitsPerPage div BitsPerUnit
|
||||
# how many units do we need to describe a page:
|
||||
# on 32 bit systems this is only 16 (!)
|
||||
|
||||
type
|
||||
PPointer = ptr pointer
|
||||
|
||||
TCollectorData = int
|
||||
TCell = record
|
||||
refcount: TCollectorData # the refcount and bit flags
|
||||
typ: PNimType
|
||||
stackcount: int # stack counter for debugging
|
||||
drefc: int # real reference counter for debugging
|
||||
|
||||
PCell = ptr TCell
|
||||
|
||||
proc cellToUsr(cell: PCell): pointer {.inline.} =
|
||||
# convert object (=pointer to refcount) to pointer to userdata
|
||||
result = cast[pointer](cast[TAddress](cell)+%TAddress(sizeof(TCell)))
|
||||
|
||||
proc usrToCell(usr: pointer): PCell {.inline.} =
|
||||
# convert pointer to userdata to object (=pointer to refcount)
|
||||
result = cast[PCell](cast[TAddress](usr)-%TAddress(sizeof(TCell)))
|
||||
|
||||
proc gcAlloc(size: int): pointer =
|
||||
result = alloc0(size)
|
||||
if result == nil: raiseOutOfMem()
|
||||
|
||||
# ------------------ Zero count table (ZCT) and any table (AT) -------------
|
||||
|
||||
# this that has to equals zero, otherwise we have to round up UnitsPerPage:
|
||||
when BitsPerPage mod BitsPerUnit != 0:
|
||||
{.error: "(BitsPerPage mod BitsPerUnit) should be zero!".}
|
||||
|
||||
# ------------------- cell set handling ------------------------------
|
||||
# A cellset consists of a hash table of page descriptors. A page
|
||||
# descriptor has a bit for
|
||||
# every Memalignment'th byte in the page.
|
||||
# However, only bits corresponding to addresses that start memory blocks
|
||||
# are set.
|
||||
# Page descriptors are also linked to a list; the list
|
||||
# is used for easy traversing of all page descriptors; this allows a
|
||||
# fast iterator.
|
||||
# We use a specialized hashing scheme; the formula is :
|
||||
# hash = Page bitand max
|
||||
# We use linear probing with the formular: (5*h)+1
|
||||
# Thus we likely get no collisions at all if the pages are given to us
|
||||
# in a sequential manner by the operating system!
|
||||
const
|
||||
bitsPerNode = 10 # we use 10 bits per node; this means 3 memory accesses on
|
||||
# 32 bit systems
|
||||
|
||||
type
|
||||
PPageDesc = ptr TPageDesc
|
||||
|
||||
TBitIndex = range[0..UnitsPerPage-1]
|
||||
|
||||
TPageDesc = record
|
||||
next: PPageDesc # all nodes are connected with this pointer
|
||||
key: TAddress # start address at bit 0
|
||||
bits: array[TBitIndex, int] # a bit vector
|
||||
|
||||
PPageDescArray = ptr array[0..1000_000, PPageDesc]
|
||||
TCellSet = record
|
||||
counter, max: int
|
||||
head: PPageDesc
|
||||
data: PPageDescArray
|
||||
|
||||
TSetNode = record
|
||||
n: array[0.. (1 shl bitsPerNode)-1, PSetNode]
|
||||
PSetNode = ptr TSetNode
|
||||
|
||||
const
|
||||
InitCellSetSize = 1024 # must be a power of two!
|
||||
|
||||
proc CellSetInit(s: var TCellSet) =
|
||||
s.data = gcAlloc(InitCellSetSize * sizeof(PPageDesc))
|
||||
s.max = InitCellSetSize-1
|
||||
s.counter = 0
|
||||
s.head = nil
|
||||
|
||||
proc CellSetDeinit(s: var TCellSet) =
|
||||
var it = s.head
|
||||
while it != nil:
|
||||
var n = it.next
|
||||
dealloc(it)
|
||||
it = n
|
||||
s.head = nil # play it safe here
|
||||
dealloc(s.data)
|
||||
s.data = nil
|
||||
s.counter = 0
|
||||
|
||||
proc CellSetGet(t: TCellSet, key: TAddress): PPageDesc =
|
||||
var h = cast[int](key) and t.max
|
||||
while t.data[h] != nil:
|
||||
if t.data[h].key == key: return t.data[h]
|
||||
h = nextTry(h, t.max)
|
||||
return nil
|
||||
|
||||
proc CellSetRawInsert(t: TCellSet, data: PPageDescArray,
|
||||
desc: PPageDesc) =
|
||||
var h = cast[int](desc.key) and t.max
|
||||
while data[h] != nil:
|
||||
assert(data[h] != desc)
|
||||
h = nextTry(h, t.max)
|
||||
assert(data[h] == nil)
|
||||
data[h] = desc
|
||||
|
||||
proc CellSetEnlarge(t: var TCellSet) =
|
||||
var
|
||||
n: PPageDescArray
|
||||
oldMax = t.max
|
||||
t.max = ((t.max+1)*2)-1
|
||||
n = gcAlloc((t.max + 1) * sizeof(PPageDesc))
|
||||
for i in 0 .. oldmax:
|
||||
if t.data[i] != nil:
|
||||
CellSetRawInsert(t, n, t.data[i])
|
||||
dealloc(t.data)
|
||||
t.data = n
|
||||
|
||||
proc CellSetPut(t: var TCellSet, key: TAddress): PPageDesc =
|
||||
var h = cast[int](key) and t.max
|
||||
while true:
|
||||
var x = t.data[h]
|
||||
if x == nil: break
|
||||
if x.key == key: return x
|
||||
h = nextTry(h, t.max)
|
||||
|
||||
if (t.max+1) * 2 < t.counter * 3: CellSetEnlarge(t)
|
||||
inc(t.counter)
|
||||
h = cast[int](key) and t.max
|
||||
while t.data[h] != nil: h = nextTry(h, t.max)
|
||||
assert(t.data[h] == nil)
|
||||
# the new page descriptor goes into result
|
||||
result = gcAlloc(sizeof(TPageDesc))
|
||||
result.next = t.head
|
||||
result.key = key
|
||||
t.head = result
|
||||
t.data[h] = result
|
||||
|
||||
# ---------- slightly higher level procs ----------------------------------
|
||||
|
||||
proc in_Operator(s: TCellSet, cell: PCell): bool =
|
||||
var
|
||||
u: TAddress
|
||||
t: PPageDesc
|
||||
u = cast[TAddress](cell)
|
||||
t = CellSetGet(s, u /% PageSize)
|
||||
if t != nil:
|
||||
u = (u %% PageSize) /% MemAlignment
|
||||
result = (t.bits[u /% BitsPerUnit] and (1 shl (u %% BitsPerUnit))) != 0
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc incl(s: var TCellSet, cell: PCell) =
|
||||
var
|
||||
u: TAddress
|
||||
t: PPageDesc
|
||||
u = cast[TAddress](cell)
|
||||
t = CellSetPut(s, u /% PageSize)
|
||||
u = (u %% PageSize) /% MemAlignment
|
||||
t.bits[u /% BitsPerUnit] = t.bits[u /% BitsPerUnit] or
|
||||
(1 shl (u %% BitsPerUnit))
|
||||
|
||||
proc excl(s: var TCellSet, cell: PCell) =
|
||||
var
|
||||
u: TAddress
|
||||
t: PPageDesc
|
||||
u = cast[TAddress](cell)
|
||||
t = CellSetGet(s, u /% PageSize)
|
||||
if t != nil:
|
||||
u = (u %% PageSize) /% MemAlignment
|
||||
t.bits[u %% BitsPerUnit] = (t.bits[u /% BitsPerUnit] and
|
||||
not (1 shl (u %% BitsPerUnit)))
|
||||
|
||||
iterator elements(t: TCellSet): PCell {.inline.} =
|
||||
# while traversing it is forbidden to add pointers to the tree!
|
||||
var r = t.head
|
||||
while r != nil:
|
||||
var i = 0
|
||||
while i <= high(r.bits):
|
||||
var w = r.bits[i] # taking a copy of r.bits[i] here is correct, because
|
||||
# modifying operations are not allowed during traversation
|
||||
var j = 0
|
||||
while w != 0: # test all remaining bits for zero
|
||||
if (w and 1) != 0: # the bit is set!
|
||||
yield cast[PCell]((r.key *% PageSize) +%
|
||||
(i*%BitsPerUnit+%j) *% MemAlignment)
|
||||
inc(j)
|
||||
w = w shr 1
|
||||
inc(i)
|
||||
r = r.next
|
||||
|
||||
233
lib/repr.nim
Executable file
233
lib/repr.nim
Executable file
@@ -0,0 +1,233 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# The generic ``repr`` procedure. It is an invaluable debugging tool.
|
||||
|
||||
#proc cstrToNimStrDummy(s: cstring): string {.inline.} =
|
||||
# result = cast[string](cstrToNimStr(s))
|
||||
|
||||
proc reprInt(x: int64): string {.compilerproc.} = return $x
|
||||
proc reprFloat(x: float): string {.compilerproc.} = return $x
|
||||
|
||||
proc reprPointer(x: pointer): string {.compilerproc.} =
|
||||
var buf: array [0..59, char]
|
||||
c_sprintf(buf, "%p", x)
|
||||
return $buf
|
||||
|
||||
proc reprStrAux(result: var string, s: string) =
|
||||
if cast[pointer](s) == nil:
|
||||
add result "nil"
|
||||
return
|
||||
add result, reprPointer(cast[pointer](s)) & "\""
|
||||
for c in items(s):
|
||||
case c
|
||||
of '"': add result "\\\""
|
||||
of '\\': add result, "\\\\" # BUGFIX: forgotten
|
||||
of '\10': add result, "\\10\"\n\"" # " \n " # better readability
|
||||
of '\128' .. '\255', '\0'..'\9', '\11'..'\31':
|
||||
add result, "\\" & reprInt(ord(c))
|
||||
else: result.add(c)
|
||||
add result, "\""
|
||||
|
||||
proc reprStr(s: string): string {.compilerproc.} =
|
||||
result = ""
|
||||
reprStrAux(result, s)
|
||||
|
||||
proc reprBool(x: bool): string {.compilerproc.} =
|
||||
if x: result = "true"
|
||||
else: result = "false"
|
||||
|
||||
proc reprChar(x: char): string {.compilerproc.} =
|
||||
result = "\'"
|
||||
case x
|
||||
of '"': add result, "\\\""
|
||||
of '\\': add result, "\\\\"
|
||||
of '\128' .. '\255', '\0'..'\31': add result, "\\" & reprInt(ord(x))
|
||||
else: add result, x
|
||||
add result, "\'"
|
||||
|
||||
proc reprEnum(e: int, typ: PNimType): string {.compilerproc.} =
|
||||
if e <% typ.node.len: # BUGFIX
|
||||
result = $typ.node.sons[e].name
|
||||
else:
|
||||
result = $e & " (invalid data!)"
|
||||
|
||||
type
|
||||
pbyteArray = ptr array[0.. 0xffff, byte]
|
||||
|
||||
proc addSetElem(result: var string, elem: int, typ: PNimType) =
|
||||
case typ.kind
|
||||
of tyEnum: add result, reprEnum(elem, typ)
|
||||
of tyBool: add result, reprBool(bool(elem))
|
||||
of tyChar: add result, reprChar(chr(elem))
|
||||
of tyRange: addSetElem(result, elem, typ.base)
|
||||
of tyInt..tyInt64: add result, reprInt(elem)
|
||||
else: # data corrupt --> inform the user
|
||||
add result, " (invalid data!)"
|
||||
|
||||
proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
|
||||
# "typ.slots.len" field is for sets the "first" field
|
||||
var elemCounter = 0 # we need this flag for adding the comma at
|
||||
# the right places
|
||||
add result, "{"
|
||||
var u: int64
|
||||
case typ.size
|
||||
of 1: u = ze64(cast[ptr int8](p)^)
|
||||
of 2: u = ze64(cast[ptr int16](p)^)
|
||||
of 4: u = ze64(cast[ptr int32](p)^)
|
||||
of 8: u = ze64(cast[ptr int64](p)^)
|
||||
else:
|
||||
var a = cast[pbyteArray](p)^
|
||||
for i in 0 .. typ.size*8-1:
|
||||
if (a[i div 8] and (1 shl (i mod 8))) != 0:
|
||||
if elemCounter > 0: add result, ", "
|
||||
addSetElem(result, i+typ.node.len, typ.base)
|
||||
inc(elemCounter)
|
||||
if typ.size <= 8:
|
||||
for i in 0..sizeof(int64)*8-1:
|
||||
if (u and (1 shl i)) != 0:
|
||||
if elemCounter > 0: add result, ", "
|
||||
addSetElem(result, i+typ.node.len, typ.base)
|
||||
inc(elemCounter)
|
||||
add result, "}"
|
||||
|
||||
proc reprSet(p: pointer, typ: PNimType): string {.compilerproc.} =
|
||||
result = ""
|
||||
reprSetAux(result, p, typ)
|
||||
|
||||
type
|
||||
TReprClosure = record # we cannot use a global variable here
|
||||
# as this wouldn't be thread-safe
|
||||
marked: TCellSet
|
||||
recdepth: int # do not recurse endless
|
||||
indent: int # indentation
|
||||
|
||||
proc initReprClosure(cl: var TReprClosure) =
|
||||
CellSetInit(cl.marked)
|
||||
cl.recdepth = -1 # default is to display everything!
|
||||
cl.indent = 0
|
||||
|
||||
proc deinitReprClosure(cl: var TReprClosure) =
|
||||
CellSetDeinit(cl.marked)
|
||||
|
||||
proc reprBreak(result: var string, cl: TReprClosure) =
|
||||
add result, "\n"
|
||||
for i in 0..cl.indent-1: add result, ' '
|
||||
|
||||
proc reprAux(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure)
|
||||
|
||||
proc reprArray(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
add result, "["
|
||||
var bs = typ.base.size
|
||||
for i in 0..typ.size div bs - 1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), typ.base, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprSequence(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
if p == nil:
|
||||
add result, "nil"
|
||||
return
|
||||
result.add(reprPointer(p) & "[")
|
||||
var bs = typ.base.size
|
||||
for i in 0..cast[PGenericSeq](p).len-1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + GenericSeqSize + i*bs),
|
||||
typ.Base, cl)
|
||||
add result, "]"
|
||||
|
||||
|
||||
proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
|
||||
cl: var TReprClosure) =
|
||||
case n.kind
|
||||
of nkNone: assert(false)
|
||||
of nkSlot:
|
||||
add result, $n.name
|
||||
add result, " = "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
|
||||
of nkList:
|
||||
for i in 0..n.len-1:
|
||||
if i > 0: add result, ",\n"
|
||||
reprRecordAux(result, p, n.sons[i], cl)
|
||||
of nkCase:
|
||||
var m = selectBranch(p, n)
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
|
||||
if m != nil: reprRecordAux(result, p, m, cl)
|
||||
|
||||
proc reprRecord(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
add result, "["
|
||||
reprRecordAux(result, p, typ.node, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprRef(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
# we know that p is not nil here:
|
||||
var cell = usrToCell(p)
|
||||
add result, "ref " & reprPointer(p)
|
||||
if cell notin cl.marked:
|
||||
# only the address is shown:
|
||||
incl(cl.marked, cell)
|
||||
add result, " --> "
|
||||
reprAux(result, p, typ.base, cl)
|
||||
|
||||
proc reprAux(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
if cl.recdepth == 0:
|
||||
add result, "..."
|
||||
return
|
||||
dec(cl.recdepth)
|
||||
case typ.kind
|
||||
of tySet: reprSetAux(result, p, typ)
|
||||
of tyArray: reprArray(result, p, typ, cl)
|
||||
of tyRecord: reprRecord(result, p, typ, cl)
|
||||
of tyObject: # result = reprRecord(p, typ, cl)
|
||||
var t = cast[ptr PNimType](p)^
|
||||
reprRecord(result, p, t, cl)
|
||||
of tyRef, tyPtr:
|
||||
assert(p != nil)
|
||||
if cast[ppointer](p)^ == nil: add result, "nil"
|
||||
else: reprRef(result, cast[ppointer](p)^, typ, cl)
|
||||
of tySequence:
|
||||
reprSequence(result, cast[ppointer](p)^, typ, cl)
|
||||
of tyInt: add result, $(cast[ptr int](p)^)
|
||||
of tyInt8: add result, $int(cast[ptr Int8](p)^)
|
||||
of tyInt16: add result, $int(cast[ptr Int16](p)^)
|
||||
of tyInt32: add result, $int(cast[ptr Int32](p)^)
|
||||
of tyInt64: add result, $(cast[ptr Int64](p)^)
|
||||
of tyFloat: add result, $(cast[ptr float](p)^)
|
||||
of tyFloat32: add result, $(cast[ptr float32](p)^)
|
||||
of tyFloat64: add result, $(cast[ptr float64](p)^)
|
||||
of tyEnum: add result, reprEnum(cast[ptr int](p)^, typ)
|
||||
of tyBool: add result, reprBool(cast[ptr bool](p)^)
|
||||
of tyChar: add result, reprChar(cast[ptr char](p)^)
|
||||
of tyString: reprStrAux(result, cast[ptr string](p)^)
|
||||
of tyCString: reprStrAux(result, $(cast[ptr cstring](p)^))
|
||||
of tyRange: reprAux(result, p, typ.base, cl)
|
||||
of tyProc, tyPointer:
|
||||
if cast[ppointer](p)^ == nil: add result, "nil"
|
||||
else: add result, reprPointer(cast[ppointer](p)^)
|
||||
else:
|
||||
add result, "(invalid data!)"
|
||||
inc(cl.recdepth)
|
||||
|
||||
proc reprAny(p: pointer, typ: PNimType): string =
|
||||
var
|
||||
cl: TReprClosure
|
||||
initReprClosure(cl)
|
||||
result = ""
|
||||
if typ.kind in {tyObject, tyRecord, tyArray, tySet}:
|
||||
reprAux(result, p, typ, cl)
|
||||
else:
|
||||
reprAux(result, addr(p), typ, cl)
|
||||
add result, "\n"
|
||||
deinitReprClosure(cl)
|
||||
88
lib/sets.nim
Executable file
88
lib/sets.nim
Executable file
@@ -0,0 +1,88 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# set handling
|
||||
|
||||
type
|
||||
TMyByte = int8
|
||||
TNimSet = array [0..4*2048-1, TMyByte]
|
||||
|
||||
# implementation:
|
||||
|
||||
proc countBits(n: int32): int {.exportc: "countBits".}
|
||||
# We use a prototype here, not in "cntbits.nim", because that is included
|
||||
# in math.nim too. So when linking with math.nim it'd give a duplicated
|
||||
# symbol error which we avoid by renaming here.
|
||||
|
||||
include cntbits
|
||||
|
||||
proc unionSets(res: var TNimSet, a, b: TNimSet, len: int) {.
|
||||
compilerproc, inline.} =
|
||||
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) or ze(b[i]))
|
||||
|
||||
proc diffSets(res: var TNimSet, a, b: TNimSet, len: int) {.
|
||||
compilerproc, inline.} =
|
||||
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) and not ze(b[i]))
|
||||
|
||||
proc intersectSets(res: var TNimSet, a, b: TNimSet, len: int) {.
|
||||
compilerproc, inline.} =
|
||||
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) and ze(b[i]))
|
||||
|
||||
proc symdiffSets(res: var TNimSet, a, b: TNimSet, len: int) {.
|
||||
compilerproc, inline.} =
|
||||
for i in countup(0, len-1): res[i] = toU8(ze(a[i]) xor ze(b[i]))
|
||||
|
||||
proc containsSets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} =
|
||||
# s1 <= s2 ?
|
||||
for i in countup(0, len-1):
|
||||
if (ze(a[i]) and not ze(b[i])) != 0: return false
|
||||
return true
|
||||
|
||||
proc containsSubsets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} =
|
||||
# s1 < s2 ?
|
||||
result = false # assume they are equal
|
||||
for i in countup(0, len-1):
|
||||
if (ze(a[i]) and not ze(b[i])) != 0: return false
|
||||
if ze(a[i]) != ze(b[i]): result = true # they are not equal
|
||||
|
||||
proc equalSets(a, b: TNimSet, len: int): bool {.compilerproc, inline.} =
|
||||
for i in countup(0, len-1):
|
||||
if ze(a[i]) != ze(b[i]): return false
|
||||
return true
|
||||
|
||||
proc cardSet(s: TNimSet, len: int): int {.compilerproc, inline.} =
|
||||
result = 0
|
||||
for i in countup(0, len-1):
|
||||
inc(result, countBits(ze(s[i])))
|
||||
|
||||
const
|
||||
WORD_SIZE = sizeof(TMyByte)*8
|
||||
|
||||
proc inSet(s: TNimSet, elem: int): bool {.compilerproc, inline.} =
|
||||
return (s[elem /% WORD_SIZE] and (1 shl (elem %% WORD_SIZE))) != 0
|
||||
|
||||
proc inclSets(s: var TNimSet, e: int) {.compilerproc, inline.} =
|
||||
s[e /% WORD_SIZE] = toU8(s[e /% WORD_SIZE] or (1 shl (e %% WORD_SIZE)))
|
||||
|
||||
proc inclRange(s: var TNimSet, first, last: int) {.compilerproc.} =
|
||||
# not very fast, but it is seldom used
|
||||
for i in countup(first, last): inclSets(s, i)
|
||||
|
||||
proc smallInclRange(s: var int, first, last: int) {.compilerproc.} =
|
||||
# not very fast, but it is seldom used
|
||||
for i in countup(first, last):
|
||||
s = s or (1 shl (i %% sizeof(int)*8))
|
||||
|
||||
proc exclSets(s: var TNimSet, e: int) {.compilerproc, inline.} =
|
||||
s[e /% WORD_SIZE] = toU8(s[e /% WORD_SIZE] and
|
||||
not (1 shl (e %% WORD_SIZE)))
|
||||
|
||||
proc smallContainsSubsets(a, b: int): bool {.compilerProc, inline.} =
|
||||
# not used by new code generator
|
||||
return ((a and not b) != 0) and (a != b)
|
||||
627
lib/strutils.nim
Executable file
627
lib/strutils.nim
Executable file
@@ -0,0 +1,627 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
|
||||
## This module contains various string utility routines.
|
||||
## See the module `regexprs` for regular expression support.
|
||||
|
||||
{.push debugger:off .} # the user does not want to trace a part
|
||||
# of the standard library!
|
||||
|
||||
# copied from excpt.nim, because I don't want to make this template public
|
||||
template newException(exceptn, message: expr): expr =
|
||||
block: # open a new scope
|
||||
var
|
||||
e: ref exceptn
|
||||
new(e)
|
||||
e.msg = message
|
||||
e
|
||||
|
||||
type
|
||||
TCharSet* = set[char] # for compability for Nim
|
||||
|
||||
const
|
||||
Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'}
|
||||
## All the characters that count as whitespace.
|
||||
|
||||
strStart* = 0 # this is only for bootstraping
|
||||
# XXX: remove this someday
|
||||
nl* = "\n" # this is only for bootstraping XXX: remove this somehow
|
||||
|
||||
proc strip*(s: string): string {.noSideEffect.}
|
||||
## Strips leading and trailing whitespace from `s`.
|
||||
|
||||
proc toLower*(s: string): string {.noSideEffect.}
|
||||
## Converts `s` into lower case. This works only for the letters A-Z.
|
||||
## See `charsets.nativeToLower` for a version that is locale-dependant.
|
||||
|
||||
proc toLower*(c: Char): Char {.noSideEffect.}
|
||||
## Converts `c` into lower case. This works only for the letters A-Z.
|
||||
## See `charsets.nativeToLower()` for a version that is locale-dependant.
|
||||
|
||||
proc toUpper*(s: string): string {.noSideEffect.}
|
||||
## Converts `s` into upper case. This works only for the letters a-z.
|
||||
## See `charsets.nativeToUpper()` for a version that is locale-dependant.
|
||||
|
||||
proc toUpper*(c: Char): Char {.noSideEffect.}
|
||||
## Converts `c` into upper case. This works only for the letters a-z.
|
||||
## See `charsets.nativeToUpper()` for a version that is locale-dependant.
|
||||
|
||||
proc capitalize*(s: string): string {.noSideEffect.}
|
||||
## Converts the first character of `s` into upper case.
|
||||
## This works only for the letters a-z.
|
||||
|
||||
proc normalize*(s: string): string {.noSideEffect.}
|
||||
## Normalizes the string `s`. That means to convert it to lower case and
|
||||
## remove any '_'. This is needed for Nimrod identifiers for example.
|
||||
|
||||
proc findSubStr*(sub, s: string, start: int = 0): int {.noSideEffect.}
|
||||
## Searches for `sub` in `s` starting at position `start`. Searching is
|
||||
## case-sensitive. If `sub` is not in `s`, -1 is returned.
|
||||
|
||||
proc findSubStr*(sub: char, s: string, start: int = 0): int {.noSideEffect.}
|
||||
## Searches for `sub` in `s` starting at position `start`. Searching is
|
||||
## case-sensitive. If `sub` is not in `s`, -1 is returned.
|
||||
|
||||
proc replaceStr*(s, sub, by: string): string {.noSideEffect.}
|
||||
## Replaces `sub` in `s` by the string `by`.
|
||||
|
||||
proc deleteStr*(s: var string, first, last: int)
|
||||
## Deletes in `s` the characters at position `first`..`last`. This modifies
|
||||
## `s` itself, it does not return a copy.
|
||||
|
||||
proc toOctal*(c: char): string
|
||||
## Converts a character `c` to its octal representation. The resulting
|
||||
## string may not have a leading zero. Its length is always exactly 3.
|
||||
|
||||
iterator split*(s: string, seps: set[char] = Whitespace): string =
|
||||
## Splits the string `s` into substrings.
|
||||
##
|
||||
## Substrings are separated by a substring containing only `seps`.
|
||||
## The seperator substrings are not returned in `sub`, nor are they part
|
||||
## of `sub`.
|
||||
## Examples::
|
||||
##
|
||||
## for word in split(" this is an example "):
|
||||
## writeln(stdout, word)
|
||||
##
|
||||
## Results in::
|
||||
##
|
||||
## "this"
|
||||
## "is"
|
||||
## "an"
|
||||
## "example"
|
||||
##
|
||||
## for word in split(";;this;is;an;;example;;;", {';'}):
|
||||
## writeln(stdout, word)
|
||||
##
|
||||
## produces in the same output.
|
||||
var
|
||||
first: int = 0
|
||||
last: int = 0
|
||||
assert(not ('\0' in seps))
|
||||
while last < len(s):
|
||||
while s[last] in seps: inc(last)
|
||||
first = last
|
||||
while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX!
|
||||
yield copy(s, first, last-1)
|
||||
|
||||
proc splitSeq*(s: string, seps: set[char] = Whitespace): seq[string] {.
|
||||
noSideEffect.}
|
||||
## The same as `split`, but is a proc that returns a sequence of substrings.
|
||||
|
||||
proc cmpIgnoreCase*(a, b: string): int {.noSideEffect.}
|
||||
## Compares two strings in a case insensitive manner. Returns:
|
||||
##
|
||||
## | 0 iff a == b
|
||||
## | < 0 iff a < b
|
||||
## | > 0 iff a > b
|
||||
|
||||
proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect.}
|
||||
## Compares two strings normalized (i.e. case and
|
||||
## underscores do not matter). Returns:
|
||||
##
|
||||
## | 0 iff a == b
|
||||
## | < 0 iff a < b
|
||||
## | > 0 iff a > b
|
||||
|
||||
proc in_Operator*(s: string, c: char): bool {.noSideEffect.}
|
||||
## Same as `findSubStr(c, s) >= 0`.
|
||||
|
||||
proc in_Operator*(s, sub: string): bool {.noSideEffect.}
|
||||
## Same as `findSubStr(sub, s) >= 0`.
|
||||
|
||||
proc toHex*(x: BiggestInt, len: int): string {.noSideEffect.}
|
||||
## Converts `x` to its hexadecimal representation. The resulting string
|
||||
## will be exactly `len` characters long. No prefix like ``0x``
|
||||
## is generated. `x` is treated as unsigned value.
|
||||
|
||||
proc intToStr*(x: int, minchars: int = 1): string
|
||||
## Converts `x` to its decimal representation. The resulting string
|
||||
## will be minimally `minchars` characters long. This is achieved by
|
||||
## adding leading zeros.
|
||||
|
||||
proc ParseInt*(s: string): int {.noSideEffect.}
|
||||
## Parses a decimal integer value contained in `s`. If `s` is not
|
||||
## a valid integer, `EInvalidValue` is raised.
|
||||
# XXX: make this biggestint!
|
||||
|
||||
proc ParseFloat*(s: string): float {.noSideEffect.}
|
||||
## Parses a decimal floating point value contained in `s`. If `s` is not
|
||||
## a valid floating point number, `EInvalidValue` is raised.
|
||||
# XXX: make this biggestfloat.
|
||||
|
||||
# the stringify and format operators:
|
||||
proc toString*[Ty](x: Ty): string
|
||||
## This generic proc is the same as the stringify operator `$`.
|
||||
|
||||
proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect.}
|
||||
## The substitution operator performs string substitutions in `formatstr`
|
||||
## and returns the modified `formatstr`.
|
||||
##
|
||||
## This is best explained by an example::
|
||||
##
|
||||
## "$1 eats $2." % ["The cat", "fish"]
|
||||
##
|
||||
## Results in::
|
||||
##
|
||||
## "The cat eats fish."
|
||||
##
|
||||
## The substitution variables (the thing after the ``$``)
|
||||
## are enumerated from 1 to 9.
|
||||
## Substitution variables can also be words (that is
|
||||
## ``[A-Za-z_]+[A-Za-z0-9_]*``) in which case the arguments in `a` with even
|
||||
## indices are keys and with odd indices are the corresponding values. Again
|
||||
## an example::
|
||||
##
|
||||
## "$animal eats $food." % ["animal", "The cat", "food", "fish"]
|
||||
##
|
||||
## Results in::
|
||||
##
|
||||
## "The cat eats fish."
|
||||
##
|
||||
## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is
|
||||
## raised if an ill-formed format string has been passed to the `%` operator.
|
||||
|
||||
proc `%` *(formatstr, a: string): string {.noSideEffect.}
|
||||
## This is the same as `formatstr % [a]`.
|
||||
|
||||
proc repeatChar*(count: int, c: Char = ' '): string
|
||||
## Returns a string of length `count` consisting only of
|
||||
## the character `c`.
|
||||
|
||||
proc startsWith*(s, prefix: string): bool {.noSideEffect.}
|
||||
## Returns true iff ``s`` starts with ``prefix``.
|
||||
## If ``prefix == ""`` true is returned.
|
||||
|
||||
proc endsWith*(s, suffix: string): bool {.noSideEffect.}
|
||||
## Returns true iff ``s`` ends with ``suffix``.
|
||||
## If ``suffix == ""`` true is returned.
|
||||
|
||||
# implementation
|
||||
|
||||
proc allCharsInSet*(s: string, theSet: TCharSet): bool =
|
||||
## returns true iff each character of `s` is in the set `theSet`.
|
||||
for c in items(s):
|
||||
if not (c in theSet): return false
|
||||
return true
|
||||
|
||||
proc c_strcmp(a, b: CString): int {.importc: "strcmp", nodecl.}
|
||||
|
||||
proc startsWith(s, prefix: string): bool =
|
||||
var i = 0
|
||||
while true:
|
||||
if prefix[i] == '\0': return true
|
||||
if s[i] != prefix[i]: return false
|
||||
inc(i)
|
||||
|
||||
proc endsWith(s, suffix: string): bool =
|
||||
var
|
||||
i = 0
|
||||
j = len(s) - len(suffix)
|
||||
while true:
|
||||
if suffix[i] == '\0': return true
|
||||
if s[i+j] != suffix[i]: return false
|
||||
inc(i)
|
||||
|
||||
proc repeatChar(count: int, c: Char = ' '): string =
|
||||
result = newString(count)
|
||||
for i in 0..count-1:
|
||||
result[i] = c
|
||||
|
||||
proc intToStr(x: int, minchars: int = 1): string =
|
||||
result = $abs(x)
|
||||
for i in 1 .. minchars - len(result):
|
||||
result = '0' & result
|
||||
if x < 0:
|
||||
result = '-' & result
|
||||
|
||||
proc toString[Ty](x: Ty): string = return $x
|
||||
|
||||
proc toOctal(c: char): string =
|
||||
var
|
||||
val: int
|
||||
result = newString(3)
|
||||
val = ord(c)
|
||||
for i in countdown(2, 0):
|
||||
result[i] = Chr(val mod 8 + ord('0'))
|
||||
val = val div 8
|
||||
|
||||
proc `%`(formatstr: string, a: string): string =
|
||||
return formatstr % [a]
|
||||
|
||||
proc findNormalized(x: string, inArray: openarray[string]): int =
|
||||
var i = 0
|
||||
while i < high(inArray):
|
||||
if cmpIgnoreStyle(x, inArray[i]) == 0: return i
|
||||
inc(i, 2) # incrementing by 1 would probably result in a
|
||||
# security whole ...
|
||||
return -1
|
||||
|
||||
proc `%`(formatstr: string, a: openarray[string]): string =
|
||||
# the format operator
|
||||
const
|
||||
PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\128'..'\255', '_'}
|
||||
result = ""
|
||||
var i = 0
|
||||
while i < len(formatstr):
|
||||
if formatstr[i] == '$':
|
||||
case formatstr[i+1] # again we use the fact that strings
|
||||
# are zero-terminated here
|
||||
of '$':
|
||||
add result, '$'
|
||||
inc(i, 2)
|
||||
of '1'..'9':
|
||||
var j = 0
|
||||
inc(i) # skip $
|
||||
while formatstr[i] in {'0'..'9'}:
|
||||
j = j * 10 + ord(formatstr[i]) - ord('0')
|
||||
inc(i)
|
||||
add result, a[j - 1]
|
||||
of '{':
|
||||
var j = i+1
|
||||
while formatstr[j] notin {'\0', '}'}: inc(j)
|
||||
var x = findNormalized(copy(formatstr, i+2, j-1), a)
|
||||
if x >= 0 and x < high(a): add result, a[x+1]
|
||||
else: raise newException(EInvalidValue, "invalid format string")
|
||||
i = j+1
|
||||
of 'a'..'z', 'A'..'Z', '\128'..'\255', '_':
|
||||
var j = i+1
|
||||
while formatstr[j] in PatternChars: inc(j)
|
||||
var x = findNormalized(copy(formatstr, i+1, j-1), a)
|
||||
if x >= 0 and x < high(a): add result, a[x+1]
|
||||
else: raise newException(EInvalidValue, "invalid format string")
|
||||
i = j
|
||||
else: raise newException(EInvalidValue, "invalid format string")
|
||||
else:
|
||||
add result, formatstr[i]
|
||||
inc(i)
|
||||
|
||||
proc cmpIgnoreCase(a, b: string): int =
|
||||
# makes usage of the fact that strings are zero-terminated
|
||||
var
|
||||
aa, bb: char
|
||||
for i in 0..len(a)-1:
|
||||
aa = toLower(a[i])
|
||||
bb = toLower(b[i])
|
||||
result = ord(aa) - ord(bb)
|
||||
if result != 0: break
|
||||
|
||||
{.push checks: off, line_trace: off .} # this is a hot-spot in the compiler!
|
||||
# thus we compile without checks here
|
||||
|
||||
proc cmpIgnoreStyle(a, b: string): int =
|
||||
var
|
||||
aa, bb: char
|
||||
i = 0
|
||||
j = 0
|
||||
while True:
|
||||
while a[i] == '_': inc(i)
|
||||
while b[j] == '_': inc(j) # BUGFIX: typo
|
||||
aa = toLower(a[i])
|
||||
bb = toLower(b[j])
|
||||
result = ord(aa) - ord(bb)
|
||||
if result != 0 or aa == '\0': break
|
||||
inc(i)
|
||||
inc(j)
|
||||
|
||||
{.pop.}
|
||||
|
||||
# ---------- splitting -----------------------------------------------------
|
||||
|
||||
proc splitSeq(s: string, seps: set[char]): seq[string] =
|
||||
result = []
|
||||
for sub in split(s, seps): add result, sub
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
proc strip(s: string): string =
|
||||
const
|
||||
chars: set[Char] = Whitespace
|
||||
var
|
||||
first = 0
|
||||
last = len(s)-1
|
||||
while s[first] in chars: inc(first)
|
||||
while last >= 0 and s[last] in chars: dec(last)
|
||||
result = copy(s, first, last)
|
||||
|
||||
proc toLower(c: Char): Char =
|
||||
if c in {'A'..'Z'}:
|
||||
result = chr(ord(c) + (ord('a') - ord('A')))
|
||||
else:
|
||||
result = c
|
||||
|
||||
proc toLower(s: string): string =
|
||||
result = newString(len(s))
|
||||
for i in 0..len(s) - 1:
|
||||
result[i] = toLower(s[i])
|
||||
|
||||
proc toUpper(c: Char): Char =
|
||||
if c in {'a'..'z'}:
|
||||
result = Chr(Ord(c) - (Ord('a') - Ord('A')))
|
||||
else:
|
||||
result = c
|
||||
|
||||
proc toUpper(s: string): string =
|
||||
result = newString(len(s))
|
||||
for i in 0..len(s) - 1:
|
||||
result[i] = toUpper(s[i])
|
||||
|
||||
proc capitalize(s: string): string =
|
||||
result = toUpper(s[0]) & copy(s, 1)
|
||||
|
||||
proc normalize(s: string): string =
|
||||
result = ""
|
||||
for i in 0..len(s) - 1:
|
||||
if s[i] in {'A'..'Z'}:
|
||||
add result, Chr(Ord(s[i]) + (Ord('a') - Ord('A')))
|
||||
elif s[i] != '_':
|
||||
add result, s[i]
|
||||
|
||||
type
|
||||
TSkipTable = array[Char, int]
|
||||
|
||||
proc preprocessSub(sub: string, a: var TSkipTable) =
|
||||
var m = len(sub)
|
||||
for i in 0..0xff: a[chr(i)] = m+1
|
||||
for i in 0..m-1: a[sub[i]] = m-i
|
||||
|
||||
proc findSubStrAux(sub, s: string, start: int, a: TSkipTable): int =
|
||||
# fast "quick search" algorithm:
|
||||
var
|
||||
m = len(sub)
|
||||
n = len(s)
|
||||
# search:
|
||||
var j = start
|
||||
while j <= n - m:
|
||||
block match:
|
||||
for k in 0..m-1:
|
||||
if sub[k] != s[k+j]: break match
|
||||
return j
|
||||
inc(j, a[s[j+m]])
|
||||
return -1
|
||||
|
||||
proc findSubStr(sub, s: string, start: int = 0): int =
|
||||
var a: TSkipTable
|
||||
preprocessSub(sub, a)
|
||||
result = findSubStrAux(sub, s, start, a)
|
||||
# slow linear search:
|
||||
#var
|
||||
# i, j, M, N: int
|
||||
#M = len(sub)
|
||||
#N = len(s)
|
||||
#i = start
|
||||
#j = 0
|
||||
#if i >= N:
|
||||
# result = -1
|
||||
#else:
|
||||
# while True:
|
||||
# if s[i] == sub[j]:
|
||||
# Inc(i)
|
||||
# Inc(j)
|
||||
# else:
|
||||
# i = i - j + 1
|
||||
# j = 0
|
||||
# if (j >= M):
|
||||
# return i - M
|
||||
# elif (i >= N):
|
||||
# return -1
|
||||
|
||||
|
||||
proc findSubStr(sub: char, s: string, start: int = 0): int =
|
||||
for i in start..len(s)-1:
|
||||
if sub == s[i]: return i
|
||||
return -1
|
||||
|
||||
proc in_Operator(s: string, c: char): bool =
|
||||
return findSubStr(c, s) >= 0
|
||||
|
||||
proc in_Operator(s, sub: string): bool =
|
||||
return findSubStr(sub, s) >= 0
|
||||
|
||||
proc replaceStr(s, sub, by: string): string =
|
||||
var
|
||||
i, j: int
|
||||
a: TSkipTable
|
||||
result = ""
|
||||
preprocessSub(sub, a)
|
||||
i = 0
|
||||
while true:
|
||||
j = findSubStrAux(sub, s, i, a)
|
||||
if j < 0: break
|
||||
add result, copy(s, i, j - 1)
|
||||
add result, by
|
||||
i = j + len(sub)
|
||||
# copy the rest:
|
||||
add result, copy(s, i)
|
||||
|
||||
proc deleteStr(s: var string, first, last: int) =
|
||||
# example: "abc___uvwxyz\0" (___ is to be deleted)
|
||||
# --> first == 3, last == 5
|
||||
# s[first..] = s[last+1..]
|
||||
var
|
||||
i = first
|
||||
while last+i+1 < len(s):
|
||||
s[i] = s[last+i+1]
|
||||
inc(i)
|
||||
setlen(s, len(s)-(last-first+1))
|
||||
|
||||
# parsing numbers:
|
||||
|
||||
proc sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs.}
|
||||
|
||||
proc toHex(x: BiggestInt, len: int): string =
|
||||
const
|
||||
HexChars = "0123456789ABCDEF"
|
||||
var
|
||||
shift: BiggestInt
|
||||
result = newString(len)
|
||||
shift = 0
|
||||
for j in countdown(len-1, 0):
|
||||
result[j] = HexChars[toU32(x shr shift) and 0xF]
|
||||
shift = shift + 4
|
||||
|
||||
{.push overflowChecks: on.}
|
||||
# this must be compiled with overflow checking turned on:
|
||||
proc rawParseInt(s: string, index: var int): BiggestInt =
|
||||
# index contains the start position at proc entry; end position will be
|
||||
# an index before the proc returns; index = -1 on error (no number at all)
|
||||
# the problem here is that integers have an asymmetrical range: there is
|
||||
# one more valid negative than prositive integer. Thus we perform the
|
||||
# computation as a negative number and then change the sign at the end.
|
||||
var
|
||||
i: int
|
||||
sign: BiggestInt
|
||||
i = index
|
||||
# a local i is more efficient than accessing an in out parameter
|
||||
sign = -1
|
||||
if s[i] == '+':
|
||||
inc(i)
|
||||
elif s[i] == '-':
|
||||
inc(i)
|
||||
sign = 1
|
||||
if s[i] in {'0'..'9'}:
|
||||
result = 0
|
||||
while s[i] in {'0'..'9'}:
|
||||
result = result * 10 - (ord(s[i]) - ord('0'))
|
||||
inc(i)
|
||||
while s[i] == '_':
|
||||
inc(i) # underscores are allowed and ignored
|
||||
result = result * sign
|
||||
index = i # store index back
|
||||
else:
|
||||
index = -1
|
||||
|
||||
{.pop.} # overflowChecks
|
||||
|
||||
proc parseInt(s: string): int =
|
||||
var
|
||||
index: int
|
||||
res: BiggestInt
|
||||
index = strStart
|
||||
res = rawParseInt(s, index)
|
||||
if index == -1:
|
||||
raise newException(EInvalidValue, "invalid integer: " & s)
|
||||
elif (sizeof(int) <= 4) and
|
||||
((res < low(int)) or (res > high(int))):
|
||||
raise newException(EOverflow, "overflow")
|
||||
else:
|
||||
result = int(res) # convert to smaller integer type
|
||||
|
||||
proc ParseFloat(s: string): float =
|
||||
var
|
||||
hd, esign, sign: float
|
||||
exponent, i: int
|
||||
flags: int
|
||||
result = 0.0
|
||||
i = 0
|
||||
exponent = 0
|
||||
esign = 1.0
|
||||
flags = 0
|
||||
sign = 1.0
|
||||
if s[i] == '+': inc(i)
|
||||
elif s[i] == '-':
|
||||
sign = -1.0
|
||||
inc(i)
|
||||
while s[i] in {'0'..'9'}:
|
||||
# Read integer part
|
||||
flags = flags or 1
|
||||
result = result * 10.0 + toFloat(ord(s[i]) - ord('0'))
|
||||
inc(i)
|
||||
while s[i] == '_': inc(i)
|
||||
# Decimal?
|
||||
if s[i] == '.':
|
||||
hd = 1.0
|
||||
inc(i)
|
||||
while s[i] in {'0'..'9'}:
|
||||
# Read fractional part
|
||||
flags = flags or 2
|
||||
result = result * 10.0 + toFloat(ord(s[i]) - ord('0'))
|
||||
hd = hd * 10.0
|
||||
inc(i)
|
||||
while s[i] == '_': inc(i)
|
||||
result = result / hd # this complicated way preserves precision
|
||||
# Again, read integer and fractional part
|
||||
if flags == 0:
|
||||
raise newException(EInvalidValue, "invalid float:" & s)
|
||||
# Exponent?
|
||||
if s[i] in {'e', 'E'}:
|
||||
inc(i)
|
||||
if s[i] == '+':
|
||||
inc(i)
|
||||
elif s[i] == '-':
|
||||
esign = -1.0
|
||||
inc(i)
|
||||
if s[i] notin {'0'..'9'}:
|
||||
raise newException(EInvalidValue, "invalid float: " & s)
|
||||
while s[i] in {'0'..'9'}:
|
||||
exponent = exponent * 10 + ord(s[i]) - ord('0')
|
||||
inc(i)
|
||||
while s[i] == '_': inc(i)
|
||||
# Calculate Exponent
|
||||
hd = 1.0
|
||||
for j in 1..exponent:
|
||||
hd = hd * 10.0
|
||||
if esign > 0.0: result = result * hd
|
||||
else: result = result / hd
|
||||
# Not all characters are read?
|
||||
if s[i] != '\0': raise newException(EInvalidValue, "invalid float: " & s)
|
||||
# evaluate sign
|
||||
result = result * sign
|
||||
|
||||
proc toOct*(x: BiggestInt, len: int): string =
|
||||
## converts `x` into its octal representation. The resulting string is
|
||||
## always `len` characters long. No leading ``0c`` prefix is generated.
|
||||
var
|
||||
mask, shift: BiggestInt
|
||||
assert(len > 0)
|
||||
result = newString(len)
|
||||
mask = 7
|
||||
shift = 0
|
||||
for j in countdown(len-1, 0):
|
||||
result[j] = chr(int((x and mask) shr shift) + ord('0'))
|
||||
shift = shift + 3
|
||||
mask = mask shl 3
|
||||
|
||||
proc toBin*(x: BiggestInt, len: int): string =
|
||||
## converts `x` into its binary representation. The resulting string is
|
||||
## always `len` characters long. No leading ``0b`` prefix is generated.
|
||||
var
|
||||
mask, shift: BiggestInt
|
||||
assert(len > 0)
|
||||
result = newString(len)
|
||||
mask = 1
|
||||
shift = 0
|
||||
for j in countdown(len-1, 0):
|
||||
result[j] = chr(int((x and mask) shr shift) + ord('0'))
|
||||
shift = shift + 1
|
||||
mask = mask shl 1
|
||||
|
||||
{.pop.}
|
||||
163
lib/sysio.nim
Executable file
163
lib/sysio.nim
Executable file
@@ -0,0 +1,163 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
## Nimrod's standard IO library. It contains high-performance
|
||||
## routines for reading and writing data to (buffered) files or
|
||||
## TTYs.
|
||||
|
||||
{.push debugger:off .} # the user does not want to trace a part
|
||||
# of the standard library!
|
||||
|
||||
|
||||
proc fputs(c: cstring, f: TFile) {.importc: "fputs", noDecl.}
|
||||
proc fgets(c: cstring, n: int, f: TFile): cstring {.importc: "fgets", noDecl.}
|
||||
proc fgetc(stream: TFile): int {.importc: "fgetc", nodecl.}
|
||||
proc ungetc(c: int, f: TFile) {.importc: "ungetc", nodecl.}
|
||||
proc putc(c: Char, stream: TFile) {.importc: "putc", nodecl.}
|
||||
proc fprintf(f: TFile, frmt: CString) {.importc: "fprintf", nodecl, varargs.}
|
||||
proc strlen(c: cstring): int {.importc: "strlen", nodecl.}
|
||||
|
||||
proc setvbuf(stream: TFile, buf: pointer, typ, size: cint): cint {.
|
||||
importc, nodecl.}
|
||||
|
||||
proc write(f: TFile, c: cstring) = fputs(c, f)
|
||||
|
||||
var
|
||||
IOFBF {.importc: "_IOFBF", nodecl.}: cint
|
||||
IONBF {.importc: "_IONBF", nodecl.}: cint
|
||||
|
||||
# copied here to remove dependancy on strutils:
|
||||
#proc toNimstr(x: Cstring, len: int): string {.
|
||||
# noSideEffect, importc: "toNimStr".}
|
||||
|
||||
proc rawReadLine(f: TFile, result: var string) {.noStatic.} =
|
||||
# of course this could be optimized a bit; but IO is slow anyway...
|
||||
# and it was difficult to get this CORRECT with Ansi C's methods
|
||||
var
|
||||
c: cint
|
||||
setLen(result, 0) # reuse the buffer!
|
||||
while True:
|
||||
c = fgetc(f)
|
||||
if c < 0:
|
||||
result = nil
|
||||
break # EOF
|
||||
if c == 10: break # LF
|
||||
if c == 13: # CR
|
||||
c = fgetc(f) # is the next char LF?
|
||||
if c != 10: ungetc(c, f) # no, put the character back
|
||||
break
|
||||
add result, chr(int(c))
|
||||
|
||||
proc readLine(f: TFile): string =
|
||||
result = ""
|
||||
rawReadLine(f, result)
|
||||
|
||||
proc readFile(filename: string): string =
|
||||
var f: TFile
|
||||
try:
|
||||
if openFile(f, filename):
|
||||
var len = getFileSize(f)
|
||||
if len < high(int):
|
||||
result = newString(int(len))
|
||||
if readBuffer(f, addr(result[0]), int(len)) != len:
|
||||
result = nil
|
||||
closeFile(f)
|
||||
else:
|
||||
result = nil
|
||||
except EIO:
|
||||
result = nil
|
||||
|
||||
proc write(f: TFile, s: string) = fputs(s, f)
|
||||
proc write(f: TFile, i: int) = fprintf(f, "%ld", i)
|
||||
proc write(f: TFile, b: bool) =
|
||||
if b: write(f, "true")
|
||||
else: write(f, "false")
|
||||
proc write(f: TFile, r: float) = fprintf(f, "%g", r)
|
||||
proc write(f: TFile, c: Char) = putc(c, f)
|
||||
|
||||
proc EndOfFile(f: TFile): bool =
|
||||
# do not blame me; blame the ANSI C standard this is so brain-damaged
|
||||
var
|
||||
c: int
|
||||
c = fgetc(f)
|
||||
ungetc(c, f)
|
||||
return c == -1
|
||||
|
||||
proc writeln[Ty](f: TFile, x: Ty) =
|
||||
write(f, x)
|
||||
write(f, "\n")
|
||||
proc echo[Ty](x: Ty) = writeln(stdout, x)
|
||||
|
||||
# interface to the C procs:
|
||||
proc fopen(filename, mode: CString): pointer {.importc: "fopen", noDecl.}
|
||||
|
||||
const
|
||||
FormatOpen: array [TFileMode, string] = ["rb", "wb", "w+b", "r+b", "ab"]
|
||||
#"rt", "wt", "w+t", "r+t", "at"
|
||||
# we always use binary here as for Nimrod the OS line ending
|
||||
# should not be translated.
|
||||
|
||||
|
||||
proc OpenFile(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead,
|
||||
bufSize: int = -1): Bool =
|
||||
var
|
||||
p: pointer
|
||||
p = fopen(filename, FormatOpen[mode])
|
||||
result = (p != nil)
|
||||
f = cast[TFile](p)
|
||||
if bufSize > 0:
|
||||
if setvbuf(f, nil, IOFBF, bufSize) != 0:
|
||||
raise newException(EOutOfMemory, "out of memory")
|
||||
elif bufSize == 0:
|
||||
discard setvbuf(f, nil, IONBF, 0)
|
||||
|
||||
# C routine that is used here:
|
||||
proc fread(buf: Pointer, size, n: int, f: TFile): int {.
|
||||
importc: "fread", noDecl.}
|
||||
proc fseek(f: TFile, offset: clong, whence: int): int {.
|
||||
importc: "fseek", noDecl.}
|
||||
proc ftell(f: TFile): int {.importc: "ftell", noDecl.}
|
||||
|
||||
proc fwrite(buf: Pointer, size, n: int, f: TFile): int {.
|
||||
importc: "fwrite", noDecl.}
|
||||
# size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);
|
||||
|
||||
proc readBuffer(f: TFile, buffer: pointer, len: int): int =
|
||||
result = fread(buffer, 1, len, f)
|
||||
|
||||
proc ReadBytes(f: TFile, a: var openarray[byte], start, len: int): int =
|
||||
result = readBuffer(f, addr(a[start]), len)
|
||||
|
||||
proc ReadChars(f: TFile, a: var openarray[char], start, len: int): int =
|
||||
result = readBuffer(f, addr(a[start]), len)
|
||||
|
||||
proc writeBytes(f: TFile, a: openarray[byte], start, len: int): int =
|
||||
result = writeBuffer(f, addr(a[start]), len)
|
||||
proc writeChars(f: TFile, a: openarray[char], start, len: int): int =
|
||||
result = writeBuffer(f, addr(a[start]), len)
|
||||
proc writeBuffer(f: TFile, buffer: pointer, len: int): int =
|
||||
result = fwrite(buffer, 1, len, f)
|
||||
|
||||
proc setFilePos(f: TFile, pos: int64) =
|
||||
if fseek(f, clong(pos), 0) != 0:
|
||||
raise newException(EIO, "cannot set file position")
|
||||
|
||||
proc getFilePos(f: TFile): int64 =
|
||||
result = ftell(f)
|
||||
if result < 0: raise newException(EIO, "cannot retrieve file position")
|
||||
|
||||
proc getFileSize(f: TFile): int64 =
|
||||
var oldPos = getFilePos(f)
|
||||
discard fseek(f, 0, 2) # seek the end of the file
|
||||
result = getFilePos(f)
|
||||
setFilePos(f, oldPos)
|
||||
|
||||
{.pop.}
|
||||
294
lib/sysstr.nim
Executable file
294
lib/sysstr.nim
Executable file
@@ -0,0 +1,294 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# string & sequence handling procedures needed by the code generator
|
||||
|
||||
# strings are dynamically resized, have a length field
|
||||
# and are zero-terminated, so they can be casted to C
|
||||
# strings easily
|
||||
# we don't use refcounts because that's a behaviour
|
||||
# the programmer may not want
|
||||
|
||||
type
|
||||
TStringDesc {.importc, nodecl.} = record
|
||||
len, space: int # len and space without counting the terminating zero
|
||||
data: array[0..0, char] # for the '\0' character
|
||||
|
||||
mstring {.importc: "string".} = ptr TStringDesc
|
||||
|
||||
# implementation:
|
||||
|
||||
proc resize(old: int): int {.inline.} =
|
||||
assert(old < 65536 * 4)
|
||||
if old <= 0: return 1
|
||||
elif old < 65536: return old * 2
|
||||
else: return old * 3 div 2 # for large arrays * 3/2 is better
|
||||
|
||||
proc cmpStrings(a, b: mstring): int {.inline, compilerProc.} =
|
||||
if a == b: return 0
|
||||
if a == nil: return -1
|
||||
if b == nil: return 1
|
||||
return c_strcmp(a.data, b.data)
|
||||
|
||||
proc eqStrings(a, b: mstring): bool {.inline, compilerProc.} =
|
||||
if a == b: return true
|
||||
if a == nil or b == nil: return false
|
||||
return a.len == b.len and
|
||||
c_memcmp(a.data, b.data, a.len * sizeof(char)) == 0
|
||||
|
||||
proc rawNewString(space: int): mstring {.compilerProc.} =
|
||||
result = cast[mstring](newObj(addr(strDesc), sizeof(TStringDesc) +
|
||||
space * sizeof(char)))
|
||||
result.len = 0
|
||||
result.space = space
|
||||
result.data[0] = '\0'
|
||||
|
||||
proc mnewString(len: int): mstring {.exportc.} =
|
||||
result = rawNewString(len)
|
||||
result.len = len
|
||||
result.data[len] = '\0'
|
||||
|
||||
proc toNimStr(str: CString, len: int): mstring {.compilerProc.} =
|
||||
result = rawNewString(len)
|
||||
result.len = len
|
||||
c_memcpy(result.data, str, (len+1) * sizeof(Char))
|
||||
result.data[len] = '\0' # IO.readline relies on this!
|
||||
|
||||
proc cstrToNimstr(str: CString): mstring {.compilerProc.} =
|
||||
return toNimstr(str, c_strlen(str))
|
||||
|
||||
proc copyString(src: mstring): mstring {.compilerProc.} =
|
||||
result = rawNewString(src.space)
|
||||
result.len = src.len
|
||||
c_memcpy(result.data, src.data, (src.len + 1) * sizeof(Char))
|
||||
|
||||
proc hashString(s: string): int {.compilerproc.} =
|
||||
# the compiler needs exactly the same hash function!
|
||||
# this used to be used for efficient generation of string case statements
|
||||
var
|
||||
h: int
|
||||
h = 0
|
||||
for i in 0..Len(s)-1:
|
||||
h = h +% Ord(s[i])
|
||||
h = h +% h shl 10
|
||||
h = h xor (h shr 6)
|
||||
h = h +% h shl 3
|
||||
h = h xor (h shr 11)
|
||||
h = h +% h shl 15
|
||||
result = h
|
||||
|
||||
# copy(s: string, start = 0): string
|
||||
# {.extern: "copyStr", noDecl, noSideEffect.}
|
||||
# copy(s: string, start, len: int): string
|
||||
# {.extern: "copyStrLen", noDecl, noSideEffect.}
|
||||
#
|
||||
# setLength(var s: string, newlen: int)
|
||||
# {.extern: "setLengthStr", noDecl, noSideEffect.}
|
||||
|
||||
|
||||
proc copyStrLast(s: mstring, start, last: int): mstring {.exportc.} =
|
||||
var
|
||||
len: int
|
||||
if start >= s.len: return mnewString(0) # BUGFIX
|
||||
if last >= s.len:
|
||||
len = s.len - start # - 1 + 1
|
||||
else:
|
||||
len = last - start + 1
|
||||
result = rawNewString(len)
|
||||
result.len = len
|
||||
c_memcpy(result.data, addr(s.data[start]), len * sizeof(Char))
|
||||
result.data[len] = '\0'
|
||||
|
||||
proc copyStr(s: mstring, start: int): mstring {.exportc.} =
|
||||
return copyStrLast(s, start, s.len-1)
|
||||
|
||||
proc addChar(s: mstring, c: char): mstring {.compilerProc.} =
|
||||
result = s
|
||||
if result.len >= result.space:
|
||||
result.space = resize(result.space)
|
||||
result = cast[mstring](growObj(result,
|
||||
sizeof(TStringDesc) + result.space * sizeof(char)))
|
||||
result.data[result.len] = c
|
||||
result.data[result.len+1] = '\0'
|
||||
inc(result.len)
|
||||
|
||||
# These routines should be used like following:
|
||||
# <Nimrod code>
|
||||
# s &= "hallo " & name & " how do you feel?"
|
||||
#
|
||||
# <generated C code>
|
||||
# {
|
||||
# s = resizeString(s, 6 + name->len + 17);
|
||||
# appendString(s, strLit1);
|
||||
# appendString(s, strLit2);
|
||||
# appendString(s, strLit3);
|
||||
# }
|
||||
#
|
||||
# <Nimrod code>
|
||||
# s = "hallo " & name & " how do you feel?"
|
||||
#
|
||||
# <generated C code>
|
||||
# {
|
||||
# string tmp0;
|
||||
# tmp0 = rawNewString(6 + name->len + 17);
|
||||
# appendString(s, strLit1);
|
||||
# appendString(s, strLit2);
|
||||
# appendString(s, strLit3);
|
||||
# s = tmp0;
|
||||
# }
|
||||
#
|
||||
# <Nimrod code>
|
||||
# s = ""
|
||||
#
|
||||
# <generated C code>
|
||||
# s = rawNewString(0);
|
||||
|
||||
proc resizeString(dest: mstring, addlen: int): mstring {.compilerproc.} =
|
||||
if dest.len + addLen + 1 <= dest.space: # BUGFIX: this is horrible!
|
||||
result = dest
|
||||
else: # slow path:
|
||||
var
|
||||
sp = max(resize(dest.space), dest.len + addLen + 1)
|
||||
result = cast[mstring](growObj(dest, sizeof(TStringDesc) +
|
||||
sp * sizeof(Char)))
|
||||
# DO NOT UPDATE LEN YET: dest.len = newLen
|
||||
result.space = sp
|
||||
|
||||
proc appendString(dest, src: mstring) {.compilerproc, inline.} =
|
||||
c_memcpy(addr(dest.data[dest.len]), src.data, (src.len + 1) * sizeof(Char))
|
||||
inc(dest.len, src.len)
|
||||
|
||||
proc appendChar(dest: mstring, c: char) {.compilerproc, inline.} =
|
||||
dest.data[dest.len] = c
|
||||
dest.data[dest.len+1] = '\0'
|
||||
inc(dest.len)
|
||||
|
||||
proc setLengthStr(s: mstring, newLen: int): mstring {.compilerProc.} =
|
||||
var n = max(newLen, 0)
|
||||
if n <= s.space:
|
||||
result = s
|
||||
else:
|
||||
result = resizeString(s, n)
|
||||
result.len = n
|
||||
result.data[n] = '\0'
|
||||
|
||||
# ----------------- sequences ----------------------------------------------
|
||||
|
||||
proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
|
||||
# increments the length by one:
|
||||
# this is needed for supporting the &= operator;
|
||||
#
|
||||
# add seq x generates:
|
||||
# seq = incrSeq(seq, sizeof(x));
|
||||
# seq[seq->len-1] = x;
|
||||
result = seq
|
||||
if result.len >= result.space:
|
||||
var
|
||||
s: TAddress
|
||||
result.space = resize(result.space)
|
||||
result = cast[PGenericSeq](growObj(result, elemSize * result.space +
|
||||
GenericSeqSize))
|
||||
# set new elements to zero:
|
||||
s = cast[TAddress](result)
|
||||
zeroMem(cast[pointer](s + GenericSeqSize + (result.len * elemSize)),
|
||||
(result.space - result.len) * elemSize)
|
||||
# for i in len .. space-1:
|
||||
# seq->data[i] = 0
|
||||
inc(result.len)
|
||||
|
||||
proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
|
||||
compilerProc.} =
|
||||
result = seq
|
||||
if result.space < newLen:
|
||||
var
|
||||
s: TAddress
|
||||
result.space = max(resize(result.space), newLen)
|
||||
result = cast[PGenericSeq](growObj(result, elemSize * result.space +
|
||||
GenericSeqSize))
|
||||
# set new elements to zero (needed for GC):
|
||||
s = cast[TAddress](result)
|
||||
zeroMem(cast[pointer](s + GenericSeqSize + (result.len * elemSize)),
|
||||
(result.space - result.len) * elemSize)
|
||||
# Else: We could decref references, if we had type information here :-(
|
||||
# However, this does not happen often
|
||||
result.len = newLen
|
||||
|
||||
# --------------- other string routines ----------------------------------
|
||||
proc `$`(x: int): string =
|
||||
result = newString(sizeof(x)*4)
|
||||
var i = 0
|
||||
var y = x
|
||||
while True:
|
||||
var d = y div 10
|
||||
result[i] = chr(abs(int(y - d*10)) + ord('0'))
|
||||
inc(i)
|
||||
y = d
|
||||
if y == 0: break
|
||||
if x < 0:
|
||||
result[i] = '-'
|
||||
inc(i)
|
||||
setLen(result, i)
|
||||
# mirror the string:
|
||||
for j in 0..i div 2 - 1:
|
||||
swap(result[j], result[i-j-1])
|
||||
|
||||
{.push warnings: off.}
|
||||
proc `$`(x: float): string =
|
||||
var buf: array [0..59, char]
|
||||
c_sprintf(buf, "%#g", x)
|
||||
return $buf
|
||||
{.pop.}
|
||||
|
||||
proc `$`(x: int64): string =
|
||||
# we don't rely on C's runtime here as some C compiler's
|
||||
# int64 support is weak
|
||||
result = newString(sizeof(x)*4)
|
||||
var i = 0
|
||||
var y = x
|
||||
while True:
|
||||
var d = y div 10
|
||||
result[i] = chr(abs(int(y - d*10)) + ord('0'))
|
||||
inc(i)
|
||||
y = d
|
||||
if y == 0: break
|
||||
if x < 0:
|
||||
result[i] = '-'
|
||||
inc(i)
|
||||
setLen(result, i)
|
||||
# mirror the string:
|
||||
for j in 0..i div 2 - 1:
|
||||
swap(result[j], result[i-j-1])
|
||||
|
||||
proc `$`(x: bool): string =
|
||||
if x: result = "true"
|
||||
else: result = "false"
|
||||
|
||||
proc `$`(x: char): string =
|
||||
result = newString(1)
|
||||
result[0] = x
|
||||
|
||||
proc `$`(x: string): string =
|
||||
# this is useful for generic code!
|
||||
return x
|
||||
|
||||
|
||||
proc binaryStrSearch(x: openarray[string], y: string): int {.compilerproc.} =
|
||||
var
|
||||
a = 0
|
||||
b = len(x)
|
||||
while a < b:
|
||||
var mid = (a + b) div 2
|
||||
if x[mid] < y:
|
||||
a = mid + 1
|
||||
else:
|
||||
b = mid
|
||||
if (a < len(x)) and (x[a] == y):
|
||||
return a
|
||||
else:
|
||||
return -1
|
||||
1184
lib/system.nim
Executable file
1184
lib/system.nim
Executable file
File diff suppressed because it is too large
Load Diff
179
lib/times.nim
Executable file
179
lib/times.nim
Executable file
@@ -0,0 +1,179 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
|
||||
## This module contains routines and types for dealing with time.
|
||||
|
||||
{.push debugger:off .} # the user does not want to trace a part
|
||||
# of the standard library!
|
||||
|
||||
import
|
||||
strutils
|
||||
|
||||
type
|
||||
TMonth* = enum ## represents a month
|
||||
mJan, mFeb, mMar, mApr, mMay, mJun, mJul, mAug, mSep, mOct, mNov, mDec
|
||||
TWeekDay* = enum ## represents a weekday
|
||||
dMon, dTue, dWed, dThu, dFri, dSat, dSun
|
||||
|
||||
TTime* {.importc: "time_t".} = record ## abstract type that represents a time
|
||||
|
||||
TTimeInfo* = record ## represents a time in different parts
|
||||
second*: range[0..61] ## The number of seconds after the minute,
|
||||
## normally in the range 0 to 59, but can
|
||||
## be up to 61 to allow for leap seconds.
|
||||
minute*: range[0..59] ## The number of minutes after the hour,
|
||||
## in the range 0 to 59.
|
||||
hour*: range[0..23] ## The number of hours past midnight,
|
||||
## in the range 0 to 23.
|
||||
monthday*: range[1..31] ## The day of the month, in the range 1 to 31.
|
||||
month*: TMonth ## The current month.
|
||||
year*: int ## The current year.
|
||||
weekday*: TWeekDay ## The current day of the week.
|
||||
yearday*: range[0..365] ## The number of days since January 1,
|
||||
## in the range 0 to 365.
|
||||
|
||||
proc getTime*(): TTime ## gets the current calendar time
|
||||
proc getLocalTime*(t: TTime): TTimeInfo
|
||||
## converts the calendar time `t` to broken-time representation,
|
||||
## expressed relative to the user's specified time zone.
|
||||
proc getGMTime*(t: TTime): TTimeInfo
|
||||
## converts the calendar time `t` to broken-down time representation,
|
||||
## expressed in Coordinated Universal Time (UTC).
|
||||
|
||||
proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime
|
||||
## converts a broken-down time structure, expressed as local time, to
|
||||
## calendar time representation. The function ignores the specified
|
||||
## contents of the structure members `weekday` and `yearday` and recomputes
|
||||
## them from the other information in the broken-down time structure.
|
||||
|
||||
proc `$` *(timeInfo: TTimeInfo): string
|
||||
## converts a `TTimeInfo` record to a
|
||||
## string representation.
|
||||
proc `$` *(time: TTime): string
|
||||
## converts a calendar time to a
|
||||
## string representation.
|
||||
|
||||
proc getDateStr*(): string
|
||||
## gets the current date as a string of the format
|
||||
## ``YYYY-MM-DD``.
|
||||
proc getClockStr*(): string
|
||||
## gets the current clock time as a string of the format ``HH:MM:SS``.
|
||||
|
||||
proc `-` *(a, b: TTime): int64
|
||||
## computes the difference of two calendar times. Result is in seconds.
|
||||
|
||||
proc getStartMilsecs*(): int
|
||||
## get the miliseconds from the start of the program
|
||||
|
||||
#implementation
|
||||
|
||||
# C wrapper:
|
||||
type
|
||||
structTM {.importc: "struct tm".} = record
|
||||
second {.importc: "tm_sec".},
|
||||
minute {.importc: "tm_min".},
|
||||
hour {.importc: "tm_hour".},
|
||||
monthday {.importc: "tm_mday".},
|
||||
month {.importc: "tm_mon".},
|
||||
year {.importc: "tm_year".},
|
||||
weekday {.importc: "tm_wday".},
|
||||
yearday {.importc: "tm_yday".},
|
||||
isdst {.importc: "tm_isdst".}: cint
|
||||
|
||||
PTimeInfo = ptr structTM
|
||||
PTime = ptr TTime
|
||||
|
||||
TClock {.importc: "clock_t".} = range[low(int)..high(int)]
|
||||
|
||||
proc localtime(timer: PTime): PTimeInfo {.
|
||||
importc: "localtime", header: "<time.h>".}
|
||||
proc gmtime(timer: PTime): PTimeInfo {.importc: "gmtime", header: "<time.h>".}
|
||||
proc timec(timer: PTime): TTime {.importc: "time", header: "<time.h>".}
|
||||
proc mktime(t: structTM): TTime {.importc: "mktime", header: "<time.h>".}
|
||||
proc asctime(tblock: structTM): CString {.
|
||||
importc: "asctime", header: "<time.h>".}
|
||||
proc ctime(time: PTime): CString {.importc: "ctime", header: "<time.h>".}
|
||||
# strftime(s: CString, maxsize: int, fmt: CString, t: tm): int {.
|
||||
# importc: "strftime", header: "<time.h>".}
|
||||
proc clock(): TClock {.importc: "clock", header: "<time.h>".}
|
||||
proc difftime(a, b: TTime): float {.importc: "difftime", header: "<time.h>".}
|
||||
|
||||
var
|
||||
clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
|
||||
|
||||
|
||||
# our own procs on top of that:
|
||||
proc tmToTimeInfo(tm: structTM): TTimeInfo =
|
||||
const
|
||||
weekDays: array [0..6, TWeekDay] = [
|
||||
dSun, dMon, dTue, dWed, dThu, dFri, dSat]
|
||||
result.second = int(tm.second)
|
||||
result.minute = int(tm.minute)
|
||||
result.hour = int(tm.hour)
|
||||
result.monthday = int(tm.monthday)
|
||||
result.month = TMonth(tm.month)
|
||||
result.year = tm.year + 1900
|
||||
result.weekday = weekDays[int(tm.weekDay)]
|
||||
result.yearday = int(tm.yearday)
|
||||
|
||||
proc timeInfoToTM(t: TTimeInfo): structTM =
|
||||
const
|
||||
weekDays: array [TWeekDay, int] = [1, 2, 3, 4, 5, 6, 0]
|
||||
result.second = t.second
|
||||
result.minute = t.minute
|
||||
result.hour = t.hour
|
||||
result.monthday = t.monthday
|
||||
result.month = ord(t.month)
|
||||
result.year = t.year - 1900
|
||||
result.weekday = weekDays[t.weekDay]
|
||||
result.yearday = t.yearday
|
||||
result.isdst = -1
|
||||
|
||||
proc `-` (a, b: TTime): int64 =
|
||||
return toInt(difftime(a, b)) # XXX: toBiggestInt is needed here, but
|
||||
# Nim does not support it!
|
||||
|
||||
proc getStartMilsecs(): int = return clock() div (clocksPerSec div 1000)
|
||||
proc getTime(): TTime = return timec(nil)
|
||||
proc getLocalTime(t: TTime): TTimeInfo =
|
||||
var a = t
|
||||
result = tmToTimeInfo(localtime(addr(a))^)
|
||||
# copying is needed anyway to provide reentrancity; thus
|
||||
# the convertion is not expensive
|
||||
|
||||
proc getGMTime(t: TTime): TTimeInfo =
|
||||
var a = t
|
||||
result = tmToTimeInfo(gmtime(addr(a))^)
|
||||
# copying is needed anyway to provide reentrancity; thus
|
||||
# the convertion is not expensive
|
||||
|
||||
proc TimeInfoToTime(timeInfo: TTimeInfo): TTime =
|
||||
var cTimeInfo = timeInfo # for C++ we have to make a copy,
|
||||
# because the header of mktime is broken in my version of libc
|
||||
return mktime(timeInfoToTM(cTimeInfo))
|
||||
|
||||
proc getDateStr(): string =
|
||||
var ti = getLocalTime(getTime())
|
||||
result = $ti.year & "-" & intToStr(ord(ti.month)+1, 2) &
|
||||
"-" & intToStr(ti.monthDay, 2)
|
||||
|
||||
proc getClockStr(): string =
|
||||
var ti = getLocalTime(getTime())
|
||||
result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 2) &
|
||||
':' & intToStr(ti.second, 2)
|
||||
|
||||
proc `$`(timeInfo: TTimeInfo): string =
|
||||
return $asctime(timeInfoToTM(timeInfo))
|
||||
|
||||
proc `$`(time: TTime): string =
|
||||
var a = time
|
||||
return $ctime(addr(a))
|
||||
|
||||
{.pop.}
|
||||
221
lib/typeinfo.nim
Executable file
221
lib/typeinfo.nim
Executable file
@@ -0,0 +1,221 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# type-info module for Nimrod
|
||||
|
||||
include hti
|
||||
|
||||
proc typeid(x: any): PNimType
|
||||
|
||||
type
|
||||
Variant = opaque record
|
||||
# contains the address and a typeinfo
|
||||
a: pointer # an address
|
||||
k: TNimTypeKind
|
||||
|
||||
# conversions to any and from any are inserted by the compiler!
|
||||
# x.attr is supported, as well as x[]!
|
||||
# here is a special iterator for variants:
|
||||
iterator fields(x: variant): (fieldname: string, value: variant) =
|
||||
proc setField(structure: variant, fieldname: string, value: variant)
|
||||
proc getField(structure: variant, fieldname: string)
|
||||
|
||||
# any is implemented as a pair (val: pointer, info: PTypeInfo)
|
||||
# val is for:
|
||||
# an array - its address
|
||||
# a record - its address
|
||||
# an object - its address
|
||||
# a string - the address of the pointer to the string data
|
||||
# a sequence - the address of the pointer to the sequence data
|
||||
# a float - the address of a memory location where the float is stored
|
||||
# this is a given address; storage comes from compiler or is
|
||||
# already there (in a container)
|
||||
# an int - the address of a memory location where the int is stored
|
||||
# storage comes from compiler or is
|
||||
# already there (in a container)
|
||||
# a cstring - the address of an address of an array of chars
|
||||
# a ref - the address of the ref! (not the ref itself!)
|
||||
|
||||
# But this does not work too well...
|
||||
# Better: any is a ref to Object; than we define intObj, floatObj,
|
||||
# etc.; for strings this not needed as they already fit into the
|
||||
# scheme!
|
||||
#
|
||||
|
||||
type
|
||||
TAnyImpl {.exportc: "TAnyImpl".} = record
|
||||
typ {.exportc: "info".}: PNimType
|
||||
val {.exportc: "val".}: pointer
|
||||
|
||||
proc
|
||||
typeKind(p: PNimType): TTypeKind {.inline.}
|
||||
|
||||
getAnyLength(x: any): int
|
||||
|
||||
isContainer(x: any): bool
|
||||
|
||||
writeAny(container: any, index: int, val: any)
|
||||
readAny(container: any, index: int): any
|
||||
|
||||
writeAny(container: any, name: string, val: any)
|
||||
readAny(container: any, name: string): any
|
||||
|
||||
getAttr(container: any, index: int, out name: string, out val: any)
|
||||
|
||||
getEnumStrings(enumeration: any): sequence of string
|
||||
|
||||
anyToInt(x: any): biggestint
|
||||
anyToFloat(x: any): biggestfloat
|
||||
anyToString(x: any): string
|
||||
anyToChar(x: any): char
|
||||
anyToBool(x: any): bool
|
||||
#anyToT{T}(x: any, out result: T)
|
||||
|
||||
# etc...
|
||||
|
||||
#write(a: array of any) # also possible!
|
||||
|
||||
#generic proc
|
||||
# deepCopy{T}(x: T): T
|
||||
|
||||
import
|
||||
strutils
|
||||
|
||||
proc anyToImpl(a: any): TAnyImpl {.inline.} =
|
||||
result = cast{TAnyImpl}(a)
|
||||
|
||||
proc typeKind(p: PNimType): TTypeKind =
|
||||
result = p.typeKind
|
||||
|
||||
type
|
||||
Pint = untraced ref int
|
||||
Pint8 = untraced ref int8
|
||||
Pint16 = untraced ref int16
|
||||
Pint32 = untraced ref int32
|
||||
Pint64 = untraced ref int64
|
||||
Puint = untraced ref uint
|
||||
Puint8 = untraced ref uint8
|
||||
Puint16 = untraced ref uint16
|
||||
Puint32 = untraced ref uint32
|
||||
Puint64 = untraced ref uint64
|
||||
Pfloat = untraced ref float
|
||||
Pfloat32 = untraced ref float32
|
||||
Pfloat64 = untraced ref float64
|
||||
Pstring = untraced ref string
|
||||
Pbool = untraced ref bool
|
||||
Pchar = untraced ref char
|
||||
|
||||
proc anyToInt(x: any): biggestint =
|
||||
var impl = anyToImpl(x)
|
||||
case impl.typ.typeKind
|
||||
of tyInt, tyEnum: result = cast{pint}(x.val)^
|
||||
of tySInt8: result = cast{pint8}(x.val)^
|
||||
of tySInt16: result = cast{pint16}(x.val)^
|
||||
of tySInt32: result = cast{pint32}(x.val)^
|
||||
of tySInt64: result = cast{pint64}(x.val)^
|
||||
of tyUInt: result = cast{puint}(x.val)^
|
||||
of tyUInt8: result = cast{puint8}(x.val)^
|
||||
of tyUInt16: result = cast{puint16}(x.val)^
|
||||
of tyUInt32: result = cast{puint32}(x.val)^
|
||||
of tyUInt64: result = cast{puint64}(x.val)^
|
||||
else: raise EConvertError
|
||||
|
||||
proc anyToFloat(x: any): biggestfloat =
|
||||
var impl = anyToImpl(x)
|
||||
case impl.typ.typeKind
|
||||
of tyReal: result = cast{pfloat}(x.val)^
|
||||
of tyReal32: result = cast{pfloat32}(x.val)^
|
||||
of tyReal64: result = cast{pfloat64}(x.val)^
|
||||
# of tyReal128:
|
||||
else: raise EConvertError
|
||||
|
||||
proc anyToString(x: any): string =
|
||||
var impl = anyToImpl(x)
|
||||
case impl.typ.typeKind
|
||||
of tyString: result = cast{pstring}(x.val)^
|
||||
else: raise EConvertError
|
||||
|
||||
proc anyToChar(x: any): char =
|
||||
var impl = anyToImpl(x)
|
||||
case impl.typ.typeKind
|
||||
of tyChar: result = cast{pchar}(x.val)^
|
||||
else: raise EConvertError
|
||||
|
||||
proc anyToBool(x: any): bool =
|
||||
var impl = anyToImpl(x)
|
||||
case impl.typ.typeKind
|
||||
of tyBool: result = cast{pbool}(x.val)^
|
||||
else: raise EConvertError
|
||||
|
||||
proc getAnyLength(x: any): int =
|
||||
result = anyToImpl(x).typ.len
|
||||
|
||||
const
|
||||
ContainerSet = {tyArray, tyRecord, tyObject, tyOpenArray, tySequence, tyTable}
|
||||
|
||||
proc isContainer(x: any): bool =
|
||||
result = anyToImpl(x).typ.typeKind in ContainerSet
|
||||
|
||||
proc strcmp(a, b: cstring): int {.external: "strcmp", nodecl.}
|
||||
|
||||
proc strToIndex(info: PTypeInfo, str: string): int =
|
||||
for i in 0..typ.len-1:
|
||||
if strcmp(info.slots[i].name, str) == 0:
|
||||
return i
|
||||
raise EConvertError
|
||||
|
||||
proc writeAny(container: any, index: int, val: any) =
|
||||
var x = anyToImpl(container)
|
||||
if index >= 0 and index < container.len:
|
||||
case x.typ.typeKind
|
||||
of tySequence:
|
||||
var u = cast{TAddress}(x.val)
|
||||
genericAssignAux(cast{pointer}(u) +% x.typ.slots[index].offset +%
|
||||
GenericSeqSize,
|
||||
anyToImpl(val).val, u.typ.baseType)
|
||||
of tyArray:
|
||||
of tyRecord, tyObject:
|
||||
else: raise EConvertError
|
||||
else:
|
||||
raise EIndexError
|
||||
|
||||
|
||||
proc readAny(container: any, index: int): any =
|
||||
var x = anyToImpl(container)
|
||||
if x.typ.typeKind in ContainerSet:
|
||||
if index >= 0 and index < container.len:
|
||||
# XXX
|
||||
|
||||
else:
|
||||
raise EIndexError
|
||||
else:
|
||||
raise EConvertError
|
||||
|
||||
proc writeAny(container: any, name: string, val: any) =
|
||||
result = writeAny(container, strToIndex(anyToImpl(container).typ), val)
|
||||
|
||||
proc readAny(container: any, name: string): any =
|
||||
result = readAny(container, strToIndex(anyToImpl(container).typ))
|
||||
|
||||
proc getAttr(container: any, index: int, out name: string, out val: any) =
|
||||
var x = anyToImpl(container)
|
||||
if x.typ.typeKind in ContainerSet:
|
||||
val = readAny(container, index)
|
||||
name = $x.typ.slots[index].name
|
||||
else:
|
||||
raise EConvertError
|
||||
|
||||
proc getEnumStrings(enumeration: any): sequence of string =
|
||||
result = []
|
||||
var x = anyToImpl(enumeration)
|
||||
if x.typ.typekind == tyEnum:
|
||||
for i in 0 .. x.typ.len-1:
|
||||
result &= $x.typ.slots[i].name
|
||||
else:
|
||||
raise EConvertError
|
||||
103
lib/unicode.nim
Executable file
103
lib/unicode.nim
Executable file
@@ -0,0 +1,103 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
type
|
||||
TUniChar* = int32 ## type that can hold any Unicode character
|
||||
TUniChar16* = int16 ##
|
||||
|
||||
template ones(n) = ((1 shl n)-1)
|
||||
|
||||
proc uniCharLen*(s: string): int =
|
||||
## returns the number of Unicode characters of the string `s`.
|
||||
var i = 0
|
||||
while i < len(s):
|
||||
if ord(s[i]) <= 127:
|
||||
inc(i)
|
||||
elif ord(s[i]) shr 5 == 0b110:
|
||||
inc(i, 2)
|
||||
elif ord(s[i]) shr 4 == 0b1110:
|
||||
inc(i, 3)
|
||||
elif ord(s[i]) shr 3 == 0b11110:
|
||||
inc(i, 4)
|
||||
else:
|
||||
assert(false)
|
||||
inc(result)
|
||||
|
||||
proc uniCharAt*(s: string, i: int): TUniChar =
|
||||
if ord(s[i]) <= 127:
|
||||
result = ord(s[i])
|
||||
elif ord(s[i]) shr 5 == 0b110:
|
||||
assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and ones(5)) shl 6 or (ord(s[i+1]) and ones(6))
|
||||
elif ord(s[i]) shr 4 == 0b1110:
|
||||
assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and ones(4)) shl 12 or
|
||||
(ord(s[i+1]) and ones(6)) shl 6 or
|
||||
(ord(s[i+2]) and ones(6))
|
||||
elif ord(s[i]) shr 3 == 0b11110:
|
||||
assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
assert(ord(s[i+3]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and ones(3)) shl 18 or
|
||||
(ord(s[i+1]) and ones(6)) shl 12 or
|
||||
(ord(s[i+2]) and ones(6)) shl 6 or
|
||||
(ord(s[i+3]) and ones(6))
|
||||
else:
|
||||
assert(false)
|
||||
|
||||
iterator unichars*(s: string): TUniChar =
|
||||
## iterates over any unicode character of the string `s`. Fastest possible
|
||||
## method.
|
||||
var
|
||||
i = 0
|
||||
result: TUniChar
|
||||
while i < len(s):
|
||||
if ord(s[i]) <= 127:
|
||||
result = ord(s[i])
|
||||
inc(i)
|
||||
elif ord(s[i]) shr 5 == 0b110:
|
||||
result = (ord(s[i]) and ones(5)) shl 6 or (ord(s[i+1]) and ones(6))
|
||||
inc(i, 2)
|
||||
elif ord(s[i]) shr 4 == 0b1110:
|
||||
result = (ord(s[i]) and ones(4)) shl 12 or
|
||||
(ord(s[i+1]) and ones(6)) shl 6 or
|
||||
(ord(s[i+2]) and ones(6))
|
||||
inc(i, 3)
|
||||
elif ord(s[i]) shr 3 == 0b11110:
|
||||
result = (ord(s[i]) and ones(3)) shl 18 or
|
||||
(ord(s[i+1]) and ones(6)) shl 12 or
|
||||
(ord(s[i+2]) and ones(6)) shl 6 or
|
||||
(ord(s[i+3]) and ones(6))
|
||||
inc(i, 4)
|
||||
else:
|
||||
assert(false)
|
||||
yield result
|
||||
|
||||
proc utf8toLocale*(s: string): string
|
||||
proc localeToUtf8*(s: string): string
|
||||
|
||||
proc utf8toUtf16*(s: string): seq[TUniChar16]
|
||||
proc utf8toUcs4*(s: string): seq[TUniChar] =
|
||||
result = []
|
||||
for u in unichars(s):
|
||||
|
||||
proc ucs4ToUtf8(s: seq[TUnichar]): string
|
||||
proc utf16ToUtf8(s: seq[TUnichar16]): string
|
||||
proc ucs4toUft16(s: seq[TUnichar]): seq[TUnichar16]
|
||||
proc uft16toUcs4(s: seq[Tunichar16]): seq[TUnichar]
|
||||
|
||||
proc cmpUnicode*(a, b: string): int =
|
||||
## treats `a` and `b` as UTF-8 strings and compares them. Returns:
|
||||
## | < 0 iff a < b
|
||||
## | > 0 iff a > b
|
||||
## | == 0 iff a == b
|
||||
## This routine is useful for sorting UTF-8 strings.
|
||||
return -1
|
||||
|
||||
2656
lib/windows/mmsystem.nim
Executable file
2656
lib/windows/mmsystem.nim
Executable file
File diff suppressed because it is too large
Load Diff
230
lib/windows/nb30.nim
Executable file
230
lib/windows/nb30.nim
Executable file
@@ -0,0 +1,230 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
# NetBIOS 3.0 interface unit
|
||||
|
||||
# This unit contains the definitions for portable NetBIOS 3.0 support.
|
||||
|
||||
import # Data structure templates
|
||||
Windows
|
||||
|
||||
const
|
||||
NCBNAMSZ* = 16 # absolute length of a net name
|
||||
MAX_LANA* = 254 # lana's in range 0 to MAX_LANA inclusive
|
||||
|
||||
type # Network Control Block
|
||||
PNCB* = ptr TNCB
|
||||
TNCBPostProc* = proc (P: PNCB)
|
||||
TNCB* = record # Structure returned to the NCB command NCBASTAT is ADAPTER_STATUS followed
|
||||
# by an array of NAME_BUFFER structures.
|
||||
ncb_command*: Char # command code
|
||||
ncb_retcode*: Char # return code
|
||||
ncb_lsn*: Char # local session number
|
||||
ncb_num*: Char # number of our network name
|
||||
ncb_buffer*: cstring # address of message buffer
|
||||
ncb_length*: int16 # size of message buffer
|
||||
ncb_callname*: array[0..NCBNAMSZ - 1, char] # blank-padded name of remote
|
||||
ncb_name*: array[0..NCBNAMSZ - 1, char] # our blank-padded netname
|
||||
ncb_rto*: Char # rcv timeout/retry count
|
||||
ncb_sto*: Char # send timeout/sys timeout
|
||||
ncb_post*: TNCBPostProc # POST routine address
|
||||
ncb_lana_num*: Char # lana (adapter) number
|
||||
ncb_cmd_cplt*: Char # 0xff => commmand pending
|
||||
ncb_reserve*: array[0..9, Char] # reserved, used by BIOS
|
||||
ncb_event*: THandle # HANDLE to Win32 event which
|
||||
# will be set to the signalled
|
||||
# state when an ASYNCH command
|
||||
# completes
|
||||
|
||||
PAdapterStatus* = ptr TAdapterStatus
|
||||
TAdapterStatus* = record
|
||||
adapter_address*: array[0..5, Char]
|
||||
rev_major*: Char
|
||||
reserved0*: Char
|
||||
adapter_type*: Char
|
||||
rev_minor*: Char
|
||||
duration*: int16
|
||||
frmr_recv*: int16
|
||||
frmr_xmit*: int16
|
||||
iframe_recv_err*: int16
|
||||
xmit_aborts*: int16
|
||||
xmit_success*: DWORD
|
||||
recv_success*: DWORD
|
||||
iframe_xmit_err*: int16
|
||||
recv_buff_unavail*: int16
|
||||
t1_timeouts*: int16
|
||||
ti_timeouts*: int16
|
||||
reserved1*: DWORD
|
||||
free_ncbs*: int16
|
||||
max_cfg_ncbs*: int16
|
||||
max_ncbs*: int16
|
||||
xmit_buf_unavail*: int16
|
||||
max_dgram_size*: int16
|
||||
pending_sess*: int16
|
||||
max_cfg_sess*: int16
|
||||
max_sess*: int16
|
||||
max_sess_pkt_size*: int16
|
||||
name_count*: int16
|
||||
|
||||
PNameBuffer* = ptr TNameBuffer
|
||||
TNameBuffer* = record
|
||||
name*: array[0..NCBNAMSZ - 1, Char]
|
||||
name_num*: Char
|
||||
name_flags*: Char
|
||||
|
||||
|
||||
const # values for name_flags bits.
|
||||
NAME_FLAGS_MASK* = 0x00000087
|
||||
GROUP_NAME* = 0x00000080
|
||||
UNIQUE_NAME* = 0x00000000
|
||||
REGISTERING* = 0x00000000
|
||||
REGISTERED* = 0x00000004
|
||||
DEREGISTERED* = 0x00000005
|
||||
DUPLICATE* = 0x00000006
|
||||
DUPLICATE_DEREG* = 0x00000007
|
||||
|
||||
type # Structure returned to the NCB command NCBSSTAT is SESSION_HEADER followed
|
||||
# by an array of SESSION_BUFFER structures. If the NCB_NAME starts with an
|
||||
# asterisk then an array of these structures is returned containing the
|
||||
# status for all names.
|
||||
PSessionHeader* = ptr TSessionHeader
|
||||
TSessionHeader* = record
|
||||
sess_name*: Char
|
||||
num_sess*: Char
|
||||
rcv_dg_outstanding*: Char
|
||||
rcv_any_outstanding*: Char
|
||||
|
||||
PSessionBuffer* = ptr TSessionBuffer
|
||||
TSessionBuffer* = record
|
||||
lsn*: Char
|
||||
state*: Char
|
||||
local_name*: array[0..NCBNAMSZ - 1, Char]
|
||||
remote_name*: array[0..NCBNAMSZ - 1, Char]
|
||||
rcvs_outstanding*: Char
|
||||
sends_outstanding*: Char
|
||||
|
||||
|
||||
const # Values for state
|
||||
LISTEN_OUTSTANDING* = 0x00000001
|
||||
CALL_PENDING* = 0x00000002
|
||||
SESSION_ESTABLISHED* = 0x00000003
|
||||
HANGUP_PENDING* = 0x00000004
|
||||
HANGUP_COMPLETE* = 0x00000005
|
||||
SESSION_ABORTED* = 0x00000006
|
||||
|
||||
type # Structure returned to the NCB command NCBENUM.
|
||||
# On a system containing lana's 0, 2 and 3, a structure with
|
||||
# length =3, lana[0]=0, lana[1]=2 and lana[2]=3 will be returned.
|
||||
PLanaEnum* = ptr TLanaEnum
|
||||
TLanaEnum* = record # Structure returned to the NCB command NCBFINDNAME is FIND_NAME_HEADER followed
|
||||
# by an array of FIND_NAME_BUFFER structures.
|
||||
len*: Char # Number of valid entries in lana[]
|
||||
lana*: array[0..MAX_LANA, Char]
|
||||
|
||||
PFindNameHeader* = ptr TFindNameHeader
|
||||
TFindNameHeader* = record
|
||||
node_count*: int16
|
||||
reserved*: Char
|
||||
unique_group*: Char
|
||||
|
||||
PFindNameBuffer* = ptr TFindNameBuffer
|
||||
TFindNameBuffer* = record # Structure provided with NCBACTION. The purpose of NCBACTION is to provide
|
||||
# transport specific extensions to netbios.
|
||||
len*: Char
|
||||
access_control*: Char
|
||||
frame_control*: Char
|
||||
destination_addr*: array[0..5, Char]
|
||||
source_addr*: array[0..5, Char]
|
||||
routing_info*: array[0..17, Char]
|
||||
|
||||
PActionHeader* = ptr TActionHeader
|
||||
TActionHeader* = record
|
||||
transport_id*: int32
|
||||
action_code*: int16
|
||||
reserved*: int16
|
||||
|
||||
|
||||
const # Values for transport_id
|
||||
ALL_TRANSPORTS* = "M\0\0\0"
|
||||
MS_NBF* = "MNBF" # Special values and constants
|
||||
|
||||
const # NCB Command codes
|
||||
NCBCALL* = 0x00000010 # NCB CALL
|
||||
NCBLISTEN* = 0x00000011 # NCB LISTEN
|
||||
NCBHANGUP* = 0x00000012 # NCB HANG UP
|
||||
NCBSEND* = 0x00000014 # NCB SEND
|
||||
NCBRECV* = 0x00000015 # NCB RECEIVE
|
||||
NCBRECVANY* = 0x00000016 # NCB RECEIVE ANY
|
||||
NCBCHAINSEND* = 0x00000017 # NCB CHAIN SEND
|
||||
NCBDGSEND* = 0x00000020 # NCB SEND DATAGRAM
|
||||
NCBDGRECV* = 0x00000021 # NCB RECEIVE DATAGRAM
|
||||
NCBDGSENDBC* = 0x00000022 # NCB SEND BROADCAST DATAGRAM
|
||||
NCBDGRECVBC* = 0x00000023 # NCB RECEIVE BROADCAST DATAGRAM
|
||||
NCBADDNAME* = 0x00000030 # NCB ADD NAME
|
||||
NCBDELNAME* = 0x00000031 # NCB DELETE NAME
|
||||
NCBRESET* = 0x00000032 # NCB RESET
|
||||
NCBASTAT* = 0x00000033 # NCB ADAPTER STATUS
|
||||
NCBSSTAT* = 0x00000034 # NCB SESSION STATUS
|
||||
NCBCANCEL* = 0x00000035 # NCB CANCEL
|
||||
NCBADDGRNAME* = 0x00000036 # NCB ADD GROUP NAME
|
||||
NCBENUM* = 0x00000037 # NCB ENUMERATE LANA NUMBERS
|
||||
NCBUNLINK* = 0x00000070 # NCB UNLINK
|
||||
NCBSENDNA* = 0x00000071 # NCB SEND NO ACK
|
||||
NCBCHAINSENDNA* = 0x00000072 # NCB CHAIN SEND NO ACK
|
||||
NCBLANSTALERT* = 0x00000073 # NCB LAN STATUS ALERT
|
||||
NCBACTION* = 0x00000077 # NCB ACTION
|
||||
NCBFINDNAME* = 0x00000078 # NCB FIND NAME
|
||||
NCBTRACE* = 0x00000079 # NCB TRACE
|
||||
ASYNCH* = 0x00000080 # high bit set = asynchronous
|
||||
# NCB Return codes
|
||||
NRC_GOODRET* = 0x00000000 # good return
|
||||
# also returned when ASYNCH request accepted
|
||||
NRC_BUFLEN* = 0x00000001 # illegal buffer length
|
||||
NRC_ILLCMD* = 0x00000003 # illegal command
|
||||
NRC_CMDTMO* = 0x00000005 # command timed out
|
||||
NRC_INCOMP* = 0x00000006 # message incomplete, issue another command
|
||||
NRC_BADDR* = 0x00000007 # illegal buffer address
|
||||
NRC_SNUMOUT* = 0x00000008 # session number out of range
|
||||
NRC_NORES* = 0x00000009 # no resource available
|
||||
NRC_SCLOSED* = 0x0000000A # session closed
|
||||
NRC_CMDCAN* = 0x0000000B # command cancelled
|
||||
NRC_DUPNAME* = 0x0000000D # duplicate name
|
||||
NRC_NAMTFUL* = 0x0000000E # name table full
|
||||
NRC_ACTSES* = 0x0000000F # no deletions, name has active sessions
|
||||
NRC_LOCTFUL* = 0x00000011 # local session table full
|
||||
NRC_REMTFUL* = 0x00000012 # remote session table full
|
||||
NRC_ILLNN* = 0x00000013 # illegal name number
|
||||
NRC_NOCALL* = 0x00000014 # no callname
|
||||
NRC_NOWILD* = 0x00000015 # cannot put * in NCB_NAME
|
||||
NRC_INUSE* = 0x00000016 # name in use on remote adapter
|
||||
NRC_NAMERR* = 0x00000017 # name deleted
|
||||
NRC_SABORT* = 0x00000018 # session ended abnormally
|
||||
NRC_NAMCONF* = 0x00000019 # name conflict detected
|
||||
NRC_IFBUSY* = 0x00000021 # interface busy, IRET before retrying
|
||||
NRC_TOOMANY* = 0x00000022 # too many commands outstanding, retry later
|
||||
NRC_BRIDGE* = 0x00000023 # NCB_lana_num field invalid
|
||||
NRC_CANOCCR* = 0x00000024 # command completed while cancel occurring
|
||||
NRC_CANCEL* = 0x00000026 # command not valid to cancel
|
||||
NRC_DUPENV* = 0x00000030 # name defined by anther local process
|
||||
NRC_ENVNOTDEF* = 0x00000034 # environment undefined. RESET required
|
||||
NRC_OSRESNOTAV* = 0x00000035 # required OS resources exhausted
|
||||
NRC_MAXAPPS* = 0x00000036 # max number of applications exceeded
|
||||
NRC_NOSAPS* = 0x00000037 # no saps available for netbios
|
||||
NRC_NORESOURCES* = 0x00000038 # requested resources are not available
|
||||
NRC_INVADDRESS* = 0x00000039 # invalid ncb address or length > segment
|
||||
NRC_INVDDID* = 0x0000003B # invalid NCB DDID
|
||||
NRC_LOCKFAIL* = 0x0000003C # lock of user area failed
|
||||
NRC_OPENERR* = 0x0000003F # NETBIOS not loaded
|
||||
NRC_SYSTEM* = 0x00000040 # system error
|
||||
NRC_PENDING* = 0x000000FF # asynchronous command is not yet finished
|
||||
# main user entry point for NetBIOS 3.0
|
||||
# Usage: Result = Netbios( pncb );
|
||||
|
||||
proc Netbios*(P: PNCB): Char{.stdcall, dynlib: "netapi32.dll",
|
||||
importc: "Netbios".}
|
||||
# implementation
|
||||
208
lib/windows/ole2.nim
Executable file
208
lib/windows/ole2.nim
Executable file
@@ -0,0 +1,208 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2006 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
import
|
||||
windows
|
||||
|
||||
const
|
||||
GUID_NULL*: TGUID = (D1: 0x00000000, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000])
|
||||
IID_IUnknown*: TGUID = (D1: 0x00000000, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IClassFactory*: TGUID = (D1: 0x00000001, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IMarshal*: TGUID = (D1: 0x00000003, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IMalloc*: TGUID = (D1: 0x00000002, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IStdMarshalInfo*: TGUID = (D1: 0x00000018, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IExternalConnection*: TGUID = (D1: 0x00000019, D2: 0x00000000,
|
||||
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000046])
|
||||
IID_IEnumUnknown*: TGUID = (D1: 0x00000100, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IBindCtx*: TGUID = (D1: 0x0000000E, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IEnumMoniker*: TGUID = (D1: 0x00000102, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IRunnableObject*: TGUID = (D1: 0x00000126, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IRunningObjectTable*: TGUID = (D1: 0x00000010, D2: 0x00000000,
|
||||
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000046])
|
||||
IID_IPersist*: TGUID = (D1: 0x0000010C, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IPersistStream*: TGUID = (D1: 0x00000109, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IMoniker*: TGUID = (D1: 0x0000000F, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IEnumString*: TGUID = (D1: 0x00000101, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IStream*: TGUID = (D1: 0x0000000C, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IEnumStatStg*: TGUID = (D1: 0x0000000D, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IStorage*: TGUID = (D1: 0x0000000B, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IPersistFile*: TGUID = (D1: 0x0000010B, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IPersistStorage*: TGUID = (D1: 0x0000010A, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_ILockBytes*: TGUID = (D1: 0x0000000A, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IEnumFormatEtc*: TGUID = (D1: 0x00000103, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IEnumStatData*: TGUID = (D1: 0x00000105, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IRootStorage*: TGUID = (D1: 0x00000012, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IAdviseSink*: TGUID = (D1: 0x0000010F, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IAdviseSink2*: TGUID = (D1: 0x00000125, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IDataObject*: TGUID = (D1: 0x0000010E, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IDataAdviseHolder*: TGUID = (D1: 0x00000110, D2: 0x00000000,
|
||||
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000046])
|
||||
IID_IMessageFilter*: TGUID = (D1: 0x00000016, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IRpcChannelBuffer*: TGUID = (D1: 0xD5F56B60, D2: 0x0000593B,
|
||||
D3: 0x0000101A, D4: [0x000000B5, 0x00000069, 0x00000008, 0x00000000,
|
||||
0x0000002B, 0x0000002D, 0x000000BF, 0x0000007A])
|
||||
IID_IRpcProxyBuffer*: TGUID = (D1: 0xD5F56A34, D2: 0x0000593B, D3: 0x0000101A, D4: [
|
||||
0x000000B5, 0x00000069, 0x00000008, 0x00000000, 0x0000002B, 0x0000002D,
|
||||
0x000000BF, 0x0000007A])
|
||||
IID_IRpcStubBuffer*: TGUID = (D1: 0xD5F56AFC, D2: 0x0000593B, D3: 0x0000101A, D4: [
|
||||
0x000000B5, 0x00000069, 0x00000008, 0x00000000, 0x0000002B, 0x0000002D,
|
||||
0x000000BF, 0x0000007A])
|
||||
IID_IPSFactoryBuffer*: TGUID = (D1: 0xD5F569D0, D2: 0x0000593B,
|
||||
D3: 0x0000101A, D4: [0x000000B5, 0x00000069, 0x00000008, 0x00000000,
|
||||
0x0000002B, 0x0000002D, 0x000000BF, 0x0000007A])
|
||||
IID_ICreateTypeInfo*: TGUID = (D1: 0x00020405, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_ICreateTypeLib*: TGUID = (D1: 0x00020406, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IDispatch*: TGUID = (D1: 0x00020400, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IEnumVariant*: TGUID = (D1: 0x00020404, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_ITypeComp*: TGUID = (D1: 0x00020403, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_ITypeInfo*: TGUID = (D1: 0x00020401, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_ITypeLib*: TGUID = (D1: 0x00020402, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IErrorInfo*: TGUID = (D1: 0x1CF2B120, D2: 0x0000547D, D3: 0x0000101B, D4: [
|
||||
0x0000008E, 0x00000065, 0x00000008, 0x00000000, 0x0000002B, 0x0000002B,
|
||||
0x000000D1, 0x00000019])
|
||||
IID_ICreateErrorInfo*: TGUID = (D1: 0x22F03340, D2: 0x0000547D,
|
||||
D3: 0x0000101B, D4: [0x0000008E, 0x00000065, 0x00000008, 0x00000000,
|
||||
0x0000002B, 0x0000002B, 0x000000D1, 0x00000019])
|
||||
IID_ISupportErrorInfo*: TGUID = (D1: 0xDF0B3D60, D2: 0x0000548F,
|
||||
D3: 0x0000101B, D4: [0x0000008E, 0x00000065, 0x00000008, 0x00000000,
|
||||
0x0000002B, 0x0000002B, 0x000000D1, 0x00000019])
|
||||
IID_IOleAdviseHolder*: TGUID = (D1: 0x00000111, D2: 0x00000000,
|
||||
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000046])
|
||||
IID_IOleCache*: TGUID = (D1: 0x0000011E, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IOleCache2*: TGUID = (D1: 0x00000128, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IOleCacheControl*: TGUID = (D1: 0x00000129, D2: 0x00000000,
|
||||
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000046])
|
||||
IID_IParseDisplayName*: TGUID = (D1: 0x0000011A, D2: 0x00000000,
|
||||
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000046])
|
||||
IID_IOleContainer*: TGUID = (D1: 0x0000011B, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IOleClientSite*: TGUID = (D1: 0x00000118, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IOleObject*: TGUID = (D1: 0x00000112, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IOleWindow*: TGUID = (D1: 0x00000114, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IOleLink*: TGUID = (D1: 0x0000011D, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IOleItemContainer*: TGUID = (D1: 0x0000011C, D2: 0x00000000,
|
||||
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000046])
|
||||
IID_IOleInPlaceUIWindow*: TGUID = (D1: 0x00000115, D2: 0x00000000,
|
||||
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000046])
|
||||
IID_IOleInPlaceActiveObject*: TGUID = (D1: 0x00000117, D2: 0x00000000,
|
||||
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000046])
|
||||
IID_IOleInPlaceFrame*: TGUID = (D1: 0x00000116, D2: 0x00000000,
|
||||
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000046])
|
||||
IID_IOleInPlaceObject*: TGUID = (D1: 0x00000113, D2: 0x00000000,
|
||||
D3: 0x00000000, D4: [0x000000C0, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000046])
|
||||
IID_IOleInPlaceSite*: TGUID = (D1: 0x00000119, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IViewObject*: TGUID = (D1: 0x0000010D, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IViewObject2*: TGUID = (D1: 0x00000127, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IDropSource*: TGUID = (D1: 0x00000121, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IDropTarget*: TGUID = (D1: 0x00000122, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
IID_IEnumOleVerb*: TGUID = (D1: 0x00000104, D2: 0x00000000, D3: 0x00000000, D4: [
|
||||
0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000046])
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user