summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-07-16 18:34:18 +0200
committerAraq <rumpf_a@web.de>2011-07-16 18:34:18 +0200
commit42e6130b2c37345963c0b5469e12a287b88bf3eb (patch)
tree98a957645b04b43ddf86a7c499a8fc7d9cad69aa
parentfe5df368c18c79ee76fb63cb64121e1f9c3946bc (diff)
downloadNim-42e6130b2c37345963c0b5469e12a287b88bf3eb.tar.gz
first steps to explicit channels for thread communication; added mainThreadId
-rwxr-xr-xcompiler/lexer.nim10
-rwxr-xr-xcompiler/nversion.nim2
-rwxr-xr-xcompiler/semcall.nim30
-rwxr-xr-xcompiler/seminst.nim2
-rwxr-xr-xcompiler/semstmts.nim38
-rwxr-xr-xdoc/endb.txt12
-rwxr-xr-xdoc/manual.txt2
-rwxr-xr-xdoc/tut2.txt2
-rwxr-xr-xlib/pure/ropes.nim10
-rwxr-xr-xlib/system.nim7
-rwxr-xr-xlib/system/inboxes.nim59
-rwxr-xr-xlib/system/mmdisp.nim20
-rwxr-xr-xlib/system/threads.nim12
-rwxr-xr-xtests/threads/threadex.nim8
-rwxr-xr-xtodo.txt8
-rwxr-xr-xweb/news.txt4
16 files changed, 155 insertions, 71 deletions
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index b2932033d..2174a696f 100755
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -267,7 +267,7 @@ proc GetNumber(L: var TLexer): TToken =
         inc(L.bufpos)
       matchUnderscoreChars(L, result, {'0'..'9'})
   endpos = L.bufpos
-  if L.buf[endpos] == '\'': 
+  if L.buf[endpos] == '\'':
     #matchUnderscoreChars(L, result, ['''', 'f', 'F', 'i', 'I', '0'..'9']);
     inc(endpos)
     L.bufpos = pos            # restore position
@@ -281,7 +281,7 @@ proc GetNumber(L: var TLexer): TToken =
         result.tokType = tkFloat32Lit
         inc(endpos, 2)
       else: 
-        lexMessage(L, errInvalidNumber, result.literal)
+        lexMessage(L, errInvalidNumber, result.literal & "'f" & L.buf[endpos])
     of 'i', 'I': 
       inc(endpos)
       if (L.buf[endpos] == '6') and (L.buf[endpos + 1] == '4'): 
@@ -297,9 +297,9 @@ proc GetNumber(L: var TLexer): TToken =
         result.tokType = tkInt8Lit
         inc(endpos)
       else: 
-        lexMessage(L, errInvalidNumber, result.literal)
-    else: lexMessage(L, errInvalidNumber, result.literal)
-  else: 
+        lexMessage(L, errInvalidNumber, result.literal & "'i" & L.buf[endpos])
+    else: lexMessage(L, errInvalidNumber, result.literal & "'" & L.buf[endpos])
+  else:
     L.bufpos = pos            # restore position
   try: 
     if (L.buf[pos] == '0') and
diff --git a/compiler/nversion.nim b/compiler/nversion.nim
index 45b804d40..0c0630dfd 100755
--- a/compiler/nversion.nim
+++ b/compiler/nversion.nim
@@ -15,6 +15,6 @@ const
   defaultAsmMarkerSymbol* = '!'
   VersionMajor* = 0
   VersionMinor* = 8
-  VersionPatch* = 12
+  VersionPatch* = 13
   VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
 
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 294c0399b..cf277728d 100755
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -83,6 +83,13 @@ proc explicitGenericInstError(n: PNode): PNode =
   LocalError(n.info, errCannotInstantiateX, renderTree(n))
   result = n
 
+proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
+  var x: TCandidate
+  initCandidate(x, s, n)
+  var newInst = generateInstance(c, s, x.bindings, n.info)
+  markUsed(n, s)
+  result = newSymNode(newInst, n.info)
+
 proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = 
   assert n.kind == nkBracketExpr
   for i in 1..sonsLen(n)-1:
