~ubuntu-branches/ubuntu/maverick/texinfo/maverick

« back to all changes in this revision

Viewing changes to info/infokey.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2005-10-28 15:10:30 UTC
  • mto: (2.1.1 dapper) (3.1.4 hardy)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20051028151030-9nsf2s2k2z3fktjt
Tags: upstream-4.8
ImportĀ upstreamĀ versionĀ 4.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* infokey.c -- compile ~/.infokey to ~/.info.
2
 
   $Id: infokey.c,v 1.5 2002/02/26 16:17:57 karl Exp $
 
2
   $Id: infokey.c,v 1.9 2004/12/14 00:15:36 karl Exp $
3
3
 
4
 
   Copyright (C) 1999, 2001, 02 Free Software Foundation, Inc.
 
4
   Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5
5
 
6
6
   This program is free software; you can redistribute it and/or modify
7
7
   it under the terms of the GNU General Public License as published by
60
60
  {
61
61
    info = 0,
62
62
    ea = 1,
63
 
    var = 2,
 
63
    var = 2
64
64
  };
65
65
struct sect
66
66
  {
69
69
  };
70
70
 
71
71
/* Some "forward" declarations. */
72
 
static char *mkpath ();
73
 
static int compile (), write_infokey_file ();
74
 
static void syntax_error (), error_message (), suggest_help (), short_help ();
 
72
static char *mkpath (const char *dir, const char *file);
 
73
static int compile (FILE *fp, const char *filename, struct sect *sections);
 
74
static int write_infokey_file (FILE *fp, struct sect *sections);
 
75
static void syntax_error (const char *filename,
 
76
    unsigned int linenum, const char *fmt,
 
77
    const void *a1, const void *a2, const void *a3, const void *a4);
 
78
static void error_message (int error_code, const char *fmt,
 
79
    const void *a1, const void *a2, const void *a3, const void *a4);
 
80
static void suggest_help (void);
 
81
static void short_help (void);
75
82
 
76
83
 
77
84
/* **************************************************************** */
81
88
/* **************************************************************** */
82
89
 
83
90
int
84
 
main (argc, argv)
85
 
     int argc;
86
 
     char **argv;
 
91
main (int argc, char **argv)
87
92
{
88
93
  int getopt_long_index;        /* Index returned by getopt_long (). */
89
 
  NODE *initial_node;           /* First node loaded by Info. */
90
94
 
91
95
#ifdef HAVE_SETLOCALE
92
96
  /* Set locale via LC_ALL.  */
93
97
  setlocale (LC_ALL, "");
94
98
#endif
95
99
 
 
100
#ifdef ENABLE_NLS
96
101
  /* Set the text message domain.  */
97
102
  bindtextdomain (PACKAGE, LOCALEDIR);
98
103
  textdomain (PACKAGE);
 
104
#endif
99
105
 
100
106
  while (1)
101
107
    {
140
146
There is NO warranty.  You may redistribute this software\n\
141
147
under the terms of the GNU General Public License.\n\
142
148
For more information about these matters, see the files named COPYING.\n"),
143
 
              "1999");
 
149
              "2003");
144
150
      xexit (0);
145
151
    }
146
152
 
161
167
    }
162
168
  else if (optind != argc)
163
169
    {
164
 
      error_message (0, _("incorrect number of arguments"));
 
170
      error_message (0, _("incorrect number of arguments"),
 
171
          NULL, NULL, NULL, NULL);
165
172
      suggest_help ();
166
173
      xexit (1);
167
174
    }
191
198
    inf = fopen (input_filename, "r");
192
199
    if (!inf)
193
200
      {
194
 
        error_message (errno, _("cannot open input file `%s'"), input_filename);
 
201
        error_message (errno, _("cannot open input file `%s'"),
 
202
            input_filename, NULL, NULL, NULL);
195
203
        xexit (1);
196
204
      }
197
205
 
204
212
        outf = fopen (output_filename, FOPEN_WBIN);
205
213
        if (!outf)
