1. program directory
Hi all. Wow, are the sparks flying in the Euphoria Listworld or what!
Hehe, frankly I find it quite amusing, if a bit tiring... No more
mention of that, though. :)
A question:
I have been wondering for a while now, how does one find out the
directory a program is in when it was run? Not the directory it was run
from, given by current_dir() or the location of ex.exe given by
examining the command_line() (the program is not bound), but the
location of the .ex file itself.
for example..
I have a program, frog.ex in the directory c:\euphoria\progs\frog. It
needs a data file in the same directory.
Say a friend of mine gets the program, installs it in windows and
double-clicks on the .ex icon. (he has .ex files calling ex.exe) My
program will then look in c:\windows or some other strange place for
it's data file, exiting ungracefully when it can't be found.
I am reluctant to specify an absolute path to the data file, after all
programs that force install into a particular directory kind of suck,
huh. I can't tell my friend to change his system configuration either,
just to run my program? no way!
An installer that writes an ini or environment variable with the
absolute location of the program is the very last contingency. Please,
nooo....
I hope I have overlooked the obvious. Most of us appear to be content
with looking in the current directory, or relative to it for data and
images, hoping the user hasn't typed something like
c:\>ex c:\euphoria\progs\frog.ex
as I suspect happens sometimes, well maybe not, but windows does this
kind of thing and one can't guarantee it won't happen after all.
Something in the form:
function get_program_dir()
(workings)
return dir
end function
so I can do the following:
bitmap_name = "frog.bmp"
program_dir = get_program_dir()
frog = read_bitmap(program_dir & "\\" & bitmap_name)
Any help is most appreciated.
------------------------------------------------------------------------------
Note for fractal lovers -- Fractal Factory is coming!
Fractal Factory will the definitive fractal program in Euphoria. Yet
another fractal program? well this one does things that even Fractint
can't do.. it's not a patch on the speed of Fractint, sure enough, but
it makes some quite startling images so far. And it's (nearly) 100%
Euphoria! I have a lot of work to do on it yet, so it won't be
available for some time to come but I have made some images and stuff
available. Come and see at http://www.alphalink.com.au/~metcalfn if
you're interested. Any suggestions, comments, ideas, input, feedback,
contributions, collaborations and more are sought.
------------------------------------------------------------------------------
Many thanks to all,
Nick
2. Re: program directory
> A question:
> I have been wondering for a while now, how does one find out the
> directory a program is in when it was run? Not the directory it was run
> from, given by current_dir() or the location of ex.exe given by
> examining the command_line() (the program is not bound), but the
> location of the .ex file itself.
include misc.e
constant cl = command_line ()
sequence s
s = reverse(cl[2])
if find ('\\', s) then
s = s[find('\\',s)..length(s)]
end if
puts (1, "The directory of the .ex file or the .exe file (when bound) is: " &
reverse (s) & '\n')
-- An explenation:
-- Command line always returns at least a 2-element-sequence.
-- { path_name_of_interpreter , path_name_of_code , ...}
With bound files, where the path and filename of the interpreter is the same as
that of the code, the first two arguments are
the same. With unbound file they are not. Most likely it will be something like
..
{ "c:\\euphoria\\bin\\ex.exe" , "c:\\projects\\progs\\frog.ex", ...}
> for example..
> I have a program, frog.ex in the directory c:\euphoria\progs\frog. It
> needs a data file in the same directory.
> Say a friend of mine gets the program, installs it in windows and
> double-clicks on the .ex icon. (he has .ex files calling ex.exe) My
> program will then look in c:\windows or some other strange place for
> it's data file, exiting ungracefully when it can't be found.
This is what 'pifs' are really for. You can tell windows for an dos-executable
what the 'target'-directory must be.
This is the default directory that applies when opening files without any path.
> I am reluctant to specify an absolute path to the data file, after all
> programs that force install into a particular directory kind of suck,
> huh. I can't tell my friend to change his system configuration either,
> just to run my program? no way!
> I hope I have overlooked the obvious. Most of us appear to be content
> with looking in the current directory, or relative to it for data and
> images, hoping the user hasn't typed something like
> c:\>ex c:\euphoria\progs\frog.ex
> as I suspect happens sometimes, well maybe not, but windows does this
> kind of thing and one can't guarantee it won't happen after all.
Well, anyways, thankfully Euphoria _is_ quite capable of telling us the
source-directory.
Good luck with your program.
Ralf
3. Re: program directory
Thanks Ralf. I suspected there was something I had overlooked, and that was
indeed it.
--Nick
Ralf Nieuwenhuijsen wrote:
> > A question:
> > I have been wondering for a while now, how does one find out the
> > directory a program is in when it was run? Not the directory it was run
> > from, given by current_dir() or the location of ex.exe given by
> > examining the command_line() (the program is not bound), but the
> > location of the .ex file itself.
>
> include misc.e
> constant cl = command_line ()
> sequence s
> s = reverse(cl[2])
> if find ('\\', s) then
> s = s[find('\\',s)..length(s)]
> end if
> puts (1, "The directory of the .ex file or the .exe file (when bound) is: " &
> reverse (s) & '\n')
>
> -- An explenation:
> -- Command line always returns at least a 2-element-sequence.
> -- { path_name_of_interpreter , path_name_of_code , ...}
>
> With bound files, where the path and filename of the interpreter is the same
> as that of the code, the first two arguments are
> the same. With unbound file they are not. Most likely it will be something
> like ..
>
> { "c:\\euphoria\\bin\\ex.exe" , "c:\\projects\\progs\\frog.ex", ...}
>
> > for example..
> > I have a program, frog.ex in the directory c:\euphoria\progs\frog. It
> > needs a data file in the same directory.
> > Say a friend of mine gets the program, installs it in windows and
> > double-clicks on the .ex icon. (he has .ex files calling ex.exe) My
> > program will then look in c:\windows or some other strange place for
> > it's data file, exiting ungracefully when it can't be found.
>
> This is what 'pifs' are really for. You can tell windows for an dos-executable
> what the 'target'-directory must be.
> This is the default directory that applies when opening files without any
> path.
>
> > I am reluctant to specify an absolute path to the data file, after all
> > programs that force install into a particular directory kind of suck,
> > huh. I can't tell my friend to change his system configuration either,
> > just to run my program? no way!
>
> > I hope I have overlooked the obvious. Most of us appear to be content
> > with looking in the current directory, or relative to it for data and
> > images, hoping the user hasn't typed something like
> > c:\>ex c:\euphoria\progs\frog.ex
> > as I suspect happens sometimes, well maybe not, but windows does this
> > kind of thing and one can't guarantee it won't happen after all.
>
> Well, anyways, thankfully Euphoria _is_ quite capable of telling us the
> source-directory.
> Good luck with your program.
>
> Ralf
4. Re: program directory
>> A question:
>> I have been wondering for a while now, how does one find out the
>> directory a program is in when it was run? Not the directory it was run
>> from, given by current_dir() or the location of ex.exe given by
>> examining the command_line() (the program is not bound), but the
>> location of the .ex file itself.
>
>include misc.e
>constant cl = command_line ()
>sequence s
>s = reverse(cl[2])
>if find ('\\', s) then
> s = s[find('\\',s)..length(s)]
>end if
>puts (1, "The directory of the .ex file or the .exe file (when bound) is: "
& reverse (s) & '\n')
>
>-- An explenation:
>-- Command line always returns at least a 2-element-sequence.
>-- { path_name_of_interpreter , path_name_of_code , ...}
>
>With bound files, where the path and filename of the interpreter is the
same as that of the code, the first two arguments are
>the same. With unbound file they are not. Most likely it will be something
like ..
>
>{ "c:\\euphoria\\bin\\ex.exe" , "c:\\projects\\progs\\frog.ex", ...}
When you run your code from an editor this is (most likely) true, however
when you type for example at the dosprompt: ex frog.ex it will be like:
{ "c:\\euphoria\\bin\\ex.exe", "frog.ex", ... }
So your routine will not show current path. The next routine should handle
this:
include file.e
include misc.e
constant cl = command_line ()
sequence s
if compare(cl[1], cl[2]) = 0 then -- Bound-file: First 2 arguments are
the same
s = reverse(cl[2])
else
if (cl[2][1] = '\\') or ((length(cl[2]) > 1) and (cl[2][2] = ':'))
-- Complete path specified as argument
s = reverse(cl[2])
else
s = reverse(current_dir() & '\\' & cl[2])
end if
end if
if find ('\\', s) then
s = s[find('\\',s)..length(s)]
end if
puts (1, "The directory of the .ex file or the .exe file (when bound) is: "
& reverse (s) & '\n')
The whole thing is has been broken down in 4 different possibilities:
1. The program is bound. Euphoria's docs state here that both the 1st as the
2nd argument specify the full-path
2. The program is called as in: ex \euphoria\progs\frog. The full path is
thus given by the user.
3. The program is called as in: ex d:\euphoria\progs\frog (note the
drive-letter). The full path is thus given by the user.
4. The program is called as in: ex frog. Now we have to figure out what
directory it is in. Since it is accessible from the current-directory, I
take the current directory as the 'base-directory' and add the second
argument to it.
Suppose I call the program now like: ex ..\frog\frog.ex, while I'm in the
directory c:\euphoria\test. The directory shown would now be:
c:\euphoria\test\..\frog\
I _know_ this is not a nice looking directory, but it is legal.
OK I can now think of another exception of calling an Euphoria program
(while or at a directory at the c-drive): ex d:frog.ex
It isn't handled correctly... yet.
>This is what 'pifs' are really for. You can tell windows for an
dos-executable what the 'target'-directory must be.
>This is the default directory that applies when opening files without any
path.
In Win yes, but it applies to DOS as well. Since you don't have to be IN the
directory to execute a program.
>> I am reluctant to specify an absolute path to the data file, after all
>> programs that force install into a particular directory kind of suck,
>> huh. I can't tell my friend to change his system configuration either,
I'm glad you did install Euphoria anyway. When I installed Euphoria I could
just choose the drive to install it on, not the directory I wanted it
in.
> c:\>ex c:\euphoria\progs\frog.ex
>> as I suspect happens sometimes, well maybe not, but windows does this
Well it DOES happen sometimes... often... always...
Bye,
Martin Schut
5. Re: program directory
> Suppose I call the program now like: ex ..\frog\frog.ex, while I'm in the
> directory c:\euphoria\test. The directory shown would now be:
> c:\euphoria\test\..\frog\
>
> I _know_ this is not a nice looking directory, but it is legal.
I've got routines that can handle such relative routines.
They're included as a class in my common.e which can be found at my site..
When I have the complete documentation finished, I'll ask Robert to put a link
to it.
You can for now, check it out for yourself: http://www.xs4all.nl/~nieuwen
The class provides 'fake' directory systems.
class my_class
my_class = default_ dir -- make a new instance out of it
my_class = fdir_down (my_class, "./windows/../windows/../windows/system") --
just changes to the windows directory
> OK I can now think of another exception of calling an Euphoria program
> (while or at a directory at the c-drive): ex d:frog.ex
>
> It isn't handled correctly... yet.
This isn't support by my routines as well, for the simple reason that I don't
keep record of the current directories among
drives. Maybe I should.
> >This is what 'pifs' are really for. You can tell windows for an
> dos-executable what the 'target'-directory must be.
> >This is the default directory that applies when opening files without any
> path.
>
> In Win yes, but it applies to DOS as well. Since you don't have to be IN the
> directory to execute a program.
True, but the problem situation discussed was about a win32 program.
Ralf
6. Re: program directory
Martin and Ralf,
Here's my solution to the program directory problem. This is based on some
very old and klunky code of mine, which I have updated and repaired with
some ideas from Ralf and Hawke'. This should work for every situation you
have addressed. If you have any problems, let me know.
------------------------------------------------------------------------
------------------------------------
-- sequence manipulation routines --
------------------------------------
function find_last(object value, sequence s)
-- return the LAST occurrence of value in sequence s
for i = length(s) to 1 by -1 do
if equal(s[i], value) then
return i
end if
end for
return 0
end function
function find_all(object value, sequence s)
-- return a list of all indexes where value is found in s
-- [Hawke''s routine -- thanks! :) ]
sequence list list = {}
for i = 1 to length(s) do
if equal(s[i], value) then
list = append(list, i)
end if
end for
return list
end function
function parse(sequence s, object x)
-- parse s based on delimiter x into a sequence of values
-- NOTE: we append x to s so we have at least one delimiter, at the end
sequence list
integer len, prev, curr
list = find_all(x, append(s, x)) -- list of delimiter positions
len = length(list)
prev = 0
for i = 1 to len do
curr = list[i]
list[i] = s[prev+1..curr-1]
prev = curr
end for
return list -- now, a list of the delimited values
end function
------------------------
-- program_location() --
------------------------
include file.e
function program_location()
-- returns a string value containing the program's location
-- returns -1 if an error occurs
sequence cmd, program, s, list
integer loc
cmd = command_line()
program = cmd[2]
loc = find_last('\\', program)
if loc then
-- the program location is included in the name
return program[1..loc]
elsif find(':', program) = 2 then
-- the program location is included in the name
return program[1..2]
else
-- verify that we have a file extension on our program name
if not find('.', program) then
cmd = cmd[1]
if match("EX.EXE", cmd) then
program &= ".ex"
elsif match("EXW.EXE", cmd) then
program &= ".exw"
else
-- ?!? This should never happen, but...
return -1
end if
end if
if sequence(dir(program)) then
-- it's in the current directory
return ""
else
-- it's somewhere in our PATH
list = parse(getenv("PATH"), ';')
for i = 1 to length(list) do
s = list[i]
if length(s) then
if sequence(dir(s & '\\' & program)) then
return s & '\\'
end if
end if
end for
end if
end if
-- the program's location was not found!
-- (this should never happen, but just in case...)
return -1
end function
------------------------------------------------------------------------
Be seeing you,
Gabriel Boehme
------
Men do not differ much about what things they will call evils; they differ
enormously about what evils they will call excusable.
G.K. Chesterton
------
7. Re: program directory
Martin and Ralf,
Here's my solution to the program directory problem. This is based on some
very old and klunky code of mine, which I have updated and repaired with
some ideas from you and Hawke'. This should work for every situation you
have addressed. If you have any problems, let me know.
------------------------------------------------------------------------
------------------------------------
-- sequence manipulation routines --
------------------------------------
function find_last(object value, sequence s)
-- return the LAST occurrence of value in sequence s
for i = length(s) to 1 by -1 do
if equal(s[i], value) then
return i
end if
end for
return 0
end function
function find_all(object value, sequence s)
-- return a list of all indexes where value is found in s
-- [Hawke''s routine -- thanks! :) ]
sequence list list = {}
for i = 1 to length(s) do
if equal(s[i], value) then
list = append(list, i)
end if
end for
return list
end function
function parse(sequence s, object x)
-- parse s based on delimiter x into a sequence of values
-- NOTE: we append x to s so we have at least one delimiter, at the end
sequence list
integer len, prev, curr
list = find_all(x, append(s, x)) -- list of delimiter positions
len = length(list)
prev = 0
for i = 1 to len do
curr = list[i]
list[i] = s[prev+1..curr-1]
prev = curr
end for
return list -- now, a list of the delimited values
end function
------------------------
-- program_location() --
------------------------
include file.e
function program_location()
-- returns a string value containing the program's location
-- returns -1 if an error occurs
sequence cmd, program, s, list
integer loc
cmd = command_line()
program = cmd[2]
loc = find_last('\\', program)
if loc then
-- the program location is included in the name
return program[1..loc]
elsif find(':', program) = 2 then
-- the program location is included in the name
return program[1..2]
else
-- verify that we have a file extension on our program name
if not find('.', program) then
cmd = cmd[1]
if match("EX.EXE", cmd) then
program &= ".ex"
elsif match("EXW.EXE", cmd) then
program &= ".exw"
else
-- ?!? This should never happen, but...
return -1
end if
end if
if sequence(dir(program)) then
-- it's in the current directory
return ""
else
-- it's somewhere in our PATH
list = parse(getenv("PATH"), ';')
for i = 1 to length(list) do
s = list[i]
if length(s) then
if sequence(dir(s & '\\' & program)) then
return s & '\\'
end if
end if
end for
end if
end if
-- the program's location was not found!
-- (this should never happen, but just in case...)
return -1
end function
------------------------------------------------------------------------
Be seeing you,
Gabriel Boehme
------
Men do not differ much about what things they will call evils; they differ
enormously about what evils they will call excusable.
G.K. Chesterton
------
8. Re: program directory
Whoops, the old code remnant strikes again! My parse() function was
unnecessarily using a separate variable for the list sequence length. Here's
the "corrected" function:
------------------------------------------------------------------------
function parse(sequence s, object x)
-- parse s based on delimiter x into a sequence of values
-- NOTE: we append x to s so we have at least one delimiter, at the end
sequence list
integer prev, curr
list = find_all(x, append(s, x)) -- list of delimiter positions
prev = 0
for i = 1 to length(list) do
curr = list[i]
list[i] = s[prev+1..curr-1]
prev = curr
end for
return list -- now, a list of the delimited values
end function
------------------------------------------------------------------------
The rest of the functions should be just fine. Please note that find_last(),
find_all() and parse() are general-purpose routines which can be used for
many other purposes.
Be seeing you,
Gabriel Boehme
------
Most modern freedom is at root fear. It is not so much that we are too bold
to endure rules; it is rather that we are too timid to endure
responsibilities.
G.K. Chesterton
------