#!/usr/bin/awk -f
#
# AWK-script: strip_ifdef
#
# Strips all #ifdef <key> encapsulated lines from *.c and *.h files.
#
# usage: strip_ifdef key=VERSION2 infile > outfile
#
#
# The following cases are supported (including full nesting with other ifdefs):
#
# #ifdef VERSION2
#   skipped lines
# #endif
#
# #ifndef VERSION2
#   passed lines
# #endif
#
# #ifdef VERSION2
#   skipped lines
# #else
#   passed lines
# #endif
#
# #ifndef VERSION2
#   passed lines
# #else
#   skipped lines
# #endif
#
#
# 07-apr-98   Heiko Purnhagen   (purnhage@tnt.uni-hannover.de)
#
# 07-apr-98   initial version
# 08-apr-98   fixed passing of non-key ifdefs
# 28-apr-98   added #if #elif
# 27-nov-98   fixed usage: strip_ifdef
#

# depth          0: outside any ifdef/ifndef   1..n: n-th nested ifdef
# state[depth]   0: outside   1: ifdef/ifndef (not key or in skip mode)
#                2: ifdef/ifndef else (not key or in skip mode)
#                3: ifdef key   4: ifdef key else
#                5: ifndef key   6: ifndef key else
# skip           0: pass lines   1: skip lines

BEGIN {
  depth = 0;
  state[0] = 0;
  skip = 0;
  if (ARGC == 1) {
    printf "usage: strip_ifdef key=VERSION2 infile > outfile\n" >"/dev/stderr";
    exit 1;
  }
}

{
  if (key == "") {
    printf "usage: strip_ifdef key=VERSION2 infile > outfile\n" >"/dev/stderr";
    exit 1;
  }
  if (skip == 0) {
    if ($1 == "#ifdef" || $1 == "#ifndef") {
      depth++;
      if ($2 == key) {
	if ($1 == "#ifdef") {
	  skip = 1;
	  state[depth] = 3;
	}
	else {
	  skip = 0;
	  state[depth] = 5;
	}
      }
      else {
	state[depth] = 1;
	print $0;
      }
    }
    else if ($1 == "#if") {
      depth++;
      state[depth] = 1;
      print $0;
    }
    else if ($1 == "#else") {
      if (state[depth] == 2 || state[depth] == 4 || state[depth] == 6) {
	printf "error (line %d): else else\n",NR >"/dev/stderr";
	exit -1;
      }
      if (state[depth] == 0) {
	printf "error (line %d): else without if\n",NR >"/dev/stderr";
	exit -1;
      }
      state[depth]++;
      if (state[depth] == 2)
	print $0;
      if (state[depth] == 4)
	skip = 0;
      if (state[depth] == 6)
	skip = 1;
    }
    else if ($1 == "#endif") {
      if (state[depth] <= 3)
	print $0;
      depth--;
    }
    else
      print $0;
  }
  else {
    if ($1 == "#ifdef" || $1 == "#ifndef" || $1 == "#if") {
      depth++;
      state[depth] = 1;
    }
    else if ($1 == "#else") {
      if (state[depth] == 2 || state[depth] == 4 || state[depth] == 6) {
	printf "error (line %d): else else\n",NR >"/dev/stderr";
	exit -1;
      }
      if (state[depth] == 0) {
	printf "error (line %d): else without if\n",NR >"/dev/stderr";
	exit -1;
      }
      state[depth]++;
      if (state[depth] == 4)
	skip = 0;
      if (state[depth] == 6)
	skip = 1;
    }
    else if ($1 == "#endif") {
      if (state[depth] >= 3)
	skip = 0;
      depth--;
    }
  }
  if (depth < 0) {
    printf "error (line %d): endif without if\n",NR >"/dev/stderr";
    exit -1;
  }
}

END {
  if (depth > 0)
    printf "error (line %d): endif missing\n",NR >"/dev/stderr";
  if (depth != 0) {
    printf "error: depth = %d\n",depth >"/dev/stderr";
    exit -1;
  }
  if (state[0] != 0) {
    printf "error: state[0] = %d\n",state[0] >"/dev/stderr";
    exit -1;
  }
  if (skip != 0) {
    printf "error: skip = %d\n",skip >"/dev/stderr";
    exit -1;
  }
  exit 0;
}

