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 ++; } } }