#!/usr/local/bin/perl
#
# Filter for turning ANSI code into [shudder] non-ANSI.
#
# Copyright 1999 by Gray Watson
#
# This file is part of the dmalloc package.
#
# Permission to use, copy, modify, and distribute this software for
# any purpose and without fee is hereby granted, provided that the
# above copyright notice and this permission notice appear in all
# copies, and that the name of Gray Watson not be used in advertising
# or publicity pertaining to distribution of the document or software
# without specific, written prior permission.
#
# Gray Watson makes no representations about the suitability of the
# software described herein for any purpose.  It is provided "as is"
# without express or implied warranty.
#
# The author may be contacted via http://www.dmalloc.com/
#
# $Id: Deansify.pl,v 1.6 1999/03/04 19:13:44 gray Exp $
#

#
# process the protoypes from $INPATH and print output to $OUTFILE
#
sub prototype {
  # read in the args to prototype
  local ($inpath, $outfile) = @_;
  
  # open the input file
  open (infile, "< $inpath") || die "Can't open $inpath: $!\n";
  
  while ( <infile> ) {
    
    # get rid of const
    # void * -> char *
    s,\bconst[ \011]\b,,g;
    s,\bvoid([ \011]+)[*],char\1\*,g;
    
    # take care of stdarg -> varargs
    # ... -> va_alist
    s,\<stdarg.h\>,\<varargs.h\>,;
    s,\.\.\.[ \011]*\),va_alist\),;
    s,(va_start[^\,]*)[^\)]*\),\1\),;
    
    #
    # is it a procedure we have?
    # special case is EXPORT void (*foo)() = NULL; which is a variable
    #
    if ( ! m,^(EXPORT|LOCAL|IMPORT|extern|static|int[ \011]+main).*\(, || m,\)[ \011]*=, ) {
      print $outfile $_;
      next;
    }
    
    # find the end of the thing
    if ( ! m,\), ) {
      @def_list = ( $_ );
      
      while ( <infile> ) {
	# get rid of const
	# void * -> char *
	s,\bconst[ \011]\b,,g;
	s,\bvoid([ \011]+)[*],char\1\*,g;
	
	@def_list = ( @def_list, $_ );
	if ( m,\), ) {
	  last;
	}
      }
      
      $_ = join ('', @def_list);
    }
    
    # do we have an empty prototype?
    # HACK: handles function call definitions
    if ( m,\(\);, ) {
      print $outfile $_;
      next;
    }
    
    # do we have a prototype already?
    if ( m,\)[ \011]*;, ) {
      # comment out the arguments
      s,\([ \011]*([^\\]),\(/\* \1,;
      s,([^\\])[ \011]*\),\1 \*/\),;
      print $outfile $_;
      next;
    }
      
    # if it is void then just comment it out
    if ( m/\([ \011]*void[ \011]*\)/ ) {
      s,\([ \011]*([^\\]),\(/\* \1,;
      s,([^\\])[ \011]*\),\1 \*/\),;
      print $outfile $_;
      next;
    }

    $func = $_;
    $func =~
      s/([^\(]*\()?[ \011]*[^,\)]* [ \011]*[*]?([^,\)]*)([,\)])/\1\2\3 /g;
    print $outfile $func;
    
    # make the prototypes
    s/[^\(]*\(([^\)]*)\)/\1;/;
    s/,/;\n/g;
    s/[ \011]+/ /g;
    s/\n+/\n/g;
    s/^ */  /g;
    s/\n *(.)/\n  \1/g;
    
    # handle va_alist -> va_dcl
    s,va_alist[ \011]*;,va_dcl,;
    
    print $outfile $_;
  }
  
  close (infile);
}

###############################################################################
# main program
###############################################################################

#
# usage message
#
if (@ARGV == 0) {
  die "Usage:  $0 file1.[ch] ...\n";
}

while ( $_ = $ARGV[0] ) {
  shift;
  
  $file = $_;
  $tfile = $file . ".t";
  
  # does the $cfile exist?
  if (! -r $file ) {
    print STDERR sprintf ("%s", "Cannot find $cfile: $!\n");
    next;
  }
  
  # remove the tilda and temp files
  unlink ( $tfile );
  
  # open the input file file, move it to a temporary one
  open (outfile, "> $tfile") || die "Can't open $tfile: $!\n";
  
  do prototype ($file, outfile);
  
  close (infile);
  close (outfile);
  
  printf ("De-ansi'ed '%s'\n", $file);
  unlink ($file . "~");
  rename ($file, $file . "~");
  rename ($tfile, $file);
}

exit (0);