@@ -94,27 +101,30 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
     # number of generic type parameters:
     if safeLen(s.ast.sons[genericParamsPos]) != n.len-1:
       return explicitGenericInstError(n)
+    result = explicitGenericSym(c, n, s)
   elif a.kind == nkSymChoice:
     # choose the generic proc with the proper number of type parameters.
     # XXX I think this could be improved by reusing sigmatch.ParamTypesMatch.
     # It's good enough for now.
-    var candidateCount = 0
+    result = newNodeI(nkSymChoice, n.info)
     for i in countup(0, len(a)-1): 
       var candidate = a.sons[i].sym
       if candidate.kind in {skProc, skMethod, skConverter, skIterator}: 
         # if suffices that the candidate has the proper number of generic 
         # type parameters:
         if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
-          s = candidate
-          inc(candidateCount)
-    if candidateCount != 1: return explicitGenericInstError(n)
+          result.add(explicitGenericSym(c, n, candidate))
+    # get rid of nkSymChoice if not ambigious:
+    if result.len == 1: result = result[0]
+    # candidateCount != 1: return explicitGenericInstError(n)
   else:
     assert false
   
-  var x: TCandidate
-  initCandidate(x, s, n)
-  var newInst = generateInstance(c, s, x.bindings, n.info)
-  
-  markUsed(n, s)
-  result = newSymNode(newInst, n.info)
+  when false:
+    var x: TCandidate
+    initCandidate(x, s, n)
+    var newInst = generateInstance(c, s, x.bindings, n.info)
+    
+    markUsed(n, s)
+    result = newSymNode(newInst, n.info)
 
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 2db8289f2..3d0b672bc 100755
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -25,7 +25,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
     if t == nil: 
       LocalError(a.info, errCannotInstantiateX, s.name.s)
       break
-    if (t.kind == tyGenericParam): 
+    if t.kind == tyGenericParam: 
       InternalError(a.info, "instantiateGenericParamList: " & q.name.s)
     s.typ = t
     addDecl(c, s)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 61709ad48..a341ce64d 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -152,42 +152,32 @@ proc semCase(c: PContext, n: PNode): PNode =
   closeScope(c.tab)
 
 proc SemReturn(c: PContext, n: PNode): PNode = 
-  var 
-    restype: PType
-    a: PNode                  # temporary assignment for code generator
   result = n
   checkSonsLen(n, 1)
-  if not (c.p.owner.kind in {skConverter, skMethod, skProc, skMacro}): 
+  if c.p.owner.kind notin {skConverter, skMethod, skProc, skMacro}:
     globalError(n.info, errXNotAllowedHere, "\'return\'")
-  if n.sons[0].kind != nkEmpty: 
-    n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
-    restype = c.p.owner.typ.sons[0]
-    if restype != nil: 
-      a = newNodeI(nkAsgn, n.sons[0].info)
-      n.sons[0] = fitNode(c, restype, n.sons[0])
-      # optimize away ``return result``, because it would be transformed
-      # to ``result = result; return``:
-      if (n.sons[0].kind == nkSym) and (sfResult in n.sons[0].sym.flags): 
-        n.sons[0] = ast.emptyNode
-      else: 
-        if (c.p.resultSym == nil): InternalError(n.info, "semReturn")
-        addSon(a, semExprWithType(c, newSymNode(c.p.resultSym)))
-        addSon(a, n.sons[0])
-        n.sons[0] = a
-    else: 
-      localError(n.info, errCannotReturnExpr)
+  if n.sons[0].kind != nkEmpty:
+    # transform ``return expr`` to ``result = expr; return``
+    if c.p.resultSym == nil: InternalError(n.info, "semReturn")
+    var a = newNodeI(nkAsgn, n.sons[0].info)
+    addSon(a, newSymNode(c.p.resultSym))
+    addSon(a, n.sons[0])
+    n.sons[0] = semAsgn(c, a)
+    # optimize away ``result = result``:
+    if n[0][1].kind == nkSym and sfResult in n[0][1].sym.flags: 
+      n.sons[0] = ast.emptyNode
   
 proc SemYield(c: PContext, n: PNode): PNode = 
   result = n
   checkSonsLen(n, 1)