206
214
          {
207
 
            error_message (errno, _("cannot create output file `%s'"), output_filename);
 
215
            error_message (errno, _("cannot create output file `%s'"),
 
216
                output_filename, NULL, NULL, NULL);
208
217
            xexit (1);
209
218
          }
210
219
 
214
223
        write_error = 0;
215
224
        if (!write_infokey_file (outf, sections))
216
225
          {
217
 
            error_message (errno, _("error writing to `%s'"), output_filename);
 
226
            error_message (errno, _("error writing to `%s'"),
 
227
                output_filename, NULL, NULL, NULL);
218
228
            write_error = 1;
219
229
          }
220
230
        if (fclose (outf) == EOF)
221
231
          {
222
 
            error_message (errno, _("error closing output file `%s'"), output_filename);
 
232
            error_message (errno, _("error closing output file `%s'"),
 
233
                output_filename, NULL, NULL, NULL);
223
234
            write_error = 1;
224
235
          }
225
236
        if (write_error)
233
244
    fclose (inf);
234
245
  }
235
246
 
236
 
  xexit (0);
 
247
  return 0;
237
248
}
238
249
 
239
250
static char *
240
 
mkpath (dir, file)
241
 
     const char *dir;
242
 
     const char *file;
 
251
mkpath (const char *dir, const char *file)
243
252
{
244
253
  char *p;
245
254
 
289
298
                #info
290
299
                #echo-area
291
300
                #var
292
 
        
 
301
 
293
302
        The sections may occur in any order.  Each section may be
294
303
        omitted completely.  If the 'info' section is the first in the
295
304
        file, its '#info' line may be omitted.
296
 
        
 
305
 
297
306
        The 'info' and 'echo-area' sections
298
307
        -----------------------------------
299
308
        Each line in the 'info' or 'echo-area' sections has the
300
309
        following syntax:
301
310
 
302
311
                key-sequence SPACE action-name [ SPACE [ # comment ] ] \n
303
 
        
 
312
 
304
313
        Where SPACE is one or more white space characters excluding
305
314
        newline, "action-name" is the name of a GNU Info command,
306
315
        "comment" is any sequence of characters excluding newline, and
319
328
                \r indicates a single CR;
320
329
                \t indicates a single TAB;
321
330
                \b indicates a single BACKSPACE;
322
 
        
 
331
 
323
332
           4.   \ku indicates the Up Arrow key;
324
333
                \kd indicates the Down Arrow key;
325
334
                \kl indicates the Left Arrow key;
345
354
        If the following line:
346
355
 
347
356
                #stop
348
 
        
 
357
 
349
358
        occurs anywhere in an 'info' or 'echo-area' section, that
350
359
        indicates to GNU Info to suppress all of its default key
351
360
        bindings in that context.
352
 
        
 
361
 
353
362
        The 'var' section
354
363
        -----------------
355
364
        Each line in the 'var' section has the following syntax:
356
365
 
357
366
                variable-name = value \n
358
 
        
 
367
 
359
368
        Where "variable-name" is the name of a GNU Info variable and
360
369
        "value" is the value that GNU Info will assign to that variable
361
370
        when commencing execution.  There must be no white space in the
366
375
        following the '=' is not ignored.
367
376
 */
368
377
 
369
 
static int add_to_section (), lookup_action ();
 
378
static int add_to_section (struct sect *s, const char *str, unsigned int len);
 
379
static int lookup_action (const char *actname);
370
380
 
371
381
/* Compile the input file into its various sections.  Return true if no
372
382
   error was encountered.
373
383
 */
374
384
static int
375
 
compile (fp, filename, sections)
376
 
     FILE *fp;
377
 
     const char *filename;
378
 
     struct sect sections[];
 
385
compile (FILE *fp, const char *filename, struct sect *sections)
379
386
{
380
387
  int error = 0;
381
388
  char rescan = 0;
382
389
  unsigned int lnum = 0;
383
 
  int c;
 
390
  int c = 0;
384
391
 
385
392
  /* This parser is a true state machine, with no sneaky fetching
386
393
     of input characters inside the main loop.  In other words, all
400
407
      got_varname,
401
408
      get_equals,
402
409
      got_equals,
403
 
      get_value,
 
410
      get_value
404
411
    }
405
412
  state = start_of_line;
406
413
  enum sect_e section = info;
410
417
      slosh,
411
418
      control,
412
419
      octal,
413
 
      special_key,
 
420
      special_key
414
421
    }
415
 
  seqstate;                     /* used if state == get_keyseq */
 
422
  seqstate;             /* used if state == get_keyseq */
416
423
  char meta = 0;
417
 
  char ocnt;                    /* used if state == get_keyseq && seqstate == octal */
 
424
  char ocnt = 0;        /* used if state == get_keyseq && seqstate == octal */
418
425
 
419
426
  /* Data is accumulated in the following variables.  The code
420
427
     avoids overflowing these strings, and throws an error
422
429
     lengths are arbitrary (and should be large enough) and their
423
430
     lengths are not hard-coded anywhere else, so increasing them
424
431
     here will not break anything.  */
425
 
  char oval;
 
432
  char oval = 0;
426
433
  char comment[10];
427
 
  unsigned int clen;
 
434
  unsigned int clen = 0;
428
435
  char seq[20];
429
 
  unsigned int slen;
 
436
  unsigned int slen = 0;
430
437
  char act[80];
431
 
  unsigned int alen;
 
438
  unsigned int alen = 0;
432
439
  char varn[80];
433
 
  unsigned int varlen;
 
440
  unsigned int varlen = 0;
434
441
  char val[80];
435
 
  unsigned int vallen;
 
442
  unsigned int vallen = 0;
436
443
 
437
444
#define To_seq(c) \
438
445
                  do { \
440
447
                      seq[slen++] = meta ? Meta(c) : (c); \
441
448
                    else \
442
449
                      { \
443
 
                        syntax_error(filename, lnum, _("key sequence too long")); \
 
450
                        syntax_error(filename, lnum, _("key sequence too long"), \
 
451
                            NULL, NULL, NULL, NULL); \
444
452
                        error = 1; \
445
453
                      } \
446
454
                    meta = 0; \
518
526
                  rescan = 1;
519
527
                  if (slen == 0)
520
528
                    {
521
 
                      syntax_error (filename, lnum, _("missing key sequence"));
 
529
                      syntax_error (filename, lnum, _("missing key sequence"),
 
530
                          NULL, NULL, NULL, NULL);
522
531
                      error = 1;
523
532
                    }
524
533
                }
567
576
                  seqstate = special_key;
568
577
                  break;
569
578
                default:
570
 
                  /* Backslash followed by any other char 
 
579
                  /* Backslash followed by any other char
571
580
                     just means that char.  */
572
581
                  To_seq (c);
573
582
                  seqstate = normal;
597
606
                    To_seq (oval);
598
607
                  else
599
608
                    {
600
 
                      syntax_error (filename, lnum, _("NUL character (\\000) not permitted"));
 
609
                      syntax_error (filename, lnum,
 
610
                          _("NUL character (\\000) not permitted"),
 
611
                          NULL, NULL, NULL, NULL);
601
612
                      error = 1;
602
613
                    }
603
614
                }
626
637
                To_seq (CONTROL (c));
627
638
              else
628
639
                {
629
 
                  syntax_error (filename, lnum, _("NUL character (^%c) not permitted"), c);
 
640
                  syntax_error (filename, lnum,
 
641
                      (char *) _("NUL character (^%c) not permitted"),
 
642
                      (void *) (long) c, NULL, NULL, NULL);
630
643
                  error = 1;
631
644
                }
632
645
              seqstate = normal;
649
662
              rescan = 1;
650
663
              if (alen == 0)
651
664
                {
652
 
                  syntax_error (filename, lnum, _("missing action name"), c);
 
665
                  syntax_error (filename, lnum, (char *) _("missing action name"),
 
666
                                (void *) (long) c, NULL, NULL, NULL);
653
667
                  error = 1;
654
668
                }
655
669
              else
664
678
                            && add_to_section (&sections[section], "", 1)
665
679
                            && add_to_section (&sections[section], &av, 1)))
666
680
                        {
667
 
                          syntax_error (filename, lnum, _("section too long"));
 
681
                          syntax_error (filename, lnum, _("section too long"),
 
682
                              NULL, NULL, NULL, NULL);
668
683
                          error = 1;
669
684
                        }
670
685
                    }
