feat: C++ 阶段 2 - 模板函数基础
- template <class T> 函数: 捕获定义, 调用时按首参类型推断实例化 - 实例化命名: max(3,5)->max_i, max(1.5,2.5)->max_d, bigger(p1,p2)->bigger_Point - 输出三段式布局: [声明/类] [模板实例化定义] [顶层函数] - 类类型模板参数自动加 struct 前缀 - 多参数模板/模板类: 干净跳过并注释 - 修复: Cls a(3), b(7) 多声明符带构造参数 - 输出改为内存缓冲 (8MB) 支持重排
这个提交包含在:
二进制
二进制文件未显示。
+344
-8
@@ -36,6 +36,33 @@ static Token g_tok;
|
|||||||
static int g_line = 1;
|
static int g_line = 1;
|
||||||
static int g_ns_open = 0; /* namespace block depth (flattened) */
|
static int g_ns_open = 0; /* namespace block depth (flattened) */
|
||||||
|
|
||||||
|
/* ---------------- templates ---------------- */
|
||||||
|
|
||||||
|
typedef struct TplFn {
|
||||||
|
char name[64]; /* template function name */
|
||||||
|
char tparam[32]; /* type parameter name (e.g. "T") */
|
||||||
|
char body[4096]; /* captured function text with T placeholder */
|
||||||
|
struct TplFn *next;
|
||||||
|
} TplFn;
|
||||||
|
static TplFn *g_tplfns = NULL;
|
||||||
|
|
||||||
|
typedef struct TplInst {
|
||||||
|
char name[128]; /* mangled instantiated name, e.g. max_i */
|
||||||
|
struct TplInst *next;
|
||||||
|
} TplInst;
|
||||||
|
static TplInst *g_tplinsts = NULL;
|
||||||
|
|
||||||
|
static int g_capture = 0; /* capture emit() into g_cap */
|
||||||
|
static char g_cap[4096];
|
||||||
|
static int g_cap_len;
|
||||||
|
static int g_emit_sect = 0; /* 0 = decl buffer, 1 = function buffer */
|
||||||
|
static char g_outbuf[8 * 1024 * 1024]; /* declarations (classes, globals) */
|
||||||
|
static int g_out_len;
|
||||||
|
static char g_fn_buf[8 * 1024 * 1024]; /* top-level function bodies */
|
||||||
|
static int g_fn_len;
|
||||||
|
static char g_tpl_defs[16384]; /* instantiated definitions (flushed at end) */
|
||||||
|
static int g_tpl_defs_len;
|
||||||
|
|
||||||
typedef struct ClassInfo {
|
typedef struct ClassInfo {
|
||||||
char name[128];
|
char name[128];
|
||||||
char base[128];
|
char base[128];
|
||||||
@@ -355,8 +382,23 @@ static int g_out_is_word = 0; /* last emitted char was word char */
|
|||||||
static void emit(const char *fmt, ...)
|
static void emit(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
int n;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vfprintf(g_out, fmt, ap);
|
if (g_capture) {
|
||||||
|
n = vsnprintf(g_cap + g_cap_len, sizeof g_cap - g_cap_len, fmt, ap);
|
||||||
|
if (n > 0) g_cap_len += n;
|
||||||
|
if (g_cap_len >= (int)sizeof g_cap - 1) g_cap_len = sizeof g_cap - 1;
|
||||||
|
} else if (g_emit_sect == 1) {
|
||||||
|
if (g_fn_len < (int)sizeof g_fn_buf - 1) {
|
||||||
|
n = vsnprintf(g_fn_buf + g_fn_len,
|
||||||
|
sizeof g_fn_buf - g_fn_len, fmt, ap);
|
||||||
|
if (n > 0) g_fn_len += n;
|
||||||
|
}
|
||||||
|
} else if (g_out_len < (int)sizeof g_outbuf - 1) {
|
||||||
|
n = vsnprintf(g_outbuf + g_out_len,
|
||||||
|
sizeof g_outbuf - g_out_len, fmt, ap);
|
||||||
|
if (n > 0) g_out_len += n;
|
||||||
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,6 +455,7 @@ static void proto_emit(const char *fmt, ...)
|
|||||||
/* ---------------- class parsing ---------------- */
|
/* ---------------- class parsing ---------------- */
|
||||||
|
|
||||||
static void gather_decl(char *type, int typesz, char *name, int namesz);
|
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)
|
static void parse_member_decl(const char *cls, const char *ret_type, const char *mname_in)
|
||||||
{
|
{
|
||||||
@@ -555,6 +598,9 @@ static void parse_member_decl(const char *cls, const char *ret_type, const char
|
|||||||
}
|
}
|
||||||
unread_tok(&nxt);
|
unread_tok(&nxt);
|
||||||
}
|
}
|
||||||
|
/* template function call inside a method body */
|
||||||
|
if (tpl_call_check(NULL, NULL, 0))
|
||||||
|
continue;
|
||||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{")) { bd++; proto_emit(" {"); prev_dot = 0; next_tok(); continue; }
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{")) { bd++; proto_emit(" {"); prev_dot = 0; next_tok(); continue; }
|
||||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "}")) { bd--; if (bd > 0) proto_emit("}"); next_tok(); continue; }
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "}")) { bd--; if (bd > 0) proto_emit("}"); next_tok(); continue; }
|
||||||
if (g_tok.type == T_THIS) { proto_emit("this"); prev_dot = 0; next_tok(); continue; }
|
if (g_tok.type == T_THIS) { proto_emit("this"); prev_dot = 0; next_tok(); continue; }
|
||||||
@@ -978,6 +1024,9 @@ static void parse_member_definition(const char *ret_type)
|
|||||||
}
|
}
|
||||||
unread_tok(&nxt);
|
unread_tok(&nxt);
|
||||||
}
|
}
|
||||||
|
/* template function call inside a method body */
|
||||||
|
if (tpl_call_check(NULL, NULL, 0))
|
||||||
|
continue;
|
||||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{")) { depth++; emit(" {"); prev_dot = 0; next_tok(); continue; }
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{")) { depth++; emit(" {"); prev_dot = 0; next_tok(); continue; }
|
||||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "}")) {
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "}")) {
|
||||||
if (depth > 0) { depth--; emit("}"); next_tok(); continue; }
|
if (depth > 0) { depth--; emit("}"); next_tok(); continue; }
|
||||||
@@ -1258,6 +1307,9 @@ static void parse_free_operator(const char *ret_type, const char *name)
|
|||||||
}
|
}
|
||||||
unread_tok(&nxt);
|
unread_tok(&nxt);
|
||||||
}
|
}
|
||||||
|
/* template function call inside an operator body */
|
||||||
|
if (tpl_call_check(NULL, NULL, 0))
|
||||||
|
continue;
|
||||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{")) {
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{")) {
|
||||||
bdepth++;
|
bdepth++;
|
||||||
emit(" {");
|
emit(" {");
|
||||||
@@ -1362,6 +1414,135 @@ static void parse_free_operator(const char *ret_type, const char *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------------- templates ---------------- */
|
||||||
|
|
||||||
|
/* replace standalone identifiers 'from' with 'to' in src */
|
||||||
|
static void tpl_subst(char *dst, int dsz, const char *src,
|
||||||
|
const char *from, const char *to)
|
||||||
|
{
|
||||||
|
int d = 0, i = 0, fl = (int)strlen(from), tl = (int)strlen(to);
|
||||||
|
while (src[i] && d < dsz - 1) {
|
||||||
|
if (!strncmp(src + i, from, fl) &&
|
||||||
|
(i == 0 || !(isalnum((unsigned char)src[i-1]) || src[i-1] == '_')) &&
|
||||||
|
!(isalnum((unsigned char)src[i+fl]) || src[i+fl] == '_')) {
|
||||||
|
if (d + tl < dsz - 1) {
|
||||||
|
memcpy(dst + d, to, tl);
|
||||||
|
d += tl;
|
||||||
|
}
|
||||||
|
i += fl;
|
||||||
|
} else {
|
||||||
|
dst[d++] = src[i++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst[d] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TplFn *find_tplfn(const char *name)
|
||||||
|
{
|
||||||
|
TplFn *p;
|
||||||
|
for (p = g_tplfns; p; p = p->next)
|
||||||
|
if (!strcmp(p->name, name)) return p;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *type_suffix(const char *t)
|
||||||
|
{
|
||||||
|
if (!strcmp(t, "int")) return "i";
|
||||||
|
if (!strcmp(t, "double")) return "d";
|
||||||
|
if (!strcmp(t, "float")) return "f";
|
||||||
|
if (!strcmp(t, "char")) return "c";
|
||||||
|
if (!strcmp(t, "long")) return "l";
|
||||||
|
if (!strcmp(t, "short")) return "s";
|
||||||
|
if (!strcmp(t, "unsigned int")) return "u";
|
||||||
|
return t; /* class name */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* emit (once) the instantiated definition of a template function */
|
||||||
|
static void instantiate_tpl_fn(TplFn *tf, const char *ttype, const char *mname)
|
||||||
|
{
|
||||||
|
TplInst *p;
|
||||||
|
for (p = g_tplinsts; p; p = p->next)
|
||||||
|
if (!strcmp(p->name, mname)) return;
|
||||||
|
p = (TplInst*)calloc(1, sizeof *p);
|
||||||
|
strncpy(p->name, mname, sizeof p->name - 1);
|
||||||
|
p->name[sizeof p->name - 1] = 0;
|
||||||
|
p->next = g_tplinsts;
|
||||||
|
g_tplinsts = p;
|
||||||
|
{
|
||||||
|
char tmp[4096], def[4096];
|
||||||
|
char stype[96];
|
||||||
|
const char *subst_type = ttype;
|
||||||
|
if (find_class(ttype)) {
|
||||||
|
snprintf(stype, sizeof stype, "struct %s", ttype);
|
||||||
|
subst_type = stype;
|
||||||
|
}
|
||||||
|
tpl_subst(tmp, sizeof tmp, tf->body, tf->tparam, subst_type);
|
||||||
|
tpl_subst(def, sizeof def, tmp, tf->name, mname);
|
||||||
|
{
|
||||||
|
int l = (int)strlen(def);
|
||||||
|
if (g_tpl_defs_len + l + 1 < (int)sizeof g_tpl_defs) {
|
||||||
|
memcpy(g_tpl_defs + g_tpl_defs_len, def, l);
|
||||||
|
g_tpl_defs_len += l;
|
||||||
|
g_tpl_defs[g_tpl_defs_len++] = '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If g_tok is a template function name followed by '(', infer the
|
||||||
|
concrete type from the first argument and rewrite g_tok to the
|
||||||
|
mangled instantiation name (the def is queued in g_tpl_defs).
|
||||||
|
Returns 1 if handled. */
|
||||||
|
static int tpl_call_check(char varcls[][128], char varname[][64], int nvars)
|
||||||
|
{
|
||||||
|
TplFn *tf;
|
||||||
|
Token nxt, a1;
|
||||||
|
const char *ttype = "int";
|
||||||
|
char suffix[64];
|
||||||
|
char mname[128];
|
||||||
|
|
||||||
|
if (g_tok.type != T_IDENT) return 0;
|
||||||
|
tf = find_tplfn(g_tok.text);
|
||||||
|
if (!tf) return 0;
|
||||||
|
read_tok(&nxt);
|
||||||
|
if (!(nxt.type == T_PUNCT && !strcmp(nxt.text, "("))) {
|
||||||
|
unread_tok(&nxt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* stream is now at the first argument; read it to infer the type */
|
||||||
|
read_tok(&a1);
|
||||||
|
if (a1.type == T_NUMBER) {
|
||||||
|
if (strchr(a1.text, '.') || strchr(a1.text, 'e') ||
|
||||||
|
strchr(a1.text, 'E') || strchr(a1.text, 'f') ||
|
||||||
|
strchr(a1.text, 'F') || strchr(a1.text, 'l'))
|
||||||
|
ttype = "double";
|
||||||
|
else
|
||||||
|
ttype = "int";
|
||||||
|
} else if (a1.type == T_CHAR) {
|
||||||
|
ttype = "char";
|
||||||
|
} else if (a1.type == T_IDENT && nvars > 0) {
|
||||||
|
int k;
|
||||||
|
ttype = "int";
|
||||||
|
for (k = 0; k < nvars; k++)
|
||||||
|
if (!strcmp(a1.text, varname[k])) {
|
||||||
|
ttype = varcls[k];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* restore the stream: arg back, then '(' back */
|
||||||
|
unread_tok(&a1);
|
||||||
|
unread_tok(&nxt);
|
||||||
|
/* g_tok is still the template name; rewrite it to the mangle */
|
||||||
|
strncpy(suffix, type_suffix(ttype), sizeof suffix - 1);
|
||||||
|
suffix[sizeof suffix - 1] = 0;
|
||||||
|
snprintf(mname, sizeof mname, "%s_%s", tf->name, suffix);
|
||||||
|
instantiate_tpl_fn(tf, ttype, mname);
|
||||||
|
g_tok.type = T_IDENT;
|
||||||
|
strncpy(g_tok.text, mname, sizeof g_tok.text - 1);
|
||||||
|
g_tok.text[sizeof g_tok.text - 1] = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_function(const char *ret_type, const char *name)
|
static void parse_function(const char *ret_type, const char *name)
|
||||||
{
|
{
|
||||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "::")) {
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "::")) {
|
||||||
@@ -1405,6 +1586,9 @@ static void parse_function(const char *ret_type, const char *name)
|
|||||||
}
|
}
|
||||||
unread_tok(&nxt);
|
unread_tok(&nxt);
|
||||||
}
|
}
|
||||||
|
/* template function call: max(a, b) -> max_i(a, b) */
|
||||||
|
if (tpl_call_check(varcls, varname, nvars))
|
||||||
|
continue;
|
||||||
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, "{")) { depth++; emit(" {"); next_tok(); continue; }
|
||||||
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "}")) {
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "}")) {
|
||||||
if (depth > 0) { depth--; emit("}"); next_tok(); continue; }
|
if (depth > 0) { depth--; emit("}"); next_tok(); continue; }
|
||||||
@@ -1499,7 +1683,7 @@ static void parse_function(const char *ret_type, const char *name)
|
|||||||
if (g_tok.type == T_PUNCT &&
|
if (g_tok.type == T_PUNCT &&
|
||||||
!strcmp(g_tok.text, ")")) next_tok();
|
!strcmp(g_tok.text, ")")) next_tok();
|
||||||
}
|
}
|
||||||
continue;
|
goto add_decls;
|
||||||
}
|
}
|
||||||
/* plain declaration: Cls var; -> default ctor */
|
/* plain declaration: Cls var; -> default ctor */
|
||||||
if (g_tok.type == T_PUNCT &&
|
if (g_tok.type == T_PUNCT &&
|
||||||
@@ -1510,16 +1694,53 @@ static void parse_function(const char *ret_type, const char *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* additional declarators: Cls a, b, c; */
|
/* additional declarators: Cls a, b(2), c; */
|
||||||
|
add_decls:
|
||||||
while (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ",")) {
|
while (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ",")) {
|
||||||
emit(", ");
|
|
||||||
next_tok();
|
next_tok();
|
||||||
if (g_tok.type == T_IDENT && nvars < 64) {
|
if (g_tok.type == T_IDENT && nvars < 64) {
|
||||||
|
char vn[64];
|
||||||
strncpy(varcls[nvars], clsname, 127);
|
strncpy(varcls[nvars], clsname, 127);
|
||||||
strncpy(varname[nvars], g_tok.text, 63);
|
strncpy(varname[nvars], g_tok.text, 63);
|
||||||
|
strncpy(vn, g_tok.text, sizeof vn - 1);
|
||||||
|
vn[sizeof vn - 1] = 0;
|
||||||
nvars++;
|
nvars++;
|
||||||
emit(" %s", g_tok.text);
|
|
||||||
next_tok();
|
next_tok();
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "(")) {
|
||||||
|
ClassInfo *cci2 = find_class(clsname);
|
||||||
|
if (cci2 && cci2->has_ctor) {
|
||||||
|
/* declarator with ctor args: a(3), b(7) */
|
||||||
|
emit("; struct %s %s; %s_ctor(&%s",
|
||||||
|
clsname, vn, clsname, vn);
|
||||||
|
next_tok();
|
||||||
|
if (g_tok.type == T_PUNCT &&
|
||||||
|
!strcmp(g_tok.text, ")")) {
|
||||||
|
emit(")");
|
||||||
|
next_tok();
|
||||||
|
} else {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
continue; /* look for more declarators */
|
||||||
|
}
|
||||||
|
emit(", %s(", vn);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
emit(", %s", vn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@@ -1727,6 +1948,100 @@ static void gather_decl(char *type, int typesz, char *name, int namesz)
|
|||||||
/* no name found; caller handles */
|
/* no name found; caller handles */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* skip a declaration up to ';' or a balanced '}' */
|
||||||
|
static void skip_decl(void)
|
||||||
|
{
|
||||||
|
int depth = 0;
|
||||||
|
while (!(g_tok.type == T_EOF)) {
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "{")) depth++;
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "}")) {
|
||||||
|
if (depth == 0) { next_tok(); return; }
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ";") && depth == 0) {
|
||||||
|
next_tok();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
next_tok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* template <class T> function/class */
|
||||||
|
static void parse_template(void)
|
||||||
|
{
|
||||||
|
char tparam[32] = "T";
|
||||||
|
char tybuf[512], nmbuf[256];
|
||||||
|
int multi = 0;
|
||||||
|
|
||||||
|
next_tok(); /* '<' */
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "<")) {
|
||||||
|
next_tok();
|
||||||
|
/* class T | typename T | struct T */
|
||||||
|
if (g_tok.type == T_CLASS || g_tok.type == T_STRUCT ||
|
||||||
|
(g_tok.type == T_IDENT && !strcmp(g_tok.text, "typename")))
|
||||||
|
next_tok();
|
||||||
|
if (g_tok.type == T_IDENT) {
|
||||||
|
strncpy(tparam, g_tok.text, sizeof tparam - 1);
|
||||||
|
tparam[sizeof tparam - 1] = 0;
|
||||||
|
next_tok();
|
||||||
|
}
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ",")) multi = 1;
|
||||||
|
/* skip to '>' */
|
||||||
|
while (!(g_tok.type == T_EOF)) {
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ">")) break;
|
||||||
|
next_tok();
|
||||||
|
}
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ">")) next_tok();
|
||||||
|
} else if (g_tok.type == T_CLASS) {
|
||||||
|
/* template<class T> */
|
||||||
|
next_tok();
|
||||||
|
if (g_tok.type == T_IDENT) {
|
||||||
|
strncpy(tparam, g_tok.text, sizeof tparam - 1);
|
||||||
|
tparam[sizeof tparam - 1] = 0;
|
||||||
|
next_tok();
|
||||||
|
}
|
||||||
|
if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, ">")) next_tok();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multi) {
|
||||||
|
/* multi-parameter templates: not supported, skip declaration */
|
||||||
|
skip_decl();
|
||||||
|
emit("/* skipped multi-param template */\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_tok.type == T_CLASS || g_tok.type == T_STRUCT) {
|
||||||
|
/* template class: not yet supported, skip it cleanly */
|
||||||
|
skip_decl();
|
||||||
|
emit("/* skipped template class */\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* template function */
|
||||||
|
gather_decl(tybuf, sizeof tybuf, nmbuf, sizeof nmbuf);
|
||||||
|
if (nmbuf[0]) {
|
||||||
|
g_capture = 1;
|
||||||
|
g_cap_len = 0;
|
||||||
|
parse_function(tybuf[0] ? tybuf : "int", nmbuf);
|
||||||
|
g_capture = 0;
|
||||||
|
g_cap[g_cap_len] = 0;
|
||||||
|
{
|
||||||
|
TplFn *tf = (TplFn*)calloc(1, sizeof *tf);
|
||||||
|
strncpy(tf->name, nmbuf, sizeof tf->name - 1);
|
||||||
|
tf->name[sizeof tf->name - 1] = 0;
|
||||||
|
strncpy(tf->tparam, tparam, sizeof tf->tparam - 1);
|
||||||
|
tf->tparam[sizeof tf->tparam - 1] = 0;
|
||||||
|
strncpy(tf->body, g_cap, sizeof tf->body - 1);
|
||||||
|
tf->body[sizeof tf->body - 1] = 0;
|
||||||
|
tf->next = g_tplfns;
|
||||||
|
g_tplfns = tf;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
skip_decl();
|
||||||
|
emit("/* skipped unknown template */\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_program(void)
|
static void parse_program(void)
|
||||||
{
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -1811,9 +2126,14 @@ static void parse_program(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_tok.type == T_USING || g_tok.type == T_TEMPLATE ||
|
if (g_tok.type == T_TEMPLATE) {
|
||||||
g_tok.type == T_INLINE || g_tok.type == T_CONSTEXPR ||
|
parse_template();
|
||||||
g_tok.type == T_FRIEND || g_tok.type == T_VIRTUAL) {
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_tok.type == T_USING || g_tok.type == T_INLINE ||
|
||||||
|
g_tok.type == T_CONSTEXPR || g_tok.type == T_FRIEND ||
|
||||||
|
g_tok.type == T_VIRTUAL) {
|
||||||
next_tok();
|
next_tok();
|
||||||
while (!(g_tok.type == T_EOF)) {
|
while (!(g_tok.type == T_EOF)) {
|
||||||
if (g_tok.type == T_PUNCT &&
|
if (g_tok.type == T_PUNCT &&
|
||||||
@@ -1837,13 +2157,19 @@ static void parse_program(void)
|
|||||||
char tybuf[512], nmbuf[256];
|
char tybuf[512], nmbuf[256];
|
||||||
gather_decl(tybuf, sizeof tybuf, nmbuf, sizeof nmbuf);
|
gather_decl(tybuf, sizeof tybuf, nmbuf, sizeof nmbuf);
|
||||||
if (nmbuf[0]) {
|
if (nmbuf[0]) {
|
||||||
|
int was = g_emit_sect;
|
||||||
|
g_emit_sect = 1;
|
||||||
parse_function(tybuf[0] ? tybuf : "int", nmbuf);
|
parse_function(tybuf[0] ? tybuf : "int", nmbuf);
|
||||||
|
g_emit_sect = was;
|
||||||
} else if (g_tok.type == T_EOF) {
|
} else if (g_tok.type == T_EOF) {
|
||||||
break;
|
break;
|
||||||
} else if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "(")) {
|
} else if (g_tok.type == T_PUNCT && !strcmp(g_tok.text, "(")) {
|
||||||
/* function without return type (C style) */
|
/* function without return type (C style) */
|
||||||
|
int was = g_emit_sect;
|
||||||
|
g_emit_sect = 1;
|
||||||
emit("int ");
|
emit("int ");
|
||||||
parse_function("int", "f");
|
parse_function("int", "f");
|
||||||
|
g_emit_sect = was;
|
||||||
} else {
|
} else {
|
||||||
/* global variable: type + rest */
|
/* global variable: type + rest */
|
||||||
if (tybuf[0]) emit("%s", tybuf);
|
if (tybuf[0]) emit("%s", tybuf);
|
||||||
@@ -1883,6 +2209,16 @@ int main(int argc, char **argv)
|
|||||||
next_tok();
|
next_tok();
|
||||||
parse_program();
|
parse_program();
|
||||||
|
|
||||||
|
/* layout: [declarations/classes] [template instantiations]
|
||||||
|
[top-level functions] */
|
||||||
|
fwrite(g_outbuf, 1, g_out_len, g_out);
|
||||||
|
if (g_tpl_defs_len) {
|
||||||
|
fputc('\n', g_out);
|
||||||
|
fwrite(g_tpl_defs, 1, g_tpl_defs_len, g_out);
|
||||||
|
}
|
||||||
|
fputc('\n', g_out);
|
||||||
|
fwrite(g_fn_buf, 1, g_fn_len, g_out);
|
||||||
|
|
||||||
fclose(g_in);
|
fclose(g_in);
|
||||||
if (g_out != stdout) fclose(g_out);
|
if (g_out != stdout) fclose(g_out);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户