OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libgfortran/] [runtime/] [environ.c] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* Copyright (C) 2002,2003,2005 Free Software Foundation, Inc.
2
   Contributed by Andy Vaught
3
 
4
This file is part of the GNU Fortran 95 runtime library (libgfortran).
5
 
6
Libgfortran is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
In addition to the permissions in the GNU General Public License, the
12
Free Software Foundation gives you unlimited permission to link the
13
compiled version of this file into combinations with other programs,
14
and to distribute those combinations without any restriction coming
15
from the use of this file.  (The General Public License restrictions
16
do apply in other respects; for example, they cover modification of
17
the file, and distribution when not linked into a combine
18
executable.)
19
 
20
Libgfortran is distributed in the hope that it will be useful,
21
but WITHOUT ANY WARRANTY; without even the implied warranty of
22
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
GNU General Public License for more details.
24
 
25
You should have received a copy of the GNU General Public License
26
along with libgfortran; see the file COPYING.  If not, write to
27
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
28
Boston, MA 02110-1301, USA.  */
29
 
30
#include "config.h"
31
#include <stdio.h>
32
#include <string.h>
33
#include <stdlib.h>
34
#include <ctype.h>
35
 
36
#include "libgfortran.h"
37
#include "../io/io.h"
38
 
39
 
40
/* Environment scanner.  Examine the environment for controlling minor
41
 * aspects of the program's execution.  Our philosophy here that the
42
 * environment should not prevent the program from running, so an
43
 * environment variable with a messed-up value will be interpreted in
44
 * the default way.
45
 *
46
 * Most of the environment is checked early in the startup sequence,
47
 * but other variables are checked during execution of the user's
48
 * program. */
49
 
50
options_t options;
51
 
52
 
53
typedef struct variable
54
{
55
  const char *name;
56
  int value, *var;
57
  void (*init) (struct variable *);
58
  void (*show) (struct variable *);
59
  const char *desc;
60
  int bad;
61
}
62
variable;
63
 
64
static void init_unformatted (variable *);
65
 
66
/* print_spaces()-- Print a particular number of spaces.  */
67
 
68
static void
69
print_spaces (int n)
70
{
71
  char buffer[80];
72
  int i;
73
 
74
  if (n <= 0)
75
    return;
76
 
77
  for (i = 0; i < n; i++)
78
    buffer[i] = ' ';
79
 
80
  buffer[i] = '\0';
81
 
82
  st_printf (buffer);
83
}
84
 
85
 
86
/* var_source()-- Return a string that describes where the value of a
87
 * variable comes from */
88
 
89
static const char *
90
var_source (variable * v)
91
{
92
  if (getenv (v->name) == NULL)
93
    return "Default";
94
 
95
  if (v->bad)
96
    return "Bad    ";
97
 
98
  return "Set    ";
99
}
100
 
101
 
102
/* init_integer()-- Initialize an integer environment variable.  */
103
 
104
static void
105
init_integer (variable * v)
106
{
107
  char *p, *q;
108
 
109
  p = getenv (v->name);
110
  if (p == NULL)
111
    goto set_default;
112
 
113
  for (q = p; *q; q++)
114
    if (!isdigit (*q) && (p != q || *q != '-'))
115
      {
116
        v->bad = 1;
117
        goto set_default;
118
      }
119
 
120
  *v->var = atoi (p);
121
  return;
122
 
123
 set_default:
124
  *v->var = v->value;
125
  return;
126
}
127
 
128
 
129
/* init_unsigned_integer()-- Initialize an integer environment variable
130
   which has to be positive.  */
131
 
132
static void
133
init_unsigned_integer (variable * v)
134
{
135
  char *p, *q;
136
 
137
  p = getenv (v->name);
138
  if (p == NULL)
139
    goto set_default;
140
 
141
  for (q = p; *q; q++)
142
    if (!isdigit (*q))
143
      {
144
        v->bad = 1;
145
        goto set_default;
146
      }
147
 
148
  *v->var = atoi (p);
149
  return;
150
 
151
 set_default:
152
  *v->var = v->value;
153
  return;
154
}
155
 
156
 
157
/* show_integer()-- Show an integer environment variable */
158
 
159
static void
160
show_integer (variable * v)
161
{
162
  st_printf ("%s  %d\n", var_source (v), *v->var);
163
}
164
 
165
 
166
/* init_boolean()-- Initialize a boolean environment variable.  We
167
 * only look at the first letter of the variable. */
168
 
169
static void
170
init_boolean (variable * v)
171
{
172
  char *p;
173
 
174
  p = getenv (v->name);
175
  if (p == NULL)
176
    goto set_default;
177
 
178
  if (*p == '1' || *p == 'Y' || *p == 'y')
179
    {
180
      *v->var = 1;
181
      return;
182
    }
183
 
184
  if (*p == '0' || *p == 'N' || *p == 'n')
185
    {
186
      *v->var = 0;
187
      return;
188
    }
189
 
190
  v->bad = 1;
191
 
192
set_default:
193
  *v->var = v->value;
194
  return;
195
}
196
 
197
 
198
/* show_boolean()-- Show a boolean environment variable */
199
 
200
static void
201
show_boolean (variable * v)
202
{
203
  st_printf ("%s  %s\n", var_source (v), *v->var ? "Yes" : "No");
204
}
205
 
206
 
207
/* init_mem()-- Initialize environment variables that have to do with
208
 * how memory from an ALLOCATE statement is filled.  A single flag
209
 * enables filling and a second variable gives the value that is used
210
 * to initialize the memory. */
211
 
212
static void
213
init_mem (variable * v)
214
{
215
  int offset, n;
216
  char *p;
217
 
218
  p = getenv (v->name);
219
 
220
  options.allocate_init_flag = 0;        /* The default */
221
 
222
  if (p == NULL)
223
    return;
224
 
225
  if (strcasecmp (p, "NONE") == 0)
226
    return;
227
 
228
  /* IEEE-754 Quiet Not-a-Number that will work for single and double
229
   * precision.  Look for the 'f95' mantissa in debug dumps. */
230
 
231
  if (strcasecmp (p, "NaN") == 0)
232
    {
233
      options.allocate_init_flag = 1;
234
      options.allocate_init_value = 0xfff80f95;
235
      return;
236
    }
237
 
238
  /* Interpret the string as a hexadecimal constant */
239
 
240
  n = 0;
241
  while (*p)
242
    {
243
      if (!isxdigit (*p))
244
        {
245
          v->bad = 1;
246
          return;
247
        }
248
 
249
      offset = '0';
250
      if (islower (*p))
251
        offset = 'a';
252
      if (isupper (*p))
253
        offset = 'A';
254
 
255
      n = (n << 4) | (*p++ - offset);
256
    }
257
 
258
  options.allocate_init_flag = 1;
259
  options.allocate_init_value = n;
260
}
261
 
262
 
263
static void
264
show_mem (variable * v)
265
{
266
  char *p;
267
 
268
  p = getenv (v->name);
269
 
270
  st_printf ("%s  ", var_source (v));
271
 
272
  if (options.allocate_init_flag)
273
    st_printf ("0x%x", options.allocate_init_value);
274
 
275
  st_printf ("\n");
276
}
277
 
278
 
279
static void
280
init_sep (variable * v)
281
{
282
  int seen_comma;
283
  char *p;
284
 
285
  p = getenv (v->name);
286
  if (p == NULL)
287
    goto set_default;
288
 
289
  v->bad = 1;
290
  options.separator = p;
291
  options.separator_len = strlen (p);
292
 
293
  /* Make sure the separator is valid */
294
 
295
  if (options.separator_len == 0)
296
    goto set_default;
297
  seen_comma = 0;
298
 
299
  while (*p)
300
    {
301
      if (*p == ',')
302
        {
303
          if (seen_comma)
304
            goto set_default;
305
          seen_comma = 1;
306
          p++;
307
          continue;
308
        }
309
 
310
      if (*p++ != ' ')
311
        goto set_default;
312
    }
313
 
314
  v->bad = 0;
315
  return;
316
 
317
set_default:
318
  options.separator = " ";
319
  options.separator_len = 1;
320
}
321
 
322
 
323
static void
324
show_sep (variable * v)
325
{
326
  st_printf ("%s  \"%s\"\n", var_source (v), options.separator);
327
}
328
 
329
 
330
static void
331
init_string (variable * v __attribute__ ((unused)))
332
{
333
}
334
 
335
static void
336
show_string (variable * v)
337
{
338
  const char *p;
339
 
340
  p = getenv (v->name);
341
  if (p == NULL)
342
    p = "";
343
 
344
  st_printf ("%s  \"%s\"\n", var_source (v), p);
345
}
346
 
347
 
348
/* Structure for associating names and values.  */
349
 
350
typedef struct
351
{
352
  const char *name;
353
  int value;
354
}
355
choice;
356
 
357
 
358
enum
359
{ FP_ROUND_NEAREST, FP_ROUND_UP, FP_ROUND_DOWN, FP_ROUND_ZERO };
360
 
361
static const choice rounding[] = {
362
  {"NEAREST", FP_ROUND_NEAREST},
363
  {"UP", FP_ROUND_UP},
364
  {"DOWN", FP_ROUND_DOWN},
365
  {"ZERO", FP_ROUND_ZERO},
366
  {NULL, 0}
367
};
368
 
369
static const choice precision[] =
370
{
371
  { "24", 1},
372
  { "53", 2},
373
  { "64", 0},
374
  { NULL, 0}
375
};
376
 
377
static const choice signal_choices[] =
378
{
379
  { "IGNORE", 1},
380
  { "ABORT", 0},
381
  { NULL, 0}
382
};
383
 
384
 
385
static void
386
init_choice (variable * v, const choice * c)
387
{
388
  char *p;
389
 
390
  p = getenv (v->name);
391
  if (p == NULL)
392
    goto set_default;
393
 
394
  for (; c->name; c++)
395
    if (strcasecmp (c->name, p) == 0)
396
      break;
397
 
398
  if (c->name == NULL)
399
    {
400
      v->bad = 1;
401
      goto set_default;
402
    }
403
 
404
  *v->var = c->value;
405
  return;
406
 
407
 set_default:
408
  *v->var = v->value;
409
}
410
 
411
 
412
static void
413
show_choice (variable * v, const choice * c)
414
{
415
  st_printf ("%s  ", var_source (v));
416
 
417
  for (; c->name; c++)
418
    if (c->value == *v->var)
419
      break;
420
 
421
  if (c->name)
422
    st_printf ("%s\n", c->name);
423
  else
424
    st_printf ("(Unknown)\n");
425
}
426
 
427
 
428
static void
429
init_round (variable * v)
430
{
431
  init_choice (v, rounding);
432
}
433
 
434
static void
435
show_round (variable * v)
436
{
437
  show_choice (v, rounding);
438
}
439
 
440
static void
441
init_precision (variable * v)
442
{
443
  init_choice (v, precision);
444
}
445
 
446
static void
447
show_precision (variable * v)
448
{
449
  show_choice (v, precision);
450
}
451
 
452
static void
453
init_signal (variable * v)
454
{
455
  init_choice (v, signal_choices);
456
}
457
 
458
static void
459
show_signal (variable * v)
460
{
461
  show_choice (v, signal_choices);
462
}
463
 
464
 
