1#!/usr/bin/perl
2#
3# Format output generated by flex 2.5.31
4#
5# Usage:
6#  flex -o$output $input
7#  perl fix-flex $output > $tmp
8#  mv $tmp $output
9#
10# (C) Copyright 2004-2014 Dave Beckett http://www.dajobe.org/
11# (C) Copyright 2004 University of Bristol
12#
13
14my $line_offset = 1; # #line directives always refer to the NEXT line
15
16print <<'EOT';
17#ifdef HAVE_CONFIG_H
18#include <rasqal_config.h>
19#endif
20
21#ifdef WIN32
22#include <win32_rasqal_config.h>
23#endif
24
25EOT
26$line_offset += 8; # added 8 lines above to output
27
28my $debug = 0;
29
30# Lexer symbol prefix such as 'turtle_lexer_'
31my $prefix = undef;
32# Current function or undef if out of function
33my $cur_function = undef;
34# State for current function for rules to use.
35my(%fn_state);
36
37while(<>) {
38  # find lexer prefix
39  if(!defined($prefix) && /^void\s*(.+?)restart\s*\(.*;$/) {
40    $prefix = $1;
41    warn "$.: Lexer prefix $prefix\n"
42	if $debug > 0;
43  }
44
45  # Remove generated yy_fatal_error declaration and definition to avoid warnings about unused/non-defined static function
46  # declaration
47  if(/^static void yy_fatal_error\s*\(.*\)\s*\;\s*$/) {
48    $line_offset--; # skipped 1 line
49    next;
50  }
51  # definition
52  if(/^static void yy_fatal_error\s*\(.*\)\s*[^\;]\s*$/) {
53    do {
54      $_=<>;
55      $line_offset--; # skipped 1 line
56    } while(!/^}/);
57    $line_offset--; # skipped 1 line
58    next;
59  }
60
61  # Replace calls to yy_fatal_error("msg", yyscanner) to YY_FATAL_ERROR("msg") macro
62  s/(^\s*)yy_fatal_error\s*\(\s*(\".*\")\s*,\s*yyscanner\s*\)/$1YY_FATAL_ERROR($2)/;
63
64  # flex has %option nounistd however it does not work in 2.5.31
65  # It is safe to add yet another wrapper.
66  if(m%^(\#include \<unistd.h\>)$%) {
67    $_=<<"EOT";
68#ifndef YY_NO_UNISTD_H
69$1
70#endif
71EOT
72    $line_offset += 2; # added 2 lines to output
73  }
74
75  # Fix .[ch] line references because we have added lines to it
76  my $line = $. + $line_offset;
77  s/^#line \d+ (\".*\.[ch]\")/#line $line $1/;
78
79  # Fix signed / unsigned comparison gcc 4.x warning:
80  #   int n : in the macro YY_INPUT definition
81  #   (size_t)num_to_read : which is silly since num_to_read is an int!
82  s/yyg->yy_n_chars, \(size_t\) num_to_read \)/yyg->yy_n_chars, num_to_read \)/;
83
84
85  # Match prefixed functions and a couple of static ones starting yy_
86  if(!defined($cur_function) && /^.*?((?:${prefix}|yy_)\w+)\s+\((.*)$/) {
87    my($f,$rest)=($1,$2);
88    if($rest !~ /;$/) {
89      $cur_function=$1;
90      warn "$.: Now in $cur_function: $_\n"
91	  if $debug > 1;
92      %fn_state=();
93    }
94  } elsif(defined($cur_function) && /^\}/) {
95    warn "$.: End of $cur_function\n"
96	if $debug > 1;
97    $cur_function = undef;
98    %fn_state=();
99  }
100
101  # Fix declaration of signed 'i' operating over range of yy_size_t
102  if($cur_function eq $prefix."_scan_bytes") {
103    s/int i;/yy_size_t i;/;
104  }
105
106  # Add $prefix_cleanup() call at the end of $prefix_lex_destroy()
107  # find the start of lex_destroy function definition and capture prefix
108  # look for lexer_free(yyscanner, yyscanner) statement within the function and place the cleanup call before it
109  if($cur_function eq $prefix."lex_destroy") {
110    if(/(^\s*)(${prefix}free\s*\(\s*yyscanner\s*,\s*yyscanner\s*\)\s*\;)\s*$/) {
111      $_=<<"EOT";
112$1/* clean up leaks if any before freeing yyscanner */
113$1${prefix}cleanup(yyscanner);
114$1$2
115EOT
116      $line_offset += 2; # added 2 lines to output
117    }
118  }
119
120  if($cur_function eq $prefix."_switch_to_buffer" ||
121     $cur_function eq $prefix."restart" ||
122     $cur_function eq $prefix."push_buffer_state") {
123    if(!exists($fn_state{'seen_ensure'})) {
124      s%(^\s*if\s*\(\s*!\s*)YY_CURRENT_BUFFER(\s*\)\s*\{.*$)%${1}yyg->yy_buffer_stack${2}%;
125      if(m%^\s*${prefix}ensure_buffer_stack\s*\(%) {
126	$fn_state{'seen_ensure'} = 1;
127      }
128    } else {
129      # In condition with whitespace
130      s%(\s+)YY_CURRENT_BUFFER(\s+)%${1}YY_CURRENT_BUFFER_LVALUE${2}%;
131      # In parameter or condition
132      s%([,\(])YY_CURRENT_BUFFER([,\)])%${1}YY_CURRENT_BUFFER_LVALUE${2}%;
133    }
134  }
135
136  if($cur_function eq 'yy_get_next_buffer') {
137    if(!exists($fn_state{'seen_yyinput'}) &&
138       m%^\s*YY_INPUT\(%) {
139      $fn_state{'seen_yyinput'} = 1;
140    } elsif(exists($fn_state{'seen_yyinput'})) {
141      # Remove dead code after YY_INPUT - which is a return NULL
142      s%^\s*YY_CURRENT_BUFFER_LVALUE->yy_n_chars\s*=\s*yyg->yy_n_chars;%%;
143    }
144  }
145
146  if($cur_function eq $prefix.'pop_buffer_state') {
147    # Change last if use of YY_CURRENT_BUFFER macro to unconditional value
148    s%^(\s*if \(\s*)YY_CURRENT_BUFFER(\s*\)\s*\{.*)$%${1}YY_CURRENT_BUFFER_LVALUE${2}%;
149  }
150
151  print;
152}
153