<?xml version='1.0'?>
<!DOCTYPE slides SYSTEM "file:///D:/xmltools/slides3/slides.dtd"
[

<!ENTITY slideinfotitle "The C Runtime System">
<!ENTITY % defaults SYSTEM "file:///D:/webpub/make/gendefs.xml">
%defaults;
<!ENTITY author "Walter Kriha">
]>
<slides>
<slidesinfo>
  <title>&slideinfotitle;</title>
		<authorblurb>
			<para>I have to say thanks to Jason Maasson from Frije Universiteit Amsterdam for his excellent script and slides. I've translated most of the slides and added some graphics and text.</para>
			<para>I would also like to thank Marshall Brain, founder of "www.howstuffworks.com"  for his wonderful article on "How C Programming Works" which explains also the c-runtime environment.</para>
			<para>And last but not least Steven Simpson from Lancaster University for pointing out the differences between both languages on a few excellent pages.</para>
		<para>Look at the resource section at the end for links.</para>		
		</authorblurb>
</slidesinfo>
	<foilgroup>
		<title>Introduction</title>
	<foil>
		<title>Goals</title>
		<orderedlist>
				<listitem>
					<para>A word on debugging and generating assembler code</para>
				</listitem>
			<listitem><para>learn how function calls work</para>
			</listitem>
			<listitem>
				<para>Learn what happens when a C program is executed </para>
			</listitem>
			<listitem><para>Understand memory management issues and performance problems</para>
			</listitem>
			<listitem><para>Frequent bugs and errors in C programs</para>
			</listitem>
		</orderedlist>
	</foil>
	<foil>
		<title>Roadmap</title>
		<orderedlist>
				<listitem>
					<para>How to create assembler code</para>
				</listitem>
			<listitem>
				<para>Assembler code for a funtion call</para>
			</listitem>
			<listitem>
				<para>How malloc works and when OS support is needed</para>
			</listitem>
			<listitem>
				<para>Purify to the rescue: when your program leaks memory</para>
			</listitem>			
      <listitem>
				<para>How the system call execve starts a C program</para>
			</listitem>
				<listitem>
					<para>How to debug your programs</para>
				</listitem>
		</orderedlist>
		</foil>
	</foilgroup>
	<foilgroup>
		<title>Assembler code</title>
		<foil>
			<title>Generating assembler code</title>
			<para>Sometimes when you are working on a device driver or some kernel functions - or just if you need to speed-up one small function in your program you might want to create the function in assembler code. Writing assembler is hard but you can let the C compiler do the hard stuff for you and then just optimize the result. Sometimes you might hit an optimizer bug which forces you to look at the generated code to see where the problem is - even compilers have bugs.</para>
			<programlisting>gcc -S fCall.c </programlisting>
			<para>produces assembler output.</para>
		</foil>
		<foil>
			<title>A C code example to demonstrate assembly language</title>
			<programlisting>
extern int myFunc(int intPar, char* stringPar);

int main(void) {
    char * string = "hello";  // a local string
    int result = 0;           // a local integer 
    int arg1 = 1;             // a local integer
    result = myFunc(arg1, string); // 2 parameter, 1 return parameter
    return 0;
}

int myFunc(int intPar, char* stringPar) {

    int localVar = intPar;        // parameter used to init local var.
    char* localString = stringPar; // same here
    return 44;                   // return value needs to go back to caller
}
</programlisting>
		</foil>
		<foil>
			<title>A word on assembler code</title>
			<para>The example below uses assembler code for intel type CPUs generated by the GNU assembler. Unlike most Intel assembler this tools moves things from the left side to the right side in an expression. Some things to know for reading the output:</para>
			<variablelist>
				<varlistentry>
					<term>.text</term>
					<listitem>
						<para>like .date or .bss this statement simply tells where the linker finally has to put the following code or data. In our case we will see that sometimes even data (e.g. a string "hello") might go into the non-writeable text segment.</para>
					</listitem>
				</varlistentry>
				<varlistentry>
					<term>.globl</term>
					<listitem>
						<para>A statement that makes stuff included here available for public access (linker can use it to resolve externals)</para>
					</listitem>
				</varlistentry>
				<varlistentry>
					<term>eax, ebx...</term>
					<listitem>
						<para>The register names of Intel CPUs. eax is really the workhorse of those CPUs (accumulator). As you can see a typical access goes like this: move something from stack into eax. Move it from eax somewhere else on the stack. This is also the way function parameters are accessed and assigned to local variables</para>
					</listitem>
				</varlistentry>
			</variablelist>
		</foil>
		<foil>
			<title>Assembler output listing</title>
			<para>My comments are tagged with the C comment characters.</para>
			<programlisting>
.file	"fCall.c"    // the original source file
.def	___main;	.scl	2;	.type	32;	.endef
.text              // this goes into the text segment
LC0:                 // a gnerated label to store the string value
.ascii "hello\0"   // note that the string goes into TEXT segment!
.align 2           // tells linker to align this section on a two byte border
.globl _main         // puts our main in the .global section
.def	_main;	.scl	2;	.type	32;	.endef
_main:               // this is where our main really starts
pushl	%ebp           // save frame (base) pointer on stack
movl	%esp, %ebp     // store stackpointer in framepointer
subl	$24, %esp      // decrement stack pointer to make room 
                     // for main's local variables and future call arguments
andl	$-16, %esp   
movl	$0, %eax       // put 0 into eax register
movl	%eax, -16(%ebp) // move content of eax to where framepointer points 
                      // but with offset -16 
movl	-16(%ebp), %eax // get framepointer offset -16 into eax ???
call	__alloca       // call a c-runtime function to allocate memory
call	___main        // call a c-runtime function __main
                      
movl	$LC0, -4(%ebp) // get the address of LC0 (our string) and put it to 
                     // framepointer -4 on the stack. This is not surprisingly
                     // where our first local variable "string" lives.
movl	$0, -8(%ebp)   // put a 8 at framepointer -8 where our second var lives 
                     // (result)
movl	$1, -12(%ebp)  // put 1 at framepointer -12 where our third var (arg1)lives
movl	-12(%ebp), %eax// move arg1 from stack into register eax
movl	%eax, (%esp)   // put eax content on stack. Note, this is the leftmost 
                     // argument for function call!!!
movl	-4(%ebp), %eax // put the string address from stack into eax
movl	%eax, 4(%esp)  // and put it from there onto the stack
                     // now we have set up the stack with two arguments and can 
                     // call our function. 
                     // You will need to look at _myFunc to see how the arguments
                     // are processed by our function.
call	_myFunc        // tell CPU to push the current instruction address on the 
                     // stack (saving it for return) and move the address where  
                     // _myFunc lives into the instruction register
//----------------------------------------------------
// after we come back from the call to _myFunc:
movl	%eax, -8(%ebp) // in eax is the return value from our function call
                     // with a debugger you would find 44 here
movl	$0, %eax       // generate main's return value (0 for everything OK)
leave                // restore framepointer and stackpointer to how they
                     // where BEFORE main function was running
ret                  // tell CPU to get return address (the address from where 
                     // our main was called) and jump to it, effectively continuing 
                     // callers processing right after the function call to main.
                     // in this case this would mean jumping back into the
                     // C-runtime code which started our program.
//-----------------------------------------------------
.align 2
.globl _myFunc
.def	_myFunc;	.scl	2;	.type	32;	.endef
myFunc:
pushl	%ebp           //save framepointer from caller (prolog)
movl	%esp, %ebp     // put stackpointer into framepointer which
                     // is now our vehicle to access OUR (myFunc's) local
                     // variables and arguments
subl	$8, %esp       // make room on stack for 8 bytes
movl	8(%ebp), %eax  // move 4 bytes from framepointer offset 8 into eax register
movl	%eax, -4(%ebp) // move those bytes now into local variable at offset -4 
                     // what does: int localVar = intPar;    
movl	12(%ebp), %eax // again move 4 bytes from offset 12 into eax 
movl	%eax, -8(%ebp) // and store them at offset -8 which makes:
                    //     char* localString = stringPar;
movl	$44, %eax     // put decimal 44 into register eax which
                    // creates our RETURN value (must be in eax as we 
                    // will see when we look at how the caller receives this
                    // value: return 44;
leave               // clean up the local calling frame (restore framepointer and
                    // stack pointer to HOW THE CALLER LEFT THEM. Any surprise here 
                    // is not really funny.
ret                 // tells the cpu to take the callers return address from stack
                    // into the instruction pointer register and continue executing
<!-- .def	_myFunc;	.scl	2;	.type	32;	.endef  -->
</programlisting>
		</foil>
	</foilgroup>
	<foilgroup>
		<title>How function calls work</title>
		<foil>
			<title>Why is this assembler stuff important?</title>
			<para>A close look at how a function call really works will teach you several things:</para>
			<variablelist>
				<varlistentry>
					<term>Call by Reference vs. call by Value</term>
					<listitem>
						<para>Look at the function arguments arg1 (an integer) and string (a character pointer). The value from the integer is COPIED onto the stack and received as a value from myFunc. At NO time does myFunc access the memory where arg1 really lives on the stack because this stack area belongs to the main function. myFunc works on a COPY of the integer. But now look at the string variable. It is NOT copied onto the stack. Instead, the MEMORY ADDRESS where the string lives is COPIED with the following instruction onto the stack: 	movl	$LC0, -4(%ebp). If the receiving function myFunc would do anything with the string parameter it would go DIRECTLY to where the string lives - leaving its own memory area. </para>
					</listitem>
				</varlistentry>
				<varlistentry>
					<term>Speed and Pointers</term>
					<listitem>
						<para>The string from above is a pointer and you have seen it is transported by reference (effectively only its address is copied, not the whole string). This is of course much faster than performing a whole string copy operation across the stack. But it also shows the danger of pointers (or references in general). There are now 2 places which can access the string: main and myFunc. Main cannot prevent myFunc from abusing its variable string through the pointer (not true because of the text segment here but if string would not be a literal it would be true).</para>
					</listitem>
				</varlistentry>
				<varlistentry>
					<term>Remote Procedure Calls</term>
					<listitem>
						<para>In distributed systems we will see how this fast function call mechanism is broken up into 2 parts on different machines. We will call the callers part a "stub" and the receiving functions part a "skeleton" and complicated middleware will move the parameters back and forth. And this will be NOT AT ALL FAST because it involves a lot of networking.</para>
					</listitem>
				</varlistentry>
				<varlistentry>
					<term>Buffer Overflows</term>
					<listitem>
						<para>Most security attacks involve buffer overflows on the stack. To really understand how those attacks work you need to understand the stack mechanism, especially the return from a function call where an address from the stack becomes the new instruction pointer. If the stack is overwritten with buffer overflow code, an attacker can point the program at return right to its own virus code.</para>
					</listitem>
				</varlistentry>
			</variablelist>
		</foil>
		<foil>
			<title>C Function Calling Convention</title>
			<mediaobject>
				<imageobject>
					<imagedata depth="12cm" align="center" fileref="pictures/ccallingconvention.PNG" format="PNG"/>
				</imageobject>
			</mediaobject>
		</foil>
		<foil>
			<title>C stack layout</title>
			<mediaobject>
				<imageobject>
					<imagedata depth="12cm" align="center" fileref="pictures/stacklayout.PNG" format="PNG"/>
				</imageobject>
			</mediaobject>
		</foil>
	</foilgroup>
	<foilgroup>
		<title>Debugging</title>
		<foil>
			<title>Program crashes and core files</title>
			<para>On Unix platforms if a program crashes a so called "core file" is created. It contains the memory status of the program when it crashed. This information can be used for post-mortem debugging using a debugger like gdb. </para>
			<para>For best debugging results a program needs to be compiled with debugging turned on. This creates additional debugging instructions in the object code of the program and preserves all symbol and line information. This allows a debugger to show the proper source code pieces.</para>
			<para> <systemitem> man gcc </systemitem> lists a large number of debugging and optimization options. Some compilers do not allow mixing debugging and optimization.</para>
		</foil>
	</foilgroup>
	<foilgroup>
		<title>Pointer Arithmetics</title>
		<para>Pointer arithmetic is frequently used in C programs which means that a C programmer must know how to do this. The basic concept is that a pointer variable (which contains the address of some piece of memory) can be modified by the programmer. Here really shows that pointers are special types because incrementing a pointer can give some surprising results.</para>
		<programlisting>
int k= 3;
int* ptr = &amp;k;  // ptr now contains the address of k
ptr++;  // incrementing the pointer makes it point to 
        // address of k PLUS 4 byte. 
</programlisting>
		<para>The reason for this is that pointer arithmetic calculates with the SIZE OF THE TYPE the pointer is pointing to. The formula is: <systemitem> pointer + x == ptr + (x * sizeof(pointerType) </systemitem> </para>
		<foil>
			<title>Memory layout and pointer arithmetics</title>
			<mediaobject>
				<imageobject>
					<imagedata depth="12cm" align="center" fileref="cpointerarithmetics.PNG" format="PNG"/>
				</imageobject>
			</mediaobject>
		</foil>
		<foil>
			<title>Pointers and Arrays revisited</title>
			<programlisting>
#include &lt;stdio.h&gt;
int main(void) {
 int* ptr;
 int my_array[] = {11,22,33,44};
 ptr = &amp;my_array[0];
 for (i=0;i&lt;4;i++) {
  printf("my_array[%d] = %d   ", i, my_array[i]);
  printf("ptr + %d  = %d\n", i, (*ptr+1));
 }
 return 0;
}
</programlisting>
<programlisting>
my_array[0] = 11  ptr + 0 = 11;
my_array[1] = 22  ptr + 4 = 22;
my_array[2] = 33  ptr + 8 = 33;
my_array[3] = 44  ptr + 12 = 44;
</programlisting>
			<para>This shows the following facts about pointers and arrays:</para>
			<orderedlist>
				<listitem>
					<para>The address of an array at element 0 (&amp;my_array[0]) is the same as the array name.</para>
				</listitem>
				<listitem>
					<para>The following statements are therefore equivalent: <systemitem> ptr = &amp;my_array[0]; and ptr = my_array;</systemitem>.</para>
				</listitem>
				<listitem>
					<para>An array is a pointer to the first element of the array.</para>
				</listitem>
				<listitem>
					<para>But an array cannot be re-assigned like a pointer. While my_array == ptr the following code does not work:</para>
					<programlisting>
int my_array[5];
int* prt;
ptr = my_array;
my_array = ptr; // ERROR: an array is NOT an lvalue 
</programlisting>
				</listitem>
			</orderedlist>
		</foil>
		<foil>
			<title>Strings revisited</title>
			<para>A string is an array of characters and therefore also a pointer of type pointer to character.</para>
			<programlisting>
char myArray[] = {'a', 'b', 'c'};
char c = my_array[1];  // gives b
c = *(my_array + 1);   // gives b

int i;
for (i=0; i%lt; 3;i++) {
  printf("%c", *my_array++;)
  }  // prints "abc"
</programlisting>
		</foil>
	</foilgroup>
	<foilgroup>
		<title>Dynamic memory allocation</title>
		<para>Almost every application needs to allocate memory dynamically. The data segment of an application does NOT grow. All variables there have been allocated at compiletime and the sizes are fixed. The area where the application gets dynamic memory is called heap. The heap starts at the end of the data segment and grows against the bottom of the stack. If both meet your program is in trouble and will be terminated by the operating system.</para>
		<note>
			<para>Allocation of dynamic memory is THE area of application programming with the largest potential for bugs or very slow performance. At least the performance problem does also exist in languages with garbage collection.</para>
		</note>
			<para>Here is how dynamic memory allocation in C works: <systemitem> void *malloc(size_t size) </systemitem> allocates memory. Please check the return value for not being "null". A null indicates that the system is out of memory. And <systemitem> void free(void *ptr) </systemitem> gives the memory back to the pool.</para>
		<foil>
			<title>Program Memory Areas</title>
			<mediaobject>
				<imageobject>
					<imagedata depth="12cm" align="center" fileref="pictures/memoryareas.PNG" format="PNG"/>
				</imageobject>
			</mediaobject>
		</foil>
		<foil>
			<title>How malloc and free work</title>
			<para>Some steps from a typical malloc call will show you how much work is performed here:</para>
			<orderedlist>
				<listitem>
					<para>A program does request memory from the heap with <systemitem> int* ptr = (int*) malloc(1024 * sizeof(int)); </systemitem>. It expects a pointer back which points to a newly allocated areas on the heap which is at least big enough to hold 1024 integer values, no matter how big an integer on this platform is. If the program would ask for (1024 * 2) bytes it would assume 16 bit integer values and would not be portable to other hardware. </para>
				</listitem>
				<listitem>The malloc function is part of the C runtime library. It will now check the current status of free memory on the heap. It needs to find a piece of memory big enough for 1024 integers. Once it finds it, it will be returned to the application. What could be simpler?
				</listitem>
				<listitem>
					<para>The reason for malloc being a very expensive call has many facets. First, finding the proper area needs a clever memory organisation by malloc so that it will find those pieces fast. Remember, malloc does not know how much memory will be request. Could  be one byte, could be thousands. The next problem appears when the current heap size becomes too small. Now malloc must ask the Operating System for more heap space, using a <systemitem> brk or sbrk </systemitem> system call. Now the operating system allocates physical memory and maps it into the process address space which belongs to the heap. Frequent allocations are expensive if done in small sizes, but how should malloc know?</para>. And last but not least when the memory is returned malloc has to try to reduce fragmentation of memory space. Otherwise it will not find a piece of memory big enough to satisfy a request even though enough small pieces would be available. A lot of list processing.
				</listitem>
				<listitem>
					<para>Just to top it off: If this is a multi-threaded program chances are that malloc needs to protect its heap data structures from being corrupted by threads trying to allocate memory in parallel. This means expensive semaphore and monitor operations.</para>
				</listitem>
			</orderedlist>
		</foil>
		<foil>
			<title>Rules of thumb for application programmers in need of dynamic memory</title>
			<orderedlist>
				<listitem>
					<para>Malloc is generic and good. Many small allocations will work but they will slow your application down.</para>
				</listitem>
				<listitem>
					<para>It may be better if the application allocates a large chunk of heap and maintains it by itself. It knows best what kind of allocations will happen. Try to avoid frequent small allocations via malloc.</para>
				</listitem>
				<listitem>
					<para>Do not give memory back just to allocate it a few milliseconds later again. Keep your own memory pool and REUSE memory as much as possible. Caching and pooling is the name of the game for successful applications.</para>
				</listitem>
				<listitem>
					<para>In languages without garbage collection: Define your own memory management policy and design a coding standard with function names that make it clear when somebody takes over responsibility for a piece of memory. </para>
					<programlisting>
char* value = getSomething(); // does the function expect the caller to call free?
                      // is the memory area a constant and the program
                      // will crash if free(value) is called?
                      // if value will be a parameter to another call, who
                      // will take over responsibility for free-ing it?</programlisting>
				</listitem>
				<listitem>Even if you have done all this, get yourself a memory leak checker like purify which detects leaks AND overwritten memory. Leaks just slow your application down as we will see in the session on memory management. Overwritten memory is memory that got a new owner while the old one still has a reference and uses it. Or it is memory that is written beyond its boundary (like arrays).
				</listitem>
			</orderedlist>
		</foil>
		<foil>
			<title>Example of Memory Leak</title>
			<programlisting>
#include &lt;stdio.h&gt;

int* create(int size) {
  return (int* malloc(size*sizeof(int));
}

int main(void) {
  int *arr = create(10);
  // do something useful with memory
  // e.g. maintain a dynamic list
  // free(arr); // this will cause a LEAK
  return 0;
}</programlisting>
			<para>This may look like stupid programming but it is actually very hard to maintain pairwise allocation/deallocation if both can happen in functions that are far away from each other in the software package.</para>
		</foil>
		<foil>
			<title>Implementing a dynamic list with malloc</title>
			<programlisting>
#include &lt;stdio.h&gt;
struct node {
    int i;
    struct node *next;
};
int main(void) {
 struct node* temp, *list = NULL;
 for(i=0;i&lt;10;i++) {
  temp = (struct node *) malloc(sizeof(struct list));
  temp-&gt;i = i;
  temp-&gt;next = list;
  list = temp;
 }
  // do something with list and free nodes later
  return 0;
}</programlisting>
			<para>This is extremely common code in C programs. Freeing the list is easy because all nodes are hanging together via the next pointer.</para>
		</foil>
		<foil>
			<title>C vs. Java Memory Management</title>
			<para>At the first glance Java seems to solve many of the problems related to dynamic memory management in C. The garbage collector automatically collects objects which are no longer reachable.</para>
			<programlisting>
public Class Foo {
 public int i;
 public String bar;

void someMethod() {
   Class Foo fooObject = new Foo(); // allocates a Foo object on heap
  } // and now the fooObject IS NO LONGER REACHABLE
    // It will be collected at some future time and
    // returned to the heap. 
}
Foo someOtherMethod() {
   Class Foo fooObject = new Foo(); 
   return fooObject;// allocates a Foo object on heap
  } // fooObject is STILL reachable from the caller which 
    // gets the reference to it as a return value 
}</programlisting>
		</foil>
		<foil>
			<title>Things to know about Java Memory Management</title>
			<variablelist>
				<varlistentry>
					<term>stack vs. heap</term>
					<listitem>
						<para>ALL java object (except primitive types) are allocated on the HEAP. Creating a Class Foo instance means to allocate the 8 bytes for a Class Foo object from above (assuming that the VM uses 4 bytes to represent an integer and 4 bytes to represent a String reference. "Newing many small objects is exactly what we said is very bad for dynamic memory management. So don't think just because your objects are small allocating them costs nothing...</para>
					</listitem>
				</varlistentry>
				<varlistentry>
					<term>malloc vs. new</term>
					<listitem>
						<para>As a matter of fact, malloc is probably used to allocate the 8 bytes for a Class Foo object from above (assuming that the VM uses 4 bytes to represent an integer and 4 bytes to represent a String reference. You know now that malloc is expensive and so is new...</para>
					</listitem>
				</varlistentry>
				<varlistentry>
					<term>Garbage Collection vs. self-managed memory</term>
					<listitem>
						<para>There is ABSOLUTELY no doubt that garbage collection is superior for application programming. But this does not mean that it is free or that you can't have memory leaks with a GC. And the type of GC will impact your performance dramatically. (Compare a generational GC with an non-generational GC in the context of large caches for web applicationsl...) We will discuss this in depth in our Virtual Machine session. Frequent bugs with GCs are: Forgetting static variables which hold references to large objects which reference large objects and so on... Or calling system functions which keep references to user objects without telling about: Have a look at Java ThreadGroups...</para>
						<para>So event with Java, get a memory leak checker which will also tell you if your singletons are no singletons or how long method calls really take. Be ready for some surprises...</para>
					</listitem>
				</varlistentry>
			</variablelist>
		</foil>
	</foilgroup>
	<foilgroup>
		<title>Resources</title>
		<para>The resources cover freely available information as well as excellent books right to the topic. All entries are commented to let you know what a paper or book is all about. I also expect participants to use this literature in case of questions.</para>
		<foil>
			<title>Open Source Information on C programming</title>
			<para>The following information is freely available and taken together is an excellent introduction to the subject.</para>
			<orderedlist>
				<listitem>
					<para>Jason Maassen, C for Java Programmers. A complete introduction to C for Java people. I have used and extended his slides for this lecture but you should read the background information here as well.60+ pages. Good if you need to prepare for a test or need some more information about a feature from my slides. Find his C course with other materials here: <ulink url="http://www.cs.vu.nl/~jason/course.html"> http://www.cs.vu.nl/~jason/course.html </ulink>.</para>
				</listitem>
				<listitem>
					<para>Steven Simpson, Learning C from Java. An experienced Java programmer will get the most from this short paper focussing on the differences. Excellent. <ulink url="http://www.comp.lancs.ac.uk/computing/users/ss/java2c/diffs.html"> http://www.comp.lancs.ac.uk/computing/users/ss/java2c/diffs.htm </ulink>.</para>
				</listitem>
				<listitem>
					<para>Marshal Brain, How C programming works. Another excellent paper from www.howstuffworks.com. This really explains complicated memory problems using pointers, how array overwriting can happen etc. And many useful pointers to other computing related topics like memory organization, operating systems etc. www.howstuffworks.com </para>
				</listitem>
			</orderedlist>
		</foil>
		<foil>
			<title>Books</title>
			<para>I always try to have all recommended books available in our library. Also take a look at my special section there where I collect books which should be present at all times.</para>
			<orderedlist>
				<listitem>
					<para>Kernighan/Ritchie, Programming in C. The bible of c-programming from the inventors. A classic text. Very short- compare this to nowadays documentation bloat.</para>
				</listitem>
				<listitem>
					<para>The C pocket reference. A short book covering the latest developments in C. In my library.</para>
				</listitem>
				<listitem>
					<para>The C Puzzle Book. Alan R. Feuer. A very short and nice book full of examples with C.  </para>
				</listitem>
			</orderedlist>

		</foil>
	</foilgroup>

</slides>
