initial import from SVN
diff --git a/examples/c_files/funky.c b/examples/c_files/funky.c new file mode 100644 index 0000000..252375f --- /dev/null +++ b/examples/c_files/funky.c
@@ -0,0 +1,20 @@ +char foo(void) +{ + return '1'; +} + +int maxout_in(int paste, char** matrix) +{ + char o = foo(); + return (int) matrix[1][2] * 5 - paste; +} + +int main() +{ + auto char* multi = "a multi"; + + +} + + +
diff --git a/examples/c_files/hash.c b/examples/c_files/hash.c new file mode 100644 index 0000000..7ec500e --- /dev/null +++ b/examples/c_files/hash.c
@@ -0,0 +1,200 @@ +/* +** C implementation of a hash table ADT +*/ +typedef enum tagReturnCode {SUCCESS, FAIL} ReturnCode; + + +typedef struct tagEntry +{ + char* key; + char* value; +} Entry; + + + +typedef struct tagNode +{ + Entry* entry; + + struct tagNode* next; +} Node; + + +typedef struct tagHash +{ + unsigned int table_size; + + Node** heads; + +} Hash; + + +static unsigned int hash_func(const char* str, unsigned int table_size) +{ + unsigned int hash_value; + unsigned int a = 127; + + for (hash_value = 0; *str != 0; ++str) + hash_value = (a*hash_value + *str) % table_size; + + return hash_value; +} + + +ReturnCode HashCreate(Hash** hash, unsigned int table_size) +{ + unsigned int i; + + if (table_size < 1) + return FAIL; + + // + // Allocate space for the Hash + // + if (((*hash) = malloc(sizeof(**hash))) == NULL) + return FAIL; + + // + // Allocate space for the array of list heads + // + if (((*hash)->heads = malloc(table_size*sizeof(*((*hash)->heads)))) == NULL) + return FAIL; + + // + // Initialize Hash info + // + for (i = 0; i < table_size; ++i) + { + (*hash)->heads[i] = NULL; + } + + (*hash)->table_size = table_size; + + return SUCCESS; +} + + +ReturnCode HashInsert(Hash* hash, const Entry* entry) +{ + unsigned int index = hash_func(entry->key, hash->table_size); + Node* temp = hash->heads[index]; + + HashRemove(hash, entry->key); + + if ((hash->heads[index] = malloc(sizeof(Node))) == NULL) + return FAIL; + + hash->heads[index]->entry = malloc(sizeof(Entry)); + hash->heads[index]->entry->key = malloc(strlen(entry->key)+1); + hash->heads[index]->entry->value = malloc(strlen(entry->value)+1); + strcpy(hash->heads[index]->entry->key, entry->key); + strcpy(hash->heads[index]->entry->value, entry->value); + + hash->heads[index]->next = temp; + + return SUCCESS; +} + + + +const Entry* HashFind(const Hash* hash, const char* key) +{ + unsigned int index = hash_func(key, hash->table_size); + Node* temp = hash->heads[index]; + + while (temp != NULL) + { + if (!strcmp(key, temp->entry->key)) + return temp->entry; + + temp = temp->next; + } + + return NULL; +} + + +ReturnCode HashRemove(Hash* hash, const char* key) +{ + unsigned int index = hash_func(key, hash->table_size); + Node* temp1 = hash->heads[index]; + Node* temp2 = temp1; + + while (temp1 != NULL) + { + if (!strcmp(key, temp1->entry->key)) + { + if (temp1 == hash->heads[index]) + hash->heads[index] = hash->heads[index]->next; + else + temp2->next = temp1->next; + + free(temp1->entry->key); + free(temp1->entry->value); + free(temp1->entry); + free(temp1); + temp1 = NULL; + + return SUCCESS; + } + + temp2 = temp1; + temp1 = temp1->next; + } + + return FAIL; +} + + +void HashPrint(Hash* hash, void (*PrintFunc)(char*, char*)) +{ + unsigned int i; + + if (hash == NULL || hash->heads == NULL) + return; + + for (i = 0; i < hash->table_size; ++i) + { + Node* temp = hash->heads[i]; + + while (temp != NULL) + { + PrintFunc(temp->entry->key, temp->entry->value); + temp = temp->next; + } + } +} + + + +void HashDestroy(Hash* hash) +{ + unsigned int i; + + if (hash == NULL) + return; + + for (i = 0; i < hash->table_size; ++i) + { + Node* temp = hash->heads[i]; + + while (temp != NULL) + { + Node* temp2 = temp; + + free(temp->entry->key); + free(temp->entry->value); + free(temp->entry); + + temp = temp->next; + + free(temp2); + } + } + + free(hash->heads); + hash->heads = NULL; + + free(hash); +} +
diff --git a/examples/c_files/memmgr.c b/examples/c_files/memmgr.c new file mode 100644 index 0000000..6036ec6 --- /dev/null +++ b/examples/c_files/memmgr.c
@@ -0,0 +1,206 @@ +//---------------------------------------------------------------- +// Statically-allocated memory manager +// +// by Eli Bendersky ([email protected]) +// +// This code is in the public domain. +//---------------------------------------------------------------- +#include "memmgr.h" + +typedef ulong Align; + +union mem_header_union +{ + struct + { + // Pointer to the next block in the free list + // + union mem_header_union* next; + + // Size of the block (in quantas of sizeof(mem_header_t)) + // + ulong size; + } s; + + // Used to align headers in memory to a boundary + // + Align align_dummy; +}; + +typedef union mem_header_union mem_header_t; + +// Initial empty list +// +static mem_header_t base; + +// Start of free list +// +static mem_header_t* freep = 0; + +// Static pool for new allocations +// +static byte pool[POOL_SIZE] = {0}; +static ulong pool_free_pos = 0; + + +void memmgr_init() +{ + base.s.next = 0; + base.s.size = 0; + freep = 0; + pool_free_pos = 0; +} + + +static mem_header_t* get_mem_from_pool(ulong nquantas) +{ + ulong total_req_size; + + mem_header_t* h; + + if (nquantas < MIN_POOL_ALLOC_QUANTAS) + nquantas = MIN_POOL_ALLOC_QUANTAS; + + total_req_size = nquantas * sizeof(mem_header_t); + + if (pool_free_pos + total_req_size <= POOL_SIZE) + { + h = (mem_header_t*) (pool + pool_free_pos); + h->s.size = nquantas; + memmgr_free((void*) (h + 1)); + pool_free_pos += total_req_size; + } + else + { + return 0; + } + + return freep; +} + + +// Allocations are done in 'quantas' of header size. +// The search for a free block of adequate size begins at the point 'freep' +// where the last block was found. +// If a too-big block is found, it is split and the tail is returned (this +// way the header of the original needs only to have its size adjusted). +// The pointer returned to the user points to the free space within the block, +// which begins one quanta after the header. +// +void* memmgr_alloc(ulong nbytes) +{ + mem_header_t* p; + mem_header_t* prevp; + + // Calculate how many quantas are required: we need enough to house all + // the requested bytes, plus the header. The -1 and +1 are there to make sure + // that if nbytes is a multiple of nquantas, we don't allocate too much + // + ulong nquantas = (nbytes + sizeof(mem_header_t) - 1) / sizeof(mem_header_t) + 1; + + // First alloc call, and no free list yet ? Use 'base' for an initial + // denegerate block of size 0, which points to itself + // + if ((prevp = freep) == 0) + { + base.s.next = freep = prevp = &base; + base.s.size = 0; + } + + for (p = prevp->s.next; ; prevp = p, p = p->s.next) + { + // big enough ? + if (p->s.size >= nquantas) + { + // exactly ? + if (p->s.size == nquantas) + { + // just eliminate this block from the free list by pointing + // its prev's next to its next + // + prevp->s.next = p->s.next; + } + else // too big + { + p->s.size -= nquantas; + p += p->s.size; + p->s.size = nquantas; + } + + freep = prevp; + return (void*) (p + 1); + } + // Reached end of free list ? + // Try to allocate the block from the pool. If that succeeds, + // get_mem_from_pool adds the new block to the free list and + // it will be found in the following iterations. If the call + // to get_mem_from_pool doesn't succeed, we've run out of + // memory + // + else if (p == freep) + { + if ((p = get_mem_from_pool(nquantas)) == 0) + { + #ifdef DEBUG_MEMMGR_FATAL + printf("!! Memory allocation failed !!\n"); + #endif + return 0; + } + } + } +} + + +// Scans the free list, starting at freep, looking the the place to insert the +// free block. This is either between two existing blocks or at the end of the +// list. In any case, if the block being freed is adjacent to either neighbor, +// the adjacent blocks are combined. +// +void memmgr_free(void* ap) +{ + mem_header_t* block; + mem_header_t* p; + + // acquire pointer to block header + block = ((mem_header_t*) ap) - 1; + + // Find the correct place to place the block in (the free list is sorted by + // address, increasing order) + // + for (p = freep; !(block > p && block < p->s.next); p = p->s.next) + { + // Since the free list is circular, there is one link where a + // higher-addressed block points to a lower-addressed block. + // This condition checks if the block should be actually + // inserted between them + // + if (p >= p->s.next && (block > p || block < p->s.next)) + break; + } + + // Try to combine with the higher neighbor + // + if (block + block->s.size == p->s.next) + { + block->s.size += p->s.next->s.size; + block->s.next = p->s.next->s.next; + } + else + { + block->s.next = p->s.next; + } + + // Try to combine with the lower neighbor + // + if (p + p->s.size == block) + { + p->s.size += block->s.size; + p->s.next = block->s.next; + } + else + { + p->s.next = block; + } + + freep = p; +}
diff --git a/examples/c_files/memmgr.h b/examples/c_files/memmgr.h new file mode 100644 index 0000000..ae8212d --- /dev/null +++ b/examples/c_files/memmgr.h
@@ -0,0 +1,96 @@ +//---------------------------------------------------------------- +// Statically-allocated memory manager +// +// by Eli Bendersky ([email protected]) +// +// This code is in the public domain. +//---------------------------------------------------------------- +#ifndef MEMMGR_H +#define MEMMGR_H + +// +// Memory manager: dynamically allocates memory from +// a fixed pool that is allocated statically at link-time. +// +// Usage: after calling memmgr_init() in your +// initialization routine, just use memmgr_alloc() instead +// of malloc() and memmgr_free() instead of free(). +// Naturally, you can use the preprocessor to define +// malloc() and free() as aliases to memmgr_alloc() and +// memmgr_free(). This way the manager will be a drop-in +// replacement for the standard C library allocators, and can +// be useful for debugging memory allocation problems and +// leaks. +// +// Preprocessor flags you can define to customize the +// memory manager: +// +// DEBUG_MEMMGR_FATAL +// Allow printing out a message when allocations fail +// +// DEBUG_MEMMGR_SUPPORT_STATS +// Allow printing out of stats in function +// memmgr_print_stats When this is disabled, +// memmgr_print_stats does nothing. +// +// Note that in production code on an embedded system +// you'll probably want to keep those undefined, because +// they cause printf to be called. +// +// POOL_SIZE +// Size of the pool for new allocations. This is +// effectively the heap size of the application, and can +// be changed in accordance with the available memory +// resources. +// +// MIN_POOL_ALLOC_QUANTAS +// Internally, the memory manager allocates memory in +// quantas roughly the size of two ulong objects. To +// minimize pool fragmentation in case of multiple allocations +// and deallocations, it is advisable to not allocate +// blocks that are too small. +// This flag sets the minimal ammount of quantas for +// an allocation. If the size of a ulong is 4 and you +// set this flag to 16, the minimal size of an allocation +// will be 4 * 2 * 16 = 128 bytes +// If you have a lot of small allocations, keep this value +// low to conserve memory. If you have mostly large +// allocations, it is best to make it higher, to avoid +// fragmentation. +// +// Notes: +// 1. This memory manager is *not thread safe*. Use it only +// for single thread/task applications. +// + +#define DEBUG_MEMMGR_SUPPORT_STATS 1 + +#define POOL_SIZE 8 * 1024 +#define MIN_POOL_ALLOC_QUANTAS 16 + + +typedef unsigned char byte; +typedef unsigned long ulong; + + + +// Initialize the memory manager. This function should be called +// only once in the beginning of the program. +// +void memmgr_init(); + +// 'malloc' clone +// +void* memmgr_alloc(ulong nbytes); + +// 'free' clone +// +void memmgr_free(void* ap); + +// Prints statistics about the current state of the memory +// manager +// +void memmgr_print_stats(); + + +#endif // MEMMGR_H
diff --git a/examples/c_files/year.c b/examples/c_files/year.c new file mode 100644 index 0000000..c0f583d --- /dev/null +++ b/examples/c_files/year.c
@@ -0,0 +1,53 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +void convert(int thousands, int hundreds, int tens, int ones) +{ +char *num[] = {"", "One", "Two", "Three", "Four", "Five", "Six", + "Seven", "Eight", "Nine"}; + +char *for_ten[] = {"", "", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty", + "Seventy", "Eighty", "Ninty"}; + +char *af_ten[] = {"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", + "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Ninteen"}; + + printf("\nThe year in words is:\n"); + + printf("%s thousand", num[thousands]); + if (hundreds != 0) + printf(" %s hundred", num[hundreds]); + + if (tens != 1) + printf(" %s %s", for_ten[tens], num[ones]); + else + printf(" %s", af_ten[ones]); +} + + +int main() +{ +int year; +int n1000, n100, n10, n1; + + printf("\nEnter the year (4 digits): "); + scanf("%d", &year); + + if (year > 9999 || year < 1000) + { + printf("\nError !! The year must contain 4 digits."); + exit(EXIT_FAILURE); + } + + n1000 = year/1000; + n100 = ((year)%1000)/100; + n10 = (year%100)/10; + n1 = ((year%10)%10); + + convert(n1000, n100, n10, n1); + +return 0; +} + +
diff --git a/examples/cdecl.py b/examples/cdecl.py new file mode 100644 index 0000000..1db5149 --- /dev/null +++ b/examples/cdecl.py
@@ -0,0 +1,108 @@ +#----------------------------------------------------------------- +# pycparser: cdecl.py +# +# Example of the CDECL tool using pycparser. CDECL "explains" +# C type declarations in plain English. +# +# The AST generated by pycparser from the given declaration is +# traversed recursively to build the explanation. +# Note that the declaration must be a valid external declaration +# in C. All the types used in it must be defined with typedef, +# or parsing will fail. The definition can be arbitrary, it isn't +# really used - by pycparser must know which tokens are types. +# +# For example: +# +# 'typedef int Node; const Node* (*ar)[10];' +# => +# ar is a pointer to array[10] of pointer to const Node +# +# Copyright (C) 2008, Eli Bendersky +# License: LGPL +#----------------------------------------------------------------- +import sys + +# This is not required if you've installed pycparser into +# your site-packages/ with setup.py +# +sys.path.insert(0, '..') + +from pycparser import c_parser, c_ast +from pycparser.portability import printme + + +def explain_c_declaration(c_decl): + """ Parses the declaration in c_decl and returns a text + explanation as a string. + + The last external node of the string is used, to allow + earlier typedefs for used types. + """ + parser = c_parser.CParser() + + try: + node = parser.parse(c_decl, filename='<stdin>') + except c_parser.ParseError: + e = sys.exc_info()[1] + return "Parse error:" + str(e) + + if ( not isinstance(node, c_ast.FileAST) or + not isinstance(node.ext[-1], c_ast.Decl)): + return "Not a valid declaration" + + return _explain_decl_node(node.ext[-1]) + + +def _explain_decl_node(decl_node): + """ Receives a c_ast.Decl note and returns its explanation in + English. + """ + #~ print decl_node.show() + storage = ' '.join(decl_node.storage) + ' ' if decl_node.storage else '' + + return (decl_node.name + + " is a " + + storage + + _explain_type(decl_node.type)) + + +def _explain_type(decl): + """ Recursively explains a type decl node + """ + typ = type(decl) + + if typ == c_ast.TypeDecl: + quals = ' '.join(decl.quals) + ' ' if decl.quals else '' + return quals + _explain_type(decl.type) + elif typ == c_ast.Typename or typ == c_ast.Decl: + return _explain_type(decl.type) + elif typ == c_ast.IdentifierType: + return ' '.join(decl.names) + elif typ == c_ast.PtrDecl: + quals = ' '.join(decl.quals) + ' ' if decl.quals else '' + return quals + 'pointer to ' + _explain_type(decl.type) + elif typ == c_ast.ArrayDecl: + arr = 'array' + if decl.dim: arr += '[%s]' % decl.dim.value + + return arr + " of " + _explain_type(decl.type) + + elif typ == c_ast.FuncDecl: + if decl.args: + params = [_explain_type(param) for param in decl.args.params] + args = ', '.join(params) + else: + args = '' + + return ('function(%s) returning ' % (args) + + _explain_type(decl.type)) + + +if __name__ == "__main__": + if len(sys.argv) > 1: + c_decl = sys.argv[1] + else: + c_decl = "char *(*(**foo[][8])())[];" + + printme(["Explaining the declaration:", c_decl]) + printme(["\n", explain_c_declaration(c_decl)])
diff --git a/examples/explore_ast.py b/examples/explore_ast.py new file mode 100644 index 0000000..7daf15b --- /dev/null +++ b/examples/explore_ast.py
@@ -0,0 +1,153 @@ +#----------------------------------------------------------------- +# pycparser: explore_ast.py +# +# This example demonstrates how to "explore" the AST created by +# pycparser to understand its structure. The AST is a n-nary tree +# of nodes, each node having several children, each with a name. +# Just read the code, and let the comments guide you. The lines +# beginning with #~ can be uncommented to print out useful +# information from the AST. +# It helps to have the _c_ast.yaml file in front of you. +# +# Copyright (C) 2008, Eli Bendersky +# License: LGPL +#----------------------------------------------------------------- +import sys + +# This is not required if you've installed pycparser into +# your site-packages/ with setup.py +# +sys.path.insert(0, '..') + +from pycparser import c_parser, c_ast + +# This is some C source to parse. Note that pycparser must begin +# at the top level of the C file, i.e. with either declarations +# or function definitions (this is called "external declarations" +# in C grammar lingo) +# +# Also, a C parser must have all the types declared in order to +# build the correct AST. It doesn't matter what they're declared +# to, so I've inserted the dummy typedef in the code to let the +# parser know Hash and Node are types. You don't need to do it +# when parsing real, correct C code. +# +text = r""" + typedef int Node, Hash; + + void HashPrint(Hash* hash, void (*PrintFunc)(char*, char*)) + { + unsigned int i; + + if (hash == NULL || hash->heads == NULL) + return; + + for (i = 0; i < hash->table_size; ++i) + { + Node* temp = hash->heads[i]; + + while (temp != NULL) + { + PrintFunc(temp->entry->key, temp->entry->value); + temp = temp->next; + } + } + } +""" + +# Create the parser and ask to parse the text. parse() will throw +# a ParseError if there's an error in the code +# +parser = c_parser.CParser() +ast = parser.parse(text, filename='<none>') + +# Uncomment the following line to see the AST in a nice, human +# readable way. show() is the most useful tool in exploring ASTs +# created by pycparser. See the c_ast.py file for the options you +# can pass it. +# +#~ ast.show() + +# OK, we've seen that the top node is FileAST. This is always the +# top node of the AST. Its children are "external declarations", +# and are stored in a list called ext[] (see _c_ast.yaml for the +# names and types of Nodes and their children). +# As you see from the printout, our AST has two Typedef children +# and one FuncDef child. +# Let's explore FuncDef more closely. As I've mentioned, the list +# ext[] holds the children of FileAST. Since the function +# definition is the third child, it's ext[2]. Uncomment the +# following line to show it: +# +#~ ast.ext[2].show() + +# A FuncDef consists of a declaration, a list of parameter +# declarations (for K&R style function definitions), and a body. +# Let's focus on the body for this example. The body is of +# type Compound, which is a placeholder for a block surrounded +# by {} (You should be reading _c_ast.yaml parallel to this +# explanation and seeing these things by your own eyes). +# +# Let's see the block's declarations: +# +function_body = ast.ext[2].body + +# The following displays the variable declarations in the function +# body +# +#~ for decl in function_body.decls: + #~ decl.show() + +# We can see a single variable, i, declared to be a simple type +# declaration of type 'unsigned int'. +# +# Let's look at the statemts now: +# +#~ for stmt in function_body.stmts: + #~ stmt.show() + +# stmts is a list, so the second element is the For statement: +# +for_stmt = function_body.stmts[1] +#~ for_stmt.show() + +# As you can see in _c_ast.yaml, For's children are 'init, cond, +# next' for the respective parts of the 'for' loop specifier, +# and stmt, which is either a single stmt or a Compound if there's +# a block. +# +# Let's dig deeper, to the while statement inside the for loop: +# +while_stmt = for_stmt.stmt.stmts[0] +#~ while_stmt.show() + +# While is simpler, it only has a condition node and a stmt node. +# The condition: +# +while_cond = while_stmt.cond +#~ while_cond.show() + +# Note that it's a BinaryOp node - the basic constituent of +# expressions in our AST. BinaryOp is the expression tree, with +# left and right nodes as children. It also has the op attribute, +# which is just the string representation of the operator. +# +#~ print while_cond.op +#~ while_cond.left.show() +#~ while_cond.right.show() + +# +# That's if for the example. I hope you now see how easy it is to +# explore the AST created by pycparser. Although on the surface it +# is quite complex and has a lot of node types, this is the +# inherent complexity of the C language every parser/compiler +# designer has to cope with. +# Using the tools provided by the c_ast package it's easy to +# explore the structure of AST nodes and write code that processes +# them. +# Specifically, see the cdecl.py example for a non-trivial +# demonstration of what you can do by recursively going through +# the AST. +# + +
diff --git a/examples/func_calls.py b/examples/func_calls.py new file mode 100644 index 0000000..eaa3a67 --- /dev/null +++ b/examples/func_calls.py
@@ -0,0 +1,51 @@ +#----------------------------------------------------------------- +# pycparser: func_defs.py +# +# Using pycparser for printing out all the calls of some function +# in a C file. +# +# Copyright (C) 2008, Eli Bendersky +# License: LGPL +#----------------------------------------------------------------- +import sys + +# This is not required if you've installed pycparser into +# your site-packages/ with setup.py +# +sys.path.insert(0, '..') + +from pycparser import c_parser, c_ast, parse_file +from pycparser.portability import printme + + +# A visitor with some state information (the funcname it's +# looking for) +# +class FuncCallVisitor(c_ast.NodeVisitor): + def __init__(self, funcname): + self.funcname = funcname + + def visit_FuncCall(self, node): + if node.name.name == self.funcname: + printme('%s called at %s\n' % ( + self.funcname, node.name.coord)) + + +def show_func_calls(filename, funcname): + ast = parse_file(filename, use_cpp=True) + v = FuncCallVisitor(funcname) + v.visit(ast) + + +if __name__ == "__main__": + if len(sys.argv) > 2: + filename = sys.argv[1] + func = sys.argv[2] + else: + filename = 'c_files/hash.c' + func = 'malloc' + + show_func_calls(filename, func) + + +
diff --git a/examples/func_defs.py b/examples/func_defs.py new file mode 100644 index 0000000..fa15b38 --- /dev/null +++ b/examples/func_defs.py
@@ -0,0 +1,51 @@ +#----------------------------------------------------------------- +# pycparser: func_defs.py +# +# Using pycparser for printing out all the functions defined in a +# C file. +# +# This is a simple example of traversing the AST generated by +# pycparser. +# +# Copyright (C) 2008-2009, Eli Bendersky +# License: LGPL +#----------------------------------------------------------------- +import sys + +# This is not required if you've installed pycparser into +# your site-packages/ with setup.py +# +sys.path.insert(0, '..') + +from pycparser import c_parser, c_ast, parse_file +from pycparser.portability import printme + + +# A simple visitor for FuncDef nodes that prints the names and +# locations of function definitions. +# +class FuncDefVisitor(c_ast.NodeVisitor): + def visit_FuncDef(self, node): + printme('%s at %s\n' % (node.decl.name, node.decl.coord)) + + +def show_func_defs(filename): + # Note that cpp is used. Provide a path to your own cpp or + # make sure one exists in PATH. + # + ast = parse_file(filename, use_cpp=True) + + v = FuncDefVisitor() + v.visit(ast) + + +if __name__ == "__main__": + if len(sys.argv) > 1: + filename = sys.argv[1] + else: + filename = 'c_files/memmgr.c' + + show_func_defs(filename) + + +
diff --git a/examples/using_cpp_libc.py b/examples/using_cpp_libc.py new file mode 100644 index 0000000..e7c5daa --- /dev/null +++ b/examples/using_cpp_libc.py
@@ -0,0 +1,35 @@ +#----------------------------------------------------------------- +# pycparser: use_cpp_libc.py +# +# Shows how to use the provided 'cpp' (on Windows, substitute for +# the 'real' cpp if you're on Linux/Unix) and "fake" libc includes +# to parse a file that includes standard C headers. +# +# Copyright (C) 2008-2009, Eli Bendersky +# License: LGPL +#----------------------------------------------------------------- +import sys + +# This is not required if you've installed pycparser into +# your site-packages/ with setup.py +# +sys.path.insert(0, '..') + +# Portable cpp path for Windows and Linux/Unix +CPPPATH = '../utils/cpp.exe' if sys.platform == 'win32' else 'cpp' + +from pycparser import parse_file + + +if __name__ == "__main__": + if len(sys.argv) > 1: + filename = sys.argv[1] + else: + filename = 'c_files/year.c' + + ast = parse_file(filename, use_cpp=True, + cpp_path=CPPPATH, + cpp_args=r'-I../utils/fake_libc_include') + + ast.show() +