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()
+