ftp.nice.ch/pub/next/text/framemaker/filters/mif2man.tar.gz#/mif2man.c

This is mif2man.c in view mode; [Download] [Up]

/*****************************************************************************/
/**       Copyright 1989 by Evans & Sutherland Computer Division            **/
/**                           Mountain View, CA                             **/
/**                                                                         **/
/**                           All Rights Reserved                           **/
/**                                                                         **/
/**    Permission to use, copy, modify, and distribute this software and    **/
/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
/**    granted, provided that the above copyright notice appear  in  all    **/
/**    copies and that both  that  copyright  notice  and  this  permis-    **/
/**    sion  notice appear in supporting  documentation,  and  that  the    **/
/**    name  of Evans & Sutherland  not be used in advertising or publi-    **/
/**    city pertaining to distribution  of the software without  specif-    **/
/**    ic, written prior permission.                                        **/
/**                                                                         **/
/**    EVANS  & SUTHERLAND  DISCLAIMS  ALL  WARRANTIES  WITH  REGARD  TO    **/
/**    THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILI-    **/
/**    TY AND FITNESS, IN NO EVENT SHALL EVANS &  SUTHERLAND  BE  LIABLE    **/
/**    FOR  ANY  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY  DAM-    **/
/**    AGES  WHATSOEVER RESULTING FROM  LOSS OF USE,  DATA  OR  PROFITS,    **/
/**    WHETHER   IN  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS    **/
/**    ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE  OR PER-    **/
/**    FORMANCE OF THIS SOFTWARE.                                           **/
/*****************************************************************************/
/****************************************************************/
/* mif2man							*/
/* 	Convert a frame MIF file troff format using the man 	*/
/* 	macros.  Only certain formatting information is 	*/
/* 	preserved.						*/
/*								*/
/* Written by: Karl Rowley, 12/21/88				*/
/*             Evans & Sutherland Computer Division		*/
/*	       (Don't ask use for any help, though. Sorry.)     */
/****************************************************************/
/* History:							*/
/* 	0.1	Extract String's in order given in MIF 		*/
/* 		file.						*/
/*	0.2	Add paragraphs.					*/
/*	0.3	Add bold, italics, bold-italics, regular fonts	*/
/*	0.4	Add interpretation of catalog defs.		*/
/*	0.5	Output text with catalog information, including */
/*		tabs, first indendation, and indendation.       */
/* 	0.6 	Interpret back-slashes in input and output  	*/
/*		correctly.					*/
/*	0.7	Add HardReturn and HardSpace.  Ignore strings   */
/*		in TextLine's.  Add other special characters    */
/*		including single and double quotes. ( Textlines */
/* 		were a problem with tbl(1) ).			*/
/* 	0.8	Add NAME section heading at top of page.        */
/*		Output periods specially to avoid confusing     */
/* 		roff when strings look like macros.		*/
/* 	0.9	Allow indentation info. for current paragraph 	*/
/*		to be changed on-the-fly without affecting the  */
/*		catalog information (tbl (1) was a problem).	*/
/*	1.0 	Tested on a number of ES-1 man pages.		*/
/****************************************************************/

#include <stdio.h>
#include <ctype.h>

#include "table.h"
#include "mandefs.h"
#include "mifparse.h"
#include "catalog.h"

#define output(string) printf(string)
#define TRUE 1
#define FALSE 0

/**********************************/
/* Variables                      */


/* Context stack for MIF interpretter */

#define STACKSIZE 2000

int pool[STACKSIZE];	/* Memory pool for stack */
int *stack;		/* Stack pointer */

/* Modes for the interpretter */

int catalog_mode;	/* Loading catalog information */
int font_mode;		/* Loading information for a font */
int textline_mode;	/* inside of a TextLine */

/* Current font information */
struct {
	int bold;
	int italic;
	} font;

int strcount;		/* count of strings */

int n_pgfs;
int current_tab;

CAT_ENTRY *current_pgf;	/* pointer to current pgf style */

char *filename;		/* file name currently being processed */

/*******************************/
/* Push a token onto the stack */
push( token )
int token;
{
	*++stack = token;
}

/******************************/
/* Pop a token from the stack */
int pop()
{
	return( *stack-- );
}

/************************/
/* Initialize the stack */
init_stack()
{
	stack = &pool[0];
	*stack = NONE;
}


/****************************************************/
/* Output any font information needed for text      */
output_font()
{
	if ( font.italic ) {
                output ( ROF_ITALIC );
        }
        else if ( font.bold ) {
                output( ROF_BOLD);
	}
	else {
		output( ROF_NORMAL );
	}
}


/***********************************************/
/* Functions to add and search catalog tables  */

/* Add an entry to the catalog */
CAT_ENTRY *
new_cat_pgf( name )
	char *name;
{
        CAT_ENTRY *entry;
        entry = &cat_table[n_pgfs++ ];
        strcpy( entry->name, name );
	/* initialize some other fields */
	entry->ntabs = 0;
	entry->bold = FALSE;
	entry->italic = FALSE;
	entry->firstindent = 0;
	entry->indent = 0;
        return( entry );
}

/* Get an entry from the catalog */
CAT_ENTRY *
get_cat_pgf( name )
	char *name;
{
	int i;
	static CAT_ENTRY none;
        for ( i = 0; i <= n_pgfs; i++ ) {
                if ( strcmp( cat_table[i].name, name ) == 0 ) 
                        return( &cat_table[i] );
        }
	/* Not found -- make a dummy entry on the fly */
	none.ntabs = 0;
        return ( &none );
}

int
search_table( string , table )
	char *string;
	RECORD *table;
{
	char *p;
        int i = 0;
	RECORD *r;
        p = string;
	while ( *p == ' ' )
                p++;
	while ( table[i].name[0] != '\0' ) {
                if ( strlen( p ) == strlen(table[i].name ) ) {
                        if ( strncmp( p,table[i].name,
                           strlen( table[i].name) ) == 0 ) {
                                return( table[i].value);
                        }
                }
		i++;
        }
        return OTHER;
}


/*******************************************/
/* Determine the ID of a MIF function call */
int 
getfuncid( line )
	char *line;
{
	char *p;
	int i;
	p = line;
	while ( *p == ' ' ) 
		p++;
	for ( i = 0; i <= (sizeof( token_table )/sizeof(RECORD) -1 )
			 ; i++ ) {
		if ( strlen( p ) == strlen(token_table[i].name ) ) {
			if ( strncmp( p, token_table[i].name, 
			   strlen( token_table[i].name) ) == 0 ) {
				return( token_table[i].value);
			}
		}
	}
	return OTHER;
}

/*********************************************/
/* Parse a line of input */
parse (string, line )
	char *string;
	INLINE *line;
{
	static char buff[100];
	char *p;
	char *f;
	p = string;
	if ( *p == '#' ) {
		(*line).type = COMMENT;
		return;
	}
	while ( *p == ' ' ) 
		p++;
	if ( *p == '>' ) {
		(*line).func = END;
		return;
	}
	while ( *p == '<' )
		p++;
	f = p;
	while ( *p != ' ' & *p != '\n' ) 
		p++;
	while ( *p == ' ' ) {
		*p = '\0';
		p++;
	}
	(*line).func = search_table(f, &token_table[0] );
	if ( *p == '\n' ) {
		(*line).type = FUNC;
		return;
	}
	else {
		char *p1;
		p1 = buff;
		(*line).args = buff;
		if ( *p == '`' ) {
			while ( ( *p != '\'')  & (*p != '\n') & (*p != '\0') ) 
				*p1++ = *p++;
			*p1++ = *p;
			*p1 = '\0';
		} 
		else {
			while ( ( *p != '\n')  & (*p != '\0') & (*p != ' ') & 
			   (*p != '>') ) 
				*p1++ = *p ++;
			*p1 = '\0';
		}
		return;
	}
}


/*******************************************/
/* Extract a string from within single quotes */
char*
extract_string( arg )
	char *arg;
{
	static char buff[100];
	char *p, *p1;
	p = arg;
	/* go past the first single quote mark */
	while (*p != '`'  & *p != '\n' &  *p != '\0')  
		p++;
	if ( *p != '\n' & *p != '\0' ) 
		p++;
	/* copy until the next quote mark */
	p1 = buff;
	while ( *p != '\'' & *p != '\0' ) 
		*p1++ = *p++;
	*p1 = '\0';
	return buff;
}

