even more strict isNil handling for strings/seqs in order to detect bugs

This commit is contained in:
Araq 2018-08-22 12:35:46 +02:00
commit 64517445ea
36 changed files with 193 additions and 245 deletions

View file

@ -1020,13 +1020,16 @@ proc isCallExpr*(n: PNode): bool =
proc discardSons*(father: PNode) proc discardSons*(father: PNode)
proc len*(n: PNode): int {.inline.} = proc len*(n: PNode): int {.inline.} =
if isNil(n.sons): result = 0 when defined(nimNoNilSeqs):
else: result = len(n.sons) result = len(n.sons)
else:
if isNil(n.sons): result = 0
else: result = len(n.sons)
proc safeLen*(n: PNode): int {.inline.} = proc safeLen*(n: PNode): int {.inline.} =
## works even for leaves. ## works even for leaves.
if n.kind in {nkNone..nkNilLit} or isNil(n.sons): result = 0 if n.kind in {nkNone..nkNilLit}: result = 0
else: result = len(n.sons) else: result = len(n)
proc safeArrLen*(n: PNode): int {.inline.} = proc safeArrLen*(n: PNode): int {.inline.} =
## works for array-like objects (strings passed as openArray in VM). ## works for array-like objects (strings passed as openArray in VM).
@ -1036,7 +1039,8 @@ proc safeArrLen*(n: PNode): int {.inline.} =
proc add*(father, son: PNode) = proc add*(father, son: PNode) =
assert son != nil assert son != nil
if isNil(father.sons): father.sons = @[] when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
add(father.sons, son) add(father.sons, son)
type Indexable = PNode | PType type Indexable = PNode | PType
@ -1134,19 +1138,16 @@ const # for all kind of hash tables:
proc copyStrTable*(dest: var TStrTable, src: TStrTable) = proc copyStrTable*(dest: var TStrTable, src: TStrTable) =
dest.counter = src.counter dest.counter = src.counter
if isNil(src.data): return
setLen(dest.data, len(src.data)) setLen(dest.data, len(src.data))
for i in countup(0, high(src.data)): dest.data[i] = src.data[i] for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
proc copyIdTable*(dest: var TIdTable, src: TIdTable) = proc copyIdTable*(dest: var TIdTable, src: TIdTable) =
dest.counter = src.counter dest.counter = src.counter
if isNil(src.data): return
newSeq(dest.data, len(src.data)) newSeq(dest.data, len(src.data))
for i in countup(0, high(src.data)): dest.data[i] = src.data[i] for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
proc copyObjectSet*(dest: var TObjectSet, src: TObjectSet) = proc copyObjectSet*(dest: var TObjectSet, src: TObjectSet) =
dest.counter = src.counter dest.counter = src.counter
if isNil(src.data): return
setLen(dest.data, len(src.data)) setLen(dest.data, len(src.data))
for i in countup(0, high(src.data)): dest.data[i] = src.data[i] for i in countup(0, high(src.data)): dest.data[i] = src.data[i]
@ -1243,7 +1244,8 @@ proc newStrNode*(strVal: string; info: TLineInfo): PNode =
proc addSon*(father, son: PNode) = proc addSon*(father, son: PNode) =
assert son != nil assert son != nil
if isNil(father.sons): father.sons = @[] when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
add(father.sons, son) add(father.sons, son)
proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode, proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
@ -1287,16 +1289,22 @@ proc mergeLoc(a: var TLoc, b: TLoc) =
if a.r == nil: a.r = b.r if a.r == nil: a.r = b.r
proc newSons*(father: PNode, length: int) = proc newSons*(father: PNode, length: int) =
if isNil(father.sons): when defined(nimNoNilSeqs):
newSeq(father.sons, length)
else:
setLen(father.sons, length) setLen(father.sons, length)
else:
if isNil(father.sons):
newSeq(father.sons, length)
else:
setLen(father.sons, length)
proc newSons*(father: PType, length: int) = proc newSons*(father: PType, length: int) =
if isNil(father.sons): when defined(nimNoNilSeqs):
newSeq(father.sons, length)
else:
setLen(father.sons, length) setLen(father.sons, length)
else:
if isNil(father.sons):
newSeq(father.sons, length)
else:
setLen(father.sons, length)
proc sonsLen*(n: PType): int = n.sons.len proc sonsLen*(n: PType): int = n.sons.len
proc len*(n: PType): int = n.sons.len proc len*(n: PType): int = n.sons.len
@ -1464,20 +1472,26 @@ proc propagateToOwner*(owner, elem: PType) =
owner.flags.incl tfHasGCedMem owner.flags.incl tfHasGCedMem
proc rawAddSon*(father, son: PType) = proc rawAddSon*(father, son: PType) =
if isNil(father.sons): father.sons = @[] when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
add(father.sons, son) add(father.sons, son)
if not son.isNil: propagateToOwner(father, son) if not son.isNil: propagateToOwner(father, son)
proc rawAddSonNoPropagationOfTypeFlags*(father, son: PType) = proc rawAddSonNoPropagationOfTypeFlags*(father, son: PType) =
if isNil(father.sons): father.sons = @[] when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
add(father.sons, son) add(father.sons, son)
proc addSonNilAllowed*(father, son: PNode) = proc addSonNilAllowed*(father, son: PNode) =
if isNil(father.sons): father.sons = @[] when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
add(father.sons, son) add(father.sons, son)
proc delSon*(father: PNode, idx: int) = proc delSon*(father: PNode, idx: int) =
if isNil(father.sons): return when defined(nimNoNilSeqs):
if father.len == 0: return
else:
if isNil(father.sons): return
var length = sonsLen(father) var length = sonsLen(father)
for i in countup(idx, length - 2): father.sons[i] = father.sons[i + 1] for i in countup(idx, length - 2): father.sons[i] = father.sons[i + 1]
setLen(father.sons, length - 1) setLen(father.sons, length - 1)

View file

@ -206,7 +206,7 @@ proc makeYamlString*(s: string): Rope =
const MaxLineLength = 64 const MaxLineLength = 64
result = nil result = nil
var res = "\"" var res = "\""
for i in countup(0, if s.isNil: -1 else: (len(s)-1)): for i in 0 ..< s.len:
if (i + 1) mod MaxLineLength == 0: if (i + 1) mod MaxLineLength == 0:
add(res, '\"') add(res, '\"')
add(res, "\n") add(res, "\n")
@ -314,10 +314,7 @@ proc treeToYamlAux(conf: ConfigRef; n: PNode, marker: var IntSet, indent: int,
addf(result, ",$N$1\"floatVal\": $2", addf(result, ",$N$1\"floatVal\": $2",
[istr, rope(n.floatVal.toStrMaxPrecision)]) [istr, rope(n.floatVal.toStrMaxPrecision)])
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
if n.strVal.isNil: addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
addf(result, ",$N$1\"strVal\": null", [istr])
else:
addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
of nkSym: of nkSym:
addf(result, ",$N$1\"sym\": $2", addf(result, ",$N$1\"sym\": $2",
[istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth)]) [istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth)])
@ -395,10 +392,7 @@ proc debugTree(conf: ConfigRef; n: PNode, indent: int, maxRecDepth: int;
addf(result, ",$N$1\"floatVal\": $2", addf(result, ",$N$1\"floatVal\": $2",
[istr, rope(n.floatVal.toStrMaxPrecision)]) [istr, rope(n.floatVal.toStrMaxPrecision)])
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
if n.strVal.isNil: addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
addf(result, ",$N$1\"strVal\": null", [istr])
else:
addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
of nkSym: of nkSym:
addf(result, ",$N$1\"sym\": $2_$3", addf(result, ",$N$1\"sym\": $2_$3",
[istr, rope(n.sym.name.s), rope(n.sym.id)]) [istr, rope(n.sym.name.s), rope(n.sym.id)])
@ -759,10 +753,6 @@ proc idNodeTableGet(t: TIdNodeTable, key: PIdObj): PNode =
if index >= 0: result = t.data[index].val if index >= 0: result = t.data[index].val
else: result = nil else: result = nil
proc idNodeTableGetLazy*(t: TIdNodeTable, key: PIdObj): PNode =
if not isNil(t.data):
result = idNodeTableGet(t, key)
proc idNodeTableRawInsert(data: var TIdNodePairSeq, key: PIdObj, val: PNode) = proc idNodeTableRawInsert(data: var TIdNodePairSeq, key: PIdObj, val: PNode) =
var h: Hash var h: Hash
h = key.id and high(data) h = key.id and high(data)
@ -789,10 +779,6 @@ proc idNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) =
idNodeTableRawInsert(t.data, key, val) idNodeTableRawInsert(t.data, key, val)
inc(t.counter) inc(t.counter)
proc idNodeTablePutLazy*(t: var TIdNodeTable, key: PIdObj, val: PNode) =
if isNil(t.data): initIdNodeTable(t)
idNodeTablePut(t, key, val)
iterator pairs*(t: TIdNodeTable): tuple[key: PIdObj, val: PNode] = iterator pairs*(t: TIdNodeTable): tuple[key: PIdObj, val: PNode] =
for i in 0 .. high(t.data): for i in 0 .. high(t.data):
if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val) if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val)

