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

new topic     » topic index » view message » categorize

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

new topic     » goto parent     » topic index » view message » categorize

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

new topic     » goto parent     » topic index » view message » categorize

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

new topic     » goto parent     » topic index » view message » categorize

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 blink

> 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

new topic     » goto parent     » topic index » view message » categorize

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
 ------

new topic     » goto parent     » topic index » view message » categorize

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
 ------

new topic     » goto parent     » topic index » view message » categorize

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
 ------

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu