4 * !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
6 * This file is generated automatically by the Parrot build process
7 * from the file compilers/imcc/imcc.l.
9 * Any changes made here will be lost!
13 /* HEADERIZER HFILE: none */
16 #ifndef __STDC_VERSION__
17 # define __STDC_VERSION__ 0
26 * Intermediate Code Compiler for Parrot
28 * Copyright (C) 2002 Melvin Smith <melvin.smith@mindspring.com>
29 * Copyright (C) 2002-2008, The Perl Foundation.
46 typedef struct yyguts_t yyguts_t;
47 typedef struct parser_state_t parser_state_t;
49 typedef struct params_t {
50 char *name[MAX_PARAM];
54 typedef struct macro_t {
60 /* parser state structure
61 * the first few items are common to struct parser_state, but
62 * we AFAIK need this hack as flex doesn't export YY_BUFFER_STATE
64 typedef struct macro_frame_t {
65 struct parser_state_t s;
74 YY_BUFFER_STATE buffer;
77 /* static function declarations */
78 static void pop_parser_state(PARROT_INTERP, ARGMOD(void *yyscanner));
80 static struct macro_frame_t *new_frame(PARROT_INTERP);
82 static void define_macro(PARROT_INTERP, ARGIN(const char *name), ARGIN(const params_t *params),
83 ARGIN(const char *expansion), int start_line);
85 static macro_t *find_macro(PARROT_INTERP, ARGIN(const char *name));
87 static void scan_string(macro_frame_t *frame, ARGIN(const char *expansion),
88 ARGMOD(void *yyscanner));
90 static void scan_file(PARROT_INTERP, ARGIN(struct macro_frame_t *frame), ARGMOD(FILE *file),
91 ARGMOD(void *yyscanner));
93 static int destroy_frame(macro_frame_t *frame, ARGMOD(void *yyscanner));
95 static int yylex_skip(YYSTYPE *valp, PARROT_INTERP, ARGIN(const char *skip),
96 ARGMOD(void *yyscanner));
98 static int read_macro(YYSTYPE *valp, PARROT_INTERP, ARGMOD(void *yyscanner));
100 static int expand_macro(PARROT_INTERP, ARGIN(const char *name), ARGMOD(void *yyscanner));
102 static void include_file(PARROT_INTERP, char *file_name, ARGMOD(void *yyscanner));
104 #define YY_DECL int yylex(YYSTYPE *valp, yyscan_t yyscanner, PARROT_INTERP)
106 #define YYCHOP() (yytext[--yyleng] = '\0')
108 #define DUP_AND_RET(valp, token) \
110 if (valp) (valp)->s = str_dup(yytext); \
114 #define DUP_AND_RET_FREE(valp, token) \
117 mem_sys_free((valp)->s); \
118 (valp)->s = str_dup(yytext); \
126 %option never-interactive
132 HEX 0[xX][0-9A-Fa-f]+
137 BIGINT {SIGN}?{DIGITS}"L"
138 FLOATNUM {SIGN}?(({DIGITS}{DOT}{DIGIT}*|{DOT}{DIGITS})([eE]{SIGN}?{DIGITS})?|{DIGITS}[eE]{SIGN}?{DIGITS})
139 LETTERDIGIT [a-zA-Z0-9_]
140 LABELLETTERDIGIT([a-zA-Z0-9_@]|"::")
141 ID {LETTER}{LABELLETTERDIGIT}*
142 DQ_STRING \"(\\.|[^"\\\n])*\"
143 ENCCHAR {LETTER}|{DIGIT}|"-"
145 ENC {LETTER}{ENCCHARS}":"
146 UNICODE {ENC}{ENC}?{DQ_STRING}
147 STRINGCONSTANT {SQ_STRING}|{DQ_STRING}
148 SQ_STRING \'[^'\n]*\'
168 if (IMCC_INFO(interp)->expect_pasm == 1 && !IMCC_INFO(interp)->in_pod) {
169 IMCC_INFO(interp)->expect_pasm = 2;
173 if (IMCC_INFO(interp)->frames->s.pasm_file && YYSTATE == INITIAL &&
174 !IMCC_INFO(interp)->in_pod)
176 if (IMCC_INFO(interp)->frames->s.pasm_file == 1) {
185 IMCC_INFO(interp)->frames->heredoc_rest = str_dup(yytext);
190 /* heredocs have highest priority
191 * arrange them befor all wildcard state matches
194 /* Newline in the heredoc. Realloc and cat on. */
195 IMCC_INFO(interp)->line++;
196 IMCC_INFO(interp)->heredoc_content =
197 (char*)mem_sys_realloc(IMCC_INFO(interp)->heredoc_content,
198 strlen(IMCC_INFO(interp)->heredoc_content) +
200 strcpy(IMCC_INFO(interp)->heredoc_content +
201 strlen(IMCC_INFO(interp)->heredoc_content), yytext);
205 /* Are we at the end of the heredoc? */
206 if (STREQ(IMCC_INFO(interp)->heredoc_end, yytext)) {
207 /* End of the heredoc. */
208 yyguts_t * const yyg = (yyguts_t *)yyscanner;
209 const int len = strlen(IMCC_INFO(interp)->heredoc_content);
212 IMCC_INFO(interp)->heredoc_content[len] =
213 IMCC_INFO(interp)->heredoc_content[0];
215 IMCC_INFO(interp)->heredoc_content[len + 1] = 0;
217 mem_sys_free(IMCC_INFO(interp)->heredoc_end);
218 IMCC_INFO(interp)->heredoc_end = NULL;
220 IMCC_INFO(interp)->frames->buffer = YY_CURRENT_BUFFER;
222 IMCC_INFO(interp)->heredoc_content;
224 yy_pop_state(yyscanner);
225 yy_scan_string(IMCC_INFO(interp)->frames->heredoc_rest, yyscanner);
227 /* RT #42382 delete quotes, -> emit, pbc */
231 /* Part of the heredoc. Realloc and cat the line on. */
232 IMCC_INFO(interp)->heredoc_content =
233 (char *)mem_sys_realloc(IMCC_INFO(interp)->heredoc_content,
234 strlen(IMCC_INFO(interp)->heredoc_content) +
236 strcpy(IMCC_INFO(interp)->heredoc_content +
237 strlen(IMCC_INFO(interp)->heredoc_content), yytext);
242 <*>^"#line"{SP}{DIGITS}{SP}["] {
243 yy_push_state(cmt2, yyscanner);
244 IMCC_INFO(interp)->line = atoi(yytext+6);
249 yy_pop_state(yyscanner);
250 yy_push_state(cmt3, yyscanner);
252 IMCC_INFO(interp)->frames->s.file = str_dup(yytext);
253 IMCC_INFO(interp)->cur_unit->file = str_dup(yytext);
259 yy_pop_state(yyscanner);
260 yy_push_state(cmt4, yyscanner);
263 <*>setfile{SP}+["] { yy_push_state(cmt2, yyscanner); }
265 <*>setline{SP}+ { yy_push_state(cmt1, yyscanner); }
268 IMCC_INFO(interp)->line = atoi(yytext);
269 yy_pop_state(yyscanner);
270 yy_push_state(cmt4, yyscanner);
275 yy_pop_state(yyscanner);
276 IMCC_INFO(interp)->line++;
279 <INITIAL,emit>{EOL} {
280 if (IMCC_INFO(interp)->expect_pasm == 2)
283 IMCC_INFO(interp)->expect_pasm = 0;
284 IMCC_INFO(interp)->line++;
290 yy_push_state(cmt5, yyscanner);
294 if (IMCC_INFO(interp)->expect_pasm == 2)
297 yy_pop_state(yyscanner);
299 IMCC_INFO(interp)->expect_pasm = 0;
300 IMCC_INFO(interp)->line++;
306 <*>[ISNP]{DIGIT}{DIGIT}? {
307 valp->s = str_dup(yytext);
311 <INITIAL,emit,macro>^"=" {
312 IMCC_INFO(interp)->in_pod = 1;
313 yy_push_state(pod, yyscanner);
317 IMCC_INFO(interp)->in_pod = 0;
318 yy_pop_state(yyscanner);
319 IMCC_INFO(interp)->line++;
322 <pod>.* { /*ignore*/ }
324 <pod>{EOL} { IMCC_INFO(interp)->line++; }
326 <INITIAL,emit>".lex" return LEXICAL;
330 ".begin_call" return PCC_BEGIN;
331 ".end_call" return PCC_END;
332 ".call" return PCC_CALL;
333 ".nci_call" return NCI_CALL;
334 ".meth_call" return METH_CALL;
335 ".invocant" return INVOCANT;
336 <emit,INITIAL>".pcc_sub" return PCC_SUB;
337 ".begin_return" return PCC_BEGIN_RETURN;
338 ".end_return" return PCC_END_RETURN;
339 ".begin_yield" return PCC_BEGIN_YIELD;
340 ".end_yield" return PCC_END_YIELD;
342 <emit,INITIAL>":method" return METHOD;
343 <emit,INITIAL>":multi" return MULTI;
344 <emit,INITIAL>":main" return MAIN;
345 <emit,INITIAL>":load" return LOAD;
346 <emit,INITIAL>":init" return INIT;
347 <emit,INITIAL>":immediate" return IMMEDIATE;
348 <emit,INITIAL>":postcomp" return POSTCOMP;
349 <emit,INITIAL>":anon" return ANON;
350 <emit,INITIAL>":outer" return OUTER;
351 <emit,INITIAL>":lex" return NEED_LEX;
352 <emit,INITIAL>":vtable" return VTABLE_METHOD;
353 ":unique_reg" return UNIQUE_REG;
354 ":instanceof" return SUB_INSTANCE_OF;
355 ":lexid" return SUB_LEXID;
357 ".result" return RESULT;
358 ".get_results" return GET_RESULTS;
359 ".yield" return YIELDT;
360 ".return" return RETURN;
361 <emit,INITIAL>".loadlib" return LOADLIB;
363 ":flat" return ADV_FLAT;
364 ":slurpy" return ADV_SLURPY;
365 ":optional" return ADV_OPTIONAL;
366 ":opt_flag" return ADV_OPT_FLAG;
367 ":named" return ADV_NAMED;
368 "=>" return ADV_ARROW;
369 ":invocant" return ADV_INVOCANT;
371 <emit,INITIAL>".namespace" return NAMESPACE;
372 <emit,INITIAL>".HLL" return HLL;
373 <emit,INITIAL>".HLL_map" return HLL_MAP;
374 ".endnamespace" return ENDNAMESPACE;
375 ".local" return LOCAL;
376 ".global" return GLOBAL;
377 <emit,INITIAL>".const" return CONST;
378 ".globalconst" return GLOBAL_CONST;
379 ".param" return PARAM;
380 <*>".pragma" return PRAGMA;
381 <*>"n_operators" return N_OPERATORS;
384 "unless" return UNLESS;
390 "global" return GLOBALOP;
392 "string" return STRINGV;
393 "<<" return SHIFT_LEFT;
394 ">>" return SHIFT_RIGHT;
395 ">>>" return SHIFT_RIGHT_U;
400 "<=" return RELOP_LTE;
402 ">=" return RELOP_GTE;
403 "==" return RELOP_EQ;
404 "!=" return RELOP_NE;
407 {WS}+"."{WS}+ return CONCAT;
409 <emit,INITIAL>".." return DOTDOT;
410 "+=" return PLUS_ASSIGN;
411 "-=" return MINUS_ASSIGN;
412 "*=" return MUL_ASSIGN;
413 "/=" return DIV_ASSIGN;
414 "%=" return MOD_ASSIGN;
416 "//=" return FDIV_ASSIGN;
417 "&=" return BAND_ASSIGN;
418 "|=" return BOR_ASSIGN;
419 "~=" return BXOR_ASSIGN;
420 ">>=" return SHR_ASSIGN;
421 "<<=" return SHL_ASSIGN;
422 ">>>=" return SHR_U_ASSIGN;
423 ".=" return CONCAT_ASSIGN;
425 <emit,INITIAL>".macro_const" {
428 int start_cond = YY_START;
431 c = yylex_skip(valp, interp, " ", yyscanner);
434 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
435 "Constant names must be identifiers");
437 IMCC_INFO(interp)->cur_macro_name = valp->s;
438 start_line = IMCC_INFO(interp)->line;
440 c = yylex_skip(valp, interp, " ", yyscanner);
442 if (c != INTC && c != FLOATC && c != STRINGC && c != REG)
443 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
444 "Constant '%s' value must be a number, "
445 "stringliteral or register", IMCC_INFO(interp)->cur_macro_name);
447 define_macro(interp, IMCC_INFO(interp)->cur_macro_name, NULL, valp->s, start_line);
449 IMCC_INFO(interp)->cur_macro_name = NULL;
455 <emit,INITIAL>".macro" {
456 return read_macro(valp, interp, yyscanner);
459 <emit,INITIAL>".include" {
460 const int c = yylex(valp, yyscanner, interp);
465 include_file(interp, yytext + 1, yyscanner);
468 <emit,INITIAL>{ID}"$:" {
476 if (!IMCC_INFO(interp)->frames || !IMCC_INFO(interp)->frames->label)
477 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR, "missing space?");
480 label = (char *)mem_sys_allocate(len);
481 snprintf(label, len, "%s%d", yytext, IMCC_INFO(interp)->frames->label);
483 /* XXX: free valp->s if it exists? */
490 <emit,INITIAL>{ID}"$" {
497 /* RT #32421 if$I0 is parsed as if$ I0 */
498 if (!IMCC_INFO(interp)->frames || !IMCC_INFO(interp)->frames->label)
499 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR, "missing space?");
502 label = (char *)mem_sys_allocate(len);
503 snprintf(label, len, "%s%d", yytext, IMCC_INFO(interp)->frames->label);
505 /* XXX: free valp->s if it exists? */
512 <emit,INITIAL>"," return COMMA;
514 <emit,INITIAL>{ID}":" {
524 <emit,INITIAL>{DOT}{LETTER}{LETTERDIGIT}* {
525 char * const macro_name = yytext + 1;
526 STRING * name_string = string_from_cstring(interp, macro_name, 0);
527 const int type = pmc_type(interp, name_string);
530 const size_t len = 16;
531 char * const buf = (char *)mem_sys_allocate(len);
532 snprintf(buf, len, "%d", type);
534 /* XXX: free valp->s if already used? Sounds like a good idea, */
535 /* but big segfaults if you do. */
540 if (!expand_macro(interp, macro_name, yyscanner)) {
548 SymReg *r = find_sym(interp, yytext);
550 if (r && (r->type & (VTIDENTIFIER|VT_CONSTP))) {
555 if (IMCC_INFO(interp)->cur_unit
556 && IMCC_INFO(interp)->cur_unit->instructions
557 && (r = IMCC_INFO(interp)->cur_unit->instructions->symregs[0])
560 if (((r->pcc_sub->pragma & P_METHOD)
561 || (IMCC_INFO(interp)->cur_unit->is_vtable_method))
562 && !strcmp(yytext, "self")) {
563 valp->sr = mk_ident(interp, "self", 'P');
564 IMCC_INFO(interp)->cur_unit->type |= IMC_HAS_SELF;
570 valp->s = str_dup(yytext);
571 return (!is_def && is_op(interp, valp->s) ? PARROT_OP : IDENTIFIER);
574 <*>{FLOATNUM} DUP_AND_RET(valp, FLOATC);
575 <*>{SIGN}?{DIGIT}+ DUP_AND_RET(valp, INTC);
576 <*>{HEX} DUP_AND_RET(valp, INTC);
577 <*>{BIN} DUP_AND_RET(valp, INTC);
578 <*>{OCT} DUP_AND_RET(valp, INTC);
581 valp->s = str_dup(yytext);
584 valp->s[strlen(valp->s) - 1] = '\0';
586 /* no BIGINT native format yet */
590 <*>{STRINGCONSTANT} {
591 valp->s = str_dup(yytext);
593 /* RT #42382 delete quotes, -> emit, pbc */
597 <*>"<<"{STRINGCONSTANT} {
598 macro_frame_t *frame;
600 /* Save the string we want to mark the end of the heredoc and snip
601 off newline and quote. */
602 if (IMCC_INFO(interp)->frames->heredoc_rest)
603 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR, "nested heredoc not supported");
604 IMCC_INFO(interp)->heredoc_end = str_dup(yytext + 3);
605 IMCC_INFO(interp)->heredoc_end[strlen(IMCC_INFO(interp)->heredoc_end) - 1] = 0;
607 if (!strlen(IMCC_INFO(interp)->heredoc_end))
608 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR, "empty heredoc delimiter");
610 frame = new_frame(interp);
611 frame->s.next = (parser_state_t *)IMCC_INFO(interp)->frames;
612 IMCC_INFO(interp)->frames = frame;
614 /* Start slurping up the heredoc. */
615 IMCC_INFO(interp)->heredoc_content = (char *)mem_sys_allocate(2);
618 IMCC_INFO(interp)->heredoc_content[0] = yytext[2];
621 IMCC_INFO(interp)->heredoc_content[1] = 0;
622 yy_push_state(heredoc1, yyscanner);
627 valp->s = str_dup(yytext);
629 /* this is actually not unicode but a string with a charset */
633 <emit,INITIAL>\$I[0-9]+ {
634 if (valp) (valp)->s = yytext;
635 if (IMCC_INFO(interp)->state->pasm_file)
636 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
637 "'%s' is not a valid register name in pasm mode", yytext);
641 <emit,INITIAL>\$N[0-9]+ {
642 if (valp) (valp)->s = yytext;
643 if (IMCC_INFO(interp)->state->pasm_file)
644 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
645 "'%s' is not a valid register name in pasm mode", yytext);
649 <emit,INITIAL>\$S[0-9]+ {
650 if (valp) (valp)->s = yytext;
651 if (IMCC_INFO(interp)->state->pasm_file)
652 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
653 "'%s' is not a valid register name in pasm mode", yytext);
657 <emit,INITIAL>\$P[0-9]+ {
658 if (valp) (valp)->s = yytext;
659 if (IMCC_INFO(interp)->state->pasm_file)
660 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
661 "'%s' is not a valid register name in pasm mode", yytext);
665 <emit,INITIAL>\$[a-zA-Z0-9]+ {
666 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
667 "'%s' is not a valid register name", yytext);
671 <emit,INITIAL>{WS}+ /* skip */;
673 <emit,cmt1,cmt2,cmt3,cmt4,cmt5,INITIAL>. {
674 /* catch all except for state macro */
681 if (IMCC_INFO(interp)->frames->s.pasm_file) {
682 IMCC_INFO(interp)->frames->s.pasm_file = 2;
689 <INITIAL><<EOF>> yyterminate();
691 <macro>".endm" DUP_AND_RET(valp, ENDM);
694 IMCC_INFO(interp)->line++;
695 DUP_AND_RET(valp, '\n');
698 <macro>"$"{ID}":" return LABEL;
700 <macro>".label"{WS}+ {
702 if (yylex(valp, yyscanner, interp) != LABEL)
703 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR, "LABEL expected");
710 len = strlen(IMCC_INFO(interp)->cur_macro_name) + yyleng + 15;
711 label = (char *)mem_sys_allocate(len);
713 snprintf(label, len, "local__%s__%s__$:",
714 IMCC_INFO(interp)->cur_macro_name, yytext+1);
716 /* XXX: free valp->s if it exists? */
725 const size_t len = strlen(IMCC_INFO(interp)->cur_macro_name) + yyleng + 12;
726 char * const label = (char *)mem_sys_allocate(len);
728 snprintf(label, len, "local__%s__%s__$",
729 IMCC_INFO(interp)->cur_macro_name, yytext+2);
737 <macro>^{WS}+ /* skip leading ws */;
738 <macro>{WS}+ DUP_AND_RET(valp, ' ');
739 <macro>{ID} DUP_AND_RET(valp, IDENTIFIER);
740 <macro>{DOT}{ID} DUP_AND_RET(valp, MACRO);
741 <macro>. DUP_AND_RET(valp, yytext[0]);
742 <macro><<EOF>> yyterminate();
750 int yywrap(void* yyscanner) {
751 /* Add code here to open next source file and start scanning
752 * yywrap returns 0 if scanning is to continue */
753 Interp * const interp = yyget_extra(yyscanner);
754 yyguts_t * const yyg = (yyguts_t *)yyscanner;
757 fprintf(stderr, "Argh, interp not found\n");
761 yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner);
764 if (IMCC_INFO(interp)->frames->s.next) {
765 pop_parser_state(IMCC_INFO(interp)->frames->s.interp, yyscanner);
766 if (YYSTATE == INITIAL || YYSTATE == emit)
767 BEGIN(IMCC_INFO(interp)->frames->s.pasm_file ? emit : INITIAL);
774 static macro_frame_t *
775 new_frame(PARROT_INTERP) {
776 static int label = 0;
777 macro_frame_t * const tmp = mem_allocate_zeroed_typed(macro_frame_t);
779 tmp->label = ++label;
780 tmp->s.line = IMCC_INFO(interp)->line;
781 tmp->s.handle = NULL;
783 if (IMCC_INFO(interp)->frames) {
784 tmp->s.pasm_file = IMCC_INFO(interp)->frames->s.pasm_file;
785 tmp->s.file = IMCC_INFO(interp)->frames->s.file;
786 tmp->s.pragmas = IMCC_INFO(interp)->frames->s.pragmas;
789 tmp->s.interp = interp;
795 scan_string(macro_frame_t *frame, ARGIN(const char *expansion), void *yyscanner)
797 yyguts_t * const yyg = (yyguts_t *)yyscanner;
798 Interp * const interp = yyget_extra(yyscanner);
800 frame->buffer = YY_CURRENT_BUFFER;
801 frame->s.next = (parser_state_t *)IMCC_INFO(interp)->frames;
802 IMCC_INFO(interp)->frames = frame;
804 yy_scan_string(expansion, yyscanner);
808 destroy_frame(struct macro_frame_t *frame, void *yyscanner)
810 YY_BUFFER_STATE buffer = frame->buffer;
815 for (i = 0; i < frame->expansion.num_param; i++) {
816 mem_sys_free(frame->expansion.name[i]);
817 frame->expansion.name[i] = NULL;
820 if (frame->heredoc_rest) {
821 mem_sys_free(frame->heredoc_rest);
822 frame->heredoc_rest = NULL;
826 /* RT #42383 if frame->s.file was allocated free it */
830 yy_switch_to_buffer(buffer, yyscanner);
836 yylex_skip(YYSTYPE *valp, PARROT_INTERP, const char *skip, void *yyscanner)
840 yyguts_t * const yyg = (yyguts_t *)yyscanner;
843 c = yylex(valp, yyscanner, interp);
846 while (*p && c != *p)
849 } while (*p != '\0');
852 DUP_AND_RET_FREE(valp, c);
858 read_braced(YYSTYPE *valp, PARROT_INTERP, const char *macro_name,
859 char *current, void *yyscanner)
862 size_t len = strlen(current);
863 int c = yylex(&val, yyscanner, interp);
866 while (c != '}' || count > 0) {
874 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
875 "End of file reached while reading arguments in '%s'",
878 len += strlen(val.s);
879 current = (char *)realloc(current, len + 1);
880 strcat(current,val.s);
884 c = yylex(&val, yyscanner, interp);
896 read_params(YYSTYPE *valp, PARROT_INTERP, params_t *params,
897 ARGIN(const char *macro_name), int need_id, void *yyscanner)
901 char *current = str_dup("");
902 yyguts_t *yyg = (yyguts_t *)yyscanner;
903 int c = yylex_skip(&val, interp, " \n", yyscanner);
905 params->num_param = 0;
907 /* See http://rt.perl.org/rt3/Ticket/Display.html?id=50920 for the saga of this bug. */
908 /* For some reason, we have to use a dupe of the macro name to pass in to */
909 /* read_params, or we get a segfault. XXX Make it stop. */
910 macro_name = str_dup(macro_name);
913 if (YYSTATE == heredoc2)
914 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
915 "Heredoc in macro '%s' not allowed", macro_name);
918 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
919 "End of file reached while reading arguments in '%s'",
922 if (params->num_param == MAX_PARAM)
923 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
924 "More than %d params in '%s'",
925 MAX_PARAM, macro_name);
927 params->name[params->num_param++] = current;
928 current = str_dup("");
931 c = yylex_skip(&val, interp, " \n", yyscanner);
933 else if (need_id && (*current || c != IDENTIFIER) && c != ' ') {
934 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
935 "Parameter definition in '%s' must be IDENTIFIER",
939 current = read_braced(&val, interp, macro_name, current, yyscanner);
940 c = yylex_skip(&val, interp, " \n", yyscanner);
941 len = strlen(current);
944 if (!need_id || c != ' ') {
945 len += strlen(val.s);
946 current = (char *)realloc(current, len + 1);
947 strcat(current, val.s);
952 c = yylex(&val, yyscanner, interp);
956 params->name[params->num_param++] = current;
967 read_macro(YYSTYPE *valp, PARROT_INTERP, void *yyscanner)
971 yyguts_t * const yyg = (yyguts_t *)yyscanner;
972 int start_cond = YY_START;
978 c = yylex_skip(valp, interp, " ", yyscanner);
981 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR, "Macro names must be identifiers");
983 IMCC_INFO(interp)->cur_macro_name = valp->s;
984 start_line = IMCC_INFO(interp)->line++;
986 memset(¶ms, 0, sizeof (params_t));
988 /* white space is allowed between macro and opening paren) */
989 c = yylex_skip(valp, interp, " ", yyscanner);
992 mem_sys_free(valp->s);
995 c = read_params(NULL, interp, ¶ms,
996 IMCC_INFO(interp)->cur_macro_name, 1, yyscanner);
998 c = yylex(valp, yyscanner, interp);
1005 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
1006 "File ended before macro '%s' was complete",
1007 IMCC_INFO(interp)->cur_macro_name);
1009 PARROT_ASSERT(valp->s);
1010 elem_len = strlen(valp->s);
1013 if (buffer_used + elem_len > buffer_size) {
1014 buffer_size += elem_len;
1017 IMCC_INFO(interp)->macro_buffer =
1018 (char *)mem_sys_realloc(IMCC_INFO(interp)->macro_buffer,
1023 buffer_size = (elem_len << 1) > 1024 ? elem_len << 1 : 1024;
1025 IMCC_INFO(interp)->macro_buffer =
1026 (char *)mem_sys_allocate_zeroed(buffer_size);
1028 strcat(IMCC_INFO(interp)->macro_buffer, valp->s);
1029 buffer_used += elem_len;
1030 mem_sys_free(valp->s);
1033 c = yylex(valp, yyscanner, interp);
1036 mem_sys_free(valp->s);
1041 define_macro(interp, IMCC_INFO(interp)->cur_macro_name,
1042 ¶ms, IMCC_INFO(interp)->macro_buffer, start_line);
1044 mem_sys_free(IMCC_INFO(interp)->macro_buffer);
1045 IMCC_INFO(interp)->macro_buffer = NULL;
1046 IMCC_INFO(interp)->cur_macro_name = NULL;
1052 find_macro_param(PARROT_INTERP, const char *name)
1056 for (f = IMCC_INFO(interp)->frames; f; f = (macro_frame_t *)f->s.next) {
1059 for (i = 0; i < f->params->num_param; i++) {
1060 if (STREQ(f->params->name[i], name))
1061 return f->expansion.name[i];
1070 define_macro(PARROT_INTERP, ARGIN(const char *name), ARGIN(const params_t *params),
1071 ARGIN(const char *expansion), int start_line)
1073 macro_t *m = find_macro(interp, name);
1076 mem_sys_free(m->expansion);
1077 m->expansion = NULL;
1080 m = mem_allocate_zeroed_typed(macro_t);
1082 if (!IMCC_INFO(interp)->macros)
1083 parrot_new_cstring_hash(interp, &IMCC_INFO(interp)->macros);
1084 parrot_hash_put(interp, IMCC_INFO(interp)->macros, str_dup(name), m);
1088 m->params = *params;
1090 memset(&m->params, 0, sizeof (params_t));
1092 m->expansion = str_dup(expansion);
1093 m->line = start_line;
1097 find_macro(PARROT_INTERP, const char *name)
1099 if (!IMCC_INFO(interp)->macros)
1102 return (macro_t *)parrot_hash_get(interp, IMCC_INFO(interp)->macros, name);
1106 expand_macro(PARROT_INTERP, ARGIN(const char *name), void *yyscanner)
1108 yyguts_t * const yyg = (yyguts_t *)yyscanner;
1109 const char * const expansion = find_macro_param(interp, name);
1113 macro_frame_t * const frame = new_frame(interp);
1115 /* When an error occurs, then report it as being in a macro */
1116 frame->is_macro = 1;
1117 scan_string(frame, expansion, yyscanner);
1121 m = find_macro(interp, name);
1125 macro_frame_t * const frame = new_frame(interp);
1126 frame->params = &m->params;
1128 /* When an error occurs, then report it as being in a macro */
1129 frame->is_macro = 1;
1131 /* remember macro name for error reporting
1132 RT #42384 check that all the .file text is malloced / freed */
1133 frame->s.file = str_dup(name);
1135 /* whitespace can be safely ignored */
1138 c = yyinput(yyscanner);
1140 c = input(yyscanner);
1142 } while (c == ' ' || c == '\t');
1145 if (m->params.num_param != 0)
1146 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
1147 "Macro '%s' needs %d arguments",
1148 name, m->params.num_param);
1150 scan_string(frame, m->expansion, yyscanner);
1154 start_cond = YY_START;
1157 read_params(NULL, interp, &frame->expansion, name, 0, yyscanner);
1161 if (frame->expansion.num_param == 0 && m->params.num_param == 1) {
1162 frame->expansion.name[0] = str_dup("");
1163 frame->expansion.num_param = 1;
1166 if (frame->expansion.num_param != m->params.num_param) {
1167 IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
1168 "Macro '%s' requires %d arguments, but %d given",
1169 name, m->params.num_param, frame->expansion.num_param);
1172 /* expand arguments */
1173 for (i = 0; i < frame->expansion.num_param; i++) {
1174 char * const current = frame->expansion.name[i];
1176 /* parameter of outer macro */
1177 if (current[0] == '.') {
1178 const char * const s = find_macro_param(interp, current + 1);
1181 frame->expansion.name[i] = str_dup(s);
1182 mem_sys_free(current);
1187 const size_t len = strlen(current);
1188 if (len && (current[len - 1] == '$')) { /* local label */
1189 const size_t slen = len + 10;
1190 char * const s = (char *)mem_sys_allocate(slen);
1192 current[len - 1] = '\0';
1194 snprintf(s, slen, "%s%d", current, IMCC_INFO(interp)->frames->label);
1196 frame->expansion.name[i] = s;
1197 mem_sys_free(current);
1202 IMCC_INFO(interp)->line = m->line;
1203 scan_string(frame, m->expansion, yyscanner);
1211 include_file(PARROT_INTERP, char *file_name, void *yyscanner)
1213 yyguts_t * const yyg = (yyguts_t *)yyscanner;
1214 macro_frame_t * const frame = new_frame(interp);
1215 char *s = Parrot_locate_runtime_file(interp, file_name,
1216 PARROT_RUNTIME_FT_INCLUDE);
1220 if (!s || !(file = fopen(s, "r")))
1221 IMCC_fataly(interp, EXCEPTION_EXTERNAL_ERROR, strerror(errno));
1224 frame->s.file = file_name;
1225 frame->s.handle = file;
1226 ext = strrchr(file_name, '.');
1229 if (STREQ(ext, ".pasm")) {
1230 frame->s.pasm_file = 1;
1233 else if (STREQ(ext, ".pir")) {
1234 frame->s.pasm_file = 0;
1239 scan_file(interp, frame, file, yyscanner);
1243 scan_file(PARROT_INTERP, macro_frame_t *frame, FILE *file, void *yyscanner)
1245 yyguts_t * const yyg = (yyguts_t *)yyscanner;
1246 frame->buffer = YY_CURRENT_BUFFER;
1247 frame->s.next = (parser_state_t *)IMCC_INFO(interp)->frames;
1248 IMCC_INFO(interp)->frames = frame;
1249 IMCC_INFO(interp)->state = (parser_state_t *)IMCC_INFO(interp)->frames;
1251 IMCC_INFO(interp)->line = 1;
1253 yy_switch_to_buffer(yy_create_buffer(file, YY_BUF_SIZE, yyscanner),
1258 IMCC_push_parser_state(PARROT_INTERP)
1260 macro_frame_t * const frame = new_frame(interp);
1261 frame->s.next = (parser_state_t *)IMCC_INFO(interp)->frames;
1262 IMCC_INFO(interp)->frames = frame;
1263 frame->s.line = IMCC_INFO(interp)->line
1265 IMCC_INFO(interp)->state = (parser_state_t *)IMCC_INFO(interp)->frames;
1269 pop_parser_state(PARROT_INTERP, void *yyscanner)
1271 macro_frame_t * const tmp = IMCC_INFO(interp)->frames;
1275 fclose(tmp->s.handle);
1277 IMCC_INFO(interp)->frames =
1278 (macro_frame_t *)IMCC_INFO(interp)->frames->s.next;
1280 l = destroy_frame(tmp, yyscanner);
1283 IMCC_INFO(interp)->line = l;
1286 IMCC_INFO(interp)->state = (parser_state_t *)IMCC_INFO(interp)->frames;
1290 IMCC_pop_parser_state(PARROT_INTERP, void *yyscanner)
1292 pop_parser_state(interp, yyscanner);
1296 compile_file(PARROT_INTERP, FILE *file, void *yyscanner)
1298 yyguts_t * const yyg = (yyguts_t *)yyscanner;
1299 YY_BUFFER_STATE buffer;
1301 IMCC_INFO(interp)->frames->s.next = NULL;
1302 buffer = YY_CURRENT_BUFFER;
1304 yy_switch_to_buffer(yy_create_buffer(file, YY_BUF_SIZE, yyscanner),
1307 emit_open(interp, 1, NULL);
1309 IMCC_TRY(IMCC_INFO(interp)->jump_buf, IMCC_INFO(interp)->error_code) {
1310 yyparse(yyscanner, interp);
1311 imc_compile_all_units(interp);
1314 IMCC_CATCH(IMCC_FATAL_EXCEPTION) {
1315 IMCC_INFO(interp)->error_code = IMCC_FATAL_EXCEPTION;
1318 IMCC_CATCH(IMCC_FATALY_EXCEPTION) {
1319 IMCC_INFO(interp)->error_code = IMCC_FATALY_EXCEPTION;
1325 yy_switch_to_buffer(buffer, yyscanner);
1329 compile_string(PARROT_INTERP, const char *s, void *yyscanner)
1331 yyguts_t * const yyg = (yyguts_t *)yyscanner;
1332 YY_BUFFER_STATE buffer;
1334 IMCC_INFO(interp)->frames->s.next = NULL;
1335 buffer = YY_CURRENT_BUFFER;
1337 yy_scan_string(s, yyscanner);
1338 emit_open(interp, 1, NULL);
1340 IMCC_TRY(IMCC_INFO(interp)->jump_buf, IMCC_INFO(interp)->error_code) {
1341 yyparse(yyscanner, interp);
1342 imc_compile_all_units(interp);
1345 IMCC_CATCH(IMCC_FATAL_EXCEPTION) {
1346 IMCC_INFO(interp)->error_code = IMCC_FATAL_EXCEPTION;
1349 IMCC_CATCH(IMCC_FATALY_EXCEPTION) {
1350 IMCC_INFO(interp)->error_code = IMCC_FATALY_EXCEPTION;
1356 yy_switch_to_buffer(buffer, yyscanner);
1360 IMCC_print_inc(PARROT_INTERP)
1363 const char *old = IMCC_INFO(interp)->frames->s.file;
1365 if (IMCC_INFO(interp)->frames && IMCC_INFO(interp)->frames->is_macro)
1366 fprintf(stderr, "\n\tin macro '.%s' line %d\n",
1367 IMCC_INFO(interp)->frames->s.file, IMCC_INFO(interp)->line);
1369 fprintf(stderr, "\n\tin file '%s' line %d\n",
1370 IMCC_INFO(interp)->frames->s.file, IMCC_INFO(interp)->line);
1373 for (f = IMCC_INFO(interp)->frames; f; f = (macro_frame_t *)f->s.next) {
1374 if (!STREQ(f->s.file, old)) {
1375 fprintf(stderr, "\tincluded from '%s' line %d\n",
1376 f->s.file, f->s.line);
1383 /* Functions to set and get yyin, as we can't decorate it for export
1384 (since it is defined in a file generated by yacc/bison). */
1385 FILE* imc_yyin_set(FILE* new_yyin, void *yyscanner)
1387 yyguts_t * const yyg = (yyguts_t *)yyscanner;
1388 yyg->yyin_r = new_yyin;
1393 FILE* imc_yyin_get(void *yyscanner)
1395 const yyguts_t * const yyg = (yyguts_t *)yyscanner;
1399 /* return true if scanner is at EOF */
1400 int at_eof(yyscan_t yyscanner)
1402 yyguts_t * const yyg = (yyguts_t *)yyscanner;
1403 return yyg->yy_hold_char == '\0';
1408 * c-file-style: "parrot"
1410 * vim: expandtab shiftwidth=4: