Deprecate TaintedString (#15423)
Co-authored-by: Timothee Cour <timothee.cour2@gmail.com> Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>
This commit is contained in:
parent
7b632f9ccb
commit
78a99587a4
36 changed files with 184 additions and 229 deletions
|
|
@ -122,6 +122,8 @@ with other backends. see #9125. Use `-d:nimLegacyJsRound` for previous behavior.
|
||||||
|
|
||||||
- Added `--declaredlocs` to show symbol declaration location in messages.
|
- Added `--declaredlocs` to show symbol declaration location in messages.
|
||||||
|
|
||||||
|
- Deprecated `TaintedString` and `--taintmode`.
|
||||||
|
|
||||||
- Source+Edit links now appear on top of every docgen'd page when
|
- Source+Edit links now appear on top of every docgen'd page when
|
||||||
`nim doc --git.url:url ...` is given.
|
`nim doc --git.url:url ...` is given.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -312,7 +312,7 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
|
||||||
of "symbolfiles": result = conf.symbolFiles != disabledSf
|
of "symbolfiles": result = conf.symbolFiles != disabledSf
|
||||||
of "genscript": result = contains(conf.globalOptions, optGenScript)
|
of "genscript": result = contains(conf.globalOptions, optGenScript)
|
||||||
of "threads": result = contains(conf.globalOptions, optThreads)
|
of "threads": result = contains(conf.globalOptions, optThreads)
|
||||||
of "taintmode": result = contains(conf.globalOptions, optTaintMode)
|
of "taintmode": result = false # pending https://github.com/nim-lang/Nim/issues/16731
|
||||||
of "tlsemulation": result = contains(conf.globalOptions, optTlsEmulation)
|
of "tlsemulation": result = contains(conf.globalOptions, optTlsEmulation)
|
||||||
of "implicitstatic": result = contains(conf.options, optImplicitStatic)
|
of "implicitstatic": result = contains(conf.options, optImplicitStatic)
|
||||||
of "patterns", "trmacros": result = contains(conf.options, optTrMacros)
|
of "patterns", "trmacros": result = contains(conf.options, optTrMacros)
|
||||||
|
|
@ -670,7 +670,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||||
processOnOffSwitchG(conf, {optThreads}, arg, pass, info)
|
processOnOffSwitchG(conf, {optThreads}, arg, pass, info)
|
||||||
#if optThreads in conf.globalOptions: conf.setNote(warnGcUnsafe)
|
#if optThreads in conf.globalOptions: conf.setNote(warnGcUnsafe)
|
||||||
of "tlsemulation": processOnOffSwitchG(conf, {optTlsEmulation}, arg, pass, info)
|
of "tlsemulation": processOnOffSwitchG(conf, {optTlsEmulation}, arg, pass, info)
|
||||||
of "taintmode": processOnOffSwitchG(conf, {optTaintMode}, arg, pass, info)
|
of "taintmode": discard # pending https://github.com/nim-lang/Nim/issues/16731
|
||||||
of "implicitstatic":
|
of "implicitstatic":
|
||||||
processOnOffSwitch(conf, {optImplicitStatic}, arg, pass, info)
|
processOnOffSwitch(conf, {optImplicitStatic}, arg, pass, info)
|
||||||
of "patterns", "trmacros":
|
of "patterns", "trmacros":
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,6 @@ type # please make sure we have under 32 options
|
||||||
optThreads, # support for multi-threading
|
optThreads, # support for multi-threading
|
||||||
optStdout, # output to stdout
|
optStdout, # output to stdout
|
||||||
optThreadAnalysis, # thread analysis pass
|
optThreadAnalysis, # thread analysis pass
|
||||||
optTaintMode, # taint mode turned on
|
|
||||||
optTlsEmulation, # thread var emulation turned on
|
optTlsEmulation, # thread var emulation turned on
|
||||||
optGenIndex # generate index file for documentation;
|
optGenIndex # generate index file for documentation;
|
||||||
optEmbedOrigSrc # embed the original source in the generated code
|
optEmbedOrigSrc # embed the original source in the generated code
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,6 @@ Advanced options:
|
||||||
in the generated output
|
in the generated output
|
||||||
--threadanalysis:on|off turn thread analysis on|off
|
--threadanalysis:on|off turn thread analysis on|off
|
||||||
--tlsEmulation:on|off turn thread local storage emulation on|off
|
--tlsEmulation:on|off turn thread local storage emulation on|off
|
||||||
--taintMode:on|off turn taint mode on|off
|
|
||||||
--implicitStatic:on|off turn implicit compile time evaluation on|off
|
--implicitStatic:on|off turn implicit compile time evaluation on|off
|
||||||
--trmacros:on|off turn term rewriting macros on|off
|
--trmacros:on|off turn term rewriting macros on|off
|
||||||
--multimethods:on|off turn multi-methods on|off
|
--multimethods:on|off turn multi-methods on|off
|
||||||
|
|
|
||||||
|
|
@ -329,7 +329,7 @@ skLet
|
||||||
let
|
let
|
||||||
text = "some text"
|
text = "some text"
|
||||||
--> col 2: $MODULE.text
|
--> col 2: $MODULE.text
|
||||||
col 3: TaintedString
|
col 3: string
|
||||||
col 7: ""
|
col 7: ""
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1718,28 +1718,6 @@ e.g. with given example ``echo("ab")`` will be rewritten just once:
|
||||||
``noRewrite`` pragma can be useful to control term-rewriting macros recursion.
|
``noRewrite`` pragma can be useful to control term-rewriting macros recursion.
|
||||||
|
|
||||||
|
|
||||||
Taint mode
|
|
||||||
==========
|
|
||||||
|
|
||||||
The Nim compiler and most parts of the standard library support
|
|
||||||
a taint mode. Input strings are declared with the `TaintedString`:idx:
|
|
||||||
string type declared in the ``system`` module.
|
|
||||||
|
|
||||||
If the taint mode is turned on (via the ``--taintMode:on`` command line
|
|
||||||
option) it is a distinct string type which helps to detect input
|
|
||||||
validation errors:
|
|
||||||
|
|
||||||
.. code-block:: nim
|
|
||||||
echo "your name: "
|
|
||||||
var name: TaintedString = stdin.readline
|
|
||||||
# it is safe here to output the name without any input validation, so
|
|
||||||
# we simply convert `name` to string to make the compiler happy:
|
|
||||||
echo "hi, ", name.string
|
|
||||||
|
|
||||||
If the taint mode is turned off, ``TaintedString`` is simply an alias for
|
|
||||||
``string``.
|
|
||||||
|
|
||||||
|
|
||||||
Aliasing restrictions in parameter passing
|
Aliasing restrictions in parameter passing
|
||||||
==========================================
|
==========================================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ type
|
||||||
pos: int
|
pos: int
|
||||||
remainingShortOptions: string
|
remainingShortOptions: string
|
||||||
kind*: CmdLineKind ## the detected command line token
|
kind*: CmdLineKind ## the detected command line token
|
||||||
key*, val*: TaintedString ## key and value pair; ``key`` is the option
|
key*, val*: string ## key and value pair; ``key`` is the option
|
||||||
## or the argument, ``value`` is not "" if
|
## or the argument, ``value`` is not "" if
|
||||||
## the option was given a value
|
## the option was given a value
|
||||||
|
|
||||||
|
|
@ -80,7 +80,7 @@ proc nextOption(p: var OptParser, token: string, allowEmpty: bool) =
|
||||||
proc next(p: var OptParser) =
|
proc next(p: var OptParser) =
|
||||||
if p.remainingShortOptions.len != 0:
|
if p.remainingShortOptions.len != 0:
|
||||||
p.kind = cmdShortOption
|
p.kind = cmdShortOption
|
||||||
p.key = TaintedString(p.remainingShortOptions[0..0])
|
p.key = p.remainingShortOptions[0..0]
|
||||||
p.val = ""
|
p.val = ""
|
||||||
p.remainingShortOptions = p.remainingShortOptions[1..p.remainingShortOptions.len-1]
|
p.remainingShortOptions = p.remainingShortOptions[1..p.remainingShortOptions.len-1]
|
||||||
return
|
return
|
||||||
|
|
@ -103,13 +103,13 @@ proc next(p: var OptParser) =
|
||||||
p.key = token
|
p.key = token
|
||||||
p.val = ""
|
p.val = ""
|
||||||
|
|
||||||
proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo2$1".} =
|
proc cmdLineRest*(p: OptParser): string {.rtl, extern: "npo2$1".} =
|
||||||
## Returns the part of command line string that has not been parsed yet,
|
## Returns the part of command line string that has not been parsed yet,
|
||||||
## properly quoted.
|
## properly quoted.
|
||||||
return p.cmd[p.pos..p.cmd.len-1].quoteShellCommand
|
return p.cmd[p.pos..p.cmd.len-1].quoteShellCommand
|
||||||
|
|
||||||
type
|
type
|
||||||
GetoptResult* = tuple[kind: CmdLineKind, key, val: TaintedString]
|
GetoptResult* = tuple[kind: CmdLineKind, key, val: string]
|
||||||
|
|
||||||
iterator getopt*(p: var OptParser): GetoptResult =
|
iterator getopt*(p: var OptParser): GetoptResult =
|
||||||
## This is an convenience iterator for iterating over the given OptParser object.
|
## This is an convenience iterator for iterating over the given OptParser object.
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,13 @@
|
||||||
## echo userResponse
|
## echo userResponse
|
||||||
|
|
||||||
when defined(Windows):
|
when defined(Windows):
|
||||||
proc readLineFromStdin*(prompt: string): TaintedString {.
|
proc readLineFromStdin*(prompt: string): string {.
|
||||||
tags: [ReadIOEffect, WriteIOEffect].} =
|
tags: [ReadIOEffect, WriteIOEffect].} =
|
||||||
## Reads a line from stdin.
|
## Reads a line from stdin.
|
||||||
stdout.write(prompt)
|
stdout.write(prompt)
|
||||||
result = readLine(stdin)
|
result = readLine(stdin)
|
||||||
|
|
||||||
proc readLineFromStdin*(prompt: string, line: var TaintedString): bool {.
|
proc readLineFromStdin*(prompt: string, line: var string): bool {.
|
||||||
tags: [ReadIOEffect, WriteIOEffect].} =
|
tags: [ReadIOEffect, WriteIOEffect].} =
|
||||||
## Reads a `line` from stdin. `line` must not be
|
## Reads a `line` from stdin. `line` must not be
|
||||||
## ``nil``! May throw an IO exception.
|
## ``nil``! May throw an IO exception.
|
||||||
|
|
@ -40,35 +40,35 @@ when defined(Windows):
|
||||||
result = readLine(stdin, line)
|
result = readLine(stdin, line)
|
||||||
|
|
||||||
elif defined(genode):
|
elif defined(genode):
|
||||||
proc readLineFromStdin*(prompt: string): TaintedString {.
|
proc readLineFromStdin*(prompt: string): string {.
|
||||||
tags: [ReadIOEffect, WriteIOEffect].} =
|
tags: [ReadIOEffect, WriteIOEffect].} =
|
||||||
stdin.readLine()
|
stdin.readLine()
|
||||||
|
|
||||||
proc readLineFromStdin*(prompt: string, line: var TaintedString): bool {.
|
proc readLineFromStdin*(prompt: string, line: var string): bool {.
|
||||||
tags: [ReadIOEffect, WriteIOEffect].} =
|
tags: [ReadIOEffect, WriteIOEffect].} =
|
||||||
stdin.readLine(line)
|
stdin.readLine(line)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
import linenoise
|
import linenoise
|
||||||
|
|
||||||
proc readLineFromStdin*(prompt: string): TaintedString {.
|
proc readLineFromStdin*(prompt: string): string {.
|
||||||
tags: [ReadIOEffect, WriteIOEffect].} =
|
tags: [ReadIOEffect, WriteIOEffect].} =
|
||||||
var buffer = linenoise.readLine(prompt)
|
var buffer = linenoise.readLine(prompt)
|
||||||
if isNil(buffer):
|
if isNil(buffer):
|
||||||
raise newException(IOError, "Linenoise returned nil")
|
raise newException(IOError, "Linenoise returned nil")
|
||||||
result = TaintedString($buffer)
|
result = $buffer
|
||||||
if result.string.len > 0:
|
if result.len > 0:
|
||||||
historyAdd(buffer)
|
historyAdd(buffer)
|
||||||
linenoise.free(buffer)
|
linenoise.free(buffer)
|
||||||
|
|
||||||
proc readLineFromStdin*(prompt: string, line: var TaintedString): bool {.
|
proc readLineFromStdin*(prompt: string, line: var string): bool {.
|
||||||
tags: [ReadIOEffect, WriteIOEffect].} =
|
tags: [ReadIOEffect, WriteIOEffect].} =
|
||||||
var buffer = linenoise.readLine(prompt)
|
var buffer = linenoise.readLine(prompt)
|
||||||
if isNil(buffer):
|
if isNil(buffer):
|
||||||
line.string.setLen(0)
|
line.setLen(0)
|
||||||
return false
|
return false
|
||||||
line = TaintedString($buffer)
|
line = $buffer
|
||||||
if line.string.len > 0:
|
if line.len > 0:
|
||||||
historyAdd(buffer)
|
historyAdd(buffer)
|
||||||
linenoise.free(buffer)
|
linenoise.free(buffer)
|
||||||
result = true
|
result = true
|
||||||
|
|
|
||||||
|
|
@ -134,9 +134,9 @@ type
|
||||||
|
|
||||||
const multiLineLimit = 10000
|
const multiLineLimit = 10000
|
||||||
|
|
||||||
proc expectReply(ftp: AsyncFtpClient): Future[TaintedString] {.async.} =
|
proc expectReply(ftp: AsyncFtpClient): Future[string] {.async.} =
|
||||||
var line = await ftp.csock.recvLine()
|
var line = await ftp.csock.recvLine()
|
||||||
result = TaintedString(line)
|
result = line
|
||||||
var count = 0
|
var count = 0
|
||||||
while line.len > 3 and line[3] == '-':
|
while line.len > 3 and line[3] == '-':
|
||||||
## Multi-line reply.
|
## Multi-line reply.
|
||||||
|
|
@ -146,7 +146,7 @@ proc expectReply(ftp: AsyncFtpClient): Future[TaintedString] {.async.} =
|
||||||
if count >= multiLineLimit:
|
if count >= multiLineLimit:
|
||||||
raise newException(ReplyError, "Reached maximum multi-line reply count.")
|
raise newException(ReplyError, "Reached maximum multi-line reply count.")
|
||||||
|
|
||||||
proc send*(ftp: AsyncFtpClient, m: string): Future[TaintedString] {.async.} =
|
proc send*(ftp: AsyncFtpClient, m: string): Future[string] {.async.} =
|
||||||
## Send a message to the server, and wait for a primary reply.
|
## Send a message to the server, and wait for a primary reply.
|
||||||
## ``\c\L`` is added for you.
|
## ``\c\L`` is added for you.
|
||||||
##
|
##
|
||||||
|
|
@ -158,9 +158,9 @@ proc send*(ftp: AsyncFtpClient, m: string): Future[TaintedString] {.async.} =
|
||||||
await ftp.csock.send(m & "\c\L")
|
await ftp.csock.send(m & "\c\L")
|
||||||
return await ftp.expectReply()
|
return await ftp.expectReply()
|
||||||
|
|
||||||
proc assertReply(received: TaintedString, expected: varargs[string]) =
|
proc assertReply(received: string, expected: varargs[string]) =
|
||||||
for i in items(expected):
|
for i in items(expected):
|
||||||
if received.string.startsWith(i): return
|
if received.startsWith(i): return
|
||||||
raise newException(ReplyError,
|
raise newException(ReplyError,
|
||||||
"Expected reply '$1' got: $2" %
|
"Expected reply '$1' got: $2" %
|
||||||
[expected.join("' or '"), received.string])
|
[expected.join("' or '"), received.string])
|
||||||
|
|
@ -169,7 +169,7 @@ proc pasv(ftp: AsyncFtpClient) {.async.} =
|
||||||
## Negotiate a data connection.
|
## Negotiate a data connection.
|
||||||
ftp.dsock = newAsyncSocket()
|
ftp.dsock = newAsyncSocket()
|
||||||
|
|
||||||
var pasvMsg = (await ftp.send("PASV")).string.strip.TaintedString
|
var pasvMsg = (await ftp.send("PASV")).strip
|
||||||
assertReply(pasvMsg, "227")
|
assertReply(pasvMsg, "227")
|
||||||
var betweenParens = captureBetween(pasvMsg.string, '(', ')')
|
var betweenParens = captureBetween(pasvMsg.string, '(', ')')
|
||||||
var nums = betweenParens.split(',')
|
var nums = betweenParens.split(',')
|
||||||
|
|
@ -201,11 +201,11 @@ proc connect*(ftp: AsyncFtpClient) {.async.} =
|
||||||
if ftp.pass != "":
|
if ftp.pass != "":
|
||||||
assertReply(await(ftp.send("PASS " & ftp.pass)), "230")
|
assertReply(await(ftp.send("PASS " & ftp.pass)), "230")
|
||||||
|
|
||||||
proc pwd*(ftp: AsyncFtpClient): Future[TaintedString] {.async.} =
|
proc pwd*(ftp: AsyncFtpClient): Future[string] {.async.} =
|
||||||
## Returns the current working directory.
|
## Returns the current working directory.
|
||||||
let wd = await ftp.send("PWD")
|
let wd = await ftp.send("PWD")
|
||||||
assertReply wd, "257"
|
assertReply wd, "257"
|
||||||
return wd.string.captureBetween('"').TaintedString # "
|
return wd.captureBetween('"') # "
|
||||||
|
|
||||||
proc cd*(ftp: AsyncFtpClient, dir: string) {.async.} =
|
proc cd*(ftp: AsyncFtpClient, dir: string) {.async.} =
|
||||||
## Changes the current directory on the remote FTP server to ``dir``.
|
## Changes the current directory on the remote FTP server to ``dir``.
|
||||||
|
|
@ -253,7 +253,7 @@ proc createDir*(ftp: AsyncFtpClient, dir: string, recursive = false){.async.} =
|
||||||
if not recursive:
|
if not recursive:
|
||||||
assertReply(await(ftp.send("MKD " & dir.normalizePathSep)), "257")
|
assertReply(await(ftp.send("MKD " & dir.normalizePathSep)), "257")
|
||||||
else:
|
else:
|
||||||
var reply = TaintedString""
|
var reply = ""
|
||||||
var previousDirs = ""
|
var previousDirs = ""
|
||||||
for p in split(dir, {os.DirSep, os.AltSep}):
|
for p in split(dir, {os.DirSep, os.AltSep}):
|
||||||
if p != "":
|
if p != "":
|
||||||
|
|
|
||||||
|
|
@ -81,14 +81,14 @@ proc getEncodedData(allowedMethods: set[RequestMethod]): string =
|
||||||
if methodNone notin allowedMethods:
|
if methodNone notin allowedMethods:
|
||||||
cgiError("'REQUEST_METHOD' must be 'POST' or 'GET'")
|
cgiError("'REQUEST_METHOD' must be 'POST' or 'GET'")
|
||||||
|
|
||||||
iterator decodeData*(data: string): tuple[key, value: TaintedString] =
|
iterator decodeData*(data: string): tuple[key, value: string] =
|
||||||
## 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.
|
## data consists of.
|
||||||
for (key, value) in uri.decodeQuery(data):
|
for (key, value) in uri.decodeQuery(data):
|
||||||
yield (key, value)
|
yield (key, value)
|
||||||
|
|
||||||
iterator decodeData*(allowedMethods: set[RequestMethod] =
|
iterator decodeData*(allowedMethods: set[RequestMethod] =
|
||||||
{methodNone, methodPost, methodGet}): tuple[key, value: TaintedString] =
|
{methodNone, methodPost, methodGet}): tuple[key, value: string] =
|
||||||
## 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, a `CgiError` exception is raised.
|
## `allowedMethods` set, a `CgiError` exception is raised.
|
||||||
|
|
@ -301,10 +301,10 @@ proc setCookie*(name, value: string) =
|
||||||
var
|
var
|
||||||
gcookies {.threadvar.}: StringTableRef
|
gcookies {.threadvar.}: StringTableRef
|
||||||
|
|
||||||
proc getCookie*(name: string): TaintedString =
|
proc getCookie*(name: string): string =
|
||||||
## Gets a cookie. If no cookie of `name` exists, "" is returned.
|
## Gets a cookie. If no cookie of `name` exists, "" is returned.
|
||||||
if gcookies == nil: gcookies = parseCookies(getHttpCookie())
|
if gcookies == nil: gcookies = parseCookies(getHttpCookie())
|
||||||
result = TaintedString(gcookies.getOrDefault(name))
|
result = gcookies.getOrDefault(name)
|
||||||
|
|
||||||
proc existsCookie*(name: string): bool =
|
proc existsCookie*(name: string): bool =
|
||||||
## Checks if a cookie of `name` exists.
|
## Checks if a cookie of `name` exists.
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ when not declared(os) and not declared(ospaths):
|
||||||
{.error: "This is an include file for os.nim!".}
|
{.error: "This is an include file for os.nim!".}
|
||||||
|
|
||||||
when defined(nodejs):
|
when defined(nodejs):
|
||||||
proc getEnv*(key: string, default = ""): TaintedString {.tags: [ReadEnvEffect].} =
|
proc getEnv*(key: string, default = ""): string {.tags: [ReadEnvEffect].} =
|
||||||
var ret: cstring
|
var ret: cstring
|
||||||
let key2 = key.cstring
|
let key2 = key.cstring
|
||||||
{.emit: "`ret` = process.env[`key2`];".}
|
{.emit: "`ret` = process.env[`key2`];".}
|
||||||
|
|
@ -25,7 +25,7 @@ when defined(nodejs):
|
||||||
var key2 = key.cstring
|
var key2 = key.cstring
|
||||||
{.emit: "delete process.env[`key2`];".}
|
{.emit: "delete process.env[`key2`];".}
|
||||||
|
|
||||||
iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
|
iterator envPairs*(): tuple[key, value: string] {.tags: [ReadEnvEffect].} =
|
||||||
var num: int
|
var num: int
|
||||||
var keys: RootObj
|
var keys: RootObj
|
||||||
{.emit: "`keys` = Object.keys(process.env); `num` = `keys`.length;".}
|
{.emit: "`keys` = Object.keys(process.env); `num` = `keys`.length;".}
|
||||||
|
|
@ -144,7 +144,7 @@ else:
|
||||||
if startsWith(environment[i], temp): return i
|
if startsWith(environment[i], temp): return i
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
proc getEnv*(key: string, default = ""): TaintedString {.tags: [ReadEnvEffect].} =
|
proc getEnv*(key: string, default = ""): string {.tags: [ReadEnvEffect].} =
|
||||||
## Returns the value of the `environment variable`:idx: named `key`.
|
## Returns the value of the `environment variable`:idx: named `key`.
|
||||||
##
|
##
|
||||||
## If the variable does not exist, `""` is returned. To distinguish
|
## If the variable does not exist, `""` is returned. To distinguish
|
||||||
|
|
@ -165,11 +165,11 @@ else:
|
||||||
else:
|
else:
|
||||||
var i = findEnvVar(key)
|
var i = findEnvVar(key)
|
||||||
if i >= 0:
|
if i >= 0:
|
||||||
return TaintedString(substr(environment[i], find(environment[i], '=')+1))
|
return substr(environment[i], find(environment[i], '=')+1)
|
||||||
else:
|
else:
|
||||||
var env = c_getenv(key)
|
var env = c_getenv(key)
|
||||||
if env == nil: return TaintedString(default)
|
if env == nil: return default
|
||||||
result = TaintedString($env)
|
result = $env
|
||||||
|
|
||||||
proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
|
proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
|
||||||
## Checks whether the environment variable named `key` exists.
|
## Checks whether the environment variable named `key` exists.
|
||||||
|
|
@ -248,7 +248,7 @@ else:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
environment.delete(indx)
|
environment.delete(indx)
|
||||||
|
|
||||||
iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect].} =
|
iterator envPairs*(): tuple[key, value: string] {.tags: [ReadEnvEffect].} =
|
||||||
## Iterate over all `environments variables`:idx:.
|
## Iterate over all `environments variables`:idx:.
|
||||||
##
|
##
|
||||||
## In the first component of the tuple is the name of the current variable stored,
|
## In the first component of the tuple is the name of the current variable stored,
|
||||||
|
|
@ -262,5 +262,5 @@ else:
|
||||||
getEnvVarsC()
|
getEnvVarsC()
|
||||||
for i in 0..high(environment):
|
for i in 0..high(environment):
|
||||||
var p = find(environment[i], '=')
|
var p = find(environment[i], '=')
|
||||||
yield (TaintedString(substr(environment[i], 0, p-1)),
|
yield (substr(environment[i], 0, p-1),
|
||||||
TaintedString(substr(environment[i], p+1)))
|
substr(environment[i], p+1))
|
||||||
|
|
|
||||||
|
|
@ -428,17 +428,17 @@ iterator memSlices*(mfile: MemFile, delim = '\l', eat = '\r'): MemSlice {.inline
|
||||||
ms.data = cast[pointer](cast[int](ending) +% 1) # skip delim
|
ms.data = cast[pointer](cast[int](ending) +% 1) # skip delim
|
||||||
remaining = mfile.size - (ms.data -! mfile.mem)
|
remaining = mfile.size - (ms.data -! mfile.mem)
|
||||||
|
|
||||||
iterator lines*(mfile: MemFile, buf: var TaintedString, delim = '\l',
|
iterator lines*(mfile: MemFile, buf: var string, delim = '\l',
|
||||||
eat = '\r'): TaintedString {.inline.} =
|
eat = '\r'): string {.inline.} =
|
||||||
## Replace contents of passed buffer with each new line, like
|
## Replace contents of passed buffer with each new line, like
|
||||||
## `readLine(File) <io.html#readLine,File,TaintedString>`_.
|
## `readLine(File) <io.html#readLine,File,string>`_.
|
||||||
## `delim`, `eat`, and delimiting logic is exactly as for `memSlices
|
## `delim`, `eat`, and delimiting logic is exactly as for `memSlices
|
||||||
## <#memSlices.i,MemFile,char,char>`_, but Nim strings are returned.
|
## <#memSlices.i,MemFile,char,char>`_, but Nim strings are returned.
|
||||||
##
|
##
|
||||||
## Example:
|
## Example:
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
## var buffer: TaintedString = ""
|
## var buffer: string = ""
|
||||||
## for line in lines(memfiles.open("foo"), buffer):
|
## for line in lines(memfiles.open("foo"), buffer):
|
||||||
## echo line
|
## echo line
|
||||||
|
|
||||||
|
|
@ -448,7 +448,7 @@ iterator lines*(mfile: MemFile, buf: var TaintedString, delim = '\l',
|
||||||
copyMem(addr string(buf)[0], ms.data, ms.size)
|
copyMem(addr string(buf)[0], ms.data, ms.size)
|
||||||
yield buf
|
yield buf
|
||||||
|
|
||||||
iterator lines*(mfile: MemFile, delim = '\l', eat = '\r'): TaintedString {.inline.} =
|
iterator lines*(mfile: MemFile, delim = '\l', eat = '\r'): string {.inline.} =
|
||||||
## Return each line in a file as a Nim string, like
|
## Return each line in a file as a Nim string, like
|
||||||
## `lines(File) <io.html#lines.i,File>`_.
|
## `lines(File) <io.html#lines.i,File>`_.
|
||||||
## `delim`, `eat`, and delimiting logic is exactly as for `memSlices
|
## `delim`, `eat`, and delimiting logic is exactly as for `memSlices
|
||||||
|
|
@ -460,7 +460,7 @@ iterator lines*(mfile: MemFile, delim = '\l', eat = '\r'): TaintedString {.inlin
|
||||||
## for line in lines(memfiles.open("foo")):
|
## for line in lines(memfiles.open("foo")):
|
||||||
## echo line
|
## echo line
|
||||||
|
|
||||||
var buf = TaintedString(newStringOfCap(80))
|
var buf = newStringOfCap(80)
|
||||||
for line in lines(mfile, buf, delim, eat):
|
for line in lines(mfile, buf, delim, eat):
|
||||||
yield buf
|
yield buf
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1490,7 +1490,7 @@ proc peekChar(socket: Socket, c: var char): int {.tags: [ReadIOEffect].} =
|
||||||
return
|
return
|
||||||
result = recv(socket.fd, addr(c), 1, MSG_PEEK)
|
result = recv(socket.fd, addr(c), 1, MSG_PEEK)
|
||||||
|
|
||||||
proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
|
proc readLine*(socket: Socket, line: var string, timeout = -1,
|
||||||
flags = {SocketFlag.SafeDisconn}, maxLength = MaxLineLength) {.
|
flags = {SocketFlag.SafeDisconn}, maxLength = MaxLineLength) {.
|
||||||
tags: [ReadIOEffect, TimeEffect].} =
|
tags: [ReadIOEffect, TimeEffect].} =
|
||||||
## Reads a line of data from ``socket``.
|
## Reads a line of data from ``socket``.
|
||||||
|
|
@ -1548,7 +1548,7 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1,
|
||||||
|
|
||||||
proc recvLine*(socket: Socket, timeout = -1,
|
proc recvLine*(socket: Socket, timeout = -1,
|
||||||
flags = {SocketFlag.SafeDisconn},
|
flags = {SocketFlag.SafeDisconn},
|
||||||
maxLength = MaxLineLength): TaintedString =
|
maxLength = MaxLineLength): string =
|
||||||
## Reads a line of data from ``socket``.
|
## Reads a line of data from ``socket``.
|
||||||
##
|
##
|
||||||
## If a full line is read ``\r\L`` is not
|
## If a full line is read ``\r\L`` is not
|
||||||
|
|
@ -1566,7 +1566,7 @@ proc recvLine*(socket: Socket, timeout = -1,
|
||||||
## that can be read. The result is truncated after that.
|
## that can be read. The result is truncated after that.
|
||||||
##
|
##
|
||||||
## **Warning**: Only the ``SafeDisconn`` flag is currently supported.
|
## **Warning**: Only the ``SafeDisconn`` flag is currently supported.
|
||||||
result = "".TaintedString
|
result = ""
|
||||||
readLine(socket, result, timeout, flags, maxLength)
|
readLine(socket, result, timeout, flags, maxLength)
|
||||||
|
|
||||||
proc recvFrom*(socket: Socket, data: var string, length: int,
|
proc recvFrom*(socket: Socket, data: var string, length: int,
|
||||||
|
|
|
||||||
|
|
@ -2670,7 +2670,7 @@ when defined(nimdoc):
|
||||||
## else:
|
## else:
|
||||||
## # Do something else!
|
## # Do something else!
|
||||||
|
|
||||||
proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} =
|
proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
|
||||||
## Returns the `i`-th `command line argument`:idx: given to the application.
|
## Returns the `i`-th `command line argument`:idx: given to the application.
|
||||||
##
|
##
|
||||||
## `i` should be in the range `1..paramCount()`, the `IndexDefect`
|
## `i` should be in the range `1..paramCount()`, the `IndexDefect`
|
||||||
|
|
@ -2704,7 +2704,7 @@ when defined(nimdoc):
|
||||||
|
|
||||||
elif defined(nimscript): discard
|
elif defined(nimscript): discard
|
||||||
elif defined(nintendoswitch) or weirdTarget:
|
elif defined(nintendoswitch) or weirdTarget:
|
||||||
proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} =
|
proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
|
||||||
raise newException(OSError, "paramStr is not implemented on Nintendo Switch")
|
raise newException(OSError, "paramStr is not implemented on Nintendo Switch")
|
||||||
|
|
||||||
proc paramCount*(): int {.tags: [ReadIOEffect].} =
|
proc paramCount*(): int {.tags: [ReadIOEffect].} =
|
||||||
|
|
@ -2727,17 +2727,17 @@ elif defined(windows):
|
||||||
ownParsedArgv = true
|
ownParsedArgv = true
|
||||||
result = ownArgv.len-1
|
result = ownArgv.len-1
|
||||||
|
|
||||||
proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1",
|
proc paramStr*(i: int): string {.rtl, extern: "nos$1",
|
||||||
tags: [ReadIOEffect].} =
|
tags: [ReadIOEffect].} =
|
||||||
# Docstring in nimdoc block.
|
# Docstring in nimdoc block.
|
||||||
if not ownParsedArgv:
|
if not ownParsedArgv:
|
||||||
ownArgv = parseCmdLine($getCommandLine())
|
ownArgv = parseCmdLine($getCommandLine())
|
||||||
ownParsedArgv = true
|
ownParsedArgv = true
|
||||||
if i < ownArgv.len and i >= 0: return TaintedString(ownArgv[i])
|
if i < ownArgv.len and i >= 0: return ownArgv[i]
|
||||||
raise newException(IndexDefect, formatErrorIndexBound(i, ownArgv.len-1))
|
raise newException(IndexDefect, formatErrorIndexBound(i, ownArgv.len-1))
|
||||||
|
|
||||||
elif defined(genode):
|
elif defined(genode):
|
||||||
proc paramStr*(i: int): TaintedString =
|
proc paramStr*(i: int): string =
|
||||||
raise newException(OSError, "paramStr is not implemented on Genode")
|
raise newException(OSError, "paramStr is not implemented on Genode")
|
||||||
|
|
||||||
proc paramCount*(): int =
|
proc paramCount*(): int =
|
||||||
|
|
@ -2750,9 +2750,9 @@ elif not defined(createNimRtl) and
|
||||||
cmdCount {.importc: "cmdCount".}: cint
|
cmdCount {.importc: "cmdCount".}: cint
|
||||||
cmdLine {.importc: "cmdLine".}: cstringArray
|
cmdLine {.importc: "cmdLine".}: cstringArray
|
||||||
|
|
||||||
proc paramStr*(i: int): TaintedString {.tags: [ReadIOEffect].} =
|
proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =
|
||||||
# Docstring in nimdoc block.
|
# Docstring in nimdoc block.
|
||||||
if i < cmdCount and i >= 0: return TaintedString($cmdLine[i])
|
if i < cmdCount and i >= 0: return $cmdLine[i]
|
||||||
raise newException(IndexDefect, formatErrorIndexBound(i, cmdCount-1))
|
raise newException(IndexDefect, formatErrorIndexBound(i, cmdCount-1))
|
||||||
|
|
||||||
proc paramCount*(): int {.tags: [ReadIOEffect].} =
|
proc paramCount*(): int {.tags: [ReadIOEffect].} =
|
||||||
|
|
@ -2760,7 +2760,7 @@ elif not defined(createNimRtl) and
|
||||||
result = cmdCount-1
|
result = cmdCount-1
|
||||||
|
|
||||||
when declared(paramCount) or defined(nimdoc):
|
when declared(paramCount) or defined(nimdoc):
|
||||||
proc commandLineParams*(): seq[TaintedString] =
|
proc commandLineParams*(): seq[string] =
|
||||||
## Convenience proc which returns the command line parameters.
|
## Convenience proc which returns the command line parameters.
|
||||||
##
|
##
|
||||||
## This returns **only** the parameters. If you want to get the application
|
## This returns **only** the parameters. If you want to get the application
|
||||||
|
|
@ -2789,7 +2789,7 @@ when declared(paramCount) or defined(nimdoc):
|
||||||
for i in 1..paramCount():
|
for i in 1..paramCount():
|
||||||
result.add(paramStr(i))
|
result.add(paramStr(i))
|
||||||
else:
|
else:
|
||||||
proc commandLineParams*(): seq[TaintedString] {.error:
|
proc commandLineParams*(): seq[string] {.error:
|
||||||
"commandLineParams() unsupported by dynamic libraries".} =
|
"commandLineParams() unsupported by dynamic libraries".} =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ const poDemon* {.deprecated.} = poDaemon ## Nim versions before 0.20
|
||||||
proc execProcess*(command: string, workingDir: string = "",
|
proc execProcess*(command: string, workingDir: string = "",
|
||||||
args: openArray[string] = [], env: StringTableRef = nil,
|
args: openArray[string] = [], env: StringTableRef = nil,
|
||||||
options: set[ProcessOption] = {poStdErrToStdOut, poUsePath, poEvalCommand}):
|
options: set[ProcessOption] = {poStdErrToStdOut, poUsePath, poEvalCommand}):
|
||||||
TaintedString {.rtl, extern: "nosp$1",
|
string {.rtl, extern: "nosp$1",
|
||||||
tags: [ExecIOEffect, ReadIOEffect, RootEffect].}
|
tags: [ExecIOEffect, ReadIOEffect, RootEffect].}
|
||||||
## A convenience procedure that executes ``command`` with ``startProcess``
|
## A convenience procedure that executes ``command`` with ``startProcess``
|
||||||
## and returns its output as a string.
|
## and returns its output as a string.
|
||||||
|
|
@ -504,13 +504,13 @@ when not defined(useNimRtl):
|
||||||
args: openArray[string] = [], env: StringTableRef = nil,
|
args: openArray[string] = [], env: StringTableRef = nil,
|
||||||
options: set[ProcessOption] = {poStdErrToStdOut, poUsePath,
|
options: set[ProcessOption] = {poStdErrToStdOut, poUsePath,
|
||||||
poEvalCommand}):
|
poEvalCommand}):
|
||||||
TaintedString =
|
string =
|
||||||
|
|
||||||
var p = startProcess(command, workingDir = workingDir, args = args,
|
var p = startProcess(command, workingDir = workingDir, args = args,
|
||||||
env = env, options = options)
|
env = env, options = options)
|
||||||
var outp = outputStream(p)
|
var outp = outputStream(p)
|
||||||
result = TaintedString""
|
result = ""
|
||||||
var line = newStringOfCap(120).TaintedString
|
var line = newStringOfCap(120)
|
||||||
while true:
|
while true:
|
||||||
# FIXME: converts CR-LF to LF.
|
# FIXME: converts CR-LF to LF.
|
||||||
if outp.readLine(line):
|
if outp.readLine(line):
|
||||||
|
|
@ -1572,7 +1572,7 @@ elif not defined(useNimRtl):
|
||||||
proc execCmdEx*(command: string, options: set[ProcessOption] = {
|
proc execCmdEx*(command: string, options: set[ProcessOption] = {
|
||||||
poStdErrToStdOut, poUsePath}, env: StringTableRef = nil,
|
poStdErrToStdOut, poUsePath}, env: StringTableRef = nil,
|
||||||
workingDir = "", input = ""): tuple[
|
workingDir = "", input = ""): tuple[
|
||||||
output: TaintedString,
|
output: string,
|
||||||
exitCode: int] {.tags:
|
exitCode: int] {.tags:
|
||||||
[ExecIOEffect, ReadIOEffect, RootEffect], gcsafe.} =
|
[ExecIOEffect, ReadIOEffect, RootEffect], gcsafe.} =
|
||||||
## A convenience proc that runs the `command`, and returns its `output` and
|
## A convenience proc that runs the `command`, and returns its `output` and
|
||||||
|
|
@ -1619,8 +1619,8 @@ proc execCmdEx*(command: string, options: set[ProcessOption] = {
|
||||||
inputStream(p).write(input)
|
inputStream(p).write(input)
|
||||||
close inputStream(p)
|
close inputStream(p)
|
||||||
|
|
||||||
result = (TaintedString"", -1)
|
result = ("", -1)
|
||||||
var line = newStringOfCap(120).TaintedString
|
var line = newStringOfCap(120)
|
||||||
while true:
|
while true:
|
||||||
if outp.readLine(line):
|
if outp.readLine(line):
|
||||||
result[0].string.add(line.string)
|
result[0].string.add(line.string)
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ type
|
||||||
cmds: seq[string]
|
cmds: seq[string]
|
||||||
idx: int
|
idx: int
|
||||||
kind*: CmdLineKind ## The detected command line token
|
kind*: CmdLineKind ## The detected command line token
|
||||||
key*, val*: TaintedString ## Key and value pair; the key is the option
|
key*, val*: string ## Key and value pair; the key is the option
|
||||||
## or the argument, and the value is not "" if
|
## or the argument, and the value is not "" if
|
||||||
## the option was given a value
|
## the option was given a value
|
||||||
|
|
||||||
|
|
@ -231,10 +231,10 @@ when declared(os.paramCount):
|
||||||
result.cmds[i-1] = os.paramStr(i).string
|
result.cmds[i-1] = os.paramStr(i).string
|
||||||
|
|
||||||
result.kind = cmdEnd
|
result.kind = cmdEnd
|
||||||
result.key = TaintedString""
|
result.key = ""
|
||||||
result.val = TaintedString""
|
result.val = ""
|
||||||
|
|
||||||
proc initOptParser*(cmdline: seq[TaintedString], shortNoVal: set[char] = {},
|
proc initOptParser*(cmdline: seq[string], shortNoVal: set[char] = {},
|
||||||
longNoVal: seq[string] = @[];
|
longNoVal: seq[string] = @[];
|
||||||
allowWhitespaceAfterColon = true): OptParser =
|
allowWhitespaceAfterColon = true): OptParser =
|
||||||
## Initializes the command line parser.
|
## Initializes the command line parser.
|
||||||
|
|
@ -245,7 +245,7 @@ when declared(os.paramCount):
|
||||||
## <#initOptParser,string,set[char],seq[string]>`_.
|
## <#initOptParser,string,set[char],seq[string]>`_.
|
||||||
##
|
##
|
||||||
## See also:
|
## See also:
|
||||||
## * `getopt iterator<#getopt.i,seq[TaintedString],set[char],seq[string]>`_
|
## * `getopt iterator<#getopt.i,seq[string],set[char],seq[string]>`_
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var p = initOptParser()
|
var p = initOptParser()
|
||||||
p = initOptParser(@["--left", "--debug:3", "-l", "-r:2"])
|
p = initOptParser(@["--left", "--debug:3", "-l", "-r:2"])
|
||||||
|
|
@ -267,8 +267,8 @@ when declared(os.paramCount):
|
||||||
for i in countup(1, os.paramCount()):
|
for i in countup(1, os.paramCount()):
|
||||||
result.cmds[i-1] = os.paramStr(i).string
|
result.cmds[i-1] = os.paramStr(i).string
|
||||||
result.kind = cmdEnd
|
result.kind = cmdEnd
|
||||||
result.key = TaintedString""
|
result.key = ""
|
||||||
result.val = TaintedString""
|
result.val = ""
|
||||||
|
|
||||||
proc handleShortOption(p: var OptParser; cmd: string) =
|
proc handleShortOption(p: var OptParser; cmd: string) =
|
||||||
var i = p.pos
|
var i = p.pos
|
||||||
|
|
@ -286,7 +286,7 @@ proc handleShortOption(p: var OptParser; cmd: string) =
|
||||||
inc(i)
|
inc(i)
|
||||||
p.inShortState = false
|
p.inShortState = false
|
||||||
while i < cmd.len and cmd[i] in {'\t', ' '}: inc(i)
|
while i < cmd.len and cmd[i] in {'\t', ' '}: inc(i)
|
||||||
p.val = TaintedString substr(cmd, i)
|
p.val = substr(cmd, i)
|
||||||
p.pos = 0
|
p.pos = 0
|
||||||
inc p.idx
|
inc p.idx
|
||||||
else:
|
else:
|
||||||
|
|
@ -349,12 +349,12 @@ proc next*(p: var OptParser) {.rtl, extern: "npo$1".} =
|
||||||
inc p.idx
|
inc p.idx
|
||||||
i = 0
|
i = 0
|
||||||
if p.idx < p.cmds.len:
|
if p.idx < p.cmds.len:
|
||||||
p.val = TaintedString p.cmds[p.idx].substr(i)
|
p.val = p.cmds[p.idx].substr(i)
|
||||||
elif len(p.longNoVal) > 0 and p.key.string notin p.longNoVal and p.idx+1 < p.cmds.len:
|
elif len(p.longNoVal) > 0 and p.key.string notin p.longNoVal and p.idx+1 < p.cmds.len:
|
||||||
p.val = TaintedString p.cmds[p.idx+1]
|
p.val = p.cmds[p.idx+1]
|
||||||
inc p.idx
|
inc p.idx
|
||||||
else:
|
else:
|
||||||
p.val = TaintedString""
|
p.val = ""
|
||||||
inc p.idx
|
inc p.idx
|
||||||
p.pos = 0
|
p.pos = 0
|
||||||
else:
|
else:
|
||||||
|
|
@ -362,11 +362,11 @@ proc next*(p: var OptParser) {.rtl, extern: "npo$1".} =
|
||||||
handleShortOption(p, p.cmds[p.idx])
|
handleShortOption(p, p.cmds[p.idx])
|
||||||
else:
|
else:
|
||||||
p.kind = cmdArgument
|
p.kind = cmdArgument
|
||||||
p.key = TaintedString p.cmds[p.idx]
|
p.key = p.cmds[p.idx]
|
||||||
inc p.idx
|
inc p.idx
|
||||||
p.pos = 0
|
p.pos = 0
|
||||||
|
|
||||||
proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1".} =
|
proc cmdLineRest*(p: OptParser): string {.rtl, extern: "npo$1".} =
|
||||||
## Retrieves the rest of the command line that has not been parsed yet.
|
## Retrieves the rest of the command line that has not been parsed yet.
|
||||||
##
|
##
|
||||||
## See also:
|
## See also:
|
||||||
|
|
@ -382,9 +382,9 @@ proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1".} =
|
||||||
## break
|
## break
|
||||||
## else: continue
|
## else: continue
|
||||||
## doAssert p.cmdLineRest == "foo.txt bar.txt"
|
## doAssert p.cmdLineRest == "foo.txt bar.txt"
|
||||||
result = p.cmds[p.idx .. ^1].quoteShellCommand.TaintedString
|
result = p.cmds[p.idx .. ^1].quoteShellCommand
|
||||||
|
|
||||||
proc remainingArgs*(p: OptParser): seq[TaintedString] {.rtl, extern: "npo$1".} =
|
proc remainingArgs*(p: OptParser): seq[string] {.rtl, extern: "npo$1".} =
|
||||||
## Retrieves a sequence of the arguments that have not been parsed yet.
|
## Retrieves a sequence of the arguments that have not been parsed yet.
|
||||||
##
|
##
|
||||||
## See also:
|
## See also:
|
||||||
|
|
@ -401,10 +401,10 @@ proc remainingArgs*(p: OptParser): seq[TaintedString] {.rtl, extern: "npo$1".} =
|
||||||
## else: continue
|
## else: continue
|
||||||
## doAssert p.remainingArgs == @["foo.txt", "bar.txt"]
|
## doAssert p.remainingArgs == @["foo.txt", "bar.txt"]
|
||||||
result = @[]
|
result = @[]
|
||||||
for i in p.idx..<p.cmds.len: result.add TaintedString(p.cmds[i])
|
for i in p.idx..<p.cmds.len: result.add p.cmds[i]
|
||||||
|
|
||||||
iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key,
|
iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key,
|
||||||
val: TaintedString] =
|
val: string] =
|
||||||
## Convenience iterator for iterating over the given
|
## Convenience iterator for iterating over the given
|
||||||
## `OptParser<#OptParser>`_.
|
## `OptParser<#OptParser>`_.
|
||||||
##
|
##
|
||||||
|
|
@ -443,9 +443,9 @@ iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key,
|
||||||
yield (p.kind, p.key, p.val)
|
yield (p.kind, p.key, p.val)
|
||||||
|
|
||||||
when declared(initOptParser):
|
when declared(initOptParser):
|
||||||
iterator getopt*(cmdline: seq[TaintedString] = commandLineParams(),
|
iterator getopt*(cmdline: seq[string] = commandLineParams(),
|
||||||
shortNoVal: set[char] = {}, longNoVal: seq[string] = @[]):
|
shortNoVal: set[char] = {}, longNoVal: seq[string] = @[]):
|
||||||
tuple[kind: CmdLineKind, key, val: TaintedString] =
|
tuple[kind: CmdLineKind, key, val: string] =
|
||||||
## Convenience iterator for iterating over command line arguments.
|
## Convenience iterator for iterating over command line arguments.
|
||||||
##
|
##
|
||||||
## This creates a new `OptParser<#OptParser>`_. If no command line
|
## This creates a new `OptParser<#OptParser>`_. If no command line
|
||||||
|
|
@ -460,7 +460,7 @@ when declared(initOptParser):
|
||||||
## There is no need to check for ``cmdEnd`` while iterating.
|
## There is no need to check for ``cmdEnd`` while iterating.
|
||||||
##
|
##
|
||||||
## See also:
|
## See also:
|
||||||
## * `initOptParser proc<#initOptParser,seq[TaintedString],set[char],seq[string]>`_
|
## * `initOptParser proc<#initOptParser,seq[string],set[char],seq[string]>`_
|
||||||
##
|
##
|
||||||
## **Examples:**
|
## **Examples:**
|
||||||
##
|
##
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ proc debugSend*(smtp: Smtp | AsyncSmtp, cmd: string) {.multisync.} =
|
||||||
echo("C:" & cmd)
|
echo("C:" & cmd)
|
||||||
await smtp.sock.send(cmd)
|
await smtp.sock.send(cmd)
|
||||||
|
|
||||||
proc debugRecv*(smtp: Smtp | AsyncSmtp): Future[TaintedString] {.multisync.} =
|
proc debugRecv*(smtp: Smtp | AsyncSmtp): Future[string] {.multisync.} =
|
||||||
## Receives a line of data from the socket connected to the
|
## Receives a line of data from the socket connected to the
|
||||||
## SMTP server.
|
## SMTP server.
|
||||||
##
|
##
|
||||||
|
|
|
||||||
|
|
@ -96,8 +96,6 @@
|
||||||
|
|
||||||
import std/private/since
|
import std/private/since
|
||||||
|
|
||||||
const taintMode = compileOption("taintmode")
|
|
||||||
|
|
||||||
proc newEIO(msg: string): owned(ref IOError) =
|
proc newEIO(msg: string): owned(ref IOError) =
|
||||||
new(result)
|
new(result)
|
||||||
result.msg = msg
|
result.msg = msg
|
||||||
|
|
@ -124,7 +122,7 @@ type
|
||||||
readDataStrImpl*: proc (s: Stream, buffer: var string, slice: Slice[int]): int
|
readDataStrImpl*: proc (s: Stream, buffer: var string, slice: Slice[int]): int
|
||||||
{.nimcall, raises: [Defect, IOError, OSError], tags: [ReadIOEffect], gcsafe.}
|
{.nimcall, raises: [Defect, IOError, OSError], tags: [ReadIOEffect], gcsafe.}
|
||||||
|
|
||||||
readLineImpl*: proc(s: Stream, line: var TaintedString): bool
|
readLineImpl*: proc(s: Stream, line: var string): bool
|
||||||
{.nimcall, raises: [Defect, IOError, OSError], tags: [ReadIOEffect], gcsafe.}
|
{.nimcall, raises: [Defect, IOError, OSError], tags: [ReadIOEffect], gcsafe.}
|
||||||
|
|
||||||
readDataImpl*: proc (s: Stream, buffer: pointer, bufLen: int): int
|
readDataImpl*: proc (s: Stream, buffer: pointer, bufLen: int): int
|
||||||
|
|
@ -921,26 +919,20 @@ proc peekFloat64*(s: Stream): float64 =
|
||||||
|
|
||||||
peek(s, result)
|
peek(s, result)
|
||||||
|
|
||||||
template untaint(s: var TaintedString): var string =
|
proc readStrPrivate(s: Stream, length: int, str: var string) =
|
||||||
when taintMode: # for VM, bug #12282
|
if length > len(str): setLen(str, length)
|
||||||
s.string
|
|
||||||
else:
|
|
||||||
s
|
|
||||||
|
|
||||||
proc readStrPrivate(s: Stream, length: int, str: var TaintedString) =
|
|
||||||
if length > len(str): setLen(str.untaint, length)
|
|
||||||
when defined(js):
|
when defined(js):
|
||||||
let L = readData(s, addr(str), length)
|
let L = readData(s, addr(str), length)
|
||||||
else:
|
else:
|
||||||
let L = readData(s, cstring(str.string), length)
|
let L = readData(s, cstring(str.string), length)
|
||||||
if L != len(str): setLen(str.untaint, L)
|
if L != len(str): setLen(str, L)
|
||||||
|
|
||||||
proc readStr*(s: Stream, length: int, str: var TaintedString) {.since: (1, 3).} =
|
proc readStr*(s: Stream, length: int, str: var string) {.since: (1, 3).} =
|
||||||
## Reads a string of length `length` from the stream `s`. Raises `IOError` if
|
## Reads a string of length `length` from the stream `s`. Raises `IOError` if
|
||||||
## an error occurred.
|
## an error occurred.
|
||||||
readStrPrivate(s, length, str)
|
readStrPrivate(s, length, str)
|
||||||
|
|
||||||
proc readStr*(s: Stream, length: int): TaintedString =
|
proc readStr*(s: Stream, length: int): string =
|
||||||
## Reads a string of length `length` from the stream `s`. Raises `IOError` if
|
## Reads a string of length `length` from the stream `s`. Raises `IOError` if
|
||||||
## an error occurred.
|
## an error occurred.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
|
|
@ -950,23 +942,23 @@ proc readStr*(s: Stream, length: int): TaintedString =
|
||||||
doAssert strm.readStr(2) == "e"
|
doAssert strm.readStr(2) == "e"
|
||||||
doAssert strm.readStr(2) == ""
|
doAssert strm.readStr(2) == ""
|
||||||
strm.close()
|
strm.close()
|
||||||
result = newString(length).TaintedString
|
result = newString(length)
|
||||||
readStrPrivate(s, length, result)
|
readStrPrivate(s, length, result)
|
||||||
|
|
||||||
proc peekStrPrivate(s: Stream, length: int, str: var TaintedString) =
|
proc peekStrPrivate(s: Stream, length: int, str: var string) =
|
||||||
if length > len(str): setLen(str.untaint, length)
|
if length > len(str): setLen(str, length)
|
||||||
when defined(js):
|
when defined(js):
|
||||||
let L = peekData(s, addr(str), length)
|
let L = peekData(s, addr(str), length)
|
||||||
else:
|
else:
|
||||||
let L = peekData(s, cstring(str.string), length)
|
let L = peekData(s, cstring(str.string), length)
|
||||||
if L != len(str): setLen(str.untaint, L)
|
if L != len(str): setLen(str, L)
|
||||||
|
|
||||||
proc peekStr*(s: Stream, length: int, str: var TaintedString) {.since: (1, 3).} =
|
proc peekStr*(s: Stream, length: int, str: var string) {.since: (1, 3).} =
|
||||||
## Peeks a string of length `length` from the stream `s`. Raises `IOError` if
|
## Peeks a string of length `length` from the stream `s`. Raises `IOError` if
|
||||||
## an error occurred.
|
## an error occurred.
|
||||||
peekStrPrivate(s, length, str)
|
peekStrPrivate(s, length, str)
|
||||||
|
|
||||||
proc peekStr*(s: Stream, length: int): TaintedString =
|
proc peekStr*(s: Stream, length: int): string =
|
||||||
## Peeks a string of length `length` from the stream `s`. Raises `IOError` if
|
## Peeks a string of length `length` from the stream `s`. Raises `IOError` if
|
||||||
## an error occurred.
|
## an error occurred.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
|
|
@ -977,10 +969,10 @@ proc peekStr*(s: Stream, length: int): TaintedString =
|
||||||
doAssert strm.readStr(2) == "ab"
|
doAssert strm.readStr(2) == "ab"
|
||||||
doAssert strm.peekStr(2) == "cd"
|
doAssert strm.peekStr(2) == "cd"
|
||||||
strm.close()
|
strm.close()
|
||||||
result = newString(length).TaintedString
|
result = newString(length)
|
||||||
peekStrPrivate(s, length, result)
|
peekStrPrivate(s, length, result)
|
||||||
|
|
||||||
proc readLine*(s: Stream, line: var TaintedString): bool =
|
proc readLine*(s: Stream, line: var string): bool =
|
||||||
## Reads a line of text from the stream `s` into `line`. `line` must not be
|
## Reads a line of text from the stream `s` into `line`. `line` must not be
|
||||||
## ``nil``! May throw an IO exception.
|
## ``nil``! May throw an IO exception.
|
||||||
##
|
##
|
||||||
|
|
@ -992,7 +984,7 @@ proc readLine*(s: Stream, line: var TaintedString): bool =
|
||||||
## See also:
|
## See also:
|
||||||
## * `readLine(Stream) proc <#readLine,Stream>`_
|
## * `readLine(Stream) proc <#readLine,Stream>`_
|
||||||
## * `peekLine(Stream) proc <#peekLine,Stream>`_
|
## * `peekLine(Stream) proc <#peekLine,Stream>`_
|
||||||
## * `peekLine(Stream, TaintedString) proc <#peekLine,Stream,TaintedString>`_
|
## * `peekLine(Stream, string) proc <#peekLine,Stream,string>`_
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var strm = newStringStream("The first line\nthe second line\nthe third line")
|
var strm = newStringStream("The first line\nthe second line\nthe third line")
|
||||||
var line = ""
|
var line = ""
|
||||||
|
|
@ -1010,7 +1002,7 @@ proc readLine*(s: Stream, line: var TaintedString): bool =
|
||||||
result = s.readLineImpl(s, line)
|
result = s.readLineImpl(s, line)
|
||||||
else:
|
else:
|
||||||
# fallback
|
# fallback
|
||||||
line.untaint.setLen(0)
|
line.setLen(0)
|
||||||
while true:
|
while true:
|
||||||
var c = readChar(s)
|
var c = readChar(s)
|
||||||
if c == '\c':
|
if c == '\c':
|
||||||
|
|
@ -1020,10 +1012,10 @@ proc readLine*(s: Stream, line: var TaintedString): bool =
|
||||||
elif c == '\0':
|
elif c == '\0':
|
||||||
if line.len > 0: break
|
if line.len > 0: break
|
||||||
else: return false
|
else: return false
|
||||||
line.untaint.add(c)
|
line.add(c)
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc peekLine*(s: Stream, line: var TaintedString): bool =
|
proc peekLine*(s: Stream, line: var string): bool =
|
||||||
## Peeks a line of text from the stream `s` into `line`. `line` must not be
|
## Peeks a line of text from the stream `s` into `line`. `line` must not be
|
||||||
## ``nil``! May throw an IO exception.
|
## ``nil``! May throw an IO exception.
|
||||||
##
|
##
|
||||||
|
|
@ -1034,7 +1026,7 @@ proc peekLine*(s: Stream, line: var TaintedString): bool =
|
||||||
##
|
##
|
||||||
## See also:
|
## See also:
|
||||||
## * `readLine(Stream) proc <#readLine,Stream>`_
|
## * `readLine(Stream) proc <#readLine,Stream>`_
|
||||||
## * `readLine(Stream, TaintedString) proc <#readLine,Stream,TaintedString>`_
|
## * `readLine(Stream, string) proc <#readLine,Stream,string>`_
|
||||||
## * `peekLine(Stream) proc <#peekLine,Stream>`_
|
## * `peekLine(Stream) proc <#peekLine,Stream>`_
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var strm = newStringStream("The first line\nthe second line\nthe third line")
|
var strm = newStringStream("The first line\nthe second line\nthe third line")
|
||||||
|
|
@ -1054,15 +1046,15 @@ proc peekLine*(s: Stream, line: var TaintedString): bool =
|
||||||
defer: setPosition(s, pos)
|
defer: setPosition(s, pos)
|
||||||
result = readLine(s, line)
|
result = readLine(s, line)
|
||||||
|
|
||||||
proc readLine*(s: Stream): TaintedString =
|
proc readLine*(s: Stream): string =
|
||||||
## Reads a line from a stream `s`. Raises `IOError` if an error occurred.
|
## Reads a line from a stream `s`. Raises `IOError` if an error occurred.
|
||||||
##
|
##
|
||||||
## **Note:** This is not very efficient.
|
## **Note:** This is not very efficient.
|
||||||
##
|
##
|
||||||
## See also:
|
## See also:
|
||||||
## * `readLine(Stream, TaintedString) proc <#readLine,Stream,TaintedString>`_
|
## * `readLine(Stream, string) proc <#readLine,Stream,string>`_
|
||||||
## * `peekLine(Stream) proc <#peekLine,Stream>`_
|
## * `peekLine(Stream) proc <#peekLine,Stream>`_
|
||||||
## * `peekLine(Stream, TaintedString) proc <#peekLine,Stream,TaintedString>`_
|
## * `peekLine(Stream, string) proc <#peekLine,Stream,string>`_
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var strm = newStringStream("The first line\nthe second line\nthe third line")
|
var strm = newStringStream("The first line\nthe second line\nthe third line")
|
||||||
doAssert strm.readLine() == "The first line"
|
doAssert strm.readLine() == "The first line"
|
||||||
|
|
@ -1071,7 +1063,7 @@ proc readLine*(s: Stream): TaintedString =
|
||||||
doAssertRaises(IOError): discard strm.readLine()
|
doAssertRaises(IOError): discard strm.readLine()
|
||||||
strm.close()
|
strm.close()
|
||||||
|
|
||||||
result = TaintedString""
|
result = ""
|
||||||
if s.atEnd:
|
if s.atEnd:
|
||||||
raise newEIO("cannot read from stream")
|
raise newEIO("cannot read from stream")
|
||||||
while true:
|
while true:
|
||||||
|
|
@ -1082,17 +1074,17 @@ proc readLine*(s: Stream): TaintedString =
|
||||||
if c == '\L' or c == '\0':
|
if c == '\L' or c == '\0':
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
result.untaint.add(c)
|
result.add(c)
|
||||||
|
|
||||||
proc peekLine*(s: Stream): TaintedString =
|
proc peekLine*(s: Stream): string =
|
||||||
## Peeks a line from a stream `s`. Raises `IOError` if an error occurred.
|
## Peeks a line from a stream `s`. Raises `IOError` if an error occurred.
|
||||||
##
|
##
|
||||||
## **Note:** This is not very efficient.
|
## **Note:** This is not very efficient.
|
||||||
##
|
##
|
||||||
## See also:
|
## See also:
|
||||||
## * `readLine(Stream) proc <#readLine,Stream>`_
|
## * `readLine(Stream) proc <#readLine,Stream>`_
|
||||||
## * `readLine(Stream, TaintedString) proc <#readLine,Stream,TaintedString>`_
|
## * `readLine(Stream, string) proc <#readLine,Stream,string>`_
|
||||||
## * `peekLine(Stream, TaintedString) proc <#peekLine,Stream,TaintedString>`_
|
## * `peekLine(Stream, string) proc <#peekLine,Stream,string>`_
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var strm = newStringStream("The first line\nthe second line\nthe third line")
|
var strm = newStringStream("The first line\nthe second line\nthe third line")
|
||||||
doAssert strm.peekLine() == "The first line"
|
doAssert strm.peekLine() == "The first line"
|
||||||
|
|
@ -1106,13 +1098,13 @@ proc peekLine*(s: Stream): TaintedString =
|
||||||
defer: setPosition(s, pos)
|
defer: setPosition(s, pos)
|
||||||
result = readLine(s)
|
result = readLine(s)
|
||||||
|
|
||||||
iterator lines*(s: Stream): TaintedString =
|
iterator lines*(s: Stream): string =
|
||||||
## Iterates over every line in the stream.
|
## Iterates over every line in the stream.
|
||||||
## The iteration is based on ``readLine``.
|
## The iteration is based on ``readLine``.
|
||||||
##
|
##
|
||||||
## See also:
|
## See also:
|
||||||
## * `readLine(Stream) proc <#readLine,Stream>`_
|
## * `readLine(Stream) proc <#readLine,Stream>`_
|
||||||
## * `readLine(Stream, TaintedString) proc <#readLine,Stream,TaintedString>`_
|
## * `readLine(Stream, string) proc <#readLine,Stream,string>`_
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
var strm = newStringStream("The first line\nthe second line\nthe third line")
|
var strm = newStringStream("The first line\nthe second line\nthe third line")
|
||||||
var lines: seq[string]
|
var lines: seq[string]
|
||||||
|
|
@ -1121,7 +1113,7 @@ iterator lines*(s: Stream): TaintedString =
|
||||||
doAssert lines == @["The first line", "the second line", "the third line"]
|
doAssert lines == @["The first line", "the second line", "the third line"]
|
||||||
strm.close()
|
strm.close()
|
||||||
|
|
||||||
var line: TaintedString
|
var line: string
|
||||||
while s.readLine(line):
|
while s.readLine(line):
|
||||||
yield line
|
yield line
|
||||||
|
|
||||||
|
|
@ -1333,7 +1325,7 @@ proc fsWriteData(s: Stream, buffer: pointer, bufLen: int) =
|
||||||
if writeBuffer(FileStream(s).f, buffer, bufLen) != bufLen:
|
if writeBuffer(FileStream(s).f, buffer, bufLen) != bufLen:
|
||||||
raise newEIO("cannot write to stream")
|
raise newEIO("cannot write to stream")
|
||||||
|
|
||||||
proc fsReadLine(s: Stream, line: var TaintedString): bool =
|
proc fsReadLine(s: Stream, line: var string): bool =
|
||||||
result = readLine(FileStream(s).f, line)
|
result = readLine(FileStream(s).f, line)
|
||||||
|
|
||||||
proc newFileStream*(f: File): owned FileStream =
|
proc newFileStream*(f: File): owned FileStream =
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ type
|
||||||
baseReadLineImpl: typeof(StreamObj.readLineImpl)
|
baseReadLineImpl: typeof(StreamObj.readLineImpl)
|
||||||
baseReadDataImpl: typeof(StreamObj.readDataImpl)
|
baseReadDataImpl: typeof(StreamObj.readDataImpl)
|
||||||
|
|
||||||
proc posReadLine[T](s: Stream, line: var TaintedString): bool =
|
proc posReadLine[T](s: Stream, line: var string): bool =
|
||||||
var s = PipeOutStream[T](s)
|
var s = PipeOutStream[T](s)
|
||||||
assert s.baseReadLineImpl != nil
|
assert s.baseReadLineImpl != nil
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -771,7 +771,7 @@ proc getch*(): char =
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
from unicode import toUTF8, Rune, runeLenAt
|
from unicode import toUTF8, Rune, runeLenAt
|
||||||
|
|
||||||
proc readPasswordFromStdin*(prompt: string, password: var TaintedString):
|
proc readPasswordFromStdin*(prompt: string, password: var string):
|
||||||
bool {.tags: [ReadIOEffect, WriteIOEffect].} =
|
bool {.tags: [ReadIOEffect, WriteIOEffect].} =
|
||||||
## Reads a `password` from stdin without printing it. `password` must not
|
## Reads a `password` from stdin without printing it. `password` must not
|
||||||
## be ``nil``! Returns ``false`` if the end of the file has been reached,
|
## be ``nil``! Returns ``false`` if the end of the file has been reached,
|
||||||
|
|
@ -797,7 +797,7 @@ when defined(windows):
|
||||||
else:
|
else:
|
||||||
import termios
|
import termios
|
||||||
|
|
||||||
proc readPasswordFromStdin*(prompt: string, password: var TaintedString):
|
proc readPasswordFromStdin*(prompt: string, password: var string):
|
||||||
bool {.tags: [ReadIOEffect, WriteIOEffect].} =
|
bool {.tags: [ReadIOEffect, WriteIOEffect].} =
|
||||||
password.string.setLen(0)
|
password.string.setLen(0)
|
||||||
let fd = stdin.getFileHandle()
|
let fd = stdin.getFileHandle()
|
||||||
|
|
@ -811,9 +811,9 @@ else:
|
||||||
stdout.write "\n"
|
stdout.write "\n"
|
||||||
discard fd.tcSetAttr(TCSADRAIN, old.addr)
|
discard fd.tcSetAttr(TCSADRAIN, old.addr)
|
||||||
|
|
||||||
proc readPasswordFromStdin*(prompt = "password: "): TaintedString =
|
proc readPasswordFromStdin*(prompt = "password: "): string =
|
||||||
## Reads a password from stdin without printing it.
|
## Reads a password from stdin without printing it.
|
||||||
result = TaintedString("")
|
result = ""
|
||||||
discard readPasswordFromStdin(prompt, result)
|
discard readPasswordFromStdin(prompt, result)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ func encodeQuery*(query: openArray[(string, string)], usePlus = true,
|
||||||
result.add('=')
|
result.add('=')
|
||||||
result.add(encodeUrl(val, usePlus))
|
result.add(encodeUrl(val, usePlus))
|
||||||
|
|
||||||
iterator decodeQuery*(data: string): tuple[key, value: TaintedString] =
|
iterator decodeQuery*(data: string): tuple[key, value: string] =
|
||||||
## Reads and decodes query string `data` and yields the `(key, value)` pairs
|
## Reads and decodes query string `data` and yields the `(key, value)` pairs
|
||||||
## the data consists of. If compiled with `-d:nimLegacyParseQueryStrict`, an
|
## the data consists of. If compiled with `-d:nimLegacyParseQueryStrict`, an
|
||||||
## error is raised when there is an unencoded `=` character in a decoded
|
## error is raised when there is an unencoded `=` character in a decoded
|
||||||
|
|
@ -197,7 +197,7 @@ iterator decodeQuery*(data: string): tuple[key, value: TaintedString] =
|
||||||
i = parseData(data, i, value, '=')
|
i = parseData(data, i, value, '=')
|
||||||
else:
|
else:
|
||||||
i = parseData(data, i, value, '&')
|
i = parseData(data, i, value, '&')
|
||||||
yield (name.TaintedString, value.TaintedString)
|
yield (name, value)
|
||||||
if i < data.len:
|
if i < data.len:
|
||||||
when defined(nimLegacyParseQueryStrict):
|
when defined(nimLegacyParseQueryStrict):
|
||||||
if data[i] != '&':
|
if data[i] != '&':
|
||||||
|
|
|
||||||
|
|
@ -1084,7 +1084,6 @@ const
|
||||||
const
|
const
|
||||||
hasThreadSupport = compileOption("threads") and not defined(nimscript)
|
hasThreadSupport = compileOption("threads") and not defined(nimscript)
|
||||||
hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own
|
hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own
|
||||||
taintMode = compileOption("taintmode")
|
|
||||||
nimEnableCovariance* = defined(nimEnableCovariance) # or true
|
nimEnableCovariance* = defined(nimEnableCovariance) # or true
|
||||||
|
|
||||||
when hasThreadSupport and defined(tcc) and not compileOption("tlsEmulation"):
|
when hasThreadSupport and defined(tcc) and not compileOption("tlsEmulation"):
|
||||||
|
|
@ -1107,22 +1106,8 @@ when defined(boehmgc):
|
||||||
const boehmLib = "libgc.so.1"
|
const boehmLib = "libgc.so.1"
|
||||||
{.pragma: boehmGC, noconv, dynlib: boehmLib.}
|
{.pragma: boehmGC, noconv, dynlib: boehmLib.}
|
||||||
|
|
||||||
when taintMode:
|
type TaintedString* {.deprecated: "Deprecated since 1.5".} = string
|
||||||
type TaintedString* = distinct string ## A distinct string type that
|
|
||||||
## is `tainted`:idx:, see `taint mode
|
|
||||||
## <manual_experimental.html#taint-mode>`_
|
|
||||||
## for details. It is an alias for
|
|
||||||
## ``string`` if the taint mode is not
|
|
||||||
## turned on.
|
|
||||||
|
|
||||||
proc len*(s: TaintedString): int {.borrow.}
|
|
||||||
else:
|
|
||||||
type TaintedString* = string ## A distinct string type that
|
|
||||||
## is `tainted`:idx:, see `taint mode
|
|
||||||
## <manual_experimental.html#taint-mode>`_
|
|
||||||
## for details. It is an alias for
|
|
||||||
## ``string`` if the taint mode is not
|
|
||||||
## turned on.
|
|
||||||
|
|
||||||
when defined(profiler) and not defined(nimscript):
|
when defined(profiler) and not defined(nimscript):
|
||||||
proc nimProfile() {.compilerproc, noinline.}
|
proc nimProfile() {.compilerproc, noinline.}
|
||||||
|
|
|
||||||
|
|
@ -358,7 +358,7 @@ when defined(nimdoc) or (defined(posix) and not defined(nimscript)) or defined(w
|
||||||
result = setHandleInformation(cast[IoHandle](f), HANDLE_FLAG_INHERIT,
|
result = setHandleInformation(cast[IoHandle](f), HANDLE_FLAG_INHERIT,
|
||||||
inheritable.WinDWORD) != 0
|
inheritable.WinDWORD) != 0
|
||||||
|
|
||||||
proc readLine*(f: File, line: var TaintedString): bool {.tags: [ReadIOEffect],
|
proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
|
||||||
benign.} =
|
benign.} =
|
||||||
## reads a line of text from the file `f` into `line`. May throw an IO
|
## reads a line of text from the file `f` into `line`. May throw an IO
|
||||||
## exception.
|
## exception.
|
||||||
|
|
@ -420,15 +420,15 @@ proc readLine*(f: File, line: var TaintedString): bool {.tags: [ReadIOEffect],
|
||||||
if buffer[i].uint16 == 26: #Ctrl+Z
|
if buffer[i].uint16 == 26: #Ctrl+Z
|
||||||
close(f) #has the same effect as setting EOF
|
close(f) #has the same effect as setting EOF
|
||||||
if i == 0:
|
if i == 0:
|
||||||
line = TaintedString("")
|
line = ""
|
||||||
return false
|
return false
|
||||||
numberOfCharsRead = i
|
numberOfCharsRead = i
|
||||||
break
|
break
|
||||||
buffer[numberOfCharsRead] = 0.Utf16Char
|
buffer[numberOfCharsRead] = 0.Utf16Char
|
||||||
when defined(nimv2):
|
when defined(nimv2):
|
||||||
line = TaintedString($toWideCString(buffer))
|
line = $toWideCString(buffer)
|
||||||
else:
|
else:
|
||||||
line = TaintedString($buffer)
|
line = $buffer
|
||||||
return(true)
|
return(true)
|
||||||
|
|
||||||
var pos = 0
|
var pos = 0
|
||||||
|
|
@ -479,11 +479,11 @@ proc readLine*(f: File, line: var TaintedString): bool {.tags: [ReadIOEffect],
|
||||||
sp = 128 # read in 128 bytes at a time
|
sp = 128 # read in 128 bytes at a time
|
||||||
line.string.setLen(pos+sp)
|
line.string.setLen(pos+sp)
|
||||||
|
|
||||||
proc readLine*(f: File): TaintedString {.tags: [ReadIOEffect], benign.} =
|
proc readLine*(f: File): string {.tags: [ReadIOEffect], benign.} =
|
||||||
## reads a line of text from the file `f`. May throw an IO exception.
|
## reads a line of text from the file `f`. May throw an IO exception.
|
||||||
## A line of text may be delimited by ``LF`` or ``CRLF``. The newline
|
## A line of text may be delimited by ``LF`` or ``CRLF``. The newline
|
||||||
## character(s) are not part of the returned string.
|
## character(s) are not part of the returned string.
|
||||||
result = TaintedString(newStringOfCap(80))
|
result = newStringOfCap(80)
|
||||||
if not readLine(f, result): raiseEOF()
|
if not readLine(f, result): raiseEOF()
|
||||||
|
|
||||||
proc write*(f: File, i: int) {.tags: [WriteIOEffect], benign.} =
|
proc write*(f: File, i: int) {.tags: [WriteIOEffect], benign.} =
|
||||||
|
|
@ -563,7 +563,7 @@ proc readAllFile(file: File): string =
|
||||||
var len = rawFileSize(file)
|
var len = rawFileSize(file)
|
||||||
result = readAllFile(file, len)
|
result = readAllFile(file, len)
|
||||||
|
|
||||||
proc readAll*(file: File): TaintedString {.tags: [ReadIOEffect], benign.} =
|
proc readAll*(file: File): string {.tags: [ReadIOEffect], benign.} =
|
||||||
## Reads all data from the stream `file`.
|
## Reads all data from the stream `file`.
|
||||||
##
|
##
|
||||||
## Raises an IO exception in case of an error. It is an error if the
|
## Raises an IO exception in case of an error. It is an error if the
|
||||||
|
|
@ -576,9 +576,9 @@ proc readAll*(file: File): TaintedString {.tags: [ReadIOEffect], benign.} =
|
||||||
else:
|
else:
|
||||||
let len = rawFileSize(file)
|
let len = rawFileSize(file)
|
||||||
if len > 0:
|
if len > 0:
|
||||||
result = readAllFile(file, len).TaintedString
|
result = readAllFile(file, len)
|
||||||
else:
|
else:
|
||||||
result = readAllBuffer(file).TaintedString
|
result = readAllBuffer(file)
|
||||||
|
|
||||||
proc writeLine*[Ty](f: File, x: varargs[Ty, `$`]) {.inline,
|
proc writeLine*[Ty](f: File, x: varargs[Ty, `$`]) {.inline,
|
||||||
tags: [WriteIOEffect], benign.} =
|
tags: [WriteIOEffect], benign.} =
|
||||||
|
|
@ -841,7 +841,7 @@ when defined(windows) and appType == "console" and
|
||||||
discard setConsoleOutputCP(Utf8codepage)
|
discard setConsoleOutputCP(Utf8codepage)
|
||||||
discard setConsoleCP(Utf8codepage)
|
discard setConsoleCP(Utf8codepage)
|
||||||
|
|
||||||
proc readFile*(filename: string): TaintedString {.tags: [ReadIOEffect], benign.} =
|
proc readFile*(filename: string): string {.tags: [ReadIOEffect], benign.} =
|
||||||
## Opens a file named `filename` for reading, calls `readAll
|
## Opens a file named `filename` for reading, calls `readAll
|
||||||
## <#readAll,File>`_ and closes the file afterwards. Returns the string.
|
## <#readAll,File>`_ and closes the file afterwards. Returns the string.
|
||||||
## Raises an IO exception in case of an error. If you need to call
|
## Raises an IO exception in case of an error. If you need to call
|
||||||
|
|
@ -882,7 +882,7 @@ proc writeFile*(filename: string, content: openArray[byte]) {.since: (1, 1).} =
|
||||||
else:
|
else:
|
||||||
raise newException(IOError, "cannot open: " & filename)
|
raise newException(IOError, "cannot open: " & filename)
|
||||||
|
|
||||||
proc readLines*(filename: string, n: Natural): seq[TaintedString] =
|
proc readLines*(filename: string, n: Natural): seq[string] =
|
||||||
## read `n` lines from the file named `filename`. Raises an IO exception
|
## read `n` lines from the file named `filename`. Raises an IO exception
|
||||||
## in case of an error. Raises EOF if file does not contain at least `n` lines.
|
## in case of an error. Raises EOF if file does not contain at least `n` lines.
|
||||||
## Available at compile time. A line of text may be delimited by ``LF`` or ``CRLF``.
|
## Available at compile time. A line of text may be delimited by ``LF`` or ``CRLF``.
|
||||||
|
|
@ -890,7 +890,7 @@ proc readLines*(filename: string, n: Natural): seq[TaintedString] =
|
||||||
var f: File = nil
|
var f: File = nil
|
||||||
if open(f, filename):
|
if open(f, filename):
|
||||||
try:
|
try:
|
||||||
result = newSeq[TaintedString](n)
|
result = newSeq[string](n)
|
||||||
for i in 0 .. n - 1:
|
for i in 0 .. n - 1:
|
||||||
if not readLine(f, result[i]):
|
if not readLine(f, result[i]):
|
||||||
raiseEOF()
|
raiseEOF()
|
||||||
|
|
@ -899,10 +899,10 @@ proc readLines*(filename: string, n: Natural): seq[TaintedString] =
|
||||||
else:
|
else:
|
||||||
sysFatal(IOError, "cannot open: " & filename)
|
sysFatal(IOError, "cannot open: " & filename)
|
||||||
|
|
||||||
template readLines*(filename: string): seq[TaintedString] {.deprecated: "use readLines with two arguments".} =
|
template readLines*(filename: string): seq[string] {.deprecated: "use readLines with two arguments".} =
|
||||||
readLines(filename, 1)
|
readLines(filename, 1)
|
||||||
|
|
||||||
iterator lines*(filename: string): TaintedString {.tags: [ReadIOEffect].} =
|
iterator lines*(filename: string): string {.tags: [ReadIOEffect].} =
|
||||||
## Iterates over any line in the file named `filename`.
|
## Iterates over any line in the file named `filename`.
|
||||||
##
|
##
|
||||||
## If the file does not exist `IOError` is raised. The trailing newline
|
## If the file does not exist `IOError` is raised. The trailing newline
|
||||||
|
|
@ -918,12 +918,12 @@ iterator lines*(filename: string): TaintedString {.tags: [ReadIOEffect].} =
|
||||||
## writeFile(filename, buffer)
|
## writeFile(filename, buffer)
|
||||||
var f = open(filename, bufSize=8000)
|
var f = open(filename, bufSize=8000)
|
||||||
try:
|
try:
|
||||||
var res = TaintedString(newStringOfCap(80))
|
var res = newStringOfCap(80)
|
||||||
while f.readLine(res): yield res
|
while f.readLine(res): yield res
|
||||||
finally:
|
finally:
|
||||||
close(f)
|
close(f)
|
||||||
|
|
||||||
iterator lines*(f: File): TaintedString {.tags: [ReadIOEffect].} =
|
iterator lines*(f: File): string {.tags: [ReadIOEffect].} =
|
||||||
## Iterate over any line in the file `f`.
|
## Iterate over any line in the file `f`.
|
||||||
##
|
##
|
||||||
## The trailing newline character(s) are removed from the iterated lines.
|
## The trailing newline character(s) are removed from the iterated lines.
|
||||||
|
|
@ -936,5 +936,5 @@ iterator lines*(f: File): TaintedString {.tags: [ReadIOEffect].} =
|
||||||
## if letter == '0':
|
## if letter == '0':
|
||||||
## result.zeros += 1
|
## result.zeros += 1
|
||||||
## result.lines += 1
|
## result.lines += 1
|
||||||
var res = TaintedString(newStringOfCap(80))
|
var res = newStringOfCap(80)
|
||||||
while f.readLine(res): yield res
|
while f.readLine(res): yield res
|
||||||
|
|
|
||||||
|
|
@ -360,21 +360,21 @@ proc cppDefine*(define: string) =
|
||||||
## needs to be mangled.
|
## needs to be mangled.
|
||||||
builtin
|
builtin
|
||||||
|
|
||||||
proc stdinReadLine(): TaintedString {.
|
proc stdinReadLine(): string {.
|
||||||
tags: [ReadIOEffect], raises: [IOError].} =
|
tags: [ReadIOEffect], raises: [IOError].} =
|
||||||
builtin
|
builtin
|
||||||
|
|
||||||
proc stdinReadAll(): TaintedString {.
|
proc stdinReadAll(): string {.
|
||||||
tags: [ReadIOEffect], raises: [IOError].} =
|
tags: [ReadIOEffect], raises: [IOError].} =
|
||||||
builtin
|
builtin
|
||||||
|
|
||||||
proc readLineFromStdin*(): TaintedString {.raises: [IOError].} =
|
proc readLineFromStdin*(): string {.raises: [IOError].} =
|
||||||
## Reads a line of data from stdin - blocks until \n or EOF which happens when stdin is closed
|
## Reads a line of data from stdin - blocks until \n or EOF which happens when stdin is closed
|
||||||
log "readLineFromStdin":
|
log "readLineFromStdin":
|
||||||
result = stdinReadLine()
|
result = stdinReadLine()
|
||||||
checkError(EOFError)
|
checkError(EOFError)
|
||||||
|
|
||||||
proc readAllFromStdin*(): TaintedString {.raises: [IOError].} =
|
proc readAllFromStdin*(): string {.raises: [IOError].} =
|
||||||
## Reads all data from stdin - blocks until EOF which happens when stdin is closed
|
## Reads all data from stdin - blocks until EOF which happens when stdin is closed
|
||||||
log "readAllFromStdin":
|
log "readAllFromStdin":
|
||||||
result = stdinReadAll()
|
result = stdinReadAll()
|
||||||
|
|
|
||||||
|
|
@ -319,7 +319,7 @@ proc replTcp(x: ThreadParams) {.thread.} =
|
||||||
else:
|
else:
|
||||||
server.bindAddr(x.port, x.address)
|
server.bindAddr(x.port, x.address)
|
||||||
server.listen()
|
server.listen()
|
||||||
var inp = "".TaintedString
|
var inp = ""
|
||||||
var stdoutSocket: Socket
|
var stdoutSocket: Socket
|
||||||
while true:
|
while true:
|
||||||
accept(server, stdoutSocket)
|
accept(server, stdoutSocket)
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ proc doCaasCommand(session: var NimSession, command: string): string =
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
while true:
|
while true:
|
||||||
var line = TaintedString("")
|
var line = ""
|
||||||
if session.nim.outputStream.readLine(line):
|
if session.nim.outputStream.readLine(line):
|
||||||
if line.string == "": break
|
if line.string == "": break
|
||||||
result.add(line.string & "\n")
|
result.add(line.string & "\n")
|
||||||
|
|
@ -78,7 +78,7 @@ proc doProcCommand(session: var NimSession, command: string): string =
|
||||||
var
|
var
|
||||||
process = startProcess(NimBin, args = session.replaceVars(command).split)
|
process = startProcess(NimBin, args = session.replaceVars(command).split)
|
||||||
stream = outputStream(process)
|
stream = outputStream(process)
|
||||||
line = TaintedString("")
|
line = ""
|
||||||
|
|
||||||
result = ""
|
result = ""
|
||||||
while stream.readLine(line):
|
while stream.readLine(line):
|
||||||
|
|
@ -113,12 +113,12 @@ proc doScenario(script: string, output: Stream, mode: TRunMode, verbose: bool):
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
var f = open(script)
|
var f = open(script)
|
||||||
var project = TaintedString("")
|
var project = ""
|
||||||
|
|
||||||
if f.readLine(project):
|
if f.readLine(project):
|
||||||
var
|
var
|
||||||
s = startNimSession(script.parentDir / project.string, script, mode)
|
s = startNimSession(script.parentDir / project.string, script, mode)
|
||||||
tline = TaintedString("")
|
tline = ""
|
||||||
ln = 1
|
ln = 1
|
||||||
|
|
||||||
while f.readLine(tline):
|
while f.readLine(tline):
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ proc getFileDir(filename: string): string =
|
||||||
|
|
||||||
proc execCmdEx2(command: string, args: openArray[string]; workingDir, input: string = ""): tuple[
|
proc execCmdEx2(command: string, args: openArray[string]; workingDir, input: string = ""): tuple[
|
||||||
cmdLine: string,
|
cmdLine: string,
|
||||||
output: TaintedString,
|
output: string,
|
||||||
exitCode: int] {.tags:
|
exitCode: int] {.tags:
|
||||||
[ExecIOEffect, ReadIOEffect, RootEffect], gcsafe.} =
|
[ExecIOEffect, ReadIOEffect, RootEffect], gcsafe.} =
|
||||||
|
|
||||||
|
|
@ -122,7 +122,7 @@ proc execCmdEx2(command: string, args: openArray[string]; workingDir, input: str
|
||||||
close instream
|
close instream
|
||||||
|
|
||||||
result.exitCode = -1
|
result.exitCode = -1
|
||||||
var line = newStringOfCap(120).TaintedString
|
var line = newStringOfCap(120)
|
||||||
while true:
|
while true:
|
||||||
if outp.readLine(line):
|
if outp.readLine(line):
|
||||||
result.output.string.add(line.string)
|
result.output.string.add(line.string)
|
||||||
|
|
@ -161,7 +161,7 @@ proc callCompiler(cmdTemplate, filename, options, nimcache: string,
|
||||||
var x = newStringOfCap(120)
|
var x = newStringOfCap(120)
|
||||||
result.nimout = ""
|
result.nimout = ""
|
||||||
while true:
|
while true:
|
||||||
if outp.readLine(x.TaintedString):
|
if outp.readLine(x):
|
||||||
result.nimout.add(x & "\n")
|
result.nimout.add(x & "\n")
|
||||||
if x =~ pegOfInterest:
|
if x =~ pegOfInterest:
|
||||||
# `err` should contain the last error/warning message
|
# `err` should contain the last error/warning message
|
||||||
|
|
@ -210,7 +210,7 @@ proc callCCompiler(cmdTemplate, filename, options: string,
|
||||||
result.output = ""
|
result.output = ""
|
||||||
result.line = -1
|
result.line = -1
|
||||||
while true:
|
while true:
|
||||||
if outp.readLine(x.TaintedString):
|
if outp.readLine(x):
|
||||||
result.nimout.add(x & "\n")
|
result.nimout.add(x & "\n")
|
||||||
elif not running(p):
|
elif not running(p):
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ block :tmp:
|
||||||
try:
|
try:
|
||||||
var res
|
var res
|
||||||
try:
|
try:
|
||||||
res = TaintedString(newStringOfCap(80))
|
res = newStringOfCap(80)
|
||||||
block :tmp_1:
|
block :tmp_1:
|
||||||
while readLine(f, res):
|
while readLine(f, res):
|
||||||
x_cursor = res
|
x_cursor = res
|
||||||
|
|
|
||||||
|
|
@ -834,7 +834,7 @@ proc getBar(x: string): Bar =
|
||||||
Bar(foo: none[seq[Foo]](),
|
Bar(foo: none[seq[Foo]](),
|
||||||
s: "")
|
s: "")
|
||||||
|
|
||||||
proc fakeReadLine(): TaintedString = "hey"
|
proc fakeReadLine(): string = "hey"
|
||||||
|
|
||||||
echo getBar(fakeReadLine()) # causes error
|
echo getBar(fakeReadLine()) # causes error
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ proc unused =
|
||||||
iterator lineIter2*(filename: string): string {.closure.} =
|
iterator lineIter2*(filename: string): string {.closure.} =
|
||||||
var f = open(filename, bufSize=8000)
|
var f = open(filename, bufSize=8000)
|
||||||
defer: close(f) # <-- commenting defer "solves" the problem
|
defer: close(f) # <-- commenting defer "solves" the problem
|
||||||
var res = TaintedString(newStringOfCap(80))
|
var res = newStringOfCap(80)
|
||||||
while f.readLine(res): yield res
|
while f.readLine(res): yield res
|
||||||
|
|
||||||
proc unusedB =
|
proc unusedB =
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,7 @@ template raise_or_quit(exception, message: untyped) =
|
||||||
|
|
||||||
template run_custom_proc(parsed_parameter: Tparsed_parameter,
|
template run_custom_proc(parsed_parameter: Tparsed_parameter,
|
||||||
custom_validator: Tparameter_callback,
|
custom_validator: Tparameter_callback,
|
||||||
parameter: TaintedString) =
|
parameter: string) =
|
||||||
## Runs the custom validator if it is not nil.
|
## Runs the custom validator if it is not nil.
|
||||||
##
|
##
|
||||||
## Pass in the string of the parameter triggering the call. If the
|
## Pass in the string of the parameter triggering the call. If the
|
||||||
|
|
@ -318,7 +318,7 @@ proc echo_help*(expected: seq[Tparameter_specification] = @[],
|
||||||
|
|
||||||
|
|
||||||
proc parse*(expected: seq[Tparameter_specification] = @[],
|
proc parse*(expected: seq[Tparameter_specification] = @[],
|
||||||
type_of_positional_parameters = PK_STRING, args: seq[TaintedString] = @[],
|
type_of_positional_parameters = PK_STRING, args: seq[string] = @[],
|
||||||
bad_prefixes = @["-", "--"], end_of_options = "--",
|
bad_prefixes = @["-", "--"], end_of_options = "--",
|
||||||
quit_on_failure = true): Tcommandline_results =
|
quit_on_failure = true): Tcommandline_results =
|
||||||
## Parses parameters and returns results.
|
## Parses parameters and returns results.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import streams
|
import streams
|
||||||
from strutils import repeat
|
from strutils import repeat
|
||||||
|
|
||||||
proc readPaddedStr*(s: PStream, length: int, padChar = '\0'): TaintedString =
|
proc readPaddedStr*(s: PStream, length: int, padChar = '\0'): string =
|
||||||
var lastChr = length
|
var lastChr = length
|
||||||
result = s.readStr(length)
|
result = s.readStr(length)
|
||||||
while lastChr >= 0 and result[lastChr - 1] == padChar: dec(lastChr)
|
while lastChr >= 0 and result[lastChr - 1] == padChar: dec(lastChr)
|
||||||
|
|
@ -16,7 +16,7 @@ proc writePaddedStr*(s: PStream, str: string, length: int, padChar = '\0') =
|
||||||
else:
|
else:
|
||||||
s.write(str)
|
s.write(str)
|
||||||
|
|
||||||
proc readLEStr*(s: PStream): TaintedString =
|
proc readLEStr*(s: PStream): string =
|
||||||
var len = s.readInt16()
|
var len = s.readInt16()
|
||||||
result = s.readStr(len)
|
result = s.readStr(len)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ disabled: "appveyor"
|
||||||
|
|
||||||
import memfiles
|
import memfiles
|
||||||
var inp = memfiles.open("tests/stdlib/tmemlinesBuf.nim")
|
var inp = memfiles.open("tests/stdlib/tmemlinesBuf.nim")
|
||||||
var buffer: TaintedString = ""
|
var buffer: string = ""
|
||||||
var lineCount = 0
|
var lineCount = 0
|
||||||
for line in lines(inp, buffer):
|
for line in lines(inp, buffer):
|
||||||
lineCount += 1
|
lineCount += 1
|
||||||
|
|
|
||||||
|
|
@ -195,15 +195,15 @@ else: # main driver
|
||||||
# bugfix: windows stdin.close was a noop and led to blocking reads
|
# bugfix: windows stdin.close was a noop and led to blocking reads
|
||||||
proc startProcessTest(command: string, options: set[ProcessOption] = {
|
proc startProcessTest(command: string, options: set[ProcessOption] = {
|
||||||
poStdErrToStdOut, poUsePath}, input = ""): tuple[
|
poStdErrToStdOut, poUsePath}, input = ""): tuple[
|
||||||
output: TaintedString,
|
output: string,
|
||||||
exitCode: int] {.tags:
|
exitCode: int] {.tags:
|
||||||
[ExecIOEffect, ReadIOEffect, RootEffect], gcsafe.} =
|
[ExecIOEffect, ReadIOEffect, RootEffect], gcsafe.} =
|
||||||
var p = startProcess(command, options = options + {poEvalCommand})
|
var p = startProcess(command, options = options + {poEvalCommand})
|
||||||
var outp = outputStream(p)
|
var outp = outputStream(p)
|
||||||
if input.len > 0: inputStream(p).write(input)
|
if input.len > 0: inputStream(p).write(input)
|
||||||
close inputStream(p)
|
close inputStream(p)
|
||||||
result = (TaintedString"", -1)
|
result = ("", -1)
|
||||||
var line = newStringOfCap(120).TaintedString
|
var line = newStringOfCap(120)
|
||||||
while true:
|
while true:
|
||||||
if outp.readLine(line):
|
if outp.readLine(line):
|
||||||
result[0].string.add(line.string)
|
result[0].string.add(line.string)
|
||||||
|
|
@ -223,7 +223,7 @@ else: # main driver
|
||||||
p.inputStream.flush()
|
p.inputStream.flush()
|
||||||
var line = ""
|
var line = ""
|
||||||
var s: seq[string]
|
var s: seq[string]
|
||||||
while p.outputStream.readLine(line.TaintedString):
|
while p.outputStream.readLine(line):
|
||||||
s.add line
|
s.add line
|
||||||
doAssert s == @["10"]
|
doAssert s == @["10"]
|
||||||
|
|
||||||
|
|
@ -235,15 +235,15 @@ else: # main driver
|
||||||
deferScoped: p.close()
|
deferScoped: p.close()
|
||||||
do:
|
do:
|
||||||
var sout: seq[string]
|
var sout: seq[string]
|
||||||
while p.outputStream.readLine(x.TaintedString): sout.add x
|
while p.outputStream.readLine(x): sout.add x
|
||||||
doAssert sout == @["start ta_out", "to stdout", "to stdout", "to stderr", "to stderr", "to stdout", "to stdout", "end ta_out"]
|
doAssert sout == @["start ta_out", "to stdout", "to stdout", "to stderr", "to stderr", "to stdout", "to stdout", "end ta_out"]
|
||||||
block: # startProcess stderr (replaces old test `tstderr` + `ta_out`)
|
block: # startProcess stderr (replaces old test `tstderr` + `ta_out`)
|
||||||
var p = startProcess(output, dir, options={})
|
var p = startProcess(output, dir, options={})
|
||||||
deferScoped: p.close()
|
deferScoped: p.close()
|
||||||
do:
|
do:
|
||||||
var serr, sout: seq[string]
|
var serr, sout: seq[string]
|
||||||
while p.errorStream.readLine(x.TaintedString): serr.add x
|
while p.errorStream.readLine(x): serr.add x
|
||||||
while p.outputStream.readLine(x.TaintedString): sout.add x
|
while p.outputStream.readLine(x): sout.add x
|
||||||
doAssert serr == @["to stderr", "to stderr"]
|
doAssert serr == @["to stderr", "to stderr"]
|
||||||
doAssert sout == @["start ta_out", "to stdout", "to stdout", "to stdout", "to stdout", "end ta_out"]
|
doAssert sout == @["start ta_out", "to stdout", "to stdout", "to stdout", "to stdout", "end ta_out"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ proc exec(cmd: string) =
|
||||||
let status = execShellCmd(cmd)
|
let status = execShellCmd(cmd)
|
||||||
doAssert status == 0, cmd
|
doAssert status == 0, cmd
|
||||||
|
|
||||||
proc execEx(cmd: string): tuple[output: TaintedString, exitCode: int] =
|
proc execEx(cmd: string): tuple[output: string, exitCode: int] =
|
||||||
echo "deps.cmd: " & cmd
|
echo "deps.cmd: " & cmd
|
||||||
execCmdEx(cmd, {poStdErrToStdOut, poUsePath, poEvalCommand})
|
execCmdEx(cmd, {poStdErrToStdOut, poUsePath, poEvalCommand})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,12 +104,12 @@ Microsoft (R) C/C++ Optimizing Compiler if no secondary
|
||||||
command was specified
|
command was specified
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc parseVccexeCmdLine(argseq: seq[TaintedString],
|
proc parseVccexeCmdLine(argseq: seq[string],
|
||||||
vccversionArg: var seq[string], printPathArg: var bool,
|
vccversionArg: var seq[string], printPathArg: var bool,
|
||||||
vcvarsallArg: var string, commandArg: var string, noCommandArg: var bool,
|
vcvarsallArg: var string, commandArg: var string, noCommandArg: var bool,
|
||||||
platformArg: var VccArch, sdkTypeArg: var VccPlatformType,
|
platformArg: var VccArch, sdkTypeArg: var VccPlatformType,
|
||||||
sdkVersionArg: var string, verboseArg: var bool,
|
sdkVersionArg: var string, verboseArg: var bool,
|
||||||
clArgs: var seq[TaintedString]) =
|
clArgs: var seq[string]) =
|
||||||
## Cannot use usual command-line argument parser here
|
## Cannot use usual command-line argument parser here
|
||||||
## Since vccexe command-line arguments are intermingled
|
## Since vccexe command-line arguments are intermingled
|
||||||
## with the secondary command-line arguments which have
|
## with the secondary command-line arguments which have
|
||||||
|
|
@ -160,7 +160,7 @@ when isMainModule:
|
||||||
var sdkVersionArg: string
|
var sdkVersionArg: string
|
||||||
var verboseArg: bool = false
|
var verboseArg: bool = false
|
||||||
|
|
||||||
var clArgs: seq[TaintedString] = @[]
|
var clArgs: seq[string] = @[]
|
||||||
|
|
||||||
let wrapperArgs = commandLineParams()
|
let wrapperArgs = commandLineParams()
|
||||||
parseVccexeCmdLine(wrapperArgs, vccversionArg, printPathArg, vcvarsallArg,
|
parseVccexeCmdLine(wrapperArgs, vccversionArg, printPathArg, vcvarsallArg,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue