82ae955ebec94afa52547d3f68e92e9322d352d3
[gcc.git] / gcc / f / target.c
1 /* target.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 1997, 1998, 2002 Free Software Foundation, Inc.
3 Contributed by James Craig Burley.
4
5 This file is part of GNU Fortran.
6
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Fortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Fortran; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21
22 Related Modules:
23 None
24
25 Description:
26 Implements conversion of lexer tokens to machine-dependent numerical
27 form and accordingly issues diagnostic messages when necessary.
28
29 Also, this module, especially its .h file, provides nearly all of the
30 information on the target machine's data type, kind type, and length
31 type capabilities. The idea is that by carefully going through
32 target.h and changing things properly, one can accomplish much
33 towards the porting of the FFE to a new machine. There are limits
34 to how much this can accomplish towards that end, however. For one
35 thing, the ffeexpr_collapse_convert function doesn't contain all the
36 conversion cases necessary, because the text file would be
37 enormous (even though most of the function would be cut during the
38 cpp phase because of the absence of the types), so when adding to
39 the number of supported kind types for a given type, one must look
40 to see if ffeexpr_collapse_convert needs modification in this area,
41 in addition to providing the appropriate macros and functions in
42 ffetarget. Note that if combinatorial explosion actually becomes a
43 problem for a given machine, one might have to modify the way conversion
44 expressions are built so that instead of just one conversion expr, a
45 series of conversion exprs are built to make a path from one type to
46 another that is not a "near neighbor". For now, however, with a handful
47 of each of the numeric types and only one character type, things appear
48 manageable.
49
50 A nonobvious change to ffetarget would be if the target machine was
51 not a 2's-complement machine. Any item with the word "magical" (case-
52 insensitive) in the FFE's source code (at least) indicates an assumption
53 that a 2's-complement machine is the target, and thus that there exists
54 a magnitude that can be represented as a negative number but not as
55 a positive number. It is possible that this situation can be dealt
56 with by changing only ffetarget, for example, on a 1's-complement
57 machine, perhaps #defineing ffetarget_constant_is_magical to simply
58 FALSE along with making the appropriate changes in ffetarget's number
59 parsing functions would be sufficient to effectively "comment out" code
60 in places like ffeexpr that do certain magical checks. But it is
61 possible there are other 2's-complement dependencies lurking in the
62 FFE (as possibly is true of any large program); if you find any, please
63 report them so we can replace them with dependencies on ffetarget
64 instead.
65
66 Modifications:
67 */
68
69 /* Include files. */
70
71 #include "proj.h"
72 #include "target.h"
73 #include "diagnostic.h"
74 #include "bad.h"
75 #include "info.h"
76 #include "lex.h"
77 #include "malloc.h"
78 #include "real.h"
79
80 /* Externals defined here. */
81
82 char ffetarget_string_[40]; /* Temp for ascii-to-double (atof). */
83 HOST_WIDE_INT ffetarget_long_val_;
84 HOST_WIDE_INT ffetarget_long_junk_;
85
86 /* Simple definitions and enumerations. */
87
88
89 /* Internal typedefs. */
90
91
92 /* Private include files. */
93
94
95 /* Internal structure definitions. */
96
97
98 /* Static objects accessed by functions in this module. */
99
100
101 /* Static functions (internal). */
102
103 static void ffetarget_print_char_ (FILE *f, unsigned char c);
104
105 /* Internal macros. */
106
107 #ifdef REAL_VALUE_ATOF
108 #define FFETARGET_ATOF_(p,m) REAL_VALUE_ATOF ((p),(m))
109 #else
110 #define FFETARGET_ATOF_(p,m) atof ((p))
111 #endif
112 \f
113
114 /* ffetarget_print_char_ -- Print a single character (in apostrophe context)
115
116 See prototype.
117
118 Outputs char so it prints or is escaped C style. */
119
120 static void
121 ffetarget_print_char_ (FILE *f, unsigned char c)
122 {
123 switch (c)
124 {
125 case '\\':
126 fputs ("\\\\", f);
127 break;
128
129 case '\'':
130 fputs ("\\\'", f);
131 break;
132
133 default:
134 if (ISPRINT (c))
135 fputc (c, f);
136 else
137 fprintf (f, "\\%03o", (unsigned int) c);
138 break;
139 }
140 }
141
142 /* ffetarget_aggregate_info -- Determine type for aggregate storage area
143
144 See prototype.
145
146 If aggregate type is distinct, just return it. Else return a type
147 representing a common denominator for the nondistinct type (for now,
148 just return default character, since that'll work on almost all target
149 machines).
150
151 The rules for abt/akt are (as implemented by ffestorag_update):
152
153 abt == FFEINFO_basictypeANY (akt == FFEINFO_kindtypeANY also, by
154 definition): CHARACTER and non-CHARACTER types mixed.
155
156 abt == FFEINFO_basictypeNONE (akt == FFEINFO_kindtypeNONE also, by
157 definition): More than one non-CHARACTER type mixed, but no CHARACTER
158 types mixed in.
159
160 abt some other value, akt == FFEINFO_kindtypeNONE: abt indicates the
161 only basic type mixed in, but more than one kind type is mixed in.
162
163 abt some other value, akt some other value: abt and akt indicate the
164 only type represented in the aggregation. */
165
166 void
167 ffetarget_aggregate_info (ffeinfoBasictype *ebt, ffeinfoKindtype *ekt,
168 ffetargetAlign *units, ffeinfoBasictype abt,
169 ffeinfoKindtype akt)
170 {
171 ffetype type;
172
173 if ((abt == FFEINFO_basictypeNONE) || (abt == FFEINFO_basictypeANY)
174 || (akt == FFEINFO_kindtypeNONE))
175 {
176 *ebt = FFEINFO_basictypeCHARACTER;
177 *ekt = FFEINFO_kindtypeCHARACTERDEFAULT;
178 }
179 else
180 {
181 *ebt = abt;
182 *ekt = akt;
183 }
184
185 type = ffeinfo_type (*ebt, *ekt);
186 assert (type != NULL);
187
188 *units = ffetype_size (type);
189 }
190
191 /* ffetarget_align -- Align one storage area to superordinate, update super
192
193 See prototype.
194
195 updated_alignment/updated_modulo contain the already existing
196 alignment requirements for the storage area at whose offset the
197 object with alignment requirements alignment/modulo is to be placed.
198 Find the smallest pad such that the requirements are maintained and
199 return it, but only after updating the updated_alignment/_modulo
200 requirements as necessary to indicate the placement of the new object. */
201
202 ffetargetAlign
203 ffetarget_align (ffetargetAlign *updated_alignment,
204 ffetargetAlign *updated_modulo, ffetargetOffset offset,
205 ffetargetAlign alignment, ffetargetAlign modulo)
206 {
207 ffetargetAlign pad;
208 ffetargetAlign min_pad; /* Minimum amount of padding needed. */
209 ffetargetAlign min_m = 0; /* Minimum-padding m. */
210 ffetargetAlign ua; /* Updated alignment. */
211 ffetargetAlign um; /* Updated modulo. */
212 ffetargetAlign ucnt; /* Multiplier applied to ua. */
213 ffetargetAlign m; /* Copy of modulo. */
214 ffetargetAlign cnt; /* Multiplier applied to alignment. */
215 ffetargetAlign i;
216 ffetargetAlign j;
217
218 assert (alignment > 0);
219 assert (*updated_alignment > 0);
220
221 assert (*updated_modulo < *updated_alignment);
222 assert (modulo < alignment);
223
224 /* The easy case: similar alignment requirements. */
225 if (*updated_alignment == alignment)
226 {
227 if (modulo > *updated_modulo)
228 pad = alignment - (modulo - *updated_modulo);
229 else
230 pad = *updated_modulo - modulo;
231 if (offset < 0)
232 /* De-negatize offset, since % wouldn't do the expected thing. */
233 offset = alignment - ((- offset) % alignment);
234 pad = (offset + pad) % alignment;
235 if (pad != 0)
236 pad = alignment - pad;
237 return pad;
238 }
239
240 /* Sigh, find LCM (Least Common Multiple) for the two alignment factors. */
241
242 for (ua = *updated_alignment, ucnt = 1;
243 ua % alignment != 0;
244 ua += *updated_alignment)
245 ++ucnt;
246
247 cnt = ua / alignment;
248
249 if (offset < 0)
250 /* De-negatize offset, since % wouldn't do the expected thing. */
251 offset = ua - ((- offset) % ua);
252
253 /* Set to largest value. */
254 min_pad = ~(ffetargetAlign) 0;
255
256 /* Find all combinations of modulo values the two alignment requirements
257 have; pick the combination that results in the smallest padding
258 requirement. Of course, if a zero-pad requirement is encountered, just
259 use that one. */
260
261 for (um = *updated_modulo, i = 0; i < ucnt; um += *updated_alignment, ++i)
262 {
263 for (m = modulo, j = 0; j < cnt; m += alignment, ++j)
264 {
265 /* This code is similar to the "easy case" code above. */
266 if (m > um)
267 pad = ua - (m - um);
268 else
269 pad = um - m;
270 pad = (offset + pad) % ua;
271 if (pad == 0)
272 {
273 /* A zero pad means we've got something useful. */
274 *updated_alignment = ua;
275 *updated_modulo = um;
276 return 0;
277 }
278 pad = ua - pad;
279 if (pad < min_pad)
280 { /* New minimum padding value. */
281 min_pad = pad;
282 min_m = um;
283 }
284 }
285 }
286
287 *updated_alignment = ua;
288 *updated_modulo = min_m;
289 return min_pad;
290 }
291
292 /* Always append a null byte to the end, in case this is wanted in
293 a special case such as passing a string as a FORMAT or %REF.
294 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
295 because it isn't a "feature" that is self-documenting. Use the
296 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
297 in the code. */
298
299 #if FFETARGET_okCHARACTER1
300 bool
301 ffetarget_character1 (ffetargetCharacter1 *val, ffelexToken character,
302 mallocPool pool)
303 {
304 val->length = ffelex_token_length (character);
305 if (val->length == 0)
306 val->text = NULL;
307 else
308 {
309 val->text = malloc_new_kp (pool, "ffetargetCharacter1", val->length + 1);
310 memcpy (val->text, ffelex_token_text (character), val->length);
311 val->text[val->length] = '\0';
312 }
313
314 return TRUE;
315 }
316
317 #endif
318 /* Produce orderable comparison between two constants
319
320 Compare lengths, if equal then use memcmp. */
321
322 #if FFETARGET_okCHARACTER1
323 int
324 ffetarget_cmp_character1 (ffetargetCharacter1 l, ffetargetCharacter1 r)
325 {
326 if (l.length < r.length)
327 return -1;
328 if (l.length > r.length)
329 return 1;
330 if (l.length == 0)
331 return 0;
332 return memcmp (l.text, r.text, l.length);
333 }
334
335 #endif
336 /* ffetarget_concatenate_character1 -- Perform CONCAT op on two constants
337
338 Always append a null byte to the end, in case this is wanted in
339 a special case such as passing a string as a FORMAT or %REF.
340 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
341 because it isn't a "feature" that is self-documenting. Use the
342 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
343 in the code. */
344
345 #if FFETARGET_okCHARACTER1
346 ffebad
347 ffetarget_concatenate_character1 (ffetargetCharacter1 *res,
348 ffetargetCharacter1 l, ffetargetCharacter1 r, mallocPool pool,
349 ffetargetCharacterSize *len)
350 {
351 res->length = *len = l.length + r.length;
352 if (*len == 0)
353 res->text = NULL;
354 else
355 {
356 res->text = malloc_new_kp (pool, "ffetargetCharacter1(CONCAT)", *len + 1);
357 if (l.length != 0)
358 memcpy (res->text, l.text, l.length);
359 if (r.length != 0)
360 memcpy (res->text + l.length, r.text, r.length);
361 res->text[*len] = '\0';
362 }
363
364 return FFEBAD;
365 }
366
367 #endif
368 /* ffetarget_eq_character1 -- Perform relational comparison on char constants
369
370 Compare lengths, if equal then use memcmp. */
371
372 #if FFETARGET_okCHARACTER1
373 ffebad
374 ffetarget_eq_character1 (bool *res, ffetargetCharacter1 l,
375 ffetargetCharacter1 r)
376 {
377 assert (l.length == r.length);
378 *res = (memcmp (l.text, r.text, l.length) == 0);
379 return FFEBAD;
380 }
381
382 #endif
383 /* ffetarget_le_character1 -- Perform relational comparison on char constants
384
385 Compare lengths, if equal then use memcmp. */
386
387 #if FFETARGET_okCHARACTER1
388 ffebad
389 ffetarget_le_character1 (bool *res, ffetargetCharacter1 l,
390 ffetargetCharacter1 r)
391 {
392 assert (l.length == r.length);
393 *res = (memcmp (l.text, r.text, l.length) <= 0);
394 return FFEBAD;
395 }
396
397 #endif
398 /* ffetarget_lt_character1 -- Perform relational comparison on char constants
399
400 Compare lengths, if equal then use memcmp. */
401
402 #if FFETARGET_okCHARACTER1
403 ffebad
404 ffetarget_lt_character1 (bool *res, ffetargetCharacter1 l,
405 ffetargetCharacter1 r)
406 {
407 assert (l.length == r.length);
408 *res = (memcmp (l.text, r.text, l.length) < 0);
409 return FFEBAD;
410 }
411
412 #endif
413 /* ffetarget_ge_character1 -- Perform relational comparison on char constants
414
415 Compare lengths, if equal then use memcmp. */
416
417 #if FFETARGET_okCHARACTER1
418 ffebad
419 ffetarget_ge_character1 (bool *res, ffetargetCharacter1 l,
420 ffetargetCharacter1 r)
421 {
422 assert (l.length == r.length);
423 *res = (memcmp (l.text, r.text, l.length) >= 0);
424 return FFEBAD;
425 }
426
427 #endif
428 /* ffetarget_gt_character1 -- Perform relational comparison on char constants
429
430 Compare lengths, if equal then use memcmp. */
431
432 #if FFETARGET_okCHARACTER1
433 ffebad
434 ffetarget_gt_character1 (bool *res, ffetargetCharacter1 l,
435 ffetargetCharacter1 r)
436 {
437 assert (l.length == r.length);
438 *res = (memcmp (l.text, r.text, l.length) > 0);
439 return FFEBAD;
440 }
441 #endif
442
443 #if FFETARGET_okCHARACTER1
444 bool
445 ffetarget_iszero_character1 (ffetargetCharacter1 constant)
446 {
447 ffetargetCharacterSize i;
448
449 for (i = 0; i < constant.length; ++i)
450 if (constant.text[i] != 0)
451 return FALSE;
452 return TRUE;
453 }
454 #endif
455
456 bool
457 ffetarget_iszero_hollerith (ffetargetHollerith constant)
458 {
459 ffetargetHollerithSize i;
460
461 for (i = 0; i < constant.length; ++i)
462 if (constant.text[i] != 0)
463 return FALSE;
464 return TRUE;
465 }
466
467 /* ffetarget_layout -- Do storage requirement analysis for entity
468
469 Return the alignment/modulo requirements along with the size, given the
470 data type info and the number of elements an array (1 for a scalar). */
471
472 void
473 ffetarget_layout (const char *error_text UNUSED, ffetargetAlign *alignment,
474 ffetargetAlign *modulo, ffetargetOffset *size,
475 ffeinfoBasictype bt, ffeinfoKindtype kt,
476 ffetargetCharacterSize charsize,
477 ffetargetIntegerDefault num_elements)
478 {
479 bool ok; /* For character type. */
480 ffetargetOffset numele; /* Converted from num_elements. */
481 ffetype type;
482
483 type = ffeinfo_type (bt, kt);
484 assert (type != NULL);
485
486 *alignment = ffetype_alignment (type);
487 *modulo = ffetype_modulo (type);
488 if (bt == FFEINFO_basictypeCHARACTER)
489 {
490 ok = ffetarget_offset_charsize (size, charsize, ffetype_size (type));
491 #ifdef ffetarget_offset_overflow
492 if (!ok)
493 ffetarget_offset_overflow (error_text);
494 #endif
495 }
496 else
497 *size = ffetype_size (type);
498
499 if ((num_elements < 0)
500 || !ffetarget_offset (&numele, num_elements)
501 || !ffetarget_offset_multiply (size, *size, numele))
502 {
503 ffetarget_offset_overflow (error_text);
504 *alignment = 1;
505 *modulo = 0;
506 *size = 0;
507 }
508 }
509
510 /* ffetarget_ne_character1 -- Perform relational comparison on char constants
511
512 Compare lengths, if equal then use memcmp. */
513
514 #if FFETARGET_okCHARACTER1
515 ffebad
516 ffetarget_ne_character1 (bool *res, ffetargetCharacter1 l,
517 ffetargetCharacter1 r)
518 {
519 assert (l.length == r.length);
520 *res = (memcmp (l.text, r.text, l.length) != 0);
521 return FFEBAD;
522 }
523
524 #endif
525 /* ffetarget_substr_character1 -- Perform SUBSTR op on three constants
526
527 Always append a null byte to the end, in case this is wanted in
528 a special case such as passing a string as a FORMAT or %REF.
529 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
530 because it isn't a "feature" that is self-documenting. Use the
531 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
532 in the code. */
533
534 #if FFETARGET_okCHARACTER1
535 ffebad
536 ffetarget_substr_character1 (ffetargetCharacter1 *res,
537 ffetargetCharacter1 l,
538 ffetargetCharacterSize first,
539 ffetargetCharacterSize last, mallocPool pool,
540 ffetargetCharacterSize *len)
541 {
542 if (last < first)
543 {
544 res->length = *len = 0;
545 res->text = NULL;
546 }
547 else
548 {
549 res->length = *len = last - first + 1;
550 res->text = malloc_new_kp (pool, "ffetargetCharacter1(SUBSTR)", *len + 1);
551 memcpy (res->text, l.text + first - 1, *len);
552 res->text[*len] = '\0';
553 }
554
555 return FFEBAD;
556 }
557
558 #endif
559 /* ffetarget_cmp_hollerith -- Produce orderable comparison between two
560 constants
561
562 Compare lengths, if equal then use memcmp. */
563
564 int
565 ffetarget_cmp_hollerith (ffetargetHollerith l, ffetargetHollerith r)
566 {
567 if (l.length < r.length)
568 return -1;
569 if (l.length > r.length)
570 return 1;
571 return memcmp (l.text, r.text, l.length);
572 }
573
574 ffebad
575 ffetarget_convert_any_character1_ (char *res, size_t size,
576 ffetargetCharacter1 l)
577 {
578 if (size <= (size_t) l.length)
579 {
580 char *p;
581 ffetargetCharacterSize i;
582
583 memcpy (res, l.text, size);
584 for (p = &l.text[0] + size, i = l.length - size;
585 i > 0;
586 ++p, --i)
587 if (*p != ' ')
588 return FFEBAD_TRUNCATING_CHARACTER;
589 }
590 else
591 {
592 memcpy (res, l.text, size);
593 memset (res + l.length, ' ', size - l.length);
594 }
595
596 return FFEBAD;
597 }
598
599 ffebad
600 ffetarget_convert_any_hollerith_ (char *res, size_t size,
601 ffetargetHollerith l)
602 {
603 if (size <= (size_t) l.length)
604 {
605 char *p;
606 ffetargetCharacterSize i;
607
608 memcpy (res, l.text, size);
609 for (p = &l.text[0] + size, i = l.length - size;
610 i > 0;
611 ++p, --i)
612 if (*p != ' ')
613 return FFEBAD_TRUNCATING_HOLLERITH;
614 }
615 else
616 {
617 memcpy (res, l.text, size);
618 memset (res + l.length, ' ', size - l.length);
619 }
620
621 return FFEBAD;
622 }
623
624 ffebad
625 ffetarget_convert_any_typeless_ (char *res, size_t size,
626 ffetargetTypeless l)
627 {
628 unsigned long long int l1;
629 unsigned long int l2;
630 unsigned int l3;
631 unsigned short int l4;
632 unsigned char l5;
633 size_t size_of;
634 char *p;
635
636 if (size >= sizeof (l1))
637 {
638 l1 = l;
639 p = (char *) &l1;
640 size_of = sizeof (l1);
641 }
642 else if (size >= sizeof (l2))
643 {
644 l2 = l;
645 p = (char *) &l2;
646 size_of = sizeof (l2);
647 l1 = l2;
648 }
649 else if (size >= sizeof (l3))
650 {
651 l3 = l;
652 p = (char *) &l3;
653 size_of = sizeof (l3);
654 l1 = l3;
655 }
656 else if (size >= sizeof (l4))
657 {
658 l4 = l;
659 p = (char *) &l4;
660 size_of = sizeof (l4);
661 l1 = l4;
662 }
663 else if (size >= sizeof (l5))
664 {
665 l5 = l;
666 p = (char *) &l5;
667 size_of = sizeof (l5);
668 l1 = l5;
669 }
670 else
671 {
672 assert ("stumped by conversion from typeless!" == NULL);
673 abort ();
674 }
675
676 if (size <= size_of)
677 {
678 int i = size_of - size;
679
680 memcpy (res, p + i, size);
681 for (; i > 0; ++p, --i)
682 if (*p != '\0')
683 return FFEBAD_TRUNCATING_TYPELESS;
684 }
685 else
686 {
687 int i = size - size_of;
688
689 memset (res, 0, i);
690 memcpy (res + i, p, size_of);
691 }
692
693 if (l1 != l)
694 return FFEBAD_TRUNCATING_TYPELESS;
695 return FFEBAD;
696 }
697
698 /* Always append a null byte to the end, in case this is wanted in
699 a special case such as passing a string as a FORMAT or %REF.
700 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
701 because it isn't a "feature" that is self-documenting. Use the
702 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
703 in the code. */
704
705 #if FFETARGET_okCHARACTER1
706 ffebad
707 ffetarget_convert_character1_character1 (ffetargetCharacter1 *res,
708 ffetargetCharacterSize size,
709 ffetargetCharacter1 l,
710 mallocPool pool)
711 {
712 res->length = size;
713 if (size == 0)
714 res->text = NULL;
715 else
716 {
717 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
718 if (size <= l.length)
719 memcpy (res->text, l.text, size);
720 else
721 {
722 memcpy (res->text, l.text, l.length);
723 memset (res->text + l.length, ' ', size - l.length);
724 }
725 res->text[size] = '\0';
726 }
727
728 return FFEBAD;
729 }
730
731 #endif
732
733 /* Always append a null byte to the end, in case this is wanted in
734 a special case such as passing a string as a FORMAT or %REF.
735 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
736 because it isn't a "feature" that is self-documenting. Use the
737 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
738 in the code. */
739
740 #if FFETARGET_okCHARACTER1
741 ffebad
742 ffetarget_convert_character1_hollerith (ffetargetCharacter1 *res,
743 ffetargetCharacterSize size,
744 ffetargetHollerith l, mallocPool pool)
745 {
746 res->length = size;
747 if (size == 0)
748 res->text = NULL;
749 else
750 {
751 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
752 res->text[size] = '\0';
753 if (size <= l.length)
754 {
755 char *p;
756 ffetargetCharacterSize i;
757
758 memcpy (res->text, l.text, size);
759 for (p = &l.text[0] + size, i = l.length - size;
760 i > 0;
761 ++p, --i)
762 if (*p != ' ')
763 return FFEBAD_TRUNCATING_HOLLERITH;
764 }
765 else
766 {
767 memcpy (res->text, l.text, l.length);
768 memset (res->text + l.length, ' ', size - l.length);
769 }
770 }
771
772 return FFEBAD;
773 }
774
775 #endif
776 /* ffetarget_convert_character1_integer4 -- Raw conversion.
777
778 Always append a null byte to the end, in case this is wanted in
779 a special case such as passing a string as a FORMAT or %REF.
780 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
781 because it isn't a "feature" that is self-documenting. Use the
782 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
783 in the code. */
784
785 #if FFETARGET_okCHARACTER1
786 ffebad
787 ffetarget_convert_character1_integer4 (ffetargetCharacter1 *res,
788 ffetargetCharacterSize size,
789 ffetargetInteger4 l, mallocPool pool)
790 {
791 long long int l1;
792 long int l2;
793 int l3;
794 short int l4;
795 char l5;
796 size_t size_of;
797 char *p;
798
799 if (((size_t) size) >= sizeof (l1))
800 {
801 l1 = l;
802 p = (char *) &l1;
803 size_of = sizeof (l1);
804 }
805 else if (((size_t) size) >= sizeof (l2))
806 {
807 l2 = l;
808 p = (char *) &l2;
809 size_of = sizeof (l2);
810 l1 = l2;
811 }
812 else if (((size_t) size) >= sizeof (l3))
813 {
814 l3 = l;
815 p = (char *) &l3;
816 size_of = sizeof (l3);
817 l1 = l3;
818 }
819 else if (((size_t) size) >= sizeof (l4))
820 {
821 l4 = l;
822 p = (char *) &l4;
823 size_of = sizeof (l4);
824 l1 = l4;
825 }
826 else if (((size_t) size) >= sizeof (l5))
827 {
828 l5 = l;
829 p = (char *) &l5;
830 size_of = sizeof (l5);
831 l1 = l5;
832 }
833 else
834 {
835 assert ("stumped by conversion from integer1!" == NULL);
836 abort ();
837 }
838
839 res->length = size;
840 if (size == 0)
841 res->text = NULL;
842 else
843 {
844 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
845 res->text[size] = '\0';
846 if (((size_t) size) <= size_of)
847 {
848 int i = size_of - size;
849
850 memcpy (res->text, p + i, size);
851 for (; i > 0; ++p, --i)
852 if (*p != 0)
853 return FFEBAD_TRUNCATING_NUMERIC;
854 }
855 else
856 {
857 int i = size - size_of;
858
859 memset (res->text, 0, i);
860 memcpy (res->text + i, p, size_of);
861 }
862 }
863
864 if (l1 != l)
865 return FFEBAD_TRUNCATING_NUMERIC;
866 return FFEBAD;
867 }
868
869 #endif
870 /* ffetarget_convert_character1_logical4 -- Raw conversion.
871
872 Always append a null byte to the end, in case this is wanted in
873 a special case such as passing a string as a FORMAT or %REF.
874 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
875 because it isn't a "feature" that is self-documenting. Use the
876 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
877 in the code. */
878
879 #if FFETARGET_okCHARACTER1
880 ffebad
881 ffetarget_convert_character1_logical4 (ffetargetCharacter1 *res,
882 ffetargetCharacterSize size,
883 ffetargetLogical4 l, mallocPool pool)
884 {
885 long long int l1;
886 long int l2;
887 int l3;
888 short int l4;
889 char l5;
890 size_t size_of;
891 char *p;
892
893 if (((size_t) size) >= sizeof (l1))
894 {
895 l1 = l;
896 p = (char *) &l1;
897 size_of = sizeof (l1);
898 }
899 else if (((size_t) size) >= sizeof (l2))
900 {
901 l2 = l;
902 p = (char *) &l2;
903 size_of = sizeof (l2);
904 l1 = l2;
905 }
906 else if (((size_t) size) >= sizeof (l3))
907 {
908 l3 = l;
909 p = (char *) &l3;
910 size_of = sizeof (l3);
911 l1 = l3;
912 }
913 else if (((size_t) size) >= sizeof (l4))
914 {
915 l4 = l;
916 p = (char *) &l4;
917 size_of = sizeof (l4);
918 l1 = l4;
919 }
920 else if (((size_t) size) >= sizeof (l5))
921 {
922 l5 = l;
923 p = (char *) &l5;
924 size_of = sizeof (l5);
925 l1 = l5;
926 }
927 else
928 {
929 assert ("stumped by conversion from logical1!" == NULL);
930 abort ();
931 }
932
933 res->length = size;
934 if (size == 0)
935 res->text = NULL;
936 else
937 {
938 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
939 res->text[size] = '\0';
940 if (((size_t) size) <= size_of)
941 {
942 int i = size_of - size;
943
944 memcpy (res->text, p + i, size);
945 for (; i > 0; ++p, --i)
946 if (*p != 0)
947 return FFEBAD_TRUNCATING_NUMERIC;
948 }
949 else
950 {
951 int i = size - size_of;
952
953 memset (res->text, 0, i);
954 memcpy (res->text + i, p, size_of);
955 }
956 }
957
958 if (l1 != l)
959 return FFEBAD_TRUNCATING_NUMERIC;
960 return FFEBAD;
961 }
962
963 #endif
964 /* ffetarget_convert_character1_typeless -- Raw conversion.
965
966 Always append a null byte to the end, in case this is wanted in
967 a special case such as passing a string as a FORMAT or %REF.
968 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
969 because it isn't a "feature" that is self-documenting. Use the
970 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
971 in the code. */
972
973 #if FFETARGET_okCHARACTER1
974 ffebad
975 ffetarget_convert_character1_typeless (ffetargetCharacter1 *res,
976 ffetargetCharacterSize size,
977 ffetargetTypeless l, mallocPool pool)
978 {
979 unsigned long long int l1;
980 unsigned long int l2;
981 unsigned int l3;
982 unsigned short int l4;
983 unsigned char l5;
984 size_t size_of;
985 char *p;
986
987 if (((size_t) size) >= sizeof (l1))
988 {
989 l1 = l;
990 p = (char *) &l1;
991 size_of = sizeof (l1);
992 }
993 else if (((size_t) size) >= sizeof (l2))
994 {
995 l2 = l;
996 p = (char *) &l2;
997 size_of = sizeof (l2);
998 l1 = l2;
999 }
1000 else if (((size_t) size) >= sizeof (l3))
1001 {
1002 l3 = l;
1003 p = (char *) &l3;
1004 size_of = sizeof (l3);
1005 l1 = l3;
1006 }
1007 else if (((size_t) size) >= sizeof (l4))
1008 {
1009 l4 = l;
1010 p = (char *) &l4;
1011 size_of = sizeof (l4);
1012 l1 = l4;
1013 }
1014 else if (((size_t) size) >= sizeof (l5))
1015 {
1016 l5 = l;
1017 p = (char *) &l5;
1018 size_of = sizeof (l5);
1019 l1 = l5;
1020 }
1021 else
1022 {
1023 assert ("stumped by conversion from typeless!" == NULL);
1024 abort ();
1025 }
1026
1027 res->length = size;
1028 if (size == 0)
1029 res->text = NULL;
1030 else
1031 {
1032 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
1033 res->text[size] = '\0';
1034 if (((size_t) size) <= size_of)
1035 {
1036 int i = size_of - size;
1037
1038 memcpy (res->text, p + i, size);
1039 for (; i > 0; ++p, --i)
1040 if (*p != 0)
1041 return FFEBAD_TRUNCATING_TYPELESS;
1042 }
1043 else
1044 {
1045 int i = size - size_of;
1046
1047 memset (res->text, 0, i);
1048 memcpy (res->text + i, p, size_of);
1049 }
1050 }
1051
1052 if (l1 != l)
1053 return FFEBAD_TRUNCATING_TYPELESS;
1054 return FFEBAD;
1055 }
1056
1057 #endif
1058 /* ffetarget_divide_complex1 -- Divide function
1059
1060 See prototype. */
1061
1062 #if FFETARGET_okCOMPLEX1
1063 ffebad
1064 ffetarget_divide_complex1 (ffetargetComplex1 *res, ffetargetComplex1 l,
1065 ffetargetComplex1 r)
1066 {
1067 ffebad bad;
1068 ffetargetReal1 tmp1, tmp2, tmp3, tmp4;
1069
1070 bad = ffetarget_multiply_real1 (&tmp1, r.real, r.real);
1071 if (bad != FFEBAD)
1072 return bad;
1073 bad = ffetarget_multiply_real1 (&tmp2, r.imaginary, r.imaginary);
1074 if (bad != FFEBAD)
1075 return bad;
1076 bad = ffetarget_add_real1 (&tmp3, tmp1, tmp2);
1077 if (bad != FFEBAD)
1078 return bad;
1079
1080 if (ffetarget_iszero_real1 (tmp3))
1081 {
1082 ffetarget_real1_zero (&(res)->real);
1083 ffetarget_real1_zero (&(res)->imaginary);
1084 return FFEBAD_DIV_BY_ZERO;
1085 }
1086
1087 bad = ffetarget_multiply_real1 (&tmp1, l.real, r.real);
1088 if (bad != FFEBAD)
1089 return bad;
1090 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, r.imaginary);
1091 if (bad != FFEBAD)
1092 return bad;
1093 bad = ffetarget_add_real1 (&tmp4, tmp1, tmp2);
1094 if (bad != FFEBAD)
1095 return bad;
1096 bad = ffetarget_divide_real1 (&res->real, tmp4, tmp3);
1097 if (bad != FFEBAD)
1098 return bad;
1099
1100 bad = ffetarget_multiply_real1 (&tmp1, r.real, l.imaginary);
1101 if (bad != FFEBAD)
1102 return bad;
1103 bad = ffetarget_multiply_real1 (&tmp2, l.real, r.imaginary);
1104 if (bad != FFEBAD)
1105 return bad;
1106 bad = ffetarget_subtract_real1 (&tmp4, tmp1, tmp2);
1107 if (bad != FFEBAD)
1108 return bad;
1109 bad = ffetarget_divide_real1 (&res->imaginary, tmp4, tmp3);
1110
1111 return FFEBAD;
1112 }
1113
1114 #endif
1115 /* ffetarget_divide_complex2 -- Divide function
1116
1117 See prototype. */
1118
1119 #if FFETARGET_okCOMPLEX2
1120 ffebad
1121 ffetarget_divide_complex2 (ffetargetComplex2 *res, ffetargetComplex2 l,
1122 ffetargetComplex2 r)
1123 {
1124 ffebad bad;
1125 ffetargetReal2 tmp1, tmp2, tmp3, tmp4;
1126
1127 bad = ffetarget_multiply_real2 (&tmp1, r.real, r.real);
1128 if (bad != FFEBAD)
1129 return bad;
1130 bad = ffetarget_multiply_real2 (&tmp2, r.imaginary, r.imaginary);
1131 if (bad != FFEBAD)
1132 return bad;
1133 bad = ffetarget_add_real2 (&tmp3, tmp1, tmp2);
1134 if (bad != FFEBAD)
1135 return bad;
1136
1137 if (ffetarget_iszero_real2 (tmp3))
1138 {
1139 ffetarget_real2_zero (&(res)->real);
1140 ffetarget_real2_zero (&(res)->imaginary);
1141 return FFEBAD_DIV_BY_ZERO;
1142 }
1143
1144 bad = ffetarget_multiply_real2 (&tmp1, l.real, r.real);
1145 if (bad != FFEBAD)
1146 return bad;
1147 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, r.imaginary);
1148 if (bad != FFEBAD)
1149 return bad;
1150 bad = ffetarget_add_real2 (&tmp4, tmp1, tmp2);
1151 if (bad != FFEBAD)
1152 return bad;
1153 bad = ffetarget_divide_real2 (&res->real, tmp4, tmp3);
1154 if (bad != FFEBAD)
1155 return bad;
1156
1157 bad = ffetarget_multiply_real2 (&tmp1, r.real, l.imaginary);
1158 if (bad != FFEBAD)
1159 return bad;
1160 bad = ffetarget_multiply_real2 (&tmp2, l.real, r.imaginary);
1161 if (bad != FFEBAD)
1162 return bad;
1163 bad = ffetarget_subtract_real2 (&tmp4, tmp1, tmp2);
1164 if (bad != FFEBAD)
1165 return bad;
1166 bad = ffetarget_divide_real2 (&res->imaginary, tmp4, tmp3);
1167
1168 return FFEBAD;
1169 }
1170
1171 #endif
1172 /* ffetarget_hollerith -- Convert token to a hollerith constant
1173
1174 Always append a null byte to the end, in case this is wanted in
1175 a special case such as passing a string as a FORMAT or %REF.
1176 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
1177 because it isn't a "feature" that is self-documenting. Use the
1178 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
1179 in the code. */
1180
1181 bool
1182 ffetarget_hollerith (ffetargetHollerith *val, ffelexToken integer,
1183 mallocPool pool)
1184 {
1185 val->length = ffelex_token_length (integer);
1186 val->text = malloc_new_kp (pool, "ffetargetHollerith", val->length + 1);
1187 memcpy (val->text, ffelex_token_text (integer), val->length);
1188 val->text[val->length] = '\0';
1189
1190 return TRUE;
1191 }
1192
1193 /* ffetarget_integer_bad_magical -- Complain about a magical number
1194
1195 Just calls ffebad with the arguments. */
1196
1197 void
1198 ffetarget_integer_bad_magical (ffelexToken t)
1199 {
1200 ffebad_start (FFEBAD_BAD_MAGICAL);
1201 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1202 ffebad_finish ();
1203 }
1204
1205 /* ffetarget_integer_bad_magical_binary -- Complain about a magical number
1206
1207 Just calls ffebad with the arguments. */
1208
1209 void
1210 ffetarget_integer_bad_magical_binary (ffelexToken integer,
1211 ffelexToken minus)
1212 {
1213 ffebad_start (FFEBAD_BAD_MAGICAL_BINARY);
1214 ffebad_here (0, ffelex_token_where_line (integer),
1215 ffelex_token_where_column (integer));
1216 ffebad_here (1, ffelex_token_where_line (minus),
1217 ffelex_token_where_column (minus));
1218 ffebad_finish ();
1219 }
1220
1221 /* ffetarget_integer_bad_magical_precedence -- Complain about a magical
1222 number
1223
1224 Just calls ffebad with the arguments. */
1225
1226 void
1227 ffetarget_integer_bad_magical_precedence (ffelexToken integer,
1228 ffelexToken uminus,
1229 ffelexToken higher_op)
1230 {
1231 ffebad_start (FFEBAD_BAD_MAGICAL_PRECEDENCE);
1232 ffebad_here (0, ffelex_token_where_line (integer),
1233 ffelex_token_where_column (integer));
1234 ffebad_here (1, ffelex_token_where_line (uminus),
1235 ffelex_token_where_column (uminus));
1236 ffebad_here (2, ffelex_token_where_line (higher_op),
1237 ffelex_token_where_column (higher_op));
1238 ffebad_finish ();
1239 }
1240
1241 /* ffetarget_integer_bad_magical_precedence_binary -- Complain...
1242
1243 Just calls ffebad with the arguments. */
1244
1245 void
1246 ffetarget_integer_bad_magical_precedence_binary (ffelexToken integer,
1247 ffelexToken minus,
1248 ffelexToken higher_op)
1249 {
1250 ffebad_start (FFEBAD_BAD_MAGICAL_PRECEDENCE_BINARY);
1251 ffebad_here (0, ffelex_token_where_line (integer),
1252 ffelex_token_where_column (integer));
1253 ffebad_here (1, ffelex_token_where_line (minus),
1254 ffelex_token_where_column (minus));
1255 ffebad_here (2, ffelex_token_where_line (higher_op),
1256 ffelex_token_where_column (higher_op));
1257 ffebad_finish ();
1258 }
1259
1260 /* ffetarget_integer1 -- Convert token to an integer
1261
1262 See prototype.
1263
1264 Token use count not affected overall. */
1265
1266 #if FFETARGET_okINTEGER1
1267 bool
1268 ffetarget_integer1 (ffetargetInteger1 *val, ffelexToken integer)
1269 {
1270 ffetargetInteger1 x;
1271 char *p;
1272 char c;
1273
1274 assert (ffelex_token_type (integer) == FFELEX_typeNUMBER);
1275
1276 p = ffelex_token_text (integer);
1277 x = 0;
1278
1279 /* Skip past leading zeros. */
1280
1281 while (((c = *p) != '\0') && (c == '0'))
1282 ++p;
1283
1284 /* Interpret rest of number. */
1285
1286 while (c != '\0')
1287 {
1288 if ((x == FFETARGET_integerALMOST_BIG_MAGICAL)
1289 && (c == '0' + FFETARGET_integerFINISH_BIG_MAGICAL)
1290 && (*(p + 1) == '\0'))
1291 {
1292 *val = (ffetargetInteger1) FFETARGET_integerBIG_MAGICAL;
1293 return TRUE;
1294 }
1295 else if (x == FFETARGET_integerALMOST_BIG_MAGICAL)
1296 {
1297 if ((c > '0' + FFETARGET_integerFINISH_BIG_MAGICAL)
1298 || (*(p + 1) != '\0'))
1299 {
1300 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1301 ffebad_here (0, ffelex_token_where_line (integer),
1302 ffelex_token_where_column (integer));
1303 ffebad_finish ();
1304 *val = 0;
1305 return FALSE;
1306 }
1307 }
1308 else if (x > FFETARGET_integerALMOST_BIG_MAGICAL)
1309 {
1310 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1311 ffebad_here (0, ffelex_token_where_line (integer),
1312 ffelex_token_where_column (integer));
1313 ffebad_finish ();
1314 *val = 0;
1315 return FALSE;
1316 }
1317 x = x * 10 + c - '0';
1318 c = *(++p);
1319 };
1320
1321 *val = x;
1322 return TRUE;
1323 }
1324
1325 #endif
1326 /* ffetarget_integerbinary -- Convert token to a binary integer
1327
1328 ffetarget_integerbinary x;
1329 if (ffetarget_integerdefault_8(&x,integer_token))
1330 // conversion ok.
1331
1332 Token use count not affected overall. */
1333
1334 bool
1335 ffetarget_integerbinary (ffetargetIntegerDefault *val, ffelexToken integer)
1336 {
1337 ffetargetIntegerDefault x;
1338 char *p;
1339 char c;
1340 bool bad_digit;
1341
1342 assert ((ffelex_token_type (integer) == FFELEX_typeNAME)
1343 || (ffelex_token_type (integer) == FFELEX_typeNUMBER));
1344
1345 p = ffelex_token_text (integer);
1346 x = 0;
1347
1348 /* Skip past leading zeros. */
1349
1350 while (((c = *p) != '\0') && (c == '0'))
1351 ++p;
1352
1353 /* Interpret rest of number. */
1354
1355 bad_digit = FALSE;
1356 while (c != '\0')
1357 {
1358 if ((c >= '0') && (c <= '1'))
1359 c -= '0';
1360 else
1361 {
1362 bad_digit = TRUE;
1363 c = 0;
1364 }
1365
1366 #if 0 /* Don't complain about signed overflow; just
1367 unsigned overflow. */
1368 if ((x == FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY)
1369 && (c == FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY)
1370 && (*(p + 1) == '\0'))
1371 {
1372 *val = FFETARGET_integerBIG_OVERFLOW_BINARY;
1373 return TRUE;
1374 }
1375 else
1376 #endif
1377 #if FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY == 0
1378 if ((x & FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY) != 0)
1379 #else
1380 if (x == FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY)
1381 {
1382 if ((c > FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY)
1383 || (*(p + 1) != '\0'))
1384 {
1385 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1386 ffebad_here (0, ffelex_token_where_line (integer),
1387 ffelex_token_where_column (integer));
1388 ffebad_finish ();
1389 *val = 0;
1390 return FALSE;
1391 }
1392 }
1393 else if (x > FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY)
1394 #endif
1395 {
1396 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1397 ffebad_here (0, ffelex_token_where_line (integer),
1398 ffelex_token_where_column (integer));
1399 ffebad_finish ();
1400 *val = 0;
1401 return FALSE;
1402 }
1403 x = (x << 1) + c;
1404 c = *(++p);
1405 };
1406
1407 if (bad_digit)
1408 {
1409 ffebad_start (FFEBAD_INVALID_BINARY_DIGIT);
1410 ffebad_here (0, ffelex_token_where_line (integer),
1411 ffelex_token_where_column (integer));
1412 ffebad_finish ();
1413 }
1414
1415 *val = x;
1416 return !bad_digit;
1417 }
1418
1419 /* ffetarget_integerhex -- Convert token to a hex integer
1420
1421 ffetarget_integerhex x;
1422 if (ffetarget_integerdefault_8(&x,integer_token))
1423 // conversion ok.
1424
1425 Token use count not affected overall. */
1426
1427 bool
1428 ffetarget_integerhex (ffetargetIntegerDefault *val, ffelexToken integer)
1429 {
1430 ffetargetIntegerDefault x;
1431 char *p;
1432 char c;
1433 bool bad_digit;
1434
1435 assert ((ffelex_token_type (integer) == FFELEX_typeNAME)
1436 || (ffelex_token_type (integer) == FFELEX_typeNUMBER));
1437
1438 p = ffelex_token_text (integer);
1439 x = 0;
1440
1441 /* Skip past leading zeros. */
1442
1443 while (((c = *p) != '\0') && (c == '0'))
1444 ++p;
1445
1446 /* Interpret rest of number. */
1447
1448 bad_digit = FALSE;
1449 while (c != '\0')
1450 {
1451 if (hex_p (c))
1452 c = hex_value (c);
1453 else
1454 {
1455 bad_digit = TRUE;
1456 c = 0;
1457 }
1458
1459 #if 0 /* Don't complain about signed overflow; just
1460 unsigned overflow. */
1461 if ((x == FFETARGET_integerALMOST_BIG_OVERFLOW_HEX)
1462 && (c == FFETARGET_integerFINISH_BIG_OVERFLOW_HEX)
1463 && (*(p + 1) == '\0'))
1464 {
1465 *val = FFETARGET_integerBIG_OVERFLOW_HEX;
1466 return TRUE;
1467 }
1468 else
1469 #endif
1470 #if FFETARGET_integerFINISH_BIG_OVERFLOW_HEX == 0
1471 if (x >= FFETARGET_integerALMOST_BIG_OVERFLOW_HEX)
1472 #else
1473 if (x == FFETARGET_integerALMOST_BIG_OVERFLOW_HEX)
1474 {
1475 if ((c > FFETARGET_integerFINISH_BIG_OVERFLOW_HEX)
1476 || (*(p + 1) != '\0'))
1477 {
1478 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1479 ffebad_here (0, ffelex_token_where_line (integer),
1480 ffelex_token_where_column (integer));
1481 ffebad_finish ();
1482 *val = 0;
1483 return FALSE;
1484 }
1485 }
1486 else if (x > FFETARGET_integerALMOST_BIG_OVERFLOW_HEX)
1487 #endif
1488 {
1489 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1490 ffebad_here (0, ffelex_token_where_line (integer),
1491 ffelex_token_where_column (integer));
1492 ffebad_finish ();
1493 *val = 0;
1494 return FALSE;
1495 }
1496 x = (x << 4) + c;
1497 c = *(++p);
1498 };
1499
1500 if (bad_digit)
1501 {
1502 ffebad_start (FFEBAD_INVALID_HEX_DIGIT);
1503 ffebad_here (0, ffelex_token_where_line (integer),
1504 ffelex_token_where_column (integer));
1505 ffebad_finish ();
1506 }
1507
1508 *val = x;
1509 return !bad_digit;
1510 }
1511
1512 /* ffetarget_integeroctal -- Convert token to an octal integer
1513
1514 ffetarget_integeroctal x;
1515 if (ffetarget_integerdefault_8(&x,integer_token))
1516 // conversion ok.
1517
1518 Token use count not affected overall. */
1519
1520 bool
1521 ffetarget_integeroctal (ffetargetIntegerDefault *val, ffelexToken integer)
1522 {
1523 ffetargetIntegerDefault x;
1524 char *p;
1525 char c;
1526 bool bad_digit;
1527
1528 assert ((ffelex_token_type (integer) == FFELEX_typeNAME)
1529 || (ffelex_token_type (integer) == FFELEX_typeNUMBER));
1530
1531 p = ffelex_token_text (integer);
1532 x = 0;
1533
1534 /* Skip past leading zeros. */
1535
1536 while (((c = *p) != '\0') && (c == '0'))
1537 ++p;
1538
1539 /* Interpret rest of number. */
1540
1541 bad_digit = FALSE;
1542 while (c != '\0')
1543 {
1544 if ((c >= '0') && (c <= '7'))
1545 c -= '0';
1546 else
1547 {
1548 bad_digit = TRUE;
1549 c = 0;
1550 }
1551
1552 #if 0 /* Don't complain about signed overflow; just
1553 unsigned overflow. */
1554 if ((x == FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL)
1555 && (c == FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL)
1556 && (*(p + 1) == '\0'))
1557 {
1558 *val = FFETARGET_integerBIG_OVERFLOW_OCTAL;
1559 return TRUE;
1560 }
1561 else
1562 #endif
1563 #if FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL == 0
1564 if (x >= FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL)
1565 #else
1566 if (x == FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL)
1567 {
1568 if ((c > FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL)
1569 || (*(p + 1) != '\0'))
1570 {
1571 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1572 ffebad_here (0, ffelex_token_where_line (integer),
1573 ffelex_token_where_column (integer));
1574 ffebad_finish ();
1575 *val = 0;
1576 return FALSE;
1577 }
1578 }
1579 else if (x > FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL)
1580 #endif
1581 {
1582 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1583 ffebad_here (0, ffelex_token_where_line (integer),
1584 ffelex_token_where_column (integer));
1585 ffebad_finish ();
1586 *val = 0;
1587 return FALSE;
1588 }
1589 x = (x << 3) + c;
1590 c = *(++p);
1591 };
1592
1593 if (bad_digit)
1594 {
1595 ffebad_start (FFEBAD_INVALID_OCTAL_DIGIT);
1596 ffebad_here (0, ffelex_token_where_line (integer),
1597 ffelex_token_where_column (integer));
1598 ffebad_finish ();
1599 }
1600
1601 *val = x;
1602 return !bad_digit;
1603 }
1604
1605 /* ffetarget_multiply_complex1 -- Multiply function
1606
1607 See prototype. */
1608
1609 #if FFETARGET_okCOMPLEX1
1610 ffebad
1611 ffetarget_multiply_complex1 (ffetargetComplex1 *res, ffetargetComplex1 l,
1612 ffetargetComplex1 r)
1613 {
1614 ffebad bad;
1615 ffetargetReal1 tmp1, tmp2;
1616
1617 bad = ffetarget_multiply_real1 (&tmp1, l.real, r.real);
1618 if (bad != FFEBAD)
1619 return bad;
1620 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, r.imaginary);
1621 if (bad != FFEBAD)
1622 return bad;
1623 bad = ffetarget_subtract_real1 (&res->real, tmp1, tmp2);
1624 if (bad != FFEBAD)
1625 return bad;
1626 bad = ffetarget_multiply_real1 (&tmp1, l.imaginary, r.real);
1627 if (bad != FFEBAD)
1628 return bad;
1629 bad = ffetarget_multiply_real1 (&tmp2, l.real, r.imaginary);
1630 if (bad != FFEBAD)
1631 return bad;
1632 bad = ffetarget_add_real1 (&res->imaginary, tmp1, tmp2);
1633
1634 return bad;
1635 }
1636
1637 #endif
1638 /* ffetarget_multiply_complex2 -- Multiply function
1639
1640 See prototype. */
1641
1642 #if FFETARGET_okCOMPLEX2
1643 ffebad
1644 ffetarget_multiply_complex2 (ffetargetComplex2 *res, ffetargetComplex2 l,
1645 ffetargetComplex2 r)
1646 {
1647 ffebad bad;
1648 ffetargetReal2 tmp1, tmp2;
1649
1650 bad = ffetarget_multiply_real2 (&tmp1, l.real, r.real);
1651 if (bad != FFEBAD)
1652 return bad;
1653 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, r.imaginary);
1654 if (bad != FFEBAD)
1655 return bad;
1656 bad = ffetarget_subtract_real2 (&res->real, tmp1, tmp2);
1657 if (bad != FFEBAD)
1658 return bad;
1659 bad = ffetarget_multiply_real2 (&tmp1, l.imaginary, r.real);
1660 if (bad != FFEBAD)
1661 return bad;
1662 bad = ffetarget_multiply_real2 (&tmp2, l.real, r.imaginary);
1663 if (bad != FFEBAD)
1664 return bad;
1665 bad = ffetarget_add_real2 (&res->imaginary, tmp1, tmp2);
1666
1667 return bad;
1668 }
1669
1670 #endif
1671 /* ffetarget_power_complexdefault_integerdefault -- Power function
1672
1673 See prototype. */
1674
1675 ffebad
1676 ffetarget_power_complexdefault_integerdefault (ffetargetComplexDefault *res,
1677 ffetargetComplexDefault l,
1678 ffetargetIntegerDefault r)
1679 {
1680 ffebad bad;
1681 ffetargetRealDefault tmp;
1682 ffetargetRealDefault tmp1;
1683 ffetargetRealDefault tmp2;
1684 ffetargetRealDefault two;
1685
1686 if (ffetarget_iszero_real1 (l.real)
1687 && ffetarget_iszero_real1 (l.imaginary))
1688 {
1689 ffetarget_real1_zero (&res->real);
1690 ffetarget_real1_zero (&res->imaginary);
1691 return FFEBAD;
1692 }
1693
1694 if (r == 0)
1695 {
1696 ffetarget_real1_one (&res->real);
1697 ffetarget_real1_zero (&res->imaginary);
1698 return FFEBAD;
1699 }
1700
1701 if (r < 0)
1702 {
1703 r = -r;
1704 bad = ffetarget_multiply_real1 (&tmp1, l.real, l.real);
1705 if (bad != FFEBAD)
1706 return bad;
1707 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, l.imaginary);
1708 if (bad != FFEBAD)
1709 return bad;
1710 bad = ffetarget_add_real1 (&tmp, tmp1, tmp2);
1711 if (bad != FFEBAD)
1712 return bad;
1713 bad = ffetarget_divide_real1 (&l.real, l.real, tmp);
1714 if (bad != FFEBAD)
1715 return bad;
1716 bad = ffetarget_divide_real1 (&l.imaginary, l.imaginary, tmp);
1717 if (bad != FFEBAD)
1718 return bad;
1719 bad = ffetarget_uminus_real1 (&l.imaginary, l.imaginary);
1720 if (bad != FFEBAD)
1721 return bad;
1722 }
1723
1724 ffetarget_real1_two (&two);
1725
1726 while ((r & 1) == 0)
1727 {
1728 bad = ffetarget_multiply_real1 (&tmp1, l.real, l.real);
1729 if (bad != FFEBAD)
1730 return bad;
1731 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, l.imaginary);
1732 if (bad != FFEBAD)
1733 return bad;
1734 bad = ffetarget_subtract_real1 (&tmp, tmp1, tmp2);
1735 if (bad != FFEBAD)
1736 return bad;
1737 bad = ffetarget_multiply_real1 (&l.imaginary, l.real, l.imaginary);
1738 if (bad != FFEBAD)
1739 return bad;
1740 bad = ffetarget_multiply_real1 (&l.imaginary, l.imaginary, two);
1741 if (bad != FFEBAD)
1742 return bad;
1743 l.real = tmp;
1744 r >>= 1;
1745 }
1746
1747 *res = l;
1748 r >>= 1;
1749
1750 while (r != 0)
1751 {
1752 bad = ffetarget_multiply_real1 (&tmp1, l.real, l.real);
1753 if (bad != FFEBAD)
1754 return bad;
1755 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, l.imaginary);
1756 if (bad != FFEBAD)
1757 return bad;
1758 bad = ffetarget_subtract_real1 (&tmp, tmp1, tmp2);
1759 if (bad != FFEBAD)
1760 return bad;
1761 bad = ffetarget_multiply_real1 (&l.imaginary, l.real, l.imaginary);
1762 if (bad != FFEBAD)
1763 return bad;
1764 bad = ffetarget_multiply_real1 (&l.imaginary, l.imaginary, two);
1765 if (bad != FFEBAD)
1766 return bad;
1767 l.real = tmp;
1768 if ((r & 1) == 1)
1769 {
1770 bad = ffetarget_multiply_real1 (&tmp1, res->real, l.real);
1771 if (bad != FFEBAD)
1772 return bad;
1773 bad = ffetarget_multiply_real1 (&tmp2, res->imaginary,
1774 l.imaginary);
1775 if (bad != FFEBAD)
1776 return bad;
1777 bad = ffetarget_subtract_real1 (&tmp, tmp1, tmp2);
1778 if (bad != FFEBAD)
1779 return bad;
1780 bad = ffetarget_multiply_real1 (&tmp1, res->imaginary, l.real);
1781 if (bad != FFEBAD)
1782 return bad;
1783 bad = ffetarget_multiply_real1 (&tmp2, res->real, l.imaginary);
1784 if (bad != FFEBAD)
1785 return bad;
1786 bad = ffetarget_add_real1 (&res->imaginary, tmp1, tmp2);
1787 if (bad != FFEBAD)
1788 return bad;
1789 res->real = tmp;
1790 }
1791 r >>= 1;
1792 }
1793
1794 return FFEBAD;
1795 }
1796
1797 /* ffetarget_power_complexdouble_integerdefault -- Power function
1798
1799 See prototype. */
1800
1801 #if FFETARGET_okCOMPLEXDOUBLE
1802 ffebad
1803 ffetarget_power_complexdouble_integerdefault (ffetargetComplexDouble *res,
1804 ffetargetComplexDouble l, ffetargetIntegerDefault r)
1805 {
1806 ffebad bad;
1807 ffetargetRealDouble tmp;
1808 ffetargetRealDouble tmp1;
1809 ffetargetRealDouble tmp2;
1810 ffetargetRealDouble two;
1811
1812 if (ffetarget_iszero_real2 (l.real)
1813 && ffetarget_iszero_real2 (l.imaginary))
1814 {
1815 ffetarget_real2_zero (&res->real);
1816 ffetarget_real2_zero (&res->imaginary);
1817 return FFEBAD;
1818 }
1819
1820 if (r == 0)
1821 {
1822 ffetarget_real2_one (&res->real);
1823 ffetarget_real2_zero (&res->imaginary);
1824 return FFEBAD;
1825 }
1826
1827 if (r < 0)
1828 {
1829 r = -r;
1830 bad = ffetarget_multiply_real2 (&tmp1, l.real, l.real);
1831 if (bad != FFEBAD)
1832 return bad;
1833 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, l.imaginary);
1834 if (bad != FFEBAD)
1835 return bad;
1836 bad = ffetarget_add_real2 (&tmp, tmp1, tmp2);
1837 if (bad != FFEBAD)
1838 return bad;
1839 bad = ffetarget_divide_real2 (&l.real, l.real, tmp);
1840 if (bad != FFEBAD)
1841 return bad;
1842 bad = ffetarget_divide_real2 (&l.imaginary, l.imaginary, tmp);
1843 if (bad != FFEBAD)
1844 return bad;
1845 bad = ffetarget_uminus_real2 (&l.imaginary, l.imaginary);
1846 if (bad != FFEBAD)
1847 return bad;
1848 }
1849
1850 ffetarget_real2_two (&two);
1851
1852 while ((r & 1) == 0)
1853 {
1854 bad = ffetarget_multiply_real2 (&tmp1, l.real, l.real);
1855 if (bad != FFEBAD)
1856 return bad;
1857 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, l.imaginary);
1858 if (bad != FFEBAD)
1859 return bad;
1860 bad = ffetarget_subtract_real2 (&tmp, tmp1, tmp2);
1861 if (bad != FFEBAD)
1862 return bad;
1863 bad = ffetarget_multiply_real2 (&l.imaginary, l.real, l.imaginary);
1864 if (bad != FFEBAD)
1865 return bad;
1866 bad = ffetarget_multiply_real2 (&l.imaginary, l.imaginary, two);
1867 if (bad != FFEBAD)
1868 return bad;
1869 l.real = tmp;
1870 r >>= 1;
1871 }
1872
1873 *res = l;
1874 r >>= 1;
1875
1876 while (r != 0)
1877 {
1878 bad = ffetarget_multiply_real2 (&tmp1, l.real, l.real);
1879 if (bad != FFEBAD)
1880 return bad;
1881 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, l.imaginary);
1882 if (bad != FFEBAD)
1883 return bad;
1884 bad = ffetarget_subtract_real2 (&tmp, tmp1, tmp2);
1885 if (bad != FFEBAD)
1886 return bad;
1887 bad = ffetarget_multiply_real2 (&l.imaginary, l.real, l.imaginary);
1888 if (bad != FFEBAD)
1889 return bad;
1890 bad = ffetarget_multiply_real2 (&l.imaginary, l.imaginary, two);
1891 if (bad != FFEBAD)
1892 return bad;
1893 l.real = tmp;
1894 if ((r & 1) == 1)
1895 {
1896 bad = ffetarget_multiply_real2 (&tmp1, res->real, l.real);
1897 if (bad != FFEBAD)
1898 return bad;
1899 bad = ffetarget_multiply_real2 (&tmp2, res->imaginary,
1900 l.imaginary);
1901 if (bad != FFEBAD)
1902 return bad;
1903 bad = ffetarget_subtract_real2 (&tmp, tmp1, tmp2);
1904 if (bad != FFEBAD)
1905 return bad;
1906 bad = ffetarget_multiply_real2 (&tmp1, res->imaginary, l.real);
1907 if (bad != FFEBAD)
1908 return bad;
1909 bad = ffetarget_multiply_real2 (&tmp2, res->real, l.imaginary);
1910 if (bad != FFEBAD)
1911 return bad;
1912 bad = ffetarget_add_real2 (&res->imaginary, tmp1, tmp2);
1913 if (bad != FFEBAD)
1914 return bad;
1915 res->real = tmp;
1916 }
1917 r >>= 1;
1918 }
1919
1920 return FFEBAD;
1921 }
1922
1923 #endif
1924 /* ffetarget_power_integerdefault_integerdefault -- Power function
1925
1926 See prototype. */
1927
1928 ffebad
1929 ffetarget_power_integerdefault_integerdefault (ffetargetIntegerDefault *res,
1930 ffetargetIntegerDefault l, ffetargetIntegerDefault r)
1931 {
1932 if (l == 0)
1933 {
1934 *res = 0;
1935 return FFEBAD;
1936 }
1937
1938 if (r == 0)
1939 {
1940 *res = 1;
1941 return FFEBAD;
1942 }
1943
1944 if (r < 0)
1945 {
1946 if (l == 1)
1947 *res = 1;
1948 else if (l == 0)
1949 *res = 1;
1950 else if (l == -1)
1951 *res = ((-r) & 1) == 0 ? 1 : -1;
1952 else
1953 *res = 0;
1954 return FFEBAD;
1955 }
1956
1957 while ((r & 1) == 0)
1958 {
1959 l *= l;
1960 r >>= 1;
1961 }
1962
1963 *res = l;
1964 r >>= 1;
1965
1966 while (r != 0)
1967 {
1968 l *= l;
1969 if ((r & 1) == 1)
1970 *res *= l;
1971 r >>= 1;
1972 }
1973
1974 return FFEBAD;
1975 }
1976
1977 /* ffetarget_power_realdefault_integerdefault -- Power function
1978
1979 See prototype. */
1980
1981 ffebad
1982 ffetarget_power_realdefault_integerdefault (ffetargetRealDefault *res,
1983 ffetargetRealDefault l, ffetargetIntegerDefault r)
1984 {
1985 ffebad bad;
1986
1987 if (ffetarget_iszero_real1 (l))
1988 {
1989 ffetarget_real1_zero (res);
1990 return FFEBAD;
1991 }
1992
1993 if (r == 0)
1994 {
1995 ffetarget_real1_one (res);
1996 return FFEBAD;
1997 }
1998
1999 if (r < 0)
2000 {
2001 ffetargetRealDefault one;
2002
2003 ffetarget_real1_one (&one);
2004 r = -r;
2005 bad = ffetarget_divide_real1 (&l, one, l);
2006 if (bad != FFEBAD)
2007 return bad;
2008 }
2009
2010 while ((r & 1) == 0)
2011 {
2012 bad = ffetarget_multiply_real1 (&l, l, l);
2013 if (bad != FFEBAD)
2014 return bad;
2015 r >>= 1;
2016 }
2017
2018 *res = l;
2019 r >>= 1;
2020
2021 while (r != 0)
2022 {
2023 bad = ffetarget_multiply_real1 (&l, l, l);
2024 if (bad != FFEBAD)
2025 return bad;
2026 if ((r & 1) == 1)
2027 {
2028 bad = ffetarget_multiply_real1 (res, *res, l);
2029 if (bad != FFEBAD)
2030 return bad;
2031 }
2032 r >>= 1;
2033 }
2034
2035 return FFEBAD;
2036 }
2037
2038 /* ffetarget_power_realdouble_integerdefault -- Power function
2039
2040 See prototype. */
2041
2042 ffebad
2043 ffetarget_power_realdouble_integerdefault (ffetargetRealDouble *res,
2044 ffetargetRealDouble l,
2045 ffetargetIntegerDefault r)
2046 {
2047 ffebad bad;
2048
2049 if (ffetarget_iszero_real2 (l))
2050 {
2051 ffetarget_real2_zero (res);
2052 return FFEBAD;
2053 }
2054
2055 if (r == 0)
2056 {
2057 ffetarget_real2_one (res);
2058 return FFEBAD;
2059 }
2060
2061 if (r < 0)
2062 {
2063 ffetargetRealDouble one;
2064
2065 ffetarget_real2_one (&one);
2066 r = -r;
2067 bad = ffetarget_divide_real2 (&l, one, l);
2068 if (bad != FFEBAD)
2069 return bad;
2070 }
2071
2072 while ((r & 1) == 0)
2073 {
2074 bad = ffetarget_multiply_real2 (&l, l, l);
2075 if (bad != FFEBAD)
2076 return bad;
2077 r >>= 1;
2078 }
2079
2080 *res = l;
2081 r >>= 1;
2082
2083 while (r != 0)
2084 {
2085 bad = ffetarget_multiply_real2 (&l, l, l);
2086 if (bad != FFEBAD)
2087 return bad;
2088 if ((r & 1) == 1)
2089 {
2090 bad = ffetarget_multiply_real2 (res, *res, l);
2091 if (bad != FFEBAD)
2092 return bad;
2093 }
2094 r >>= 1;
2095 }
2096
2097 return FFEBAD;
2098 }
2099
2100 /* ffetarget_print_binary -- Output typeless binary integer
2101
2102 ffetargetTypeless val;
2103 ffetarget_typeless_binary(dmpout,val); */
2104
2105 void
2106 ffetarget_print_binary (FILE *f, ffetargetTypeless value)
2107 {
2108 char *p;
2109 char digits[sizeof (value) * CHAR_BIT + 1];
2110
2111 if (f == NULL)
2112 f = dmpout;
2113
2114 p = &digits[ARRAY_SIZE (digits) - 1];
2115 *p = '\0';
2116 do
2117 {
2118 *--p = (value & 1) + '0';
2119 value >>= 1;
2120 } while (value == 0);
2121
2122 fputs (p, f);
2123 }
2124
2125 /* ffetarget_print_character1 -- Output character string
2126
2127 ffetargetCharacter1 val;
2128 ffetarget_print_character1(dmpout,val); */
2129
2130 void
2131 ffetarget_print_character1 (FILE *f, ffetargetCharacter1 value)
2132 {
2133 unsigned char *p;
2134 ffetargetCharacterSize i;
2135
2136 fputc ('\'', dmpout);
2137 for (i = 0, p = value.text; i < value.length; ++i, ++p)
2138 ffetarget_print_char_ (f, *p);
2139 fputc ('\'', dmpout);
2140 }
2141
2142 /* ffetarget_print_hollerith -- Output hollerith string
2143
2144 ffetargetHollerith val;
2145 ffetarget_print_hollerith(dmpout,val); */
2146
2147 void
2148 ffetarget_print_hollerith (FILE *f, ffetargetHollerith value)
2149 {
2150 unsigned char *p;
2151 ffetargetHollerithSize i;
2152
2153 fputc ('\'', dmpout);
2154 for (i = 0, p = value.text; i < value.length; ++i, ++p)
2155 ffetarget_print_char_ (f, *p);
2156 fputc ('\'', dmpout);
2157 }
2158
2159 /* ffetarget_print_octal -- Output typeless octal integer
2160
2161 ffetargetTypeless val;
2162 ffetarget_print_octal(dmpout,val); */
2163
2164 void
2165 ffetarget_print_octal (FILE *f, ffetargetTypeless value)
2166 {
2167 char *p;
2168 char digits[sizeof (value) * CHAR_BIT / 3 + 1];
2169
2170 if (f == NULL)
2171 f = dmpout;
2172
2173 p = &digits[ARRAY_SIZE (digits) - 3];
2174 *p = '\0';
2175 do
2176 {
2177 *--p = (value & 3) + '0';
2178 value >>= 3;
2179 } while (value == 0);
2180
2181 fputs (p, f);
2182 }
2183
2184 /* ffetarget_print_hex -- Output typeless hex integer
2185
2186 ffetargetTypeless val;
2187 ffetarget_print_hex(dmpout,val); */
2188
2189 void
2190 ffetarget_print_hex (FILE *f, ffetargetTypeless value)
2191 {
2192 char *p;
2193 char digits[sizeof (value) * CHAR_BIT / 4 + 1];
2194 static const char hexdigits[16] = "0123456789ABCDEF";
2195
2196 if (f == NULL)
2197 f = dmpout;
2198
2199 p = &digits[ARRAY_SIZE (digits) - 3];
2200 *p = '\0';
2201 do
2202 {
2203 *--p = hexdigits[value & 4];
2204 value >>= 4;
2205 } while (value == 0);
2206
2207 fputs (p, f);
2208 }
2209
2210 /* ffetarget_real1 -- Convert token to a single-precision real number
2211
2212 See prototype.
2213
2214 Pass NULL for any token not provided by the user, but a valid Fortran
2215 real number must be provided somehow. For example, it is ok for
2216 exponent_sign_token and exponent_digits_token to be NULL as long as
2217 exponent_token not only starts with "E" or "e" but also contains at least
2218 one digit following it. Token use counts not affected overall. */
2219
2220 #if FFETARGET_okREAL1
2221 bool
2222 ffetarget_real1 (ffetargetReal1 *value, ffelexToken integer,
2223 ffelexToken decimal, ffelexToken fraction,
2224 ffelexToken exponent, ffelexToken exponent_sign,
2225 ffelexToken exponent_digits)
2226 {
2227 size_t sz = 1; /* Allow room for '\0' byte at end. */
2228 char *ptr = &ffetarget_string_[0];
2229 char *p = ptr;
2230 char *q;
2231
2232 #define dotok(x) if (x != NULL) ++sz;
2233 #define dotoktxt(x) if (x != NULL) sz += ffelex_token_length(x)
2234
2235 dotoktxt (integer);
2236 dotok (decimal);
2237 dotoktxt (fraction);
2238 dotoktxt (exponent);
2239 dotok (exponent_sign);
2240 dotoktxt (exponent_digits);
2241
2242 #undef dotok
2243 #undef dotoktxt
2244
2245 if (sz > ARRAY_SIZE (ffetarget_string_))
2246 p = ptr = (char *) malloc_new_ks (malloc_pool_image (), "ffetarget_real1",
2247 sz);
2248
2249 #define dotoktxt(x) if (x != NULL) \
2250 { \
2251 for (q = ffelex_token_text(x); *q != '\0'; ++q) \
2252 *p++ = *q; \
2253 }
2254
2255 dotoktxt (integer);
2256
2257 if (decimal != NULL)
2258 *p++ = '.';
2259
2260 dotoktxt (fraction);
2261 dotoktxt (exponent);
2262
2263 if (exponent_sign != NULL)
2264 {
2265 if (ffelex_token_type (exponent_sign) == FFELEX_typePLUS)
2266 *p++ = '+';
2267 else
2268 {
2269 assert (ffelex_token_type (exponent_sign) == FFELEX_typeMINUS);
2270 *p++ = '-';
2271 }
2272 }
2273
2274 dotoktxt (exponent_digits);
2275
2276 #undef dotoktxt
2277
2278 *p = '\0';
2279
2280 {
2281 REAL_VALUE_TYPE rv;
2282 rv = FFETARGET_ATOF_ (ptr, SFmode);
2283 ffetarget_make_real1 (value, rv);
2284 }
2285
2286 if (sz > ARRAY_SIZE (ffetarget_string_))
2287 malloc_kill_ks (malloc_pool_image (), ptr, sz);
2288
2289 return TRUE;
2290 }
2291
2292 #endif
2293 /* ffetarget_real2 -- Convert token to a single-precision real number
2294
2295 See prototype.
2296
2297 Pass NULL for any token not provided by the user, but a valid Fortran
2298 real number must be provided somehow. For example, it is ok for
2299 exponent_sign_token and exponent_digits_token to be NULL as long as
2300 exponent_token not only starts with "E" or "e" but also contains at least
2301 one digit following it. Token use counts not affected overall. */
2302
2303 #if FFETARGET_okREAL2
2304 bool
2305 ffetarget_real2 (ffetargetReal2 *value, ffelexToken integer,
2306 ffelexToken decimal, ffelexToken fraction,
2307 ffelexToken exponent, ffelexToken exponent_sign,
2308 ffelexToken exponent_digits)
2309 {
2310 size_t sz = 1; /* Allow room for '\0' byte at end. */
2311 char *ptr = &ffetarget_string_[0];
2312 char *p = ptr;
2313 char *q;
2314
2315 #define dotok(x) if (x != NULL) ++sz;
2316 #define dotoktxt(x) if (x != NULL) sz += ffelex_token_length(x)
2317
2318 dotoktxt (integer);
2319 dotok (decimal);
2320 dotoktxt (fraction);
2321 dotoktxt (exponent);
2322 dotok (exponent_sign);
2323 dotoktxt (exponent_digits);
2324
2325 #undef dotok
2326 #undef dotoktxt
2327
2328 if (sz > ARRAY_SIZE (ffetarget_string_))
2329 p = ptr = (char *) malloc_new_ks (malloc_pool_image (), "ffetarget_real1", sz);
2330
2331 #define dotoktxt(x) if (x != NULL) \
2332 { \
2333 for (q = ffelex_token_text(x); *q != '\0'; ++q) \
2334 *p++ = *q; \
2335 }
2336 #define dotoktxtexp(x) if (x != NULL) \
2337 { \
2338 *p++ = 'E'; \
2339 for (q = ffelex_token_text(x) + 1; *q != '\0'; ++q) \
2340 *p++ = *q; \
2341 }
2342
2343 dotoktxt (integer);
2344
2345 if (decimal != NULL)
2346 *p++ = '.';
2347
2348 dotoktxt (fraction);
2349 dotoktxtexp (exponent);
2350
2351 if (exponent_sign != NULL)
2352 {
2353 if (ffelex_token_type (exponent_sign) == FFELEX_typePLUS)
2354 *p++ = '+';
2355 else
2356 {
2357 assert (ffelex_token_type (exponent_sign) == FFELEX_typeMINUS);
2358 *p++ = '-';
2359 }
2360 }
2361
2362 dotoktxt (exponent_digits);
2363
2364 #undef dotoktxt
2365
2366 *p = '\0';
2367
2368 {
2369 REAL_VALUE_TYPE rv;
2370 rv = FFETARGET_ATOF_ (ptr, DFmode);
2371 ffetarget_make_real2 (value, rv);
2372 }
2373
2374 if (sz > ARRAY_SIZE (ffetarget_string_))
2375 malloc_kill_ks (malloc_pool_image (), ptr, sz);
2376
2377 return TRUE;
2378 }
2379
2380 #endif
2381 bool
2382 ffetarget_typeless_binary (ffetargetTypeless *xvalue, ffelexToken token)
2383 {
2384 char *p;
2385 char c;
2386 ffetargetTypeless value = 0;
2387 ffetargetTypeless new_value = 0;
2388 bool bad_digit = FALSE;
2389 bool overflow = FALSE;
2390
2391 p = ffelex_token_text (token);
2392
2393 for (c = *p; c != '\0'; c = *++p)
2394 {
2395 new_value <<= 1;
2396 if ((new_value >> 1) != value)
2397 overflow = TRUE;
2398 if (ISDIGIT (c))
2399 new_value += c - '0';
2400 else
2401 bad_digit = TRUE;
2402 value = new_value;
2403 }
2404
2405 if (bad_digit)
2406 {
2407 ffebad_start (FFEBAD_INVALID_TYPELESS_BINARY_DIGIT);
2408 ffebad_here (0, ffelex_token_where_line (token),
2409 ffelex_token_where_column (token));
2410 ffebad_finish ();
2411 }
2412 else if (overflow)
2413 {
2414 ffebad_start (FFEBAD_TYPELESS_OVERFLOW);
2415 ffebad_here (0, ffelex_token_where_line (token),
2416 ffelex_token_where_column (token));
2417 ffebad_finish ();
2418 }
2419
2420 *xvalue = value;
2421
2422 return !bad_digit && !overflow;
2423 }
2424
2425 bool
2426 ffetarget_typeless_octal (ffetargetTypeless *xvalue, ffelexToken token)
2427 {
2428 char *p;
2429 char c;
2430 ffetargetTypeless value = 0;
2431 ffetargetTypeless new_value = 0;
2432 bool bad_digit = FALSE;
2433 bool overflow = FALSE;
2434
2435 p = ffelex_token_text (token);
2436
2437 for (c = *p; c != '\0'; c = *++p)
2438 {
2439 new_value <<= 3;
2440 if ((new_value >> 3) != value)
2441 overflow = TRUE;
2442 if (ISDIGIT (c))
2443 new_value += c - '0';
2444 else
2445 bad_digit = TRUE;
2446 value = new_value;
2447 }
2448
2449 if (bad_digit)
2450 {
2451 ffebad_start (FFEBAD_INVALID_TYPELESS_OCTAL_DIGIT);
2452 ffebad_here (0, ffelex_token_where_line (token),
2453 ffelex_token_where_column (token));
2454 ffebad_finish ();
2455 }
2456 else if (overflow)
2457 {
2458 ffebad_start (FFEBAD_TYPELESS_OVERFLOW);
2459 ffebad_here (0, ffelex_token_where_line (token),
2460 ffelex_token_where_column (token));
2461 ffebad_finish ();
2462 }
2463
2464 *xvalue = value;
2465
2466 return !bad_digit && !overflow;
2467 }
2468
2469 bool
2470 ffetarget_typeless_hex (ffetargetTypeless *xvalue, ffelexToken token)
2471 {
2472 char *p;
2473 char c;
2474 ffetargetTypeless value = 0;
2475 ffetargetTypeless new_value = 0;
2476 bool bad_digit = FALSE;
2477 bool overflow = FALSE;
2478
2479 p = ffelex_token_text (token);
2480
2481 for (c = *p; c != '\0'; c = *++p)
2482 {
2483 new_value <<= 4;
2484 if ((new_value >> 4) != value)
2485 overflow = TRUE;
2486 if (hex_p (c))
2487 new_value += hex_value (c);
2488 else
2489 bad_digit = TRUE;
2490 value = new_value;
2491 }
2492
2493 if (bad_digit)
2494 {
2495 ffebad_start (FFEBAD_INVALID_TYPELESS_HEX_DIGIT);
2496 ffebad_here (0, ffelex_token_where_line (token),
2497 ffelex_token_where_column (token));
2498 ffebad_finish ();
2499 }
2500 else if (overflow)
2501 {
2502 ffebad_start (FFEBAD_TYPELESS_OVERFLOW);
2503 ffebad_here (0, ffelex_token_where_line (token),
2504 ffelex_token_where_column (token));
2505 ffebad_finish ();
2506 }
2507
2508 *xvalue = value;
2509
2510 return !bad_digit && !overflow;
2511 }
2512
2513 void
2514 ffetarget_verify_character1 (mallocPool pool, ffetargetCharacter1 val)
2515 {
2516 if (val.length != 0)
2517 malloc_verify_kp (pool, val.text, val.length);
2518 }
2519
2520 /* This is like memcpy. It is needed because some systems' header files
2521 don't declare memcpy as a function but instead
2522 "#define memcpy(to,from,len) something". */
2523
2524 void *
2525 ffetarget_memcpy_ (void *dst, void *src, size_t len)
2526 {
2527 #ifdef CROSS_COMPILE
2528 /* HOST_WORDS_BIG_ENDIAN corresponds to both WORDS_BIG_ENDIAN and
2529 BYTES_BIG_ENDIAN (i.e. there are no HOST_ macros to represent a
2530 difference in the two latter). */
2531 int host_words_big_endian =
2532 #ifndef HOST_WORDS_BIG_ENDIAN
2533 0
2534 #else
2535 HOST_WORDS_BIG_ENDIAN
2536 #endif
2537 ;
2538
2539 /* This is just hands thrown up in the air over bits coming through this
2540 function representing a number being memcpy:d as-is from host to
2541 target. We can't generally adjust endianness here since we don't
2542 know whether it's an integer or floating point number; they're passed
2543 differently. Better to not emit code at all than to emit wrong code.
2544 We will get some false hits because some data coming through here
2545 seems to be just character vectors, but often enough it's numbers,
2546 for instance in g77.f-torture/execute/980628-[4-6].f and alpha2.f.
2547 Still, we compile *some* code. FIXME: Rewrite handling of numbers. */
2548 if (!WORDS_BIG_ENDIAN != !host_words_big_endian
2549 || !BYTES_BIG_ENDIAN != !host_words_big_endian)
2550 sorry ("data initializer on host with different endianness");
2551
2552 #endif /* CROSS_COMPILE */
2553
2554 return (void *) memcpy (dst, src, len);
2555 }
2556
2557 /* ffetarget_num_digits_ -- Determine number of non-space characters in token
2558
2559 ffetarget_num_digits_(token);
2560
2561 All non-spaces are assumed to be binary, octal, or hex digits. */
2562
2563 int
2564 ffetarget_num_digits_ (ffelexToken token)
2565 {
2566 int i;
2567 char *c;
2568
2569 switch (ffelex_token_type (token))
2570 {
2571 case FFELEX_typeNAME:
2572 case FFELEX_typeNUMBER:
2573 return ffelex_token_length (token);
2574
2575 case FFELEX_typeCHARACTER:
2576 i = 0;
2577 for (c = ffelex_token_text (token); *c != '\0'; ++c)
2578 {
2579 if (*c != ' ')
2580 ++i;
2581 }
2582 return i;
2583
2584 default:
2585 assert ("weird token" == NULL);
2586 return 1;
2587 }
2588 }