/************************************************/
/* Output the characters from a string          */
output_string( arg )
	char *arg;
{
	char *p, *p1;
	char buff[120];    /* buffer for upper case conv */
	p = extract_string( arg );
	/* don't bother outputting the null string */
	if ( *p != '\n' & *p != '\0' ) {
		/* Certain tags from the catalog require */
		/* special treatment here.               */
		switch( search_table( 
			current_pgf->name, special_tags) ) {
		case HEADING:
			/* Convert to all bold */
			p1 = buff;
			while ( *p != ':' & *p != '\0' ) {
				if ( islower(*p) )
					*p1 = toupper( *p );
				else 
					*p1 = *p;
				p1++;
				p++;
			}
			/* Drop the final ':' character */
			*p1 = '\0';
			/* Output the .SH macro with string */
			output( MANSH );
			output( buff );
			break;
		default:
			p1 = buff;
			/* Catch the . char to keep roff */
			/* from getting confused by it as the */
			/* first character of a word */
			if ( *p == '.' ) { /* output the period by itself */
				output_font();
				output( "\\&." );
				p++;
			}
			/* if ( ( *p == '.') & ( *(p+1) != ' ' ) &
			   (*(p+1) != '\0') ) {
				*p1++ = ' ';
				*p1++ = '.';
				p++;
			} */
			/* Interpret any other special characters */
			while ( *p != '\0' ) {
				switch ( *p ) {
				case '\\':
					/* output double-backslash */
					*p1++ = '\\';
					p++;
					break;
				case '%':
					/* output %% for printf */
					*p1++ = '%';
					*p1++ = '%';
					p++;
					break;
				default:
					/* output char */
					*p1++ = *p++;
					break;
				}
			}
			*p1 = '\0';
			output_font();
			output ( buff );
			break;
		}
	}
}

/***********************************************/
/* Test if the value of an argument is Yes     */
int
isyes( arg )
	char *arg;
{
	if ( arg[0] == 'Y' & arg[1] == 'e' & arg[2] == 's' ) 
		return TRUE;
	else
		return FALSE;
}

/**************************************************/
/* Output a special character                     */
output_char( arg )
char *arg;
{
	switch ( search_table( arg, char_table ) ) {
	case ENDASH:
		output_font();
		output( ROF_DASH );
		break;
	case TAB:
		output( ROF_TAB );
		break;
	case HARDSPACE:
		output ( ROF_HARDSPACE );
		break;
	case HARDRETURN:
		output( "\n" );
		output( ROF_BR );
		output( "\n" );
		break;
	case CHAR210:
		output_font();
		output( ROF_DQUOTE );
		break;
	case CHAR211:
		output_font();
		output( ROF_DQUOTE );
                break;
	case CHAR212:
		output_font();
		output( ROF_LQUOTE );
		break;
	case CHAR213:
		output_font();
		output( ROF_RQUOTE );
		break;
	}
}


/*********************************************************/
/* Get a size from a text string.  Lengths are stored    */
/* internally and added as MIF lenghts to avoid problems */
/* lining up tabs and indented paragraphs.               */
int
get_length ( string )
	char *string;
{
	int length = 0;
	int decimal = FALSE;   /* is there a dec. in the string */
	char *p;
	p = string;
	while ( ( *p >= '0' & *p <= '9') | *p == '.' ) {
		if ( *p >= '0' & *p <= '9' ) {
			length *= 10;
			length += *p - '0';
		}
		else if ( *p == '.' ) {
			decimal = TRUE;
		}
		p++;
	}
	if ( !decimal ) 
		length *= 100;
	return length;
}

/****************************************************/
/* Extract the command name from the argument given */
/* on the command line.  This is a less than ideal  */
/* way to get this information.                     */

char *
get_name()
{
	char *p, *p1;
	static char buff[50];
	p1 = buff;
	p = filename;
	while ( *p != '.' & *p != '\0' )
		*p1++ = *p++;
	*p1 = '\0';
	return buff;
}

/***************************************************/
/* Get the section number for this man page.       */