View file

@ -71,8 +71,7 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
else: else:
result = genStringLiteral(p.module, n) result = genStringLiteral(p.module, n)
else: else:
if n.strVal.isNil: result = rope("NIM_NIL") result = makeCString(n.strVal)
else: result = makeCString(n.strVal)
of nkFloatLit, nkFloat64Lit: of nkFloatLit, nkFloat64Lit:
result = rope(n.floatVal.toStrMaxPrecision) result = rope(n.floatVal.toStrMaxPrecision)
of nkFloat32Lit: of nkFloat32Lit:
@ -2548,7 +2547,7 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
var t = skipTypes(n.typ, abstractInst) var t = skipTypes(n.typ, abstractInst)
if t.kind == tySequence: if t.kind == tySequence:
result = genConstSeq(p, n, n.typ) result = genConstSeq(p, n, n.typ)
elif t.kind == tyProc and t.callConv == ccClosure and not n.sons.isNil and elif t.kind == tyProc and t.callConv == ccClosure and n.len > 0 and
n.sons[0].kind == nkNilLit and n.sons[1].kind == nkNilLit: n.sons[0].kind == nkNilLit and n.sons[1].kind == nkNilLit:
# this hack fixes issue that nkNilLit is expanded to {NIM_NIL,NIM_NIL} # this hack fixes issue that nkNilLit is expanded to {NIM_NIL,NIM_NIL}
# this behaviour is needed since closure_var = nil must be # this behaviour is needed since closure_var = nil must be

View file

@ -271,9 +271,7 @@ proc escapeJSString(s: string): string =
result.add("\"") result.add("\"")
proc makeJSString(s: string, escapeNonAscii = true): Rope = proc makeJSString(s: string, escapeNonAscii = true): Rope =
if s.isNil: if escapeNonAscii:
result = "null".rope
elif escapeNonAscii:
result = strutils.escape(s).rope result = strutils.escape(s).rope
else: else:
result = escapeJSString(s).rope result = escapeJSString(s).rope
@ -1369,7 +1367,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
let length = int(lengthOrd(p.config, t)) let length = int(lengthOrd(p.config, t))
let e = elemType(t) let e = elemType(t)
let jsTyp = arrayTypeForElemType(e) let jsTyp = arrayTypeForElemType(e)
if not jsTyp.isNil: if jsTyp.len > 0:
result = "new $1($2)" % [rope(jsTyp), rope(length)] result = "new $1($2)" % [rope(jsTyp), rope(length)]
elif length > 32: elif length > 32:
useMagic(p, "arrayConstr") useMagic(p, "arrayConstr")

View file

@ -120,7 +120,8 @@ proc skipIntLit*(t: PType): PType {.inline.} =
result = t result = t
proc addSonSkipIntLit*(father, son: PType) = proc addSonSkipIntLit*(father, son: PType) =
if isNil(father.sons): father.sons = @[] when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
let s = son.skipIntLit let s = son.skipIntLit
add(father.sons, s) add(father.sons, s)
propagateToOwner(father, s) propagateToOwner(father, s)

View file

@ -176,7 +176,7 @@ proc getHash*(conf: ConfigRef; fileIdx: FileIndex): string =
proc toFullPathConsiderDirty*(conf: ConfigRef; fileIdx: FileIndex): string = proc toFullPathConsiderDirty*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0: if fileIdx.int32 < 0:
result = "???" result = "???"
elif not conf.m.fileInfos[fileIdx.int32].dirtyFile.isNil: elif conf.m.fileInfos[fileIdx.int32].dirtyFile.len > 0:
result = conf.m.fileInfos[fileIdx.int32].dirtyFile result = conf.m.fileInfos[fileIdx.int32].dirtyFile
else: else:
result = conf.m.fileInfos[fileIdx.int32].fullPath result = conf.m.fileInfos[fileIdx.int32].fullPath

View file

@ -33,7 +33,8 @@ proc getPackageName*(conf: ConfigRef; path: string): string =
result = file.splitFile.name result = file.splitFile.name
break packageSearch break packageSearch
# we also store if we didn't find anything: # we also store if we didn't find anything:
if result.isNil: result = "" when not defined(nimNoNilSeqs):
if result.isNil: result = ""
for d in myParentDirs(path): for d in myParentDirs(path):
#echo "set cache ", d, " |", result, "|", parents #echo "set cache ", d, " |", result, "|", parents
conf.packageCache[d] = result conf.packageCache[d] = result

View file

@ -175,7 +175,7 @@ proc put(g: var TSrcGen, kind: TTokType, s: string) =
g.pendingWhitespace = s.len g.pendingWhitespace = s.len
proc putComment(g: var TSrcGen, s: string) = proc putComment(g: var TSrcGen, s: string) =
if s.isNil: return if s.len == 0: return
var i = 0 var i = 0
let hi = len(s) - 1 let hi = len(s) - 1
var isCode = (len(s) >= 2) and (s[1] != ' ') var isCode = (len(s) >= 2) and (s[1] != ' ')
@ -216,7 +216,7 @@ proc putComment(g: var TSrcGen, s: string) =
optNL(g) optNL(g)
proc maxLineLength(s: string): int = proc maxLineLength(s: string): int =
if s.isNil: return 0 if s.len == 0: return 0
var i = 0 var i = 0
let hi = len(s) - 1 let hi = len(s) - 1
var lineLen = 0 var lineLen = 0

View file

@ -323,13 +323,13 @@ proc catches(tracked: PEffects, e: PType) =
dec L dec L
else: else:
inc i inc i
if not isNil(tracked.exc.sons): if tracked.exc.len > 0:
setLen(tracked.exc.sons, L) setLen(tracked.exc.sons, L)
else: else:
assert L == 0 assert L == 0
proc catchesAll(tracked: PEffects) = proc catchesAll(tracked: PEffects) =
if not isNil(tracked.exc.sons): if tracked.exc.len > 0:
setLen(tracked.exc.sons, tracked.bottom) setLen(tracked.exc.sons, tracked.bottom)
proc track(tracked: PEffects, n: PNode) proc track(tracked: PEffects, n: PNode)

View file

@ -1609,7 +1609,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
n.sons[pragmasPos] = proto.ast.sons[pragmasPos] n.sons[pragmasPos] = proto.ast.sons[pragmasPos]
if n.sons[namePos].kind != nkSym: internalError(c.config, n.info, "semProcAux") if n.sons[namePos].kind != nkSym: internalError(c.config, n.info, "semProcAux")
n.sons[namePos].sym = proto n.sons[namePos].sym = proto
if importantComments(c.config) and not isNil(proto.ast.comment): if importantComments(c.config) and proto.ast.comment.len > 0:
n.comment = proto.ast.comment n.comment = proto.ast.comment
proto.ast = n # needed for code generation proto.ast = n # needed for code generation
popOwner(c) popOwner(c)

View file

@ -47,7 +47,7 @@ template origModuleName(m: PSym): string = m.name.s
proc findDocComment(n: PNode): PNode = proc findDocComment(n: PNode): PNode =
if n == nil: return nil if n == nil: return nil
if not isNil(n.comment): return n if n.comment.len > 0: return n
if n.kind in {nkStmtList, nkStmtListExpr, nkObjectTy, nkRecList} and n.len > 0: if n.kind in {nkStmtList, nkStmtListExpr, nkObjectTy, nkRecList} and n.len > 0:
result = findDocComment(n.sons[0]) result = findDocComment(n.sons[0])
if result != nil: return if result != nil: return

View file

@ -29,8 +29,7 @@ proc hashTree(n: PNode): Hash =
if (n.floatVal >= - 1000000.0) and (n.floatVal <= 1000000.0): if (n.floatVal >= - 1000000.0) and (n.floatVal <= 1000000.0):
result = result !& toInt(n.floatVal) result = result !& toInt(n.floatVal)
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
if not n.strVal.isNil: result = result !& hash(n.strVal)
result = result !& hash(n.strVal)
else: else:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
result = result !& hashTree(n.sons[i]) result = result !& hashTree(n.sons[i])

View file

@ -759,9 +759,10 @@ proc initSameTypeClosure: TSameTypeClosure =
discard discard
proc containsOrIncl(c: var TSameTypeClosure, a, b: PType): bool = proc containsOrIncl(c: var TSameTypeClosure, a, b: PType): bool =
result = not isNil(c.s) and c.s.contains((a.id, b.id)) result = c.s.len > 0 and c.s.contains((a.id, b.id))
if not result: if not result:
if isNil(c.s): c.s = @[] when not defined(nimNoNilSeqs):
if isNil(c.s): c.s = @[]
c.s.add((a.id, b.id)) c.s.add((a.id, b.id))
proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool

View file

