Merge pull request #4 from Syeberman/dollar-in-identifier

Dollar signs in identifiers
diff --git a/CHANGES b/CHANGES
index 5896ff2..0f96f4d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
 + Version 2.10 (??)
 
   - BitBucket issue #9: c_generator error for ExprList in expression context.
+  - Github pull request #2: assume default int type for functions whose
+    argument or return types were not specified.
 
 + Version 2.09.1 (29.12.2012)
 
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 102126b..1ccd56f 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -17,6 +17,7 @@
 * Rory Yorke
 * Rubin
 * Scott Tsai
+* Sye van der Veen
 * Thomas W. Barr
 * Tomer Segal
 * Weyllor
diff --git a/pycparser/c_lexer.py b/pycparser/c_lexer.py
index f75769f..610bbbe 100644
--- a/pycparser/c_lexer.py
+++ b/pycparser/c_lexer.py
@@ -176,7 +176,7 @@
     hex_digits = '[0-9a-fA-F]+'
 
     # integer constants (K&R2: A.2.5.1)
-    integer_suffix_opt = r'(u?ll|U?LL|([uU][lL])|([lL][uU])|[uU]|[lL])?'
+    integer_suffix_opt = r'(([uU]ll)|([uU]LL)|(ll[uU]?)|(LL[uU]?)|([uU][lL])|([lL][uU]?)|[uU])?'
     decimal_constant = '(0'+integer_suffix_opt+')|([1-9][0-9]*'+integer_suffix_opt+')'
     octal_constant = '0[0-7]*'+integer_suffix_opt
     hex_constant = hex_prefix+hex_digits+integer_suffix_opt
diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py
index 88fe21d..abe7604 100644
--- a/pycparser/c_parser.py
+++ b/pycparser/c_parser.py
@@ -273,11 +273,22 @@
                     type.type = tn
                     return decl
 
-        # At this point, we know that typename is a list of IdentifierType
-        # nodes. Concatenate all the names into a single list.
-        type.type = c_ast.IdentifierType(
-            [name for id in typename for name in id.names],
-            coord=typename[0].coord)
+        if not typename:
+            # Functions default to returning int
+            #
+            if not isinstance(decl.type, c_ast.FuncDecl):
+                self._parse_error(
+                        "Missing type in declaration", decl.coord)
+            type.type = c_ast.IdentifierType(
+                    ['int'],
+                    coord=decl.coord)
+        else:
+            # At this point, we know that typename is a list of IdentifierType
+            # nodes. Concatenate all the names into a single list.
+            #
+            type.type = c_ast.IdentifierType(
+                [name for id in typename for name in id.names],
+                coord=typename[0].coord)
         return decl
 
     def _add_declaration_specifier(self, declspec, newspec, kind):
@@ -411,8 +422,13 @@
     def p_function_definition_1(self, p):
         """ function_definition : declarator declaration_list_opt compound_statement
         """
-        # no declaration specifiers
-        spec = dict(qual=[], storage=[], type=[])
+        # no declaration specifiers - 'int' becomes the default type
+        spec = dict(
+            qual=[],
+            storage=[],
+            type=[c_ast.IdentifierType(['int'],
+                                       coord=self._coord(p.lineno(1)))],
+            function=[])
 
         p[0] = self._build_function_definition(
             decl=p[1],
diff --git a/tests/test_c_lexer.py b/tests/test_c_lexer.py
index 14242b8..790ab39 100644
--- a/tests/test_c_lexer.py
+++ b/tests/test_c_lexer.py
@@ -55,9 +55,14 @@
     def test_integer_constants(self):
         self.assertTokensTypes('12', ['INT_CONST_DEC'])
         self.assertTokensTypes('12u', ['INT_CONST_DEC'])
+        self.assertTokensTypes('12l', ['INT_CONST_DEC'])
         self.assertTokensTypes('199872Ul', ['INT_CONST_DEC'])
+        self.assertTokensTypes('199872lU', ['INT_CONST_DEC'])
         self.assertTokensTypes('199872LL', ['INT_CONST_DEC'])
         self.assertTokensTypes('199872ull', ['INT_CONST_DEC'])
+        self.assertTokensTypes('199872llu', ['INT_CONST_DEC'])
+        self.assertTokensTypes('1009843200000uLL', ['INT_CONST_DEC'])
+        self.assertTokensTypes('1009843200000LLu', ['INT_CONST_DEC'])
 
         self.assertTokensTypes('077', ['INT_CONST_OCT'])
         self.assertTokensTypes('0123456L', ['INT_CONST_OCT'])
diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py
index e1ceec3..bae764c 100644
--- a/tests/test_c_parser.py
+++ b/tests/test_c_parser.py
@@ -260,6 +260,15 @@
                     ],
                 ['TypeDecl', ['IdentifierType', ['int']]]]])
 
