Page 1 of 1 1
Topic Options
#180931 - 2007-09-28 01:57 AM Dynamically call Functions
iso Offline
Fresh Scripter

Registered: 2007-06-29
Posts: 10
I have a loop that CALLs all kix files in enabled folder. Each file contains a function. Function name is the name of the file.

/enabled/IE.kix
/enabled/ENV.kix
/enabled/NOTICE.kix

I am trying to dynamically call these functions with the function below. the CALL($EN) doesn't seem to call the corresponding function. I also tried $EN().

I can invoke them just fine with ENV() or CALL ENV
 Code:
RUN_ENABLED("C:\Docume~1\iso\Desktop\KIX\Development\enabled")

Function RUN_ENABLED($path)
  $runenabled = Dir("$path\*.*")
  While $runenabled <> "" AND @ERROR = 0
    If $runenabled <> "." AND $runenabled <> ".."
      $EN=SUBSTR("$runenabled",1,LEN($runenabled)-4)
      CALL($EN)
    EndIf
    $runenabled = Dir()
  Loop
EndFunction


Any help would be appreciated! Thanks in advance.


Edited by iso (2007-09-28 01:59 AM)

Top
#180936 - 2007-09-28 09:03 AM Re: Dynamically call Functions [Re: iso]
Björn Offline
Korg Regular
*****

Registered: 2005-12-07
Posts: 953
Loc: Stockholm, Sweden.
shouldn't CALL($EN) be CALL $EN ?
And, just a hit, but
 Code:
$runenabled='/enabled/IE.kix'
$EN=SUBSTR("$runenabled",1,LEN($runenabled)-4)
$EN ? ; - gave me "/enabled/IE"

you will need the whole filename and path to call it (IE.kix)


Edited by Björn (2007-09-28 09:09 AM)
_________________________
as long as it works - why fix it?
If it doesn't work - kix-it!

Top
#180939 - 2007-09-28 09:52 AM Re: Dynamically call Functions [Re: Björn]
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
Just as Bjorn says:
  1. You need to remember to include the path, otherwise the file will be local.
  2. You don't need to strip the suffix.
  3. CALL is a command, not a function.

Here is your code slightly modified - it should get you closer.
 Code:
RUN_ENABLED("C:\Docume~1\iso\Desktop\KIX\Development\enabled")
  
Function RUN_ENABLED($path)
  Dim $runenabled
  $runenabled = Dir("$path\*.*")
  While Not @ERROR
    If $runenabled <> "." AND $runenabled <> ".."
      Call $path+"\"+$runenabled
    EndIf
    $runenabled = Dir()
  Loop
EndFunction

Top
#181034 - 2007-10-02 04:50 PM Re: Dynamically call Functions [Re: Richard H.]
iso Offline
Fresh Scripter

Registered: 2007-06-29
Posts: 10
Each file (ie.kix, env.kix.. ) contains a function. Prior to this piece of code, these files have already been called and loaded into memory. Here I am trying to call the functions within the files. CALL ENV works if I hard code it in, however CALL $EN doesn't seem to work. The stripping is to retrieve the function names only.

Thanks for the clarifications!

Top
#181035 - 2007-10-02 05:04 PM Re: Dynamically call Functions [Re: iso]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
Here's a block of code from my KGen utility, which locates all of the UDFs in the current and defined library folders. It creates an array of UDF name and the file it exists in. You can modify this to return a simple array of UDF names (since they are already loaded and you don't need to know WHERE they are).

It requires a $PATHS variable with the names of folders to search. You could probably add your CALL statement here, since the full path is defined. The advantage of this kind of code is that it will identify all of the UDFs in a file, not just the one based on the file name. Also - the file name and UDF name don't need to match.

Glenn

 Code:
; Assemble a 2-dimensional array containing a list of function names and the files
; that hold them. Search the folders defined in the PATHS array

'Searching for available UDFs' 
For Each $PATH in $PATHS
  $File = Dir($Path + '\*.*')
  
  While $File <> '' And @ERROR = 0 
    If Left($File, 1) <> '.'

      If Right($File, 4) = '.udf' Or Right($File, 4) = '.kxf' Or $File = $SrcFile
        If $PATH = '.' And $File <> $SrcFile		; automatically include everything in '.'

          ; If the .KXF/.UDF file is in the project folder (.), just include it
          $FnFiles[$OP] = $PATH + '\' + $File	; add file to array of included files
          $OP = $OP + 1
          $ = RedirectOutput($LogFile)
          ' adding project file ' + $PATH + '\' + $File ?
          $ = RedirectOutput('')

        EndIf	; PATH = '.'

        ; open the file, read lines until 'function' is found in a non-comment area
        ; obtain the function name, and add the function name and file name to the array
        If Open(3, $Path + '\' + $File, 2) = 0

          $Line = Trim(ReadLine(3))
          While @ERROR = 0

            ; Function definition must be in column 1 after trimming spaces to be considered valid
            If InStr($Line, 'Function') = 1
              ; get rid of the 'function ' and split off the function name
              $Fn = Trim(Split(SubStr($Line, 10), '(')[0])

              $UDFNames = $UDFNames + $Fn + '(,'
              $Functions[$FP,0] = $Fn
              $Functions[$FP,1] = $PATH + '\' + $File
              $FP = $FP + 1
              If $FP Mod 8 = 0 '.' EndIf			; status indicator
            EndIf

            $Line = Trim(ReadLine(3))
          Loop	; while not error
          $ = Close(3)
        EndIf	; Open

        $FF = $FF + 1

      EndIf	; .udf or .kxf file

    EndIF	; not '.'

    $File = Dir()					; get next file

  Loop

Next ; $Path
? ' ' $FP ' UDFs located in ' $FF ' files.' ?

_________________________
Actually I am a Rocket Scientist! \:D

Top
#181046 - 2007-10-02 08:31 PM Re: Dynamically call Functions [Re: Glenn Barnas]
iso Offline
Fresh Scripter

Registered: 2007-06-29
Posts: 10
Sick! Thanks Glenn. This approach is much better.
Top
#181049 - 2007-10-02 08:53 PM Re: Dynamically call Functions [Re: iso]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
If you think that's sick/cool, go download the Kix Development kit from my web site. KGen will locate all of the UDFs in your library folder(s), parse your script, and automatically include all required UDFs into the finished script. It does this recursively, so it even resolves dependencies of one UDF on another.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#181050 - 2007-10-02 10:15 PM Re: Dynamically call Functions [Re: Glenn Barnas]
iso Offline
Fresh Scripter

Registered: 2007-06-29
Posts: 10
Glenn, is your site down?
Top
#181052 - 2007-10-02 10:34 PM Re: Dynamically call Functions [Re: iso]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
Nope.

It runs on port 2080, since it's hosted at home and 80 is blocked. Your firewall might block 2080, but that's not common. Connections to the site are automatically forwarded to port 2080.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#181056 - 2007-10-02 11:28 PM Re: Dynamically call Functions [Re: Glenn Barnas]
NTDOC Administrator Offline
Administrator
*****

Registered: 2000-07-28
Posts: 11631
Loc: CA
bummer - you now make people register to download \:\(
Top
#181058 - 2007-10-03 12:30 AM Re: Dynamically call Functions [Re: NTDOC]
iso Offline
Fresh Scripter

Registered: 2007-06-29
Posts: 10
I did some modifying of the code above and was still running into problem. So I did the following test.

This called the function loaded into memory.
 Code:
CALL "C:\Docume~1\ana\Desktop\KIX\Development\enabled\NOTICE.kix"
$test = NOTICE
CALL $test


For some reason, this code doesn't.
 Code:
Function RUN_ENABLED($path)
  $count = 0
  $runenabled = Dir("$path\*.*")
  While $runenabled <> '' AND @ERROR = 0
    If Left($runenabled, 1) <> '.'
      If Right($runenabled, 4) = '.kix'
        CALL "$path\$runenabled"
        If Open(3,"$path\$runenabled",2) = 0
          $Line = Trim(ReadLine(3))
          While @ERROR = 0
            If InStr($Line, 'Function') = 1
              $Fn = Trim(Split(SubStr($Line, 10), '(')[0])
              CALL $Fn
              ;CALL NOTICE
            EndIf
            $Line = Trim(ReadLine(3))
          Loop
        $ = Close(3)
        EndIf     
      EndIf
    EndIf
  $runenabled = Dir()
  Loop  
EndFunction




Any help would be appreciated.
Thanks!


Edited by iso (2007-10-03 12:38 AM)

Top
#181059 - 2007-10-03 01:57 AM Re: Dynamically call Functions [Re: iso]
iso Offline
Fresh Scripter

Registered: 2007-06-29
Posts: 10
A little more messing around yield the following results.

If I put NOTICE in " ", it fails to call the function
(NOTICE NOTICE)
 Code:
? $Fn
$Fn = "NOTICE"
? $Fn
CALL $Fn




If I leave out " ", it's able to call the function
(NOTICE -------)
 Code:
? $Fn
$Fn = NOTICE
? $Fn
CALL $Fn


Edited by iso (2007-10-03 01:59 AM)

Top
#181064 - 2007-10-03 05:19 AM Re: Dynamically call Functions [Re: NTDOC]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
Bummer, Doc? I already have your email addy, and you've got VPN access direct to the share - what are you gripin' about? ;\)

The registration is part of a migration to offering some commercial apps in the near future. I decided to track the downloads of the larger components more to see why people were interested, how they found it, etc. I've also sent out notifications of bugs & updates. I don't - and won't - use the info for marketing. What's coming soon, as well, is a download section that won't require registration, and provides direct view/download of Kix UDFs, Best Practice/Process documents, and detailed How-To's. I hope to have that all by early 2008.

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#181066 - 2007-10-03 05:38 AM Re: Dynamically call Functions [Re: iso]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
Couple of quick things..

$test = NOTICE <= no quotes around NOTICE

Call "$path\$runenabled" <= variables in strings - would be better as
Call $Path + '\' | $RunEnabled

Also, I guess you have something like
 Code:
$MyPath = 'c:\somewhere\enabled'
Run_Enabled($MyPath)
somewhere to call the function?

I've added some comments and debug statements to your code. Since you're only interested in .KIX files, I've eliminated the checks for "." and ".kix". Those were necessary in my example because I searched for .KXF and .UDF files.

 Code:
Function RUN_ENABLED($path)
  $count = 0
  $runenabled = Dir($path + '\*.KIX')
  While $runenabled <> '' AND @ERROR = 0
 ;;;   If Left($runenabled, 1) <> '.'
 ;;;     If Right($runenabled, 4) = '.kix'
        'Loading ' $Path + '\' + $runenabled ' into memory' ?
        CALL $path + '\' + $runenabled		; Load into memory
        If Open(3,$path + '\' + $runenabled,2) = 0 ; open the function file
          $Line = Trim(ReadLine(3)) ; read the line, remove all leading/trailing spaces
          While @ERROR = 0 			; loop until EOF error
            If InStr($Line, 'Function') = 1	; does the line contain a Function declaration?
              ; Line should look like:
              ; 1234567890123...
              ; Function MyFunc(arg)
              ; so get the data starting at the 10th char and continue to the "(" char
              $Fn = Trim(Split(SubStr($Line, 10), '(')[0])
              'Calling ' $Fn ?
              Execute ($Fn + '()' ; This string might need to be built to contain args.
              ;CALL NOTICE
            EndIf
            $Line = Trim(ReadLine(3)) 		; Get the next line
          Loop
          $ = Close(3)				; done, close the input file
        EndIf  ; open success   
 ;;;     EndIf  ; .kix file
 ;;;   EndIf  ; not a dir file
  $runenabled = Dir()				; find next file
  Loop  
EndFunction

Adding diagnostic messages in your code is an important part of development. Without them, you can only guess as to what's happening. You might want to use a RedirectOutput statement so they are saved to a log file.

Another comment - "?" is not a shortcut for the "print" command like it is in BASIC. It's actually a shortcut for the CRLF - "?" and @CRLF are interchangable, and generally would occure AFTER the text is output, not before.

Also - a personal preference with a reason. I use single quotes to surround strings unless the string contains a contraction (like "can't"), when I use double quotes. The reason is that DOS commands usually require double quotes, so - if you Shell or Run O/S commands, you'll need to surround your commands in "'" so you can embed the " chars for the O/S commands.

Glenn


Edited by Glenn Barnas (2007-10-03 01:34 PM)
Edit Reason: Adjusted for Richard's Execute correction
_________________________
Actually I am a Rocket Scientist! \:D

Top
#181080 - 2007-10-03 01:30 PM Re: Dynamically call Functions [Re: iso]
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
 Originally Posted By: iso
Each file (ie.kix, env.kix.. ) contains a function. Prior to this piece of code, these files have already been called and loaded into memory. Here I am trying to call the functions within the files. CALL ENV works if I hard code it in, however CALL $EN doesn't seem to work. The stripping is to retrieve the function names only.

Thanks for the clarifications!


I'm a little confused.

You do not use CALL to execute a function. If you have CALLed a script to load a function, then you simply use the function name to execute the function.

After re-reading this thread through I am less confused, I think I know what you are trying to do:
 Code:
RUN_ENABLED("C:\Docume~1\iso\Desktop\KIX\Development\enabled")
  
Function RUN_ENABLED($path)
  Dim $runenabled
  $runenabled = Dir("$path\*.*")
  While Not @ERROR
    If $runenabled <> "." AND $runenabled <> ".."
      Call $path+"\"+$runenabled
      $=Execute(Split($runenabled,".")[0]+"()")   ; Magic here.
    EndIf
    $runenabled = Dir()
  Loop
EndFunction


The line '$=Execute(Split($runenabled,".")[0]+"()")' is the bit of magic that you need to execute the loaded function.

Top
#181081 - 2007-10-03 01:37 PM Re: Dynamically call Functions [Re: Richard H.]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4402
Loc: New Jersey
Good catch, Richard. It seems odd to me to simply run every function in a path, especially without passing any args, so my brain was engaged in loading. I've updated my example with the Execute($Fn + '()') in the appropriate place.

Still, wondering how one can have so many UDFs that don't take any args, and even if they do, they are all Optional..

- or -

They don't contain functions at all, just external code!

Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#181858 - 2007-10-23 03:37 PM Re: Dynamically call Functions [Re: Glenn Barnas]
iso Offline
Fresh Scripter

Registered: 2007-06-29
Posts: 10
Thanks Richard. Your magic worked.
Top
Page 1 of 1 1


Moderator:  Jochen, Allen, Radimus, Glenn Barnas, ShaneEP, Ruud van Velsen, Arend_, Mart 
Hop to:
Shout Box

Who's Online
0 registered and 302 anonymous users online.
Newest Members
Sir_Barrington, batdk82, StuTheCoder, M_Moore, BeeEm
17886 Registered Users

Generated in 0.073 seconds in which 0.023 seconds were spent on a total of 13 queries. Zlib compression enabled.

Search the board with:
superb Board Search
or try with google:
Google
Web kixtart.org