/*
 * (c) Copyright 1993 by Panagiotis Tsirigotis
 * All rights reserved.  The file named COPYRIGHT specifies the terms 
 * and conditions for redistribution.
 */

static char RCSid[] = "$Id: common.c,v 1.4 1993/02/10 21:16:10 panos Exp $" ;

#include <varargs.h>

void exit() ;
char *malloc() ;
char *realloc() ;

#include "sio.h"

#include "defs.h"

/*
 * Skip all characters in the input until you find the character in 'c'
 */
void skip_until( fd, c )
	int fd ;
	int c ;
{
	int ic ;

	for ( ;; )
	{
		NEXT_CHAR( fd, ic ) ;
		if ( ic == SIO_EOF || ic == c )
			return ;
	}
}


/*
 * Skip procedure definition: we assume that a procedure starts with an
 * open curly bracket.
 */
void skip_bracket( fd, open_bracket, closed_bracket )
	int fd ;
	char open_bracket, closed_bracket ;
{
	int c ;
	int bracket_level = 1 ;
	int start_line = line_count ;

	while ( bracket_level > 0 )
	{
		NEXT_CHAR( fd, c ) ;
		if ( c == SIO_EOF )
			error(
				"Reached EOF while looking for '%c' (search started at line %d)\n",
					closed_bracket, start_line ) ;
		if ( c == closed_bracket )
			bracket_level-- ;
		else if ( c == open_bracket )
			bracket_level++ ;
	}
}


int next_char( fd )
	int fd ;
{
	int c ;

	NEXT_CHAR( fd, c ) ;
	if ( c == SIO_EOF )
		error( "Unexpected end of file\n" ) ;
	return( c ) ;
}


#define BUF_INCREMENT								1000

static char *outbuf ;
static int buflen ;
static int used ;
static int replace_space_with_newline ;

void printout( c )
	int c ;
{
	if ( outbuf == NULL )
	{
		buflen = BUF_INCREMENT ;
		outbuf = malloc( buflen ) ;
		if ( outbuf == NULL )
			error( "out of memory\n" ) ;
		used = 0 ;
	}

	if ( c == NEWLINE )
	{
		if ( outbuf[ used-1 ] == '-' )
		{
			used-- ;										/* remove the '-' */
			replace_space_with_newline = TRUE ;
			return ;
		}
	}
	else if ( c == SPACE && replace_space_with_newline )
	{
		c = NEWLINE ;
		replace_space_with_newline = FALSE ;
	}

	/*
	 * We only output complete lines
	 */
	if ( c != NEWLINE )
	{
		if ( used == buflen )
		{
			char *newbuf ;

			buflen += BUF_INCREMENT ;
			newbuf = realloc( outbuf, buflen ) ;
			if ( newbuf == NULL )
				error( "out of memory\n" ) ;
			outbuf = newbuf ;
		}
		outbuf[ used++ ] = c ;
	}
	else
	{
		Swrite( 1, outbuf, used ) ;
		Sputchar( 1, NEWLINE ) ;
		used = 0 ;
	}
}


void printout_flush()
{
	if ( used )
	{
		Swrite( 1, outbuf, used ) ;
		Sputchar( 1, NEWLINE ) ;
		used = 0 ;
	}
}


void start_paragraph()
{
	printout_flush() ;
	Sputchar( 1, NEWLINE ) ;
}


void error( fmt, va_alist )
	char *fmt ;
	va_dcl
{
	va_list ap ;

	va_start( ap ) ;
	Sprint( 2, "Line %d: ", line_count ) ;
	Sprintv( 2, fmt, ap ) ;
	exit( 1 ) ;
}


void decode_string( get_char, arg )
	int (*get_char)() ;
	void *arg ;
{
	int c ;
	int skip_input = FALSE ;

	for ( ;; )
	{
		if ( ! skip_input )
			c = (*get_char)( arg ) ;
		skip_input = FALSE ;

		if ( c == CLOSE_PAREN )
			return ;
		
		if ( c != BACKSLASH )
		{
			printout( c ) ;
			continue ;
		}

		/*
		 * Interpret the character after the backslash
		 */
		c = (*get_char) ( arg ) ;
		if ( c == OPEN_PAREN || c == CLOSE_PAREN )
			printout( c ) ;
		else if ( c == 't' )
			printout( TAB ) ;
		else if ( c == 'n' )
			printout( NEWLINE ) ;
		else if ( c == BACKSLASH )
			printout( BACKSLASH ) ;
		else if ( isdigit( c ) )
		{
			int i ;
			int num = NUM( c ) ;

			/*
			 * We ignore numbers; Postscript allows up to 3 digits in \ddd
			 * and we have already consumed one.
			 */
			for ( i = 0 ; i < 2 ; i++ )
			{
				c = (*get_char)( arg ) ;
				if ( isdigit( c ) )
				{
					num *= 8 ;
					num += NUM( c ) ;
				}
				else
				{
					skip_input = TRUE ;
					break ;
				}
			}

			if ( num == 013 )
			{
				printout( 'f' ) ;
				printout( 'f' ) ;
			}
			else if ( num == 016 )
			{
				printout( 'f' ) ;
				printout( 'f' ) ;
				printout( 'i' ) ;
			}
			else if ( num == 0214 ) {
				printout( 'f' ) ;
				printout( 'i' ) ;
			}
			else if ( num == 0244 )
				printout( '/' ) ;
			else if ( num == 0251 || num == 0270 )
				printout( '\'' ) ;
			else if ( num == 0252 || num == 0271 || num == 0272 )
				printout( '"' ) ;
			else if ( num == 0253 )
			{
				printout( '<' ) ;
				printout( '<' ) ;
			}
			else if ( num == 0254 )
				printout( '<' ) ;
			else if ( num == 0255 )
				printout( '>' ) ;
			else if ( num == 014 || num == 0256 )
			{
				printout( 'f' ) ;
				printout( 'i' ) ;
			}
			else if ( num == 015 || num == 0257 )
			{
				printout( 'f' ) ;
				printout( 'l' ) ;
			}
			else if ( num == 0261 )
				printout( '-' ) ;
			else if ( num == 0267 )		/* bullet point */
				printout( '*' ) ;
			else if ( num == 0273 )
			{
				printout( '>' ) ;
				printout( '>' ) ;
			}
			else if ( num == 274 )
			{
				printout( '.' ) ;
				printout( '.' ) ;
				printout( '.' ) ;
			}
			else if ( num == 0303 )
				printout( '^' ) ;
			else if ( num == 0304 )
				printout( '~' ) ;
			else if ( isascii( num ) && isprint( num ) )
				printout( num ) ;
		}
	}
}

