Home  |  Linux  | Mysql  | PHP  | XML
Deprecated: Function ereg() is deprecated in /rscs/rs/websites/lmpx.com/code/nav/common.inc on line 99
Deprecated: Function ereg() is deprecated in /rscs/rs/websites/lmpx.com/code/nav/common.inc on line 82
From:kjs@cvs.perl.org Date:Sun Oct 12 13:03:09 2008
Subject:[svn:parrot] r31896 - trunk/compilers/pirc/heredoc
Author: kjs
Date: Sun Oct 12 06:03:07 2008
New Revision: 31896

Modified:
trunk/compilers/pirc/heredoc/hdocprep.c
trunk/compilers/pirc/heredoc/hdocprep.l

Log:
[pirc/heredoc] rewritten the heredoc preprocessor. Works well on cygwin and windows. Need test on Mac and linux.

Modified: trunk/compilers/pirc/heredoc/hdocprep.c
==============================================================================
--- trunk/compilers/pirc/heredoc/hdocprep.c (original)
+++ trunk/compilers/pirc/heredoc/hdocprep.c Sun Oct 12 06:03:07 2008
@@ -453,22 +453,21 @@
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[125] =
+static yyconst flex_int16_t yy_accept[118] =
{ 0,
- 0, 0, 0, 0, 12, 12, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 21, 14, 13, 14,
- 14, 14, 14, 14, 20, 4, 20, 20, 20, 12,
- 11, 12, 12, 20, 19, 20, 20, 20, 9, 20,
- 20, 20, 10, 20, 20, 6, 5, 6, 6, 6,
- 16, 18, 16, 20, 20, 13, 0, 13, 0, 1,
- 0, 0, 0, 0, 2, 0, 0, 4, 0, 4,
- 0, 1, 0, 0, 12, 11, 12, 12, 19, 0,
- 9, 0, 9, 0, 1, 0, 0, 10, 0, 10,
- 0, 1, 0, 5, 0, 18, 0, 17, 0, 0,
-
- 0, 0, 0, 0, 0, 0, 0, 0, 8, 0,
- 0, 0, 0, 7, 0, 0, 0, 0, 3, 0,
- 0, 0, 15, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 21, 19, 5, 19, 19, 19,
+ 19, 19, 20, 4, 20, 20, 20, 18, 15, 17,
+ 15, 18, 18, 18, 20, 7, 20, 20, 20, 8,
+ 20, 20, 20, 9, 20, 20, 13, 12, 13, 13,
+ 13, 5, 0, 1, 0, 0, 0, 0, 2, 0,
+ 0, 4, 0, 0, 1, 0, 0, 17, 0, 16,
+ 0, 0, 0, 7, 0, 0, 1, 0, 0, 8,
+ 0, 0, 1, 0, 0, 10, 0, 9, 0, 1,
+ 0, 12, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 6, 0, 0, 0, 0, 11, 0, 0, 0,
+ 0, 3, 0, 0, 0, 14, 0
} ;

static yyconst flex_int32_t yy_ec[256] =
@@ -509,116 +508,116 @@
1, 1, 1, 1, 1, 1, 1, 1, 1
} ;

-static yyconst flex_int16_t yy_base[149] =
+static yyconst flex_int16_t yy_base[142] =
{ 0,
- 0, 7, 15, 19, 27, 31, 35, 39, 43, 47,
- 51, 55, 59, 66, 74, 0, 220, 221, 23, 216,
- 63, 203, 208, 70, 79, 221, 81, 83, 85, 0,
- 221, 213, 87, 221, 221, 212, 89, 91, 221, 95,
- 97, 99, 221, 101, 103, 221, 221, 211, 105, 204,
- 221, 221, 174, 9, 169, 107, 172, 109, 111, 221,
- 113, 157, 0, 115, 221, 117, 119, 221, 121, 221,
- 123, 221, 125, 127, 0, 221, 129, 131, 221, 133,
- 221, 135, 221, 137, 221, 139, 141, 221, 144, 221,
- 146, 221, 148, 221, 148, 221, 149, 221, 0, 166,
-
- 84, 151, 64, 160, 154, 57, 44, 156, 221, 0,
- 49, 154, 161, 221, 0, 45, 29, 165, 221, 167,
- 31, 26, 221, 221, 178, 180, 182, 184, 186, 188,
- 190, 192, 194, 196, 198, 35, 200, 202, 204, 206,
- 208, 31, 27, 23, 11, 1, 0, 210
+ 0, 7, 15, 19, 28, 34, 39, 43, 47, 51,
+ 55, 59, 63, 70, 220, 221, 221, 216, 23, 203,
+ 208, 67, 74, 221, 77, 79, 81, 221, 221, 221,
+ 176, 9, 83, 171, 85, 221, 87, 91, 93, 221,
+ 95, 97, 99, 221, 101, 103, 221, 221, 173, 105,
+ 154, 221, 107, 221, 109, 143, 0, 111, 221, 113,
+ 115, 221, 117, 119, 221, 121, 123, 221, 123, 221,
+ 0, 134, 126, 221, 128, 132, 221, 134, 136, 221,
+ 140, 142, 221, 144, 146, 221, 148, 221, 150, 221,
+ 152, 221, 152, 121, 153, 85, 162, 156, 68, 52,
+
+ 157, 221, 0, 57, 166, 166, 221, 0, 53, 37,
+ 169, 221, 171, 39, 34, 221, 221, 180, 182, 184,
+ 186, 188, 190, 192, 194, 196, 198, 200, 43, 27,
+ 202, 204, 206, 208, 210, 212, 23, 11, 1, 0,
+ 214
} ;

-static yyconst flex_int16_t yy_def[149] =
+static yyconst flex_int16_t yy_def[142] =
{ 0,
- 125, 125, 126, 126, 127, 127, 128, 128, 129, 129,
- 130, 130, 131, 131, 128, 15, 124, 124, 124, 124,
- 132, 124, 124, 133, 134, 124, 134, 135, 134, 136,
- 124, 136, 137, 124, 124, 124, 132, 138, 124, 138,
- 139, 140, 124, 140, 141, 124, 124, 124, 132, 124,
- 124, 124, 124, 142, 143, 124, 124, 124, 132, 124,
- 132, 124, 124, 133, 124, 133, 134, 124, 134, 124,
- 135, 124, 135, 134, 136, 124, 137, 137, 124, 138,
- 124, 138, 124, 139, 124, 139, 140, 124, 140, 124,
- 141, 124, 141, 124, 124, 124, 142, 124, 142, 143,
-
- 124, 144, 145, 134, 146, 147, 124, 144, 124, 144,
- 145, 148, 146, 124, 146, 147, 124, 148, 124, 148,
- 124, 124, 124, 0, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124
+ 118, 118, 119, 119, 120, 120, 121, 121, 122, 122,
+ 123, 123, 124, 124, 117, 117, 117, 117, 125, 117,
+ 117, 126, 127, 117, 127, 128, 127, 117, 117, 117,
+ 117, 129, 125, 130, 131, 117, 131, 132, 133, 117,
+ 133, 134, 135, 117, 135, 136, 117, 117, 117, 125,
+ 117, 117, 125, 117, 125, 117, 117, 126, 117, 126,
+ 127, 117, 127, 128, 117, 128, 127, 117, 129, 117,
+ 129, 130, 131, 117, 131, 132, 117, 132, 133, 117,
+ 133, 134, 117, 134, 135, 117, 135, 117, 136, 117,
+ 136, 117, 117, 117, 137, 138, 127, 139, 140, 117,
+
+ 137, 117, 137, 138, 141, 139, 117, 139, 140, 117,
+ 141, 117, 141, 117, 117, 117, 0, 117, 117, 117,
+ 117, 117, 117, 117, 117, 117, 117, 117, 117, 117,
+ 117, 117, 117, 117, 117, 117, 117, 117, 117, 117,
+ 117
} ;

static yyconst flex_int16_t yy_nxt[241] =
{ 0,
- 116, 113, 19, 20, 102, 21, 103, 22, 23, 19,
- 20, 111, 21, 98, 22, 23, 24, 26, 27, 99,
- 28, 26, 27, 108, 28, 56, 57, 100, 29, 31,
- 32, 97, 33, 31, 32, 75, 33, 35, 36, 123,
- 37, 35, 36, 122, 37, 39, 40, 121, 41, 39,
- 40, 114, 41, 43, 44, 109, 45, 43, 44, 117,
- 45, 47, 48, 114, 49, 60, 61, 50, 47, 48,
- 109, 49, 65, 66, 50, 51, 52, 53, 54, 37,
- 55, 68, 69, 70, 69, 72, 73, 68, 69, 60,
- 78, 60, 61, 81, 82, 107, 74, 83, 82, 85,
-
- 86, 88, 89, 90, 89, 92, 93, 60, 61, 56,
- 57, 56, 57, 60, 61, 60, 61, 65, 66, 65,
- 66, 68, 69, 68, 69, 72, 73, 72, 73, 68,
- 69, 60, 78, 60, 78, 81, 82, 81, 82, 85,
- 86, 85, 86, 88, 89, 104, 88, 89, 92, 93,
- 92, 93, 105, 98, 106, 109, 119, 120, 114, 99,
- 109, 110, 68, 69, 115, 114, 110, 119, 120, 119,
- 120, 115, 98, 101, 56, 98, 96, 112, 18, 18,
- 25, 25, 30, 30, 34, 34, 38, 38, 42, 42,
- 46, 46, 59, 59, 64, 64, 67, 67, 71, 71,
-
- 77, 77, 80, 80, 84, 84, 87, 87, 91, 91,
- 118, 118, 95, 94, 79, 76, 63, 62, 58, 124,
- 17, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124
+ 109, 106, 17, 18, 95, 19, 96, 20, 21, 17,
+ 18, 104, 19, 70, 20, 21, 22, 24, 25, 71,
+ 26, 24, 25, 101, 26, 54, 55, 72, 27, 29,
+ 30, 31, 32, 33, 34, 29, 30, 31, 32, 33,
+ 34, 36, 37, 69, 38, 36, 37, 116, 38, 40,
+ 41, 115, 42, 40, 41, 114, 42, 44, 45, 107,
+ 46, 44, 45, 102, 46, 48, 49, 110, 50, 59,
+ 60, 51, 48, 49, 107, 50, 62, 63, 51, 62,
+ 63, 65, 66, 62, 63, 54, 55, 74, 75, 74,
+ 75, 102, 67, 77, 78, 80, 81, 80, 81, 83,
+
+ 84, 86, 87, 88, 87, 90, 91, 54, 55, 54,
+ 55, 54, 55, 59, 60, 59, 60, 62, 63, 62,
+ 63, 65, 66, 65, 66, 62, 63, 70, 74, 75,
+ 74, 75, 100, 71, 77, 78, 77, 78, 80, 81,
+ 70, 97, 80, 81, 83, 84, 83, 84, 86, 87,
+ 86, 87, 90, 91, 90, 91, 98, 102, 99, 94,
+ 107, 102, 93, 103, 62, 63, 108, 103, 112, 113,
+ 107, 112, 113, 112, 113, 92, 108, 70, 68, 105,
+ 16, 16, 23, 23, 28, 28, 35, 35, 39, 39,
+ 43, 43, 47, 47, 53, 53, 58, 58, 61, 61,
+
+ 64, 64, 73, 73, 76, 76, 79, 79, 82, 82,
+ 85, 85, 89, 89, 111, 111, 57, 56, 52, 117,
+ 15, 117, 117, 117, 117, 117, 117, 117, 117, 117,
+ 117, 117, 117, 117, 117, 117, 117, 117, 117, 117
} ;

static yyconst flex_int16_t yy_chk[241] =
{ 0,
- 147, 146, 1, 1, 63, 1, 63, 1, 1, 2,
- 2, 145, 2, 54, 2, 2, 2, 3, 3, 54,
- 3, 4, 4, 144, 4, 19, 19, 143, 4, 5,
- 5, 142, 5, 6, 6, 136, 6, 7, 7, 122,
- 7, 8, 8, 121, 8, 9, 9, 117, 9, 10,
- 10, 116, 10, 11, 11, 111, 11, 12, 12, 107,
- 12, 13, 13, 106, 13, 21, 21, 13, 14, 14,
- 103, 14, 24, 24, 14, 15, 15, 15, 15, 15,
- 15, 25, 25, 27, 27, 28, 28, 29, 29, 33,
- 33, 37, 37, 38, 38, 101, 29, 40, 40, 41,
-
- 41, 42, 42, 44, 44, 45, 45, 49, 49, 56,
- 56, 58, 58, 59, 59, 61, 61, 64, 64, 66,
- 66, 67, 67, 69, 69, 71, 71, 73, 73, 74,
- 74, 77, 77, 78, 78, 80, 80, 82, 82, 84,
- 84, 86, 86, 87, 87, 74, 89, 89, 91, 91,
- 93, 93, 95, 97, 95, 102, 112, 112, 105, 97,
- 108, 102, 104, 104, 105, 113, 108, 118, 118, 120,
- 120, 113, 100, 62, 57, 55, 53, 104, 125, 125,
- 126, 126, 127, 127, 128, 128, 129, 129, 130, 130,
- 131, 131, 132, 132, 133, 133, 134, 134, 135, 135,
-
- 137, 137, 138, 138, 139, 139, 140, 140, 141, 141,
- 148, 148, 50, 48, 36, 32, 23, 22, 20, 17,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 124, 124, 124, 124, 124
+ 140, 139, 1, 1, 57, 1, 57, 1, 1, 2,
+ 2, 138, 2, 32, 2, 2, 2, 3, 3, 32,
+ 3, 4, 4, 137, 4, 19, 19, 130, 4, 5,
+ 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
+ 6, 7, 7, 129, 7, 8, 8, 115, 8, 9,
+ 9, 114, 9, 10, 10, 110, 10, 11, 11, 109,
+ 11, 12, 12, 104, 12, 13, 13, 100, 13, 22,
+ 22, 13, 14, 14, 99, 14, 23, 23, 14, 25,
+ 25, 26, 26, 27, 27, 33, 33, 35, 35, 37,
+ 37, 96, 27, 38, 38, 39, 39, 41, 41, 42,
+
+ 42, 43, 43, 45, 45, 46, 46, 50, 50, 53,
+ 53, 55, 55, 58, 58, 60, 60, 61, 61, 63,
+ 63, 64, 64, 66, 66, 67, 67, 69, 73, 73,
+ 75, 75, 94, 69, 76, 76, 78, 78, 79, 79,
+ 72, 67, 81, 81, 82, 82, 84, 84, 85, 85,
+ 87, 87, 89, 89, 91, 91, 93, 95, 93, 56,
+ 98, 101, 51, 95, 97, 97, 98, 101, 105, 105,
+ 106, 111, 111, 113, 113, 49, 106, 34, 31, 97,
+ 118, 118, 119, 119, 120, 120, 121, 121, 122, 122,
+ 123, 123, 124, 124, 125, 125, 126, 126, 127, 127,
+
+ 128, 128, 131, 131, 132, 132, 133, 133, 134, 134,
+ 135, 135, 136, 136, 141, 141, 21, 20, 18, 15,
+ 117, 117, 117, 117, 117, 117, 117, 117, 117, 117,
+ 117, 117, 117, 117, 117, 117, 117, 117, 117, 117
} ;

/* Table of booleans, true if rule could match eol. */
static yyconst flex_int32_t yy_rule_can_match_eol[21] =
{ 0,
-1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1,
+1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, };

static yyconst flex_int16_t yy_rule_linenum[20] =
{ 0,
- 317, 319, 322, 326, 333, 335, 357, 372, 389, 401,
- 415, 436, 495, 501, 505, 509, 511, 522, 525
+ 301, 303, 306, 310, 317, 320, 337, 349, 371, 390,
+ 442, 461, 463, 493, 497, 499, 524, 528, 530
} ;

/* The intent behind this definition is that it'll catch
@@ -641,22 +640,20 @@
* normal strings. Newline characters are escaped.
* POD comments and line comments are filtered out.
*
+ *
*/

-/* TODO:
- - there's a weirdness in the SAVELINE state; we need to duplicate
- the yytext string twice, otherwise things go wrong badly.
-
- - it might be interesting to improve memory handling to make things
- a bit more efficient.
-
- */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
-#include <assert.h>
+
+/* to easily switch between parrot's functions and without; for testing */
+/*
+#define LINKPARROT
+*/
+

#ifdef LINKPARROT

@@ -665,13 +662,18 @@

#else

-#define STREQ(x,y) (0 == strcmp(x,y))
-#define mem_sys_allocate(x) yyalloc(x,yyscanner)
+#include <assert.h>
+
+#define NULLOK(x) x
+#define NOTNULL(x) x
+#define STREQ(x,y) (0 == strcmp(x,y))
+#define mem_sys_allocate(x) calloc(1, x)
+#define mem_sys_allocate_zeroed(x) calloc(1, x)
#define PARROT_MALLOC
#define PARROT_WARN_UNUSED_RESULT
#define PARROT_CANNOT_RETURN_NULL
-#define PARROT_ASSERT(x) assert(x)
-#define mem_sys_free(x) yyfree(x,yyscanner)
+#define PARROT_ASSERT(x) assert(x)
+#define mem_sys_free(x) free(x)

#endif

@@ -682,8 +684,6 @@
#define YY_DECL int yylex(yyscan_t yyscanner)


-
-
extern char *yyget_text(yyscan_t yyscanner);
extern void yyset_in(FILE *fp,yyscan_t yyscanner);
extern int yylex_destroy(yyscan_t yyscanner);
@@ -705,6 +705,8 @@
YY_BUFFER_STATE file_buffer; /* needed to store the ref. to the file
when scanning a string buffer */

+ FILE *outfile; /* output file; or STDOUT if no file is specified */
+
} global_state;

/* accessor methods for setting and getting the lexer_state */
@@ -713,12 +715,6 @@
extern YY_EXTRA_TYPE yyget_extra(yyscan_t scanner);
extern void yyset_extra(YY_EXTRA_TYPE lexer ,yyscan_t scanner);

-#define output stdout
-
-/* macro to chop off the last character, typically a newline character,
- * but can also be something else
- */
-#define chop_yytext() (yytext[--yyleng] = '\0')


/*
@@ -736,7 +732,7 @@

*/
static void
-lex_error(yyscan_t yyscanner, char const * const message, ...) {
+lex_error(yyscan_t yyscanner, NOTNULL(char const * const message), ...) {
global_state * const state = yyget_extra(yyscanner);
int lineno = yyget_lineno(yyscanner);
va_list arg_ptr;
@@ -753,34 +749,12 @@
}


-/*
-
-=item C<char *
-dupstr(char * const source)>
-
-The C89 standard does not define a dupstr() in the C library,
-so define our own dupstr. Function names beginning with "str"
-are reserved (I think), so make it dupstr, as that is what it
-does: duplicate a string.
-
-=cut
-
-*/
-PARROT_MALLOC
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-char *
-dupstr(char * const source, yyscan_t yyscanner) {
- char *newstring = (char *)mem_sys_allocate((strlen(source) + 1) * sizeof (char));
- strcpy(newstring, source);
- return newstring;
-}
-


/*

-=item C<init_global_state>
+=item C<static global_state *
+init_global_state(char * const filename, FILE *outfile)>

create and initialize a global_state structure, containing all 'global'
variables that are needed during the scanning.
@@ -792,20 +766,23 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
static global_state *
-init_global_state(char * const filename, yyscan_t yyscanner) {
+init_global_state(NOTNULL(char * const filename), NOTNULL(FILE *outfile)) {
global_state *state = (global_state *)mem_sys_allocate(sizeof (global_state));
- state->filename = filename;
- state->heredoc = NULL;
- state->linebuffer = dupstr("", yyscanner);
- state->delimiter = NULL;
- state->file_buffer = NULL;
- state->errors = 0;
+ state->filename = filename;
+ state->heredoc = NULL;
+ state->linebuffer = NULL;
+ state->delimiter = NULL;
+ state->file_buffer = NULL;
+ state->errors = 0;
+ state->outfile = outfile;
+
return state;
}

/*

-=item C<destroy_global_state>
+=item C<static void
+destroy_global_state(global_state * state)>

free all memory of the global state structure.

@@ -813,7 +790,7 @@

*/
static void
-destroy_global_state(global_state *state, yyscan_t yyscanner) {
+destroy_global_state(NOTNULL(global_state *state)) {
if (state->linebuffer)
mem_sys_free(state->linebuffer);
if (state->heredoc)
@@ -827,13 +804,13 @@
/*

=item C<static void
-scanfile(char * const filename)>
+scanfile(char * const filename, FILE *outputfile)>

=cut

*/
static void
-scanfile(char * const filename) {
+scanfile(NOTNULL(char * const filename), NOTNULL(FILE *outfile)) {
yyscan_t yyscanner;
global_state *state = NULL;
FILE *fp;
@@ -851,24 +828,19 @@
/* set the scanner to a string buffer and go parse */
yyset_in(fp,yyscanner);

- state = init_global_state(filename, yyscanner);
+ state = init_global_state(filename, outfile);

yyset_extra(state,yyscanner);

/* the lexer never returns anything, only call it once. Don't give a YYSTYPE object. */
yylex(yyscanner);

- /*
- destroy_global_state(state, yyscanner);
- */
+ destroy_global_state(state);

/* clean up after playing */
yylex_destroy(yyscanner);
-
-
-
-
}
+
/*

=item C<int
@@ -881,13 +853,30 @@
*/
int
main(int argc, char *argv[]) {
+ FILE *outfile;
+ char *outputfile = "heredoc.out";
+
/* check for proper usage */
if (argc < 2) {
fprintf(stderr, "Usage: %s <file>\n", argv[0]);
exit(EXIT_FAILURE);
}

- scanfile(argv[1]);
+ outfile = fopen(outputfile, "w");
+
+ if (outfile == NULL) {
+ fprintf(stderr, "Failed to open file '%s' for output. Aborting.\n", outputfile);
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(outfile, "# output generated by %s\n", argv[0]);
+
+ scanfile(argv[1], outfile);
+
+ fclose(outfile);
+
+
+ fprintf(stderr, "heredoc pre-processed successfully.\n");

return 0;
}
@@ -910,17 +899,15 @@



-
-#line 915 "hdocprep.c"
+#line 903 "hdocprep.c"

#define INITIAL 0
#define POD 1
-#define HEREDOC 2
-#define HEREDOC2 3
-#define SAVELINE 4
-#define SAVELINE2 5
-#define SCANSTRING 6
-#define INCLUDE 7
+#define INCLUDE 2
+#define SAVE_REST_OF_LINE 3
+#define SAVE_REST_AGAIN 4
+#define HEREDOC_STRING 5
+#define SCAN_STRING 6

#ifndef YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way
@@ -1203,10 +1190,10 @@
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

/* %% [7.0] user's declarations go here */
-#line 315 "hdocprep.l"
+#line 299 "hdocprep.l"


-#line 1210 "hdocprep.c"
+#line 1197 "hdocprep.c"

if ( !yyg->yy_init )
{
@@ -1270,13 +1257,13 @@
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 125 )
+ if ( yy_current_state >= 118 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_current_state != 124 );
+ while ( yy_current_state != 117 );
yy_cp = yyg->yy_last_accepting_cpos;
yy_current_state = yyg->yy_last_accepting_state;

@@ -1332,293 +1319,316 @@
case 1:
/* rule 1 can match eol */
YY_RULE_SETUP
-#line 317 "hdocprep.l"
+#line 301 "hdocprep.l"
{ /* ignore line comments */ }
YY_BREAK
case 2:
/* rule 2 can match eol */
YY_RULE_SETUP
-#line 319 "hdocprep.l"
+#line 303 "hdocprep.l"
{ yy_push_state(POD, yyscanner); }
YY_BREAK
case 3:
/* rule 3 can match eol */
YY_RULE_SETUP
-#line 322 "hdocprep.l"
+#line 306 "hdocprep.l"
{ /* end of POD comment */
- yy_pop_state(yyscanner);
- }
+ yy_pop_state(yyscanner);
+ }
YY_BREAK
case 4:
/* rule 4 can match eol */
YY_RULE_SETUP
-#line 326 "hdocprep.l"
+#line 310 "hdocprep.l"
{ /* ignore pod comments */ }
YY_BREAK
case YY_STATE_EOF(POD):
-#line 328 "hdocprep.l"
+#line 312 "hdocprep.l"
{ /* we're scanning a POD comment, but encountered end-of-file. */
- lex_error(yyscanner, "POD comment not closed!");
- yyterminate();
- }
+ lex_error(yyscanner, "POD comment not closed!");
+ yyterminate();
+ }
YY_BREAK
case 5:
/* rule 5 can match eol */
YY_RULE_SETUP
-#line 333 "hdocprep.l"
-{ /* don't do anything */ }
+#line 317 "hdocprep.l"
+{ fprintf(yyget_extra(yyscanner)->outfile, "\n"); }
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 335 "hdocprep.l"
-{ /* echo everything when scanning the string. */
- fprintf(output, "%s", yytext);
- }
- YY_BREAK
-case YY_STATE_EOF(SCANSTRING):
-#line 339 "hdocprep.l"
-{ /* end of saved string */
- global_state *state = yyget_extra(yyscanner);
- PARROT_ASSERT(state->file_buffer);
- yy_switch_to_buffer(state->file_buffer,yyscanner);
-
- /* clear the temp. variable; file_buffer is only used to temporarily
- * store a reference to the current buffer when we switch from file
- * to string scanning; after finishing scanning the string (which
- * is now, as we just scanned <<EOF>>), we switch back to the file
- * buffer.
- */
- state->file_buffer = NULL;
+#line 320 "hdocprep.l"
+{
+ global_state * const state = yyget_extra(yyscanner);
+
+ state->delimiter = (char *)mem_sys_allocate_zeroed((yyleng - 4 + 1)
+ * sizeof (char));
+
+ strncpy(state->delimiter, yytext + 3, yyleng - 4);

- BEGIN(INITIAL);
+ state->heredoc = (char *)mem_sys_allocate_zeroed(3 * sizeof (char));

- }
+ strcpy(state->heredoc, "\\n");
+
+ BEGIN(SAVE_REST_OF_LINE);
+
+ }
YY_BREAK
case 7:
+/* rule 7 can match eol */
YY_RULE_SETUP
-#line 357 "hdocprep.l"
-{ /* 2nd and later heredoc argument */
- global_state *state = yyget_extra(yyscanner);
- /* yyleng - (4 (for << and 2 quotes), + 1 for NULL character = 3) */
- state->delimiter = (char *)mem_sys_allocate((yyleng - 4 + 1)
- * sizeof (char));
-
- PARROT_ASSERT(state->delimiter);
-
- strncpy(state->delimiter, yytext + 3, yyleng - 4);
- state->delimiter[yyleng - 4] = '\0';
- state->heredoc = dupstr("", yyscanner);
+#line 337 "hdocprep.l"
+{ /* match the rest of the line */
+ global_state * const state = yyget_extra(yyscanner);

- BEGIN(SAVELINE2);
- }
+ state->linebuffer = (char *)mem_sys_allocate_zeroed((yyleng + 2)
+ * sizeof (char));
+
+ sprintf(state->linebuffer, "%s\n", yytext);
+
+ BEGIN(HEREDOC_STRING);
+
+ }
YY_BREAK
case 8:
+/* rule 8 can match eol */
YY_RULE_SETUP
-#line 372 "hdocprep.l"
-{ /* only copy the string after "<<'" and skip the last quote too */
- global_state *state = yyget_extra(yyscanner);
- /* allocate storage for the delimiter, skip the << and quote characters. */
- state->delimiter = (char *)mem_sys_allocate((yyleng - 4 + 1)
- * sizeof (char));
- PARROT_ASSERT(state->delimiter);
+#line 349 "hdocprep.l"
+{ /* match the rest of the line */
+ global_state * const state = yyget_extra(yyscanner);

- strncpy(state->delimiter, yytext + 3, yyleng - 4);
- state->delimiter[yyleng - 4] = '\0';
+ /* at this point we're saving the rest of the line again,
+ * so we were scanning the line buffer; free this now to
+ * prevent memory leaks.
+ */
+ PARROT_ASSERT(state->linebuffer != NULL);
+ mem_sys_free(state->linebuffer);

- state->heredoc = dupstr("", yyscanner);
+ state->linebuffer = (char *)mem_sys_allocate_zeroed((yyleng + 2)
+ * sizeof (char));

+ sprintf(state->linebuffer, "%s\n", yytext);

+ yy_switch_to_buffer(state->file_buffer,yyscanner);

- BEGIN(SAVELINE);
- }
+ BEGIN(HEREDOC_STRING);
+
+ }
YY_BREAK
case 9:
/* rule 9 can match eol */
YY_RULE_SETUP
-#line 389 "hdocprep.l"
-{ /* this state is used when reading the first heredoc delimiter
- * argument. Save the rest of the line and go scan the heredoc.
- */
- global_state *state = yyget_extra(yyscanner);
+#line 371 "hdocprep.l"
+{
+ global_state * const state = yyget_extra(yyscanner);

- PARROT_ASSERT(state->linebuffer != NULL);
+ int len = strlen(state->heredoc);

- state->linebuffer = dupstr(yytext, yyscanner);
+ /* allocate enough space for the current heredoc and an
+ * escaped newline character, + the NULL character.
+ */
+ char *temp = (char *)mem_sys_allocate_zeroed((len + 1 + 2)
+ * sizeof (char));

- BEGIN(HEREDOC);
- }
- YY_BREAK
-case 10:
-/* rule 10 can match eol */
-YY_RULE_SETUP
-#line 401 "hdocprep.l"
-{ /* this state is used when reading the 2nd and later heredoc
- delimiter arguments. Save the rest of the line and go scan
- the heredoc string. First, though, switch back to the file,
- because <SAVELINE2> state is activated when reading a string.
- */
- global_state *state = yyget_extra(yyscanner);
+ sprintf(temp, "%s\\n", state->heredoc);

- state->linebuffer = dupstr(yytext, yyscanner);
+ mem_sys_free(state->heredoc);

- yy_switch_to_buffer(state->file_buffer,yyscanner);
+ state->heredoc = temp;

- BEGIN(HEREDOC);
- }
+ }
YY_BREAK
-case 11:
-/* rule 11 can match eol */
+case 10:
+/* rule 10 can match eol */
YY_RULE_SETUP
-#line 415 "hdocprep.l"
-{ /* Scan a newline character, append this to the heredoc, but
- escape it.
- */
- global_state *state = yyget_extra(yyscanner);
-
- int len = strlen(state->heredoc);
-
- /* length of heredoc + 1 for NULL character + 2 for escaped '\n' */
- char *temp = (char *)mem_sys_allocate((len + 3) * sizeof (char));
-
- PARROT_ASSERT(state->heredoc != NULL);
+#line 390 "hdocprep.l"
+{
+ global_state * const state = yyget_extra(yyscanner);

+ /* remove the newline character */
+ /* can this be done through #ifdef, to prevent checks? */
+ if (yytext[yyleng - 2] == '\r')
+ yytext[yyleng - 2] = '\0';
+ else /* yytext[yyleng - 1] is '\n'. */
+ yytext[yyleng - 1] = '\0';

- /* translate "\n" to a "\" and "n" character */
- sprintf(temp, "%s\\n", state->heredoc);
+ if (strcmp(state->delimiter, yytext) == 0) { /* delimiter found? */

+ /* done with the delimiter */
+ mem_sys_free(state->delimiter);
+ state->delimiter = NULL;

- state->heredoc = temp;
+ /* we're going to scan from the linebuffer, save the current
+ * buffer for later (to restore it).
+ */
+ state->file_buffer = YY_CURRENT_BUFFER;

- }
- YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 436 "hdocprep.l"
-{ /* scan heredoc string contents */
+ /* print the flattened heredoc string */
+ fprintf(yyget_extra(yyscanner)->outfile, "\"%s\"", state->heredoc);

- global_state *state = yyget_extra(yyscanner);
+ mem_sys_free(state->heredoc);
+ state->heredoc = NULL;

- /* on windows remove the '\r' character */
- if (yytext[yyleng - 1] == '\r') {
- chop_yytext();
- }
+ /* now continue with scanning the string that we saved */
+ BEGIN(SCAN_STRING);

- if (STREQ(yytext, state->delimiter)) {
+ yy_scan_string(state->linebuffer,yyscanner);
+ }
+ else { /* nope, this is part of the heredoc; save this line */

- fprintf(output, "\"%s\"", state->heredoc);
+ int len = strlen(state->heredoc);

- /* free the delimiter memory */
- mem_sys_free(state->delimiter);
+ char *temp = (char *)mem_sys_allocate((len + yyleng + 1 + 2)
+ * sizeof (char));

- state->delimiter = NULL;
+ sprintf(temp, "%s%s\\n", state->heredoc, yytext);

- PARROT_ASSERT(state->heredoc != NULL);
+ mem_sys_free(state->heredoc);

- /* mem_sys_free(state->heredoc);
- */
+ state->heredoc = temp;
+ }
+ }
+ YY_BREAK
+case YY_STATE_EOF(HEREDOC_STRING):
+#line 437 "hdocprep.l"
+{ /* end of file while reading heredoc */
+ lex_error(yyscanner, "runaway heredoc string");
+ yyterminate();
+ }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 442 "hdocprep.l"
+{ /* a 'nested' heredoc string */
+ global_state *state = yyget_extra(yyscanner);

- state->heredoc = dupstr("", yyscanner);
+ PARROT_ASSERT(state->delimiter == NULL);

- /* save the current buffer, because we go scan the
- * rest of the string that was saved in <SAVELINE(2)>.
- */
- state->file_buffer = YY_CURRENT_BUFFER;
+ /* <<"FOO", only save the characters 'F','O','O'. */
+ state->delimiter = (char *)mem_sys_allocate_zeroed((yyleng - 4 + 1)
+ * sizeof (char));
+ /* strncpy adds the NULL char., according to the spec. */
+ strncpy(state->delimiter, yytext + 3, yyleng - 4);

- BEGIN(SCANSTRING);
+ state->heredoc = (char *)mem_sys_allocate_zeroed(3 * sizeof (char));

- PARROT_ASSERT(state->linebuffer != NULL);
+ /* an empty heredoc has at least a newline */
+ strcpy(state->heredoc, "\\n");

- yy_scan_string(state->linebuffer,yyscanner);
+ BEGIN(SAVE_REST_AGAIN);
+ }
+ YY_BREAK
+case 12:
+/* rule 12 can match eol */
+YY_RULE_SETUP
+#line 461 "hdocprep.l"
+{ /* do nothing */ }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 463 "hdocprep.l"
+{ fprintf(yyget_extra(yyscanner)->outfile, "%s", yytext); }
+ YY_BREAK
+case YY_STATE_EOF(SCAN_STRING):
+#line 465 "hdocprep.l"
+{
+ global_state * const state = yyget_extra(yyscanner);

+ /* switch back to file; */
+ yy_switch_to_buffer(state->file_buffer,yyscanner);

- }
- else {
- /* save this heredoc string line */
- char * const thisline = dupstr(yytext, yyscanner);
+ /* done with scanning the rest of the line; free its memory */
+ mem_sys_free(state->linebuffer);
+ /* and make sure there's no stray pointers */
+ state->linebuffer = NULL;

- state->heredoc = strcat(state->heredoc, thisline);
- }
- }
- YY_BREAK
-case YY_STATE_EOF(HEREDOC):
-#line 482 "hdocprep.l"
-{ /* End of file while reading a heredoc string. This is bad. */
+ state->file_buffer = NULL;

- lex_error(yyscanner, "end of file while reading heredoc string '%s'",
- yyget_extra(yyscanner)->delimiter);
+ /* make sure the PIR parser will report the right line numbers,
+ * in case of errors; as the heredoc string, which was X lines,
+ * is now flattened into 1 line, the line number must be adjusted.
+ */
+ fprintf(state->outfile, "\n.line %d\n", yyget_lineno(yyscanner));

- yyterminate();
- }
+ BEGIN(INITIAL);
+ }
YY_BREAK
case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(HEREDOC2):
-case YY_STATE_EOF(SAVELINE):
-case YY_STATE_EOF(SAVELINE2):
-case YY_STATE_EOF(INCLUDE):
-#line 491 "hdocprep.l"
+#line 489 "hdocprep.l"
{ /* end of file */
- yyterminate();
- }
- YY_BREAK
-case 13:
-/* rule 13 can match eol */
-YY_RULE_SETUP
-#line 495 "hdocprep.l"
-{ /* we only want to print a single newline instead of all newlines. */
- fprintf(output, "\n");
- }
+ yyterminate();
+ }
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 501 "hdocprep.l"
-{ /* just echo everything else */
- fprintf(output, "%s", yytext);
- }
- YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 505 "hdocprep.l"
+#line 493 "hdocprep.l"
{ /* .include directives must be handled here */
- yy_push_state(INCLUDE, yyscanner);
- }
+ yy_push_state(INCLUDE, yyscanner);
+ }
YY_BREAK
-case 16:
+case 15:
YY_RULE_SETUP
-#line 509 "hdocprep.l"
+#line 497 "hdocprep.l"
{ /* skip whitespace */ }
YY_BREAK
-case 17:
+case 16:
YY_RULE_SETUP
-#line 511 "hdocprep.l"
+#line 499 "hdocprep.l"
{ /* include this file */
- char * filename = dupstr(yytext, yyscanner);
+ global_state * const state = yyget_extra(yyscanner);
+
+ char * filename = (char *)mem_sys_allocate_zeroed((yyleng - 2 + 1)
+ * sizeof (char));
+
+ strncpy(filename, yytext + 1, yyleng - 2);

- filename[strlen(filename) - 1] = '\0';
- scanfile(filename + 1);
+ /* make sure that any error messages that occur in the .included
+ * file will report the right line number and file name.
+ */
+ fprintf(state->outfile, ".line 1\n");
+ fprintf(state->outfile, ".file %s\n", yytext); /* is quoted */

- /*mem_sys_free(filename);
- */
+ scanfile(filename, state->outfile);

- }
+ /* restore the location information; we didn't count the "\n"
+ * yet that will come after the .include dir.; hence the + 1 now.
+ */
+ fprintf(state->outfile, ".line %d\n", yyget_lineno(yyscanner) + 1);
+ fprintf(state->outfile, ".file '%s'\n", state->filename);
+
+ mem_sys_free(filename);
+ }
+ YY_BREAK
+case 17:
+/* rule 17 can match eol */
+YY_RULE_SETUP
+#line 524 "hdocprep.l"
+{ /* after .include "foo.pir", go back to the state we were in */
+ yy_pop_state(yyscanner);
+ }
YY_BREAK
case 18:
-/* rule 18 can match eol */
YY_RULE_SETUP
-#line 522 "hdocprep.l"
-{ yy_pop_state(yyscanner); }
+#line 528 "hdocprep.l"
+{ fprintf(stderr, "wrong scanner state\n"); }
YY_BREAK
case 19:
-/* rule 19 can match eol */
YY_RULE_SETUP
-#line 525 "hdocprep.l"
-{ /* do nothing. */ }
+#line 530 "hdocprep.l"
+{
+ fprintf(yyget_extra(yyscanner)->outfile, "%s", yytext);
+ }
YY_BREAK
case 20:
YY_RULE_SETUP
-#line 527 "hdocprep.l"
+#line 534 "hdocprep.l"
ECHO;
YY_BREAK
-#line 1622 "hdocprep.c"
+#line 1628 "hdocprep.c"
+case YY_STATE_EOF(INCLUDE):
+case YY_STATE_EOF(SAVE_REST_OF_LINE):
+case YY_STATE_EOF(SAVE_REST_AGAIN):
+ yyterminate();

