Using a function that doesn't exist =\

I

Itay

While going through the code of the open source project PCSX2
(www.pcsx2.net - PS2 emulator for windows and linux. source code can be
d/led from here: http://tinyurl.com/6242p), I saw a strange (at least
for me...) thing:
in the R5900.h header (hmm..emulating a CPU...), there's a struct which
looks like this:
typedef struct {
int (*Init)();
void (*Reset)();
void (*Step)();
void (*Execute)();
void (*ExecuteBlock)();
void (*ExecuteVU0Block)();
void (*ExecuteVU1Block)();
void (*EnableVU0micro)(int enable);
void (*EnableVU1micro)(int enable);
void (*Clear)(u32 Addr, u32 Size);
void (*ClearVU0)(u32 Addr, u32 Size);
void (*ClearVU1)(u32 Addr, u32 Size);
void (*Shutdown)();
} R5900cpu;

and then

R5900cpu *Cpu;

and somewhere in R5900.c:

Cpu->ExecuteBlock();

ExecuteBlock is not defined anywhere. I did a "search in files" in the
whole project, and the whole project dir...Only references to
ExecuteBlock found..no definition. What's going on here?!

It must be found somehwere, because it's in a function that's - CMIIW -
always called (indirectly) from WinMain ...and it doesn't make sense
that it's accidently there...
Any explanation?

thanks,

Itay
 
E

Eric Sosman

Itay said:
While going through the code of the open source project PCSX2
(www.pcsx2.net - PS2 emulator for windows and linux. source code can be
d/led from here: http://tinyurl.com/6242p), I saw a strange (at least
for me...) thing:
in the R5900.h header (hmm..emulating a CPU...), there's a struct which
looks like this:
typedef struct {
int (*Init)();
void (*Reset)();
void (*Step)();
void (*Execute)();
void (*ExecuteBlock)();
void (*ExecuteVU0Block)();
void (*ExecuteVU1Block)();
void (*EnableVU0micro)(int enable);
void (*EnableVU1micro)(int enable);
void (*Clear)(u32 Addr, u32 Size);
void (*ClearVU0)(u32 Addr, u32 Size);
void (*ClearVU1)(u32 Addr, u32 Size);
void (*Shutdown)();
} R5900cpu;

and then

R5900cpu *Cpu;

and somewhere in R5900.c:

Cpu->ExecuteBlock();

ExecuteBlock is not defined anywhere. I did a "search in files" in the
whole project, and the whole project dir...Only references to
ExecuteBlock found..no definition. What's going on here?!

It must be found somehwere, because it's in a function that's - CMIIW -
always called (indirectly) from WinMain ...and it doesn't make sense
that it's accidently there...
Any explanation?

The things in the struct are *pointers* to functions,
not function names. Somewhere you should find something
like

void frammis();
...
Cpu->ExecuteBlock = frammis;

.... and once this has been done, `Cpu->ExecuteBlock()'
behaves as if you had written `frammis()' instead. What
you need to do is find the assignment or initialization,
make note of the name assigned ("frammis"), and then search
for the function with that name.
 
K

Keith Thompson

ItayP said:
Can't find it anywhere!
What's going on here? =\

Sorry, I have no idea what you're talking about, since you didn't
provide any context (and my news server doesn't have the parent
article).

As we've said here many many times:

"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers."
 
I

ItayP

