L
Lionel
Let me start by apologizing for the sample code
that I use later in this message. It has been
over 15 years since I've written 'C' code that
could be viewed by anyone other than myself. I
have had it pointed out to me by 'C' language
"purists" that this code could certainly stand
to be improved.
Let me also add a little side note about development
tools. Like many of you, over the years I have
gathered some useful programming utilities that make
my life easier. One of my favorite is a tool I wrote
a long time ago that searches source code files for
specific text and then inserts additional code either
before or after the search text. This permits me
to add source code, for unit testing purposes, that
will NOT be included in the final program. It also
allows for conditional compiles without all the
#if...#endif statements. The code listed below has
statements ending with "// DEBUG" that can be removed,
as a whole, without affecting the application.
IMHO...
A well-written program is a hierarchy of function
calls starting and ending from a single function (in
'C', it's 'main').
Historically, one of my most time-consuming challenges
is learning the flow of a program. There is usually
no development documentation that describes this flow
and I resort to reading through the application's
source code. Typically I am asked to do this in order
to fix a bug. The problem is, I can't know what's
going _wrong_ until I know how it's supposed to be
done _right_.
Enter XML. XML is primarily used to communicate data.
Because of it's flexibility, I hope to demonstrate how
it can also be used to map out program flow. After
executing the following program, an XML file is created
(debug.xml) that shows which functions are being called
and in which order. Data values are also printed out
from within the functions that use them. If the program
has a bug, as my example program has in the "fourth(int)"
method below, the XML will not be well-formed when the
program executes that method. The resulting XML then
becomes a debugging 'trace' file showing where execution
has stopped.
My hope is that you will find this concept useful and
will tell your friends and co-workers. As a Software
Architect, I am often asked to examine a system and to
determine how it can be improved. By having an XML file
that shows program flow I can easily talk to programmers
and non-programmers while using the same tool. Adding
the output XML source code is a simple task and if done
with a development utility as described above, can be
easily removed from the final code.
I am aware that this concept is an extension of the
age old primative "printf without XML" debugging
process, but I think adding XML to the mix has added
a new twist. With XML as the output, collapsing
whole sections of program flow information is easily
done. This also makes it easy to see, without
having to walk through a debugger session and keep
the flow in your head or scribbled down on a piece
of paper, what the high-level flow will look like.
By incorporating XML tags around output data values,
it is also possible to keep track of how and when
data values are getting changed.
SAMPLE CODE:
===================================================
#include <stdio.h>
#include <stdlib.h>
FILE* fp; // DEBUG
void first();
void second(int);
int third(int);
int fourth(int);
void first()
{
fprintf(fp, "<first>\n"); // DEBUG
printf("No parameters, so 'X' is equal to 1.\n");
fprintf(fp, "</first>\n"); // DEBUG
return;
} // end first()
void second(int x)
{
fprintf(fp, "<second>\n"); // DEBUG
fprintf(fp, "<X>%i</X>\n", x); // DEBUG
int y = 0;
if (x <= 5)
{
printf("'X' is less than or equal to 5. You're doing good.\n");
}
else
{
printf("'X' is greater than 5. Moving on.\n");
y = third(x);
}
fprintf(fp, "</second>\n"); // DEBUG
return;
} // end second(int)
int third(int x)
{
fprintf(fp, "<third>\n"); // DEBUG
fprintf(fp, "<X>%i</X>\n", x); // DEBUG
int y = x;
if (x < 10)
{
printf("Phew!!! You just made it!\n");
}
else
{
printf("'X' is greater or equal to 10. Moving on.\n");
y = fourth(x);
}
fprintf(fp, "</third>\n"); // DEBUG
return y;
} // end third(int)
int fourth(int x)
{
fprintf(fp, "<fourth>\n"); // DEBUG
fprintf(fp, "<X>%i</X>\n", x); // DEBUG
printf("Trouble here. Time to call it a day.\n");
exit(-1);
fprintf(fp, "</fourth>\n"); // DEBUG
return x;
} // end fourth(int)
int main(int argc, char* argv[])
{
if ((fp = fopen("debug.xml", "w")) == NULL) // DEBUG
{ // DEBUG
printf("Cannot open debug file.\n"); // DEBUG
return 1; // DEBUG
} // DEBUG
fprintf(fp, "<?xml version=\"1.0\" ?>\n"); // DEBUG
fprintf(fp, "<foo_main>\n"); // DEBUG
int x = 0;
// Start the show...
if (1 == argv)
{
first();
x = 1;
}
else
{
x = atoi(argc[1]);
}
second(x);
fprintf(fp, "</foo_main>\n"); // DEBUG
if (fp) fclose(fp); // DEBUG
return 0;
} // end main()
===================================================
After compiling this code, you will get the following
results in the XML file (debug.xml):
No command-line parameters:
Method 'first()' gets called and then method 'second(int)'.
Parameter less than or equal to '5':
Method 'second(int)' gets called.
Parameter greater than '5' but less than '10':
Methods 'second(int)' and 'third(int)' get called.
Parameter greater than or equal to '10':
Methods 'second(int)', 'third(int)' and 'fourth(int)' get called.
Method 'fourth(int)' has an 'exit' statement that forces
premature program termination. Entering a command-line
parameter that is '10' or greater will create a malformed
XML document that can be viewed in your favorite text
editor. All other parameters values produce a valid XML
file that shows program flow.
I will also include three XML files here for those of
you who don't want to go through the trouble of compiling
and executing the code.
================= No Parameters ===================
<?xml version="1.0" ?>
<foo_main>
<first>
</first>
<second>
<X>1</X>
</second>
</foo_main>
===================================================
================= Parmeter = '6' ==================
<?xml version="1.0" ?>
<foo_main>
<second>
<X>6</X>
<third>
<X>6</X>
</third>
</second>
</foo_main>
===================================================
================= Parmeter = '10' =================
<?xml version="1.0" ?>
<foo_main>
<second>
<X>10</X>
<third>
<X>10</X>
<fourth>
<X>10</X>
===================================================
Who knows, maybe some day you'll be required to take
over the maintanence of an application that has
thousands of lines of code and you'll be handed an
XML file that shows you the program flow and data
values in a clean and concise manner.
Thank you.
P.S. - I apologize for the length of this message.
Lionel
lrogers42"AT"yahoo.com
that I use later in this message. It has been
over 15 years since I've written 'C' code that
could be viewed by anyone other than myself. I
have had it pointed out to me by 'C' language
"purists" that this code could certainly stand
to be improved.
Let me also add a little side note about development
tools. Like many of you, over the years I have
gathered some useful programming utilities that make
my life easier. One of my favorite is a tool I wrote
a long time ago that searches source code files for
specific text and then inserts additional code either
before or after the search text. This permits me
to add source code, for unit testing purposes, that
will NOT be included in the final program. It also
allows for conditional compiles without all the
#if...#endif statements. The code listed below has
statements ending with "// DEBUG" that can be removed,
as a whole, without affecting the application.
IMHO...
A well-written program is a hierarchy of function
calls starting and ending from a single function (in
'C', it's 'main').
Historically, one of my most time-consuming challenges
is learning the flow of a program. There is usually
no development documentation that describes this flow
and I resort to reading through the application's
source code. Typically I am asked to do this in order
to fix a bug. The problem is, I can't know what's
going _wrong_ until I know how it's supposed to be
done _right_.
Enter XML. XML is primarily used to communicate data.
Because of it's flexibility, I hope to demonstrate how
it can also be used to map out program flow. After
executing the following program, an XML file is created
(debug.xml) that shows which functions are being called
and in which order. Data values are also printed out
from within the functions that use them. If the program
has a bug, as my example program has in the "fourth(int)"
method below, the XML will not be well-formed when the
program executes that method. The resulting XML then
becomes a debugging 'trace' file showing where execution
has stopped.
My hope is that you will find this concept useful and
will tell your friends and co-workers. As a Software
Architect, I am often asked to examine a system and to
determine how it can be improved. By having an XML file
that shows program flow I can easily talk to programmers
and non-programmers while using the same tool. Adding
the output XML source code is a simple task and if done
with a development utility as described above, can be
easily removed from the final code.
I am aware that this concept is an extension of the
age old primative "printf without XML" debugging
process, but I think adding XML to the mix has added
a new twist. With XML as the output, collapsing
whole sections of program flow information is easily
done. This also makes it easy to see, without
having to walk through a debugger session and keep
the flow in your head or scribbled down on a piece
of paper, what the high-level flow will look like.
By incorporating XML tags around output data values,
it is also possible to keep track of how and when
data values are getting changed.
SAMPLE CODE:
===================================================
#include <stdio.h>
#include <stdlib.h>
FILE* fp; // DEBUG
void first();
void second(int);
int third(int);
int fourth(int);
void first()
{
fprintf(fp, "<first>\n"); // DEBUG
printf("No parameters, so 'X' is equal to 1.\n");
fprintf(fp, "</first>\n"); // DEBUG
return;
} // end first()
void second(int x)
{
fprintf(fp, "<second>\n"); // DEBUG
fprintf(fp, "<X>%i</X>\n", x); // DEBUG
int y = 0;
if (x <= 5)
{
printf("'X' is less than or equal to 5. You're doing good.\n");
}
else
{
printf("'X' is greater than 5. Moving on.\n");
y = third(x);
}
fprintf(fp, "</second>\n"); // DEBUG
return;
} // end second(int)
int third(int x)
{
fprintf(fp, "<third>\n"); // DEBUG
fprintf(fp, "<X>%i</X>\n", x); // DEBUG
int y = x;
if (x < 10)
{
printf("Phew!!! You just made it!\n");
}
else
{
printf("'X' is greater or equal to 10. Moving on.\n");
y = fourth(x);
}
fprintf(fp, "</third>\n"); // DEBUG
return y;
} // end third(int)
int fourth(int x)
{
fprintf(fp, "<fourth>\n"); // DEBUG
fprintf(fp, "<X>%i</X>\n", x); // DEBUG
printf("Trouble here. Time to call it a day.\n");
exit(-1);
fprintf(fp, "</fourth>\n"); // DEBUG
return x;
} // end fourth(int)
int main(int argc, char* argv[])
{
if ((fp = fopen("debug.xml", "w")) == NULL) // DEBUG
{ // DEBUG
printf("Cannot open debug file.\n"); // DEBUG
return 1; // DEBUG
} // DEBUG
fprintf(fp, "<?xml version=\"1.0\" ?>\n"); // DEBUG
fprintf(fp, "<foo_main>\n"); // DEBUG
int x = 0;
// Start the show...
if (1 == argv)
{
first();
x = 1;
}
else
{
x = atoi(argc[1]);
}
second(x);
fprintf(fp, "</foo_main>\n"); // DEBUG
if (fp) fclose(fp); // DEBUG
return 0;
} // end main()
===================================================
After compiling this code, you will get the following
results in the XML file (debug.xml):
No command-line parameters:
Method 'first()' gets called and then method 'second(int)'.
Parameter less than or equal to '5':
Method 'second(int)' gets called.
Parameter greater than '5' but less than '10':
Methods 'second(int)' and 'third(int)' get called.
Parameter greater than or equal to '10':
Methods 'second(int)', 'third(int)' and 'fourth(int)' get called.
Method 'fourth(int)' has an 'exit' statement that forces
premature program termination. Entering a command-line
parameter that is '10' or greater will create a malformed
XML document that can be viewed in your favorite text
editor. All other parameters values produce a valid XML
file that shows program flow.
I will also include three XML files here for those of
you who don't want to go through the trouble of compiling
and executing the code.
================= No Parameters ===================
<?xml version="1.0" ?>
<foo_main>
<first>
</first>
<second>
<X>1</X>
</second>
</foo_main>
===================================================
================= Parmeter = '6' ==================
<?xml version="1.0" ?>
<foo_main>
<second>
<X>6</X>
<third>
<X>6</X>
</third>
</second>
</foo_main>
===================================================
================= Parmeter = '10' =================
<?xml version="1.0" ?>
<foo_main>
<second>
<X>10</X>
<third>
<X>10</X>
<fourth>
<X>10</X>
===================================================
Who knows, maybe some day you'll be required to take
over the maintanence of an application that has
thousands of lines of code and you'll be handed an
XML file that shows you the program flow and data
values in a clean and concise manner.
Thank you.
P.S. - I apologize for the length of this message.
Lionel
lrogers42"AT"yahoo.com