source: rtems/doc/tools/bmenu/main.c @ 139b2e4

4.104.114.84.95
Last change on this file since 139b2e4 was 139b2e4, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 4, 1997 at 6:32:07 PM

added CVS Id string

  • Property mode set to 100644
File size: 22.2 KB
Line 
1/*
2 *  main.c
3 * 
4 *  This program takes a texinfo file without node and menu commands,
5 *  build those commands and inserts them.
6 *
7 *  It works by reading the input file into a linked list of lines
8 *  and then performing sweeps on that list until all formatting is
9 *  complete.  After the program is run, there is still a little
10 *  clean up to be performed by hand.  The following have to be fixed
11 *  by hand:
12 *    + previous of the first node
13 *    + next of the last node
14 *
15 *  COPYRIGHT (c) 1988-1997.
16 *  On-Line Applications Research Corporation (OAR).
17 *  All rights reserved.
18 *
19 *  $Id$
20 */
21
22#include <assert.h>
23#include <ctype.h>
24#include <limits.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29/* XXX -- just for testing -- these should be set by options */
30char DocsNextNode[]     = "";
31char DocsPreviousNode[] = "Top";
32char DocsUpNode[]       = "Top";
33
34extern int   optind;     /* Why is this not in <stdlib.h>? */
35extern char *optarg;     /* Why is this not in <stdlib.h>? */
36
37#ifndef NAME_MAX
38#define NAME_MAX      14 /* Why is the one in limits.h not showing up? */
39#endif
40#define INIT_DATA
41#define EXTERN
42
43#include "base.h"
44
45FILE           *OutFile = stdout;
46
47/*************************************************************************
48 *************************************************************************
49 *****                 DATA TYPES AND CONSTANT TABLES                *****
50 *************************************************************************
51 *************************************************************************/
52/*
53 *  Usage Information
54 */
55
56char *Usage_Strings[] = {
57  "\n",
58  "usage: cmd [-bv] files ...\n", 
59  "\n",
60  "EOF"
61};
62
63/*
64 *  The page separator is not really a keyword and will be purged before
65 *  it is seen elsewhere.
66 */
67
68#define PAGE_SEPARATOR                            "#PAGE"
69
70/*
71 *  Section Delimiter Keywords
72 */
73
74#define MAXIMUM_KEYWORD_LENGTH   32
75
76/*
77 *  Level indicates where in the format the delimiter is allowed to occur.
78 *    1 indicates a major section divider (e.g. "ATTRIBUTE DESCRIPTIONS:").
79 *    2 indicates a subsection (e.g. "ATTRIBUTE:").
80 *    3 indicates a heading (e.g. "DESCRIPTION:").
81 */
82
83#define TEXT         0
84#define SECTION      1
85#define SUBSECTION   2
86#define HEADING      3
87 
88typedef enum {
89  UNUSED,                            /* dummy 0 slot */
90  KEYWORD_CHAPTER,
91  KEYWORD_CHAPHEADING,
92  KEYWORD_SECTION,
93  KEYWORD_SUBSECTION,
94  KEYWORD_OTHER,
95  KEYWORD_END
96 
97}  Keyword_indices_t;
98
99#define KEYWORD_FIRST KEYOWRD_CHAPTER
100#define KEYWORD_LAST  KEYWORD_END
101
102/*
103 *  Line Management Structure
104 */
105
106typedef enum {
107  NO_EXTRA_FORMATTING_INFO,
108  RAW_OUTPUT,
109  PARAGRAPH_OUTPUT
110}  ExtraFormat_info_t;
111
112typedef struct {
113  Chain_Node         Node;
114  Keyword_indices_t  keyword;   /* unused is unknown/undecided */
115  ExtraFormat_info_t format;
116  int                number;
117  char               Contents[ PARAGRAPH_SIZE ];
118} Line_Control;
119
120typedef enum {
121  RT_FORBIDDEN,     /* no text to right allowed */
122  RT_OPTIONAL,      /* text to right optional -- none below */
123  RT_NONE,          /* text to right is "none" or nothing -- none below */
124  RT_REQUIRED,      /* text to right required -- none below */
125  RT_BELOW,         /* text to right forbidden -- text below required */
126  RT_NONE_OR_BELOW, /* text to right is "none" OR there is text below  */
127  RT_EITHER,        /* text to right OR below */
128  RT_BOTH           /* text to right AND below */
129}  Keywords_text_mode_t;
130
131typedef enum {
132  BL_FORBIDDEN,     /* text below forbidden */
133  BL_FORMATTED,     /* text below is to be formatted as paragraphs */
134  BL_RAW,           /* text below is to be unprocessed by this program */
135}  Keywords_text_below_t;
136
137typedef (*Keyword_validater_t)( Line_Control * );
138
139typedef struct {
140  char                      Name[ MAXIMUM_KEYWORD_LENGTH ];
141  int                       level;
142  Keywords_text_mode_t      text_mode;
143  Keywords_text_below_t     text_below_mode;
144  Keyword_validater_t       keyword_validation_routine;
145}  Keyword_info_t;
146
147Keyword_info_t Keywords[] = {
148  { "unused",
149        0,         0,                0, NULL }, /* so 0 can be invalid */
150  { "@chapter",    SECTION,    RT_FORBIDDEN,      BL_FORBIDDEN, NULL },
151  { "@chapheading",SECTION,    RT_FORBIDDEN,      BL_FORBIDDEN, NULL },
152  { "@section",    SECTION,    RT_FORBIDDEN,      BL_FORBIDDEN, NULL },
153  { "@subsection", SUBSECTION, RT_FORBIDDEN,      BL_FORBIDDEN, NULL },
154  { "",            HEADING,    RT_FORBIDDEN,      BL_FORBIDDEN, NULL },
155  { "END OF FILE", SECTION,    RT_FORBIDDEN,      BL_FORBIDDEN, NULL }
156};
157
158#define NUMBER_OF_KEYWORDS \
159  ( sizeof( Keywords ) / sizeof( Keyword_info_t ) ) - 2
160
161/*
162 *  exit_application
163 */
164
165void exit_application( 
166  int status
167)
168{
169  fprintf( stderr, "*** Error encountered ***\n" );
170/*
171  fprintf( stderr, "*** Error encountered on line %d ***\n", CurrentLine );
172*/
173  fclose( OutFile ); 
174  exit( status );
175}
176
177/*************************************************************************
178 *************************************************************************
179 *****                LINE MANIPULATION ROUTINES                     *****
180 *************************************************************************
181 *************************************************************************/
182
183/*
184 * PrintLine
185 */
186
187void PrintLine(
188  Line_Control *line
189)
190{
191  assert( line );
192
193  if ( line->number == -1 )
194    fprintf( stderr, "     " );
195  else
196    fprintf( stderr, "%5d", line->number );
197
198#if 0
199  fprintf( stderr, "%s\n", line->Contents );
200#else
201  /*
202   *  Include some debugging information
203   */
204  fprintf(
205    stderr,
206    "<%d,%d>:%s\n", 
207    line->keyword,
208    line->format,
209    line->Contents
210  );
211#endif
212}
213
214Chain_Control Line_Pool;
215
216/*
217 *  FillLinePool
218 */
219
220void FillLinePool( void )
221{
222  void *pool;
223
224#define LINE_POOL_FILL_COUNT 100
225
226  pool = malloc( sizeof( Line_Control ) * LINE_POOL_FILL_COUNT );
227  assert( pool );
228
229  _Chain_Initialize(
230    &Line_Pool,
231    pool,
232    LINE_POOL_FILL_COUNT,
233    sizeof( Line_Control )
234  );
235}
236
237/*
238 * AllocateLine
239 */
240
241Line_Control *AllocateLine( void )
242{
243  Line_Control  *new_line;
244
245  new_line = (Line_Control *) _Chain_Get( &Line_Pool );
246  if ( !new_line ) {
247    FillLinePool();
248    new_line = (Line_Control *) _Chain_Get( &Line_Pool );
249    assert( new_line );
250  }
251 
252/*
253 *  This is commented out because although it is helpful during debug,
254 *  it consumes a significant percentage of the program's execution time.
255 
256  memset( new_line->Contents, '\0', sizeof( new_line->Contents ) );
257*/
258  new_line->number = -1;
259
260  new_line->keyword = UNUSED;
261  new_line->format = NO_EXTRA_FORMATTING_INFO;
262
263  new_line->Node.next     = NULL;
264  new_line->Node.previous = NULL;
265
266  return new_line;
267}
268
269/*
270 * FreeLine
271 */
272
273void FreeLine(
274  Line_Control *line
275)
276{
277  fflush( stdout );
278  _Chain_Append( &Line_Pool, &line->Node );
279}
280
281/*
282 * DeleteLine
283 */
284
285Line_Control *DeleteLine(
286  Line_Control *line
287)
288{
289  Line_Control *next;
290 
291  next = (Line_Control *)line->Node.next; 
292  _Chain_Extract( &line->Node );
293  FreeLine( line );
294  return next;
295}
296
297/*
298 *  PrintSurroundingLines
299 */
300
301void PrintSurroundingLines(
302  Line_Control *line,
303  int           backward,
304  int           forward
305)
306{
307  int           i;
308  int           real_backward;
309  Line_Control *local;
310
311  for ( local=line, real_backward=0, i=1 ; 
312        i<=backward ; 
313        i++, real_backward++ ) {
314    if ( &local->Node == Lines.first )
315      break;
316    local = (Line_Control *) local->Node.previous;
317  }
318
319  for ( i=1 ; i<=real_backward ; i++ ) {
320    PrintLine( local );
321    local = (Line_Control *) local->Node.next;
322  }
323 
324  PrintLine( local );
325
326  for ( i=1 ; i<=forward ; i++ ) {
327    local = (Line_Control *) local->Node.next;
328    if ( _Chain_Is_last( &local->Node ) )
329      break;
330    PrintLine( local );
331  }
332 
333}
334
335/*
336 *  SetLineFormat
337 */
338
339void SetLineFormat(
340  Line_Control       *line,
341  ExtraFormat_info_t  format
342)
343{
344  if ( line->format != NO_EXTRA_FORMATTING_INFO ) {
345    fprintf( stderr, "Line %d is already formatted\n", line->number );
346    PrintLine( line );
347    assert( FALSE );
348  }
349
350  line->format = format;
351}
352
353/*
354 *  LineCopyFromRight
355 */
356
357void LineCopyFromRight(
358  Line_Control *line,
359  char         *dest
360)
361{
362  char *p;
363
364  for ( p=line->Contents ; *p != ' ' ; p++ ) 
365    ;
366  p++;  /* skip the ' ' */
367  for ( ; isspace( *p ) ; p++ )
368    ;
369
370  strcpy( dest, p );
371
372}
373
374/*
375 *  LineCopySectionName
376 */
377
378void LineCopySectionName(
379  Line_Control *line,
380  char         *dest
381)
382{
383  char *p;
384  char *d;
385
386  p = line->Contents;
387  d = dest;
388
389  if ( *p == '@' ) {                /* skip texinfo command */
390    while ( !isspace( *p++ ) )
391      ;
392  }
393
394  for ( ; *p ; ) 
395    *d++ = *p++;
396
397  *d = '\0';
398}
399
400/*************************************************************************
401 *************************************************************************
402 *****              END OF LINE MANIPULATION ROUTINES                *****
403 *************************************************************************
404 *************************************************************************/
405
406/*
407 *  main
408 */
409
410int main(
411  int    argc,
412  char **argv
413)
414{
415  int      c;
416  int      index;
417  boolean  single_file_mode;
418
419  Verbose = FALSE;
420
421  while ((c = getopt(argc, argv, "bv")) != EOF) {
422    switch (c) {
423      case 'v':
424        Verbose = TRUE;
425        break;
426      case '?':
427        usage();
428        return 0;
429    }
430  }
431
432  if ( Verbose )
433    fprintf( stderr, "Arguments successfully parsed\n" );
434
435  FillLinePool();
436
437  for ( index=optind ; index < argc ; index++ ) {
438    ProcessFile( argv[ index ], NULL );
439  }
440   
441  if ( Verbose )
442    fprintf( stderr, "Exitting\n" );
443
444  return 0;
445}
446
447/*
448 *  ProcessFile
449 */
450
451void ProcessFile(
452  char   *inname,
453  char   *outname
454)
455{
456   char            out[ 256 ];
457   int             index;
458
459   /*
460    *  Automatically generate the output file name.
461    */
462
463   if ( outname == NULL ) {
464     for( index=0 ; inname[index] && inname[index] != '.' ; index++ ) {
465       out[ index ] = inname[ index ];
466     }
467
468     out[ index++ ] = '.';
469     out[ index++ ] = 't';
470     out[ index++ ] = 'x';
471     out[ index++ ] = 't';
472     out[ index ] = '\0';
473
474   }
475
476   /*
477    *  Read the file into our internal data structure
478    */
479
480   if ( Verbose )
481     printf( "Processing (%s) -> (%s)\n", inname, out );
482
483   ReadFileIntoChain( inname );
484
485   if ( Verbose )
486     fprintf( stderr, "-------->FILE READ IN\n" );
487
488   /*
489    *  Remove any spaces before the keyword and mark each keyword line as
490    *  such.  Also remove extra white space at the end of lines.
491    */
492
493   StripBlanks();
494
495   if ( Verbose )
496     fprintf( stderr, "-------->BLANKS BEFORE KEYWORDS STRIPPED\n" );
497
498
499   FormatToTexinfo();
500
501   if ( Verbose ) 
502     fprintf( stderr, "-------->FILE FORMATTED TO TEXINFO\n" );
503
504   /*
505    *  Print the file
506    */
507
508   PrintFile( out );
509
510   if ( Verbose ) 
511     fprintf( stderr, "-------->FILE PRINTED\n" );
512
513   /*
514    *  Clean Up
515    */
516
517   ReleaseFile();
518
519   if ( Verbose )
520     fprintf( stderr, "-------->FILE RELEASED\n" );
521}
522
523/*
524 *  usage
525 */
526
527void usage( void )
528{
529  int index;
530
531  for ( index=0 ; strcmp( Usage_Strings[ index ], "EOF" ) ; index++ )
532    fprintf( stderr, Usage_Strings[ index ] );
533}
534
535/*
536 *  ReadFileIntoChain
537 */
538
539void ReadFileIntoChain( 
540  char *inname
541)
542{
543   FILE *InFile;
544   int   line_count;
545   int   max_length;
546   char *line;
547   char  Buffer[ BUFFER_SIZE ];
548   Line_Control *new_line;
549
550   InFile = fopen( inname, "r" );
551
552   if ( !InFile ) {
553     fprintf( stderr, "Unable to open (%s)\n", inname );
554     exit( 1 );
555   }
556   assert( InFile );
557
558   max_length = 0;
559   line_count = 0;
560
561   _Chain_Initialize_empty( &Lines );
562
563   for ( ;; ) {
564      line = fgets( Buffer, BUFFER_SIZE, InFile );
565      if ( !line ) 
566        break;
567
568      Buffer[ strlen( Buffer ) - 1 ] = '\0';
569
570      new_line = AllocateLine();
571 
572      strcpy( new_line->Contents, Buffer );
573
574      new_line->number = ++line_count;
575 
576      _Chain_Append( &Lines, &new_line->Node );
577   } 
578
579   fclose( InFile ); 
580}
581
582/*
583 *  StripBlanks
584 */
585
586void StripBlanks( void )
587{
588  Line_Control      *line;
589  Keyword_indices_t  index;
590  int                indentation;
591  int                length;
592 
593  for ( line = (Line_Control *) Lines.first ;
594        !_Chain_Is_last( &line->Node ) ;
595        line = (Line_Control *) line->Node.next
596        ) {
597
598    /*
599     *  Strip white space from the end of each line
600     */
601
602    length = strlen( line->Contents );
603
604    while ( isspace( line->Contents[ --length ] ) ) 
605      line->Contents[ length ] = '\0';
606
607    if ( strstr( line->Contents, "@chapter" ) )
608      line->keyword = KEYWORD_CHAPTER;
609    else if ( strstr( line->Contents, "@chapheading" ) )
610      line->keyword = KEYWORD_CHAPHEADING;
611    else if ( strstr( line->Contents, "@section" ) )
612      line->keyword = KEYWORD_SECTION;
613    else if ( strstr( line->Contents, "@subsection" ) )
614      line->keyword = KEYWORD_SUBSECTION;
615    else
616      line->keyword = KEYWORD_OTHER;
617   
618  }
619  line = AllocateLine();
620  line->keyword = KEYWORD_END;
621  _Chain_Append( &Lines, &line->Node );
622}
623
624/*
625 *  strIsAllSpace
626 */
627
628boolean strIsAllSpace(
629  char *s
630)
631{
632  char *p;
633
634  for ( p = s ; *p ; p++ )
635    if ( !isspace( *p ) )
636      return FALSE;
637
638  return TRUE;
639}
640
641/*
642 *  BuildTexinfoNodes
643 */
644
645void BuildTexinfoNodes( void ) 
646{
647  Line_Control *line;
648  Line_Control *new_line;
649  Line_Control *next_node;
650  char          Buffer[ BUFFER_SIZE ];
651  char          ChapterName[ BUFFER_SIZE ];
652  char          NodeName[ BUFFER_SIZE ];
653  char          NextNode[ BUFFER_SIZE ];
654  char          NextNodeName[ BUFFER_SIZE ];
655  char          PreviousNodeName[ BUFFER_SIZE ];
656  char          UpNodeName[ BUFFER_SIZE ];
657  char          SectionName[ BUFFER_SIZE ];
658  char          MenuBuffer[ BUFFER_SIZE ];
659  Line_Control *node_insert_point;
660  Line_Control *menu_insert_point;
661  Line_Control *node_line;
662  boolean       next_found;
663  int           menu_items;
664
665  strcpy( PreviousNodeName, DocsPreviousNode );
666
667  for ( line = (Line_Control *) Lines.first ;
668        !_Chain_Is_last( &line->Node ) ; 
669        line = (Line_Control *) line->Node.next
670      ) {
671
672    menu_insert_point = (Line_Control *) line->Node.next;
673
674    switch ( Keywords[ line->keyword ].level ) {
675      case TEXT:
676      case HEADING:
677        break;
678      case SECTION:
679        if ( line->keyword == KEYWORD_END )
680          goto bottom; 
681
682        if ( line->keyword == KEYWORD_CHAPTER || 
683             line->keyword == KEYWORD_CHAPHEADING ) {
684          LineCopyFromRight( line, ChapterName );
685          strcpy( UpNodeName, DocsUpNode );
686          strcpy( NodeName, ChapterName );
687        } else {
688          LineCopySectionName( line, Buffer );
689          sprintf( NodeName, "%s %s", ChapterName, Buffer );
690          strcpy( UpNodeName, ChapterName );
691        }
692        strcpy( SectionName, NodeName );
693
694        /*
695         *  Go ahead and put it on the chain in the right order (ahead of
696         *  the menu) and we can fill it in later (after the menu is built).
697         */
698
699        new_line = AllocateLine();
700        strcpy( new_line->Contents, "@ifinfo" );
701        _Chain_Insert( line->Node.previous, &new_line->Node );
702
703        node_line = AllocateLine();
704        _Chain_Insert( line->Node.previous, &node_line->Node );
705
706        new_line = AllocateLine();
707        strcpy( new_line->Contents, "@end ifinfo" );
708        _Chain_Insert( line->Node.previous, &new_line->Node );
709
710        menu_items = 0;
711       
712        if ( line->keyword == KEYWORD_CHAPTER || line->keyword == KEYWORD_CHAPHEADING ) {
713          next_node = (Line_Control *) line->Node.next;
714          next_found = FALSE;
715          for ( ; ; ) {
716            if ( next_node->keyword == KEYWORD_END )
717              break;
718            if ( Keywords[ next_node->keyword ].level == SECTION ) {
719              LineCopySectionName( next_node, Buffer );
720              if ( !next_found ) {
721                next_found = TRUE;
722                sprintf( NextNodeName, "%s %s", ChapterName, Buffer );
723              }
724
725              if ( menu_items == 0 ) {
726                new_line = AllocateLine();
727                strcpy( new_line->Contents, "@ifinfo" );
728                _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
729
730                new_line = AllocateLine();
731                strcpy( new_line->Contents, "@menu" );
732                _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
733              }
734
735              menu_items++;
736
737              new_line = AllocateLine();
738              sprintf( new_line->Contents, "* %s %s::", ChapterName, Buffer );
739              _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
740            }
741            next_node = (Line_Control *) next_node->Node.next;
742          }
743        } else {
744          next_node = (Line_Control *) line->Node.next;
745       
746          next_found = FALSE;
747          for ( ; ; ) {
748            if ( Keywords[ next_node->keyword ].level == SECTION ) {
749              if ( !next_found ) {
750                if ( next_node->keyword == KEYWORD_END ) {
751                  strcpy( NextNodeName, DocsNextNode );
752                } else {
753                  LineCopySectionName( next_node, Buffer );
754                  sprintf( NextNodeName, "%s %s", ChapterName, Buffer );
755                }
756                next_found = TRUE;
757              }
758              break;
759            } else if ( Keywords[ next_node->keyword ].level == SUBSECTION ) {
760              LineCopySectionName( next_node, MenuBuffer ); /* has next node */
761
762              if ( menu_items == 0 ) {
763                new_line = AllocateLine();
764                strcpy( new_line->Contents, "@ifinfo" );
765                _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
766
767                new_line = AllocateLine();
768                strcpy( new_line->Contents, "@menu" );
769                _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
770              }
771
772              menu_items++;
773
774              new_line = AllocateLine();
775              sprintf( new_line->Contents, "* %s::", MenuBuffer );
776              _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
777
778              if ( !next_found ) {
779                next_found = TRUE;
780                strcpy( NextNodeName, MenuBuffer );
781              }
782            }
783            next_node = (Line_Control *) next_node->Node.next;
784          }
785        }
786
787        if ( menu_items ) {
788          new_line = AllocateLine();
789          strcpy( new_line->Contents, "@end menu" );
790          _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
791
792          new_line = AllocateLine();
793          strcpy( new_line->Contents, "@end ifinfo" );
794          _Chain_Insert( menu_insert_point->Node.previous, &new_line->Node );
795        }
796#if 0
797        fprintf(
798          stderr,
799          "@node %s, %s, %s, %s\n",
800          NodeName,
801          NextNodeName,
802          PreviousNodeName,
803          UpNodeName
804        );
805#endif
806        /* node_line was previously inserted */
807        sprintf(
808          node_line->Contents,
809          "@node %s, %s, %s, %s",
810          NodeName,
811          NextNodeName,
812          PreviousNodeName,
813          UpNodeName
814        );
815
816        strcpy( PreviousNodeName, NodeName );
817        break;
818
819      case SUBSECTION:
820        strcpy( UpNodeName, SectionName );
821
822        LineCopyFromRight( line, NodeName );
823
824        new_line = AllocateLine();
825        strcpy( new_line->Contents, "@ifinfo" );
826        _Chain_Insert( line->Node.previous, &new_line->Node );
827
828        next_node = (Line_Control *) line->Node.next;
829        for ( ; ; ) {
830          if ( Keywords[ next_node->keyword ].level == SECTION ) {
831            if ( next_node->keyword == KEYWORD_END ) {
832              strcpy( NextNodeName, DocsNextNode );
833            } else {
834              LineCopySectionName( next_node, Buffer );
835              sprintf( NextNodeName, "%s %s", ChapterName, Buffer );
836            }
837            break;
838          } else if ( Keywords[ next_node->keyword ].level == SUBSECTION ) {
839            LineCopyFromRight( next_node, NextNodeName );
840            break;
841          }
842          next_node = (Line_Control *) next_node->Node.next;
843        }
844
845#if 0
846        fprintf(
847          stderr,
848          "@node %s, %s, %s, %s\n",
849          NodeName,
850          NextNodeName,
851          PreviousNodeName,
852          UpNodeName
853        );
854#endif
855        new_line = AllocateLine();
856        sprintf(
857          new_line->Contents,
858          "@node %s, %s, %s, %s",
859          NodeName,
860          NextNodeName,
861          PreviousNodeName,
862          UpNodeName
863        );
864        _Chain_Insert( line->Node.previous, &new_line->Node );
865
866        new_line = AllocateLine();
867        strcpy( new_line->Contents, "@end ifinfo" );
868        _Chain_Insert( line->Node.previous, &new_line->Node );
869
870        strcpy( PreviousNodeName, NodeName );
871        break;
872    }
873  }
874bottom:
875}
876
877/*
878 *  FormatToTexinfo
879 */
880
881void FormatToTexinfo( void )
882{
883  if ( Verbose )
884    fprintf( stderr, "-------->INSERTING TEXINFO MENUS\n" );
885
886  BuildTexinfoNodes();
887}
888
889/*
890 *  PrintFile
891 */
892
893void PrintFile(
894  char *out
895)
896{
897  Line_Control *line;
898
899  OutFile = fopen( out, "w+" );
900
901  if ( !OutFile ) {
902    fprintf( stderr, "Unable to open (%s) for output\n", out );
903    exit_application( 1 );
904  }
905  assert( OutFile );
906
907  for ( line = (Line_Control *) Lines.first ;
908        !_Chain_Is_last( &line->Node ) ; 
909        line = (Line_Control *) line->Node.next ) {
910    fprintf( OutFile, "%s\n", line->Contents );
911/*
912    fprintf(
913      OutFile,
914      "(%d,%d)%s\n",
915      line->keyword,
916      line->format,
917      line->Contents
918    );
919*/
920  }
921}
922
923/*
924 *  DumpList
925 */
926
927void DumpList( 
928  Chain_Control  *the_list
929)
930{
931  Line_Control  *line;
932
933  fprintf( stderr, "---> Dumping list (%p)\n", the_list );
934
935  for ( line = (Line_Control *) the_list->first ;
936      !_Chain_Is_last( &line->Node ) ; 
937      line = (Line_Control *) line->Node.next ) {
938    fprintf( stderr, "%s\n", line->Contents );
939  }
940}
941
942/*
943 * ReleaseFile
944 */
945
946void ReleaseFile()
947{
948   Line_Control *line;
949   Line_Control *next;
950
951   for ( line = (Line_Control *) Lines.first ;
952         !_Chain_Is_last( &line->Node ) ; 
953       ) {
954     next = (Line_Control *) line->Node.next;
955     line = next;
956   }
957}
958
959/*
960 *  strtoInitialCaps
961 */
962
963void strtoInitialCaps(
964  char *dest,
965  char *src
966)
967{
968  char *source = src;
969  char *destination = dest;
970
971  source = src;
972  destination = (dest) ? dest : src;
973
974  while ( *source ) {
975    while ( isspace( *source ) )
976      *destination++ = *source++;
977
978    if ( !*source )
979      break;
980
981    *destination++ = toupper( *source++ );
982
983    for ( ; *source && !isspace( *source ) ; source++ )
984      *destination++ = tolower( *source );
985     
986    if ( !*source )
987      break;
988  }
989
990  *destination = '\0';
991}
Note: See TracBrowser for help on using the repository browser.