+        # function return values and parameters may not have type information
+        self.assertEqual(self.get_decl('extern foobar(foo, bar);'), 
+            ['Decl', 'foobar', 
+                ['FuncDecl', 
+                    [   ['ID', 'foo'],
+                        ['ID', 'bar']
+                    ], 
+                ['TypeDecl', ['IdentifierType', ['int']]]]])
+
     def test_nested_decls(self): # the fun begins
         self.assertEqual(self.get_decl('char** ar2D;'),
             ['Decl', 'ar2D',
@@ -1067,6 +1076,20 @@
         self.assertEqual(expand_decl(f3.param_decls[1]),
             ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
 
+        # function return values and parameters may not have type information
+        f4 = parse_fdef('''
+        que(p)
+        {
+            return 3;
+        }
+        ''')
+
+        self.assertEqual(fdef_decl(f4),
+            ['Decl', 'que',
+                ['FuncDecl',
+                    [['ID', 'p']],
+                    ['TypeDecl', ['IdentifierType', ['int']]]]])
+
     def test_unified_string_literals(self):
         # simple string, for reference
         d1 = self.get_decl_init('char* s = "hello";')
diff --git a/z_test.py b/z.py
similarity index 85%
rename from z_test.py
rename to z.py
index c1aab48..2247bb3 100644
--- a/z_test.py
+++ b/z.py
@@ -8,7 +8,7 @@
     """ Converts the declaration into a nested list.
     """
     typ = type(decl)
-    
+
     if typ == TypeDecl:
         return ['TypeDecl', expand_decl(decl.type)]
     elif typ == IdentifierType:
@@ -18,9 +18,9 @@
     elif typ in [Struct, Union]:
         decls = [expand_decl(d) for d in decl.decls or []]
         return [typ.__name__, decl.name, decls]
-    else:        
+    else:
         nested = expand_decl(decl.type)
-    
+
         if typ == Decl:
             if decl.quals:
                 return ['Decl', decl.quals, decl.name, nested]
@@ -49,22 +49,22 @@
 class NodeVisitor(object):
     def __init__(self):
         self.current_parent = None
-        
+
     def visit(self, node):
-        """ Visit a node. 
+        """ Visit a node.
         """
         method = 'visit_' + node.__class__.__name__
         visitor = getattr(self, method, self.generic_visit)
         return visitor(node)
-    
+
     def visit_FuncCall(self, node):
         print("Visiting FuncCall")
         print(node.show())
         print('---- parent ----')
         print(self.current_parent.show())
-    
+
     def generic_visit(self, node):
-        """ Called if no explicit visitor function exists for a 
+        """ Called if no explicit visitor function exists for a
             node. Implements preorder visiting of the node.
         """
         oldparent = self.current_parent
@@ -74,20 +74,17 @@
         self.current_parent = oldparent
 
 
-if __name__ == "__main__":    
+if __name__ == "__main__":
     source_code = r'''
-    typedef int foobar;
-    typedef int foobar;
-    void main(void) {
-        foobar i;
-    }
+        struct sample
+        {
+            int nodeId;
+            char nodeName[10];
+        } SSample;
     '''
 
-    parser = CParser(lex_optimize=False, yacc_optimize=False, yacc_debug=True)
+    parser = CParser()
     ast = parser.parse(source_code, filename='zz')
     ast.show(showcoord=False, attrnames=True, nodenames=True)
-    #~ nv=NodeVisitor()
-    #~ nv.visit(ast)
 
-    print('-- done --')