stage2: reference support (refs)
- Builtin refs: int& -> int* in signature, (*a) deref in body - Class refs: Cls& -> Cls* in signature, p.field -> p->field in body - Call-site & injection via FnRef table (swap(x,y) -> swap(&x,&y)) - Member call ref args also get & injected - Virtual dispatch for pointer-ref params preserved - parse_member_decl: ptr param recording + dot-to-arrow conversion - parse_function: iref body rewrite + fnref call-site rewrite
这个提交包含在:
二进制
二进制文件未显示。
+386
-26
@@ -37,6 +37,41 @@ static int g_line = 1;
|
||||
static int g_ns_open = 0; /* namespace block depth (flattened) */
|
||||
static int g_virt_pending = 0; /* next member decl is virtual */
|
||||
|
||||
/* ---------------- references ---------------- */
|
||||
typedef struct FnRef {
|
||||
char fn[64];
|
||||
int arg[16];
|
||||
int narg;
|
||||
struct FnRef *next;
|
||||
} FnRef;
|
||||
static FnRef *g_fnrefs = NULL;
|
||||
static FnRef *find_fnref(const char *fn)
|
||||
{
|
||||
FnRef *p;
|
||||
for (p = g_fnrefs; p; p = p->next)
|
||||
if (!strcmp(p->fn, fn)) return p;
|
||||
return NULL;
|
||||
}
|
||||
static int fr_has_arg(const FnRef *fr, int ai)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < fr->narg; i++)
|
||||
if (fr->arg[i] == ai) return 1;
|
||||
return 0;
|
||||
}
|
||||
static void add_fnref(const char *fn, int ai)
|
||||
{
|
||||
FnRef *p = find_fnref(fn);
|
||||
if (!p) {
|
||||
p = (FnRef*)calloc(1, sizeof *p);
|
||||
strncpy(p->fn, fn, sizeof p->fn - 1);
|
||||
p->fn[sizeof p->fn - 1] = 0;
|
||||
p->next = g_fnrefs;
|
||||
g_fnrefs = p;
|
||||
}
|
||||
if (p->narg < 16) p->arg[p->narg++] = ai;
|
||||
}
|
||||
|
||||
/* ---------------- templates ---------------- */
|
||||
|
||||
typedef struct TplFn {
|
||||
@@ -523,12 +558,16 @@ static void proto_emit(const char *fmt, ...)
|
||||
static void gather_decl(char *type, int typesz, char *name, int namesz);
|
||||
static int tpl_call_check(char varcls[][128], char varname[][64], int nvars);
|
||||
|
||||
static void parse_member_decl(const char *cls, const char *ret_type,
|
||||
const char *mname_in, int is_virtual)
|
||||
static void parse_member_decl(const char *cls, const char *ret_type, const char *mname_in, int is_virt)
|
||||
{
|
||||
char name[256];
|
||||
char mname[256];
|
||||
int is_ctor, is_dtor;
|
||||
char bptrcls[64][128], bptrname[64][64];
|
||||
int bnptrs = 0;
|
||||
char biref[64][64];
|
||||
int bn_iref = 0;
|
||||
int sig_pidx = 0;
|
||||
ClassInfo *ci = find_class(cls);
|
||||
|
||||
if (mname_in && mname_in[0])
|
||||
@@ -543,7 +582,7 @@ static void parse_member_decl(const char *cls, const char *ret_type,
|
||||
if (is_dtor) ci->has_dtor = 1;
|
||||
else add_member(ci, name);
|
||||
/* record virtual methods (name + trimmed return type) */
|
||||
if (is_virtual && !is_ctor && !is_dtor && ci->n_virt < 16) {
|
||||
if (is_virt && !is_ctor && !is_dtor && ci->n_virt < 16) {
|
||||
char rtb[64];
|
||||
int rl;
|
||||
snprintf(rtb, sizeof rtb, "%s", ret_type);
|
||||
@@ -609,10 +648,29 @@ static void parse_member_decl(const char *cls, const char *ret_type,
|
||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")")) depth--;
|
||||
/* class type param -> struct Class */
|
||||
if (g_tok.type == T_IDENT && find_class(g_tok.text)) {
|
||||
char ptcls[128];
|
||||
strncpy(ptcls, g_tok.text, sizeof ptcls - 1);
|
||||
ptcls[sizeof ptcls - 1] = 0;
|
||||
proto_emit(" struct %s", g_tok.text);
|
||||
strncat(g_params, " struct ", sizeof g_params - strlen(g_params) - 1);
|
||||
strncat(g_params, g_tok.text, sizeof g_params - strlen(g_params) - 1);
|
||||
next_tok();
|
||||
/* handle * or & suffix: convert to pointer param */
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
(!strcmp(g_tok.text, "*") || !strcmp(g_tok.text, "&"))) {
|
||||
int is_ref = !strcmp(g_tok.text, "&");
|
||||
proto_emit(" *");
|
||||
strncat(g_params, " *", sizeof g_params - strlen(g_params) - 1);
|
||||
next_tok();
|
||||
/* record ptr param for body dispatch */
|
||||
if (g_tok.type == T_IDENT && bnptrs < 64) {
|
||||
strncpy(bptrcls[bnptrs], ptcls, 127);
|
||||
strncpy(bptrname[bnptrs], g_tok.text, 63);
|
||||
bnptrs++;
|
||||
}
|
||||
if (is_ref)
|
||||
add_fnref(mname, sig_pidx);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* smart spacing for prototype params */
|
||||
@@ -620,12 +678,19 @@ static void parse_member_decl(const char *cls, const char *ret_type,
|
||||
const char *tt = g_tok.text;
|
||||
int c = tt[0];
|
||||
if (g_tok.type == T_PUNCT) {
|
||||
if (!(c == ')' || c == ']' || c == ';' || c == ',' ||
|
||||
c == '*' || c == '&' || c == '(' ))
|
||||
proto_emit(" ");
|
||||
proto_emit("%s", tt);
|
||||
strncat(g_params, " ", sizeof g_params - strlen(g_params) - 1);
|
||||
strncat(g_params, tt, sizeof g_params - strlen(g_params) - 1);
|
||||
if (c == '&') {
|
||||
/* reference param -> pointer param */
|
||||
proto_emit("*");
|
||||
strncat(g_params, " *", sizeof g_params - strlen(g_params) - 1);
|
||||
add_fnref(mname, sig_pidx);
|
||||
} else {
|
||||
if (!(c == ')' || c == ']' || c == ';' || c == ',' ||
|
||||
c == '*' || c == '&' || c == '(' ))
|
||||
proto_emit(" ");
|
||||
proto_emit("%s", tt);
|
||||
strncat(g_params, " ", sizeof g_params - strlen(g_params) - 1);
|
||||
strncat(g_params, tt, sizeof g_params - strlen(g_params) - 1);
|
||||
}
|
||||
} else {
|
||||
proto_emit(" %s", tt);
|
||||
strncat(g_params, " ", sizeof g_params - strlen(g_params) - 1);
|
||||
@@ -675,6 +740,17 @@ static void parse_member_decl(const char *cls, const char *ret_type,
|
||||
int prev_dot = 0;
|
||||
while (bd > 0) {
|
||||
if (g_tok.type == T_EOF) break;
|
||||
/* builtin ref param: a -> (*a) */
|
||||
if (g_tok.type == T_IDENT && bn_iref > 0) {
|
||||
int i;
|
||||
for (i = 0; i < bn_iref; i++)
|
||||
if (!strcmp(g_tok.text, biref[i])) break;
|
||||
if (i < bn_iref) {
|
||||
proto_emit(" (*%s)", g_tok.text);
|
||||
next_tok();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* namespace-qualified name: ns::name -> name */
|
||||
if (g_tok.type == T_IDENT && !find_class(g_tok.text)) {
|
||||
Token nxt;
|
||||
@@ -838,7 +914,85 @@ static void parse_member_decl(const char *cls, const char *ret_type,
|
||||
next_tok();
|
||||
continue;
|
||||
}
|
||||
/* ptr/var member dispatch: p->method / p.field */
|
||||
if (g_tok.type == T_IDENT && bnptrs > 0) {
|
||||
int pi;
|
||||
for (pi = 0; pi < bnptrs; pi++) {
|
||||
if (!strcmp(g_tok.text, bptrname[pi])) {
|
||||
Token t1, t2;
|
||||
read_tok(&t1);
|
||||
if (t1.type == T_PUNCT && !strcmp(t1.text, "->")) {
|
||||
read_tok(&t2);
|
||||
if (t2.type == T_IDENT) {
|
||||
Token t3;
|
||||
read_tok(&t3);
|
||||
if (t3.type == T_PUNCT && !strcmp(t3.text, "(")) {
|
||||
char meth[128], mname[256];
|
||||
ClassInfo *pci = find_class(bptrcls[pi]);
|
||||
strncpy(meth, t2.text, sizeof meth - 1);
|
||||
meth[sizeof meth - 1] = 0;
|
||||
if (is_virtual(pci, meth)) {
|
||||
proto_emit(" %s->__vtbl->%s(%s",
|
||||
g_tok.text, meth, g_tok.text);
|
||||
} else {
|
||||
snprintf(mname, sizeof mname, "%s_%s",
|
||||
bptrcls[pi], meth);
|
||||
proto_emit(" %s(%s", mname, g_tok.text);
|
||||
}
|
||||
next_tok(); next_tok(); next_tok();
|
||||
if (!(g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")"))) {
|
||||
proto_emit(", ");
|
||||
int ad = 0;
|
||||
while (!(g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")") && ad == 0)) {
|
||||
if (g_tok.type == T_EOF) break;
|
||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "(")) ad++;
|
||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")")) ad--;
|
||||
proto_emit(" %s", g_tok.text);
|
||||
next_tok();
|
||||
}
|
||||
}
|
||||
proto_emit(")");
|
||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ")")) next_tok();
|
||||
prev_dot = 0;
|
||||
continue;
|
||||
}
|
||||
unread_tok(&t3);
|
||||
}
|
||||
unread_tok(&t2);
|
||||
} else if (t1.type == T_PUNCT && !strcmp(t1.text, ".")) {
|
||||
unread_tok(&t1);
|
||||
break;
|
||||
}
|
||||
unread_tok(&t1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* fall-through: emit token as-is */
|
||||
/* ptr ref: p.field -> p->field (fix dot to arrow for known ptr vars) */
|
||||
if (g_tok.type == T_IDENT && bnptrs > 0) {
|
||||
int pi2;
|
||||
for (pi2 = 0; pi2 < bnptrs; pi2++) {
|
||||
if (!strcmp(g_tok.text, bptrname[pi2])) {
|
||||
Token nxt2;
|
||||
read_tok(&nxt2);
|
||||
if (nxt2.type == T_PUNCT && !strcmp(nxt2.text, ".")) {
|
||||
Token nxt3;
|
||||
read_tok(&nxt3);
|
||||
if (nxt3.type == T_IDENT) {
|
||||
proto_emit("%s->%s", g_tok.text, nxt3.text);
|
||||
/* consumed '.', field by read_tok; skip 'p' via next_tok */
|
||||
next_tok(); /* consume 'p' from g_tok */
|
||||
prev_dot = 1;
|
||||
continue;
|
||||
}
|
||||
unread_tok(&nxt3);
|
||||
}
|
||||
unread_tok(&nxt2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev_dot = (g_tok.type == T_PUNCT &&
|
||||
(!strcmp(g_tok.text, ".") || !strcmp(g_tok.text, "->")));
|
||||
proto_emit(" %s", g_tok.text);
|
||||
@@ -1126,6 +1280,18 @@ static void parse_member_definition(const char *ret_type)
|
||||
if (g_tok.type == T_IDENT && find_class(g_tok.text)) {
|
||||
emit(" struct %s", g_tok.text);
|
||||
next_tok();
|
||||
/* handle * or & suffix */
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
(!strcmp(g_tok.text, "*") || !strcmp(g_tok.text, "&"))) {
|
||||
emit(" *");
|
||||
next_tok();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* builtin ref param: type &name -> type *name */
|
||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "&")) {
|
||||
emit("*");
|
||||
next_tok();
|
||||
continue;
|
||||
}
|
||||
emit_tok();
|
||||
@@ -1706,6 +1872,9 @@ static void parse_function(const char *ret_type, const char *name)
|
||||
char ptrcls[64][128]; /* pointer variable name -> class name */
|
||||
char ptrname[64][64];
|
||||
int nptrs = 0;
|
||||
char iref[64][64]; /* builtin-type reference params (deref in body) */
|
||||
int n_iref = 0;
|
||||
int sig_pidx = 0; /* param index while scanning signature */
|
||||
|
||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "::")) {
|
||||
/* member function: class is 'name', method follows */
|
||||
@@ -1742,14 +1911,21 @@ static void parse_function(const char *ret_type, const char *name)
|
||||
/* signature: class types need 'struct'; class params are recorded */
|
||||
while (!(g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{"))) {
|
||||
if (g_tok.type == T_EOF) break;
|
||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ",")) {
|
||||
sig_pidx++;
|
||||
emit_tok();
|
||||
next_tok();
|
||||
continue;
|
||||
}
|
||||
if (g_tok.type == T_IDENT && find_class(g_tok.text)) {
|
||||
char clsname[128];
|
||||
Token nxt;
|
||||
strncpy(clsname, g_tok.text, sizeof clsname - 1);
|
||||
clsname[sizeof clsname - 1] = 0;
|
||||
read_tok(&nxt);
|
||||
if (nxt.type == T_PUNCT && !strcmp(nxt.text, "*")) {
|
||||
/* Cls* name -> struct Cls* name (pointer param) */
|
||||
if (nxt.type == T_PUNCT &&
|
||||
(!strcmp(nxt.text, "*") || !strcmp(nxt.text, "&"))) {
|
||||
/* Cls* / Cls& name -> struct Cls* name (pointer param) */
|
||||
emit(" struct %s*", clsname);
|
||||
next_tok(); /* g_tok = param name */
|
||||
if (g_tok.type == T_IDENT && nptrs < 64) {
|
||||
@@ -1758,6 +1934,8 @@ static void parse_function(const char *ret_type, const char *name)
|
||||
nptrs++;
|
||||
emit(" %s", g_tok.text);
|
||||
next_tok();
|
||||
if (!strcmp(nxt.text, "&"))
|
||||
add_fnref(name, sig_pidx);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1774,6 +1952,24 @@ static void parse_function(const char *ret_type, const char *name)
|
||||
}
|
||||
emit(" struct %s", clsname);
|
||||
unread_tok(&nxt);
|
||||
} else if (g_tok.type == T_IDENT && !find_class(g_tok.text)) {
|
||||
/* builtin ref param: int &a -> int *a */
|
||||
Token nxt;
|
||||
read_tok(&nxt);
|
||||
if (nxt.type == T_PUNCT && !strcmp(nxt.text, "&")) {
|
||||
emit(" %s*", g_tok.text);
|
||||
next_tok(); /* g_tok = param name */
|
||||
if (g_tok.type == T_IDENT && n_iref < 64) {
|
||||
strncpy(iref[n_iref], g_tok.text, 63);
|
||||
iref[n_iref][63] = 0;
|
||||
n_iref++;
|
||||
}
|
||||
add_fnref(name, sig_pidx);
|
||||
emit(" %s", g_tok.text); /* emit param name */
|
||||
next_tok();
|
||||
continue;
|
||||
}
|
||||
unread_tok(&nxt);
|
||||
}
|
||||
emit_tok();
|
||||
next_tok();
|
||||
@@ -1797,6 +1993,64 @@ static void parse_function(const char *ret_type, const char *name)
|
||||
/* template function call: max(a, b) -> max_i(a, b) */
|
||||
if (tpl_call_check(varcls, varname, nvars))
|
||||
continue;
|
||||
/* builtin ref param: a -> (*a) */
|
||||
if (g_tok.type == T_IDENT && n_iref > 0) {
|
||||
int i;
|
||||
for (i = 0; i < n_iref; i++)
|
||||
if (!strcmp(g_tok.text, iref[i])) break;
|
||||
if (i < n_iref) {
|
||||
emit(" (*%s)", g_tok.text);
|
||||
next_tok();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* function call with reference args: swap(x, y) -> swap(&x, &y) */
|
||||
if (g_tok.type == T_IDENT) {
|
||||
FnRef *fr = find_fnref(g_tok.text);
|
||||
if (fr) {
|
||||
Token nxt;
|
||||
read_tok(&nxt);
|
||||
if (nxt.type == T_PUNCT && !strcmp(nxt.text, "(")) {
|
||||
unread_tok(&nxt); /* push '(' back — next_tok calls will consume properly */
|
||||
int ai = 0, adepth = 0;
|
||||
for (int ki = 0; ki < n_iref; ki++) fprintf(stderr, " iref[%d]=%s", ki, iref[ki]);
|
||||
fprintf(stderr, "\n");
|
||||
for (int ki = 0; ki < fr->narg; ki++) fprintf(stderr, " DBG fnref arg[%d]=%d", ki, fr->arg[ki]);
|
||||
fprintf(stderr, "\n");
|
||||
emit(" %s(", g_tok.text);
|
||||
next_tok(); /* consume name */
|
||||
next_tok(); /* consume '(' */
|
||||
if (!(g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")"))) {
|
||||
for (;;) {
|
||||
if (g_tok.type == T_EOF) break;
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")") && adepth == 0)
|
||||
break;
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, "(")) adepth++;
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")")) adepth--;
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ",") && adepth == 0) {
|
||||
ai++;
|
||||
emit(",");
|
||||
next_tok();
|
||||
continue;
|
||||
}
|
||||
if (fr_has_arg(fr, ai)) emit("&");
|
||||
emit_tok();
|
||||
next_tok();
|
||||
}
|
||||
}
|
||||
emit(")");
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")")) next_tok();
|
||||
continue;
|
||||
}
|
||||
unread_tok(&nxt);
|
||||
}
|
||||
}
|
||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{")) { depth++; emit(" {"); next_tok(); continue; }
|
||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "}")) {
|
||||
if (depth > 0) { depth--; emit("}"); next_tok(); continue; }
|
||||
@@ -1810,6 +2064,27 @@ static void parse_function(const char *ret_type, const char *name)
|
||||
clsname[sizeof clsname - 1] = 0;
|
||||
emit(" struct %s", clsname);
|
||||
next_tok();
|
||||
/* reference declaration: Cls& r = p -> struct Cls* r = &p */
|
||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "&")) {
|
||||
emit(" *");
|
||||
next_tok();
|
||||
if (g_tok.type == T_IDENT && nptrs < 64) {
|
||||
strncpy(ptrcls[nptrs], clsname, 127);
|
||||
strncpy(ptrname[nptrs], g_tok.text, 63);
|
||||
nptrs++;
|
||||
emit(" %s", g_tok.text);
|
||||
next_tok();
|
||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "=")) {
|
||||
emit(" = &");
|
||||
next_tok();
|
||||
if (g_tok.type == T_IDENT) {
|
||||
emit(" %s", g_tok.text);
|
||||
next_tok();
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* pointer declaration: Cls* p = ... */
|
||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "*")) {
|
||||
emit(" *");
|
||||
@@ -2046,21 +2321,33 @@ static void parse_function(const char *ret_type, const char *name)
|
||||
token to reach first arg or ')' */
|
||||
next_tok(); /* -> first arg or ) */
|
||||
/* now g_tok is first arg or ')' */
|
||||
if (!(g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")"))) {
|
||||
emit(", ");
|
||||
int adepth = 0;
|
||||
while (!(g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")") && adepth == 0)) {
|
||||
if (g_tok.type == T_EOF) break;
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, "(")) adepth++;
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")")) adepth--;
|
||||
emit_tok();
|
||||
next_tok();
|
||||
}
|
||||
}
|
||||
if (!(g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")"))) {
|
||||
emit(", ");
|
||||
int adepth = 0;
|
||||
int carg = 0;
|
||||
while (!(g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")") && adepth == 0)) {
|
||||
if (g_tok.type == T_EOF) break;
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, "(")) adepth++;
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")")) adepth--;
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ",") && adepth == 0) {
|
||||
carg++;
|
||||
emit(",");
|
||||
next_tok();
|
||||
continue;
|
||||
}
|
||||
if (carg < 16) {
|
||||
FnRef *fr = find_fnref(mname);
|
||||
if (fr && fr_has_arg(fr, carg)) emit("&");
|
||||
}
|
||||
emit_tok();
|
||||
next_tok();
|
||||
}
|
||||
}
|
||||
emit(")");
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")")) next_tok();
|
||||
@@ -2134,6 +2421,78 @@ static void parse_function(const char *ret_type, const char *name)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* pointer member call / virtual dispatch: p->method(args) */
|
||||
if (g_tok.type == T_IDENT && nptrs > 0) {
|
||||
int pi;
|
||||
for (pi = 0; pi < nptrs; pi++) {
|
||||
if (!strcmp(g_tok.text, ptrname[pi])) {
|
||||
Token t1;
|
||||
read_tok(&t1);
|
||||
if (t1.type == T_PUNCT && !strcmp(t1.text, "->")) {
|
||||
/* method call via -> */
|
||||
Token t2;
|
||||
read_tok(&t2);
|
||||
if (t2.type == T_IDENT) {
|
||||
Token t3;
|
||||
read_tok(&t3);
|
||||
if (t3.type == T_PUNCT &&
|
||||
!strcmp(t3.text, "(")) {
|
||||
char meth[128], mname[256];
|
||||
ClassInfo *pci = find_class(ptrcls[pi]);
|
||||
strncpy(meth, t2.text, sizeof meth - 1);
|
||||
meth[sizeof meth - 1] = 0;
|
||||
if (is_virtual(pci, meth)) {
|
||||
emit(" %s->__vtbl->%s(%s",
|
||||
g_tok.text, meth, g_tok.text);
|
||||
} else {
|
||||
snprintf(mname, sizeof mname, "%s_%s",
|
||||
ptrcls[pi], meth);
|
||||
emit(" %s(%s", mname, g_tok.text);
|
||||
}
|
||||
next_tok();
|
||||
next_tok();
|
||||
next_tok();
|
||||
if (!(g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")"))) {
|
||||
emit(", ");
|
||||
int adepth = 0;
|
||||
while (!(g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")") &&
|
||||
adepth == 0)) {
|
||||
if (g_tok.type == T_EOF) break;
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, "(")) adepth++;
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")")) adepth--;
|
||||
emit_tok();
|
||||
next_tok();
|
||||
}
|
||||
}
|
||||
emit(")");
|
||||
if (g_tok.type == T_PUNCT &&
|
||||
!strcmp(g_tok.text, ")")) next_tok();
|
||||
goto next_body_tok;
|
||||
}
|
||||
unread_tok(&t3);
|
||||
}
|
||||
unread_tok(&t2);
|
||||
} else if (t1.type == T_PUNCT && !strcmp(t1.text, ".")) {
|
||||
/* data member via ref: p.field -> p->field */
|
||||
Token t2;
|
||||
read_tok(&t2);
|
||||
if (t2.type == T_IDENT) {
|
||||
emit(" %s->%s", g_tok.text, t2.text);
|
||||
next_tok(); /* consume '.' */
|
||||
next_tok(); /* consume field name */
|
||||
goto next_body_tok;
|
||||
}
|
||||
unread_tok(&t2);
|
||||
}
|
||||
unread_tok(&t1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* class name used as type -> add 'struct' */
|
||||
if (g_tok.type == T_IDENT && find_class(g_tok.text)) {
|
||||
emit(" struct %s", g_tok.text);
|
||||
@@ -2519,3 +2878,4 @@ int main(int argc, char **argv)
|
||||
if (g_out != stdout) fclose(g_out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户