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.

290 lines
10 KiB

  1. /*++
  2. Revision History:
  3. GorN: 29-Sep-2000 - fix %% handling
  4. GorN: 29-Sep-2000 - pulled out __FUNCTION__ support, now traceprt handles it
  5. GorN: 10-Oct-2000 - special case for .*
  6. GorN: 23-Oct-2000 - support for I type specifier (pointer size integer)
  7. --*/
  8. struct OffsetPair {
  9. int _beg;
  10. int _end;
  11. OffsetPair():_beg(0),_end(0){}
  12. // OffsetPair(const OffsetPair& i):beg(i.beg),end(i.end) {}
  13. OffsetPair(LPCSTR base, LPCSTR b, LPCSTR e):
  14. _beg((int)(b-base)), _end((int)(e-base)) {}
  15. void set(LPCSTR base, LPCSTR b, LPCSTR e) {
  16. _beg = (int)(b-base); _end = (int)(e-base); }
  17. int len() const { return _end - _beg; }
  18. LPCSTR beg(LPCSTR base) const { return base + _beg; }
  19. LPCSTR end(LPCSTR base) const { return base + _end; }
  20. void adjust_by(size_t size) {
  21. _beg += (int)size;
  22. _end += (int)size;
  23. }
  24. };
  25. struct FormatItem {
  26. int no; // arg no
  27. string width;
  28. string typeName; // for debugging only. We don't need it
  29. OffsetPair location; // where it is in the host string
  30. const WppType * type;
  31. string argName;
  32. string expr;
  33. bool operator < (const FormatItem& b) const {
  34. return *type < *b.type;
  35. }
  36. void print(FILE* f) {
  37. fprintf(f,"<%d:%s:%s:%x:%d>", no, width.c_str(), type->TypeName.c_str(),
  38. location._beg, location.len() );
  39. }
  40. };
  41. struct ParsedFormatString {
  42. string HostString;
  43. vector<FormatItem> Items;
  44. int ArgCount;
  45. // mutable bool signatureValid;
  46. private:
  47. // mutable string _Signature;
  48. LPCSTR SkipTypePrefix(LPCSTR p, LPCSTR e, int* no = 0)
  49. {
  50. BOOL no_arg_no = FALSE;
  51. int sum = 0;
  52. // treat .* as a part of a type name
  53. if (p+1 < e && p[0] == '.' && p[1] == '*') {
  54. return p;
  55. }
  56. // skip flags.
  57. while (*p == '-' || *p == '#' || *p == '+') {
  58. no_arg_no = TRUE;
  59. if (++p == e) return e;
  60. }
  61. // skip width (or argno)
  62. while ( isdigit(*p) ) {
  63. sum = sum * 10 + (*p - '0');
  64. if (++p == e) return e;
  65. }
  66. if (*p == '.') {
  67. no_arg_no = TRUE;
  68. // skip precision //
  69. do {
  70. if (++p == e) return e;
  71. } while ( isdigit(*p) );
  72. }
  73. if (no) {
  74. *no = (no_arg_no)?-1:sum;
  75. }
  76. return p;
  77. }
  78. public:
  79. ParsedFormatString(): ArgCount(0) {}
  80. void insert_prefix(const ParsedFormatString& b)
  81. {
  82. for (int i = 0; i < Items.size(); ++i) {
  83. Items[i].location.adjust_by( b.HostString.size() );
  84. if (Items[i].no > 0) {
  85. Items[i].no += b.ArgCount;
  86. }
  87. }
  88. Items.insert(Items.begin(), b.Items.begin(), b.Items.end());
  89. HostString.insert( 0, b.HostString );
  90. ArgCount += b.ArgCount;
  91. }
  92. void append(const ParsedFormatString& b)
  93. {
  94. // adjust location information
  95. int n = (int)Items.size();
  96. Items.insert(Items.end(), b.Items.begin(), b.Items.end());
  97. for (int i = n; i < Items.size(); ++i) {
  98. Items[i].location.adjust_by( HostString.size() );
  99. if (Items[i].no > 0) {
  100. Items[i].no += ArgCount;
  101. }
  102. }
  103. HostString.append( b.HostString );
  104. ArgCount += b.ArgCount;
  105. }
  106. void print(FILE *f) const
  107. {
  108. int i;
  109. fprintf(f,"\"%s\" (%d)", HostString.c_str(), ArgCount);
  110. for (i = 0; i < Items.size(); ++i) {
  111. fprintf(f," %d:%s!%s!", Items[i].no, Items[i].width.c_str(), Items[i].typeName.c_str());
  112. }
  113. fprintf(f,"\n");
  114. LPCSTR b = HostString.begin(), e = HostString.end();
  115. for (i = 0; i < Items.size(); ++i) {
  116. fprintf(f,"%s", string(b, Items[i].location.beg(HostString.begin())).c_str() );
  117. if (Items[i].no >= 0) {
  118. fprintf(f,"<%d:%s:%s>", Items[i].no, Items[i].width.c_str(), Items[i].typeName.c_str());
  119. } else {
  120. fprintf(f,"%s", Items[i].typeName.c_str() );
  121. }
  122. b = Items[i].location.end(HostString.begin());
  123. }
  124. fprintf(f,"%s\n", string(b,e).c_str() );
  125. }
  126. void ParsedFormatString::printMofTxt(FILE *f, int LineNo) const
  127. {
  128. LPCSTR b = HostString.begin(), e = HostString.end();
  129. for (int i = 0; i < Items.size(); ++i) {
  130. fprint_str(f, b, Items[i].location.beg(HostString.begin()) );
  131. b = Items[i].location.end(HostString.begin());
  132. if (Items[i].no > 0) { // BUGBUG
  133. fprintf(f,"%%%d!%s%s!", Items[i].no, Items[i].width.c_str(), Items[i].type->FormatSpec.c_str());
  134. } else {
  135. string fs(Items[i].type->FormatSpec);
  136. if (fs.compare("__LINE__") == 0) {
  137. char fmt[255];
  138. sprintf(fmt,"%%%sd", Items[i].width.c_str() );
  139. fprintf(f,fmt,LineNo);
  140. } else if (fs.compare("__FILE__") == 0) {
  141. char fmt[255];
  142. sprintf(fmt,"%%%ss", Items[i].width.c_str() );
  143. fprintf(f,fmt,currentFileName().c_str() );
  144. } else if (fs.compare("__COMPNAME__") == 0) {
  145. char fmt[255];
  146. sprintf(fmt,"%%%ss", Items[i].width.c_str() );
  147. fprintf(f,fmt,ComponentName.c_str() );
  148. } else {
  149. fprintf(f,"%s", fs.c_str() );
  150. }
  151. }
  152. }
  153. fprint_str(f, b, e);
  154. }
  155. BOOL init(const string& str) {
  156. ArgCount = 0;
  157. Items.resize(0); // to allow reuse
  158. HostString.assign(str);
  159. LPCSTR b = HostString.begin(), e = HostString.end();
  160. LPCSTR p = b, q; // walking ptr
  161. FormatItem current;
  162. int next_argno = 1, maxno = 0;
  163. LPCSTR insert_start;
  164. TYPE_SET::iterator it;
  165. while (p < e) {
  166. for(;;) {
  167. if (*p == '%') {
  168. // make sure it is not followed by another %
  169. if (p+1 == e) goto success;
  170. if (p[1] != '%') break;
  171. p += 2; // skip %%
  172. } else {
  173. p++;
  174. }
  175. if (p == e) goto success;
  176. }
  177. insert_start = p; // remember where '%' starts
  178. if (++p == e) goto unterminated_format_specifier;
  179. // assert(*p != '%')
  180. if (*p != '%') {
  181. current.no = 0; // auto asign
  182. p = SkipTypePrefix(p,e,&current.no);
  183. if (p == e) goto unterminated_format_specifier;
  184. if (noshrieks)
  185. {
  186. q = p; if (q+1 < e && *q == '.' && q[1] == '*') q += 2;
  187. while (q < e && (isdigit(*q) || isalpha(*q) || *q == '_') ) ++q ;
  188. current.typeName.assign(insert_start+1, q);
  189. it = TypeSet.find( current.typeName );
  190. if ( it != TypeSet.end() ) {
  191. current.width.erase();
  192. current.location.set(HostString.begin(),insert_start, q);
  193. p = q - 1;
  194. goto shortcut;
  195. }
  196. } // noshrieks
  197. if (*p == '!') {
  198. LPCSTR second_bang = find(p+1,e,'!');
  199. if (second_bang == e) { goto unterminated_format_specifier; }
  200. if (current.no == -1) {
  201. ReportError("Only digits are allowed between '%' and '!' (%s)\n",
  202. str.c_str() );
  203. return FALSE;
  204. }
  205. q = SkipTypePrefix(p+1,second_bang);
  206. if (q == second_bang) { goto unterminated_format_specifier; }
  207. current.width.assign(p+1, q);
  208. current.typeName.assign(q, second_bang);
  209. current.location.set(HostString.begin(),insert_start, second_bang+1);
  210. p = second_bang;
  211. } else {
  212. current.no = 0;
  213. current.width.assign(insert_start + 1, p);
  214. q = p;
  215. if (*q == 'I') {
  216. if (++q == e) {
  217. goto unterminated_format_specifier;
  218. }
  219. if ( *q == '6' || *q == '4') {
  220. if ( ++q == e || (*q != '4' && *q != '2') )
  221. {
  222. ReportError("bad I64 format in %s\n", str.c_str());
  223. return FALSE;
  224. }
  225. if (++q == e) { goto unterminated_format_specifier; }
  226. }
  227. } else if (*q == 'h'|| *q == 'l' || *q == 'w') {
  228. if (++q == e) { goto unterminated_format_specifier; }
  229. }
  230. current.typeName.assign(p,q+1);
  231. p = q;
  232. current.location.set(HostString.begin(),insert_start, p+1);
  233. }
  234. it = TypeSet.find( current.typeName );
  235. if (it == TypeSet.end() ) {
  236. ReportError("Type '%s' not found. \"%s\"",
  237. current.typeName.c_str(), str.c_str() );
  238. return FALSE;
  239. }
  240. shortcut:
  241. current.type = &it->second;
  242. if ( current.type->isConstant() ) {
  243. current.no = -1;
  244. } else {
  245. if (current.no == 0) {
  246. current.no = next_argno++;
  247. } else {
  248. current.no = current.no - ArgBase + 1;
  249. }
  250. if (current.no > maxno) {
  251. maxno = current.no;
  252. }
  253. }
  254. }
  255. Items.push_back(current);
  256. ++p;
  257. }
  258. success:
  259. if(DbgLevel >= DBG_FLOOD) { print(stdout); }
  260. ArgCount = maxno;
  261. return TRUE;
  262. unterminated_format_specifier:
  263. ReportError("Unterminated Format Specifier in %s\n", str.c_str());
  264. return FALSE;
  265. }
  266. };