char *
get_section( str )
	char *str;
{
	char *p, *p1;
	static char buff[10];
	p = filename;
	p1 = buff;
	/* go past the first '.' */
	while ( *p != '\0' & *p != '.' )  p++;
	p++;
	while ( *p != '\0' & *p != '.' ) 
		*p1++ = *p++;
	*p1 = '\0';
	return buff;
}

/*******************************************/
/* Extract the date from the first string. */

char *
get_date( str )
	char *str;
{
	char *p, *p1;
	static char buff[50];
	int i;
	p = str;
	p1 = buff;
	/* Go to the second ';' */
	while ( *p != '\0' & *p != ';' ) p++;
	p++;
        while ( *p != '\0' & *p != ';' ) p++;
	p++;
	/* Skip leading blanks */
	while ( *p != '\0' & *p == ' ' ) p++; 
	/* Copy date characters */
	while  ( *p != '\0' & *p != ')' ) 
		*p1++ = *p++;
	*p1 = '\0';
	return buff;
}

/*************************************************/
/* Create the line with the .TH macro            */

do_th(  str )
	char *str;
{
	output( MANTH );
	output( get_name() );
	output( " " );
	output( get_section(str) );
	output( " " );
	output( "\"" );
	output ( get_date(str) );
	output( "\"" );
	output ( "\n" );
}

/**********************************************/
/* Output a roff comment                      */

do_comment( str )
	char *str;
{
	char buff[100];
	output( ROF_COMMENT );
	output( extract_string( str) ) ;
	output ( "\n" );
}

/*******************************************************/
/* Output a length for troff output.  Input is a MIF   */
/* length in 100'ths of inches.  The length is         */
/* divided by a fudge factor since font size in        */
/* nroff/troff is different from MIF (i.e. adjustment  */
/* is necessary to make tabs / paragraphs look good).  */
/* WARNING:  Changing this fudge factor may cause      */
/* problems with tab/indentation allignment.           */

output_length( points )
	int points;
{
	printf("%4.1fi", ( (float) points / 75.  )  );
}

/****************************************************/
/* Output pgf style                                 */
output_pgfstyle() 
{
int i;
if ( strcount > 2 ) {
	/* set indents to new values */
	output ( ROF_IN );
	output_length( current_pgf->indent );
        output( "\n" );
        output( ROF_TI );
        output_length(
                 current_pgf->firstindent );
        output( "\n" );
        /* Set tabs for this style, if any */
        if ( current_pgf->ntabs > 0 ) {
             output( ROF_TA );
            for ( i = 0; i<=
            current_pgf->ntabs-1; i++ ) {
                output_length(
                     current_pgf->tabs[i] -
                     current_pgf->firstindent );
                output( " " );
            }
            output( "\n" );
	}
}
}

CAT_ENTRY *
copy_pgf( input )
	CAT_ENTRY *input;
{
	int i;
	static CAT_ENTRY outcat;
	strcpy( outcat.name, input->name );
	outcat.bold = input->bold;
	outcat.italic = input->italic;
	outcat.firstindent = input->firstindent;
	outcat.indent = input->indent;
	outcat.ntabs = input->ntabs;
	for ( i=0; i <= input->ntabs -1; i++ )
		outcat.tabs[i] = input->tabs[i];
	return &outcat;
}

/***************************/	
/* Process a line of input */

