📄 bmenu2.c
字号:
/* * main.c * * This program takes a texinfo file without node and menu commands, * build those commands and inserts them. * * It works by reading the input file into a linked list of lines * and then performing sweeps on that list until all formatting is * complete. After the program is run, there is still a little * clean up to be performed by hand. The following have to be fixed * by hand: * + previous of the first node * + next of the last node * * COPYRIGHT (c) 1988-2002. * On-Line Applications Research Corporation (OAR). * All rights reserved. * * $Id: bmenu2.c,v 1.2 2002/01/17 21:47:47 joel Exp $ */#include <assert.h>#include <ctype.h>#include <limits.h>#include <stdio.h>#include <stdlib.h>#include <string.h>/* XXX -- just for testing -- these should be set by options */char TopString[] = "Top";char EmptyString[] = "";char *DocsNextNode;char *DocsPreviousNode;char *DocsUpNode;int NodeNameIncludesChapter = 1;extern int optind; /* Why is this not in <stdlib.h>? */extern char *optarg; /* Why is this not in <stdlib.h>? */#ifndef NAME_MAX#define NAME_MAX 14 /* Why is the one in limits.h not showing up? */#endif#define INIT_DATA#define EXTERN#include "base.h"FILE *OutFile;static void ProcessFile2( FILE *infile, FILE *outfile );static void PrintFile2( FILE *outfile );static void ReadFileIntoChain2( FILE *InFile ); /************************************************************************* ************************************************************************* ***** DATA TYPES AND CONSTANT TABLES ***** ************************************************************************* *************************************************************************//* * Usage Information */char *Usage_Strings[] = { "\n", "usage: cmd [-cv] [-p prev] [-n next] [-u up] \n", "\n", "EOF"};/* * The page separator is not really a keyword and will be purged before * it is seen elsewhere. */#define PAGE_SEPARATOR "#PAGE"/* * Section Delimiter Keywords */#define MAXIMUM_KEYWORD_LENGTH 32/* * Level indicates where in the format the delimiter is allowed to occur. * 1 indicates a major section divider (e.g. "ATTRIBUTE DESCRIPTIONS:"). * 2 indicates a subsection (e.g. "ATTRIBUTE:"). * 3 indicates a heading (e.g. "DESCRIPTION:"). */#define TEXT 0#define SECTION 1#define SUBSECTION 2#define SUBSUBSECTION 3#define HEADING 4 typedef enum { UNUSED, /* dummy 0 slot */ KEYWORD_CHAPTER, KEYWORD_APPENDIX, KEYWORD_PREFACE, KEYWORD_CHAPHEADING, KEYWORD_SECTION, KEYWORD_SUBSECTION, KEYWORD_SUBSUBSECTION, KEYWORD_RAISE, KEYWORD_LOWER, KEYWORD_OTHER, KEYWORD_END } Keyword_indices_t;#define KEYWORD_FIRST KEYOWRD_CHAPTER#define KEYWORD_LAST KEYWORD_END/* * Line Management Structure */typedef enum { NO_EXTRA_FORMATTING_INFO, RAW_OUTPUT, PARAGRAPH_OUTPUT} ExtraFormat_info_t;typedef struct { Chain_Node Node; Keyword_indices_t keyword; /* unused is unknown/undecided */ ExtraFormat_info_t format; int number; int level; char Contents[ PARAGRAPH_SIZE ];} Line_Control;typedef enum { RT_FORBIDDEN, /* no text to right allowed */ RT_OPTIONAL, /* text to right optional -- none below */ RT_NONE, /* text to right is "none" or nothing -- none below */ RT_REQUIRED, /* text to right required -- none below */ RT_BELOW, /* text to right forbidden -- text below required */ RT_NONE_OR_BELOW, /* text to right is "none" OR there is text below */ RT_EITHER, /* text to right OR below */ RT_BOTH /* text to right AND below */} Keywords_text_mode_t;typedef enum { BL_FORBIDDEN, /* text below forbidden */ BL_FORMATTED, /* text below is to be formatted as paragraphs */ BL_RAW, /* text below is to be unprocessed by this program */} Keywords_text_below_t;typedef (*Keyword_validater_t)( Line_Control * );typedef struct { char Name[ MAXIMUM_KEYWORD_LENGTH ]; int level; Keywords_text_mode_t text_mode; Keywords_text_below_t text_below_mode; Keyword_validater_t keyword_validation_routine;} Keyword_info_t;Keyword_info_t Keywords[] = { { "unused", 0, 0, 0, NULL }, /* so 0 can be invalid */ { "@chapter", SECTION, RT_FORBIDDEN, BL_FORBIDDEN, NULL }, { "@appendix", SECTION, RT_FORBIDDEN, BL_FORBIDDEN, NULL }, { "@preface", SECTION, RT_FORBIDDEN, BL_FORBIDDEN, NULL }, { "@chapheading", SECTION, RT_FORBIDDEN, BL_FORBIDDEN, NULL }, { "@section", SECTION, RT_FORBIDDEN, BL_FORBIDDEN, NULL }, { "@subsection", SUBSECTION, RT_FORBIDDEN, BL_FORBIDDEN, NULL }, { "@subsubsection", SUBSUBSECTION, RT_FORBIDDEN, BL_FORBIDDEN, NULL }, { "@raise", SUBSECTION, RT_FORBIDDEN, BL_FORBIDDEN, NULL }, { "@lower", SUBSECTION, RT_FORBIDDEN, BL_FORBIDDEN, NULL }, { "", HEADING, RT_FORBIDDEN, BL_FORBIDDEN, NULL }, { "END OF FILE", SECTION, RT_FORBIDDEN, BL_FORBIDDEN, NULL }};#define NUMBER_OF_KEYWORDS \ ( sizeof( Keywords ) / sizeof( Keyword_info_t ) ) - 2/* * exit_application */void exit_application( int status){ fprintf( stderr, "*** Error encountered ***\n" );/* fprintf( stderr, "*** Error encountered on line %d ***\n", CurrentLine );*/ fclose( OutFile ); exit( status );}/************************************************************************* ************************************************************************* ***** LINE MANIPULATION ROUTINES ***** ************************************************************************* *************************************************************************//* * PrintLine */void PrintLine( Line_Control *line){ assert( line ); if ( line->number == -1 ) fprintf( stderr, " " ); else fprintf( stderr, "%5d", line->number );#if 0 fprintf( stderr, "%s\n", line->Contents );#else /* * Include some debugging information */ fprintf( stderr, "<%d,%d,%d>:%s\n", line->keyword, line->format, line->level, line->Contents );#endif}Chain_Control Line_Pool;/* * FillLinePool */void FillLinePool( void ){ void *pool;#define LINE_POOL_FILL_COUNT 100 pool = malloc( sizeof( Line_Control ) * LINE_POOL_FILL_COUNT ); assert( pool ); _Chain_Initialize( &Line_Pool, pool, LINE_POOL_FILL_COUNT, sizeof( Line_Control ) );}/* * AllocateLine */Line_Control *AllocateLine( void ){ Line_Control *new_line; new_line = (Line_Control *) _Chain_Get( &Line_Pool ); if ( !new_line ) { FillLinePool(); new_line = (Line_Control *) _Chain_Get( &Line_Pool ); assert( new_line ); } /* * This is commented out because although it is helpful during debug, * it consumes a significant percentage of the program's execution time. memset( new_line->Contents, '\0', sizeof( new_line->Contents ) );*/ new_line->number = -1; new_line->level = -1; new_line->keyword = UNUSED; new_line->format = NO_EXTRA_FORMATTING_INFO; new_line->Node.next = NULL; new_line->Node.previous = NULL; return new_line;}/* * FreeLine */void FreeLine( Line_Control *line){ fflush( stdout ); _Chain_Append( &Line_Pool, &line->Node );}/* * DeleteLine */Line_Control *DeleteLine( Line_Control *line){ Line_Control *next; next = (Line_Control *)line->Node.next; _Chain_Extract( &line->Node ); FreeLine( line ); return next;}/* * PrintSurroundingLines */void PrintSurroundingLines( Line_Control *line, int backward, int forward){ int i; int real_backward; Line_Control *local; for ( local=line, real_backward=0, i=1 ; i<=backward ; i++, real_backward++ ) { if ( &local->Node == Lines.first ) break; local = (Line_Control *) local->Node.previous; } for ( i=1 ; i<=real_backward ; i++ ) { PrintLine( local ); local = (Line_Control *) local->Node.next; } PrintLine( local ); for ( i=1 ; i<=forward ; i++ ) { local = (Line_Control *) local->Node.next; if ( _Chain_Is_last( &local->Node ) ) break; PrintLine( local ); } }/* * SetLineFormat */void SetLineFormat( Line_Control *line, ExtraFormat_info_t format){ if ( line->format != NO_EXTRA_FORMATTING_INFO ) { fprintf( stderr, "Line %d is already formatted\n", line->number ); PrintLine( line ); assert( FALSE ); } line->format = format;}/* * LineCopyFromRight */void LineCopyFromRight( Line_Control *line, char *dest){ char *p; for ( p=line->Contents ; *p != ' ' ; p++ ) ; p++; /* skip the ' ' */ for ( ; isspace( *p ) ; p++ ) ; strcpy( dest, p );}/* * LineCopySectionName */void LineCopySectionName( Line_Control *line, char *dest){ char *p; char *d; p = line->Contents; d = dest; if ( *p == '@' ) { /* skip texinfo command */ while ( !isspace( *p++ ) ) ; } for ( ; *p ; ) *d++ = *p++; *d = '\0';}/************************************************************************* ************************************************************************* ***** END OF LINE MANIPULATION ROUTINES ***** ************************************************************************* *************************************************************************//* * main */int main( int argc, char **argv){ int c; int index; boolean single_file_mode; OutFile = stdout; Verbose = FALSE; DocsNextNode = EmptyString; DocsPreviousNode = TopString; DocsUpNode = TopString; while ((c = getopt(argc, argv, "vcp:n:u:")) != EOF) { switch (c) { case 'v': Verbose = TRUE; break; case 'c': NodeNameIncludesChapter = 0; break; case 'p': DocsPreviousNode = strdup(optarg); break; case 'n': DocsNextNode = strdup(optarg); break; case 'u': DocsUpNode = strdup(optarg); break; case '?': usage(); return 0; } } if ( optind != argc ) { usage(); return 0 ; } if ( Verbose ) fprintf( stderr, "Arguments successfully parsed\n" ); FillLinePool(); ProcessFile2( stdin, stdout ); if ( Verbose ) fprintf( stderr, "Exitting\n" ); return 0;}/* * ProcessFile */void ProcessFile2( FILE *infile, FILE *outfile){ int index; /* * Read the file into our internal data structure */ if ( Verbose ) printf( "Processing (%s) -> (%s)\n", "stdin", "stdout" ); ReadFileIntoChain2( infile ); if ( Verbose ) fprintf( stderr, "-------->FILE READ IN\n" ); /* * Remove any spaces before the keyword and mark each keyword line as * such. Also remove extra white space at the end of lines. */ StripBlanks(); if ( Verbose )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -