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.
5 This file is part of GNU Fortran.
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)
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.
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
26 Implements conversion of lexer tokens to machine-dependent numerical
27 form and accordingly issues diagnostic messages when necessary.
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
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
73 #include "diagnostic.h"
80 /* Externals defined here. */
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_
;
86 /* Simple definitions and enumerations. */
89 /* Internal typedefs. */
92 /* Private include files. */
95 /* Internal structure definitions. */
98 /* Static objects accessed by functions in this module. */
101 /* Static functions (internal). */
103 static void ffetarget_print_char_ (FILE *f
, unsigned char c
);
105 /* Internal macros. */
107 #ifdef REAL_VALUE_ATOF
108 #define FFETARGET_ATOF_(p,m) REAL_VALUE_ATOF ((p),(m))
110 #define FFETARGET_ATOF_(p,m) atof ((p))
114 /* ffetarget_print_char_ -- Print a single character (in apostrophe context)
118 Outputs char so it prints or is escaped C style. */
121 ffetarget_print_char_ (FILE *f
, unsigned char c
)
137 fprintf (f
, "\\%03o", (unsigned int) c
);
142 /* ffetarget_aggregate_info -- Determine type for aggregate storage area
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
151 The rules for abt/akt are (as implemented by ffestorag_update):
153 abt == FFEINFO_basictypeANY (akt == FFEINFO_kindtypeANY also, by
154 definition): CHARACTER and non-CHARACTER types mixed.
156 abt == FFEINFO_basictypeNONE (akt == FFEINFO_kindtypeNONE also, by
157 definition): More than one non-CHARACTER type mixed, but no CHARACTER
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.
163 abt some other value, akt some other value: abt and akt indicate the
164 only type represented in the aggregation. */
167 ffetarget_aggregate_info (ffeinfoBasictype
*ebt
, ffeinfoKindtype
*ekt
,
168 ffetargetAlign
*units
, ffeinfoBasictype abt
,
173 if ((abt
== FFEINFO_basictypeNONE
) || (abt
== FFEINFO_basictypeANY
)
174 || (akt
== FFEINFO_kindtypeNONE
))
176 *ebt
= FFEINFO_basictypeCHARACTER
;
177 *ekt
= FFEINFO_kindtypeCHARACTERDEFAULT
;
185 type
= ffeinfo_type (*ebt
, *ekt
);
186 assert (type
!= NULL
);
188 *units
= ffetype_size (type
);
191 /* ffetarget_align -- Align one storage area to superordinate, update super
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. */
203 ffetarget_align (ffetargetAlign
*updated_alignment
,
204 ffetargetAlign
*updated_modulo
, ffetargetOffset offset
,
205 ffetargetAlign alignment
, ffetargetAlign modulo
)
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. */
218 assert (alignment
> 0);
219 assert (*updated_alignment
> 0);
221 assert (*updated_modulo
< *updated_alignment
);
222 assert (modulo
< alignment
);
224 /* The easy case: similar alignment requirements. */
225 if (*updated_alignment
== alignment
)
227 if (modulo
> *updated_modulo
)
228 pad
= alignment
- (modulo
- *updated_modulo
);
230 pad
= *updated_modulo
- modulo
;
232 /* De-negatize offset, since % wouldn't do the expected thing. */
233 offset
= alignment
- ((- offset
) % alignment
);
234 pad
= (offset
+ pad
) % alignment
;
236 pad
= alignment
- pad
;
240 /* Sigh, find LCM (Least Common Multiple) for the two alignment factors. */
242 for (ua
= *updated_alignment
, ucnt
= 1;
244 ua
+= *updated_alignment
)
247 cnt
= ua
/ alignment
;
250 /* De-negatize offset, since % wouldn't do the expected thing. */
251 offset
= ua
- ((- offset
) % ua
);
253 /* Set to largest value. */
254 min_pad
= ~(ffetargetAlign
) 0;
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
261 for (um
= *updated_modulo
, i
= 0; i
< ucnt
; um
+= *updated_alignment
, ++i
)
263 for (m
= modulo
, j
= 0; j
< cnt
; m
+= alignment
, ++j
)
265 /* This code is similar to the "easy case" code above. */
270 pad
= (offset
+ pad
) % ua
;
273 /* A zero pad means we've got something useful. */
274 *updated_alignment
= ua
;
275 *updated_modulo
= um
;
280 { /* New minimum padding value. */
287 *updated_alignment
= ua
;
288 *updated_modulo
= min_m
;
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
299 #if FFETARGET_okCHARACTER1
301 ffetarget_character1 (ffetargetCharacter1
*val
, ffelexToken character
,
304 val
->length
= ffelex_token_length (character
);
305 if (val
->length
== 0)
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';
318 /* Produce orderable comparison between two constants
320 Compare lengths, if equal then use memcmp. */
322 #if FFETARGET_okCHARACTER1
324 ffetarget_cmp_character1 (ffetargetCharacter1 l
, ffetargetCharacter1 r
)
326 if (l
.length
< r
.length
)
328 if (l
.length
> r
.length
)
332 return memcmp (l
.text
, r
.text
, l
.length
);
336 /* ffetarget_concatenate_character1 -- Perform CONCAT op on two constants
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
345 #if FFETARGET_okCHARACTER1
347 ffetarget_concatenate_character1 (ffetargetCharacter1
*res
,
348 ffetargetCharacter1 l
, ffetargetCharacter1 r
, mallocPool pool
,
349 ffetargetCharacterSize
*len
)
351 res
->length
= *len
= l
.length
+ r
.length
;
356 res
->text
= malloc_new_kp (pool
, "ffetargetCharacter1(CONCAT)", *len
+ 1);
358 memcpy (res
->text
, l
.text
, l
.length
);
360 memcpy (res
->text
+ l
.length
, r
.text
, r
.length
);
361 res
->text
[*len
] = '\0';
368 /* ffetarget_eq_character1 -- Perform relational comparison on char constants
370 Compare lengths, if equal then use memcmp. */
372 #if FFETARGET_okCHARACTER1
374 ffetarget_eq_character1 (bool *res
, ffetargetCharacter1 l
,
375 ffetargetCharacter1 r
)
377 assert (l
.length
== r
.length
);
378 *res
= (memcmp (l
.text
, r
.text
, l
.length
) == 0);
383 /* ffetarget_le_character1 -- Perform relational comparison on char constants
385 Compare lengths, if equal then use memcmp. */
387 #if FFETARGET_okCHARACTER1
389 ffetarget_le_character1 (bool *res
, ffetargetCharacter1 l
,
390 ffetargetCharacter1 r
)
392 assert (l
.length
== r
.length
);
393 *res
= (memcmp (l
.text
, r
.text
, l
.length
) <= 0);
398 /* ffetarget_lt_character1 -- Perform relational comparison on char constants
400 Compare lengths, if equal then use memcmp. */
402 #if FFETARGET_okCHARACTER1
404 ffetarget_lt_character1 (bool *res
, ffetargetCharacter1 l
,
405 ffetargetCharacter1 r
)
407 assert (l
.length
== r
.length
);
408 *res
= (memcmp (l
.text
, r
.text
, l
.length
) < 0);
413 /* ffetarget_ge_character1 -- Perform relational comparison on char constants
415 Compare lengths, if equal then use memcmp. */
417 #if FFETARGET_okCHARACTER1
419 ffetarget_ge_character1 (bool *res
, ffetargetCharacter1 l
,
420 ffetargetCharacter1 r
)
422 assert (l
.length
== r
.length
);
423 *res
= (memcmp (l
.text
, r
.text
, l
.length
) >= 0);
428 /* ffetarget_gt_character1 -- Perform relational comparison on char constants
430 Compare lengths, if equal then use memcmp. */
432 #if FFETARGET_okCHARACTER1
434 ffetarget_gt_character1 (bool *res
, ffetargetCharacter1 l
,
435 ffetargetCharacter1 r
)
437 assert (l
.length
== r
.length
);
438 *res
= (memcmp (l
.text
, r
.text
, l
.length
) > 0);
443 #if FFETARGET_okCHARACTER1
445 ffetarget_iszero_character1 (ffetargetCharacter1 constant
)
447 ffetargetCharacterSize i
;
449 for (i
= 0; i
< constant
.length
; ++i
)
450 if (constant
.text
[i
] != 0)
457 ffetarget_iszero_hollerith (ffetargetHollerith constant
)
459 ffetargetHollerithSize i
;
461 for (i
= 0; i
< constant
.length
; ++i
)
462 if (constant
.text
[i
] != 0)
467 /* ffetarget_layout -- Do storage requirement analysis for entity
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). */
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
)
479 bool ok
; /* For character type. */
480 ffetargetOffset numele
; /* Converted from num_elements. */
483 type
= ffeinfo_type (bt
, kt
);
484 assert (type
!= NULL
);
486 *alignment
= ffetype_alignment (type
);
487 *modulo
= ffetype_modulo (type
);
488 if (bt
== FFEINFO_basictypeCHARACTER
)
490 ok
= ffetarget_offset_charsize (size
, charsize
, ffetype_size (type
));
491 #ifdef ffetarget_offset_overflow
493 ffetarget_offset_overflow (error_text
);
497 *size
= ffetype_size (type
);
499 if ((num_elements
< 0)
500 || !ffetarget_offset (&numele
, num_elements
)
501 || !ffetarget_offset_multiply (size
, *size
, numele
))
503 ffetarget_offset_overflow (error_text
);
510 /* ffetarget_ne_character1 -- Perform relational comparison on char constants
512 Compare lengths, if equal then use memcmp. */
514 #if FFETARGET_okCHARACTER1
516 ffetarget_ne_character1 (bool *res
, ffetargetCharacter1 l
,
517 ffetargetCharacter1 r
)
519 assert (l
.length
== r
.length
);
520 *res
= (memcmp (l
.text
, r
.text
, l
.length
) != 0);
525 /* ffetarget_substr_character1 -- Perform SUBSTR op on three constants
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
534 #if FFETARGET_okCHARACTER1
536 ffetarget_substr_character1 (ffetargetCharacter1
*res
,
537 ffetargetCharacter1 l
,
538 ffetargetCharacterSize first
,
539 ffetargetCharacterSize last
, mallocPool pool
,
540 ffetargetCharacterSize
*len
)
544 res
->length
= *len
= 0;
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';
559 /* ffetarget_cmp_hollerith -- Produce orderable comparison between two
562 Compare lengths, if equal then use memcmp. */
565 ffetarget_cmp_hollerith (ffetargetHollerith l
, ffetargetHollerith r
)
567 if (l
.length
< r
.length
)
569 if (l
.length
> r
.length
)
571 return memcmp (l
.text
, r
.text
, l
.length
);
575 ffetarget_convert_any_character1_ (char *res
, size_t size
,
576 ffetargetCharacter1 l
)
578 if (size
<= (size_t) l
.length
)
581 ffetargetCharacterSize i
;
583 memcpy (res
, l
.text
, size
);
584 for (p
= &l
.text
[0] + size
, i
= l
.length
- size
;
588 return FFEBAD_TRUNCATING_CHARACTER
;
592 memcpy (res
, l
.text
, size
);
593 memset (res
+ l
.length
, ' ', size
- l
.length
);
600 ffetarget_convert_any_hollerith_ (char *res
, size_t size
,
601 ffetargetHollerith l
)
603 if (size
<= (size_t) l
.length
)
606 ffetargetCharacterSize i
;
608 memcpy (res
, l
.text
, size
);
609 for (p
= &l
.text
[0] + size
, i
= l
.length
- size
;
613 return FFEBAD_TRUNCATING_HOLLERITH
;
617 memcpy (res
, l
.text
, size
);
618 memset (res
+ l
.length
, ' ', size
- l
.length
);
625 ffetarget_convert_any_typeless_ (char *res
, size_t size
,
628 unsigned long long int l1
;
629 unsigned long int l2
;
631 unsigned short int l4
;
636 if (size
>= sizeof (l1
))
640 size_of
= sizeof (l1
);
642 else if (size
>= sizeof (l2
))
646 size_of
= sizeof (l2
);
649 else if (size
>= sizeof (l3
))
653 size_of
= sizeof (l3
);
656 else if (size
>= sizeof (l4
))
660 size_of
= sizeof (l4
);
663 else if (size
>= sizeof (l5
))
667 size_of
= sizeof (l5
);
672 assert ("stumped by conversion from typeless!" == NULL
);
678 int i
= size_of
- size
;
680 memcpy (res
, p
+ i
, size
);
681 for (; i
> 0; ++p
, --i
)
683 return FFEBAD_TRUNCATING_TYPELESS
;
687 int i
= size
- size_of
;
690 memcpy (res
+ i
, p
, size_of
);
694 return FFEBAD_TRUNCATING_TYPELESS
;
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
705 #if FFETARGET_okCHARACTER1
707 ffetarget_convert_character1_character1 (ffetargetCharacter1
*res
,
708 ffetargetCharacterSize size
,
709 ffetargetCharacter1 l
,
717 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
+ 1);
718 if (size
<= l
.length
)
719 memcpy (res
->text
, l
.text
, size
);
722 memcpy (res
->text
, l
.text
, l
.length
);
723 memset (res
->text
+ l
.length
, ' ', size
- l
.length
);
725 res
->text
[size
] = '\0';
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
740 #if FFETARGET_okCHARACTER1
742 ffetarget_convert_character1_hollerith (ffetargetCharacter1
*res
,
743 ffetargetCharacterSize size
,
744 ffetargetHollerith l
, mallocPool pool
)
751 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
+ 1);
752 res
->text
[size
] = '\0';
753 if (size
<= l
.length
)
756 ffetargetCharacterSize i
;
758 memcpy (res
->text
, l
.text
, size
);
759 for (p
= &l
.text
[0] + size
, i
= l
.length
- size
;
763 return FFEBAD_TRUNCATING_HOLLERITH
;
767 memcpy (res
->text
, l
.text
, l
.length
);
768 memset (res
->text
+ l
.length
, ' ', size
- l
.length
);
776 /* ffetarget_convert_character1_integer4 -- Raw conversion.
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
785 #if FFETARGET_okCHARACTER1
787 ffetarget_convert_character1_integer4 (ffetargetCharacter1
*res
,
788 ffetargetCharacterSize size
,
789 ffetargetInteger4 l
, mallocPool pool
)
799 if (((size_t) size
) >= sizeof (l1
))
803 size_of
= sizeof (l1
);
805 else if (((size_t) size
) >= sizeof (l2
))
809 size_of
= sizeof (l2
);
812 else if (((size_t) size
) >= sizeof (l3
))
816 size_of
= sizeof (l3
);
819 else if (((size_t) size
) >= sizeof (l4
))
823 size_of
= sizeof (l4
);
826 else if (((size_t) size
) >= sizeof (l5
))
830 size_of
= sizeof (l5
);
835 assert ("stumped by conversion from integer1!" == NULL
);
844 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
+ 1);
845 res
->text
[size
] = '\0';
846 if (((size_t) size
) <= size_of
)
848 int i
= size_of
- size
;
850 memcpy (res
->text
, p
+ i
, size
);
851 for (; i
> 0; ++p
, --i
)
853 return FFEBAD_TRUNCATING_NUMERIC
;
857 int i
= size
- size_of
;
859 memset (res
->text
, 0, i
);
860 memcpy (res
->text
+ i
, p
, size_of
);
865 return FFEBAD_TRUNCATING_NUMERIC
;
870 /* ffetarget_convert_character1_logical4 -- Raw conversion.
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
879 #if FFETARGET_okCHARACTER1
881 ffetarget_convert_character1_logical4 (ffetargetCharacter1
*res
,
882 ffetargetCharacterSize size
,
883 ffetargetLogical4 l
, mallocPool pool
)
893 if (((size_t) size
) >= sizeof (l1
))
897 size_of
= sizeof (l1
);
899 else if (((size_t) size
) >= sizeof (l2
))
903 size_of
= sizeof (l2
);
906 else if (((size_t) size
) >= sizeof (l3
))
910 size_of
= sizeof (l3
);
913 else if (((size_t) size
) >= sizeof (l4
))
917 size_of
= sizeof (l4
);
920 else if (((size_t) size
) >= sizeof (l5
))
924 size_of
= sizeof (l5
);
929 assert ("stumped by conversion from logical1!" == NULL
);
938 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
+ 1);
939 res
->text
[size
] = '\0';
940 if (((size_t) size
) <= size_of
)
942 int i
= size_of
- size
;
944 memcpy (res
->text
, p
+ i
, size
);
945 for (; i
> 0; ++p
, --i
)
947 return FFEBAD_TRUNCATING_NUMERIC
;
951 int i
= size
- size_of
;
953 memset (res
->text
, 0, i
);
954 memcpy (res
->text
+ i
, p
, size_of
);
959 return FFEBAD_TRUNCATING_NUMERIC
;
964 /* ffetarget_convert_character1_typeless -- Raw conversion.
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
973 #if FFETARGET_okCHARACTER1
975 ffetarget_convert_character1_typeless (ffetargetCharacter1
*res
,
976 ffetargetCharacterSize size
,
977 ffetargetTypeless l
, mallocPool pool
)
979 unsigned long long int l1
;
980 unsigned long int l2
;
982 unsigned short int l4
;
987 if (((size_t) size
) >= sizeof (l1
))
991 size_of
= sizeof (l1
);
993 else if (((size_t) size
) >= sizeof (l2
))
997 size_of
= sizeof (l2
);
1000 else if (((size_t) size
) >= sizeof (l3
))
1004 size_of
= sizeof (l3
);
1007 else if (((size_t) size
) >= sizeof (l4
))
1011 size_of
= sizeof (l4
);
1014 else if (((size_t) size
) >= sizeof (l5
))
1018 size_of
= sizeof (l5
);
1023 assert ("stumped by conversion from typeless!" == NULL
);
1032 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
+ 1);
1033 res
->text
[size
] = '\0';
1034 if (((size_t) size
) <= size_of
)
1036 int i
= size_of
- size
;
1038 memcpy (res
->text
, p
+ i
, size
);
1039 for (; i
> 0; ++p
, --i
)
1041 return FFEBAD_TRUNCATING_TYPELESS
;
1045 int i
= size
- size_of
;
1047 memset (res
->text
, 0, i
);
1048 memcpy (res
->text
+ i
, p
, size_of
);
1053 return FFEBAD_TRUNCATING_TYPELESS
;
1058 /* ffetarget_divide_complex1 -- Divide function
1062 #if FFETARGET_okCOMPLEX1
1064 ffetarget_divide_complex1 (ffetargetComplex1
*res
, ffetargetComplex1 l
,
1065 ffetargetComplex1 r
)
1068 ffetargetReal1 tmp1
, tmp2
, tmp3
, tmp4
;
1070 bad
= ffetarget_multiply_real1 (&tmp1
, r
.real
, r
.real
);
1073 bad
= ffetarget_multiply_real1 (&tmp2
, r
.imaginary
, r
.imaginary
);
1076 bad
= ffetarget_add_real1 (&tmp3
, tmp1
, tmp2
);
1080 if (ffetarget_iszero_real1 (tmp3
))
1082 ffetarget_real1_zero (&(res
)->real
);
1083 ffetarget_real1_zero (&(res
)->imaginary
);
1084 return FFEBAD_DIV_BY_ZERO
;
1087 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, r
.real
);
1090 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, r
.imaginary
);
1093 bad
= ffetarget_add_real1 (&tmp4
, tmp1
, tmp2
);
1096 bad
= ffetarget_divide_real1 (&res
->real
, tmp4
, tmp3
);
1100 bad
= ffetarget_multiply_real1 (&tmp1
, r
.real
, l
.imaginary
);
1103 bad
= ffetarget_multiply_real1 (&tmp2
, l
.real
, r
.imaginary
);
1106 bad
= ffetarget_subtract_real1 (&tmp4
, tmp1
, tmp2
);
1109 bad
= ffetarget_divide_real1 (&res
->imaginary
, tmp4
, tmp3
);
1115 /* ffetarget_divide_complex2 -- Divide function
1119 #if FFETARGET_okCOMPLEX2
1121 ffetarget_divide_complex2 (ffetargetComplex2
*res
, ffetargetComplex2 l
,
1122 ffetargetComplex2 r
)
1125 ffetargetReal2 tmp1
, tmp2
, tmp3
, tmp4
;
1127 bad
= ffetarget_multiply_real2 (&tmp1
, r
.real
, r
.real
);
1130 bad
= ffetarget_multiply_real2 (&tmp2
, r
.imaginary
, r
.imaginary
);
1133 bad
= ffetarget_add_real2 (&tmp3
, tmp1
, tmp2
);
1137 if (ffetarget_iszero_real2 (tmp3
))
1139 ffetarget_real2_zero (&(res
)->real
);
1140 ffetarget_real2_zero (&(res
)->imaginary
);
1141 return FFEBAD_DIV_BY_ZERO
;
1144 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, r
.real
);
1147 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, r
.imaginary
);
1150 bad
= ffetarget_add_real2 (&tmp4
, tmp1
, tmp2
);
1153 bad
= ffetarget_divide_real2 (&res
->real
, tmp4
, tmp3
);
1157 bad
= ffetarget_multiply_real2 (&tmp1
, r
.real
, l
.imaginary
);
1160 bad
= ffetarget_multiply_real2 (&tmp2
, l
.real
, r
.imaginary
);
1163 bad
= ffetarget_subtract_real2 (&tmp4
, tmp1
, tmp2
);
1166 bad
= ffetarget_divide_real2 (&res
->imaginary
, tmp4
, tmp3
);
1172 /* ffetarget_hollerith -- Convert token to a hollerith constant
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
1182 ffetarget_hollerith (ffetargetHollerith
*val
, ffelexToken integer
,
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';
1193 /* ffetarget_integer_bad_magical -- Complain about a magical number
1195 Just calls ffebad with the arguments. */
1198 ffetarget_integer_bad_magical (ffelexToken t
)
1200 ffebad_start (FFEBAD_BAD_MAGICAL
);
1201 ffebad_here (0, ffelex_token_where_line (t
), ffelex_token_where_column (t
));
1205 /* ffetarget_integer_bad_magical_binary -- Complain about a magical number
1207 Just calls ffebad with the arguments. */
1210 ffetarget_integer_bad_magical_binary (ffelexToken integer
,
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
));
1221 /* ffetarget_integer_bad_magical_precedence -- Complain about a magical
1224 Just calls ffebad with the arguments. */
1227 ffetarget_integer_bad_magical_precedence (ffelexToken integer
,
1229 ffelexToken higher_op
)
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
));
1241 /* ffetarget_integer_bad_magical_precedence_binary -- Complain...
1243 Just calls ffebad with the arguments. */
1246 ffetarget_integer_bad_magical_precedence_binary (ffelexToken integer
,
1248 ffelexToken higher_op
)
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
));
1260 /* ffetarget_integer1 -- Convert token to an integer
1264 Token use count not affected overall. */
1266 #if FFETARGET_okINTEGER1
1268 ffetarget_integer1 (ffetargetInteger1
*val
, ffelexToken integer
)
1270 ffetargetInteger1 x
;
1274 assert (ffelex_token_type (integer
) == FFELEX_typeNUMBER
);
1276 p
= ffelex_token_text (integer
);
1279 /* Skip past leading zeros. */
1281 while (((c
= *p
) != '\0') && (c
== '0'))
1284 /* Interpret rest of number. */
1288 if ((x
== FFETARGET_integerALMOST_BIG_MAGICAL
)
1289 && (c
== '0' + FFETARGET_integerFINISH_BIG_MAGICAL
)
1290 && (*(p
+ 1) == '\0'))
1292 *val
= (ffetargetInteger1
) FFETARGET_integerBIG_MAGICAL
;
1295 else if (x
== FFETARGET_integerALMOST_BIG_MAGICAL
)
1297 if ((c
> '0' + FFETARGET_integerFINISH_BIG_MAGICAL
)
1298 || (*(p
+ 1) != '\0'))
1300 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1301 ffebad_here (0, ffelex_token_where_line (integer
),
1302 ffelex_token_where_column (integer
));
1308 else if (x
> FFETARGET_integerALMOST_BIG_MAGICAL
)
1310 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1311 ffebad_here (0, ffelex_token_where_line (integer
),
1312 ffelex_token_where_column (integer
));
1317 x
= x
* 10 + c
- '0';
1326 /* ffetarget_integerbinary -- Convert token to a binary integer
1328 ffetarget_integerbinary x;
1329 if (ffetarget_integerdefault_8(&x,integer_token))
1332 Token use count not affected overall. */
1335 ffetarget_integerbinary (ffetargetIntegerDefault
*val
, ffelexToken integer
)
1337 ffetargetIntegerDefault x
;
1342 assert ((ffelex_token_type (integer
) == FFELEX_typeNAME
)
1343 || (ffelex_token_type (integer
) == FFELEX_typeNUMBER
));
1345 p
= ffelex_token_text (integer
);
1348 /* Skip past leading zeros. */
1350 while (((c
= *p
) != '\0') && (c
== '0'))
1353 /* Interpret rest of number. */
1358 if ((c
>= '0') && (c
<= '1'))
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'))
1372 *val
= FFETARGET_integerBIG_OVERFLOW_BINARY
;
1377 #if FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY == 0
1378 if ((x
& FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY
) != 0)
1380 if (x
== FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY
)
1382 if ((c
> FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY
)
1383 || (*(p
+ 1) != '\0'))
1385 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1386 ffebad_here (0, ffelex_token_where_line (integer
),
1387 ffelex_token_where_column (integer
));
1393 else if (x
> FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY
)
1396 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1397 ffebad_here (0, ffelex_token_where_line (integer
),
1398 ffelex_token_where_column (integer
));
1409 ffebad_start (FFEBAD_INVALID_BINARY_DIGIT
);
1410 ffebad_here (0, ffelex_token_where_line (integer
),
1411 ffelex_token_where_column (integer
));
1419 /* ffetarget_integerhex -- Convert token to a hex integer
1421 ffetarget_integerhex x;
1422 if (ffetarget_integerdefault_8(&x,integer_token))
1425 Token use count not affected overall. */
1428 ffetarget_integerhex (ffetargetIntegerDefault
*val
, ffelexToken integer
)
1430 ffetargetIntegerDefault x
;
1435 assert ((ffelex_token_type (integer
) == FFELEX_typeNAME
)
1436 || (ffelex_token_type (integer
) == FFELEX_typeNUMBER
));
1438 p
= ffelex_token_text (integer
);
1441 /* Skip past leading zeros. */
1443 while (((c
= *p
) != '\0') && (c
== '0'))
1446 /* Interpret rest of number. */
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'))
1465 *val
= FFETARGET_integerBIG_OVERFLOW_HEX
;
1470 #if FFETARGET_integerFINISH_BIG_OVERFLOW_HEX == 0
1471 if (x
>= FFETARGET_integerALMOST_BIG_OVERFLOW_HEX
)
1473 if (x
== FFETARGET_integerALMOST_BIG_OVERFLOW_HEX
)
1475 if ((c
> FFETARGET_integerFINISH_BIG_OVERFLOW_HEX
)
1476 || (*(p
+ 1) != '\0'))
1478 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1479 ffebad_here (0, ffelex_token_where_line (integer
),
1480 ffelex_token_where_column (integer
));
1486 else if (x
> FFETARGET_integerALMOST_BIG_OVERFLOW_HEX
)
1489 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1490 ffebad_here (0, ffelex_token_where_line (integer
),
1491 ffelex_token_where_column (integer
));
1502 ffebad_start (FFEBAD_INVALID_HEX_DIGIT
);
1503 ffebad_here (0, ffelex_token_where_line (integer
),
1504 ffelex_token_where_column (integer
));
1512 /* ffetarget_integeroctal -- Convert token to an octal integer
1514 ffetarget_integeroctal x;
1515 if (ffetarget_integerdefault_8(&x,integer_token))
1518 Token use count not affected overall. */
1521 ffetarget_integeroctal (ffetargetIntegerDefault
*val
, ffelexToken integer
)
1523 ffetargetIntegerDefault x
;
1528 assert ((ffelex_token_type (integer
) == FFELEX_typeNAME
)
1529 || (ffelex_token_type (integer
) == FFELEX_typeNUMBER
));
1531 p
= ffelex_token_text (integer
);
1534 /* Skip past leading zeros. */
1536 while (((c
= *p
) != '\0') && (c
== '0'))
1539 /* Interpret rest of number. */
1544 if ((c
>= '0') && (c
<= '7'))
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'))
1558 *val
= FFETARGET_integerBIG_OVERFLOW_OCTAL
;
1563 #if FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL == 0
1564 if (x
>= FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL
)
1566 if (x
== FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL
)
1568 if ((c
> FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL
)
1569 || (*(p
+ 1) != '\0'))
1571 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1572 ffebad_here (0, ffelex_token_where_line (integer
),
1573 ffelex_token_where_column (integer
));
1579 else if (x
> FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL
)
1582 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1583 ffebad_here (0, ffelex_token_where_line (integer
),
1584 ffelex_token_where_column (integer
));
1595 ffebad_start (FFEBAD_INVALID_OCTAL_DIGIT
);
1596 ffebad_here (0, ffelex_token_where_line (integer
),
1597 ffelex_token_where_column (integer
));
1605 /* ffetarget_multiply_complex1 -- Multiply function
1609 #if FFETARGET_okCOMPLEX1
1611 ffetarget_multiply_complex1 (ffetargetComplex1
*res
, ffetargetComplex1 l
,
1612 ffetargetComplex1 r
)
1615 ffetargetReal1 tmp1
, tmp2
;
1617 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, r
.real
);
1620 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, r
.imaginary
);
1623 bad
= ffetarget_subtract_real1 (&res
->real
, tmp1
, tmp2
);
1626 bad
= ffetarget_multiply_real1 (&tmp1
, l
.imaginary
, r
.real
);
1629 bad
= ffetarget_multiply_real1 (&tmp2
, l
.real
, r
.imaginary
);
1632 bad
= ffetarget_add_real1 (&res
->imaginary
, tmp1
, tmp2
);
1638 /* ffetarget_multiply_complex2 -- Multiply function
1642 #if FFETARGET_okCOMPLEX2
1644 ffetarget_multiply_complex2 (ffetargetComplex2
*res
, ffetargetComplex2 l
,
1645 ffetargetComplex2 r
)
1648 ffetargetReal2 tmp1
, tmp2
;
1650 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, r
.real
);
1653 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, r
.imaginary
);
1656 bad
= ffetarget_subtract_real2 (&res
->real
, tmp1
, tmp2
);
1659 bad
= ffetarget_multiply_real2 (&tmp1
, l
.imaginary
, r
.real
);
1662 bad
= ffetarget_multiply_real2 (&tmp2
, l
.real
, r
.imaginary
);
1665 bad
= ffetarget_add_real2 (&res
->imaginary
, tmp1
, tmp2
);
1671 /* ffetarget_power_complexdefault_integerdefault -- Power function
1676 ffetarget_power_complexdefault_integerdefault (ffetargetComplexDefault
*res
,
1677 ffetargetComplexDefault l
,
1678 ffetargetIntegerDefault r
)
1681 ffetargetRealDefault tmp
;
1682 ffetargetRealDefault tmp1
;
1683 ffetargetRealDefault tmp2
;
1684 ffetargetRealDefault two
;
1686 if (ffetarget_iszero_real1 (l
.real
)
1687 && ffetarget_iszero_real1 (l
.imaginary
))
1689 ffetarget_real1_zero (&res
->real
);
1690 ffetarget_real1_zero (&res
->imaginary
);
1696 ffetarget_real1_one (&res
->real
);
1697 ffetarget_real1_zero (&res
->imaginary
);
1704 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, l
.real
);
1707 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, l
.imaginary
);
1710 bad
= ffetarget_add_real1 (&tmp
, tmp1
, tmp2
);
1713 bad
= ffetarget_divide_real1 (&l
.real
, l
.real
, tmp
);
1716 bad
= ffetarget_divide_real1 (&l
.imaginary
, l
.imaginary
, tmp
);
1719 bad
= ffetarget_uminus_real1 (&l
.imaginary
, l
.imaginary
);
1724 ffetarget_real1_two (&two
);
1726 while ((r
& 1) == 0)
1728 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, l
.real
);
1731 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, l
.imaginary
);
1734 bad
= ffetarget_subtract_real1 (&tmp
, tmp1
, tmp2
);
1737 bad
= ffetarget_multiply_real1 (&l
.imaginary
, l
.real
, l
.imaginary
);
1740 bad
= ffetarget_multiply_real1 (&l
.imaginary
, l
.imaginary
, two
);
1752 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, l
.real
);
1755 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, l
.imaginary
);
1758 bad
= ffetarget_subtract_real1 (&tmp
, tmp1
, tmp2
);
1761 bad
= ffetarget_multiply_real1 (&l
.imaginary
, l
.real
, l
.imaginary
);
1764 bad
= ffetarget_multiply_real1 (&l
.imaginary
, l
.imaginary
, two
);
1770 bad
= ffetarget_multiply_real1 (&tmp1
, res
->real
, l
.real
);
1773 bad
= ffetarget_multiply_real1 (&tmp2
, res
->imaginary
,
1777 bad
= ffetarget_subtract_real1 (&tmp
, tmp1
, tmp2
);
1780 bad
= ffetarget_multiply_real1 (&tmp1
, res
->imaginary
, l
.real
);
1783 bad
= ffetarget_multiply_real1 (&tmp2
, res
->real
, l
.imaginary
);
1786 bad
= ffetarget_add_real1 (&res
->imaginary
, tmp1
, tmp2
);
1797 /* ffetarget_power_complexdouble_integerdefault -- Power function
1801 #if FFETARGET_okCOMPLEXDOUBLE
1803 ffetarget_power_complexdouble_integerdefault (ffetargetComplexDouble
*res
,
1804 ffetargetComplexDouble l
, ffetargetIntegerDefault r
)
1807 ffetargetRealDouble tmp
;
1808 ffetargetRealDouble tmp1
;
1809 ffetargetRealDouble tmp2
;
1810 ffetargetRealDouble two
;
1812 if (ffetarget_iszero_real2 (l
.real
)
1813 && ffetarget_iszero_real2 (l
.imaginary
))
1815 ffetarget_real2_zero (&res
->real
);
1816 ffetarget_real2_zero (&res
->imaginary
);
1822 ffetarget_real2_one (&res
->real
);
1823 ffetarget_real2_zero (&res
->imaginary
);
1830 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, l
.real
);
1833 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, l
.imaginary
);
1836 bad
= ffetarget_add_real2 (&tmp
, tmp1
, tmp2
);
1839 bad
= ffetarget_divide_real2 (&l
.real
, l
.real
, tmp
);
1842 bad
= ffetarget_divide_real2 (&l
.imaginary
, l
.imaginary
, tmp
);
1845 bad
= ffetarget_uminus_real2 (&l
.imaginary
, l
.imaginary
);
1850 ffetarget_real2_two (&two
);
1852 while ((r
& 1) == 0)
1854 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, l
.real
);
1857 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, l
.imaginary
);
1860 bad
= ffetarget_subtract_real2 (&tmp
, tmp1
, tmp2
);
1863 bad
= ffetarget_multiply_real2 (&l
.imaginary
, l
.real
, l
.imaginary
);
1866 bad
= ffetarget_multiply_real2 (&l
.imaginary
, l
.imaginary
, two
);
1878 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, l
.real
);
1881 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, l
.imaginary
);
1884 bad
= ffetarget_subtract_real2 (&tmp
, tmp1
, tmp2
);
1887 bad
= ffetarget_multiply_real2 (&l
.imaginary
, l
.real
, l
.imaginary
);
1890 bad
= ffetarget_multiply_real2 (&l
.imaginary
, l
.imaginary
, two
);
1896 bad
= ffetarget_multiply_real2 (&tmp1
, res
->real
, l
.real
);
1899 bad
= ffetarget_multiply_real2 (&tmp2
, res
->imaginary
,
1903 bad
= ffetarget_subtract_real2 (&tmp
, tmp1
, tmp2
);
1906 bad
= ffetarget_multiply_real2 (&tmp1
, res
->imaginary
, l
.real
);
1909 bad
= ffetarget_multiply_real2 (&tmp2
, res
->real
, l
.imaginary
);
1912 bad
= ffetarget_add_real2 (&res
->imaginary
, tmp1
, tmp2
);
1924 /* ffetarget_power_integerdefault_integerdefault -- Power function
1929 ffetarget_power_integerdefault_integerdefault (ffetargetIntegerDefault
*res
,
1930 ffetargetIntegerDefault l
, ffetargetIntegerDefault r
)
1951 *res
= ((-r
) & 1) == 0 ? 1 : -1;
1957 while ((r
& 1) == 0)
1977 /* ffetarget_power_realdefault_integerdefault -- Power function
1982 ffetarget_power_realdefault_integerdefault (ffetargetRealDefault
*res
,
1983 ffetargetRealDefault l
, ffetargetIntegerDefault r
)
1987 if (ffetarget_iszero_real1 (l
))
1989 ffetarget_real1_zero (res
);
1995 ffetarget_real1_one (res
);
2001 ffetargetRealDefault one
;
2003 ffetarget_real1_one (&one
);
2005 bad
= ffetarget_divide_real1 (&l
, one
, l
);
2010 while ((r
& 1) == 0)
2012 bad
= ffetarget_multiply_real1 (&l
, l
, l
);
2023 bad
= ffetarget_multiply_real1 (&l
, l
, l
);
2028 bad
= ffetarget_multiply_real1 (res
, *res
, l
);
2038 /* ffetarget_power_realdouble_integerdefault -- Power function
2043 ffetarget_power_realdouble_integerdefault (ffetargetRealDouble
*res
,
2044 ffetargetRealDouble l
,
2045 ffetargetIntegerDefault r
)
2049 if (ffetarget_iszero_real2 (l
))
2051 ffetarget_real2_zero (res
);
2057 ffetarget_real2_one (res
);
2063 ffetargetRealDouble one
;
2065 ffetarget_real2_one (&one
);
2067 bad
= ffetarget_divide_real2 (&l
, one
, l
);
2072 while ((r
& 1) == 0)
2074 bad
= ffetarget_multiply_real2 (&l
, l
, l
);
2085 bad
= ffetarget_multiply_real2 (&l
, l
, l
);
2090 bad
= ffetarget_multiply_real2 (res
, *res
, l
);
2100 /* ffetarget_print_binary -- Output typeless binary integer
2102 ffetargetTypeless val;
2103 ffetarget_typeless_binary(dmpout,val); */
2106 ffetarget_print_binary (FILE *f
, ffetargetTypeless value
)
2109 char digits
[sizeof (value
) * CHAR_BIT
+ 1];
2114 p
= &digits
[ARRAY_SIZE (digits
) - 1];
2118 *--p
= (value
& 1) + '0';
2120 } while (value
== 0);
2125 /* ffetarget_print_character1 -- Output character string
2127 ffetargetCharacter1 val;
2128 ffetarget_print_character1(dmpout,val); */
2131 ffetarget_print_character1 (FILE *f
, ffetargetCharacter1 value
)
2134 ffetargetCharacterSize i
;
2136 fputc ('\'', dmpout
);
2137 for (i
= 0, p
= value
.text
; i
< value
.length
; ++i
, ++p
)
2138 ffetarget_print_char_ (f
, *p
);
2139 fputc ('\'', dmpout
);
2142 /* ffetarget_print_hollerith -- Output hollerith string
2144 ffetargetHollerith val;
2145 ffetarget_print_hollerith(dmpout,val); */
2148 ffetarget_print_hollerith (FILE *f
, ffetargetHollerith value
)
2151 ffetargetHollerithSize i
;
2153 fputc ('\'', dmpout
);
2154 for (i
= 0, p
= value
.text
; i
< value
.length
; ++i
, ++p
)
2155 ffetarget_print_char_ (f
, *p
);
2156 fputc ('\'', dmpout
);
2159 /* ffetarget_print_octal -- Output typeless octal integer
2161 ffetargetTypeless val;
2162 ffetarget_print_octal(dmpout,val); */
2165 ffetarget_print_octal (FILE *f
, ffetargetTypeless value
)
2168 char digits
[sizeof (value
) * CHAR_BIT
/ 3 + 1];
2173 p
= &digits
[ARRAY_SIZE (digits
) - 3];
2177 *--p
= (value
& 3) + '0';
2179 } while (value
== 0);
2184 /* ffetarget_print_hex -- Output typeless hex integer
2186 ffetargetTypeless val;
2187 ffetarget_print_hex(dmpout,val); */
2190 ffetarget_print_hex (FILE *f
, ffetargetTypeless value
)
2193 char digits
[sizeof (value
) * CHAR_BIT
/ 4 + 1];
2194 static const char hexdigits
[16] = "0123456789ABCDEF";
2199 p
= &digits
[ARRAY_SIZE (digits
) - 3];
2203 *--p
= hexdigits
[value
& 4];
2205 } while (value
== 0);
2210 /* ffetarget_real1 -- Convert token to a single-precision real number
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. */
2220 #if FFETARGET_okREAL1
2222 ffetarget_real1 (ffetargetReal1
*value
, ffelexToken integer
,
2223 ffelexToken decimal
, ffelexToken fraction
,
2224 ffelexToken exponent
, ffelexToken exponent_sign
,
2225 ffelexToken exponent_digits
)
2227 size_t sz
= 1; /* Allow room for '\0' byte at end. */
2228 char *ptr
= &ffetarget_string_
[0];
2232 #define dotok(x) if (x != NULL) ++sz;
2233 #define dotoktxt(x) if (x != NULL) sz += ffelex_token_length(x)
2237 dotoktxt (fraction
);
2238 dotoktxt (exponent
);
2239 dotok (exponent_sign
);
2240 dotoktxt (exponent_digits
);
2245 if (sz
> ARRAY_SIZE (ffetarget_string_
))
2246 p
= ptr
= (char *) malloc_new_ks (malloc_pool_image (), "ffetarget_real1",
2249 #define dotoktxt(x) if (x != NULL) \
2251 for (q = ffelex_token_text(x); *q != '\0'; ++q) \
2257 if (decimal
!= NULL
)
2260 dotoktxt (fraction
);
2261 dotoktxt (exponent
);
2263 if (exponent_sign
!= NULL
)
2265 if (ffelex_token_type (exponent_sign
) == FFELEX_typePLUS
)
2269 assert (ffelex_token_type (exponent_sign
) == FFELEX_typeMINUS
);
2274 dotoktxt (exponent_digits
);
2282 rv
= FFETARGET_ATOF_ (ptr
, SFmode
);
2283 ffetarget_make_real1 (value
, rv
);
2286 if (sz
> ARRAY_SIZE (ffetarget_string_
))
2287 malloc_kill_ks (malloc_pool_image (), ptr
, sz
);
2293 /* ffetarget_real2 -- Convert token to a single-precision real number
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. */
2303 #if FFETARGET_okREAL2
2305 ffetarget_real2 (ffetargetReal2
*value
, ffelexToken integer
,
2306 ffelexToken decimal
, ffelexToken fraction
,
2307 ffelexToken exponent
, ffelexToken exponent_sign
,
2308 ffelexToken exponent_digits
)
2310 size_t sz
= 1; /* Allow room for '\0' byte at end. */
2311 char *ptr
= &ffetarget_string_
[0];
2315 #define dotok(x) if (x != NULL) ++sz;
2316 #define dotoktxt(x) if (x != NULL) sz += ffelex_token_length(x)
2320 dotoktxt (fraction
);
2321 dotoktxt (exponent
);
2322 dotok (exponent_sign
);
2323 dotoktxt (exponent_digits
);
2328 if (sz
> ARRAY_SIZE (ffetarget_string_
))
2329 p
= ptr
= (char *) malloc_new_ks (malloc_pool_image (), "ffetarget_real1", sz
);
2331 #define dotoktxt(x) if (x != NULL) \
2333 for (q = ffelex_token_text(x); *q != '\0'; ++q) \
2336 #define dotoktxtexp(x) if (x != NULL) \
2339 for (q = ffelex_token_text(x) + 1; *q != '\0'; ++q) \
2345 if (decimal
!= NULL
)
2348 dotoktxt (fraction
);
2349 dotoktxtexp (exponent
);
2351 if (exponent_sign
!= NULL
)
2353 if (ffelex_token_type (exponent_sign
) == FFELEX_typePLUS
)
2357 assert (ffelex_token_type (exponent_sign
) == FFELEX_typeMINUS
);
2362 dotoktxt (exponent_digits
);
2370 rv
= FFETARGET_ATOF_ (ptr
, DFmode
);
2371 ffetarget_make_real2 (value
, rv
);
2374 if (sz
> ARRAY_SIZE (ffetarget_string_
))
2375 malloc_kill_ks (malloc_pool_image (), ptr
, sz
);
2382 ffetarget_typeless_binary (ffetargetTypeless
*xvalue
, ffelexToken token
)
2386 ffetargetTypeless value
= 0;
2387 ffetargetTypeless new_value
= 0;
2388 bool bad_digit
= FALSE
;
2389 bool overflow
= FALSE
;
2391 p
= ffelex_token_text (token
);
2393 for (c
= *p
; c
!= '\0'; c
= *++p
)
2396 if ((new_value
>> 1) != value
)
2399 new_value
+= c
- '0';
2407 ffebad_start (FFEBAD_INVALID_TYPELESS_BINARY_DIGIT
);
2408 ffebad_here (0, ffelex_token_where_line (token
),
2409 ffelex_token_where_column (token
));
2414 ffebad_start (FFEBAD_TYPELESS_OVERFLOW
);
2415 ffebad_here (0, ffelex_token_where_line (token
),
2416 ffelex_token_where_column (token
));
2422 return !bad_digit
&& !overflow
;
2426 ffetarget_typeless_octal (ffetargetTypeless
*xvalue
, ffelexToken token
)
2430 ffetargetTypeless value
= 0;
2431 ffetargetTypeless new_value
= 0;
2432 bool bad_digit
= FALSE
;
2433 bool overflow
= FALSE
;
2435 p
= ffelex_token_text (token
);
2437 for (c
= *p
; c
!= '\0'; c
= *++p
)
2440 if ((new_value
>> 3) != value
)
2443 new_value
+= c
- '0';
2451 ffebad_start (FFEBAD_INVALID_TYPELESS_OCTAL_DIGIT
);
2452 ffebad_here (0, ffelex_token_where_line (token
),
2453 ffelex_token_where_column (token
));
2458 ffebad_start (FFEBAD_TYPELESS_OVERFLOW
);
2459 ffebad_here (0, ffelex_token_where_line (token
),
2460 ffelex_token_where_column (token
));
2466 return !bad_digit
&& !overflow
;
2470 ffetarget_typeless_hex (ffetargetTypeless
*xvalue
, ffelexToken token
)
2474 ffetargetTypeless value
= 0;
2475 ffetargetTypeless new_value
= 0;
2476 bool bad_digit
= FALSE
;
2477 bool overflow
= FALSE
;
2479 p
= ffelex_token_text (token
);
2481 for (c
= *p
; c
!= '\0'; c
= *++p
)
2484 if ((new_value
>> 4) != value
)
2487 new_value
+= hex_value (c
);
2495 ffebad_start (FFEBAD_INVALID_TYPELESS_HEX_DIGIT
);
2496 ffebad_here (0, ffelex_token_where_line (token
),
2497 ffelex_token_where_column (token
));
2502 ffebad_start (FFEBAD_TYPELESS_OVERFLOW
);
2503 ffebad_here (0, ffelex_token_where_line (token
),
2504 ffelex_token_where_column (token
));
2510 return !bad_digit
&& !overflow
;
2514 ffetarget_verify_character1 (mallocPool pool
, ffetargetCharacter1 val
)
2516 if (val
.length
!= 0)
2517 malloc_verify_kp (pool
, val
.text
, val
.length
);
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". */
2525 ffetarget_memcpy_ (void *dst
, void *src
, size_t len
)
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
2535 HOST_WORDS_BIG_ENDIAN
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");
2552 #endif /* CROSS_COMPILE */
2554 return (void *) memcpy (dst
, src
, len
);
2557 /* ffetarget_num_digits_ -- Determine number of non-space characters in token
2559 ffetarget_num_digits_(token);
2561 All non-spaces are assumed to be binary, octal, or hex digits. */
2564 ffetarget_num_digits_ (ffelexToken token
)
2569 switch (ffelex_token_type (token
))
2571 case FFELEX_typeNAME
:
2572 case FFELEX_typeNUMBER
:
2573 return ffelex_token_length (token
);
2575 case FFELEX_typeCHARACTER
:
2577 for (c
= ffelex_token_text (token
); *c
!= '\0'; ++c
)
2585 assert ("weird token" == NULL
);