@ -29,7 +29,6 @@ proc renderPlainSymbolName*(n: PNode): string =
else: else:
result = "" result = ""
#internalError(n.info, "renderPlainSymbolName() with " & $n.kind) #internalError(n.info, "renderPlainSymbolName() with " & $n.kind)
assert(not result.isNil)
proc renderType(n: PNode): string = proc renderType(n: PNode): string =
## Returns a string with the node type or the empty string. ## Returns a string with the node type or the empty string.
@ -80,7 +79,6 @@ proc renderType(n: PNode): string =
for i in 1 ..< len(n): result.add(renderType(n[i]) & ',') for i in 1 ..< len(n): result.add(renderType(n[i]) & ',')
result[len(result)-1] = ']' result[len(result)-1] = ']'
else: result = "" else: result = ""
assert(not result.isNil)
proc renderParamTypes(found: var seq[string], n: PNode) = proc renderParamTypes(found: var seq[string], n: PNode) =

View file

@ -242,7 +242,8 @@ template getstr(a: untyped): untyped =
(if a.kind == rkNode: a.node.strVal else: $chr(int(a.intVal))) (if a.kind == rkNode: a.node.strVal else: $chr(int(a.intVal)))
proc pushSafePoint(f: PStackFrame; pc: int) = proc pushSafePoint(f: PStackFrame; pc: int) =
if f.safePoints.isNil: f.safePoints = @[] when not defined(nimNoNilSeqs):
if f.safePoints.isNil: f.safePoints = @[]
f.safePoints.add(pc) f.safePoints.add(pc)
proc popSafePoint(f: PStackFrame) = proc popSafePoint(f: PStackFrame) =
@ -255,7 +256,7 @@ proc cleanUpOnException(c: PCtx; tos: PStackFrame):
let raisedType = c.currentExceptionA.typ.skipTypes(abstractPtrs) let raisedType = c.currentExceptionA.typ.skipTypes(abstractPtrs)
var f = tos var f = tos
while true: while true:
while f.safePoints.isNil or f.safePoints.len == 0: while f.safePoints.len == 0:
f = f.next f = f.next
if f.isNil: return (-1, nil) if f.isNil: return (-1, nil)
var pc2 = f.safePoints[f.safePoints.high] var pc2 = f.safePoints[f.safePoints.high]
@ -297,7 +298,6 @@ proc cleanUpOnException(c: PCtx; tos: PStackFrame):
discard f.safePoints.pop discard f.safePoints.pop
proc cleanUpOnReturn(c: PCtx; f: PStackFrame): int = proc cleanUpOnReturn(c: PCtx; f: PStackFrame): int =
if f.safePoints.isNil: return -1
for s in f.safePoints: for s in f.safePoints:
var pc = s var pc = s
while c.code[pc].opcode == opcExcept: while c.code[pc].opcode == opcExcept:
@ -531,9 +531,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
decodeBC(rkInt) decodeBC(rkInt)
let idx = regs[rc].intVal.int let idx = regs[rc].intVal.int
let s = regs[rb].node.strVal let s = regs[rb].node.strVal
if s.isNil: if idx <% s.len:
stackTrace(c, tos, pc, errNilAccess)
elif idx <% s.len:
regs[ra].intVal = s[idx].ord regs[ra].intVal = s[idx].ord
elif idx == s.len and optLaxStrings in c.config.options: elif idx == s.len and optLaxStrings in c.config.options:
regs[ra].intVal = 0 regs[ra].intVal = 0
@ -1220,7 +1218,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
# Note that `nfIsRef` + `nkNilLit` represents an allocated # Note that `nfIsRef` + `nkNilLit` represents an allocated
# reference with the value `nil`, so `isNil` should be false! # reference with the value `nil`, so `isNil` should be false!
(node.kind == nkNilLit and nfIsRef notin node.flags) or (node.kind == nkNilLit and nfIsRef notin node.flags) or
(node.kind in {nkStrLit..nkTripleStrLit} and node.strVal.isNil) or
(not node.typ.isNil and node.typ.kind == tyProc and (not node.typ.isNil and node.typ.kind == tyProc and
node.typ.callConv == ccClosure and node.sons[0].kind == nkNilLit and node.typ.callConv == ccClosure and node.sons[0].kind == nkNilLit and
node.sons[1].kind == nkNilLit)) node.sons[1].kind == nkNilLit))
@ -1396,9 +1393,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let ast = parseString(regs[rb].node.strVal, c.cache, c.config, let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
toFullPath(c.config, c.debug[pc]), c.debug[pc].line.int, toFullPath(c.config, c.debug[pc]), c.debug[pc].line.int,
proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) = proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) =
if error.isNil and msg <= errMax: if error.len == 0 and msg <= errMax:
error = formatMsg(conf, info, msg, arg)) error = formatMsg(conf, info, msg, arg))
if not error.isNil: if error.len > 0:
c.errorFlag = error c.errorFlag = error
elif sonsLen(ast) != 1: elif sonsLen(ast) != 1:
c.errorFlag = formatMsg(c.config, c.debug[pc], errGenerated, c.errorFlag = formatMsg(c.config, c.debug[pc], errGenerated,
@ -1411,9 +1408,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let ast = parseString(regs[rb].node.strVal, c.cache, c.config, let ast = parseString(regs[rb].node.strVal, c.cache, c.config,
toFullPath(c.config, c.debug[pc]), c.debug[pc].line.int, toFullPath(c.config, c.debug[pc]), c.debug[pc].line.int,
proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) = proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string) =
if error.isNil and msg <= errMax: if error.len == 0 and msg <= errMax:
error = formatMsg(conf, info, msg, arg)) error = formatMsg(conf, info, msg, arg))
if not error.isNil: if error.len > 0:
c.errorFlag = error c.errorFlag = error
else: else:
regs[ra].node = ast regs[ra].node = ast
@ -1726,7 +1723,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
inc pc inc pc
let typ = c.types[c.code[pc].regBx - wordExcess] let typ = c.types[c.code[pc].regBx - wordExcess]
createStrKeepNode(regs[ra]) createStrKeepNode(regs[ra])
if regs[ra].node.strVal.isNil: regs[ra].node.strVal = newStringOfCap(1000) when not defined(nimNoNilSeqs):
if regs[ra].node.strVal.isNil: regs[ra].node.strVal = newStringOfCap(1000)
storeAny(regs[ra].node.strVal, typ, regs[rb].regToNode, c.config) storeAny(regs[ra].node.strVal, typ, regs[rb].regToNode, c.config)
of opcToNarrowInt: of opcToNarrowInt:
decodeBC(rkInt) decodeBC(rkInt)

View file

@ -127,7 +127,7 @@ proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet;
storeAny(s, t.lastSon, a, stored, conf) storeAny(s, t.lastSon, a, stored, conf)
s.add("]") s.add("]")
of tyString, tyCString: of tyString, tyCString:
if a.kind == nkNilLit or a.strVal.isNil: s.add("null") if a.kind == nkNilLit: s.add("null")
else: s.add(escapeJson(a.strVal)) else: s.add(escapeJson(a.strVal))
of tyInt..tyInt64, tyUInt..tyUInt64: s.add($a.intVal) of tyInt..tyInt64, tyUInt..tyUInt64: s.add($a.intVal)
of tyFloat..tyFloat128: s.add($a.floatVal) of tyFloat..tyFloat128: s.add($a.floatVal)

View file

@ -1387,7 +1387,7 @@ proc parseSectionWrapper(p: var RstParser): PRstNode =
result = result.sons[0] result = result.sons[0]
proc `$`(t: Token): string = proc `$`(t: Token): string =
result = $t.kind & ' ' & (if isNil(t.symbol): "NIL" else: t.symbol) result = $t.kind & ' ' & t.symbol
proc parseDoc(p: var RstParser): PRstNode = proc parseDoc(p: var RstParser): PRstNode =
result = parseSectionWrapper(p) result = parseSectionWrapper(p)

View file