-  if (c.p.owner == nil) or (c.p.owner.kind != skIterator): 
+  if c.p.owner == nil or c.p.owner.kind != skIterator: 
     GlobalError(n.info, errYieldNotAllowedHere)
-  if n.sons[0].kind != nkEmpty: 
+  if n.sons[0].kind != nkEmpty:
     n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
     var restype = c.p.owner.typ.sons[0]
     if restype != nil: 
       n.sons[0] = fitNode(c, restype, n.sons[0])
-      if (n.sons[0].typ == nil): InternalError(n.info, "semYield")
+      if n.sons[0].typ == nil: InternalError(n.info, "semYield")
     else: 
       localError(n.info, errCannotReturnExpr)
   
diff --git a/doc/endb.txt b/doc/endb.txt
index 3cc20cdb8..853af8cad 100755
--- a/doc/endb.txt
+++ b/doc/endb.txt
@@ -6,10 +6,10 @@
 :Version: |nimrodversion|

 

 .. contents::

-
-
-**Note:** ENDB has not been maintained/tested since several versions. Help if
-you want this debugger to survive.
+

+

+**Note:** ENDB has not been maintained/tested since several versions. Help if

+you want this debugger to survive.

 

 Nimrod comes with a platform independant debugger -

 the `Embedded Nimrod Debugger`:idx: (`ENDB`:idx:). The debugger is

@@ -57,7 +57,7 @@ Executing Commands
     Continue execution until the next breakpoint.

 

 ``i``, ``ignore``

-    Continue execution, ignore all breakpoints. This is effectively quitting

+    Continue execution, ignore all breakpoints. This effectively quits

     the debugger and runs the program until it finishes.

 

 

@@ -143,7 +143,7 @@ Data Display Commands
     painfully slow, the debugger uses a *maximal display depth* concept for

     displaying.

 

-    You can alter the *maximal display depth* with the ``maxdisplay``

+    You can alter the maximal display depth with the ``maxdisplay``

     command.

 

 ``maxdisplay`` <natural>

diff --git a/doc/manual.txt b/doc/manual.txt
index cf813c664..f12ed7f0c 100755
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -3153,7 +3153,7 @@ over *fine grained* concurrency.
 Threads and exceptions

 ----------------------

 

-The interaction between threads and exception is simple: A *handled* exception 

+The interaction between threads and exceptions is simple: A *handled* exception 

 in one thread cannot affect any other thread. However, an *unhandled* 

 exception in one thread terminates the whole *process*!

 

diff --git a/doc/tut2.txt b/doc/tut2.txt
index bd9769af3..ac9fd1282 100755
--- a/doc/tut2.txt
+++ b/doc/tut2.txt
@@ -200,7 +200,7 @@ for any type:
   echo("abc".len) # is the same as echo(len("abc"))
   echo("abc".toUpper())
   echo({'a', 'b', 'c'}.card)
-  stdout.writeln("Hallo") # the same as write(stdout, "Hallo")
+  stdout.writeln("Hallo") # the same as writeln(stdout, "Hallo")
 
 (Another way to look at the method call syntax is that it provides the missing
 postfix notation.)
diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim
index 69737576f..4a6c3f530 100755
--- a/lib/pure/ropes.nim
+++ b/lib/pure/ropes.nim
@@ -145,17 +145,17 @@ proc rope*(i: BiggestInt): PRope {.rtl, extern: "nro$1BiggestInt".} =
 proc rope*(f: BiggestFloat): PRope {.rtl, extern: "nro$1BiggestFloat".} =
   ## Converts a float to a rope. 
   result = rope($f)
-
-proc disableCache*() {.rtl, extern: "nro$1".} =
-  ## the cache is discarded and disabled. The GC will reuse its used memory.
-  cache = nil
-  cacheEnabled = false
   
 proc enableCache*() {.rtl, extern: "nro$1".} =
   ## Enables the caching of leaves. This reduces the memory footprint at
   ## the cost of runtime efficiency.
   cacheEnabled = true
 
