Various fixes for C++ class parsing (nesting, templates) (from test

cases provided by Michael Lin).
This commit is contained in:
Eric Pouech 2005-01-31 11:29:09 +00:00 committed by Alexandre Julliard
parent 5e2075be3a
commit e4a44b3545
1 changed files with 49 additions and 15 deletions

View File

@ -104,9 +104,18 @@ static void stab_strcpy(char* dest, int sz, const char* source)
* A strcpy routine that stops when we hit the ':' character.
* Faster than copying the whole thing, and then nuking the
* ':'.
* Takes also care of (valid) a::b constructs
*/
while (*source != '\0' && *source != ':' && sz-- > 0)
*dest++ = *source++;
while (*source != '\0')
{
if (source[0] != ':' && sz-- > 0) *dest++ = *source++;
else if (source[1] == ':' && (sz -= 2) > 0)
{
*dest++ = *source++;
*dest++ = *source++;
}
else break;
}
*dest-- = '\0';
/* GCC seems to emit, in some cases, a .<digit>+ suffix.
* This is used for static variable inside functions, so
@ -358,16 +367,29 @@ static int stabs_pts_read_type_def(struct ParseTypedefData* ptd,
static int stabs_pts_read_id(struct ParseTypedefData* ptd)
{
const char* first = ptd->ptr;
unsigned int len;
unsigned int template = 0;
char ch;
PTS_ABORTIF(ptd, (ptd->ptr = strchr(ptd->ptr, ':')) == NULL);
len = ptd->ptr - first;
PTS_ABORTIF(ptd, len >= sizeof(ptd->buf) - ptd->idx);
memcpy(ptd->buf + ptd->idx, first, len);
ptd->buf[ptd->idx + len] = '\0';
ptd->idx += len + 1;
ptd->ptr++; /* ':' */
return 0;
while ((ch = *ptd->ptr++) != '\0')
{
switch (ch)
{
case ':':
if (template == 0)
{
unsigned int len = ptd->ptr - first - 1;
PTS_ABORTIF(ptd, len >= sizeof(ptd->buf) - ptd->idx);
memcpy(ptd->buf + ptd->idx, first, len);
ptd->buf[ptd->idx + len] = '\0';
ptd->idx += len + 1;
return 0;
}
break;
case '<': template++; break;
case '>': PTS_ABORTIF(ptd, template == 0); template--; break;
}
}
return -1;
}
static int stabs_pts_read_number(struct ParseTypedefData* ptd, long* v)
@ -604,7 +626,7 @@ static inline int stabs_pts_read_aggregate(struct ParseTypedefData* ptd,
DWORD size;
symt_get_info(adt, TI_GET_SYMNAME, &name);
strcmp(tmp, "__inherited_class_");
strcpy(tmp, "__inherited_class_");
WideCharToMultiByte(CP_ACP, 0, name, -1,
tmp + strlen(tmp), sizeof(tmp) - strlen(tmp),
NULL, NULL);
@ -845,16 +867,28 @@ static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, const char* typ
}
else
{
unsigned l1, l2;
if (udt->symt.tag != SymTagUDT)
{
ERR("Forward declaration (%p/%s) is not an aggregate (%u)\n",
udt, symt_get_name(&udt->symt), udt->symt.tag);
return -1;
}
if (strcmp(udt->hash_elt.name, typename))
/* FIXME: we currently don't correctly construct nested C++
* classes names. Therefore, we could be here with either:
* - typename and udt->hash_elt.name being the same string
* (non embedded case)
* - typename being foo::bar while udt->hash_elt.name being
* just bar
* So, we twist the comparison to test both occurrences. When
* we have proper C++ types in this file, this twist has to be
* removed
*/
l1 = strlen(udt->hash_elt.name);
l2 = strlen(typename);
if (l1 > l2 || strcmp(udt->hash_elt.name, typename + l2 - l1))
ERR("Forward declaration name mismatch %s <> %s\n",
udt->hash_elt.name, typename);
/* should check typename is the same too */
new_dt = &udt->symt;
}
PTS_ABORTIF(ptd, stabs_pts_read_aggregate(ptd, udt) == -1);
@ -971,7 +1005,7 @@ static int stabs_parse_typedef(struct module* module, const char* ptr,
/* check for already existing definition */
TRACE("%s\n", debugstr_a(ptr));
TRACE("%s => %s\n", typename, debugstr_a(ptr));
ptd.module = module;
ptd.idx = 0;
#ifdef PTS_DEBUG