int 
process(string)
	char* string;
{
	int i;
	INLINE line;
	int fudge;
	int stacktop;
	fflush( stdout );
	parse( string, &line );
	if ( line.type == COMMENT ) 
		return;
	if ( line.func == END ) {
		stacktop = pop();
		/* Complete actions for some functions */
		switch (stacktop ) {
		case FONT: 	
			font_mode = FALSE;
			break;
		case CATALOG:
			catalog_mode = FALSE;
			break;
		case PARALINE:
			break;
		case PARA:
			output( "\n" );
			break;
		case TEXTLINE:
			textline_mode = FALSE;
		}
		return;
	}
	/* 
	 * MIF functions without args. are pushed onto the 
	 * interpretter stack.
	 */
	if ( line.type == FUNC ) 
		push ( line.func );
	switch ( line.func ) {
	case STRING:
		/* 
		 * Don't output strings in TextLine statements.
		 */
		if ( ! textline_mode ) {
			strcount++;
			/* 
			 * The first few strings are special cases.  
			 * This would have to be changed to produce  
			 * general roff output without being specific
			 * for man pages.
			 */
			if ( strcount == 1 ) {
				do_comment( line.args );
				do_th( line.args );
				break;
			}
			if ( strcount == 2 ) {
				do_comment( line.args );
				break;
			}
			if ( strcount == 3 ) {   /* output section heading */
				output ( MANSH );
				output ( "NAME" );
				output ( "\n" );
			}
			/* 
			 * Output the text of the string.  Special 
			 * tags are handled by output_string().
			 */
			output_string( line.args );
		}
		break;				
	case PARA:
		/* 
		 * Set font style to default to start with.
		 */
		font.bold = FALSE;
		font.italic = FALSE;
		/* Output begin paragraph */
		if ( strcount > 2 ) { 
			/* set temp. indent for first line */
			output ( ROF_TI );
			output_length( current_pgf->firstindent );
			output( "\n" );
			output( ROF_SP );
			output( "\n" );
		}
		break;
	case PARALINE:
		break;
	case FONT:
		font_mode = TRUE;
		break;
	case FPLAIN:
		if ( font_mode ) 
			if ( isyes (line.args ) ) {
				font.bold = FALSE;
				font.italic = FALSE;
			}
		break;
	case FBOLD:
		if ( font_mode ) 
			if ( isyes( line.args ) ) {
				font.bold = TRUE;
			}
			else
				font.bold = FALSE;
		break;		
	case FITALIC:
		if ( font_mode ) 
			if ( isyes ( line.args ) ) 
				font.italic = TRUE;
			else
				font.italic = FALSE;
		break;
	case CHAR:
		output_char( line.args );
		break;
	case CATALOG:
		catalog_mode = TRUE; 
		break;
	case PGF:
		break;
	case PGFTAG:
		fflush(stdout);
		if ( catalog_mode ) {
			current_pgf = new_cat_pgf( 
				extract_string ( line.args  ) );
		}
		else {
			current_pgf = copy_pgf( get_cat_pgf(
				extract_string (line.args) ) ) ;
			output_pgfstyle();
		}
		break;
	case TABSTOP:
		break;
	case TSX:
		current_pgf->tabs[current_pgf->ntabs++] = 
			get_length( line.args);
		break;
	case TSTYPE:
		break;
	case PGFLINDENT:
		current_pgf->indent = get_length( line.args );
		if ( ! catalog_mode )  /* on the fly setting */
			output_pgfstyle();
		break;
	case PGFFINDENT:
		current_pgf->firstindent = get_length( line.args );
		if ( ! catalog_mode ) 
			output_pgfstyle();
		break;
	case TEXTLINE:
		textline_mode = TRUE;
		break;
	case OTHER:
	default:
		break;
	}
}

/************************************************/
/* Extract a command name from a file name      */

char *
command_name (file )
	char *file;
{
	return( file);
}

/***************************************************/
/* Output the prologue for any man page            */

output_prologue()
{
	/* set pgf style to ragged-right */
	output( ROF_RAGGED );
	output( "\n" );
	output( ROF_NH );
	output( "\n" );
}

/***********************************************/
/* Initialize variables      			*/

init() 
{
	/* Set the initial font style to plain */
	font.bold = FALSE;
	font.italic = FALSE;
	/* Initialize the context stack */
	init_stack();
	/* Initialize string counter for special cases */
	strcount = 0;
	catalog_mode = FALSE;
	font_mode = FALSE;
	n_pgfs = 0;
	current_tab = 0;
}

/************************************************/
/* Translate from MIF to man format		*/

translate(file ) 
FILE *file;
{
        char line[120];
	output_prologue();
        while ( fgets(line, 120,file) != NULL ) {
                process( line );
        }
}


/***********************************************/

main(argc, argv )
int argc;
char *argv[];
{
	FILE *infile;
	if ( argc !=2 ) {
		fprintf(stderr, "Usage: mif2man file\n");
		exit(1);
	}
	filename = argv[1];
	if ( (infile = fopen(argv[1], "r") ) == NULL ) {
		perror(argv[1]);
		exit();
	}
	init();
	translate(infile );
}


These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.