@ -243,7 +243,7 @@ proc dispA(target: OutputTarget, dest: var string,
else: addf(dest, tex, args) else: addf(dest, tex, args)
proc `or`(x, y: string): string {.inline.} = proc `or`(x, y: string): string {.inline.} =
result = if x.isNil: y else: x result = if x.len == 0: y else: x
proc renderRstToOut*(d: var RstGenerator, n: PRstNode, result: var string) proc renderRstToOut*(d: var RstGenerator, n: PRstNode, result: var string)
## Writes into ``result`` the rst ast ``n`` using the ``d`` configuration. ## Writes into ``result`` the rst ast ``n`` using the ``d`` configuration.
@ -387,20 +387,16 @@ proc hash(x: IndexEntry): Hash =
## Returns the hash for the combined fields of the type. ## Returns the hash for the combined fields of the type.
## ##
## The hash is computed as the chained hash of the individual string hashes. ## The hash is computed as the chained hash of the individual string hashes.
assert(not x.keyword.isNil)
assert(not x.link.isNil)
result = x.keyword.hash !& x.link.hash result = x.keyword.hash !& x.link.hash
result = result !& (x.linkTitle or "").hash result = result !& x.linkTitle.hash
result = result !& (x.linkDesc or "").hash result = result !& x.linkDesc.hash
result = !$result result = !$result
proc `<-`(a: var IndexEntry, b: IndexEntry) = proc `<-`(a: var IndexEntry, b: IndexEntry) =
shallowCopy a.keyword, b.keyword shallowCopy a.keyword, b.keyword
shallowCopy a.link, b.link shallowCopy a.link, b.link
if b.linkTitle.isNil: a.linkTitle = "" shallowCopy a.linkTitle, b.linkTitle
else: shallowCopy a.linkTitle, b.linkTitle shallowCopy a.linkDesc, b.linkDesc
if b.linkDesc.isNil: a.linkDesc = ""
else: shallowCopy a.linkDesc, b.linkDesc
proc sortIndex(a: var openArray[IndexEntry]) = proc sortIndex(a: var openArray[IndexEntry]) =
# we use shellsort here; fast and simple # we use shellsort here; fast and simple
@ -444,8 +440,8 @@ proc generateSymbolIndex(symbols: seq[IndexEntry]): string =
while j < symbols.len and keyword == symbols[j].keyword: while j < symbols.len and keyword == symbols[j].keyword:
let let
url = symbols[j].link.escapeLink url = symbols[j].link.escapeLink
text = if not symbols[j].linkTitle.isNil: symbols[j].linkTitle else: url text = if symbols[j].linkTitle.len > 0: symbols[j].linkTitle else: url
desc = if not symbols[j].linkDesc.isNil: symbols[j].linkDesc else: "" desc = if symbols[j].linkDesc.len > 0: symbols[j].linkDesc else: ""
if desc.len > 0: if desc.len > 0:
result.addf("""<li><a class="reference external" result.addf("""<li><a class="reference external"
title="$3" data-doc-search-tag="$2" href="$1">$2</a></li> title="$3" data-doc-search-tag="$2" href="$1">$2</a></li>
@ -528,8 +524,6 @@ proc generateDocumentationTOC(entries: seq[IndexEntry]): string =
""", [titleTag & " : " & levels[L].text, link, levels[L].text]) """, [titleTag & " : " & levels[L].text, link, levels[L].text])
inc L inc L
result.add(level.indentToLevel(1) & "</ul>\n") result.add(level.indentToLevel(1) & "</ul>\n")
assert(not titleRef.isNil,
"Can't use this proc on an API index, docs always have a title entry")
proc generateDocumentationIndex(docs: IndexedDocs): string = proc generateDocumentationIndex(docs: IndexedDocs): string =
## Returns all the documentation TOCs in an HTML hierarchical list. ## Returns all the documentation TOCs in an HTML hierarchical list.
@ -596,7 +590,7 @@ proc readIndexDir(dir: string):
fileEntries[F].keyword = line.substr(0, s-1) fileEntries[F].keyword = line.substr(0, s-1)
fileEntries[F].link = line.substr(s+1) fileEntries[F].link = line.substr(s+1)
# See if we detect a title, a link without a `#foobar` trailing part. # See if we detect a title, a link without a `#foobar` trailing part.
if title.keyword.isNil and fileEntries[F].link.isDocumentationTitle: if title.keyword.len == 0 and fileEntries[F].link.isDocumentationTitle:
title.keyword = fileEntries[F].keyword title.keyword = fileEntries[F].keyword
title.link = fileEntries[F].link title.link = fileEntries[F].link
@ -611,11 +605,11 @@ proc readIndexDir(dir: string):
fileEntries[F].linkDesc = "" fileEntries[F].linkDesc = ""
inc F inc F
# Depending on type add this to the list of symbols or table of APIs. # Depending on type add this to the list of symbols or table of APIs.
if title.keyword.isNil: if title.keyword.len == 0:
for i in 0 .. <F: for i in 0 .. <F:
# Don't add to symbols TOC entries (they start with a whitespace). # Don't add to symbols TOC entries (they start with a whitespace).
let toc = fileEntries[i].linkTitle let toc = fileEntries[i].linkTitle
if not toc.isNil and toc.len > 0 and toc[0] == ' ': if toc.len > 0 and toc[0] == ' ':
continue continue
# Ok, non TOC entry, add it. # Ok, non TOC entry, add it.
setLen(result.symbols, L + 1) setLen(result.symbols, L + 1)

View file

@ -135,10 +135,9 @@ iterator decodeData*(allowedMethods: set[RequestMethod] =
## Reads and decodes CGI data and yields the (name, value) pairs the ## Reads and decodes CGI data and yields the (name, value) pairs the
## data consists of. If the client does not use a method listed in the ## data consists of. If the client does not use a method listed in the
## `allowedMethods` set, an `ECgi` exception is raised. ## `allowedMethods` set, an `ECgi` exception is raised.
var data = getEncodedData(allowedMethods) let data = getEncodedData(allowedMethods)
if not isNil(data): for key, value in decodeData(data):
for key, value in decodeData(data): yield (key, value)
yield (key, value)
proc readData*(allowedMethods: set[RequestMethod] = proc readData*(allowedMethods: set[RequestMethod] =
{methodNone, methodPost, methodGet}): StringTableRef = {methodNone, methodPost, methodGet}): StringTableRef =

View file

@ -74,7 +74,7 @@ proc isValid*[A](s: HashSet[A]): bool =
## proc savePreferences(options: HashSet[string]) = ## proc savePreferences(options: HashSet[string]) =
## assert options.isValid, "Pass an initialized set!" ## assert options.isValid, "Pass an initialized set!"
## # Do stuff here, may crash in release builds! ## # Do stuff here, may crash in release builds!
result = not s.data.isNil result = s.data.len > 0
proc len*[A](s: HashSet[A]): int = proc len*[A](s: HashSet[A]): int =
## Returns the number of keys in `s`. ## Returns the number of keys in `s`.

View file

@ -185,7 +185,7 @@ proc body*(response: Response): string =
## Retrieves the specified response's body. ## Retrieves the specified response's body.
## ##
## The response's body stream is read synchronously. ## The response's body stream is read synchronously.
if response.body.isNil(): if response.body.len == 0:
response.body = response.bodyStream.readAll() response.body = response.bodyStream.readAll()
return response.body return response.body
@ -198,7 +198,7 @@ proc `body=`*(response: Response, value: string) {.deprecated.} =
proc body*(response: AsyncResponse): Future[string] {.async.} = proc body*(response: AsyncResponse): Future[string] {.async.} =
## Reads the response's body and caches it. The read is performed only ## Reads the response's body and caches it. The read is performed only
## once. ## once.
if response.body.isNil: if response.body.len == 0:
response.body = await readAll(response.bodyStream) response.body = await readAll(response.bodyStream)
return response.body return response.body

View file

@ -256,7 +256,6 @@ proc add*(obj: JsonNode, key: string, val: JsonNode) =
proc `%`*(s: string): JsonNode = proc `%`*(s: string): JsonNode =
## Generic constructor for JSON data. Creates a new `JString JsonNode`. ## Generic constructor for JSON data. Creates a new `JString JsonNode`.
new(result) new(result)
if s.isNil: return
result.kind = JString result.kind = JString
result.str = s result.str = s

View file

@ -103,14 +103,9 @@ var
proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): string = proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): string =
## Format a log message using the ``frmt`` format string, ``level`` and varargs. ## Format a log message using the ``frmt`` format string, ``level`` and varargs.
## See the module documentation for the format string syntax. ## See the module documentation for the format string syntax.
const nilString = "nil"
var msgLen = 0 var msgLen = 0
for arg in args: for arg in args:
if arg.isNil: msgLen += arg.len
msgLen += nilString.len
else:
msgLen += arg.len
result = newStringOfCap(frmt.len + msgLen + 20) result = newStringOfCap(frmt.len + msgLen + 20)
var i = 0 var i = 0
while i < frmt.len: while i < frmt.len:
@ -137,10 +132,7 @@ proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): str
of "levelname": result.add(LevelNames[level]) of "levelname": result.add(LevelNames[level])
else: discard else: discard
for arg in args: for arg in args:
if arg.isNil: result.add(arg)
result.add(nilString)
else:
result.add(arg)
method log*(logger: Logger, level: Level, args: varargs[string, `$`]) {. method log*(logger: Logger, level: Level, args: varargs[string, `$`]) {.
raises: [Exception], gcsafe, raises: [Exception], gcsafe,
@ -338,7 +330,6 @@ template fatal*(args: varargs[string, `$`]) =
proc addHandler*(handler: Logger) = proc addHandler*(handler: Logger) =
## Adds ``handler`` to the list of handlers. ## Adds ``handler`` to the list of handlers.
if handlers.isNil: handlers = @[]
handlers.add(handler) handlers.add(handler)
proc getHandlers*(): seq[Logger] = proc getHandlers*(): seq[Logger] =

View file

@ -98,8 +98,7 @@ proc storeAny(s: Stream, a: Any, stored: var IntSet) =
of akProc, akPointer, akCString: s.write($a.getPointer.ptrToInt) of akProc, akPointer, akCString: s.write($a.getPointer.ptrToInt)
of akString: of akString:
var x = getString(a) var x = getString(a)
if isNil(x): s.write("null") if x.validateUtf8() == -1: s.write(escapeJson(x))
elif x.validateUtf8() == -1: s.write(escapeJson(x))
else: else:
s.write("[") s.write("[")
var i = 0 var i = 0

View file

@ -233,7 +233,7 @@ proc fileNewer*(a, b: string): bool {.rtl, extern: "nos$1".} =
## modification time is later than `b`'s. ## modification time is later than `b`'s.
when defined(posix): when defined(posix):
# If we don't have access to nanosecond resolution, use '>=' # If we don't have access to nanosecond resolution, use '>='
when not StatHasNanoseconds: when not StatHasNanoseconds:
result = getLastModificationTime(a) >= getLastModificationTime(b) result = getLastModificationTime(a) >= getLastModificationTime(b)
else: else:
result = getLastModificationTime(a) > getLastModificationTime(b) result = getLastModificationTime(a) > getLastModificationTime(b)
@ -1343,16 +1343,21 @@ elif defined(windows):
# is always the same -- independent of the used C compiler. # is always the same -- independent of the used C compiler.
var var
ownArgv {.threadvar.}: seq[string] ownArgv {.threadvar.}: seq[string]
ownParsedArgv {.threadvar.}: bool
proc paramCount*(): int {.rtl, extern: "nos$1", tags: [ReadIOEffect].} = proc paramCount*(): int {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
# Docstring in nimdoc block. # Docstring in nimdoc block.
if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine()) if not ownParsedArgv:
ownArgv = parseCmdLine($getCommandLine())
ownParsedArgv = true
result = ownArgv.len-1 result = ownArgv.len-1
proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1", proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1",
tags: [ReadIOEffect].} = tags: [ReadIOEffect].} =
# Docstring in nimdoc block. # Docstring in nimdoc block.
if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine()) if not ownParsedArgv:
ownArgv = parseCmdLine($getCommandLine())
ownParsedArgv = true
if i < ownArgv.len and i >= 0: return TaintedString(ownArgv[i]) if i < ownArgv.len and i >= 0: return TaintedString(ownArgv[i])
raise newException(IndexError, "invalid index") raise newException(IndexError, "invalid index")

