Sign in to follow this  
Followers 0
Valik

Code To Fix Include() Recursion

6 posts in this topic

Here's the code I used to get more recursion from Include(). You might check to make sure I used the right buffer sizes later on in the script for szBuffer. I didn't actually test this with any scripts, only with an infinite loop of includes like CyberSlug originally posted. On the two systems I tried, it ran to 100 and displayed the error box like it was supposed to (Systems were both XP Pro, one was clean install, the other was SP-2. The clean install was running in a virtual machine with 256 MB of RAM while the one with SP-2 was a real machine with 512MB of RAM.

I don't know about a fix for Aut2Exe, I'm not familar with it's internal workings, but it also has issues with include depth, hopefully this fix is translatable to how it works.

I also added comments to your empty if statement, I think that might be the not version of that statement, but I'm not positive. It is a bugger to figure out.

P.S. Jon, did you get the code I submitted to your email yesterday for ConvertBase? I just want to make sure it sent okay as I was having issues with my email client at the time.

bool AutoIt_ScriptFile::Include(const char *szFileName, int nIncludeID)
{
    char            szDrive[_MAX_DRIVE+1];
    char            szDir[_MAX_DIR+1];
    char            szFname[_MAX_FNAME+1];
    char            szExt[_MAX_EXT+1];
    char            *szFilePart;
    char            szOldWorkingDir[_MAX_PATH+1];
    char            szWorkingDir[_MAX_PATH+1];
    char            szFullFileName[_MAX_PATH+1];    // Full path of current file to include

//  char            szBuffer[65535+1];
//  char            szTemp[65535+1];
    char            szBuffer[AUT_MAX_LINESIZE];
    char            szTemp[_MAX_PATH+1];
    int             nLineNum = 1;               // Line# in .aut file
    FILE            *fptr;
    bool            bErr = true;
    bool            bNextLineAppend = false;    // If true the next line read should be appended
    bool            bContinuationFound;
    int             nLen;
    static int nRecurse = 0;    // Don't forget to decrement on the way out...

    if (++nRecurse > 100)   // increment, then compare (This size may need lowered...)
    {
        Util_FatalError("AutoIt", "#include depth too large, > 100", NULL);
        --nRecurse;
        return false;
    }

    // Open a handle to the script file
    fptr = fopen(szFileName, "r");              // ASCII read
    if ( fptr == NULL  )                        // File error
    {
        strcpy(szBuffer, "Error reading the file:\n\n");
        strcat(szBuffer, szFileName);
        Util_FatalError("AutoIt", szBuffer, NULL);
        --nRecurse;
        return false;
    }

    // Get the current working directory
    GetCurrentDirectory(_MAX_PATH, szOldWorkingDir);

    // Get the FULL PATH of the filename we are working with (for future use with IsInlcudedOnceOnly)
    GetFullPathName(szFileName, _MAX_PATH, szFullFileName, &szFilePart);

    // Set the working directory based on the filename we just opened - NOTE this will BREAK any further calls
    // to GetFullPathName for the currently loaded file which uses the working directory to resolve!
    _splitpath( szFullFileName, szDrive, szDir, szFname, szExt );
    strcpy(szWorkingDir, szDrive);
    strcat(szWorkingDir, szDir);
    SetCurrentDirectory(szWorkingDir);


    // Read in lines of text until EOF is reached or error occurs
    while ( fgets(szBuffer, AUT_MAX_LINESIZE-1, fptr) && bErr == true)  // Leave room for \0
    {
        // Enforce our maximum line length (must be smaller than szBuffer!) and then
        // strip all trailing and leading whitespace
        szBuffer[AUT_MAX_LINESIZE] = '\0';
        StripLeading(szBuffer);             // Only required in AutoIt
        StripTrailing(szBuffer);            // Strip trailing

        // Check for the #includeonce directive (don't check on line continuation)
        if (bNextLineAppend == false && IsIncludeOnceOnly(szBuffer, szFullFileName) == true)
        {
            SetCurrentDirectory(szOldWorkingDir);   // Restore the old working directory
            --nRecurse;
            return true;                        // No error, just return
        }

        // Don't check for #include if we are continuing previous line
        if ( bNextLineAppend == false && IncludeParse(szBuffer, szTemp) == true )
        {
            bErr = Include(szTemp, AddIncludeName(szTemp)); // Get the include file
        }
        else
        {
            // If the line is blank or a comment line AND we are not continuing then ignore it 
            // Have to check continutation for cases like "jjjjjj   _;jjjj"
            if ( (szBuffer[0] == '\0' || szBuffer[0] == ';') && bNextLineAppend == false )
            {
                // Couldn't think of NOT version of the above...
                // Would this work?
                // if (szBuffer[0] != '\0' && szBuffer[0] != ';' || bNextLineAppend == true)
            }
            else
            {
                // Check if the last character is requesting a continuation
                nLen = (int)strlen(szBuffer);
                if (nLen && szBuffer[nLen-1] == '_')
                {
                    szBuffer[nLen-1] = '\0';        // Erase the continuation char
                    bContinuationFound = true;
                }
                else
                    bContinuationFound = false;

                // Was previous line a continuation?
                if (bNextLineAppend == true)
                    AppendLastLine(szBuffer);
                else
                    AddLine(nLineNum, szBuffer, nIncludeID );

                if (bContinuationFound == true)
                    bNextLineAppend = true;
                else
                    bNextLineAppend = false;
            }
        }
        
        nLineNum++;                             // Increment the line number

    } // End While

    // Close our script file
    fclose(fptr);

    SetCurrentDirectory(szOldWorkingDir);       // Restore the old working directory

    --nRecurse;
    return bErr;

} // Include()

Share this post


Link to post
Share on other sites



You get the email I sent that had this code, Jon?

Share this post


Link to post
Share on other sites

Quick related question: When do you need #include, as opposed to #include-once. I can't think of any situations. Could #include --> #include-once?


blub

Share this post


Link to post
Share on other sites

#Include includes the text of the given file (hopefully .au3) in the current location of the script.

#Include-Once says that if the current script file gets #Include'd more than once, then ignore the subsequent #Include's. Do this when you specify functions and constants in your include function.

You can include the same code in several locations in your script to cause the same thing happen in each place. I would tend to use a function here, but that is just me. :whistle:


David Nuttall
Nuttall Computer Consulting

An Aquarius born during the Age of Aquarius

AutoIt allows me to re-invent the wheel so much faster.

I'm off to write a wizard, a wonderful wizard of odd...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0