671
686
                  else
672
687
                    {
673
 
                      syntax_error (filename, lnum, _("unknown action `%s'"), act);
 
688
                      syntax_error (filename, lnum, _("unknown action `%s'"),
 
689
                          act, NULL, NULL, NULL);
674
690
                      error = 1;
675
691
                    }
676
692
                }
679
695
            act[alen++] = c;
680
696
          else
681
697
            {
682
 
              syntax_error (filename, lnum, _("action name too long"));
 
698
              syntax_error (filename, lnum, _("action name too long"),
 
699
                  NULL, NULL, NULL, NULL);
683
700
              error = 1;
684
701
            }
685
702
          break;
686
 
        
 
703
 
687
704
        case got_action:
688
705
          if (c == '#')
689
706
            state = in_trailing_comment;
691
708
            state = start_of_line;
692
709
          else if (!isspace (c))
693
710
            {
694
 
              syntax_error (filename, lnum, _("extra characters following action `%s'"), act);
 
711
              syntax_error (filename, lnum,
 
712
                  _("extra characters following action `%s'"),
 
713
                  act, NULL, NULL, NULL);
695
714
              error = 1;
696
715
            }
697
716
          break;
701
720
            {
702
721
              if (varlen == 0)
703
722
                {
704
 
                  syntax_error (filename, lnum, _("missing variable name"));
 
723
                  syntax_error (filename, lnum, _("missing variable name"),
 
724
                      NULL, NULL, NULL, NULL);
705
725
                  error = 1;
706
726
                }
707
727
              state = get_value;
709
729
            }
