1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 //-----------------------------------------------------------------------------
19 //-----------------------------------------------------------------------------
21 #include "nel/misc/variable.h"
22 #include "nel/misc/path.h"
23 #include "game_share/file_description_container.h"
24 #include "game_share/utils.h"
25 #include "char_scan_script.h"
28 //-----------------------------------------------------------------------------
30 //-----------------------------------------------------------------------------
33 using namespace NLMISC
;
36 //-----------------------------------------------------------------------------
38 //-----------------------------------------------------------------------------
40 CVariable
<string
> ScriptDirectory("variables", "ScriptDirectory", "Directory containing script files", string("./"), 0, true);
41 CVariable
<string
> OutputDirectory("variables", "OutputDirectory", "Directory containing output files", string("./"), 0, true);
44 //-------------------------------------------------------------------------------------------------
45 // methods CCharScanScript
46 //-------------------------------------------------------------------------------------------------
48 bool CCharScanScript::addScriptFile(const std::string
& fileName
)
50 std::string fullFileName
=NLMISC::CPath::standardizePath(ScriptDirectory
)+fileName
;
52 // make sure the file exists
53 if (!NLMISC::CFile::fileExists(fullFileName
))
55 nlwarning("script file not found: %s",fullFileName
.c_str());
59 // make sure the file hasn't already been included previously
60 for (uint32 i
=0;i
<_ScriptFiles
.size();++i
)
62 if (_ScriptFiles
[i
].getFileName()==fullFileName
)
64 nlwarning("attempt to include script file '%s' more than once",fullFileName
.c_str());
69 // add & parse the new file
70 return vectAppend(_ScriptFiles
).parseFile(fullFileName
);
73 void CCharScanScript::applyToJob(CCharacterScanJob
& job
)
75 // iterate backwards over the script files in order to apply the most important files last
76 for (uint32 i
=(uint32
)_ScriptFiles
.size();i
--;)
78 _ScriptFiles
[i
].applyToJob(job
);
82 //-------------------------------------------------------------------------------------------------
83 // methods CCharScanScriptFile
84 //-------------------------------------------------------------------------------------------------
86 bool CCharScanScriptFile::parseFile(const std::string
& fileName
, CCharScanScript
* container
)
90 // read the content of the input file
92 NLMISC::CSString fileContent
;
93 result
=fileContent
.readFromFile(fileName
);
96 nlwarning("Failed to read script file: %s",fileName
.c_str());
100 // split the file into lines and execute them one by one
101 NLMISC::CVectorSString lines
;
102 fileContent
.splitLines(lines
);
103 for (uint32 i
=0;i
<lines
.size();++i
)
105 // strip comments and leading and trailing blanks
106 CSString theLine
= lines
[i
].replace("//","\xff").splitTo('\xff').strip();
110 CCharScanScriptCommandRegistry::getInstance()->execute(*this,theLine
,container
);
115 bool CCharScanScriptFile::applyToJob(CCharacterScanJob
& job
)
119 // apply the file names
120 CFileDescriptionContainer fdc
;
121 for (uint32 i
=0;i
<_InputFiles
.size();++i
)
123 fdc
.addFileSpec(_InputFiles
[i
]);
128 for (uint32 i
=0;i
<_Filters
.size();++i
)
130 ICharFilter
* filter
= CCharFilterFactory::getInstance()->build(_Filters
[i
]);
133 nlwarning("Failed to build filter description from line: %s",_Filters
[i
].c_str());
137 job
.addFilter(filter
);
140 // apply the info extractors
141 for (uint32 i
=0;i
<_InfoExtractors
.size();++i
)
143 ICharInfoExtractor
* infoExtractor
= CCharInfoExtractorFactory::getInstance()->build(_InfoExtractors
[i
]);
144 if (infoExtractor
==NULL
)
146 nlwarning("Failed to build filter description from line: %s",_InfoExtractors
[i
].c_str());
150 job
.addInfoExtractor(infoExtractor
);
153 // apply the output path
154 job
.setOutputPath(_OutputPath
);
159 const std::string
& CCharScanScriptFile::getFileName() const
164 const std::string
& CCharScanScriptFile::getDescription() const
169 bool CCharScanScriptFile::setDescription(const std::string
& description
)
171 _Description
= description
;
175 bool CCharScanScriptFile::setOutputPath(const std::string
& path
)
181 bool CCharScanScriptFile::addFilter(const std::string
& rawArgs
)
183 _Filters
.push_back(rawArgs
);
187 bool CCharScanScriptFile::addInfoExtractor(const std::string
& rawArgs
)
189 _InfoExtractors
.push_back(rawArgs
);
193 bool CCharScanScriptFile::addInputFiles(const std::string
& rawArgs
)
195 _InputFiles
.push_back(rawArgs
);
200 //-------------------------------------------------------------------------------------------------
201 // methods CCharScanScriptCommandRegistry
202 //-------------------------------------------------------------------------------------------------
204 CCharScanScriptCommandRegistry
* CCharScanScriptCommandRegistry::getInstance()
206 static CCharScanScriptCommandRegistry
* ptr
=NULL
;
208 ptr
= new CCharScanScriptCommandRegistry
;
212 void CCharScanScriptCommandRegistry::registerScriptCommand(NLMISC::CSmartPtr
<ICharScanScriptCommand
> scriptCommand
)
214 // ensure that we don't have a name conflict with an existing script command
215 for (uint32 i
=0;i
<_ScriptCommands
.size();++i
)
217 nlassert(scriptCommand
->getName()!=_ScriptCommands
[i
]->getName());
220 // add the new script command
221 _ScriptCommands
.push_back(scriptCommand
);
224 void CCharScanScriptCommandRegistry::displayScriptCommands(NLMISC::CLog
* log
)
226 uint32 longestName
=4;
228 // iterate over the script commands to determine the length of the longest name
229 for (uint32 i
=0;i
<_ScriptCommands
.size();++i
)
231 std::string s
= _ScriptCommands
[i
]->getName();
232 if (s
.size()>longestName
)
233 longestName
=(uint32
)s
.size();
236 // iterate over the script commands displaying names and description
237 for (uint32 i
=0;i
<_ScriptCommands
.size();++i
)
239 log
->displayNL("%-*s %s",longestName
,_ScriptCommands
[i
]->getName(),_ScriptCommands
[i
]->getDescription());
243 bool CCharScanScriptCommandRegistry::execute(CCharScanScriptFile
& scriptFile
,const CSString
& commandLine
,CCharScanScript
* container
)
245 // split the command line into its constituent parts
246 CSString theCommand
= commandLine
.firstWordConst();
247 CSString theRawArgs
= commandLine
.tailFromFirstWord().strip();
248 CVectorSString theArgs
;
249 theRawArgs
.splitByOneOfSeparators(" \t",theArgs
,false,false,false,false,true);
251 // try to locate and execute the given command
252 for (uint32 i
=0;i
<_ScriptCommands
.size();++i
)
254 if (theCommand
==_ScriptCommands
[i
]->getName())
256 return _ScriptCommands
[i
]->execute(scriptFile
,theArgs
,theRawArgs
,commandLine
,container
);
260 // we failed to find the command so bomb
261 nlwarning("Unknown script command '%s' in line: %s",theCommand
.c_str(),commandLine
.c_str());
266 //-----------------------------------------------------------------------------
267 // CHAR_SCAN_SCRIPT_COMMAND: instances
268 //-----------------------------------------------------------------------------
270 CHAR_SCAN_SCRIPT_COMMAND(description
,"<description>","Set the description phrase for the script - displayed by the listScripts command")
272 if (rawArgs
.strip().empty())
275 return scriptFile
.setDescription(rawArgs
);
278 CHAR_SCAN_SCRIPT_COMMAND(include
,"<include_file_name>","Include another script file")
286 return container
->addScriptFile(args
[0]);
289 CHAR_SCAN_SCRIPT_COMMAND(inputFiles
,"[<path>/]<file_spec>","Add a set of files to be parsed")
291 if (rawArgs
.strip().empty())
294 return scriptFile
.addInputFiles(rawArgs
);
297 CHAR_SCAN_SCRIPT_COMMAND(filter
,"<name> [<args>]","Add a filter to limit the set criteria to determine which files' content to reflect in output")
299 if (rawArgs
.strip().empty())
302 return scriptFile
.addFilter(rawArgs
);
305 CHAR_SCAN_SCRIPT_COMMAND(infoExtactor
,"<name> [<args>]","Add an info extractor")
307 if (rawArgs
.strip().empty())
310 return scriptFile
.addInfoExtractor(rawArgs
);
313 CHAR_SCAN_SCRIPT_COMMAND(outputPath
,"<path>","Set the directory to which the output will be written")
318 return scriptFile
.setOutputPath(args
[0]);
322 //-----------------------------------------------------------------------------