home *** CD-ROM | disk | FTP | other *** search
- #define LEN 256
- #define ORDERED 1
- #define SIMPLE 2
- #define BULLET 3
-
- #include <ctype.h>
- #define TRUE 1
- #define FALSE 0
-
- char chdtText[LEN];
- char chdthdText[LEN];
- char chAppendBuffer[LEN * 4];
-
- int append = 0;
- int bExample = FALSE;
- int num_styles = 0;
- int ii_lineno = 1;
- int ii_list_type = 0;
- int ii_list_order = 1;
- int bfirst = TRUE;
-
- FILE *fp_rtf, *fp_ipf, *fp_err;
-
-
- int isstring(ch)
- char ch;
- {
- if ( isalnum(ch) || ((ch) == '_') || ((ch) == ' '))
- return(TRUE);
- else
- return(FALSE);
- }
-
- //
- // Main will take 1 or two arguements.
- // With no arguements, the input file is assumed to be 'sample.ipf'
- // The first arguement [if it exists] is the input file name.
- // The second arguement, regardless of what it is, specifies
- // 'debug mode' which prints tokens as they are read and intermixes
- // this with the RTF output.
- //
- // The output is always out.rtf.
- // stderr may be redirected. The default is the console.
- //
- main( argc, argv)
- int argc;
- char *argv[];
- {
- int ii;
- int ii_token;
- int ii_prev_token = 0;
- char *input;
- int debug = FALSE;
-
- memset( chAppendBuffer, 0x00, LEN * 4);
-
- ii = 0;
-
- if (argc > 1)
- input = argv[1];
- else
- input = "sample.ipf";
-
- if (argc > 2)
- debug = TRUE;
-
- fp_ipf = freopen( input, "rt", stdin);
- fp_rtf = freopen( "out.rtf", "w", stdout);
- fp_err = stderr;
-
- //
- // Opening RTF commands. Note that :userdoc is ignored when found.
- //
- do_begin();
-
- while (ii_token = yylex())
- {
-
- //
- // Comments are eaten, thereby cleaning up debug output.
- // The newline following the comment is eaten here as well.
- //
- if (ii_token == COMMENT)
- {
- if ((ii_token = yylex()) == NL)
- {
- ii_lineno++;
- ii_token = yylex();
- }
- }
-
- //
- // Print that token if we are debugging.
- //
- if (debug)
- debug_token( fp_rtf, ii_token);
-
- //
- // 'Append' mode is only entered when processing
- // hypertext *outside* of a list item.
- //
- // We customize the parsing of hypertext and we need the
- // entire string from :hpt thru :ehpt.
- //
- if ( append )
- {
- if ( ii_token == EHPT )
- {
- append = 0;
- }
- else
- strcat( chAppendBuffer, yytext);
-
- continue;
- }
-
- switch( ii_token)
- {
- case COMMENT: break;
-
- // Note that the new line will not effect the text.
- case COLON: fprintf( fp_rtf, ":\n", yytext); break;
-
- // A newline is treated as whitespace in IPF, but not
- // RTF. Insert that space!
- case NTEXT: fprintf( fp_rtf, "%s \n", yytext); break;
-
- // I keep track of newlines but don't use it yet.
- // enhanced error reporting needs this.
- case NL:
- ii_lineno++;
- if (bExample)
- fprintf( fp_rtf, "\\par\n", yytext);
- break;
-
- case HDR: do_hdr(); break;
-
- // Windows help doesn't differentiate between primary
- // and secondary indexes.
- case NDX1: do_ndx(); break;
- case NDX2: do_ndx(); break;
-
- case HPT: append = 1; break;
- case EHPT: break;
-
- case PARA: fprintf( fp_rtf, "\\par\n"); break;
-
- case FNREF: do_hpt( 1); break;
- case HDREF: do_hpt( 2); break;
-
- case STYLE: do_style(); break;
- case ESTYLE: do_estyle(); break;
-
- // I do not honor margin requests at present.
- // Partly because I don't know how to convert from
- // IPF margin amounts to the correct figure in
- // twips.
- case MARGIN: break;
-
- // I do not honor 'nt' commands, except to insert this
- // string.
- case NOTE: fprintf( fp_rtf, "Note: "); break;
- case ENOTE: break;
-
- // I can do nothing for examples, really.
- case XMP: do_xmp(); break;
- case EXMP: do_exmp(); break;
-
- // I ignore the compact option, as well as lists-in-lists.
- // This handles simple, ordered, and bullet lists.
- case SL: do_list(); break;
- case SLC: do_list(); break;
-
- case DL: break;
-
- case EDL:
- case ESL:
- case EPARML:
- do_endlist();
- break;
-
- // Save the dthd text.
- case DTHD:
- while ((ii_token = yylex()) != NTEXT) ;
- strcpy( chdthdText, yytext);
- break;
-
- // this requires a preceeding dthd.
- case DDHD:
- while ((ii_token = yylex()) != NTEXT) ;
- do_ddhd();
- break;
- // Process a list item. This gets involved due to
- // embedded styles and hypertext.
- case LI: do_li(ii_list_type); break;
- case DT: do_li(DT); break;
- case DD: do_li(DD); break;
-
- case PARML: break;
- case PT: break;
- case PD: break;
-
- // runin is ignored.
- case ARTWORK: do_art(); break;
-
- case FN: do_fn(); break;
- case EFN: fprintf( fp_rtf, "\\par\n"); break;
- case USERDOC: break;
- case EUSERDOC: fprintf( fp_rtf, "}"); return(0);
- }
-
- // historical, and it might be useful one day.
- ii_prev_token = ii_token;
-
- }
- }
-
- //
- // Process an index command.
- //
- do_ndx()
- {
- char chName[LEN];
- char chBuffer[LEN];
- int ii = 0;
- char ch;
- char *pchsource;
- char *pchdest;
-
-
- pchsource = yytext;
-
- //
- // Looking for the ending '.' of the tag. This position differs between
- // primary and secondary indexes.
- //
- while ( *pchsource++ != '.') ;
- pchdest = chBuffer;
- while (isstring(ch = *pchsource++))
- {
- *pchdest++ = ch;
- }
- *pchdest = 0x00;
-
- fprintf( fp_rtf, "K{\\footnote %s}\n", chBuffer);
- }
-
- //
- // What type of list is it?
- //
- do_list()
- {
-
- switch( yytext[1])
- {
- case 'u':
- ii_list_type = BULLET;
- break;
- case 'o':
- ii_list_type = ORDERED;
- break;
- case 's':
- default:
- ii_list_type = SIMPLE;
- }
-
- }
- #define LIST_FORMAT() \
- fprintf( fp_rtf, "\\par\n\\pard\\fi-240\\li300\\tx300\\ri120\\sb60\n")
-
- //
- // Process a nice, harry header line.
- //
- do_hdr()
- {
- char chName[LEN];
- char chBuffer[LEN];
- int ii = 0;
- char ch;
- char *pchsource;
- char *pchdest;
-
-
- // Obtain the ID of the header.
- get_id( chName, "Header", yytext);
-
- // This assumes the name of the header is on the same line
- // as the :h tag.
- pchsource = yytext;
- while ( *pchsource++ != '.') ;
- pchdest = chBuffer;
- while (isstring(ch = *pchsource++))
- {
- *pchdest++ = ch;
- }
- *pchdest = 0x00;
- if (!bfirst)
- {
- fprintf( fp_rtf, "\\page\n");
- }
- else
- bfirst = FALSE;
-
- fprintf( fp_rtf, "\\pard\\sb120\\f2\\fs20\\li60\\ri60\n");
- fprintf( fp_rtf, "${\\footnote %s}\n", chBuffer);
- // fprintf( fp_rtf, "K{\\footnote %s}\n", chBuffer);
- fprintf( fp_rtf, "#{\\footnote %s}\n", chName);
- }
-
- //
- // Handle hypertext outside of a list item.
- //
- do_hpt( flag)
- int flag;
- {
- char chBuffer[LEN];
-
- get_id( chBuffer, "Hypertext", yytext);
- fprintf( fp_rtf, "{\\ul");
- if ( flag == 2)
- fprintf( fp_rtf, "db ");
- else
- fprintf( fp_rtf, " ");
-
- fprintf( fp_rtf, "%s}{\\v %s} \n", chAppendBuffer, chBuffer);
- memset( chAppendBuffer, 0x00, LEN * 4);
-
- }
-
- #if 0
- get_name(pchName, pchError)
- char *pchName;
- char *pchError;
- {
- int ii = 0;
- char ch;
-
- while ( yytext[ii] && yytext[ii] != '=' ) ii++;
- if ( yytext[ii] != '=')
- {
- fprintf(fp_err, "Error parseing %s\n", pchError);
- }
- ii++;
- while ( ch = yytext[ii] )
- {
- if ( isalnum(ch))
- {
- *pchName++ = ch;
- }
- ii++;
- }
- *pchName = 0x00;
- }
-
- #endif
-
- //
- // Place a ID name [precedded by an '=']
- // in pchName from the string pchSource
- // and write an error message based on pchError if you don't find it.
- //
- get_id(pchName, pchError, pchSource)
- char *pchName;
- char *pchError;
- char *pchSource;
- {
- int ii = 0;
- char ch;
-
- while ( *pchSource && *pchSource != '=' ) pchSource++;
- if ( *pchSource != '=')
- {
- //
- // List processing now has some error recovery, and
- // a way of handling this error so it doesn't want the
- // error message in that case.
- //
- if (pchError)
- fprintf(fp_err, "Error parseing %s\n", pchError);
- return(-1);
- }
-
- pchSource++;
- while ( isalnum(ch = *pchSource) || *pchSource == '_')
- {
- *pchName++ = ch;
- pchSource++;
- }
- *pchName = 0x00;
- return(0);
- }
-
- // do a footnote.
- do_fn()
- {
- char chBuffer[256];
- char ch;
-
- get_id( chBuffer, "Footnote", yytext);
-
- fprintf( fp_rtf, "\\page\n\\pard\\sb120\\f2\\fs20\\li60\\ri60\n");
- fprintf( fp_rtf, "#{\\footnote %s}", chBuffer);
- }
-
- do_endlist()
- {
- ii_list_order = 1;
- ii_list_type = 0;
- fprintf( fp_rtf, "\\par\n\\pard\\li60\\ri60\\sb120\n");
- }
-
- //
- // Search the RTF file for MS_MS to locate example code.
- //
- do_xmp()
- {
- bExample = TRUE;
- fprintf( fp_rtf, "\\sb0\\par\n\\pard\\f5\\li300\\ri120\\keep\n");
- fprintf( fp_rtf, "MS_MS Example follows:\\par\n");
- }
-
- do_exmp()
- {
- bExample = FALSE;
- fprintf( fp_rtf, "\\keep\\par\\pard");
- }
-
- // unwind those styles!
- do_estyle()
- {
- while ( num_styles > 0)
- {
- num_styles--;
- fprintf( fp_rtf, "}");
- }
- fprintf( fp_rtf, "\n");
- }
-
- // establish style type and begin it appropriately
- do_style()
- {
- char ch;
- int ii_style;
-
- ii_style = yytext[3] - '0';
-
- switch (ii_style)
- {
- case 1:
- num_styles += 1;
- fprintf( fp_rtf, "{\\i ");
- break;
- case 2:
- num_styles += 1;
-
- fprintf( fp_rtf, "{\\b ");
- break;
- case 3:
- num_styles += 2;
-
- fprintf( fp_rtf, "{\\b {\\i ");
- break;
- case 5:
- num_styles = +1;
-
- fprintf( fp_rtf, "{\\ul ");
- break;
- default:
- fprintf( fp_err, "Unknown Style %d\n", ii_style);
- }
-
- }
-
-
- do_ddhd()
- {
- fprintf( fp_rtf, "\\par\\pard\\sb120\\fi-1568\\li1628\\tx1628");
- fprintf( fp_rtf, "\\ri120\\brdrb\\brdrs\n");
- fprintf( fp_rtf, "{%s \\tab %s}\n", chdthdText, yytext);
- }
-
-
- do_art( )
- {
- int ii = 0;
- int jj = 6;
- char chBuffer[256];
- char ch;
- int bPeriod = FALSE;
-
- while ( yytext[ii] && yytext[ii] != '=' ) ii++;
- if ( yytext[ii] != '=')
- {
- fprintf(fp_err, "Error parseing Artwork\n");
- }
- ii++;
- sprintf( chBuffer, "\\{bmc ");
- while ( ch = yytext[ii] )
- {
- if (ch == '.')
- if (!bPeriod)
- {
- chBuffer[jj++] = ch;
- bPeriod = TRUE;
- }
- if ( isalpha(ch) )
- {
- chBuffer[jj++] = ch;
- }
-
- if (ch == ' ')
- {
- yytext[ii] = 0x00;
- }
- else
- ii++;
- }
- chBuffer[jj] = 0x00;
- fprintf( fp_rtf, "%s\\}\n", chBuffer);
- }
-
- do_begin()
- {
- fprintf( fp_rtf, "{\\rtf1\\ansi\n");
- fprintf( fp_rtf, "{\\fonttbl\n");
- fprintf( fp_rtf, "{\\f0\\froman Tms Rmn; }\n");
- fprintf( fp_rtf, "{\\f1\\fdecor Courier; }\n");
- fprintf( fp_rtf, "{\\f2\\fswiss Helv; }\n");
- fprintf( fp_rtf, "{\\f3\\fdecor ZapfDingbats; }\n");
- fprintf( fp_rtf, "{\\f4\\fdecor Symbol; }\n");
- fprintf( fp_rtf, "{\\f5\\fmodern Courier; }\n");
- fprintf( fp_rtf, "}\n");
- fprintf( fp_rtf, "{\\colortbl;\n");
- fprintf( fp_rtf, "\\red0\\green0\\blue0;\\red255\\green0\\blue0;");
- fprintf( fp_rtf, "\\red0\\green128\\blue0;\\red0\\green0\\blue255;");
- fprintf( fp_rtf, "}\n");
- }
-
- #ifdef DEBUG
- #include "dbgtok.h"
- #endif
-
- char yytmp[YYLMAX];
-
- //
- // The situation: while processing a list item I discover that
- // it is incomplete, and some formatting is on the next line.
- //
- // I need to get the next line, regardless of its token value,
- // and append to my current text.
- //
- // This is designed to do that.
- //
- int append_token(ii_nl)
- int ii_nl;
- {
- int ii_new = 0;
-
- yytmp[0] = 0x00;
- strcpy( yytmp, yytext);
- while (ii_nl)
- {
- ii_new = yylex();
- if (ii_new != NL)
- strcat( yytmp, yytext);
- else
- {
- strcat( yytmp, " ");
- ii_nl--;
- ii_lineno++;
- }
- }
-
- strcpy( yytext, yytmp);
- return(ii_new);
- }
-
-
- //
- // List items: Complex parsing!
- //
- do_li(list_type)
- int list_type;
- {
- char *pchsource = yytext + 4;
- char chListText[LEN];
- char *pchList = chListText;
- char chRefText[LEN];
- char *pchRef = chRefText;
- char chHyperText[LEN];
- char *pchHyper = chHyperText;
- char chHyperLinkBuffer[LEN];
- char chBuffer[LEN];
- char ch;
- int bHyper = FALSE;
- int bRef = FALSE;
- int ii_type = 0;
-
- memset( chListText, 0x00, LEN);
- *pchRef = 0x00;
- *pchHyper = 0x00;
-
- // Parse the input string into the output list buffer.
- while ( ch = *pchsource++)
- {
- // Copy if it isn't a tag
- if (ch != ':' )
- {
- *pchList++ = ch;
- }
- // a hypertext reference.
- else if ( ( strncmp( pchsource, "hdref", 5) == 0)
- || ( strncmp( pchsource, "fnref", 5) == 0) )
- {
- if (bHyper == FALSE)
- {
- fprintf( fp_err, "No Hypertext!");
- *pchHyper = 0x00;
- }
-
- if (*pchsource == 'h')
- ii_type = 1;
-
- //
- // Find the ID. If you don't find it the first time,
- // go to next line to find it.
- //
- if (get_id( chRefText, NULL, pchsource))
- {
- append_token(2);
- if (get_id( chRefText, "Embedded Reference", pchsource))
- exit(-1);
- }
-
- strcpy( chBuffer, "{\\ul");
- if (ii_type == 1)
- strcat( chBuffer, "db");
-
- //
- // This is a little extra fancy since I am accumulating
- // a text string in chListText instead of doing direct
- // RTF output.
- //
- sprintf( chHyperLinkBuffer, "%s %s}{\\v %s}",
- chBuffer, chHyperText, chRefText);
- strcat( chListText, chHyperLinkBuffer);
- pchList = chListText + strlen( chListText);
- chHyperText[0] = 0x00;
- chHyperLinkBuffer[0] = 0x00;
- pchHyper = chHyperText;
- bHyper = FALSE;
-
- // copy till we find the ending period.
- do
- {
- ch = *pchsource++;
- } while (ch && ch != '.');
- if ( ch == 0x00)
- pchsource--;
- }
- // end style
- else if (strncmp( pchsource, "ehp", 3) == 0)
- {
- while ( num_styles > 0)
- {
- num_styles--;
- *pchList++ = '}';
- }
- pchsource += 5;
- }
-
- // Begin a style
- else if ( *pchsource == 'h' &&
- *(pchsource + 1) == 'p' &&
- isdigit(*(pchsource + 2)))
- {
- switch ( *(pchsource + 2) )
- {
- case '1':
- num_styles += 1;
- strcat( pchList - 1, "{\\i ");
- pchList += 4;
- break;
- case '2':
- num_styles += 1;
- strcat( pchList - 1, "{\\b ");
- pchList += 4;
- break;
- case '3':
- num_styles += 2;
- strcat( pchList - 1, "{\\b {\\i ");
- pchList += 8;
- break;
- case '5':
- num_styles += 1;
- strcat( pchList - 1, "{\\ul ");
- pchList += 5;
- break;
- default:
- fprintf( fp_err, "Unknown Style in List\n");
-
- }
- pchsource += 4;
- }
- // Begin hypertext
- else if ( strncmp( pchsource, "hpt.", 4) == 0)
- {
- bHyper = TRUE;
- pchsource += 4;
- do
- {
- ch = *pchsource++;
-
- if (ch != ':')
- *pchHyper++ = ch;
- else if ( strncmp( pchsource, "ehpt.", 5) == 0)
- {
- pchsource += 5;
- *pchHyper = 0x00;
- ch = 0x00;
- }
- else
- {
- fprintf( fp_err, "Unexpected Token", pchsource);
- *pchHyper = 0x00;
- ch = 0x00;
- }
- } while (ch != 0x00);
- }
- }
-
- // Now that we have a complex output buffer, format it
- // properly for the type of list we are processing.
- switch (list_type)
- {
- case BULLET:
- LIST_FORMAT();
- fprintf( fp_rtf, "\\{bmc bullet.bmp\\}\n\\tab\n%s\n",
- chListText);
- break;
- case ORDERED:
- fprintf( fp_rtf, "\\par\n");
- LIST_FORMAT();
- fprintf( fp_rtf, "%d\n\\tab\n", ii_list_order++);
- fprintf( fp_rtf, "%s\n", chListText);
- break;
-
- case SIMPLE:
- fprintf( fp_rtf, "\\par\n");
- LIST_FORMAT();
- fprintf( fp_rtf, "%s\n", chListText);
- break;
- case DD:
- fprintf( fp_rtf, "\\par\n\\pard\\fi-1568\\li1628\\tx1628");
- fprintf( fp_rtf, "\\ri120\\sb60\n{%s}\n\\tab\n%s \n",
- chdtText, chListText);
- break;
- case DT:
- strcpy( chdtText, chListText);
- break;
-
- }
- }
-
- // A debug print routine.
- debug_token( fp, ii)
- FILE *fp;
- int ii;
- {
- switch( ii)
- {
- case NL:
- case COMMENT:
- break;
-
- case COLON:
- case NTEXT:
- case HDR:
- case NDX1:
- case NDX2:
- case HPT:
- case EHPT:
- case PARA:
- case FNREF:
- case HDREF:
- case STYLE:
- case ESTYLE:
- case MARGIN:
- case NOTE:
- case ENOTE:
- case XMP:
- case EXMP:
- case LI:
- case SL:
- case SLC:
- case DL:
- case EDL:
- case ESL:
- case EPARML:
- case DTHD:
- case DDHD:
- case DT:
- case DD:
- case PARML:
- case PT:
- case PD:
- case ARTWORK:
- case FN:
- case EFN:
- case USERDOC:
- case EUSERDOC:
- fprintf( fp, "##%s {{%s}}\n", pch_token_string[ii], yytext);
- break;
- default:
- break;
- }
- }
-
-