710
730
          else if (c == '\n' || isspace (c))
711
731
            {
712
 
              syntax_error (filename, lnum, _("missing `=' immediately after variable name"));
 
732
              syntax_error (filename, lnum,
 
733
                  _("missing `=' immediately after variable name"),
 
734
                  NULL, NULL, NULL, NULL);
713
735
              error = 1;
714
736
            }
715
737
          else if (varlen < sizeof varn)
716
738
            varn[varlen++] = c;
717
739
          else
718
740
            {
719
 
              syntax_error (filename, lnum, _("variable name too long"));
 
741
              syntax_error (filename, lnum, _("variable name too long"),
 
742
                  NULL, NULL, NULL, NULL);
720
743
              error = 1;
721
744
            }
722
745
          break;
723
 
        
 
746
 
724
747
        case get_value:
725
748
          if (c == '\n')
726
749
            {
730
753
                    && add_to_section (&sections[section], val, vallen)
731
754
                    && add_to_section (&sections[section], "", 1)))
732
755
                {
733
 
                  syntax_error (filename, lnum, _("section too long"));
 
756
                  syntax_error (filename, lnum, _("section too long"),
 
757
                      NULL, NULL, NULL, NULL);
734
758
                  error = 1;
735
759
                }
736
760
            }
738
762
            val[vallen++] = c;
739
763
          else
740
764
            {
741
 
              syntax_error (filename, lnum, _("value too long"));
 
765
              syntax_error (filename, lnum, _("value too long"),
 
766
                  NULL, NULL, NULL, NULL);
742
767
              error = 1;
743
768
            }
744
769
          break;
 
770
 
 
771
        case get_equals:
 
772
        case got_equals:
 
773
        case got_varname:
 
774
          break;
745
775
        }
746
776
    }
747
777
 
754
784
   characters fit, or false if the section's size limit was exceeded.
755
785
 */
756
786
static int
757
 
add_to_section (s, str, len)
758
 
     struct sect *s;
759
 
     const char *str;
760
 
     unsigned int len;
 
787
add_to_section (struct sect *s, const char *str, unsigned int len)
761
788
{
762
789
  if (s->cur + len > sizeof s->data)
763
790
    return 0;
764
 
  strncpy (s->data + s->cur, str, len);
 
791
  strncpy ((char *) s->data + s->cur, str, len);
765
792
  s->cur += len;
766
793
  return 1;
767
794
}
770
797
   auto-generated array in key.c.
