Merge remote-tracking branch 'upstream/master' into standalone
This commit is contained in:
commit
7dd9dbe4dd
119 changed files with 4593 additions and 1580 deletions
|
|
@ -1,24 +0,0 @@
|
|||
===============================================================================
|
||||
Nimrod -- a Compiler for Nimrod. http://nimrod-code.org/
|
||||
|
||||
Copyright (C) 2004-2013 Andreas Rumpf. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
[ MIT license: http://www.opensource.org/licenses/mit-license.php ]
|
||||
|
|
@ -390,7 +390,7 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
|
|||
|
||||
add(result, ")")
|
||||
|
||||
macro dumpTree*(s: stmt): stmt = echo s.treeRepr
|
||||
macro dumpTree*(s: stmt): stmt {.immediate.} = echo s.treeRepr
|
||||
## Accepts a block of nimrod code and prints the parsed abstract syntax
|
||||
## tree using the `toTree` function. Printing is done *at compile time*.
|
||||
##
|
||||
|
|
@ -398,16 +398,16 @@ macro dumpTree*(s: stmt): stmt = echo s.treeRepr
|
|||
## tree and to discover what kind of nodes must be created to represent
|
||||
## a certain expression/statement.
|
||||
|
||||
macro dumpLisp*(s: stmt): stmt = echo s.lispRepr
|
||||
macro dumpLisp*(s: stmt): stmt {.immediate.} = echo s.lispRepr
|
||||
## Accepts a block of nimrod code and prints the parsed abstract syntax
|
||||
## tree using the `toLisp` function. Printing is done *at compile time*.
|
||||
##
|
||||
## See `dumpTree`.
|
||||
|
||||
macro dumpTreeImm*(s: stmt): stmt {.immediate.} = echo s.treeRepr
|
||||
macro dumpTreeImm*(s: stmt): stmt {.immediate, deprecated.} = echo s.treeRepr
|
||||
## The ``immediate`` version of `dumpTree`.
|
||||
|
||||
macro dumpLispImm*(s: stmt): stmt {.immediate.} = echo s.lispRepr
|
||||
macro dumpLispImm*(s: stmt): stmt {.immediate, deprecated.} = echo s.lispRepr
|
||||
## The ``immediate`` version of `dumpLisp`.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ proc getBiggestInt*(x: TAny): biggestInt =
|
|||
of tyInt8: result = biggestInt(cast[ptr int8](x.value)[])
|
||||
of tyInt16: result = biggestInt(cast[ptr int16](x.value)[])
|
||||
of tyInt32: result = biggestInt(cast[ptr int32](x.value)[])
|
||||
of tyInt64: result = biggestInt(cast[ptr int64](x.value)[])
|
||||
of tyInt64, tyUInt64: result = biggestInt(cast[ptr int64](x.value)[])
|
||||
of tyBool: result = biggestInt(cast[ptr bool](x.value)[])
|
||||
of tyChar: result = biggestInt(cast[ptr char](x.value)[])
|
||||
of tyEnum, tySet:
|
||||
|
|
@ -389,6 +389,10 @@ proc getBiggestInt*(x: TAny): biggestInt =
|
|||
of 4: result = biggestInt(cast[ptr int32](x.value)[])
|
||||
of 8: result = biggestInt(cast[ptr int64](x.value)[])
|
||||
else: assert false
|
||||
of tyUInt: result = biggestInt(cast[ptr uint](x.value)[])
|
||||
of tyUInt8: result = biggestInt(cast[ptr uint8](x.value)[])
|
||||
of tyUInt16: result = biggestInt(cast[ptr uint16](x.value)[])
|
||||
of tyUInt32: result = biggestInt(cast[ptr uint32](x.value)[])
|
||||
else: assert false
|
||||
|
||||
proc setBiggestInt*(x: TAny, y: biggestInt) =
|
||||
|
|
@ -400,7 +404,7 @@ proc setBiggestInt*(x: TAny, y: biggestInt) =
|
|||
of tyInt8: cast[ptr int8](x.value)[] = int8(y)
|
||||
of tyInt16: cast[ptr int16](x.value)[] = int16(y)
|
||||
of tyInt32: cast[ptr int32](x.value)[] = int32(y)
|
||||
of tyInt64: cast[ptr int64](x.value)[] = int64(y)
|
||||
of tyInt64, tyUInt64: cast[ptr int64](x.value)[] = int64(y)
|
||||
of tyBool: cast[ptr bool](x.value)[] = y != 0
|
||||
of tyChar: cast[ptr char](x.value)[] = chr(y.int)
|
||||
of tyEnum, tySet:
|
||||
|
|
@ -410,6 +414,10 @@ proc setBiggestInt*(x: TAny, y: biggestInt) =
|
|||
of 4: cast[ptr int32](x.value)[] = int32(y)
|
||||
of 8: cast[ptr int64](x.value)[] = y
|
||||
else: assert false
|
||||
of tyUInt: cast[ptr uint](x.value)[] = uint(y)
|
||||
of tyUInt8: cast[ptr uint8](x.value)[] = uint8(y)
|
||||
of tyUInt16: cast[ptr uint16](x.value)[] = uint16(y)
|
||||
of tyUInt32: cast[ptr uint32](x.value)[] = uint32(y)
|
||||
else: assert false
|
||||
|
||||
proc getChar*(x: TAny): char =
|
||||
|
|
|
|||
|
|
@ -242,7 +242,6 @@ template `=~` *(s: string, pattern: TRegEx): expr =
|
|||
bind maxSubPatterns
|
||||
when not definedInScope(matches):
|
||||
var matches {.inject.}: array[0..maxSubPatterns-1, string]
|
||||
{.warning: "injected 'matches' might be affected by new scoping rules in 0.9.4".}
|
||||
match(s, pattern, matches)
|
||||
|
||||
# ------------------------- more string handling ------------------------------
|
||||
|
|
|
|||
|
|
@ -443,11 +443,11 @@ struct TFrame {
|
|||
};
|
||||
|
||||
#define nimfr(proc, file) \
|
||||
volatile TFrame F; \
|
||||
TFrame F; \
|
||||
F.procname = proc; F.filename = file; F.line = 0; F.len = 0; nimFrame(&F);
|
||||
|
||||
#define nimfrs(proc, file, slots, length) \
|
||||
volatile struct {TFrame* prev;NCSTRING procname;NI line;NCSTRING filename; NI len; TVarSlot s[slots];} F; \
|
||||
struct {TFrame* prev;NCSTRING procname;NI line;NCSTRING filename; NI len; TVarSlot s[slots];} F; \
|
||||
F.procname = proc; F.filename = file; F.line = 0; F.len = length; nimFrame((TFrame*)&F);
|
||||
|
||||
#define nimln(n, file) \
|
||||
|
|
|
|||
|
|
@ -44,7 +44,17 @@ const
|
|||
"Assembler", "Preprocessor", "Directive", "Command", "Rule", "Hyperlink",
|
||||
"Label", "Reference", "Other"]
|
||||
|
||||
nimrodKeywords = slurp("doc/keywords.txt").split
|
||||
# The following list comes from doc/keywords.txt, make sure it is
|
||||
# synchronized with this array by running the module itself as a test case.
|
||||
nimrodKeywords = ["addr", "and", "as", "asm", "atomic", "bind", "block",
|
||||
"break", "case", "cast", "const", "continue", "converter", "discard",
|
||||
"distinct", "div", "do", "elif", "else", "end", "enum", "except", "export",
|
||||
"finally", "for", "from", "generic", "if", "import", "in", "include",
|
||||
"interface", "is", "isnot", "iterator", "lambda", "let", "macro", "method",
|
||||
"mixin", "mod", "nil", "not", "notin", "object", "of", "or", "out", "proc",
|
||||
"ptr", "raise", "ref", "return", "shared", "shl", "shr", "static",
|
||||
"template", "try", "tuple", "type", "var", "when", "while", "with",
|
||||
"without", "xor", "yield"]
|
||||
|
||||
proc getSourceLanguage*(name: string): TSourceLanguage =
|
||||
for i in countup(succ(low(TSourceLanguage)), high(TSourceLanguage)):
|
||||
|
|
@ -535,3 +545,16 @@ proc getNextToken*(g: var TGeneralTokenizer, lang: TSourceLanguage) =
|
|||
of langC: cNextToken(g)
|
||||
of langJava: javaNextToken(g)
|
||||
|
||||
when isMainModule:
|
||||
var keywords: seq[string]
|
||||
# Try to work running in both the subdir or at the root.
|
||||
for filename in ["doc/keywords.txt", "../../../doc/keywords.txt"]:
|
||||
except: echo filename, " not found"
|
||||
let input = string(readFile(filename))
|
||||
keywords = input.split()
|
||||
break
|
||||
doAssert (not keywords.isNil, "Couldn't read any keywords.txt file!")
|
||||
doAssert keywords.len == nimrodKeywords.len, "No matching lengths"
|
||||
for i in 0..keywords.len-1:
|
||||
#echo keywords[i], " == ", nimrodKeywords[i]
|
||||
doAssert keywords[i] == nimrodKeywords[i], "Unexpected keyword"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module implements a `reStructuredText`:idx parser. A large
|
||||
## This module implements a `reStructuredText`:idx: parser. A large
|
||||
## subset is implemented. Some features of the `markdown`:idx: wiki syntax are
|
||||
## also supported.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module implements an AST for the `reStructuredText`:idx parser.
|
||||
## This module implements an AST for the `reStructuredText`:idx: parser.
|
||||
|
||||
import strutils
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module implements a generator of HTML/Latex from `reStructuredText`:idx.
|
||||
## This module implements a generator of HTML/Latex from `reStructuredText`:idx:.
|
||||
|
||||
import strutils, os, hashes, strtabs, rstast, rst, highlite
|
||||
|
||||
|
|
@ -692,4 +692,4 @@ proc rstToHtml*(s: string, options: TRstParseOptions,
|
|||
var rst = rstParse(s, filen, 0, 1, dummyHasToc, options)
|
||||
result = ""
|
||||
renderRstToOut(d, rst, result)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ proc AsyncSocket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
|
|||
result = newAsyncSocket()
|
||||
result.socket = socket(domain, typ, protocol, buffered)
|
||||
result.proto = protocol
|
||||
if result.socket == InvalidSocket: OSError()
|
||||
if result.socket == InvalidSocket: OSError(OSLastError())
|
||||
result.socket.setBlocking(false)
|
||||
|
||||
proc toAsyncSocket*(sock: TSocket, state: TInfo = SockConnected): PAsyncSocket =
|
||||
|
|
@ -349,7 +349,7 @@ proc acceptAddr*(server: PAsyncSocket, client: var PAsyncSocket,
|
|||
client.sslNeedAccept = false
|
||||
client.info = SockConnected
|
||||
|
||||
if c == InvalidSocket: OSError()
|
||||
if c == InvalidSocket: SocketError(server.socket)
|
||||
c.setBlocking(false) # TODO: Needs to be tested.
|
||||
|
||||
# deleg.open is set in ``toDelegate``.
|
||||
|
|
@ -423,6 +423,10 @@ proc isConnecting*(s: PAsyncSocket): bool =
|
|||
proc isClosed*(s: PAsyncSocket): bool =
|
||||
## Determines whether ``s`` has been closed.
|
||||
return s.info == SockClosed
|
||||
proc isSendDataBuffered*(s: PAsyncSocket): bool =
|
||||
## Determines whether ``s`` has data waiting to be sent, i.e. whether this
|
||||
## socket's sendBuffer contains data.
|
||||
return s.sendBuffer.len != 0
|
||||
|
||||
proc setHandleWrite*(s: PAsyncSocket,
|
||||
handleWrite: proc (s: PAsyncSocket) {.closure.}) =
|
||||
|
|
@ -638,8 +642,7 @@ when isMainModule:
|
|||
proc testRead(s: PAsyncSocket, no: int) =
|
||||
echo("Reading! " & $no)
|
||||
var data = ""
|
||||
if not s.readLine(data):
|
||||
OSError()
|
||||
if not s.readLine(data): return
|
||||
if data == "":
|
||||
echo("Closing connection. " & $no)
|
||||
s.close()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -35,8 +35,12 @@ type
|
|||
tagAddress, ## the HTML ``address`` element
|
||||
tagApplet, ## the deprecated HTML ``applet`` element
|
||||
tagArea, ## the HTML ``area`` element
|
||||
tagArticle, ## the HTML ``article`` element
|
||||
tagAside, ## the HTML ``aside`` element
|
||||
tagAudio, ## the HTML ``audio`` element
|
||||
tagB, ## the HTML ``b`` element
|
||||
tagBase, ## the HTML ``base`` element
|
||||
tagBdi, ## the HTML ``bdi`` element
|
||||
tagBdo, ## the deprecated HTML ``dbo`` element
|
||||
tagBasefont, ## the deprecated HTML ``basefont`` element
|
||||
tagBig, ## the HTML ``big`` element
|
||||
|
|
@ -44,22 +48,31 @@ type
|
|||
tagBody, ## the HTML ``body`` element
|
||||
tagBr, ## the HTML ``br`` element
|
||||
tagButton, ## the HTML ``button`` element
|
||||
tagCanvas, ## the HTML ``canvas`` element
|
||||
tagCaption, ## the HTML ``caption`` element
|
||||
tagCenter, ## the deprecated HTML ``center`` element
|
||||
tagCite, ## the HTML ``cite`` element
|
||||
tagCode, ## the HTML ``code`` element
|
||||
tagCol, ## the HTML ``col`` element
|
||||
tagColgroup, ## the HTML ``colgroup`` element
|
||||
tagCommand, ## the HTML ``command`` element
|
||||
tagDatalist, ## the HTML ``datalist`` element
|
||||
tagDd, ## the HTML ``dd`` element
|
||||
tagDel, ## the HTML ``del`` element
|
||||
tagDetails, ## the HTML ``details`` element
|
||||
tagDfn, ## the HTML ``dfn`` element
|
||||
tagDialog, ## the HTML ``dialog`` element
|
||||
tagDiv, ## the HTML ``div`` element
|
||||
tagDir, ## the deprecated HTLM ``dir`` element
|
||||
tagDl, ## the HTML ``dl`` element
|
||||
tagDt, ## the HTML ``dt`` element
|
||||
tagEm, ## the HTML ``em`` element
|
||||
tagEmbed, ## the HTML ``embed`` element
|
||||
tagFieldset, ## the HTML ``fieldset`` element
|
||||
tagFigcaption, ## the HTML ``figcaption`` element
|
||||
tagFigure, ## the HTML ``figure`` element
|
||||
tagFont, ## the deprecated HTML ``font`` element
|
||||
tagFooter, ## the HTML ``footer`` element
|
||||
tagForm, ## the HTML ``form`` element
|
||||
tagFrame, ## the HTML ``frame`` element
|
||||
tagFrameset, ## the deprecated HTML ``frameset`` element
|
||||
|
|
@ -70,6 +83,8 @@ type
|
|||
tagH5, ## the HTML ``h5`` element
|
||||
tagH6, ## the HTML ``h6`` element
|
||||
tagHead, ## the HTML ``head`` element
|
||||
tagHeader, ## the HTML ``header`` element
|
||||
tagHgroup, ## the HTML ``hgroup`` element
|
||||
tagHtml, ## the HTML ``html`` element
|
||||
tagHr, ## the HTML ``hr`` element
|
||||
tagI, ## the HTML ``i`` element
|
||||
|
|
@ -79,13 +94,17 @@ type
|
|||
tagIns, ## the HTML ``ins`` element
|
||||
tagIsindex, ## the deprecated HTML ``isindex`` element
|
||||
tagKbd, ## the HTML ``kbd`` element
|
||||
tagKeygen, ## the HTML ``keygen`` element
|
||||
tagLabel, ## the HTML ``label`` element
|
||||
tagLegend, ## the HTML ``legend`` element
|
||||
tagLi, ## the HTML ``li`` element
|
||||
tagLink, ## the HTML ``link`` element
|
||||
tagMap, ## the HTML ``map`` element
|
||||
tagMark, ## the HTML ``mark`` element
|
||||
tagMenu, ## the deprecated HTML ``menu`` element
|
||||
tagMeta, ## the HTML ``meta`` element
|
||||
tagMeter, ## the HTML ``meter`` element
|
||||
tagNav, ## the HTML ``nav`` element
|
||||
tagNobr, ## the deprecated HTML ``nobr`` element
|
||||
tagNoframes, ## the deprecated HTML ``noframes`` element
|
||||
tagNoscript, ## the HTML ``noscript`` element
|
||||
|
|
@ -93,20 +112,28 @@ type
|
|||
tagOl, ## the HTML ``ol`` element
|
||||
tagOptgroup, ## the HTML ``optgroup`` element
|
||||
tagOption, ## the HTML ``option`` element
|
||||
tagOutput, ## the HTML ``output`` element
|
||||
tagP, ## the HTML ``p`` element
|
||||
tagParam, ## the HTML ``param`` element
|
||||
tagPre, ## the HTML ``pre`` element
|
||||
tagProgress, ## the HTML ``progress`` element
|
||||
tagQ, ## the HTML ``q`` element
|
||||
tagRp, ## the HTML ``rp`` element
|
||||
tagRt, ## the HTML ``rt`` element
|
||||
tagRuby, ## the HTML ``ruby`` element
|
||||
tagS, ## the deprecated HTML ``s`` element
|
||||
tagSamp, ## the HTML ``samp`` element
|
||||
tagScript, ## the HTML ``script`` element
|
||||
tagSection, ## the HTML ``section`` element
|
||||
tagSelect, ## the HTML ``select`` element
|
||||
tagSmall, ## the HTML ``small`` element
|
||||
tagSource, ## the HTML ``source`` element
|
||||
tagSpan, ## the HTML ``span`` element
|
||||
tagStrike, ## the deprecated HTML ``strike`` element
|
||||
tagStrong, ## the HTML ``strong`` element
|
||||
tagStyle, ## the HTML ``style`` element
|
||||
tagSub, ## the HTML ``sub`` element
|
||||
tagSummary, ## the HTML ``summary`` element
|
||||
tagSup, ## the HTML ``sup`` element
|
||||
tagTable, ## the HTML ``table`` element
|
||||
tagTbody, ## the HTML ``tbody`` element
|
||||
|
|
@ -115,37 +142,46 @@ type
|
|||
tagTfoot, ## the HTML ``tfoot`` element
|
||||
tagTh, ## the HTML ``th`` element
|
||||
tagThead, ## the HTML ``thead`` element
|
||||
tagTime, ## the HTML ``time`` element
|
||||
tagTitle, ## the HTML ``title`` element
|
||||
tagTr, ## the HTML ``tr`` element
|
||||
tagTrack, ## the HTML ``track`` element
|
||||
tagTt, ## the HTML ``tt`` element
|
||||
tagU, ## the deprecated HTML ``u`` element
|
||||
tagUl, ## the HTML ``ul`` element
|
||||
tagVar ## the HTML ``var`` element
|
||||
tagVar, ## the HTML ``var`` element
|
||||
tagVideo, ## the HTML ``video`` element
|
||||
tagWbr ## the HTML ``wbr`` element
|
||||
|
||||
const
|
||||
tagToStr* = [
|
||||
"a", "abbr", "acronym", "address", "applet", "area",
|
||||
"b", "base", "basefont", "bdo", "big", "blockquote", "body",
|
||||
"br", "button", "caption", "center", "cite", "code",
|
||||
"col", "colgroup", "dd", "del", "dfn", "div",
|
||||
"dir", "dl", "dt", "em", "fieldset", "font",
|
||||
"a", "abbr", "acronym", "address", "applet", "area", "article",
|
||||
"aside", "audio",
|
||||
"b", "base", "basefont", "bdi", "bdo", "big", "blockquote", "body",
|
||||
"br", "button", "canvas", "caption", "center", "cite", "code",
|
||||
"col", "colgroup", "command",
|
||||
"datalist", "dd", "del", "details", "dfn", "dialog", "div",
|
||||
"dir", "dl", "dt", "em", "embed", "fieldset",
|
||||
"figcaption", "figure", "font", "footer",
|
||||
"form", "frame", "frameset", "h1", "h2", "h3",
|
||||
"h4", "h5", "h6", "head", "html", "hr",
|
||||
"h4", "h5", "h6", "head", "header", "hgroup", "html", "hr",
|
||||
"i", "iframe", "img", "input", "ins", "isindex",
|
||||
"kbd", "label", "legend", "li", "link", "map",
|
||||
"menu", "meta", "nobr", "noframes", "noscript", "object", "ol",
|
||||
"optgroup", "option", "p", "param", "pre", "q",
|
||||
"s", "samp", "script", "select", "small", "span",
|
||||
"strike", "strong", "style", "sub", "sup", "table",
|
||||
"tbody", "td", "textarea", "tfoot", "th", "thead",
|
||||
"title", "tr", "tt", "u", "ul", "var"]
|
||||
"kbd", "keygen", "label", "legend", "li", "link", "map", "mark",
|
||||
"menu", "meta", "meter", "nav", "nobr", "noframes", "noscript",
|
||||
"object", "ol",
|
||||
"optgroup", "option", "output", "p", "param", "pre", "progress", "q",
|
||||
"rp", "rt", "ruby", "s", "samp", "script", "section", "select", "small",
|
||||
"source", "span", "strike", "strong", "style",
|
||||
"sub", "summary", "sup", "table",
|
||||
"tbody", "td", "textarea", "tfoot", "th", "thead", "time",
|
||||
"title", "tr", "track", "tt", "u", "ul", "var", "video", "wbr"]
|
||||
InlineTags* = {tagA, tagAbbr, tagAcronym, tagApplet, tagB, tagBasefont,
|
||||
tagBdo, tagBig, tagBr, tagButton, tagCite, tagCode, tagDel, tagDfn,
|
||||
tagEm, tagFont, tagI, tagImg, tagIns, tagInput, tagIframe, tagKbd,
|
||||
tagLabel, tagMap, tagObject, tagQ, tagSamp, tagScript, tagSelect,
|
||||
tagSmall, tagSpan, tagStrong, tagSub, tagSup, tagTextarea, tagTt,
|
||||
tagVar, tagApplet, tagBasefont, tagFont, tagIframe, tagU, tagS,
|
||||
tagStrike}
|
||||
tagStrike, tagWbr}
|
||||
BlockTags* = {tagAddress, tagBlockquote, tagCenter, tagDel, tagDir, tagDiv,
|
||||
tagDl, tagFieldset, tagForm, tagH1, tagH2, tagH3, tagH4,
|
||||
tagH5, tagH6, tagHr, tagIns, tagIsindex, tagMenu, tagNoframes, tagNoscript,
|
||||
|
|
@ -153,7 +189,7 @@ const
|
|||
tagMenu, tagNoframes}
|
||||
SingleTags* = {tagArea, tagBase, tagBasefont,
|
||||
tagBr, tagCol, tagFrame, tagHr, tagImg, tagIsindex,
|
||||
tagLink, tagMeta, tagParam}
|
||||
tagLink, tagMeta, tagParam, tagWbr}
|
||||
|
||||
Entities = [
|
||||
("nbsp", 0x00A0), ("iexcl", 0x00A1), ("cent", 0x00A2), ("pound", 0x00A3),
|
||||
|
|
@ -228,28 +264,149 @@ const
|
|||
("loz", 0x25CA), ("spades", 0x2660), ("clubs", 0x2663),
|
||||
("hearts", 0x2665), ("diams", 0x2666)]
|
||||
|
||||
proc binaryStrSearch(x: openarray[string], y: string): int =
|
||||
## XXX put this into the library somewhere!
|
||||
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
|
||||
proc allLower(s: string): bool =
|
||||
for c in s:
|
||||
if c < 'a' or c > 'z': return false
|
||||
return true
|
||||
|
||||
proc toHtmlTag(s: string): THtmlTag =
|
||||
case s
|
||||
of "a": tagA
|
||||
of "abbr": tagAbbr
|
||||
of "acronym": tagAcronym
|
||||
of "address": tagAddress
|
||||
of "applet": tagApplet
|
||||
of "area": tagArea
|
||||
of "article": tagArticle
|
||||
of "aside": tagAside
|
||||
of "audio": tagAudio
|
||||
of "b": tagB
|
||||
of "base": tagBase
|
||||
of "basefont": tagBasefont
|
||||
of "bdi": tagBdi
|
||||
of "bdo": tagBdo
|
||||
of "big": tagBig
|
||||
of "blockquote": tagBlockquote
|
||||
of "body": tagBody
|
||||
of "br": tagBr
|
||||
of "button": tagButton
|
||||
of "canvas": tagCanvas
|
||||
of "caption": tagCaption
|
||||
of "center": tagCenter
|
||||
of "cite": tagCite
|
||||
of "code": tagCode
|
||||
of "col": tagCol
|
||||
of "colgroup": tagColgroup
|
||||
of "command": tagCommand
|
||||
of "datalist": tagDatalist
|
||||
of "dd": tagDd
|
||||
of "del": tagDel
|
||||
of "details": tagDetails
|
||||
of "dfn": tagDfn
|
||||
of "dialog": tagDialog
|
||||
of "div": tagDiv
|
||||
of "dir": tagDir
|
||||
of "dl": tagDl
|
||||
of "dt": tagDt
|
||||
of "em": tagEm
|
||||
of "embed": tagEmbed
|
||||
of "fieldset": tagFieldset
|
||||
of "figcaption": tagFigcaption
|
||||
of "figure": tagFigure
|
||||
of "font": tagFont
|
||||
of "footer": tagFooter
|
||||
of "form": tagForm
|
||||
of "frame": tagFrame
|
||||
of "frameset": tagFrameset
|
||||
of "h1": tagH1
|
||||
of "h2": tagH2
|
||||
of "h3": tagH3
|
||||
of "h4": tagH4
|
||||
of "h5": tagH5
|
||||
of "h6": tagH6
|
||||
of "head": tagHead
|
||||
of "header": tagHeader
|
||||
of "hgroup": tagHgroup
|
||||
of "html": tagHtml
|
||||
of "hr": tagHr
|
||||
of "i": tagI
|
||||
of "iframe": tagIframe
|
||||
of "img": tagImg
|
||||
of "input": tagInput
|
||||
of "ins": tagIns
|
||||
of "isindex": tagIsindex
|
||||
of "kbd": tagKbd
|
||||
of "keygen": tagKeygen
|
||||
of "label": tagLabel
|
||||
of "legend": tagLegend
|
||||
of "li": tagLi
|
||||
of "link": tagLink
|
||||
of "map": tagMap
|
||||
of "mark": tagMark
|
||||
of "menu": tagMenu
|
||||
of "meta": tagMeta
|
||||
of "meter": tagMeter
|
||||
of "nav": tagNav
|
||||
of "nobr": tagNobr
|
||||
of "noframes": tagNoframes
|
||||
of "noscript": tagNoscript
|
||||
of "object": tagObject
|
||||
of "ol": tagOl
|
||||
of "optgroup": tagOptgroup
|
||||
of "option": tagOption
|
||||
of "output": tagOutput
|
||||
of "p": tagP
|
||||
of "param": tagParam
|
||||
of "pre": tagPre
|
||||
of "progress": tagProgress
|
||||
of "q": tagQ
|
||||
of "rp": tagRp
|
||||
of "rt": tagRt
|
||||
of "ruby": tagRuby
|
||||
of "s": tagS
|
||||
of "samp": tagSamp
|
||||
of "script": tagScript
|
||||
of "section": tagSection
|
||||
of "select": tagSelect
|
||||
of "small": tagSmall
|
||||
of "source": tagSource
|
||||
of "span": tagSpan
|
||||
of "strike": tagStrike
|
||||
of "strong": tagStrong
|
||||
of "style": tagStyle
|
||||
of "sub": tagSub
|
||||
of "summary": tagSummary
|
||||
of "sup": tagSup
|
||||
of "table": tagTable
|
||||
of "tbody": tagTbody
|
||||
of "td": tagTd
|
||||
of "textarea": tagTextarea
|
||||
of "tfoot": tagTfoot
|
||||
of "th": tagTh
|
||||
of "thead": tagThead
|
||||
of "time": tagTime
|
||||
of "title": tagTitle
|
||||
of "tr": tagTr
|
||||
of "track": tagTrack
|
||||
of "tt": tagTt
|
||||
of "u": tagU
|
||||
of "ul": tagUl
|
||||
of "var": tagVar
|
||||
of "video": tagVideo
|
||||
of "wbr": tagWbr
|
||||
else: tagUnknown
|
||||
|
||||
proc htmlTag*(n: PXmlNode): THtmlTag =
|
||||
## gets `n`'s tag as a ``THtmlTag``.
|
||||
if n.clientData == 0:
|
||||
n.clientData = binaryStrSearch(tagToStr, n.tag)+1
|
||||
n.clientData = toHtmlTag(n.tag).ord
|
||||
result = THtmlTag(n.clientData)
|
||||
|
||||
proc htmlTag*(s: string): THtmlTag =
|
||||
## converts `s` to a ``THtmlTag``. If `s` is no HTML tag, ``tagUnknown`` is
|
||||
## returned.
|
||||
result = THtmlTag(binaryStrSearch(tagToStr, s.toLower)+1)
|
||||
let s = if allLower(s): s else: s.toLower
|
||||
result = toHtmlTag(s)
|
||||
|
||||
proc entityToUtf8*(entity: string): string =
|
||||
## converts an HTML entity name like ``Ü`` to its UTF-8 equivalent.
|
||||
|
|
@ -267,11 +424,13 @@ proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode
|
|||
proc expected(x: var TXmlParser, n: PXmlNode): string =
|
||||
result = errorMsg(x, "</" & n.tag & "> expected")
|
||||
|
||||
template elemName(x: expr): expr = rawData(x)
|
||||
|
||||
proc untilElementEnd(x: var TXmlParser, result: PXmlNode,
|
||||
errors: var seq[string]) =
|
||||
# we parsed e.g. ``<br>`` and don't really expect a ``</br>``:
|
||||
if result.htmlTag in singleTags:
|
||||
if x.kind != xmlElementEnd or cmpIgnoreCase(x.elementName, result.tag) != 0:
|
||||
if x.kind != xmlElementEnd or cmpIgnoreCase(x.elemName, result.tag) != 0:
|
||||
return
|
||||
while true:
|
||||
case x.kind
|
||||
|
|
@ -279,28 +438,29 @@ proc untilElementEnd(x: var TXmlParser, result: PXmlNode,
|
|||
case result.htmlTag
|
||||
of tagLi, tagP, tagDt, tagDd, tagInput, tagOption:
|
||||
# some tags are common to have no ``</end>``, like ``<li>``:
|
||||
if htmlTag(x.elementName) in {tagLi, tagP, tagDt, tagDd, tagInput,
|
||||
tagOption}:
|
||||
if htmlTag(x.elemName) in {tagLi, tagP, tagDt, tagDd, tagInput,
|
||||
tagOption}:
|
||||
errors.add(expected(x, result))
|
||||
break
|
||||
when false:
|
||||
if htmlTag(x.elementName) notin InlineTags:
|
||||
errors.add(expected(x, result))
|
||||
break
|
||||
of tagTr, tagTd, tagTh, tagTfoot, tagThead:
|
||||
if htmlTag(x.elementName) in {tagTr, tagTd, tagTh, tagTfoot, tagThead}:
|
||||
of tagTd, tagTh, tagTfoot, tagThead:
|
||||
if htmlTag(x.elemName) in {tagTr, tagTd, tagTh, tagTfoot, tagThead}:
|
||||
errors.add(expected(x, result))
|
||||
break
|
||||
of tagTr:
|
||||
if htmlTag(x.elemName) == tagTr:
|
||||
errors.add(expected(x, result))
|
||||
break
|
||||
of tagOptgroup:
|
||||
if htmlTag(x.elementName) in {tagOption, tagOptgroup}:
|
||||
if htmlTag(x.elemName) in {tagOption, tagOptgroup}:
|
||||
errors.add(expected(x, result))
|
||||
break
|
||||
else: nil
|
||||
result.addNode(parse(x, errors))
|
||||
of xmlElementEnd:
|
||||
if cmpIgnoreCase(x.elementName, result.tag) == 0:
|
||||
if cmpIgnoreCase(x.elemName, result.tag) == 0:
|
||||
next(x)
|
||||
else:
|
||||
echo "5; expected: ", result.htmltag, " ", x.elemName
|
||||
errors.add(expected(x, result))
|
||||
# do not skip it here!
|
||||
break
|
||||
|
|
@ -313,10 +473,10 @@ proc untilElementEnd(x: var TXmlParser, result: PXmlNode,
|
|||
proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode =
|
||||
case x.kind
|
||||
of xmlComment:
|
||||
result = newComment(x.charData)
|
||||
result = newComment(x.rawData)
|
||||
next(x)
|
||||
of xmlCharData, xmlWhitespace:
|
||||
result = newText(x.charData)
|
||||
result = newText(x.rawData)
|
||||
next(x)
|
||||
of xmlPI, xmlSpecial:
|
||||
# we just ignore processing instructions for now
|
||||
|
|
@ -325,19 +485,19 @@ proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode =
|
|||
errors.add(errorMsg(x))
|
||||
next(x)
|
||||
of xmlElementStart:
|
||||
result = newElement(x.elementName.toLower)
|
||||
result = newElement(x.elemName.toLower)
|
||||
next(x)
|
||||
untilElementEnd(x, result, errors)
|
||||
of xmlElementEnd:
|
||||
errors.add(errorMsg(x, "unexpected ending tag: " & x.elementName))
|
||||
errors.add(errorMsg(x, "unexpected ending tag: " & x.elemName))
|
||||
of xmlElementOpen:
|
||||
result = newElement(x.elementName.toLower)
|
||||
result = newElement(x.elemName.toLower)
|
||||
next(x)
|
||||
result.attrs = newStringTable()
|
||||
while true:
|
||||
case x.kind
|
||||
of xmlAttribute:
|
||||
result.attrs[x.attrKey] = x.attrValue
|
||||
result.attrs[x.rawData] = x.rawData2
|
||||
next(x)
|
||||
of xmlElementClose:
|
||||
next(x)
|
||||
|
|
@ -355,10 +515,10 @@ proc parse(x: var TXmlParser, errors: var seq[string]): PXmlNode =
|
|||
errors.add(errorMsg(x, "<some_tag> expected"))
|
||||
next(x)
|
||||
of xmlCData:
|
||||
result = newCData(x.charData)
|
||||
result = newCData(x.rawData)
|
||||
next(x)
|
||||
of xmlEntity:
|
||||
var u = entityToUtf8(x.entityName)
|
||||
var u = entityToUtf8(x.rawData)
|
||||
if u.len != 0: result = newText(u)
|
||||
next(x)
|
||||
of xmlEof: nil
|
||||
|
|
@ -372,16 +532,20 @@ proc parseHtml*(s: PStream, filename: string,
|
|||
next(x)
|
||||
# skip the DOCTYPE:
|
||||
if x.kind == xmlSpecial: next(x)
|
||||
result = parse(x, errors)
|
||||
if x.kind != xmlEof:
|
||||
errors.add(errorMsg(x, "EOF expected"))
|
||||
|
||||
result = newElement("document")
|
||||
result.addNode(parse(x, errors))
|
||||
#if x.kind != xmlEof:
|
||||
# errors.add(errorMsg(x, "EOF expected"))
|
||||
while x.kind != xmlEof:
|
||||
var oldPos = x.bufpos # little hack to see if we made any progess
|
||||
result.addNode(parse(x, errors))
|
||||
if x.bufpos == oldPos:
|
||||
if x.bufpos == oldPos:
|
||||
# force progress!
|
||||
next(x)
|
||||
next(x)
|
||||
close(x)
|
||||
if result.len == 1:
|
||||
result = result[0]
|
||||
|
||||
proc parseHtml*(s: PStream): PXmlNode =
|
||||
## parses the XTML from stream `s` and returns a ``PXmlNode``. All parsing
|
||||
|
|
@ -400,22 +564,9 @@ proc loadHtml*(path: string, errors: var seq[string]): PXmlNode =
|
|||
proc loadHtml*(path: string): PXmlNode =
|
||||
## Loads and parses HTML from file specified by ``path``, and returns
|
||||
## a ``PXmlNode``. All parsing errors are ignored.
|
||||
var errors: seq[string] = @[]
|
||||
var errors: seq[string] = @[]
|
||||
result = loadHtml(path, errors)
|
||||
|
||||
when true:
|
||||
nil
|
||||
else:
|
||||
proc checkHtmlAux(n: PXmlNode, errors: var seq[string]) =
|
||||
nil
|
||||
|
||||
proc checkHtmlStructure*(n: PXmlNode, errors: var seq[string]) =
|
||||
## checks the HTML structure after parsing for other errors like
|
||||
## a ``<h1>`` element within a ``<p>`` element.
|
||||
if n == nil or n.htmlTag != tagHtml:
|
||||
errors.add("<html> tag expected")
|
||||
checkHtmlAux(n, errors)
|
||||
|
||||
when isMainModule:
|
||||
import os
|
||||
|
||||
|
|
@ -429,4 +580,3 @@ when isMainModule:
|
|||
f.close()
|
||||
else:
|
||||
quit("cannot write test.txt")
|
||||
|
||||
|
|
|
|||
|
|
@ -47,10 +47,11 @@ proc badRequest(client: TSocket) =
|
|||
send(client, "<p>Your browser sent a bad request, " &
|
||||
"such as a POST without a Content-Length.</p>" & wwwNL)
|
||||
|
||||
proc cannotExec(client: TSocket) =
|
||||
send(client, "HTTP/1.1 500 Internal Server Error" & wwwNL)
|
||||
sendTextContentType(client)
|
||||
send(client, "<P>Error prohibited CGI execution." & wwwNL)
|
||||
when false:
|
||||
proc cannotExec(client: TSocket) =
|
||||
send(client, "HTTP/1.1 500 Internal Server Error" & wwwNL)
|
||||
sendTextContentType(client)
|
||||
send(client, "<P>Error prohibited CGI execution." & wwwNL)
|
||||
|
||||
proc headers(client: TSocket, filename: string) =
|
||||
# XXX could use filename to determine file type
|
||||
|
|
@ -79,11 +80,11 @@ proc unimplemented(client: TSocket) =
|
|||
|
||||
# ----------------- file serving ---------------------------------------------
|
||||
|
||||
proc discardHeaders(client: TSocket) = skip(client)
|
||||
when false:
|
||||
proc discardHeaders(client: TSocket) = skip(client)
|
||||
|
||||
proc serveFile*(client: TSocket, filename: string) =
|
||||
## serves a file to the client.
|
||||
when false: discardHeaders(client)
|
||||
var f: TFile
|
||||
if open(f, filename):
|
||||
headers(client, filename)
|
||||
|
|
@ -96,7 +97,7 @@ proc serveFile*(client: TSocket, filename: string) =
|
|||
if bytesread != bytesWritten:
|
||||
dealloc(buf)
|
||||
close(f)
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
if bytesread != bufSize: break
|
||||
dealloc(buf)
|
||||
close(f)
|
||||
|
|
@ -104,108 +105,109 @@ proc serveFile*(client: TSocket, filename: string) =
|
|||
notFound(client)
|
||||
|
||||
# ------------------ CGI execution -------------------------------------------
|
||||
when false:
|
||||
# TODO: Fix this, or get rid of it.
|
||||
type
|
||||
TRequestMethod = enum reqGet, reqPost
|
||||
|
||||
type
|
||||
TRequestMethod = enum reqGet, reqPost
|
||||
proc executeCgi(client: TSocket, path, query: string, meth: TRequestMethod) =
|
||||
var env = newStringTable(modeCaseInsensitive)
|
||||
var contentLength = -1
|
||||
case meth
|
||||
of reqGet:
|
||||
discardHeaders(client)
|
||||
|
||||
proc executeCgi(client: TSocket, path, query: string, meth: TRequestMethod) =
|
||||
var env = newStringTable(modeCaseInsensitive)
|
||||
var contentLength = -1
|
||||
case meth
|
||||
of reqGet:
|
||||
discardHeaders(client)
|
||||
env["REQUEST_METHOD"] = "GET"
|
||||
env["QUERY_STRING"] = query
|
||||
of reqPost:
|
||||
var buf = TaintedString""
|
||||
var dataAvail = false
|
||||
while dataAvail:
|
||||
dataAvail = recvLine(client, buf) # TODO: This is incorrect.
|
||||
var L = toLower(buf.string)
|
||||
if L.startsWith("content-length:"):
|
||||
var i = len("content-length:")
|
||||
while L[i] in Whitespace: inc(i)
|
||||
contentLength = parseInt(substr(L, i))
|
||||
|
||||
env["REQUEST_METHOD"] = "GET"
|
||||
env["QUERY_STRING"] = query
|
||||
of reqPost:
|
||||
var buf = TaintedString""
|
||||
var dataAvail = false
|
||||
while dataAvail:
|
||||
dataAvail = recvLine(client, buf) # TODO: This is incorrect.
|
||||
var L = toLower(buf.string)
|
||||
if L.startsWith("content-length:"):
|
||||
var i = len("content-length:")
|
||||
while L[i] in Whitespace: inc(i)
|
||||
contentLength = parseInt(substr(L, i))
|
||||
if contentLength < 0:
|
||||
badRequest(client)
|
||||
return
|
||||
|
||||
if contentLength < 0:
|
||||
badRequest(client)
|
||||
return
|
||||
env["REQUEST_METHOD"] = "POST"
|
||||
env["CONTENT_LENGTH"] = $contentLength
|
||||
|
||||
env["REQUEST_METHOD"] = "POST"
|
||||
env["CONTENT_LENGTH"] = $contentLength
|
||||
send(client, "HTTP/1.0 200 OK" & wwwNL)
|
||||
|
||||
send(client, "HTTP/1.0 200 OK" & wwwNL)
|
||||
|
||||
var process = startProcess(command=path, env=env)
|
||||
if meth == reqPost:
|
||||
# get from client and post to CGI program:
|
||||
var buf = alloc(contentLength)
|
||||
if recv(client, buf, contentLength) != contentLength:
|
||||
var process = startProcess(command=path, env=env)
|
||||
if meth == reqPost:
|
||||
# get from client and post to CGI program:
|
||||
var buf = alloc(contentLength)
|
||||
if recv(client, buf, contentLength) != contentLength:
|
||||
dealloc(buf)
|
||||
OSError()
|
||||
var inp = process.inputStream
|
||||
inp.writeData(buf, contentLength)
|
||||
dealloc(buf)
|
||||
OSError()
|
||||
var inp = process.inputStream
|
||||
inp.writeData(buf, contentLength)
|
||||
dealloc(buf)
|
||||
|
||||
var outp = process.outputStream
|
||||
var line = newStringOfCap(120).TaintedString
|
||||
while true:
|
||||
if outp.readLine(line):
|
||||
send(client, line.string)
|
||||
send(client, wwwNL)
|
||||
elif not running(process): break
|
||||
var outp = process.outputStream
|
||||
var line = newStringOfCap(120).TaintedString
|
||||
while true:
|
||||
if outp.readLine(line):
|
||||
send(client, line.string)
|
||||
send(client, wwwNL)
|
||||
elif not running(process): break
|
||||
|
||||
# --------------- Server Setup -----------------------------------------------
|
||||
# --------------- Server Setup -----------------------------------------------
|
||||
|
||||
proc acceptRequest(client: TSocket) =
|
||||
var cgi = false
|
||||
var query = ""
|
||||
var buf = TaintedString""
|
||||
discard recvLine(client, buf)
|
||||
var path = ""
|
||||
var data = buf.string.split()
|
||||
var meth = reqGet
|
||||
proc acceptRequest(client: TSocket) =
|
||||
var cgi = false
|
||||
var query = ""
|
||||
var buf = TaintedString""
|
||||
discard recvLine(client, buf)
|
||||
var path = ""
|
||||
var data = buf.string.split()
|
||||
var meth = reqGet
|
||||
|
||||
var q = find(data[1], '?')
|
||||
var q = find(data[1], '?')
|
||||
|
||||
# extract path
|
||||
if q >= 0:
|
||||
# strip "?..." from path, this may be found in both POST and GET
|
||||
path = "." & data[1].substr(0, q-1)
|
||||
else:
|
||||
path = "." & data[1]
|
||||
# path starts with "/", by adding "." in front of it we serve files from cwd
|
||||
|
||||
if cmpIgnoreCase(data[0], "GET") == 0:
|
||||
# extract path
|
||||
if q >= 0:
|
||||
# strip "?..." from path, this may be found in both POST and GET
|
||||
path = "." & data[1].substr(0, q-1)
|
||||
else:
|
||||
path = "." & data[1]
|
||||
# path starts with "/", by adding "." in front of it we serve files from cwd
|
||||
|
||||
if cmpIgnoreCase(data[0], "GET") == 0:
|
||||
if q >= 0:
|
||||
cgi = true
|
||||
query = data[1].substr(q+1)
|
||||
elif cmpIgnoreCase(data[0], "POST") == 0:
|
||||
cgi = true
|
||||
query = data[1].substr(q+1)
|
||||
elif cmpIgnoreCase(data[0], "POST") == 0:
|
||||
cgi = true
|
||||
meth = reqPost
|
||||
else:
|
||||
unimplemented(client)
|
||||
|
||||
if path[path.len-1] == '/' or existsDir(path):
|
||||
path = path / "index.html"
|
||||
|
||||
if not ExistsFile(path):
|
||||
discardHeaders(client)
|
||||
notFound(client)
|
||||
else:
|
||||
when defined(Windows):
|
||||
var ext = splitFile(path).ext.toLower
|
||||
if ext == ".exe" or ext == ".cgi":
|
||||
# XXX: extract interpreter information here?
|
||||
cgi = true
|
||||
meth = reqPost
|
||||
else:
|
||||
if {fpUserExec, fpGroupExec, fpOthersExec} * path.getFilePermissions != {}:
|
||||
cgi = true
|
||||
if not cgi:
|
||||
serveFile(client, path)
|
||||
unimplemented(client)
|
||||
|
||||
if path[path.len-1] == '/' or existsDir(path):
|
||||
path = path / "index.html"
|
||||
|
||||
if not ExistsFile(path):
|
||||
discardHeaders(client)
|
||||
notFound(client)
|
||||
else:
|
||||
executeCgi(client, path, query, meth)
|
||||
when defined(Windows):
|
||||
var ext = splitFile(path).ext.toLower
|
||||
if ext == ".exe" or ext == ".cgi":
|
||||
# XXX: extract interpreter information here?
|
||||
cgi = true
|
||||
else:
|
||||
if {fpUserExec, fpGroupExec, fpOthersExec} * path.getFilePermissions != {}:
|
||||
cgi = true
|
||||
if not cgi:
|
||||
serveFile(client, path)
|
||||
else:
|
||||
executeCgi(client, path, query, meth)
|
||||
|
||||
type
|
||||
TServer* = object of TObject ## contains the current server state
|
||||
|
|
@ -226,7 +228,7 @@ proc open*(s: var TServer, port = TPort(80)) =
|
|||
## creates a new server at port `port`. If ``port == 0`` a free port is
|
||||
## acquired that can be accessed later by the ``port`` proc.
|
||||
s.socket = socket(AF_INET)
|
||||
if s.socket == InvalidSocket: OSError()
|
||||
if s.socket == InvalidSocket: OSError(OSLastError())
|
||||
bindAddr(s.socket, port)
|
||||
listen(s.socket)
|
||||
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ when isMainModule:
|
|||
["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
|
||||
["test", "1", "2", "3", "4"]]
|
||||
testit(x)
|
||||
var test2: tuple[name: string, s: int] = ("tuple test", 56)
|
||||
var test2: tuple[name: string, s: uint] = ("tuple test", 56u)
|
||||
testit(test2)
|
||||
|
||||
type
|
||||
|
|
|
|||
|
|
@ -50,11 +50,11 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
result.size = 0
|
||||
|
||||
when defined(windows):
|
||||
template fail(msg: expr) =
|
||||
template fail(errCode: TOSErrorCode, msg: expr) =
|
||||
rollback()
|
||||
if result.fHandle != 0: discard CloseHandle(result.fHandle)
|
||||
if result.mapHandle != 0: discard CloseHandle(result.mapHandle)
|
||||
OSError()
|
||||
OSError(errCode)
|
||||
# return false
|
||||
#raise newException(EIO, msg)
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
result.fHandle = callCreateFile(CreateFileA, filename)
|
||||
|
||||
if result.fHandle == INVALID_HANDLE_VALUE:
|
||||
fail "error opening file"
|
||||
fail(OSLastError(), "error opening file")
|
||||
|
||||
if newFileSize != -1:
|
||||
var
|
||||
|
|
@ -83,9 +83,10 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
|
||||
var status = SetFilePointer(result.fHandle, sizeLow, addr(sizeHigh),
|
||||
FILE_BEGIN)
|
||||
if (status == INVALID_SET_FILE_POINTER and GetLastError() != NO_ERROR) or
|
||||
let lastErr = OSLastError()
|
||||
if (status == INVALID_SET_FILE_POINTER and lastErr.int32 != NO_ERROR) or
|
||||
(SetEndOfFile(result.fHandle) == 0):
|
||||
fail "error setting file size"
|
||||
fail(lastErr, "error setting file size")
|
||||
|
||||
# since the strings are always 'nil', we simply always call
|
||||
# CreateFileMappingW which should be slightly faster anyway:
|
||||
|
|
@ -95,7 +96,7 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
0, 0, nil)
|
||||
|
||||
if result.mapHandle == 0:
|
||||
fail "error creating mapping"
|
||||
fail(OSLastError(), "error creating mapping")
|
||||
|
||||
result.mem = MapViewOfFileEx(
|
||||
result.mapHandle,
|
||||
|
|
@ -106,22 +107,22 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
nil)
|
||||
|
||||
if result.mem == nil:
|
||||
fail "error mapping view"
|
||||
fail(OSLastError(), "error mapping view")
|
||||
|
||||
var hi, low: int32
|
||||
low = GetFileSize(result.fHandle, addr(hi))
|
||||
if low == INVALID_FILE_SIZE:
|
||||
fail "error getting file size"
|
||||
fail(OSLastError(), "error getting file size")
|
||||
else:
|
||||
var fileSize = (int64(hi) shr 32) or low
|
||||
if mappedSize != -1: result.size = min(fileSize, mappedSize).int
|
||||
else: result.size = fileSize.int
|
||||
|
||||
else:
|
||||
template fail(msg: expr) =
|
||||
template fail(errCode: TOSErrorCode, msg: expr) =
|
||||
rollback()
|
||||
if result.handle != 0: discard close(result.handle)
|
||||
OSError()
|
||||
OSError(errCode)
|
||||
|
||||
var flags = if readonly: O_RDONLY else: O_RDWR
|
||||
|
||||
|
|
@ -132,11 +133,11 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
if result.handle == -1:
|
||||
# XXX: errno is supposed to be set here
|
||||
# Is there an exception that wraps it?
|
||||
fail "error opening file"
|
||||
fail(OSLastError(), "error opening file")
|
||||
|
||||
if newFileSize != -1:
|
||||
if ftruncate(result.handle, newFileSize) == -1:
|
||||
fail "error setting file size"
|
||||
fail(OSLastError(), "error setting file size")
|
||||
|
||||
if mappedSize != -1:
|
||||
result.size = mappedSize
|
||||
|
|
@ -147,7 +148,7 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
# Why is mmap taking int anyway?
|
||||
result.size = int(stat.st_size)
|
||||
else:
|
||||
fail "error getting file size"
|
||||
fail(OSLastError(), "error getting file size")
|
||||
|
||||
result.mem = mmap(
|
||||
nil,
|
||||
|
|
@ -158,21 +159,24 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
offset)
|
||||
|
||||
if result.mem == cast[pointer](MAP_FAILED):
|
||||
fail "file mapping failed"
|
||||
fail(OSLastError(), "file mapping failed")
|
||||
|
||||
proc close*(f: var TMemFile) =
|
||||
## closes the memory mapped file `f`. All changes are written back to the
|
||||
## file system, if `f` was opened with write access.
|
||||
|
||||
var error = false
|
||||
var lastErr: TOSErrorCode
|
||||
|
||||
when defined(windows):
|
||||
if f.fHandle != INVALID_HANDLE_VALUE:
|
||||
lastErr = OSLastError()
|
||||
error = UnmapViewOfFile(f.mem) == 0
|
||||
error = (CloseHandle(f.mapHandle) == 0) or error
|
||||
error = (CloseHandle(f.fHandle) == 0) or error
|
||||
else:
|
||||
if f.handle != 0:
|
||||
lastErr = OSLastError()
|
||||
error = munmap(f.mem, f.size) != 0
|
||||
error = (close(f.handle) != 0) or error
|
||||
|
||||
|
|
@ -185,5 +189,5 @@ proc close*(f: var TMemFile) =
|
|||
else:
|
||||
f.handle = 0
|
||||
|
||||
if error: OSError()
|
||||
if error: OSError(lastErr)
|
||||
|
||||
|
|
|
|||
179
lib/pure/os.nim
179
lib/pure/os.nim
|
|
@ -39,6 +39,8 @@ type
|
|||
FWriteDir* = object of FWriteIO ## effect that denotes a write operation to
|
||||
## the directory structure
|
||||
|
||||
TOSErrorCode* = distinct int32 ## Specifies an OS Error Code.
|
||||
|
||||
const
|
||||
doslike = defined(windows) or defined(OS2) or defined(DOS)
|
||||
# DOS-like filesystem
|
||||
|
|
@ -171,10 +173,13 @@ const
|
|||
## The character which separates the base filename from the extension;
|
||||
## for example, the '.' in ``os.nim``.
|
||||
|
||||
proc OSErrorMsg*(): string {.rtl, extern: "nos$1".} =
|
||||
proc OSErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} =
|
||||
## Retrieves the operating system's error flag, ``errno``.
|
||||
## On Windows ``GetLastError`` is checked before ``errno``.
|
||||
## Returns "" if no error occured.
|
||||
##
|
||||
## **Deprecated since version 0.9.4**: use the other ``OSErrorMsg`` proc.
|
||||
|
||||
result = ""
|
||||
when defined(Windows):
|
||||
var err = GetLastError()
|
||||
|
|
@ -194,17 +199,89 @@ proc OSErrorMsg*(): string {.rtl, extern: "nos$1".} =
|
|||
if errno != 0'i32:
|
||||
result = $os.strerror(errno)
|
||||
|
||||
proc OSError*(msg: string = "") {.noinline, rtl, extern: "nos$1".} =
|
||||
{.push warning[deprecated]: off.}
|
||||
proc OSError*(msg: string = "") {.noinline, rtl, extern: "nos$1", deprecated.} =
|
||||
## raises an EOS exception with the given message ``msg``.
|
||||
## If ``msg == ""``, the operating system's error flag
|
||||
## (``errno``) is converted to a readable error message. On Windows
|
||||
## ``GetLastError`` is checked before ``errno``.
|
||||
## If no error flag is set, the message ``unknown OS error`` is used.
|
||||
##
|
||||
## **Deprecated since version 0.9.4**: use the other ``OSError`` proc.
|
||||
if len(msg) == 0:
|
||||
var m = OSErrorMsg()
|
||||
raise newException(EOS, if m.len > 0: m else: "unknown OS error")
|
||||
else:
|
||||
raise newException(EOS, msg)
|
||||
{.pop.}
|
||||
|
||||
proc `==`*(err1, err2: TOSErrorCode): bool {.borrow.}
|
||||
proc `$`*(err: TOSErrorCode): string {.borrow.}
|
||||
|
||||
proc OSErrorMsg*(errorCode: TOSErrorCode): string =
|
||||
## Converts an OS error code into a human readable string.
|
||||
##
|
||||
## The error code can be retrieved using the ``OSLastError`` proc.
|
||||
##
|
||||
## If conversion fails, or ``errorCode`` is ``0`` then ``""`` will be
|
||||
## returned.
|
||||
##
|
||||
## On Windows, the ``-d:useWinAnsi`` compilation flag can be used to
|
||||
## make this procedure use the non-unicode Win API calls to retrieve the
|
||||
## message.
|
||||
result = ""
|
||||
when defined(Windows):
|
||||
if errorCode != TOSErrorCode(0'i32):
|
||||
when useWinUnicode:
|
||||
var msgbuf: widecstring
|
||||
if FormatMessageW(0x00000100 or 0x00001000 or 0x00000200,
|
||||
nil, errorCode.int32, 0, addr(msgbuf), 0, nil) != 0'i32:
|
||||
result = $msgbuf
|
||||
if msgbuf != nil: LocalFree(cast[pointer](msgbuf))
|
||||
else:
|
||||
var msgbuf: cstring
|
||||
if FormatMessageA(0x00000100 or 0x00001000 or 0x00000200,
|
||||
nil, errorCode.int32, 0, addr(msgbuf), 0, nil) != 0'i32:
|
||||
result = $msgbuf
|
||||
if msgbuf != nil: LocalFree(msgbuf)
|
||||
else:
|
||||
if errorCode != TOSErrorCode(0'i32):
|
||||
result = $os.strerror(errorCode.int32)
|
||||
|
||||
proc OSError*(errorCode: TOSErrorCode) =
|
||||
## Raises an ``EOS`` exception. The ``errorCode`` will determine the
|
||||
## message, ``OSErrorMsg`` will be used to get this message.
|
||||
##
|
||||
## The error code can be retrieved using the ``OSLastError`` proc.
|
||||
##
|
||||
## If the error code is ``0`` or an error message could not be retrieved,
|
||||
## the message ``unknown OS error`` will be used.
|
||||
let msg = OSErrorMsg(errorCode)
|
||||
if msg == "":
|
||||
raise newException(EOS, "unknown OS error")
|
||||
else:
|
||||
raise newException(EOS, msg)
|
||||
|
||||
{.push stackTrace:off.}
|
||||
proc OSLastError*(): TOSErrorCode =
|
||||
## Retrieves the last operating system error code.
|
||||
##
|
||||
## This procedure is useful in the event when an OS call fails. In that case
|
||||
## this procedure will return the error code describing the reason why the
|
||||
## OS call failed. The ``OSErrorMsg`` procedure can then be used to convert
|
||||
## this code into a string.
|
||||
##
|
||||
## **Warning**:
|
||||
## The behaviour of this procedure varies between Windows and POSIX systems.
|
||||
## On Windows some OS calls can reset the error code to ``0`` causing this
|
||||
## procedure to return ``0``. It is therefore advised to call this procedure
|
||||
## immediately after an OS call fails. On POSIX systems this is not a problem.
|
||||
|
||||
when defined(windows):
|
||||
result = TOSErrorCode(GetLastError())
|
||||
else:
|
||||
result = TOSErrorCode(errno)
|
||||
{.pop.}
|
||||
|
||||
proc UnixToNativePath*(path: string): string {.
|
||||
noSideEffect, rtl, extern: "nos$1".} =
|
||||
|
|
@ -311,12 +388,12 @@ proc getLastModificationTime*(file: string): TTime {.rtl, extern: "nos$1".} =
|
|||
## Returns the `file`'s last modification time.
|
||||
when defined(posix):
|
||||
var res: TStat
|
||||
if stat(file, res) < 0'i32: OSError()
|
||||
if stat(file, res) < 0'i32: OSError(OSLastError())
|
||||
return res.st_mtime
|
||||
else:
|
||||
var f: TWIN32_Find_Data
|
||||
var h = findfirstFile(file, f)
|
||||
if h == -1'i32: OSError()
|
||||
if h == -1'i32: OSError(OSLastError())
|
||||
result = winTimeToUnixTime(rdFileTime(f.ftLastWriteTime))
|
||||
findclose(h)
|
||||
|
||||
|
|
@ -324,12 +401,12 @@ proc getLastAccessTime*(file: string): TTime {.rtl, extern: "nos$1".} =
|
|||
## Returns the `file`'s last read or write access time.
|
||||
when defined(posix):
|
||||
var res: TStat
|
||||
if stat(file, res) < 0'i32: OSError()
|
||||
if stat(file, res) < 0'i32: OSError(OSLastError())
|
||||
return res.st_atime
|
||||
else:
|
||||
var f: TWIN32_Find_Data
|
||||
var h = findfirstFile(file, f)
|
||||
if h == -1'i32: OSError()
|
||||
if h == -1'i32: OSError(OSLastError())
|
||||
result = winTimeToUnixTime(rdFileTime(f.ftLastAccessTime))
|
||||
findclose(h)
|
||||
|
||||
|
|
@ -337,12 +414,12 @@ proc getCreationTime*(file: string): TTime {.rtl, extern: "nos$1".} =
|
|||
## Returns the `file`'s creation time.
|
||||
when defined(posix):
|
||||
var res: TStat
|
||||
if stat(file, res) < 0'i32: OSError()
|
||||
if stat(file, res) < 0'i32: OSError(OSLastError())
|
||||
return res.st_ctime
|
||||
else:
|
||||
var f: TWIN32_Find_Data
|
||||
var h = findfirstFile(file, f)
|
||||
if h == -1'i32: OSError()
|
||||
if h == -1'i32: OSError(OSLastError())
|
||||
result = winTimeToUnixTime(rdFileTime(f.ftCreationTime))
|
||||
findclose(h)
|
||||
|
||||
|
|
@ -358,30 +435,30 @@ proc getCurrentDir*(): string {.rtl, extern: "nos$1", tags: [].} =
|
|||
when useWinUnicode:
|
||||
var res = newWideCString("", bufsize)
|
||||
var L = GetCurrentDirectoryW(bufsize, res)
|
||||
if L == 0'i32: OSError()
|
||||
if L == 0'i32: OSError(OSLastError())
|
||||
result = res$L
|
||||
else:
|
||||
result = newString(bufsize)
|
||||
var L = GetCurrentDirectoryA(bufsize, result)
|
||||
if L == 0'i32: OSError()
|
||||
if L == 0'i32: OSError(OSLastError())
|
||||
setLen(result, L)
|
||||
else:
|
||||
result = newString(bufsize)
|
||||
if getcwd(result, bufsize) != nil:
|
||||
setlen(result, c_strlen(result))
|
||||
else:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
|
||||
proc setCurrentDir*(newDir: string) {.inline, tags: [].} =
|
||||
## Sets the `current working directory`:idx:; `EOS` is raised if
|
||||
## `newDir` cannot been set.
|
||||
when defined(Windows):
|
||||
when useWinUnicode:
|
||||
if SetCurrentDirectoryW(newWideCString(newDir)) == 0'i32: OSError()
|
||||
if SetCurrentDirectoryW(newWideCString(newDir)) == 0'i32: OSError(OSLastError())
|
||||
else:
|
||||
if SetCurrentDirectoryA(newDir) == 0'i32: OSError()
|
||||
if SetCurrentDirectoryA(newDir) == 0'i32: OSError(OSLastError())
|
||||
else:
|
||||
if chdir(newDir) != 0'i32: OSError()
|
||||
if chdir(newDir) != 0'i32: OSError(OSLastError())
|
||||
|
||||
proc JoinPath*(head, tail: string): string {.
|
||||
noSideEffect, rtl, extern: "nos$1".} =
|
||||
|
|
@ -571,23 +648,23 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
|
|||
var res = newWideCString("", bufsize div 2)
|
||||
var L = GetFullPathNameW(newWideCString(filename), bufsize, res, unused)
|
||||
if L <= 0'i32 or L >= bufsize:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
result = res$L
|
||||
else:
|
||||
var unused: cstring
|
||||
result = newString(bufsize)
|
||||
var L = GetFullPathNameA(filename, bufsize, result, unused)
|
||||
if L <= 0'i32 or L >= bufsize: OSError()
|
||||
if L <= 0'i32 or L >= bufsize: OSError(OSLastError())
|
||||
setLen(result, L)
|
||||
elif defined(macosx) or defined(bsd):
|
||||
# On Mac OS X 10.5, realpath does not allocate the buffer on its own
|
||||
var pathBuffer: cstring = newString(pathMax)
|
||||
var resultBuffer = realpath(filename, pathBuffer)
|
||||
if resultBuffer == nil: OSError()
|
||||
if resultBuffer == nil: OSError(OSLastError())
|
||||
result = $resultBuffer
|
||||
else:
|
||||
var res = realpath(filename, nil)
|
||||
if res == nil: OSError()
|
||||
if res == nil: OSError(OSLastError())
|
||||
result = $res
|
||||
c_free(res)
|
||||
|
||||
|
|
@ -677,6 +754,7 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
|
|||
var f1 = OpenHandle(path1)
|
||||
var f2 = OpenHandle(path2)
|
||||
|
||||
var lastErr: TOSErrorCode
|
||||
if f1 != INVALID_HANDLE_VALUE and f2 != INVALID_HANDLE_VALUE:
|
||||
var fi1, fi2: TBY_HANDLE_FILE_INFORMATION
|
||||
|
||||
|
|
@ -685,17 +763,21 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
|
|||
result = fi1.dwVolumeSerialNumber == fi2.dwVolumeSerialNumber and
|
||||
fi1.nFileIndexHigh == fi2.nFileIndexHigh and
|
||||
fi1.nFileIndexLow == fi2.nFileIndexLow
|
||||
else: success = false
|
||||
else: success = false
|
||||
else:
|
||||
lastErr = OSLastError()
|
||||
success = false
|
||||
else:
|
||||
lastErr = OSLastError()
|
||||
success = false
|
||||
|
||||
discard CloseHandle(f1)
|
||||
discard CloseHandle(f2)
|
||||
|
||||
if not success: OSError()
|
||||
if not success: OSError(lastErr)
|
||||
else:
|
||||
var a, b: TStat
|
||||
if stat(path1, a) < 0'i32 or stat(path2, b) < 0'i32:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
else:
|
||||
result = a.st_dev == b.st_dev and a.st_ino == b.st_ino
|
||||
|
||||
|
|
@ -738,17 +820,17 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
|
|||
when useWinUnicode:
|
||||
let s = newWideCString(source)
|
||||
let d = newWideCString(dest)
|
||||
if CopyFileW(s, d, 0'i32) == 0'i32: OSError()
|
||||
if CopyFileW(s, d, 0'i32) == 0'i32: OSError(OSLastError())
|
||||
else:
|
||||
if CopyFileA(source, dest, 0'i32) == 0'i32: OSError()
|
||||
if CopyFileA(source, dest, 0'i32) == 0'i32: OSError(OSLastError())
|
||||
else:
|
||||
# generic version of copyFile which works for any platform:
|
||||
const bufSize = 8000 # better for memory manager
|
||||
var d, s: TFile
|
||||
if not open(s, source): OSError()
|
||||
if not open(s, source): OSError(OSLastError())
|
||||
if not open(d, dest, fmWrite):
|
||||
close(s)
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
var buf = alloc(bufsize)
|
||||
while True:
|
||||
var bytesread = readBuffer(s, buf, bufsize)
|
||||
|
|
@ -758,7 +840,7 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
|
|||
dealloc(buf)
|
||||
close(s)
|
||||
close(d)
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
if bytesread != bufSize: break
|
||||
dealloc(buf)
|
||||
close(s)
|
||||
|
|
@ -767,7 +849,8 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
|
|||
proc moveFile*(source, dest: string) {.rtl, extern: "nos$1",
|
||||
tags: [FReadIO, FWriteIO].} =
|
||||
## Moves a file from `source` to `dest`. If this fails, `EOS` is raised.
|
||||
if crename(source, dest) != 0'i32: OSError()
|
||||
if crename(source, dest) != 0'i32:
|
||||
raise newException(EOS, $strerror(errno))
|
||||
|
||||
when not defined(ENOENT):
|
||||
var ENOENT {.importc, header: "<errno.h>".}: cint
|
||||
|
|
@ -775,7 +858,8 @@ when not defined(ENOENT):
|
|||
proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} =
|
||||
## Removes the `file`. If this fails, `EOS` is raised. This does not fail
|
||||
## if the file never existed in the first place.
|
||||
if cremove(file) != 0'i32 and errno != ENOENT: OSError()
|
||||
if cremove(file) != 0'i32 and errno != ENOENT:
|
||||
raise newException(EOS, $strerror(errno))
|
||||
|
||||
proc execShellCmd*(command: string): int {.rtl, extern: "nos$1",
|
||||
tags: [FExecIO].} =
|
||||
|
|
@ -907,14 +991,14 @@ proc putEnv*(key, val: string) {.tags: [FWriteEnv].} =
|
|||
indx = high(environment)
|
||||
when defined(unix):
|
||||
if cputenv(environment[indx]) != 0'i32:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
else:
|
||||
when useWinUnicode:
|
||||
var k = newWideCString(key)
|
||||
var v = newWideCString(val)
|
||||
if SetEnvironmentVariableW(k, v) == 0'i32: OSError()
|
||||
if SetEnvironmentVariableW(k, v) == 0'i32: OSError(OSLastError())
|
||||
else:
|
||||
if SetEnvironmentVariableA(key, val) == 0'i32: OSError()
|
||||
if SetEnvironmentVariableA(key, val) == 0'i32: OSError(OSLastError())
|
||||
|
||||
iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [FReadEnv].} =
|
||||
## Iterate over all `environments variables`:idx:. In the first component
|
||||
|
|
@ -1044,10 +1128,12 @@ proc rawRemoveDir(dir: string) =
|
|||
wrapUnary(res, RemoveDirectoryW, dir)
|
||||
else:
|
||||
var res = RemoveDirectoryA(dir)
|
||||
if res == 0'i32 and GetLastError() != 3'i32 and
|
||||
GetLastError() != 18'i32: OSError()
|
||||
let lastError = OSLastError()
|
||||
if res == 0'i32 and lastError.int32 != 3'i32 and
|
||||
lastError.int32 != 18'i32 and lastError.int32 != 2'i32:
|
||||
OSError(lastError)
|
||||
else:
|
||||
if rmdir(dir) != 0'i32 and errno != ENOENT: OSError()
|
||||
if rmdir(dir) != 0'i32 and errno != ENOENT: OSError(OSLastError())
|
||||
|
||||
proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
|
||||
FWriteDir, FReadDir].} =
|
||||
|
|
@ -1065,14 +1151,14 @@ proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
|
|||
proc rawCreateDir(dir: string) =
|
||||
when defined(unix):
|
||||
if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
else:
|
||||
when useWinUnicode:
|
||||
wrapUnary(res, CreateDirectoryW, dir)
|
||||
else:
|
||||
var res = CreateDirectoryA(dir)
|
||||
if res == 0'i32 and GetLastError() != 183'i32:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
|
||||
proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} =
|
||||
## Creates the `directory`:idx: `dir`.
|
||||
|
|
@ -1213,7 +1299,7 @@ proc getFilePermissions*(filename: string): set[TFilePermission] {.
|
|||
## permission is available in any case.
|
||||
when defined(posix):
|
||||
var a: TStat
|
||||
if stat(filename, a) < 0'i32: OSError()
|
||||
if stat(filename, a) < 0'i32: OSError(OSLastError())
|
||||
result = {}
|
||||
if (a.st_mode and S_IRUSR) != 0'i32: result.incl(fpUserRead)
|
||||
if (a.st_mode and S_IWUSR) != 0'i32: result.incl(fpUserWrite)
|
||||
|
|
@ -1231,7 +1317,7 @@ proc getFilePermissions*(filename: string): set[TFilePermission] {.
|
|||
wrapUnary(res, GetFileAttributesW, filename)
|
||||
else:
|
||||
var res = GetFileAttributesA(filename)
|
||||
if res == -1'i32: OSError()
|
||||
if res == -1'i32: OSError(OSLastError())
|
||||
if (res and FILE_ATTRIBUTE_READONLY) != 0'i32:
|
||||
result = {fpUserExec, fpUserRead, fpGroupExec, fpGroupRead,
|
||||
fpOthersExec, fpOthersRead}
|
||||
|
|
@ -1257,13 +1343,13 @@ proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {.
|
|||
if fpOthersWrite in permissions: p = p or S_IWOTH
|
||||
if fpOthersExec in permissions: p = p or S_IXOTH
|
||||
|
||||
if chmod(filename, p) != 0: OSError()
|
||||
if chmod(filename, p) != 0: OSError(OSLastError())
|
||||
else:
|
||||
when useWinUnicode:
|
||||
wrapUnary(res, GetFileAttributesW, filename)
|
||||
else:
|
||||
var res = GetFileAttributesA(filename)
|
||||
if res == -1'i32: OSError()
|
||||
if res == -1'i32: OSError(OSLastError())
|
||||
if fpUserWrite in permissions:
|
||||
res = res and not FILE_ATTRIBUTE_READONLY
|
||||
else:
|
||||
|
|
@ -1272,7 +1358,7 @@ proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {.
|
|||
wrapBinary(res2, SetFileAttributesW, filename, res)
|
||||
else:
|
||||
var res2 = SetFileAttributesA(filename, res)
|
||||
if res2 == - 1'i32: OSError()
|
||||
if res2 == - 1'i32: OSError(OSLastError())
|
||||
|
||||
proc inclFilePermissions*(filename: string,
|
||||
permissions: set[TFilePermission]) {.
|
||||
|
|
@ -1368,6 +1454,9 @@ when defined(macosx):
|
|||
|
||||
proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [FReadIO].} =
|
||||
## Returns the filename of the application's executable.
|
||||
##
|
||||
## This procedure will resolve symlinks.
|
||||
##
|
||||
## **Note**: This does not work reliably on BSD.
|
||||
|
||||
# Linux: /proc/<pid>/exe
|
||||
|
|
@ -1397,6 +1486,8 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [FReadIO].} =
|
|||
result = newString(int(size))
|
||||
if getExecPath2(result, size):
|
||||
result = "" # error!
|
||||
if result.len > 0:
|
||||
result = result.expandFilename
|
||||
else:
|
||||
# little heuristic that may work on other POSIX-like systems:
|
||||
result = string(getEnv("_"))
|
||||
|
|
@ -1443,7 +1534,7 @@ proc getFileSize*(file: string): biggestInt {.rtl, extern: "nos$1",
|
|||
when defined(windows):
|
||||
var a: TWin32FindData
|
||||
var resA = findfirstFile(file, a)
|
||||
if resA == -1: OSError()
|
||||
if resA == -1: OSError(OSLastError())
|
||||
result = rdFileSize(a)
|
||||
findclose(resA)
|
||||
else:
|
||||
|
|
@ -1451,7 +1542,7 @@ proc getFileSize*(file: string): biggestInt {.rtl, extern: "nos$1",
|
|||
if open(f, file):
|
||||
result = getFileSize(f)
|
||||
close(f)
|
||||
else: OSError()
|
||||
else: OSError(OSLastError())
|
||||
|
||||
proc findExe*(exe: string): string {.tags: [FReadDir, FReadEnv].} =
|
||||
## Searches for `exe` in the current working directory and then
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
# TRUE and zero bytes returned (EOF).
|
||||
# TRUE and n (>0) bytes returned (good data).
|
||||
# FALSE and bytes returned undefined (system error).
|
||||
if a == 0 and br != 0: OSError()
|
||||
if a == 0 and br != 0: OSError(OSLastError())
|
||||
s.atTheEnd = br < bufLen
|
||||
result = br
|
||||
|
||||
|
|
@ -272,7 +272,7 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
var s = PFileHandleStream(s)
|
||||
var bytesWritten: int32
|
||||
var a = winlean.writeFile(s.handle, buffer, bufLen.cint, bytesWritten, nil)
|
||||
if a == 0: OSError()
|
||||
if a == 0: OSError(OSLastError())
|
||||
|
||||
proc newFileHandleStream(handle: THandle): PFileHandleStream =
|
||||
new(result)
|
||||
|
|
@ -313,7 +313,7 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
piInheritablePipe.lpSecurityDescriptor = nil
|
||||
piInheritablePipe.Binherithandle = 1
|
||||
if CreatePipe(Rdhandle, Wrhandle, piInheritablePipe, 1024) == 0'i32:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
|
||||
proc fileClose(h: THandle) {.inline.} =
|
||||
if h > 4: discard CloseHandle(h)
|
||||
|
|
@ -370,6 +370,7 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
else:
|
||||
success = winlean.CreateProcessA(nil,
|
||||
cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, SI, ProcInfo)
|
||||
let lastError = OSLastError()
|
||||
|
||||
if poParentStreams notin options:
|
||||
FileClose(si.hStdInput)
|
||||
|
|
@ -379,7 +380,7 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
|
||||
if e != nil: dealloc(e)
|
||||
dealloc(cmdl)
|
||||
if success == 0: OSError()
|
||||
if success == 0: OSError(lastError)
|
||||
# Close the handle now so anyone waiting is woken:
|
||||
discard closeHandle(procInfo.hThread)
|
||||
result.FProcessHandle = procInfo.hProcess
|
||||
|
|
@ -450,7 +451,7 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
var res = winlean.CreateProcessA(nil, command, nil, nil, 0,
|
||||
NORMAL_PRIORITY_CLASS, nil, nil, SI, ProcInfo)
|
||||
if res == 0:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
else:
|
||||
Process = ProcInfo.hProcess
|
||||
discard CloseHandle(ProcInfo.hThread)
|
||||
|
|
@ -473,7 +474,7 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
of WAIT_TIMEOUT:
|
||||
return 0
|
||||
of WAIT_FAILED:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
else:
|
||||
var i = ret - WAIT_OBJECT_0
|
||||
readfds.del(i)
|
||||
|
|
@ -531,7 +532,7 @@ elif not defined(useNimRtl):
|
|||
if poParentStreams notin options:
|
||||
if pipe(p_stdin) != 0'i32 or pipe(p_stdout) != 0'i32 or
|
||||
pipe(p_stderr) != 0'i32:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
|
||||
var pid: TPid
|
||||
when defined(posix_spawn) and not defined(useFork):
|
||||
|
|
@ -539,7 +540,7 @@ elif not defined(useNimRtl):
|
|||
var fops: Tposix_spawn_file_actions
|
||||
|
||||
template chck(e: expr) =
|
||||
if e != 0'i32: OSError()
|
||||
if e != 0'i32: OSError(OSLastError())
|
||||
|
||||
chck posix_spawn_file_actions_init(fops)
|
||||
chck posix_spawnattr_init(attr)
|
||||
|
|
@ -584,20 +585,20 @@ elif not defined(useNimRtl):
|
|||
else:
|
||||
|
||||
Pid = fork()
|
||||
if Pid < 0: OSError()
|
||||
if Pid < 0: OSError(OSLastError())
|
||||
if pid == 0:
|
||||
## child process:
|
||||
|
||||
if poParentStreams notin options:
|
||||
discard close(p_stdin[writeIdx])
|
||||
if dup2(p_stdin[readIdx], readIdx) < 0: OSError()
|
||||
if dup2(p_stdin[readIdx], readIdx) < 0: OSError(OSLastError())
|
||||
discard close(p_stdout[readIdx])
|
||||
if dup2(p_stdout[writeIdx], writeIdx) < 0: OSError()
|
||||
if dup2(p_stdout[writeIdx], writeIdx) < 0: OSError(OSLastError())
|
||||
discard close(p_stderr[readIdx])
|
||||
if poStdErrToStdOut in options:
|
||||
if dup2(p_stdout[writeIdx], 2) < 0: OSError()
|
||||
if dup2(p_stdout[writeIdx], 2) < 0: OSError(OSLastError())
|
||||
else:
|
||||
if dup2(p_stderr[writeIdx], 2) < 0: OSError()
|
||||
if dup2(p_stderr[writeIdx], 2) < 0: OSError(OSLastError())
|
||||
|
||||
# Create a new process group
|
||||
if setpgid(0, 0) == -1: quit("setpgid call failed: " & $strerror(errno))
|
||||
|
|
@ -652,10 +653,10 @@ elif not defined(useNimRtl):
|
|||
discard close(p.errorHandle)
|
||||
|
||||
proc suspend(p: PProcess) =
|
||||
if kill(-p.id, SIGSTOP) != 0'i32: OSError()
|
||||
if kill(-p.id, SIGSTOP) != 0'i32: OSError(OSLastError())
|
||||
|
||||
proc resume(p: PProcess) =
|
||||
if kill(-p.id, SIGCONT) != 0'i32: OSError()
|
||||
if kill(-p.id, SIGCONT) != 0'i32: OSError(OSLastError())
|
||||
|
||||
proc running(p: PProcess): bool =
|
||||
var ret = waitPid(p.id, p.exitCode, WNOHANG)
|
||||
|
|
@ -665,8 +666,8 @@ elif not defined(useNimRtl):
|
|||
proc terminate(p: PProcess) =
|
||||
if kill(-p.id, SIGTERM) == 0'i32:
|
||||
if p.running():
|
||||
if kill(-p.id, SIGKILL) != 0'i32: OSError()
|
||||
else: OSError()
|
||||
if kill(-p.id, SIGKILL) != 0'i32: OSError(OSLastError())
|
||||
else: OSError(OSLastError())
|
||||
|
||||
proc waitForExit(p: PProcess, timeout: int = -1): int =
|
||||
#if waitPid(p.id, p.exitCode, 0) == int(p.id):
|
||||
|
|
@ -676,7 +677,7 @@ elif not defined(useNimRtl):
|
|||
if p.exitCode != -3: return p.exitCode
|
||||
if waitPid(p.id, p.exitCode, 0) < 0:
|
||||
p.exitCode = -3
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
result = int(p.exitCode) shr 8
|
||||
|
||||
proc peekExitCode(p: PProcess): int =
|
||||
|
|
@ -690,7 +691,7 @@ elif not defined(useNimRtl):
|
|||
proc createStream(stream: var PStream, handle: var TFileHandle,
|
||||
fileMode: TFileMode) =
|
||||
var f: TFile
|
||||
if not open(f, handle, fileMode): OSError()
|
||||
if not open(f, handle, fileMode): OSError(OSLastError())
|
||||
stream = newFileStream(f)
|
||||
|
||||
proc inputStream(p: PProcess): PStream =
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@ type
|
|||
# implementation
|
||||
|
||||
const
|
||||
SymChars: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF', '.'}
|
||||
SymChars: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF', '.',
|
||||
'/', '\\'}
|
||||
|
||||
proc rawGetTok(c: var TCfgParser, tok: var TToken)
|
||||
|
||||
|
|
@ -149,7 +150,7 @@ proc getEscapedChar(c: var TCfgParser, tok: var TToken) =
|
|||
of 't', 'T':
|
||||
add(tok.literal, '\t')
|
||||
Inc(c.bufpos)
|
||||
of '\'', '\"':
|
||||
of '\'', '"':
|
||||
add(tok.literal, c.buf[c.bufpos])
|
||||
Inc(c.bufpos)
|
||||
of '\\':
|
||||
|
|
@ -178,7 +179,7 @@ proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) =
|
|||
var pos = c.bufPos + 1 # skip "
|
||||
var buf = c.buf # put `buf` in a register
|
||||
tok.kind = tkSymbol
|
||||
if (buf[pos] == '\"') and (buf[pos + 1] == '\"'):
|
||||
if (buf[pos] == '"') and (buf[pos + 1] == '"'):
|
||||
# long string literal:
|
||||
inc(pos, 2) # skip ""
|
||||
# skip leading newline:
|
||||
|
|
@ -186,9 +187,9 @@ proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) =
|
|||
buf = c.buf
|
||||
while true:
|
||||
case buf[pos]
|
||||
of '\"':
|
||||
if (buf[pos + 1] == '\"') and (buf[pos + 2] == '\"'): break
|
||||
add(tok.literal, '\"')
|
||||
of '"':
|
||||
if (buf[pos + 1] == '"') and (buf[pos + 2] == '"'): break
|
||||
add(tok.literal, '"')
|
||||
Inc(pos)
|
||||
of '\c', '\L':
|
||||
pos = HandleCRLF(c, pos)
|
||||
|
|
@ -205,7 +206,7 @@ proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) =
|
|||
# ordinary string literal
|
||||
while true:
|
||||
var ch = buf[pos]
|
||||
if ch == '\"':
|
||||
if ch == '"':
|
||||
inc(pos) # skip '"'
|
||||
break
|
||||
if ch in {'\c', '\L', lexbase.EndOfFile}:
|
||||
|
|
@ -278,7 +279,7 @@ proc rawGetTok(c: var TCfgParser, tok: var TToken) =
|
|||
tok.kind = tkBracketRi
|
||||
Inc(c.bufpos)
|
||||
tok.literal = "]"
|
||||
of '\"':
|
||||
of '"':
|
||||
getString(c, tok, false)
|
||||
of lexbase.EndOfFile:
|
||||
tok.kind = tkEof
|
||||
|
|
@ -351,7 +352,7 @@ proc next*(c: var TCfgParser): TCfgEvent {.rtl, extern: "npc$1".} =
|
|||
rawGetTok(c, c.tok)
|
||||
else:
|
||||
result.kind = cfgError
|
||||
result.msg = errorStr(c, "\']\' expected, but found: " & c.tok.literal)
|
||||
result.msg = errorStr(c, "']' expected, but found: " & c.tok.literal)
|
||||
of tkInvalid, tkEquals, tkColon, tkBracketRi:
|
||||
result.kind = cfgError
|
||||
result.msg = errorStr(c, "invalid token: " & c.tok.literal)
|
||||
|
|
|
|||
|
|
@ -131,6 +131,10 @@ proc close*(my: var TXmlParser) {.inline.} =
|
|||
## closes the parser `my` and its associated input stream.
|
||||
lexbase.close(my)
|
||||
|
||||
proc kind*(my: TXmlParser): TXmlEventKind {.inline.} =
|
||||
## returns the current event type for the XML parser
|
||||
return my.kind
|
||||
|
||||
proc charData*(my: TXmlParser): string {.inline.} =
|
||||
## returns the character data for the events: ``xmlCharData``,
|
||||
## ``xmlWhitespace``, ``xmlComment``, ``xmlCData``, ``xmlSpecial``
|
||||
|
|
@ -138,10 +142,6 @@ proc charData*(my: TXmlParser): string {.inline.} =
|
|||
xmlSpecial})
|
||||
return my.a
|
||||
|
||||
proc kind*(my: TXmlParser): TXmlEventKind {.inline.} =
|
||||
## returns the current event type for the XML parser
|
||||
return my.kind
|
||||
|
||||
proc elementName*(my: TXmlParser): string {.inline.} =
|
||||
## returns the element name for the events: ``xmlElementStart``,
|
||||
## ``xmlElementEnd``, ``xmlElementOpen``
|
||||
|
|
@ -173,6 +173,16 @@ proc PIRest*(my: TXmlParser): string {.inline.} =
|
|||
assert(my.kind == xmlPI)
|
||||
return my.b
|
||||
|
||||
proc rawData*(my: TXmlParser): string {.inline.} =
|
||||
## returns the underlying 'data' string by reference.
|
||||
## This is only used for speed hacks.
|
||||
shallowCopy(result, my.a)
|
||||
|
||||
proc rawData2*(my: TXmlParser): string {.inline.} =
|
||||
## returns the underlying second 'data' string by reference.
|
||||
## This is only used for speed hacks.
|
||||
shallowCopy(result, my.b)
|
||||
|
||||
proc getColumn*(my: TXmlParser): int {.inline.} =
|
||||
## get the current column the parser has arrived at.
|
||||
result = getColNumber(my, my.bufPos)
|
||||
|
|
@ -439,6 +449,7 @@ proc parseTag(my: var TXmlParser) =
|
|||
if my.buf[my.bufpos] == '/' and my.buf[my.bufpos+1] == '>':
|
||||
inc(my.bufpos, 2)
|
||||
my.state = stateEmptyElementTag
|
||||
my.c = nil
|
||||
elif my.buf[my.bufpos] == '>':
|
||||
inc(my.bufpos)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ type
|
|||
of pkChar, pkGreedyRepChar: ch: char
|
||||
of pkCharChoice, pkGreedyRepSet: charChoice: ref set[char]
|
||||
of pkNonTerminal: nt: PNonTerminal
|
||||
of pkBackRef..pkBackRefIgnoreStyle: index: range[1..MaxSubpatterns]
|
||||
of pkBackRef..pkBackRefIgnoreStyle: index: range[0..MaxSubpatterns]
|
||||
else: sons: seq[TNode]
|
||||
PNonTerminal* = ref TNonTerminal
|
||||
|
||||
|
|
@ -870,7 +870,6 @@ template `=~`*(s: string, pattern: TPeg): bool =
|
|||
bind maxSubpatterns
|
||||
when not definedInScope(matches):
|
||||
var matches {.inject.}: array[0..maxSubpatterns-1, string]
|
||||
{.warning: "injected 'matches' might be affected by new scoping rules in 0.9.4".}
|
||||
match(s, pattern, matches)
|
||||
|
||||
# ------------------------- more string handling ------------------------------
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ proc open*(host = "localhost", port = 6379.TPort): TRedis =
|
|||
## Opens a connection to the redis server.
|
||||
result.socket = socket(buffered = false)
|
||||
if result.socket == InvalidSocket:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
result.socket.connect(host, port)
|
||||
|
||||
proc raiseInvalidReply(expected, got: char) =
|
||||
|
|
@ -50,34 +50,31 @@ proc raiseNoOK(status: string) =
|
|||
|
||||
proc parseStatus(r: TRedis): TRedisStatus =
|
||||
var line = ""
|
||||
if r.socket.recvLine(line):
|
||||
if line == "":
|
||||
raise newException(ERedis, "Server closed connection prematurely")
|
||||
r.socket.readLine(line)
|
||||
if line == "":
|
||||
raise newException(ERedis, "Server closed connection prematurely")
|
||||
|
||||
if line[0] == '-':
|
||||
raise newException(ERedis, strip(line))
|
||||
if line[0] != '+':
|
||||
raiseInvalidReply('+', line[0])
|
||||
|
||||
if line[0] == '-':
|
||||
raise newException(ERedis, strip(line))
|
||||
if line[0] != '+':
|
||||
raiseInvalidReply('+', line[0])
|
||||
|
||||
return line.substr(1) # Strip '+'
|
||||
else:
|
||||
OSError()
|
||||
return line.substr(1) # Strip '+'
|
||||
|
||||
proc parseInteger(r: TRedis): TRedisInteger =
|
||||
var line = ""
|
||||
if r.socket.recvLine(line):
|
||||
if line == "":
|
||||
raise newException(ERedis, "Server closed connection prematurely")
|
||||
r.socket.readLine(line)
|
||||
if line == "":
|
||||
raise newException(ERedis, "Server closed connection prematurely")
|
||||
|
||||
if line[0] == '-':
|
||||
raise newException(ERedis, strip(line))
|
||||
if line[0] != ':':
|
||||
raiseInvalidReply(':', line[0])
|
||||
|
||||
# Strip ':'
|
||||
if parseBiggestInt(line, result, 1) == 0:
|
||||
raise newException(EInvalidReply, "Unable to parse integer.")
|
||||
else: OSError()
|
||||
if line[0] == '-':
|
||||
raise newException(ERedis, strip(line))
|
||||
if line[0] != ':':
|
||||
raiseInvalidReply(':', line[0])
|
||||
|
||||
# Strip ':'
|
||||
if parseBiggestInt(line, result, 1) == 0:
|
||||
raise newException(EInvalidReply, "Unable to parse integer.")
|
||||
|
||||
proc recv(sock: TSocket, size: int): TaintedString =
|
||||
result = newString(size).TaintedString
|
||||
|
|
@ -86,8 +83,7 @@ proc recv(sock: TSocket, size: int): TaintedString =
|
|||
|
||||
proc parseBulk(r: TRedis, allowMBNil = False): TRedisString =
|
||||
var line = ""
|
||||
if not r.socket.recvLine(line.TaintedString):
|
||||
raise newException(EInvalidReply, "recvLine failed")
|
||||
r.socket.readLine(line.TaintedString)
|
||||
|
||||
# Error.
|
||||
if line[0] == '-':
|
||||
|
|
@ -110,8 +106,7 @@ proc parseBulk(r: TRedis, allowMBNil = False): TRedisString =
|
|||
|
||||
proc parseMultiBulk(r: TRedis): TRedisList =
|
||||
var line = TaintedString""
|
||||
if not r.socket.recvLine(line):
|
||||
raise newException(EInvalidReply, "recvLine failed")
|
||||
r.socket.readLine(line)
|
||||
|
||||
if line.string[0] != '*':
|
||||
raiseInvalidReply('*', line.string[0])
|
||||
|
|
@ -848,10 +843,8 @@ proc shutdown*(r: TRedis) =
|
|||
## Synchronously save the dataset to disk and then shut down the server
|
||||
r.sendCommand("SHUTDOWN")
|
||||
var s = "".TaintedString
|
||||
if r.socket.recvLine(s):
|
||||
if s.string.len != 0: raise newException(ERedis, s.string)
|
||||
else:
|
||||
OSError()
|
||||
r.socket.readLine(s)
|
||||
if s.string.len != 0: raise newException(ERedis, s.string)
|
||||
|
||||
proc slaveof*(r: TRedis, host: string, port: string) =
|
||||
## Make the server a slave of another instance, or promote it as master
|
||||
|
|
|
|||
|
|
@ -175,6 +175,15 @@ proc recvBufferAsync(client: PAsyncClient, L: int): TReadLineResult =
|
|||
if ret == L:
|
||||
return ReadFullLine
|
||||
|
||||
proc checkCloseSocket(client: PAsyncClient) =
|
||||
if not client.c.isClosed:
|
||||
if client.c.isSendDataBuffered:
|
||||
client.c.setHandleWrite do (s: PAsyncSocket):
|
||||
if not s.isClosed and not s.isSendDataBuffered:
|
||||
s.close()
|
||||
s.delHandleWrite()
|
||||
else: client.c.close()
|
||||
|
||||
proc handleClientRead(client: PAsyncClient, s: PAsyncScgiState) =
|
||||
case client.mode
|
||||
of ClientReadChar:
|
||||
|
|
@ -206,7 +215,7 @@ proc handleClientRead(client: PAsyncClient, s: PAsyncScgiState) =
|
|||
client.mode = ClientReadContent
|
||||
else:
|
||||
s.handleRequest(client.c, client.input, client.headers)
|
||||
if not client.c.isClosed: client.c.close()
|
||||
checkCloseSocket(client)
|
||||
of ReadPartialLine, ReadDisconnected, ReadNone: return
|
||||
of ClientReadContent:
|
||||
let L = parseInt(client.headers["CONTENT_LENGTH"])-client.input.len
|
||||
|
|
@ -215,11 +224,11 @@ proc handleClientRead(client: PAsyncClient, s: PAsyncScgiState) =
|
|||
case ret
|
||||
of ReadFullLine:
|
||||
s.handleRequest(client.c, client.input, client.headers)
|
||||
if not client.c.isClosed: client.c.close()
|
||||
checkCloseSocket(client)
|
||||
of ReadPartialLine, ReadDisconnected, ReadNone: return
|
||||
else:
|
||||
s.handleRequest(client.c, client.input, client.headers)
|
||||
if not client.c.isClosed: client.c.close()
|
||||
checkCloseSocket(client)
|
||||
|
||||
proc handleAccept(sock: PAsyncSocket, s: PAsyncScgiState) =
|
||||
var client: PAsyncSocket
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ when defined(ssl):
|
|||
if err == 0:
|
||||
raise newException(ESSL, "No error reported.")
|
||||
if err == -1:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
var errStr = ErrErrorString(err, nil)
|
||||
raise newException(ESSL, $errStr)
|
||||
|
||||
|
|
@ -347,24 +347,23 @@ proc SocketError*(socket: TSocket, err: int = -1, async = false) =
|
|||
else: SSLError("Unknown Error")
|
||||
|
||||
if err == -1 and not (when defined(ssl): socket.isSSL else: false):
|
||||
let lastError = OSLastError()
|
||||
if async:
|
||||
when defined(windows):
|
||||
# TODO: Test on Windows
|
||||
var err = WSAGetLastError()
|
||||
if err == WSAEWOULDBLOCK:
|
||||
if lastError.int32 == WSAEWOULDBLOCK:
|
||||
return
|
||||
else: OSError()
|
||||
else: OSError(lastError)
|
||||
else:
|
||||
if errno == EAGAIN or errno == EWOULDBLOCK:
|
||||
if lastError.int32 == EAGAIN or lastError.int32 == EWOULDBLOCK:
|
||||
return
|
||||
else: OSError()
|
||||
else: OSError()
|
||||
else: OSError(lastError)
|
||||
else: OSError(lastError)
|
||||
|
||||
proc listen*(socket: TSocket, backlog = SOMAXCONN) {.tags: [FReadIO].} =
|
||||
## Marks ``socket`` as accepting connections.
|
||||
## ``Backlog`` specifies the maximum length of the
|
||||
## queue of pending connections.
|
||||
if listen(socket.fd, cint(backlog)) < 0'i32: OSError()
|
||||
if listen(socket.fd, cint(backlog)) < 0'i32: OSError(OSLastError())
|
||||
|
||||
proc invalidIp4(s: string) {.noreturn, noinline.} =
|
||||
raise newException(EInvalidValue, "invalid ip4 address: " & s)
|
||||
|
|
@ -403,7 +402,7 @@ template gaiNim(a, p, h, list: expr): stmt =
|
|||
var gaiResult = getAddrInfo(a, $p, addr(h), list)
|
||||
if gaiResult != 0'i32:
|
||||
when defined(windows):
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
else:
|
||||
OSError($gai_strerror(gaiResult))
|
||||
|
||||
|
|
@ -423,7 +422,7 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") {.
|
|||
name.sin_addr.s_addr = sockets.htonl(INADDR_ANY)
|
||||
if bindSocket(socket.fd, cast[ptr TSockAddr](addr(name)),
|
||||
sizeof(name).TSockLen) < 0'i32:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
else:
|
||||
var hints: TAddrInfo
|
||||
var aiList: ptr TAddrInfo = nil
|
||||
|
|
@ -432,21 +431,7 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") {.
|
|||
hints.ai_protocol = toInt(IPPROTO_TCP)
|
||||
gaiNim(address, port, hints, aiList)
|
||||
if bindSocket(socket.fd, aiList.ai_addr, aiList.ai_addrLen.TSockLen) < 0'i32:
|
||||
OSError()
|
||||
|
||||
when false:
|
||||
proc bindAddr*(socket: TSocket, port = TPort(0)) =
|
||||
## binds a port number to a socket.
|
||||
var name: Tsockaddr_in
|
||||
when defined(Windows):
|
||||
name.sin_family = int16(ord(AF_INET))
|
||||
else:
|
||||
name.sin_family = posix.AF_INET
|
||||
name.sin_port = sockets.htons(int16(port))
|
||||
name.sin_addr.s_addr = sockets.htonl(INADDR_ANY)
|
||||
if bindSocket(cint(socket), cast[ptr TSockAddr](addr(name)),
|
||||
sizeof(name).TSockLen) < 0'i32:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
|
||||
proc getSockName*(socket: TSocket): TPort =
|
||||
## returns the socket's associated port number.
|
||||
|
|
@ -460,7 +445,7 @@ proc getSockName*(socket: TSocket): TPort =
|
|||
var namelen = sizeof(name).TSockLen
|
||||
if getsockname(socket.fd, cast[ptr TSockAddr](addr(name)),
|
||||
addr(namelen)) == -1'i32:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
result = TPort(sockets.ntohs(name.sin_port))
|
||||
|
||||
template acceptAddrPlain(noClientRet, successRet: expr,
|
||||
|
|
@ -472,26 +457,25 @@ template acceptAddrPlain(noClientRet, successRet: expr,
|
|||
addr(addrLen))
|
||||
|
||||
if sock < 0:
|
||||
# TODO: Test on Windows.
|
||||
let err = OSLastError()
|
||||
when defined(windows):
|
||||
var err = WSAGetLastError()
|
||||
if err == WSAEINPROGRESS:
|
||||
if err.int32 == WSAEINPROGRESS:
|
||||
client = InvalidSocket
|
||||
address = ""
|
||||
when noClientRet.int == -1:
|
||||
return
|
||||
else:
|
||||
return noClientRet
|
||||
else: OSError()
|
||||
else: OSError(err)
|
||||
else:
|
||||
if errno == EAGAIN or errno == EWOULDBLOCK:
|
||||
if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK:
|
||||
client = InvalidSocket
|
||||
address = ""
|
||||
when noClientRet.int == -1:
|
||||
return
|
||||
else:
|
||||
return noClientRet
|
||||
else: OSError()
|
||||
else: OSError(err)
|
||||
else:
|
||||
client.fd = sock
|
||||
client.isBuffered = server.isBuffered
|
||||
|
|
@ -644,7 +628,7 @@ proc getServByName*(name, proto: string): TServent {.tags: [FReadIO].} =
|
|||
var s = winlean.getservbyname(name, proto)
|
||||
else:
|
||||
var s = posix.getservbyname(name, proto)
|
||||
if s == nil: OSError()
|
||||
if s == nil: OSError(OSLastError())
|
||||
result.name = $s.s_name
|
||||
result.aliases = cstringArrayToSeq(s.s_aliases)
|
||||
result.port = TPort(s.s_port)
|
||||
|
|
@ -656,7 +640,7 @@ proc getServByPort*(port: TPort, proto: string): TServent {.tags: [FReadIO].} =
|
|||
var s = winlean.getservbyport(ze(int16(port)).cint, proto)
|
||||
else:
|
||||
var s = posix.getservbyport(ze(int16(port)).cint, proto)
|
||||
if s == nil: OSError()
|
||||
if s == nil: OSError(OSLastError())
|
||||
result.name = $s.s_name
|
||||
result.aliases = cstringArrayToSeq(s.s_aliases)
|
||||
result.port = TPort(s.s_port)
|
||||
|
|
@ -670,7 +654,7 @@ proc getHostByAddr*(ip: string): THostEnt {.tags: [FReadIO].} =
|
|||
when defined(windows):
|
||||
var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint,
|
||||
cint(sockets.AF_INET))
|
||||
if s == nil: OSError()
|
||||
if s == nil: OSError(OSLastError())
|
||||
else:
|
||||
var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).TSockLen,
|
||||
cint(posix.AF_INET))
|
||||
|
|
@ -687,7 +671,7 @@ proc getHostByAddr*(ip: string): THostEnt {.tags: [FReadIO].} =
|
|||
elif s.h_addrtype == posix.AF_INET6:
|
||||
result.addrType = AF_INET6
|
||||
else:
|
||||
OSError("unknown h_addrtype")
|
||||
raise newException(EOS, "unknown h_addrtype")
|
||||
result.addrList = cstringArrayToSeq(s.h_addr_list)
|
||||
result.length = int(s.h_length)
|
||||
|
||||
|
|
@ -697,7 +681,7 @@ proc getHostByName*(name: string): THostEnt {.tags: [FReadIO].} =
|
|||
var s = winlean.gethostbyname(name)
|
||||
else:
|
||||
var s = posix.gethostbyname(name)
|
||||
if s == nil: OSError()
|
||||
if s == nil: OSError(OSLastError())
|
||||
result.name = $s.h_name
|
||||
result.aliases = cstringArrayToSeq(s.h_aliases)
|
||||
when defined(windows):
|
||||
|
|
@ -708,7 +692,7 @@ proc getHostByName*(name: string): THostEnt {.tags: [FReadIO].} =
|
|||
elif s.h_addrtype == posix.AF_INET6:
|
||||
result.addrType = AF_INET6
|
||||
else:
|
||||
OSError("unknown h_addrtype")
|
||||
raise newException(EOS, "unknown h_addrtype")
|
||||
result.addrList = cstringArrayToSeq(s.h_addr_list)
|
||||
result.length = int(s.h_length)
|
||||
|
||||
|
|
@ -719,7 +703,7 @@ proc getSockOptInt*(socket: TSocket, level, optname: int): int {.
|
|||
var size = sizeof(res).TSockLen
|
||||
if getsockopt(socket.fd, cint(level), cint(optname),
|
||||
addr(res), addr(size)) < 0'i32:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
result = int(res)
|
||||
|
||||
proc setSockOptInt*(socket: TSocket, level, optname, optval: int) {.
|
||||
|
|
@ -728,7 +712,7 @@ proc setSockOptInt*(socket: TSocket, level, optname, optval: int) {.
|
|||
var value = cint(optval)
|
||||
if setsockopt(socket.fd, cint(level), cint(optname), addr(value),
|
||||
sizeof(value).TSockLen) < 0'i32:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
|
||||
proc connect*(socket: TSocket, address: string, port = TPort(0),
|
||||
af: TDomain = AF_INET) {.tags: [FReadIO].} =
|
||||
|
|
@ -746,15 +730,17 @@ proc connect*(socket: TSocket, address: string, port = TPort(0),
|
|||
gaiNim(address, port, hints, aiList)
|
||||
# try all possibilities:
|
||||
var success = false
|
||||
var lastError: TOSErrorCode
|
||||
var it = aiList
|
||||
while it != nil:
|
||||
if connect(socket.fd, it.ai_addr, it.ai_addrlen.TSockLen) == 0'i32:
|
||||
success = true
|
||||
break
|
||||
else: lastError = OSLastError()
|
||||
it = it.ai_next
|
||||
|
||||
freeaddrinfo(aiList)
|
||||
if not success: OSError()
|
||||
if not success: OSError(lastError)
|
||||
|
||||
when defined(ssl):
|
||||
if socket.isSSL:
|
||||
|
|
@ -807,6 +793,7 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
|
|||
gaiNim(name, port, hints, aiList)
|
||||
# try all possibilities:
|
||||
var success = false
|
||||
var lastError: TOSErrorCode
|
||||
var it = aiList
|
||||
while it != nil:
|
||||
var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.TSockLen)
|
||||
|
|
@ -814,22 +801,21 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
|
|||
success = true
|
||||
break
|
||||
else:
|
||||
# TODO: Test on Windows.
|
||||
lastError = OSLastError()
|
||||
when defined(windows):
|
||||
var err = WSAGetLastError()
|
||||
# Windows EINTR doesn't behave same as POSIX.
|
||||
if err == WSAEWOULDBLOCK:
|
||||
if lastError.int32 == WSAEWOULDBLOCK:
|
||||
success = true
|
||||
break
|
||||
else:
|
||||
if errno == EINTR or errno == EINPROGRESS:
|
||||
if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS:
|
||||
success = true
|
||||
break
|
||||
|
||||
it = it.ai_next
|
||||
|
||||
freeaddrinfo(aiList)
|
||||
if not success: OSError()
|
||||
if not success: OSError(lastError)
|
||||
when defined(ssl):
|
||||
if socket.isSSL:
|
||||
socket.sslNoHandshake = true
|
||||
|
|
@ -1110,7 +1096,7 @@ proc waitFor(socket: TSocket, waited: var float, timeout, size: int,
|
|||
var s = @[socket]
|
||||
var startTime = epochTime()
|
||||
let selRet = select(s, timeout - int(waited * 1000.0))
|
||||
if selRet < 0: OSError()
|
||||
if selRet < 0: OSError(OSLastError())
|
||||
if selRet != 1:
|
||||
raise newException(ETimeout, "Call to '" & funcName & "' timed out.")
|
||||
waited += (epochTime() - startTime)
|
||||
|
|
@ -1259,14 +1245,14 @@ proc readLine*(socket: TSocket, line: var TaintedString, timeout = -1) {.
|
|||
var c: char
|
||||
discard waitFor(socket, waited, timeout, 1, "readLine")
|
||||
var n = recv(socket, addr(c), 1)
|
||||
if n < 0: OSError()
|
||||
if n < 0: OSError(OSLastError())
|
||||
elif n == 0: return
|
||||
if c == '\r':
|
||||
discard waitFor(socket, waited, timeout, 1, "readLine")
|
||||
n = peekChar(socket, c)
|
||||
if n > 0 and c == '\L':
|
||||
discard recv(socket, addr(c), 1)
|
||||
elif n <= 0: OSError()
|
||||
elif n <= 0: OSError(OSLastError())
|
||||
addNlIfEmpty()
|
||||
return
|
||||
elif c == '\L':
|
||||
|
|
@ -1326,6 +1312,7 @@ proc readLineAsync*(socket: TSocket,
|
|||
while true:
|
||||
var c: char
|
||||
var n = recv(socket, addr(c), 1)
|
||||
#echo(n)
|
||||
if n < 0:
|
||||
if line.len == 0: errorOrNone else: return ReadPartialLine
|
||||
elif n == 0:
|
||||
|
|
@ -1352,7 +1339,7 @@ proc recv*(socket: TSocket): TaintedString {.tags: [FReadIO], deprecated.} =
|
|||
var pos = 0
|
||||
while true:
|
||||
var bytesRead = recv(socket, addr(string(result)[pos]), bufSize-1)
|
||||
if bytesRead == -1: OSError()
|
||||
if bytesRead == -1: OSError(OSLastError())
|
||||
setLen(result.string, pos + bytesRead)
|
||||
if bytesRead != bufSize-1: break
|
||||
# increase capacity:
|
||||
|
|
@ -1364,7 +1351,7 @@ proc recv*(socket: TSocket): TaintedString {.tags: [FReadIO], deprecated.} =
|
|||
while true:
|
||||
var bytesRead = recv(socket, cstring(buf), bufSize-1)
|
||||
# Error
|
||||
if bytesRead == -1: OSError()
|
||||
if bytesRead == -1: OSError(OSLastError())
|
||||
|
||||
buf[bytesRead] = '\0' # might not be necessary
|
||||
setLen(buf, bytesRead)
|
||||
|
|
@ -1421,16 +1408,15 @@ proc recvAsync*(socket: TSocket, s: var TaintedString): bool {.
|
|||
else: SSLError("Unknown Error")
|
||||
|
||||
if bytesRead == -1 and not (when defined(ssl): socket.isSSL else: false):
|
||||
let err = OSLastError()
|
||||
when defined(windows):
|
||||
# TODO: Test on Windows
|
||||
var err = WSAGetLastError()
|
||||
if err == WSAEWOULDBLOCK:
|
||||
if err.int32 == WSAEWOULDBLOCK:
|
||||
return False
|
||||
else: OSError()
|
||||
else: OSError(err)
|
||||
else:
|
||||
if errno == EAGAIN or errno == EWOULDBLOCK:
|
||||
if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK:
|
||||
return False
|
||||
else: OSError()
|
||||
else: OSError(err)
|
||||
|
||||
setLen(s.string, pos + bytesRead)
|
||||
if bytesRead != bufSize-1: break
|
||||
|
|
@ -1475,16 +1461,15 @@ proc recvFromAsync*(socket: TSocket, data: var String, length: int,
|
|||
result = true
|
||||
var callRes = recvFrom(socket, data, length, address, port, flags)
|
||||
if callRes < 0:
|
||||
let err = OSLastError()
|
||||
when defined(windows):
|
||||
# TODO: Test on Windows
|
||||
var err = WSAGetLastError()
|
||||
if err == WSAEWOULDBLOCK:
|
||||
if err.int32 == WSAEWOULDBLOCK:
|
||||
return False
|
||||
else: OSError()
|
||||
else: OSError(err)
|
||||
else:
|
||||
if errno == EAGAIN or errno == EWOULDBLOCK:
|
||||
if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK:
|
||||
return False
|
||||
else: OSError()
|
||||
else: OSError(err)
|
||||
|
||||
proc skip*(socket: TSocket) {.tags: [FReadIO], deprecated.} =
|
||||
## skips all the data that is pending for the socket
|
||||
|
|
@ -1531,7 +1516,7 @@ proc send*(socket: TSocket, data: string) {.tags: [FWriteIO].} =
|
|||
if socket.isSSL:
|
||||
SSLError()
|
||||
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
|
||||
proc sendAsync*(socket: TSocket, data: string): int {.tags: [FWriteIO].} =
|
||||
## sends data to a non-blocking socket.
|
||||
|
|
@ -1561,16 +1546,15 @@ proc sendAsync*(socket: TSocket, data: string): int {.tags: [FWriteIO].} =
|
|||
else:
|
||||
return
|
||||
if result == -1:
|
||||
let err = OSLastError()
|
||||
when defined(windows):
|
||||
var err = WSAGetLastError()
|
||||
# TODO: Test on windows.
|
||||
if err == WSAEINPROGRESS:
|
||||
if err.int32 == WSAEINPROGRESS:
|
||||
return 0
|
||||
else: OSError()
|
||||
else: OSError(err)
|
||||
else:
|
||||
if errno == EAGAIN or errno == EWOULDBLOCK:
|
||||
if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK:
|
||||
return 0
|
||||
else: OSError()
|
||||
else: OSError(err)
|
||||
|
||||
|
||||
proc trySend*(socket: TSocket, data: string): bool {.tags: [FWriteIO].} =
|
||||
|
|
@ -1626,15 +1610,15 @@ proc setBlocking(s: TSocket, blocking: bool) =
|
|||
when defined(Windows):
|
||||
var mode = clong(ord(not blocking)) # 1 for non-blocking, 0 for blocking
|
||||
if ioctlsocket(TWinSocket(s.fd), FIONBIO, addr(mode)) == -1:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
else: # BSD sockets
|
||||
var x: int = fcntl(s.fd, F_GETFL, 0)
|
||||
if x == -1:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
else:
|
||||
var mode = if blocking: x and not O_NONBLOCK else: x or O_NONBLOCK
|
||||
if fcntl(s.fd, F_SETFL, mode) == -1:
|
||||
OSError()
|
||||
OSError(OSLastError())
|
||||
s.nonblocking = not blocking
|
||||
|
||||
proc connect*(socket: TSocket, address: string, port = TPort(0), timeout: int,
|
||||
|
|
@ -1665,6 +1649,6 @@ proc getFD*(socket: TSocket): cint = return socket.fd
|
|||
|
||||
when defined(Windows):
|
||||
var wsa: TWSADATA
|
||||
if WSAStartup(0x0101'i16, wsa) != 0: OSError()
|
||||
if WSAStartup(0x0101'i16, addr wsa) != 0: OSError(OSLastError())
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,312 +1,310 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module contains a few procedures to control the *terminal*
|
||||
## (also called *console*). On UNIX, the implementation simply uses ANSI escape
|
||||
## sequences and does not depend on any other module, on Windows it uses the
|
||||
## Windows API.
|
||||
## Changing the style is permanent even after program termination! Use the
|
||||
## code ``system.addQuitProc(resetAttributes)`` to restore the defaults.
|
||||
|
||||
import macros
|
||||
|
||||
when defined(windows):
|
||||
import windows, os
|
||||
|
||||
var
|
||||
conHandle: THandle
|
||||
# = createFile("CONOUT$", GENERIC_WRITE, 0, nil, OPEN_ALWAYS, 0, 0)
|
||||
|
||||
block:
|
||||
var hTemp = GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
if DuplicateHandle(GetCurrentProcess(), hTemp, GetCurrentProcess(),
|
||||
addr(conHandle), 0, 1, DUPLICATE_SAME_ACCESS) == 0:
|
||||
OSError()
|
||||
|
||||
proc getCursorPos(): tuple [x,y: int] =
|
||||
var c: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
if GetConsoleScreenBufferInfo(conHandle, addr(c)) == 0: OSError()
|
||||
return (int(c.dwCursorPosition.x), int(c.dwCursorPosition.y))
|
||||
|
||||
proc getAttributes(): int16 =
|
||||
var c: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
# workaround Windows bugs: try several times
|
||||
if GetConsoleScreenBufferInfo(conHandle, addr(c)) != 0:
|
||||
return c.wAttributes
|
||||
else:
|
||||
OSError()
|
||||
return 0x70'i16 # ERROR: return white background, black text
|
||||
|
||||
var
|
||||
oldAttr = getAttributes()
|
||||
|
||||
proc setCursorPos*(x, y: int) =
|
||||
## sets the terminal's cursor to the (x,y) position. (0,0) is the
|
||||
## upper left of the screen.
|
||||
when defined(windows):
|
||||
var c: TCoord
|
||||
c.x = int16(x)
|
||||
c.y = int16(y)
|
||||
if SetConsoleCursorPosition(conHandle, c) == 0: OSError()
|
||||
else:
|
||||
stdout.write("\e[" & $y & ';' & $x & 'f')
|
||||
|
||||
proc setCursorXPos*(x: int) =
|
||||
## sets the terminal's cursor to the x position. The y position is
|
||||
## not changed.
|
||||
when defined(windows):
|
||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
var hStdout = conHandle
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError()
|
||||
var origin = scrbuf.dwCursorPosition
|
||||
origin.x = int16(x)
|
||||
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError()
|
||||
else:
|
||||
stdout.write("\e[" & $x & 'G')
|
||||
|
||||
when defined(windows):
|
||||
proc setCursorYPos*(y: int) =
|
||||
## sets the terminal's cursor to the y position. The x position is
|
||||
## not changed. **Warning**: This is not supported on UNIX!
|
||||
when defined(windows):
|
||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
var hStdout = conHandle
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError()
|
||||
var origin = scrbuf.dwCursorPosition
|
||||
origin.y = int16(y)
|
||||
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError()
|
||||
else:
|
||||
nil
|
||||
|
||||
proc CursorUp*(count=1) =
|
||||
## Moves the cursor up by `count` rows.
|
||||
when defined(windows):
|
||||
var p = getCursorPos()
|
||||
dec(p.y, count)
|
||||
setCursorPos(p.x, p.y)
|
||||
else:
|
||||
stdout.write("\e[" & $count & 'A')
|
||||
|
||||
proc CursorDown*(count=1) =
|
||||
## Moves the cursor down by `count` rows.
|
||||
when defined(windows):
|
||||
var p = getCursorPos()
|
||||
inc(p.y, count)
|
||||
setCursorPos(p.x, p.y)
|
||||
else:
|
||||
stdout.write("\e[" & $count & 'B')
|
||||
|
||||
proc CursorForward*(count=1) =
|
||||
## Moves the cursor forward by `count` columns.
|
||||
when defined(windows):
|
||||
var p = getCursorPos()
|
||||
inc(p.x, count)
|
||||
setCursorPos(p.x, p.y)
|
||||
else:
|
||||
stdout.write("\e[" & $count & 'C')
|
||||
|
||||
proc CursorBackward*(count=1) =
|
||||
## Moves the cursor backward by `count` columns.
|
||||
when defined(windows):
|
||||
var p = getCursorPos()
|
||||
dec(p.x, count)
|
||||
setCursorPos(p.x, p.y)
|
||||
else:
|
||||
stdout.write("\e[" & $count & 'D')
|
||||
|
||||
when true:
|
||||
nil
|
||||
else:
|
||||
proc EraseLineEnd* =
|
||||
## Erases from the current cursor position to the end of the current line.
|
||||
when defined(windows):
|
||||
nil
|
||||
else:
|
||||
stdout.write("\e[K")
|
||||
|
||||
proc EraseLineStart* =
|
||||
## Erases from the current cursor position to the start of the current line.
|
||||
when defined(windows):
|
||||
nil
|
||||
else:
|
||||
stdout.write("\e[1K")
|
||||
|
||||
proc EraseDown* =
|
||||
## Erases the screen from the current line down to the bottom of the screen.
|
||||
when defined(windows):
|
||||
nil
|
||||
else:
|
||||
stdout.write("\e[J")
|
||||
|
||||
proc EraseUp* =
|
||||
## Erases the screen from the current line up to the top of the screen.
|
||||
when defined(windows):
|
||||
nil
|
||||
else:
|
||||
stdout.write("\e[1J")
|
||||
|
||||
proc EraseLine* =
|
||||
## Erases the entire current line.
|
||||
when defined(windows):
|
||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
var numwrote: DWORD
|
||||
var hStdout = conHandle
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError()
|
||||
var origin = scrbuf.dwCursorPosition
|
||||
origin.x = 0'i16
|
||||
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError()
|
||||
var ht = scrbuf.dwSize.Y - origin.Y
|
||||
var wt = scrbuf.dwSize.X - origin.X
|
||||
if FillConsoleOutputCharacter(hStdout,' ', ht*wt,
|
||||
origin, addr(numwrote)) == 0:
|
||||
OSError()
|
||||
if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, ht * wt,
|
||||
scrbuf.dwCursorPosition, addr(numwrote)) == 0:
|
||||
OSError()
|
||||
else:
|
||||
stdout.write("\e[2K")
|
||||
setCursorXPos(0)
|
||||
|
||||
proc EraseScreen* =
|
||||
## Erases the screen with the background colour and moves the cursor to home.
|
||||
when defined(windows):
|
||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
var numwrote: DWORD
|
||||
var origin: TCoord # is inititalized to 0, 0
|
||||
var hStdout = conHandle
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError()
|
||||
if FillConsoleOutputCharacter(hStdout, ' ', scrbuf.dwSize.X*scrbuf.dwSize.Y,
|
||||
origin, addr(numwrote)) == 0:
|
||||
OSError()
|
||||
if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes,
|
||||
scrbuf.dwSize.X * scrbuf.dwSize.Y,
|
||||
origin, addr(numwrote)) == 0:
|
||||
OSError()
|
||||
setCursorXPos(0)
|
||||
else:
|
||||
stdout.write("\e[2J")
|
||||
|
||||
proc ResetAttributes* {.noconv.} =
|
||||
## resets all attributes; it is advisable to register this as a quit proc
|
||||
## with ``system.addQuitProc(resetAttributes)``.
|
||||
when defined(windows):
|
||||
discard SetConsoleTextAttribute(conHandle, oldAttr)
|
||||
else:
|
||||
stdout.write("\e[0m")
|
||||
|
||||
type
|
||||
TStyle* = enum ## different styles for text output
|
||||
styleBright = 1, ## bright text
|
||||
styleDim, ## dim text
|
||||
styleUnknown, ## unknown
|
||||
styleUnderscore = 4, ## underscored text
|
||||
styleBlink, ## blinking/bold text
|
||||
styleReverse = 7, ## unknown
|
||||
styleHidden ## hidden text
|
||||
|
||||
when not defined(windows):
|
||||
var
|
||||
# XXX: These better be thread-local
|
||||
gFG = 0
|
||||
gBG = 0
|
||||
|
||||
proc setStyle*(style: set[TStyle]) =
|
||||
## sets the terminal style
|
||||
when defined(windows):
|
||||
var a = 0'i16
|
||||
if styleBright in style: a = a or int16(FOREGROUND_INTENSITY)
|
||||
if styleBlink in style: a = a or int16(BACKGROUND_INTENSITY)
|
||||
if styleReverse in style: a = a or 0x4000'i16 # COMMON_LVB_REVERSE_VIDEO
|
||||
if styleUnderscore in style: a = a or 0x8000'i16 # COMMON_LVB_UNDERSCORE
|
||||
discard SetConsoleTextAttribute(conHandle, a)
|
||||
else:
|
||||
for s in items(style):
|
||||
stdout.write("\e[" & $ord(s) & 'm')
|
||||
|
||||
proc WriteStyled*(txt: string, style: set[TStyle] = {styleBright}) =
|
||||
## writes the text `txt` in a given `style`.
|
||||
when defined(windows):
|
||||
var old = getAttributes()
|
||||
setStyle(style)
|
||||
stdout.write(txt)
|
||||
discard SetConsoleTextAttribute(conHandle, old)
|
||||
else:
|
||||
setStyle(style)
|
||||
stdout.write(txt)
|
||||
resetAttributes()
|
||||
if gFG != 0:
|
||||
stdout.write("\e[" & $ord(gFG) & 'm')
|
||||
if gBG != 0:
|
||||
stdout.write("\e[" & $ord(gBG) & 'm')
|
||||
|
||||
type
|
||||
TForegroundColor* = enum ## terminal's foreground colors
|
||||
fgBlack = 30, ## black
|
||||
fgRed, ## red
|
||||
fgGreen, ## green
|
||||
fgYellow, ## yellow
|
||||
fgBlue, ## blue
|
||||
fgMagenta, ## magenta
|
||||
fgCyan, ## cyan
|
||||
fgWhite ## white
|
||||
|
||||
TBackgroundColor* = enum ## terminal's background colors
|
||||
bgBlack = 40, ## black
|
||||
bgRed, ## red
|
||||
bgGreen, ## green
|
||||
bgYellow, ## yellow
|
||||
bgBlue, ## blue
|
||||
bgMagenta, ## magenta
|
||||
bgCyan, ## cyan
|
||||
bgWhite ## white
|
||||
|
||||
proc setForegroundColor*(fg: TForegroundColor, bright=false) =
|
||||
## sets the terminal's foreground color
|
||||
when defined(windows):
|
||||
var old = getAttributes() and not 0x0007
|
||||
if bright:
|
||||
old = old or FOREGROUND_INTENSITY
|
||||
const lookup: array [TForegroundColor, int] = [
|
||||
0,
|
||||
(FOREGROUND_RED),
|
||||
(FOREGROUND_GREEN),
|
||||
(FOREGROUND_RED or FOREGROUND_GREEN),
|
||||
(FOREGROUND_BLUE),
|
||||
(FOREGROUND_RED or FOREGROUND_BLUE),
|
||||
(FOREGROUND_BLUE or FOREGROUND_GREEN),
|
||||
(FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_RED)]
|
||||
discard SetConsoleTextAttribute(conHandle, toU16(old or lookup[fg]))
|
||||
else:
|
||||
gFG = ord(fg)
|
||||
if bright: inc(gFG, 60)
|
||||
stdout.write("\e[" & $gFG & 'm')
|
||||
|
||||
proc setBackgroundColor*(bg: TBackgroundColor, bright=false) =
|
||||
## sets the terminal's background color
|
||||
when defined(windows):
|
||||
var old = getAttributes() and not 0x0070
|
||||
if bright:
|
||||
old = old or BACKGROUND_INTENSITY
|
||||
const lookup: array [TBackgroundColor, int] = [
|
||||
0,
|
||||
(BACKGROUND_RED),
|
||||
(BACKGROUND_GREEN),
|
||||
(BACKGROUND_RED or BACKGROUND_GREEN),
|
||||
(BACKGROUND_BLUE),
|
||||
(BACKGROUND_RED or BACKGROUND_BLUE),
|
||||
(BACKGROUND_BLUE or BACKGROUND_GREEN),
|
||||
(BACKGROUND_BLUE or BACKGROUND_GREEN or BACKGROUND_RED)]
|
||||
discard SetConsoleTextAttribute(conHandle, toU16(old or lookup[bg]))
|
||||
else:
|
||||
gBG = ord(bg)
|
||||
if bright: inc(gBG, 60)
|
||||
stdout.write("\e[" & $gBG & 'm')
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module contains a few procedures to control the *terminal*
|
||||
## (also called *console*). On UNIX, the implementation simply uses ANSI escape
|
||||
## sequences and does not depend on any other module, on Windows it uses the
|
||||
## Windows API.
|
||||
## Changing the style is permanent even after program termination! Use the
|
||||
## code ``system.addQuitProc(resetAttributes)`` to restore the defaults.
|
||||
|
||||
import macros
|
||||
|
||||
when defined(windows):
|
||||
import windows, os
|
||||
|
||||
var
|
||||
conHandle: THandle
|
||||
# = createFile("CONOUT$", GENERIC_WRITE, 0, nil, OPEN_ALWAYS, 0, 0)
|
||||
|
||||
block:
|
||||
var hTemp = GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
if DuplicateHandle(GetCurrentProcess(), hTemp, GetCurrentProcess(),
|
||||
addr(conHandle), 0, 1, DUPLICATE_SAME_ACCESS) == 0:
|
||||
OSError(OSLastError())
|
||||
|
||||
proc getCursorPos(): tuple [x,y: int] =
|
||||
var c: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
if GetConsoleScreenBufferInfo(conHandle, addr(c)) == 0: OSError(OSLastError())
|
||||
return (int(c.dwCursorPosition.x), int(c.dwCursorPosition.y))
|
||||
|
||||
proc getAttributes(): int16 =
|
||||
var c: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
# workaround Windows bugs: try several times
|
||||
if GetConsoleScreenBufferInfo(conHandle, addr(c)) != 0:
|
||||
return c.wAttributes
|
||||
return 0x70'i16 # ERROR: return white background, black text
|
||||
|
||||
var
|
||||
oldAttr = getAttributes()
|
||||
|
||||
proc setCursorPos*(x, y: int) =
|
||||
## sets the terminal's cursor to the (x,y) position. (0,0) is the
|
||||
## upper left of the screen.
|
||||
when defined(windows):
|
||||
var c: TCoord
|
||||
c.x = int16(x)
|
||||
c.y = int16(y)
|
||||
if SetConsoleCursorPosition(conHandle, c) == 0: OSError(OSLastError())
|
||||
else:
|
||||
stdout.write("\e[" & $y & ';' & $x & 'f')
|
||||
|
||||
proc setCursorXPos*(x: int) =
|
||||
## sets the terminal's cursor to the x position. The y position is
|
||||
## not changed.
|
||||
when defined(windows):
|
||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
var hStdout = conHandle
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError(OSLastError())
|
||||
var origin = scrbuf.dwCursorPosition
|
||||
origin.x = int16(x)
|
||||
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError(OSLastError())
|
||||
else:
|
||||
stdout.write("\e[" & $x & 'G')
|
||||
|
||||
when defined(windows):
|
||||
proc setCursorYPos*(y: int) =
|
||||
## sets the terminal's cursor to the y position. The x position is
|
||||
## not changed. **Warning**: This is not supported on UNIX!
|
||||
when defined(windows):
|
||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
var hStdout = conHandle
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError(OSLastError())
|
||||
var origin = scrbuf.dwCursorPosition
|
||||
origin.y = int16(y)
|
||||
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError(OSLastError())
|
||||
else:
|
||||
nil
|
||||
|
||||
proc CursorUp*(count=1) =
|
||||
## Moves the cursor up by `count` rows.
|
||||
when defined(windows):
|
||||
var p = getCursorPos()
|
||||
dec(p.y, count)
|
||||
setCursorPos(p.x, p.y)
|
||||
else:
|
||||
stdout.write("\e[" & $count & 'A')
|
||||
|
||||
proc CursorDown*(count=1) =
|
||||
## Moves the cursor down by `count` rows.
|
||||
when defined(windows):
|
||||
var p = getCursorPos()
|
||||
inc(p.y, count)
|
||||
setCursorPos(p.x, p.y)
|
||||
else:
|
||||
stdout.write("\e[" & $count & 'B')
|
||||
|
||||
proc CursorForward*(count=1) =
|
||||
## Moves the cursor forward by `count` columns.
|
||||
when defined(windows):
|
||||
var p = getCursorPos()
|
||||
inc(p.x, count)
|
||||
setCursorPos(p.x, p.y)
|
||||
else:
|
||||
stdout.write("\e[" & $count & 'C')
|
||||
|
||||
proc CursorBackward*(count=1) =
|
||||
## Moves the cursor backward by `count` columns.
|
||||
when defined(windows):
|
||||
var p = getCursorPos()
|
||||
dec(p.x, count)
|
||||
setCursorPos(p.x, p.y)
|
||||
else:
|
||||
stdout.write("\e[" & $count & 'D')
|
||||
|
||||
when true:
|
||||
nil
|
||||
else:
|
||||
proc EraseLineEnd* =
|
||||
## Erases from the current cursor position to the end of the current line.
|
||||
when defined(windows):
|
||||
nil
|
||||
else:
|
||||
stdout.write("\e[K")
|
||||
|
||||
proc EraseLineStart* =
|
||||
## Erases from the current cursor position to the start of the current line.
|
||||
when defined(windows):
|
||||
nil
|
||||
else:
|
||||
stdout.write("\e[1K")
|
||||
|
||||
proc EraseDown* =
|
||||
## Erases the screen from the current line down to the bottom of the screen.
|
||||
when defined(windows):
|
||||
nil
|
||||
else:
|
||||
stdout.write("\e[J")
|
||||
|
||||
proc EraseUp* =
|
||||
## Erases the screen from the current line up to the top of the screen.
|
||||
when defined(windows):
|
||||
nil
|
||||
else:
|
||||
stdout.write("\e[1J")
|
||||
|
||||
proc EraseLine* =
|
||||
## Erases the entire current line.
|
||||
when defined(windows):
|
||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
var numwrote: DWORD
|
||||
var hStdout = conHandle
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError(OSLastError())
|
||||
var origin = scrbuf.dwCursorPosition
|
||||
origin.x = 0'i16
|
||||
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError(OSLastError())
|
||||
var ht = scrbuf.dwSize.Y - origin.Y
|
||||
var wt = scrbuf.dwSize.X - origin.X
|
||||
if FillConsoleOutputCharacter(hStdout,' ', ht*wt,
|
||||
origin, addr(numwrote)) == 0:
|
||||
OSError(OSLastError())
|
||||
if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, ht * wt,
|
||||
scrbuf.dwCursorPosition, addr(numwrote)) == 0:
|
||||
OSError(OSLastError())
|
||||
else:
|
||||
stdout.write("\e[2K")
|
||||
setCursorXPos(0)
|
||||
|
||||
proc EraseScreen* =
|
||||
## Erases the screen with the background colour and moves the cursor to home.
|
||||
when defined(windows):
|
||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
var numwrote: DWORD
|
||||
var origin: TCoord # is inititalized to 0, 0
|
||||
var hStdout = conHandle
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError(OSLastError())
|
||||
if FillConsoleOutputCharacter(hStdout, ' ', scrbuf.dwSize.X*scrbuf.dwSize.Y,
|
||||
origin, addr(numwrote)) == 0:
|
||||
OSError(OSLastError())
|
||||
if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes,
|
||||
scrbuf.dwSize.X * scrbuf.dwSize.Y,
|
||||
origin, addr(numwrote)) == 0:
|
||||
OSError(OSLastError())
|
||||
setCursorXPos(0)
|
||||
else:
|
||||
stdout.write("\e[2J")
|
||||
|
||||
proc ResetAttributes* {.noconv.} =
|
||||
## resets all attributes; it is advisable to register this as a quit proc
|
||||
## with ``system.addQuitProc(resetAttributes)``.
|
||||
when defined(windows):
|
||||
discard SetConsoleTextAttribute(conHandle, oldAttr)
|
||||
else:
|
||||
stdout.write("\e[0m")
|
||||
|
||||
type
|
||||
TStyle* = enum ## different styles for text output
|
||||
styleBright = 1, ## bright text
|
||||
styleDim, ## dim text
|
||||
styleUnknown, ## unknown
|
||||
styleUnderscore = 4, ## underscored text
|
||||
styleBlink, ## blinking/bold text
|
||||
styleReverse = 7, ## unknown
|
||||
styleHidden ## hidden text
|
||||
|
||||
when not defined(windows):
|
||||
var
|
||||
# XXX: These better be thread-local
|
||||
gFG = 0
|
||||
gBG = 0
|
||||
|
||||
proc setStyle*(style: set[TStyle]) =
|
||||
## sets the terminal style
|
||||
when defined(windows):
|
||||
var a = 0'i16
|
||||
if styleBright in style: a = a or int16(FOREGROUND_INTENSITY)
|
||||
if styleBlink in style: a = a or int16(BACKGROUND_INTENSITY)
|
||||
if styleReverse in style: a = a or 0x4000'i16 # COMMON_LVB_REVERSE_VIDEO
|
||||
if styleUnderscore in style: a = a or 0x8000'i16 # COMMON_LVB_UNDERSCORE
|
||||
discard SetConsoleTextAttribute(conHandle, a)
|
||||
else:
|
||||
for s in items(style):
|
||||
stdout.write("\e[" & $ord(s) & 'm')
|
||||
|
||||
proc WriteStyled*(txt: string, style: set[TStyle] = {styleBright}) =
|
||||
## writes the text `txt` in a given `style`.
|
||||
when defined(windows):
|
||||
var old = getAttributes()
|
||||
setStyle(style)
|
||||
stdout.write(txt)
|
||||
discard SetConsoleTextAttribute(conHandle, old)
|
||||
else:
|
||||
setStyle(style)
|
||||
stdout.write(txt)
|
||||
resetAttributes()
|
||||
if gFG != 0:
|
||||
stdout.write("\e[" & $ord(gFG) & 'm')
|
||||
if gBG != 0:
|
||||
stdout.write("\e[" & $ord(gBG) & 'm')
|
||||
|
||||
type
|
||||
TForegroundColor* = enum ## terminal's foreground colors
|
||||
fgBlack = 30, ## black
|
||||
fgRed, ## red
|
||||
fgGreen, ## green
|
||||
fgYellow, ## yellow
|
||||
fgBlue, ## blue
|
||||
fgMagenta, ## magenta
|
||||
fgCyan, ## cyan
|
||||
fgWhite ## white
|
||||
|
||||
TBackgroundColor* = enum ## terminal's background colors
|
||||
bgBlack = 40, ## black
|
||||
bgRed, ## red
|
||||
bgGreen, ## green
|
||||
bgYellow, ## yellow
|
||||
bgBlue, ## blue
|
||||
bgMagenta, ## magenta
|
||||
bgCyan, ## cyan
|
||||
bgWhite ## white
|
||||
|
||||
proc setForegroundColor*(fg: TForegroundColor, bright=false) =
|
||||
## sets the terminal's foreground color
|
||||
when defined(windows):
|
||||
var old = getAttributes() and not 0x0007
|
||||
if bright:
|
||||
old = old or FOREGROUND_INTENSITY
|
||||
const lookup: array [TForegroundColor, int] = [
|
||||
0,
|
||||
(FOREGROUND_RED),
|
||||
(FOREGROUND_GREEN),
|
||||
(FOREGROUND_RED or FOREGROUND_GREEN),
|
||||
(FOREGROUND_BLUE),
|
||||
(FOREGROUND_RED or FOREGROUND_BLUE),
|
||||
(FOREGROUND_BLUE or FOREGROUND_GREEN),
|
||||
(FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_RED)]
|
||||
discard SetConsoleTextAttribute(conHandle, toU16(old or lookup[fg]))
|
||||
else:
|
||||
gFG = ord(fg)
|
||||
if bright: inc(gFG, 60)
|
||||
stdout.write("\e[" & $gFG & 'm')
|
||||
|
||||
proc setBackgroundColor*(bg: TBackgroundColor, bright=false) =
|
||||
## sets the terminal's background color
|
||||
when defined(windows):
|
||||
var old = getAttributes() and not 0x0070
|
||||
if bright:
|
||||
old = old or BACKGROUND_INTENSITY
|
||||
const lookup: array [TBackgroundColor, int] = [
|
||||
0,
|
||||
(BACKGROUND_RED),
|
||||
(BACKGROUND_GREEN),
|
||||
(BACKGROUND_RED or BACKGROUND_GREEN),
|
||||
(BACKGROUND_BLUE),
|
||||
(BACKGROUND_RED or BACKGROUND_BLUE),
|
||||
(BACKGROUND_BLUE or BACKGROUND_GREEN),
|
||||
(BACKGROUND_BLUE or BACKGROUND_GREEN or BACKGROUND_RED)]
|
||||
discard SetConsoleTextAttribute(conHandle, toU16(old or lookup[bg]))
|
||||
else:
|
||||
gBG = ord(bg)
|
||||
if bright: inc(gBG, 60)
|
||||
stdout.write("\e[" & $gBG & 'm')
|
||||
|
||||
proc isatty*(f: TFile): bool =
|
||||
## returns true if `f` is associated with a terminal device.
|
||||
|
|
@ -318,33 +316,33 @@ proc isatty*(f: TFile): bool =
|
|||
importc: "_isatty", header: "<io.h>".}
|
||||
|
||||
result = isatty(fileHandle(f)) != 0'i32
|
||||
|
||||
proc styledEchoProcessArg(s: string) = write stdout, s
|
||||
proc styledEchoProcessArg(style: TStyle) = setStyle({style})
|
||||
proc styledEchoProcessArg(style: set[TStyle]) = setStyle style
|
||||
proc styledEchoProcessArg(color: TForegroundColor) = setForeGroundColor color
|
||||
proc styledEchoProcessArg(color: TBackgroundColor) = setBackGroundColor color
|
||||
|
||||
|
||||
proc styledEchoProcessArg(s: string) = write stdout, s
|
||||
proc styledEchoProcessArg(style: TStyle) = setStyle({style})
|
||||
proc styledEchoProcessArg(style: set[TStyle]) = setStyle style
|
||||
proc styledEchoProcessArg(color: TForegroundColor) = setForeGroundColor color
|
||||
proc styledEchoProcessArg(color: TBackgroundColor) = setBackGroundColor color
|
||||
|
||||
macro styledEcho*(m: varargs[expr]): stmt =
|
||||
## to be documented.
|
||||
let m = callsite()
|
||||
result = newNimNode(nnkStmtList)
|
||||
|
||||
for i in countup(1, m.len - 1):
|
||||
result.add(newCall(bindSym"styledEchoProcessArg", m[i]))
|
||||
|
||||
result.add(newCall(bindSym"write", bindSym"stdout", newStrLitNode("\n")))
|
||||
result.add(newCall(bindSym"resetAttributes"))
|
||||
|
||||
when isMainModule:
|
||||
system.addQuitProc(resetAttributes)
|
||||
write(stdout, "never mind")
|
||||
eraseLine()
|
||||
#setCursorPos(2, 2)
|
||||
writeStyled("styled text ", {styleBright, styleBlink, styleUnderscore})
|
||||
setBackGroundColor(bgCyan, true)
|
||||
setForeGroundColor(fgBlue)
|
||||
writeln(stdout, "ordinary text")
|
||||
|
||||
result = newNimNode(nnkStmtList)
|
||||
|
||||
for i in countup(1, m.len - 1):
|
||||
result.add(newCall(bindSym"styledEchoProcessArg", m[i]))
|
||||
|
||||
result.add(newCall(bindSym"write", bindSym"stdout", newStrLitNode("\n")))
|
||||
result.add(newCall(bindSym"resetAttributes"))
|
||||
|
||||
when isMainModule:
|
||||
system.addQuitProc(resetAttributes)
|
||||
write(stdout, "never mind")
|
||||
eraseLine()
|
||||
#setCursorPos(2, 2)
|
||||
writeStyled("styled text ", {styleBright, styleBlink, styleUnderscore})
|
||||
setBackGroundColor(bgCyan, true)
|
||||
setForeGroundColor(fgBlue)
|
||||
writeln(stdout, "ordinary text")
|
||||
|
||||
styledEcho("styled text ", {styleBright, styleBlink, styleUnderscore})
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -338,24 +338,24 @@ when not defined(JS):
|
|||
const
|
||||
weekDays: array [0..6, TWeekDay] = [
|
||||
dSun, dMon, dTue, dWed, dThu, dFri, dSat]
|
||||
result.second = int(tm.second)
|
||||
result.minute = int(tm.minute)
|
||||
result.hour = int(tm.hour)
|
||||
result.monthday = int(tm.monthday)
|
||||
result.month = TMonth(tm.month)
|
||||
result.year = tm.year + 1900'i32
|
||||
result.weekday = weekDays[int(tm.weekDay)]
|
||||
result.yearday = int(tm.yearday)
|
||||
result.isDST = tm.isDST > 0
|
||||
if local:
|
||||
if result.isDST:
|
||||
result.tzname = getTzname().DST
|
||||
else:
|
||||
result.tzname = getTzname().nonDST
|
||||
else:
|
||||
result.tzname = "UTC"
|
||||
|
||||
result.timezone = if local: getTimezone() else: 0
|
||||
TTimeInfo(second: int(tm.second),
|
||||
minute: int(tm.minute),
|
||||
hour: int(tm.hour),
|
||||
monthday: int(tm.monthday),
|
||||
month: TMonth(tm.month),
|
||||
year: tm.year + 1900'i32,
|
||||
weekday: weekDays[int(tm.weekDay)],
|
||||
yearday: int(tm.yearday),
|
||||
isDST: tm.isDST > 0,
|
||||
tzname: if local:
|
||||
if tm.isDST > 0:
|
||||
getTzname().DST
|
||||
else:
|
||||
getTzname().nonDST
|
||||
else:
|
||||
"UTC",
|
||||
timezone: if local: getTimezone() else: 0
|
||||
)
|
||||
|
||||
proc timeInfoToTM(t: TTimeInfo): structTM =
|
||||
const
|
||||
|
|
|
|||
|
|
@ -110,11 +110,9 @@ proc parseXml*(s: PStream, filename: string,
|
|||
of xmlElementOpen, xmlElementStart:
|
||||
result = parse(x, errors)
|
||||
break
|
||||
of xmlComment, xmlWhitespace: nil # just skip it
|
||||
of xmlComment, xmlWhitespace, xmlSpecial: nil # just skip it
|
||||
of xmlError:
|
||||
errors.add(errorMsg(x))
|
||||
of xmlSpecial:
|
||||
errors.add(errorMsg(x, "<some_tag> expected"))
|
||||
else:
|
||||
errors.add(errorMsg(x, "<some_tag> expected"))
|
||||
break
|
||||
|
|
|
|||
|
|
@ -71,6 +71,16 @@ proc text*(n: PXmlNode): string {.inline.} =
|
|||
assert n.k in {xnText, xnComment, xnCData, xnEntity}
|
||||
result = n.fText
|
||||
|
||||
proc rawText*(n: PXmlNode): string {.inline.} =
|
||||
## returns the underlying 'text' string by reference.
|
||||
## This is only used for speed hacks.
|
||||
shallowCopy(result, n.fText)
|
||||
|
||||
proc rawTag*(n: PXmlNode): string {.inline.} =
|
||||
## returns the underlying 'tag' string by reference.
|
||||
## This is only used for speed hacks.
|
||||
shallowCopy(result, n.fTag)
|
||||
|
||||
proc innerText*(n: PXmlNode): string =
|
||||
## gets the inner text of `n`. `n` has to be an ``xnElement`` node. Only
|
||||
## ``xnText`` and ``xnEntity`` nodes are considered part of `n`'s inner text,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ when defined(Windows):
|
|||
OwningThread: int
|
||||
LockSemaphore: int
|
||||
Reserved: int32
|
||||
|
||||
|
||||
TSysCond = THandle
|
||||
|
||||
proc InitSysLock(L: var TSysLock) {.stdcall, noSideEffect,
|
||||
|
|
|
|||
|
|
@ -489,7 +489,7 @@ proc FD_SET*(Socket: TWinSocket, FDSet: var TFDSet) =
|
|||
proc FD_ZERO*(FDSet: var TFDSet) =
|
||||
FDSet.fd_count = 0
|
||||
|
||||
proc WSAStartup*(wVersionRequired: int16, WSData: var TWSAData): cint {.
|
||||
proc WSAStartup*(wVersionRequired: int16, WSData: ptr TWSAData): cint {.
|
||||
stdcall, importc: "WSAStartup", dynlib: ws2dll.}
|
||||
|
||||
proc getaddrinfo*(nodename, servname: cstring, hints: ptr TAddrInfo,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ type
|
|||
gshort* = cshort
|
||||
glong* = clong
|
||||
gint* = cint
|
||||
gboolean* = bool
|
||||
gboolean* = distinct gint
|
||||
guchar* = char
|
||||
gushort* = int16
|
||||
gulong* = int
|
||||
|
|
@ -173,6 +173,12 @@ type
|
|||
TGBoxedFreeFunc* = proc (boxed: gpointer){.cdecl.}
|
||||
PGsource = pointer # I don't know and don't care
|
||||
|
||||
converter gbool*(nimbool: bool): gboolean =
|
||||
return ord(nimbool).gboolean
|
||||
|
||||
converter toBool*(gbool: gboolean): bool =
|
||||
return int(gbool) == 1
|
||||
|
||||
const
|
||||
G_TYPE_FUNDAMENTAL_SHIFT* = 2
|
||||
G_TYPE_FUNDAMENTAL_MAX* = 255 shl G_TYPE_FUNDAMENTAL_SHIFT
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
import
|
||||
glib2, atk, pango, gdk2pixbuf, gdk2
|
||||
|
||||
export gbool, toBool
|
||||
|
||||
when defined(win32):
|
||||
const
|
||||
lib = "libgtk-win32-2.0-0.dll"
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ import
|
|||
|
||||
proc pushstring*(L: PState, s: string)
|
||||
# compatibilty macros
|
||||
proc getn*(L: PState, n: int): int
|
||||
proc getn*(L: PState, n: cint): cint
|
||||
# calls lua_objlen
|
||||
proc setn*(L: PState, t, n: int)
|
||||
proc setn*(L: PState, t, n: cint)
|
||||
# does nothing!
|
||||
type
|
||||
Treg*{.final.} = object
|
||||
|
|
@ -37,58 +37,45 @@ type
|
|||
|
||||
Preg* = ptr Treg
|
||||
|
||||
proc openlib*(L: PState, libname: cstring, lr: Preg, nup: int){.cdecl,
|
||||
dynlib: lua.LIB_NAME, importc: "luaL_openlib".}
|
||||
proc register*(L: PState, libname: cstring, lr: Preg){.cdecl,
|
||||
dynlib: lua.LIB_NAME, importc: "luaL_register".}
|
||||
proc getmetafield*(L: PState, obj: int, e: cstring): int{.cdecl,
|
||||
dynlib: lua.LIB_NAME, importc: "luaL_getmetafield".}
|
||||
proc callmeta*(L: PState, obj: int, e: cstring): int{.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_callmeta".}
|
||||
proc typerror*(L: PState, narg: int, tname: cstring): int{.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_typerror".}
|
||||
proc argerror*(L: PState, numarg: int, extramsg: cstring): int{.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_argerror".}
|
||||
proc checklstring*(L: PState, numArg: int, len: ptr int): cstring{.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_checklstring".}
|
||||
proc optlstring*(L: PState, numArg: int, def: cstring, len: ptr int): cstring{.
|
||||
cdecl, dynlib: LIB_NAME, importc: "luaL_optlstring".}
|
||||
proc checknumber*(L: PState, numArg: int): Number{.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_checknumber".}
|
||||
proc optnumber*(L: PState, nArg: int, def: Number): Number{.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_optnumber".}
|
||||
proc checkinteger*(L: PState, numArg: int): Integer{.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_checkinteger".}
|
||||
proc optinteger*(L: PState, nArg: int, def: Integer): Integer{.
|
||||
cdecl, dynlib: LIB_NAME, importc: "luaL_optinteger".}
|
||||
proc checkstack*(L: PState, sz: int, msg: cstring){.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_checkstack".}
|
||||
proc checktype*(L: PState, narg, t: int){.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaL_checktype".}
|
||||
proc checkany*(L: PState, narg: int){.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaL_checkany".}
|
||||
proc newmetatable*(L: PState, tname: cstring): int{.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_newmetatable".}
|
||||
proc checkudata*(L: PState, ud: int, tname: cstring): Pointer{.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_checkudata".}
|
||||
proc where*(L: PState, lvl: int){.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaL_where".}
|
||||
proc error*(L: PState, fmt: cstring): int{.cdecl, varargs,
|
||||
dynlib: LIB_NAME, importc: "luaL_error".}
|
||||
proc checkoption*(L: PState, narg: int, def: cstring, lst: cstringArray): int{.
|
||||
cdecl, dynlib: LIB_NAME, importc: "luaL_checkoption".}
|
||||
proc reference*(L: PState, t: int): int{.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaL_ref".}
|
||||
proc unref*(L: PState, t, theref: int){.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaL_unref".}
|
||||
proc loadfile*(L: PState, filename: cstring): int{.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_loadfile".}
|
||||
proc loadbuffer*(L: PState, buff: cstring, size: int, name: cstring): int{.
|
||||
cdecl, dynlib: LIB_NAME, importc: "luaL_loadbuffer".}
|
||||
proc loadstring*(L: PState, s: cstring): int{.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaL_loadstring".}
|
||||
proc newstate*(): PState{.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaL_newstate".}
|
||||
|
||||
{.push callConv: cdecl, dynlib: lua.LIB_NAME.}
|
||||
{.push importc: "luaL_$1".}
|
||||
|
||||
proc openlib*(L: PState, libname: cstring, lr: Preg, nup: cint)
|
||||
proc register*(L: PState, libname: cstring, lr: Preg)
|
||||
|
||||
proc getmetafield*(L: PState, obj: cint, e: cstring): cint
|
||||
proc callmeta*(L: PState, obj: cint, e: cstring): cint
|
||||
proc typerror*(L: PState, narg: cint, tname: cstring): cint
|
||||
proc argerror*(L: PState, numarg: cint, extramsg: cstring): cint
|
||||
proc checklstring*(L: PState, numArg: cint, len: ptr int): cstring
|
||||
proc optlstring*(L: PState, numArg: cint, def: cstring, len: ptr cint): cstring
|
||||
proc checknumber*(L: PState, numArg: cint): Number
|
||||
proc optnumber*(L: PState, nArg: cint, def: Number): Number
|
||||
proc checkinteger*(L: PState, numArg: cint): Integer
|
||||
proc optinteger*(L: PState, nArg: cint, def: Integer): Integer
|
||||
proc checkstack*(L: PState, sz: cint, msg: cstring)
|
||||
proc checktype*(L: PState, narg, t: cint)
|
||||
|
||||
proc checkany*(L: PState, narg: cint)
|
||||
proc newmetatable*(L: PState, tname: cstring): cint
|
||||
|
||||
proc checkudata*(L: PState, ud: cint, tname: cstring): Pointer
|
||||
proc where*(L: PState, lvl: cint)
|
||||
proc error*(L: PState, fmt: cstring): cint{.varargs.}
|
||||
proc checkoption*(L: PState, narg: cint, def: cstring, lst: cstringArray): cint
|
||||
|
||||
proc unref*(L: PState, t, theref: cint)
|
||||
proc loadfile*(L: PState, filename: cstring): cint
|
||||
proc loadbuffer*(L: PState, buff: cstring, size: cint, name: cstring): cint
|
||||
proc loadstring*(L: PState, s: cstring): cint
|
||||
proc newstate*(): PState
|
||||
|
||||
{.pop.}
|
||||
proc reference*(L: PState, t: cint): cint{.importc: "luaL_ref".}
|
||||
|
||||
{.pop.}
|
||||
|
||||
proc open*(): PState
|
||||
# compatibility; moved from unit lua to lauxlib because it needs luaL_newstate
|
||||
#
|
||||
|
|
@ -96,18 +83,18 @@ proc open*(): PState
|
|||
#** some useful macros
|
||||
#** ===============================================================
|
||||
#
|
||||
proc argcheck*(L: PState, cond: bool, numarg: int, extramsg: cstring)
|
||||
proc checkstring*(L: PState, n: int): cstring
|
||||
proc optstring*(L: PState, n: int, d: cstring): cstring
|
||||
proc checkint*(L: PState, n: int): int
|
||||
proc checklong*(L: PState, n: int): int32
|
||||
proc optint*(L: PState, n: int, d: float64): int
|
||||
proc optlong*(L: PState, n: int, d: float64): int32
|
||||
proc dofile*(L: PState, filename: cstring): int
|
||||
proc dostring*(L: PState, str: cstring): int
|
||||
proc argcheck*(L: PState, cond: bool, numarg: cint, extramsg: cstring)
|
||||
proc checkstring*(L: PState, n: cint): cstring
|
||||
proc optstring*(L: PState, n: cint, d: cstring): cstring
|
||||
proc checkint*(L: PState, n: cint): cint
|
||||
proc checklong*(L: PState, n: cint): clong
|
||||
proc optint*(L: PState, n: cint, d: float64): cint
|
||||
proc optlong*(L: PState, n: cint, d: float64): clong
|
||||
proc dofile*(L: PState, filename: cstring): cint
|
||||
proc dostring*(L: PState, str: cstring): cint
|
||||
proc getmetatable*(L: PState, tname: cstring)
|
||||
# not translated:
|
||||
# #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
|
||||
# #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
|
||||
#
|
||||
#** =======================================================
|
||||
#** Generic Buffer manipulation
|
||||
|
|
@ -119,7 +106,7 @@ const # note: this is just arbitrary, as it related to t
|
|||
type
|
||||
Buffer*{.final.} = object
|
||||
p*: cstring # current position in buffer
|
||||
lvl*: int # number of strings in the stack (level)
|
||||
lvl*: cint # number of strings in the stack (level)
|
||||
L*: PState
|
||||
buffer*: array[0..BUFFERSIZE - 1, Char] # warning: see note above about LUAL_BUFFERSIZE
|
||||
|
||||
|
|
@ -130,80 +117,76 @@ proc addchar*(B: PBuffer, c: Char)
|
|||
# compatibility only (alias for luaL_addchar)
|
||||
proc putchar*(B: PBuffer, c: Char)
|
||||
# warning: see note above about LUAL_BUFFERSIZE
|
||||
proc addsize*(B: PBuffer, n: int)
|
||||
proc buffinit*(L: PState, B: PBuffer){.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaL_buffinit".}
|
||||
proc prepbuffer*(B: PBuffer): cstring{.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaL_prepbuffer".}
|
||||
proc addlstring*(B: PBuffer, s: cstring, L: int){.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_addlstring".}
|
||||
proc addstring*(B: PBuffer, s: cstring){.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaL_addstring".}
|
||||
proc addvalue*(B: PBuffer){.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaL_addvalue".}
|
||||
proc pushresult*(B: PBuffer){.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaL_pushresult".}
|
||||
proc gsub*(L: PState, s, p, r: cstring): cstring{.cdecl,
|
||||
dynlib: LIB_NAME, importc: "luaL_gsub".}
|
||||
proc findtable*(L: PState, idx: int, fname: cstring, szhint: int): cstring{.
|
||||
cdecl, dynlib: LIB_NAME, importc: "luaL_findtable".}
|
||||
proc addsize*(B: PBuffer, n: cint)
|
||||
|
||||
{.push callConv: cdecl, dynlib: lua.LIB_NAME, importc: "luaL_$1".}
|
||||
proc buffinit*(L: PState, B: PBuffer)
|
||||
proc prepbuffer*(B: PBuffer): cstring
|
||||
proc addlstring*(B: PBuffer, s: cstring, L: cint)
|
||||
proc addstring*(B: PBuffer, s: cstring)
|
||||
proc addvalue*(B: PBuffer)
|
||||
proc pushresult*(B: PBuffer)
|
||||
proc gsub*(L: PState, s, p, r: cstring): cstring
|
||||
proc findtable*(L: PState, idx: cint, fname: cstring, szhint: cint): cstring
|
||||
# compatibility with ref system
|
||||
# pre-defined references
|
||||
{.pop.}
|
||||
|
||||
const
|
||||
NOREF* = - 2
|
||||
REFNIL* = - 1
|
||||
|
||||
proc unref*(L: PState, theref: int)
|
||||
proc getref*(L: PState, theref: int)
|
||||
proc unref*(L: PState, theref: cint)
|
||||
proc getref*(L: PState, theref: cint)
|
||||
#
|
||||
#** Compatibility macros and functions
|
||||
#
|
||||
# implementation
|
||||
|
||||
proc pushstring(L: PState, s: string) =
|
||||
pushlstring(L, cstring(s), len(s))
|
||||
pushlstring(L, cstring(s), s.len.cint)
|
||||
|
||||
proc getn(L: PState, n: int): int =
|
||||
proc getn(L: PState, n: cint): cint =
|
||||
Result = objlen(L, n)
|
||||
|
||||
proc setn(L: PState, t, n: int) =
|
||||
proc setn(L: PState, t, n: cint) =
|
||||
# does nothing as this operation is deprecated
|
||||
nil
|
||||
|
||||
proc open(): PState =
|
||||
Result = newstate()
|
||||
|
||||
proc dofile(L: PState, filename: cstring): int =
|
||||
proc dofile(L: PState, filename: cstring): cint =
|
||||
Result = loadfile(L, filename)
|
||||
if Result == 0: Result = pcall(L, 0, MULTRET, 0)
|
||||
|
||||
proc dostring(L: PState, str: cstring): int =
|
||||
proc dostring(L: PState, str: cstring): cint =
|
||||
Result = loadstring(L, str)
|
||||
if Result == 0: Result = pcall(L, 0, MULTRET, 0)
|
||||
|
||||
proc getmetatable(L: PState, tname: cstring) =
|
||||
getfield(L, REGISTRYINDEX, tname)
|
||||
|
||||
proc argcheck(L: PState, cond: bool, numarg: int, extramsg: cstring) =
|
||||
proc argcheck(L: PState, cond: bool, numarg: cint, extramsg: cstring) =
|
||||
if not cond:
|
||||
discard argerror(L, numarg, extramsg)
|
||||
|
||||
proc checkstring(L: PState, n: int): cstring =
|
||||
proc checkstring(L: PState, n: cint): cstring =
|
||||
Result = checklstring(L, n, nil)
|
||||
|
||||
proc optstring(L: PState, n: int, d: cstring): cstring =
|
||||
proc optstring(L: PState, n: cint, d: cstring): cstring =
|
||||
Result = optlstring(L, n, d, nil)
|
||||
|
||||
proc checkint(L: PState, n: int): int =
|
||||
Result = toInt(checknumber(L, n))
|
||||
proc checkint(L: PState, n: cint): cint =
|
||||
Result = cint(checknumber(L, n))
|
||||
|
||||
proc checklong(L: PState, n: int): int32 =
|
||||
proc checklong(L: PState, n: cint): clong =
|
||||
Result = int32(ToInt(checknumber(L, n)))
|
||||
|
||||
proc optint(L: PState, n: int, d: float64): int =
|
||||
Result = int(ToInt(optnumber(L, n, d)))
|
||||
proc optint(L: PState, n: cint, d: float64): cint =
|
||||
Result = optnumber(L, n, d).cint
|
||||
|
||||
proc optlong(L: PState, n: int, d: float64): int32 =
|
||||
proc optlong(L: PState, n: cint, d: float64): clong =
|
||||
Result = int32(ToInt(optnumber(L, n, d)))
|
||||
|
||||
proc addchar(B: PBuffer, c: Char) =
|
||||
|
|
@ -215,11 +198,11 @@ proc addchar(B: PBuffer, c: Char) =
|
|||
proc putchar(B: PBuffer, c: Char) =
|
||||
addchar(B, c)
|
||||
|
||||
proc addsize(B: PBuffer, n: int) =
|
||||
proc addsize(B: PBuffer, n: cint) =
|
||||
B.p = cast[cstring](cast[int](B.p) + n)
|
||||
|
||||
proc unref(L: PState, theref: int) =
|
||||
proc unref(L: PState, theref: cint) =
|
||||
unref(L, REGISTRYINDEX, theref)
|
||||
|
||||
proc getref(L: PState, theref: int) =
|
||||
proc getref(L: PState, theref: cint) =
|
||||
rawgeti(L, REGISTRYINDEX, theref)
|
||||
|
|
|
|||
|
|
@ -51,16 +51,16 @@ when defined(useLuajit):
|
|||
else:
|
||||
when defined(MACOSX):
|
||||
const
|
||||
NAME* = "liblua(|5.2|5.1|5.0).dylib"
|
||||
LIB_NAME* = "liblua(|5.2|5.1|5.0).dylib"
|
||||
NAME* = "liblua(|5.1|5.0).dylib"
|
||||
LIB_NAME* = "liblua(|5.1|5.0).dylib"
|
||||
elif defined(UNIX):
|
||||
const
|
||||
NAME* = "liblua(|5.2|5.1|5.0).so(|.0)"
|
||||
LIB_NAME* = "liblua(|5.2|5.1|5.0).so(|.0)"
|
||||
NAME* = "liblua(|5.1|5.0).so(|.0)"
|
||||
LIB_NAME* = "liblua(|5.1|5.0).so(|.0)"
|
||||
else:
|
||||
const
|
||||
NAME* = "lua(|5.2|5.1|5.0).dll"
|
||||
LIB_NAME* = "lua(|5.2|5.1|5.0).dll"
|
||||
NAME* = "lua(|5.1|5.0).dll"
|
||||
LIB_NAME* = "lua(|5.1|5.0).dll"
|
||||
|
||||
const
|
||||
VERSION* = "Lua 5.1"
|
||||
|
|
@ -76,7 +76,7 @@ const
|
|||
ENVIRONINDEX* = - 10001
|
||||
GLOBALSINDEX* = - 10002
|
||||
|
||||
proc upvalueindex*(I: int): int
|
||||
proc upvalueindex*(I: cint): cint
|
||||
const # thread status; 0 is OK
|
||||
constYIELD* = 1
|
||||
ERRRUN* = 2
|
||||
|
|
@ -86,16 +86,16 @@ const # thread status; 0 is OK
|
|||
|
||||
type
|
||||
PState* = Pointer
|
||||
CFunction* = proc (L: PState): int{.cdecl.}
|
||||
CFunction* = proc (L: PState): cint{.cdecl.}
|
||||
|
||||
#
|
||||
#** functions that read/write blocks when loading/dumping Lua chunks
|
||||
#
|
||||
|
||||
type
|
||||
Reader* = proc (L: PState, ud: Pointer, sz: ptr int): cstring{.cdecl.}
|
||||
Writer* = proc (L: PState, p: Pointer, sz: int, ud: Pointer): int{.cdecl.}
|
||||
Alloc* = proc (ud, theptr: Pointer, osize, nsize: int){.cdecl.}
|
||||
Reader* = proc (L: PState, ud: Pointer, sz: ptr cint): cstring{.cdecl.}
|
||||
Writer* = proc (L: PState, p: Pointer, sz: cint, ud: Pointer): cint{.cdecl.}
|
||||
Alloc* = proc (ud, theptr: Pointer, osize, nsize: cint){.cdecl.}
|
||||
|
||||
const
|
||||
TNONE* = - 1
|
||||
|
|
@ -112,130 +112,86 @@ const
|
|||
|
||||
type # Type of Numbers in Lua
|
||||
Number* = float
|
||||
Integer* = int
|
||||
Integer* = cint
|
||||
|
||||
{.pragma: ilua, importc: "lua_$1".}
|
||||
|
||||
{.push callConv: cdecl, dynlib: LibName.}
|
||||
#{.push importc: "lua_$1".}
|
||||
|
||||
proc newstate*(f: Alloc, ud: Pointer): PState {.ilua.}
|
||||
|
||||
proc close*(L: PState){.ilua.}
|
||||
proc newthread*(L: PState): PState{.ilua.}
|
||||
proc atpanic*(L: PState, panicf: CFunction): CFunction{.ilua.}
|
||||
|
||||
proc gettop*(L: PState): cint{.ilua.}
|
||||
proc settop*(L: PState, idx: cint){.ilua.}
|
||||
proc pushvalue*(L: PState, Idx: cint){.ilua.}
|
||||
proc remove*(L: PState, idx: cint){.ilua.}
|
||||
proc insert*(L: PState, idx: cint){.ilua.}
|
||||
proc replace*(L: PState, idx: cint){.ilua.}
|
||||
proc checkstack*(L: PState, sz: cint): cint{.ilua.}
|
||||
proc xmove*(`from`, `to`: PState, n: cint){.ilua.}
|
||||
proc isnumber*(L: PState, idx: cint): cint{.ilua.}
|
||||
proc isstring*(L: PState, idx: cint): cint{.ilua.}
|
||||
proc iscfunction*(L: PState, idx: cint): cint{.ilua.}
|
||||
proc isuserdata*(L: PState, idx: cint): cint{.ilua.}
|
||||
proc luatype*(L: PState, idx: cint): cint{.importc: "lua_type".}
|
||||
proc typename*(L: PState, tp: cint): cstring{.ilua.}
|
||||
proc equal*(L: PState, idx1, idx2: cint): cint{.ilua.}
|
||||
proc rawequal*(L: PState, idx1, idx2: cint): cint{.ilua.}
|
||||
proc lessthan*(L: PState, idx1, idx2: cint): cint{.ilua.}
|
||||
proc tonumber*(L: PState, idx: cint): Number{.ilua.}
|
||||
proc tointeger*(L: PState, idx: cint): Integer{.ilua.}
|
||||
proc toboolean*(L: PState, idx: cint): cint{.ilua.}
|
||||
proc tolstring*(L: PState, idx: cint, length: ptr cint): cstring{.ilua.}
|
||||
proc objlen*(L: PState, idx: cint): cint{.ilua.}
|
||||
proc tocfunction*(L: PState, idx: cint): CFunction{.ilua.}
|
||||
proc touserdata*(L: PState, idx: cint): Pointer{.ilua.}
|
||||
proc tothread*(L: PState, idx: cint): PState{.ilua.}
|
||||
proc topointer*(L: PState, idx: cint): Pointer{.ilua.}
|
||||
proc pushnil*(L: PState){.ilua.}
|
||||
proc pushnumber*(L: PState, n: Number){.ilua.}
|
||||
proc pushinteger*(L: PState, n: Integer){.ilua.}
|
||||
proc pushlstring*(L: PState, s: cstring, len: cint){.ilua.}
|
||||
proc pushstring*(L: PState, s: cstring){.ilua.}
|
||||
proc pushvfstring*(L: PState, fmt: cstring, argp: Pointer): cstring{.ilua.}
|
||||
proc pushfstring*(L: PState, fmt: cstring): cstring{.varargs,ilua.}
|
||||
proc pushcclosure*(L: PState, fn: CFunction, n: cint){.ilua.}
|
||||
proc pushboolean*(L: PState, b: cint){.ilua.}
|
||||
proc pushlightuserdata*(L: PState, p: Pointer){.ilua.}
|
||||
proc pushthread*(L: PState){.ilua.}
|
||||
proc gettable*(L: PState, idx: cint){.ilua.}
|
||||
proc getfield*(L: Pstate, idx: cint, k: cstring){.ilua.}
|
||||
proc rawget*(L: PState, idx: cint){.ilua.}
|
||||
proc rawgeti*(L: PState, idx, n: cint){.ilua.}
|
||||
proc createtable*(L: PState, narr, nrec: cint){.ilua.}
|
||||
proc newuserdata*(L: PState, sz: cint): Pointer{.ilua.}
|
||||
proc getmetatable*(L: PState, objindex: cint): cint{.ilua.}
|
||||
proc getfenv*(L: PState, idx: cint){.ilua.}
|
||||
proc settable*(L: PState, idx: cint){.ilua.}
|
||||
proc setfield*(L: PState, idx: cint, k: cstring){.ilua.}
|
||||
proc rawset*(L: PState, idx: cint){.ilua.}
|
||||
proc rawseti*(L: PState, idx, n: cint){.ilua.}
|
||||
proc setmetatable*(L: PState, objindex: cint): cint{.ilua.}
|
||||
proc setfenv*(L: PState, idx: cint): cint{.ilua.}
|
||||
proc call*(L: PState, nargs, nresults: cint){.ilua.}
|
||||
proc pcall*(L: PState, nargs, nresults, errf: cint): cint{.ilua.}
|
||||
proc cpcall*(L: PState, func: CFunction, ud: Pointer): cint{.ilua.}
|
||||
proc load*(L: PState, reader: Reader, dt: Pointer, chunkname: cstring): cint{.ilua.}
|
||||
proc dump*(L: PState, writer: Writer, data: Pointer): cint{.ilua.}
|
||||
proc luayield*(L: PState, nresults: cint): cint{.importc: "lua_yield".}
|
||||
proc resume*(L: PState, narg: cint): cint{.ilua.}
|
||||
proc status*(L: PState): cint{.ilua.}
|
||||
proc gc*(L: PState, what, data: cint): cint{.ilua.}
|
||||
proc error*(L: PState): cint{.ilua.}
|
||||
proc next*(L: PState, idx: cint): cint{.ilua.}
|
||||
proc concat*(L: PState, n: cint){.ilua.}
|
||||
proc getallocf*(L: PState, ud: ptr Pointer): Alloc{.ilua.}
|
||||
proc setallocf*(L: PState, f: Alloc, ud: Pointer){.ilua.}
|
||||
{.pop.}
|
||||
|
||||
proc newstate*(f: Alloc, ud: Pointer): PState{.cdecl, dynlib: NAME,
|
||||
importc: "lua_newstate".}
|
||||
proc close*(L: PState){.cdecl, dynlib: NAME, importc: "lua_close".}
|
||||
proc newthread*(L: PState): PState{.cdecl, dynlib: NAME,
|
||||
importc: "lua_newthread".}
|
||||
proc atpanic*(L: PState, panicf: CFunction): CFunction{.cdecl, dynlib: NAME,
|
||||
importc: "lua_atpanic".}
|
||||
proc gettop*(L: PState): int{.cdecl, dynlib: NAME, importc: "lua_gettop".}
|
||||
proc settop*(L: PState, idx: int){.cdecl, dynlib: NAME, importc: "lua_settop".}
|
||||
proc pushvalue*(L: PState, Idx: int){.cdecl, dynlib: NAME,
|
||||
importc: "lua_pushvalue".}
|
||||
proc remove*(L: PState, idx: int){.cdecl, dynlib: NAME, importc: "lua_remove".}
|
||||
proc insert*(L: PState, idx: int){.cdecl, dynlib: NAME, importc: "lua_insert".}
|
||||
proc replace*(L: PState, idx: int){.cdecl, dynlib: NAME, importc: "lua_replace".}
|
||||
proc checkstack*(L: PState, sz: int): cint{.cdecl, dynlib: NAME,
|
||||
importc: "lua_checkstack".}
|
||||
proc xmove*(`from`, `to`: PState, n: int){.cdecl, dynlib: NAME,
|
||||
importc: "lua_xmove".}
|
||||
proc isnumber*(L: PState, idx: int): cint{.cdecl, dynlib: NAME,
|
||||
importc: "lua_isnumber".}
|
||||
proc isstring*(L: PState, idx: int): cint{.cdecl, dynlib: NAME,
|
||||
importc: "lua_isstring".}
|
||||
proc iscfunction*(L: PState, idx: int): cint{.cdecl, dynlib: NAME,
|
||||
importc: "lua_iscfunction".}
|
||||
proc isuserdata*(L: PState, idx: int): cint{.cdecl, dynlib: NAME,
|
||||
importc: "lua_isuserdata".}
|
||||
proc luatype*(L: PState, idx: int): int{.cdecl, dynlib: NAME, importc: "lua_type".}
|
||||
proc typename*(L: PState, tp: int): cstring{.cdecl, dynlib: NAME,
|
||||
importc: "lua_typename".}
|
||||
proc equal*(L: PState, idx1, idx2: int): cint{.cdecl, dynlib: NAME,
|
||||
importc: "lua_equal".}
|
||||
proc rawequal*(L: PState, idx1, idx2: int): cint{.cdecl, dynlib: NAME,
|
||||
importc: "lua_rawequal".}
|
||||
proc lessthan*(L: PState, idx1, idx2: int): cint{.cdecl, dynlib: NAME,
|
||||
importc: "lua_lessthan".}
|
||||
proc tonumber*(L: PState, idx: int): Number{.cdecl, dynlib: NAME,
|
||||
importc: "lua_tonumber".}
|
||||
proc tointeger*(L: PState, idx: int): Integer{.cdecl, dynlib: NAME,
|
||||
importc: "lua_tointeger".}
|
||||
proc toboolean*(L: PState, idx: int): cint{.cdecl, dynlib: NAME,
|
||||
importc: "lua_toboolean".}
|
||||
proc tolstring*(L: PState, idx: int, length: ptr int): cstring{.cdecl,
|
||||
dynlib: NAME, importc: "lua_tolstring".}
|
||||
proc objlen*(L: PState, idx: int): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_objlen".}
|
||||
proc tocfunction*(L: PState, idx: int): CFunction{.cdecl, dynlib: NAME,
|
||||
importc: "lua_tocfunction".}
|
||||
proc touserdata*(L: PState, idx: int): Pointer{.cdecl, dynlib: NAME,
|
||||
importc: "lua_touserdata".}
|
||||
proc tothread*(L: PState, idx: int): PState{.cdecl, dynlib: NAME,
|
||||
importc: "lua_tothread".}
|
||||
proc topointer*(L: PState, idx: int): Pointer{.cdecl, dynlib: NAME,
|
||||
importc: "lua_topointer".}
|
||||
proc pushnil*(L: PState){.cdecl, dynlib: NAME, importc: "lua_pushnil".}
|
||||
proc pushnumber*(L: PState, n: Number){.cdecl, dynlib: NAME,
|
||||
importc: "lua_pushnumber".}
|
||||
proc pushinteger*(L: PState, n: Integer){.cdecl, dynlib: NAME,
|
||||
importc: "lua_pushinteger".}
|
||||
proc pushlstring*(L: PState, s: cstring, len: int){.cdecl, dynlib: NAME,
|
||||
importc: "lua_pushlstring".}
|
||||
proc pushstring*(L: PState, s: cstring){.cdecl, dynlib: NAME,
|
||||
importc: "lua_pushstring".}
|
||||
proc pushvfstring*(L: PState, fmt: cstring, argp: Pointer): cstring{.cdecl,
|
||||
dynlib: NAME, importc: "lua_pushvfstring".}
|
||||
proc pushfstring*(L: PState, fmt: cstring): cstring{.cdecl, varargs,
|
||||
dynlib: NAME, importc: "lua_pushfstring".}
|
||||
proc pushcclosure*(L: PState, fn: CFunction, n: int){.cdecl, dynlib: NAME,
|
||||
importc: "lua_pushcclosure".}
|
||||
proc pushboolean*(L: PState, b: cint){.cdecl, dynlib: NAME,
|
||||
importc: "lua_pushboolean".}
|
||||
proc pushlightuserdata*(L: PState, p: Pointer){.cdecl, dynlib: NAME,
|
||||
importc: "lua_pushlightuserdata".}
|
||||
proc pushthread*(L: PState){.cdecl, dynlib: NAME, importc: "lua_pushthread".}
|
||||
proc gettable*(L: PState, idx: int){.cdecl, dynlib: NAME,
|
||||
importc: "lua_gettable".}
|
||||
proc getfield*(L: Pstate, idx: int, k: cstring){.cdecl, dynlib: NAME,
|
||||
importc: "lua_getfield".}
|
||||
proc rawget*(L: PState, idx: int){.cdecl, dynlib: NAME, importc: "lua_rawget".}
|
||||
proc rawgeti*(L: PState, idx, n: int){.cdecl, dynlib: NAME,
|
||||
importc: "lua_rawgeti".}
|
||||
proc createtable*(L: PState, narr, nrec: int){.cdecl, dynlib: NAME,
|
||||
importc: "lua_createtable".}
|
||||
proc newuserdata*(L: PState, sz: int): Pointer{.cdecl, dynlib: NAME,
|
||||
importc: "lua_newuserdata".}
|
||||
proc getmetatable*(L: PState, objindex: int): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_getmetatable".}
|
||||
proc getfenv*(L: PState, idx: int){.cdecl, dynlib: NAME, importc: "lua_getfenv".}
|
||||
proc settable*(L: PState, idx: int){.cdecl, dynlib: NAME,
|
||||
importc: "lua_settable".}
|
||||
proc setfield*(L: PState, idx: int, k: cstring){.cdecl, dynlib: NAME,
|
||||
importc: "lua_setfield".}
|
||||
proc rawset*(L: PState, idx: int){.cdecl, dynlib: NAME, importc: "lua_rawset".}
|
||||
proc rawseti*(L: PState, idx, n: int){.cdecl, dynlib: NAME,
|
||||
importc: "lua_rawseti".}
|
||||
proc setmetatable*(L: PState, objindex: int): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_setmetatable".}
|
||||
proc setfenv*(L: PState, idx: int): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_setfenv".}
|
||||
proc call*(L: PState, nargs, nresults: int){.cdecl, dynlib: NAME,
|
||||
importc: "lua_call".}
|
||||
proc pcall*(L: PState, nargs, nresults, errf: int): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_pcall".}
|
||||
proc cpcall*(L: PState, func: CFunction, ud: Pointer): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_cpcall".}
|
||||
proc load*(L: PState, reader: Reader, dt: Pointer, chunkname: cstring): int{.
|
||||
cdecl, dynlib: NAME, importc: "lua_load".}
|
||||
proc dump*(L: PState, writer: Writer, data: Pointer): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_dump".}
|
||||
proc luayield*(L: PState, nresults: int): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_yield".}
|
||||
proc resume*(L: PState, narg: int): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_resume".}
|
||||
proc status*(L: PState): int{.cdecl, dynlib: NAME, importc: "lua_status".}
|
||||
proc gc*(L: PState, what, data: int): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_gc".}
|
||||
proc error*(L: PState): int{.cdecl, dynlib: NAME, importc: "lua_error".}
|
||||
proc next*(L: PState, idx: int): int{.cdecl, dynlib: NAME, importc: "lua_next".}
|
||||
proc concat*(L: PState, n: int){.cdecl, dynlib: NAME, importc: "lua_concat".}
|
||||
proc getallocf*(L: PState, ud: ptr Pointer): Alloc{.cdecl, dynlib: NAME,
|
||||
importc: "lua_getallocf".}
|
||||
proc setallocf*(L: PState, f: Alloc, ud: Pointer){.cdecl, dynlib: NAME,
|
||||
importc: "lua_setallocf".}
|
||||
#
|
||||
#** Garbage-collection functions and options
|
||||
#
|
||||
|
|
@ -256,29 +212,29 @@ const
|
|||
#** ===============================================================
|
||||
#
|
||||
|
||||
proc pop*(L: PState, n: int)
|
||||
proc pop*(L: PState, n: cint)
|
||||
proc newtable*(L: Pstate)
|
||||
proc register*(L: PState, n: cstring, f: CFunction)
|
||||
proc pushcfunction*(L: PState, f: CFunction)
|
||||
proc strlen*(L: Pstate, i: int): int
|
||||
proc isfunction*(L: PState, n: int): bool
|
||||
proc istable*(L: PState, n: int): bool
|
||||
proc islightuserdata*(L: PState, n: int): bool
|
||||
proc isnil*(L: PState, n: int): bool
|
||||
proc isboolean*(L: PState, n: int): bool
|
||||
proc isthread*(L: PState, n: int): bool
|
||||
proc isnone*(L: PState, n: int): bool
|
||||
proc isnoneornil*(L: PState, n: int): bool
|
||||
proc strlen*(L: Pstate, i: cint): cint
|
||||
proc isfunction*(L: PState, n: cint): bool
|
||||
proc istable*(L: PState, n: cint): bool
|
||||
proc islightuserdata*(L: PState, n: cint): bool
|
||||
proc isnil*(L: PState, n: cint): bool
|
||||
proc isboolean*(L: PState, n: cint): bool
|
||||
proc isthread*(L: PState, n: cint): bool
|
||||
proc isnone*(L: PState, n: cint): bool
|
||||
proc isnoneornil*(L: PState, n: cint): bool
|
||||
proc pushliteral*(L: PState, s: cstring)
|
||||
proc setglobal*(L: PState, s: cstring)
|
||||
proc getglobal*(L: PState, s: cstring)
|
||||
proc tostring*(L: PState, i: int): cstring
|
||||
proc tostring*(L: PState, i: cint): cstring
|
||||
#
|
||||
#** compatibility macros and functions
|
||||
#
|
||||
|
||||
proc getregistry*(L: PState)
|
||||
proc getgccount*(L: PState): int
|
||||
proc getgccount*(L: PState): cint
|
||||
type
|
||||
Chunkreader* = Reader
|
||||
Chunkwriter* = Writer
|
||||
|
|
@ -307,18 +263,18 @@ const
|
|||
|
||||
type
|
||||
TDebug*{.final.} = object # activation record
|
||||
event*: int
|
||||
event*: cint
|
||||
name*: cstring # (n)
|
||||
namewhat*: cstring # (n) `global', `local', `field', `method'
|
||||
what*: cstring # (S) `Lua', `C', `main', `tail'
|
||||
source*: cstring # (S)
|
||||
currentline*: int # (l)
|
||||
nups*: int # (u) number of upvalues
|
||||
linedefined*: int # (S)
|
||||
lastlinedefined*: int # (S)
|
||||
short_src*: array[0..IDSIZE - 1, Char] # (S)
|
||||
# private part
|
||||
i_ci*: int # active function
|
||||
currentline*: cint # (l)
|
||||
nups*: cint # (u) number of upvalues
|
||||
linedefined*: cint # (S)
|
||||
lastlinedefined*: cint # (S)
|
||||
short_src*: array[0.. <IDSIZE, Char] # (S) \
|
||||
# private part
|
||||
i_ci*: cint # active function
|
||||
|
||||
PDebug* = ptr TDebug
|
||||
Hook* = proc (L: PState, ar: PDebug){.cdecl.}
|
||||
|
|
@ -329,31 +285,27 @@ type
|
|||
#** ======================================================================
|
||||
#
|
||||
|
||||
proc getstack*(L: PState, level: int, ar: PDebug): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_getstack".}
|
||||
proc getinfo*(L: PState, what: cstring, ar: PDebug): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_getinfo".}
|
||||
proc getlocal*(L: PState, ar: PDebug, n: int): cstring{.cdecl, dynlib: NAME,
|
||||
importc: "lua_getlocal".}
|
||||
proc setlocal*(L: PState, ar: PDebug, n: int): cstring{.cdecl, dynlib: NAME,
|
||||
importc: "lua_setlocal".}
|
||||
proc getupvalue*(L: PState, funcindex: int, n: int): cstring{.cdecl,
|
||||
dynlib: NAME, importc: "lua_getupvalue".}
|
||||
proc setupvalue*(L: PState, funcindex: int, n: int): cstring{.cdecl,
|
||||
dynlib: NAME, importc: "lua_setupvalue".}
|
||||
proc sethook*(L: PState, func: Hook, mask: int, count: int): int{.cdecl,
|
||||
dynlib: NAME, importc: "lua_sethook".}
|
||||
proc gethook*(L: PState): Hook{.cdecl, dynlib: NAME, importc: "lua_gethook".}
|
||||
proc gethookmask*(L: PState): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_gethookmask".}
|
||||
proc gethookcount*(L: PState): int{.cdecl, dynlib: NAME,
|
||||
importc: "lua_gethookcount".}
|
||||
{.push callConv: cdecl, dynlib: lua.LIB_NAME.}
|
||||
|
||||
proc getstack*(L: PState, level: cint, ar: PDebug): cint{.ilua.}
|
||||
proc getinfo*(L: PState, what: cstring, ar: PDebug): cint{.ilua.}
|
||||
proc getlocal*(L: PState, ar: PDebug, n: cint): cstring{.ilua.}
|
||||
proc setlocal*(L: PState, ar: PDebug, n: cint): cstring{.ilua.}
|
||||
proc getupvalue*(L: PState, funcindex: cint, n: cint): cstring{.ilua.}
|
||||
proc setupvalue*(L: PState, funcindex: cint, n: cint): cstring{.ilua.}
|
||||
proc sethook*(L: PState, func: Hook, mask: cint, count: cint): cint{.ilua.}
|
||||
proc gethook*(L: PState): Hook{.ilua.}
|
||||
proc gethookmask*(L: PState): cint{.ilua.}
|
||||
proc gethookcount*(L: PState): cint{.ilua.}
|
||||
|
||||
{.pop.}
|
||||
|
||||
# implementation
|
||||
|
||||
proc upvalueindex(I: int): int =
|
||||
proc upvalueindex(I: cint): cint =
|
||||
Result = GLOBALSINDEX - i
|
||||
|
||||
proc pop(L: PState, n: int) =
|
||||
proc pop(L: PState, n: cint) =
|
||||
settop(L, - n - 1)
|
||||
|
||||
proc newtable(L: PState) =
|
||||
|
|
@ -366,35 +318,35 @@ proc register(L: PState, n: cstring, f: CFunction) =
|
|||
proc pushcfunction(L: PState, f: CFunction) =
|
||||
pushcclosure(L, f, 0)
|
||||
|
||||
proc strlen(L: PState, i: int): int =
|
||||
proc strlen(L: PState, i: cint): cint =
|
||||
Result = objlen(L, i)
|
||||
|
||||
proc isfunction(L: PState, n: int): bool =
|
||||
proc isfunction(L: PState, n: cint): bool =
|
||||
Result = luatype(L, n) == TFUNCTION
|
||||
|
||||
proc istable(L: PState, n: int): bool =
|
||||
proc istable(L: PState, n: cint): bool =
|
||||
Result = luatype(L, n) == TTABLE
|
||||
|
||||
proc islightuserdata(L: PState, n: int): bool =
|
||||
proc islightuserdata(L: PState, n: cint): bool =
|
||||
Result = luatype(L, n) == TLIGHTUSERDATA
|
||||
|
||||
proc isnil(L: PState, n: int): bool =
|
||||
proc isnil(L: PState, n: cint): bool =
|
||||
Result = luatype(L, n) == TNIL
|
||||
|
||||
proc isboolean(L: PState, n: int): bool =
|
||||
proc isboolean(L: PState, n: cint): bool =
|
||||
Result = luatype(L, n) == TBOOLEAN
|
||||
|
||||
proc isthread(L: PState, n: int): bool =
|
||||
proc isthread(L: PState, n: cint): bool =
|
||||
Result = luatype(L, n) == TTHREAD
|
||||
|
||||
proc isnone(L: PState, n: int): bool =
|
||||
proc isnone(L: PState, n: cint): bool =
|
||||
Result = luatype(L, n) == TNONE
|
||||
|
||||
proc isnoneornil(L: PState, n: int): bool =
|
||||
proc isnoneornil(L: PState, n: cint): bool =
|
||||
Result = luatype(L, n) <= 0
|
||||
|
||||
proc pushliteral(L: PState, s: cstring) =
|
||||
pushlstring(L, s, len(s))
|
||||
pushlstring(L, s, s.len.cint)
|
||||
|
||||
proc setglobal(L: PState, s: cstring) =
|
||||
setfield(L, GLOBALSINDEX, s)
|
||||
|
|
@ -402,11 +354,11 @@ proc setglobal(L: PState, s: cstring) =
|
|||
proc getglobal(L: PState, s: cstring) =
|
||||
getfield(L, GLOBALSINDEX, s)
|
||||
|
||||
proc tostring(L: PState, i: int): cstring =
|
||||
proc tostring(L: PState, i: cint): cstring =
|
||||
Result = tolstring(L, i, nil)
|
||||
|
||||
proc getregistry(L: PState) =
|
||||
pushvalue(L, REGISTRYINDEX)
|
||||
|
||||
proc getgccount(L: PState): int =
|
||||
proc getgccount(L: PState): cint =
|
||||
Result = gc(L, GCCOUNT, 0)
|
||||
|
|
|
|||
|
|
@ -32,35 +32,33 @@ const
|
|||
DBLIBNAME* = "debug"
|
||||
LOADLIBNAME* = "package"
|
||||
|
||||
proc open_base*(L: PState): cint{.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaopen_base".}
|
||||
proc open_table*(L: PState): cint{.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaopen_table".}
|
||||
proc open_io*(L: PState): cint{.cdecl, dynlib: LIB_NAME, importc: "luaopen_io".}
|
||||
proc open_string*(L: PState): cint{.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaopen_string".}
|
||||
proc open_math*(L: PState): cint{.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaopen_math".}
|
||||
proc open_debug*(L: PState): cint{.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaopen_debug".}
|
||||
proc open_package*(L: PState): cint{.cdecl, dynlib: LIB_NAME,
|
||||
importc: "luaopen_package".}
|
||||
proc openlibs*(L: PState){.cdecl, dynlib: LIB_NAME, importc: "luaL_openlibs".}
|
||||
{.pragma: ilua, importc: "lua$1".}
|
||||
|
||||
{.push callConv: cdecl, dynlib: lua.LIB_NAME.}
|
||||
proc open_base*(L: PState): cint{.ilua.}
|
||||
proc open_table*(L: PState): cint{.ilua.}
|
||||
proc open_io*(L: PState): cint{.ilua.}
|
||||
proc open_string*(L: PState): cint{.ilua.}
|
||||
proc open_math*(L: PState): cint{.ilua.}
|
||||
proc open_debug*(L: PState): cint{.ilua.}
|
||||
proc open_package*(L: PState): cint{.ilua.}
|
||||
proc openlibs*(L: PState){.importc: "luaL_openlibs".}
|
||||
{.pop.}
|
||||
|
||||
proc baselibopen*(L: PState): Bool =
|
||||
Result = open_base(L) != 0'i32
|
||||
open_base(L) != 0'i32
|
||||
|
||||
proc tablibopen*(L: PState): Bool =
|
||||
Result = open_table(L) != 0'i32
|
||||
open_table(L) != 0'i32
|
||||
|
||||
proc iolibopen*(L: PState): Bool =
|
||||
Result = open_io(L) != 0'i32
|
||||
open_io(L) != 0'i32
|
||||
|
||||
proc strlibopen*(L: PState): Bool =
|
||||
Result = open_string(L) != 0'i32
|
||||
open_string(L) != 0'i32
|
||||
|
||||
proc mathlibopen*(L: PState): Bool =
|
||||
Result = open_math(L) != 0'i32
|
||||
open_math(L) != 0'i32
|
||||
|
||||
proc dblibopen*(L: PState): Bool =
|
||||
Result = open_debug(L) != 0'i32
|
||||
open_debug(L) != 0'i32
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ const
|
|||
|
||||
proc SSL_library_init*(): cInt{.cdecl, dynlib: DLLSSLName, importc, discardable.}
|
||||
proc SSL_load_error_strings*(){.cdecl, dynlib: DLLSSLName, importc.}
|
||||
proc ERR_load_BIO_strings*(){.cdecl, dynlib: DLLSSLName, importc.}
|
||||
proc ERR_load_BIO_strings*(){.cdecl, dynlib: DLLUtilName, importc.}
|
||||
|
||||
proc SSLv23_client_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.}
|
||||
proc SSLv23_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
|
@ -262,14 +262,15 @@ proc ERR_error_string*(e: cInt, buf: cstring): cstring{.cdecl,
|
|||
proc ERR_get_error*(): cInt{.cdecl, dynlib: DLLUtilName, importc.}
|
||||
proc ERR_peek_last_error*(): cInt{.cdecl, dynlib: DLLUtilName, importc.}
|
||||
|
||||
proc OpenSSL_add_all_algorithms*(){.cdecl, dynlib: DLLSSLName, importc: "OPENSSL_add_all_algorithms_conf".}
|
||||
proc OpenSSL_add_all_algorithms*(){.cdecl, dynlib: DLLUtilName, importc: "OPENSSL_add_all_algorithms_conf".}
|
||||
|
||||
proc OPENSSL_config*(configName: cstring){.cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
||||
proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl, dynlib: DLLSSLName, importc.}
|
||||
|
||||
proc CRYPTO_malloc_init*() =
|
||||
CRYPTO_set_mem_functions(alloc, realloc, dealloc)
|
||||
when not defined(windows):
|
||||
CRYPTO_set_mem_functions(alloc, realloc, dealloc)
|
||||
|
||||
when True:
|
||||
nil
|
||||
|
|
|
|||
|
|
@ -156,33 +156,34 @@ const
|
|||
type
|
||||
Thook_func* = proc (a2: cstring): cstring{.cdecl.}
|
||||
|
||||
# If non-null, this contains the address of a function that the application
|
||||
# wants called before trying the standard tilde expansions. The function
|
||||
# is called with the text sans tilde, and returns a malloc()'ed string
|
||||
# which is the expansion, or a NULL pointer if the expansion fails.
|
||||
when not defined(macosx):
|
||||
# If non-null, this contains the address of a function that the application
|
||||
# wants called before trying the standard tilde expansions. The function
|
||||
# is called with the text sans tilde, and returns a malloc()'ed string
|
||||
# which is the expansion, or a NULL pointer if the expansion fails.
|
||||
|
||||
var expansion_preexpansion_hook*{.importc: "tilde_expansion_preexpansion_hook",
|
||||
dynlib: tildeDll.}: Thook_func
|
||||
var expansion_preexpansion_hook*{.importc: "tilde_expansion_preexpansion_hook",
|
||||
dynlib: tildeDll.}: Thook_func
|
||||
|
||||
# If non-null, this contains the address of a function to call if the
|
||||
# standard meaning for expanding a tilde fails. The function is called
|
||||
# with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
|
||||
# which is the expansion, or a NULL pointer if there is no expansion.
|
||||
# If non-null, this contains the address of a function to call if the
|
||||
# standard meaning for expanding a tilde fails. The function is called
|
||||
# with the text (sans tilde, as in "foo"), and returns a malloc()'ed string
|
||||
# which is the expansion, or a NULL pointer if there is no expansion.
|
||||
|
||||
var expansion_failure_hook*{.importc: "tilde_expansion_failure_hook",
|
||||
dynlib: tildeDll.}: Thook_func
|
||||
var expansion_failure_hook*{.importc: "tilde_expansion_failure_hook",
|
||||
dynlib: tildeDll.}: Thook_func
|
||||
|
||||
# When non-null, this is a NULL terminated array of strings which
|
||||
# are duplicates for a tilde prefix. Bash uses this to expand
|
||||
# `=~' and `:~'.
|
||||
# When non-null, this is a NULL terminated array of strings which
|
||||
# are duplicates for a tilde prefix. Bash uses this to expand
|
||||
# `=~' and `:~'.
|
||||
|
||||
var additional_prefixes*{.importc: "tilde_additional_prefixes", dynlib: tildeDll.}: cstringArray
|
||||
var additional_prefixes*{.importc: "tilde_additional_prefixes", dynlib: tildeDll.}: cstringArray
|
||||
|
||||
# When non-null, this is a NULL terminated array of strings which match
|
||||
# the end of a username, instead of just "/". Bash sets this to
|
||||
# `:' and `=~'.
|
||||
# When non-null, this is a NULL terminated array of strings which match
|
||||
# the end of a username, instead of just "/". Bash sets this to
|
||||
# `:' and `=~'.
|
||||
|
||||
var additional_suffixes*{.importc: "tilde_additional_suffixes", dynlib: tildeDll.}: cstringArray
|
||||
var additional_suffixes*{.importc: "tilde_additional_suffixes", dynlib: tildeDll.}: cstringArray
|
||||
|
||||
# Return a new string which is the result of tilde expanding STRING.
|
||||
|
||||
|
|
@ -229,7 +230,8 @@ type
|
|||
|
||||
# The current undo list for RL_LINE_BUFFER.
|
||||
|
||||
var undo_list*{.importc: "rl_undo_list", dynlib: readlineDll.}: ptr TUNDO_LIST
|
||||
when not defined(macosx):
|
||||
var undo_list*{.importc: "rl_undo_list", dynlib: readlineDll.}: ptr TUNDO_LIST
|
||||
|
||||
# The data structure for mapping textual names to code addresses.
|
||||
|
||||
|
|
@ -239,7 +241,8 @@ type
|
|||
function*: TCommandFunc
|
||||
|
||||
|
||||
var funmap*{.importc: "funmap", dynlib: readlineDll.}: ptr ptr TFUNMAP
|
||||
when not defined(macosx):
|
||||
var funmap*{.importc: "funmap", dynlib: readlineDll.}: ptr ptr TFUNMAP
|
||||
|
||||
# ****************************************************************
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Interface to the `libzip <http://www.nih.at/libzip/index.html>`_ library by
|
||||
## Dieter Baron and Thomas Klausner. However, this does not need any external
|
||||
## library (DLL, lib*.so), as the source for this library is included and
|
||||
## compiled with this interface.
|
||||
## Dieter Baron and Thomas Klausner. This version links
|
||||
## against ``libzip2.so.2`` unless you define the symbol ``useLibzipSrc``; then
|
||||
## it is compiled against some old ``libizp_all.c`` file.
|
||||
|
||||
#
|
||||
# zip.h -- exported declarations.
|
||||
|
|
@ -47,9 +47,16 @@
|
|||
|
||||
import times
|
||||
|
||||
{.compile: "libzip_all.c".}
|
||||
when defined(unix):
|
||||
{.passl: "-lz".}
|
||||
when defined(unix) and not defined(useLibzipSrc):
|
||||
when defined(macosx):
|
||||
{.pragma: mydll, dynlib: "libzip2.dylib".}
|
||||
else:
|
||||
{.pragma: mydll, dynlib: "libzip2.so(|.2|.1|.0)".}
|
||||
else:
|
||||
when defined(unix):
|
||||
{.passl: "-lz".}
|
||||
{.compile: "libzip_all.c".}
|
||||
{.pragma: mydll.}
|
||||
|
||||
type
|
||||
Tzip_source_cmd* = int32
|
||||
|
|
@ -57,7 +64,7 @@ type
|
|||
Tzip_source_callback* = proc (state: pointer, data: pointer, length: int,
|
||||
cmd: Tzip_source_cmd): int {.cdecl.}
|
||||
Pzip_stat* = ptr Tzip_stat
|
||||
Tzip_stat* {.final, pure.} = object
|
||||
Tzip_stat* = object ## the 'zip_stat' struct
|
||||
name*: cstring ## name of the file
|
||||
index*: int32 ## index within archive
|
||||
crc*: int32 ## crc of file data
|
||||
|
|
@ -67,9 +74,9 @@ type
|
|||
comp_method*: int16 ## compression method used
|
||||
encryption_method*: int16 ## encryption method used
|
||||
|
||||
Tzip {.final, pure.} = object
|
||||
Tzip_source {.final, pure.} = object
|
||||
Tzip_file {.final, pure.} = object
|
||||
Tzip = object
|
||||
Tzip_source = object
|
||||
Tzip_file = object
|
||||
|
||||
Pzip* = ptr Tzip ## represents a zip archive
|
||||
Pzip_file* = ptr Tzip_file ## represents a file within an archive
|
||||
|
|
@ -160,82 +167,83 @@ const
|
|||
constZIP_SOURCE_FREE* = 5'i32 ## cleanup and free resources
|
||||
|
||||
proc zip_add*(para1: Pzip, para2: cstring, para3: Pzip_source): int32 {.cdecl,
|
||||
importc: "zip_add".}
|
||||
importc: "zip_add", mydll.}
|
||||
proc zip_add_dir*(para1: Pzip, para2: cstring): int32 {.cdecl,
|
||||
importc: "zip_add_dir".}
|
||||
proc zip_close*(para1: Pzip) {.cdecl, importc: "zip_close".}
|
||||
proc zip_delete*(para1: Pzip, para2: int32): int32 {.cdecl,
|
||||
importc: "zip_add_dir", mydll.}
|
||||
proc zip_close*(para1: Pzip) {.cdecl, importc: "zip_close", mydll.}
|
||||
proc zip_delete*(para1: Pzip, para2: int32): int32 {.cdecl, mydll,
|
||||
importc: "zip_delete".}
|
||||
proc zip_error_clear*(para1: Pzip) {.cdecl, importc: "zip_error_clear".}
|
||||
proc zip_error_clear*(para1: Pzip) {.cdecl, importc: "zip_error_clear", mydll.}
|
||||
proc zip_error_get*(para1: Pzip, para2: ptr int32, para3: ptr int32) {.cdecl,
|
||||
importc: "zip_error_get".}
|
||||
proc zip_error_get_sys_type*(para1: int32): int32 {.cdecl,
|
||||
importc: "zip_error_get", mydll.}
|
||||
proc zip_error_get_sys_type*(para1: int32): int32 {.cdecl, mydll,
|
||||
importc: "zip_error_get_sys_type".}
|
||||
proc zip_error_to_str*(para1: cstring, para2: int, para3: int32,
|
||||
para4: int32): int32 {.cdecl,
|
||||
para4: int32): int32 {.cdecl, mydll,
|
||||
importc: "zip_error_to_str".}
|
||||
proc zip_fclose*(para1: Pzip_file) {.cdecl,
|
||||
proc zip_fclose*(para1: Pzip_file) {.cdecl, mydll,
|
||||
importc: "zip_fclose".}
|
||||
proc zip_file_error_clear*(para1: Pzip_file) {.cdecl,
|
||||
proc zip_file_error_clear*(para1: Pzip_file) {.cdecl, mydll,
|
||||
importc: "zip_file_error_clear".}
|
||||
proc zip_file_error_get*(para1: Pzip_file, para2: ptr int32, para3: ptr int32) {.
|
||||
cdecl, importc: "zip_file_error_get".}
|
||||
proc zip_file_strerror*(para1: Pzip_file): cstring {.cdecl,
|
||||
cdecl, mydll, importc: "zip_file_error_get".}
|
||||
proc zip_file_strerror*(para1: Pzip_file): cstring {.cdecl, mydll,
|
||||
importc: "zip_file_strerror".}
|
||||
proc zip_fopen*(para1: Pzip, para2: cstring, para3: int32): Pzip_file {.cdecl,
|
||||
importc: "zip_fopen".}
|
||||
mydll, importc: "zip_fopen".}
|
||||
proc zip_fopen_index*(para1: Pzip, para2: int32, para3: int32): Pzip_file {.
|
||||
cdecl, importc: "zip_fopen_index".}
|
||||
cdecl, mydll, importc: "zip_fopen_index".}
|
||||
proc zip_fread*(para1: Pzip_file, para2: pointer, para3: int): int {.
|
||||
cdecl, importc: "zip_fread".}
|
||||
cdecl, mydll, importc: "zip_fread".}
|
||||
proc zip_get_archive_comment*(para1: Pzip, para2: ptr int32, para3: int32): cstring {.
|
||||
cdecl, importc: "zip_get_archive_comment".}
|
||||
cdecl, mydll, importc: "zip_get_archive_comment".}
|
||||
proc zip_get_archive_flag*(para1: Pzip, para2: int32, para3: int32): int32 {.
|
||||
cdecl, importc: "zip_get_archive_flag".}
|
||||
cdecl, mydll, importc: "zip_get_archive_flag".}
|
||||
proc zip_get_file_comment*(para1: Pzip, para2: int32, para3: ptr int32,
|
||||
para4: int32): cstring {.cdecl,
|
||||
para4: int32): cstring {.cdecl, mydll,
|
||||
importc: "zip_get_file_comment".}
|
||||
proc zip_get_name*(para1: Pzip, para2: int32, para3: int32): cstring {.cdecl,
|
||||
importc: "zip_get_name".}
|
||||
mydll, importc: "zip_get_name".}
|
||||
proc zip_get_num_files*(para1: Pzip): int32 {.cdecl,
|
||||
importc: "zip_get_num_files".}
|
||||
mydll, importc: "zip_get_num_files".}
|
||||
proc zip_name_locate*(para1: Pzip, para2: cstring, para3: int32): int32 {.cdecl,
|
||||
importc: "zip_name_locate".}
|
||||
mydll, importc: "zip_name_locate".}
|
||||
proc zip_open*(para1: cstring, para2: int32, para3: ptr int32): Pzip {.cdecl,
|
||||
importc: "zip_open".}
|
||||
mydll, importc: "zip_open".}
|
||||
proc zip_rename*(para1: Pzip, para2: int32, para3: cstring): int32 {.cdecl,
|
||||
importc: "zip_rename".}
|
||||
mydll, importc: "zip_rename".}
|
||||
proc zip_replace*(para1: Pzip, para2: int32, para3: Pzip_source): int32 {.cdecl,
|
||||
importc: "zip_replace".}
|
||||
mydll, importc: "zip_replace".}
|
||||
proc zip_set_archive_comment*(para1: Pzip, para2: cstring, para3: int32): int32 {.
|
||||
cdecl, importc: "zip_set_archive_comment".}
|
||||
cdecl, mydll, importc: "zip_set_archive_comment".}
|
||||
proc zip_set_archive_flag*(para1: Pzip, para2: int32, para3: int32): int32 {.
|
||||
cdecl, importc: "zip_set_archive_flag".}
|
||||
cdecl, mydll, importc: "zip_set_archive_flag".}
|
||||
proc zip_set_file_comment*(para1: Pzip, para2: int32, para3: cstring,
|
||||
para4: int32): int32 {.cdecl,
|
||||
para4: int32): int32 {.cdecl, mydll,
|
||||
importc: "zip_set_file_comment".}
|
||||
proc zip_source_buffer*(para1: Pzip, para2: pointer, para3: int, para4: int32): Pzip_source {.
|
||||
cdecl, importc: "zip_source_buffer".}
|
||||
cdecl, mydll, importc: "zip_source_buffer".}
|
||||
proc zip_source_file*(para1: Pzip, para2: cstring, para3: int, para4: int): Pzip_source {.
|
||||
cdecl, importc: "zip_source_file".}
|
||||
cdecl, mydll, importc: "zip_source_file".}
|
||||
proc zip_source_filep*(para1: Pzip, para2: TFile, para3: int, para4: int): Pzip_source {.
|
||||
cdecl, importc: "zip_source_filep".}
|
||||
proc zip_source_free*(para1: Pzip_source) {.cdecl,
|
||||
cdecl, mydll, importc: "zip_source_filep".}
|
||||
proc zip_source_free*(para1: Pzip_source) {.cdecl, mydll,
|
||||
importc: "zip_source_free".}
|
||||
proc zip_source_function*(para1: Pzip, para2: Tzip_source_callback,
|
||||
para3: pointer): Pzip_source {.cdecl,
|
||||
para3: pointer): Pzip_source {.cdecl, mydll,
|
||||
importc: "zip_source_function".}
|
||||
proc zip_source_zip*(para1: Pzip, para2: Pzip, para3: int32, para4: int32,
|
||||
para5: int, para6: int): Pzip_source {.cdecl,
|
||||
para5: int, para6: int): Pzip_source {.cdecl, mydll,
|
||||
importc: "zip_source_zip".}
|
||||
proc zip_stat*(para1: Pzip, para2: cstring, para3: int32, para4: Pzip_stat): int32 {.
|
||||
cdecl, importc: "zip_stat".}
|
||||
cdecl, mydll, importc: "zip_stat".}
|
||||
proc zip_stat_index*(para1: Pzip, para2: int32, para3: int32, para4: Pzip_stat): int32 {.
|
||||
cdecl, importc: "zip_stat_index".}
|
||||
proc zip_stat_init*(para1: Pzip_stat) {.cdecl, importc: "zip_stat_init".}
|
||||
proc zip_strerror*(para1: Pzip): cstring {.cdecl, importc: "zip_strerror".}
|
||||
proc zip_unchange*(para1: Pzip, para2: int32): int32 {.cdecl,
|
||||
cdecl, mydll, importc: "zip_stat_index".}
|
||||
proc zip_stat_init*(para1: Pzip_stat) {.cdecl, mydll, importc: "zip_stat_init".}
|
||||
proc zip_strerror*(para1: Pzip): cstring {.cdecl, mydll, importc: "zip_strerror".}
|
||||
proc zip_unchange*(para1: Pzip, para2: int32): int32 {.cdecl, mydll,
|
||||
importc: "zip_unchange".}
|
||||
proc zip_unchange_all*(para1: Pzip): int32 {.cdecl, importc: "zip_unchange_all".}
|
||||
proc zip_unchange_archive*(para1: Pzip): int32 {.cdecl,
|
||||
proc zip_unchange_all*(para1: Pzip): int32 {.cdecl, mydll,
|
||||
importc: "zip_unchange_all".}
|
||||
proc zip_unchange_archive*(para1: Pzip): int32 {.cdecl, mydll,
|
||||
importc: "zip_unchange_archive".}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue