summary refs log tree commit diff stats
path: root/rod/c2nim
diff options
context:
space:
mode:
authorAndreas Rumpf <andreas@andreas-desktop>2010-08-11 23:13:11 +0200
committerAndreas Rumpf <andreas@andreas-desktop>2010-08-11 23:13:11 +0200
commitafbff2d5040ce219c62fa6b9298ed2a8cfc2406b (patch)
treed853536dd10c18b12aabea3c280a6ecae10e5c7b /rod/c2nim
parent040c57f0a566b257ab7fcca4c6557be4b3c76f24 (diff)
downloadNim-afbff2d5040ce219c62fa6b9298ed2a8cfc2406b.tar.gz
c2nim: new features & bugfixes
Diffstat (limited to 'rod/c2nim')
-rwxr-xr-xrod/c2nim/c2nim.nim4
-rwxr-xr-xrod/c2nim/cparse.nim144
-rwxr-xr-xrod/c2nim/cpp.nim24
-rwxr-xr-xrod/c2nim/manual.txt47
-rwxr-xr-xrod/c2nim/tests/systest.c68
5 files changed, 222 insertions, 65 deletions
diff --git a/rod/c2nim/c2nim.nim b/rod/c2nim/c2nim.nim
index fd1e227df..f1cb05920 100755
--- a/rod/c2nim/c2nim.nim
+++ b/rod/c2nim/c2nim.nim
@@ -12,7 +12,7 @@ import
   clex, cparse
 
 const
-  Version = "0.8.10"
+  Version = NimrodVersion
   Usage = """
 c2nim - C to Nimrod source converter
   (c) 2010 Andreas Rumpf
@@ -29,6 +29,8 @@ Options:
   --suffix:SUFFIX        strip suffix for the generated Nimrod identifiers 
                          (multiple --suffix options are supported)
   --skipinclude          do not convert ``#include`` to ``import``
+  --typeprefixes         generate ``T`` and ``P`` type prefixes
+  --skipcomments         do not copy comments
   -v, --version          write c2nim's version
   -h, --help             show this help
 """
diff --git a/rod/c2nim/cparse.nim b/rod/c2nim/cparse.nim
index 28cad2805..de2355bba 100755
--- a/rod/c2nim/cparse.nim
+++ b/rod/c2nim/cparse.nim
@@ -11,7 +11,7 @@
 ## It translates a C source file into a Nimrod AST. Then the renderer can be
 ## used to convert the AST to its text representation.
 
-## XXX cleanup of declaration handling. Standalone enums.
+# XXX cleanup of declaration handling.
 
 import 
   os, llstream, rnimsyn, clex, idents, strutils, pegs, ast, astalgo, msgs,
@@ -22,7 +22,9 @@ type
     pfRefs,             ## use "ref" instead of "ptr" for C's typ*
     pfCDecl,            ## annotate procs with cdecl
     pfStdCall,          ## annotate procs with stdcall
-    pfSkipInclude       ## skip all ``#include``
+    pfSkipInclude,      ## skip all ``#include``
+    pfTypePrefixes,     ## all generated types start with 'T' or 'P'
+    pfSkipComments      ## do not generate comments
   
   TMacro {.final.} = object
     name: string
@@ -33,8 +35,10 @@ type
     flags: set[TParserFlag]
     prefixes, suffixes: seq[string]
     mangleRules: seq[tuple[pattern: TPeg, frmt: string]]
+    privateRules: seq[TPeg]
     dynlibSym, header: string
     macros: seq[TMacro]
+    toMangle: PStringTable
   PParserOptions* = ref TParserOptions
   
   TParser* {.final.} = object
@@ -53,9 +57,11 @@ proc newParserOptions*(): PParserOptions =
   result.suffixes = @[]
   result.macros = @[]
   result.mangleRules = @[]
+  result.privateRules = @[]
   result.flags = {}
   result.dynlibSym = ""
   result.header = ""
+  result.toMangle = newStringTable()
 
 proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool = 
   result = true
@@ -68,6 +74,8 @@ proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool =
   of "prefix": parserOptions.prefixes.add(val)
   of "suffix": parserOptions.suffixes.add(val)
   of "skipinclude": incl(parserOptions.flags, pfSkipInclude)
+  of "typeprefixes": incl(parserOptions.flags, pfTypePrefixes)
+  of "skipcomments": incl(parserOptions.flags, pfSkipComments)
   else: result = false
 
 proc ParseUnit*(p: var TParser): PNode
@@ -190,8 +198,9 @@ proc parLineInfo(p: TParser): TLineInfo =
 
 proc skipComAux(p: var TParser, n: PNode) =
   if (n != nil): 
-    if n.comment == nil: n.comment = p.tok.s
-    else: add(n.comment, "\n" & p.tok.s)
+    if pfSkipComments notin p.options.flags:
+      if n.comment == nil: n.comment = p.tok.s
+      else: add(n.comment, "\n" & p.tok.s)
   else: 
     parMessage(p, warnCommentXIgnored, p.tok.s)
   getTok(p)
@@ -257,20 +266,31 @@ proc newIdentNodeP(ident: PIdent, p: TParser): PNode =
 proc newIdentNodeP(ident: string, p: TParser): PNode =
   result = newIdentNodeP(getIdent(ident), p)
 
+proc mangleRules(s: string, p: TParser): string = 
+  block mangle:
+    for pattern, frmt in items(p.options.mangleRules):
+      if s.match(pattern):
+        result = s.replace(pattern, frmt)
+        break mangle
+    block prefixes:
+      for prefix in items(p.options.prefixes): 
+        if s.startsWith(prefix): 
+          result = s.copy(prefix.len)
+          break prefixes
+      result = s
+    block suffixes:
+      for suffix in items(p.options.suffixes):
+        if result.endsWith(suffix):
+          setLen(result, result.len - suffix.len)
+          break suffixes
+
 proc mangleName(s: string, p: TParser): string = 
-  for pattern, frmt in items(p.options.mangleRules):
-    if s.match(pattern):
-      return s.replace(pattern, frmt)
-  block prefixes:
-    for prefix in items(p.options.prefixes): 
-      if s.startsWith(prefix): 
-        result = s.copy(prefix.len)
-        break prefixes
-    result = s
-  for suffix in items(p.options.suffixes):
-    if result.endsWith(suffix):
-      setLen(result, result.len - suffix.len)
-      break
+  if p.options.toMangle.hasKey(s): result = p.options.toMangle[s]
+  else: result = mangleRules(s, p)
+
+proc isPrivate(s: string, p: TParser): bool = 
+  for pattern in items(p.options.privateRules): 
+     if s.match(pattern): return true
 
 proc mangledIdent(ident: string, p: TParser): PNode = 
   result = newNodeP(nkIdent, p)
@@ -293,16 +313,16 @@ proc addImportToPragma(pragmas: PNode, ident: string, p: TParser) =
   else:
     addSon(pragmas, newIdentStrLitPair("header", p.options.header, p))
 
-proc exportSym(p: TParser, i: PNode): PNode = 
+proc exportSym(p: TParser, i: PNode, origName: string): PNode = 
   assert i.kind == nkIdent
-  if p.scopeCounter == 0:
+  if p.scopeCounter == 0 and not isPrivate(origName, p):
     result = newNodeI(nkPostfix, i.info)
     addSon(result, newIdentNode(getIdent("*"), i.info), i)
   else:
     result = i
 
 proc varIdent(ident: string, p: TParser): PNode = 
-  result = exportSym(p, mangledIdent(ident, p))
+  result = exportSym(p, mangledIdent(ident, p), ident)
   if p.scopeCounter > 0: return
   if p.options.dynlibSym.len > 0 or p.options.header.len > 0: 
     var a = result
@@ -313,7 +333,7 @@ proc varIdent(ident: string, p: TParser): PNode =
     addImportToPragma(pragmas, ident, p)
 
 proc fieldIdent(ident: string, p: TParser): PNode = 
-  result = exportSym(p, mangledIdent(ident, p))
+  result = exportSym(p, mangledIdent(ident, p), ident)
   if p.scopeCounter > 0: return
   if p.options.header.len > 0: 
     var a = result
@@ -340,8 +360,30 @@ proc skipIdent(p: var TParser): PNode =
 
 proc skipIdentExport(p: var TParser): PNode = 
   expectIdent(p)
-  result = exportSym(p, mangledIdent(p.tok.s, p))
+  result = exportSym(p, mangledIdent(p.tok.s, p), p.tok.s)
   getTok(p, result)
+
+proc skipTypeIdentExport(p: var TParser, prefix='T'): PNode = 
+  expectIdent(p)
+  var n = prefix & mangleName(p.tok.s, p)
+  p.options.toMangle[p.tok.s] = n
+  var i = newNodeP(nkIdent, p)
+  i.ident = getIdent(n)
+  result = exportSym(p, i, p.tok.s)
+  getTok(p, result)
+
+proc markTypeIdent(p: var TParser, typ: PNode) = 
+  if pfTypePrefixes in p.options.flags:
+    var prefix = ""
+    if typ == nil: 
+      prefix = "T"
+    else: 
+      var t = typ
+      while t != nil and t.kind in {nkVarTy, nkPtrTy, nkRefTy}: 
+        prefix.add('P')
+        t = t.sons[0]
+    expectIdent(p)
+    p.options.toMangle[p.tok.s] = prefix & mangleRules(p.tok.s, p)
   
 # --------------- parser -----------------------------------------------------
 # We use this parsing rule: If it looks like a declaration, it is one. This
@@ -394,12 +436,13 @@ proc typeAtom(p: var TParser): PNode =
   elif isIntType(p.tok.s):
     var x = "c" & p.tok.s
     getTok(p, nil)
-    while p.tok.xkind == pxSymbol and (isIntType(p.tok.s) or p.tok.s == "char"):
+    while p.tok.xkind == pxSymbol and 
+        (isIntType(p.tok.s) or p.tok.s == "char"):
       add(x, p.tok.s)
       getTok(p, nil)
-    result = newIdentNodeP(x, p)
+    result = mangledIdent(x, p)
   else: 
-    result = newIdentNodeP(p.tok.s, p)
+    result = mangledIdent(p.tok.s, p)
     getTok(p, result)
     
 proc newPointerTy(p: TParser, typ: PNode): PNode =
@@ -528,7 +571,7 @@ proc parseStructBody(p: var TParser, isUnion: bool,
 proc structPragmas(p: TParser, name: PNode, origName: string): PNode = 
   assert name.kind == nkIdent
   result = newNodeP(nkPragmaExpr, p)
-  addson(result, exportSym(p, name))
+  addson(result, exportSym(p, name, origName))
   var pragmas = newNodep(nkPragma, p)
   addSon(pragmas, newIdentNodeP("pure", p), newIdentNodeP("final", p))
   if p.options.header.len > 0:
@@ -541,7 +584,8 @@ proc enumPragmas(p: TParser, name: PNode): PNode =
   addson(result, name)
   var pragmas = newNodep(nkPragma, p)
   var e = newNodeP(nkExprColonExpr, p)
-  addSon(e, newIdentNodeP("size", p), newIntNodeP(nkIntLit, 4, p))
+  # HACK: sizeof(cint) should be constructed as AST
+  addSon(e, newIdentNodeP("size", p), newIdentNodeP("sizeof(cint)", p))
   addSon(pragmas, e)
   addSon(result, pragmas)
 
@@ -608,6 +652,7 @@ proc parseFunctionPointerDecl(p: var TParser, rettyp: PNode): PNode =
   parseCallConv(p, pragmas)
   if p.tok.xkind == pxStar: getTok(p, params)
   else: parMessage(p, errTokenExpected, "*")
+  if p.inTypeDef > 0: markTypeIdent(p, nil)
   var name = skipIdentExport(p)
   eat(p, pxParRi, name)
   parseFormalParams(p, params, pragmas)
@@ -633,17 +678,18 @@ proc otherTypeDef(p: var TParser, section, typ: PNode) =
   case p.tok.xkind
   of pxParLe: 
     # function pointer: typedef typ (*name)();
-    getTok(p, nil)
     var x = parseFunctionPointerDecl(p, typ)
     name = x[0]
     t = x[2]
   of pxStar:
     # typedef typ *b;
     t = pointer(p, typ)
+    markTypeIdent(p, t)
     name = skipIdentExport(p)
   else: 
     # typedef typ name;
     t = typ
+    markTypeIdent(p, t)
     name = skipIdentExport(p)
   t = parseTypeSuffix(p, t)
   addTypeDef(section, name, t)
@@ -652,6 +698,7 @@ proc parseTrailingDefinedTypes(p: var TParser, section, typ: PNode) =
   while p.tok.xkind == pxComma:
     getTok(p, nil)
     var newTyp = pointer(p, typ)
+    markTypeIdent(p, newTyp)
     var newName = skipIdentExport(p)
     newTyp = parseTypeSuffix(p, newTyp)
     addTypeDef(section, newName, newTyp)
@@ -678,11 +725,13 @@ proc parseTypedefStruct(p: var TParser, result: PNode, isUnion: bool) =
   if p.tok.xkind == pxCurlyLe:
     var t = parseStruct(p, isUnion)
     var origName = p.tok.s
+    markTypeIdent(p, nil)
     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:
+    markTypeIdent(p, nil)
     var origName = p.tok.s
     var nameOrType = skipIdent(p)
     case p.tok.xkind 
@@ -691,6 +740,7 @@ proc parseTypedefStruct(p: var TParser, result: PNode, isUnion: bool) =
       if p.tok.xkind == pxSymbol: 
         # typedef struct tagABC {} abc, *pabc;
         # --> abc is a better type name than tagABC!
+        markTypeIdent(p, nil)
         var origName = p.tok.s
         var name = skipIdent(p)
         addTypeDef(result, structPragmas(p, name, origName), t)
@@ -716,11 +766,15 @@ proc parseTypedefEnum(p: var TParser, result: PNode) =
     getTok(p, result)
     var t = enumFields(p)
     eat(p, pxCurlyRi, t)
+    var origName = p.tok.s
+    markTypeIdent(p, nil)
     var name = skipIdent(p)
-    addTypeDef(result, enumPragmas(p, exportSym(p, name)), t)
+    addTypeDef(result, enumPragmas(p, exportSym(p, name, origName)), t)
     parseTrailingDefinedTypes(p, result, name)
   elif p.tok.xkind == pxSymbol: 
     # name to be defined or type "enum a", we don't know yet:
+    markTypeIdent(p, nil)
+    var origName = p.tok.s
     var nameOrType = skipIdent(p)
     case p.tok.xkind 
     of pxCurlyLe:
@@ -730,11 +784,14 @@ proc parseTypedefEnum(p: var TParser, result: PNode) =
       if p.tok.xkind == pxSymbol: 
         # typedef enum tagABC {} abc, *pabc;
         # --> abc is a better type name than tagABC!
+        markTypeIdent(p, nil)
+        var origName = p.tok.s
         var name = skipIdent(p)
-        addTypeDef(result, enumPragmas(p, exportSym(p, name)), t)
+        addTypeDef(result, enumPragmas(p, exportSym(p, name, origName)), t)
         parseTrailingDefinedTypes(p, result, name)
       else:
-        addTypeDef(result, enumPragmas(p, exportSym(p, nameOrType)), t)
+        addTypeDef(result, 
+                   enumPragmas(p, exportSym(p, nameOrType, origName)), t)
     of pxSymbol: 
       # typedef enum a a?
       if mangleName(p.tok.s, p) == nameOrType.ident.s:
@@ -862,7 +919,7 @@ proc declaration(p: var TParser): PNode =
       addSon(pragmas, newIdentNodeP("cdecl", p))
     elif pfStdcall in p.options.flags:
       addSon(pragmas, newIdentNodeP("stdcall", p))
-    addSon(result, exportSym(p, name), nil) # no generics
+    addSon(result, exportSym(p, name, origName), nil) # no generics
     addSon(result, params, pragmas)
     case p.tok.xkind 
     of pxSemicolon: 
@@ -884,9 +941,11 @@ proc createConst(name, typ, val: PNode, p: TParser): PNode =
   addSon(result, name, typ, val)
 
 proc enumSpecifier(p: var TParser): PNode =  
+  saveContext(p)
   getTok(p, nil) # skip "enum"
   case p.tok.xkind
   of pxCurlyLe: 
+    closeContext(p)
     # make a const section out of it:
     result = newNodeP(nkConstSection, p)
     getTok(p, result)
@@ -909,17 +968,31 @@ proc enumSpecifier(p: var TParser): PNode =
     eat(p, pxCurlyRi, result)
     eat(p, pxSemicolon)
   of pxSymbol: 
+    var origName = p.tok.s
+    markTypeIdent(p, nil)
     result = skipIdent(p)
-    if p.tok.xkind == pxCurlyLe: 
+    case p.tok.xkind 
+    of pxCurlyLe: 
+      closeContext(p)
       var name = result
       # create a type section containing the enum
       result = newNodeP(nkTypeSection, p)
       var t = newNodeP(nkTypeDef, p)
       getTok(p, t)
       var e = enumFields(p)
-      addSon(t, exportSym(p, name), nil, e) # nil for generic params
+      addSon(t, exportSym(p, name, origName), nil, e) # nil for generic params
       addSon(result, t)
+      eat(p, pxCurlyRi, result)
+      eat(p, pxSemicolon)
+    of pxSemicolon:
+      # just ignore ``enum X;`` for now.
+      closeContext(p)
+      getTok(p, nil)
+    else: 
+      backtrackContext(p)
+      result = declaration(p)
   else:
+    closeContext(p)
     parMessage(p, errTokenExpected, "{")
     
 # Expressions
@@ -1415,9 +1488,10 @@ proc parseStandaloneStruct(p: var TParser, isUnion: bool): PNode =
   getTok(p, result) # skip "struct" or "union"
   var origName = ""
   if p.tok.xkind == pxSymbol: 
+    markTypeIdent(p, nil)
     origName = p.tok.s
     getTok(p, result)
-  if p.tok.xkind == pxCurlyLe:
+  if p.tok.xkind in {pxCurlyLe, pxSemiColon}:
     if origName.len > 0: 
       var name = mangledIdent(origName, p)
       var t = parseStruct(p, isUnion)
diff --git a/rod/c2nim/cpp.nim b/rod/c2nim/cpp.nim
index dc4e7249e..5f304e1f8 100755
--- a/rod/c2nim/cpp.nim
+++ b/rod/c2nim/cpp.nim
@@ -25,7 +25,8 @@ proc skipLine(p: var TParser) =
 
 proc parseDefineBody(p: var TParser, tmplDef: PNode): string = 
   if p.tok.xkind == pxCurlyLe or 
-    (p.tok.xkind == pxSymbol and (declKeyword(p.tok.s) or stmtKeyword(p.tok.s))):
+    (p.tok.xkind == pxSymbol and (
+        declKeyword(p.tok.s) or stmtKeyword(p.tok.s))):
     addSon(tmplDef, statement(p))
     result = "stmt"
   elif p.tok.xkind in {pxLineComment, pxNewLine}:
@@ -272,22 +273,25 @@ proc parseIfDir(p: var TParser): PNode =
   eatNewLine(p, nil)
   parseIfDirAux(p, result)
 
-proc parseMangleDir(p: var TParser) = 
+proc parsePegLit(p: var TParser): TPeg =
   var col = getColumn(p.lex) + 2
   getTok(p)
   if p.tok.xkind != pxStrLit: ExpectIdent(p)
   try:
-    var pattern = parsePeg(
-      input = p.tok.s, 
+    result = parsePeg(
+      input = if p.tok.xkind == pxStrLit: p.tok.s else: escapePeg(p.tok.s), 
       filename = p.lex.filename, 
       line = p.lex.linenumber, 
       col = col)
     getTok(p)
-    if p.tok.xkind != pxStrLit: ExpectIdent(p)
-    p.options.mangleRules.add((pattern, p.tok.s))
-    getTok(p)
   except EInvalidPeg:
     parMessage(p, errUser, getCurrentExceptionMsg())
+
+proc parseMangleDir(p: var TParser) = 
+  var pattern = parsePegLit(p)
+  if p.tok.xkind != pxStrLit: ExpectIdent(p)
+  p.options.mangleRules.add((pattern, p.tok.s))
+  getTok(p)
   eatNewLine(p, nil)
 
 proc parseDir(p: var TParser): PNode = 
@@ -298,7 +302,7 @@ proc parseDir(p: var TParser): PNode =
   of "ifdef": result = parseIfdef(p)
   of "ifndef": result = parseIfndef(p)
   of "if": result = parseIfDir(p)
-  of "cdecl", "stdcall", "ref", "skipinclude": 
+  of "cdecl", "stdcall", "ref", "skipinclude", "typeprefixes", "skipcomments": 
     discard setOption(p.options, p.tok.s)
     getTok(p)
     eatNewLine(p, nil)
@@ -315,6 +319,10 @@ proc parseDir(p: var TParser): PNode =
     var L = p.options.macros.len
     setLen(p.options.macros, L+1)
     parseDef(p, p.options.macros[L])
+  of "private":
+    var pattern = parsePegLit(p)
+    p.options.privateRules.add(pattern)
+    eatNewLine(p, nil)
   else: 
     # ignore unimportant/unknown directive ("undef", "pragma", "error")
     skipLine(p)
diff --git a/rod/c2nim/manual.txt b/rod/c2nim/manual.txt
index bb89c9567..7aa8b557b 100755
--- a/rod/c2nim/manual.txt
+++ b/rod/c2nim/manual.txt
@@ -1,9 +1,9 @@
 =================================
   c2nim  User's manual
 =================================
-

-:Author: Andreas Rumpf

-:Version: 0.8.10
+
+:Author: Andreas Rumpf
+:Version: |nimrodversion|
 
 .. contents::
 
@@ -211,6 +211,47 @@ identifier should be converted:
 .. code-block:: C
   #mangle "'GTK_'{.*}" "TGtk$1"
 
+For convenience the PEG pattern and the replacement can be a single identifiers
+too, there is no need to quote them: 
+
+.. code-block:: C
+  #mangle ssize_t  int
+  // is short for:
+  #mangle "'ssize_t'" "int"
+
+
+``#private`` directive
+----------------------
+
+By default c2nim marks every top level identifier (proc name, variable, etc.)
+as exported (the export marker is ``*`` in Nimrod). With the ``#private`` 
+directive identifiers can be marked as private so that the resulting Nimrod
+module does not export them. The ``#private`` directive takes a PEG pattern:
+
+.. code-block:: C
+  #private "@('_'!.)" // all identifiers ending in '_' are private
+  
+Note: The pattern refers to the original C identifiers, not to the resulting
+identifiers after mangling!
+
+
+``#skipcomments`` directive
+---------------------------
+**Note**: There is also a ``--skipcomments`` command line option that can be
+used for the same purpose.
+
+The ``#skipcomments`` directive can be put into the C code to make c2nim
+ignore comments and not copy them into the generated Nimrod file.
+
+
+``#typeprefixes`` directive
+---------------------------
+**Note**: There is also a ``--typeprefixes`` command line option that can be
+used for the same purpose.
+
+The ``#typeprefixes`` directive can be put into the C code to make c2nim
+generate the ``T`` or ``P`` prefix for every defined type.
+
 
 ``#def`` directive
 ------------------
diff --git a/rod/c2nim/tests/systest.c b/rod/c2nim/tests/systest.c
index b2b7646bb..7f689c002 100755
--- a/rod/c2nim/tests/systest.c
+++ b/rod/c2nim/tests/systest.c
@@ -9,32 +9,64 @@ extern "C" {
 #  endif
 #endif
 
+#private expatDll
+
+#if !defined(expatDll)
+#  if defined(windows)
+#    define expatDll "expat.dll"
+#  elif defined(macosx)
+#    define expatDll "libexpat.dynlib"
+#  else
+#    define expatDll "libexpat.so(.1|)"
+#  endif
+#endif
+
+#mangle "'XML_'{.*}" "$1"
+#private "'XML_ParserStruct'"
+
+#mangle cunsignedint cint
+
+unsigned int uiVar;
+
+#private "@('_'!.)"
+unsigned int myPrivateVar__;
+
+
+struct XML_ParserStruct;
+
+#def XMLCALL __cdecl
+
+typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData,
+                                                const XML_Char *name,
+                                                XML_Content *model);
+
+
 void* x;
 void* fn(void);
 void (*fn)(void);
 void* (*fn)(void);
 void* (*fn)(void*);
 
-/*

- * Very ugly real world code ahead:

- */

+/*
+ * Very ugly real world code ahead:
+ */
 
 #def JMETHOD(rettype, name, params) rettype (*name) params
-

-typedef struct cjpeg_source_struct * cjpeg_source_ptr;

-

-struct cjpeg_source_struct {

-  JMETHOD(void, start_input, (j_compress_ptr cinfo,

-			      cjpeg_source_ptr sinfo));

-  JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,

-				       cjpeg_source_ptr sinfo));

-  JMETHOD(void, finish_input, (j_compress_ptr cinfo,

-			       cjpeg_source_ptr sinfo));

-

-  FILE *input_file;

-

-  JSAMPARRAY buffer;

-  JDIMENSION buffer_height;

+
+typedef struct cjpeg_source_struct * cjpeg_source_ptr;
+
+struct cjpeg_source_struct {
+  JMETHOD(void, start_input, (j_compress_ptr cinfo,
+			      cjpeg_source_ptr sinfo));
+  JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
+				       cjpeg_source_ptr sinfo));
+  JMETHOD(void, finish_input, (j_compress_ptr cinfo,
+			       cjpeg_source_ptr sinfo));
+
+  FILE *input_file;
+
+  JSAMPARRAY buffer;
+  JDIMENSION buffer_height;
 };
 
 // Test standalone structs: