3 #define TEMPLATE_COMMA "templ_comma"
4 #define TEMPLATE_PARENTH "templ_parenth"
12 static int nocd
, ncdpt
;
14 static inline void output_templtok (Token i
)
17 OCD
= (Token
*) realloc (OCD
, sizeof (Token
) * (nocd
+= 512));
21 static Template
**tpls
;
26 static void _export_token (Token t
)
29 static bool concatenation
= false;
31 if (t
== FINISH_CMD
) {
32 if (lasttok
) output_itoken (GLOBAL
, lasttok
);
33 } else if (t
== CONCAT_CMD
) {
34 if (concatenation
) return;
37 } else if (!ISSYMBOL (t
) && !ISRESERVED (t
) && !ISVALUE (t
)) {
38 if (lasttok
) output_itoken (GLOBAL
, lasttok
);
39 output_itoken (GLOBAL
, t
);
41 concatenation
= false;
42 } else if (!concatenation
) {
43 if (lasttok
) output_itoken (GLOBAL
, lasttok
);
46 char *tmp
= (char*) alloca (strlen (expand (lasttok
)) + strlen (expand (t
)) + 1);
47 strcat (strcpy (tmp
, expand (lasttok
)), expand (t
));
48 lasttok
= new_symbol (strdup (tmp
));
52 static void export_token (Token t
)
55 if (t
== '>' && !havelev
) {
59 if (t
== '<' && havelev
) {
60 _export_token (CONCAT_CMD
);
71 static void expand_template (Template
*t
, Token
**argv
)
73 NormPtr i
, len
= t
->len
;
74 Token
*BODY
= t
->BODY
;
76 for (i
= 0; i
< len
; i
++)
77 if (ISTPLARG (BODY
[i
])) {
78 Token
*p
= argv
[BODY
[i
] - ARGBASE
];
81 } else export_token (BODY
[i
]);
82 export_token (FINISH_CMD
);
85 static NormPtr
expand_parse_template (NormPtr i
)
87 Template
*t
= tpls
[CODE
[i
++] - IDENTBASE
];
88 Token
**argv
= (Token
**) alloca (t
->argc
* sizeof (Token
*)), *argvv
;
92 if (CODE
[i
++] != '(') parse_error (i
, "template invokation");
93 for (argc
= 0; argc
< t
->argc
; i
++) {
95 while (CODE
[i
] != ',' && CODE
[i
] != ')')
97 argv
[argc
++] = argvv
= (Token
*) alloca ((1 + i
- s
) * sizeof (Token
));
98 intextract (argvv
, &CODE
[s
], i
- s
);
99 for (c
= 0; argvv
[c
] != -1; c
++)
100 if (!tokcmp (argvv
[c
], TEMPLATE_COMMA
))
102 else if (!tokcmp (argvv
[c
], TEMPLATE_PARENTH
))
104 if (CODE
[i
] == ')') break;
106 if (argc
< t
->argc
) parse_error (i
, "too few arguments to template");
107 if (CODE
[i
] != ')') parse_error (i
, "too many arguments to template");
108 expand_template (t
, argv
);
113 static NormPtr
templatedef (NormPtr i
)
116 Token tname
= CODE
[i
++];
118 int argc
= 0, j
, blockno
;
120 if (!ISSYMBOL (tname
)) parse_error (i
, "template name missing");
121 if (tpls
[tname
- IDENTBASE
]) parse_error (i
, "template redefined");
122 if (CODE
[i
++] != '(') parse_error (i
, "template name '('");
124 targ
[argc
] = CODE
[i
++];
125 if (!ISSYMBOL (targ
[argc
])) parse_error (i
, "template argument name");
127 if (CODE
[i
] == ',') continue;
130 if (CODE
[i
++] != ')' || argc
== 0)
131 parse_error (i
, "bad argument list for template");
133 OCD
= (Token
*) malloc ((nocd
= 512) * sizeof (Token
));
136 if (CODE
[i
++] != '{') parse_error (i
, "template '{'");
138 for (blockno
= 1; CODE
[i
] != -1; i
++)
139 if (ISSYMBOL (CODE
[i
])) {
140 for (j
= 0; j
< argc
; j
++)
141 if (CODE
[i
] == targ
[j
]) break;
143 output_templtok (ARGBASE
+ j
);
146 output_templtok (CODE
[i
]);
147 } else if (CODE
[i
] == '{') {
148 output_templtok ('{');
150 } else if (CODE
[i
] == '}') {
151 if (--blockno
== 0) break;
152 output_templtok ('}');
153 } else output_templtok (CODE
[i
]);
155 if (CODE
[i
] == -1) parse_error (i
, "unclosed template definition");
157 Template
*t
= tpls
[tname
- IDENTBASE
] = (Template
*) malloc (sizeof (Template
));
158 t
->BODY
= (Token
*) realloc (OCD
, ncdpt
* sizeof (Token
));
162 adjust_lines (pstart
, pstart
- i
);
171 for (i
= 0; CODE
[i
] != -1; i
++)
172 if (CODE
[i
] == RESERVED_template
173 && CODE
[i
+ 1] != RESERVED_class
&& CODE
[i
+ 1] != RESERVED_struct
)
174 i
= templatedef (i
+ 1);
175 else if (ISSYMBOL (CODE
[i
]) && tpls
[CODE
[i
] - IDENTBASE
])
176 i
= expand_parse_template (i
);
177 else output_itoken (GLOBAL
, CODE
[i
]);
179 output_itoken (GLOBAL
, -1);
186 GLOBAL
= new_stream ();
187 tpls
= (Template
**) alloca (c_nsym
* sizeof (Template
*));
189 for (i
= 0; i
< c_nsym
; i
++)
194 for (i
= 0; i
< c_nsym
; i
++)
196 free (tpls
[i
]->BODY
);
200 CODE
= combine_output (GLOBAL
);