path canonicalization for imported modules, relative paths written in rod files

This commit is contained in:
Zahary Karadjov 2011-12-11 09:41:04 +02:00
commit d171a8b36f
10 changed files with 73 additions and 58 deletions

View file

@ -11,7 +11,7 @@
import import
msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists, msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists,
intsets, idgen intsets, idgen, os
const const
ImportTablePos* = 0 # imported symbols are at level 0 ImportTablePos* = 0 # imported symbols are at level 0
@ -1030,3 +1030,18 @@ proc getStrOrChar*(a: PNode): string =
internalError(a.info, "getStrOrChar") internalError(a.info, "getStrOrChar")
result = "" result = ""
proc getModuleName*(n: PNode): string =
# This returns a short relative module name without the nim extension
# e.g. like "system", "importer" or "somepath/module"
# The proc won't perform any checks that the path is actually valid
case n.kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
result = UnixToNativePath(n.strVal)
of nkIdent:
result = n.ident.s
of nkSym:
result = n.sym.name.s
else:
internalError(n.info, "getModuleName")
result = ""

View file

@ -33,10 +33,10 @@ proc addDotDependency(c: PPassContext, n: PNode): PNode =
case n.kind case n.kind
of nkImportStmt: of nkImportStmt:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var imported = splitFile(getModuleFile(n.sons[i])).name var imported = getModuleName(n.sons[i])
addDependencyAux(g.module.name.s, imported) addDependencyAux(g.module.name.s, imported)
of nkFromStmt: of nkFromStmt:
var imported = splitFile(getModuleFile(n.sons[0])).name var imported = getModuleName(n.sons[0])
addDependencyAux(g.module.name.s, imported) addDependencyAux(g.module.name.s, imported)
of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr: of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr:
for i in countup(0, sonsLen(n) - 1): discard addDotDependency(c, n.sons[i]) for i in countup(0, sonsLen(n) - 1): discard addDotDependency(c, n.sons[i])

View file

@ -760,21 +760,12 @@ proc renderRstToOut(d: PDoc, n: PRstNode): PRope =
proc checkForFalse(n: PNode): bool = proc checkForFalse(n: PNode): bool =
result = n.kind == nkIdent and IdentEq(n.ident, "false") result = n.kind == nkIdent and IdentEq(n.ident, "false")
proc getModuleFile(n: PNode): string =
case n.kind
of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.strVal
of nkIdent: result = n.ident.s
of nkSym: result = n.sym.name.s
else:
internalError(n.info, "getModuleFile()")
result = ""
proc traceDeps(d: PDoc, n: PNode) = proc traceDeps(d: PDoc, n: PNode) =
const k = skModule const k = skModule
if d.section[k] != nil: app(d.section[k], ", ") if d.section[k] != nil: app(d.section[k], ", ")
dispA(d.section[k], dispA(d.section[k],
"<a class=\"reference external\" href=\"$1.html\">$1</a>", "<a class=\"reference external\" href=\"$1.html\">$1</a>",
"$1", [toRope(getModuleFile(n))]) "$1", [toRope(getModuleName(n))])
proc generateDoc(d: PDoc, n: PNode) = proc generateDoc(d: PDoc, n: PNode) =
case n.kind case n.kind

View file

@ -16,25 +16,13 @@ import
proc evalImport*(c: PContext, n: PNode): PNode proc evalImport*(c: PContext, n: PNode): PNode
proc evalFrom*(c: PContext, n: PNode): PNode proc evalFrom*(c: PContext, n: PNode): PNode
proc importAllSymbols*(c: PContext, fromMod: PSym) proc importAllSymbols*(c: PContext, fromMod: PSym)
proc getModuleFile*(n: PNode): string
# implementation
proc findModule(info: TLineInfo, modulename: string): string = proc checkModuleName*(n: PNode): string =
# returns path to module # This returns the full canonical path for a given module import
result = options.FindFile(AddFileExt(modulename, nimExt)) var modulename = n.getModuleName
if result == "": Fatal(info, errCannotOpenFile, modulename) result = findModule(modulename)
if result.len == 0:
proc getModuleFile(n: PNode): string = Fatal(n.info, errCannotOpenFile, modulename)
case n.kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
result = findModule(n.info, UnixToNativePath(n.strVal))
of nkIdent:
result = findModule(n.info, n.ident.s)
of nkSym:
result = findModule(n.info, n.sym.name.s)
else:
internalError(n.info, "getModuleFile()")
result = ""
proc rawImportSymbol(c: PContext, s: PSym) = proc rawImportSymbol(c: PContext, s: PSym) =
# This does not handle stubs, because otherwise loading on demand would be # This does not handle stubs, because otherwise loading on demand would be
@ -103,7 +91,7 @@ proc importAllSymbols(c: PContext, fromMod: PSym) =
proc evalImport(c: PContext, n: PNode): PNode = proc evalImport(c: PContext, n: PNode): PNode =
result = n result = n
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var f = getModuleFile(n.sons[i]) var f = checkModuleName(n.sons[i])
var m = gImportModule(f) var m = gImportModule(f)
if sfDeprecated in m.flags: if sfDeprecated in m.flags:
Message(n.sons[i].info, warnDeprecated, m.name.s) Message(n.sons[i].info, warnDeprecated, m.name.s)
@ -114,7 +102,7 @@ proc evalImport(c: PContext, n: PNode): PNode =
proc evalFrom(c: PContext, n: PNode): PNode = proc evalFrom(c: PContext, n: PNode): PNode =
result = n result = n
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2)
var f = getModuleFile(n.sons[0]) var f = checkModuleName(n.sons[0])
var m = gImportModule(f) var m = gImportModule(f)
n.sons[0] = newSymNode(m) n.sons[0] = newSymNode(m)
addDecl(c, m) # add symbol to symbol table of module addDecl(c, m) # add symbol to symbol table of module

