Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

SET('DEFAULT') Not returning drive and path for default directory 3

Status
Not open for further replies.

USMA99

Programmer
Oct 12, 2000
83
US
At least in the experience of some, SET('DEFAULT') returns only the drive letter rather than the drive letter and path as expected, such as SYS(5) & SYS(2003) or FULLPATH(SET('DEFAULT')) would.


There is some conjecture that this is windows-related, or perhaps not, per 1814250

Does anyone know why SET('DEFAULT') isn’t working as expected?
 
Why do you say this "isn’t working as expected"? SET("DEFAULT") has always returned just the drive letter. This is its normal behaviour. Adn it's not Windows-related. It goes all the way back to DOS versions of Foxpro and even Foxbase.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Sure, Mike?

I didn't think so. As all SET() function calls are usually the inverse of SET commands and you SET DEFAULT or C into a directory, I expect a directory, not just a drive letter.
Help on the Set function documents SET('DEFAULT') returns a cDirectory, not cDrive.

SYS(5) returns the default drive and also mentions "Use SET DEFAULT or CD to specify a default drive." But we all know C and SET DFAULT can set more than just the drive.

A lot of code uses SYS(5)+SYS(2003), I know, but what do we really have here.

Besides that point about SET('DEFAULT') is just a thing that I observed about a mishap of the program buffer that could be explained that way.

It would really be okay, if I err on this, pardon me, but then it's just one hint about why the program buffer could fail not taking into accouunt the path of a PRG. It's not a proof, just a coincidence that this path might be lost if only the drive is taken. But what do we know about how VFP decides to take a PR from the program buffer instead of the current directory. In the other thread of USMA99 I called two PRGS of same name and that gave their different return values. If one assumes the program buffer looks up what prg to run by just the prg name, it would only return what the first call returns, even if you switch default to a directory with the same name prg returning another value, wouldn't it? So the program buffer "lookup key" must respect the location of the prg.

Unless you believe the program buffer isn't imediately effective and so the ping pong of two different PRGs works for a while.

What do I say anyway, the other thread this is related to has my test code.



Chriss
 
For what it's worth, in 2.6 SET('DEFAULT') returns the drive letter only. From the help:
Code:
DEFAULT     SET("DEFAULT") returns the default
                   drive.
                   The default directory is returned by
                   SYS(2003).
 
We wrote this in the Hacker's Guide a long time ago:

For some reason, SET("DEFAULT") has never been enhanced to keep up with the times. It still returns just the drive with no path. No extra parameters or anything to let you find the path. Of course, CURDIR() provides the path. Even better, the undocumented SET("DIRECTORY") gives you the drive and path as a single string.
 
Pretty lively forum here ...

I'd say if fox never gave the full path and the help never said otherwise, drive-letter-only is WAD for SET('DEFAULT').

Nice tip on SET('DIRECTORY') ...
 
Chris,

I'm not sure I understand what you are saying. It takes a moment to test this. Enter [tt]? SET("DEFAULT")[/tt] in the command window and you will see that it only returns the drive. It's always been that way.

And there is a possible reason for that. Foxpro's predecessors, including Foxbase and dBASE, all ran under MS-DOS 1.0 (and of course similar versions of PC-DOS, DR-DOS and others). Those OSs didn't support a directory tree (hard to believe nowadays). So the "default" was always the default drive, not the default directory. With the arrival of directories, it was no problem to extend SET DEFAULT to cater for them, but doing so with SET("DEFAULT") would have meant that it returned something other than what you previously expected, and thus broke backward compatibility.

At least, that's my guess.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike Lewis said:
It takes a moment to test this
Of course I see this, but you don't seem to take in that I can't verify if that was always the case with earlier VFP versions or windows versions by executing this with just my current Windows version and VFP version. I take in that Tamar confirms this, too.

Then the help documentation of the return value of SET('DEFAULT') to be
Help on SET() function said:
cDirectory
is a documentation bug. It still makes me a bit suspicious, that the plan still was SET('DEFAULT') works like the undocumented SET('DIRECTORY').

All that aside, in the grand scheme the question was how the program buffer doesn't kick in and thus allows a construct with two same name PRGs in different directories to work. The program buffer seem to depend on how you call a PRG. And the observation about SET('DEFAULT') made it a candidate for the reason the program buffer doesn't work as expected.

At this point I want to point out that the program buffer was a topic in several threads here:
thread184-1814250
thread184-1813648
And I think at least one more I don't find right away.

Again starting with the non-ideal situation of two PRGs with same name, when and how program buffering takes place is a bit of an unsolved mystery, unless you disbelieve USMA99 saying that the pattern of SET DEFAULT TO cDirectory and then calling programs in that directory worked so far without a program buffer kicking in and executing a program with same name but from another directory. Unless recently.

The essential statement about how he executes PRGs is:
Code:
 I sometimes use DO WITH or other times use perenthesis with parameters, but without parameters I have never included the extension or parens and simply say DO basename.

I read this as calls to a basename.prg are made like

Code:
DO basename WITH param1,param2
or
Code:
basename(param1,param2)
or
Code:
DO basename

but in the case basename.prg doesn't have parameters always just
Code:
DO basename

What the application never does is a call like basename() without parameters.

Just taking the experience of my example in thread184-1814250, the reason all this worked so far may be precisely about that, because the program buffer only became active when the not used calling convention of basename() is used. So there are some more tests to be done with a PRG that has parameters and I'm now pretty sure we'd just reveal a bug in program buffering. If the program buffer would buffer all PRGs called any way we all would be much more aware of CLEAR PROGRAM and the fact that CLEAR ALL doesn't include CLEAR PROGRAM, too.

To me that's a good learning, as I can use the program buffer more effectively when knowing what makes it buffer a PRG and what not.

I'm writing all this before making more experiments instead of doing that first and I know that's some king of waste of time, as I simply could come up with final results, but I also have the feeling there will be no definite reproducible result as it may also depend on one or more settings of VFP or even Windows.

I hope I can make you more aware of the precise problem we face here. We could wipe the problem from the table as unimportant to resolve, because you simply can work by the rule of no same name PRGs or classes or anything and then the ambiguity of it is solved no matter how the program buffer works and has changed behavior. It won't matter. And while that is the solution I'd also recommend to use, it still is interesting to me to investigate further into how and when and why the program buffer works. The criticism about that I get from all sides isn't silencing that interest, sorry for however that annoys anyone, I don't want to sweep this under the rug but go deeper into that rabbit hole.

I hope even if you don't share that sentiment you at least will understand my point now.

Chriss
 
Mike Yearwood,

you still overlook a very simple thing: The program buffer doesn't kick in. When you do the two programs you do get "hello" and "world", not twice "hello", as would be expected by the program buffering.

Can we get the following recognized?
You and all others are still only picking on my wrong idea of SET('DEFAULT'). Even the first time I said it could be the reason the program buffer doesn't get the right idea what to run. But this is something you still didn't get or even didn't want to get after I already told you. The problem is, you're not alone this time in overlooking the facts that still make this an interesting case about the program buffering, not about SET('DEFAULT').

I'm about the program buffer here. I now know that you, Mike Yearwood, assume that USMA99s construct didn't ever worked and he was only lucky to never call PRGs from two directories with same name. I showed that this isn't a problem in general, only at a specific point which I still want to pin down precisely, the program buffer reused the PRG that wasn't meant to run, but this didn't happen right away. In your idea of the program buffer I'd only ever get 'hello' output and never 'world' from the PRG in the other directory.

Edit:
As you're much about performance, this should interest you, as it means there is a best practice not only in not using the construct, but about running PRGs in ways they do get into the program buffer at all.

Edit2: Further reasons to still talk about an effect that could lead to VFP not getting the right directory context:
1. In other cases where two things do the same, it is in fact documented, as in ID() and SYS(0). The help on ID() tells: "The same functionality is available by using SYS(0)".
There isn't even a dedicated help topic on SET('DEFAULT') the only mention of it is in the help topic of the general SET() function. But even at that point the documentation could tell and doesn't tell that SET('DEFAULT') has the same functionality as SYS(5)
2. Just seeing SET('DEFAULT') only returning 'C:' isn't enough evidence to know it always only returns the drive. There are functions that depend on settings, like FSIZE() depending on SET COMPATIBLE. I'm not saying that 1+1 resulting in 2 is depending on settings. You still don't seem to want to see the logical connection between such behaviors contributing to wrong workings of the program buffer. I bet what you didn't yet say but think "is obvious" is that the program buffer doesn't care about the directory anyway, it only reacts to same filename. Then perhaps it's time to look into my sample code that shows that same name doesn't instantly let the program buffer kick in.