771
798
 */
772
799
static int
773
 
lookup_action (actname)
774
 
     const char *actname;
 
800
lookup_action (const char *actname)
775
801
{
776
802
  int i;
777
803
 
788
814
   in radix INFOKEY_RADIX.
789
815
 */
790
816
static int
791
 
putint (i, fp)
792
 
     int i;
793
 
     FILE *fp;
 
817
putint (int i, FILE *fp)
794
818
{
795
819
  return fputc (i % INFOKEY_RADIX, fp) != EOF
796
820
    && fputc ((i / INFOKEY_RADIX) % INFOKEY_RADIX, fp) != EOF;
800
824
   empty, simply omit it.
801
825
 */
802
826
static int
803
 
putsect (s, code, fp)
804
 
     struct sect *s;
805
 
     int code;
806
 
     FILE *fp;
 
827
putsect (struct sect *s, int code, FILE *fp)
807
828
{
808
829
  if (s->cur == 0)
809
830
    return 1;
815
836
/* Write an entire infokey file, given an array containing its sections.
816
837
 */
817
838
static int
818
 
write_infokey_file (fp, sections)
819
 
     FILE *fp;
820
 
     struct sect sections[];
 
839
write_infokey_file (FILE *fp, struct sect *sections)
821
840
{
822
841
  /* Get rid of sections with no effect. */
823
842
  if (sections[info].cur == 1 && sections[info].data[0] == 0)
849
868
        progname: "filename", line N: message
850
869
 */
851
870
static void
852
 
error_message (error_code, fmt, a1, a2, a3, a4)
853
 
     int error_code;
854
 
     const char *fmt;
855
 
     const void *a1, *a2, *a3, *a4;
 
871
error_message (int error_code, const char *fmt,
 
872
    const void *a1, const void *a2, const void *a3, const void *a4)
856
873
{
857
874
  fprintf (stderr, "%s: ", program_name);
858
875
  fprintf (stderr, fmt, a1, a2, a3, a4);
865
882
        progname: message
866
883
 */
867
884
static void
868
 
syntax_error (filename, linenum, fmt, a1, a2, a3, a4)
869
 
     const char *filename;
870
 
     unsigned int linenum;
871
 
     const char *fmt;
872
 
     const void *a1, *a2, *a3, *a4;
 
885
syntax_error (const char *filename,
 
886
    unsigned int linenum, const char *fmt,
 
887
    const void *a1, const void *a2, const void *a3, const void *a4)
873
888
{
874
889
  fprintf (stderr, "%s: ", program_name);
875
890
  fprintf (stderr, _("\"%s\", line %u: "), filename, linenum);
879
894
 
880
895
/* Produce a gentle rtfm. */
881
896
static void
882
 
suggest_help ()
 
897
suggest_help (void)
883
898
{
884
899
  fprintf (stderr, _("Try --help for more information.\n"));
885
900
}
886
901
 
887
902
/* Produce a scaled down description of the available options to Info. */
888
903
static void
889
 
short_help ()
 
904
short_help (void)
890
905
{
891
 
  printf (_ ("\
 
906
  printf (_("\
892
907
Usage: %s [OPTION]... [INPUT-FILE]\n\
893
908
\n\
894
909
Compile infokey source file to infokey file.  Reads INPUT-FILE (default\n\
898
913
  --output FILE        output to FILE instead of $HOME/.info\n\
899
914
  --help               display this help and exit.\n\
900
915
  --version            display version information and exit.\n\
901
 
\n\
 
916
"), program_name);
 
917
 
 
918
  puts (_("\n\
902
919
Email bug reports to bug-texinfo@gnu.org,\n\
903
920
general questions and discussion to help-texinfo@gnu.org.\n\
904
 
"),
905
 
          program_name
906
 
    );
 
921
Texinfo home page: http://www.gnu.org/software/texinfo/"));
 
922
 
907
923
  xexit (0);
908
924
}