case YY_END_OF_BUFFER:
{
@@ -1925,7 +1935,7 @@
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 125 )
+ if ( yy_current_state >= 118 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1959,11 +1969,11 @@
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 125 )
+ if ( yy_current_state >= 118 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 124);
+ yy_is_jam = (yy_current_state == 117);

return yy_is_jam ? 0 : yy_current_state;
}
@@ -2867,7 +2877,7 @@

/* %ok-for-header */

-#line 527 "hdocprep.l"
+#line 534 "hdocprep.l"




Modified: trunk/compilers/pirc/heredoc/hdocprep.l
==============================================================================
--- trunk/compilers/pirc/heredoc/hdocprep.l (original)
+++ trunk/compilers/pirc/heredoc/hdocprep.l Sun Oct 12 06:03:07 2008
@@ -10,22 +10,20 @@
* normal strings. Newline characters are escaped.
* POD comments and line comments are filtered out.
*
+ *
*/

-/* TODO:
- - there's a weirdness in the SAVELINE state; we need to duplicate
- the yytext string twice, otherwise things go wrong badly.
-
- - it might be interesting to improve memory handling to make things
- a bit more efficient.
-
- */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
-#include <assert.h>
+
+/* to easily switch between parrot's functions and without; for testing */
+/*
+#define LINKPARROT
+*/
+