View file

@ -593,7 +593,6 @@ proc len*(n: SqlNode): int =
proc `[]`*(n: SqlNode; i: int): SqlNode = n.sons[i] proc `[]`*(n: SqlNode; i: int): SqlNode = n.sons[i]
proc add*(father, n: SqlNode) = proc add*(father, n: SqlNode) =
if isNil(father.sons): father.sons = @[]
add(father.sons, n) add(father.sons, n)
proc getTok(p: var SqlParser) = proc getTok(p: var SqlParser) =

View file

@ -61,7 +61,6 @@ proc unidecode*(s: string): string =
## ##
## Results in: "Bei Jing" ## Results in: "Bei Jing"
## ##
assert(not isNil(translationTable))
result = "" result = ""
for r in runes(s): for r in runes(s):
var c = int(r) var c = int(r)

View file

@ -172,34 +172,30 @@ proc documentElement*(doc: PDocument): PElement =
proc findNodes(nl: PNode, name: string): seq[PNode] = proc findNodes(nl: PNode, name: string): seq[PNode] =
# Made for getElementsByTagName # Made for getElementsByTagName
var r: seq[PNode] = @[] var r: seq[PNode] = @[]
if isNil(nl.childNodes): return @[] if nl.childNodes.len == 0: return @[]
if nl.childNodes.len() == 0: return @[]
for i in items(nl.childNodes): for i in items(nl.childNodes):
if i.fNodeType == ElementNode: if i.fNodeType == ElementNode:
if i.fNodeName == name or name == "*": if i.fNodeName == name or name == "*":
r.add(i) r.add(i)
if not isNil(i.childNodes): if i.childNodes.len() != 0:
if i.childNodes.len() != 0: r.add(findNodes(i, name))
r.add(findNodes(i, name))
return r return r
proc findNodesNS(nl: PNode, namespaceURI: string, localName: string): seq[PNode] = proc findNodesNS(nl: PNode, namespaceURI: string, localName: string): seq[PNode] =
# Made for getElementsByTagNameNS # Made for getElementsByTagNameNS
var r: seq[PNode] = @[] var r: seq[PNode] = @[]
if isNil(nl.childNodes): return @[] if nl.childNodes.len == 0: return @[]
if nl.childNodes.len() == 0: return @[]
for i in items(nl.childNodes): for i in items(nl.childNodes):
if i.fNodeType == ElementNode: if i.fNodeType == ElementNode:
if (i.fNamespaceURI == namespaceURI or namespaceURI == "*") and (i.fLocalName == localName or localName == "*"): if (i.fNamespaceURI == namespaceURI or namespaceURI == "*") and (i.fLocalName == localName or localName == "*"):
r.add(i) r.add(i)
if not isNil(i.childNodes): if i.childNodes.len != 0:
if i.childNodes.len() != 0: r.add(findNodesNS(i, namespaceURI, localName))
r.add(findNodesNS(i, namespaceURI, localName))
return r return r
@ -233,8 +229,8 @@ proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: str
# Exceptions # Exceptions
if qualifiedName.contains(':'): if qualifiedName.contains(':'):
let qfnamespaces = qualifiedName.toLowerAscii().split(':') let qfnamespaces = qualifiedName.toLowerAscii().split(':')
if isNil(namespaceURI): if namespaceURI.len == 0:
raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil") raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be empty")
elif qfnamespaces[0] == "xml" and elif qfnamespaces[0] == "xml" and
namespaceURI != "http://www.w3.org/XML/1998/namespace" and namespaceURI != "http://www.w3.org/XML/1998/namespace" and
qfnamespaces[1] notin stdattrnames: qfnamespaces[1] notin stdattrnames:
@ -312,8 +308,8 @@ proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: strin
## Creates an element of the given qualified name and namespace URI. ## Creates an element of the given qualified name and namespace URI.
if qualifiedName.contains(':'): if qualifiedName.contains(':'):
let qfnamespaces = qualifiedName.toLowerAscii().split(':') let qfnamespaces = qualifiedName.toLowerAscii().split(':')
if isNil(namespaceURI): if namespaceURI.len == 0:
raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil") raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be empty")
elif qfnamespaces[0] == "xml" and elif qfnamespaces[0] == "xml" and
namespaceURI != "http://www.w3.org/XML/1998/namespace" and namespaceURI != "http://www.w3.org/XML/1998/namespace" and
qfnamespaces[1] notin stdattrnames: qfnamespaces[1] notin stdattrnames:
@ -453,7 +449,7 @@ proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
proc firstChild*(n: PNode): PNode = proc firstChild*(n: PNode): PNode =
## Returns this node's first child ## Returns this node's first child
if not isNil(n.childNodes) and n.childNodes.len() > 0: if n.childNodes.len > 0:
return n.childNodes[0] return n.childNodes[0]
else: else:
return nil return nil
@ -461,8 +457,8 @@ proc firstChild*(n: PNode): PNode =
proc lastChild*(n: PNode): PNode = proc lastChild*(n: PNode): PNode =
## Returns this node's last child ## Returns this node's last child
if not isNil(n.childNodes) and n.childNodes.len() > 0: if n.childNodes.len > 0:
return n.childNodes[n.childNodes.len() - 1] return n.childNodes[n.childNodes.len - 1]
else: else:
return nil return nil
@ -482,7 +478,7 @@ proc `namespaceURI=`*(n: PNode, value: string) =
proc nextSibling*(n: PNode): PNode = proc nextSibling*(n: PNode): PNode =
## Returns the next sibling of this node ## Returns the next sibling of this node
if isNil(n.fParentNode) or isNil(n.fParentNode.childNodes): if isNil(n.fParentNode):
return nil return nil
var nLow: int = low(n.fParentNode.childNodes) var nLow: int = low(n.fParentNode.childNodes)
var nHigh: int = high(n.fParentNode.childNodes) var nHigh: int = high(n.fParentNode.childNodes)
@ -514,7 +510,7 @@ proc parentNode*(n: PNode): PNode =
proc previousSibling*(n: PNode): PNode = proc previousSibling*(n: PNode): PNode =
## Returns the previous sibling of this node ## Returns the previous sibling of this node
if isNil(n.fParentNode) or isNil(n.fParentNode.childNodes): if isNil(n.fParentNode):
return nil return nil
var nLow: int = low(n.fParentNode.childNodes) var nLow: int = low(n.fParentNode.childNodes)
var nHigh: int = high(n.fParentNode.childNodes) var nHigh: int = high(n.fParentNode.childNodes)
@ -531,8 +527,8 @@ proc `prefix=`*(n: PNode, value: string) =
if illegalChars in value: if illegalChars in value:
raise newException(EInvalidCharacterErr, "Invalid character") raise newException(EInvalidCharacterErr, "Invalid character")
if isNil(n.fNamespaceURI): if n.fNamespaceURI.len == 0:
raise newException(ENamespaceErr, "namespaceURI cannot be nil") raise newException(ENamespaceErr, "namespaceURI cannot be empty")
elif value.toLowerAscii() == "xml" and n.fNamespaceURI != "http://www.w3.org/XML/1998/namespace": elif value.toLowerAscii() == "xml" and n.fNamespaceURI != "http://www.w3.org/XML/1998/namespace":
raise newException(ENamespaceErr, raise newException(ENamespaceErr,
"When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"") "When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"")
@ -557,10 +553,9 @@ proc appendChild*(n: PNode, newChild: PNode) =
## If the newChild is already in the tree, it is first removed. ## If the newChild is already in the tree, it is first removed.
# Check if n contains newChild # Check if n contains newChild
if not isNil(n.childNodes): for i in low(n.childNodes)..high(n.childNodes):
for i in low(n.childNodes)..high(n.childNodes): if n.childNodes[i] == newChild:
if n.childNodes[i] == newChild: raise newException(EHierarchyRequestErr, "The node to append is already in this nodes children.")
raise newException(EHierarchyRequestErr, "The node to append is already in this nodes children.")
# Check if newChild is from this nodes document # Check if newChild is from this nodes document
if n.fOwnerDocument != newChild.fOwnerDocument: if n.fOwnerDocument != newChild.fOwnerDocument:
@ -572,7 +567,8 @@ proc appendChild*(n: PNode, newChild: PNode) =
if n.nodeType in childlessObjects: if n.nodeType in childlessObjects:
raise newException(ENoModificationAllowedErr, "Cannot append children to a childless node") raise newException(ENoModificationAllowedErr, "Cannot append children to a childless node")
if isNil(n.childNodes): n.childNodes = @[] when not defined(nimNoNilSeqs):
if isNil(n.childNodes): n.childNodes = @[]
newChild.fParentNode = n newChild.fParentNode = n
for i in low(n.childNodes)..high(n.childNodes): for i in low(n.childNodes)..high(n.childNodes):
@ -597,10 +593,10 @@ proc cloneNode*(n: PNode, deep: bool): PNode =
newNode = PElement(n) newNode = PElement(n)
# Import the childNodes # Import the childNodes
var tmp: seq[PNode] = n.childNodes var tmp: seq[PNode] = n.childNodes
n.childNodes = @[] newNode.childNodes = @[]
if deep and not isNil(tmp): if deep:
for i in low(tmp.len())..high(tmp.len()): for i in low(n.childNodes)..high(n.childNodes):
n.childNodes.add(cloneNode(tmp[i], deep)) newNode.childNodes.add(cloneNode(n.childNodes[i], deep))
return newNode return newNode
else: else:
var newNode: PNode var newNode: PNode
@ -610,11 +606,11 @@ proc cloneNode*(n: PNode, deep: bool): PNode =
proc hasAttributes*(n: PNode): bool = proc hasAttributes*(n: PNode): bool =
## Returns whether this node (if it is an element) has any attributes. ## Returns whether this node (if it is an element) has any attributes.
return not isNil(n.attributes) and n.attributes.len() > 0 return n.attributes.len > 0
proc hasChildNodes*(n: PNode): bool = proc hasChildNodes*(n: PNode): bool =
## Returns whether this node has any children. ## Returns whether this node has any children.
return not isNil(n.childNodes) and n.childNodes.len() > 0 return n.childNodes.len > 0
proc insertBefore*(n: PNode, newChild: PNode, refChild: PNode): PNode = proc insertBefore*(n: PNode, newChild: PNode, refChild: PNode): PNode =
## Inserts the node ``newChild`` before the existing child node ``refChild``. ## Inserts the node ``newChild`` before the existing child node ``refChild``.
@ -624,9 +620,6 @@ proc insertBefore*(n: PNode, newChild: PNode, refChild: PNode): PNode =
if n.fOwnerDocument != newChild.fOwnerDocument: if n.fOwnerDocument != newChild.fOwnerDocument:
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.") raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
if isNil(n.childNodes):
n.childNodes = @[]
for i in low(n.childNodes)..high(n.childNodes): for i in low(n.childNodes)..high(n.childNodes):
if n.childNodes[i] == refChild: if n.childNodes[i] == refChild:
n.childNodes.insert(newChild, i - 1) n.childNodes.insert(newChild, i - 1)
@ -641,7 +634,7 @@ proc isSupported*(n: PNode, feature: string, version: string): bool =
proc isEmpty(s: string): bool = proc isEmpty(s: string): bool =
if isNil(s) or s == "": if s == "":
return true return true
for i in items(s): for i in items(s):
if i != ' ': if i != ' ':
@ -655,7 +648,7 @@ proc normalize*(n: PNode) =
var newChildNodes: seq[PNode] = @[] var newChildNodes: seq[PNode] = @[]
while true: while true:
if isNil(n.childNodes) or i >= n.childNodes.len: if i >= n.childNodes.len:
break break
if n.childNodes[i].nodeType == TextNode: if n.childNodes[i].nodeType == TextNode:
@ -679,12 +672,11 @@ proc normalize*(n: PNode) =
proc removeChild*(n: PNode, oldChild: PNode): PNode = proc removeChild*(n: PNode, oldChild: PNode): PNode =
## Removes the child node indicated by ``oldChild`` from the list of children, and returns it. ## Removes the child node indicated by ``oldChild`` from the list of children, and returns it.
if not isNil(n.childNodes): for i in low(n.childNodes)..high(n.childNodes):
for i in low(n.childNodes)..high(n.childNodes): if n.childNodes[i] == oldChild:
if n.childNodes[i] == oldChild: result = n.childNodes[i]
result = n.childNodes[i] n.childNodes.delete(i)
n.childNodes.delete(i) return
return
raise newException(ENotFoundErr, "Node not found") raise newException(ENotFoundErr, "Node not found")
@ -695,12 +687,11 @@ proc replaceChild*(n: PNode, newChild: PNode, oldChild: PNode): PNode =
if n.fOwnerDocument != newChild.fOwnerDocument: if n.fOwnerDocument != newChild.fOwnerDocument:
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.") raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
if not isNil(n.childNodes): for i in low(n.childNodes)..high(n.childNodes):
for i in low(n.childNodes)..high(n.childNodes): if n.childNodes[i] == oldChild:
if n.childNodes[i] == oldChild: result = n.childNodes[i]
result = n.childNodes[i] n.childNodes[i] = newChild
n.childNodes[i] = newChild return
return
raise newException(ENotFoundErr, "Node not found") raise newException(ENotFoundErr, "Node not found")
@ -764,11 +755,10 @@ proc removeNamedItemNS*(nList: var seq[PNode], namespaceURI: string, localName:
proc setNamedItem*(nList: var seq[PNode], arg: PNode): PNode = proc setNamedItem*(nList: var seq[PNode], arg: PNode): PNode =
## Adds ``arg`` as a ``Node`` to the ``NList`` ## Adds ``arg`` as a ``Node`` to the ``NList``
## If a node with the same name is already present in this map, it is replaced by the new one. ## If a node with the same name is already present in this map, it is replaced by the new one.
if not isNil(nList): if nList.len > 0:
if nList.len() > 0: #Check if newChild is from this nodes document
#Check if newChild is from this nodes document if nList[0].fOwnerDocument != arg.fOwnerDocument:
if nList[0].fOwnerDocument != arg.fOwnerDocument: raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
#Exceptions End #Exceptions End
var item: PNode = nList.getNamedItem(arg.nodeName()) var item: PNode = nList.getNamedItem(arg.nodeName())
@ -788,11 +778,10 @@ proc setNamedItem*(nList: var seq[PNode], arg: PNode): PNode =
proc setNamedItem*(nList: var seq[PAttr], arg: PAttr): PAttr = proc setNamedItem*(nList: var seq[PAttr], arg: PAttr): PAttr =
## Adds ``arg`` as a ``Node`` to the ``NList`` ## Adds ``arg`` as a ``Node`` to the ``NList``
## If a node with the same name is already present in this map, it is replaced by the new one. ## If a node with the same name is already present in this map, it is replaced by the new one.
if not isNil(nList): if nList.len > 0:
if nList.len() > 0: # Check if newChild is from this nodes document
# Check if newChild is from this nodes document if nList[0].fOwnerDocument != arg.fOwnerDocument:
if nList[0].fOwnerDocument != arg.fOwnerDocument: raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
if not isNil(arg.fOwnerElement): if not isNil(arg.fOwnerElement):
raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode") raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode")
@ -814,11 +803,10 @@ proc setNamedItem*(nList: var seq[PAttr], arg: PAttr): PAttr =
proc setNamedItemNS*(nList: var seq[PNode], arg: PNode): PNode = proc setNamedItemNS*(nList: var seq[PNode], arg: PNode): PNode =
## Adds a node using its ``namespaceURI`` and ``localName`` ## Adds a node using its ``namespaceURI`` and ``localName``
if not isNil(nList): if nList.len > 0:
if nList.len() > 0: # Check if newChild is from this nodes document
# Check if newChild is from this nodes document if nList[0].fOwnerDocument != arg.fOwnerDocument:
if nList[0].fOwnerDocument != arg.fOwnerDocument: raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
#Exceptions end #Exceptions end
var item: PNode = nList.getNamedItemNS(arg.namespaceURI(), arg.localName()) var item: PNode = nList.getNamedItemNS(arg.namespaceURI(), arg.localName())
@ -837,11 +825,10 @@ proc setNamedItemNS*(nList: var seq[PNode], arg: PNode): PNode =
proc setNamedItemNS*(nList: var seq[PAttr], arg: PAttr): PAttr = proc setNamedItemNS*(nList: var seq[PAttr], arg: PAttr): PAttr =
## Adds a node using its ``namespaceURI`` and ``localName`` ## Adds a node using its ``namespaceURI`` and ``localName``
if not isNil(nList): if nList.len > 0:
if nList.len() > 0: # Check if newChild is from this nodes document
# Check if newChild is from this nodes document if nList[0].fOwnerDocument != arg.fOwnerDocument:
if nList[0].fOwnerDocument != arg.fOwnerDocument: raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
if not isNil(arg.fOwnerElement): if not isNil(arg.fOwnerElement):
raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode") raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode")
@ -868,17 +855,14 @@ proc setNamedItemNS*(nList: var seq[PAttr], arg: PAttr): PAttr =
# Attributes # Attributes
proc name*(a: PAttr): string = proc name*(a: PAttr): string =
## Returns the name of the Attribute ## Returns the name of the Attribute
return a.fName return a.fName
proc specified*(a: PAttr): bool = proc specified*(a: PAttr): bool =
## Specifies whether this attribute was specified in the original document ## Specifies whether this attribute was specified in the original document
return a.fSpecified return a.fSpecified
proc ownerElement*(a: PAttr): PElement = proc ownerElement*(a: PAttr): PElement =
## Returns this Attributes owner element ## Returns this Attributes owner element
return a.fOwnerElement return a.fOwnerElement
# Element # Element
@ -886,14 +870,11 @@ proc ownerElement*(a: PAttr): PElement =
proc tagName*(el: PElement): string = proc tagName*(el: PElement): string =
## Returns the Element Tag Name ## Returns the Element Tag Name
return el.fTagName return el.fTagName
# Procedures # Procedures
proc getAttribute*(el: PNode, name: string): string = proc getAttribute*(el: PNode, name: string): string =
## Retrieves an attribute value by ``name`` ## Retrieves an attribute value by ``name``
if isNil(el.attributes):
return ""
var attribute = el.attributes.getNamedItem(name) var attribute = el.attributes.getNamedItem(name)
if not isNil(attribute): if not isNil(attribute):
return attribute.value return attribute.value
@ -902,8 +883,6 @@ proc getAttribute*(el: PNode, name: string): string =
proc getAttributeNS*(el: PNode, namespaceURI: string, localName: string): string = proc getAttributeNS*(el: PNode, namespaceURI: string, localName: string): string =
## Retrieves an attribute value by ``localName`` and ``namespaceURI`` ## Retrieves an attribute value by ``localName`` and ``namespaceURI``
if isNil(el.attributes):
return ""
var attribute = el.attributes.getNamedItemNS(namespaceURI, localName) var attribute = el.attributes.getNamedItemNS(namespaceURI, localName)
if not isNil(attribute): if not isNil(attribute):
return attribute.value return attribute.value
@ -913,14 +892,10 @@ proc getAttributeNS*(el: PNode, namespaceURI: string, localName: string): string
proc getAttributeNode*(el: PElement, name: string): PAttr = proc getAttributeNode*(el: PElement, name: string): PAttr =
## Retrieves an attribute node by ``name`` ## Retrieves an attribute node by ``name``
## To retrieve an attribute node by qualified name and namespace URI, use the `getAttributeNodeNS` method ## To retrieve an attribute node by qualified name and namespace URI, use the `getAttributeNodeNS` method
if isNil(el.attributes):
return nil
return el.attributes.getNamedItem(name) return el.attributes.getNamedItem(name)
proc getAttributeNodeNS*(el: PElement, namespaceURI: string, localName: string): PAttr = proc getAttributeNodeNS*(el: PElement, namespaceURI: string, localName: string): PAttr =
## Retrieves an `Attr` node by ``localName`` and ``namespaceURI`` ## Retrieves an `Attr` node by ``localName`` and ``namespaceURI``
if isNil(el.attributes):
return nil
return el.attributes.getNamedItemNS(namespaceURI, localName) return el.attributes.getNamedItemNS(namespaceURI, localName)
proc getElementsByTagName*(el: PElement, name: string): seq[PNode] = proc getElementsByTagName*(el: PElement, name: string): seq[PNode] =
@ -938,41 +913,34 @@ proc getElementsByTagNameNS*(el: PElement, namespaceURI: string, localName: stri
proc hasAttribute*(el: PElement, name: string): bool = proc hasAttribute*(el: PElement, name: string): bool =
## Returns ``true`` when an attribute with a given ``name`` is specified ## Returns ``true`` when an attribute with a given ``name`` is specified
## on this element , ``false`` otherwise. ## on this element , ``false`` otherwise.
if isNil(el.attributes):
return false
return not isNil(el.attributes.getNamedItem(name)) return not isNil(el.attributes.getNamedItem(name))
proc hasAttributeNS*(el: PElement, namespaceURI: string, localName: string): bool = proc hasAttributeNS*(el: PElement, namespaceURI: string, localName: string): bool =
## Returns ``true`` when an attribute with a given ``localName`` and ## Returns ``true`` when an attribute with a given ``localName`` and
## ``namespaceURI`` is specified on this element , ``false`` otherwise ## ``namespaceURI`` is specified on this element , ``false`` otherwise
if isNil(el.attributes):
return false
return not isNil(el.attributes.getNamedItemNS(namespaceURI, localName)) return not isNil(el.attributes.getNamedItemNS(namespaceURI, localName))
proc removeAttribute*(el: PElement, name: string) = proc removeAttribute*(el: PElement, name: string) =
## Removes an attribute by ``name`` ## Removes an attribute by ``name``
if not isNil(el.attributes): for i in low(el.attributes)..high(el.attributes):
for i in low(el.attributes)..high(el.attributes): if el.attributes[i].fName == name:
if el.attributes[i].fName == name: el.attributes.delete(i)
el.attributes.delete(i)
proc removeAttributeNS*(el: PElement, namespaceURI: string, localName: string) = proc removeAttributeNS*(el: PElement, namespaceURI: string, localName: string) =
## Removes an attribute by ``localName`` and ``namespaceURI`` ## Removes an attribute by ``localName`` and ``namespaceURI``
if not isNil(el.attributes): for i in low(el.attributes)..high(el.attributes):
for i in low(el.attributes)..high(el.attributes): if el.attributes[i].fNamespaceURI == namespaceURI and
if el.attributes[i].fNamespaceURI == namespaceURI and el.attributes[i].fLocalName == localName:
el.attributes[i].fLocalName == localName: el.attributes.delete(i)
el.attributes.delete(i)
proc removeAttributeNode*(el: PElement, oldAttr: PAttr): PAttr = proc removeAttributeNode*(el: PElement, oldAttr: PAttr): PAttr =
## Removes the specified attribute node ## Removes the specified attribute node
## If the attribute node cannot be found raises ``ENotFoundErr`` ## If the attribute node cannot be found raises ``ENotFoundErr``
if not isNil(el.attributes): for i in low(el.attributes)..high(el.attributes):
for i in low(el.attributes)..high(el.attributes): if el.attributes[i] == oldAttr:
if el.attributes[i] == oldAttr: result = el.attributes[i]
result = el.attributes[i] el.attributes.delete(i)
el.attributes.delete(i) return
return
raise newException(ENotFoundErr, "oldAttr is not a member of el's Attributes") raise newException(ENotFoundErr, "oldAttr is not a member of el's Attributes")
@ -991,7 +959,6 @@ proc setAttributeNode*(el: PElement, newAttr: PAttr): PAttr =
"This attribute is in use by another element, use cloneNode") "This attribute is in use by another element, use cloneNode")
# Exceptions end # Exceptions end
if isNil(el.attributes): el.attributes = @[]
return el.attributes.setNamedItem(newAttr) return el.attributes.setNamedItem(newAttr)
proc setAttributeNodeNS*(el: PElement, newAttr: PAttr): PAttr = proc setAttributeNodeNS*(el: PElement, newAttr: PAttr): PAttr =
@ -1009,7 +976,6 @@ proc setAttributeNodeNS*(el: PElement, newAttr: PAttr): PAttr =
"This attribute is in use by another element, use cloneNode") "This attribute is in use by another element, use cloneNode")
# Exceptions end # Exceptions end
if isNil(el.attributes): el.attributes = @[]
return el.attributes.setNamedItemNS(newAttr) return el.attributes.setNamedItemNS(newAttr)
proc setAttribute*(el: PElement, name: string, value: string) = proc setAttribute*(el: PElement, name: string, value: string) =
@ -1057,9 +1023,9 @@ proc splitData*(textNode: PText, offset: int): PText =
var left: string = textNode.data.substr(0, offset) var left: string = textNode.data.substr(0, offset)
textNode.data = left textNode.data = left
var right: string = textNode.data.substr(offset, textNode.data.len()) var right: string = textNode.data.substr(offset, textNode.data.len)
if not isNil(textNode.fParentNode) and not isNil(textNode.fParentNode.childNodes): if not isNil(textNode.fParentNode) and textNode.fParentNode.childNodes.len > 0:
for i in low(textNode.fParentNode.childNodes)..high(textNode.fParentNode.childNodes): for i in low(textNode.fParentNode.childNodes)..high(textNode.fParentNode.childNodes):
if textNode.fParentNode.childNodes[i] == textNode: if textNode.fParentNode.childNodes[i] == textNode:
var newNode: PText = textNode.fOwnerDocument.createTextNode(right) var newNode: PText = textNode.fOwnerDocument.createTextNode(right)
@ -1098,11 +1064,10 @@ proc escapeXml*(s: string): string =
proc nodeToXml(n: PNode, indent: int = 0): string = proc nodeToXml(n: PNode, indent: int = 0): string =
result = spaces(indent) & "<" & n.nodeName result = spaces(indent) & "<" & n.nodeName
if not isNil(n.attributes): for i in items(n.attributes):
for i in items(n.attributes): result.add(" " & i.name & "=\"" & escapeXml(i.value) & "\"")
result.add(" " & i.name & "=\"" & escapeXml(i.value) & "\"")
if isNil(n.childNodes) or n.childNodes.len() == 0: if n.childNodes.len == 0:
result.add("/>") # No idea why this doesn't need a \n :O result.add("/>") # No idea why this doesn't need a \n :O
else: else:
# End the beginning of this tag # End the beginning of this tag
@ -1134,3 +1099,4 @@ proc `$`*(doc: PDocument): string =
## Converts a PDocument object into a string representation of it's XML ## Converts a PDocument object into a string representation of it's XML
result = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" result = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
result.add(nodeToXml(doc.documentElement)) result.add(nodeToXml(doc.documentElement))

View file

@ -2292,9 +2292,18 @@ iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} =
inc(i) inc(i)
proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil", deprecated.} when defined(nimNoNilSeqs2):
when not compileOption("nilseqs"):
{.pragma: nilError, error.}
else:
{.pragma: nilError.}
else:
{.pragma: nilError.}
proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil", nilError.}
proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".} proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil", deprecated.} proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil", nilError.}
proc isNil*[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".} proc isNil*[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: pointer): bool {.noSideEffect, magic: "IsNil".} proc isNil*(x: pointer): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".} proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".}

View file

@ -213,7 +213,7 @@ proc auxWriteStackTrace(f: PFrame; s: var seq[StackTraceEntry]) =
inc(i) inc(i)
it = it.prev it = it.prev
var last = i-1 var last = i-1
if s.isNil: if s.len == 0:
s = newSeq[StackTraceEntry](i) s = newSeq[StackTraceEntry](i)
else: else:
last = s.len + i - 1 last = s.len + i - 1
@ -361,10 +361,10 @@ proc raiseExceptionAux(e: ref Exception) =
else: else:
when hasSomeStackTrace: when hasSomeStackTrace:
var buf = newStringOfCap(2000) var buf = newStringOfCap(2000)
if isNil(e.trace): rawWriteStackTrace(buf) if e.trace.len == 0: rawWriteStackTrace(buf)
else: add(buf, $e.trace) else: add(buf, $e.trace)
add(buf, "Error: unhandled exception: ") add(buf, "Error: unhandled exception: ")
if not isNil(e.msg): add(buf, e.msg) add(buf, e.msg)
add(buf, " [") add(buf, " [")
add(buf, $e.name) add(buf, $e.name)
add(buf, "]\n") add(buf, "]\n")
@ -382,7 +382,7 @@ proc raiseExceptionAux(e: ref Exception) =
var buf: array[0..2000, char] var buf: array[0..2000, char]
var L = 0 var L = 0
add(buf, "Error: unhandled exception: ") add(buf, "Error: unhandled exception: ")
if not isNil(e.msg): add(buf, e.msg) add(buf, e.msg)
add(buf, " [") add(buf, " [")
xadd(buf, e.name, e.name.len) xadd(buf, e.name, e.name.len)
add(buf, "]\n") add(buf, "]\n")
@ -397,7 +397,7 @@ proc raiseExceptionAux(e: ref Exception) =
proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} = proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
if e.name.isNil: e.name = ename if e.name.isNil: e.name = ename
when hasSomeStackTrace: when hasSomeStackTrace:
if e.trace.isNil: if e.trace.len == 0:
rawWriteStackTrace(e.trace) rawWriteStackTrace(e.trace)
elif framePtr != nil: elif framePtr != nil:
e.trace.add reraisedFrom(reraisedFromBegin) e.trace.add reraisedFrom(reraisedFromBegin)
@ -427,7 +427,7 @@ proc getStackTrace(): string =
result = "No stack traceback available\n" result = "No stack traceback available\n"
proc getStackTrace(e: ref Exception): string = proc getStackTrace(e: ref Exception): string =
if not isNil(e) and not isNil(e.trace): if not isNil(e):
result = $e.trace result = $e.trace
else: else:
result = "" result = ""

View file

@ -266,7 +266,7 @@ when not defined(useNimRtl):
of tyChar: add result, reprChar(cast[ptr char](p)[]) of tyChar: add result, reprChar(cast[ptr char](p)[])
of tyString: of tyString:
let sp = cast[ptr string](p) let sp = cast[ptr string](p)
reprStrAux(result, if sp[].isNil: nil else: sp[].cstring, sp[].len) reprStrAux(result, sp[].cstring, sp[].len)
of tyCString: of tyCString:
let cs = cast[ptr cstring](p)[] let cs = cast[ptr cstring](p)[]
if cs.isNil: add result, "nil" if cs.isNil: add result, "nil"

View file

@ -232,10 +232,7 @@ proc reprAux(result: var string, p: pointer, typ: PNimType,
of tyString: of tyString:
var fp: int var fp: int
{. emit: "`fp` = `p`;\n" .} {. emit: "`fp` = `p`;\n" .}
if cast[string](fp).isNil: add( result, reprStr(cast[string](p)) )
add(result, "nil")
else:
add( result, reprStr(cast[string](p)) )
of tyCString: of tyCString:
var fp: cstring var fp: cstring
{. emit: "`fp` = `p`;\n" .} {. emit: "`fp` = `p`;\n" .}

View file

@ -144,13 +144,7 @@ proc getFileHandle*(f: File): FileHandle = c_fileno(f)
proc readLine(f: File, line: var TaintedString): bool = proc readLine(f: File, line: var TaintedString): bool =
var pos = 0 var pos = 0
var sp: cint = 80 var sp: cint = 80
# Use the currently reserved space for a first try line.string.setLen(sp)
if line.string.isNil:
line = TaintedString(newStringOfCap(80))
else:
when not defined(nimscript) and not defined(gcDestructors):
sp = cint(cast[PGenericSeq](line.string).space)
line.string.setLen(sp)
while true: while true:
# memset to \L so that we can tell how far fgets wrote, even on EOF, where # memset to \L so that we can tell how far fgets wrote, even on EOF, where
# fgets doesn't append an \L # fgets doesn't append an \L

View file

@ -393,8 +393,9 @@ proc onThreadDestruction*(handler: proc () {.closure, gcsafe.}) =
## A thread is destructed when the ``.thread`` proc returns ## A thread is destructed when the ``.thread`` proc returns
## normally or when it raises an exception. Note that unhandled exceptions ## normally or when it raises an exception. Note that unhandled exceptions
## in a thread nevertheless cause the whole process to die. ## in a thread nevertheless cause the whole process to die.
if threadDestructionHandlers.isNil: when not defined(nimNoNilSeqs):
threadDestructionHandlers = @[] if threadDestructionHandlers.isNil:
threadDestructionHandlers = @[]
threadDestructionHandlers.add handler threadDestructionHandlers.add handler
template afterThreadRuns() = template afterThreadRuns() =

View file

@ -232,7 +232,7 @@ template run_custom_proc(parsed_parameter: Tparsed_parameter,
if not custom_validator.isNil: if not custom_validator.isNil:
try: try:
let message = custom_validator(parameter, parsed_parameter) let message = custom_validator(parameter, parsed_parameter)
if not message.isNil and message.len > 0: if message.len > 0:
raise_or_quit(ValueError, ("Failed to validate value for " & raise_or_quit(ValueError, ("Failed to validate value for " &
"parameter $1:\n$2" % [escape(parameter), message])) "parameter $1:\n$2" % [escape(parameter), message]))
except: except:

View file

@ -7,3 +7,4 @@ path = "dependencies/genpacket"
path = "enet_server" path = "enet_server"
debugger = off debugger = off
warning[SmallLshouldNotBeUsed] = off warning[SmallLshouldNotBeUsed] = off
nilseqs = on