#!/usr/bin/gawk -f
# 
# Rewrite the interpreter source in $1 to use GNU C extensions, writing the
# modified file to stdout.
# 
# Author: Ian.Piumarta@INRIA.Fr
#
# Last edited: 2006-10-18 10:14:33 by piumarta on emilia.local

#   Copyright (C) 1996-2004 by Ian Piumarta and other authors/contributors
#                              listed elsewhere in this file.
#   All rights reserved.
#   
#   This file is part of Unix Squeak.
# 
#   Permission is hereby granted, free of charge, to any person obtaining a copy
#   of this software and associated documentation files (the "Software"), to deal
#   in the Software without restriction, including without limitation the rights
#   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#   copies of the Software, and to permit persons to whom the Software is
#   furnished to do so, subject to the following conditions:
# 
#   The above copyright notice and this permission notice shall be included in
#   all copies or substantial portions of the Software.
# 
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#   SOFTWARE.

BEGIN {
  print "/* This file has been post-processed for GNU C */\n\n";
# print "copying first section of file" > "/dev/stderr";
  stage= 0;
}

/#include "sq.h"/ {
  print "#include \"sqGnu.h\"\n";
  next;
}

# An inlining comment means the interpreter was not inlined

/inline\: true/ {
# print NR, $0 > "/dev/stderr";
# print "" > "/dev/stderr";
# print "*** interpreter was not inlined: bailing out! ***" > "/dev/stderr";
# print "" > "/dev/stderr";
  stage= -1;
}


(stage == 0) && /^int interpret\(void\) \{/ {
# print "interpret: adding static register assignments" > "/dev/stderr";
  stage= 1;
  print;
  next;
}

(stage == 0) && /^sqInt interpret\(void\) \{/ {
# print "interpret: adding static register assignments" > "/dev/stderr";
  stage= 1;
  print;
  next;
}

(stage == 1) && /^    char\* localIP;/ {
  print "    register char* localIP IP_REG;";
  next;
}

(stage == 1) && /^register struct foo \* foo = &fum;/ {
  print "    register struct foo * foo GP_REG= &fum;";
  next;
}

(stage == 1) && /^    char\* localSP;/ {
  print "    register char* localSP SP_REG;";
  next;
}

(stage == 1) && /^    int currentBytecode;/ {
  print "    register int currentBytecode CB_REG;";
  next;
}

(stage == 1) && /^    sqInt currentBytecode;/ {
  print "    register int currentBytecode CB_REG;";
  next;
}

(stage == 1) && /^$/ {
# print "interpret: adding bytecode dispatch table" > "/dev/stderr";
  print "    JUMP_TABLE;\n";
# print "interpret: rewriting case labels and outer breaks" > "/dev/stderr";
  stage= 2;
  FS=" ";
# FS="[ 	:]+";
  next;
}

(stage == 2) && /^		case / {
  print "		CASE(" (($NF) + 0) ")";
# print "		CASE(" $3 ")";
  next;
}

(stage == 2) && /^			break;/ {
  print "			BREAK;";
  next;
}

(stage == 2) && /^\}/ {
  stage= -1;
  print;
  next;
}

(stage == 3) && /^int primitiveResponse\(/ {
  print;
# print "primitiveResponse: adding primitive dispatch table" > "/dev/stderr";
  print "    PRIM_TABLE;\n";
# print "primitiveResponse: rewriting case labels" > "/dev/stderr";
  stage= 4;
  FS=" ";
# FS="[ 	:]+";
  next;
}

(stage == 3) && /^sqInt primitiveResponse\(/ {
  print;
# print "primitiveResponse: adding primitive dispatch table" > "/dev/stderr";
  print "    PRIM_TABLE;\n";
# print "primitiveResponse: rewriting case labels" > "/dev/stderr";
  stage= 4;
  FS=" ";
# FS="[ 	:]+";
  next;
}


(stage == 4) && /^	switch \(primitiveIndex\) \{/ {
# print "primitiveResponse: adding primitive dispatch" > "/dev/stderr";
  print "	PRIM_DISPATCH;";
  print;
  next;
}

(stage == 4) && /^	switch \(foo->primitiveIndex\) \{/ {
# print "primitiveResponse: adding primitive dispatch" > "/dev/stderr";
  print "	PRIM_DISPATCH;";
  print;
  next;
}

(stage == 4) && /^	case / {
  print "	CASE(" (($NF) + 0) ")";
# print "	CASE(" $3 ")";
  next;
}

(stage == 4) && /^\}/ {
# print "copying last section of file" > "/dev/stderr";
  stage= -1;
  FS=" ";
  print;
  next;
}

# default
{
  print;
  next;
}

END {
  if (stage != -1) {
    print "#error GNUIFICATION FAILED (", stage, ")"
  }
}
