CmGLSLPreprocessor.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. /**
  2. -----------------------------------------------------------------------------
  3. This source file is part of OGRE
  4. (Object-oriented Graphics Rendering Engine)
  5. For the latest info, see http://www.ogre3d.org/
  6. Copyright (c) 2000-2011 Torus Knot Software Ltd
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. -----------------------------------------------------------------------------
  23. */
  24. #ifndef __OGRE_CPREPROCESSOR_H__
  25. #define __OGRE_CPREPROCESSOR_H__
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include "OgrePrerequisites.h"
  29. namespace CamelotEngine {
  30. /**
  31. * This is a simplistic C/C++-like preprocessor.
  32. * It takes an non-zero-terminated string on input and outputs a
  33. * non-zero-terminated string buffer.
  34. *
  35. * This preprocessor was designed specifically for GLSL shaders, so
  36. * if you want to use it for other purposes you might want to check
  37. * if the feature set it provides is enough for you.
  38. *
  39. * Here's a list of supported features:
  40. * <ul>
  41. * <li>Fast memory allocation-less operation (mostly).
  42. * <li>Line continuation (backslash-newline) is swallowed.
  43. * <li>Line numeration is fully preserved by inserting empty lines where
  44. * required. This is crucial if, say, GLSL compiler reports you an error
  45. * with a line number.
  46. * <li>#define: Parametrized and non-parametrized macros. Invoking a macro with
  47. * less arguments than it takes assignes empty values to missing arguments.
  48. * <li>#undef: Forget defined macros
  49. * <li>#ifdef/#ifndef/#else/#endif: Conditional suppression of parts of code.
  50. * <li>#if: Supports numeric expression of any complexity, also supports the
  51. * defined() pseudo-function.
  52. * <ul>
  53. */
  54. class CPreprocessor
  55. {
  56. /**
  57. * A input token.
  58. *
  59. * For performance reasons most tokens will point to portions of the
  60. * input stream, so no unneeded memory allocation is done. However,
  61. * in some cases we must allocate different memory for token storage,
  62. * in this case this is signalled by setting the Allocated member
  63. * to non-zero in which case the destructor will know that it must
  64. * free memory on object destruction.
  65. *
  66. * Again for performance reasons we use malloc/realloc/free here because
  67. * C++-style new[] lacks the realloc() counterpart.
  68. */
  69. class Token
  70. {
  71. public:
  72. enum Kind
  73. {
  74. TK_EOS, // End of input stream
  75. TK_ERROR, // An error has been encountered
  76. TK_WHITESPACE, // A whitespace span (but not newline)
  77. TK_NEWLINE, // A single newline (CR & LF)
  78. TK_LINECONT, // Line continuation ('\' followed by LF)
  79. TK_NUMBER, // A number
  80. TK_KEYWORD, // A keyword
  81. TK_PUNCTUATION, // A punctuation character
  82. TK_DIRECTIVE, // A preprocessor directive
  83. TK_STRING, // A string
  84. TK_COMMENT, // A block comment
  85. TK_LINECOMMENT, // A line comment
  86. TK_TEXT, // An unparsed text (cannot be returned from GetToken())
  87. };
  88. /// Token type
  89. Kind Type;
  90. /// True if string was allocated (and must be freed)
  91. mutable size_t Allocated;
  92. union
  93. {
  94. /// A pointer somewhere into the input buffer
  95. const char *String;
  96. /// A memory-allocated string
  97. char *Buffer;
  98. };
  99. /// Token length in bytes
  100. size_t Length;
  101. Token () : Allocated (0), String (NULL)
  102. { }
  103. Token (Kind iType) : Type (iType), Allocated (0), String (NULL)
  104. { }
  105. Token (Kind iType, const char *iString, size_t iLength) :
  106. Type (iType), Allocated (0), String (iString), Length (iLength)
  107. { }
  108. Token (const Token &iOther)
  109. {
  110. Type = iOther.Type;
  111. Allocated = iOther.Allocated;
  112. iOther.Allocated = 0; // !!! not quite correct but effective
  113. String = iOther.String;
  114. Length = iOther.Length;
  115. }
  116. ~Token ()
  117. { if (Allocated) free (Buffer); }
  118. /// Assignment operator
  119. Token &operator = (const Token &iOther)
  120. {
  121. if (Allocated) free (Buffer);
  122. Type = iOther.Type;
  123. Allocated = iOther.Allocated;
  124. iOther.Allocated = 0; // !!! not quite correct but effective
  125. String = iOther.String;
  126. Length = iOther.Length;
  127. return *this;
  128. }
  129. /// Append a string to this token
  130. void Append (const char *iString, size_t iLength);
  131. /// Append a token to this token
  132. void Append (const Token &iOther);
  133. /// Append given number of newlines to this token
  134. void AppendNL (int iCount);
  135. /// Count number of newlines in this token
  136. int CountNL ();
  137. /// Get the numeric value of the token
  138. bool GetValue (long &oValue) const;
  139. /// Set the numeric value of the token
  140. void SetValue (long iValue);
  141. /// Test two tokens for equality
  142. bool operator == (const Token &iOther)
  143. {
  144. if (iOther.Length != Length)
  145. return false;
  146. return (memcmp (String, iOther.String, Length) == 0);
  147. }
  148. };
  149. /// A macro definition
  150. class Macro
  151. {
  152. public:
  153. /// Macro name
  154. Token Name;
  155. /// Number of arguments
  156. int NumArgs;
  157. /// The names of the arguments
  158. Token *Args;
  159. /// The macro value
  160. Token Value;
  161. /// Unparsed macro body (keeps the whole raw unparsed macro body)
  162. Token Body;
  163. /// Next macro in chained list
  164. Macro *Next;
  165. /// A pointer to function implementation (if macro is really a func)
  166. Token (*ExpandFunc) (CPreprocessor *iParent, int iNumArgs, Token *iArgs);
  167. /// true if macro expansion is in progress
  168. bool Expanding;
  169. Macro (const Token &iName) :
  170. Name (iName), NumArgs (0), Args (NULL), Next (NULL),
  171. ExpandFunc (NULL), Expanding (false)
  172. { }
  173. ~Macro ()
  174. { delete [] Args; delete Next; }
  175. /// Expand the macro value (will not work for functions)
  176. Token Expand (int iNumArgs, Token *iArgs, Macro *iMacros);
  177. };
  178. friend class CPreprocessor::Macro;
  179. /// The current source text input
  180. const char *Source;
  181. /// The end of the source text
  182. const char *SourceEnd;
  183. /// Current line number
  184. int Line;
  185. /// True if we are at beginning of line
  186. bool BOL;
  187. /// A stack of 32 booleans packed into one value :)
  188. unsigned EnableOutput;
  189. /// The list of macros defined so far
  190. Macro *MacroList;
  191. /**
  192. * Private constructor to re-parse a single token.
  193. */
  194. CPreprocessor (const Token &iToken, int iLine);
  195. /**
  196. * Stateless tokenizer: Parse the input text and return the next token.
  197. * @param iExpand
  198. * If true, macros will be expanded to their values
  199. * @return
  200. * The next token from the input stream
  201. */
  202. Token GetToken (bool iExpand);
  203. /**
  204. * Handle a preprocessor directive.
  205. * @param iToken
  206. * The whole preprocessor directive line (until EOL)
  207. * @param iLine
  208. * The line where the directive begins (for error reports)
  209. * @return
  210. * The last input token that was not proceeded.
  211. */
  212. Token HandleDirective (Token &iToken, int iLine);
  213. /**
  214. * Handle a #define directive.
  215. * @param iBody
  216. * The body of the directive (everything after the directive
  217. * until end of line).
  218. * @param iLine
  219. * The line where the directive begins (for error reports)
  220. * @return
  221. * true if everything went ok, false if not
  222. */
  223. bool HandleDefine (Token &iBody, int iLine);
  224. /**
  225. * Undefine a previously defined macro
  226. * @param iBody
  227. * The body of the directive (everything after the directive
  228. * until end of line).
  229. * @param iLine
  230. * The line where the directive begins (for error reports)
  231. * @return
  232. * true if everything went ok, false if not
  233. */
  234. bool HandleUnDef (Token &iBody, int iLine);
  235. /**
  236. * Handle an #ifdef directive.
  237. * @param iBody
  238. * The body of the directive (everything after the directive
  239. * until end of line).
  240. * @param iLine
  241. * The line where the directive begins (for error reports)
  242. * @return
  243. * true if everything went ok, false if not
  244. */
  245. bool HandleIfDef (Token &iBody, int iLine);
  246. /**
  247. * Handle an #if directive.
  248. * @param iBody
  249. * The body of the directive (everything after the directive
  250. * until end of line).
  251. * @param iLine
  252. * The line where the directive begins (for error reports)
  253. * @return
  254. * true if everything went ok, false if not
  255. */
  256. bool HandleIf (Token &iBody, int iLine);
  257. /**
  258. * Handle an #else directive.
  259. * @param iBody
  260. * The body of the directive (everything after the directive
  261. * until end of line).
  262. * @param iLine
  263. * The line where the directive begins (for error reports)
  264. * @return
  265. * true if everything went ok, false if not
  266. */
  267. bool HandleElse (Token &iBody, int iLine);
  268. /**
  269. * Handle an #endif directive.
  270. * @param iBody
  271. * The body of the directive (everything after the directive
  272. * until end of line).
  273. * @param iLine
  274. * The line where the directive begins (for error reports)
  275. * @return
  276. * true if everything went ok, false if not
  277. */
  278. bool HandleEndIf (Token &iBody, int iLine);
  279. /**
  280. * Get a single function argument until next ',' or ')'.
  281. * @param oArg
  282. * The argument is returned in this variable.
  283. * @param iExpand
  284. * If false, parameters are not expanded and no expressions are
  285. * allowed; only a single keyword is expected per argument.
  286. * @return
  287. * The first unhandled token after argument.
  288. */
  289. Token GetArgument (Token &oArg, bool iExpand);
  290. /**
  291. * Get all the arguments of a macro: '(' arg1 { ',' arg2 { ',' ... }} ')'
  292. * @param oNumArgs
  293. * Number of parsed arguments is stored into this variable.
  294. * @param oArgs
  295. * This is set to a pointer to an array of parsed arguments.
  296. * @param iExpand
  297. * If false, parameters are not expanded and no expressions are
  298. * allowed; only a single keyword is expected per argument.
  299. */
  300. Token GetArguments (int &oNumArgs, Token *&oArgs, bool iExpand);
  301. /**
  302. * Parse an expression, compute it and return the result.
  303. * @param oResult
  304. * A token containing the result of expression
  305. * @param iLine
  306. * The line at which the expression starts (for error reports)
  307. * @param iOpPriority
  308. * Operator priority (at which operator we will stop if
  309. * proceeding recursively -- used internally. Parser stops
  310. * when it encounters an operator with higher or equal priority).
  311. * @return
  312. * The last unhandled token after the expression
  313. */
  314. Token GetExpression (Token &oResult, int iLine, int iOpPriority = 0);
  315. /**
  316. * Get the numeric value of a token.
  317. * If the token was produced by expanding a macro, we will get
  318. * an TEXT token which can contain a whole expression; in this
  319. * case we will call GetExpression to parse it. Otherwise we
  320. * just call the token's GetValue() method.
  321. * @param iToken
  322. * The token to get the numeric value of
  323. * @param oValue
  324. * The variable to put the value into
  325. * @param iLine
  326. * The line where the directive begins (for error reports)
  327. * @return
  328. * true if ok, false if not
  329. */
  330. bool GetValue (const Token &iToken, long &oValue, int iLine);
  331. /**
  332. * Expand the given macro, if it exists.
  333. * If macro has arguments, they are collected from source stream.
  334. * @param iToken
  335. * A KEYWORD token containing the (possible) macro name.
  336. * @return
  337. * The expanded token or iToken if it is not a macro
  338. */
  339. Token ExpandMacro (const Token &iToken);
  340. /**
  341. * Check if a macro is defined, and if so, return it
  342. * @param iToken
  343. * Macro name
  344. * @return
  345. * The macro object or NULL if a macro with this name does not exist
  346. */
  347. Macro *IsDefined (const Token &iToken);
  348. /**
  349. * The implementation of the defined() preprocessor function
  350. * @param iParent
  351. * The parent preprocessor object
  352. * @param iNumArgs
  353. * Number of arguments
  354. * @param iArgs
  355. * The arguments themselves
  356. * @return
  357. * The return value encapsulated in a token
  358. */
  359. static Token ExpandDefined (CPreprocessor *iParent, int iNumArgs, Token *iArgs);
  360. /**
  361. * Parse the input string and return a token containing the whole output.
  362. * @param iSource
  363. * The source text enclosed in a token
  364. * @return
  365. * The output text enclosed in a token
  366. */
  367. Token Parse (const Token &iSource);
  368. /**
  369. * Call the error handler
  370. * @param iLine
  371. * The line at which the error happened.
  372. * @param iError
  373. * The error string.
  374. * @param iToken
  375. * If not NULL contains the erroneous token
  376. */
  377. void Error (int iLine, const char *iError, const Token *iToken = NULL);
  378. public:
  379. /// Create an empty preprocessor object
  380. CPreprocessor () : MacroList (NULL)
  381. { }
  382. /// Destroy the preprocessor object
  383. virtual ~CPreprocessor ();
  384. /**
  385. * Define a macro without parameters.
  386. * @param iMacroName
  387. * The name of the defined macro
  388. * @param iMacroNameLen
  389. * The length of the name of the defined macro
  390. * @param iMacroValue
  391. * The value of the defined macro
  392. * @param iMacroValueLen
  393. * The length of the value of the defined macro
  394. */
  395. void Define (const char *iMacroName, size_t iMacroNameLen,
  396. const char *iMacroValue, size_t iMacroValueLen);
  397. /**
  398. * Define a numerical macro.
  399. * @param iMacroName
  400. * The name of the defined macro
  401. * @param iMacroNameLen
  402. * The length of the name of the defined macro
  403. * @param iMacroValue
  404. * The value of the defined macro
  405. */
  406. void Define (const char *iMacroName, size_t iMacroNameLen, long iMacroValue);
  407. /**
  408. * Undefine a macro.
  409. * @param iMacroName
  410. * The name of the macro to undefine
  411. * @param iMacroNameLen
  412. * The length of the name of the macro to undefine
  413. * @return
  414. * true if the macro has been undefined, false if macro doesn't exist
  415. */
  416. bool Undef (const char *iMacroName, size_t iMacroNameLen);
  417. /**
  418. * Parse the input string and return a newly-allocated output string.
  419. * @note
  420. * The returned preprocessed string is NOT zero-terminated
  421. * (just like the input string).
  422. * @param iSource
  423. * The source text
  424. * @param iLength
  425. * The length of the source text in characters
  426. * @param oLength
  427. * The length of the output string.
  428. * @return
  429. * The output from preprocessor, allocated with malloc().
  430. * The parser can actually allocate more than needed for performance
  431. * reasons, but this should not be a problem unless you will want
  432. * to store the returned pointer for long time in which case you
  433. * might want to realloc() it.
  434. * If an error has been encountered, the function returns NULL.
  435. * In some cases the function may return an unallocated address
  436. * that's *inside* the source buffer. You must free() the result
  437. * string only if the returned address is not inside the source text.
  438. */
  439. char *Parse (const char *iSource, size_t iLength, size_t &oLength);
  440. /**
  441. * An error handler function type.
  442. * The default implementation just drops a note to stderr and
  443. * then the parser ends, returning NULL.
  444. * @param iData
  445. * User-specific pointer from the corresponding CPreprocessor object.
  446. * @param iLine
  447. * The line at which the error happened.
  448. * @param iError
  449. * The error string.
  450. * @param iToken
  451. * If not NULL contains the erroneous token
  452. * @param iTokenLen
  453. * The length of iToken. iToken is never zero-terminated!
  454. */
  455. typedef void (*ErrorHandlerFunc) (
  456. void *iData, int iLine, const char *iError,
  457. const char *iToken, size_t iTokenLen);
  458. /**
  459. * A pointer to the preprocessor's error handler.
  460. * You can assign the address of your own function to this variable
  461. * and implement your own error handling (e.g. throwing an exception etc).
  462. */
  463. static ErrorHandlerFunc ErrorHandler;
  464. /// User-specific storage, passed to Error()
  465. void *ErrorData;
  466. };
  467. } // namespace CamelotEngine
  468. #endif // __OGRE_CPREPROCESSOR_H__