#!/usr/bin/gawk -f

############################################################################
#
# Script for filtering TRACE_ENTRY(), TRACE_EXIT() and TRACE_EXIT_RES()
# statements from a patch.
#
# Copyright (C) 2009 Bart Van Assche <bvanassche@acm.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation, version 2
# of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
############################################################################

function categorize_line(line) {
  is_blank = 0
  is_trace_entry = 0
  is_trace_exit = 0
  is_label = 0
  is_return_void = 0
  is_brace_at_start_of_line = 0
  if (line ~ "^+$")
    is_blank = 1
  else if (line ~ "^+\tTRACE_ENTRY\\(\\);$")
    is_trace_entry = 1
  else if (line ~ "^+\tTRACE_EXIT\\(\\);$" \
           || line ~ "^+\tTRACE_EXIT_RES\\(.*\\);$" \
           || line ~ "^+\tTRACE_EXIT_HRES\\(.*\\);$")
    is_trace_exit = 1
  else if (line ~ ":$")
    is_label = 1
  else if (line ~ "^+\treturn;$")
    is_return_void = 1
  else if (line ~ "^+}$")
    is_brace_at_start_of_line = 1
}

# Leave out TRACE_ENTRY() and the blank line below it and also TRACE_EXIT()
# and the blank line before it.
function print_conditionally() {
  if (previous_is_trace_entry                                  \
      || (before_previous_is_trace_entry && previous_is_blank) \
      || previous_is_trace_exit                                \
      || (previous_is_blank && is_trace_exit)                  \
      || (!before_previous_is_label                            \
          && previous_is_return_void                           \
          && is_brace_at_start_of_line))
  {
    # print "deleted", previous_line
    lines_deleted++
    reverse_shift_state_variables()
  }
  else
  {
    # printf "[%d] %s\n", lines, previous_line
    line[lines++] = previous_line
  }
}

function shift_state_variables(line) {
  previous_line                  = line
  before_previous_is_blank       = previous_is_blank
  before_previous_is_trace_entry = previous_is_trace_entry
  before_previous_is_trace_exit  = previous_is_trace_exit
  before_previous_is_label       = previous_is_label
  previous_is_blank              = is_blank
  previous_is_trace_entry        = is_trace_entry
  previous_is_trace_exit         = is_trace_exit
  previous_is_label              = is_label
  previous_is_return_void        = is_return_void
}

function reverse_shift_state_variables() {
  previous_is_blank       = before_previous_is_blank
  previous_is_trace_entry = before_previous_is_trace_entry
  previous_is_trace_exit  = before_previous_is_trace_exit
  previous_is_label       = before_previous_is_label
}

function reset_hunk_state_variables() {
  lines                          = 0
  lines_deleted                  = 0
  first_line_of_hunk             = 1
  before_previous_is_blank       = 0
  before_previous_is_trace_entry = 0
  before_previous_is_trace_exit  = 0
  before_previous_is_label       = 0
  previous_is_blank              = 0
  previous_is_trace_entry        = 0
  previous_is_trace_exit         = 0
  previous_is_label              = 0
  previous_is_return_void        = 0
}

function dump_lines() {
  # Detect empty hunks
  first_modif = -1
  for (i = 0; i < lines; i++)
  {
    if (line[i] ~ "^[+-]")
    {
      first_modif = i
      break
    }
  }

  # printf "dump_lines(): lines = %d, first_modif = %d\n", lines, first_modif

  # Dump line[] as a hunk, but only if the hunk is not empty.
  if (first_modif >= 0)
  {
    if (h[0] != "")
      printf "@@ -%d,%d +%d,%d @@%s\n",h[1],h[2],h[3],h[4]-lines_deleted,h[5]
    for (i = 0; i < lines; i++)
      print line[i]
  }
  reset_hunk_state_variables()
}

BEGIN {
  reset_hunk_state_variables()
}

{
  # If the line currently being processed is a hunk header, print all lines
  # that were stored in the array line[] since the last hunk header was read.
  if (match($0, "^@@ -([0-9]*),([0-9]*) \\+([0-9]*),([0-9]*) @@(.*)$"))
  {
    categorize_line("")
    print_conditionally()
    dump_lines()
    match($0, "^@@ -([0-9]*),([0-9]*) \\+([0-9]*),([0-9]*) @@(.*)$", h)
  }
  else
  {
    if (first_line_of_hunk)
      first_line_of_hunk = 0
    else
    {
      categorize_line($0)
      print_conditionally()
    }
    shift_state_variables($0)
  }
}

END {
  categorize_line("")
  print_conditionally()
  dump_lines()
}

# Local variables:
# indent-tabs-mode: nil
# c-basic-offset: 2
# End:
