sLKz / picoc

Automatically exported from code.google.com/p/picoc
0 stars 0 forks source link

<function> is out of scope -- OS X related #186

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I'm using version r603 of code, and I've found a problem that I can reproduce 
on OS X 10.8.5 using gcc 4.2.1. I have not tried to reproduce using Mavericks, 
and testing under Linux does not show a problem.

What steps will reproduce the problem?
The following cut-and-paste shows the exact details: 1) start picoc in 
interactive mode, 2) verify that printf works, 3) define and implement a simple 
function (any function seems to repro the problem), 4) try to use printf again:

Marks-iMac:picoc-603$ ./picoc -i
starting picoc v2.2 beta r603
picoc> printf("initial printf\n");
initial printf
picoc> void a()
     > {
     > }
picoc> printf("broken printf\n");
              ^
:5:7 'printf' is out of scope
picoc> 

This is not limited to affecting printf, however it does not affect everything. 
You can see here that fprintf is affected while strlen is not:
picoc> int b = strlen("test");
picoc> fprintf(stdout, "stdout test\n");
               ^
:6:8 'fprintf' is out of scope
picoc> 

NOTE: this problem appears to be related to interactive mode. The following 
shows the same input succeeding when run in script mode but failing from 
interactive mode:
Marks-iMac:picoc-603$ cat ../test 
printf("test\n");
void a() {
}
printf("test2\n");

Marks-iMac:picoc-603$ ./picoc -s ../test 
test
test2

Marks-iMac:picoc-603$ ./picoc -i
starting picoc v2.2 beta r603
picoc> printf("test\n");
test
picoc> void a() {
     > }
picoc> printf("test2\n");
              ^
:4:7 'printf' is out of scope
picoc> 

r599 appears to be the first change to exhibit this problem. I've tested r580, 
590, 595, 597, and 598 without seeing it.

Original issue reported on code.google.com by m...@heilpern.com on 30 Oct 2013 at 5:44

GoogleCodeExporter commented 9 years ago
TL;DR: there is a possible cause for this at the bottom of this update.

If I start with the r599 code base and edit parse.c to remove 4 lines of code, 
the problem goes away. Functions ParseFor() and ParseBlock() contain the 
following pattern at the head/tail; removing them suppresses the problem.

Head: int PrevScopeID = 0, ScopeID = VariableScopeBegin(Parser, &PrevScopeID);
Tail: VariableScopeEnd(Parser, ScopeID, PrevScopeID);

If I reenable those lines and add #define VAR_SCOPE_DEBUG to interpreter.h, I 
get the following edited output:
Marks-iMac:picoc-test heilpern$ ./picoc -i 
def uid_t 0 (unistd.h:1:12)
def gid_t 0 (unistd.h:1:31)
def pid_t 0 (unistd.h:1:50)
def off_t 0 (unistd.h:1:69)
def size_t 0 (unistd.h:1:88)
def ssize_t 0 (unistd.h:1:108)
def useconds_t 0 (unistd.h:1:129)
def intptr_t 0 (unistd.h:1:152)
def time_t 56957788 (time.h:1:12)
def clock_t 56957788 (time.h:1:32)
def va_list dac0dbf0 (stdio.h:1:31)
def FILE dac0dbf0 (stdio.h:1:68)
def bool 92c4ae4 (stdbool.h:1:12)
starting picoc v2.2 beta r599M
picoc> void a() {}
                  ^
:1: 
>>> out of scope: optopt 0 0
>>> out of scope: EIDRM 0 90
>>> out of scope: remove 0 1452638800
>>> out of scope: SEEK_CUR 0 1

[ many other symbols removed from this list, for brevity]

>>> out of scope: BUFSIZ 0 1024
>>> out of scope: clock 0 1452638800
>>> out of scope: setreuid 0 1452638800
picoc> printf("test\n");
              ^
:2: 'printf' is out of scope
picoc> 

Probable root cause: in VariableScopeBegin, a "ScopeID" is generated and 
returned. When run in interactive mode, Parser->SourceText (which is used to 
generate the ID) is 0, leading to a 0 ScopeID. I am assuming that this is an 
invalid scope ID and is instead assigned to all globals -- causing them to go 
out of scope when the current scope (intended to be some block with a non-zero 
scope id) closes its scope.

The full block of code at that location is:
    Parser->ScopeID = (int)(intptr_t)(Parser->SourceText) * ((int)(intptr_t)(Parser->Pos) / sizeof(char*));
    /* or maybe a more human-readable hash for debugging? */
    /* Parser->ScopeID = Parser->Line * 0x10000 + Parser->CharacterPos; */
If I comment out the first line assigning the (0) ScopeID, and instead remove 
the comments around the "human readable" line, my problem goes away.

Original comment by m...@heilpern.com on 30 Oct 2013 at 7:04

GoogleCodeExporter commented 9 years ago
One more comment… the code seems to want to set the ScopeID as a hash and 
"hope for no collisions". It seems to me that the most straight forward way to 
do this is to simply let Parser->ScopeID = OldScopeID. That is, since we can't 
have two scopes using the same address for saving the previous scope (since the 
only way to get that would include invalidating an old scope), there's no fancy 
computation needed.

Original comment by m...@heilpern.com on 30 Oct 2013 at 7:08