Esempio n. 1
0
static int l_persist_dofile(lua_State *L)
{
    const char *sFilename = luaL_checkstring(L, 1);
    lua_settop(L, 1);

    // Read entire file into memory
    FILE *fFile = fopen(sFilename, "r");
    if(fFile == NULL)
    {
        const char *sError = strerror(errno);
        return luaL_error(L, "cannot open %s: %s", sFilename, sError);
    }
    size_t iBufferSize = lua_objlen(L, lua_upvalueindex(1));
    size_t iBufferUsed = 0;
    while(!feof(fFile))
    {
        iBufferUsed += fread(reinterpret_cast<char*>(lua_touserdata(L,
            lua_upvalueindex(1))) + iBufferUsed, 1, iBufferSize - iBufferUsed, fFile);
        if(iBufferUsed == iBufferSize)
        {
            iBufferSize *= 2;
            memcpy(lua_newuserdata(L, iBufferSize), lua_touserdata(L, lua_upvalueindex(1)), iBufferUsed);
            lua_replace(L, lua_upvalueindex(1));
        }
        else
            break;
    }
    int iStatus = ferror(fFile);
    fclose(fFile);
    if(iStatus)
    {
        const char *sError = strerror(errno);
        return luaL_error(L, "cannot read %s: %s", sFilename, sError);
    }

    // Check file
    char *sFile = reinterpret_cast<char*>(lua_touserdata(L, lua_upvalueindex(1)));
    sFile[iBufferUsed] = 0;
    if(sFile[0] == '#')
    {
        do
        {
          ++sFile;
          --iBufferUsed;
        } while(sFile[0] != 0 && sFile[0] != '\r' && sFile[0] != '\n');
    }
    if(sFile[0] == LUA_SIGNATURE[0])
    {
        return luaL_error(L, "cannot load %s: compiled files not permitted", sFilename);
    }

    // Load and do file
    lua_pushliteral(L, "@");
    lua_pushvalue(L, 1);
    lua_concat(L, 2);
    if(luaL_loadbuffer(L, sFile, iBufferUsed, lua_tostring(L, -1)) != 0)
        return lua_error(L);
    lua_remove(L, -2);
    int iBufferCopyIndex = lua_gettop(L);
    memcpy(lua_newuserdata(L, iBufferUsed + 1), sFile, iBufferUsed + 1);
    lua_insert(L, -2);
    lua_call(L, 0, LUA_MULTRET);
    sFile = reinterpret_cast<char*>(lua_touserdata(L, lua_upvalueindex(1)));
    memcpy(sFile, lua_touserdata(L, iBufferCopyIndex), iBufferUsed + 1);
    lua_remove(L, iBufferCopyIndex);

    // Extract persistable functions
    const char *sPosition = sFile;
    while(true)
    {
        sPosition = strstr(sPosition, "--[[persistable:");
        if(!sPosition)
            break;
        sPosition += 16;
        const char *sNameEnd = strstr(sPosition, "]]");
        if(sNameEnd)
        {
            int iLineNumber = CalculateLineNumber(sFile, sNameEnd);
            const char *sFunctionArgs = strchr(sNameEnd + 2, '(');
            const char *sFunctionEnd = FindFunctionEnd(L, sFunctionArgs);
            if((sNameEnd - sPosition) == 1 && *sPosition == ':')
            {
                // --[[persistable::]] means take the existing name of the function
                sPosition = strstr(sNameEnd, "function") + 8;
                sPosition += strspn(sPosition, " \t");
                sNameEnd = sFunctionArgs;
                while(sNameEnd[-1] == ' ')
                    --sNameEnd;
            }
            if(iLineNumber != -1 && sFunctionArgs && sFunctionEnd)
            {
                // Save <filename>:<line> => <name>
                lua_pushfstring(L, "%s:%d", sFilename, iLineNumber);
                lua_pushvalue(L, -1);
                lua_gettable(L, lua_upvalueindex(2));
                if(lua_isnil(L, -1))
                {
                    lua_pop(L, 1);
                    lua_pushlstring(L, sPosition, sNameEnd - sPosition);
                    lua_settable(L, lua_upvalueindex(2));
                }
                else
                {
                    return luaL_error(L, "Multiple persistable functions defin"
                        "ed on the same line (%s:%d)", sFilename, iLineNumber);
                }

                // Save <name> => <filename>
                lua_pushlstring(L, sPosition, sNameEnd - sPosition);
                lua_pushvalue(L, -1);
                lua_gettable(L, lua_upvalueindex(3));
                if(lua_isnil(L, -1))
                {
                    lua_pop(L, 1);
                    lua_pushvalue(L, 1);
                    lua_settable(L, lua_upvalueindex(3));
                }
                else
                {
                    return luaL_error(L, "Persistable function name \'%s\' is"
                        " not unique (defined in both %s and %s)",
                        lua_tostring(L, -2), lua_tostring(L, -1), sFilename);
                }

                // Save <name> => <code>
                lua_pushlstring(L, sPosition, sNameEnd - sPosition);
                lua_pushliteral(L, "\n");
                lua_getfield(L, -1, "rep");
                lua_insert(L, -2);
                lua_pushinteger(L, iLineNumber - 1);
                lua_call(L, 2, 1);
                lua_pushliteral(L, "function");
                lua_pushlstring(L, sFunctionArgs, sFunctionEnd - sFunctionArgs);
                lua_concat(L, 3);
                lua_settable(L, lua_upvalueindex(4));
            }
        }
    }

    // Finish
    return lua_gettop(L) - 1;
}
void ToDoListView::ParseBuffer(const wxString& buffer, const wxString& filename)
{
    // this is the actual workhorse...

    HighlightLanguage hlang = Manager::Get()->GetEditorManager()->GetColourSet()->GetLanguageForFilename(filename);
    CommentToken cmttoken = Manager::Get()->GetEditorManager()->GetColourSet()->GetCommentToken(hlang);
    wxString langName = Manager::Get()->GetEditorManager()->GetColourSet()->GetLanguageName(hlang);

    m_ItemsMap[filename].clear();

    wxArrayString allowedTypes;
    size_t t = 0;
    while(t < m_Types.Count())
    {
        if(m_pAllowedTypesDlg->IsChecked(m_Types.Item(t)))
            allowedTypes.Add(m_Types.Item(t));
        t++;
    }

    wxArrayString startStrings;
    if (langName == _T("C/C++") )
    {
        startStrings.Add(_T("#warning"));
        startStrings.Add(_T("#error"));
    }
    if (!cmttoken.doxygenLineComment.IsEmpty())
        startStrings.Add(cmttoken.doxygenLineComment);
    if (!cmttoken.doxygenStreamCommentStart.IsEmpty())
        startStrings.Add(cmttoken.doxygenStreamCommentStart);

    if ( !cmttoken.lineComment.IsEmpty() )
        startStrings.Add(cmttoken.lineComment);
    if ( !cmttoken.streamCommentStart.IsEmpty() )
        startStrings.Add(cmttoken.streamCommentStart);

    if ( startStrings.IsEmpty() || allowedTypes.IsEmpty() )
    {
        Manager::Get()->GetLogManager()->Log(_T("ToDoList: Warning: No to-do types or comment symbols selected to search for, nothing to do."));
        return;
    }

    for ( unsigned k = 0; k < startStrings.size(); k++)
    {
        size_t pos = 0;
        int oldline=0, oldlinepos=0;
        while (1)
        {
            pos = buffer.find(startStrings[k], pos);
            if ( pos == (size_t)wxNOT_FOUND )
                break;

            pos += startStrings[k].length();
            SkipSpaces(buffer, pos);

            for (unsigned int i = 0; i < allowedTypes.GetCount(); ++i)
            {
                wxString type = buffer.Mid(pos, allowedTypes[i].length());
                if ( type != allowedTypes[i])
                    continue;
                pos += allowedTypes[i].length();
                SkipSpaces(buffer, pos);

                ToDoItem item;
                item.type = allowedTypes[i];
                item.filename = filename;


                // ok, we look for two basic kinds of todo entries in the text
                // our version...
                // TODO (mandrav#0#): Implement code to do this and the other...
                // and a generic version...
                // TODO: Implement code to do this and the other...

                wxChar c = buffer.GetChar(pos);
                // is it ours or generic todo?
                if (c == _T('('))
                {
                    // it's ours, find user and/or priority
                    ++pos;
                    while(pos < buffer.length() && buffer.GetChar(pos) != _T('\r') && buffer.GetChar(pos) != _T('\n'))
                    {
                        wxChar c1 = buffer.GetChar(pos);
                        if (c1 != _T('#') && c1 != _T(')'))
                        {
                            // a little logic doesn't hurt ;)
                            if (c1 == _T(' ') || c1 == _T('\t'))
                            {
                                // allow one consecutive space
                                if (item.user.Last() != _T(' '))
                                    item.user << _T(' ');
                            }
                            else
                                item.user << c1;
                        }
                        else if (c1 == _T('#'))
                        {
                            // look for priority
                            c1 = buffer.GetChar(++pos);
                            const wxString allowedChars = _T("0123456789");
                            if ((int)allowedChars.Index(c1) != wxNOT_FOUND)
                                item.priorityStr << c1;
                            // skip to start of date
                            while (pos < buffer.length() && buffer.GetChar(pos) != _T('\r') && buffer.GetChar(pos) != _T('\n') )
                            {
                                wxChar c2 = buffer.GetChar(pos);
                                if ( c2 == _T('#'))
                                {
                                    pos++;
                                    break;
                                }
                                if ( c2 == _T(')') )
                                    break;
                                pos++;
                            }
                            // look for date
                            while (pos < buffer.length() && buffer.GetChar(pos) != _T('\r') && buffer.GetChar(pos) != _T('\n') )
                            {
                                wxChar c2 = buffer.GetChar(pos++);
                                if (c2 == _T(')'))
                                    break;
                                item.date << c2;
                            }

                            break;
                        }
                        else if (c1 == _T(')'))
                        {
                            ++pos;
                            break;
                        }
                        else
                            break;
                        ++pos;
                    }
                }
                // ok, we 've reached the actual todo text :)
                // take everything up to the end of line
                if( buffer.GetChar(pos) == _T(':'))
                    ++pos;
                size_t idx = pos;
                while (buffer.GetChar(idx) != _T('\r') && buffer.GetChar(idx) != _T('\n'))
                    idx++;
                item.text = buffer.Mid(pos, idx-pos);

                // do some clean-up
                item.text.Trim();
                item.text.Trim(false);
                item.user.Trim();
                item.user.Trim(false);
                wxDateTime date;
                if ( !date.ParseDate(item.date.wx_str()) )
                {
                    item.date.clear(); // not able to parse date so clear the string
                }
                item.line = CalculateLineNumber(buffer, pos, oldline, oldlinepos);
                item.lineStr << wxString::Format(_T("%d"), item.line + 1); // 1-based line number for list
                m_ItemsMap[filename].push_back(item);
                m_Items.Add(item);

                pos = idx;
            }
            pos ++;
        }
    }
}