fixes merge conflict

This commit is contained in:
Andreas Rumpf
2018-05-26 19:09:02 +02:00
16 changed files with 235 additions and 213 deletions

View File

@@ -42,8 +42,7 @@ proc newLine(p: var TTmplParser) =
proc scanPar(p: var TTmplParser, d: int) =
var i = d
let hi = p.x.len - 1
while i <= hi:
while i < p.x.len:
case p.x[i]
of '(': inc(p.par)
of ')': dec(p.par)
@@ -63,22 +62,19 @@ const
proc parseLine(p: var TTmplParser) =
var j = 0
let hi = p.x.len - 1
let len = p.x.len
if hi == 0:
return
while j < len and p.x[j] == ' ': inc(j)
while j <= hi and p.x[j] == ' ': inc(j)
if p.x.len >= 2 and p.x[0] == p.nimDirective and p.x[1] == '?':
if len >= 2 and p.x[0] == p.nimDirective and p.x[1] == '?':
newLine(p)
elif j < p.x.len and p.x[j] == p.nimDirective:
elif j < len and p.x[j] == p.nimDirective:
newLine(p)
inc(j)
while j <= hi and p.x[j] == ' ': inc(j)
while j < len and p.x[j] == ' ': inc(j)
let d = j
var keyw = ""
while j <= hi and p.x[j] in PatternChars:
while j < len and p.x[j] in PatternChars:
add(keyw, p.x[j])
inc(j)
@@ -132,7 +128,7 @@ proc parseLine(p: var TTmplParser) =
llStreamWrite(p.outp, "(\"")
inc(p.emitPar)
p.state = psTempl
while j <= hi:
while j < len:
case p.x[j]
of '\x01'..'\x1F', '\x80'..'\xFF':
llStreamWrite(p.outp, "\\x")
@@ -160,7 +156,7 @@ proc parseLine(p: var TTmplParser) =
llStreamWrite(p.outp, '(')
inc(j)
var curly = 0
while j <= hi:
while j < len:
case p.x[j]
of '{':
inc(j)
@@ -185,7 +181,7 @@ proc parseLine(p: var TTmplParser) =
llStreamWrite(p.outp, p.conc)
llStreamWrite(p.outp, p.toStr)
llStreamWrite(p.outp, '(')
while j <= hi and p.x[j] in PatternChars:
while j < len and p.x[j] in PatternChars:
llStreamWrite(p.outp, p.x[j])
inc(j)
llStreamWrite(p.outp, ')')

View File

@@ -263,7 +263,8 @@ proc newConfigRef*(): ConfigRef =
linkOptions: "",
compileOptions: "",
ccompilerpath: "",
toCompile: @[]
toCompile: @[],
arguments: ""
)
setTargetFromSystem(result.target)
# enable colors by default on terminals
@@ -562,20 +563,6 @@ proc isDynlibOverride*(conf: ConfigRef; lib: string): bool =
result = optDynlibOverrideAll in conf.globalOptions or
conf.dllOverrides.hasKey(lib.canonDynlibName)
proc binaryStrSearch*(x: openArray[string], y: string): int =
var a = 0
var b = len(x) - 1
while a <= b:
var mid = (a + b) div 2
var c = cmpIgnoreCase(x[mid], y)
if c < 0:
a = mid + 1
elif c > 0:
b = mid - 1
else:
return mid
result = - 1
proc parseIdeCmd*(s: string): IdeCmd =
case s:
of "sug": ideSug

View File

@@ -13,6 +13,7 @@
import
strutils
from algorithm import binarySearch
type
TokenClass* = enum
@@ -365,32 +366,10 @@ proc generalStrLit(g: var GeneralTokenizer, position: int): int =
result = pos
proc isKeyword(x: openArray[string], y: string): int =
var a = 0
var b = len(x) - 1
while a <= b:
var mid = (a + b) div 2
var c = cmp(x[mid], y)
if c < 0:
a = mid + 1
elif c > 0:
b = mid - 1
else:
return mid
result = - 1
binarySearch(x, y)
proc isKeywordIgnoreCase(x: openArray[string], y: string): int =
var a = 0
var b = len(x) - 1
while a <= b:
var mid = (a + b) div 2
var c = cmpIgnoreCase(x[mid], y)
if c < 0:
a = mid + 1
elif c > 0:
b = mid - 1
else:
return mid
result = - 1
binarySearch(x, y, cmpIgnoreCase)
type
TokenizerFlag = enum

View File

@@ -208,6 +208,7 @@ proc nextSplitPoint*(s: string, start: int): int =
dec(result) # last valid index
proc esc*(target: OutputTarget, s: string, splitAfter = -1): string =
## Escapes the HTML.
result = ""
if splitAfter >= 0:
var partLen = 0
@@ -769,43 +770,45 @@ proc renderTocEntries*(d: var RstGenerator, j: var int, lvl: int,
result.add(tmp)
proc renderImage(d: PDoc, n: PRstNode, result: var string) =
template valid(s): bool =
s.len > 0 and allCharsInSet(s, {'.','/',':','%','_','\\','\128'..'\xFF'} +
Digits + Letters + WhiteSpace)
let
arg = getArgument(n)
isObject = arg.toLowerAscii().endsWith(".svg")
var
options = ""
content = ""
var s = getFieldValue(n, "scale")
if s.valid: dispA(d.target, options, if isObject: "" else: " scale=\"$1\"",
" scale=$1", [strip(s)])
s = getFieldValue(n, "height")
if s.valid: dispA(d.target, options, " height=\"$1\"", " height=$1", [strip(s)])
var s = esc(d.target, getFieldValue(n, "scale").strip())
if s.len > 0:
dispA(d.target, options, " scale=\"$1\"", " scale=$1", [s])
s = getFieldValue(n, "width")
if s.valid: dispA(d.target, options, " width=\"$1\"", " width=$1", [strip(s)])
s = esc(d.target, getFieldValue(n, "height").strip())
if s.len > 0:
dispA(d.target, options, " height=\"$1\"", " height=$1", [s])
s = getFieldValue(n, "alt")
if s.valid:
# <object> displays its content if it cannot render the image
if isObject: dispA(d.target, content, "$1", "", [strip(s)])
else: dispA(d.target, options, " alt=\"$1\"", "", [strip(s)])
s = esc(d.target, getFieldValue(n, "width").strip())
if s.len > 0:
dispA(d.target, options, " width=\"$1\"", " width=$1", [s])
s = getFieldValue(n, "align")
if s.valid: dispA(d.target, options, " align=\"$1\"", "", [strip(s)])
s = esc(d.target, getFieldValue(n, "alt").strip())
if s.len > 0:
dispA(d.target, options, " alt=\"$1\"", "", [s])
s = esc(d.target, getFieldValue(n, "align").strip())
if s.len > 0:
dispA(d.target, options, " align=\"$1\"", "", [s])
if options.len > 0: options = dispF(d.target, "$1", "[$1]", [options])
if arg.valid:
let htmlOut = if isObject:
"<object data=\"$1\" type=\"image/svg+xml\"$2 >" & content & "</object>"
else:
"<img src=\"$1\"$2 />"
dispA(d.target, result, htmlOut, "\\includegraphics$2{$1}",
[arg, options])
var htmlOut = ""
if arg.endsWith(".mp4") or arg.endsWith(".ogg") or
arg.endsWith(".webm"):
htmlOut = """
<video src="$1"$2 autoPlay='true' loop='true' muted='true'>
Sorry, your browser doesn't support embedded videos
</video>
"""
else:
htmlOut = "<img src=\"$1\"$2/>"
dispA(d.target, result, htmlOut, "\\includegraphics$2{$1}",
[esc(d.target, arg), options])
if len(n) >= 3: renderRstToOut(d, n.sons[2], result)
proc renderSmiley(d: PDoc, n: PRstNode, result: var string) =
@@ -881,7 +884,8 @@ proc buildLinesHTMLTable(d: PDoc; params: CodeBlockParams, code: string):
inc d.listingCounter
let id = $d.listingCounter
if not params.numberLines:
result = (d.config.getOrDefault"doc.listing_start" % [id, $params.lang],
result = (d.config.getOrDefault"doc.listing_start" %
[id, sourceLanguageToStr[params.lang]],
d.config.getOrDefault"doc.listing_end" % id)
return
@@ -894,7 +898,8 @@ proc buildLinesHTMLTable(d: PDoc; params: CodeBlockParams, code: string):
line.inc
codeLines.dec
result.beginTable.add("</pre></td><td>" & (
d.config.getOrDefault"doc.listing_start" % [id, $params.lang]))
d.config.getOrDefault"doc.listing_start" %
[id, sourceLanguageToStr[params.lang]]))
result.endTable = (d.config.getOrDefault"doc.listing_end" % id) &
"</td></tr></tbody></table>" & (
d.config.getOrDefault"doc.listing_button" % id)
@@ -944,7 +949,7 @@ proc renderCodeBlock(d: PDoc, n: PRstNode, result: var string) =
proc renderContainer(d: PDoc, n: PRstNode, result: var string) =
var tmp = ""
renderRstToOut(d, n.sons[2], tmp)
var arg = strip(getArgument(n))
var arg = esc(d.target, strip(getArgument(n)))
if arg == "":
dispA(d.target, result, "<div>$1</div>", "$1", [tmp])
else:

View File