465
static variable variable_table[] = {
466
  {"GFORTRAN_STDIN_UNIT", 5, &options.stdin_unit, init_integer, show_integer,
467
   "Unit number that will be preconnected to standard input\n"
468
   "(No preconnection if negative)", 0},
469
 
470
  {"GFORTRAN_STDOUT_UNIT", 6, &options.stdout_unit, init_integer,
471
   show_integer,
472
   "Unit number that will be preconnected to standard output\n"
473
   "(No preconnection if negative)", 0},
474
 
475
  {"GFORTRAN_STDERR_UNIT", 0, &options.stderr_unit, init_integer,
476
   show_integer,
477
   "Unit number that will be preconnected to standard error\n"
478
   "(No preconnection if negative)", 0},
479
 
480
  {"GFORTRAN_USE_STDERR", 1, &options.use_stderr, init_boolean,
481
   show_boolean,
482
   "Sends library output to standard error instead of standard output.", 0},
483
 
484
  {"GFORTRAN_TMPDIR", 0, NULL, init_string, show_string,
485
   "Directory for scratch files.  Overrides the TMP environment variable\n"
486
   "If TMP is not set " DEFAULT_TEMPDIR " is used.", 0},
487
 
488
  {"GFORTRAN_UNBUFFERED_ALL", 0, &options.all_unbuffered, init_boolean,
489
   show_boolean,
490
   "If TRUE, all output is unbuffered.  This will slow down large writes "
491
   "but can be\nuseful for forcing data to be displayed immediately.", 0},
492
 
493
  {"GFORTRAN_SHOW_LOCUS", 1, &options.locus, init_boolean, show_boolean,
494
   "If TRUE, print filename and line number where runtime errors happen.", 0},
495
 
496
  {"GFORTRAN_OPTIONAL_PLUS", 0, &options.optional_plus, init_boolean, show_boolean,
497
   "Print optional plus signs in numbers where permitted.  Default FALSE.", 0},
498
 
499
  {"GFORTRAN_DEFAULT_RECL", DEFAULT_RECL, &options.default_recl,
500
   init_unsigned_integer, show_integer,
501
   "Default maximum record length for sequential files.  Most useful for\n"
502
   "adjusting line length of preconnected units.  Default "
503
   stringize (DEFAULT_RECL), 0},
504
 
505
  {"GFORTRAN_LIST_SEPARATOR", 0, NULL, init_sep, show_sep,
506
   "Separatator to use when writing list output.  May contain any number of "
507
   "spaces\nand at most one comma.  Default is a single space.", 0},
508
 
509
  /* Memory related controls */
510
 
511
  {"GFORTRAN_MEM_INIT", 0, NULL, init_mem, show_mem,
512
   "How to initialize allocated memory.  Default value is NONE for no "
513
   "initialization\n(faster), NAN for a Not-a-Number with the mantissa "
514
   "0x40f95 or a custom\nhexadecimal value", 0},
515
 
516
  {"GFORTRAN_MEM_CHECK", 0, &options.mem_check, init_boolean, show_boolean,
517
   "Whether memory still allocated will be reported when the program ends.",
518
   0},
519
 
520
  /* Signal handling (Unix).  */
521
 
522
  {"GFORTRAN_SIGHUP", 0, &options.sighup, init_signal, show_signal,
523
   "Whether the program will IGNORE or ABORT on SIGHUP.", 0},
524
 
525
  {"GFORTRAN_SIGINT", 0, &options.sigint, init_signal, show_signal,
526
   "Whether the program will IGNORE or ABORT on SIGINT.", 0},
527
 
528
  /* Floating point control */
529
 
530
  {"GFORTRAN_FPU_ROUND", 0, &options.fpu_round, init_round, show_round,
531
   "Set floating point rounding.  Values are NEAREST, UP, DOWN, ZERO.", 0},
532
 
533
  {"GFORTRAN_FPU_PRECISION", 0, &options.fpu_precision, init_precision,
534
   show_precision,
535
   "Precision of intermediate results.  Values are 24, 53 and 64.", 0},
536
 
537
  /* GFORTRAN_CONVERT_UNIT - Set the default data conversion for
538
   unformatted I/O.  */
539
  {"GFORTRAN_CONVERT_UNIT", 0, 0, init_unformatted, show_string,
540
   "Set format for unformatted files", 0},
541
 
542
  {NULL, 0, NULL, NULL, NULL, NULL, 0}
543
};
544
 
545
 
546
/* init_variables()-- Initialize most runtime variables from
547
 * environment variables. */
548
 
549
void
550
init_variables (void)
551
{
552
  variable *v;
553
 
554
  for (v = variable_table; v->name; v++)
555
    v->init (v);
556
}
557
 
558
 
559
/* check_buffered()-- Given an unit number n, determine if an override
560
 * for the stream exists.  Returns zero for unbuffered, one for
561
 * buffered or two for not set. */
562
 
563
int
564
check_buffered (int n)
565
{
566
  char name[22 + sizeof (n) * 3];
567
  variable v;
568
  int rv;
569
 
570
  if (options.all_unbuffered)
571
    return 0;
572
 
573
  sprintf (name, "GFORTRAN_UNBUFFERED_%d", n);
574
 
575
  v.name = name;
576
  v.value = 2;
577
  v.var = &rv;
578
 
579
  init_boolean (&v);
580
 
581
  return rv;
582
}
583
 
584
 