View file

@ -69,7 +69,7 @@ proc importModule(filename: string): PSym =
proc CompileModule(filename: string, flags: TSymFlags): PSym = proc CompileModule(filename: string, flags: TSymFlags): PSym =
var rd: PRodReader = nil var rd: PRodReader = nil
var f = addFileExt(filename, nimExt) var f = addFileExt(filename, nimExt)
result = newModule(filename) result = newModule(f)
result.flags = result.flags + flags result.flags = result.flags + flags
if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}: if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}:
rd = handleSymbolFile(result, f) rd = handleSymbolFile(result, f)

View file

@ -409,26 +409,34 @@ proc newFileInfo(fullPath, projPath: string): TFileInfo =
result.projPath = projPath result.projPath = projPath
proc fileInfoIdx*(filename: string): int32 = proc fileInfoIdx*(filename: string): int32 =
var canonical = canonicalizePath(filename) var
canonical: string
pseudoPath = false
try:
canonical = canonicalizePath(filename)
except:
canonical = filename
# The compiler uses "filenames" such as `command line` or `stdin`
# This flag indicates that we are working with such a path here
pseudoPath = true
if filenameToIndexTbl.hasKey(canonical): if filenameToIndexTbl.hasKey(canonical):
result = filenameToIndexTbl[canonical] result = filenameToIndexTbl[canonical]
else: else:
result = fileInfos.len.int32 result = fileInfos.len.int32
fileInfos.add(newFileInfo(canonical, canonical.shortenDir)) fileInfos.add(newFileInfo(canonical, if pseudoPath: "" else: canonical.shortenDir))
filenameToIndexTbl[canonical] = result filenameToIndexTbl[canonical] = result
proc newLineInfo*(filename: string, line, col: int): TLineInfo =
result.fileIndex = filename.fileInfoIdx
result.line = int16(line)
result.col = int16(col)
proc newLineInfo*(fileInfoIdx: int32, line, col: int): TLineInfo = proc newLineInfo*(fileInfoIdx: int32, line, col: int): TLineInfo =
result.fileIndex = fileInfoIdx result.fileIndex = fileInfoIdx
result.line = int16(line) result.line = int16(line)
result.col = int16(col) result.col = int16(col)
fileInfos.add(newFileInfo("command line", "")) proc newLineInfo*(filename: string, line, col: int): TLineInfo {.inline.} =
result = newLineInfo(filename.fileInfoIdx, line, col)
fileInfos.add(newFileInfo("", "command line"))
var gCmdLineInfo* = newLineInfo(int32(0), 1, 1) var gCmdLineInfo* = newLineInfo(int32(0), 1, 1)
proc raiseRecoverableError*() {.noinline, noreturn.} = proc raiseRecoverableError*() {.noinline, noreturn.} =

View file

@ -189,18 +189,27 @@ iterator iterSearchPath*(): string =
it = PStrEntry(it.Next) it = PStrEntry(it.Next)
proc rawFindFile(f: string): string = proc rawFindFile(f: string): string =
template ret(e: expr) =
result = e.canonicalizePath
return
if ExistsFile(f): if ExistsFile(f):
result = f ret f
else: else:
for it in iterSearchPath(): for it in iterSearchPath():
result = JoinPath(it, f) result = JoinPath(it, f)
if ExistsFile(result): return if ExistsFile(result):
ret result
result = "" result = ""
proc FindFile*(f: string): string = proc FindFile*(f: string): string =
result = rawFindFile(f) result = rawFindFile(f)
if len(result) == 0: result = rawFindFile(toLower(f)) if len(result) == 0: result = rawFindFile(toLower(f))
proc findModule*(modulename: string): string {.inline.} =
# returns path to module
result = FindFile(AddFileExt(modulename, nimExt))
proc binaryStrSearch*(x: openarray[string], y: string): int = proc binaryStrSearch*(x: openarray[string], y: string): int =
var a = 0 var a = 0
var b = len(x) - 1 var b = len(x) - 1