#ifdef LINKPARROT

@@ -34,13 +32,18 @@

#else

-#define STREQ(x,y) (0 == strcmp(x,y))
-#define mem_sys_allocate(x) yyalloc(x, yyscanner)
+#include <assert.h>
+
+#define NULLOK(x) x
+#define NOTNULL(x) x
+#define STREQ(x,y) (0 == strcmp(x,y))
+#define mem_sys_allocate(x) calloc(1, x)
+#define mem_sys_allocate_zeroed(x) calloc(1, x)
#define PARROT_MALLOC
#define PARROT_WARN_UNUSED_RESULT
#define PARROT_CANNOT_RETURN_NULL
-#define PARROT_ASSERT(x) assert(x)
-#define mem_sys_free(x) yyfree(x, yyscanner)
+#define PARROT_ASSERT(x) assert(x)
+#define mem_sys_free(x) free(x)

#endif

@@ -51,8 +54,6 @@
#define YY_DECL int yylex(yyscan_t yyscanner)


-
-
extern char *yyget_text(yyscan_t yyscanner);
extern void yyset_in(FILE *fp, yyscan_t yyscanner);
extern int yylex_destroy(yyscan_t yyscanner);
@@ -74,6 +75,8 @@
YY_BUFFER_STATE file_buffer; /* needed to store the ref. to the file
when scanning a string buffer */

+ FILE *outfile; /* output file; or STDOUT if no file is specified */
+
} global_state;

/* accessor methods for setting and getting the lexer_state */
@@ -82,12 +85,6 @@
extern YY_EXTRA_TYPE yyget_extra(yyscan_t scanner);
extern void yyset_extra(YY_EXTRA_TYPE lexer , yyscan_t scanner);

-#define output stdout
-
-/* macro to chop off the last character, typically a newline character,
- * but can also be something else
- */
-#define chop_yytext() (yytext[--yyleng] = '\0')


