View mode: basic / threaded / horizontal-split · Log in · Help
January 12, 2003
An example of a use of C macros that has not been discussed
An example of a use of C macros that has not been discussed
===========================================================

In an embedded http server I wrote, I want all my pages to be in the
constant section, so I defined macros to easily create HTTP pages
with a consistent format, declared all as "const char *". What follows
is an actual sample of code.

I would VERY much like to use D for embedded projects. I believe
it is absolutely essential to be able to manipulate constant data
as in the example below. Even C macros are not powerful enough IMO.

On-the-fly generation of the HTML text is not an option.

-paul

#define RESPONSE_HEADER(n,s) "\
HTTP/1.0 " #n " " #s "\r\n\
Server: PaulOS internal proxy\r\n\
Content-Type: text/html\r\n\
Proxy-Connection: close\r\n\
\r\n\
"

#define RESPONSE_TEXT_HEADER(n,s) "\
HTTP/1.0 " #n " " #s "\r\n\
Server: PaulOS internal proxy\r\n\
Content-Type: text/plain\r\n\
Proxy-Connection: close\r\n\
\r\n\
"

#define HTML_TOP(meta,title,body) "\
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\r\n\
<HTML>\r\n\
<HEAD>\r\n\
<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=ISO-8859-1\">\
" meta "\r\n\
<TITLE>" title "</TITLE>\r\n\
</HEAD>\r\n\
<BODY" body ">\r\n"

#define HTML_BOTTOM "\
<TABLE width=\"100%\" border=\"0\" rules=\"none\" cellspacing=\"0\" cellpadding=\"0\"><TR><TD align=\"right\">\r\n\
<A href=\"credits\" target=\"_blank\">þ</A>\r\n\
</TD></TR></TABLE>\r\n\
</BODY></HTML>\r\n"

#define HTML_HEADER(h1,h2) HTML_TOP("", #h1 ": " #h2, "") "\
<TABLE bgcolor=\"#0080FF\" width=\"100%\" border=\"0\" rules=\"none\" cellspacing=\"0\" cellpadding=\"3\"><TR><TD>\r\n\
<TABLE bgcolor=\"#FFFFFF\" width=\"100%\" border=\"0\" rules=\"none\" cellspacing=\"0\" cellpadding=\"5\"><TR><TD>\r\n\
<CENTER><FONT face=\"Arial, Helvetica, sans-serif\" color=\"#0080FF\"><B>InsTconnect Router</B></FONT></CENTER>\r\n\
</TD></TR></TABLE>\r\n\
</TD></TR></TABLE>\r\n\
<P><FONT size=\"+2\"><B>" #h1 "</B></FONT><P>\r\n\
<FONT size=\"+1\"><B>" #h2 "</B></FONT><P>\r\n\
<P>\r\n\
<TABLE bgcolor=\"#0080FF\" width=\"100%\" border=\"0\" rules=\"none\" cellspacing=\"0\" cellpadding=\"3\"><TR><TD>\r\n\
<TABLE bgcolor=\"#FFFFFF\" width=\"100%\" border=\"0\" rules=\"none\" cellspacing=\"0\" cellpadding=\"10\"><TR><TD>\r\n\
"

#define HTML_FOOTER() "\
</TD></TR></TABLE>\r\n\
</TD></TR></TABLE>\r\n" HTML_BOTTOM

#define DECLARE_MESSAGE(a,b,c,d)	static const char a[] = b c d HTML_FOOTER()


DECLARE_MESSAGE(NODIAL_RESPONSE, RESPONSE_HEADER (200, Ok), HTML_HEADER(DIAL, Wait for dial), \
"You must enable \"HTTP proxy\" in your web browser for this action to work.\r\n");

DECLARE_MESSAGE(NO_MATCH, RESPONSE_HEADER (404, Not Found), HTML_HEADER(ERROR, Invalid request), \
"You made a request to the router that was invalid.\r\n");

DECLARE_MESSAGE(BAD_USER_NAME, RESPONSE_HEADER (200, Ok), HTML_HEADER(REGISTER, Bad user name), \
"The user name <FONT color=\"red\">$U</FONT> is to short or already exists.\r\n");

DECLARE_MESSAGE(SETPASSWORD_SUCCESS, RESPONSE_HEADER (200, Ok), HTML_HEADER(REGISTER, Set password success), \
"The administrator password has been set.\r\n");

DECLARE_MESSAGE(USER_ADDED, RESPONSE_HEADER (200, Ok), HTML_HEADER(REGISTER, Success), \
"User <FONT color=\"red\">$U</FONT> is now associated\r\n\
with IP address <FONT color=\"red\">$I</FONT>. You are now\r\n\
free to use this gateway.\r\n");
January 12, 2003
Re: An example of a use of C macros that has not been discussed
I understand what you're doing, and you're right, D doesn't offer the
ability to stringize macro parameters.

I would guess that such strings & macros form only a small part of your
program, couldn't a .d file be generated programmatically? For example,
write a D program along the lines of:

void main()
{
   string("foo", "bar");
}

void string(char[] s, char[] t)
{
   file.write("char[] abc = \"prefix" ~ s ~ "middle" ~ t ~ "suffix\";");
}

"Paul Sheer" <psheer@icon.co.za> wrote in message
news:avru6h$1ri8$1@digitaldaemon.com...
>
> An example of a use of C macros that has not been discussed
> ===========================================================
>
> In an embedded http server I wrote, I want all my pages to be in the
> constant section, so I defined macros to easily create HTTP pages
> with a consistent format, declared all as "const char *". What follows
> is an actual sample of code.
>
> I would VERY much like to use D for embedded projects. I believe
> it is absolutely essential to be able to manipulate constant data
> as in the example below. Even C macros are not powerful enough IMO.
>
> On-the-fly generation of the HTML text is not an option.
>
> -paul
>
> #define RESPONSE_HEADER(n,s) "\
> HTTP/1.0 " #n " " #s "\r\n\
> Server: PaulOS internal proxy\r\n\
> Content-Type: text/html\r\n\
> Proxy-Connection: close\r\n\
> \r\n\
> "
>
> #define RESPONSE_TEXT_HEADER(n,s) "\
> HTTP/1.0 " #n " " #s "\r\n\
> Server: PaulOS internal proxy\r\n\
> Content-Type: text/plain\r\n\
> Proxy-Connection: close\r\n\
> \r\n\
> "
>
> #define HTML_TOP(meta,title,body) "\
> <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\r\n\
> <HTML>\r\n\
> <HEAD>\r\n\
> <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;
charset=ISO-8859-1\">\
> " meta "\r\n\
> <TITLE>" title "</TITLE>\r\n\
> </HEAD>\r\n\
> <BODY" body ">\r\n"
>
> #define HTML_BOTTOM "\
> <TABLE width=\"100%\" border=\"0\" rules=\"none\" cellspacing=\"0\"
cellpadding=\"0\"><TR><TD align=\"right\">\r\n\
> <A href=\"credits\" target=\"_blank\">þ</A>\r\n\
> </TD></TR></TABLE>\r\n\
> </BODY></HTML>\r\n"
>
> #define HTML_HEADER(h1,h2) HTML_TOP("", #h1 ": " #h2, "") "\
> <TABLE bgcolor=\"#0080FF\" width=\"100%\" border=\"0\" rules=\"none\"
cellspacing=\"0\" cellpadding=\"3\"><TR><TD>\r\n\
> <TABLE bgcolor=\"#FFFFFF\" width=\"100%\" border=\"0\" rules=\"none\"
cellspacing=\"0\" cellpadding=\"5\"><TR><TD>\r\n\
> <CENTER><FONT face=\"Arial, Helvetica, sans-serif\"
color=\"#0080FF\"><B>InsTconnect Router</B></FONT></CENTER>\r\n\
> </TD></TR></TABLE>\r\n\
> </TD></TR></TABLE>\r\n\
> <P><FONT size=\"+2\"><B>" #h1 "</B></FONT><P>\r\n\
> <FONT size=\"+1\"><B>" #h2 "</B></FONT><P>\r\n\
> <P>\r\n\
> <TABLE bgcolor=\"#0080FF\" width=\"100%\" border=\"0\" rules=\"none\"
cellspacing=\"0\" cellpadding=\"3\"><TR><TD>\r\n\
> <TABLE bgcolor=\"#FFFFFF\" width=\"100%\" border=\"0\" rules=\"none\"
cellspacing=\"0\" cellpadding=\"10\"><TR><TD>\r\n\
> "
>
> #define HTML_FOOTER() "\
> </TD></TR></TABLE>\r\n\
> </TD></TR></TABLE>\r\n" HTML_BOTTOM
>
> #define DECLARE_MESSAGE(a,b,c,d) static const char a[] = b c d
HTML_FOOTER()
>
>
> DECLARE_MESSAGE(NODIAL_RESPONSE, RESPONSE_HEADER (200, Ok),
HTML_HEADER(DIAL, Wait for dial), \
> "You must enable \"HTTP proxy\" in your web browser for this action to
work.\r\n");
>
> DECLARE_MESSAGE(NO_MATCH, RESPONSE_HEADER (404, Not Found),
HTML_HEADER(ERROR, Invalid request), \
> "You made a request to the router that was invalid.\r\n");
>
> DECLARE_MESSAGE(BAD_USER_NAME, RESPONSE_HEADER (200, Ok),
HTML_HEADER(REGISTER, Bad user name), \
> "The user name <FONT color=\"red\">$U</FONT> is to short or already
exists.\r\n");
>
> DECLARE_MESSAGE(SETPASSWORD_SUCCESS, RESPONSE_HEADER (200, Ok),
HTML_HEADER(REGISTER, Set password success), \
> "The administrator password has been set.\r\n");
>
> DECLARE_MESSAGE(USER_ADDED, RESPONSE_HEADER (200, Ok),
HTML_HEADER(REGISTER, Success), \
> "User <FONT color=\"red\">$U</FONT> is now associated\r\n\
> with IP address <FONT color=\"red\">$I</FONT>. You are now\r\n\
> free to use this gateway.\r\n");
>
>
January 13, 2003
Re: An example of a use of C macros that has not been discussed
> I understand what you're doing, and you're right, D doesn't offer the
> ability to stringize macro parameters.
> 
> I would guess that such strings & macros form only a small part of your
> program, 

yes, but they are used all over; for example (this is just
toooo convenient):

const struct device __device[] = {
   {"/dev/null", (void *) 0, &file_null},
   {"/dev/ttyS0", (void *) SAMSUMG_UART1, &file_samsungserial},
   {"/dev/ttyS1", (void *) SAMSUMG_UART0, &file_samsungserial},
   {"/dev/loop0", (void *) 0, &file_loop},
#ifdef HAVE_ETH
   {"/dev/eth0", (void *) 0, &file_samsungeth},
#endif
#ifdef HAVE_PPPOE
   {"/dev/pppoe", (void *) 0, &file_pppoe},
#endif
#ifdef HAVE_HDLC
   {"/dev/hdlc0", (void *) SAMSUNG_HDLC_A, &file_samsunghdlc},
#endif
#ifdef HAVE_NET
   {"/dev/tcp", (void *) IPPROTO_TCP, &file_socket},
#ifdef HAVE_UDP
   {"/dev/udp", (void *) IPPROTO_UDP, &file_udp},
#endif
#endif
   {"/dev/flash", (void *) ((u_int32_t) 0x1000000 | 0x4000000), &file_flash},
#ifdef HAVE_PPPCONF
   {"/etc/ppp.conf", (void *) &pppconf_data, &file_staticfile},
#endif
   {0, 0, 0},
};

> couldn't a .d file be generated programmatically? 

yes, but then it would be like having a D macro preprocessor
in any case :-)

you see, people ARE going to use the C preprocessor regardless
of whether you include it as part of the D specification. They
simply HAVE to use it in some situations. the same happened with
the Haskell compiler: people use cpp with haskell.

So you might as well create a better macro language than cpp.

> For example, write a [...]

yeah yeah i got you :-)