585
void
586
show_variables (void)
587
{
588
  variable *v;
589
  int n;
590
 
591
  /* TODO: print version number.  */
592
  st_printf ("GNU Fortran 95 runtime library version "
593
             "UNKNOWN" "\n\n");
594
 
595
  st_printf ("Environment variables:\n");
596
  st_printf ("----------------------\n");
597
 
598
  for (v = variable_table; v->name; v++)
599
    {
600
      n = st_printf ("%s", v->name);
601
      print_spaces (25 - n);
602
 
603
      if (v->show == show_integer)
604
        st_printf ("Integer ");
605
      else if (v->show == show_boolean)
606
        st_printf ("Boolean ");
607
      else
608
        st_printf ("String  ");
609
 
610
      v->show (v);
611
      st_printf ("%s\n\n", v->desc);
612
    }
613
 
614
  /* System error codes */
615
 
616
  st_printf ("\nRuntime error codes:");
617
  st_printf ("\n--------------------\n");
618
 
619
  for (n = ERROR_FIRST + 1; n < ERROR_LAST; n++)
620
    if (n < 0 || n > 9)
621
      st_printf ("%d  %s\n", n, translate_error (n));
622
    else
623
      st_printf (" %d  %s\n", n, translate_error (n));
624
 
625
  st_printf ("\nCommand line arguments:\n");
626
  st_printf ("  --help               Print this list\n");
627
 
628
  /* st_printf("  --resume <dropfile>  Resume program execution from dropfile\n"); */
629
 
630
  sys_exit (0);
631
}
632
 
633
/* This is the handling of the GFORTRAN_CONVERT_UNITS environment variable.
634
   It is called from environ.c to parse this variable, and from
635
   open.c to determine if the user specified a default for an
636
   unformatted file.
637
   The syntax of the environment variable is, in bison grammar:
638
 
639
   GFORTRAN_CONVERT_UNITS: mode | mode ';' exception ;
640
   mode: 'native' | 'swap' | 'big_endian' | 'little_endian' ;
641
   exception: mode ':' unit_list | unit_list ;
642
   unit_list: unit_spec | unit_list unit_spec ;
643
   unit_spec: INTEGER | INTEGER '-' INTEGER ;
644
*/
645
 
646
/* Defines for the tokens.  Other valid tokens are ',', ':', '-'.  */
647
 
648
 
649
#define NATIVE   257
650
#define SWAP     258
651
#define BIG      259
652
#define LITTLE   260
653
/* Some space for additional tokens later.  */
654
#define INTEGER  273
655
#define END      (-1)
656
#define ILLEGAL  (-2)
657
 
658
typedef struct
659
{
660
  int unit;
661
  unit_convert conv;
662
} exception_t;
663
 
664
 
665
static char *p;            /* Main character pointer for parsing.  */
666
static char *lastpos;      /* Auxiliary pointer, for backing up.  */
667
static int unit_num;       /* The last unit number read.  */
668
static int unit_count;     /* The number of units found. */
669
static int do_count;       /* Parsing is done twice - first to count the number
670
                              of units, then to fill in the table.  This
671
                              variable controls what to do.  */
672
static exception_t *elist; /* The list of exceptions to the default. This is
673
                              sorted according to unit number.  */
674
static int n_elist;        /* Number of exceptions to the default.  */
675
 
676
static unit_convert endian; /* Current endianness.  */
677
 
678
static unit_convert def; /* Default as specified (if any).  */
679
 
680
/* Search for a unit number, using a binary search.  The
681
   first argument is the unit number to search for.  The second argument
682
   is a pointer to an index.
683
   If the unit number is found, the function returns 1, and the index
684
   is that of the element.
685
   If the unit number is not found, the function returns 0, and the
686
   index is the one where the element would be inserted.  */
687
 
688
static int
689
search_unit (int unit, int *ip)
690
{
691
  int low, high, mid;
692
 
693
  low = -1;
694
  high = n_elist;
695
  while (high - low > 1)
696
    {
697
      mid = (low + high) / 2;
698
      if (unit <= elist[mid].unit)
699
        high = mid;
700
      else
701
        low = mid;
702
    }
703
  *ip = high;
704
  if (elist[high].unit == unit)
705
    return 1;
706
  else
707
    return 0;
708
}
709
 
710
/* This matches a keyword.  If it is found, return the token supplied,
711
   otherwise return ILLEGAL.  */
712
 
713
static int
714
match_word (const char *word, int tok)
715
{
716
  int res;
717
 
718
  if (strncasecmp (p, word, strlen (word)) == 0)
719
    {
720
      p += strlen (word);
721
      res = tok;
722
    }
723
  else
724
    res = ILLEGAL;
725
  return res;
726
 
727
}
728
 
729
/* Match an integer and store its value in unit_num.  This only works
730
   if p actually points to the start of an integer.  The caller has
731
   to ensure this.  */
732
 
733
static int
734
match_integer (void)
735
{
736
  unit_num = 0;
737
  while (isdigit (*p))
738
    unit_num = unit_num * 10 + (*p++ - '0');
739
  return INTEGER;
740
 
741
}
742
 
743
/* This reads the next token from the GFORTRAN_CONVERT_UNITS variable.
744
   Returned values are the different tokens.  */
745
 
746
static int
747
next_token (void)
748
{
749
  int result;
750
 
751
  lastpos = p;
752
  switch (*p)
753
    {
754
    case '\0':
755
      result = END;
756
      break;
757
 
758
    case ':':
759
    case ',':
760
    case '-':
761
    case ';':
762
      result = *p;
763
      p++;
764
      break;
765
 
766
    case 'b':
767
    case 'B':
768
      result = match_word ("big_endian", BIG);
769
      break;
770
 
771
    case 'l':
772
    case 'L':
773
      result = match_word ("little_endian", LITTLE);
774
      break;
775
 
776
    case 'n':
777
    case 'N':
778
      result = match_word ("native", NATIVE);
779
      break;
780
 
781
    case 's':
782
    case 'S':
783
      result = match_word ("swap", SWAP);
784
      break;
785
 
786
    case '1': case '2': case '3': case '4': case '5':
787
    case '6': case '7': case '8': case '9':
788
      result = match_integer ();
789
      break;
790
 
791
    default:
792
      result = ILLEGAL;
793
      break;
794
    }
795
  return result;
796
}
797
 
798
/* Back up the last token by setting back the character pointer.  */
799
 
800
static void
801
push_token (void)
802
{
803
  p = lastpos;
804
}
805
 
806
/* This is called when a unit is identified.  If do_count is nonzero,
807
   increment the number of units by one.  If do_count is zero,
808
   put the unit into the table.  */
809
 
810
static void
811
mark_single (int unit)
812
{
813
  int i,j;
814
 
815
  if (do_count)
816
    {
817
      unit_count++;
818
      return;
819
    }
820
  if (search_unit (unit, &i))
821
    {
822
      elist[unit].conv = endian;
823
    }
824
  else
825
    {
826
      for (j=n_elist; j>=i; j--)
827
        elist[j+1] = elist[j];
828
 
829
      n_elist += 1;
830
      elist[i].unit = unit;
831
      elist[i].conv = endian;
832
    }
833
}
834
 
835
/* This is called when a unit range is identified.  If do_count is
836
   nonzero, increase the number of units.  If do_count is zero,
837
   put the unit into the table.  */
838
 
839
static void
840
mark_range (int unit1, int unit2)
841
{
842
  int i;
843
  if (do_count)
844
    unit_count += abs (unit2 - unit1) + 1;
845
  else
846
    {
847
      if (unit2 < unit1)
848
        for (i=unit2; i<=unit1; i++)
849
          mark_single (i);
850
      else
851
        for (i=unit1; i<=unit2; i++)
852
          mark_single (i);
853
    }
854
}
855
 
856
/* Parse the GFORTRAN_CONVERT_UNITS variable.  This is called
857
   twice, once to count the units and once to actually mark them in
858
   the table.  When counting, we don't check for double occurences
859
   of units.  */
860
 
861
static int
862
do_parse (void)
863
{
864
  int tok, def;
865
  int unit1;
866
  int continue_ulist;
867
  char *start;
868
 
869
  unit_count = 0;
870
 
871
  def = 0;
872
  start = p;
873
 
874
  /* Parse the string.  First, let's look for a default.  */
875
  tok = next_token ();
876
  switch (tok)
877
    {
878
    case NATIVE:
879
      endian = CONVERT_NATIVE;
880
      break;
881
 
882
    case SWAP:
883
      endian = CONVERT_SWAP;
884
      break;
885
 
886
    case BIG:
887
      endian = CONVERT_BIG;
888
      break;
889
 
890
    case LITTLE:
891
      endian = CONVERT_LITTLE;
892
      break;
893
 
894
    case INTEGER:
895
      /* A leading digit means that we are looking at an exception.
896
         Reset the position to the beginning, and continue processing
897
         at the exception list.  */
898
      p = start;
899
      goto exceptions;
900
      break;
901
 
902
    case END:
903
      goto end;
904
      break;
905
 
906
    default:
907
      goto error;
908
      break;
909
    }
910
 
911
  tok = next_token ();
912
  switch (tok)
913
    {
914
    case ';':
915
      def = endian;
916
      break;
917
 
918
    case ':':
919
      /* This isn't a default after all.  Reset the position to the
920
         beginning, and continue processing at the exception list.  */
921
      p = start;
922
      goto exceptions;
923
      break;
924
 
925
    case END:
926
      goto end;
927
      break;
928
 
929
    default:
930
      goto error;
931
      break;
932
    }
933
 
934
 exceptions:
935
 
936
  /* Loop over all exceptions.  */
937
  while(1)
938
    {
939
      tok = next_token ();
940
      switch (tok)
941
        {
942
        case LITTLE:
943
          if (next_token () != ':')
944
            goto error;
945
          endian = CONVERT_LITTLE;
946
          break;
947
 
948
        case BIG:
949
          if (next_token () != ':')
950
            goto error;
951
          endian = CONVERT_BIG;
952
          break;
953
 
954
        case INTEGER:
955
          push_token ();
956
          break;
957
 
958
        case END:
959
          goto end;
960
          break;
961
 
962
        default:
963
          goto error;
964
          break;
965
        }
966
      /* We arrive here when we want to parse a list of
967
         numbers.  */
968
      continue_ulist = 1;
969
      do
970
        {
971
          tok = next_token ();
972
          if (tok != INTEGER)
973
            goto error;
974
 
975
          unit1 = unit_num;
976
          tok = next_token ();
977
          /* The number can be followed by a - and another number,
978
             which means that this is a unit range, a comma
979
             or a semicolon.  */
980
          if (tok == '-')
981
            {
982
              if (next_token () != INTEGER)
983
                goto error;
984
 
985
              mark_range (unit1, unit_num);
986
              tok = next_token ();
987
              if (tok == END)
988
                goto end;
989
              else if (tok == ';')
990
                continue_ulist = 0;
991
              else if (tok != ',')
992
                goto error;
993
            }
994
          else
995
            {
996
              mark_single (unit1);
997
              switch (tok)
998
                {
999
                case ';':
1000
                  continue_ulist = 0;
1001
                  break;
1002
 
1003
                case ',':
1004
                  break;
1005
 
1006
                case END:
1007
                  goto end;
1008
                  break;
1009
 
1010
                default:
1011
                  goto error;
1012
                }
1013
            }
1014
        } while (continue_ulist);
1015
    }
1016
 end:
1017
  return 0;
1018
 error:
1019
  def = CONVERT_NONE;
1020
  return -1;
1021
}
1022
 
1023
void init_unformatted (variable * v)
1024
{
1025
  char *val;
1026
  val = getenv (v->name);
1027
  def = CONVERT_NONE;
1028
  n_elist = 0;
1029
 
1030
  if (val == NULL)
1031
    return;
1032
  do_count = 1;
1033
  p = val;
1034
  do_parse ();
1035
  if (do_count <= 0)
1036
    {
1037
      n_elist = 0;
1038
      elist = NULL;
1039
    }
1040
  else
1041
    {
1042
      elist = get_mem (unit_count * sizeof (exception_t));
1043
      do_count = 0;
1044
      p = val;
1045
      do_parse ();
1046
    }
1047
}
1048
 
1049
/* Get the default conversion for for an unformatted unit.  */
1050
 
1051
unit_convert
1052
get_unformatted_convert (int unit)
1053
{
1054
  int i;
1055
 
1056
  if (elist == NULL)
1057
    return def;
1058
  else if (search_unit (unit, &i))
1059
    return elist[i].conv;
1060
  else
1061
    return def;
1062
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.