version 0.8.5: bugfixes; compiler now maintained in Nimrod

This commit is contained in:
Andreas Rumpf
2009-12-07 01:21:35 +01:00
parent 196ef92c86
commit 90119066ad
30 changed files with 1248 additions and 3819 deletions

View File

@@ -1,17 +0,0 @@
[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;

View File

@@ -1,70 +0,0 @@
#
#
# Nimrod Bootstrap Program
# (c) Copyright 2009 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import
os, strutils
const
BootCmd = [
"nimrod cc --compile:build/platdef.c $1 rod/nimrod.nim",
"bin/nimrod cc --compile:build/platdef.c $1 rod/nimrod.nim"
]
PlatdefCTmpl = """
/* Generated by boot.nim */
char* nimOS(void) { return "$1"; }
char* nimCPU(void) { return "$2"; }
"""
proc exec(cmd: string) =
echo(cmd)
if execShellCmd(cmd) != 0: quit("FAILURE")
proc writePlatdefC =
var f: TFile
if open(f, "build/platdef.c", fmWrite):
write(f, PlatdefcTmpl % [system.hostOS, system.hostCPU])
close(f)
else:
quit("Cannot write 'build/platdef.c'\n")
proc rodsrc =
const
blacklist = ["nsystem", "nmath", "nos", "osproc", "ntime", "strutils"]
cmd = "nimrod boot --skip_proj_cfg -o:rod/$1.nim nim/$1"
for fi in walkFiles("nim/*.pas"):
var f = splitFile(fi).name
if find(blacklist, f) >= 0: continue
var r = "rod" / addFileExt(f, "nim")
if not existsFile(r) or fileNewer(fi, r):
Exec(cmd % f)
proc boot(args: string) =
writePlatdefC()
rodsrc()
var newExe = addFileExt("rod/nimrod", ExeExt)
var oldExe = addFileExt("bin/nimrod", ExeExt)
for i in 0..1:
Echo("iteration: ", i+1)
# use the new executable to compile the files in the bootstrap directory:
Exec(Bootcmd[i] % args)
if sameFileContent(newExe, oldExe):
Echo("executables are equal: SUCCESS!")
return
else:
Echo("executables are not equal: compile once again...")
# move the new executable to bin directory:
os.moveFile(oldExe, newExe)
Echo("[Warning] executables are still not equal")
var a = ""
for i in 1 .. paramCount():
add(a, ' ')
add(a, paramStr(i))
boot(a)

709
cogapp.py
View File

@@ -1,709 +0,0 @@
""" 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 $
# modified to run with Python1.5.2 and Python3.0 by Andreas Rumpf
import os, re, string, sys, traceback, types, imp, copy, getopt, shlex
from pycompab import *
__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 $1 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.
"""
gErrorMsg = "" # this is needed to support Python 1.5.2 till 3.0
# Other package modules
from whiteutils import *
class CogError(Exception):
""" Any exception raised by Cog.
"""
def __init__(self, msg, file='', line=0):
global gErrorMsg
if file:
gErrorMsg = Subs("$1($2): $2", file, line, msg)
else:
gErrorMsg = msg
Exception.__init__(self, gErrorMsg)
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):
s = 0
e = len(L)
while s < len(L) and L[s] == '\n': s = s + 1
while e >= 1 and L[e-1] == '\n': e = e - 1
self.lines.append(L[s:e+1])
def getCode(self):
""" Extract the executable Python code from the generator.
"""
# 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:
tmp = []
for L in self.markers: tmp.append(replace(L, prefIn, '', 1))
self.markers = tmp
tmp = []
for L in self.lines: tmp.append(replace(L, prefIn, '', 1))
self.lines = tmp
#self.markers = [ l.replace(prefIn, '', 1) for l in self.markers ]
#self.lines = [ l.replace(prefIn, '', 1) for l in self.lines ]
return reindentBlock(self.lines, '')
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" + replace(intext, "\r\n", "\n") + "\n"
code = None
try:
import compiler
except ImportError:
code = compile(intext, str(fname), 'exec')
if code == None:
code = compiler.compile(intext, filename=str(fname), mode='exec')
# Make sure the "cog" module has our state.
cog.cogmodule.msg = self.msg
cog.cogmodule.out = self.out
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 = self.outstring + '\n'
return reindentBlock(self.outstring, prefOut)
def msg(self, s):
self.stdout.write("Message: "+s+"\n")
def out(self, sOut='', dedent=false, trimblanklines=false):
""" The cog.out function.
"""
if trimblanklines and ('\n' in sOut):
lines = split(sOut, '\n')
if strip(lines[0]) == '':
del lines[0]
if lines and strip(lines[-1]) == '':
del lines[-1]
sOut = join(lines,'\n')+'\n'
if dedent:
sOut = reindentBlock(sOut)
self.outstring = self.outstring + sOut
def outl(self, sOut='', dedent=false, trimblanklines=false):
""" The cog.outl function.
"""
self.out(sOut, dedent, trimblanklines)
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 = 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 = split(dirs, 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:
raise CogUsageError("invalid command line")
# 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 = split(a, '=', 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(Subs("Don't understand argument $1", 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: $1)'
self.options = CogOptions()
self.sOutputMode = 'w'
self.installCogModule()
def showWarning(self, msg):
self.stdout.write("Warning: " + msg + "\n")
def isBeginSpecLine(self, s):
return find(s, self.sBeginSpec) >= 0
def isEndSpecLine(self, s):
return find(s, self.sEndSpec) >= 0 and \
not self.isEndOutputLine(s)
def isEndOutputLine(self, s):
return 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 type(fIn) == type(""):
# Open the input file.
sFileIn = fIn
fIn = open(fIn, 'r')
if type(fOut) == type(""):
# 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(Subs("Unexpected '$1'", self.sEndSpec),
file=sFileIn, line=fIn.linenumber())
if self.isEndOutputLine(L):
raise CogError(Subs("Unexpected '$1'", 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 = find(L, self.sBeginSpec)
end = find(L, self.sEndSpec)
if beg > end:
raise CogError("Cog code markers inverted",
file=sFileIn, line=firstLineNum)
else:
sCode = strip(L[beg+len(self.sBeginSpec):end])
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(Subs("Unexpected '$1'", self.sBeginSpec),
file=sFileIn, line=fIn.linenumber())
if self.isEndOutputLine(L):
raise CogError(Subs("Unexpected '$1'", 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 = newMD5()
while L and not self.isEndOutputLine(L):
if self.isBeginSpecLine(L):
raise CogError(Subs("Unexpected '$1'", self.sBeginSpec),
file=sFileIn, line=fIn.linenumber())
if self.isEndSpecLine(L):
raise CogError(Subs("Unexpected '$1'", self.sEndSpec),
file=sFileIn, line=fIn.linenumber())
MD5update(hasher, L)
L = fIn.readline()
curHash = mydigest(hasher)
if not L and not self.options.bEofCanBeEnd:
# We reached end of file before we found the end output line.
raise CogError(Subs("Missing '$1' 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 = newMD5()
if not self.options.bNoGenerate:
sFile = Subs("$1+$2", sFileIn, firstLineNum)
sGen = gen.evaluate(cog=self, globals=globals, fname=sFile)
sGen = self.suffixLines(sGen)
MD5update(hasher, sGen)
fOut.write(sGen)
newHash = mydigest(hasher)
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 = split(L, hashMatch.group(0), 1)
else:
# There was no old hash, but we want a new hash.
endpieces = split(L, self.sEndOutput, 1)
L = join(endpieces, Subs(self.sEndFormat, newHash))
else:
# We don't want hashes output, so if there was one, get rid of
# it.
if hashMatch:
L = replace(L, 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 " + 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>" + replace(self.options.sSuffix, '\\', '\\\\')
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 = replace(self.options.sMakeWritableCmd, '$1', sOldPath)
self.stdout.write(os.popen(cmd).read())
if not os.access(sOldPath, os.W_OK):
raise CogError(Subs("Couldn't make $1 writable", sOldPath))
else:
# Can't write!
raise CogError("Can't overwrite " + 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.
self.stdout.write("Cogging " + sFile)
bNeedNewline = true
try:
fOldFile = open(sFile)
sOldText = fOldFile.read()
fOldFile.close()
sNewText = self.processString(sOldText, fname=sFile)
if sOldText != sNewText:
self.stdout.write(" (changed)\n")
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:
self.stdout.write('\n')
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:
self.stderr.write(usage)
return
self.options.parseArgs(argv)
self.options.validate()
if self.options.bShowVersion:
self.stdout.write(Subs("Cog version $1\n", __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.
"""
global gErrorMsg
try:
self.callableMain(argv)
return 0
except CogUsageError:
self.stderr.write(gErrorMsg + "\n")
self.stderr.write("(for help use -?)\n")
return 2
except CogGeneratedError:
self.stderr.write(Subs("Error: $1\n", gErrorMsg))
return 3
except CogError:
self.stderr.write(gErrorMsg + "\n")
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.

5
configure vendored
View File

@@ -1,5 +0,0 @@
#! /usr/bin/env sh
echo "there is nothing to configure"

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +1,3 @@
This directory contains data files in Python or ordinary text format. These
files are required for building Nimrod.
files are required for building Nimrod. Note: I try to get rid of the "data"
dictionary in the long run.

View File

@@ -168,7 +168,7 @@ tupleDesc ::= '[' optInd [param (comma param)*] [SAD] ']'
objectDef ::= 'object' [pragma] ['of' typeDesc] objectPart
enumField ::= symbol ['=' expr]
enumDef ::= 'enum' ['of' typeDesc] (enumField [comma] [COMMENT | IND COMMENT])+
enumDef ::= 'enum' (enumField [comma] [COMMENT | IND COMMENT])+
typeDecl ::= COMMENT
| symbol ['*'] [genericParams] ['=' typeDef] [COMMENT | IND COMMENT]

View File

@@ -22,13 +22,13 @@ Path Purpose
``bin`` generated binary files
``build`` generated C code for the installation
``nim`` Pascal sources of the Nimrod compiler; this
should be modified, not the Nimrod version in
``rod``!
has been used for bootstrapping, but new
development is done with the Nimrod version.
``rod`` Nimrod sources of the Nimrod compiler;
automatically generated from the Pascal
version
version.
``data`` data files that are used for generating source
code
code; not used anymore
``doc`` the documentation; it is a bunch of
reStructuredText files
``dist`` additional packages for the distribution
@@ -43,80 +43,23 @@ Path Purpose
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. However, the Pascal version
has no garbage collector and leaks memory! So the Pascal version should only
be used for bootstrapping.
Requirements for bootstrapping:
- Python (should work with version 1.5 or higher) (optional)
- supported C compiler
As of version 0.8.5 the compiler is maintained in Nimrod. (The first versions
have been implemented in Object Pascal.) The Python-based build system has
been rewritten in Nimrod too.
Compiling the compiler is a simple matter of running::
koch.py boot
nimrod c koch.nim
./koch boot
For a release version use::
koch.py boot -d:release
nimrod c koch.nim
./koch boot -d:release
The ``koch.py`` script is Nimrod's maintainance script. It is a replacement for
The ``koch`` program is Nimrod's maintainance script. It is a replacement for
make and shell scripting with the advantage that it is much more portable.
If you don't have Python, there is a ``boot`` Nimrod program which does roughly
the same::
nimrod cc boot.nim
./boot [-d:release]
Pascal annotations
==================
There are some annotations that the Pascal sources use so that they can
be converted to Nimrod automatically:
``{@discard} <expr>``
Tells the compiler that a ``discard`` statement is needed for Nimrod
here.
``{@cast}typ(expr)``
Tells the compiler that the Pascal conversion is a ``cast`` in Nimrod.
``{@emit <code>}``
Emits ``<code>``. The code fragment needs to be in Pascal syntax.
``{@ignore} <codeA> {@emit <codeB>}``
Ignores ``<codeA>`` and instead emits ``<codeB>`` which needs to be in
Pascal syntax. An empty ``{@emit}`` is possible too (it then only closes
the ``<codeA>`` part).
``record {@tuple}``
Is used to tell the compiler that the record type should be transformed
to a Nimrod tuple type.
``^ {@ptr}``
Is used to tell the compiler that the pointer type should be transformed
to a Nimrod ``ptr`` type. The default is a ``ref`` type.
``'a' + ''``
The idiom ``+''`` is used to tell the compiler that it is a string
literal and not a character literal. (Pascal does not distinguish between
character literals and string literals of length 1.)
``+{&}``
This tells the compiler that Pascal's ``+`` here is a string concatenation
and thus should be converted to ``&``. Note that this is not needed if
any of the operands is a string literal because the compiler then can
figure this out by itself.
``{@set}['a', 'b', 'c']``
Tells the compiler that Pascal's ``[]`` constructor is a set and not an
array. This is only needed if the compiler cannot figure this out for
itself.
Coding Guidelines
=================

View File

@@ -47,7 +47,7 @@ components called `locations`:idx:. A variable is basically a name for a
location. Each variable and location is of a certain `type`:idx:. The
variable's type is called `static type`:idx:, the location's type is called
`dynamic type`:idx:. If the static type is not the same as the dynamic type,
it is a supertype of the dynamic type.
it is a supertype or subtype of the dynamic type.
An `identifier`:idx: is a symbol declared as a name for a variable, type,
procedure, etc. The region of the program over which a declaration applies is
@@ -1066,7 +1066,7 @@ Type equality
~~~~~~~~~~~~~
Nimrod uses structural type equivalence for most types. Only for objects,
enumerations and distinct types name equivalence is used. The following
algorithm determines type equality:
algorithm (in pseudo-code) determines type equality:
.. code-block:: nimrod
proc typeEqualsAux(a, b: PType,
@@ -1362,11 +1362,12 @@ Example:
The `case`:idx: statement is similar to the if statement, but it represents
a multi-branch selection. The expression after the keyword ``case`` is
evaluated and if its value is in a *vallist* the corresponding statements
evaluated and if its value is in a *slicelist* the corresponding statements
(after the ``of`` keyword) are executed. If the value is not in any
given *slicelist* the ``else`` part is executed. If there is no ``else``
part and not all possible values that ``expr`` can hold occur in a ``vallist``,
a static error is given. This holds only for expressions of ordinal types.
part and not all possible values that ``expr`` can hold occur in a
``slicelist``, a static error occurs. This holds only for expressions of
ordinal types.
If the expression is not of an ordinal type, and no ``else`` part is
given, control passes after the ``case`` statement.
@@ -1398,7 +1399,7 @@ The `when`:idx: statement is almost identical to the ``if`` statement with some
exceptions:
* Each ``expr`` has to be a constant expression (of type ``bool``).
* The statements do not open a new scope if they introduce new identifiers.
* The statements do not open a new scope.
* The statements that belong to the expression that evaluated to true are
translated by the compiler, the other statements are not checked for
semantics! However, each ``expr`` is checked for semantics.
@@ -1814,8 +1815,8 @@ One can use `tuple unpacking`:idx: to access the tuple's fields:
Multi-methods
~~~~~~~~~~~~~
Procedures always use static dispatch. Dynamic dispatch is achieved by
`multi-methods`:idx:.
Procedures always use static dispatch. `Multi-methods`:idx: use dynamic
dispatch.
.. code-block:: nimrod
type
@@ -2133,8 +2134,8 @@ Symbol binding within templates happens after template instantation:
echo genId() # Error: undeclared identifier: 'lastId'
Exporting a template is a often a leaky abstraction. However, to compensate for
this case, the ``bind`` operator can be used: All identifiers
within a ``bind`` context are bound early (i.e. when the template is parsed).
this case, the ``bind`` operator can be used: All identifiers within a ``bind``
context are bound early (i.e. when the template is parsed).
The affected identifiers are then always bound early even if the other
occurences are in no ``bind`` context:

View File

@@ -6,7 +6,8 @@
:Version: |nimrodversion|
.. contents::
Introduction
============

View File

@@ -1,24 +0,0 @@
#! /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()

View File

@@ -1,302 +0,0 @@
#!/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"

201
koch.nim Executable file
View File

@@ -0,0 +1,201 @@
#
#
# Maintenance program for Nimrod
# (c) Copyright 2009 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import
os, strutils, parseopt
const
HelpText = """
+-----------------------------------------------------------------+
| Maintenance program for Nimrod |
| Version $1|
| (c) 2009 Andreas Rumpf |
+-----------------------------------------------------------------+
Build time: $2, $3
Usage:
koch.py [options] command [options for command]
Options:
--help, -h shows this help and quits
Possible Commands:
boot [options] bootstraps with given command line options
clean cleans Nimrod project; removes generated files
web generates the website
csource [options] builds the C sources for installation
zip builds the installation ZIP package
inno builds the Inno Setup installer
"""
proc exec(cmd: string) =
echo(cmd)
if execShellCmd(cmd) != 0: quit("FAILURE")
proc tryExec(cmd: string): bool =
echo(cmd)
result = execShellCmd(cmd) == 0
proc csource(args: string) =
exec("nimrod cc $# -r tools/niminst --var:version=$# csource rod/nimrod $2" %
[args, NimrodVersion])
proc zip(args: string) =
exec("nimrod cc -r tools/niminst --var:version=$# zip rod/nimrod" %
NimrodVersion)
proc inno(args: string) =
exec("nimrod cc -r tools/niminst --var:version=$# inno rod/nimrod" %
NimrodVersion)
proc install(args: string) =
exec("sh ./build.sh")
proc web(args: string) =
exec("nimrod cc -r tools/nimweb.nim web/nimrod --putenv:nimrodversion=$#" %
NimrodVersion)
proc exe(f: string): string = return addFileExt(f, ExeExt)
# -------------- nim ----------------------------------------------------------
proc compileNimCmd(args: string): string =
var cwd = getCurrentDir()
result = ("fpc -Cs16777216 -gl -bl -Crtoi -Sgidh -vw -Se1 $4 -o\"$1\" " &
"-FU\"$2\" \"$3\"") % [cwd / "bin" / "nim".exe,
cwd / "obj",
cwd / "nim" / "nimrod.pas",
args]
proc nim(args: string) = exec(compileNimCmd(args))
# -------------- boot ---------------------------------------------------------
proc writePlatdefC =
const
PlatdefCTmpl = """
/* Generated by boot.nim */
char* nimOS(void) { return "$#"; }
char* nimCPU(void) { return "$#"; }
"""
var f: TFile
if open(f, "build/platdef.c", fmWrite):
write(f, PlatdefcTmpl % [system.hostOS, system.hostCPU])
close(f)
else:
quit("Cannot write 'build/platdef.c'\n")
const
bootOptions = "--compile:build/platdef.c"
proc findStartNimrod: string =
const buildScript = "build.sh"
# we try several things before giving up:
# * bin/nimrod
# * $PATH/nimrod
# * bin/nim
# If these fail, we build nimrod with the "build.sh" script
# (but only on UNIX). Otherwise we try to compile "nim" with FPC
# and use "bin/nim".
var nimrod = "nimrod".exe
result = "bin" / nimrod
if ExistsFile(result): return
for dir in split(getEnv("PATH"), PathSep):
if ExistsFile(dir / nimrod): return nimrod
result = "bin" / "nim".exe
if ExistsFile(result): return
when defined(Posix):
if ExistsFile(buildScript):
if tryExec("./" & buildScript): return "bin" / nimrod
if tryExec(compileNimCmd("")): return
echo("Found no nimrod compiler and every attempt to build one failed!")
quit("FAILURE")
proc bootIteration(args: string): bool =
var nimrod1 = "rod" / "nimrod1".exe
moveFile nimrod1, "rod" / "nimrod".exe
exec "rod" / "nimrod1 cc $# $# rod/nimrod.nim" % [bootOptions, args]
result = sameFileContent("rod" / "nimrod".exe, "rod" / "nimrod1".exe)
if result:
moveFile "bin" / "nimrod".exe, "rod" / "nimrod".exe
echo "executables are equal: SUCCESS!"
removeFile nimrod1
proc boot(args: string) =
writePlatdefC()
echo "iteration: 1"
exec findStartNimrod() & " cc $# $# rod" / "nimrod.nim" % [bootOptions, args]
echo "iteration: 2"
if not bootIteration(args):
echo "executables are not equal: compile once again..."
if not bootIteration(args):
echo "[Warning] executables are still not equal"
# -------------- clean --------------------------------------------------------
const
cleanExt = [
".ppu", ".o", ".obj", ".dcu", ".~pas", ".~inc", ".~dsk", ".~dpr",
".map", ".tds", ".err", ".bak", ".pyc", ".exe", ".rod", ".pdb", ".idb"
]
ignore = [
".bzrignore", "nimrod", "nimrod.exe", "koch", "koch.exe"
]
proc cleanAux(dir: string) =
for kind, path in walkDir(dir):
case kind
of pcFile:
var (dir, name, ext) = splitFile(path)
if ext == "" or cleanExt.contains(ext):
if not ignore.contains(name):
echo "removing: ", path
removeFile(path)
of pcDir:
case splitPath(path).tail
of "nimcache":
echo "removing dir: ", path
removeDir(path)
of "dist", ".bzr":
nil
else:
cleanAux(path)
else: nil
proc removePattern(pattern: string) =
for f in WalkFiles(pattern):
echo "removing: ", f
removeFile(f)
proc clean(args: string) =
if ExistsFile("koch.dat"): removeFile("koch.dat")
removePattern("web/*.html")
removePattern("doc/*.html")
cleanAux(getCurrentDir())
proc showHelp() =
quit(HelpText % [NimrodVersion & repeatChar(44-len(NimrodVersion)),
CompileDate, CompileTime])
var op = initOptParser()
op.next()
case op.kind
of cmdLongOption, cmdShortOption: showHelp()
of cmdArgument:
case normalize(op.key)
of "boot": boot(op.cmdLineRest)
of "clean": clean(op.cmdLineRest)
of "web": web(op.cmdLineRest)
of "csource": csource(op.cmdLineRest)
of "zip": zip(op.cmdLineRest)
of "inno": inno(op.cmdLineRest)
of "install": install(op.cmdLineRest)
of "nim": nim(op.cmdLineRest)
else: showHelp()
of cmdEnd: showHelp()

668
koch.py
View File

@@ -1,668 +0,0 @@
#! /usr/bin/env python
##########################################################################
## ##
## Build script of the Nimrod Compiler ##
## (c) 2009 Andreas Rumpf ##
## ##
##########################################################################
import sys, os, os.path, re, shutil, time, getopt, glob, zlib, pickle
from pycompab import *
# --------------------- constants ----------------------------------------
NIMROD_VERSION = '0.8.3'
# 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**!
# 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; unfortunately often
# not backwards-compatible
# Patch level: is increased for every patch; should be completely
# backwards-compatible
EXPLAIN = true
force = false
GENERATE_DIFF = false
# if set, a diff.log file is generated when bootstrapping
USE_FPC = true
BOOTCMD = "$1 cc --compile:build/platdef.c $2 rod/nimrod.nim"
# the command used for bootstrapping
# ---------------------- compiler detection --------------------------------
def detect(cmd, lookFor="version"):
try:
pipe = os.popen4(cmd)[1]
except AttributeError:
pipe = os.popen(cmd)
result = None
for line in pipe.readlines():
if find(lower(line), lookFor) >= 0:
result = line[:-1]
break
pipe.close()
if not result:
# don't give up yet; it may have written to stderr
if os.system(cmd) == 0:
result = cmd
return result
def detectNimrod():
if detect("nimrod"):
return "nimrod"
elif detect("bin/nimrod"):
return "bin/nimrod"
else:
Error("could not find a working nimrod executable")
def detectNim():
if USE_FPC and detect("fpc -h"):
# workaround a bug in the macosx version of nim:
if getHost() == "macosx": return "nim"
else: return "bin/nim"
return detectNimrod()
def detectAndCompileNim():
result = detectNim()
if result == "bin/nim" or result == "nim":
cmd_nim()
return result
# --------------------------------------------------------------------------
def Error(msg): sys.exit("[Koch] *** ERROR: " + msg)
def Warn(msg): print("[Koch] *** WARNING: " + msg)
def Echo(msg): print("[Koch] " + msg)
def _Info(msg): print("[Koch] " + msg)
_FINGERPRINTS_FILE = "koch.dat"
# in this file all the fingerprints are kept to allow recognizing when a file
# has changed. This works reliably, which cannot be said from just taking
# filetime-stamps.
def SameFileContent(filenameA, filenameB):
SIZE = 4096*2
result = true
a = open(filenameA, "rb")
b = open(filenameB, "rb")
while true:
x = a.read(SIZE)
y = b.read(SIZE)
if x != y:
result = false
break
elif len(x) < SIZE: # EOF?
break
a.close()
b.close()
return result
def SplitArg(s):
if ':' in s: c = ':'
elif '=' in s: c = '='
else: return (s, '')
i = find(s, c)
return (s[:i], s[i+1:])
_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 = replace(result, "/", os.sep)
if os.pardir != "..": result = replace(result, "..", os.pardir)
return result
def Join(*args):
result = []
for a in args[:-1]:
result.append(a)
if result[-1] != "/": result.append("/")
result.append(args[-1])
return replace(join(result, ""), "//", "/")
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 Remove(f):
try:
os.remove(Path(f))
except OSError:
Warn("could not remove: " + f)
def Move(src, dest):
try:
m = shutil.move
except AttributeError:
def f(src, dest):
shutil.copy(src, dest)
Remove(src)
m = f
s = Path(src)
d = Path(dest)
try:
m(s, d)
except IOError:
Warn(Subs("could not move $1 to $2", s, d))
except OSError:
Warn(Subs("could not move $1 to $2", s, d))
def Copy(src, dest):
s = Path(src)
d = Path(dest)
try:
shutil.copyfile(s, d)
except IOError:
Warn(Subs("could not copy $1 to $2", s, d))
except OSError:
Warn(Subs("could not copy $1 to $2", s, d))
def RemoveDir(f):
try:
shutil.rmtree(Path(f))
except OSError:
Warn("could not remove: " + 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*.nim won't work
global _baseDir
(head, tail) = os.path.split(Path(pattern))
result = []
if os.path.exists(head):
try:
os.chdir(os.path.join(_baseDir, head))
try:
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):
return _Ext(trunc, 'lib${trunc}.so', '${trunc}.dll')
def LibExt(trunc):
return _Ext(trunc, '${trunc}.a', '${trunc}.lib')
def ScriptExt(trunc):
return _Ext(trunc, '${trunc}.sh', '${trunc}.bat')
def ExeExt(trunc):
return _Ext(trunc, '${trunc}', '${trunc}.exe')
def MakeExecutable(file):
os.chmod(file, 493)
class Changed:
""" Returns a Changed object. check() returns true iff one of the
given files has changed. You have to call the object's success()
method if the build has been a success.
Example:
c = Changed("unique_name", "file1.pas file2.pas file3.pas")
if c.check():
Exec("fpc file1.pas")
# Exec raises an exception if it fails, thus if we reach the
# next statement, 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 = pickle.load(open(fingerprintsfile, "rb"))
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 = open(f, "rb")
result = self._hashStr(x.read())
x.close() # for other Python implementations
return result
def check(self):
if type(self.files) == type(""):
self.files = split(self.files)
result = false
target = self.id
if not has_key(self.fingers, target):
self.fingers[target] = {}
if self.explain: _Info(Subs("no entries for target '$1'", target))
result = true
for d in self.files:
if Exists(d):
n = self._hashFile(d)
if not has_key(self.fingers[target], d) or n != self.fingers[target][d]:
result = true
if self.explain: _Info(Subs("'$1' modified since last build", d))
self.fingers[target][d] = n
else:
Warn(Subs("'$1' does not exist!", d))
result = true
return result
def update(self, filename):
self.fingers[self.id][filename] = self._hashFile(filename)
def success(self):
pickle.dump(self.fingers, open(self.filename, "wb+"))
# --------------------------------------------------------------------------
def CogRule(name, filename, dependson):
def processCog(filename):
from cogapp import Cog
ret = Cog().main([sys.argv[0], "-r", Path(filename)])
return ret
c = Changed(name, filename + " " + dependson, EXPLAIN)
if c.check() or force:
if processCog(filename) == 0:
c.update(filename)
c.success()
else:
Error("Cog failed")
_nim_exe = os.path.join(os.getcwd(), "bin", ExeExt("nim"))
_output_obj = os.path.join(os.getcwd(), "obj")
FPC_CMD = Subs("fpc -Cs16777216 -gl -bl -Crtoi -Sgidh -vw -Se1 -o\"$1\" "
"-FU\"$2\" \"$3\"", _nim_exe, _output_obj,
os.path.join(os.getcwd(), "nim", "nimrod.pas"))
def buildRod(options):
Exec(Subs("nim compile --compile:build/platdef.c $1 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")
CogRule("macros", "lib/pure/macros.nim", "koch.py data/ast.yml")
c = Changed("nim", Glob("nim/*.pas"), EXPLAIN)
if c.check() or force:
Exec(FPC_CMD)
if Exists(ExeExt("bin/nim")):
c.success()
return true
return false
def cmd_rod(options):
prereqs = Glob("lib/*.nim") + Glob("rod/*.nim") + [
"lib/nimbase.h", "config/nimrod.cfg"]
c = Changed("rod", prereqs, EXPLAIN)
if c.check() or cmd_nim() or force:
buildRod(options)
if Exists(ExeExt("bin/nimrod")):
c.success()
# -----------------------------------------------------------------------------
HELP = Subs("""\
+-----------------------------------------------------------------+
| Maintenance script for Nimrod |
| Version $1|
| (c) 2009 Andreas Rumpf |
+-----------------------------------------------------------------+
Your Python version: $2
Usage:
koch.py [options] command [options for command]
Options:
--force, -f, -B, -b forces rebuild
--diff generates a diff.log file when bootstrapping
--help, -h shows this help and quits
--no_fpc bootstrap without FPC
Possible Commands:
nim builds the Pascal version of Nimrod
rod [options] builds the Nimrod version of Nimrod (with options)
clean cleans Nimrod project; removes generated files
boot [options] bootstraps with given command line options
rodsrc generates Nimrod version from Pascal version
web generates the website
profile profiles the Nimrod compiler
csource [options] builds the C sources for installation
zip builds the installation ZIP package
inno builds the Inno Setup installer
""", NIMROD_VERSION + ' ' * (44-len(NIMROD_VERSION)), sys.version)
def main(args):
if len(args) == 0:
print(HELP)
else:
i = 0
while args[i][:1] == "-":
a = args[i]
if a in ("--force", "-f", "-B", "-b"):
global force
force = true
elif a in ("-h", "--help", "-?"):
print(HELP)
return
elif a == "--diff":
global GENERATE_DIFF
GENERATE_DIFF = true
elif a == "--no_fpc":
global USE_FPC
USE_FPC = false
else:
Error("illegal option: " + a)
i = i + 1
cmd = args[i]
if cmd == "rod": cmd_rod(join(args[i+1:]))
elif cmd == "nim": cmd_nim()
elif cmd == "clean": cmd_clean()
elif cmd == "boot": cmd_boot(join(args[i+1:]))
elif cmd == "rodsrc": cmd_rodsrc()
elif cmd == "web": cmd_web()
elif cmd == "profile": cmd_profile()
elif cmd == "zip": cmd_zip()
elif cmd == "inno": cmd_inno()
elif cmd == "csource": cmd_csource(join(args[i+1:]))
elif cmd == "install": cmd_install() # for backwards compability
#elif cmd == "llvmdebug": cmd_llvm(debug=true)
else: Error("illegal command: " + cmd)
def cmd_csource(args):
Exec(Subs(
"nimrod cc $2 -r tools/niminst --var:version=$1 csource rod/nimrod $2",
NIMROD_VERSION, args))
def cmd_zip():
Exec(Subs("nimrod cc -r tools/niminst --var:version=$1 zip rod/nimrod",
NIMROD_VERSION))
def cmd_inno():
Exec(Subs("nimrod cc -r tools/niminst --var:version=$1 inno rod/nimrod",
NIMROD_VERSION))
def cmd_install():
Exec("sh ./build.sh")
def cmd_llvm(debug=true):
if not debug: release = "--enable-optimized"
else: release = ""
Exec(Subs("./configure --enable-bindings $1 --enable-shared" +
" --enable-targets=host", release))
Exec("make")
Echo("Type [sudo] make install!")
# -------------------------- bootstrap ----------------------------------------
def readCFiles():
result = {}
if GENERATE_DIFF:
for f in Glob("rod/nimcache/rod/*.c") + Glob("rod/nimcache/lib/*.c"):
x = os.path.split(f)[1]
result[x] = open(f).readlines()[1:]
return result
def genBootDiff(genA, genB):
def interestingDiff(a, b):
#a = re.sub(r"([a-zA-Z_]+)([0-9]+)", r"\1____", a)
#b = re.sub(r"([a-zA-Z_]+)([0-9]+)", r"\1____", b)
return a != b
BOOTLOG = "bootdiff.log"
result = false
for f in Glob("diff/*.c"): Remove(f)
if Exists(BOOTLOG): Remove(BOOTLOG)
if GENERATE_DIFF:
lines = [] # lines of the generated logfile
if len(genA) != len(genB): Warn("number of generated files differ!")
for filename, acontent in genA.items():
bcontent = genB[filename]
if bcontent != acontent:
lines.append("------------------------------------------------------")
lines.append(filename + " differs")
# write the interesting lines to the log file:
for i in range(min(len(acontent), len(bcontent))):
la = acontent[i][:-1] # without newline!
lb = bcontent[i][:-1]
if interestingDiff(la, lb):
lines.append(Subs("$1 - $2", i, la))
lines.append(Subs("$1 + $2", i, lb))
if len(acontent) > len(bcontent):
cont = acontent
marker = "-"
else:
cont = bcontent
marker = "+"
for i in range(min(len(acontent), len(bcontent)), len(cont)):
lines.append(Subs("$1 $2 $3", i, marker, cont[i]))
open(os.path.join("diff", "a_"+filename), "w+").write(join(acontent, ""))
open(os.path.join("diff", "b_"+filename), "w+").write(join(bcontent, ""))
if lines: result = true
open(BOOTLOG, "w+").write(join(lines, "\n"))
return result
def cmd_rodsrc():
"converts the src/*.pas files into Nimrod syntax"
PAS_FILES_BLACKLIST = split("""nsystem nmath nos osproc ntime strutils""")
compiler = detectAndCompileNim()
CMD = "$1 boot --skip_proj_cfg -o:rod/$2.nim nim/$3"
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.check() or force:
Exec(Subs(CMD, compiler, f, f+".pas"))
Exec(Subs("$1 parse rod/$2.nim", compiler, f))
c.success()
result = true
return result
def moveExes():
Move(ExeExt("rod/nimrod"), ExeExt("bin/nimrod"))
def cmd_boot(args):
def myExec(compiler, args=args):
Exec(Subs(BOOTCMD, compiler, args))
# some C compilers (PellesC) output the executable to the
# wrong directory. We work around this bug here:
if Exists(ExeExt("rod/nimcache/nimrod")):
Move(ExeExt("rod/nimcache/nimrod"), ExeExt("rod/nimrod"))
writePlatdefC(getNimrodPath())
compiler = detectAndCompileNim()
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:
myExec(compiler)
genA = readCFiles() # first generation of generated C files
# move the new executable to bin directory:
moveExes()
# compile again and compare:
myExec("bin/nimrod") # here we always use the new executable
genB = readCFiles() # second generation of generated C files
diff = genBootDiff(genA, genB)
if diff:
Warn("generated C files are not equal: cycle once again...")
# check if the executables are the same (they should!):
if SameFileContent(Path(ExeExt("rod/nimrod")),
Path(ExeExt("bin/nimrod"))):
Echo("executables are equal: SUCCESS!")
else:
Echo("executables are not equal: cycle once again...")
diff = true
if diff:
# move the new executable to bin directory:
moveExes()
# use the new executable to compile Nimrod:
myExec("bin/nimrod")
if SameFileContent(Path(ExeExt("rod/nimrod")),
Path(ExeExt("bin/nimrod"))):
Echo("executables are equal: SUCCESS!")
else:
Warn("executables are still not equal")
# ------------------ profile --------------------------------------------------
def cmd_profile():
Exec(Subs(BOOTCMD, "nimrod", "-d:release --profiler:on"))
moveExes()
Exec(Subs(BOOTCMD, "nimrod", "--compile_only"))
# ------------------ web ------------------------------------------------------
def cmd_web():
Exec(Subs("nimrod cc -r tools/nimweb.nim web/nimrod "
"--putenv:nimrodversion=$1", NIMROD_VERSION))
# -----------------------------------------------------------------------------
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 = "."):
L = []
for x in split(CLEAN_EXT):
L.append(r".*\."+ x +"$")
extRegEx = re.compile(join(L, "|"))
if Exists("koch.dat"): Remove("koch.dat")
for f in Glob("*.pdb"): Remove(f)
for f in Glob("*.idb"): Remove(f)
for f in Glob("web/*.html"): Remove(f)
for f in Glob("doc/*.html"): Remove(f)
for f in Glob("doc/*.pdf"): Remove(f)
for f in Glob("rod/*.nim"): Remove(f) # remove generated source code
def visit(extRegEx, dirname, names):
if os.path.split(dirname)[1] == "nimcache":
shutil.rmtree(path=dirname, ignore_errors=true)
del names
else:
for name in names:
x = os.path.join(dirname, name)
if os.path.isdir(x): continue
if (extRegEx.match(name)
or (os.path.split(dirname)[1] == "tests" and ('.' not in name))):
if find(x, "/dist/") < 0 and find(x, "\\dist\\") < 0:
Echo("removing: " + x)
Remove(x)
os.path.walk(dir, visit, extRegEx)
def getHost():
# incomplete list that sys.platform may return:
# win32 aix3 aix4 atheos beos5 darwin freebsd2 freebsd3 freebsd4 freebsd5
# freebsd6 freebsd7 generic irix5 irix6 linux2 mac netbsd1 next3 os2emx
# riscos sunos5 unixware7
x = replace(lower(re.sub(r"[0-9]+$", r"", sys.platform)), "-", "")
if x == "win": return "windows"
elif x == "darwin": return "macosx" # probably Mac OS X
elif x == "sunos": return "solaris"
else: return x
def mydirwalker(dir, L):
for name in os.listdir(dir):
path = os.path.join(dir, name)
if os.path.isdir(path):
mydirwalker(path, L)
else:
L.append(path)
# --------------- install target ----------------------------------------------
def getOSandProcessor():
host = getHost()
if host == "windows": processor = "i386" # BUGFIX
else: processor = os.uname()[4]
if lower(processor) in ("i686", "i586", "i468", "i386"):
processor = "i386"
if lower(processor) in ("x86_64", "x86-64", "amd64"):
processor = "amd64"
if find(lower(processor), "sparc") >= 0:
processor = "sparc"
return (host, processor)
def writePlatdefC(nimrodpath):
host, processor = getOSandProcessor()
f = open(os.path.join(nimrodpath, "build/platdef.c"), "w+")
f.write(Subs('/* Generated by koch.py */\n'
'char* nimOS(void) { return "$1"; }\n'
'char* nimCPU(void) { return "$2"; }\n'
'\n', host, processor))
f.close()
def getNimrodPath():
if os.name == "posix":
# Does not work 100% reliably. It is the best solution though.
p = replace(sys.argv[0], "./", "")
return os.path.split(os.path.join(os.getcwd(), p))[0]
else: # Windows
return os.path.split(sys.argv[0])[0]
# ------------------- main ----------------------------------------------------
if __name__ == "__main__":
main(sys.argv[1:])

View File

@@ -339,3 +339,37 @@ proc writeContentType*() =
write(stdout, "Content-type: text/html\n\n")
system.stackTraceNewLine = "<br />\n"
proc setCookie*(name, value: string) =
## Sets a cookie.
write(stdout, "Set-Cookie: ", name, "=", value, "\n")
var
cookies: PStringTable = nil
proc parseCookies(s: string): PStringTable =
result = newStringTable(modeCaseInsensitive)
var i = 0
while true:
while s[i] == ' ' or s[i] == '\t': inc(i)
var keystart = i
while s[i] != '=' and s[i] != '\0': inc(i)
var keyend = i-1
if s[i] == '\0': break
inc(i) # skip '='
var valstart = i
while s[i] != ';' and s[i] != '\0': inc(i)
result[copy(s, keystart, keyend)] = copy(s, valstart, i-1)
if s[i] == '\0': break
inc(i) # skip ';'
proc getCookie*(name: string): string =
## Gets a cookie. If no cookie of `name` exists, "" is returned.
if cookies == nil: cookies = parseCookies(getHttpCookie())
result = cookies[name]
proc existsCookie*(name: string): bool =
## Checks if a cookie of `name` exists.
if cookies == nil: cookies = parseCookies(getHttpCookie())
result = hasKey(cookies)

View File

@@ -906,7 +906,7 @@ proc removeDir*(dir: string) =
for kind, path in walkDir(dir):
case kind
of pcFile, pcLinkToFile, pcLinkToDir: removeFile(path)
of pcDir: removeDir(dir)
of pcDir: removeDir(path)
rawRemoveDir(dir)
proc rawCreateDir(dir: string) =
@@ -935,7 +935,7 @@ proc parseCmdLine*(c: string): seq[string] =
result = @[]
var i = 0
var a = ""
while c[i] != '\0':
while true:
setLen(a, 0)
while c[i] >= '\1' and c[i] <= ' ': inc(i) # skip whitespace
case c[i]
@@ -946,6 +946,7 @@ proc parseCmdLine*(c: string): seq[string] =
add a, c[i]
inc(i)
if c[i] != '\0': inc(i)
of '\0': break
else:
while c[i] > ' ':
add(a, c[i])

View File

@@ -212,7 +212,7 @@ iterator split*(s: string, sep: char): string =
inc(last)
iterator splitLines*(s: string): string =
## Splits the string `s` into its containing lines. Each newline
## Splits the string `s` into its containing lines. Every newline
## combination (CR, LF, CR-LF) is supported. The result strings contain
## no trailing ``\n``.
##

View File

@@ -1120,6 +1120,11 @@ proc find*[T, S: typeDesc](a: T, item: S): int {.inline.}=
inc(result)
result = -1
proc contains*[T](a: openArray[T], item: T): bool {.inline.}=
## Returns true if `item` is in `a` or false if not found. This is a shortcut
## for ``find(a, item) >= 0``.
return find(a, item) >= 0
proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} =
## returns the last item of `s` and decreases ``s.len`` by one. This treats
## `s` as a stack and implements the common *pop* operation.

944
lib/wrappers/iup.nim Executable file
View File

@@ -0,0 +1,944 @@
#
# Binding for the IUP GUI toolkit
# (c) 2009 Andreas Rumpf
# C header files translated by hand
# Licence of IUP follows:
# ****************************************************************************
# Copyright (C) 1994-2009 Tecgraf, PUC-Rio.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# ****************************************************************************
when defined(windows):
const dllname = "iup(30|27|26|25|24).dll"
elif defined(macosx):
const dllname = "libiup(3.0|2.7|2.6|2.5|2.4).dylib"
else:
const dllname = "libiup(3.0|2.7|2.6|2.5|2.4).so.1"
const
IUP_NAME* = "IUP - Portable User Interface"
IUP_COPYRIGHT* = "Copyright (C) 1994-2009 Tecgraf, PUC-Rio."
IUP_DESCRIPTION* = "Portable toolkit for building graphical user interfaces."
constIUP_VERSION* = "3.0"
constIUP_VERSION_NUMBER* = 300000
constIUP_VERSION_DATE* = "2009/07/18"
type
Ihandle {.pure.} = object
PIhandle* = ptr Ihandle
Icallback* = proc (arg: PIhandle): cint {.cdecl.}
# pre-definided dialogs
proc FileDlg*: PIhandle {.importc: "IupFileDlg", dynlib: dllname, cdecl.}
proc MessageDlg*: PIhandle {.importc: "IupMessageDlg", dynlib: dllname, cdecl.}
proc ColorDlg*: PIhandle {.importc: "IupColorDlg", dynlib: dllname, cdecl.}
proc FontDlg*: PIhandle {.importc: "IupFontDlg", dynlib: dllname, cdecl.}
proc GetFile*(arq: cstring): cint {.
importc: "IupGetFile", dynlib: dllname, cdecl.}
proc Message*(title, msg: cstring) {.
importc: "IupMessage", dynlib: dllname, cdecl.}
proc Messagef*(title, format: cstring) {.
importc: "IupMessagef", dynlib: dllname, cdecl, varargs.}
proc Alarm*(title, msg, b1, b2, b3: cstring): cint {.
importc: "IupAlarm", dynlib: dllname, cdecl.}
proc Scanf*(format: cstring): cint {.
importc: "IupScanf", dynlib: dllname, cdecl, varargs.}
proc ListDialog*(theType: cint, title: cstring, size: cint,
list: cstringArray, op, max_col, max_lin: cint,
marks: ptr cint): cint {.
importc: "IupListDialog", dynlib: dllname, cdecl.}
proc GetText*(title, text: cstring): cint {.
importc: "IupGetText", dynlib: dllname, cdecl.}
proc GetColor*(x, y: cint, r, g, b: var byte): cint {.
importc: "IupGetColor", dynlib: dllname, cdecl.}
type
Iparamcb* = proc (dialog: PIhandle, param_index: cint,
user_data: pointer): cint {.cdecl.}
proc GetParam*(title: cstring, action: Iparamcb, user_data: pointer,
format: cstring): cint {.
importc: "IupGetParam", cdecl, varargs, dynlib: dllname.}
proc GetParamv*(title: cstring, action: Iparamcb, user_data: pointer,
format: cstring, param_count, param_extra: cint,
param_data: pointer): cint {.
importc: "IupGetParamv", cdecl, dynlib: dllname.}
# Functions
proc Open*(argc: ptr cint, argv: ptr cstringArray): cint {.
importc: "IupOpen", cdecl, dynlib: dllname.}
proc Close*() {.importc: "IupClose", cdecl, dynlib: dllname.}
proc ImageLibOpen*() {.importc: "IupImageLibOpen", cdecl, dynlib: dllname.}
proc MainLoop*(): cint {.importc: "IupMainLoop", cdecl, dynlib: dllname.}
proc LoopStep*(): cint {.importc: "IupLoopStep", cdecl, dynlib: dllname.}
proc MainLoopLevel*(): cint {.importc: "IupMainLoopLevel", cdecl, dynlib: dllname.}
proc Flush*() {.importc: "IupFlush", cdecl, dynlib: dllname.}
proc ExitLoop*() {.importc: "IupExitLoop", cdecl, dynlib: dllname.}
proc Update*(ih: PIhandle) {.importc: "IupUpdate", cdecl, dynlib: dllname.}
proc UpdateChildren*(ih: PIhandle) {.importc: "IupUpdateChildren", cdecl, dynlib: dllname.}
proc Redraw*(ih: PIhandle, children: cint) {.importc: "IupRedraw", cdecl, dynlib: dllname.}
proc Refresh*(ih: PIhandle) {.importc: "IupRefresh", cdecl, dynlib: dllname.}
proc MapFont*(iupfont: cstring): cstring {.importc: "IupMapFont", cdecl, dynlib: dllname.}
proc UnMapFont*(driverfont: cstring): cstring {.importc: "IupUnMapFont", cdecl, dynlib: dllname.}
proc Help*(url: cstring): cint {.importc: "IupHelp", cdecl, dynlib: dllname.}
proc Load*(filename: cstring): cstring {.importc: "IupLoad", cdecl, dynlib: dllname.}
proc IupVersion*(): cstring {.importc: "IupVersion", cdecl, dynlib: dllname.}
proc IupVersionDate*(): cstring {.importc: "IupVersionDate", cdecl, dynlib: dllname.}
proc IupVersionNumber*(): cint {.importc: "IupVersionNumber", cdecl, dynlib: dllname.}
proc SetLanguage*(lng: cstring) {.importc: "IupSetLanguage", cdecl, dynlib: dllname.}
proc GetLanguage*(): cstring {.importc: "IupGetLanguage", cdecl, dynlib: dllname.}
proc Destroy*(ih: PIhandle) {.importc: "IupDestroy", cdecl, dynlib: dllname.}
proc Detach*(child: PIhandle) {.importc: "IupDetach", cdecl, dynlib: dllname.}
proc Append*(ih, child: PIhandle): PIhandle {.
importc: "IupAppend", cdecl, dynlib: dllname.}
proc Insert*(ih, ref_child, child: PIhandle): PIhandle {.
importc: "IupInsert", cdecl, dynlib: dllname.}
proc GetChild*(ih: PIhandle, pos: cint): PIhandle {.
importc: "IupGetChild", cdecl, dynlib: dllname.}
proc GetChildPos*(ih, child: PIhandle): cint {.
importc: "IupGetChildPos", cdecl, dynlib: dllname.}
proc GetChildCount*(ih: PIhandle): cint {.
importc: "IupGetChildCount", cdecl, dynlib: dllname.}
proc GetNextChild*(ih, child: PIhandle): PIhandle {.
importc: "IupGetNextChild", cdecl, dynlib: dllname.}
proc GetBrother*(ih: PIhandle): PIhandle {.
importc: "IupGetBrother", cdecl, dynlib: dllname.}
proc GetParent*(ih: PIhandle): PIhandle {.
importc: "IupGetParent", cdecl, dynlib: dllname.}
proc GetDialog*(ih: PIhandle): PIhandle {.
importc: "IupGetDialog", cdecl, dynlib: dllname.}
proc GetDialogChild*(ih: PIhandle, name: cstring): PIhandle {.
importc: "IupGetDialogChild", cdecl, dynlib: dllname.}
proc Reparent*(ih, new_parent: PIhandle): cint {.
importc: "IupReparent", cdecl, dynlib: dllname.}
proc Popup*(ih: PIhandle, x, y: cint): cint {.
importc: "IupPopup", cdecl, dynlib: dllname.}
proc Show*(ih: PIhandle): cint {.
importc: "IupShow", cdecl, dynlib: dllname.}
proc ShowXY*(ih: PIhandle, x, y: cint): cint {.
importc: "IupShowXY", cdecl, dynlib: dllname.}
proc Hide*(ih: PIhandle): cint {.
importc: "IupHide", cdecl, dynlib: dllname.}
proc Map*(ih: PIhandle): cint {.
importc: "IupMap", cdecl, dynlib: dllname.}
proc Unmap*(ih: PIhandle) {.
importc: "IupUnmap", cdecl, dynlib: dllname.}
proc SetAttribute*(ih: PIhandle, name, value: cstring) {.
importc: "IupSetAttribute", cdecl, dynlib: dllname.}
proc StoreAttribute*(ih: PIhandle, name, value: cstring) {.
importc: "IupStoreAttribute", cdecl, dynlib: dllname.}
proc SetAttributes*(ih: PIhandle, str: cstring): PIhandle {.
importc: "IupSetAttributes", cdecl, dynlib: dllname.}
proc GetAttribute*(ih: PIhandle, name: cstring): cstring {.
importc: "IupGetAttribute", cdecl, dynlib: dllname.}
proc GetAttributes*(ih: PIhandle): cstring {.
importc: "IupGetAttributes", cdecl, dynlib: dllname.}
proc GetInt*(ih: PIhandle, name: cstring): cint {.
importc: "IupGetInt", cdecl, dynlib: dllname.}
proc GetInt2*(ih: PIhandle, name: cstring): cint {.
importc: "IupGetInt2", cdecl, dynlib: dllname.}
proc GetIntInt*(ih: PIhandle, name: cstring, i1, i2: var cint): cint {.
importc: "IupGetIntInt", cdecl, dynlib: dllname.}
proc GetFloat*(ih: PIhandle, name: cstring): cfloat {.
importc: "IupGetFloat", cdecl, dynlib: dllname.}
proc SetfAttribute*(ih: PIhandle, name, format: cstring) {.
importc: "IupSetfAttribute", cdecl, dynlib: dllname, varargs.}
proc GetAllAttributes*(ih: PIhandle, names: cstringArray, n: cint): cint {.
importc: "IupGetAllAttributes", cdecl, dynlib: dllname.}
proc SetAtt*(handle_name: cstring, ih: PIhandle, name: cstring): PIhandle {.
importc: "IupSetAtt", cdecl, dynlib: dllname, varargs.}
proc SetGlobal*(name, value: cstring) {.
importc: "IupSetGlobal", cdecl, dynlib: dllname.}
proc StoreGlobal*(name, value: cstring) {.
importc: "IupStoreGlobal", cdecl, dynlib: dllname.}
proc GetGlobal*(name: cstring): cstring {.
importc: "IupGetGlobal", cdecl, dynlib: dllname.}
proc SetFocus*(ih: PIhandle): PIhandle {.
importc: "IupSetFocus", cdecl, dynlib: dllname.}
proc GetFocus*(): PIhandle {.
importc: "IupGetFocus", cdecl, dynlib: dllname.}
proc PreviousField*(ih: PIhandle): PIhandle {.
importc: "IupPreviousField", cdecl, dynlib: dllname.}
proc NextField*(ih: PIhandle): PIhandle {.
importc: "IupNextField", cdecl, dynlib: dllname.}
proc GetCallback*(ih: PIhandle, name: cstring): Icallback {.
importc: "IupGetCallback", cdecl, dynlib: dllname.}
proc SetCallback*(ih: PIhandle, name: cstring, func: Icallback): Icallback {.
importc: "IupSetCallback", cdecl, dynlib: dllname.}
proc SetCallbacks*(ih: PIhandle, name: cstring, func: Icallback): PIhandle {.
importc: "IupSetCallbacks", cdecl, dynlib: dllname, varargs.}
proc GetFunction*(name: cstring): Icallback {.
importc: "IupGetFunction", cdecl, dynlib: dllname.}
proc SetFunction*(name: cstring, func: Icallback): Icallback {.
importc: "IupSetFunction", cdecl, dynlib: dllname.}
proc GetActionName*(): cstring {.
importc: "IupGetActionName", cdecl, dynlib: dllname.}
proc GetHandle*(name: cstring): PIhandle {.
importc: "IupGetHandle", cdecl, dynlib: dllname.}
proc SetHandle*(name: cstring, ih: PIhandle): PIhandle {.
importc: "IupSetHandle", cdecl, dynlib: dllname.}
proc GetAllNames*(names: cstringArray, n: cint): cint {.
importc: "IupGetAllNames", cdecl, dynlib: dllname.}
proc GetAllDialogs*(names: cstringArray, n: cint): cint {.
importc: "IupGetAllDialogs", cdecl, dynlib: dllname.}
proc GetName*(ih: PIhandle): cstring {.
importc: "IupGetName", cdecl, dynlib: dllname.}
proc SetAttributeHandle*(ih: PIhandle, name: cstring, ih_named: PIhandle) {.
importc: "IupSetAttributeHandle", cdecl, dynlib: dllname.}
proc GetAttributeHandle*(ih: PIhandle, name: cstring): PIhandle {.
importc: "IupGetAttributeHandle", cdecl, dynlib: dllname.}
proc GetClassName*(ih: PIhandle): cstring {.
importc: "IupGetClassName", cdecl, dynlib: dllname.}
proc GetClassType*(ih: PIhandle): cstring {.
importc: "IupGetClassType", cdecl, dynlib: dllname.}
proc GetClassAttributes*(classname: cstring, names: cstringArray,
n: cint): cint {.
importc: "IupGetClassAttributes", cdecl, dynlib: dllname.}
proc SaveClassAttributes*(ih: PIhandle) {.
importc: "IupSaveClassAttributes", cdecl, dynlib: dllname.}
proc SetClassDefaultAttribute*(classname, name, value: cstring) {.
importc: "IupSetClassDefaultAttribute", cdecl, dynlib: dllname.}
proc Create*(classname: cstring): PIhandle {.
importc: "IupCreate", cdecl, dynlib: dllname.}
proc Createv*(classname: cstring, params: pointer): PIhandle {.
importc: "IupCreatev", cdecl, dynlib: dllname.}
proc Createp*(classname: cstring, first: pointer): PIhandle {.
importc: "IupCreatep", cdecl, dynlib: dllname, varargs.}
proc Fill*(): PIhandle {.importc: "IupFill", cdecl, dynlib: dllname.}
proc Radio*(child: PIhandle): PIhandle {.
importc: "IupRadio", cdecl, dynlib: dllname.}
proc Vbox*(child: PIhandle): PIhandle {.
importc: "IupVbox", cdecl, dynlib: dllname, varargs.}
proc Vboxv*(children: ptr PIhandle): PIhandle {.
importc: "IupVboxv", cdecl, dynlib: dllname.}
proc Zbox*(child: PIhandle): PIhandle {.
importc: "IupZbox", cdecl, dynlib: dllname, varargs.}
proc Zboxv*(children: ptr PIhandle): PIhandle {.
importc: "IupZboxv", cdecl, dynlib: dllname.}
proc Hbox*(child: PIhandle): PIhandle {.
importc: "IupHbox", cdecl, dynlib: dllname, varargs.}
proc Hboxv*(children: ptr PIhandle): PIhandle {.
importc: "IupHboxv", cdecl, dynlib: dllname.}
proc Normalizer*(ih_first: PIhandle): PIhandle {.
importc: "IupNormalizer", cdecl, dynlib: dllname, varargs.}
proc Normalizerv*(ih_list: ptr PIhandle): PIhandle {.
importc: "IupNormalizerv", cdecl, dynlib: dllname.}
proc Cbox*(child: PIhandle): PIhandle {.
importc: "IupCbox", cdecl, dynlib: dllname, varargs.}
proc Cboxv*(children: ptr PIhandle): PIhandle {.
importc: "IupCboxv", cdecl, dynlib: dllname.}
proc Sbox*(child: PIhandle): PIhandle {.
importc: "IupSbox", cdecl, dynlib: dllname.}
proc Frame*(child: PIhandle): PIhandle {.
importc: "IupFrame", cdecl, dynlib: dllname.}
proc Image*(width, height: cint, pixmap: pointer): PIhandle {.
importc: "IupImage", cdecl, dynlib: dllname.}
proc ImageRGB*(width, height: cint, pixmap: pointer): PIhandle {.
importc: "IupImageRGB", cdecl, dynlib: dllname.}
proc ImageRGBA*(width, height: cint, pixmap: pointer): PIhandle {.
importc: "IupImageRGBA", cdecl, dynlib: dllname.}
proc Item*(title, action: cstring): PIhandle {.
importc: "IupItem", cdecl, dynlib: dllname.}
proc Submenu*(title: cstring, child: PIhandle): PIhandle {.
importc: "IupSubmenu", cdecl, dynlib: dllname.}
proc Separator*(): PIhandle {.
importc: "IupSeparator", cdecl, dynlib: dllname.}
proc Menu*(child: PIhandle): PIhandle {.
importc: "IupMenu", cdecl, dynlib: dllname, varargs.}
proc Menuv*(children: ptr PIhandle): PIhandle {.
importc: "IupMenuv", cdecl, dynlib: dllname.}
proc Button*(title, action: cstring): PIhandle {.
importc: "IupButton", cdecl, dynlib: dllname.}
proc Canvas*(action: cstring): PIhandle {.
importc: "IupCanvas", cdecl, dynlib: dllname.}
proc Dialog*(child: PIhandle): PIhandle {.
importc: "IupDialog", cdecl, dynlib: dllname.}
proc User*(): PIhandle {.
importc: "IupUser", cdecl, dynlib: dllname.}
proc Label*(title: cstring): PIhandle {.
importc: "IupLabel", cdecl, dynlib: dllname.}
proc List*(action: cstring): PIhandle {.
importc: "IupList", cdecl, dynlib: dllname.}
proc Text*(action: cstring): PIhandle {.
importc: "IupText", cdecl, dynlib: dllname.}
proc MultiLine*(action: cstring): PIhandle {.
importc: "IupMultiLine", cdecl, dynlib: dllname.}
proc Toggle*(title, action: cstring): PIhandle {.
importc: "IupToggle", cdecl, dynlib: dllname.}
proc Timer*(): PIhandle {.
importc: "IupTimer", cdecl, dynlib: dllname.}
proc ProgressBar*(): PIhandle {.
importc: "IupProgressBar", cdecl, dynlib: dllname.}
proc Val*(theType: cstring): PIhandle {.
importc: "IupVal", cdecl, dynlib: dllname.}
proc Tabs*(child: PIhandle): PIhandle {.
importc: "IupTabs", cdecl, dynlib: dllname, varargs.}
proc Tabsv*(children: ptr PIhandle): PIhandle {.
importc: "IupTabsv", cdecl, dynlib: dllname.}
proc Tree*(): PIhandle {.importc: "IupTree", cdecl, dynlib: dllname.}
proc Spin*(): PIhandle {.importc: "IupSpin", cdecl, dynlib: dllname.}
proc Spinbox*(child: PIhandle): PIhandle {.
importc: "IupSpinbox", cdecl, dynlib: dllname.}
# IupText utilities
proc TextConvertLinColToPos*(ih: PIhandle, lin, col: cint, pos: var cint) {.
importc: "IupTextConvertLinColToPos", cdecl, dynlib: dllname.}
proc TextConvertPosToLinCol*(ih: PIhandle, pos: cint, lin, col: var cint) {.
importc: "IupTextConvertPosToLinCol", cdecl, dynlib: dllname.}
proc ConvertXYToPos*(ih: PIhandle, x, y: cint): cint {.
importc: "IupConvertXYToPos", cdecl, dynlib: dllname.}
# IupTree utilities
proc TreeSetUserId*(ih: PIhandle, id: cint, userid: pointer): cint {.
importc: "IupTreeSetUserId", cdecl, dynlib: dllname.}
proc TreeGetUserId*(ih: PIhandle, id: cint): pointer {.
importc: "IupTreeGetUserId", cdecl, dynlib: dllname.}
proc TreeGetId*(ih: PIhandle, userid: pointer): cint {.
importc: "IupTreeGetId", cdecl, dynlib: dllname.}
proc TreeSetAttribute*(ih: PIhandle, name: cstring, id: cint, value: cstring) {.
importc: "IupTreeSetAttribute", cdecl, dynlib: dllname.}
proc TreeStoreAttribute*(ih: PIhandle, name: cstring, id: cint, value: cstring) {.
importc: "IupTreeStoreAttribute", cdecl, dynlib: dllname.}
proc TreeGetAttribute*(ih: PIhandle, name: cstring, id: cint): cstring {.
importc: "IupTreeGetAttribute", cdecl, dynlib: dllname.}
proc TreeGetInt*(ih: PIhandle, name: cstring, id: cint): cint {.
importc: "IupTreeGetInt", cdecl, dynlib: dllname.}
proc TreeGetFloat*(ih: PIhandle, name: cstring, id: cint): cfloat {.
importc: "IupTreeGetFloat", cdecl, dynlib: dllname.}
proc TreeSetfAttribute*(ih: PIhandle, name: cstring, id: cint, format: cstring) {.
importc: "IupTreeSetfAttribute", cdecl, dynlib: dllname, varargs.}
# Common Return Values
const
IUP_ERROR* = cint(1)
IUP_NOERROR* = cint(0)
IUP_OPENED* = cint(-1)
IUP_INVALID* = cint(-1)
# Callback Return Values
IUP_IGNORE* = cint(-1)
IUP_DEFAULT* = cint(-2)
IUP_CLOSE* = cint(-3)
IUP_CONTINUE* = cint(-4)
# IupPopup and IupShowXY Parameter Values
IUP_CENTER* = cint(0xFFFF)
IUP_LEFT* = cint(0xFFFE)
IUP_RIGHT* = cint(0xFFFD)
IUP_MOUSEPOS* = cint(0xFFFC)
IUP_CURRENT* = cint(0xFFFB)
IUP_CENTERPARENT* = cint(0xFFFA)
IUP_TOP* = IUP_LEFT
IUP_BOTTOM* = IUP_RIGHT
# SHOW_CB Callback Values
IUP_SHOW* = cint(0)
IUP_RESTORE* = cint(1)
IUP_MINIMIZE* = cint(2)
IUP_MAXIMIZE* = cint(3)
IUP_HIDE* = cint(4)
# SCROLL_CB Callback Values
IUP_SBUP* = cint(0)
IUP_SBDN* = cint(1)
IUP_SBPGUP* = cint(2)
IUP_SBPGDN* = cint(3)
IUP_SBPOSV* = cint(4)
IUP_SBDRAGV* = cint(5)
IUP_SBLEFT* = cint(6)
IUP_SBRIGHT* = cint(7)
IUP_SBPGLEFT* = cint(8)
IUP_SBPGRIGHT* = cint(9)
IUP_SBPOSH* = cint(10)
IUP_SBDRAGH* = cint(11)
# Mouse Button Values and Macros
IUP_BUTTON1* = cint(ord('1'))
IUP_BUTTON2* = cint(ord('2'))
IUP_BUTTON3* = cint(ord('3'))
IUP_BUTTON4* = cint(ord('4'))
IUP_BUTTON5* = cint(ord('5'))
proc isShift*(s: cstring): bool = return s[0] == 'S'
proc isControl*(s: cstring): bool = return s[1] == 'C'
proc isButton1*(s: cstring): bool = return s[2] == '1'
proc isButton2*(s: cstring): bool = return s[3] == '2'
proc isbutton3*(s: cstring): bool = return s[4] == '3'
proc isDouble*(s: cstring): bool = return s[5] == 'D'
proc isAlt*(s: cstring): bool = return s[6] == 'A'
proc isSys*(s: cstring): bool = return s[7] == 'Y'
proc isButton4*(s: cstring): bool = return s[8] == '4'
proc isButton5*(s: cstring): bool = return s[9] == '5'
# Pre-Defined Masks
const
IUP_MASK_FLOAT* = "[+/-]?(/d+/.?/d*|/./d+)"
IUP_MASK_UFLOAT* = "(/d+/.?/d*|/./d+)"
IUP_MASK_EFLOAT* = "[+/-]?(/d+/.?/d*|/./d+)([eE][+/-]?/d+)?"
IUP_MASK_INT* = "[+/-]?/d+"
IUP_MASK_UINT* = "/d+"
# from 32 to 126, all character sets are equal,
# the key code i the same as the character code.
const
K_SP* = cint(ord(' '))
K_exclam* = cint(ord('!'))
K_quotedbl* = cint(ord('\"'))
K_numbersign* = cint(ord('#'))
K_dollar* = cint(ord('$'))
K_percent* = cint(ord('%'))
K_ampersand* = cint(ord('&'))
K_apostrophe* = cint(ord('\''))
K_parentleft* = cint(ord('('))
K_parentright* = cint(ord(')'))
K_asterisk* = cint(ord('*'))
K_plus* = cint(ord('+'))
K_comma* = cint(ord(','))
K_minus* = cint(ord('-'))
K_period* = cint(ord('.'))
K_slash* = cint(ord('/'))
K_0* = cint(ord('0'))
K_1* = cint(ord('1'))
K_2* = cint(ord('2'))
K_3* = cint(ord('3'))
K_4* = cint(ord('4'))
K_5* = cint(ord('5'))
K_6* = cint(ord('6'))
K_7* = cint(ord('7'))
K_8* = cint(ord('8'))
K_9* = cint(ord('9'))
K_colon* = cint(ord(':'))
K_semicolon* = cint(ord(';'))
K_less* = cint(ord('<'))
K_equal* = cint(ord('='))
K_greater* = cint(ord('>'))
K_question* = cint(ord('?'))
K_at* = cint(ord('@'))
K_upperA* = cint(ord('A'))
K_upperB* = cint(ord('B'))
K_upperC* = cint(ord('C'))
K_upperD* = cint(ord('D'))
K_upperE* = cint(ord('E'))
K_upperF* = cint(ord('F'))
K_upperG* = cint(ord('G'))
K_upperH* = cint(ord('H'))
K_upperI* = cint(ord('I'))
K_upperJ* = cint(ord('J'))
K_upperK* = cint(ord('K'))
K_upperL* = cint(ord('L'))
K_upperM* = cint(ord('M'))
K_upperN* = cint(ord('N'))
K_upperO* = cint(ord('O'))
K_upperP* = cint(ord('P'))
K_upperQ* = cint(ord('Q'))
K_upperR* = cint(ord('R'))
K_upperS* = cint(ord('S'))
K_upperT* = cint(ord('T'))
K_upperU* = cint(ord('U'))
K_upperV* = cint(ord('V'))
K_upperW* = cint(ord('W'))
K_upperX* = cint(ord('X'))
K_upperY* = cint(ord('Y'))
K_upperZ* = cint(ord('Z'))
K_bracketleft* = cint(ord('['))
K_backslash* = cint(ord('\\'))
K_bracketright* = cint(ord(']'))
K_circum* = cint(ord('^'))
K_underscore* = cint(ord('_'))
K_grave* = cint(ord('`'))
K_lowera* = cint(ord('a'))
K_lowerb* = cint(ord('b'))
K_lowerc* = cint(ord('c'))
K_lowerd* = cint(ord('d'))
K_lowere* = cint(ord('e'))
K_lowerf* = cint(ord('f'))
K_lowerg* = cint(ord('g'))
K_lowerh* = cint(ord('h'))
K_loweri* = cint(ord('i'))
K_lowerj* = cint(ord('j'))
K_lowerk* = cint(ord('k'))
K_lowerl* = cint(ord('l'))
K_lowerm* = cint(ord('m'))
K_lowern* = cint(ord('n'))
K_lowero* = cint(ord('o'))
K_lowerp* = cint(ord('p'))
K_lowerq* = cint(ord('q'))
K_lowerr* = cint(ord('r'))
K_lowers* = cint(ord('s'))
K_lowert* = cint(ord('t'))
K_loweru* = cint(ord('u'))
K_lowerv* = cint(ord('v'))
K_lowerw* = cint(ord('w'))
K_lowerx* = cint(ord('x'))
K_lowery* = cint(ord('y'))
K_lowerz* = cint(ord('z'))
K_braceleft* = cint(ord('{'))
K_bar* = cint(ord('|'))
K_braceright* = cint(ord('}'))
K_tilde* = cint(ord('~'))
proc isPrint*(c: cint): bool = return c > 31 and c < 127
# also define the escape sequences that have keys associated
const
K_BS* = cint(ord('\b'))
K_TAB* = cint(ord('\t'))
K_LF* = cint(10)
K_CR* = cint(13)
# IUP Extended Key Codes, range start at 128
# Modifiers use 256 interval
# These key code definitions are specific to IUP
proc isXkey*(c: cint): bool = return c > 128
proc isShiftXkey*(c: cint): bool = return c > 256 and c < 512
proc isCtrlXkey*(c: cint): bool = return c > 512 and c < 768
proc isAltXkey*(c: cint): bool = return c > 768 and c < 1024
proc isSysXkey*(c: cint): bool = return c > 1024 and c < 1280
proc IUPxCODE*(c: cint): cint = return c + cint(128) # Normal (must be above 128)
proc IUPsxCODE*(c: cint): cint =
return c + cint(256)
# Shift (must have range to include the standard keys and the normal
# extended keys, so must be above 256
proc IUPcxCODE*(c: cint): cint = return c + cint(512) # Ctrl
proc IUPmxCODE*(c: cint): cint = return c + cint(768) # Alt
proc IUPyxCODE*(c: cint): cint = return c + cint(1024) # Sys (Win or Apple)
const
IUP_NUMMAXCODES* = 1280 ## 5*256=1280 Normal+Shift+Ctrl+Alt+Sys
K_HOME* = IUPxCODE(1)
K_UP* = IUPxCODE(2)
K_PGUP* = IUPxCODE(3)
K_LEFT* = IUPxCODE(4)
K_MIDDLE* = IUPxCODE(5)
K_RIGHT* = IUPxCODE(6)
K_END* = IUPxCODE(7)
K_DOWN* = IUPxCODE(8)
K_PGDN* = IUPxCODE(9)
K_INS* = IUPxCODE(10)
K_DEL* = IUPxCODE(11)
K_PAUSE* = IUPxCODE(12)
K_ESC* = IUPxCODE(13)
K_ccedilla* = IUPxCODE(14)
K_F1* = IUPxCODE(15)
K_F2* = IUPxCODE(16)
K_F3* = IUPxCODE(17)
K_F4* = IUPxCODE(18)
K_F5* = IUPxCODE(19)
K_F6* = IUPxCODE(20)
K_F7* = IUPxCODE(21)
K_F8* = IUPxCODE(22)
K_F9* = IUPxCODE(23)
K_F10* = IUPxCODE(24)
K_F11* = IUPxCODE(25)
K_F12* = IUPxCODE(26)
K_Print* = IUPxCODE(27)
K_Menu* = IUPxCODE(28)
K_acute* = IUPxCODE(29) # no Shift/Ctrl/Alt
K_sHOME* = IUPsxCODE(K_HOME)
K_sUP* = IUPsxCODE(K_UP)
K_sPGUP* = IUPsxCODE(K_PGUP)
K_sLEFT* = IUPsxCODE(K_LEFT)
K_sMIDDLE* = IUPsxCODE(K_MIDDLE)
K_sRIGHT* = IUPsxCODE(K_RIGHT)
K_sEND* = IUPsxCODE(K_END)
K_sDOWN* = IUPsxCODE(K_DOWN)
K_sPGDN* = IUPsxCODE(K_PGDN)
K_sINS* = IUPsxCODE(K_INS)
K_sDEL* = IUPsxCODE(K_DEL)
K_sSP* = IUPsxCODE(K_SP)
K_sTAB* = IUPsxCODE(K_TAB)
K_sCR* = IUPsxCODE(K_CR)
K_sBS* = IUPsxCODE(K_BS)
K_sPAUSE* = IUPsxCODE(K_PAUSE)
K_sESC* = IUPsxCODE(K_ESC)
K_sCcedilla* = IUPsxCODE(K_ccedilla)
K_sF1* = IUPsxCODE(K_F1)
K_sF2* = IUPsxCODE(K_F2)
K_sF3* = IUPsxCODE(K_F3)
K_sF4* = IUPsxCODE(K_F4)
K_sF5* = IUPsxCODE(K_F5)
K_sF6* = IUPsxCODE(K_F6)
K_sF7* = IUPsxCODE(K_F7)
K_sF8* = IUPsxCODE(K_F8)
K_sF9* = IUPsxCODE(K_F9)
K_sF10* = IUPsxCODE(K_F10)
K_sF11* = IUPsxCODE(K_F11)
K_sF12* = IUPsxCODE(K_F12)
K_sPrint* = IUPsxCODE(K_Print)
K_sMenu* = IUPsxCODE(K_Menu)
K_cHOME* = IUPcxCODE(K_HOME)
K_cUP* = IUPcxCODE(K_UP)
K_cPGUP* = IUPcxCODE(K_PGUP)
K_cLEFT* = IUPcxCODE(K_LEFT)
K_cMIDDLE* = IUPcxCODE(K_MIDDLE)
K_cRIGHT* = IUPcxCODE(K_RIGHT)
K_cEND* = IUPcxCODE(K_END)
K_cDOWN* = IUPcxCODE(K_DOWN)
K_cPGDN* = IUPcxCODE(K_PGDN)
K_cINS* = IUPcxCODE(K_INS)
K_cDEL* = IUPcxCODE(K_DEL)
K_cSP* = IUPcxCODE(K_SP)
K_cTAB* = IUPcxCODE(K_TAB)
K_cCR* = IUPcxCODE(K_CR)
K_cBS* = IUPcxCODE(K_BS)
K_cPAUSE* = IUPcxCODE(K_PAUSE)
K_cESC* = IUPcxCODE(K_ESC)
K_cCcedilla* = IUPcxCODE(K_ccedilla)
K_cF1* = IUPcxCODE(K_F1)
K_cF2* = IUPcxCODE(K_F2)
K_cF3* = IUPcxCODE(K_F3)
K_cF4* = IUPcxCODE(K_F4)
K_cF5* = IUPcxCODE(K_F5)
K_cF6* = IUPcxCODE(K_F6)
K_cF7* = IUPcxCODE(K_F7)
K_cF8* = IUPcxCODE(K_F8)
K_cF9* = IUPcxCODE(K_F9)
K_cF10* = IUPcxCODE(K_F10)
K_cF11* = IUPcxCODE(K_F11)
K_cF12* = IUPcxCODE(K_F12)
K_cPrint* = IUPcxCODE(K_Print)
K_cMenu* = IUPcxCODE(K_Menu)
K_mHOME* = IUPmxCODE(K_HOME)
K_mUP* = IUPmxCODE(K_UP)
K_mPGUP* = IUPmxCODE(K_PGUP)
K_mLEFT* = IUPmxCODE(K_LEFT)
K_mMIDDLE* = IUPmxCODE(K_MIDDLE)
K_mRIGHT* = IUPmxCODE(K_RIGHT)
K_mEND* = IUPmxCODE(K_END)
K_mDOWN* = IUPmxCODE(K_DOWN)
K_mPGDN* = IUPmxCODE(K_PGDN)
K_mINS* = IUPmxCODE(K_INS)
K_mDEL* = IUPmxCODE(K_DEL)
K_mSP* = IUPmxCODE(K_SP)
K_mTAB* = IUPmxCODE(K_TAB)
K_mCR* = IUPmxCODE(K_CR)
K_mBS* = IUPmxCODE(K_BS)
K_mPAUSE* = IUPmxCODE(K_PAUSE)
K_mESC* = IUPmxCODE(K_ESC)
K_mCcedilla* = IUPmxCODE(K_ccedilla)
K_mF1* = IUPmxCODE(K_F1)
K_mF2* = IUPmxCODE(K_F2)
K_mF3* = IUPmxCODE(K_F3)
K_mF4* = IUPmxCODE(K_F4)
K_mF5* = IUPmxCODE(K_F5)
K_mF6* = IUPmxCODE(K_F6)
K_mF7* = IUPmxCODE(K_F7)
K_mF8* = IUPmxCODE(K_F8)
K_mF9* = IUPmxCODE(K_F9)
K_mF10* = IUPmxCODE(K_F10)
K_mF11* = IUPmxCODE(K_F11)
K_mF12* = IUPmxCODE(K_F12)
K_mPrint* = IUPmxCODE(K_Print)
K_mMenu* = IUPmxCODE(K_Menu)
K_yHOME* = IUPyxCODE(K_HOME)
K_yUP* = IUPyxCODE(K_UP)
K_yPGUP* = IUPyxCODE(K_PGUP)
K_yLEFT* = IUPyxCODE(K_LEFT)
K_yMIDDLE* = IUPyxCODE(K_MIDDLE)
K_yRIGHT* = IUPyxCODE(K_RIGHT)
K_yEND* = IUPyxCODE(K_END)
K_yDOWN* = IUPyxCODE(K_DOWN)
K_yPGDN* = IUPyxCODE(K_PGDN)
K_yINS* = IUPyxCODE(K_INS)
K_yDEL* = IUPyxCODE(K_DEL)
K_ySP* = IUPyxCODE(K_SP)
K_yTAB* = IUPyxCODE(K_TAB)
K_yCR* = IUPyxCODE(K_CR)
K_yBS* = IUPyxCODE(K_BS)
K_yPAUSE* = IUPyxCODE(K_PAUSE)
K_yESC* = IUPyxCODE(K_ESC)
K_yCcedilla* = IUPyxCODE(K_ccedilla)
K_yF1* = IUPyxCODE(K_F1)
K_yF2* = IUPyxCODE(K_F2)
K_yF3* = IUPyxCODE(K_F3)
K_yF4* = IUPyxCODE(K_F4)
K_yF5* = IUPyxCODE(K_F5)
K_yF6* = IUPyxCODE(K_F6)
K_yF7* = IUPyxCODE(K_F7)
K_yF8* = IUPyxCODE(K_F8)
K_yF9* = IUPyxCODE(K_F9)
K_yF10* = IUPyxCODE(K_F10)
K_yF11* = IUPyxCODE(K_F11)
K_yF12* = IUPyxCODE(K_F12)
K_yPrint* = IUPyxCODE(K_Print)
K_yMenu* = IUPyxCODE(K_Menu)
K_sPlus* = IUPsxCODE(K_plus)
K_sComma* = IUPsxCODE(K_comma)
K_sMinus* = IUPsxCODE(K_minus)
K_sPeriod* = IUPsxCODE(K_period)
K_sSlash* = IUPsxCODE(K_slash)
K_sAsterisk* = IUPsxCODE(K_asterisk)
K_cupperA* = IUPcxCODE(K_upperA)
K_cupperB* = IUPcxCODE(K_upperB)
K_cupperC* = IUPcxCODE(K_upperC)
K_cupperD* = IUPcxCODE(K_upperD)
K_cupperE* = IUPcxCODE(K_upperE)
K_cupperF* = IUPcxCODE(K_upperF)
K_cupperG* = IUPcxCODE(K_upperG)
K_cupperH* = IUPcxCODE(K_upperH)
K_cupperI* = IUPcxCODE(K_upperI)
K_cupperJ* = IUPcxCODE(K_upperJ)
K_cupperK* = IUPcxCODE(K_upperK)
K_cupperL* = IUPcxCODE(K_upperL)
K_cupperM* = IUPcxCODE(K_upperM)
K_cupperN* = IUPcxCODE(K_upperN)
K_cupperO* = IUPcxCODE(K_upperO)
K_cupperP* = IUPcxCODE(K_upperP)
K_cupperQ* = IUPcxCODE(K_upperQ)
K_cupperR* = IUPcxCODE(K_upperR)
K_cupperS* = IUPcxCODE(K_upperS)
K_cupperT* = IUPcxCODE(K_upperT)
K_cupperU* = IUPcxCODE(K_upperU)
K_cupperV* = IUPcxCODE(K_upperV)
K_cupperW* = IUPcxCODE(K_upperW)
K_cupperX* = IUPcxCODE(K_upperX)
K_cupperY* = IUPcxCODE(K_upperY)
K_cupperZ* = IUPcxCODE(K_upperZ)
K_c1* = IUPcxCODE(K_1)
K_c2* = IUPcxCODE(K_2)
K_c3* = IUPcxCODE(K_3)
K_c4* = IUPcxCODE(K_4)
K_c5* = IUPcxCODE(K_5)
K_c6* = IUPcxCODE(K_6)
K_c7* = IUPcxCODE(K_7)
K_c8* = IUPcxCODE(K_8)
K_c9* = IUPcxCODE(K_9)
K_c0* = IUPcxCODE(K_0)
K_cPlus* = IUPcxCODE(K_plus)
K_cComma* = IUPcxCODE(K_comma)
K_cMinus* = IUPcxCODE(K_minus)
K_cPeriod* = IUPcxCODE(K_period)
K_cSlash* = IUPcxCODE(K_slash)
K_cSemicolon* = IUPcxCODE(K_semicolon)
K_cEqual* = IUPcxCODE(K_equal)
K_cBracketleft* = IUPcxCODE(K_bracketleft)
K_cBracketright* = IUPcxCODE(K_bracketright)
K_cBackslash* = IUPcxCODE(K_backslash)
K_cAsterisk* = IUPcxCODE(K_asterisk)
K_mupperA* = IUPmxCODE(K_upperA)
K_mupperB* = IUPmxCODE(K_upperB)
K_mupperC* = IUPmxCODE(K_upperC)
K_mupperD* = IUPmxCODE(K_upperD)
K_mupperE* = IUPmxCODE(K_upperE)
K_mupperF* = IUPmxCODE(K_upperF)
K_mupperG* = IUPmxCODE(K_upperG)
K_mupperH* = IUPmxCODE(K_upperH)
K_mupperI* = IUPmxCODE(K_upperI)
K_mupperJ* = IUPmxCODE(K_upperJ)
K_mupperK* = IUPmxCODE(K_upperK)
K_mupperL* = IUPmxCODE(K_upperL)
K_mupperM* = IUPmxCODE(K_upperM)
K_mupperN* = IUPmxCODE(K_upperN)
K_mupperO* = IUPmxCODE(K_upperO)
K_mupperP* = IUPmxCODE(K_upperP)
K_mupperQ* = IUPmxCODE(K_upperQ)
K_mupperR* = IUPmxCODE(K_upperR)
K_mupperS* = IUPmxCODE(K_upperS)
K_mupperT* = IUPmxCODE(K_upperT)
K_mupperU* = IUPmxCODE(K_upperU)
K_mupperV* = IUPmxCODE(K_upperV)
K_mupperW* = IUPmxCODE(K_upperW)
K_mupperX* = IUPmxCODE(K_upperX)
K_mupperY* = IUPmxCODE(K_upperY)
K_mupperZ* = IUPmxCODE(K_upperZ)
K_m1* = IUPmxCODE(K_1)
K_m2* = IUPmxCODE(K_2)
K_m3* = IUPmxCODE(K_3)
K_m4* = IUPmxCODE(K_4)
K_m5* = IUPmxCODE(K_5)
K_m6* = IUPmxCODE(K_6)
K_m7* = IUPmxCODE(K_7)
K_m8* = IUPmxCODE(K_8)
K_m9* = IUPmxCODE(K_9)
K_m0* = IUPmxCODE(K_0)
K_mPlus* = IUPmxCODE(K_plus)
K_mComma* = IUPmxCODE(K_comma)
K_mMinus* = IUPmxCODE(K_minus)
K_mPeriod* = IUPmxCODE(K_period)
K_mSlash* = IUPmxCODE(K_slash)
K_mSemicolon* = IUPmxCODE(K_semicolon)
K_mEqual* = IUPmxCODE(K_equal)
K_mBracketleft* = IUPmxCODE(K_bracketleft)
K_mBracketright* = IUPmxCODE(K_bracketright)
K_mBackslash* = IUPmxCODE(K_backslash)
K_mAsterisk* = IUPmxCODE(K_asterisk)
K_yA* = IUPyxCODE(K_upperA)
K_yB* = IUPyxCODE(K_upperB)
K_yC* = IUPyxCODE(K_upperC)
K_yD* = IUPyxCODE(K_upperD)
K_yE* = IUPyxCODE(K_upperE)
K_yF* = IUPyxCODE(K_upperF)
K_yG* = IUPyxCODE(K_upperG)
K_yH* = IUPyxCODE(K_upperH)
K_yI* = IUPyxCODE(K_upperI)
K_yJ* = IUPyxCODE(K_upperJ)
K_yK* = IUPyxCODE(K_upperK)
K_yL* = IUPyxCODE(K_upperL)
K_yM* = IUPyxCODE(K_upperM)
K_yN* = IUPyxCODE(K_upperN)
K_yO* = IUPyxCODE(K_upperO)
K_yP* = IUPyxCODE(K_upperP)
K_yQ* = IUPyxCODE(K_upperQ)
K_yR* = IUPyxCODE(K_upperR)
K_yS* = IUPyxCODE(K_upperS)
K_yT* = IUPyxCODE(K_upperT)
K_yU* = IUPyxCODE(K_upperU)
K_yV* = IUPyxCODE(K_upperV)
K_yW* = IUPyxCODE(K_upperW)
K_yX* = IUPyxCODE(K_upperX)
K_yY* = IUPyxCODE(K_upperY)
K_yZ* = IUPyxCODE(K_upperZ)
K_y1* = IUPyxCODE(K_1)
K_y2* = IUPyxCODE(K_2)
K_y3* = IUPyxCODE(K_3)
K_y4* = IUPyxCODE(K_4)
K_y5* = IUPyxCODE(K_5)
K_y6* = IUPyxCODE(K_6)
K_y7* = IUPyxCODE(K_7)
K_y8* = IUPyxCODE(K_8)
K_y9* = IUPyxCODE(K_9)
K_y0* = IUPyxCODE(K_0)
K_yPlus* = IUPyxCODE(K_plus)
K_yComma* = IUPyxCODE(K_comma)
K_yMinus* = IUPyxCODE(K_minus)
K_yPeriod* = IUPyxCODE(K_period)
K_ySlash* = IUPyxCODE(K_slash)
K_ySemicolon* = IUPyxCODE(K_semicolon)
K_yEqual* = IUPyxCODE(K_equal)
K_yBracketleft* = IUPyxCODE(K_bracketleft)
K_yBracketright* = IUPyxCODE(K_bracketright)
K_yBackslash* = IUPyxCODE(K_backslash)
K_yAsterisk* = IUPyxCODE(K_asterisk)
proc ControlsOpen*(): cint {.cdecl, importc: "IupControlsOpen", dynlib: dllname.}
proc ControlsClose*() {.cdecl, importc: "IupControlsClose", dynlib: dllname.}
proc OldValOpen*() {.cdecl, importc: "IupOldValOpen", dynlib: dllname.}
proc OldTabsOpen*() {.cdecl, importc: "IupOldTabsOpen", dynlib: dllname.}
proc Colorbar*(): PIhandle {.cdecl, importc: "IupColorbar", dynlib: dllname.}
proc Cells*(): PIhandle {.cdecl, importc: "IupCells", dynlib: dllname.}
proc ColorBrowser*(): PIhandle {.cdecl, importc: "IupColorBrowser", dynlib: dllname.}
proc Gauge*(): PIhandle {.cdecl, importc: "IupGauge", dynlib: dllname.}
proc Dial*(theType: cstring): PIhandle {.cdecl, importc: "IupDial", dynlib: dllname.}
proc Matrix*(action: cstring): PIhandle {.cdecl, importc: "IupMatrix", dynlib: dllname.}
# IupMatrix utilities
proc MatSetAttribute*(ih: PIhandle, name: cstring, lin, col: cint,
value: cstring) {.
cdecl, importc: "IupMatSetAttribute", dynlib: dllname.}
proc MatStoreAttribute*(ih: PIhandle, name: cstring, lin, col: cint,
value: cstring) {.cdecl,
importc: "IupMatStoreAttribute", dynlib: dllname.}
proc MatGetAttribute*(ih: PIhandle, name: cstring, lin, col: cint): cstring {.
cdecl, importc: "IupMatGetAttribute", dynlib: dllname.}
proc MatGetInt*(ih: PIhandle, name: cstring, lin, col: cint): cint {.
cdecl, importc: "IupMatGetInt", dynlib: dllname.}
proc MatGetFloat*(ih: PIhandle, name: cstring, lin, col: cint): cfloat {.
cdecl, importc: "IupMatGetFloat", dynlib: dllname.}
proc MatSetfAttribute*(ih: PIhandle, name: cstring, lin, col: cint,
format: cstring) {.cdecl,
importc: "IupMatSetfAttribute",
dynlib: dllname, varargs.}
# Used by IupColorbar
const
IUP_PRIMARY* = -1
IUP_SECONDARY* = -2
# Initialize PPlot widget class
proc PPlotOpen*() {.cdecl, importc: "IupPPlotOpen", dynlib: dllname.}
# Create an PPlot widget instance
proc PPlot*: PIhandle {.cdecl, importc: "IupPPlot", dynlib: dllname.}
# Add dataset to plot
proc PPlotBegin*(ih: PIhandle, strXdata: cint) {.
cdecl, importc: "IupPPlotBegin", dynlib: dllname.}
proc PPlotAdd*(ih: PIhandle, x, y: cfloat) {.
cdecl, importc: "IupPPlotAdd", dynlib: dllname.}
proc PPlotAddStr*(ih: PIhandle, x: cstring, y: cfloat) {.
cdecl, importc: "IupPPlotAddStr", dynlib: dllname.}
proc PPlotEnd*(ih: PIhandle): cint {.
cdecl, importc: "IupPPlotEnd", dynlib: dllname.}
proc PPlotInsertStr*(ih: PIhandle, index, sample_index: cint, x: cstring,
y: cfloat) {.cdecl, importc: "IupPPlotInsertStr",
dynlib: dllname.}
proc PPlotInsert*(ih: PIhandle, index, sample_index: cint,
x, y: cfloat) {.
cdecl, importc: "IupPPlotInsert", dynlib: dllname.}
# convert from plot coordinates to pixels
proc PPlotTransform*(ih: PIhandle, x, y: cfloat, ix, iy: var cint) {.
cdecl, importc: "IupPPlotTransform", dynlib: dllname.}
# Plot on the given device. Uses a "cdCanvas*".
proc PPlotPaintTo*(ih: PIhandle, cnv: pointer) {.
cdecl, importc: "IupPPlotPaintTo", dynlib: dllname.}

View File

@@ -1,14 +0,0 @@
# Dummy makefile for people who don't read "readme" files, or for automated
# installations
.PHONY : all
all:
python koch.py boot -d:release
.PHONY : install
install:
sh build.sh
.PHONY : clean
clean:
python koch.py clean

View File

@@ -886,19 +886,19 @@ begin
else begin
key := it;
end;
assert(key.kind = nkIdent);
case whichKeyword(key.ident) of
wBreakpoint: genBreakPoint(p, it);
wDeadCodeElim: begin
if not (optDeadCodeElim in gGlobalOptions) then begin
// we need to keep track of ``deadCodeElim`` pragma
if (sfDeadCodeElim in p.module.module.flags) then
addPendingModule(p.module)
end
if key.kind = nkIdent then
case whichKeyword(key.ident) of
wBreakpoint: genBreakPoint(p, it);
wDeadCodeElim: begin
if not (optDeadCodeElim in gGlobalOptions) then begin
// we need to keep track of ``deadCodeElim`` pragma
if (sfDeadCodeElim in p.module.module.flags) then
addPendingModule(p.module)
end
end
else begin end
end
else begin end
end
end;
end
end;
procedure genAsgn(p: BProc; e: PNode);

View File

@@ -1460,7 +1460,6 @@ begin
result := newNodeP(nkEnumTy, p);
a := nil;
getTok(p);
optInd(p, result);
if p.tok.tokType = tkOf then begin
a := newNodeP(nkOfInherit, p);
getTok(p); optInd(p, a);
@@ -1468,6 +1467,7 @@ begin
addSon(result, a)
end
else addSon(result, nil);
optInd(p, result);
while true do begin
case p.tok.tokType of

View File

@@ -607,7 +607,7 @@ begin
else invalidPragma(it);
end
else begin
processNote(c, n)
processNote(c, it)
end;
end;
if (sym <> nil) and (sym.kind <> skModule) then begin

View File

@@ -1,3 +1,4 @@
This is the Pascal version of the sources. The Nimrod version is generated
automatically from it. DO NOT MODIFY THE NIMROD VERSION OF THE SOURCES,
BUT THIS VERSION!
This is the Pascal version of the sources. The Nimrod version has been
generated automatically from it. DO NOT MODIFY THIS OLD VERSION, BUT THE
UP-TO-DATE VERSION IN NIMROD!

View File

@@ -1,109 +0,0 @@
""" Python compability library
With careful and painful coding, compability from Python 1.5.2 up to 3.0
is achieved. Don't try this at home.
Copyright 2009, Andreas Rumpf
"""
import sys
python3 = sys.version[0] >= "3"
python26 = sys.version[0] == "2" and sys.version[2] >= "6"
true, false = 0==0, 0==1
if python3:
sys.exit("This script does not yet work with Python 3.0")
try:
from cStringIO import StringIO
except ImportError:
from io import StringIO
if python3:
def replace(s, a, b): return s.replace(a, b)
def lower(s): return s.lower()
def join(a, s=""): return s.join(a)
def find(s, a): return s.find(a)
def split(s, a=None): return s.split(a)
def strip(s): return s.strip()
def has_key(dic, key): return key in dic
else:
from string import replace, lower, join, find, split, strip
def has_key(dic, key): return dic.has_key(key)
if not python3 and not python26:
import md5
def newMD5(): return md5.new()
def MD5update(obj, x):
return obj.update(x)
else:
import hashlib
def newMD5(): return hashlib.md5()
def MD5update(obj, x):
if python26:
return obj.update(x)
else:
return obj.update(bytes(x, "utf-8"))
def mydigest(hasher):
result = ""
for c in hasher.digest():
if python3:
x = hex(c)[2:]
else:
x = hex(ord(c))[2:]
if len(x) == 1: x = "0" + x
result = result + x
return result
def Subs(frmt, *args, **substitution):
DIGITS = "0123456789"
LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
chars = DIGITS+LETTERS+"_"
d = substitution
a = args
result = []
i = 0
num = 0
L = len(frmt)
while i < L:
if frmt[i] == '$':
i = i+1
if frmt[i] == '#':
result.append(a[num])
num = num+1
i = i+1
elif frmt[i] == '$':
result.append('$')
i = i+1
elif frmt[i] == '{':
i = i+1
j = i
while frmt[i] != '}': i = i+1
i = i+1 # skip }
x = frmt[j:i-1]
if x[0] in DIGITS:
result.append(str(a[int(x)-1]))
else:
result.append(str(d[x]))
elif frmt[i] in chars:
j = i
i = i+1
while i < len(frmt) and frmt[i] in chars: i = i + 1
x = frmt[j:i]
if x[0] in DIGITS:
num = int(x)
result.append(str(a[num-1]))
else:
result.append(str(d[x]))
else:
assert(false)
else:
result.append(frmt[i])
i = i+1
return join(result, "")

View File

@@ -33,7 +33,6 @@ Files: "doc/*.cfg"
Files: "readme.txt;install.txt"
Files: "configure;makefile"
Files: "*.html"
Files: "*.py"
Files: "*.ini"
Files: "*.nim"
@@ -89,6 +88,7 @@ Files: "examples/*.tmpl"
[Windows]
Files: "bin/nimrod.exe"
Files: "koch.exe"
Files: "dist/mingw"
BinPath: r"bin;dist\mingw\bin"
InnoSetup: "Yes"

View File

@@ -1,3 +1,3 @@
This directory contains the Nimrod version of Nimrod's source code. These files
are generated by the ``boot`` command of nimrod. DO NOT MODIFY THE FILES HERE!
Modify the Pascal version.
This directory contains the Nimrod version of Nimrod's source code. MODIFY THIS
VERSION, NOT THE PASCAL VERSION!

View File

@@ -1,25 +0,0 @@
#! /usr/bin/env python
"Replace LF with CRLF in argument files. Print names of changed files."
import sys, re, 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 = re.sub("\r?\n", "\r\n", data)
if newdata != data:
print filename
f = open(filename, "wb")
f.write(newdata)
f.close()
if __name__ == '__main__':
main()

View File

@@ -34,8 +34,8 @@ Additions
can be used to exclude the GC from the executable.
Changes affecting backwards compability
---------------------------------------
Changes affecting backwards compatibility
-----------------------------------------
- Taking the address of an object discriminant is now invalid.
- Passing a proc to a proc var is only allowed for procs marked with
``procvar`` or a calling convention != ``nimcall``. For now this only causes
@@ -100,8 +100,8 @@ Additions
- implemented ``strutils.join``
Changes affecting backwards compability
---------------------------------------
Changes affecting backwards compatibility
-----------------------------------------
- two phase symbol lookup is performed in generic routines
- ``bind`` is now a reserved word; ``exception`` is no reserved word anymore
@@ -168,8 +168,8 @@ Additions
* implemented ``abstract`` types
Changes affecting backwards compability
---------------------------------------
Changes affecting backwards compatibility
-----------------------------------------
- the organization within the ``lib`` folder now reflects the documentation;
as a result old configuration files need to be updated
@@ -305,8 +305,8 @@ Additions
- new wrappers: ``mysql``, ``sqlite3``, ``libcurl``
Changes affecting backwards compability
---------------------------------------
Changes affecting backwards compatibility
-----------------------------------------
- ``strutils.findSubStr``, ``strutils.findChars`` deprecated:
use ``strutils.find`` instead
@@ -360,8 +360,8 @@ Additions
const
z = fac(3) # computes 6 at compile time
Changes affecting backwards compability
---------------------------------------
Changes affecting backwards compatibility
-----------------------------------------
- renamed ``in_Operator`` to ``contains``: ``in`` is now a template that
translates to ``contains``

View File

@@ -1,68 +0,0 @@
""" Indentation utilities for Cog.
http://nedbatchelder.com/code/cog
Copyright 2004-2005, Ned Batchelder.
"""
# $Id: whiteutils.py 110 2005-08-27 22:35:20Z ned $
# modified to run with Python1.5.2 by Andreas Rumpf
import sys, re, types, os, os.path, re, shutil, time, getopt
import glob, zlib
from pycompab import *
def whitePrefix(strings):
""" Determine the whitespace prefix common to all non-blank lines
in the argument list.
"""
# Remove all blank lines from the list
strings = filter(lambda s: strip(s) != '', strings)
if not strings: return ''
# Find initial whitespace chunk in the first line.
# This is the best prefix we can hope for.
prefix = re.match(r'\s*', strings[0]).group(0)
# Loop over the other strings, keeping only as much of
# the prefix as matches each string.
for s in strings:
for i in range(len(prefix)):
if prefix[i] != s[i]:
prefix = prefix[:i]
break
return prefix
def reindentBlock(lines, newIndent=''):
""" Take a block of text as a string or list of lines.
Remove any common whitespace indentation.
Re-indent using newIndent, and return it as a single string.
"""
if type(lines) == type(""):
lines = split(lines, '\n')
oldIndent = whitePrefix(lines)
outLines = []
for l in lines:
if oldIndent:
l = replace(l, oldIndent, '', 1)
if l and newIndent:
l = newIndent + l
outLines.append(l)
return join(outLines, '\n')
def commonPrefix(strings):
""" Find the longest string that is a prefix of all the strings.
"""
if not strings:
return ''
prefix = strings[0]
for s in strings:
if len(s) < len(prefix):
prefix = prefix[:len(s)]
if not prefix:
return ''
for i in range(len(prefix)):
if prefix[i] != s[i]:
prefix = prefix[:i]
break
return prefix