/web/piffle-html-0.1.2/piffle.html
HTML | 1306 lines | 1284 code | 21 blank | 1 comment | 0 complexity | e87973a38f0c28f431ab434c9334aef5 MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
- <html >
- <head><title>Piffle A Packet Filter Language</title>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <meta name="generator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/mn.html)">
- <meta name="originator" content="TeX4ht (http://www.cse.ohio-state.edu/~gurari/TeX4ht/mn.html)">
- <!-- html -->
- <meta name="src" content="piffle.tex">
- <meta name="date" content="2007-06-05 11:59:00">
- <link rel="stylesheet" type="text/css" href="piffle.css">
- </head><body
- >
- <div class="maketitle"><div class="titlepage">
- <table class="minipage"><tr><td>Vrije Universiteit Amsterdam
- <br class="newline" />MPhil Parallel and Distributed Computer Systems
- <br class="newline" />Compiler Construction Practical</td></tr></table>
- <h2 class="titleHead"><h2 class="titleHead">Piffle<br />
- A Packet Filter Language</h2></h2>
- <div class="author" ><div class="author" ><span
- class="cmr-17">Jaap Weel</span></div></div>
- <br />
- <div class="date" ><div class="date" ><span
- class="cmr-17">Version 0.1.2 </span></div></div>
- </div> </div>
- <h2 class="likechapterHead"><a
- id="x1-1000"></a>Contents</h2> <div class="tableofcontents">
- <span class="chapterToc">1  <a
- href="#x1-20001" id="QQ2-1-2">Notices</a></span>
- <br />  <span class="sectionToc">1.1  <a
- href="#x1-30001.1" id="QQ2-1-3">Latest version of this document</a></span>
- <br />  <span class="sectionToc">1.2  <a
- href="#x1-40001.2" id="QQ2-1-4">Copyright notice</a></span>
- <br /> <span class="chapterToc">2  <a
- href="#x1-50002" id="QQ2-1-5">Introduction</a></span>
- <br /> <span class="chapterToc">3  <a
- href="#x1-60003" id="QQ2-1-6">Bounded packet filters</a></span>
- <br />  <span class="sectionToc">3.1  <a
- href="#x1-70003.1" id="QQ2-1-7">Dynamic bounds on packet filters</a></span>
- <br />  <span class="sectionToc">3.2  <a
- href="#x1-80003.2" id="QQ2-1-8">Static bounds on arbitrary packet filters</a></span>
- <br />  <span class="sectionToc">3.3  <a
- href="#x1-90003.3" id="QQ2-1-9">Proof carrying code</a></span>
- <br />  <span class="sectionToc">3.4  <a
- href="#x1-100003.4" id="QQ2-1-10">Bounds on restricted packet filters</a></span>
- <br /> <span class="chapterToc">4  <a
- href="#x1-110004" id="QQ2-1-11">Language definition</a></span>
- <br />  <span class="sectionToc">4.1  <a
- href="#x1-120004.1" id="QQ2-1-12">Vocabulary and representation</a></span>
- <br />  <span class="sectionToc">4.2  <a
- href="#x1-130004.2" id="QQ2-1-13">Declarations</a></span>
- <br />  <span class="sectionToc">4.3  <a
- href="#x1-140004.3" id="QQ2-1-14">Types</a></span>
- <br />  <span class="sectionToc">4.4  <a
- href="#x1-150004.4" id="QQ2-1-15">Expressions</a></span>
- <br />  <span class="sectionToc">4.5  <a
- href="#x1-160004.5" id="QQ2-1-16">Operators</a></span>
- <br />  <span class="sectionToc">4.6  <a
- href="#x1-170004.6" id="QQ2-1-17">The types of expressions</a></span>
- <br />  <span class="sectionToc">4.7  <a
- href="#x1-180004.7" id="QQ2-1-18">Constant expressions</a></span>
- <br />  <span class="sectionToc">4.8  <a
- href="#x1-190004.8" id="QQ2-1-19">Source files</a></span>
- <br />  <span class="sectionToc">4.9  <a
- href="#x1-200004.9" id="QQ2-1-20">The filter function</a></span>
- <br />  <span class="sectionToc">4.10  <a
- href="#x1-210004.10" id="QQ2-1-21">Preprocessor</a></span>
- <br /> <span class="chapterToc">5  <a
- href="#x1-220005" id="QQ2-1-22">The Piffle compiler, pfc</a></span>
- <br />  <span class="sectionToc">5.1  <a
- href="#x1-230005.1" id="QQ2-1-23">The pfc(1) manual page</a></span>
- <br /> <span class="chapterToc">6  <a
- href="#x1-240006" id="QQ2-1-24">The pcap boilerplate, pcap.c</a></span>
- <br />  <span class="sectionToc">6.1  <a
- href="#x1-250006.1" id="QQ2-1-25">The pfc.pcap(1) manual page</a></span>
- <br />  <span class="sectionToc">6.2  <a
- href="#x1-260006.2" id="QQ2-1-26">Writing programs for the pcap.c boilerplate</a></span>
- <br /> <span class="chapterToc">7  <a
- href="#x1-270007" id="QQ2-1-27">The test boilerplate, test.c</a></span>
- <br />  <span class="sectionToc">7.1  <a
- href="#x1-280007.1" id="QQ2-1-28">The pfc.test(1) manual page</a></span>
- <br /> <span class="chapterToc">8  <a
- href="#x1-290008" id="QQ2-1-29">An example of a packet filter</a></span>
- <br />  <span class="sectionToc">8.1  <a
- href="#x1-300008.1" id="QQ2-1-30">A packet filter in PFL</a></span>
- <br />  <span class="sectionToc">8.2  <a
- href="#x1-310008.2" id="QQ2-1-31">The packet filter translated to C by pfc</a></span>
- </div>
- <h2 class="chapterHead"><span class="titlemark">1</span>.  <a
- id="x1-20001"></a>Notices</h2>
- <h3 class="sectionHead"><span class="titlemark">1.1</span>.  <a
- id="x1-30001.1"></a>Latest version of this document</h3>
- <!--l. 23--><p class="noindent">For up-to-date information on Piffle, and the latest version of this document, be sure to visit
- the following web site:
- <!--l. 26--><p class="indent"> <span
- class="cmti-12">http://code.google.com/p/piffle/wiki/PiffleWiki</span>
- <!--l. 28--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">1.2</span>.  <a
- id="x1-40001.2"></a>Copyright notice</h3>
- <!--l. 30--><p class="noindent">Copyright (c) 2007, Jaap Weel. This work is licensed under the Creative Commons
- Attribution–Share-Alike 3.0 License. To view a copy of this license, visit
- <!--l. 34--><p class="indent"> <span
- class="cmti-12">http://creativecommons.org/licenses/by-sa/3.0/</span>
- <!--l. 36--><p class="indent"> or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco,
- California, 94105, USA.
- <h2 class="chapterHead"><span class="titlemark">2</span>.  <a
- id="x1-50002"></a>Introduction</h2>
- <!--l. 44--><p class="noindent">Piffle is a pronounceable form of PFL, that is, Packet Filter Language. (“Piffle” is also an
- obscure word for “chatter”.) Piffle is a very simple programming language for writing network
- packet filters, with one special feature: the compiler can enforce limits on the processor time
- and memory used for processing each packet of input. This is accomplished by passing
- arguments to the –C and –M command line options. Memory bounds are in words, more or
- less, and CPU bounds are in arbitrary units.
- <!--l. 53--><p class="indent"> In this document, I will first consider in general the problem of checking arbitrary programs
- for transgression of such resource bounds, and notice that it is very hard. I will conclude that
- in Piffle we must punt and restrict the class of programs that can be used as packet filters,
- which makes the problem comparatively easy.
- <!--l. 59--><p class="indent"> After that, I will give the definition of the Piffle language, and some instructions for how to
- use the Piffle compiler.
- <h2 class="chapterHead"><span class="titlemark">3</span>.  <a
- id="x1-60003"></a>Bounded packet filters</h2>
- <!--l. 65--><p class="noindent">An important requirement in designing network packet processing code is that the amount of
- time and memory spent processing each packet be bounded. We do not want the entire
- network connection grinding to a halt because of an unforeseen infinite loop in a packet filter.
- There are several ways to prevent such havoc. In this chapter, I will discuss each of them, and
- explain which one I chose and why.
- <h3 class="sectionHead"><span class="titlemark">3.1</span>.  <a
- id="x1-70003.1"></a>Dynamic bounds on packet filters</h3>
- <!--l. 74--><p class="noindent">We can check bounds at runtime. For instance, we can run the packet filter on each packet for
- a specified quota of clock ticks and drop the packet if processing has not finished by the time
- the quota runs out.
- <!--l. 79--><p class="indent"> One problem with this runtime approach is that a bug in the packet filters can
- remain hidden for a long time until some unusual packet is received that triggers the
- bug.
- <!--l. 83--><p class="indent"> Another problem is that it is not clear exactly what to do when the bound is exceeded:
- Should we drop the packet? Should we pass it along unaltered? We would like to be able to
- give the packet filter author the opportunity to decide what to do with packets that take too
- long to analyze. But if we allow that sort of flexibility within the dynamic checking framework,
- we will inevitably have to allow a chunk of cleanup code to deal with “slow” packets, which
- in turn can only run for a restricted amount of time. If <span
- class="cmti-12">that </span>time is exceeded, do
- we need a third program to deal with slow packet filters that have slow cleanup
- code?
- <!--l. 94--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">3.2</span>.  <a
- id="x1-80003.2"></a>Static bounds on arbitrary packet filters</h3>
- <!--l. 96--><p class="noindent">Given the problems with checking bounds at run time, we might want to check at compile
- time. To do that, we need a language in which we can express exactly those packet filter
- programs that execute within given time and space bounds.
- <!--l. 101--><p class="indent"> Determining whether a given program runs within these bounds sounds like it ought to be
- undecidable, but it is not. After all, we are not trying to evaluate whether a given packet filter
- will terminate <span
- class="cmti-12">at all, in the end</span>; we merely want it to terminate within a given number of
- steps. (The space bound problem is analogous.)
- <!--l. 107--><p class="indent"> The problem of determining whether a given Turing machine will terminate within a certain
- number of steps is, in fact, decidable. In a limited number <span
- class="cmmi-12">N </span>of steps the machine can read
- only a limited amount <span
- class="cmmi-12">N </span>of its tape, which means we could check whether the time bound by
- exhaustively running the machine for at most <span
- class="cmmi-12">N </span>steps on all tapes of length at most
- <span
- class="cmmi-12">N</span>.
- <!--l. 114--><p class="indent"> It should be obvious that this procedure, while quite satisfactory as a constructive proof of
- decidability, is impractical, because the process of bounds checking itself would take lots of
- time (in fact, exponential in <span
- class="cmmi-12">N</span>). What we need is a bound on the process of bounds
- checking.
- <!--l. 120--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">3.3</span>.  <a
- id="x1-90003.3"></a>Proof carrying code</h3>
- <!--l. 122--><p class="noindent">One way to design a language that would let us check bounds at compile time would be to
- annotate the program with a proof of the statement that it will terminate within a given
- number of steps.
- <!--l. 126--><p class="indent"> Proofs could be provided either as annotations or as part of a type
- system.<span class="footnote-mark"><a
- href="piffle2.html#fn1x5"><sup class="textsuperscript">1</sup></a></span><a
- id="x1-9001f1"></a>
- The use of proof carrying code would allow all packet filters to be written that can be
- proven to execute within bounds, and it would allow for the bounds checking problem
- itself to be tractable. Depending on the details of the formal system used, proof
- (or type) checking can be polynomial (and often linear) in the length of the proof.
- Therefore, bound checking of annotated code complies with the rule of thumb that
- compilers should use only algorithms that are at most polynomial in the length of the
- program.
- <!--l. 137--><p class="indent"> The practical liabilities of proof carrying code are well known. Programmers are unfamiliar
- with proof systems, and those who know their way around them could still have trouble
- coming up with the (possibly lengthy) proofs in individual cases. Therefore, we
- will not pursue proof carrying code any further now, and turn instead to a simpler
- solution.
- <!--l. 144--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">3.4</span>.  <a
- id="x1-100003.4"></a>Bounds on restricted packet filters</h3>
- <!--l. 146--><p class="noindent">If we do not want to get bogged down in the depths of formal type theory, but still design a
- language that would let us check bounds at compile time, we arrive at what is, in fact, the
- traditional solution to the problem of bounded packet filters. We will construct a programming
- language out of familiar abstractions, and that language will allow us to express a
- <span
- class="cmti-12">large but arbitrary </span>subset of the set of all packet filters that execute in bounded
- time.
- <!--l. 154--><p class="indent"> Such a language is not Turing complete, but if it is designed intelligently, it can
- cover a large fraction of the problems that people may want to solve using packet
- filters.
- <!--l. 158--><p class="indent"> An example of a packet filter language based on familiar programming abstractions is the traditional BSD
- packet filter <span
- class="cmti-12">bpf</span>.<span class="footnote-mark"><a
- href="piffle3.html#fn2x5"><sup class="textsuperscript">2</sup></a></span><a
- id="x1-10001f2"></a>
- Its packet filters are written in a simple machine code with a little twist: the virtual machine
- allows jumps forward, but not backward. That way, the time spent executing any given packet
- filter program is at most proportional to the length of the program.
- <!--l. 167--><p class="indent"> For Piffle, we take a similar approach. Piffle is not based on machine language, but on block
- structured, procedural programming languages such as C and Pascal. Just as the <span
- class="cmti-12">bpf </span>language
- omits backward jumps from machine code, Piffle omits unbounded looping constructs and
- recursive procedure calls from block structured, procedural code. Piffle does provide some
- bounded looping constructs, and procedure calls are allowed as long as the call graph contains
- no cycles.
- <h2 class="chapterHead"><span class="titlemark">4</span>.  <a
- id="x1-110004"></a>Language definition</h2>
- <!--l. 193--><p class="noindent">The Piffle language is defined as a set of sentences, called source files, well formed according to
- the Piffle syntax. To describe the syntax, I will use a modified version of the Backus Normal
- Form (also known as Backus-Naur Formalism or BNF), using <span
- class="cmmi-12">x</span><sup><span
- class="cmr-8">?</span></sup> to indicate that <span
- class="cmmi-12">x</span>
- may appear either once or not at all, <span
- class="cmmi-12">x</span><sup><span
- class="cmr-8">+</span></sup> to indicate that <span
- class="cmmi-12">x </span>may appear at least
- once, and <span
- class="cmmi-12">x</span><sup><span
- class="cmsy-8">*</span></sup> to indicate that <span
- class="cmmi-12">x </span>may appear any number of times, including not at
- all.
- <!--l. 201--><p class="indent"> I will not provide a formal definition of the semantics of Piffle. In general, when I do not
- specify the meaning or type of some Piffle construct, it can be assumed that it is analogous to
- the semantics of its closest analog in C.
- <h3 class="sectionHead"><span class="titlemark">4.1</span>.  <a
- id="x1-120004.1"></a>Vocabulary and representation</h3>
- <!--l. 208--><p class="noindent">A well formed Piffle program is composed of tokens, which are identifiers, literals, and reserved
- tokens. Each token is a sequence of characters, and may not contain whitespace unless this is
- explicitly specified. Any amount of whitespace may be inserted between tokens, and indeed
- must be inserted between any two tokens that would make a valid token when put
- together.
- <!--l. 215--><p class="indent"> Whitespace is any sequence of blanks, tabs, vertical tabs, form feeds, line feeds, and carriage
- returns (in C notation, any character in the string <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">"</span><span
- class="cmtt-12"> \v\f\t\r\n"</span></span></span>). Comments may also
- appear wherever whitespace can appear. (Unlike in C, they may <span
- class="cmti-12">not </span>appear inside of a token.)
- In-line comments may be inserted between any two tokens. They are delimited by <span
- class="cmtt-12">/* </span>and <span
- class="cmtt-12">*/</span>
- and may be nested. End-of-line comments may also be inserted between any two tokens,
- and they run from <span
- class="cmtt-12">// </span>to the next line end, or the end of the file, whichever comes
- first.
- <!--l. 225--><p class="indent"> Identifiers are sequences of letters, digits, and underscores. The first character may not be a
- digit. <div class="eqnarray">
- <center class="math-display" >
- <img
- src="piffle0x.png" alt=" |--| |-| *
- ident = (-letter |-x-)|(letter |-x-|-digit)
- letter = |A || ⋅⋅⋅ ||Z|| a || ⋅⋅⋅ | z|
- |--| |--| --- ---
- digit = |0 || ⋅⋅⋅ ||9|
- --- ---
- " class="math-display" ></center>
- </div>
- <!--l. 235--><p class="indent"> The literals available in Piffle, are numbers, the <span
- class="cmtt-12">unit </span>literal, which is the canonical value of
- type <span
- class="cmtt-12">void</span>, <span
- class="cmtt-12">true</span>, which means the same as <span
- class="cmtt-12">1 :</span><span
- class="cmtt-12"> bool</span>, and <span
- class="cmtt-12">false</span>, which means the same as <span
- class="cmtt-12">0</span>
- <span
- class="cmtt-12">:</span><span
- class="cmtt-12"> bool</span>. The only numbers available are integers. They can be represented as decimal, octal,
- or hexidecimal, the same way as in Haskell 98. Note that this differs from C syntax in that
- leading 0s are simply ignored, and the prefix for octal is 0o or 0O rather than simply
- 0.
- <!--l. 253--><p class="indent"> <div class="eqnarray">
- <center class="math-display" >
- <img
- src="piffle1x.png" alt=" |----|- |-----| |------|
- literal = unit---|-true--|-false---| integer| |--|
- integer = digit+ | ( 0o|| |0O ) octit+| ( 0x || |0X|) hexit+
- |-| |--| |-|- |-| |-|-- ---|-|
- hexit = 0 || ⋅⋅⋅ ||9|| A || ⋅ ⋅⋅ | F|| a|| ⋅⋅⋅ | f|
- |-| |--| --- --- --- ---
- octit = 0--| ⋅⋅⋅ |-7|
- " class="math-display" ></center>
- </div>
- <!--l. 255--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">4.2</span>.  <a
- id="x1-130004.2"></a>Declarations</h3>
- <!--l. 257--><p class="noindent">Piffle allows no recursion, and all functions must be defined before they are used. Therefore,
- there is no need for forward declarations. If the return type of a function is omitted, <span
- class="cmtt-12">void </span>is
- implied. The meaning of duplicate definitions is undefined.
- <!--l. 270--><p class="indent"> <div class="eqnarray">
- <center class="math-display" >
- <img
- src="piffle2x.png" alt="declaration = vardec | fundec
- |----| |-|
- vardec = |var-|ident |:|type |-| |-| |-|
- fundec = |fun |ident |(|argl? |)| (|:| type )? = |expression
- ----- |-| --- |-| --- |-|- ---
- argl = ident :--type ( ,--ident -:- type )*
- " class="math-display" ></center>
- </div>
- <!--l. 272--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">4.3</span>.  <a
- id="x1-140004.3"></a>Types</h3>
- <!--l. 274--><p class="noindent">A type in Piffle is <span
- class="cmtt-12">void</span>, an atomic type, or an array. Atomic types come in signed and
- unsigned, and have 8, 16, or 32 bits. Each array type encompasses only arrays of a specific
- length; you can declare an “array of 1024 integers”, but not an “array of integers”. This is an
- important feature, because it is what enables the calculation of resource limits. It is
- at present <span
- class="cmti-12">not </span>actually used for anything else; in particular, there are no bounds
- checks.
- <!--l. 290--><p class="indent"> <div class="eqnarray">
- <center class="math-display" >
- <img
- src="piffle3x.png" alt=" |-----| |--| |-|
- type = void---| atomic | atomic-[-|integer ]--
- |-----| |---| |---| |----| |--| |----| |----|
- atomic = bool---|-u8-|| u16-- |-u32-|| s8--| -s16-||-s32-|
- " class="math-display" ></center>
- </div>
- <!--l. 292--><p class="indent"> Whenever a value of type of void is expected, a value of any other type will do as
- well.
- <!--l. 295--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">4.4</span>.  <a
- id="x1-150004.4"></a>Expressions</h3>
- <!--l. 297--><p class="noindent">Unlike in C or Pascal, in Piffle there is no syntactic distinction between expressions and
- statements; every expression can be used as a statement and vice versa.
- <!--l. 327--><p class="indent"> <div class="eqnarray">
- <center class="math-display" >
- <img
- src="piffle4x.png" alt=" *
- expression = expression2 (binop expression2 ) |--| |-|
- expression2 = unop *expression3 ( [--expression -]-) ? ( :-atomic )?
- expression3 = literal |--| |-| |--|
- | ident (-(-|(expression ( ,--expression) *)?-)-) ?
- |-| |--|
- | -(-expression -)-| ---
- | | |-| * |-| * | |
- | |{--(declaration |;--)-( expression ;--)--}--
- | |if |expression then |expression (|else |expression )?
- |----| |--|------- |------|----- |---|
- | -for-|ident in--expression ( -while--expression) ?-do-|expression
- |----| |-----| |---|
- | -for-|ident from---integer -to-|integer
- |-------| ? |--|
- (-while--|expression ) do--expression
- " class="math-display" ></center>
- </div>
- <!--l. 329--><p class="indent"> Cast expressions (like <span
- class="cmtt-12">x : u32</span>) allow the use of a value of one atomic type with another
- atomic type. The exact meaning of such conversions is undefined but expected to correspond
- to the behavior of the C compiler on the platform in use.
- <!--l. 334--><p class="indent"> Blocks have the value of the last expression in them (which is why there is no <span
- class="cmtt-12">return</span>
- statement); if a block contains no expressions, <span
- class="cmtt-12">unit </span>is implied.
- <!--l. 338--><p class="indent"> If-then-else statements have values, and correspond more closely to the C ternary
- operator (<span
- class="cmtt-12">?:</span>) than to the C if-else statement. If an <span
- class="cmtt-12">else </span>clause is omitted, <span
- class="cmtt-12">unit </span>is
- implied.
- <!--l. 342--><p class="indent"> Loops in Piffle are somewhat peculiar, in order to accommodate resource bound checking.
- There are two types of loops: one will iterate with a variable sequentially bound to each
- number in a range (which includes both bounds), and the other will iterate with a
- variable sequentially bound to each element in an array. Both allow the use of a <span
- class="cmtt-12">while</span>
- clause, which will be evaluated before each iteration; if it evaluates to 0, the loop is
- aborted immediately. The iterator variable is bound within the while clause, so it is
- perfectly valid to say something like <span
- class="cmtt-12">for i from 0 to 10 while is</span><span
- class="cmtt-12">_useful(i) do</span>
- <span
- class="cmtt-12">...</span>.
- <!--l. 354--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">4.5</span>.  <a
- id="x1-160004.5"></a>Operators</h3>
- <!--l. 356--><p class="noindent">The operators are given by <div class="eqnarray">
- <center class="math-display" >
- <img
- src="piffle5x.png" alt=" |--| |-| |-| |-| |-| |---| |---| |-|
- binop = |*-|| /--| %|-||+-||----|--<<-||->>-|||<--
- | |> || <= || >= | ||== |||!= || & || |^|
- |--| |--| |--| |--| |---| |--| |--|
- | -|-|| &&--| |-|- |-=-||-+=-|| -=--| -*=-
- |---| |--| |---| |---| |--| |----| |----|
- | -%=-|| /=--| -|=-||-&=-|| ^=--| ->>=-||-<<=-|
- |--| |-| |-| |-|
- unop = -+-|| ---| ~--| !--
- " class="math-display" ></center>
- </div>
- <!--l. 370--><p class="indent"> The grammar as specified so far correctly and completely specifies the language, but it is
- misleading and ambiguous, because it does not indicate the meaning of certain compound
- expressions. In fact, the actual Piffle parser will respect the standard C precedence rules, as
- summarized in the following table.
- <div class="tabular"><table class="tabular"
- cellspacing="0" cellpadding="0"
- ><colgroup id="TBL-2-1g"><col
- id="TBL-2-1"><col
- id="TBL-2-2"></colgroup><tr
- class="hline"><td><hr></td><td><hr></td></tr><tr
- class="hline"><td><hr></td><td><hr></td></tr><tr
- style="vertical-align:baseline;" id="TBL-2-1-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-1-1"
- class="td11">Operators (ordered from tight to loose) </td><td style="white-space:nowrap; text-align:left;" id="TBL-2-1-2"
- class="td11">Associativity</td>
- </tr><tr
- class="hline"><td><hr></td><td><hr></td></tr><tr
- style="vertical-align:baseline;" id="TBL-2-2-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-2-1"
- class="td11"><span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">*</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">/</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">%</span></span></span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-2-2-2"
- class="td11">left-to-right </td>
- </tr><tr
- style="vertical-align:baseline;" id="TBL-2-3-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-3-1"
- class="td11"><span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">+</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">-</span></span></span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-2-3-2"
- class="td11">left-to-right </td>
- </tr><tr
- style="vertical-align:baseline;" id="TBL-2-4-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-4-1"
- class="td11"><span class="obeylines-h"><span class="verb"><span
- class="cmtt-12"><<</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">>></span></span></span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-2-4-2"
- class="td11">left-to-right </td>
- </tr><tr
- style="vertical-align:baseline;" id="TBL-2-5-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-5-1"
- class="td11"><span class="obeylines-h"><span class="verb"><span
- class="cmtt-12"><</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">></span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12"><=</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">>=</span></span></span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-2-5-2"
- class="td11">left-to-right </td>
- </tr><tr
- style="vertical-align:baseline;" id="TBL-2-6-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-6-1"
- class="td11"><span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">==</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">!=</span></span></span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-2-6-2"
- class="td11">left-to-right </td>
- </tr><tr
- style="vertical-align:baseline;" id="TBL-2-7-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-7-1"
- class="td11"><span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">&</span></span></span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-2-7-2"
- class="td11">left-to-right </td>
- </tr><tr
- style="vertical-align:baseline;" id="TBL-2-8-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-8-1"
- class="td11"><span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">^</span></span></span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-2-8-2"
- class="td11">left-to-right </td>
- </tr><tr
- style="vertical-align:baseline;" id="TBL-2-9-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-9-1"
- class="td11"><span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">|</span></span></span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-2-9-2"
- class="td11">left-to-right </td>
- </tr><tr
- style="vertical-align:baseline;" id="TBL-2-10-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-10-1"
- class="td11"><span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">&&</span></span></span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-2-10-2"
- class="td11">left-to-right </td>
- </tr><tr
- style="vertical-align:baseline;" id="TBL-2-11-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-11-1"
- class="td11"><span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">||</span></span></span> </td><td style="white-space:nowrap; text-align:left;" id="TBL-2-11-2"
- class="td11">left-to-right </td>
- </tr><tr
- style="vertical-align:baseline;" id="TBL-2-12-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-12-1"
- class="td11"><span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">=</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">+=</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">-=</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">*=</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">%=</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">/=</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">|=</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">&=</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">^=</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12">>>=</span></span></span> <span class="obeylines-h"><span class="verb"><span
- class="cmtt-12"><<=</span></span></span></td><td style="white-space:nowrap; text-align:left;" id="TBL-2-12-2"
- class="td11">right-to-left </td>
- </tr><tr
- class="hline"><td><hr></td><td><hr></td></tr><tr
- class="hline"><td><hr></td><td><hr></td></tr><tr
- style="vertical-align:baseline;" id="TBL-2-13-"><td style="white-space:nowrap; text-align:left;" id="TBL-2-13-1"
- class="td11"> </td> </tr></table>
- </div>
- <!--l. 399--><p class="indent"> The keywords have the loosest possible preference, and thus the expressions at the end of <span
- class="cmtt-12">if</span>
- and <span
- class="cmtt-12">for </span>expressions extend to the right as far as possible.
- <!--l. 403--><p class="indent"> Even though any expression may be used, according to the grammar, as the left-hand side
- of an assignment, assignment is only a meaningful operation when the left-hand side is an
- “lvalue” of the form <span
- class="cmti-12">ident</span> ( <span class="fbox"><span
- class="cmtt-12">[</span></span> <span
- class="cmti-12">expression</span> <span class="fbox"><span
- class="cmtt-12">]</span></span> ) <sup><span
- class="cmr-8">?</span></sup>.
- <!--l. 408--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">4.6</span>.  <a
- id="x1-170004.6"></a>The types of expressions</h3>
- <!--l. 410--><p class="noindent">The binary operators <span
- class="cmtt-12">*</span>, <span
- class="cmtt-12">/</span>, <span
- class="cmtt-12">%</span>, <span
- class="cmtt-12">+</span>, <span
- class="cmtt-12">-</span>, <span
- class="cmtt-12">&</span>, <span
- class="cmtt-12">|</span>, <span
- class="cmtt-12">^</span>, <span
- class="cmtt-12">=</span>, <span
- class="cmtt-12">*=</span>, <span
- class="cmtt-12">/=</span>, <span
- class="cmtt-12">%=</span>, <span
- class="cmtt-12">+=</span>, <span
- class="cmtt-12">-=</span>, <span
- class="cmtt-12">&=</span>, <span
- class="cmtt-12">|=</span>, <span
- class="cmtt-12">^=</span>, all take
- two operands of the same, atomic, type, and return a value of that type, that is,
- formally,
- <center class="math-display" >
- <img
- src="piffle6x.png" alt="*, /,%,+,-,&,| ,^,=,*=,...,^= : ∀τ ∈ {bool, u8,u16, u32,s8, s16,s32 }. τ × τ → τ .
- " class="math-display" ></center>
- <!--l. 420--><p class="nopar"> The unary operators <span
- class="cmtt-12">+</span>, <span
- class="cmtt-12">-</span>, and <span
- class="cmtt-12">~ </span>all take one operand of any integer type and return a value
- of that type, that is, formally,
- <center class="math-display" >
- <img
- src="piffle7x.png" alt="+,- ,~ : ∀τ ∈ {bool, u8,u16, u32,s8, s16,s32 }. τ → τ .
- " class="math-display" ></center>
- <!--l. 426--><p class="nopar"> The binary operators <span
- class="cmtt-12"><</span>, <span
- class="cmtt-12">></span>, <span
- class="cmtt-12"><=</span>, <span
- class="cmtt-12">>=</span>, <span
- class="cmtt-12">==</span>, <span
- class="cmtt-12">!=</span>, <span
- class="cmtt-12">&&</span>, and <span
- class="cmtt-12">|| </span>all take two operands of arbitrary
- atomic types, and return a value of type <span
- class="cmtt-12">bool</span>, that is, formally
- <center class="math-display" >
- <img
- src="piffle8x.png" alt="<, >,<=,>=, ==,!=,&&, || : ∀τ,υ ∈ {bool, u8, u16,u32, s8,s16,s32 }. τ × υ → bool .
- " class="math-display" ></center>
- <!--l. 436--><p class="nopar"> The unary operator <span
- class="cmtt-12">! </span>takes one operand of any integer types and returns a value of type
- <span
- class="cmtt-12">bool</span>, that is, formally,
- <center class="math-display" >
- <img
- src="piffle9x.png" alt="! : ∀τ ∈ {bool, u8,u16, u32,s8, s16,s32 }. τ → bool .
- " class="math-display" ></center>
- <!--l. 442--><p class="nopar"> For the binary operators <span
- class="cmtt-12"><<</span>, <span
- class="cmtt-12">>></span>, <span
- class="cmtt-12"><<=</span>, and <span
- class="cmtt-12">>>=</span>, the value being shifted and the value
- indicating the number of bits to shift need not be of the same type, but both types
- must be atomic, and the entire expression gets the type of the value being shifted.
- Formally,
- <center class="math-display" >
- <img
- src="piffle10x.png" alt="<<,>>,<<=, >>= : ∀σ, τ ∈ {bool, u8,u16,u32, s8,s16, s32}. τ × σ → τ .
- " class="math-display" ></center>
- <!--l. 451--><p class="nopar">
- <!--l. 453--><p class="indent"> A sequence <span
- class="cmsy-10x-x-120">{</span><span
- class="cmtt-12">...</span><span
- class="cmsy-10x-x-120">} </span>of expressions has the value and type of the last expression in the
- sequence, or <span
- class="cmtt-12">void </span>if there are no expressions. All expressions preceding the last are
- expected to have type <span
- class="cmtt-12">void</span>, but as stated above, any other type will do when <span
- class="cmtt-12">void </span>is
- expected.
- <!--l. 459--><p class="indent"> An <span
- class="cmtt-12">if </span>expression consists of a condition, a consequent, and an optional alternative. If the
- alternative is omitted, <span
- class="cmtt-12">unit </span>is implied. The condition may be of any atomic type. The types of
- the consequent and the alternative must match, but note again that because any type can be
- used instead of <span
- class="cmtt-12">void</span>, if the type of either branch is <span
- class="cmtt-12">void</span>, the other branch can have any type.
- The alternative is evaluated only if the condition evaluates to <span
- class="cmtt-12">0</span>; otherwise, the consequent is
- evaluated. In either case, the entire expression gets the value of the evaluated clause. To
- clarify:
- <table
- class="verbatim"><tr class="verbatim"><td
- class="verbatim"><div class="verbatim">
- fun frob () : void = {
-  <br />    var x, y : u32;
-  <br />    if 3 < 5 then do_something();  /* do_something() is executed */
-  <br />    x = if 3 < 5 then 0 else 1;    /* x is set to 0 */
-  <br />    x = if 3 > 5 then 0 else 1;    /* x is set to 1 */
-  <br />    y = if 3 < 5 then 0;           /* This won’t type check!! */
-  <br />};
- </div>
- </td></tr></table>
- <!--l. 476--><p class="nopar">
- <!--l. 478--><p class="indent"> There are two iteration constructs in Piffle. Both are different from iteration constructs in
- comparable languages because of the need for computing resource bounds.
- <!--l. 482--><p class="indent"> An expression of the form
- <center class="math-display" >
- <img
- src="piffle11x.png" alt="|---| |---| |------| ? |--|
- for--α -in-β ( -while--γ) do--δ
- " class="math-display" ></center>
- <!--l. 483--><p class="nopar"> has type <span
- class="cmtt-12">void</span>. The range <span
- class="cmmi-12">β </span>must be of type <span
- class="cmtt-12">array </span><span
- class="cmmi-12">i τ</span>, for some integer <span
- class="cmmi-12">i </span>and some atomic
- type <span
- class="cmmi-12">τ</span>, and the variable <span
- class="cmmi-12">α </span>will be of type <span
- class="cmmi-12">τ </span>and scope over <span
- class="cmmi-12">γ </span>and <span
- class="cmmi-12">δ</span>. The condition <span
- class="cmmi-12">γ </span>may
- have any atomic type, and the body <span
- class="cmmi-12">δ </span>must be of type <span
- class="cmtt-12">void </span>(with any other type
- allowed).
- <!--l. 491--><p class="indent"> An expression of the form
- <center class="math-display" >
- <img
- src="piffle12x.png" alt="|----| |-----| |---| |------| ? |--|
- -for-|α -from--β0-to-|β1 (-while--γ) -do-δ
- " class="math-display" ></center>
- <!--l. 492--><p class="nopar"> has type <span
- class="cmtt-12">void</span>. The bounds <span
- class="cmmi-12">β</span><sub><span
- class="cmr-8">0</span><span
- class="cmmi-8">,</span><span
- class="cmr-8">1</span></sub> must be constant expressions of any atomic type, and <span
- class="cmmi-12">α </span>will
- be of type <span
- class="cmtt-12">u32 </span>and scope over <span
- class="cmmi-12">γ </span>and <span
- class="cmmi-12">δ</span>. The condition <span
- class="cmmi-12">γ </span>may have any atomic type, and the
- body <span
- class="cmmi-12">δ </span>must be of type <span
- class="cmtt-12">void </span>(with any other type allowed).
- <!--l. 499--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">4.7</span>.  <a
- id="x1-180004.7"></a>Constant expressions</h3>
- <!--l. 501--><p class="noindent">Integer literals are assigned a special type (<span
- class="cmtt-12">sliteral</span>) by the compiler. This type is considered
- atomic, and values of type <span
- class="cmtt-12">sliteral </span>can always be used when any atomic type is
- expected.
- <!--l. 506--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">4.8</span>.  <a
- id="x1-190004.8"></a>Source files</h3>
- <!--l. 508--><p class="noindent">A source file consists of a number of declarations separated by semicolons.
- <!--l. 513--><p class="indent"> <div class="eqnarray">
- <center class="math-display" >
- <img
- src="piffle13x.png" alt=" |--|
- file = ( declaration |; ) *
- ---
- " class="math-display" ></center>
- </div>
- <!--l. 515--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">4.9</span>.  <a
- id="x1-200004.9"></a>The filter function</h3>
- <!--l. 517--><p class="noindent">The function named <span
- class="cmtt-12">filter </span>has a special meaning. It is used as the root of the call graph
- (which is actually a tree, in the Piffle case) by the compiler when checking for memory
- and CPU usage bounds. It is also the function that gets called on every incoming
- packet.
- <!--l. 522--><p class="indent"> Strictly speaking, this is dependent on which boilerplate is being used. Boilerplates are a
- concept we will get to in the chapter about the compiler, but rest assured that all
- currently available boilerplates will cause <span
- class="cmtt-12">filter </span>to be called on each incoming
- packet.
- <!--l. 529--><p class="noindent">
- <h3 class="sectionHead"><span class="titlemark">4.10</span>.  <a
- id="x1-210004.10"></a>Preprocessor</h3>
- <!--l. 531--><p class="noindent">It should be possible to run a Piffle program through a regular C preprocessor (cpp). This is
- not done by default; you would have to do it manually. Also make sure not to use nested
- comments if you want to use cpp. The compiler does not interpret cpp line directives, so any
- error messages you get about preprocessed code will refer to positions in the preprocessed
- source.
- <h2 class="chapterHead"><span class="titlemark">5</span>.  <a
- id="x1-220005"></a>The Piffle compiler, pfc</h2>
- <!--l. 540--><p class="noindent">The Piffle compiler, pfc, is a fairly simple compiler, written in the Haskell programming language,
- that outputs C code. It is documented in the pfc(1) man page, which is reproduced here in its
- entirety.<span class="footnote-mark"><a
- href="piffle4.html#fn1x7"><sup class="textsuperscript">1</sup></a></span><a
- id="x1-22001f1"></a>
- <h3 class="sectionHead"><span class="titlemark">5.1</span>.  <a
- id="x1-230005.1"></a>The pfc(1) manual page</h3>
- <!--l. 550--><p class="noindent">
- <div class="fancyvrb" id="fancyvrb1">
- <a
- id="x1-23002r1"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> PFC(1)</span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> PFC(1)</span>
- <br class="fancyvrb" /><a
- id="x1-23004r2"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span>
- <br class="fancyvrb" /><a
- id="x1-23006r3"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span>
- <br class="fancyvrb" /><a
- id="x1-23008r4"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span>
- <br class="fancyvrb" /><a
- id="x1-23010r5"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> NAME</span>
- <br class="fancyvrb" /><a
- id="x1-23012r6"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> pfc</span><span
- class="cmtt-10"> -</span><span
- class="cmtt-10"> Piffle</span><span
- class="cmtt-10"> Compiler</span>
- <br class="fancyvrb" /><a
- id="x1-23014r7"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span>
- <br class="fancyvrb" /><a
- id="x1-23016r8"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> SYNOPSIS</span>
- <br class="fancyvrb" /><a
- id="x1-23018r9"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> pfc</span><span
- class="cmtt-10"> [OPTIONS]</span><span
- class="cmtt-10"> file.pfl</span>
- <br class="fancyvrb" /><a
- id="x1-23020r10"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span>
- <br class="fancyvrb" /><a
- id="x1-23022r11"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> INTRODUCTION</span>
- <br class="fancyvrb" /><a
- id="x1-23024r12"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> Piffle</span><span
- class="cmtt-10"> is</span><span
- class="cmtt-10"> a</span><span
- class="cmtt-10"> pronounceable</span><span
- class="cmtt-10"> form</span><span
- class="cmtt-10"> of</span><span
- class="cmtt-10"> PFL,</span><span
- class="cmtt-10"> that</span><span
- class="cmtt-10"> is,</span><span
- class="cmtt-10"> Packet</span><span
- class="cmtt-10"> Filter</span><span
- class="cmtt-10"> Language.</span>
- <br class="fancyvrb" /><a
- id="x1-23026r13"></a><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class="cmtt-10"> </span><span
- class=…
Large files files are truncated, but you can click here to view the full file