Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3278 lines
98 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. tracewpp.c
  5. Abstract:
  6. Parameter processing and main entry point for tracewpp.exe
  7. Author:
  8. Gor Nishanov (gorn) 03-Apr-1999
  9. Revision History:
  10. gorn 03-Apr-1999 -- hacked together to prove that this can work
  11. GorN: 29-Sep-2000 - do not scan files that didn't change
  12. GorN: 29-Sep-2000 - support -notimechk -nohashchk -dll switches
  13. GorN: 29-Sep-2000 - add support for KdPrintEx((level,comp,msg,...)) like functions
  14. GorN: 09-Oct-2000 - fix hashing; added NULL arg
  15. GorN: 07-Mar-2001 - add arglimit option
  16. ToDo:
  17. all Clean it up
  18. parseConfigCheck for premature termination Ex: CUSTOM_TYPE(x, ItemListLong(dfdf))
  19. cool Automatic fill of the arguments if ...
  20. nice better error chk
  21. types to mof it stinks to generate long enums multiple times
  22. later guidless
  23. bug check for types with dup names
  24. bug tpl: check for unterminated keyword
  25. later detect WPP_CLEANUP -- complain
  26. print in macros what to do about prints in macro?
  27. cmdline get the flags from the env variable
  28. !!! Don't assume that whatever is not recognized is func
  29. bug updated CRC computations to properly work with consts
  30. bug enum doesn't work
  31. bug %10!..! doesnt' work
  32. bug %% is not handled
  33. mess rename hidden => visible
  34. mess remove ugly MSGTYPBASE. Make FmtStr 0 based
  35. mess let message share some of the func field handlers
  36. traceprt think how to make the level indenting
  37. ezparse report unmatched end_wpp
  38. now get cmdline options from a file or env.var
  39. later handle "str" STRMACRO "another string" as a MSG arg
  40. strange output
  41. ..\logsup.c(4180) : error : Unterminated Format SpecifierHere is the signature: (0)
  42. ..\logsup.c(4180) : error : Extra argument. Only 0 are specified in the string
  43. why we didn't catch the error
  44. CsDbgPrint(LOG_NOISE,
  45. ("[FM] FmpSetGroupEnumOwner: Group %1!ws! not found\n"));
  46. CsDbgPrint(LOG_UNUSUAL, (
  47. "[NMJOIN] Cannot add node '%1!ws!' to the cluster because "
  48. "no slots are available in the node table.\n"
  49. ));
  50. printf("Port no in network order %1!port!, regular order %1!u!, 0x0102);
  51. NetDeviceTrace( NETDEV_DBG_EXIT | NETDEV_DBG_INFO,
  52. "ClientMdlSetup Client[%10!d!], RCB[%11!d!]: "
  53. "Exit w/ Func 0x%12!04X!, Send 0x%14!04X!, Recv 0x%15!04X!",
  54. deviceExtension->Ordinal, // LOGULONG
  55. RequestCB->RequestIdx, // LOGUSHORT
  56. ios->MajorFunction, // LOGUCHAR
  57. ios->MajorFunction, // LOGUCHAR
  58. sendBytes, // LOGULONG
  59. recvBytes); // LOGULONG => AV's
  60. DONE DONE DONE DONE DONE DONE DONE DONE DONE DONE
  61. later handle KdPrintEx
  62. later add "if" to templates (at least if not empty)
  63. requirement md5
  64. later detect WPP_INIT_TRACING
  65. main Time ourselves and print how fast we are
  66. useful ignore anything but .c .cxx .cpp .c++
  67. useful -gen{a,b,c}h.tpl
  68. -ext:.c.cxx.cpp.c++
  69. -v verbose
  70. -q extra quiet
  71. footprint merge multiple formats together
  72. difficult? Think how to unify DoTraceMacro0 TraceLazy, etc
  73. figureout DbgPrint
  74. -odir:path
  75. trivial add "\" to -odir if needed
  76. nice scan
  77. -gen:{a.tpl}auto.c
  78. -gen:{a.tpl}*.c
  79. outstanding take plain DebugPrint format as well
  80. difficult? Add generation of by value types
  81. --*/
  82. #define STRICT
  83. #include <stdio.h>
  84. #include <windows.h>
  85. #include <rpc.h>
  86. #include <rpcdce.h>
  87. #pragma warning(disable: 4702) // unreachable code
  88. #pragma warning(disable: 4786)
  89. #pragma warning(disable: 4503) // decorated length
  90. #pragma warning(disable: 4512) // cannot generate assignment
  91. #pragma warning(disable: 4100) // '_P' : unreferenced formal parameter
  92. #pragma warning(disable: 4267) // 'return' : conversion from 'size_t' to 'int'
  93. #include <xmemory>
  94. #include <xstring>
  95. #include <set>
  96. #include <map>
  97. #pragma warning(disable: 4663)
  98. #pragma warning(disable: 4018) // signed/unsigned mismatch
  99. #include <vector>
  100. //#pragma warning(default: 4018 4663) // signed/unsigned mismatch
  101. #pragma warning(default: 4100)
  102. #include <algorithm>
  103. #include "ezparse.h"
  104. #include "crc32.h"
  105. #include "md5.h"
  106. #include "fieldtable.h"
  107. #include "tpl.h"
  108. #define override
  109. //typedef ULONG CRC32;
  110. using namespace std;
  111. BOOL md5 = TRUE;
  112. BOOL reorder = FALSE;
  113. BOOL userMode = TRUE;
  114. BOOL noshrieks = FALSE;
  115. UINT SeparateTraceGuidPerFile = 1;
  116. INT MSGTYPBASE = 10;
  117. UINT MessageCount = 0;
  118. UINT ArgBase = 1;
  119. BOOL CheckTimestamp = TRUE;
  120. BOOL CheckHash = TRUE;
  121. BOOL IgnoreDupTypes = FALSE;
  122. int arglimit = 32;
  123. //string OutputInc ("_tracewpp.h");
  124. //string OutputMof ("_tracewpp.mof");
  125. string OutputMac;
  126. string OutputDir (".\\");
  127. //string ArrayPrefix("WPP_");
  128. string MacroPrefix("LOG");
  129. string AllowedExtensions(".c.cxx.cpp.c++.C.CPP");
  130. string CurrentDir;
  131. #define DEFAULT_UM_GEN_OPTION "{um-default.tpl}*.tmh"
  132. #define DEFAULT_KM_GEN_OPTION "{km-default.tpl}*.tmh"
  133. #define DEFAULT_GEN_OPTION (userMode?DEFAULT_UM_GEN_OPTION:DEFAULT_KM_GEN_OPTION)
  134. #define DEFAULT_CONFIG_NAME "defaultwpp.ini"
  135. string LOCAL_CONFIG_NAME("localwpp.ini");
  136. string WppDefault(DEFAULT_CONFIG_NAME);
  137. vector<string> SearchDirs;
  138. //string Revision;
  139. string LocalConfig;
  140. string ComponentName;
  141. // Checks whether string passed has an allowed extension
  142. // Lame: uses global variable AllowedExtensions
  143. BOOL AllowedExtension(const string str)
  144. {
  145. string::size_type p = str.rfind('.'), q, n;
  146. if (p == string::npos) {
  147. Unusual("File %s has no extension\n", str.c_str() );
  148. return FALSE;
  149. }
  150. n = str.size() - p; // extension length
  151. q = AllowedExtensions.find(&str[p], 0, n);
  152. if ( (q == string::npos)
  153. || (q + n < AllowedExtensions.size() && AllowedExtensions[q + n] != '.') )
  154. {
  155. Unusual("File %s has unrecognized extension\n", str.c_str() );
  156. return FALSE;
  157. }
  158. return TRUE;
  159. }
  160. inline size_t fprint_str(FILE* f, const string& str) {
  161. return fwrite(str.c_str(), str.length(), 1, f );
  162. }
  163. inline size_t fprint_str(FILE* f, LPCSTR beg, LPCSTR end) {
  164. return fwrite(beg, end - beg, 1, f );
  165. }
  166. inline size_t fprint_str(FILE* f, const STR_PAIR& Pair) {
  167. return fwrite(Pair.beg, Pair.end - Pair.beg, 1, f );
  168. }
  169. inline int stoi(const STR_PAIR& str, LPCSTR name)
  170. {
  171. LPCSTR p = str.beg;
  172. int sum = 0;
  173. int sgn = 1;
  174. if (p < str.end && *p == '-') {
  175. ++p; sgn = -1;
  176. }
  177. while (p < str.end) {
  178. if (!isdigit(*p)) {
  179. ReportError("%s should be a number (%s supplied)\n",
  180. name, string(str.beg, str.end).c_str() );
  181. break;
  182. }
  183. sum = 10 * sum + (*p - '0');
  184. ++p;
  185. }
  186. return sgn * sum;
  187. }
  188. inline unsigned char HexVal(int ch) {
  189. return (unsigned char)(isdigit(ch) ? ch - '0' : ch - 'a' + 10); }
  190. UINT Hex(LPCSTR s, int n)
  191. {
  192. UINT res = 0;
  193. while(n--) {
  194. res = res * 16 + HexVal(*s++);
  195. }
  196. return res;
  197. }
  198. CHAR HexDigit(int val) {
  199. if (val < 10) return (CHAR)(val + '0');
  200. else return (CHAR)(val + 'a' - 10);
  201. }
  202. ULONGLONG GetFileModificationTime(const string& str)
  203. {
  204. WIN32_FIND_DATA FindData;
  205. ULONGLONG Time;
  206. HANDLE FindHandle = FindFirstFile(str.c_str(), &FindData);
  207. if (FindHandle == INVALID_HANDLE_VALUE) {
  208. return 0;
  209. }
  210. FindClose(FindHandle);
  211. CopyMemory(&Time, &FindData.ftLastWriteTime, sizeof(Time));
  212. return Time;
  213. }
  214. // Prototypes //
  215. void DealWithCmdLineOptions(LPCSTR s);
  216. void DealWithCmdLineOptions(LPCSTR beg, LPCSTR end)
  217. {
  218. DealWithCmdLineOptions(string(beg,end).c_str() );
  219. }
  220. struct Hasher {
  221. virtual void Init() = 0;
  222. virtual void Finalize() = 0;
  223. virtual void Hash(const void* buf, int nBytes) = 0;
  224. virtual int Size() const = 0;
  225. virtual const unsigned char * Buf() const = 0;
  226. void Hash(const std::string& str) {
  227. Hash(str.begin(), (int)str.size());
  228. }
  229. void fromString(LPCSTR beg, LPCSTR end)
  230. {
  231. int n = min((ULONG)(end - beg)/2, Size());
  232. unsigned char * buf = BufRW();
  233. ZeroMemory(buf, Size());
  234. for(int i = 0; i < n; ++i) {
  235. buf[i] = HexVal(beg[2*i]) * 16 + HexVal(beg[2*i + 1]);
  236. }
  237. }
  238. void print(FILE* out) const {
  239. int n = Size();
  240. const UCHAR* buf = Buf();
  241. for(int i = 0; i < n; ++i) {
  242. fprintf(out, "%x%x", buf[i] >> 4, buf[i] & 0xF);
  243. }
  244. }
  245. bool operator ==(const Hasher& b) const {
  246. return Size() == b.Size() && memcmp(Buf(), b.Buf(), Size()) == 0;
  247. }
  248. private:
  249. unsigned char* BufRW() { return (unsigned char*)Buf(); }
  250. };
  251. class Crc32Hasher : public Hasher
  252. {
  253. ULONG Crc;
  254. public:
  255. override void Init() { Crc = (ULONG)~0; }
  256. override void Finalize() {}
  257. override void Hash(const void* buf, int nBytes) {
  258. Crc = FstubCrc32(Crc, (PVOID)buf, nBytes);
  259. }
  260. override int Size() const { return sizeof(Crc); }
  261. override const unsigned char * Buf() const { return (UCHAR*)&Crc; }
  262. };
  263. class Md5Hasher : public Hasher
  264. {
  265. MD5_CTX Ctx;
  266. public:
  267. override void Init()
  268. {
  269. MD5Init(&Ctx);
  270. }
  271. override void Finalize()
  272. {
  273. MD5Final(&Ctx);
  274. }
  275. override void Hash(const void* buf, int nBytes)
  276. {
  277. MD5Update(&Ctx, (const unsigned char*)buf, nBytes);
  278. }
  279. virtual int Size() const
  280. {
  281. // assert(MD5DIGESTLEN == sizeof(GUID));
  282. return MD5DIGESTLEN; // == 16
  283. }
  284. virtual const unsigned char * Buf() const
  285. {
  286. return Ctx.digest;
  287. }
  288. };
  289. //typedef Crc32Hasher DefaultHasher;
  290. typedef Md5Hasher DefaultHasher;
  291. void ReplaceCrOrLfWith(string& s, char ch)
  292. {
  293. for(int i = 0; i < s.size(); ++i) {
  294. if (s[i] == '\n' || s[i] == '\r') s[i] = ch;
  295. if (s[i] == '"') s[i] = '\'';
  296. }
  297. }
  298. string currentFileName();
  299. bool
  300. Files_AddFile(const string& Name, string Path, const WIN32_FIND_DATA& FindData) ;
  301. enum {
  302. WT_MACRONAME = 0x00000001, // TypeName is actually a MacroName. Don't have to be prepended with Log Macro Prefix
  303. };
  304. struct WppType : FieldHolder {
  305. string TypeName;
  306. string EquivType; // c-type
  307. string MacroStart; // WPP_LOGVALARG(%s, if not specified
  308. string MofType; // yeah
  309. string Extension; // something to be merged with MofType
  310. string FormatSpec; // sprintf style
  311. string Sig;
  312. int priority;
  313. int ArgConsumed;
  314. mutable BOOL Used;
  315. DWORD Flags;
  316. void hash(Hasher& hash) const {hash.Hash(TypeName);} // BUGBUG ?? Maybe we need to hash it
  317. string sig() const { return Sig; }
  318. bool isConstant() const { return EquivType.size() == 0; }
  319. WppType() {} // To make STL happy
  320. WppType(const string& a, const string&b, const string& c,
  321. const string& d, const string& e, const string& f,
  322. const string& g, int prio, int argConsumed):
  323. TypeName(a), EquivType(b), MacroStart(c), MofType(d),
  324. Extension(e), FormatSpec(f), Sig(g),
  325. priority(prio),Used(0),ArgConsumed(argConsumed) {}
  326. // WppType(LPCSTR beg, LPCSTR end):TypeName(beg, end),Used(0){}
  327. // explicit WppType(char name):TypeName(&name, &name+1),Used(0){}
  328. bool operator < (const WppType& b) const {
  329. int diff = b.priority - priority; // higher prio first
  330. if (diff < 0) return TRUE;
  331. if (diff > 0) return FALSE;
  332. return TypeName.compare(b.TypeName) < 0;
  333. }
  334. virtual BOOL Hidden(std::string) const { return !Used; }
  335. BEGIN_FIELD_TABLE(WppType, f)
  336. TEXT_FIELD(Name) fprint_str(f, TypeName);
  337. TEXT_FIELD(EquivType) fprint_str(f, EquivType);
  338. TEXT_FIELD(MacroName)
  339. {
  340. if (!(Flags & WT_MACRONAME)) fprint_str(f, MacroPrefix);
  341. fprint_str(f, TypeName);
  342. }
  343. TEXT_FIELD(MacroStart) fprintf(f, MacroStart.c_str(), EquivType.c_str());
  344. TEXT_FIELD(MacroEnd) fprintf(f, ")");
  345. TEXT_FIELD(MofType) fprint_str(f, MofType);
  346. TEXT_FIELD(Extension) fprint_str(f, Extension);
  347. TEXT_FIELD(FormatSpec) fprint_str(f, FormatSpec);
  348. END_FIELD_TABLE
  349. };
  350. typedef map<string,WppType,strless> TYPE_SET;
  351. string SimpleValueMacroStart("WPP_LOGTYPEVAL(%s,");
  352. string SimplePtrMacroStart("WPP_LOGTYPEPTR(");
  353. TYPE_SET TypeSet;
  354. struct Argument : FieldHolder {
  355. const WppType* Type;
  356. string Name;
  357. string OverrideName;
  358. int No;
  359. bool operator < (const Argument& b) const { return *Type < *b.Type; }
  360. Argument(){} // To make STL happy //
  361. Argument(string name, const WppType* type):Type(type),Name(name)
  362. { ReplaceCrOrLfWith(Name, ' '); }
  363. void hash(Hasher& hash) const {
  364. hash.Hash(Name);
  365. if(Type) Type->hash(hash);
  366. }
  367. BEGIN_FIELD_TABLE(Argument, f)
  368. TEXT_FIELD(No) {fprintf(f, "%d", No);}
  369. TEXT_FIELD(Name) {fprint_str(f, Name);}
  370. TEXT_FIELD(MofType) {fprint_str(f, Type->MofType); fprint_str(f,Type->Extension);}
  371. END_FIELD_TABLE
  372. };
  373. struct Reorder : FieldHolder {
  374. string Name;
  375. vector<int> Args;
  376. Reorder(){} // to make stl happy
  377. explicit Reorder(string name, const vector<Argument>& args): Name(name)
  378. { Args.resize( args.size() );
  379. for(int i = 0; i < args.size(); ++i) {
  380. Args[i] = args[i].No - MSGTYPBASE;
  381. }
  382. }
  383. bool operator < (const Reorder& b) const
  384. { return Name.compare(b.Name) < 0; }
  385. BEGIN_FIELD_TABLE(Reorder, f)
  386. TEXT_FIELD(Name) fprint_str(f, Name);
  387. TEXT_FIELD(Permutation)
  388. {
  389. for(int i = 0; i < Args.size(); ++i) {
  390. fprintf(f, ", a%d", Args[i]);
  391. }
  392. }
  393. TEXT_FIELD(Arguments)
  394. {
  395. fprintf(f,"MSG");
  396. for(int i = 0; i < Args.size(); ++i) {
  397. fprintf(f, ", a%d", i);
  398. }
  399. }
  400. END_FIELD_TABLE
  401. };
  402. set<Reorder> ReorderSet;
  403. string GetReorderSig(const vector<Argument>& args)
  404. {
  405. string sig;
  406. if (args.size() > 256) {
  407. ReportError("Only upto 256 arguments are supported\n");
  408. return sig;
  409. }
  410. if (args.size() <= 16) {
  411. sig.resize(args.size());
  412. for(int i = 0; i < args.size(); ++i) {
  413. sig[i] = HexDigit(args[i].No - MSGTYPBASE);
  414. }
  415. } else {
  416. sig.resize(2 * args.size());
  417. for(int i = 0; i < args.size(); ++i) {
  418. int val = args[i].No;
  419. sig[2 * i] = HexDigit(val >> 16);
  420. sig[2 * i + 1] = HexDigit(val & 15);
  421. }
  422. }
  423. ReorderSet.insert( Reorder(sig, args) );
  424. return sig;
  425. }
  426. #include "parsed-string.hxx"
  427. struct TypeSig : FieldHolder {
  428. string Name;
  429. vector<const WppType*> Types;
  430. BOOL Unsafe;
  431. TypeSig() {} // To make STL happy
  432. TypeSig(const vector<Argument>& args, const string& sig, BOOL unsafe):
  433. Unsafe(unsafe)
  434. {
  435. Name.assign(sig);
  436. for(int i = 0; i < args.size(); ++i) {
  437. Types.push_back(args[i].Type);
  438. }
  439. }
  440. bool operator < (const TypeSig& b) const {
  441. return Name.compare(b.Name) < 0;
  442. }
  443. virtual BOOL Hidden(std::string str) const {
  444. if (str.size() == 0) { return FALSE; }
  445. else if (str.compare("UnsafeArgs") == 0) { return !Unsafe; }
  446. else if (str.compare("!UnsafeArgs") == 0) { return Unsafe; }
  447. else { ReportError("Unknown filter '%s'\n", str.c_str()); exit(1); }
  448. return NULL;
  449. }
  450. BEGIN_FIELD_TABLE(TypeSig, f)
  451. TEXT_FIELD(Name) fprint_str(f, Name);
  452. TEXT_FIELD(Count) fprintf(f, "%d", Name.size());
  453. TEXT_FIELD(Arguments)
  454. {
  455. for(int i = 0; i < Types.size(); ++i) {
  456. fprintf(f,", ");
  457. fprint_str(f, Types[i]->EquivType);
  458. fprintf(f, " _a%d", i+1);
  459. }
  460. }
  461. TEXT_FIELD(LogArgs)
  462. {
  463. for(int i = 0; i < Types.size(); ++i) {
  464. fprintf(f, Types[i]->MacroStart.c_str(),
  465. Types[i]->EquivType.c_str());
  466. fprintf(f, "_a%d) ", i+1);
  467. }
  468. }
  469. TEXT_FIELD(DeclVars)
  470. {
  471. for(int i = 0; i < Types.size(); ++i) {
  472. fprintf(f, "%s _a%d = va_arg(ap, %s); ",
  473. Types[i]->EquivType.c_str(), i+1,
  474. Types[i]->EquivType.c_str());
  475. }
  476. }
  477. END_FIELD_TABLE
  478. };
  479. typedef map<string,TypeSig,strless> TYPESIG_MAP;
  480. TYPESIG_MAP TypeSigMap;
  481. TypeSig* GetTypeSig(const vector<Argument>& args, BOOL unsafe)
  482. {
  483. string sig;
  484. if (unsafe) {
  485. sig.assign("v");
  486. }
  487. for(int i = 0; i < args.size(); ++i) {
  488. sig.append(args[i].Type->sig() );
  489. }
  490. TYPESIG_MAP::iterator it = TypeSigMap.find( sig );
  491. if ( it == TypeSigMap.end() ) {
  492. // we need to add one //
  493. return &(TypeSigMap[ sig ] = TypeSig(args, sig, unsafe));
  494. }
  495. return &it->second;
  496. }
  497. void Fill(
  498. string pattern)
  499. {
  500. WIN32_FIND_DATA findData;
  501. HANDLE handle;
  502. handle = FindFirstFile(pattern.c_str(), &findData);
  503. if (handle == INVALID_HANDLE_VALUE) {
  504. DWORD status = GetLastError();
  505. if (status != ERROR_FILE_NOT_FOUND) {
  506. Noise("FindFirstFile(%s): error %d\n", pattern.c_str(), GetLastError() );
  507. }
  508. return;
  509. }
  510. string::size_type p = pattern.find_last_of(":\\");
  511. if (p != string::npos) {
  512. pattern.resize(p+1); // to include the symbol
  513. } else {
  514. pattern.resize(0);
  515. }
  516. do {
  517. Files_AddFile(findData.cFileName, pattern, findData);
  518. } while( FindNextFile(handle, &findData) );
  519. FindClose(handle);
  520. }
  521. struct Group : FieldHolder {
  522. UINT GrpId;
  523. vector<string> MsgIds;
  524. string _Name;
  525. Group(){}
  526. Group(UINT id, string Name, string Msg):GrpId(id),_Name(Name) { MsgIds.push_back(Msg); }
  527. BEGIN_FIELD_TABLE(Group, f)
  528. TEXT_FIELD(GuidNo) fprintf(f, "%d", GrpId / 32);
  529. TEXT_FIELD(BitNo) fprintf(f, "%d", GrpId & 31);
  530. TEXT_FIELD(Name) fprint_str(f, _Name);
  531. TEXT_FIELD(References)
  532. {
  533. vector<string>::const_iterator i;
  534. for(i = MsgIds.begin(); i != MsgIds.end(); ++i) {
  535. putc(' ', f); fprint_str(f, *i);
  536. }
  537. }
  538. END_FIELD_TABLE
  539. };
  540. //void RegenerateMacroMap();
  541. struct Prefix{
  542. string FuncName;
  543. // string MsgPrefix;
  544. // vector<Argument> Args;
  545. ParsedFormatString FmtStr;
  546. Prefix(){}
  547. Prefix(PSTR_PAIR str, UINT count);
  548. };
  549. int inline sign(UCHAR val) { return val?1:0; }
  550. enum FuncOptions {
  551. FO_VAR_ARGS = 0x01,
  552. FO_UNSAFE = 0x02,
  553. FO_DOUBLEP = 0x04,
  554. FO_LINE_BEG = 0x08,
  555. FO_NOMACRO = 0x10,
  556. };
  557. struct Func : FieldHolder {
  558. const Prefix *prefix, *suffix;
  559. string _name;
  560. vector<string> Args; // all supplied args - var args
  561. vector<string> Goo; // values for GooId, usually = GooId
  562. vector<string> GooId; // all unrecognized args + LEV
  563. UCHAR Grp, MsgArg, Msg, Arg;
  564. UCHAR Num, Indent, MsgVal, Reserved;
  565. ULONG Options;
  566. size_t nAssumedArgs;
  567. void SetPS(const Prefix* val, const Prefix*& var, LPCSTR msg)
  568. {
  569. if (val && val->FmtStr.ArgCount > 0 && MsgArg) {
  570. ReportError("Function %s has (something,(MSG,...)) type\n"
  571. "It cannot have non-const %s\n",
  572. _name.c_str(), msg );
  573. }
  574. var = val;
  575. }
  576. void set(ULONG flag) { Options |= flag; }
  577. ULONG is(ULONG flag) const { return Options & flag; }
  578. void SetLineBeg() { Options |= FO_LINE_BEG; }
  579. void SetVarArgs() { Options |= FO_VAR_ARGS | FO_LINE_BEG; }
  580. void SetUnsafe() { Options |= FO_UNSAFE; }
  581. void SetDoubleP() { Options |= FO_DOUBLEP; }
  582. BOOL LineBeg() const { return Options & FO_LINE_BEG; }
  583. BOOL VarArgs() const { return Options & FO_VAR_ARGS; }
  584. BOOL Unsafe() const { return Options & FO_UNSAFE; }
  585. BOOL DoubleP() const { return Options & FO_DOUBLEP; }
  586. void SetPrefix(const Prefix* pr) { SetPS(pr,prefix,"prefix"); }
  587. void SetSuffix(const Prefix* sf) { SetPS(sf,suffix,"suffix"); }
  588. virtual BOOL Hidden(std::string str) const {
  589. if (str.size() == 0) { return FALSE; }
  590. if (is(FO_NOMACRO)) return str.compare("NoMacro") != 0;
  591. else if (str.compare("MsgArgs") == 0) { return !MsgArg; }
  592. else if (str.compare("!MsgArgs") == 0) { return MsgArg; }
  593. else if (str.compare("!DoubleP && !MsgArgs") == 0) { return !(!DoubleP() && !MsgArg); }
  594. else if (str.compare("DoubleP && !MsgArgs") == 0) { return !(DoubleP() && !MsgArg); }
  595. else { ReportError("Unknown filter '%s'\n", str.c_str()); exit(1); }
  596. return NULL;
  597. }
  598. #if 0
  599. // returns recognized argument count
  600. int count() const {
  601. return sign(Grp) + sign(Id) + sign(Msg) + sign(Arg);
  602. }
  603. #endif
  604. void printArgs(FILE* f) const {
  605. for(int i = 1; i <= Num; ++i) {
  606. if (i > 1) fprintf(f, ", ");
  607. else fprintf(f, "(");
  608. fprint_str(f, Args[i]);
  609. /*
  610. if (i == Grp) fprintf(f,"GRP");
  611. else if (i == Id) fprintf(f,"ID");
  612. else if (i == Msg) fprintf(f,"MSG");
  613. else if (i == Arg) fprintf(f,"ARG");
  614. else fprintf(f,"_unknown%d", i);
  615. */
  616. }
  617. fprintf(f, ")");
  618. }
  619. BEGIN_FIELD_TABLE(Func, out)
  620. TEXT_FIELD(Name) fprintf(out, "%s", _name.c_str() );
  621. TEXT_FIELD(Arguments) {printArgs(out);}
  622. TEXT_FIELD(MSG) {fprintf(out, Msg?"MSG":"\"\"");}
  623. TEXT_FIELD(ARG) {fprintf(out, Arg?"ARG":"");}
  624. TEXT_FIELD(GRP) {fprintf(out, Grp?"GRP":"WPP_DEFAULT_GROUP_ID");}
  625. // TEXT_FIELD(ID) {fprintf(out, Id?"ID":"WPP_AUTO_ID");}
  626. TEXT_FIELD(FixedArgs)
  627. {
  628. for(int i = 0; i < Args.size(); ++i) {
  629. fprint_str(out, Args[i]);
  630. fprintf(out,", ");
  631. }
  632. }
  633. TEXT_FIELD(GooArgs)
  634. {
  635. for(int i = 0; i < GooId.size(); ++i) {
  636. if (i > 0) fprintf(out,",");
  637. fprint_str(out, GooId[i]);
  638. }
  639. }
  640. TEXT_FIELD(GooVals)
  641. {
  642. for(int i = 0; i < Goo.size(); ++i) {
  643. if (i > 0) fprintf(out,", ");
  644. fprint_str(out, Goo[i]);
  645. }
  646. }
  647. TEXT_FIELD(GooId)
  648. {
  649. for(int i = 0; i < GooId.size(); ++i) {
  650. fprintf(out,"_");
  651. fprint_str(out, GooId[i]);
  652. }
  653. }
  654. END_FIELD_TABLE
  655. Func(){}
  656. Func(std::string Name):_name(Name),prefix(0),suffix(0),
  657. Grp(0), MsgArg(0), Msg(0), Arg(0),
  658. Num(0), Indent(0), MsgVal(0), Options(0),nAssumedArgs(0) {}
  659. };
  660. #define GRP(x) ((x).Grp)
  661. #define MSG(x) ((x).Msg)
  662. #define ARG(x) ((x).Arg)
  663. #define NUM(x) ((x).Num)
  664. //BOOL
  665. //UpgradeFormatSpecifiers(string& str, int startCount, string* TypeSig = 0);
  666. void printTraceGuid(FILE* f, int guidno);
  667. struct Message : FieldHolder {
  668. // string Msg;
  669. string IdName;
  670. string msgval;
  671. string Indent;
  672. string reorderSig;
  673. int LineNo;
  674. ParsedFormatString FormatStr;
  675. TypeSig* typeSig;
  676. const Func* func;
  677. vector<Argument> Args;
  678. vector<string> GooActualValues;
  679. UINT id;
  680. string TypeListHost;
  681. virtual BOOL Hidden(std::string str) const { return func->Hidden(str); }
  682. void hash(Hasher& hash) const;
  683. int ArgConsumed() const ;
  684. // void ChkArgs() const;
  685. BEGIN_FIELD_TABLE(Message, f)
  686. TEXT_FIELD(Text) { FormatStr.printMofTxt(f,LineNo); }
  687. TEXT_FIELD(Indent)
  688. {
  689. if(Indent.size()) {
  690. fprintf(f, "INDENT=");
  691. fprint_str(f, Indent);
  692. }
  693. }
  694. TEXT_FIELD(MsgNo) { fprintf(f, "%d", id & 0xFFFF); }
  695. TEXT_FIELD(GuidNo) { fprintf(f, "%d", id >> 16); }
  696. TEXT_FIELD(Guid) { printTraceGuid(f, id >> 16); }
  697. TEXT_FIELD(Name) { fprint_str(f, IdName ); }
  698. TEXT_FIELD(Line) { fprintf(f, "%d", LineNo ); }
  699. TEXT_FIELD(MsgVal) { fprint_str(f, msgval ); }
  700. TEXT_FIELD(ReorderSig) { fprint_str(f, reorderSig ); }
  701. TEXT_FIELD(TypeSig) { fprint_str(f, typeSig->Name); }
  702. TEXT_FIELD(Count) { fprintf(f, "%d", FormatStr.ArgCount); }
  703. // TEXT_FIELD(CtlMsg) { ??? }
  704. // TEXT_FIELD(Enabled)
  705. ENUM_FIELD(Arguments, Args, VectorTag)
  706. TEXT_FIELD(GooPairs)
  707. {
  708. size_t k = func->nAssumedArgs;
  709. // print assumed arguments
  710. for(size_t i = 0; i < k; ++i) {
  711. fprintf(f, " ");
  712. fprint_str(f, func->GooId[i]);
  713. fprintf(f, "=");
  714. fprint_str(f, func->Goo[i]);
  715. }
  716. // print the goo we pulled out of the trace statement itself
  717. size_t n = min(func->GooId.size()-k, GooActualValues.size());
  718. for(size_t i = 0; i < n; ++i) {
  719. fprintf(f, " ");
  720. fprint_str(f, func->GooId[i+k]);
  721. fprintf(f, "=");
  722. fprint_str(f, GooActualValues[i]);
  723. }
  724. }
  725. TEXT_FIELD(FixedArgs)
  726. {
  727. for(int i = 0; i < func->Args.size(); ++i) {
  728. fprint_str(f, func->Args[i]);
  729. fprintf(f, ", ");
  730. }
  731. }
  732. TEXT_FIELD(GooVals)
  733. {
  734. for(int i = 0; i < func->Goo.size(); ++i) {
  735. if (i > 0) fprintf(f,", ");
  736. fprint_str(f, func->Goo[i]);
  737. }
  738. }
  739. TEXT_FIELD(GooArgs)
  740. {
  741. for(int i = 0; i < func->GooId.size(); ++i) {
  742. if (i > 0) fprintf(f,",");
  743. fprint_str(f, func->GooId[i]);
  744. }
  745. }
  746. TEXT_FIELD(GooId)
  747. {
  748. for(int i = 0; i < func->GooId.size(); ++i) {
  749. fprintf(f,"_");
  750. fprint_str(f, func->GooId[i]);
  751. }
  752. }
  753. TEXT_FIELD(MacroExprs)
  754. {
  755. for(int i = 0; i < Args.size(); ++i) {
  756. if (Args[i].OverrideName.size() > 0) {
  757. fprintf(f,",");
  758. fprint_str(f, Args[i].OverrideName);
  759. } else {
  760. fprintf(f, ",a%d", Args[i].No);
  761. }
  762. }
  763. }
  764. TEXT_FIELD(MacroArgs)
  765. {
  766. fprintf(f,"MSG");
  767. for(int i = 0; i < Args.size(); ++i) {
  768. if (Args[i].OverrideName.size() > 0) {
  769. // fprint_str(f, Args[i].OverrideName);
  770. } else {
  771. // if (i != 0) fprintf(f,",");
  772. fprintf(f, ",a%d", i + MSGTYPBASE);
  773. }
  774. }
  775. }
  776. END_FIELD_TABLE
  777. Message(){}
  778. Message(
  779. const string& idTxt,
  780. const string&,
  781. const vector<Argument>&,
  782. UINT msgid,
  783. int lineno,
  784. const ParsedFormatString& fmtStr,
  785. const Func& aFunc
  786. )
  787. :IdName(idTxt), id(msgid), LineNo(lineno),
  788. FormatStr(fmtStr),func(&aFunc)
  789. {
  790. Args.resize(FormatStr.ArgCount, Argument("",0) );
  791. for(int i = 0; i < FormatStr.Items.size(); ++i) {
  792. int no = FormatStr.Items[i].no;
  793. if (no > 0) {
  794. Args[no-1] = Argument
  795. (FormatStr.Items[i].expr, FormatStr.Items[i].type);
  796. Args[no-1].OverrideName = FormatStr.Items[i].argName;
  797. Args[no-1].No = no-1 + MSGTYPBASE;
  798. }
  799. }
  800. if (reorder) {
  801. sort(Args.begin(), Args.end());
  802. }
  803. for (int j = 0; j < FormatStr.Items.size(); ++j) {
  804. int& no = FormatStr.Items[j].no;
  805. if (no > 0) {
  806. // find new msg no for that
  807. for(int k = 0; k < Args.size(); ++k) {
  808. if (Args[k].No == no-1 + MSGTYPBASE) {
  809. no = MSGTYPBASE + k;
  810. break;
  811. }
  812. }
  813. // Args[no-1].OverrideName = FormatStr.Items[i].argName;
  814. }
  815. }
  816. typeSig = GetTypeSig(Args, func->Unsafe());
  817. if (func->MsgArg) {
  818. reorderSig = GetReorderSig(Args);
  819. }
  820. // UpgradeFormatSpecifiers(Msg, 10, (typeSig.size())?0:&TypeSig);
  821. // ChkArgs();
  822. }
  823. };
  824. struct File : FieldHolder {
  825. string _CanonicalName; // lower case, bad chars => _
  826. string _Path;
  827. string _UppercaseName; // uppercase canonical
  828. string _Name;
  829. string _BaseName; // no extension
  830. ULONGLONG ModificationTime;
  831. //
  832. // Since the file is a member of the set type
  833. // fields that don't affect set membership should be mutables
  834. //
  835. mutable vector<Message*> Msgs;
  836. mutable set<string, strless> IdsFound;
  837. BEGIN_FIELD_TABLE(File, out)
  838. TEXT_FIELD(Name) fprint_str(out, _Name );
  839. TEXT_FIELD(Path) fprint_str(out, _Path );
  840. TEXT_FIELD(CanonicalName) fprint_str(out, _CanonicalName );
  841. TEXT_FIELD(UppercaseName) fprint_str(out, _UppercaseName );
  842. ENUM_FIELD(Messages, Msgs, VectorPtrTag)
  843. END_FIELD_TABLE
  844. File(){} // to make STL and compiler happy
  845. string FullFileName() const {
  846. string Tmp(_Path);
  847. Tmp.append(_Name);
  848. return Tmp;
  849. }
  850. File(const string& FileName, const string& Path, const WIN32_FIND_DATA& FindData)
  851. :_Name(FileName), _Path(Path)
  852. {
  853. CopyMemory(&ModificationTime, &FindData.ftLastWriteTime, sizeof(ModificationTime));
  854. // Canonicalize FileName
  855. // i.e. make it suitable to be a DEFINE name
  856. //
  857. // Cut the path out. Replace all non-alphanumeric symbols
  858. // with an underscore.
  859. string::size_type pos = _Name.rfind('\\');
  860. if (pos == string::npos) {
  861. // No back slash
  862. _CanonicalName.assign(_Name);
  863. } else {
  864. // Get only the name part
  865. _CanonicalName.assign(_Name.begin() + pos, _Name.end());
  866. }
  867. // strip extension for a base name
  868. string::size_type ext = _CanonicalName.rfind('.');
  869. if (ext != string::npos) {
  870. // there was a "."
  871. _BaseName.assign(_CanonicalName.begin(),
  872. _CanonicalName.begin() + ext);
  873. } else {
  874. _BaseName.assign(_CanonicalName);
  875. }
  876. // Can't have a digit in the first position
  877. // Let's prepend it with an underscore
  878. {
  879. char ch = _CanonicalName[0];
  880. if ( ch >= '0' && ch <= '9' ) {
  881. _CanonicalName.insert(0, '_');
  882. }
  883. }
  884. _UppercaseName.assign( _CanonicalName );
  885. for(UINT i = 0; i < _CanonicalName.size(); ++i) {
  886. char ch = _CanonicalName[i];
  887. if ( (ch == '_')
  888. || ((ch >= 'A') && (ch <= 'Z'))
  889. || ((ch >= '0') && (ch <= '9')) )
  890. {
  891. // Good Character. Do nothing
  892. } else if ( (ch >= 'a') && (ch <= 'z') ) {
  893. _UppercaseName[i] = static_cast<char>(ch - 'a' + 'A');
  894. } else {
  895. _CanonicalName[i] = '_';
  896. _UppercaseName[i] = '_';
  897. }
  898. }
  899. }
  900. bool operator < (const File& b) const {
  901. return _CanonicalName.compare(b._CanonicalName) < 0;
  902. }
  903. };
  904. int Message::ArgConsumed() const
  905. {
  906. vector<Argument>::const_iterator i = Args.begin();
  907. int sum = 0;
  908. for(;i != Args.end(); ++i) {
  909. sum += i->Type->ArgConsumed;
  910. }
  911. return sum;
  912. }
  913. void Message::hash(Hasher& hash) const
  914. {
  915. vector<Argument>::const_iterator i = Args.begin();
  916. for(;i != Args.end(); ++i) {
  917. i->hash(hash);
  918. }
  919. hash.Hash(&id, sizeof(id));
  920. hash.Hash(IdName);
  921. hash.Hash(FormatStr.HostString);
  922. }
  923. typedef map<string, string, strless > TYPE_MAP;
  924. typedef map<string, Message, strless > MSG_MAP;
  925. //typedef map<string, WppTyp, strless > MACRO_MAP;
  926. typedef map<string, Func, strless > FUNC_MAP;
  927. typedef map<string, Group, strless> GROUP_MAP;
  928. typedef vector< Prefix > PREFIX_VECTOR;
  929. typedef set<File> FILES;
  930. FILES::iterator CurrentFile;
  931. string CurrentTpl;
  932. string currentFileName()
  933. { return CurrentFile->_Name; }
  934. void MsgMapHash(
  935. const MSG_MAP& msgmap,
  936. Hasher& hash
  937. )
  938. {
  939. MSG_MAP::iterator i = msgmap.begin();
  940. for(;i != msgmap.end(); ++i) {
  941. i->second.hash(hash);
  942. }
  943. }
  944. void expand(IN OUT string& str, const string& id);
  945. BOOL
  946. parseMsg(
  947. IN LPCSTR beg,
  948. IN LPCSTR end,
  949. IN OUT string& str,
  950. OUT LPCSTR* strend = 0
  951. )
  952. {
  953. LPCSTR p = beg;
  954. for(;;) {
  955. if (*p == '_' || isalpha(*p)) {
  956. const char * id = p;
  957. for(;;) {
  958. if (++p == end) { expand(str, string(id,p)); goto done; }
  959. if (*p == '_' || isalpha(*p) || isdigit(*p)) continue;
  960. break;
  961. }
  962. expand(str, string(id,p));
  963. }
  964. if (*p == ',') goto done;
  965. if (*p == '"') {
  966. const char * run = ++p;
  967. for(;;) {
  968. if (p == end) goto unterminated;
  969. if (*p == '"' && p[-1] != '\\') break;
  970. ++p;
  971. }
  972. str.append(run,p);
  973. }
  974. if (++p == end) break;
  975. }
  976. done:
  977. if (str.size() == 0) {
  978. ReportError("parsing %s. Cannot find format string\n",
  979. string(beg,end).c_str() );
  980. return FALSE;
  981. }
  982. // eat whitespace at the end
  983. while (str.size() > 0 && isspace( str.end()[-1]) )
  984. { str.resize(str.size()-1); }
  985. // get rid of pesky trailing \n
  986. if (str.size() >= 2 && str.end()[-1] == 'n' && str.end()[-2] == '\\') {
  987. str.resize(str.size()-2);
  988. }
  989. Flood("msg: \"%s\".\n", str.c_str() );
  990. if (strend) {
  991. *strend = p;
  992. }
  993. return TRUE;
  994. unterminated:
  995. ReportError("Unterminated string constant\n");
  996. return FALSE;
  997. }
  998. BOOL
  999. parseArgs(
  1000. IN LPCSTR beg,
  1001. IN LPCSTR end,
  1002. IN OUT vector<Argument>& args
  1003. );
  1004. #define isvar(x) ( isalnum(x) || (x == '_') )
  1005. /*
  1006. ArgType::ArgType(
  1007. IN const WppType* wppType):Type(0),TypevString(wppType->FormatSpec), NativeType(wppType),Used(FALSE)
  1008. {
  1009. MofType = wppType->MofType;
  1010. ExtendedType = wppType->Extension;
  1011. }
  1012. */
  1013. Prefix::Prefix(
  1014. IN PSTR_PAIR str,
  1015. IN UINT count):FuncName(str[1].beg, str[1].end)
  1016. {
  1017. vector<string> ArgNames;
  1018. if (count > 2) {
  1019. string msg;
  1020. if (str[2].beg < str[2].end &&
  1021. str[2].beg[0] == '"') parseMsg(str[2].beg, str[2].end, msg);
  1022. else msg.assign(str[2].beg, str[2].end);
  1023. FmtStr.init( msg );
  1024. }
  1025. if (count > 3) {
  1026. count -= 3; str += 2;
  1027. while (count-- > 0) {
  1028. ++str; ArgNames.push_back( string(str->beg,str->end) );
  1029. }
  1030. }
  1031. // check that sizes match //
  1032. if (ArgNames.size() > FmtStr.ArgCount ) {
  1033. ReportError("Prefix: Extra argument. Only %d are specified in the string\n", FmtStr.ArgCount);
  1034. exit(1);
  1035. }
  1036. if (ArgNames.size() < FmtStr.ArgCount ) {
  1037. ReportError("Prefix: Not enough args. %d are specified in the string\n", FmtStr.ArgCount);
  1038. exit(1);
  1039. }
  1040. for(int i = 0; i < FmtStr.Items.size(); ++i) {
  1041. int no = FmtStr.Items[i].no;
  1042. if (no > 0) {
  1043. FmtStr.Items[i].argName = ArgNames[no-1];
  1044. FmtStr.Items[i].expr = ArgNames[no-1];
  1045. }
  1046. }
  1047. }
  1048. struct GuidEntry : FieldHolder {
  1049. GUID guid;
  1050. string comment;
  1051. int count;
  1052. vector<Message*> Msgs;
  1053. void printTxt(FILE* f) const {
  1054. fprintf(f,"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  1055. guid.Data1,guid.Data2,guid.Data3,
  1056. guid.Data4[0],guid.Data4[1],guid.Data4[2],guid.Data4[3],
  1057. guid.Data4[4],guid.Data4[5],guid.Data4[6],guid.Data4[7] );
  1058. }
  1059. void printDat(FILE* f) const {
  1060. fprintf(f,"{0x%08x,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}}",
  1061. guid.Data1,guid.Data2,guid.Data3,
  1062. guid.Data4[0],guid.Data4[1],guid.Data4[2],guid.Data4[3],
  1063. guid.Data4[4],guid.Data4[5],guid.Data4[6],guid.Data4[7] );
  1064. }
  1065. BEGIN_FIELD_TABLE(GuidEntry, f)
  1066. TEXT_FIELD(Text) { printTxt(f); }
  1067. TEXT_FIELD(Struct) { printDat(f);}
  1068. TEXT_FIELD(Comment) fprintf(f, "%s", comment.c_str() );
  1069. ENUM_FIELD(Messages, Msgs, VectorPtrTag);
  1070. END_FIELD_TABLE
  1071. GuidEntry(){}
  1072. GuidEntry(int cnt, const string& cmnt):count(cnt),comment(cmnt) {
  1073. RPC_STATUS status = UuidCreate( &guid );
  1074. if ( status != RPC_S_OK ) {
  1075. ReportError("UuidCreate failed with error %s\n", status);
  1076. exit(1);
  1077. }
  1078. }
  1079. GuidEntry(PSTR_PAIR p, int cnt, const string& cmnt):count(cnt),comment(cmnt)
  1080. {
  1081. guid.Data1 = Hex(p->beg + 0, 8);
  1082. guid.Data2 = (USHORT)Hex(p->beg + 9, 4);
  1083. guid.Data3 = (USHORT)Hex(p->beg + 14, 4);
  1084. guid.Data4[0] = (UCHAR) Hex(p->beg + 19, 2);
  1085. guid.Data4[1] = (UCHAR) Hex(p->beg + 21, 2);
  1086. guid.Data4[2] = (UCHAR) Hex(p->beg + 24, 2);
  1087. guid.Data4[3] = (UCHAR) Hex(p->beg + 26, 2);
  1088. guid.Data4[4] = (UCHAR) Hex(p->beg + 28, 2);
  1089. guid.Data4[5] = (UCHAR) Hex(p->beg + 30, 2);
  1090. guid.Data4[6] = (UCHAR) Hex(p->beg + 32, 2);
  1091. guid.Data4[7] = (UCHAR) Hex(p->beg + 34, 2);
  1092. }
  1093. };
  1094. struct Guids : FieldHolder {
  1095. UINT min_val;
  1096. UINT max_val;
  1097. vector<GuidEntry> guids;
  1098. int current;
  1099. string currentFileName;
  1100. Guids(int lo, int hi) : min_val(lo),max_val(hi),current(0) {}
  1101. void erase() {current = 0; guids.erase(guids.begin(), guids.end());}
  1102. BEGIN_FIELD_TABLE(Guids, f)
  1103. TEXT_FIELD(Count) fprintf(f, "%d", min(current+1, (signed)guids.size()) );
  1104. DEFAULT_ENUM_FIELD(guids, VectorTag)
  1105. END_FIELD_TABLE
  1106. //void add_guid(PSTR_PAIR p) { }
  1107. ULONG getid() {
  1108. for(;;) {
  1109. if ( current == (signed)guids.size() ) {
  1110. guids.push_back(GuidEntry(max_val - min_val + 1, currentFileName) );
  1111. }
  1112. if ( guids[current].count ) {
  1113. ULONG ret = (max_val + 1 - guids[current].count--) | ( current << 16 );
  1114. return ret;
  1115. }
  1116. ++current;
  1117. }
  1118. }
  1119. void add_guids(PSTR_PAIR p, int count) {
  1120. --count; ++p; // skip func name //
  1121. string comment(p->beg,p->end);
  1122. while (--count) {
  1123. guids.push_back(GuidEntry(++p, max_val - min_val + 1, comment));
  1124. }
  1125. }
  1126. void new_file(const char* fname) {
  1127. currentFileName.assign(fname);
  1128. // this will force a new guid to be allocated
  1129. // when a new id is required
  1130. current = static_cast<int>(guids.size());
  1131. }
  1132. };
  1133. struct GenPair {
  1134. string tpl;
  1135. string out;
  1136. GenPair(){} // STL pleaser
  1137. GenPair(const string& a, const string& b)
  1138. :tpl(a),out(b) {}
  1139. };
  1140. //TYPE_MAP AutoGen;
  1141. TYPE_MAP TypeMap;
  1142. MSG_MAP MsgMap;
  1143. //MACRO_MAP MacroMap;
  1144. FUNC_MAP Funcs;
  1145. GROUP_MAP Groups;
  1146. PREFIX_VECTOR Prefixes;
  1147. PREFIX_VECTOR Suffixes;
  1148. //Guids CtrlGuids(0,31);
  1149. Guids TraceGuids(10,65535);
  1150. FILES Files;
  1151. vector<string> ScanForMacros;
  1152. vector<string> Touch;
  1153. vector<GenPair>GenMulti;
  1154. vector<GenPair>GenSingle;
  1155. set<string, strless> LookFor;
  1156. void printTraceGuid(FILE* f, int guidno)
  1157. {
  1158. TraceGuids.guids[guidno].printTxt(f);
  1159. }
  1160. struct Keyword {
  1161. int nParams; // if < 0 then at least -nParams, otherwise = nParams //
  1162. EZPARSE_CALLBACK handler;
  1163. int id;
  1164. PVOID context;
  1165. Keyword(){}
  1166. Keyword(EZPARSE_CALLBACK func,
  1167. int n, UINT i, PVOID ctx) : nParams(n), handler(func), id(i), context(ctx) {}
  1168. };
  1169. typedef map<string, Keyword, strless> KEYWORD_MAP;
  1170. KEYWORD_MAP Keywords;
  1171. #if DEPRECATED
  1172. //BOOL GenerateTypeTable;
  1173. string TypeTableBegin;
  1174. string TypeTableEntry;
  1175. string TypeTableEnd;
  1176. string TypeTablePrefix;
  1177. string GuidStore;
  1178. #endif
  1179. const string CtlStr("LEVEL"); // the same as GRP
  1180. const string MakeStr("MAKESTR");
  1181. const string MsgArgStrUnsafe("(MSG,..unsafe..)");
  1182. const string MsgArgStr("(MSG,...)");
  1183. const string MsgValStr("MsgVal");
  1184. const string MsgStr("MSG");
  1185. const string ArgStr("...");
  1186. const string ArgStrUnsafe("..unsafe..");
  1187. const string IndentStr("INDENT");
  1188. const string NullStr("NULL");
  1189. bool
  1190. Files_AddFile(const string& Name, string Path, const WIN32_FIND_DATA& FindData)
  1191. {
  1192. if (!AllowedExtension(Name)) {
  1193. return FALSE;
  1194. }
  1195. pair<FILES::iterator, bool> result = Files.insert(File(Name,Path,FindData));
  1196. if (!result.second) {
  1197. if (Name.compare(result.first->_Name) == 0) {
  1198. ReportError("File %s was already in the processing list\n");
  1199. } else {
  1200. ReportError("Files %s and %s have the same canonical name %s\n",
  1201. Name.c_str(),
  1202. result.first->_Name.c_str(),
  1203. result.first->_CanonicalName.c_str());
  1204. }
  1205. }
  1206. return result.second;
  1207. }
  1208. int
  1209. compare(const string& a, const STR_PAIR& b)
  1210. {
  1211. return a.compare(0, a.length(), b.beg, b.end - b.beg);
  1212. }
  1213. BOOL
  1214. parseLegacy(
  1215. IN PSTR_PAIR strs,
  1216. IN INT count,
  1217. IN INT hole, // args - msg, usually one
  1218. IN OUT string& Msg,
  1219. IN OUT vector<Argument>&,
  1220. OUT ParsedFormatString& FmtStr
  1221. )
  1222. {
  1223. vector<string> ArgNames;
  1224. STR_PAIR buf = *strs;
  1225. LPCSTR p = buf.beg, q;
  1226. int i;
  1227. if ( p < buf.end && buf.end[-1] == ')' ) --buf.end;
  1228. if(!parseMsg(buf.beg, buf.end, Msg, &p)) {
  1229. return FALSE;
  1230. }
  1231. if( !FmtStr.init(Msg) ) {
  1232. return FALSE;
  1233. }
  1234. ArgNames.reserve(FmtStr.ArgCount);
  1235. if (count == 1) {
  1236. // need to grok args from the string
  1237. // Let's get to the first ','
  1238. if (p == buf.end) goto success;
  1239. while(*p != ',') if (++p == buf.end) goto success;
  1240. q = ++p;
  1241. for(i = 0;;++i) {
  1242. int parlevel = 0;
  1243. // currently we don't deal with the case of commas or parents within '"'
  1244. while (p < buf.end) {
  1245. if (parlevel == 0 && *p == ',') break;
  1246. if (*p == '(') ++parlevel;
  1247. if (*p == ')') {
  1248. if (--parlevel < 0)
  1249. {ReportError("Too many ')'\n"); return FALSE;}
  1250. }
  1251. ++p;
  1252. }
  1253. if (parlevel > 0) {
  1254. ReportError("No closing ')'");
  1255. }
  1256. LPCSTR tmp = p; // remember where we were
  1257. while (q < p && isspace(*q)) ++ q;
  1258. while (q < p && isspace(p[-1])) --p;
  1259. ArgNames.push_back( string(q,p) );
  1260. p = tmp;
  1261. if (p == buf.end) break;
  1262. q = ++p;
  1263. }
  1264. } else {
  1265. // arguments were supplied in strs
  1266. strs += hole; count -= hole;
  1267. while (count-- > 0) {
  1268. ArgNames.push_back( string(strs->beg,strs->end) );
  1269. ++strs;
  1270. }
  1271. }
  1272. success:
  1273. // check that sizes match //
  1274. if ((unsigned)ArgNames.size() != (unsigned)FmtStr.ArgCount ) {
  1275. ReportError("%d argument(s) expected, argument(s) supplied: %d\n", FmtStr.ArgCount, ArgNames.size());
  1276. return FALSE;
  1277. }
  1278. for(i = 0; i < FmtStr.Items.size(); ++i) {
  1279. int no = FmtStr.Items[i].no;
  1280. if (no > 0) {
  1281. FmtStr.Items[i].expr = ArgNames[no-1];
  1282. }
  1283. }
  1284. return TRUE;
  1285. }
  1286. BOOL
  1287. parseArgs(
  1288. IN LPCSTR beg,
  1289. IN LPCSTR end,
  1290. IN OUT vector<Argument>& args
  1291. )
  1292. {
  1293. LPCSTR p = beg;
  1294. // MACRO_MAP::iterator macro;
  1295. TYPE_SET::iterator macro;
  1296. for(;;) {
  1297. while ( isspace(*p) ) {
  1298. if (++p == end) return TRUE;
  1299. }
  1300. LPCSTR q = p; // id start
  1301. while ( isvar(*p) ) {
  1302. if (++p == end) return TRUE;
  1303. }
  1304. macro = TypeSet.find( string(q, p) );
  1305. if ( macro == TypeSet.end() ) {
  1306. if (p == q) {
  1307. q = beg;
  1308. p = end;
  1309. }
  1310. ReportError("Unknown type: %s\n", string(q, p).c_str() );
  1311. return FALSE;
  1312. }
  1313. macro->second.Used = TRUE;
  1314. while ( *p != '(') {
  1315. if (++p == end) return TRUE;
  1316. }
  1317. q = p; // now q points to '('
  1318. int level = 0;
  1319. for (;;) {
  1320. if (*p == '(') {
  1321. ++level;
  1322. } else if (*p == ')') {
  1323. if (--level == 0) {
  1324. break;
  1325. }
  1326. }
  1327. if (++p == end) return TRUE;
  1328. }
  1329. args.push_back( Argument(string(q+1,p), &macro->second) );
  1330. if (++p == end) return TRUE;
  1331. }
  1332. // return TRUE; // unreachable code
  1333. }
  1334. enum {
  1335. // ID_UseTraceGuid,
  1336. // ID_UseCtrlGuid,
  1337. // ID_GrpidRange,
  1338. ID_TraceRange,
  1339. ID_ProcessFiles,
  1340. ID_TemplateFile,
  1341. // ID_OutputInc,
  1342. // ID_OutputMof,
  1343. // ID_OutputRc,
  1344. // ID_OutputCode,
  1345. ID_TypeMacro,
  1346. ID_TypevMacro,
  1347. ID_Include,
  1348. ID_UsePrefix,
  1349. ID_UseSuffix,
  1350. ID_NoPrefix,
  1351. // ID_ArrayPrefix,
  1352. ID_DefineSimpleTypePtr,
  1353. ID_DefineSimpleType,
  1354. ID_DefineCplxType,
  1355. ID_CustomType,
  1356. ID_DefineFlavor,
  1357. ID_SeparateTraceGuidPerFile,
  1358. ID_Touch,
  1359. ID_ScanForMacros,
  1360. ID_GenerateTypeTable,
  1361. // ID_AutoGen,
  1362. ID_Exceptions,
  1363. ID_WppFlags,
  1364. };
  1365. void
  1366. UpdateIntVar(
  1367. UINT* var,
  1368. PSTR_PAIR Str
  1369. )
  1370. {
  1371. LPCSTR p = Str->beg, q = Str->end;
  1372. UINT x = 0;
  1373. while (p != q && isdigit(*p) ) {
  1374. x = (x * 10) + (*p - '0');
  1375. ++p;
  1376. }
  1377. *var = x;
  1378. }
  1379. void parseAssumedArgs(Func& f,LPCSTR beg, LPCSTR end)
  1380. {
  1381. // we have a string of A=value1,B=value2,C=value3,...,F=valuen}
  1382. // we need to put A,B,C into f.GooId,
  1383. // and value1, value2, value3 into f.Goo
  1384. LPCSTR p = beg, q, stop;
  1385. if (p >= end) return;
  1386. Flood("Got %p %p\n", beg, end );
  1387. for(;p < end;) {
  1388. while (isspace(*p)) ++p; // cannot have spaces all the way. there is '}'
  1389. if (p == end) return;
  1390. q = p++;
  1391. while (p < end && *p != '=') ++p;
  1392. if (p == end) {
  1393. ReportError("Missing '=' in %s\n", string(beg,end).c_str() ); exit(1); }
  1394. stop = p;
  1395. while (--p > q && isspace(*p));
  1396. if (p == q) {
  1397. ReportError("Id required before '=' in %s\n", string(beg,end).c_str() ); exit(1); }
  1398. f.GooId.push_back( string(q,p+1) );
  1399. p = stop + 1;
  1400. while (isspace(*p)) ++p; // cannot have spaces all the way. there is '}'
  1401. q = p++;
  1402. while (*p != '}' && *p != ',') ++p;
  1403. stop = p;
  1404. while (--p > q && isspace(*p));
  1405. if (isspace(*p)) { // BUGBUG Verify that this condition is correct
  1406. ReportError("value required after '=' in %s\n", string(beg,end).c_str() ); exit(1); }
  1407. f.Goo.push_back( string(q,p+1) );
  1408. if (*stop == '}') break;
  1409. p = stop + 1;
  1410. }
  1411. f.nAssumedArgs = f.Goo.size();
  1412. }
  1413. DWORD
  1414. ParseConfigCallback (
  1415. IN PSTR_PAIR Str,
  1416. IN INT Count,
  1417. IN PVOID Context,
  1418. IN PEZPARSE_CONTEXT ParseContext
  1419. )
  1420. {
  1421. string Name(Str[0].beg, Str[0].end);
  1422. KEYWORD_MAP::iterator keyword = Keywords.find(Name);
  1423. if (Context) {
  1424. // We need to ignore all the keywords besides ID_TypeMacro //
  1425. if (keyword != Keywords.end() && keyword->second.id == ID_TypeMacro) {
  1426. // proceed and do the job //
  1427. } else {
  1428. // Ignore everything else
  1429. return ERROR_SUCCESS;
  1430. }
  1431. }
  1432. if (keyword != Keywords.end() ) {
  1433. if (keyword->second.nParams < 0 && Count - 1 < -keyword->second.nParams ) {
  1434. ReportError("%s requires at least %d parameter(s)\n",
  1435. Name.c_str(), -keyword->second.nParams);
  1436. return ERROR_INVALID_PARAMETER;
  1437. }
  1438. if (keyword->second.nParams > 0 && Count - 1 != keyword->second.nParams ) {
  1439. ReportError("%s requires %d parameter(s) (we have %s)\n",
  1440. Name.c_str(), keyword->second.nParams, std::string(Str[1].beg, Str[Count-1].end).c_str() );
  1441. return ERROR_INVALID_PARAMETER;
  1442. }
  1443. switch (keyword->second.id) {
  1444. #ifdef DEPRECATED
  1445. case ID_UseTraceGuid:
  1446. TraceGuids.add_guids(Str+1, Count-1);
  1447. break;
  1448. case ID_UseCtrlGuid:
  1449. CtrlGuids.add_guids(Str+1, Count-1);
  1450. break;
  1451. case ID_SeparateTraceGuidPerFile:
  1452. UpdateIntVar((UINT*)(keyword->second.context), Str+1);
  1453. break;
  1454. case ID_GrpidRange:
  1455. UpdateIntVar(&CtrlGuids.min_val, Str+1); UpdateIntVar(&CtrlGuids.max_val, Str+2);
  1456. break;
  1457. #endif
  1458. case ID_TraceRange:
  1459. UpdateIntVar(&TraceGuids.min_val, Str+1); UpdateIntVar(&TraceGuids.max_val, Str+2);
  1460. break;
  1461. case ID_ProcessFiles:
  1462. while(--Count) { ++Str; Fill( string(Str->beg, Str->end) ); }
  1463. break;
  1464. case ID_WppFlags:
  1465. while(--Count) { ++Str; if(*Str->beg == '-') ++Str->beg; DealWithCmdLineOptions( Str->beg, Str->end ); }
  1466. Unusual("\n");
  1467. break;
  1468. case ID_ScanForMacros:
  1469. while(--Count) { ++Str; ScanForMacros.push_back( string(Str->beg, Str->end) ); }
  1470. break;
  1471. case ID_Touch:
  1472. while(--Count) { ++Str; Touch.push_back( string(Str->beg, Str->end) ); }
  1473. break;
  1474. case ID_DefineSimpleType:
  1475. {
  1476. string Name(Str[1].beg, Str[1].end);
  1477. if (Str[4].beg < Str[4].end && *Str[4].beg == '"') Str[4].beg++;
  1478. if (Str[4].beg < Str[4].end && Str[4].end[-1] == '"') Str[4].end--;
  1479. if (TypeSet.find(Name) != TypeSet.end()) {
  1480. if (IgnoreDupTypes) {
  1481. return ERROR_SUCCESS;
  1482. }
  1483. ReportError("Type %s is already defined\n", Name.c_str() );
  1484. break;
  1485. }
  1486. Flood(" type %s\n", Name.c_str());
  1487. TypeSet[Name] = WppType( Name , // name
  1488. string(Str[2].beg, Str[2].end), // c-type
  1489. SimpleValueMacroStart,
  1490. string(Str[3].beg, Str[3].end), // mof type
  1491. "", // MofExtension
  1492. string(Str[4].beg, Str[4].end),
  1493. string(Str[5].beg, Str[5].end),
  1494. stoi(Str[6], "priority"),
  1495. Count > 7?stoi(Str[7], "argused"):1
  1496. );
  1497. break;
  1498. }
  1499. case ID_DefineSimpleTypePtr:
  1500. {
  1501. string Name(Str[1].beg, Str[1].end);
  1502. if (Str[4].beg < Str[4].end && *Str[4].beg == '"') Str[4].beg++;
  1503. if (Str[4].beg < Str[4].end && Str[4].end[-1] == '"') Str[4].end--;
  1504. if (TypeSet.find(Name) != TypeSet.end()) {
  1505. if (IgnoreDupTypes) {
  1506. return ERROR_SUCCESS;
  1507. }
  1508. ReportError("Type %s is already defined\n", Name.c_str() );
  1509. break;
  1510. }
  1511. TypeSet[Name] = WppType( Name , // name
  1512. string(Str[2].beg, Str[2].end), // c-type
  1513. SimplePtrMacroStart,
  1514. string(Str[3].beg, Str[3].end), // mof type
  1515. "", // MofExtension
  1516. string(Str[4].beg, Str[4].end),
  1517. string(Str[5].beg, Str[5].end),
  1518. stoi(Str[6], "priority"),
  1519. Count > 7?stoi(Str[7], "argused"):1
  1520. );
  1521. break;
  1522. }
  1523. case ID_DefineCplxType:
  1524. {
  1525. string Name(Str[1].beg, Str[1].end);
  1526. string MacroStart(Str[2].beg, Str[2].end);
  1527. MacroStart.append("(");
  1528. if (Str[5].beg < Str[5].end && *Str[5].beg == '"') Str[5].beg++;
  1529. if (Str[5].beg < Str[5].end && Str[5].end[-1] == '"') Str[5].end--;
  1530. if (TypeSet.find(Name) != TypeSet.end()) {
  1531. if (IgnoreDupTypes) {
  1532. return ERROR_SUCCESS;
  1533. }
  1534. ReportError("Type %s is already defined\n", Name.c_str() );
  1535. break;
  1536. }
  1537. TypeSet[Name] = WppType( Name , // name
  1538. string(Str[3].beg, Str[3].end), // equiv type
  1539. MacroStart,
  1540. string(Str[4].beg, Str[4].end), // mof type
  1541. "", // MofExtension
  1542. string(Str[5].beg, Str[5].end),
  1543. string(Str[6].beg, Str[6].end),
  1544. stoi(Str[7], "priority"),
  1545. Count > 8?stoi(Str[8], "argused"):1
  1546. );
  1547. }
  1548. break;
  1549. case ID_DefineFlavor:
  1550. {
  1551. string Name(Str[1].beg, Str[1].end);
  1552. string BaseType(Str[2].beg, Str[2].end);
  1553. TYPE_SET::const_iterator it = TypeSet.find(BaseType);
  1554. if (Str[4].beg < Str[4].end && *Str[4].beg == '"') Str[4].beg++;
  1555. if (Str[4].beg < Str[4].end && Str[4].end[-1] == '"') Str[4].end--;
  1556. if (it == TypeSet.end()) {
  1557. ReportError("Type Not Found %s\n", BaseType.c_str());
  1558. break;
  1559. }
  1560. if (TypeSet.find(Name) != TypeSet.end()) {
  1561. if (IgnoreDupTypes) {
  1562. return ERROR_SUCCESS;
  1563. }
  1564. ReportError("Type %s is already defined\n", Name.c_str() );
  1565. break;
  1566. }
  1567. WppType Flavor(it->second);
  1568. Flavor.TypeName = Name;
  1569. if (!Str[3].empty())
  1570. { Flavor.MofType.assign(Str[3].beg, Str[3].end); }
  1571. if (!Str[4].empty())
  1572. { Flavor.FormatSpec.assign(Str[4].beg, Str[4].end); }
  1573. TypeSet[Name] = Flavor;
  1574. break;
  1575. }
  1576. case ID_TypeMacro:
  1577. case ID_CustomType:
  1578. {
  1579. string Name(Str[1].beg, Str[1].end);
  1580. LPCSTR p = Str[2].beg, q = Str[2].end;
  1581. while (p < Str[2].end && *p != '(') ++p;
  1582. if (p < Str[2].end) {
  1583. q = p-1;
  1584. while (q >= Str[2].beg && isspace(*q)) --q;
  1585. ++q;
  1586. }
  1587. string BaseType(Str[2].beg, q);
  1588. TYPE_SET::const_iterator it = TypeSet.find(BaseType);
  1589. if (it == TypeSet.end()) {
  1590. ReportError("Type Not Found %s\n", BaseType.c_str());
  1591. break;
  1592. }
  1593. if (TypeSet.find(Name) != TypeSet.end()) {
  1594. if (IgnoreDupTypes) {
  1595. return ERROR_SUCCESS;
  1596. }
  1597. ReportError("Type %s is already defined\n", Name.c_str() );
  1598. break;
  1599. }
  1600. if (Count == 4) {
  1601. if (Str[3].beg < Str[3].end && *Str[3].beg == '"') Str[3].beg++;
  1602. if (Str[3].beg < Str[3].end && Str[3].end[-1] == '"') Str[3].end--;
  1603. }
  1604. {
  1605. string ExtendedType;
  1606. LPCSTR end = Str[2].end;
  1607. if ( p != end ) {
  1608. ExtendedType.reserve(end - p);
  1609. do {
  1610. while(p != end && isspace(*p)) ++p;
  1611. LPCSTR q = p;
  1612. while(q != end && !isspace(*q)) ++q;
  1613. ExtendedType.append(p, q);
  1614. p = q;
  1615. } while ( p != end );
  1616. }
  1617. WppType Flavor(it->second);
  1618. Flavor.TypeName = Name;
  1619. Flavor.Extension = ExtendedType;
  1620. if (Count == 4)
  1621. { Flavor.FormatSpec.assign(Str[3].beg,Str[3].end); }
  1622. if (keyword->second.id == ID_TypeMacro) {
  1623. Flavor.Flags = WT_MACRONAME;
  1624. } else {
  1625. Flavor.Flags = 0;
  1626. }
  1627. TypeSet[Name] = Flavor;
  1628. }
  1629. break;
  1630. }
  1631. /*
  1632. case ID_OutputInc:
  1633. case ID_OutputCode:
  1634. case ID_OutputMof:
  1635. case ID_OutputRc:
  1636. case ID_TemplateFile:
  1637. case ID_ArrayPrefix:
  1638. ((string*)(keyword->second.context))->assign(Str[1].beg, Str[1].end);
  1639. break;
  1640. */
  1641. // case ID_AutoGen:
  1642. // AutoGen[ string(Str[1].beg, Str[1].end) ] = string(Str[2].beg, Str[2].end);
  1643. // break;
  1644. case ID_Include:
  1645. return EzParse(std::string(Str[1].beg, Str[1].end).c_str(),ParseConfigCallback,0);
  1646. case ID_UseSuffix:
  1647. // RegenerateMacroMap();
  1648. Suffixes.push_back( Prefix(Str, Count) );
  1649. break;
  1650. case ID_UsePrefix:
  1651. case ID_NoPrefix:
  1652. // We need to regenerate macro table before using prefix //
  1653. // RegenerateMacroMap();
  1654. Prefixes.push_back( Prefix(Str, Count) );
  1655. break;
  1656. default:;
  1657. //return Keywords->handler(Str, Count, Context);
  1658. }
  1659. } else {
  1660. // INT i;
  1661. //
  1662. // a macro can have a list of assumed arguments in
  1663. // curly braces right after the name
  1664. //
  1665. // Ex: TraceNoise{LEVEL=Noise}(MSG,...)
  1666. //
  1667. Flood("Got %s\n", Name.c_str() );
  1668. LPCSTR assumed_beg = find(Str[0].beg,Str[0].end, '{');
  1669. LPCSTR assumed_end = find(Str[0].beg,Str[0].end, '}');
  1670. if (assumed_beg != Str[0].end) {
  1671. if (assumed_end == Str[0].end) {
  1672. ReportError("No closing brace in '%s'\n",
  1673. Name.c_str() );
  1674. exit(1);
  1675. }
  1676. Name.assign(Str[0].beg, assumed_beg);
  1677. Noise("Real name is %s (%s)\n", Name.c_str(),
  1678. string(assumed_beg+1, assumed_end).c_str() );
  1679. } else if (assumed_end != Str[0].end) {
  1680. ReportError("No openning brace in '%s'\n",
  1681. Name.c_str() );
  1682. exit(1);
  1683. }
  1684. FUNC_MAP::iterator it = Funcs.find(Name);
  1685. if (it != Funcs.end()) {
  1686. ReportError("Function %s is already defined\n",
  1687. Name.c_str() );
  1688. exit(1);
  1689. }
  1690. Func f(Name);
  1691. if (ParseContext->doubleParent) {
  1692. f.SetDoubleP();
  1693. }
  1694. if (assumed_end > assumed_beg) {
  1695. parseAssumedArgs(f, assumed_beg+1, assumed_end+1);
  1696. }
  1697. for (int i = 1; i < Count; ++i) {
  1698. // check for '='
  1699. LPCSTR div = find(Str[i].beg, Str[i].end, '=' );
  1700. if ( div != Str[i].end ) {
  1701. //f.Args.push_back( string(div+1, Str[i].end) );
  1702. f.Goo.push_back( string(Str[i].beg, div ) );
  1703. f.GooId.push_back( string(Str[i].beg, div ) );
  1704. f.MsgVal = static_cast<UCHAR>(i); // can I have more of those?
  1705. continue;
  1706. }
  1707. if ( compare(CtlStr, Str[i]) == 0 ) {
  1708. f.Grp = static_cast<UCHAR>(i);
  1709. f.Goo.push_back( string(Str[i].beg, Str[i].end) );
  1710. f.GooId.push_back( string(Str[i].beg, Str[i].end) );
  1711. // } else if ( compare(GrpStr, Str[i]) == 0 ) {
  1712. // f.Grp = static_cast<UCHAR>(i);
  1713. // f.Goo.push_back( string(Str[i].beg, Str[i].end) );
  1714. // } else if ( compare(ArgsStr, Str[i]) == 0 ) {
  1715. // f.Arg = static_cast<UCHAR>(i);
  1716. } else if ( compare(MsgArgStr, Str[i]) == 0 ) {
  1717. f.MsgArg = static_cast<UCHAR>(i); // can I have more of those?
  1718. // f.SetLineBeg();
  1719. continue;
  1720. } else if ( compare(MsgArgStrUnsafe, Str[i]) == 0 ) {
  1721. f.SetUnsafe();
  1722. f.MsgArg = static_cast<UCHAR>(i); // can I have more of those?
  1723. continue;
  1724. } else if ( compare(MsgValStr, Str[i]) == 0 ) {
  1725. f.MsgVal = static_cast<UCHAR>(i); // can I have more of those?
  1726. } else if ( compare(MakeStr, Str[i]) == 0 ) {
  1727. f.MsgVal = static_cast<UCHAR>(i); // can I have more of those?
  1728. f.set(FO_NOMACRO);
  1729. // f.SetLineBeg();
  1730. // should i continue?
  1731. } else if ( compare(MsgStr, Str[i]) == 0 ) {
  1732. f.Msg = static_cast<UCHAR>(i);
  1733. continue;
  1734. // } else if ( compare(Msg2Str, Str[i]) == 0 ) {
  1735. // f.Msg = static_cast<UCHAR>(i);
  1736. // } else if ( compare(IdStr, Str[i]) == 0 ) {
  1737. // f.Id = static_cast<UCHAR>(i);
  1738. // } else if ( compare(MsgArgsStr, Str[i]) == 0 ) {
  1739. // f.Msg = static_cast<UCHAR>(i);
  1740. // f.VarArgs = TRUE;
  1741. } else if ( compare(NullStr, Str[i]) == 0 ) {
  1742. // not used
  1743. } else if ( compare(IndentStr, Str[i]) == 0 ) {
  1744. f.Indent = static_cast<UCHAR>(i);
  1745. } else if ( compare(ArgStrUnsafe, Str[i]) == 0 ) {
  1746. f.Arg = static_cast<UCHAR>(i);
  1747. f.SetUnsafe();
  1748. f.SetVarArgs();
  1749. if (i != Count - 1) {
  1750. ReportError("func %s: '...' has to be the very last argument\n",
  1751. Name.c_str() );
  1752. }
  1753. continue;
  1754. } else if ( compare(ArgStr, Str[i]) == 0 ) {
  1755. f.Arg = static_cast<UCHAR>(i);
  1756. f.SetVarArgs();
  1757. if (i != Count - 1) {
  1758. ReportError("func %s: '...' has to be the very last argument\n",
  1759. Name.c_str() );
  1760. }
  1761. continue;
  1762. } else {
  1763. f.Goo.push_back( string(Str[i].beg, Str[i].end) );
  1764. f.GooId.push_back( string(Str[i].beg, Str[i].end) );
  1765. }
  1766. f.Args.push_back( string(Str[i].beg, Str[i].end) );
  1767. }
  1768. f.Num = static_cast<UCHAR>(Count - 1);
  1769. Noise(" func %s\n", Name.c_str() );
  1770. Funcs[ Name ] = f;
  1771. }
  1772. return ERROR_SUCCESS;
  1773. }
  1774. #if 0
  1775. DWORD
  1776. PrintCallback (
  1777. IN PSTR_PAIR Str,
  1778. IN UINT Count,
  1779. IN PVOID
  1780. )
  1781. {
  1782. UINT i;
  1783. for (i = 0; i < Count; ++i) {
  1784. putchar('<'); fwrite(Str[i].beg, Str[i].end - Str[i].beg, 1, stdout); putchar('>');
  1785. }
  1786. putchar('\n');
  1787. return ERROR_SUCCESS;
  1788. }
  1789. #endif
  1790. void CleanupString(LPCSTR beg, LPCSTR end, OUT string& msg)
  1791. {
  1792. LPCSTR p = beg, q;
  1793. msg.resize(0);
  1794. while (p < end) {
  1795. // skip spaces
  1796. while (p < end && isspace(*p)) ++p;
  1797. q = p;
  1798. if (p < end && *p == '"') {
  1799. ++p;
  1800. while (p < end && (*p != '"' || p[-1] != '\\')) ++p;
  1801. }
  1802. if (p < end) ++p;
  1803. msg.append(q,p);
  1804. }
  1805. }
  1806. DWORD
  1807. ParseSrcCallback (
  1808. IN PSTR_PAIR Str,
  1809. IN INT Count,
  1810. IN PVOID,
  1811. IN PEZPARSE_CONTEXT ParseContext
  1812. )
  1813. {
  1814. string FuncName(Str[0].beg, Str[0].end);
  1815. string msg, msgval, id, indent;
  1816. vector<Argument> args;
  1817. ParsedFormatString FmtStr;
  1818. int LineNo;
  1819. // UINT argno = 10;
  1820. if (FuncName.compare("WPP_COMPONENT_NAME") == 0) {
  1821. if (Count != 2) {
  1822. ReportError("WPP_COMPONENT_NAME requires 1 argument.\n");
  1823. exit(1);
  1824. }
  1825. ComponentName.assign(Str[1].beg, Str[1].end);
  1826. return ERROR_SUCCESS;
  1827. }
  1828. // Look for special directive
  1829. if ( LookFor.find( FuncName ) != LookFor.end() ) {
  1830. Noise("SpecialString found %s\n", FuncName.c_str());
  1831. CurrentFile->IdsFound.insert(FuncName);
  1832. }
  1833. FUNC_MAP::iterator func = Funcs.find( FuncName );
  1834. if (func == Funcs.end() ) {
  1835. return ERROR_SUCCESS;
  1836. }
  1837. if (func->second.DoubleP() && !ParseContext->doubleParent) {
  1838. ReportError("%s requires ((args))\n", func->first.c_str() );
  1839. exit(1);
  1840. }
  1841. if (!func->second.DoubleP() && ParseContext->doubleParent) {
  1842. ReportError("%s doesn't take ((args))\n", func->first.c_str() );
  1843. exit(1);
  1844. }
  1845. msg.reserve(255);
  1846. msgval.reserve(255);
  1847. if (func->second.VarArgs()) {
  1848. if (Count < func->second.Num ) {
  1849. ReportError("%s requires at least %d arguments. (Found only %d)\n",
  1850. func->first.c_str(), func->second.Num, Count-1);
  1851. return ERROR_INVALID_PARAMETER;
  1852. }
  1853. } else {
  1854. if (Count-1 != func->second.Num ) {
  1855. ReportError("%s requires %d arguments. (Found only %d)\n",
  1856. func->first.c_str(), func->second.Num, Count-1);
  1857. return ERROR_INVALID_PARAMETER;
  1858. }
  1859. }
  1860. if (func->second.LineBeg() && !func->second.DoubleP() ) {
  1861. LineNo = EzGetLineNo(Str[0].beg, ParseContext);
  1862. } else {
  1863. LineNo = EzGetLineNo(ParseContext->macroEnd, ParseContext);
  1864. }
  1865. {
  1866. char Num[64];
  1867. sprintf(Num,"%d", LineNo);
  1868. id = CurrentFile->_CanonicalName;
  1869. id += Num;
  1870. }
  1871. if (GRP(func->second)) {
  1872. PSTR_PAIR p = Str + GRP(func->second);
  1873. string group(p->beg, p->end);
  1874. GROUP_MAP::iterator i = Groups.find(group);
  1875. if (i == Groups.end()) {
  1876. Groups[ string(p->beg, p->end) ] = Group(0, string(p->beg, p->end), id);
  1877. } else {
  1878. i->second.MsgIds.push_back(id);
  1879. }
  1880. }
  1881. // BUGBUG make it legacy bugs
  1882. /*
  1883. if (ARG(func->second)) {
  1884. PSTR_PAIR p = Str + ARG(func->second);
  1885. if( !parseArgs(p->beg, p->end, args) ) {
  1886. return ERROR_INVALID_PARAMETER;
  1887. }
  1888. }
  1889. */
  1890. if (func->second.MsgArg) {
  1891. PSTR_PAIR p = Str + func->second.MsgArg;
  1892. if (p->beg == p->end || *p->beg != '(') {
  1893. ReportError("MsgArg argument should have form (MSG,...)\n");
  1894. exit(1);
  1895. }
  1896. if (!parseLegacy(p, 1, 1, msg, args, FmtStr)) {
  1897. return ERROR_INVALID_PARAMETER;
  1898. }
  1899. }
  1900. if (MSG(func->second)) {
  1901. PSTR_PAIR p = Str + MSG(func->second);
  1902. if (func->second.VarArgs()) {
  1903. if (!parseLegacy(p, Count-MSG(func->second),
  1904. ARG(func->second) - MSG(func->second),
  1905. msg, args, FmtStr)) {
  1906. return ERROR_INVALID_PARAMETER;
  1907. }
  1908. } else if ( !parseMsg(p->beg, p->end, msg) ) {
  1909. return ERROR_INVALID_PARAMETER;
  1910. }
  1911. }
  1912. if (func->second.Indent) {
  1913. PSTR_PAIR p = Str + func->second.Indent;
  1914. indent.assign(p->beg, p->end);
  1915. }
  1916. if (func->second.MsgVal) {
  1917. PSTR_PAIR p = Str + func->second.MsgVal;
  1918. CleanupString(p->beg, p->end, msgval);
  1919. //msgval.assign(p->beg, p->end);
  1920. string::size_type div = msgval.find('=');
  1921. if (div != string::npos) {
  1922. FmtStr.HostString += msgval.substr(div+1);
  1923. } else {
  1924. FmtStr.HostString += msgval;
  1925. }
  1926. msgval.append(","); // Why comma?
  1927. }
  1928. if (func->second.prefix) {
  1929. FmtStr.insert_prefix(func->second.prefix->FmtStr);
  1930. }
  1931. if (func->second.suffix) {
  1932. FmtStr.append(func->second.suffix->FmtStr);
  1933. }
  1934. {
  1935. MSG_MAP::iterator i = MsgMap.find(id);
  1936. if ( i != MsgMap.end() ) {
  1937. // Id already exists. Can't happen //
  1938. ReportError("Can't handle two printf statements on the same line\n");
  1939. exit(1);
  1940. }
  1941. Message* Msg =
  1942. &(MsgMap[id] =
  1943. Message(id, msg, args, TraceGuids.getid(), LineNo, FmtStr,
  1944. func->second) ) ;
  1945. Msg->msgval = msgval;
  1946. Msg->Indent = indent;
  1947. for(int i = 1; i < Count; ++i) {
  1948. if (i == func->second.Indent)
  1949. continue;
  1950. if (i == func->second.MsgVal ||
  1951. i == func->second.MsgArg ||
  1952. i == MSG(func->second) )
  1953. {
  1954. break;
  1955. }
  1956. Msg->GooActualValues.push_back(string(Str[i].beg, Str[i].end));
  1957. }
  1958. CurrentFile->Msgs.push_back( Msg );
  1959. TraceGuids.guids[TraceGuids.current].Msgs.push_back( Msg );
  1960. ++MessageCount;
  1961. if (Msg->ArgConsumed() > arglimit) {
  1962. ReportError("Too many arguments supplied: %d > %d\n",
  1963. Msg->ArgConsumed(), arglimit);
  1964. }
  1965. }
  1966. return ERROR_SUCCESS;
  1967. }
  1968. /*
  1969. void RegenerateMacroMap()
  1970. //
  1971. // Fill Macro Map table
  1972. //
  1973. {
  1974. TYPE_SET::const_iterator it = TypeSet.begin();
  1975. MacroMap.erase(MacroMap.begin(), MacroMap.end());
  1976. for(;it != TypeSet.end(); ++it) {
  1977. string MacroName(MacroPrefix);
  1978. if(it->second.Flags & WT_MACRONAME) {
  1979. MacroName.assign(it->second.TypeName);
  1980. } else {
  1981. MacroName.append(it->second.TypeName);
  1982. }
  1983. MacroMap[ MacroName ] = ArgType(&it->second);
  1984. }
  1985. }
  1986. */
  1987. void
  1988. InitKeywords()
  1989. {
  1990. #define HANDLER(A,B,C,D) Keywords[B] = Keyword(0,C,ID_ ## A, D)
  1991. // HANDLER( UseTraceGuid, "USETRACEGUID", -3, NULL);
  1992. // HANDLER( UseCtrlGuid, "USECTRLGUID", -3, NULL);
  1993. // HANDLER( GrpidRange, "GRPIDRANGE", 2, NULL);
  1994. HANDLER( WppFlags, "WPP_FLAGS", -1, NULL);
  1995. HANDLER( TraceRange, "TRACERANGE", 2, NULL);
  1996. // HANDLER( AutoGen, "AUTOGEN", 2, NULL);
  1997. HANDLER( ProcessFiles, "PROCESSFILES", -1, NULL);
  1998. HANDLER( Touch, "TOUCH", -1, NULL);
  1999. HANDLER( ScanForMacros,"SCANFORMACROS", -1, NULL);
  2000. HANDLER( Exceptions, "EXCEPTIONS", -2, NULL);
  2001. // HANDLER( OutputInc, "OUTPUT_H", 1, &OutputInc);
  2002. // HANDLER( OutputMof, "OUTPUT_MOF", 1, &OutputMof);
  2003. // HANDLER( ArrayPrefix, "ARRAY_PREFIX", 1, &ArrayPrefix);
  2004. HANDLER( TypeMacro, "TYPEMACRO", 2, NULL);
  2005. HANDLER( TypevMacro, "TYPEVMACRO", 3, NULL);
  2006. HANDLER( Include, "INCLUDE", 1, NULL);
  2007. HANDLER( UsePrefix, "USEPREFIX", -2, NULL);
  2008. HANDLER( UseSuffix, "USESUFFIX", -2, NULL); // 3
  2009. HANDLER( NoPrefix, "NOPREFIX", 1, NULL);
  2010. HANDLER( SeparateTraceGuidPerFile, "SEPARATE_TRACE_GUID_PERFILE", 1, &SeparateTraceGuidPerFile);
  2011. HANDLER( DefineSimpleTypePtr, "DEFINE_SIMPLE_TYPE_PTR",-6, NULL);
  2012. HANDLER( DefineSimpleType, "DEFINE_SIMPLE_TYPE", -6, NULL);
  2013. HANDLER( DefineCplxType, "DEFINE_CPLX_TYPE", -7, NULL);
  2014. HANDLER( DefineFlavor, "DEFINE_FLAVOR", 4, NULL);
  2015. HANDLER( CustomType, "CUSTOM_TYPE", -2, NULL);
  2016. // HANDLER( GenerateTypeTable, "GENERATE_TYPE_TABLE", 4, NULL);
  2017. }
  2018. struct iterless {
  2019. typedef MSG_MAP::iterator ty;
  2020. bool operator() (const ty& a, const ty&b) const { return a->second.id < b->second.id; }
  2021. };
  2022. /*
  2023. bool
  2024. FileExists(
  2025. LPSTR fileName
  2026. )
  2027. {
  2028. HANDLE hFile = CreateFile(fileName, 0, 0, 0, OPEN_EXISTING, 0, 0);
  2029. if (hFile == INVALID_HANDLE_VALUE) {
  2030. return FALSE;
  2031. } else {
  2032. CloseHandle( hFile );
  2033. return TRUE;
  2034. }
  2035. }
  2036. */
  2037. void
  2038. MyGetCurrentDirectory(string& str, int level = 0)
  2039. {
  2040. char buf[4096];
  2041. int n;
  2042. n = GetCurrentDirectory(sizeof(buf), buf);
  2043. if (n == 0 || n > sizeof(buf) ) {
  2044. ReportError("GetCurrentDirectory failed: %d\n", GetLastError());
  2045. exit(1);
  2046. }
  2047. {
  2048. char *p, *q;
  2049. p = buf;
  2050. while (level) {
  2051. q = strrchr(buf, '\\');
  2052. if (q == 0) {
  2053. break;
  2054. }
  2055. *q = '_'; p = q+1;
  2056. --level;
  2057. }
  2058. str.assign(p);
  2059. }
  2060. }
  2061. ContainerAdapter<MSG_MAP, MapTag> MsgMap_tpl("Messages", MsgMap);
  2062. ContainerAdapter<GROUP_MAP, MapTag> GroupMap_tpl("Groups", Groups);
  2063. ContainerAdapter<FUNC_MAP, MapTag> FuncMap_tpl("Funcs", Funcs);
  2064. ContainerAdapter<set<Reorder>, VectorTag> Reorder_tpl("Reorder", ReorderSet);
  2065. ContainerAdapter<FILES, VectorTag> Files_tpl("Files", Files);
  2066. ContainerAdapter<TYPE_SET, MapTag> TypeSet_tpl("TypeSet", TypeSet);
  2067. ContainerAdapter<TYPESIG_MAP, MapTag> TypeSigSet_tpl("TypeSigSet", TypeSigMap);
  2068. StringAdapter CurrentDir_tpl("CurrentDir", CurrentDir);
  2069. StringAdapter MacroPrefix_tpl("MacroPrefix", MacroPrefix);
  2070. //StringAdapter GuidStore_tpl("GuidStore", GuidStore);
  2071. StringAdapter TemplateFile_tpl("TemplateFile", CurrentTpl);
  2072. IteratorAdapter<FILES::iterator> CurrentFile_tpl(&CurrentFile);
  2073. struct NameAlias : FieldHolder {
  2074. string _Name, _Alias;
  2075. NameAlias(){} // To make STL happy
  2076. NameAlias(const string& Name, const string& Alias): _Name(Name), _Alias(Alias){}
  2077. bool operator < (const NameAlias& b) const { return _Name.compare(b._Name) < 0; }
  2078. BEGIN_FIELD_TABLE(NameAlias, f)
  2079. TEXT_FIELD(Name) fprint_str(f, _Name);
  2080. TEXT_FIELD(Alias) fprint_str(f, _Alias);
  2081. TEXT_FIELD(MacroName) {
  2082. string::size_type br = _Name.find('(');
  2083. if (br == string::npos) {
  2084. fprint_str(f, _Name);
  2085. } else {
  2086. fprint_str(f, _Name.begin(), _Name.begin() + br);
  2087. }
  2088. }
  2089. END_FIELD_TABLE
  2090. };
  2091. struct Compiler : FieldHolder {
  2092. const Hasher* Checksum;
  2093. BEGIN_FIELD_TABLE(Compiler, f)
  2094. TEXT_FIELD(Name) fprintf(f, "WPP");
  2095. TEXT_FIELD(Version) fprintf(f, "0.01");
  2096. TEXT_FIELD(Checksum) if (Checksum) Checksum->print(f);
  2097. TEXT_FIELD(Timestamp) fprintf(f, __TIMESTAMP__);
  2098. END_FIELD_TABLE
  2099. };
  2100. struct SystemObj : FieldHolder {
  2101. BEGIN_FIELD_TABLE(SystemObject, out)
  2102. TEXT_FIELD(Date) {
  2103. SYSTEMTIME UtcTime; GetSystemTime(&UtcTime);
  2104. fprintf(out, "%02d/%02d/%04d", UtcTime.wMonth, UtcTime.wDay, UtcTime.wYear);
  2105. }
  2106. TEXT_FIELD(Time) {
  2107. SYSTEMTIME UtcTime; GetSystemTime(&UtcTime);
  2108. fprintf(out, "%02d:%02d:%02d", UtcTime.wHour, UtcTime.wMinute, UtcTime.wSecond);
  2109. }
  2110. END_FIELD_TABLE
  2111. };
  2112. struct FoundTpl: FieldHolder {
  2113. virtual BOOL Hidden(std::string filter="") const {
  2114. return CurrentFile->IdsFound.find(filter) == CurrentFile->IdsFound.end();
  2115. }
  2116. BEGIN_FIELD_TABLE(FoundTpl, f)
  2117. __f__;
  2118. END_FIELD_TABLE
  2119. };
  2120. FoundTpl Found_tpl;
  2121. SystemObj System_tpl;
  2122. Compiler Compiler_tpl;
  2123. //vector<NameAlias> AutoGenMacros;
  2124. //ContainerAdapter< vector<NameAlias>, VectorTag > AutoGenMacros_tpl("AutoGenMacros", AutoGenMacros);
  2125. set<NameAlias> MacroDefinitions;
  2126. ContainerAdapter< set<NameAlias>, VectorTag > MacroDefintions_tpl("MacroDefinitions", MacroDefinitions);
  2127. void AddMacroDefinition(LPCSTR s)
  2128. {
  2129. LPCSTR end = s + strlen(s);
  2130. LPCSTR q = strchr(s, '=');
  2131. if (q == NULL) {
  2132. MacroDefinitions.insert( NameAlias( s , "" ) );
  2133. } else {
  2134. MacroDefinitions.insert( NameAlias( string(s,q) , string(q+1,end) ) );
  2135. }
  2136. }
  2137. void expand(IN OUT string& str, const string& id)
  2138. {
  2139. NameAlias dummy(id, "");
  2140. set<NameAlias>::const_iterator it = MacroDefinitions.find(dummy);
  2141. if (it != MacroDefinitions.end()) {
  2142. str.append(it->_Alias);
  2143. }
  2144. }
  2145. void processGenOption(LPCSTR s)
  2146. {
  2147. LPCSTR end = s + strlen(s), div = strchr(s,'}'), star = strchr(s,'*');
  2148. vector<GenPair>& v = star ? GenMulti : GenSingle;
  2149. if (*s != '{') { goto usage; }
  2150. if (div == 0) { goto usage; }
  2151. if (s+1 == div || div+1 == end) { goto usage; }
  2152. if (star) {
  2153. if (div+1 != star) {
  2154. ReportError(" '*' can appear only as a first charachter of output-filename part\n");
  2155. goto usage;
  2156. }
  2157. ++star;
  2158. } else {
  2159. star = div+1;
  2160. }
  2161. if (star == end) goto usage;
  2162. v.push_back( GenPair(string(s+1, div), string(star, end)) );
  2163. return;
  2164. usage:
  2165. ReportError(" use -gen:{template-fpathname}output-fpathname\n"
  2166. " you supplied -gen:%s\n", s);
  2167. ExitProcess(1);
  2168. }
  2169. void
  2170. PrepareSearchPaths(LPCSTR s)
  2171. {
  2172. //
  2173. // split /Isdf;sdf;y into a vector of strings
  2174. //
  2175. while(s)
  2176. {
  2177. LPCSTR semi = strchr(s, ';');
  2178. if (semi) {
  2179. SearchDirs.push_back(string(s,semi));
  2180. ++semi;
  2181. } else {
  2182. SearchDirs.push_back(string(s));
  2183. }
  2184. s = semi;
  2185. if (SearchDirs.back().size() > 0
  2186. && SearchDirs.back().end()[-1] != '\\')
  2187. {
  2188. SearchDirs.back().append("\\");
  2189. }
  2190. }
  2191. }
  2192. // 2fb37eda-004b-4b64-a1c4-84c53cb55df5
  2193. // 0 1 2 3
  2194. // 01234567typeName1234567typeName1234567typeName12345
  2195. void processCtlOption(string s)
  2196. {
  2197. // first let's check that the guid is OK
  2198. if ( (s.size() == 16 * 2 + 4)
  2199. && (s[8] == '-') && (s[13] == '-')
  2200. && (s[18] == '-') && s[23] == '-')
  2201. {
  2202. s[8] = s[13] = s[18] = s[23] = ',';
  2203. MacroDefinitions.insert( NameAlias(
  2204. string("WPP_DEFAULT_CONTROL_GUID"), s) );
  2205. }
  2206. }
  2207. void processCfgItem(const string& s)
  2208. {
  2209. LPCSTR beg = s.begin(), end = s.end();
  2210. ULONG Status;
  2211. EZPARSE_CONTEXT ParseContext;
  2212. ZeroMemory(&ParseContext, sizeof(ParseContext) );
  2213. ParseContext.start = beg;
  2214. ParseContext.filename = "cmdline";
  2215. ParseContext.scannedLineCount = 1;
  2216. ParseContext.lastScanned = beg;
  2217. // EzParseCurrentContext = &ParseContext;
  2218. Status = ScanForFunctionCallsEx
  2219. (beg, end, ParseConfigCallback, 0, &ParseContext, NO_SEMICOLON);
  2220. if (Status != ERROR_SUCCESS) {
  2221. exit(1);
  2222. }
  2223. }
  2224. vector<string> cmdinit; // config commands specified on the command line.
  2225. void ParseConfigFromCmdline()
  2226. {
  2227. for(int i = 0; i < cmdinit.size(); ++i) {
  2228. processCfgItem(cmdinit[i]);
  2229. }
  2230. }
  2231. void DealWithCmdLineOptions(LPCSTR s)
  2232. {
  2233. Unusual(" -%s", s);
  2234. if (lstrcmp(s,"km") == 0) {
  2235. AddMacroDefinition("WPP_KERNEL_MODE");
  2236. userMode = FALSE;
  2237. } else if (lstrcmp(s,"um") == 0) {
  2238. AddMacroDefinition("WPP_USER_MODE");
  2239. userMode = TRUE;
  2240. } else if (strcmp(s, "dll")==0) {
  2241. AddMacroDefinition("WPP_DLL");
  2242. } else if (strcmp(s, "ignoreduptypes")==0) {
  2243. IgnoreDupTypes = TRUE;
  2244. } else if (strncmp(s, "gen:", 4)==0) {
  2245. processGenOption(s+4);
  2246. } else if (strncmp(s, "gen{", 4)==0) { // I was always forgetting to put :
  2247. processGenOption(s+3);
  2248. } else if (strncmp(s, "ctl:", 4)==0) {
  2249. processCtlOption(string(s+4));
  2250. } else if (strncmp(s, "scan:", 5)==0) {
  2251. ScanForMacros.push_back(string(s+5));
  2252. } else if (strncmp(s, "defwpp:", 7)==0) {
  2253. WppDefault.assign(s+7);
  2254. } else if (strncmp(s, "v", 1)==0) {
  2255. if ( isdigit(s[1]) ) {
  2256. DbgLevel = s[1] - '0';
  2257. } else {
  2258. DbgLevel = 1;
  2259. }
  2260. } else if (strncmp(s, "ini:", 4)==0) {
  2261. LocalConfig.assign(s+4);
  2262. } else if (strncmp(s, "lookfor:", 8)==0) {
  2263. LookFor.insert(string(s+8));
  2264. } else if (strncmp(s, "ext:", 4)==0) {
  2265. AllowedExtensions.assign(s+4);
  2266. } else if (strncmp(s, "cfgdir:", 7)==0) { // OBSOLETE
  2267. PrepareSearchPaths(s+7);
  2268. } else if (strncmp(s, "arglimit:", 9)==0) {
  2269. arglimit = atoi(s+9);
  2270. } else if (strncmp(s, "I", 1)==0) {
  2271. PrepareSearchPaths(s+1);
  2272. } else if (strcmp(s, "reorder")==0) {
  2273. reorder = TRUE;
  2274. } else if (strcmp(s, "noreorder")==0) {
  2275. reorder = FALSE;
  2276. } else if (strcmp(s, "donothing")==0) {
  2277. exit(0);
  2278. } else if (strcmp(s, "notimechk")==0) {
  2279. CheckTimestamp = FALSE;
  2280. } else if (strcmp(s, "noshrieks")==0) {
  2281. noshrieks = TRUE;
  2282. } else if (strcmp(s, "nohashchk")==0) {
  2283. CheckHash = FALSE;
  2284. } else if (strncmp(s, "func:",5)==0) {
  2285. cmdinit.push_back( string(s+5) );
  2286. } else if (strcmp(s, "md5")==0) {
  2287. md5 = TRUE;
  2288. } else if (strcmp(s, "nomd5")==0) {
  2289. md5 = FALSE;
  2290. } else if (strncmp(s, "omac:", 5)==0) {
  2291. OutputMac.assign(s+5);
  2292. } else if (strncmp(s, "argbase:", 8)==0) {
  2293. ArgBase = atoi(s+8);
  2294. } else if (strncmp(s, "odir:", 5)==0) {
  2295. OutputDir.assign(s+5);
  2296. if (OutputDir.size() > 0 && OutputDir.end()[-1] != '\\') {
  2297. OutputDir.append("\\");
  2298. }
  2299. } else if (strncmp(s, "D", 1)==0) {
  2300. AddMacroDefinition(s+1);
  2301. } else {
  2302. ReportError("Unknown cmdline option: -%s\n", s);
  2303. exit(1);
  2304. }
  2305. }
  2306. void parseStringAsCmdLine(
  2307. LPCSTR beg, LPCSTR end
  2308. )
  2309. {
  2310. LPCSTR p = beg;
  2311. if( end == NULL ) {
  2312. end = beg + strlen(beg);
  2313. }
  2314. // need to skip spaces. " is processed specially
  2315. for(;;) {
  2316. while (p < end && isspace(*p)) ++p;
  2317. if (p == end) return;
  2318. LPCSTR q = p; // beginning of the the string
  2319. if (*p == '"') {
  2320. ++q; // skip openning quote
  2321. do {
  2322. ++p; while (p < end && *p != '"') ++p;
  2323. if (p == end) {
  2324. ReportError("Unterminated string in %s\n", string(beg, end).c_str() );
  2325. exit(1);
  2326. }
  2327. }
  2328. while (*p == '\\');
  2329. // now p points to '"' which is not prefixed by '\'
  2330. } else {
  2331. while (p < end && !isspace(*p)) ++p;
  2332. }
  2333. if (*q != '-') {
  2334. ReportError("Option doesn't start with '-' %s in \"%s\"\n",
  2335. string(q,p).c_str(), string(beg, end).c_str() );
  2336. }
  2337. DealWithCmdLineOptions(q+1, p);
  2338. if (*p == '"') ++p;
  2339. }
  2340. }
  2341. enum {
  2342. FAVOR_LOCAL_DIR = 0x01,
  2343. UPDATE_NAME = 0x02,
  2344. COMPLAIN_BITTERLY = 0x04,
  2345. };
  2346. BOOL
  2347. FileExists(
  2348. string& fname,
  2349. string path = "",
  2350. ULONG options = 0)
  2351. {
  2352. string file(path);
  2353. file.append(fname);
  2354. WIN32_FIND_DATA Dummy;
  2355. HANDLE ffh = FindFirstFile(file.c_str(), &Dummy);
  2356. if (ffh != INVALID_HANDLE_VALUE) {
  2357. FindClose(ffh);
  2358. Noise("found %s in %s\n", fname.c_str(), path.c_str());
  2359. if (options & UPDATE_NAME) {
  2360. fname = file;
  2361. }
  2362. return TRUE;
  2363. }
  2364. return FALSE;
  2365. }
  2366. void
  2367. FindFileOnPath(string& Name, ULONG Options = 0)
  2368. {
  2369. if (Options & FAVOR_LOCAL_DIR) {
  2370. if(FileExists(Name)) { goto found; }
  2371. }
  2372. int i;
  2373. for(i = 0; i < SearchDirs.size(); ++i) {
  2374. if(FileExists(Name, SearchDirs[i], Options))
  2375. { goto found; }
  2376. }
  2377. if ( !(Options & FAVOR_LOCAL_DIR) ) {
  2378. if(FileExists(Name)) { goto found; }
  2379. }
  2380. if ( Options & COMPLAIN_BITTERLY ) {
  2381. ReportError("File %s not found\n", Name.c_str());
  2382. exit(1);
  2383. }
  2384. found:;
  2385. }
  2386. void InitGlobals()
  2387. {
  2388. InitKeywords();
  2389. MyGetCurrentDirectory(CurrentDir, 1);
  2390. // ArrayPrefix.assign(currentDir);
  2391. // ArrayPrefix.append("_wpp_");
  2392. PopulateFieldMap();
  2393. if (OutputMac.size() > 0) {
  2394. DeleteFile( OutputMac.c_str() );
  2395. }
  2396. ObjectMap["Reorder"] = &Reorder_tpl;
  2397. ObjectMap["TraceGuids"] = &TraceGuids;
  2398. // ObjectMap["CtrlGuids"] = &CtrlGuids;
  2399. ObjectMap["Messages"] = &MsgMap_tpl;
  2400. ObjectMap["Groups"] = &GroupMap_tpl;
  2401. ObjectMap["Funcs"] = &FuncMap_tpl;
  2402. // ObjectMap["AutoMacros"] = &AutoGenMacros_tpl;
  2403. ObjectMap["CurrentDir"] = &CurrentDir_tpl;
  2404. ObjectMap["MacroPrefix"] = &MacroPrefix_tpl;
  2405. ObjectMap["Compiler"] = &Compiler_tpl;
  2406. ObjectMap["Files"] = &Files_tpl;
  2407. ObjectMap["TypeSet"] = &TypeSet_tpl;
  2408. ObjectMap["System"] = &System_tpl;
  2409. ObjectMap["MacroDefinitions"] = &MacroDefintions_tpl;
  2410. ObjectMap["TemplateFile"] = &TemplateFile_tpl;
  2411. ObjectMap["SourceFile"] = &CurrentFile_tpl;
  2412. ObjectMap["TypeSigSet"] = &TypeSigSet_tpl;
  2413. ObjectMap["FOUND"] = &Found_tpl;
  2414. }
  2415. VOID ReadCommandLineArgs(int argc, char** argv)
  2416. {
  2417. Unusual(" tracewpp");
  2418. for (int i = 1; i < argc; ++i) {
  2419. char* s = argv[i];
  2420. int len = (int)strlen(s);
  2421. if (len > 1 && s[0] == '-') {
  2422. DealWithCmdLineOptions(s+1);
  2423. } else {
  2424. Unusual(" %s", argv[i]);
  2425. Fill( string(argv[i]));
  2426. }
  2427. }
  2428. Unusual("\n");
  2429. {
  2430. LPCSTR p = getenv("WPP_FLAGS");
  2431. if (p) {
  2432. Noise("WPP_FLAGS defined: %s\n", p);
  2433. parseStringAsCmdLine(p, NULL);
  2434. }
  2435. }
  2436. /*
  2437. // THINK do we need revision at all?
  2438. if (Revision.size() > 0) {
  2439. if(SearchDirs.size() == 0) {
  2440. ReportError("Revision can be specified only when -cfgdir directive is specified");
  2441. ExitProcess(3);
  2442. } else {
  2443. if (Revision.end()[-1] != '\\') {
  2444. Revision.append("\\");
  2445. }
  2446. int i, n = SearchDirs.size();
  2447. for (i = 0; i < n; ++i) {
  2448. SearchDirs.push_back( SearchDirs[i] );
  2449. SearchDirs.back().append(Revision);
  2450. }
  2451. }
  2452. }
  2453. */
  2454. }
  2455. void ReadConfig()
  2456. {
  2457. DWORD status;
  2458. BOOL WppParsed = FALSE;
  2459. // If default config file was specified,
  2460. // process it
  2461. if (WppDefault.size() > 0) {
  2462. WppParsed = TRUE;
  2463. Noise("parsing config file %s\n", WppDefault.c_str());
  2464. status = EzParse(WppDefault.c_str(), ParseConfigCallback,0);
  2465. if (status != ERROR_SUCCESS) {
  2466. ExitProcess( status );
  2467. }
  2468. }
  2469. if (LocalConfig.size() == 0) {
  2470. if (FileExists(LOCAL_CONFIG_NAME) ) {
  2471. WppParsed = TRUE;
  2472. Noise("parsing config file %s\n", LOCAL_CONFIG_NAME.c_str());
  2473. status = EzParse(LOCAL_CONFIG_NAME.c_str(),ParseConfigCallback,0);
  2474. if (status != ERROR_SUCCESS) {
  2475. ExitProcess( status );
  2476. }
  2477. }
  2478. }
  2479. else
  2480. {
  2481. WppParsed = TRUE;
  2482. Noise("parsing config file %s\n", LocalConfig.c_str());
  2483. status = EzParse(LocalConfig.c_str(),ParseConfigCallback,0);
  2484. if (status != ERROR_SUCCESS) {
  2485. ExitProcess( status );
  2486. }
  2487. }
  2488. if (!WppParsed) {
  2489. ReportError("configuration file not found\n");
  2490. ExitProcess( ERROR_FILE_NOT_FOUND );
  2491. }
  2492. if (Files.begin() == Files.end()) {
  2493. Unusual("Nothing to compile\n");
  2494. ExitProcess( ERROR_FILE_NOT_FOUND );
  2495. }
  2496. {
  2497. // Scan files for macro //
  2498. vector<string>::iterator i;
  2499. for (i = ScanForMacros.begin(); i != ScanForMacros.end(); ++i) {
  2500. Noise("scanning %s... \n", i->c_str());
  2501. EzParseEx(i->c_str(), SmartScan, ParseConfigCallback,0, 0);
  2502. }
  2503. }
  2504. ParseConfigFromCmdline();
  2505. //
  2506. // We need to add prefix and suffix information to FuncMap
  2507. //
  2508. {
  2509. PREFIX_VECTOR::iterator i;
  2510. Prefix * defaultPrefix = 0;
  2511. Prefix * defaultSuffix = 0;
  2512. string star("*");
  2513. for (i = Prefixes.begin(); i != Prefixes.end(); ++i) {
  2514. if ( 0 == i->FuncName.compare(star) ) {
  2515. defaultPrefix = i;
  2516. } else {
  2517. Funcs[i->FuncName].SetPrefix(i);
  2518. }
  2519. }
  2520. for (i = Suffixes.begin(); i != Suffixes.end(); ++i) {
  2521. if ( 0 == i->FuncName.compare(star) ) {
  2522. defaultSuffix = i;
  2523. } else {
  2524. Funcs[i->FuncName].SetSuffix(i);
  2525. }
  2526. }
  2527. //
  2528. // Assign the appendicies to the all other functions
  2529. //
  2530. FUNC_MAP::iterator j = Funcs.begin();
  2531. for(; j != Funcs.end(); ++j) {
  2532. if (!j->second.prefix) {
  2533. j->second.SetPrefix( defaultPrefix );
  2534. }
  2535. if (!j->second.suffix) {
  2536. j->second.SetSuffix( defaultSuffix );
  2537. }
  2538. }
  2539. }
  2540. //
  2541. // Generates names of the log macros based on type names
  2542. // Thus users of the tool can have LOGULONG or log_ulong
  2543. // or w_ulong(). Whatever they like best
  2544. //
  2545. // RegenerateMacroMap();
  2546. }
  2547. // used by tpl.cpp to do template include [BUGBUG] currently broken
  2548. void ProcessTemplate(LPCSTR b, LPCSTR e, void* Context)
  2549. {
  2550. string prev(CurrentTpl);
  2551. CurrentTpl.assign(b,e);
  2552. FindFileOnPath(CurrentTpl, COMPLAIN_BITTERLY | UPDATE_NAME | FAVOR_LOCAL_DIR);
  2553. EzParseEx(CurrentTpl.c_str(), processTemplate,0, Context, 0);
  2554. CurrentTpl.assign(prev);
  2555. }
  2556. void FormOutputFileName(
  2557. IN const string& to,
  2558. IN const string& suffix,
  2559. OUT string& OutputFile,
  2560. OUT BOOL &StdOut
  2561. )
  2562. {
  2563. string::size_type backSlash = to.find('\\');
  2564. string::size_type colon = to.find(':');
  2565. if (to.compare("-") == 0) {
  2566. StdOut = TRUE;
  2567. OutputFile.assign("-");
  2568. } else {
  2569. StdOut = FALSE;
  2570. if (backSlash == string::npos && colon == string::npos) {
  2571. // can prepend odir
  2572. OutputFile.assign(OutputDir);
  2573. OutputFile.append(to);
  2574. } else {
  2575. OutputFile.assign(to);
  2576. }
  2577. OutputFile.append(suffix);
  2578. }
  2579. }
  2580. void GenerateOutput(string tpl, string to, string suffix = "")
  2581. {
  2582. string OutputFile;
  2583. FILE * f = 0;
  2584. BOOL useStdOut = FALSE;
  2585. FormOutputFileName(to, suffix, OutputFile, useStdOut);
  2586. DefaultHasher computedHash;
  2587. computedHash.Init();
  2588. MsgMapHash(MsgMap, computedHash);
  2589. computedHash.Finalize();
  2590. Compiler_tpl.Checksum = &computedHash;
  2591. if (md5) {
  2592. size_t len = min(sizeof(GUID), computedHash.Size() );
  2593. Flood("Going MD5... %d guid(s) ", TraceGuids.guids.size());
  2594. for (int i = 0; i < TraceGuids.guids.size(); ++i) {
  2595. // The following two lines are just needed in case
  2596. // we ever decide DefaultHasher to be CRC32
  2597. // If it will always be MD5 hasher, we can remove them
  2598. ZeroMemory(&TraceGuids.guids[i].guid, sizeof(TraceGuids.guids[i].guid));
  2599. TraceGuids.guids[i].guid.Data2 = (USHORT)i;
  2600. CopyMemory(&TraceGuids.guids[i].guid, computedHash.Buf(), len);
  2601. if (DbgLevel >= DBG_FLOOD) {
  2602. TraceGuids.guids[i].printTxt(stdout); putchar(' ');
  2603. }
  2604. }
  2605. Flood("\n");
  2606. }
  2607. // check whether we need to regenerate the file
  2608. if (ErrorCount == 0 && CheckHash) {
  2609. // Scan the beginning of the
  2610. FILE *inc = fopen(OutputFile.c_str(), "r");
  2611. if (inc) {
  2612. DefaultHasher readHash;
  2613. char buf[128], *p = buf;
  2614. int n = (int)fread(buf, 1, sizeof(buf)-1, inc);
  2615. fclose(inc);
  2616. buf[n] = 0;
  2617. while (!isalnum(*p) && *p ) ++p;
  2618. readHash.fromString(p, buf + n);
  2619. if (DbgLevel >= DBG_FLOOD) {
  2620. computedHash.print(stdout); putchar(' ');
  2621. readHash.print(stdout); putchar(' ');
  2622. }
  2623. if (computedHash == readHash) {
  2624. Noise("No changes in %s.\n",
  2625. CurrentFile->_Name.c_str() );
  2626. return;
  2627. }
  2628. }
  2629. }
  2630. if (ErrorCount) {
  2631. DeleteFile(OutputFile.c_str());
  2632. Noise("errors detected. deleting %s...\n", OutputFile.c_str());
  2633. return;
  2634. }
  2635. Noise("generating %s...\n", OutputFile.c_str());
  2636. if (useStdOut) {
  2637. f = stdout;
  2638. } else {
  2639. f = fopen(OutputFile.c_str(), "w");
  2640. if (!f) {
  2641. ReportError("Cannot open '%s' for writing, error %d\n", OutputFile.c_str(), GetLastError() );
  2642. ExitProcess( GetLastError() );
  2643. }
  2644. }
  2645. ProcessTemplate(tpl.begin(), tpl.end(), f);
  2646. if (!useStdOut) {
  2647. fclose(f);
  2648. }
  2649. }
  2650. void printTime(LPCSTR Name, ULONGLONG Time)
  2651. {
  2652. FILETIME Local; ZeroMemory(&Local, sizeof(Local));
  2653. SYSTEMTIME st; ZeroMemory(&st, sizeof(st));
  2654. FileTimeToLocalFileTime((LPFILETIME)&Time, &Local);
  2655. //CopyMemory(&Local, &Time, sizeof(Time));
  2656. FileTimeToSystemTime(&Local, &st);
  2657. printf("%s %04d/%02d/%02d %02d:%02d:%02d\n", Name,
  2658. st.wYear, st.wMonth, st.wDay,
  2659. st.wHour, st.wMinute, st.wSecond);
  2660. }
  2661. void
  2662. VerifyAndUpdateTemplatesNames(
  2663. vector<GenPair>& Gen
  2664. )
  2665. {
  2666. // verify that the template
  2667. vector<GenPair>::iterator i;
  2668. for(i = Gen.begin();i != Gen.end();++i){
  2669. FindFileOnPath(i->tpl, COMPLAIN_BITTERLY | UPDATE_NAME | FAVOR_LOCAL_DIR);
  2670. }
  2671. }
  2672. int RealMain(int argc, char** argv)
  2673. {
  2674. InitGlobals();
  2675. ReadCommandLineArgs(argc, argv);
  2676. if (WppDefault.size()) {
  2677. FindFileOnPath(WppDefault, COMPLAIN_BITTERLY | UPDATE_NAME);
  2678. }
  2679. ReadConfig();
  2680. if (GenSingle.size() == 0 && GenMulti.size() == 0)
  2681. {
  2682. // add default template
  2683. processGenOption(DEFAULT_GEN_OPTION);
  2684. }
  2685. BOOL OneAtATime = GenMulti.size() > 0;
  2686. VerifyAndUpdateTemplatesNames(GenMulti);
  2687. VerifyAndUpdateTemplatesNames(GenSingle);
  2688. {
  2689. FILES::iterator file;
  2690. if (CheckTimestamp)
  2691. {
  2692. //
  2693. // Before we do any heavyweight processing
  2694. // let's check timestamps of source
  2695. // and output files
  2696. //
  2697. ULONGLONG Now, MaxSrcTime, MinOutTime;
  2698. string OutputFile;
  2699. GetSystemTimeAsFileTime((LPFILETIME)&Now);
  2700. MaxSrcTime = 0;
  2701. MinOutTime = Now;
  2702. for (file = Files.begin(); file != Files.end(); ++file) {
  2703. if (file->ModificationTime == 0) {
  2704. Always("%s file has invalid modification time\n",
  2705. file->_BaseName.c_str());
  2706. goto out_of_date;
  2707. }
  2708. if (file->ModificationTime > Now) {
  2709. Always("%s file modification time is in the future\n",
  2710. file->_BaseName.c_str());
  2711. goto out_of_date;
  2712. }
  2713. if (file->ModificationTime > MaxSrcTime) {
  2714. MaxSrcTime = file->ModificationTime;
  2715. }
  2716. vector<GenPair>::iterator i;
  2717. for(i = GenMulti.begin();i != GenMulti.end();++i){
  2718. BOOL StdOut;
  2719. ULONGLONG Time;
  2720. FormOutputFileName(file->_BaseName, i->out.c_str(),
  2721. OutputFile, StdOut);
  2722. if (StdOut) {
  2723. // StdOut is always out of date //
  2724. goto out_of_date;
  2725. }
  2726. Time = GetFileModificationTime(OutputFile);
  2727. if (Time == 0) {
  2728. goto out_of_date;
  2729. }
  2730. if (Time > Now) {
  2731. Always("%s file modification time is in the future\n",
  2732. OutputFile.c_str());
  2733. goto out_of_date;
  2734. }
  2735. if (Time < MinOutTime) {
  2736. MinOutTime = Time;
  2737. }
  2738. }
  2739. }
  2740. vector<GenPair>::iterator i;
  2741. for(i = GenSingle.begin();i != GenSingle.end();++i){
  2742. BOOL StdOut;
  2743. ULONGLONG Time;
  2744. FormOutputFileName(file->_BaseName, i->out.c_str(),
  2745. OutputFile, StdOut);
  2746. if (StdOut) {
  2747. // StdOut is always out of date //
  2748. goto out_of_date;
  2749. }
  2750. Time = GetFileModificationTime(OutputFile);
  2751. if (Time == 0) {
  2752. goto out_of_date;
  2753. }
  2754. if (Time > Now) {
  2755. Always("%s file modification time is in the future\n",
  2756. OutputFile.c_str());
  2757. goto out_of_date;
  2758. }
  2759. if (Time < MinOutTime) {
  2760. MinOutTime = Time;
  2761. }
  2762. }
  2763. if (MaxSrcTime <= MinOutTime) {
  2764. // printTime("Src time:", MaxSrcTime);
  2765. // printTime("Out time:", MinOutTime);
  2766. // Noise("No Processing Required\n");
  2767. return 0;
  2768. }
  2769. } // if (CheckTimestamp) //
  2770. out_of_date:
  2771. //
  2772. // Now we are ready to start scanning the source files
  2773. //
  2774. for (file = Files.begin(); file != Files.end(); ++file) {
  2775. Noise("processing %s... \n", file->FullFileName().c_str());
  2776. CurrentFile = file;
  2777. if (SeparateTraceGuidPerFile) {
  2778. TraceGuids.new_file( file->_Name.c_str() );
  2779. }
  2780. EzParseWithOptions(file->FullFileName().c_str(), ParseSrcCallback, 0, IGNORE_CPP_COMMENT);
  2781. {
  2782. vector<GenPair>::iterator i;
  2783. for(i = GenMulti.begin();i != GenMulti.end();++i){
  2784. GenerateOutput(i->tpl, file->_BaseName, i->out.c_str());
  2785. }
  2786. }
  2787. if (OneAtATime) {
  2788. // Clear the tables for the next iteration
  2789. MsgMap.erase(MsgMap.begin(), MsgMap.end());
  2790. TypeSigMap.erase(TypeSigMap.begin(), TypeSigMap.end());
  2791. TraceGuids.erase();
  2792. for (TYPE_SET::const_iterator i = TypeSet.begin();
  2793. i != TypeSet.end(); ++i)
  2794. {
  2795. i->second.Used = FALSE;
  2796. }
  2797. }
  2798. }
  2799. Noise("done. Errors: %d.\n", ErrorCount);
  2800. }
  2801. #if 0
  2802. // update Used field for every type in TypeSigSet
  2803. {
  2804. for (TYPESIG_MAP::const_iterator i = TypeSigMap.begin();
  2805. i != TypeSigMap.end(); ++i)
  2806. {
  2807. for(int j = 0; j < i->Types.size(); ++j) {
  2808. i->second.Types[j]->Used = TRUE;
  2809. }
  2810. }
  2811. }
  2812. #endif
  2813. // generate global files
  2814. {
  2815. vector<GenPair>::iterator i;
  2816. for(i = GenSingle.begin();i != GenSingle.end();++i){
  2817. GenerateOutput(i->tpl, i->out.c_str());
  2818. }
  2819. }
  2820. return ErrorCount;
  2821. }
  2822. int __cdecl main(int argc, char** argv)
  2823. {
  2824. int status = 0;
  2825. __int64 a, b;
  2826. GetSystemTimeAsFileTime((LPFILETIME)&a);
  2827. __try
  2828. {
  2829. status = RealMain(argc, argv);
  2830. }
  2831. __except(EXCEPTION_EXECUTE_HANDLER)
  2832. {
  2833. status = 1;
  2834. ReportError("Internal Error : Contact GorN\n");
  2835. }
  2836. {
  2837. SYSTEMTIME st;
  2838. GetSystemTimeAsFileTime((LPFILETIME)&b);
  2839. b -= a;
  2840. FileTimeToSystemTime((LPFILETIME)&b, &st);
  2841. Always("tracewpp: %d file(s) with %d message(s), processed in %d.%03d seconds\n",
  2842. Files.size(), MessageCount,
  2843. st.wSecond, st.wMilliseconds);
  2844. }
  2845. return status;
  2846. }