+proc disableCache*() {.rtl, extern: "nro$1".} =
+  ## the cache is discarded and disabled. The GC will reuse its used memory.
+  cache = nil
+  cacheEnabled = false
+
 proc `&`*(a, b: PRope): PRope {.rtl, extern: "nroConcRopeRope".} =
   ## the concatenation operator for ropes.
   if a == nil: 
diff --git a/lib/system.nim b/lib/system.nim
index b6a119ddd..a8f8ba09b 100755
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -783,7 +783,7 @@ const
   hasThreadSupport = compileOption("threads")
   hasSharedHeap = defined(boehmgc) # don't share heaps; every thread has its own
 
-when hasThreadSupport and not hasSharedHeap:
+when hasThreadSupport:
   {.pragma: rtlThreadVar, threadvar.}
 else:
   {.pragma: rtlThreadVar.}
@@ -835,7 +835,7 @@ proc insert*[T](x: var seq[T], item: T, i = 0) {.noSideEffect.} =
   setLen(x, xl+1)
   var j = xl-1
   while j >= i:
-    x[j+1] = x[j]
+    shallowCopy(x[j+1], x[j])
     dec(j)
   x[i] = item
 
@@ -1411,7 +1411,8 @@ var
     ## writes an error message and terminates the program. `outOfMemHook` can
     ## be used to raise an exception in case of OOM like so:
     ## 
-    ## code-block:: nimrod
+    ## .. code-block:: nimrod
+    ##
     ##   var gOutOfMem: ref EOutOfMemory
     ##   new(gOutOfMem) # need to be allocated *before* OOM really happened!
     ##   gOutOfMem.msg = "out of memory"
diff --git a/lib/system/inboxes.nim b/lib/system/inboxes.nim
index 7b522c7ae..b2db103cb 100755
--- a/lib/system/inboxes.nim
+++ b/lib/system/inboxes.nim
@@ -205,9 +205,8 @@ proc send*[TMsg](receiver: TThreadId[TMsg], msg: TMsg) =
   var q = cast[PInbox](getInBoxMem(receiver[]))

   sendImpl(q)

 

-proc llRecv(res: pointer, typ: PNimType) =

+proc llRecv(q: PInbox, res: pointer, typ: PNimType) =

   # to save space, the generic is as small as possible

-  var q = cast[PInbox](getInBoxMem())

   acquireSys(q.lock)

   q.ready = true

   while q.count <= 0:

@@ -222,7 +221,8 @@ proc llRecv(res: pointer, typ: PNimType) =
 proc recv*[TMsg](): TMsg =

   ## receives a message from its internal message queue. This blocks until

   ## a message has arrived! You may use ``peek`` to avoid the blocking.

-  llRecv(addr(result), cast[PNimType](getTypeInfo(result)))

+  var q = cast[PInbox](getInBoxMem())

+  llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))

 

 proc peek*(): int =

   ## returns the current number of messages in the inbox.

@@ -242,3 +242,56 @@ proc ready*[TMsg](t: var TThread[TMsg]): bool =
   var q = cast[PInbox](getInBoxMem(t))

   result = q.ready

 

+# ---------------------- channel support -------------------------------------

+

+type

+  TChannel*[TMsg] = TInbox ## a channel for thread communication

+  TChannelId*[TMsg] = ptr TChannel[TMsg] ## the current implementation uses

+                                         ## a pointer as a channel ID.

+

+proc open*[TMsg](c: var TChannel[TMsg]) =

+  ## opens a channel `c` for inter thread communication.

+  initInbox(addr(c))

+

+proc close*[TMsg](c: var TChannel[TMsg]) =

+  ## closes a channel `c` and frees its associated resources.

+  freeInbox(addr(c))

+

+proc channelId*[TMsg](c: var TChannel[TMsg]): TChannelId[TMsg] {.inline.} =

+  ## returns the channel ID of `c`.

+  result = addr(c)

+  

+proc send*[TMsg](c: var TChannel[TMsg], msg: TMsg) =

+  ## sends a message to a channel. `msg` is deeply copied.

+  var q = cast[PInbox](addr(c))

+  sendImpl(q)

+

+proc send*[TMsg](c: TChannelId[TMsg], msg: TMsg) =

+  ## sends a message to a thread. `msg` is deeply copied.

+  var q = cast[PInbox](c)

+  sendImpl(q)

+

+proc peek*[TMsg](c: var TChannel[TMsg]): int =

+  ## returns the current number of messages in the channel `c`.

+  var q = cast[PInbox](addr(c))

+  lockInbox(q):

+    result = q.count

+

+proc peek*[TMsg](c: TChannelId[TMsg]): int =

+  ## returns the current number of messages in the channel `c`.

+  var q = cast[PInbox](c)

+  lockInbox(q):

+    result = q.count

+

+proc recv*[TMsg](c: TChannelId[TMsg]): TMsg =

+  ## receives a message from the channel `c`. This blocks until

+  ## a message has arrived! You may use ``peek`` to avoid the blocking.

+  var q = cast[PInbox](c)

+  llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))

+

+proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =

+  ## receives a message from the channel `c`. This blocks until

+  ## a message has arrived! You may use ``peek`` to avoid the blocking.

+  var q = cast[PInbox](addr(c))

+  llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))

+

diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index e5efff615..0cbee1d47 100755
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -133,6 +133,26 @@ when defined(boehmgc):
   proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
 
+  type
+    TMemRegion = object {.final, pure.}
+  
+  var
+    dummy {.rtlThreadVar.}: int
+  
+  proc rawAlloc(r: var TMemRegion, size: int): pointer =
+    result = boehmAlloc(size)
+    if result == nil: raiseOutOfMem()
+  proc rawAlloc0(r: var TMemRegion, size: int): pointer =
+    result = alloc(size)
+    zeroMem(result, size)
+  proc realloc(r: var TMemRegion, p: Pointer, newsize: int): pointer =
+    result = boehmRealloc(p, newsize)
+    if result == nil: raiseOutOfMem()
+  proc rawDealloc(r: var TMemRegion, p: Pointer) = boehmDealloc(p)
+
+  proc deallocOsPages(r: var TMemRegion) {.inline.} = nil
+  proc deallocOsPages() {.inline.} = nil
+
   include "system/cellsets"
 elif defined(nogc):
   # Even though we don't want the GC, we cannot simply use C's memory manager
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index 3e99afcde..823844c55 100755
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -266,7 +266,10 @@ proc initInbox(p: pointer)
 proc freeInbox(p: pointer)
 when not defined(boehmgc) and not hasSharedHeap:
   proc deallocOsPages()
-  
+
+when defined(mainThread):
+  initInbox(addr(mainThread.inbox))
+
 template ThreadProcWrapperBody(closure: expr) =
   ThreadVarSetValue(globalsSlot, closure)
   var t = cast[ptr TThread[TMsg]](closure)
@@ -379,6 +382,10 @@ proc myThreadId*[TMsg](): TThreadId[TMsg] =
   ## returns the thread ID of the thread that calls this proc.
   result = cast[TThreadId[TMsg]](ThreadVarGetValue(globalsSlot))
 
+proc mainThreadId*[TMsg](): TThreadId[TMsg] =
+  ## returns the thread ID of the main thread.
+  result = cast[TThreadId[TMsg]](addr(mainThread))
+
 when useStackMaskHack:
   proc runMain(tp: proc () {.thread.}) {.compilerproc.} =
     var mainThread: TThread[pointer]
@@ -388,7 +395,8 @@ when useStackMaskHack:
 # --------------------------- lock handling ----------------------------------
 
 type
-  TLock* = TSysLock ## Nimrod lock; not re-entrant!
+  TLock* = TSysLock ## Nimrod lock; whether this is re-entrant
+                    ## or not is unspecified!
   
 const
   noDeadlocks = false # compileOption("deadlockPrevention")