/*
@@ -105,7 +102,7 @@

*/
static void
-lex_error(yyscan_t yyscanner, char const * const message, ...) {
+lex_error(yyscan_t yyscanner, NOTNULL(char const * const message), ...) {
global_state * const state = yyget_extra(yyscanner);
int lineno = yyget_lineno(yyscanner);
va_list arg_ptr;
@@ -122,34 +119,12 @@
}


-/*
-
-=item C<char *
-dupstr(char * const source)>
-
-The C89 standard does not define a dupstr() in the C library,
-so define our own dupstr. Function names beginning with "str"
-are reserved (I think), so make it dupstr, as that is what it
-does: duplicate a string.
-
-=cut
-
-*/
-PARROT_MALLOC
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-char *
-dupstr(char * const source, yyscan_t yyscanner) {
- char *newstring = (char *)mem_sys_allocate((strlen(source) + 1) * sizeof (char));
- strcpy(newstring, source);
- return newstring;
-}
-


/*

-=item C<init_global_state>
+=item C<static global_state *
+init_global_state(char * const filename, FILE *outfile)>

create and initialize a global_state structure, containing all 'global'
variables that are needed during the scanning.
@@ -161,20 +136,23 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CANNOT_RETURN_NULL
static global_state *
-init_global_state(char * const filename, yyscan_t yyscanner) {
+init_global_state(NOTNULL(char * const filename), NOTNULL(FILE *outfile)) {
global_state *state = (global_state *)mem_sys_allocate(sizeof (global_state));
- state->filename = filename;
- state->heredoc = NULL;
- state->linebuffer = dupstr("", yyscanner);
- state->delimiter = NULL;
- state->file_buffer = NULL;
- state->errors = 0;
+ state->filename = filename;
+ state->heredoc = NULL;
+ state->linebuffer = NULL;
+ state->delimiter = NULL;
+ state->file_buffer = NULL;
+ state->errors = 0;
+ state->outfile = outfile;
+
return state;
}

/*

-=item C<destroy_global_state>
+=item C<static void
+destroy_global_state(global_state * state)>

free all memory of the global state structure.

@@ -182,7 +160,7 @@

*/
static void
-destroy_global_state(global_state *state, yyscan_t yyscanner) {
+destroy_global_state(NOTNULL(global_state *state)) {
if (state->linebuffer)
mem_sys_free(state->linebuffer);
if (state->heredoc)
@@ -196,13 +174,13 @@
/*

=item C<static void
-scanfile(char * const filename)>
+scanfile(char * const filename, FILE *outputfile)>

=cut

*/
static void
-scanfile(char * const filename) {
+scanfile(NOTNULL(char * const filename), NOTNULL(FILE *outfile)) {
yyscan_t yyscanner;
global_state *state = NULL;
FILE *fp;
@@ -220,24 +198,19 @@
/* set the scanner to a string buffer and go parse */
yyset_in(fp, yyscanner);

- state = init_global_state(filename, yyscanner);
+ state = init_global_state(filename, outfile);

yyset_extra(state, yyscanner);

/* the lexer never returns anything, only call it once. Don't give a YYSTYPE object. */
yylex(yyscanner);

- /*
- destroy_global_state(state, yyscanner);
- */
+ destroy_global_state(state);

/* clean up after playing */
yylex_destroy(yyscanner);
-
-
-
-
}
+
/*

=item C<int
@@ -250,13 +223,30 @@
*/
int
main(int argc, char *argv[]) {
+ FILE *outfile;
+ char *outputfile = "heredoc.out";
+
/* check for proper usage */
if (argc < 2) {
fprintf(stderr, "Usage: %s <file>\n", argv[0]);
exit(EXIT_FAILURE);
}

- scanfile(argv[1]);
+ outfile = fopen(outputfile, "w");
+
+ if (outfile == NULL) {
+ fprintf(stderr, "Failed to open file '%s' for output. Aborting.\n", outputfile);
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(outfile, "# output generated by %s\n", argv[0]);
+
+ scanfile(argv[1], outfile);
+
+ fclose(outfile);
+
+
+ fprintf(stderr, "heredoc pre-processed successfully.\n");

return 0;
}
@@ -292,237 +282,254 @@
%pointer

%x POD
-%x HEREDOC
-%x HEREDOC2
-%x SAVELINE
-%x SAVELINE2
-%x SCANSTRING
%x INCLUDE
+%x SAVE_REST_OF_LINE
+%x SAVE_REST_AGAIN
+%x HEREDOC_STRING
+%x SCAN_STRING
+

-ALPHA [a-zA-Z@_]
-DIGIT [0-9]
-DIGITS {DIGIT}+
-ALNUM {ALPHA}|{DIGIT}
-IDENT {ALPHA}{ALNUM}*
WS [\t\f\r\x1a ]
EOL \r?\n
DQ_STRING \"(\\.|[^"\\\n])*\"
SQ_STRING \'[^'\n]*\'
Q_STRING {SQ_STRING}|{DQ_STRING}
-NEWLINE {EOL}({WS}|{EOL})*
LINECOMMENT [#].*{EOL}

%%

-<*>{LINECOMMENT} { /* ignore line comments */ }
+<*>{LINECOMMENT} { /* ignore line comments */ }

-<INITIAL>^"=".*{EOL} { yy_push_state(POD, yyscanner); }
+<INITIAL>^"=".*{EOL} { yy_push_state(POD, yyscanner); }


-<POD>^"=cut".*{EOL} { /* end of POD comment */
- yy_pop_state(yyscanner);
- }
+<POD>^"=cut".*{EOL} { /* end of POD comment */
+ yy_pop_state(yyscanner);
+ }

-<POD>.*{EOL} { /* ignore pod comments */ }
+<POD>.*{EOL} { /* ignore pod comments */ }

-<POD><<EOF>> { /* we're scanning a POD comment, but encountered end-of-file. */
- lex_error(yyscanner, "POD comment not closed!");
- yyterminate();
- }
+<POD><<EOF>> { /* we're scanning a POD comment, but encountered end-of-file. */
+ lex_error(yyscanner, "POD comment not closed!");
+ yyterminate();
+ }

-<SCANSTRING>{EOL} { /* don't do anything */ }
+<INITIAL>{EOL} { fprintf(yyget_extra(yyscanner)->outfile, "\n"); }

-<SCANSTRING>. { /* echo everything when scanning the string. */
- fprintf(output, "%s", yytext);
- }

-<SCANSTRING><<EOF>> { /* end of saved string */
- global_state *state = yyget_extra(yyscanner);
- PARROT_ASSERT(state->file_buffer);
- yy_switch_to_buffer(state->file_buffer, yyscanner);
+<INITIAL>"<<"{Q_STRING} {
+ global_state * const state = yyget_extra(yyscanner);

- /* clear the temp. variable; file_buffer is only used to temporarily
- * store a reference to the current buffer when we switch from file
- * to string scanning; after finishing scanning the string (which
- * is now, as we just scanned <<EOF>>), we switch back to the file
- * buffer.
- */
- state->file_buffer = NULL;
+ state->delimiter = (char *)mem_sys_allocate_zeroed((yyleng - 4 + 1)
+ * sizeof (char));

- BEGIN(INITIAL);
+ strncpy(state->delimiter, yytext + 3, yyleng - 4);

- }
+ state->heredoc = (char *)mem_sys_allocate_zeroed(3 * sizeof (char));

+ strcpy(state->heredoc, "\\n");

-<SCANSTRING>"<<"{Q_STRING} { /* 2nd and later heredoc argument */
- global_state *state = yyget_extra(yyscanner);
- /* yyleng - (4 (for << and 2 quotes), + 1 for NULL character = 3) */
- state->delimiter = (char *)mem_sys_allocate((yyleng - 4 + 1)
- * sizeof (char));
+ BEGIN(SAVE_REST_OF_LINE);

- PARROT_ASSERT(state->delimiter);
+ }

- strncpy(state->delimiter, yytext + 3, yyleng - 4);
- state->delimiter[yyleng - 4] = '\0';
- state->heredoc = dupstr("", yyscanner);

- BEGIN(SAVELINE2);
- }
+<SAVE_REST_OF_LINE>.*{EOL} { /* match the rest of the line */
+ global_state * const state = yyget_extra(yyscanner);

-<INITIAL>"<<"{Q_STRING} { /* only copy the string after "<<'" and skip the last quote too */
- global_state *state = yyget_extra(yyscanner);
- /* allocate storage for the delimiter, skip the << and quote characters. */
- state->delimiter = (char *)mem_sys_allocate((yyleng - 4 + 1)
- * sizeof (char));
- PARROT_ASSERT(state->delimiter);
+ state->linebuffer = (char *)mem_sys_allocate_zeroed((yyleng + 2)
+ * sizeof (char));

- strncpy(state->delimiter, yytext + 3, yyleng - 4);
- state->delimiter[yyleng - 4] = '\0';
+ sprintf(state->linebuffer, "%s\n", yytext);

- state->heredoc = dupstr("", yyscanner);
+ BEGIN(HEREDOC_STRING);

+ }

+<SAVE_REST_AGAIN>.*{EOL} { /* match the rest of the line */
+ global_state * const state = yyget_extra(yyscanner);

- BEGIN(SAVELINE);
- }
+ /* at this point we're saving the rest of the line again,
+ * so we were scanning the line buffer; free this now to
+ * prevent memory leaks.
+ */
+ PARROT_ASSERT(state->linebuffer != NULL);
+ mem_sys_free(state->linebuffer);
+
+ state->linebuffer = (char *)mem_sys_allocate_zeroed((yyleng + 2)
+ * sizeof (char));
+
+ sprintf(state->linebuffer, "%s\n", yytext);
+
+ yy_switch_to_buffer(state->file_buffer, yyscanner);

-<SAVELINE>.*{EOL} { /* this state is used when reading the first heredoc delimiter
- * argument. Save the rest of the line and go scan the heredoc.
- */
- global_state *state = yyget_extra(yyscanner);
+ BEGIN(HEREDOC_STRING);

- PARROT_ASSERT(state->linebuffer != NULL);
+ }

- state->linebuffer = dupstr(yytext, yyscanner);

- BEGIN(HEREDOC);
- }
+<HEREDOC_STRING>{EOL} {
+ global_state * const state = yyget_extra(yyscanner);

-<SAVELINE2>.*{EOL} { /* this state is used when reading the 2nd and later heredoc
- delimiter arguments. Save the rest of the line and go scan
- the heredoc string. First, though, switch back to the file,
- because <SAVELINE2> state is activated when reading a string.
- */
- global_state *state = yyget_extra(yyscanner);
+ int len = strlen(state->heredoc);

- state->linebuffer = dupstr(yytext, yyscanner);
+ /* allocate enough space for the current heredoc and an
+ * escaped newline character, + the NULL character.
+ */
+ char *temp = (char *)mem_sys_allocate_zeroed((len + 1 + 2)
+ * sizeof (char));

- yy_switch_to_buffer(state->file_buffer, yyscanner);
+ sprintf(temp, "%s\\n", state->heredoc);

- BEGIN(HEREDOC);
- }
+ mem_sys_free(state->heredoc);

-<HEREDOC>{EOL} { /* Scan a newline character, append this to the heredoc, but
- escape it.
- */
- global_state *state = yyget_extra(yyscanner);
+ state->heredoc = temp;

- int len = strlen(state->heredoc);
+ }

- /* length of heredoc + 1 for NULL character + 2 for escaped '\n' */
- char *temp = (char *)mem_sys_allocate((len + 3) * sizeof (char));
+<HEREDOC_STRING>.*{EOL} {
+ global_state * const state = yyget_extra(yyscanner);

- PARROT_ASSERT(state->heredoc != NULL);
+ /* remove the newline character */
+ /* can this be done through #ifdef, to prevent checks? */
+ if (yytext[yyleng - 2] == '\r')
+ yytext[yyleng - 2] = '\0';
+ else /* yytext[yyleng - 1] is '\n'. */
+ yytext[yyleng - 1] = '\0';

+ if (strcmp(state->delimiter, yytext) == 0) { /* delimiter found? */

- /* translate "\n" to a "\" and "n" character */
- sprintf(temp, "%s\\n", state->heredoc);
+ /* done with the delimiter */
+ mem_sys_free(state->delimiter);
+ state->delimiter = NULL;

+ /* we're going to scan from the linebuffer, save the current
+ * buffer for later (to restore it).
+ */
+ state->file_buffer = YY_CURRENT_BUFFER;

- state->heredoc = temp;
+ /* print the flattened heredoc string */
+ fprintf(yyget_extra(yyscanner)->outfile, "\"%s\"", state->heredoc);

- }
+ mem_sys_free(state->heredoc);
+ state->heredoc = NULL;

-<HEREDOC>.* { /* scan heredoc string contents */
+ /* now continue with scanning the string that we saved */
+ BEGIN(SCAN_STRING);

- global_state *state = yyget_extra(yyscanner);
+ yy_scan_string(state->linebuffer, yyscanner);
+ }
+ else { /* nope, this is part of the heredoc; save this line */

- /* on windows remove the '\r' character */
- if (yytext[yyleng - 1] == '\r') {
- chop_yytext();
- }
+ int len = strlen(state->heredoc);

- if (STREQ(yytext, state->delimiter)) {
+ char *temp = (char *)mem_sys_allocate((len + yyleng + 1 + 2)
+ * sizeof (char));

- fprintf(output, "\"%s\"", state->heredoc);
+ sprintf(temp, "%s%s\\n", state->heredoc, yytext);
+
+ mem_sys_free(state->heredoc);
+
+ state->heredoc = temp;
+ }
+ }

- /* free the delimiter memory */
- mem_sys_free(state->delimiter);
+<HEREDOC_STRING><<EOF>> { /* end of file while reading heredoc */
+ lex_error(yyscanner, "runaway heredoc string");
+ yyterminate();
+ }

- state->delimiter = NULL;
+<SCAN_STRING>"<<"{Q_STRING} { /* a 'nested' heredoc string */
+ global_state *state = yyget_extra(yyscanner);

- PARROT_ASSERT(state->heredoc != NULL);
+ PARROT_ASSERT(state->delimiter == NULL);

- /* mem_sys_free(state->heredoc);
- */
+ /* <<"FOO", only save the characters 'F','O','O'. */
+ state->delimiter = (char *)mem_sys_allocate_zeroed((yyleng - 4 + 1)
+ * sizeof (char));
+ /* strncpy adds the NULL char., according to the spec. */
+ strncpy(state->delimiter, yytext + 3, yyleng - 4);

- state->heredoc = dupstr("", yyscanner);
+ state->heredoc = (char *)mem_sys_allocate_zeroed(3 * sizeof (char));

- /* save the current buffer, because we go scan the
- * rest of the string that was saved in <SAVELINE(2)>.
- */
- state->file_buffer = YY_CURRENT_BUFFER;
+ /* an empty heredoc has at least a newline */
+ strcpy(state->heredoc, "\\n");

- BEGIN(SCANSTRING);
+ BEGIN(SAVE_REST_AGAIN);
+ }

- PARROT_ASSERT(state->linebuffer != NULL);
+<SCAN_STRING>{EOL} { /* do nothing */ }

- yy_scan_string(state->linebuffer, yyscanner);
+<SCAN_STRING>. { fprintf(yyget_extra(yyscanner)->outfile, "%s", yytext); }

+<SCAN_STRING><<EOF>> {
+ global_state * const state = yyget_extra(yyscanner);

- }
- else {
- /* save this heredoc string line */
- char * const thisline = dupstr(yytext, yyscanner);
+ /* switch back to file; */
+ yy_switch_to_buffer(state->file_buffer, yyscanner);

- state->heredoc = strcat(state->heredoc, thisline);
- }
- }
+ /* done with scanning the rest of the line; free its memory */
+ mem_sys_free(state->linebuffer);
+ /* and make sure there's no stray pointers */
+ state->linebuffer = NULL;

-<HEREDOC><<EOF>> { /* End of file while reading a heredoc string. This is bad. */
+ state->file_buffer = NULL;

- lex_error(yyscanner, "end of file while reading heredoc string '%s'",
- yyget_extra(yyscanner)->delimiter);
+ /* make sure the PIR parser will report the right line numbers,
+ * in case of errors; as the heredoc string, which was X lines,
+ * is now flattened into 1 line, the line number must be adjusted.
+ */
+ fprintf(state->outfile, "\n.line %d\n", yyget_lineno(yyscanner));

- yyterminate();
- }
+ BEGIN(INITIAL);
+ }


-<<EOF>> { /* end of file */
- yyterminate();
- }

-<INITIAL>{EOL}+ { /* we only want to print a single newline instead of all newlines. */
- fprintf(output, "\n");
- }
+<INITIAL><<EOF>> { /* end of file */
+ yyterminate();
+ }

+<INITIAL>".include" { /* .include directives must be handled here */
+ yy_push_state(INCLUDE, yyscanner);
+ }

+<INCLUDE>{WS} { /* skip whitespace */ }

-<INITIAL>. { /* just echo everything else */
- fprintf(output, "%s", yytext);
- }
+<INCLUDE>{Q_STRING} { /* include this file */
+ global_state * const state = yyget_extra(yyscanner);

-".include" { /* .include directives must be handled here */
- yy_push_state(INCLUDE, yyscanner);
- }
+ char * filename = (char *)mem_sys_allocate_zeroed((yyleng - 2 + 1)
+ * sizeof (char));

-<INCLUDE>{WS} { /* skip whitespace */ }
+ strncpy(filename, yytext + 1, yyleng - 2);

-<INCLUDE>{Q_STRING} { /* include this file */
- char * filename = dupstr(yytext, yyscanner);
+ /* make sure that any error messages that occur in the .included
+ * file will report the right line number and file name.
+ */
+ fprintf(state->outfile, ".line 1\n");
+ fprintf(state->outfile, ".file %s\n", yytext); /* is quoted */

- filename[strlen(filename) - 1] = '\0';
- scanfile(filename + 1);
+ scanfile(filename, state->outfile);

- /*mem_sys_free(filename);
- */
+ /* restore the location information; we didn't count the "\n"
+ * yet that will come after the .include dir.; hence the + 1 now.
+ */
+ fprintf(state->outfile, ".line %d\n", yyget_lineno(yyscanner) + 1);
+ fprintf(state->outfile, ".file '%s'\n", state->filename);

- }
+ mem_sys_free(filename);
+ }

-<INCLUDE>{EOL} { yy_pop_state(yyscanner); }
+<INCLUDE>{EOL} { /* after .include "foo.pir", go back to the state we were in */
+ yy_pop_state(yyscanner);
+ }

+<INCLUDE>. { fprintf(stderr, "wrong scanner state\n"); }

-<*>{EOL} { /* do nothing. */ }
+<INITIAL>. {
+ fprintf(yyget_extra(yyscanner)->outfile, "%s", yytext);
+ }

%%

Navigate in group perl.cvs.parrot at sever nntp.perl.org
Previous Next


Your recent visits
Re: Mass value assigment
Re: question on software development
Re: Replacement in 3GB file
Re: Any Good SCM tool to manage Perl Code locally
Re: Any Good SCM tool to manage Perl Code locally



  
© No Copyright
You are free to use Anything, but please consult your advocate before doing so as this website
also list content from other sources which may be copyrighted.
Site Maintained by Zareef Ahmed
Powered By PHP Consultants