By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,463 Members | 1,623 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,463 IT Pros & Developers. It's quick & easy.

A new use for XML

P: n/a
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.

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 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 (eXtensible Markup Language) 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.

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 argv, char* argc[])
{
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.

Note: If you don't have an XML document viewer, simply open the well
formed XML files in IE.

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.

Lionel
lrogers42"AT"yahoo.com

Nov 15 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a

Lionel wrote:
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 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.


Tis is a pretty bold statement. In my experience it is never a good
idea to trust testing done on anything byt actual release code. If you
test one thing and release something else that you never tested you
can't be sure that some unexpected results won't occur.

I also think this approach is not really anything different than using
printf without XML. What is it you feel the XML adds to this that I
could not achieve just by printing text to a file? I agree that you can
easily trace a path of execution but what does that have to do with the
fact that you are using XML?

Nov 15 '05 #2

P: n/a
G> In my experience it is never a good idea to trust
G> testing done on anything byt actual release code.

Agreed! Any release testing should only occur against
the code that is going to be part of the release. I'm
sorry if I led you to believe any different. When I
said, "This permits me to add source code, for testing
purposes, that will NOT be included in the final program.",
I only meant that this process could be used, as other
debugging processes are used (like #if statements), in
the initial "unit testing" phase.

Debugging and documentation, however, is another matter.
You're idea of using "printf without XML" is closer to
the mark. Conditional debug logging is an old trick.
I'm just adding a new twist to it.

G> What is it you feel the XML adds to this...

Regular printf statements don't complain if an opening
tag is not followed by a closing tag (see my example
that shows what happens when the method "fourth(int)"
is executed). If you try to view the resulting XML
file in IE, the browser lets you know that there is a
problem.

Regular printf statements can't be "hidden" by collapsing
elements. Some XML document viewers even indent nested
elements. View the first two XML files in IE if you
have a chance. You will see when siblings methods
(methods that are executed from within the same parent
method) are indented to the same degree.

Beyond these, XML is "structured" text. If you include
time values immediately after entering a method and just
before leaving that same method, it is a easy step to
pull these elements from the XML document into a graphing
application. Regular text would have to be parsed first
to produce the same result.

Lionel
lrogers42"AT"yahoo.com

Nov 15 '05 #3

P: n/a
Lionel wrote:

void first();
This declares first() as taking any number of parameters; it would
be better to write:

void first(void);
void first()
{
return;
Useless return statement.
} // end first()
Comments starting "//" are illegal in ANSI C.
exit(-1);
-1 is a poor value to pass to exit() , as it is unclear what
will come out on the other end when the calling environment
tries to examine it.
int main(int argv, char* argc[])
Traditionally it is (int argc, char *argv[]).
The 'c' stands for "count", and the 'v' for "vector".
{
if ((fp = fopen("debug.xml", "w")) == NULL) // DEBUG
{ // DEBUG
printf("Cannot open debug file.\n"); // DEBUG
return 1; // DEBUG
In VMS, 1 indicates success. Try:
return EXIT_FAILURE:
} // 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]);
atoi() causes undefined behaviour in some cases, eg. if the
string is a number that's too large to fit in an int.
Use strtol() instead.
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
Sounds like a great reason to not output XML ...
All other parameters values produce a valid XML file that shows
program flow.
Well, that's nice.

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. :-)


Usually, if the programmer can be bothered to document program
flow, then the code is quite maintainable anyway.

What I'd like to see is a tool that can generate this information
without us having to uglify the source code. Either a compiler
option, or some sort of preprocessor.

Nov 15 '05 #4

P: n/a
"Old Wolf" <ol*****@inspire.net.nz> writes:
Lionel wrote:

[snip]
} // end first()


Comments starting "//" are illegal in ANSI C.


<ANNOYINGLY_PEDANTIC>
Yes, if by ANSI C you mean the 1989 ANSI standard (which is how most
people use the term), but the 1999 ISO standard *is* the ANSI
standard.
</ANNOYINGLY_PEDANTIC>

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #5

P: n/a
OW> ...it would be better to write:...

It's a good thing I apologized for my poorly written
'C' code at the start of my message. :-)
snip snip snip


All-in-all, not bad for someone who mainly writes
in Java and C#. I have noted your comments and will
not make the same mistakes in the future.

OW> Well, that's nice.

A luke-warm response, but a whole lot better than
"this is a bunch of crap".

OW> ...without us having to uglify the source code.

I agree! BTW, that is one of the reasons I suggested
removing the "ugly" debug statements from the final
code. Who knows, if this is found to be useful, maybe
some of the compiler producers will include it in
with their next version. :-)

Thank you for taking the time to respond.

Lionel
lrogers42"AT"yahoo.com

Nov 15 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.