Ok...Sorry for not knowing about the broken reply link.
I was told that there must be somewhere something similar to that:
void frammis();
...
Cpu->ExecuteBlock = frammis;
(shouldn't it be &frammis?)
anyway, I couldn't find anything similar..
 
K

Keith Thompson

Please don't top-post. Your reply should be after, or interspersed
with, any quoted text, which should be trimmed to what's necessary for
context.

ItayP said:
Itay wrote: [...]
and somewhere in R5900.c:

Cpu->ExecuteBlock();

ExecuteBlock is not defined anywhere. I did a "search in files" in
the whole project, and the whole project dir...Only references to
ExecuteBlock found..no definition. What's going on here?!
[...]

Ok...Sorry for not knowing about the broken reply link.
I was told that there must be somewhere something similar to that:
void frammis();
...
Cpu->ExecuteBlock = frammis;
(shouldn't it be &frammis?)
anyway, I couldn't find anything similar..

Right. Cpu is a pointer to an object of some struct type. One of the
members of the struct, a pointer-to-function, is named ExecuteBlock.
So ExecuteBlock is the name of the struct member, not the name of a
function.

If frammis is a function compatible with the declaration of
ExecuteBlock, then assigning

Cpu->ExecuteBlock = frammis;

allows you to call frammis indirectly as:

Cpu->ExecuteBlock();

The assignment is the most straightforward way to set the value of
Cpu->ExecuteBlock, but it's not the only way. I would exect a global
search for ExecuteBlock to find the assignment unless something ugly
is being done (like setting it in an assembly language routine,
perhaps?).

The assignment does not require the "&" operator. A reference to a
function name is implicitly converted to a pointer to the function
(unless it's the operand of a sizeof or "&" operator; in the case of
sizeof the result is an illegal expression). So you can use &frammis
if you like, but just frammis is ok.

Note that a function call is one of the contexts in which a function
name is implicitly converted to a pointer. A function call is
effectively an operator whose first operad is a value of an
appropriate pointer-to-function type, so even an ordinary function
call:
myfunc(1, 2);
is really an indirect call through a pointer. (Of course an
implementation is free to optimize this to a more direct form in the
generated code as long as the result is the same.)

Here's a (rather silly) illustration:

#include <stdio.h>
void myfunc(int n)
{
printf("myfunc(%d)\n", n);
}

int main(void)
{
myfunc(1);
(&myfunc)(2);
(*&myfunc)(3);
(*myfunc)(4);
(**myfunc)(5);
(***myfunc)(6);
(*&*&*myfunc)(7);
return 0;
}
 
O

Old Wolf

Itay said:
typedef struct {
int (*Init)();
void (*Reset)();
void (*Step)();
void (*Execute)();
void (*ExecuteBlock)();
void (*ExecuteVU0Block)();
void (*ExecuteVU1Block)();
void (*EnableVU0micro)(int enable);
void (*EnableVU1micro)(int enable);
void (*Clear)(u32 Addr, u32 Size);
void (*ClearVU0)(u32 Addr, u32 Size);
void (*ClearVU1)(u32 Addr, u32 Size);
void (*Shutdown)();
} R5900cpu;

and then

R5900cpu *Cpu;

and somewhere in R5900.c:

Cpu->ExecuteBlock();

ExecuteBlock is not defined anywhere. I did a "search in files"
in the whole project, and the whole project dir...
Only references to ExecuteBlock found..no definition.

Perhaps it is initialized rather than assigned. If you
search for 'Cpu' you should see where it's assigned to
something (obviously you can't write Cpu-> ..... without
first setting Cpu to point to something).

For example the code might be something like:

R5900cpu foo =
{ &foo_Init, &foo_Reset, &foo_Stop, ............ };

and then

Cpu = &foo;
Cpu->Init();
 
C

Carlos

Keith said:
[...]
The assignment is the most straightforward way to set the value of
Cpu->ExecuteBlock, but it's not the only way. I would exect a global
search for ExecuteBlock to find the assignment unless something ugly
is being done (like setting it in an assembly language routine,
perhaps?).

Maybe *Cpu was assigned a struct literal?

--
 
I

ItayP

if (Config.Cpu) Cpu = &intCpu;
#ifdef __i386__
else Cpu = &recCpu;
#endif

Ahaaa!!! :D

Keith said:
Please don't top-post. Your reply should be after, or interspersed
with, any quoted text, which should be trimmed to what's necessary for
context.

ItayP said:
Itay wrote: [...]
and somewhere in R5900.c:

Cpu->ExecuteBlock();

ExecuteBlock is not defined anywhere. I did a "search in files" in
the whole project, and the whole project dir...Only references to
ExecuteBlock found..no definition. What's going on here?!
[...]

Ok...Sorry for not knowing about the broken reply link.
I was told that there must be somewhere something similar to that:
void frammis();
...
Cpu->ExecuteBlock = frammis;
(shouldn't it be &frammis?)
anyway, I couldn't find anything similar..

Right. Cpu is a pointer to an object of some struct type. One of the
members of the struct, a pointer-to-function, is named ExecuteBlock.
So ExecuteBlock is the name of the struct member, not the name of a
function.

If frammis is a function compatible with the declaration of
ExecuteBlock, then assigning

Cpu->ExecuteBlock = frammis;

allows you to call frammis indirectly as:

Cpu->ExecuteBlock();

The assignment is the most straightforward way to set the value of
Cpu->ExecuteBlock, but it's not the only way. I would exect a global
search for ExecuteBlock to find the assignment unless something ugly
is being done (like setting it in an assembly language routine,
perhaps?).

The assignment does not require the "&" operator. A reference to a
function name is implicitly converted to a pointer to the function
(unless it's the operand of a sizeof or "&" operator; in the case of
sizeof the result is an illegal expression). So you can use &frammis
if you like, but just frammis is ok.

Note that a function call is one of the contexts in which a function
name is implicitly converted to a pointer. A function call is
effectively an operator whose first operad is a value of an
appropriate pointer-to-function type, so even an ordinary function
call:
myfunc(1, 2);
is really an indirect call through a pointer. (Of course an
implementation is free to optimize this to a more direct form in the
generated code as long as the result is the same.)

Here's a (rather silly) illustration:

#include <stdio.h>
void myfunc(int n)
{
printf("myfunc(%d)\n", n);
}

int main(void)
{
myfunc(1);
(&myfunc)(2);
(*&myfunc)(3);
(*myfunc)(4);
(**myfunc)(5);
(***myfunc)(6);
(*&*&*myfunc)(7);
return 0;
}
San Diego Supercomputer Center <*>
We must do something. This is something. Therefore, we must do
this.
 
K

Keith Thompson

ItayP said:
if (Config.Cpu) Cpu = &intCpu;
#ifdef __i386__
else Cpu = &recCpu;
#endif

Ahaaa!!! :D
[snip]

Read this again, carefully:

Please don't top-post. Your reply should be after, or interspersed
with, any quoted text, which should be trimmed to what's necessary
for context.
 

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

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top