source: rtems/doc/tools/bmenu/main.c @ 5b9ec351

4.104.114.84.95
Last change on this file since 5b9ec351 was 5b9ec351, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 15, 1997 at 4:40:21 PM

Added command line options for next, previous, and up node.

Added error check to insure we don't write over a .texi file given
to us as input.

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