Revision 238 (by dpavlin, 2004/03/08 17:46:16) tagging openisis 0.9.0
#!/usr/bin/perl -w
#/*
#	openisis - an open implementation of the CDS/ISIS database
#	Version 0.8.x (patchlevel see file Version)
#	Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org
#
#	This library is free software; you can redistribute it and/or
#	modify it under the terms of the GNU Lesser General Public
#	License as published by the Free Software Foundation; either
#	version 2.1 of the License, or (at your option) any later version.
#
#	This library 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
#	Lesser General Public License for more details.
#
#	You should have received a copy of the GNU Lesser General Public
#	License along with this library; if not, write to the Free Software
#	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#	see README for more information
#EOH */

# $Id: oipc,v 1.2 2003/04/08 00:20:53 kripke Exp $
#
#	usage
#	./oipc foo.oip gcc %o && ./a.out
#	./oipc foo.oip gcc %o -shared -o foo.oip.so && ./oipl $PWD/foo.oip.so


sub mk {
	my $ifile = shift;
	my $ofile = $ifile . '.c';
	my $buf = ''; # collected strings from output mode
	my @code = ('',''); # main and global code
	my $code = 0, $state = -1; 
	# -1: file header
	# 0: stuff to output literally 
	# run code:
	#	1: in <%
	#	2: in <%=
	# global code:
	#	3: in <%!
	#	4: in <%@
	die "could not read $ifile" unless open I, $ifile;
	# transform line by line
	LIN: while (<I>) {
		if ( -1 == $state ) { # skipping initial # lines
			next if /^#/;
			$state = 0; # switch to output state
		}
		while (1) {
			if ( ! $state ) { # output up to <%
				my ($o,$s,$m,$x) = /^(.*?)(<%([=!@])?(.*))?$/s;
				if ( length $o ) {
					$o =~ s/\\/\\\\/g;
					$o =~ s/"/\\"/g;
					if ( defined $s ) {
						$buf .= '"' . $o . '"';
					} else {
						$buf .= '"' . $o . '\n"' . "\n";
					}
				}
				next LIN unless defined $s;
				$code[$code] .= "\tOIPS(\n".$buf."\t);\n" if length $buf;
				$buf = '';
				($m ||= 0) =~ y/=!@/123/;
				$state = 1+$m;
				$code = 2 < $state ? 1 : 0;
				$_ = $x;
				$code[$code] .= "\n#line ".$.."\n";
				next LIN unless length $x;
			}
			my ($x,$s,$m,$o) = /^(.*?)((!)?%>(.*))?$/s;
			$buf .= $x;
			if ( defined $s ) {
				if ( 2 == $state ) { # <%=
					if ( 1 == length $buf ) {
						if ( $buf =~ /[i-n]/ ) { # integer shorthand
							$buf = '"%d",'.$buf;
						} elsif ( $buf =~ /[u-w]/ ) { # unsigned shorthand
							$buf = '"%u",'.$buf;
						} elsif ( $buf =~ /[f-h]/ ) { # OpenIsis Field shorthand
							$buf = '"%.*s",'.$buf.'->len,'.$buf.'->val';
						}
					}
					if ( $buf =~ /^\s*"/ ) {
						$buf = 'OIPP(OIPF,'.$buf.');';
					} else {
						$buf = 'OIPS('.$buf.');';
					}
				}
				$code[$code] .= $buf;
				# don't reset print code destination if global ends with !%>
				$code = 0 unless $code && defined $m;
				$state = 0;
				if ( length $o ) {
					$buf = '';
					$_ = $o;
					next;
				}
				$buf = '"\n"';
			} else {
				$buf .= "\n";
			}
			last;
		}
	}
	close I;
	$code[0] .= "OIPS(\n".$buf.");\n" if length $buf;
	die "could not write $ofile" unless open O, '>', $ofile;
	print O '#include "oip.h"',"\n";
	print O $code[1];
	print O "OIPRUN\n";
	print O $code[0];
	print O "OIPEND\n";
	close O;
	map s/%o/$ofile/, @_;
	die 'exec '.join(' ',@_)." failed\n" unless exec @_;
}

mk @ARGV;