%{ #include #include #include "y.tab.h" /* Buffer for building field content */ static char field_buffer[8192]; static int field_pos = 0; void reset_field_buffer() { field_pos = 0; field_buffer[0] = '\0'; } void append_to_field(char c) { if (field_pos < sizeof(field_buffer) - 1) { /* Reserve space for null terminator */ field_buffer[field_pos++] = c; field_buffer[field_pos] = '\0'; } } void append_string_to_field(const char* s) { while (*s && field_pos < sizeof(field_buffer) - 1) { /* Reserve space for null terminator */ field_buffer[field_pos++] = *s++; } field_buffer[field_pos] = '\0'; } char* get_field_content() { char* result = strdup(field_buffer); /* NOTE: Caller must free() this memory */ if (!result) { fprintf(stderr, "Memory allocation failed in get_field_content()\n"); exit(1); /* Conservative approach: exit on memory failure */ } return result; } %} %option noyywrap %option yylineno %x ESCAPED_FIELD TEXTDATA [\x20-\x21\x23-\x2B\x2D-\x7E] COMMA \x2C CR \x0D LF \x0A DQUOTE \x22 CRLF {CR}{LF} %% {COMMA} { return COMMA_TOK; } {CRLF} { return CRLF_TOK; } {LF} { return CRLF_TOK; } {DQUOTE} { reset_field_buffer(); BEGIN(ESCAPED_FIELD); } {DQUOTE}{DQUOTE} { append_to_field('"'); } {DQUOTE} { yylval.str = get_field_content(); BEGIN(INITIAL); return FIELD_TOK; } {TEXTDATA} { append_to_field(yytext[0]); } {COMMA} { append_to_field(','); } {CR} { append_to_field('\r'); } {LF} { append_to_field('\n'); } . { append_to_field(yytext[0]); } <> { /* Handle unterminated quoted field */ yylval.str = get_field_content(); BEGIN(INITIAL); return FIELD_TOK; } {TEXTDATA}+ { yylval.str = strdup(yytext); /* NOTE: Caller must free() this memory */ if (!yylval.str) { fprintf(stderr, "Memory allocation failed in TEXTDATA rule\n"); exit(1); /* Conservative approach: exit on memory failure */ } return FIELD_TOK; } [ \t] { /* ignore whitespace outside of fields */ } . { return yytext[0]; } %%