Evaluating a string as C++ Code

M

Miro

Hello, Usenet.

I come from a background of mostly Perl and Ruby, so C++ is the first
truly low level programming language that I know. However, I have
something I'd like to ask the community about. I'm rewriting a BC-
esque terminal calculator I did in Perl. (You can find it on
SourceForge as PerlCalc, I believe.), and I've encountered a problem
that my manual book doesn't cover. In Perl, you can evaluate a string
as code like this:
#Getting the string
my $string = <STDIN>;
chomp( $string );
# Evaluate it and print it
print(eval($string));

How, pray tell, might I do that in C++?

Thanks for your help,
Miro
 
J

Jens Thoms Toerring

Miro said:
I come from a background of mostly Perl and Ruby, so C++ is the first
truly low level programming language that I know. However, I have
something I'd like to ask the community about. I'm rewriting a BC-
esque terminal calculator I did in Perl. (You can find it on
SourceForge as PerlCalc, I believe.), and I've encountered a problem
that my manual book doesn't cover. In Perl, you can evaluate a string
as code like this:
#Getting the string
my $string = <STDIN>;
chomp( $string );
# Evaluate it and print it
print(eval($string));
How, pray tell, might I do that in C++?

Simple (and rather conplete) answer: you don't. C+ isn't an
interpreted language, so there's no way to use source code
in a compiled program like you're used to from interpreted
languages. Consider the difference: if you have a Perl script
to run it the perl prgram must be installed on that machine
and it's that what's running (interpreting) your program
while, if you have a program that was created from C++
source code, nothing of C++ (well, beside the run-time li-
brary) must be available. It's a standalone program and
it's more or less immaterial what language it was written
in (there are enough programs that are assembled from parts
that originally were written in different languages, e.g.
C++, C, FORTRAN etc.).

This isn't about high-level versus low-level languages but
it's due to the fundamental difference between interpreted
and compiled languages.

The only thing you can do is write out the code to a file,
compile that file and then run the result from within your
program (using system() or something like that) and read
what that new program outputs. Not simple, hard to impos-
sible to write in a system independent way and requires
that a compiler is installed on the machine that this is
to be done on. And, of course, this new program has no
access at all to variables of the program it was created
from. In short: not a good idea. But then I can count the
number if cases where I have really needed Perl's eval()
(i.e. the 'eval EXPR' kind of Perl's eval) in the last 10
years on the fingers of one hand.

Regards, Jens
 
C

Carlo Milanesi

I'm rewriting a BC-
esque terminal calculator I did in Perl. (You can find it on
SourceForge as PerlCalc, I believe.), and I've encountered a problem
that my manual book doesn't cover. In Perl, you can evaluate a string
as code like this:
#Getting the string
my $string =<STDIN>;
chomp( $string );
# Evaluate it and print it
print(eval($string));

You can save the string to a file, launch a C++ compiler to generate the
corresponding executable program file, launch the generated executable
program, giving to that program the required input, and probably
receiving from that program the result.
Of course the target platform needs to have a C++ compiler installed
(but you already knew that to run a Perl program the target platform
needs to have a Perl interpreter installed).
Communication between the main program and the auxiliary program may be
performed through:
- command line and return code (command line is a string and return code
a byte)
- unnamed pipes
- named pipes
- temporary files (deprecated, but more portable)
- other IPC
- networking

An alternative (and probably better) solution is to evaluate your string
with a built-in interpreter for your language, that is probably way
simpler than C++.
There are many open-source embeddable interpreters for simple languages.
 
B

BGB

You can't do that; what you can do is to write an expression interpreter
in C++ which evaluates the string. A lot of such have been already
written; for arithmetic expressions I think libformulc is freely
available; so is libperl, coming to think of it...

one can also use a VM for a more capable and "similar" language, such as
JavaScript.

implementations like SpiderMonkey and V8 are relatively well-known and
relatively mature (not perfect though, but maybe good enough).

some people have also used CINT and TinyC.
there is also LLVM / CLang.


in my case, I have my own scripting VM and language (BGBScript, which is
currently mostly like JavaScript and ActionScript, but includes some
more Java-like and C-like syntax extensions, and puts some effort in
trying to have relatively transparent cross-language interop), but sadly
it is a bit far from being a mature solution.
 
M

Miro

Simple (and rather conplete) answer: you don't. C+ isn't an
interpreted language, so there's no way to use sourcecode
in a compiled program like you're used to from interpreted
languages. Consider the difference: if you have a Perl script
to run it the perl prgram must be installed on that machine
and it's that what's running (interpreting) your program
while, if you have a program that was created fromC++
sourcecode, nothing ofC++(well, beside the run-time li-
brary) must be available. It's a standalone program and
it's more or less immaterial what language it was written
in (there are enough programs that are assembled from parts
that originally were written in different languages, e.g.C++, C, FORTRAN etc.).

This isn't about high-level versus low-level languages but
it's due to the fundamental difference between interpreted
and compiled languages.

The only thing you can do is write out thecodeto a file,
compile that file and then run the result from within your
program (using system() or something like that) and read
what that new program outputs. Not simple, hard to impos-
sible to write in a system independent way and requires
that a compiler is installed on the machine that this is
to be done on. And, of course, this new program has no
access at all to variables of the program it was created
from. In short: not a good idea. But then I can count the
number if cases where I have really needed Perl's eval()
(i.e. the 'eval EXPR' kind of Perl's eval) in the last 10
years on the fingers of one hand.

                             Regards, Jens

Thanks, this group as a whole has probably given me the sanest and
soberest sounding answer I've heard all over the internet. :)
I'll probably just, as suggested, keep it in Perl or some other
scripting language and do the rest in CPP.

Miro
 
J

Jens Thoms Toerring

Miro said:
I'll probably just, as suggested, keep it in Perl or some other
scripting language and do the rest in CPP.

That's a very sound descision: use the best tool for the job
you've got to get done and don't get stuck in "that's-better-
than-something-else" for purely ideological reasons. If you
need something like Perl's 'eval EXPR' then C or C++ isn't
where you will find it (without a lot of pain) so use Perl
(or some other interpreted language supplying the required
functionality). If you've got the chance to mix interpreted
and compiled languages so that you can pick the best of both
worlds don't hesitate unless for good reasons.

Regards, Jens
 
J

James Kanze

You can save the string to a file, launch a C++ compiler to generate the
corresponding executable program file, launch the generated executable
program, giving to that program the required input, and probably
receiving from that program the result.
Of course the target platform needs to have a C++ compiler installed
(but you already knew that to run a Perl program the target platform
needs to have a Perl interpreter installed).
Communication between the main program and the auxiliary program may be
performed through:
- command line and return code (command line is a string and return code
a byte)
- unnamed pipes
- named pipes
- temporary files (deprecated, but more portable)
- other IPC
- networking

An alternative (and probably better) solution is to evaluate your string
with a built-in interpreter for your language, that is probably way
simpler than C++.
There are many open-source embeddable interpreters for simple languages.

You could also compile and link the code to a DLL, then load that.
(Not that I'm recommending such things.)
 
J

Jorgen Grahn

On Jul 30, 7:08 pm, Carlo Milanesi <[email protected]> .... ....

You could also compile and link the code to a DLL, then load that.
(Not that I'm recommending such things.)

Normally I agree. But I've seen at least one application where it
would have been a good idea. Embedded system, IP packet filtering with
large amounts of configurable, complex rules, high performance
needed.

We're so used to assume that there is no compiler on the target
system. But nowadays, on Linux and *BSDs, if we have a need for one
it's not more troublesome than any other dependency. It's not as if
you, as an end user, have to buy a license for gcc ...

/Jorgen
 
J

jacob navia

Le 30/07/11 18:52, Miro a écrit :
Hello, Usenet.

I come from a background of mostly Perl and Ruby, so C++ is the first
truly low level programming language that I know. However, I have
something I'd like to ask the community about. I'm rewriting a BC-
esque terminal calculator I did in Perl. (You can find it on
SourceForge as PerlCalc, I believe.), and I've encountered a problem
that my manual book doesn't cover. In Perl, you can evaluate a string
as code like this:
#Getting the string
my $string =<STDIN>;
chomp( $string );
# Evaluate it and print it
print(eval($string));

How, pray tell, might I do that in C++?

Thanks for your help,
Miro

If you limit yourself to the C language (not C++) you do:

#include <jit.h>

int (*pfn)(void);

int main(void)
{
pfn = compile("#include <stdio.h>\nint main(void){ printf(\"hello\");}\n");
if (pfn)
pfn();
}

You can do this using a Just In Time compiler. For more
information (and pricing) just contact

jacob at jacob dot remcomp dot fr
 
J

Juha Nieminen

jacob navia said:
You can do this using a Just In Time compiler. For more
information (and pricing) just contact

jacob at jacob dot remcomp dot fr

Yeah, that's not suspicious at all.

(Come on, not even a website? Just an obscure email address?)
 
J

jacob navia

Le 12/08/11 14:07, Juha Nieminen a écrit :
Yeah, that's not suspicious at all.

(Come on, not even a website? Just an obscure email address?)

Well, you can contact me for more information at

q-software-solutions.com (pricing info)

Web site

http://www.cs.virginia.edu/~lcc-win32/

You can download a version of the compiler system (with no JIT,
just a conventional compiler) from the web site above

jacob
 
J

Jorgen Grahn

So what answer does your calculator give to system"rm -rf /"?

More explicitly: eval isn't as useful as you might think, not even in
interpreted languages, due to the security issues around it.

(By the way, system() in POSIX is in itself an eval -- it's input is
basically a shell script. Even without the eval, and even in C++, this
example would have been a problem.)

/Jorgen
 
N

Nobody

More explicitly: eval isn't as useful as you might think, not even in
interpreted languages, due to the security issues around it.

That depends upon which flavour of eval you're talking about.

Lisp's "eval" is perfectly safe; it takes an s-expression as its argument,
and evaluates that. In practical terms, this means that lists are treated
as function calls, while anything else (including a string) evaluates to
itself.

The problem is with the combined read+eval found in most other languages.
In Lisp, "read" converts a sequence of characters (either from a string or
a file) to a parse tree, while "eval" evaluates the parse tree. It's the
"read" part where security issues occur (usually in the form of injection
attacks). And most languages don't allow the two stages to be separated.
 
J

Jorgen Grahn

More explicitly: eval isn't as useful as you might think, not even in
interpreted languages, due to the security issues around it.

That depends upon which flavour of eval you're talking about.
Lisp's "eval" is perfectly safe [...]

Sorry, I was talking about imperative interpreted languages.

/Jorgen
 
N

Nobody

That depends upon which flavour of eval you're talking about.
Lisp's "eval" is perfectly safe [...]

Sorry, I was talking about imperative interpreted languages.

Lisp is frequently both of those. It's rare to see purely "functional"
Lisp code (i.e. no use of mutable state).

Also, Python does have the ability to separate the read and eval, but it's
far more work than doing the same thing in Lisp, and you have to learn the
AST (Abstract Syntax Tree) structure, which isn't something you'd
otherwise learn (OTOH, Lisp's syntax *is* the parse tree). Consequently,
hardly anyone actually uses this feature.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top