View file

@ -576,7 +576,9 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
L = 0 L = 0
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')': while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
setlen(r.files, L + 1) setlen(r.files, L + 1)
r.files[L] = decodeStr(r.s, r.pos) var relativePath = decodeStr(r.s, r.pos)
var resolvedPath = relativePath.findModule
r.files[L] = if resolvedPath.len > 0: resolvedPath else: relativePath
inc(r.pos) # skip #10 inc(r.pos) # skip #10
inc(r.line) inc(r.line)
inc(L) inc(L)
@ -628,7 +630,8 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
r.initIdx = r.pos + 2 # "(\10" r.initIdx = r.pos + 2 # "(\10"
skipSection(r) skipSection(r)
else: else:
MsgWriteln("skipping section: " & $r.pos) MsgWriteln("skipping section: " & section &
" at " & $r.pos & " in " & r.filename)
skipSection(r) skipSection(r)
if r.s[r.pos] == '\x0A': if r.s[r.pos] == '\x0A':
inc(r.pos) inc(r.pos)

View file

@ -95,9 +95,10 @@ const
rodNL = "\x0A" rodNL = "\x0A"
proc addInclDep(w: PRodWriter, dep: string) = proc addInclDep(w: PRodWriter, dep: string) =
var resolved = dep.findModule
encodeVInt(fileIdx(w, dep), w.inclDeps) encodeVInt(fileIdx(w, dep), w.inclDeps)
add(w.inclDeps, " ") add(w.inclDeps, " ")
encodeVInt(crcFromFile(dep), w.inclDeps) encodeVInt(crcFromFile(resolved), w.inclDeps)
add(w.inclDeps, rodNL) add(w.inclDeps, rodNL)
proc pushType(w: PRodWriter, t: PType) = proc pushType(w: PRodWriter, t: PType) =
@ -555,13 +556,13 @@ proc process(c: PPassContext, n: PNode): PNode =
# addInterfaceSym(w, a.sons[j].sym); # addInterfaceSym(w, a.sons[j].sym);
# end # end
of nkImportStmt: of nkImportStmt:
for i in countup(0, sonsLen(n) - 1): addModDep(w, getModuleFile(n.sons[i])) for i in countup(0, sonsLen(n) - 1): addModDep(w, getModuleName(n.sons[i]))
addStmt(w, n) addStmt(w, n)
of nkFromStmt: of nkFromStmt:
addModDep(w, getModuleFile(n.sons[0])) addModDep(w, getModuleName(n.sons[0]))
addStmt(w, n) addStmt(w, n)
of nkIncludeStmt: of nkIncludeStmt:
for i in countup(0, sonsLen(n) - 1): addInclDep(w, getModuleFile(n.sons[i])) for i in countup(0, sonsLen(n) - 1): addInclDep(w, getModuleName(n.sons[i]))
of nkPragma: of nkPragma:
addStmt(w, n) addStmt(w, n)
else: else:
@ -569,7 +570,7 @@ proc process(c: PPassContext, n: PNode): PNode =
proc myOpen(module: PSym, filename: string): PPassContext = proc myOpen(module: PSym, filename: string): PPassContext =
if module.id < 0: InternalError("rodwrite: module ID not set") if module.id < 0: InternalError("rodwrite: module ID not set")
var w = newRodWriter(filename, rodread.GetCRC(filename), module) var w = newRodWriter(filename, rodread.GetCRC(module.info.toFullPath), module)
rawAddInterfaceSym(w, module) rawAddInterfaceSym(w, module)
result = w result = w

View file

@ -797,7 +797,7 @@ proc evalInclude(c: PContext, n: PNode): PNode =
result = newNodeI(nkStmtList, n.info) result = newNodeI(nkStmtList, n.info)
addSon(result, n) addSon(result, n)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var f = getModuleFile(n.sons[i]) var f = checkModuleName(n.sons[i])
var fileIndex = f.fileInfoIdx var fileIndex = f.fileInfoIdx
if ContainsOrIncl(c.includedFiles, fileIndex): if ContainsOrIncl(c.includedFiles, fileIndex):
GlobalError(n.info, errRecursiveDependencyX, f) GlobalError(n.info, errRecursiveDependencyX, f)