@@ -84,17 +84,27 @@ proc binarySearch*[T, K](a: openArray[T], key: K,
if (len and (len - 1)) == 0:
# when `len` is a power of 2, a faster shr can be used.
var step = len shr 1
var cmpRes: int
while step > 0:
let i = result or step
if cmp(a[i], key) < 1:
cmpRes = cmp(a[i], key)
if cmpRes == 0:
return i
if cmpRes < 1:
result = i
step = step shr 1
if cmp(a[result], key) != 0: result = -1
else:
var b = len
var cmpRes: int
while result < b:
var mid = (result + b) shr 1
if cmp(a[mid], key) < 0:
cmpRes = cmp(a[mid], key)
if cmpRes == 0:
return mid
if cmpRes < 0:
result = mid + 1
else:
b = mid

View File

@@ -10,6 +10,7 @@
## the ``graphics`` module.
import strutils
from algorithm import binarySearch
type
Color* = distinct int ## a color stored as RGB
@@ -371,37 +372,28 @@ proc `$`*(c: Color): string =
## converts a color into its textual representation. Example: ``#00FF00``.
result = '#' & toHex(int(c), 6)
proc binaryStrSearch(x: openArray[tuple[name: string, col: Color]],
y: string): int =
var a = 0
var b = len(x) - 1
while a <= b:
var mid = (a + b) div 2
var c = cmp(x[mid].name, y)
if c < 0: a = mid + 1
elif c > 0: b = mid - 1
else: return mid
result = - 1
proc colorNameCmp(x: tuple[name: string, col: Color], y: string): int =
result = cmpIgnoreCase(x.name, y)
proc parseColor*(name: string): Color =
## parses `name` to a color value. If no valid color could be
## parsed ``EInvalidValue`` is raised.
## parsed ``EInvalidValue`` is raised. Case insensitive.
if name[0] == '#':
result = Color(parseHexInt(name))
else:
var idx = binaryStrSearch(colorNames, name)
var idx = binarySearch(colorNames, name, colorNameCmp)
if idx < 0: raise newException(ValueError, "unknown color: " & name)
result = colorNames[idx][1]
proc isColor*(name: string): bool =
## returns true if `name` is a known color name or a hexadecimal color
## prefixed with ``#``.
## prefixed with ``#``. Case insensitive.
if name[0] == '#':
for i in 1 .. name.len-1:
if name[i] notin {'0'..'9', 'a'..'f', 'A'..'F'}: return false
result = true
else:
result = binaryStrSearch(colorNames, name) >= 0
result = binarySearch(colorNames, name, colorNameCmp) >= 0
proc rgb*(r, g, b: range[0..255]): Color =
## constructs a color from RGB values.

View File

@@ -362,15 +362,13 @@ when not defined(ssl):
type SSLContext = ref object
var defaultSSLContext {.threadvar.}: SSLContext
when defined(ssl):
defaultSSLContext = newContext(verifyMode = CVerifyNone)
template contextOrDefault(ctx: SSLContext): SSLContext =
var result = ctx
if ctx == nil:
if defaultSSLContext == nil:
defaultSSLContext = newContext(verifyMode = CVerifyNone)
proc getDefaultSSL(): SSLContext =
result = defaultSslContext
when defined(ssl):
if result == nil:
defaultSSLContext = newContext(verifyMode = CVerifyNone)
result = defaultSSLContext
result
doAssert result != nil, "failure to initialize the SSL context"
proc newProxy*(url: string, auth = ""): Proxy =
## Constructs a new ``TProxy`` object.
@@ -480,9 +478,9 @@ proc format(p: MultipartData): tuple[contentType, body: string] =
result.body.add("--" & bound & "--\c\L")
proc request*(url: string, httpMethod: string, extraHeaders = "",
body = "", sslContext = defaultSSLContext, timeout = -1,
body = "", sslContext = getDefaultSSL(), timeout = -1,
userAgent = defUserAgent, proxy: Proxy = nil): Response
{.deprecated.} =
{.deprecated: "use HttpClient.request instead".} =
## | Requests ``url`` with the custom method string specified by the
## | ``httpMethod`` parameter.
## | Extra headers can be specified and must be separated by ``\c\L``
@@ -580,7 +578,7 @@ proc request*(url: string, httpMethod: string, extraHeaders = "",
result = parseResponse(s, httpMethod != "HEAD", timeout)
proc request*(url: string, httpMethod = HttpGET, extraHeaders = "",
body = "", sslContext = defaultSSLContext, timeout = -1,
body = "", sslContext = getDefaultSSL(), timeout = -1,
userAgent = defUserAgent, proxy: Proxy = nil): Response
{.deprecated.} =
## | Requests ``url`` with the specified ``httpMethod``.
@@ -611,7 +609,7 @@ proc getNewLocation(lastURL: string, headers: HttpHeaders): string =
result = $parsed
proc get*(url: string, extraHeaders = "", maxRedirects = 5,
sslContext: SSLContext = defaultSSLContext,
sslContext: SSLContext = getDefaultSSL(),
timeout = -1, userAgent = defUserAgent,
proxy: Proxy = nil): Response {.deprecated.} =
## | GETs the ``url`` and returns a ``Response`` object
@@ -632,7 +630,7 @@ proc get*(url: string, extraHeaders = "", maxRedirects = 5,
lastURL = redirectTo
proc getContent*(url: string, extraHeaders = "", maxRedirects = 5,
sslContext: SSLContext = defaultSSLContext,
sslContext: SSLContext = getDefaultSSL(),
timeout = -1, userAgent = defUserAgent,
proxy: Proxy = nil): string {.deprecated.} =
## | GETs the body and returns it as a string.
@@ -651,7 +649,7 @@ proc getContent*(url: string, extraHeaders = "", maxRedirects = 5,
proc post*(url: string, extraHeaders = "", body = "",
maxRedirects = 5,
sslContext: SSLContext = defaultSSLContext,
sslContext: SSLContext = getDefaultSSL(),
timeout = -1, userAgent = defUserAgent,
proxy: Proxy = nil,
multipart: MultipartData = nil): Response {.deprecated.} =
@@ -694,7 +692,7 @@ proc post*(url: string, extraHeaders = "", body = "",
proc postContent*(url: string, extraHeaders = "", body = "",
maxRedirects = 5,
sslContext: SSLContext = defaultSSLContext,
sslContext: SSLContext = getDefaultSSL(),
timeout = -1, userAgent = defUserAgent,
proxy: Proxy = nil,
multipart: MultipartData = nil): string
@@ -717,7 +715,7 @@ proc postContent*(url: string, extraHeaders = "", body = "",
return r.body
proc downloadFile*(url: string, outputFilename: string,
sslContext: SSLContext = defaultSSLContext,
sslContext: SSLContext = getDefaultSSL(),
timeout = -1, userAgent = defUserAgent,
proxy: Proxy = nil) {.deprecated.} =
## | Downloads ``url`` and saves it to ``outputFilename``
@@ -817,7 +815,7 @@ type
HttpClient* = HttpClientBase[Socket]
proc newHttpClient*(userAgent = defUserAgent,
maxRedirects = 5, sslContext = defaultSslContext, proxy: Proxy = nil,
maxRedirects = 5, sslContext = getDefaultSSL(), proxy: Proxy = nil,
timeout = -1): HttpClient =
## Creates a new HttpClient instance.
##
@@ -844,7 +842,7 @@ proc newHttpClient*(userAgent = defUserAgent,
result.bodyStream = newStringStream()
result.getBody = true
when defined(ssl):
result.sslContext = contextOrDefault(sslContext)
result.sslContext = sslContext
type
AsyncHttpClient* = HttpClientBase[AsyncSocket]
@@ -852,7 +850,7 @@ type
{.deprecated: [PAsyncHttpClient: AsyncHttpClient].}
proc newAsyncHttpClient*(userAgent = defUserAgent,
maxRedirects = 5, sslContext = defaultSslContext,
maxRedirects = 5, sslContext = getDefaultSSL(),
proxy: Proxy = nil): AsyncHttpClient =
## Creates a new AsyncHttpClient instance.
##
@@ -876,7 +874,7 @@ proc newAsyncHttpClient*(userAgent = defUserAgent,
result.bodyStream = newFutureStream[string]("newAsyncHttpClient")
result.getBody = true
when defined(ssl):
result.sslContext = contextOrDefault(sslContext)
result.sslContext = sslContext
proc close*(client: HttpClient | AsyncHttpClient) =
## Closes any connections held by the HTTP client.

View File

@@ -1010,14 +1010,18 @@ proc replace*(s: string, sub: Peg, cb: proc(
inc(m)
add(result, substr(s, i))
proc transformFile*(infile, outfile: string,
subs: varargs[tuple[pattern: Peg, repl: string]]) {.
rtl, extern: "npegs$1".} =
## reads in the file `infile`, performs a parallel replacement (calls
## `parallelReplace`) and writes back to `outfile`. Raises ``EIO`` if an
## error occurs. This is supposed to be used for quick scripting.
var x = readFile(infile).string
writeFile(outfile, x.parallelReplace(subs))
when not defined(js):
proc transformFile*(infile, outfile: string,
subs: varargs[tuple[pattern: Peg, repl: string]]) {.
rtl, extern: "npegs$1".} =
## reads in the file `infile`, performs a parallel replacement (calls
## `parallelReplace`) and writes back to `outfile`. Raises ``EIO`` if an
## error occurs. This is supposed to be used for quick scripting.
##
## **Note**: this proc does not exist while using the JS backend.
var x = readFile(infile).string
writeFile(outfile, x.parallelReplace(subs))
iterator split*(s: string, sep: Peg): string =
## Splits the string `s` into substrings.
@@ -1121,7 +1125,7 @@ proc handleCR(L: var PegLexer, pos: int): int =
assert(L.buf[pos] == '\c')
inc(L.lineNumber)
result = pos+1
if L.buf[result] == '\L': inc(result)
if result < L.buf.len and L.buf[result] == '\L': inc(result)
L.lineStart = result
proc handleLF(L: var PegLexer, pos: int): int =
@@ -1217,12 +1221,13 @@ proc getEscapedChar(c: var PegLexer, tok: var Token) =
proc skip(c: var PegLexer) =
var pos = c.bufpos
var buf = c.buf
while true:
while pos < c.buf.len:
case buf[pos]
of ' ', '\t':
inc(pos)
of '#':
while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
while (pos < c.buf.len) and
not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
of '\c':
pos = handleCR(c, pos)
buf = c.buf
@@ -1238,7 +1243,7 @@ proc getString(c: var PegLexer, tok: var Token) =
var pos = c.bufpos + 1
var buf = c.buf
var quote = buf[pos-1]
while true:
while pos < c.buf.len:
case buf[pos]
of '\\':
c.bufpos = pos
@@ -1261,7 +1266,7 @@ proc getDollar(c: var PegLexer, tok: var Token) =
if buf[pos] in {'0'..'9'}:
tok.kind = tkBackref
tok.index = 0
while buf[pos] in {'0'..'9'}:
while pos < c.buf.len and buf[pos] in {'0'..'9'}:
tok.index = tok.index * 10 + ord(buf[pos]) - ord('0')
inc(pos)
else:
@@ -1277,11 +1282,11 @@ proc getCharSet(c: var PegLexer, tok: var Token) =
if buf[pos] == '^':
inc(pos)
caret = true
while true:
while pos < c.buf.len:
var ch: char
case buf[pos]
of ']':
inc(pos)
if pos < c.buf.len: inc(pos)
break
of '\\':
c.bufpos = pos
@@ -1296,11 +1301,14 @@ proc getCharSet(c: var PegLexer, tok: var Token) =
inc(pos)
incl(tok.charset, ch)
if buf[pos] == '-':
if buf[pos+1] == ']':
if pos+1 < c.buf.len and buf[pos+1] == ']':
incl(tok.charset, '-')
inc(pos)
else:
inc(pos)
if pos+1 < c.buf.len:
inc(pos)
else:
break
var ch2: char
case buf[pos]
of '\\':
@@ -1312,8 +1320,11 @@ proc getCharSet(c: var PegLexer, tok: var Token) =
tok.kind = tkInvalid
break
else:
ch2 = buf[pos]
inc(pos)
if pos+1 < c.buf.len:
ch2 = buf[pos]
inc(pos)
else:
break
for i in ord(ch)+1 .. ord(ch2):
incl(tok.charset, chr(i))
c.bufpos = pos
@@ -1322,15 +1333,15 @@ proc getCharSet(c: var PegLexer, tok: var Token) =
proc getSymbol(c: var PegLexer, tok: var Token) =
var pos = c.bufpos
var buf = c.buf
while true:
while pos < c.buf.len:
add(tok.literal, buf[pos])
inc(pos)
if buf[pos] notin strutils.IdentChars: break
if pos < buf.len and buf[pos] notin strutils.IdentChars: break
c.bufpos = pos
tok.kind = tkIdentifier
proc getBuiltin(c: var PegLexer, tok: var Token) =
if c.buf[c.bufpos+1] in strutils.Letters:
if c.bufpos+1 < c.buf.len and c.buf[c.bufpos+1] in strutils.Letters:
inc(c.bufpos)
getSymbol(c, tok)
tok.kind = tkBuiltin
@@ -1343,10 +1354,12 @@ proc getTok(c: var PegLexer, tok: var Token) =
tok.modifier = modNone
setLen(tok.literal, 0)
skip(c)
case c.buf[c.bufpos]
of '{':
inc(c.bufpos)
if c.buf[c.bufpos] == '@' and c.buf[c.bufpos+1] == '}':
if c.buf[c.bufpos] == '@' and c.bufpos+2 < c.buf.len and
c.buf[c.bufpos+1] == '}':
tok.kind = tkCurlyAt
inc(c.bufpos, 2)
add(tok.literal, "{@}")
@@ -1379,13 +1392,11 @@ proc getTok(c: var PegLexer, tok: var Token) =
getBuiltin(c, tok)
of '\'', '"': getString(c, tok)
of '$': getDollar(c, tok)
of '\0':
tok.kind = tkEof
tok.literal = "[EOF]"
of 'a'..'z', 'A'..'Z', '\128'..'\255':
getSymbol(c, tok)
if c.buf[c.bufpos] in {'\'', '"'} or
c.buf[c.bufpos] == '$' and c.buf[c.bufpos+1] in {'0'..'9'}:
c.buf[c.bufpos] == '$' and c.bufpos+1 < c.buf.len and
c.buf[c.bufpos+1] in {'0'..'9'}:
case tok.literal
of "i": tok.modifier = modIgnoreCase
of "y": tok.modifier = modIgnoreStyle
@@ -1406,7 +1417,7 @@ proc getTok(c: var PegLexer, tok: var Token) =
inc(c.bufpos)
add(tok.literal, '+')
of '<':
if c.buf[c.bufpos+1] == '-':
if c.bufpos+2 < c.buf.len and c.buf[c.bufpos+1] == '-':
inc(c.bufpos, 2)
tok.kind = tkArrow
add(tok.literal, "<-")
@@ -1441,14 +1452,17 @@ proc getTok(c: var PegLexer, tok: var Token) =
inc(c.bufpos)
add(tok.literal, '^')
else:
if c.bufpos >= c.buf.len:
tok.kind = tkEof
tok.literal = "[EOF]"
add(tok.literal, c.buf[c.bufpos])
inc(c.bufpos)
proc arrowIsNextTok(c: PegLexer): bool =
# the only look ahead we need
var pos = c.bufpos
while c.buf[pos] in {'\t', ' '}: inc(pos)
result = c.buf[pos] == '<' and c.buf[pos+1] == '-'
while pos < c.buf.len and c.buf[pos] in {'\t', ' '}: inc(pos)
result = c.buf[pos] == '<' and (pos+1 < c.buf.len) and c.buf[pos+1] == '-'
# ----------------------------- parser ----------------------------------------
@@ -1471,7 +1485,7 @@ proc pegError(p: PegParser, msg: string, line = -1, col = -1) =
proc getTok(p: var PegParser) =
getTok(p, p.tok)
if p.tok.kind == tkInvalid: pegError(p, "invalid token")
if p.tok.kind == tkInvalid: pegError(p, "'" & p.tok.literal & "' is invalid token")
proc eat(p: var PegParser, kind: TokKind) =
if p.tok.kind == kind: getTok(p)

View File

@@ -86,18 +86,20 @@ proc readData*(s: Stream, buffer: pointer, bufLen: int): int =
## low level proc that reads data into an untyped `buffer` of `bufLen` size.
result = s.readDataImpl(s, buffer, bufLen)
proc readAll*(s: Stream): string =
## Reads all available data.
const bufferSize = 1000
result = newString(bufferSize)
var r = 0
while true:
let readBytes = readData(s, addr(result[r]), bufferSize)
if readBytes < bufferSize:
setLen(result, r+readBytes)
break
inc r, bufferSize
setLen(result, r+bufferSize)
when not defined(js):
proc readAll*(s: Stream): string =
## Reads all available data.
const bufferSize = 1024
var buffer {.noinit.}: array[bufferSize, char]
while true:
let readBytes = readData(s, addr(buffer[0]), bufferSize)
if readBytes == 0:
break
let prevLen = result.len
result.setLen(prevLen + readBytes)
copyMem(addr(result[prevLen]), addr(buffer[0]), readBytes)
if readBytes < bufferSize:
break
proc peekData*(s: Stream, buffer: pointer, bufLen: int): int =
## low level proc that reads data into an untyped `buffer` of `bufLen` size
@@ -131,7 +133,7 @@ proc write*(s: Stream, x: string) =
when nimvm:
writeData(s, cstring(x), x.len)
else:
if x.len > 0: writeData(s, unsafeAddr x[0], x.len)
if x.len > 0: writeData(s, cstring(x), x.len)
proc writeLine*(s: Stream, args: varargs[string, `$`]) =
## writes one or more strings to the the stream `s` followed
@@ -251,14 +253,14 @@ proc readStr*(s: Stream, length: int): TaintedString =
## reads a string of length `length` from the stream `s`. Raises `EIO` if
## an error occurred.
result = newString(length).TaintedString
var L = readData(s, addr(string(result)[0]), length)
var L = readData(s, cstring(result), length)
if L != length: setLen(result.string, L)
proc peekStr*(s: Stream, length: int): TaintedString =
## peeks a string of length `length` from the stream `s`. Raises `EIO` if
## an error occurred.
result = newString(length).TaintedString
var L = peekData(s, addr(string(result)[0]), length)
var L = peekData(s, cstring(result), length)
if L != length: setLen(result.string, L)
proc readLine*(s: Stream, line: var TaintedString): bool =

View File

@@ -9,7 +9,7 @@
## A simple XML tree. More efficient and simpler than the DOM.
import macros, strtabs
import macros, strtabs, strutils
type
XmlNode* = ref XmlNodeObj ## an XML tree consists of ``XmlNode``'s.
@@ -217,8 +217,9 @@ proc escape*(s: string): string =
result = newStringOfCap(s.len)
addEscaped(result, s)
proc addIndent(result: var string, indent: int) =
result.add("\n")
proc addIndent(result: var string, indent: int, addNewLines: bool) =
if addNewLines:
result.add("\n")
for i in 1..indent: result.add(' ')
proc noWhitespace(n: XmlNode): bool =
@@ -227,7 +228,8 @@ proc noWhitespace(n: XmlNode): bool =
for i in 0..n.len-1:
if n[i].kind in {xnText, xnEntity}: return true
proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
addNewLines=true) =
## adds the textual representation of `n` to `result`.
proc addEscapedAttr(result: var string, s: string) =
@@ -260,14 +262,15 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2) =
# for mixed leaves, we cannot output whitespace for readability,
# because this would be wrong. For example: ``a<b>b</b>`` is
# different from ``a <b>b</b>``.
for i in 0..n.len-1: result.add(n[i], indent+indWidth, indWidth)
for i in 0..n.len-1:
result.add(n[i], indent+indWidth, indWidth, addNewLines)
else:
for i in 0..n.len-1:
result.addIndent(indent+indWidth)
result.add(n[i], indent+indWidth, indWidth)
result.addIndent(indent)
result.addIndent(indent+indWidth, addNewLines)
result.add(n[i], indent+indWidth, indWidth, addNewLines)
result.addIndent(indent, addNewLines)
else:
result.add(n[0], indent+indWidth, indWidth)
result.add(n[0], indent+indWidth, indWidth, addNewLines)
result.add("</")
result.add(n.fTag)
result.add(">")
@@ -316,7 +319,10 @@ proc xmlConstructor(a: NimNode): NimNode {.compileTime.} =
var elements = newNimNode(nnkBracket, a)
for i in 1..a.len-1:
if a[i].kind == nnkExprEqExpr:
attrs.add(toStrLit(a[i][0]))
# In order to support attributes like `data-lang` we have to
# replace whitespace because `toStrLit` gives `data - lang`.
let attrName = toStrLit(a[i][0]).strVal.replace(" ", "")
attrs.add(newStrLitNode(attrName))
attrs.add(a[i][1])
#echo repr(attrs)
else:

View File

@@ -32,8 +32,6 @@ type
PRawChannel = ptr RawChannel
LoadStoreMode = enum mStore, mLoad
Channel* {.gcsafe.}[TMsg] = RawChannel ## a channel for thread communication
{.deprecated: [TRawChannel: RawChannel, TLoadStoreMode: LoadStoreMode,
TChannel: Channel].}
const ChannelDeadMask = -2

View File

@@ -144,7 +144,7 @@ proc allocSlowPath(r: var MemRegion; size: int) =
r.tail = fresh
r.remaining = s - sizeof(BaseChunk)
proc alloc(r: var MemRegion; size: int): pointer =
proc allocFast(r: var MemRegion; size: int): pointer =
if size <= MaxSmallObject:
var it = r.freeLists[size div MemAlign]
if it != nil:
@@ -270,7 +270,7 @@ proc isOnHeap*(r: MemRegion; p: pointer): bool =
it = it.next
proc rawNewObj(r: var MemRegion, typ: PNimType, size: int): pointer =
var res = cast[ptr ObjHeader](alloc(r, size + sizeof(ObjHeader)))
var res = cast[ptr ObjHeader](allocFast(r, size + sizeof(ObjHeader)))
res.typ = typ
if typ.finalizer != nil:
res.nextFinal = r.head.head
@@ -278,7 +278,7 @@ proc rawNewObj(r: var MemRegion, typ: PNimType, size: int): pointer =
result = res +! sizeof(ObjHeader)
proc rawNewSeq(r: var MemRegion, typ: PNimType, size: int): pointer =
var res = cast[ptr SeqHeader](alloc(r, size + sizeof(SeqHeader)))
var res = cast[ptr SeqHeader](allocFast(r, size + sizeof(SeqHeader)))
res.typ = typ
res.region = addr(r)
result = res +! sizeof(SeqHeader)
@@ -351,6 +351,11 @@ proc alloc0(r: var MemRegion; size: Natural): pointer =
# but incorrect in general. XXX
result = alloc0(size)
proc alloc(r: var MemRegion; size: Natural): pointer =
# ignore the region. That is correct for the channels module
# but incorrect in general. XXX
result = alloc(size)
proc dealloc(r: var MemRegion; p: pointer) = dealloc(p)
proc allocShared(size: Natural): pointer =
@@ -390,3 +395,6 @@ proc getTotalMem*(r: MemRegion): int =
result = r.totalSize
proc setStackBottom(theStackBottom: pointer) = discard
proc nimGCref(x: pointer) {.compilerProc.} = discard
proc nimGCunref(x: pointer) {.compilerProc.} = discard

View File

@@ -576,18 +576,3 @@ proc nimBoolToStr(x: bool): string {.compilerRtl.} =
proc nimCharToStr(x: char): string {.compilerRtl.} =
result = newString(1)
result[0] = x
proc binaryStrSearch(x: openArray[string], y: string): int {.compilerproc.} =
var
a = 0
b = len(x)
while a < b:
var mid = (a + b) div 2
if x[mid] < y:
a = mid + 1
else:
b = mid
if a < len(x) and x[a] == y:
result = a
else:
result = -1

View File

@@ -5,9 +5,9 @@ discard """
type
TMsgKind = enum
mLine, mEof
TMsg = object {.pure, final.}
TMsg = object
case k: TMsgKind
of mEof: nil
of mEof: discard
of mLine: data: string
var

View File

@@ -1,5 +1,5 @@
#? stdtmpl(subsChar='?') | standard
#proc generateBuildBatchScript(c: ConfigData, winIndex, cpuIndex: int): string =
#proc generateBuildBatchScript(c: ConfigData, winIndex, cpuIndex32, cpuIndex64: int): string =
# result = "@echo off\nREM Generated by niminst\n"
SET CC=gcc
SET LINKER=gcc
@@ -7,27 +7,63 @@ SET COMP_FLAGS=?{c.ccompiler.flags}
SET LINK_FLAGS=?{c.linker.flags}
SET BIN_DIR=?{firstBinPath(c).toWin}
REM Detect gcc arch
IF DEFINED ARCH (
ECHO Forcing %CC% arch
) ELSE (
ECHO Detecting %CC% arch
ECHO int main^(^) { return sizeof^(void *^); } | gcc -xc - -o archtest && archtest
IF ERRORLEVEL 4 SET ARCH=32
IF ERRORLEVEL 8 SET ARCH=64
del archtest.*
)
ECHO Building with %ARCH% bit %CC%
if EXIST ..\koch.nim SET BIN_DIR=..\bin
if NOT EXIST %BIN_DIR%\nul mkdir %BIN_DIR%
REM call the compiler:
IF %ARCH% EQU 32 (
# block win32:
# var linkCmd = ""
# for ff in items(c.cfiles[winIndex][cpuIndex]):
# let f = ff.toWin
ECHO %CC% %COMP_FLAGS% -Ic_code -c ?{f} -o ?{changeFileExt(f, "o")}
CALL %CC% %COMP_FLAGS% -Ic_code -c ?{f} -o ?{changeFileExt(f, "o")}
# linkCmd.add(" " & changeFileExt(f, "o"))
IF ERRORLEVEL 1 (GOTO:END)
# end for
# if cpuIndex32 != -1:
# for ff in items(c.cfiles[winIndex][cpuIndex32]):
# let f = ff.toWin
ECHO %CC% %COMP_FLAGS% -Ic_code -c ?{f} -o ?{changeFileExt(f, "o")}
CALL %CC% %COMP_FLAGS% -Ic_code -c ?{f} -o ?{changeFileExt(f, "o")}
# linkCmd.add(" " & changeFileExt(f, "o"))
IF ERRORLEVEL 1 (GOTO:END)
# end for
# end if
ECHO %LINKER% -o ?{"%BIN_DIR%"\toLowerAscii(c.name)}.exe ?linkCmd %LINK_FLAGS%
CALL %LINKER% -o ?{"%BIN_DIR%"\toLowerAscii(c.name)}.exe ?linkCmd %LINK_FLAGS%
ECHO %LINKER% -o ?{"%BIN_DIR%"\toLowerAscii(c.name)}.exe ?linkCmd %LINK_FLAGS%
CALL %LINKER% -o ?{"%BIN_DIR%"\toLowerAscii(c.name)}.exe ?linkCmd %LINK_FLAGS%
# end block
) ELSE IF %ARCH% EQU 64 (
# block win64:
# var linkCmd = ""
# if cpuIndex64 != -1:
# for ff in items(c.cfiles[winIndex][cpuIndex64]):
# let f = ff.toWin
ECHO %CC% %COMP_FLAGS% -Ic_code -c ?{f} -o ?{changeFileExt(f, "o")}
CALL %CC% %COMP_FLAGS% -Ic_code -c ?{f} -o ?{changeFileExt(f, "o")}
# linkCmd.add(" " & changeFileExt(f, "o"))
IF ERRORLEVEL 1 (GOTO:END)
# end for
# end if
ECHO %LINKER% -o ?{"%BIN_DIR%"\toLowerAscii(c.name)}.exe ?linkCmd %LINK_FLAGS%
CALL %LINKER% -o ?{"%BIN_DIR%"\toLowerAscii(c.name)}.exe ?linkCmd %LINK_FLAGS%
# end block
)
:END
IF ERRORLEVEL 1 (
ECHO FAILURE
@@ -35,6 +71,8 @@ IF ERRORLEVEL 1 (
ECHO CSource compilation failed. Please check that the gcc compiler is in
ECHO the PATH environment variable, and that you are calling the batch script
ECHO that matches the target architecture of the compiler.
ECHO.
ECHO Use build.bat to autodetect the compiler architecture.
) ELSE (
ECHO SUCCESS
)

View File

@@ -21,7 +21,8 @@ const
maxOS = 20 # max number of OSes
maxCPU = 20 # max number of CPUs
buildShFile = "build.sh"
buildBatFile32 = "build.bat"
buildBatFile = "build.bat"
buildBatFile32 = "build32.bat"
buildBatFile64 = "build64.bat"
makeFile = "makefile"
installShFile = "install.sh"
@@ -542,12 +543,13 @@ proc srcdist(c: var ConfigData) =
inclFilePermissions(getOutputDir(c) / buildShFile, {fpUserExec, fpGroupExec, fpOthersExec})
writeFile(getOutputDir(c) / makeFile, generateMakefile(c), "\10")
if winIndex >= 0:
if intel32Index >= 0 or intel64Index >= 0:
writeFile(getOutputDir(c) / buildBatFile,
generateBuildBatchScript(c, winIndex, intel32Index, intel64Index), "\13\10")
if intel32Index >= 0:
writeFile(getOutputDir(c) / buildBatFile32,
generateBuildBatchScript(c, winIndex, intel32Index), "\13\10")
writeFile(getOutputDir(c) / buildBatFile32, "SET ARCH=32\nCALL build.bat\n")
if intel64Index >= 0:
writeFile(getOutputDir(c) / buildBatFile64,
generateBuildBatchScript(c, winIndex, intel64Index), "\13\10")
writeFile(getOutputDir(c) / buildBatFile64, "SET ARCH=64\nCALL build.bat\n")
writeInstallScripts(c)
# --------------------- generate inno setup -----------------------------------
@@ -593,6 +595,7 @@ when haveZipLib:
else: n = c.outdir / n
var z: ZipArchive
if open(z, n, fmWrite):
addFile(z, proj / buildBatFile, "build" / buildBatFile)
addFile(z, proj / buildBatFile32, "build" / buildBatFile32)
addFile(z, proj / buildBatFile64, "build" / buildBatFile64)
addFile(z, proj / buildShFile, "build" / buildShFile)
@@ -631,11 +634,12 @@ proc xzDist(c: var ConfigData; windowsZip=false) =
if not dirExists(destDir): createDir(destDir)
copyFileWithPermissions(src, dest)
if not windowsZip and not existsFile("build" / buildBatFile32):
if not windowsZip and not existsFile("build" / buildBatFile):
quit("No C sources found in ./build/, please build by running " &
"./koch csource -d:release.")
if not windowsZip:
processFile(proj / buildBatFile, "build" / buildBatFile)
processFile(proj / buildBatFile32, "build" / buildBatFile32)
processFile(proj / buildBatFile64, "build" / buildBatFile64)
processFile(proj / buildShFile, "build" / buildShFile)