Announcement

Collapse
No announcement yet.

Un-Used Variables Part 5 1/4 - VarDumpah

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

  • Un-Used Variables Part 5 1/4 - VarDumpah

    I have finished my app I thought I would share it.

    It searches source code for unused GLOBALs, LOCALs and DIMs and deletes them!
    You can step through the un-used variables one by one looking at
    your source code in a window and then choosing to dump them or keep
    them.

    I have tested on a project with 10 includes (some in the WinApi folder)
    it does not dump variables out of the INCLUDES it only checks them
    to verify that a GLOBAL is used.

    Teh concept is that you only need to process an Included file once
    after that its the main project file that needs processing.

    However, if you launch the app first and then drag and drop a bunch
    of files onto it, they will all be processed automatically (no user
    options tho) If you want to see whats going on and go step by step
    and create a report, drag a single file onto the icon to launch it.

    It will work for split line declarations of any kind and arrays
    declared as anything (MyType, WIN32_FIND_DATA etc etc)

    It will allow TYPEs declared anyway I know how.

    After it has deleted the un-used variables it does a little cleanup
    and you can immediatly compile your code.

    It will also create a report of the unused variables,
    if they were deleted or not, if there are local and Global vars with
    the same name, the function and line number and filename.

    I have tested it with 15 examples that between them cover all the
    permutations I could come up with. THey are below.

    The program assumes the code will compile befor you process it.

    The method I have used is a little different form the first app
    posted, but it seems robust.

    If you find any code it has trouble with pls post a short (40lines or less)
    example that illustrates the problem and Ill work on it, or you
    are welcome to develop it yourself

    Its not fast. I must admit i took the direct approach and did not
    take alot of trouble to consider the speed. Im sure it could be
    imporved upon by all you great programmers.

    Finally ater a week of this, I have two things to say to the PB guys...
    Im not worthy .... Im not worthy ....


    Examples in Source Code forum ...

    ------------------
    Kind Regards
    Mike



    [This message has been edited by Mike Trader (edited July 28, 2001).]

  • #2
    Full Code - In the source code forum now ...



    [This message has been edited by Mike Trader (edited July 28, 2001).]

    Comment


    • #3
      Michael, there is one immediate problem with the code - it rejects ALL file types. The line of code:
      Code:
          IF  TempStr <> ".BAS" OR TempStr <> ".INC" THEN ' add your flavors here ...
      should actually read:
      Code:
          IF  TempStr <> ".BAS" [b]AND[/b] TempStr <> ".INC" THEN ' add your flavors here ...

      ------------------
      Lance
      PowerBASIC Support
      mailto:[email protected][email protected]</A>
      Lance
      mailto:[email protected]

      Comment


      • #4
        Ok, I've posted my latest attempt in the Source Code forum.

        This is a heavily modified version of the original CHECKIT code.

        I've mentioned some of the changes, and added a lot of comments to
        help folks work out what I've done.

        The biggest additions are as follows:

        1. Optional parsing of WINAPI files
        2. Parsing of nested parameters in DIM statements
        3. Reporting of #INCLUDE files not located
        4. Refinements in the report format

        To do:

        1. UDT <types> are not parsed, such as in "DIM <variable> AS <type>" to identify unused TYPES (although the variables are obviously parsed.
        2. Better handling of the /I compiler path needs to be implemented. Currently this uses the PB/DLL 6.0 IDE setting, and this code does not handle multiple paths (separated by semicolons).
        3. Reporting of USED API Subs/Functions.
        4. ? Bound to be something else wrong or to be added.


        ------------------
        Lance
        PowerBASIC Support
        mailto:[email protected][email protected]</A>
        Lance
        mailto:[email protected]

        Comment


        • #5
          Nice app lance!

          Thx for finding the silly bug in my code. That was the 2am addition
          to the code (can you tell) after reading back through the thread

          ------------------
          Kind Regards
          Mike

          Comment


          • #6
            Lance, good work, but a quick test shows your code doesn't handle Globals
            declared in an Include file properly, when they are used in main file.
            First gather them, then search in all files need to be done there. Also,
            it wrongly reports a bunch of Subs/Functions in include files as un-used.
            Probably same kind of fault - main file isn't re-parsed for them.
            Also-also, some strange reports for local vars. Example:
            Code:
              LOCAL hFont AS LONG, ed AS EDM32DATA PTR : ed = GetWindowLong(hWnd, 0)
              'ed it reported as un-used..
             
              DIM tbb(20) AS STATIC TBBUTTON
              DIM IniName(bInList) AS STRING
              'AS is reported as un-used local var for both..
            It is a challenge, yes, which is why I decided to rewrite the parser
            from scratch. Nothing wrong with the already posted code, but this way,
            I feel I can understand things and see the flow better. I'm sometimes
            stupid that way and often rewrite perfectly working code from scratch,
            just to make myself understand things better..


            ------------------

            Comment


            • #7
              Thanks Borje - there is nothing like parsing someone else's writing style to show up the weak points!

              When I find time, I'll take a closer look at your GLOBAL analysis technique and maybe borrow some of the logic!



              ------------------
              Lance
              PowerBASIC Support
              mailto:[email protected][email protected]</A>
              Lance
              mailto:[email protected]

              Comment


              • #8
                Borje, you code is simply excellent, no question! I think I'll abandon my pursuit of the original CheckIt.Bas now!

                However, your code too has a couple of problems.

                For example, I have a statement: GLOBAL gprinters() AS STRING and in PBMAIN i have a statement DIM gprinters(1:1) AS GLOBAL STRING. Your parsing engine says I have a variable that is both local and global. Also, the reference count is shown as -1.

                If I change the like to a REDIM, then your code reports it correctly.

                I also have a lot of code that I have cut/paste DECLARE's from WIN32API.INC, etc. Rather than reporting these functions as "declared but not present", it would be better to parse out the LIB clause and exclude these from the list if they reference one of the common system DLL's (Kernel32, User32, etc).

                If I ever manage to find some more time, I'll see if I can help solve the problems.

                Keep up the good work!

                ------------------
                Lance
                PowerBASIC Support
                mailto:[email protected][email protected]</A>
                Lance
                mailto:[email protected]

                Comment


                • #9
                  Okay, I see the problem and have just uploaded a fix. Now it looks for
                  " LIB " when "DECLARE " flag has been set and excludes such declarations.

                  Also, in DoProcess, under label ExtractLine, I added code to scan line
                  with colons and replace those inside paranthesis with something else.
                  Seems to work fine. Also changed from deleting text within double quotes
                  to simply blank it out. Same result, but should be a bit faster.

                  Still a lot left to do with it, like what you pointed out - parsing for
                  multiple include dirs, etc, but it'll get there some day..


                  ------------------

                  Comment


                  • #10
                    Borje,

                    I have been studying your code. I have learnt alot form this whole
                    execise about how you pros write. If I knew the language better I
                    think i would have cover more in VarDumpah.

                    I have a couple of questions ..
                    why do write like this:

                    FUNCTION DoProcess(BYVAL TheFile AS STRING, BYVAL fNum AS LONG, WhatRun AS LONG) AS LONG
                    '
                    ' GOSUB ExtractLine
                    '
                    EXIT FUNCTION

                    '---------------------------------------------------------
                    ' Extract line from main text
                    '---------------------------------------------------------
                    ExtractLine:
                    '
                    '
                    RETURN

                    Why Not just declare the Sub:
                    FUNCTION DoProcess(BYVAL TheFile AS STRING, BYVAL fNum AS LONG, WhatRun AS LONG) AS LONG
                    '
                    ' GOSUB ExtractLine
                    '
                    EXIT FUNCTION

                    '---------------------------------------------------------
                    ' Extract line from main text
                    '---------------------------------------------------------
                    SUB ExtractLine
                    '
                    '
                    RETURN

                    I assume this is slower??
                    Is it that much slower?

                    Also in general, why do some people use DIM over LOCAL?
                    Ive never been clear on the practical difference in use

                    LOCAL ci AS LONG, p AS LONG, Letter AS BYTE PTR ' etc
                    vs.
                    DIM ci AS LONG, p AS LONG, Letter AS BYTE PTR ' etc

                    also, why cant you declare GLOBAL arrays the same way you can
                    LOCAL arrays?
                    ie:

                    GLOBAL tmpFiles(4) AS STRING
                    vs.
                    FUNCTION DoGetIncFiles(BYVAL TheFile AS STRING) AS LONG
                    '
                    REDIM tmpFiles(4) AS STRING

                    I am realizing that I have to check any array DIM or REDIM statements
                    against the GLOBAL declarations of arrays in case the DIM is just
                    dimensioning a GLOBAL array rather than declaring and dimensioning
                    a LOCAL array.

                    I got a little writing to do...


                    ------------------
                    Kind Regards
                    Mike

                    Comment


                    • #11
                      borje,

                      from my vantage point, your program is behaving perfectly with one exception.
                      i keep downloading your latest, hoping that you have changed this one problem.

                      in my code, i declare all of my global arrays in an include file.
                      i then dimension them in a sub of the main file as shown below:

                      'include file -----------
                      global myarray as string

                      'main file --------------
                      sub initialize()
                      dim myarray(100)

                      i should point out that myarray() is not referenced again in sub initialize,
                      but is used many, many times in other subs.

                      your program reports myarray as an unused local variable. but the compiler
                      treats it as global, not local. in fact, if the dim is changed to redim,
                      your program reports correctly. i don't believe redim should treat a
                      variable's scope any different than the dim statement. once, a variable
                      is declared as a global, then unless it is explicitly declared local in a sub,
                      it must be treated as a global variable.

                      ref lance's responce july 25: http://www.powerbasic.com/support/pb...ead.php?t=4092
                      borje, that syntax is allowed. the "as global" portion is currently optional,
                      but recommended for clarity (to avoid scope confusion).

                      if you have problems when omitting the "as global" clause, there must be some
                      other issue in the code affecting the scope of the variable/array.
                      i believe borje, that your pbcodec program is destined to become nearly as
                      popular as your remarkable poffs program, so please keep perfecting it.


                      ------------------

                      Comment


                      • #12
                        I have included better array handling and fixed a few bugs in VarDumpah.
                        The latest version is in the Source Code Forum.

                        If you use it to find and delete unused variables in its own code
                        this is a good test due to all the words like GLOBAL LOCAL etc used in it.

                        You can drag and drop multiple files at once. It processed 11 files
                        (and the 11 includes in each file) in the project that prompted
                        this program development.

                        I love Borje and Lances work, your code is more sophisticated
                        than mine but I have about 100 unused variables in 11 apps.
                        I dont want to take the time to go thru each one deleting all them.

                        ------------------
                        Kind Regards
                        Mike

                        [This message has been edited by Mike Trader (edited July 29, 2001).]

                        Comment


                        • #13
                          Okay, think I have it fixed now - new file uploaded. Had to check DIM
                          more carefully, since DIM/REDIM may have been preceeded with a GLOBAL
                          declare of same variable. Seems to work now..

                          Just remember one thing - this whole project is result of many people's
                          work, all originating from question from Mike, code by Scott Slater and
                          extensive help and tips from a bunch of helpful souls, where Lance of
                          course has an honorary chair. I am just one of the piano players here.
                          Once again, the powerful PB community has spoken..


                          ------------------

                          Comment


                          • #14
                            Borje,
                            tiny bug ...

                            Code:
                                 CASE %WM_TIMER
                                     KILLTIMER  CBHNDL, 1
                                     CALL DoInitProcess(CBHNDL, Files(1))
                            
                            should be
                            
                                 CASE %WM_TIMER
                                     KILLTIMER  CBHNDL, 1
                                     CALL DoInitProcess(CBHNDL, Files(0))
                            Great app!

                            any chance of a quick answer to my questions above

                            ------------------
                            Kind Regards
                            Mike

                            Comment


                            • #15
                              Thanks Mike, fixed and uploaded. Well, I'll try to answer: Using labels and
                              GOTO or GOSUB inside a Function or Sub is *much* faster. GOTO is fastest,
                              but I like GOSUB because RETURN makes life so easy. Personally, I also think
                              it's easier to follow flow when labels have been used inside same routine,
                              instead of external calls, but that's me - I know many disagree with me there..

                              DIM vs LOCAL is sometimes a mystery to me too. LOCAL allocates memory on the
                              stack and can take advantage of "automatically" becoming register variables,
                              if there are any registers available and REGISTER NONE *not* have been used.

                              If using LOCAL, it can differ a lot if most used variables are declared first,
                              since the chance of ending up as register variable is higher. Can of course be
                              over-ridden by stating #REGISTER NONE and then use: REGISTER var AS LONG..

                              DIM probably uses the global heap (?), which makes it a bit more flexible,
                              but documentation states they both are strictly local, which is true, until
                              DIM is used to redim a global variable. Sometimes, the compiler is to kind
                              to us, I think. One should have to use REDIM on global vars, because in a
                              huge project, it can be easy to forgot that what you think is DIM'd as a
                              local var/array, in fact becomes a REDIM'd global one. No big deal and
                              to late to change, but DIM, IMHO, can be source for confusion, so I prefer
                              using LOCAL and GLOBAL when I can.

                              Like Tom has pointed out several times, it's wise to use a prefix in name,
                              like g_var for globals vars, etc, but for many of us, that means to change
                              old habits. I have tried, but always fall back on stupid "blind" naming.
                              You obviously can't teach old dogs like me to sit..


                              ------------------

                              Comment


                              • #16
                                Foremostly, DIM simply declares a variable.

                                If the DIM statement does not specify scope (with an "AS LOCAL/STATIC/GLOBAL" clause) and the variable is already declared GLOBAL within the code, PowerBASIC simply uses that variable (hence the variable in that Sub/Function will use the GLOBAL variable of the same name).

                                To explicitly define the scope of a variable, you should use the LOCAL or STATIC statements, or DIM..AS LOCAL/STATIC/GLOBAL.

                                Clear as mud?

                                ------------------
                                Lance
                                PowerBASIC Support
                                mailto:[email protected][email protected]</A>
                                Lance
                                mailto:[email protected]

                                Comment


                                • #17
                                  Borje, I just downloaded your latest, and my problem still exists in pbcodec.
                                  Here is a simple example illustrating the probem:
                                  pbcodec reports that myArray is an unused local variable.

                                  Code:
                                  'main file: "problem.bas" -------------------
                                  
                                  #COMPILE EXE
                                  #INCLUDE "Problem.inc"
                                  
                                  FUNCTION PBMAIN
                                     initialize
                                     myArray(1) = "Try this string"
                                     MSGBOX "Done"
                                  END FUNCTION
                                  
                                  SUB initialize
                                     DIM myArray(100)
                                  END SUB
                                  
                                  
                                  'include file: "problem.inc ------------------
                                  GLOBAL myArray() AS STRING
                                  DECLARE SUB initialize
                                  ------------------


                                  [This message has been edited by Charles Dietz (edited July 30, 2001).]

                                  Comment


                                  • #18
                                    Of course it couldn't work, because I'm an idiot. Not easy when your
                                    mind is on vacation. Previous fix: 1, collect local vars, 2, compare
                                    local's array against global's array. 3, collect global vars.

                                    Can you see the error? Nothing to compare with in step 2. Sigh! Ok,
                                    now it stores the type of declare for local DIM and do the compare
                                    against global's array just before report. Tested on your situation
                                    Charles and it seems to handle it properly.

                                    Fixed file uploaded to http://www.tolken99.com/pb/pbcodec.zip

                                    ------------------

                                    Comment


                                    • #19
                                      Borje, It fixed the simple example, but not my real application.
                                      I took a look at your code, and it looks to me like there is a mistake on
                                      line # 841.

                                      You have: ARRAY DELETE lVars(cTmp - 1)
                                      should be: ARRAY DELETE lVars(I)

                                      Line #847 may be the same error.


                                      ------------------

                                      Comment


                                      • #20
                                        See, I told you my mind is on vacation.. Thanks a lot, just uploaded
                                        fixed file. Second part there, on AllLocals, was okay though.


                                        ------------------

                                        Comment

                                        Working...
                                        X