initial import from SVN
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..22fa7fb
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,9 @@
+recursive-include examples *.c *.h *.py

+recursive-include tests *.c *.h *.py

+recursive-include pycparser *.py *.yaml

+include utils/*.exe

+include utils/fake_libc_include/*.h

+include README.*

+include setup.*

+

+prune tests/yacctab.*

diff --git a/README.html b/README.html
new file mode 100644
index 0000000..279ff59
--- /dev/null
+++ b/README.html
@@ -0,0 +1,532 @@
+<?xml version="1.0" encoding="utf-8" ?>

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

+<head>

+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

+<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />

+<title>pycparser v1.06</title>

+<meta name="author" content="Eli Bendersky" />

+<style type="text/css">

+

+/*

+:Author: David Goodger (goodger@python.org)

+:Id: $Id: html4css1.css 5951 2009-05-18 18:03:10Z milde $

+:Copyright: This stylesheet has been placed in the public domain.

+

+Default cascading style sheet for the HTML output of Docutils.

+

+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to

+customize this style sheet.

+*/

+

+/* used to remove borders from tables and images */

+.borderless, table.borderless td, table.borderless th {

+  border: 0 }

+

+table.borderless td, table.borderless th {

+  /* Override padding for "table.docutils td" with "! important".

+     The right padding separates the table cells. */

+  padding: 0 0.5em 0 0 ! important }

+

+.first {

+  /* Override more specific margin styles with "! important". */

+  margin-top: 0 ! important }

+

+.last, .with-subtitle {

+  margin-bottom: 0 ! important }

+

+.hidden {

+  display: none }

+

+a.toc-backref {

+  text-decoration: none ;

+  color: black }

+

+blockquote.epigraph {

+  margin: 2em 5em ; }

+

+dl.docutils dd {

+  margin-bottom: 0.5em }

+

+/* Uncomment (and remove this text!) to get bold-faced definition list terms

+dl.docutils dt {

+  font-weight: bold }

+*/

+

+div.abstract {

+  margin: 2em 5em }

+

+div.abstract p.topic-title {

+  font-weight: bold ;

+  text-align: center }

+

+div.admonition, div.attention, div.caution, div.danger, div.error,

+div.hint, div.important, div.note, div.tip, div.warning {

+  margin: 2em ;

+  border: medium outset ;

+  padding: 1em }

+

+div.admonition p.admonition-title, div.hint p.admonition-title,

+div.important p.admonition-title, div.note p.admonition-title,

+div.tip p.admonition-title {

+  font-weight: bold ;

+  font-family: sans-serif }

+

+div.attention p.admonition-title, div.caution p.admonition-title,

+div.danger p.admonition-title, div.error p.admonition-title,

+div.warning p.admonition-title {

+  color: red ;

+  font-weight: bold ;

+  font-family: sans-serif }

+

+/* Uncomment (and remove this text!) to get reduced vertical space in

+   compound paragraphs.

+div.compound .compound-first, div.compound .compound-middle {

+  margin-bottom: 0.5em }

+

+div.compound .compound-last, div.compound .compound-middle {

+  margin-top: 0.5em }

+*/

+

+div.dedication {

+  margin: 2em 5em ;

+  text-align: center ;

+  font-style: italic }

+

+div.dedication p.topic-title {

+  font-weight: bold ;

+  font-style: normal }

+

+div.figure {

+  margin-left: 2em ;

+  margin-right: 2em }

+

+div.footer, div.header {

+  clear: both;

+  font-size: smaller }

+

+div.line-block {

+  display: block ;

+  margin-top: 1em ;

+  margin-bottom: 1em }

+

+div.line-block div.line-block {

+  margin-top: 0 ;

+  margin-bottom: 0 ;

+  margin-left: 1.5em }

+

+div.sidebar {

+  margin: 0 0 0.5em 1em ;

+  border: medium outset ;

+  padding: 1em ;

+  background-color: #ffffee ;

+  width: 40% ;

+  float: right ;

+  clear: right }

+

+div.sidebar p.rubric {

+  font-family: sans-serif ;

+  font-size: medium }

+

+div.system-messages {

+  margin: 5em }

+

+div.system-messages h1 {

+  color: red }

+

+div.system-message {

+  border: medium outset ;

+  padding: 1em }

+

+div.system-message p.system-message-title {

+  color: red ;

+  font-weight: bold }

+

+div.topic {

+  margin: 2em }

+

+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,

+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {

+  margin-top: 0.4em }

+

+h1.title {

+  text-align: center }

+

+h2.subtitle {

+  text-align: center }

+

+hr.docutils {

+  width: 75% }

+

+img.align-left, .figure.align-left{

+  clear: left ;

+  float: left ;

+  margin-right: 1em }

+

+img.align-right, .figure.align-right {

+  clear: right ;

+  float: right ;

+  margin-left: 1em }

+

+.align-left {

+  text-align: left }

+

+.align-center {

+  clear: both ;

+  text-align: center }

+

+.align-right {

+  text-align: right }

+

+/* reset inner alignment in figures */

+div.align-right {

+  text-align: left }

+

+/* div.align-center * { */

+/*   text-align: left } */

+

+ol.simple, ul.simple {

+  margin-bottom: 1em }

+

+ol.arabic {

+  list-style: decimal }

+

+ol.loweralpha {

+  list-style: lower-alpha }

+

+ol.upperalpha {

+  list-style: upper-alpha }

+

+ol.lowerroman {

+  list-style: lower-roman }

+

+ol.upperroman {

+  list-style: upper-roman }

+

+p.attribution {

+  text-align: right ;

+  margin-left: 50% }

+

+p.caption {

+  font-style: italic }

+

+p.credits {

+  font-style: italic ;

+  font-size: smaller }

+

+p.label {

+  white-space: nowrap }

+

+p.rubric {

+  font-weight: bold ;

+  font-size: larger ;

+  color: maroon ;

+  text-align: center }

+

+p.sidebar-title {

+  font-family: sans-serif ;

+  font-weight: bold ;

+  font-size: larger }

+

+p.sidebar-subtitle {

+  font-family: sans-serif ;

+  font-weight: bold }

+

+p.topic-title {

+  font-weight: bold }

+

+pre.address {

+  margin-bottom: 0 ;

+  margin-top: 0 ;

+  font: inherit }

+

+pre.literal-block, pre.doctest-block {

+  margin-left: 2em ;

+  margin-right: 2em }

+

+span.classifier {

+  font-family: sans-serif ;

+  font-style: oblique }

+

+span.classifier-delimiter {

+  font-family: sans-serif ;

+  font-weight: bold }

+

+span.interpreted {

+  font-family: sans-serif }

+

+span.option {

+  white-space: nowrap }

+

+span.pre {

+  white-space: pre }

+

+span.problematic {

+  color: red }

+

+span.section-subtitle {

+  /* font-size relative to parent (h1..h6 element) */

+  font-size: 80% }

+

+table.citation {

+  border-left: solid 1px gray;

+  margin-left: 1px }

+

+table.docinfo {

+  margin: 2em 4em }

+

+table.docutils {

+  margin-top: 0.5em ;

+  margin-bottom: 0.5em }

+

+table.footnote {

+  border-left: solid 1px black;

+  margin-left: 1px }

+

+table.docutils td, table.docutils th,

+table.docinfo td, table.docinfo th {

+  padding-left: 0.5em ;

+  padding-right: 0.5em ;

+  vertical-align: top }

+

+table.docutils th.field-name, table.docinfo th.docinfo-name {

+  font-weight: bold ;

+  text-align: left ;

+  white-space: nowrap ;

+  padding-left: 0 }

+

+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,

+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {

+  font-size: 100% }

+

+ul.auto-toc {

+  list-style-type: none }

+

+</style>

+</head>

+<body>

+<div class="document" id="pycparser-v1-06">

+<h1 class="title">pycparser v1.06</h1>

+<table class="docinfo" frame="void" rules="none">

+<col class="docinfo-name" />

+<col class="docinfo-content" />

+<tbody valign="top">

+<tr><th class="docinfo-name">Author:</th>

+<td><a class="first reference external" href="http://eli.thegreenplace.net">Eli Bendersky</a></td></tr>

+</tbody>

+</table>

+<div class="contents topic" id="contents">

+<p class="topic-title first">Contents</p>

+<ul class="simple">

+<li><a class="reference internal" href="#introduction" id="id1">Introduction</a><ul>

+<li><a class="reference internal" href="#what-is-pycparser" id="id2">What is pycparser?</a></li>

+<li><a class="reference internal" href="#what-is-it-good-for" id="id3">What is it good for?</a></li>

+<li><a class="reference internal" href="#which-version-of-c-does-pycparser-support" id="id4">Which version of C does pycparser support?</a></li>

+<li><a class="reference internal" href="#what-grammar-does-pycparser-follow" id="id5">What grammar does pycparser follow?</a></li>

+<li><a class="reference internal" href="#what-is-an-ast" id="id6">What is an AST?</a></li>

+<li><a class="reference internal" href="#how-is-pycparser-licensed" id="id7">How is pycparser licensed?</a></li>

+<li><a class="reference internal" href="#contact-details" id="id8">Contact details</a></li>

+</ul>

+</li>

+<li><a class="reference internal" href="#installing" id="id9">Installing</a><ul>

+<li><a class="reference internal" href="#prerequisites" id="id10">Prerequisites</a></li>

+<li><a class="reference internal" href="#installation-process" id="id11">Installation process</a></li>

+</ul>

+</li>

+<li><a class="reference internal" href="#using" id="id12">Using</a><ul>

+<li><a class="reference internal" href="#interaction-with-the-c-preprocessor" id="id13">Interaction with the C preprocessor</a></li>

+<li><a class="reference internal" href="#what-about-the-standard-c-library-headers" id="id14">What about the standard C library headers?</a></li>

+<li><a class="reference internal" href="#basic-usage" id="id15">Basic usage</a></li>

+<li><a class="reference internal" href="#advanced-usage" id="id16">Advanced usage</a></li>

+</ul>

+</li>

+<li><a class="reference internal" href="#modifying" id="id17">Modifying</a></li>

+<li><a class="reference internal" href="#package-contents" id="id18">Package contents</a></li>

+<li><a class="reference internal" href="#changelog" id="id19">Changelog</a><ul>

+<li><a class="reference internal" href="#version-1-07-18-05-2010" id="id20">Version 1.07 (18.05.2010)</a></li>

+<li><a class="reference internal" href="#version-1-06-10-04-2010" id="id21">Version 1.06 (10.04.2010)</a></li>

+<li><a class="reference internal" href="#version-1-05-16-10-2009" id="id22">Version 1.05 (16.10.2009)</a></li>

+<li><a class="reference internal" href="#version-1-04-22-05-2009" id="id23">Version 1.04 (22.05.2009)</a></li>

+<li><a class="reference internal" href="#version-1-03-31-01-2009" id="id24">Version 1.03 (31.01.2009)</a></li>

+<li><a class="reference internal" href="#version-1-02-16-01-2009" id="id25">Version 1.02 (16.01.2009)</a></li>

+<li><a class="reference internal" href="#version-1-01-09-01-2009" id="id26">Version 1.01 (09.01.2009)</a></li>

+<li><a class="reference internal" href="#version-1-0-15-11-2008" id="id27">Version 1.0 (15.11.2008)</a></li>

+</ul>

+</li>

+</ul>

+</div>

+<div class="section" id="introduction">

+<h1><a class="toc-backref" href="#id1">Introduction</a></h1>

+<div class="section" id="what-is-pycparser">

+<h2><a class="toc-backref" href="#id2">What is pycparser?</a></h2>

+<p><tt class="docutils literal"><span class="pre">pycparser</span></tt> is a parser for the C language, written in pure Python. It is a module designed to be easily integrated into applications that need to parse C source code.</p>

+</div>

+<div class="section" id="what-is-it-good-for">

+<h2><a class="toc-backref" href="#id3">What is it good for?</a></h2>

+<p>Anything that needs C code to be parsed. The following are some uses for <tt class="docutils literal"><span class="pre">pycparser</span></tt>, taken from real user reports:</p>

+<ul class="simple">

+<li>C code obfuscator</li>

+<li>Front-end for various specialized C compilers</li>

+<li>Static code checker</li>

+<li>Automatic unit-test discovery</li>

+<li>Adding specialized extensions to the C language</li>

+</ul>

+<p><tt class="docutils literal"><span class="pre">pycparser</span></tt> is unique in the sense that it's written in pure Python - a very high level language that's easy to experiment with and tweak. To people familiar with Lex and Yacc, <tt class="docutils literal"><span class="pre">pycparser</span></tt>'s code will be simple to understand.</p>

+</div>

+<div class="section" id="which-version-of-c-does-pycparser-support">

+<h2><a class="toc-backref" href="#id4">Which version of C does pycparser support?</a></h2>

+<p>At the moment, <tt class="docutils literal"><span class="pre">pycparser</span></tt> supports ANSI/ISO C89, the language described by Kernighan and Ritchie in &quot;The C Programming language, 2nd edition&quot; (K&amp;R2), with only selected extensions from C99. The currently supported C99 features are:</p>

+<ul class="simple">

+<li>Allowing a comma after the last value in an enumeration list</li>

+</ul>

+<p><tt class="docutils literal"><span class="pre">pycparser</span></tt> doesn't support any GCC extensions.</p>

+</div>

+<div class="section" id="what-grammar-does-pycparser-follow">

+<h2><a class="toc-backref" href="#id5">What grammar does pycparser follow?</a></h2>

+<p><tt class="docutils literal"><span class="pre">pycparser</span></tt> very closely follows the ANSI C grammar provided in the end of K&amp;R2. Listings of this grammar (often in Yacc syntax) can be easily found by a simple web search. Google for <cite>ansi c grammar</cite> to get started.</p>

+</div>

+<div class="section" id="what-is-an-ast">

+<h2><a class="toc-backref" href="#id6">What is an AST?</a></h2>

+<p><a class="reference external" href="http://en.wikipedia.org/wiki/Abstract_syntax_tree">AST</a> - Abstract Syntax Tree. It is a tree representation of the syntax of source code - a convenient hierarchical data structure that's built from the code and is readily suitable for exploration and manipulation.</p>

+</div>

+<div class="section" id="how-is-pycparser-licensed">

+<h2><a class="toc-backref" href="#id7">How is pycparser licensed?</a></h2>

+<p><a class="reference external" href="http://www.gnu.org/licenses/lgpl.html">LGPL</a></p>

+</div>

+<div class="section" id="contact-details">

+<h2><a class="toc-backref" href="#id8">Contact details</a></h2>

+<p>Drop me an email to <a class="reference external" href="mailto:eliben&#64;gmail.com">eliben&#64;gmail.com</a> for any questions regarding <tt class="docutils literal"><span class="pre">pycparser</span></tt>.</p>

+</div>

+</div>

+<div class="section" id="installing">

+<h1><a class="toc-backref" href="#id9">Installing</a></h1>

+<div class="section" id="prerequisites">

+<h2><a class="toc-backref" href="#id10">Prerequisites</a></h2>

+<ul class="simple">

+<li><tt class="docutils literal"><span class="pre">pycparser</span></tt> was tested on Python 2.5, 2.6 and 3.1, on both Linux and Windows</li>

+<li><tt class="docutils literal"><span class="pre">pycparser</span></tt> uses the PLY module for the actual lexer and parser construction. You'll also need to install PLY version 3.2 (earlier versions work at least since 2.5) from <a class="reference external" href="http://www.dabeaz.com/ply/">its website</a>.</li>

+<li>If you want to modify <tt class="docutils literal"><span class="pre">pycparser</span></tt>'s code, you'll need to install <a class="reference external" href="http://pyyaml.org/">PyYAML</a>, since it's used by <tt class="docutils literal"><span class="pre">pycparser</span></tt> to store the AST configuration in a YAML file.</li>

+</ul>

+</div>

+<div class="section" id="installation-process">

+<h2><a class="toc-backref" href="#id11">Installation process</a></h2>

+<p>Installing <tt class="docutils literal"><span class="pre">pycparser</span></tt> is very simple. Once you download it from its <a class="reference external" href="http://code.google.com/p/pycparser/">website</a> and unzip the package, you just have to execute the standard <tt class="docutils literal"><span class="pre">python</span> <span class="pre">setup.py</span> <span class="pre">install</span></tt>. The setup script will then place the <tt class="docutils literal"><span class="pre">pycparser</span></tt> module into <tt class="docutils literal"><span class="pre">site-packages</span></tt> in your Python's installation library.</p>

+<p>It's recommended to run <tt class="docutils literal"><span class="pre">_build_tables.py</span></tt> in the <tt class="docutils literal"><span class="pre">pycparser</span></tt> code directory to make sure the parsing tables of PLY are pre-generated. This can make your code run faster.</p>

+</div>

+</div>

+<div class="section" id="using">

+<h1><a class="toc-backref" href="#id12">Using</a></h1>

+<div class="section" id="interaction-with-the-c-preprocessor">

+<h2><a class="toc-backref" href="#id13">Interaction with the C preprocessor</a></h2>

+<p>In order to be compilable, C code must be preprocessed by the C preprocessor - <tt class="docutils literal"><span class="pre">cpp</span></tt>. <tt class="docutils literal"><span class="pre">cpp</span></tt> handles preprocessing directives like <tt class="docutils literal"><span class="pre">#include</span></tt> and <tt class="docutils literal"><span class="pre">#define</span></tt>, removes comments, and does other minor tasks that prepare the C code for compilation.</p>

+<p>For all but the most trivial snippets of C code, <tt class="docutils literal"><span class="pre">pycparser</span></tt>, like a C compiler, must receive preprocessed C code in order to function correctly. If you import the top-level <tt class="docutils literal"><span class="pre">parse_file</span></tt> function from the <tt class="docutils literal"><span class="pre">pycparser</span></tt> package, it will interact with <tt class="docutils literal"><span class="pre">cpp</span></tt> for you, as long as it's in your PATH, or you provide a path to it.</p>

+<p>On the vast majority of Linux systems, <tt class="docutils literal"><span class="pre">cpp</span></tt> is installed and is in the PATH. If you're on Windows and don't have <tt class="docutils literal"><span class="pre">cpp</span></tt> somewhere, you can use the one provided in the <tt class="docutils literal"><span class="pre">utils</span></tt> directory in <tt class="docutils literal"><span class="pre">pycparser</span></tt>'s distribution. This <tt class="docutils literal"><span class="pre">cpp</span></tt> executable was compiled from the <a class="reference external" href="http://www.cs.princeton.edu/software/lcc/">LCC distribution</a>, and is provided under LCC's license terms.</p>

+</div>

+<div class="section" id="what-about-the-standard-c-library-headers">

+<h2><a class="toc-backref" href="#id14">What about the standard C library headers?</a></h2>

+<p>C code almost always includes various header files from the standard C library, like <tt class="docutils literal"><span class="pre">stdio.h</span></tt>. While, with some effort, <tt class="docutils literal"><span class="pre">pycparser</span></tt> can be made to parse the standard headers from any C compiler, it's much simpler to use the provided &quot;fake&quot; standard in includes in <tt class="docutils literal"><span class="pre">utils/fake_libc_include</span></tt>. These are standard C header files that contain only the bare necessities to allow valid compilation of the files that use them. As a bonus, since they're minimal, it can significantly improve the performance of parsing C files.</p>

+<p>See the <tt class="docutils literal"><span class="pre">using_cpp_libc.py</span></tt> example for more details.</p>

+</div>

+<div class="section" id="basic-usage">

+<h2><a class="toc-backref" href="#id15">Basic usage</a></h2>

+<p>Take a look at the <tt class="docutils literal"><span class="pre">examples</span></tt> directory of the distribution for a few examples of using <tt class="docutils literal"><span class="pre">pycparser</span></tt>. These should be enough to get you started.</p>

+</div>

+<div class="section" id="advanced-usage">

+<h2><a class="toc-backref" href="#id16">Advanced usage</a></h2>

+<p>The public interface of <tt class="docutils literal"><span class="pre">pycparser</span></tt> is well documented with comments in <tt class="docutils literal"><span class="pre">pycparser/c_parser.py</span></tt>. For a detailed overview of the various AST nodes created by the parser, see <tt class="docutils literal"><span class="pre">pycparser/_c_ast.yaml</span></tt>.</p>

+<p>In any case, you can always drop me an <a class="reference external" href="mailto:eliben&#64;gmail.com">email</a> for help.</p>

+</div>

+</div>

+<div class="section" id="modifying">

+<h1><a class="toc-backref" href="#id17">Modifying</a></h1>

+<p>There are a few points to keep in mind when modifying <tt class="docutils literal"><span class="pre">pycparser</span></tt>:</p>

+<ul class="simple">

+<li>The code for <tt class="docutils literal"><span class="pre">pycparser</span></tt>'s AST nodes is automatically generated from a YAML configuration file - <tt class="docutils literal"><span class="pre">_c_ast.yaml</span></tt>, by <tt class="docutils literal"><span class="pre">_ast_gen.py</span></tt>. If you modify the AST configuration, make sure to re-generate the code.</li>

+<li>Make sure you understand the optimized mode of <tt class="docutils literal"><span class="pre">pycparser</span></tt> - for that you must read the docstring in the constructor of the <tt class="docutils literal"><span class="pre">CParser</span></tt> class. For development you should create the parser without optimizations, so that it will regenerate the Yacc and Lex tables when you change the grammar.</li>

+<li>The script <tt class="docutils literal"><span class="pre">_build_tables.py</span></tt> can be helpful - it regenerates all the tables needed by <tt class="docutils literal"><span class="pre">pycparser</span></tt>, and the AST code from YAML.</li>

+</ul>

+</div>

+<div class="section" id="package-contents">

+<h1><a class="toc-backref" href="#id18">Package contents</a></h1>

+<p>Once you unzip the <tt class="docutils literal"><span class="pre">pycparser</span></tt> package, you'll see the following files and directories:</p>

+<dl class="docutils">

+<dt>README.txt/html:</dt>

+<dd>This README file.</dd>

+<dt>setup.py:</dt>

+<dd>Installation script</dd>

+<dt>examples/:</dt>

+<dd>A directory with some examples of using <tt class="docutils literal"><span class="pre">pycparser</span></tt></dd>

+<dt>pycparser/:</dt>

+<dd>The <tt class="docutils literal"><span class="pre">pycparser</span></tt> module source code.</dd>

+<dt>tests/:</dt>

+<dd>Unit tests.</dd>

+<dt>utils/cpp.exe:</dt>

+<dd>A Windows executable of the C pre-processor suitable for working with pycparser</dd>

+<dt>utils/fake_libc_include:</dt>

+<dd>Minimal standard C library include files that should allow to parse any C code.</dd>

+<dt>utils/internal/:</dt>

+<dd>Internal utilities for my own use. You probably don't need them.</dd>

+</dl>

+</div>

+<div class="section" id="changelog">

+<h1><a class="toc-backref" href="#id19">Changelog</a></h1>

+<div class="section" id="version-1-07-18-05-2010">

+<h2><a class="toc-backref" href="#id20">Version 1.07 (18.05.2010)</a></h2>

+<ul class="simple">

+<li>Python 3.1 compatibility: <tt class="docutils literal"><span class="pre">pycparser</span></tt> was modified to run on Python 3.1 as well as 2.6</li>

+</ul>

+</div>

+<div class="section" id="version-1-06-10-04-2010">

+<h2><a class="toc-backref" href="#id21">Version 1.06 (10.04.2010)</a></h2>

+<ul class="simple">

+<li>Bug fixes:<ul>

+<li>coord not propagated to FuncCall nodes</li>

+<li>lexing of the ^= token (XOREQUALS)</li>

+<li>parsing failed on some abstract declarator rules</li>

+</ul>

+</li>

+<li>Linux compatibility: fixed end-of-line and <tt class="docutils literal"><span class="pre">cpp</span></tt> path issues to allow all tests and examples run on Linux</li>

+</ul>

+</div>

+<div class="section" id="version-1-05-16-10-2009">

+<h2><a class="toc-backref" href="#id22">Version 1.05 (16.10.2009)</a></h2>

+<ul class="simple">

+<li>Fixed the <tt class="docutils literal"><span class="pre">parse_file</span></tt> auxiliary function to handle multiple arguments to <tt class="docutils literal"><span class="pre">cpp</span></tt> correctly</li>

+</ul>

+</div>

+<div class="section" id="version-1-04-22-05-2009">

+<h2><a class="toc-backref" href="#id23">Version 1.04 (22.05.2009)</a></h2>

+<ul class="simple">

+<li>Added the <tt class="docutils literal"><span class="pre">fake_libc_include</span></tt> directory to allow parsing of C code that uses standard C library include files without dependency on a real C library.</li>

+<li>Tested with Python 2.6 and PLY 3.2</li>

+</ul>

+</div>

+<div class="section" id="version-1-03-31-01-2009">

+<h2><a class="toc-backref" href="#id24">Version 1.03 (31.01.2009)</a></h2>

+<ul class="simple">

+<li>Accept enumeration lists with a comma after the last item (C99 feature).</li>

+</ul>

+</div>

+<div class="section" id="version-1-02-16-01-2009">

+<h2><a class="toc-backref" href="#id25">Version 1.02 (16.01.2009)</a></h2>

+<ul class="simple">

+<li>Fixed problem of parsing struct/enum/union names that were named similarly to previously defined <tt class="docutils literal"><span class="pre">typedef</span></tt> types.</li>

+</ul>

+</div>

+<div class="section" id="version-1-01-09-01-2009">

+<h2><a class="toc-backref" href="#id26">Version 1.01 (09.01.2009)</a></h2>

+<ul class="simple">

+<li>Fixed subprocess invocation in the helper function parse_file - now it's more portable</li>

+</ul>

+</div>

+<div class="section" id="version-1-0-15-11-2008">

+<h2><a class="toc-backref" href="#id27">Version 1.0 (15.11.2008)</a></h2>

+<ul class="simple">

+<li>Initial release</li>

+<li>Support for ANSI C89</li>

+</ul>

+</div>

+</div>

+</div>

+</body>

+</html>

diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..4674782
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,208 @@
+===============

+pycparser v1.06

+===============

+

+:Author: `Eli Bendersky <http://eli.thegreenplace.net>`_

+

+

+.. contents::

+

+Introduction

+============

+

+What is pycparser?

+------------------

+

+``pycparser`` is a parser for the C language, written in pure Python. It is a module designed to be easily integrated into applications that need to parse C source code.

+

+What is it good for?

+--------------------

+

+Anything that needs C code to be parsed. The following are some uses for ``pycparser``, taken from real user reports:

+

+* C code obfuscator

+* Front-end for various specialized C compilers

+* Static code checker

+* Automatic unit-test discovery

+* Adding specialized extensions to the C language

+

+``pycparser`` is unique in the sense that it's written in pure Python - a very high level language that's easy to experiment with and tweak. To people familiar with Lex and Yacc, ``pycparser``'s code will be simple to understand.

+

+

+Which version of C does pycparser support?

+------------------------------------------

+

+At the moment, ``pycparser`` supports ANSI/ISO C89, the language described by Kernighan and Ritchie in "The C Programming language, 2nd edition" (K&R2), with only selected extensions from C99. The currently supported C99 features are:

+

+* Allowing a comma after the last value in an enumeration list

+

+``pycparser`` doesn't support any GCC extensions.

+

+What grammar does pycparser follow?

+-----------------------------------

+

+``pycparser`` very closely follows the ANSI C grammar provided in the end of K&R2. Listings of this grammar (often in Yacc syntax) can be easily found by a simple web search. Google for `ansi c grammar` to get started.

+

+

+What is an AST?

+---------------

+

+`AST <http://en.wikipedia.org/wiki/Abstract_syntax_tree>`_ - Abstract Syntax Tree. It is a tree representation of the syntax of source code - a convenient hierarchical data structure that's built from the code and is readily suitable for exploration and manipulation.

+

+How is pycparser licensed?

+--------------------------

+

+`LGPL <http://www.gnu.org/licenses/lgpl.html>`_

+

+Contact details

+---------------

+

+Drop me an email to eliben@gmail.com for any questions regarding ``pycparser``.

+

+

+Installing

+==========

+

+Prerequisites

+-------------

+

+* ``pycparser`` was tested on Python 2.5, 2.6 and 3.1, on both Linux and Windows

+* ``pycparser`` uses the PLY module for the actual lexer and parser construction. You'll also need to install PLY version 3.2 (earlier versions work at least since 2.5) from `its website <http://www.dabeaz.com/ply/>`_.

+* If you want to modify ``pycparser``'s code, you'll need to install `PyYAML <http://pyyaml.org/>`_, since it's used by ``pycparser`` to store the AST configuration in a YAML file.

+

+Installation process

+--------------------

+

+Installing ``pycparser`` is very simple. Once you download it from its `website <http://code.google.com/p/pycparser/>`_ and unzip the package, you just have to execute the standard ``python setup.py install``. The setup script will then place the ``pycparser`` module into ``site-packages`` in your Python's installation library.

+

+It's recommended to run ``_build_tables.py`` in the ``pycparser`` code directory to make sure the parsing tables of PLY are pre-generated. This can make your code run faster.

+

+

+Using

+=====

+

+Interaction with the C preprocessor

+-----------------------------------

+

+In order to be compilable, C code must be preprocessed by the C preprocessor - ``cpp``. ``cpp`` handles preprocessing directives like ``#include`` and ``#define``, removes comments, and does other minor tasks that prepare the C code for compilation.

+

+For all but the most trivial snippets of C code, ``pycparser``, like a C compiler, must receive preprocessed C code in order to function correctly. If you import the top-level ``parse_file`` function from the ``pycparser`` package, it will interact with ``cpp`` for you, as long as it's in your PATH, or you provide a path to it. 

+

+On the vast majority of Linux systems, ``cpp`` is installed and is in the PATH. If you're on Windows and don't have ``cpp`` somewhere, you can use the one provided in the ``utils`` directory in ``pycparser``'s distribution. This ``cpp`` executable was compiled from the `LCC distribution <http://www.cs.princeton.edu/software/lcc/>`_, and is provided under LCC's license terms.

+

+What about the standard C library headers?

+------------------------------------------

+

+C code almost always includes various header files from the standard C library, like ``stdio.h``. While, with some effort, ``pycparser`` can be made to parse the standard headers from any C compiler, it's much simpler to use the provided "fake" standard in includes in ``utils/fake_libc_include``. These are standard C header files that contain only the bare necessities to allow valid compilation of the files that use them. As a bonus, since they're minimal, it can significantly improve the performance of parsing C files.

+

+See the ``using_cpp_libc.py`` example for more details.

+

+Basic usage

+-----------

+

+Take a look at the ``examples`` directory of the distribution for a few examples of using ``pycparser``. These should be enough to get you started.

+

+Advanced usage

+--------------

+

+The public interface of ``pycparser`` is well documented with comments in ``pycparser/c_parser.py``. For a detailed overview of the various AST nodes created by the parser, see ``pycparser/_c_ast.yaml``.

+

+In any case, you can always drop me an `email <eliben@gmail.com>`_ for help.

+

+Modifying

+=========

+

+There are a few points to keep in mind when modifying ``pycparser``:

+

+* The code for ``pycparser``'s AST nodes is automatically generated from a YAML configuration file - ``_c_ast.yaml``, by ``_ast_gen.py``. If you modify the AST configuration, make sure to re-generate the code.

+* Make sure you understand the optimized mode of ``pycparser`` - for that you must read the docstring in the constructor of the ``CParser`` class. For development you should create the parser without optimizations, so that it will regenerate the Yacc and Lex tables when you change the grammar.

+* The script ``_build_tables.py`` can be helpful - it regenerates all the tables needed by ``pycparser``, and the AST code from YAML.

+

+

+Package contents

+================

+

+Once you unzip the ``pycparser`` package, you'll see the following files and directories:

+

+README.txt/html:

+  This README file.

+

+setup.py:

+  Installation script

+

+examples/:

+  A directory with some examples of using ``pycparser``

+

+pycparser/:

+  The ``pycparser`` module source code.

+

+tests/:

+  Unit tests.

+

+utils/cpp.exe:

+  A Windows executable of the C pre-processor suitable for working with pycparser

+

+utils/fake_libc_include:

+  Minimal standard C library include files that should allow to parse any C code.

+

+utils/internal/:

+  Internal utilities for my own use. You probably don't need them.

+

+

+Changelog

+=========

+

+Version 1.07 (18.05.2010)

+-------------------------

+

+* Python 3.1 compatibility: ``pycparser`` was modified to run on Python 3.1 as well as 2.6

+

+

+Version 1.06 (10.04.2010)

+-------------------------

+

+* Bug fixes: 

+

+  + coord not propagated to FuncCall nodes

+  + lexing of the ^= token (XOREQUALS)

+  + parsing failed on some abstract declarator rules

+

+* Linux compatibility: fixed end-of-line and ``cpp`` path issues to allow all tests and examples run on Linux

+

+

+Version 1.05 (16.10.2009)

+-------------------------

+

+* Fixed the ``parse_file`` auxiliary function to handle multiple arguments to ``cpp`` correctly

+

+Version 1.04 (22.05.2009)

+-------------------------

+

+* Added the ``fake_libc_include`` directory to allow parsing of C code that uses standard C library include files without dependency on a real C library.

+* Tested with Python 2.6 and PLY 3.2

+

+

+Version 1.03 (31.01.2009)

+-------------------------

+

+* Accept enumeration lists with a comma after the last item (C99 feature).

+

+Version 1.02 (16.01.2009)

+-------------------------

+

+* Fixed problem of parsing struct/enum/union names that were named similarly to previously defined ``typedef`` types. 

+

+Version 1.01 (09.01.2009)

+-------------------------

+

+* Fixed subprocess invocation in the helper function parse_file - now it's more portable

+

+Version 1.0 (15.11.2008)

+------------------------

+

+* Initial release

+* Support for ANSI C89

+

+

+

+

diff --git a/TODO.txt b/TODO.txt
new file mode 100644
index 0000000..4b85109
--- /dev/null
+++ b/TODO.txt
@@ -0,0 +1,33 @@
+Fixes since last:

+------------------

+

+

+

+Version Update

+--------------

+

+setup.py, __init__.py, README.txt

+

+

+

+rst2html readme.txt > readme.html

+

+setup.py sdist

+

+

+

+

+

+yacc optimization: 

+- If parsetab.py/pyc doesn't exist in the path, the table will be reconstructed anyway, regardless of the optimize parameter

+- If it does exist:

+  - If optimize=True, the table will be loaded unconditionally

+  - If optimize=False, the table will be loaded only if it's older than the grammar

+

+lex optimization:

+- If optimize=False, the lexical table is re-computed and is not saved to a lextab file

+- If optimize=True:

+  - If lextab.py/pyc exists in the path, it will be loaded unconditionally

+  - If lextab.py/pyc doesn't exist, it will be created and loaded

+

+

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 (eliben@gmail.com)

+//  

+// 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 (eliben@gmail.com)

+//  

+// 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()
+
diff --git a/pycparser/__init__.py b/pycparser/__init__.py
new file mode 100644
index 0000000..1489b68
--- /dev/null
+++ b/pycparser/__init__.py
@@ -0,0 +1,74 @@
+#-----------------------------------------------------------------

+# pycparser: __init__.py

+#

+# This package file exports some convenience functions for 

+# interacting with pycparser

+#

+# Copyright (C) 2008-2009, Eli Bendersky

+# License: LGPL

+#-----------------------------------------------------------------

+

+__all__ = ['c_lexer', 'c_parser', 'c_ast']

+__version__ = '1.07'

+

+from subprocess import Popen, PIPE

+

+from .c_parser import CParser

+

+

+def parse_file( filename, use_cpp=False, 

+                cpp_path='cpp', cpp_args=''):

+    """ Parse a C file using pycparser.

+    

+        filename:

+            Name of the file you want to parse.

+        

+        use_cpp:

+            Set to True if you want to execute the C pre-processor

+            on the file prior to parsing it.

+        

+        cpp_path:

+            If use_cpp is True, this is the path to 'cpp' on your

+            system. If no path is provided, it attempts to just

+            execute 'cpp', so it must be in your PATH.

+        

+        cpp_args:

+            If use_cpp is True, set this to the command line 

+            arguments strings to cpp. Be careful with quotes - 

+            it's best to pass a raw string (r'') here. 

+            For example:

+            r'-I../utils/fake_libc_include'

+            If several arguments are required, pass a list of 

+            strings.

+        

+        When successful, an AST is returned. ParseError can be 

+        thrown if the file doesn't parse successfully.

+        

+        Errors from cpp will be printed out. 
+    """

+    if use_cpp:   

+        path_list = [cpp_path]

+        if isinstance(cpp_args, list):

+            path_list += cpp_args

+        elif cpp_args != '': 

+            path_list += [cpp_args]

+        path_list += [filename]

+        

+        # Note the use of universal_newlines to treat all newlines

+        # as \n for Python's purpose

+        #

+        pipe = Popen(   path_list, 

+                        stdout=PIPE, 

+                        universal_newlines=True)

+        text = pipe.communicate()[0]

+    else:

+        text = open(filename, 'rU').read()

+    

+    parser = CParser()

+    return parser.parse(text, filename)

+    

+

+if __name__ == "__main__":

+    pass

+    
+

diff --git a/pycparser/_ast_gen.py b/pycparser/_ast_gen.py
new file mode 100644
index 0000000..47ba148
--- /dev/null
+++ b/pycparser/_ast_gen.py
@@ -0,0 +1,249 @@
+#-----------------------------------------------------------------

+# _ast_gen.py

+#

+# Generates the AST Node classes from a specification given in 

+# a .yaml file

+#

+# The design of this module was inspired by astgen.py from the

+# Python 2.5 code-base.

+#

+# Copyright (C) 2008-2009, Eli Bendersky

+# License: LGPL

+#-----------------------------------------------------------------

+

+import pprint

+from string import Template

+

+import yaml

+

+

+class ASTCodeGenerator(object):
+    def __init__(self, cfg_filename='_c_ast.yaml'):

+        """ Initialize the code generator from a configuration

+            file.
+        """

+        self.cfg_filename = cfg_filename

+        cfg = yaml.load(open(cfg_filename).read())

+        self.node_cfg = [NodeCfg(name, cfg[name]) for name in cfg]

+

+        #~ pprint.pprint(self.node_cfg)

+        #~ print ''

+

+    def generate(self, file=None):

+        """ Generates the code into file, an open file buffer.

+        """

+        src = Template(_PROLOGUE_COMMENT).substitute(

+            cfg_filename=self.cfg_filename)

+        

+        src += _PROLOGUE_CODE

+        for node_cfg in self.node_cfg:

+            src += node_cfg.generate_source() + '\n\n'

+        

+        file.write(src)
+

+

+class NodeCfg(object):
+    def __init__(self, name, contents):

+        self.name = name

+        self.all_entries = []

+        self.attr = []

+        self.child = []

+        self.seq_child = []

+        

+        for entry in contents:

+            clean_entry = entry.rstrip('*')

+            self.all_entries.append(clean_entry)

+            

+            if entry.endswith('**'):

+                self.seq_child.append(clean_entry)

+            elif entry.endswith('*'):

+                self.child.append(clean_entry)

+            else:

+                self.attr.append(entry)
+

+    def generate_source(self):
+        src = self._gen_init()

+        src += '\n' + self._gen_children()

+        src += '\n' + self._gen_show()

+        return src

+    

+    def _gen_init(self):
+        src = "class %s(Node):\n" % self.name

+

+        if self.all_entries:

+            args = ', '.join(self.all_entries)

+            arglist = '(self, %s, coord=None)' % args

+        else:

+            arglist = '(self, coord=None)'

+        

+        src += "    def __init__%s:\n" % arglist

+        

+        for name in self.all_entries + ['coord']:

+            src += "        self.%s = %s\n" % (name, name)

+        

+        return src

+    

+    def _gen_children(self):
+        src = '    def children(self):\n'

+        

+        if self.all_entries:

+            src += '        nodelist = []\n'

+            

+            template = ('' +

+                '        if self.%s is not None:' +

+                ' nodelist.%s(self.%s)\n')

+            

+            for child in self.child:

+                src += template % (

+                    child, 'append', child)

+            

+            for seq_child in self.seq_child:

+                src += template % (

+                    seq_child, 'extend', seq_child)

+                    

+            src += '        return tuple(nodelist)\n'

+        else:

+            src += '        return ()\n'

+            

+        return src

+

+    def _gen_show(self):
+        src = '    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):\n'

+        src += "        lead = ' ' * offset\n"

+        

+        src += "        buf.write(lead + '%s: ')\n\n" % self.name

+        

+        if self.attr:

+            src += "        if attrnames:\n"

+            src += "            attrstr = ', '.join('%s=%s' % nv for nv in ["

+            src += ', '.join('("%s", repr(%s))' % (nv, 'self.%s' % nv) for nv in self.attr)

+            src += '])\n'

+            src += "        else:\n"

+            src += "            attrstr = ', '.join('%s' % v for v in ["

+            src += ', '.join('self.%s' % v for v in self.attr)

+            src += '])\n'

+            src += "        buf.write(attrstr)\n\n"

+        

+        src += "        if showcoord:\n"

+        src += "            buf.write(' (at %s)' % self.coord)\n"

+        src += "        buf.write('\\n')\n\n"

+        

+        src += "        for c in self.children():\n"

+        src += "            c.show(buf, offset + 2, attrnames, showcoord)\n"

+        

+        return src

+

+

+_PROLOGUE_COMMENT = \

+r'''#-----------------------------------------------------------------

+# ** ATTENTION **

+# This code was automatically generated from the file:

+# $cfg_filename 

+#

+# Do not modify it directly. Modify the configuration file and

+# run the generator again.

+# ** ** *** ** **

+#

+# pycparser: c_ast.py

+#

+# AST Node classes.

+#

+# Copyright (C) 2008, Eli Bendersky

+# License: LGPL

+#-----------------------------------------------------------------

+

+'''

+

+_PROLOGUE_CODE = r'''

+import sys

+

+

+class Node(object):

+    """ Abstract base class for AST nodes.

+    """

+    def children(self):

+        """ A sequence of all children that are Nodes

+        """

+        pass

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        """ Pretty print the Node and all its attributes and

+            children (recursively) to a buffer.

+            

+            file:   

+                Open IO buffer into which the Node is printed.

+            

+            offset: 

+                Initial offset (amount of leading spaces) 

+            

+            attrnames:

+                True if you want to see the attribute names in

+                name=value pairs. False to only see the values.

+            

+            showcoord:

+                Do you want the coordinates of each Node to be

+                displayed.

+        """

+        pass

+

+

+class NodeVisitor(object):

+    """ A base NodeVisitor class for visiting c_ast nodes. 

+        Subclass it and define your own visit_XXX methods, where

+        XXX is the class name you want to visit with these 

+        methods.

+        

+        For example:

+        

+        class ConstantVisitor(NodeVisitor):

+            def __init__(self):

+                self.values = []

+            

+            def visit_Constant(self, node):

+                self.values.append(node.value)

+

+        Creates a list of values of all the constant nodes 

+        encountered below the given node. To use it:

+        

+        cv = ConstantVisitor()

+        cv.visit(node)

+        

+        Notes:

+        

+        *   generic_visit() will be called for AST nodes for which 

+            no visit_XXX method was defined. 

+        *   The children of nodes for which a visit_XXX was 

+            defined will not be visited - if you need this, call

+            generic_visit() on the node. 

+            You can use:

+                NodeVisitor.generic_visit(self, node)

+        *   Modeled after Python's own AST visiting facilities

+            (the ast module of Python 3.0)

+    """

+    def visit(self, node):

+        """ Visit a node. 

+        """

+        method = 'visit_' + node.__class__.__name__

+        visitor = getattr(self, method, self.generic_visit)

+        return visitor(node)

+        

+    def generic_visit(self, node):

+        """ Called if no explicit visitor function exists for a 

+            node. Implements preorder visiting of the node.

+        """

+        for c in node.children():

+            self.visit(c)

+

+

+'''

+

+

+

+if __name__ == "__main__":

+    import sys

+    
+    ast_gen = ASTCodeGenerator('_c_ast.yaml')

+    ast_gen.generate(open('c_ast.py', 'w'))

+    

+    

+    

diff --git a/pycparser/_build_tables.py b/pycparser/_build_tables.py
new file mode 100644
index 0000000..0f02387
--- /dev/null
+++ b/pycparser/_build_tables.py
@@ -0,0 +1,31 @@
+#-----------------------------------------------------------------
+# pycparser: _build_tables.py
+#
+# A dummy for generating the lexing/parsing tables and and 
+# compiling them into .pyc for faster execution in optimized mode.
+# Also generates AST code from the _c_ast.yaml configuration file.
+#
+# Copyright (C) 2008, Eli Bendersky
+# License: LGPL
+#-----------------------------------------------------------------
+
+# Generate c_ast.py
+#
+from _ast_gen import ASTCodeGenerator
+ast_gen = ASTCodeGenerator('_c_ast.yaml')
+ast_gen.generate(open('c_ast.py', 'w'))
+
+import c_parser
+
+# Generates the tables
+#
+c_parser.CParser(
+    lex_optimize=True, 
+    yacc_debug=False, 
+    yacc_optimize=True)
+
+# Load to compile into .pyc
+#
+import lextab
+import yacctab
+import c_ast
diff --git a/pycparser/_c_ast.yaml b/pycparser/_c_ast.yaml
new file mode 100644
index 0000000..c954e38
--- /dev/null
+++ b/pycparser/_c_ast.yaml
@@ -0,0 +1,164 @@
+#-----------------------------------------------------------------

+# pycparser: _c_ast_gen.yaml

+#

+# Defines the AST Node classes used in pycparser.

+# 

+# Each entry is a Node sub-class name, listing the attributes

+# and child nodes of the class:

+#   <name>*     - a child node

+#   <name>**    - a sequence of child nodes

+#   <name>      - an attribute

+#

+# Copyright (C) 2008-2009, Eli Bendersky

+# License: LGPL

+#-----------------------------------------------------------------

+

+

+ArrayDecl: [type*, dim*]

+

+ArrayRef: [name*, subscript*]

+

+# op: =, +=, /= etc.

+#

+Assignment: [op, lvalue*, rvalue*]

+

+BinaryOp: [op, left*, right*]

+

+Break: []

+

+Case: [expr*, stmt*]

+

+Cast: [to_type*, expr*]

+

+# Compound statement: { declarations... statements...}

+#

+Compound: [decls**, stmts**]

+

+# type: int, char, float, etc. see CLexer for constant token types

+#

+Constant: [type, value]

+

+Continue: []

+

+# name: the variable being declared

+# quals: list of qualifiers (const, volatile)

+# storage: list of storage specifiers (extern, register, etc.)

+# type: declaration type (probably nested with all the modifiers)

+# init: initialization value, or None

+# bitsize: bit field size, or None

+#

+Decl: [name, quals, storage, type*, init*, bitsize*]

+

+Default: [stmt*]

+

+DoWhile: [cond*, stmt*]

+

+# Represents the ellipsis (...) parameter in a function 

+# declaration

+#

+EllipsisParam: []

+

+# Enumeration type specifier

+# name: an optional ID

+# values: an EnumeratorList

+#

+Enum: [name, values*]

+

+# A name/value pair for enumeration values

+#

+Enumerator: [name, value*]

+

+# A list of enumerators

+#

+EnumeratorList: [enumerators**]

+

+# a list of comma separated expressions

+#

+ExprList: [exprs**]

+

+# This is the top of the AST, representing a single C file (a 

+# translation unit in K&R jargon). It contains a list of 

+# "external-declaration"s, which is either declarations (Decl),

+# Typedef or function definitions (FuncDef).

+# 

+FileAST: [ext**]

+

+# for (init; cond; next) stmt

+#

+For: [init*, cond*, next*, stmt*]

+

+# name: Id

+# args: ExprList

+#

+FuncCall: [name*, args*]

+

+# type <decl>(args)

+#

+FuncDecl: [args*, type*]

+

+# Function definition: a declarator for the function name and

+# a body, which is a compound statement. 

+# There's an optional list of parameter declarations for old

+# K&R-style definitions

+#

+FuncDef: [decl*, param_decls**, body*]

+

+Goto: [name]

+

+ID: [name]

+

+# Holder for types that are a simple identifier (e.g. the built

+# ins void, char etc. and typedef-defined types)

+#

+IdentifierType: [names]

+

+If: [cond*, iftrue*, iffalse*]

+

+Label: [name, stmt*]

+

+# a list of comma separated function parameter declarations

+#

+ParamList: [params**]

+

+PtrDecl: [quals, type*]

+

+Return: [expr*]

+

+# name: struct tag name

+# decls: declaration of members

+#

+Struct: [name, decls**]

+

+# type: . or ->

+# name.field or name->field

+#

+StructRef: [name*, type, field*]

+

+Switch: [cond*, stmt*]

+

+# cond ? iftrue : iffalse

+#

+TernaryOp: [cond*, iftrue*, iffalse*]

+

+# A base type declaration

+#

+TypeDecl: [declname, quals, type*]

+

+# A typedef declaration.

+# Very similar to Decl, but without some attributes

+#

+Typedef: [name, quals, storage, type*]

+

+Typename: [quals, type*]

+

+UnaryOp: [op, expr*]

+

+# name: union tag name

+# decls: declaration of members

+#

+Union: [name, decls**]

+

+While: [cond*, stmt*]

+

+

+

diff --git a/pycparser/c_ast.py b/pycparser/c_ast.py
new file mode 100644
index 0000000..90cfb79
--- /dev/null
+++ b/pycparser/c_ast.py
@@ -0,0 +1,1163 @@
+#-----------------------------------------------------------------

+# ** ATTENTION **

+# This code was automatically generated from the file:

+# _c_ast.yaml 

+#

+# Do not modify it directly. Modify the configuration file and

+# run the generator again.

+# ** ** *** ** **

+#

+# pycparser: c_ast.py

+#

+# AST Node classes.

+#

+# Copyright (C) 2008, Eli Bendersky

+# License: LGPL

+#-----------------------------------------------------------------

+

+

+import sys

+

+

+class Node(object):

+    """ Abstract base class for AST nodes.

+    """

+    def children(self):

+        """ A sequence of all children that are Nodes

+        """

+        pass

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        """ Pretty print the Node and all its attributes and

+            children (recursively) to a buffer.

+            

+            file:   

+                Open IO buffer into which the Node is printed.

+            

+            offset: 

+                Initial offset (amount of leading spaces) 

+            

+            attrnames:

+                True if you want to see the attribute names in

+                name=value pairs. False to only see the values.

+            

+            showcoord:

+                Do you want the coordinates of each Node to be

+                displayed.

+        """

+        pass

+

+

+class NodeVisitor(object):

+    """ A base NodeVisitor class for visiting c_ast nodes. 

+        Subclass it and define your own visit_XXX methods, where

+        XXX is the class name you want to visit with these 

+        methods.

+        

+        For example:

+        

+        class ConstantVisitor(NodeVisitor):

+            def __init__(self):

+                self.values = []

+            

+            def visit_Constant(self, node):

+                self.values.append(node.value)

+

+        Creates a list of values of all the constant nodes 

+        encountered below the given node. To use it:

+        

+        cv = ConstantVisitor()

+        cv.visit(node)

+        

+        Notes:

+        

+        *   generic_visit() will be called for AST nodes for which 

+            no visit_XXX method was defined. 

+        *   The children of nodes for which a visit_XXX was 

+            defined will not be visited - if you need this, call

+            generic_visit() on the node. 

+            You can use:

+                NodeVisitor.generic_visit(self, node)

+        *   Modeled after Python's own AST visiting facilities

+            (the ast module of Python 3.0)

+    """

+    def visit(self, node):

+        """ Visit a node. 

+        """

+        method = 'visit_' + node.__class__.__name__

+        visitor = getattr(self, method, self.generic_visit)

+        return visitor(node)

+        

+    def generic_visit(self, node):

+        """ Called if no explicit visitor function exists for a 

+            node. Implements preorder visiting of the node.

+        """

+        for c in node.children():

+            self.visit(c)

+

+

+class Typedef(Node):

+    def __init__(self, name, quals, storage, type, coord=None):

+        self.name = name

+        self.quals = quals

+        self.storage = storage

+        self.type = type

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.type is not None: nodelist.append(self.type)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Typedef: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name)), ("quals", repr(self.quals)), ("storage", repr(self.storage))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.name, self.quals, self.storage])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Struct(Node):

+    def __init__(self, name, decls, coord=None):

+        self.name = name

+        self.decls = decls

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.decls is not None: nodelist.extend(self.decls)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Struct: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.name])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class FuncCall(Node):

+    def __init__(self, name, args, coord=None):

+        self.name = name

+        self.args = args

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.name is not None: nodelist.append(self.name)

+        if self.args is not None: nodelist.append(self.args)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'FuncCall: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class UnaryOp(Node):

+    def __init__(self, op, expr, coord=None):

+        self.op = op

+        self.expr = expr

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.expr is not None: nodelist.append(self.expr)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'UnaryOp: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("op", repr(self.op))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.op])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Union(Node):

+    def __init__(self, name, decls, coord=None):

+        self.name = name

+        self.decls = decls

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.decls is not None: nodelist.extend(self.decls)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Union: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.name])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class TernaryOp(Node):

+    def __init__(self, cond, iftrue, iffalse, coord=None):

+        self.cond = cond

+        self.iftrue = iftrue

+        self.iffalse = iffalse

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.cond is not None: nodelist.append(self.cond)

+        if self.iftrue is not None: nodelist.append(self.iftrue)

+        if self.iffalse is not None: nodelist.append(self.iffalse)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'TernaryOp: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Label(Node):

+    def __init__(self, name, stmt, coord=None):

+        self.name = name

+        self.stmt = stmt

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.stmt is not None: nodelist.append(self.stmt)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Label: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.name])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class IdentifierType(Node):

+    def __init__(self, names, coord=None):

+        self.names = names

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'IdentifierType: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("names", repr(self.names))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.names])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class FuncDef(Node):

+    def __init__(self, decl, param_decls, body, coord=None):

+        self.decl = decl

+        self.param_decls = param_decls

+        self.body = body

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.decl is not None: nodelist.append(self.decl)

+        if self.body is not None: nodelist.append(self.body)

+        if self.param_decls is not None: nodelist.extend(self.param_decls)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'FuncDef: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Enumerator(Node):

+    def __init__(self, name, value, coord=None):

+        self.name = name

+        self.value = value

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.value is not None: nodelist.append(self.value)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Enumerator: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.name])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class For(Node):

+    def __init__(self, init, cond, next, stmt, coord=None):

+        self.init = init

+        self.cond = cond

+        self.next = next

+        self.stmt = stmt

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.init is not None: nodelist.append(self.init)

+        if self.cond is not None: nodelist.append(self.cond)

+        if self.next is not None: nodelist.append(self.next)

+        if self.stmt is not None: nodelist.append(self.stmt)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'For: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Assignment(Node):

+    def __init__(self, op, lvalue, rvalue, coord=None):

+        self.op = op

+        self.lvalue = lvalue

+        self.rvalue = rvalue

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.lvalue is not None: nodelist.append(self.lvalue)

+        if self.rvalue is not None: nodelist.append(self.rvalue)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Assignment: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("op", repr(self.op))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.op])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class FuncDecl(Node):

+    def __init__(self, args, type, coord=None):

+        self.args = args

+        self.type = type

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.args is not None: nodelist.append(self.args)

+        if self.type is not None: nodelist.append(self.type)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'FuncDecl: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Enum(Node):

+    def __init__(self, name, values, coord=None):

+        self.name = name

+        self.values = values

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.values is not None: nodelist.append(self.values)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Enum: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.name])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class ExprList(Node):

+    def __init__(self, exprs, coord=None):

+        self.exprs = exprs

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.exprs is not None: nodelist.extend(self.exprs)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'ExprList: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Break(Node):

+    def __init__(self, coord=None):

+        self.coord = coord

+

+    def children(self):

+        return ()

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Break: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class DoWhile(Node):

+    def __init__(self, cond, stmt, coord=None):

+        self.cond = cond

+        self.stmt = stmt

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.cond is not None: nodelist.append(self.cond)

+        if self.stmt is not None: nodelist.append(self.stmt)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'DoWhile: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class StructRef(Node):

+    def __init__(self, name, type, field, coord=None):

+        self.name = name

+        self.type = type

+        self.field = field

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.name is not None: nodelist.append(self.name)

+        if self.field is not None: nodelist.append(self.field)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'StructRef: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("type", repr(self.type))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.type])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class BinaryOp(Node):

+    def __init__(self, op, left, right, coord=None):

+        self.op = op

+        self.left = left

+        self.right = right

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.left is not None: nodelist.append(self.left)

+        if self.right is not None: nodelist.append(self.right)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'BinaryOp: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("op", repr(self.op))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.op])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Compound(Node):

+    def __init__(self, decls, stmts, coord=None):

+        self.decls = decls

+        self.stmts = stmts

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.decls is not None: nodelist.extend(self.decls)

+        if self.stmts is not None: nodelist.extend(self.stmts)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Compound: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class ArrayDecl(Node):

+    def __init__(self, type, dim, coord=None):

+        self.type = type

+        self.dim = dim

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.type is not None: nodelist.append(self.type)

+        if self.dim is not None: nodelist.append(self.dim)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'ArrayDecl: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Case(Node):

+    def __init__(self, expr, stmt, coord=None):

+        self.expr = expr

+        self.stmt = stmt

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.expr is not None: nodelist.append(self.expr)

+        if self.stmt is not None: nodelist.append(self.stmt)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Case: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Cast(Node):

+    def __init__(self, to_type, expr, coord=None):

+        self.to_type = to_type

+        self.expr = expr

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.to_type is not None: nodelist.append(self.to_type)

+        if self.expr is not None: nodelist.append(self.expr)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Cast: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class TypeDecl(Node):

+    def __init__(self, declname, quals, type, coord=None):

+        self.declname = declname

+        self.quals = quals

+        self.type = type

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.type is not None: nodelist.append(self.type)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'TypeDecl: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("declname", repr(self.declname)), ("quals", repr(self.quals))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.declname, self.quals])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Default(Node):

+    def __init__(self, stmt, coord=None):

+        self.stmt = stmt

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.stmt is not None: nodelist.append(self.stmt)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Default: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class PtrDecl(Node):

+    def __init__(self, quals, type, coord=None):

+        self.quals = quals

+        self.type = type

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.type is not None: nodelist.append(self.type)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'PtrDecl: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("quals", repr(self.quals))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.quals])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Switch(Node):

+    def __init__(self, cond, stmt, coord=None):

+        self.cond = cond

+        self.stmt = stmt

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.cond is not None: nodelist.append(self.cond)

+        if self.stmt is not None: nodelist.append(self.stmt)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Switch: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Continue(Node):

+    def __init__(self, coord=None):

+        self.coord = coord

+

+    def children(self):

+        return ()

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Continue: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class ParamList(Node):

+    def __init__(self, params, coord=None):

+        self.params = params

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.params is not None: nodelist.extend(self.params)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'ParamList: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Return(Node):

+    def __init__(self, expr, coord=None):

+        self.expr = expr

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.expr is not None: nodelist.append(self.expr)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Return: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Typename(Node):

+    def __init__(self, quals, type, coord=None):

+        self.quals = quals

+        self.type = type

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.type is not None: nodelist.append(self.type)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Typename: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("quals", repr(self.quals))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.quals])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class ID(Node):

+    def __init__(self, name, coord=None):

+        self.name = name

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'ID: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.name])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Goto(Node):

+    def __init__(self, name, coord=None):

+        self.name = name

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Goto: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.name])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Decl(Node):

+    def __init__(self, name, quals, storage, type, init, bitsize, coord=None):

+        self.name = name

+        self.quals = quals

+        self.storage = storage

+        self.type = type

+        self.init = init

+        self.bitsize = bitsize

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.type is not None: nodelist.append(self.type)

+        if self.init is not None: nodelist.append(self.init)

+        if self.bitsize is not None: nodelist.append(self.bitsize)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Decl: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("name", repr(self.name)), ("quals", repr(self.quals)), ("storage", repr(self.storage))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.name, self.quals, self.storage])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class Constant(Node):

+    def __init__(self, type, value, coord=None):

+        self.type = type

+        self.value = value

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'Constant: ')

+

+        if attrnames:

+            attrstr = ', '.join('%s=%s' % nv for nv in [("type", repr(self.type)), ("value", repr(self.value))])

+        else:

+            attrstr = ', '.join('%s' % v for v in [self.type, self.value])

+        buf.write(attrstr)

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class FileAST(Node):

+    def __init__(self, ext, coord=None):

+        self.ext = ext

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.ext is not None: nodelist.extend(self.ext)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'FileAST: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class ArrayRef(Node):

+    def __init__(self, name, subscript, coord=None):

+        self.name = name

+        self.subscript = subscript

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.name is not None: nodelist.append(self.name)

+        if self.subscript is not None: nodelist.append(self.subscript)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'ArrayRef: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class While(Node):

+    def __init__(self, cond, stmt, coord=None):

+        self.cond = cond

+        self.stmt = stmt

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.cond is not None: nodelist.append(self.cond)

+        if self.stmt is not None: nodelist.append(self.stmt)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'While: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class EnumeratorList(Node):

+    def __init__(self, enumerators, coord=None):

+        self.enumerators = enumerators

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.enumerators is not None: nodelist.extend(self.enumerators)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'EnumeratorList: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class EllipsisParam(Node):

+    def __init__(self, coord=None):

+        self.coord = coord

+

+    def children(self):

+        return ()

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'EllipsisParam: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

+class If(Node):

+    def __init__(self, cond, iftrue, iffalse, coord=None):

+        self.cond = cond

+        self.iftrue = iftrue

+        self.iffalse = iffalse

+        self.coord = coord

+

+    def children(self):

+        nodelist = []

+        if self.cond is not None: nodelist.append(self.cond)

+        if self.iftrue is not None: nodelist.append(self.iftrue)

+        if self.iffalse is not None: nodelist.append(self.iffalse)

+        return tuple(nodelist)

+

+    def show(self, buf=sys.stdout, offset=0, attrnames=False, showcoord=False):

+        lead = ' ' * offset

+        buf.write(lead + 'If: ')

+

+        if showcoord:

+            buf.write(' (at %s)' % self.coord)

+        buf.write('\n')

+

+        for c in self.children():

+            c.show(buf, offset + 2, attrnames, showcoord)

+

+

diff --git a/pycparser/c_lexer.py b/pycparser/c_lexer.py
new file mode 100644
index 0000000..b5327cb
--- /dev/null
+++ b/pycparser/c_lexer.py
@@ -0,0 +1,445 @@
+#-----------------------------------------------------------------
+# pycparser: c_lexer.py
+#
+# CLexer class: lexer for the C language
+#
+# Copyright (C) 2008-2010, Eli Bendersky
+# License: LGPL
+#-----------------------------------------------------------------
+
+import re
+import sys
+
+import ply.lex
+from ply.lex import TOKEN
+
+
+class CLexer(object):
+    """ A lexer for the C language. After building it, set the
+        input text with input(), and call token() to get new 
+        tokens.
+        
+        The public attribute filename can be set to an initial
+        filaneme, but the lexer will update it upon #line 
+        directives.
+    """
+    def __init__(self, error_func, type_lookup_func):
+        """ Create a new Lexer.
+        
+            error_func:
+                An error function. Will be called with an error
+                message, line and column as arguments, in case of 
+                an error during lexing.
+                
+            type_lookup_func:
+                A type lookup function. Given a string, it must
+                return True IFF this string is a name of a type
+                that was defined with a typedef earlier.
+        """
+        self.error_func = error_func
+        self.type_lookup_func = type_lookup_func
+        self.filename = ''
+        
+        # Allow either "# line" or "# <num>" to support GCC's
+        # cpp output
+        #
+        self.line_pattern = re.compile('([ \t]*line\W)|([ \t]*\d+)')
+
+    def build(self, **kwargs):
+        """ Builds the lexer from the specification. Must be
+            called after the lexer object is created. 
+            
+            This method exists separately, because the PLY
+            manual warns against calling lex.lex inside
+            __init__
+        """
+        self.lexer = ply.lex.lex(object=self, **kwargs)
+
+    def reset_lineno(self):
+        """ Resets the internal line number counter of the lexer.
+        """
+        self.lexer.lineno = 1
+
+    def input(self, text):
+        self.lexer.input(text)
+    
+    def token(self):
+        g = self.lexer.token()
+        return g
+
+    ######################--   PRIVATE   --######################
+    
+    ##
+    ## Internal auxiliary methods
+    ##
+    def _error(self, msg, token):
+        location = self._make_tok_location(token)
+        self.error_func(msg, location[0], location[1])
+        self.lexer.skip(1)
+    
+    def _find_tok_column(self, token):
+        i = token.lexpos
+        while i > 0:
+            if self.lexer.lexdata[i] == '\n': break
+            i -= 1
+        return (token.lexpos - i) + 1
+    
+    def _make_tok_location(self, token):
+        return (token.lineno, self._find_tok_column(token))
+    
+    ##
+    ## Reserved keywords
+    ##
+    keywords = (
+        'AUTO', 'BREAK', 'CASE', 'CHAR', 'CONST', 'CONTINUE', 
+        'DEFAULT', 'DO', 'DOUBLE', 'ELSE', 'ENUM', 'EXTERN', 
+        'FLOAT', 'FOR', 'GOTO', 'IF', 'INT', 'LONG', 'REGISTER',
+        'RETURN', 'SHORT', 'SIGNED', 'SIZEOF', 'STATIC', 'STRUCT', 
+        'SWITCH', 'TYPEDEF', 'UNION', 'UNSIGNED', 'VOID', 
+        'VOLATILE', 'WHILE',
+    )
+
+    keyword_map = {}
+    for r in keywords:
+        keyword_map[r.lower()] = r
+
+    ##
+    ## All the tokens recognized by the lexer
+    ##
+    tokens = keywords + (
+        # Identifiers
+        'ID', 
+        
+        # Type identifiers (identifiers previously defined as 
+        # types with typedef)
+        'TYPEID',
+        
+        # constants 
+        'INT_CONST_DEC', 'INT_CONST_OCT', 'INT_CONST_HEX',
+        'FLOAT_CONST', 
+        'CHAR_CONST',
+        'WCHAR_CONST',
+        
+        # String literals
+        'STRING_LITERAL',
+        'WSTRING_LITERAL',
+
+        # Operators 
+        'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD',
+        'OR', 'AND', 'NOT', 'XOR', 'LSHIFT', 'RSHIFT',
+        'LOR', 'LAND', 'LNOT',
+        'LT', 'LE', 'GT', 'GE', 'EQ', 'NE',
+        
+        # Assignment
+        'EQUALS', 'TIMESEQUAL', 'DIVEQUAL', 'MODEQUAL', 
+        'PLUSEQUAL', 'MINUSEQUAL',
+        'LSHIFTEQUAL','RSHIFTEQUAL', 'ANDEQUAL', 'XOREQUAL', 
+        'OREQUAL',
+
+        # Increment/decrement 
+        'PLUSPLUS', 'MINUSMINUS',
+
+        # Structure dereference (->)
+        'ARROW',
+
+        # Conditional operator (?)
+        'CONDOP',
+        
+        # Delimeters 
+        'LPAREN', 'RPAREN',         # ( )
+        'LBRACKET', 'RBRACKET',     # [ ]
+        'LBRACE', 'RBRACE',         # { } 
+        'COMMA', 'PERIOD',          # . ,
+        'SEMI', 'COLON',            # ; :
+
+        # Ellipsis (...)
+        'ELLIPSIS',
+        
+        # pre-processor 
+        'PPHASH',      # '#'
+    )
+
+    ##
+    ## Regexes for use in tokens
+    ##
+    ##
+
+    # valid C identifiers (K&R2: A.2.3)
+    identifier = r'[a-zA-Z_][0-9a-zA-Z_]*'
+
+    # integer constants (K&R2: A.2.5.1)
+    integer_suffix_opt = r'(([uU][lL])|([lL][uU])|[uU]|[lL])?'
+    decimal_constant = '(0'+integer_suffix_opt+')|([1-9][0-9]*'+integer_suffix_opt+')'
+    octal_constant = '0[0-7]*'+integer_suffix_opt
+    hex_constant = '0[xX][0-9a-fA-F]+'+integer_suffix_opt
+    
+    bad_octal_constant = '0[0-7]*[89]'
+
+    # character constants (K&R2: A.2.5.2)
+    # Note: a-zA-Z are allowed as escape chars to support #line
+    # directives with Windows paths as filenames (\dir\file...)
+    #
+    simple_escape = r"""([a-zA-Z\\?'"])"""
+    octal_escape = r"""([0-7]{1,3})"""
+    hex_escape = r"""(x[0-9a-fA-F]+)"""
+    bad_escape = r"""([\\][^a-zA-Z\\?'"x0-7])"""
+
+    escape_sequence = r"""(\\("""+simple_escape+'|'+octal_escape+'|'+hex_escape+'))'
+    cconst_char = r"""([^'\\\n]|"""+escape_sequence+')'    
+    char_const = "'"+cconst_char+"'"
+    wchar_const = 'L'+char_const
+    unmatched_quote = "('"+cconst_char+"*\\n)|('"+cconst_char+"*$)"
+    bad_char_const = r"""('"""+cconst_char+"""[^'\n]+')|('')|('"""+bad_escape+r"""[^'\n]*')"""
+
+    # string literals (K&R2: A.2.6)
+    string_char = r"""([^"\\\n]|"""+escape_sequence+')'    
+    string_literal = '"'+string_char+'*"'
+    wstring_literal = 'L'+string_literal
+    bad_string_literal = '"'+string_char+'*'+bad_escape+string_char+'*"'
+
+    # floating constants (K&R2: A.2.5.3)
+    exponent_part = r"""([eE][-+]?[0-9]+)"""
+    fractional_constant = r"""([0-9]*\.[0-9]+)|([0-9]+\.)"""
+    floating_constant = '(((('+fractional_constant+')'+exponent_part+'?)|([0-9]+'+exponent_part+'))[FfLl]?)'
+
+    ##
+    ## Lexer states
+    ##
+    states = (
+        # ppline: preprocessor line directives
+        # 
+        ('ppline', 'exclusive'),
+    )
+    
+    def t_PPHASH(self, t):
+        r'[ \t]*\#'
+        m = self.line_pattern.match(
+            t.lexer.lexdata, pos=t.lexer.lexpos)
+        
+        if m:
+            t.lexer.begin('ppline')
+            self.pp_line = self.pp_filename = None
+            #~ print "ppline starts on line %s" % t.lexer.lineno
+        else:
+            t.type = 'PPHASH'
+            return t
+    
+    ##
+    ## Rules for the ppline state
+    ##
+    @TOKEN(string_literal)
+    def t_ppline_FILENAME(self, t):
+        if self.pp_line is None:
+            self._error('filename before line number in #line', t)
+        else:
+            self.pp_filename = t.value.lstrip('"').rstrip('"')
+            #~ print "PP got filename: ", self.pp_filename
+
+    @TOKEN(decimal_constant)
+    def t_ppline_LINE_NUMBER(self, t):
+        if self.pp_line is None:
+            self.pp_line = t.value
+        else:
+            # Ignore: GCC's cpp sometimes inserts a numeric flag
+            # after the file name
+            pass
+
+    def t_ppline_NEWLINE(self, t):
+        r'\n'
+        
+        if self.pp_line is None:
+            self._error('line number missing in #line', t)
+        else:
+            self.lexer.lineno = int(self.pp_line)
+            
+            if self.pp_filename is not None:
+                self.filename = self.pp_filename
+                
+        t.lexer.begin('INITIAL')
+
+    def t_ppline_PPLINE(self, t):
+        r'line'
+        pass
+    
+    t_ppline_ignore = ' \t'
+
+    def t_ppline_error(self, t):
+        msg = 'invalid #line directive'
+        self._error(msg, t)
+
+    ##
+    ## Rules for the normal state
+    ##
+    t_ignore = ' \t'
+
+    # Newlines
+    def t_NEWLINE(self, t):
+        r'\n+'
+        t.lexer.lineno += t.value.count("\n")
+
+    # Operators
+    t_PLUS              = r'\+'
+    t_MINUS             = r'-'
+    t_TIMES             = r'\*'
+    t_DIVIDE            = r'/'
+    t_MOD               = r'%'
+    t_OR                = r'\|'
+    t_AND               = r'&'
+    t_NOT               = r'~'
+    t_XOR               = r'\^'
+    t_LSHIFT            = r'<<'
+    t_RSHIFT            = r'>>'
+    t_LOR               = r'\|\|'
+    t_LAND              = r'&&'
+    t_LNOT              = r'!'
+    t_LT                = r'<'
+    t_GT                = r'>'
+    t_LE                = r'<='
+    t_GE                = r'>='
+    t_EQ                = r'=='
+    t_NE                = r'!='
+
+    # Assignment operators
+    t_EQUALS            = r'='
+    t_TIMESEQUAL        = r'\*='
+    t_DIVEQUAL          = r'/='
+    t_MODEQUAL          = r'%='
+    t_PLUSEQUAL         = r'\+='
+    t_MINUSEQUAL        = r'-='
+    t_LSHIFTEQUAL       = r'<<='
+    t_RSHIFTEQUAL       = r'>>='
+    t_ANDEQUAL          = r'&='
+    t_OREQUAL           = r'\|='
+    t_XOREQUAL          = r'\^='
+
+    # Increment/decrement
+    t_PLUSPLUS          = r'\+\+'
+    t_MINUSMINUS        = r'--'
+
+    # ->
+    t_ARROW             = r'->'
+
+    # ?
+    t_CONDOP            = r'\?'
+
+    # Delimeters
+    t_LPAREN            = r'\('
+    t_RPAREN            = r'\)'
+    t_LBRACKET          = r'\['
+    t_RBRACKET          = r'\]'
+    t_LBRACE            = r'\{'
+    t_RBRACE            = r'\}'
+    t_COMMA             = r','
+    t_PERIOD            = r'\.'
+    t_SEMI              = r';'
+    t_COLON             = r':'
+    t_ELLIPSIS          = r'\.\.\.'
+
+    t_STRING_LITERAL    = string_literal
+    
+    # The following floating and integer constants are defined as 
+    # functions to impose a strict order (otherwise, decimal
+    # is placed before the others because its regex is longer,
+    # and this is bad)
+    #
+    @TOKEN(floating_constant)
+    def t_FLOAT_CONST(self, t):
+        return t
+
+    @TOKEN(hex_constant)
+    def t_INT_CONST_HEX(self, t):
+        return t
+
+    @TOKEN(bad_octal_constant)
+    def t_BAD_CONST_OCT(self, t):
+        msg = "Invalid octal constant"
+        self._error(msg, t)
+
+    @TOKEN(octal_constant)
+    def t_INT_CONST_OCT(self, t):
+        return t
+
+    @TOKEN(decimal_constant)
+    def t_INT_CONST_DEC(self, t):
+        return t
+
+    # Must come before bad_char_const, to prevent it from 
+    # catching valid char constants as invalid
+    # 
+    @TOKEN(char_const)
+    def t_CHAR_CONST(self, t):
+        return t
+        
+    @TOKEN(wchar_const)
+    def t_WCHAR_CONST(self, t):
+        return t
+    
+    @TOKEN(unmatched_quote)
+    def t_UNMATCHED_QUOTE(self, t):
+        msg = "Unmatched '"
+        self._error(msg, t)
+
+    @TOKEN(bad_char_const)
+    def t_BAD_CHAR_CONST(self, t):
+        msg = "Invalid char constant %s" % t.value
+        self._error(msg, t)
+
+    @TOKEN(wstring_literal)
+    def t_WSTRING_LITERAL(self, t):
+        return t
+    
+    # unmatched string literals are caught by the preprocessor
+    
+    @TOKEN(bad_string_literal)
+    def t_BAD_STRING_LITERAL(self, t):
+        msg = "String contains invalid escape code" 
+        self._error(msg, t)
+
+    @TOKEN(identifier)
+    def t_ID(self, t):
+        t.type = self.keyword_map.get(t.value, "ID")
+        
+        if t.type == 'ID' and self.type_lookup_func(t.value):
+            t.type = "TYPEID"
+            
+        return t
+    
+    def t_error(self, t):
+        msg = 'Illegal character %s' % repr(t.value[0])
+        self._error(msg, t)
+
+
+if __name__ == "__main__":
+    from portability import printme
+    filename = '../zp.c'
+    text = open(filename).read()
+    
+    #~ text = '"'+r"""ka \p ka"""+'"'
+    text = r"""
+    546
+        #line 66 "kwas\df.h" 
+        id 4
+        # 5 
+        dsf
+    """
+    
+    def errfoo(msg, a, b):
+        printme(msg)
+        sys.exit()
+    
+    def typelookup(namd):
+        return False
+    
+    clex = CLexer(errfoo, typelookup)
+    clex.build()
+    clex.input(text)
+    
+    while 1:
+        tok = clex.token()
+        if not tok: break
+            
+        #~ print type(tok)
+        printme([tok.value, tok.type, tok.lineno, clex.filename, tok.lexpos])
+        
+        
+
diff --git a/pycparser/c_parser.py b/pycparser/c_parser.py
new file mode 100644
index 0000000..8e75519
--- /dev/null
+++ b/pycparser/c_parser.py
@@ -0,0 +1,1258 @@
+#-----------------------------------------------------------------

+# pycparser: c_parser.py

+#

+# CParser class: Parser and AST builder for the C language

+#

+# Copyright (C) 2008-2010, Eli Bendersky

+# License: LGPL

+#-----------------------------------------------------------------

+

+import re

+

+import ply.yacc

+

+from . import c_ast

+from .c_lexer import CLexer

+from .plyparser import PLYParser, Coord, ParseError

+

+

+class CParser(PLYParser):    

+    def __init__(

+            self, 

+            lex_optimize=True,

+            lextab='pycparser.lextab',

+            yacc_optimize=True,

+            yacctab='pycparser.yacctab',

+            yacc_debug=False):

+        """ Create a new CParser.

+        

+            Some arguments for controlling the debug/optimization

+            level of the parser are provided. The defaults are 

+            tuned for release/performance mode. 

+            The simple rules for using them are:

+            *) When tweaking CParser/CLexer, set these to False

+            *) When releasing a stable parser, set to True

+            

+            lex_optimize:

+                Set to False when you're modifying the lexer.

+                Otherwise, changes in the lexer won't be used, if

+                some lextab.py file exists.

+                When releasing with a stable lexer, set to True

+                to save the re-generation of the lexer table on 

+                each run.

+            

+            lextab:

+                Points to the lex table that's used for optimized

+                mode. Only if you're modifying the lexer and want

+                some tests to avoid re-generating the table, make 

+                this point to a local lex table file (that's been

+                earlier generated with lex_optimize=True)

+            

+            yacc_optimize:

+                Set to False when you're modifying the parser.

+                Otherwise, changes in the parser won't be used, if

+                some parsetab.py file exists.

+                When releasing with a stable parser, set to True

+                to save the re-generation of the parser table on 

+                each run.

+            

+            yacctab:

+                Points to the yacc table that's used for optimized

+                mode. Only if you're modifying the parser, make 

+                this point to a local yacc table file

+                        

+            yacc_debug:

+                Generate a parser.out file that explains how yacc

+                built the parsing table from the grammar.

+        """

+        self.clex = CLexer(

+            error_func=self._lex_error_func,

+            type_lookup_func=self._lex_type_lookup_func)

+            

+        self.clex.build(

+            optimize=lex_optimize,

+            lextab=lextab)

+        self.tokens = self.clex.tokens

+        

+        rules_with_opt = [

+            'abstract_declarator',

+            'constant_expression',

+            'declaration_list',

+            'declaration_specifiers',

+            'expression',

+            'identifier_list',

+            'init_declarator_list',

+            'parameter_type_list',

+            'specifier_qualifier_list',

+            'statement_list',

+            'type_qualifier_list',

+        ]

+        

+        for rule in rules_with_opt:

+            self._create_opt_rule(rule)

+        

+        self.cparser = ply.yacc.yacc(

+            module=self, 

+            start='translation_unit',

+            debug=yacc_debug,

+            optimize=yacc_optimize,

+            tabmodule=yacctab)

+        

+        # A table of identifiers defined as typedef types during

+        # parsing.

+        #

+        self.typedef_table = set([])

+    

+    def parse(self, text, filename='', debuglevel=0):

+        """ Parses C code and returns an AST.

+        

+            text:

+                A string containing the C source code

+            

+            filename:

+                Name of the file being parsed (for meaningful

+                error messages)

+            

+            debuglevel:

+                Debug level to yacc

+        """

+        self.clex.filename = filename

+        self.clex.reset_lineno()

+        self.typedef_table = set([])

+        return self.cparser.parse(text, lexer=self.clex, debug=debuglevel)

+    

+    ######################--   PRIVATE   --######################

+    

+    def _lex_error_func(self, msg, line, column):

+        self._parse_error(msg, self._coord(line, column))

+    

+    def _lex_type_lookup_func(self, name):

+        """ Looks up types that were previously defined with

+            typedef. 

+            Passed to the lexer for recognizing identifiers that

+            are types.

+        """

+        return name in self.typedef_table

+    

+    def _add_typedef_type(self, name):

+        """ Adds names that were defined as new types with 

+            typedef.

+        """

+        self.typedef_table.add(name)

+    

+    # To understand what's going on here, read sections A.8.5 and 

+    # A.8.6 of K&R2 very carefully.

+    # 

+    # A C type consists of a basic type declaration, with a list

+    # of modifiers. For example:

+    #

+    # int *c[5];

+    #

+    # The basic declaration here is 'int x', and the pointer and

+    # the array are the modifiers.

+    #

+    # Basic declarations are represented by TypeDecl (from module

+    # c_ast) and the modifiers are FuncDecl, PtrDecl and 

+    # ArrayDecl.

+    #

+    # The standard states that whenever a new modifier is parsed,

+    # it should be added to the end of the list of modifiers. For

+    # example:

+    #

+    # K&R2 A.8.6.2: Array Declarators

+    #

+    # In a declaration T D where D has the form  

+    #   D1 [constant-expression-opt]  

+    # and the type of the identifier in the declaration T D1 is 

+    # "type-modifier T", the type of the 

+    # identifier of D is "type-modifier array of T"

+    #

+    # This is what this method does. The declarator it receives

+    # can be a list of declarators ending with TypeDecl. It 

+    # tacks the modifier to the end of this list, just before 

+    # the TypeDecl.

+    #

+    # Additionally, the modifier may be a list itself. This is 

+    # useful for pointers, that can come as a chain from the rule

+    # p_pointer. In this case, the whole modifier list is spliced 

+    # into the new location.

+    #

+    def _type_modify_decl(self, decl, modifier):

+        """ Tacks a type modifier on a declarator, and returns

+            the modified declarator.

+            

+            Note: the declarator and modifier may be modified

+        """

+        #~ print '****'

+        #~ decl.show(offset=3)

+        #~ modifier.show(offset=3)

+        #~ print '****'

+        

+        modifier_head = modifier

+        modifier_tail = modifier

+        

+        # The modifier may be a nested list. Reach its tail.

+        #

+        while modifier_tail.type: 

+            modifier_tail = modifier_tail.type

+        

+        # If the decl is a basic type, just tack the modifier onto

+        # it

+        #

+        if isinstance(decl, c_ast.TypeDecl):

+            modifier_tail.type = decl

+            return modifier

+        else:

+            # Otherwise, the decl is a list of modifiers. Reach

+            # its tail and splice the modifier onto the tail,

+            # pointing to the underlying basic type.

+            #

+            decl_tail = decl

+            

+            while not isinstance(decl_tail.type, c_ast.TypeDecl):

+                decl_tail = decl_tail.type

+            

+            modifier_tail.type = decl_tail.type

+            decl_tail.type = modifier_head

+            return decl

+

+    # Due to the order in which declarators are constructed,

+    # they have to be fixed in order to look like a normal AST.

+    # 

+    # When a declaration arrives from syntax construction, it has

+    # these problems:

+    # * The innermost TypeDecl has no type (because the basic

+    #   type is only known at the uppermost declaration level)

+    # * The declaration has no variable name, since that is saved

+    #   in the innermost TypeDecl

+    # * The typename of the declaration is a list of type 

+    #   specifiers, and not a node. Here, basic identifier types

+    #   should be separated from more complex types like enums

+    #   and structs.

+    #

+    # This method fixes these problem.

+    #

+    def _fix_decl_name_type(self, decl, typename):

+        """ Fixes a declaration. Modifies decl.

+        """

+        # Reach the underlying basic type

+        #

+        type = decl

+        while not isinstance(type, c_ast.TypeDecl):

+            type = type.type

+        

+        decl.name = type.declname

+        type.quals = decl.quals

+        

+        # The typename is a list of types. If any type in this 

+        # list isn't a simple string type, it must be the only

+        # type in the list (it's illegal to declare "int enum .."

+        # If all the types are basic, they're collected in the

+        # IdentifierType holder.

+        #

+        for tn in typename:

+            if not isinstance(tn, str):

+                if len(typename) > 1:

+                    self._parse_error(

+                        "Invalid multiple types specified", tn.coord)

+                else:

+                    type.type = tn

+                    return decl

+        

+        type.type = c_ast.IdentifierType(typename)

+        return decl

+    

+    def _add_declaration_specifier(self, declspec, newspec, kind):

+        """ Declaration specifiers are represented by a dictionary

+            with 3 entries:

+            * qual: a list of type qualifiers

+            * storage: a list of storage type qualifiers

+            * type: a list of type specifiers

+            

+            This method is given a declaration specifier, and a 

+            new specifier of a given kind.

+            Returns the declaration specifier, with the new 

+            specifier incorporated.

+        """

+        spec = declspec or dict(qual=[], storage=[], type=[])

+        spec[kind].append(newspec)

+        return spec

+    

+    def _build_function_definition(self, decl, spec, param_decls, body):

+        """ Builds a function definition.

+        """

+        declaration = c_ast.Decl(

+            name=None,

+            quals=spec['qual'],

+            storage=spec['storage'],

+            type=decl, 

+            init=None, 

+            bitsize=None, 

+            coord=decl.coord)

+        

+        typename = spec['type']

+        declaration = self._fix_decl_name_type(declaration, typename)

+        return c_ast.FuncDef(

+            decl=declaration,

+            param_decls=param_decls,

+            body=body,

+            coord=decl.coord)

+

+    def _select_struct_union_class(self, token):

+        """ Given a token (either STRUCT or UNION), selects the

+            appropriate AST class.

+        """

+        if token == 'struct':

+            return c_ast.Struct

+        else:

+            return c_ast.Union

+

+    ##

+    ## Precedence and associativity of operators

+    ##

+    precedence = (

+        ('left', 'LOR'),

+        ('left', 'LAND'),

+        ('left', 'OR'),

+        ('left', 'XOR'),

+        ('left', 'AND'),

+        ('left', 'EQ', 'NE'),

+        ('left', 'GT', 'GE', 'LT', 'LE'),

+        ('left', 'RSHIFT', 'LSHIFT'),

+        ('left', 'PLUS', 'MINUS'),

+        ('left', 'TIMES', 'DIVIDE', 'MOD')

+    )

+    

+    ##

+    ## Grammar productions

+    ## Implementation of the BNF defined in K&R2 A.13

+    ##

+    def p_translation_unit_1(self, p):

+        """ translation_unit    : external_declaration 

+        """

+        # Note: external_declaration is already a list

+        #

+        p[0] = c_ast.FileAST(p[1])

+    

+    def p_translation_unit_2(self, p):

+        """ translation_unit    : translation_unit external_declaration

+        """

+        p[1].ext.extend(p[2])

+        p[0] = p[1]

+    

+    # Declarations always come as lists (because they can be

+    # several in one line), so we wrap the function definition 

+    # into a list as well, to make the return value of 

+    # external_declaration homogenous.

+    #

+    def p_external_declaration_1(self, p):

+        """ external_declaration    : function_definition

+        """

+        p[0] = [p[1]]

+    

+    def p_external_declaration_2(self, p):

+        """ external_declaration    : declaration

+        """

+        p[0] = p[1]

+

+    def p_external_declaration_3(self, p):

+        """ external_declaration    : pp_directive

+        """

+        p[0] = p[1]

+

+    def p_pp_directive(self, p):

+        """ pp_directive  : PPHASH 

+        """

+        self._parse_error('Directives not supported yet', 

+            self._coord(p.lineno(1)))

+

+    # In function definitions, the declarator can be followed by

+    # a declaration list, for old "K&R style" function definitios.

+    #

+    def p_function_definition_1(self, p):

+        """ function_definition : declarator declaration_list_opt compound_statement

+        """

+        # no declaration specifiers

+        spec = dict(qual=[], storage=[], type=[])

+

+        p[0] = self._build_function_definition(

+            decl=p[1],

+            spec=spec, 

+            param_decls=p[2],

+            body=p[3])

+                    

+    def p_function_definition_2(self, p):

+        """ function_definition : declaration_specifiers declarator declaration_list_opt compound_statement

+        """

+        spec = p[1]

+

+        p[0] = self._build_function_definition(

+            decl=p[2],

+            spec=spec, 

+            param_decls=p[3],

+            body=p[4])

+        

+    def p_statement(self, p):

+        """ statement   : labeled_statement

+                        | expression_statement

+                        | compound_statement

+                        | selection_statement

+                        | iteration_statement    

+                        | jump_statement

+        """

+        p[0] = p[1]

+

+    # In C, declarations can come several in a line:

+    #   int x, *px, romulo = 5;

+    #

+    # However, for the AST, we will split them to separate Decl

+    # nodes.

+    #

+    # This rule splits its declarations and always returns a list

+    # of Decl nodes, even if it's one element long.

+    #

+    def p_decl_body(self, p):

+        """ decl_body : declaration_specifiers init_declarator_list_opt

+        """

+        spec = p[1]

+        is_typedef = 'typedef' in spec['storage']

+        decls = []

+

+        # p[2] (init_declarator_list_opt) is either a list or None

+        #

+        if p[2] is None:

+            # Then it's a declaration of a struct / enum tag,

+            # without an actual declarator.

+            #

+            type = spec['type']

+            if len(type) > 1:

+                coord = '?'

+                for t in type:

+                    if hasattr(t, 'coord'):

+                        coord = t.coord

+                        break

+                        

+                self._parse_error('Multiple type specifiers with a type tag', coord)

+            

+            decl = c_ast.Decl(

+                name=None,

+                quals=spec['qual'],

+                storage=spec['storage'],

+                type=type[0],

+                init=None,

+                bitsize=None,

+                coord=type[0].coord)

+            decls = [decl]

+        else:

+            for decl, init in p[2] or []:

+                if is_typedef:

+                    decl = c_ast.Typedef(

+                        name=None,

+                        quals=spec['qual'],

+                        storage=spec['storage'],

+                        type=decl,

+                        coord=decl.coord)

+                else:

+                    decl = c_ast.Decl(

+                        name=None,

+                        quals=spec['qual'],

+                        storage=spec['storage'],

+                        type=decl, 

+                        init=init, 

+                        bitsize=None, 

+                        coord=decl.coord)

+                

+                typename = spec['type']

+                fixed_decl = self._fix_decl_name_type(decl, typename)

+

+                # Add the type name defined by typedef to a

+                # symbol table (for usage in the lexer)

+                # 

+                if is_typedef:

+                    self._add_typedef_type(fixed_decl.name)

+

+                decls.append(fixed_decl)

+

+        p[0] = decls

+

+    # The declaration has been split to a decl_body sub-rule and

+    # SEMI, because having them in a single rule created a problem

+    # for defining typedefs.

+    #

+    # If a typedef line was directly followed by a line using the

+    # type defined with the typedef, the type would not be 

+    # recognized. This is because to reduce the declaration rule,

+    # the parser's lookahead asked for the token after SEMI, which

+    # was the type from the next line, and the lexer had no chance

+    # to see the updated type symbol table.

+    #

+    # Splitting solves this problem, because after seeing SEMI,

+    # the parser reduces decl_body, which actually adds the new

+    # type into the table to be seen by the lexer before the next

+    # line is reached.

+    #

+    def p_declaration(self, p):

+        """ declaration : decl_body SEMI 

+        """

+        p[0] = p[1]

+

+    # Since each declaration is a list of declarations, this

+    # rule will combine all the declarations and return a single

+    # list

+    # 

+    def p_declaration_list(self, p):

+        """ declaration_list    : declaration

+                                | declaration_list declaration

+        """

+        p[0] = p[1] if len(p) == 2 else p[1] + p[2]

+    

+    def p_declaration_specifiers_1(self, p):

+        """ declaration_specifiers  : type_qualifier declaration_specifiers_opt 

+        """

+        p[0] = self._add_declaration_specifier(p[2], p[1], 'qual')

+        

+    def p_declaration_specifiers_2(self, p):

+        """ declaration_specifiers  : type_specifier declaration_specifiers_opt

+        """

+        p[0] = self._add_declaration_specifier(p[2], p[1], 'type')

+        

+    def p_declaration_specifiers_3(self, p):

+        """ declaration_specifiers  : storage_class_specifier declaration_specifiers_opt

+        """

+        p[0] = self._add_declaration_specifier(p[2], p[1], 'storage')

+        

+    def p_storage_class_specifier(self, p):

+        """ storage_class_specifier : AUTO

+                                    | REGISTER

+                                    | STATIC

+                                    | EXTERN

+                                    | TYPEDEF

+        """

+        p[0] = p[1]

+        

+    def p_type_specifier_1(self, p):

+        """ type_specifier  : VOID

+                            | CHAR

+                            | SHORT

+                            | INT

+                            | LONG

+                            | FLOAT

+                            | DOUBLE

+                            | SIGNED

+                            | UNSIGNED

+                            | typedef_name

+                            | enum_specifier

+                            | struct_or_union_specifier

+        """

+        p[0] = p[1]

+    

+    def p_type_qualifier(self, p):

+        """ type_qualifier  : CONST

+                            | VOLATILE

+        """

+        p[0] = p[1]

+    

+    def p_init_declarator_list(self, p):

+        """ init_declarator_list    : init_declarator

+                                    | init_declarator_list COMMA init_declarator

+        """

+        p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]]

+

+    # Returns a (declarator, intializer) pair

+    # If there's no initializer, returns (declarator, None)

+    #

+    def p_init_declarator(self, p):

+        """ init_declarator : declarator

+                            | declarator EQUALS initializer

+        """

+        p[0] = (p[1], p[3] if len(p) > 2 else None)        

+    

+    def p_specifier_qualifier_list_1(self, p):

+        """ specifier_qualifier_list    : type_qualifier specifier_qualifier_list_opt

+        """

+        p[0] = self._add_declaration_specifier(p[2], p[1], 'qual')

+        

+    def p_specifier_qualifier_list_2(self, p):

+        """ specifier_qualifier_list    : type_specifier specifier_qualifier_list_opt

+        """

+        p[0] = self._add_declaration_specifier(p[2], p[1], 'type')

+

+    # TYPEID is allowed here (and in other struct/enum related tag names), because

+    # struct/enum tags reside in their own namespace and can be named the same as types

+    #

+    def p_struct_or_union_specifier_1(self, p):

+        """ struct_or_union_specifier   : struct_or_union ID

+                                        | struct_or_union TYPEID

+        """

+        klass = self._select_struct_union_class(p[1])

+        p[0] = klass(

+            name=p[2], 

+            decls=None, 

+            coord=self._coord(p.lineno(2)))

+

+    def p_struct_or_union_specifier_2(self, p):

+        """ struct_or_union_specifier : struct_or_union LBRACE struct_declaration_list RBRACE

+        """

+        klass = self._select_struct_union_class(p[1])

+        p[0] = klass(

+            name=None,

+            decls=p[3],

+            coord=self._coord(p.lineno(2)))

+

+    def p_struct_or_union_specifier_3(self, p):

+        """ struct_or_union_specifier   : struct_or_union ID LBRACE struct_declaration_list RBRACE

+                                        | struct_or_union TYPEID LBRACE struct_declaration_list RBRACE

+        """

+        klass = self._select_struct_union_class(p[1])

+        p[0] = klass(

+            name=p[2],

+            decls=p[4],

+            coord=self._coord(p.lineno(2)))

+

+    def p_struct_or_union(self, p):

+        """ struct_or_union : STRUCT 

+                            | UNION

+        """

+        p[0] = p[1]

+

+    # Combine all declarations into a single list

+    #

+    def p_struct_declaration_list(self, p):

+        """ struct_declaration_list     : struct_declaration

+                                        | struct_declaration_list struct_declaration

+        """

+        p[0] = p[1] if len(p) == 2 else p[1] + p[2]

+

+    def p_struct_declaration_1(self, p):

+        """ struct_declaration : specifier_qualifier_list struct_declarator_list SEMI

+        """

+        spec = p[1]

+        decls = []

+        

+        for struct_decl in p[2]:

+            decl = c_ast.Decl(

+                name=None,

+                quals=spec['qual'],

+                storage=spec['storage'],

+                type=struct_decl['decl'],

+                init=None,

+                bitsize=struct_decl['bitsize'],

+                coord=struct_decl['decl'].coord)

+            

+            typename = spec['type']

+            decls.append(self._fix_decl_name_type(decl, typename))

+        

+        p[0] = decls

+    

+    def p_struct_declarator_list(self, p):

+        """ struct_declarator_list  : struct_declarator

+                                    | struct_declarator_list COMMA struct_declarator

+        """

+        p[0] = p[1] + [p[3]] if len(p) == 4 else [p[1]]

+    

+    # struct_declarator passes up a dict with the keys: decl (for

+    # the underlying declarator) and bitsize (for the bitsize)

+    #

+    def p_struct_declarator_1(self, p):

+        """ struct_declarator : declarator

+        """

+        p[0] = {'decl': p[1], 'bitsize': None}

+    

+    def p_struct_declarator_2(self, p):

+        """ struct_declarator   : declarator COLON constant_expression

+                                | COLON constant_expression

+        """

+        if len(p) > 3:

+            p[0] = {'decl': p[1], 'bitsize': p[3]}

+        else:

+            p[0] = {'decl': None, 'bitsize': p[2]}

+    

+    def p_enum_specifier_1(self, p):

+        """ enum_specifier  : ENUM ID

+                            | ENUM TYPEID

+        """

+        p[0] = c_ast.Enum(p[2], None, self._coord(p.lineno(1)))

+    

+    def p_enum_specifier_2(self, p):

+        """ enum_specifier  : ENUM LBRACE enumerator_list RBRACE

+        """

+        p[0] = c_ast.Enum(None, p[3], self._coord(p.lineno(1)))

+    

+    def p_enum_specifier_3(self, p):

+        """ enum_specifier  : ENUM ID LBRACE enumerator_list RBRACE

+                            | ENUM TYPEID LBRACE enumerator_list RBRACE

+        """

+        p[0] = c_ast.Enum(p[2], p[4], self._coord(p.lineno(1)))

+        

+    def p_enumerator_list(self, p):

+        """ enumerator_list : enumerator

+                            | enumerator_list COMMA

+                            | enumerator_list COMMA enumerator

+        """

+        if len(p) == 2:

+            p[0] = c_ast.EnumeratorList([p[1]], p[1].coord)

+        elif len(p) == 3:

+            p[0] = p[1]

+        else:

+            p[1].enumerators.append(p[3])

+            p[0] = p[1]

+

+    def p_enumerator(self, p):

+        """ enumerator  : ID

+                        | ID EQUALS constant_expression

+        """

+        if len(p) == 2:

+            p[0] = c_ast.Enumerator(

+                        p[1], None, 

+                        self._coord(p.lineno(1)))

+        else:

+            p[0] = c_ast.Enumerator(

+                        p[1], p[3], 

+                        self._coord(p.lineno(1)))

+    

+    def p_declarator_1(self, p):

+        """ declarator  : direct_declarator 

+        """

+        p[0] = p[1]

+    

+    def p_declarator_2(self, p):

+        """ declarator  : pointer direct_declarator 

+        """

+        p[0] = self._type_modify_decl(p[2], p[1])

+    

+    def p_direct_declarator_1(self, p):

+        """ direct_declarator   : ID 

+        """

+        p[0] = c_ast.TypeDecl(

+            declname=p[1], 

+            type=None, 

+            quals=None,

+            coord=self._coord(p.lineno(1)))

+        

+    def p_direct_declarator_2(self, p):

+        """ direct_declarator   : LPAREN declarator RPAREN 

+        """

+        p[0] = p[2]

+        

+    def p_direct_declarator_3(self, p):

+        """ direct_declarator   : direct_declarator LBRACKET constant_expression_opt RBRACKET 

+        """

+        arr = c_ast.ArrayDecl(

+            type=None,

+            dim=p[3],

+            coord=p[1].coord)

+        

+        p[0] = self._type_modify_decl(decl=p[1], modifier=arr)

+

+    def p_direct_declarator_4(self, p):

+        """ direct_declarator   : direct_declarator LPAREN parameter_type_list RPAREN 

+                                | direct_declarator LPAREN identifier_list_opt RPAREN

+        """

+        func = c_ast.FuncDecl(

+            args=p[3],

+            type=None,

+            coord=p[1].coord)

+        

+        p[0] = self._type_modify_decl(decl=p[1], modifier=func)

+    

+    def p_pointer(self, p):

+        """ pointer : TIMES type_qualifier_list_opt

+                    | TIMES type_qualifier_list_opt pointer

+        """

+        coord = self._coord(p.lineno(1))

+        

+        p[0] = c_ast.PtrDecl(

+            quals=p[2] or [],

+            type=p[3] if len(p) > 3 else None,

+            coord=coord)

+    

+    def p_type_qualifier_list(self, p):

+        """ type_qualifier_list : type_qualifier

+                                | type_qualifier_list type_qualifier

+        """

+        p[0] = [p[1]] if len(p) == 2 else p[1] + [p[2]]

+    

+    def p_parameter_type_list(self, p):

+        """ parameter_type_list : parameter_list

+                                | parameter_list COMMA ELLIPSIS

+        """

+        if len(p) > 2: 

+            p[1].params.append(c_ast.EllipsisParam())

+        

+        p[0] = p[1]

+

+    def p_parameter_list(self, p):

+        """ parameter_list  : parameter_declaration

+                            | parameter_list COMMA parameter_declaration

+        """

+        if len(p) == 2: # single parameter

+            p[0] = c_ast.ParamList([p[1]], p[1].coord)

+        else:

+            p[1].params.append(p[3])

+            p[0] = p[1]

+

+    def p_parameter_declaration_1(self, p):

+        """ parameter_declaration   : declaration_specifiers declarator

+        """

+        spec = p[1]

+        decl = p[2]

+        

+        decl = c_ast.Decl(

+            name=None,

+            quals=spec['qual'],

+            storage=spec['storage'],

+            type=decl, 

+            init=None, 

+            bitsize=None, 

+            coord=decl.coord)

+        

+        typename = spec['type'] or ['int']

+        p[0] = self._fix_decl_name_type(decl, typename)

+        

+    def p_parameter_declaration_2(self, p):

+        """ parameter_declaration   : declaration_specifiers abstract_declarator_opt

+        """

+        spec = p[1]

+        decl = c_ast.Typename(

+            quals=spec['qual'], 

+            type=p[2] or c_ast.TypeDecl(None, None, None))

+            

+        typename = spec['type'] or ['int']

+        

+        p[0] = self._fix_decl_name_type(decl, typename)        

+    

+    def p_identifier_list(self, p):

+        """ identifier_list : identifier

+                            | identifier_list COMMA identifier

+        """

+        if len(p) == 2: # single parameter

+            p[0] = c_ast.ParamList([p[1]], p[1].coord)

+        else:

+            p[1].params.append(p[3])

+            p[0] = p[1]

+

+    def p_initializer_1(self, p):

+        """ initializer : assignment_expression

+        """

+        p[0] = p[1]

+    

+    def p_initializer_2(self, p):

+        """ initializer : LBRACE initializer_list RBRACE

+                        | LBRACE initializer_list COMMA RBRACE

+        """

+        p[0] = p[2]

+

+    def p_initializer_list(self, p):

+        """ initializer_list    : initializer

+                                | initializer_list COMMA initializer

+        """

+        if len(p) == 2: # single initializer

+            p[0] = c_ast.ExprList([p[1]], p[1].coord)

+        else:

+            p[1].exprs.append(p[3])

+            p[0] = p[1]

+        

+    def p_type_name(self, p):

+        """ type_name   : specifier_qualifier_list abstract_declarator_opt 

+        """

+        #~ print '=========='

+        #~ print p[1]

+        #~ print p[2]

+        #~ print p[2].children()

+        #~ print '=========='

+        

+        typename = c_ast.Typename(

+            quals=p[1]['qual'], 

+            type=p[2] or c_ast.TypeDecl(None, None, None))

+        

+        p[0] = self._fix_decl_name_type(typename, p[1]['type'])

+

+    def p_abstract_declarator_1(self, p):

+        """ abstract_declarator     : pointer

+        """

+        dummytype = c_ast.TypeDecl(None, None, None)

+        p[0] = self._type_modify_decl(

+            decl=dummytype, 

+            modifier=p[1])

+        

+    def p_abstract_declarator_2(self, p):

+        """ abstract_declarator     : pointer direct_abstract_declarator

+        """

+        p[0] = self._type_modify_decl(p[2], p[1])

+        

+    def p_abstract_declarator_3(self, p):

+        """ abstract_declarator     : direct_abstract_declarator

+        """

+        p[0] = p[1]

+    

+    # Creating and using direct_abstract_declarator_opt here 

+    # instead of listing both direct_abstract_declarator and the

+    # lack of it in the beginning of _1 and _2 caused two 

+    # shift/reduce errors.

+    #

+    def p_direct_abstract_declarator_1(self, p):

+        """ direct_abstract_declarator  : LPAREN abstract_declarator RPAREN """

+        p[0] = p[2]

+    

+    def p_direct_abstract_declarator_2(self, p):

+        """ direct_abstract_declarator  : direct_abstract_declarator LBRACKET constant_expression_opt RBRACKET 

+        """

+        arr = c_ast.ArrayDecl(

+            type=None,

+            dim=p[3],

+            coord=p[1].coord)

+        

+        p[0] = self._type_modify_decl(decl=p[1], modifier=arr)

+        

+    def p_direct_abstract_declarator_3(self, p):

+        """ direct_abstract_declarator  : LBRACKET constant_expression_opt RBRACKET 

+        """

+        p[0] = c_ast.ArrayDecl(

+            type=c_ast.TypeDecl(None, None, None),

+            dim=p[2],

+            coord=self._coord(p.lineno(1)))

+        

+    def p_direct_abstract_declarator_4(self, p):

+        """ direct_abstract_declarator  : direct_abstract_declarator LPAREN parameter_type_list_opt RPAREN 

+        """

+        func = c_ast.FuncDecl(

+            args=p[3],

+            type=None,

+            coord=p[1].coord)

+        

+        p[0] = self._type_modify_decl(decl=p[1], modifier=func)

+        

+    def p_direct_abstract_declarator_5(self, p):

+        """ direct_abstract_declarator  : LPAREN parameter_type_list_opt RPAREN 

+        """

+        p[0] = c_ast.FuncDecl(

+            args=p[2],

+            type=c_ast.TypeDecl(None, None, None),

+            coord=self._coord(p.lineno(1)))

+        

+    def p_compound_statement_1(self, p):

+        """ compound_statement : LBRACE statement_list_opt RBRACE """

+        p[0] = c_ast.Compound(

+            decls=None, 

+            stmts=p[2], 

+            coord=self._coord(p.lineno(1)))

+    

+    def p_compound_statement_2(self, p):

+        """ compound_statement : LBRACE declaration_list RBRACE """

+        p[0] = c_ast.Compound(

+            decls=p[2], 

+            stmts=None, 

+            coord=self._coord(p.lineno(1)))

+    

+    def p_compound_statement_3(self, p):

+        """ compound_statement : LBRACE declaration_list statement_list RBRACE """

+        #~ print '(((((('

+        #~ print p[2]

+        #~ print p[3]

+        #~ print '(((((('

+        p[0] = c_ast.Compound(

+            decls=p[2], 

+            stmts=p[3], 

+            coord=self._coord(p.lineno(1)))

+    

+    # Note: this doesn't create an AST node, but a list of AST 

+    # nodes that will be used as the statement list of a compound

+    #

+    def p_statement_list(self, p):

+        """ statement_list  : statement 

+                            | statement_list statement

+        """

+        if len(p) == 2: # single expr

+            p[0] = [p[1]] if p[1] else [] 

+        else:

+            p[0] = p[1] + ([p[2]] if p[2] else [])

+    

+    def p_labeled_statement_1(self, p):

+        """ labeled_statement : ID COLON statement """

+        p[0] = c_ast.Label(p[1], p[3], self._coord(p.lineno(1)))

+    

+    def p_labeled_statement_2(self, p):

+        """ labeled_statement : CASE constant_expression COLON statement """

+        p[0] = c_ast.Case(p[2], p[4], self._coord(p.lineno(1)))

+        

+    def p_labeled_statement_3(self, p):

+        """ labeled_statement : DEFAULT COLON statement """

+        p[0] = c_ast.Default(p[3], self._coord(p.lineno(1)))

+        

+    def p_selection_statement_1(self, p):

+        """ selection_statement : IF LPAREN expression RPAREN statement """

+        p[0] = c_ast.If(p[3], p[5], None, self._coord(p.lineno(1)))

+    

+    def p_selection_statement_2(self, p):

+        """ selection_statement : IF LPAREN expression RPAREN statement ELSE statement """

+        p[0] = c_ast.If(p[3], p[5], p[7], self._coord(p.lineno(1)))

+    

+    def p_selection_statement_3(self, p):

+        """ selection_statement : SWITCH LPAREN expression RPAREN statement """

+        p[0] = c_ast.Switch(p[3], p[5], self._coord(p.lineno(1)))

+    

+    def p_iteration_statement_1(self, p):

+        """ iteration_statement : WHILE LPAREN expression RPAREN statement """

+        p[0] = c_ast.While(p[3], p[5], self._coord(p.lineno(1)))

+    

+    def p_iteration_statement_2(self, p):

+        """ iteration_statement : DO statement WHILE LPAREN expression RPAREN """

+        p[0] = c_ast.DoWhile(p[5], p[2], self._coord(p.lineno(1)))

+    

+    def p_iteration_statement_3(self, p):

+        """ iteration_statement : FOR LPAREN expression_opt SEMI expression_opt SEMI expression_opt RPAREN statement """

+        p[0] = c_ast.For(p[3], p[5], p[7], p[9], self._coord(p.lineno(1)))

+    

+    def p_jump_statement_1(self, p):

+        """ jump_statement  : GOTO ID SEMI """

+        p[0] = c_ast.Goto(p[2], self._coord(p.lineno(1)))

+    

+    def p_jump_statement_2(self, p):

+        """ jump_statement  : BREAK SEMI """

+        p[0] = c_ast.Break(self._coord(p.lineno(1)))

+    

+    def p_jump_statement_3(self, p):

+        """ jump_statement  : CONTINUE SEMI """

+        p[0] = c_ast.Continue(self._coord(p.lineno(1)))

+        

+    def p_jump_statement_4(self, p):

+        """ jump_statement  : RETURN expression SEMI  

+                            | RETURN SEMI 

+        """

+        p[0] = c_ast.Return(p[2] if len(p) == 4 else None, self._coord(p.lineno(1)))

+    

+    def p_expression_statement(self, p):

+        """ expression_statement : expression_opt SEMI """

+        p[0] = p[1]

+    

+    def p_expression(self, p):

+        """ expression  : assignment_expression 

+                        | expression COMMA assignment_expression

+        """

+        if len(p) == 2:

+            p[0] = p[1]

+        else:

+            if not isinstance(p[1], c_ast.ExprList):

+                p[1] = c_ast.ExprList([p[1]], p[1].coord)

+            

+            p[1].exprs.append(p[3])

+            p[0] = p[1] 

+

+    def p_typedef_name(self, p):

+        """ typedef_name : TYPEID """

+        p[0] = p[1]

+

+    def p_assignment_expression(self, p):

+        """ assignment_expression   : conditional_expression

+                                    | unary_expression assignment_operator assignment_expression

+        """

+        if len(p) == 2:

+            p[0] = p[1]

+        else:

+            p[0] = c_ast.Assignment(p[2], p[1], p[3], p[1].coord)

+

+    # K&R2 defines these as many separate rules, to encode 

+    # precedence and associativity. Why work hard ? I'll just use

+    # the built in precedence/associativity specification feature

+    # of PLY. (see precedence declaration above)

+    #

+    def p_assignment_operator(self, p):

+        """ assignment_operator : EQUALS

+                                | XOREQUAL   

+                                | TIMESEQUAL  

+                                | DIVEQUAL    

+                                | MODEQUAL    

+                                | PLUSEQUAL   

+                                | MINUSEQUAL  

+                                | LSHIFTEQUAL 

+                                | RSHIFTEQUAL 

+                                | ANDEQUAL    

+                                | OREQUAL     

+        """

+        p[0] = p[1]

+        

+    def p_constant_expression(self, p):

+        """ constant_expression : conditional_expression """

+        p[0] = p[1]

+    

+    def p_conditional_expression(self, p):

+        """ conditional_expression  : binary_expression

+                                    | binary_expression CONDOP expression COLON conditional_expression

+        """

+        if len(p) == 2:

+            p[0] = p[1]

+        else:

+            p[0] = c_ast.TernaryOp(p[1], p[3], p[5], p[1].coord)

+    

+    def p_binary_expression(self, p):

+        """ binary_expression   : cast_expression

+                                | binary_expression TIMES binary_expression

+                                | binary_expression DIVIDE binary_expression

+                                | binary_expression MOD binary_expression

+                                | binary_expression PLUS binary_expression

+                                | binary_expression MINUS binary_expression

+                                | binary_expression RSHIFT binary_expression

+                                | binary_expression LSHIFT binary_expression

+                                | binary_expression LT binary_expression

+                                | binary_expression LE binary_expression

+                                | binary_expression GE binary_expression

+                                | binary_expression GT binary_expression

+                                | binary_expression EQ binary_expression

+                                | binary_expression NE binary_expression

+                                | binary_expression AND binary_expression

+                                | binary_expression OR binary_expression

+                                | binary_expression XOR binary_expression

+                                | binary_expression LAND binary_expression

+                                | binary_expression LOR binary_expression

+        """

+        if len(p) == 2:

+            p[0] = p[1]

+        else:

+            p[0] = c_ast.BinaryOp(p[2], p[1], p[3], p[1].coord)

+    

+    def p_cast_expression_1(self, p):

+        """ cast_expression : unary_expression """

+        p[0] = p[1]

+        

+    def p_cast_expression_2(self, p):

+        """ cast_expression : LPAREN type_name RPAREN cast_expression """

+        p[0] = c_ast.Cast(p[2], p[4], p[2].coord)

+    

+    def p_unary_expression_1(self, p):

+        """ unary_expression    : postfix_expression """

+        p[0] = p[1]

+    

+    def p_unary_expression_2(self, p):

+        """ unary_expression    : PLUSPLUS unary_expression 

+                                | MINUSMINUS unary_expression

+                                | unary_operator cast_expression

+        """

+        p[0] = c_ast.UnaryOp(p[1], p[2], p[2].coord)

+    

+    def p_unary_expression_3(self, p):

+        """ unary_expression    : SIZEOF unary_expression 

+                                | SIZEOF LPAREN type_name RPAREN

+        """

+        p[0] = c_ast.UnaryOp(

+            p[1], 

+            p[2] if len(p) == 3 else p[3], 

+            self._coord(p.lineno(1)))

+    

+    def p_unary_operator(self, p):

+        """ unary_operator  : AND

+                            | TIMES

+                            | PLUS

+                            | MINUS

+                            | NOT

+                            | LNOT

+        """

+        p[0] = p[1]

+                                

+    def p_postfix_exptession_1(self, p):

+        """ postfix_expression  : primary_expression """

+        p[0] = p[1]

+    

+    def p_postfix_exptession_2(self, p):

+        """ postfix_expression  : postfix_expression LBRACKET expression RBRACKET """

+        p[0] = c_ast.ArrayRef(p[1], p[3], p[1].coord)

+    

+    def p_postfix_exptession_3(self, p):

+        """ postfix_expression  : postfix_expression LPAREN argument_expression_list RPAREN

+                                | postfix_expression LPAREN RPAREN

+        """

+        p[0] = c_ast.FuncCall(p[1], p[3] if len(p) == 5 else None, p[1].coord)

+    

+    def p_postfix_expression_4(self, p):

+        """ postfix_expression  : postfix_expression PERIOD identifier

+                                | postfix_expression ARROW identifier

+        """

+        p[0] = c_ast.StructRef(p[1], p[2], p[3], p[1].coord)

+

+    def p_postfix_expression_5(self, p):

+        """ postfix_expression  : postfix_expression PLUSPLUS 

+                                | postfix_expression MINUSMINUS

+        """

+        p[0] = c_ast.UnaryOp('p' + p[2], p[1], p[1].coord)

+

+    def p_primary_expression_1(self, p):

+        """ primary_expression  : identifier """

+        p[0] = p[1]

+        

+    def p_primary_expression_2(self, p):

+        """ primary_expression  : constant """

+        p[0] = p[1]

+        

+    def p_primary_expression_3(self, p):

+        """ primary_expression  : STRING_LITERAL 

+                                | WSTRING_LITERAL

+        """

+        p[0] = c_ast.Constant(

+            'string', p[1], self._coord(p.lineno(1)))

+            

+    def p_primary_expression_4(self, p):

+        """ primary_expression  : LPAREN expression RPAREN """

+        p[0] = p[2]

+        

+    def p_argument_expression_list(self, p):

+        """ argument_expression_list    : assignment_expression 

+                                        | argument_expression_list COMMA assignment_expression

+        """

+        if len(p) == 2: # single expr

+            p[0] = c_ast.ExprList([p[1]], p[1].coord)

+        else:

+            p[1].exprs.append(p[3])

+            p[0] = p[1]

+        

+    def p_identifier(self, p):

+        """ identifier  : ID """

+        p[0] = c_ast.ID(p[1], self._coord(p.lineno(1)))

+        

+    def p_constant_1(self, p):

+        """ constant    : INT_CONST_DEC

+                        | INT_CONST_OCT

+                        | INT_CONST_HEX

+        """

+        p[0] = c_ast.Constant(

+            'int', p[1], self._coord(p.lineno(1)))

+            

+    def p_constant_2(self, p):

+        """ constant    : FLOAT_CONST """

+        p[0] = c_ast.Constant(

+            'float', p[1], self._coord(p.lineno(1)))

+    

+    def p_constant_3(self, p):

+        """ constant    : CHAR_CONST

+                        | WCHAR_CONST

+        """

+        p[0] = c_ast.Constant(

+            'char', p[1], self._coord(p.lineno(1)))

+        

+    def p_empty(self, p):

+        'empty : '

+        p[0] = None

+        

+    def p_error(self, p):

+        if p:

+            self._parse_error(

+                'before: %s' % p.value, 

+                self._coord(p.lineno))

+        else:

+            self._parse_error('At end of input', '')

+

+

+if __name__ == "__main__":

+    import pprint

+    import time

+    from portability import printme

+    

+    t1 = time.time()

+    parser = CParser(lex_optimize=True, yacc_debug=True, yacc_optimize=False)

+    printme(time.time() - t1)

+    

+    buf = ''' 

+        int (*k)(int);

+    '''

+    

+    # set debuglevel to 2 for debugging

+    t = parser.parse(buf, 'x.c', debuglevel=0)

+    t.show(showcoord=True)

diff --git a/pycparser/plyparser.py b/pycparser/plyparser.py
new file mode 100644
index 0000000..107b317
--- /dev/null
+++ b/pycparser/plyparser.py
@@ -0,0 +1,55 @@
+#-----------------------------------------------------------------

+# plyparser.py

+#

+# PLYParser class and other utilites for simplifying programming

+# parsers with PLY

+#

+# Copyright (C) 2008-2009, Eli Bendersky

+# License: LGPL

+#-----------------------------------------------------------------

+

+

+class Coord(object):

+    """ Coordinates of a syntactic element. Consists of:

+            - File name

+            - Line number

+            - (optional) column number, for the Lexer

+    """

+    def __init__(self, file, line, column=None):

+        self.file = file

+        self.line = line

+        self.column = column

+

+    def __str__(self):

+        str = "%s:%s" % (self.file, self.line)

+        if self.column: str += ":%s" % self.column

+        return str

+

+

+class ParseError(Exception): pass

+

+

+class PLYParser(object):
+    def _create_opt_rule(self, rulename):

+        """ Given a rule name, creates an optional ply.yacc rule

+            for it. The name of the optional rule is

+            <rulename>_opt

+        """

+        optname = rulename + '_opt'

+

+        def optrule(self, p):

+            p[0] = p[1]

+

+        optrule.__doc__ = '%s : empty\n| %s' % (optname, rulename)

+        optrule.__name__ = 'p_%s' % optname

+        setattr(self.__class__, optrule.__name__, optrule)

+    

+    def _coord(self, lineno, column=None):

+        return Coord(

+                file=self.clex.filename, 

+                line=lineno,

+                column=column)

+

+    def _parse_error(self, msg, coord):

+        raise ParseError("%s: %s" % (coord, msg))

+

diff --git a/pycparser/portability.py b/pycparser/portability.py
new file mode 100644
index 0000000..3893cec
--- /dev/null
+++ b/pycparser/portability.py
@@ -0,0 +1,18 @@
+#-----------------------------------------------------------------
+# pycparser: portability.py
+#
+# Portability code for working with different versions of Python
+#
+# Copyright (C) 2008-2010, Eli Bendersky
+# License: LGPL
+#----------------------
+import sys
+
+
+def printme(s):
+    sys.stdout.write(str(s))
+
+
+
+
+     
\ No newline at end of file
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..442c7d0
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,26 @@
+import os, sys

+from distutils.core import setup

+

+

+setup(

+    # metadata

+    name='pycparser',

+    description='C parser in Python',

+    long_description="""

+        pycparser is a complete parser of the C language, written in 

+        pure Python using the PLY parsing library.

+        It parses C code into an AST and can serve as a front-end for

+        C compilers or analysis tools.

+    """,

+    license='LGPL',

+    version='1.07',

+    author='Eli Bendersky',

+    maintainer='Eli Bendersky',

+    author_email='eliben@gmail.com',

+    url='http://code.google.com/p/pycparser/',

+    platforms='Cross Platform',

+    

+    packages=['pycparser'],

+)

+

+    

diff --git a/tests/all_tests.py b/tests/all_tests.py
new file mode 100644
index 0000000..0ed455c
--- /dev/null
+++ b/tests/all_tests.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+import unittest
+
+
+suite = unittest.TestLoader().loadTestsFromNames(
+    [
+        'test_c_lexer',
+        'test_c_ast',
+        'test_general',
+        'test_c_parser',
+    ]
+)
+    
+unittest.TextTestRunner(verbosity=1).run(suite)
diff --git a/tests/c_files/cppd_with_stdio_h.c b/tests/c_files/cppd_with_stdio_h.c
new file mode 100644
index 0000000..ab1426a
--- /dev/null
+++ b/tests/c_files/cppd_with_stdio_h.c
@@ -0,0 +1,5038 @@
+#line 1 "example_c_file.c"

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+#line 19 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+#line 25 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/_ansi.h"

+

+

+

+#line 11 "D:\eli\cpp_stuff\libc_include/_ansi.h"

+

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/newlib.h"

+

+#line 3 "D:\eli\cpp_stuff\libc_include/newlib.h"

+#line 16 "D:\eli\cpp_stuff\libc_include/_ansi.h"

+#line 1 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/machine/ieeefp.h"

+

+

+

+

+#line 52 "D:\eli\cpp_stuff\libc_include/machine/ieeefp.h"

+

+

+

+#line 58 "D:\eli\cpp_stuff\libc_include/machine/ieeefp.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 83 "D:\eli\cpp_stuff\libc_include/machine/ieeefp.h"

+

+#line 86 "D:\eli\cpp_stuff\libc_include/machine/ieeefp.h"

+

+#line 89 "D:\eli\cpp_stuff\libc_include/machine/ieeefp.h"

+

+

+#line 95 "D:\eli\cpp_stuff\libc_include/machine/ieeefp.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 5 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+

+

+#line 11 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 143 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 157 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 195 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+

+

+

+

+

+

+

+

+#line 207 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+

+

+

+

+#line 17 "D:\eli\cpp_stuff\libc_include/_ansi.h"

+

+

+

+#line 21 "D:\eli\cpp_stuff\libc_include/_ansi.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 30 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+#line 19 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 26 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 30 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+#line 35 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 39 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+#line 42 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+#line 53 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 56 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+#line 67 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+#line 76 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 98 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+#line 108 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 126 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+#line 131 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 170 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+typedef long unsigned int size_t;

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 243 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 246 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 290 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+#line 302 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+#line 310 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 361 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+#line 365 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 418 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+#line 422 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+#line 427 "D:\eli\cpp_stuff\libc_include/stddef.h"

+#line 35 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/stdarg.h"

+

+#line 19 "D:\eli\cpp_stuff\libc_include/stdarg.h"

+

+

+#line 26 "D:\eli\cpp_stuff\libc_include/stdarg.h"

+

+

+#line 30 "D:\eli\cpp_stuff\libc_include/stdarg.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+typedef char* __builtin_va_list;

+typedef __builtin_va_list __gnuc_va_list;

+

+

+

+#line 50 "D:\eli\cpp_stuff\libc_include/stdarg.h"

+

+

+

+

+

+

+

+

+

+

+

+

+#line 66 "D:\eli\cpp_stuff\libc_include/stdarg.h"

+

+

+

+

+

+

+

+

+

+

+

+#line 80 "D:\eli\cpp_stuff\libc_include/stdarg.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 98 "D:\eli\cpp_stuff\libc_include/stdarg.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 38 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+#line 44 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+#line 1 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+#line 6 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/_ansi.h"

+

+

+

+#line 11 "D:\eli\cpp_stuff\libc_include/_ansi.h"

+

+

+

+

+

+

+

+

+

+#line 21 "D:\eli\cpp_stuff\libc_include/_ansi.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 14 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+#line 1 "D:\eli\cpp_stuff\libc_include/sys/_types.h"

+

+

+

+#line 8 "D:\eli\cpp_stuff\libc_include/sys/_types.h"

+

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/machine/_types.h"

+

+#line 4 "D:\eli\cpp_stuff\libc_include/machine/_types.h"

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/machine/_default_types.h"

+

+#line 4 "D:\eli\cpp_stuff\libc_include/machine/_default_types.h"

+

+

+

+

+

+

+

+

+

+#line 15 "D:\eli\cpp_stuff\libc_include/machine/_default_types.h"

+

+#line 17 "D:\eli\cpp_stuff\libc_include/machine/_default_types.h"

+

+

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/limits.h"

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/newlib.h"

+

+#line 3 "D:\eli\cpp_stuff\libc_include/newlib.h"

+#line 5 "D:\eli\cpp_stuff\libc_include/limits.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 19 "D:\eli\cpp_stuff\libc_include/limits.h"

+

+

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+

+

+

+

+

+

+#line 11 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 143 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 157 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 195 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+

+

+

+

+

+

+

+

+#line 207 "D:\eli\cpp_stuff\libc_include/sys/config.h"

+

+

+

+

+

+

+

+#line 25 "D:\eli\cpp_stuff\libc_include/limits.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 79 "D:\eli\cpp_stuff\libc_include/limits.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 23 "D:\eli\cpp_stuff\libc_include/machine/_default_types.h"

+

+

+

+typedef signed char __int8_t ;

+typedef unsigned char __uint8_t ;

+

+

+

+

+

+

+

+

+typedef signed short __int16_t;

+typedef unsigned short __uint16_t;

+

+

+

+

+

+

+

+

+typedef __int16_t __int_least16_t;

+typedef __uint16_t __uint_least16_t;

+

+

+

+

+

+

+

+

+

+

+typedef signed int __int32_t;

+typedef unsigned int __uint32_t;

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+typedef __int32_t __int_least32_t;

+typedef __uint32_t __uint_least32_t;

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 8 "D:\eli\cpp_stuff\libc_include/machine/_types.h"

+

+#line 13 "D:\eli\cpp_stuff\libc_include/sys/_types.h"

+#line 1 "D:\eli\cpp_stuff\libc_include/sys/lock.h"

+

+

+

+

+

+typedef int _LOCK_T;

+typedef int _LOCK_RECURSIVE_T;

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 14 "D:\eli\cpp_stuff\libc_include/sys/_types.h"

+

+

+typedef long _off_t;

+

+

+

+

+

+

+

+typedef short __dev_t;

+

+

+

+

+typedef unsigned short __uid_t;

+

+

+typedef unsigned short __gid_t;

+

+

+

+ typedef long long _off64_t;

+

+

+

+#line 43 "D:\eli\cpp_stuff\libc_include/sys/_types.h"

+

+typedef long _fpos_t;

+

+

+

+

+

+

+

+

+

+

+

+typedef int _ssize_t;

+

+

+

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+#line 19 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 26 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 30 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+#line 35 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 39 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+#line 42 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+#line 53 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 56 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+#line 67 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+#line 76 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 98 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+#line 108 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 126 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+#line 131 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 170 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 243 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 246 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 290 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+#line 302 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+#line 310 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+typedef unsigned int wint_t;

+

+

+

+

+

+#line 361 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+#line 365 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 418 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+#line 422 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+#line 427 "D:\eli\cpp_stuff\libc_include/stddef.h"

+#line 64 "D:\eli\cpp_stuff\libc_include/sys/_types.h"

+

+

+

+typedef struct

+{

+  int __count;

+  union

+  {

+    wint_t __wch;

+    unsigned char __wchb[4];

+  } __value;

+} _mbstate_t;

+

+

+

+typedef _LOCK_RECURSIVE_T _flock_t;

+

+

+

+

+typedef void *_iconv_t;

+

+

+

+#line 15 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+typedef unsigned long __ULong;

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+struct _reent;

+

+

+#line 43 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+struct _Bigint

+{

+  struct _Bigint *_next;

+  int _k, _maxwds, _sign, _wds;

+  __ULong _x[1];

+};

+

+

+struct __tm

+{

+  int   __tm_sec;

+  int   __tm_min;

+  int   __tm_hour;

+  int   __tm_mday;

+  int   __tm_mon;

+  int   __tm_year;

+  int   __tm_wday;

+  int   __tm_yday;

+  int   __tm_isdst;

+};

+

+

+#line 68 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+struct _on_exit_args {

+	void *  _fnargs[32];

+	void *	_dso_handle[32];

+

+	__ULong _fntypes;

+#line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+	__ULong _is_cxa;

+};

+

+

+

+

+

+

+

+

+

+struct _atexit {

+	struct	_atexit *_next;

+	int	_ind;

+

+	void	(*_fns[32])(void);

+        struct _on_exit_args _on_exit_args;

+};

+

+

+

+#line 104 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+struct __sbuf {

+	unsigned char *_base;

+	int	_size;

+};

+

+

+#line 134 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+#line 141 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+struct __sFILE {

+  unsigned char *_p;

+  int	_r;

+  int	_w;

+  short	_flags;

+  short	_file;

+  struct __sbuf _bf;

+  int	_lbfsize;

+

+

+

+

+

+

+ char * _cookie;

+

+ int(*_read)();

+#line 176 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+ int(*_write)();

+#line 178 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+  _fpos_t(*_seek)();

+  int(*_close)();

+

+

+  struct __sbuf _ub;

+  unsigned char *_up;

+  int	_ur;

+

+

+  unsigned char _ubuf[3];

+  unsigned char _nbuf[1];

+

+

+  struct __sbuf _lb;

+

+

+  int	_blksize;

+  int	_offset;

+

+

+  struct _reent *_data;

+

+

+

+  _flock_t _lock;

+

+};

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+typedef struct __sFILE   __FILE;

+

+

+

+struct _glue

+{

+  struct _glue *_next;

+  int _niobs;

+  __FILE *_iobs;

+};

+

+

+#line 284 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+struct _rand48 {

+  unsigned short _seed[3];

+  unsigned short _mult[3];

+  unsigned short _add;

+

+

+

+

+};

+

+

+

+

+

+

+

+#line 313 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 344 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+#line 350 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 420 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 452 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 474 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 478 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 482 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+#line 494 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+#line 496 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 503 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+#line 505 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 508 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 531 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+#line 533 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 536 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+struct _reent

+{

+  int _errno;

+

+

+#line 571 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+  __FILE *_stdin, *_stdout, *_stderr;

+

+  int  _inc;

+  char _emergency[25];

+

+  int _current_category;

+ char *_current_locale;

+

+  int __sdidinit;

+

+  void(*__cleanup)();

+

+

+  struct _Bigint *_result;

+  int _result_k;

+  struct _Bigint *_p5s;

+  struct _Bigint **_freelist;

+

+

+  int _cvtlen;

+  char *_cvtbuf;

+

+  union

+    {

+      struct

+        {

+          unsigned int _unused_rand;

+          char * _strtok_last;

+          char _asctime_buf[26];

+          struct __tm _localtime_buf;

+          int _gamma_signgam;

+ unsigned long long _rand_next;

+          struct _rand48 _r48;

+          _mbstate_t _mblen_state;

+          _mbstate_t _mbtowc_state;

+          _mbstate_t _wctomb_state;

+          char _l64a_buf[8];

+          char _signal_buf[24];

+          int _getdate_err;

+          _mbstate_t _mbrlen_state;

+          _mbstate_t _mbrtowc_state;

+          _mbstate_t _mbsrtowcs_state;

+          _mbstate_t _wcrtomb_state;

+          _mbstate_t _wcsrtombs_state;

+        } _reent;

+

+#line 619 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+      struct

+        {

+

+          unsigned char * _nextf[30];

+          unsigned int _nmalloc[30];

+        } _unused;

+    } _new;

+

+

+  struct _atexit *_atexit;

+  struct _atexit _atexit0;

+

+

+  void (**(_sig_func))(int);

+

+

+#line 637 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+  struct _glue __sglue;

+  __FILE __sf[3];

+};

+

+

+#line 689 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 751 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 791 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+extern struct _reent *_impure_ptr;

+extern struct _reent * _global_impure_ptr;

+

+void _reclaim_reent();

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 46 "D:\eli\cpp_stuff\libc_include/stdio.h"

+#line 1 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+#line 17 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/_ansi.h"

+

+

+

+#line 11 "D:\eli\cpp_stuff\libc_include/_ansi.h"

+

+

+

+

+

+

+

+

+

+#line 21 "D:\eli\cpp_stuff\libc_include/_ansi.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 21 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/machine/_types.h"

+

+#line 4 "D:\eli\cpp_stuff\libc_include/machine/_types.h"

+

+

+

+

+

+#line 26 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+

+#line 33 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/sys/_types.h"

+

+

+

+#line 8 "D:\eli\cpp_stuff\libc_include/sys/_types.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 43 "D:\eli\cpp_stuff\libc_include/sys/_types.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 62 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+

+

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+#line 19 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 26 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 30 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+#line 35 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 39 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+#line 42 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+#line 53 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 56 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+#line 67 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+#line 76 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 98 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+#line 108 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 126 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+#line 131 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+typedef long int ptrdiff_t;

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 170 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 243 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+#line 246 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 290 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+#line 302 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+#line 310 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+typedef int wchar_t;

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 361 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+#line 365 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 418 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+#line 422 "D:\eli\cpp_stuff\libc_include/stddef.h"

+

+

+

+

+#line 427 "D:\eli\cpp_stuff\libc_include/stddef.h"

+#line 70 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+#line 1 "D:\eli\cpp_stuff\libc_include/machine/types.h"

+

+

+

+

+#line 9 "D:\eli\cpp_stuff\libc_include/machine/types.h"

+

+

+

+

+

+

+

+

+

+

+typedef long int __off_t;

+typedef int __pid_t;

+

+

+

+typedef long int __loff_t;

+

+

+

+

+

+

+#line 71 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+#line 79 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+typedef	unsigned char	u_char;

+typedef	unsigned short	u_short;

+typedef	unsigned int	u_int;

+typedef	unsigned long	u_long;

+

+

+

+typedef	unsigned short	ushort;

+typedef	unsigned int	uint;

+

+

+

+typedef unsigned long clock_t;

+

+

+

+

+typedef long time_t;

+

+

+

+

+struct timespec {

+  time_t  tv_sec;

+  long    tv_nsec;

+};

+

+struct itimerspec {

+  struct timespec  it_interval;

+  struct timespec  it_value;

+};

+

+

+typedef	long	daddr_t;

+typedef	char *	caddr_t;

+

+

+

+#line 131 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+typedef	unsigned short	ino_t;

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 160 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+typedef _off_t	off_t;

+typedef __dev_t dev_t;

+typedef __uid_t uid_t;

+typedef __gid_t gid_t;

+

+

+typedef int pid_t;

+

+typedef	long key_t;

+

+typedef _ssize_t ssize_t;

+

+

+

+

+

+

+

+

+

+

+

+

+

+typedef unsigned int mode_t;

+

+

+

+

+typedef unsigned short nlink_t;

+

+

+#line 200 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+

+

+#line 209 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+

+

+typedef	long	fd_mask;

+

+

+

+

+

+

+#line 221 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+typedef	struct _types_fd_set {

+	fd_mask	fds_bits[(((64)+(((sizeof (fd_mask) * 8))-1))/((sizeof (fd_mask) * 8)))];

+} _types_fd_set;

+

+

+

+

+

+

+

+#line 236 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+

+

+

+

+

+

+typedef unsigned long clockid_t;

+

+

+

+

+typedef unsigned long timer_t;

+

+

+

+typedef unsigned long useconds_t;

+typedef long suseconds_t;

+

+#line 1 "D:\eli\cpp_stuff\libc_include/sys/features.h"

+

+#line 20 "D:\eli\cpp_stuff\libc_include/sys/features.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 257 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+

+#line 266 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+

+

+

+#line 273 "D:\eli\cpp_stuff\libc_include/sys/types.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 47 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+typedef __FILE FILE;

+

+

+

+

+

+

+

+

+typedef _fpos_t fpos_t;

+

+

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/sys/stdio.h"

+

+

+

+#line 1 "D:\eli\cpp_stuff\libc_include/sys/lock.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 5 "D:\eli\cpp_stuff\libc_include/sys/stdio.h"

+#line 1 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+#line 6 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 43 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 68 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+#line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 104 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+#line 134 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+#line 141 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 284 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 313 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 344 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+#line 350 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 420 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 452 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 474 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 478 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 482 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+#line 494 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+#line 496 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 503 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+#line 505 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 508 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 531 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+#line 533 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 536 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 571 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 619 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 637 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+#line 689 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+#line 751 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 791 "D:\eli\cpp_stuff\libc_include/sys/reent.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 6 "D:\eli\cpp_stuff\libc_include/sys/stdio.h"

+

+

+#line 11 "D:\eli\cpp_stuff\libc_include/sys/stdio.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 66 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 96 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 163 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+

+

+

+FILE * tmpfile();

+char * tmpnam();

+int fclose();

+int fflush();

+FILE * freopen();

+void setbuf();

+int setvbuf();

+int fprintf();

+#line 179 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int fscanf();

+#line 181 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int printf();

+#line 183 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int scanf();

+#line 185 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int sscanf();

+#line 187 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vfprintf();

+#line 189 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vprintf();

+#line 191 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vsprintf();

+#line 193 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int fgetc();

+char * fgets();

+int fputc();

+int fputs();

+int getc();

+int getchar();

+char * gets();

+int putc();

+int putchar();

+int puts();

+int ungetc();

+size_t fread();

+size_t fwrite();

+

+

+

+int fgetpos();

+

+int fseek();

+

+

+

+int fsetpos();

+

+long ftell();

+void rewind();

+void clearerr();

+int feof();

+int ferror();

+void perror();

+

+FILE * fopen();

+int sprintf();

+#line 227 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int remove();

+int rename();

+

+

+

+

+

+

+int fseeko();

+off_t ftello();

+

+

+int asiprintf();

+#line 241 "D:\eli\cpp_stuff\libc_include/stdio.h"

+char * asniprintf();

+#line 243 "D:\eli\cpp_stuff\libc_include/stdio.h"

+char * asnprintf();

+#line 245 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int asprintf();

+#line 247 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+int diprintf();

+#line 250 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+int fcloseall();

+int fiprintf();

+#line 254 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int fiscanf();

+#line 256 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int iprintf();

+#line 258 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int iscanf();

+#line 260 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int siprintf();

+#line 262 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int siscanf();

+#line 264 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int snprintf();

+#line 266 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int sniprintf();

+#line 268 "D:\eli\cpp_stuff\libc_include/stdio.h"

+char * tempnam();

+int vasiprintf();

+#line 271 "D:\eli\cpp_stuff\libc_include/stdio.h"

+char * vasniprintf();

+#line 273 "D:\eli\cpp_stuff\libc_include/stdio.h"

+char * vasnprintf();

+#line 275 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vasprintf();

+#line 277 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vdiprintf();

+#line 279 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vfiprintf();

+#line 281 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vfiscanf();

+#line 283 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vfscanf();

+#line 285 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int viprintf();

+#line 287 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int viscanf();

+#line 289 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vscanf();

+#line 291 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vsiprintf();

+#line 293 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vsiscanf();

+#line 295 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vsniprintf();

+#line 297 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vsnprintf();

+#line 299 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int vsscanf();

+#line 301 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+#line 307 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+FILE * fdopen();

+

+int fileno();

+int getw();

+int pclose();

+FILE * popen();

+int putw();

+void setbuffer();

+int setlinebuf();

+int getc_unlocked();

+int getchar_unlocked();

+void flockfile();

+int ftrylockfile();

+void funlockfile();

+int putc_unlocked();

+int putchar_unlocked();

+

+

+

+#line 331 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+int dprintf();

+#line 337 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+FILE * fmemopen();

+

+

+FILE * open_memstream();

+

+int vdprintf();

+#line 345 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+#line 351 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+int _asiprintf_r();

+#line 354 "D:\eli\cpp_stuff\libc_include/stdio.h"

+char * _asniprintf_r();

+#line 356 "D:\eli\cpp_stuff\libc_include/stdio.h"

+char * _asnprintf_r();

+#line 358 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _asprintf_r();

+#line 360 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _diprintf_r();

+#line 362 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _dprintf_r();

+#line 364 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _fclose_r();

+int _fcloseall_r();

+FILE * _fdopen_r();

+int _fflush_r();

+char * _fgets_r();

+int _fiprintf_r();

+#line 371 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _fiscanf_r();

+#line 373 "D:\eli\cpp_stuff\libc_include/stdio.h"

+FILE * _fmemopen_r();

+FILE * _fopen_r();

+int _fprintf_r();

+#line 377 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _fputc_r();

+int _fputs_r();

+size_t _fread_r();

+int _fscanf_r();

+#line 382 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _fseek_r();

+long _ftell_r();

+size_t _fwrite_r();

+int _getc_r();

+int _getc_unlocked_r();

+int _getchar_r();

+int _getchar_unlocked_r();

+char * _gets_r();

+int _iprintf_r();

+#line 392 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _iscanf_r();

+#line 394 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _mkstemp_r();

+char * _mktemp_r();

+FILE * _open_memstream_r();

+void _perror_r();

+int _printf_r();

+#line 400 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _putc_r();

+int _putc_unlocked_r();

+int _putchar_unlocked_r();

+int _putchar_r();

+int _puts_r();

+int _remove_r();

+int _rename_r();

+#line 408 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _scanf_r();

+#line 410 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _siprintf_r();

+#line 412 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _siscanf_r();

+#line 414 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _sniprintf_r();

+#line 416 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _snprintf_r();

+#line 418 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _sprintf_r();

+#line 420 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _sscanf_r();

+#line 422 "D:\eli\cpp_stuff\libc_include/stdio.h"

+char * _tempnam_r();

+FILE * _tmpfile_r();

+char * _tmpnam_r();

+int _ungetc_r();

+int _vasiprintf_r();

+#line 428 "D:\eli\cpp_stuff\libc_include/stdio.h"

+char * _vasniprintf_r();

+#line 430 "D:\eli\cpp_stuff\libc_include/stdio.h"

+char * _vasnprintf_r();

+#line 432 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vasprintf_r();

+#line 434 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vdiprintf_r();

+#line 436 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vdprintf_r();

+#line 438 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vfiprintf_r();

+#line 440 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vfiscanf_r();

+#line 442 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vfprintf_r();

+#line 444 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vfscanf_r();

+#line 446 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _viprintf_r();

+#line 448 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _viscanf_r();

+#line 450 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vprintf_r();

+#line 452 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vscanf_r();

+#line 454 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vsiprintf_r();

+#line 456 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vsiscanf_r();

+#line 458 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vsniprintf_r();

+#line 460 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vsnprintf_r();

+#line 462 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vsprintf_r();

+#line 464 "D:\eli\cpp_stuff\libc_include/stdio.h"

+int _vsscanf_r();

+#line 466 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+ssize_t __getdelim();

+ssize_t __getline();

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 493 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+int __srget_r();

+int __swbuf_r();

+

+

+#line 500 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+

+

+

+

+

+FILE	* funopen();

+#line 514 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+#line 518 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+#line 520 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+typedef ssize_t cookie_read_function_t(void *__cookie, char *__buf, size_t __n);

+typedef ssize_t cookie_write_function_t(void *__cookie, const char *__buf,

+					size_t __n);

+

+

+

+

+typedef int cookie_seek_function_t(void *__cookie, off_t *__off, int __whence);

+

+typedef int cookie_close_function_t(void *__cookie);

+typedef struct

+{

+

+#line 535 "D:\eli\cpp_stuff\libc_include/stdio.h"

+  cookie_read_function_t  *read;

+  cookie_write_function_t *write;

+  cookie_seek_function_t  *seek;

+  cookie_close_function_t *close;

+} cookie_io_functions_t;

+FILE * fopencookie();

+#line 542 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+#line 549 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+#line 574 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+

+#line 580 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 603 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+

+

+

+

+#line 613 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+#line 621 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+#line 626 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 657 "D:\eli\cpp_stuff\libc_include/stdio.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+#line 4 "example_c_file.c"

+

+#line 8 "example_c_file.c"

+

+char tav = 'b';

+char maav = L"'guruguru\n";

+char* moral = "ain't I \\\"\\\t\" a nice string?\"\"";

+char* comment_inside = "but you will /* see it */!!!!";

+char* i_have_newlines = "line one\nline two\nline three";

+

+int main()

+{

+    auto char* multi = "a multi";

+}

+

+

+

+

+

diff --git a/tests/c_files/example_c_file.c b/tests/c_files/example_c_file.c
new file mode 100644
index 0000000..17b2ac4
--- /dev/null
+++ b/tests/c_files/example_c_file.c
@@ -0,0 +1,12 @@
+char tav = 'b';

+char* moral = "ain't I \\\"\\\t\" a nice string?\"\"";

+char* comment_inside = "but you will /* see it */!!!!";

+char* i_have_newlines = "line one\nline two\nline three";

+

+int main()

+{

+    auto char* multi = "a multi";

+}

+

+

+

diff --git a/tests/c_files/memmgr.c b/tests/c_files/memmgr.c
new file mode 100644
index 0000000..6036ec6
--- /dev/null
+++ b/tests/c_files/memmgr.c
@@ -0,0 +1,206 @@
+//----------------------------------------------------------------

+// Statically-allocated memory manager

+//

+// by Eli Bendersky (eliben@gmail.com)

+//  

+// 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/tests/c_files/memmgr.h b/tests/c_files/memmgr.h
new file mode 100644
index 0000000..ae8212d
--- /dev/null
+++ b/tests/c_files/memmgr.h
@@ -0,0 +1,96 @@
+//----------------------------------------------------------------

+// Statically-allocated memory manager

+//

+// by Eli Bendersky (eliben@gmail.com)

+//  

+// 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/tests/c_files/memmgr_with_h.c b/tests/c_files/memmgr_with_h.c
new file mode 100644
index 0000000..8ea6ff6
--- /dev/null
+++ b/tests/c_files/memmgr_with_h.c
@@ -0,0 +1,350 @@
+#line 1 "memmgr.c"

+

+

+

+

+

+

+

+#line 1 "./memmgr.h"

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+typedef unsigned char byte;

+typedef unsigned long ulong;

+

+

+

+

+

+

+void memmgr_init();

+

+

+

+void* memmgr_alloc(ulong nbytes);

+

+

+

+void memmgr_free(void* ap);

+

+

+

+

+void memmgr_print_stats();

+

+

+

+#line 9 "memmgr.c"

+

+typedef ulong Align;

+

+union mem_header_union

+{

+    struct

+    {

+

+

+        union mem_header_union* next;

+

+

+

+        ulong size;

+    } s;

+

+

+

+    Align align_dummy;

+};

+

+typedef union mem_header_union mem_header_t;

+

+

+

+static mem_header_t base;

+

+

+

+static mem_header_t* freep = 0;

+

+

+

+static byte pool[8 * 1024] = {0};

+static ulong pool_free_pos = 0;

+

+

+void memmgr_init()

+{

+    base.s.next = 0;

+    base.s.size = 0;

+    freep = 0;

+    pool_free_pos = 0;

+}

+

+

+void memmgr_print_stats()

+{

+

+    mem_header_t* p;

+

+    printf("------ Memory manager stats ------\n\n");

+    printf(    "Pool: free_pos = %lu (%lu bytes left)\n\n",

+            pool_free_pos,8 * 1024 - pool_free_pos);

+

+    p = (mem_header_t*) pool;

+

+    while (p < (mem_header_t*) (pool + pool_free_pos))

+    {

+        printf(    "  * Addr: 0x%8lu; Size: %8lu\n",

+                p, p->s.size);

+

+        p += p->s.size;

+    }

+

+    printf("\nFree list:\n\n");

+

+    if (freep)

+    {

+        p = freep;

+

+        while (1)

+        {

+            printf(    "  * Addr: 0x%8lu; Size: %8lu; Next: 0x%8lu\n",

+                    p, p->s.size, p->s.next);

+

+            p = p->s.next;

+

+            if (p == freep)

+                break;

+        }

+    }

+    else

+    {

+        printf("Empty\n");

+    }

+

+    printf("\n");

+

+}

+

+

+static mem_header_t* get_mem_from_pool(ulong nquantas)

+{

+    ulong total_req_size;

+

+    mem_header_t* h;

+

+    if (nquantas < 16)

+        nquantas = 16;

+

+    total_req_size = nquantas * sizeof(mem_header_t);

+

+    if (pool_free_pos + total_req_size <= 8 * 1024)

+    {

+        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;

+}

+

+

+

+

+

+

+

+

+

+

+void* memmgr_alloc(ulong nbytes)

+{

+    mem_header_t* p;

+    mem_header_t* prevp;

+

+

+

+

+

+    ulong nquantas = (nbytes + sizeof(mem_header_t) - 1) / sizeof(mem_header_t) + 1;

+

+

+

+

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

+    {

+

+        if (p->s.size >= nquantas)

+        {

+

+            if (p->s.size == nquantas)

+            {

+

+

+

+                prevp->s.next = p->s.next;

+            }

+            else

+            {

+                p->s.size -= nquantas;

+                p += p->s.size;

+                p->s.size = nquantas;

+            }

+

+            freep = prevp;

+            return (void*) (p + 1);

+        }

+

+

+

+

+

+

+

+        else if (p == freep)

+        {

+            if ((p = get_mem_from_pool(nquantas)) == 0)

+            {

+

+

+

+                return 0;

+            }

+        }

+    }

+}

+

+

+

+

+

+

+

+void memmgr_free(void* ap)

+{

+    mem_header_t* block;

+    mem_header_t* p;

+

+

+    block = ((mem_header_t*) ap) - 1;

+

+

+

+

+    for (p = freep; !(block > p && block < p->s.next); p = p->s.next)

+    {

+

+

+

+

+

+        if (p >= p->s.next && (block > p || block < p->s.next))

+            break;

+    }

+

+

+

+    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;

+    }

+

+

+

+    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/tests/c_files/year.c b/tests/c_files/year.c
new file mode 100644
index 0000000..c0f583d
--- /dev/null
+++ b/tests/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/tests/test_c_ast.py b/tests/test_c_ast.py
new file mode 100644
index 0000000..d5794e1
--- /dev/null
+++ b/tests/test_c_ast.py
@@ -0,0 +1,89 @@
+import pprint

+import re

+import sys

+import unittest

+

+sys.path.insert(0, '..')

+import pycparser.c_ast as c_ast

+

+

+class Test_c_ast(unittest.TestCase):

+    def test_BinaryOp(self):
+        b1 = c_ast.BinaryOp(

+            op='+', 

+            left=c_ast.Constant(type='int', value='6'),

+            right=c_ast.ID(name='joe'))

+

+        self.failUnless(isinstance(b1.left, c_ast.Constant))

+        self.assertEqual(b1.left.type, 'int')

+        self.assertEqual(b1.left.value, '6')

+        

+        self.failUnless(isinstance(b1.right, c_ast.ID))

+        self.assertEqual(b1.right.name, 'joe')

+

+

+class TestNodeVisitor(unittest.TestCase):

+    class ConstantVisitor(c_ast.NodeVisitor):

+        def __init__(self):

+            self.values = []

+        

+        def visit_Constant(self, node):

+            self.values.append(node.value)

+    

+    def test_scalar_children(self):

+        b1 = c_ast.BinaryOp(

+            op='+', 

+            left=c_ast.Constant(type='int', value='6'),

+            right=c_ast.ID(name='joe'))

+    

+        cv = self.ConstantVisitor()

+        cv.visit(b1)

+        

+        self.assertEqual(cv.values, ['6'])

+        

+        b2 = c_ast.BinaryOp(

+            op='*',

+            left=c_ast.Constant(type='int', value='111'),

+            right=b1)

+        

+        b3 = c_ast.BinaryOp(

+            op='^',

+            left=b2,

+            right=b1)

+        

+        cv = self.ConstantVisitor()

+        cv.visit(b3)

+        

+        self.assertEqual(cv.values, ['111', '6', '6'])

+

+    def tests_list_children(self):
+        c1 = c_ast.Constant(type='float', value='5.6')

+        c2 = c_ast.Constant(type='char', value='t')

+        

+        b1 = c_ast.BinaryOp(

+            op='+',

+            left=c1,

+            right=c2)

+        

+        b2 = c_ast.BinaryOp(

+            op='-',

+            left=b1,

+            right=c2)

+

+        comp = c_ast.Compound(

+            decls=[b1, b2],

+            stmts=[c1, c2])

+        

+        cv = self.ConstantVisitor()

+        cv.visit(comp)

+        

+        self.assertEqual(cv.values, 

+            ['5.6', 't', '5.6', 't', 't', '5.6', 't'])

+

+

+if __name__ == '__main__':

+    unittest.main()

+

+

+

+

diff --git a/tests/test_c_lexer.py b/tests/test_c_lexer.py
new file mode 100644
index 0000000..6a2f42a
--- /dev/null
+++ b/tests/test_c_lexer.py
@@ -0,0 +1,327 @@
+import re

+import sys

+import unittest

+

+sys.path.insert(0, '..')

+from pycparser.c_lexer import CLexer

+

+

+def token_list(clex):

+    return list(iter(clex.token, None))

+

+

+def token_types(clex):
+    return [i.type for i in token_list(clex)]

+

+

+class TestCLexerNoErrors(unittest.TestCase):

+    """ Test lexing of strings that are not supposed to cause

+        errors. Therefore, the error_func passed to the lexer

+        raises an exception.
+    """

+    def error_func(self, msg, line, column):
+        self.fail(msg)

+    

+    def type_lookup_func(self, typ):

+        if typ.startswith('mytype'):

+            return True
+        else:

+            return False

+    

+    def setUp(self):
+        self.clex = CLexer(self.error_func, self.type_lookup_func)

+        self.clex.build(optimize=False)

+    

+    def assertTokensTypes(self, str, types):

+        self.clex.input(str)
+        self.assertEqual(token_types(self.clex), types)

+    

+    def test_trivial_tokens(self):

+        self.assertTokensTypes('1', ['INT_CONST_DEC'])

+        self.assertTokensTypes('-', ['MINUS'])

+        self.assertTokensTypes('volatile', ['VOLATILE'])

+        self.assertTokensTypes('...', ['ELLIPSIS'])

+        self.assertTokensTypes('++', ['PLUSPLUS'])

+        self.assertTokensTypes('case int', ['CASE', 'INT'])

+        self.assertTokensTypes('caseint', ['ID'])

+        self.assertTokensTypes('i ^= 1;', ['ID', 'XOREQUAL', 'INT_CONST_DEC', 'SEMI'])

+        

+    def test_id_typeid(self):
+        self.assertTokensTypes('myt', ['ID'])

+        self.assertTokensTypes('mytype', ['TYPEID'])

+        self.assertTokensTypes('mytype6 var', ['TYPEID', 'ID'])

+    

+    def test_integer_constants(self):

+        self.assertTokensTypes('12', ['INT_CONST_DEC'])

+        self.assertTokensTypes('12u', ['INT_CONST_DEC'])

+        self.assertTokensTypes('199872Ul', ['INT_CONST_DEC'])

+        

+        self.assertTokensTypes('077', ['INT_CONST_OCT'])

+        self.assertTokensTypes('0123456L', ['INT_CONST_OCT'])

+               

+        self.assertTokensTypes('0xf7', ['INT_CONST_HEX'])

+        self.assertTokensTypes('0x01202AAbbf7Ul', ['INT_CONST_HEX'])

+        

+        # no 0 before x, so ID catches it

+        self.assertTokensTypes('xf7', ['ID'])

+        

+        # - is MINUS, the rest a constnant

+        self.assertTokensTypes('-1', ['MINUS', 'INT_CONST_DEC'])

+        

+    def test_floating_constants(self):
+        self.assertTokensTypes('1.5f', ['FLOAT_CONST'])

+        self.assertTokensTypes('01.5', ['FLOAT_CONST'])

+        self.assertTokensTypes('.15L', ['FLOAT_CONST'])

+        self.assertTokensTypes('0.', ['FLOAT_CONST'])

+        

+        # but just a period is a period

+        self.assertTokensTypes('.', ['PERIOD'])

+        

+        self.assertTokensTypes('3.3e-3', ['FLOAT_CONST'])

+        self.assertTokensTypes('.7e25L', ['FLOAT_CONST'])

+        self.assertTokensTypes('6.e+125f', ['FLOAT_CONST'])

+        self.assertTokensTypes('666e666', ['FLOAT_CONST'])

+        self.assertTokensTypes('00666e+3', ['FLOAT_CONST'])

+        

+        # but this is a hex integer + 3

+        self.assertTokensTypes('0x0666e+3', ['INT_CONST_HEX', 'PLUS', 'INT_CONST_DEC'])

+    

+    def test_char_constants(self):
+        self.assertTokensTypes(r"""'x'""", ['CHAR_CONST'])

+        self.assertTokensTypes(r"""L'x'""", ['WCHAR_CONST'])

+        self.assertTokensTypes(r"""'\t'""", ['CHAR_CONST'])

+        self.assertTokensTypes(r"""'\''""", ['CHAR_CONST'])

+        self.assertTokensTypes(r"""'\?'""", ['CHAR_CONST'])

+        self.assertTokensTypes(r"""'\012'""", ['CHAR_CONST'])

+        self.assertTokensTypes(r"""'\x2f'""", ['CHAR_CONST'])

+        self.assertTokensTypes(r"""'\x2f12'""", ['CHAR_CONST'])

+        self.assertTokensTypes(r"""L'\xaf'""", ['WCHAR_CONST'])

+

+    def test_string_literal(self):
+        self.assertTokensTypes('"a string"', ['STRING_LITERAL'])

+        self.assertTokensTypes('L"ing"', ['WSTRING_LITERAL'])

+        self.assertTokensTypes(

+            '"i am a string too \t"', 

+            ['STRING_LITERAL'])

+        self.assertTokensTypes(

+            r'''"esc\ape \"\'\? \0234 chars \rule"''', 

+            ['STRING_LITERAL'])

+        self.assertTokensTypes(

+            r'''"hello 'joe' wanna give it a \"go\"?"''',

+            ['STRING_LITERAL'])

+

+    def test_mess(self):
+        self.assertTokensTypes(

+            r'[{}]()',

+            ['LBRACKET', 

+                'LBRACE', 'RBRACE', 

+            'RBRACKET', 

+            'LPAREN', 'RPAREN'])

+

+        self.assertTokensTypes(

+            r'()||!C&~Z?J',

+            ['LPAREN', 'RPAREN', 

+            'LOR', 

+            'LNOT', 'ID', 

+            'AND', 

+            'NOT', 'ID', 

+            'CONDOP', 'ID'])

+        

+        self.assertTokensTypes(

+            r'+-*/%|||&&&^><>=<===!=',

+            ['PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD', 

+            'LOR', 'OR', 

+            'LAND', 'AND', 

+            'XOR', 

+            'GT', 'LT', 'GE', 'LE', 'EQ', 'NE'])

+            

+        self.assertTokensTypes(

+            r'++--->?.,;:',

+            ['PLUSPLUS', 'MINUSMINUS', 

+            'ARROW', 'CONDOP', 

+            'PERIOD', 'COMMA', 'SEMI', 'COLON'])

+

+    def test_exprs(self):

+        self.assertTokensTypes(

+            'bb-cc',

+            ['ID', 'MINUS', 'ID'])

+

+        self.assertTokensTypes(

+            'foo & 0xFF',

+            ['ID', 'AND', 'INT_CONST_HEX'])

+
+        self.assertTokensTypes(

+            '(2+k) * 62', 

+            ['LPAREN', 'INT_CONST_DEC', 'PLUS', 'ID', 

+            'RPAREN', 'TIMES', 'INT_CONST_DEC'],)

+        

+        self.assertTokensTypes(

+            'x | y >> z',

+            ['ID', 'OR', 'ID', 'RSHIFT', 'ID'])

+        

+        self.assertTokensTypes(

+            'x <<= z << 5',

+            ['ID', 'LSHIFTEQUAL', 'ID', 'LSHIFT', 'INT_CONST_DEC'])

+        

+        self.assertTokensTypes(

+            'x = y > 0 ? y : -6',

+            ['ID', 'EQUALS', 

+                'ID', 'GT', 'INT_CONST_OCT', 

+                'CONDOP', 

+                'ID', 

+                'COLON', 

+                'MINUS', 'INT_CONST_DEC'])

+        

+        self.assertTokensTypes(

+            'a+++b',

+            ['ID', 'PLUSPLUS', 'PLUS', 'ID'])

+

+    def test_statements(self):
+        self.assertTokensTypes(

+            'for (int i = 0; i < n; ++i)',

+            ['FOR', 'LPAREN', 

+                        'INT', 'ID', 'EQUALS', 'INT_CONST_OCT', 'SEMI', 

+                        'ID', 'LT', 'ID', 'SEMI', 

+                        'PLUSPLUS', 'ID', 

+                    'RPAREN'])

+

+        self.assertTokensTypes(

+            'self: goto self;',

+            ['ID', 'COLON', 'GOTO', 'ID', 'SEMI'])

+            

+        self.assertTokensTypes(

+            """ switch (typ)

+                {

+                    case TYPE_ID:

+                        m = 5;

+                        break;

+                    default:

+                        m = 8;

+                }""",

+            ['SWITCH', 'LPAREN', 'ID', 'RPAREN', 

+                'LBRACE', 

+                    'CASE', 'ID', 'COLON', 

+                        'ID', 'EQUALS', 'INT_CONST_DEC', 'SEMI', 

+                        'BREAK', 'SEMI', 

+                    'DEFAULT', 'COLON', 

+                        'ID', 'EQUALS', 'INT_CONST_DEC', 'SEMI', 

+                'RBRACE'])

+    

+    def test_preprocessor(self):

+        self.assertTokensTypes('#abracadabra', ['PPHASH', 'ID'])

+        

+        str = r"""

+        546

+        #line 66 "kwas\df.h" 

+        id 4

+        dsf

+        # 9 

+        armo

+        """

+        

+        #~ self.clex.filename

+        self.clex.input(str)

+        self.clex.reset_lineno()

+        

+        t1 = self.clex.token()

+        self.assertEqual(t1.type, 'INT_CONST_DEC')

+        self.assertEqual(t1.lineno, 2)

+        

+        t2 = self.clex.token()

+        self.assertEqual(t2.type, 'ID')

+        self.assertEqual(t2.value, 'id')

+        self.assertEqual(t2.lineno, 66)

+        self.assertEqual(self.clex.filename, r'kwas\df.h')

+        

+        for i in range(3):

+            t = self.clex.token()

+        

+        self.assertEqual(t.type, 'ID')

+        self.assertEqual(t.value, 'armo')

+        self.assertEqual(t.lineno, 9)

+        self.assertEqual(self.clex.filename, r'kwas\df.h')

+        

+

+

+# Keeps all the errors the lexer spits in one place, to allow

+# easier modification if the error syntax changes.

+#

+ERR_ILLEGAL_CHAR    = 'Illegal character'

+ERR_OCTAL           = 'Invalid octal constant'

+ERR_UNMATCHED_QUOTE = 'Unmatched \''

+ERR_INVALID_CCONST  = 'Invalid char constant'

+ERR_STRING_ESCAPE   = 'String contains invalid escape'

+

+ERR_FILENAME_BEFORE_LINE    = 'filename before line'

+ERR_LINENUM_MISSING         = 'line number missing'

+ERR_INVALID_LINE_DIRECTIVE  = 'invalid #line directive'

+

+

+class TestCLexerErrors(unittest.TestCase):

+    """ Test lexing of erroneous strings.

+        Works by passing an error functions that saves the error

+        in an attribute for later perusal.

+    """    

+    def error_func(self, msg, line, column):

+        self.error = msg

+        

+    def type_lookup_func(self, typ):

+        return False

+        

+    def setUp(self):

+        self.clex = CLexer(self.error_func, self.type_lookup_func)

+        self.clex.build(optimize=False)

+        self.error = ""

+

+    def assertLexerError(self, str, error_like):

+        # feed the string to the lexer
+        self.clex.input(str)

+        

+        # Pulls all tokens from the string. Errors will

+        # be written into self.error by the error_func

+        # callback

+        #

+        token_types(self.clex) 

+        

+        # compare the error to the expected

+        self.failUnless(re.search(error_like, self.error),

+            "\nExpected error matching: %s\nGot: %s" % 

+                (error_like, self.error))

+        

+        # clear last error, for the sake of subsequent invocations

+        self.error = ""

+

+    def test_trivial_tokens(self):

+        self.assertLexerError('@', ERR_ILLEGAL_CHAR)
+        self.assertLexerError('$', ERR_ILLEGAL_CHAR)

+        self.assertLexerError('`', ERR_ILLEGAL_CHAR)

+        self.assertLexerError('\\', ERR_ILLEGAL_CHAR)

+    

+    def test_integer_constants(self):
+        self.assertLexerError('029', ERR_OCTAL)

+        self.assertLexerError('012345678', ERR_OCTAL)

+        

+    def test_char_constants(self):
+        self.assertLexerError("'", ERR_UNMATCHED_QUOTE)

+        self.assertLexerError("'b\n", ERR_UNMATCHED_QUOTE)

+    

+        self.assertLexerError("'jx'", ERR_INVALID_CCONST)

+        self.assertLexerError("'\*'", ERR_INVALID_CCONST)

+        self.assertLexerError("'\9'", ERR_INVALID_CCONST)

+        self.assertLexerError("L'\9'", ERR_INVALID_CCONST)

+    

+    def test_string_literals(self):
+        self.assertLexerError('"jx\9"', ERR_STRING_ESCAPE)

+        self.assertLexerError('"hekllo\* on ix"', ERR_STRING_ESCAPE)

+        self.assertLexerError('L"hekllo\* on ix"', ERR_STRING_ESCAPE)

+            

+    def test_preprocessor(self):
+        self.assertLexerError('#line "ka"', ERR_FILENAME_BEFORE_LINE)

+        self.assertLexerError('#line df', ERR_INVALID_LINE_DIRECTIVE)

+        self.assertLexerError('#line \n', ERR_LINENUM_MISSING)

+

+

+if __name__ == '__main__':

+    unittest.main()

+        
+

diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py
new file mode 100644
index 0000000..d57d8ee
--- /dev/null
+++ b/tests/test_c_parser.py
@@ -0,0 +1,1028 @@
+#!/usr/bin/env python
+
+import pprint
+import re
+import sys
+import unittest
+
+sys.path.insert(0, '..')
+
+from pycparser import c_parser
+from pycparser.c_ast import *
+from pycparser.c_parser import CParser, Coord, ParseError
+
+
+_c_parser = c_parser.CParser(
+                lex_optimize=False,
+                yacc_debug=True, 
+                yacc_optimize=False,
+                yacctab='yacctab')
+
+
+def expand_decl(decl):
+    """ Converts the declaration into a nested list.
+    """
+    typ = type(decl)
+    
+    if typ == TypeDecl:
+        return ['TypeDecl', expand_decl(decl.type)]
+    elif typ == IdentifierType:
+        return ['IdentifierType', decl.names]
+    elif typ == ID:
+        return ['ID', decl.name]
+    elif typ in [Struct, Union]:
+        decls = [expand_decl(d) for d in decl.decls or []]
+        return [typ.__name__, decl.name, decls]
+    else:        
+        nested = expand_decl(decl.type)
+    
+        if typ == Decl:
+            if decl.quals:
+                return ['Decl', decl.quals, decl.name, nested]
+            else:
+                return ['Decl', decl.name, nested]
+        elif typ == Typename: # for function parameters
+            if decl.quals:
+                return ['Typename', decl.quals, nested]
+            else:
+                return ['Typename', nested]
+        elif typ == ArrayDecl:
+            dimval = decl.dim.value if decl.dim else ''
+            return ['ArrayDecl', dimval, nested]
+        elif typ == PtrDecl:
+            return ['PtrDecl', nested]
+        elif typ == Typedef:
+            return ['Typedef', decl.name, nested]
+        elif typ == FuncDecl:
+            if decl.args:
+                params = [expand_decl(param) for param in decl.args.params]
+            else:
+                params = []
+            return ['FuncDecl', params, nested]
+    
+
+def expand_init(init):
+    """ Converts an initialization into a nested list
+    """
+    typ = type(init)
+    
+    if typ == Constant:
+        return ['Constant', init.type, init.value]
+    elif typ == ID:
+        return ['ID', init.name]
+    elif typ == ExprList:
+        return [expand_init(expr) for expr in init.exprs]
+
+
+class TestCParser_fundamentals(unittest.TestCase):
+    """ Tests for "fundamental features" of CParser. Testing 
+        (mostly) each feature in a detailed manner.
+    """
+    def parse(self, txt, filename=''):
+        return self.cparser.parse(txt, filename)
+    
+    def setUp(self):
+        self.cparser = _c_parser
+    
+    def get_decl(self, txt, index=0):
+        """ Given a source and an index returns the expanded
+            declaration at that index.
+            
+            FileAST holds a list of 'external declarations'. 
+            index is the offset of the desired declaration in that
+            list.
+        """
+        t = self.parse(txt).ext[index]
+        return expand_decl(t)
+    
+    def get_decl_init(self, txt, index=0):
+        """ Returns the expanded initializer of the declaration 
+            at index.
+        """
+        t = self.parse(txt).ext[index]
+        return expand_init(t.init)
+    
+    def test_FileAST(self):
+        t = self.parse('int a; char c;')
+        self.failUnless(isinstance(t, FileAST))
+        self.assertEqual(len(t.ext), 2)
+
+    """ Tests the "coordinates" of parsed elements - file 
+        name and line numbers, with modification insterted by
+        #line directives.
+    """
+    def assert_coord(self, node, line, file=None):
+        self.assertEqual(node.coord.line, line)
+        if file:
+            self.assertEqual(node.coord.file, file)
+
+    def test_coords(self):
+        self.assert_coord(self.parse('int a;').ext[0], 1)
+        
+        t1 = """
+        int a;
+        int b;\n\n
+        int c;
+        """
+        f1 = self.parse(t1, filename='test.c')
+        self.assert_coord(f1.ext[0], 2, 'test.c')
+        self.assert_coord(f1.ext[1], 3, 'test.c')
+        self.assert_coord(f1.ext[2], 6, 'test.c')
+
+        t1_1 = '''
+        int main() {
+            k = p;
+            printf("%d", b);
+            return 0;
+        }'''
+        f1_1 = self.parse(t1_1, filename='test.c')
+        self.assert_coord(f1_1.ext[0].body.stmts[0], 3, 'test.c')
+        self.assert_coord(f1_1.ext[0].body.stmts[1], 4, 'test.c')
+        
+        t2 = """
+        #line 99
+        int c;
+        """
+        self.assert_coord(self.parse(t2).ext[0], 99)
+        
+        t3 = """
+        int dsf;
+        char p;
+        #line 3000 "in.h"
+        char d;
+        """
+        f3 = self.parse(t3, filename='test.c')
+        self.assert_coord(f3.ext[0], 2, 'test.c')
+        self.assert_coord(f3.ext[1], 3, 'test.c')
+        self.assert_coord(f3.ext[2], 3000, 'in.h')
+
+        t4 = """
+        #line 20 "restore.h"
+        int maydler(char);
+        
+        #line 30 "includes/daween.ph"
+        long j, k;
+        
+        #line 50000
+        char* ro;
+        """
+        f4 = self.parse(t4, filename='myb.c')
+        self.assert_coord(f4.ext[0], 20, 'restore.h')
+        self.assert_coord(f4.ext[1], 30, 'includes/daween.ph')
+        self.assert_coord(f4.ext[2], 30, 'includes/daween.ph')
+        self.assert_coord(f4.ext[3], 50000, 'includes/daween.ph')        
+
+        t5 = """
+        int 
+        #line 99 
+        c;
+        """
+        self.assert_coord(self.parse(t5).ext[0], 99)
+
+    def test_simple_decls(self):
+        self.assertEqual(self.get_decl('int a;'), 
+            ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
+
+        self.assertEqual(self.get_decl('unsigned int a;'), 
+            ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int', 'unsigned']]]])
+
+        self.assertEqual(self.get_decl('char* string;'), 
+            ['Decl', 'string', 
+                ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]])
+
+        self.assertEqual(self.get_decl('long ar[15];'), 
+            ['Decl', 'ar', 
+                ['ArrayDecl', '15', 
+                    ['TypeDecl', ['IdentifierType', ['long']]]]])
+        
+        self.assertEqual(self.get_decl('unsigned ar[];'), 
+            ['Decl', 'ar', 
+                ['ArrayDecl', '', 
+                    ['TypeDecl', ['IdentifierType', ['unsigned']]]]])
+            
+        self.assertEqual(self.get_decl('int strlen(char* s);'), 
+            ['Decl', 'strlen', 
+                ['FuncDecl', 
+                    [['Decl', 's', 
+                        ['PtrDecl', 
+                            ['TypeDecl', ['IdentifierType', ['char']]]]]], 
+                    ['TypeDecl', ['IdentifierType', ['int']]]]])
+                    
+        self.assertEqual(self.get_decl('int strcmp(char* s1, char* s2);'), 
+            ['Decl', 'strcmp', 
+                ['FuncDecl', 
+                    [   ['Decl', 's1', 
+                            ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]], 
+                        ['Decl', 's2', 
+                            ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]
+                    ], 
+                ['TypeDecl', ['IdentifierType', ['int']]]]])
+
+    def test_nested_decls(self): # the fun begins
+        self.assertEqual(self.get_decl('char** ar2D;'),
+            ['Decl', 'ar2D', 
+                ['PtrDecl', ['PtrDecl', 
+                    ['TypeDecl', ['IdentifierType', ['char']]]]]])
+        
+        self.assertEqual(self.get_decl('int (*a)[1][2];'), 
+            ['Decl', 'a', 
+                ['PtrDecl', 
+                    ['ArrayDecl', '1', 
+                        ['ArrayDecl', '2', 
+                        ['TypeDecl', ['IdentifierType', ['int']]]]]]])
+
+        self.assertEqual(self.get_decl('int *a[1][2];'), 
+            ['Decl', 'a', 
+                ['ArrayDecl', '1', 
+                    ['ArrayDecl', '2', 
+                        ['PtrDecl', ['TypeDecl', ['IdentifierType', ['int']]]]]]])
+        
+        self.assertEqual(self.get_decl('char ***ar3D[40];'),
+            ['Decl', 'ar3D', 
+                ['ArrayDecl', '40', 
+                    ['PtrDecl', ['PtrDecl', ['PtrDecl', 
+                        ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
+                        
+        self.assertEqual(self.get_decl('char (***ar3D)[40];'),
+            ['Decl', 'ar3D', 
+                ['PtrDecl', ['PtrDecl', ['PtrDecl', 
+                    ['ArrayDecl', '40', ['TypeDecl', ['IdentifierType', ['char']]]]]]]])
+            
+        self.assertEqual(self.get_decl('int (*x[4])(char, int);'),
+            ['Decl', 'x', 
+                ['ArrayDecl', '4', 
+                    ['PtrDecl', 
+                        ['FuncDecl', 
+                            [   ['Typename',  ['TypeDecl', ['IdentifierType', ['char']]]], 
+                                ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]], 
+                            ['TypeDecl', ['IdentifierType', ['int']]]]]]])
+        
+        self.assertEqual(self.get_decl('char *(*(**foo [][8])())[];'),
+            ['Decl', 'foo', 
+                ['ArrayDecl', '', 
+                    ['ArrayDecl', '8', 
+                        ['PtrDecl', ['PtrDecl', 
+                            ['FuncDecl', 
+                                [], 
+                                ['PtrDecl', 
+                                    ['ArrayDecl', '', 
+                                        ['PtrDecl', 
+                                            ['TypeDecl', 
+                                                ['IdentifierType', ['char']]]]]]]]]]]])
+    
+        # explore named and unnamed function pointer parameters,
+        # with and without qualifiers
+        #
+        
+        # unnamed w/o quals
+        self.assertEqual(self.get_decl('int (*k)(int);'),
+            ['Decl', 'k', 
+                ['PtrDecl', 
+                    ['FuncDecl', 
+                        [['Typename', ['TypeDecl', ['IdentifierType', ['int']]]]], 
+                        ['TypeDecl', ['IdentifierType', ['int']]]]]])
+    
+        # unnamed w/ quals
+        self.assertEqual(self.get_decl('int (*k)(const int);'),
+            ['Decl', 'k', 
+                ['PtrDecl', 
+                    ['FuncDecl', 
+                        [['Typename', ['const'], ['TypeDecl', ['IdentifierType', ['int']]]]], 
+                        ['TypeDecl', ['IdentifierType', ['int']]]]]])
+        
+        # named w/o quals
+        self.assertEqual(self.get_decl('int (*k)(int q);'),
+            ['Decl', 'k', 
+                ['PtrDecl', 
+                    ['FuncDecl', 
+                        [['Decl', 'q', ['TypeDecl', ['IdentifierType', ['int']]]]], 
+                        ['TypeDecl', ['IdentifierType', ['int']]]]]])
+        
+        # named w/ quals
+        self.assertEqual(self.get_decl('int (*k)(const volatile int q);'),
+            ['Decl', 'k', 
+                ['PtrDecl', 
+                    ['FuncDecl', 
+                        [['Decl', ['volatile', 'const'], 'q', 
+                            ['TypeDecl', ['IdentifierType', ['int']]]]], 
+                        ['TypeDecl', ['IdentifierType', ['int']]]]]])
+        
+        
+    def test_qualifiers_storage_specifiers(self):
+        def assert_qs(txt, index, quals, storage):
+            d = self.parse(txt).ext[index]
+            self.assertEqual(d.quals, quals)
+            self.assertEqual(d.storage, storage)
+        
+        assert_qs("extern int p;", 0, [], ['extern'])
+        assert_qs("const long p = 6;", 0, ['const'], [])
+        
+        d1 = "static const int p, q, r;"
+        for i in range(3):
+            assert_qs(d1, i, ['const'], ['static'])
+        
+        d2 = "static char * const p;"
+        assert_qs(d2, 0, [], ['static'])
+        pdecl = self.parse(d2).ext[0].type
+        self.failUnless(isinstance(pdecl, PtrDecl))
+        self.assertEqual(pdecl.quals, ['const'])
+    
+    def test_sizeof(self):
+        e = """
+            void foo()
+            {
+                int a = sizeof k;
+                int b = sizeof(int);
+                int c = sizeof(int**);
+                
+                char* p = "just to make sure this parses w/o error...";
+                int d = sizeof(int());
+            }
+        """
+        compound = self.parse(e).ext[0].body
+        
+        s1 = compound.decls[0].init
+        self.assertTrue(isinstance(s1, UnaryOp))
+        self.assertEqual(s1.op, 'sizeof')
+        self.assertTrue(isinstance(s1.expr, ID))
+        self.assertEqual(s1.expr.name, 'k')
+        
+        s2 = compound.decls[1].init
+        self.assertEqual(expand_decl(s2.expr),
+            ['Typename', ['TypeDecl', ['IdentifierType', ['int']]]])
+        
+        s3 = compound.decls[2].init
+        self.assertEqual(expand_decl(s3.expr),
+            ['Typename', 
+                ['PtrDecl', 
+                    ['PtrDecl', 
+                        ['TypeDecl', 
+                            ['IdentifierType', ['int']]]]]])
+    
+    def test_enums(self):
+        e1 = "enum mycolor op;"
+        e1_type = self.parse(e1).ext[0].type.type
+        
+        self.assertTrue(isinstance(e1_type, Enum))
+        self.assertEqual(e1_type.name, 'mycolor')
+        self.assertEqual(e1_type.values, None)
+        
+        e2 = "enum mysize {large=20, small, medium} shoes;"
+        e2_type = self.parse(e2).ext[0].type.type
+        
+        self.assertTrue(isinstance(e2_type, Enum))
+        self.assertEqual(e2_type.name, 'mysize')
+        
+        e2_elist = e2_type.values
+        self.assertTrue(isinstance(e2_elist, EnumeratorList))
+        
+        for e2_eval in e2_elist.enumerators:
+            self.assertTrue(isinstance(e2_eval, Enumerator))
+        
+        self.assertEqual(e2_elist.enumerators[0].name, 'large')
+        self.assertEqual(e2_elist.enumerators[0].value.value, '20')
+        self.assertEqual(e2_elist.enumerators[2].name, 'medium')
+        self.assertEqual(e2_elist.enumerators[2].value, None)
+    
+        # enum with trailing comma (C99 feature)
+        e3 = """
+            enum 
+            {
+                red,
+                blue,
+                green,
+            } color;
+            """
+        
+        e3_type = self.parse(e3).ext[0].type.type
+        self.assertTrue(isinstance(e3_type, Enum))
+        e3_elist = e3_type.values
+        self.assertTrue(isinstance(e3_elist, EnumeratorList))
+        
+        for e3_eval in e3_elist.enumerators:
+            self.assertTrue(isinstance(e3_eval, Enumerator))
+        
+        self.assertEqual(e3_elist.enumerators[0].name, 'red')
+        self.assertEqual(e3_elist.enumerators[0].value, None)
+        self.assertEqual(e3_elist.enumerators[1].name, 'blue')
+        self.assertEqual(e3_elist.enumerators[2].name, 'green')
+        
+    def test_typedef(self):
+        # without typedef, error
+        s1 = """
+            node k;
+        """
+        self.assertRaises(ParseError, self.parse, s1)
+
+        # now with typedef, works
+        s2 = """
+            typedef void* node;
+            node k;
+        """
+        ps2 = self.parse(s2)
+        self.assertEqual(expand_decl(ps2.ext[0]),
+            ['Typedef', 'node', 
+                ['PtrDecl', 
+                    ['TypeDecl', ['IdentifierType', ['void']]]]])
+        
+        self.assertEqual(expand_decl(ps2.ext[1]),
+            ['Decl', 'k', 
+                ['TypeDecl', ['IdentifierType', ['node']]]])
+    
+        s3 = """
+            typedef int T;
+            typedef T *pT;
+            
+            pT aa, bb;
+        """
+        ps3 = self.parse(s3)
+        self.assertEqual(expand_decl(ps3.ext[3]),
+            ['Decl', 'bb', 
+                ['TypeDecl', ['IdentifierType', ['pT']]]])
+        
+        s4 = '''
+            typedef char* __builtin_va_list;
+            typedef __builtin_va_list __gnuc_va_list;
+        '''
+        ps4 = self.parse(s4)
+        self.assertEqual(expand_decl(ps4.ext[1]),
+            ['Typedef', '__gnuc_va_list', 
+                ['TypeDecl', 
+                    ['IdentifierType', ['__builtin_va_list']]]])
+        
+        s5 = '''typedef struct tagHash Hash;'''
+        ps5 = self.parse(s5)
+        self.assertEqual(expand_decl(ps5.ext[0]),
+            ['Typedef', 'Hash', ['TypeDecl', ['Struct', 'tagHash', []]]])
+        
+    def test_struct_union(self):
+        s1 = """
+            struct {
+                int id;
+                char* name;
+            } joe;
+            """
+    
+        self.assertEqual(expand_decl(self.parse(s1).ext[0]),
+            ['Decl', 'joe', 
+                ['TypeDecl', ['Struct', None, 
+                    [   ['Decl', 'id', 
+                            ['TypeDecl', 
+                                ['IdentifierType', ['int']]]], 
+                        ['Decl', 'name', 
+                            ['PtrDecl', 
+                                ['TypeDecl', 
+                                    ['IdentifierType', ['char']]]]]]]]])
+    
+        s2 = """
+            struct node p;
+        """
+        self.assertEqual(expand_decl(self.parse(s2).ext[0]),
+            ['Decl', 'p', 
+                ['TypeDecl', ['Struct', 'node', []]]])
+    
+        s21 = """
+            union pri ra;
+        """
+        self.assertEqual(expand_decl(self.parse(s21).ext[0]),
+            ['Decl', 'ra', 
+                ['TypeDecl', ['Union', 'pri', []]]])
+    
+        s3 = """
+            struct node* p;
+        """
+        self.assertEqual(expand_decl(self.parse(s3).ext[0]),
+            ['Decl', 'p', 
+                ['PtrDecl', 
+                    ['TypeDecl', ['Struct', 'node', []]]]])
+                    
+        s4 = """
+            struct node;
+        """
+        self.assertEqual(expand_decl(self.parse(s4).ext[0]),
+            ['Decl', None, 
+                ['Struct', 'node', []]])
+        
+        s5 = """
+            union
+            {
+                struct
+                {
+                    int type;
+                } n;
+                
+                struct
+                {
+                    int type;
+                    int intnode;
+                } ni;
+            } u;
+        """
+        self.assertEqual(expand_decl(self.parse(s5).ext[0]),
+            ['Decl', 'u', 
+                ['TypeDecl', 
+                    ['Union', None, 
+                        [['Decl', 'n', 
+                            ['TypeDecl', 
+                                ['Struct', None, 
+                                    [['Decl', 'type', 
+                                        ['TypeDecl', ['IdentifierType', ['int']]]]]]]], 
+                        ['Decl', 'ni', 
+                            ['TypeDecl', 
+                                ['Struct', None, 
+                                    [['Decl', 'type', 
+                                        ['TypeDecl', ['IdentifierType', ['int']]]], 
+                                    ['Decl', 'intnode', 
+                                        ['TypeDecl', ['IdentifierType', ['int']]]]]]]]]]]])
+        
+        s6 = """
+            typedef struct foo_tag
+            {
+                void* data;
+            } foo, *pfoo;
+        """
+        s6_ast = self.parse(s6)
+        
+        self.assertEqual(expand_decl(s6_ast.ext[0]),
+            ['Typedef', 'foo',
+                ['TypeDecl', 
+                    ['Struct', 'foo_tag', 
+                        [['Decl', 'data', 
+                            ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]])
+        
+        self.assertEqual(expand_decl(s6_ast.ext[1]),
+            ['Typedef', 'pfoo',
+                ['PtrDecl',
+                    ['TypeDecl', 
+                        ['Struct', 'foo_tag', 
+                            [['Decl', 'data', 
+                                ['PtrDecl', ['TypeDecl', ['IdentifierType', ['void']]]]]]]]]])
+        
+        s7 = r"""
+            struct _on_exit_args {
+                void *  _fnargs[32];
+                void *  _dso_handle[32];
+
+                long _fntypes;
+                #line 77 "D:\eli\cpp_stuff\libc_include/sys/reent.h"
+
+                long _is_cxa;
+            };
+        """
+        
+        s7_ast = self.parse(s7, filename='test.c')
+        self.assert_coord(s7_ast.ext[0].type.decls[2], 6, 'test.c')
+        self.assert_coord(s7_ast.ext[0].type.decls[3], 78, 
+            r'D:\eli\cpp_stuff\libc_include/sys/reent.h')
+            
+        s8 = """
+            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;
+        """
+        s8_ast = self.parse(s8)
+        self.assertEqual(expand_decl(s8_ast.ext[3]),
+            ['Typedef', 'Hash', 
+                ['TypeDecl', ['Struct', 'tagHash', 
+                    [['Decl', 'table_size', 
+                        ['TypeDecl', ['IdentifierType', ['int', 'unsigned']]]], 
+                    ['Decl', 'heads', 
+                        ['PtrDecl', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['Node']]]]]]]]]])
+    
+    def test_tags_namespace(self):
+        """ Tests that the tags of structs/unions/enums reside in a separate namespace and
+            can be named after existing types.
+        """
+        s1 = """
+                typedef int tagEntry;
+
+                struct tagEntry
+                {
+                    char* key;
+                    char* value;
+                } Entry;
+            """
+        
+        s1_ast = self.parse(s1)
+        self.assertEqual(expand_decl(s1_ast.ext[1]),
+            ['Decl', 'Entry', 
+                ['TypeDecl', ['Struct', 'tagEntry', 
+                    [['Decl', 'key', 
+                        ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]], 
+                    ['Decl', 'value', 
+                        ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
+    
+        s2 = """
+                struct tagEntry;
+
+                typedef struct tagEntry tagEntry;
+
+                struct tagEntry
+                {
+                    char* key;
+                    char* value;
+                } Entry;
+            """
+        
+        s2_ast = self.parse(s2)
+        self.assertEqual(expand_decl(s2_ast.ext[2]),
+            ['Decl', 'Entry', 
+                ['TypeDecl', ['Struct', 'tagEntry', 
+                    [['Decl', 'key', 
+                        ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]], 
+                    ['Decl', 'value', 
+                        ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]]]]])
+        
+        s3 = """                
+                typedef int mytag;
+
+                enum mytag {ABC, CDE};
+                enum mytag joe;
+            """
+            
+        s3_type = self.parse(s3).ext[1].type
+        
+        self.assertTrue(isinstance(s3_type, Enum))
+        self.assertEqual(s3_type.name, 'mytag')        
+    
+    def test_multi_decls(self):
+        d1 = 'int a, b;'
+        
+        self.assertEqual(self.get_decl(d1, 0),
+            ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
+        self.assertEqual(self.get_decl(d1, 1),
+            ['Decl', 'b', ['TypeDecl', ['IdentifierType', ['int']]]])
+    
+        d2 = 'char* p, notp, ar[4];'
+        self.assertEqual(self.get_decl(d2, 0),
+            ['Decl', 'p', 
+                ['PtrDecl',
+                    ['TypeDecl', ['IdentifierType', ['char']]]]])
+        self.assertEqual(self.get_decl(d2, 1),
+            ['Decl', 'notp', ['TypeDecl', ['IdentifierType', ['char']]]])
+        self.assertEqual(self.get_decl(d2, 2),
+            ['Decl', 'ar', 
+                ['ArrayDecl', '4',
+                    ['TypeDecl', ['IdentifierType', ['char']]]]])
+    
+    def test_invalid_multiple_types_error(self):
+        bad = [
+            'int enum {ab, cd} fubr;',
+            'enum kid char brbr;']
+        
+        for b in bad:
+            self.assertRaises(ParseError, self.parse, b)        
+    
+    def test_decl_inits(self):
+        d1 = 'int a = 16;'
+        self.assertEqual(self.get_decl(d1),
+            ['Decl', 'a', ['TypeDecl', ['IdentifierType', ['int']]]])
+        self.assertEqual(self.get_decl_init(d1),
+            ['Constant', 'int', '16'])
+        
+        d2 = 'long ar[] = {7, 8, 9};'
+        self.assertEqual(self.get_decl(d2),
+            ['Decl', 'ar', 
+                ['ArrayDecl', '',
+                    ['TypeDecl', ['IdentifierType', ['long']]]]])
+        self.assertEqual(self.get_decl_init(d2),
+            [   ['Constant', 'int', '7'],
+                ['Constant', 'int', '8'],
+                ['Constant', 'int', '9'],])
+        
+        d3 = 'char p = j;'
+        self.assertEqual(self.get_decl(d3),
+            ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['char']]]])
+        self.assertEqual(self.get_decl_init(d3),
+            ['ID', 'j'])
+        
+        d4 = "char x = 'c', *p = {0, 1, 2, {4, 5}, 6};"
+        self.assertEqual(self.get_decl(d4, 0),
+            ['Decl', 'x', ['TypeDecl', ['IdentifierType', ['char']]]])
+        self.assertEqual(self.get_decl_init(d4, 0),
+            ['Constant', 'char', "'c'"])
+        self.assertEqual(self.get_decl(d4, 1),
+            ['Decl', 'p', 
+                ['PtrDecl',
+                    ['TypeDecl', ['IdentifierType', ['char']]]]])
+        self.assertEqual(self.get_decl_init(d4, 1),
+            [   ['Constant', 'int', '0'], 
+                ['Constant', 'int', '1'], 
+                ['Constant', 'int', '2'], 
+                [   ['Constant', 'int', '4'], 
+                    ['Constant', 'int', '5']], 
+                ['Constant', 'int', '6']])
+
+    def test_function_definitions(self):
+        def parse_fdef(str):
+            return self.parse(str).ext[0]
+        
+        def fdef_decl(fdef):
+            return expand_decl(fdef.decl)
+        
+        f1 = parse_fdef('''
+        int factorial(int p)
+        {
+            return 3;
+        }
+        ''')
+        
+        self.assertEqual(fdef_decl(f1),
+            ['Decl', 'factorial',
+                ['FuncDecl', 
+                    [['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]]], 
+                    ['TypeDecl', ['IdentifierType', ['int']]]]])
+        
+        self.assertEqual(type(f1.body.stmts[0]), Return)
+        self.assertEqual(f1.body.decls, None)
+        
+        f2 = parse_fdef('''
+        char* zzz(int p, char* c)
+        {
+            int a;
+            char b;
+            
+            a = b + 2;
+            return 3;
+        }
+        ''')
+        
+        self.assertEqual(fdef_decl(f2),
+            ['Decl', 'zzz', 
+                ['FuncDecl', 
+                    [   ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['int']]]], 
+                        ['Decl', 'c', ['PtrDecl', 
+                                        ['TypeDecl', ['IdentifierType', ['char']]]]]], 
+                    ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
+            
+        self.assertEqual(list(map(type, f2.body.stmts)), 
+            [Assignment, Return])
+        self.assertEqual(len(f2.body.decls), 2)
+        
+        f3 = parse_fdef('''
+        char* zzz(p, c)
+        long p, *c;
+        {
+            int a;
+            char b;
+            
+            a = b + 2;
+            return 3;
+        }
+        ''')
+        
+        self.assertEqual(fdef_decl(f3),
+            ['Decl', 'zzz', 
+                ['FuncDecl', 
+                    [   ['ID', 'p'],
+                        ['ID', 'c']],
+                    ['PtrDecl', ['TypeDecl', ['IdentifierType', ['char']]]]]])
+        
+        self.assertEqual(list(map(type, f3.body.stmts)), 
+            [Assignment, Return])
+        self.assertEqual(len(f3.body.decls), 2)
+        
+        self.assertEqual(expand_decl(f3.param_decls[0]),
+            ['Decl', 'p', ['TypeDecl', ['IdentifierType', ['long']]]])
+        self.assertEqual(expand_decl(f3.param_decls[1]),
+            ['Decl', 'c', ['PtrDecl', ['TypeDecl', ['IdentifierType', ['long']]]]])
+
+
+class TestCParser_whole_code(unittest.TestCase):
+    """ Testing of parsing whole chunks of code.
+    
+        Since I don't want to rely on the structure of ASTs too
+        much, most of these tests are implemented with visitors.
+    """
+    def parse(self, txt, filename=''):
+        return self.cparser.parse(txt, filename)
+    
+    def setUp(self):
+        self.cparser = _c_parser
+
+    # A simple helper visitor that lists the values of all the 
+    # Constant nodes it sees.
+    #
+    class ConstantVisitor(NodeVisitor):
+        def __init__(self):
+            self.values = []
+        
+        def visit_Constant(self, node):
+            self.values.append(node.value)
+    
+    # This visitor counts the amount of references to the ID 
+    # with the name provided to it in the constructor.
+    #
+    class IDNameCounter(NodeVisitor):
+        def __init__(self, name):
+            self.name = name
+            self.nrefs = 0
+        
+        def visit_ID(self, node):
+            if node.name == self.name:
+                self.nrefs += 1
+    
+    # Counts the amount of nodes of a given class 
+    # 
+    class NodeKlassCounter(NodeVisitor):
+        def __init__(self, node_klass):
+            self.klass = node_klass
+            self.n = 0
+        
+        def generic_visit(self, node):
+            if node.__class__ == self.klass:
+                self.n += 1
+            
+            NodeVisitor.generic_visit(self, node)
+    
+    def assert_all_Constants(self, code, constants):
+        """ Asserts that the list of all Constant values (by 
+            'preorder' appearance) in the chunk of code is as 
+            given.
+        """
+        parsed = self.parse(code)
+        cv = self.ConstantVisitor()
+        cv.visit(parsed)
+        self.assertEqual(cv.values, constants)
+
+    def assert_num_ID_refs(self, code, name, num):
+        """ Asserts the number of references to the ID with
+            the given name.
+        """
+        if isinstance(code, str):
+            parsed = self.parse(code)
+        else:
+            parsed = code
+    
+        iv = self.IDNameCounter(name)
+        iv.visit(parsed)
+        self.assertEqual(iv.nrefs, num)
+
+    def assert_num_klass_nodes(self, code, klass, num):
+        """ Asserts the amount of klass nodes in the code.
+        """
+        if isinstance(code, str):
+            parsed = self.parse(code)
+        else:
+            parsed = code
+        
+        cv = self.NodeKlassCounter(klass)
+        cv.visit(parsed)
+        self.assertEqual(cv.n, num)
+
+    def test_expressions(self):
+        e1 = '''int k = (r + 10.0) >> 6 + 8 << (3 & 0x14);'''
+        self.assert_all_Constants(e1, ['10.0', '6', '8', '3', '0x14'])
+        
+        e2 = r'''char n = '\n', *prefix = "st_";'''
+        self.assert_all_Constants(e2, [r"'\n'", '"st_"'])
+        
+    def test_statements(self):
+        s1 = r'''
+            void foo(){
+            if (sp == 1)
+                if (optind >= argc ||
+                    argv[optind][0] != '-' || argv[optind][1] == '\0')
+                        return -1;
+                else if (strcmp(argv[optind], "--") == 0) {
+                    optind++;
+                    return -1;
+                }
+            }
+        '''
+        
+        self.assert_all_Constants(s1, 
+            ['1', '0', r"'-'", '1', r"'\0'", '1', r'"--"', '0', '1'])
+        
+        ps1 = self.parse(s1)
+        self.assert_num_ID_refs(ps1, 'argv', 3)
+        self.assert_num_ID_refs(ps1, 'optind', 5)
+        
+        self.assert_num_klass_nodes(ps1, If, 3)
+        self.assert_num_klass_nodes(ps1, Return, 2)
+        self.assert_num_klass_nodes(ps1, FuncCall, 1) # strcmp
+        self.assert_num_klass_nodes(ps1, BinaryOp, 7)
+
+        # In the following code, Hash and Node were defined as
+        # int to pacify the parser that sees they're used as 
+        # types
+        #
+        s2 = r'''
+        typedef int Hash, Node; 
+        
+        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);
+        }
+        '''
+        
+        ps2 = self.parse(s2)
+        self.assert_num_klass_nodes(ps2, FuncCall, 6)
+        self.assert_num_klass_nodes(ps2, FuncDef, 1)
+        self.assert_num_klass_nodes(ps2, For, 1)
+        self.assert_num_klass_nodes(ps2, While, 1)
+        self.assert_num_klass_nodes(ps2, StructRef, 10)
+        
+        # declarations don't count
+        self.assert_num_ID_refs(ps2, 'hash', 6)
+        self.assert_num_ID_refs(ps2, 'i', 4)
+
+    def test_whole_file(self):
+        # See how pycparser handles a whole, real C file.
+        #
+        filename = 'c_files/memmgr_with_h.c'
+        code = open(filename, 'rU').read()
+        p = self.parse(code)
+        
+        self.assert_num_klass_nodes(p, FuncDef, 5)
+        
+        # each FuncDef also has a FuncDecl. 4 declarations 
+        # + 5 definitions, overall 9
+        self.assert_num_klass_nodes(p, FuncDecl, 9)
+        
+        self.assert_num_klass_nodes(p, Typedef, 4)
+        
+        self.assertEqual(p.ext[4].coord.line, 88)
+        self.assertEqual(p.ext[4].coord.file, "./memmgr.h")
+        
+        self.assertEqual(p.ext[6].coord.line, 10)
+        self.assertEqual(p.ext[6].coord.file, "memmgr.c")
+
+    def test_whole_file_with_stdio(self):
+        # Parse a whole file with stdio.h included by cpp
+        #
+        filename = 'c_files/cppd_with_stdio_h.c'
+        code = open(filename, 'rU').read()
+        p = self.parse(code)
+        
+        self.failUnless(isinstance(p.ext[0], Typedef))
+        self.assertEqual(p.ext[0].coord.line, 213)
+        self.assertEqual(p.ext[0].coord.file, "D:\eli\cpp_stuff\libc_include/stddef.h")
+        
+        self.failUnless(isinstance(p.ext[-1], FuncDef))
+        self.assertEqual(p.ext[-1].coord.line, 15)
+        self.assertEqual(p.ext[-1].coord.file, "example_c_file.c")
+        
+        self.failUnless(isinstance(p.ext[-8], Typedef))
+        self.failUnless(isinstance(p.ext[-8].type, TypeDecl))
+        self.assertEqual(p.ext[-8].name, 'cookie_io_functions_t')
+        
+
+if __name__ == '__main__':
+    #~ suite = unittest.TestLoader().loadTestsFromNames(
+        #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
+    
+    #~ suite = unittest.TestLoader().loadTestsFromNames(
+        #~ ['test_c_parser.TestCParser_whole_code.test_whole_file_with_stdio'])
+    
+    #~ suite = unittest.TestLoader().loadTestsFromTestCase(
+        #~ TestCParser_whole_code)
+
+    #~ unittest.TextTestRunner(verbosity=2).run(suite)
+    unittest.main()
diff --git a/tests/test_general.py b/tests/test_general.py
new file mode 100644
index 0000000..882a1ed
--- /dev/null
+++ b/tests/test_general.py
@@ -0,0 +1,37 @@
+import sys

+import unittest

+

+sys.path.insert(0, '..')

+from pycparser import parse_file, c_ast

+

+# Portable cpp path for Windows and Linux/Unix

+CPPPATH = '../utils/cpp.exe' if sys.platform == 'win32' else 'cpp'

+

+

+# Test successful parsing

+#

+class TestParsing(unittest.TestCase):

+    def test_without_cpp(self):
+        ast = parse_file('c_files/example_c_file.c')

+        self.failUnless(isinstance(ast, c_ast.FileAST))

+

+    def test_with_cpp(self):
+        ast = parse_file('c_files/memmgr.c', use_cpp=True,

+            cpp_path=CPPPATH,

+            cpp_args=r'-I../utils/fake_libc_include')

+        self.failUnless(isinstance(ast, c_ast.FileAST))

+    

+        ast2 = parse_file('c_files/year.c', use_cpp=True,

+            cpp_path=CPPPATH, 

+            cpp_args=r'-I../utils/fake_libc_include')

+    

+        self.failUnless(isinstance(ast2, c_ast.FileAST))

+

+

+if __name__ == '__main__':

+    unittest.main()

+

+        
+

+

+

diff --git a/utils/cpp.exe b/utils/cpp.exe
new file mode 100644
index 0000000..60c7787
--- /dev/null
+++ b/utils/cpp.exe
Binary files differ
diff --git a/utils/fake_libc_include/_ansi.h b/utils/fake_libc_include/_ansi.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/_ansi.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/_fake_defines.h b/utils/fake_libc_include/_fake_defines.h
new file mode 100644
index 0000000..4a30792
--- /dev/null
+++ b/utils/fake_libc_include/_fake_defines.h
@@ -0,0 +1,28 @@
+#ifndef _FAKE_DEFINES_H

+#define _FAKE_DEFINES_H

+

+#define	NULL	0

+#define	BUFSIZ		1024

+#define	FOPEN_MAX	20

+#define	FILENAME_MAX	1024

+

+#ifndef SEEK_SET

+#define	SEEK_SET	0	/* set file offset to offset */

+#endif

+#ifndef SEEK_CUR

+#define	SEEK_CUR	1	/* set file offset to current plus offset */

+#endif

+#ifndef SEEK_END

+#define	SEEK_END	2	/* set file offset to EOF plus offset */

+#endif

+

+

+#define EXIT_FAILURE 1

+#define EXIT_SUCCESS 0

+

+#define RAND_MAX 32767

+#define INT_MAX 32767

+

+

+

+#endif

diff --git a/utils/fake_libc_include/_fake_typedefs.h b/utils/fake_libc_include/_fake_typedefs.h
new file mode 100644
index 0000000..344cbc6
--- /dev/null
+++ b/utils/fake_libc_include/_fake_typedefs.h
@@ -0,0 +1,80 @@
+#ifndef _FAKE_TYPEDEFS_H

+#define _FAKE_TYPEDEFS_H

+

+typedef int size_t;

+typedef int __builtin_va_list;

+typedef int __gnuc_va_list;

+typedef int __int8_t;

+typedef int __uint8_t;

+typedef int __int16_t;

+typedef int __uint16_t;

+typedef int __int_least16_t;

+typedef int __uint_least16_t;

+typedef int __int32_t;

+typedef int __uint32_t;

+typedef int __int_least32_t;

+typedef int __uint_least32_t;

+typedef int _LOCK_T;

+typedef int _LOCK_RECURSIVE_T;

+typedef int _off_t;

+typedef int __dev_t;

+typedef int __uid_t;

+typedef int __gid_t;

+typedef int _off64_t;

+typedef int _fpos_t;

+typedef int _ssize_t;

+typedef int wint_t;

+typedef int _mbstate_t;

+typedef int _flock_t;

+typedef int _iconv_t;

+typedef int __ULong;

+typedef int __FILE;

+typedef int ptrdiff_t;

+typedef int wchar_t;

+typedef int __off_t;

+typedef int __pid_t;

+typedef int __loff_t;

+typedef int u_char;

+typedef int u_short;

+typedef int u_int;

+typedef int u_long;

+typedef int ushort;

+typedef int uint;

+typedef int clock_t;

+typedef int time_t;

+typedef int daddr_t;

+typedef int caddr_t;

+typedef int ino_t;

+typedef int off_t;

+typedef int dev_t;

+typedef int uid_t;

+typedef int gid_t;

+typedef int pid_t;

+typedef int key_t;

+typedef int ssize_t;

+typedef int mode_t;

+typedef int nlink_t;

+typedef int fd_mask;

+typedef int _types_fd_set;

+typedef int clockid_t;

+typedef int timer_t;

+typedef int useconds_t;

+typedef int suseconds_t;

+typedef int FILE;

+typedef int fpos_t;

+typedef int cookie_read_function_t;

+typedef int cookie_write_function_t;

+typedef int cookie_seek_function_t;

+typedef int cookie_close_function_t;

+typedef int cookie_io_functions_t;

+typedef int div_t;

+typedef int ldiv_t;

+typedef int lldiv_t;

+typedef int sigset_t;

+typedef int _sig_func_ptr;

+typedef int sig_atomic_t;

+typedef int __tzrule_type;

+typedef int __tzinfo_type;

+typedef int mbstate_t;

+

+#endif

diff --git a/utils/fake_libc_include/_syslist.h b/utils/fake_libc_include/_syslist.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/_syslist.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/alloca.h b/utils/fake_libc_include/alloca.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/alloca.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/ar.h b/utils/fake_libc_include/ar.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/ar.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/argz.h b/utils/fake_libc_include/argz.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/argz.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/assert.h b/utils/fake_libc_include/assert.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/assert.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/ctype.h b/utils/fake_libc_include/ctype.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/ctype.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/dirent.h b/utils/fake_libc_include/dirent.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/dirent.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/envz.h b/utils/fake_libc_include/envz.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/envz.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/errno.h b/utils/fake_libc_include/errno.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/errno.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/fastmath.h b/utils/fake_libc_include/fastmath.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/fastmath.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/fcntl.h b/utils/fake_libc_include/fcntl.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/fcntl.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/getopt.h b/utils/fake_libc_include/getopt.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/getopt.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/grp.h b/utils/fake_libc_include/grp.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/grp.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/iconv.h b/utils/fake_libc_include/iconv.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/iconv.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/ieeefp.h b/utils/fake_libc_include/ieeefp.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/ieeefp.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/inttypes.h b/utils/fake_libc_include/inttypes.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/inttypes.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/langinfo.h b/utils/fake_libc_include/langinfo.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/langinfo.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/libgen.h b/utils/fake_libc_include/libgen.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/libgen.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/limits.h b/utils/fake_libc_include/limits.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/limits.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/locale.h b/utils/fake_libc_include/locale.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/locale.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/malloc.h b/utils/fake_libc_include/malloc.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/malloc.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/math.h b/utils/fake_libc_include/math.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/math.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/newlib.h b/utils/fake_libc_include/newlib.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/newlib.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/paths.h b/utils/fake_libc_include/paths.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/paths.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/process.h b/utils/fake_libc_include/process.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/process.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/pthread.h b/utils/fake_libc_include/pthread.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/pthread.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/pwd.h b/utils/fake_libc_include/pwd.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/pwd.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/reent.h b/utils/fake_libc_include/reent.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/reent.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/regdef.h b/utils/fake_libc_include/regdef.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/regdef.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/sched.h b/utils/fake_libc_include/sched.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/sched.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/search.h b/utils/fake_libc_include/search.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/search.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/setjmp.h b/utils/fake_libc_include/setjmp.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/setjmp.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/signal.h b/utils/fake_libc_include/signal.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/signal.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/stdarg.h b/utils/fake_libc_include/stdarg.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/stdarg.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/stddef.h b/utils/fake_libc_include/stddef.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/stddef.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/stdint.h b/utils/fake_libc_include/stdint.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/stdint.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/stdio.h b/utils/fake_libc_include/stdio.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/stdio.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/stdlib.h b/utils/fake_libc_include/stdlib.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/stdlib.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/string.h b/utils/fake_libc_include/string.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/string.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/tar.h b/utils/fake_libc_include/tar.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/tar.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/termios.h b/utils/fake_libc_include/termios.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/termios.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/time.h b/utils/fake_libc_include/time.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/time.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/unctrl.h b/utils/fake_libc_include/unctrl.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/unctrl.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/unistd.h b/utils/fake_libc_include/unistd.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/unistd.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/utime.h b/utils/fake_libc_include/utime.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/utime.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/utmp.h b/utils/fake_libc_include/utmp.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/utmp.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/wchar.h b/utils/fake_libc_include/wchar.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/wchar.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/fake_libc_include/wctype.h b/utils/fake_libc_include/wctype.h
new file mode 100644
index 0000000..f2992f3
--- /dev/null
+++ b/utils/fake_libc_include/wctype.h
@@ -0,0 +1,2 @@
+#include "_fake_defines.h"

+#include "_fake_typedefs.h"

diff --git a/utils/internal/cppify.bat b/utils/internal/cppify.bat
new file mode 100644
index 0000000..fb16db5
--- /dev/null
+++ b/utils/internal/cppify.bat
@@ -0,0 +1,3 @@
+REM ~ ..\cpp -D__i386__ -I"D:\eli\cpp_stuff\libc_include" -D__extension__ example_c_file.c > example_c_file_pp.c

+REM ~ ..\cpp -D__i386__ -I"D:\eli\c_analyzing\pycparser-trunk\utils\fake_libc_include" example_c_file.c > example_c_file_pp.c

+..\cpp -D__i386__ -I"D:\eli\c_analyzing\pycparser-trunk\utils\fake_libc_include" zc.c > zc_pp.c

diff --git a/utils/internal/example_c_file.c b/utils/internal/example_c_file.c
new file mode 100644
index 0000000..44564ac
--- /dev/null
+++ b/utils/internal/example_c_file.c
@@ -0,0 +1,25 @@
+/* a comment / */

+/* "not a string" */

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <assert.h>

+#include <ctype.h>

+#include <signal.h>

+#include <time.h>

+#include <wchar.h>

+

+/*

+    multiline comment

+    comment

+*/

+

+int main()

+{

+    auto char* multi = "a multi"; /* and a comment !*/

+}

+

+/* A final comment for good measure /* /* /* */

+

+

+

diff --git a/utils/internal/fake_includes.py b/utils/internal/fake_includes.py
new file mode 100644
index 0000000..b55f767
--- /dev/null
+++ b/utils/internal/fake_includes.py
@@ -0,0 +1,13 @@
+import os.path

+

+for cur_path, dirs, files in os.walk('.'):

+    if cur_path == '.':

+        for f in files:

+            if f.endswith('.h'):

+                print f

+                fo = open(f, 'w')

+                fo.write('#include "_fake_defines.h"\n')

+                fo.write('#include "_fake_typedefs.h"\n')

+                fo.close()

+

+

diff --git a/utils/internal/make_fake_typedefs.py b/utils/internal/make_fake_typedefs.py
new file mode 100644
index 0000000..68f57b3
--- /dev/null
+++ b/utils/internal/make_fake_typedefs.py
@@ -0,0 +1,21 @@
+import sys

+sys.path.insert(0, '../..')

+

+from pycparser import c_parser, c_ast, parse_file

+

+

+class MyVisitor(c_ast.NodeVisitor):
+    def visit_Typedef(self, node):
+        print 'typedef int %s;' % node.name

+

+

+

+def generate_fake_typedefs(filename):
+    ast = parse_file(filename, use_cpp=True, cpp_path="../cpp.exe")

+    v = MyVisitor()

+    v.visit(ast)

+

+

+if __name__ == "__main__":

+    generate_fake_typedefs('example_c_file_pp.c')

+

diff --git a/utils/internal/zc.c b/utils/internal/zc.c
new file mode 100644
index 0000000..eff94bd
--- /dev/null
+++ b/utils/internal/zc.c
@@ -0,0 +1,107 @@
+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <getopt.h>

+

+#define PACKAGE "wgram"

+#define VERSION "0.0.4"

+#define MAXLINE 1024

+#define MAXGRAM 32

+

+/* status epilepticus .. print help */

+void print_help(int exval);

+

+int main (int argc, char *argv[]) {

+ /* word delimeter for strtok() */

+ char delim[] = ".,:;`/\"+-_(){}[]<>*&^%$#@!?~/|\\=1234567890 \t\n";

+ char line[MAXLINE];     /* input buff, fgets() */

+ char *stray = NULL;     /* returned value by strtok() */

+ char **strarray = NULL; /* array to hold all entrys */

+ int i = 0;              /* general counter */

+ int strcount = 0;       /* number of entrys in pointer array */

+ int N = 3, pos = 0;     /* ngram size, 3 in this case */

+ int opt = 0;            /* holds command line opt nr.. */

+ int word_flag = 0;      /* print only the `raw' words */

+ FILE *fp = stdin;       /* read input from `FILE', default is stdin */

+

+ while((opt = getopt(argc, argv, "hvn:wf:")) != -1) {

+  switch(opt) {

+   case 'h':

+    print_help(0);

+    break;

+   case 'v':

+  exit(0);

+    break;

+   case 'n':

+    N = atoi(optarg);

+    if(N > MAXGRAM || N < 2) {

+     fprintf(stderr, "%s: Error - Ngram length `%d' out of range `0-%d'\n", 

+       PACKAGE, N, MAXGRAM);

+     return 1;

+    }

+    break;

+   case 'w':

+    word_flag = 1;

+    break;

+   case 'f':

+    if(freopen(optarg, "r", fp) == NULL) {

+     fprintf(stderr, "%s: Error - opening `%s'\n", PACKAGE, optarg);

+     return 1;

+    }

+    break;

+   case '?':

+    fprintf(stderr, "%s: Error - No such option: `%c'\n\n", PACKAGE, optopt);

+    print_help(1);

+  } /* switch */

+ } /* while */

+

+ /* start reading lines from file pointer, add all entrys to **strarray */ 

+ while((fgets(line, MAXLINE, fp)) != NULL) {

+  if(strlen(line) < 2)

+   continue;

+

+  stray = strtok(line, delim);

+  while(stray != NULL) {

+   strarray = (char **)realloc(strarray, (strcount + 1) * sizeof(char *));

+   strarray[strcount++] = strdup(stray);

+   stray = strtok(NULL, delim);

+  }

+ }

+

+ if(word_flag == 0) {

+  /* 

+  // print the array of strings, jumping back each time

+  // (N - 1) positions if a whole ngram of words has been printed

+  */

+  for(i = 0, pos = N; i < strcount; i++, pos--) {

+   if(pos == 0) pos = N, i -= (N - 1), printf("\n");

+    printf("%s ", strarray[i]);

+  }

+  printf("\n");

+ } else {

+  /* print raw words */

+  for(i = 0; i < strcount; i++)

+   printf("%s\n", strarray[i]);

+ }

+

+ /* free the string array */

+ for(i = 0; i < strcount; i++)

+  free(strarray[i]);

+

+ free(strarray);

+ return 0;

+}

+

+/* status epilepticus .. print help */

+void print_help(int exval) {

+ printf("%s,%s extract N-grams from text data\n", PACKAGE, VERSION);

+ printf("Usage: %s [-h] [-v] [-n INT] [-w] [-f FILE]\n\n", PACKAGE);

+

+ printf(" -h        print this help and exit\n");

+ printf(" -v        print version and exit\n\n");

+

+ printf(" -n INT    set ngram length (default=3)\n");

+ printf(" -w        print only the extracted words\n");

+ printf(" -f FILE   read input from `FILE' (default=stdin)\n\n");

+ exit(exval);

+}

diff --git a/utils/internal/zz_parse.py b/utils/internal/zz_parse.py
new file mode 100644
index 0000000..6251a9f
--- /dev/null
+++ b/utils/internal/zz_parse.py
@@ -0,0 +1,10 @@
+import sys

+sys.path.insert(0, '../..')

+

+from pycparser import c_parser, c_ast, parse_file

+

+

+if __name__ == "__main__":

+    ast = parse_file('zc_pp.c', use_cpp=True, cpp_path="../cpp.exe")

+    

+

diff --git a/z_test.py b/z_test.py
new file mode 100644
index 0000000..1eec2a0
--- /dev/null
+++ b/z_test.py
@@ -0,0 +1,75 @@
+from pycparser.c_ast import *

+from pycparser.c_parser import CParser, Coord, ParseError

+

+

+def expand_decl(decl):

+    """ Converts the declaration into a nested list.

+    """

+    typ = type(decl)

+    

+    if typ == TypeDecl:

+        return ['TypeDecl', expand_decl(decl.type)]

+    elif typ == IdentifierType:

+        return ['IdentifierType', decl.names]

+    elif typ == ID:

+        return ['ID', decl.name]

+    elif typ in [Struct, Union]:

+        decls = [expand_decl(d) for d in decl.decls or []]

+        return [typ.__name__, decl.name, decls]

+    else:        

+        nested = expand_decl(decl.type)

+    

+        if typ == Decl:

+            if decl.quals:

+                return ['Decl', decl.quals, decl.name, nested]

+            else:

+                return ['Decl', decl.name, nested]

+        elif typ == Typename: # for function parameters

+            if decl.quals:

+                return ['Typename', decl.quals, nested]

+            else:

+                return ['Typename', nested]

+        elif typ == ArrayDecl:

+            dimval = decl.dim.value if decl.dim else ''

+            return ['ArrayDecl', dimval, nested]

+        elif typ == PtrDecl:

+            return ['PtrDecl', nested]

+        elif typ == Typedef:

+            return ['Typedef', decl.name, nested]

+        elif typ == FuncDecl:

+            if decl.args:

+                params = [expand_decl(param) for param in decl.args.params]

+            else:

+                params = []

+            return ['FuncDecl', params, nested]

+

+#-----------------------------------------------------------------

+

+source_code = """

+int main()

+{

+    int a;

+    a = sizeof(int());

+}

+"""

+

+parser = CParser()

+ast = parser.parse(source_code)

+function_body = ast.ext[0].body #hardcoded to the main() function

+

+for stmt in function_body.stmts:

+    print stmt.coord, expand_decl(stmt.rvalue.expr.type)

+    

+#~ class StructRefVisitor(c_ast.NodeVisitor):

+    #~ def visit_StructRef(self, node):

+        #~ print node.name.name, node.field.name

+

+

+#~ parser = c_parser.CParser()

+#~ ast = parser.parse(code)

+

+#~ ast.show()

+

+#~ v = StructRefVisitor()

+#~ v.visit(ast)

+