I worked on something allow embedding C code in Pike several years ago.
So that, when I need calling a C lib, I don't need to write a CMOD.
Following is a example to call iconv, notic C{ and P{ :
$ cat iconv.pmod
#pike __REAL_VERSION__
//! Call iconv(3) to perform character set conversion
//! @param from
//! Encoding convert characters from.
//! @param to
//! Encoding cconvert characters to.
//! @param s
//! String to be converted.
//! @returns
//! String converted.
//!
//! @note
//! More info see iconv manpage.
string `()(string from,string to,string s,void|int ignore_error)
{
//werror("enter iconv %s %s %O\n",from,to,s);
if(s==0)
return 0;
if(!stringp(s))
throw(({"ERROR: bad input\n",backtrace()}));
Cross.CC("gcc -g -shared -fPIC");
Cross.INCLUDE(
"#include <iconv.h>\n"
"#include <errno.h>\n"
"#include <string.h>\n" );
string err;
string res="";
C{
iconv_t cd=iconv_open(STRING{to},STRING{from});
if(cd==(iconv_t)-1){
P{err=sprintf("iconv: Can't convert (iconv_open fail): %s (%s -> %s)",s,from,to);}
return;
}else{
size_t insize=strlen(STRING{s});
char* inbuf=STRING{s};
char buffer[1025];
while(insize){
char* outbuf=buffer;
size_t outsize=1024;
size_t n=iconv(cd,&inbuf,&insize,&outbuf,&outsize);
if(n==-1&&errno!=E2BIG){
iconv_close(cd);
P{err=sprintf("iconv: Can't convert (%s): %s (%s -> %s)",STRING{strerror(errno)},s,from,to);}
return;
}
*outbuf='\0';
char* p=buffer;
P{ res+=STRING{p}; }
}
iconv_close(cd);
}
}
if(!err)
return res;
else{
if(ignore_error)
return res;
throw(({sprintf("ERROR: %s\n",err),backtrace()}));
}
}
The codes inside C{ ... } is actually a literal-string, P{ ... } inside it,
and there maybe more C{ ... } inside P{ ... } and forever.
I hacked into Pike's cpp code to implement it, using Parser.Pike, take out the things
inside C{} or P{}, and reconstruct the code.
Post by Chris AngelicoThe question is, do we actually need more than three? Is the
flexibility all that useful?
ChrisA
I don't, I hack into Pike, but if it exist, maybe help.
Post by Chris AngelicoPost by Martin Bähri can't even imagine how code that uses 3 levels would look like.
anyone with an example of why one would need/want to do that?
Martin BÀhr
Only if you're embedding the entire thing in a single string.
ChrisA
When you do code embedding like me, you will found that you don't like #( #{ #[ things.
Because we do copy-paste. A block quoted by #( ... #) may be copyed and pasted into a
block quoted by #( ... #) too, or by #( ... #[ ... #] ...#). If so, the inside #) terminated outter #( .
Post by Chris AngelicoPost by Martin BährBut it needs to write "mis-nested" quote characters, with their
nesting cleaned up by concatenation.
Well, that should work perfectly right now, since there is no nesting
of the same characters involved there.
Per Hedbor
I presume all this is for some sort of auto-generated code anyway, or
it's easy enough to break up manually - or to use #string or #" - and
the solution we're looking for is encapsualting unknown code.
Mirar
Don't worry about auto-generated code. If auto-generated, it's easy to auto-quoted.
Human writing matters.
Post by Chris AngelicoI think it is not really needed, if we just allow nesting of the other
quotes.
That is, allow #{ #{#} #} (equal to " #{#} ").
Then it only matters if you have more than tree different unbalances
chunks of code to output nested in each other.
I thing that most likely will be a rather rare occurence.
Per Hedbor
I like this idea.