summary refs log tree commit diff stats
path: root/rod/c2nim
diff options
context:
space:
mode:
authorAndreas Rumpf <andreas@andreas-laptop>2010-07-23 03:10:00 +0200
committerAndreas Rumpf <andreas@andreas-laptop>2010-07-23 03:10:00 +0200
commitc71011901537079fa0ef8703bb2dd790fba37658 (patch)
tree52efdaa2eb56f32d13226ce917166796a467229f /rod/c2nim
parent704663738ada74976130fc999e2912fbe7962220 (diff)
downloadNim-c71011901537079fa0ef8703bb2dd790fba37658.tar.gz
c2nim: cast-bug fixes (sort of)
Diffstat (limited to 'rod/c2nim')
-rwxr-xr-xrod/c2nim/cparse.nim252
-rw-r--r--rod/c2nim/tests/systest.c9
2 files changed, 149 insertions, 112 deletions
diff --git a/rod/c2nim/cparse.nim b/rod/c2nim/cparse.nim
index 668b68c0b..1a0215735 100755
--- a/rod/c2nim/cparse.nim
+++ b/rod/c2nim/cparse.nim
@@ -12,8 +12,6 @@
 ## used to convert the AST to its text representation.
 
 # XXX standalone structs and unions!
-# XXX header pragma for struct and union fields!
-# XXX "cast" bug!
 
 import 
   os, llstream, rnimsyn, clex, idents, strutils, pegs, ast, astalgo, msgs,
@@ -314,6 +312,17 @@ proc varIdent(ident: string, p: TParser): PNode =
     addSon(result, pragmas)
     addImportToPragma(pragmas, ident, p)
 
+proc fieldIdent(ident: string, p: TParser): PNode = 
+  result = exportSym(p, mangledIdent(ident, p))
+  if p.scopeCounter > 0: return
+  if p.options.header.len > 0: 
+    var a = result
+    result = newNodeP(nkPragmaExpr, p)
+    var pragmas = newNodeP(nkPragma, p)
+    addSon(result, a)
+    addSon(result, pragmas)
+    addSon(pragmas, newIdentStrLitPair("importc", ident, p))
+
 proc DoImport(ident: string, pragmas: PNode, p: TParser) = 
   if p.options.dynlibSym.len > 0 or p.options.header.len > 0: 
     addImportToPragma(pragmas, ident, p)
@@ -333,20 +342,6 @@ proc skipIdentExport(p: var TParser): PNode =
   expectIdent(p)
   result = exportSym(p, mangledIdent(p.tok.s, p))
   getTok(p, result)
-
-proc addPragmaToIdent(ident: var PNode, pragma: PNode) = 
-  var pragmasNode: PNode
-  if ident.kind != nkPragmaExpr: 
-    pragmasNode = newNodeI(nkPragma, ident.info)
-    var e = newNodeI(nkPragmaExpr, ident.info)
-    addSon(e, ident)
-    addSon(e, pragmasNode)
-    ident = e
-  else: 
-    pragmasNode = ident.sons[1]
-    if pragmasNode.kind != nkPragma: 
-      InternalError(ident.info, "addPragmaToIdent")
-  addSon(pragmasNode, pragma)
   
 # --------------- parser -----------------------------------------------------
 # We use this parsing rule: If it looks like a declaration, it is one. This
@@ -472,7 +467,9 @@ proc parseStructBody(p: var TParser): PNode =
     while true:
       var def = newNodeP(nkIdentDefs, p)
       var t = pointer(p, baseTyp)
-      var i = skipIdentExport(p)
+      expectIdent(p)
+      var i = fieldIdent(p.tok.s, p)
+      getTok(p, i)
       t = parseTypeSuffix(p, t)
       addSon(def, i, t, nil)
       addSon(result, def)
@@ -481,12 +478,16 @@ proc parseStructBody(p: var TParser): PNode =
     eat(p, pxSemicolon, lastSon(result))
   eat(p, pxCurlyRi, result)
 
-proc structPragmas(p: TParser, name: PNode): PNode = 
+proc structPragmas(p: TParser, name: PNode, origName: string): PNode = 
+  assert name.kind == nkIdent
   result = newNodeP(nkPragmaExpr, p)
-  addson(result, name)
+  addson(result, exportSym(p, name))
   var pragmas = newNodep(nkPragma, p)
   addSon(pragmas, newIdentNodeP("pure", p))
   addSon(pragmas, newIdentNodeP("final", p))
+  if p.options.header.len > 0:
+    addSon(pragmas, newIdentStrLitPair("importc", origName, p))
+    addSon(pragmas, newIdentStrLitPair("header", p.options.header, p))
   addSon(result, pragmas)
 
 proc enumPragmas(p: TParser, name: PNode): PNode =
@@ -638,87 +639,93 @@ proc enumFields(p: var TParser): PNode =
     if p.tok.xkind != pxComma: break
     getTok(p, e)
 
-proc parseTypeDef(p: var TParser): PNode =  
-  result = newNodeP(nkTypeSection, p)
-  while p.tok.xkind == pxSymbol and p.tok.s == "typedef":
-    getTok(p, result)
-    inc(p.inTypeDef)
-    expectIdent(p)
-    case p.tok.s
-    of "struct", "union": 
-      getTok(p, result)
-      if p.tok.xkind == pxCurlyLe:
-        var t = parseStruct(p)
+proc parseTypedefStruct(p: var TParser, result: PNode) = 
+  getTok(p, result)
+  if p.tok.xkind == pxCurlyLe:
+    var t = parseStruct(p)
+    var origName = p.tok.s
+    var name = skipIdent(p)
+    addTypeDef(result, structPragmas(p, name, origName), t)
+    parseTrailingDefinedTypes(p, result, name)
+  elif p.tok.xkind == pxSymbol: 
+    # name to be defined or type "struct a", we don't know yet:
+    var origName = p.tok.s
+    var nameOrType = skipIdent(p)
+    case p.tok.xkind 
+    of pxCurlyLe:
+      var t = parseStruct(p)
+      if p.tok.xkind == pxSymbol: 
+        # typedef struct tagABC {} abc, *pabc;
+        # --> abc is a better type name than tagABC!
+        var origName = p.tok.s
         var name = skipIdent(p)
-        addTypeDef(result, structPragmas(p, exportSym(p, name)), t)
+        addTypeDef(result, structPragmas(p, name, origName), t)
         parseTrailingDefinedTypes(p, result, name)
-      elif p.tok.xkind == pxSymbol: 
-        # name to be defined or type "struct a", we don't know yet:
-        var nameOrType = skipIdent(p)
-        case p.tok.xkind 
-        of pxCurlyLe:
-          var t = parseStruct(p)
-          if p.tok.xkind == pxSymbol: 
-            # typedef struct tagABC {} abc, *pabc;
-            # --> abc is a better type name than tagABC!
-            var name = skipIdent(p)
-            addTypeDef(result, structPragmas(p, exportSym(p, name)), t)
-            parseTrailingDefinedTypes(p, result, name)
-          else:
-            addTypeDef(result, structPragmas(p, exportSym(p, nameOrType)), t)
-        of pxSymbol: 
-          # typedef struct a a?
-          if mangleName(p.tok.s, p) == nameOrType.ident.s:
-            # ignore the declaration:
-            getTok(p, nil)
-          else:
-            # typedef struct a b; or typedef struct a b[45];
-            otherTypeDef(p, result, nameOrType)
-        else: 
-          otherTypeDef(p, result, nameOrType)
       else:
-        expectIdent(p)
-    of "enum": 
+        addTypeDef(result, structPragmas(p, nameOrType, origName), t)
+    of pxSymbol: 
+      # typedef struct a a?
+      if mangleName(p.tok.s, p) == nameOrType.ident.s:
+        # ignore the declaration:
+        getTok(p, nil)
+      else:
+        # typedef struct a b; or typedef struct a b[45];
+        otherTypeDef(p, result, nameOrType)
+    else: 
+      otherTypeDef(p, result, nameOrType)
+  else:
+    expectIdent(p)
+
+proc parseTypedefEnum(p: var TParser, result: PNode) = 
+  getTok(p, result)
+  if p.tok.xkind == pxCurlyLe:
+    getTok(p, result)
+    var t = enumFields(p)
+    eat(p, pxCurlyRi, t)
+    var name = skipIdent(p)
+    addTypeDef(result, enumPragmas(p, exportSym(p, name)), t)
+    parseTrailingDefinedTypes(p, result, name)
+  elif p.tok.xkind == pxSymbol: 
+    # name to be defined or type "enum a", we don't know yet:
+    var nameOrType = skipIdent(p)
+    case p.tok.xkind 
+    of pxCurlyLe:
       getTok(p, result)
-      if p.tok.xkind == pxCurlyLe:
-        getTok(p, result)
-        var t = enumFields(p)
-        eat(p, pxCurlyRi, t)
+      var t = enumFields(p)
+      eat(p, pxCurlyRi, t)
+      if p.tok.xkind == pxSymbol: 
+        # typedef enum tagABC {} abc, *pabc;
+        # --> abc is a better type name than tagABC!
         var name = skipIdent(p)
         addTypeDef(result, enumPragmas(p, exportSym(p, name)), t)
         parseTrailingDefinedTypes(p, result, name)
-      elif p.tok.xkind == pxSymbol: 
-        # name to be defined or type "enum a", we don't know yet:
-        var nameOrType = skipIdent(p)
-        case p.tok.xkind 
-        of pxCurlyLe:
-          getTok(p, result)
-          var t = enumFields(p)
-          eat(p, pxCurlyRi, t)
-          if p.tok.xkind == pxSymbol: 
-            # typedef enum tagABC {} abc, *pabc;
-            # --> abc is a better type name than tagABC!
-            var name = skipIdent(p)
-            addTypeDef(result, enumPragmas(p, exportSym(p, name)), t)
-            parseTrailingDefinedTypes(p, result, name)
-          else:
-            addTypeDef(result, enumPragmas(p, exportSym(p, nameOrType)), t)
-        of pxSymbol: 
-          # typedef enum a a?
-          if mangleName(p.tok.s, p) == nameOrType.ident.s:
-            # ignore the declaration:
-            getTok(p, nil)
-          else:
-            # typedef enum a b; or typedef enum a b[45];
-            otherTypeDef(p, result, nameOrType)
-        else: 
-          otherTypeDef(p, result, nameOrType)
       else:
-        expectIdent(p)
+        addTypeDef(result, enumPragmas(p, exportSym(p, nameOrType)), t)
+    of pxSymbol: 
+      # typedef enum a a?
+      if mangleName(p.tok.s, p) == nameOrType.ident.s:
+        # ignore the declaration:
+        getTok(p, nil)
+      else:
+        # typedef enum a b; or typedef enum a b[45];
+        otherTypeDef(p, result, nameOrType)
+    else: 
+      otherTypeDef(p, result, nameOrType)
+  else:
+    expectIdent(p)
+
+proc parseTypeDef(p: var TParser): PNode =  
+  result = newNodeP(nkTypeSection, p)
+  while p.tok.xkind == pxSymbol and p.tok.s == "typedef":
+    getTok(p, result)
+    inc(p.inTypeDef)
+    expectIdent(p)
+    case p.tok.s
+    of "struct", "union": parseTypedefStruct(p, result)
+    of "enum": parseTypedefEnum(p, result)
     else: 
       var t = typeAtom(p)
       otherTypeDef(p, result, t)
-    
     eat(p, pxSemicolon)
     dec(p.inTypeDef)
     
@@ -874,6 +881,50 @@ proc setBaseFlags(n: PNode, base: TNumericalBase) =
   of base2: incl(n.flags, nfBase2)
   of base8: incl(n.flags, nfBase8)
   of base16: incl(n.flags, nfBase16)
+
+proc unaryExpression(p: var TParser): PNode
+
+proc isDefinitelyAType(p: var TParser): bool = 
+  var starFound = false
+  var words = 0
+  while true:
+    case p.tok.xkind 
+    of pxSymbol:
+      if declKeyword(p.tok.s): return true
+      elif starFound: return false
+      else: inc(words)
+    of pxStar:
+      starFound = true
+    of pxParRi: return words == 0 or words > 1 or starFound
+    else: return false
+    getTok(p, nil)
+
+proc castExpression(p: var TParser): PNode = 
+  if p.tok.xkind == pxParLe: 
+    SafeContext(p)
+    result = newNodeP(nkCast, p)
+    getTok(p, result)
+    var t = isDefinitelyAType(p)
+    backtrackContext(p)
+    if t:
+      eat(p, pxParLe, result)
+      var a = typeDesc(p)
+      eat(p, pxParRi, result)
+      addSon(result, a)
+      addSon(result, castExpression(p))
+    else: 
+      # else it is just an expression in ():
+      result = newNodeP(nkPar, p)
+      eat(p, pxParLe, result)
+      addSon(result, expression(p))
+      if p.tok.xkind != pxParRi:  
+        # ugh, it is a cast, even though it does not look like one:
+        result.kind = nkCast
+        addSon(result, castExpression(p))
+      eat(p, pxParRi, result)
+      #result = unaryExpression(p)
+  else:
+    result = unaryExpression(p)
   
 proc primaryExpression(p: var TParser): PNode = 
   case p.tok.xkind
@@ -906,31 +957,10 @@ proc primaryExpression(p: var TParser): PNode =
     result = newIntNodeP(nkCharLit, ord(p.tok.s[0]), p)
     getTok(p, result)
   of pxParLe:
-    result = newNodeP(nkPar, p)
-    getTok(p, result)
-    addSon(result, expression(p))
-    eat(p, pxParRi, result)
+    result = castExpression(p)
   else:
     result = nil
 
-proc unaryExpression(p: var TParser): PNode
-proc castExpression(p: var TParser): PNode = 
-  if p.tok.xkind == pxParLe: 
-    SafeContext(p)
-    result = newNodeP(nkCast, p)
-    getTok(p, result)
-    var a = typeDesc(p)
-    if a != nil and p.tok.xkind == pxParRi: 
-      closeContext(p)
-      eat(p, pxParRi, result)
-      addSon(result, a)
-      addSon(result, castExpression(p))
-    else: 
-      backtrackContext(p)
-      result = unaryExpression(p)
-  else:
-    result = unaryExpression(p)
-
 proc multiplicativeExpression(p: var TParser): PNode = 
   result = castExpression(p)
   while true:
diff --git a/rod/c2nim/tests/systest.c b/rod/c2nim/tests/systest.c
index f6ccaeb0f..2d195ec0f 100644
--- a/rod/c2nim/tests/systest.c
+++ b/rod/c2nim/tests/systest.c
@@ -11,6 +11,11 @@ extern "C" {
 
 // Test C2NIM skipping:
 
+#define MASK(x) ((x) & 0xff)
+#define CAST1(x) ((int) &x)
+#define CAST2(x) (typ*) &x
+#define CAST3(x) ((const unsigned char**) &x)
+
 #ifndef C2NIM 
   #if someNestedCond
     This is an invalid text that should generate a parser error, if not 
@@ -53,10 +58,12 @@ point* newPoint(void) {
     --p;
   } else if (**p == '\t') {
     p += 3;
-  } else {
+  } else { 
     p = 45 + (mytype*)45;
     p = 45 + ((mytype*)45);
     p = 45 + ((mytype)45);
+    // BUG: This does not parse:
+    // p = 45 + (mytype)45;
   }
 
   while (x >= 6 && x <= 20)