Merge remote-tracking branch 'upstream/devel' into better-error-message
This commit is contained in:
commit
f233b2fe8b
19 changed files with 537 additions and 402 deletions
|
|
@ -90,6 +90,8 @@ proc enumToString*(enums: openArray[enum]): string =
|
||||||
- There is a new stdlib module `std/diff` to compute the famous "diff"
|
- There is a new stdlib module `std/diff` to compute the famous "diff"
|
||||||
of two texts by line.
|
of two texts by line.
|
||||||
|
|
||||||
|
- Added `os.relativePath`.
|
||||||
|
|
||||||
### Library changes
|
### Library changes
|
||||||
|
|
||||||
- The string output of `macros.lispRepr` proc has been tweaked
|
- The string output of `macros.lispRepr` proc has been tweaked
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,15 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
|
||||||
if self.suggestMode:
|
if self.suggestMode:
|
||||||
conf.command = "nimsuggest"
|
conf.command = "nimsuggest"
|
||||||
|
|
||||||
|
# These defines/options should not be enabled while processing nimscript
|
||||||
|
# bug #4446, #9420, #8991, #9589, #9153
|
||||||
|
undefSymbol(conf.symbols, "profiler")
|
||||||
|
undefSymbol(conf.symbols, "memProfiler")
|
||||||
|
undefSymbol(conf.symbols, "nodejs")
|
||||||
|
|
||||||
|
# bug #9120
|
||||||
|
conf.globalOptions.excl(optTaintMode)
|
||||||
|
|
||||||
proc runNimScriptIfExists(path: AbsoluteFile)=
|
proc runNimScriptIfExists(path: AbsoluteFile)=
|
||||||
if fileExists(path):
|
if fileExists(path):
|
||||||
runNimScript(cache, path, freshDefines = false, conf)
|
runNimScript(cache, path, freshDefines = false, conf)
|
||||||
|
|
@ -79,6 +88,9 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
|
||||||
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file
|
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
# Reload configuration from .cfg file
|
||||||
|
loadConfigs(DefaultConfig, cache, conf)
|
||||||
|
|
||||||
# now process command line arguments again, because some options in the
|
# now process command line arguments again, because some options in the
|
||||||
# command line can overwite the config file's settings
|
# command line can overwite the config file's settings
|
||||||
extccomp.initVars(conf)
|
extccomp.initVars(conf)
|
||||||
|
|
|
||||||
|
|
@ -780,7 +780,7 @@ proc linkViaResponseFile(conf: ConfigRef; cmd: string) =
|
||||||
let linkerArgs = conf.projectName & "_" & "linkerArgs.txt"
|
let linkerArgs = conf.projectName & "_" & "linkerArgs.txt"
|
||||||
let args = cmd.substr(i)
|
let args = cmd.substr(i)
|
||||||
# GCC's response files don't support backslashes. Junk.
|
# GCC's response files don't support backslashes. Junk.
|
||||||
if conf.cCompiler == ccGcc:
|
if conf.cCompiler == ccGcc or conf.cCompiler == ccCLang:
|
||||||
writeFile(linkerArgs, args.replace('\\', '/'))
|
writeFile(linkerArgs, args.replace('\\', '/'))
|
||||||
else:
|
else:
|
||||||
writeFile(linkerArgs, args)
|
writeFile(linkerArgs, args)
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,8 @@
|
||||||
|
|
||||||
## Path handling utilities for Nim. Strictly typed code in order
|
## Path handling utilities for Nim. Strictly typed code in order
|
||||||
## to avoid the never ending time sink in getting path handling right.
|
## to avoid the never ending time sink in getting path handling right.
|
||||||
## Might be a candidate for the stdlib later.
|
|
||||||
|
|
||||||
import os, strutils
|
import os, strutils, pathnorm
|
||||||
|
|
||||||
type
|
type
|
||||||
AbsoluteFile* = distinct string
|
AbsoluteFile* = distinct string
|
||||||
|
|
@ -45,130 +44,9 @@ proc cmpPaths*(x, y: AbsoluteDir): int {.borrow.}
|
||||||
|
|
||||||
proc createDir*(x: AbsoluteDir) {.borrow.}
|
proc createDir*(x: AbsoluteDir) {.borrow.}
|
||||||
|
|
||||||
type
|
|
||||||
PathIter = object
|
|
||||||
i, prev: int
|
|
||||||
notFirst: bool
|
|
||||||
|
|
||||||
proc hasNext(it: PathIter; x: string): bool =
|
|
||||||
it.i < x.len
|
|
||||||
|
|
||||||
proc next(it: var PathIter; x: string): (int, int) =
|
|
||||||
it.prev = it.i
|
|
||||||
if not it.notFirst and x[it.i] in {DirSep, AltSep}:
|
|
||||||
# absolute path:
|
|
||||||
inc it.i
|
|
||||||
else:
|
|
||||||
while it.i < x.len and x[it.i] notin {DirSep, AltSep}: inc it.i
|
|
||||||
if it.i > it.prev:
|
|
||||||
result = (it.prev, it.i-1)
|
|
||||||
elif hasNext(it, x):
|
|
||||||
result = next(it, x)
|
|
||||||
|
|
||||||
# skip all separators:
|
|
||||||
while it.i < x.len and x[it.i] in {DirSep, AltSep}: inc it.i
|
|
||||||
it.notFirst = true
|
|
||||||
|
|
||||||
iterator dirs(x: string): (int, int) =
|
|
||||||
var it: PathIter
|
|
||||||
while hasNext(it, x): yield next(it, x)
|
|
||||||
|
|
||||||
proc isDot(x: string; bounds: (int, int)): bool =
|
|
||||||
bounds[1] == bounds[0] and x[bounds[0]] == '.'
|
|
||||||
|
|
||||||
proc isDotDot(x: string; bounds: (int, int)): bool =
|
|
||||||
bounds[1] == bounds[0] + 1 and x[bounds[0]] == '.' and x[bounds[0]+1] == '.'
|
|
||||||
|
|
||||||
proc isSlash(x: string; bounds: (int, int)): bool =
|
|
||||||
bounds[1] == bounds[0] and x[bounds[0]] in {DirSep, AltSep}
|
|
||||||
|
|
||||||
const canonDirSep = when isMainModule: '/' else: DirSep
|
|
||||||
|
|
||||||
proc canon(x: string; result: var string; state: var int) =
|
|
||||||
# state: 0th bit set if isAbsolute path. Other bits count
|
|
||||||
# the number of path components.
|
|
||||||
for b in dirs(x):
|
|
||||||
if (state shr 1 == 0) and isSlash(x, b):
|
|
||||||
result.add canonDirSep
|
|
||||||
state = state or 1
|
|
||||||
elif result.len > (state and 1) and isDotDot(x, b):
|
|
||||||
var d = result.len
|
|
||||||
# f/..
|
|
||||||
while (d-1) > (state and 1) and result[d-1] notin {DirSep, AltSep}:
|
|
||||||
dec d
|
|
||||||
if d > 0: setLen(result, d-1)
|
|
||||||
elif isDot(x, b):
|
|
||||||
discard "discard the dot"
|
|
||||||
elif b[1] >= b[0]:
|
|
||||||
if result.len > 0 and result[^1] notin {DirSep, AltSep}:
|
|
||||||
result.add canonDirSep
|
|
||||||
result.add substr(x, b[0], b[1])
|
|
||||||
inc state, 2
|
|
||||||
|
|
||||||
proc canon(x: string): string =
|
|
||||||
# - Turn multiple slashes into single slashes.
|
|
||||||
# - Resolve '/foo/../bar' to '/bar'.
|
|
||||||
# - Remove './' from the path.
|
|
||||||
result = newStringOfCap(x.len)
|
|
||||||
var state = 0
|
|
||||||
canon(x, result, state)
|
|
||||||
|
|
||||||
when FileSystemCaseSensitive:
|
|
||||||
template `!=?`(a, b: char): bool = toLowerAscii(a) != toLowerAscii(b)
|
|
||||||
else:
|
|
||||||
template `!=?`(a, b: char): bool = a != b
|
|
||||||
|
|
||||||
proc relativeTo(full, base: string; sep = canonDirSep): string =
|
|
||||||
if full.len == 0: return ""
|
|
||||||
var f, b: PathIter
|
|
||||||
var ff = (0, -1)
|
|
||||||
var bb = (0, -1) # (int, int)
|
|
||||||
result = newStringOfCap(full.len)
|
|
||||||
# skip the common prefix:
|
|
||||||
while f.hasNext(full) and b.hasNext(base):
|
|
||||||
ff = next(f, full)
|
|
||||||
bb = next(b, base)
|
|
||||||
let diff = ff[1] - ff[0]
|
|
||||||
if diff != bb[1] - bb[0]: break
|
|
||||||
var same = true
|
|
||||||
for i in 0..diff:
|
|
||||||
if full[i + ff[0]] !=? base[i + bb[0]]:
|
|
||||||
same = false
|
|
||||||
break
|
|
||||||
if not same: break
|
|
||||||
ff = (0, -1)
|
|
||||||
bb = (0, -1)
|
|
||||||
# for i in 0..diff:
|
|
||||||
# result.add base[i + bb[0]]
|
|
||||||
|
|
||||||
# /foo/bar/xxx/ -- base
|
|
||||||
# /foo/bar/baz -- full path
|
|
||||||
# ../baz
|
|
||||||
# every directory that is in 'base', needs to add '..'
|
|
||||||
while true:
|
|
||||||
if bb[1] >= bb[0]:
|
|
||||||
if result.len > 0 and result[^1] != sep:
|
|
||||||
result.add sep
|
|
||||||
result.add ".."
|
|
||||||
if not b.hasNext(base): break
|
|
||||||
bb = b.next(base)
|
|
||||||
|
|
||||||
# add the rest of 'full':
|
|
||||||
while true:
|
|
||||||
if ff[1] >= ff[0]:
|
|
||||||
if result.len > 0 and result[^1] != sep:
|
|
||||||
result.add sep
|
|
||||||
for i in 0..ff[1] - ff[0]:
|
|
||||||
result.add full[i + ff[0]]
|
|
||||||
if not f.hasNext(full): break
|
|
||||||
ff = f.next(full)
|
|
||||||
|
|
||||||
when true:
|
when true:
|
||||||
proc eqImpl(x, y: string): bool =
|
proc eqImpl(x, y: string): bool {.inline.} =
|
||||||
when FileSystemCaseSensitive:
|
result = cmpPaths(x, y) == 0
|
||||||
result = cmpIgnoreCase(canon x, canon y) == 0
|
|
||||||
else:
|
|
||||||
result = canon(x) == canon(y)
|
|
||||||
|
|
||||||
proc `==`*(x, y: AbsoluteFile): bool = eqImpl(x.string, y.string)
|
proc `==`*(x, y: AbsoluteFile): bool = eqImpl(x.string, y.string)
|
||||||
proc `==`*(x, y: AbsoluteDir): bool = eqImpl(x.string, y.string)
|
proc `==`*(x, y: AbsoluteDir): bool = eqImpl(x.string, y.string)
|
||||||
|
|
@ -180,20 +58,20 @@ when true:
|
||||||
assert(not isAbsolute(f.string))
|
assert(not isAbsolute(f.string))
|
||||||
result = AbsoluteFile newStringOfCap(base.string.len + f.string.len)
|
result = AbsoluteFile newStringOfCap(base.string.len + f.string.len)
|
||||||
var state = 0
|
var state = 0
|
||||||
canon(base.string, result.string, state)
|
addNormalizePath(base.string, result.string, state)
|
||||||
canon(f.string, result.string, state)
|
addNormalizePath(f.string, result.string, state)
|
||||||
|
|
||||||
proc `/`*(base: AbsoluteDir; f: RelativeDir): AbsoluteDir =
|
proc `/`*(base: AbsoluteDir; f: RelativeDir): AbsoluteDir =
|
||||||
#assert isAbsolute(base.string)
|
#assert isAbsolute(base.string)
|
||||||
assert(not isAbsolute(f.string))
|
assert(not isAbsolute(f.string))
|
||||||
result = AbsoluteDir newStringOfCap(base.string.len + f.string.len)
|
result = AbsoluteDir newStringOfCap(base.string.len + f.string.len)
|
||||||
var state = 0
|
var state = 0
|
||||||
canon(base.string, result.string, state)
|
addNormalizePath(base.string, result.string, state)
|
||||||
canon(f.string, result.string, state)
|
addNormalizePath(f.string, result.string, state)
|
||||||
|
|
||||||
proc relativeTo*(fullPath: AbsoluteFile, baseFilename: AbsoluteDir;
|
proc relativeTo*(fullPath: AbsoluteFile, baseFilename: AbsoluteDir;
|
||||||
sep = canonDirSep): RelativeFile =
|
sep = DirSep): RelativeFile =
|
||||||
RelativeFile(relativeTo(fullPath.string, baseFilename.string, sep))
|
RelativeFile(relativePath(fullPath.string, baseFilename.string, sep))
|
||||||
|
|
||||||
proc toAbsolute*(file: string; base: AbsoluteDir): AbsoluteFile =
|
proc toAbsolute*(file: string; base: AbsoluteDir): AbsoluteFile =
|
||||||
if isAbsolute(file): result = AbsoluteFile(file)
|
if isAbsolute(file): result = AbsoluteFile(file)
|
||||||
|
|
@ -208,37 +86,8 @@ when true:
|
||||||
proc writeFile*(x: AbsoluteFile; content: string) {.borrow.}
|
proc writeFile*(x: AbsoluteFile; content: string) {.borrow.}
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
doAssert canon"/foo/../bar" == "/bar"
|
|
||||||
doAssert canon"foo/../bar" == "bar"
|
|
||||||
|
|
||||||
doAssert canon"/f/../bar///" == "/bar"
|
|
||||||
doAssert canon"f/..////bar" == "bar"
|
|
||||||
|
|
||||||
doAssert canon"../bar" == "../bar"
|
|
||||||
doAssert canon"/../bar" == "/../bar"
|
|
||||||
|
|
||||||
doAssert canon("foo/../../bar/") == "../bar"
|
|
||||||
doAssert canon("./bla/blob/") == "bla/blob"
|
|
||||||
doAssert canon(".hiddenFile") == ".hiddenFile"
|
|
||||||
doAssert canon("./bla/../../blob/./zoo.nim") == "../blob/zoo.nim"
|
|
||||||
|
|
||||||
doAssert canon("C:/file/to/this/long") == "C:/file/to/this/long"
|
|
||||||
doAssert canon("") == ""
|
|
||||||
doAssert canon("foobar") == "foobar"
|
|
||||||
doAssert canon("f/////////") == "f"
|
|
||||||
|
|
||||||
doAssert relativeTo("/foo/bar//baz.nim", "/foo") == "bar/baz.nim"
|
|
||||||
|
|
||||||
doAssert relativeTo("/Users/me/bar/z.nim", "/Users/other/bad") == "../../me/bar/z.nim"
|
|
||||||
|
|
||||||
doAssert relativeTo("/Users/me/bar/z.nim", "/Users/other") == "../me/bar/z.nim"
|
|
||||||
doAssert relativeTo("/Users///me/bar//z.nim", "//Users/") == "me/bar/z.nim"
|
|
||||||
doAssert relativeTo("/Users/me/bar/z.nim", "/Users/me") == "bar/z.nim"
|
|
||||||
doAssert relativeTo("", "/users/moo") == ""
|
|
||||||
doAssert relativeTo("foo", "") == "foo"
|
|
||||||
|
|
||||||
doAssert AbsoluteDir"/Users/me///" / RelativeFile"z.nim" == AbsoluteFile"/Users/me/z.nim"
|
doAssert AbsoluteDir"/Users/me///" / RelativeFile"z.nim" == AbsoluteFile"/Users/me/z.nim"
|
||||||
doAssert relativeTo("/foo/bar.nim", "/foo/") == "bar.nim"
|
doAssert relativePath("/foo/bar.nim", "/foo/", '/') == "bar.nim"
|
||||||
|
|
||||||
when isMainModule and defined(windows):
|
when isMainModule and defined(windows):
|
||||||
let nasty = string(AbsoluteDir(r"C:\Users\rumpf\projects\nim\tests\nimble\nimbleDir\linkedPkgs\pkgB-#head\../../simplePkgs/pkgB-#head/") / RelativeFile"pkgA/module.nim")
|
let nasty = string(AbsoluteDir(r"C:\Users\rumpf\projects\nim\tests\nimble\nimbleDir\linkedPkgs\pkgB-#head\../../simplePkgs/pkgB-#head/") / RelativeFile"pkgA/module.nim")
|
||||||
|
|
|
||||||
|
|
@ -807,11 +807,13 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||||
typ = commonType(typ, x.sons[1])
|
typ = commonType(typ, x.sons[1])
|
||||||
closeScope(c)
|
closeScope(c)
|
||||||
of nkElse:
|
of nkElse:
|
||||||
chckCovered = false
|
|
||||||
checkSonsLen(x, 1, c.config)
|
checkSonsLen(x, 1, c.config)
|
||||||
x.sons[0] = semExprBranchScope(c, x.sons[0])
|
x.sons[0] = semExprBranchScope(c, x.sons[0])
|
||||||
typ = commonType(typ, x.sons[0])
|
typ = commonType(typ, x.sons[0])
|
||||||
hasElse = true
|
hasElse = true
|
||||||
|
if chckCovered and covered == toCover(c, n.sons[0].typ):
|
||||||
|
localError(c.config, x.info, "invalid else, all cases are already covered")
|
||||||
|
chckCovered = false
|
||||||
else:
|
else:
|
||||||
illFormedAst(x, c.config)
|
illFormedAst(x, c.config)
|
||||||
if chckCovered:
|
if chckCovered:
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||||
if sonsLen(v) == 2:
|
if sonsLen(v) == 2:
|
||||||
strVal = v.sons[1] # second tuple part is the string value
|
strVal = v.sons[1] # second tuple part is the string value
|
||||||
if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}:
|
if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}:
|
||||||
if not isOrdinalType(v.sons[0].typ):
|
if not isOrdinalType(v.sons[0].typ, allowEnumWithHoles=true):
|
||||||
localError(c.config, v.sons[0].info, errOrdinalTypeExpected & "; given: " & typeToString(v.sons[0].typ, preferDesc))
|
localError(c.config, v.sons[0].info, errOrdinalTypeExpected & "; given: " & typeToString(v.sons[0].typ, preferDesc))
|
||||||
x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
|
x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
|
||||||
else:
|
else:
|
||||||
|
|
@ -101,7 +101,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||||
strVal = v
|
strVal = v
|
||||||
x = counter
|
x = counter
|
||||||
else:
|
else:
|
||||||
if not isOrdinalType(v.typ):
|
if not isOrdinalType(v.typ, allowEnumWithHoles=true):
|
||||||
localError(c.config, v.info, errOrdinalTypeExpected & "; given: " & typeToString(v.typ, preferDesc))
|
localError(c.config, v.info, errOrdinalTypeExpected & "; given: " & typeToString(v.typ, preferDesc))
|
||||||
x = getOrdValue(v)
|
x = getOrdValue(v)
|
||||||
if i != 1:
|
if i != 1:
|
||||||
|
|
|
||||||
|
|
@ -368,6 +368,11 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
|
||||||
else:
|
else:
|
||||||
# we need to introduce new local variables:
|
# we need to introduce new local variables:
|
||||||
add(result, introduceNewLocalVars(c, c.transCon.forLoopBody.PNode))
|
add(result, introduceNewLocalVars(c, c.transCon.forLoopBody.PNode))
|
||||||
|
if result.len > 0:
|
||||||
|
var changeNode = PNode(result[0])
|
||||||
|
changeNode.info = c.transCon.forStmt.info
|
||||||
|
for i, child in changeNode:
|
||||||
|
child.info = changeNode.info
|
||||||
|
|
||||||
proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
|
proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
|
||||||
result = transformSons(c, n)
|
result = transformSons(c, n)
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,6 @@ when defined(Posix):
|
||||||
of AF_UNIX: result = posix.AF_UNIX
|
of AF_UNIX: result = posix.AF_UNIX
|
||||||
of AF_INET: result = posix.AF_INET
|
of AF_INET: result = posix.AF_INET
|
||||||
of AF_INET6: result = posix.AF_INET6
|
of AF_INET6: result = posix.AF_INET6
|
||||||
else: discard
|
|
||||||
|
|
||||||
proc toInt(typ: SockType): cint =
|
proc toInt(typ: SockType): cint =
|
||||||
case typ
|
case typ
|
||||||
|
|
@ -227,7 +226,6 @@ when defined(Posix):
|
||||||
of SOCK_DGRAM: result = posix.SOCK_DGRAM
|
of SOCK_DGRAM: result = posix.SOCK_DGRAM
|
||||||
of SOCK_SEQPACKET: result = posix.SOCK_SEQPACKET
|
of SOCK_SEQPACKET: result = posix.SOCK_SEQPACKET
|
||||||
of SOCK_RAW: result = posix.SOCK_RAW
|
of SOCK_RAW: result = posix.SOCK_RAW
|
||||||
else: discard
|
|
||||||
|
|
||||||
proc toInt(p: Protocol): cint =
|
proc toInt(p: Protocol): cint =
|
||||||
case p
|
case p
|
||||||
|
|
@ -237,7 +235,6 @@ when defined(Posix):
|
||||||
of IPPROTO_IPV6: result = posix.IPPROTO_IPV6
|
of IPPROTO_IPV6: result = posix.IPPROTO_IPV6
|
||||||
of IPPROTO_RAW: result = posix.IPPROTO_RAW
|
of IPPROTO_RAW: result = posix.IPPROTO_RAW
|
||||||
of IPPROTO_ICMP: result = posix.IPPROTO_ICMP
|
of IPPROTO_ICMP: result = posix.IPPROTO_ICMP
|
||||||
else: discard
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
proc toInt(domain: Domain): cint =
|
proc toInt(domain: Domain): cint =
|
||||||
|
|
@ -853,7 +850,6 @@ proc connect*(socket: Socket, address: string, port = Port(0),
|
||||||
of AF_UNIX: s.sin_family = posix.AF_UNIX
|
of AF_UNIX: s.sin_family = posix.AF_UNIX
|
||||||
of AF_INET: s.sin_family = posix.AF_INET
|
of AF_INET: s.sin_family = posix.AF_INET
|
||||||
of AF_INET6: s.sin_family = posix.AF_INET6
|
of AF_INET6: s.sin_family = posix.AF_INET6
|
||||||
else: nil
|
|
||||||
if connect(socket.fd, cast[ptr TSockAddr](addr(s)), sizeof(s).cint) < 0'i32:
|
if connect(socket.fd, cast[ptr TSockAddr](addr(s)), sizeof(s).cint) < 0'i32:
|
||||||
OSError()
|
OSError()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -622,6 +622,61 @@ proc bindAddr*(socket: AsyncSocket, port = Port(0), address = "") {.
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
freeAddrInfo(aiList)
|
freeAddrInfo(aiList)
|
||||||
|
|
||||||
|
when defined(posix):
|
||||||
|
|
||||||
|
proc connectUnix*(socket: AsyncSocket, path: string): Future[void] =
|
||||||
|
## Binds Unix socket to `path`.
|
||||||
|
## This only works on Unix-style systems: Mac OS X, BSD and Linux
|
||||||
|
when not defined(nimdoc):
|
||||||
|
let retFuture = newFuture[void]("connectUnix")
|
||||||
|
result = retFuture
|
||||||
|
|
||||||
|
proc cb(fd: AsyncFD): bool =
|
||||||
|
let ret = SocketHandle(fd).getSockOptInt(cint(SOL_SOCKET), cint(SO_ERROR))
|
||||||
|
if ret == 0:
|
||||||
|
retFuture.complete()
|
||||||
|
return true
|
||||||
|
elif ret == EINTR:
|
||||||
|
return false
|
||||||
|
else:
|
||||||
|
retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret))))
|
||||||
|
return true
|
||||||
|
|
||||||
|
var socketAddr = makeUnixAddr(path)
|
||||||
|
let ret = socket.fd.connect(cast[ptr SockAddr](addr socketAddr),
|
||||||
|
(sizeof(socketAddr.sun_family) + path.len).Socklen)
|
||||||
|
if ret == 0:
|
||||||
|
# Request to connect completed immediately.
|
||||||
|
retFuture.complete()
|
||||||
|
else:
|
||||||
|
let lastError = osLastError()
|
||||||
|
if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS:
|
||||||
|
addWrite(AsyncFD(socket.fd), cb)
|
||||||
|
else:
|
||||||
|
retFuture.fail(newException(OSError, osErrorMsg(lastError)))
|
||||||
|
|
||||||
|
proc bindUnix*(socket: AsyncSocket, path: string) {.
|
||||||
|
tags: [ReadIOEffect].} =
|
||||||
|
## Binds Unix socket to `path`.
|
||||||
|
## This only works on Unix-style systems: Mac OS X, BSD and Linux
|
||||||
|
when not defined(nimdoc):
|
||||||
|
var socketAddr = makeUnixAddr(path)
|
||||||
|
if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr),
|
||||||
|
(sizeof(socketAddr.sun_family) + path.len).Socklen) != 0'i32:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
|
elif defined(nimdoc):
|
||||||
|
|
||||||
|
proc connectUnix*(socket: AsyncSocket, path: string): Future[void] =
|
||||||
|
## Binds Unix socket to `path`.
|
||||||
|
## This only works on Unix-style systems: Mac OS X, BSD and Linux
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc bindUnix*(socket: AsyncSocket, path: string) =
|
||||||
|
## Binds Unix socket to `path`.
|
||||||
|
## This only works on Unix-style systems: Mac OS X, BSD and Linux
|
||||||
|
discard
|
||||||
|
|
||||||
proc close*(socket: AsyncSocket) =
|
proc close*(socket: AsyncSocket) =
|
||||||
## Closes the socket.
|
## Closes the socket.
|
||||||
defer:
|
defer:
|
||||||
|
|
|
||||||
130
lib/pure/includes/osseps.nim
Normal file
130
lib/pure/includes/osseps.nim
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
# Include file that implements 'DirSep' and friends. Do not import this when
|
||||||
|
# you also import ``os.nim``!
|
||||||
|
|
||||||
|
const
|
||||||
|
doslikeFileSystem* = defined(windows) or defined(OS2) or defined(DOS)
|
||||||
|
|
||||||
|
when defined(Nimdoc): # only for proper documentation:
|
||||||
|
const
|
||||||
|
CurDir* = '.'
|
||||||
|
## The constant string used by the operating system to refer to the
|
||||||
|
## current directory.
|
||||||
|
##
|
||||||
|
## For example: '.' for POSIX or ':' for the classic Macintosh.
|
||||||
|
|
||||||
|
ParDir* = ".."
|
||||||
|
## The constant string used by the operating system to refer to the
|
||||||
|
## parent directory.
|
||||||
|
##
|
||||||
|
## For example: ".." for POSIX or "::" for the classic Macintosh.
|
||||||
|
|
||||||
|
DirSep* = '/'
|
||||||
|
## The character used by the operating system to separate pathname
|
||||||
|
## components, for example, '/' for POSIX or ':' for the classic
|
||||||
|
## Macintosh.
|
||||||
|
|
||||||
|
AltSep* = '/'
|
||||||
|
## An alternative character used by the operating system to separate
|
||||||
|
## pathname components, or the same as `DirSep` if only one separator
|
||||||
|
## character exists. This is set to '/' on Windows systems
|
||||||
|
## where `DirSep` is a backslash.
|
||||||
|
|
||||||
|
PathSep* = ':'
|
||||||
|
## The character conventionally used by the operating system to separate
|
||||||
|
## search patch components (as in PATH), such as ':' for POSIX
|
||||||
|
## or ';' for Windows.
|
||||||
|
|
||||||
|
FileSystemCaseSensitive* = true
|
||||||
|
## true if the file system is case sensitive, false otherwise. Used by
|
||||||
|
## `cmpPaths` to compare filenames properly.
|
||||||
|
|
||||||
|
ExeExt* = ""
|
||||||
|
## The file extension of native executables. For example:
|
||||||
|
## "" for POSIX, "exe" on Windows.
|
||||||
|
|
||||||
|
ScriptExt* = ""
|
||||||
|
## The file extension of a script file. For example: "" for POSIX,
|
||||||
|
## "bat" on Windows.
|
||||||
|
|
||||||
|
DynlibFormat* = "lib$1.so"
|
||||||
|
## The format string to turn a filename into a `DLL`:idx: file (also
|
||||||
|
## called `shared object`:idx: on some operating systems).
|
||||||
|
|
||||||
|
elif defined(macos):
|
||||||
|
const
|
||||||
|
CurDir* = ':'
|
||||||
|
ParDir* = "::"
|
||||||
|
DirSep* = ':'
|
||||||
|
AltSep* = Dirsep
|
||||||
|
PathSep* = ','
|
||||||
|
FileSystemCaseSensitive* = false
|
||||||
|
ExeExt* = ""
|
||||||
|
ScriptExt* = ""
|
||||||
|
DynlibFormat* = "$1.dylib"
|
||||||
|
|
||||||
|
# MacOS paths
|
||||||
|
# ===========
|
||||||
|
# MacOS directory separator is a colon ":" which is the only character not
|
||||||
|
# allowed in filenames.
|
||||||
|
#
|
||||||
|
# A path containing no colon or which begins with a colon is a partial
|
||||||
|
# path.
|
||||||
|
# E.g. ":kalle:petter" ":kalle" "kalle"
|
||||||
|
#
|
||||||
|
# All other paths are full (absolute) paths. E.g. "HD:kalle:" "HD:"
|
||||||
|
# When generating paths, one is safe if one ensures that all partial paths
|
||||||
|
# begin with a colon, and all full paths end with a colon.
|
||||||
|
# In full paths the first name (e g HD above) is the name of a mounted
|
||||||
|
# volume.
|
||||||
|
# These names are not unique, because, for instance, two diskettes with the
|
||||||
|
# same names could be inserted. This means that paths on MacOS are not
|
||||||
|
# waterproof. In case of equal names the first volume found will do.
|
||||||
|
# Two colons "::" are the relative path to the parent. Three is to the
|
||||||
|
# grandparent etc.
|
||||||
|
elif doslikeFileSystem:
|
||||||
|
const
|
||||||
|
CurDir* = '.'
|
||||||
|
ParDir* = ".."
|
||||||
|
DirSep* = '\\' # seperator within paths
|
||||||
|
AltSep* = '/'
|
||||||
|
PathSep* = ';' # seperator between paths
|
||||||
|
FileSystemCaseSensitive* = false
|
||||||
|
ExeExt* = "exe"
|
||||||
|
ScriptExt* = "bat"
|
||||||
|
DynlibFormat* = "$1.dll"
|
||||||
|
elif defined(PalmOS) or defined(MorphOS):
|
||||||
|
const
|
||||||
|
DirSep* = '/'
|
||||||
|
AltSep* = Dirsep
|
||||||
|
PathSep* = ';'
|
||||||
|
ParDir* = ".."
|
||||||
|
FileSystemCaseSensitive* = false
|
||||||
|
ExeExt* = ""
|
||||||
|
ScriptExt* = ""
|
||||||
|
DynlibFormat* = "$1.prc"
|
||||||
|
elif defined(RISCOS):
|
||||||
|
const
|
||||||
|
DirSep* = '.'
|
||||||
|
AltSep* = '.'
|
||||||
|
ParDir* = ".." # is this correct?
|
||||||
|
PathSep* = ','
|
||||||
|
FileSystemCaseSensitive* = true
|
||||||
|
ExeExt* = ""
|
||||||
|
ScriptExt* = ""
|
||||||
|
DynlibFormat* = "lib$1.so"
|
||||||
|
else: # UNIX-like operating system
|
||||||
|
const
|
||||||
|
CurDir* = '.'
|
||||||
|
ParDir* = ".."
|
||||||
|
DirSep* = '/'
|
||||||
|
AltSep* = DirSep
|
||||||
|
PathSep* = ':'
|
||||||
|
FileSystemCaseSensitive* = when defined(macosx): false else: true
|
||||||
|
ExeExt* = ""
|
||||||
|
ScriptExt* = ""
|
||||||
|
DynlibFormat* = when defined(macosx): "lib$1.dylib" else: "lib$1.so"
|
||||||
|
|
||||||
|
const
|
||||||
|
ExtSep* = '.'
|
||||||
|
## The character which separates the base filename from the extension;
|
||||||
|
## for example, the '.' in ``os.nim``.
|
||||||
|
|
@ -105,6 +105,7 @@ else:
|
||||||
osInvalidSocket* = posix.INVALID_SOCKET
|
osInvalidSocket* = posix.INVALID_SOCKET
|
||||||
nativeAfInet = posix.AF_INET
|
nativeAfInet = posix.AF_INET
|
||||||
nativeAfInet6 = posix.AF_INET6
|
nativeAfInet6 = posix.AF_INET6
|
||||||
|
nativeAfUnix = posix.AF_UNIX
|
||||||
|
|
||||||
proc `==`*(a, b: Port): bool {.borrow.}
|
proc `==`*(a, b: Port): bool {.borrow.}
|
||||||
## ``==`` for ports.
|
## ``==`` for ports.
|
||||||
|
|
@ -482,8 +483,18 @@ proc getAddrString*(sockAddr: ptr SockAddr): string =
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
setLen(result, len(cstring(result)))
|
setLen(result, len(cstring(result)))
|
||||||
else:
|
else:
|
||||||
|
when defined(posix) and not defined(nimdoc):
|
||||||
|
if sockAddr.sa_family.cint == nativeAfUnix:
|
||||||
|
return "unix"
|
||||||
raise newException(IOError, "Unknown socket family in getAddrString")
|
raise newException(IOError, "Unknown socket family in getAddrString")
|
||||||
|
|
||||||
|
when defined(posix) and not defined(nimdoc):
|
||||||
|
proc makeUnixAddr*(path: string): Sockaddr_un =
|
||||||
|
result.sun_family = AF_UNIX.uint16
|
||||||
|
if path.len >= Sockaddr_un_path_length:
|
||||||
|
raise newException(ValueError, "socket path too long")
|
||||||
|
copyMem(addr result.sun_path, path.cstring, path.len + 1)
|
||||||
|
|
||||||
proc getSockName*(socket: SocketHandle): Port =
|
proc getSockName*(socket: SocketHandle): Port =
|
||||||
## returns the socket's associated port number.
|
## returns the socket's associated port number.
|
||||||
var name: Sockaddr_in
|
var name: Sockaddr_in
|
||||||
|
|
|
||||||
|
|
@ -947,13 +947,6 @@ proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) {
|
||||||
var valuei = cint(if value: 1 else: 0)
|
var valuei = cint(if value: 1 else: 0)
|
||||||
setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei)
|
setSockOptInt(socket.fd, cint(level), toCInt(opt), valuei)
|
||||||
|
|
||||||
when defined(posix) and not defined(nimdoc):
|
|
||||||
proc makeUnixAddr(path: string): Sockaddr_un =
|
|
||||||
result.sun_family = AF_UNIX.uint16
|
|
||||||
if path.len >= Sockaddr_un_path_length:
|
|
||||||
raise newException(ValueError, "socket path too long")
|
|
||||||
copyMem(addr result.sun_path, path.cstring, path.len + 1)
|
|
||||||
|
|
||||||
when defined(posix) or defined(nimdoc):
|
when defined(posix) or defined(nimdoc):
|
||||||
proc connectUnix*(socket: Socket, path: string) =
|
proc connectUnix*(socket: Socket, path: string) =
|
||||||
## Connects to Unix socket on `path`.
|
## Connects to Unix socket on `path`.
|
||||||
|
|
|
||||||
249
lib/pure/os.nim
249
lib/pure/os.nim
|
|
@ -17,7 +17,7 @@
|
||||||
include "system/inclrtl"
|
include "system/inclrtl"
|
||||||
|
|
||||||
import
|
import
|
||||||
strutils
|
strutils, pathnorm
|
||||||
|
|
||||||
when defined(nimscript):
|
when defined(nimscript):
|
||||||
discard
|
discard
|
||||||
|
|
@ -51,133 +51,7 @@ type
|
||||||
|
|
||||||
OSErrorCode* = distinct int32 ## Specifies an OS Error Code.
|
OSErrorCode* = distinct int32 ## Specifies an OS Error Code.
|
||||||
|
|
||||||
const
|
include "includes/osseps"
|
||||||
doslikeFileSystem* = defined(windows) or defined(OS2) or defined(DOS)
|
|
||||||
|
|
||||||
when defined(Nimdoc): # only for proper documentation:
|
|
||||||
const
|
|
||||||
CurDir* = '.'
|
|
||||||
## The constant string used by the operating system to refer to the
|
|
||||||
## current directory.
|
|
||||||
##
|
|
||||||
## For example: '.' for POSIX or ':' for the classic Macintosh.
|
|
||||||
|
|
||||||
ParDir* = ".."
|
|
||||||
## The constant string used by the operating system to refer to the
|
|
||||||
## parent directory.
|
|
||||||
##
|
|
||||||
## For example: ".." for POSIX or "::" for the classic Macintosh.
|
|
||||||
|
|
||||||
DirSep* = '/'
|
|
||||||
## The character used by the operating system to separate pathname
|
|
||||||
## components, for example, '/' for POSIX or ':' for the classic
|
|
||||||
## Macintosh.
|
|
||||||
|
|
||||||
AltSep* = '/'
|
|
||||||
## An alternative character used by the operating system to separate
|
|
||||||
## pathname components, or the same as `DirSep` if only one separator
|
|
||||||
## character exists. This is set to '/' on Windows systems
|
|
||||||
## where `DirSep` is a backslash.
|
|
||||||
|
|
||||||
PathSep* = ':'
|
|
||||||
## The character conventionally used by the operating system to separate
|
|
||||||
## search patch components (as in PATH), such as ':' for POSIX
|
|
||||||
## or ';' for Windows.
|
|
||||||
|
|
||||||
FileSystemCaseSensitive* = true
|
|
||||||
## true if the file system is case sensitive, false otherwise. Used by
|
|
||||||
## `cmpPaths` to compare filenames properly.
|
|
||||||
|
|
||||||
ExeExt* = ""
|
|
||||||
## The file extension of native executables. For example:
|
|
||||||
## "" for POSIX, "exe" on Windows.
|
|
||||||
|
|
||||||
ScriptExt* = ""
|
|
||||||
## The file extension of a script file. For example: "" for POSIX,
|
|
||||||
## "bat" on Windows.
|
|
||||||
|
|
||||||
DynlibFormat* = "lib$1.so"
|
|
||||||
## The format string to turn a filename into a `DLL`:idx: file (also
|
|
||||||
## called `shared object`:idx: on some operating systems).
|
|
||||||
|
|
||||||
elif defined(macos):
|
|
||||||
const
|
|
||||||
CurDir* = ':'
|
|
||||||
ParDir* = "::"
|
|
||||||
DirSep* = ':'
|
|
||||||
AltSep* = Dirsep
|
|
||||||
PathSep* = ','
|
|
||||||
FileSystemCaseSensitive* = false
|
|
||||||
ExeExt* = ""
|
|
||||||
ScriptExt* = ""
|
|
||||||
DynlibFormat* = "$1.dylib"
|
|
||||||
|
|
||||||
# MacOS paths
|
|
||||||
# ===========
|
|
||||||
# MacOS directory separator is a colon ":" which is the only character not
|
|
||||||
# allowed in filenames.
|
|
||||||
#
|
|
||||||
# A path containing no colon or which begins with a colon is a partial
|
|
||||||
# path.
|
|
||||||
# E.g. ":kalle:petter" ":kalle" "kalle"
|
|
||||||
#
|
|
||||||
# All other paths are full (absolute) paths. E.g. "HD:kalle:" "HD:"
|
|
||||||
# When generating paths, one is safe if one ensures that all partial paths
|
|
||||||
# begin with a colon, and all full paths end with a colon.
|
|
||||||
# In full paths the first name (e g HD above) is the name of a mounted
|
|
||||||
# volume.
|
|
||||||
# These names are not unique, because, for instance, two diskettes with the
|
|
||||||
# same names could be inserted. This means that paths on MacOS are not
|
|
||||||
# waterproof. In case of equal names the first volume found will do.
|
|
||||||
# Two colons "::" are the relative path to the parent. Three is to the
|
|
||||||
# grandparent etc.
|
|
||||||
elif doslikeFileSystem:
|
|
||||||
const
|
|
||||||
CurDir* = '.'
|
|
||||||
ParDir* = ".."
|
|
||||||
DirSep* = '\\' # seperator within paths
|
|
||||||
AltSep* = '/'
|
|
||||||
PathSep* = ';' # seperator between paths
|
|
||||||
FileSystemCaseSensitive* = false
|
|
||||||
ExeExt* = "exe"
|
|
||||||
ScriptExt* = "bat"
|
|
||||||
DynlibFormat* = "$1.dll"
|
|
||||||
elif defined(PalmOS) or defined(MorphOS):
|
|
||||||
const
|
|
||||||
DirSep* = '/'
|
|
||||||
AltSep* = Dirsep
|
|
||||||
PathSep* = ';'
|
|
||||||
ParDir* = ".."
|
|
||||||
FileSystemCaseSensitive* = false
|
|
||||||
ExeExt* = ""
|
|
||||||
ScriptExt* = ""
|
|
||||||
DynlibFormat* = "$1.prc"
|
|
||||||
elif defined(RISCOS):
|
|
||||||
const
|
|
||||||
DirSep* = '.'
|
|
||||||
AltSep* = '.'
|
|
||||||
ParDir* = ".." # is this correct?
|
|
||||||
PathSep* = ','
|
|
||||||
FileSystemCaseSensitive* = true
|
|
||||||
ExeExt* = ""
|
|
||||||
ScriptExt* = ""
|
|
||||||
DynlibFormat* = "lib$1.so"
|
|
||||||
else: # UNIX-like operating system
|
|
||||||
const
|
|
||||||
CurDir* = '.'
|
|
||||||
ParDir* = ".."
|
|
||||||
DirSep* = '/'
|
|
||||||
AltSep* = DirSep
|
|
||||||
PathSep* = ':'
|
|
||||||
FileSystemCaseSensitive* = when defined(macosx): false else: true
|
|
||||||
ExeExt* = ""
|
|
||||||
ScriptExt* = ""
|
|
||||||
DynlibFormat* = when defined(macosx): "lib$1.dylib" else: "lib$1.so"
|
|
||||||
|
|
||||||
const
|
|
||||||
ExtSep* = '.'
|
|
||||||
## The character which separates the base filename from the extension;
|
|
||||||
## for example, the '.' in ``os.nim``.
|
|
||||||
|
|
||||||
proc normalizePathEnd(path: var string, trailingSep = false) =
|
proc normalizePathEnd(path: var string, trailingSep = false) =
|
||||||
## ensures ``path`` has exactly 0 or 1 trailing `DirSep`, depending on
|
## ensures ``path`` has exactly 0 or 1 trailing `DirSep`, depending on
|
||||||
|
|
@ -192,7 +66,7 @@ proc normalizePathEnd(path: var string, trailingSep = false) =
|
||||||
path.setLen(i)
|
path.setLen(i)
|
||||||
# foo => foo/
|
# foo => foo/
|
||||||
path.add DirSep
|
path.add DirSep
|
||||||
elif i>0:
|
elif i > 0:
|
||||||
# foo// => foo
|
# foo// => foo
|
||||||
path.setLen(i)
|
path.setLen(i)
|
||||||
else:
|
else:
|
||||||
|
|
@ -228,29 +102,40 @@ proc joinPath*(head, tail: string): string {.
|
||||||
## assert joinPath("", "lib") == "lib"
|
## assert joinPath("", "lib") == "lib"
|
||||||
## assert joinPath("", "/lib") == "/lib"
|
## assert joinPath("", "/lib") == "/lib"
|
||||||
## assert joinPath("usr/", "/lib") == "usr/lib"
|
## assert joinPath("usr/", "/lib") == "usr/lib"
|
||||||
if len(head) == 0:
|
result = newStringOfCap(head.len + tail.len)
|
||||||
result = tail
|
var state = 0
|
||||||
elif head[len(head)-1] in {DirSep, AltSep}:
|
addNormalizePath(head, result, state, DirSep)
|
||||||
if tail.len > 0 and tail[0] in {DirSep, AltSep}:
|
if tail.len == 0:
|
||||||
result = head & substr(tail, 1)
|
result.add DirSep
|
||||||
else:
|
|
||||||
result = head & tail
|
|
||||||
else:
|
else:
|
||||||
if tail.len > 0 and tail[0] in {DirSep, AltSep}:
|
addNormalizePath(tail, result, state, DirSep)
|
||||||
result = head & tail
|
when false:
|
||||||
|
if len(head) == 0:
|
||||||
|
result = tail
|
||||||
|
elif head[len(head)-1] in {DirSep, AltSep}:
|
||||||
|
if tail.len > 0 and tail[0] in {DirSep, AltSep}:
|
||||||
|
result = head & substr(tail, 1)
|
||||||
|
else:
|
||||||
|
result = head & tail
|
||||||
else:
|
else:
|
||||||
result = head & DirSep & tail
|
if tail.len > 0 and tail[0] in {DirSep, AltSep}:
|
||||||
|
result = head & tail
|
||||||
|
else:
|
||||||
|
result = head & DirSep & tail
|
||||||
|
|
||||||
proc joinPath*(parts: varargs[string]): string {.noSideEffect,
|
proc joinPath*(parts: varargs[string]): string {.noSideEffect,
|
||||||
rtl, extern: "nos$1OpenArray".} =
|
rtl, extern: "nos$1OpenArray".} =
|
||||||
## The same as `joinPath(head, tail)`, but works with any number of
|
## The same as `joinPath(head, tail)`, but works with any number of
|
||||||
## directory parts. You need to pass at least one element or the proc
|
## directory parts. You need to pass at least one element or the proc
|
||||||
## will assert in debug builds and crash on release builds.
|
## will assert in debug builds and crash on release builds.
|
||||||
result = parts[0]
|
var estimatedLen = 0
|
||||||
for i in 1..high(parts):
|
for p in parts: estimatedLen += p.len
|
||||||
result = joinPath(result, parts[i])
|
result = newStringOfCap(estimatedLen)
|
||||||
|
var state = 0
|
||||||
|
for i in 0..high(parts):
|
||||||
|
addNormalizePath(parts[i], result, state, DirSep)
|
||||||
|
|
||||||
proc `/` * (head, tail: string): string {.noSideEffect.} =
|
proc `/`*(head, tail: string): string {.noSideEffect.} =
|
||||||
## The same as ``joinPath(head, tail)``
|
## The same as ``joinPath(head, tail)``
|
||||||
##
|
##
|
||||||
## Here are some examples for Unix:
|
## Here are some examples for Unix:
|
||||||
|
|
@ -287,6 +172,71 @@ proc splitPath*(path: string): tuple[head, tail: string] {.
|
||||||
result.head = ""
|
result.head = ""
|
||||||
result.tail = path
|
result.tail = path
|
||||||
|
|
||||||
|
when FileSystemCaseSensitive:
|
||||||
|
template `!=?`(a, b: char): bool = toLowerAscii(a) != toLowerAscii(b)
|
||||||
|
else:
|
||||||
|
template `!=?`(a, b: char): bool = a != b
|
||||||
|
|
||||||
|
proc relativePath*(path, base: string; sep = DirSep): string {.
|
||||||
|
noSideEffect, rtl, extern: "nos$1", raises: [].} =
|
||||||
|
## Converts `path` to a path relative to `base`.
|
||||||
|
## The `sep` is used for the path normalizations, this can be useful to
|
||||||
|
## ensure the relative path only contains '/' so that it can be used for
|
||||||
|
## URL constructions.
|
||||||
|
runnableExamples:
|
||||||
|
doAssert relativePath("/Users/me/bar/z.nim", "/Users/other/bad", '/') == "../../me/bar/z.nim"
|
||||||
|
doAssert relativePath("/Users/me/bar/z.nim", "/Users/other", '/') == "../me/bar/z.nim"
|
||||||
|
doAssert relativePath("/Users///me/bar//z.nim", "//Users/", '/') == "me/bar/z.nim"
|
||||||
|
doAssert relativePath("/Users/me/bar/z.nim", "/Users/me", '/') == "bar/z.nim"
|
||||||
|
doAssert relativePath("", "/users/moo", '/') == ""
|
||||||
|
|
||||||
|
|
||||||
|
# Todo: If on Windows, path and base do not agree on the drive letter,
|
||||||
|
# return `path` as is.
|
||||||
|
if path.len == 0: return ""
|
||||||
|
var f, b: PathIter
|
||||||
|
var ff = (0, -1)
|
||||||
|
var bb = (0, -1) # (int, int)
|
||||||
|
result = newStringOfCap(path.len)
|
||||||
|
# skip the common prefix:
|
||||||
|
while f.hasNext(path) and b.hasNext(base):
|
||||||
|
ff = next(f, path)
|
||||||
|
bb = next(b, base)
|
||||||
|
let diff = ff[1] - ff[0]
|
||||||
|
if diff != bb[1] - bb[0]: break
|
||||||
|
var same = true
|
||||||
|
for i in 0..diff:
|
||||||
|
if path[i + ff[0]] !=? base[i + bb[0]]:
|
||||||
|
same = false
|
||||||
|
break
|
||||||
|
if not same: break
|
||||||
|
ff = (0, -1)
|
||||||
|
bb = (0, -1)
|
||||||
|
# for i in 0..diff:
|
||||||
|
# result.add base[i + bb[0]]
|
||||||
|
|
||||||
|
# /foo/bar/xxx/ -- base
|
||||||
|
# /foo/bar/baz -- path path
|
||||||
|
# ../baz
|
||||||
|
# every directory that is in 'base', needs to add '..'
|
||||||
|
while true:
|
||||||
|
if bb[1] >= bb[0]:
|
||||||
|
if result.len > 0 and result[^1] != sep:
|
||||||
|
result.add sep
|
||||||
|
result.add ".."
|
||||||
|
if not b.hasNext(base): break
|
||||||
|
bb = b.next(base)
|
||||||
|
|
||||||
|
# add the rest of 'path':
|
||||||
|
while true:
|
||||||
|
if ff[1] >= ff[0]:
|
||||||
|
if result.len > 0 and result[^1] != sep:
|
||||||
|
result.add sep
|
||||||
|
for i in 0..ff[1] - ff[0]:
|
||||||
|
result.add path[i + ff[0]]
|
||||||
|
if not f.hasNext(path): break
|
||||||
|
ff = f.next(path)
|
||||||
|
|
||||||
proc parentDirPos(path: string): int =
|
proc parentDirPos(path: string): int =
|
||||||
var q = 1
|
var q = 1
|
||||||
if len(path) >= 1 and path[len(path)-1] in {DirSep, AltSep}: q = 2
|
if len(path) >= 1 and path[len(path)-1] in {DirSep, AltSep}: q = 2
|
||||||
|
|
@ -478,14 +428,17 @@ proc cmpPaths*(pathA, pathB: string): int {.
|
||||||
doAssert cmpPaths("foo", "Foo") == 0
|
doAssert cmpPaths("foo", "Foo") == 0
|
||||||
elif defined(posix):
|
elif defined(posix):
|
||||||
doAssert cmpPaths("foo", "Foo") > 0
|
doAssert cmpPaths("foo", "Foo") > 0
|
||||||
|
|
||||||
|
let a = normalizePath(pathA)
|
||||||
|
let b = normalizePath(pathB)
|
||||||
if FileSystemCaseSensitive:
|
if FileSystemCaseSensitive:
|
||||||
result = cmp(pathA, pathB)
|
result = cmp(a, b)
|
||||||
else:
|
else:
|
||||||
when defined(nimscript):
|
when defined(nimscript):
|
||||||
result = cmpic(pathA, pathB)
|
result = cmpic(a, b)
|
||||||
elif defined(nimdoc): discard
|
elif defined(nimdoc): discard
|
||||||
else:
|
else:
|
||||||
result = cmpIgnoreCase(pathA, pathB)
|
result = cmpIgnoreCase(a, b)
|
||||||
|
|
||||||
proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} =
|
proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} =
|
||||||
## Checks whether a given `path` is absolute.
|
## Checks whether a given `path` is absolute.
|
||||||
|
|
@ -523,12 +476,10 @@ proc unixToNativePath*(path: string, drive=""): string {.
|
||||||
## which drive label to use during absolute path conversion.
|
## which drive label to use during absolute path conversion.
|
||||||
## `drive` defaults to the drive of the current working directory, and is
|
## `drive` defaults to the drive of the current working directory, and is
|
||||||
## ignored on systems that do not have a concept of "drives".
|
## ignored on systems that do not have a concept of "drives".
|
||||||
|
|
||||||
when defined(unix):
|
when defined(unix):
|
||||||
result = path
|
result = path
|
||||||
else:
|
else:
|
||||||
if path.len == 0:
|
if path.len == 0: return ""
|
||||||
return ""
|
|
||||||
|
|
||||||
var start: int
|
var start: int
|
||||||
if path[0] == '/':
|
if path[0] == '/':
|
||||||
|
|
|
||||||
95
lib/pure/pathnorm.nim
Normal file
95
lib/pure/pathnorm.nim
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Nim's Runtime Library
|
||||||
|
# (c) Copyright 2018 Andreas Rumpf
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
## OS-Path normalization. Used by ``os.nim`` but also
|
||||||
|
## generally useful for dealing with paths. Note that this module
|
||||||
|
## does not provide a stable API.
|
||||||
|
|
||||||
|
# Yes, this uses import here, not include so that
|
||||||
|
# we don't end up exporting these symbols from pathnorm and os:
|
||||||
|
import "includes/osseps"
|
||||||
|
|
||||||
|
type
|
||||||
|
PathIter* = object
|
||||||
|
i, prev: int
|
||||||
|
notFirst: bool
|
||||||
|
|
||||||
|
proc hasNext*(it: PathIter; x: string): bool =
|
||||||
|
it.i < x.len
|
||||||
|
|
||||||
|
proc next*(it: var PathIter; x: string): (int, int) =
|
||||||
|
it.prev = it.i
|
||||||
|
if not it.notFirst and x[it.i] in {DirSep, AltSep}:
|
||||||
|
# absolute path:
|
||||||
|
inc it.i
|
||||||
|
else:
|
||||||
|
while it.i < x.len and x[it.i] notin {DirSep, AltSep}: inc it.i
|
||||||
|
if it.i > it.prev:
|
||||||
|
result = (it.prev, it.i-1)
|
||||||
|
elif hasNext(it, x):
|
||||||
|
result = next(it, x)
|
||||||
|
|
||||||
|
# skip all separators:
|
||||||
|
while it.i < x.len and x[it.i] in {DirSep, AltSep}: inc it.i
|
||||||
|
it.notFirst = true
|
||||||
|
|
||||||
|
iterator dirs(x: string): (int, int) =
|
||||||
|
var it: PathIter
|
||||||
|
while hasNext(it, x): yield next(it, x)
|
||||||
|
|
||||||
|
proc isDot(x: string; bounds: (int, int)): bool =
|
||||||
|
bounds[1] == bounds[0] and x[bounds[0]] == '.'
|
||||||
|
|
||||||
|
proc isDotDot(x: string; bounds: (int, int)): bool =
|
||||||
|
bounds[1] == bounds[0] + 1 and x[bounds[0]] == '.' and x[bounds[0]+1] == '.'
|
||||||
|
|
||||||
|
proc isSlash(x: string; bounds: (int, int)): bool =
|
||||||
|
bounds[1] == bounds[0] and x[bounds[0]] in {DirSep, AltSep}
|
||||||
|
|
||||||
|
proc addNormalizePath*(x: string; result: var string; state: var int; dirSep = DirSep) =
|
||||||
|
## Low level proc. Undocumented.
|
||||||
|
|
||||||
|
# state: 0th bit set if isAbsolute path. Other bits count
|
||||||
|
# the number of path components.
|
||||||
|
var it: PathIter
|
||||||
|
it.notFirst = (state shr 1) > 0
|
||||||
|
if it.notFirst:
|
||||||
|
while it.i < x.len and x[it.i] in {DirSep, AltSep}: inc it.i
|
||||||
|
while hasNext(it, x):
|
||||||
|
let b = next(it, x)
|
||||||
|
if (state shr 1 == 0) and isSlash(x, b):
|
||||||
|
result.add dirSep
|
||||||
|
state = state or 1
|
||||||
|
elif result.len > (state and 1) and isDotDot(x, b):
|
||||||
|
var d = result.len
|
||||||
|
# f/..
|
||||||
|
while (d-1) > (state and 1) and result[d-1] notin {DirSep, AltSep}:
|
||||||
|
dec d
|
||||||
|
if d > 0: setLen(result, d-1)
|
||||||
|
elif isDot(x, b):
|
||||||
|
discard "discard the dot"
|
||||||
|
elif b[1] >= b[0]:
|
||||||
|
if result.len > 0 and result[^1] notin {DirSep, AltSep}:
|
||||||
|
result.add dirSep
|
||||||
|
result.add substr(x, b[0], b[1])
|
||||||
|
inc state, 2
|
||||||
|
|
||||||
|
proc normalizePath*(path: string; dirSep = DirSep): string =
|
||||||
|
## Example:
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## assert normalizePath("./foo//bar/../baz") == "foo/baz"
|
||||||
|
##
|
||||||
|
##
|
||||||
|
## - Turns multiple slashes into single slashes.
|
||||||
|
## - Resolves '/foo/../bar' to '/bar'.
|
||||||
|
## - Removes './' from the path.
|
||||||
|
result = newStringOfCap(path.len)
|
||||||
|
var state = 0
|
||||||
|
addNormalizePath(path, result, state, dirSep)
|
||||||
|
|
@ -239,7 +239,6 @@ method testEnded*(formatter: ConsoleOutputFormatter, testResult: TestResult) =
|
||||||
of OK: fgGreen
|
of OK: fgGreen
|
||||||
of FAILED: fgRed
|
of FAILED: fgRed
|
||||||
of SKIPPED: fgYellow
|
of SKIPPED: fgYellow
|
||||||
else: fgWhite
|
|
||||||
styledEcho styleBright, color, prefix, "[", $testResult.status, "] ", resetStyle, testResult.testName
|
styledEcho styleBright, color, prefix, "[", $testResult.status, "] ", resetStyle, testResult.testName
|
||||||
else:
|
else:
|
||||||
rawPrint()
|
rawPrint()
|
||||||
|
|
|
||||||
|
|
@ -292,8 +292,7 @@ proc generatedFile(test: TTest, target: TTarget): string =
|
||||||
let (_, name, _) = test.name.splitFile
|
let (_, name, _) = test.name.splitFile
|
||||||
let ext = targetToExt[target]
|
let ext = targetToExt[target]
|
||||||
result = nimcacheDir(test.name, test.options, target) /
|
result = nimcacheDir(test.name, test.options, target) /
|
||||||
(if target == targetJS: "" else: "compiler_") &
|
((if target == targetJS: "" else: "compiler_") & name.changeFileExt(ext))
|
||||||
name.changeFileExt(ext)
|
|
||||||
|
|
||||||
proc needsCodegenCheck(spec: TSpec): bool =
|
proc needsCodegenCheck(spec: TSpec): bool =
|
||||||
result = spec.maxCodeSize > 0 or spec.ccodeCheck.len > 0
|
result = spec.maxCodeSize > 0 or spec.ccodeCheck.len > 0
|
||||||
|
|
|
||||||
|
|
@ -1,63 +1,99 @@
|
||||||
discard """
|
discard """
|
||||||
output: ""
|
output: ""
|
||||||
"""
|
"""
|
||||||
# test the ospaths module
|
# test the ospaths module
|
||||||
|
|
||||||
import os
|
import os, pathnorm
|
||||||
|
|
||||||
doAssert unixToNativePath("") == ""
|
doAssert unixToNativePath("") == ""
|
||||||
doAssert unixToNativePath(".") == $CurDir
|
doAssert unixToNativePath(".") == $CurDir
|
||||||
doAssert unixToNativePath("..") == $ParDir
|
doAssert unixToNativePath("..") == $ParDir
|
||||||
doAssert isAbsolute(unixToNativePath("/"))
|
doAssert isAbsolute(unixToNativePath("/"))
|
||||||
doAssert isAbsolute(unixToNativePath("/", "a"))
|
doAssert isAbsolute(unixToNativePath("/", "a"))
|
||||||
doAssert isAbsolute(unixToNativePath("/a"))
|
doAssert isAbsolute(unixToNativePath("/a"))
|
||||||
doAssert isAbsolute(unixToNativePath("/a", "a"))
|
doAssert isAbsolute(unixToNativePath("/a", "a"))
|
||||||
doAssert isAbsolute(unixToNativePath("/a/b"))
|
doAssert isAbsolute(unixToNativePath("/a/b"))
|
||||||
doAssert isAbsolute(unixToNativePath("/a/b", "a"))
|
doAssert isAbsolute(unixToNativePath("/a/b", "a"))
|
||||||
doAssert unixToNativePath("a/b") == joinPath("a", "b")
|
doAssert unixToNativePath("a/b") == joinPath("a", "b")
|
||||||
|
|
||||||
when defined(macos):
|
when defined(macos):
|
||||||
doAssert unixToNativePath("./") == ":"
|
doAssert unixToNativePath("./") == ":"
|
||||||
doAssert unixToNativePath("./abc") == ":abc"
|
doAssert unixToNativePath("./abc") == ":abc"
|
||||||
doAssert unixToNativePath("../abc") == "::abc"
|
doAssert unixToNativePath("../abc") == "::abc"
|
||||||
doAssert unixToNativePath("../../abc") == ":::abc"
|
doAssert unixToNativePath("../../abc") == ":::abc"
|
||||||
doAssert unixToNativePath("/abc", "a") == "abc"
|
doAssert unixToNativePath("/abc", "a") == "abc"
|
||||||
doAssert unixToNativePath("/abc/def", "a") == "abc:def"
|
doAssert unixToNativePath("/abc/def", "a") == "abc:def"
|
||||||
elif doslikeFileSystem:
|
elif doslikeFileSystem:
|
||||||
doAssert unixToNativePath("./") == ".\\"
|
doAssert unixToNativePath("./") == ".\\"
|
||||||
doAssert unixToNativePath("./abc") == ".\\abc"
|
doAssert unixToNativePath("./abc") == ".\\abc"
|
||||||
doAssert unixToNativePath("../abc") == "..\\abc"
|
doAssert unixToNativePath("../abc") == "..\\abc"
|
||||||
doAssert unixToNativePath("../../abc") == "..\\..\\abc"
|
doAssert unixToNativePath("../../abc") == "..\\..\\abc"
|
||||||
doAssert unixToNativePath("/abc", "a") == "a:\\abc"
|
doAssert unixToNativePath("/abc", "a") == "a:\\abc"
|
||||||
doAssert unixToNativePath("/abc/def", "a") == "a:\\abc\\def"
|
doAssert unixToNativePath("/abc/def", "a") == "a:\\abc\\def"
|
||||||
else:
|
else:
|
||||||
#Tests for unix
|
#Tests for unix
|
||||||
doAssert unixToNativePath("./") == "./"
|
doAssert unixToNativePath("./") == "./"
|
||||||
doAssert unixToNativePath("./abc") == "./abc"
|
doAssert unixToNativePath("./abc") == "./abc"
|
||||||
doAssert unixToNativePath("../abc") == "../abc"
|
doAssert unixToNativePath("../abc") == "../abc"
|
||||||
doAssert unixToNativePath("../../abc") == "../../abc"
|
doAssert unixToNativePath("../../abc") == "../../abc"
|
||||||
doAssert unixToNativePath("/abc", "a") == "/abc"
|
doAssert unixToNativePath("/abc", "a") == "/abc"
|
||||||
doAssert unixToNativePath("/abc/def", "a") == "/abc/def"
|
doAssert unixToNativePath("/abc/def", "a") == "/abc/def"
|
||||||
|
|
||||||
block extractFilenameTest:
|
block extractFilenameTest:
|
||||||
doAssert extractFilename("") == ""
|
doAssert extractFilename("") == ""
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
doAssert extractFilename("foo/bar") == "bar"
|
doAssert extractFilename("foo/bar") == "bar"
|
||||||
doAssert extractFilename("foo/bar.txt") == "bar.txt"
|
doAssert extractFilename("foo/bar.txt") == "bar.txt"
|
||||||
doAssert extractFilename("foo/") == ""
|
doAssert extractFilename("foo/") == ""
|
||||||
doAssert extractFilename("/") == ""
|
doAssert extractFilename("/") == ""
|
||||||
when doslikeFileSystem:
|
when doslikeFileSystem:
|
||||||
doAssert extractFilename(r"foo\bar") == "bar"
|
doAssert extractFilename(r"foo\bar") == "bar"
|
||||||
doAssert extractFilename(r"foo\bar.txt") == "bar.txt"
|
doAssert extractFilename(r"foo\bar.txt") == "bar.txt"
|
||||||
doAssert extractFilename(r"foo\") == ""
|
doAssert extractFilename(r"foo\") == ""
|
||||||
doAssert extractFilename(r"C:\") == ""
|
doAssert extractFilename(r"C:\") == ""
|
||||||
|
|
||||||
block lastPathPartTest:
|
block lastPathPartTest:
|
||||||
doAssert lastPathPart("") == ""
|
doAssert lastPathPart("") == ""
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
doAssert lastPathPart("foo/bar.txt") == "bar.txt"
|
doAssert lastPathPart("foo/bar.txt") == "bar.txt"
|
||||||
doAssert lastPathPart("foo/") == "foo"
|
doAssert lastPathPart("foo/") == "foo"
|
||||||
doAssert lastPathPart("/") == ""
|
doAssert lastPathPart("/") == ""
|
||||||
when doslikeFileSystem:
|
when doslikeFileSystem:
|
||||||
doAssert lastPathPart(r"foo\bar.txt") == "bar.txt"
|
doAssert lastPathPart(r"foo\bar.txt") == "bar.txt"
|
||||||
doAssert lastPathPart(r"foo\") == "foo"
|
doAssert lastPathPart(r"foo\") == "foo"
|
||||||
|
|
||||||
|
template canon(x): untyped = normalizePath(x, '/')
|
||||||
|
doAssert canon"/foo/../bar" == "/bar"
|
||||||
|
doAssert canon"foo/../bar" == "bar"
|
||||||
|
|
||||||
|
doAssert canon"/f/../bar///" == "/bar"
|
||||||
|
doAssert canon"f/..////bar" == "bar"
|
||||||
|
|
||||||
|
doAssert canon"../bar" == "../bar"
|
||||||
|
doAssert canon"/../bar" == "/../bar"
|
||||||
|
|
||||||
|
doAssert canon("foo/../../bar/") == "../bar"
|
||||||
|
doAssert canon("./bla/blob/") == "bla/blob"
|
||||||
|
doAssert canon(".hiddenFile") == ".hiddenFile"
|
||||||
|
doAssert canon("./bla/../../blob/./zoo.nim") == "../blob/zoo.nim"
|
||||||
|
|
||||||
|
doAssert canon("C:/file/to/this/long") == "C:/file/to/this/long"
|
||||||
|
doAssert canon("") == ""
|
||||||
|
doAssert canon("foobar") == "foobar"
|
||||||
|
doAssert canon("f/////////") == "f"
|
||||||
|
|
||||||
|
doAssert relativePath("/foo/bar//baz.nim", "/foo", '/') == "bar/baz.nim"
|
||||||
|
doAssert normalizePath("./foo//bar/../baz", '/') == "foo/baz"
|
||||||
|
|
||||||
|
doAssert relativePath("/Users/me/bar/z.nim", "/Users/other/bad", '/') == "../../me/bar/z.nim"
|
||||||
|
|
||||||
|
doAssert relativePath("/Users/me/bar/z.nim", "/Users/other", '/') == "../me/bar/z.nim"
|
||||||
|
doAssert relativePath("/Users///me/bar//z.nim", "//Users/", '/') == "me/bar/z.nim"
|
||||||
|
doAssert relativePath("/Users/me/bar/z.nim", "/Users/me", '/') == "bar/z.nim"
|
||||||
|
doAssert relativePath("", "/users/moo", '/') == ""
|
||||||
|
doAssert relativePath("foo", "", '/') == "foo"
|
||||||
|
|
||||||
|
doAssert joinPath("usr", "") == unixToNativePath"usr/"
|
||||||
|
doAssert joinPath("", "lib") == "lib"
|
||||||
|
doAssert joinPath("", "/lib") == unixToNativePath"/lib"
|
||||||
|
doAssert joinPath("usr/", "/lib") == unixToNativePath"usr/lib"
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@ import strutils, strtabs, os, osproc, vcvarsall, vccenv
|
||||||
|
|
||||||
type
|
type
|
||||||
VccVersion* = enum ## VCC compiler backend versions
|
VccVersion* = enum ## VCC compiler backend versions
|
||||||
vccUndefined = (0, ""), ## VCC version undefined, resolves to the latest recognizable VCC version
|
vccUndefined = 0, ## VCC version undefined, resolves to the latest recognizable VCC version
|
||||||
vcc90 = vs90, ## Visual Studio 2008 (Version 9.0)
|
vcc90 = vs90 ## Visual Studio 2008 (Version 9.0)
|
||||||
vcc100 = vs100, ## Visual Studio 2010 (Version 10.0)
|
vcc100 = vs100 ## Visual Studio 2010 (Version 10.0)
|
||||||
vcc110 = vs110, ## Visual Studio 2012 (Version 11.0)
|
vcc110 = vs110 ## Visual Studio 2012 (Version 11.0)
|
||||||
vcc120 = vs120, ## Visual Studio 2013 (Version 12.0)
|
vcc120 = vs120 ## Visual Studio 2013 (Version 12.0)
|
||||||
vcc140 = vs140 ## Visual Studio 2015 (Version 14.0)
|
vcc140 = vs140 ## Visual Studio 2015 (Version 14.0)
|
||||||
|
|
||||||
proc discoverVccVcVarsAllPath*(version: VccVersion = vccUndefined): string =
|
proc discoverVccVcVarsAllPath*(version: VccVersion = vccUndefined): string =
|
||||||
## Returns the path to the vcvarsall utility of the specified VCC compiler backend.
|
## Returns the path to the vcvarsall utility of the specified VCC compiler backend.
|
||||||
|
|
@ -101,12 +101,12 @@ command was specified
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
var vccversionArg: seq[string] = @[]
|
var vccversionArg: seq[string] = @[]
|
||||||
var printPathArg: bool = false
|
var printPathArg: bool = false
|
||||||
var vcvarsallArg: string = nil
|
var vcvarsallArg: string
|
||||||
var commandArg: string = nil
|
var commandArg: string
|
||||||
var noCommandArg: bool = false
|
var noCommandArg: bool = false
|
||||||
var platformArg: VccArch
|
var platformArg: VccArch
|
||||||
var sdkTypeArg: VccPlatformType
|
var sdkTypeArg: VccPlatformType
|
||||||
var sdkVersionArg: string = nil
|
var sdkVersionArg: string
|
||||||
var verboseArg: bool = false
|
var verboseArg: bool = false
|
||||||
|
|
||||||
var clArgs: seq[TaintedString] = @[]
|
var clArgs: seq[TaintedString] = @[]
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ type
|
||||||
vccplatUWP = "uwp", ## Universal Windows Platform (UWP) Application
|
vccplatUWP = "uwp", ## Universal Windows Platform (UWP) Application
|
||||||
vccplatOneCore = "onecore" # Undocumented platform type in the Windows SDK, probably XBox One SDK platform type.
|
vccplatOneCore = "onecore" # Undocumented platform type in the Windows SDK, probably XBox One SDK platform type.
|
||||||
|
|
||||||
proc vccVarsAll*(path: string, arch: VccArch = vccarchUnspecified, platform_type: VccPlatformType = vccplatEmpty, sdk_version: string = nil, verbose: bool = false): StringTableRef =
|
proc vccVarsAll*(path: string, arch: VccArch = vccarchUnspecified, platform_type: VccPlatformType = vccplatEmpty, sdk_version: string = "", verbose: bool = false): StringTableRef =
|
||||||
## Returns a string table containing the proper process environment to successfully execute VCC compile commands for the specified SDK version, CPU architecture and platform type.
|
## Returns a string table containing the proper process environment to successfully execute VCC compile commands for the specified SDK version, CPU architecture and platform type.
|
||||||
##
|
##
|
||||||
## path
|
## path
|
||||||
|
|
@ -50,7 +50,7 @@ proc vccVarsAll*(path: string, arch: VccArch = vccarchUnspecified, platform_type
|
||||||
|
|
||||||
var vccvarsallpath = path
|
var vccvarsallpath = path
|
||||||
# Assume that default executable is in current directory or in PATH
|
# Assume that default executable is in current directory or in PATH
|
||||||
if path == nil or path.len < 1:
|
if path == "":
|
||||||
vccvarsallpath = vcvarsallDefaultPath
|
vccvarsallpath = vcvarsallDefaultPath
|
||||||
|
|
||||||
var args: seq[string] = @[]
|
var args: seq[string] = @[]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue