environ.c revision 1.1.1.3 1 1.1.1.3 mrg /* Copyright (C) 2002-2022 Free Software Foundation, Inc.
2 1.1 mrg Contributed by Andy Vaught
3 1.1 mrg
4 1.1 mrg This file is part of the GNU Fortran runtime library (libgfortran).
5 1.1 mrg
6 1.1 mrg Libgfortran is free software; you can redistribute it and/or modify
7 1.1 mrg it under the terms of the GNU General Public License as published by
8 1.1 mrg the Free Software Foundation; either version 3, or (at your option)
9 1.1 mrg any later version.
10 1.1 mrg
11 1.1 mrg Libgfortran is distributed in the hope that it will be useful,
12 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 mrg GNU General Public License for more details.
15 1.1 mrg
16 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
17 1.1 mrg permissions described in the GCC Runtime Library Exception, version
18 1.1 mrg 3.1, as published by the Free Software Foundation.
19 1.1 mrg
20 1.1 mrg You should have received a copy of the GNU General Public License and
21 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
22 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 1.1 mrg <http://www.gnu.org/licenses/>. */
24 1.1 mrg
25 1.1 mrg #include "libgfortran.h"
26 1.1 mrg
27 1.1 mrg #include <string.h>
28 1.1 mrg #include <strings.h>
29 1.1 mrg
30 1.1 mrg #ifdef HAVE_UNISTD_H
31 1.1 mrg #include <unistd.h>
32 1.1 mrg #endif
33 1.1 mrg
34 1.1 mrg
35 1.1 mrg /* Implementation of secure_getenv() for targets where it is not
36 1.1 mrg provided. */
37 1.1 mrg
38 1.1 mrg #ifdef FALLBACK_SECURE_GETENV
39 1.1 mrg
40 1.1 mrg #if SUPPORTS_WEAKREF && defined(HAVE___SECURE_GETENV)
41 1.1 mrg static char* weak_secure_getenv (const char*)
42 1.1 mrg __attribute__((__weakref__("__secure_getenv")));
43 1.1 mrg #endif
44 1.1 mrg
45 1.1 mrg char *
46 1.1 mrg secure_getenv (const char *name)
47 1.1 mrg {
48 1.1 mrg #if SUPPORTS_WEAKREF && defined(HAVE___SECURE_GETENV)
49 1.1 mrg if (weak_secure_getenv)
50 1.1 mrg return weak_secure_getenv (name);
51 1.1 mrg #endif
52 1.1 mrg
53 1.1 mrg if ((getuid () == geteuid ()) && (getgid () == getegid ()))
54 1.1 mrg return getenv (name);
55 1.1 mrg else
56 1.1 mrg return NULL;
57 1.1 mrg }
58 1.1 mrg #endif
59 1.1 mrg
60 1.1 mrg
61 1.1 mrg
62 1.1 mrg /* Examine the environment for controlling aspects of the program's
63 1.1 mrg execution. Our philosophy here that the environment should not prevent
64 1.1 mrg the program from running, so any invalid value will be ignored. */
65 1.1 mrg
66 1.1 mrg
67 1.1 mrg options_t options;
68 1.1 mrg
69 1.1 mrg typedef struct variable
70 1.1 mrg {
71 1.1 mrg const char *name;
72 1.1 mrg int default_value;
73 1.1 mrg int *var;
74 1.1 mrg void (*init) (struct variable *);
75 1.1 mrg }
76 1.1 mrg variable;
77 1.1 mrg
78 1.1 mrg static void init_unformatted (variable *);
79 1.1 mrg
80 1.1 mrg
81 1.1 mrg /* Initialize an integer environment variable. */
82 1.1 mrg
83 1.1 mrg static void
84 1.1 mrg init_integer (variable * v)
85 1.1 mrg {
86 1.1 mrg char *p, *q;
87 1.1 mrg
88 1.1 mrg p = getenv (v->name);
89 1.1 mrg if (p == NULL)
90 1.1 mrg return;
91 1.1 mrg
92 1.1 mrg for (q = p; *q; q++)
93 1.1.1.3 mrg if (!safe_isdigit (*q) && (p != q || *q != '-'))
94 1.1 mrg return;
95 1.1 mrg
96 1.1 mrg *v->var = atoi (p);
97 1.1 mrg }
98 1.1 mrg
99 1.1 mrg
100 1.1 mrg /* Initialize a boolean environment variable. We only look at the first
101 1.1 mrg letter of the value. */
102 1.1 mrg
103 1.1 mrg static void
104 1.1 mrg init_boolean (variable * v)
105 1.1 mrg {
106 1.1 mrg char *p;
107 1.1 mrg
108 1.1 mrg p = getenv (v->name);
109 1.1 mrg if (p == NULL)
110 1.1 mrg return;
111 1.1 mrg
112 1.1 mrg if (*p == '1' || *p == 'Y' || *p == 'y')
113 1.1 mrg *v->var = 1;
114 1.1 mrg else if (*p == '0' || *p == 'N' || *p == 'n')
115 1.1 mrg *v->var = 0;
116 1.1 mrg }
117 1.1 mrg
118 1.1 mrg
119 1.1 mrg /* Initialize a list output separator. It may contain any number of spaces
120 1.1 mrg and at most one comma. */
121 1.1 mrg
122 1.1 mrg static void
123 1.1 mrg init_sep (variable * v)
124 1.1 mrg {
125 1.1 mrg int seen_comma;
126 1.1 mrg char *p;
127 1.1 mrg
128 1.1 mrg p = getenv (v->name);
129 1.1 mrg if (p == NULL)
130 1.1 mrg goto set_default;
131 1.1 mrg
132 1.1 mrg options.separator = p;
133 1.1 mrg options.separator_len = strlen (p);
134 1.1 mrg
135 1.1 mrg /* Make sure the separator is valid */
136 1.1 mrg
137 1.1 mrg if (options.separator_len == 0)
138 1.1 mrg goto set_default;
139 1.1 mrg seen_comma = 0;
140 1.1 mrg
141 1.1 mrg while (*p)
142 1.1 mrg {
143 1.1 mrg if (*p == ',')
144 1.1 mrg {
145 1.1 mrg if (seen_comma)
146 1.1 mrg goto set_default;
147 1.1 mrg seen_comma = 1;
148 1.1 mrg p++;
149 1.1 mrg continue;
150 1.1 mrg }
151 1.1 mrg
152 1.1 mrg if (*p++ != ' ')
153 1.1 mrg goto set_default;
154 1.1 mrg }
155 1.1 mrg
156 1.1 mrg return;
157 1.1 mrg
158 1.1 mrg set_default:
159 1.1 mrg options.separator = " ";
160 1.1 mrg options.separator_len = 1;
161 1.1 mrg }
162 1.1 mrg
163 1.1 mrg
164 1.1 mrg static variable variable_table[] = {
165 1.1 mrg
166 1.1 mrg /* Unit number that will be preconnected to standard input */
167 1.1 mrg { "GFORTRAN_STDIN_UNIT", GFC_STDIN_UNIT_NUMBER, &options.stdin_unit,
168 1.1 mrg init_integer },
169 1.1 mrg
170 1.1 mrg /* Unit number that will be preconnected to standard output */
171 1.1 mrg { "GFORTRAN_STDOUT_UNIT", GFC_STDOUT_UNIT_NUMBER, &options.stdout_unit,
172 1.1 mrg init_integer },
173 1.1 mrg
174 1.1 mrg /* Unit number that will be preconnected to standard error */
175 1.1 mrg { "GFORTRAN_STDERR_UNIT", GFC_STDERR_UNIT_NUMBER, &options.stderr_unit,
176 1.1 mrg init_integer },
177 1.1 mrg
178 1.1 mrg /* If TRUE, all output will be unbuffered */
179 1.1 mrg { "GFORTRAN_UNBUFFERED_ALL", 0, &options.all_unbuffered, init_boolean },
180 1.1 mrg
181 1.1 mrg /* If TRUE, output to preconnected units will be unbuffered */
182 1.1 mrg { "GFORTRAN_UNBUFFERED_PRECONNECTED", 0, &options.unbuffered_preconnected,
183 1.1 mrg init_boolean },
184 1.1 mrg
185 1.1 mrg /* Whether to print filename and line number on runtime error */
186 1.1 mrg { "GFORTRAN_SHOW_LOCUS", 1, &options.locus, init_boolean },
187 1.1 mrg
188 1.1 mrg /* Print optional plus signs in numbers where permitted */
189 1.1 mrg { "GFORTRAN_OPTIONAL_PLUS", 0, &options.optional_plus, init_boolean },
190 1.1 mrg
191 1.1 mrg /* Separator to use when writing list output */
192 1.1 mrg { "GFORTRAN_LIST_SEPARATOR", 0, NULL, init_sep },
193 1.1 mrg
194 1.1 mrg /* Set the default data conversion for unformatted I/O */
195 1.1 mrg { "GFORTRAN_CONVERT_UNIT", 0, 0, init_unformatted },
196 1.1 mrg
197 1.1 mrg /* Print out a backtrace if possible on runtime error */
198 1.1 mrg { "GFORTRAN_ERROR_BACKTRACE", -1, &options.backtrace, init_boolean },
199 1.1 mrg
200 1.1 mrg /* Buffer size for unformatted files. */
201 1.1 mrg { "GFORTRAN_UNFORMATTED_BUFFER_SIZE", 0, &options.unformatted_buffer_size,
202 1.1 mrg init_integer },
203 1.1 mrg
204 1.1 mrg /* Buffer size for formatted files. */
205 1.1 mrg { "GFORTRAN_FORMATTED_BUFFER_SIZE", 0, &options.formatted_buffer_size,
206 1.1 mrg init_integer },
207 1.1 mrg
208 1.1 mrg { NULL, 0, NULL, NULL }
209 1.1 mrg };
210 1.1 mrg
211 1.1 mrg
212 1.1 mrg /* Initialize most runtime variables from
213 1.1 mrg * environment variables. */
214 1.1 mrg
215 1.1 mrg void
216 1.1 mrg init_variables (void)
217 1.1 mrg {
218 1.1 mrg variable *v;
219 1.1 mrg
220 1.1 mrg for (v = variable_table; v->name; v++)
221 1.1 mrg {
222 1.1 mrg if (v->var)
223 1.1 mrg *v->var = v->default_value;
224 1.1 mrg v->init (v);
225 1.1 mrg }
226 1.1 mrg }
227 1.1 mrg
228 1.1 mrg
229 1.1 mrg /* This is the handling of the GFORTRAN_CONVERT_UNITS environment variable.
230 1.1 mrg It is called from environ.c to parse this variable, and from
231 1.1 mrg open.c to determine if the user specified a default for an
232 1.1 mrg unformatted file.
233 1.1 mrg The syntax of the environment variable is, in bison grammar:
234 1.1 mrg
235 1.1 mrg GFORTRAN_CONVERT_UNITS: mode | mode ';' exception ;
236 1.1 mrg mode: 'native' | 'swap' | 'big_endian' | 'little_endian' ;
237 1.1 mrg exception: mode ':' unit_list | unit_list ;
238 1.1 mrg unit_list: unit_spec | unit_list unit_spec ;
239 1.1 mrg unit_spec: INTEGER | INTEGER '-' INTEGER ;
240 1.1 mrg */
241 1.1 mrg
242 1.1 mrg /* Defines for the tokens. Other valid tokens are ',', ':', '-'. */
243 1.1 mrg
244 1.1 mrg
245 1.1 mrg #define NATIVE 257
246 1.1 mrg #define SWAP 258
247 1.1 mrg #define BIG 259
248 1.1 mrg #define LITTLE 260
249 1.1.1.3 mrg #ifdef HAVE_GFC_REAL_17
250 1.1.1.3 mrg #define R16_IEEE 261
251 1.1.1.3 mrg #define R16_IBM 262
252 1.1.1.3 mrg #endif
253 1.1.1.3 mrg
254 1.1 mrg /* Some space for additional tokens later. */
255 1.1 mrg #define INTEGER 273
256 1.1 mrg #define END (-1)
257 1.1 mrg #define ILLEGAL (-2)
258 1.1 mrg
259 1.1 mrg typedef struct
260 1.1 mrg {
261 1.1 mrg int unit;
262 1.1 mrg unit_convert conv;
263 1.1 mrg } exception_t;
264 1.1 mrg
265 1.1 mrg
266 1.1 mrg static char *p; /* Main character pointer for parsing. */
267 1.1 mrg static char *lastpos; /* Auxiliary pointer, for backing up. */
268 1.1 mrg static int unit_num; /* The last unit number read. */
269 1.1 mrg static int unit_count; /* The number of units found. */
270 1.1 mrg static int do_count; /* Parsing is done twice - first to count the number
271 1.1 mrg of units, then to fill in the table. This
272 1.1 mrg variable controls what to do. */
273 1.1 mrg static exception_t *elist; /* The list of exceptions to the default. This is
274 1.1 mrg sorted according to unit number. */
275 1.1 mrg static int n_elist; /* Number of exceptions to the default. */
276 1.1 mrg
277 1.1 mrg static unit_convert endian; /* Current endianness. */
278 1.1 mrg
279 1.1 mrg static unit_convert def; /* Default as specified (if any). */
280 1.1 mrg
281 1.1 mrg /* Search for a unit number, using a binary search. The
282 1.1 mrg first argument is the unit number to search for. The second argument
283 1.1 mrg is a pointer to an index.
284 1.1 mrg If the unit number is found, the function returns 1, and the index
285 1.1 mrg is that of the element.
286 1.1 mrg If the unit number is not found, the function returns 0, and the
287 1.1 mrg index is the one where the element would be inserted. */
288 1.1 mrg
289 1.1 mrg static int
290 1.1 mrg search_unit (int unit, int *ip)
291 1.1 mrg {
292 1.1 mrg int low, high, mid;
293 1.1 mrg
294 1.1 mrg if (n_elist == 0)
295 1.1 mrg {
296 1.1 mrg *ip = 0;
297 1.1 mrg return 0;
298 1.1 mrg }
299 1.1 mrg
300 1.1 mrg low = 0;
301 1.1 mrg high = n_elist - 1;
302 1.1 mrg
303 1.1 mrg do
304 1.1 mrg {
305 1.1 mrg mid = (low + high) / 2;
306 1.1 mrg if (unit == elist[mid].unit)
307 1.1 mrg {
308 1.1 mrg *ip = mid;
309 1.1 mrg return 1;
310 1.1 mrg }
311 1.1 mrg else if (unit > elist[mid].unit)
312 1.1 mrg low = mid + 1;
313 1.1 mrg else
314 1.1 mrg high = mid - 1;
315 1.1 mrg } while (low <= high);
316 1.1 mrg
317 1.1 mrg if (unit > elist[mid].unit)
318 1.1 mrg *ip = mid + 1;
319 1.1 mrg else
320 1.1 mrg *ip = mid;
321 1.1 mrg
322 1.1 mrg return 0;
323 1.1 mrg }
324 1.1 mrg
325 1.1 mrg /* This matches a keyword. If it is found, return the token supplied,
326 1.1 mrg otherwise return ILLEGAL. */
327 1.1 mrg
328 1.1 mrg static int
329 1.1 mrg match_word (const char *word, int tok)
330 1.1 mrg {
331 1.1 mrg int res;
332 1.1 mrg
333 1.1 mrg if (strncasecmp (p, word, strlen (word)) == 0)
334 1.1 mrg {
335 1.1 mrg p += strlen (word);
336 1.1 mrg res = tok;
337 1.1 mrg }
338 1.1 mrg else
339 1.1 mrg res = ILLEGAL;
340 1.1 mrg return res;
341 1.1 mrg }
342 1.1 mrg
343 1.1 mrg /* Match an integer and store its value in unit_num. This only works
344 1.1 mrg if p actually points to the start of an integer. The caller has
345 1.1 mrg to ensure this. */
346 1.1 mrg
347 1.1 mrg static int
348 1.1 mrg match_integer (void)
349 1.1 mrg {
350 1.1 mrg unit_num = 0;
351 1.1.1.3 mrg while (safe_isdigit (*p))
352 1.1 mrg unit_num = unit_num * 10 + (*p++ - '0');
353 1.1 mrg return INTEGER;
354 1.1 mrg }
355 1.1 mrg
356 1.1 mrg /* This reads the next token from the GFORTRAN_CONVERT_UNITS variable.
357 1.1 mrg Returned values are the different tokens. */
358 1.1 mrg
359 1.1 mrg static int
360 1.1 mrg next_token (void)
361 1.1 mrg {
362 1.1 mrg int result;
363 1.1 mrg
364 1.1 mrg lastpos = p;
365 1.1 mrg switch (*p)
366 1.1 mrg {
367 1.1 mrg case '\0':
368 1.1 mrg result = END;
369 1.1 mrg break;
370 1.1 mrg
371 1.1 mrg case ':':
372 1.1 mrg case ',':
373 1.1 mrg case '-':
374 1.1 mrg case ';':
375 1.1 mrg result = *p;
376 1.1 mrg p++;
377 1.1 mrg break;
378 1.1 mrg
379 1.1 mrg case 'b':
380 1.1 mrg case 'B':
381 1.1 mrg result = match_word ("big_endian", BIG);
382 1.1 mrg break;
383 1.1 mrg
384 1.1 mrg case 'l':
385 1.1 mrg case 'L':
386 1.1 mrg result = match_word ("little_endian", LITTLE);
387 1.1 mrg break;
388 1.1 mrg
389 1.1 mrg case 'n':
390 1.1 mrg case 'N':
391 1.1 mrg result = match_word ("native", NATIVE);
392 1.1 mrg break;
393 1.1 mrg
394 1.1 mrg case 's':
395 1.1 mrg case 'S':
396 1.1 mrg result = match_word ("swap", SWAP);
397 1.1 mrg break;
398 1.1 mrg
399 1.1.1.3 mrg #ifdef HAVE_GFC_REAL_17
400 1.1.1.3 mrg case 'r':
401 1.1.1.3 mrg case 'R':
402 1.1.1.3 mrg result = match_word ("r16_ieee", R16_IEEE);
403 1.1.1.3 mrg if (result == ILLEGAL)
404 1.1.1.3 mrg result = match_word ("r16_ibm", R16_IBM);
405 1.1.1.3 mrg break;
406 1.1.1.3 mrg
407 1.1.1.3 mrg #endif
408 1.1 mrg case '1': case '2': case '3': case '4': case '5':
409 1.1 mrg case '6': case '7': case '8': case '9':
410 1.1 mrg result = match_integer ();
411 1.1 mrg break;
412 1.1 mrg
413 1.1 mrg default:
414 1.1 mrg result = ILLEGAL;
415 1.1 mrg break;
416 1.1 mrg }
417 1.1 mrg return result;
418 1.1 mrg }
419 1.1 mrg
420 1.1 mrg /* Back up the last token by setting back the character pointer. */
421 1.1 mrg
422 1.1 mrg static void
423 1.1 mrg push_token (void)
424 1.1 mrg {
425 1.1 mrg p = lastpos;
426 1.1 mrg }
427 1.1 mrg
428 1.1 mrg /* This is called when a unit is identified. If do_count is nonzero,
429 1.1 mrg increment the number of units by one. If do_count is zero,
430 1.1.1.3 mrg put the unit into the table. For POWER, we have to make sure that
431 1.1.1.3 mrg we can also put in the conversion btween IBM and IEEE long double. */
432 1.1 mrg
433 1.1 mrg static void
434 1.1 mrg mark_single (int unit)
435 1.1 mrg {
436 1.1 mrg int i,j;
437 1.1 mrg
438 1.1 mrg if (do_count)
439 1.1 mrg {
440 1.1 mrg unit_count++;
441 1.1 mrg return;
442 1.1 mrg }
443 1.1 mrg if (search_unit (unit, &i))
444 1.1 mrg {
445 1.1.1.3 mrg #ifdef HAVE_GFC_REAL_17
446 1.1.1.3 mrg elist[i].conv |= endian;
447 1.1.1.3 mrg #else
448 1.1 mrg elist[i].conv = endian;
449 1.1.1.3 mrg #endif
450 1.1 mrg }
451 1.1 mrg else
452 1.1 mrg {
453 1.1 mrg for (j=n_elist-1; j>=i; j--)
454 1.1 mrg elist[j+1] = elist[j];
455 1.1 mrg
456 1.1 mrg n_elist += 1;
457 1.1 mrg elist[i].unit = unit;
458 1.1.1.3 mrg #ifdef HAVE_GFC_REAL_17
459 1.1.1.3 mrg elist[i].conv |= endian;
460 1.1.1.3 mrg #else
461 1.1 mrg elist[i].conv = endian;
462 1.1.1.3 mrg #endif
463 1.1 mrg }
464 1.1 mrg }
465 1.1 mrg
466 1.1 mrg /* This is called when a unit range is identified. If do_count is
467 1.1 mrg nonzero, increase the number of units. If do_count is zero,
468 1.1 mrg put the unit into the table. */
469 1.1 mrg
470 1.1 mrg static void
471 1.1 mrg mark_range (int unit1, int unit2)
472 1.1 mrg {
473 1.1 mrg int i;
474 1.1 mrg if (do_count)
475 1.1 mrg unit_count += abs (unit2 - unit1) + 1;
476 1.1 mrg else
477 1.1 mrg {
478 1.1 mrg if (unit2 < unit1)
479 1.1 mrg for (i=unit2; i<=unit1; i++)
480 1.1 mrg mark_single (i);
481 1.1 mrg else
482 1.1 mrg for (i=unit1; i<=unit2; i++)
483 1.1 mrg mark_single (i);
484 1.1 mrg }
485 1.1 mrg }
486 1.1 mrg
487 1.1 mrg /* Parse the GFORTRAN_CONVERT_UNITS variable. This is called
488 1.1 mrg twice, once to count the units and once to actually mark them in
489 1.1 mrg the table. When counting, we don't check for double occurrences
490 1.1 mrg of units. */
491 1.1 mrg
492 1.1 mrg static int
493 1.1 mrg do_parse (void)
494 1.1 mrg {
495 1.1 mrg int tok;
496 1.1 mrg int unit1;
497 1.1 mrg int continue_ulist;
498 1.1 mrg char *start;
499 1.1 mrg
500 1.1 mrg unit_count = 0;
501 1.1 mrg
502 1.1 mrg /* Parse the string. First, let's look for a default. */
503 1.1.1.3 mrg endian = 0;
504 1.1.1.3 mrg while (1)
505 1.1 mrg {
506 1.1.1.3 mrg start = p;
507 1.1.1.3 mrg tok = next_token ();
508 1.1.1.3 mrg switch (tok)
509 1.1.1.3 mrg {
510 1.1.1.3 mrg case NATIVE:
511 1.1.1.3 mrg endian = GFC_CONVERT_NATIVE;
512 1.1.1.3 mrg break;
513 1.1 mrg
514 1.1.1.3 mrg case SWAP:
515 1.1.1.3 mrg endian = GFC_CONVERT_SWAP;
516 1.1.1.3 mrg break;
517 1.1 mrg
518 1.1.1.3 mrg case BIG:
519 1.1.1.3 mrg endian = GFC_CONVERT_BIG;
520 1.1.1.3 mrg break;
521 1.1 mrg
522 1.1.1.3 mrg case LITTLE:
523 1.1.1.3 mrg endian = GFC_CONVERT_LITTLE;
524 1.1.1.3 mrg break;
525 1.1 mrg
526 1.1.1.3 mrg #ifdef HAVE_GFC_REAL_17
527 1.1.1.3 mrg case R16_IEEE:
528 1.1.1.3 mrg endian = GFC_CONVERT_R16_IEEE;
529 1.1.1.3 mrg break;
530 1.1 mrg
531 1.1.1.3 mrg case R16_IBM:
532 1.1.1.3 mrg endian = GFC_CONVERT_R16_IBM;
533 1.1.1.3 mrg break;
534 1.1.1.3 mrg #endif
535 1.1.1.3 mrg case INTEGER:
536 1.1.1.3 mrg /* A leading digit means that we are looking at an exception.
537 1.1.1.3 mrg Reset the position to the beginning, and continue processing
538 1.1.1.3 mrg at the exception list. */
539 1.1.1.3 mrg p = start;
540 1.1.1.3 mrg goto exceptions;
541 1.1.1.3 mrg break;
542 1.1 mrg
543 1.1.1.3 mrg case END:
544 1.1.1.3 mrg goto end;
545 1.1.1.3 mrg break;
546 1.1.1.3 mrg
547 1.1.1.3 mrg default:
548 1.1.1.3 mrg goto error;
549 1.1.1.3 mrg break;
550 1.1 mrg }
551 1.1 mrg
552 1.1.1.3 mrg tok = next_token ();
553 1.1.1.3 mrg switch (tok)
554 1.1.1.3 mrg {
555 1.1.1.3 mrg case ';':
556 1.1.1.3 mrg def = def == GFC_CONVERT_NONE ? endian : def | endian;
557 1.1.1.3 mrg break;
558 1.1 mrg
559 1.1.1.3 mrg case ':':
560 1.1.1.3 mrg /* This isn't a default after all. Reset the position to the
561 1.1.1.3 mrg beginning, and continue processing at the exception list. */
562 1.1.1.3 mrg p = start;
563 1.1.1.3 mrg goto exceptions;
564 1.1.1.3 mrg break;
565 1.1 mrg
566 1.1.1.3 mrg case END:
567 1.1.1.3 mrg def = def == GFC_CONVERT_NONE ? endian : def | endian;
568 1.1.1.3 mrg goto end;
569 1.1.1.3 mrg break;
570 1.1 mrg
571 1.1.1.3 mrg default:
572 1.1.1.3 mrg goto error;
573 1.1.1.3 mrg break;
574 1.1.1.3 mrg }
575 1.1 mrg }
576 1.1 mrg
577 1.1 mrg exceptions:
578 1.1 mrg
579 1.1 mrg /* Loop over all exceptions. */
580 1.1 mrg while(1)
581 1.1 mrg {
582 1.1 mrg tok = next_token ();
583 1.1 mrg switch (tok)
584 1.1 mrg {
585 1.1 mrg case NATIVE:
586 1.1 mrg if (next_token () != ':')
587 1.1 mrg goto error;
588 1.1 mrg endian = GFC_CONVERT_NATIVE;
589 1.1 mrg break;
590 1.1 mrg
591 1.1 mrg case SWAP:
592 1.1 mrg if (next_token () != ':')
593 1.1 mrg goto error;
594 1.1 mrg endian = GFC_CONVERT_SWAP;
595 1.1 mrg break;
596 1.1 mrg
597 1.1 mrg case LITTLE:
598 1.1 mrg if (next_token () != ':')
599 1.1 mrg goto error;
600 1.1 mrg endian = GFC_CONVERT_LITTLE;
601 1.1 mrg break;
602 1.1 mrg
603 1.1 mrg case BIG:
604 1.1 mrg if (next_token () != ':')
605 1.1 mrg goto error;
606 1.1 mrg endian = GFC_CONVERT_BIG;
607 1.1 mrg break;
608 1.1.1.3 mrg #ifdef HAVE_GFC_REAL_17
609 1.1.1.3 mrg case R16_IEEE:
610 1.1.1.3 mrg if (next_token () != ':')
611 1.1.1.3 mrg goto error;
612 1.1.1.3 mrg endian = GFC_CONVERT_R16_IEEE;
613 1.1.1.3 mrg break;
614 1.1.1.3 mrg
615 1.1.1.3 mrg case R16_IBM:
616 1.1.1.3 mrg if (next_token () != ':')
617 1.1.1.3 mrg goto error;
618 1.1.1.3 mrg endian = GFC_CONVERT_R16_IBM;
619 1.1.1.3 mrg break;
620 1.1.1.3 mrg #endif
621 1.1 mrg
622 1.1 mrg case INTEGER:
623 1.1 mrg push_token ();
624 1.1 mrg break;
625 1.1 mrg
626 1.1 mrg case END:
627 1.1 mrg goto end;
628 1.1 mrg break;
629 1.1 mrg
630 1.1 mrg default:
631 1.1 mrg goto error;
632 1.1 mrg break;
633 1.1 mrg }
634 1.1 mrg /* We arrive here when we want to parse a list of
635 1.1 mrg numbers. */
636 1.1 mrg continue_ulist = 1;
637 1.1 mrg do
638 1.1 mrg {
639 1.1 mrg tok = next_token ();
640 1.1 mrg if (tok != INTEGER)
641 1.1 mrg goto error;
642 1.1 mrg
643 1.1 mrg unit1 = unit_num;
644 1.1 mrg tok = next_token ();
645 1.1 mrg /* The number can be followed by a - and another number,
646 1.1 mrg which means that this is a unit range, a comma
647 1.1 mrg or a semicolon. */
648 1.1 mrg if (tok == '-')
649 1.1 mrg {
650 1.1 mrg if (next_token () != INTEGER)
651 1.1 mrg goto error;
652 1.1 mrg
653 1.1 mrg mark_range (unit1, unit_num);
654 1.1 mrg tok = next_token ();
655 1.1 mrg if (tok == END)
656 1.1 mrg goto end;
657 1.1 mrg else if (tok == ';')
658 1.1 mrg continue_ulist = 0;
659 1.1 mrg else if (tok != ',')
660 1.1 mrg goto error;
661 1.1 mrg }
662 1.1 mrg else
663 1.1 mrg {
664 1.1 mrg mark_single (unit1);
665 1.1 mrg switch (tok)
666 1.1 mrg {
667 1.1 mrg case ';':
668 1.1 mrg continue_ulist = 0;
669 1.1 mrg break;
670 1.1 mrg
671 1.1 mrg case ',':
672 1.1 mrg break;
673 1.1 mrg
674 1.1 mrg case END:
675 1.1 mrg goto end;
676 1.1 mrg break;
677 1.1 mrg
678 1.1 mrg default:
679 1.1 mrg goto error;
680 1.1 mrg }
681 1.1 mrg }
682 1.1 mrg } while (continue_ulist);
683 1.1 mrg }
684 1.1 mrg end:
685 1.1 mrg return 0;
686 1.1 mrg error:
687 1.1 mrg def = GFC_CONVERT_NONE;
688 1.1 mrg return -1;
689 1.1 mrg }
690 1.1 mrg
691 1.1 mrg void init_unformatted (variable * v)
692 1.1 mrg {
693 1.1 mrg char *val;
694 1.1 mrg val = getenv (v->name);
695 1.1 mrg def = GFC_CONVERT_NONE;
696 1.1 mrg n_elist = 0;
697 1.1 mrg
698 1.1 mrg if (val == NULL)
699 1.1 mrg return;
700 1.1 mrg do_count = 1;
701 1.1 mrg p = val;
702 1.1 mrg do_parse ();
703 1.1 mrg if (do_count <= 0)
704 1.1 mrg {
705 1.1 mrg n_elist = 0;
706 1.1 mrg elist = NULL;
707 1.1 mrg }
708 1.1 mrg else
709 1.1 mrg {
710 1.1 mrg elist = xmallocarray (unit_count, sizeof (exception_t));
711 1.1 mrg do_count = 0;
712 1.1 mrg p = val;
713 1.1 mrg do_parse ();
714 1.1 mrg }
715 1.1 mrg }
716 1.1 mrg
717 1.1 mrg /* Get the default conversion for for an unformatted unit. */
718 1.1 mrg
719 1.1 mrg unit_convert
720 1.1 mrg get_unformatted_convert (int unit)
721 1.1 mrg {
722 1.1 mrg int i;
723 1.1 mrg
724 1.1 mrg if (elist == NULL)
725 1.1 mrg return def;
726 1.1 mrg else if (search_unit (unit, &i))
727 1.1 mrg return elist[i].conv;
728 1.1 mrg else
729 1.1 mrg return def;
730 1.1 mrg }
731