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