Monday, June 25, 2007
Saturday, June 23, 2007
Why do a lot of #defines in the Linux kernel use do { ... } while(0)?
- Empty statements give a warning from the compiler so this is why you see #define FOO do { } while(0).
- It gives you a basic block in which to declare local variables.
- It allows you to use more complex macros in conditional code. Imagine a macro of several lines of code like:
#define FOO(x) \
printf("arg is %s\n", x); \
do_something_useful(x);
Now imagine using it like:
if (blah == 2)
FOO(blah);
This interprets to:
if (blah == 2)
printf("arg is %s\n", blah);
do_something_useful(blah);;
As you can see, the if then only encompasses the printf(), and the do_something_useful() call is unconditional (not within the scope of the if), like you wanted it. So, by using a block like do { ... } while(0), you would get this:
if (blah == 2)
do {
printf("arg is %s\n", blah);
do_something_useful(blah);
} while (0);
Which is exactly what you want.
If you want a block statement so you can have several lines of code and declare local variables. But then the natural thing would be to just use for example:
#define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }
However that wouldn't work in some cases. The following code is meant to be an if-statement with two branches:
if (x > y)
exch(x,y); // Branch 1
else
do_something(); // Branch 2
But it would be interpreted as an if-statement with only one branch:
if (x > y) { // Single-branch if-statement!!!
int tmp; // The one and only branch consists
tmp = x; // of the block.
x = y;
y = tmp;
}
; // empty statement
else // ERROR!!! "parse error before else"
do_something();
The problem is the semi-colon (;) coming directly after the block. The solution for this is to sandwich the block between do and while (0). Then we have a single statement with the capabilities of a block, but not considered as being a block statement by the compiler. Our if-statement now becomes:
if (x > y)
do {
int tmp;
tmp = x;
x = y;
y = tmp;
} while(0);
else
do_something();
Sunday, June 10, 2007
AJAX and XML Response
1) Set the content type of the response as xml:
response.setContentType("application/xml");
Otherwise function xmlHttpRequest.responseXML would return a null object and the XML you are trying to return as response would be returned as String object rather than a XML object and you can access that by xmlHttpRequest.responseText.
2) Construct a well-formed XML which you are going to return in response, make the XML as standalone :
returnXML = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<root>
<allxmlelements></allxmlelements>
</root>";
Important: If the XML constructed above is not well formed you won't be able get the correct response back when you try to access the returned XML in JavaScript using:
var rspXml = xmlHttpRequest.responseXML;
Q: How to check if the XML you are returning in AJAX response is correct/well-formed or not?
A: Best way to check whether the returned XML is well formed or not is to type the URL being passed in the AJAX request directly into the browser. If the response XML is well formed then browser would display the complete XML or else it would display error in the XML. (This is the best and easiest way to check the response.)
Example: in an STRUTS application when the AJAX request is processed in an Action class you can return the XML using code below;
response.setContentType("application/xml");
response.getWriter().write(returnXML);
return (null);
Note: In a STRUTS application for an AJAX request to complete successfully, the execute method of the Action class being called should return "null" instead of an ActionForward.
This article has now moved to my new BLOG.
Labels: AJAX, HTTP, J2EE, Java, reponse, request, response.getWriter().write, response.setContentType, responseText, responseXML, Struts, XMLHttpRequest