Edit3: To state it extra: I am setting aside the effect SET('DEFAULT') could have had and take in that I have a wrong idea about it. That still doesn't turn away the fact that program buffering isn't working as expected about same PRG names.

Chriss
 
Here's something that only half confirms how I thought calling a prg with the calling convention of basename() puts itinto the program buffer:

Code:
CLEAR 
CD GETENV("Temp")
MKDIR "foo"
MKDIR "bar"
MKDIR "surprise"
STRTOFILE("?? 'hello'",".\foo\some.prg")
STRTOFILE("?? 'world'",".\bar\some.prg")
STRTOFILE("?? 'surprise'",".\surprise\some.prg")
CD foo
DO some.prg && expect and get 'hello'
FOR n=1 TO 100
   CD ..\bar
   DO some.prg && expect and get 'world'
   CD ..\foo
   DO some.prg && expect and get 'hello'
ENDFOR

? '---'
? 'call prg as funtion'
CD ..\surprise
some() && expect 'surprise', get 'world'
? '---'

FOR n=1 TO 100
   CD ..\bar
   some() && 'world'
   CD ..\foo
   some() && 'world'
ENDFOR

Here's the output:
programbuffer_kntxp3.png


This shows that %TEMP%\bar\some.prg gets buffered, neither the first called %TEMP%\foo\some.prg nor %TEMP%\surprise\some.prg

And that is a surprise, because I get confirmed that the call of some() triggers the buffer to kick in, but it kicks in with a previous call of %TEMP%\bar\some.prg. I would expect it to now start caching and then cache what I first call with some() instead of DO some.prg. What is cached seems to be random, but also backwards, is it because the cache only sinks in while VFP is in idle? And even if so, why the second call and not the first? Or why not the one that triggers caching?

If that's not getting your interest now, I don't know.

Chriss
 
Now we can turn it around in making the major aim to let program buffering do its duty and 'goddamnit' cache the executed program.

As far as I know that's not happening with DO some.prg and it's better when using some(), there are some further things to try. Getting rid of any buffered things by restarting VFP.
Now I did
Code:
CLEAR 
CD GETENV("Temp")
CD foo
DO some.prg && expect and get 'hello'
FOR n=1 TO 100
   CD ..\bar
   DO some() && expect 'world'
   CD ..\foo
   DO some() && expect 'world'
ENDFOR
And I didn't even meant to do this, The left over DO some.prg should have been removed.
It's interesting nevertheless, that it's now foo\some.prg that is buffered.

Because the output is all 'hello':
programbuffer2_m3o3om.png


So the DO some.prg call does get buffered this time and it's the call of Do %TEMP%/foo/some.prg (aka ?? 'hello').

Again, IDE restart and this time without any DO:
Code:
CLEAR 
CD GETENV("Temp")
MKDIR 'empty'
CD empty
FOR n=1 TO 100
   CD ..\foo
   some() && expect and get 'hello'
   CD ..\bar
   some() && expect 'world' or 'hello' and get 'hello'
   CD ..\surprise
   some() && expect 'surprise' or 'hello' and get 'hello'
ENDFOR

Now this is consistent with what to expect from program buffering when you also expect the cache mechanism to not pay any attention to the directory.

The question is, when sometimes Do some.prg is in fact cached and sometimes not (at least not the first call) and instead calling some() does cause buffering, but not necessarily this call is buffered, then how do you even get consistent results from calling a PRG?

Of course the simple answer is: Only having the name once in all your project items and files on HDD that could get called. But then you're only taking into account your control and not any outside PRG put somewhere, benevolent or not.

And it seems straight forward to some that buffering doesn't take the full qualified name aka full path into account at all. You could conclude that from how EXE internal images are used no matter what path code uses, even not mapped drive letters that only existed on the developer PC won't matter at runtime on a client, but why should code buffering not make a distinction of code in some specific directory? That's just short circuiting what you know from resource buffering to program buffering. There is only one caching mechanism in VFP, you say? I don't know, I wouldn't bet on that.

Chriss
 
Mike,

you're right. I didn't meant to write Do some().
Despite that error I'm still not understanding when VFP caches code in its program buffer.


Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top