windows-nt/Source/XPSP1/NT/sdktools/trace/tracewpp/parsed-string.hxx

291 lines
10 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Revision History:
GorN: 29-Sep-2000 - fix %% handling
GorN: 29-Sep-2000 - pulled out __FUNCTION__ support, now traceprt handles it
GorN: 10-Oct-2000 - special case for .*
GorN: 23-Oct-2000 - support for I type specifier (pointer size integer)
--*/
struct OffsetPair {
int _beg;
int _end;
OffsetPair():_beg(0),_end(0){}
// OffsetPair(const OffsetPair& i):beg(i.beg),end(i.end) {}
OffsetPair(LPCSTR base, LPCSTR b, LPCSTR e):
_beg((int)(b-base)), _end((int)(e-base)) {}
void set(LPCSTR base, LPCSTR b, LPCSTR e) {
_beg = (int)(b-base); _end = (int)(e-base); }
int len() const { return _end - _beg; }
LPCSTR beg(LPCSTR base) const { return base + _beg; }
LPCSTR end(LPCSTR base) const { return base + _end; }
void adjust_by(size_t size) {
_beg += (int)size;
_end += (int)size;
}
};
struct FormatItem {
int no; // arg no
string width;
string typeName; // for debugging only. We don't need it
OffsetPair location; // where it is in the host string
const WppType * type;
string argName;
string expr;
bool operator < (const FormatItem& b) const {
return *type < *b.type;
}
void print(FILE* f) {
fprintf(f,"<%d:%s:%s:%x:%d>", no, width.c_str(), type->TypeName.c_str(),
location._beg, location.len() );
}
};
struct ParsedFormatString {
string HostString;
vector<FormatItem> Items;
int ArgCount;
// mutable bool signatureValid;
private:
// mutable string _Signature;
LPCSTR SkipTypePrefix(LPCSTR p, LPCSTR e, int* no = 0)
{
BOOL no_arg_no = FALSE;
int sum = 0;
// treat .* as a part of a type name
if (p+1 < e && p[0] == '.' && p[1] == '*') {
return p;
}
// skip flags.
while (*p == '-' || *p == '#' || *p == '+') {
no_arg_no = TRUE;
if (++p == e) return e;
}
// skip width (or argno)
while ( isdigit(*p) ) {
sum = sum * 10 + (*p - '0');
if (++p == e) return e;
}
if (*p == '.') {
no_arg_no = TRUE;
// skip precision //
do {
if (++p == e) return e;
} while ( isdigit(*p) );
}
if (no) {
*no = (no_arg_no)?-1:sum;
}
return p;
}
public:
ParsedFormatString(): ArgCount(0) {}
void insert_prefix(const ParsedFormatString& b)
{
for (int i = 0; i < Items.size(); ++i) {
Items[i].location.adjust_by( b.HostString.size() );
if (Items[i].no > 0) {
Items[i].no += b.ArgCount;
}
}
Items.insert(Items.begin(), b.Items.begin(), b.Items.end());
HostString.insert( 0, b.HostString );
ArgCount += b.ArgCount;
}
void append(const ParsedFormatString& b)
{
// adjust location information
int n = (int)Items.size();
Items.insert(Items.end(), b.Items.begin(), b.Items.end());
for (int i = n; i < Items.size(); ++i) {
Items[i].location.adjust_by( HostString.size() );
if (Items[i].no > 0) {
Items[i].no += ArgCount;
}
}
HostString.append( b.HostString );
ArgCount += b.ArgCount;
}
void print(FILE *f) const
{
int i;
fprintf(f,"\"%s\" (%d)", HostString.c_str(), ArgCount);
for (i = 0; i < Items.size(); ++i) {
fprintf(f," %d:%s!%s!", Items[i].no, Items[i].width.c_str(), Items[i].typeName.c_str());
}
fprintf(f,"\n");
LPCSTR b = HostString.begin(), e = HostString.end();
for (i = 0; i < Items.size(); ++i) {
fprintf(f,"%s", string(b, Items[i].location.beg(HostString.begin())).c_str() );
if (Items[i].no >= 0) {
fprintf(f,"<%d:%s:%s>", Items[i].no, Items[i].width.c_str(), Items[i].typeName.c_str());
} else {
fprintf(f,"%s", Items[i].typeName.c_str() );
}
b = Items[i].location.end(HostString.begin());
}
fprintf(f,"%s\n", string(b,e).c_str() );
}
void ParsedFormatString::printMofTxt(FILE *f, int LineNo) const
{
LPCSTR b = HostString.begin(), e = HostString.end();
for (int i = 0; i < Items.size(); ++i) {
fprint_str(f, b, Items[i].location.beg(HostString.begin()) );
b = Items[i].location.end(HostString.begin());
if (Items[i].no > 0) { // BUGBUG
fprintf(f,"%%%d!%s%s!", Items[i].no, Items[i].width.c_str(), Items[i].type->FormatSpec.c_str());
} else {
string fs(Items[i].type->FormatSpec);
if (fs.compare("__LINE__") == 0) {
char fmt[255];
sprintf(fmt,"%%%sd", Items[i].width.c_str() );
fprintf(f,fmt,LineNo);
} else if (fs.compare("__FILE__") == 0) {
char fmt[255];
sprintf(fmt,"%%%ss", Items[i].width.c_str() );
fprintf(f,fmt,currentFileName().c_str() );
} else if (fs.compare("__COMPNAME__") == 0) {
char fmt[255];
sprintf(fmt,"%%%ss", Items[i].width.c_str() );
fprintf(f,fmt,ComponentName.c_str() );
} else {
fprintf(f,"%s", fs.c_str() );
}
}
}
fprint_str(f, b, e);
}
BOOL init(const string& str) {
ArgCount = 0;
Items.resize(0); // to allow reuse
HostString.assign(str);
LPCSTR b = HostString.begin(), e = HostString.end();
LPCSTR p = b, q; // walking ptr
FormatItem current;
int next_argno = 1, maxno = 0;
LPCSTR insert_start;
TYPE_SET::iterator it;
while (p < e) {
for(;;) {
if (*p == '%') {
// make sure it is not followed by another %
if (p+1 == e) goto success;
if (p[1] != '%') break;
p += 2; // skip %%
} else {
p++;
}
if (p == e) goto success;
}
insert_start = p; // remember where '%' starts
if (++p == e) goto unterminated_format_specifier;
// assert(*p != '%')
if (*p != '%') {
current.no = 0; // auto asign
p = SkipTypePrefix(p,e,&current.no);
if (p == e) goto unterminated_format_specifier;
if (noshrieks)
{
q = p; if (q+1 < e && *q == '.' && q[1] == '*') q += 2;
while (q < e && (isdigit(*q) || isalpha(*q) || *q == '_') ) ++q ;
current.typeName.assign(insert_start+1, q);
it = TypeSet.find( current.typeName );
if ( it != TypeSet.end() ) {
current.width.erase();
current.location.set(HostString.begin(),insert_start, q);
p = q - 1;
goto shortcut;
}
} // noshrieks
if (*p == '!') {
LPCSTR second_bang = find(p+1,e,'!');
if (second_bang == e) { goto unterminated_format_specifier; }
if (current.no == -1) {
ReportError("Only digits are allowed between '%' and '!' (%s)\n",
str.c_str() );
return FALSE;
}
q = SkipTypePrefix(p+1,second_bang);
if (q == second_bang) { goto unterminated_format_specifier; }
current.width.assign(p+1, q);
current.typeName.assign(q, second_bang);
current.location.set(HostString.begin(),insert_start, second_bang+1);
p = second_bang;
} else {
current.no = 0;
current.width.assign(insert_start + 1, p);
q = p;
if (*q == 'I') {
if (++q == e) {
goto unterminated_format_specifier;
}
if ( *q == '6' || *q == '4') {
if ( ++q == e || (*q != '4' && *q != '2') )
{
ReportError("bad I64 format in %s\n", str.c_str());
return FALSE;
}
if (++q == e) { goto unterminated_format_specifier; }
}
} else if (*q == 'h'|| *q == 'l' || *q == 'w') {
if (++q == e) { goto unterminated_format_specifier; }
}
current.typeName.assign(p,q+1);
p = q;
current.location.set(HostString.begin(),insert_start, p+1);
}
it = TypeSet.find( current.typeName );
if (it == TypeSet.end() ) {
ReportError("Type '%s' not found. \"%s\"",
current.typeName.c_str(), str.c_str() );
return FALSE;
}
shortcut:
current.type = &it->second;
if ( current.type->isConstant() ) {
current.no = -1;
} else {
if (current.no == 0) {
current.no = next_argno++;
} else {
current.no = current.no - ArgBase + 1;
}
if (current.no > maxno) {
maxno = current.no;
}
}
}
Items.push_back(current);
++p;
}
success:
if(DbgLevel >= DBG_FLOOD) { print(stdout); }
ArgCount = maxno;
return TRUE;
unterminated_format_specifier:
ReportError("Unterminated Format Specifier in %s\n", str.c_str());
return FALSE;
}
};