Announcement

Collapse
No announcement yet.

Calling a function using a variable

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Michael Mattias
    replied
    Could also do the same thing without assembly language by setting a user-defined error and RESUME linenumber.

    ie

    Code:
    %MY_ERROR =   151   ' or whatever is in range 
    
    ON ERROR GOTO Handler 
    
       IF condition  
           ERROR %MY_ERROR 
    ...
    ...
    Where_To_Restart :
         PRINT " restarted after condition was true here" 
    ...
    
    Handler:
         IF ERR = %My_ERROR THEN 
           do something 
           RESUME   Where_to_restart
           ....
    But IMO both this and "RETURN linenumber" are UGLY spaghetti code... way too many "jumps" for my taste.


    MCM

    Leave a comment:


  • Vidar Hanto
    replied
    Close enough?

    Code:
    #COMPILE EXE
    #DIM ALL
    
     MACRO ReturnToLine (LineNumber)
     ' This macro is a substitute for 'RETURN lLineNumber' as instructed by Bob Zale in this forum 2008-09-18
       ! ADD ESP, 4
       GOTO LineNumber
     END MACRO
    
    FUNCTION PBMAIN () AS LONG
    
       LOCAL sKeys AS STRING
    
       GOSUB AB
       PRINT "Will not display"
    
    
    1200  PRINT "Will display"
    
       EXIT FUNCTION
    
    AB:
       ReturnToLine (1200)
    
    END FUNCTION
    Sorry - MSGBOX in the Console Compiler forum? MSGBox replaced with PRINT
    Last edited by Vidar Hanto; 25 Sep 2008, 10:28 AM.

    Leave a comment:


  • Michael Mattias
    replied
    Looks like someone should be sending in a New Feature Suggestion...

    " Please add support for "RETURN linenumber"

    On second thought, don't do that. Trying to figure out code with lots of GOTOs is bad enough.

    MCM

    Leave a comment:


  • Bob Zale
    replied
    Originally posted by Chris Holbrook View Post
    That's handy... future proof?

    For 32-bit code... yes.

    Leave a comment:


  • Paul Dixon
    replied
    MCM,
    <<assembly language freely intermixed ..>>

    If PB didn't allow that I'd had gone elsewhere.

    Paul.

    Leave a comment:


  • Michael Mattias
    replied
    You have to love this BASIC: assembly language freely intermixed with GOTO.

    Something for everyone I guess.

    Leave a comment:


  • Chris Holbrook
    replied
    Originally posted by Bob Zale View Post
    ASM ADD ESP, 4
    GOTO 1200
    That's handy... future proof?

    Leave a comment:


  • Dan English
    replied
    Wow, thanks very much! Wouldn't exactly have guessed that...

    Leave a comment:


  • Bob Zale
    replied
    RETURN 1200 -->> substitute...

    ASM ADD ESP, 4
    GOTO 1200

    Leave a comment:


  • Dan English
    replied
    Ok, thanks guys. In regard to program flow concepts for the converted app, I think ready to go.

    Now all that's left for me is some keystroke handling conversion issues (e.g. ON KEY(3)/KEY ON/KEY OFF equivalents), and issuing a RETURN to a specific line (e.g. "RETURN 1200", in QB returns to line 1200, which can't be done in PB). To keep things on topic, I'll address these in their own threads however.

    Leave a comment:


  • Michael Mattias
    replied
    I think there are two decisions made by PB a long time ago which in hindsight PB wishes it had made differently....

    1. Making #DIM NONE the default instead of #DIM ALL. Many less problems requring intervention by the PB support department if the users (that would be you and me) had to go out our way to allow 'undeclared variables'

    2. Using the syntax "THREAD CLOSE" instead of "THREAD CLOSE HANDLE". I think this might be the 'winner' in terms of people not understanding what this statement does (notwithstanding that it's clearly documented).

    Leave a comment:


  • Mel Bishop
    replied
    As a word of note: GOSUB's are only valid in the SUB/FUNCTION calling them. Trying to GOSUB outside the sub/function won't work. I don't think it will even compile. For example, the following code is valid:
    Code:
    function DoSomething
    ...process
    ...process
    GOSUB somewhere
    ...process
    ...process
    exit function    '< To avoid a RETURN without GOSUB error message
    
    somewhere:
    ...
    ...
    return
    end function

    The following code is NOT valid. It's outside the calling function:
    Code:
    function DoSomething
    ...
    ...
    gosub somewhere
    ...
    ...
    end function
    
    somewhere:
    ...
    ...
    return
    This little detail caused me some head scratching when I was learning CC.
    Last edited by Mel Bishop; 17 Sep 2008, 07:53 PM.

    Leave a comment:


  • Dan English
    replied
    Oh, there's a huge number of GOSUBs in this code... probably shouldn't go adding many more!

    We haven't gone through 100% of the old code yet, so we may yet run into some procedures. We've browsed probably half of it though, and so far so good. Every one of the programs have been self-contained, which is very nice. Here's hoping it continues that way.

    Good advice on that #DIM ALL, thanks. It's currently set to #DIM NONE. I had wondered about that earlier, but forgot to follow up on it.

    Leave a comment:


  • Laurence Jackson
    replied
    If it helps any for a function despatch, the good old ON n GOTO/GOSUB statements are still available!

    Leave a comment:


  • Michael Mattias
    replied
    If you never had any procedures (SUBs or FUNCTIONs) in any of those programs, then making the variables LOCAL is just fine... perfect in fact and no, you don't have to rename them.

    I guess I am just used to looking at QB 4.5 which do use procedures, and because of that seem to always use SHARED or COMMON variables.

    You have lucked out big-time.

    BTW, if you have duplicate names like that, I think using #DIM ALL would be a good idea, as you never know what's lurking in an old program file. (It's also IMO a very good habit to acquire).

    Leave a comment:


  • Dan English
    replied
    Thanks for the help so far, it's much appreciated!

    Merging these into a monolithic program is actually what I've been doing up to this point.

    In the old version, there are no programs that have functions or subs. They're just straight code from first to last line. This makes it very easy to put each file into a function.

    So these:

    program1.bas
    program2.bas
    program3.bas
    ...etc...

    became these:

    FUNCTION program1() AS LONG ... END FUNCTION
    FUNCTION program2() AS LONG ... END FUNCTION
    FUNCTION program3() AS LONG ... END FUNCTION
    ...etc...

    Should I be using SUBs instead of FUNCTIONs?

    There are only less than ten COMMON vars, which I changed to GLOBAL, as per a QB->PB thread I saw here a while back.

    Is it really necessary to rename every variable from "varname" to "program_varname"? Since all these programs are in their own functions, should the scope of these non-GLOBAL vars stay within the function? I can see your point if you are doing it only for readability's sake.

    Another thing I've run into, is that the old app has duplicate var names with different data types. PB/CC doesn't like this. For example, I'd have vars like this:

    VAR1$
    VAR1

    So, I just renamed them to:

    VAR1_STR
    VAR1

    A pain, but it seems to work.

    Leave a comment:


  • Michael Mattias
    replied
    Worst case scenario to merge all into one program:

    You put SUB programname () ...END SUB around all code in each program which is not currently located in a procedure......

    I take it back.. the worst case scenario is SHARED variables with same name in each separate program ... so first thing you do is in each program do a global seach and replace of "varname" with "programname_varname".

    Then you can do the SUB.. END SUB thing.

    MCM
    (See? SHARED/GLOBAL variables are a PITA after all!)

    Leave a comment:


  • Paul D. Elliott
    replied
    Dan,

    Would it be possible to put everything in 1 program? PB CC can handle
    quite large amounts of source. I would recommend doing as Guy suggested
    and start with a clean slate as it will save a LOT of headaches later on.
    Probably most of the code will be usable with small changes. If not then
    take the time & code "what it should do" if you find that it is too sloppy
    as is.

    But if you don't want to do all that work now then redo the main program
    over in PB and copy in the old sources 1 at a time ( making what changes
    are needed ) and you can GOTO the first function of the merged program.
    You'll probably have problems with function names & making sure that all
    code is in either a function or a sub but whatever you can do to get
    it all compilable in CC will certainly help when you move on to PB Win.

    I take it that this is probably some sort of data entry program with
    built-in reports?

    I realize that this is straying far from your original question but it might
    be useful info.

    Leave a comment:


  • Kev Peel
    replied
    CodePtr() needs an actual FUNCTION/SUB name, it will not work with a variable. If you want to call functions in an EXE by literal name, you'll need some sort of translation function, as the following example shows:

    Code:
    #Compile Exe
    #Dim All
     
    Function MyFunc1() As Long
        ? "You called MyFunc1()..."
    End Function
     
    Function MyFunc2() As Long
        ? "You called MyFunc2()..."
    End Function
     
    Function Translation(ByVal sFunction As String) As Dword
      Select Case Const$ UCase$(Trim$(sFunction))
             Case "MYFUNC1": Function = CodePtr(MyFunc1)
             Case "MYFUNC2": Function = CodePtr(MyFunc2)
      End Select
    End Function
     
     
    Function PBMain
     
        Local MyFuncPtr As Dword
        Local funcName As String
     
        funcName = "MyFunc1" ' <  Try
        'funcName = "MyFunc2" ' < Either
     
        MyFuncPtr = Translation(funcName)
     
        If (MyFuncPtr) Then Call Dword MyFuncPtr
     
    End Function

    Leave a comment:


  • Dan English
    replied
    By the way, just tried an experiment with CODEPTR. Apparently, it doesn't like variables either:

    Code:
    #COMPILE EXE
    
    FUNCTION MyFunc() AS LONG
        PRINT "You called MyFunc()..."
    END FUNCTION
    
    FUNCTION PBMAIN
        LOCAL MyFuncPtr AS LONG
    
        LOCAL funcName AS STRING
        funcName = "MyFunc"
    
        ' This works
        MyFuncPtr = CODEPTR(MyFunc)
    
        ' But this doesn't
        MyFuncPtr = CODEPTR(funcName)
    
        CALL DWORD MyFuncPtr
    END FUNCTION

    Leave a comment:

Working...
X