diff --git a/tests/threads/threadex.nim b/tests/threads/threadex.nim
index 65056a954..d8b4a94fb 100755
--- a/tests/threads/threadex.nim
+++ b/tests/threads/threadex.nim
@@ -9,7 +9,6 @@ type
 
 var
   consumer: TThread[TMsg]
-  producer: TThread[int]
   printedLines = 0
 
 proc consume() {.thread.} =
@@ -21,7 +20,7 @@ proc consume() {.thread.} =
     echo x.data
     discard atomicInc(printedLines)
 
-proc produce() {.thread.} =
+proc produce() =
   var m: TMsg
   var input = open("readme.txt")
   while not endOfFile(input):
@@ -30,15 +29,14 @@ proc produce() {.thread.} =
       consumer.send(m)
   close(input)
   m.k = mEof
-  m.backTo = myThreadId[int]()
+  m.backTo = mainThreadId[int]()
   consumer.send(m)
   var result = recv[int]()
   echo result
   
 createThread(consumer, consume)
-createThread(producer, produce)
+produce()
 joinThread(consumer)
-joinThread(producer)
 
 echo printedLines
 
diff --git a/todo.txt b/todo.txt
index 5e0ce7b5f..e1d0d8f0e 100755
--- a/todo.txt
+++ b/todo.txt
@@ -31,7 +31,8 @@ version 0.9.XX
 - distinct types for array/seq indexes
 - GC: marker procs for native Nimrod GC and Boehm GC; precise stack marking
 - implicit ref/ptr->var conversion; the compiler may store an object
-  implicitly on the heap for write barrier efficiency
+  implicitly on the heap for write barrier efficiency; better: 
+  proc specialization in the code gen
 - resizing of strings/sequences could take into account the memory that
   is allocated
 - typeAllowed() for parameters...
@@ -50,13 +51,14 @@ version 0.9.XX
 Library
 -------
 
+- proper URL-parser
+- wrappers for poppler; libharu
 - radix tree for strings; maybe suffix tree
 - locale support
 - bignums
 - ftp (and other internet protocols)
 
 - pdcurses bindings
-- queues additional to streams: have two positions (read/write) instead of one
 
 - for system:
   proc `@` [T](a: openArray[T]): seq[T] = 
@@ -70,7 +72,7 @@ Low priority
 ------------
 
 - ``when T is int`` for generic code
-- ``when validCode( proc ()  )`` for generic code
+- ``when validCode(proc())`` for generic code
 - find a way for easy constructors and destructors; (destructors are much more
   important than constructors)
 - code generated for type information is wasteful
diff --git a/web/news.txt b/web/news.txt
index 062b171a1..4d4feb367 100755
--- a/web/news.txt
+++ b/web/news.txt
@@ -22,11 +22,13 @@ Compiler Additions
 Library Additions
 -----------------
 
+- Added ``system.mainThreadId``.
+- Added explicit channels for thread communication.
+
 
 2011-07-10 Version 0.8.12 released
 ==================================
 
-
 Bugfixes
 --------
 
ze_t, size_t, FILE*); /* * File Positioning Functions */ int fseek (FILE*, long, int); long ftell (FILE*); void rewind (FILE*); #ifdef __USE_MINGW_FSEEK /* These are in libmingwex.a */ /* * Workaround for limitations on win9x where a file contents are * not zero'd out if you seek past the end and then write. */ int __mingw_fseek (FILE *, long, int); int __mingw_fwrite (const void*, size_t, size_t, FILE*); #define fseek(fp, offset, whence) __mingw_fseek(fp, offset, whence) #define fwrite(buffer, size, count, fp) __mingw_fwrite(buffer, size, count, fp) #endif /* __USE_MINGW_FSEEK */ /* * An opaque data type used for storing file positions... The contents of * this type are unknown, but we (the compiler) need to know the size * because the programmer using fgetpos and fsetpos will be setting aside * storage for fpos_t structres. Actually I tested using a byte array and * it is fairly evident that the fpos_t type is a long (in CRTDLL.DLL). * Perhaps an unsigned long? TODO? It's definitely a 64-bit number in * MSVCRT however, and for now `long long' will do. */ #ifdef __MSVCRT__ typedef long long fpos_t; #else typedef long fpos_t; #endif int fgetpos (FILE*, fpos_t*); int fsetpos (FILE*, const fpos_t*); /* * Error Functions */ void clearerr (FILE*); int feof (FILE*); int ferror (FILE*); void perror (const char*); #ifndef __STRICT_ANSI__ /* * Pipes */ FILE* _popen (const char*, const char*); int _pclose (FILE*); #ifndef NO_OLDNAMES FILE* popen (const char*, const char*); int pclose (FILE*); #endif /* * Other Non ANSI functions */ int _flushall (void); int _fgetchar (void); int _fputchar (int); FILE* _fdopen (int, const char*); int _fileno (FILE*); #ifndef _NO_OLDNAMES int fgetchar (void); int fputchar (int); FILE* fdopen (int, const char*); int fileno (FILE*); #endif /* Not _NO_OLDNAMES */ #endif /* Not __STRICT_ANSI__ */ /* Wide versions */ #ifndef _WSTDIO_DEFINED /* also in wchar.h - keep in sync */ int fwprintf (FILE*, const wchar_t*, ...); int wprintf (const wchar_t*, ...); int swprintf (wchar_t*, const wchar_t*, ...); int _snwprintf (wchar_t*, size_t, const wchar_t*, ...); int vfwprintf (FILE*, const wchar_t*, va_list); int vwprintf (const wchar_t*, va_list); int vswprintf (wchar_t*, const wchar_t*, va_list); int _vsnwprintf (wchar_t*, size_t, const wchar_t*, va_list); int fwscanf (FILE*, const wchar_t*, ...); int wscanf (const wchar_t*, ...); int swscanf (const wchar_t*, const wchar_t*, ...); wint_t fgetwc (FILE*); wint_t fputwc (wchar_t, FILE*); wint_t ungetwc (wchar_t, FILE*); #ifdef __MSVCRT__ wchar_t* fgetws (wchar_t*, int, FILE*); int fputws (const wchar_t*, FILE*); wint_t getwc (FILE*); wint_t getwchar (void); wchar_t* _getws (wchar_t*); wint_t putwc (wint_t, FILE*); int _putws (const wchar_t*); wint_t putwchar (wint_t); FILE* _wfopen (const wchar_t*, const wchar_t*); FILE* _wfreopen (const wchar_t*, const wchar_t*, FILE*); FILE* _wfsopen (const wchar_t*, const wchar_t*, int); wchar_t* _wtmpnam (wchar_t*); wchar_t* _wtempnam (const wchar_t*, const wchar_t*); int _wrename (const wchar_t*, const wchar_t*); int _wremove (const wchar_t*); void _wperror (const wchar_t*); FILE* _wpopen (const wchar_t*, const wchar_t*); #endif /* __MSVCRT__ */ #ifndef __NO_ISOCEXT /* externs in libmingwex.a */ int snwprintf(wchar_t* s, size_t n, const wchar_t* format, ...); extern inline int vsnwprintf (wchar_t* s, size_t n, const wchar_t* format, va_list arg) { return _vsnwprintf ( s, n, format, arg); } #endif #define _WSTDIO_DEFINED #endif /* _WSTDIO_DEFINED */ #ifndef __STRICT_ANSI__ #ifdef __MSVCRT__ #ifndef NO_OLDNAMES FILE* wpopen (const wchar_t*, const wchar_t*); #endif /* not NO_OLDNAMES */ #endif /* MSVCRT runtime */ /* * Other Non ANSI wide functions */ wint_t _fgetwchar (void); wint_t _fputwchar (wint_t); int _getw (FILE*); int _putw (int, FILE*); #ifndef _NO_OLDNAMES wint_t fgetwchar (void); wint_t fputwchar (wint_t); int getw (FILE*); int putw (int, FILE*); #endif /* Not _NO_OLDNAMES */ #endif /* __STRICT_ANSI */ #ifdef __cplusplus } #endif #endif /* Not RC_INVOKED */ #endif /* _STDIO_H_ */