/* Reading the operator name */ static int lex_op(usenet_parser_t self, int ch) { /* Watch for EOF or linefeed in the middle of the expression */ if (ch == EOF || ch == '\n') { parse_error(self, "unexpected end of line"); return -1; } /* Watch for an escape character */ if (ch == '\\') { self->state = lex_op_esc; return 0; } /* Watch for a stray separator */ if (ch == '/') { parse_error(self, "incomplete expression"); return -1; } /* Watch for more whitespace */ if (isspace(ch)) { /* Null-terminate the token */ if (append_char(self, '\0') < 0) { return -1; } /* Look up the operator */ self->operator = translate_op(self->token); if (self->operator == O_NONE) { char *buffer = malloc(strlen(OP_ERROR_MSG) + strlen( self->token) - 1); if (buffer != NULL) { sprintf(buffer, OP_ERROR_MSG, self->token); parse_error(self, buffer); free(buffer); } return -1; } /* Make sure there's agreement between the field and the operator */ if (self->field == F_XPOSTS) { if (self->operator == O_MATCHES || self->operator == O_NOT) { parse_error(self, "illegal field/operator combination"); return -1; } } else { if (self->operator == O_LT || self->operator == O_GT || self->operator == O_LE || self->operator == O_GE) { parse_error(self, "illegal field/operator combination"); return -1; } } /* Get ready to read the pattern */ self->token_pointer = self->token; self->state = lex_pattern_start; return 0; } /* Anything else is part of the operator */ return append_char(self, ch); }
/***************************************************************************** * * Given a mangled name in "src", unmangle it if necessary, putting the * result in "dest", copying at most "maxlen" characters, including * trailing null. It is assumed that dest is bigger than src, and big * enough for any function name + class name. * * Returns zero if the name is not a legal mangled name. * */ umKind unmangle(char * src, char * dest, unsigned maxlen, char * classP, char * nameP, int doArgs) { char * srcP; /* for scanning src */ char * dstP; /* for scanning dest */ char * mainName; /* the main name */ char * className; /* qualifying name, if present */ char * dstClass; unsigned len; int avail; /* chars left in dest */ char cfunc; /* it is a const function */ char vfunc; /* it is a volatile function */ char argBuff[MAXARGSLEN]; /* for arg tables */ char name[MAXNOTRUNC]; umKind kind; int thunk; if (src == 0) return UM_NOT_MANGLED; if (*src != '@') { strcpy(dest, src); return UM_NOT_MANGLED; } if (dest) { char * tmpp = dest; char near * endp = (char near *)tmpp + maxlen; do { *tmpp++ = 0; } while ((char near *)tmpp < endp); } outerClass = 0; strncpy(name, src, MAXNOTRUNC-1); name[MAXNOTRUNC-1] = 0; /* Setup arg buffer variables */ argBuffNext = argBuff; argBuffFree = MAXARGSLEN; /* See if this is a pascal (up-cased) mangled name */ for (srcP = name+1; *srcP; srcP++) { if (*srcP >= 'a' && *srcP <= 'z') goto NOT_PASCAL; } /* Entire name is uppercase, assume it's been pascal-ized */ for (srcP = name+1; *srcP; srcP++) *srcP = tolower(*srcP); NOT_PASCAL: /* Find the second '@' or '$' separator */ srcP = name + 1; if (srcP[0] == '$' && (srcP[1] == 'b' || srcP[1] == 'o')) srcP += 3; while (*srcP) { if (*srcP == '@' || *srcP == '$') break; if (*srcP == '%') { srcP = skipTemplateName(srcP); continue; } srcP++; } /* Can't be mangled if second '@' or '$' is missing */ if (*srcP == 0) { /* Special check: truncated template class name */ if (src[0] == '@' && src[1] == '%') { isTemplateName = 0; if (!setjmp(jmpb)) { if (dest ) copyClassName(dest, src+1, maxlen); if (nameP) copyClassName(nameP, src+1, maxlen); return UM_NOT_MANGLED; } /* Is this a template name? */ if (isTemplateName) { if (dest ) strcat(dest, "...>"); if (nameP) strcat(nameP, "...>"); return UM_NOT_MANGLED; } } NOT_MANGLED: if (dest ) strcpy(dest, src); if (nameP) strcpy(nameP, src); return UM_NOT_MANGLED; } /* See if this is a member function */ if (*srcP == '@') { char * tmpP; /* See if this is a nested class member */ for (tmpP = srcP + 1; *tmpP; tmpP++) { if (*tmpP == '@') { /* Remember last '@' separator */ srcP = tmpP; } else if (*tmpP == '$') { break; } else if (*tmpP == '%') { /* This is a template class name */ tmpP = skipTemplateName(tmpP); } } *srcP++ = 0; /* null-terminate class name */ className = name + 1; while (isdigit(*srcP)) /* 'huge' class? */ srcP++; /* Now pointing to the main name */ mainName = srcP; /* find '$' separator */ if (srcP[0] == '$' && (srcP[1] == 'b' || srcP[1] == 'o')) srcP += 3; while (*srcP && *srcP != '$') ++srcP; if (*srcP == 0) { /* Must be a static member */ kind = UM_STATIC_DM; goto COPYIT; } } else { className = 0; /* not a member function */ mainName = name + 1; if (mainName == srcP) { /* 'main' name appears to be empty - is this a thunk? */ if (strncmp(srcP, "$vc1$", 5)) goto NOT_MANGLED; srcP += 5; kind = UM_THUNK; thunk = 1; goto COPYIT; } } /* null-terminate "main" name and point to encoding of type definition */ *srcP++ = 0; /* Now figure out what kind of beast this is */ if (mainName[0] == '$') /* check for special names */ { mainName += 2; if (mainName[-1] == 'b') /* ctor, dtor, or operator */ { if (strcmp(mainName, "ctr") == 0) kind = UM_CONSTRUCTOR; else if (strcmp(mainName, "dtr") == 0) kind = UM_DESTRUCTOR; else kind = UM_OPERATOR; } else kind = UM_CONVERSION; /* type conversion */ } else kind = UM_MEMBER_FN; /* "ordinary" name */ /* Copy class and main name to caller's buffers (if applicable) */ COPYIT: dstClass = 0; if (classP) copyClassName(classP, className, maxlen); if ( nameP) { if (dest == 0) { dstP = nameP; doArgs = 0; avail = 63; if (setjmp(jmpb)) goto trunc_exit; goto DONAME; } strcpy( nameP, mainName); } if (dest == 0) return kind; /* Setup destination pointer, and remaining dest. buffer length */ dstP = dest; avail = maxlen - 5; /* Leave some extra room at the end */ /* Prepare the quick exit route */ if (setjmp(jmpb)) { trunc_exit: /* Make sure there's room for the "..." */ if (maxlen) dest[maxlen - 4] = 0; strcat(dstP, "..."); return kind; } /* Setup arg buffer variables */ argBuffNext = argBuff; argBuffFree = MAXARGSLEN; /* emit qualifying name, if any */ #ifdef IN_MOJO if (className && !(doArgs & DoArgsNoClassPrefix)) #else if (className) #endif { dstClass = dstP; len = copyClassName(dstP, className, avail); dstP += len; *dstP++ = ':'; *dstP++ = ':'; avail -= len + 2; } /* emit the main name */ DONAME: switch (kind) { case UM_DESTRUCTOR: *dstP++ = '~'; case UM_CONSTRUCTOR: if (dstClass) { char * temp = dstP - 2; if (temp[-1] == ':') temp--; *temp = 0; strcpy(dstP, lastClassName(dstClass)); dstP += strlen(dstP); *temp = ':'; } else { dstP += copyClassName(dstP, className, avail); } break; case UM_OPERATOR: strcpy(dstP, "operator "); dstP += 9; strcpy(dstP, translate_op(mainName)); break; case UM_CONVERSION: strcpy(dstP, "operator "); dstP += 9; avail -= 9; arg_type(&mainName, &dstP, &avail, 0); kind = UM_CONVERSION; break; case UM_MEMBER_FN: case UM_STATIC_DM: strcpy(dstP, mainName); break; case UM_THUNK: convertThunkName(dstP, srcP, thunk); break; } #ifdef IN_MOJO if (!(doArgs & DoArgsArguments)) return kind; #else if (!doArgs) return kind; #endif /* Point to end of destination and figure available space */ dstP += strlen(dstP); avail = dest + maxlen - dstP - 1; if (avail < 0) avail = 0; /* check for a const/volatile function */ cfunc = vfunc = 0; for (;;) { if (*srcP == 'x') cfunc = 1; else if (*srcP == 'w') vfunc = 1; else break; ++srcP; } /* handle argument list */ if (*srcP == 'q') { ++srcP; arg_list(&srcP, &dstP, &avail); } /* tack on const/volatile function modifier */ if (cfunc) { if (avail < 6) goto trunc_exit; strcat(dstP, " const"); } if (vfunc) { if (avail < 9) goto trunc_exit; strcat(dstP, " volatile"); } return kind; }