blob: 088c7700338d0495d7a7986c67462f0243bb5c8c [file] [log] [blame]
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001#!/usr/bin/env python
2
3import pprint
4import re
5import sys
6import unittest
7
8sys.path.insert(0, '..')
9
10from pycparser import c_parser
11from pycparser.c_ast import *
12from pycparser.c_parser import CParser, Coord, ParseError
13
Eli Bendersky3921e8e2010-05-21 09:05:39 +030014_c_parser = c_parser.CParser(
15 lex_optimize=False,
16 yacc_debug=True,
17 yacc_optimize=False,
18 yacctab='yacctab')
19
20
21def expand_decl(decl):
22 """ Converts the declaration into a nested list.
23 """
24 typ = type(decl)
25
26 if typ == TypeDecl:
27 return ['TypeDecl', expand_decl(decl.type)]
28 elif typ == IdentifierType:
29 return ['IdentifierType', decl.names]
30 elif typ == ID:
31 return ['ID', decl.name]
32 elif typ in [Struct, Union]:
33 decls = [expand_decl(d) for d in decl.decls or []]
34 return [typ.__name__, decl.name, decls]
35 else:
36 nested = expand_decl(decl.type)
37
38 if typ == Decl:
39 if decl.quals:
40 return ['Decl', decl.quals, decl.name, nested]
41 else:
42 return ['Decl', decl.name, nested]
43 elif typ == Typename: # for function parameters
44 if decl.quals:
45 return ['Typename', decl.quals, nested]
46 else:
47 return ['Typename', nested]
48 elif typ == ArrayDecl:
49 dimval = decl.dim.value if decl.dim else ''
50 return ['ArrayDecl', dimval, nested]
51 elif typ == PtrDecl:
52 return ['PtrDecl', nested]
53 elif typ == Typedef:
54 return ['Typedef', decl.name, nested]
55 elif typ == FuncDecl:
56 if decl.args:
57 params = [expand_decl(param) for param in decl.args.params]
58 else:
59 params = []
60 return ['FuncDecl', params, nested]
61
62
63def expand_init(init):
64 """ Converts an initialization into a nested list
65 """
66 typ = type(init)
67
eli.benderskyf890a862010-10-30 12:13:23 +020068 if typ == NamedInitializer:
69 des = [expand_init(dp) for dp in init.name]
70 return (des, expand_init(init.expr))
71 elif typ == ExprList:
72 return [expand_init(expr) for expr in init.exprs]
73 elif typ == Constant:
Eli Bendersky3921e8e2010-05-21 09:05:39 +030074 return ['Constant', init.type, init.value]
75 elif typ == ID:
76 return ['ID', init.name]
Eli Bendersky3921e8e2010-05-21 09:05:39 +030077
78
79class TestCParser_fundamentals(unittest.TestCase):
80 """ Tests for "fundamental features" of CParser. Testing
81 (mostly) each feature in a detailed manner.
82 """
83 def parse(self, txt, filename=''):
84 return self.cparser.parse(txt, filename)
85
86 def setUp(self):
87 self.cparser = _c_parser
88
89 def get_decl(self, txt, index=0):
90 """ Given a source and an index returns the expanded
91 declaration at that index.
92
93 FileAST holds a list of 'external declarations'.
94 index is the offset of the desired declaration in that
95 list.
96 """
97 t = self.parse(txt).ext[index]
98 return expand_decl(t)
99
100 def get_decl_init(self, txt, index=0):
101 """ Returns the expanded initializer of the declaration
102 at index.
103 """
104 t = self.parse(txt).ext[index]
105 return expand_init(t.init)
106
107 def test_FileAST(self):
108 t = self.parse('int a; char c;')
109 self.failUnless(isinstance(t, FileAST))
110 self.assertEqual(len(t.ext), 2)
111
eli.bendersky38165b72011-02-04 08:13:39 +0200112 def test_empty_toplevel_decl(self):
113 code = 'int foo;;'
114 t = self.parse(code)
115 self.failUnless(isinstance(t, FileAST))
116 self.assertEqual(len(t.ext), 1)
117 self.assertEqual(self.get_decl(code),
118 ['Decl', 'foo',
119 ['TypeDecl', ['IdentifierType', ['int']]]])
120
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300121 def assert_coord(self, node, line, file=None):
122 self.assertEqual(node.coord.line, line)
123 if file:
124 self.assertEqual(node.coord.file, file)
125
126 def test_coords(self):
eli.bendersky38165b72011-02-04 08:13:39 +0200127 """ Tests the "coordinates" of parsed elements - file
128 name and line numbers, with modification insterted by
129 #line directives.
130 """
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300131 self.assert_coord(self.parse('int a;').ext[0], 1)
132
133 t1 = """
134 int a;
135 int b;\n\n
136 int c;
137 """
138 f1 = self.parse(t1, filename='test.c')
139 self.assert_coord(f1.ext[0], 2, 'test.c')
140 self.assert_coord(f1.ext[1], 3, 'test.c')
141 self.assert_coord(f1.ext[2], 6, 'test.c')
142
143 t1_1 = '''
144 int main() {
145 k = p;
146 printf("%d", b);
147 return 0;
148 }'''
149 f1_1 = self.parse(t1_1, filename='test.c')
eli.benderskyef29ff92010-10-29 16:25:43 +0200150 self.assert_coord(f1_1.ext[0].body.block_items[0], 3, 'test.c')
151 self.assert_coord(f1_1.ext[0].body.block_items[1], 4, 'test.c')
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300152
153 t2 = """
154 #line 99
155 int c;
156 """
157 self.assert_coord(self.parse(t2).ext[0], 99)
158
159 t3 = """
160 int dsf;
161 char p;
162 #line 3000 "in.h"
163 char d;
164 """
165 f3 = self.parse(t3, filename='test.c')
166 self.assert_coord(f3.ext[0], 2, 'test.c')
167 self.assert_coord(f3.ext[1], 3, 'test.c')
168 self.assert_coord(f3.ext[2], 3000, 'in.h')
169
170 t4 = """
171 #line 20 "restore.h"
172 int maydler(char);
173
174 #line 30 "includes/daween.ph"
175 long j, k;
176
177 #line 50000
178 char* ro;
179 """
180 f4 = self.parse(t4, filename='myb.c')
181 self.assert_coord(f4.ext[0], 20, 'restore.h')
182 self.assert_coord(f4.ext[1], 30, 'includes/daween.ph')
183 self.assert_coord(f4.ext[2], 30, 'includes/daween.ph')
184 self.assert_coord(f4.ext[3], 50000, 'includes/daween.ph')
185
186 t5 = """
187 int
188 #line 99
189 c;
190 """
191 self.assert_coord(self.parse(t5).ext[0], 99)
192
193 def test_simple_decls(self):
194 self.assertEqual(self.get_decl('int a;'),
195 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
196
197 self.assertEqual(self.get_decl('unsigned int a;'),
198 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int', 'unsigned']]]])
199
200 self.assertEqual(self.get_decl('char* string;'),
201 ['Decl', 'string',
202 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]])
203
204 self.assertEqual(self.get_decl('long ar[15];'),
205 ['Decl', 'ar',
206 ['ArrayDecl', '15',
207 ['TypeDecl', ['IdentifierType', ['long']]]]])
eli.bendersky98f45372010-10-30 09:46:29 +0200208
209 self.assertEqual(self.get_decl('long long ar[15];'),
210 ['Decl', 'ar',
211 ['ArrayDecl', '15',
eli.benderskyf890a862010-10-30 12:13:23 +0200212 ['TypeDecl', ['IdentifierType', ['long', 'long']]]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300213
214 self.assertEqual(self.get_decl('unsigned ar[];'),
215 ['Decl', 'ar',
216 ['ArrayDecl', '',
217 ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
218
219 self.assertEqual(self.get_decl('int strlen(char* s);'),
220 ['Decl', 'strlen',
221 ['FuncDecl',
222 [['Decl', 's',
223 ['PtrDecl',
224 ['TypeDecl', ['IdentifierType', ['char']]]]]],
225 ['TypeDecl', ['IdentifierType', ['int']]]]])
226
227 self.assertEqual(self.get_decl('int strcmp(char* s1, char* s2);'),
228 ['Decl', 'strcmp',
229 ['FuncDecl',
230 [ ['Decl', 's1',
231 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
232 ['Decl', 's2',
233 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]
234 ],
235 ['TypeDecl', ['IdentifierType', ['int']]]]])
236
237 def test_nested_decls(self): # the fun begins
238 self.assertEqual(self.get_decl('char** ar2D;'),
239 ['Decl', 'ar2D',
240 ['PtrDecl', ['PtrDecl',
241 ['TypeDecl', ['IdentifierType', ['char']]]]]])
242
243 self.assertEqual(self.get_decl('int (*a)[1][2];'),
244 ['Decl', 'a',
245 ['PtrDecl',
246 ['ArrayDecl', '1',
247 ['ArrayDecl', '2',
248 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
249
250 self.assertEqual(self.get_decl('int *a[1][2];'),
251 ['Decl', 'a',
252 ['ArrayDecl', '1',
253 ['ArrayDecl', '2',
254 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
255
256 self.assertEqual(self.get_decl('char ***ar3D[40];'),
257 ['Decl', 'ar3D',
258 ['ArrayDecl', '40',
259 ['PtrDecl', ['PtrDecl', ['PtrDecl',
260 ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
261
262 self.assertEqual(self.get_decl('char (***ar3D)[40];'),
263 ['Decl', 'ar3D',
264 ['PtrDecl', ['PtrDecl', ['PtrDecl',
265 ['ArrayDecl', '40', ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
266
267 self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
268 ['Decl', 'x',
269 ['ArrayDecl', '4',
270 ['PtrDecl',
271 ['FuncDecl',
272 [ ['Typename', ['TypeDecl', ['IdentifierType', ['char']]]],
273 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
274 ['TypeDecl', ['IdentifierType', ['int']]]]]]])
275
276 self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
277 ['Decl', 'foo',
278 ['ArrayDecl', '',
279 ['ArrayDecl', '8',
280 ['PtrDecl', ['PtrDecl',
281 ['FuncDecl',
282 [],
283 ['PtrDecl',
284 ['ArrayDecl', '',
285 ['PtrDecl',
286 ['TypeDecl',
287 ['IdentifierType', ['char']]]]]]]]]]]])
288
289 # explore named and unnamed function pointer parameters,
290 # with and without qualifiers
291 #
292
293 # unnamed w/o quals
294 self.assertEqual(self.get_decl('int (*k)(int);'),
295 ['Decl', 'k',
296 ['PtrDecl',
297 ['FuncDecl',
298 [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]],
299 ['TypeDecl', ['IdentifierType', ['int']]]]]])
300
301 # unnamed w/ quals
302 self.assertEqual(self.get_decl('int (*k)(const int);'),
303 ['Decl', 'k',
304 ['PtrDecl',
305 ['FuncDecl',
306 [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]],
307 ['TypeDecl', ['IdentifierType', ['int']]]]]])
308
309 # named w/o quals
310 self.assertEqual(self.get_decl('int (*k)(int q);'),
311 ['Decl', 'k',
312 ['PtrDecl',
313 ['FuncDecl',
314 [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]],
315 ['TypeDecl', ['IdentifierType', ['int']]]]]])
316
317 # named w/ quals
318 self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
319 ['Decl', 'k',
320 ['PtrDecl',
321 ['FuncDecl',
322 [['Decl', ['volatile', 'const'], 'q',
323 ['TypeDecl', ['IdentifierType', ['int']]]]],
324 ['TypeDecl', ['IdentifierType', ['int']]]]]])
325
eli.bendersky79d5cf62010-10-29 13:33:52 +0200326 # restrict qualifier
327 self.assertEqual(self.get_decl('int (*k)(restrict int* q);'),
328 ['Decl', 'k',
329 ['PtrDecl',
330 ['FuncDecl',
331 [['Decl', ['restrict'], 'q',
332 ['PtrDecl',
333 ['TypeDecl', ['IdentifierType', ['int']]]]]],
334 ['TypeDecl', ['IdentifierType', ['int']]]]]])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300335
336 def test_qualifiers_storage_specifiers(self):
337 def assert_qs(txt, index, quals, storage):
338 d = self.parse(txt).ext[index]
339 self.assertEqual(d.quals, quals)
340 self.assertEqual(d.storage, storage)
341
342 assert_qs("extern int p;", 0, [], ['extern'])
343 assert_qs("const long p = 6;", 0, ['const'], [])
344
345 d1 = "static const int p, q, r;"
346 for i in range(3):
347 assert_qs(d1, i, ['const'], ['static'])
348
349 d2 = "static char * const p;"
350 assert_qs(d2, 0, [], ['static'])
351 pdecl = self.parse(d2).ext[0].type
352 self.failUnless(isinstance(pdecl, PtrDecl))
353 self.assertEqual(pdecl.quals, ['const'])
354
355 def test_sizeof(self):
356 e = """
357 void foo()
358 {
359 int a = sizeof k;
360 int b = sizeof(int);
eli.benderskyc51e1d32011-02-04 08:52:33 +0200361 int c = sizeof(int**);;
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300362
363 char* p = "just to make sure this parses w/o error...";
364 int d = sizeof(int());
365 }
366 """
367 compound = self.parse(e).ext[0].body
368
eli.benderskyef29ff92010-10-29 16:25:43 +0200369 s1 = compound.block_items[0].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300370 self.assertTrue(isinstance(s1, UnaryOp))
371 self.assertEqual(s1.op, 'sizeof')
372 self.assertTrue(isinstance(s1.expr, ID))
373 self.assertEqual(s1.expr.name, 'k')
374
eli.benderskyef29ff92010-10-29 16:25:43 +0200375 s2 = compound.block_items[1].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300376 self.assertEqual(expand_decl(s2.expr),
377 ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
378
eli.benderskyef29ff92010-10-29 16:25:43 +0200379 s3 = compound.block_items[2].init
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300380 self.assertEqual(expand_decl(s3.expr),
381 ['Typename',
382 ['PtrDecl',
383 ['PtrDecl',
384 ['TypeDecl',
385 ['IdentifierType', ['int']]]]]])
386
eli.bendersky9f481562010-10-30 15:50:47 +0200387 # The C99 compound literal feature
388 #
eli.benderskyf890a862010-10-30 12:13:23 +0200389 def test_compound_literals(self):
eli.bendersky9f481562010-10-30 15:50:47 +0200390 ps1 = self.parse(r'''
eli.benderskyf890a862010-10-30 12:13:23 +0200391 void foo() {
eli.bendersky9f481562010-10-30 15:50:47 +0200392 p = (long long){k};
393 tc = (struct jk){.a = {1, 2}, .b[0] = t};
394 }''')
eli.benderskyf890a862010-10-30 12:13:23 +0200395
eli.bendersky9f481562010-10-30 15:50:47 +0200396 compound = ps1.ext[0].body.block_items[0].rvalue
397 self.assertEqual(expand_decl(compound.type),
398 ['Typename', ['TypeDecl', ['IdentifierType', ['long', 'long']]]])
399 self.assertEqual(expand_init(compound.init),
400 [['ID', 'k']])
401
402 compound = ps1.ext[0].body.block_items[1].rvalue
403 self.assertEqual(expand_decl(compound.type),
404 ['Typename', ['TypeDecl', ['Struct', 'jk', []]]])
405 self.assertEqual(expand_init(compound.init),
406 [
407 ([['ID', 'a']], [['Constant', 'int', '1'], ['Constant', 'int', '2']]),
408 ([['ID', 'b'], ['Constant', 'int', '0']], ['ID', 't'])])
eli.benderskyf890a862010-10-30 12:13:23 +0200409
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300410 def test_enums(self):
411 e1 = "enum mycolor op;"
412 e1_type = self.parse(e1).ext[0].type.type
413
414 self.assertTrue(isinstance(e1_type, Enum))
415 self.assertEqual(e1_type.name, 'mycolor')
416 self.assertEqual(e1_type.values, None)
417
418 e2 = "enum mysize {large=20, small, medium} shoes;"
419 e2_type = self.parse(e2).ext[0].type.type
420
421 self.assertTrue(isinstance(e2_type, Enum))
422 self.assertEqual(e2_type.name, 'mysize')
423
424 e2_elist = e2_type.values
425 self.assertTrue(isinstance(e2_elist, EnumeratorList))
426
427 for e2_eval in e2_elist.enumerators:
428 self.assertTrue(isinstance(e2_eval, Enumerator))
429
430 self.assertEqual(e2_elist.enumerators[0].name, 'large')
431 self.assertEqual(e2_elist.enumerators[0].value.value, '20')
432 self.assertEqual(e2_elist.enumerators[2].name, 'medium')
433 self.assertEqual(e2_elist.enumerators[2].value, None)
434
435 # enum with trailing comma (C99 feature)
436 e3 = """
437 enum
438 {
439 red,
440 blue,
441 green,
442 } color;
443 """
444
445 e3_type = self.parse(e3).ext[0].type.type
446 self.assertTrue(isinstance(e3_type, Enum))
447 e3_elist = e3_type.values
448 self.assertTrue(isinstance(e3_elist, EnumeratorList))
449
450 for e3_eval in e3_elist.enumerators:
451 self.assertTrue(isinstance(e3_eval, Enumerator))
452
453 self.assertEqual(e3_elist.enumerators[0].name, 'red')
454 self.assertEqual(e3_elist.enumerators[0].value, None)
455 self.assertEqual(e3_elist.enumerators[1].name, 'blue')
456 self.assertEqual(e3_elist.enumerators[2].name, 'green')
457
458 def test_typedef(self):
459 # without typedef, error
460 s1 = """
461 node k;
462 """
463 self.assertRaises(ParseError, self.parse, s1)
464
465 # now with typedef, works
466 s2 = """
467 typedef void* node;
468 node k;
469 """
470 ps2 = self.parse(s2)
471 self.assertEqual(expand_decl(ps2.ext[0]),
472 ['Typedef', 'node',
473 ['PtrDecl',
474 ['TypeDecl', ['IdentifierType', ['void']]]]])
475
476 self.assertEqual(expand_decl(ps2.ext[1]),
477 ['Decl', 'k',
478 ['TypeDecl', ['IdentifierType', ['node']]]])
479
480 s3 = """
481 typedef int T;
482 typedef T *pT;
483
484 pT aa, bb;
485 """
486 ps3 = self.parse(s3)
487 self.assertEqual(expand_decl(ps3.ext[3]),
488 ['Decl', 'bb',
489 ['TypeDecl', ['IdentifierType', ['pT']]]])
490
491 s4 = '''
492 typedef char* __builtin_va_list;
493 typedef __builtin_va_list __gnuc_va_list;
494 '''
495 ps4 = self.parse(s4)
496 self.assertEqual(expand_decl(ps4.ext[1]),
497 ['Typedef', '__gnuc_va_list',
498 ['TypeDecl',
499 ['IdentifierType', ['__builtin_va_list']]]])
500
501 s5 = '''typedef struct tagHash Hash;'''
502 ps5 = self.parse(s5)
503 self.assertEqual(expand_decl(ps5.ext[0]),
504 ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
505
506 def test_struct_union(self):
507 s1 = """
508 struct {
509 int id;
510 char* name;
511 } joe;
512 """
513
514 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
515 ['Decl', 'joe',
516 ['TypeDecl', ['Struct', None,
517 [ ['Decl', 'id',
518 ['TypeDecl',
519 ['IdentifierType', ['int']]]],
520 ['Decl', 'name',
521 ['PtrDecl',
522 ['TypeDecl',
523 ['IdentifierType', ['char']]]]]]]]])
524
525 s2 = """
526 struct node p;
527 """
528 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
529 ['Decl', 'p',
530 ['TypeDecl', ['Struct', 'node', []]]])
531
532 s21 = """
533 union pri ra;
534 """
535 self.assertEqual(expand_decl(self.parse(s21).ext[0]),
536 ['Decl', 'ra',
537 ['TypeDecl', ['Union', 'pri', []]]])
538
539 s3 = """
540 struct node* p;
541 """
542 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
543 ['Decl', 'p',
544 ['PtrDecl',
545 ['TypeDecl', ['Struct', 'node', []]]]])
546
547 s4 = """
548 struct node;
549 """
550 self.assertEqual(expand_decl(self.parse(s4).ext[0]),
551 ['Decl', None,
552 ['Struct', 'node', []]])
553
554 s5 = """
555 union
556 {
557 struct
558 {
559 int type;
560 } n;
561
562 struct
563 {
564 int type;
565 int intnode;
566 } ni;
567 } u;
568 """
569 self.assertEqual(expand_decl(self.parse(s5).ext[0]),
570 ['Decl', 'u',
571 ['TypeDecl',
572 ['Union', None,
573 [['Decl', 'n',
574 ['TypeDecl',
575 ['Struct', None,
576 [['Decl', 'type',
577 ['TypeDecl', ['IdentifierType', ['int']]]]]]]],
578 ['Decl', 'ni',
579 ['TypeDecl',
580 ['Struct', None,
581 [['Decl', 'type',
582 ['TypeDecl', ['IdentifierType', ['int']]]],
583 ['Decl', 'intnode',
584 ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
585
586 s6 = """
587 typedef struct foo_tag
588 {
589 void* data;
590 } foo, *pfoo;
591 """
592 s6_ast = self.parse(s6)
593
594 self.assertEqual(expand_decl(s6_ast.ext[0]),
595 ['Typedef', 'foo',
596 ['TypeDecl',
597 ['Struct', 'foo_tag',
598 [['Decl', 'data',
599 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
600
601 self.assertEqual(expand_decl(s6_ast.ext[1]),
602 ['Typedef', 'pfoo',
603 ['PtrDecl',
604 ['TypeDecl',
605 ['Struct', 'foo_tag',
606 [['Decl', 'data',
607 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
608
609 s7 = r"""
610 struct _on_exit_args {
611 void * _fnargs[32];
612 void * _dso_handle[32];
613
614 long _fntypes;
615 #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
616
617 long _is_cxa;
618 };
619 """
620
621 s7_ast = self.parse(s7, filename='test.c')
622 self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 'test.c')
623 self.assert_coord(s7_ast.ext[0].type.decls[3], 78,
624 r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
625
626 s8 = """
627 typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode;
628
629 typedef struct tagEntry
630 {
631 char* key;
632 char* value;
633 } Entry;
634
635
636 typedef struct tagNode
637 {
638 Entry* entry;
639
640 struct tagNode* next;
641 } Node;
642
643 typedef struct tagHash
644 {
645 unsigned int table_size;
646
647 Node** heads;
648
649 } Hash;
650 """
651 s8_ast = self.parse(s8)
652 self.assertEqual(expand_decl(s8_ast.ext[3]),
653 ['Typedef', 'Hash',
654 ['TypeDecl', ['Struct', 'tagHash',
655 [['Decl', 'table_size',
656 ['TypeDecl', ['IdentifierType', ['int', 'unsigned']]]],
657 ['Decl', 'heads',
658 ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
659
eli.bendersky697ecc52011-02-10 07:05:13 +0200660 def test_anonymous_struct_union(self):
661 s1 = """
662 union
663 {
664 union
665 {
666 int i;
667 long l;
668 };
669
670 struct
671 {
672 int type;
673 int intnode;
674 };
675 } u;
676 """
677
678 self.assertEqual(expand_decl(self.parse(s1).ext[0]),
679 ['Decl', 'u',
680 ['TypeDecl',
681 ['Union', None,
682 [['Decl', None,
683 ['Union', None,
684 [['Decl', 'i',
685 ['TypeDecl',
686 ['IdentifierType', ['int']]]],
687 ['Decl', 'l',
688 ['TypeDecl',
689 ['IdentifierType', ['long']]]]]]],
690 ['Decl', None,
691 ['Struct', None,
692 [['Decl', 'type',
693 ['TypeDecl',
694 ['IdentifierType', ['int']]]],
695 ['Decl', 'intnode',
696 ['TypeDecl',
697 ['IdentifierType', ['int']]]]]]]]]]])
698
699 s2 = """
700 struct
701 {
702 int i;
703 union
704 {
705 int id;
706 char* name;
707 };
708 float f;
709 } joe;
710 """
711
712 self.assertEqual(expand_decl(self.parse(s2).ext[0]),
713 ['Decl', 'joe',
714 ['TypeDecl',
715 ['Struct', None,
716 [['Decl', 'i',
717 ['TypeDecl',
718 ['IdentifierType', ['int']]]],
719 ['Decl', None,
720 ['Union', None,
721 [['Decl', 'id',
722 ['TypeDecl',
723 ['IdentifierType', ['int']]]],
724 ['Decl', 'name',
725 ['PtrDecl',
726 ['TypeDecl',
727 ['IdentifierType', ['char']]]]]]]],
728 ['Decl', 'f',
729 ['TypeDecl',
730 ['IdentifierType', ['float']]]]]]]])
731
732 # ISO/IEC 9899:201x Commitee Draft 2010-11-16, N1539
733 # section 6.7.2.1, par. 19, example 1
734 s3 = """
735 struct v {
736 union {
737 struct { int i, j; };
738 struct { long k, l; } w;
739 };
740 int m;
741 } v1;
742 """
743
744 self.assertEqual(expand_decl(self.parse(s3).ext[0]),
745 ['Decl', 'v1',
746 ['TypeDecl',
747 ['Struct', 'v',
748 [['Decl', None,
749 ['Union', None,
750 [['Decl', None,
751 ['Struct', None,
752 [['Decl', 'i',
753 ['TypeDecl',
754 ['IdentifierType', ['int']]]],
755 ['Decl', 'j',
756 ['TypeDecl',
757 ['IdentifierType', ['int']]]]]]],
758 ['Decl', 'w',
759 ['TypeDecl',
760 ['Struct', None,
761 [['Decl', 'k',
762 ['TypeDecl',
763 ['IdentifierType', ['long']]]],
764 ['Decl', 'l',
765 ['TypeDecl',
766 ['IdentifierType', ['long']]]]]]]]]]],
767 ['Decl', 'm',
768 ['TypeDecl',
769 ['IdentifierType', ['int']]]]]]]])
770
eli.benderskydce29a02011-02-10 07:55:00 +0200771 s4 = """
772 struct v {
773 int i;
774 float;
775 } v2;"""
776
777 self.assertRaises(ParseError, self.parse, s4)
778
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200779 def test_struct_bitfields(self):
eli.bendersky38ed9a92010-10-09 09:29:59 +0200780 # a struct with two bitfields, one unnamed
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200781 s1 = """
782 struct {
783 int k:6;
784 int :2;
785 } joe;
786 """
787
788 parsed_struct = self.parse(s1).ext[0]
789
eli.bendersky38ed9a92010-10-09 09:29:59 +0200790 # We can see here the name of the decl for the unnamed bitfield is
eli.bendersky0e0a71f2010-10-09 08:32:00 +0200791 # None, but expand_decl doesn't show bitfield widths
792 # ...
793 self.assertEqual(expand_decl(parsed_struct),
794 ['Decl', 'joe',
795 ['TypeDecl', ['Struct', None,
796 [ ['Decl', 'k',
797 ['TypeDecl',
798 ['IdentifierType', ['int']]]],
799 ['Decl', None,
800 ['TypeDecl',
801 ['IdentifierType', ['int']]]]]]]])
802
803 # ...
804 # so we test them manually
805 self.assertEqual(parsed_struct.type.type.decls[0].bitsize.value, '6')
806 self.assertEqual(parsed_struct.type.type.decls[1].bitsize.value, '2')
807
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300808 def test_tags_namespace(self):
809 """ Tests that the tags of structs/unions/enums reside in a separate namespace and
810 can be named after existing types.
811 """
812 s1 = """
813 typedef int tagEntry;
814
815 struct tagEntry
816 {
817 char* key;
818 char* value;
819 } Entry;
820 """
821
822 s1_ast = self.parse(s1)
823 self.assertEqual(expand_decl(s1_ast.ext[1]),
824 ['Decl', 'Entry',
825 ['TypeDecl', ['Struct', 'tagEntry',
826 [['Decl', 'key',
827 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
828 ['Decl', 'value',
829 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
830
831 s2 = """
832 struct tagEntry;
833
834 typedef struct tagEntry tagEntry;
835
836 struct tagEntry
837 {
838 char* key;
839 char* value;
840 } Entry;
841 """
842
843 s2_ast = self.parse(s2)
844 self.assertEqual(expand_decl(s2_ast.ext[2]),
845 ['Decl', 'Entry',
846 ['TypeDecl', ['Struct', 'tagEntry',
847 [['Decl', 'key',
848 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]],
849 ['Decl', 'value',
850 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
851
852 s3 = """
853 typedef int mytag;
854
855 enum mytag {ABC, CDE};
856 enum mytag joe;
857 """
858
859 s3_type = self.parse(s3).ext[1].type
860
861 self.assertTrue(isinstance(s3_type, Enum))
862 self.assertEqual(s3_type.name, 'mytag')
863
864 def test_multi_decls(self):
865 d1 = 'int a, b;'
866
867 self.assertEqual(self.get_decl(d1, 0),
868 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
869 self.assertEqual(self.get_decl(d1, 1),
870 ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
871
872 d2 = 'char* p, notp, ar[4];'
873 self.assertEqual(self.get_decl(d2, 0),
874 ['Decl', 'p',
875 ['PtrDecl',
876 ['TypeDecl', ['IdentifierType', ['char']]]]])
877 self.assertEqual(self.get_decl(d2, 1),
878 ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
879 self.assertEqual(self.get_decl(d2, 2),
880 ['Decl', 'ar',
881 ['ArrayDecl', '4',
882 ['TypeDecl', ['IdentifierType', ['char']]]]])
883
884 def test_invalid_multiple_types_error(self):
885 bad = [
886 'int enum {ab, cd} fubr;',
887 'enum kid char brbr;']
888
889 for b in bad:
890 self.assertRaises(ParseError, self.parse, b)
891
892 def test_decl_inits(self):
893 d1 = 'int a = 16;'
eli.benderskyf890a862010-10-30 12:13:23 +0200894 #~ self.parse(d1).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300895 self.assertEqual(self.get_decl(d1),
896 ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
897 self.assertEqual(self.get_decl_init(d1),
898 ['Constant', 'int', '16'])
899
900 d2 = 'long ar[] = {7, 8, 9};'
eli.benderskyf890a862010-10-30 12:13:23 +0200901 #~ self.parse(d2).show()
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300902 self.assertEqual(self.get_decl(d2),
903 ['Decl', 'ar',
904 ['ArrayDecl', '',
905 ['TypeDecl', ['IdentifierType', ['long']]]]])
906 self.assertEqual(self.get_decl_init(d2),
907 [ ['Constant', 'int', '7'],
908 ['Constant', 'int', '8'],
eli.benderskyf890a862010-10-30 12:13:23 +0200909 ['Constant', 'int', '9']])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300910
911 d3 = 'char p = j;'
912 self.assertEqual(self.get_decl(d3),
913 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
914 self.assertEqual(self.get_decl_init(d3),
915 ['ID', 'j'])
916
917 d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
918 self.assertEqual(self.get_decl(d4, 0),
919 ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
920 self.assertEqual(self.get_decl_init(d4, 0),
921 ['Constant', 'char', "'c'"])
922 self.assertEqual(self.get_decl(d4, 1),
923 ['Decl', 'p',
924 ['PtrDecl',
925 ['TypeDecl', ['IdentifierType', ['char']]]]])
eli.benderskyf890a862010-10-30 12:13:23 +0200926
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300927 self.assertEqual(self.get_decl_init(d4, 1),
928 [ ['Constant', 'int', '0'],
929 ['Constant', 'int', '1'],
930 ['Constant', 'int', '2'],
eli.benderskyf890a862010-10-30 12:13:23 +0200931 [['Constant', 'int', '4'],
932 ['Constant', 'int', '5']],
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300933 ['Constant', 'int', '6']])
eli.benderskyf890a862010-10-30 12:13:23 +0200934
935 def test_decl_named_inits(self):
936 d1 = 'int a = {.k = 16};'
937 self.assertEqual(self.get_decl_init(d1),
938 [( [['ID', 'k']],
939 ['Constant', 'int', '16'])])
940
941 d2 = 'int a = { [0].a = {1}, [1].a[0] = 2 };'
942 self.assertEqual(self.get_decl_init(d2),
943 [
944 ([['Constant', 'int', '0'], ['ID', 'a']],
945 [['Constant', 'int', '1']]),
946 ([['Constant', 'int', '1'], ['ID', 'a'], ['Constant', 'int', '0']],
947 ['Constant', 'int', '2'])])
948
949 d3 = 'int a = { .a = 1, .c = 3, 4, .b = 5};'
950 self.assertEqual(self.get_decl_init(d3),
951 [
952 ([['ID', 'a']], ['Constant', 'int', '1']),
953 ([['ID', 'c']], ['Constant', 'int', '3']),
954 ['Constant', 'int', '4'],
955 ([['ID', 'b']], ['Constant', 'int', '5'])])
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300956
957 def test_function_definitions(self):
958 def parse_fdef(str):
959 return self.parse(str).ext[0]
960
961 def fdef_decl(fdef):
962 return expand_decl(fdef.decl)
963
964 f1 = parse_fdef('''
965 int factorial(int p)
966 {
967 return 3;
968 }
969 ''')
970
971 self.assertEqual(fdef_decl(f1),
972 ['Decl', 'factorial',
973 ['FuncDecl',
974 [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]],
975 ['TypeDecl', ['IdentifierType', ['int']]]]])
976
eli.benderskyef29ff92010-10-29 16:25:43 +0200977 self.assertEqual(type(f1.body.block_items[0]), Return)
Eli Bendersky3921e8e2010-05-21 09:05:39 +0300978
979 f2 = parse_fdef('''
980 char* zzz(int p, char* c)
981 {
982 int a;
983 char b;
984
985 a = b + 2;
986 return 3;
987 }
988 ''')
989
990 self.assertEqual(fdef_decl(f2),
991 ['Decl', 'zzz',
992 ['FuncDecl',
993 [ ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]],
994 ['Decl', 'c', ['PtrDecl',
995 ['TypeDecl', ['IdentifierType', ['char']]]]]],
996 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
997
eli.benderskyef29ff92010-10-29 16:25:43 +0200998 self.assertEqual(list(map(type, f2.body.block_items)),
999 [Decl, Decl, Assignment, Return])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001000
1001 f3 = parse_fdef('''
1002 char* zzz(p, c)
1003 long p, *c;
1004 {
1005 int a;
1006 char b;
1007
1008 a = b + 2;
1009 return 3;
1010 }
1011 ''')
1012
1013 self.assertEqual(fdef_decl(f3),
1014 ['Decl', 'zzz',
1015 ['FuncDecl',
1016 [ ['ID', 'p'],
1017 ['ID', 'c']],
1018 ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
1019
eli.benderskyef29ff92010-10-29 16:25:43 +02001020 self.assertEqual(list(map(type, f3.body.block_items)),
1021 [Decl, Decl, Assignment, Return])
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001022
1023 self.assertEqual(expand_decl(f3.param_decls[0]),
1024 ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
1025 self.assertEqual(expand_decl(f3.param_decls[1]),
1026 ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
1027
eli.bendersky71540662010-07-03 12:58:52 +02001028 def test_unified_string_literals(self):
1029 # simple string, for reference
1030 d1 = self.get_decl_init('char* s = "hello";')
1031 self.assertEqual(d1, ['Constant', 'string', '"hello"'])
1032
1033 d2 = self.get_decl_init('char* s = "hello" " world";')
1034 self.assertEqual(d2, ['Constant', 'string', '"hello world"'])
1035
1036 # the test case from issue 6
1037 d3 = self.parse(r'''
1038 int main() {
1039 fprintf(stderr,
1040 "Wrong Params?\n"
1041 "Usage:\n"
1042 "%s <binary_file_path>\n",
1043 argv[0]
1044 );
1045 }
1046 ''')
1047
1048 self.assertEqual(
eli.benderskyef29ff92010-10-29 16:25:43 +02001049 d3.ext[0].body.block_items[0].args.exprs[1].value,
eli.bendersky71540662010-07-03 12:58:52 +02001050 r'"Wrong Params?\nUsage:\n%s <binary_file_path>\n"')
eli.bendersky4a89f112010-07-05 06:02:03 +02001051
1052 d4 = self.get_decl_init('char* s = "" "foobar";')
1053 self.assertEqual(d4, ['Constant', 'string', '"foobar"'])
1054
1055 d5 = self.get_decl_init(r'char* s = "foo\"" "bar";')
1056 self.assertEqual(d5, ['Constant', 'string', r'"foo\"bar"'])
eli.bendersky71540662010-07-03 12:58:52 +02001057
eli.bendersky79d5cf62010-10-29 13:33:52 +02001058 def test_inline_specifier(self):
1059 ps2 = self.parse('static inline void inlinefoo(void);')
1060 self.assertEqual(ps2.ext[0].funcspec, ['inline'])
eli.bendersky2e907fa2010-10-29 15:51:07 +02001061
1062 # variable length array
1063 def test_vla(self):
1064 ps2 = self.parse(r'''
1065 int main() {
1066 int size;
1067 int var[size = 5];
1068
1069 int var2[*];
1070 }
1071 ''')
eli.benderskyef29ff92010-10-29 16:25:43 +02001072 self.failUnless(isinstance(ps2.ext[0].body.block_items[1].type.dim, Assignment))
1073 self.failUnless(isinstance(ps2.ext[0].body.block_items[2].type.dim, ID))
eli.bendersky79d5cf62010-10-29 13:33:52 +02001074
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001075
1076class TestCParser_whole_code(unittest.TestCase):
1077 """ Testing of parsing whole chunks of code.
1078
1079 Since I don't want to rely on the structure of ASTs too
1080 much, most of these tests are implemented with visitors.
1081 """
1082 def parse(self, txt, filename=''):
1083 return self.cparser.parse(txt, filename)
1084
1085 def setUp(self):
1086 self.cparser = _c_parser
1087
1088 # A simple helper visitor that lists the values of all the
1089 # Constant nodes it sees.
1090 #
1091 class ConstantVisitor(NodeVisitor):
1092 def __init__(self):
1093 self.values = []
1094
1095 def visit_Constant(self, node):
1096 self.values.append(node.value)
1097
1098 # This visitor counts the amount of references to the ID
1099 # with the name provided to it in the constructor.
1100 #
1101 class IDNameCounter(NodeVisitor):
1102 def __init__(self, name):
1103 self.name = name
1104 self.nrefs = 0
1105
1106 def visit_ID(self, node):
1107 if node.name == self.name:
1108 self.nrefs += 1
1109
1110 # Counts the amount of nodes of a given class
1111 #
1112 class NodeKlassCounter(NodeVisitor):
1113 def __init__(self, node_klass):
1114 self.klass = node_klass
1115 self.n = 0
1116
1117 def generic_visit(self, node):
1118 if node.__class__ == self.klass:
1119 self.n += 1
1120
1121 NodeVisitor.generic_visit(self, node)
1122
1123 def assert_all_Constants(self, code, constants):
1124 """ Asserts that the list of all Constant values (by
1125 'preorder' appearance) in the chunk of code is as
1126 given.
1127 """
eli.benderskyed890492010-06-25 08:25:55 +03001128 if isinstance(code, str):
1129 parsed = self.parse(code)
1130 else:
1131 parsed = code
1132
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001133 cv = self.ConstantVisitor()
1134 cv.visit(parsed)
1135 self.assertEqual(cv.values, constants)
1136
1137 def assert_num_ID_refs(self, code, name, num):
1138 """ Asserts the number of references to the ID with
1139 the given name.
1140 """
1141 if isinstance(code, str):
1142 parsed = self.parse(code)
1143 else:
1144 parsed = code
1145
1146 iv = self.IDNameCounter(name)
1147 iv.visit(parsed)
1148 self.assertEqual(iv.nrefs, num)
1149
1150 def assert_num_klass_nodes(self, code, klass, num):
1151 """ Asserts the amount of klass nodes in the code.
1152 """
1153 if isinstance(code, str):
1154 parsed = self.parse(code)
1155 else:
1156 parsed = code
1157
1158 cv = self.NodeKlassCounter(klass)
1159 cv.visit(parsed)
1160 self.assertEqual(cv.n, num)
1161
1162 def test_expressions(self):
1163 e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
1164 self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
1165
1166 e2 = r'''char n = '\n', *prefix = "st_";'''
1167 self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
1168
1169 def test_statements(self):
1170 s1 = r'''
1171 void foo(){
1172 if (sp == 1)
1173 if (optind >= argc ||
1174 argv[optind][0] != '-' || argv[optind][1] == '\0')
1175 return -1;
1176 else if (strcmp(argv[optind], "--") == 0) {
1177 optind++;
1178 return -1;
1179 }
1180 }
1181 '''
1182
1183 self.assert_all_Constants(s1,
1184 ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
1185
1186 ps1 = self.parse(s1)
1187 self.assert_num_ID_refs(ps1, 'argv', 3)
1188 self.assert_num_ID_refs(ps1, 'optind', 5)
1189
1190 self.assert_num_klass_nodes(ps1, If, 3)
1191 self.assert_num_klass_nodes(ps1, Return, 2)
1192 self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
1193 self.assert_num_klass_nodes(ps1, BinaryOp, 7)
1194
1195 # In the following code, Hash and Node were defined as
1196 # int to pacify the parser that sees they're used as
1197 # types
1198 #
1199 s2 = r'''
1200 typedef int Hash, Node;
1201
1202 void HashDestroy(Hash* hash)
1203 {
1204 unsigned int i;
1205
1206 if (hash == NULL)
1207 return;
1208
1209 for (i = 0; i < hash->table_size; ++i)
1210 {
1211 Node* temp = hash->heads[i];
1212
1213 while (temp != NULL)
1214 {
1215 Node* temp2 = temp;
1216
1217 free(temp->entry->key);
1218 free(temp->entry->value);
1219 free(temp->entry);
1220
1221 temp = temp->next;
1222
1223 free(temp2);
1224 }
1225 }
1226
1227 free(hash->heads);
1228 hash->heads = NULL;
1229
1230 free(hash);
1231 }
1232 '''
1233
1234 ps2 = self.parse(s2)
1235 self.assert_num_klass_nodes(ps2, FuncCall, 6)
1236 self.assert_num_klass_nodes(ps2, FuncDef, 1)
1237 self.assert_num_klass_nodes(ps2, For, 1)
1238 self.assert_num_klass_nodes(ps2, While, 1)
1239 self.assert_num_klass_nodes(ps2, StructRef, 10)
1240
1241 # declarations don't count
1242 self.assert_num_ID_refs(ps2, 'hash', 6)
1243 self.assert_num_ID_refs(ps2, 'i', 4)
eli.benderskyed890492010-06-25 08:25:55 +03001244
1245 s3 = r'''
1246 void x(void) {
1247 int a, b;
1248 if (a < b)
1249 do {
1250 a = 0;
1251 } while (0);
1252 else if (a == b) {
1253 a = 1;
1254 }
1255 }
1256 '''
1257
1258 ps3 = self.parse(s3)
1259 self.assert_num_klass_nodes(ps3, DoWhile, 1)
1260 self.assert_num_ID_refs(ps3, 'a', 4)
1261 self.assert_all_Constants(ps3, ['0', '0', '1'])
eli.bendersky145890d2010-10-29 12:02:32 +02001262
1263 def test_for_statement(self):
1264 s2 = r'''
1265 void x(void)
1266 {
1267 int i;
1268 for (i = 0; i < 5; ++i) {
1269 x = 50;
1270 }
1271 }
1272 '''
1273 ps2 = self.parse(s2)
1274 self.assert_num_klass_nodes(ps2, For, 1)
1275 # here there are 3 refs to 'i' since the declaration doesn't count as
1276 # a ref in the visitor
1277 #
1278 self.assert_num_ID_refs(ps2, 'i', 3)
eli.benderskyed890492010-06-25 08:25:55 +03001279
eli.bendersky145890d2010-10-29 12:02:32 +02001280 s3 = r'''
1281 void x(void)
1282 {
1283 for (int i = 0; i < 5; ++i) {
1284 x = 50;
1285 }
1286 }
1287 '''
1288 ps3 = self.parse(s3)
eli.bendersky145890d2010-10-29 12:02:32 +02001289 self.assert_num_klass_nodes(ps3, For, 1)
1290 # here there are 2 refs to 'i' since the declaration doesn't count as
1291 # a ref in the visitor
1292 #
1293 self.assert_num_ID_refs(ps3, 'i', 2)
Eli Bendersky3921e8e2010-05-21 09:05:39 +03001294
1295 def test_whole_file(self):
1296 # See how pycparser handles a whole, real C file.
1297 #
1298 filename = 'c_files/memmgr_with_h.c'
1299 code = open(filename, 'rU').read()
1300 p = self.parse(code)
1301
1302 self.assert_num_klass_nodes(p, FuncDef, 5)
1303
1304 # each FuncDef also has a FuncDecl. 4 declarations
1305 # + 5 definitions, overall 9
1306 self.assert_num_klass_nodes(p, FuncDecl, 9)
1307
1308 self.assert_num_klass_nodes(p, Typedef, 4)
1309
1310 self.assertEqual(p.ext[4].coord.line, 88)
1311 self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
1312
1313 self.assertEqual(p.ext[6].coord.line, 10)
1314 self.assertEqual(p.ext[6].coord.file, "memmgr.c")
1315
1316 def test_whole_file_with_stdio(self):
1317 # Parse a whole file with stdio.h included by cpp
1318 #
1319 filename = 'c_files/cppd_with_stdio_h.c'
1320 code = open(filename, 'rU').read()
1321 p = self.parse(code)
1322
1323 self.failUnless(isinstance(p.ext[0], Typedef))
1324 self.assertEqual(p.ext[0].coord.line, 213)
1325 self.assertEqual(p.ext[0].coord.file, "D:\eli\cpp_stuff\libc_include/stddef.h")
1326
1327 self.failUnless(isinstance(p.ext[-1], FuncDef))
1328 self.assertEqual(p.ext[-1].coord.line, 15)
1329 self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
1330
1331 self.failUnless(isinstance(p.ext[-8], Typedef))
1332 self.failUnless(isinstance(p.ext[-8].type, TypeDecl))
1333 self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
1334
1335
1336if __name__ == '__main__':
1337 #~ suite = unittest.TestLoader().loadTestsFromNames(
1338 #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
1339
1340 #~ suite = unittest.TestLoader().loadTestsFromNames(
1341 #~ ['test_c_parser.TestCParser_whole_code.test_whole_file_with_stdio'])
1342
1343 #~ suite = unittest.TestLoader().loadTestsFromTestCase(
1344 #~ TestCParser_whole_code)
1345
1346 #~ unittest.TextTestRunner(verbosity=2).run(suite)
1347 unittest.main()