you see D is so important for embedded systems because
they are notoriously difficult to debug. with D you can
write pretty safe code, but you can still write things
like a tcp stack which you would previously only do in C.

-paul


--------------------------

> void main()
> {
>     string("foo", "bar");
> }
> 
> void string(char[] s, char[] t)
> {
>     file.write("char[] abc = \"prefix" ~ s ~ "middle" ~ t ~ "suffix\";");
> }
> 
> "Paul Sheer" <psheer@icon.co.za> wrote in message
> news:avru6h$1ri8$1@digitaldaemon.com...
>>
>> An example of a use of C macros that has not been discussed
>> ===========================================================
>>
>> In an embedded http server I wrote, I want all my pages to be in the
>> constant section, so I defined macros to easily create HTTP pages
>> with a consistent format, declared all as "const char *". What follows
>> is an actual sample of code.
>>
>> I would VERY much like to use D for embedded projects. I believe
>> it is absolutely essential to be able to manipulate constant data
>> as in the example below. Even C macros are not powerful enough IMO.
>>
>> On-the-fly generation of the HTML text is not an option.
>>
>> -paul
>>
>> #define RESPONSE_HEADER(n,s) "\
>> HTTP/1.0 " #n " " #s "\r\n\
>> Server: PaulOS internal proxy\r\n\
>> Content-Type: text/html\r\n\
>> Proxy-Connection: close\r\n\
>> \r\n\
>> "
>>
>> #define RESPONSE_TEXT_HEADER(n,s) "\
>> HTTP/1.0 " #n " " #s "\r\n\
>> Server: PaulOS internal proxy\r\n\
>> Content-Type: text/plain\r\n\
>> Proxy-Connection: close\r\n\
>> \r\n\
>> "
>>
>> #define HTML_TOP(meta,title,body) "\
>> <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\r\n\
>> <HTML>\r\n\
>> <HEAD>\r\n\
>> <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;
> charset=ISO-8859-1\">\
>> " meta "\r\n\
>> <TITLE>" title "</TITLE>\r\n\
>> </HEAD>\r\n\
>> <BODY" body ">\r\n"
>>
>> #define HTML_BOTTOM "\
>> <TABLE width=\"100%\" border=\"0\" rules=\"none\" cellspacing=\"0\"
> cellpadding=\"0\"><TR><TD align=\"right\">\r\n\
>> <A href=\"credits\" target=\"_blank\">þ</A>\r\n\
>> </TD></TR></TABLE>\r\n\
>> </BODY></HTML>\r\n"
>>
>> #define HTML_HEADER(h1,h2) HTML_TOP("", #h1 ": " #h2, "") "\
>> <TABLE bgcolor=\"#0080FF\" width=\"100%\" border=\"0\" rules=\"none\"
> cellspacing=\"0\" cellpadding=\"3\"><TR><TD>\r\n\
>> <TABLE bgcolor=\"#FFFFFF\" width=\"100%\" border=\"0\" rules=\"none\"
> cellspacing=\"0\" cellpadding=\"5\"><TR><TD>\r\n\
>> <CENTER><FONT face=\"Arial, Helvetica, sans-serif\"
> color=\"#0080FF\"><B>InsTconnect Router</B></FONT></CENTER>\r\n\
>> </TD></TR></TABLE>\r\n\
>> </TD></TR></TABLE>\r\n\
>> <P><FONT size=\"+2\"><B>" #h1 "</B></FONT><P>\r\n\
>> <FONT size=\"+1\"><B>" #h2 "</B></FONT><P>\r\n\
>> <P>\r\n\
>> <TABLE bgcolor=\"#0080FF\" width=\"100%\" border=\"0\" rules=\"none\"
> cellspacing=\"0\" cellpadding=\"3\"><TR><TD>\r\n\
>> <TABLE bgcolor=\"#FFFFFF\" width=\"100%\" border=\"0\" rules=\"none\"
> cellspacing=\"0\" cellpadding=\"10\"><TR><TD>\r\n\
>> "
>>
>> #define HTML_FOOTER() "\
>> </TD></TR></TABLE>\r\n\
>> </TD></TR></TABLE>\r\n" HTML_BOTTOM
>>
>> #define DECLARE_MESSAGE(a,b,c,d) static const char a[] = b c d
> HTML_FOOTER()
>>
>>
>> DECLARE_MESSAGE(NODIAL_RESPONSE, RESPONSE_HEADER (200, Ok),
> HTML_HEADER(DIAL, Wait for dial), \
>> "You must enable \"HTTP proxy\" in your web browser for this action to
> work.\r\n");
>>
>> DECLARE_MESSAGE(NO_MATCH, RESPONSE_HEADER (404, Not Found),
> HTML_HEADER(ERROR, Invalid request), \
>> "You made a request to the router that was invalid.\r\n");
>>
>> DECLARE_MESSAGE(BAD_USER_NAME, RESPONSE_HEADER (200, Ok),
> HTML_HEADER(REGISTER, Bad user name), \
>> "The user name <FONT color=\"red\">$U</FONT> is to short or already
> exists.\r\n");
>>
>> DECLARE_MESSAGE(SETPASSWORD_SUCCESS, RESPONSE_HEADER (200, Ok),
> HTML_HEADER(REGISTER, Set password success), \
>> "The administrator password has been set.\r\n");
>>
>> DECLARE_MESSAGE(USER_ADDED, RESPONSE_HEADER (200, Ok),
> HTML_HEADER(REGISTER, Success), \
>> "User <FONT color=\"red\">$U</FONT> is now associated\r\n\
>> with IP address <FONT color=\"red\">$I</FONT>. You are now\r\n\
>> free to use this gateway.\r\n");
>>
>>
January 13, 2003
Re: An example of a use of C macros that has not been discussed
there is 'version'
> const struct device __device[] = {
>     {"/dev/null", (void *) 0, &file_null},
>     {"/dev/ttyS0", (void *) SAMSUMG_UART1, &file_samsungserial},
>     {"/dev/ttyS1", (void *) SAMSUMG_UART0, &file_samsungserial},
>     {"/dev/loop0", (void *) 0, &file_loop},
> #ifdef HAVE_ETH
>     {"/dev/eth0", (void *) 0, &file_samsungeth},
> #endif
> #ifdef HAVE_PPPOE
>     {"/dev/pppoe", (void *) 0, &file_pppoe},
> #endif

like (but not quite D code)
Device __devices[] = [
  new Device( .... ),
  new Device( .... ),
version ( HAVE_ETH ) {
  new Device( "Ethernet", ...  ),
}
];

currently you have to create arrays in you modules static initialiser,
rather than declare it "inline" (D only has runtime inits rather than
optional compile time inits).
January 13, 2003
Re: An example of a use of C macros that has not been discussed
With D, you'd wrap the entire struct declaration in a version declaration.
Whether it would wind up looking better or worse than the #ifdef version is
a matter of personal taste.

Also, yes, people will always be writing programs that spit out source code
to be compiled. I do it all the time, usually for generating complex tables.
No macro processor is going to do it.

"Paul Sheer" <psheer@icon.co.za> wrote in message
news:avtseg$1s5r$1@digitaldaemon.com...
>
> > I understand what you're doing, and you're right, D doesn't offer the
> > ability to stringize macro parameters.
> >
> > I would guess that such strings & macros form only a small part of your
> > program,
>
> yes, but they are used all over; for example (this is just
> toooo convenient):
>
> const struct device __device[] = {
>     {"/dev/null", (void *) 0, &file_null},
>     {"/dev/ttyS0", (void *) SAMSUMG_UART1, &file_samsungserial},
>     {"/dev/ttyS1", (void *) SAMSUMG_UART0, &file_samsungserial},
>     {"/dev/loop0", (void *) 0, &file_loop},
> #ifdef HAVE_ETH
>     {"/dev/eth0", (void *) 0, &file_samsungeth},
> #endif
> #ifdef HAVE_PPPOE
>     {"/dev/pppoe", (void *) 0, &file_pppoe},
> #endif
> #ifdef HAVE_HDLC
>     {"/dev/hdlc0", (void *) SAMSUNG_HDLC_A, &file_samsunghdlc},
> #endif
> #ifdef HAVE_NET
>     {"/dev/tcp", (void *) IPPROTO_TCP, &file_socket},
> #ifdef HAVE_UDP
>     {"/dev/udp", (void *) IPPROTO_UDP, &file_udp},
> #endif
> #endif
>     {"/dev/flash", (void *) ((u_int32_t) 0x1000000 | 0x4000000),
&file_flash},
> #ifdef HAVE_PPPCONF
>     {"/etc/ppp.conf", (void *) &pppconf_data, &file_staticfile},
> #endif
>     {0, 0, 0},
> };
>
> > couldn't a .d file be generated programmatically?
>
> yes, but then it would be like having a D macro preprocessor
> in any case :-)
>
> you see, people ARE going to use the C preprocessor regardless
> of whether you include it as part of the D specification. They
> simply HAVE to use it in some situations. the same happened with
> the Haskell compiler: people use cpp with haskell.
>
> So you might as well create a better macro language than cpp.
>
> > For example, write a [...]
>
> yeah yeah i got you :-)
>
> you see D is so important for embedded systems because
> they are notoriously difficult to debug. with D you can
> write pretty safe code, but you can still write things
> like a tcp stack which you would previously only do in C.
>
> -paul
>
>
> --------------------------
>
> > void main()
> > {
> >     string("foo", "bar");
> > }
> >
> > void string(char[] s, char[] t)
> > {
> >     file.write("char[] abc = \"prefix" ~ s ~ "middle" ~ t ~
"suffix\";");
> > }
> >
> > "Paul Sheer" <psheer@icon.co.za> wrote in message
> > news:avru6h$1ri8$1@digitaldaemon.com...
> >>
> >> An example of a use of C macros that has not been discussed
> >> ===========================================================
> >>
> >> In an embedded http server I wrote, I want all my pages to be in the
> >> constant section, so I defined macros to easily create HTTP pages
> >> with a consistent format, declared all as "const char *". What follows
> >> is an actual sample of code.
> >>
> >> I would VERY much like to use D for embedded projects. I believe
> >> it is absolutely essential to be able to manipulate constant data
> >> as in the example below. Even C macros are not powerful enough IMO.
> >>
> >> On-the-fly generation of the HTML text is not an option.
> >>
> >> -paul
> >>
> >> #define RESPONSE_HEADER(n,s) "\
> >> HTTP/1.0 " #n " " #s "\r\n\
> >> Server: PaulOS internal proxy\r\n\
> >> Content-Type: text/html\r\n\
> >> Proxy-Connection: close\r\n\
> >> \r\n\
> >> "
> >>
> >> #define RESPONSE_TEXT_HEADER(n,s) "\
> >> HTTP/1.0 " #n " " #s "\r\n\
> >> Server: PaulOS internal proxy\r\n\
> >> Content-Type: text/plain\r\n\
> >> Proxy-Connection: close\r\n\
> >> \r\n\
> >> "
> >>
> >> #define HTML_TOP(meta,title,body) "\
> >> <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\r\n\
> >> <HTML>\r\n\
> >> <HEAD>\r\n\
> >> <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;
> > charset=ISO-8859-1\">\
> >> " meta "\r\n\
> >> <TITLE>" title "</TITLE>\r\n\
> >> </HEAD>\r\n\
> >> <BODY" body ">\r\n"
> >>
> >> #define HTML_BOTTOM "\
> >> <TABLE width=\"100%\" border=\"0\" rules=\"none\" cellspacing=\"0\"
> > cellpadding=\"0\"><TR><TD align=\"right\">\r\n\
> >> <A href=\"credits\" target=\"_blank\">þ</A>\r\n\
> >> </TD></TR></TABLE>\r\n\
> >> </BODY></HTML>\r\n"
> >>
> >> #define HTML_HEADER(h1,h2) HTML_TOP("", #h1 ": " #h2, "") "\
> >> <TABLE bgcolor=\"#0080FF\" width=\"100%\" border=\"0\" rules=\"none\"
> > cellspacing=\"0\" cellpadding=\"3\"><TR><TD>\r\n\
> >> <TABLE bgcolor=\"#FFFFFF\" width=\"100%\" border=\"0\" rules=\"none\"
> > cellspacing=\"0\" cellpadding=\"5\"><TR><TD>\r\n\
> >> <CENTER><FONT face=\"Arial, Helvetica, sans-serif\"
> > color=\"#0080FF\"><B>InsTconnect Router</B></FONT></CENTER>\r\n\
> >> </TD></TR></TABLE>\r\n\
> >> </TD></TR></TABLE>\r\n\
> >> <P><FONT size=\"+2\"><B>" #h1 "</B></FONT><P>\r\n\
> >> <FONT size=\"+1\"><B>" #h2 "</B></FONT><P>\r\n\
> >> <P>\r\n\
> >> <TABLE bgcolor=\"#0080FF\" width=\"100%\" border=\"0\" rules=\"none\"
> > cellspacing=\"0\" cellpadding=\"3\"><TR><TD>\r\n\
> >> <TABLE bgcolor=\"#FFFFFF\" width=\"100%\" border=\"0\" rules=\"none\"
> > cellspacing=\"0\" cellpadding=\"10\"><TR><TD>\r\n\
> >> "
> >>
> >> #define HTML_FOOTER() "\
> >> </TD></TR></TABLE>\r\n\
> >> </TD></TR></TABLE>\r\n" HTML_BOTTOM
> >>
> >> #define DECLARE_MESSAGE(a,b,c,d) static const char a[] = b c d
> > HTML_FOOTER()
> >>
> >>
> >> DECLARE_MESSAGE(NODIAL_RESPONSE, RESPONSE_HEADER (200, Ok),
> > HTML_HEADER(DIAL, Wait for dial), \
> >> "You must enable \"HTTP proxy\" in your web browser for this action to
> > work.\r\n");
> >>
> >> DECLARE_MESSAGE(NO_MATCH, RESPONSE_HEADER (404, Not Found),
> > HTML_HEADER(ERROR, Invalid request), \
> >> "You made a request to the router that was invalid.\r\n");
> >>
> >> DECLARE_MESSAGE(BAD_USER_NAME, RESPONSE_HEADER (200, Ok),
> > HTML_HEADER(REGISTER, Bad user name), \
> >> "The user name <FONT color=\"red\">$U</FONT> is to short or already
> > exists.\r\n");
> >>
> >> DECLARE_MESSAGE(SETPASSWORD_SUCCESS, RESPONSE_HEADER (200, Ok),
> > HTML_HEADER(REGISTER, Set password success), \
> >> "The administrator password has been set.\r\n");
> >>
> >> DECLARE_MESSAGE(USER_ADDED, RESPONSE_HEADER (200, Ok),
> > HTML_HEADER(REGISTER, Success), \
> >> "User <FONT color=\"red\">$U</FONT> is now associated\r\n\
> >> with IP address <FONT color=\"red\">$I</FONT>. You are now\r\n\
> >> free to use this gateway.\r\n");
> >>
> >>
>
January 14, 2003
Re: An example of a use of C macros that has not been discussed
I think this is all about the code optimization problem.
C compiler used to rely on developers to optimize this kind of situations.

But I think, for this piece of code:

char* f(char* s)
{
   return "abc " + s + " xyz";
}

void foo()
{
   char *p = f("123");
   char *q = f(p);
}

/* I know, this may not be really correct D code */

A smart enough compiler should simply assign p a pointer to the string "abc
123 xyz" while execute some code for assigning the right thing to q.

If the compiler is so smart, the following kind of macro processing is
completely unnecessary.

In addition, if this kind of optimization can be turned off, debugging this
kind of "macros" would become much easier.

BTW, can the D compiler do something like this?

Kiyo

"Paul Sheer" <psheer@icon.co.za> wrote in message
news:avru6h$1ri8$1@digitaldaemon.com...
>
> An example of a use of C macros that has not been discussed
> ===========================================================
>
> In an embedded http server I wrote, I want all my pages to be in the
> constant section, so I defined macros to easily create HTTP pages
> with a consistent format, declared all as "const char *". What follows
> is an actual sample of code.
>
> I would VERY much like to use D for embedded projects. I believe
> it is absolutely essential to be able to manipulate constant data
> as in the example below. Even C macros are not powerful enough IMO.
>
> On-the-fly generation of the HTML text is not an option.
>
> -paul
>
> #define RESPONSE_HEADER(n,s) "\
> HTTP/1.0 " #n " " #s "\r\n\
> Server: PaulOS internal proxy\r\n\
> Content-Type: text/html\r\n\
> Proxy-Connection: close\r\n\
> \r\n\
> "
>
> #define RESPONSE_TEXT_HEADER(n,s) "\
> HTTP/1.0 " #n " " #s "\r\n\
> Server: PaulOS internal proxy\r\n\
> Content-Type: text/plain\r\n\
> Proxy-Connection: close\r\n\
> \r\n\
> "
>
> #define HTML_TOP(meta,title,body) "\
> <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\r\n\
> <HTML>\r\n\
> <HEAD>\r\n\
> <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html;
charset=ISO-8859-1\">\
> " meta "\r\n\
> <TITLE>" title "</TITLE>\r\n\
> </HEAD>\r\n\
> <BODY" body ">\r\n"
>
> #define HTML_BOTTOM "\
> <TABLE width=\"100%\" border=\"0\" rules=\"none\" cellspacing=\"0\"
cellpadding=\"0\"><TR><TD align=\"right\">\r\n\
> <A href=\"credits\" target=\"_blank\">þ</A>\r\n\
> </TD></TR></TABLE>\r\n\
> </BODY></HTML>\r\n"
>
> #define HTML_HEADER(h1,h2) HTML_TOP("", #h1 ": " #h2, "") "\
> <TABLE bgcolor=\"#0080FF\" width=\"100%\" border=\"0\" rules=\"none\"
cellspacing=\"0\" cellpadding=\"3\"><TR><TD>\r\n\
> <TABLE bgcolor=\"#FFFFFF\" width=\"100%\" border=\"0\" rules=\"none\"
cellspacing=\"0\" cellpadding=\"5\"><TR><TD>\r\n\
> <CENTER><FONT face=\"Arial, Helvetica, sans-serif\"
color=\"#0080FF\"><B>InsTconnect Router</B></FONT></CENTER>\r\n\
> </TD></TR></TABLE>\r\n\
> </TD></TR></TABLE>\r\n\
> <P><FONT size=\"+2\"><B>" #h1 "</B></FONT><P>\r\n\
> <FONT size=\"+1\"><B>" #h2 "</B></FONT><P>\r\n\
> <P>\r\n\
> <TABLE bgcolor=\"#0080FF\" width=\"100%\" border=\"0\" rules=\"none\"
cellspacing=\"0\" cellpadding=\"3\"><TR><TD>\r\n\
> <TABLE bgcolor=\"#FFFFFF\" width=\"100%\" border=\"0\" rules=\"none\"
cellspacing=\"0\" cellpadding=\"10\"><TR><TD>\r\n\
> "
>
> #define HTML_FOOTER() "\
> </TD></TR></TABLE>\r\n\
> </TD></TR></TABLE>\r\n" HTML_BOTTOM
>
> #define DECLARE_MESSAGE(a,b,c,d) static const char a[] = b c d
HTML_FOOTER()
>
>
> DECLARE_MESSAGE(NODIAL_RESPONSE, RESPONSE_HEADER (200, Ok),
HTML_HEADER(DIAL, Wait for dial), \
> "You must enable \"HTTP proxy\" in your web browser for this action to
work.\r\n");
>
> DECLARE_MESSAGE(NO_MATCH, RESPONSE_HEADER (404, Not Found),
HTML_HEADER(ERROR, Invalid request), \
> "You made a request to the router that was invalid.\r\n");
>
> DECLARE_MESSAGE(BAD_USER_NAME, RESPONSE_HEADER (200, Ok),
HTML_HEADER(REGISTER, Bad user name), \
> "The user name <FONT color=\"red\">$U</FONT> is to short or already
exists.\r\n");
>
> DECLARE_MESSAGE(SETPASSWORD_SUCCESS, RESPONSE_HEADER (200, Ok),
HTML_HEADER(REGISTER, Set password success), \
> "The administrator password has been set.\r\n");
>
> DECLARE_MESSAGE(USER_ADDED, RESPONSE_HEADER (200, Ok),
HTML_HEADER(REGISTER, Success), \
> "User <FONT color=\"red\">$U</FONT> is now associated\r\n\
> with IP address <FONT color=\"red\">$I</FONT>. You are now\r\n\
> free to use this gateway.\r\n");
>
>
Top | Discussion index | About this forum | D home