summaryrefslogtreecommitdiff
path: root/scripts/fix-bison.pl
blob: 2327a7ae2c5dc581af38c455160ac0ed67083972 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/usr/bin/perl
#
# Format output code generated by bison
#
# Usage:
#  bison -b foo_parser -p foo_parser_ -d -v foo_parser.y
#  perl fix-bison.pl foo_parser.tab.c
#
# Copyright (C) 2004-2014, David Beckett http://www.dajobe.org/
# Copyright (C) 2004, University of Bristol, UK http://www.bristol.ac.uk/
#

my $seen_yyerrlab1=0;
my $syntax_error_has_default=0;
my $line_offset=1; # #line directives always refer to the NEXT line

my $extension = '.bak';

sub fix($)
{
  my ($file) = @_;
  my $backup = $file . $extension;
  rename($file, $backup);
  open(IN, "$backup");
  open(OUT, ">$file");

  while(<IN>) {
    # Remove code that causes a warning
    if(/Suppress GCC warning that yyerrlab1/) {
      do {
        $_ = <IN>;
        $line_offset--; # skipped a line
      } while (!/^\#endif/);
      $line_offset--; # skipped a line
      next;
    }

    $seen_yyerrlab1=1 if /goto yyerrlab1/;

    s/^yyerrlab1:// unless $seen_yyerrlab1;

    # Do not use macro name for a temporary variable
    s/unsigned int yylineno = /unsigned int yylineno_tmp = /;
    s/yyrule - 1, yylineno\)/yyrule - 1, yylineno_tmp\)/;

    # Do not (re)define prototypes that the system did better
    if(m%^void \*malloc\s*\(%) {
      $line_offset--; # skipped a line
      next;
    }
    if(m%^void free\s*\(%) {
      $line_offset--; # skipped a line
      next;
    }

    # syntax error handler will have a default case already in Bison 3.0.5+
    $syntax_error_has_default=1 if /default: \/\* Avoid compiler warnings. \*\//;

    if(m%^\# undef YYCASE_$% and $syntax_error_has_default==0) {
      # Add a default value for yyformat on Bison <3.0.5, for coverity CID 10838
      my $line=$_;
      print OUT qq{      default: yyformat = YY_("syntax error");\n};
      $line_offset++; # extra line
      print OUT $line;
      next;
    }

    if(m%yysyntax_error_status = YYSYNTAX_ERROR%) {
      # Set yytoken to non-negative value for coverity CID 29259
      my $line=$_;
      print OUT qq{if(yytoken < 0) yytoken = YYUNDEFTOK;\n};
      $line_offset++; # extra line
      print OUT $line;
      next;
    }

    # Suppress warnings about empty declarations
    s/(^static int .*_init_globals.*);$/$1/;

    # Remove always false condition
    if(m%if \(/\*CONSTCOND\*/ 0\)%) {
      $line_offset--; # skipped a line
      $_ = <IN>;
      $line_offset--; # skipped a line
      next;
    }

    # Remove always false condition; this macro is #defined to 0
    if(m%if \(yytable_value_is_error \(yyn\)\)%) {
      $line_offset--; # skipped a line
      $_ = <IN>;
      $line_offset--; # skipped a line
      next;
    }

    # Fixup pending filename renaming, see above.
    # Fix line numbers.
    my $line=$. +$line_offset;
    s/^(\#line) \d+ (.*\.c)/$1 $line $2/;

    print OUT;
  }
}

for my $file (@ARGV) {
  fix $file;
}