Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

LuaState.cpp

Go to the documentation of this file.
00001 
00002 // This source file is part of the LuaState (Lua Wrapper) source distribution
00003 // and is Copyright 2000-2001 by Joshua C. Jensen (jjensen@workspacewhiz.com).
00004 // The latest version may be obtained from http://www.workspacewhiz.com/.
00005 //
00006 // The code presented in this file may be freely used and modified for all
00007 // non-commercial and commercial purposes.
00009 #include "LuaState.h"
00010 #ifdef WIN32
00011 #include <windows.h>
00012 #undef GetObject
00013 #endif WIN32
00014 #pragma warning(disable: 4786)
00015 #include <list>
00016 #include <string>
00017 #include <algorithm>
00018 #include <stdio.h>
00019 #include <string.h>
00020 #include "LuaStateFunctions.h"
00021 #pragma warning(disable: 4786)
00022 
00023 //-----------------------------------------------------------------------------
00024 extern "C"
00025 {
00026 #include "lualib.h"
00027 }
00028 
00029 static int LS_LOG(LuaState state)
00030 {
00031     LuaObject obj(state, 1);
00032 #ifdef WIN32
00033     OutputDebugStringA(obj.GetString());
00034     OutputDebugStringA("\n");
00035 #else
00036     printf("%s\n", obj.GetString());
00037 #endif
00038     return 0;
00039 }
00040 
00041 
00044 static int LS_WriteLuaObject(LuaState state)
00045 {
00046     FILE* stdioFile = (FILE *)LuaObject(state, 1).GetUserData();
00047     LuaObject nameObj(state, 2);
00048     LuaObject valueObj(state, 3);
00049     LuaObject indentLevelObj(state, 4);
00050     LuaObject writeAllObj(state, 5);
00051     LuaObject alphabeticalObj(state, 6);
00052     LuaObject maxIndentLevelObj(state, 7);
00053     bool writeAll = !writeAllObj.IsNil()  &&  writeAllObj.GetInteger() != 0;
00054     bool alphabetical = !alphabeticalObj.IsNil()  &&  alphabeticalObj.GetInteger() != 0;
00055     int maxIndentLevel = maxIndentLevelObj.IsNumber() ? maxIndentLevelObj.GetInteger() : 0xFFFFFFFF;
00056 
00057     LuaStateOutFile file;
00058     file.Assign(stdioFile);
00059     state.WriteLuaObject(file, nameObj.GetString(), valueObj, indentLevelObj.GetInteger(), writeAll, alphabetical, false, maxIndentLevel);
00060 
00061     return 0;
00062 }
00063 
00064 
00067 static int LS_WriteLuaFile(LuaState state)
00068 {
00069     LPCSTR fileName = state.ToString(1);
00070     FILE* file = fopen(fileName, "wt");
00071     if (!file)
00072     {
00073         state.PushBool(false);
00074         return 1;
00075     }
00076     LuaObject nameObj(state, 2);
00077     LuaObject valueObj(state, 3);
00078     LuaObject indentLevelObj(state, 4);
00079     LuaObject writeAllObj(state, 5);
00080     LuaObject alphabeticalObj(state, 6);
00081     LuaObject maxIndentLevelObj(state, 7);
00082     bool writeAll = !writeAllObj.IsNil()  &&  writeAllObj.GetInteger() != 0;
00083     bool alphabetical = !alphabeticalObj.IsNil()  &&  alphabeticalObj.GetInteger() != 0;
00084     int maxIndentLevel = maxIndentLevelObj.IsNumber() ? maxIndentLevelObj.GetInteger() : 0xFFFFFFFF;
00085 
00086     LuaStateOutFile stdFile;
00087     stdFile.Assign(file);
00088     state.WriteLuaObject(stdFile, nameObj.GetString(), valueObj,
00089             indentLevelObj.GetInteger(), writeAll, alphabetical, false, maxIndentLevel);
00090     fclose(file);
00091 
00092     state.PushBool(true);
00093     return 1;
00094 }
00095 
00096 
00099 static int LS_WriteLuaGlobalsFile(LuaState state)
00100 {
00101     LPCSTR fileName = state.ToString(1);
00102     LuaObject writeAllObj(state, 2);
00103     LuaObject alphabeticalObj(state, 3);
00104     LuaObject maxIndentLevelObj(state, 4);
00105     bool writeAll = !writeAllObj.IsNil()  &&  writeAllObj.GetInteger() != 0;
00106     bool alphabetical = !alphabeticalObj.IsNil()  &&  alphabeticalObj.GetInteger() != 0;
00107     int maxIndentLevel = maxIndentLevelObj.IsNumber() ? maxIndentLevelObj.GetInteger() : 0xFFFFFFFF;
00108 
00109     state.WriteLuaGlobalsFile(fileName, writeAll, alphabetical, false, maxIndentLevel);
00110 
00111     state.PushBool(true);
00112     return 1;
00113 }
00114 
00115 
00118 static void FatalError()
00119 {
00120     throw -1;
00121 }
00122 
00123 
00126 static void LSLock(void* data)
00127 {
00128     CRITICAL_SECTION* cs = (CRITICAL_SECTION*)data;
00129     ::EnterCriticalSection(cs);
00130 }
00131 
00132 
00135 static void LSUnlock(void* data)
00136 {
00137     CRITICAL_SECTION* cs = (CRITICAL_SECTION*)data;
00138     ::LeaveCriticalSection(cs);
00139 }
00140 
00141 
00144 LuaStateOwner::LuaStateOwner(bool initStandardLibrary, DWORD stackSize, bool multithreaded)
00145 {
00146     m_state = lua_open(stackSize);
00147 
00148     if (multithreaded)
00149     {
00150         // What about clean up?
00151         CRITICAL_SECTION* cs = new CRITICAL_SECTION;
00152         ::InitializeCriticalSection(cs);
00153         lua_setlockfunctions(m_state, LSLock, LSUnlock, cs);
00154     }
00155     
00156     Init(initStandardLibrary, stackSize);
00157 }
00158 
00159 
00162 LuaStateOwner::LuaStateOwner(LuaState& script, bool initStandardLibrary, DWORD stackSize)
00163 {
00164     m_state = lua_newthread(script, stackSize);
00165     Init(initStandardLibrary, stackSize);
00166 }
00167 
00168 
00169 extern "C" int lua_dumplibopen (lua_State *L);
00170 
00173 void LuaStateOwner::Init(bool initStandardLibrary, DWORD stackSize)
00174 {
00175     // Register some basic functions with Lua.
00176     if (initStandardLibrary)
00177     {
00178         lua_baselibopen(m_state);
00179         lua_iolibopen(m_state);
00180         lua_strlibopen(m_state);
00181         lua_mathlibopen(m_state);
00182         lua_dblibopen(m_state);
00183         lua_dumplibopen(m_state);
00184 
00185         ScriptFunctionsRegister(m_state);
00186 
00187         Register("WriteLuaObject", LS_WriteLuaObject);
00188         Register("WriteLuaFile", LS_WriteLuaFile);
00189         Register("WriteLuaGlobalsFile", LS_WriteLuaGlobalsFile);
00190     }
00191 
00192     Register("LOG", LS_LOG);
00193     Register("_ALERT", LS_LOG);
00194 
00195     lua_setfatalerrorfunction(m_state, FatalError);
00196 }
00197 
00198 
00203 int LuaState::ConfigGetInteger(const char* section, const char* entry,
00204                              int defaultValue)
00205 {
00206     return static_cast<int>(ConfigGetReal(section, entry, defaultValue));
00207 }
00208 
00209 
00214 float LuaState::ConfigGetReal(const char* section, const char* entry,
00215                             double defaultValue)
00216 {
00217     LuaAutoBlock block(*this);
00218 
00219     LuaObject obj = GetGlobal(section);
00220     if (obj.IsNil())
00221         return (float)defaultValue;
00222     obj = obj.GetByName(entry);
00223     if (obj.IsNumber())
00224         return obj.GetNumber();
00225     return (float)defaultValue;
00226 }
00227 
00228 
00233 const char* LuaState::ConfigGetString(const char* section, const char* entry,
00234                                     const char* defaultValue)
00235 {
00236     LuaAutoBlock block(*this);
00237 
00238     LuaObject obj = GetGlobal(section);
00239     if (obj.IsNil())
00240         return defaultValue;
00241     obj = obj.GetByName(entry);
00242     if (obj.IsString())
00243         return obj.GetString();
00244     return defaultValue;
00245 }
00246 
00247 
00251 void LuaState::ConfigSetInteger(const char* section, const char* entry, int value)
00252 {
00253     LuaAutoBlock block(*this);
00254 
00255     // section.entry = value
00256     // Difficult in code.  Do it this way.
00257     LuaObject sectionTable = GetGlobal(section);
00258 
00259     // If the global table isn't there, then create it.
00260     if (sectionTable.IsNil())
00261     {
00262         sectionTable = GetGlobals().CreateTable(section);
00263     }
00264 
00265     sectionTable.SetNumber(entry, value);
00266 }
00267 
00268 
00272 void LuaState::ConfigSetReal(const char* section, const char* entry, double value)
00273 {
00274     LuaAutoBlock block(*this);
00275 
00276     // section.entry = value
00277     // Difficult in code.  Do it this way.
00278     LuaObject sectionTable = GetGlobal(section);
00279 
00280     // If the global table isn't there, then create it.
00281     if (sectionTable.IsNil())
00282     {
00283         sectionTable = GetGlobals().CreateTable(section);
00284     }
00285 
00286     sectionTable.SetNumber(entry, value);
00287 }
00288 
00289 
00293 void LuaState::ConfigSetString(const char* section, const char* entry, const char* value)
00294 {
00295     LuaAutoBlock block(*this);
00296 
00297     // section.entry = value
00298     // Difficult in code.  Do it this way.
00299     LuaObject sectionTable = GetGlobal(section);
00300 
00301     // If the global table isn't there, then create it.
00302     if (sectionTable.IsNil())
00303     {
00304         sectionTable = GetGlobals().CreateTable(section);
00305     }
00306 
00307     sectionTable.SetString(entry, value);
00308 }
00309 
00310 
00314 static void IndentFile(LuaStateOutFile& file, unsigned int indentLevel)
00315 {
00316     // Write out indentation.
00317     char spaces[500];
00318     for (unsigned int i = 0; i < indentLevel; ++i)
00319         spaces[i] = '\t';
00320     spaces[i] = 0;
00321     file.Print(spaces);
00322 }
00323 
00324 bool LuaState::WriteLuaObject(FILE* stdioFile, const char* name, LuaObject value,
00325                              int indentLevel, bool writeAll, bool alphabetical,
00326                              bool writeTablePointers, unsigned int maxIndentLevel)
00327 {
00328     LuaStateOutFile file;
00329     file.Assign(stdioFile);
00330     WriteLuaObject(file, name, value, indentLevel, writeAll, alphabetical,
00331             writeTablePointers, maxIndentLevel);
00332     return false;
00333 }   
00334 
00335 
00336 static void luaI_addquotedbinary (LuaStateOutFile& file, lua_State *L, const char* s, int l)
00337 {
00338     file.Print("%c", l_c('"'));
00339     while (l--)
00340     {
00341         switch (*s)
00342         {
00343             case l_c('"'):  case l_c('\\'):
00344                 file.Print("\\%c", *s);
00345                 break;
00346             case l_c('\a'):     file.Print("\\a");      break;
00347             case l_c('\b'):     file.Print("\\b");      break;
00348             case l_c('\f'):     file.Print("\\f");      break;
00349             case l_c('\n'):     file.Print("\\n");      break;
00350             case l_c('\r'):     file.Print("\\r");      break;
00351             case l_c('\t'):     file.Print("\\t");      break;
00352             case l_c('\v'):     file.Print("\\v");      break;
00353             default:
00354                 if (isprint((BYTE)*s))
00355                     file.Print("%c", *s);
00356                 else
00357                 {
00358                     file.Print("\\%03d", (BYTE)*s);
00359                 }
00360         }
00361         s++;
00362     }
00363     file.Print("%c", l_c('"'));
00364 }
00365 
00366 
00367 static void luaI_addquotedwidebinary (LuaStateOutFile& file, lua_State *L, const wchar_t* s, int l)
00368 {
00369     file.Print("L\"");
00370     while (l--)
00371     {
00372         switch (*s)
00373         {
00374             case l_uc('"'):
00375             case l_uc('\\'):
00376                 file.Print("\\%c", *s);
00377                 break;
00378             case l_uc('\a'):        file.Print("\\a");      break;
00379             case l_uc('\b'):        file.Print("\\b");      break;
00380             case l_uc('\f'):        file.Print("\\f");      break;
00381             case l_uc('\n'):        file.Print("\\n");      break;
00382             case l_uc('\r'):        file.Print("\\r");      break;
00383             case l_uc('\t'):        file.Print("\\t");      break;
00384             case l_uc('\v'):        file.Print("\\v");      break;
00385             default:
00386                 if (*s < 256  &&  isprint((BYTE)*s))
00387                 {
00388                     file.Print("%c", *s);
00389                 }
00390                 else
00391                 {
00392                     file.Print("\\x%04x", (DWORD)*s);
00393                 }
00394         }
00395         s++;
00396     }
00397     file.Print("\"");
00398 }
00399 
00400 
00404 bool LuaState::WriteLuaObject(LuaStateOutFile& file, const char* name, LuaObject value,
00405                          int indentLevel, bool writeAll, bool alphabetical,
00406                          bool writeTablePointers, unsigned int maxIndentLevel)
00407 {
00408     LuaState script = value;
00409     
00410     // If there is nothing in the variable, then don't write it.
00411     if (value.IsNil())
00412         return false;
00413 
00414     // If the variable is user data or a function, then don't write it.
00415     if (value.IsUserData()  ||  value.IsFunction()  ||  value.IsCFunction())
00416     {
00417         if (writeAll  &&  name)
00418         {
00419             if (value.IsUserData())
00420                 file.Print("-- %s = '!!!USERDATA!!!'\n", name);
00421             else if (value.IsFunction())
00422             {
00423                 lua_Debug ar;
00424                 PushValue(value);
00425                 lua_getinfo(m_state, ">S", &ar);
00426 //              printf("%d\n", ar.linedefined);
00427                 file.Print("-- %s = '!!!FUNCTION!!! %s %d'\n", name, ar.source, ar.linedefined);
00428             }
00429             else
00430                 file.Print("-- %s = '!!!CFUNCTION!!!'\n", name);
00431             return true;
00432         }
00433         return false;
00434     }
00435 
00436     // Indent the line the number of spaces for the current indentation level.
00437     const unsigned int INDENT_SIZE = 1;
00438     const unsigned int indentSpaces = (indentLevel == -1 ? 0 : indentLevel) * INDENT_SIZE;
00439     IndentFile(file, indentSpaces);
00440     
00441     // If the object has a name, write it out.
00442     if (name)
00443         file.Print("%s = ", name);
00444 
00445     // If the object's value is a number, write it as a number.
00446     if (value.IsNumber())
00447         file.Print("%.16g", value.GetNumber());
00448 
00449     // Or if the object's value is a string, write it as a quoted string.
00450     else if (value.IsString())
00451     {
00452         luaI_addquotedbinary(file, m_state, value.GetString(), value.StrLen());
00453     }
00454 
00455     // Or if the object's value is a string, write it as a quoted string.
00456     else if (value.IsUString())
00457     {
00458         luaI_addquotedwidebinary(file, m_state, value.GetUString(), value.StrLen());
00459     }
00460 
00461     // Otherwise, see if the object's value is a table.
00462     else if (value.IsTable())
00463     {
00464         // Write the table header.
00465         if (indentLevel != -1)
00466         {
00467             if (indentLevel < maxIndentLevel)
00468             {
00469                 file.Print("\n");
00470                 IndentFile(file, indentSpaces);
00471             }
00472             if (writeTablePointers)
00473                 file.Print("{ --%8x\n", lua_topointer(m_state, value));
00474             else
00475                 file.Print("{");
00476             if (indentLevel < maxIndentLevel)
00477             {
00478                 file.Print("\n");
00479             }
00480         }
00481 
00482         // Rename, just for ease of reading.
00483         LuaObject table = value;
00484 
00485         // upperIndex is the upper index value of a sequential numerical array
00486         // items.
00487         int upperIndex = 1;
00488         bool wroteSemi = false;
00489         bool hasSequential = false;
00490 
00491         // Block to search for array items.
00492         {
00493             // Pop the stack state when done.
00494             LuaAutoBlock block(*this);
00495 
00496             // Grab index 1 and index 2 of the table.
00497             LuaObject value1 = table.GetByIndex(1);
00498             LuaObject value2 = table.GetByIndex(2);
00499 
00500             // If they both exist, then there is a sequential list.
00501             if (!value1.IsNil()  &&  !value2.IsNil())
00502             {
00503                 // Cycle through the list.
00504                 bool firstSequential = true;
00505                 for (; ; ++upperIndex)
00506                 {
00507                     // Restore the stack state each iteration.
00508                     LuaAutoBlock block(*this);
00509 
00510                     // Try retrieving the table entry at upperIndex.
00511                     LuaObject value = table.GetByIndex(upperIndex);
00512 
00513                     // If it doesn't exist, then exit the loop.
00514                     if (value.IsNil())
00515                         break;
00516 
00517                     // Only add the comma and return if not on the first item.
00518                     if (!firstSequential  &&  indentLevel != -1)
00519                     {
00520                         file.Print(",");
00521                         if (indentLevel < maxIndentLevel)
00522                         {
00523                             file.Print("\n");
00524                         }
00525                     }
00526                     
00527                     // Write the object as an unnamed entry.
00528                     WriteLuaObject(file, NULL, value, indentLevel + 1, writeAll, alphabetical, writeTablePointers, maxIndentLevel);
00529 
00530                     // We've definitely passed the first item now.
00531                     firstSequential = false;
00532                 }
00533             }
00534         }
00535 
00536         // Did we find any sequential table values?
00537         if (upperIndex > 1)
00538         {
00539             hasSequential = true;
00540         }
00541         
00542         if (alphabetical)
00543         {
00544             std::list<std::string> keyNames;
00545 
00546             // Cycle through the table.
00547             int i;
00548             PushNil();
00549             while ((i = Next(table)) != 0)
00550             {
00551                 char keyName[255];
00552 
00553                 // Retrieve the table entry's key and value.
00554                 LuaObject key(this, GetTop() - 1);
00555 
00556                 // Is the key a number?
00557                 if (key.IsNumber())
00558                 {
00559                     // Yes, were there sequential array items in this table?
00560                     if (hasSequential)
00561                     {
00562                         // Is the array item's key an integer?
00563                         float realNum = key.GetNumber();
00564                         int intNum = (int)realNum;
00565                         if (realNum == (float)intNum)
00566                         {
00567                             // Yes.  Is it between 1 and upperIndex?
00568                             if (intNum >= 1  &&  intNum < upperIndex)
00569                             {
00570                                 // We already wrote it as part of the sequential
00571                                 // list.
00572                                 Pop();
00573                                 continue;
00574                             }
00575                         }
00576                     }
00577 
00578                     // Build the table entry name for the number.
00579                     sprintf(keyName, "[%.16g]", key.GetNumber());
00580                 }
00581                 else
00582                 {
00583                     // Build the table entry name for the string key name.
00584                     const char* ptr = key.GetString();
00585                     bool isAlphaNumeric = true;
00586                     while (*ptr)
00587                     {
00588                         if (!isalnum(*ptr)  &&  *ptr != '_')
00589                         {
00590                             isAlphaNumeric = false;
00591                             break;
00592                         }
00593                         ptr++;
00594                     }
00595                     if (isAlphaNumeric)
00596                         strcpy(keyName, key.GetString());
00597                     else
00598                         sprintf(keyName, "[\"%s\"]", key.GetString());
00599                 }
00600 
00601                 keyNames.push_back(keyName);
00602 
00603                 // Go to the next item.
00604                 Pop();
00605             }
00606 
00607             keyNames.sort();
00608 
00609             if (keyNames.size() > 0)
00610             {
00611                 // If we wrote a sequential list, the value we're about to write
00612                 // is not nil, and we haven't written the semicolon to separate
00613                 // the sequential table entries from the keyed table entries...
00614                 if (hasSequential  &&  indentLevel != -1)
00615                 {
00616                     // Then add a comma (for good measure) and the semicolon.
00617                     file.Print(", ;");
00618                     if (indentLevel < maxIndentLevel)
00619                     {
00620                         file.Print("\n");
00621                     }
00622                     wroteSemi = true;
00623                 }
00624             }
00625 
00626             for(std::list<std::string>::iterator it = keyNames.begin(); it != keyNames.end(); ++it)
00627             {
00628                 LuaAutoBlock autoBlock(*this);
00629                 const std::string& keyFullName = (*it);
00630 
00631                 LuaObject value = table;        // Temp
00632                 if (keyFullName[0] == '[')
00633                 {
00634                     if (keyFullName[1] == '"')
00635                     {
00636                         std::string keyName = keyFullName.substr(2, keyFullName.size() - 4);
00637                         value = table.GetByName(keyName.c_str());
00638                     }
00639                     else
00640                     {
00641                         std::string keyName = keyFullName.substr(1, keyFullName.size() - 2);
00642                         int number = atoi(keyName.c_str());
00643                         value = table.GetByIndex(number);
00644                     }
00645                 }
00646                 else
00647                 {
00648                     value = table.GetByName(keyFullName.c_str());
00649                 }
00650 
00651                 // Write the table entry.
00652                 bool ret = WriteLuaObject(file, keyFullName.c_str(), value, indentLevel + 1, writeAll, alphabetical, writeTablePointers, maxIndentLevel);
00653 
00654                 // Add a comma after the table entry.
00655                 if (indentLevel != -1  &&  ret)
00656                 {
00657                     file.Print(",");
00658                     if (indentLevel < maxIndentLevel)
00659                     {
00660                         file.Print("\n");
00661                     }
00662                 }
00663             }
00664         }
00665         else
00666         {
00667             // Cycle through the table.
00668             int i;
00669             PushNil();
00670             while ((i = Next(table)) != 0)
00671             {
00672                 char keyName[255];
00673 
00674                 // Retrieve the table entry's key and value.
00675                 LuaObject key(this, GetTop() - 1);
00676                 LuaObject value(this, GetTop());
00677 
00678                 // Is the key a number?
00679                 if (key.IsNumber())
00680                 {
00681                     // Yes, were there sequential array items in this table?
00682                     if (hasSequential)
00683                     {
00684                         // Is the array item's key an integer?
00685                         float realNum = key.GetNumber();
00686                         int intNum = (int)realNum;
00687                         if (realNum == (float)intNum)
00688                         {
00689                             // Yes.  Is it between 1 and upperIndex?
00690                             if (intNum >= 1  &&  intNum < upperIndex)
00691                             {
00692                                 // We already wrote it as part of the sequential
00693                                 // list.
00694                                 Pop();
00695                                 continue;
00696                             }
00697                         }
00698                     }
00699 
00700                     // Build the table entry name for the number.
00701                     sprintf(keyName, "[%.16g]", key.GetNumber());
00702                 }
00703                 else
00704                 {
00705                     // Build the table entry name for the string key name.
00706                     const char* ptr = key.GetString();
00707                     bool isAlphaNumeric = true;
00708                     while (*ptr)
00709                     {
00710                         if (!isalnum(*ptr)  &&  *ptr != '_')
00711                         {
00712                             isAlphaNumeric = false;
00713                             break;
00714                         }
00715                         ptr++;
00716                     }
00717                     if (isAlphaNumeric)
00718                         strcpy(keyName, key.GetString());
00719                     else
00720                         sprintf(keyName, "[\"%s\"]", key.GetString());
00721                 }
00722 
00723                 // If we wrote a sequential list, the value we're about to write
00724                 // is not nil, and we haven't written the semicolon to separate
00725                 // the sequential table entries from the keyed table entries...
00726                 if (hasSequential  &&  !value.IsNil()  &&  !wroteSemi)
00727                 {
00728                     // Then add a comma (for good measure) and the semicolon.
00729                     if (indentLevel != -1)
00730                     {
00731                         file.Print(", ;");
00732                         if (indentLevel < maxIndentLevel)
00733                         {
00734                             file.Print("\n");
00735                         }
00736                     }
00737                     wroteSemi = true;
00738                 }
00739 
00740                 // Write the table entry.
00741                 bool ret = WriteLuaObject(file, keyName, value, indentLevel + 1, writeAll, alphabetical, writeTablePointers, maxIndentLevel);
00742 
00743                 // Add a comma after the table entry.
00744                 if (ret  &&  indentLevel != -1)
00745                 {
00746                     file.Print(",");
00747                     if (indentLevel < maxIndentLevel)
00748                     {
00749                         file.Print("\n");
00750                     }
00751                 }
00752 
00753                 // Go to the next item.
00754                 Pop();
00755             }
00756         }
00757 
00758         // If we wrote a sequential list and haven't written a semicolon, then
00759         // there were no keyed table entries.  Just write the final comma.
00760         if (hasSequential  &&  !wroteSemi  &&  indentLevel != -1)
00761         {
00762             file.Print(",");
00763             if (indentLevel < maxIndentLevel)
00764             {
00765                 file.Print("\n");
00766             }
00767         }
00768         
00769         // Indent, with the intent of closing up the table.
00770         IndentFile(file, indentSpaces);
00771 
00772         // If the indentation level is 0, then we're at the root position.
00773         if (indentLevel == 0)
00774         {
00775             // Add a couple extra returns for readability's sake.
00776             file.Print("}");
00777             if (indentLevel < maxIndentLevel)
00778             {
00779                 file.Print("\n\n", file);
00780             }
00781         }
00782         else if (indentLevel > 0)
00783         {
00784             // Close the table.  The comma is written when WriteObject()
00785             // returns from the recursive call.
00786             file.Print("}");
00787         }
00788     }
00789 
00790     // If the indentation level is at the root, then add a return to separate
00791     // the lines.
00792     if (indentLevel == 0)
00793     {
00794         if (indentLevel < maxIndentLevel)
00795         {
00796             file.Print("\n");
00797         }
00798     }
00799 
00800     return true;
00801 }
00802 
00803 
00807 void LuaState::WriteLuaGlobalsFile(const char* filename, bool writeAll,
00808                                    bool alphabetical, bool writeTablePointers,
00809                                    unsigned int maxIndentLevel)
00810 {
00811     // For safety, just in case we leave something behind on the script stack.
00812     LuaAutoBlock block(*this);
00813 
00814     WriteLuaFile(filename, NULL, GetGlobals(), -1, writeAll, alphabetical,
00815             writeTablePointers, maxIndentLevel);
00816 }
00817 
00818 
00822 void LuaState::WriteLuaFile(const char* filename, const char* name, LuaObject value,
00823                          int indentLevel, bool writeAll, bool alphabetical,
00824                          bool writeTablePointers, unsigned int maxIndentLevel)
00825 {
00826     // Open the text file to write the script state to.
00827     LuaStateOutFile file;
00828     file.Open(filename);
00829 
00830     // For safety, just in case we leave something behind on the script stack.
00831     LuaAutoBlock block(*this);
00832 
00833     // Run through all the globals.
00834     WriteLuaObject(file, name, value, indentLevel, writeAll, alphabetical,
00835             writeTablePointers, maxIndentLevel);
00836 }
00837 
00838 

Generated on Wed Nov 7 21:15:16 2001 for LuaState(LuaWrapper) by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001