Merge branch 'devel' of git://github.com/Araq/Nimrod
This commit is contained in:
commit
a8b4e3c764
741 changed files with 20953 additions and 11950 deletions
|
|
@ -45,28 +45,28 @@ when noDeadlocks:
|
|||
locksLen {.threadvar.}: int
|
||||
locks {.threadvar.}: array [0..MaxLocksPerThread-1, pointer]
|
||||
|
||||
proc OrderedLocks(): bool =
|
||||
proc orderedLocks(): bool =
|
||||
for i in 0 .. locksLen-2:
|
||||
if locks[i] >= locks[i+1]: return false
|
||||
result = true
|
||||
|
||||
proc InitLock*(lock: var TLock) {.inline.} =
|
||||
proc initLock*(lock: var TLock) {.inline.} =
|
||||
## Initializes the given lock.
|
||||
InitSysLock(lock)
|
||||
initSysLock(lock)
|
||||
|
||||
proc DeinitLock*(lock: var TLock) {.inline.} =
|
||||
proc deinitLock*(lock: var TLock) {.inline.} =
|
||||
## Frees the resources associated with the lock.
|
||||
DeinitSys(lock)
|
||||
deinitSys(lock)
|
||||
|
||||
proc TryAcquire*(lock: var TLock): bool {.tags: [FAquireLock].} =
|
||||
proc tryAcquire*(lock: var TLock): bool {.tags: [FAquireLock].} =
|
||||
## Tries to acquire the given lock. Returns `true` on success.
|
||||
result = TryAcquireSys(lock)
|
||||
result = tryAcquireSys(lock)
|
||||
when noDeadlocks:
|
||||
if not result: return
|
||||
# we have to add it to the ordered list. Oh, and we might fail if
|
||||
# there is no space in the array left ...
|
||||
if locksLen >= len(locks):
|
||||
ReleaseSys(lock)
|
||||
releaseSys(lock)
|
||||
raise newException(EResourceExhausted, "cannot acquire additional lock")
|
||||
# find the position to add:
|
||||
var p = addr(lock)
|
||||
|
|
@ -83,14 +83,14 @@ proc TryAcquire*(lock: var TLock): bool {.tags: [FAquireLock].} =
|
|||
dec L
|
||||
locks[i] = p
|
||||
inc(locksLen)
|
||||
assert OrderedLocks()
|
||||
assert orderedLocks()
|
||||
return
|
||||
# simply add to the end:
|
||||
locks[locksLen] = p
|
||||
inc(locksLen)
|
||||
assert OrderedLocks()
|
||||
assert orderedLocks()
|
||||
|
||||
proc Acquire*(lock: var TLock) {.tags: [FAquireLock].} =
|
||||
proc acquire*(lock: var TLock) {.tags: [FAquireLock].} =
|
||||
## Acquires the given lock.
|
||||
when nodeadlocks:
|
||||
var p = addr(lock)
|
||||
|
|
@ -106,36 +106,36 @@ proc Acquire*(lock: var TLock) {.tags: [FAquireLock].} =
|
|||
raise newException(EResourceExhausted,
|
||||
"cannot acquire additional lock")
|
||||
while L >= i:
|
||||
ReleaseSys(cast[ptr TSysLock](locks[L])[])
|
||||
releaseSys(cast[ptr TSysLock](locks[L])[])
|
||||
locks[L+1] = locks[L]
|
||||
dec L
|
||||
# acquire the current lock:
|
||||
AcquireSys(lock)
|
||||
acquireSys(lock)
|
||||
locks[i] = p
|
||||
inc(locksLen)
|
||||
# acquire old locks in proper order again:
|
||||
L = locksLen-1
|
||||
inc i
|
||||
while i <= L:
|
||||
AcquireSys(cast[ptr TSysLock](locks[i])[])
|
||||
acquireSys(cast[ptr TSysLock](locks[i])[])
|
||||
inc(i)
|
||||
# DANGER: We can only modify this global var if we gained every lock!
|
||||
# NO! We need an atomic increment. Crap.
|
||||
discard system.atomicInc(deadlocksPrevented, 1)
|
||||
assert OrderedLocks()
|
||||
assert orderedLocks()
|
||||
return
|
||||
|
||||
# simply add to the end:
|
||||
if locksLen >= len(locks):
|
||||
raise newException(EResourceExhausted, "cannot acquire additional lock")
|
||||
AcquireSys(lock)
|
||||
acquireSys(lock)
|
||||
locks[locksLen] = p
|
||||
inc(locksLen)
|
||||
assert OrderedLocks()
|
||||
assert orderedLocks()
|
||||
else:
|
||||
AcquireSys(lock)
|
||||
acquireSys(lock)
|
||||
|
||||
proc Release*(lock: var TLock) {.tags: [FReleaseLock].} =
|
||||
proc release*(lock: var TLock) {.tags: [FReleaseLock].} =
|
||||
## Releases the given lock.
|
||||
when nodeadlocks:
|
||||
var p = addr(lock)
|
||||
|
|
@ -145,20 +145,20 @@ proc Release*(lock: var TLock) {.tags: [FReleaseLock].} =
|
|||
for j in i..L-2: locks[j] = locks[j+1]
|
||||
dec locksLen
|
||||
break
|
||||
ReleaseSys(lock)
|
||||
releaseSys(lock)
|
||||
|
||||
|
||||
proc InitCond*(cond: var TCond) {.inline.} =
|
||||
proc initCond*(cond: var TCond) {.inline.} =
|
||||
## Initializes the given condition variable.
|
||||
InitSysCond(cond)
|
||||
initSysCond(cond)
|
||||
|
||||
proc DeinitCond*(cond: var TCond) {.inline.} =
|
||||
proc deinitCond*(cond: var TCond) {.inline.} =
|
||||
## Frees the resources associated with the lock.
|
||||
DeinitSysCond(cond)
|
||||
deinitSysCond(cond)
|
||||
|
||||
proc wait*(cond: var TCond, lock: var TLock) {.inline.} =
|
||||
## waits on the condition variable `cond`.
|
||||
WaitSysCond(cond, lock)
|
||||
waitSysCond(cond, lock)
|
||||
|
||||
proc signal*(cond: var TCond) {.inline.} =
|
||||
## sends a signal to the condition variable `cond`.
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ type
|
|||
nnkBindStmt, nnkMixinStmt, nnkUsingStmt,
|
||||
nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
|
||||
nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy,
|
||||
nnkTupleTy, nnkTypeClassTy, nnkRecList, nnkRecCase, nnkRecWhen,
|
||||
nnkTupleTy, nnkTypeClassTy, nnkStaticTy,
|
||||
nnkRecList, nnkRecCase, nnkRecWhen,
|
||||
nnkRefTy, nnkPtrTy, nnkVarTy,
|
||||
nnkConstTy, nnkMutableTy,
|
||||
nnkDistinctTy,
|
||||
|
|
@ -147,18 +148,24 @@ proc del*(father: PNimrodNode, idx = 0, n = 1) {.magic: "NDel".}
|
|||
proc kind*(n: PNimrodNode): TNimrodNodeKind {.magic: "NKind".}
|
||||
## returns the `kind` of the node `n`.
|
||||
|
||||
proc intVal*(n: PNimrodNode): biggestInt {.magic: "NIntVal".}
|
||||
proc floatVal*(n: PNimrodNode): biggestFloat {.magic: "NFloatVal".}
|
||||
proc intVal*(n: PNimrodNode): BiggestInt {.magic: "NIntVal".}
|
||||
proc floatVal*(n: PNimrodNode): BiggestFloat {.magic: "NFloatVal".}
|
||||
proc symbol*(n: PNimrodNode): PNimrodSymbol {.magic: "NSymbol".}
|
||||
proc ident*(n: PNimrodNode): TNimrodIdent {.magic: "NIdent".}
|
||||
proc typ*(n: PNimrodNode): typedesc {.magic: "NGetType".}
|
||||
proc strVal*(n: PNimrodNode): string {.magic: "NStrVal".}
|
||||
|
||||
proc `intVal=`*(n: PNimrodNode, val: biggestInt) {.magic: "NSetIntVal".}
|
||||
proc `floatVal=`*(n: PNimrodNode, val: biggestFloat) {.magic: "NSetFloatVal".}
|
||||
proc `intVal=`*(n: PNimrodNode, val: BiggestInt) {.magic: "NSetIntVal".}
|
||||
proc `floatVal=`*(n: PNimrodNode, val: BiggestFloat) {.magic: "NSetFloatVal".}
|
||||
proc `symbol=`*(n: PNimrodNode, val: PNimrodSymbol) {.magic: "NSetSymbol".}
|
||||
proc `ident=`*(n: PNimrodNode, val: TNimrodIdent) {.magic: "NSetIdent".}
|
||||
proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".}
|
||||
#proc `typ=`*(n: PNimrodNode, typ: typedesc) {.magic: "NSetType".}
|
||||
# this is not sound! Unfortunately forbidding 'typ=' is not enough, as you
|
||||
# can easily do:
|
||||
# let bracket = semCheck([1, 2])
|
||||
# let fake = semCheck(2.0)
|
||||
# bracket[0] = fake # constructs a mixed array with ints and floats!
|
||||
|
||||
proc `strVal=`*(n: PNimrodNode, val: string) {.magic: "NSetStrVal".}
|
||||
|
||||
proc newNimNode*(kind: TNimrodNodeKind,
|
||||
|
|
@ -181,12 +188,12 @@ proc newStrLitNode*(s: string): PNimrodNode {.compileTime.} =
|
|||
result = newNimNode(nnkStrLit)
|
||||
result.strVal = s
|
||||
|
||||
proc newIntLitNode*(i: biggestInt): PNimrodNode {.compileTime.} =
|
||||
proc newIntLitNode*(i: BiggestInt): PNimrodNode {.compileTime.} =
|
||||
## creates a int literal node from `i`
|
||||
result = newNimNode(nnkIntLit)
|
||||
result.intVal = i
|
||||
|
||||
proc newFloatLitNode*(f: biggestFloat): PNimrodNode {.compileTime.} =
|
||||
proc newFloatLitNode*(f: BiggestFloat): PNimrodNode {.compileTime.} =
|
||||
## creates a float literal node from `f`
|
||||
result = newNimNode(nnkFloatLit)
|
||||
result.floatVal = f
|
||||
|
|
@ -287,16 +294,18 @@ proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst".}
|
|||
## if not `ex`:
|
||||
## echo `info` & ": Check failed: " & `expString`
|
||||
|
||||
template emit*(e: expr[string]): stmt =
|
||||
## accepts a single string argument and treats it as nimrod code
|
||||
## that should be inserted verbatim in the program
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
##
|
||||
## emit("echo " & '"' & "hello world".toUpper & '"')
|
||||
##
|
||||
eval: result = e.parseStmt
|
||||
when not defined(booting):
|
||||
template emit*(e: static[string]): stmt =
|
||||
## accepts a single string argument and treats it as nimrod code
|
||||
## that should be inserted verbatim in the program
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## emit("echo " & '"' & "hello world".toUpper & '"')
|
||||
##
|
||||
macro payload: stmt {.gensym.} =
|
||||
result = e.parseStmt
|
||||
payload()
|
||||
|
||||
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
|
||||
## checks that `n` is of kind `k`. If this is not the case,
|
||||
|
|
@ -345,12 +354,12 @@ proc newLit*(c: char): PNimrodNode {.compileTime.} =
|
|||
result = newNimNode(nnkCharLit)
|
||||
result.intVal = ord(c)
|
||||
|
||||
proc newLit*(i: biggestInt): PNimrodNode {.compileTime.} =
|
||||
proc newLit*(i: BiggestInt): PNimrodNode {.compileTime.} =
|
||||
## produces a new integer literal node.
|
||||
result = newNimNode(nnkIntLit)
|
||||
result.intVal = i
|
||||
|
||||
proc newLit*(f: biggestFloat): PNimrodNode {.compileTime.} =
|
||||
proc newLit*(f: BiggestFloat): PNimrodNode {.compileTime.} =
|
||||
## produces a new float literal node.
|
||||
result = newNimNode(nnkFloatLit)
|
||||
result.floatVal = f
|
||||
|
|
@ -381,7 +390,7 @@ proc treeRepr*(n: PNimrodNode): string {.compileTime.} =
|
|||
res.add(($n.kind).substr(3))
|
||||
|
||||
case n.kind
|
||||
of nnkEmpty: nil # same as nil node in this representation
|
||||
of nnkEmpty: discard # same as nil node in this representation
|
||||
of nnkNilLit: res.add(" nil")
|
||||
of nnkCharLit..nnkInt64Lit: res.add(" " & $n.intVal)
|
||||
of nnkFloatLit..nnkFloat64Lit: res.add(" " & $n.floatVal)
|
||||
|
|
@ -406,7 +415,7 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
|
|||
add(result, "(")
|
||||
|
||||
case n.kind
|
||||
of nnkEmpty: nil # same as nil node in this representation
|
||||
of nnkEmpty: discard # same as nil node in this representation
|
||||
of nnkNilLit: add(result, "nil")
|
||||
of nnkCharLit..nnkInt64Lit: add(result, $n.intVal)
|
||||
of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal)
|
||||
|
|
@ -529,7 +538,7 @@ from strutils import cmpIgnoreStyle, format
|
|||
proc expectKind*(n: PNimrodNode; k: set[TNimrodNodeKind]) {.compileTime.} =
|
||||
assert n.kind in k, "Expected one of $1, got $2".format(k, n.kind)
|
||||
|
||||
proc newProc*(name = newEmptyNode(); params: openarray[PNimrodNode] = [newEmptyNode()];
|
||||
proc newProc*(name = newEmptyNode(); params: openArray[PNimrodNode] = [newEmptyNode()];
|
||||
body: PNimrodNode = newStmtList(), procType = nnkProcDef): PNimrodNode {.compileTime.} =
|
||||
## shortcut for creating a new proc
|
||||
##
|
||||
|
|
@ -567,7 +576,7 @@ proc copyChildrenTo*(src, dest: PNimrodNode) {.compileTime.}=
|
|||
dest.add src[i].copyNimTree
|
||||
|
||||
template expectRoutine(node: PNimrodNode): stmt =
|
||||
expectKind(node, routineNodes)
|
||||
expectKind(node, RoutineNodes)
|
||||
|
||||
proc name*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
|
||||
someProc.expectRoutine
|
||||
|
|
@ -604,7 +613,7 @@ proc body*(someProc: PNimrodNode): PNimrodNode {.compileTime.} =
|
|||
of routineNodes:
|
||||
return someProc[6]
|
||||
of nnkBlockStmt, nnkWhileStmt:
|
||||
return someproc[1]
|
||||
return someProc[1]
|
||||
of nnkForStmt:
|
||||
return someProc.last
|
||||
else:
|
||||
|
|
@ -628,7 +637,7 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} =
|
|||
of nnkIdent:
|
||||
result = $node.ident
|
||||
of nnkStrLit:
|
||||
result = node.strval
|
||||
result = node.strVal
|
||||
else:
|
||||
badNodeKind node.kind, "$"
|
||||
|
||||
|
|
@ -639,10 +648,13 @@ iterator children*(n: PNimrodNode): PNimrodNode {.inline.}=
|
|||
for i in 0 .. high(n):
|
||||
yield n[i]
|
||||
|
||||
template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {.immediate, dirty.} =
|
||||
## Find the first child node matching condition (or nil)
|
||||
## var res = findChild(n, it.kind == nnkPostfix and it.basename.ident == !"foo")
|
||||
|
||||
template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {.
|
||||
immediate, dirty.} =
|
||||
## Find the first child node matching condition (or nil).
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## var res = findChild(n, it.kind == nnkPostfix and
|
||||
## it.basename.ident == !"foo")
|
||||
block:
|
||||
var result: PNimrodNode
|
||||
for it in n.children:
|
||||
|
|
@ -651,7 +663,7 @@ template findChild*(n: PNimrodNode; cond: expr): PNimrodNode {.immediate, dirty.
|
|||
break
|
||||
result
|
||||
|
||||
proc insert*(a: PNimrodNOde; pos: int; b: PNimrodNode) {.compileTime.} =
|
||||
proc insert*(a: PNimrodNode; pos: int; b: PNimrodNode) {.compileTime.} =
|
||||
## Insert node B into A at pos
|
||||
if high(a) < pos:
|
||||
## add some empty nodes first
|
||||
|
|
@ -672,14 +684,14 @@ proc basename*(a: PNimrodNode): PNimrodNode {.compiletime.} =
|
|||
of nnkIdent: return a
|
||||
of nnkPostfix, nnkPrefix: return a[1]
|
||||
else:
|
||||
quit "Do not know how to get basename of ("& treerepr(a) &")\n"& repr(a)
|
||||
quit "Do not know how to get basename of ("& treeRepr(a) &")\n"& repr(a)
|
||||
|
||||
proc `basename=`*(a: PNimrodNode; val: string) {.compileTime.}=
|
||||
case a.kind
|
||||
of nnkIdent: macros.`ident=`(a, !val)
|
||||
of nnkPostfix, nnkPrefix: a[1] = ident(val)
|
||||
else:
|
||||
quit "Do not know how to get basename of ("& treerepr(a)& ")\n"& repr(a)
|
||||
quit "Do not know how to get basename of ("& treeRepr(a)& ")\n"& repr(a)
|
||||
|
||||
proc postfix*(node: PNimrodNode; op: string): PNimrodNode {.compileTime.} =
|
||||
newNimNode(nnkPostfix).add(ident(op), node)
|
||||
|
|
@ -730,6 +742,6 @@ proc addIdentIfAbsent*(dest: PNimrodNode, ident: string) {.compiletime.} =
|
|||
if ident.eqIdent($node): return
|
||||
of nnkExprColonExpr:
|
||||
if ident.eqIdent($node[0]): return
|
||||
else: nil
|
||||
else: discard
|
||||
dest.add(ident(ident))
|
||||
|
||||
|
|
|
|||
|
|
@ -47,12 +47,12 @@ proc dbError*(db: TDbConn, msg: string) {.noreturn.} =
|
|||
e.msg = $db.err & " " & msg
|
||||
raise e
|
||||
|
||||
proc Close*(db: var TDbConn) {.tags: [FDB].} =
|
||||
proc close*(db: var TDbConn) {.tags: [FDB].} =
|
||||
## closes the database connection.
|
||||
disconnect(db)
|
||||
destroy(db)
|
||||
|
||||
proc Open*(host: string = defaultHost, port: int = defaultPort): TDbConn {.
|
||||
proc open*(host: string = defaultHost, port: int = defaultPort): TDbConn {.
|
||||
tags: [FDB].} =
|
||||
## opens a database connection. Raises `EDb` if the connection could not
|
||||
## be established.
|
||||
|
|
@ -113,7 +113,7 @@ proc getId*(obj: var TBSon): TOid =
|
|||
else:
|
||||
raise newException(EInvalidIndex, "_id not in object")
|
||||
|
||||
proc insertID*(db: var TDbConn, namespace: string, data: PJsonNode): TOid {.
|
||||
proc insertId*(db: var TDbConn, namespace: string, data: PJsonNode): TOid {.
|
||||
tags: [FWriteDb].} =
|
||||
## converts `data` to BSON format and inserts it in `namespace`. Returns
|
||||
## the generated OID for the ``_id`` field.
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
|
|||
else:
|
||||
add(result, c)
|
||||
|
||||
proc TryExec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): bool {.
|
||||
proc tryExec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): bool {.
|
||||
tags: [FReadDB, FWriteDb].} =
|
||||
## tries to execute the query and returns true if successful, false otherwise.
|
||||
var q = dbFormat(query, args)
|
||||
|
|
@ -75,7 +75,7 @@ proc rawExec(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) =
|
|||
var q = dbFormat(query, args)
|
||||
if mysql.RealQuery(db, q, q.len) != 0'i32: dbError(db)
|
||||
|
||||
proc Exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
|
||||
proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
|
||||
tags: [FReadDB, FWriteDb].} =
|
||||
## executes the query and raises EDB if not successful.
|
||||
var q = dbFormat(query, args)
|
||||
|
|
@ -90,7 +90,7 @@ proc properFreeResult(sqlres: mysql.PRES, row: cstringArray) =
|
|||
while mysql.FetchRow(sqlres) != nil: nil
|
||||
mysql.FreeResult(sqlres)
|
||||
|
||||
iterator FastRows*(db: TDbConn, query: TSqlQuery,
|
||||
iterator fastRows*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
|
||||
## executes the query and iterates over the result dataset. This is very
|
||||
## fast, but potenially dangerous: If the for-loop-body executes another
|
||||
|
|
@ -126,7 +126,7 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
|
|||
add(result[i], row[i])
|
||||
properFreeResult(sqlres, row)
|
||||
|
||||
proc GetAllRows*(db: TDbConn, query: TSqlQuery,
|
||||
proc getAllRows*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
|
||||
## executes the query and returns the whole result dataset.
|
||||
result = @[]
|
||||
|
|
@ -145,12 +145,12 @@ proc GetAllRows*(db: TDbConn, query: TSqlQuery,
|
|||
inc(j)
|
||||
mysql.FreeResult(sqlres)
|
||||
|
||||
iterator Rows*(db: TDbConn, query: TSqlQuery,
|
||||
iterator rows*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
|
||||
## same as `FastRows`, but slower and safe.
|
||||
for r in items(GetAllRows(db, query, args)): yield r
|
||||
|
||||
proc GetValue*(db: TDbConn, query: TSqlQuery,
|
||||
proc getValue*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): string {.tags: [FReadDB].} =
|
||||
## executes the query and returns the first column of the first row of the
|
||||
## result dataset. Returns "" if the dataset contains no rows or the database
|
||||
|
|
@ -160,7 +160,7 @@ proc GetValue*(db: TDbConn, query: TSqlQuery,
|
|||
result = row[0]
|
||||
break
|
||||
|
||||
proc TryInsertID*(db: TDbConn, query: TSqlQuery,
|
||||
proc tryInsertId*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
|
||||
## executes the query (typically "INSERT") and returns the
|
||||
## generated ID for the row or -1 in case of an error.
|
||||
|
|
@ -170,14 +170,14 @@ proc TryInsertID*(db: TDbConn, query: TSqlQuery,
|
|||
else:
|
||||
result = mysql.InsertId(db)
|
||||
|
||||
proc InsertID*(db: TDbConn, query: TSqlQuery,
|
||||
proc insertId*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
|
||||
## executes the query (typically "INSERT") and returns the
|
||||
## generated ID for the row.
|
||||
result = TryInsertID(db, query, args)
|
||||
if result < 0: dbError(db)
|
||||
|
||||
proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery,
|
||||
proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.
|
||||
tags: [FReadDB, FWriteDb].} =
|
||||
## runs the query (typically "UPDATE") and returns the
|
||||
|
|
@ -185,11 +185,11 @@ proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery,
|
|||
rawExec(db, query, args)
|
||||
result = mysql.AffectedRows(db)
|
||||
|
||||
proc Close*(db: TDbConn) {.tags: [FDb].} =
|
||||
proc close*(db: TDbConn) {.tags: [FDb].} =
|
||||
## closes the database connection.
|
||||
if db != nil: mysql.Close(db)
|
||||
if db != nil: mysql.close(db)
|
||||
|
||||
proc Open*(connection, user, password, database: string): TDbConn {.
|
||||
proc open*(connection, user, password, database: string): TDbConn {.
|
||||
tags: [FDb].} =
|
||||
## opens a database connection. Raises `EDb` if the connection could not
|
||||
## be established.
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
|
|||
else:
|
||||
add(result, c)
|
||||
|
||||
proc TryExec*(db: TDbConn, query: TSqlQuery,
|
||||
proc tryExec*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} =
|
||||
## tries to execute the query and returns true if successful, false otherwise.
|
||||
var q = dbFormat(query, args)
|
||||
|
|
@ -72,7 +72,7 @@ proc TryExec*(db: TDbConn, query: TSqlQuery,
|
|||
result = PQresultStatus(res) == PGRES_COMMAND_OK
|
||||
PQclear(res)
|
||||
|
||||
proc Exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
|
||||
proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
|
||||
tags: [FReadDB, FWriteDb].} =
|
||||
## executes the query and raises EDB if not successful.
|
||||
var q = dbFormat(query, args)
|
||||
|
|
@ -96,7 +96,7 @@ proc setRow(res: PPGresult, r: var TRow, line, cols: int32) =
|
|||
var x = PQgetvalue(res, line, col)
|
||||
add(r[col], x)
|
||||
|
||||
iterator FastRows*(db: TDbConn, query: TSqlQuery,
|
||||
iterator fastRows*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
|
||||
## executes the query and iterates over the result dataset. This is very
|
||||
## fast, but potenially dangerous: If the for-loop-body executes another
|
||||
|
|
@ -119,19 +119,19 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
|
|||
setRow(res, result, 0, L)
|
||||
PQclear(res)
|
||||
|
||||
proc GetAllRows*(db: TDbConn, query: TSqlQuery,
|
||||
proc getAllRows*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
|
||||
## executes the query and returns the whole result dataset.
|
||||
result = @[]
|
||||
for r in FastRows(db, query, args):
|
||||
result.add(r)
|
||||
|
||||
iterator Rows*(db: TDbConn, query: TSqlQuery,
|
||||
iterator rows*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
|
||||
## same as `FastRows`, but slower and safe.
|
||||
for r in items(GetAllRows(db, query, args)): yield r
|
||||
|
||||
proc GetValue*(db: TDbConn, query: TSqlQuery,
|
||||
proc getValue*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): string {.tags: [FReadDB].} =
|
||||
## executes the query and returns the first column of the first row of the
|
||||
## result dataset. Returns "" if the dataset contains no rows or the database
|
||||
|
|
@ -139,7 +139,7 @@ proc GetValue*(db: TDbConn, query: TSqlQuery,
|
|||
var x = PQgetvalue(setupQuery(db, query, args), 0, 0)
|
||||
result = if isNil(x): "" else: $x
|
||||
|
||||
proc TryInsertID*(db: TDbConn, query: TSqlQuery,
|
||||
proc tryInsertID*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.tags: [FWriteDb].}=
|
||||
## executes the query (typically "INSERT") and returns the
|
||||
## generated ID for the row or -1 in case of an error. For Postgre this adds
|
||||
|
|
@ -152,7 +152,7 @@ proc TryInsertID*(db: TDbConn, query: TSqlQuery,
|
|||
else:
|
||||
result = -1
|
||||
|
||||
proc InsertID*(db: TDbConn, query: TSqlQuery,
|
||||
proc insertID*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
|
||||
## executes the query (typically "INSERT") and returns the
|
||||
## generated ID for the row. For Postgre this adds
|
||||
|
|
@ -161,7 +161,7 @@ proc InsertID*(db: TDbConn, query: TSqlQuery,
|
|||
result = TryInsertID(db, query, args)
|
||||
if result < 0: dbError(db)
|
||||
|
||||
proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery,
|
||||
proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.tags: [
|
||||
FReadDB, FWriteDb].} =
|
||||
## executes the query (typically "UPDATE") and returns the
|
||||
|
|
@ -172,11 +172,11 @@ proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery,
|
|||
result = parseBiggestInt($PQcmdTuples(res))
|
||||
PQclear(res)
|
||||
|
||||
proc Close*(db: TDbConn) {.tags: [FDb].} =
|
||||
proc close*(db: TDbConn) {.tags: [FDb].} =
|
||||
## closes the database connection.
|
||||
if db != nil: PQfinish(db)
|
||||
|
||||
proc Open*(connection, user, password, database: string): TDbConn {.
|
||||
proc open*(connection, user, password, database: string): TDbConn {.
|
||||
tags: [FDb].} =
|
||||
## opens a database connection. Raises `EDb` if the connection could not
|
||||
## be established.
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
|
|||
else:
|
||||
add(result, c)
|
||||
|
||||
proc TryExec*(db: TDbConn, query: TSqlQuery,
|
||||
proc tryExec*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} =
|
||||
## tries to execute the query and returns true if successful, false otherwise.
|
||||
var q = dbFormat(query, args)
|
||||
|
|
@ -73,10 +73,10 @@ proc TryExec*(db: TDbConn, query: TSqlQuery,
|
|||
if step(stmt) == SQLITE_DONE:
|
||||
result = finalize(stmt) == SQLITE_OK
|
||||
|
||||
proc Exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
|
||||
proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
|
||||
tags: [FReadDB, FWriteDb].} =
|
||||
## executes the query and raises EDB if not successful.
|
||||
if not TryExec(db, query, args): dbError(db)
|
||||
if not tryExec(db, query, args): dbError(db)
|
||||
|
||||
proc newRow(L: int): TRow =
|
||||
newSeq(result, L)
|
||||
|
|
@ -94,7 +94,7 @@ proc setRow(stmt: PStmt, r: var TRow, cols: cint) =
|
|||
let x = column_text(stmt, col)
|
||||
if not isNil(x): add(r[col], x)
|
||||
|
||||
iterator FastRows*(db: TDbConn, query: TSqlQuery,
|
||||
iterator fastRows*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
|
||||
## executes the query and iterates over the result dataset. This is very
|
||||
## fast, but potenially dangerous: If the for-loop-body executes another
|
||||
|
|
@ -118,19 +118,19 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
|
|||
setRow(stmt, result, L)
|
||||
if finalize(stmt) != SQLITE_OK: dbError(db)
|
||||
|
||||
proc GetAllRows*(db: TDbConn, query: TSqlQuery,
|
||||
proc getAllRows*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
|
||||
## executes the query and returns the whole result dataset.
|
||||
result = @[]
|
||||
for r in FastRows(db, query, args):
|
||||
for r in fastRows(db, query, args):
|
||||
result.add(r)
|
||||
|
||||
iterator Rows*(db: TDbConn, query: TSqlQuery,
|
||||
iterator rows*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
|
||||
## same as `FastRows`, but slower and safe.
|
||||
for r in FastRows(db, query, args): yield r
|
||||
for r in fastRows(db, query, args): yield r
|
||||
|
||||
proc GetValue*(db: TDbConn, query: TSqlQuery,
|
||||
proc getValue*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): string {.tags: [FReadDB].} =
|
||||
## executes the query and returns the first column of the first row of the
|
||||
## result dataset. Returns "" if the dataset contains no rows or the database
|
||||
|
|
@ -143,44 +143,44 @@ proc GetValue*(db: TDbConn, query: TSqlQuery,
|
|||
else:
|
||||
result = newStringOfCap(cb)
|
||||
add(result, column_text(stmt, 0))
|
||||
if finalize(stmt) != SQLITE_OK: dbError(db)
|
||||
else:
|
||||
result = ""
|
||||
if finalize(stmt) != SQLITE_OK: dbError(db)
|
||||
|
||||
proc TryInsertID*(db: TDbConn, query: TSqlQuery,
|
||||
proc tryInsertID*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
|
||||
## executes the query (typically "INSERT") and returns the
|
||||
## generated ID for the row or -1 in case of an error.
|
||||
var q = dbFormat(query, args)
|
||||
var stmt: sqlite3.PStmt
|
||||
result = -1
|
||||
if prepare_v2(db, q, q.len.cint, stmt, nil) == SQLITE_OK:
|
||||
if step(stmt) == SQLITE_DONE:
|
||||
if finalize(stmt) == SQLITE_OK:
|
||||
return last_insert_rowid(db)
|
||||
result = -1
|
||||
result = last_insert_rowid(db)
|
||||
if finalize(stmt) != SQLITE_OK: dbError(db)
|
||||
|
||||
proc InsertID*(db: TDbConn, query: TSqlQuery,
|
||||
proc insertID*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
|
||||
## executes the query (typically "INSERT") and returns the
|
||||
## generated ID for the row. For Postgre this adds
|
||||
## ``RETURNING id`` to the query, so it only works if your primary key is
|
||||
## named ``id``.
|
||||
result = TryInsertID(db, query, args)
|
||||
result = tryInsertID(db, query, args)
|
||||
if result < 0: dbError(db)
|
||||
|
||||
proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery,
|
||||
proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.
|
||||
tags: [FReadDB, FWriteDb].} =
|
||||
## executes the query (typically "UPDATE") and returns the
|
||||
## number of affected rows.
|
||||
Exec(db, query, args)
|
||||
exec(db, query, args)
|
||||
result = changes(db)
|
||||
|
||||
proc Close*(db: TDbConn) {.tags: [FDB].} =
|
||||
proc close*(db: TDbConn) {.tags: [FDB].} =
|
||||
## closes the database connection.
|
||||
if sqlite3.close(db) != SQLITE_OK: dbError(db)
|
||||
|
||||
proc Open*(connection, user, password, database: string): TDbConn {.
|
||||
proc open*(connection, user, password, database: string): TDbConn {.
|
||||
tags: [FDB].} =
|
||||
## opens a database connection. Raises `EDb` if the connection could not
|
||||
## be established. Only the ``connection`` parameter is used for ``sqlite``.
|
||||
|
|
@ -192,7 +192,7 @@ proc Open*(connection, user, password, database: string): TDbConn {.
|
|||
|
||||
when isMainModule:
|
||||
var db = open("db.sql", "", "", "")
|
||||
Exec(db, sql"create table tbl1(one varchar(10), two smallint)", [])
|
||||
exec(db, sql"create table tbl1(one varchar(10), two smallint)", [])
|
||||
exec(db, sql"insert into tbl1 values('hello!',10)", [])
|
||||
exec(db, sql"insert into tbl1 values('goodbye', 20)", [])
|
||||
#db.query("create table tbl1(one varchar(10), two smallint)")
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ proc error*(window: PWindow, msg: string) =
|
|||
destroy(PWidget(dialog))
|
||||
|
||||
|
||||
proc ChooseFileToOpen*(window: PWindow, root: string = ""): string =
|
||||
proc chooseFileToOpen*(window: PWindow, root: string = ""): string =
|
||||
## Opens a dialog that requests a filename from the user. Returns ""
|
||||
## if the user closed the dialog without selecting a file. On Windows,
|
||||
## the native dialog is used, else the GTK dialog is used.
|
||||
|
|
@ -92,7 +92,7 @@ proc ChooseFileToOpen*(window: PWindow, root: string = ""): string =
|
|||
result = ""
|
||||
destroy(PWidget(chooser))
|
||||
|
||||
proc ChooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] =
|
||||
proc chooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] =
|
||||
## Opens a dialog that requests filenames from the user. Returns ``@[]``
|
||||
## if the user closed the dialog without selecting a file. On Windows,
|
||||
## the native dialog is used, else the GTK dialog is used.
|
||||
|
|
@ -153,7 +153,7 @@ proc ChooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] =
|
|||
destroy(PWidget(chooser))
|
||||
|
||||
|
||||
proc ChooseFileToSave*(window: PWindow, root: string = ""): string =
|
||||
proc chooseFileToSave*(window: PWindow, root: string = ""): string =
|
||||
## Opens a dialog that requests a filename to save to from the user.
|
||||
## Returns "" if the user closed the dialog without selecting a file.
|
||||
## On Windows, the native dialog is used, else the GTK dialog is used.
|
||||
|
|
@ -190,7 +190,7 @@ proc ChooseFileToSave*(window: PWindow, root: string = ""): string =
|
|||
destroy(PWidget(chooser))
|
||||
|
||||
|
||||
proc ChooseDir*(window: PWindow, root: string = ""): string =
|
||||
proc chooseDir*(window: PWindow, root: string = ""): string =
|
||||
## Opens a dialog that requests a directory from the user.
|
||||
## Returns "" if the user closed the dialog without selecting a directory.
|
||||
## On Windows, the native dialog is used, else the GTK dialog is used.
|
||||
|
|
|
|||
|
|
@ -343,7 +343,7 @@ proc fillRect*(sur: PSurface, r: TRect, col: TColor) =
|
|||
if sdl.FillRect(sur.s, addr(rect), sur.createSdlColor(col)) == -1:
|
||||
raiseEGraphics()
|
||||
|
||||
proc Plot4EllipsePoints(sur: PSurface, CX, CY, X, Y: Natural, col: TColor) =
|
||||
proc plot4EllipsePoints(sur: PSurface, CX, CY, X, Y: Natural, col: TColor) =
|
||||
var video = cast[PPixels](sur.s.pixels)
|
||||
var pitch = sur.s.pitch.int div ColSize
|
||||
if CX+X <= sur.s.w-1:
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ const
|
|||
# GetSystemMetrics
|
||||
SM_SERVERR2 = 89
|
||||
|
||||
proc GlobalMemoryStatusEx*(lpBuffer: var TMEMORYSTATUSEX){.stdcall, dynlib: "kernel32",
|
||||
proc globalMemoryStatusEx*(lpBuffer: var TMEMORYSTATUSEX){.stdcall, dynlib: "kernel32",
|
||||
importc: "GlobalMemoryStatusEx".}
|
||||
|
||||
proc getMemoryInfo*(): TMemoryInfo =
|
||||
|
|
@ -159,7 +159,7 @@ proc getMemoryInfo*(): TMemoryInfo =
|
|||
var statex: TMEMORYSTATUSEX
|
||||
statex.dwLength = sizeof(statex).int32
|
||||
|
||||
GlobalMemoryStatusEx(statex)
|
||||
globalMemoryStatusEx(statex)
|
||||
result.MemoryLoad = statex.dwMemoryLoad
|
||||
result.TotalPhysMem = statex.ullTotalPhys
|
||||
result.AvailablePhysMem = statex.ullAvailPhys
|
||||
|
|
@ -168,20 +168,20 @@ proc getMemoryInfo*(): TMemoryInfo =
|
|||
result.TotalVirtualMem = statex.ullTotalVirtual
|
||||
result.AvailableVirtualMem = statex.ullAvailExtendedVirtual
|
||||
|
||||
proc GetVersionEx*(lpVersionInformation: var TOSVERSIONINFOEX): WINBOOL{.stdcall,
|
||||
proc getVersionEx*(lpVersionInformation: var TOSVERSIONINFOEX): WINBOOL{.stdcall,
|
||||
dynlib: "kernel32", importc: "GetVersionExA".}
|
||||
|
||||
proc GetProcAddress*(hModule: int, lpProcName: cstring): pointer{.stdcall,
|
||||
proc getProcAddress*(hModule: int, lpProcName: cstring): pointer{.stdcall,
|
||||
dynlib: "kernel32", importc: "GetProcAddress".}
|
||||
|
||||
proc GetModuleHandleA*(lpModuleName: cstring): int{.stdcall,
|
||||
dynlib: "kernel32", importc.}
|
||||
proc getModuleHandleA*(lpModuleName: cstring): int{.stdcall,
|
||||
dynlib: "kernel32", importc: "GetModuleHandleA".}
|
||||
|
||||
proc getVersionInfo*(): TVersionInfo =
|
||||
## Retrieves operating system info
|
||||
var osvi: TOSVERSIONINFOEX
|
||||
osvi.dwOSVersionInfoSize = sizeof(osvi).int32
|
||||
discard GetVersionEx(osvi)
|
||||
discard getVersionEx(osvi)
|
||||
result.majorVersion = osvi.dwMajorVersion
|
||||
result.minorVersion = osvi.dwMinorVersion
|
||||
result.buildNumber = osvi.dwBuildNumber
|
||||
|
|
@ -197,8 +197,8 @@ proc getProductInfo*(majorVersion, minorVersion, SPMajorVersion,
|
|||
## Retrieves Windows' ProductInfo, this function only works in Vista and 7
|
||||
|
||||
var pGPI = cast[proc (dwOSMajorVersion, dwOSMinorVersion,
|
||||
dwSpMajorVersion, dwSpMinorVersion: int32, outValue: Pint32)](GetProcAddress(
|
||||
GetModuleHandleA("kernel32.dll"), "GetProductInfo"))
|
||||
dwSpMajorVersion, dwSpMinorVersion: int32, outValue: Pint32)](getProcAddress(
|
||||
getModuleHandleA("kernel32.dll"), "GetProductInfo"))
|
||||
|
||||
if pGPI != nil:
|
||||
var dwType: int32
|
||||
|
|
@ -207,25 +207,25 @@ proc getProductInfo*(majorVersion, minorVersion, SPMajorVersion,
|
|||
else:
|
||||
return PRODUCT_UNDEFINED
|
||||
|
||||
proc GetSystemInfo*(lpSystemInfo: LPSYSTEM_INFO){.stdcall, dynlib: "kernel32",
|
||||
proc getSystemInfo*(lpSystemInfo: LPSYSTEM_INFO){.stdcall, dynlib: "kernel32",
|
||||
importc: "GetSystemInfo".}
|
||||
|
||||
proc getSystemInfo*(): TSYSTEM_INFO =
|
||||
## Returns the SystemInfo
|
||||
|
||||
# Use GetNativeSystemInfo if it's available
|
||||
var pGNSI = cast[proc (lpSystemInfo: LPSYSTEM_INFO)](GetProcAddress(
|
||||
GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo"))
|
||||
var pGNSI = cast[proc (lpSystemInfo: LPSYSTEM_INFO)](getProcAddress(
|
||||
getModuleHandleA("kernel32.dll"), "GetNativeSystemInfo"))
|
||||
|
||||
var systemi: TSYSTEM_INFO
|
||||
if pGNSI != nil:
|
||||
pGNSI(addr(systemi))
|
||||
else:
|
||||
GetSystemInfo(addr(systemi))
|
||||
getSystemInfo(addr(systemi))
|
||||
|
||||
return systemi
|
||||
|
||||
proc GetSystemMetrics*(nIndex: int32): int32{.stdcall, dynlib: "user32",
|
||||
proc getSystemMetrics*(nIndex: int32): int32{.stdcall, dynlib: "user32",
|
||||
importc: "GetSystemMetrics".}
|
||||
|
||||
proc `$`*(osvi: TVersionInfo): string =
|
||||
|
|
@ -283,11 +283,11 @@ proc `$`*(osvi: TVersionInfo): string =
|
|||
of PRODUCT_WEB_SERVER:
|
||||
result.add("Web Server Edition")
|
||||
else:
|
||||
nil
|
||||
discard
|
||||
# End of Windows 6.*
|
||||
|
||||
if osvi.majorVersion == 5 and osvi.minorVersion == 2:
|
||||
if GetSystemMetrics(SM_SERVERR2) != 0:
|
||||
if getSystemMetrics(SM_SERVERR2) != 0:
|
||||
result.add("Windows Server 2003 R2, ")
|
||||
elif (osvi.SuiteMask and VER_SUITE_PERSONAL) != 0: # Not sure if this will work
|
||||
result.add("Windows Storage Server 2003")
|
||||
|
|
@ -365,21 +365,21 @@ proc `$`*(osvi: TVersionInfo): string =
|
|||
result = "Unknown version of windows[Kernel version <= 4]"
|
||||
|
||||
|
||||
proc getFileSize*(file: string): biggestInt =
|
||||
proc getFileSize*(file: string): BiggestInt =
|
||||
var fileData: TWIN32_FIND_DATA
|
||||
|
||||
when useWinUnicode:
|
||||
var aa = newWideCString(file)
|
||||
var hFile = FindFirstFileW(aa, fileData)
|
||||
var hFile = findFirstFileW(aa, fileData)
|
||||
else:
|
||||
var hFile = FindFirstFileA(file, fileData)
|
||||
var hFile = findFirstFileA(file, fileData)
|
||||
|
||||
if hFile == INVALID_HANDLE_VALUE:
|
||||
raise newException(EIO, $GetLastError())
|
||||
raise newException(EIO, $getLastError())
|
||||
|
||||
return fileData.nFileSizeLow
|
||||
|
||||
proc GetDiskFreeSpaceEx*(lpDirectoryName: cstring, lpFreeBytesAvailableToCaller,
|
||||
proc getDiskFreeSpaceEx*(lpDirectoryName: cstring, lpFreeBytesAvailableToCaller,
|
||||
lpTotalNumberOfBytes,
|
||||
lpTotalNumberOfFreeBytes: var TFiletime): WINBOOL{.
|
||||
stdcall, dynlib: "kernel32", importc: "GetDiskFreeSpaceExA".}
|
||||
|
|
@ -387,7 +387,7 @@ proc GetDiskFreeSpaceEx*(lpDirectoryName: cstring, lpFreeBytesAvailableToCaller,
|
|||
proc getPartitionInfo*(partition: string): TPartitionInfo =
|
||||
## Retrieves partition info, for example ``partition`` may be ``"C:\"``
|
||||
var FreeBytes, TotalBytes, TotalFreeBytes: TFiletime
|
||||
var res = GetDiskFreeSpaceEx(r"C:\", FreeBytes, TotalBytes,
|
||||
var res = getDiskFreeSpaceEx(r"C:\", FreeBytes, TotalBytes,
|
||||
TotalFreeBytes)
|
||||
return (FreeBytes, TotalBytes)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@
|
|||
## wanted functionality.
|
||||
|
||||
when defined(Windows):
|
||||
proc ReadLineFromStdin*(prompt: string): TaintedString {.
|
||||
proc readLineFromStdin*(prompt: string): TaintedString {.
|
||||
tags: [FReadIO, FWriteIO].} =
|
||||
## Reads a line from stdin.
|
||||
stdout.write(prompt)
|
||||
result = readLine(stdin)
|
||||
|
||||
proc ReadLineFromStdin*(prompt: string, line: var TaintedString): bool {.
|
||||
proc readLineFromStdin*(prompt: string, line: var TaintedString): bool {.
|
||||
tags: [FReadIO, FWriteIO].} =
|
||||
## Reads a `line` from stdin. `line` must not be
|
||||
## ``nil``! May throw an IO exception.
|
||||
|
|
@ -34,7 +34,7 @@ when defined(Windows):
|
|||
else:
|
||||
import readline, history
|
||||
|
||||
proc ReadLineFromStdin*(prompt: string): TaintedString {.
|
||||
proc readLineFromStdin*(prompt: string): TaintedString {.
|
||||
tags: [FReadIO, FWriteIO].} =
|
||||
var buffer = readline.readLine(prompt)
|
||||
if isNil(buffer): quit(0)
|
||||
|
|
@ -43,7 +43,7 @@ else:
|
|||
add_history(buffer)
|
||||
readline.free(buffer)
|
||||
|
||||
proc ReadLineFromStdin*(prompt: string, line: var TaintedString): bool {.
|
||||
proc readLineFromStdin*(prompt: string, line: var TaintedString): bool {.
|
||||
tags: [FReadIO, FWriteIO].} =
|
||||
var buffer = readline.readLine(prompt)
|
||||
if isNil(buffer): quit(0)
|
||||
|
|
@ -56,7 +56,7 @@ else:
|
|||
|
||||
# initialization:
|
||||
# disable auto-complete:
|
||||
proc doNothing(a, b: cint): cint {.cdecl, procvar.} = nil
|
||||
proc doNothing(a, b: cint): cint {.cdecl, procvar.} = discard
|
||||
|
||||
discard readline.bind_key('\t'.ord, doNothing)
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const
|
|||
## More subpatterns cannot be captured!
|
||||
|
||||
type
|
||||
TRegExFlag* = enum ## options for regular expressions
|
||||
TRegexFlag* = enum ## options for regular expressions
|
||||
reIgnoreCase = 0, ## do caseless matching
|
||||
reMultiLine = 1, ## ``^`` and ``$`` match newlines within data
|
||||
reDotAll = 2, ## ``.`` matches anything including NL
|
||||
|
|
@ -36,11 +36,11 @@ type
|
|||
reStudy = 4 ## study the expression (may be omitted if the
|
||||
## expression will be used only once)
|
||||
|
||||
TRegExDesc {.pure, final.} = object
|
||||
TRegexDesc {.pure, final.} = object
|
||||
h: PPcre
|
||||
e: ptr TExtra
|
||||
|
||||
TRegEx* = ref TRegExDesc ## a compiled regular expression
|
||||
TRegex* = ref TRegexDesc ## a compiled regular expression
|
||||
|
||||
EInvalidRegEx* = object of EInvalidValue
|
||||
## is raised if the pattern is no valid regular expression.
|
||||
|
|
@ -53,13 +53,13 @@ proc raiseInvalidRegex(msg: string) {.noinline, noreturn.} =
|
|||
|
||||
proc rawCompile(pattern: string, flags: cint): PPcre =
|
||||
var
|
||||
msg: CString
|
||||
msg: cstring
|
||||
offset: cint
|
||||
result = pcre.Compile(pattern, flags, addr(msg), addr(offset), nil)
|
||||
if result == nil:
|
||||
raiseInvalidRegEx($msg & "\n" & pattern & "\n" & repeatChar(offset) & "^\n")
|
||||
raiseInvalidRegex($msg & "\n" & pattern & "\n" & repeatChar(offset) & "^\n")
|
||||
|
||||
proc finalizeRegEx(x: TRegEx) =
|
||||
proc finalizeRegEx(x: TRegex) =
|
||||
# XXX This is a hack, but PCRE does not export its "free" function properly.
|
||||
# Sigh. The hack relies on PCRE's implementation (see ``pcre_get.c``).
|
||||
# Fortunately the implementation is unlikely to change.
|
||||
|
|
@ -67,7 +67,7 @@ proc finalizeRegEx(x: TRegEx) =
|
|||
if not isNil(x.e):
|
||||
pcre.free_substring(cast[cstring](x.e))
|
||||
|
||||
proc re*(s: string, flags = {reExtended, reStudy}): TRegEx =
|
||||
proc re*(s: string, flags = {reExtended, reStudy}): TRegex =
|
||||
## Constructor of regular expressions. Note that Nimrod's
|
||||
## extended raw string literals support this syntax ``re"[abc]"`` as
|
||||
## a short form for ``re(r"[abc]")``.
|
||||
|
|
@ -78,7 +78,7 @@ proc re*(s: string, flags = {reExtended, reStudy}): TRegEx =
|
|||
result.e = pcre.study(result.h, 0, msg)
|
||||
if not isNil(msg): raiseInvalidRegex($msg)
|
||||
|
||||
proc matchOrFind(s: string, pattern: TRegEx, matches: var openarray[string],
|
||||
proc matchOrFind(s: string, pattern: TRegex, matches: var openArray[string],
|
||||
start, flags: cint): cint =
|
||||
var
|
||||
rawMatches: array[0..maxSubpatterns * 3 - 1, cint]
|
||||
|
|
@ -92,7 +92,7 @@ proc matchOrFind(s: string, pattern: TRegEx, matches: var openarray[string],
|
|||
else: matches[i-1] = ""
|
||||
return rawMatches[1] - rawMatches[0]
|
||||
|
||||
proc findBounds*(s: string, pattern: TRegEx, matches: var openarray[string],
|
||||
proc findBounds*(s: string, pattern: TRegex, matches: var openArray[string],
|
||||
start = 0): tuple[first, last: int] =
|
||||
## returns the starting position and end position of `pattern` in `s`
|
||||
## and the captured
|
||||
|
|
@ -110,8 +110,8 @@ proc findBounds*(s: string, pattern: TRegEx, matches: var openarray[string],
|
|||
else: matches[i-1] = ""
|
||||
return (rawMatches[0].int, rawMatches[1].int - 1)
|
||||
|
||||
proc findBounds*(s: string, pattern: TRegEx,
|
||||
matches: var openarray[tuple[first, last: int]],
|
||||
proc findBounds*(s: string, pattern: TRegex,
|
||||
matches: var openArray[tuple[first, last: int]],
|
||||
start = 0): tuple[first, last: int] =
|
||||
## returns the starting position and end position of ``pattern`` in ``s``
|
||||
## and the captured substrings in the array `matches`.
|
||||
|
|
@ -129,7 +129,7 @@ proc findBounds*(s: string, pattern: TRegEx,
|
|||
else: matches[i-1] = (-1,0)
|
||||
return (rawMatches[0].int, rawMatches[1].int - 1)
|
||||
|
||||
proc findBounds*(s: string, pattern: TRegEx,
|
||||
proc findBounds*(s: string, pattern: TRegex,
|
||||
start = 0): tuple[first, last: int] =
|
||||
## returns the starting position of `pattern` in `s`. If it does not
|
||||
## match, ``(-1,0)`` is returned.
|
||||
|
|
@ -140,14 +140,14 @@ proc findBounds*(s: string, pattern: TRegEx,
|
|||
if res < 0'i32: return (int(res), 0)
|
||||
return (int(rawMatches[0]), int(rawMatches[1]-1))
|
||||
|
||||
proc matchOrFind(s: string, pattern: TRegEx, start, flags: cint): cint =
|
||||
proc matchOrFind(s: string, pattern: TRegex, start, flags: cint): cint =
|
||||
var rawMatches: array [0..maxSubpatterns * 3 - 1, cint]
|
||||
result = pcre.Exec(pattern.h, pattern.e, s, len(s).cint, start, flags,
|
||||
cast[ptr cint](addr(rawMatches)), maxSubpatterns * 3)
|
||||
if result >= 0'i32:
|
||||
result = rawMatches[1] - rawMatches[0]
|
||||
|
||||
proc match*(s: string, pattern: TRegEx, matches: var openarray[string],
|
||||
proc match*(s: string, pattern: TRegex, matches: var openArray[string],
|
||||
start = 0): bool =
|
||||
## returns ``true`` if ``s[start..]`` matches the ``pattern`` and
|
||||
## the captured substrings in the array ``matches``. If it does not
|
||||
|
|
@ -156,24 +156,24 @@ proc match*(s: string, pattern: TRegEx, matches: var openarray[string],
|
|||
return matchOrFind(s, pattern, matches, start.cint,
|
||||
pcre.ANCHORED) == cint(s.len - start)
|
||||
|
||||
proc match*(s: string, pattern: TRegEx, start = 0): bool =
|
||||
proc match*(s: string, pattern: TRegex, start = 0): bool =
|
||||
## returns ``true`` if ``s[start..]`` matches the ``pattern``.
|
||||
return matchOrFind(s, pattern, start.cint, pcre.ANCHORED) == cint(s.len-start)
|
||||
|
||||
proc matchLen*(s: string, pattern: TRegEx, matches: var openarray[string],
|
||||
proc matchLen*(s: string, pattern: TRegex, matches: var openArray[string],
|
||||
start = 0): int =
|
||||
## the same as ``match``, but it returns the length of the match,
|
||||
## if there is no match, -1 is returned. Note that a match length
|
||||
## of zero can happen.
|
||||
return matchOrFind(s, pattern, matches, start.cint, pcre.ANCHORED)
|
||||
|
||||
proc matchLen*(s: string, pattern: TRegEx, start = 0): int =
|
||||
proc matchLen*(s: string, pattern: TRegex, start = 0): int =
|
||||
## the same as ``match``, but it returns the length of the match,
|
||||
## if there is no match, -1 is returned. Note that a match length
|
||||
## of zero can happen.
|
||||
return matchOrFind(s, pattern, start.cint, pcre.ANCHORED)
|
||||
|
||||
proc find*(s: string, pattern: TRegEx, matches: var openarray[string],
|
||||
proc find*(s: string, pattern: TRegex, matches: var openArray[string],
|
||||
start = 0): int =
|
||||
## returns the starting position of ``pattern`` in ``s`` and the captured
|
||||
## substrings in the array ``matches``. If it does not match, nothing
|
||||
|
|
@ -190,7 +190,7 @@ proc find*(s: string, pattern: TRegEx, matches: var openarray[string],
|
|||
else: matches[i-1] = ""
|
||||
return rawMatches[0]
|
||||
|
||||
proc find*(s: string, pattern: TRegEx, start = 0): int =
|
||||
proc find*(s: string, pattern: TRegex, start = 0): int =
|
||||
## returns the starting position of ``pattern`` in ``s``. If it does not
|
||||
## match, -1 is returned.
|
||||
var
|
||||
|
|
@ -200,7 +200,7 @@ proc find*(s: string, pattern: TRegEx, start = 0): int =
|
|||
if res < 0'i32: return res
|
||||
return rawMatches[0]
|
||||
|
||||
iterator findAll*(s: string, pattern: TRegEx, start = 0): string =
|
||||
iterator findAll*(s: string, pattern: TRegex, start = 0): string =
|
||||
## Yields all matching *substrings* of `s` that match `pattern`.
|
||||
##
|
||||
## Note that since this is an iterator you should not modify the string you
|
||||
|
|
@ -216,7 +216,7 @@ iterator findAll*(s: string, pattern: TRegEx, start = 0): string =
|
|||
yield substr(s, int(a), int(b)-1)
|
||||
i = b
|
||||
|
||||
proc findAll*(s: string, pattern: TRegEx, start = 0): seq[string] =
|
||||
proc findAll*(s: string, pattern: TRegex, start = 0): seq[string] =
|
||||
## returns all matching *substrings* of `s` that match `pattern`.
|
||||
## If it does not match, @[] is returned.
|
||||
accumulateResult(findAll(s, pattern, start))
|
||||
|
|
@ -224,7 +224,7 @@ proc findAll*(s: string, pattern: TRegEx, start = 0): seq[string] =
|
|||
when not defined(nimhygiene):
|
||||
{.pragma: inject.}
|
||||
|
||||
template `=~` *(s: string, pattern: TRegEx): expr =
|
||||
template `=~` *(s: string, pattern: TRegex): expr =
|
||||
## This calls ``match`` with an implicit declared ``matches`` array that
|
||||
## can be used in the scope of the ``=~`` call:
|
||||
##
|
||||
|
|
@ -244,30 +244,30 @@ template `=~` *(s: string, pattern: TRegEx): expr =
|
|||
##
|
||||
bind maxSubPatterns
|
||||
when not definedInScope(matches):
|
||||
var matches {.inject.}: array[0..maxSubPatterns-1, string]
|
||||
var matches {.inject.}: array[0..MaxSubpatterns-1, string]
|
||||
match(s, pattern, matches)
|
||||
|
||||
# ------------------------- more string handling ------------------------------
|
||||
|
||||
proc contains*(s: string, pattern: TRegEx, start = 0): bool =
|
||||
proc contains*(s: string, pattern: TRegex, start = 0): bool =
|
||||
## same as ``find(s, pattern, start) >= 0``
|
||||
return find(s, pattern, start) >= 0
|
||||
|
||||
proc contains*(s: string, pattern: TRegEx, matches: var openArray[string],
|
||||
proc contains*(s: string, pattern: TRegex, matches: var openArray[string],
|
||||
start = 0): bool =
|
||||
## same as ``find(s, pattern, matches, start) >= 0``
|
||||
return find(s, pattern, matches, start) >= 0
|
||||
|
||||
proc startsWith*(s: string, prefix: TRegEx): bool =
|
||||
proc startsWith*(s: string, prefix: TRegex): bool =
|
||||
## returns true if `s` starts with the pattern `prefix`
|
||||
result = matchLen(s, prefix) >= 0
|
||||
|
||||
proc endsWith*(s: string, suffix: TRegEx): bool =
|
||||
proc endsWith*(s: string, suffix: TRegex): bool =
|
||||
## returns true if `s` ends with the pattern `prefix`
|
||||
for i in 0 .. s.len-1:
|
||||
if matchLen(s, suffix, i) == s.len - i: return true
|
||||
|
||||
proc replace*(s: string, sub: TRegEx, by = ""): string =
|
||||
proc replace*(s: string, sub: TRegex, by = ""): string =
|
||||
## Replaces `sub` in `s` by the string `by`. Captures cannot be
|
||||
## accessed in `by`. Examples:
|
||||
##
|
||||
|
|
@ -289,7 +289,7 @@ proc replace*(s: string, sub: TRegEx, by = ""): string =
|
|||
prev = match.last + 1
|
||||
add(result, substr(s, prev))
|
||||
|
||||
proc replacef*(s: string, sub: TRegEx, by: string): string =
|
||||
proc replacef*(s: string, sub: TRegex, by: string): string =
|
||||
## Replaces `sub` in `s` by the string `by`. Captures can be accessed in `by`
|
||||
## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples:
|
||||
##
|
||||
|
|
@ -327,7 +327,7 @@ proc replacef*(s: string, sub: TRegEx, by: string): string =
|
|||
add(result, substr(s, i))
|
||||
|
||||
proc parallelReplace*(s: string, subs: openArray[
|
||||
tuple[pattern: TRegEx, repl: string]]): string =
|
||||
tuple[pattern: TRegex, repl: string]]): string =
|
||||
## Returns a modified copy of `s` with the substitutions in `subs`
|
||||
## applied in parallel.
|
||||
result = ""
|
||||
|
|
@ -347,14 +347,14 @@ proc parallelReplace*(s: string, subs: openArray[
|
|||
add(result, substr(s, i))
|
||||
|
||||
proc transformFile*(infile, outfile: string,
|
||||
subs: openArray[tuple[pattern: TRegEx, repl: string]]) =
|
||||
subs: openArray[tuple[pattern: TRegex, repl: string]]) =
|
||||
## reads in the file `infile`, performs a parallel replacement (calls
|
||||
## `parallelReplace`) and writes back to `outfile`. Raises ``EIO`` if an
|
||||
## error occurs. This is supposed to be used for quick scripting.
|
||||
var x = readFile(infile).string
|
||||
writeFile(outfile, x.parallelReplace(subs))
|
||||
|
||||
iterator split*(s: string, sep: TRegEx): string =
|
||||
iterator split*(s: string, sep: TRegex): string =
|
||||
## Splits the string `s` into substrings.
|
||||
##
|
||||
## Substrings are separated by the regular expression `sep`.
|
||||
|
|
@ -386,7 +386,7 @@ iterator split*(s: string, sep: TRegEx): string =
|
|||
if first < last:
|
||||
yield substr(s, first, last-1)
|
||||
|
||||
proc split*(s: string, sep: TRegEx): seq[string] =
|
||||
proc split*(s: string, sep: TRegex): seq[string] =
|
||||
## Splits the string `s` into substrings.
|
||||
accumulateResult(split(s, sep))
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ proc addFile*(z: var TZipArchive, file: string) =
|
|||
addFile(z, file, file)
|
||||
|
||||
proc mySourceCallback(state, data: pointer, len: int,
|
||||
cmd: Tzip_source_cmd): int {.cdecl.} =
|
||||
cmd: TZipSourceCmd): int {.cdecl.} =
|
||||
var src = cast[PStream](state)
|
||||
case cmd
|
||||
of ZIP_SOURCE_OPEN:
|
||||
|
|
@ -108,7 +108,7 @@ proc addFile*(z: var TZipArchive, dest: string, src: PStream) =
|
|||
|
||||
type
|
||||
TZipFileStream = object of TStream
|
||||
f: Pzip_file
|
||||
f: PZipFile
|
||||
|
||||
PZipFileStream* =
|
||||
ref TZipFileStream ## a reader stream of a file within a zip archive
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ const
|
|||
"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",
|
||||
"template", "try", "tuple", "type", "using", "var", "when", "while", "with",
|
||||
"without", "xor", "yield"]
|
||||
|
||||
proc getSourceLanguage*(name: string): TSourceLanguage =
|
||||
|
|
@ -73,7 +73,7 @@ proc initGeneralTokenizer*(g: var TGeneralTokenizer, buf: string) =
|
|||
g.pos = pos
|
||||
|
||||
proc deinitGeneralTokenizer*(g: var TGeneralTokenizer) =
|
||||
nil
|
||||
discard
|
||||
|
||||
proc nimGetKeyword(id: string): TTokenClass =
|
||||
for k in nimrodKeywords:
|
||||
|
|
@ -102,7 +102,7 @@ proc nimNumberPostfix(g: var TGeneralTokenizer, position: int): int =
|
|||
if g.buf[pos] in {'0'..'9'}: inc(pos)
|
||||
if g.buf[pos] in {'0'..'9'}: inc(pos)
|
||||
else:
|
||||
nil
|
||||
discard
|
||||
result = pos
|
||||
|
||||
proc nimNumber(g: var TGeneralTokenizer, position: int): int =
|
||||
|
|
@ -321,7 +321,7 @@ proc generalStrLit(g: var TGeneralTokenizer, position: int): int =
|
|||
inc(pos)
|
||||
result = pos
|
||||
|
||||
proc isKeyword(x: openarray[string], y: string): int =
|
||||
proc isKeyword(x: openArray[string], y: string): int =
|
||||
var a = 0
|
||||
var b = len(x) - 1
|
||||
while a <= b:
|
||||
|
|
@ -335,7 +335,7 @@ proc isKeyword(x: openarray[string], y: string): int =
|
|||
return mid
|
||||
result = - 1
|
||||
|
||||
proc isKeywordIgnoreCase(x: openarray[string], y: string): int =
|
||||
proc isKeywordIgnoreCase(x: openArray[string], y: string): int =
|
||||
var a = 0
|
||||
var b = len(x) - 1
|
||||
while a <= b:
|
||||
|
|
@ -354,7 +354,7 @@ type
|
|||
hasPreprocessor, hasNestedComments
|
||||
TTokenizerFlags = set[TTokenizerFlag]
|
||||
|
||||
proc clikeNextToken(g: var TGeneralTokenizer, keywords: openarray[string],
|
||||
proc clikeNextToken(g: var TGeneralTokenizer, keywords: openArray[string],
|
||||
flags: TTokenizerFlags) =
|
||||
const
|
||||
hexChars = {'0'..'9', 'A'..'F', 'a'..'f'}
|
||||
|
|
@ -428,7 +428,7 @@ proc clikeNextToken(g: var TGeneralTokenizer, keywords: openarray[string],
|
|||
g.kind = gtOperator
|
||||
of 'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF':
|
||||
var id = ""
|
||||
while g.buf[pos] in SymChars:
|
||||
while g.buf[pos] in symChars:
|
||||
add(id, g.buf[pos])
|
||||
inc(pos)
|
||||
if isKeyword(keywords, id) >= 0: g.kind = gtKeyword
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ proc getThing(L: var TLexer, tok: var TToken, s: TCharSet) =
|
|||
tok.line = L.line
|
||||
tok.col = L.col
|
||||
var pos = L.bufpos
|
||||
while True:
|
||||
while true:
|
||||
add(tok.symbol, L.buf[pos])
|
||||
inc(pos)
|
||||
if L.buf[pos] notin s: break
|
||||
|
|
@ -143,7 +143,7 @@ proc getAdornment(L: var TLexer, tok: var TToken) =
|
|||
tok.col = L.col
|
||||
var pos = L.bufpos
|
||||
var c = L.buf[pos]
|
||||
while True:
|
||||
while true:
|
||||
add(tok.symbol, L.buf[pos])
|
||||
inc(pos)
|
||||
if L.buf[pos] != c: break
|
||||
|
|
@ -162,7 +162,7 @@ proc getIndentAux(L: var TLexer, start: int): int =
|
|||
if L.skipPounds:
|
||||
if buf[pos] == '#': inc(pos)
|
||||
if buf[pos] == '#': inc(pos)
|
||||
while True:
|
||||
while true:
|
||||
case buf[pos]
|
||||
of ' ', '\x0B', '\x0C':
|
||||
inc(pos)
|
||||
|
|
@ -242,7 +242,7 @@ proc getTokens(buffer: string, skipPounds: bool, tokens: var TTokenSeq): int =
|
|||
inc(result)
|
||||
while true:
|
||||
inc(length)
|
||||
setlen(tokens, length)
|
||||
setLen(tokens, length)
|
||||
rawGetTok(L, tokens[length - 1])
|
||||
if tokens[length - 1].kind == tkEof: break
|
||||
if tokens[0].kind == tkWhite:
|
||||
|
|
@ -251,7 +251,7 @@ proc getTokens(buffer: string, skipPounds: bool, tokens: var TTokenSeq): int =
|
|||
tokens[0].kind = tkIndent
|
||||
|
||||
type
|
||||
TLevelMap = array[Char, int]
|
||||
TLevelMap = array[char, int]
|
||||
TSubstitution{.final.} = object
|
||||
key*: string
|
||||
value*: PRstNode
|
||||
|
|
@ -294,11 +294,11 @@ proc whichMsgClass*(k: TMsgKind): TMsgClass =
|
|||
|
||||
proc defaultMsgHandler*(filename: string, line, col: int, msgkind: TMsgKind,
|
||||
arg: string) {.procvar.} =
|
||||
let mc = msgKind.whichMsgClass
|
||||
let a = messages[msgKind] % arg
|
||||
let mc = msgkind.whichMsgClass
|
||||
let a = messages[msgkind] % arg
|
||||
let message = "$1($2, $3) $4: $5" % [filename, $line, $col, $mc, a]
|
||||
if mc == mcError: raise newException(EParseError, message)
|
||||
else: Writeln(stdout, message)
|
||||
else: writeln(stdout, message)
|
||||
|
||||
proc defaultFindFile*(filename: string): string {.procvar.} =
|
||||
if existsFile(filename): result = filename
|
||||
|
|
@ -339,7 +339,7 @@ proc pushInd(p: var TRstParser, ind: int) =
|
|||
add(p.indentStack, ind)
|
||||
|
||||
proc popInd(p: var TRstParser) =
|
||||
if len(p.indentStack) > 1: setlen(p.indentStack, len(p.indentStack) - 1)
|
||||
if len(p.indentStack) > 1: setLen(p.indentStack, len(p.indentStack) - 1)
|
||||
|
||||
proc initParser(p: var TRstParser, sharedState: PSharedState) =
|
||||
p.indentStack = @[0]
|
||||
|
|
@ -408,7 +408,7 @@ proc setSub(p: var TRstParser, key: string, value: PRstNode) =
|
|||
if key == p.s.subs[i].key:
|
||||
p.s.subs[i].value = value
|
||||
return
|
||||
setlen(p.s.subs, length + 1)
|
||||
setLen(p.s.subs, length + 1)
|
||||
p.s.subs[length].key = key
|
||||
p.s.subs[length].value = value
|
||||
|
||||
|
|
@ -421,7 +421,7 @@ proc setRef(p: var TRstParser, key: string, value: PRstNode) =
|
|||
|
||||
p.s.refs[i].value = value
|
||||
return
|
||||
setlen(p.s.refs, length + 1)
|
||||
setLen(p.s.refs, length + 1)
|
||||
p.s.refs[length].key = key
|
||||
p.s.refs[length].value = value
|
||||
|
||||
|
|
@ -479,7 +479,7 @@ proc isInlineMarkupEnd(p: TRstParser, markup: string): bool =
|
|||
result = false
|
||||
|
||||
proc isInlineMarkupStart(p: TRstParser, markup: string): bool =
|
||||
var d: Char
|
||||
var d: char
|
||||
result = p.tok[p.idx].symbol == markup
|
||||
if not result:
|
||||
return # Rule 1:
|
||||
|
|
@ -535,7 +535,7 @@ proc match(p: TRstParser, start: int, expr: string): bool =
|
|||
case p.tok[j].symbol[0]
|
||||
of 'a'..'z', 'A'..'Z': result = len(p.tok[j].symbol) == 1
|
||||
of '0'..'9': result = allCharsInSet(p.tok[j].symbol, {'0'..'9'})
|
||||
else: nil
|
||||
else: discard
|
||||
else:
|
||||
var c = expr[i]
|
||||
var length = 0
|
||||
|
|
@ -615,7 +615,7 @@ proc matchVerbatim(p: TRstParser, start: int, expr: string): int =
|
|||
|
||||
proc parseSmiley(p: var TRstParser): PRstNode =
|
||||
if p.tok[p.idx].symbol[0] notin SmileyStartChars: return
|
||||
for key, val in items(smilies):
|
||||
for key, val in items(Smilies):
|
||||
let m = matchVerbatim(p, p.idx, key)
|
||||
if m > 0:
|
||||
p.idx = m
|
||||
|
|
@ -629,18 +629,18 @@ when false:
|
|||
'$', '(', ')', '~', '_', '?', '+', '-', '=', '\\', '.', '&',
|
||||
'\128'..'\255'}
|
||||
|
||||
proc isURL(p: TRstParser, i: int): bool =
|
||||
proc isUrl(p: TRstParser, i: int): bool =
|
||||
result = (p.tok[i+1].symbol == ":") and (p.tok[i+2].symbol == "//") and
|
||||
(p.tok[i+3].kind == tkWord) and
|
||||
(p.tok[i].symbol in ["http", "https", "ftp", "telnet", "file"])
|
||||
|
||||
proc parseURL(p: var TRstParser, father: PRstNode) =
|
||||
proc parseUrl(p: var TRstParser, father: PRstNode) =
|
||||
#if p.tok[p.idx].symbol[strStart] == '<':
|
||||
if isURL(p, p.idx):
|
||||
if isUrl(p, p.idx):
|
||||
var n = newRstNode(rnStandaloneHyperlink)
|
||||
while true:
|
||||
case p.tok[p.idx].kind
|
||||
of tkWord, tkAdornment, tkOther: nil
|
||||
of tkWord, tkAdornment, tkOther: discard
|
||||
of tkPunct:
|
||||
if p.tok[p.idx+1].kind notin {tkWord, tkAdornment, tkOther, tkPunct}:
|
||||
break
|
||||
|
|
@ -806,7 +806,7 @@ proc parseInline(p: var TRstParser, father: PRstNode) =
|
|||
return
|
||||
add(father, newLeaf(p))
|
||||
inc(p.idx)
|
||||
else: nil
|
||||
else: discard
|
||||
|
||||
proc getDirective(p: var TRstParser): string =
|
||||
if p.tok[p.idx].kind == tkWhite and p.tok[p.idx+1].kind == tkWord:
|
||||
|
|
@ -835,14 +835,14 @@ proc parseComment(p: var TRstParser): PRstNode =
|
|||
inc(p.idx) # empty comment
|
||||
else:
|
||||
var indent = p.tok[p.idx].ival
|
||||
while True:
|
||||
while true:
|
||||
case p.tok[p.idx].kind
|
||||
of tkEof:
|
||||
break
|
||||
of tkIndent:
|
||||
if (p.tok[p.idx].ival < indent): break
|
||||
else:
|
||||
nil
|
||||
discard
|
||||
inc(p.idx)
|
||||
else:
|
||||
while p.tok[p.idx].kind notin {tkIndent, tkEof}: inc(p.idx)
|
||||
|
|
@ -864,13 +864,13 @@ proc getDirKind(s: string): TDirKind =
|
|||
else: result = dkNone
|
||||
|
||||
proc parseLine(p: var TRstParser, father: PRstNode) =
|
||||
while True:
|
||||
while true:
|
||||
case p.tok[p.idx].kind
|
||||
of tkWhite, tkWord, tkOther, tkPunct: parseInline(p, father)
|
||||
else: break
|
||||
|
||||
proc parseUntilNewline(p: var TRstParser, father: PRstNode) =
|
||||
while True:
|
||||
while true:
|
||||
case p.tok[p.idx].kind
|
||||
of tkWhite, tkWord, tkAdornment, tkOther, tkPunct: parseInline(p, father)
|
||||
of tkEof, tkIndent: break
|
||||
|
|
@ -879,9 +879,9 @@ proc parseSection(p: var TRstParser, result: PRstNode)
|
|||
proc parseField(p: var TRstParser): PRstNode =
|
||||
result = newRstNode(rnField)
|
||||
var col = p.tok[p.idx].col
|
||||
var fieldname = newRstNode(rnFieldname)
|
||||
var fieldname = newRstNode(rnFieldName)
|
||||
parseUntil(p, fieldname, ":", false)
|
||||
var fieldbody = newRstNode(rnFieldbody)
|
||||
var fieldbody = newRstNode(rnFieldBody)
|
||||
if p.tok[p.idx].kind != tkIndent: parseLine(p, fieldbody)
|
||||
if p.tok[p.idx].kind == tkIndent:
|
||||
var indent = p.tok[p.idx].ival
|
||||
|
|
@ -933,7 +933,7 @@ proc parseLiteralBlock(p: var TRstParser): PRstNode =
|
|||
if p.tok[p.idx].kind == tkIndent:
|
||||
var indent = p.tok[p.idx].ival
|
||||
inc(p.idx)
|
||||
while True:
|
||||
while true:
|
||||
case p.tok[p.idx].kind
|
||||
of tkEof:
|
||||
break
|
||||
|
|
@ -953,7 +953,7 @@ proc parseLiteralBlock(p: var TRstParser): PRstNode =
|
|||
inc(p.idx)
|
||||
add(result, n)
|
||||
|
||||
proc getLevel(map: var TLevelMap, lvl: var int, c: Char): int =
|
||||
proc getLevel(map: var TLevelMap, lvl: var int, c: char): int =
|
||||
if map[c] == 0:
|
||||
inc(lvl)
|
||||
map[c] = lvl
|
||||
|
|
@ -999,7 +999,7 @@ proc whichSection(p: TRstParser): TRstNodeKind =
|
|||
elif match(p, p.idx + 1, "i"): result = rnOverline
|
||||
else: result = rnLeaf
|
||||
of tkPunct:
|
||||
if match(p, tokenAfterNewLine(p), "ai"):
|
||||
if match(p, tokenAfterNewline(p), "ai"):
|
||||
result = rnHeadline
|
||||
elif p.tok[p.idx].symbol == "::":
|
||||
result = rnLiteralBlock
|
||||
|
|
@ -1026,7 +1026,7 @@ proc whichSection(p: TRstParser): TRstNodeKind =
|
|||
else:
|
||||
result = rnParagraph
|
||||
of tkWord, tkOther, tkWhite:
|
||||
if match(p, tokenAfterNewLine(p), "ai"): result = rnHeadline
|
||||
if match(p, tokenAfterNewline(p), "ai"): result = rnHeadline
|
||||
elif match(p, p.idx, "e) ") or match(p, p.idx, "e. "): result = rnEnumList
|
||||
elif isDefList(p): result = rnDefList
|
||||
else: result = rnParagraph
|
||||
|
|
@ -1052,7 +1052,7 @@ proc parseLineBlock(p: var TRstParser): PRstNode =
|
|||
popInd(p)
|
||||
|
||||
proc parseParagraph(p: var TRstParser, result: PRstNode) =
|
||||
while True:
|
||||
while true:
|
||||
case p.tok[p.idx].kind
|
||||
of tkIndent:
|
||||
if p.tok[p.idx + 1].kind == tkIndent:
|
||||
|
|
@ -1084,7 +1084,7 @@ proc parseParagraph(p: var TRstParser, result: PRstNode) =
|
|||
|
||||
proc parseHeadline(p: var TRstParser): PRstNode =
|
||||
result = newRstNode(rnHeadline)
|
||||
parseUntilNewLine(p, result)
|
||||
parseUntilNewline(p, result)
|
||||
assert(p.tok[p.idx].kind == tkIndent)
|
||||
assert(p.tok[p.idx + 1].kind == tkAdornment)
|
||||
var c = p.tok[p.idx + 1].symbol[0]
|
||||
|
|
@ -1101,7 +1101,7 @@ proc getColumns(p: var TRstParser, cols: var TIntSeq) =
|
|||
var L = 0
|
||||
while true:
|
||||
inc(L)
|
||||
setlen(cols, L)
|
||||
setLen(cols, L)
|
||||
cols[L - 1] = tokEnd(p)
|
||||
assert(p.tok[p.idx].kind == tkAdornment)
|
||||
inc(p.idx)
|
||||
|
|
@ -1119,7 +1119,7 @@ proc parseSimpleTable(p: var TRstParser): PRstNode =
|
|||
cols: TIntSeq
|
||||
row: seq[string]
|
||||
i, last, line: int
|
||||
c: Char
|
||||
c: char
|
||||
q: TRstParser
|
||||
a, b: PRstNode
|
||||
result = newRstNode(rnTable)
|
||||
|
|
@ -1135,7 +1135,7 @@ proc parseSimpleTable(p: var TRstParser): PRstNode =
|
|||
p.idx = last
|
||||
break
|
||||
getColumns(p, cols)
|
||||
setlen(row, len(cols))
|
||||
setLen(row, len(cols))
|
||||
if a != nil:
|
||||
for j in 0..len(a)-1: a.sons[j].kind = rnTableHeaderCell
|
||||
if p.tok[p.idx].kind == tkEof: break
|
||||
|
|
@ -1243,7 +1243,7 @@ proc parseOptionList(p: var TRstParser): PRstNode =
|
|||
|
||||
proc parseDefinitionList(p: var TRstParser): PRstNode =
|
||||
result = nil
|
||||
var j = tokenAfterNewLine(p) - 1
|
||||
var j = tokenAfterNewline(p) - 1
|
||||
if (j >= 1) and (p.tok[j].kind == tkIndent) and
|
||||
(p.tok[j].ival > currInd(p)) and (p.tok[j - 1].symbol != "::"):
|
||||
var col = p.tok[p.idx].col
|
||||
|
|
@ -1269,10 +1269,10 @@ proc parseDefinitionList(p: var TRstParser): PRstNode =
|
|||
break
|
||||
if (p.tok[p.idx].kind == tkIndent) and (p.tok[p.idx].ival == col):
|
||||
inc(p.idx)
|
||||
j = tokenAfterNewLine(p) - 1
|
||||
j = tokenAfterNewline(p) - 1
|
||||
if j >= 1 and p.tok[j].kind == tkIndent and p.tok[j].ival > col and
|
||||
p.tok[j-1].symbol != "::" and p.tok[j+1].kind != tkIndent:
|
||||
nil
|
||||
discard
|
||||
else:
|
||||
break
|
||||
if len(result) == 0: result = nil
|
||||
|
|
@ -1290,7 +1290,7 @@ proc parseEnumList(p: var TRstParser): PRstNode =
|
|||
var col = p.tok[p.idx].col
|
||||
result = newRstNode(rnEnumList)
|
||||
inc(p.idx, wildpos[w] + 3)
|
||||
var j = tokenAfterNewLine(p)
|
||||
var j = tokenAfterNewline(p)
|
||||
if (p.tok[j].col == p.tok[p.idx].col) or match(p, j, wildcards[w]):
|
||||
pushInd(p, p.tok[p.idx].col)
|
||||
while true:
|
||||
|
|
@ -1335,11 +1335,11 @@ proc parseSection(p: var TRstParser, result: PRstNode) =
|
|||
inc(p.idx) # skip '::'
|
||||
a = parseLiteralBlock(p)
|
||||
of rnBulletList: a = parseBulletList(p)
|
||||
of rnLineblock: a = parseLineBlock(p)
|
||||
of rnLineBlock: a = parseLineBlock(p)
|
||||
of rnDirective: a = parseDotDot(p)
|
||||
of rnEnumList: a = parseEnumList(p)
|
||||
of rnLeaf: rstMessage(p, meNewSectionExpected)
|
||||
of rnParagraph: nil
|
||||
of rnParagraph: discard
|
||||
of rnDefList: a = parseDefinitionList(p)
|
||||
of rnFieldList:
|
||||
if p.idx > 0: dec(p.idx)
|
||||
|
|
@ -1351,7 +1351,7 @@ proc parseSection(p: var TRstParser, result: PRstNode) =
|
|||
of rnOptionList: a = parseOptionList(p)
|
||||
else:
|
||||
#InternalError("rst.parseSection()")
|
||||
nil
|
||||
discard
|
||||
if a == nil and k != rnDirective:
|
||||
a = newRstNode(rnParagraph)
|
||||
parseParagraph(p, a)
|
||||
|
|
@ -1394,7 +1394,7 @@ proc parseDirective(p: var TRstParser, flags: TDirFlags): PRstNode =
|
|||
if hasArg in flags:
|
||||
args = newRstNode(rnDirArg)
|
||||
if argIsFile in flags:
|
||||
while True:
|
||||
while true:
|
||||
case p.tok[p.idx].kind
|
||||
of tkWord, tkOther, tkPunct, tkAdornment:
|
||||
add(args, newLeaf(p))
|
||||
|
|
@ -1566,7 +1566,7 @@ proc parseDotDot(p: var TRstParser): PRstNode =
|
|||
result = dirRaw(p)
|
||||
else:
|
||||
rstMessage(p, meInvalidDirective, d)
|
||||
of dkCodeblock: result = dirCodeBlock(p)
|
||||
of dkCodeBlock: result = dirCodeBlock(p)
|
||||
of dkIndex: result = dirIndex(p)
|
||||
else: rstMessage(p, meInvalidDirective, d)
|
||||
popInd(p)
|
||||
|
|
@ -1624,7 +1624,7 @@ proc resolveSubs(p: var TRstParser, n: PRstNode): PRstNode =
|
|||
add(result, n)
|
||||
add(result, y)
|
||||
of rnLeaf:
|
||||
nil
|
||||
discard
|
||||
of rnContents:
|
||||
p.hasToc = true
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -62,9 +62,9 @@ type
|
|||
# leaf val
|
||||
|
||||
|
||||
PRSTNode* = ref TRstNode ## an RST node
|
||||
PRstNode* = ref TRstNode ## an RST node
|
||||
TRstNodeSeq* = seq[PRstNode]
|
||||
TRSTNode* {.acyclic, final.} = object ## an RST node's description
|
||||
TRstNode* {.acyclic, final.} = object ## an RST node's description
|
||||
kind*: TRstNodeKind ## the node's kind
|
||||
text*: string ## valid for leafs in the AST; and the title of
|
||||
## the document or the section
|
||||
|
|
@ -120,11 +120,11 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
|||
|
||||
let oldLen = result.len
|
||||
renderRstSons(d, n, result)
|
||||
let HeadlineLen = result.len - oldLen
|
||||
let headlineLen = result.len - oldLen
|
||||
|
||||
result.add("\n")
|
||||
result.add(ind)
|
||||
result.add repeatChar(HeadlineLen, lvlToChar[n.level])
|
||||
result.add repeatChar(headlineLen, lvlToChar[n.level])
|
||||
of rnOverline:
|
||||
result.add("\n")
|
||||
result.add(ind)
|
||||
|
|
@ -132,7 +132,7 @@ proc renderRstToRst(d: var TRenderContext, n: PRstNode, result: var string) =
|
|||
var headline = ""
|
||||
renderRstSons(d, n, headline)
|
||||
|
||||
let lvl = repeatChar(headline.Len - d.indent, lvlToChar[n.level])
|
||||
let lvl = repeatChar(headline.len - d.indent, lvlToChar[n.level])
|
||||
result.add(lvl)
|
||||
result.add("\n")
|
||||
result.add(headline)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ type
|
|||
splitAfter*: int # split too long entries in the TOC
|
||||
tocPart*: seq[TTocEntry]
|
||||
hasToc*: bool
|
||||
theIndex: string
|
||||
theIndex: string # Contents of the index file to be dumped at the end.
|
||||
options*: TRstParseOptions
|
||||
findFile*: TFindFileHandler
|
||||
msgHandler*: TMsgHandler
|
||||
|
|
@ -111,9 +111,13 @@ proc initRstGenerator*(g: var TRstGenerator, target: TOutputTarget,
|
|||
for i in low(g.meta)..high(g.meta): g.meta[i] = ""
|
||||
|
||||
proc writeIndexFile*(g: var TRstGenerator, outfile: string) =
|
||||
## Writes the current index buffer to the specified output file.
|
||||
##
|
||||
## You previously need to add entries to the index with the ``setIndexTerm``
|
||||
## proc. If the index is empty the file won't be created.
|
||||
if g.theIndex.len > 0: writeFile(outfile, g.theIndex)
|
||||
|
||||
proc addXmlChar(dest: var string, c: Char) =
|
||||
proc addXmlChar(dest: var string, c: char) =
|
||||
case c
|
||||
of '&': add(dest, "&")
|
||||
of '<': add(dest, "<")
|
||||
|
|
@ -121,14 +125,14 @@ proc addXmlChar(dest: var string, c: Char) =
|
|||
of '\"': add(dest, """)
|
||||
else: add(dest, c)
|
||||
|
||||
proc addRtfChar(dest: var string, c: Char) =
|
||||
proc addRtfChar(dest: var string, c: char) =
|
||||
case c
|
||||
of '{': add(dest, "\\{")
|
||||
of '}': add(dest, "\\}")
|
||||
of '\\': add(dest, "\\\\")
|
||||
else: add(dest, c)
|
||||
|
||||
proc addTexChar(dest: var string, c: Char) =
|
||||
proc addTexChar(dest: var string, c: char) =
|
||||
case c
|
||||
of '_': add(dest, "\\_")
|
||||
of '{': add(dest, "\\symbol{123}")
|
||||
|
|
@ -148,7 +152,7 @@ proc addTexChar(dest: var string, c: Char) =
|
|||
|
||||
var splitter*: string = "<wbr />"
|
||||
|
||||
proc escChar*(target: TOutputTarget, dest: var string, c: Char) {.inline.} =
|
||||
proc escChar*(target: TOutputTarget, dest: var string, c: char) {.inline.} =
|
||||
case target
|
||||
of outHtml: addXmlChar(dest, c)
|
||||
of outLatex: addTexChar(dest, c)
|
||||
|
|
@ -161,7 +165,7 @@ proc nextSplitPoint*(s: string, start: int): int =
|
|||
of 'a'..'z':
|
||||
if result + 1 < len(s) + 0:
|
||||
if s[result + 1] in {'A'..'Z'}: return
|
||||
else: nil
|
||||
else: discard
|
||||
inc(result)
|
||||
dec(result) # last valid index
|
||||
|
||||
|
|
@ -224,6 +228,13 @@ proc renderAux(d: PDoc, n: PRstNode, frmtA, frmtB: string, result: var string) =
|
|||
# ---------------- index handling --------------------------------------------
|
||||
|
||||
proc setIndexTerm*(d: var TRstGenerator, id, term: string) =
|
||||
## Adds a `term` to the index using the specified hyperlink identifier.
|
||||
##
|
||||
## The ``d.theIndex`` string will be used to append the term in the format
|
||||
## ``term<tab>file#id``. The anchor will be the based on the name of the file
|
||||
## currently being parsed plus the `id`, which will be appended after a hash.
|
||||
##
|
||||
## The index won't be written to disk unless you call ``writeIndexFile``.
|
||||
d.theIndex.add(term)
|
||||
d.theIndex.add('\t')
|
||||
let htmlFile = changeFileExt(extractFilename(d.filename), HtmlExt)
|
||||
|
|
@ -263,14 +274,14 @@ proc `<-`(a: var TIndexEntry, b: TIndexEntry) =
|
|||
|
||||
proc sortIndex(a: var openArray[TIndexEntry]) =
|
||||
# we use shellsort here; fast and simple
|
||||
let N = len(a)
|
||||
let n = len(a)
|
||||
var h = 1
|
||||
while true:
|
||||
h = 3 * h + 1
|
||||
if h > N: break
|
||||
if h > n: break
|
||||
while true:
|
||||
h = h div 3
|
||||
for i in countup(h, N - 1):
|
||||
for i in countup(h, n - 1):
|
||||
var v: TIndexEntry
|
||||
v <- a[i]
|
||||
var j = i
|
||||
|
|
@ -320,7 +331,7 @@ proc renderHeadline(d: PDoc, n: PRstNode, result: var string) =
|
|||
var refname = rstnodeToRefname(n)
|
||||
if d.hasToc:
|
||||
var length = len(d.tocPart)
|
||||
setlen(d.tocPart, length + 1)
|
||||
setLen(d.tocPart, length + 1)
|
||||
d.tocPart[length].refname = refname
|
||||
d.tocPart[length].n = n
|
||||
d.tocPart[length].header = tmp
|
||||
|
|
@ -456,7 +467,7 @@ proc renderField(d: PDoc, n: PRstNode, result: var string) =
|
|||
if d.meta[metaAuthor].len == 0:
|
||||
d.meta[metaAuthor] = fieldval
|
||||
b = true
|
||||
elif cmpIgnoreStyle(fieldName, "version") == 0:
|
||||
elif cmpIgnoreStyle(fieldname, "version") == 0:
|
||||
if d.meta[metaVersion].len == 0:
|
||||
d.meta[metaVersion] = fieldval
|
||||
b = true
|
||||
|
|
@ -620,14 +631,14 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
|
|||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
proc getVarIdx(varnames: openarray[string], id: string): int =
|
||||
proc getVarIdx(varnames: openArray[string], id: string): int =
|
||||
for i in countup(0, high(varnames)):
|
||||
if cmpIgnoreStyle(varnames[i], id) == 0:
|
||||
return i
|
||||
result = -1
|
||||
|
||||
proc formatNamedVars*(frmt: string, varnames: openarray[string],
|
||||
varvalues: openarray[string]): string =
|
||||
proc formatNamedVars*(frmt: string, varnames: openArray[string],
|
||||
varvalues: openArray[string]): string =
|
||||
var i = 0
|
||||
var L = len(frmt)
|
||||
result = ""
|
||||
|
|
@ -646,7 +657,7 @@ proc formatNamedVars*(frmt: string, varnames: openarray[string],
|
|||
of '0'..'9':
|
||||
var j = 0
|
||||
while true:
|
||||
j = (j * 10) + Ord(frmt[i]) - ord('0')
|
||||
j = (j * 10) + ord(frmt[i]) - ord('0')
|
||||
inc(i)
|
||||
if i > L-1 or frmt[i] notin {'0'..'9'}: break
|
||||
if j > high(varvalues) + 1:
|
||||
|
|
@ -688,7 +699,18 @@ proc formatNamedVars*(frmt: string, varnames: openarray[string],
|
|||
|
||||
|
||||
proc defaultConfig*(): PStringTable =
|
||||
## creates a default configuration for HTML generation.
|
||||
## Returns a default configuration for embedded HTML generation.
|
||||
##
|
||||
## The returned ``PStringTable`` contains the paramters used by the HTML
|
||||
## engine to build the final output. For information on what these parameters
|
||||
## are and their purpose, please look up the file ``config/nimdoc.cfg``
|
||||
## bundled with the compiler.
|
||||
##
|
||||
## The only difference between the contents of that file and the values
|
||||
## provided by this proc is the ``doc.file`` variable. The ``doc.file``
|
||||
## variable of the configuration file contains HTML to build standalone
|
||||
## pages, while this proc returns just the content for procs like
|
||||
## ``rstToHtml`` to generate the bare minimum HTML.
|
||||
result = newStringTable(modeStyleInsensitive)
|
||||
|
||||
template setConfigVar(key, val: expr) =
|
||||
|
|
|
|||
|
|
@ -85,15 +85,15 @@ type
|
|||
|
||||
Tdirent* {.importc: "struct dirent",
|
||||
header: "<dirent.h>", final, pure.} = object ## dirent_t struct
|
||||
d_ino*: TIno ## File serial number.
|
||||
d_ino*: Tino ## File serial number.
|
||||
d_name*: array [0..255, char] ## Name of entry.
|
||||
|
||||
Tflock* {.importc: "flock", final, pure,
|
||||
header: "<fcntl.h>".} = object ## flock type
|
||||
l_type*: cshort ## Type of lock; F_RDLCK, F_WRLCK, F_UNLCK.
|
||||
l_whence*: cshort ## Flag for starting offset.
|
||||
l_start*: Toff ## Relative offset in bytes.
|
||||
l_len*: Toff ## Size; if 0 then until EOF.
|
||||
l_start*: TOff ## Relative offset in bytes.
|
||||
l_len*: TOff ## Size; if 0 then until EOF.
|
||||
l_pid*: TPid ## Process ID of the process holding the lock;
|
||||
## returned with F_GETLK.
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ type
|
|||
TPasswd* {.importc: "struct passwd", header: "<pwd.h>",
|
||||
final, pure.} = object ## struct passwd
|
||||
pw_name*: cstring ## User's login name.
|
||||
pw_uid*: TUid ## Numerical user ID.
|
||||
pw_uid*: Tuid ## Numerical user ID.
|
||||
pw_gid*: TGid ## Numerical group ID.
|
||||
pw_dir*: cstring ## Initial working directory.
|
||||
pw_shell*: cstring ## Program to use as shell.
|
||||
|
|
@ -240,20 +240,20 @@ type
|
|||
TSem* {.importc: "sem_t", header: "<semaphore.h>", final, pure.} = object
|
||||
Tipc_perm* {.importc: "struct ipc_perm",
|
||||
header: "<sys/ipc.h>", final, pure.} = object ## struct ipc_perm
|
||||
uid*: tuid ## Owner's user ID.
|
||||
gid*: tgid ## Owner's group ID.
|
||||
uid*: Tuid ## Owner's user ID.
|
||||
gid*: TGid ## Owner's group ID.
|
||||
cuid*: Tuid ## Creator's user ID.
|
||||
cgid*: Tgid ## Creator's group ID.
|
||||
cgid*: TGid ## Creator's group ID.
|
||||
mode*: TMode ## Read/write permission.
|
||||
|
||||
TStat* {.importc: "struct stat",
|
||||
header: "<sys/stat.h>", final, pure.} = object ## struct stat
|
||||
st_dev*: TDev ## Device ID of device containing file.
|
||||
st_ino*: TIno ## File serial number.
|
||||
st_ino*: Tino ## File serial number.
|
||||
st_mode*: TMode ## Mode of file (see below).
|
||||
st_nlink*: tnlink ## Number of hard links to the file.
|
||||
st_uid*: tuid ## User ID of file.
|
||||
st_gid*: Tgid ## Group ID of file.
|
||||
st_nlink*: TNlink ## Number of hard links to the file.
|
||||
st_uid*: Tuid ## User ID of file.
|
||||
st_gid*: TGid ## Group ID of file.
|
||||
st_rdev*: TDev ## Device ID (if file is character or block special).
|
||||
st_size*: TOff ## For regular files, the file size in bytes.
|
||||
## For symbolic links, the length in bytes of the
|
||||
|
|
@ -262,9 +262,9 @@ type
|
|||
## For a typed memory object, the length in bytes.
|
||||
## For other file types, the use of this field is
|
||||
## unspecified.
|
||||
st_atime*: ttime ## Time of last access.
|
||||
st_mtime*: ttime ## Time of last data modification.
|
||||
st_ctime*: ttime ## Time of last status change.
|
||||
st_atime*: TTime ## Time of last access.
|
||||
st_mtime*: TTime ## Time of last data modification.
|
||||
st_ctime*: TTime ## Time of last status change.
|
||||
st_blksize*: Tblksize ## A file system-specific preferred I/O block size
|
||||
## for this object. In some file system types, this
|
||||
## may vary from file to file.
|
||||
|
|
@ -305,12 +305,12 @@ type
|
|||
tm_isdst*: cint ## Daylight Savings flag.
|
||||
Ttimespec* {.importc: "struct timespec",
|
||||
header: "<time.h>", final, pure.} = object ## struct timespec
|
||||
tv_sec*: Ttime ## Seconds.
|
||||
tv_sec*: TTime ## Seconds.
|
||||
tv_nsec*: int ## Nanoseconds.
|
||||
titimerspec* {.importc: "struct itimerspec", header: "<time.h>",
|
||||
final, pure.} = object ## struct itimerspec
|
||||
it_interval*: ttimespec ## Timer period.
|
||||
it_value*: ttimespec ## Timer expiration.
|
||||
it_interval*: Ttimespec ## Timer period.
|
||||
it_value*: Ttimespec ## Timer expiration.
|
||||
|
||||
Tsig_atomic* {.importc: "sig_atomic_t", header: "<signal.h>".} = cint
|
||||
## Possibly volatile-qualified integer type of an object that can be
|
||||
|
|
@ -322,9 +322,9 @@ type
|
|||
header: "<signal.h>", final, pure.} = object ## struct sigevent
|
||||
sigev_notify*: cint ## Notification type.
|
||||
sigev_signo*: cint ## Signal number.
|
||||
sigev_value*: Tsigval ## Signal value.
|
||||
sigev_notify_function*: proc (x: TSigval) {.noconv.} ## Notification func.
|
||||
sigev_notify_attributes*: ptr Tpthreadattr ## Notification attributes.
|
||||
sigev_value*: TsigVal ## Signal value.
|
||||
sigev_notify_function*: proc (x: TsigVal) {.noconv.} ## Notification func.
|
||||
sigev_notify_attributes*: ptr Tpthread_attr ## Notification attributes.
|
||||
|
||||
TsigVal* {.importc: "union sigval",
|
||||
header: "<signal.h>", final, pure.} = object ## struct sigval
|
||||
|
|
@ -335,10 +335,10 @@ type
|
|||
sa_handler*: proc (x: cint) {.noconv.} ## Pointer to a signal-catching
|
||||
## function or one of the macros
|
||||
## SIG_IGN or SIG_DFL.
|
||||
sa_mask*: TsigSet ## Set of signals to be blocked during execution of
|
||||
sa_mask*: Tsigset ## Set of signals to be blocked during execution of
|
||||
## the signal handling function.
|
||||
sa_flags*: cint ## Special flags.
|
||||
sa_sigaction*: proc (x: cint, y: var TSigInfo, z: pointer) {.noconv.}
|
||||
sa_sigaction*: proc (x: cint, y: var TsigInfo, z: pointer) {.noconv.}
|
||||
|
||||
TStack* {.importc: "stack_t",
|
||||
header: "<signal.h>", final, pure.} = object ## stack_t
|
||||
|
|
@ -357,12 +357,12 @@ type
|
|||
si_code*: cint ## Signal code.
|
||||
si_errno*: cint ## If non-zero, an errno value associated with
|
||||
## this signal, as defined in <errno.h>.
|
||||
si_pid*: tpid ## Sending process ID.
|
||||
si_uid*: tuid ## Real user ID of sending process.
|
||||
si_pid*: TPid ## Sending process ID.
|
||||
si_uid*: Tuid ## Real user ID of sending process.
|
||||
si_addr*: pointer ## Address of faulting instruction.
|
||||
si_status*: cint ## Exit value or signal.
|
||||
si_band*: int ## Band event for SIGPOLL.
|
||||
si_value*: TSigval ## Signal value.
|
||||
si_value*: TsigVal ## Signal value.
|
||||
|
||||
Tnl_item* {.importc: "nl_item", header: "<nl_types.h>".} = cint
|
||||
Tnl_catd* {.importc: "nl_catd", header: "<nl_types.h>".} = cint
|
||||
|
|
@ -373,9 +373,9 @@ type
|
|||
sched_priority*: cint
|
||||
sched_ss_low_priority*: cint ## Low scheduling priority for
|
||||
## sporadic server.
|
||||
sched_ss_repl_period*: ttimespec ## Replenishment period for
|
||||
sched_ss_repl_period*: Ttimespec ## Replenishment period for
|
||||
## sporadic server.
|
||||
sched_ss_init_budget*: ttimespec ## Initial budget for sporadic server.
|
||||
sched_ss_init_budget*: Ttimespec ## Initial budget for sporadic server.
|
||||
sched_ss_max_repl*: cint ## Maximum pending replenishments for
|
||||
## sporadic server.
|
||||
|
||||
|
|
@ -383,8 +383,8 @@ type
|
|||
final, pure.} = object ## struct timeval
|
||||
tv_sec*: int ## Seconds.
|
||||
tv_usec*: int ## Microseconds.
|
||||
Tfd_set* {.importc: "fd_set", header: "<sys/select.h>",
|
||||
final, pure.} = object
|
||||
TFdSet* {.importc: "fd_set", header: "<sys/select.h>",
|
||||
final, pure.} = object
|
||||
Tmcontext* {.importc: "mcontext_t", header: "<ucontext.h>",
|
||||
final, pure.} = object
|
||||
Tucontext* {.importc: "ucontext_t", header: "<ucontext.h>",
|
||||
|
|
@ -406,7 +406,7 @@ when hasAioH:
|
|||
aio_buf*: pointer ## Location of buffer.
|
||||
aio_nbytes*: int ## Length of transfer.
|
||||
aio_reqprio*: cint ## Request priority offset.
|
||||
aio_sigevent*: TSigEvent ## Signal number and value.
|
||||
aio_sigevent*: TsigEvent ## Signal number and value.
|
||||
aio_lio_opcode: cint ## Operation to be performed.
|
||||
|
||||
when hasSpawnH:
|
||||
|
|
@ -422,13 +422,13 @@ type
|
|||
|
||||
TSockAddr* {.importc: "struct sockaddr", header: "<sys/socket.h>",
|
||||
pure, final.} = object ## struct sockaddr
|
||||
sa_family*: Tsa_family ## Address family.
|
||||
sa_family*: TSa_Family ## Address family.
|
||||
sa_data*: array [0..255, char] ## Socket address (variable-length data).
|
||||
|
||||
Tsockaddr_storage* {.importc: "struct sockaddr_storage",
|
||||
header: "<sys/socket.h>",
|
||||
pure, final.} = object ## struct sockaddr_storage
|
||||
ss_family*: Tsa_family ## Address family.
|
||||
ss_family*: TSa_Family ## Address family.
|
||||
|
||||
Tif_nameindex* {.importc: "struct if_nameindex", final,
|
||||
pure, header: "<net/if.h>".} = object ## struct if_nameindex
|
||||
|
|
@ -444,17 +444,17 @@ type
|
|||
Tmsghdr* {.importc: "struct msghdr", pure, final,
|
||||
header: "<sys/socket.h>".} = object ## struct msghdr
|
||||
msg_name*: pointer ## Optional address.
|
||||
msg_namelen*: TSockLen ## Size of address.
|
||||
msg_namelen*: TSocklen ## Size of address.
|
||||
msg_iov*: ptr TIOVec ## Scatter/gather array.
|
||||
msg_iovlen*: cint ## Members in msg_iov.
|
||||
msg_control*: pointer ## Ancillary data; see below.
|
||||
msg_controllen*: TSockLen ## Ancillary data buffer len.
|
||||
msg_controllen*: TSocklen ## Ancillary data buffer len.
|
||||
msg_flags*: cint ## Flags on received message.
|
||||
|
||||
|
||||
Tcmsghdr* {.importc: "struct cmsghdr", pure, final,
|
||||
header: "<sys/socket.h>".} = object ## struct cmsghdr
|
||||
cmsg_len*: TSockLen ## Data byte count, including the cmsghdr.
|
||||
cmsg_len*: TSocklen ## Data byte count, including the cmsghdr.
|
||||
cmsg_level*: cint ## Originating protocol.
|
||||
cmsg_type*: cint ## Protocol-specific type.
|
||||
|
||||
|
|
@ -475,7 +475,7 @@ type
|
|||
|
||||
Tsockaddr_in* {.importc: "struct sockaddr_in", pure, final,
|
||||
header: "<netinet/in.h>".} = object ## struct sockaddr_in
|
||||
sin_family*: TSa_family ## AF_INET.
|
||||
sin_family*: TSa_Family ## AF_INET.
|
||||
sin_port*: TInPort ## Port number.
|
||||
sin_addr*: TInAddr ## IP address.
|
||||
|
||||
|
|
@ -485,10 +485,10 @@ type
|
|||
|
||||
Tsockaddr_in6* {.importc: "struct sockaddr_in6", pure, final,
|
||||
header: "<netinet/in.h>".} = object ## struct sockaddr_in6
|
||||
sin6_family*: TSa_family ## AF_INET6.
|
||||
sin6_family*: TSa_Family ## AF_INET6.
|
||||
sin6_port*: TInPort ## Port number.
|
||||
sin6_flowinfo*: int32 ## IPv6 traffic class and flow information.
|
||||
sin6_addr*: Tin6Addr ## IPv6 address.
|
||||
sin6_addr*: TIn6Addr ## IPv6 address.
|
||||
sin6_scope_id*: int32 ## Set of interfaces for a scope.
|
||||
|
||||
Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final,
|
||||
|
|
@ -543,10 +543,10 @@ type
|
|||
ai_family*: cint ## Address family of socket.
|
||||
ai_socktype*: cint ## Socket type.
|
||||
ai_protocol*: cint ## Protocol of socket.
|
||||
ai_addrlen*: TSockLen ## Length of socket address.
|
||||
ai_addrlen*: TSocklen ## Length of socket address.
|
||||
ai_addr*: ptr TSockAddr ## Socket address of socket.
|
||||
ai_canonname*: cstring ## Canonical name of service location.
|
||||
ai_next*: ptr TAddrInfo ## Pointer to next in list.
|
||||
ai_next*: ptr Taddrinfo ## Pointer to next in list.
|
||||
|
||||
TPollfd* {.importc: "struct pollfd", pure, final,
|
||||
header: "<poll.h>".} = object ## struct pollfd
|
||||
|
|
@ -1616,9 +1616,9 @@ var
|
|||
IPPROTO_UDP* {.importc, header: "<netinet/in.h>".}: cint
|
||||
## User datagram protocol.
|
||||
|
||||
INADDR_ANY* {.importc, header: "<netinet/in.h>".}: TinAddrScalar
|
||||
INADDR_ANY* {.importc, header: "<netinet/in.h>".}: TInAddrScalar
|
||||
## IPv4 local host address.
|
||||
INADDR_BROADCAST* {.importc, header: "<netinet/in.h>".}: TinAddrScalar
|
||||
INADDR_BROADCAST* {.importc, header: "<netinet/in.h>".}: TInAddrScalar
|
||||
## IPv4 broadcast address.
|
||||
|
||||
INET_ADDRSTRLEN* {.importc, header: "<netinet/in.h>".}: cint
|
||||
|
|
@ -1726,7 +1726,7 @@ var
|
|||
## Invalid fd member (revents only).
|
||||
|
||||
|
||||
when hasSpawnh:
|
||||
when hasSpawnH:
|
||||
var
|
||||
POSIX_SPAWN_RESETIDS* {.importc, header: "<spawn.h>".}: cint
|
||||
POSIX_SPAWN_SETPGROUP* {.importc, header: "<spawn.h>".}: cint
|
||||
|
|
@ -1750,11 +1750,11 @@ when hasAioH:
|
|||
proc aio_fsync*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
||||
proc aio_read*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
||||
proc aio_return*(a1: ptr Taiocb): int {.importc, header: "<aio.h>".}
|
||||
proc aio_suspend*(a1: ptr ptr Taiocb, a2: cint, a3: ptr ttimespec): cint {.
|
||||
proc aio_suspend*(a1: ptr ptr Taiocb, a2: cint, a3: ptr Ttimespec): cint {.
|
||||
importc, header: "<aio.h>".}
|
||||
proc aio_write*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
||||
proc lio_listio*(a1: cint, a2: ptr ptr Taiocb, a3: cint,
|
||||
a4: ptr Tsigevent): cint {.importc, header: "<aio.h>".}
|
||||
a4: ptr TsigEvent): cint {.importc, header: "<aio.h>".}
|
||||
|
||||
# arpa/inet.h
|
||||
proc htonl*(a1: int32): int32 {.importc, header: "<arpa/inet.h>".}
|
||||
|
|
@ -1778,9 +1778,9 @@ proc IN6ADDR_LOOPBACK_INIT* (): TIn6Addr {.importc, header: "<netinet/in.h>".}
|
|||
|
||||
# dirent.h
|
||||
proc closedir*(a1: ptr TDIR): cint {.importc, header: "<dirent.h>".}
|
||||
proc opendir*(a1: cstring): ptr TDir {.importc, header: "<dirent.h>".}
|
||||
proc readdir*(a1: ptr TDIR): ptr TDirent {.importc, header: "<dirent.h>".}
|
||||
proc readdir_r*(a1: ptr TDIR, a2: ptr Tdirent, a3: ptr ptr TDirent): cint {.
|
||||
proc opendir*(a1: cstring): ptr TDIR {.importc, header: "<dirent.h>".}
|
||||
proc readdir*(a1: ptr TDIR): ptr Tdirent {.importc, header: "<dirent.h>".}
|
||||
proc readdir_r*(a1: ptr TDIR, a2: ptr Tdirent, a3: ptr ptr Tdirent): cint {.
|
||||
importc, header: "<dirent.h>".}
|
||||
proc rewinddir*(a1: ptr TDIR) {.importc, header: "<dirent.h>".}
|
||||
proc seekdir*(a1: ptr TDIR, a2: int) {.importc, header: "<dirent.h>".}
|
||||
|
|
@ -1792,12 +1792,12 @@ proc dlerror*(): cstring {.importc, header: "<dlfcn.h>".}
|
|||
proc dlopen*(a1: cstring, a2: cint): pointer {.importc, header: "<dlfcn.h>".}
|
||||
proc dlsym*(a1: pointer, a2: cstring): pointer {.importc, header: "<dlfcn.h>".}
|
||||
|
||||
proc creat*(a1: cstring, a2: Tmode): cint {.importc, header: "<fcntl.h>".}
|
||||
proc creat*(a1: cstring, a2: TMode): cint {.importc, header: "<fcntl.h>".}
|
||||
proc fcntl*(a1: cint | TSocketHandle, a2: cint): cint {.varargs, importc, header: "<fcntl.h>".}
|
||||
proc open*(a1: cstring, a2: cint): cint {.varargs, importc, header: "<fcntl.h>".}
|
||||
proc posix_fadvise*(a1: cint, a2, a3: Toff, a4: cint): cint {.
|
||||
proc posix_fadvise*(a1: cint, a2, a3: TOff, a4: cint): cint {.
|
||||
importc, header: "<fcntl.h>".}
|
||||
proc posix_fallocate*(a1: cint, a2, a3: Toff): cint {.
|
||||
proc posix_fallocate*(a1: cint, a2, a3: TOff): cint {.
|
||||
importc, header: "<fcntl.h>".}
|
||||
|
||||
proc feclearexcept*(a1: cint): cint {.importc, header: "<fenv.h>".}
|
||||
|
|
@ -1812,7 +1812,7 @@ proc fesetround*(a1: cint): cint {.importc, header: "<fenv.h>".}
|
|||
proc fegetenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
|
||||
proc feholdexcept*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
|
||||
proc fesetenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
|
||||
proc feupdateenv*(a1: ptr TFenv): cint {.importc, header: "<fenv.h>".}
|
||||
proc feupdateenv*(a1: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
|
||||
|
||||
when not defined(haiku):
|
||||
proc fmtmsg*(a1: int, a2: cstring, a3: cint,
|
||||
|
|
@ -1830,12 +1830,12 @@ proc nftw*(a1: cstring,
|
|||
|
||||
proc glob*(a1: cstring, a2: cint,
|
||||
a3: proc (x1: cstring, x2: cint): cint {.noconv.},
|
||||
a4: ptr Tglob): cint {.importc, header: "<glob.h>".}
|
||||
a4: ptr TGlob): cint {.importc, header: "<glob.h>".}
|
||||
proc globfree*(a1: ptr TGlob) {.importc, header: "<glob.h>".}
|
||||
|
||||
proc getgrgid*(a1: TGid): ptr TGroup {.importc, header: "<grp.h>".}
|
||||
proc getgrnam*(a1: cstring): ptr TGroup {.importc, header: "<grp.h>".}
|
||||
proc getgrgid_r*(a1: Tgid, a2: ptr TGroup, a3: cstring, a4: int,
|
||||
proc getgrgid_r*(a1: TGid, a2: ptr TGroup, a3: cstring, a4: int,
|
||||
a5: ptr ptr TGroup): cint {.importc, header: "<grp.h>".}
|
||||
proc getgrnam_r*(a1: cstring, a2: ptr TGroup, a3: cstring,
|
||||
a4: int, a5: ptr ptr TGroup): cint {.
|
||||
|
|
@ -1845,7 +1845,7 @@ proc endgrent*() {.importc, header: "<grp.h>".}
|
|||
proc setgrent*() {.importc, header: "<grp.h>".}
|
||||
|
||||
|
||||
proc iconv_open*(a1, a2: cstring): TIconv {.importc, header: "<iconv.h>".}
|
||||
proc iconv_open*(a1, a2: cstring): Ticonv {.importc, header: "<iconv.h>".}
|
||||
proc iconv*(a1: Ticonv, a2: var cstring, a3: var int, a4: var cstring,
|
||||
a5: var int): int {.importc, header: "<iconv.h>".}
|
||||
proc iconv_close*(a1: Ticonv): cint {.importc, header: "<iconv.h>".}
|
||||
|
|
@ -1862,33 +1862,33 @@ proc setlocale*(a1: cint, a2: cstring): cstring {.
|
|||
proc strfmon*(a1: cstring, a2: int, a3: cstring): int {.varargs,
|
||||
importc, header: "<monetary.h>".}
|
||||
|
||||
proc mq_close*(a1: Tmqd): cint {.importc, header: "<mqueue.h>".}
|
||||
proc mq_getattr*(a1: Tmqd, a2: ptr Tmq_attr): cint {.
|
||||
proc mq_close*(a1: TMqd): cint {.importc, header: "<mqueue.h>".}
|
||||
proc mq_getattr*(a1: TMqd, a2: ptr TMqAttr): cint {.
|
||||
importc, header: "<mqueue.h>".}
|
||||
proc mq_notify*(a1: Tmqd, a2: ptr Tsigevent): cint {.
|
||||
proc mq_notify*(a1: TMqd, a2: ptr TsigEvent): cint {.
|
||||
importc, header: "<mqueue.h>".}
|
||||
proc mq_open*(a1: cstring, a2: cint): TMqd {.
|
||||
varargs, importc, header: "<mqueue.h>".}
|
||||
proc mq_receive*(a1: Tmqd, a2: cstring, a3: int, a4: var int): int {.
|
||||
proc mq_receive*(a1: TMqd, a2: cstring, a3: int, a4: var int): int {.
|
||||
importc, header: "<mqueue.h>".}
|
||||
proc mq_send*(a1: Tmqd, a2: cstring, a3: int, a4: int): cint {.
|
||||
proc mq_send*(a1: TMqd, a2: cstring, a3: int, a4: int): cint {.
|
||||
importc, header: "<mqueue.h>".}
|
||||
proc mq_setattr*(a1: Tmqd, a2, a3: ptr Tmq_attr): cint {.
|
||||
proc mq_setattr*(a1: TMqd, a2, a3: ptr TMqAttr): cint {.
|
||||
importc, header: "<mqueue.h>".}
|
||||
|
||||
proc mq_timedreceive*(a1: Tmqd, a2: cstring, a3: int, a4: int,
|
||||
a5: ptr TTimespec): int {.importc, header: "<mqueue.h>".}
|
||||
proc mq_timedsend*(a1: Tmqd, a2: cstring, a3: int, a4: int,
|
||||
a5: ptr TTimeSpec): cint {.importc, header: "<mqueue.h>".}
|
||||
proc mq_timedreceive*(a1: TMqd, a2: cstring, a3: int, a4: int,
|
||||
a5: ptr Ttimespec): int {.importc, header: "<mqueue.h>".}
|
||||
proc mq_timedsend*(a1: TMqd, a2: cstring, a3: int, a4: int,
|
||||
a5: ptr Ttimespec): cint {.importc, header: "<mqueue.h>".}
|
||||
proc mq_unlink*(a1: cstring): cint {.importc, header: "<mqueue.h>".}
|
||||
|
||||
|
||||
proc getpwnam*(a1: cstring): ptr TPasswd {.importc, header: "<pwd.h>".}
|
||||
proc getpwuid*(a1: Tuid): ptr TPasswd {.importc, header: "<pwd.h>".}
|
||||
proc getpwnam_r*(a1: cstring, a2: ptr Tpasswd, a3: cstring, a4: int,
|
||||
a5: ptr ptr Tpasswd): cint {.importc, header: "<pwd.h>".}
|
||||
proc getpwuid_r*(a1: Tuid, a2: ptr Tpasswd, a3: cstring,
|
||||
a4: int, a5: ptr ptr Tpasswd): cint {.importc, header: "<pwd.h>".}
|
||||
proc getpwnam_r*(a1: cstring, a2: ptr TPasswd, a3: cstring, a4: int,
|
||||
a5: ptr ptr TPasswd): cint {.importc, header: "<pwd.h>".}
|
||||
proc getpwuid_r*(a1: Tuid, a2: ptr TPasswd, a3: cstring,
|
||||
a4: int, a5: ptr ptr TPasswd): cint {.importc, header: "<pwd.h>".}
|
||||
proc endpwent*() {.importc, header: "<pwd.h>".}
|
||||
proc getpwent*(): ptr TPasswd {.importc, header: "<pwd.h>".}
|
||||
proc setpwent*() {.importc, header: "<pwd.h>".}
|
||||
|
|
@ -1933,9 +1933,9 @@ proc pthread_attr_setscope*(a1: ptr Tpthread_attr, a2: cint): cint {.importc,
|
|||
header: "<pthread.h>".}
|
||||
proc pthread_attr_setstack*(a1: ptr Tpthread_attr, a2: pointer, a3: int): cint {.
|
||||
importc, header: "<pthread.h>".}
|
||||
proc pthread_attr_setstackaddr*(a1: ptr TPthread_attr, a2: pointer): cint {.
|
||||
proc pthread_attr_setstackaddr*(a1: ptr Tpthread_attr, a2: pointer): cint {.
|
||||
importc, header: "<pthread.h>".}
|
||||
proc pthread_attr_setstacksize*(a1: ptr TPthread_attr, a2: int): cint {.
|
||||
proc pthread_attr_setstacksize*(a1: ptr Tpthread_attr, a2: int): cint {.
|
||||
importc, header: "<pthread.h>".}
|
||||
proc pthread_barrier_destroy*(a1: ptr Tpthread_barrier): cint {.
|
||||
importc, header: "<pthread.h>".}
|
||||
|
|
@ -1949,9 +1949,9 @@ proc pthread_barrierattr_destroy*(a1: ptr Tpthread_barrierattr): cint {.
|
|||
proc pthread_barrierattr_getpshared*(
|
||||
a1: ptr Tpthread_barrierattr, a2: var cint): cint {.
|
||||
importc, header: "<pthread.h>".}
|
||||
proc pthread_barrierattr_init*(a1: ptr TPthread_barrierattr): cint {.
|
||||
proc pthread_barrierattr_init*(a1: ptr Tpthread_barrierattr): cint {.
|
||||
importc, header: "<pthread.h>".}
|
||||
proc pthread_barrierattr_setpshared*(a1: ptr TPthread_barrierattr,
|
||||
proc pthread_barrierattr_setpshared*(a1: ptr Tpthread_barrierattr,
|
||||
a2: cint): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_cancel*(a1: Tpthread): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_cleanup_push*(a1: proc (x: pointer) {.noconv.}, a2: pointer) {.
|
||||
|
|
@ -1970,13 +1970,13 @@ proc pthread_cond_wait*(a1: ptr Tpthread_cond,
|
|||
a2: ptr Tpthread_mutex): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_condattr_destroy*(a1: ptr Tpthread_condattr): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_condattr_getclock*(a1: ptr Tpthread_condattr,
|
||||
a2: var Tclockid): cint {.importc, header: "<pthread.h>".}
|
||||
a2: var TClockId): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_condattr_getpshared*(a1: ptr Tpthread_condattr,
|
||||
a2: var cint): cint {.importc, header: "<pthread.h>".}
|
||||
|
||||
proc pthread_condattr_init*(a1: ptr TPthread_condattr): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_condattr_setclock*(a1: ptr TPthread_condattr,a2: Tclockid): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_condattr_setpshared*(a1: ptr TPthread_condattr, a2: cint): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_condattr_init*(a1: ptr Tpthread_condattr): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_condattr_setclock*(a1: ptr Tpthread_condattr,a2: TClockId): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_condattr_setpshared*(a1: ptr Tpthread_condattr, a2: cint): cint {.importc, header: "<pthread.h>".}
|
||||
|
||||
proc pthread_create*(a1: ptr Tpthread, a2: ptr Tpthread_attr,
|
||||
a3: proc (x: pointer): pointer {.noconv.}, a4: pointer): cint {.importc, header: "<pthread.h>".}
|
||||
|
|
@ -1984,7 +1984,7 @@ proc pthread_detach*(a1: Tpthread): cint {.importc, header: "<pthread.h>".}
|
|||
proc pthread_equal*(a1, a2: Tpthread): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_exit*(a1: pointer) {.importc, header: "<pthread.h>".}
|
||||
proc pthread_getconcurrency*(): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_getcpuclockid*(a1: Tpthread, a2: var Tclockid): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_getcpuclockid*(a1: Tpthread, a2: var TClockId): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_getschedparam*(a1: Tpthread, a2: var cint,
|
||||
a3: ptr Tsched_param): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_getspecific*(a1: Tpthread_key): pointer {.importc, header: "<pthread.h>".}
|
||||
|
|
@ -2016,7 +2016,7 @@ proc pthread_mutexattr_gettype*(a1: ptr Tpthread_mutexattr,
|
|||
a2: var cint): cint {.importc, header: "<pthread.h>".}
|
||||
|
||||
proc pthread_mutexattr_init*(a1: ptr Tpthread_mutexattr): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_mutexattr_setprioceiling*(a1: ptr tpthread_mutexattr, a2: cint): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_mutexattr_setprioceiling*(a1: ptr Tpthread_mutexattr, a2: cint): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_mutexattr_setprotocol*(a1: ptr Tpthread_mutexattr, a2: cint): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_mutexattr_setpshared*(a1: ptr Tpthread_mutexattr, a2: cint): cint {.importc, header: "<pthread.h>".}
|
||||
proc pthread_mutexattr_settype*(a1: ptr Tpthread_mutexattr, a2: cint): cint {.importc, header: "<pthread.h>".}
|
||||
|
|
@ -2069,7 +2069,7 @@ proc pthread_testcancel*() {.importc, header: "<pthread.h>".}
|
|||
proc access*(a1: cstring, a2: cint): cint {.importc, header: "<unistd.h>".}
|
||||
proc alarm*(a1: cint): cint {.importc, header: "<unistd.h>".}
|
||||
proc chdir*(a1: cstring): cint {.importc, header: "<unistd.h>".}
|
||||
proc chown*(a1: cstring, a2: Tuid, a3: Tgid): cint {.importc, header: "<unistd.h>".}
|
||||
proc chown*(a1: cstring, a2: Tuid, a3: TGid): cint {.importc, header: "<unistd.h>".}
|
||||
proc close*(a1: cint | TSocketHandle): cint {.importc, header: "<unistd.h>".}
|
||||
proc confstr*(a1: cint, a2: cstring, a3: int): int {.importc, header: "<unistd.h>".}
|
||||
proc crypt*(a1, a2: cstring): cstring {.importc, header: "<unistd.h>".}
|
||||
|
|
@ -2085,19 +2085,19 @@ proc execv*(a1: cstring, a2: cstringArray): cint {.importc, header: "<unistd.h>"
|
|||
proc execve*(a1: cstring, a2, a3: cstringArray): cint {.
|
||||
importc, header: "<unistd.h>".}
|
||||
proc execvp*(a1: cstring, a2: cstringArray): cint {.importc, header: "<unistd.h>".}
|
||||
proc fchown*(a1: cint, a2: Tuid, a3: Tgid): cint {.importc, header: "<unistd.h>".}
|
||||
proc fchown*(a1: cint, a2: Tuid, a3: TGid): cint {.importc, header: "<unistd.h>".}
|
||||
proc fchdir*(a1: cint): cint {.importc, header: "<unistd.h>".}
|
||||
proc fdatasync*(a1: cint): cint {.importc, header: "<unistd.h>".}
|
||||
proc fork*(): Tpid {.importc, header: "<unistd.h>".}
|
||||
proc fork*(): TPid {.importc, header: "<unistd.h>".}
|
||||
proc fpathconf*(a1, a2: cint): int {.importc, header: "<unistd.h>".}
|
||||
proc fsync*(a1: cint): cint {.importc, header: "<unistd.h>".}
|
||||
proc ftruncate*(a1: cint, a2: Toff): cint {.importc, header: "<unistd.h>".}
|
||||
proc ftruncate*(a1: cint, a2: TOff): cint {.importc, header: "<unistd.h>".}
|
||||
proc getcwd*(a1: cstring, a2: int): cstring {.importc, header: "<unistd.h>".}
|
||||
proc getegid*(): TGid {.importc, header: "<unistd.h>".}
|
||||
proc geteuid*(): TUid {.importc, header: "<unistd.h>".}
|
||||
proc geteuid*(): Tuid {.importc, header: "<unistd.h>".}
|
||||
proc getgid*(): TGid {.importc, header: "<unistd.h>".}
|
||||
|
||||
proc getgroups*(a1: cint, a2: ptr array[0..255, Tgid]): cint {.
|
||||
proc getgroups*(a1: cint, a2: ptr array[0..255, TGid]): cint {.
|
||||
importc, header: "<unistd.h>".}
|
||||
proc gethostid*(): int {.importc, header: "<unistd.h>".}
|
||||
proc gethostname*(a1: cstring, a2: int): cint {.importc, header: "<unistd.h>".}
|
||||
|
|
@ -2106,105 +2106,105 @@ proc getlogin_r*(a1: cstring, a2: int): cint {.importc, header: "<unistd.h>".}
|
|||
|
||||
proc getopt*(a1: cint, a2: cstringArray, a3: cstring): cint {.
|
||||
importc, header: "<unistd.h>".}
|
||||
proc getpgid*(a1: Tpid): Tpid {.importc, header: "<unistd.h>".}
|
||||
proc getpgrp*(): Tpid {.importc, header: "<unistd.h>".}
|
||||
proc getpid*(): Tpid {.importc, header: "<unistd.h>".}
|
||||
proc getppid*(): Tpid {.importc, header: "<unistd.h>".}
|
||||
proc getsid*(a1: Tpid): Tpid {.importc, header: "<unistd.h>".}
|
||||
proc getpgid*(a1: TPid): TPid {.importc, header: "<unistd.h>".}
|
||||
proc getpgrp*(): TPid {.importc, header: "<unistd.h>".}
|
||||
proc getpid*(): TPid {.importc, header: "<unistd.h>".}
|
||||
proc getppid*(): TPid {.importc, header: "<unistd.h>".}
|
||||
proc getsid*(a1: TPid): TPid {.importc, header: "<unistd.h>".}
|
||||
proc getuid*(): Tuid {.importc, header: "<unistd.h>".}
|
||||
proc getwd*(a1: cstring): cstring {.importc, header: "<unistd.h>".}
|
||||
proc isatty*(a1: cint): cint {.importc, header: "<unistd.h>".}
|
||||
proc lchown*(a1: cstring, a2: Tuid, a3: Tgid): cint {.importc, header: "<unistd.h>".}
|
||||
proc lchown*(a1: cstring, a2: Tuid, a3: TGid): cint {.importc, header: "<unistd.h>".}
|
||||
proc link*(a1, a2: cstring): cint {.importc, header: "<unistd.h>".}
|
||||
|
||||
proc lockf*(a1, a2: cint, a3: Toff): cint {.importc, header: "<unistd.h>".}
|
||||
proc lseek*(a1: cint, a2: Toff, a3: cint): Toff {.importc, header: "<unistd.h>".}
|
||||
proc lockf*(a1, a2: cint, a3: TOff): cint {.importc, header: "<unistd.h>".}
|
||||
proc lseek*(a1: cint, a2: TOff, a3: cint): TOff {.importc, header: "<unistd.h>".}
|
||||
proc nice*(a1: cint): cint {.importc, header: "<unistd.h>".}
|
||||
proc pathconf*(a1: cstring, a2: cint): int {.importc, header: "<unistd.h>".}
|
||||
|
||||
proc pause*(): cint {.importc, header: "<unistd.h>".}
|
||||
proc pipe*(a: array[0..1, cint]): cint {.importc, header: "<unistd.h>".}
|
||||
proc pread*(a1: cint, a2: pointer, a3: int, a4: Toff): int {.
|
||||
proc pread*(a1: cint, a2: pointer, a3: int, a4: TOff): int {.
|
||||
importc, header: "<unistd.h>".}
|
||||
proc pwrite*(a1: cint, a2: pointer, a3: int, a4: Toff): int {.
|
||||
proc pwrite*(a1: cint, a2: pointer, a3: int, a4: TOff): int {.
|
||||
importc, header: "<unistd.h>".}
|
||||
proc read*(a1: cint, a2: pointer, a3: int): int {.importc, header: "<unistd.h>".}
|
||||
proc readlink*(a1, a2: cstring, a3: int): int {.importc, header: "<unistd.h>".}
|
||||
|
||||
proc rmdir*(a1: cstring): cint {.importc, header: "<unistd.h>".}
|
||||
proc setegid*(a1: Tgid): cint {.importc, header: "<unistd.h>".}
|
||||
proc setegid*(a1: TGid): cint {.importc, header: "<unistd.h>".}
|
||||
proc seteuid*(a1: Tuid): cint {.importc, header: "<unistd.h>".}
|
||||
proc setgid*(a1: Tgid): cint {.importc, header: "<unistd.h>".}
|
||||
proc setgid*(a1: TGid): cint {.importc, header: "<unistd.h>".}
|
||||
|
||||
proc setpgid*(a1, a2: Tpid): cint {.importc, header: "<unistd.h>".}
|
||||
proc setpgrp*(): Tpid {.importc, header: "<unistd.h>".}
|
||||
proc setregid*(a1, a2: Tgid): cint {.importc, header: "<unistd.h>".}
|
||||
proc setpgid*(a1, a2: TPid): cint {.importc, header: "<unistd.h>".}
|
||||
proc setpgrp*(): TPid {.importc, header: "<unistd.h>".}
|
||||
proc setregid*(a1, a2: TGid): cint {.importc, header: "<unistd.h>".}
|
||||
proc setreuid*(a1, a2: Tuid): cint {.importc, header: "<unistd.h>".}
|
||||
proc setsid*(): Tpid {.importc, header: "<unistd.h>".}
|
||||
proc setsid*(): TPid {.importc, header: "<unistd.h>".}
|
||||
proc setuid*(a1: Tuid): cint {.importc, header: "<unistd.h>".}
|
||||
proc sleep*(a1: cint): cint {.importc, header: "<unistd.h>".}
|
||||
proc swab*(a1, a2: pointer, a3: int) {.importc, header: "<unistd.h>".}
|
||||
proc symlink*(a1, a2: cstring): cint {.importc, header: "<unistd.h>".}
|
||||
proc sync*() {.importc, header: "<unistd.h>".}
|
||||
proc sysconf*(a1: cint): int {.importc, header: "<unistd.h>".}
|
||||
proc tcgetpgrp*(a1: cint): tpid {.importc, header: "<unistd.h>".}
|
||||
proc tcsetpgrp*(a1: cint, a2: Tpid): cint {.importc, header: "<unistd.h>".}
|
||||
proc truncate*(a1: cstring, a2: Toff): cint {.importc, header: "<unistd.h>".}
|
||||
proc tcgetpgrp*(a1: cint): TPid {.importc, header: "<unistd.h>".}
|
||||
proc tcsetpgrp*(a1: cint, a2: TPid): cint {.importc, header: "<unistd.h>".}
|
||||
proc truncate*(a1: cstring, a2: TOff): cint {.importc, header: "<unistd.h>".}
|
||||
proc ttyname*(a1: cint): cstring {.importc, header: "<unistd.h>".}
|
||||
proc ttyname_r*(a1: cint, a2: cstring, a3: int): cint {.
|
||||
importc, header: "<unistd.h>".}
|
||||
proc ualarm*(a1, a2: Tuseconds): Tuseconds {.importc, header: "<unistd.h>".}
|
||||
proc unlink*(a1: cstring): cint {.importc, header: "<unistd.h>".}
|
||||
proc usleep*(a1: Tuseconds): cint {.importc, header: "<unistd.h>".}
|
||||
proc vfork*(): tpid {.importc, header: "<unistd.h>".}
|
||||
proc vfork*(): TPid {.importc, header: "<unistd.h>".}
|
||||
proc write*(a1: cint, a2: pointer, a3: int): int {.importc, header: "<unistd.h>".}
|
||||
|
||||
proc sem_close*(a1: ptr Tsem): cint {.importc, header: "<semaphore.h>".}
|
||||
proc sem_destroy*(a1: ptr Tsem): cint {.importc, header: "<semaphore.h>".}
|
||||
proc sem_getvalue*(a1: ptr Tsem, a2: var cint): cint {.
|
||||
proc sem_close*(a1: ptr TSem): cint {.importc, header: "<semaphore.h>".}
|
||||
proc sem_destroy*(a1: ptr TSem): cint {.importc, header: "<semaphore.h>".}
|
||||
proc sem_getvalue*(a1: ptr TSem, a2: var cint): cint {.
|
||||
importc, header: "<semaphore.h>".}
|
||||
proc sem_init*(a1: ptr Tsem, a2: cint, a3: cint): cint {.
|
||||
proc sem_init*(a1: ptr TSem, a2: cint, a3: cint): cint {.
|
||||
importc, header: "<semaphore.h>".}
|
||||
proc sem_open*(a1: cstring, a2: cint): ptr TSem {.
|
||||
varargs, importc, header: "<semaphore.h>".}
|
||||
proc sem_post*(a1: ptr Tsem): cint {.importc, header: "<semaphore.h>".}
|
||||
proc sem_timedwait*(a1: ptr Tsem, a2: ptr Ttimespec): cint {.
|
||||
proc sem_post*(a1: ptr TSem): cint {.importc, header: "<semaphore.h>".}
|
||||
proc sem_timedwait*(a1: ptr TSem, a2: ptr Ttimespec): cint {.
|
||||
importc, header: "<semaphore.h>".}
|
||||
proc sem_trywait*(a1: ptr Tsem): cint {.importc, header: "<semaphore.h>".}
|
||||
proc sem_trywait*(a1: ptr TSem): cint {.importc, header: "<semaphore.h>".}
|
||||
proc sem_unlink*(a1: cstring): cint {.importc, header: "<semaphore.h>".}
|
||||
proc sem_wait*(a1: ptr Tsem): cint {.importc, header: "<semaphore.h>".}
|
||||
proc sem_wait*(a1: ptr TSem): cint {.importc, header: "<semaphore.h>".}
|
||||
|
||||
proc ftok*(a1: cstring, a2: cint): Tkey {.importc, header: "<sys/ipc.h>".}
|
||||
proc ftok*(a1: cstring, a2: cint): TKey {.importc, header: "<sys/ipc.h>".}
|
||||
|
||||
proc statvfs*(a1: cstring, a2: var Tstatvfs): cint {.
|
||||
proc statvfs*(a1: cstring, a2: var TStatvfs): cint {.
|
||||
importc, header: "<sys/statvfs.h>".}
|
||||
proc fstatvfs*(a1: cint, a2: var Tstatvfs): cint {.
|
||||
proc fstatvfs*(a1: cint, a2: var TStatvfs): cint {.
|
||||
importc, header: "<sys/statvfs.h>".}
|
||||
|
||||
proc chmod*(a1: cstring, a2: TMode): cint {.importc, header: "<sys/stat.h>".}
|
||||
proc fchmod*(a1: cint, a2: TMode): cint {.importc, header: "<sys/stat.h>".}
|
||||
proc fstat*(a1: cint, a2: var Tstat): cint {.importc, header: "<sys/stat.h>".}
|
||||
proc lstat*(a1: cstring, a2: var Tstat): cint {.importc, header: "<sys/stat.h>".}
|
||||
proc fstat*(a1: cint, a2: var TStat): cint {.importc, header: "<sys/stat.h>".}
|
||||
proc lstat*(a1: cstring, a2: var TStat): cint {.importc, header: "<sys/stat.h>".}
|
||||
proc mkdir*(a1: cstring, a2: TMode): cint {.importc, header: "<sys/stat.h>".}
|
||||
proc mkfifo*(a1: cstring, a2: TMode): cint {.importc, header: "<sys/stat.h>".}
|
||||
proc mknod*(a1: cstring, a2: TMode, a3: Tdev): cint {.
|
||||
proc mknod*(a1: cstring, a2: TMode, a3: TDev): cint {.
|
||||
importc, header: "<sys/stat.h>".}
|
||||
proc stat*(a1: cstring, a2: var Tstat): cint {.importc, header: "<sys/stat.h>".}
|
||||
proc umask*(a1: Tmode): TMode {.importc, header: "<sys/stat.h>".}
|
||||
proc stat*(a1: cstring, a2: var TStat): cint {.importc, header: "<sys/stat.h>".}
|
||||
proc umask*(a1: TMode): TMode {.importc, header: "<sys/stat.h>".}
|
||||
|
||||
proc S_ISBLK*(m: Tmode): bool {.importc, header: "<sys/stat.h>".}
|
||||
proc S_ISBLK*(m: TMode): bool {.importc, header: "<sys/stat.h>".}
|
||||
## Test for a block special file.
|
||||
proc S_ISCHR*(m: Tmode): bool {.importc, header: "<sys/stat.h>".}
|
||||
proc S_ISCHR*(m: TMode): bool {.importc, header: "<sys/stat.h>".}
|
||||
## Test for a character special file.
|
||||
proc S_ISDIR*(m: Tmode): bool {.importc, header: "<sys/stat.h>".}
|
||||
proc S_ISDIR*(m: TMode): bool {.importc, header: "<sys/stat.h>".}
|
||||
## Test for a directory.
|
||||
proc S_ISFIFO*(m: Tmode): bool {.importc, header: "<sys/stat.h>".}
|
||||
proc S_ISFIFO*(m: TMode): bool {.importc, header: "<sys/stat.h>".}
|
||||
## Test for a pipe or FIFO special file.
|
||||
proc S_ISREG*(m: Tmode): bool {.importc, header: "<sys/stat.h>".}
|
||||
proc S_ISREG*(m: TMode): bool {.importc, header: "<sys/stat.h>".}
|
||||
## Test for a regular file.
|
||||
proc S_ISLNK*(m: Tmode): bool {.importc, header: "<sys/stat.h>".}
|
||||
proc S_ISLNK*(m: TMode): bool {.importc, header: "<sys/stat.h>".}
|
||||
## Test for a symbolic link.
|
||||
proc S_ISSOCK*(m: Tmode): bool {.importc, header: "<sys/stat.h>".}
|
||||
proc S_ISSOCK*(m: TMode): bool {.importc, header: "<sys/stat.h>".}
|
||||
## Test for a socket.
|
||||
|
||||
proc S_TYPEISMQ*(buf: var TStat): bool {.importc, header: "<sys/stat.h>".}
|
||||
|
|
@ -2219,7 +2219,7 @@ proc S_TYPEISTMO*(buf: var TStat): bool {.importc, header: "<sys/stat.h>".}
|
|||
|
||||
proc mlock*(a1: pointer, a2: int): cint {.importc, header: "<sys/mman.h>".}
|
||||
proc mlockall*(a1: cint): cint {.importc, header: "<sys/mman.h>".}
|
||||
proc mmap*(a1: pointer, a2: int, a3, a4, a5: cint, a6: Toff): pointer {.
|
||||
proc mmap*(a1: pointer, a2: int, a3, a4, a5: cint, a6: TOff): pointer {.
|
||||
importc, header: "<sys/mman.h>".}
|
||||
proc mprotect*(a1: pointer, a2: int, a3: cint): cint {.
|
||||
importc, header: "<sys/mman.h>".}
|
||||
|
|
@ -2229,75 +2229,75 @@ proc munlockall*(): cint {.importc, header: "<sys/mman.h>".}
|
|||
proc munmap*(a1: pointer, a2: int): cint {.importc, header: "<sys/mman.h>".}
|
||||
proc posix_madvise*(a1: pointer, a2: int, a3: cint): cint {.
|
||||
importc, header: "<sys/mman.h>".}
|
||||
proc posix_mem_offset*(a1: pointer, a2: int, a3: var Toff,
|
||||
proc posix_mem_offset*(a1: pointer, a2: int, a3: var TOff,
|
||||
a4: var int, a5: var cint): cint {.importc, header: "<sys/mman.h>".}
|
||||
proc posix_typed_mem_get_info*(a1: cint,
|
||||
a2: var Tposix_typed_mem_info): cint {.importc, header: "<sys/mman.h>".}
|
||||
proc posix_typed_mem_open*(a1: cstring, a2, a3: cint): cint {.
|
||||
importc, header: "<sys/mman.h>".}
|
||||
proc shm_open*(a1: cstring, a2: cint, a3: Tmode): cint {.
|
||||
proc shm_open*(a1: cstring, a2: cint, a3: TMode): cint {.
|
||||
importc, header: "<sys/mman.h>".}
|
||||
proc shm_unlink*(a1: cstring): cint {.importc, header: "<sys/mman.h>".}
|
||||
|
||||
proc asctime*(a1: var ttm): cstring{.importc, header: "<time.h>".}
|
||||
proc asctime*(a1: var Ttm): cstring{.importc, header: "<time.h>".}
|
||||
|
||||
proc asctime_r*(a1: var ttm, a2: cstring): cstring {.importc, header: "<time.h>".}
|
||||
proc clock*(): Tclock {.importc, header: "<time.h>".}
|
||||
proc clock_getcpuclockid*(a1: tpid, a2: var Tclockid): cint {.
|
||||
proc asctime_r*(a1: var Ttm, a2: cstring): cstring {.importc, header: "<time.h>".}
|
||||
proc clock*(): TClock {.importc, header: "<time.h>".}
|
||||
proc clock_getcpuclockid*(a1: TPid, a2: var TClockId): cint {.
|
||||
importc, header: "<time.h>".}
|
||||
proc clock_getres*(a1: Tclockid, a2: var Ttimespec): cint {.
|
||||
proc clock_getres*(a1: TClockId, a2: var Ttimespec): cint {.
|
||||
importc, header: "<time.h>".}
|
||||
proc clock_gettime*(a1: Tclockid, a2: var Ttimespec): cint {.
|
||||
proc clock_gettime*(a1: TClockId, a2: var Ttimespec): cint {.
|
||||
importc, header: "<time.h>".}
|
||||
proc clock_nanosleep*(a1: Tclockid, a2: cint, a3: var Ttimespec,
|
||||
proc clock_nanosleep*(a1: TClockId, a2: cint, a3: var Ttimespec,
|
||||
a4: var Ttimespec): cint {.importc, header: "<time.h>".}
|
||||
proc clock_settime*(a1: Tclockid, a2: var Ttimespec): cint {.
|
||||
proc clock_settime*(a1: TClockId, a2: var Ttimespec): cint {.
|
||||
importc, header: "<time.h>".}
|
||||
|
||||
proc ctime*(a1: var Ttime): cstring {.importc, header: "<time.h>".}
|
||||
proc ctime_r*(a1: var Ttime, a2: cstring): cstring {.importc, header: "<time.h>".}
|
||||
proc difftime*(a1, a2: Ttime): cdouble {.importc, header: "<time.h>".}
|
||||
proc getdate*(a1: cstring): ptr ttm {.importc, header: "<time.h>".}
|
||||
proc ctime*(a1: var TTime): cstring {.importc, header: "<time.h>".}
|
||||
proc ctime_r*(a1: var TTime, a2: cstring): cstring {.importc, header: "<time.h>".}
|
||||
proc difftime*(a1, a2: TTime): cdouble {.importc, header: "<time.h>".}
|
||||
proc getdate*(a1: cstring): ptr Ttm {.importc, header: "<time.h>".}
|
||||
|
||||
proc gmtime*(a1: var ttime): ptr ttm {.importc, header: "<time.h>".}
|
||||
proc gmtime_r*(a1: var ttime, a2: var ttm): ptr ttm {.importc, header: "<time.h>".}
|
||||
proc localtime*(a1: var ttime): ptr ttm {.importc, header: "<time.h>".}
|
||||
proc localtime_r*(a1: var ttime, a2: var ttm): ptr ttm {.importc, header: "<time.h>".}
|
||||
proc mktime*(a1: var ttm): ttime {.importc, header: "<time.h>".}
|
||||
proc gmtime*(a1: var TTime): ptr Ttm {.importc, header: "<time.h>".}
|
||||
proc gmtime_r*(a1: var TTime, a2: var Ttm): ptr Ttm {.importc, header: "<time.h>".}
|
||||
proc localtime*(a1: var TTime): ptr Ttm {.importc, header: "<time.h>".}
|
||||
proc localtime_r*(a1: var TTime, a2: var Ttm): ptr Ttm {.importc, header: "<time.h>".}
|
||||
proc mktime*(a1: var Ttm): TTime {.importc, header: "<time.h>".}
|
||||
proc nanosleep*(a1, a2: var Ttimespec): cint {.importc, header: "<time.h>".}
|
||||
proc strftime*(a1: cstring, a2: int, a3: cstring,
|
||||
a4: var ttm): int {.importc, header: "<time.h>".}
|
||||
proc strptime*(a1, a2: cstring, a3: var ttm): cstring {.importc, header: "<time.h>".}
|
||||
proc time*(a1: var Ttime): ttime {.importc, header: "<time.h>".}
|
||||
proc timer_create*(a1: var Tclockid, a2: var Tsigevent,
|
||||
a4: var Ttm): int {.importc, header: "<time.h>".}
|
||||
proc strptime*(a1, a2: cstring, a3: var Ttm): cstring {.importc, header: "<time.h>".}
|
||||
proc time*(a1: var TTime): TTime {.importc, header: "<time.h>".}
|
||||
proc timer_create*(a1: var TClockId, a2: var TsigEvent,
|
||||
a3: var Ttimer): cint {.importc, header: "<time.h>".}
|
||||
proc timer_delete*(a1: var Ttimer): cint {.importc, header: "<time.h>".}
|
||||
proc timer_gettime*(a1: Ttimer, a2: var Titimerspec): cint {.
|
||||
proc timer_gettime*(a1: Ttimer, a2: var titimerspec): cint {.
|
||||
importc, header: "<time.h>".}
|
||||
proc timer_getoverrun*(a1: Ttimer): cint {.importc, header: "<time.h>".}
|
||||
proc timer_settime*(a1: Ttimer, a2: cint, a3: var Titimerspec,
|
||||
proc timer_settime*(a1: Ttimer, a2: cint, a3: var titimerspec,
|
||||
a4: var titimerspec): cint {.importc, header: "<time.h>".}
|
||||
proc tzset*() {.importc, header: "<time.h>".}
|
||||
|
||||
|
||||
proc wait*(a1: var cint): tpid {.importc, header: "<sys/wait.h>".}
|
||||
proc waitid*(a1: cint, a2: tid, a3: var Tsiginfo, a4: cint): cint {.
|
||||
proc wait*(a1: var cint): TPid {.importc, header: "<sys/wait.h>".}
|
||||
proc waitid*(a1: cint, a2: Tid, a3: var TsigInfo, a4: cint): cint {.
|
||||
importc, header: "<sys/wait.h>".}
|
||||
proc waitpid*(a1: tpid, a2: var cint, a3: cint): tpid {.
|
||||
proc waitpid*(a1: TPid, a2: var cint, a3: cint): TPid {.
|
||||
importc, header: "<sys/wait.h>".}
|
||||
|
||||
proc bsd_signal*(a1: cint, a2: proc (x: pointer) {.noconv.}) {.
|
||||
importc, header: "<signal.h>".}
|
||||
proc kill*(a1: Tpid, a2: cint): cint {.importc, header: "<signal.h>".}
|
||||
proc killpg*(a1: Tpid, a2: cint): cint {.importc, header: "<signal.h>".}
|
||||
proc pthread_kill*(a1: tpthread, a2: cint): cint {.importc, header: "<signal.h>".}
|
||||
proc kill*(a1: TPid, a2: cint): cint {.importc, header: "<signal.h>".}
|
||||
proc killpg*(a1: TPid, a2: cint): cint {.importc, header: "<signal.h>".}
|
||||
proc pthread_kill*(a1: Tpthread, a2: cint): cint {.importc, header: "<signal.h>".}
|
||||
proc pthread_sigmask*(a1: cint, a2, a3: var Tsigset): cint {.
|
||||
importc, header: "<signal.h>".}
|
||||
proc `raise`*(a1: cint): cint {.importc, header: "<signal.h>".}
|
||||
proc sigaction*(a1: cint, a2, a3: var Tsigaction): cint {.
|
||||
proc sigaction*(a1: cint, a2, a3: var TSigaction): cint {.
|
||||
importc, header: "<signal.h>".}
|
||||
proc sigaddset*(a1: var Tsigset, a2: cint): cint {.importc, header: "<signal.h>".}
|
||||
proc sigaltstack*(a1, a2: var Tstack): cint {.importc, header: "<signal.h>".}
|
||||
proc sigaltstack*(a1, a2: var TStack): cint {.importc, header: "<signal.h>".}
|
||||
proc sigdelset*(a1: var Tsigset, a2: cint): cint {.importc, header: "<signal.h>".}
|
||||
proc sigemptyset*(a1: var Tsigset): cint {.importc, header: "<signal.h>".}
|
||||
proc sigfillset*(a1: var Tsigset): cint {.importc, header: "<signal.h>".}
|
||||
|
|
@ -2308,20 +2308,20 @@ proc sigismember*(a1: var Tsigset, a2: cint): cint {.importc, header: "<signal.h
|
|||
proc signal*(a1: cint, a2: proc (x: cint) {.noconv.}) {.
|
||||
importc, header: "<signal.h>".}
|
||||
proc sigpause*(a1: cint): cint {.importc, header: "<signal.h>".}
|
||||
proc sigpending*(a1: var tsigset): cint {.importc, header: "<signal.h>".}
|
||||
proc sigprocmask*(a1: cint, a2, a3: var tsigset): cint {.
|
||||
proc sigpending*(a1: var Tsigset): cint {.importc, header: "<signal.h>".}
|
||||
proc sigprocmask*(a1: cint, a2, a3: var Tsigset): cint {.
|
||||
importc, header: "<signal.h>".}
|
||||
proc sigqueue*(a1: tpid, a2: cint, a3: Tsigval): cint {.
|
||||
proc sigqueue*(a1: TPid, a2: cint, a3: TsigVal): cint {.
|
||||
importc, header: "<signal.h>".}
|
||||
proc sigrelse*(a1: cint): cint {.importc, header: "<signal.h>".}
|
||||
proc sigset*(a1: int, a2: proc (x: cint) {.noconv.}) {.
|
||||
importc, header: "<signal.h>".}
|
||||
proc sigsuspend*(a1: var Tsigset): cint {.importc, header: "<signal.h>".}
|
||||
proc sigtimedwait*(a1: var Tsigset, a2: var tsiginfo,
|
||||
a3: var ttimespec): cint {.importc, header: "<signal.h>".}
|
||||
proc sigtimedwait*(a1: var Tsigset, a2: var TsigInfo,
|
||||
a3: var Ttimespec): cint {.importc, header: "<signal.h>".}
|
||||
proc sigwait*(a1: var Tsigset, a2: var cint): cint {.
|
||||
importc, header: "<signal.h>".}
|
||||
proc sigwaitinfo*(a1: var Tsigset, a2: var tsiginfo): cint {.
|
||||
proc sigwaitinfo*(a1: var Tsigset, a2: var TsigInfo): cint {.
|
||||
importc, header: "<signal.h>".}
|
||||
|
||||
|
||||
|
|
@ -2333,81 +2333,81 @@ proc catopen*(a1: cstring, a2: cint): Tnl_catd {.
|
|||
|
||||
proc sched_get_priority_max*(a1: cint): cint {.importc, header: "<sched.h>".}
|
||||
proc sched_get_priority_min*(a1: cint): cint {.importc, header: "<sched.h>".}
|
||||
proc sched_getparam*(a1: tpid, a2: var Tsched_param): cint {.
|
||||
proc sched_getparam*(a1: TPid, a2: var Tsched_param): cint {.
|
||||
importc, header: "<sched.h>".}
|
||||
proc sched_getscheduler*(a1: tpid): cint {.importc, header: "<sched.h>".}
|
||||
proc sched_rr_get_interval*(a1: tpid, a2: var Ttimespec): cint {.
|
||||
proc sched_getscheduler*(a1: TPid): cint {.importc, header: "<sched.h>".}
|
||||
proc sched_rr_get_interval*(a1: TPid, a2: var Ttimespec): cint {.
|
||||
importc, header: "<sched.h>".}
|
||||
proc sched_setparam*(a1: tpid, a2: var Tsched_param): cint {.
|
||||
proc sched_setparam*(a1: TPid, a2: var Tsched_param): cint {.
|
||||
importc, header: "<sched.h>".}
|
||||
proc sched_setscheduler*(a1: tpid, a2: cint, a3: var tsched_param): cint {.
|
||||
proc sched_setscheduler*(a1: TPid, a2: cint, a3: var Tsched_param): cint {.
|
||||
importc, header: "<sched.h>".}
|
||||
proc sched_yield*(): cint {.importc, header: "<sched.h>".}
|
||||
|
||||
proc strerror*(errnum: cint): cstring {.importc, header: "<string.h>".}
|
||||
proc hstrerror*(herrnum: cint): cstring {.importc, header: "<netdb.h>".}
|
||||
|
||||
proc FD_CLR*(a1: cint, a2: var Tfd_set) {.importc, header: "<sys/select.h>".}
|
||||
proc FD_ISSET*(a1: cint | TSocketHandle, a2: var Tfd_set): cint {.
|
||||
proc FD_CLR*(a1: cint, a2: var TFdSet) {.importc, header: "<sys/select.h>".}
|
||||
proc FD_ISSET*(a1: cint | TSocketHandle, a2: var TFdSet): cint {.
|
||||
importc, header: "<sys/select.h>".}
|
||||
proc FD_SET*(a1: cint | TSocketHandle, a2: var Tfd_set) {.importc, header: "<sys/select.h>".}
|
||||
proc FD_ZERO*(a1: var Tfd_set) {.importc, header: "<sys/select.h>".}
|
||||
proc FD_SET*(a1: cint | TSocketHandle, a2: var TFdSet) {.importc, header: "<sys/select.h>".}
|
||||
proc FD_ZERO*(a1: var TFdSet) {.importc, header: "<sys/select.h>".}
|
||||
|
||||
proc pselect*(a1: cint, a2, a3, a4: ptr Tfd_set, a5: ptr ttimespec,
|
||||
proc pselect*(a1: cint, a2, a3, a4: ptr TFdSet, a5: ptr Ttimespec,
|
||||
a6: var Tsigset): cint {.importc, header: "<sys/select.h>".}
|
||||
proc select*(a1: cint, a2, a3, a4: ptr Tfd_set, a5: ptr ttimeval): cint {.
|
||||
proc select*(a1: cint, a2, a3, a4: ptr TFdSet, a5: ptr Ttimeval): cint {.
|
||||
importc, header: "<sys/select.h>".}
|
||||
|
||||
when hasSpawnH:
|
||||
proc posix_spawn*(a1: var tpid, a2: cstring,
|
||||
proc posix_spawn*(a1: var TPid, a2: cstring,
|
||||
a3: var Tposix_spawn_file_actions,
|
||||
a4: var Tposix_spawnattr,
|
||||
a5, a6: cstringArray): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawn_file_actions_addclose*(a1: var tposix_spawn_file_actions,
|
||||
proc posix_spawn_file_actions_addclose*(a1: var Tposix_spawn_file_actions,
|
||||
a2: cint): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawn_file_actions_adddup2*(a1: var tposix_spawn_file_actions,
|
||||
proc posix_spawn_file_actions_adddup2*(a1: var Tposix_spawn_file_actions,
|
||||
a2, a3: cint): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawn_file_actions_addopen*(a1: var tposix_spawn_file_actions,
|
||||
a2: cint, a3: cstring, a4: cint, a5: tmode): cint {.
|
||||
proc posix_spawn_file_actions_addopen*(a1: var Tposix_spawn_file_actions,
|
||||
a2: cint, a3: cstring, a4: cint, a5: TMode): cint {.
|
||||
importc, header: "<spawn.h>".}
|
||||
proc posix_spawn_file_actions_destroy*(
|
||||
a1: var tposix_spawn_file_actions): cint {.importc, header: "<spawn.h>".}
|
||||
a1: var Tposix_spawn_file_actions): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawn_file_actions_init*(
|
||||
a1: var tposix_spawn_file_actions): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_destroy*(a1: var tposix_spawnattr): cint {.
|
||||
a1: var Tposix_spawn_file_actions): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_destroy*(a1: var Tposix_spawnattr): cint {.
|
||||
importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_getsigdefault*(a1: var tposix_spawnattr,
|
||||
proc posix_spawnattr_getsigdefault*(a1: var Tposix_spawnattr,
|
||||
a2: var Tsigset): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_getflags*(a1: var tposix_spawnattr,
|
||||
proc posix_spawnattr_getflags*(a1: var Tposix_spawnattr,
|
||||
a2: var cshort): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_getpgroup*(a1: var tposix_spawnattr,
|
||||
a2: var tpid): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_getschedparam*(a1: var tposix_spawnattr,
|
||||
a2: var tsched_param): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_getschedpolicy*(a1: var tposix_spawnattr,
|
||||
proc posix_spawnattr_getpgroup*(a1: var Tposix_spawnattr,
|
||||
a2: var TPid): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_getschedparam*(a1: var Tposix_spawnattr,
|
||||
a2: var Tsched_param): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_getschedpolicy*(a1: var Tposix_spawnattr,
|
||||
a2: var cint): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_getsigmask*(a1: var tposix_spawnattr,
|
||||
a2: var tsigset): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_getsigmask*(a1: var Tposix_spawnattr,
|
||||
a2: var Tsigset): cint {.importc, header: "<spawn.h>".}
|
||||
|
||||
proc posix_spawnattr_init*(a1: var tposix_spawnattr): cint {.
|
||||
proc posix_spawnattr_init*(a1: var Tposix_spawnattr): cint {.
|
||||
importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_setsigdefault*(a1: var tposix_spawnattr,
|
||||
a2: var tsigset): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_setflags*(a1: var tposix_spawnattr, a2: cint): cint {.
|
||||
proc posix_spawnattr_setsigdefault*(a1: var Tposix_spawnattr,
|
||||
a2: var Tsigset): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_setflags*(a1: var Tposix_spawnattr, a2: cint): cint {.
|
||||
importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_setpgroup*(a1: var tposix_spawnattr, a2: tpid): cint {.
|
||||
proc posix_spawnattr_setpgroup*(a1: var Tposix_spawnattr, a2: TPid): cint {.
|
||||
importc, header: "<spawn.h>".}
|
||||
|
||||
proc posix_spawnattr_setschedparam*(a1: var tposix_spawnattr,
|
||||
a2: var tsched_param): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_setschedpolicy*(a1: var tposix_spawnattr,
|
||||
proc posix_spawnattr_setschedparam*(a1: var Tposix_spawnattr,
|
||||
a2: var Tsched_param): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_setschedpolicy*(a1: var Tposix_spawnattr,
|
||||
a2: cint): cint {.
|
||||
importc, header: "<spawn.h>".}
|
||||
proc posix_spawnattr_setsigmask*(a1: var tposix_spawnattr,
|
||||
a2: var tsigset): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnp*(a1: var tpid, a2: cstring,
|
||||
a3: var tposix_spawn_file_actions,
|
||||
a4: var tposix_spawnattr,
|
||||
proc posix_spawnattr_setsigmask*(a1: var Tposix_spawnattr,
|
||||
a2: var Tsigset): cint {.importc, header: "<spawn.h>".}
|
||||
proc posix_spawnp*(a1: var TPid, a2: cstring,
|
||||
a3: var Tposix_spawn_file_actions,
|
||||
a4: var Tposix_spawnattr,
|
||||
a5, a6: cstringArray): cint {.importc, header: "<spawn.h>".}
|
||||
|
||||
proc getcontext*(a1: var Tucontext): cint {.importc, header: "<ucontext.h>".}
|
||||
|
|
@ -2424,10 +2424,10 @@ proc writev*(a1: cint, a2: ptr TIOVec, a3: cint): int {.
|
|||
proc CMSG_DATA*(cmsg: ptr Tcmsghdr): cstring {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
|
||||
proc CMSG_NXTHDR*(mhdr: ptr TMsgHdr, cmsg: ptr TCMsgHdr): ptr TCmsgHdr {.
|
||||
proc CMSG_NXTHDR*(mhdr: ptr Tmsghdr, cmsg: ptr Tcmsghdr): ptr Tcmsghdr {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
|
||||
proc CMSG_FIRSTHDR*(mhdr: ptr TMsgHdr): ptr TCMsgHdr {.
|
||||
proc CMSG_FIRSTHDR*(mhdr: ptr Tmsghdr): ptr Tcmsghdr {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
|
||||
const
|
||||
|
|
@ -2435,21 +2435,21 @@ const
|
|||
|
||||
proc `==`*(x, y: TSocketHandle): bool {.borrow.}
|
||||
|
||||
proc accept*(a1: TSocketHandle, a2: ptr Tsockaddr, a3: ptr Tsocklen): TSocketHandle {.
|
||||
proc accept*(a1: TSocketHandle, a2: ptr TSockAddr, a3: ptr TSocklen): TSocketHandle {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
|
||||
proc bindSocket*(a1: TSocketHandle, a2: ptr Tsockaddr, a3: Tsocklen): cint {.
|
||||
proc bindSocket*(a1: TSocketHandle, a2: ptr TSockAddr, a3: TSocklen): cint {.
|
||||
importc: "bind", header: "<sys/socket.h>".}
|
||||
## is Posix's ``bind``, because ``bind`` is a reserved word
|
||||
|
||||
proc connect*(a1: TSocketHandle, a2: ptr Tsockaddr, a3: Tsocklen): cint {.
|
||||
proc connect*(a1: TSocketHandle, a2: ptr TSockAddr, a3: TSocklen): cint {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
proc getpeername*(a1: TSocketHandle, a2: ptr Tsockaddr, a3: ptr Tsocklen): cint {.
|
||||
proc getpeername*(a1: TSocketHandle, a2: ptr TSockAddr, a3: ptr TSocklen): cint {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
proc getsockname*(a1: TSocketHandle, a2: ptr Tsockaddr, a3: ptr Tsocklen): cint {.
|
||||
proc getsockname*(a1: TSocketHandle, a2: ptr TSockAddr, a3: ptr TSocklen): cint {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
|
||||
proc getsockopt*(a1: TSocketHandle, a2, a3: cint, a4: pointer, a5: ptr Tsocklen): cint {.
|
||||
proc getsockopt*(a1: TSocketHandle, a2, a3: cint, a4: pointer, a5: ptr TSocklen): cint {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
|
||||
proc listen*(a1: TSocketHandle, a2: cint): cint {.
|
||||
|
|
@ -2457,7 +2457,7 @@ proc listen*(a1: TSocketHandle, a2: cint): cint {.
|
|||
proc recv*(a1: TSocketHandle, a2: pointer, a3: int, a4: cint): int {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
proc recvfrom*(a1: TSocketHandle, a2: pointer, a3: int, a4: cint,
|
||||
a5: ptr Tsockaddr, a6: ptr Tsocklen): int {.
|
||||
a5: ptr TSockAddr, a6: ptr TSocklen): int {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
proc recvmsg*(a1: TSocketHandle, a2: ptr Tmsghdr, a3: cint): int {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
|
|
@ -2465,10 +2465,10 @@ proc send*(a1: TSocketHandle, a2: pointer, a3: int, a4: cint): int {.
|
|||
importc, header: "<sys/socket.h>".}
|
||||
proc sendmsg*(a1: TSocketHandle, a2: ptr Tmsghdr, a3: cint): int {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
proc sendto*(a1: TSocketHandle, a2: pointer, a3: int, a4: cint, a5: ptr Tsockaddr,
|
||||
a6: Tsocklen): int {.
|
||||
proc sendto*(a1: TSocketHandle, a2: pointer, a3: int, a4: cint, a5: ptr TSockAddr,
|
||||
a6: TSocklen): int {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
proc setsockopt*(a1: TSocketHandle, a2, a3: cint, a4: pointer, a5: Tsocklen): cint {.
|
||||
proc setsockopt*(a1: TSocketHandle, a2, a3: cint, a4: pointer, a5: TSocklen): cint {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
proc shutdown*(a1: TSocketHandle, a2: cint): cint {.
|
||||
importc, header: "<sys/socket.h>".}
|
||||
|
|
@ -2530,21 +2530,21 @@ proc freeaddrinfo*(a1: ptr Taddrinfo) {.importc, header: "<netdb.h>".}
|
|||
|
||||
proc gai_strerror*(a1: cint): cstring {.importc, header: "<netdb.h>".}
|
||||
|
||||
proc getaddrinfo*(a1, a2: cstring, a3: ptr TAddrInfo,
|
||||
a4: var ptr TAddrInfo): cint {.importc, header: "<netdb.h>".}
|
||||
proc getaddrinfo*(a1, a2: cstring, a3: ptr Taddrinfo,
|
||||
a4: var ptr Taddrinfo): cint {.importc, header: "<netdb.h>".}
|
||||
|
||||
proc gethostbyaddr*(a1: pointer, a2: Tsocklen, a3: cint): ptr THostent {.
|
||||
proc gethostbyaddr*(a1: pointer, a2: TSocklen, a3: cint): ptr Thostent {.
|
||||
importc, header: "<netdb.h>".}
|
||||
proc gethostbyname*(a1: cstring): ptr THostent {.importc, header: "<netdb.h>".}
|
||||
proc gethostent*(): ptr THostent {.importc, header: "<netdb.h>".}
|
||||
proc gethostbyname*(a1: cstring): ptr Thostent {.importc, header: "<netdb.h>".}
|
||||
proc gethostent*(): ptr Thostent {.importc, header: "<netdb.h>".}
|
||||
|
||||
proc getnameinfo*(a1: ptr Tsockaddr, a2: Tsocklen,
|
||||
a3: cstring, a4: Tsocklen, a5: cstring,
|
||||
a6: Tsocklen, a7: cint): cint {.importc, header: "<netdb.h>".}
|
||||
proc getnameinfo*(a1: ptr TSockAddr, a2: TSocklen,
|
||||
a3: cstring, a4: TSocklen, a5: cstring,
|
||||
a6: TSocklen, a7: cint): cint {.importc, header: "<netdb.h>".}
|
||||
|
||||
proc getnetbyaddr*(a1: int32, a2: cint): ptr TNetent {.importc, header: "<netdb.h>".}
|
||||
proc getnetbyname*(a1: cstring): ptr TNetent {.importc, header: "<netdb.h>".}
|
||||
proc getnetent*(): ptr TNetent {.importc, header: "<netdb.h>".}
|
||||
proc getnetbyaddr*(a1: int32, a2: cint): ptr Tnetent {.importc, header: "<netdb.h>".}
|
||||
proc getnetbyname*(a1: cstring): ptr Tnetent {.importc, header: "<netdb.h>".}
|
||||
proc getnetent*(): ptr Tnetent {.importc, header: "<netdb.h>".}
|
||||
|
||||
proc getprotobyname*(a1: cstring): ptr TProtoent {.importc, header: "<netdb.h>".}
|
||||
proc getprotobynumber*(a1: cint): ptr TProtoent {.importc, header: "<netdb.h>".}
|
||||
|
|
@ -2560,10 +2560,10 @@ proc setnetent*(a1: cint) {.importc, header: "<netdb.h>".}
|
|||
proc setprotoent*(a1: cint) {.importc, header: "<netdb.h>".}
|
||||
proc setservent*(a1: cint) {.importc, header: "<netdb.h>".}
|
||||
|
||||
proc poll*(a1: ptr Tpollfd, a2: Tnfds, a3: int): cint {.
|
||||
proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: int): cint {.
|
||||
importc, header: "<poll.h>".}
|
||||
|
||||
proc realpath*(name, resolved: CString): CString {.
|
||||
proc realpath*(name, resolved: cstring): cstring {.
|
||||
importc: "realpath", header: "<stdlib.h>".}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ proc reverse*[T](a: var openArray[T]) =
|
|||
## reverses the array `a`.
|
||||
reverse(a, 0, a.high)
|
||||
|
||||
proc binarySearch*[T](a: openarray[T], key: T): int =
|
||||
proc binarySearch*[T](a: openArray[T], key: T): int =
|
||||
## binary search for `key` in `a`. Returns -1 if not found.
|
||||
var b = len(a)
|
||||
while result < b:
|
||||
|
|
@ -79,7 +79,7 @@ proc merge[T](a, b: var openArray[T], lo, m, hi: int,
|
|||
inc(bb)
|
||||
inc(j)
|
||||
else:
|
||||
CopyMem(addr(b[0]), addr(a[j]), sizeof(T)*(m-j+1))
|
||||
copyMem(addr(b[0]), addr(a[j]), sizeof(T)*(m-j+1))
|
||||
j = m+1
|
||||
var i = 0
|
||||
var k = lo
|
||||
|
|
|
|||
|
|
@ -139,27 +139,27 @@ type
|
|||
proc newDelegate*(): PDelegate =
|
||||
## Creates a new delegate.
|
||||
new(result)
|
||||
result.handleRead = (proc (h: PObject) = nil)
|
||||
result.handleWrite = (proc (h: PObject) = nil)
|
||||
result.handleError = (proc (h: PObject) = nil)
|
||||
result.handleRead = (proc (h: PObject) = discard)
|
||||
result.handleWrite = (proc (h: PObject) = discard)
|
||||
result.handleError = (proc (h: PObject) = discard)
|
||||
result.hasDataBuffered = (proc (h: PObject): bool = return false)
|
||||
result.task = (proc (h: PObject) = nil)
|
||||
result.task = (proc (h: PObject) = discard)
|
||||
result.mode = fmRead
|
||||
|
||||
proc newAsyncSocket(): PAsyncSocket =
|
||||
new(result)
|
||||
result.info = SockIdle
|
||||
|
||||
result.handleRead = (proc (s: PAsyncSocket) = nil)
|
||||
result.handleRead = (proc (s: PAsyncSocket) = discard)
|
||||
result.handleWrite = nil
|
||||
result.handleConnect = (proc (s: PAsyncSocket) = nil)
|
||||
result.handleAccept = (proc (s: PAsyncSocket) = nil)
|
||||
result.handleTask = (proc (s: PAsyncSocket) = nil)
|
||||
result.handleConnect = (proc (s: PAsyncSocket) = discard)
|
||||
result.handleAccept = (proc (s: PAsyncSocket) = discard)
|
||||
result.handleTask = (proc (s: PAsyncSocket) = discard)
|
||||
|
||||
result.lineBuffer = "".TaintedString
|
||||
result.sendBuffer = ""
|
||||
|
||||
proc AsyncSocket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
|
||||
proc asyncSocket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
|
||||
protocol: TProtocol = IPPROTO_TCP,
|
||||
buffered = true): PAsyncSocket =
|
||||
## Initialises an AsyncSocket object. If a socket cannot be initialised
|
||||
|
|
@ -233,8 +233,11 @@ proc asyncSockHandleWrite(h: PObject) =
|
|||
let sock = PAsyncSocket(h)
|
||||
try:
|
||||
let bytesSent = sock.socket.sendAsync(sock.sendBuffer)
|
||||
assert bytesSent > 0
|
||||
if bytesSent != sock.sendBuffer.len:
|
||||
if bytesSent == 0:
|
||||
# Apparently the socket cannot be written to. Even though select
|
||||
# just told us that it can be... This used to be an assert. Just
|
||||
# do nothing instead.
|
||||
elif bytesSent != sock.sendBuffer.len:
|
||||
sock.sendBuffer = sock.sendBuffer[bytesSent .. -1]
|
||||
elif bytesSent == sock.sendBuffer.len:
|
||||
sock.sendBuffer = ""
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ proc openDefaultBrowser*(url: string) =
|
|||
when useWinUnicode:
|
||||
var o = newWideCString("open")
|
||||
var u = newWideCString(url)
|
||||
discard ShellExecuteW(0'i32, o, u, nil, nil, SW_SHOWNORMAL)
|
||||
discard shellExecuteW(0'i32, o, u, nil, nil, SW_SHOWNORMAL)
|
||||
else:
|
||||
discard ShellExecuteA(0'i32, "open", url, nil, nil, SW_SHOWNORMAL)
|
||||
discard shellExecuteA(0'i32, "open", url, nil, nil, SW_SHOWNORMAL)
|
||||
elif defined(macosx):
|
||||
discard execShellCmd("open " & quoteShell(url))
|
||||
else:
|
||||
|
|
@ -45,4 +45,4 @@ proc openDefaultBrowser*(url: string) =
|
|||
discard startProcess(command=b, args=[url], options={poUseShell})
|
||||
return
|
||||
except EOS:
|
||||
nil
|
||||
discard
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ elif sizeof(int) == 8: # 64bit
|
|||
TRaw = range[0..4611686018427387903]
|
||||
## The range of uint values that can be stored directly in a value slot
|
||||
## when on a 64 bit platform
|
||||
else: echo("unsupported platform")
|
||||
else:
|
||||
{.error: "unsupported platform".}
|
||||
|
||||
type
|
||||
TEntry = tuple
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ proc mustRehash(length, counter: int): bool {.inline.} =
|
|||
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
||||
result = ((5 * h) + 1) and maxHash
|
||||
|
||||
proc IntSetGet(t: TIntSet, key: int): PTrunk =
|
||||
proc intSetGet(t: TIntSet, key: int): PTrunk =
|
||||
var h = key and t.max
|
||||
while t.data[h] != nil:
|
||||
if t.data[h].key == key:
|
||||
|
|
@ -58,7 +58,7 @@ proc IntSetGet(t: TIntSet, key: int): PTrunk =
|
|||
h = nextTry(h, t.max)
|
||||
result = nil
|
||||
|
||||
proc IntSetRawInsert(t: TIntSet, data: var TTrunkSeq, desc: PTrunk) =
|
||||
proc intSetRawInsert(t: TIntSet, data: var TTrunkSeq, desc: PTrunk) =
|
||||
var h = desc.key and t.max
|
||||
while data[h] != nil:
|
||||
assert(data[h] != desc)
|
||||
|
|
@ -66,22 +66,22 @@ proc IntSetRawInsert(t: TIntSet, data: var TTrunkSeq, desc: PTrunk) =
|
|||
assert(data[h] == nil)
|
||||
data[h] = desc
|
||||
|
||||
proc IntSetEnlarge(t: var TIntSet) =
|
||||
proc intSetEnlarge(t: var TIntSet) =
|
||||
var n: TTrunkSeq
|
||||
var oldMax = t.max
|
||||
t.max = ((t.max + 1) * 2) - 1
|
||||
newSeq(n, t.max + 1)
|
||||
for i in countup(0, oldmax):
|
||||
if t.data[i] != nil: IntSetRawInsert(t, n, t.data[i])
|
||||
for i in countup(0, oldMax):
|
||||
if t.data[i] != nil: intSetRawInsert(t, n, t.data[i])
|
||||
swap(t.data, n)
|
||||
|
||||
proc IntSetPut(t: var TIntSet, key: int): PTrunk =
|
||||
proc intSetPut(t: var TIntSet, key: int): PTrunk =
|
||||
var h = key and t.max
|
||||
while t.data[h] != nil:
|
||||
if t.data[h].key == key:
|
||||
return t.data[h]
|
||||
h = nextTry(h, t.max)
|
||||
if mustRehash(t.max + 1, t.counter): IntSetEnlarge(t)
|
||||
if mustRehash(t.max + 1, t.counter): intSetEnlarge(t)
|
||||
inc(t.counter)
|
||||
h = key and t.max
|
||||
while t.data[h] != nil: h = nextTry(h, t.max)
|
||||
|
|
@ -94,7 +94,7 @@ proc IntSetPut(t: var TIntSet, key: int): PTrunk =
|
|||
|
||||
proc contains*(s: TIntSet, key: int): bool =
|
||||
## returns true iff `key` is in `s`.
|
||||
var t = IntSetGet(s, `shr`(key, TrunkShift))
|
||||
var t = intSetGet(s, `shr`(key, TrunkShift))
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
|
||||
|
|
@ -103,14 +103,14 @@ proc contains*(s: TIntSet, key: int): bool =
|
|||
|
||||
proc incl*(s: var TIntSet, key: int) =
|
||||
## includes an element `key` in `s`.
|
||||
var t = IntSetPut(s, `shr`(key, TrunkShift))
|
||||
var t = intSetPut(s, `shr`(key, TrunkShift))
|
||||
var u = key and TrunkMask
|
||||
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
|
||||
`shl`(1, u and IntMask)
|
||||
|
||||
proc excl*(s: var TIntSet, key: int) =
|
||||
## excludes `key` from the set `s`.
|
||||
var t = IntSetGet(s, `shr`(key, TrunkShift))
|
||||
var t = intSetGet(s, `shr`(key, TrunkShift))
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] and
|
||||
|
|
@ -119,7 +119,7 @@ proc excl*(s: var TIntSet, key: int) =
|
|||
proc containsOrIncl*(s: var TIntSet, key: int): bool =
|
||||
## returns true if `s` contains `key`, otherwise `key` is included in `s`
|
||||
## and false is returned.
|
||||
var t = IntSetGet(s, `shr`(key, TrunkShift))
|
||||
var t = intSetGet(s, `shr`(key, TrunkShift))
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
|
||||
|
|
|
|||
|
|
@ -41,19 +41,19 @@ type
|
|||
|
||||
proc initSinglyLinkedList*[T](): TSinglyLinkedList[T] =
|
||||
## creates a new singly linked list that is empty.
|
||||
nil
|
||||
discard
|
||||
|
||||
proc initDoublyLinkedList*[T](): TDoublyLinkedList[T] =
|
||||
## creates a new doubly linked list that is empty.
|
||||
nil
|
||||
discard
|
||||
|
||||
proc initSinglyLinkedRing*[T](): TSinglyLinkedRing[T] =
|
||||
## creates a new singly linked ring that is empty.
|
||||
nil
|
||||
discard
|
||||
|
||||
proc initDoublyLinkedRing*[T](): TDoublyLinkedRing[T] =
|
||||
## creates a new doubly linked ring that is empty.
|
||||
nil
|
||||
discard
|
||||
|
||||
proc newDoublyLinkedNode*[T](value: T): PDoublyLinkedNode[T] =
|
||||
## creates a new doubly linked node with the given `value`.
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ proc delete*[T](s: var seq[T], first=0, last=0) =
|
|||
s[i].shallowCopy(s[j])
|
||||
inc(i)
|
||||
inc(j)
|
||||
setlen(s, newLen)
|
||||
setLen(s, newLen)
|
||||
|
||||
proc insert*[T](dest: var seq[T], src: openArray[T], pos=0) =
|
||||
## Inserts items from `src` into `dest` at position `pos`. This modifies
|
||||
|
|
|
|||
|
|
@ -65,38 +65,38 @@ template rawInsertImpl() {.dirty.} =
|
|||
data[h].key = key
|
||||
data[h].slot = seFilled
|
||||
|
||||
proc RawGet[A](s: TSet[A], key: A): int =
|
||||
proc rawGet[A](s: TSet[A], key: A): int =
|
||||
rawGetImpl()
|
||||
|
||||
proc contains*[A](s: TSet[A], key: A): bool =
|
||||
## returns true iff `key` is in `s`.
|
||||
var index = RawGet(s, key)
|
||||
var index = rawGet(s, key)
|
||||
result = index >= 0
|
||||
|
||||
proc RawInsert[A](s: var TSet[A], data: var TKeyValuePairSeq[A], key: A) =
|
||||
proc rawInsert[A](s: var TSet[A], data: var TKeyValuePairSeq[A], key: A) =
|
||||
rawInsertImpl()
|
||||
|
||||
proc Enlarge[A](s: var TSet[A]) =
|
||||
proc enlarge[A](s: var TSet[A]) =
|
||||
var n: TKeyValuePairSeq[A]
|
||||
newSeq(n, len(s.data) * growthFactor)
|
||||
for i in countup(0, high(s.data)):
|
||||
if s.data[i].slot == seFilled: RawInsert(s, n, s.data[i].key)
|
||||
if s.data[i].slot == seFilled: rawInsert(s, n, s.data[i].key)
|
||||
swap(s.data, n)
|
||||
|
||||
template inclImpl() {.dirty.} =
|
||||
var index = RawGet(s, key)
|
||||
var index = rawGet(s, key)
|
||||
if index < 0:
|
||||
if mustRehash(len(s.data), s.counter): Enlarge(s)
|
||||
RawInsert(s, s.data, key)
|
||||
if mustRehash(len(s.data), s.counter): enlarge(s)
|
||||
rawInsert(s, s.data, key)
|
||||
inc(s.counter)
|
||||
|
||||
template containsOrInclImpl() {.dirty.} =
|
||||
var index = RawGet(s, key)
|
||||
var index = rawGet(s, key)
|
||||
if index >= 0:
|
||||
result = true
|
||||
else:
|
||||
if mustRehash(len(s.data), s.counter): Enlarge(s)
|
||||
RawInsert(s, s.data, key)
|
||||
if mustRehash(len(s.data), s.counter): enlarge(s)
|
||||
rawInsert(s, s.data, key)
|
||||
inc(s.counter)
|
||||
|
||||
proc incl*[A](s: var TSet[A], key: A) =
|
||||
|
|
@ -105,7 +105,7 @@ proc incl*[A](s: var TSet[A], key: A) =
|
|||
|
||||
proc excl*[A](s: var TSet[A], key: A) =
|
||||
## excludes `key` from the set `s`.
|
||||
var index = RawGet(s, key)
|
||||
var index = rawGet(s, key)
|
||||
if index >= 0:
|
||||
s.data[index].slot = seDeleted
|
||||
dec(s.counter)
|
||||
|
|
@ -122,7 +122,7 @@ proc initSet*[A](initialSize=64): TSet[A] =
|
|||
result.counter = 0
|
||||
newSeq(result.data, initialSize)
|
||||
|
||||
proc toSet*[A](keys: openarray[A]): TSet[A] =
|
||||
proc toSet*[A](keys: openArray[A]): TSet[A] =
|
||||
## creates a new hash set that contains the given `keys`.
|
||||
result = initSet[A](nextPowerOfTwo(keys.len+10))
|
||||
for key in items(keys): result.incl(key)
|
||||
|
|
@ -169,15 +169,15 @@ iterator items*[A](s: TOrderedSet[A]): A =
|
|||
forAllOrderedPairs:
|
||||
yield s.data[h].key
|
||||
|
||||
proc RawGet[A](s: TOrderedSet[A], key: A): int =
|
||||
proc rawGet[A](s: TOrderedSet[A], key: A): int =
|
||||
rawGetImpl()
|
||||
|
||||
proc contains*[A](s: TOrderedSet[A], key: A): bool =
|
||||
## returns true iff `key` is in `s`.
|
||||
var index = RawGet(s, key)
|
||||
var index = rawGet(s, key)
|
||||
result = index >= 0
|
||||
|
||||
proc RawInsert[A](s: var TOrderedSet[A],
|
||||
proc rawInsert[A](s: var TOrderedSet[A],
|
||||
data: var TOrderedKeyValuePairSeq[A], key: A) =
|
||||
rawInsertImpl()
|
||||
data[h].next = -1
|
||||
|
|
@ -185,7 +185,7 @@ proc RawInsert[A](s: var TOrderedSet[A],
|
|||
if s.last >= 0: data[s.last].next = h
|
||||
s.last = h
|
||||
|
||||
proc Enlarge[A](s: var TOrderedSet[A]) =
|
||||
proc enlarge[A](s: var TOrderedSet[A]) =
|
||||
var n: TOrderedKeyValuePairSeq[A]
|
||||
newSeq(n, len(s.data) * growthFactor)
|
||||
var h = s.first
|
||||
|
|
@ -194,7 +194,7 @@ proc Enlarge[A](s: var TOrderedSet[A]) =
|
|||
while h >= 0:
|
||||
var nxt = s.data[h].next
|
||||
if s.data[h].slot == seFilled:
|
||||
RawInsert(s, n, s.data[h].key)
|
||||
rawInsert(s, n, s.data[h].key)
|
||||
h = nxt
|
||||
swap(s.data, n)
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ proc initOrderedSet*[A](initialSize=64): TOrderedSet[A] =
|
|||
result.last = -1
|
||||
newSeq(result.data, initialSize)
|
||||
|
||||
proc toOrderedSet*[A](keys: openarray[A]): TOrderedSet[A] =
|
||||
proc toOrderedSet*[A](keys: openArray[A]): TOrderedSet[A] =
|
||||
## creates a new ordered hash set that contains the given `keys`.
|
||||
result = initOrderedSet[A](nextPowerOfTwo(keys.len+10))
|
||||
for key in items(keys): result.incl(key)
|
||||
|
|
@ -224,5 +224,3 @@ proc toOrderedSet*[A](keys: openarray[A]): TOrderedSet[A] =
|
|||
proc `$`*[A](s: TOrderedSet[A]): string =
|
||||
## The `$` operator for ordered hash sets.
|
||||
dollarImpl()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ template rawInsertImpl() {.dirty.} =
|
|||
data[h].val = val
|
||||
data[h].slot = seFilled
|
||||
|
||||
proc RawGet[A, B](t: TTable[A, B], key: A): int =
|
||||
proc rawGet[A, B](t: TTable[A, B], key: A): int =
|
||||
rawGetImpl()
|
||||
|
||||
proc `[]`*[A, B](t: TTable[A, B], key: A): B =
|
||||
|
|
@ -93,13 +93,13 @@ proc `[]`*[A, B](t: TTable[A, B], key: A): B =
|
|||
## default empty value for the type `B` is returned
|
||||
## and no exception is raised. One can check with ``hasKey`` whether the key
|
||||
## exists.
|
||||
var index = RawGet(t, key)
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0: result = t.data[index].val
|
||||
|
||||
proc mget*[A, B](t: var TTable[A, B], key: A): var B =
|
||||
## retrieves the value at ``t[key]``. The value can be modified.
|
||||
## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
|
||||
var index = RawGet(t, key)
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0: result = t.data[index].val
|
||||
else: raise newException(EInvalidKey, "key not found: " & $key)
|
||||
|
||||
|
|
@ -107,39 +107,39 @@ proc hasKey*[A, B](t: TTable[A, B], key: A): bool =
|
|||
## returns true iff `key` is in the table `t`.
|
||||
result = rawGet(t, key) >= 0
|
||||
|
||||
proc RawInsert[A, B](t: var TTable[A, B], data: var TKeyValuePairSeq[A, B],
|
||||
proc rawInsert[A, B](t: var TTable[A, B], data: var TKeyValuePairSeq[A, B],
|
||||
key: A, val: B) =
|
||||
rawInsertImpl()
|
||||
|
||||
proc Enlarge[A, B](t: var TTable[A, B]) =
|
||||
proc enlarge[A, B](t: var TTable[A, B]) =
|
||||
var n: TKeyValuePairSeq[A, B]
|
||||
newSeq(n, len(t.data) * growthFactor)
|
||||
for i in countup(0, high(t.data)):
|
||||
if t.data[i].slot == seFilled: RawInsert(t, n, t.data[i].key, t.data[i].val)
|
||||
if t.data[i].slot == seFilled: rawInsert(t, n, t.data[i].key, t.data[i].val)
|
||||
swap(t.data, n)
|
||||
|
||||
template AddImpl() {.dirty.} =
|
||||
if mustRehash(len(t.data), t.counter): Enlarge(t)
|
||||
RawInsert(t, t.data, key, val)
|
||||
template addImpl() {.dirty.} =
|
||||
if mustRehash(len(t.data), t.counter): enlarge(t)
|
||||
rawInsert(t, t.data, key, val)
|
||||
inc(t.counter)
|
||||
|
||||
template PutImpl() {.dirty.} =
|
||||
var index = RawGet(t, key)
|
||||
template putImpl() {.dirty.} =
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0:
|
||||
t.data[index].val = val
|
||||
else:
|
||||
AddImpl()
|
||||
addImpl()
|
||||
|
||||
when false:
|
||||
# not yet used:
|
||||
template HasKeyOrPutImpl() {.dirty.} =
|
||||
var index = RawGet(t, key)
|
||||
template hasKeyOrPutImpl() {.dirty.} =
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0:
|
||||
t.data[index].val = val
|
||||
result = true
|
||||
else:
|
||||
if mustRehash(len(t.data), t.counter): Enlarge(t)
|
||||
RawInsert(t, t.data, key, val)
|
||||
if mustRehash(len(t.data), t.counter): enlarge(t)
|
||||
rawInsert(t, t.data, key, val)
|
||||
inc(t.counter)
|
||||
result = false
|
||||
|
||||
|
|
@ -149,11 +149,11 @@ proc `[]=`*[A, B](t: var TTable[A, B], key: A, val: B) =
|
|||
|
||||
proc add*[A, B](t: var TTable[A, B], key: A, val: B) =
|
||||
## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.
|
||||
AddImpl()
|
||||
addImpl()
|
||||
|
||||
proc del*[A, B](t: var TTable[A, B], key: A) =
|
||||
## deletes `key` from hash table `t`.
|
||||
var index = RawGet(t, key)
|
||||
let index = rawGet(t, key)
|
||||
if index >= 0:
|
||||
t.data[index].slot = seDeleted
|
||||
dec(t.counter)
|
||||
|
|
@ -168,7 +168,7 @@ proc initTable*[A, B](initialSize=64): TTable[A, B] =
|
|||
result.counter = 0
|
||||
newSeq(result.data, initialSize)
|
||||
|
||||
proc toTable*[A, B](pairs: openarray[tuple[key: A,
|
||||
proc toTable*[A, B](pairs: openArray[tuple[key: A,
|
||||
val: B]]): TTable[A, B] =
|
||||
## creates a new hash table that contains the given `pairs`.
|
||||
result = initTable[A, B](nextPowerOfTwo(pairs.len+10))
|
||||
|
|
@ -240,7 +240,7 @@ iterator mvalues*[A, B](t: var TOrderedTable[A, B]): var B =
|
|||
forAllOrderedPairs:
|
||||
yield t.data[h].val
|
||||
|
||||
proc RawGet[A, B](t: TOrderedTable[A, B], key: A): int =
|
||||
proc rawGet[A, B](t: TOrderedTable[A, B], key: A): int =
|
||||
rawGetImpl()
|
||||
|
||||
proc `[]`*[A, B](t: TOrderedTable[A, B], key: A): B =
|
||||
|
|
@ -248,13 +248,13 @@ proc `[]`*[A, B](t: TOrderedTable[A, B], key: A): B =
|
|||
## default empty value for the type `B` is returned
|
||||
## and no exception is raised. One can check with ``hasKey`` whether the key
|
||||
## exists.
|
||||
var index = RawGet(t, key)
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0: result = t.data[index].val
|
||||
|
||||
proc mget*[A, B](t: var TOrderedTable[A, B], key: A): var B =
|
||||
## retrieves the value at ``t[key]``. The value can be modified.
|
||||
## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
|
||||
var index = RawGet(t, key)
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0: result = t.data[index].val
|
||||
else: raise newException(EInvalidKey, "key not found: " & $key)
|
||||
|
||||
|
|
@ -262,7 +262,7 @@ proc hasKey*[A, B](t: TOrderedTable[A, B], key: A): bool =
|
|||
## returns true iff `key` is in the table `t`.
|
||||
result = rawGet(t, key) >= 0
|
||||
|
||||
proc RawInsert[A, B](t: var TOrderedTable[A, B],
|
||||
proc rawInsert[A, B](t: var TOrderedTable[A, B],
|
||||
data: var TOrderedKeyValuePairSeq[A, B],
|
||||
key: A, val: B) =
|
||||
rawInsertImpl()
|
||||
|
|
@ -271,7 +271,7 @@ proc RawInsert[A, B](t: var TOrderedTable[A, B],
|
|||
if t.last >= 0: data[t.last].next = h
|
||||
t.last = h
|
||||
|
||||
proc Enlarge[A, B](t: var TOrderedTable[A, B]) =
|
||||
proc enlarge[A, B](t: var TOrderedTable[A, B]) =
|
||||
var n: TOrderedKeyValuePairSeq[A, B]
|
||||
newSeq(n, len(t.data) * growthFactor)
|
||||
var h = t.first
|
||||
|
|
@ -280,7 +280,7 @@ proc Enlarge[A, B](t: var TOrderedTable[A, B]) =
|
|||
while h >= 0:
|
||||
var nxt = t.data[h].next
|
||||
if t.data[h].slot == seFilled:
|
||||
RawInsert(t, n, t.data[h].key, t.data[h].val)
|
||||
rawInsert(t, n, t.data[h].key, t.data[h].val)
|
||||
h = nxt
|
||||
swap(t.data, n)
|
||||
|
||||
|
|
@ -290,7 +290,7 @@ proc `[]=`*[A, B](t: var TOrderedTable[A, B], key: A, val: B) =
|
|||
|
||||
proc add*[A, B](t: var TOrderedTable[A, B], key: A, val: B) =
|
||||
## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists.
|
||||
AddImpl()
|
||||
addImpl()
|
||||
|
||||
proc initOrderedTable*[A, B](initialSize=64): TOrderedTable[A, B] =
|
||||
## creates a new ordered hash table that is empty.
|
||||
|
|
@ -304,7 +304,7 @@ proc initOrderedTable*[A, B](initialSize=64): TOrderedTable[A, B] =
|
|||
result.last = -1
|
||||
newSeq(result.data, initialSize)
|
||||
|
||||
proc toOrderedTable*[A, B](pairs: openarray[tuple[key: A,
|
||||
proc toOrderedTable*[A, B](pairs: openArray[tuple[key: A,
|
||||
val: B]]): TOrderedTable[A, B] =
|
||||
## creates a new ordered hash table that contains the given `pairs`.
|
||||
result = initOrderedTable[A, B](nextPowerOfTwo(pairs.len+10))
|
||||
|
|
@ -398,7 +398,7 @@ iterator mvalues*[A](t: TCountTable[A]): var int =
|
|||
for h in 0..high(t.data):
|
||||
if t.data[h].val != 0: yield t.data[h].val
|
||||
|
||||
proc RawGet[A](t: TCountTable[A], key: A): int =
|
||||
proc rawGet[A](t: TCountTable[A], key: A): int =
|
||||
var h: THash = hash(key) and high(t.data) # start with real hash value
|
||||
while t.data[h].val != 0:
|
||||
if t.data[h].key == key: return h
|
||||
|
|
@ -409,13 +409,13 @@ proc `[]`*[A](t: TCountTable[A], key: A): int =
|
|||
## retrieves the value at ``t[key]``. If `key` is not in `t`,
|
||||
## 0 is returned. One can check with ``hasKey`` whether the key
|
||||
## exists.
|
||||
var index = RawGet(t, key)
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0: result = t.data[index].val
|
||||
|
||||
proc mget*[A](t: var TCountTable[A], key: A): var int =
|
||||
## retrieves the value at ``t[key]``. The value can be modified.
|
||||
## If `key` is not in `t`, the ``EInvalidKey`` exception is raised.
|
||||
var index = RawGet(t, key)
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0: result = t.data[index].val
|
||||
else: raise newException(EInvalidKey, "key not found: " & $key)
|
||||
|
||||
|
|
@ -423,24 +423,24 @@ proc hasKey*[A](t: TCountTable[A], key: A): bool =
|
|||
## returns true iff `key` is in the table `t`.
|
||||
result = rawGet(t, key) >= 0
|
||||
|
||||
proc RawInsert[A](t: TCountTable[A], data: var seq[tuple[key: A, val: int]],
|
||||
proc rawInsert[A](t: TCountTable[A], data: var seq[tuple[key: A, val: int]],
|
||||
key: A, val: int) =
|
||||
var h: THash = hash(key) and high(data)
|
||||
while data[h].val != 0: h = nextTry(h, high(data))
|
||||
data[h].key = key
|
||||
data[h].val = val
|
||||
|
||||
proc Enlarge[A](t: var TCountTable[A]) =
|
||||
proc enlarge[A](t: var TCountTable[A]) =
|
||||
var n: seq[tuple[key: A, val: int]]
|
||||
newSeq(n, len(t.data) * growthFactor)
|
||||
for i in countup(0, high(t.data)):
|
||||
if t.data[i].val != 0: RawInsert(t, n, t.data[i].key, t.data[i].val)
|
||||
if t.data[i].val != 0: rawInsert(t, n, t.data[i].key, t.data[i].val)
|
||||
swap(t.data, n)
|
||||
|
||||
proc `[]=`*[A](t: var TCountTable[A], key: A, val: int) =
|
||||
## puts a (key, value)-pair into `t`. `val` has to be positive.
|
||||
assert val > 0
|
||||
PutImpl()
|
||||
putImpl()
|
||||
|
||||
proc initCountTable*[A](initialSize=64): TCountTable[A] =
|
||||
## creates a new count table that is empty.
|
||||
|
|
@ -463,15 +463,15 @@ proc `$`*[A](t: TCountTable[A]): string =
|
|||
|
||||
proc inc*[A](t: var TCountTable[A], key: A, val = 1) =
|
||||
## increments `t[key]` by `val`.
|
||||
var index = RawGet(t, key)
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0:
|
||||
inc(t.data[index].val, val)
|
||||
else:
|
||||
if mustRehash(len(t.data), t.counter): Enlarge(t)
|
||||
RawInsert(t, t.data, key, val)
|
||||
if mustRehash(len(t.data), t.counter): enlarge(t)
|
||||
rawInsert(t, t.data, key, val)
|
||||
inc(t.counter)
|
||||
|
||||
proc Smallest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
|
||||
proc smallest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
|
||||
## returns the largest (key,val)-pair. Efficiency: O(n)
|
||||
assert t.len > 0
|
||||
var minIdx = 0
|
||||
|
|
@ -480,7 +480,7 @@ proc Smallest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
|
|||
result.key = t.data[minIdx].key
|
||||
result.val = t.data[minIdx].val
|
||||
|
||||
proc Largest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
|
||||
proc largest*[A](t: TCountTable[A]): tuple[key: A, val: int] =
|
||||
## returns the (key,val)-pair with the largest `val`. Efficiency: O(n)
|
||||
assert t.len > 0
|
||||
var maxIdx = 0
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
# (c) Copyright 2014 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -14,21 +14,21 @@ import os, parseutils, strutils
|
|||
|
||||
when not defined(windows):
|
||||
type
|
||||
TConverter = object {.pure, final.}
|
||||
TConverter = object
|
||||
PConverter* = ptr TConverter ## can convert between two character sets
|
||||
|
||||
|
||||
else:
|
||||
type
|
||||
TCodePage = distinct int32
|
||||
PConverter* = object {.pure.}
|
||||
PConverter* = object
|
||||
dest, src: TCodePage
|
||||
|
||||
|
||||
type
|
||||
EInvalidEncoding* = object of EInvalidValue ## exception that is raised
|
||||
## for encoding errors
|
||||
|
||||
when defined(windows):
|
||||
proc EqEncodingNames(a, b: string): bool =
|
||||
proc eqEncodingNames(a, b: string): bool =
|
||||
var i = 0
|
||||
var j = 0
|
||||
while i < a.len and j < b.len:
|
||||
|
|
@ -208,31 +208,31 @@ when defined(windows):
|
|||
when false:
|
||||
# not needed yet:
|
||||
type
|
||||
TCpInfo = object {.pure.}
|
||||
MaxCharSize: int32
|
||||
DefaultChar: array[0..1, char]
|
||||
LeadByte: array[0..12-1, char]
|
||||
TCpInfo = object
|
||||
maxCharSize: int32
|
||||
defaultChar: array[0..1, char]
|
||||
leadByte: array[0..12-1, char]
|
||||
|
||||
proc GetCPInfo(CodePage: TCodePage, lpCPInfo: var TCpInfo): int32 {.
|
||||
proc getCPInfo(codePage: TCodePage, lpCPInfo: var TCpInfo): int32 {.
|
||||
stdcall, importc: "GetCPInfo", dynlib: "kernel32".}
|
||||
|
||||
proc nameToCodePage(name: string): TCodePage =
|
||||
var nameAsInt: int
|
||||
if parseInt(name, nameAsInt) == 0: nameAsInt = -1
|
||||
for no, na in items(winEncodings):
|
||||
if no == nameAsInt or EqEncodingNames(na, name): return TCodePage(no)
|
||||
if no == nameAsInt or eqEncodingNames(na, name): return TCodePage(no)
|
||||
result = TCodePage(-1)
|
||||
|
||||
proc codePageToName(c: TCodePage): string =
|
||||
for no, na in items(winEncodings):
|
||||
if no == int(c):
|
||||
if no == int(c):
|
||||
return if na.len != 0: na else: $no
|
||||
result = ""
|
||||
|
||||
proc GetACP(): TCodePage {.stdcall, importc: "GetACP", dynlib: "kernel32".}
|
||||
proc getACP(): TCodePage {.stdcall, importc: "GetACP", dynlib: "kernel32".}
|
||||
|
||||
proc MultiByteToWideChar(
|
||||
CodePage: TCodePage,
|
||||
proc multiByteToWideChar(
|
||||
codePage: TCodePage,
|
||||
dwFlags: int32,
|
||||
lpMultiByteStr: cstring,
|
||||
cbMultiByte: cint,
|
||||
|
|
@ -240,8 +240,8 @@ when defined(windows):
|
|||
cchWideChar: cint): cint {.
|
||||
stdcall, importc: "MultiByteToWideChar", dynlib: "kernel32".}
|
||||
|
||||
proc WideCharToMultiByte(
|
||||
CodePage: TCodePage,
|
||||
proc wideCharToMultiByte(
|
||||
codePage: TCodePage,
|
||||
dwFlags: int32,
|
||||
lpWideCharStr: cstring,
|
||||
cchWideChar: cint,
|
||||
|
|
@ -321,7 +321,6 @@ proc close*(c: PConverter) =
|
|||
iconvClose(c)
|
||||
|
||||
when defined(windows):
|
||||
|
||||
proc convert*(c: PConverter, s: string): string =
|
||||
## converts `s` to `destEncoding` that was given to the converter `c`. It
|
||||
## assumed that `s` is in `srcEncoding`.
|
||||
|
|
@ -333,26 +332,26 @@ when defined(windows):
|
|||
var cap = s.len + s.len shr 2
|
||||
result = newStringOfCap(cap*2)
|
||||
# convert to utf-16 LE
|
||||
var m = MultiByteToWideChar(CodePage = c.src, dwFlags = 0'i32,
|
||||
var m = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32,
|
||||
lpMultiByteStr = cstring(s),
|
||||
cbMultiByte = cint(s.len),
|
||||
lpWideCharStr = cstring(result),
|
||||
cchWideChar = cint(cap))
|
||||
if m == 0:
|
||||
# try again; ask for capacity:
|
||||
cap = MultiByteToWideChar(CodePage = c.src, dwFlags = 0'i32,
|
||||
cap = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32,
|
||||
lpMultiByteStr = cstring(s),
|
||||
cbMultiByte = cint(s.len),
|
||||
lpWideCharStr = nil,
|
||||
cchWideChar = cint(0))
|
||||
# and do the conversion properly:
|
||||
result = newStringOfCap(cap*2)
|
||||
m = MultiByteToWideChar(CodePage = c.src, dwFlags = 0'i32,
|
||||
m = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32,
|
||||
lpMultiByteStr = cstring(s),
|
||||
cbMultiByte = cint(s.len),
|
||||
lpWideCharStr = cstring(result),
|
||||
cchWideChar = cint(cap))
|
||||
if m == 0: OSError()
|
||||
if m == 0: osError(osLastError())
|
||||
setLen(result, m*2)
|
||||
elif m <= cap:
|
||||
setLen(result, m*2)
|
||||
|
|
@ -364,8 +363,8 @@ when defined(windows):
|
|||
# otherwise the fun starts again:
|
||||
cap = s.len + s.len shr 2
|
||||
var res = newStringOfCap(cap)
|
||||
m = WideCharToMultiByte(
|
||||
CodePage = c.dest,
|
||||
m = wideCharToMultiByte(
|
||||
codePage = c.dest,
|
||||
dwFlags = 0'i32,
|
||||
lpWideCharStr = cstring(result),
|
||||
cchWideChar = cint(result.len div 2),
|
||||
|
|
@ -373,8 +372,8 @@ when defined(windows):
|
|||
cbMultiByte = cap.cint)
|
||||
if m == 0:
|
||||
# try again; ask for capacity:
|
||||
cap = WideCharToMultiByte(
|
||||
CodePage = c.dest,
|
||||
cap = wideCharToMultiByte(
|
||||
codePage = c.dest,
|
||||
dwFlags = 0'i32,
|
||||
lpWideCharStr = cstring(result),
|
||||
cchWideChar = cint(result.len div 2),
|
||||
|
|
@ -382,14 +381,14 @@ when defined(windows):
|
|||
cbMultiByte = cint(0))
|
||||
# and do the conversion properly:
|
||||
res = newStringOfCap(cap)
|
||||
m = WideCharToMultiByte(
|
||||
CodePage = c.dest,
|
||||
m = wideCharToMultiByte(
|
||||
codePage = c.dest,
|
||||
dwFlags = 0'i32,
|
||||
lpWideCharStr = cstring(result),
|
||||
cchWideChar = cint(result.len div 2),
|
||||
lpMultiByteStr = cstring(res),
|
||||
cbMultiByte = cap.cint)
|
||||
if m == 0: OSError()
|
||||
if m == 0: osError(osLastError())
|
||||
setLen(res, m)
|
||||
result = res
|
||||
elif m <= cap:
|
||||
|
|
@ -399,15 +398,14 @@ when defined(windows):
|
|||
assert(false) # cannot happen
|
||||
|
||||
else:
|
||||
|
||||
proc convert*(c: PConverter, s: string): string =
|
||||
result = newString(s.len)
|
||||
var inLen = len(S)
|
||||
var inLen = len(s)
|
||||
var outLen = len(result)
|
||||
var src = cstring(S)
|
||||
var src = cstring(s)
|
||||
var dst = cstring(result)
|
||||
var iconvres: int
|
||||
while InLen > 0:
|
||||
while inLen > 0:
|
||||
iconvres = iconv(c, src, inLen, dst, outLen)
|
||||
if iconvres == -1:
|
||||
var lerr = errno
|
||||
|
|
@ -425,11 +423,11 @@ else:
|
|||
dst = cast[cstring](cast[int](cstring(result)) + offset)
|
||||
outLen = len(result) - offset
|
||||
else:
|
||||
OSError()
|
||||
osError(lerr.TOSErrorCode)
|
||||
# iconv has a buffer that needs flushing, specially if the last char is
|
||||
# not '\0'
|
||||
discard iconv(c, nil, nil, dst, outlen)
|
||||
if iconvres == Cint(-1) and errno == E2BIG:
|
||||
if iconvres == cint(-1) and errno == E2BIG:
|
||||
var offset = cast[int](dst) - cast[int](cstring(result))
|
||||
setLen(result, len(result)+inLen*2+5)
|
||||
# 5 is minimally one utf-8 char
|
||||
|
|
@ -450,7 +448,7 @@ proc convert*(s: string, destEncoding = "UTF-8",
|
|||
finally:
|
||||
close(c)
|
||||
|
||||
when IsMainModule:
|
||||
when isMainModule:
|
||||
let
|
||||
orig = "öäüß"
|
||||
cp1252 = convert(orig, "CP1252", "UTF-8")
|
||||
|
|
|
|||
|
|
@ -34,14 +34,26 @@ proc swapEndian32*(outp, inp: pointer) =
|
|||
o[2] = i[1]
|
||||
o[3] = i[0]
|
||||
|
||||
proc swapEndian16*(outp, inp: pointer) =
|
||||
## copies `inp` to `outp` swapping bytes. Both buffers are supposed to
|
||||
## contain at least 2 bytes.
|
||||
var
|
||||
i = cast[cstring](inp)
|
||||
o = cast[cstring](outp)
|
||||
o[0] = i[1]
|
||||
o[1] = i[0]
|
||||
|
||||
when system.cpuEndian == bigEndian:
|
||||
proc littleEndian64*(outp, inp: pointer) {.inline.} = swapEndian64(outp, inp)
|
||||
proc littleEndian32*(outp, inp: pointer) {.inline.} = swapEndian32(outp, inp)
|
||||
proc littleEndian16*(outp, inp: pointer) {.inline.} = swapEndian16(outp, inp)
|
||||
proc bigEndian64*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 8)
|
||||
proc bigEndian32*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 4)
|
||||
proc bigEndian16*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 2)
|
||||
else:
|
||||
proc littleEndian64*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 8)
|
||||
proc littleEndian32*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 4)
|
||||
proc littleEndian16*(outp, inp: pointer){.inline.} = copyMem(outp, inp, 2)
|
||||
proc bigEndian64*(outp, inp: pointer) {.inline.} = swapEndian64(outp, inp)
|
||||
proc bigEndian32*(outp, inp: pointer) {.inline.} = swapEndian32(outp, inp)
|
||||
|
||||
proc bigEndian16*(outp, inp: pointer) {.inline.} = swapEndian16(outp, inp)
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ type
|
|||
EInvalidReply* = object of ESynch
|
||||
EFTP* = object of ESynch
|
||||
|
||||
proc FTPClient*(address: string, port = TPort(21),
|
||||
proc ftpClient*(address: string, port = TPort(21),
|
||||
user, pass = ""): PFTPClient =
|
||||
## Create a ``PFTPClient`` object.
|
||||
new(result)
|
||||
|
|
@ -298,7 +298,7 @@ proc getLines(ftp: PFTPClient, async: bool = false): bool =
|
|||
var readSocks: seq[TSocket] = @[ftp.getCSock()]
|
||||
# This is only needed here. Asyncio gets this socket...
|
||||
blockingOperation(ftp.getCSock()):
|
||||
if readSocks.select(1) != 0 and ftp.getCSock() notin readSocks:
|
||||
if readSocks.select(1) != 0 and ftp.getCSock() in readSocks:
|
||||
assertReply ftp.expectReply(), "226"
|
||||
return true
|
||||
|
||||
|
|
@ -315,7 +315,7 @@ proc listDirs*(ftp: PFTPClient, dir: string = "",
|
|||
assertReply ftp.send("NLST " & dir.normalizePathSep), ["125", "150"]
|
||||
|
||||
if not async:
|
||||
while not ftp.job.prc(ftp, false): nil
|
||||
while not ftp.job.prc(ftp, false): discard
|
||||
result = splitLines(ftp.job.lines)
|
||||
ftp.deleteJob()
|
||||
else: return @[]
|
||||
|
|
@ -390,7 +390,7 @@ proc list*(ftp: PFTPClient, dir: string = "", async = false): string =
|
|||
assertReply(ftp.send("LIST" & " " & dir.normalizePathSep), ["125", "150"])
|
||||
|
||||
if not async:
|
||||
while not ftp.job.prc(ftp, false): nil
|
||||
while not ftp.job.prc(ftp, false): discard
|
||||
result = ftp.job.lines
|
||||
ftp.deleteJob()
|
||||
else:
|
||||
|
|
@ -405,7 +405,7 @@ proc retrText*(ftp: PFTPClient, file: string, async = false): string =
|
|||
assertReply ftp.send("RETR " & file.normalizePathSep), ["125", "150"]
|
||||
|
||||
if not async:
|
||||
while not ftp.job.prc(ftp, false): nil
|
||||
while not ftp.job.prc(ftp, false): discard
|
||||
result = ftp.job.lines
|
||||
ftp.deleteJob()
|
||||
else:
|
||||
|
|
@ -434,7 +434,7 @@ proc getFile(ftp: PFTPClient, async = false): bool =
|
|||
if not async:
|
||||
var readSocks: seq[TSocket] = @[ftp.getCSock()]
|
||||
blockingOperation(ftp.getCSock()):
|
||||
if readSocks.select(1) != 0 and ftp.getCSock() notin readSocks:
|
||||
if readSocks.select(1) != 0 and ftp.getCSock() in readSocks:
|
||||
assertReply ftp.expectReply(), "226"
|
||||
return true
|
||||
|
||||
|
|
@ -460,7 +460,7 @@ proc retrFile*(ftp: PFTPClient, file, dest: string, async = false) =
|
|||
ftp.job.filename = file.normalizePathSep
|
||||
|
||||
if not async:
|
||||
while not ftp.job.prc(ftp, false): nil
|
||||
while not ftp.job.prc(ftp, false): discard
|
||||
ftp.deleteJob()
|
||||
|
||||
proc doUpload(ftp: PFTPClient, async = false): bool =
|
||||
|
|
@ -518,7 +518,7 @@ proc store*(ftp: PFTPClient, file, dest: string, async = false) =
|
|||
assertReply ftp.send("STOR " & dest.normalizePathSep), ["125", "150"]
|
||||
|
||||
if not async:
|
||||
while not ftp.job.prc(ftp, false): nil
|
||||
while not ftp.job.prc(ftp, false): discard
|
||||
ftp.deleteJob()
|
||||
|
||||
proc close*(ftp: PFTPClient) =
|
||||
|
|
@ -554,10 +554,10 @@ proc csockHandleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) =
|
|||
|
||||
ftp.handleEvent(ftp, r)
|
||||
|
||||
proc AsyncFTPClient*(address: string, port = TPort(21),
|
||||
proc asyncFTPClient*(address: string, port = TPort(21),
|
||||
user, pass = "",
|
||||
handleEvent: proc (ftp: PAsyncFTPClient, ev: TFTPEvent) {.closure.} =
|
||||
(proc (ftp: PAsyncFTPClient, ev: TFTPEvent) = nil)): PAsyncFTPClient =
|
||||
(proc (ftp: PAsyncFTPClient, ev: TFTPEvent) = discard)): PAsyncFTPClient =
|
||||
## Create a ``PAsyncFTPClient`` object.
|
||||
##
|
||||
## Use this if you want to use asyncio's dispatcher.
|
||||
|
|
@ -604,7 +604,7 @@ when isMainModule:
|
|||
ftp.close()
|
||||
echo d.len
|
||||
else: assert(false)
|
||||
var ftp = AsyncFTPClient("picheta.me", user = "test", pass = "asf", handleEvent = hev)
|
||||
var ftp = asyncFTPClient("picheta.me", user = "test", pass = "asf", handleEvent = hev)
|
||||
|
||||
d.register(ftp)
|
||||
d.len.echo()
|
||||
|
|
@ -618,7 +618,7 @@ when isMainModule:
|
|||
|
||||
|
||||
when isMainModule and false:
|
||||
var ftp = FTPClient("picheta.me", user = "asdasd", pass = "asfwq")
|
||||
var ftp = ftpClient("picheta.me", user = "asdasd", pass = "asfwq")
|
||||
ftp.connect()
|
||||
echo ftp.pwd()
|
||||
echo ftp.list()
|
||||
|
|
|
|||
|
|
@ -32,26 +32,26 @@ proc `!$`*(h: THash): THash {.inline.} =
|
|||
result = result xor (result shr 11)
|
||||
result = result +% result shl 15
|
||||
|
||||
proc hashData*(Data: Pointer, Size: int): THash =
|
||||
proc hashData*(data: pointer, size: int): THash =
|
||||
## hashes an array of bytes of size `size`
|
||||
var h: THash = 0
|
||||
when defined(js):
|
||||
var p: cstring
|
||||
asm """`p` = `Data`;"""
|
||||
else:
|
||||
var p = cast[cstring](Data)
|
||||
var p = cast[cstring](data)
|
||||
var i = 0
|
||||
var s = size
|
||||
while s > 0:
|
||||
h = h !& ord(p[i])
|
||||
Inc(i)
|
||||
Dec(s)
|
||||
inc(i)
|
||||
dec(s)
|
||||
result = !$h
|
||||
|
||||
when defined(js):
|
||||
var objectID = 0
|
||||
|
||||
proc hash*(x: Pointer): THash {.inline.} =
|
||||
proc hash*(x: pointer): THash {.inline.} =
|
||||
## efficient hashing of pointers
|
||||
when defined(js):
|
||||
asm """
|
||||
|
|
@ -126,6 +126,6 @@ proc hash*(x: float): THash {.inline.} =
|
|||
var y = x + 1.0
|
||||
result = cast[ptr THash](addr(y))[]
|
||||
|
||||
proc hash*[A](x: openarray[A]): THash =
|
||||
proc hash*[A](x: openArray[A]): THash =
|
||||
for it in items(x): result = result !& hash(it)
|
||||
result = !$result
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string,
|
|||
result.add(newStrLitNode("</"))
|
||||
result.add(newStrLitNode(tag))
|
||||
result.add(newStrLitNode(">"))
|
||||
result = NestList(!"&", result)
|
||||
result = nestList(!"&", result)
|
||||
|
||||
|
||||
macro a*(e: expr): expr {.immediate.} =
|
||||
|
|
|
|||
|
|
@ -220,9 +220,8 @@ proc parseResponse(s: TSocket, getBody: bool, timeout: int): TResponse =
|
|||
inc(linei, le)
|
||||
if line[linei] != ':': httpError("invalid headers")
|
||||
inc(linei) # Skip :
|
||||
linei += skipWhitespace(line, linei)
|
||||
|
||||
result.headers[name] = line[linei.. -1]
|
||||
result.headers[name] = line[linei.. -1].strip()
|
||||
if not fullyRead:
|
||||
httpError("Connection was closed before full request has been made")
|
||||
if getBody:
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ proc poll*(irc: PIRC, ev: var TIRCEvent,
|
|||
var line = TaintedString""
|
||||
var socks = @[irc.sock]
|
||||
var ret = socks.select(timeout)
|
||||
if socks.len() == 0 and ret != 0:
|
||||
if socks.len() != 0 and ret != 0:
|
||||
irc.sock.readLine(line)
|
||||
ev = irc.processLine(line.string)
|
||||
result = true
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ proc str*(my: TJsonParser): string {.inline.} =
|
|||
assert(my.kind in {jsonInt, jsonFloat, jsonString})
|
||||
return my.a
|
||||
|
||||
proc getInt*(my: TJsonParser): biggestInt {.inline.} =
|
||||
proc getInt*(my: TJsonParser): BiggestInt {.inline.} =
|
||||
## returns the number for the event: ``jsonInt``
|
||||
assert(my.kind == jsonInt)
|
||||
return parseBiggestInt(my.a)
|
||||
|
|
@ -151,11 +151,11 @@ proc kind*(my: TJsonParser): TJsonEventKind {.inline.} =
|
|||
|
||||
proc getColumn*(my: TJsonParser): int {.inline.} =
|
||||
## get the current column the parser has arrived at.
|
||||
result = getColNumber(my, my.bufPos)
|
||||
result = getColNumber(my, my.bufpos)
|
||||
|
||||
proc getLine*(my: TJsonParser): int {.inline.} =
|
||||
## get the current line the parser has arrived at.
|
||||
result = my.linenumber
|
||||
result = my.lineNumber
|
||||
|
||||
proc getFilename*(my: TJsonParser): string {.inline.} =
|
||||
## get the filename of the file that the parser processes.
|
||||
|
|
@ -173,7 +173,7 @@ proc errorMsgExpected*(my: TJsonParser, e: string): string =
|
|||
result = "$1($2, $3) Error: $4" % [
|
||||
my.filename, $getLine(my), $getColumn(my), e & " expected"]
|
||||
|
||||
proc handleHexChar(c: Char, x: var int): bool =
|
||||
proc handleHexChar(c: char, x: var int): bool =
|
||||
result = true # Success
|
||||
case c
|
||||
of '0'..'9': x = (x shl 4) or (ord(c) - ord('0'))
|
||||
|
|
@ -227,11 +227,11 @@ proc parseString(my: var TJsonParser): TTokKind =
|
|||
add(my.a, buf[pos])
|
||||
inc(pos)
|
||||
of '\c':
|
||||
pos = lexbase.HandleCR(my, pos)
|
||||
pos = lexbase.handleCR(my, pos)
|
||||
buf = my.buf
|
||||
add(my.a, '\c')
|
||||
of '\L':
|
||||
pos = lexbase.HandleLF(my, pos)
|
||||
pos = lexbase.handleLF(my, pos)
|
||||
buf = my.buf
|
||||
add(my.a, '\L')
|
||||
else:
|
||||
|
|
@ -253,11 +253,11 @@ proc skip(my: var TJsonParser) =
|
|||
of '\0':
|
||||
break
|
||||
of '\c':
|
||||
pos = lexbase.HandleCR(my, pos)
|
||||
pos = lexbase.handleCR(my, pos)
|
||||
buf = my.buf
|
||||
break
|
||||
of '\L':
|
||||
pos = lexbase.HandleLF(my, pos)
|
||||
pos = lexbase.handleLF(my, pos)
|
||||
buf = my.buf
|
||||
break
|
||||
else:
|
||||
|
|
@ -271,10 +271,10 @@ proc skip(my: var TJsonParser) =
|
|||
my.err = errEOC_Expected
|
||||
break
|
||||
of '\c':
|
||||
pos = lexbase.HandleCR(my, pos)
|
||||
pos = lexbase.handleCR(my, pos)
|
||||
buf = my.buf
|
||||
of '\L':
|
||||
pos = lexbase.HandleLF(my, pos)
|
||||
pos = lexbase.handleLF(my, pos)
|
||||
buf = my.buf
|
||||
of '*':
|
||||
inc(pos)
|
||||
|
|
@ -286,12 +286,12 @@ proc skip(my: var TJsonParser) =
|
|||
else:
|
||||
break
|
||||
of ' ', '\t':
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
of '\c':
|
||||
pos = lexbase.HandleCR(my, pos)
|
||||
pos = lexbase.handleCR(my, pos)
|
||||
buf = my.buf
|
||||
of '\L':
|
||||
pos = lexbase.HandleLF(my, pos)
|
||||
pos = lexbase.handleLF(my, pos)
|
||||
buf = my.buf
|
||||
else:
|
||||
break
|
||||
|
|
@ -517,7 +517,7 @@ type
|
|||
of JString:
|
||||
str*: string
|
||||
of JInt:
|
||||
num*: biggestInt
|
||||
num*: BiggestInt
|
||||
of JFloat:
|
||||
fnum*: float
|
||||
of JBool:
|
||||
|
|
@ -535,30 +535,30 @@ proc raiseParseErr*(p: TJsonParser, msg: string) {.noinline, noreturn.} =
|
|||
## raises an `EJsonParsingError` exception.
|
||||
raise newException(EJsonParsingError, errorMsgExpected(p, msg))
|
||||
|
||||
proc newJString*(s: String): PJsonNode =
|
||||
proc newJString*(s: string): PJsonNode =
|
||||
## Creates a new `JString PJsonNode`.
|
||||
new(result)
|
||||
result.kind = JString
|
||||
result.str = s
|
||||
|
||||
proc newJStringMove(s: String): PJsonNode =
|
||||
proc newJStringMove(s: string): PJsonNode =
|
||||
new(result)
|
||||
result.kind = JString
|
||||
shallowCopy(result.str, s)
|
||||
|
||||
proc newJInt*(n: biggestInt): PJsonNode =
|
||||
proc newJInt*(n: BiggestInt): PJsonNode =
|
||||
## Creates a new `JInt PJsonNode`.
|
||||
new(result)
|
||||
result.kind = JInt
|
||||
result.num = n
|
||||
|
||||
proc newJFloat*(n: Float): PJsonNode =
|
||||
proc newJFloat*(n: float): PJsonNode =
|
||||
## Creates a new `JFloat PJsonNode`.
|
||||
new(result)
|
||||
result.kind = JFloat
|
||||
result.fnum = n
|
||||
|
||||
proc newJBool*(b: Bool): PJsonNode =
|
||||
proc newJBool*(b: bool): PJsonNode =
|
||||
## Creates a new `JBool PJsonNode`.
|
||||
new(result)
|
||||
result.kind = JBool
|
||||
|
|
@ -587,7 +587,7 @@ proc `%`*(s: string): PJsonNode =
|
|||
result.kind = JString
|
||||
result.str = s
|
||||
|
||||
proc `%`*(n: biggestInt): PJsonNode =
|
||||
proc `%`*(n: BiggestInt): PJsonNode =
|
||||
## Generic constructor for JSON data. Creates a new `JInt PJsonNode`.
|
||||
new(result)
|
||||
result.kind = JInt
|
||||
|
|
@ -612,7 +612,7 @@ proc `%`*(keyVals: openArray[tuple[key: string, val: PJsonNode]]): PJsonNode =
|
|||
newSeq(result.fields, keyVals.len)
|
||||
for i, p in pairs(keyVals): result.fields[i] = p
|
||||
|
||||
proc `%`*(elements: openArray[PJSonNode]): PJsonNode =
|
||||
proc `%`*(elements: openArray[PJsonNode]): PJsonNode =
|
||||
## Generic constructor for JSON data. Creates a new `JArray PJsonNode`
|
||||
new(result)
|
||||
result.kind = JArray
|
||||
|
|
@ -626,9 +626,9 @@ proc len*(n: PJsonNode): int =
|
|||
case n.kind
|
||||
of JArray: result = n.elems.len
|
||||
of JObject: result = n.fields.len
|
||||
else: nil
|
||||
else: discard
|
||||
|
||||
proc `[]`*(node: PJsonNode, name: String): PJsonNode =
|
||||
proc `[]`*(node: PJsonNode, name: string): PJsonNode =
|
||||
## Gets a field from a `JObject`. Returns nil if the key is not found.
|
||||
assert(node.kind == JObject)
|
||||
for key, item in items(node.fields):
|
||||
|
|
@ -636,17 +636,18 @@ proc `[]`*(node: PJsonNode, name: String): PJsonNode =
|
|||
return item
|
||||
return nil
|
||||
|
||||
proc `[]`*(node: PJsonNode, index: Int): PJsonNode =
|
||||
proc `[]`*(node: PJsonNode, index: int): PJsonNode =
|
||||
## Gets the node at `index` in an Array.
|
||||
assert(node.kind == JArray)
|
||||
return node.elems[index]
|
||||
|
||||
proc hasKey*(node: PJsonNode, key: String): Bool =
|
||||
proc hasKey*(node: PJsonNode, key: string): bool =
|
||||
## Checks if `key` exists in `node`.
|
||||
assert(node.kind == JObject)
|
||||
for k, item in items(node.fields):
|
||||
if k == key: return True
|
||||
proc existsKey*(node: PJsonNode, key: String): Bool {.deprecated.} = node.hasKey(key)
|
||||
if k == key: return true
|
||||
|
||||
proc existsKey*(node: PJsonNode, key: string): bool {.deprecated.} = node.hasKey(key)
|
||||
## Deprecated for `hasKey`
|
||||
|
||||
proc add*(father, child: PJsonNode) =
|
||||
|
|
@ -661,7 +662,7 @@ proc add*(obj: PJsonNode, key: string, val: PJsonNode) =
|
|||
assert obj.kind == JObject
|
||||
obj.fields.add((key, val))
|
||||
|
||||
proc `[]=`*(obj: PJsonNode, key: String, val: PJsonNode) =
|
||||
proc `[]=`*(obj: PJsonNode, key: string, val: PJsonNode) =
|
||||
## Sets a field from a `JObject`. Performs a check for duplicate keys.
|
||||
assert(obj.kind == JObject)
|
||||
for i in 0..obj.fields.len-1:
|
||||
|
|
@ -706,7 +707,7 @@ proc copy*(p: PJsonNode): PJsonNode =
|
|||
proc indent(s: var string, i: int) =
|
||||
s.add(repeatChar(i))
|
||||
|
||||
proc newIndent(curr, indent: int, ml: bool): Int =
|
||||
proc newIndent(curr, indent: int, ml: bool): int =
|
||||
if ml: return curr + indent
|
||||
else: return indent
|
||||
|
||||
|
|
@ -730,8 +731,8 @@ proc escapeJson*(s: string): string =
|
|||
result.add(toHex(r, 4))
|
||||
result.add("\"")
|
||||
|
||||
proc toPretty(result: var string, node: PJsonNode, indent = 2, ml = True,
|
||||
lstArr = False, currIndent = 0) =
|
||||
proc toPretty(result: var string, node: PJsonNode, indent = 2, ml = true,
|
||||
lstArr = false, currIndent = 0) =
|
||||
case node.kind
|
||||
of JObject:
|
||||
if currIndent != 0 and not lstArr: result.nl(ml)
|
||||
|
|
@ -747,7 +748,7 @@ proc toPretty(result: var string, node: PJsonNode, indent = 2, ml = True,
|
|||
result.indent(newIndent(currIndent, indent, ml))
|
||||
result.add(escapeJson(node.fields[i].key))
|
||||
result.add(": ")
|
||||
toPretty(result, node.fields[i].val, indent, ml, False,
|
||||
toPretty(result, node.fields[i].val, indent, ml, false,
|
||||
newIndent(currIndent, indent, ml))
|
||||
result.nl(ml)
|
||||
result.indent(currIndent) # indent the same as {
|
||||
|
|
@ -776,7 +777,7 @@ proc toPretty(result: var string, node: PJsonNode, indent = 2, ml = True,
|
|||
result.add(", ")
|
||||
result.nl(ml) # New Line
|
||||
toPretty(result, node.elems[i], indent, ml,
|
||||
True, newIndent(currIndent, indent, ml))
|
||||
true, newIndent(currIndent, indent, ml))
|
||||
result.nl(ml)
|
||||
result.indent(currIndent)
|
||||
result.add("]")
|
||||
|
|
@ -785,18 +786,18 @@ proc toPretty(result: var string, node: PJsonNode, indent = 2, ml = True,
|
|||
if lstArr: result.indent(currIndent)
|
||||
result.add("null")
|
||||
|
||||
proc pretty*(node: PJsonNode, indent = 2): String =
|
||||
proc pretty*(node: PJsonNode, indent = 2): string =
|
||||
## Converts `node` to its JSON Representation, with indentation and
|
||||
## on multiple lines.
|
||||
result = ""
|
||||
toPretty(result, node, indent)
|
||||
|
||||
proc `$`*(node: PJsonNode): String =
|
||||
proc `$`*(node: PJsonNode): string =
|
||||
## Converts `node` to its JSON Representation on one line.
|
||||
result = ""
|
||||
toPretty(result, node, 1, False)
|
||||
toPretty(result, node, 1, false)
|
||||
|
||||
iterator items*(node: PJsonNode): PJSonNode =
|
||||
iterator items*(node: PJsonNode): PJsonNode =
|
||||
## Iterator for the items of `node`. `node` has to be a JArray.
|
||||
assert node.kind == JArray
|
||||
for i in items(node.elems):
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ type
|
|||
buf*: cstring ## the buffer itself
|
||||
bufLen*: int ## length of buffer in characters
|
||||
input: PStream ## the input stream
|
||||
LineNumber*: int ## the current line number
|
||||
lineNumber*: int ## the current line number
|
||||
sentinel: int
|
||||
lineStart: int # index of last line start in buffer
|
||||
fileOpened: bool
|
||||
|
|
@ -48,11 +48,11 @@ proc getCurrentLine*(L: TBaseLexer, marker: bool = true): string
|
|||
proc getColNumber*(L: TBaseLexer, pos: int): int
|
||||
## retrieves the current column.
|
||||
|
||||
proc HandleCR*(L: var TBaseLexer, pos: int): int
|
||||
proc handleCR*(L: var TBaseLexer, pos: int): int
|
||||
## Call this if you scanned over '\c' in the buffer; it returns the the
|
||||
## position to continue the scanning from. `pos` must be the position
|
||||
## of the '\c'.
|
||||
proc HandleLF*(L: var TBaseLexer, pos: int): int
|
||||
proc handleLF*(L: var TBaseLexer, pos: int): int
|
||||
## Call this if you scanned over '\L' in the buffer; it returns the the
|
||||
## position to continue the scanning from. `pos` must be the position
|
||||
## of the '\L'.
|
||||
|
|
@ -66,7 +66,7 @@ proc close(L: var TBaseLexer) =
|
|||
dealloc(L.buf)
|
||||
close(L.input)
|
||||
|
||||
proc FillBuffer(L: var TBaseLexer) =
|
||||
proc fillBuffer(L: var TBaseLexer) =
|
||||
var
|
||||
charsRead, toCopy, s: int # all are in characters,
|
||||
# not bytes (in case this
|
||||
|
|
@ -75,10 +75,10 @@ proc FillBuffer(L: var TBaseLexer) =
|
|||
# we know here that pos == L.sentinel, but not if this proc
|
||||
# is called the first time by initBaseLexer()
|
||||
assert(L.sentinel < L.bufLen)
|
||||
toCopy = L.BufLen - L.sentinel - 1
|
||||
toCopy = L.bufLen - L.sentinel - 1
|
||||
assert(toCopy >= 0)
|
||||
if toCopy > 0:
|
||||
MoveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize)
|
||||
moveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize)
|
||||
# "moveMem" handles overlapping regions
|
||||
charsRead = readData(L.input, addr(L.buf[toCopy]),
|
||||
(L.sentinel + 1) * chrSize) div chrSize
|
||||
|
|
@ -91,7 +91,7 @@ proc FillBuffer(L: var TBaseLexer) =
|
|||
dec(s) # BUGFIX (valgrind)
|
||||
while true:
|
||||
assert(s < L.bufLen)
|
||||
while (s >= 0) and not (L.buf[s] in NewLines): Dec(s)
|
||||
while (s >= 0) and not (L.buf[s] in NewLines): dec(s)
|
||||
if s >= 0:
|
||||
# we found an appropriate character for a sentinel:
|
||||
L.sentinel = s
|
||||
|
|
@ -99,11 +99,11 @@ proc FillBuffer(L: var TBaseLexer) =
|
|||
else:
|
||||
# rather than to give up here because the line is too long,
|
||||
# double the buffer's size and try again:
|
||||
oldBufLen = L.BufLen
|
||||
L.bufLen = L.BufLen * 2
|
||||
oldBufLen = L.bufLen
|
||||
L.bufLen = L.bufLen * 2
|
||||
L.buf = cast[cstring](realloc(L.buf, L.bufLen * chrSize))
|
||||
assert(L.bufLen - oldBuflen == oldBufLen)
|
||||
charsRead = ReadData(L.input, addr(L.buf[oldBufLen]),
|
||||
assert(L.bufLen - oldBufLen == oldBufLen)
|
||||
charsRead = readData(L.input, addr(L.buf[oldBufLen]),
|
||||
oldBufLen * chrSize) div chrSize
|
||||
if charsRead < oldBufLen:
|
||||
L.buf[oldBufLen + charsRead] = EndOfFile
|
||||
|
|
@ -121,19 +121,19 @@ proc fillBaseLexer(L: var TBaseLexer, pos: int): int =
|
|||
result = 0
|
||||
L.lineStart = result
|
||||
|
||||
proc HandleCR(L: var TBaseLexer, pos: int): int =
|
||||
proc handleCR(L: var TBaseLexer, pos: int): int =
|
||||
assert(L.buf[pos] == '\c')
|
||||
inc(L.linenumber)
|
||||
inc(L.lineNumber)
|
||||
result = fillBaseLexer(L, pos)
|
||||
if L.buf[result] == '\L':
|
||||
result = fillBaseLexer(L, result)
|
||||
|
||||
proc HandleLF(L: var TBaseLexer, pos: int): int =
|
||||
proc handleLF(L: var TBaseLexer, pos: int): int =
|
||||
assert(L.buf[pos] == '\L')
|
||||
inc(L.linenumber)
|
||||
inc(L.lineNumber)
|
||||
result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result;
|
||||
|
||||
proc skip_UTF_8_BOM(L: var TBaseLexer) =
|
||||
proc skipUtf8Bom(L: var TBaseLexer) =
|
||||
if (L.buf[0] == '\xEF') and (L.buf[1] == '\xBB') and (L.buf[2] == '\xBF'):
|
||||
inc(L.bufpos, 3)
|
||||
inc(L.lineStart, 3)
|
||||
|
|
@ -147,9 +147,9 @@ proc open(L: var TBaseLexer, input: PStream, bufLen: int = 8192) =
|
|||
L.buf = cast[cstring](alloc(bufLen * chrSize))
|
||||
L.sentinel = bufLen - 1
|
||||
L.lineStart = 0
|
||||
L.linenumber = 1 # lines start at 1
|
||||
L.lineNumber = 1 # lines start at 1
|
||||
fillBuffer(L)
|
||||
skip_UTF_8_BOM(L)
|
||||
skipUtf8Bom(L)
|
||||
|
||||
proc getColNumber(L: TBaseLexer, pos: int): int =
|
||||
result = abs(pos - L.lineStart)
|
||||
|
|
@ -163,5 +163,5 @@ proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
|
|||
inc(i)
|
||||
add(result, "\n")
|
||||
if marker:
|
||||
add(result, RepeatChar(getColNumber(L, L.bufpos)) & "^\n")
|
||||
add(result, repeatChar(getColNumber(L, L.bufpos)) & "^\n")
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ proc nextPowerOfTwo*(x: int): int =
|
|||
result = result or (result shr 4)
|
||||
result = result or (result shr 2)
|
||||
result = result or (result shr 1)
|
||||
Inc(result)
|
||||
inc(result)
|
||||
|
||||
proc countBits32*(n: int32): int {.noSideEffect.} =
|
||||
## counts the set bits in `n`.
|
||||
|
|
@ -103,17 +103,17 @@ proc countBits32*(n: int32): int {.noSideEffect.} =
|
|||
v = (v and 0x33333333'i32) +% ((v shr 2'i32) and 0x33333333'i32)
|
||||
result = ((v +% (v shr 4'i32) and 0xF0F0F0F'i32) *% 0x1010101'i32) shr 24'i32
|
||||
|
||||
proc sum*[T](x: openarray[T]): T {.noSideEffect.} =
|
||||
proc sum*[T](x: openArray[T]): T {.noSideEffect.} =
|
||||
## computes the sum of the elements in `x`.
|
||||
## If `x` is empty, 0 is returned.
|
||||
for i in items(x): result = result + i
|
||||
|
||||
proc mean*(x: openarray[float]): float {.noSideEffect.} =
|
||||
proc mean*(x: openArray[float]): float {.noSideEffect.} =
|
||||
## computes the mean of the elements in `x`.
|
||||
## If `x` is empty, NaN is returned.
|
||||
result = sum(x) / toFloat(len(x))
|
||||
|
||||
proc variance*(x: openarray[float]): float {.noSideEffect.} =
|
||||
proc variance*(x: openArray[float]): float {.noSideEffect.} =
|
||||
## computes the variance of the elements in `x`.
|
||||
## If `x` is empty, NaN is returned.
|
||||
result = 0.0
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ type
|
|||
MD5Digest* = array[0..15, int8]
|
||||
MD5Buffer = array[0..63, int8]
|
||||
MD5Context* {.final.} = object
|
||||
State: MD5State
|
||||
Count: array[0..1, int32]
|
||||
Buffer: MD5Buffer
|
||||
state: MD5State
|
||||
count: array[0..1, int32]
|
||||
buffer: MD5Buffer
|
||||
|
||||
const
|
||||
padding: cstring = "\x80\0\0\0" &
|
||||
|
|
@ -32,16 +32,16 @@ const
|
|||
"\0\0\0\0"
|
||||
|
||||
proc F(x, y, z: int32): int32 {.inline.} =
|
||||
Result = (x and y) or ((not x) and z)
|
||||
result = (x and y) or ((not x) and z)
|
||||
|
||||
proc G(x, y, z: int32): int32 {.inline.} =
|
||||
Result = (x and z) or (y and (not z))
|
||||
result = (x and z) or (y and (not z))
|
||||
|
||||
proc H(x, y, z: int32): int32 {.inline.} =
|
||||
Result = x xor y xor z
|
||||
result = x xor y xor z
|
||||
|
||||
proc I(x, y, z: int32): int32 {.inline.} =
|
||||
Result = y xor (x or (not z))
|
||||
result = y xor (x or (not z))
|
||||
|
||||
proc rot(x: var int32, n: int8) {.inline.} =
|
||||
x = toU32(x shl ze(n)) or (x shr toU32(32 -% ze(n)))
|
||||
|
|
@ -75,7 +75,7 @@ proc encode(dest: var MD5Block, src: cstring) =
|
|||
ord(src[j+3]) shl 24)
|
||||
inc(j, 4)
|
||||
|
||||
proc decode(dest: var openarray[int8], src: openarray[int32]) =
|
||||
proc decode(dest: var openArray[int8], src: openArray[int32]) =
|
||||
var i = 0
|
||||
for j in 0..high(src):
|
||||
dest[i] = toU8(src[j] and 0xff'i32)
|
||||
|
|
@ -87,7 +87,7 @@ proc decode(dest: var openarray[int8], src: openarray[int32]) =
|
|||
proc transform(Buffer: pointer, State: var MD5State) =
|
||||
var
|
||||
myBlock: MD5Block
|
||||
encode(myBlock, cast[cstring](buffer))
|
||||
encode(myBlock, cast[cstring](Buffer))
|
||||
var a = State[0]
|
||||
var b = State[1]
|
||||
var c = State[2]
|
||||
|
|
@ -161,7 +161,7 @@ proc transform(Buffer: pointer, State: var MD5State) =
|
|||
State[2] = State[2] +% c
|
||||
State[3] = State[3] +% d
|
||||
|
||||
proc MD5Init*(c: var MD5Context) =
|
||||
proc md5Init*(c: var MD5Context) =
|
||||
## initializes a MD5Context
|
||||
c.State[0] = 0x67452301'i32
|
||||
c.State[1] = 0xEFCDAB89'i32
|
||||
|
|
@ -169,64 +169,64 @@ proc MD5Init*(c: var MD5Context) =
|
|||
c.State[3] = 0x10325476'i32
|
||||
c.Count[0] = 0'i32
|
||||
c.Count[1] = 0'i32
|
||||
ZeroMem(addr(c.Buffer), SizeOf(MD5Buffer))
|
||||
zeroMem(addr(c.Buffer), sizeof(MD5Buffer))
|
||||
|
||||
proc MD5Update*(c: var MD5Context, input: cstring, len: int) =
|
||||
proc md5Update*(c: var MD5Context, input: cstring, len: int) =
|
||||
## updates the MD5Context with the `input` data of length `len`
|
||||
var input = input
|
||||
var Index = (c.Count[0] shr 3) and 0x3F
|
||||
var Index = (c.count[0] shr 3) and 0x3F
|
||||
c.Count[0] = c.count[0] +% toU32(len shl 3)
|
||||
if c.Count[0] < (len shl 3): c.Count[1] = c.count[1] +% 1'i32
|
||||
c.Count[1] = c.count[1] +% toU32(len shr 29)
|
||||
var PartLen = 64 - Index
|
||||
if len >= PartLen:
|
||||
CopyMem(addr(c.Buffer[Index]), Input, PartLen)
|
||||
copyMem(addr(c.Buffer[Index]), input, PartLen)
|
||||
transform(addr(c.Buffer), c.State)
|
||||
var i = PartLen
|
||||
while i + 63 < len:
|
||||
Transform(addr(Input[I]), c.State)
|
||||
transform(addr(input[i]), c.State)
|
||||
inc(i, 64)
|
||||
CopyMem(addr(c.Buffer[0]), addr(Input[i]), len-i)
|
||||
copyMem(addr(c.Buffer[0]), addr(input[i]), len-i)
|
||||
else:
|
||||
CopyMem(addr(c.Buffer[Index]), addr(Input[0]), len)
|
||||
copyMem(addr(c.Buffer[Index]), addr(input[0]), len)
|
||||
|
||||
proc MD5Final*(c: var MD5Context, digest: var MD5Digest) =
|
||||
proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
|
||||
## finishes the MD5Context and stores the result in `digest`
|
||||
var
|
||||
Bits: MD5CBits
|
||||
PadLen: int
|
||||
decode(bits, c.Count)
|
||||
decode(Bits, c.Count)
|
||||
var Index = (c.Count[0] shr 3) and 0x3F
|
||||
if Index < 56: PadLen = 56 - Index
|
||||
else: PadLen = 120 - Index
|
||||
MD5Update(c, padding, PadLen)
|
||||
MD5Update(c, cast[cstring](addr(Bits)), 8)
|
||||
md5Update(c, padding, PadLen)
|
||||
md5Update(c, cast[cstring](addr(Bits)), 8)
|
||||
decode(digest, c.State)
|
||||
ZeroMem(addr(c), SizeOf(MD5Context))
|
||||
zeroMem(addr(c), sizeof(MD5Context))
|
||||
|
||||
proc toMD5*(s: string): MD5Digest =
|
||||
## computes the MD5Digest value for a string `s`
|
||||
var c: MD5Context
|
||||
MD5Init(c)
|
||||
MD5Update(c, cstring(s), len(s))
|
||||
MD5Final(c, result)
|
||||
md5Init(c)
|
||||
md5Update(c, cstring(s), len(s))
|
||||
md5Final(c, result)
|
||||
|
||||
proc `$`*(D: MD5Digest): string =
|
||||
## converts a MD5Digest value into its string representation
|
||||
const digits = "0123456789abcdef"
|
||||
result = ""
|
||||
for i in 0..15:
|
||||
add(result, Digits[(D[I] shr 4) and 0xF])
|
||||
add(result, Digits[D[I] and 0xF])
|
||||
add(result, Digits[(D[i] shr 4) and 0xF])
|
||||
add(result, Digits[D[i] and 0xF])
|
||||
|
||||
proc getMD5*(s: string): string =
|
||||
## computes an MD5 value of `s` and returns its string representation
|
||||
var
|
||||
c: MD5Context
|
||||
d: MD5Digest
|
||||
MD5Init(c)
|
||||
MD5Update(c, cstring(s), len(s))
|
||||
MD5Final(c, d)
|
||||
md5Init(c)
|
||||
md5Update(c, cstring(s), len(s))
|
||||
md5Final(c, d)
|
||||
result = $d
|
||||
|
||||
proc `==`*(D1, D2: MD5Digest): bool =
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
when defined(windows):
|
||||
template fail(errCode: TOSErrorCode, msg: expr) =
|
||||
rollback()
|
||||
if result.fHandle != 0: discard CloseHandle(result.fHandle)
|
||||
if result.mapHandle != 0: discard CloseHandle(result.mapHandle)
|
||||
OSError(errCode)
|
||||
if result.fHandle != 0: discard closeHandle(result.fHandle)
|
||||
if result.mapHandle != 0: discard closeHandle(result.mapHandle)
|
||||
osError(errCode)
|
||||
# return false
|
||||
#raise newException(EIO, msg)
|
||||
|
||||
|
|
@ -69,36 +69,36 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
0)
|
||||
|
||||
when useWinUnicode:
|
||||
result.fHandle = callCreateFile(CreateFileW, newWideCString(filename))
|
||||
result.fHandle = callCreateFile(createFileW, newWideCString(filename))
|
||||
else:
|
||||
result.fHandle = callCreateFile(CreateFileA, filename)
|
||||
|
||||
if result.fHandle == INVALID_HANDLE_VALUE:
|
||||
fail(OSLastError(), "error opening file")
|
||||
fail(osLastError(), "error opening file")
|
||||
|
||||
if newFileSize != -1:
|
||||
var
|
||||
sizeHigh = int32(newFileSize shr 32)
|
||||
sizeLow = int32(newFileSize and 0xffffffff)
|
||||
|
||||
var status = SetFilePointer(result.fHandle, sizeLow, addr(sizeHigh),
|
||||
var status = setFilePointer(result.fHandle, sizeLow, addr(sizeHigh),
|
||||
FILE_BEGIN)
|
||||
let lastErr = OSLastError()
|
||||
let lastErr = osLastError()
|
||||
if (status == INVALID_SET_FILE_POINTER and lastErr.int32 != NO_ERROR) or
|
||||
(SetEndOfFile(result.fHandle) == 0):
|
||||
(setEndOfFile(result.fHandle) == 0):
|
||||
fail(lastErr, "error setting file size")
|
||||
|
||||
# since the strings are always 'nil', we simply always call
|
||||
# CreateFileMappingW which should be slightly faster anyway:
|
||||
result.mapHandle = CreateFileMappingW(
|
||||
result.mapHandle = createFileMappingW(
|
||||
result.fHandle, nil,
|
||||
if readonly: PAGE_READONLY else: PAGE_READWRITE,
|
||||
0, 0, nil)
|
||||
|
||||
if result.mapHandle == 0:
|
||||
fail(OSLastError(), "error creating mapping")
|
||||
fail(osLastError(), "error creating mapping")
|
||||
|
||||
result.mem = MapViewOfFileEx(
|
||||
result.mem = mapViewOfFileEx(
|
||||
result.mapHandle,
|
||||
if readonly: FILE_MAP_READ else: FILE_MAP_WRITE,
|
||||
int32(offset shr 32),
|
||||
|
|
@ -107,12 +107,12 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
nil)
|
||||
|
||||
if result.mem == nil:
|
||||
fail(OSLastError(), "error mapping view")
|
||||
fail(osLastError(), "error mapping view")
|
||||
|
||||
var hi, low: int32
|
||||
low = GetFileSize(result.fHandle, addr(hi))
|
||||
low = getFileSize(result.fHandle, addr(hi))
|
||||
if low == INVALID_FILE_SIZE:
|
||||
fail(OSLastError(), "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
|
||||
|
|
@ -122,7 +122,7 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
template fail(errCode: TOSErrorCode, msg: expr) =
|
||||
rollback()
|
||||
if result.handle != 0: discard close(result.handle)
|
||||
OSError(errCode)
|
||||
osError(errCode)
|
||||
|
||||
var flags = if readonly: O_RDONLY else: O_RDWR
|
||||
|
||||
|
|
@ -133,22 +133,22 @@ 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(OSLastError(), "error opening file")
|
||||
fail(osLastError(), "error opening file")
|
||||
|
||||
if newFileSize != -1:
|
||||
if ftruncate(result.handle, newFileSize) == -1:
|
||||
fail(OSLastError(), "error setting file size")
|
||||
fail(osLastError(), "error setting file size")
|
||||
|
||||
if mappedSize != -1:
|
||||
result.size = mappedSize
|
||||
else:
|
||||
var stat: Tstat
|
||||
var stat: TStat
|
||||
if fstat(result.handle, stat) != -1:
|
||||
# XXX: Hmm, this could be unsafe
|
||||
# Why is mmap taking int anyway?
|
||||
result.size = int(stat.st_size)
|
||||
else:
|
||||
fail(OSLastError(), "error getting file size")
|
||||
fail(osLastError(), "error getting file size")
|
||||
|
||||
result.mem = mmap(
|
||||
nil,
|
||||
|
|
@ -159,7 +159,7 @@ proc open*(filename: string, mode: TFileMode = fmRead,
|
|||
offset)
|
||||
|
||||
if result.mem == cast[pointer](MAP_FAILED):
|
||||
fail(OSLastError(), "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
|
||||
|
|
@ -170,13 +170,13 @@ proc close*(f: var TMemFile) =
|
|||
|
||||
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
|
||||
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()
|
||||
lastErr = osLastError()
|
||||
error = munmap(f.mem, f.size) != 0
|
||||
error = (close(f.handle) != 0) or error
|
||||
|
||||
|
|
@ -189,5 +189,5 @@ proc close*(f: var TMemFile) =
|
|||
else:
|
||||
f.handle = 0
|
||||
|
||||
if error: OSError(lastErr)
|
||||
if error: osError(lastErr)
|
||||
|
||||
|
|
|
|||
501
lib/pure/os.nim
501
lib/pure/os.nim
File diff suppressed because it is too large
Load diff
|
|
@ -23,7 +23,7 @@ else:
|
|||
type
|
||||
TProcess = object of TObject
|
||||
when defined(windows):
|
||||
FProcessHandle: Thandle
|
||||
fProcessHandle: THandle
|
||||
inHandle, outHandle, errHandle: TFileHandle
|
||||
id: THandle
|
||||
else:
|
||||
|
|
@ -108,7 +108,7 @@ proc execCmd*(command: string): int {.rtl, extern: "nosp$1", tags: [FExecIO].}
|
|||
|
||||
proc startProcess*(command: string,
|
||||
workingDir: string = "",
|
||||
args: openarray[string] = [],
|
||||
args: openArray[string] = [],
|
||||
env: PStringTable = nil,
|
||||
options: set[TProcessOption] = {poStdErrToStdOut}):
|
||||
PProcess {.rtl, extern: "nosp$1", tags: [FExecIO, FReadEnv].}
|
||||
|
|
@ -219,7 +219,7 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
|
|||
## returns the numer of the processors/cores the machine has.
|
||||
## Returns 0 if it cannot be detected.
|
||||
when defined(windows):
|
||||
var x = getenv("NUMBER_OF_PROCESSORS")
|
||||
var x = getEnv("NUMBER_OF_PROCESSORS")
|
||||
if x.len > 0: result = parseInt(x.string)
|
||||
elif defined(macosx) or defined(bsd):
|
||||
var
|
||||
|
|
@ -329,18 +329,18 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
handle: THandle
|
||||
atTheEnd: bool
|
||||
|
||||
proc hsClose(s: PStream) = nil # nothing to do here
|
||||
proc hsClose(s: PStream) = discard # nothing to do here
|
||||
proc hsAtEnd(s: PStream): bool = return PFileHandleStream(s).atTheEnd
|
||||
|
||||
proc hsReadData(s: PStream, buffer: pointer, bufLen: int): int =
|
||||
var s = PFileHandleStream(s)
|
||||
if s.atTheEnd: return 0
|
||||
var br: int32
|
||||
var a = winlean.ReadFile(s.handle, buffer, bufLen.cint, br, nil)
|
||||
var a = winlean.readFile(s.handle, buffer, bufLen.cint, br, nil)
|
||||
# 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(OSLastError())
|
||||
if a == 0 and br != 0: osError(osLastError())
|
||||
s.atTheEnd = br < bufLen
|
||||
result = br
|
||||
|
||||
|
|
@ -348,7 +348,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(OSLastError())
|
||||
if a == 0: osError(osLastError())
|
||||
|
||||
proc newFileHandleStream(handle: THandle): PFileHandleStream =
|
||||
new(result)
|
||||
|
|
@ -358,7 +358,7 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
result.readDataImpl = hsReadData
|
||||
result.writeDataImpl = hsWriteData
|
||||
|
||||
proc buildCommandLine(a: string, args: openarray[string]): cstring =
|
||||
proc buildCommandLine(a: string, args: openArray[string]): cstring =
|
||||
var res = quoteShell(a)
|
||||
for i in 0..high(args):
|
||||
res.add(' ')
|
||||
|
|
@ -383,45 +383,45 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
# O_WRONLY {.importc: "_O_WRONLY", header: "<fcntl.h>".}: int
|
||||
# O_RDONLY {.importc: "_O_RDONLY", header: "<fcntl.h>".}: int
|
||||
|
||||
proc CreatePipeHandles(Rdhandle, WrHandle: var THandle) =
|
||||
var piInheritablePipe: TSecurityAttributes
|
||||
piInheritablePipe.nlength = SizeOF(TSecurityAttributes).cint
|
||||
proc createPipeHandles(rdHandle, wrHandle: var THandle) =
|
||||
var piInheritablePipe: TSECURITY_ATTRIBUTES
|
||||
piInheritablePipe.nLength = sizeof(TSECURITY_ATTRIBUTES).cint
|
||||
piInheritablePipe.lpSecurityDescriptor = nil
|
||||
piInheritablePipe.Binherithandle = 1
|
||||
if CreatePipe(Rdhandle, Wrhandle, piInheritablePipe, 1024) == 0'i32:
|
||||
OSError(OSLastError())
|
||||
piInheritablePipe.bInheritHandle = 1
|
||||
if createPipe(rdHandle, wrHandle, piInheritablePipe, 1024) == 0'i32:
|
||||
osError(osLastError())
|
||||
|
||||
proc fileClose(h: THandle) {.inline.} =
|
||||
if h > 4: discard CloseHandle(h)
|
||||
if h > 4: discard closeHandle(h)
|
||||
|
||||
proc startProcess(command: string,
|
||||
workingDir: string = "",
|
||||
args: openarray[string] = [],
|
||||
args: openArray[string] = [],
|
||||
env: PStringTable = nil,
|
||||
options: set[TProcessOption] = {poStdErrToStdOut}): PProcess =
|
||||
var
|
||||
SI: TStartupInfo
|
||||
ProcInfo: TProcessInformation
|
||||
si: TSTARTUPINFO
|
||||
procInfo: TPROCESS_INFORMATION
|
||||
success: int
|
||||
hi, ho, he: THandle
|
||||
new(result)
|
||||
SI.cb = SizeOf(SI).cint
|
||||
si.cb = sizeof(si).cint
|
||||
if poParentStreams notin options:
|
||||
SI.dwFlags = STARTF_USESTDHANDLES # STARTF_USESHOWWINDOW or
|
||||
CreatePipeHandles(SI.hStdInput, HI)
|
||||
CreatePipeHandles(HO, Si.hStdOutput)
|
||||
si.dwFlags = STARTF_USESTDHANDLES # STARTF_USESHOWWINDOW or
|
||||
createPipeHandles(si.hStdInput, hi)
|
||||
createPipeHandles(ho, si.hStdOutput)
|
||||
if poStdErrToStdOut in options:
|
||||
SI.hStdError = SI.hStdOutput
|
||||
HE = HO
|
||||
si.hStdError = si.hStdOutput
|
||||
he = ho
|
||||
else:
|
||||
CreatePipeHandles(HE, Si.hStdError)
|
||||
createPipeHandles(he, si.hStdError)
|
||||
result.inHandle = TFileHandle(hi)
|
||||
result.outHandle = TFileHandle(ho)
|
||||
result.errHandle = TFileHandle(he)
|
||||
else:
|
||||
SI.hStdError = GetStdHandle(STD_ERROR_HANDLE)
|
||||
SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE)
|
||||
SI.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
si.hStdError = getStdHandle(STD_ERROR_HANDLE)
|
||||
si.hStdInput = getStdHandle(STD_INPUT_HANDLE)
|
||||
si.hStdOutput = getStdHandle(STD_OUTPUT_HANDLE)
|
||||
result.inHandle = TFileHandle(si.hStdInput)
|
||||
result.outHandle = TFileHandle(si.hStdOutput)
|
||||
result.errHandle = TFileHandle(si.hStdError)
|
||||
|
|
@ -440,64 +440,64 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
var tmp = newWideCString(cmdl)
|
||||
var ee = newWideCString(e)
|
||||
var wwd = newWideCString(wd)
|
||||
success = winlean.CreateProcessW(nil,
|
||||
success = winlean.createProcessW(nil,
|
||||
tmp, nil, nil, 1, NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT,
|
||||
ee, wwd, SI, ProcInfo)
|
||||
ee, wwd, si, procInfo)
|
||||
else:
|
||||
success = winlean.CreateProcessA(nil,
|
||||
success = winlean.createProcessA(nil,
|
||||
cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, SI, ProcInfo)
|
||||
let lastError = OSLastError()
|
||||
let lastError = osLastError()
|
||||
|
||||
if poParentStreams notin options:
|
||||
FileClose(si.hStdInput)
|
||||
FileClose(si.hStdOutput)
|
||||
fileClose(si.hStdInput)
|
||||
fileClose(si.hStdOutput)
|
||||
if poStdErrToStdOut notin options:
|
||||
FileClose(si.hStdError)
|
||||
fileClose(si.hStdError)
|
||||
|
||||
if e != nil: dealloc(e)
|
||||
dealloc(cmdl)
|
||||
if success == 0: OSError(lastError)
|
||||
if success == 0: osError(lastError)
|
||||
# Close the handle now so anyone waiting is woken:
|
||||
discard closeHandle(procInfo.hThread)
|
||||
result.FProcessHandle = procInfo.hProcess
|
||||
result.id = procInfo.dwProcessID
|
||||
result.fProcessHandle = procInfo.hProcess
|
||||
result.id = procInfo.dwProcessId
|
||||
|
||||
proc close(p: PProcess) =
|
||||
when false:
|
||||
# somehow this does not work on Windows:
|
||||
discard CloseHandle(p.inHandle)
|
||||
discard CloseHandle(p.outHandle)
|
||||
discard CloseHandle(p.errHandle)
|
||||
discard CloseHandle(p.FProcessHandle)
|
||||
discard closeHandle(p.inHandle)
|
||||
discard closeHandle(p.outHandle)
|
||||
discard closeHandle(p.errHandle)
|
||||
discard closeHandle(p.FProcessHandle)
|
||||
|
||||
proc suspend(p: PProcess) =
|
||||
discard SuspendThread(p.FProcessHandle)
|
||||
discard suspendThread(p.fProcessHandle)
|
||||
|
||||
proc resume(p: PProcess) =
|
||||
discard ResumeThread(p.FProcessHandle)
|
||||
discard resumeThread(p.fProcessHandle)
|
||||
|
||||
proc running(p: PProcess): bool =
|
||||
var x = waitForSingleObject(p.FProcessHandle, 50)
|
||||
var x = waitForSingleObject(p.fProcessHandle, 50)
|
||||
return x == WAIT_TIMEOUT
|
||||
|
||||
proc terminate(p: PProcess) =
|
||||
if running(p):
|
||||
discard TerminateProcess(p.FProcessHandle, 0)
|
||||
discard terminateProcess(p.fProcessHandle, 0)
|
||||
|
||||
proc waitForExit(p: PProcess, timeout: int = -1): int =
|
||||
discard WaitForSingleObject(p.FProcessHandle, timeout.int32)
|
||||
discard waitForSingleObject(p.fProcessHandle, timeout.int32)
|
||||
|
||||
var res: int32
|
||||
discard GetExitCodeProcess(p.FProcessHandle, res)
|
||||
discard getExitCodeProcess(p.fProcessHandle, res)
|
||||
result = res
|
||||
discard CloseHandle(p.FProcessHandle)
|
||||
discard closeHandle(p.fProcessHandle)
|
||||
|
||||
proc peekExitCode(p: PProcess): int =
|
||||
var b = waitForSingleObject(p.FProcessHandle, 50) == WAIT_TIMEOUT
|
||||
var b = waitForSingleObject(p.fProcessHandle, 50) == WAIT_TIMEOUT
|
||||
if b: result = -1
|
||||
else:
|
||||
var res: int32
|
||||
discard GetExitCodeProcess(p.FProcessHandle, res)
|
||||
discard getExitCodeProcess(p.fProcessHandle, res)
|
||||
return res
|
||||
|
||||
proc inputStream(p: PProcess): PStream =
|
||||
|
|
@ -511,38 +511,38 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
|
||||
proc execCmd(command: string): int =
|
||||
var
|
||||
SI: TStartupInfo
|
||||
ProcInfo: TProcessInformation
|
||||
si: TSTARTUPINFO
|
||||
procInfo: TPROCESS_INFORMATION
|
||||
process: THandle
|
||||
L: int32
|
||||
SI.cb = SizeOf(SI).cint
|
||||
SI.hStdError = GetStdHandle(STD_ERROR_HANDLE)
|
||||
SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE)
|
||||
SI.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
si.cb = sizeof(si).cint
|
||||
si.hStdError = getStdHandle(STD_ERROR_HANDLE)
|
||||
si.hStdInput = getStdHandle(STD_INPUT_HANDLE)
|
||||
si.hStdOutput = getStdHandle(STD_OUTPUT_HANDLE)
|
||||
when useWinUnicode:
|
||||
var c = newWideCString(command)
|
||||
var res = winlean.CreateProcessW(nil, c, nil, nil, 0,
|
||||
NORMAL_PRIORITY_CLASS, nil, nil, SI, ProcInfo)
|
||||
var res = winlean.createProcessW(nil, c, nil, nil, 0,
|
||||
NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo)
|
||||
else:
|
||||
var res = winlean.CreateProcessA(nil, command, nil, nil, 0,
|
||||
var res = winlean.createProcessA(nil, command, nil, nil, 0,
|
||||
NORMAL_PRIORITY_CLASS, nil, nil, SI, ProcInfo)
|
||||
if res == 0:
|
||||
OSError(OSLastError())
|
||||
osError(osLastError())
|
||||
else:
|
||||
Process = ProcInfo.hProcess
|
||||
discard CloseHandle(ProcInfo.hThread)
|
||||
if WaitForSingleObject(Process, INFINITE) != -1:
|
||||
discard GetExitCodeProcess(Process, L)
|
||||
process = procInfo.hProcess
|
||||
discard closeHandle(procInfo.hThread)
|
||||
if waitForSingleObject(process, INFINITE) != -1:
|
||||
discard getExitCodeProcess(process, L)
|
||||
result = int(L)
|
||||
else:
|
||||
result = -1
|
||||
discard CloseHandle(Process)
|
||||
discard closeHandle(process)
|
||||
|
||||
proc select(readfds: var seq[PProcess], timeout = 500): int =
|
||||
assert readfds.len <= MAXIMUM_WAIT_OBJECTS
|
||||
var rfds: TWOHandleArray
|
||||
for i in 0..readfds.len()-1:
|
||||
rfds[i] = readfds[i].FProcessHandle
|
||||
rfds[i] = readfds[i].fProcessHandle
|
||||
|
||||
var ret = waitForMultipleObjects(readfds.len.int32,
|
||||
addr(rfds), 0'i32, timeout.int32)
|
||||
|
|
@ -550,7 +550,7 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
of WAIT_TIMEOUT:
|
||||
return 0
|
||||
of WAIT_FAILED:
|
||||
OSError(OSLastError())
|
||||
osError(osLastError())
|
||||
else:
|
||||
var i = ret - WAIT_OBJECT_0
|
||||
readfds.del(i)
|
||||
|
|
@ -561,13 +561,13 @@ elif not defined(useNimRtl):
|
|||
readIdx = 0
|
||||
writeIdx = 1
|
||||
|
||||
proc addCmdArgs(command: string, args: openarray[string]): string =
|
||||
proc addCmdArgs(command: string, args: openArray[string]): string =
|
||||
result = quoteShell(command)
|
||||
for i in 0 .. high(args):
|
||||
add(result, " ")
|
||||
add(result, quoteShell(args[i]))
|
||||
|
||||
proc toCStringArray(b, a: openarray[string]): cstringArray =
|
||||
proc toCStringArray(b, a: openArray[string]): cstringArray =
|
||||
result = cast[cstringArray](alloc0((a.len + b.len + 1) * sizeof(cstring)))
|
||||
for i in 0..high(b):
|
||||
result[i] = cast[cstring](alloc(b[i].len+1))
|
||||
|
|
@ -576,7 +576,7 @@ elif not defined(useNimRtl):
|
|||
result[i+b.len] = cast[cstring](alloc(a[i].len+1))
|
||||
copyMem(result[i+b.len], cstring(a[i]), a[i].len+1)
|
||||
|
||||
proc ToCStringArray(t: PStringTable): cstringArray =
|
||||
proc toCStringArray(t: PStringTable): cstringArray =
|
||||
result = cast[cstringArray](alloc0((t.len + 1) * sizeof(cstring)))
|
||||
var i = 0
|
||||
for key, val in pairs(t):
|
||||
|
|
@ -585,7 +585,7 @@ elif not defined(useNimRtl):
|
|||
copyMem(result[i], addr(x[0]), x.len+1)
|
||||
inc(i)
|
||||
|
||||
proc EnvToCStringArray(): cstringArray =
|
||||
proc envToCStringArray(): cstringArray =
|
||||
var counter = 0
|
||||
for key, val in envPairs(): inc counter
|
||||
result = cast[cstringArray](alloc0((counter + 1) * sizeof(cstring)))
|
||||
|
|
@ -598,17 +598,17 @@ elif not defined(useNimRtl):
|
|||
|
||||
proc startProcess(command: string,
|
||||
workingDir: string = "",
|
||||
args: openarray[string] = [],
|
||||
args: openArray[string] = [],
|
||||
env: PStringTable = nil,
|
||||
options: set[TProcessOption] = {poStdErrToStdOut}): PProcess =
|
||||
var
|
||||
p_stdin, p_stdout, p_stderr: array [0..1, cint]
|
||||
pStdin, pStdout, pStderr: array [0..1, cint]
|
||||
new(result)
|
||||
result.exitCode = -3 # for ``waitForExit``
|
||||
if poParentStreams notin options:
|
||||
if pipe(p_stdin) != 0'i32 or pipe(p_stdout) != 0'i32 or
|
||||
pipe(p_stderr) != 0'i32:
|
||||
OSError(OSLastError())
|
||||
if pipe(pStdin) != 0'i32 or pipe(pStdout) != 0'i32 or
|
||||
pipe(pStderr) != 0'i32:
|
||||
osError(osLastError())
|
||||
|
||||
var pid: TPid
|
||||
when defined(posix_spawn) and not defined(useFork):
|
||||
|
|
@ -616,7 +616,7 @@ elif not defined(useNimRtl):
|
|||
var fops: Tposix_spawn_file_actions
|
||||
|
||||
template chck(e: expr) =
|
||||
if e != 0'i32: OSError(OSLastError())
|
||||
if e != 0'i32: osError(osLastError())
|
||||
|
||||
chck posix_spawn_file_actions_init(fops)
|
||||
chck posix_spawnattr_init(attr)
|
||||
|
|
@ -631,17 +631,17 @@ elif not defined(useNimRtl):
|
|||
POSIX_SPAWN_SETPGROUP)
|
||||
|
||||
if poParentStreams notin options:
|
||||
chck posix_spawn_file_actions_addclose(fops, p_stdin[writeIdx])
|
||||
chck posix_spawn_file_actions_adddup2(fops, p_stdin[readIdx], readIdx)
|
||||
chck posix_spawn_file_actions_addclose(fops, p_stdout[readIdx])
|
||||
chck posix_spawn_file_actions_adddup2(fops, p_stdout[writeIdx], writeIdx)
|
||||
chck posix_spawn_file_actions_addclose(fops, p_stderr[readIdx])
|
||||
chck posix_spawn_file_actions_addclose(fops, pStdin[writeIdx])
|
||||
chck posix_spawn_file_actions_adddup2(fops, pStdin[readIdx], readIdx)
|
||||
chck posix_spawn_file_actions_addclose(fops, pStdout[readIdx])
|
||||
chck posix_spawn_file_actions_adddup2(fops, pStdout[writeIdx], writeIdx)
|
||||
chck posix_spawn_file_actions_addclose(fops, pStderr[readIdx])
|
||||
if poStdErrToStdOut in options:
|
||||
chck posix_spawn_file_actions_adddup2(fops, p_stdout[writeIdx], 2)
|
||||
chck posix_spawn_file_actions_adddup2(fops, pStdout[writeIdx], 2)
|
||||
else:
|
||||
chck posix_spawn_file_actions_adddup2(fops, p_stderr[writeIdx], 2)
|
||||
chck posix_spawn_file_actions_adddup2(fops, pStderr[writeIdx], 2)
|
||||
|
||||
var e = if env == nil: EnvToCStringArray() else: ToCStringArray(env)
|
||||
var e = if env == nil: envToCStringArray() else: toCStringArray(env)
|
||||
var a: cstringArray
|
||||
var res: cint
|
||||
if workingDir.len > 0: os.setCurrentDir(workingDir)
|
||||
|
|
@ -660,21 +660,21 @@ elif not defined(useNimRtl):
|
|||
|
||||
else:
|
||||
|
||||
Pid = fork()
|
||||
if Pid < 0: OSError(OSLastError())
|
||||
pid = fork()
|
||||
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(OSLastError())
|
||||
if dup2(p_stdin[readIdx], readIdx) < 0: osError(osLastError())
|
||||
discard close(p_stdout[readIdx])
|
||||
if dup2(p_stdout[writeIdx], writeIdx) < 0: OSError(OSLastError())
|
||||
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(OSLastError())
|
||||
if dup2(p_stdout[writeIdx], 2) < 0: osError(osLastError())
|
||||
else:
|
||||
if dup2(p_stderr[writeIdx], 2) < 0: OSError(OSLastError())
|
||||
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))
|
||||
|
|
@ -685,14 +685,14 @@ elif not defined(useNimRtl):
|
|||
if env == nil:
|
||||
discard execv(command, a)
|
||||
else:
|
||||
discard execve(command, a, ToCStringArray(env))
|
||||
discard execve(command, a, toCStringArray(env))
|
||||
else:
|
||||
var x = addCmdArgs(command, args)
|
||||
var a = toCStringArray(["sh", "-c"], [x])
|
||||
if env == nil:
|
||||
discard execv("/bin/sh", a)
|
||||
else:
|
||||
discard execve("/bin/sh", a, ToCStringArray(env))
|
||||
discard execve("/bin/sh", a, toCStringArray(env))
|
||||
# too risky to raise an exception here:
|
||||
quit("execve call failed: " & $strerror(errno))
|
||||
# Parent process. Copy process information.
|
||||
|
|
@ -709,16 +709,16 @@ elif not defined(useNimRtl):
|
|||
else:
|
||||
result.errHandle = 2
|
||||
else:
|
||||
result.inHandle = p_stdin[writeIdx]
|
||||
result.outHandle = p_stdout[readIdx]
|
||||
result.inHandle = pStdin[writeIdx]
|
||||
result.outHandle = pStdout[readIdx]
|
||||
if poStdErrToStdOut in options:
|
||||
result.errHandle = result.outHandle
|
||||
discard close(p_stderr[readIdx])
|
||||
discard close(pStderr[readIdx])
|
||||
else:
|
||||
result.errHandle = p_stderr[readIdx]
|
||||
discard close(p_stderr[writeIdx])
|
||||
discard close(p_stdin[readIdx])
|
||||
discard close(p_stdout[writeIdx])
|
||||
result.errHandle = pStderr[readIdx]
|
||||
discard close(pStderr[writeIdx])
|
||||
discard close(pStdin[readIdx])
|
||||
discard close(pStdout[writeIdx])
|
||||
|
||||
proc close(p: PProcess) =
|
||||
if p.inStream != nil: close(p.inStream)
|
||||
|
|
@ -729,21 +729,21 @@ elif not defined(useNimRtl):
|
|||
discard close(p.errHandle)
|
||||
|
||||
proc suspend(p: PProcess) =
|
||||
if kill(-p.id, SIGSTOP) != 0'i32: OSError(OSLastError())
|
||||
if kill(-p.id, SIGSTOP) != 0'i32: osError(osLastError())
|
||||
|
||||
proc resume(p: PProcess) =
|
||||
if kill(-p.id, SIGCONT) != 0'i32: OSError(OSLastError())
|
||||
if kill(-p.id, SIGCONT) != 0'i32: osError(osLastError())
|
||||
|
||||
proc running(p: PProcess): bool =
|
||||
var ret = waitPid(p.id, p.exitCode, WNOHANG)
|
||||
var ret = waitpid(p.id, p.exitCode, WNOHANG)
|
||||
if ret == 0: return true # Can't establish status. Assume running.
|
||||
result = ret == int(p.id)
|
||||
|
||||
proc terminate(p: PProcess) =
|
||||
if kill(-p.id, SIGTERM) == 0'i32:
|
||||
if p.running():
|
||||
if kill(-p.id, SIGKILL) != 0'i32: OSError(OSLastError())
|
||||
else: OSError(OSLastError())
|
||||
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):
|
||||
|
|
@ -751,14 +751,14 @@ elif not defined(useNimRtl):
|
|||
# ``running`` probably set ``p.exitCode`` for us. Since ``p.exitCode`` is
|
||||
# initialized with -3, wrong success exit codes are prevented.
|
||||
if p.exitCode != -3: return p.exitCode
|
||||
if waitPid(p.id, p.exitCode, 0) < 0:
|
||||
if waitpid(p.id, p.exitCode, 0) < 0:
|
||||
p.exitCode = -3
|
||||
OSError(OSLastError())
|
||||
osError(osLastError())
|
||||
result = int(p.exitCode) shr 8
|
||||
|
||||
proc peekExitCode(p: PProcess): int =
|
||||
if p.exitCode != -3: return p.exitCode
|
||||
var ret = waitPid(p.id, p.exitCode, WNOHANG)
|
||||
var ret = waitpid(p.id, p.exitCode, WNOHANG)
|
||||
var b = ret == int(p.id)
|
||||
if b: result = -1
|
||||
if p.exitCode == -3: result = -1
|
||||
|
|
@ -767,7 +767,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(OSLastError())
|
||||
if not open(f, handle, fileMode): osError(osLastError())
|
||||
stream = newFileStream(f)
|
||||
|
||||
proc inputStream(p: PProcess): PStream =
|
||||
|
|
@ -800,7 +800,7 @@ elif not defined(useNimRtl):
|
|||
var i = 0
|
||||
var L = s.len
|
||||
while i < L:
|
||||
if FD_ISSET(cint(s[i].outHandle), fd) != 0'i32:
|
||||
if FD_ISSET(cint(s[i].outHandle), fd) == 0'i32:
|
||||
s[i] = s[L-1]
|
||||
dec(L)
|
||||
else:
|
||||
|
|
@ -808,7 +808,7 @@ elif not defined(useNimRtl):
|
|||
setLen(s, L)
|
||||
|
||||
proc select(readfds: var seq[PProcess], timeout = 500): int =
|
||||
var tv: TTimeVal
|
||||
var tv: Ttimeval
|
||||
tv.tv_sec = 0
|
||||
tv.tv_usec = timeout * 1000
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ proc open*(c: var TCfgParser, input: PStream, filename: string,
|
|||
c.filename = filename
|
||||
c.tok.kind = tkInvalid
|
||||
c.tok.literal = ""
|
||||
inc(c.linenumber, lineOffset)
|
||||
inc(c.lineNumber, lineOffset)
|
||||
rawGetTok(c, c.tok)
|
||||
|
||||
proc close*(c: var TCfgParser) {.rtl, extern: "npc$1".} =
|
||||
|
|
@ -91,11 +91,11 @@ proc close*(c: var TCfgParser) {.rtl, extern: "npc$1".} =
|
|||
|
||||
proc getColumn*(c: TCfgParser): int {.rtl, extern: "npc$1".} =
|
||||
## get the current column the parser has arrived at.
|
||||
result = getColNumber(c, c.bufPos)
|
||||
result = getColNumber(c, c.bufpos)
|
||||
|
||||
proc getLine*(c: TCfgParser): int {.rtl, extern: "npc$1".} =
|
||||
## get the current line the parser has arrived at.
|
||||
result = c.linenumber
|
||||
result = c.lineNumber
|
||||
|
||||
proc getFilename*(c: TCfgParser): string {.rtl, extern: "npc$1".} =
|
||||
## get the filename of the file that the parser processes.
|
||||
|
|
@ -113,7 +113,7 @@ proc handleHexChar(c: var TCfgParser, xi: var int) =
|
|||
xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
|
||||
inc(c.bufpos)
|
||||
else:
|
||||
nil
|
||||
discard
|
||||
|
||||
proc handleDecChars(c: var TCfgParser, xi: var int) =
|
||||
while c.buf[c.bufpos] in {'0'..'9'}:
|
||||
|
|
@ -125,74 +125,74 @@ proc getEscapedChar(c: var TCfgParser, tok: var TToken) =
|
|||
case c.buf[c.bufpos]
|
||||
of 'n', 'N':
|
||||
add(tok.literal, "\n")
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'r', 'R', 'c', 'C':
|
||||
add(tok.literal, '\c')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'l', 'L':
|
||||
add(tok.literal, '\L')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'f', 'F':
|
||||
add(tok.literal, '\f')
|
||||
inc(c.bufpos)
|
||||
of 'e', 'E':
|
||||
add(tok.literal, '\e')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'a', 'A':
|
||||
add(tok.literal, '\a')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'b', 'B':
|
||||
add(tok.literal, '\b')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'v', 'V':
|
||||
add(tok.literal, '\v')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 't', 'T':
|
||||
add(tok.literal, '\t')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of '\'', '"':
|
||||
add(tok.literal, c.buf[c.bufpos])
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of '\\':
|
||||
add(tok.literal, '\\')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'x', 'X':
|
||||
inc(c.bufpos)
|
||||
var xi = 0
|
||||
handleHexChar(c, xi)
|
||||
handleHexChar(c, xi)
|
||||
add(tok.literal, Chr(xi))
|
||||
add(tok.literal, chr(xi))
|
||||
of '0'..'9':
|
||||
var xi = 0
|
||||
handleDecChars(c, xi)
|
||||
if (xi <= 255): add(tok.literal, Chr(xi))
|
||||
if (xi <= 255): add(tok.literal, chr(xi))
|
||||
else: tok.kind = tkInvalid
|
||||
else: tok.kind = tkInvalid
|
||||
|
||||
proc HandleCRLF(c: var TCfgParser, pos: int): int =
|
||||
proc handleCRLF(c: var TCfgParser, pos: int): int =
|
||||
case c.buf[pos]
|
||||
of '\c': result = lexbase.HandleCR(c, pos)
|
||||
of '\L': result = lexbase.HandleLF(c, pos)
|
||||
of '\c': result = lexbase.handleCR(c, pos)
|
||||
of '\L': result = lexbase.handleLF(c, pos)
|
||||
else: result = pos
|
||||
|
||||
proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) =
|
||||
var pos = c.bufPos + 1 # skip "
|
||||
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] == '"'):
|
||||
# long string literal:
|
||||
inc(pos, 2) # skip ""
|
||||
# skip leading newline:
|
||||
pos = HandleCRLF(c, pos)
|
||||
pos = handleCRLF(c, pos)
|
||||
buf = c.buf
|
||||
while true:
|
||||
case buf[pos]
|
||||
of '"':
|
||||
if (buf[pos + 1] == '"') and (buf[pos + 2] == '"'): break
|
||||
add(tok.literal, '"')
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
of '\c', '\L':
|
||||
pos = HandleCRLF(c, pos)
|
||||
pos = handleCRLF(c, pos)
|
||||
buf = c.buf
|
||||
add(tok.literal, "\n")
|
||||
of lexbase.EndOfFile:
|
||||
|
|
@ -200,7 +200,7 @@ proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) =
|
|||
break
|
||||
else:
|
||||
add(tok.literal, buf[pos])
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
c.bufpos = pos + 3 # skip the three """
|
||||
else:
|
||||
# ordinary string literal
|
||||
|
|
@ -213,12 +213,12 @@ proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) =
|
|||
tok.kind = tkInvalid
|
||||
break
|
||||
if (ch == '\\') and not rawMode:
|
||||
c.bufPos = pos
|
||||
c.bufpos = pos
|
||||
getEscapedChar(c, tok)
|
||||
pos = c.bufPos
|
||||
pos = c.bufpos
|
||||
else:
|
||||
add(tok.literal, ch)
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
c.bufpos = pos
|
||||
|
||||
proc getSymbol(c: var TCfgParser, tok: var TToken) =
|
||||
|
|
@ -226,7 +226,7 @@ proc getSymbol(c: var TCfgParser, tok: var TToken) =
|
|||
var buf = c.buf
|
||||
while true:
|
||||
add(tok.literal, buf[pos])
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
if not (buf[pos] in SymChars): break
|
||||
c.bufpos = pos
|
||||
tok.kind = tkSymbol
|
||||
|
|
@ -237,11 +237,11 @@ proc skip(c: var TCfgParser) =
|
|||
while true:
|
||||
case buf[pos]
|
||||
of ' ', '\t':
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
of '#', ';':
|
||||
while not (buf[pos] in {'\c', '\L', lexbase.EndOfFile}): inc(pos)
|
||||
of '\c', '\L':
|
||||
pos = HandleCRLF(c, pos)
|
||||
pos = handleCRLF(c, pos)
|
||||
buf = c.buf
|
||||
else:
|
||||
break # EndOfFile also leaves the loop
|
||||
|
|
@ -249,7 +249,7 @@ proc skip(c: var TCfgParser) =
|
|||
|
||||
proc rawGetTok(c: var TCfgParser, tok: var TToken) =
|
||||
tok.kind = tkInvalid
|
||||
setlen(tok.literal, 0)
|
||||
setLen(tok.literal, 0)
|
||||
skip(c)
|
||||
case c.buf[c.bufpos]
|
||||
of '=':
|
||||
|
|
@ -257,8 +257,8 @@ proc rawGetTok(c: var TCfgParser, tok: var TToken) =
|
|||
inc(c.bufpos)
|
||||
tok.literal = "="
|
||||
of '-':
|
||||
inc(c.bufPos)
|
||||
if c.buf[c.bufPos] == '-': inc(c.bufPos)
|
||||
inc(c.bufpos)
|
||||
if c.buf[c.bufpos] == '-': inc(c.bufpos)
|
||||
tok.kind = tkDashDash
|
||||
tok.literal = "--"
|
||||
of ':':
|
||||
|
|
@ -266,8 +266,8 @@ proc rawGetTok(c: var TCfgParser, tok: var TToken) =
|
|||
inc(c.bufpos)
|
||||
tok.literal = ":"
|
||||
of 'r', 'R':
|
||||
if c.buf[c.bufPos + 1] == '\"':
|
||||
Inc(c.bufPos)
|
||||
if c.buf[c.bufpos + 1] == '\"':
|
||||
inc(c.bufpos)
|
||||
getString(c, tok, true)
|
||||
else:
|
||||
getSymbol(c, tok)
|
||||
|
|
@ -277,7 +277,7 @@ proc rawGetTok(c: var TCfgParser, tok: var TToken) =
|
|||
tok.literal = "]"
|
||||
of ']':
|
||||
tok.kind = tkBracketRi
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
tok.literal = "]"
|
||||
of '"':
|
||||
getString(c, tok, false)
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
## It supports one convenience iterator over all command line options and some
|
||||
## lower-level features.
|
||||
##
|
||||
## DEPRECATED. Use parseopt2 instead as this version has issues with spaces
|
||||
## in arguments.
|
||||
## **Deprecated since version 0.9.3:** Use the `parseopt2 <parseopt2.html>`_
|
||||
## module instead as this version has issues with spaces in arguments.
|
||||
{.deprecated.}
|
||||
{.push debugger: off.}
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ type
|
|||
## or the argument, ``value`` is not "" if
|
||||
## the option was given a value
|
||||
|
||||
when defined(os.ParamCount):
|
||||
when defined(os.paramCount):
|
||||
# we cannot provide this for NimRtl creation on Posix, because we can't
|
||||
# access the command line arguments then!
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ when defined(os.ParamCount):
|
|||
result.cmd = cmdline
|
||||
else:
|
||||
result.cmd = ""
|
||||
for i in countup(1, ParamCount()):
|
||||
for i in countup(1, paramCount()):
|
||||
result.cmd = result.cmd & quoteIfContainsWhite(paramStr(i).string) & ' '
|
||||
result.kind = cmdEnd
|
||||
result.key = TaintedString""
|
||||
|
|
@ -94,8 +94,8 @@ proc next*(p: var TOptParser) {.
|
|||
var i = p.pos
|
||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||
p.pos = i
|
||||
setlen(p.key.string, 0)
|
||||
setlen(p.val.string, 0)
|
||||
setLen(p.key.string, 0)
|
||||
setLen(p.val.string, 0)
|
||||
if p.inShortState:
|
||||
handleShortOption(p)
|
||||
return
|
||||
|
|
@ -105,7 +105,7 @@ proc next*(p: var TOptParser) {.
|
|||
of '-':
|
||||
inc(i)
|
||||
if p.cmd[i] == '-':
|
||||
p.kind = cmdLongOption
|
||||
p.kind = cmdLongoption
|
||||
inc(i)
|
||||
i = parseWord(p.cmd, i, p.key.string, {'\0', ' ', '\x09', ':', '='})
|
||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ proc parseHex*(s: string, number: var int, start = 0): int {.
|
|||
elif s[i] == '#': inc(i)
|
||||
while true:
|
||||
case s[i]
|
||||
of '_': nil
|
||||
of '_': discard
|
||||
of '0'..'9':
|
||||
number = number shl 4 or (ord(s[i]) - ord('0'))
|
||||
foundDigit = true
|
||||
|
|
@ -74,7 +74,7 @@ proc parseOct*(s: string, number: var int, start = 0): int {.
|
|||
if s[i] == '0' and (s[i+1] == 'o' or s[i+1] == 'O'): inc(i, 2)
|
||||
while true:
|
||||
case s[i]
|
||||
of '_': nil
|
||||
of '_': discard
|
||||
of '0'..'7':
|
||||
number = number shl 3 or (ord(s[i]) - ord('0'))
|
||||
foundDigit = true
|
||||
|
|
@ -189,7 +189,7 @@ proc captureBetween*(s: string, first: char, second = '\0', start = 0): string =
|
|||
|
||||
{.push overflowChecks: on.}
|
||||
# this must be compiled with overflow checking turned on:
|
||||
proc rawParseInt(s: string, b: var biggestInt, start = 0): int =
|
||||
proc rawParseInt(s: string, b: var BiggestInt, start = 0): int =
|
||||
var
|
||||
sign: BiggestInt = -1
|
||||
i = start
|
||||
|
|
@ -207,12 +207,12 @@ proc rawParseInt(s: string, b: var biggestInt, start = 0): int =
|
|||
result = i - start
|
||||
{.pop.} # overflowChecks
|
||||
|
||||
proc parseBiggestInt*(s: string, number: var biggestInt, start = 0): int {.
|
||||
proc parseBiggestInt*(s: string, number: var BiggestInt, start = 0): int {.
|
||||
rtl, extern: "npuParseBiggestInt", noSideEffect.} =
|
||||
## parses an integer starting at `start` and stores the value into `number`.
|
||||
## Result is the number of processed chars or 0 if there is no integer.
|
||||
## `EOverflow` is raised if an overflow occurs.
|
||||
var res: biggestInt
|
||||
var res: BiggestInt
|
||||
# use 'res' for exception safety (don't write to 'number' in case of an
|
||||
# overflow exception:
|
||||
result = rawParseInt(s, res, start)
|
||||
|
|
@ -223,7 +223,7 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
|
|||
## parses an integer starting at `start` and stores the value into `number`.
|
||||
## Result is the number of processed chars or 0 if there is no integer.
|
||||
## `EOverflow` is raised if an overflow occurs.
|
||||
var res: biggestInt
|
||||
var res: BiggestInt
|
||||
result = parseBiggestInt(s, res, start)
|
||||
if (sizeof(int) <= 4) and
|
||||
((res < low(int)) or (res > high(int))):
|
||||
|
|
@ -231,7 +231,7 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
|
|||
else:
|
||||
number = int(res)
|
||||
|
||||
proc tenToThePowerOf(b: int): biggestFloat =
|
||||
proc tenToThePowerOf(b: int): BiggestFloat =
|
||||
var b = b
|
||||
var a = 10.0
|
||||
result = 1.0
|
||||
|
|
@ -242,7 +242,7 @@ proc tenToThePowerOf(b: int): biggestFloat =
|
|||
if b == 0: break
|
||||
a *= a
|
||||
|
||||
proc parseBiggestFloat*(s: string, number: var biggestFloat, start = 0): int {.
|
||||
proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
|
||||
rtl, extern: "npuParseBiggestFloat", noSideEffect.} =
|
||||
## parses a float starting at `start` and stores the value into `number`.
|
||||
## Result is the number of processed chars or 0 if there occured a parsing
|
||||
|
|
@ -319,7 +319,7 @@ proc parseFloat*(s: string, number: var float, start = 0): int {.
|
|||
## parses a float starting at `start` and stores the value into `number`.
|
||||
## Result is the number of processed chars or 0 if there occured a parsing
|
||||
## error.
|
||||
var bf: biggestFloat
|
||||
var bf: BiggestFloat
|
||||
result = parseBiggestFloat(s, bf, start)
|
||||
number = bf
|
||||
|
||||
|
|
@ -370,7 +370,7 @@ iterator interpolatedFragments*(s: string): tuple[kind: TInterpolatedKind,
|
|||
of '\0':
|
||||
raise newException(EInvalidValue,
|
||||
"Expected closing '}': " & s[i..s.len])
|
||||
else: nil
|
||||
else: discard
|
||||
inc j
|
||||
inc i, 2 # skip ${
|
||||
kind = ikExpr
|
||||
|
|
|
|||
|
|
@ -249,23 +249,23 @@ proc newLine*: TPeg {.inline.} =
|
|||
## constructs the PEG `newline`:idx: (``\n``)
|
||||
result.kind = pkNewline
|
||||
|
||||
proc UnicodeLetter*: TPeg {.inline.} =
|
||||
proc unicodeLetter*: TPeg {.inline.} =
|
||||
## constructs the PEG ``\letter`` which matches any Unicode letter.
|
||||
result.kind = pkLetter
|
||||
|
||||
proc UnicodeLower*: TPeg {.inline.} =
|
||||
proc unicodeLower*: TPeg {.inline.} =
|
||||
## constructs the PEG ``\lower`` which matches any Unicode lowercase letter.
|
||||
result.kind = pkLower
|
||||
|
||||
proc UnicodeUpper*: TPeg {.inline.} =
|
||||
proc unicodeUpper*: TPeg {.inline.} =
|
||||
## constructs the PEG ``\upper`` which matches any Unicode uppercase letter.
|
||||
result.kind = pkUpper
|
||||
|
||||
proc UnicodeTitle*: TPeg {.inline.} =
|
||||
proc unicodeTitle*: TPeg {.inline.} =
|
||||
## constructs the PEG ``\title`` which matches any Unicode title letter.
|
||||
result.kind = pkTitle
|
||||
|
||||
proc UnicodeWhitespace*: TPeg {.inline.} =
|
||||
proc unicodeWhitespace*: TPeg {.inline.} =
|
||||
## constructs the PEG ``\white`` which matches any Unicode
|
||||
## whitespace character.
|
||||
result.kind = pkWhitespace
|
||||
|
|
@ -306,7 +306,7 @@ proc backrefIgnoreStyle*(index: range[1..MaxSubPatterns]): TPeg {.
|
|||
|
||||
proc spaceCost(n: TPeg): int =
|
||||
case n.kind
|
||||
of pkEmpty: nil
|
||||
of pkEmpty: discard
|
||||
of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar,
|
||||
pkGreedyRepChar, pkCharChoice, pkGreedyRepSet,
|
||||
pkAny..pkWhitespace, pkGreedyAny:
|
||||
|
|
@ -340,28 +340,28 @@ proc newNonTerminal*(name: string, line, column: int): PNonTerminal {.
|
|||
|
||||
template letters*: expr =
|
||||
## expands to ``charset({'A'..'Z', 'a'..'z'})``
|
||||
charset({'A'..'Z', 'a'..'z'})
|
||||
charSet({'A'..'Z', 'a'..'z'})
|
||||
|
||||
template digits*: expr =
|
||||
## expands to ``charset({'0'..'9'})``
|
||||
charset({'0'..'9'})
|
||||
charSet({'0'..'9'})
|
||||
|
||||
template whitespace*: expr =
|
||||
## expands to ``charset({' ', '\9'..'\13'})``
|
||||
charset({' ', '\9'..'\13'})
|
||||
charSet({' ', '\9'..'\13'})
|
||||
|
||||
template identChars*: expr =
|
||||
## expands to ``charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})``
|
||||
charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})
|
||||
charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'})
|
||||
|
||||
template identStartChars*: expr =
|
||||
## expands to ``charset({'A'..'Z', 'a'..'z', '_'})``
|
||||
charset({'a'..'z', 'A'..'Z', '_'})
|
||||
charSet({'a'..'z', 'A'..'Z', '_'})
|
||||
|
||||
template ident*: expr =
|
||||
## same as ``[a-zA-Z_][a-zA-z_0-9]*``; standard identifier
|
||||
sequence(charset({'a'..'z', 'A'..'Z', '_'}),
|
||||
*charset({'a'..'z', 'A'..'Z', '0'..'9', '_'}))
|
||||
sequence(charSet({'a'..'z', 'A'..'Z', '_'}),
|
||||
*charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'}))
|
||||
|
||||
template natural*: expr =
|
||||
## same as ``\d+``
|
||||
|
|
@ -385,7 +385,7 @@ proc esc(c: char, reserved = {'\0'..'\255'}): string =
|
|||
elif c in reserved: result = '\\' & c
|
||||
else: result = $c
|
||||
|
||||
proc singleQuoteEsc(c: Char): string = return "'" & esc(c, {'\''}) & "'"
|
||||
proc singleQuoteEsc(c: char): string = return "'" & esc(c, {'\''}) & "'"
|
||||
|
||||
proc singleQuoteEsc(str: string): string =
|
||||
result = "'"
|
||||
|
|
@ -409,11 +409,11 @@ proc charSetEscAux(cc: set[char]): string =
|
|||
c1 = c2
|
||||
inc(c1)
|
||||
|
||||
proc CharSetEsc(cc: set[char]): string =
|
||||
proc charSetEsc(cc: set[char]): string =
|
||||
if card(cc) >= 128+64:
|
||||
result = "[^" & CharSetEscAux({'\1'..'\xFF'} - cc) & ']'
|
||||
result = "[^" & charSetEscAux({'\1'..'\xFF'} - cc) & ']'
|
||||
else:
|
||||
result = '[' & CharSetEscAux(cc) & ']'
|
||||
result = '[' & charSetEscAux(cc) & ']'
|
||||
|
||||
proc toStrAux(r: TPeg, res: var string) =
|
||||
case r.kind
|
||||
|
|
@ -590,7 +590,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
|
|||
var a: TRune
|
||||
result = start
|
||||
fastRuneAt(s, result, a)
|
||||
if isWhitespace(a): dec(result, start)
|
||||
if isWhiteSpace(a): dec(result, start)
|
||||
else: result = -1
|
||||
else:
|
||||
result = -1
|
||||
|
|
@ -747,7 +747,7 @@ template fillMatches(s, caps, c: expr) =
|
|||
for k in 0..c.ml-1:
|
||||
caps[k] = substr(s, c.matches[k][0], c.matches[k][1])
|
||||
|
||||
proc match*(s: string, pattern: TPeg, matches: var openarray[string],
|
||||
proc match*(s: string, pattern: TPeg, matches: var openArray[string],
|
||||
start = 0): bool {.nosideEffect, rtl, extern: "npegs$1Capture".} =
|
||||
## returns ``true`` if ``s[start..]`` matches the ``pattern`` and
|
||||
## the captured substrings in the array ``matches``. If it does not
|
||||
|
|
@ -765,7 +765,7 @@ proc match*(s: string, pattern: TPeg,
|
|||
c.origStart = start
|
||||
result = rawMatch(s, pattern, start, c) == len(s)-start
|
||||
|
||||
proc matchLen*(s: string, pattern: TPeg, matches: var openarray[string],
|
||||
proc matchLen*(s: string, pattern: TPeg, matches: var openArray[string],
|
||||
start = 0): int {.nosideEffect, rtl, extern: "npegs$1Capture".} =
|
||||
## the same as ``match``, but it returns the length of the match,
|
||||
## if there is no match, -1 is returned. Note that a match length
|
||||
|
|
@ -786,7 +786,7 @@ proc matchLen*(s: string, pattern: TPeg,
|
|||
c.origStart = start
|
||||
result = rawMatch(s, pattern, start, c)
|
||||
|
||||
proc find*(s: string, pattern: TPeg, matches: var openarray[string],
|
||||
proc find*(s: string, pattern: TPeg, matches: var openArray[string],
|
||||
start = 0): int {.nosideEffect, rtl, extern: "npegs$1Capture".} =
|
||||
## returns the starting position of ``pattern`` in ``s`` and the captured
|
||||
## substrings in the array ``matches``. If it does not match, nothing
|
||||
|
|
@ -801,7 +801,7 @@ proc find*(s: string, pattern: TPeg, matches: var openarray[string],
|
|||
return -1
|
||||
# could also use the pattern here: (!P .)* P
|
||||
|
||||
proc findBounds*(s: string, pattern: TPeg, matches: var openarray[string],
|
||||
proc findBounds*(s: string, pattern: TPeg, matches: var openArray[string],
|
||||
start = 0): tuple[first, last: int] {.
|
||||
nosideEffect, rtl, extern: "npegs$1Capture".} =
|
||||
## returns the starting position and end position of ``pattern`` in ``s``
|
||||
|
|
@ -869,7 +869,7 @@ template `=~`*(s: string, pattern: TPeg): bool =
|
|||
##
|
||||
bind maxSubpatterns
|
||||
when not definedInScope(matches):
|
||||
var matches {.inject.}: array[0..maxSubpatterns-1, string]
|
||||
var matches {.inject.}: array[0..MaxSubpatterns-1, string]
|
||||
match(s, pattern, matches)
|
||||
|
||||
# ------------------------- more string handling ------------------------------
|
||||
|
|
@ -1074,14 +1074,14 @@ const
|
|||
"@", "built-in", "escaped", "$", "$", "^"
|
||||
]
|
||||
|
||||
proc HandleCR(L: var TPegLexer, pos: int): int =
|
||||
proc handleCR(L: var TPegLexer, pos: int): int =
|
||||
assert(L.buf[pos] == '\c')
|
||||
inc(L.linenumber)
|
||||
result = pos+1
|
||||
if L.buf[result] == '\L': inc(result)
|
||||
L.lineStart = result
|
||||
|
||||
proc HandleLF(L: var TPegLexer, pos: int): int =
|
||||
proc handleLF(L: var TPegLexer, pos: int): int =
|
||||
assert(L.buf[pos] == '\L')
|
||||
inc(L.linenumber)
|
||||
result = pos+1
|
||||
|
|
@ -1117,45 +1117,45 @@ proc handleHexChar(c: var TPegLexer, xi: var int) =
|
|||
of 'A'..'F':
|
||||
xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
|
||||
inc(c.bufpos)
|
||||
else: nil
|
||||
else: discard
|
||||
|
||||
proc getEscapedChar(c: var TPegLexer, tok: var TToken) =
|
||||
inc(c.bufpos)
|
||||
case c.buf[c.bufpos]
|
||||
of 'r', 'R', 'c', 'C':
|
||||
add(tok.literal, '\c')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'l', 'L':
|
||||
add(tok.literal, '\L')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'f', 'F':
|
||||
add(tok.literal, '\f')
|
||||
inc(c.bufpos)
|
||||
of 'e', 'E':
|
||||
add(tok.literal, '\e')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'a', 'A':
|
||||
add(tok.literal, '\a')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'b', 'B':
|
||||
add(tok.literal, '\b')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'v', 'V':
|
||||
add(tok.literal, '\v')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 't', 'T':
|
||||
add(tok.literal, '\t')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'x', 'X':
|
||||
inc(c.bufpos)
|
||||
var xi = 0
|
||||
handleHexChar(c, xi)
|
||||
handleHexChar(c, xi)
|
||||
if xi == 0: tok.kind = tkInvalid
|
||||
else: add(tok.literal, Chr(xi))
|
||||
else: add(tok.literal, chr(xi))
|
||||
of '0'..'9':
|
||||
var val = ord(c.buf[c.bufpos]) - ord('0')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
var i = 1
|
||||
while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}):
|
||||
val = val * 10 + ord(c.buf[c.bufpos]) - ord('0')
|
||||
|
|
@ -1169,7 +1169,7 @@ proc getEscapedChar(c: var TPegLexer, tok: var TToken) =
|
|||
tok.kind = tkInvalid
|
||||
else:
|
||||
add(tok.literal, c.buf[c.bufpos])
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
|
||||
proc skip(c: var TPegLexer) =
|
||||
var pos = c.bufpos
|
||||
|
|
@ -1177,14 +1177,14 @@ proc skip(c: var TPegLexer) =
|
|||
while true:
|
||||
case buf[pos]
|
||||
of ' ', '\t':
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
of '#':
|
||||
while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
|
||||
of '\c':
|
||||
pos = HandleCR(c, pos)
|
||||
pos = handleCR(c, pos)
|
||||
buf = c.buf
|
||||
of '\L':
|
||||
pos = HandleLF(c, pos)
|
||||
pos = handleLF(c, pos)
|
||||
buf = c.buf
|
||||
else:
|
||||
break # EndOfFile also leaves the loop
|
||||
|
|
@ -1209,7 +1209,7 @@ proc getString(c: var TPegLexer, tok: var TToken) =
|
|||
break
|
||||
else:
|
||||
add(tok.literal, buf[pos])
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
c.bufpos = pos
|
||||
|
||||
proc getDollar(c: var TPegLexer, tok: var TToken) =
|
||||
|
|
@ -1250,7 +1250,7 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) =
|
|||
break
|
||||
else:
|
||||
ch = buf[pos]
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
incl(tok.charset, ch)
|
||||
if buf[pos] == '-':
|
||||
if buf[pos+1] == ']':
|
||||
|
|
@ -1270,7 +1270,7 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) =
|
|||
break
|
||||
else:
|
||||
ch2 = buf[pos]
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
for i in ord(ch)+1 .. ord(ch2):
|
||||
incl(tok.charset, chr(i))
|
||||
c.bufpos = pos
|
||||
|
|
@ -1281,7 +1281,7 @@ proc getSymbol(c: var TPegLexer, tok: var TToken) =
|
|||
var buf = c.buf
|
||||
while true:
|
||||
add(tok.literal, buf[pos])
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
if buf[pos] notin strutils.IdentChars: break
|
||||
c.bufpos = pos
|
||||
tok.kind = tkIdentifier
|
||||
|
|
@ -1298,7 +1298,7 @@ proc getBuiltin(c: var TPegLexer, tok: var TToken) =
|
|||
proc getTok(c: var TPegLexer, tok: var TToken) =
|
||||
tok.kind = tkInvalid
|
||||
tok.modifier = modNone
|
||||
setlen(tok.literal, 0)
|
||||
setLen(tok.literal, 0)
|
||||
skip(c)
|
||||
case c.buf[c.bufpos]
|
||||
of '{':
|
||||
|
|
@ -1315,14 +1315,14 @@ proc getTok(c: var TPegLexer, tok: var TToken) =
|
|||
inc(c.bufpos)
|
||||
add(tok.literal, '}')
|
||||
of '[':
|
||||
getCharset(c, tok)
|
||||
getCharSet(c, tok)
|
||||
of '(':
|
||||
tok.kind = tkParLe
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
add(tok.literal, '(')
|
||||
of ')':
|
||||
tok.kind = tkParRi
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
add(tok.literal, ')')
|
||||
of '.':
|
||||
tok.kind = tkAny
|
||||
|
|
@ -1347,7 +1347,7 @@ proc getTok(c: var TPegLexer, tok: var TToken) =
|
|||
of "i": tok.modifier = modIgnoreCase
|
||||
of "y": tok.modifier = modIgnoreStyle
|
||||
of "v": tok.modifier = modVerbatim
|
||||
else: nil
|
||||
else: discard
|
||||
setLen(tok.literal, 0)
|
||||
if c.buf[c.bufpos] == '$':
|
||||
getDollar(c, tok)
|
||||
|
|
@ -1452,28 +1452,28 @@ proc modifiedTerm(s: string, m: TModifier): TPeg =
|
|||
|
||||
proc modifiedBackref(s: int, m: TModifier): TPeg =
|
||||
case m
|
||||
of modNone, modVerbatim: result = backRef(s)
|
||||
of modIgnoreCase: result = backRefIgnoreCase(s)
|
||||
of modIgnoreStyle: result = backRefIgnoreStyle(s)
|
||||
of modNone, modVerbatim: result = backref(s)
|
||||
of modIgnoreCase: result = backrefIgnoreCase(s)
|
||||
of modIgnoreStyle: result = backrefIgnoreStyle(s)
|
||||
|
||||
proc builtin(p: var TPegParser): TPeg =
|
||||
# do not use "y", "skip" or "i" as these would be ambiguous
|
||||
case p.tok.literal
|
||||
of "n": result = newLine()
|
||||
of "d": result = charset({'0'..'9'})
|
||||
of "D": result = charset({'\1'..'\xff'} - {'0'..'9'})
|
||||
of "s": result = charset({' ', '\9'..'\13'})
|
||||
of "S": result = charset({'\1'..'\xff'} - {' ', '\9'..'\13'})
|
||||
of "w": result = charset({'a'..'z', 'A'..'Z', '_', '0'..'9'})
|
||||
of "W": result = charset({'\1'..'\xff'} - {'a'..'z','A'..'Z','_','0'..'9'})
|
||||
of "a": result = charset({'a'..'z', 'A'..'Z'})
|
||||
of "A": result = charset({'\1'..'\xff'} - {'a'..'z', 'A'..'Z'})
|
||||
of "d": result = charSet({'0'..'9'})
|
||||
of "D": result = charSet({'\1'..'\xff'} - {'0'..'9'})
|
||||
of "s": result = charSet({' ', '\9'..'\13'})
|
||||
of "S": result = charSet({'\1'..'\xff'} - {' ', '\9'..'\13'})
|
||||
of "w": result = charSet({'a'..'z', 'A'..'Z', '_', '0'..'9'})
|
||||
of "W": result = charSet({'\1'..'\xff'} - {'a'..'z','A'..'Z','_','0'..'9'})
|
||||
of "a": result = charSet({'a'..'z', 'A'..'Z'})
|
||||
of "A": result = charSet({'\1'..'\xff'} - {'a'..'z', 'A'..'Z'})
|
||||
of "ident": result = pegs.ident
|
||||
of "letter": result = UnicodeLetter()
|
||||
of "upper": result = UnicodeUpper()
|
||||
of "lower": result = UnicodeLower()
|
||||
of "title": result = UnicodeTitle()
|
||||
of "white": result = UnicodeWhitespace()
|
||||
of "letter": result = unicodeLetter()
|
||||
of "upper": result = unicodeUpper()
|
||||
of "lower": result = unicodeLower()
|
||||
of "title": result = unicodeTitle()
|
||||
of "white": result = unicodeWhitespace()
|
||||
else: pegError(p, "unknown built-in: " & p.tok.literal)
|
||||
|
||||
proc token(terminal: TPeg, p: TPegParser): TPeg =
|
||||
|
|
@ -1494,7 +1494,7 @@ proc primary(p: var TPegParser): TPeg =
|
|||
of tkCurlyAt:
|
||||
getTok(p)
|
||||
return !*\primary(p).token(p)
|
||||
else: nil
|
||||
else: discard
|
||||
case p.tok.kind
|
||||
of tkIdentifier:
|
||||
if p.identIsVerbatim:
|
||||
|
|
@ -1505,7 +1505,7 @@ proc primary(p: var TPegParser): TPeg =
|
|||
elif not arrowIsNextTok(p):
|
||||
var nt = getNonTerminal(p, p.tok.literal)
|
||||
incl(nt.flags, ntUsed)
|
||||
result = nonTerminal(nt).token(p)
|
||||
result = nonterminal(nt).token(p)
|
||||
getTok(p)
|
||||
else:
|
||||
pegError(p, "expression expected, but found: " & p.tok.literal)
|
||||
|
|
@ -1517,7 +1517,7 @@ proc primary(p: var TPegParser): TPeg =
|
|||
of tkCharSet:
|
||||
if '\0' in p.tok.charset:
|
||||
pegError(p, "binary zero ('\\0') not allowed in character class")
|
||||
result = charset(p.tok.charset).token(p)
|
||||
result = charSet(p.tok.charset).token(p)
|
||||
getTok(p)
|
||||
of tkParLe:
|
||||
getTok(p)
|
||||
|
|
@ -1549,7 +1549,7 @@ proc primary(p: var TPegParser): TPeg =
|
|||
of tkBackref:
|
||||
var m = p.tok.modifier
|
||||
if m == modNone: m = p.modifier
|
||||
result = modifiedBackRef(p.tok.index, m).token(p)
|
||||
result = modifiedBackref(p.tok.index, m).token(p)
|
||||
if p.tok.index < 0 or p.tok.index > p.captures:
|
||||
pegError(p, "invalid back reference index: " & $p.tok.index)
|
||||
getTok(p)
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ proc next*(s: var TScgistate, timeout: int = -1): bool =
|
|||
## request, if ``timeout`` is `-1` then this function will never time out.
|
||||
## Returns `True` if a new request has been processed.
|
||||
var rsocks = @[s.server]
|
||||
if select(rsocks, timeout) == 1 and rsocks.len == 0:
|
||||
if select(rsocks, timeout) == 1 and rsocks.len == 1:
|
||||
new(s.client)
|
||||
accept(s.server, s.client)
|
||||
var L = 0
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
{.deadCodeElim: on.}
|
||||
|
||||
when hostos == "solaris":
|
||||
when hostOS == "solaris":
|
||||
{.passl: "-lsocket -lnsl".}
|
||||
|
||||
import os, parseutils
|
||||
|
|
@ -132,17 +132,17 @@ type
|
|||
ETimeout* = object of ESynch
|
||||
|
||||
let
|
||||
InvalidSocket*: TSocket = nil ## invalid socket
|
||||
invalidSocket*: TSocket = nil ## invalid socket
|
||||
|
||||
when defined(windows):
|
||||
let
|
||||
OSInvalidSocket = winlean.INVALID_SOCKET
|
||||
osInvalidSocket = winlean.INVALID_SOCKET
|
||||
else:
|
||||
let
|
||||
OSInvalidSocket = posix.INVALID_SOCKET
|
||||
osInvalidSocket = posix.INVALID_SOCKET
|
||||
|
||||
proc newTSocket(fd: TSocketHandle, isBuff: bool): TSocket =
|
||||
if fd == OSInvalidSocket:
|
||||
if fd == osInvalidSocket:
|
||||
return nil
|
||||
new(result)
|
||||
result.fd = fd
|
||||
|
|
@ -187,22 +187,22 @@ proc htons*(x: int16): int16 =
|
|||
result = sockets.ntohs(x)
|
||||
|
||||
when defined(Posix):
|
||||
proc ToInt(domain: TDomain): cint =
|
||||
proc toInt(domain: TDomain): cint =
|
||||
case domain
|
||||
of AF_UNIX: result = posix.AF_UNIX
|
||||
of AF_INET: result = posix.AF_INET
|
||||
of AF_INET6: result = posix.AF_INET6
|
||||
else: nil
|
||||
else: discard
|
||||
|
||||
proc ToInt(typ: TType): cint =
|
||||
proc toInt(typ: TType): cint =
|
||||
case typ
|
||||
of SOCK_STREAM: result = posix.SOCK_STREAM
|
||||
of SOCK_DGRAM: result = posix.SOCK_DGRAM
|
||||
of SOCK_SEQPACKET: result = posix.SOCK_SEQPACKET
|
||||
of SOCK_RAW: result = posix.SOCK_RAW
|
||||
else: nil
|
||||
else: discard
|
||||
|
||||
proc ToInt(p: TProtocol): cint =
|
||||
proc toInt(p: TProtocol): cint =
|
||||
case p
|
||||
of IPPROTO_TCP: result = posix.IPPROTO_TCP
|
||||
of IPPROTO_UDP: result = posix.IPPROTO_UDP
|
||||
|
|
@ -210,16 +210,16 @@ when defined(Posix):
|
|||
of IPPROTO_IPV6: result = posix.IPPROTO_IPV6
|
||||
of IPPROTO_RAW: result = posix.IPPROTO_RAW
|
||||
of IPPROTO_ICMP: result = posix.IPPROTO_ICMP
|
||||
else: nil
|
||||
else: discard
|
||||
|
||||
else:
|
||||
proc toInt(domain: TDomain): cint =
|
||||
result = toU16(ord(domain))
|
||||
|
||||
proc ToInt(typ: TType): cint =
|
||||
proc toInt(typ: TType): cint =
|
||||
result = cint(ord(typ))
|
||||
|
||||
proc ToInt(p: TProtocol): cint =
|
||||
proc toInt(p: TProtocol): cint =
|
||||
result = cint(ord(p))
|
||||
|
||||
proc socket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
|
||||
|
|
@ -230,7 +230,7 @@ proc socket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM,
|
|||
when defined(Windows):
|
||||
result = newTSocket(winlean.socket(ord(domain), ord(typ), ord(protocol)), buffered)
|
||||
else:
|
||||
result = newTSocket(posix.socket(ToInt(domain), ToInt(typ), ToInt(protocol)), buffered)
|
||||
result = newTSocket(posix.socket(toInt(domain), toInt(typ), toInt(protocol)), buffered)
|
||||
|
||||
when defined(ssl):
|
||||
CRYPTO_malloc_init()
|
||||
|
|
@ -333,7 +333,7 @@ when defined(ssl):
|
|||
if SSLSetFd(socket.sslHandle, socket.fd) != 1:
|
||||
SSLError()
|
||||
|
||||
proc SocketError*(socket: TSocket, err: int = -1, async = false) =
|
||||
proc socketError*(socket: TSocket, err: int = -1, async = false) =
|
||||
## Raises proper errors based on return values of ``recv`` functions.
|
||||
##
|
||||
## If ``async`` is ``True`` no error will be thrown in the case when the
|
||||
|
|
@ -362,28 +362,28 @@ 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()
|
||||
let lastError = osLastError()
|
||||
if async:
|
||||
when defined(windows):
|
||||
if lastError.int32 == WSAEWOULDBLOCK:
|
||||
return
|
||||
else: OSError(lastError)
|
||||
else: osError(lastError)
|
||||
else:
|
||||
if lastError.int32 == EAGAIN or lastError.int32 == EWOULDBLOCK:
|
||||
return
|
||||
else: OSError(lastError)
|
||||
else: OSError(lastError)
|
||||
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(OSLastError())
|
||||
if listen(socket.fd, cint(backlog)) < 0'i32: osError(osLastError())
|
||||
|
||||
proc invalidIp4(s: string) {.noreturn, noinline.} =
|
||||
raise newException(EInvalidValue, "invalid ip4 address: " & s)
|
||||
|
||||
proc parseIp4*(s: string): biggestInt =
|
||||
proc parseIp4*(s: string): BiggestInt =
|
||||
## parses an IP version 4 in dotted decimal form like "a.b.c.d".
|
||||
##
|
||||
## This is equivalent to `inet_ntoa`:idx:.
|
||||
|
|
@ -410,14 +410,14 @@ proc parseIp4*(s: string): biggestInt =
|
|||
if j <= 0: invalidIp4(s)
|
||||
inc(i, j)
|
||||
if s[i] != '\0': invalidIp4(s)
|
||||
result = biggestInt(a shl 24 or b shl 16 or c shl 8 or d)
|
||||
result = BiggestInt(a shl 24 or b shl 16 or c shl 8 or d)
|
||||
|
||||
template gaiNim(a, p, h, list: expr): stmt =
|
||||
block:
|
||||
var gaiResult = getAddrInfo(a, $p, addr(h), list)
|
||||
var gaiResult = getaddrinfo(a, $p, addr(h), list)
|
||||
if gaiResult != 0'i32:
|
||||
when defined(windows):
|
||||
OSError(OSLastError())
|
||||
osError(osLastError())
|
||||
else:
|
||||
raise newException(EOS, $gai_strerror(gaiResult))
|
||||
|
||||
|
|
@ -436,17 +436,17 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") {.
|
|||
name.sin_port = sockets.htons(int16(port))
|
||||
name.sin_addr.s_addr = sockets.htonl(INADDR_ANY)
|
||||
if bindSocket(socket.fd, cast[ptr TSockAddr](addr(name)),
|
||||
sizeof(name).TSockLen) < 0'i32:
|
||||
OSError(OSLastError())
|
||||
sizeof(name).TSocklen) < 0'i32:
|
||||
osError(osLastError())
|
||||
else:
|
||||
var hints: TAddrInfo
|
||||
var aiList: ptr TAddrInfo = nil
|
||||
var hints: Taddrinfo
|
||||
var aiList: ptr Taddrinfo = nil
|
||||
hints.ai_family = toInt(AF_INET)
|
||||
hints.ai_socktype = toInt(SOCK_STREAM)
|
||||
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(OSLastError())
|
||||
if bindSocket(socket.fd, aiList.ai_addr, aiList.ai_addrlen.TSocklen) < 0'i32:
|
||||
osError(osLastError())
|
||||
|
||||
proc getSockName*(socket: TSocket): TPort =
|
||||
## returns the socket's associated port number.
|
||||
|
|
@ -457,40 +457,40 @@ proc getSockName*(socket: TSocket): TPort =
|
|||
name.sin_family = posix.AF_INET
|
||||
#name.sin_port = htons(cint16(port))
|
||||
#name.sin_addr.s_addr = htonl(INADDR_ANY)
|
||||
var namelen = sizeof(name).TSockLen
|
||||
var namelen = sizeof(name).TSocklen
|
||||
if getsockname(socket.fd, cast[ptr TSockAddr](addr(name)),
|
||||
addr(namelen)) == -1'i32:
|
||||
OSError(OSLastError())
|
||||
osError(osLastError())
|
||||
result = TPort(sockets.ntohs(name.sin_port))
|
||||
|
||||
template acceptAddrPlain(noClientRet, successRet: expr,
|
||||
sslImplementation: stmt): stmt {.immediate.} =
|
||||
assert(client != nil)
|
||||
var sockAddress: Tsockaddr_in
|
||||
var addrLen = sizeof(sockAddress).TSockLen
|
||||
var addrLen = sizeof(sockAddress).TSocklen
|
||||
var sock = accept(server.fd, cast[ptr TSockAddr](addr(sockAddress)),
|
||||
addr(addrLen))
|
||||
|
||||
if sock == OSInvalidSocket:
|
||||
let err = OSLastError()
|
||||
if sock == osInvalidSocket:
|
||||
let err = osLastError()
|
||||
when defined(windows):
|
||||
if err.int32 == WSAEINPROGRESS:
|
||||
client = InvalidSocket
|
||||
client = invalidSocket
|
||||
address = ""
|
||||
when noClientRet.int == -1:
|
||||
return
|
||||
else:
|
||||
return noClientRet
|
||||
else: OSError(err)
|
||||
else: osError(err)
|
||||
else:
|
||||
if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK:
|
||||
client = InvalidSocket
|
||||
client = invalidSocket
|
||||
address = ""
|
||||
when noClientRet.int == -1:
|
||||
return
|
||||
else:
|
||||
return noClientRet
|
||||
else: OSError(err)
|
||||
else: osError(err)
|
||||
else:
|
||||
client.fd = sock
|
||||
client.isBuffered = server.isBuffered
|
||||
|
|
@ -628,7 +628,7 @@ proc accept*(server: TSocket): TSocket {.deprecated, tags: [FReadIO].} =
|
|||
proc close*(socket: TSocket) =
|
||||
## closes a socket.
|
||||
when defined(windows):
|
||||
discard winlean.closeSocket(socket.fd)
|
||||
discard winlean.closesocket(socket.fd)
|
||||
else:
|
||||
discard posix.close(socket.fd)
|
||||
# TODO: These values should not be discarded. An EOS should be raised.
|
||||
|
|
@ -669,7 +669,7 @@ proc getServByPort*(port: TPort, proto: string): TServent {.tags: [FReadIO].} =
|
|||
result.port = TPort(s.s_port)
|
||||
result.proto = $s.s_proto
|
||||
|
||||
proc getHostByAddr*(ip: string): THostEnt {.tags: [FReadIO].} =
|
||||
proc getHostByAddr*(ip: string): Thostent {.tags: [FReadIO].} =
|
||||
## This function will lookup the hostname of an IP Address.
|
||||
var myaddr: TInAddr
|
||||
myaddr.s_addr = inet_addr(ip)
|
||||
|
|
@ -677,43 +677,43 @@ 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(OSLastError())
|
||||
if s == nil: osError(osLastError())
|
||||
else:
|
||||
var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).TSockLen,
|
||||
var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).TSocklen,
|
||||
cint(posix.AF_INET))
|
||||
if s == nil:
|
||||
raise newException(EOS, $hStrError(h_errno))
|
||||
raise newException(EOS, $hstrerror(h_errno))
|
||||
|
||||
result.name = $s.h_name
|
||||
result.aliases = cstringArrayToSeq(s.h_aliases)
|
||||
when defined(windows):
|
||||
result.addrType = TDomain(s.h_addrtype)
|
||||
result.addrtype = TDomain(s.h_addrtype)
|
||||
else:
|
||||
if s.h_addrtype == posix.AF_INET:
|
||||
result.addrType = AF_INET
|
||||
result.addrtype = AF_INET
|
||||
elif s.h_addrtype == posix.AF_INET6:
|
||||
result.addrType = AF_INET6
|
||||
result.addrtype = AF_INET6
|
||||
else:
|
||||
raise newException(EOS, "unknown h_addrtype")
|
||||
result.addrList = cstringArrayToSeq(s.h_addr_list)
|
||||
result.length = int(s.h_length)
|
||||
|
||||
proc getHostByName*(name: string): THostEnt {.tags: [FReadIO].} =
|
||||
proc getHostByName*(name: string): Thostent {.tags: [FReadIO].} =
|
||||
## This function will lookup the IP address of a hostname.
|
||||
when defined(Windows):
|
||||
var s = winlean.gethostbyname(name)
|
||||
else:
|
||||
var s = posix.gethostbyname(name)
|
||||
if s == nil: OSError(OSLastError())
|
||||
if s == nil: osError(osLastError())
|
||||
result.name = $s.h_name
|
||||
result.aliases = cstringArrayToSeq(s.h_aliases)
|
||||
when defined(windows):
|
||||
result.addrType = TDomain(s.h_addrtype)
|
||||
result.addrtype = TDomain(s.h_addrtype)
|
||||
else:
|
||||
if s.h_addrtype == posix.AF_INET:
|
||||
result.addrType = AF_INET
|
||||
result.addrtype = AF_INET
|
||||
elif s.h_addrtype == posix.AF_INET6:
|
||||
result.addrType = AF_INET6
|
||||
result.addrtype = AF_INET6
|
||||
else:
|
||||
raise newException(EOS, "unknown h_addrtype")
|
||||
result.addrList = cstringArrayToSeq(s.h_addr_list)
|
||||
|
|
@ -723,10 +723,10 @@ proc getSockOptInt*(socket: TSocket, level, optname: int): int {.
|
|||
tags: [FReadIO].} =
|
||||
## getsockopt for integer options.
|
||||
var res: cint
|
||||
var size = sizeof(res).TSockLen
|
||||
var size = sizeof(res).TSocklen
|
||||
if getsockopt(socket.fd, cint(level), cint(optname),
|
||||
addr(res), addr(size)) < 0'i32:
|
||||
OSError(OSLastError())
|
||||
osError(osLastError())
|
||||
result = int(res)
|
||||
|
||||
proc setSockOptInt*(socket: TSocket, level, optname, optval: int) {.
|
||||
|
|
@ -734,8 +734,8 @@ proc setSockOptInt*(socket: TSocket, level, optname, optval: int) {.
|
|||
## setsockopt for integer options.
|
||||
var value = cint(optval)
|
||||
if setsockopt(socket.fd, cint(level), cint(optname), addr(value),
|
||||
sizeof(value).TSockLen) < 0'i32:
|
||||
OSError(OSLastError())
|
||||
sizeof(value).TSocklen) < 0'i32:
|
||||
osError(osLastError())
|
||||
|
||||
proc toCInt(opt: TSOBool): cint =
|
||||
case opt
|
||||
|
|
@ -751,10 +751,10 @@ proc getSockOpt*(socket: TSocket, opt: TSOBool, level = SOL_SOCKET): bool {.
|
|||
tags: [FReadIO].} =
|
||||
## Retrieves option ``opt`` as a boolean value.
|
||||
var res: cint
|
||||
var size = sizeof(res).TSockLen
|
||||
var size = sizeof(res).TSocklen
|
||||
if getsockopt(socket.fd, cint(level), toCInt(opt),
|
||||
addr(res), addr(size)) < 0'i32:
|
||||
OSError(OSLastError())
|
||||
osError(osLastError())
|
||||
result = res != 0
|
||||
|
||||
proc setSockOpt*(socket: TSocket, opt: TSOBool, value: bool, level = SOL_SOCKET) {.
|
||||
|
|
@ -762,8 +762,8 @@ proc setSockOpt*(socket: TSocket, opt: TSOBool, value: bool, level = SOL_SOCKET)
|
|||
## Sets option ``opt`` to a boolean value specified by ``value``.
|
||||
var valuei = cint(if value: 1 else: 0)
|
||||
if setsockopt(socket.fd, cint(level), toCInt(opt), addr(valuei),
|
||||
sizeof(valuei).TSockLen) < 0'i32:
|
||||
OSError(OSLastError())
|
||||
sizeof(valuei).TSocklen) < 0'i32:
|
||||
osError(osLastError())
|
||||
|
||||
proc connect*(socket: TSocket, address: string, port = TPort(0),
|
||||
af: TDomain = AF_INET) {.tags: [FReadIO].} =
|
||||
|
|
@ -773,8 +773,8 @@ proc connect*(socket: TSocket, address: string, port = TPort(0),
|
|||
## not do it.
|
||||
##
|
||||
## If ``socket`` is an SSL socket a handshake will be automatically performed.
|
||||
var hints: TAddrInfo
|
||||
var aiList: ptr TAddrInfo = nil
|
||||
var hints: Taddrinfo
|
||||
var aiList: ptr Taddrinfo = nil
|
||||
hints.ai_family = toInt(af)
|
||||
hints.ai_socktype = toInt(SOCK_STREAM)
|
||||
hints.ai_protocol = toInt(IPPROTO_TCP)
|
||||
|
|
@ -784,14 +784,14 @@ proc connect*(socket: TSocket, address: string, port = TPort(0),
|
|||
var lastError: TOSErrorCode
|
||||
var it = aiList
|
||||
while it != nil:
|
||||
if connect(socket.fd, it.ai_addr, it.ai_addrlen.TSockLen) == 0'i32:
|
||||
if connect(socket.fd, it.ai_addr, it.ai_addrlen.TSocklen) == 0'i32:
|
||||
success = true
|
||||
break
|
||||
else: lastError = OSLastError()
|
||||
else: lastError = osLastError()
|
||||
it = it.ai_next
|
||||
|
||||
freeaddrinfo(aiList)
|
||||
if not success: OSError(lastError)
|
||||
if not success: osError(lastError)
|
||||
|
||||
when defined(ssl):
|
||||
if socket.isSSL:
|
||||
|
|
@ -836,8 +836,8 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
|
|||
##
|
||||
## **Note**: For SSL sockets, the ``handshake`` procedure must be called
|
||||
## whenever the socket successfully connects to a server.
|
||||
var hints: TAddrInfo
|
||||
var aiList: ptr TAddrInfo = nil
|
||||
var hints: Taddrinfo
|
||||
var aiList: ptr Taddrinfo = nil
|
||||
hints.ai_family = toInt(af)
|
||||
hints.ai_socktype = toInt(SOCK_STREAM)
|
||||
hints.ai_protocol = toInt(IPPROTO_TCP)
|
||||
|
|
@ -847,12 +847,12 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
|
|||
var lastError: TOSErrorCode
|
||||
var it = aiList
|
||||
while it != nil:
|
||||
var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.TSockLen)
|
||||
var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.TSocklen)
|
||||
if ret == 0'i32:
|
||||
success = true
|
||||
break
|
||||
else:
|
||||
lastError = OSLastError()
|
||||
lastError = osLastError()
|
||||
when defined(windows):
|
||||
# Windows EINTR doesn't behave same as POSIX.
|
||||
if lastError.int32 == WSAEWOULDBLOCK:
|
||||
|
|
@ -866,7 +866,7 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0),
|
|||
it = it.ai_next
|
||||
|
||||
freeaddrinfo(aiList)
|
||||
if not success: OSError(lastError)
|
||||
if not success: osError(lastError)
|
||||
when defined(ssl):
|
||||
if socket.isSSL:
|
||||
socket.sslNoHandshake = true
|
||||
|
|
@ -912,7 +912,7 @@ when defined(ssl):
|
|||
else:
|
||||
SSLError("Socket is not an SSL socket.")
|
||||
|
||||
proc timeValFromMilliseconds(timeout = 500): TTimeVal =
|
||||
proc timeValFromMilliseconds(timeout = 500): Ttimeval =
|
||||
if timeout != -1:
|
||||
var seconds = timeout div 1000
|
||||
result.tv_sec = seconds.int32
|
||||
|
|
@ -928,7 +928,7 @@ proc pruneSocketSet(s: var seq[TSocket], fd: var TFdSet) =
|
|||
var i = 0
|
||||
var L = s.len
|
||||
while i < L:
|
||||
if FD_ISSET(s[i].fd, fd) != 0'i32:
|
||||
if FD_ISSET(s[i].fd, fd) == 0'i32:
|
||||
s[i] = s[L-1]
|
||||
dec(L)
|
||||
else:
|
||||
|
|
@ -970,7 +970,7 @@ proc select*(readfds, writefds, exceptfds: var seq[TSocket],
|
|||
if buffersFilled > 0:
|
||||
return buffersFilled
|
||||
|
||||
var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout)
|
||||
var tv {.noInit.}: Ttimeval = timeValFromMilliseconds(timeout)
|
||||
|
||||
var rd, wr, ex: TFdSet
|
||||
var m = 0
|
||||
|
|
@ -993,7 +993,7 @@ proc select*(readfds, writefds: var seq[TSocket],
|
|||
let buffersFilled = checkBuffer(readfds)
|
||||
if buffersFilled > 0:
|
||||
return buffersFilled
|
||||
var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout)
|
||||
var tv {.noInit.}: Ttimeval = timeValFromMilliseconds(timeout)
|
||||
|
||||
var rd, wr: TFdSet
|
||||
var m = 0
|
||||
|
|
@ -1017,7 +1017,7 @@ proc selectWrite*(writefds: var seq[TSocket],
|
|||
##
|
||||
## ``timeout`` is specified in miliseconds and ``-1`` can be specified for
|
||||
## an unlimited time.
|
||||
var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout)
|
||||
var tv {.noInit.}: Ttimeval = timeValFromMilliseconds(timeout)
|
||||
|
||||
var wr: TFdSet
|
||||
var m = 0
|
||||
|
|
@ -1035,7 +1035,7 @@ proc select*(readfds: var seq[TSocket], timeout = 500): int =
|
|||
let buffersFilled = checkBuffer(readfds)
|
||||
if buffersFilled > 0:
|
||||
return buffersFilled
|
||||
var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout)
|
||||
var tv {.noInit.}: Ttimeval = timeValFromMilliseconds(timeout)
|
||||
|
||||
var rd: TFdSet
|
||||
var m = 0
|
||||
|
|
@ -1058,7 +1058,7 @@ proc readIntoBuf(socket: TSocket, flags: int32): int =
|
|||
else:
|
||||
result = recv(socket.fd, addr(socket.buffer), cint(socket.buffer.high), flags)
|
||||
if result <= 0:
|
||||
socket.buflen = 0
|
||||
socket.bufLen = 0
|
||||
socket.currPos = 0
|
||||
return result
|
||||
socket.bufLen = result
|
||||
|
|
@ -1142,7 +1142,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(OSLastError())
|
||||
if selRet < 0: osError(osLastError())
|
||||
if selRet != 1:
|
||||
raise newException(ETimeout, "Call to '" & funcName & "' timed out.")
|
||||
waited += (epochTime() - startTime)
|
||||
|
|
@ -1180,7 +1180,7 @@ proc recv*(socket: TSocket, data: var string, size: int, timeout = -1): int =
|
|||
result = recv(socket, cstring(data), size, timeout)
|
||||
if result < 0:
|
||||
data.setLen(0)
|
||||
socket.SocketError(result)
|
||||
socket.socketError(result)
|
||||
data.setLen(result)
|
||||
|
||||
proc recvAsync*(socket: TSocket, data: var string, size: int): int =
|
||||
|
|
@ -1194,7 +1194,7 @@ proc recvAsync*(socket: TSocket, data: var string, size: int): int =
|
|||
result = recv(socket, cstring(data), size)
|
||||
if result < 0:
|
||||
data.setLen(0)
|
||||
socket.SocketError(async = true)
|
||||
socket.socketError(async = true)
|
||||
result = -1
|
||||
data.setLen(result)
|
||||
|
||||
|
|
@ -1258,10 +1258,10 @@ proc recvLine*(socket: TSocket, line: var TaintedString, timeout = -1): bool {.
|
|||
if n > 0 and c == '\L':
|
||||
discard recv(socket, addr(c), 1)
|
||||
elif n <= 0: return false
|
||||
addNlIfEmpty()
|
||||
addNLIfEmpty()
|
||||
return true
|
||||
elif c == '\L':
|
||||
addNlIfEmpty()
|
||||
addNLIfEmpty()
|
||||
return true
|
||||
add(line.string, c)
|
||||
|
||||
|
|
@ -1291,18 +1291,18 @@ 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(OSLastError())
|
||||
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(OSLastError())
|
||||
addNlIfEmpty()
|
||||
elif n <= 0: osError(osLastError())
|
||||
addNLIfEmpty()
|
||||
return
|
||||
elif c == '\L':
|
||||
addNlIfEmpty()
|
||||
addNLIfEmpty()
|
||||
return
|
||||
add(line.string, c)
|
||||
|
||||
|
|
@ -1352,7 +1352,7 @@ proc readLineAsync*(socket: TSocket,
|
|||
setLen(line.string, 0)
|
||||
|
||||
template errorOrNone =
|
||||
socket.SocketError(async = true)
|
||||
socket.socketError(async = true)
|
||||
return ReadNone
|
||||
|
||||
while true:
|
||||
|
|
@ -1385,7 +1385,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(OSLastError())
|
||||
if bytesRead == -1: osError(osLastError())
|
||||
setLen(result.string, pos + bytesRead)
|
||||
if bytesRead != bufSize-1: break
|
||||
# increase capacity:
|
||||
|
|
@ -1454,22 +1454,22 @@ 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()
|
||||
let err = osLastError()
|
||||
when defined(windows):
|
||||
if err.int32 == WSAEWOULDBLOCK:
|
||||
return False
|
||||
else: OSError(err)
|
||||
return false
|
||||
else: osError(err)
|
||||
else:
|
||||
if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK:
|
||||
return False
|
||||
else: OSError(err)
|
||||
return false
|
||||
else: osError(err)
|
||||
|
||||
setLen(s.string, pos + bytesRead)
|
||||
if bytesRead != bufSize-1: break
|
||||
# increase capacity:
|
||||
setLen(s.string, s.string.len + bufSize)
|
||||
inc(pos, bytesRead)
|
||||
result = True
|
||||
result = true
|
||||
|
||||
proc recvFrom*(socket: TSocket, data: var string, length: int,
|
||||
address: var string, port: var TPort, flags = 0'i32): int {.
|
||||
|
|
@ -1488,8 +1488,8 @@ proc recvFrom*(socket: TSocket, data: var string, length: int,
|
|||
# TODO: Buffered sockets
|
||||
data.setLen(length)
|
||||
var sockAddress: Tsockaddr_in
|
||||
var addrLen = sizeof(sockAddress).TSockLen
|
||||
result = recvFrom(socket.fd, cstring(data), length.cint, flags.cint,
|
||||
var addrLen = sizeof(sockAddress).TSocklen
|
||||
result = recvfrom(socket.fd, cstring(data), length.cint, flags.cint,
|
||||
cast[ptr TSockAddr](addr(sockAddress)), addr(addrLen))
|
||||
|
||||
if result != -1:
|
||||
|
|
@ -1497,7 +1497,7 @@ proc recvFrom*(socket: TSocket, data: var string, length: int,
|
|||
address = $inet_ntoa(sockAddress.sin_addr)
|
||||
port = ntohs(sockAddress.sin_port).TPort
|
||||
|
||||
proc recvFromAsync*(socket: TSocket, data: var String, length: int,
|
||||
proc recvFromAsync*(socket: TSocket, data: var string, length: int,
|
||||
address: var string, port: var TPort,
|
||||
flags = 0'i32): bool {.tags: [FReadIO].} =
|
||||
## Variant of ``recvFrom`` for non-blocking sockets. Unlike ``recvFrom``,
|
||||
|
|
@ -1507,15 +1507,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()
|
||||
let err = osLastError()
|
||||
when defined(windows):
|
||||
if err.int32 == WSAEWOULDBLOCK:
|
||||
return False
|
||||
else: OSError(err)
|
||||
return false
|
||||
else: osError(err)
|
||||
else:
|
||||
if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK:
|
||||
return False
|
||||
else: OSError(err)
|
||||
return false
|
||||
else: osError(err)
|
||||
|
||||
proc skip*(socket: TSocket) {.tags: [FReadIO], deprecated.} =
|
||||
## skips all the data that is pending for the socket
|
||||
|
|
@ -1523,7 +1523,7 @@ proc skip*(socket: TSocket) {.tags: [FReadIO], deprecated.} =
|
|||
## **Deprecated since version 0.9.2**: This function is not safe for use.
|
||||
const bufSize = 1000
|
||||
var buf = alloc(bufSize)
|
||||
while recv(socket, buf, bufSize) == bufSize: nil
|
||||
while recv(socket, buf, bufSize) == bufSize: discard
|
||||
dealloc(buf)
|
||||
|
||||
proc skip*(socket: TSocket, size: int, timeout = -1) =
|
||||
|
|
@ -1565,7 +1565,7 @@ proc send*(socket: TSocket, data: string) {.tags: [FWriteIO].} =
|
|||
if socket.isSSL:
|
||||
SSLError()
|
||||
|
||||
OSError(OSLastError())
|
||||
osError(osLastError())
|
||||
|
||||
if sent != data.len:
|
||||
raise newException(EOS, "Could not send all data.")
|
||||
|
|
@ -1598,15 +1598,15 @@ proc sendAsync*(socket: TSocket, data: string): int {.tags: [FWriteIO].} =
|
|||
else:
|
||||
return
|
||||
if result == -1:
|
||||
let err = OSLastError()
|
||||
let err = osLastError()
|
||||
when defined(windows):
|
||||
if err.int32 == WSAEINPROGRESS:
|
||||
return 0
|
||||
else: OSError(err)
|
||||
else: osError(err)
|
||||
else:
|
||||
if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK:
|
||||
return 0
|
||||
else: OSError(err)
|
||||
else: osError(err)
|
||||
|
||||
|
||||
proc trySend*(socket: TSocket, data: string): bool {.tags: [FWriteIO].} =
|
||||
|
|
@ -1622,8 +1622,8 @@ proc sendTo*(socket: TSocket, address: string, port: TPort, data: pointer,
|
|||
## this function will try each IP of that hostname.
|
||||
##
|
||||
## **Note:** This proc is not available for SSL sockets.
|
||||
var hints: TAddrInfo
|
||||
var aiList: ptr TAddrInfo = nil
|
||||
var hints: Taddrinfo
|
||||
var aiList: ptr Taddrinfo = nil
|
||||
hints.ai_family = toInt(af)
|
||||
hints.ai_socktype = toInt(SOCK_STREAM)
|
||||
hints.ai_protocol = toInt(IPPROTO_TCP)
|
||||
|
|
@ -1633,8 +1633,8 @@ proc sendTo*(socket: TSocket, address: string, port: TPort, data: pointer,
|
|||
var success = false
|
||||
var it = aiList
|
||||
while it != nil:
|
||||
result = sendTo(socket.fd, data, size.cint, flags.cint, it.ai_addr,
|
||||
it.ai_addrlen.TSockLen)
|
||||
result = sendto(socket.fd, data, size.cint, flags.cint, it.ai_addr,
|
||||
it.ai_addrlen.TSocklen)
|
||||
if result != -1'i32:
|
||||
success = true
|
||||
break
|
||||
|
|
@ -1661,16 +1661,16 @@ when defined(Windows):
|
|||
proc setBlocking(s: TSocket, blocking: bool) =
|
||||
when defined(Windows):
|
||||
var mode = clong(ord(not blocking)) # 1 for non-blocking, 0 for blocking
|
||||
if ioctlsocket(TSocketHandle(s.fd), FIONBIO, addr(mode)) == -1:
|
||||
OSError(OSLastError())
|
||||
if ioctlsocket(s.fd, FIONBIO, addr(mode)) == -1:
|
||||
osError(osLastError())
|
||||
else: # BSD sockets
|
||||
var x: int = fcntl(s.fd, F_GETFL, 0)
|
||||
if x == -1:
|
||||
OSError(OSLastError())
|
||||
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(OSLastError())
|
||||
osError(osLastError())
|
||||
s.nonblocking = not blocking
|
||||
|
||||
discard """ proc setReuseAddr*(s: TSocket) =
|
||||
|
|
@ -1709,7 +1709,7 @@ proc isBlocking*(socket: TSocket): bool = not socket.nonblocking
|
|||
## Determines whether ``socket`` is blocking.
|
||||
|
||||
when defined(Windows):
|
||||
var wsa: TWSADATA
|
||||
if WSAStartup(0x0101'i16, addr wsa) != 0: OSError(OSLastError())
|
||||
var wsa: TWSAData
|
||||
if wsaStartup(0x0101'i16, addr wsa) != 0: osError(osLastError())
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ proc fsClose(s: PStream) =
|
|||
close(PFileStream(s).f)
|
||||
PFileStream(s).f = nil
|
||||
proc fsFlush(s: PStream) = flushFile(PFileStream(s).f)
|
||||
proc fsAtEnd(s: PStream): bool = return EndOfFile(PFileStream(s).f)
|
||||
proc fsAtEnd(s: PStream): bool = return endOfFile(PFileStream(s).f)
|
||||
proc fsSetPosition(s: PStream, pos: int) = setFilePos(PFileStream(s).f, pos)
|
||||
proc fsGetPosition(s: PStream): int = return int(getFilePos(PFileStream(s).f))
|
||||
|
||||
|
|
@ -277,11 +277,11 @@ proc newFileStream*(filename: string, mode: TFileMode): PFileStream =
|
|||
## If the file cannot be opened, nil is returned. See the `system
|
||||
## <system.html>`_ module for a list of available TFileMode enums.
|
||||
var f: TFile
|
||||
if Open(f, filename, mode): result = newFileStream(f)
|
||||
if open(f, filename, mode): result = newFileStream(f)
|
||||
|
||||
|
||||
when true:
|
||||
nil
|
||||
discard
|
||||
else:
|
||||
type
|
||||
TFileHandle* = cint ## Operating system file handle
|
||||
|
|
|
|||
|
|
@ -88,10 +88,10 @@ proc mustRehash(length, counter: int): bool =
|
|||
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
||||
result = ((5 * h) + 1) and maxHash
|
||||
|
||||
proc RawGet(t: PStringTable, key: string): int =
|
||||
proc rawGet(t: PStringTable, key: string): int =
|
||||
var h: THash = myhash(t, key) and high(t.data) # start with real hash value
|
||||
while not isNil(t.data[h].key):
|
||||
if mycmp(t, t.data[h].key, key):
|
||||
if myCmp(t, t.data[h].key, key):
|
||||
return h
|
||||
h = nextTry(h, high(t.data))
|
||||
result = - 1
|
||||
|
|
@ -100,7 +100,7 @@ proc `[]`*(t: PStringTable, key: string): string {.rtl, extern: "nstGet".} =
|
|||
## retrieves the value at ``t[key]``. If `key` is not in `t`, "" is returned
|
||||
## and no exception is raised. One can check with ``hasKey`` whether the key
|
||||
## exists.
|
||||
var index = RawGet(t, key)
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0: result = t.data[index].val
|
||||
else: result = ""
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ proc mget*(t: PStringTable, key: string): var string {.
|
|||
rtl, extern: "nstTake".} =
|
||||
## retrieves the location at ``t[key]``. If `key` is not in `t`, the
|
||||
## ``EInvalidKey`` exception is raised.
|
||||
var index = RawGet(t, key)
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0: result = t.data[index].val
|
||||
else: raise newException(EInvalidKey, "key does not exist: " & key)
|
||||
|
||||
|
|
@ -116,31 +116,31 @@ proc hasKey*(t: PStringTable, key: string): bool {.rtl, extern: "nst$1".} =
|
|||
## returns true iff `key` is in the table `t`.
|
||||
result = rawGet(t, key) >= 0
|
||||
|
||||
proc RawInsert(t: PStringTable, data: var TKeyValuePairSeq, key, val: string) =
|
||||
proc rawInsert(t: PStringTable, data: var TKeyValuePairSeq, key, val: string) =
|
||||
var h: THash = myhash(t, key) and high(data)
|
||||
while not isNil(data[h].key):
|
||||
h = nextTry(h, high(data))
|
||||
data[h].key = key
|
||||
data[h].val = val
|
||||
|
||||
proc Enlarge(t: PStringTable) =
|
||||
proc enlarge(t: PStringTable) =
|
||||
var n: TKeyValuePairSeq
|
||||
newSeq(n, len(t.data) * growthFactor)
|
||||
for i in countup(0, high(t.data)):
|
||||
if not isNil(t.data[i].key): RawInsert(t, n, t.data[i].key, t.data[i].val)
|
||||
if not isNil(t.data[i].key): rawInsert(t, n, t.data[i].key, t.data[i].val)
|
||||
swap(t.data, n)
|
||||
|
||||
proc `[]=`*(t: PStringTable, key, val: string) {.rtl, extern: "nstPut".} =
|
||||
## puts a (key, value)-pair into `t`.
|
||||
var index = RawGet(t, key)
|
||||
var index = rawGet(t, key)
|
||||
if index >= 0:
|
||||
t.data[index].val = val
|
||||
else:
|
||||
if mustRehash(len(t.data), t.counter): Enlarge(t)
|
||||
RawInsert(t, t.data, key, val)
|
||||
if mustRehash(len(t.data), t.counter): enlarge(t)
|
||||
rawInsert(t, t.data, key, val)
|
||||
inc(t.counter)
|
||||
|
||||
proc RaiseFormatException(s: string) =
|
||||
proc raiseFormatException(s: string) =
|
||||
var e: ref EInvalidValue
|
||||
new(e)
|
||||
e.msg = "format string: key not found: " & s
|
||||
|
|
@ -184,7 +184,7 @@ proc newStringTable*(keyValuePairs: varargs[tuple[key, val: string]],
|
|||
## var mytab = newStringTable({"key1": "val1", "key2": "val2"},
|
||||
## modeCaseInsensitive)
|
||||
result = newStringTable(mode)
|
||||
for key, val in items(keyvaluePairs): result[key] = val
|
||||
for key, val in items(keyValuePairs): result[key] = val
|
||||
|
||||
proc `%`*(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string {.
|
||||
rtl, extern: "nstFormat".} =
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -27,15 +27,15 @@ when defined(windows):
|
|||
var hTemp = GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
if DuplicateHandle(GetCurrentProcess(), hTemp, GetCurrentProcess(),
|
||||
addr(conHandle), 0, 1, DUPLICATE_SAME_ACCESS) == 0:
|
||||
OSError(OSLastError())
|
||||
osError(osLastError())
|
||||
|
||||
proc getCursorPos(): tuple [x,y: int] =
|
||||
var c: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
if GetConsoleScreenBufferInfo(conHandle, addr(c)) == 0: OSError(OSLastError())
|
||||
var c: TCONSOLESCREENBUFFERINFO
|
||||
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
|
||||
var c: TCONSOLESCREENBUFFERINFO
|
||||
# workaround Windows bugs: try several times
|
||||
if GetConsoleScreenBufferInfo(conHandle, addr(c)) != 0:
|
||||
return c.wAttributes
|
||||
|
|
@ -48,10 +48,10 @@ 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
|
||||
var c: TCOORD
|
||||
c.x = int16(x)
|
||||
c.y = int16(y)
|
||||
if SetConsoleCursorPosition(conHandle, c) == 0: OSError(OSLastError())
|
||||
if SetConsoleCursorPosition(conHandle, c) == 0: osError(osLastError())
|
||||
else:
|
||||
stdout.write("\e[" & $y & ';' & $x & 'f')
|
||||
|
||||
|
|
@ -59,12 +59,12 @@ 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 scrbuf: TCONSOLESCREENBUFFERINFO
|
||||
var hStdout = conHandle
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError(OSLastError())
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: osError(osLastError())
|
||||
var origin = scrbuf.dwCursorPosition
|
||||
origin.x = int16(x)
|
||||
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError(OSLastError())
|
||||
if SetConsoleCursorPosition(conHandle, origin) == 0: osError(osLastError())
|
||||
else:
|
||||
stdout.write("\e[" & $x & 'G')
|
||||
|
||||
|
|
@ -73,16 +73,16 @@ when defined(windows):
|
|||
## 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 scrbuf: TCONSOLESCREENBUFFERINFO
|
||||
var hStdout = conHandle
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError(OSLastError())
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: osError(osLastError())
|
||||
var origin = scrbuf.dwCursorPosition
|
||||
origin.y = int16(y)
|
||||
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError(OSLastError())
|
||||
if SetConsoleCursorPosition(conHandle, origin) == 0: osError(osLastError())
|
||||
else:
|
||||
nil
|
||||
discard
|
||||
|
||||
proc CursorUp*(count=1) =
|
||||
proc cursorUp*(count=1) =
|
||||
## Moves the cursor up by `count` rows.
|
||||
when defined(windows):
|
||||
var p = getCursorPos()
|
||||
|
|
@ -91,7 +91,7 @@ proc CursorUp*(count=1) =
|
|||
else:
|
||||
stdout.write("\e[" & $count & 'A')
|
||||
|
||||
proc CursorDown*(count=1) =
|
||||
proc cursorDown*(count=1) =
|
||||
## Moves the cursor down by `count` rows.
|
||||
when defined(windows):
|
||||
var p = getCursorPos()
|
||||
|
|
@ -100,7 +100,7 @@ proc CursorDown*(count=1) =
|
|||
else:
|
||||
stdout.write("\e[" & $count & 'B')
|
||||
|
||||
proc CursorForward*(count=1) =
|
||||
proc cursorForward*(count=1) =
|
||||
## Moves the cursor forward by `count` columns.
|
||||
when defined(windows):
|
||||
var p = getCursorPos()
|
||||
|
|
@ -109,7 +109,7 @@ proc CursorForward*(count=1) =
|
|||
else:
|
||||
stdout.write("\e[" & $count & 'C')
|
||||
|
||||
proc CursorBackward*(count=1) =
|
||||
proc cursorBackward*(count=1) =
|
||||
## Moves the cursor backward by `count` columns.
|
||||
when defined(windows):
|
||||
var p = getCursorPos()
|
||||
|
|
@ -119,78 +119,78 @@ proc CursorBackward*(count=1) =
|
|||
stdout.write("\e[" & $count & 'D')
|
||||
|
||||
when true:
|
||||
nil
|
||||
discard
|
||||
else:
|
||||
proc EraseLineEnd* =
|
||||
proc eraseLineEnd* =
|
||||
## Erases from the current cursor position to the end of the current line.
|
||||
when defined(windows):
|
||||
nil
|
||||
discard
|
||||
else:
|
||||
stdout.write("\e[K")
|
||||
|
||||
proc EraseLineStart* =
|
||||
proc eraseLineStart* =
|
||||
## Erases from the current cursor position to the start of the current line.
|
||||
when defined(windows):
|
||||
nil
|
||||
discard
|
||||
else:
|
||||
stdout.write("\e[1K")
|
||||
|
||||
proc EraseDown* =
|
||||
proc eraseDown* =
|
||||
## Erases the screen from the current line down to the bottom of the screen.
|
||||
when defined(windows):
|
||||
nil
|
||||
discard
|
||||
else:
|
||||
stdout.write("\e[J")
|
||||
|
||||
proc EraseUp* =
|
||||
proc eraseUp* =
|
||||
## Erases the screen from the current line up to the top of the screen.
|
||||
when defined(windows):
|
||||
nil
|
||||
discard
|
||||
else:
|
||||
stdout.write("\e[1J")
|
||||
|
||||
proc EraseLine* =
|
||||
proc eraseLine* =
|
||||
## Erases the entire current line.
|
||||
when defined(windows):
|
||||
var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO
|
||||
var scrbuf: TCONSOLESCREENBUFFERINFO
|
||||
var numwrote: DWORD
|
||||
var hStdout = conHandle
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError(OSLastError())
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: osError(osLastError())
|
||||
var origin = scrbuf.dwCursorPosition
|
||||
origin.x = 0'i16
|
||||
if SetConsoleCursorPosition(conHandle, origin) == 0: OSError(OSLastError())
|
||||
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())
|
||||
osError(osLastError())
|
||||
if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, ht * wt,
|
||||
scrbuf.dwCursorPosition, addr(numwrote)) == 0:
|
||||
OSError(OSLastError())
|
||||
osError(osLastError())
|
||||
else:
|
||||
stdout.write("\e[2K")
|
||||
setCursorXPos(0)
|
||||
|
||||
proc EraseScreen* =
|
||||
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 scrbuf: TCONSOLESCREENBUFFERINFO
|
||||
var numwrote: DWORD
|
||||
var origin: TCoord # is inititalized to 0, 0
|
||||
var origin: TCOORD # is inititalized to 0, 0
|
||||
var hStdout = conHandle
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError(OSLastError())
|
||||
if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: osError(osLastError())
|
||||
if FillConsoleOutputCharacter(hStdout, ' ', scrbuf.dwSize.X*scrbuf.dwSize.Y,
|
||||
origin, addr(numwrote)) == 0:
|
||||
OSError(OSLastError())
|
||||
osError(osLastError())
|
||||
if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes,
|
||||
scrbuf.dwSize.X * scrbuf.dwSize.Y,
|
||||
origin, addr(numwrote)) == 0:
|
||||
OSError(OSLastError())
|
||||
osError(osLastError())
|
||||
setCursorXPos(0)
|
||||
else:
|
||||
stdout.write("\e[2J")
|
||||
|
||||
proc ResetAttributes* {.noconv.} =
|
||||
proc resetAttributes* {.noconv.} =
|
||||
## resets all attributes; it is advisable to register this as a quit proc
|
||||
## with ``system.addQuitProc(resetAttributes)``.
|
||||
when defined(windows):
|
||||
|
|
@ -227,7 +227,7 @@ proc setStyle*(style: set[TStyle]) =
|
|||
for s in items(style):
|
||||
stdout.write("\e[" & $ord(s) & 'm')
|
||||
|
||||
proc WriteStyled*(txt: string, style: set[TStyle] = {styleBright}) =
|
||||
proc writeStyled*(txt: string, style: set[TStyle] = {styleBright}) =
|
||||
## writes the text `txt` in a given `style`.
|
||||
when defined(windows):
|
||||
var old = getAttributes()
|
||||
|
|
@ -320,8 +320,8 @@ proc isatty*(f: TFile): bool =
|
|||
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(color: TForegroundColor) = setForegroundColor color
|
||||
proc styledEchoProcessArg(color: TBackgroundColor) = setBackgroundColor color
|
||||
|
||||
macro styledEcho*(m: varargs[expr]): stmt =
|
||||
## to be documented.
|
||||
|
|
@ -345,4 +345,4 @@ when isMainModule:
|
|||
writeln(stdout, "ordinary text")
|
||||
|
||||
styledEcho("styled text ", {styleBright, styleBlink, styleUnderscore})
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ proc getGMTime*(t: TTime): TTimeInfo {.tags: [FTime], raises: [].}
|
|||
## converts the calendar time `t` to broken-down time representation,
|
||||
## expressed in Coordinated Universal Time (UTC).
|
||||
|
||||
proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime {.tags: [].}
|
||||
proc timeInfoToTime*(timeInfo: TTimeInfo): TTime {.tags: [].}
|
||||
## converts a broken-down time structure to
|
||||
## calendar time representation. The function ignores the specified
|
||||
## contents of the structure members `weekday` and `yearday` and recomputes
|
||||
|
|
@ -256,7 +256,7 @@ proc `+`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
|
|||
##
|
||||
## **Note:** This has been only briefly tested and it may not be
|
||||
## very accurate.
|
||||
let t = toSeconds(TimeInfoToTime(a))
|
||||
let t = toSeconds(timeInfoToTime(a))
|
||||
let secs = toSeconds(a, interval)
|
||||
if a.tzname == "UTC":
|
||||
result = getGMTime(fromSeconds(t + secs))
|
||||
|
|
@ -268,7 +268,7 @@ proc `-`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo =
|
|||
##
|
||||
## **Note:** This has been only briefly tested, it is inaccurate especially
|
||||
## when you subtract so much that you reach the Julian calendar.
|
||||
let t = toSeconds(TimeInfoToTime(a))
|
||||
let t = toSeconds(timeInfoToTime(a))
|
||||
let secs = toSeconds(a, interval)
|
||||
if a.tzname == "UTC":
|
||||
result = getGMTime(fromSeconds(t - secs))
|
||||
|
|
@ -297,7 +297,7 @@ when not defined(JS):
|
|||
when not defined(JS):
|
||||
# C wrapper:
|
||||
type
|
||||
structTM {.importc: "struct tm", final.} = object
|
||||
StructTM {.importc: "struct tm", final.} = object
|
||||
second {.importc: "tm_sec".},
|
||||
minute {.importc: "tm_min".},
|
||||
hour {.importc: "tm_hour".},
|
||||
|
|
@ -308,7 +308,7 @@ when not defined(JS):
|
|||
yearday {.importc: "tm_yday".},
|
||||
isdst {.importc: "tm_isdst".}: cint
|
||||
|
||||
PTimeInfo = ptr structTM
|
||||
PTimeInfo = ptr StructTM
|
||||
PTime = ptr TTime
|
||||
|
||||
TClock {.importc: "clock_t".} = distinct int
|
||||
|
|
@ -319,11 +319,11 @@ when not defined(JS):
|
|||
importc: "gmtime", header: "<time.h>", tags: [].}
|
||||
proc timec(timer: PTime): TTime {.
|
||||
importc: "time", header: "<time.h>", tags: [].}
|
||||
proc mktime(t: structTM): TTime {.
|
||||
proc mktime(t: StructTM): TTime {.
|
||||
importc: "mktime", header: "<time.h>", tags: [].}
|
||||
proc asctime(tblock: structTM): CString {.
|
||||
proc asctime(tblock: StructTM): cstring {.
|
||||
importc: "asctime", header: "<time.h>", tags: [].}
|
||||
proc ctime(time: PTime): CString {.
|
||||
proc ctime(time: PTime): cstring {.
|
||||
importc: "ctime", header: "<time.h>", tags: [].}
|
||||
# strftime(s: CString, maxsize: int, fmt: CString, t: tm): int {.
|
||||
# importc: "strftime", header: "<time.h>".}
|
||||
|
|
@ -335,7 +335,7 @@ when not defined(JS):
|
|||
clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int
|
||||
|
||||
# our own procs on top of that:
|
||||
proc tmToTimeInfo(tm: structTM, local: bool): TTimeInfo =
|
||||
proc tmToTimeInfo(tm: StructTM, local: bool): TTimeInfo =
|
||||
const
|
||||
weekDays: array [0..6, TWeekDay] = [
|
||||
dSun, dMon, dTue, dWed, dThu, dFri, dSat]
|
||||
|
|
@ -345,11 +345,11 @@ when not defined(JS):
|
|||
monthday: int(tm.monthday),
|
||||
month: TMonth(tm.month),
|
||||
year: tm.year + 1900'i32,
|
||||
weekday: weekDays[int(tm.weekDay)],
|
||||
weekday: weekDays[int(tm.weekday)],
|
||||
yearday: int(tm.yearday),
|
||||
isDST: tm.isDST > 0,
|
||||
isDST: tm.isdst > 0,
|
||||
tzname: if local:
|
||||
if tm.isDST > 0:
|
||||
if tm.isdst > 0:
|
||||
getTzname().DST
|
||||
else:
|
||||
getTzname().nonDST
|
||||
|
|
@ -358,7 +358,7 @@ when not defined(JS):
|
|||
timezone: if local: getTimezone() else: 0
|
||||
)
|
||||
|
||||
proc timeInfoToTM(t: TTimeInfo): structTM =
|
||||
proc timeInfoToTM(t: TTimeInfo): StructTM =
|
||||
const
|
||||
weekDays: array [TWeekDay, int8] = [1'i8,2'i8,3'i8,4'i8,5'i8,6'i8,0'i8]
|
||||
result.second = t.second
|
||||
|
|
@ -367,7 +367,7 @@ when not defined(JS):
|
|||
result.monthday = t.monthday
|
||||
result.month = ord(t.month)
|
||||
result.year = t.year - 1900
|
||||
result.weekday = weekDays[t.weekDay]
|
||||
result.weekday = weekDays[t.weekday]
|
||||
result.yearday = t.yearday
|
||||
result.isdst = if t.isDST: 1 else: 0
|
||||
|
||||
|
|
@ -401,7 +401,7 @@ when not defined(JS):
|
|||
# copying is needed anyway to provide reentrancity; thus
|
||||
# the conversion is not expensive
|
||||
|
||||
proc TimeInfoToTime(timeInfo: TTimeInfo): TTime =
|
||||
proc timeInfoToTime(timeInfo: TTimeInfo): TTime =
|
||||
var cTimeInfo = timeInfo # for C++ we have to make a copy,
|
||||
# because the header of mktime is broken in my version of libc
|
||||
return mktime(timeInfoToTM(cTimeInfo))
|
||||
|
|
@ -453,7 +453,7 @@ when not defined(JS):
|
|||
result = toFloat(a.tv_sec) + toFloat(a.tv_usec)*0.00_0001
|
||||
elif defined(windows):
|
||||
var f: winlean.TFiletime
|
||||
GetSystemTimeAsFileTime(f)
|
||||
getSystemTimeAsFileTime(f)
|
||||
var i64 = rdFileTime(f) - epochDiff
|
||||
var secs = i64 div rateDiff
|
||||
var subsecs = i64 mod rateDiff
|
||||
|
|
@ -498,7 +498,7 @@ elif defined(JS):
|
|||
result.weekday = weekDays[t.getUTCDay()]
|
||||
result.yearday = 0
|
||||
|
||||
proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime =
|
||||
proc timeInfoToTime*(timeInfo: TTimeInfo): TTime =
|
||||
result = internGetTime()
|
||||
result.setSeconds(timeInfo.second)
|
||||
result.setMinutes(timeInfo.minute)
|
||||
|
|
@ -532,7 +532,7 @@ proc getDateStr*(): string {.rtl, extern: "nt$1", tags: [FTime].} =
|
|||
## gets the current date as a string of the format ``YYYY-MM-DD``.
|
||||
var ti = getLocalTime(getTime())
|
||||
result = $ti.year & '-' & intToStr(ord(ti.month)+1, 2) &
|
||||
'-' & intToStr(ti.monthDay, 2)
|
||||
'-' & intToStr(ti.monthday, 2)
|
||||
|
||||
proc getClockStr*(): string {.rtl, extern: "nt$1", tags: [FTime].} =
|
||||
## gets the current clock time as a string of the format ``HH:MM:SS``.
|
||||
|
|
@ -593,7 +593,7 @@ proc format*(info: TTimeInfo, f: string): string =
|
|||
result = ""
|
||||
var i = 0
|
||||
var currentF = ""
|
||||
while True:
|
||||
while true:
|
||||
case f[i]
|
||||
of ' ', '-', '/', ':', '\'', '\0', '(', ')', '[', ']', ',':
|
||||
case currentF
|
||||
|
|
@ -698,7 +698,7 @@ proc format*(info: TTimeInfo, f: string): string =
|
|||
of "ZZZ":
|
||||
result.add(info.tzname)
|
||||
of "":
|
||||
nil # Do nothing.
|
||||
discard
|
||||
else:
|
||||
raise newException(EInvalidValue, "Invalid format string: " & currentF)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
include "system/inclrtl"
|
||||
|
||||
type
|
||||
irune = int # underlying type of TRune
|
||||
TRune* = distinct irune ## type that can hold any Unicode character
|
||||
IRune = int # underlying type of TRune
|
||||
TRune* = distinct IRune ## type that can hold any Unicode character
|
||||
TRune16* = distinct int16 ## 16 bit Unicode character
|
||||
|
||||
proc `<=%`*(a, b: TRune): bool = return int(a) <=% int(b)
|
||||
|
|
@ -109,7 +109,7 @@ proc runeAt*(s: string, i: int): TRune =
|
|||
|
||||
proc toUTF8*(c: TRune): string {.rtl, extern: "nuc$1".} =
|
||||
## converts a rune into its UTF8 representation
|
||||
var i = irune(c)
|
||||
var i = IRune(c)
|
||||
if i <=% 127:
|
||||
result = newString(1)
|
||||
result[0] = chr(i)
|
||||
|
|
@ -132,6 +132,10 @@ proc toUTF8*(c: TRune): string {.rtl, extern: "nuc$1".} =
|
|||
result = newString(1)
|
||||
result[0] = chr(i)
|
||||
|
||||
proc `$`*(rune: TRune): string =
|
||||
## converts a rune to a string
|
||||
rune.toUTF8
|
||||
|
||||
proc `$`*(runes: seq[TRune]): string =
|
||||
## converts a sequence of runes to a string
|
||||
result = ""
|
||||
|
|
@ -1096,7 +1100,7 @@ const
|
|||
0x01f1, 501, #
|
||||
0x01f3, 499] #
|
||||
|
||||
proc binarySearch(c: irune, tab: openArray[iRune], len, stride: int): int =
|
||||
proc binarySearch(c: IRune, tab: openArray[IRune], len, stride: int): int =
|
||||
var n = len
|
||||
var t = 0
|
||||
while n > 1:
|
||||
|
|
@ -1114,29 +1118,29 @@ proc binarySearch(c: irune, tab: openArray[iRune], len, stride: int): int =
|
|||
proc toLower*(c: TRune): TRune {.rtl, extern: "nuc$1", procvar.} =
|
||||
## Converts `c` into lower case. This works for any Unicode character.
|
||||
## If possible, prefer `toLower` over `toUpper`.
|
||||
var c = irune(c)
|
||||
var p = binarySearch(c, tolowerRanges, len(toLowerRanges) div 3, 3)
|
||||
var c = IRune(c)
|
||||
var p = binarySearch(c, tolowerRanges, len(tolowerRanges) div 3, 3)
|
||||
if p >= 0 and c >= tolowerRanges[p] and c <= tolowerRanges[p+1]:
|
||||
return TRune(c + tolowerRanges[p+2] - 500)
|
||||
p = binarySearch(c, toLowerSinglets, len(toLowerSinglets) div 2, 2)
|
||||
if p >= 0 and c == toLowerSinglets[p]:
|
||||
return TRune(c + toLowerSinglets[p+1] - 500)
|
||||
p = binarySearch(c, tolowerSinglets, len(tolowerSinglets) div 2, 2)
|
||||
if p >= 0 and c == tolowerSinglets[p]:
|
||||
return TRune(c + tolowerSinglets[p+1] - 500)
|
||||
return TRune(c)
|
||||
|
||||
proc toUpper*(c: TRune): TRune {.rtl, extern: "nuc$1", procvar.} =
|
||||
## Converts `c` into upper case. This works for any Unicode character.
|
||||
## If possible, prefer `toLower` over `toUpper`.
|
||||
var c = irune(c)
|
||||
var p = binarySearch(c, toUpperRanges, len(toUpperRanges) div 3, 3)
|
||||
if p >= 0 and c >= toUpperRanges[p] and c <= toUpperRanges[p+1]:
|
||||
return TRune(c + toUpperRanges[p+2] - 500)
|
||||
p = binarySearch(c, toUpperSinglets, len(toUpperSinglets) div 2, 2)
|
||||
if p >= 0 and c == toUpperSinglets[p]:
|
||||
return TRune(c + toUpperSinglets[p+1] - 500)
|
||||
var c = IRune(c)
|
||||
var p = binarySearch(c, toupperRanges, len(toupperRanges) div 3, 3)
|
||||
if p >= 0 and c >= toupperRanges[p] and c <= toupperRanges[p+1]:
|
||||
return TRune(c + toupperRanges[p+2] - 500)
|
||||
p = binarySearch(c, toupperSinglets, len(toupperSinglets) div 2, 2)
|
||||
if p >= 0 and c == toupperSinglets[p]:
|
||||
return TRune(c + toupperSinglets[p+1] - 500)
|
||||
return TRune(c)
|
||||
|
||||
proc toTitle*(c: TRune): TRune {.rtl, extern: "nuc$1", procvar.} =
|
||||
var c = irune(c)
|
||||
var c = IRune(c)
|
||||
var p = binarySearch(c, toTitleSinglets, len(toTitleSinglets) div 2, 2)
|
||||
if p >= 0 and c == toTitleSinglets[p]:
|
||||
return TRune(c + toTitleSinglets[p+1] - 500)
|
||||
|
|
@ -1145,32 +1149,32 @@ proc toTitle*(c: TRune): TRune {.rtl, extern: "nuc$1", procvar.} =
|
|||
proc isLower*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} =
|
||||
## returns true iff `c` is a lower case Unicode character
|
||||
## If possible, prefer `isLower` over `isUpper`.
|
||||
var c = irune(c)
|
||||
var c = IRune(c)
|
||||
# Note: toUpperRanges is correct here!
|
||||
var p = binarySearch(c, toUpperRanges, len(toUpperRanges) div 3, 3)
|
||||
if p >= 0 and c >= toUpperRanges[p] and c <= toUpperRanges[p+1]:
|
||||
var p = binarySearch(c, toupperRanges, len(toupperRanges) div 3, 3)
|
||||
if p >= 0 and c >= toupperRanges[p] and c <= toupperRanges[p+1]:
|
||||
return true
|
||||
p = binarySearch(c, toUpperSinglets, len(toUpperSinglets) div 2, 2)
|
||||
if p >= 0 and c == toUpperSinglets[p]:
|
||||
p = binarySearch(c, toupperSinglets, len(toupperSinglets) div 2, 2)
|
||||
if p >= 0 and c == toupperSinglets[p]:
|
||||
return true
|
||||
|
||||
proc isUpper*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} =
|
||||
## returns true iff `c` is a upper case Unicode character
|
||||
## If possible, prefer `isLower` over `isUpper`.
|
||||
var c = irune(c)
|
||||
var c = IRune(c)
|
||||
# Note: toLowerRanges is correct here!
|
||||
var p = binarySearch(c, toLowerRanges, len(toLowerRanges) div 3, 3)
|
||||
if p >= 0 and c >= toLowerRanges[p] and c <= toLowerRanges[p+1]:
|
||||
var p = binarySearch(c, tolowerRanges, len(tolowerRanges) div 3, 3)
|
||||
if p >= 0 and c >= tolowerRanges[p] and c <= tolowerRanges[p+1]:
|
||||
return true
|
||||
p = binarySearch(c, toLowerSinglets, len(toLowerSinglets) div 2, 2)
|
||||
if p >= 0 and c == toLowerSinglets[p]:
|
||||
p = binarySearch(c, tolowerSinglets, len(tolowerSinglets) div 2, 2)
|
||||
if p >= 0 and c == tolowerSinglets[p]:
|
||||
return true
|
||||
|
||||
proc isAlpha*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} =
|
||||
## returns true iff `c` is an *alpha* Unicode character (i.e. a letter)
|
||||
if isUpper(c) or isLower(c):
|
||||
return true
|
||||
var c = irune(c)
|
||||
var c = IRune(c)
|
||||
var p = binarySearch(c, alphaRanges, len(alphaRanges) div 2, 2)
|
||||
if p >= 0 and c >= alphaRanges[p] and c <= alphaRanges[p+1]:
|
||||
return true
|
||||
|
|
@ -1183,7 +1187,7 @@ proc isTitle*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} =
|
|||
|
||||
proc isWhiteSpace*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} =
|
||||
## returns true iff `c` is a Unicode whitespace character
|
||||
var c = irune(c)
|
||||
var c = IRune(c)
|
||||
var p = binarySearch(c, spaceRanges, len(spaceRanges) div 2, 2)
|
||||
if p >= 0 and c >= spaceRanges[p] and c <= spaceRanges[p+1]:
|
||||
return true
|
||||
|
|
@ -1210,7 +1214,7 @@ proc cmpRunesIgnoreCase*(a, b: string): int {.rtl, extern: "nuc$1", procvar.} =
|
|||
# slow path:
|
||||
fastRuneAt(a, i, ar)
|
||||
fastRuneAt(b, j, br)
|
||||
result = irune(toLower(ar)) - irune(toLower(br))
|
||||
result = IRune(toLower(ar)) - IRune(toLower(br))
|
||||
if result != 0: return
|
||||
result = a.len - b.len
|
||||
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ var
|
|||
|
||||
checkpoints: seq[string] = @[]
|
||||
|
||||
template TestSetupIMPL*: stmt {.immediate, dirty.} = nil
|
||||
template TestTeardownIMPL*: stmt {.immediate, dirty.} = nil
|
||||
template TestSetupIMPL*: stmt {.immediate, dirty.} = discard
|
||||
template TestTeardownIMPL*: stmt {.immediate, dirty.} = discard
|
||||
|
||||
proc shouldRun(testName: string): bool =
|
||||
result = true
|
||||
|
|
@ -126,7 +126,7 @@ macro check*(conditions: stmt): stmt {.immediate.} =
|
|||
for i in 1 .. <exp.len:
|
||||
if exp[i].kind notin nnkLiterals:
|
||||
inc counter
|
||||
var arg = newIdentNode(":p" & ($counter))
|
||||
var arg = newIdentNode(":p" & $counter)
|
||||
var argStr = exp[i].toStrLit
|
||||
if exp[i].kind in nnkCallKinds: inspectArgs(exp[i])
|
||||
argsAsgns.add getAst(asgn(arg, exp[i]))
|
||||
|
|
@ -146,7 +146,8 @@ macro check*(conditions: stmt): stmt {.immediate.} =
|
|||
|
||||
var checkedStr = checked.toStrLit
|
||||
inspectArgs(checked)
|
||||
result = getAst(rewrite(checked, checked.lineinfo, checkedStr, argsAsgns, argsPrintOuts))
|
||||
result = getAst(rewrite(checked, checked.lineinfo, checkedStr,
|
||||
argsAsgns, argsPrintOuts))
|
||||
|
||||
of nnkStmtList:
|
||||
result = newNimNode(nnkStmtList)
|
||||
|
|
@ -176,7 +177,7 @@ macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} =
|
|||
checkpoint(lineInfoLit & ": Expect Failed, no exception was thrown.")
|
||||
fail()
|
||||
except errorTypes:
|
||||
nil
|
||||
discard
|
||||
|
||||
var body = exp[exp.len - 1]
|
||||
|
||||
|
|
|
|||
262
lib/system.nim
262
lib/system.nim
|
|
@ -144,7 +144,7 @@ proc reset*[T](obj: var T) {.magic: "Reset", noSideEffect.}
|
|||
## be called before any possible `object branch transition`:idx:.
|
||||
|
||||
# for low and high the return type T may not be correct, but
|
||||
# we handle that with compiler magic in SemLowHigh()
|
||||
# we handle that with compiler magic in semLowHigh()
|
||||
proc high*[T](x: T): T {.magic: "High", noSideEffect.}
|
||||
## returns the highest possible index of an array, a sequence, a string or
|
||||
## the highest possible value of an ordinal value `x`. As a special
|
||||
|
|
@ -159,7 +159,7 @@ type
|
|||
range*{.magic: "Range".}[T] ## Generic type to construct range types.
|
||||
array*{.magic: "Array".}[I, T] ## Generic type to construct
|
||||
## fixed-length arrays.
|
||||
openarray*{.magic: "OpenArray".}[T] ## Generic type to construct open arrays.
|
||||
openArray*{.magic: "OpenArray".}[T] ## Generic type to construct open arrays.
|
||||
## Open arrays are implemented as a
|
||||
## pointer to the array data and a
|
||||
## length field.
|
||||
|
|
@ -186,7 +186,10 @@ proc `..`*[T](b: T): TSlice[T] {.noSideEffect, inline.} =
|
|||
when not defined(niminheritable):
|
||||
{.pragma: inheritable.}
|
||||
|
||||
when not defined(JS) and not defined(NimrodVM):
|
||||
const NoFakeVars* = defined(NimrodVM) ## true if the backend doesn't support \
|
||||
## "fake variables" like 'var EBADF {.importc.}: cint'.
|
||||
|
||||
when not defined(JS):
|
||||
type
|
||||
TGenericSeq {.compilerproc, pure, inheritable.} = object
|
||||
len, reserved: int
|
||||
|
|
@ -195,14 +198,15 @@ when not defined(JS) and not defined(NimrodVM):
|
|||
NimStringDesc {.compilerproc, final.} = object of TGenericSeq
|
||||
data: array[0..100_000_000, char]
|
||||
NimString = ptr NimStringDesc
|
||||
|
||||
|
||||
when not defined(JS) and not defined(NimrodVM):
|
||||
template space(s: PGenericSeq): int {.dirty.} =
|
||||
s.reserved and not seqShallowFlag
|
||||
|
||||
include "system/hti"
|
||||
|
||||
type
|
||||
Byte* = uInt8 ## this is an alias for ``uint8``, that is an unsigned
|
||||
Byte* = uint8 ## this is an alias for ``uint8``, that is an unsigned
|
||||
## int 8 bits wide.
|
||||
|
||||
Natural* = range[0..high(int)]
|
||||
|
|
@ -335,13 +339,13 @@ type
|
|||
|
||||
TResult* = enum Failure, Success
|
||||
|
||||
proc sizeof*[T](x: T): natural {.magic: "SizeOf", noSideEffect.}
|
||||
proc sizeof*[T](x: T): Natural {.magic: "SizeOf", noSideEffect.}
|
||||
## returns the size of ``x`` in bytes. Since this is a low-level proc,
|
||||
## its usage is discouraged - using ``new`` for the most cases suffices
|
||||
## that one never needs to know ``x``'s size. As a special semantic rule,
|
||||
## ``x`` may also be a type identifier (``sizeof(int)`` is valid).
|
||||
|
||||
proc `<`*[T](x: ordinal[T]): T {.magic: "UnaryLt", noSideEffect.}
|
||||
proc `<`*[T](x: Ordinal[T]): T {.magic: "UnaryLt", noSideEffect.}
|
||||
## unary ``<`` that can be used for nice looking excluding ranges:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
|
|
@ -349,22 +353,22 @@ proc `<`*[T](x: ordinal[T]): T {.magic: "UnaryLt", noSideEffect.}
|
|||
##
|
||||
## Semantically this is the same as ``pred``.
|
||||
|
||||
proc succ*[T](x: ordinal[T], y = 1): T {.magic: "Succ", noSideEffect.}
|
||||
proc succ*[T](x: Ordinal[T], y = 1): T {.magic: "Succ", noSideEffect.}
|
||||
## returns the ``y``-th successor of the value ``x``. ``T`` has to be
|
||||
## an ordinal type. If such a value does not exist, ``EOutOfRange`` is raised
|
||||
## or a compile time error occurs.
|
||||
|
||||
proc pred*[T](x: ordinal[T], y = 1): T {.magic: "Pred", noSideEffect.}
|
||||
proc pred*[T](x: Ordinal[T], y = 1): T {.magic: "Pred", noSideEffect.}
|
||||
## returns the ``y``-th predecessor of the value ``x``. ``T`` has to be
|
||||
## an ordinal type. If such a value does not exist, ``EOutOfRange`` is raised
|
||||
## or a compile time error occurs.
|
||||
|
||||
proc inc*[T](x: var ordinal[T], y = 1) {.magic: "Inc", noSideEffect.}
|
||||
proc inc*[T](x: var Ordinal[T], y = 1) {.magic: "Inc", noSideEffect.}
|
||||
## increments the ordinal ``x`` by ``y``. If such a value does not
|
||||
## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a
|
||||
## short notation for: ``x = succ(x, y)``.
|
||||
|
||||
proc dec*[T](x: var ordinal[T], y = 1) {.magic: "Dec", noSideEffect.}
|
||||
proc dec*[T](x: var Ordinal[T], y = 1) {.magic: "Dec", noSideEffect.}
|
||||
## decrements the ordinal ``x`` by ``y``. If such a value does not
|
||||
## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a
|
||||
## short notation for: ``x = pred(x, y)``.
|
||||
|
|
@ -418,10 +422,18 @@ proc incl*[T](x: var set[T], y: T) {.magic: "Incl", noSideEffect.}
|
|||
## includes element ``y`` to the set ``x``. This is the same as
|
||||
## ``x = x + {y}``, but it might be more efficient.
|
||||
|
||||
template incl*[T](s: var set[T], flags: set[T]) =
|
||||
## includes the set of flags to the set ``x``.
|
||||
s = s + flags
|
||||
|
||||
proc excl*[T](x: var set[T], y: T) {.magic: "Excl", noSideEffect.}
|
||||
## excludes element ``y`` to the set ``x``. This is the same as
|
||||
## ``x = x - {y}``, but it might be more efficient.
|
||||
|
||||
template excl*[T](s: var set[T], flags: set[T]) =
|
||||
## excludes the set of flags to ``x``.
|
||||
s = s - flags
|
||||
|
||||
proc card*[T](x: set[T]): int {.magic: "Card", noSideEffect.}
|
||||
## returns the cardinality of the set ``x``, i.e. the number of elements
|
||||
## in the set.
|
||||
|
|
@ -435,38 +447,38 @@ proc chr*(u: range[0..255]): char {.magic: "Chr", noSideEffect.}
|
|||
# --------------------------------------------------------------------------
|
||||
# built-in operators
|
||||
|
||||
proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect.}
|
||||
## zero extends a smaller integer type to ``int``. This treats `x` as
|
||||
## unsigned.
|
||||
proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect.}
|
||||
## zero extends a smaller integer type to ``int``. This treats `x` as
|
||||
## unsigned.
|
||||
when not defined(JS):
|
||||
proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect.}
|
||||
## zero extends a smaller integer type to ``int``. This treats `x` as
|
||||
## unsigned.
|
||||
proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect.}
|
||||
## zero extends a smaller integer type to ``int``. This treats `x` as
|
||||
## unsigned.
|
||||
|
||||
proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect.}
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned.
|
||||
proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect.}
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned.
|
||||
proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect.}
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned.
|
||||
proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect.}
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned.
|
||||
|
||||
proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect.}
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned.
|
||||
proc ze64*(x: int): int64 {.magic: "ZeIToI64", noSideEffect.}
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned. Does nothing if the size of an ``int`` is the same as ``int64``.
|
||||
## (This is the case on 64 bit processors.)
|
||||
|
||||
proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect.}
|
||||
## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
|
||||
## from `x`.
|
||||
proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect.}
|
||||
## treats `x` as unsigned and converts it to an ``int16`` by taking the last
|
||||
## 16 bits from `x`.
|
||||
proc toU32*(x: int64): int32 {.magic: "ToU32", noSideEffect.}
|
||||
## treats `x` as unsigned and converts it to an ``int32`` by taking the
|
||||
## last 32 bits from `x`.
|
||||
proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect.}
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned.
|
||||
proc ze64*(x: int): int64 {.magic: "ZeIToI64", noSideEffect.}
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned. Does nothing if the size of an ``int`` is the same as ``int64``.
|
||||
## (This is the case on 64 bit processors.)
|
||||
|
||||
proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect.}
|
||||
## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
|
||||
## from `x`.
|
||||
proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect.}
|
||||
## treats `x` as unsigned and converts it to an ``int16`` by taking the last
|
||||
## 16 bits from `x`.
|
||||
proc toU32*(x: int64): int32 {.magic: "ToU32", noSideEffect.}
|
||||
## treats `x` as unsigned and converts it to an ``int32`` by taking the
|
||||
## last 32 bits from `x`.
|
||||
|
||||
# integer calculations:
|
||||
proc `+` *(x: int): int {.magic: "UnaryPlusI", noSideEffect.}
|
||||
|
|
@ -584,46 +596,46 @@ proc `<` *(x, y: int64): bool {.magic: "LtI64", noSideEffect.}
|
|||
## Returns true iff `x` is less than `y`.
|
||||
|
||||
type
|
||||
IntMax32 = bool|int|int8|int16|int32
|
||||
IntMax32 = int|int8|int16|int32
|
||||
|
||||
proc `+%` *(x, y: IntMax32): IntMax32 {.magic: "AddU", noSideEffect.}
|
||||
proc `+%` *(x, y: Int64): Int64 {.magic: "AddU", noSideEffect.}
|
||||
proc `+%` *(x, y: int64): int64 {.magic: "AddU", noSideEffect.}
|
||||
## treats `x` and `y` as unsigned and adds them. The result is truncated to
|
||||
## fit into the result. This implements modulo arithmetic. No overflow
|
||||
## errors are possible.
|
||||
|
||||
proc `-%` *(x, y: IntMax32): IntMax32 {.magic: "SubU", noSideEffect.}
|
||||
proc `-%` *(x, y: Int64): Int64 {.magic: "SubU", noSideEffect.}
|
||||
proc `-%` *(x, y: int64): int64 {.magic: "SubU", noSideEffect.}
|
||||
## treats `x` and `y` as unsigned and subtracts them. The result is
|
||||
## truncated to fit into the result. This implements modulo arithmetic.
|
||||
## No overflow errors are possible.
|
||||
|
||||
proc `*%` *(x, y: IntMax32): IntMax32 {.magic: "MulU", noSideEffect.}
|
||||
proc `*%` *(x, y: Int64): Int64 {.magic: "MulU", noSideEffect.}
|
||||
proc `*%` *(x, y: int64): int64 {.magic: "MulU", noSideEffect.}
|
||||
## treats `x` and `y` as unsigned and multiplies them. The result is
|
||||
## truncated to fit into the result. This implements modulo arithmetic.
|
||||
## No overflow errors are possible.
|
||||
|
||||
proc `/%` *(x, y: IntMax32): IntMax32 {.magic: "DivU", noSideEffect.}
|
||||
proc `/%` *(x, y: Int64): Int64 {.magic: "DivU", noSideEffect.}
|
||||
proc `/%` *(x, y: int64): int64 {.magic: "DivU", noSideEffect.}
|
||||
## treats `x` and `y` as unsigned and divides them. The result is
|
||||
## truncated to fit into the result. This implements modulo arithmetic.
|
||||
## No overflow errors are possible.
|
||||
|
||||
proc `%%` *(x, y: IntMax32): IntMax32 {.magic: "ModU", noSideEffect.}
|
||||
proc `%%` *(x, y: Int64): Int64 {.magic: "ModU", noSideEffect.}
|
||||
proc `%%` *(x, y: int64): int64 {.magic: "ModU", noSideEffect.}
|
||||
## treats `x` and `y` as unsigned and compute the modulo of `x` and `y`.
|
||||
## The result is truncated to fit into the result.
|
||||
## This implements modulo arithmetic.
|
||||
## No overflow errors are possible.
|
||||
|
||||
proc `<=%` *(x, y: IntMax32): bool {.magic: "LeU", noSideEffect.}
|
||||
proc `<=%` *(x, y: Int64): bool {.magic: "LeU64", noSideEffect.}
|
||||
proc `<=%` *(x, y: int64): bool {.magic: "LeU64", noSideEffect.}
|
||||
## treats `x` and `y` as unsigned and compares them.
|
||||
## Returns true iff ``unsigned(x) <= unsigned(y)``.
|
||||
|
||||
proc `<%` *(x, y: IntMax32): bool {.magic: "LtU", noSideEffect.}
|
||||
proc `<%` *(x, y: Int64): bool {.magic: "LtU64", noSideEffect.}
|
||||
proc `<%` *(x, y: int64): bool {.magic: "LtU64", noSideEffect.}
|
||||
## treats `x` and `y` as unsigned and compares them.
|
||||
## Returns true iff ``unsigned(x) < unsigned(y)``.
|
||||
|
||||
|
|
@ -728,10 +740,10 @@ proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} =
|
|||
result = s.a <= value and value <= s.b
|
||||
|
||||
template `in` * (x, y: expr): expr {.immediate.} = contains(y, x)
|
||||
template `not_in` * (x, y: expr): expr {.immediate.} = not contains(y, x)
|
||||
template `notin` * (x, y: expr): expr {.immediate.} = not contains(y, x)
|
||||
|
||||
proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.}
|
||||
template `is_not` *(x, y: expr): expr {.immediate.} = not (x is y)
|
||||
template `isnot` *(x, y: expr): expr {.immediate.} = not (x is y)
|
||||
|
||||
proc `of` *[T, S](x: T, y: S): bool {.magic: "Of", noSideEffect.}
|
||||
|
||||
|
|
@ -933,7 +945,6 @@ template sysAssert(cond: bool, msg: string) =
|
|||
if not cond:
|
||||
echo "[SYSASSERT] ", msg
|
||||
quit 1
|
||||
nil
|
||||
|
||||
include "system/inclrtl"
|
||||
|
||||
|
|
@ -1061,7 +1072,7 @@ proc toFloat*(i: int): float {.
|
|||
## fails, `EInvalidValue` is raised. However, on most platforms the
|
||||
## conversion cannot fail.
|
||||
|
||||
proc toBiggestFloat*(i: biggestint): biggestfloat {.
|
||||
proc toBiggestFloat*(i: BiggestInt): BiggestFloat {.
|
||||
magic: "ToBiggestFloat", noSideEffect, importc: "toBiggestFloat".}
|
||||
## converts an biggestint `i` into a ``biggestfloat``. If the conversion
|
||||
## fails, `EInvalidValue` is raised. However, on most platforms the
|
||||
|
|
@ -1073,7 +1084,7 @@ proc toInt*(f: float): int {.
|
|||
## rounds `f` if it does not contain an integer value. If the conversion
|
||||
## fails (because `f` is infinite for example), `EInvalidValue` is raised.
|
||||
|
||||
proc toBiggestInt*(f: biggestfloat): biggestint {.
|
||||
proc toBiggestInt*(f: BiggestFloat): BiggestInt {.
|
||||
magic: "ToBiggestInt", noSideEffect, importc: "toBiggestInt".}
|
||||
## converts a biggestfloat `f` into a ``biggestint``. Conversion
|
||||
## rounds `f` if it does not contain an integer value. If the conversion
|
||||
|
|
@ -1115,19 +1126,19 @@ proc substr*(s: string, first, last: int): string {.
|
|||
## or `limit`:idx: a string's length.
|
||||
|
||||
when not defined(nimrodVM):
|
||||
proc zeroMem*(p: Pointer, size: int) {.importc, noDecl.}
|
||||
proc zeroMem*(p: pointer, size: int) {.importc, noDecl.}
|
||||
## overwrites the contents of the memory at ``p`` with the value 0.
|
||||
## Exactly ``size`` bytes will be overwritten. Like any procedure
|
||||
## dealing with raw memory this is *unsafe*.
|
||||
|
||||
proc copyMem*(dest, source: Pointer, size: int) {.
|
||||
proc copyMem*(dest, source: pointer, size: int) {.
|
||||
importc: "memcpy", header: "<string.h>".}
|
||||
## copies the contents from the memory at ``source`` to the memory
|
||||
## at ``dest``. Exactly ``size`` bytes will be copied. The memory
|
||||
## regions may not overlap. Like any procedure dealing with raw
|
||||
## memory this is *unsafe*.
|
||||
|
||||
proc moveMem*(dest, source: Pointer, size: int) {.
|
||||
proc moveMem*(dest, source: pointer, size: int) {.
|
||||
importc: "memmove", header: "<string.h>".}
|
||||
## copies the contents from the memory at ``source`` to the memory
|
||||
## at ``dest``. Exactly ``size`` bytes will be copied. The memory
|
||||
|
|
@ -1135,14 +1146,14 @@ when not defined(nimrodVM):
|
|||
## and is thus somewhat more safe than ``copyMem``. Like any procedure
|
||||
## dealing with raw memory this is still *unsafe*, though.
|
||||
|
||||
proc equalMem*(a, b: Pointer, size: int): bool {.
|
||||
proc equalMem*(a, b: pointer, size: int): bool {.
|
||||
importc: "equalMem", noDecl, noSideEffect.}
|
||||
## compares the memory blocks ``a`` and ``b``. ``size`` bytes will
|
||||
## be compared. If the blocks are equal, true is returned, false
|
||||
## otherwise. Like any procedure dealing with raw memory this is
|
||||
## *unsafe*.
|
||||
|
||||
when hostOs != "standalone":
|
||||
when hostOS != "standalone":
|
||||
proc alloc*(size: int): pointer {.noconv, rtl, tags: [].}
|
||||
## allocates a new memory block with at least ``size`` bytes. The
|
||||
## block has to be freed with ``realloc(block, 0)`` or
|
||||
|
|
@ -1157,7 +1168,7 @@ when not defined(nimrodVM):
|
|||
## containing zero, so it is somewhat safer than ``alloc``.
|
||||
## The allocated memory belongs to its allocating thread!
|
||||
## Use `allocShared0` to allocate from a shared heap.
|
||||
proc realloc*(p: Pointer, newsize: int): pointer {.noconv, rtl, tags: [].}
|
||||
proc realloc*(p: pointer, newsize: int): pointer {.noconv, rtl, tags: [].}
|
||||
## grows or shrinks a given memory block. If p is **nil** then a new
|
||||
## memory block is returned. In either way the block has at least
|
||||
## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil**
|
||||
|
|
@ -1165,7 +1176,7 @@ when not defined(nimrodVM):
|
|||
## be freed with ``dealloc``.
|
||||
## The allocated memory belongs to its allocating thread!
|
||||
## Use `reallocShared` to reallocate from a shared heap.
|
||||
proc dealloc*(p: Pointer) {.noconv, rtl, tags: [].}
|
||||
proc dealloc*(p: pointer) {.noconv, rtl, tags: [].}
|
||||
## frees the memory allocated with ``alloc``, ``alloc0`` or
|
||||
## ``realloc``. This procedure is dangerous! If one forgets to
|
||||
## free the memory a leak occurs; if one tries to access freed
|
||||
|
|
@ -1186,13 +1197,13 @@ when not defined(nimrodVM):
|
|||
## ``reallocShared(block, 0)`` or ``deallocShared(block)``.
|
||||
## The block is initialized with all bytes
|
||||
## containing zero, so it is somewhat safer than ``allocShared``.
|
||||
proc reallocShared*(p: Pointer, newsize: int): pointer {.noconv, rtl.}
|
||||
proc reallocShared*(p: pointer, newsize: int): pointer {.noconv, rtl.}
|
||||
## grows or shrinks a given memory block on the heap. If p is **nil**
|
||||
## then a new memory block is returned. In either way the block has at least
|
||||
## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil**
|
||||
## ``reallocShared`` calls ``deallocShared(p)``. In other cases the
|
||||
## block has to be freed with ``deallocShared``.
|
||||
proc deallocShared*(p: Pointer) {.noconv, rtl.}
|
||||
proc deallocShared*(p: pointer) {.noconv, rtl.}
|
||||
## frees the memory allocated with ``allocShared``, ``allocShared0`` or
|
||||
## ``reallocShared``. This procedure is dangerous! If one forgets to
|
||||
## free the memory a leak occurs; if one tries to access freed
|
||||
|
|
@ -1237,7 +1248,7 @@ proc `$` *(x: char): string {.magic: "CharToStr", noSideEffect.}
|
|||
## The stingify operator for a character argument. Returns `x`
|
||||
## converted to a string.
|
||||
|
||||
proc `$` *(x: Cstring): string {.magic: "CStrToStr", noSideEffect.}
|
||||
proc `$` *(x: cstring): string {.magic: "CStrToStr", noSideEffect.}
|
||||
## The stingify operator for a CString argument. Returns `x`
|
||||
## converted to a string.
|
||||
|
||||
|
|
@ -1259,13 +1270,13 @@ proc getRefcount*[T](x: seq[T]): int {.importc: "getRefcount", noSideEffect.}
|
|||
## retrieves the reference count of an heap-allocated object. The
|
||||
## value is implementation-dependent.
|
||||
|
||||
# new constants:
|
||||
|
||||
const
|
||||
inf* {.magic: "Inf".} = 1.0 / 0.0
|
||||
Inf* {.magic: "Inf".} = 1.0 / 0.0
|
||||
## contains the IEEE floating point value of positive infinity.
|
||||
neginf* {.magic: "NegInf".} = -inf
|
||||
NegInf* {.magic: "NegInf".} = -Inf
|
||||
## contains the IEEE floating point value of negative infinity.
|
||||
nan* {.magic: "NaN".} = 0.0 / 0.0
|
||||
NaN* {.magic: "NaN".} = 0.0 / 0.0
|
||||
## contains an IEEE floating point value of *Not A Number*. Note
|
||||
## that you cannot compare a floating point value to this value
|
||||
## and expect a reasonable result - use the `classify` procedure
|
||||
|
|
@ -1319,7 +1330,7 @@ iterator `||`*[S, T](a: S, b: T, annotation=""): T {.
|
|||
## such isn't aware of the parallelism in your code! Be careful! Later
|
||||
## versions of ``||`` will get proper support by Nimrod's code generator
|
||||
## and GC.
|
||||
nil
|
||||
discard
|
||||
|
||||
{.push stackTrace:off.}
|
||||
proc min*(x, y: int): int {.magic: "MinI", noSideEffect.} =
|
||||
|
|
@ -1372,7 +1383,7 @@ proc clamp*[T](x, a, b: T): T =
|
|||
if x > b: return b
|
||||
return x
|
||||
|
||||
iterator items*[T](a: openarray[T]): T {.inline.} =
|
||||
iterator items*[T](a: openArray[T]): T {.inline.} =
|
||||
## iterates over each item of `a`.
|
||||
var i = 0
|
||||
while i < len(a):
|
||||
|
|
@ -1425,7 +1436,7 @@ iterator items*(E: typedesc[enum]): E =
|
|||
for v in low(E)..high(E):
|
||||
yield v
|
||||
|
||||
iterator pairs*[T](a: openarray[T]): tuple[key: int, val: T] {.inline.} =
|
||||
iterator pairs*[T](a: openArray[T]): tuple[key: int, val: T] {.inline.} =
|
||||
## iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
|
||||
var i = 0
|
||||
while i < len(a):
|
||||
|
|
@ -1959,20 +1970,20 @@ when not defined(JS): #and not defined(NimrodVM):
|
|||
## Template which expands to either stdout or stderr depending on
|
||||
## `useStdoutAsStdmsg` compile-time switch.
|
||||
|
||||
proc Open*(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead, bufSize: int = -1): Bool {.tags: [].}
|
||||
proc open*(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead, bufSize: int = -1): bool {.tags: [].}
|
||||
## Opens a file named `filename` with given `mode`.
|
||||
##
|
||||
## Default mode is readonly. Returns true iff the file could be opened.
|
||||
## This throws no exception if the file could not be opened.
|
||||
|
||||
proc Open*(f: var TFile, filehandle: TFileHandle,
|
||||
mode: TFileMode = fmRead): Bool {.tags: [].}
|
||||
proc open*(f: var TFile, filehandle: TFileHandle,
|
||||
mode: TFileMode = fmRead): bool {.tags: [].}
|
||||
## Creates a ``TFile`` from a `filehandle` with given `mode`.
|
||||
##
|
||||
## Default mode is readonly. Returns true iff the file could be opened.
|
||||
|
||||
proc Open*(filename: string,
|
||||
proc open*(filename: string,
|
||||
mode: TFileMode = fmRead, bufSize: int = -1): TFile =
|
||||
## Opens a file named `filename` with given `mode`.
|
||||
##
|
||||
|
|
@ -1989,16 +2000,16 @@ when not defined(JS): #and not defined(NimrodVM):
|
|||
##
|
||||
## Default mode is readonly. Returns true iff the file could be reopened.
|
||||
|
||||
proc Close*(f: TFile) {.importc: "fclose", header: "<stdio.h>", tags: [].}
|
||||
proc close*(f: TFile) {.importc: "fclose", header: "<stdio.h>", tags: [].}
|
||||
## Closes the file.
|
||||
|
||||
proc EndOfFile*(f: TFile): Bool {.tags: [].}
|
||||
proc endOfFile*(f: TFile): bool {.tags: [].}
|
||||
## Returns true iff `f` is at the end.
|
||||
|
||||
proc readChar*(f: TFile): char {.
|
||||
importc: "fgetc", header: "<stdio.h>", tags: [FReadIO].}
|
||||
## Reads a single character from the stream `f`.
|
||||
proc FlushFile*(f: TFile) {.
|
||||
proc flushFile*(f: TFile) {.
|
||||
importc: "fflush", header: "<stdio.h>", tags: [FWriteIO].}
|
||||
## Flushes `f`'s buffer.
|
||||
|
||||
|
|
@ -2018,10 +2029,10 @@ when not defined(JS): #and not defined(NimrodVM):
|
|||
|
||||
proc write*(f: TFile, r: float32) {.tags: [FWriteIO].}
|
||||
proc write*(f: TFile, i: int) {.tags: [FWriteIO].}
|
||||
proc write*(f: TFile, i: biggestInt) {.tags: [FWriteIO].}
|
||||
proc write*(f: TFile, r: biggestFloat) {.tags: [FWriteIO].}
|
||||
proc write*(f: TFile, i: BiggestInt) {.tags: [FWriteIO].}
|
||||
proc write*(f: TFile, r: BiggestFloat) {.tags: [FWriteIO].}
|
||||
proc write*(f: TFile, s: string) {.tags: [FWriteIO].}
|
||||
proc write*(f: TFile, b: Bool) {.tags: [FWriteIO].}
|
||||
proc write*(f: TFile, b: bool) {.tags: [FWriteIO].}
|
||||
proc write*(f: TFile, c: char) {.tags: [FWriteIO].}
|
||||
proc write*(f: TFile, c: cstring) {.tags: [FWriteIO].}
|
||||
proc write*(f: TFile, a: varargs[string, `$`]) {.tags: [FWriteIO].}
|
||||
|
|
@ -2047,13 +2058,13 @@ when not defined(JS): #and not defined(NimrodVM):
|
|||
proc getFileSize*(f: TFile): int64 {.tags: [FReadIO].}
|
||||
## retrieves the file size (in bytes) of `f`.
|
||||
|
||||
proc ReadBytes*(f: TFile, a: var openarray[int8], start, len: int): int {.
|
||||
proc readBytes*(f: TFile, a: var openArray[int8], start, len: int): int {.
|
||||
tags: [FReadIO].}
|
||||
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
|
||||
## the actual number of bytes that have been read which may be less than
|
||||
## `len` (if not as many bytes are remaining), but not greater.
|
||||
|
||||
proc ReadChars*(f: TFile, a: var openarray[char], start, len: int): int {.
|
||||
proc readChars*(f: TFile, a: var openArray[char], start, len: int): int {.
|
||||
tags: [FReadIO].}
|
||||
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
|
||||
## the actual number of bytes that have been read which may be less than
|
||||
|
|
@ -2064,13 +2075,13 @@ when not defined(JS): #and not defined(NimrodVM):
|
|||
## the actual number of bytes that have been read which may be less than
|
||||
## `len` (if not as many bytes are remaining), but not greater.
|
||||
|
||||
proc writeBytes*(f: TFile, a: openarray[int8], start, len: int): int {.
|
||||
proc writeBytes*(f: TFile, a: openArray[int8], start, len: int): int {.
|
||||
tags: [FWriteIO].}
|
||||
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
|
||||
## the number of actual written bytes, which may be less than `len` in case
|
||||
## of an error.
|
||||
|
||||
proc writeChars*(f: tFile, a: openarray[char], start, len: int): int {.
|
||||
proc writeChars*(f: TFile, a: openArray[char], start, len: int): int {.
|
||||
tags: [FWriteIO].}
|
||||
## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns
|
||||
## the number of actual written bytes, which may be less than `len` in case
|
||||
|
|
@ -2192,7 +2203,7 @@ when not defined(JS): #and not defined(NimrodVM):
|
|||
const
|
||||
GenericSeqSize = (2 * sizeof(int))
|
||||
|
||||
proc getDiscriminant(aa: Pointer, n: ptr TNimNode): int =
|
||||
proc getDiscriminant(aa: pointer, n: ptr TNimNode): int =
|
||||
sysAssert(n.kind == nkCase, "getDiscriminant: node != nkCase")
|
||||
var d: int
|
||||
var a = cast[TAddress](aa)
|
||||
|
|
@ -2203,7 +2214,7 @@ when not defined(JS): #and not defined(NimrodVM):
|
|||
else: sysAssert(false, "getDiscriminant: invalid n.typ.size")
|
||||
return d
|
||||
|
||||
proc selectBranch(aa: Pointer, n: ptr TNimNode): ptr TNimNode =
|
||||
proc selectBranch(aa: pointer, n: ptr TNimNode): ptr TNimNode =
|
||||
var discr = getDiscriminant(aa, n)
|
||||
if discr <% n.len:
|
||||
result = n.sons[discr]
|
||||
|
|
@ -2225,8 +2236,19 @@ when not defined(JS): #and not defined(NimrodVM):
|
|||
|
||||
when hostOS != "standalone":
|
||||
iterator lines*(filename: string): TaintedString {.tags: [FReadIO].} =
|
||||
## Iterate over any line in the file named `filename`.
|
||||
## If the file does not exist `EIO` is raised.
|
||||
## Iterates over any line in the file named `filename`.
|
||||
##
|
||||
## If the file does not exist `EIO` is raised. The trailing newline
|
||||
## character(s) are removed from the iterated lines. Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## import strutils
|
||||
##
|
||||
## proc transformLetters(filename: string) =
|
||||
## var buffer = ""
|
||||
## for line in filename.lines:
|
||||
## buffer.add(line.replace("a", "0") & '\x0A')
|
||||
## writeFile(filename, buffer)
|
||||
var f = open(filename)
|
||||
var res = TaintedString(newStringOfCap(80))
|
||||
while f.readLine(res): yield res
|
||||
|
|
@ -2234,6 +2256,17 @@ when not defined(JS): #and not defined(NimrodVM):
|
|||
|
||||
iterator lines*(f: TFile): TaintedString {.tags: [FReadIO].} =
|
||||
## Iterate over any line in the file `f`.
|
||||
##
|
||||
## The trailing newline character(s) are removed from the iterated lines.
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## proc countZeros(filename: TFile): tuple[lines, zeros: int] =
|
||||
## for line in filename.lines:
|
||||
## for letter in line:
|
||||
## if letter == '0':
|
||||
## result.zeros += 1
|
||||
## result.lines += 1
|
||||
var res = TaintedString(newStringOfCap(80))
|
||||
while f.readLine(res): yield res
|
||||
|
||||
|
|
@ -2547,7 +2580,7 @@ proc raiseAssert*(msg: string) {.noinline.} =
|
|||
sysFatal(EAssertionFailed, msg)
|
||||
|
||||
when true:
|
||||
proc hiddenRaiseAssert(msg: string) {.raises: [], tags: [].} =
|
||||
proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} =
|
||||
# trick the compiler to not list ``EAssertionFailed`` when called
|
||||
# by ``assert``.
|
||||
type THide = proc (msg: string) {.noinline, raises: [], noSideEffect,
|
||||
|
|
@ -2560,11 +2593,11 @@ template assert*(cond: bool, msg = "") =
|
|||
## raises an ``EAssertionFailure`` exception. However, the compiler may
|
||||
## not generate any code at all for ``assert`` if it is advised to do so.
|
||||
## Use ``assert`` for debugging purposes only.
|
||||
bind instantiationInfo, hiddenRaiseAssert
|
||||
bind instantiationInfo
|
||||
mixin failedAssertImpl
|
||||
when compileOption("assertions"):
|
||||
{.line.}:
|
||||
if not cond:
|
||||
hiddenRaiseAssert(astToStr(cond) & ' ' & msg)
|
||||
if not cond: failedAssertImpl(astToStr(cond) & ' ' & msg)
|
||||
|
||||
template doAssert*(cond: bool, msg = "") =
|
||||
## same as `assert` but is always turned on and not affected by the
|
||||
|
|
@ -2577,9 +2610,9 @@ template doAssert*(cond: bool, msg = "") =
|
|||
when not defined(nimhygiene):
|
||||
{.pragma: inject.}
|
||||
|
||||
template onFailedAssert*(msg: expr, code: stmt): stmt =
|
||||
## Sets an assertion failure handler that will intercept any assert statements
|
||||
## following `onFailedAssert` in the current lexical scope.
|
||||
template onFailedAssert*(msg: expr, code: stmt): stmt {.dirty, immediate.} =
|
||||
## Sets an assertion failure handler that will intercept any assert
|
||||
## statements following `onFailedAssert` in the current lexical scope.
|
||||
## Can be defined multiple times in a single function.
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
|
|
@ -2596,8 +2629,8 @@ template onFailedAssert*(msg: expr, code: stmt): stmt =
|
|||
##
|
||||
## assert(...)
|
||||
##
|
||||
template raiseAssert(msgIMPL: string): stmt =
|
||||
let msg {.inject.} = msgIMPL
|
||||
template failedAssertImpl(msgIMPL: string): stmt {.dirty, immediate.} =
|
||||
let msg = msgIMPL
|
||||
code
|
||||
|
||||
proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} =
|
||||
|
|
@ -2643,7 +2676,7 @@ when hostOS != "standalone":
|
|||
x[j+i] = item[j]
|
||||
inc(j)
|
||||
|
||||
proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect.} =
|
||||
proc compiles*(x): bool {.magic: "Compiles", noSideEffect.} =
|
||||
## Special compile-time procedure that checks whether `x` can be compiled
|
||||
## without any semantic error.
|
||||
## This can be used to check whether a type supports some operation:
|
||||
|
|
@ -2651,7 +2684,7 @@ proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect.} =
|
|||
## .. code-block:: Nimrod
|
||||
## when not compiles(3 + 4):
|
||||
## echo "'+' for integers is available"
|
||||
nil
|
||||
discard
|
||||
|
||||
when defined(initDebugger):
|
||||
initDebugger()
|
||||
|
|
@ -2675,5 +2708,30 @@ proc locals*(): TObject {.magic: "Locals", noSideEffect.} =
|
|||
## in the current scope. This is quite fast as it does not rely
|
||||
## on any debug or runtime information. Note that in constrast to what
|
||||
## the official signature says, the return type is not ``TObject`` but a
|
||||
## tuple of a structure that depends on the current scope.
|
||||
nil
|
||||
## tuple of a structure that depends on the current scope. Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## proc testLocals() =
|
||||
## var
|
||||
## a = "something"
|
||||
## b = 4
|
||||
## c = locals()
|
||||
## d = "super!"
|
||||
##
|
||||
## b = 1
|
||||
## for name, value in fieldPairs(c):
|
||||
## echo "name ", name, " with value ", value
|
||||
## echo "B is ", b
|
||||
## # -> name a with value something
|
||||
## # -> name b with value 4
|
||||
## # -> B is 1
|
||||
discard
|
||||
|
||||
when not defined(booting):
|
||||
type
|
||||
semistatic*[T] = static[T] | T
|
||||
# indicates a param of proc specialized for each static value,
|
||||
# but also accepting run-time values
|
||||
|
||||
template isStatic*(x): expr = compiles(static(x))
|
||||
# checks whether `x` is a value known at compile-time
|
||||
|
|
|
|||
|
|
@ -59,15 +59,16 @@ elif defined(windows):
|
|||
MEM_DECOMMIT = 0x4000
|
||||
MEM_RELEASE = 0x8000
|
||||
|
||||
proc VirtualAlloc(lpAddress: pointer, dwSize: int, flAllocationType,
|
||||
proc virtualAlloc(lpAddress: pointer, dwSize: int, flAllocationType,
|
||||
flProtect: int32): pointer {.
|
||||
header: "<windows.h>", stdcall.}
|
||||
header: "<windows.h>", stdcall, importc: "VirtualAlloc".}
|
||||
|
||||
proc VirtualFree(lpAddress: pointer, dwSize: int,
|
||||
dwFreeType: int32) {.header: "<windows.h>", stdcall.}
|
||||
proc virtualFree(lpAddress: pointer, dwSize: int,
|
||||
dwFreeType: int32) {.header: "<windows.h>", stdcall,
|
||||
importc: "VirtualFree".}
|
||||
|
||||
proc osAllocPages(size: int): pointer {.inline.} =
|
||||
result = VirtualAlloc(nil, size, MEM_RESERVE or MEM_COMMIT,
|
||||
result = virtualAlloc(nil, size, MEM_RESERVE or MEM_COMMIT,
|
||||
PAGE_READWRITE)
|
||||
if result == nil: raiseOutOfMem()
|
||||
|
||||
|
|
@ -78,7 +79,7 @@ elif defined(windows):
|
|||
# Windows :-(. We have to live with MEM_DECOMMIT instead.
|
||||
# Well that used to be the case but MEM_DECOMMIT fragments the address
|
||||
# space heavily, so we now treat Windows as a strange unmap target.
|
||||
when reallyOsDealloc: VirtualFree(p, 0, MEM_RELEASE)
|
||||
when reallyOsDealloc: virtualFree(p, 0, MEM_RELEASE)
|
||||
#VirtualFree(p, size, MEM_DECOMMIT)
|
||||
|
||||
else:
|
||||
|
|
@ -108,7 +109,7 @@ type
|
|||
data: TTrunkBuckets
|
||||
|
||||
type
|
||||
TAlignType = biggestFloat
|
||||
TAlignType = BiggestFloat
|
||||
TFreeCell {.final, pure.} = object
|
||||
next: ptr TFreeCell # next free cell in chunk (overlaid with refcount)
|
||||
zeroField: int # 0 means cell is not used (overlaid with typ field)
|
||||
|
|
@ -251,36 +252,36 @@ proc llDeallocAll(a: var TMemRegion) =
|
|||
osDeallocPages(it, PageSize)
|
||||
it = next
|
||||
|
||||
proc IntSetGet(t: TIntSet, key: int): PTrunk =
|
||||
proc intSetGet(t: TIntSet, key: int): PTrunk =
|
||||
var it = t.data[key and high(t.data)]
|
||||
while it != nil:
|
||||
if it.key == key: return it
|
||||
it = it.next
|
||||
result = nil
|
||||
|
||||
proc IntSetPut(a: var TMemRegion, t: var TIntSet, key: int): PTrunk =
|
||||
result = IntSetGet(t, key)
|
||||
proc intSetPut(a: var TMemRegion, t: var TIntSet, key: int): PTrunk =
|
||||
result = intSetGet(t, key)
|
||||
if result == nil:
|
||||
result = cast[PTrunk](llAlloc(a, sizeof(result[])))
|
||||
result.next = t.data[key and high(t.data)]
|
||||
t.data[key and high(t.data)] = result
|
||||
result.key = key
|
||||
|
||||
proc Contains(s: TIntSet, key: int): bool =
|
||||
var t = IntSetGet(s, key shr TrunkShift)
|
||||
proc contains(s: TIntSet, key: int): bool =
|
||||
var t = intSetGet(s, key shr TrunkShift)
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc Incl(a: var TMemRegion, s: var TIntSet, key: int) =
|
||||
var t = IntSetPut(a, s, key shr TrunkShift)
|
||||
proc incl(a: var TMemRegion, s: var TIntSet, key: int) =
|
||||
var t = intSetPut(a, s, key shr TrunkShift)
|
||||
var u = key and TrunkMask
|
||||
t.bits[u shr IntShift] = t.bits[u shr IntShift] or (1 shl (u and IntMask))
|
||||
|
||||
proc Excl(s: var TIntSet, key: int) =
|
||||
var t = IntSetGet(s, key shr TrunkShift)
|
||||
proc excl(s: var TIntSet, key: int) =
|
||||
var t = intSetGet(s, key shr TrunkShift)
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
t.bits[u shr IntShift] = t.bits[u shr IntShift] and not
|
||||
|
|
@ -387,7 +388,7 @@ proc freeOsChunks(a: var TMemRegion, p: pointer, size: int) =
|
|||
#c_fprintf(c_stdout, "[Alloc] back to OS: %ld\n", size)
|
||||
|
||||
proc isAccessible(a: TMemRegion, p: pointer): bool {.inline.} =
|
||||
result = Contains(a.chunkStarts, pageIndex(p))
|
||||
result = contains(a.chunkStarts, pageIndex(p))
|
||||
|
||||
proc contains[T](list, x: T): bool =
|
||||
var it = list
|
||||
|
|
@ -403,7 +404,7 @@ proc writeFreeList(a: TMemRegion) =
|
|||
it, it.next, it.prev)
|
||||
it = it.next
|
||||
|
||||
proc ListAdd[T](head: var T, c: T) {.inline.} =
|
||||
proc listAdd[T](head: var T, c: T) {.inline.} =
|
||||
sysAssert(c notin head, "listAdd 1")
|
||||
sysAssert c.prev == nil, "listAdd 2"
|
||||
sysAssert c.next == nil, "listAdd 3"
|
||||
|
|
@ -413,7 +414,7 @@ proc ListAdd[T](head: var T, c: T) {.inline.} =
|
|||
head.prev = c
|
||||
head = c
|
||||
|
||||
proc ListRemove[T](head: var T, c: T) {.inline.} =
|
||||
proc listRemove[T](head: var T, c: T) {.inline.} =
|
||||
sysAssert(c in head, "listRemove")
|
||||
if c == head:
|
||||
head = c.next
|
||||
|
|
@ -443,7 +444,7 @@ proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
|
|||
if isAccessible(a, ri) and chunkUnused(ri):
|
||||
sysAssert(not isSmallChunk(ri), "freeBigChunk 3")
|
||||
if not isSmallChunk(ri):
|
||||
ListRemove(a.freeChunksList, cast[PBigChunk](ri))
|
||||
listRemove(a.freeChunksList, cast[PBigChunk](ri))
|
||||
inc(c.size, ri.size)
|
||||
excl(a.chunkStarts, pageIndex(ri))
|
||||
when coalescLeft:
|
||||
|
|
@ -453,7 +454,7 @@ proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
|
|||
if isAccessible(a, le) and chunkUnused(le):
|
||||
sysAssert(not isSmallChunk(le), "freeBigChunk 5")
|
||||
if not isSmallChunk(le):
|
||||
ListRemove(a.freeChunksList, cast[PBigChunk](le))
|
||||
listRemove(a.freeChunksList, cast[PBigChunk](le))
|
||||
inc(le.size, c.size)
|
||||
excl(a.chunkStarts, pageIndex(c))
|
||||
c = cast[PBigChunk](le)
|
||||
|
|
@ -461,7 +462,7 @@ proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
|
|||
if c.size < ChunkOsReturn or weirdUnmap:
|
||||
incl(a, a.chunkStarts, pageIndex(c))
|
||||
updatePrevSize(a, c, c.size)
|
||||
ListAdd(a.freeChunksList, c)
|
||||
listAdd(a.freeChunksList, c)
|
||||
c.used = false
|
||||
else:
|
||||
freeOsChunks(a, c, c.size)
|
||||
|
|
@ -477,7 +478,7 @@ proc splitChunk(a: var TMemRegion, c: PBigChunk, size: int) =
|
|||
updatePrevSize(a, c, rest.size)
|
||||
c.size = size
|
||||
incl(a, a.chunkStarts, pageIndex(rest))
|
||||
ListAdd(a.freeChunksList, rest)
|
||||
listAdd(a.freeChunksList, rest)
|
||||
|
||||
proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
|
||||
# use first fit for now:
|
||||
|
|
@ -488,10 +489,10 @@ proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
|
|||
while result != nil:
|
||||
sysAssert chunkUnused(result), "getBigChunk 3"
|
||||
if result.size == size:
|
||||
ListRemove(a.freeChunksList, result)
|
||||
listRemove(a.freeChunksList, result)
|
||||
break search
|
||||
elif result.size > size:
|
||||
ListRemove(a.freeChunksList, result)
|
||||
listRemove(a.freeChunksList, result)
|
||||
splitChunk(a, result, size)
|
||||
break search
|
||||
result = result.next
|
||||
|
|
@ -530,7 +531,7 @@ proc allocInv(a: TMemRegion): bool =
|
|||
while it != nil:
|
||||
if it.zeroField != 0:
|
||||
echo "[SYSASSERT] it.zeroField != 0"
|
||||
cprintf("%ld %p\n", it.zeroField, it)
|
||||
c_printf("%ld %p\n", it.zeroField, it)
|
||||
return false
|
||||
it = it.next
|
||||
c = c.next
|
||||
|
|
@ -556,7 +557,7 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
|
|||
c.free = SmallChunkSize - smallChunkOverhead() - size
|
||||
c.next = nil
|
||||
c.prev = nil
|
||||
ListAdd(a.freeSmallChunks[s], c)
|
||||
listAdd(a.freeSmallChunks[s], c)
|
||||
result = addr(c.data)
|
||||
sysAssert((cast[TAddress](result) and (MemAlign-1)) == 0, "rawAlloc 4")
|
||||
else:
|
||||
|
|
@ -580,7 +581,7 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
|
|||
sysAssert(allocInv(a), "rawAlloc: before c.free < size")
|
||||
if c.free < size:
|
||||
sysAssert(allocInv(a), "rawAlloc: before listRemove test")
|
||||
ListRemove(a.freeSmallChunks[s], c)
|
||||
listRemove(a.freeSmallChunks[s], c)
|
||||
sysAssert(allocInv(a), "rawAlloc: end listRemove test")
|
||||
sysAssert(((cast[TAddress](result) and PageMask) - smallChunkOverhead()) %%
|
||||
size == 0, "rawAlloc 21")
|
||||
|
|
@ -627,12 +628,12 @@ proc rawDealloc(a: var TMemRegion, p: pointer) =
|
|||
# check if it is not in the freeSmallChunks[s] list:
|
||||
if c.free < s:
|
||||
# add it to the freeSmallChunks[s] array:
|
||||
ListAdd(a.freeSmallChunks[s div memAlign], c)
|
||||
listAdd(a.freeSmallChunks[s div MemAlign], c)
|
||||
inc(c.free, s)
|
||||
else:
|
||||
inc(c.free, s)
|
||||
if c.free == SmallChunkSize-smallChunkOverhead():
|
||||
ListRemove(a.freeSmallChunks[s div memAlign], c)
|
||||
listRemove(a.freeSmallChunks[s div MemAlign], c)
|
||||
c.size = SmallChunkSize
|
||||
freeBigChunk(a, cast[PBigChunk](c))
|
||||
sysAssert(((cast[TAddress](p) and PageMask) - smallChunkOverhead()) %%
|
||||
|
|
@ -738,7 +739,7 @@ proc realloc(allocator: var TMemRegion, p: pointer, newsize: int): pointer =
|
|||
proc deallocOsPages(a: var TMemRegion) =
|
||||
# we free every 'ordinarily' allocated page by iterating over the page bits:
|
||||
for p in elements(a.chunkStarts):
|
||||
var page = cast[PChunk](p shl pageShift)
|
||||
var page = cast[PChunk](p shl PageShift)
|
||||
when not weirdUnmap:
|
||||
var size = if page.size < PageSize: PageSize else: page.size
|
||||
osDeallocPages(page, size)
|
||||
|
|
@ -759,7 +760,7 @@ proc getOccupiedMem(a: TMemRegion): int {.inline.} =
|
|||
|
||||
# ---------------------- thread memory region -------------------------------
|
||||
|
||||
template InstantiateForRegion(allocator: expr) =
|
||||
template instantiateForRegion(allocator: expr) =
|
||||
when defined(fulldebug):
|
||||
proc interiorAllocatedPtr*(p: pointer): pointer =
|
||||
result = interiorAllocatedPtr(allocator, p)
|
||||
|
|
@ -801,13 +802,13 @@ template InstantiateForRegion(allocator: expr) =
|
|||
when hasThreadSupport:
|
||||
var sharedHeap: TMemRegion
|
||||
var heapLock: TSysLock
|
||||
InitSysLock(HeapLock)
|
||||
initSysLock(heapLock)
|
||||
|
||||
proc allocShared(size: int): pointer =
|
||||
when hasThreadSupport:
|
||||
AcquireSys(HeapLock)
|
||||
acquireSys(heapLock)
|
||||
result = alloc(sharedHeap, size)
|
||||
ReleaseSys(HeapLock)
|
||||
releaseSys(heapLock)
|
||||
else:
|
||||
result = alloc(size)
|
||||
|
||||
|
|
@ -817,17 +818,17 @@ template InstantiateForRegion(allocator: expr) =
|
|||
|
||||
proc deallocShared(p: pointer) =
|
||||
when hasThreadSupport:
|
||||
AcquireSys(HeapLock)
|
||||
acquireSys(heapLock)
|
||||
dealloc(sharedHeap, p)
|
||||
ReleaseSys(HeapLock)
|
||||
releaseSys(heapLock)
|
||||
else:
|
||||
dealloc(p)
|
||||
|
||||
proc reallocShared(p: pointer, newsize: int): pointer =
|
||||
when hasThreadSupport:
|
||||
AcquireSys(HeapLock)
|
||||
acquireSys(heapLock)
|
||||
result = realloc(sharedHeap, p, newsize)
|
||||
ReleaseSys(HeapLock)
|
||||
releaseSys(heapLock)
|
||||
else:
|
||||
result = realloc(p, newsize)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@
|
|||
|
||||
{.push hints:off}
|
||||
|
||||
proc c_strcmp(a, b: CString): cint {.header: "<string.h>",
|
||||
proc c_strcmp(a, b: cstring): cint {.header: "<string.h>",
|
||||
noSideEffect, importc: "strcmp".}
|
||||
proc c_memcmp(a, b: CString, size: int): cint {.header: "<string.h>",
|
||||
proc c_memcmp(a, b: cstring, size: int): cint {.header: "<string.h>",
|
||||
noSideEffect, importc: "memcmp".}
|
||||
proc c_memcpy(a, b: CString, size: int) {.header: "<string.h>", importc: "memcpy".}
|
||||
proc c_strlen(a: CString): int {.header: "<string.h>",
|
||||
proc c_memcpy(a, b: cstring, size: int) {.header: "<string.h>", importc: "memcpy".}
|
||||
proc c_strlen(a: cstring): int {.header: "<string.h>",
|
||||
noSideEffect, importc: "strlen".}
|
||||
proc c_memset(p: pointer, value: cint, size: int) {.
|
||||
header: "<string.h>", importc: "memset".}
|
||||
|
|
@ -28,8 +28,8 @@ type
|
|||
final, incompleteStruct.} = object
|
||||
C_BinaryFile {.importc: "FILE", header: "<stdio.h>",
|
||||
final, incompleteStruct.} = object
|
||||
C_TextFileStar = ptr CTextFile
|
||||
C_BinaryFileStar = ptr CBinaryFile
|
||||
C_TextFileStar = ptr C_TextFile
|
||||
C_BinaryFileStar = ptr C_BinaryFile
|
||||
|
||||
C_JmpBuf {.importc: "jmp_buf", header: "<setjmp.h>".} = object
|
||||
|
||||
|
|
@ -40,21 +40,40 @@ var
|
|||
|
||||
# constants faked as variables:
|
||||
when not defined(SIGINT):
|
||||
var
|
||||
SIGINT {.importc: "SIGINT", nodecl.}: cint
|
||||
SIGSEGV {.importc: "SIGSEGV", nodecl.}: cint
|
||||
SIGABRT {.importc: "SIGABRT", nodecl.}: cint
|
||||
SIGFPE {.importc: "SIGFPE", nodecl.}: cint
|
||||
SIGILL {.importc: "SIGILL", nodecl.}: cint
|
||||
when NoFakeVars:
|
||||
when defined(windows):
|
||||
const
|
||||
SIGABRT = cint(22)
|
||||
SIGFPE = cint(8)
|
||||
SIGILL = cint(4)
|
||||
SIGINT = cint(2)
|
||||
SIGSEGV = cint(11)
|
||||
SIGTERM = cint(15)
|
||||
elif defined(macosx) or defined(linux):
|
||||
const
|
||||
SIGABRT = cint(6)
|
||||
SIGFPE = cint(8)
|
||||
SIGILL = cint(4)
|
||||
SIGINT = cint(2)
|
||||
SIGSEGV = cint(11)
|
||||
SIGTERM = cint(15)
|
||||
else:
|
||||
{.error: "SIGABRT not ported to your platform".}
|
||||
else:
|
||||
var
|
||||
SIGINT {.importc: "SIGINT", nodecl.}: cint
|
||||
SIGSEGV {.importc: "SIGSEGV", nodecl.}: cint
|
||||
SIGABRT {.importc: "SIGABRT", nodecl.}: cint
|
||||
SIGFPE {.importc: "SIGFPE", nodecl.}: cint
|
||||
SIGILL {.importc: "SIGILL", nodecl.}: cint
|
||||
|
||||
when defined(macosx):
|
||||
var
|
||||
SIGBUS {.importc: "SIGBUS", nodecl.}: cint
|
||||
# hopefully this does not lead to new bugs
|
||||
when NoFakeVars:
|
||||
const SIGBUS = cint(10)
|
||||
else:
|
||||
var SIGBUS {.importc: "SIGBUS", nodecl.}: cint
|
||||
else:
|
||||
var
|
||||
SIGBUS {.importc: "SIGSEGV", nodecl.}: cint
|
||||
# only Mac OS X has this shit
|
||||
template SIGBUS: expr = SIGSEGV
|
||||
|
||||
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||
header: "<setjmp.h>", importc: "longjmp".}
|
||||
|
|
@ -73,27 +92,27 @@ proc c_fgetc(stream: C_TextFileStar): int {.importc: "fgetc",
|
|||
header: "<stdio.h>".}
|
||||
proc c_ungetc(c: int, f: C_TextFileStar) {.importc: "ungetc",
|
||||
header: "<stdio.h>".}
|
||||
proc c_putc(c: Char, stream: C_TextFileStar) {.importc: "putc",
|
||||
proc c_putc(c: char, stream: C_TextFileStar) {.importc: "putc",
|
||||
header: "<stdio.h>".}
|
||||
proc c_fprintf(f: C_TextFileStar, frmt: CString) {.
|
||||
proc c_fprintf(f: C_TextFileStar, frmt: cstring) {.
|
||||
importc: "fprintf", header: "<stdio.h>", varargs.}
|
||||
proc c_printf(frmt: CString) {.
|
||||
proc c_printf(frmt: cstring) {.
|
||||
importc: "printf", header: "<stdio.h>", varargs.}
|
||||
|
||||
proc c_fopen(filename, mode: cstring): C_TextFileStar {.
|
||||
importc: "fopen", header: "<stdio.h>".}
|
||||
proc c_fclose(f: C_TextFileStar) {.importc: "fclose", header: "<stdio.h>".}
|
||||
|
||||
proc c_sprintf(buf, frmt: CString) {.header: "<stdio.h>",
|
||||
proc c_sprintf(buf, frmt: cstring) {.header: "<stdio.h>",
|
||||
importc: "sprintf", varargs, noSideEffect.}
|
||||
# we use it only in a way that cannot lead to security issues
|
||||
|
||||
proc c_fread(buf: Pointer, size, n: int, f: C_BinaryFileStar): int {.
|
||||
proc c_fread(buf: pointer, size, n: int, f: C_BinaryFileStar): int {.
|
||||
importc: "fread", header: "<stdio.h>".}
|
||||
proc c_fseek(f: C_BinaryFileStar, offset: clong, whence: int): int {.
|
||||
importc: "fseek", header: "<stdio.h>".}
|
||||
|
||||
proc c_fwrite(buf: Pointer, size, n: int, f: C_BinaryFileStar): int {.
|
||||
proc c_fwrite(buf: pointer, size, n: int, f: C_BinaryFileStar): int {.
|
||||
importc: "fwrite", header: "<stdio.h>".}
|
||||
|
||||
proc c_exit(errorcode: cint) {.importc: "exit", header: "<stdlib.h>".}
|
||||
|
|
@ -111,16 +130,22 @@ proc c_realloc(p: pointer, newsize: int): pointer {.
|
|||
|
||||
when hostOS != "standalone":
|
||||
when not defined(errno):
|
||||
var errno {.importc, header: "<errno.h>".}: cint ## error variable
|
||||
when defined(NimrodVM):
|
||||
var vmErrnoWrapper {.importc.}: ptr cint
|
||||
template errno: expr =
|
||||
bind vmErrnoWrapper
|
||||
vmErrnoWrapper[]
|
||||
else:
|
||||
var errno {.importc, header: "<errno.h>".}: cint ## error variable
|
||||
proc strerror(errnum: cint): cstring {.importc, header: "<string.h>".}
|
||||
|
||||
proc c_remove(filename: CString): cint {.
|
||||
proc c_remove(filename: cstring): cint {.
|
||||
importc: "remove", header: "<stdio.h>".}
|
||||
proc c_rename(oldname, newname: CString): cint {.
|
||||
proc c_rename(oldname, newname: cstring): cint {.
|
||||
importc: "rename", header: "<stdio.h>".}
|
||||
|
||||
proc c_system(cmd: CString): cint {.importc: "system", header: "<stdlib.h>".}
|
||||
proc c_getenv(env: CString): CString {.importc: "getenv", header: "<stdlib.h>".}
|
||||
proc c_putenv(env: CString): cint {.importc: "putenv", header: "<stdlib.h>".}
|
||||
proc c_system(cmd: cstring): cint {.importc: "system", header: "<stdlib.h>".}
|
||||
proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
|
||||
proc c_putenv(env: cstring): cint {.importc: "putenv", header: "<stdlib.h>".}
|
||||
|
||||
{.pop}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@
|
|||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
proc genericResetAux(dest: Pointer, n: ptr TNimNode)
|
||||
proc genericResetAux(dest: pointer, n: ptr TNimNode)
|
||||
|
||||
proc genericAssignAux(dest, src: Pointer, mt: PNimType, shallow: bool)
|
||||
proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode, shallow: bool) =
|
||||
proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool)
|
||||
proc genericAssignAux(dest, src: pointer, n: ptr TNimNode, shallow: bool) =
|
||||
var
|
||||
d = cast[TAddress](dest)
|
||||
s = cast[TAddress](src)
|
||||
|
|
@ -37,37 +37,37 @@ proc genericAssignAux(dest, src: Pointer, n: ptr TNimNode, shallow: bool) =
|
|||
# echo "ugh memory corruption! ", n.kind
|
||||
# quit 1
|
||||
|
||||
proc genericAssignAux(dest, src: Pointer, mt: PNimType, shallow: bool) =
|
||||
proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
|
||||
var
|
||||
d = cast[TAddress](dest)
|
||||
s = cast[TAddress](src)
|
||||
sysAssert(mt != nil, "genericAssignAux 2")
|
||||
case mt.Kind
|
||||
case mt.kind
|
||||
of tyString:
|
||||
var x = cast[ppointer](dest)
|
||||
var s2 = cast[ppointer](s)[]
|
||||
var x = cast[PPointer](dest)
|
||||
var s2 = cast[PPointer](s)[]
|
||||
if s2 == nil or shallow or (
|
||||
cast[PGenericSeq](s2).reserved and seqShallowFlag) != 0:
|
||||
unsureAsgnRef(x, s2)
|
||||
else:
|
||||
unsureAsgnRef(x, copyString(cast[NimString](s2)))
|
||||
of tySequence:
|
||||
var s2 = cast[ppointer](src)[]
|
||||
var s2 = cast[PPointer](src)[]
|
||||
var seq = cast[PGenericSeq](s2)
|
||||
var x = cast[ppointer](dest)
|
||||
var x = cast[PPointer](dest)
|
||||
if s2 == nil or shallow or (seq.reserved and seqShallowFlag) != 0:
|
||||
# this can happen! nil sequences are allowed
|
||||
unsureAsgnRef(x, s2)
|
||||
return
|
||||
sysAssert(dest != nil, "genericAssignAux 3")
|
||||
unsureAsgnRef(x, newSeq(mt, seq.len))
|
||||
var dst = cast[taddress](cast[ppointer](dest)[])
|
||||
var dst = cast[TAddress](cast[PPointer](dest)[])
|
||||
for i in 0..seq.len-1:
|
||||
genericAssignAux(
|
||||
cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
|
||||
cast[pointer](cast[taddress](s2) +% i *% mt.base.size +%
|
||||
cast[pointer](cast[TAddress](s2) +% i *% mt.base.size +%
|
||||
GenericSeqSize),
|
||||
mt.Base, shallow)
|
||||
mt.base, shallow)
|
||||
of tyObject:
|
||||
# we need to copy m_type field for tyObject, as it could be empty for
|
||||
# sequence reallocations:
|
||||
|
|
@ -83,16 +83,16 @@ proc genericAssignAux(dest, src: Pointer, mt: PNimType, shallow: bool) =
|
|||
genericAssignAux(cast[pointer](d +% i*% mt.base.size),
|
||||
cast[pointer](s +% i*% mt.base.size), mt.base, shallow)
|
||||
of tyRef:
|
||||
unsureAsgnRef(cast[ppointer](dest), cast[ppointer](s)[])
|
||||
unsureAsgnRef(cast[PPointer](dest), cast[PPointer](s)[])
|
||||
else:
|
||||
copyMem(dest, src, mt.size) # copy raw bits
|
||||
|
||||
proc genericAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
|
||||
proc genericAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} =
|
||||
GC_disable()
|
||||
genericAssignAux(dest, src, mt, false)
|
||||
GC_enable()
|
||||
|
||||
proc genericShallowAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
|
||||
proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} =
|
||||
GC_disable()
|
||||
genericAssignAux(dest, src, mt, true)
|
||||
GC_enable()
|
||||
|
|
@ -126,7 +126,7 @@ when false:
|
|||
cprintf("%s %ld\n", k, t.size)
|
||||
debugNimType(t.base)
|
||||
|
||||
proc genericSeqAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
|
||||
proc genericSeqAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} =
|
||||
var src = src # ugly, but I like to stress the parser sometimes :-)
|
||||
genericAssign(dest, addr(src), mt)
|
||||
|
||||
|
|
@ -139,12 +139,12 @@ proc genericAssignOpenArray(dest, src: pointer, len: int,
|
|||
genericAssign(cast[pointer](d +% i*% mt.base.size),
|
||||
cast[pointer](s +% i*% mt.base.size), mt.base)
|
||||
|
||||
proc objectInit(dest: Pointer, typ: PNimType) {.compilerProc.}
|
||||
proc objectInitAux(dest: Pointer, n: ptr TNimNode) =
|
||||
proc objectInit(dest: pointer, typ: PNimType) {.compilerProc.}
|
||||
proc objectInitAux(dest: pointer, n: ptr TNimNode) =
|
||||
var d = cast[TAddress](dest)
|
||||
case n.kind
|
||||
of nkNone: sysAssert(false, "objectInitAux")
|
||||
of nkSLot: objectInit(cast[pointer](d +% n.offset), n.typ)
|
||||
of nkSlot: objectInit(cast[pointer](d +% n.offset), n.typ)
|
||||
of nkList:
|
||||
for i in 0..n.len-1:
|
||||
objectInitAux(dest, n.sons[i])
|
||||
|
|
@ -152,7 +152,7 @@ proc objectInitAux(dest: Pointer, n: ptr TNimNode) =
|
|||
var m = selectBranch(dest, n)
|
||||
if m != nil: objectInitAux(dest, m)
|
||||
|
||||
proc objectInit(dest: Pointer, typ: PNimType) =
|
||||
proc objectInit(dest: pointer, typ: PNimType) =
|
||||
# the generic init proc that takes care of initialization of complex
|
||||
# objects on the stack or heap
|
||||
var d = cast[TAddress](dest)
|
||||
|
|
@ -168,12 +168,12 @@ proc objectInit(dest: Pointer, typ: PNimType) =
|
|||
of tyArray, tyArrayConstr:
|
||||
for i in 0..(typ.size div typ.base.size)-1:
|
||||
objectInit(cast[pointer](d +% i * typ.base.size), typ.base)
|
||||
else: nil # nothing to do
|
||||
else: discard # nothing to do
|
||||
|
||||
# ---------------------- assign zero -----------------------------------------
|
||||
|
||||
when not defined(nimmixin):
|
||||
proc destroy(x: int) = nil
|
||||
proc destroy(x: int) = discard
|
||||
proc nimDestroyRange*[T](r: T) =
|
||||
# internal proc used for destroying sequences and arrays
|
||||
for i in countup(0, r.len - 1): destroy(r[i])
|
||||
|
|
@ -184,8 +184,8 @@ else:
|
|||
mixin destroy
|
||||
for i in countup(0, r.len - 1): destroy(r[i])
|
||||
|
||||
proc genericReset(dest: Pointer, mt: PNimType) {.compilerProc.}
|
||||
proc genericResetAux(dest: Pointer, n: ptr TNimNode) =
|
||||
proc genericReset(dest: pointer, mt: PNimType) {.compilerProc.}
|
||||
proc genericResetAux(dest: pointer, n: ptr TNimNode) =
|
||||
var d = cast[TAddress](dest)
|
||||
case n.kind
|
||||
of nkNone: sysAssert(false, "genericResetAux")
|
||||
|
|
@ -197,12 +197,12 @@ proc genericResetAux(dest: Pointer, n: ptr TNimNode) =
|
|||
if m != nil: genericResetAux(dest, m)
|
||||
zeroMem(cast[pointer](d +% n.offset), n.typ.size)
|
||||
|
||||
proc genericReset(dest: Pointer, mt: PNimType) =
|
||||
proc genericReset(dest: pointer, mt: PNimType) =
|
||||
var d = cast[TAddress](dest)
|
||||
sysAssert(mt != nil, "genericReset 2")
|
||||
case mt.Kind
|
||||
case mt.kind
|
||||
of tyString, tyRef, tySequence:
|
||||
unsureAsgnRef(cast[ppointer](dest), nil)
|
||||
unsureAsgnRef(cast[PPointer](dest), nil)
|
||||
of tyObject, tyTuple:
|
||||
# we don't need to reset m_type field for tyObject
|
||||
genericResetAux(dest, mt.node)
|
||||
|
|
|
|||
|
|
@ -7,62 +7,60 @@
|
|||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# Atomic operations for Nimrod.
|
||||
## Atomic operations for Nimrod.
|
||||
|
||||
when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
|
||||
|
||||
when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
|
||||
type
|
||||
AtomMemModel* = enum
|
||||
ATOMIC_RELAXED,
|
||||
## No barriers or synchronization.
|
||||
ATOMIC_CONSUME,
|
||||
## Data dependency only for both barrier and synchronization with another thread.
|
||||
ATOMIC_ACQUIRE,
|
||||
## Barrier to hoisting of code and synchronizes with release (or stronger)
|
||||
## semantic stores from another thread.
|
||||
ATOMIC_RELEASE,
|
||||
## Barrier to sinking of code and synchronizes with acquire (or stronger)
|
||||
## semantic loads from another thread.
|
||||
ATOMIC_ACQ_REL,
|
||||
## Full barrier in both directions and synchronizes with acquire loads
|
||||
## and release stores in another thread.
|
||||
ATOMIC_SEQ_CST
|
||||
## Full barrier in both directions and synchronizes with acquire loads
|
||||
## and release stores in all threads.
|
||||
ATOMIC_RELAXED, ## No barriers or synchronization.
|
||||
ATOMIC_CONSUME, ## Data dependency only for both barrier and
|
||||
## synchronization with another thread.
|
||||
ATOMIC_ACQUIRE, ## Barrier to hoisting of code and synchronizes with
|
||||
## release (or stronger)
|
||||
## semantic stores from another thread.
|
||||
ATOMIC_RELEASE, ## Barrier to sinking of code and synchronizes with
|
||||
## acquire (or stronger)
|
||||
## semantic loads from another thread.
|
||||
ATOMIC_ACQ_REL, ## Full barrier in both directions and synchronizes
|
||||
## with acquire loads
|
||||
## and release stores in another thread.
|
||||
ATOMIC_SEQ_CST ## Full barrier in both directions and synchronizes
|
||||
## with acquire loads
|
||||
## and release stores in all threads.
|
||||
|
||||
TAtomType* = TNumber|pointer|ptr|char
|
||||
## Type Class representing valid types for use with atomic procs
|
||||
## Type Class representing valid types for use with atomic procs
|
||||
|
||||
proc atomic_load_n*[T: TAtomType](p: ptr T, mem: AtomMemModel): T {.
|
||||
proc atomicLoadN*[T: TAtomType](p: ptr T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_load_n", nodecl.}
|
||||
## This proc implements an atomic load operation. It returns the contents at p.
|
||||
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_CONSUME.
|
||||
|
||||
proc atomic_load*[T: TAtomType](p: ptr T, ret: ptr T, mem: AtomMemModel) {.
|
||||
proc atomicLoad*[T: TAtomType](p, ret: ptr T, mem: AtomMemModel) {.
|
||||
importc: "__atomic_load", nodecl.}
|
||||
## This is the generic version of an atomic load. It returns the contents at p in ret.
|
||||
|
||||
proc atomic_store_n*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel) {.
|
||||
proc atomicStoreN*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel) {.
|
||||
importc: "__atomic_store_n", nodecl.}
|
||||
## This proc implements an atomic store operation. It writes val at p.
|
||||
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, and ATOMIC_RELEASE.
|
||||
|
||||
proc atomic_store*[T: TAtomType](p: ptr T, val: ptr T, mem: AtomMemModel) {.
|
||||
proc atomicStore*[T: TAtomType](p, val: ptr T, mem: AtomMemModel) {.
|
||||
importc: "__atomic_store", nodecl.}
|
||||
## This is the generic version of an atomic store. It stores the value of val at p
|
||||
|
||||
proc atomic_exchange_n*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
proc atomicExchangeN*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_exchange_n", nodecl.}
|
||||
## This proc implements an atomic exchange operation. It writes val at p,
|
||||
## and returns the previous contents at p.
|
||||
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_RELEASE, ATOMIC_ACQ_REL
|
||||
|
||||
proc atomic_exchange*[T: TAtomType](p: ptr T, val: ptr T, ret: ptr T, mem: AtomMemModel) {.
|
||||
proc atomicExchange*[T: TAtomType](p, val, ret: ptr T, mem: AtomMemModel) {.
|
||||
importc: "__atomic_exchange", nodecl.}
|
||||
## This is the generic version of an atomic exchange. It stores the contents at val at p.
|
||||
## The original value at p is copied into ret.
|
||||
|
||||
proc atomic_compare_exchange_n*[T: TAtomType](p: ptr T, expected: ptr T, desired: T,
|
||||
proc atomicCompareExchangeN*[T: TAtomType](p, expected: ptr T, desired: T,
|
||||
weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
|
||||
importc: "__atomic_compare_exchange_n ", nodecl.}
|
||||
## This proc implements an atomic compare and exchange operation. This compares the
|
||||
|
|
@ -78,7 +76,7 @@ when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
|
|||
## cannot be __ATOMIC_RELEASE nor __ATOMIC_ACQ_REL. It also cannot be a stronger model
|
||||
## than that specified by success_memmodel.
|
||||
|
||||
proc atomic_compare_exchange*[T: TAtomType](p: ptr T, expected: ptr T, desired: ptr T,
|
||||
proc atomicCompareExchange*[T: TAtomType](p, expected, desired: ptr T,
|
||||
weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
|
||||
importc: "__atomic_compare_exchange_n ", nodecl.}
|
||||
## This proc implements the generic version of atomic_compare_exchange.
|
||||
|
|
@ -86,58 +84,58 @@ when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
|
|||
## value is also a pointer.
|
||||
|
||||
## Perform the operation return the new value, all memory models are valid
|
||||
proc atomic_add_fetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
proc atomicAddFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_add_fetch", nodecl.}
|
||||
proc atomic_sub_fetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
proc atomicSubFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_sub_fetch", nodecl.}
|
||||
proc atomic_or_fetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
proc atomicOrFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_or_fetch ", nodecl.}
|
||||
proc atomic_and_fetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
proc atomicAndFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_and_fetch", nodecl.}
|
||||
proc atomic_xor_fetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
proc atomicXorFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_xor_fetch", nodecl.}
|
||||
proc atomic_nand_fetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
proc atomicNandFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_nand_fetch ", nodecl.}
|
||||
|
||||
## Perform the operation return the old value, all memory models are valid
|
||||
proc atomic_fetch_add*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_fetch_add ", nodecl.}
|
||||
proc atomic_fetch_sub*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_fetch_sub ", nodecl.}
|
||||
proc atomic_fetch_or*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_fetch_or ", nodecl.}
|
||||
proc atomic_fetch_and*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_fetch_and ", nodecl.}
|
||||
proc atomic_fetch_xor*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_fetch_xor ", nodecl.}
|
||||
proc atomic_fetch_nand*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
proc atomicFetchAdd*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_fetch_add", nodecl.}
|
||||
proc atomicFetchSub*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_fetch_sub", nodecl.}
|
||||
proc atomicFetchOr*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_fetch_or", nodecl.}
|
||||
proc atomicFetchAnd*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_fetch_and", nodecl.}
|
||||
proc atomicFetchXor*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_fetch_xor", nodecl.}
|
||||
proc atomicFetchNand*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
|
||||
importc: "__atomic_fetch_nand", nodecl.}
|
||||
|
||||
proc atomic_test_and_set*(p: pointer, mem: AtomMemModel): bool {.
|
||||
importc: "__atomic_test_and_set ", nodecl.}
|
||||
proc atomicTestAndSet*(p: pointer, mem: AtomMemModel): bool {.
|
||||
importc: "__atomic_test_and_set", nodecl.}
|
||||
## This built-in function performs an atomic test-and-set operation on the byte at p.
|
||||
## The byte is set to some implementation defined nonzero “set” value and the return
|
||||
## value is true if and only if the previous contents were “set”.
|
||||
## All memory models are valid.
|
||||
|
||||
proc atomic_clear*(p: pointer, mem: AtomMemModel) {.
|
||||
proc atomicClear*(p: pointer, mem: AtomMemModel) {.
|
||||
importc: "__atomic_clear", nodecl.}
|
||||
## This built-in function performs an atomic clear operation at p.
|
||||
## After the operation, at p contains 0.
|
||||
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_RELEASE
|
||||
|
||||
proc atomic_thread_fence*(mem: AtomMemModel) {.
|
||||
importc: "__atomic_thread_fence ", nodecl.}
|
||||
proc atomicThreadFence*(mem: AtomMemModel) {.
|
||||
importc: "__atomic_thread_fence", nodecl.}
|
||||
## This built-in function acts as a synchronization fence between threads based
|
||||
## on the specified memory model. All memory orders are valid.
|
||||
|
||||
proc atomic_signal_fence*(mem: AtomMemModel) {.
|
||||
importc: "__atomic_signal_fence ", nodecl.}
|
||||
proc atomicSignalFence*(mem: AtomMemModel) {.
|
||||
importc: "__atomic_signal_fence", nodecl.}
|
||||
## This built-in function acts as a synchronization fence between a thread and
|
||||
## signal handlers based in the same thread. All memory orders are valid.
|
||||
|
||||
proc atomic_always_lock_free*(size: int, p: pointer): bool {.
|
||||
importc: "__atomic_always_lock_free ", nodecl.}
|
||||
proc atomicAlwaysLockFree*(size: int, p: pointer): bool {.
|
||||
importc: "__atomic_always_lock_free", nodecl.}
|
||||
## This built-in function returns true if objects of size bytes always generate
|
||||
## lock free atomic instructions for the target architecture. size must resolve
|
||||
## to a compile-time constant and the result also resolves to a compile-time constant.
|
||||
|
|
@ -145,8 +143,8 @@ when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
|
|||
## A value of 0 indicates typical alignment should be used. The compiler may also
|
||||
## ignore this parameter.
|
||||
|
||||
proc atomic_is_lock_free*(size: int, p: pointer): bool {.
|
||||
importc: "__atomic_is_lock_free ", nodecl.}
|
||||
proc atomicIsLockFree*(size: int, p: pointer): bool {.
|
||||
importc: "__atomic_is_lock_free", nodecl.}
|
||||
## This built-in function returns true if objects of size bytes always generate
|
||||
## lock free atomic instructions for the target architecture. If it is not known
|
||||
## to be lock free a call is made to a runtime routine named __atomic_is_lock_free.
|
||||
|
|
@ -154,19 +152,14 @@ when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
|
|||
## A value of 0 indicates typical alignment should be used. The compiler may also
|
||||
## ignore this parameter.
|
||||
|
||||
|
||||
|
||||
elif defined(vcc) and hasThreadSupport:
|
||||
proc add_and_fetch*(p: ptr int, val: int): int {.
|
||||
proc addAndFetch*(p: ptr int, val: int): int {.
|
||||
importc: "NimXadd", nodecl.}
|
||||
else:
|
||||
proc add_and_fetch*(p: ptr int, val: int): int {.inline.} =
|
||||
proc addAndFetch*(p: ptr int, val: int): int {.inline.} =
|
||||
inc(p[], val)
|
||||
result = p[]
|
||||
|
||||
|
||||
|
||||
|
||||
# atomic compare and swap (CAS) funcitons to implement lock-free algorithms
|
||||
|
||||
#if defined(windows) and not defined(gcc) and hasThreadSupport:
|
||||
|
|
@ -183,7 +176,7 @@ else:
|
|||
|
||||
#elif not hasThreadSupport:
|
||||
# proc compareAndSwap*[T](mem: ptr T,
|
||||
# expected: T, newValue: T): bool {.inline.} =
|
||||
# expected: T, newValue: T): bool {.inline.} =
|
||||
# ## Returns true if successfully set value at mem to newValue when value
|
||||
# ## at mem == expected
|
||||
# var oldval = mem[]
|
||||
|
|
@ -209,7 +202,4 @@ proc atomicDec*(memLoc: var int, x: int = 1): int =
|
|||
result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED)
|
||||
else:
|
||||
dec(memLoc, x)
|
||||
result = memLoc
|
||||
|
||||
|
||||
|
||||
result = memLoc
|
||||
|
|
|
|||
|
|
@ -9,30 +9,30 @@
|
|||
|
||||
# not really an AVL tree anymore, but still balanced ...
|
||||
|
||||
template IsBottom(n: PAvlNode): bool = n == bottom
|
||||
template isBottom(n: PAvlNode): bool = n == bottom
|
||||
|
||||
proc lowGauge(n: PAvlNode): int =
|
||||
var it = n
|
||||
while not IsBottom(it):
|
||||
while not isBottom(it):
|
||||
result = it.key
|
||||
it = it.link[0]
|
||||
|
||||
proc highGauge(n: PAvlNode): int =
|
||||
result = -1
|
||||
var it = n
|
||||
while not IsBottom(it):
|
||||
while not isBottom(it):
|
||||
result = it.upperBound
|
||||
it = it.link[1]
|
||||
|
||||
proc find(root: PAvlNode, key: int): PAvlNode =
|
||||
var it = root
|
||||
while not IsBottom(it):
|
||||
while not isBottom(it):
|
||||
if it.key == key: return it
|
||||
it = it.link[ord(it.key <% key)]
|
||||
|
||||
proc inRange(root: PAvlNode, key: int): PAvlNode =
|
||||
var it = root
|
||||
while not IsBottom(it):
|
||||
while not isBottom(it):
|
||||
if it.key <=% key and key <% it.upperBound: return it
|
||||
it = it.link[ord(it.key <% key)]
|
||||
|
||||
|
|
|
|||
|
|
@ -43,15 +43,15 @@ type
|
|||
|
||||
proc contains(s: TCellSeq, c: PCell): bool {.inline.} =
|
||||
for i in 0 .. s.len-1:
|
||||
if s.d[i] == c: return True
|
||||
return False
|
||||
if s.d[i] == c: return true
|
||||
return false
|
||||
|
||||
proc add(s: var TCellSeq, c: PCell) {.inline.} =
|
||||
if s.len >= s.cap:
|
||||
s.cap = s.cap * 3 div 2
|
||||
var d = cast[PCellArray](Alloc(s.cap * sizeof(PCell)))
|
||||
var d = cast[PCellArray](alloc(s.cap * sizeof(PCell)))
|
||||
copyMem(d, s.d, s.len * sizeof(PCell))
|
||||
Dealloc(s.d)
|
||||
dealloc(s.d)
|
||||
s.d = d
|
||||
# XXX: realloc?
|
||||
s.d[s.len] = c
|
||||
|
|
@ -60,10 +60,10 @@ proc add(s: var TCellSeq, c: PCell) {.inline.} =
|
|||
proc init(s: var TCellSeq, cap: int = 1024) =
|
||||
s.len = 0
|
||||
s.cap = cap
|
||||
s.d = cast[PCellArray](Alloc0(cap * sizeof(PCell)))
|
||||
s.d = cast[PCellArray](alloc0(cap * sizeof(PCell)))
|
||||
|
||||
proc deinit(s: var TCellSeq) =
|
||||
Dealloc(s.d)
|
||||
dealloc(s.d)
|
||||
s.d = nil
|
||||
s.len = 0
|
||||
s.cap = 0
|
||||
|
|
@ -73,20 +73,20 @@ proc deinit(s: var TCellSeq) =
|
|||
const
|
||||
InitCellSetSize = 1024 # must be a power of two!
|
||||
|
||||
proc Init(s: var TCellSet) =
|
||||
s.data = cast[PPageDescArray](Alloc0(InitCellSetSize * sizeof(PPageDesc)))
|
||||
proc init(s: var TCellSet) =
|
||||
s.data = cast[PPageDescArray](alloc0(InitCellSetSize * sizeof(PPageDesc)))
|
||||
s.max = InitCellSetSize-1
|
||||
s.counter = 0
|
||||
s.head = nil
|
||||
|
||||
proc Deinit(s: var TCellSet) =
|
||||
proc deinit(s: var TCellSet) =
|
||||
var it = s.head
|
||||
while it != nil:
|
||||
var n = it.next
|
||||
Dealloc(it)
|
||||
dealloc(it)
|
||||
it = n
|
||||
s.head = nil # play it safe here
|
||||
Dealloc(s.data)
|
||||
dealloc(s.data)
|
||||
s.data = nil
|
||||
s.counter = 0
|
||||
|
||||
|
|
@ -96,14 +96,14 @@ proc nextTry(h, maxHash: int): int {.inline.} =
|
|||
# generates each int in range(maxHash) exactly once (see any text on
|
||||
# random-number generation for proof).
|
||||
|
||||
proc CellSetGet(t: TCellSet, key: TAddress): PPageDesc =
|
||||
proc cellSetGet(t: TCellSet, key: TAddress): PPageDesc =
|
||||
var h = cast[int](key) and t.max
|
||||
while t.data[h] != nil:
|
||||
if t.data[h].key == key: return t.data[h]
|
||||
h = nextTry(h, t.max)
|
||||
return nil
|
||||
|
||||
proc CellSetRawInsert(t: TCellSet, data: PPageDescArray, desc: PPageDesc) =
|
||||
proc cellSetRawInsert(t: TCellSet, data: PPageDescArray, desc: PPageDesc) =
|
||||
var h = cast[int](desc.key) and t.max
|
||||
while data[h] != nil:
|
||||
sysAssert(data[h] != desc, "CellSetRawInsert 1")
|
||||
|
|
@ -111,17 +111,17 @@ proc CellSetRawInsert(t: TCellSet, data: PPageDescArray, desc: PPageDesc) =
|
|||
sysAssert(data[h] == nil, "CellSetRawInsert 2")
|
||||
data[h] = desc
|
||||
|
||||
proc CellSetEnlarge(t: var TCellSet) =
|
||||
proc cellSetEnlarge(t: var TCellSet) =
|
||||
var oldMax = t.max
|
||||
t.max = ((t.max+1)*2)-1
|
||||
var n = cast[PPageDescArray](Alloc0((t.max + 1) * sizeof(PPageDesc)))
|
||||
for i in 0 .. oldmax:
|
||||
var n = cast[PPageDescArray](alloc0((t.max + 1) * sizeof(PPageDesc)))
|
||||
for i in 0 .. oldMax:
|
||||
if t.data[i] != nil:
|
||||
CellSetRawInsert(t, n, t.data[i])
|
||||
Dealloc(t.data)
|
||||
cellSetRawInsert(t, n, t.data[i])
|
||||
dealloc(t.data)
|
||||
t.data = n
|
||||
|
||||
proc CellSetPut(t: var TCellSet, key: TAddress): PPageDesc =
|
||||
proc cellSetPut(t: var TCellSet, key: TAddress): PPageDesc =
|
||||
var h = cast[int](key) and t.max
|
||||
while true:
|
||||
var x = t.data[h]
|
||||
|
|
@ -130,13 +130,13 @@ proc CellSetPut(t: var TCellSet, key: TAddress): PPageDesc =
|
|||
h = nextTry(h, t.max)
|
||||
|
||||
if ((t.max+1)*2 < t.counter*3) or ((t.max+1)-t.counter < 4):
|
||||
CellSetEnlarge(t)
|
||||
cellSetEnlarge(t)
|
||||
inc(t.counter)
|
||||
h = cast[int](key) and t.max
|
||||
while t.data[h] != nil: h = nextTry(h, t.max)
|
||||
sysAssert(t.data[h] == nil, "CellSetPut")
|
||||
# the new page descriptor goes into result
|
||||
result = cast[PPageDesc](Alloc0(sizeof(TPageDesc)))
|
||||
result = cast[PPageDesc](alloc0(sizeof(TPageDesc)))
|
||||
result.next = t.head
|
||||
result.key = key
|
||||
t.head = result
|
||||
|
|
@ -146,7 +146,7 @@ proc CellSetPut(t: var TCellSet, key: TAddress): PPageDesc =
|
|||
|
||||
proc contains(s: TCellSet, cell: PCell): bool =
|
||||
var u = cast[TAddress](cell)
|
||||
var t = CellSetGet(s, u shr PageShift)
|
||||
var t = cellSetGet(s, u shr PageShift)
|
||||
if t != nil:
|
||||
u = (u %% PageSize) /% MemAlign
|
||||
result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0
|
||||
|
|
@ -155,13 +155,13 @@ proc contains(s: TCellSet, cell: PCell): bool =
|
|||
|
||||
proc incl(s: var TCellSet, cell: PCell) {.noinline.} =
|
||||
var u = cast[TAddress](cell)
|
||||
var t = CellSetPut(s, u shr PageShift)
|
||||
var t = cellSetPut(s, u shr PageShift)
|
||||
u = (u %% PageSize) /% MemAlign
|
||||
t.bits[u shr IntShift] = t.bits[u shr IntShift] or (1 shl (u and IntMask))
|
||||
|
||||
proc excl(s: var TCellSet, cell: PCell) =
|
||||
var u = cast[TAddress](cell)
|
||||
var t = CellSetGet(s, u shr PageShift)
|
||||
var t = cellSetGet(s, u shr PageShift)
|
||||
if t != nil:
|
||||
u = (u %% PageSize) /% MemAlign
|
||||
t.bits[u shr IntShift] = (t.bits[u shr IntShift] and
|
||||
|
|
@ -169,7 +169,7 @@ proc excl(s: var TCellSet, cell: PCell) =
|
|||
|
||||
proc containsOrIncl(s: var TCellSet, cell: PCell): bool =
|
||||
var u = cast[TAddress](cell)
|
||||
var t = CellSetGet(s, u shr PageShift)
|
||||
var t = cellSetGet(s, u shr PageShift)
|
||||
if t != nil:
|
||||
u = (u %% PageSize) /% MemAlign
|
||||
result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0
|
||||
|
|
@ -177,7 +177,7 @@ proc containsOrIncl(s: var TCellSet, cell: PCell): bool =
|
|||
t.bits[u shr IntShift] = t.bits[u shr IntShift] or
|
||||
(1 shl (u and IntMask))
|
||||
else:
|
||||
Incl(s, cell)
|
||||
incl(s, cell)
|
||||
result = false
|
||||
|
||||
iterator elements(t: TCellSet): PCell {.inline.} =
|
||||
|
|
@ -201,7 +201,7 @@ iterator elements(t: TCellSet): PCell {.inline.} =
|
|||
iterator elementsExcept(t, s: TCellSet): PCell {.inline.} =
|
||||
var r = t.head
|
||||
while r != nil:
|
||||
let ss = CellSetGet(s, r.key)
|
||||
let ss = cellSetGet(s, r.key)
|
||||
var i = 0
|
||||
while i <= high(r.bits):
|
||||
var w = r.bits[i]
|
||||
|
|
|
|||
|
|
@ -48,9 +48,9 @@ proc deinitRawChannel(p: pointer) =
|
|||
deinitSys(c.lock)
|
||||
deinitSysCond(c.cond)
|
||||
|
||||
proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
|
||||
proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
|
||||
mode: TLoadStoreMode)
|
||||
proc storeAux(dest, src: Pointer, n: ptr TNimNode, t: PRawChannel,
|
||||
proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel,
|
||||
mode: TLoadStoreMode) =
|
||||
var
|
||||
d = cast[TAddress](dest)
|
||||
|
|
@ -67,7 +67,7 @@ proc storeAux(dest, src: Pointer, n: ptr TNimNode, t: PRawChannel,
|
|||
if m != nil: storeAux(dest, src, m, t, mode)
|
||||
of nkNone: sysAssert(false, "storeAux")
|
||||
|
||||
proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
|
||||
proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
|
||||
mode: TLoadStoreMode) =
|
||||
var
|
||||
d = cast[TAddress](dest)
|
||||
|
|
@ -82,7 +82,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
|
|||
x[] = nil
|
||||
else:
|
||||
var ss = cast[NimString](s2)
|
||||
var ns = cast[NimString](Alloc(t.region, ss.len+1 + GenericSeqSize))
|
||||
var ns = cast[NimString](alloc(t.region, ss.len+1 + GenericSeqSize))
|
||||
copyMem(ns, ss, ss.len+1 + GenericSeqSize)
|
||||
x[] = ns
|
||||
else:
|
||||
|
|
@ -92,7 +92,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
|
|||
unsureAsgnRef(x, s2)
|
||||
else:
|
||||
unsureAsgnRef(x, copyString(cast[NimString](s2)))
|
||||
Dealloc(t.region, s2)
|
||||
dealloc(t.region, s2)
|
||||
of tySequence:
|
||||
var s2 = cast[ppointer](src)[]
|
||||
var seq = cast[PGenericSeq](s2)
|
||||
|
|
@ -105,7 +105,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
|
|||
else:
|
||||
sysAssert(dest != nil, "dest == nil")
|
||||
if mode == mStore:
|
||||
x[] = Alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize)
|
||||
x[] = alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize)
|
||||
else:
|
||||
unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize))
|
||||
var dst = cast[taddress](cast[ppointer](dest)[])
|
||||
|
|
@ -118,7 +118,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
|
|||
var dstseq = cast[PGenericSeq](dst)
|
||||
dstseq.len = seq.len
|
||||
dstseq.reserved = seq.len
|
||||
if mode != mStore: Dealloc(t.region, s2)
|
||||
if mode != mStore: dealloc(t.region, s2)
|
||||
of tyObject:
|
||||
# copy type field:
|
||||
var pint = cast[ptr PNimType](dest)
|
||||
|
|
@ -143,7 +143,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
|
|||
unsureAsgnRef(x, nil)
|
||||
else:
|
||||
if mode == mStore:
|
||||
x[] = Alloc(t.region, mt.base.size)
|
||||
x[] = alloc(t.region, mt.base.size)
|
||||
else:
|
||||
# XXX we should use the dynamic type here too, but that is not stored
|
||||
# in the inbox at all --> use source[]'s object type? but how? we need
|
||||
|
|
@ -151,7 +151,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
|
|||
var obj = newObj(mt, mt.base.size)
|
||||
unsureAsgnRef(x, obj)
|
||||
storeAux(x[], s, mt.base, t, mode)
|
||||
if mode != mStore: Dealloc(t.region, s)
|
||||
if mode != mStore: dealloc(t.region, s)
|
||||
else:
|
||||
copyMem(dest, src, mt.size) # copy raw bits
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ proc rawSend(q: PRawChannel, data: pointer, typ: PNimType) =
|
|||
if q.count >= cap:
|
||||
# start with capacity for 2 entries in the queue:
|
||||
if cap == 0: cap = 1
|
||||
var n = cast[pbytes](Alloc0(q.region, cap*2*typ.size))
|
||||
var n = cast[pbytes](alloc0(q.region, cap*2*typ.size))
|
||||
var z = 0
|
||||
var i = q.rd
|
||||
var c = q.count
|
||||
|
|
@ -170,7 +170,7 @@ proc rawSend(q: PRawChannel, data: pointer, typ: PNimType) =
|
|||
copyMem(addr(n[z*typ.size]), addr(q.data[i*typ.size]), typ.size)
|
||||
i = (i + 1) and q.mask
|
||||
inc z
|
||||
if q.data != nil: Dealloc(q.region, q.data)
|
||||
if q.data != nil: dealloc(q.region, q.data)
|
||||
q.data = n
|
||||
q.mask = cap*2 - 1
|
||||
q.wr = q.count
|
||||
|
|
@ -200,7 +200,7 @@ template sendImpl(q: expr) {.immediate.} =
|
|||
rawSend(q, addr(m), typ)
|
||||
q.elemType = typ
|
||||
releaseSys(q.lock)
|
||||
SignalSysCond(q.cond)
|
||||
signalSysCond(q.cond)
|
||||
|
||||
proc send*[TMsg](c: var TChannel[TMsg], msg: TMsg) =
|
||||
## sends a message to a thread. `msg` is deeply copied.
|
||||
|
|
@ -212,7 +212,7 @@ proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =
|
|||
acquireSys(q.lock)
|
||||
q.ready = true
|
||||
while q.count <= 0:
|
||||
WaitSysCond(q.cond, q.lock)
|
||||
waitSysCond(q.cond, q.lock)
|
||||
q.ready = false
|
||||
if typ != q.elemType:
|
||||
releaseSys(q.lock)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
# Implementation of some runtime checks.
|
||||
|
||||
proc raiseRangeError(val: biggestInt) {.compilerproc, noreturn, noinline.} =
|
||||
when hostOs == "standalone":
|
||||
proc raiseRangeError(val: BiggestInt) {.compilerproc, noreturn, noinline.} =
|
||||
when hostOS == "standalone":
|
||||
sysFatal(EOutOfRange, "value out of range")
|
||||
else:
|
||||
sysFatal(EOutOfRange, "value out of range: ", $val)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ proc nimLoadLibraryError(path: string) =
|
|||
stdout.rawWrite("\n")
|
||||
quit(1)
|
||||
|
||||
proc ProcAddrError(name: cstring) {.noinline.} =
|
||||
proc procAddrError(name: cstring) {.noinline.} =
|
||||
# carefully written to avoid memory allocation:
|
||||
stdout.rawWrite("could not import: ")
|
||||
stdout.write(name)
|
||||
|
|
@ -56,7 +56,7 @@ when defined(posix):
|
|||
RTLD_NOW {.importc: "RTLD_NOW", header: "<dlfcn.h>".}: int
|
||||
|
||||
proc dlclose(lib: TLibHandle) {.importc, header: "<dlfcn.h>".}
|
||||
proc dlopen(path: CString, mode: int): TLibHandle {.
|
||||
proc dlopen(path: cstring, mode: int): TLibHandle {.
|
||||
importc, header: "<dlfcn.h>".}
|
||||
proc dlsym(lib: TLibHandle, name: cstring): TProcAddr {.
|
||||
importc, header: "<dlfcn.h>".}
|
||||
|
|
@ -72,7 +72,7 @@ when defined(posix):
|
|||
|
||||
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
|
||||
result = dlsym(lib, name)
|
||||
if result == nil: ProcAddrError(name)
|
||||
if result == nil: procAddrError(name)
|
||||
|
||||
elif defined(windows) or defined(dos):
|
||||
#
|
||||
|
|
@ -83,21 +83,22 @@ elif defined(windows) or defined(dos):
|
|||
type
|
||||
THINSTANCE {.importc: "HINSTANCE".} = pointer
|
||||
|
||||
proc FreeLibrary(lib: THINSTANCE) {.importc, header: "<windows.h>", stdcall.}
|
||||
proc freeLibrary(lib: THINSTANCE) {.
|
||||
importc: "FreeLibrary", header: "<windows.h>", stdcall.}
|
||||
proc winLoadLibrary(path: cstring): THINSTANCE {.
|
||||
importc: "LoadLibraryA", header: "<windows.h>", stdcall.}
|
||||
proc GetProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
|
||||
proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
|
||||
importc: "GetProcAddress", header: "<windows.h>", stdcall.}
|
||||
|
||||
proc nimUnloadLibrary(lib: TLibHandle) =
|
||||
FreeLibrary(cast[THINSTANCE](lib))
|
||||
freeLibrary(cast[THINSTANCE](lib))
|
||||
|
||||
proc nimLoadLibrary(path: string): TLibHandle =
|
||||
result = cast[TLibHandle](winLoadLibrary(path))
|
||||
|
||||
proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
|
||||
result = GetProcAddress(cast[THINSTANCE](lib), name)
|
||||
if result == nil: ProcAddrError(name)
|
||||
result = getProcAddress(cast[THINSTANCE](lib), name)
|
||||
if result == nil: procAddrError(name)
|
||||
|
||||
elif defined(mac):
|
||||
#
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@
|
|||
# use the heap (and nor exceptions) do not include the GC or memory allocator.
|
||||
|
||||
var
|
||||
errorMessageWriter*: (proc(msg: string): void {.tags: [FWriteIO].})
|
||||
errorMessageWriter*: (proc(msg: string) {.tags: [FWriteIO].})
|
||||
## Function that will be called
|
||||
## instead of stdmsg.write when printing stacktrace.
|
||||
## Unstable API.
|
||||
|
||||
when not defined(windows) or not defined(guiapp):
|
||||
proc writeToStdErr(msg: CString) = write(stdmsg, msg)
|
||||
proc writeToStdErr(msg: cstring) = write(stdmsg, msg)
|
||||
|
||||
else:
|
||||
proc MessageBoxA(hWnd: cint, lpText, lpCaption: cstring, uType: int): int32 {.
|
||||
|
|
@ -80,9 +80,9 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
|
|||
type
|
||||
TDl_info {.importc: "Dl_info", header: "<dlfcn.h>",
|
||||
final, pure.} = object
|
||||
dli_fname: CString
|
||||
dli_fname: cstring
|
||||
dli_fbase: pointer
|
||||
dli_sname: CString
|
||||
dli_sname: cstring
|
||||
dli_saddr: pointer
|
||||
|
||||
proc backtrace(symbols: ptr pointer, size: int): int {.
|
||||
|
|
@ -240,7 +240,7 @@ proc raiseExceptionAux(e: ref E_Base) =
|
|||
showErrorMessage(buf)
|
||||
quitOrDebug()
|
||||
|
||||
proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
||||
proc raiseException(e: ref E_Base, ename: cstring) {.compilerRtl.} =
|
||||
e.name = ename
|
||||
when hasSomeStackTrace:
|
||||
e.trace = ""
|
||||
|
|
@ -253,7 +253,7 @@ proc reraiseException() {.compilerRtl.} =
|
|||
else:
|
||||
raiseExceptionAux(currException)
|
||||
|
||||
proc WriteStackTrace() =
|
||||
proc writeStackTrace() =
|
||||
when hasSomeStackTrace:
|
||||
var s = ""
|
||||
rawWriteStackTrace(s)
|
||||
|
|
@ -280,7 +280,7 @@ when defined(endb):
|
|||
|
||||
when not defined(noSignalHandler):
|
||||
proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
|
||||
template processSignal(s, action: expr) {.immediate.} =
|
||||
template processSignal(s, action: expr) {.immediate, dirty.} =
|
||||
if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n")
|
||||
elif s == SIGSEGV:
|
||||
action("SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ var
|
|||
gch {.rtlThreadVar.}: TGcHeap
|
||||
|
||||
when not defined(useNimRtl):
|
||||
InstantiateForRegion(gch.region)
|
||||
instantiateForRegion(gch.region)
|
||||
|
||||
template acquire(gch: TGcHeap) =
|
||||
when hasThreadSupport and hasSharedHeap:
|
||||
|
|
@ -132,9 +132,9 @@ when BitsPerPage mod (sizeof(int)*8) != 0:
|
|||
template color(c): expr = c.refCount and colorMask
|
||||
template setColor(c, col) =
|
||||
when col == rcBlack:
|
||||
c.refcount = c.refCount and not colorMask
|
||||
c.refcount = c.refcount and not colorMask
|
||||
else:
|
||||
c.refcount = c.refCount and not colorMask or col
|
||||
c.refcount = c.refcount and not colorMask or col
|
||||
|
||||
proc writeCell(msg: cstring, c: PCell) =
|
||||
var kind = -1
|
||||
|
|
@ -151,10 +151,10 @@ template gcTrace(cell, state: expr): stmt {.immediate.} =
|
|||
|
||||
# forward declarations:
|
||||
proc collectCT(gch: var TGcHeap)
|
||||
proc IsOnStack*(p: pointer): bool {.noinline.}
|
||||
proc isOnStack*(p: pointer): bool {.noinline.}
|
||||
proc forAllChildren(cell: PCell, op: TWalkOp)
|
||||
proc doOperation(p: pointer, op: TWalkOp)
|
||||
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp)
|
||||
proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp)
|
||||
# we need the prototype here for debugging purposes
|
||||
|
||||
when hasThreadSupport and hasSharedHeap:
|
||||
|
|
@ -162,9 +162,9 @@ when hasThreadSupport and hasSharedHeap:
|
|||
template `++`(x: expr): stmt = discard atomicInc(x, rcIncrement)
|
||||
else:
|
||||
template `--`(x: expr): expr =
|
||||
Dec(x, rcIncrement)
|
||||
dec(x, rcIncrement)
|
||||
x <% rcIncrement
|
||||
template `++`(x: expr): stmt = Inc(x, rcIncrement)
|
||||
template `++`(x: expr): stmt = inc(x, rcIncrement)
|
||||
|
||||
proc prepareDealloc(cell: PCell) =
|
||||
when useMarkForDebug:
|
||||
|
|
@ -203,7 +203,7 @@ proc decRef(c: PCell) {.inline.} =
|
|||
gcAssert(c.refcount >=% rcIncrement, "decRef")
|
||||
if --c.refcount:
|
||||
rtlAddZCT(c)
|
||||
elif canBeCycleRoot(c):
|
||||
elif canbeCycleRoot(c):
|
||||
# unfortunately this is necessary here too, because a cycle might just
|
||||
# have been broken up and we could recycle it.
|
||||
rtlAddCycleRoot(c)
|
||||
|
|
@ -211,10 +211,10 @@ proc decRef(c: PCell) {.inline.} =
|
|||
|
||||
proc incRef(c: PCell) {.inline.} =
|
||||
gcAssert(isAllocatedPtr(gch.region, c), "incRef: interiorPtr")
|
||||
c.refcount = c.refCount +% rcIncrement
|
||||
c.refcount = c.refcount +% rcIncrement
|
||||
# and not colorMask
|
||||
#writeCell("incRef", c)
|
||||
if canBeCycleRoot(c):
|
||||
if canbeCycleRoot(c):
|
||||
rtlAddCycleRoot(c)
|
||||
|
||||
proc nimGCref(p: pointer) {.compilerProc, inline.} = incRef(usrToCell(p))
|
||||
|
|
@ -235,7 +235,7 @@ proc nimGCunrefNoCycle(p: pointer) {.compilerProc, inline.} =
|
|||
sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 2")
|
||||
sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 5")
|
||||
|
||||
proc asgnRef(dest: ppointer, src: pointer) {.compilerProc, inline.} =
|
||||
proc asgnRef(dest: PPointer, src: pointer) {.compilerProc, inline.} =
|
||||
# the code generator calls this proc!
|
||||
gcAssert(not isOnStack(dest), "asgnRef")
|
||||
# BUGFIX: first incRef then decRef!
|
||||
|
|
@ -243,7 +243,7 @@ proc asgnRef(dest: ppointer, src: pointer) {.compilerProc, inline.} =
|
|||
if dest[] != nil: decRef(usrToCell(dest[]))
|
||||
dest[] = src
|
||||
|
||||
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerProc, inline.} =
|
||||
proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerProc, inline.} =
|
||||
# the code generator calls this proc if it is known at compile time that no
|
||||
# cycle is possible.
|
||||
if src != nil:
|
||||
|
|
@ -255,7 +255,7 @@ proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerProc, inline.} =
|
|||
rtlAddZCT(c)
|
||||
dest[] = src
|
||||
|
||||
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerProc.} =
|
||||
proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerProc.} =
|
||||
# unsureAsgnRef updates the reference counters only if dest is not on the
|
||||
# stack. It is used by the code generator if it cannot decide wether a
|
||||
# reference is in the stack or not (this can happen for var parameters).
|
||||
|
|
@ -318,7 +318,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
|
|||
# inlined for speed
|
||||
if n.sons[i].kind == nkSlot:
|
||||
if n.sons[i].typ.kind in {tyRef, tyString, tySequence}:
|
||||
doOperation(cast[ppointer](d +% n.sons[i].offset)[], op)
|
||||
doOperation(cast[PPointer](d +% n.sons[i].offset)[], op)
|
||||
else:
|
||||
forAllChildrenAux(cast[pointer](d +% n.sons[i].offset),
|
||||
n.sons[i].typ, op)
|
||||
|
|
@ -329,19 +329,19 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
|
|||
if m != nil: forAllSlotsAux(dest, m, op)
|
||||
of nkNone: sysAssert(false, "forAllSlotsAux")
|
||||
|
||||
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
|
||||
proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
|
||||
var d = cast[TAddress](dest)
|
||||
if dest == nil: return # nothing to do
|
||||
if ntfNoRefs notin mt.flags:
|
||||
case mt.Kind
|
||||
case mt.kind
|
||||
of tyRef, tyString, tySequence: # leaf:
|
||||
doOperation(cast[ppointer](d)[], op)
|
||||
doOperation(cast[PPointer](d)[], op)
|
||||
of tyObject, tyTuple:
|
||||
forAllSlotsAux(dest, mt.node, op)
|
||||
of tyArray, tyArrayConstr, tyOpenArray:
|
||||
for i in 0..(mt.size div mt.base.size)-1:
|
||||
forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
|
||||
else: nil
|
||||
else: discard
|
||||
|
||||
proc forAllChildren(cell: PCell, op: TWalkOp) =
|
||||
gcAssert(cell != nil, "forAllChildren: 1")
|
||||
|
|
@ -352,7 +352,7 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
|
|||
if marker != nil:
|
||||
marker(cellToUsr(cell), op.int)
|
||||
else:
|
||||
case cell.typ.Kind
|
||||
case cell.typ.kind
|
||||
of tyRef: # common case
|
||||
forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
|
||||
of tySequence:
|
||||
|
|
@ -519,7 +519,7 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
|
|||
d[j] = res
|
||||
break
|
||||
dec(j)
|
||||
if canBeCycleRoot(ol): excl(gch.cycleRoots, ol)
|
||||
if canbeCycleRoot(ol): excl(gch.cycleRoots, ol)
|
||||
when logGC:
|
||||
writeCell("growObj old cell", ol)
|
||||
writeCell("growObj new cell", res)
|
||||
|
|
@ -573,7 +573,7 @@ proc scan(s: PCell) =
|
|||
|
||||
proc collectWhite(s: PCell) =
|
||||
if s.color == rcWhite and s notin gch.cycleRoots:
|
||||
s.setcolor(rcBlack)
|
||||
s.setColor(rcBlack)
|
||||
forAllChildren(s, waCollectWhite)
|
||||
freeCyclicCell(gch, s)
|
||||
|
||||
|
|
@ -582,7 +582,7 @@ proc markRoots(gch: var TGcHeap) =
|
|||
for s in elements(gch.cycleRoots):
|
||||
#writeCell("markRoot", s)
|
||||
inc tabSize
|
||||
if s.color == rcPurple and s.refCount >=% rcIncrement:
|
||||
if s.color == rcPurple and s.refcount >=% rcIncrement:
|
||||
markGray(s)
|
||||
else:
|
||||
excl(gch.cycleRoots, s)
|
||||
|
|
@ -669,7 +669,7 @@ proc doOperation(p: pointer, op: TWalkOp) =
|
|||
proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} =
|
||||
doOperation(d, TWalkOp(op))
|
||||
|
||||
proc CollectZCT(gch: var TGcHeap): bool
|
||||
proc collectZCT(gch: var TGcHeap): bool
|
||||
|
||||
when useMarkForDebug or useBackupGc:
|
||||
proc markStackAndRegistersForSweep(gch: var TGcHeap) {.noinline, cdecl.}
|
||||
|
|
@ -869,7 +869,7 @@ else:
|
|||
sp = sp +% sizeof(pointer)*8
|
||||
# last few entries:
|
||||
while sp <=% max:
|
||||
gcMark(gch, cast[ppointer](sp)[])
|
||||
gcMark(gch, cast[PPointer](sp)[])
|
||||
sp = sp +% sizeof(pointer)
|
||||
|
||||
proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
|
||||
|
|
@ -891,7 +891,7 @@ proc collectZCT(gch: var TGcHeap): bool =
|
|||
const workPackage = 100
|
||||
var L = addr(gch.zct.len)
|
||||
|
||||
when withRealtime:
|
||||
when withRealTime:
|
||||
var steps = workPackage
|
||||
var t0: TTicks
|
||||
if gch.maxPause > 0: t0 = getticks()
|
||||
|
|
@ -904,7 +904,7 @@ proc collectZCT(gch: var TGcHeap): bool =
|
|||
c.refcount = c.refcount and not ZctFlag
|
||||
gch.zct.d[0] = gch.zct.d[L[] - 1]
|
||||
dec(L[])
|
||||
when withRealtime: dec steps
|
||||
when withRealTime: dec steps
|
||||
if c.refcount <% rcIncrement:
|
||||
# It may have a RC > 0, if it is in the hardware stack or
|
||||
# it has not been removed yet from the ZCT. This is because
|
||||
|
|
@ -913,7 +913,7 @@ proc collectZCT(gch: var TGcHeap): bool =
|
|||
# In any case, it should be removed from the ZCT. But not
|
||||
# freed. **KEEP THIS IN MIND WHEN MAKING THIS INCREMENTAL!**
|
||||
when cycleGC:
|
||||
if canBeCycleRoot(c): excl(gch.cycleRoots, c)
|
||||
if canbeCycleRoot(c): excl(gch.cycleRoots, c)
|
||||
when logGC: writeCell("zct dealloc cell", c)
|
||||
gcTrace(c, csZctFreed)
|
||||
# We are about to free the object, call the finalizer BEFORE its
|
||||
|
|
@ -927,7 +927,7 @@ proc collectZCT(gch: var TGcHeap): bool =
|
|||
else:
|
||||
sysAssert(c.typ != nil, "collectZCT 2")
|
||||
zeroMem(c, sizeof(TCell))
|
||||
when withRealtime:
|
||||
when withRealTime:
|
||||
if steps == 0:
|
||||
steps = workPackage
|
||||
if gch.maxPause > 0:
|
||||
|
|
@ -952,7 +952,7 @@ proc unmarkStackAndRegisters(gch: var TGcHeap) =
|
|||
gch.decStack.len = 0
|
||||
|
||||
proc collectCTBody(gch: var TGcHeap) =
|
||||
when withRealtime:
|
||||
when withRealTime:
|
||||
let t0 = getticks()
|
||||
sysAssert(allocInv(gch.region), "collectCT: begin")
|
||||
|
||||
|
|
@ -970,12 +970,12 @@ proc collectCTBody(gch: var TGcHeap) =
|
|||
#discard collectZCT(gch)
|
||||
inc(gch.stat.cycleCollections)
|
||||
gch.cycleThreshold = max(InitialCycleThreshold, getOccupiedMem() *
|
||||
cycleIncrease)
|
||||
CycleIncrease)
|
||||
gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold)
|
||||
unmarkStackAndRegisters(gch)
|
||||
sysAssert(allocInv(gch.region), "collectCT: end")
|
||||
|
||||
when withRealtime:
|
||||
when withRealTime:
|
||||
let duration = getticks() - t0
|
||||
gch.stat.maxPause = max(gch.stat.maxPause, duration)
|
||||
when defined(reportMissedDeadlines):
|
||||
|
|
@ -997,7 +997,7 @@ proc collectCT(gch: var TGcHeap) =
|
|||
markForDebug(gch)
|
||||
collectCTBody(gch)
|
||||
|
||||
when withRealtime:
|
||||
when withRealTime:
|
||||
proc toNano(x: int): TNanos {.inline.} =
|
||||
result = x * 1000
|
||||
|
||||
|
|
@ -1029,11 +1029,7 @@ when not defined(useNimRtl):
|
|||
dec(gch.recGcLock)
|
||||
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) =
|
||||
case strategy
|
||||
of gcThroughput: nil
|
||||
of gcResponsiveness: nil
|
||||
of gcOptimizeSpace: nil
|
||||
of gcOptimizeTime: nil
|
||||
discard
|
||||
|
||||
proc GC_enableMarkAndSweep() =
|
||||
gch.cycleThreshold = InitialCycleThreshold
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ type
|
|||
kind: TNimNodeKind
|
||||
offset: int
|
||||
typ: ptr TNimType
|
||||
name: Cstring
|
||||
name: cstring
|
||||
len: int
|
||||
sons: ptr array [0..0x7fff, ptr TNimNode]
|
||||
|
||||
|
|
|
|||
|
|
@ -472,17 +472,17 @@ proc Ze(a: int): int {.compilerproc.} =
|
|||
proc Ze64(a: int64): int64 {.compilerproc.} =
|
||||
result = a
|
||||
|
||||
proc toU8(a: int): int8 {.noStackFrame, compilerproc.} =
|
||||
proc ToU8(a: int): int8 {.noStackFrame, compilerproc.} =
|
||||
asm """
|
||||
return `a`;
|
||||
"""
|
||||
|
||||
proc toU16(a: int): int16 {.noStackFrame, compilerproc.} =
|
||||
proc ToU16(a: int): int16 {.noStackFrame, compilerproc.} =
|
||||
asm """
|
||||
return `a`;
|
||||
"""
|
||||
|
||||
proc toU32(a: int): int32 {.noStackFrame, compilerproc.} =
|
||||
proc ToU32(a: int): int32 {.noStackFrame, compilerproc.} =
|
||||
asm """
|
||||
return `a`;
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const
|
|||
|
||||
type
|
||||
PPointer = ptr pointer
|
||||
TByteArray = array[0..1000_0000, byte]
|
||||
TByteArray = array[0..1000_0000, Byte]
|
||||
PByte = ptr TByteArray
|
||||
PString = ptr string
|
||||
|
||||
|
|
@ -114,10 +114,10 @@ when defined(boehmgc):
|
|||
proc alloc0(size: int): pointer =
|
||||
result = alloc(size)
|
||||
zeroMem(result, size)
|
||||
proc realloc(p: Pointer, newsize: int): pointer =
|
||||
proc realloc(p: pointer, newsize: int): pointer =
|
||||
result = boehmRealloc(p, newsize)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc dealloc(p: Pointer) = boehmDealloc(p)
|
||||
proc dealloc(p: pointer) = boehmDealloc(p)
|
||||
|
||||
proc allocShared(size: int): pointer =
|
||||
result = boehmAlloc(size)
|
||||
|
|
@ -125,26 +125,26 @@ when defined(boehmgc):
|
|||
proc allocShared0(size: int): pointer =
|
||||
result = alloc(size)
|
||||
zeroMem(result, size)
|
||||
proc reallocShared(p: Pointer, newsize: int): pointer =
|
||||
proc reallocShared(p: pointer, newsize: int): pointer =
|
||||
result = boehmRealloc(p, newsize)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc deallocShared(p: Pointer) = boehmDealloc(p)
|
||||
proc deallocShared(p: pointer) = boehmDealloc(p)
|
||||
|
||||
#boehmGCincremental()
|
||||
|
||||
proc GC_disable() = boehmGC_disable()
|
||||
proc GC_enable() = boehmGC_enable()
|
||||
proc GC_fullCollect() = boehmGCfullCollect()
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = nil
|
||||
proc GC_enableMarkAndSweep() = nil
|
||||
proc GC_disableMarkAndSweep() = nil
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = discard
|
||||
proc GC_enableMarkAndSweep() = discard
|
||||
proc GC_disableMarkAndSweep() = discard
|
||||
proc GC_getStatistics(): string = return ""
|
||||
|
||||
proc getOccupiedMem(): int = return boehmGetHeapSize()-boehmGetFreeBytes()
|
||||
proc getFreeMem(): int = return boehmGetFreeBytes()
|
||||
proc getTotalMem(): int = return boehmGetHeapSize()
|
||||
|
||||
proc setStackBottom(theStackBottom: pointer) = nil
|
||||
proc setStackBottom(theStackBottom: pointer) = discard
|
||||
|
||||
proc initGC() =
|
||||
when defined(macosx): boehmGCinit()
|
||||
|
|
@ -160,8 +160,8 @@ when defined(boehmgc):
|
|||
proc growObj(old: pointer, newsize: int): pointer =
|
||||
result = realloc(old, newsize)
|
||||
|
||||
proc nimGCref(p: pointer) {.compilerproc, inline.} = nil
|
||||
proc nimGCunref(p: pointer) {.compilerproc, inline.} = nil
|
||||
proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
|
||||
proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
|
||||
|
||||
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
|
||||
dest[] = src
|
||||
|
|
@ -173,15 +173,15 @@ when defined(boehmgc):
|
|||
type
|
||||
TMemRegion = object {.final, pure.}
|
||||
|
||||
proc Alloc(r: var TMemRegion, size: int): pointer =
|
||||
proc alloc(r: var TMemRegion, size: int): pointer =
|
||||
result = boehmAlloc(size)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc Alloc0(r: var TMemRegion, size: int): pointer =
|
||||
proc alloc0(r: var TMemRegion, size: int): pointer =
|
||||
result = alloc(size)
|
||||
zeroMem(result, size)
|
||||
proc Dealloc(r: var TMemRegion, p: Pointer) = boehmDealloc(p)
|
||||
proc deallocOsPages(r: var TMemRegion) {.inline.} = nil
|
||||
proc deallocOsPages() {.inline.} = nil
|
||||
proc dealloc(r: var TMemRegion, p: Pointer) = boehmDealloc(p)
|
||||
proc deallocOsPages(r: var TMemRegion) {.inline.} = discard
|
||||
proc deallocOsPages() {.inline.} = discard
|
||||
|
||||
include "system/cellsets"
|
||||
elif defined(nogc) and defined(useMalloc):
|
||||
|
|
@ -193,10 +193,10 @@ elif defined(nogc) and defined(useMalloc):
|
|||
proc alloc0(size: int): pointer =
|
||||
result = alloc(size)
|
||||
zeroMem(result, size)
|
||||
proc realloc(p: Pointer, newsize: int): pointer =
|
||||
proc realloc(p: pointer, newsize: int): pointer =
|
||||
result = crealloc(p, newsize)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc dealloc(p: Pointer) = cfree(p)
|
||||
proc dealloc(p: pointer) = cfree(p)
|
||||
|
||||
proc allocShared(size: int): pointer =
|
||||
result = cmalloc(size)
|
||||
|
|
@ -204,26 +204,26 @@ elif defined(nogc) and defined(useMalloc):
|
|||
proc allocShared0(size: int): pointer =
|
||||
result = alloc(size)
|
||||
zeroMem(result, size)
|
||||
proc reallocShared(p: Pointer, newsize: int): pointer =
|
||||
proc reallocShared(p: pointer, newsize: int): pointer =
|
||||
result = crealloc(p, newsize)
|
||||
if result == nil: raiseOutOfMem()
|
||||
proc deallocShared(p: Pointer) = cfree(p)
|
||||
proc deallocShared(p: pointer) = cfree(p)
|
||||
|
||||
proc GC_disable() = nil
|
||||
proc GC_enable() = nil
|
||||
proc GC_fullCollect() = nil
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = nil
|
||||
proc GC_enableMarkAndSweep() = nil
|
||||
proc GC_disableMarkAndSweep() = nil
|
||||
proc GC_disable() = discard
|
||||
proc GC_enable() = discard
|
||||
proc GC_fullCollect() = discard
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = discard
|
||||
proc GC_enableMarkAndSweep() = discard
|
||||
proc GC_disableMarkAndSweep() = discard
|
||||
proc GC_getStatistics(): string = return ""
|
||||
|
||||
proc getOccupiedMem(): int = nil
|
||||
proc getFreeMem(): int = nil
|
||||
proc getTotalMem(): int = nil
|
||||
proc getOccupiedMem(): int = discard
|
||||
proc getFreeMem(): int = discard
|
||||
proc getTotalMem(): int = discard
|
||||
|
||||
proc setStackBottom(theStackBottom: pointer) = nil
|
||||
proc setStackBottom(theStackBottom: pointer) = discard
|
||||
|
||||
proc initGC() = nil
|
||||
proc initGC() = discard
|
||||
|
||||
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
|
||||
result = alloc(size)
|
||||
|
|
@ -235,8 +235,8 @@ elif defined(nogc) and defined(useMalloc):
|
|||
proc growObj(old: pointer, newsize: int): pointer =
|
||||
result = realloc(old, newsize)
|
||||
|
||||
proc nimGCref(p: pointer) {.compilerproc, inline.} = nil
|
||||
proc nimGCunref(p: pointer) {.compilerproc, inline.} = nil
|
||||
proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
|
||||
proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
|
||||
|
||||
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
|
||||
dest[] = src
|
||||
|
|
@ -248,13 +248,13 @@ elif defined(nogc) and defined(useMalloc):
|
|||
type
|
||||
TMemRegion = object {.final, pure.}
|
||||
|
||||
proc Alloc(r: var TMemRegion, size: int): pointer =
|
||||
proc alloc(r: var TMemRegion, size: int): pointer =
|
||||
result = alloc(size)
|
||||
proc Alloc0(r: var TMemRegion, size: int): pointer =
|
||||
proc alloc0(r: var TMemRegion, size: int): pointer =
|
||||
result = alloc0(size)
|
||||
proc Dealloc(r: var TMemRegion, p: Pointer) = Dealloc(p)
|
||||
proc deallocOsPages(r: var TMemRegion) {.inline.} = nil
|
||||
proc deallocOsPages() {.inline.} = nil
|
||||
proc dealloc(r: var TMemRegion, p: pointer) = dealloc(p)
|
||||
proc deallocOsPages(r: var TMemRegion) {.inline.} = discard
|
||||
proc deallocOsPages() {.inline.} = discard
|
||||
|
||||
elif defined(nogc):
|
||||
# Even though we don't want the GC, we cannot simply use C's memory manager
|
||||
|
|
@ -268,13 +268,13 @@ elif defined(nogc):
|
|||
|
||||
include "system/alloc"
|
||||
|
||||
proc initGC() = nil
|
||||
proc GC_disable() = nil
|
||||
proc GC_enable() = nil
|
||||
proc GC_fullCollect() = nil
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = nil
|
||||
proc GC_enableMarkAndSweep() = nil
|
||||
proc GC_disableMarkAndSweep() = nil
|
||||
proc initGC() = discard
|
||||
proc GC_disable() = discard
|
||||
proc GC_enable() = discard
|
||||
proc GC_fullCollect() = discard
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = discard
|
||||
proc GC_enableMarkAndSweep() = discard
|
||||
proc GC_disableMarkAndSweep() = discard
|
||||
proc GC_getStatistics(): string = return ""
|
||||
|
||||
|
||||
|
|
@ -287,9 +287,9 @@ elif defined(nogc):
|
|||
proc growObj(old: pointer, newsize: int): pointer =
|
||||
result = realloc(old, newsize)
|
||||
|
||||
proc setStackBottom(theStackBottom: pointer) = nil
|
||||
proc nimGCref(p: pointer) {.compilerproc, inline.} = nil
|
||||
proc nimGCunref(p: pointer) {.compilerproc, inline.} = nil
|
||||
proc setStackBottom(theStackBottom: pointer) = discard
|
||||
proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
|
||||
proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
|
||||
|
||||
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} =
|
||||
dest[] = src
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
|
|||
result = $e & " (invalid data!)"
|
||||
|
||||
type
|
||||
pbyteArray = ptr array[0.. 0xffff, int8]
|
||||
PByteArray = ptr array[0.. 0xffff, int8]
|
||||
|
||||
proc addSetElem(result: var string, elem: int, typ: PNimType) =
|
||||
case typ.kind
|
||||
|
|
@ -96,7 +96,7 @@ proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
|
|||
of 4: u = ze64(cast[ptr int32](p)[])
|
||||
of 8: u = cast[ptr int64](p)[]
|
||||
else:
|
||||
var a = cast[pbyteArray](p)
|
||||
var a = cast[PByteArray](p)
|
||||
for i in 0 .. typ.size*8-1:
|
||||
if (ze(a[i div 8]) and (1 shl (i mod 8))) != 0:
|
||||
if elemCounter > 0: add result, ", "
|
||||
|
|
@ -129,12 +129,12 @@ when not defined(useNimRtl):
|
|||
when hasThreadSupport and hasSharedHeap and defined(heapLock):
|
||||
AcquireSys(HeapLock)
|
||||
when defined(TCellSet):
|
||||
Init(cl.marked)
|
||||
init(cl.marked)
|
||||
cl.recdepth = -1 # default is to display everything!
|
||||
cl.indent = 0
|
||||
|
||||
proc deinitReprClosure(cl: var TReprClosure) =
|
||||
when defined(TCellSet): Deinit(cl.marked)
|
||||
when defined(TCellSet): deinit(cl.marked)
|
||||
when hasThreadSupport and hasSharedHeap and defined(heapLock):
|
||||
ReleaseSys(HeapLock)
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ when not defined(useNimRtl):
|
|||
for i in 0..cast[PGenericSeq](p).len-1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + GenericSeqSize + i*bs),
|
||||
typ.Base, cl)
|
||||
typ.base, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
|
||||
|
|
@ -224,17 +224,17 @@ when not defined(useNimRtl):
|
|||
reprRecord(result, p, t, cl)
|
||||
of tyRef, tyPtr:
|
||||
sysAssert(p != nil, "reprAux")
|
||||
if cast[ppointer](p)[] == nil: add result, "nil"
|
||||
else: reprRef(result, cast[ppointer](p)[], typ, cl)
|
||||
if cast[PPointer](p)[] == nil: add result, "nil"
|
||||
else: reprRef(result, cast[PPointer](p)[], typ, cl)
|
||||
of tySequence:
|
||||
reprSequence(result, cast[ppointer](p)[], typ, cl)
|
||||
reprSequence(result, cast[PPointer](p)[], typ, cl)
|
||||
of tyInt: add result, $(cast[ptr int](p)[])
|
||||
of tyInt8: add result, $int(cast[ptr Int8](p)[])
|
||||
of tyInt16: add result, $int(cast[ptr Int16](p)[])
|
||||
of tyInt32: add result, $int(cast[ptr Int32](p)[])
|
||||
of tyInt64: add result, $(cast[ptr Int64](p)[])
|
||||
of tyUInt8: add result, $ze(cast[ptr Int8](p)[])
|
||||
of tyUInt16: add result, $ze(cast[ptr Int16](p)[])
|
||||
of tyInt8: add result, $int(cast[ptr int8](p)[])
|
||||
of tyInt16: add result, $int(cast[ptr int16](p)[])
|
||||
of tyInt32: add result, $int(cast[ptr int32](p)[])
|
||||
of tyInt64: add result, $(cast[ptr int64](p)[])
|
||||
of tyUInt8: add result, $ze(cast[ptr int8](p)[])
|
||||
of tyUInt16: add result, $ze(cast[ptr int16](p)[])
|
||||
|
||||
of tyFloat: add result, $(cast[ptr float](p)[])
|
||||
of tyFloat32: add result, $(cast[ptr float32](p)[])
|
||||
|
|
@ -246,8 +246,8 @@ when not defined(useNimRtl):
|
|||
of tyCString: reprStrAux(result, $(cast[ptr cstring](p)[]))
|
||||
of tyRange: reprAux(result, p, typ.base, cl)
|
||||
of tyProc, tyPointer:
|
||||
if cast[ppointer](p)[] == nil: add result, "nil"
|
||||
else: add result, reprPointer(cast[ppointer](p)[])
|
||||
if cast[PPointer](p)[] == nil: add result, "nil"
|
||||
else: add result, reprPointer(cast[PPointer](p)[])
|
||||
else:
|
||||
add result, "(invalid data!)"
|
||||
inc(cl.recdepth)
|
||||
|
|
|
|||
|
|
@ -24,16 +24,16 @@ proc fgetc(stream: TFile): cint {.importc: "fgetc", header: "<stdio.h>",
|
|||
tags: [FReadIO].}
|
||||
proc ungetc(c: cint, f: TFile) {.importc: "ungetc", header: "<stdio.h>",
|
||||
tags: [].}
|
||||
proc putc(c: Char, stream: TFile) {.importc: "putc", header: "<stdio.h>",
|
||||
proc putc(c: char, stream: TFile) {.importc: "putc", header: "<stdio.h>",
|
||||
tags: [FWriteIO].}
|
||||
proc fprintf(f: TFile, frmt: CString) {.importc: "fprintf",
|
||||
proc fprintf(f: TFile, frmt: cstring) {.importc: "fprintf",
|
||||
header: "<stdio.h>", varargs, tags: [FWriteIO].}
|
||||
proc strlen(c: cstring): int {.
|
||||
importc: "strlen", header: "<string.h>", tags: [].}
|
||||
|
||||
|
||||
# C routine that is used here:
|
||||
proc fread(buf: Pointer, size, n: int, f: TFile): int {.
|
||||
proc fread(buf: pointer, size, n: int, f: TFile): int {.
|
||||
importc: "fread", header: "<stdio.h>", tags: [FReadIO].}
|
||||
proc fseek(f: TFile, offset: clong, whence: int): int {.
|
||||
importc: "fseek", header: "<stdio.h>", tags: [].}
|
||||
|
|
@ -45,12 +45,24 @@ proc setvbuf(stream: TFile, buf: pointer, typ, size: cint): cint {.
|
|||
proc write(f: TFile, c: cstring) = fputs(c, f)
|
||||
{.pop.}
|
||||
|
||||
var
|
||||
IOFBF {.importc: "_IOFBF", nodecl.}: cint
|
||||
IONBF {.importc: "_IONBF", nodecl.}: cint
|
||||
when NoFakeVars:
|
||||
when defined(windows):
|
||||
const
|
||||
IOFBF = cint(0)
|
||||
IONBF = cint(4)
|
||||
elif defined(macosx) or defined(linux):
|
||||
const
|
||||
IOFBF = cint(0)
|
||||
IONBF = cint(2)
|
||||
else:
|
||||
{.error: "IOFBF not ported to your platform".}
|
||||
else:
|
||||
var
|
||||
IOFBF {.importc: "_IOFBF", nodecl.}: cint
|
||||
IONBF {.importc: "_IONBF", nodecl.}: cint
|
||||
|
||||
const
|
||||
buf_size = 4000
|
||||
BufSize = 4000
|
||||
|
||||
proc raiseEIO(msg: string) {.noinline, noreturn.} =
|
||||
sysFatal(EIO, msg)
|
||||
|
|
@ -59,7 +71,7 @@ proc readLine(f: TFile, line: var TaintedString): bool =
|
|||
# of course this could be optimized a bit; but IO is slow anyway...
|
||||
# and it was difficult to get this CORRECT with Ansi C's methods
|
||||
setLen(line.string, 0) # reuse the buffer!
|
||||
while True:
|
||||
while true:
|
||||
var c = fgetc(f)
|
||||
if c < 0'i32:
|
||||
if line.len > 0: break
|
||||
|
|
@ -82,8 +94,8 @@ proc write(f: TFile, i: int) =
|
|||
else:
|
||||
fprintf(f, "%ld", i)
|
||||
|
||||
proc write(f: TFile, i: biggestInt) =
|
||||
when sizeof(biggestint) == 8:
|
||||
proc write(f: TFile, i: BiggestInt) =
|
||||
when sizeof(BiggestInt) == 8:
|
||||
fprintf(f, "%lld", i)
|
||||
else:
|
||||
fprintf(f, "%ld", i)
|
||||
|
|
@ -92,9 +104,9 @@ proc write(f: TFile, b: bool) =
|
|||
if b: write(f, "true")
|
||||
else: write(f, "false")
|
||||
proc write(f: TFile, r: float32) = fprintf(f, "%g", r)
|
||||
proc write(f: TFile, r: biggestFloat) = fprintf(f, "%g", r)
|
||||
proc write(f: TFile, r: BiggestFloat) = fprintf(f, "%g", r)
|
||||
|
||||
proc write(f: TFile, c: Char) = putc(c, f)
|
||||
proc write(f: TFile, c: char) = putc(c, f)
|
||||
proc write(f: TFile, a: varargs[string, `$`]) =
|
||||
for x in items(a): write(f, x)
|
||||
|
||||
|
|
@ -102,10 +114,10 @@ proc readAllBuffer(file: TFile): string =
|
|||
# This proc is for TFile we want to read but don't know how many
|
||||
# bytes we need to read before the buffer is empty.
|
||||
result = ""
|
||||
var buffer = newString(buf_size)
|
||||
var bytesRead = buf_size
|
||||
while bytesRead == buf_size:
|
||||
bytesRead = readBuffer(file, addr(buffer[0]), buf_size)
|
||||
var buffer = newString(BufSize)
|
||||
var bytesRead = BufSize
|
||||
while bytesRead == BufSize:
|
||||
bytesRead = readBuffer(file, addr(buffer[0]), BufSize)
|
||||
result.add(buffer)
|
||||
|
||||
proc rawFileSize(file: TFile): int =
|
||||
|
|
@ -149,7 +161,7 @@ proc writeFile(filename, content: string) =
|
|||
finally:
|
||||
close(f)
|
||||
|
||||
proc EndOfFile(f: TFile): bool =
|
||||
proc endOfFile(f: TFile): bool =
|
||||
# do not blame me; blame the ANSI C standard this is so brain-damaged
|
||||
var c = fgetc(f)
|
||||
ungetc(c, f)
|
||||
|
|
@ -167,12 +179,12 @@ proc rawEchoNL() {.inline, compilerproc.} = write(stdout, "\n")
|
|||
when defined(windows) and not defined(useWinAnsi):
|
||||
include "system/widestrs"
|
||||
|
||||
proc wfopen(filename, mode: widecstring): pointer {.
|
||||
proc wfopen(filename, mode: WideCString): pointer {.
|
||||
importc: "_wfopen", nodecl.}
|
||||
proc wfreopen(filename, mode: widecstring, stream: TFile): TFile {.
|
||||
proc wfreopen(filename, mode: WideCString, stream: TFile): TFile {.
|
||||
importc: "_wfreopen", nodecl.}
|
||||
|
||||
proc fopen(filename, mode: CString): pointer =
|
||||
proc fopen(filename, mode: cstring): pointer =
|
||||
var f = newWideCString(filename)
|
||||
var m = newWideCString(mode)
|
||||
result = wfopen(f, m)
|
||||
|
|
@ -183,7 +195,7 @@ when defined(windows) and not defined(useWinAnsi):
|
|||
result = wfreopen(f, m, stream)
|
||||
|
||||
else:
|
||||
proc fopen(filename, mode: CString): pointer {.importc: "fopen", noDecl.}
|
||||
proc fopen(filename, mode: cstring): pointer {.importc: "fopen", noDecl.}
|
||||
proc freopen(filename, mode: cstring, stream: TFile): TFile {.
|
||||
importc: "freopen", nodecl.}
|
||||
|
||||
|
|
@ -194,9 +206,9 @@ const
|
|||
# should not be translated.
|
||||
|
||||
|
||||
proc Open(f: var TFile, filename: string,
|
||||
proc open(f: var TFile, filename: string,
|
||||
mode: TFileMode = fmRead,
|
||||
bufSize: int = -1): Bool =
|
||||
bufSize: int = -1): bool =
|
||||
var p: pointer = fopen(filename, FormatOpen[mode])
|
||||
result = (p != nil)
|
||||
f = cast[TFile](p)
|
||||
|
|
@ -217,23 +229,23 @@ proc open(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
|
|||
f = fdopen(filehandle, FormatOpen[mode])
|
||||
result = f != nil
|
||||
|
||||
proc fwrite(buf: Pointer, size, n: int, f: TFile): int {.
|
||||
proc fwrite(buf: pointer, size, n: int, f: TFile): int {.
|
||||
importc: "fwrite", noDecl.}
|
||||
|
||||
proc readBuffer(f: TFile, buffer: pointer, len: int): int =
|
||||
result = fread(buffer, 1, len, f)
|
||||
|
||||
proc ReadBytes(f: TFile, a: var openarray[int8], start, len: int): int =
|
||||
proc readBytes(f: TFile, a: var openArray[int8], start, len: int): int =
|
||||
result = readBuffer(f, addr(a[start]), len)
|
||||
|
||||
proc ReadChars(f: TFile, a: var openarray[char], start, len: int): int =
|
||||
proc readChars(f: TFile, a: var openArray[char], start, len: int): int =
|
||||
result = readBuffer(f, addr(a[start]), len)
|
||||
|
||||
{.push stackTrace:off, profiler:off.}
|
||||
proc writeBytes(f: TFile, a: openarray[int8], start, len: int): int =
|
||||
proc writeBytes(f: TFile, a: openArray[int8], start, len: int): int =
|
||||
var x = cast[ptr array[0..1000_000_000, int8]](a)
|
||||
result = writeBuffer(f, addr(x[start]), len)
|
||||
proc writeChars(f: TFile, a: openarray[char], start, len: int): int =
|
||||
proc writeChars(f: TFile, a: openArray[char], start, len: int): int =
|
||||
var x = cast[ptr array[0..1000_000_000, int8]](a)
|
||||
result = writeBuffer(f, addr(x[start]), len)
|
||||
proc writeBuffer(f: TFile, buffer: pointer, len: int): int =
|
||||
|
|
|
|||
|
|
@ -22,50 +22,53 @@ when defined(Windows):
|
|||
|
||||
TSysCond = THandle
|
||||
|
||||
proc InitSysLock(L: var TSysLock) {.stdcall, noSideEffect,
|
||||
proc initSysLock(L: var TSysLock) {.stdcall, noSideEffect,
|
||||
dynlib: "kernel32", importc: "InitializeCriticalSection".}
|
||||
## Initializes the lock `L`.
|
||||
|
||||
proc TryAcquireSysAux(L: var TSysLock): int32 {.stdcall, noSideEffect,
|
||||
proc tryAcquireSysAux(L: var TSysLock): int32 {.stdcall, noSideEffect,
|
||||
dynlib: "kernel32", importc: "TryEnterCriticalSection".}
|
||||
## Tries to acquire the lock `L`.
|
||||
|
||||
proc TryAcquireSys(L: var TSysLock): bool {.inline.} =
|
||||
proc tryAcquireSys(L: var TSysLock): bool {.inline.} =
|
||||
result = TryAcquireSysAux(L) != 0'i32
|
||||
|
||||
proc AcquireSys(L: var TSysLock) {.stdcall, noSideEffect,
|
||||
proc acquireSys(L: var TSysLock) {.stdcall, noSideEffect,
|
||||
dynlib: "kernel32", importc: "EnterCriticalSection".}
|
||||
## Acquires the lock `L`.
|
||||
|
||||
proc ReleaseSys(L: var TSysLock) {.stdcall, noSideEffect,
|
||||
proc releaseSys(L: var TSysLock) {.stdcall, noSideEffect,
|
||||
dynlib: "kernel32", importc: "LeaveCriticalSection".}
|
||||
## Releases the lock `L`.
|
||||
|
||||
proc DeinitSys(L: var TSysLock) {.stdcall, noSideEffect,
|
||||
proc deinitSys(L: var TSysLock) {.stdcall, noSideEffect,
|
||||
dynlib: "kernel32", importc: "DeleteCriticalSection".}
|
||||
|
||||
proc CreateEvent(lpEventAttributes: pointer,
|
||||
proc createEvent(lpEventAttributes: pointer,
|
||||
bManualReset, bInitialState: int32,
|
||||
lpName: cstring): TSysCond {.stdcall, noSideEffect,
|
||||
dynlib: "kernel32", importc: "CreateEventA".}
|
||||
|
||||
proc CloseHandle(hObject: THandle) {.stdcall, noSideEffect,
|
||||
proc closeHandle(hObject: THandle) {.stdcall, noSideEffect,
|
||||
dynlib: "kernel32", importc: "CloseHandle".}
|
||||
proc WaitForSingleObject(hHandle: THandle, dwMilliseconds: int32): int32 {.
|
||||
proc waitForSingleObject(hHandle: THandle, dwMilliseconds: int32): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "WaitForSingleObject".}
|
||||
|
||||
proc SignalSysCond(hEvent: TSysCond) {.stdcall, noSideEffect,
|
||||
proc signalSysCond(hEvent: TSysCond) {.stdcall, noSideEffect,
|
||||
dynlib: "kernel32", importc: "SetEvent".}
|
||||
|
||||
proc InitSysCond(cond: var TSysCond) {.inline.} =
|
||||
cond = CreateEvent(nil, 0'i32, 0'i32, nil)
|
||||
proc DeinitSysCond(cond: var TSysCond) {.inline.} =
|
||||
CloseHandle(cond)
|
||||
proc WaitSysCond(cond: var TSysCond, lock: var TSysLock) =
|
||||
proc initSysCond(cond: var TSysCond) {.inline.} =
|
||||
cond = createEvent(nil, 0'i32, 0'i32, nil)
|
||||
proc deinitSysCond(cond: var TSysCond) {.inline.} =
|
||||
closeHandle(cond)
|
||||
proc waitSysCond(cond: var TSysCond, lock: var TSysLock) =
|
||||
releaseSys(lock)
|
||||
discard WaitForSingleObject(cond, -1'i32)
|
||||
discard waitForSingleObject(cond, -1'i32)
|
||||
acquireSys(lock)
|
||||
|
||||
proc waitSysCondWindows(cond: var TSysCond) =
|
||||
discard waitForSingleObject(cond, -1'i32)
|
||||
|
||||
else:
|
||||
type
|
||||
TSysLock {.importc: "pthread_mutex_t", pure, final,
|
||||
|
|
@ -73,29 +76,29 @@ else:
|
|||
TSysCond {.importc: "pthread_cond_t", pure, final,
|
||||
header: "<sys/types.h>".} = object
|
||||
|
||||
proc InitSysLock(L: var TSysLock, attr: pointer = nil) {.
|
||||
proc initSysLock(L: var TSysLock, attr: pointer = nil) {.
|
||||
importc: "pthread_mutex_init", header: "<pthread.h>", noSideEffect.}
|
||||
|
||||
proc AcquireSys(L: var TSysLock) {.noSideEffect,
|
||||
proc acquireSys(L: var TSysLock) {.noSideEffect,
|
||||
importc: "pthread_mutex_lock", header: "<pthread.h>".}
|
||||
proc TryAcquireSysAux(L: var TSysLock): cint {.noSideEffect,
|
||||
proc tryAcquireSysAux(L: var TSysLock): cint {.noSideEffect,
|
||||
importc: "pthread_mutex_trylock", header: "<pthread.h>".}
|
||||
|
||||
proc TryAcquireSys(L: var TSysLock): bool {.inline.} =
|
||||
result = TryAcquireSysAux(L) == 0'i32
|
||||
proc tryAcquireSys(L: var TSysLock): bool {.inline.} =
|
||||
result = tryAcquireSysAux(L) == 0'i32
|
||||
|
||||
proc ReleaseSys(L: var TSysLock) {.noSideEffect,
|
||||
proc releaseSys(L: var TSysLock) {.noSideEffect,
|
||||
importc: "pthread_mutex_unlock", header: "<pthread.h>".}
|
||||
proc DeinitSys(L: var TSysLock) {.
|
||||
proc deinitSys(L: var TSysLock) {.
|
||||
importc: "pthread_mutex_destroy", header: "<pthread.h>".}
|
||||
|
||||
proc InitSysCond(cond: var TSysCond, cond_attr: pointer = nil) {.
|
||||
proc initSysCond(cond: var TSysCond, cond_attr: pointer = nil) {.
|
||||
importc: "pthread_cond_init", header: "<pthread.h>".}
|
||||
proc WaitSysCond(cond: var TSysCond, lock: var TSysLock) {.
|
||||
proc waitSysCond(cond: var TSysCond, lock: var TSysLock) {.
|
||||
importc: "pthread_cond_wait", header: "<pthread.h>".}
|
||||
proc SignalSysCond(cond: var TSysCond) {.
|
||||
proc signalSysCond(cond: var TSysCond) {.
|
||||
importc: "pthread_cond_signal", header: "<pthread.h>".}
|
||||
|
||||
proc DeinitSysCond(cond: var TSysCond) {.
|
||||
proc deinitSysCond(cond: var TSysCond) {.
|
||||
importc: "pthread_cond_destroy", header: "<pthread.h>".}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ proc copyStrLast(s: NimString, start, last: int): NimString {.compilerProc.} =
|
|||
if len > 0:
|
||||
result = rawNewString(len)
|
||||
result.len = len
|
||||
c_memcpy(result.data, addr(s.data[start]), len * sizeof(Char))
|
||||
c_memcpy(result.data, addr(s.data[start]), len * sizeof(char))
|
||||
#result.data[len] = '\0'
|
||||
else:
|
||||
result = rawNewString(len)
|
||||
|
|
@ -63,14 +63,14 @@ proc copyStrLast(s: NimString, start, last: int): NimString {.compilerProc.} =
|
|||
proc copyStr(s: NimString, start: int): NimString {.compilerProc.} =
|
||||
result = copyStrLast(s, start, s.len-1)
|
||||
|
||||
proc toNimStr(str: CString, len: int): NimString {.compilerProc.} =
|
||||
proc toNimStr(str: cstring, len: int): NimString {.compilerProc.} =
|
||||
result = rawNewString(len)
|
||||
result.len = len
|
||||
c_memcpy(result.data, str, (len+1) * sizeof(Char))
|
||||
c_memcpy(result.data, str, (len+1) * sizeof(char))
|
||||
#result.data[len] = '\0' # readline relies on this!
|
||||
|
||||
proc cstrToNimstr(str: CString): NimString {.compilerRtl.} =
|
||||
result = toNimstr(str, c_strlen(str))
|
||||
proc cstrToNimstr(str: cstring): NimString {.compilerRtl.} =
|
||||
result = toNimStr(str, c_strlen(str))
|
||||
|
||||
proc copyString(src: NimString): NimString {.compilerRtl.} =
|
||||
if src != nil:
|
||||
|
|
@ -79,7 +79,7 @@ proc copyString(src: NimString): NimString {.compilerRtl.} =
|
|||
else:
|
||||
result = rawNewString(src.space)
|
||||
result.len = src.len
|
||||
c_memcpy(result.data, src.data, (src.len + 1) * sizeof(Char))
|
||||
c_memcpy(result.data, src.data, (src.len + 1) * sizeof(char))
|
||||
|
||||
proc copyStringRC1(src: NimString): NimString {.compilerRtl.} =
|
||||
if src != nil:
|
||||
|
|
@ -98,8 +98,8 @@ proc hashString(s: string): int {.compilerproc.} =
|
|||
# the compiler needs exactly the same hash function!
|
||||
# this used to be used for efficient generation of string case statements
|
||||
var h = 0
|
||||
for i in 0..Len(s)-1:
|
||||
h = h +% Ord(s[i])
|
||||
for i in 0..len(s)-1:
|
||||
h = h +% ord(s[i])
|
||||
h = h +% h shl 10
|
||||
h = h xor (h shr 6)
|
||||
h = h +% h shl 3
|
||||
|
|
@ -150,10 +150,10 @@ proc addChar(s: NimString, c: char): NimString =
|
|||
# s = rawNewString(0);
|
||||
|
||||
proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} =
|
||||
if dest.len + addLen <= dest.space:
|
||||
if dest.len + addlen <= dest.space:
|
||||
result = dest
|
||||
else: # slow path:
|
||||
var sp = max(resize(dest.space), dest.len + addLen)
|
||||
var sp = max(resize(dest.space), dest.len + addlen)
|
||||
result = cast[NimString](growObj(dest, sizeof(TGenericSeq) + sp + 1))
|
||||
result.reserved = sp
|
||||
#result = rawNewString(sp)
|
||||
|
|
@ -236,7 +236,7 @@ proc nimIntToStr(x: int): string {.compilerRtl.} =
|
|||
result = newString(sizeof(x)*4)
|
||||
var i = 0
|
||||
var y = x
|
||||
while True:
|
||||
while true:
|
||||
var d = y div 10
|
||||
result[i] = chr(abs(int(y - d*10)) + ord('0'))
|
||||
inc(i)
|
||||
|
|
@ -259,7 +259,7 @@ proc nimInt64ToStr(x: int64): string {.compilerRtl.} =
|
|||
result = newString(sizeof(x)*4)
|
||||
var i = 0
|
||||
var y = x
|
||||
while True:
|
||||
while true:
|
||||
var d = y div 10
|
||||
result[i] = chr(abs(int(y - d*10)) + ord('0'))
|
||||
inc(i)
|
||||
|
|
@ -280,7 +280,7 @@ proc nimCharToStr(x: char): string {.compilerRtl.} =
|
|||
result = newString(1)
|
||||
result[0] = x
|
||||
|
||||
proc binaryStrSearch(x: openarray[string], y: string): int {.compilerproc.} =
|
||||
proc binaryStrSearch(x: openArray[string], y: string): int {.compilerproc.} =
|
||||
var
|
||||
a = 0
|
||||
b = len(x)
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@
|
|||
##
|
||||
## proc threadFunc(interval: tuple[a,b: int]) {.thread.} =
|
||||
## for i in interval.a..interval.b:
|
||||
## Acquire(L) # lock stdout
|
||||
## acquire(L) # lock stdout
|
||||
## echo i
|
||||
## Release(L)
|
||||
## release(L)
|
||||
##
|
||||
## InitLock(L)
|
||||
## initLock(L)
|
||||
##
|
||||
## for i in 0..high(thr):
|
||||
## createThread(thr[i], threadFunc, (i*10, i*10+5))
|
||||
|
|
@ -54,9 +54,9 @@ when defined(windows):
|
|||
TSysThread = THandle
|
||||
TWinThreadProc = proc (x: pointer): int32 {.stdcall.}
|
||||
|
||||
proc CreateThread(lpThreadAttributes: Pointer, dwStackSize: int32,
|
||||
proc createThread(lpThreadAttributes: pointer, dwStackSize: int32,
|
||||
lpStartAddress: TWinThreadProc,
|
||||
lpParameter: Pointer,
|
||||
lpParameter: pointer,
|
||||
dwCreationFlags: int32,
|
||||
lpThreadId: var int32): TSysThread {.
|
||||
stdcall, dynlib: "kernel32", importc: "CreateThread".}
|
||||
|
|
@ -67,23 +67,23 @@ when defined(windows):
|
|||
proc winResumeThread(hThread: TSysThread): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "ResumeThread".}
|
||||
|
||||
proc WaitForMultipleObjects(nCount: int32,
|
||||
proc waitForMultipleObjects(nCount: int32,
|
||||
lpHandles: ptr TSysThread,
|
||||
bWaitAll: int32,
|
||||
dwMilliseconds: int32): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
|
||||
|
||||
proc TerminateThread(hThread: TSysThread, dwExitCode: int32): int32 {.
|
||||
proc terminateThread(hThread: TSysThread, dwExitCode: int32): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "TerminateThread".}
|
||||
|
||||
type
|
||||
TThreadVarSlot = distinct int32
|
||||
|
||||
proc ThreadVarAlloc(): TThreadVarSlot {.
|
||||
proc threadVarAlloc(): TThreadVarSlot {.
|
||||
importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
|
||||
proc ThreadVarSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
|
||||
proc threadVarSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
|
||||
importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
|
||||
proc ThreadVarGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
|
||||
proc threadVarGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
|
||||
importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
|
||||
|
||||
else:
|
||||
|
|
@ -116,14 +116,14 @@ else:
|
|||
proc pthread_cancel(a1: TSysThread): cint {.
|
||||
importc: "pthread_cancel", header: "<pthread.h>".}
|
||||
|
||||
proc AcquireSysTimeoutAux(L: var TSysLock, timeout: var Ttimespec): cint {.
|
||||
proc acquireSysTimeoutAux(L: var TSysLock, timeout: var Ttimespec): cint {.
|
||||
importc: "pthread_mutex_timedlock", header: "<time.h>".}
|
||||
|
||||
proc AcquireSysTimeout(L: var TSysLock, msTimeout: int) {.inline.} =
|
||||
proc acquireSysTimeout(L: var TSysLock, msTimeout: int) {.inline.} =
|
||||
var a: Ttimespec
|
||||
a.tv_sec = msTimeout div 1000
|
||||
a.tv_nsec = (msTimeout mod 1000) * 1000
|
||||
var res = AcquireSysTimeoutAux(L, a)
|
||||
var res = acquireSysTimeoutAux(L, a)
|
||||
if res != 0'i32: raise newException(EResourceExhausted, $strerror(res))
|
||||
|
||||
type
|
||||
|
|
@ -141,11 +141,11 @@ else:
|
|||
proc pthread_setspecific(a1: TThreadVarSlot, a2: pointer): int32 {.
|
||||
importc: "pthread_setspecific", header: "<pthread.h>".}
|
||||
|
||||
proc ThreadVarAlloc(): TThreadVarSlot {.inline.} =
|
||||
proc threadVarAlloc(): TThreadVarSlot {.inline.} =
|
||||
discard pthread_key_create(addr(result), nil)
|
||||
proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.inline.} =
|
||||
proc threadVarSetValue(s: TThreadVarSlot, value: pointer) {.inline.} =
|
||||
discard pthread_setspecific(s, value)
|
||||
proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.inline.} =
|
||||
proc threadVarGetValue(s: TThreadVarSlot): pointer {.inline.} =
|
||||
result = pthread_getspecific(s)
|
||||
|
||||
when useStackMaskHack:
|
||||
|
|
@ -159,7 +159,7 @@ const
|
|||
when emulatedThreadVars:
|
||||
# the compiler generates this proc for us, so that we can get the size of
|
||||
# the thread local var block; we use this only for sanity checking though
|
||||
proc NimThreadVarsSize(): int {.noconv, importc: "NimThreadVarsSize".}
|
||||
proc nimThreadVarsSize(): int {.noconv, importc: "NimThreadVarsSize".}
|
||||
|
||||
# we preallocate a fixed size for thread local storage, so that no heap
|
||||
# allocations are needed. Currently less than 7K are used on a 64bit machine.
|
||||
|
|
@ -184,7 +184,7 @@ type
|
|||
# XXX it'd be more efficient to not use a global variable for the
|
||||
# thread storage slot, but to rely on the implementation to assign slot X
|
||||
# for us... ;-)
|
||||
var globalsSlot = ThreadVarAlloc()
|
||||
var globalsSlot = threadVarAlloc()
|
||||
#const globalsSlot = TThreadVarSlot(0)
|
||||
#sysAssert checkSlot.int == globalsSlot.int
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ when emulatedThreadVars:
|
|||
result = addr(cast[PGcThread](ThreadVarGetValue(globalsSlot)).tls)
|
||||
|
||||
when useStackMaskHack:
|
||||
proc MaskStackPointer(offset: int): pointer {.compilerRtl, inl.} =
|
||||
proc maskStackPointer(offset: int): pointer {.compilerRtl, inl.} =
|
||||
var x {.volatile.}: pointer
|
||||
x = addr(x)
|
||||
result = cast[pointer]((cast[int](x) and not ThreadStackMask) +%
|
||||
|
|
@ -205,7 +205,7 @@ when not defined(useNimRtl):
|
|||
|
||||
when not useStackMaskHack:
|
||||
var mainThread: TGcThread
|
||||
ThreadVarSetValue(globalsSlot, addr(mainThread))
|
||||
threadVarSetValue(globalsSlot, addr(mainThread))
|
||||
when not defined(createNimRtl): initStackBottom()
|
||||
initGC()
|
||||
|
||||
|
|
@ -220,18 +220,18 @@ when not defined(useNimRtl):
|
|||
|
||||
proc registerThread(t: PGcThread) =
|
||||
# we need to use the GC global lock here!
|
||||
AcquireSys(HeapLock)
|
||||
acquireSys(HeapLock)
|
||||
t.prev = nil
|
||||
t.next = threadList
|
||||
if threadList != nil:
|
||||
sysAssert(threadList.prev == nil, "threadList.prev == nil")
|
||||
threadList.prev = t
|
||||
threadList = t
|
||||
ReleaseSys(HeapLock)
|
||||
releaseSys(HeapLock)
|
||||
|
||||
proc unregisterThread(t: PGcThread) =
|
||||
# we need to use the GC global lock here!
|
||||
AcquireSys(HeapLock)
|
||||
acquireSys(HeapLock)
|
||||
if t == threadList: threadList = t.next
|
||||
if t.next != nil: t.next.prev = t.prev
|
||||
if t.prev != nil: t.prev.next = t.next
|
||||
|
|
@ -239,7 +239,7 @@ when not defined(useNimRtl):
|
|||
# code executes `destroyThread`:
|
||||
t.next = nil
|
||||
t.prev = nil
|
||||
ReleaseSys(HeapLock)
|
||||
releaseSys(HeapLock)
|
||||
|
||||
# on UNIX, the GC uses ``SIGFREEZE`` to tell every thread to stop so that
|
||||
# the GC can examine the stacks?
|
||||
|
|
@ -266,7 +266,7 @@ type
|
|||
when not defined(boehmgc) and not hasSharedHeap:
|
||||
proc deallocOsPages()
|
||||
|
||||
template ThreadProcWrapperBody(closure: expr) {.immediate.} =
|
||||
template threadProcWrapperBody(closure: expr) {.immediate.} =
|
||||
when defined(globalsSlot): ThreadVarSetValue(globalsSlot, closure)
|
||||
var t = cast[ptr TThread[TArg]](closure)
|
||||
when useStackMaskHack:
|
||||
|
|
@ -294,11 +294,11 @@ template ThreadProcWrapperBody(closure: expr) {.immediate.} =
|
|||
{.push stack_trace:off.}
|
||||
when defined(windows):
|
||||
proc threadProcWrapper[TArg](closure: pointer): int32 {.stdcall.} =
|
||||
ThreadProcWrapperBody(closure)
|
||||
# implicitely return 0
|
||||
threadProcWrapperBody(closure)
|
||||
# implicitly return 0
|
||||
else:
|
||||
proc threadProcWrapper[TArg](closure: pointer) {.noconv.} =
|
||||
ThreadProcWrapperBody(closure)
|
||||
threadProcWrapperBody(closure)
|
||||
{.pop.}
|
||||
|
||||
proc running*[TArg](t: TThread[TArg]): bool {.inline.} =
|
||||
|
|
@ -308,7 +308,7 @@ proc running*[TArg](t: TThread[TArg]): bool {.inline.} =
|
|||
proc joinThread*[TArg](t: TThread[TArg]) {.inline.} =
|
||||
## waits for the thread `t` to finish.
|
||||
when hostOS == "windows":
|
||||
discard WaitForSingleObject(t.sys, -1'i32)
|
||||
discard waitForSingleObject(t.sys, -1'i32)
|
||||
else:
|
||||
discard pthread_join(t.sys, nil)
|
||||
|
||||
|
|
@ -318,7 +318,7 @@ proc joinThreads*[TArg](t: varargs[TThread[TArg]]) =
|
|||
var a: array[0..255, TSysThread]
|
||||
sysAssert a.len >= t.len, "a.len >= t.len"
|
||||
for i in 0..t.high: a[i] = t[i].sys
|
||||
discard WaitForMultipleObjects(t.len.int32,
|
||||
discard waitForMultipleObjects(t.len.int32,
|
||||
cast[ptr TSysThread](addr(a)), 1, -1)
|
||||
else:
|
||||
for i in 0..t.high: joinThread(t[i])
|
||||
|
|
@ -346,7 +346,7 @@ proc createThread*[TArg](t: var TThread[TArg],
|
|||
when hasSharedHeap: t.stackSize = ThreadStackSize
|
||||
when hostOS == "windows":
|
||||
var dummyThreadId: int32
|
||||
t.sys = CreateThread(nil, ThreadStackSize, threadProcWrapper[TArg],
|
||||
t.sys = createThread(nil, ThreadStackSize, threadProcWrapper[TArg],
|
||||
addr(t), 0'i32, dummyThreadId)
|
||||
if t.sys <= 0:
|
||||
raise newException(EResourceExhausted, "cannot create thread")
|
||||
|
|
|
|||
|
|
@ -1,149 +1,153 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system
|
||||
## module! Do not import it directly!
|
||||
|
||||
type
|
||||
TUtf16Char* = distinct int16
|
||||
WideCString* = ref array[0.. 1_000_000, TUtf16Char]
|
||||
|
||||
proc len*(w: WideCString): int =
|
||||
## returns the length of a widestring. This traverses the whole string to
|
||||
## find the binary zero end marker!
|
||||
while int16(w[result]) != 0'i16: inc result
|
||||
|
||||
const
|
||||
UNI_REPLACEMENT_CHAR = TUtf16Char(0xFFFD'i16)
|
||||
UNI_MAX_BMP = 0x0000FFFF
|
||||
UNI_MAX_UTF16 = 0x0010FFFF
|
||||
UNI_MAX_UTF32 = 0x7FFFFFFF
|
||||
UNI_MAX_LEGAL_UTF32 = 0x0010FFFF
|
||||
|
||||
halfShift = 10
|
||||
halfBase = 0x0010000
|
||||
halfMask = 0x3FF
|
||||
|
||||
UNI_SUR_HIGH_START = 0xD800
|
||||
UNI_SUR_HIGH_END = 0xDBFF
|
||||
UNI_SUR_LOW_START = 0xDC00
|
||||
UNI_SUR_LOW_END = 0xDFFF
|
||||
|
||||
template ones(n: expr): expr = ((1 shl n)-1)
|
||||
|
||||
template fastRuneAt(s: cstring, i: int, result: expr, doInc = true) =
|
||||
## Returns the unicode character ``s[i]`` in `result`. If ``doInc == true``
|
||||
## `i` is incremented by the number of bytes that have been processed.
|
||||
bind ones
|
||||
|
||||
if ord(s[i]) <=% 127:
|
||||
result = ord(s[i])
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 5 == 0b110:
|
||||
#assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and (ones(5))) shl 6 or (ord(s[i+1]) and ones(6))
|
||||
when doInc: inc(i, 2)
|
||||
elif ord(s[i]) shr 4 == 0b1110:
|
||||
#assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
#assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and ones(4)) shl 12 or
|
||||
(ord(s[i+1]) and ones(6)) shl 6 or
|
||||
(ord(s[i+2]) and ones(6))
|
||||
when doInc: inc(i, 3)
|
||||
elif ord(s[i]) shr 3 == 0b11110:
|
||||
#assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
#assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
#assert(ord(s[i+3]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and ones(3)) shl 18 or
|
||||
(ord(s[i+1]) and ones(6)) shl 12 or
|
||||
(ord(s[i+2]) and ones(6)) shl 6 or
|
||||
(ord(s[i+3]) and ones(6))
|
||||
when doInc: inc(i, 4)
|
||||
else:
|
||||
result = 0xFFFD
|
||||
when doInc: inc(i)
|
||||
|
||||
iterator runes(s: cstring): int =
|
||||
var
|
||||
i = 0
|
||||
result: int
|
||||
while s[i] != '\0':
|
||||
fastRuneAt(s, i, result, true)
|
||||
yield result
|
||||
|
||||
proc newWideCString*(source: cstring, L: int): WideCString =
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Nimrod support for C/C++'s `wide strings`:idx:. This is part of the system
|
||||
## module! Do not import it directly!
|
||||
|
||||
when not defined(NimString):
|
||||
{.error: "You must not import this module explicitly".}
|
||||
|
||||
type
|
||||
TUtf16Char* = distinct int16
|
||||
WideCString* = ref array[0.. 1_000_000, TUtf16Char]
|
||||
|
||||
proc len*(w: WideCString): int =
|
||||
## returns the length of a widestring. This traverses the whole string to
|
||||
## find the binary zero end marker!
|
||||
while int16(w[result]) != 0'i16: inc result
|
||||
|
||||
const
|
||||
UNI_REPLACEMENT_CHAR = TUtf16Char(0xFFFD'i16)
|
||||
UNI_MAX_BMP = 0x0000FFFF
|
||||
UNI_MAX_UTF16 = 0x0010FFFF
|
||||
UNI_MAX_UTF32 = 0x7FFFFFFF
|
||||
UNI_MAX_LEGAL_UTF32 = 0x0010FFFF
|
||||
|
||||
halfShift = 10
|
||||
halfBase = 0x0010000
|
||||
halfMask = 0x3FF
|
||||
|
||||
UNI_SUR_HIGH_START = 0xD800
|
||||
UNI_SUR_HIGH_END = 0xDBFF
|
||||
UNI_SUR_LOW_START = 0xDC00
|
||||
UNI_SUR_LOW_END = 0xDFFF
|
||||
|
||||
template ones(n: expr): expr = ((1 shl n)-1)
|
||||
|
||||
template fastRuneAt(s: cstring, i: int, result: expr, doInc = true) =
|
||||
## Returns the unicode character ``s[i]`` in `result`. If ``doInc == true``
|
||||
## `i` is incremented by the number of bytes that have been processed.
|
||||
bind ones
|
||||
|
||||
if ord(s[i]) <=% 127:
|
||||
result = ord(s[i])
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 5 == 0b110:
|
||||
#assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and (ones(5))) shl 6 or (ord(s[i+1]) and ones(6))
|
||||
when doInc: inc(i, 2)
|
||||
elif ord(s[i]) shr 4 == 0b1110:
|
||||
#assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
#assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and ones(4)) shl 12 or
|
||||
(ord(s[i+1]) and ones(6)) shl 6 or
|
||||
(ord(s[i+2]) and ones(6))
|
||||
when doInc: inc(i, 3)
|
||||
elif ord(s[i]) shr 3 == 0b11110:
|
||||
#assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
#assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
#assert(ord(s[i+3]) shr 6 == 0b10)
|
||||
result = (ord(s[i]) and ones(3)) shl 18 or
|
||||
(ord(s[i+1]) and ones(6)) shl 12 or
|
||||
(ord(s[i+2]) and ones(6)) shl 6 or
|
||||
(ord(s[i+3]) and ones(6))
|
||||
when doInc: inc(i, 4)
|
||||
else:
|
||||
result = 0xFFFD
|
||||
when doInc: inc(i)
|
||||
|
||||
iterator runes(s: cstring): int =
|
||||
var
|
||||
i = 0
|
||||
result: int
|
||||
while s[i] != '\0':
|
||||
fastRuneAt(s, i, result, true)
|
||||
yield result
|
||||
|
||||
proc newWideCString*(source: cstring, L: int): WideCString =
|
||||
unsafeNew(result, L * 4 + 2)
|
||||
#result = cast[wideCString](alloc(L * 4 + 2))
|
||||
var d = 0
|
||||
for ch in runes(source):
|
||||
if ch <=% UNI_MAX_BMP:
|
||||
if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_LOW_END:
|
||||
result[d] = UNI_REPLACEMENT_CHAR
|
||||
else:
|
||||
result[d] = TUtf16Char(toU16(ch))
|
||||
elif ch >% UNI_MAX_UTF16:
|
||||
result[d] = UNI_REPLACEMENT_CHAR
|
||||
else:
|
||||
let ch = ch -% halfBase
|
||||
result[d] = TUtf16Char(toU16((ch shr halfShift) +% UNI_SUR_HIGH_START))
|
||||
inc d
|
||||
result[d] = TUtf16Char(toU16((ch and halfMask) +% UNI_SUR_LOW_START))
|
||||
inc d
|
||||
result[d] = TUtf16Char(0'i16)
|
||||
|
||||
proc newWideCString*(s: cstring): WideCString =
|
||||
if s.isNil: return nil
|
||||
|
||||
when not defined(c_strlen):
|
||||
proc c_strlen(a: CString): int {.nodecl, noSideEffect, importc: "strlen".}
|
||||
|
||||
let L = cstrlen(s)
|
||||
result = newWideCString(s, L)
|
||||
|
||||
proc newWideCString*(s: string): WideCString =
|
||||
result = newWideCString(s, s.len)
|
||||
|
||||
proc `$`*(w: wideCString, estimate: int): string =
|
||||
result = newStringOfCap(estimate + estimate shr 2)
|
||||
|
||||
var i = 0
|
||||
while w[i].int16 != 0'i16:
|
||||
var ch = w[i].int
|
||||
inc i
|
||||
if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_HIGH_END:
|
||||
# If the 16 bits following the high surrogate are in the source buffer...
|
||||
let ch2 = w[i].int
|
||||
# If it's a low surrogate, convert to UTF32:
|
||||
if ch2 >=% UNI_SUR_LOW_START and ch2 <=% UNI_SUR_LOW_END:
|
||||
ch = ((ch -% UNI_SUR_HIGH_START) shr halfShift) +%
|
||||
(ch2 -% UNI_SUR_LOW_START) +% halfBase
|
||||
inc i
|
||||
|
||||
if ch <=% 127:
|
||||
result.add chr(ch)
|
||||
elif ch <=% 0x07FF:
|
||||
result.add chr((ch shr 6) or 0b110_00000)
|
||||
result.add chr((ch and ones(6)) or 0b10_000000)
|
||||
elif ch <=% 0xFFFF:
|
||||
result.add chr(ch shr 12 or 0b1110_0000)
|
||||
result.add chr(ch shr 6 and ones(6) or 0b10_0000_00)
|
||||
result.add chr(ch and ones(6) or 0b10_0000_00)
|
||||
elif ch <=% 0x0010FFFF:
|
||||
result.add chr(ch shr 18 or 0b1111_0000)
|
||||
result.add chr(ch shr 12 and ones(6) or 0b10_0000_00)
|
||||
result.add chr(ch shr 6 and ones(6) or 0b10_0000_00)
|
||||
result.add chr(ch and ones(6) or 0b10_0000_00)
|
||||
else:
|
||||
# replacement char:
|
||||
result.add chr(0xFFFD shr 12 or 0b1110_0000)
|
||||
result.add chr(0xFFFD shr 6 and ones(6) or 0b10_0000_00)
|
||||
result.add chr(0xFFFD and ones(6) or 0b10_0000_00)
|
||||
|
||||
proc `$`*(s: WideCString): string =
|
||||
result = s $ 80
|
||||
#result = cast[wideCString](alloc(L * 4 + 2))
|
||||
var d = 0
|
||||
for ch in runes(source):
|
||||
if ch <=% UNI_MAX_BMP:
|
||||
if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_LOW_END:
|
||||
result[d] = UNI_REPLACEMENT_CHAR
|
||||
else:
|
||||
result[d] = TUtf16Char(toU16(ch))
|
||||
elif ch >% UNI_MAX_UTF16:
|
||||
result[d] = UNI_REPLACEMENT_CHAR
|
||||
else:
|
||||
let ch = ch -% halfBase
|
||||
result[d] = TUtf16Char(toU16((ch shr halfShift) +% UNI_SUR_HIGH_START))
|
||||
inc d
|
||||
result[d] = TUtf16Char(toU16((ch and halfMask) +% UNI_SUR_LOW_START))
|
||||
inc d
|
||||
result[d] = TUtf16Char(0'i16)
|
||||
|
||||
proc newWideCString*(s: cstring): WideCString =
|
||||
if s.isNil: return nil
|
||||
|
||||
when not defined(c_strlen):
|
||||
proc c_strlen(a: cstring): int {.
|
||||
header: "<string.h>", noSideEffect, importc: "strlen".}
|
||||
|
||||
let L = c_strlen(s)
|
||||
result = newWideCString(s, L)
|
||||
|
||||
proc newWideCString*(s: string): WideCString =
|
||||
result = newWideCString(s, s.len)
|
||||
|
||||
proc `$`*(w: WideCString, estimate: int): string =
|
||||
result = newStringOfCap(estimate + estimate shr 2)
|
||||
|
||||
var i = 0
|
||||
while w[i].int16 != 0'i16:
|
||||
var ch = w[i].int
|
||||
inc i
|
||||
if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_HIGH_END:
|
||||
# If the 16 bits following the high surrogate are in the source buffer...
|
||||
let ch2 = w[i].int
|
||||
# If it's a low surrogate, convert to UTF32:
|
||||
if ch2 >=% UNI_SUR_LOW_START and ch2 <=% UNI_SUR_LOW_END:
|
||||
ch = ((ch -% UNI_SUR_HIGH_START) shr halfShift) +%
|
||||
(ch2 -% UNI_SUR_LOW_START) +% halfBase
|
||||
inc i
|
||||
|
||||
if ch <=% 127:
|
||||
result.add chr(ch)
|
||||
elif ch <=% 0x07FF:
|
||||
result.add chr((ch shr 6) or 0b110_00000)
|
||||
result.add chr((ch and ones(6)) or 0b10_000000)
|
||||
elif ch <=% 0xFFFF:
|
||||
result.add chr(ch shr 12 or 0b1110_0000)
|
||||
result.add chr(ch shr 6 and ones(6) or 0b10_0000_00)
|
||||
result.add chr(ch and ones(6) or 0b10_0000_00)
|
||||
elif ch <=% 0x0010FFFF:
|
||||
result.add chr(ch shr 18 or 0b1111_0000)
|
||||
result.add chr(ch shr 12 and ones(6) or 0b10_0000_00)
|
||||
result.add chr(ch shr 6 and ones(6) or 0b10_0000_00)
|
||||
result.add chr(ch and ones(6) or 0b10_0000_00)
|
||||
else:
|
||||
# replacement char:
|
||||
result.add chr(0xFFFD shr 12 or 0b1110_0000)
|
||||
result.add chr(0xFFFD shr 6 and ones(6) or 0b10_0000_00)
|
||||
result.add chr(0xFFFD and ones(6) or 0b10_0000_00)
|
||||
|
||||
proc `$`*(s: WideCString): string =
|
||||
result = s $ 80
|
||||
|
|
|
|||
|
|
@ -21856,15 +21856,9 @@ proc InflateRect*(lprc: var TRect, dx, dy: int): WINBOOL{.stdcall,
|
|||
dynlib: "user32", importc: "InflateRect".}
|
||||
proc InitializeAcl*(pAcl: var TACL, nAclLength, dwAclRevision: DWORD): WINBOOL{.
|
||||
stdcall, dynlib: "advapi32", importc: "InitializeAcl".}
|
||||
proc InitializeCriticalSectionAndSpinCount*(
|
||||
lpCriticalSection: var TRTLCriticalSection, dwSpinCount: DWORD): WINBOOL{.
|
||||
stdcall, dynlib: "kernel32",
|
||||
importc: "InitializeCriticalSectionAndSpinCount".}
|
||||
proc InitializeSid*(Sid: Pointer, pIdentifierAuthority: TSIDIdentifierAuthority,
|
||||
nSubAuthorityCount: int8): WINBOOL{.stdcall,
|
||||
dynlib: "advapi32", importc: "InitializeSid".}
|
||||
proc InsertMenuItem*(p1: HMENU, p2: UINT, p3: WINBOOL, p4: TMenuItemInfo): WINBOOL{.
|
||||
stdcall, dynlib: "user32", importc: "InsertMenuItemA".}
|
||||
proc InsertMenuItemA*(p1: HMENU, p2: UINT, p3: WINBOOL, p4: TMenuItemInfoA): WINBOOL{.
|
||||
stdcall, dynlib: "user32", importc: "InsertMenuItemA".}
|
||||
#function InsertMenuItemW(p1: HMENU; p2: UINT; p3: WINBOOL; const p4: TMenuItemInfoW): WINBOOL; stdcall; external 'user32' name 'InsertMenuItemW';
|
||||
|
|
@ -22362,11 +22356,6 @@ proc SetConsoleCursorInfo*(hConsoleOutput: THandle,
|
|||
lpConsoleCursorInfo: TConsoleCursorInfo): WINBOOL{.
|
||||
stdcall, dynlib: "kernel32", importc: "SetConsoleCursorInfo".}
|
||||
#function SetConsoleWindowInfo(hConsoleOutput: THandle; bAbsolute: WINBOOL; const lpConsoleWindow: TSmallRect): WINBOOL; stdcall; external 'kernel32' name 'SetConsoleWindowInfo';
|
||||
proc SetCriticalSectionSpinCount*(lpCriticalSection: var TRTLCriticalSection,
|
||||
dwSpinCount: DWORD): DWORD{.stdcall,
|
||||
dynlib: "kernel32", importc: "SetCriticalSectionSpinCount".}
|
||||
proc SetDeviceGammaRamp*(DC: HDC, Ramp: pointer): WINBOOL{.stdcall,
|
||||
dynlib: "gdi32", importc: "SetDeviceGammaRamp".}
|
||||
proc SetDIBColorTable*(DC: HDC, p2, p3: UINT, RGBQuadSTructs: pointer): UINT{.
|
||||
stdcall, dynlib: "gdi32", importc: "SetDIBColorTable".}
|
||||
proc SetDIBits*(DC: HDC, Bitmap: HBITMAP, StartScan, NumScans: UINT,
|
||||
|
|
@ -22476,8 +22465,6 @@ proc TranslateMDISysAccel*(hWndClient: HWND, lpMsg: TMsg): WINBOOL{.stdcall,
|
|||
proc TranslateMessage*(lpMsg: TMsg): WINBOOL{.stdcall, dynlib: "user32",
|
||||
importc: "TranslateMessage".}
|
||||
#function TransparentDIBits(DC: HDC; p2, p3, p4, p5: Integer; const p6: Pointer; const p7: PBitmapInfo; p8: UINT; p9, p10, p11, p12: Integer; p13: UINT): WINBOOL;stdcall; external 'gdi32' name 'TransparentDIBits';
|
||||
proc TryEnterCriticalSection*(lpCriticalSection: var TRTLCriticalSection): WINBOOL{.
|
||||
stdcall, dynlib: "kernel32", importc: "TryEnterCriticalSection".}
|
||||
proc UnhandledExceptionFilter*(ExceptionInfo: TExceptionPointers): int32{.
|
||||
stdcall, dynlib: "kernel32", importc: "UnhandledExceptionFilter".}
|
||||
proc UnionRect*(lprcDst: var TRect, lprcSrc1, lprcSrc2: TRect): WINBOOL{.
|
||||
|
|
@ -22847,12 +22834,6 @@ proc SUBLANGID*(lgid: int32): int32 =
|
|||
# return type might be wrong
|
||||
result = toU16(lgid) shr 10'i16
|
||||
|
||||
proc LANGIDFROMLCID*(lcid: int32): int16 =
|
||||
result = toU16(lcid)
|
||||
|
||||
proc SORTIDFROMLCID*(lcid: int32): int16 =
|
||||
result = toU16((lcid and 0x000FFFFF'i32) shr 16'i32)
|
||||
|
||||
proc MAKELCID*(lgid, srtid: int32): DWORD =
|
||||
result = toU32(srtid shl 16'i32 or lgid and 0xffff'i32)
|
||||
|
||||
|
|
|
|||
|
|
@ -42,13 +42,13 @@ type
|
|||
wShowWindow*: int16
|
||||
cbReserved2*: int16
|
||||
lpReserved2*: pointer
|
||||
hStdInput*: THANDLE
|
||||
hStdOutput*: THANDLE
|
||||
hStdError*: THANDLE
|
||||
hStdInput*: THandle
|
||||
hStdOutput*: THandle
|
||||
hStdError*: THandle
|
||||
|
||||
TPROCESS_INFORMATION* {.final, pure.} = object
|
||||
hProcess*: THANDLE
|
||||
hThread*: THANDLE
|
||||
hProcess*: THandle
|
||||
hThread*: THandle
|
||||
dwProcessId*: int32
|
||||
dwThreadId*: int32
|
||||
|
||||
|
|
@ -92,39 +92,39 @@ const
|
|||
DETACHED_PROCESS* = 8'i32
|
||||
|
||||
SW_SHOWNORMAL* = 1'i32
|
||||
INVALID_HANDLE_VALUE* = THANDLE(-1)
|
||||
INVALID_HANDLE_VALUE* = THandle(-1)
|
||||
|
||||
CREATE_UNICODE_ENVIRONMENT* = 1024'i32
|
||||
|
||||
proc CloseHandle*(hObject: THANDLE): WINBOOL {.stdcall, dynlib: "kernel32",
|
||||
proc closeHandle*(hObject: THandle): WINBOOL {.stdcall, dynlib: "kernel32",
|
||||
importc: "CloseHandle".}
|
||||
|
||||
proc ReadFile*(hFile: THandle, Buffer: pointer, nNumberOfBytesToRead: int32,
|
||||
proc readFile*(hFile: THandle, Buffer: pointer, nNumberOfBytesToRead: int32,
|
||||
lpNumberOfBytesRead: var int32, lpOverlapped: pointer): WINBOOL{.
|
||||
stdcall, dynlib: "kernel32", importc: "ReadFile".}
|
||||
|
||||
proc WriteFile*(hFile: THandle, Buffer: pointer, nNumberOfBytesToWrite: int32,
|
||||
proc writeFile*(hFile: THandle, Buffer: pointer, nNumberOfBytesToWrite: int32,
|
||||
lpNumberOfBytesWritten: var int32,
|
||||
lpOverlapped: pointer): WINBOOL{.
|
||||
stdcall, dynlib: "kernel32", importc: "WriteFile".}
|
||||
|
||||
proc CreatePipe*(hReadPipe, hWritePipe: var THandle,
|
||||
proc createPipe*(hReadPipe, hWritePipe: var THandle,
|
||||
lpPipeAttributes: var TSECURITY_ATTRIBUTES,
|
||||
nSize: int32): WINBOOL{.
|
||||
stdcall, dynlib: "kernel32", importc: "CreatePipe".}
|
||||
|
||||
when useWinUnicode:
|
||||
proc CreateProcessW*(lpApplicationName, lpCommandLine: widecstring,
|
||||
proc createProcessW*(lpApplicationName, lpCommandLine: WideCString,
|
||||
lpProcessAttributes: ptr TSECURITY_ATTRIBUTES,
|
||||
lpThreadAttributes: ptr TSECURITY_ATTRIBUTES,
|
||||
bInheritHandles: WINBOOL, dwCreationFlags: int32,
|
||||
lpEnvironment, lpCurrentDirectory: widecstring,
|
||||
lpEnvironment, lpCurrentDirectory: WideCString,
|
||||
lpStartupInfo: var TSTARTUPINFO,
|
||||
lpProcessInformation: var TPROCESS_INFORMATION): WINBOOL{.
|
||||
stdcall, dynlib: "kernel32", importc: "CreateProcessW".}
|
||||
|
||||
else:
|
||||
proc CreateProcessA*(lpApplicationName, lpCommandLine: cstring,
|
||||
proc createProcessA*(lpApplicationName, lpCommandLine: cstring,
|
||||
lpProcessAttributes: ptr TSECURITY_ATTRIBUTES,
|
||||
lpThreadAttributes: ptr TSECURITY_ATTRIBUTES,
|
||||
bInheritHandles: WINBOOL, dwCreationFlags: int32,
|
||||
|
|
@ -134,74 +134,76 @@ else:
|
|||
stdcall, dynlib: "kernel32", importc: "CreateProcessA".}
|
||||
|
||||
|
||||
proc SuspendThread*(hThread: THANDLE): int32 {.stdcall, dynlib: "kernel32",
|
||||
proc suspendThread*(hThread: THandle): int32 {.stdcall, dynlib: "kernel32",
|
||||
importc: "SuspendThread".}
|
||||
proc ResumeThread*(hThread: THANDLE): int32 {.stdcall, dynlib: "kernel32",
|
||||
proc resumeThread*(hThread: THandle): int32 {.stdcall, dynlib: "kernel32",
|
||||
importc: "ResumeThread".}
|
||||
|
||||
proc WaitForSingleObject*(hHandle: THANDLE, dwMilliseconds: int32): int32 {.
|
||||
proc waitForSingleObject*(hHandle: THandle, dwMilliseconds: int32): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "WaitForSingleObject".}
|
||||
|
||||
proc TerminateProcess*(hProcess: THANDLE, uExitCode: int): WINBOOL {.stdcall,
|
||||
proc terminateProcess*(hProcess: THandle, uExitCode: int): WINBOOL {.stdcall,
|
||||
dynlib: "kernel32", importc: "TerminateProcess".}
|
||||
|
||||
proc GetExitCodeProcess*(hProcess: THANDLE, lpExitCode: var int32): WINBOOL {.
|
||||
proc getExitCodeProcess*(hProcess: THandle, lpExitCode: var int32): WINBOOL {.
|
||||
stdcall, dynlib: "kernel32", importc: "GetExitCodeProcess".}
|
||||
|
||||
proc GetStdHandle*(nStdHandle: int32): THANDLE {.stdcall, dynlib: "kernel32",
|
||||
proc getStdHandle*(nStdHandle: int32): THandle {.stdcall, dynlib: "kernel32",
|
||||
importc: "GetStdHandle".}
|
||||
proc SetStdHandle*(nStdHandle: int32, hHandle: THANDLE): WINBOOL {.stdcall,
|
||||
proc setStdHandle*(nStdHandle: int32, hHandle: THandle): WINBOOL {.stdcall,
|
||||
dynlib: "kernel32", importc: "SetStdHandle".}
|
||||
proc FlushFileBuffers*(hFile: THANDLE): WINBOOL {.stdcall, dynlib: "kernel32",
|
||||
proc flushFileBuffers*(hFile: THandle): WINBOOL {.stdcall, dynlib: "kernel32",
|
||||
importc: "FlushFileBuffers".}
|
||||
|
||||
proc GetLastError*(): int32 {.importc, stdcall, dynlib: "kernel32".}
|
||||
proc getLastError*(): int32 {.importc: "GetLastError",
|
||||
stdcall, dynlib: "kernel32".}
|
||||
|
||||
when useWinUnicode:
|
||||
proc FormatMessageW*(dwFlags: int32, lpSource: pointer,
|
||||
proc formatMessageW*(dwFlags: int32, lpSource: pointer,
|
||||
dwMessageId, dwLanguageId: int32,
|
||||
lpBuffer: pointer, nSize: int32,
|
||||
Arguments: pointer): int32 {.
|
||||
importc, stdcall, dynlib: "kernel32".}
|
||||
importc: "FormatMessageW", stdcall, dynlib: "kernel32".}
|
||||
else:
|
||||
proc FormatMessageA*(dwFlags: int32, lpSource: pointer,
|
||||
proc formatMessageA*(dwFlags: int32, lpSource: pointer,
|
||||
dwMessageId, dwLanguageId: int32,
|
||||
lpBuffer: pointer, nSize: int32,
|
||||
Arguments: pointer): int32 {.
|
||||
importc, stdcall, dynlib: "kernel32".}
|
||||
importc: "FormatMessageA", stdcall, dynlib: "kernel32".}
|
||||
|
||||
proc LocalFree*(p: pointer) {.importc, stdcall, dynlib: "kernel32".}
|
||||
proc localFree*(p: pointer) {.
|
||||
importc: "LocalFree", stdcall, dynlib: "kernel32".}
|
||||
|
||||
when useWinUnicode:
|
||||
proc GetCurrentDirectoryW*(nBufferLength: int32,
|
||||
lpBuffer: widecstring): int32 {.
|
||||
importc, dynlib: "kernel32", stdcall.}
|
||||
proc SetCurrentDirectoryW*(lpPathName: widecstring): int32 {.
|
||||
importc, dynlib: "kernel32", stdcall.}
|
||||
proc CreateDirectoryW*(pathName: widecstring, security: Pointer=nil): int32 {.
|
||||
proc getCurrentDirectoryW*(nBufferLength: int32,
|
||||
lpBuffer: WideCString): int32 {.
|
||||
importc: "GetCurrentDirectoryW", dynlib: "kernel32", stdcall.}
|
||||
proc setCurrentDirectoryW*(lpPathName: WideCString): int32 {.
|
||||
importc: "SetCurrentDirectoryW", dynlib: "kernel32", stdcall.}
|
||||
proc createDirectoryW*(pathName: WideCString, security: pointer=nil): int32 {.
|
||||
importc: "CreateDirectoryW", dynlib: "kernel32", stdcall.}
|
||||
proc RemoveDirectoryW*(lpPathName: widecstring): int32 {.
|
||||
importc, dynlib: "kernel32", stdcall.}
|
||||
proc SetEnvironmentVariableW*(lpName, lpValue: widecstring): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc.}
|
||||
proc removeDirectoryW*(lpPathName: WideCString): int32 {.
|
||||
importc: "RemoveDirectoryW", dynlib: "kernel32", stdcall.}
|
||||
proc setEnvironmentVariableW*(lpName, lpValue: WideCString): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableW".}
|
||||
|
||||
proc GetModuleFileNameW*(handle: THandle, buf: wideCString,
|
||||
size: int32): int32 {.importc,
|
||||
proc getModuleFileNameW*(handle: THandle, buf: WideCString,
|
||||
size: int32): int32 {.importc: "GetModuleFileNameW",
|
||||
dynlib: "kernel32", stdcall.}
|
||||
else:
|
||||
proc GetCurrentDirectoryA*(nBufferLength: int32, lpBuffer: cstring): int32 {.
|
||||
importc, dynlib: "kernel32", stdcall.}
|
||||
proc SetCurrentDirectoryA*(lpPathName: cstring): int32 {.
|
||||
importc, dynlib: "kernel32", stdcall.}
|
||||
proc CreateDirectoryA*(pathName: cstring, security: Pointer=nil): int32 {.
|
||||
proc getCurrentDirectoryA*(nBufferLength: int32, lpBuffer: cstring): int32 {.
|
||||
importc: "GetCurrentDirectoryA", dynlib: "kernel32", stdcall.}
|
||||
proc setCurrentDirectoryA*(lpPathName: cstring): int32 {.
|
||||
importc: "SetCurrentDirectoryA", dynlib: "kernel32", stdcall.}
|
||||
proc createDirectoryA*(pathName: cstring, security: Pointer=nil): int32 {.
|
||||
importc: "CreateDirectoryA", dynlib: "kernel32", stdcall.}
|
||||
proc RemoveDirectoryA*(lpPathName: cstring): int32 {.
|
||||
importc, dynlib: "kernel32", stdcall.}
|
||||
proc SetEnvironmentVariableA*(lpName, lpValue: cstring): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc.}
|
||||
proc removeDirectoryA*(lpPathName: cstring): int32 {.
|
||||
importc: "RemoveDirectoryA", dynlib: "kernel32", stdcall.}
|
||||
proc setEnvironmentVariableA*(lpName, lpValue: cstring): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableA".}
|
||||
|
||||
proc GetModuleFileNameA*(handle: THandle, buf: CString, size: int32): int32 {.
|
||||
importc, dynlib: "kernel32", stdcall.}
|
||||
proc getModuleFileNameA*(handle: THandle, buf: CString, size: int32): int32 {.
|
||||
importc: "GetModuleFileNameA", dynlib: "kernel32", stdcall.}
|
||||
|
||||
const
|
||||
FILE_ATTRIBUTE_ARCHIVE* = 32'i32
|
||||
|
|
@ -228,91 +230,97 @@ type
|
|||
cAlternateFileName*: array[0..13, TWinChar]
|
||||
|
||||
when useWinUnicode:
|
||||
proc FindFirstFileW*(lpFileName: widecstring,
|
||||
lpFindFileData: var TWIN32_FIND_DATA): THANDLE {.
|
||||
proc findFirstFileW*(lpFileName: WideCString,
|
||||
lpFindFileData: var TWIN32_FIND_DATA): THandle {.
|
||||
stdcall, dynlib: "kernel32", importc: "FindFirstFileW".}
|
||||
proc FindNextFileW*(hFindFile: THANDLE,
|
||||
proc findNextFileW*(hFindFile: THandle,
|
||||
lpFindFileData: var TWIN32_FIND_DATA): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "FindNextFileW".}
|
||||
else:
|
||||
proc FindFirstFileA*(lpFileName: cstring,
|
||||
proc findFirstFileA*(lpFileName: cstring,
|
||||
lpFindFileData: var TWIN32_FIND_DATA): THANDLE {.
|
||||
stdcall, dynlib: "kernel32", importc: "FindFirstFileA".}
|
||||
proc FindNextFileA*(hFindFile: THANDLE,
|
||||
proc findNextFileA*(hFindFile: THANDLE,
|
||||
lpFindFileData: var TWIN32_FIND_DATA): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "FindNextFileA".}
|
||||
|
||||
proc FindClose*(hFindFile: THANDLE) {.stdcall, dynlib: "kernel32",
|
||||
proc findClose*(hFindFile: THandle) {.stdcall, dynlib: "kernel32",
|
||||
importc: "FindClose".}
|
||||
|
||||
when useWinUnicode:
|
||||
proc GetFullPathNameW*(lpFileName: widecstring, nBufferLength: int32,
|
||||
lpBuffer: widecstring,
|
||||
lpFilePart: var widecstring): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc.}
|
||||
proc GetFileAttributesW*(lpFileName: widecstring): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc.}
|
||||
proc SetFileAttributesW*(lpFileName: widecstring,
|
||||
proc getFullPathNameW*(lpFileName: WideCString, nBufferLength: int32,
|
||||
lpBuffer: WideCString,
|
||||
lpFilePart: var WideCString): int32 {.
|
||||
stdcall, dynlib: "kernel32",
|
||||
importc: "GetFullPathNameW".}
|
||||
proc getFileAttributesW*(lpFileName: WideCString): int32 {.
|
||||
stdcall, dynlib: "kernel32",
|
||||
importc: "GetFileAttributesW".}
|
||||
proc setFileAttributesW*(lpFileName: WideCString,
|
||||
dwFileAttributes: int32): WINBOOL {.
|
||||
stdcall, dynlib: "kernel32", importc: "SetFileAttributesW".}
|
||||
|
||||
proc CopyFileW*(lpExistingFileName, lpNewFileName: wideCString,
|
||||
proc copyFileW*(lpExistingFileName, lpNewFileName: WideCString,
|
||||
bFailIfExists: cint): cint {.
|
||||
importc, stdcall, dynlib: "kernel32".}
|
||||
importc: "CopyFileW", stdcall, dynlib: "kernel32".}
|
||||
|
||||
proc GetEnvironmentStringsW*(): widecstring {.
|
||||
stdcall, dynlib: "kernel32", importc.}
|
||||
proc FreeEnvironmentStringsW*(para1: widecstring): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc.}
|
||||
proc getEnvironmentStringsW*(): WideCString {.
|
||||
stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsW".}
|
||||
proc freeEnvironmentStringsW*(para1: WideCString): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "FreeEnvironmentStringsW".}
|
||||
|
||||
proc GetCommandLineW*(): wideCString {.importc, stdcall, dynlib: "kernel32".}
|
||||
proc getCommandLineW*(): WideCString {.importc: "GetCommandLineW",
|
||||
stdcall, dynlib: "kernel32".}
|
||||
|
||||
else:
|
||||
proc GetFullPathNameA*(lpFileName: cstring, nBufferLength: int32,
|
||||
proc getFullPathNameA*(lpFileName: cstring, nBufferLength: int32,
|
||||
lpBuffer: cstring, lpFilePart: var cstring): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc.}
|
||||
proc GetFileAttributesA*(lpFileName: cstring): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc.}
|
||||
proc SetFileAttributesA*(lpFileName: cstring,
|
||||
stdcall, dynlib: "kernel32",
|
||||
importc: "GetFullPathNameA".}
|
||||
proc getFileAttributesA*(lpFileName: cstring): int32 {.
|
||||
stdcall, dynlib: "kernel32",
|
||||
importc: "GetFileAttributesA".}
|
||||
proc setFileAttributesA*(lpFileName: cstring,
|
||||
dwFileAttributes: int32): WINBOOL {.
|
||||
stdcall, dynlib: "kernel32", importc: "SetFileAttributesA".}
|
||||
|
||||
proc CopyFileA*(lpExistingFileName, lpNewFileName: CString,
|
||||
proc copyFileA*(lpExistingFileName, lpNewFileName: CString,
|
||||
bFailIfExists: cint): cint {.
|
||||
importc, stdcall, dynlib: "kernel32".}
|
||||
importc: "CopyFileA", stdcall, dynlib: "kernel32".}
|
||||
|
||||
proc GetEnvironmentStringsA*(): cstring {.
|
||||
stdcall, dynlib: "kernel32", importc.}
|
||||
proc FreeEnvironmentStringsA*(para1: cstring): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc.}
|
||||
proc getEnvironmentStringsA*(): cstring {.
|
||||
stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsA".}
|
||||
proc freeEnvironmentStringsA*(para1: cstring): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "FreeEnvironmentStringsA".}
|
||||
|
||||
proc GetCommandLineA*(): CString {.importc, stdcall, dynlib: "kernel32".}
|
||||
proc getCommandLineA*(): cstring {.
|
||||
importc: "GetCommandLineA", stdcall, dynlib: "kernel32".}
|
||||
|
||||
proc rdFileTime*(f: TFILETIME): int64 =
|
||||
result = ze64(f.dwLowDateTime) or (ze64(f.dwHighDateTime) shl 32)
|
||||
|
||||
proc rdFileSize*(f: TWin32FindData): int64 =
|
||||
proc rdFileSize*(f: TWIN32_FIND_DATA): int64 =
|
||||
result = ze64(f.nFileSizeLow) or (ze64(f.nFileSizeHigh) shl 32)
|
||||
|
||||
proc GetSystemTimeAsFileTime*(lpSystemTimeAsFileTime: var TFILETIME) {.
|
||||
proc getSystemTimeAsFileTime*(lpSystemTimeAsFileTime: var TFILETIME) {.
|
||||
importc: "GetSystemTimeAsFileTime", dynlib: "kernel32", stdcall.}
|
||||
|
||||
proc Sleep*(dwMilliseconds: int32){.stdcall, dynlib: "kernel32",
|
||||
proc sleep*(dwMilliseconds: int32){.stdcall, dynlib: "kernel32",
|
||||
importc: "Sleep".}
|
||||
|
||||
when useWinUnicode:
|
||||
proc ShellExecuteW*(HWND: THandle, lpOperation, lpFile,
|
||||
lpParameters, lpDirectory: widecstring,
|
||||
proc shellExecuteW*(HWND: THandle, lpOperation, lpFile,
|
||||
lpParameters, lpDirectory: WideCString,
|
||||
nShowCmd: int32): THandle{.
|
||||
stdcall, dynlib: "shell32.dll", importc: "ShellExecuteW".}
|
||||
|
||||
else:
|
||||
proc ShellExecuteA*(HWND: THandle, lpOperation, lpFile,
|
||||
proc shellExecuteA*(HWND: THandle, lpOperation, lpFile,
|
||||
lpParameters, lpDirectory: cstring,
|
||||
nShowCmd: int32): THandle{.
|
||||
stdcall, dynlib: "shell32.dll", importc: "ShellExecuteA".}
|
||||
|
||||
proc GetFileInformationByHandle*(hFile: THandle,
|
||||
proc getFileInformationByHandle*(hFile: THandle,
|
||||
lpFileInformation: ptr TBY_HANDLE_FILE_INFORMATION): WINBOOL{.
|
||||
stdcall, dynlib: "kernel32", importc: "GetFileInformationByHandle".}
|
||||
|
||||
|
|
@ -332,7 +340,7 @@ const
|
|||
WSAEWOULDBLOCK* = 10035
|
||||
WSAEINPROGRESS* = 10036
|
||||
|
||||
proc WSAGetLastError*(): cint {.importc: "WSAGetLastError", dynlib: ws2dll.}
|
||||
proc wsaGetLastError*(): cint {.importc: "WSAGetLastError", dynlib: ws2dll.}
|
||||
|
||||
type
|
||||
TSocketHandle* = distinct int
|
||||
|
|
@ -410,7 +418,7 @@ type
|
|||
ai_addr*: ptr TSockAddr ## Socket address of socket.
|
||||
ai_next*: ptr TAddrInfo ## Pointer to next in list.
|
||||
|
||||
Tsocklen* = cuint
|
||||
TSockLen* = cuint
|
||||
|
||||
var
|
||||
SOMAXCONN* {.importc, header: "Winsock2.h".}: cint
|
||||
|
|
@ -437,10 +445,10 @@ proc getservbyname*(name, proto: cstring): ptr TServent {.
|
|||
proc getservbyport*(port: cint, proto: cstring): ptr TServent {.
|
||||
stdcall, importc: "getservbyport", dynlib: ws2dll.}
|
||||
|
||||
proc gethostbyaddr*(ip: ptr TInAddr, len: cuint, theType: cint): ptr THostEnt {.
|
||||
proc gethostbyaddr*(ip: ptr TInAddr, len: cuint, theType: cint): ptr Thostent {.
|
||||
stdcall, importc: "gethostbyaddr", dynlib: ws2dll.}
|
||||
|
||||
proc gethostbyname*(name: cstring): ptr THostEnt {.
|
||||
proc gethostbyname*(name: cstring): ptr Thostent {.
|
||||
stdcall, importc: "gethostbyname", dynlib: ws2dll.}
|
||||
|
||||
proc socket*(af, typ, protocol: cint): TSocketHandle {.
|
||||
|
|
@ -470,7 +478,7 @@ proc listen*(s: TSocketHandle, backlog: cint): cint {.
|
|||
proc recv*(s: TSocketHandle, buf: pointer, len, flags: cint): cint {.
|
||||
stdcall, importc: "recv", dynlib: ws2dll.}
|
||||
proc recvfrom*(s: TSocketHandle, buf: cstring, len, flags: cint,
|
||||
fromm: ptr TSockAddr, fromlen: ptr Tsocklen): cint {.
|
||||
fromm: ptr TSockAddr, fromlen: ptr TSockLen): cint {.
|
||||
stdcall, importc: "recvfrom", dynlib: ws2dll.}
|
||||
proc select*(nfds: cint, readfds, writefds, exceptfds: ptr TFdSet,
|
||||
timeout: ptr TTimeval): cint {.
|
||||
|
|
@ -478,35 +486,35 @@ proc select*(nfds: cint, readfds, writefds, exceptfds: ptr TFdSet,
|
|||
proc send*(s: TSocketHandle, buf: pointer, len, flags: cint): cint {.
|
||||
stdcall, importc: "send", dynlib: ws2dll.}
|
||||
proc sendto*(s: TSocketHandle, buf: pointer, len, flags: cint,
|
||||
to: ptr TSockAddr, tolen: Tsocklen): cint {.
|
||||
to: ptr TSockAddr, tolen: TSockLen): cint {.
|
||||
stdcall, importc: "sendto", dynlib: ws2dll.}
|
||||
|
||||
proc shutdown*(s: TSocketHandle, how: cint): cint {.
|
||||
stdcall, importc: "shutdown", dynlib: ws2dll.}
|
||||
|
||||
proc getnameinfo*(a1: ptr Tsockaddr, a2: Tsocklen,
|
||||
a3: cstring, a4: Tsocklen, a5: cstring,
|
||||
a6: Tsocklen, a7: cint): cint {.
|
||||
proc getnameinfo*(a1: ptr TSockAddr, a2: TSockLen,
|
||||
a3: cstring, a4: TSockLen, a5: cstring,
|
||||
a6: TSockLen, a7: cint): cint {.
|
||||
stdcall, importc: "getnameinfo", dynlib: ws2dll.}
|
||||
|
||||
proc inet_addr*(cp: cstring): int32 {.
|
||||
stdcall, importc: "inet_addr", dynlib: ws2dll.}
|
||||
|
||||
proc WSAFDIsSet(s: TSocketHandle, FDSet: var TFDSet): bool {.
|
||||
proc WSAFDIsSet(s: TSocketHandle, FDSet: var TFdSet): bool {.
|
||||
stdcall, importc: "__WSAFDIsSet", dynlib: ws2dll.}
|
||||
|
||||
proc FD_ISSET*(Socket: TSocketHandle, FDSet: var TFDSet): cint =
|
||||
proc FD_ISSET*(Socket: TSocketHandle, FDSet: var TFdSet): cint =
|
||||
result = if WSAFDIsSet(Socket, FDSet): 1'i32 else: 0'i32
|
||||
|
||||
proc FD_SET*(Socket: TSocketHandle, FDSet: var TFDSet) =
|
||||
proc FD_SET*(Socket: TSocketHandle, FDSet: var TFdSet) =
|
||||
if FDSet.fd_count < FD_SETSIZE:
|
||||
FDSet.fd_array[int(FDSet.fd_count)] = Socket
|
||||
inc(FDSet.fd_count)
|
||||
|
||||
proc FD_ZERO*(FDSet: var TFDSet) =
|
||||
proc FD_ZERO*(FDSet: var TFdSet) =
|
||||
FDSet.fd_count = 0
|
||||
|
||||
proc WSAStartup*(wVersionRequired: int16, WSData: ptr TWSAData): cint {.
|
||||
proc wsaStartup*(wVersionRequired: int16, WSData: ptr TWSAData): cint {.
|
||||
stdcall, importc: "WSAStartup", dynlib: ws2dll.}
|
||||
|
||||
proc getaddrinfo*(nodename, servname: cstring, hints: ptr TAddrInfo,
|
||||
|
|
@ -523,10 +531,10 @@ const
|
|||
MAXIMUM_WAIT_OBJECTS* = 0x00000040
|
||||
|
||||
type
|
||||
TWOHandleArray* = array[0..MAXIMUM_WAIT_OBJECTS - 1, THANDLE]
|
||||
TWOHandleArray* = array[0..MAXIMUM_WAIT_OBJECTS - 1, THandle]
|
||||
PWOHandleArray* = ptr TWOHandleArray
|
||||
|
||||
proc WaitForMultipleObjects*(nCount: DWORD, lpHandles: PWOHandleArray,
|
||||
proc waitForMultipleObjects*(nCount: DWORD, lpHandles: PWOHandleArray,
|
||||
bWaitAll: WINBOOL, dwMilliseconds: DWORD): DWORD{.
|
||||
stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
|
||||
|
||||
|
|
@ -558,53 +566,53 @@ const
|
|||
ERROR_ACCESS_DENIED* = 5
|
||||
|
||||
when useWinUnicode:
|
||||
proc CreateFileW*(lpFileName: widecstring, dwDesiredAccess, dwShareMode: DWORD,
|
||||
proc createFileW*(lpFileName: WideCString, dwDesiredAccess, dwShareMode: DWORD,
|
||||
lpSecurityAttributes: pointer,
|
||||
dwCreationDisposition, dwFlagsAndAttributes: DWORD,
|
||||
hTemplateFile: THANDLE): THANDLE {.
|
||||
hTemplateFile: THandle): THandle {.
|
||||
stdcall, dynlib: "kernel32", importc: "CreateFileW".}
|
||||
proc DeleteFileW*(pathName: widecstring): int32 {.
|
||||
proc deleteFileW*(pathName: WideCString): int32 {.
|
||||
importc: "DeleteFileW", dynlib: "kernel32", stdcall.}
|
||||
else:
|
||||
proc CreateFileA*(lpFileName: cstring, dwDesiredAccess, dwShareMode: DWORD,
|
||||
proc createFileA*(lpFileName: cstring, dwDesiredAccess, dwShareMode: DWORD,
|
||||
lpSecurityAttributes: pointer,
|
||||
dwCreationDisposition, dwFlagsAndAttributes: DWORD,
|
||||
hTemplateFile: THANDLE): THANDLE {.
|
||||
stdcall, dynlib: "kernel32", importc: "CreateFileA".}
|
||||
proc DeleteFileA*(pathName: cstring): int32 {.
|
||||
proc deleteFileA*(pathName: cstring): int32 {.
|
||||
importc: "DeleteFileA", dynlib: "kernel32", stdcall.}
|
||||
|
||||
proc SetEndOfFile*(hFile: THANDLE): WINBOOL {.stdcall, dynlib: "kernel32",
|
||||
proc setEndOfFile*(hFile: THandle): WINBOOL {.stdcall, dynlib: "kernel32",
|
||||
importc: "SetEndOfFile".}
|
||||
|
||||
proc SetFilePointer*(hFile: THANDLE, lDistanceToMove: LONG,
|
||||
proc setFilePointer*(hFile: THandle, lDistanceToMove: LONG,
|
||||
lpDistanceToMoveHigh: ptr LONG,
|
||||
dwMoveMethod: DWORD): DWORD {.
|
||||
stdcall, dynlib: "kernel32", importc: "SetFilePointer".}
|
||||
|
||||
proc GetFileSize*(hFile: THANDLE, lpFileSizeHigh: ptr DWORD): DWORD{.stdcall,
|
||||
proc getFileSize*(hFile: THandle, lpFileSizeHigh: ptr DWORD): DWORD{.stdcall,
|
||||
dynlib: "kernel32", importc: "GetFileSize".}
|
||||
|
||||
proc MapViewOfFileEx*(hFileMappingObject: THANDLE, dwDesiredAccess: DWORD,
|
||||
proc mapViewOfFileEx*(hFileMappingObject: THandle, dwDesiredAccess: DWORD,
|
||||
dwFileOffsetHigh, dwFileOffsetLow: DWORD,
|
||||
dwNumberOfBytesToMap: DWORD,
|
||||
lpBaseAddress: pointer): pointer{.
|
||||
stdcall, dynlib: "kernel32", importc: "MapViewOfFileEx".}
|
||||
|
||||
proc CreateFileMappingW*(hFile: THANDLE,
|
||||
proc createFileMappingW*(hFile: THandle,
|
||||
lpFileMappingAttributes: pointer,
|
||||
flProtect, dwMaximumSizeHigh: DWORD,
|
||||
dwMaximumSizeLow: DWORD,
|
||||
lpName: pointer): THANDLE {.
|
||||
lpName: pointer): THandle {.
|
||||
stdcall, dynlib: "kernel32", importc: "CreateFileMappingW".}
|
||||
|
||||
when not useWinUnicode:
|
||||
proc CreateFileMappingA*(hFile: THANDLE,
|
||||
proc createFileMappingA*(hFile: THANDLE,
|
||||
lpFileMappingAttributes: pointer,
|
||||
flProtect, dwMaximumSizeHigh: DWORD,
|
||||
dwMaximumSizeLow: DWORD, lpName: cstring): THANDLE {.
|
||||
stdcall, dynlib: "kernel32", importc: "CreateFileMappingA".}
|
||||
|
||||
proc UnmapViewOfFile*(lpBaseAddress: pointer): WINBOOL {.stdcall,
|
||||
proc unmapViewOfFile*(lpBaseAddress: pointer): WINBOOL {.stdcall,
|
||||
dynlib: "kernel32", importc: "UnmapViewOfFile".}
|
||||
|
||||
|
|
|
|||
331
lib/wrappers/libffi/common/ffi.h
Normal file
331
lib/wrappers/libffi/common/ffi.h
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
/* -----------------------------------------------------------------*-C-*-
|
||||
libffi 2.00-beta - Copyright (c) 1996-2003 Red Hat, Inc.
|
||||
|
||||
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 CYGNUS SOLUTIONS 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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------
|
||||
The basic API is described in the README file.
|
||||
|
||||
The raw API is designed to bypass some of the argument packing
|
||||
and unpacking on architectures for which it can be avoided.
|
||||
|
||||
The closure API allows interpreted functions to be packaged up
|
||||
inside a C function pointer, so that they can be called as C functions,
|
||||
with no understanding on the client side that they are interpreted.
|
||||
It can also be used in other cases in which it is necessary to package
|
||||
up a user specified parameter and a function pointer as a single
|
||||
function pointer.
|
||||
|
||||
The closure API must be implemented in order to get its functionality,
|
||||
e.g. for use by gij. Routines are provided to emulate the raw API
|
||||
if the underlying platform doesn't allow faster implementation.
|
||||
|
||||
More details on the raw and cloure API can be found in:
|
||||
|
||||
http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
|
||||
|
||||
and
|
||||
|
||||
http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
|
||||
-------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_H
|
||||
#define LIBFFI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Specify which architecture libffi is configured for. */
|
||||
//XXX #define X86
|
||||
|
||||
/* ---- System configuration information --------------------------------- */
|
||||
|
||||
#include <ffitarget.h>
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
|
||||
But we can find it either under the correct ANSI name, or under GNU
|
||||
C's internal name. */
|
||||
#ifdef LONG_LONG_MAX
|
||||
# define FFI_LONG_LONG_MAX LONG_LONG_MAX
|
||||
#else
|
||||
# ifdef LLONG_MAX
|
||||
# define FFI_LONG_LONG_MAX LLONG_MAX
|
||||
# else
|
||||
# ifdef __GNUC__
|
||||
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
|
||||
# endif
|
||||
# ifdef _MSC_VER
|
||||
# define FFI_LONG_LONG_MAX _I64_MAX
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if SCHAR_MAX == 127
|
||||
# define ffi_type_uchar ffi_type_uint8
|
||||
# define ffi_type_schar ffi_type_sint8
|
||||
#else
|
||||
#error "char size not supported"
|
||||
#endif
|
||||
|
||||
#if SHRT_MAX == 32767
|
||||
# define ffi_type_ushort ffi_type_uint16
|
||||
# define ffi_type_sshort ffi_type_sint16
|
||||
#elif SHRT_MAX == 2147483647
|
||||
# define ffi_type_ushort ffi_type_uint32
|
||||
# define ffi_type_sshort ffi_type_sint32
|
||||
#else
|
||||
#error "short size not supported"
|
||||
#endif
|
||||
|
||||
#if INT_MAX == 32767
|
||||
# define ffi_type_uint ffi_type_uint16
|
||||
# define ffi_type_sint ffi_type_sint16
|
||||
#elif INT_MAX == 2147483647
|
||||
# define ffi_type_uint ffi_type_uint32
|
||||
# define ffi_type_sint ffi_type_sint32
|
||||
#elif INT_MAX == 9223372036854775807
|
||||
# define ffi_type_uint ffi_type_uint64
|
||||
# define ffi_type_sint ffi_type_sint64
|
||||
#else
|
||||
#error "int size not supported"
|
||||
#endif
|
||||
|
||||
#define ffi_type_ulong ffi_type_uint64
|
||||
#define ffi_type_slong ffi_type_sint64
|
||||
#if LONG_MAX == 2147483647
|
||||
# if FFI_LONG_LONG_MAX != 9223372036854775807
|
||||
#error "no 64-bit data type supported"
|
||||
# endif
|
||||
#elif LONG_MAX != 9223372036854775807
|
||||
#error "long size not supported"
|
||||
#endif
|
||||
|
||||
/* The closure code assumes that this works on pointers, i.e. a size_t */
|
||||
/* can hold a pointer. */
|
||||
|
||||
typedef struct _ffi_type
|
||||
{
|
||||
size_t size;
|
||||
unsigned short alignment;
|
||||
unsigned short type;
|
||||
/*@null@*/ struct _ffi_type **elements;
|
||||
} ffi_type;
|
||||
|
||||
/* These are defined in types.c */
|
||||
extern const ffi_type ffi_type_void;
|
||||
extern const ffi_type ffi_type_uint8;
|
||||
extern const ffi_type ffi_type_sint8;
|
||||
extern const ffi_type ffi_type_uint16;
|
||||
extern const ffi_type ffi_type_sint16;
|
||||
extern const ffi_type ffi_type_uint32;
|
||||
extern const ffi_type ffi_type_sint32;
|
||||
extern const ffi_type ffi_type_uint64;
|
||||
extern const ffi_type ffi_type_sint64;
|
||||
extern const ffi_type ffi_type_float;
|
||||
extern const ffi_type ffi_type_double;
|
||||
extern const ffi_type ffi_type_longdouble;
|
||||
extern const ffi_type ffi_type_pointer;
|
||||
|
||||
|
||||
typedef enum {
|
||||
FFI_OK = 0,
|
||||
FFI_BAD_TYPEDEF,
|
||||
FFI_BAD_ABI
|
||||
} ffi_status;
|
||||
|
||||
typedef unsigned FFI_TYPE;
|
||||
|
||||
typedef struct {
|
||||
ffi_abi abi;
|
||||
unsigned nargs;
|
||||
/*@dependent@*/ ffi_type **arg_types;
|
||||
/*@dependent@*/ ffi_type *rtype;
|
||||
unsigned bytes;
|
||||
unsigned flags;
|
||||
#ifdef FFI_EXTRA_CIF_FIELDS
|
||||
FFI_EXTRA_CIF_FIELDS;
|
||||
#endif
|
||||
} ffi_cif;
|
||||
|
||||
/* ---- Definitions for the raw API -------------------------------------- */
|
||||
|
||||
#ifdef _WIN64
|
||||
#define FFI_SIZEOF_ARG 8
|
||||
#else
|
||||
#define FFI_SIZEOF_ARG 4
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
ffi_sarg sint;
|
||||
ffi_arg uint;
|
||||
float flt;
|
||||
char data[FFI_SIZEOF_ARG];
|
||||
void* ptr;
|
||||
} ffi_raw;
|
||||
|
||||
void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ ffi_raw *avalue);
|
||||
|
||||
void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
|
||||
void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
|
||||
size_t ffi_raw_size (ffi_cif *cif);
|
||||
|
||||
/* This is analogous to the raw API, except it uses Java parameter */
|
||||
/* packing, even on 64-bit machines. I.e. on 64-bit machines */
|
||||
/* longs and doubles are followed by an empty 64-bit word. */
|
||||
|
||||
void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ ffi_raw *avalue);
|
||||
|
||||
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
|
||||
void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
|
||||
size_t ffi_java_raw_size (ffi_cif *cif);
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#if FFI_CLOSURES
|
||||
|
||||
typedef struct {
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
ffi_cif *cif;
|
||||
void (*fun)(ffi_cif*,void*,void**,void*);
|
||||
void *user_data;
|
||||
} ffi_closure;
|
||||
|
||||
void ffi_closure_free(void *);
|
||||
void *ffi_closure_alloc (size_t size, void **code);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure*,
|
||||
ffi_cif *,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc);
|
||||
|
||||
typedef struct {
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
|
||||
ffi_cif *cif;
|
||||
|
||||
#if !FFI_NATIVE_RAW_API
|
||||
|
||||
/* if this is enabled, then a raw closure has the same layout
|
||||
as a regular closure. We use this to install an intermediate
|
||||
handler to do the transaltion, void** -> ffi_raw*. */
|
||||
|
||||
void (*translate_args)(ffi_cif*,void*,void**,void*);
|
||||
void *this_closure;
|
||||
|
||||
#endif
|
||||
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
|
||||
void *user_data;
|
||||
|
||||
} ffi_raw_closure;
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure (ffi_raw_closure*,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure (ffi_raw_closure*,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data);
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
|
||||
/* ---- Public interface definition -------------------------------------- */
|
||||
|
||||
ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
||||
ffi_abi abi,
|
||||
unsigned int nargs,
|
||||
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
|
||||
/*@dependent@*/ ffi_type **atypes);
|
||||
|
||||
void
|
||||
ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue);
|
||||
|
||||
/* Useful for eliminating compiler warnings */
|
||||
#define FFI_FN(f) ((void (*)())f)
|
||||
|
||||
/* ---- Definitions shared with assembly code ---------------------------- */
|
||||
|
||||
#endif
|
||||
|
||||
/* If these change, update src/mips/ffitarget.h. */
|
||||
#define FFI_TYPE_VOID 0
|
||||
#define FFI_TYPE_INT 1
|
||||
#define FFI_TYPE_FLOAT 2
|
||||
#define FFI_TYPE_DOUBLE 3
|
||||
#if 1
|
||||
#define FFI_TYPE_LONGDOUBLE 4
|
||||
#else
|
||||
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
|
||||
#endif
|
||||
#define FFI_TYPE_UINT8 5
|
||||
#define FFI_TYPE_SINT8 6
|
||||
#define FFI_TYPE_UINT16 7
|
||||
#define FFI_TYPE_SINT16 8
|
||||
#define FFI_TYPE_UINT32 9
|
||||
#define FFI_TYPE_SINT32 10
|
||||
#define FFI_TYPE_UINT64 11
|
||||
#define FFI_TYPE_SINT64 12
|
||||
#define FFI_TYPE_STRUCT 13
|
||||
#define FFI_TYPE_POINTER 14
|
||||
|
||||
/* This should always refer to the last type code (for sanity checks) */
|
||||
#define FFI_TYPE_LAST FFI_TYPE_POINTER
|
||||
|
||||
#define FFI_HIDDEN /* no idea what the origial definition looks like ... */
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define LIKELY(x) __builtin_expect(x, 1)
|
||||
# define UNLIKELY(x) __builtin_expect(x, 0)
|
||||
#else
|
||||
# define LIKELY(x) (x)
|
||||
# define UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
#define MAYBE_UNUSED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
77
lib/wrappers/libffi/common/ffi_common.h
Normal file
77
lib/wrappers/libffi/common/ffi_common.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
|
||||
|
||||
Common internal definitions and macros. Only necessary for building
|
||||
libffi.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef FFI_COMMON_H
|
||||
#define FFI_COMMON_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <fficonfig.h>
|
||||
#include <malloc.h>
|
||||
|
||||
/* Check for the existence of memcpy. */
|
||||
#if STDC_HEADERS
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifndef HAVE_MEMCPY
|
||||
# define memcpy(d, s, n) bcopy ((s), (d), (n))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(FFI_DEBUG)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef FFI_DEBUG
|
||||
/*@exits@*/ void ffi_assert(/*@temp@*/ char *expr, /*@temp@*/ char *file, int line);
|
||||
void ffi_stop_here(void);
|
||||
void ffi_type_test(/*@temp@*/ /*@out@*/ ffi_type *a, /*@temp@*/ char *file, int line);
|
||||
|
||||
#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
|
||||
#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
|
||||
#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
|
||||
#else
|
||||
#define FFI_ASSERT(x)
|
||||
#define FFI_ASSERT_AT(x, f, l)
|
||||
#define FFI_ASSERT_VALID_TYPE(x)
|
||||
#endif
|
||||
|
||||
#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
|
||||
|
||||
/* Extended cif, used in callback from assembly routine */
|
||||
typedef struct
|
||||
{
|
||||
/*@dependent@*/ ffi_cif *cif;
|
||||
/*@dependent@*/ void *rvalue;
|
||||
/*@dependent@*/ void **avalue;
|
||||
} extended_cif;
|
||||
|
||||
/* Terse sized type definitions. */
|
||||
typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
|
||||
typedef signed int SINT8 __attribute__((__mode__(__QI__)));
|
||||
typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
|
||||
typedef signed int SINT16 __attribute__((__mode__(__HI__)));
|
||||
typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
|
||||
typedef signed int SINT32 __attribute__((__mode__(__SI__)));
|
||||
typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
|
||||
typedef signed int SINT64 __attribute__((__mode__(__DI__)));
|
||||
|
||||
typedef float FLOAT32;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
96
lib/wrappers/libffi/common/fficonfig.h
Normal file
96
lib/wrappers/libffi/common/fficonfig.h
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/* fficonfig.h. Originally created by configure, now hand_maintained for MSVC. */
|
||||
|
||||
/* fficonfig.h. Generated automatically by configure. */
|
||||
/* fficonfig.h.in. Generated automatically from configure.in by autoheader. */
|
||||
|
||||
/* Define this for MSVC, but not for mingw32! */
|
||||
#ifdef _MSC_VER
|
||||
#define __attribute__(x) /* */
|
||||
#endif
|
||||
#define alloca _alloca
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
/* Define if using alloca.c. */
|
||||
/* #undef C_ALLOCA */
|
||||
|
||||
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
|
||||
This function is required for alloca.c support on those systems. */
|
||||
/* #undef CRAY_STACKSEG_END */
|
||||
|
||||
/* Define if you have alloca, as a function or macro. */
|
||||
#define HAVE_ALLOCA 1
|
||||
|
||||
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
|
||||
/* #define HAVE_ALLOCA_H 1 */
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
direction of stack growth for your system; otherwise it will be
|
||||
automatically deduced at run-time.
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown
|
||||
*/
|
||||
/* #undef STACK_DIRECTION */
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define if you have the memcpy function. */
|
||||
#define HAVE_MEMCPY 1
|
||||
|
||||
/* Define if read-only mmap of a plain file works. */
|
||||
//#define HAVE_MMAP_FILE 1
|
||||
|
||||
/* Define if mmap of /dev/zero works. */
|
||||
//#define HAVE_MMAP_DEV_ZERO 1
|
||||
|
||||
/* Define if mmap with MAP_ANON(YMOUS) works. */
|
||||
//#define HAVE_MMAP_ANON 1
|
||||
|
||||
/* The number of bytes in type double */
|
||||
#define SIZEOF_DOUBLE 8
|
||||
|
||||
/* The number of bytes in type long double */
|
||||
#define SIZEOF_LONG_DOUBLE 12
|
||||
|
||||
/* Define if you have the long double type and it is bigger than a double */
|
||||
#define HAVE_LONG_DOUBLE 1
|
||||
|
||||
/* whether byteorder is bigendian */
|
||||
/* #undef WORDS_BIGENDIAN */
|
||||
|
||||
/* Define if the host machine stores words of multi-word integers in
|
||||
big-endian order. */
|
||||
/* #undef HOST_WORDS_BIG_ENDIAN */
|
||||
|
||||
/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
|
||||
#define BYTEORDER 1234
|
||||
|
||||
/* Define if your assembler and linker support unaligned PC relative relocs. */
|
||||
/* #undef HAVE_AS_SPARC_UA_PCREL */
|
||||
|
||||
/* Define if your assembler supports .register. */
|
||||
/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
|
||||
|
||||
/* Define if .eh_frame sections should be read-only. */
|
||||
/* #undef HAVE_RO_EH_FRAME */
|
||||
|
||||
/* Define to the flags needed for the .section .eh_frame directive. */
|
||||
/* #define EH_FRAME_FLAGS "aw" */
|
||||
|
||||
/* Define to the flags needed for the .section .eh_frame directive. */
|
||||
/* #define EH_FRAME_FLAGS "aw" */
|
||||
|
||||
/* Define this if you want extra debugging. */
|
||||
/* #undef FFI_DEBUG */
|
||||
|
||||
/* Define this is you do not want support for aggregate types. */
|
||||
/* #undef FFI_NO_STRUCTS */
|
||||
|
||||
/* Define this is you do not want support for the raw API. */
|
||||
/* #undef FFI_NO_RAW_API */
|
||||
|
||||
/* Define this if you are using Purify and want to suppress spurious messages. */
|
||||
/* #undef USING_PURIFY */
|
||||
|
||||
150
lib/wrappers/libffi/common/ffitarget.h
Normal file
150
lib/wrappers/libffi/common/ffitarget.h
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 2012 Anthony Green
|
||||
Copyright (c) 1996-2003, 2010 Red Hat, Inc.
|
||||
Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
Target configuration macros for x86 and x86-64.
|
||||
|
||||
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.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_H
|
||||
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
|
||||
#endif
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
/* For code common to all platforms on x86 and x86_64. */
|
||||
#define X86_ANY
|
||||
|
||||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
||||
# if defined(__x86_64__) || defined(__x86_64) || defined(_M_X64)
|
||||
# define X86_64
|
||||
# define X86_WIN64
|
||||
# else
|
||||
# define X86_32
|
||||
# define X86_WIN32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (X86_64) && defined (__i386__)
|
||||
#undef X86_64
|
||||
#define X86
|
||||
#endif
|
||||
|
||||
#ifdef X86_WIN64
|
||||
#define FFI_SIZEOF_ARG 8
|
||||
#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */
|
||||
#endif
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
#ifdef X86_WIN64
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int64 ffi_arg;
|
||||
typedef __int64 ffi_sarg;
|
||||
#else
|
||||
typedef unsigned long long ffi_arg;
|
||||
typedef long long ffi_sarg;
|
||||
#endif
|
||||
#else
|
||||
#if defined __x86_64__ && defined __ILP32__
|
||||
#define FFI_SIZEOF_ARG 8
|
||||
#define FFI_SIZEOF_JAVA_RAW 4
|
||||
typedef unsigned long long ffi_arg;
|
||||
typedef long long ffi_sarg;
|
||||
#else
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
/* ---- Intel x86 Win32 ---------- */
|
||||
#ifdef X86_WIN32
|
||||
FFI_SYSV,
|
||||
FFI_STDCALL,
|
||||
FFI_THISCALL,
|
||||
FFI_FASTCALL,
|
||||
FFI_MS_CDECL,
|
||||
FFI_LAST_ABI,
|
||||
#ifdef _MSC_VER
|
||||
FFI_DEFAULT_ABI = FFI_MS_CDECL
|
||||
#else
|
||||
FFI_DEFAULT_ABI = FFI_SYSV
|
||||
#endif
|
||||
|
||||
#elif defined(X86_WIN64)
|
||||
FFI_WIN64,
|
||||
FFI_LAST_ABI,
|
||||
FFI_DEFAULT_ABI = FFI_WIN64
|
||||
|
||||
#else
|
||||
/* ---- Intel x86 and AMD x86-64 - */
|
||||
FFI_SYSV,
|
||||
FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */
|
||||
FFI_LAST_ABI,
|
||||
#if defined(__i386__) || defined(__i386)
|
||||
FFI_DEFAULT_ABI = FFI_SYSV
|
||||
#else
|
||||
FFI_DEFAULT_ABI = FFI_UNIX64
|
||||
#endif
|
||||
#endif
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)
|
||||
#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)
|
||||
#define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3)
|
||||
#define FFI_TYPE_MS_STRUCT (FFI_TYPE_LAST + 4)
|
||||
|
||||
#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
#else
|
||||
#ifdef X86_WIN32
|
||||
#define FFI_TRAMPOLINE_SIZE 52
|
||||
#else
|
||||
#ifdef X86_WIN64
|
||||
#define FFI_TRAMPOLINE_SIZE 29
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
#define FFI_NO_RAW_API 1
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 10
|
||||
#endif
|
||||
#endif
|
||||
#ifndef X86_WIN64
|
||||
#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
110
lib/wrappers/libffi/common/malloc_closure.c
Normal file
110
lib/wrappers/libffi/common/malloc_closure.c
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
#include <ffi.h>
|
||||
#ifdef MS_WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
|
||||
# define MAP_ANONYMOUS MAP_ANON
|
||||
# endif
|
||||
#endif
|
||||
#include "ctypes.h"
|
||||
|
||||
/* BLOCKSIZE can be adjusted. Larger blocksize will take a larger memory
|
||||
overhead, but allocate less blocks from the system. It may be that some
|
||||
systems have a limit of how many mmap'd blocks can be open.
|
||||
*/
|
||||
|
||||
#define BLOCKSIZE _pagesize
|
||||
|
||||
/* #define MALLOC_CLOSURE_DEBUG */ /* enable for some debugging output */
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
typedef union _tagITEM {
|
||||
ffi_closure closure;
|
||||
union _tagITEM *next;
|
||||
} ITEM;
|
||||
|
||||
static ITEM *free_list;
|
||||
static int _pagesize;
|
||||
|
||||
static void more_core(void)
|
||||
{
|
||||
ITEM *item;
|
||||
int count, i;
|
||||
|
||||
/* determine the pagesize */
|
||||
#ifdef MS_WIN32
|
||||
if (!_pagesize) {
|
||||
SYSTEM_INFO systeminfo;
|
||||
GetSystemInfo(&systeminfo);
|
||||
_pagesize = systeminfo.dwPageSize;
|
||||
}
|
||||
#else
|
||||
if (!_pagesize) {
|
||||
#ifdef _SC_PAGESIZE
|
||||
_pagesize = sysconf(_SC_PAGESIZE);
|
||||
#else
|
||||
_pagesize = getpagesize();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* calculate the number of nodes to allocate */
|
||||
count = BLOCKSIZE / sizeof(ITEM);
|
||||
|
||||
/* allocate a memory block */
|
||||
#ifdef MS_WIN32
|
||||
item = (ITEM *)VirtualAlloc(NULL,
|
||||
count * sizeof(ITEM),
|
||||
MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
if (item == NULL)
|
||||
return;
|
||||
#else
|
||||
item = (ITEM *)mmap(NULL,
|
||||
count * sizeof(ITEM),
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS,
|
||||
-1,
|
||||
0);
|
||||
if (item == (void *)MAP_FAILED)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifdef MALLOC_CLOSURE_DEBUG
|
||||
printf("block at %p allocated (%d bytes), %d ITEMs\n",
|
||||
item, count * sizeof(ITEM), count);
|
||||
#endif
|
||||
/* put them into the free list */
|
||||
for (i = 0; i < count; ++i) {
|
||||
item->next = free_list;
|
||||
free_list = item;
|
||||
++item;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
/* put the item back into the free list */
|
||||
void ffi_closure_free(void *p)
|
||||
{
|
||||
ITEM *item = (ITEM *)p;
|
||||
item->next = free_list;
|
||||
free_list = item;
|
||||
}
|
||||
|
||||
/* return one item from the free list, allocating more if needed */
|
||||
void *ffi_closure_alloc(size_t ignored, void** codeloc)
|
||||
{
|
||||
ITEM *item;
|
||||
if (!free_list)
|
||||
more_core();
|
||||
if (!free_list)
|
||||
return NULL;
|
||||
item = free_list;
|
||||
free_list = item->next;
|
||||
*codeloc = (void *)item;
|
||||
return (void *)item;
|
||||
}
|
||||
254
lib/wrappers/libffi/common/raw_api.c
Normal file
254
lib/wrappers/libffi/common/raw_api.c
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
raw_api.c - Copyright (c) 1999, 2008 Red Hat, Inc.
|
||||
|
||||
Author: Kresten Krab Thorup <krab@gnu.org>
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* This file defines generic functions for use with the raw api. */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
size_t
|
||||
ffi_raw_size (ffi_cif *cif)
|
||||
{
|
||||
size_t result = 0;
|
||||
int i;
|
||||
|
||||
ffi_type **at = cif->arg_types;
|
||||
|
||||
for (i = cif->nargs-1; i >= 0; i--, at++)
|
||||
{
|
||||
#if !FFI_NO_STRUCTS
|
||||
if ((*at)->type == FFI_TYPE_STRUCT)
|
||||
result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG);
|
||||
else
|
||||
#endif
|
||||
result += ALIGN ((*at)->size, FFI_SIZEOF_ARG);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2);
|
||||
break;
|
||||
|
||||
#if FFI_SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
*args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !FFI_NO_STRUCTS
|
||||
case FFI_TYPE_STRUCT:
|
||||
*args = (raw++)->ptr;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
*args = (void*) &(raw++)->ptr;
|
||||
break;
|
||||
|
||||
default:
|
||||
*args = raw;
|
||||
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* WORDS_BIGENDIAN */
|
||||
|
||||
#if !PDP
|
||||
|
||||
/* then assume little endian */
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
#if !FFI_NO_STRUCTS
|
||||
if ((*tp)->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
*args = (raw++)->ptr;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
*args = (void*) raw;
|
||||
raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#error "pdp endian not supported"
|
||||
#endif /* ! PDP */
|
||||
|
||||
#endif /* WORDS_BIGENDIAN */
|
||||
}
|
||||
|
||||
void
|
||||
ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw)
|
||||
{
|
||||
unsigned i;
|
||||
ffi_type **tp = cif->arg_types;
|
||||
|
||||
for (i = 0; i < cif->nargs; i++, tp++, args++)
|
||||
{
|
||||
switch ((*tp)->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
(raw++)->uint = *(UINT8*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT8:
|
||||
(raw++)->sint = *(SINT8*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
(raw++)->uint = *(UINT16*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
(raw++)->sint = *(SINT16*) (*args);
|
||||
break;
|
||||
|
||||
#if FFI_SIZEOF_ARG >= 4
|
||||
case FFI_TYPE_UINT32:
|
||||
(raw++)->uint = *(UINT32*) (*args);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
(raw++)->sint = *(SINT32*) (*args);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !FFI_NO_STRUCTS
|
||||
case FFI_TYPE_STRUCT:
|
||||
(raw++)->ptr = *args;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FFI_TYPE_POINTER:
|
||||
(raw++)->ptr = **(void***) args;
|
||||
break;
|
||||
|
||||
default:
|
||||
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
|
||||
raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !FFI_NATIVE_RAW_API
|
||||
|
||||
|
||||
/* This is a generic definition of ffi_raw_call, to be used if the
|
||||
* native system does not provide a machine-specific implementation.
|
||||
* Having this, allows code to be written for the raw API, without
|
||||
* the need for system-specific code to handle input in that format;
|
||||
* these following couple of functions will handle the translation forth
|
||||
* and back automatically. */
|
||||
|
||||
void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *raw)
|
||||
{
|
||||
void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
ffi_raw_to_ptrarray (cif, raw, avalue);
|
||||
ffi_call (cif, fn, rvalue, avalue);
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES /* base system provides closures */
|
||||
|
||||
static void
|
||||
ffi_translate_args (ffi_cif *cif, void *rvalue,
|
||||
void **avalue, void *user_data)
|
||||
{
|
||||
ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif));
|
||||
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
|
||||
|
||||
ffi_ptrarray_to_raw (cif, avalue, raw);
|
||||
(*cl->fun) (cif, rvalue, raw, cl->user_data);
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure_loc (ffi_raw_closure* cl,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
ffi_status status;
|
||||
|
||||
status = ffi_prep_closure_loc ((ffi_closure*) cl,
|
||||
cif,
|
||||
&ffi_translate_args,
|
||||
codeloc,
|
||||
codeloc);
|
||||
if (status == FFI_OK)
|
||||
{
|
||||
cl->fun = fun;
|
||||
cl->user_data = user_data;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
#endif /* !FFI_NATIVE_RAW_API */
|
||||
|
||||
#if FFI_CLOSURES
|
||||
|
||||
/* Again, here is the generic version of ffi_prep_raw_closure, which
|
||||
* will install an intermediate "hub" for translation of arguments from
|
||||
* the pointer-array format, to the raw format */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure (ffi_raw_closure* cl,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data)
|
||||
{
|
||||
return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl);
|
||||
}
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
|
||||
#endif /* !FFI_NO_RAW_API */
|
||||
627
lib/wrappers/libffi/gcc/closures.c
Normal file
627
lib/wrappers/libffi/gcc/closures.c
Normal file
|
|
@ -0,0 +1,627 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
closures.c - Copyright (c) 2007, 2009, 2010 Red Hat, Inc.
|
||||
Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc
|
||||
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
|
||||
|
||||
Code to allocate and deallocate memory for closures.
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#if defined __linux__ && !defined _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
|
||||
# if __gnu_linux__
|
||||
/* This macro indicates it may be forbidden to map anonymous memory
|
||||
with both write and execute permission. Code compiled when this
|
||||
option is defined will attempt to map such pages once, but if it
|
||||
fails, it falls back to creating a temporary file in a writable and
|
||||
executable filesystem and mapping pages from it into separate
|
||||
locations in the virtual memory space, one location writable and
|
||||
another executable. */
|
||||
# define FFI_MMAP_EXEC_WRIT 1
|
||||
# define HAVE_MNTENT 1
|
||||
# endif
|
||||
# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)
|
||||
/* Windows systems may have Data Execution Protection (DEP) enabled,
|
||||
which requires the use of VirtualMalloc/VirtualFree to alloc/free
|
||||
executable memory. */
|
||||
# define FFI_MMAP_EXEC_WRIT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
|
||||
# ifdef __linux__
|
||||
/* When defined to 1 check for SELinux and if SELinux is active,
|
||||
don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that
|
||||
might cause audit messages. */
|
||||
# define FFI_MMAP_EXEC_SELINUX 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if FFI_CLOSURES
|
||||
|
||||
# if FFI_EXEC_TRAMPOLINE_TABLE
|
||||
|
||||
// Per-target implementation; It's unclear what can reasonable be shared
|
||||
// between two OS/architecture implementations.
|
||||
|
||||
# elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */
|
||||
|
||||
#define USE_LOCKS 1
|
||||
#define USE_DL_PREFIX 1
|
||||
#ifdef __GNUC__
|
||||
#ifndef USE_BUILTIN_FFS
|
||||
#define USE_BUILTIN_FFS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* We need to use mmap, not sbrk. */
|
||||
#define HAVE_MORECORE 0
|
||||
|
||||
/* We could, in theory, support mremap, but it wouldn't buy us anything. */
|
||||
#define HAVE_MREMAP 0
|
||||
|
||||
/* We have no use for this, so save some code and data. */
|
||||
#define NO_MALLINFO 1
|
||||
|
||||
/* We need all allocations to be in regular segments, otherwise we
|
||||
lose track of the corresponding code address. */
|
||||
#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
|
||||
|
||||
/* Don't allocate more than a page unless needed. */
|
||||
#define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize)
|
||||
|
||||
#if FFI_CLOSURE_TEST
|
||||
/* Don't release single pages, to avoid a worst-case scenario of
|
||||
continuously allocating and releasing single pages, but release
|
||||
pairs of pages, which should do just as well given that allocations
|
||||
are likely to be small. */
|
||||
#define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize)
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#if !defined(X86_WIN32) && !defined(X86_WIN64)
|
||||
#ifdef HAVE_MNTENT
|
||||
#include <mntent.h>
|
||||
#endif /* HAVE_MNTENT */
|
||||
#include <sys/param.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/* We don't want sys/mman.h to be included after we redefine mmap and
|
||||
dlmunmap. */
|
||||
#include <sys/mman.h>
|
||||
#define LACKS_SYS_MMAN_H 1
|
||||
|
||||
#if FFI_MMAP_EXEC_SELINUX
|
||||
#include <sys/statfs.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int selinux_enabled = -1;
|
||||
|
||||
static int
|
||||
selinux_enabled_check (void)
|
||||
{
|
||||
struct statfs sfs;
|
||||
FILE *f;
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
if (statfs ("/selinux", &sfs) >= 0
|
||||
&& (unsigned int) sfs.f_type == 0xf97cff8cU)
|
||||
return 1;
|
||||
f = fopen ("/proc/mounts", "r");
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
while (getline (&buf, &len, f) >= 0)
|
||||
{
|
||||
char *p = strchr (buf, ' ');
|
||||
if (p == NULL)
|
||||
break;
|
||||
p = strchr (p + 1, ' ');
|
||||
if (p == NULL)
|
||||
break;
|
||||
if (strncmp (p + 1, "selinuxfs ", 10) == 0)
|
||||
{
|
||||
free (buf);
|
||||
fclose (f);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
free (buf);
|
||||
fclose (f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \
|
||||
: (selinux_enabled = selinux_enabled_check ()))
|
||||
|
||||
#else
|
||||
|
||||
#define is_selinux_enabled() 0
|
||||
|
||||
#endif /* !FFI_MMAP_EXEC_SELINUX */
|
||||
|
||||
/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. */
|
||||
#ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX
|
||||
#include <stdlib.h>
|
||||
|
||||
static int emutramp_enabled = -1;
|
||||
|
||||
static int
|
||||
emutramp_enabled_check (void)
|
||||
{
|
||||
if (getenv ("FFI_DISABLE_EMUTRAMP") == NULL)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
|
||||
: (emutramp_enabled = emutramp_enabled_check ()))
|
||||
#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
|
||||
|
||||
#elif defined (__CYGWIN__) || defined(__INTERIX)
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
/* Cygwin is Linux-like, but not quite that Linux-like. */
|
||||
#define is_selinux_enabled() 0
|
||||
|
||||
#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
|
||||
|
||||
#ifndef FFI_MMAP_EXEC_EMUTRAMP_PAX
|
||||
#define is_emutramp_enabled() 0
|
||||
#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
|
||||
|
||||
#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
|
||||
/* Use these for mmap and munmap within dlmalloc.c. */
|
||||
static void *dlmmap(void *, size_t, int, int, int, off_t);
|
||||
static int dlmunmap(void *, size_t);
|
||||
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
|
||||
|
||||
#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
|
||||
|
||||
/* A mutex used to synchronize access to *exec* variables in this file. */
|
||||
static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/* A file descriptor of a temporary file from which we'll map
|
||||
executable pages. */
|
||||
static int execfd = -1;
|
||||
|
||||
/* The amount of space already allocated from the temporary file. */
|
||||
static size_t execsize = 0;
|
||||
|
||||
/* Open a temporary file name, and immediately unlink it. */
|
||||
static int
|
||||
open_temp_exec_file_name (char *name)
|
||||
{
|
||||
int fd = mkstemp (name);
|
||||
|
||||
if (fd != -1)
|
||||
unlink (name);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Open a temporary file in the named directory. */
|
||||
static int
|
||||
open_temp_exec_file_dir (const char *dir)
|
||||
{
|
||||
static const char suffix[] = "/ffiXXXXXX";
|
||||
int lendir = strlen (dir);
|
||||
char *tempname = __builtin_alloca (lendir + sizeof (suffix));
|
||||
|
||||
if (!tempname)
|
||||
return -1;
|
||||
|
||||
memcpy (tempname, dir, lendir);
|
||||
memcpy (tempname + lendir, suffix, sizeof (suffix));
|
||||
|
||||
return open_temp_exec_file_name (tempname);
|
||||
}
|
||||
|
||||
/* Open a temporary file in the directory in the named environment
|
||||
variable. */
|
||||
static int
|
||||
open_temp_exec_file_env (const char *envvar)
|
||||
{
|
||||
const char *value = getenv (envvar);
|
||||
|
||||
if (!value)
|
||||
return -1;
|
||||
|
||||
return open_temp_exec_file_dir (value);
|
||||
}
|
||||
|
||||
#ifdef HAVE_MNTENT
|
||||
/* Open a temporary file in an executable and writable mount point
|
||||
listed in the mounts file. Subsequent calls with the same mounts
|
||||
keep searching for mount points in the same file. Providing NULL
|
||||
as the mounts file closes the file. */
|
||||
static int
|
||||
open_temp_exec_file_mnt (const char *mounts)
|
||||
{
|
||||
static const char *last_mounts;
|
||||
static FILE *last_mntent;
|
||||
|
||||
if (mounts != last_mounts)
|
||||
{
|
||||
if (last_mntent)
|
||||
endmntent (last_mntent);
|
||||
|
||||
last_mounts = mounts;
|
||||
|
||||
if (mounts)
|
||||
last_mntent = setmntent (mounts, "r");
|
||||
else
|
||||
last_mntent = NULL;
|
||||
}
|
||||
|
||||
if (!last_mntent)
|
||||
return -1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int fd;
|
||||
struct mntent mnt;
|
||||
char buf[MAXPATHLEN * 3];
|
||||
|
||||
if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf)) == NULL)
|
||||
return -1;
|
||||
|
||||
if (hasmntopt (&mnt, "ro")
|
||||
|| hasmntopt (&mnt, "noexec")
|
||||
|| access (mnt.mnt_dir, W_OK))
|
||||
continue;
|
||||
|
||||
fd = open_temp_exec_file_dir (mnt.mnt_dir);
|
||||
|
||||
if (fd != -1)
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_MNTENT */
|
||||
|
||||
/* Instructions to look for a location to hold a temporary file that
|
||||
can be mapped in for execution. */
|
||||
static struct
|
||||
{
|
||||
int (*func)(const char *);
|
||||
const char *arg;
|
||||
int repeat;
|
||||
} open_temp_exec_file_opts[] = {
|
||||
{ open_temp_exec_file_env, "TMPDIR", 0 },
|
||||
{ open_temp_exec_file_dir, "/tmp", 0 },
|
||||
{ open_temp_exec_file_dir, "/var/tmp", 0 },
|
||||
{ open_temp_exec_file_dir, "/dev/shm", 0 },
|
||||
{ open_temp_exec_file_env, "HOME", 0 },
|
||||
#ifdef HAVE_MNTENT
|
||||
{ open_temp_exec_file_mnt, "/etc/mtab", 1 },
|
||||
{ open_temp_exec_file_mnt, "/proc/mounts", 1 },
|
||||
#endif /* HAVE_MNTENT */
|
||||
};
|
||||
|
||||
/* Current index into open_temp_exec_file_opts. */
|
||||
static int open_temp_exec_file_opts_idx = 0;
|
||||
|
||||
/* Reset a current multi-call func, then advances to the next entry.
|
||||
If we're at the last, go back to the first and return nonzero,
|
||||
otherwise return zero. */
|
||||
static int
|
||||
open_temp_exec_file_opts_next (void)
|
||||
{
|
||||
if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
|
||||
open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL);
|
||||
|
||||
open_temp_exec_file_opts_idx++;
|
||||
if (open_temp_exec_file_opts_idx
|
||||
== (sizeof (open_temp_exec_file_opts)
|
||||
/ sizeof (*open_temp_exec_file_opts)))
|
||||
{
|
||||
open_temp_exec_file_opts_idx = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return a file descriptor of a temporary zero-sized file in a
|
||||
writable and exexutable filesystem. */
|
||||
static int
|
||||
open_temp_exec_file (void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
do
|
||||
{
|
||||
fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func
|
||||
(open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg);
|
||||
|
||||
if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat
|
||||
|| fd == -1)
|
||||
{
|
||||
if (open_temp_exec_file_opts_next ())
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (fd == -1);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Map in a chunk of memory from the temporary exec file into separate
|
||||
locations in the virtual memory address space, one writable and one
|
||||
executable. Returns the address of the writable portion, after
|
||||
storing an offset to the corresponding executable portion at the
|
||||
last word of the requested chunk. */
|
||||
static void *
|
||||
dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
if (execfd == -1)
|
||||
{
|
||||
open_temp_exec_file_opts_idx = 0;
|
||||
retry_open:
|
||||
execfd = open_temp_exec_file ();
|
||||
if (execfd == -1)
|
||||
return MFAIL;
|
||||
}
|
||||
|
||||
offset = execsize;
|
||||
|
||||
if (ftruncate (execfd, offset + length))
|
||||
return MFAIL;
|
||||
|
||||
flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS);
|
||||
flags |= MAP_SHARED;
|
||||
|
||||
ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC,
|
||||
flags, execfd, offset);
|
||||
if (ptr == MFAIL)
|
||||
{
|
||||
if (!offset)
|
||||
{
|
||||
close (execfd);
|
||||
goto retry_open;
|
||||
}
|
||||
ftruncate (execfd, offset);
|
||||
return MFAIL;
|
||||
}
|
||||
else if (!offset
|
||||
&& open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
|
||||
open_temp_exec_file_opts_next ();
|
||||
|
||||
start = mmap (start, length, prot, flags, execfd, offset);
|
||||
|
||||
if (start == MFAIL)
|
||||
{
|
||||
munmap (ptr, length);
|
||||
ftruncate (execfd, offset);
|
||||
return start;
|
||||
}
|
||||
|
||||
mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start;
|
||||
|
||||
execsize += length;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
/* Map in a writable and executable chunk of memory if possible.
|
||||
Failing that, fall back to dlmmap_locked. */
|
||||
static void *
|
||||
dlmmap (void *start, size_t length, int prot,
|
||||
int flags, int fd, off_t offset)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
assert (start == NULL && length % malloc_getpagesize == 0
|
||||
&& prot == (PROT_READ | PROT_WRITE)
|
||||
&& flags == (MAP_PRIVATE | MAP_ANONYMOUS)
|
||||
&& fd == -1 && offset == 0);
|
||||
|
||||
#if FFI_CLOSURE_TEST
|
||||
printf ("mapping in %zi\n", length);
|
||||
#endif
|
||||
|
||||
if (execfd == -1 && is_emutramp_enabled ())
|
||||
{
|
||||
ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
if (execfd == -1 && !is_selinux_enabled ())
|
||||
{
|
||||
ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
|
||||
|
||||
if (ptr != MFAIL || (errno != EPERM && errno != EACCES))
|
||||
/* Cool, no need to mess with separate segments. */
|
||||
return ptr;
|
||||
|
||||
/* If MREMAP_DUP is ever introduced and implemented, try mmap
|
||||
with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with
|
||||
MREMAP_DUP and prot at this point. */
|
||||
}
|
||||
|
||||
if (execsize == 0 || execfd == -1)
|
||||
{
|
||||
pthread_mutex_lock (&open_temp_exec_file_mutex);
|
||||
ptr = dlmmap_locked (start, length, prot, flags, offset);
|
||||
pthread_mutex_unlock (&open_temp_exec_file_mutex);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
return dlmmap_locked (start, length, prot, flags, offset);
|
||||
}
|
||||
|
||||
/* Release memory at the given address, as well as the corresponding
|
||||
executable page if it's separate. */
|
||||
static int
|
||||
dlmunmap (void *start, size_t length)
|
||||
{
|
||||
/* We don't bother decreasing execsize or truncating the file, since
|
||||
we can't quite tell whether we're unmapping the end of the file.
|
||||
We don't expect frequent deallocation anyway. If we did, we
|
||||
could locate pages in the file by writing to the pages being
|
||||
deallocated and checking that the file contents change.
|
||||
Yuck. */
|
||||
msegmentptr seg = segment_holding (gm, start);
|
||||
void *code;
|
||||
|
||||
#if FFI_CLOSURE_TEST
|
||||
printf ("unmapping %zi\n", length);
|
||||
#endif
|
||||
|
||||
if (seg && (code = add_segment_exec_offset (start, seg)) != start)
|
||||
{
|
||||
int ret = munmap (code, length);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return munmap (start, length);
|
||||
}
|
||||
|
||||
#if FFI_CLOSURE_FREE_CODE
|
||||
/* Return segment holding given code address. */
|
||||
static msegmentptr
|
||||
segment_holding_code (mstate m, char* addr)
|
||||
{
|
||||
msegmentptr sp = &m->seg;
|
||||
for (;;) {
|
||||
if (addr >= add_segment_exec_offset (sp->base, sp)
|
||||
&& addr < add_segment_exec_offset (sp->base, sp) + sp->size)
|
||||
return sp;
|
||||
if ((sp = sp->next) == 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
|
||||
|
||||
/* Allocate a chunk of memory with the given size. Returns a pointer
|
||||
to the writable address, and sets *CODE to the executable
|
||||
corresponding virtual address. */
|
||||
void *
|
||||
ffi_closure_alloc (size_t size, void **code)
|
||||
{
|
||||
*code = malloc(size);
|
||||
return *code;
|
||||
#if 0
|
||||
void *ptr;
|
||||
|
||||
if (!code)
|
||||
return NULL;
|
||||
|
||||
ptr = dlmalloc (size);
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
msegmentptr seg = segment_holding (gm, ptr);
|
||||
|
||||
*code = add_segment_exec_offset (ptr, seg);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Release a chunk of memory allocated with ffi_closure_alloc. If
|
||||
FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the
|
||||
writable or the executable address given. Otherwise, only the
|
||||
writable address can be provided here. */
|
||||
void
|
||||
ffi_closure_free (void *ptr)
|
||||
{
|
||||
#if 0
|
||||
#if FFI_CLOSURE_FREE_CODE
|
||||
msegmentptr seg = segment_holding_code(gm, ptr);
|
||||
|
||||
if (seg)
|
||||
ptr = sub_segment_exec_offset(ptr, seg);
|
||||
#endif
|
||||
|
||||
dlfree(ptr);
|
||||
#endif
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
|
||||
#if FFI_CLOSURE_TEST
|
||||
/* Do some internal sanity testing to make sure allocation and
|
||||
deallocation of pages are working as intended. */
|
||||
int main ()
|
||||
{
|
||||
void *p[3];
|
||||
#define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0)
|
||||
#define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0)
|
||||
GET (0, malloc_getpagesize / 2);
|
||||
GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*));
|
||||
PUT (1);
|
||||
GET (1, 2 * malloc_getpagesize);
|
||||
GET (2, malloc_getpagesize / 2);
|
||||
PUT (1);
|
||||
PUT (0);
|
||||
PUT (2);
|
||||
return 0;
|
||||
}
|
||||
#endif /* FFI_CLOSURE_TEST */
|
||||
# else /* ! FFI_MMAP_EXEC_WRIT */
|
||||
|
||||
/* On many systems, memory returned by malloc is writable and
|
||||
executable, so just use it. */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
void *
|
||||
ffi_closure_alloc (size_t size, void **code)
|
||||
{
|
||||
if (!code)
|
||||
return NULL;
|
||||
|
||||
return *code = malloc (size);
|
||||
}
|
||||
|
||||
void
|
||||
ffi_closure_free (void *ptr)
|
||||
{
|
||||
free (ptr);
|
||||
}
|
||||
|
||||
# endif /* ! FFI_MMAP_EXEC_WRIT */
|
||||
#endif /* FFI_CLOSURES */
|
||||
841
lib/wrappers/libffi/gcc/ffi.c
Normal file
841
lib/wrappers/libffi/gcc/ffi.c
Normal file
|
|
@ -0,0 +1,841 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc.
|
||||
Copyright (c) 2002 Ranjit Mathew
|
||||
Copyright (c) 2002 Bo Thorsen
|
||||
Copyright (c) 2002 Roger Sayle
|
||||
Copyright (C) 2008, 2010 Free Software Foundation, Inc.
|
||||
|
||||
x86 Foreign Function Interface
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#if !defined(__x86_64__) || defined(_WIN64)
|
||||
|
||||
#ifdef _WIN64
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
#ifdef X86_WIN32
|
||||
size_t p_stack_args[2];
|
||||
void *p_stack_data[2];
|
||||
char *argp2 = stack;
|
||||
int stack_args_count = 0;
|
||||
int cabi = ecif->cif->abi;
|
||||
#endif
|
||||
|
||||
argp = stack;
|
||||
|
||||
if ((ecif->cif->flags == FFI_TYPE_STRUCT
|
||||
|| ecif->cif->flags == FFI_TYPE_MS_STRUCT)
|
||||
#ifdef X86_WIN64
|
||||
&& (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
|
||||
&& ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
#ifdef X86_WIN32
|
||||
/* For fastcall/thiscall this is first register-passed
|
||||
argument. */
|
||||
if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
|
||||
{
|
||||
p_stack_args[stack_args_count] = sizeof (void*);
|
||||
p_stack_data[stack_args_count] = argp;
|
||||
++stack_args_count;
|
||||
}
|
||||
#endif
|
||||
argp += sizeof(void*);
|
||||
}
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
i != 0;
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(void*) - 1) & (size_t) argp)
|
||||
argp = (char *) ALIGN(argp, sizeof(void*));
|
||||
|
||||
z = (*p_arg)->size;
|
||||
#ifdef X86_WIN64
|
||||
if (z > sizeof(ffi_arg)
|
||||
|| ((*p_arg)->type == FFI_TYPE_STRUCT
|
||||
&& (z != 1 && z != 2 && z != 4 && z != 8))
|
||||
#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
|
||||
|| ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
z = sizeof(ffi_arg);
|
||||
*(void **)argp = *p_argv;
|
||||
}
|
||||
else if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (z < sizeof(ffi_arg))
|
||||
{
|
||||
z = sizeof(ffi_arg);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
*(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
*(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
|
||||
#ifdef X86_WIN32
|
||||
/* For thiscall/fastcall convention register-passed arguments
|
||||
are the first two none-floating-point arguments with a size
|
||||
smaller or equal to sizeof (void*). */
|
||||
if ((cabi == FFI_THISCALL && stack_args_count < 1)
|
||||
|| (cabi == FFI_FASTCALL && stack_args_count < 2))
|
||||
{
|
||||
if (z <= 4
|
||||
&& ((*p_arg)->type != FFI_TYPE_FLOAT
|
||||
&& (*p_arg)->type != FFI_TYPE_STRUCT))
|
||||
{
|
||||
p_stack_args[stack_args_count] = z;
|
||||
p_stack_data[stack_args_count] = argp;
|
||||
++stack_args_count;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
p_argv++;
|
||||
#ifdef X86_WIN64
|
||||
argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
|
||||
#else
|
||||
argp += z;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef X86_WIN32
|
||||
/* We need to move the register-passed arguments for thiscall/fastcall
|
||||
on top of stack, so that those can be moved to registers ecx/edx by
|
||||
call-handler. */
|
||||
if (stack_args_count > 0)
|
||||
{
|
||||
size_t zz = (p_stack_args[0] + 3) & ~3;
|
||||
char *h;
|
||||
|
||||
/* Move first argument to top-stack position. */
|
||||
if (p_stack_data[0] != argp2)
|
||||
{
|
||||
h = alloca (zz + 1);
|
||||
memcpy (h, p_stack_data[0], zz);
|
||||
memmove (argp2 + zz, argp2,
|
||||
(size_t) ((char *) p_stack_data[0] - (char*)argp2));
|
||||
memcpy (argp2, h, zz);
|
||||
}
|
||||
|
||||
argp2 += zz;
|
||||
--stack_args_count;
|
||||
if (zz > 4)
|
||||
stack_args_count = 0;
|
||||
|
||||
/* If we have a second argument, then move it on top
|
||||
after the first one. */
|
||||
if (stack_args_count > 0 && p_stack_data[1] != argp2)
|
||||
{
|
||||
zz = p_stack_args[1];
|
||||
zz = (zz + 3) & ~3;
|
||||
h = alloca (zz + 1);
|
||||
h = alloca (zz + 1);
|
||||
memcpy (h, p_stack_data[1], zz);
|
||||
memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2));
|
||||
memcpy (argp2, h, zz);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
unsigned int i;
|
||||
ffi_type **ptr;
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
#ifdef X86_WIN64
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
#endif
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
#ifndef X86_WIN64
|
||||
#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
#endif
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
#ifdef X86_WIN64
|
||||
case FFI_TYPE_POINTER:
|
||||
#endif
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#ifndef X86
|
||||
if (cif->rtype->size == 1)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
|
||||
}
|
||||
else if (cif->rtype->size == 2)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
|
||||
}
|
||||
else if (cif->rtype->size == 4)
|
||||
{
|
||||
#ifdef X86_WIN64
|
||||
cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
|
||||
#else
|
||||
cif->flags = FFI_TYPE_INT; /* same as int type */
|
||||
#endif
|
||||
}
|
||||
else if (cif->rtype->size == 8)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef X86_WIN32
|
||||
if (cif->abi == FFI_MS_CDECL)
|
||||
cif->flags = FFI_TYPE_MS_STRUCT;
|
||||
else
|
||||
#endif
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
/* allocate space for return value pointer */
|
||||
cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef X86_WIN64
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
case FFI_TYPE_INT:
|
||||
cif->flags = FFI_TYPE_SINT32;
|
||||
#else
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
if (((*ptr)->alignment - 1) & cif->bytes)
|
||||
cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
|
||||
cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
|
||||
}
|
||||
|
||||
#ifdef X86_WIN64
|
||||
/* ensure space for storing four registers */
|
||||
cif->bytes += 4 * sizeof(ffi_arg);
|
||||
#endif
|
||||
|
||||
cif->bytes = (cif->bytes + 15) & ~0xF;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
#ifdef X86_WIN64
|
||||
extern int
|
||||
ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
#elif defined(X86_WIN32)
|
||||
extern void
|
||||
ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
#else
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
#endif
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return */
|
||||
/* value address then we need to make one */
|
||||
|
||||
#ifdef X86_WIN64
|
||||
if (rvalue == NULL
|
||||
&& cif->flags == FFI_TYPE_STRUCT
|
||||
&& cif->rtype->size != 1 && cif->rtype->size != 2
|
||||
&& cif->rtype->size != 4 && cif->rtype->size != 8)
|
||||
{
|
||||
ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
|
||||
}
|
||||
#else
|
||||
if (rvalue == NULL
|
||||
&& (cif->flags == FFI_TYPE_STRUCT
|
||||
|| cif->flags == FFI_TYPE_MS_STRUCT))
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
#ifdef X86_WIN64
|
||||
case FFI_WIN64:
|
||||
ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
#elif defined(X86_WIN32)
|
||||
case FFI_SYSV:
|
||||
case FFI_STDCALL:
|
||||
case FFI_MS_CDECL:
|
||||
ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
case FFI_THISCALL:
|
||||
case FFI_FASTCALL:
|
||||
{
|
||||
unsigned int abi = cif->abi;
|
||||
unsigned int i, passed_regs = 0;
|
||||
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
++passed_regs;
|
||||
|
||||
for (i=0; i < cif->nargs && passed_regs < 2;i++)
|
||||
{
|
||||
size_t sz;
|
||||
|
||||
if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
|
||||
|| cif->arg_types[i]->type == FFI_TYPE_STRUCT)
|
||||
continue;
|
||||
sz = (cif->arg_types[i]->size + 3) & ~3;
|
||||
if (sz == 0 || sz > 4)
|
||||
continue;
|
||||
++passed_regs;
|
||||
}
|
||||
if (passed_regs < 2 && abi == FFI_FASTCALL)
|
||||
abi = FFI_THISCALL;
|
||||
if (passed_regs < 1 && abi == FFI_THISCALL)
|
||||
abi = FFI_STDCALL;
|
||||
ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
|
||||
fn);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** private members **/
|
||||
|
||||
/* The following __attribute__((regparm(1))) decorations will have no effect
|
||||
on MSVC or SUNPRO_C -- standard conventions apply. */
|
||||
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
|
||||
void** args, ffi_cif* cif);
|
||||
void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
|
||||
__attribute__ ((regparm(1)));
|
||||
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
#ifdef X86_WIN32
|
||||
void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
#endif
|
||||
#ifdef X86_WIN64
|
||||
void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
|
||||
#endif
|
||||
|
||||
/* This function is jumped to by the trampoline */
|
||||
|
||||
#ifdef X86_WIN64
|
||||
void * FFI_HIDDEN
|
||||
ffi_closure_win64_inner (ffi_closure *closure, void *args) {
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
void *result;
|
||||
void *resp = &result;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
|
||||
/* this call will initialize ARG_AREA, such that each
|
||||
* element in that array points to the corresponding
|
||||
* value on the stack; and if the function returns
|
||||
* a structure, it will change RESP to point to the
|
||||
* structure return address. */
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, resp, arg_area, closure->user_data);
|
||||
|
||||
/* The result is returned in rax. This does the right thing for
|
||||
result types except for floats; we have to 'mov xmm0, rax' in the
|
||||
caller to correct this.
|
||||
TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
|
||||
*/
|
||||
return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
|
||||
}
|
||||
|
||||
#else
|
||||
unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
|
||||
ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
|
||||
{
|
||||
/* our various things... */
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
|
||||
/* this call will initialize ARG_AREA, such that each
|
||||
* element in that array points to the corresponding
|
||||
* value on the stack; and if the function returns
|
||||
* a structure, it will change RESP to point to the
|
||||
* structure return address. */
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, *respp, arg_area, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
#endif /* !X86_WIN64 */
|
||||
|
||||
static void
|
||||
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
|
||||
ffi_cif *cif)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
#ifdef X86_WIN64
|
||||
if (cif->rtype->size > sizeof(ffi_arg)
|
||||
|| (cif->flags == FFI_TYPE_STRUCT
|
||||
&& (cif->rtype->size != 1 && cif->rtype->size != 2
|
||||
&& cif->rtype->size != 4 && cif->rtype->size != 8))) {
|
||||
*rvalue = *(void **) argp;
|
||||
argp += sizeof(void *);
|
||||
}
|
||||
#else
|
||||
if ( cif->flags == FFI_TYPE_STRUCT
|
||||
|| cif->flags == FFI_TYPE_MS_STRUCT ) {
|
||||
*rvalue = *(void **) argp;
|
||||
argp += sizeof(void *);
|
||||
}
|
||||
#endif
|
||||
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(void*) - 1) & (size_t) argp) {
|
||||
argp = (char *) ALIGN(argp, sizeof(void*));
|
||||
}
|
||||
|
||||
#ifdef X86_WIN64
|
||||
if ((*p_arg)->size > sizeof(ffi_arg)
|
||||
|| ((*p_arg)->type == FFI_TYPE_STRUCT
|
||||
&& ((*p_arg)->size != 1 && (*p_arg)->size != 2
|
||||
&& (*p_arg)->size != 4 && (*p_arg)->size != 8)))
|
||||
{
|
||||
z = sizeof(void *);
|
||||
*p_argv = *(void **)argp;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
z = (*p_arg)->size;
|
||||
|
||||
/* because we're little endian, this is what it turns into. */
|
||||
|
||||
*p_argv = (void*) argp;
|
||||
}
|
||||
|
||||
p_argv++;
|
||||
#ifdef X86_WIN64
|
||||
argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
|
||||
#else
|
||||
argp += z;
|
||||
#endif
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
|
||||
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
void* __fun = (void*)(FUN); \
|
||||
void* __ctx = (void*)(CTX); \
|
||||
*(unsigned char*) &__tramp[0] = 0x41; \
|
||||
*(unsigned char*) &__tramp[1] = 0xbb; \
|
||||
*(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
|
||||
*(unsigned char*) &__tramp[6] = 0x48; \
|
||||
*(unsigned char*) &__tramp[7] = 0xb8; \
|
||||
*(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
|
||||
*(unsigned char *) &__tramp[16] = 0x49; \
|
||||
*(unsigned char *) &__tramp[17] = 0xba; \
|
||||
*(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
|
||||
*(unsigned char *) &__tramp[26] = 0x41; \
|
||||
*(unsigned char *) &__tramp[27] = 0xff; \
|
||||
*(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \
|
||||
}
|
||||
|
||||
/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
|
||||
|
||||
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
|
||||
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
unsigned int __fun = (unsigned int)(FUN); \
|
||||
unsigned int __ctx = (unsigned int)(CTX); \
|
||||
unsigned int __dis = __fun - (__ctx + 10); \
|
||||
*(unsigned char*) &__tramp[0] = 0xb8; \
|
||||
*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
|
||||
*(unsigned char *) &__tramp[5] = 0xe9; \
|
||||
*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
|
||||
}
|
||||
|
||||
#define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \
|
||||
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
unsigned int __fun = (unsigned int)(FUN); \
|
||||
unsigned int __ctx = (unsigned int)(CTX); \
|
||||
unsigned int __dis = __fun - (__ctx + 49); \
|
||||
unsigned short __size = (unsigned short)(SIZE); \
|
||||
*(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \
|
||||
*(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \
|
||||
*(unsigned int *) &__tramp[8] = 0x04890424; /* mov %ecx, 4(%esp) */ \
|
||||
*(unsigned char*) &__tramp[12] = 0x24; /* mov %eax, (%esp) */ \
|
||||
*(unsigned char*) &__tramp[13] = 0xb8; \
|
||||
*(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \
|
||||
*(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \
|
||||
*(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
|
||||
*(unsigned short*) &__tramp[26] = 0x0b74; /* jz 1f */ \
|
||||
*(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \
|
||||
*(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
|
||||
*(unsigned char*) &__tramp[36] = 0x48; /* dec %eax */ \
|
||||
*(unsigned short*) &__tramp[37] = 0xf575; /* jnz 2b ; 1f: */ \
|
||||
*(unsigned char*) &__tramp[39] = 0xb8; \
|
||||
*(unsigned int*) &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
|
||||
*(unsigned char *) &__tramp[44] = 0xe8; \
|
||||
*(unsigned int*) &__tramp[45] = __dis; /* call __fun */ \
|
||||
*(unsigned char*) &__tramp[49] = 0xc2; /* ret */ \
|
||||
*(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \
|
||||
}
|
||||
|
||||
#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \
|
||||
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
unsigned int __fun = (unsigned int)(FUN); \
|
||||
unsigned int __ctx = (unsigned int)(CTX); \
|
||||
unsigned int __dis = __fun - (__ctx + 10); \
|
||||
unsigned short __size = (unsigned short)(SIZE); \
|
||||
*(unsigned char*) &__tramp[0] = 0xb8; \
|
||||
*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
|
||||
*(unsigned char *) &__tramp[5] = 0xe8; \
|
||||
*(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \
|
||||
*(unsigned char *) &__tramp[10] = 0xc2; \
|
||||
*(unsigned short*) &__tramp[11] = __size; /* ret __size */ \
|
||||
}
|
||||
|
||||
/* the cif must already be prep'ed */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
#ifdef X86_WIN64
|
||||
#define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
|
||||
#define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
|
||||
if (cif->abi == FFI_WIN64)
|
||||
{
|
||||
int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
|
||||
FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
|
||||
&ffi_closure_win64,
|
||||
codeloc, mask);
|
||||
/* make sure we can execute here */
|
||||
}
|
||||
#else
|
||||
if (cif->abi == FFI_SYSV)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0],
|
||||
&ffi_closure_SYSV,
|
||||
(void*)codeloc);
|
||||
}
|
||||
#ifdef X86_WIN32
|
||||
else if (cif->abi == FFI_THISCALL)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0],
|
||||
&ffi_closure_THISCALL,
|
||||
(void*)codeloc,
|
||||
cif->bytes);
|
||||
}
|
||||
else if (cif->abi == FFI_STDCALL)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
|
||||
&ffi_closure_STDCALL,
|
||||
(void*)codeloc, cif->bytes);
|
||||
}
|
||||
else if (cif->abi == FFI_MS_CDECL)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0],
|
||||
&ffi_closure_SYSV,
|
||||
(void*)codeloc);
|
||||
}
|
||||
#endif /* X86_WIN32 */
|
||||
#endif /* !X86_WIN64 */
|
||||
else
|
||||
{
|
||||
return FFI_BAD_ABI;
|
||||
}
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* ------- Native raw API support -------------------------------- */
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (cif->abi != FFI_SYSV) {
|
||||
#ifdef X86_WIN32
|
||||
if (cif->abi != FFI_THISCALL)
|
||||
#endif
|
||||
return FFI_BAD_ABI;
|
||||
}
|
||||
|
||||
/* we currently don't support certain kinds of arguments for raw
|
||||
closures. This should be implemented by a separate assembly
|
||||
language routine, since it would require argument processing,
|
||||
something we don't do now for performance. */
|
||||
|
||||
for (i = cif->nargs-1; i >= 0; i--)
|
||||
{
|
||||
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
|
||||
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
|
||||
}
|
||||
|
||||
#ifdef X86_WIN32
|
||||
if (cif->abi == FFI_SYSV)
|
||||
{
|
||||
#endif
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
|
||||
codeloc);
|
||||
#ifdef X86_WIN32
|
||||
}
|
||||
else if (cif->abi == FFI_THISCALL)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL,
|
||||
codeloc, cif->bytes);
|
||||
}
|
||||
#endif
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_prep_args_raw(char *stack, extended_cif *ecif)
|
||||
{
|
||||
memcpy (stack, ecif->avalue, ecif->cif->bytes);
|
||||
}
|
||||
|
||||
/* we borrow this routine from libffi (it must be changed, though, to
|
||||
* actually call the function passed in the first argument. as of
|
||||
* libffi-1.20, this is not the case.)
|
||||
*/
|
||||
|
||||
void
|
||||
ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
void **avalue = (void **)fake_avalue;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return */
|
||||
/* value address then we need to make one */
|
||||
|
||||
if (rvalue == NULL
|
||||
&& (cif->flags == FFI_TYPE_STRUCT
|
||||
|| cif->flags == FFI_TYPE_MS_STRUCT))
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
#ifdef X86_WIN32
|
||||
case FFI_SYSV:
|
||||
case FFI_STDCALL:
|
||||
case FFI_MS_CDECL:
|
||||
ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
case FFI_THISCALL:
|
||||
case FFI_FASTCALL:
|
||||
{
|
||||
unsigned int abi = cif->abi;
|
||||
unsigned int i, passed_regs = 0;
|
||||
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
++passed_regs;
|
||||
|
||||
for (i=0; i < cif->nargs && passed_regs < 2;i++)
|
||||
{
|
||||
size_t sz;
|
||||
|
||||
if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
|
||||
|| cif->arg_types[i]->type == FFI_TYPE_STRUCT)
|
||||
continue;
|
||||
sz = (cif->arg_types[i]->size + 3) & ~3;
|
||||
if (sz == 0 || sz > 4)
|
||||
continue;
|
||||
++passed_regs;
|
||||
}
|
||||
if (passed_regs < 2 && abi == FFI_FASTCALL)
|
||||
cif->abi = abi = FFI_THISCALL;
|
||||
if (passed_regs < 1 && abi == FFI_THISCALL)
|
||||
cif->abi = abi = FFI_STDCALL;
|
||||
ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !__x86_64__ || X86_WIN64 */
|
||||
|
||||
673
lib/wrappers/libffi/gcc/ffi64.c
Normal file
673
lib/wrappers/libffi/gcc/ffi64.c
Normal file
|
|
@ -0,0 +1,673 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi64.c - Copyright (c) 2013 The Written Word, Inc.
|
||||
Copyright (c) 2011 Anthony Green
|
||||
Copyright (c) 2008, 2010 Red Hat, Inc.
|
||||
Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
|
||||
|
||||
x86-64 Foreign Function Interface
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
#define MAX_GPR_REGS 6
|
||||
#define MAX_SSE_REGS 8
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#define UINT128 __m128
|
||||
#else
|
||||
#if defined(__SUNPRO_C)
|
||||
#include <sunmedia_types.h>
|
||||
#define UINT128 __m128i
|
||||
#else
|
||||
#define UINT128 __int128_t
|
||||
#endif
|
||||
#endif
|
||||
|
||||
union big_int_union
|
||||
{
|
||||
UINT32 i32;
|
||||
UINT64 i64;
|
||||
UINT128 i128;
|
||||
};
|
||||
|
||||
struct register_args
|
||||
{
|
||||
/* Registers for argument passing. */
|
||||
UINT64 gpr[MAX_GPR_REGS];
|
||||
union big_int_union sse[MAX_SSE_REGS];
|
||||
};
|
||||
|
||||
extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
|
||||
void *raddr, void (*fnaddr)(void), unsigned ssecount);
|
||||
|
||||
/* All reference to register classes here is identical to the code in
|
||||
gcc/config/i386/i386.c. Do *not* change one without the other. */
|
||||
|
||||
/* Register class used for passing given 64bit part of the argument.
|
||||
These represent classes as documented by the PS ABI, with the
|
||||
exception of SSESF, SSEDF classes, that are basically SSE class,
|
||||
just gcc will use SF or DFmode move instead of DImode to avoid
|
||||
reformatting penalties.
|
||||
|
||||
Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
|
||||
whenever possible (upper half does contain padding). */
|
||||
enum x86_64_reg_class
|
||||
{
|
||||
X86_64_NO_CLASS,
|
||||
X86_64_INTEGER_CLASS,
|
||||
X86_64_INTEGERSI_CLASS,
|
||||
X86_64_SSE_CLASS,
|
||||
X86_64_SSESF_CLASS,
|
||||
X86_64_SSEDF_CLASS,
|
||||
X86_64_SSEUP_CLASS,
|
||||
X86_64_X87_CLASS,
|
||||
X86_64_X87UP_CLASS,
|
||||
X86_64_COMPLEX_X87_CLASS,
|
||||
X86_64_MEMORY_CLASS
|
||||
};
|
||||
|
||||
#define MAX_CLASSES 4
|
||||
|
||||
#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
|
||||
|
||||
/* x86-64 register passing implementation. See x86-64 ABI for details. Goal
|
||||
of this code is to classify each 8bytes of incoming argument by the register
|
||||
class and assign registers accordingly. */
|
||||
|
||||
/* Return the union class of CLASS1 and CLASS2.
|
||||
See the x86-64 PS ABI for details. */
|
||||
|
||||
static enum x86_64_reg_class
|
||||
merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
|
||||
{
|
||||
/* Rule #1: If both classes are equal, this is the resulting class. */
|
||||
if (class1 == class2)
|
||||
return class1;
|
||||
|
||||
/* Rule #2: If one of the classes is NO_CLASS, the resulting class is
|
||||
the other class. */
|
||||
if (class1 == X86_64_NO_CLASS)
|
||||
return class2;
|
||||
if (class2 == X86_64_NO_CLASS)
|
||||
return class1;
|
||||
|
||||
/* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
|
||||
if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
|
||||
return X86_64_MEMORY_CLASS;
|
||||
|
||||
/* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
|
||||
if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
|
||||
|| (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
|
||||
return X86_64_INTEGERSI_CLASS;
|
||||
if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
|
||||
|| class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
|
||||
return X86_64_INTEGER_CLASS;
|
||||
|
||||
/* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
|
||||
MEMORY is used. */
|
||||
if (class1 == X86_64_X87_CLASS
|
||||
|| class1 == X86_64_X87UP_CLASS
|
||||
|| class1 == X86_64_COMPLEX_X87_CLASS
|
||||
|| class2 == X86_64_X87_CLASS
|
||||
|| class2 == X86_64_X87UP_CLASS
|
||||
|| class2 == X86_64_COMPLEX_X87_CLASS)
|
||||
return X86_64_MEMORY_CLASS;
|
||||
|
||||
/* Rule #6: Otherwise class SSE is used. */
|
||||
return X86_64_SSE_CLASS;
|
||||
}
|
||||
|
||||
/* Classify the argument of type TYPE and mode MODE.
|
||||
CLASSES will be filled by the register class used to pass each word
|
||||
of the operand. The number of words is returned. In case the parameter
|
||||
should be passed in memory, 0 is returned. As a special case for zero
|
||||
sized containers, classes[0] will be NO_CLASS and 1 is returned.
|
||||
|
||||
See the x86-64 PS ABI for details.
|
||||
*/
|
||||
static int
|
||||
classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
|
||||
size_t byte_offset)
|
||||
{
|
||||
switch (type->type)
|
||||
{
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT16:
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
{
|
||||
int size = byte_offset + type->size;
|
||||
|
||||
if (size <= 4)
|
||||
{
|
||||
classes[0] = X86_64_INTEGERSI_CLASS;
|
||||
return 1;
|
||||
}
|
||||
else if (size <= 8)
|
||||
{
|
||||
classes[0] = X86_64_INTEGER_CLASS;
|
||||
return 1;
|
||||
}
|
||||
else if (size <= 12)
|
||||
{
|
||||
classes[0] = X86_64_INTEGER_CLASS;
|
||||
classes[1] = X86_64_INTEGERSI_CLASS;
|
||||
return 2;
|
||||
}
|
||||
else if (size <= 16)
|
||||
{
|
||||
classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (!(byte_offset % 8))
|
||||
classes[0] = X86_64_SSESF_CLASS;
|
||||
else
|
||||
classes[0] = X86_64_SSE_CLASS;
|
||||
return 1;
|
||||
case FFI_TYPE_DOUBLE:
|
||||
classes[0] = X86_64_SSEDF_CLASS;
|
||||
return 1;
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
classes[0] = X86_64_X87_CLASS;
|
||||
classes[1] = X86_64_X87UP_CLASS;
|
||||
return 2;
|
||||
case FFI_TYPE_STRUCT:
|
||||
{
|
||||
const int UNITS_PER_WORD = 8;
|
||||
int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
|
||||
ffi_type **ptr;
|
||||
int i;
|
||||
enum x86_64_reg_class subclasses[MAX_CLASSES];
|
||||
|
||||
/* If the struct is larger than 32 bytes, pass it on the stack. */
|
||||
if (type->size > 32)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < words; i++)
|
||||
classes[i] = X86_64_NO_CLASS;
|
||||
|
||||
/* Zero sized arrays or structures are NO_CLASS. We return 0 to
|
||||
signalize memory class, so handle it as special case. */
|
||||
if (!words)
|
||||
{
|
||||
classes[0] = X86_64_NO_CLASS;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Merge the fields of structure. */
|
||||
for (ptr = type->elements; *ptr != NULL; ptr++)
|
||||
{
|
||||
int num;
|
||||
|
||||
byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
|
||||
|
||||
num = classify_argument (*ptr, subclasses, byte_offset % 8);
|
||||
if (num == 0)
|
||||
return 0;
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
int pos = byte_offset / 8;
|
||||
classes[i + pos] =
|
||||
merge_classes (subclasses[i], classes[i + pos]);
|
||||
}
|
||||
|
||||
byte_offset += (*ptr)->size;
|
||||
}
|
||||
|
||||
if (words > 2)
|
||||
{
|
||||
/* When size > 16 bytes, if the first one isn't
|
||||
X86_64_SSE_CLASS or any other ones aren't
|
||||
X86_64_SSEUP_CLASS, everything should be passed in
|
||||
memory. */
|
||||
if (classes[0] != X86_64_SSE_CLASS)
|
||||
return 0;
|
||||
|
||||
for (i = 1; i < words; i++)
|
||||
if (classes[i] != X86_64_SSEUP_CLASS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Final merger cleanup. */
|
||||
for (i = 0; i < words; i++)
|
||||
{
|
||||
/* If one class is MEMORY, everything should be passed in
|
||||
memory. */
|
||||
if (classes[i] == X86_64_MEMORY_CLASS)
|
||||
return 0;
|
||||
|
||||
/* The X86_64_SSEUP_CLASS should be always preceded by
|
||||
X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */
|
||||
if (classes[i] == X86_64_SSEUP_CLASS
|
||||
&& classes[i - 1] != X86_64_SSE_CLASS
|
||||
&& classes[i - 1] != X86_64_SSEUP_CLASS)
|
||||
{
|
||||
/* The first one should never be X86_64_SSEUP_CLASS. */
|
||||
FFI_ASSERT (i != 0);
|
||||
classes[i] = X86_64_SSE_CLASS;
|
||||
}
|
||||
|
||||
/* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
|
||||
everything should be passed in memory. */
|
||||
if (classes[i] == X86_64_X87UP_CLASS
|
||||
&& (classes[i - 1] != X86_64_X87_CLASS))
|
||||
{
|
||||
/* The first one should never be X86_64_X87UP_CLASS. */
|
||||
FFI_ASSERT (i != 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return words;
|
||||
}
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
return 0; /* Never reached. */
|
||||
}
|
||||
|
||||
/* Examine the argument and return set number of register required in each
|
||||
class. Return zero iff parameter should be passed in memory, otherwise
|
||||
the number of registers. */
|
||||
|
||||
static int
|
||||
examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
|
||||
_Bool in_return, int *pngpr, int *pnsse)
|
||||
{
|
||||
int i, n, ngpr, nsse;
|
||||
|
||||
n = classify_argument (type, classes, 0);
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
ngpr = nsse = 0;
|
||||
for (i = 0; i < n; ++i)
|
||||
switch (classes[i])
|
||||
{
|
||||
case X86_64_INTEGER_CLASS:
|
||||
case X86_64_INTEGERSI_CLASS:
|
||||
ngpr++;
|
||||
break;
|
||||
case X86_64_SSE_CLASS:
|
||||
case X86_64_SSESF_CLASS:
|
||||
case X86_64_SSEDF_CLASS:
|
||||
nsse++;
|
||||
break;
|
||||
case X86_64_NO_CLASS:
|
||||
case X86_64_SSEUP_CLASS:
|
||||
break;
|
||||
case X86_64_X87_CLASS:
|
||||
case X86_64_X87UP_CLASS:
|
||||
case X86_64_COMPLEX_X87_CLASS:
|
||||
return in_return != 0;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
*pngpr = ngpr;
|
||||
*pnsse = nsse;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing. */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep (ffi_cif *cif)
|
||||
{
|
||||
int gprcount, ssecount, i, avn, n, ngpr, nsse, flags;
|
||||
enum x86_64_reg_class classes[MAX_CLASSES];
|
||||
size_t bytes;
|
||||
|
||||
gprcount = ssecount = 0;
|
||||
|
||||
flags = cif->rtype->type;
|
||||
if (flags != FFI_TYPE_VOID)
|
||||
{
|
||||
n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
|
||||
if (n == 0)
|
||||
{
|
||||
/* The return value is passed in memory. A pointer to that
|
||||
memory is the first argument. Allocate a register for it. */
|
||||
gprcount++;
|
||||
/* We don't have to do anything in asm for the return. */
|
||||
flags = FFI_TYPE_VOID;
|
||||
}
|
||||
else if (flags == FFI_TYPE_STRUCT)
|
||||
{
|
||||
/* Mark which registers the result appears in. */
|
||||
_Bool sse0 = SSE_CLASS_P (classes[0]);
|
||||
_Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
|
||||
if (sse0 && !sse1)
|
||||
flags |= 1 << 8;
|
||||
else if (!sse0 && sse1)
|
||||
flags |= 1 << 9;
|
||||
else if (sse0 && sse1)
|
||||
flags |= 1 << 10;
|
||||
/* Mark the true size of the structure. */
|
||||
flags |= cif->rtype->size << 12;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go over all arguments and determine the way they should be passed.
|
||||
If it's in a register and there is space for it, let that be so. If
|
||||
not, add it's size to the stack byte count. */
|
||||
for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
|
||||
{
|
||||
if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
|
||||
|| gprcount + ngpr > MAX_GPR_REGS
|
||||
|| ssecount + nsse > MAX_SSE_REGS)
|
||||
{
|
||||
long align = cif->arg_types[i]->alignment;
|
||||
|
||||
if (align < 8)
|
||||
align = 8;
|
||||
|
||||
bytes = ALIGN (bytes, align);
|
||||
bytes += cif->arg_types[i]->size;
|
||||
}
|
||||
else
|
||||
{
|
||||
gprcount += ngpr;
|
||||
ssecount += nsse;
|
||||
}
|
||||
}
|
||||
if (ssecount)
|
||||
flags |= 1 << 11;
|
||||
cif->flags = flags;
|
||||
cif->bytes = ALIGN (bytes, 8);
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
enum x86_64_reg_class classes[MAX_CLASSES];
|
||||
char *stack, *argp;
|
||||
ffi_type **arg_types;
|
||||
int gprcount, ssecount, ngpr, nsse, i, avn;
|
||||
_Bool ret_in_memory;
|
||||
struct register_args *reg_args;
|
||||
|
||||
/* Can't call 32-bit mode from 64-bit mode. */
|
||||
FFI_ASSERT (cif->abi == FFI_UNIX64);
|
||||
|
||||
/* If the return value is a struct and we don't have a return value
|
||||
address then we need to make one. Note the setting of flags to
|
||||
VOID above in ffi_prep_cif_machdep. */
|
||||
ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
&& (cif->flags & 0xff) == FFI_TYPE_VOID);
|
||||
if (rvalue == NULL && ret_in_memory)
|
||||
rvalue = alloca (cif->rtype->size);
|
||||
|
||||
/* Allocate the space for the arguments, plus 4 words of temp space. */
|
||||
stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
|
||||
reg_args = (struct register_args *) stack;
|
||||
argp = stack + sizeof (struct register_args);
|
||||
|
||||
gprcount = ssecount = 0;
|
||||
|
||||
/* If the return value is passed in memory, add the pointer as the
|
||||
first integer argument. */
|
||||
if (ret_in_memory)
|
||||
reg_args->gpr[gprcount++] = (unsigned long) rvalue;
|
||||
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
for (i = 0; i < avn; ++i)
|
||||
{
|
||||
size_t size = arg_types[i]->size;
|
||||
int n;
|
||||
|
||||
n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
|
||||
if (n == 0
|
||||
|| gprcount + ngpr > MAX_GPR_REGS
|
||||
|| ssecount + nsse > MAX_SSE_REGS)
|
||||
{
|
||||
long align = arg_types[i]->alignment;
|
||||
|
||||
/* Stack arguments are *always* at least 8 byte aligned. */
|
||||
if (align < 8)
|
||||
align = 8;
|
||||
|
||||
/* Pass this argument in memory. */
|
||||
argp = (void *) ALIGN (argp, align);
|
||||
memcpy (argp, avalue[i], size);
|
||||
argp += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The argument is passed entirely in registers. */
|
||||
char *a = (char *) avalue[i];
|
||||
int j;
|
||||
|
||||
for (j = 0; j < n; j++, a += 8, size -= 8)
|
||||
{
|
||||
switch (classes[j])
|
||||
{
|
||||
case X86_64_INTEGER_CLASS:
|
||||
case X86_64_INTEGERSI_CLASS:
|
||||
/* Sign-extend integer arguments passed in general
|
||||
purpose registers, to cope with the fact that
|
||||
LLVM incorrectly assumes that this will be done
|
||||
(the x86-64 PS ABI does not specify this). */
|
||||
switch (arg_types[i]->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT8 *) a);
|
||||
break;
|
||||
case FFI_TYPE_SINT16:
|
||||
*(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT16 *) a);
|
||||
break;
|
||||
case FFI_TYPE_SINT32:
|
||||
*(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT32 *) a);
|
||||
break;
|
||||
default:
|
||||
reg_args->gpr[gprcount] = 0;
|
||||
memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8);
|
||||
}
|
||||
gprcount++;
|
||||
break;
|
||||
case X86_64_SSE_CLASS:
|
||||
case X86_64_SSEDF_CLASS:
|
||||
reg_args->sse[ssecount++].i64 = *(UINT64 *) a;
|
||||
break;
|
||||
case X86_64_SSESF_CLASS:
|
||||
reg_args->sse[ssecount++].i32 = *(UINT32 *) a;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
|
||||
cif->flags, rvalue, fn, ssecount);
|
||||
}
|
||||
|
||||
|
||||
extern void ffi_closure_unix64(void);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
volatile unsigned short *tramp;
|
||||
|
||||
/* Sanity check on the cif ABI. */
|
||||
{
|
||||
int abi = cif->abi;
|
||||
if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI)))
|
||||
return FFI_BAD_ABI;
|
||||
}
|
||||
|
||||
tramp = (volatile unsigned short *) &closure->tramp[0];
|
||||
|
||||
tramp[0] = 0xbb49; /* mov <code>, %r11 */
|
||||
*((unsigned long long * volatile) &tramp[1])
|
||||
= (unsigned long) ffi_closure_unix64;
|
||||
tramp[5] = 0xba49; /* mov <data>, %r10 */
|
||||
*((unsigned long long * volatile) &tramp[6])
|
||||
= (unsigned long) codeloc;
|
||||
|
||||
/* Set the carry bit iff the function uses any sse registers.
|
||||
This is clc or stc, together with the first byte of the jmp. */
|
||||
tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
|
||||
|
||||
tramp[11] = 0xe3ff; /* jmp *%r11 */
|
||||
|
||||
closure->cif = cif;
|
||||
closure->fun = fun;
|
||||
closure->user_data = user_data;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
int
|
||||
ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
|
||||
struct register_args *reg_args, char *argp)
|
||||
{
|
||||
ffi_cif *cif;
|
||||
void **avalue;
|
||||
ffi_type **arg_types;
|
||||
long i, avn;
|
||||
int gprcount, ssecount, ngpr, nsse;
|
||||
int ret;
|
||||
|
||||
cif = closure->cif;
|
||||
avalue = alloca(cif->nargs * sizeof(void *));
|
||||
gprcount = ssecount = 0;
|
||||
|
||||
ret = cif->rtype->type;
|
||||
if (ret != FFI_TYPE_VOID)
|
||||
{
|
||||
enum x86_64_reg_class classes[MAX_CLASSES];
|
||||
int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
|
||||
if (n == 0)
|
||||
{
|
||||
/* The return value goes in memory. Arrange for the closure
|
||||
return value to go directly back to the original caller. */
|
||||
rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++];
|
||||
/* We don't have to do anything in asm for the return. */
|
||||
ret = FFI_TYPE_VOID;
|
||||
}
|
||||
else if (ret == FFI_TYPE_STRUCT && n == 2)
|
||||
{
|
||||
/* Mark which register the second word of the structure goes in. */
|
||||
_Bool sse0 = SSE_CLASS_P (classes[0]);
|
||||
_Bool sse1 = SSE_CLASS_P (classes[1]);
|
||||
if (!sse0 && sse1)
|
||||
ret |= 1 << 8;
|
||||
else if (sse0 && !sse1)
|
||||
ret |= 1 << 9;
|
||||
}
|
||||
}
|
||||
|
||||
avn = cif->nargs;
|
||||
arg_types = cif->arg_types;
|
||||
|
||||
for (i = 0; i < avn; ++i)
|
||||
{
|
||||
enum x86_64_reg_class classes[MAX_CLASSES];
|
||||
int n;
|
||||
|
||||
n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
|
||||
if (n == 0
|
||||
|| gprcount + ngpr > MAX_GPR_REGS
|
||||
|| ssecount + nsse > MAX_SSE_REGS)
|
||||
{
|
||||
long align = arg_types[i]->alignment;
|
||||
|
||||
/* Stack arguments are *always* at least 8 byte aligned. */
|
||||
if (align < 8)
|
||||
align = 8;
|
||||
|
||||
/* Pass this argument in memory. */
|
||||
argp = (void *) ALIGN (argp, align);
|
||||
avalue[i] = argp;
|
||||
argp += arg_types[i]->size;
|
||||
}
|
||||
/* If the argument is in a single register, or two consecutive
|
||||
integer registers, then we can use that address directly. */
|
||||
else if (n == 1
|
||||
|| (n == 2 && !(SSE_CLASS_P (classes[0])
|
||||
|| SSE_CLASS_P (classes[1]))))
|
||||
{
|
||||
/* The argument is in a single register. */
|
||||
if (SSE_CLASS_P (classes[0]))
|
||||
{
|
||||
avalue[i] = ®_args->sse[ssecount];
|
||||
ssecount += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
avalue[i] = ®_args->gpr[gprcount];
|
||||
gprcount += n;
|
||||
}
|
||||
}
|
||||
/* Otherwise, allocate space to make them consecutive. */
|
||||
else
|
||||
{
|
||||
char *a = alloca (16);
|
||||
int j;
|
||||
|
||||
avalue[i] = a;
|
||||
for (j = 0; j < n; j++, a += 8)
|
||||
{
|
||||
if (SSE_CLASS_P (classes[j]))
|
||||
memcpy (a, ®_args->sse[ssecount++], 8);
|
||||
else
|
||||
memcpy (a, ®_args->gpr[gprcount++], 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Invoke the closure. */
|
||||
closure->fun (cif, rvalue, avalue, closure->user_data);
|
||||
|
||||
/* Tell assembly how to perform return type promotions. */
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
237
lib/wrappers/libffi/gcc/prep_cif.c
Normal file
237
lib/wrappers/libffi/gcc/prep_cif.c
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
prep_cif.c - Copyright (c) 2011, 2012 Anthony Green
|
||||
Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Round up to FFI_SIZEOF_ARG. */
|
||||
|
||||
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
|
||||
|
||||
/* Perform machine independent initialization of aggregate type
|
||||
specifications. */
|
||||
|
||||
static ffi_status initialize_aggregate(ffi_type *arg)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
|
||||
if (UNLIKELY(arg == NULL || arg->elements == NULL))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
arg->size = 0;
|
||||
arg->alignment = 0;
|
||||
|
||||
ptr = &(arg->elements[0]);
|
||||
|
||||
if (UNLIKELY(ptr == 0))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
while ((*ptr) != NULL)
|
||||
{
|
||||
if (UNLIKELY(((*ptr)->size == 0)
|
||||
&& (initialize_aggregate((*ptr)) != FFI_OK)))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the argument type */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
arg->size = ALIGN(arg->size, (*ptr)->alignment);
|
||||
arg->size += (*ptr)->size;
|
||||
|
||||
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
||||
arg->alignment : (*ptr)->alignment;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* Structure size includes tail padding. This is important for
|
||||
structures that fit in one register on ABIs like the PowerPC64
|
||||
Linux ABI that right justify small structs in a register.
|
||||
It's also needed for nested structure layout, for example
|
||||
struct A { long a; char b; }; struct B { struct A x; char y; };
|
||||
should find y at an offset of 2*sizeof(long) and result in a
|
||||
total size of 3*sizeof(long). */
|
||||
arg->size = ALIGN (arg->size, arg->alignment);
|
||||
|
||||
if (arg->size == 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
else
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
#ifndef __CRIS__
|
||||
/* The CRIS ABI specifies structure elements to have byte
|
||||
alignment only, so it completely overrides this functions,
|
||||
which assumes "natural" alignment and padding. */
|
||||
|
||||
/* Perform machine independent ffi_cif preparation, then call
|
||||
machine dependent routine. */
|
||||
|
||||
/* For non variadic functions isvariadic should be 0 and
|
||||
nfixedargs==ntotalargs.
|
||||
|
||||
For variadic calls, isvariadic should be 1 and nfixedargs
|
||||
and ntotalargs set as appropriate. nfixedargs must always be >=1 */
|
||||
|
||||
|
||||
ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
|
||||
unsigned int isvariadic,
|
||||
unsigned int nfixedargs,
|
||||
unsigned int ntotalargs,
|
||||
ffi_type *rtype, ffi_type **atypes)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
unsigned int i;
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT(cif != NULL);
|
||||
FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
|
||||
FFI_ASSERT(nfixedargs <= ntotalargs);
|
||||
|
||||
#ifndef X86_WIN32
|
||||
if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
|
||||
return FFI_BAD_ABI;
|
||||
#else
|
||||
if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI || abi == FFI_THISCALL))
|
||||
return FFI_BAD_ABI;
|
||||
#endif
|
||||
|
||||
cif->abi = abi;
|
||||
cif->arg_types = atypes;
|
||||
cif->nargs = ntotalargs;
|
||||
cif->rtype = rtype;
|
||||
|
||||
cif->flags = 0;
|
||||
|
||||
/* Initialize the return type if necessary */
|
||||
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the return type */
|
||||
FFI_ASSERT_VALID_TYPE(cif->rtype);
|
||||
|
||||
/* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
|
||||
#if !defined M68K && !defined X86_ANY && !defined S390 && !defined PA
|
||||
/* Make space for the return structure pointer */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
#ifdef SPARC
|
||||
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
|
||||
#endif
|
||||
#ifdef TILE
|
||||
&& (cif->rtype->size > 10 * FFI_SIZEOF_ARG)
|
||||
#endif
|
||||
#ifdef XTENSA
|
||||
&& (cif->rtype->size > 16)
|
||||
#endif
|
||||
|
||||
)
|
||||
bytes = STACK_ARG_SIZE(sizeof(void*));
|
||||
#endif
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
|
||||
/* Initialize any uninitialized aggregate type definitions */
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the argument type, do this
|
||||
check after the initialization. */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
#if !defined X86_ANY && !defined S390 && !defined PA
|
||||
#ifdef SPARC
|
||||
if (((*ptr)->type == FFI_TYPE_STRUCT
|
||||
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|
||||
|| ((*ptr)->type == FFI_TYPE_LONGDOUBLE
|
||||
&& cif->abi != FFI_V9))
|
||||
bytes += sizeof(void*);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Add any padding if necessary */
|
||||
if (((*ptr)->alignment - 1) & bytes)
|
||||
bytes = ALIGN(bytes, (*ptr)->alignment);
|
||||
|
||||
#ifdef TILE
|
||||
if (bytes < 10 * FFI_SIZEOF_ARG &&
|
||||
bytes + STACK_ARG_SIZE((*ptr)->size) > 10 * FFI_SIZEOF_ARG)
|
||||
{
|
||||
/* An argument is never split between the 10 parameter
|
||||
registers and the stack. */
|
||||
bytes = 10 * FFI_SIZEOF_ARG;
|
||||
}
|
||||
#endif
|
||||
#ifdef XTENSA
|
||||
if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4)
|
||||
bytes = 6*4;
|
||||
#endif
|
||||
|
||||
bytes += STACK_ARG_SIZE((*ptr)->size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
cif->bytes = bytes;
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
#ifdef FFI_TARGET_SPECIFIC_VARIADIC
|
||||
if (isvariadic)
|
||||
return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs);
|
||||
#endif
|
||||
|
||||
return ffi_prep_cif_machdep(cif);
|
||||
}
|
||||
#endif /* not __CRIS__ */
|
||||
|
||||
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
|
||||
ffi_type *rtype, ffi_type **atypes)
|
||||
{
|
||||
return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes);
|
||||
}
|
||||
|
||||
ffi_status ffi_prep_cif_var(ffi_cif *cif,
|
||||
ffi_abi abi,
|
||||
unsigned int nfixedargs,
|
||||
unsigned int ntotalargs,
|
||||
ffi_type *rtype,
|
||||
ffi_type **atypes)
|
||||
{
|
||||
return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
|
||||
}
|
||||
|
||||
#if FFI_CLOSURES
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
{
|
||||
return ffi_prep_closure_loc (closure, cif, fun, user_data, closure);
|
||||
}
|
||||
|
||||
#endif
|
||||
77
lib/wrappers/libffi/gcc/types.c
Normal file
77
lib/wrappers/libffi/gcc/types.c
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
types.c - Copyright (c) 1996, 1998 Red Hat, Inc.
|
||||
|
||||
Predefined ffi_types needed by libffi.
|
||||
|
||||
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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* Hide the basic type definitions from the header file, so that we
|
||||
can redefine them here as "const". */
|
||||
#define LIBFFI_HIDE_BASIC_TYPES
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
/* Type definitions */
|
||||
|
||||
#define FFI_TYPEDEF(name, type, id) \
|
||||
struct struct_align_##name { \
|
||||
char c; \
|
||||
type x; \
|
||||
}; \
|
||||
const ffi_type ffi_type_##name = { \
|
||||
sizeof(type), \
|
||||
offsetof(struct struct_align_##name, x), \
|
||||
id, NULL \
|
||||
}
|
||||
|
||||
/* Size and alignment are fake here. They must not be 0. */
|
||||
const ffi_type ffi_type_void = {
|
||||
1, 1, FFI_TYPE_VOID, NULL
|
||||
};
|
||||
|
||||
FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8);
|
||||
FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8);
|
||||
FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16);
|
||||
FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16);
|
||||
FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32);
|
||||
FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32);
|
||||
FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64);
|
||||
FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64);
|
||||
|
||||
FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER);
|
||||
|
||||
FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT);
|
||||
FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE);
|
||||
|
||||
#ifdef __alpha__
|
||||
/* Even if we're not configured to default to 128-bit long double,
|
||||
maintain binary compatibility, as -mlong-double-128 can be used
|
||||
at any time. */
|
||||
/* Validate the hard-coded number below. */
|
||||
# if defined(__LONG_DOUBLE_128__) && FFI_TYPE_LONGDOUBLE != 4
|
||||
# error FFI_TYPE_LONGDOUBLE out of date
|
||||
# endif
|
||||
const ffi_type ffi_type_longdouble = { 16, 16, 4, NULL };
|
||||
#elif FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
||||
FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE);
|
||||
#endif
|
||||
759
lib/wrappers/libffi/gcc/win32_asm.asm
Normal file
759
lib/wrappers/libffi/gcc/win32_asm.asm
Normal file
|
|
@ -0,0 +1,759 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
win32.S - Copyright (c) 1996, 1998, 2001, 2002, 2009 Red Hat, Inc.
|
||||
Copyright (c) 2001 John Beniton
|
||||
Copyright (c) 2002 Ranjit Mathew
|
||||
Copyright (c) 2009 Daniel Witte
|
||||
|
||||
|
||||
X86 Foreign Function Interface
|
||||
|
||||
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.
|
||||
-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
#include <ffitarget.h>
|
||||
|
||||
.text
|
||||
|
||||
// This assumes we are using gas.
|
||||
.balign 16
|
||||
.globl _ffi_call_win32
|
||||
#ifndef __OS2__
|
||||
.def _ffi_call_win32; .scl 2; .type 32; .endef
|
||||
#endif
|
||||
_ffi_call_win32:
|
||||
.LFB1:
|
||||
pushl %ebp
|
||||
.LCFI0:
|
||||
movl %esp,%ebp
|
||||
.LCFI1:
|
||||
// Make room for all of the new args.
|
||||
movl 20(%ebp),%ecx
|
||||
subl %ecx,%esp
|
||||
|
||||
movl %esp,%eax
|
||||
|
||||
// Place all of the ffi_prep_args in position
|
||||
pushl 12(%ebp)
|
||||
pushl %eax
|
||||
call *8(%ebp)
|
||||
|
||||
// Return stack to previous state and call the function
|
||||
addl $8,%esp
|
||||
|
||||
// Handle fastcall and thiscall
|
||||
cmpl $3, 16(%ebp) // FFI_THISCALL
|
||||
jz .do_thiscall
|
||||
cmpl $4, 16(%ebp) // FFI_FASTCALL
|
||||
jnz .do_fncall
|
||||
movl (%esp), %ecx
|
||||
movl 4(%esp), %edx
|
||||
addl $8, %esp
|
||||
jmp .do_fncall
|
||||
.do_thiscall:
|
||||
movl (%esp), %ecx
|
||||
addl $4, %esp
|
||||
|
||||
.do_fncall:
|
||||
|
||||
// FIXME: Align the stack to a 128-bit boundary to avoid
|
||||
// potential performance hits.
|
||||
|
||||
call *32(%ebp)
|
||||
|
||||
// stdcall functions pop arguments off the stack themselves
|
||||
|
||||
// Load %ecx with the return type code
|
||||
movl 24(%ebp),%ecx
|
||||
|
||||
// If the return value pointer is NULL, assume no return value.
|
||||
cmpl $0,28(%ebp)
|
||||
jne 0f
|
||||
|
||||
// Even if there is no space for the return value, we are
|
||||
// obliged to handle floating-point values.
|
||||
cmpl $FFI_TYPE_FLOAT,%ecx
|
||||
jne .Lnoretval
|
||||
fstp %st(0)
|
||||
|
||||
jmp .Lepilogue
|
||||
|
||||
0:
|
||||
call 1f
|
||||
// Do not insert anything here between the call and the jump table.
|
||||
.Lstore_table:
|
||||
.long .Lnoretval /* FFI_TYPE_VOID */
|
||||
.long .Lretint /* FFI_TYPE_INT */
|
||||
.long .Lretfloat /* FFI_TYPE_FLOAT */
|
||||
.long .Lretdouble /* FFI_TYPE_DOUBLE */
|
||||
.long .Lretlongdouble /* FFI_TYPE_LONGDOUBLE */
|
||||
.long .Lretuint8 /* FFI_TYPE_UINT8 */
|
||||
.long .Lretsint8 /* FFI_TYPE_SINT8 */
|
||||
.long .Lretuint16 /* FFI_TYPE_UINT16 */
|
||||
.long .Lretsint16 /* FFI_TYPE_SINT16 */
|
||||
.long .Lretint /* FFI_TYPE_UINT32 */
|
||||
.long .Lretint /* FFI_TYPE_SINT32 */
|
||||
.long .Lretint64 /* FFI_TYPE_UINT64 */
|
||||
.long .Lretint64 /* FFI_TYPE_SINT64 */
|
||||
.long .Lretstruct /* FFI_TYPE_STRUCT */
|
||||
.long .Lretint /* FFI_TYPE_POINTER */
|
||||
.long .Lretstruct1b /* FFI_TYPE_SMALL_STRUCT_1B */
|
||||
.long .Lretstruct2b /* FFI_TYPE_SMALL_STRUCT_2B */
|
||||
.long .Lretstruct4b /* FFI_TYPE_SMALL_STRUCT_4B */
|
||||
.long .Lretstruct /* FFI_TYPE_MS_STRUCT */
|
||||
1:
|
||||
add %ecx, %ecx
|
||||
add %ecx, %ecx
|
||||
add (%esp),%ecx
|
||||
add $4, %esp
|
||||
jmp *(%ecx)
|
||||
|
||||
/* Sign/zero extend as appropriate. */
|
||||
.Lretsint8:
|
||||
movsbl %al, %eax
|
||||
jmp .Lretint
|
||||
|
||||
.Lretsint16:
|
||||
movswl %ax, %eax
|
||||
jmp .Lretint
|
||||
|
||||
.Lretuint8:
|
||||
movzbl %al, %eax
|
||||
jmp .Lretint
|
||||
|
||||
.Lretuint16:
|
||||
movzwl %ax, %eax
|
||||
jmp .Lretint
|
||||
|
||||
.Lretint:
|
||||
// Load %ecx with the pointer to storage for the return value
|
||||
movl 28(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretfloat:
|
||||
// Load %ecx with the pointer to storage for the return value
|
||||
movl 28(%ebp),%ecx
|
||||
fstps (%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretdouble:
|
||||
// Load %ecx with the pointer to storage for the return value
|
||||
movl 28(%ebp),%ecx
|
||||
fstpl (%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretlongdouble:
|
||||
// Load %ecx with the pointer to storage for the return value
|
||||
movl 28(%ebp),%ecx
|
||||
fstpt (%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretint64:
|
||||
// Load %ecx with the pointer to storage for the return value
|
||||
movl 28(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
movl %edx,4(%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretstruct1b:
|
||||
// Load %ecx with the pointer to storage for the return value
|
||||
movl 28(%ebp),%ecx
|
||||
movb %al,0(%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretstruct2b:
|
||||
// Load %ecx with the pointer to storage for the return value
|
||||
movl 28(%ebp),%ecx
|
||||
movw %ax,0(%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretstruct4b:
|
||||
// Load %ecx with the pointer to storage for the return value
|
||||
movl 28(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretstruct:
|
||||
// Nothing to do!
|
||||
|
||||
.Lnoretval:
|
||||
.Lepilogue:
|
||||
movl %ebp,%esp
|
||||
popl %ebp
|
||||
ret
|
||||
.ffi_call_win32_end:
|
||||
.balign 16
|
||||
.globl _ffi_closure_THISCALL
|
||||
#ifndef __OS2__
|
||||
.def _ffi_closure_THISCALL; .scl 2; .type 32; .endef
|
||||
#endif
|
||||
_ffi_closure_THISCALL:
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
subl $40, %esp
|
||||
leal -24(%ebp), %edx
|
||||
movl %edx, -12(%ebp) /* resp */
|
||||
leal 12(%ebp), %edx /* account for stub return address on stack */
|
||||
jmp .stub
|
||||
.LFE1:
|
||||
|
||||
// This assumes we are using gas.
|
||||
.balign 16
|
||||
.globl _ffi_closure_SYSV
|
||||
#ifndef __OS2__
|
||||
.def _ffi_closure_SYSV; .scl 2; .type 32; .endef
|
||||
#endif
|
||||
_ffi_closure_SYSV:
|
||||
.LFB3:
|
||||
pushl %ebp
|
||||
.LCFI4:
|
||||
movl %esp, %ebp
|
||||
.LCFI5:
|
||||
subl $40, %esp
|
||||
leal -24(%ebp), %edx
|
||||
movl %edx, -12(%ebp) /* resp */
|
||||
leal 8(%ebp), %edx
|
||||
.stub:
|
||||
movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */
|
||||
leal -12(%ebp), %edx
|
||||
movl %edx, (%esp) /* &resp */
|
||||
call _ffi_closure_SYSV_inner
|
||||
movl -12(%ebp), %ecx
|
||||
|
||||
0:
|
||||
call 1f
|
||||
// Do not insert anything here between the call and the jump table.
|
||||
.Lcls_store_table:
|
||||
.long .Lcls_noretval /* FFI_TYPE_VOID */
|
||||
.long .Lcls_retint /* FFI_TYPE_INT */
|
||||
.long .Lcls_retfloat /* FFI_TYPE_FLOAT */
|
||||
.long .Lcls_retdouble /* FFI_TYPE_DOUBLE */
|
||||
.long .Lcls_retldouble /* FFI_TYPE_LONGDOUBLE */
|
||||
.long .Lcls_retuint8 /* FFI_TYPE_UINT8 */
|
||||
.long .Lcls_retsint8 /* FFI_TYPE_SINT8 */
|
||||
.long .Lcls_retuint16 /* FFI_TYPE_UINT16 */
|
||||
.long .Lcls_retsint16 /* FFI_TYPE_SINT16 */
|
||||
.long .Lcls_retint /* FFI_TYPE_UINT32 */
|
||||
.long .Lcls_retint /* FFI_TYPE_SINT32 */
|
||||
.long .Lcls_retllong /* FFI_TYPE_UINT64 */
|
||||
.long .Lcls_retllong /* FFI_TYPE_SINT64 */
|
||||
.long .Lcls_retstruct /* FFI_TYPE_STRUCT */
|
||||
.long .Lcls_retint /* FFI_TYPE_POINTER */
|
||||
.long .Lcls_retstruct1 /* FFI_TYPE_SMALL_STRUCT_1B */
|
||||
.long .Lcls_retstruct2 /* FFI_TYPE_SMALL_STRUCT_2B */
|
||||
.long .Lcls_retstruct4 /* FFI_TYPE_SMALL_STRUCT_4B */
|
||||
.long .Lcls_retmsstruct /* FFI_TYPE_MS_STRUCT */
|
||||
|
||||
1:
|
||||
add %eax, %eax
|
||||
add %eax, %eax
|
||||
add (%esp),%eax
|
||||
add $4, %esp
|
||||
jmp *(%eax)
|
||||
|
||||
/* Sign/zero extend as appropriate. */
|
||||
.Lcls_retsint8:
|
||||
movsbl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retsint16:
|
||||
movswl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retuint8:
|
||||
movzbl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retuint16:
|
||||
movzwl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retint:
|
||||
movl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retfloat:
|
||||
flds (%ecx)
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retdouble:
|
||||
fldl (%ecx)
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retldouble:
|
||||
fldt (%ecx)
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retllong:
|
||||
movl (%ecx), %eax
|
||||
movl 4(%ecx), %edx
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retstruct1:
|
||||
movsbl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retstruct2:
|
||||
movswl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retstruct4:
|
||||
movl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retstruct:
|
||||
// Caller expects us to pop struct return value pointer hidden arg.
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret $0x4
|
||||
|
||||
.Lcls_retmsstruct:
|
||||
// Caller expects us to return a pointer to the real return value.
|
||||
mov %ecx, %eax
|
||||
// Caller doesn't expects us to pop struct return value pointer hidden arg.
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_noretval:
|
||||
.Lcls_epilogue:
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
.ffi_closure_SYSV_end:
|
||||
.LFE3:
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
|
||||
#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
|
||||
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
|
||||
#define CIF_FLAGS_OFFSET 20
|
||||
.balign 16
|
||||
.globl _ffi_closure_raw_THISCALL
|
||||
#ifndef __OS2__
|
||||
.def _ffi_closure_raw_THISCALL; .scl 2; .type 32; .endef
|
||||
#endif
|
||||
_ffi_closure_raw_THISCALL:
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
pushl %esi
|
||||
subl $36, %esp
|
||||
movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
|
||||
movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
|
||||
movl %edx, 12(%esp) /* user_data */
|
||||
leal 12(%ebp), %edx /* __builtin_dwarf_cfa () */
|
||||
jmp .stubraw
|
||||
// This assumes we are using gas.
|
||||
.balign 16
|
||||
.globl _ffi_closure_raw_SYSV
|
||||
#ifndef __OS2__
|
||||
.def _ffi_closure_raw_SYSV; .scl 2; .type 32; .endef
|
||||
#endif
|
||||
_ffi_closure_raw_SYSV:
|
||||
.LFB4:
|
||||
pushl %ebp
|
||||
.LCFI6:
|
||||
movl %esp, %ebp
|
||||
.LCFI7:
|
||||
pushl %esi
|
||||
.LCFI8:
|
||||
subl $36, %esp
|
||||
movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
|
||||
movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
|
||||
movl %edx, 12(%esp) /* user_data */
|
||||
leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
|
||||
.stubraw:
|
||||
movl %edx, 8(%esp) /* raw_args */
|
||||
leal -24(%ebp), %edx
|
||||
movl %edx, 4(%esp) /* &res */
|
||||
movl %esi, (%esp) /* cif */
|
||||
call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */
|
||||
movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */
|
||||
0:
|
||||
call 1f
|
||||
// Do not insert anything here between the call and the jump table.
|
||||
.Lrcls_store_table:
|
||||
.long .Lrcls_noretval /* FFI_TYPE_VOID */
|
||||
.long .Lrcls_retint /* FFI_TYPE_INT */
|
||||
.long .Lrcls_retfloat /* FFI_TYPE_FLOAT */
|
||||
.long .Lrcls_retdouble /* FFI_TYPE_DOUBLE */
|
||||
.long .Lrcls_retldouble /* FFI_TYPE_LONGDOUBLE */
|
||||
.long .Lrcls_retuint8 /* FFI_TYPE_UINT8 */
|
||||
.long .Lrcls_retsint8 /* FFI_TYPE_SINT8 */
|
||||
.long .Lrcls_retuint16 /* FFI_TYPE_UINT16 */
|
||||
.long .Lrcls_retsint16 /* FFI_TYPE_SINT16 */
|
||||
.long .Lrcls_retint /* FFI_TYPE_UINT32 */
|
||||
.long .Lrcls_retint /* FFI_TYPE_SINT32 */
|
||||
.long .Lrcls_retllong /* FFI_TYPE_UINT64 */
|
||||
.long .Lrcls_retllong /* FFI_TYPE_SINT64 */
|
||||
.long .Lrcls_retstruct /* FFI_TYPE_STRUCT */
|
||||
.long .Lrcls_retint /* FFI_TYPE_POINTER */
|
||||
.long .Lrcls_retstruct1 /* FFI_TYPE_SMALL_STRUCT_1B */
|
||||
.long .Lrcls_retstruct2 /* FFI_TYPE_SMALL_STRUCT_2B */
|
||||
.long .Lrcls_retstruct4 /* FFI_TYPE_SMALL_STRUCT_4B */
|
||||
.long .Lrcls_retstruct /* FFI_TYPE_MS_STRUCT */
|
||||
1:
|
||||
add %eax, %eax
|
||||
add %eax, %eax
|
||||
add (%esp),%eax
|
||||
add $4, %esp
|
||||
jmp *(%eax)
|
||||
|
||||
/* Sign/zero extend as appropriate. */
|
||||
.Lrcls_retsint8:
|
||||
movsbl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retsint16:
|
||||
movswl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retuint8:
|
||||
movzbl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retuint16:
|
||||
movzwl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retint:
|
||||
movl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retfloat:
|
||||
flds -24(%ebp)
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retdouble:
|
||||
fldl -24(%ebp)
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retldouble:
|
||||
fldt -24(%ebp)
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retllong:
|
||||
movl -24(%ebp), %eax
|
||||
movl -20(%ebp), %edx
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retstruct1:
|
||||
movsbl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retstruct2:
|
||||
movswl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retstruct4:
|
||||
movl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retstruct:
|
||||
// Nothing to do!
|
||||
|
||||
.Lrcls_noretval:
|
||||
.Lrcls_epilogue:
|
||||
addl $36, %esp
|
||||
popl %esi
|
||||
popl %ebp
|
||||
ret
|
||||
.ffi_closure_raw_SYSV_end:
|
||||
.LFE4:
|
||||
|
||||
#endif /* !FFI_NO_RAW_API */
|
||||
|
||||
// This assumes we are using gas.
|
||||
.balign 16
|
||||
.globl _ffi_closure_STDCALL
|
||||
#ifndef __OS2__
|
||||
.def _ffi_closure_STDCALL; .scl 2; .type 32; .endef
|
||||
#endif
|
||||
_ffi_closure_STDCALL:
|
||||
.LFB5:
|
||||
pushl %ebp
|
||||
.LCFI9:
|
||||
movl %esp, %ebp
|
||||
.LCFI10:
|
||||
subl $40, %esp
|
||||
leal -24(%ebp), %edx
|
||||
movl %edx, -12(%ebp) /* resp */
|
||||
leal 12(%ebp), %edx /* account for stub return address on stack */
|
||||
movl %edx, 4(%esp) /* args */
|
||||
leal -12(%ebp), %edx
|
||||
movl %edx, (%esp) /* &resp */
|
||||
call _ffi_closure_SYSV_inner
|
||||
movl -12(%ebp), %ecx
|
||||
0:
|
||||
call 1f
|
||||
// Do not insert anything here between the call and the jump table.
|
||||
.Lscls_store_table:
|
||||
.long .Lscls_noretval /* FFI_TYPE_VOID */
|
||||
.long .Lscls_retint /* FFI_TYPE_INT */
|
||||
.long .Lscls_retfloat /* FFI_TYPE_FLOAT */
|
||||
.long .Lscls_retdouble /* FFI_TYPE_DOUBLE */
|
||||
.long .Lscls_retldouble /* FFI_TYPE_LONGDOUBLE */
|
||||
.long .Lscls_retuint8 /* FFI_TYPE_UINT8 */
|
||||
.long .Lscls_retsint8 /* FFI_TYPE_SINT8 */
|
||||
.long .Lscls_retuint16 /* FFI_TYPE_UINT16 */
|
||||
.long .Lscls_retsint16 /* FFI_TYPE_SINT16 */
|
||||
.long .Lscls_retint /* FFI_TYPE_UINT32 */
|
||||
.long .Lscls_retint /* FFI_TYPE_SINT32 */
|
||||
.long .Lscls_retllong /* FFI_TYPE_UINT64 */
|
||||
.long .Lscls_retllong /* FFI_TYPE_SINT64 */
|
||||
.long .Lscls_retstruct /* FFI_TYPE_STRUCT */
|
||||
.long .Lscls_retint /* FFI_TYPE_POINTER */
|
||||
.long .Lscls_retstruct1 /* FFI_TYPE_SMALL_STRUCT_1B */
|
||||
.long .Lscls_retstruct2 /* FFI_TYPE_SMALL_STRUCT_2B */
|
||||
.long .Lscls_retstruct4 /* FFI_TYPE_SMALL_STRUCT_4B */
|
||||
1:
|
||||
add %eax, %eax
|
||||
add %eax, %eax
|
||||
add (%esp),%eax
|
||||
add $4, %esp
|
||||
jmp *(%eax)
|
||||
|
||||
/* Sign/zero extend as appropriate. */
|
||||
.Lscls_retsint8:
|
||||
movsbl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retsint16:
|
||||
movswl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retuint8:
|
||||
movzbl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retuint16:
|
||||
movzwl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retint:
|
||||
movl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retfloat:
|
||||
flds (%ecx)
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retdouble:
|
||||
fldl (%ecx)
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retldouble:
|
||||
fldt (%ecx)
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retllong:
|
||||
movl (%ecx), %eax
|
||||
movl 4(%ecx), %edx
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retstruct1:
|
||||
movsbl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retstruct2:
|
||||
movswl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retstruct4:
|
||||
movl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retstruct:
|
||||
// Nothing to do!
|
||||
|
||||
.Lscls_noretval:
|
||||
.Lscls_epilogue:
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
.ffi_closure_STDCALL_end:
|
||||
.LFE5:
|
||||
|
||||
#ifndef __OS2__
|
||||
.section .eh_frame,"w"
|
||||
#endif
|
||||
.Lframe1:
|
||||
.LSCIE1:
|
||||
.long .LECIE1-.LASCIE1 /* Length of Common Information Entry */
|
||||
.LASCIE1:
|
||||
.long 0x0 /* CIE Identifier Tag */
|
||||
.byte 0x1 /* CIE Version */
|
||||
#ifdef __PIC__
|
||||
.ascii "zR\0" /* CIE Augmentation */
|
||||
#else
|
||||
.ascii "\0" /* CIE Augmentation */
|
||||
#endif
|
||||
.byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */
|
||||
.byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */
|
||||
.byte 0x8 /* CIE RA Column */
|
||||
#ifdef __PIC__
|
||||
.byte 0x1 /* .uleb128 0x1; Augmentation size */
|
||||
.byte 0x1b /* FDE Encoding (pcrel sdata4) */
|
||||
#endif
|
||||
.byte 0xc /* DW_CFA_def_cfa CFA = r4 + 4 = 4(%esp) */
|
||||
.byte 0x4 /* .uleb128 0x4 */
|
||||
.byte 0x4 /* .uleb128 0x4 */
|
||||
.byte 0x88 /* DW_CFA_offset, column 0x8 %eip at CFA + 1 * -4 */
|
||||
.byte 0x1 /* .uleb128 0x1 */
|
||||
.align 4
|
||||
.LECIE1:
|
||||
|
||||
.LSFDE1:
|
||||
.long .LEFDE1-.LASFDE1 /* FDE Length */
|
||||
.LASFDE1:
|
||||
.long .LASFDE1-.Lframe1 /* FDE CIE offset */
|
||||
#if defined __PIC__ && defined HAVE_AS_X86_PCREL
|
||||
.long .LFB1-. /* FDE initial location */
|
||||
#else
|
||||
.long .LFB1
|
||||
#endif
|
||||
.long .LFE1-.LFB1 /* FDE address range */
|
||||
#ifdef __PIC__
|
||||
.byte 0x0 /* .uleb128 0x0; Augmentation size */
|
||||
#endif
|
||||
/* DW_CFA_xxx CFI instructions go here. */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.long .LCFI0-.LFB1
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
|
||||
.byte 0x8 /* .uleb128 0x8 */
|
||||
.byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
|
||||
.byte 0x2 /* .uleb128 0x2 */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.long .LCFI1-.LCFI0
|
||||
.byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
|
||||
.byte 0x5 /* .uleb128 0x5 */
|
||||
|
||||
/* End of DW_CFA_xxx CFI instructions. */
|
||||
.align 4
|
||||
.LEFDE1:
|
||||
|
||||
|
||||
.LSFDE3:
|
||||
.long .LEFDE3-.LASFDE3 /* FDE Length */
|
||||
.LASFDE3:
|
||||
.long .LASFDE3-.Lframe1 /* FDE CIE offset */
|
||||
#if defined __PIC__ && defined HAVE_AS_X86_PCREL
|
||||
.long .LFB3-. /* FDE initial location */
|
||||
#else
|
||||
.long .LFB3
|
||||
#endif
|
||||
.long .LFE3-.LFB3 /* FDE address range */
|
||||
#ifdef __PIC__
|
||||
.byte 0x0 /* .uleb128 0x0; Augmentation size */
|
||||
#endif
|
||||
/* DW_CFA_xxx CFI instructions go here. */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.long .LCFI4-.LFB3
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
|
||||
.byte 0x8 /* .uleb128 0x8 */
|
||||
.byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
|
||||
.byte 0x2 /* .uleb128 0x2 */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.long .LCFI5-.LCFI4
|
||||
.byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
|
||||
.byte 0x5 /* .uleb128 0x5 */
|
||||
|
||||
/* End of DW_CFA_xxx CFI instructions. */
|
||||
.align 4
|
||||
.LEFDE3:
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
.LSFDE4:
|
||||
.long .LEFDE4-.LASFDE4 /* FDE Length */
|
||||
.LASFDE4:
|
||||
.long .LASFDE4-.Lframe1 /* FDE CIE offset */
|
||||
#if defined __PIC__ && defined HAVE_AS_X86_PCREL
|
||||
.long .LFB4-. /* FDE initial location */
|
||||
#else
|
||||
.long .LFB4
|
||||
#endif
|
||||
.long .LFE4-.LFB4 /* FDE address range */
|
||||
#ifdef __PIC__
|
||||
.byte 0x0 /* .uleb128 0x0; Augmentation size */
|
||||
#endif
|
||||
/* DW_CFA_xxx CFI instructions go here. */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.long .LCFI6-.LFB4
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
|
||||
.byte 0x8 /* .uleb128 0x8 */
|
||||
.byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
|
||||
.byte 0x2 /* .uleb128 0x2 */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.long .LCFI7-.LCFI6
|
||||
.byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
|
||||
.byte 0x5 /* .uleb128 0x5 */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.long .LCFI8-.LCFI7
|
||||
.byte 0x86 /* DW_CFA_offset, column 0x6 %esi at CFA + 3 * -4 */
|
||||
.byte 0x3 /* .uleb128 0x3 */
|
||||
|
||||
/* End of DW_CFA_xxx CFI instructions. */
|
||||
.align 4
|
||||
.LEFDE4:
|
||||
|
||||
#endif /* !FFI_NO_RAW_API */
|
||||
|
||||
.LSFDE5:
|
||||
.long .LEFDE5-.LASFDE5 /* FDE Length */
|
||||
.LASFDE5:
|
||||
.long .LASFDE5-.Lframe1 /* FDE CIE offset */
|
||||
#if defined __PIC__ && defined HAVE_AS_X86_PCREL
|
||||
.long .LFB5-. /* FDE initial location */
|
||||
#else
|
||||
.long .LFB5
|
||||
#endif
|
||||
.long .LFE5-.LFB5 /* FDE address range */
|
||||
#ifdef __PIC__
|
||||
.byte 0x0 /* .uleb128 0x0; Augmentation size */
|
||||
#endif
|
||||
/* DW_CFA_xxx CFI instructions go here. */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.long .LCFI9-.LFB5
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */
|
||||
.byte 0x8 /* .uleb128 0x8 */
|
||||
.byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */
|
||||
.byte 0x2 /* .uleb128 0x2 */
|
||||
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.long .LCFI10-.LCFI9
|
||||
.byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */
|
||||
.byte 0x5 /* .uleb128 0x5 */
|
||||
|
||||
/* End of DW_CFA_xxx CFI instructions. */
|
||||
.align 4
|
||||
.LEFDE5:
|
||||
736
lib/wrappers/libffi/gcc/win32_asm.s
Normal file
736
lib/wrappers/libffi/gcc/win32_asm.s
Normal file
|
|
@ -0,0 +1,736 @@
|
|||
# 1 "gcc\\win32_asm.asm"
|
||||
# 1 "<command-line>"
|
||||
# 1 "gcc\\win32_asm.asm"
|
||||
# 33 "gcc\\win32_asm.asm"
|
||||
# 1 "common/fficonfig.h" 1
|
||||
# 34 "gcc\\win32_asm.asm" 2
|
||||
# 1 "common/ffi.h" 1
|
||||
# 63 "common/ffi.h"
|
||||
# 1 "common/ffitarget.h" 1
|
||||
# 64 "common/ffi.h" 2
|
||||
# 35 "gcc\\win32_asm.asm" 2
|
||||
|
||||
|
||||
.text
|
||||
|
||||
|
||||
.balign 16
|
||||
.globl _ffi_call_win32
|
||||
|
||||
.def _ffi_call_win32; .scl 2; .type 32; .endef
|
||||
|
||||
_ffi_call_win32:
|
||||
.LFB1:
|
||||
pushl %ebp
|
||||
.LCFI0:
|
||||
movl %esp,%ebp
|
||||
.LCFI1:
|
||||
|
||||
movl 20(%ebp),%ecx
|
||||
subl %ecx,%esp
|
||||
|
||||
movl %esp,%eax
|
||||
|
||||
|
||||
pushl 12(%ebp)
|
||||
pushl %eax
|
||||
call *8(%ebp)
|
||||
|
||||
|
||||
addl $8,%esp
|
||||
|
||||
|
||||
cmpl $3, 16(%ebp)
|
||||
jz .do_thiscall
|
||||
cmpl $4, 16(%ebp)
|
||||
jnz .do_fncall
|
||||
movl (%esp), %ecx
|
||||
movl 4(%esp), %edx
|
||||
addl $8, %esp
|
||||
jmp .do_fncall
|
||||
.do_thiscall:
|
||||
movl (%esp), %ecx
|
||||
addl $4, %esp
|
||||
|
||||
.do_fncall:
|
||||
|
||||
|
||||
|
||||
|
||||
call *32(%ebp)
|
||||
|
||||
|
||||
|
||||
|
||||
movl 24(%ebp),%ecx
|
||||
|
||||
|
||||
cmpl $0,28(%ebp)
|
||||
jne 0f
|
||||
|
||||
|
||||
|
||||
cmpl $2,%ecx
|
||||
jne .Lnoretval
|
||||
fstp %st(0)
|
||||
|
||||
jmp .Lepilogue
|
||||
|
||||
0:
|
||||
call 1f
|
||||
|
||||
.Lstore_table:
|
||||
.long .Lnoretval
|
||||
.long .Lretint
|
||||
.long .Lretfloat
|
||||
.long .Lretdouble
|
||||
.long .Lretlongdouble
|
||||
.long .Lretuint8
|
||||
.long .Lretsint8
|
||||
.long .Lretuint16
|
||||
.long .Lretsint16
|
||||
.long .Lretint
|
||||
.long .Lretint
|
||||
.long .Lretint64
|
||||
.long .Lretint64
|
||||
.long .Lretstruct
|
||||
.long .Lretint
|
||||
.long .Lretstruct1b
|
||||
.long .Lretstruct2b
|
||||
.long .Lretstruct4b
|
||||
.long .Lretstruct
|
||||
1:
|
||||
add %ecx, %ecx
|
||||
add %ecx, %ecx
|
||||
add (%esp),%ecx
|
||||
add $4, %esp
|
||||
jmp *(%ecx)
|
||||
|
||||
|
||||
.Lretsint8:
|
||||
movsbl %al, %eax
|
||||
jmp .Lretint
|
||||
|
||||
.Lretsint16:
|
||||
movswl %ax, %eax
|
||||
jmp .Lretint
|
||||
|
||||
.Lretuint8:
|
||||
movzbl %al, %eax
|
||||
jmp .Lretint
|
||||
|
||||
.Lretuint16:
|
||||
movzwl %ax, %eax
|
||||
jmp .Lretint
|
||||
|
||||
.Lretint:
|
||||
|
||||
movl 28(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretfloat:
|
||||
|
||||
movl 28(%ebp),%ecx
|
||||
fstps (%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretdouble:
|
||||
|
||||
movl 28(%ebp),%ecx
|
||||
fstpl (%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretlongdouble:
|
||||
|
||||
movl 28(%ebp),%ecx
|
||||
fstpt (%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretint64:
|
||||
|
||||
movl 28(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
movl %edx,4(%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretstruct1b:
|
||||
|
||||
movl 28(%ebp),%ecx
|
||||
movb %al,0(%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretstruct2b:
|
||||
|
||||
movl 28(%ebp),%ecx
|
||||
movw %ax,0(%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretstruct4b:
|
||||
|
||||
movl 28(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
jmp .Lepilogue
|
||||
|
||||
.Lretstruct:
|
||||
|
||||
|
||||
.Lnoretval:
|
||||
.Lepilogue:
|
||||
movl %ebp,%esp
|
||||
popl %ebp
|
||||
ret
|
||||
.ffi_call_win32_end:
|
||||
.balign 16
|
||||
.globl _ffi_closure_THISCALL
|
||||
|
||||
.def _ffi_closure_THISCALL; .scl 2; .type 32; .endef
|
||||
|
||||
_ffi_closure_THISCALL:
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
subl $40, %esp
|
||||
leal -24(%ebp), %edx
|
||||
movl %edx, -12(%ebp)
|
||||
leal 12(%ebp), %edx
|
||||
jmp .stub
|
||||
.LFE1:
|
||||
|
||||
|
||||
.balign 16
|
||||
.globl _ffi_closure_SYSV
|
||||
|
||||
.def _ffi_closure_SYSV; .scl 2; .type 32; .endef
|
||||
|
||||
_ffi_closure_SYSV:
|
||||
.LFB3:
|
||||
pushl %ebp
|
||||
.LCFI4:
|
||||
movl %esp, %ebp
|
||||
.LCFI5:
|
||||
subl $40, %esp
|
||||
leal -24(%ebp), %edx
|
||||
movl %edx, -12(%ebp)
|
||||
leal 8(%ebp), %edx
|
||||
.stub:
|
||||
movl %edx, 4(%esp)
|
||||
leal -12(%ebp), %edx
|
||||
movl %edx, (%esp)
|
||||
call _ffi_closure_SYSV_inner
|
||||
movl -12(%ebp), %ecx
|
||||
|
||||
0:
|
||||
call 1f
|
||||
|
||||
.Lcls_store_table:
|
||||
.long .Lcls_noretval
|
||||
.long .Lcls_retint
|
||||
.long .Lcls_retfloat
|
||||
.long .Lcls_retdouble
|
||||
.long .Lcls_retldouble
|
||||
.long .Lcls_retuint8
|
||||
.long .Lcls_retsint8
|
||||
.long .Lcls_retuint16
|
||||
.long .Lcls_retsint16
|
||||
.long .Lcls_retint
|
||||
.long .Lcls_retint
|
||||
.long .Lcls_retllong
|
||||
.long .Lcls_retllong
|
||||
.long .Lcls_retstruct
|
||||
.long .Lcls_retint
|
||||
.long .Lcls_retstruct1
|
||||
.long .Lcls_retstruct2
|
||||
.long .Lcls_retstruct4
|
||||
.long .Lcls_retmsstruct
|
||||
|
||||
1:
|
||||
add %eax, %eax
|
||||
add %eax, %eax
|
||||
add (%esp),%eax
|
||||
add $4, %esp
|
||||
jmp *(%eax)
|
||||
|
||||
|
||||
.Lcls_retsint8:
|
||||
movsbl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retsint16:
|
||||
movswl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retuint8:
|
||||
movzbl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retuint16:
|
||||
movzwl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retint:
|
||||
movl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retfloat:
|
||||
flds (%ecx)
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retdouble:
|
||||
fldl (%ecx)
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retldouble:
|
||||
fldt (%ecx)
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retllong:
|
||||
movl (%ecx), %eax
|
||||
movl 4(%ecx), %edx
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retstruct1:
|
||||
movsbl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retstruct2:
|
||||
movswl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retstruct4:
|
||||
movl (%ecx), %eax
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_retstruct:
|
||||
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret $0x4
|
||||
|
||||
.Lcls_retmsstruct:
|
||||
|
||||
mov %ecx, %eax
|
||||
|
||||
jmp .Lcls_epilogue
|
||||
|
||||
.Lcls_noretval:
|
||||
.Lcls_epilogue:
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
.ffi_closure_SYSV_end:
|
||||
.LFE3:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.balign 16
|
||||
.globl _ffi_closure_raw_THISCALL
|
||||
|
||||
.def _ffi_closure_raw_THISCALL; .scl 2; .type 32; .endef
|
||||
|
||||
_ffi_closure_raw_THISCALL:
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
pushl %esi
|
||||
subl $36, %esp
|
||||
movl ((52 + 3) & ~3)(%eax), %esi
|
||||
movl ((((52 + 3) & ~3) + 4) + 4)(%eax), %edx
|
||||
movl %edx, 12(%esp)
|
||||
leal 12(%ebp), %edx
|
||||
jmp .stubraw
|
||||
|
||||
.balign 16
|
||||
.globl _ffi_closure_raw_SYSV
|
||||
|
||||
.def _ffi_closure_raw_SYSV; .scl 2; .type 32; .endef
|
||||
|
||||
_ffi_closure_raw_SYSV:
|
||||
.LFB4:
|
||||
pushl %ebp
|
||||
.LCFI6:
|
||||
movl %esp, %ebp
|
||||
.LCFI7:
|
||||
pushl %esi
|
||||
.LCFI8:
|
||||
subl $36, %esp
|
||||
movl ((52 + 3) & ~3)(%eax), %esi
|
||||
movl ((((52 + 3) & ~3) + 4) + 4)(%eax), %edx
|
||||
movl %edx, 12(%esp)
|
||||
leal 8(%ebp), %edx
|
||||
.stubraw:
|
||||
movl %edx, 8(%esp)
|
||||
leal -24(%ebp), %edx
|
||||
movl %edx, 4(%esp)
|
||||
movl %esi, (%esp)
|
||||
call *(((52 + 3) & ~3) + 4)(%eax)
|
||||
movl 20(%esi), %eax
|
||||
0:
|
||||
call 1f
|
||||
|
||||
.Lrcls_store_table:
|
||||
.long .Lrcls_noretval
|
||||
.long .Lrcls_retint
|
||||
.long .Lrcls_retfloat
|
||||
.long .Lrcls_retdouble
|
||||
.long .Lrcls_retldouble
|
||||
.long .Lrcls_retuint8
|
||||
.long .Lrcls_retsint8
|
||||
.long .Lrcls_retuint16
|
||||
.long .Lrcls_retsint16
|
||||
.long .Lrcls_retint
|
||||
.long .Lrcls_retint
|
||||
.long .Lrcls_retllong
|
||||
.long .Lrcls_retllong
|
||||
.long .Lrcls_retstruct
|
||||
.long .Lrcls_retint
|
||||
.long .Lrcls_retstruct1
|
||||
.long .Lrcls_retstruct2
|
||||
.long .Lrcls_retstruct4
|
||||
.long .Lrcls_retstruct
|
||||
1:
|
||||
add %eax, %eax
|
||||
add %eax, %eax
|
||||
add (%esp),%eax
|
||||
add $4, %esp
|
||||
jmp *(%eax)
|
||||
|
||||
|
||||
.Lrcls_retsint8:
|
||||
movsbl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retsint16:
|
||||
movswl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retuint8:
|
||||
movzbl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retuint16:
|
||||
movzwl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retint:
|
||||
movl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retfloat:
|
||||
flds -24(%ebp)
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retdouble:
|
||||
fldl -24(%ebp)
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retldouble:
|
||||
fldt -24(%ebp)
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retllong:
|
||||
movl -24(%ebp), %eax
|
||||
movl -20(%ebp), %edx
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retstruct1:
|
||||
movsbl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retstruct2:
|
||||
movswl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retstruct4:
|
||||
movl -24(%ebp), %eax
|
||||
jmp .Lrcls_epilogue
|
||||
|
||||
.Lrcls_retstruct:
|
||||
|
||||
|
||||
.Lrcls_noretval:
|
||||
.Lrcls_epilogue:
|
||||
addl $36, %esp
|
||||
popl %esi
|
||||
popl %ebp
|
||||
ret
|
||||
.ffi_closure_raw_SYSV_end:
|
||||
.LFE4:
|
||||
|
||||
|
||||
|
||||
|
||||
.balign 16
|
||||
.globl _ffi_closure_STDCALL
|
||||
|
||||
.def _ffi_closure_STDCALL; .scl 2; .type 32; .endef
|
||||
|
||||
_ffi_closure_STDCALL:
|
||||
.LFB5:
|
||||
pushl %ebp
|
||||
.LCFI9:
|
||||
movl %esp, %ebp
|
||||
.LCFI10:
|
||||
subl $40, %esp
|
||||
leal -24(%ebp), %edx
|
||||
movl %edx, -12(%ebp)
|
||||
leal 12(%ebp), %edx
|
||||
movl %edx, 4(%esp)
|
||||
leal -12(%ebp), %edx
|
||||
movl %edx, (%esp)
|
||||
call _ffi_closure_SYSV_inner
|
||||
movl -12(%ebp), %ecx
|
||||
0:
|
||||
call 1f
|
||||
|
||||
.Lscls_store_table:
|
||||
.long .Lscls_noretval
|
||||
.long .Lscls_retint
|
||||
.long .Lscls_retfloat
|
||||
.long .Lscls_retdouble
|
||||
.long .Lscls_retldouble
|
||||
.long .Lscls_retuint8
|
||||
.long .Lscls_retsint8
|
||||
.long .Lscls_retuint16
|
||||
.long .Lscls_retsint16
|
||||
.long .Lscls_retint
|
||||
.long .Lscls_retint
|
||||
.long .Lscls_retllong
|
||||
.long .Lscls_retllong
|
||||
.long .Lscls_retstruct
|
||||
.long .Lscls_retint
|
||||
.long .Lscls_retstruct1
|
||||
.long .Lscls_retstruct2
|
||||
.long .Lscls_retstruct4
|
||||
1:
|
||||
add %eax, %eax
|
||||
add %eax, %eax
|
||||
add (%esp),%eax
|
||||
add $4, %esp
|
||||
jmp *(%eax)
|
||||
|
||||
|
||||
.Lscls_retsint8:
|
||||
movsbl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retsint16:
|
||||
movswl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retuint8:
|
||||
movzbl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retuint16:
|
||||
movzwl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retint:
|
||||
movl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retfloat:
|
||||
flds (%ecx)
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retdouble:
|
||||
fldl (%ecx)
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retldouble:
|
||||
fldt (%ecx)
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retllong:
|
||||
movl (%ecx), %eax
|
||||
movl 4(%ecx), %edx
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retstruct1:
|
||||
movsbl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retstruct2:
|
||||
movswl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retstruct4:
|
||||
movl (%ecx), %eax
|
||||
jmp .Lscls_epilogue
|
||||
|
||||
.Lscls_retstruct:
|
||||
|
||||
|
||||
.Lscls_noretval:
|
||||
.Lscls_epilogue:
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
.ffi_closure_STDCALL_end:
|
||||
.LFE5:
|
||||
|
||||
|
||||
.section .eh_frame,"w"
|
||||
|
||||
.Lframe1:
|
||||
.LSCIE1:
|
||||
.long .LECIE1-.LASCIE1
|
||||
.LASCIE1:
|
||||
.long 0x0
|
||||
.byte 0x1
|
||||
|
||||
|
||||
|
||||
.ascii "\0"
|
||||
|
||||
.byte 0x1
|
||||
.byte 0x7c
|
||||
.byte 0x8
|
||||
|
||||
|
||||
|
||||
|
||||
.byte 0xc
|
||||
.byte 0x4
|
||||
.byte 0x4
|
||||
.byte 0x88
|
||||
.byte 0x1
|
||||
.align 4
|
||||
.LECIE1:
|
||||
|
||||
.LSFDE1:
|
||||
.long .LEFDE1-.LASFDE1
|
||||
.LASFDE1:
|
||||
.long .LASFDE1-.Lframe1
|
||||
|
||||
|
||||
|
||||
.long .LFB1
|
||||
|
||||
.long .LFE1-.LFB1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.byte 0x4
|
||||
.long .LCFI0-.LFB1
|
||||
.byte 0xe
|
||||
.byte 0x8
|
||||
.byte 0x85
|
||||
.byte 0x2
|
||||
|
||||
.byte 0x4
|
||||
.long .LCFI1-.LCFI0
|
||||
.byte 0xd
|
||||
.byte 0x5
|
||||
|
||||
|
||||
.align 4
|
||||
.LEFDE1:
|
||||
|
||||
|
||||
.LSFDE3:
|
||||
.long .LEFDE3-.LASFDE3
|
||||
.LASFDE3:
|
||||
.long .LASFDE3-.Lframe1
|
||||
|
||||
|
||||
|
||||
.long .LFB3
|
||||
|
||||
.long .LFE3-.LFB3
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.byte 0x4
|
||||
.long .LCFI4-.LFB3
|
||||
.byte 0xe
|
||||
.byte 0x8
|
||||
.byte 0x85
|
||||
.byte 0x2
|
||||
|
||||
.byte 0x4
|
||||
.long .LCFI5-.LCFI4
|
||||
.byte 0xd
|
||||
.byte 0x5
|
||||
|
||||
|
||||
.align 4
|
||||
.LEFDE3:
|
||||
|
||||
|
||||
|
||||
.LSFDE4:
|
||||
.long .LEFDE4-.LASFDE4
|
||||
.LASFDE4:
|
||||
.long .LASFDE4-.Lframe1
|
||||
|
||||
|
||||
|
||||
.long .LFB4
|
||||
|
||||
.long .LFE4-.LFB4
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.byte 0x4
|
||||
.long .LCFI6-.LFB4
|
||||
.byte 0xe
|
||||
.byte 0x8
|
||||
.byte 0x85
|
||||
.byte 0x2
|
||||
|
||||
.byte 0x4
|
||||
.long .LCFI7-.LCFI6
|
||||
.byte 0xd
|
||||
.byte 0x5
|
||||
|
||||
.byte 0x4
|
||||
.long .LCFI8-.LCFI7
|
||||
.byte 0x86
|
||||
.byte 0x3
|
||||
|
||||
|
||||
.align 4
|
||||
.LEFDE4:
|
||||
|
||||
|
||||
|
||||
.LSFDE5:
|
||||
.long .LEFDE5-.LASFDE5
|
||||
.LASFDE5:
|
||||
.long .LASFDE5-.Lframe1
|
||||
|
||||
|
||||
|
||||
.long .LFB5
|
||||
|
||||
.long .LFE5-.LFB5
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.byte 0x4
|
||||
.long .LCFI9-.LFB5
|
||||
.byte 0xe
|
||||
.byte 0x8
|
||||
.byte 0x85
|
||||
.byte 0x2
|
||||
|
||||
.byte 0x4
|
||||
.long .LCFI10-.LCFI9
|
||||
.byte 0xd
|
||||
.byte 0x5
|
||||
|
||||
|
||||
.align 4
|
||||
.LEFDE5:
|
||||
467
lib/wrappers/libffi/gcc/win64_asm.asm
Normal file
467
lib/wrappers/libffi/gcc/win64_asm.asm
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
/* Constants for ffi_call_win64 */
|
||||
#define STACK 0
|
||||
#define PREP_ARGS_FN 32
|
||||
#define ECIF 40
|
||||
#define CIF_BYTES 48
|
||||
#define CIF_FLAGS 56
|
||||
#define RVALUE 64
|
||||
#define FN 72
|
||||
|
||||
/* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *),
|
||||
extended_cif *ecif, unsigned bytes, unsigned flags,
|
||||
unsigned *rvalue, void (*fn)());
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
PUBLIC ffi_call_win64
|
||||
|
||||
EXTRN __chkstk:NEAR
|
||||
EXTRN ffi_closure_win64_inner:NEAR
|
||||
|
||||
_TEXT SEGMENT
|
||||
|
||||
;;; ffi_closure_win64 will be called with these registers set:
|
||||
;;; rax points to 'closure'
|
||||
;;; r11 contains a bit mask that specifies which of the
|
||||
;;; first four parameters are float or double
|
||||
;;;
|
||||
;;; It must move the parameters passed in registers to their stack location,
|
||||
;;; call ffi_closure_win64_inner for the actual work, then return the result.
|
||||
;;;
|
||||
ffi_closure_win64 PROC FRAME
|
||||
;; copy register arguments onto stack
|
||||
test r11, 1
|
||||
jne first_is_float
|
||||
mov QWORD PTR [rsp+8], rcx
|
||||
jmp second
|
||||
first_is_float:
|
||||
movlpd QWORD PTR [rsp+8], xmm0
|
||||
|
||||
second:
|
||||
test r11, 2
|
||||
jne second_is_float
|
||||
mov QWORD PTR [rsp+16], rdx
|
||||
jmp third
|
||||
second_is_float:
|
||||
movlpd QWORD PTR [rsp+16], xmm1
|
||||
|
||||
third:
|
||||
test r11, 4
|
||||
jne third_is_float
|
||||
mov QWORD PTR [rsp+24], r8
|
||||
jmp fourth
|
||||
third_is_float:
|
||||
movlpd QWORD PTR [rsp+24], xmm2
|
||||
|
||||
fourth:
|
||||
test r11, 8
|
||||
jne fourth_is_float
|
||||
mov QWORD PTR [rsp+32], r9
|
||||
jmp done
|
||||
fourth_is_float:
|
||||
movlpd QWORD PTR [rsp+32], xmm3
|
||||
|
||||
done:
|
||||
.ALLOCSTACK 40
|
||||
sub rsp, 40
|
||||
.ENDPROLOG
|
||||
mov rcx, rax ; context is first parameter
|
||||
mov rdx, rsp ; stack is second parameter
|
||||
add rdx, 48 ; point to start of arguments
|
||||
mov rax, ffi_closure_win64_inner
|
||||
call rax ; call the real closure function
|
||||
add rsp, 40
|
||||
movd xmm0, rax ; If the closure returned a float,
|
||||
; ffi_closure_win64_inner wrote it to rax
|
||||
ret 0
|
||||
ffi_closure_win64 ENDP
|
||||
|
||||
ffi_call_win64 PROC FRAME
|
||||
;; copy registers onto stack
|
||||
mov QWORD PTR [rsp+32], r9
|
||||
mov QWORD PTR [rsp+24], r8
|
||||
mov QWORD PTR [rsp+16], rdx
|
||||
mov QWORD PTR [rsp+8], rcx
|
||||
.PUSHREG rbp
|
||||
push rbp
|
||||
.ALLOCSTACK 48
|
||||
sub rsp, 48 ; 00000030H
|
||||
.SETFRAME rbp, 32
|
||||
lea rbp, QWORD PTR [rsp+32]
|
||||
.ENDPROLOG
|
||||
|
||||
mov eax, DWORD PTR CIF_BYTES[rbp]
|
||||
add rax, 15
|
||||
and rax, -16
|
||||
call __chkstk
|
||||
sub rsp, rax
|
||||
lea rax, QWORD PTR [rsp+32]
|
||||
mov QWORD PTR STACK[rbp], rax
|
||||
|
||||
mov rdx, QWORD PTR ECIF[rbp]
|
||||
mov rcx, QWORD PTR STACK[rbp]
|
||||
call QWORD PTR PREP_ARGS_FN[rbp]
|
||||
|
||||
mov rsp, QWORD PTR STACK[rbp]
|
||||
|
||||
movlpd xmm3, QWORD PTR [rsp+24]
|
||||
movd r9, xmm3
|
||||
|
||||
movlpd xmm2, QWORD PTR [rsp+16]
|
||||
movd r8, xmm2
|
||||
|
||||
movlpd xmm1, QWORD PTR [rsp+8]
|
||||
movd rdx, xmm1
|
||||
|
||||
movlpd xmm0, QWORD PTR [rsp]
|
||||
movd rcx, xmm0
|
||||
|
||||
call QWORD PTR FN[rbp]
|
||||
ret_struct4b$:
|
||||
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_4B
|
||||
jne ret_struct2b$
|
||||
|
||||
mov rcx, QWORD PTR RVALUE[rbp]
|
||||
mov DWORD PTR [rcx], eax
|
||||
jmp ret_void$
|
||||
|
||||
ret_struct2b$:
|
||||
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B
|
||||
jne ret_struct1b$
|
||||
|
||||
mov rcx, QWORD PTR RVALUE[rbp]
|
||||
mov WORD PTR [rcx], ax
|
||||
jmp ret_void$
|
||||
|
||||
ret_struct1b$:
|
||||
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B
|
||||
jne ret_uint8$
|
||||
|
||||
mov rcx, QWORD PTR RVALUE[rbp]
|
||||
mov BYTE PTR [rcx], al
|
||||
jmp ret_void$
|
||||
|
||||
ret_uint8$:
|
||||
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT8
|
||||
jne ret_sint8$
|
||||
|
||||
mov rcx, QWORD PTR RVALUE[rbp]
|
||||
movzx rax, al
|
||||
mov QWORD PTR [rcx], rax
|
||||
jmp ret_void$
|
||||
|
||||
ret_sint8$:
|
||||
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT8
|
||||
jne ret_uint16$
|
||||
|
||||
mov rcx, QWORD PTR RVALUE[rbp]
|
||||
movsx rax, al
|
||||
mov QWORD PTR [rcx], rax
|
||||
jmp ret_void$
|
||||
|
||||
ret_uint16$:
|
||||
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT16
|
||||
jne ret_sint16$
|
||||
|
||||
mov rcx, QWORD PTR RVALUE[rbp]
|
||||
movzx rax, ax
|
||||
mov QWORD PTR [rcx], rax
|
||||
jmp SHORT ret_void$
|
||||
|
||||
ret_sint16$:
|
||||
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT16
|
||||
jne ret_uint32$
|
||||
|
||||
mov rcx, QWORD PTR RVALUE[rbp]
|
||||
movsx rax, ax
|
||||
mov QWORD PTR [rcx], rax
|
||||
jmp SHORT ret_void$
|
||||
|
||||
ret_uint32$:
|
||||
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT32
|
||||
jne ret_sint32$
|
||||
|
||||
mov rcx, QWORD PTR RVALUE[rbp]
|
||||
mov eax, eax
|
||||
mov QWORD PTR [rcx], rax
|
||||
jmp SHORT ret_void$
|
||||
|
||||
ret_sint32$:
|
||||
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT32
|
||||
jne ret_float$
|
||||
|
||||
mov rcx, QWORD PTR RVALUE[rbp]
|
||||
cdqe
|
||||
mov QWORD PTR [rcx], rax
|
||||
jmp SHORT ret_void$
|
||||
|
||||
ret_float$:
|
||||
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_FLOAT
|
||||
jne SHORT ret_double$
|
||||
|
||||
mov rax, QWORD PTR RVALUE[rbp]
|
||||
movss DWORD PTR [rax], xmm0
|
||||
jmp SHORT ret_void$
|
||||
|
||||
ret_double$:
|
||||
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE
|
||||
jne SHORT ret_sint64$
|
||||
|
||||
mov rax, QWORD PTR RVALUE[rbp]
|
||||
movlpd QWORD PTR [rax], xmm0
|
||||
jmp SHORT ret_void$
|
||||
|
||||
ret_sint64$:
|
||||
cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64
|
||||
jne ret_void$
|
||||
|
||||
mov rcx, QWORD PTR RVALUE[rbp]
|
||||
mov QWORD PTR [rcx], rax
|
||||
jmp SHORT ret_void$
|
||||
|
||||
ret_void$:
|
||||
xor rax, rax
|
||||
|
||||
lea rsp, QWORD PTR [rbp+16]
|
||||
pop rbp
|
||||
ret 0
|
||||
ffi_call_win64 ENDP
|
||||
_TEXT ENDS
|
||||
END
|
||||
|
||||
#else
|
||||
|
||||
#ifdef SYMBOL_UNDERSCORE
|
||||
#define SYMBOL_NAME(name) _##name
|
||||
#else
|
||||
#define SYMBOL_NAME(name) name
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
.extern SYMBOL_NAME(ffi_closure_win64_inner)
|
||||
|
||||
// ffi_closure_win64 will be called with these registers set:
|
||||
// rax points to 'closure'
|
||||
// r11 contains a bit mask that specifies which of the
|
||||
// first four parameters are float or double
|
||||
// // It must move the parameters passed in registers to their stack location,
|
||||
// call ffi_closure_win64_inner for the actual work, then return the result.
|
||||
//
|
||||
.balign 16
|
||||
.globl SYMBOL_NAME(ffi_closure_win64)
|
||||
SYMBOL_NAME(ffi_closure_win64):
|
||||
// copy register arguments onto stack
|
||||
test $1,%r11
|
||||
jne .Lfirst_is_float
|
||||
mov %rcx, 8(%rsp)
|
||||
jmp .Lsecond
|
||||
.Lfirst_is_float:
|
||||
movlpd %xmm0, 8(%rsp)
|
||||
|
||||
.Lsecond:
|
||||
test $2, %r11
|
||||
jne .Lsecond_is_float
|
||||
mov %rdx, 16(%rsp)
|
||||
jmp .Lthird
|
||||
.Lsecond_is_float:
|
||||
movlpd %xmm1, 16(%rsp)
|
||||
|
||||
.Lthird:
|
||||
test $4, %r11
|
||||
jne .Lthird_is_float
|
||||
mov %r8,24(%rsp)
|
||||
jmp .Lfourth
|
||||
.Lthird_is_float:
|
||||
movlpd %xmm2, 24(%rsp)
|
||||
|
||||
.Lfourth:
|
||||
test $8, %r11
|
||||
jne .Lfourth_is_float
|
||||
mov %r9, 32(%rsp)
|
||||
jmp .Ldone
|
||||
.Lfourth_is_float:
|
||||
movlpd %xmm3, 32(%rsp)
|
||||
|
||||
.Ldone:
|
||||
// ALLOCSTACK 40
|
||||
sub $40, %rsp
|
||||
// ENDPROLOG
|
||||
mov %rax, %rcx // context is first parameter
|
||||
mov %rsp, %rdx // stack is second parameter
|
||||
add $48, %rdx // point to start of arguments
|
||||
mov $SYMBOL_NAME(ffi_closure_win64_inner), %rax
|
||||
callq *%rax // call the real closure function
|
||||
add $40, %rsp
|
||||
movq %rax, %xmm0 // If the closure returned a float,
|
||||
// ffi_closure_win64_inner wrote it to rax
|
||||
retq
|
||||
.ffi_closure_win64_end:
|
||||
|
||||
.balign 16
|
||||
.globl SYMBOL_NAME(ffi_call_win64)
|
||||
SYMBOL_NAME(ffi_call_win64):
|
||||
// copy registers onto stack
|
||||
mov %r9,32(%rsp)
|
||||
mov %r8,24(%rsp)
|
||||
mov %rdx,16(%rsp)
|
||||
mov %rcx,8(%rsp)
|
||||
// PUSHREG rbp
|
||||
push %rbp
|
||||
// ALLOCSTACK 48
|
||||
sub $48,%rsp
|
||||
// SETFRAME rbp, 32
|
||||
lea 32(%rsp),%rbp
|
||||
// ENDPROLOG
|
||||
|
||||
mov CIF_BYTES(%rbp),%eax
|
||||
add $15, %rax
|
||||
and $-16, %rax
|
||||
cmpq $0x1000, %rax
|
||||
jb Lch_done
|
||||
Lch_probe:
|
||||
subq $0x1000,%rsp
|
||||
orl $0x0, (%rsp)
|
||||
subq $0x1000,%rax
|
||||
cmpq $0x1000,%rax
|
||||
ja Lch_probe
|
||||
Lch_done:
|
||||
subq %rax, %rsp
|
||||
orl $0x0, (%rsp)
|
||||
lea 32(%rsp), %rax
|
||||
mov %rax, STACK(%rbp)
|
||||
|
||||
mov ECIF(%rbp), %rdx
|
||||
mov STACK(%rbp), %rcx
|
||||
callq *PREP_ARGS_FN(%rbp)
|
||||
|
||||
mov STACK(%rbp), %rsp
|
||||
|
||||
movlpd 24(%rsp), %xmm3
|
||||
movd %xmm3, %r9
|
||||
|
||||
movlpd 16(%rsp), %xmm2
|
||||
movd %xmm2, %r8
|
||||
|
||||
movlpd 8(%rsp), %xmm1
|
||||
movd %xmm1, %rdx
|
||||
|
||||
movlpd (%rsp), %xmm0
|
||||
movd %xmm0, %rcx
|
||||
|
||||
callq *FN(%rbp)
|
||||
.Lret_struct4b:
|
||||
cmpl $FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp)
|
||||
jne .Lret_struct2b
|
||||
|
||||
mov RVALUE(%rbp), %rcx
|
||||
mov %eax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_struct2b:
|
||||
cmpl $FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp)
|
||||
jne .Lret_struct1b
|
||||
|
||||
mov RVALUE(%rbp), %rcx
|
||||
mov %ax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_struct1b:
|
||||
cmpl $FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp)
|
||||
jne .Lret_uint8
|
||||
|
||||
mov RVALUE(%rbp), %rcx
|
||||
mov %al, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_uint8:
|
||||
cmpl $FFI_TYPE_UINT8, CIF_FLAGS(%rbp)
|
||||
jne .Lret_sint8
|
||||
|
||||
mov RVALUE(%rbp), %rcx
|
||||
movzbq %al, %rax
|
||||
movq %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_sint8:
|
||||
cmpl $FFI_TYPE_SINT8, CIF_FLAGS(%rbp)
|
||||
jne .Lret_uint16
|
||||
|
||||
mov RVALUE(%rbp), %rcx
|
||||
movsbq %al, %rax
|
||||
movq %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_uint16:
|
||||
cmpl $FFI_TYPE_UINT16, CIF_FLAGS(%rbp)
|
||||
jne .Lret_sint16
|
||||
|
||||
mov RVALUE(%rbp), %rcx
|
||||
movzwq %ax, %rax
|
||||
movq %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_sint16:
|
||||
cmpl $FFI_TYPE_SINT16, CIF_FLAGS(%rbp)
|
||||
jne .Lret_uint32
|
||||
|
||||
mov RVALUE(%rbp), %rcx
|
||||
movswq %ax, %rax
|
||||
movq %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_uint32:
|
||||
cmpl $FFI_TYPE_UINT32, CIF_FLAGS(%rbp)
|
||||
jne .Lret_sint32
|
||||
|
||||
mov RVALUE(%rbp), %rcx
|
||||
movl %eax, %eax
|
||||
movq %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_sint32:
|
||||
cmpl $FFI_TYPE_SINT32, CIF_FLAGS(%rbp)
|
||||
jne .Lret_float
|
||||
|
||||
mov RVALUE(%rbp), %rcx
|
||||
cltq
|
||||
movq %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_float:
|
||||
cmpl $FFI_TYPE_FLOAT, CIF_FLAGS(%rbp)
|
||||
jne .Lret_double
|
||||
|
||||
mov RVALUE(%rbp), %rax
|
||||
movss %xmm0, (%rax)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_double:
|
||||
cmpl $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp)
|
||||
jne .Lret_sint64
|
||||
|
||||
mov RVALUE(%rbp), %rax
|
||||
movlpd %xmm0, (%rax)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_sint64:
|
||||
cmpl $FFI_TYPE_SINT64, CIF_FLAGS(%rbp)
|
||||
jne .Lret_void
|
||||
|
||||
mov RVALUE(%rbp), %rcx
|
||||
mov %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_void:
|
||||
xor %rax, %rax
|
||||
|
||||
lea 16(%rbp), %rsp
|
||||
pop %rbp
|
||||
retq
|
||||
.ffi_call_win64_end:
|
||||
#endif /* !_MSC_VER */
|
||||
|
||||
227
lib/wrappers/libffi/gcc/win64_asm.s
Normal file
227
lib/wrappers/libffi/gcc/win64_asm.s
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
# 1 "gcc\\win64_asm.asm"
|
||||
# 1 "<command-line>"
|
||||
# 1 "gcc\\win64_asm.asm"
|
||||
|
||||
# 1 "common/fficonfig.h" 1
|
||||
# 3 "gcc\\win64_asm.asm" 2
|
||||
# 1 "common/ffi.h" 1
|
||||
# 63 "common/ffi.h"
|
||||
# 1 "common/ffitarget.h" 1
|
||||
# 64 "common/ffi.h" 2
|
||||
# 4 "gcc\\win64_asm.asm" 2
|
||||
# 244 "gcc\\win64_asm.asm"
|
||||
.text
|
||||
|
||||
.extern ffi_closure_win64_inner
|
||||
# 255 "gcc\\win64_asm.asm"
|
||||
.balign 16
|
||||
.globl ffi_closure_win64
|
||||
ffi_closure_win64:
|
||||
|
||||
test $1,%r11
|
||||
jne .Lfirst_is_float
|
||||
mov %rcx, 8(%rsp)
|
||||
jmp .Lsecond
|
||||
.Lfirst_is_float:
|
||||
movlpd %xmm0, 8(%rsp)
|
||||
|
||||
.Lsecond:
|
||||
test $2, %r11
|
||||
jne .Lsecond_is_float
|
||||
mov %rdx, 16(%rsp)
|
||||
jmp .Lthird
|
||||
.Lsecond_is_float:
|
||||
movlpd %xmm1, 16(%rsp)
|
||||
|
||||
.Lthird:
|
||||
test $4, %r11
|
||||
jne .Lthird_is_float
|
||||
mov %r8,24(%rsp)
|
||||
jmp .Lfourth
|
||||
.Lthird_is_float:
|
||||
movlpd %xmm2, 24(%rsp)
|
||||
|
||||
.Lfourth:
|
||||
test $8, %r11
|
||||
jne .Lfourth_is_float
|
||||
mov %r9, 32(%rsp)
|
||||
jmp .Ldone
|
||||
.Lfourth_is_float:
|
||||
movlpd %xmm3, 32(%rsp)
|
||||
|
||||
.Ldone:
|
||||
|
||||
sub $40, %rsp
|
||||
|
||||
mov %rax, %rcx
|
||||
mov %rsp, %rdx
|
||||
add $48, %rdx
|
||||
mov $SYMBOL_NAME(ffi_closure_win64_inner), %rax
|
||||
callq *%rax
|
||||
add $40, %rsp
|
||||
movq %rax, %xmm0
|
||||
|
||||
retq
|
||||
.ffi_closure_win64_end:
|
||||
|
||||
.balign 16
|
||||
.globl ffi_call_win64
|
||||
ffi_call_win64:
|
||||
|
||||
mov %r9,32(%rsp)
|
||||
mov %r8,24(%rsp)
|
||||
mov %rdx,16(%rsp)
|
||||
mov %rcx,8(%rsp)
|
||||
|
||||
push %rbp
|
||||
|
||||
sub $48,%rsp
|
||||
|
||||
lea 32(%rsp),%rbp
|
||||
|
||||
|
||||
mov 48(%rbp),%eax
|
||||
add $15, %rax
|
||||
and $-16, %rax
|
||||
cmpq $0x1000, %rax
|
||||
jb Lch_done
|
||||
Lch_probe:
|
||||
subq $0x1000,%rsp
|
||||
orl $0x0, (%rsp)
|
||||
subq $0x1000,%rax
|
||||
cmpq $0x1000,%rax
|
||||
ja Lch_probe
|
||||
Lch_done:
|
||||
subq %rax, %rsp
|
||||
orl $0x0, (%rsp)
|
||||
lea 32(%rsp), %rax
|
||||
mov %rax, 0(%rbp)
|
||||
|
||||
mov 40(%rbp), %rdx
|
||||
mov 0(%rbp), %rcx
|
||||
callq *32(%rbp)
|
||||
|
||||
mov 0(%rbp), %rsp
|
||||
|
||||
movlpd 24(%rsp), %xmm3
|
||||
movd %xmm3, %r9
|
||||
|
||||
movlpd 16(%rsp), %xmm2
|
||||
movd %xmm2, %r8
|
||||
|
||||
movlpd 8(%rsp), %xmm1
|
||||
movd %xmm1, %rdx
|
||||
|
||||
movlpd (%rsp), %xmm0
|
||||
movd %xmm0, %rcx
|
||||
|
||||
callq *72(%rbp)
|
||||
.Lret_struct4b:
|
||||
cmpl $FFI_TYPE_SMALL_STRUCT_4B, 56(%rbp)
|
||||
jne .Lret_struct2b
|
||||
|
||||
mov 64(%rbp), %rcx
|
||||
mov %eax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_struct2b:
|
||||
cmpl $FFI_TYPE_SMALL_STRUCT_2B, 56(%rbp)
|
||||
jne .Lret_struct1b
|
||||
|
||||
mov 64(%rbp), %rcx
|
||||
mov %ax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_struct1b:
|
||||
cmpl $FFI_TYPE_SMALL_STRUCT_1B, 56(%rbp)
|
||||
jne .Lret_uint8
|
||||
|
||||
mov 64(%rbp), %rcx
|
||||
mov %al, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_uint8:
|
||||
cmpl $FFI_TYPE_UINT8, 56(%rbp)
|
||||
jne .Lret_sint8
|
||||
|
||||
mov 64(%rbp), %rcx
|
||||
movzbq %al, %rax
|
||||
movq %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_sint8:
|
||||
cmpl $FFI_TYPE_SINT8, 56(%rbp)
|
||||
jne .Lret_uint16
|
||||
|
||||
mov 64(%rbp), %rcx
|
||||
movsbq %al, %rax
|
||||
movq %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_uint16:
|
||||
cmpl $FFI_TYPE_UINT16, 56(%rbp)
|
||||
jne .Lret_sint16
|
||||
|
||||
mov 64(%rbp), %rcx
|
||||
movzwq %ax, %rax
|
||||
movq %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_sint16:
|
||||
cmpl $FFI_TYPE_SINT16, 56(%rbp)
|
||||
jne .Lret_uint32
|
||||
|
||||
mov 64(%rbp), %rcx
|
||||
movswq %ax, %rax
|
||||
movq %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_uint32:
|
||||
cmpl $9, 56(%rbp)
|
||||
jne .Lret_sint32
|
||||
|
||||
mov 64(%rbp), %rcx
|
||||
movl %eax, %eax
|
||||
movq %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_sint32:
|
||||
cmpl $10, 56(%rbp)
|
||||
jne .Lret_float
|
||||
|
||||
mov 64(%rbp), %rcx
|
||||
cltq
|
||||
movq %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_float:
|
||||
cmpl $2, 56(%rbp)
|
||||
jne .Lret_double
|
||||
|
||||
mov 64(%rbp), %rax
|
||||
movss %xmm0, (%rax)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_double:
|
||||
cmpl $3, 56(%rbp)
|
||||
jne .Lret_sint64
|
||||
|
||||
mov 64(%rbp), %rax
|
||||
movlpd %xmm0, (%rax)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_sint64:
|
||||
cmpl $12, 56(%rbp)
|
||||
jne .Lret_void
|
||||
|
||||
mov 64(%rbp), %rcx
|
||||
mov %rax, (%rcx)
|
||||
jmp .Lret_void
|
||||
|
||||
.Lret_void:
|
||||
xor %rax, %rax
|
||||
|
||||
lea 16(%rbp), %rsp
|
||||
pop %rbp
|
||||
retq
|
||||
.ffi_call_win64_end:
|
||||
|
|
@ -26,12 +26,36 @@
|
|||
|
||||
{.deadCodeElim: on.}
|
||||
|
||||
when defined(windows):
|
||||
const libffidll* = "libffi.dll"
|
||||
elif defined(macosx):
|
||||
const libffidll* = "libffi.dylib"
|
||||
else:
|
||||
const libffidll* = "libffi.so"
|
||||
when defined(windows):
|
||||
# on Windows we don't use a DLL but instead embed libffi directly:
|
||||
{.pragma: mylib, header: r"ffi.h".}
|
||||
|
||||
#{.compile: r"common\malloc_closure.c".}
|
||||
{.compile: r"common\raw_api.c".}
|
||||
when defined(vcc):
|
||||
{.compile: r"msvc\ffi.c".}
|
||||
{.compile: r"msvc\prep_cif.c".}
|
||||
{.compile: r"msvc\win32.c".}
|
||||
{.compile: r"msvc\types.c".}
|
||||
when defined(cpu64):
|
||||
{.compile: r"msvc\win64_asm.asm".}
|
||||
else:
|
||||
{.compile: r"msvc\win32_asm.asm".}
|
||||
else:
|
||||
{.compile: r"gcc\ffi.c".}
|
||||
{.compile: r"gcc\prep_cif.c".}
|
||||
{.compile: r"gcc\types.c".}
|
||||
{.compile: r"gcc\closures.c".}
|
||||
when defined(cpu64):
|
||||
{.compile: r"gcc\ffi64.c".}
|
||||
{.compile: r"gcc\win64_asm.S".}
|
||||
else:
|
||||
{.compile: r"gcc\win32_asm.S".}
|
||||
|
||||
elif defined(macosx):
|
||||
{.pragma: mylib, dynlib: "libffi.dylib".}
|
||||
else:
|
||||
{.pragma: mylib, dynlib: "libffi.so".}
|
||||
|
||||
type
|
||||
TArg* = int
|
||||
|
|
@ -88,19 +112,19 @@ type
|
|||
elements*: ptr ptr TType
|
||||
|
||||
var
|
||||
type_void* {.importc: "ffi_type_void", dynlib: libffidll.}: TType
|
||||
type_uint8* {.importc: "ffi_type_uint8", dynlib: libffidll.}: TType
|
||||
type_sint8* {.importc: "ffi_type_sint8", dynlib: libffidll.}: TType
|
||||
type_uint16* {.importc: "ffi_type_uint16", dynlib: libffidll.}: TType
|
||||
type_sint16* {.importc: "ffi_type_sint16", dynlib: libffidll.}: TType
|
||||
type_uint32* {.importc: "ffi_type_uint32", dynlib: libffidll.}: TType
|
||||
type_sint32* {.importc: "ffi_type_sint32", dynlib: libffidll.}: TType
|
||||
type_uint64* {.importc: "ffi_type_uint64", dynlib: libffidll.}: TType
|
||||
type_sint64* {.importc: "ffi_type_sint64", dynlib: libffidll.}: TType
|
||||
type_float* {.importc: "ffi_type_float", dynlib: libffidll.}: TType
|
||||
type_double* {.importc: "ffi_type_double", dynlib: libffidll.}: TType
|
||||
type_pointer* {.importc: "ffi_type_pointer", dynlib: libffidll.}: TType
|
||||
type_longdouble* {.importc: "ffi_type_longdouble", dynlib: libffidll.}: TType
|
||||
type_void* {.importc: "ffi_type_void", mylib.}: TType
|
||||
type_uint8* {.importc: "ffi_type_uint8", mylib.}: TType
|
||||
type_sint8* {.importc: "ffi_type_sint8", mylib.}: TType
|
||||
type_uint16* {.importc: "ffi_type_uint16", mylib.}: TType
|
||||
type_sint16* {.importc: "ffi_type_sint16", mylib.}: TType
|
||||
type_uint32* {.importc: "ffi_type_uint32", mylib.}: TType
|
||||
type_sint32* {.importc: "ffi_type_sint32", mylib.}: TType
|
||||
type_uint64* {.importc: "ffi_type_uint64", mylib.}: TType
|
||||
type_sint64* {.importc: "ffi_type_sint64", mylib.}: TType
|
||||
type_float* {.importc: "ffi_type_float", mylib.}: TType
|
||||
type_double* {.importc: "ffi_type_double", mylib.}: TType
|
||||
type_pointer* {.importc: "ffi_type_pointer", mylib.}: TType
|
||||
type_longdouble* {.importc: "ffi_type_longdouble", mylib.}: TType
|
||||
|
||||
type
|
||||
Tstatus* {.size: sizeof(cint).} = enum
|
||||
|
|
@ -119,20 +143,18 @@ type
|
|||
sint*: TSArg
|
||||
|
||||
proc raw_call*(cif: var Tcif; fn: proc () {.cdecl.}; rvalue: pointer;
|
||||
avalue: ptr TRaw) {.cdecl, importc: "ffi_raw_call",
|
||||
dynlib: libffidll.}
|
||||
avalue: ptr TRaw) {.cdecl, importc: "ffi_raw_call", mylib.}
|
||||
proc ptrarray_to_raw*(cif: var Tcif; args: ptr pointer; raw: ptr TRaw) {.cdecl,
|
||||
importc: "ffi_ptrarray_to_raw", dynlib: libffidll.}
|
||||
importc: "ffi_ptrarray_to_raw", mylib.}
|
||||
proc raw_to_ptrarray*(cif: var Tcif; raw: ptr TRaw; args: ptr pointer) {.cdecl,
|
||||
importc: "ffi_raw_to_ptrarray", dynlib: libffidll.}
|
||||
proc raw_size*(cif: var Tcif): int {.cdecl, importc: "ffi_raw_size",
|
||||
dynlib: libffidll.}
|
||||
importc: "ffi_raw_to_ptrarray", mylib.}
|
||||
proc raw_size*(cif: var Tcif): int {.cdecl, importc: "ffi_raw_size", mylib.}
|
||||
|
||||
proc prep_cif*(cif: var Tcif; abi: TABI; nargs: cuint; rtype: ptr TType;
|
||||
atypes: ptr ptr TType): TStatus {.cdecl, importc: "ffi_prep_cif",
|
||||
dynlib: libffidll.}
|
||||
mylib.}
|
||||
proc call*(cif: var Tcif; fn: proc () {.cdecl.}; rvalue: pointer;
|
||||
avalue: ptr pointer) {.cdecl, importc: "ffi_call", dynlib: libffidll.}
|
||||
avalue: ptr pointer) {.cdecl, importc: "ffi_call", mylib.}
|
||||
|
||||
# the same with an easier interface:
|
||||
type
|
||||
|
|
@ -141,9 +163,9 @@ type
|
|||
|
||||
proc prep_cif*(cif: var Tcif; abi: TABI; nargs: cuint; rtype: ptr TType;
|
||||
atypes: TParamList): TStatus {.cdecl, importc: "ffi_prep_cif",
|
||||
dynlib: libffidll.}
|
||||
mylib.}
|
||||
proc call*(cif: var Tcif; fn, rvalue: pointer;
|
||||
avalue: TArgList) {.cdecl, importc: "ffi_call", dynlib: libffidll.}
|
||||
avalue: TArgList) {.cdecl, importc: "ffi_call", mylib.}
|
||||
|
||||
# Useful for eliminating compiler warnings
|
||||
##define FFI_FN(f) ((void (*)(void))f)
|
||||
457
lib/wrappers/libffi/msvc/ffi.c
Normal file
457
lib/wrappers/libffi/msvc/ffi.c
Normal file
|
|
@ -0,0 +1,457 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc.
|
||||
Copyright (c) 2002 Ranjit Mathew
|
||||
Copyright (c) 2002 Bo Thorsen
|
||||
Copyright (c) 2002 Roger Sayle
|
||||
|
||||
x86 Foreign Function Interface
|
||||
|
||||
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 CYGNUS SOLUTIONS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
extern void Py_FatalError(const char *msg);
|
||||
|
||||
/*@-exportheader@*/
|
||||
void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += sizeof(void *);
|
||||
}
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
i != 0;
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(void *) - 1) & (size_t) argp)
|
||||
argp = (char *) ALIGN(argp, sizeof(void *));
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
*(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
if (argp >= stack && (unsigned)(argp - stack) > ecif->cif->bytes)
|
||||
{
|
||||
Py_FatalError("FFI BUG: not enough stack space for arguments");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
#ifdef _WIN64
|
||||
case FFI_TYPE_POINTER:
|
||||
#endif
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
extern int
|
||||
ffi_call_x86(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)());
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
extern int
|
||||
ffi_call_AMD64(void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif *,
|
||||
unsigned, unsigned,
|
||||
/*@out@*/ unsigned *,
|
||||
void (*fn)());
|
||||
#endif
|
||||
|
||||
int
|
||||
ffi_call(/*@dependent@*/ ffi_cif *cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void *rvalue,
|
||||
/*@dependent@*/ void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return */
|
||||
/* value address then we need to make one */
|
||||
|
||||
if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
#if !defined(_WIN64)
|
||||
case FFI_SYSV:
|
||||
case FFI_STDCALL:
|
||||
return ffi_call_x86(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
#else
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
/* Function call needs at least 40 bytes stack size, on win64 AMD64 */
|
||||
return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes ? cif->bytes : 40,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
return -1; /* theller: Hrm. */
|
||||
}
|
||||
|
||||
|
||||
/** private members **/
|
||||
|
||||
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
|
||||
void** args, ffi_cif* cif);
|
||||
/* This function is jumped to by the trampoline */
|
||||
|
||||
#ifdef _WIN64
|
||||
void *
|
||||
#else
|
||||
static void __fastcall
|
||||
#endif
|
||||
ffi_closure_SYSV (ffi_closure *closure, int *argp)
|
||||
{
|
||||
// this is our return value storage
|
||||
long double res;
|
||||
|
||||
// our various things...
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
unsigned short rtype;
|
||||
void *resp = (void*)&res;
|
||||
void *args = &argp[1];
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
|
||||
/* this call will initialize ARG_AREA, such that each
|
||||
* element in that array points to the corresponding
|
||||
* value on the stack; and if the function returns
|
||||
* a structure, it will re-set RESP to point to the
|
||||
* structure return address. */
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, resp, arg_area, closure->user_data);
|
||||
|
||||
rtype = cif->flags;
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
#ifdef _MSC_VER
|
||||
/* now, do a generic return based on the value of rtype */
|
||||
if (rtype == FFI_TYPE_INT)
|
||||
{
|
||||
_asm mov eax, resp ;
|
||||
_asm mov eax, [eax] ;
|
||||
}
|
||||
else if (rtype == FFI_TYPE_FLOAT)
|
||||
{
|
||||
_asm mov eax, resp ;
|
||||
_asm fld DWORD PTR [eax] ;
|
||||
// asm ("flds (%0)" : : "r" (resp) : "st" );
|
||||
}
|
||||
else if (rtype == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
_asm mov eax, resp ;
|
||||
_asm fld QWORD PTR [eax] ;
|
||||
// asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
|
||||
}
|
||||
else if (rtype == FFI_TYPE_LONGDOUBLE)
|
||||
{
|
||||
// asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
|
||||
}
|
||||
else if (rtype == FFI_TYPE_SINT64)
|
||||
{
|
||||
_asm mov edx, resp ;
|
||||
_asm mov eax, [edx] ;
|
||||
_asm mov edx, [edx + 4] ;
|
||||
// asm ("movl 0(%0),%%eax;"
|
||||
// "movl 4(%0),%%edx"
|
||||
// : : "r"(resp)
|
||||
// : "eax", "edx");
|
||||
}
|
||||
#else
|
||||
/* now, do a generic return based on the value of rtype */
|
||||
if (rtype == FFI_TYPE_INT)
|
||||
{
|
||||
asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
|
||||
}
|
||||
else if (rtype == FFI_TYPE_FLOAT)
|
||||
{
|
||||
asm ("flds (%0)" : : "r" (resp) : "st" );
|
||||
}
|
||||
else if (rtype == FFI_TYPE_DOUBLE)
|
||||
{
|
||||
asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
|
||||
}
|
||||
else if (rtype == FFI_TYPE_LONGDOUBLE)
|
||||
{
|
||||
asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
|
||||
}
|
||||
else if (rtype == FFI_TYPE_SINT64)
|
||||
{
|
||||
asm ("movl 0(%0),%%eax;"
|
||||
"movl 4(%0),%%edx"
|
||||
: : "r"(resp)
|
||||
: "eax", "edx");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
/* The result is returned in rax. This does the right thing for
|
||||
result types except for floats; we have to 'mov xmm0, rax' in the
|
||||
caller to correct this.
|
||||
*/
|
||||
return *(void **)resp;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*@-exportheader@*/
|
||||
static void
|
||||
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
|
||||
void **avalue, ffi_cif *cif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if ( cif->rtype->type == FFI_TYPE_STRUCT ) {
|
||||
*rvalue = *(void **) argp;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(char *) - 1) & (size_t) argp) {
|
||||
argp = (char *) ALIGN(argp, sizeof(char*));
|
||||
}
|
||||
|
||||
z = (*p_arg)->size;
|
||||
|
||||
/* because we're little endian, this is what it turns into. */
|
||||
|
||||
*p_argv = (void*) argp;
|
||||
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* the cif must already be prep'ed */
|
||||
extern void ffi_closure_OUTER();
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
short bytes;
|
||||
char *tramp;
|
||||
#ifdef _WIN64
|
||||
int mask = 0;
|
||||
#endif
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
if (cif->abi == FFI_SYSV)
|
||||
bytes = 0;
|
||||
#if !defined(_WIN64)
|
||||
else if (cif->abi == FFI_STDCALL)
|
||||
bytes = cif->bytes;
|
||||
#endif
|
||||
else
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
tramp = &closure->tramp[0];
|
||||
|
||||
#define BYTES(text) memcpy(tramp, text, sizeof(text)), tramp += sizeof(text)-1
|
||||
#define POINTER(x) *(void**)tramp = (void*)(x), tramp += sizeof(void*)
|
||||
#define SHORT(x) *(short*)tramp = x, tramp += sizeof(short)
|
||||
#define INT(x) *(int*)tramp = x, tramp += sizeof(int)
|
||||
|
||||
#ifdef _WIN64
|
||||
if (cif->nargs >= 1 &&
|
||||
(cif->arg_types[0]->type == FFI_TYPE_FLOAT
|
||||
|| cif->arg_types[0]->type == FFI_TYPE_DOUBLE))
|
||||
mask |= 1;
|
||||
if (cif->nargs >= 2 &&
|
||||
(cif->arg_types[1]->type == FFI_TYPE_FLOAT
|
||||
|| cif->arg_types[1]->type == FFI_TYPE_DOUBLE))
|
||||
mask |= 2;
|
||||
if (cif->nargs >= 3 &&
|
||||
(cif->arg_types[2]->type == FFI_TYPE_FLOAT
|
||||
|| cif->arg_types[2]->type == FFI_TYPE_DOUBLE))
|
||||
mask |= 4;
|
||||
if (cif->nargs >= 4 &&
|
||||
(cif->arg_types[3]->type == FFI_TYPE_FLOAT
|
||||
|| cif->arg_types[3]->type == FFI_TYPE_DOUBLE))
|
||||
mask |= 8;
|
||||
|
||||
/* 41 BB ---- mov r11d,mask */
|
||||
BYTES("\x41\xBB"); INT(mask);
|
||||
|
||||
/* 48 B8 -------- mov rax, closure */
|
||||
BYTES("\x48\xB8"); POINTER(closure);
|
||||
|
||||
/* 49 BA -------- mov r10, ffi_closure_OUTER */
|
||||
BYTES("\x49\xBA"); POINTER(ffi_closure_OUTER);
|
||||
|
||||
/* 41 FF E2 jmp r10 */
|
||||
BYTES("\x41\xFF\xE2");
|
||||
|
||||
#else
|
||||
|
||||
/* mov ecx, closure */
|
||||
BYTES("\xb9"); POINTER(closure);
|
||||
|
||||
/* mov edx, esp */
|
||||
BYTES("\x8b\xd4");
|
||||
|
||||
/* call ffi_closure_SYSV */
|
||||
BYTES("\xe8"); POINTER((char*)&ffi_closure_SYSV - (tramp + 4));
|
||||
|
||||
/* ret bytes */
|
||||
BYTES("\xc2");
|
||||
SHORT(bytes);
|
||||
|
||||
#endif
|
||||
|
||||
if (tramp - &closure->tramp[0] > FFI_TRAMPOLINE_SIZE)
|
||||
Py_FatalError("FFI_TRAMPOLINE_SIZE too small in " __FILE__);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
return FFI_OK;
|
||||
}
|
||||
175
lib/wrappers/libffi/msvc/prep_cif.c
Normal file
175
lib/wrappers/libffi/msvc/prep_cif.c
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc.
|
||||
|
||||
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 CYGNUS SOLUTIONS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/* Round up to FFI_SIZEOF_ARG. */
|
||||
|
||||
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
|
||||
|
||||
/* Perform machine independent initialization of aggregate type
|
||||
specifications. */
|
||||
|
||||
static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
|
||||
{
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT(arg != NULL);
|
||||
|
||||
/*@-usedef@*/
|
||||
|
||||
FFI_ASSERT(arg->elements != NULL);
|
||||
FFI_ASSERT(arg->size == 0);
|
||||
FFI_ASSERT(arg->alignment == 0);
|
||||
|
||||
ptr = &(arg->elements[0]);
|
||||
|
||||
while ((*ptr) != NULL)
|
||||
{
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the argument type */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
arg->size = ALIGN(arg->size, (*ptr)->alignment);
|
||||
arg->size += (*ptr)->size;
|
||||
|
||||
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
|
||||
arg->alignment : (*ptr)->alignment;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* Structure size includes tail padding. This is important for
|
||||
structures that fit in one register on ABIs like the PowerPC64
|
||||
Linux ABI that right justify small structs in a register.
|
||||
It's also needed for nested structure layout, for example
|
||||
struct A { long a; char b; }; struct B { struct A x; char y; };
|
||||
should find y at an offset of 2*sizeof(long) and result in a
|
||||
total size of 3*sizeof(long). */
|
||||
arg->size = ALIGN (arg->size, arg->alignment);
|
||||
|
||||
if (arg->size == 0)
|
||||
return FFI_BAD_TYPEDEF;
|
||||
else
|
||||
return FFI_OK;
|
||||
|
||||
/*@=usedef@*/
|
||||
}
|
||||
|
||||
/* Perform machine independent ffi_cif preparation, then call
|
||||
machine dependent routine. */
|
||||
|
||||
ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
|
||||
ffi_abi abi, unsigned int nargs,
|
||||
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
|
||||
/*@dependent@*/ ffi_type **atypes)
|
||||
{
|
||||
unsigned bytes = 0;
|
||||
unsigned int i;
|
||||
ffi_type **ptr;
|
||||
|
||||
FFI_ASSERT(cif != NULL);
|
||||
FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
|
||||
|
||||
cif->abi = abi;
|
||||
cif->arg_types = atypes;
|
||||
cif->nargs = nargs;
|
||||
cif->rtype = rtype;
|
||||
|
||||
cif->flags = 0;
|
||||
|
||||
/* Initialize the return type if necessary */
|
||||
/*@-usedef@*/
|
||||
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
/*@=usedef@*/
|
||||
|
||||
/* Perform a sanity check on the return type */
|
||||
FFI_ASSERT_VALID_TYPE(cif->rtype);
|
||||
|
||||
/* x86-64 and s390 stack space allocation is handled in prep_machdep. */
|
||||
#if !defined M68K && !defined __x86_64__ && !defined S390
|
||||
/* Make space for the return structure pointer */
|
||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
||||
/* MSVC returns small structures in registers. But we have a different
|
||||
workaround: pretend int32 or int64 return type, and converting to
|
||||
structure afterwards. */
|
||||
#ifdef SPARC
|
||||
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
|
||||
#endif
|
||||
)
|
||||
bytes = STACK_ARG_SIZE(sizeof(void*));
|
||||
#endif
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
|
||||
/* Initialize any uninitialized aggregate type definitions */
|
||||
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
|
||||
return FFI_BAD_TYPEDEF;
|
||||
|
||||
/* Perform a sanity check on the argument type, do this
|
||||
check after the initialization. */
|
||||
FFI_ASSERT_VALID_TYPE(*ptr);
|
||||
|
||||
#if !defined __x86_64__ && !defined S390
|
||||
#ifdef SPARC
|
||||
if (((*ptr)->type == FFI_TYPE_STRUCT
|
||||
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|
||||
|| ((*ptr)->type == FFI_TYPE_LONGDOUBLE
|
||||
&& cif->abi != FFI_V9))
|
||||
bytes += sizeof(void*);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#if !defined(_MSC_VER) && !defined(__MINGW32__)
|
||||
/* Don't know if this is a libffi bug or not. At least on
|
||||
Windows with MSVC, function call parameters are *not*
|
||||
aligned in the same way as structure fields are, they are
|
||||
only aligned in integer boundaries.
|
||||
|
||||
This doesn't do any harm for cdecl functions and closures,
|
||||
since the caller cleans up the stack, but it is wrong for
|
||||
stdcall functions where the callee cleans.
|
||||
*/
|
||||
|
||||
/* Add any padding if necessary */
|
||||
if (((*ptr)->alignment - 1) & bytes)
|
||||
bytes = ALIGN(bytes, (*ptr)->alignment);
|
||||
|
||||
#endif
|
||||
bytes += STACK_ARG_SIZE((*ptr)->size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
cif->bytes = bytes;
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
return ffi_prep_cif_machdep(cif);
|
||||
}
|
||||
104
lib/wrappers/libffi/msvc/types.c
Normal file
104
lib/wrappers/libffi/msvc/types.c
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
types.c - Copyright (c) 1996, 1998 Red Hat, Inc.
|
||||
|
||||
Predefined ffi_types needed by libffi.
|
||||
|
||||
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 CYGNUS SOLUTIONS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
/* Type definitions */
|
||||
|
||||
#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) ffi_type ffi_type_##n = { s, a, t, NULL }
|
||||
#define FFI_AGGREGATE_TYPEDEF(n, e) ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e }
|
||||
|
||||
/* Size and alignment are fake here. They must not be 0. */
|
||||
FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID);
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8);
|
||||
FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8);
|
||||
FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
|
||||
FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
|
||||
FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
|
||||
FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
|
||||
FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
|
||||
|
||||
#if defined ALPHA || defined SPARC64 || defined X86_64 || defined S390X \
|
||||
|| defined IA64
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
|
||||
|
||||
#else
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined X86 || defined X86_WIN32 || defined ARM || defined M68K
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
|
||||
|
||||
#elif defined SH
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
|
||||
|
||||
#else
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
|
||||
FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined X86 || defined X86_WIN32 || defined M68K
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#elif defined SPARC
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||
#ifdef SPARC64
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
|
||||
#else
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
|
||||
#endif
|
||||
|
||||
#elif defined X86_64
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#else
|
||||
|
||||
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
|
||||
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
|
||||
|
||||
#endif
|
||||
|
||||
162
lib/wrappers/libffi/msvc/win32.c
Normal file
162
lib/wrappers/libffi/msvc/win32.c
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc.
|
||||
Copyright (c) 2001 John Beniton
|
||||
Copyright (c) 2002 Ranjit Mathew
|
||||
|
||||
|
||||
X86 Foreign Function Interface
|
||||
|
||||
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 CYGNUS SOLUTIONS 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.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* theller: almost verbatim translation from gas syntax to MSVC inline
|
||||
assembler code. */
|
||||
|
||||
/* theller: ffi_call_x86 now returns an integer - the difference of the stack
|
||||
pointer before and after the function call. If everything is ok, zero is
|
||||
returned. If stdcall functions are passed the wrong number of arguments,
|
||||
the difference will be nonzero. */
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
__declspec(naked) int
|
||||
ffi_call_x86(void (* prepfunc)(char *, extended_cif *), /* 8 */
|
||||
extended_cif *ecif, /* 12 */
|
||||
unsigned bytes, /* 16 */
|
||||
unsigned flags, /* 20 */
|
||||
unsigned *rvalue, /* 24 */
|
||||
void (*fn)()) /* 28 */
|
||||
{
|
||||
_asm {
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
push esi // NEW: this register must be preserved across function calls
|
||||
// XXX SAVE ESP NOW!
|
||||
mov esi, esp // save stack pointer before the call
|
||||
|
||||
// Make room for all of the new args.
|
||||
mov ecx, [ebp+16]
|
||||
sub esp, ecx // sub esp, bytes
|
||||
|
||||
mov eax, esp
|
||||
|
||||
// Place all of the ffi_prep_args in position
|
||||
push [ebp + 12] // ecif
|
||||
push eax
|
||||
call [ebp + 8] // prepfunc
|
||||
|
||||
// Return stack to previous state and call the function
|
||||
add esp, 8
|
||||
// FIXME: Align the stack to a 128-bit boundary to avoid
|
||||
// potential performance hits.
|
||||
call [ebp + 28]
|
||||
|
||||
// Load ecif->cif->abi
|
||||
mov ecx, [ebp + 12]
|
||||
mov ecx, [ecx]ecif.cif
|
||||
mov ecx, [ecx]ecif.cif.abi
|
||||
|
||||
cmp ecx, FFI_STDCALL
|
||||
je noclean
|
||||
// STDCALL: Remove the space we pushed for the args
|
||||
mov ecx, [ebp + 16]
|
||||
add esp, ecx
|
||||
// CDECL: Caller has already cleaned the stack
|
||||
noclean:
|
||||
// Check that esp has the same value as before!
|
||||
sub esi, esp
|
||||
|
||||
// Load %ecx with the return type code
|
||||
mov ecx, [ebp + 20]
|
||||
|
||||
// If the return value pointer is NULL, assume no return value.
|
||||
/*
|
||||
Intel asm is weird. We have to explicitely specify 'DWORD PTR' in the nexr instruction,
|
||||
otherwise only one BYTE will be compared (instead of a DWORD)!
|
||||
*/
|
||||
cmp DWORD PTR [ebp + 24], 0
|
||||
jne sc_retint
|
||||
|
||||
// Even if there is no space for the return value, we are
|
||||
// obliged to handle floating-point values.
|
||||
cmp ecx, FFI_TYPE_FLOAT
|
||||
jne sc_noretval
|
||||
// fstp %st(0)
|
||||
fstp st(0)
|
||||
|
||||
jmp sc_epilogue
|
||||
|
||||
sc_retint:
|
||||
cmp ecx, FFI_TYPE_INT
|
||||
jne sc_retfloat
|
||||
// # Load %ecx with the pointer to storage for the return value
|
||||
mov ecx, [ebp + 24]
|
||||
mov [ecx + 0], eax
|
||||
jmp sc_epilogue
|
||||
|
||||
sc_retfloat:
|
||||
cmp ecx, FFI_TYPE_FLOAT
|
||||
jne sc_retdouble
|
||||
// Load %ecx with the pointer to storage for the return value
|
||||
mov ecx, [ebp+24]
|
||||
// fstps (%ecx)
|
||||
fstp DWORD PTR [ecx]
|
||||
jmp sc_epilogue
|
||||
|
||||
sc_retdouble:
|
||||
cmp ecx, FFI_TYPE_DOUBLE
|
||||
jne sc_retlongdouble
|
||||
// movl 24(%ebp),%ecx
|
||||
mov ecx, [ebp+24]
|
||||
fstp QWORD PTR [ecx]
|
||||
jmp sc_epilogue
|
||||
|
||||
jmp sc_retlongdouble // avoid warning about unused label
|
||||
sc_retlongdouble:
|
||||
cmp ecx, FFI_TYPE_LONGDOUBLE
|
||||
jne sc_retint64
|
||||
// Load %ecx with the pointer to storage for the return value
|
||||
mov ecx, [ebp+24]
|
||||
// fstpt (%ecx)
|
||||
fstp QWORD PTR [ecx] /* XXX ??? */
|
||||
jmp sc_epilogue
|
||||
|
||||
sc_retint64:
|
||||
cmp ecx, FFI_TYPE_SINT64
|
||||
jne sc_retstruct
|
||||
// Load %ecx with the pointer to storage for the return value
|
||||
mov ecx, [ebp+24]
|
||||
mov [ecx+0], eax
|
||||
mov [ecx+4], edx
|
||||
|
||||
sc_retstruct:
|
||||
// Nothing to do!
|
||||
|
||||
sc_noretval:
|
||||
sc_epilogue:
|
||||
mov eax, esi
|
||||
pop esi // NEW restore: must be preserved across function calls
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
}
|
||||
}
|
||||
470
lib/wrappers/libffi/msvc/win32_asm.asm
Normal file
470
lib/wrappers/libffi/msvc/win32_asm.asm
Normal file
|
|
@ -0,0 +1,470 @@
|
|||
/* -----------------------------------------------------------------------
|
||||
win32.S - Copyright (c) 1996, 1998, 2001, 2002, 2009 Red Hat, Inc.
|
||||
Copyright (c) 2001 John Beniton
|
||||
Copyright (c) 2002 Ranjit Mathew
|
||||
Copyright (c) 2009 Daniel Witte
|
||||
|
||||
|
||||
X86 Foreign Function Interface
|
||||
|
||||
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.
|
||||
-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define LIBFFI_ASM
|
||||
#include <fficonfig.h>
|
||||
#include <ffi.h>
|
||||
|
||||
.386
|
||||
.MODEL FLAT, C
|
||||
|
||||
EXTRN ffi_closure_SYSV_inner:NEAR
|
||||
|
||||
_TEXT SEGMENT
|
||||
|
||||
ffi_call_win32 PROC NEAR,
|
||||
ffi_prep_args : NEAR PTR DWORD,
|
||||
ecif : NEAR PTR DWORD,
|
||||
cif_abi : DWORD,
|
||||
cif_bytes : DWORD,
|
||||
cif_flags : DWORD,
|
||||
rvalue : NEAR PTR DWORD,
|
||||
fn : NEAR PTR DWORD
|
||||
|
||||
;; Make room for all of the new args.
|
||||
mov ecx, cif_bytes
|
||||
sub esp, ecx
|
||||
|
||||
mov eax, esp
|
||||
|
||||
;; Place all of the ffi_prep_args in position
|
||||
push ecif
|
||||
push eax
|
||||
call ffi_prep_args
|
||||
|
||||
;; Return stack to previous state and call the function
|
||||
add esp, 8
|
||||
|
||||
;; Handle thiscall and fastcall
|
||||
cmp cif_abi, 3 ;; FFI_THISCALL
|
||||
jz do_thiscall
|
||||
cmp cif_abi, 4 ;; FFI_FASTCALL
|
||||
jnz do_stdcall
|
||||
mov ecx, DWORD PTR [esp]
|
||||
mov edx, DWORD PTR [esp+4]
|
||||
add esp, 8
|
||||
jmp do_stdcall
|
||||
do_thiscall:
|
||||
mov ecx, DWORD PTR [esp]
|
||||
add esp, 4
|
||||
do_stdcall:
|
||||
call fn
|
||||
|
||||
;; cdecl: we restore esp in the epilogue, so there's no need to
|
||||
;; remove the space we pushed for the args.
|
||||
;; stdcall: the callee has already cleaned the stack.
|
||||
|
||||
;; Load ecx with the return type code
|
||||
mov ecx, cif_flags
|
||||
|
||||
;; If the return value pointer is NULL, assume no return value.
|
||||
cmp rvalue, 0
|
||||
jne ca_jumptable
|
||||
|
||||
;; Even if there is no space for the return value, we are
|
||||
;; obliged to handle floating-point values.
|
||||
cmp ecx, FFI_TYPE_FLOAT
|
||||
jne ca_epilogue
|
||||
fstp st(0)
|
||||
|
||||
jmp ca_epilogue
|
||||
|
||||
ca_jumptable:
|
||||
jmp [ca_jumpdata + 4 * ecx]
|
||||
ca_jumpdata:
|
||||
;; Do not insert anything here between label and jump table.
|
||||
dd offset ca_epilogue ;; FFI_TYPE_VOID
|
||||
dd offset ca_retint ;; FFI_TYPE_INT
|
||||
dd offset ca_retfloat ;; FFI_TYPE_FLOAT
|
||||
dd offset ca_retdouble ;; FFI_TYPE_DOUBLE
|
||||
dd offset ca_retlongdouble ;; FFI_TYPE_LONGDOUBLE
|
||||
dd offset ca_retuint8 ;; FFI_TYPE_UINT8
|
||||
dd offset ca_retsint8 ;; FFI_TYPE_SINT8
|
||||
dd offset ca_retuint16 ;; FFI_TYPE_UINT16
|
||||
dd offset ca_retsint16 ;; FFI_TYPE_SINT16
|
||||
dd offset ca_retint ;; FFI_TYPE_UINT32
|
||||
dd offset ca_retint ;; FFI_TYPE_SINT32
|
||||
dd offset ca_retint64 ;; FFI_TYPE_UINT64
|
||||
dd offset ca_retint64 ;; FFI_TYPE_SINT64
|
||||
dd offset ca_epilogue ;; FFI_TYPE_STRUCT
|
||||
dd offset ca_retint ;; FFI_TYPE_POINTER
|
||||
dd offset ca_retstruct1b ;; FFI_TYPE_SMALL_STRUCT_1B
|
||||
dd offset ca_retstruct2b ;; FFI_TYPE_SMALL_STRUCT_2B
|
||||
dd offset ca_retint ;; FFI_TYPE_SMALL_STRUCT_4B
|
||||
dd offset ca_epilogue ;; FFI_TYPE_MS_STRUCT
|
||||
|
||||
/* Sign/zero extend as appropriate. */
|
||||
ca_retuint8:
|
||||
movzx eax, al
|
||||
jmp ca_retint
|
||||
|
||||
ca_retsint8:
|
||||
movsx eax, al
|
||||
jmp ca_retint
|
||||
|
||||
ca_retuint16:
|
||||
movzx eax, ax
|
||||
jmp ca_retint
|
||||
|
||||
ca_retsint16:
|
||||
movsx eax, ax
|
||||
jmp ca_retint
|
||||
|
||||
ca_retint:
|
||||
;; Load %ecx with the pointer to storage for the return value
|
||||
mov ecx, rvalue
|
||||
mov [ecx + 0], eax
|
||||
jmp ca_epilogue
|
||||
|
||||
ca_retint64:
|
||||
;; Load %ecx with the pointer to storage for the return value
|
||||
mov ecx, rvalue
|
||||
mov [ecx + 0], eax
|
||||
mov [ecx + 4], edx
|
||||
jmp ca_epilogue
|
||||
|
||||
ca_retfloat:
|
||||
;; Load %ecx with the pointer to storage for the return value
|
||||
mov ecx, rvalue
|
||||
fstp DWORD PTR [ecx]
|
||||
jmp ca_epilogue
|
||||
|
||||
ca_retdouble:
|
||||
;; Load %ecx with the pointer to storage for the return value
|
||||
mov ecx, rvalue
|
||||
fstp QWORD PTR [ecx]
|
||||
jmp ca_epilogue
|
||||
|
||||
ca_retlongdouble:
|
||||
;; Load %ecx with the pointer to storage for the return value
|
||||
mov ecx, rvalue
|
||||
fstp TBYTE PTR [ecx]
|
||||
jmp ca_epilogue
|
||||
|
||||
ca_retstruct1b:
|
||||
;; Load %ecx with the pointer to storage for the return value
|
||||
mov ecx, rvalue
|
||||
mov [ecx + 0], al
|
||||
jmp ca_epilogue
|
||||
|
||||
ca_retstruct2b:
|
||||
;; Load %ecx with the pointer to storage for the return value
|
||||
mov ecx, rvalue
|
||||
mov [ecx + 0], ax
|
||||
jmp ca_epilogue
|
||||
|
||||
ca_epilogue:
|
||||
;; Epilogue code is autogenerated.
|
||||
ret
|
||||
ffi_call_win32 ENDP
|
||||
|
||||
ffi_closure_THISCALL PROC NEAR FORCEFRAME
|
||||
sub esp, 40
|
||||
lea edx, [ebp -24]
|
||||
mov [ebp - 12], edx /* resp */
|
||||
lea edx, [ebp + 12] /* account for stub return address on stack */
|
||||
jmp stub
|
||||
ffi_closure_THISCALL ENDP
|
||||
|
||||
ffi_closure_SYSV PROC NEAR FORCEFRAME
|
||||
;; the ffi_closure ctx is passed in eax by the trampoline.
|
||||
|
||||
sub esp, 40
|
||||
lea edx, [ebp - 24]
|
||||
mov [ebp - 12], edx ;; resp
|
||||
lea edx, [ebp + 8]
|
||||
stub::
|
||||
mov [esp + 8], edx ;; args
|
||||
lea edx, [ebp - 12]
|
||||
mov [esp + 4], edx ;; &resp
|
||||
mov [esp], eax ;; closure
|
||||
call ffi_closure_SYSV_inner
|
||||
mov ecx, [ebp - 12]
|
||||
|
||||
cs_jumptable:
|
||||
jmp [cs_jumpdata + 4 * eax]
|
||||
cs_jumpdata:
|
||||
;; Do not insert anything here between the label and jump table.
|
||||
dd offset cs_epilogue ;; FFI_TYPE_VOID
|
||||
dd offset cs_retint ;; FFI_TYPE_INT
|
||||
dd offset cs_retfloat ;; FFI_TYPE_FLOAT
|
||||
dd offset cs_retdouble ;; FFI_TYPE_DOUBLE
|
||||
dd offset cs_retlongdouble ;; FFI_TYPE_LONGDOUBLE
|
||||
dd offset cs_retuint8 ;; FFI_TYPE_UINT8
|
||||
dd offset cs_retsint8 ;; FFI_TYPE_SINT8
|
||||
dd offset cs_retuint16 ;; FFI_TYPE_UINT16
|
||||
dd offset cs_retsint16 ;; FFI_TYPE_SINT16
|
||||
dd offset cs_retint ;; FFI_TYPE_UINT32
|
||||
dd offset cs_retint ;; FFI_TYPE_SINT32
|
||||
dd offset cs_retint64 ;; FFI_TYPE_UINT64
|
||||
dd offset cs_retint64 ;; FFI_TYPE_SINT64
|
||||
dd offset cs_retstruct ;; FFI_TYPE_STRUCT
|
||||
dd offset cs_retint ;; FFI_TYPE_POINTER
|
||||
dd offset cs_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B
|
||||
dd offset cs_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B
|
||||
dd offset cs_retint ;; FFI_TYPE_SMALL_STRUCT_4B
|
||||
dd offset cs_retmsstruct ;; FFI_TYPE_MS_STRUCT
|
||||
|
||||
cs_retuint8:
|
||||
movzx eax, BYTE PTR [ecx]
|
||||
jmp cs_epilogue
|
||||
|
||||
cs_retsint8:
|
||||
movsx eax, BYTE PTR [ecx]
|
||||
jmp cs_epilogue
|
||||
|
||||
cs_retuint16:
|
||||
movzx eax, WORD PTR [ecx]
|
||||
jmp cs_epilogue
|
||||
|
||||
cs_retsint16:
|
||||
movsx eax, WORD PTR [ecx]
|
||||
jmp cs_epilogue
|
||||
|
||||
cs_retint:
|
||||
mov eax, [ecx]
|
||||
jmp cs_epilogue
|
||||
|
||||
cs_retint64:
|
||||
mov eax, [ecx + 0]
|
||||
mov edx, [ecx + 4]
|
||||
jmp cs_epilogue
|
||||
|
||||
cs_retfloat:
|
||||
fld DWORD PTR [ecx]
|
||||
jmp cs_epilogue
|
||||
|
||||
cs_retdouble:
|
||||
fld QWORD PTR [ecx]
|
||||
jmp cs_epilogue
|
||||
|
||||
cs_retlongdouble:
|
||||
fld TBYTE PTR [ecx]
|
||||
jmp cs_epilogue
|
||||
|
||||
cs_retstruct:
|
||||
;; Caller expects us to pop struct return value pointer hidden arg.
|
||||
;; Epilogue code is autogenerated.
|
||||
ret 4
|
||||
|
||||
cs_retmsstruct:
|
||||
;; Caller expects us to return a pointer to the real return value.
|
||||
mov eax, ecx
|
||||
;; Caller doesn't expects us to pop struct return value pointer hidden arg.
|
||||
jmp cs_epilogue
|
||||
|
||||
cs_epilogue:
|
||||
;; Epilogue code is autogenerated.
|
||||
ret
|
||||
ffi_closure_SYSV ENDP
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3)
|
||||
#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
|
||||
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
|
||||
#define CIF_FLAGS_OFFSET 20
|
||||
|
||||
ffi_closure_raw_THISCALL PROC NEAR USES esi FORCEFRAME
|
||||
sub esp, 36
|
||||
mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif
|
||||
mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data
|
||||
mov [esp + 12], edx
|
||||
lea edx, [ebp + 12]
|
||||
jmp stubraw
|
||||
ffi_closure_raw_THISCALL ENDP
|
||||
|
||||
ffi_closure_raw_SYSV PROC NEAR USES esi FORCEFRAME
|
||||
;; the ffi_closure ctx is passed in eax by the trampoline.
|
||||
|
||||
sub esp, 40
|
||||
mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif
|
||||
mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data
|
||||
mov [esp + 12], edx ;; user_data
|
||||
lea edx, [ebp + 8]
|
||||
stubraw::
|
||||
mov [esp + 8], edx ;; raw_args
|
||||
lea edx, [ebp - 24]
|
||||
mov [esp + 4], edx ;; &res
|
||||
mov [esp], esi ;; cif
|
||||
call DWORD PTR [eax + RAW_CLOSURE_FUN_OFFSET] ;; closure->fun
|
||||
mov eax, [esi + CIF_FLAGS_OFFSET] ;; cif->flags
|
||||
lea ecx, [ebp - 24]
|
||||
|
||||
cr_jumptable:
|
||||
jmp [cr_jumpdata + 4 * eax]
|
||||
cr_jumpdata:
|
||||
;; Do not insert anything here between the label and jump table.
|
||||
dd offset cr_epilogue ;; FFI_TYPE_VOID
|
||||
dd offset cr_retint ;; FFI_TYPE_INT
|
||||
dd offset cr_retfloat ;; FFI_TYPE_FLOAT
|
||||
dd offset cr_retdouble ;; FFI_TYPE_DOUBLE
|
||||
dd offset cr_retlongdouble ;; FFI_TYPE_LONGDOUBLE
|
||||
dd offset cr_retuint8 ;; FFI_TYPE_UINT8
|
||||
dd offset cr_retsint8 ;; FFI_TYPE_SINT8
|
||||
dd offset cr_retuint16 ;; FFI_TYPE_UINT16
|
||||
dd offset cr_retsint16 ;; FFI_TYPE_SINT16
|
||||
dd offset cr_retint ;; FFI_TYPE_UINT32
|
||||
dd offset cr_retint ;; FFI_TYPE_SINT32
|
||||
dd offset cr_retint64 ;; FFI_TYPE_UINT64
|
||||
dd offset cr_retint64 ;; FFI_TYPE_SINT64
|
||||
dd offset cr_epilogue ;; FFI_TYPE_STRUCT
|
||||
dd offset cr_retint ;; FFI_TYPE_POINTER
|
||||
dd offset cr_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B
|
||||
dd offset cr_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B
|
||||
dd offset cr_retint ;; FFI_TYPE_SMALL_STRUCT_4B
|
||||
dd offset cr_epilogue ;; FFI_TYPE_MS_STRUCT
|
||||
|
||||
cr_retuint8:
|
||||
movzx eax, BYTE PTR [ecx]
|
||||
jmp cr_epilogue
|
||||
|
||||
cr_retsint8:
|
||||
movsx eax, BYTE PTR [ecx]
|
||||
jmp cr_epilogue
|
||||
|
||||
cr_retuint16:
|
||||
movzx eax, WORD PTR [ecx]
|
||||
jmp cr_epilogue
|
||||
|
||||
cr_retsint16:
|
||||
movsx eax, WORD PTR [ecx]
|
||||
jmp cr_epilogue
|
||||
|
||||
cr_retint:
|
||||
mov eax, [ecx]
|
||||
jmp cr_epilogue
|
||||
|
||||
cr_retint64:
|
||||
mov eax, [ecx + 0]
|
||||
mov edx, [ecx + 4]
|
||||
jmp cr_epilogue
|
||||
|
||||
cr_retfloat:
|
||||
fld DWORD PTR [ecx]
|
||||
jmp cr_epilogue
|
||||
|
||||
cr_retdouble:
|
||||
fld QWORD PTR [ecx]
|
||||
jmp cr_epilogue
|
||||
|
||||
cr_retlongdouble:
|
||||
fld TBYTE PTR [ecx]
|
||||
jmp cr_epilogue
|
||||
|
||||
cr_epilogue:
|
||||
;; Epilogue code is autogenerated.
|
||||
ret
|
||||
ffi_closure_raw_SYSV ENDP
|
||||
|
||||
#endif /* !FFI_NO_RAW_API */
|
||||
|
||||
ffi_closure_STDCALL PROC NEAR FORCEFRAME
|
||||
;; the ffi_closure ctx is passed in eax by the trampoline.
|
||||
|
||||
sub esp, 40
|
||||
lea edx, [ebp - 24]
|
||||
mov [ebp - 12], edx ;; resp
|
||||
lea edx, [ebp + 12] ;; account for stub return address on stack
|
||||
mov [esp + 8], edx ;; args
|
||||
lea edx, [ebp - 12]
|
||||
mov [esp + 4], edx ;; &resp
|
||||
mov [esp], eax ;; closure
|
||||
call ffi_closure_SYSV_inner
|
||||
mov ecx, [ebp - 12]
|
||||
|
||||
cd_jumptable:
|
||||
jmp [cd_jumpdata + 4 * eax]
|
||||
cd_jumpdata:
|
||||
;; Do not insert anything here between the label and jump table.
|
||||
dd offset cd_epilogue ;; FFI_TYPE_VOID
|
||||
dd offset cd_retint ;; FFI_TYPE_INT
|
||||
dd offset cd_retfloat ;; FFI_TYPE_FLOAT
|
||||
dd offset cd_retdouble ;; FFI_TYPE_DOUBLE
|
||||
dd offset cd_retlongdouble ;; FFI_TYPE_LONGDOUBLE
|
||||
dd offset cd_retuint8 ;; FFI_TYPE_UINT8
|
||||
dd offset cd_retsint8 ;; FFI_TYPE_SINT8
|
||||
dd offset cd_retuint16 ;; FFI_TYPE_UINT16
|
||||
dd offset cd_retsint16 ;; FFI_TYPE_SINT16
|
||||
dd offset cd_retint ;; FFI_TYPE_UINT32
|
||||
dd offset cd_retint ;; FFI_TYPE_SINT32
|
||||
dd offset cd_retint64 ;; FFI_TYPE_UINT64
|
||||
dd offset cd_retint64 ;; FFI_TYPE_SINT64
|
||||
dd offset cd_epilogue ;; FFI_TYPE_STRUCT
|
||||
dd offset cd_retint ;; FFI_TYPE_POINTER
|
||||
dd offset cd_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B
|
||||
dd offset cd_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B
|
||||
dd offset cd_retint ;; FFI_TYPE_SMALL_STRUCT_4B
|
||||
|
||||
cd_retuint8:
|
||||
movzx eax, BYTE PTR [ecx]
|
||||
jmp cd_epilogue
|
||||
|
||||
cd_retsint8:
|
||||
movsx eax, BYTE PTR [ecx]
|
||||
jmp cd_epilogue
|
||||
|
||||
cd_retuint16:
|
||||
movzx eax, WORD PTR [ecx]
|
||||
jmp cd_epilogue
|
||||
|
||||
cd_retsint16:
|
||||
movsx eax, WORD PTR [ecx]
|
||||
jmp cd_epilogue
|
||||
|
||||
cd_retint:
|
||||
mov eax, [ecx]
|
||||
jmp cd_epilogue
|
||||
|
||||
cd_retint64:
|
||||
mov eax, [ecx + 0]
|
||||
mov edx, [ecx + 4]
|
||||
jmp cd_epilogue
|
||||
|
||||
cd_retfloat:
|
||||
fld DWORD PTR [ecx]
|
||||
jmp cd_epilogue
|
||||
|
||||
cd_retdouble:
|
||||
fld QWORD PTR [ecx]
|
||||
jmp cd_epilogue
|
||||
|
||||
cd_retlongdouble:
|
||||
fld TBYTE PTR [ecx]
|
||||
jmp cd_epilogue
|
||||
|
||||
cd_epilogue:
|
||||
;; Epilogue code is autogenerated.
|
||||
ret
|
||||
ffi_closure_STDCALL ENDP
|
||||
|
||||
_TEXT ENDS
|
||||
END
|
||||
156
lib/wrappers/libffi/msvc/win64_asm.asm
Normal file
156
lib/wrappers/libffi/msvc/win64_asm.asm
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
PUBLIC ffi_call_AMD64
|
||||
|
||||
EXTRN __chkstk:NEAR
|
||||
EXTRN ffi_closure_SYSV:NEAR
|
||||
|
||||
_TEXT SEGMENT
|
||||
|
||||
;;; ffi_closure_OUTER will be called with these registers set:
|
||||
;;; rax points to 'closure'
|
||||
;;; r11 contains a bit mask that specifies which of the
|
||||
;;; first four parameters are float or double
|
||||
;;;
|
||||
;;; It must move the parameters passed in registers to their stack location,
|
||||
;;; call ffi_closure_SYSV for the actual work, then return the result.
|
||||
;;;
|
||||
ffi_closure_OUTER PROC FRAME
|
||||
;; save actual arguments to their stack space.
|
||||
test r11, 1
|
||||
jne first_is_float
|
||||
mov QWORD PTR [rsp+8], rcx
|
||||
jmp second
|
||||
first_is_float:
|
||||
movlpd QWORD PTR [rsp+8], xmm0
|
||||
|
||||
second:
|
||||
test r11, 2
|
||||
jne second_is_float
|
||||
mov QWORD PTR [rsp+16], rdx
|
||||
jmp third
|
||||
second_is_float:
|
||||
movlpd QWORD PTR [rsp+16], xmm1
|
||||
|
||||
third:
|
||||
test r11, 4
|
||||
jne third_is_float
|
||||
mov QWORD PTR [rsp+24], r8
|
||||
jmp forth
|
||||
third_is_float:
|
||||
movlpd QWORD PTR [rsp+24], xmm2
|
||||
|
||||
forth:
|
||||
test r11, 8
|
||||
jne forth_is_float
|
||||
mov QWORD PTR [rsp+32], r9
|
||||
jmp done
|
||||
forth_is_float:
|
||||
movlpd QWORD PTR [rsp+32], xmm3
|
||||
|
||||
done:
|
||||
.ALLOCSTACK 40
|
||||
sub rsp, 40
|
||||
.ENDPROLOG
|
||||
mov rcx, rax ; context is first parameter
|
||||
mov rdx, rsp ; stack is second parameter
|
||||
add rdx, 40 ; correct our own area
|
||||
mov rax, ffi_closure_SYSV
|
||||
call rax ; call the real closure function
|
||||
;; Here, code is missing that handles float return values
|
||||
add rsp, 40
|
||||
movd xmm0, rax ; In case the closure returned a float.
|
||||
ret 0
|
||||
ffi_closure_OUTER ENDP
|
||||
|
||||
|
||||
;;; ffi_call_AMD64
|
||||
|
||||
stack$ = 0
|
||||
prepfunc$ = 32
|
||||
ecif$ = 40
|
||||
bytes$ = 48
|
||||
flags$ = 56
|
||||
rvalue$ = 64
|
||||
fn$ = 72
|
||||
|
||||
ffi_call_AMD64 PROC FRAME
|
||||
|
||||
mov QWORD PTR [rsp+32], r9
|
||||
mov QWORD PTR [rsp+24], r8
|
||||
mov QWORD PTR [rsp+16], rdx
|
||||
mov QWORD PTR [rsp+8], rcx
|
||||
.PUSHREG rbp
|
||||
push rbp
|
||||
.ALLOCSTACK 48
|
||||
sub rsp, 48 ; 00000030H
|
||||
.SETFRAME rbp, 32
|
||||
lea rbp, QWORD PTR [rsp+32]
|
||||
.ENDPROLOG
|
||||
|
||||
mov eax, DWORD PTR bytes$[rbp]
|
||||
add rax, 15
|
||||
and rax, -16
|
||||
call __chkstk
|
||||
sub rsp, rax
|
||||
lea rax, QWORD PTR [rsp+32]
|
||||
mov QWORD PTR stack$[rbp], rax
|
||||
|
||||
mov rdx, QWORD PTR ecif$[rbp]
|
||||
mov rcx, QWORD PTR stack$[rbp]
|
||||
call QWORD PTR prepfunc$[rbp]
|
||||
|
||||
mov rsp, QWORD PTR stack$[rbp]
|
||||
|
||||
movlpd xmm3, QWORD PTR [rsp+24]
|
||||
movd r9, xmm3
|
||||
|
||||
movlpd xmm2, QWORD PTR [rsp+16]
|
||||
movd r8, xmm2
|
||||
|
||||
movlpd xmm1, QWORD PTR [rsp+8]
|
||||
movd rdx, xmm1
|
||||
|
||||
movlpd xmm0, QWORD PTR [rsp]
|
||||
movd rcx, xmm0
|
||||
|
||||
call QWORD PTR fn$[rbp]
|
||||
ret_int$:
|
||||
cmp DWORD PTR flags$[rbp], 1 ; FFI_TYPE_INT
|
||||
jne ret_float$
|
||||
|
||||
mov rcx, QWORD PTR rvalue$[rbp]
|
||||
mov DWORD PTR [rcx], eax
|
||||
jmp SHORT ret_nothing$
|
||||
|
||||
ret_float$:
|
||||
cmp DWORD PTR flags$[rbp], 2 ; FFI_TYPE_FLOAT
|
||||
jne SHORT ret_double$
|
||||
|
||||
mov rax, QWORD PTR rvalue$[rbp]
|
||||
movlpd QWORD PTR [rax], xmm0
|
||||
jmp SHORT ret_nothing$
|
||||
|
||||
ret_double$:
|
||||
cmp DWORD PTR flags$[rbp], 3 ; FFI_TYPE_DOUBLE
|
||||
jne SHORT ret_int64$
|
||||
|
||||
mov rax, QWORD PTR rvalue$[rbp]
|
||||
movlpd QWORD PTR [rax], xmm0
|
||||
jmp SHORT ret_nothing$
|
||||
|
||||
ret_int64$:
|
||||
cmp DWORD PTR flags$[rbp], 12 ; FFI_TYPE_SINT64
|
||||
jne ret_nothing$
|
||||
|
||||
mov rcx, QWORD PTR rvalue$[rbp]
|
||||
mov QWORD PTR [rcx], rax
|
||||
jmp SHORT ret_nothing$
|
||||
|
||||
ret_nothing$:
|
||||
xor eax, eax
|
||||
|
||||
lea rsp, QWORD PTR [rbp+16]
|
||||
pop rbp
|
||||
ret 0
|
||||
ffi_call_AMD64 ENDP
|
||||
_TEXT ENDS
|
||||
END
|
||||
|
|
@ -19,7 +19,7 @@ when defined(Windows):
|
|||
type
|
||||
my_bool* = bool
|
||||
Pmy_bool* = ptr my_bool
|
||||
PVIO* = Pointer
|
||||
PVIO* = pointer
|
||||
Pgptr* = ptr gptr
|
||||
gptr* = cstring
|
||||
Pmy_socket* = ptr my_socket
|
||||
|
|
@ -645,7 +645,7 @@ type
|
|||
next_slave*: Pst_mysql
|
||||
last_used_slave*: Pst_mysql # needed for round-robin slave pick
|
||||
last_used_con*: Pst_mysql # needed for send/read/store/use result to work correctly with replication
|
||||
stmts*: Pointer # was PList, list of all statements
|
||||
stmts*: pointer # was PList, list of all statements
|
||||
methods*: Pst_mysql_methods
|
||||
thd*: pointer # Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag
|
||||
# from mysql_stmt_close if close had to cancel result set of this object.
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ type
|
|||
# remain compatible.
|
||||
|
||||
type
|
||||
Textra*{.pure, final.} = object
|
||||
TExtra*{.pure, final.} = object
|
||||
flags*: int ## Bits for which fields are set
|
||||
study_data*: pointer ## Opaque data from pcre_study()
|
||||
match_limit*: int ## Maximum number of calls to match()
|
||||
|
|
@ -260,7 +260,7 @@ type
|
|||
# without modification.
|
||||
|
||||
type
|
||||
Tcallout_block*{.pure, final.} = object
|
||||
TCalloutBlock*{.pure, final.} = object
|
||||
version*: cint ## Identifies version of block
|
||||
callout_number*: cint ## Number compiled into pattern
|
||||
offset_vector*: ptr cint ## The offset vector
|
||||
|
|
@ -284,7 +284,7 @@ type
|
|||
# User defined callback which provides a stack just before the match starts.
|
||||
|
||||
type
|
||||
Tjit_callback* = proc(p: pointer): ptr Tjit_stack{.cdecl.}
|
||||
TJitCallback* = proc(p: pointer): ptr Tjit_stack{.cdecl.}
|
||||
|
||||
# Exported PCRE functions
|
||||
|
||||
|
|
@ -303,18 +303,18 @@ proc copy_substring*(a2: cstring, a3: ptr cint, a4: cint, a5: cint,
|
|||
a6: cstring,
|
||||
a7: cint): cint{.cdecl, importc: "pcre_copy_substring",
|
||||
pcreImport.}
|
||||
proc dfa_exec*(a2: ptr TPcre, a3: ptr Textra, a4: cstring, a5: cint,
|
||||
proc dfa_exec*(a2: ptr TPcre, a3: ptr TExtra, a4: cstring, a5: cint,
|
||||
a6: cint, a7: cint, a8: ptr cint, a9: cint, a10: ptr cint,
|
||||
a11: cint): cint{.cdecl, importc: "pcre_dfa_exec",
|
||||
pcreImport.}
|
||||
proc exec*(a2: ptr TPcre, a3: ptr Textra, a4: cstring, a5: cint, a6: cint,
|
||||
proc exec*(a2: ptr TPcre, a3: ptr TExtra, a4: cstring, a5: cint, a6: cint,
|
||||
a7: cint, a8: ptr cint, a9: cint): cint {.
|
||||
cdecl, importc: "pcre_exec", pcreImport.}
|
||||
proc free_substring*(a2: cstring){.cdecl, importc: "pcre_free_substring",
|
||||
pcreImport.}
|
||||
proc free_substring_list*(a2: cstringArray){.cdecl,
|
||||
importc: "pcre_free_substring_list", pcreImport.}
|
||||
proc fullinfo*(a2: ptr TPcre, a3: ptr Textra, a4: cint, a5: pointer): cint{.
|
||||
proc fullinfo*(a2: ptr TPcre, a3: ptr TExtra, a4: cint, a5: pointer): cint{.
|
||||
cdecl, importc: "pcre_fullinfo", pcreImport.}
|
||||
proc get_named_substring*(a2: ptr TPcre, a3: cstring, a4: ptr cint, a5: cint,
|
||||
a6: cstring, a7: cstringArray): cint{.cdecl,
|
||||
|
|
@ -334,13 +334,13 @@ proc maketables*(): ptr char{.cdecl, importc: "pcre_maketables",
|
|||
pcreImport.}
|
||||
proc refcount*(a2: ptr TPcre, a3: cint): cint{.cdecl, importc: "pcre_refcount",
|
||||
pcreImport.}
|
||||
proc study*(a2: ptr TPcre, a3: cint, a4: var cstring): ptr Textra{.cdecl,
|
||||
proc study*(a2: ptr TPcre, a3: cint, a4: var cstring): ptr TExtra{.cdecl,
|
||||
importc: "pcre_study", pcreImport.}
|
||||
proc version*(): cstring{.cdecl, importc: "pcre_version", pcreImport.}
|
||||
|
||||
# Utility functions for byte order swaps.
|
||||
|
||||
proc pattern_to_host_byte_order*(a2: ptr TPcre, a3: ptr Textra,
|
||||
proc pattern_to_host_byte_order*(a2: ptr TPcre, a3: ptr TExtra,
|
||||
a4: ptr char): cint{.cdecl, importc: "pcre_pattern_to_host_byte_order",
|
||||
pcreImport.}
|
||||
|
||||
|
|
@ -350,7 +350,7 @@ proc jit_stack_alloc*(a2: cint, a3: cint): ptr Tjit_stack{.cdecl,
|
|||
importc: "pcre_jit_stack_alloc", pcreImport.}
|
||||
proc jit_stack_free*(a2: ptr Tjit_stack){.cdecl, importc: "pcre_jit_stack_free",
|
||||
pcreImport.}
|
||||
proc assign_jit_stack*(a2: ptr Textra, a3: Tjit_callback, a4: pointer){.cdecl,
|
||||
proc assign_jit_stack*(a2: ptr TExtra, a3: TJitCallback, a4: pointer){.cdecl,
|
||||
importc: "pcre_assign_jit_stack", pcreImport.}
|
||||
|
||||
var
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue