char type 0 1 byte int type 0 4 bytesWe start with just the built-in names, at level 0.
int i;
char type 0 1 byte int type 0 4 bytes i var 1 1 intGlobal declarations are at level 1.
int count = 0;
char type 0 1 byte int type 0 4 bytes i var 1 1 int count var 1 2 int 0char * fred (char c, int i) {
char type 0 1 byte int type 0 4 bytes i param 2 2 int var 1 1 int count var 1 2 int 0 fred fun 1 ? char* c param 2 1 charDeclarations within functions are (initially) at level 2.
static int mark = 0;
char type 0 1 byte int type 0 4 bytes i param 2 2 int var 1 1 int count var 1 2 int 0 fred fun 1 ? char* c param 2 1 char mark var 2 1 static int 0char * result = (char *) malloc (i + 2);
char type 0 1 byte int type 0 4 bytes i param 2 2 int var 1 1 int count var 1 2 int 0 fred fun 1 ? char* c param 2 1 char mark var 2 1 static int 0 result var 2 2 char* malloc fun? 1? ? ?We don't have a declaration for malloc, so we have to try to construct something for it.
count += i;
At this point, for example, when we look up i, we find information
describing it as a parameter of fred, rather than a global variable.
Also, when we look up count, we discover that it is a variable,
so it can be assigned to, and it and i are integers, so we know what
sort of addition to perform.
{ int k;
char type 0 1 byte int type 0 4 bytes i param 2 2 int var 1 1 int count var 1 2 int 0 fred fun 1 ? char* c param 2 1 char mark var 2 1 static int 0 result var 2 2 char* malloc fun? 1? ? ? k var 3 1 intThe inner block starts a new level, level 3.
for (k = 0; k < i; k++) result [k] = c; }
char type 0 1 byte int type 0 4 bytes i param 2 2 int var 1 1 int count var 1 2 int 0 fred fun 1 ? char* c param 2 1 char mark var 2 1 static int 0 result var 2 2 char* malloc fun? 1? ? ? kAs we exit level 3, the variable k is no longer visible, so we detach the corresponding property from the namelist. However, we retain the namelist entry for k, as it may occur again lower down.
result [i++] = 0; result [i] = ++mark; return result; }
char type 0 1 byte int type 0 4 bytes i var 1 1 int count var 1 2 int 0 fred fun 1 ? char* param 2 1 char param 2 2 int c mark result malloc fun? 1? ? ? kAs we exit level 2, we discard the declarations made inside it (c, i, mark, result). In particular, we have to reconnect i to its original declaration as a global variable. We don't completely discard the entries for the parameters, as we need them to check calls to fred lower down.
int main (void) {
char type 0 1 byte int type 0 4 bytes i var 1 1 int count var 1 2 int 0 fred fun 1 ? char* param 2 1 char param 2 2 int c mark result malloc fun? 1? ? ? k main fun 1 ? intchar * string;
char type 0 1 byte int type 0 4 bytes i var 1 1 int count var 1 2 int 0 fred fun 1 ? char* param 2 1 char param 2 2 int c mark result malloc fun? 1? ? ? k main fun 1 ? int string var 2 1 char*i = 5;
At this point, for example, when we look up i, we find information describing it as a global variable, rather than a parameter of fred.
string = fred ('a', i); printf ("%s, %d, %d\n", string, string [i+1], count);
char type 0 1 byte int type 0 4 bytes i var 1 1 int count var 1 2 int 0 fred fun 1 ? char* param 2 1 char param 2 2 int c mark result malloc fun? 1? ? ? k main fun 1 ? int string var 2 1 char* printf fun? 1? ? ?string = fred ('b', i); printf ("%s, %d, %d\n", string, string [i+1], count); return 0; }
char type 0 1 byte int type 0 4 bytes i var 1 1 int count var 1 2 int 0 fred fun 1 ? char* param 2 1 char param 2 2 int c mark result malloc fun? 1? ? ? k main fun 1 ? int string printf fun? 1? ? ?