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.