mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-20 22:35:24 +00:00
crc check for external files to compile; bugfix: os.parseCmdLine
This commit is contained in:
@@ -926,28 +926,90 @@ proc createDir*(dir: string) =
|
||||
rawCreateDir(dir)
|
||||
|
||||
proc parseCmdLine*(c: string): seq[string] =
|
||||
## Splits a command line into several components; components are separated by
|
||||
## whitespace unless the whitespace occurs within ``"`` or ``'`` quotes.
|
||||
## Splits a command line into several components;
|
||||
## This proc is only occassionally useful, better use the `parseopt` module.
|
||||
##
|
||||
## On Windows, it uses the following parsing rules
|
||||
## (see http://msdn.microsoft.com/en-us/library/17w5ykft.aspx):
|
||||
##
|
||||
## * Arguments are delimited by white space, which is either a space or a tab.
|
||||
## * The caret character (^) is not recognized as an escape character or
|
||||
## delimiter. The character is handled completely by the command-line parser
|
||||
## in the operating system before being passed to the argv array in the
|
||||
## program.
|
||||
## * A string surrounded by double quotation marks ("string") is interpreted
|
||||
## as a single argument, regardless of white space contained within. A
|
||||
## quoted string can be embedded in an argument.
|
||||
## * A double quotation mark preceded by a backslash (\") is interpreted as a
|
||||
## literal double quotation mark character (").
|
||||
## * Backslashes are interpreted literally, unless they immediately precede
|
||||
## a double quotation mark.
|
||||
## * If an even number of backslashes is followed by a double quotation mark,
|
||||
## one backslash is placed in the argv array for every pair of backslashes,
|
||||
## and the double quotation mark is interpreted as a string delimiter.
|
||||
## * If an odd number of backslashes is followed by a double quotation mark,
|
||||
## one backslash is placed in the argv array for every pair of backslashes,
|
||||
## and the double quotation mark is "escaped" by the remaining backslash,
|
||||
## causing a literal double quotation mark (") to be placed in argv.
|
||||
##
|
||||
## On Posix systems, it uses the following parsing rules:
|
||||
## components are separated by
|
||||
## whitespace unless the whitespace occurs within ``"`` or ``'`` quotes.
|
||||
result = @[]
|
||||
var i = 0
|
||||
var a = ""
|
||||
while true:
|
||||
setLen(a, 0)
|
||||
while c[i] >= '\1' and c[i] <= ' ': inc(i) # skip whitespace
|
||||
case c[i]
|
||||
of '\'', '\"':
|
||||
var delim = c[i]
|
||||
inc(i) # skip ' or "
|
||||
while c[i] != '\0' and c[i] != delim:
|
||||
add a, c[i]
|
||||
inc(i)
|
||||
if c[i] != '\0': inc(i)
|
||||
of '\0': break
|
||||
while c[i] == ' ' or c[i] == '\t': inc(i)
|
||||
when defined(windows):
|
||||
# parse a single argument according to the above rules:
|
||||
var inQuote = false
|
||||
while true:
|
||||
case c[i]
|
||||
of '\0': break
|
||||
of '\\':
|
||||
var j = i
|
||||
while c[j] == '\\': inc(j)
|
||||
if c[j] == '"':
|
||||
for k in 0..(j-i) div 2: a.add('\\')
|
||||
if (j-i) mod 2 == 0:
|
||||
i = j
|
||||
else:
|
||||
a.add('"')
|
||||
i = j+1
|
||||
else:
|
||||
a.add(c[i])
|
||||
inc(i)
|
||||
of '"':
|
||||
inc(i)
|
||||
if not inQuote: inQuote = true
|
||||
elif c[i] == '"':
|
||||
a.add(c[i])
|
||||
inc(i)
|
||||
else:
|
||||
inQuote = false
|
||||
break
|
||||
of ' ', '\t':
|
||||
if not inQuote: break
|
||||
a.add(c[i])
|
||||
inc(i)
|
||||
else:
|
||||
a.add(c[i])
|
||||
inc(i)
|
||||
else:
|
||||
while c[i] > ' ':
|
||||
add(a, c[i])
|
||||
inc(i)
|
||||
case c[i]
|
||||
of '\'', '\"':
|
||||
var delim = c[i]
|
||||
inc(i) # skip ' or "
|
||||
while c[i] != '\0' and c[i] != delim:
|
||||
add a, c[i]
|
||||
inc(i)
|
||||
if c[i] != '\0': inc(i)
|
||||
of '\0': break
|
||||
else:
|
||||
while c[i] > ' ':
|
||||
add(a, c[i])
|
||||
inc(i)
|
||||
add(result, a)
|
||||
|
||||
type
|
||||
|
||||
@@ -233,9 +233,9 @@ type
|
||||
## that is too small to be represented as
|
||||
## a normal number
|
||||
EFloatInexact* {.compilerproc.} =
|
||||
object of EFloatingPoint ## Inexact. Operation produces a result that cannot
|
||||
## be represented with infinite precision --
|
||||
## for example, 2.0 / 3.0, log(1.1)
|
||||
object of EFloatingPoint ## Inexact. Operation produces a result
|
||||
## that cannot be represented with infinite
|
||||
## precision -- for example, 2.0 / 3.0, log(1.1)
|
||||
## NOTE: Nimrod currently does not detect these!
|
||||
|
||||
TResult* = enum Failure, Success
|
||||
@@ -962,7 +962,7 @@ proc `$` *(x: Cstring): string {.magic: "CStrToStr", noSideEffect.}
|
||||
proc `$` *(x: string): string {.magic: "StrToStr", noSideEffect.}
|
||||
## The stingify operator for a string argument. Returns `x`
|
||||
## as it is. This operator is useful for generic code, so
|
||||
## that ``$expr`` also works if ``expr`` is already a string.
|
||||
## that ``$expr`` also works if ``expr`` already is a string.
|
||||
|
||||
proc `$` *[T](x: ordinal[T]): string {.magic: "EnumToStr", noSideEffect.}
|
||||
## The stingify operator for an enumeration argument. This works for
|
||||
|
||||
@@ -216,11 +216,10 @@ proc processPath(path: string): string =
|
||||
result = UnixToNativePath(path % ["nimrod", getPrefixDir(), "lib", libpath])
|
||||
|
||||
proc processCompile(filename: string) =
|
||||
var found, trunc: string
|
||||
found = findFile(filename)
|
||||
var found = findFile(filename)
|
||||
if found == "": found = filename
|
||||
trunc = changeFileExt(found, "")
|
||||
extccomp.addExternalFileToCompile(trunc)
|
||||
var trunc = changeFileExt(found, "")
|
||||
extccomp.addExternalFileToCompile(found)
|
||||
extccomp.addFileToLink(completeCFilePath(trunc, false))
|
||||
|
||||
proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
|
||||
13
rod/crc.nim
13
rod/crc.nim
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -90,8 +90,7 @@ type
|
||||
PByteArray = ref TByteArray
|
||||
|
||||
proc crcFromBuf(buf: Pointer, length: int): TCrc32 =
|
||||
var p: PByteArray
|
||||
p = cast[PByteArray](buf)
|
||||
var p = cast[PByteArray](buf)
|
||||
result = InitCrc32
|
||||
for i in countup(0, length - 1): result = updateCrc32(p[i], result)
|
||||
|
||||
@@ -117,10 +116,12 @@ proc crcFromFile(filename: string): TCrc32 =
|
||||
|
||||
const
|
||||
base = int32(65521) # largest prime smaller than 65536
|
||||
#NMAX = 5552; original code with unsigned 32 bit integer
|
||||
# NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
|
||||
# NMAX = 5552; original code with unsigned 32 bit integer
|
||||
# NMAX is the largest n
|
||||
# such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
|
||||
nmax = 3854 # code with signed 32 bit integer
|
||||
# NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^31-1
|
||||
# NMAX is the largest n such that
|
||||
# 255n(n+1)/2 + (n+1)(BASE-1) <= 2^31-1
|
||||
# The penalty is the time loss in the extra MOD-calls.
|
||||
|
||||
proc updateAdler32(adler: int32, buf: pointer, length: int): int32 =
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# some things are read in from the configuration file
|
||||
|
||||
import
|
||||
lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs
|
||||
lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs, crc
|
||||
|
||||
type
|
||||
TSystemCC* = enum
|
||||
@@ -299,12 +299,30 @@ proc toObjFile(filenameWithoutExt: string): string =
|
||||
proc addFileToCompile(filename: string) =
|
||||
appendStr(toCompile, filename)
|
||||
|
||||
proc externalFileChanged(filename: string): bool =
|
||||
var crcFile = toGeneratedFile(filename, "crc")
|
||||
var currentCrc = int(crcFromFile(filename))
|
||||
var f: TFile
|
||||
if open(f, crcFile, fmRead):
|
||||
var line = f.readLine()
|
||||
if isNil(line) or line.len == 0: line = "0"
|
||||
close(f)
|
||||
var oldCrc = parseInt(line)
|
||||
result = oldCrc != currentCrc
|
||||
else:
|
||||
result = true
|
||||
if result:
|
||||
if open(f, crcFile, fmWrite):
|
||||
f.writeln($currentCrc)
|
||||
close(f)
|
||||
|
||||
proc addExternalFileToCompile(filename: string) =
|
||||
appendStr(externalToCompile, filename)
|
||||
if optForceFullMake in gGlobalOptions or externalFileChanged(filename):
|
||||
appendStr(externalToCompile, changeFileExt(filename, ""))
|
||||
|
||||
proc addFileToLink(filename: string) =
|
||||
prependStr(toLink, filename) # BUGFIX
|
||||
#appendStr(toLink, filename);
|
||||
prependStr(toLink, filename)
|
||||
# BUGFIX: was ``appendStr``
|
||||
|
||||
proc execExternalProgram(cmd: string) =
|
||||
if (optListCmd in gGlobalOptions) or (gVerbosity > 0): MessageOut(cmd)
|
||||
@@ -361,8 +379,8 @@ proc getCompileCFileCmd(cfilename: string, isExternal: bool = false): string =
|
||||
key = cc[c].name & ".exe"
|
||||
if existsConfigVar(key): exe = getConfigVar(key)
|
||||
if targetOS == osWindows: exe = addFileExt(exe, "exe")
|
||||
if (optGenDynLib in gGlobalOptions) and
|
||||
(ospNeedsPIC in platform.OS[targetOS].props):
|
||||
if optGenDynLib in gGlobalOptions and
|
||||
ospNeedsPIC in platform.OS[targetOS].props:
|
||||
add(options, ' ' & cc[c].pic)
|
||||
if targetOS == platform.hostOS:
|
||||
# compute include paths:
|
||||
@@ -383,11 +401,11 @@ proc getCompileCFileCmd(cfilename: string, isExternal: bool = false): string =
|
||||
objfile, "options", options, "include", includeCmd, "nimrod",
|
||||
getPrefixDir(), "lib", libpath]))
|
||||
add(result, ' ')
|
||||
add(result, `%`(cc[c].compileTmpl, ["file", cfile, "objfile", objfile,
|
||||
"options", options, "include", includeCmd,
|
||||
"nimrod",
|
||||
quoteIfContainsWhite(getPrefixDir()),
|
||||
"lib", quoteIfContainsWhite(libpath)]))
|
||||
addf(result, cc[c].compileTmpl, [
|
||||
"file", cfile, "objfile", objfile,
|
||||
"options", options, "include", includeCmd,
|
||||
"nimrod", quoteIfContainsWhite(getPrefixDir()),
|
||||
"lib", quoteIfContainsWhite(libpath)])
|
||||
|
||||
proc CompileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
|
||||
isExternal: bool) =
|
||||
@@ -396,7 +414,7 @@ proc CompileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
|
||||
inc(fileCounter) # call the C compiler for the .c file:
|
||||
var compileCmd = getCompileCFileCmd(it.data, isExternal)
|
||||
if not (optCompileOnly in gGlobalOptions):
|
||||
add(cmds, compileCmd) #execExternalProgram(compileCmd);
|
||||
add(cmds, compileCmd)
|
||||
if (optGenScript in gGlobalOptions):
|
||||
app(script, compileCmd)
|
||||
app(script, tnl)
|
||||
@@ -405,7 +423,7 @@ proc CompileCFile(list: TLinkedList, script: var PRope, cmds: var TStringSeq,
|
||||
proc CallCCompiler(projectfile: string) =
|
||||
var
|
||||
linkCmd, buildgui, builddll: string
|
||||
if (gGlobalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}):
|
||||
if gGlobalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}:
|
||||
return # speed up that call if only compiling and no script shall be
|
||||
# generated
|
||||
fileCounter = 0
|
||||
@@ -414,7 +432,7 @@ proc CallCCompiler(projectfile: string) =
|
||||
var cmds: TStringSeq = @[]
|
||||
CompileCFile(toCompile, script, cmds, false)
|
||||
CompileCFile(externalToCompile, script, cmds, true)
|
||||
if not (optCompileOnly in gGlobalOptions):
|
||||
if optCompileOnly notin gGlobalOptions:
|
||||
if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors()
|
||||
var res = 0
|
||||
if gNumberOfProcessors <= 1:
|
||||
@@ -426,7 +444,7 @@ proc CallCCompiler(projectfile: string) =
|
||||
res = execProcesses(cmds, {poUseShell, poParentStreams},
|
||||
gNumberOfProcessors)
|
||||
if res != 0: rawMessage(errExecutionOfProgramFailed, [])
|
||||
if not (optNoLinking in gGlobalOptions):
|
||||
if optNoLinking notin gGlobalOptions:
|
||||
# call the linker:
|
||||
var linkerExe = getConfigVar(cc[c].name & ".linkerexe")
|
||||
if len(linkerExe) == 0: linkerExe = cc[c].linkerExe
|
||||
@@ -448,22 +466,21 @@ proc CallCCompiler(projectfile: string) =
|
||||
var it = PStrEntry(toLink.head)
|
||||
var objfiles = ""
|
||||
while it != nil:
|
||||
add(objfiles, " ")
|
||||
add(objfiles, ' ')
|
||||
if targetOS == platform.hostOS:
|
||||
add(objfiles, quoteIfContainsWhite(toObjfile(it.data)))
|
||||
else:
|
||||
add(objfiles, quoteIfContainsWhite(toObjfile(extractFileName(it.data))))
|
||||
it = PStrEntry(it.next)
|
||||
linkCmd = quoteIfContainsWhite(`%`(linkCmd, ["builddll", builddll,
|
||||
linkCmd = quoteIfContainsWhite(linkCmd % ["builddll", builddll,
|
||||
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
|
||||
"exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath]))
|
||||
"exefile", exefile, "nimrod", getPrefixDir(), "lib", libpath])
|
||||
add(linkCmd, ' ')
|
||||
add(linkCmd, `%`(cc[c].linkTmpl, ["builddll", builddll, "buildgui",
|
||||
buildgui, "options", linkOptions,
|
||||
"objfiles", objfiles, "exefile", exefile,
|
||||
"nimrod",
|
||||
quoteIfContainsWhite(getPrefixDir()),
|
||||
"lib", quoteIfContainsWhite(libpath)]))
|
||||
addf(linkCmd, cc[c].linkTmpl, ["builddll", builddll,
|
||||
"buildgui", buildgui, "options", linkOptions,
|
||||
"objfiles", objfiles, "exefile", exefile,
|
||||
"nimrod", quoteIfContainsWhite(getPrefixDir()),
|
||||
"lib", quoteIfContainsWhite(libpath)])
|
||||
if not (optCompileOnly in gGlobalOptions): execExternalProgram(linkCmd)
|
||||
else:
|
||||
linkCmd = ""
|
||||
|
||||
@@ -299,7 +299,7 @@ proc processCompile(c: PContext, n: PNode) =
|
||||
var found = findFile(s)
|
||||
if found == "": found = s
|
||||
var trunc = ChangeFileExt(found, "")
|
||||
extccomp.addExternalFileToCompile(trunc)
|
||||
extccomp.addExternalFileToCompile(found)
|
||||
extccomp.addFileToLink(completeCFilePath(trunc, false))
|
||||
|
||||
proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
|
||||
|
||||
12
web/news.txt
12
web/news.txt
@@ -5,6 +5,12 @@ News
|
||||
2010-XX-XX Version 0.8.10 released
|
||||
==================================
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Bugfix: Command line parsing on Windows and ``os.parseCmdLine`` now adheres
|
||||
to the same parsing rules as Microsoft's C/C++ startup code.
|
||||
|
||||
|
||||
Changes affecting backwards compatibility
|
||||
-----------------------------------------
|
||||
@@ -13,6 +19,12 @@ Changes affecting backwards compatibility
|
||||
unless they are used in the same module.
|
||||
|
||||
|
||||
Additions
|
||||
---------
|
||||
|
||||
- The ``{.compile: "file.c".}`` pragma uses a CRC check to see if the file
|
||||
needs to be recompiled.
|
||||
|
||||
|
||||
2010-03-14 Version 0.8.8 released
|
||||
=================================
|
||||
|
||||
Reference in New Issue
Block a user