1 /* target.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995-1998 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
79 /* Externals defined here. */
81 char ffetarget_string_
[40]; /* Temp for ascii-to-double (atof). */
82 HOST_WIDE_INT ffetarget_long_val_
;
83 HOST_WIDE_INT ffetarget_long_junk_
;
85 /* Simple definitions and enumerations. */
88 /* Internal typedefs. */
91 /* Private include files. */
94 /* Internal structure definitions. */
97 /* Static objects accessed by functions in this module. */
100 /* Static functions (internal). */
102 static void ffetarget_print_char_ (FILE *f
, unsigned char c
);
104 /* Internal macros. */
106 #ifdef REAL_VALUE_ATOF
107 #define FFETARGET_ATOF_(p,m) REAL_VALUE_ATOF ((p),(m))
109 #define FFETARGET_ATOF_(p,m) atof ((p))
113 /* ffetarget_print_char_ -- Print a single character (in apostrophe context)
117 Outputs char so it prints or is escaped C style. */
120 ffetarget_print_char_ (FILE *f
, unsigned char c
)
136 fprintf (f
, "\\%03o", (unsigned int) c
);
141 /* ffetarget_aggregate_info -- Determine type for aggregate storage area
145 If aggregate type is distinct, just return it. Else return a type
146 representing a common denominator for the nondistinct type (for now,
147 just return default character, since that'll work on almost all target
150 The rules for abt/akt are (as implemented by ffestorag_update):
152 abt == FFEINFO_basictypeANY (akt == FFEINFO_kindtypeANY also, by
153 definition): CHARACTER and non-CHARACTER types mixed.
155 abt == FFEINFO_basictypeNONE (akt == FFEINFO_kindtypeNONE also, by
156 definition): More than one non-CHARACTER type mixed, but no CHARACTER
159 abt some other value, akt == FFEINFO_kindtypeNONE: abt indicates the
160 only basic type mixed in, but more than one kind type is mixed in.
162 abt some other value, akt some other value: abt and akt indicate the
163 only type represented in the aggregation. */
166 ffetarget_aggregate_info (ffeinfoBasictype
*ebt
, ffeinfoKindtype
*ekt
,
167 ffetargetAlign
*units
, ffeinfoBasictype abt
,
172 if ((abt
== FFEINFO_basictypeNONE
) || (abt
== FFEINFO_basictypeANY
)
173 || (akt
== FFEINFO_kindtypeNONE
))
175 *ebt
= FFEINFO_basictypeCHARACTER
;
176 *ekt
= FFEINFO_kindtypeCHARACTERDEFAULT
;
184 type
= ffeinfo_type (*ebt
, *ekt
);
185 assert (type
!= NULL
);
187 *units
= ffetype_size (type
);
190 /* ffetarget_align -- Align one storage area to superordinate, update super
194 updated_alignment/updated_modulo contain the already existing
195 alignment requirements for the storage area at whose offset the
196 object with alignment requirements alignment/modulo is to be placed.
197 Find the smallest pad such that the requirements are maintained and
198 return it, but only after updating the updated_alignment/_modulo
199 requirements as necessary to indicate the placement of the new object. */
202 ffetarget_align (ffetargetAlign
*updated_alignment
,
203 ffetargetAlign
*updated_modulo
, ffetargetOffset offset
,
204 ffetargetAlign alignment
, ffetargetAlign modulo
)
207 ffetargetAlign min_pad
; /* Minimum amount of padding needed. */
208 ffetargetAlign min_m
= 0; /* Minimum-padding m. */
209 ffetargetAlign ua
; /* Updated alignment. */
210 ffetargetAlign um
; /* Updated modulo. */
211 ffetargetAlign ucnt
; /* Multiplier applied to ua. */
212 ffetargetAlign m
; /* Copy of modulo. */
213 ffetargetAlign cnt
; /* Multiplier applied to alignment. */
217 assert (alignment
> 0);
218 assert (*updated_alignment
> 0);
220 assert (*updated_modulo
< *updated_alignment
);
221 assert (modulo
< alignment
);
223 /* The easy case: similar alignment requirements. */
224 if (*updated_alignment
== alignment
)
226 if (modulo
> *updated_modulo
)
227 pad
= alignment
- (modulo
- *updated_modulo
);
229 pad
= *updated_modulo
- modulo
;
231 /* De-negatize offset, since % wouldn't do the expected thing. */
232 offset
= alignment
- ((- offset
) % alignment
);
233 pad
= (offset
+ pad
) % alignment
;
235 pad
= alignment
- pad
;
239 /* Sigh, find LCM (Least Common Multiple) for the two alignment factors. */
241 for (ua
= *updated_alignment
, ucnt
= 1;
243 ua
+= *updated_alignment
)
246 cnt
= ua
/ alignment
;
249 /* De-negatize offset, since % wouldn't do the expected thing. */
250 offset
= ua
- ((- offset
) % ua
);
252 /* Set to largest value. */
253 min_pad
= ~(ffetargetAlign
) 0;
255 /* Find all combinations of modulo values the two alignment requirements
256 have; pick the combination that results in the smallest padding
257 requirement. Of course, if a zero-pad requirement is encountered, just
260 for (um
= *updated_modulo
, i
= 0; i
< ucnt
; um
+= *updated_alignment
, ++i
)
262 for (m
= modulo
, j
= 0; j
< cnt
; m
+= alignment
, ++j
)
264 /* This code is similar to the "easy case" code above. */
269 pad
= (offset
+ pad
) % ua
;
272 /* A zero pad means we've got something useful. */
273 *updated_alignment
= ua
;
274 *updated_modulo
= um
;
279 { /* New minimum padding value. */
286 *updated_alignment
= ua
;
287 *updated_modulo
= min_m
;
291 /* Always append a null byte to the end, in case this is wanted in
292 a special case such as passing a string as a FORMAT or %REF.
293 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
294 because it isn't a "feature" that is self-documenting. Use the
295 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
298 #if FFETARGET_okCHARACTER1
300 ffetarget_character1 (ffetargetCharacter1
*val
, ffelexToken character
,
303 val
->length
= ffelex_token_length (character
);
304 if (val
->length
== 0)
308 val
->text
= malloc_new_kp (pool
, "ffetargetCharacter1", val
->length
+ 1);
309 memcpy (val
->text
, ffelex_token_text (character
), val
->length
);
310 val
->text
[val
->length
] = '\0';
317 /* Produce orderable comparison between two constants
319 Compare lengths, if equal then use memcmp. */
321 #if FFETARGET_okCHARACTER1
323 ffetarget_cmp_character1 (ffetargetCharacter1 l
, ffetargetCharacter1 r
)
325 if (l
.length
< r
.length
)
327 if (l
.length
> r
.length
)
331 return memcmp (l
.text
, r
.text
, l
.length
);
335 /* ffetarget_concatenate_character1 -- Perform CONCAT op on two constants
337 Always append a null byte to the end, in case this is wanted in
338 a special case such as passing a string as a FORMAT or %REF.
339 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
340 because it isn't a "feature" that is self-documenting. Use the
341 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
344 #if FFETARGET_okCHARACTER1
346 ffetarget_concatenate_character1 (ffetargetCharacter1
*res
,
347 ffetargetCharacter1 l
, ffetargetCharacter1 r
, mallocPool pool
,
348 ffetargetCharacterSize
*len
)
350 res
->length
= *len
= l
.length
+ r
.length
;
355 res
->text
= malloc_new_kp (pool
, "ffetargetCharacter1(CONCAT)", *len
+ 1);
357 memcpy (res
->text
, l
.text
, l
.length
);
359 memcpy (res
->text
+ l
.length
, r
.text
, r
.length
);
360 res
->text
[*len
] = '\0';
367 /* ffetarget_eq_character1 -- Perform relational comparison on char constants
369 Compare lengths, if equal then use memcmp. */
371 #if FFETARGET_okCHARACTER1
373 ffetarget_eq_character1 (bool *res
, ffetargetCharacter1 l
,
374 ffetargetCharacter1 r
)
376 assert (l
.length
== r
.length
);
377 *res
= (memcmp (l
.text
, r
.text
, l
.length
) == 0);
382 /* ffetarget_le_character1 -- Perform relational comparison on char constants
384 Compare lengths, if equal then use memcmp. */
386 #if FFETARGET_okCHARACTER1
388 ffetarget_le_character1 (bool *res
, ffetargetCharacter1 l
,
389 ffetargetCharacter1 r
)
391 assert (l
.length
== r
.length
);
392 *res
= (memcmp (l
.text
, r
.text
, l
.length
) <= 0);
397 /* ffetarget_lt_character1 -- Perform relational comparison on char constants
399 Compare lengths, if equal then use memcmp. */
401 #if FFETARGET_okCHARACTER1
403 ffetarget_lt_character1 (bool *res
, ffetargetCharacter1 l
,
404 ffetargetCharacter1 r
)
406 assert (l
.length
== r
.length
);
407 *res
= (memcmp (l
.text
, r
.text
, l
.length
) < 0);
412 /* ffetarget_ge_character1 -- Perform relational comparison on char constants
414 Compare lengths, if equal then use memcmp. */
416 #if FFETARGET_okCHARACTER1
418 ffetarget_ge_character1 (bool *res
, ffetargetCharacter1 l
,
419 ffetargetCharacter1 r
)
421 assert (l
.length
== r
.length
);
422 *res
= (memcmp (l
.text
, r
.text
, l
.length
) >= 0);
427 /* ffetarget_gt_character1 -- Perform relational comparison on char constants
429 Compare lengths, if equal then use memcmp. */
431 #if FFETARGET_okCHARACTER1
433 ffetarget_gt_character1 (bool *res
, ffetargetCharacter1 l
,
434 ffetargetCharacter1 r
)
436 assert (l
.length
== r
.length
);
437 *res
= (memcmp (l
.text
, r
.text
, l
.length
) > 0);
442 #if FFETARGET_okCHARACTER1
444 ffetarget_iszero_character1 (ffetargetCharacter1 constant
)
446 ffetargetCharacterSize i
;
448 for (i
= 0; i
< constant
.length
; ++i
)
449 if (constant
.text
[i
] != 0)
456 ffetarget_iszero_hollerith (ffetargetHollerith constant
)
458 ffetargetHollerithSize i
;
460 for (i
= 0; i
< constant
.length
; ++i
)
461 if (constant
.text
[i
] != 0)
466 /* ffetarget_layout -- Do storage requirement analysis for entity
468 Return the alignment/modulo requirements along with the size, given the
469 data type info and the number of elements an array (1 for a scalar). */
472 ffetarget_layout (const char *error_text UNUSED
, ffetargetAlign
*alignment
,
473 ffetargetAlign
*modulo
, ffetargetOffset
*size
,
474 ffeinfoBasictype bt
, ffeinfoKindtype kt
,
475 ffetargetCharacterSize charsize
,
476 ffetargetIntegerDefault num_elements
)
478 bool ok
; /* For character type. */
479 ffetargetOffset numele
; /* Converted from num_elements. */
482 type
= ffeinfo_type (bt
, kt
);
483 assert (type
!= NULL
);
485 *alignment
= ffetype_alignment (type
);
486 *modulo
= ffetype_modulo (type
);
487 if (bt
== FFEINFO_basictypeCHARACTER
)
489 ok
= ffetarget_offset_charsize (size
, charsize
, ffetype_size (type
));
490 #ifdef ffetarget_offset_overflow
492 ffetarget_offset_overflow (error_text
);
496 *size
= ffetype_size (type
);
498 if ((num_elements
< 0)
499 || !ffetarget_offset (&numele
, num_elements
)
500 || !ffetarget_offset_multiply (size
, *size
, numele
))
502 ffetarget_offset_overflow (error_text
);
509 /* ffetarget_ne_character1 -- Perform relational comparison on char constants
511 Compare lengths, if equal then use memcmp. */
513 #if FFETARGET_okCHARACTER1
515 ffetarget_ne_character1 (bool *res
, ffetargetCharacter1 l
,
516 ffetargetCharacter1 r
)
518 assert (l
.length
== r
.length
);
519 *res
= (memcmp (l
.text
, r
.text
, l
.length
) != 0);
524 /* ffetarget_substr_character1 -- Perform SUBSTR op on three constants
526 Always append a null byte to the end, in case this is wanted in
527 a special case such as passing a string as a FORMAT or %REF.
528 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
529 because it isn't a "feature" that is self-documenting. Use the
530 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
533 #if FFETARGET_okCHARACTER1
535 ffetarget_substr_character1 (ffetargetCharacter1
*res
,
536 ffetargetCharacter1 l
,
537 ffetargetCharacterSize first
,
538 ffetargetCharacterSize last
, mallocPool pool
,
539 ffetargetCharacterSize
*len
)
543 res
->length
= *len
= 0;
548 res
->length
= *len
= last
- first
+ 1;
549 res
->text
= malloc_new_kp (pool
, "ffetargetCharacter1(SUBSTR)", *len
+ 1);
550 memcpy (res
->text
, l
.text
+ first
- 1, *len
);
551 res
->text
[*len
] = '\0';
558 /* ffetarget_cmp_hollerith -- Produce orderable comparison between two
561 Compare lengths, if equal then use memcmp. */
564 ffetarget_cmp_hollerith (ffetargetHollerith l
, ffetargetHollerith r
)
566 if (l
.length
< r
.length
)
568 if (l
.length
> r
.length
)
570 return memcmp (l
.text
, r
.text
, l
.length
);
574 ffetarget_convert_any_character1_ (char *res
, size_t size
,
575 ffetargetCharacter1 l
)
577 if (size
<= (size_t) l
.length
)
580 ffetargetCharacterSize i
;
582 memcpy (res
, l
.text
, size
);
583 for (p
= &l
.text
[0] + size
, i
= l
.length
- size
;
587 return FFEBAD_TRUNCATING_CHARACTER
;
591 memcpy (res
, l
.text
, size
);
592 memset (res
+ l
.length
, ' ', size
- l
.length
);
599 ffetarget_convert_any_hollerith_ (char *res
, size_t size
,
600 ffetargetHollerith l
)
602 if (size
<= (size_t) l
.length
)
605 ffetargetCharacterSize i
;
607 memcpy (res
, l
.text
, size
);
608 for (p
= &l
.text
[0] + size
, i
= l
.length
- size
;
612 return FFEBAD_TRUNCATING_HOLLERITH
;
616 memcpy (res
, l
.text
, size
);
617 memset (res
+ l
.length
, ' ', size
- l
.length
);
624 ffetarget_convert_any_typeless_ (char *res
, size_t size
,
627 unsigned long long int l1
;
628 unsigned long int l2
;
630 unsigned short int l4
;
635 if (size
>= sizeof (l1
))
639 size_of
= sizeof (l1
);
641 else if (size
>= sizeof (l2
))
645 size_of
= sizeof (l2
);
648 else if (size
>= sizeof (l3
))
652 size_of
= sizeof (l3
);
655 else if (size
>= sizeof (l4
))
659 size_of
= sizeof (l4
);
662 else if (size
>= sizeof (l5
))
666 size_of
= sizeof (l5
);
671 assert ("stumped by conversion from typeless!" == NULL
);
677 int i
= size_of
- size
;
679 memcpy (res
, p
+ i
, size
);
680 for (; i
> 0; ++p
, --i
)
682 return FFEBAD_TRUNCATING_TYPELESS
;
686 int i
= size
- size_of
;
689 memcpy (res
+ i
, p
, size_of
);
693 return FFEBAD_TRUNCATING_TYPELESS
;
697 /* Always append a null byte to the end, in case this is wanted in
698 a special case such as passing a string as a FORMAT or %REF.
699 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
700 because it isn't a "feature" that is self-documenting. Use the
701 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
704 #if FFETARGET_okCHARACTER1
706 ffetarget_convert_character1_character1 (ffetargetCharacter1
*res
,
707 ffetargetCharacterSize size
,
708 ffetargetCharacter1 l
,
716 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
+ 1);
717 if (size
<= l
.length
)
718 memcpy (res
->text
, l
.text
, size
);
721 memcpy (res
->text
, l
.text
, l
.length
);
722 memset (res
->text
+ l
.length
, ' ', size
- l
.length
);
724 res
->text
[size
] = '\0';
732 /* Always append a null byte to the end, in case this is wanted in
733 a special case such as passing a string as a FORMAT or %REF.
734 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
735 because it isn't a "feature" that is self-documenting. Use the
736 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
739 #if FFETARGET_okCHARACTER1
741 ffetarget_convert_character1_hollerith (ffetargetCharacter1
*res
,
742 ffetargetCharacterSize size
,
743 ffetargetHollerith l
, mallocPool pool
)
750 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
+ 1);
751 res
->text
[size
] = '\0';
752 if (size
<= l
.length
)
755 ffetargetCharacterSize i
;
757 memcpy (res
->text
, l
.text
, size
);
758 for (p
= &l
.text
[0] + size
, i
= l
.length
- size
;
762 return FFEBAD_TRUNCATING_HOLLERITH
;
766 memcpy (res
->text
, l
.text
, l
.length
);
767 memset (res
->text
+ l
.length
, ' ', size
- l
.length
);
775 /* ffetarget_convert_character1_integer4 -- Raw conversion.
777 Always append a null byte to the end, in case this is wanted in
778 a special case such as passing a string as a FORMAT or %REF.
779 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
780 because it isn't a "feature" that is self-documenting. Use the
781 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
784 #if FFETARGET_okCHARACTER1
786 ffetarget_convert_character1_integer4 (ffetargetCharacter1
*res
,
787 ffetargetCharacterSize size
,
788 ffetargetInteger4 l
, mallocPool pool
)
798 if (((size_t) size
) >= sizeof (l1
))
802 size_of
= sizeof (l1
);
804 else if (((size_t) size
) >= sizeof (l2
))
808 size_of
= sizeof (l2
);
811 else if (((size_t) size
) >= sizeof (l3
))
815 size_of
= sizeof (l3
);
818 else if (((size_t) size
) >= sizeof (l4
))
822 size_of
= sizeof (l4
);
825 else if (((size_t) size
) >= sizeof (l5
))
829 size_of
= sizeof (l5
);
834 assert ("stumped by conversion from integer1!" == NULL
);
843 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
+ 1);
844 res
->text
[size
] = '\0';
845 if (((size_t) size
) <= size_of
)
847 int i
= size_of
- size
;
849 memcpy (res
->text
, p
+ i
, size
);
850 for (; i
> 0; ++p
, --i
)
852 return FFEBAD_TRUNCATING_NUMERIC
;
856 int i
= size
- size_of
;
858 memset (res
->text
, 0, i
);
859 memcpy (res
->text
+ i
, p
, size_of
);
864 return FFEBAD_TRUNCATING_NUMERIC
;
869 /* ffetarget_convert_character1_logical4 -- Raw conversion.
871 Always append a null byte to the end, in case this is wanted in
872 a special case such as passing a string as a FORMAT or %REF.
873 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
874 because it isn't a "feature" that is self-documenting. Use the
875 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
878 #if FFETARGET_okCHARACTER1
880 ffetarget_convert_character1_logical4 (ffetargetCharacter1
*res
,
881 ffetargetCharacterSize size
,
882 ffetargetLogical4 l
, mallocPool pool
)
892 if (((size_t) size
) >= sizeof (l1
))
896 size_of
= sizeof (l1
);
898 else if (((size_t) size
) >= sizeof (l2
))
902 size_of
= sizeof (l2
);
905 else if (((size_t) size
) >= sizeof (l3
))
909 size_of
= sizeof (l3
);
912 else if (((size_t) size
) >= sizeof (l4
))
916 size_of
= sizeof (l4
);
919 else if (((size_t) size
) >= sizeof (l5
))
923 size_of
= sizeof (l5
);
928 assert ("stumped by conversion from logical1!" == NULL
);
937 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
+ 1);
938 res
->text
[size
] = '\0';
939 if (((size_t) size
) <= size_of
)
941 int i
= size_of
- size
;
943 memcpy (res
->text
, p
+ i
, size
);
944 for (; i
> 0; ++p
, --i
)
946 return FFEBAD_TRUNCATING_NUMERIC
;
950 int i
= size
- size_of
;
952 memset (res
->text
, 0, i
);
953 memcpy (res
->text
+ i
, p
, size_of
);
958 return FFEBAD_TRUNCATING_NUMERIC
;
963 /* ffetarget_convert_character1_typeless -- Raw conversion.
965 Always append a null byte to the end, in case this is wanted in
966 a special case such as passing a string as a FORMAT or %REF.
967 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
968 because it isn't a "feature" that is self-documenting. Use the
969 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
972 #if FFETARGET_okCHARACTER1
974 ffetarget_convert_character1_typeless (ffetargetCharacter1
*res
,
975 ffetargetCharacterSize size
,
976 ffetargetTypeless l
, mallocPool pool
)
978 unsigned long long int l1
;
979 unsigned long int l2
;
981 unsigned short int l4
;
986 if (((size_t) size
) >= sizeof (l1
))
990 size_of
= sizeof (l1
);
992 else if (((size_t) size
) >= sizeof (l2
))
996 size_of
= sizeof (l2
);
999 else if (((size_t) size
) >= sizeof (l3
))
1003 size_of
= sizeof (l3
);
1006 else if (((size_t) size
) >= sizeof (l4
))
1010 size_of
= sizeof (l4
);
1013 else if (((size_t) size
) >= sizeof (l5
))
1017 size_of
= sizeof (l5
);
1022 assert ("stumped by conversion from typeless!" == NULL
);
1031 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
+ 1);
1032 res
->text
[size
] = '\0';
1033 if (((size_t) size
) <= size_of
)
1035 int i
= size_of
- size
;
1037 memcpy (res
->text
, p
+ i
, size
);
1038 for (; i
> 0; ++p
, --i
)
1040 return FFEBAD_TRUNCATING_TYPELESS
;
1044 int i
= size
- size_of
;
1046 memset (res
->text
, 0, i
);
1047 memcpy (res
->text
+ i
, p
, size_of
);
1052 return FFEBAD_TRUNCATING_TYPELESS
;
1057 /* ffetarget_divide_complex1 -- Divide function
1061 #if FFETARGET_okCOMPLEX1
1063 ffetarget_divide_complex1 (ffetargetComplex1
*res
, ffetargetComplex1 l
,
1064 ffetargetComplex1 r
)
1067 ffetargetReal1 tmp1
, tmp2
, tmp3
, tmp4
;
1069 bad
= ffetarget_multiply_real1 (&tmp1
, r
.real
, r
.real
);
1072 bad
= ffetarget_multiply_real1 (&tmp2
, r
.imaginary
, r
.imaginary
);
1075 bad
= ffetarget_add_real1 (&tmp3
, tmp1
, tmp2
);
1079 if (ffetarget_iszero_real1 (tmp3
))
1081 ffetarget_real1_zero (&(res
)->real
);
1082 ffetarget_real1_zero (&(res
)->imaginary
);
1083 return FFEBAD_DIV_BY_ZERO
;
1086 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, r
.real
);
1089 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, r
.imaginary
);
1092 bad
= ffetarget_add_real1 (&tmp4
, tmp1
, tmp2
);
1095 bad
= ffetarget_divide_real1 (&res
->real
, tmp4
, tmp3
);
1099 bad
= ffetarget_multiply_real1 (&tmp1
, r
.real
, l
.imaginary
);
1102 bad
= ffetarget_multiply_real1 (&tmp2
, l
.real
, r
.imaginary
);
1105 bad
= ffetarget_subtract_real1 (&tmp4
, tmp1
, tmp2
);
1108 bad
= ffetarget_divide_real1 (&res
->imaginary
, tmp4
, tmp3
);
1114 /* ffetarget_divide_complex2 -- Divide function
1118 #if FFETARGET_okCOMPLEX2
1120 ffetarget_divide_complex2 (ffetargetComplex2
*res
, ffetargetComplex2 l
,
1121 ffetargetComplex2 r
)
1124 ffetargetReal2 tmp1
, tmp2
, tmp3
, tmp4
;
1126 bad
= ffetarget_multiply_real2 (&tmp1
, r
.real
, r
.real
);
1129 bad
= ffetarget_multiply_real2 (&tmp2
, r
.imaginary
, r
.imaginary
);
1132 bad
= ffetarget_add_real2 (&tmp3
, tmp1
, tmp2
);
1136 if (ffetarget_iszero_real2 (tmp3
))
1138 ffetarget_real2_zero (&(res
)->real
);
1139 ffetarget_real2_zero (&(res
)->imaginary
);
1140 return FFEBAD_DIV_BY_ZERO
;
1143 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, r
.real
);
1146 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, r
.imaginary
);
1149 bad
= ffetarget_add_real2 (&tmp4
, tmp1
, tmp2
);
1152 bad
= ffetarget_divide_real2 (&res
->real
, tmp4
, tmp3
);
1156 bad
= ffetarget_multiply_real2 (&tmp1
, r
.real
, l
.imaginary
);
1159 bad
= ffetarget_multiply_real2 (&tmp2
, l
.real
, r
.imaginary
);
1162 bad
= ffetarget_subtract_real2 (&tmp4
, tmp1
, tmp2
);
1165 bad
= ffetarget_divide_real2 (&res
->imaginary
, tmp4
, tmp3
);
1171 /* ffetarget_hollerith -- Convert token to a hollerith constant
1173 Always append a null byte to the end, in case this is wanted in
1174 a special case such as passing a string as a FORMAT or %REF.
1175 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
1176 because it isn't a "feature" that is self-documenting. Use the
1177 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
1181 ffetarget_hollerith (ffetargetHollerith
*val
, ffelexToken integer
,
1184 val
->length
= ffelex_token_length (integer
);
1185 val
->text
= malloc_new_kp (pool
, "ffetargetHollerith", val
->length
+ 1);
1186 memcpy (val
->text
, ffelex_token_text (integer
), val
->length
);
1187 val
->text
[val
->length
] = '\0';
1192 /* ffetarget_integer_bad_magical -- Complain about a magical number
1194 Just calls ffebad with the arguments. */
1197 ffetarget_integer_bad_magical (ffelexToken t
)
1199 ffebad_start (FFEBAD_BAD_MAGICAL
);
1200 ffebad_here (0, ffelex_token_where_line (t
), ffelex_token_where_column (t
));
1204 /* ffetarget_integer_bad_magical_binary -- Complain about a magical number
1206 Just calls ffebad with the arguments. */
1209 ffetarget_integer_bad_magical_binary (ffelexToken integer
,
1212 ffebad_start (FFEBAD_BAD_MAGICAL_BINARY
);
1213 ffebad_here (0, ffelex_token_where_line (integer
),
1214 ffelex_token_where_column (integer
));
1215 ffebad_here (1, ffelex_token_where_line (minus
),
1216 ffelex_token_where_column (minus
));
1220 /* ffetarget_integer_bad_magical_precedence -- Complain about a magical
1223 Just calls ffebad with the arguments. */
1226 ffetarget_integer_bad_magical_precedence (ffelexToken integer
,
1228 ffelexToken higher_op
)
1230 ffebad_start (FFEBAD_BAD_MAGICAL_PRECEDENCE
);
1231 ffebad_here (0, ffelex_token_where_line (integer
),
1232 ffelex_token_where_column (integer
));
1233 ffebad_here (1, ffelex_token_where_line (uminus
),
1234 ffelex_token_where_column (uminus
));
1235 ffebad_here (2, ffelex_token_where_line (higher_op
),
1236 ffelex_token_where_column (higher_op
));
1240 /* ffetarget_integer_bad_magical_precedence_binary -- Complain...
1242 Just calls ffebad with the arguments. */
1245 ffetarget_integer_bad_magical_precedence_binary (ffelexToken integer
,
1247 ffelexToken higher_op
)
1249 ffebad_start (FFEBAD_BAD_MAGICAL_PRECEDENCE_BINARY
);
1250 ffebad_here (0, ffelex_token_where_line (integer
),
1251 ffelex_token_where_column (integer
));
1252 ffebad_here (1, ffelex_token_where_line (minus
),
1253 ffelex_token_where_column (minus
));
1254 ffebad_here (2, ffelex_token_where_line (higher_op
),
1255 ffelex_token_where_column (higher_op
));
1259 /* ffetarget_integer1 -- Convert token to an integer
1263 Token use count not affected overall. */
1265 #if FFETARGET_okINTEGER1
1267 ffetarget_integer1 (ffetargetInteger1
*val
, ffelexToken integer
)
1269 ffetargetInteger1 x
;
1273 assert (ffelex_token_type (integer
) == FFELEX_typeNUMBER
);
1275 p
= ffelex_token_text (integer
);
1278 /* Skip past leading zeros. */
1280 while (((c
= *p
) != '\0') && (c
== '0'))
1283 /* Interpret rest of number. */
1287 if ((x
== FFETARGET_integerALMOST_BIG_MAGICAL
)
1288 && (c
== '0' + FFETARGET_integerFINISH_BIG_MAGICAL
)
1289 && (*(p
+ 1) == '\0'))
1291 *val
= (ffetargetInteger1
) FFETARGET_integerBIG_MAGICAL
;
1294 else if (x
== FFETARGET_integerALMOST_BIG_MAGICAL
)
1296 if ((c
> '0' + FFETARGET_integerFINISH_BIG_MAGICAL
)
1297 || (*(p
+ 1) != '\0'))
1299 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1300 ffebad_here (0, ffelex_token_where_line (integer
),
1301 ffelex_token_where_column (integer
));
1307 else if (x
> FFETARGET_integerALMOST_BIG_MAGICAL
)
1309 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1310 ffebad_here (0, ffelex_token_where_line (integer
),
1311 ffelex_token_where_column (integer
));
1316 x
= x
* 10 + c
- '0';
1325 /* ffetarget_integerbinary -- Convert token to a binary integer
1327 ffetarget_integerbinary x;
1328 if (ffetarget_integerdefault_8(&x,integer_token))
1331 Token use count not affected overall. */
1334 ffetarget_integerbinary (ffetargetIntegerDefault
*val
, ffelexToken integer
)
1336 ffetargetIntegerDefault x
;
1341 assert ((ffelex_token_type (integer
) == FFELEX_typeNAME
)
1342 || (ffelex_token_type (integer
) == FFELEX_typeNUMBER
));
1344 p
= ffelex_token_text (integer
);
1347 /* Skip past leading zeros. */
1349 while (((c
= *p
) != '\0') && (c
== '0'))
1352 /* Interpret rest of number. */
1357 if ((c
>= '0') && (c
<= '1'))
1365 #if 0 /* Don't complain about signed overflow; just
1366 unsigned overflow. */
1367 if ((x
== FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY
)
1368 && (c
== FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY
)
1369 && (*(p
+ 1) == '\0'))
1371 *val
= FFETARGET_integerBIG_OVERFLOW_BINARY
;
1376 #if FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY == 0
1377 if ((x
& FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY
) != 0)
1379 if (x
== FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY
)
1381 if ((c
> FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY
)
1382 || (*(p
+ 1) != '\0'))
1384 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1385 ffebad_here (0, ffelex_token_where_line (integer
),
1386 ffelex_token_where_column (integer
));
1392 else if (x
> FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY
)
1395 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1396 ffebad_here (0, ffelex_token_where_line (integer
),
1397 ffelex_token_where_column (integer
));
1408 ffebad_start (FFEBAD_INVALID_BINARY_DIGIT
);
1409 ffebad_here (0, ffelex_token_where_line (integer
),
1410 ffelex_token_where_column (integer
));
1418 /* ffetarget_integerhex -- Convert token to a hex integer
1420 ffetarget_integerhex x;
1421 if (ffetarget_integerdefault_8(&x,integer_token))
1424 Token use count not affected overall. */
1427 ffetarget_integerhex (ffetargetIntegerDefault
*val
, ffelexToken integer
)
1429 ffetargetIntegerDefault x
;
1434 assert ((ffelex_token_type (integer
) == FFELEX_typeNAME
)
1435 || (ffelex_token_type (integer
) == FFELEX_typeNUMBER
));
1437 p
= ffelex_token_text (integer
);
1440 /* Skip past leading zeros. */
1442 while (((c
= *p
) != '\0') && (c
== '0'))
1445 /* Interpret rest of number. */
1450 if ((c
>= 'A') && (c
<= 'F'))
1452 else if ((c
>= 'a') && (c
<= 'f'))
1454 else if ((c
>= '0') && (c
<= '9'))
1462 #if 0 /* Don't complain about signed overflow; just
1463 unsigned overflow. */
1464 if ((x
== FFETARGET_integerALMOST_BIG_OVERFLOW_HEX
)
1465 && (c
== FFETARGET_integerFINISH_BIG_OVERFLOW_HEX
)
1466 && (*(p
+ 1) == '\0'))
1468 *val
= FFETARGET_integerBIG_OVERFLOW_HEX
;
1473 #if FFETARGET_integerFINISH_BIG_OVERFLOW_HEX == 0
1474 if (x
>= FFETARGET_integerALMOST_BIG_OVERFLOW_HEX
)
1476 if (x
== FFETARGET_integerALMOST_BIG_OVERFLOW_HEX
)
1478 if ((c
> FFETARGET_integerFINISH_BIG_OVERFLOW_HEX
)
1479 || (*(p
+ 1) != '\0'))
1481 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1482 ffebad_here (0, ffelex_token_where_line (integer
),
1483 ffelex_token_where_column (integer
));
1489 else if (x
> FFETARGET_integerALMOST_BIG_OVERFLOW_HEX
)
1492 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1493 ffebad_here (0, ffelex_token_where_line (integer
),
1494 ffelex_token_where_column (integer
));
1505 ffebad_start (FFEBAD_INVALID_HEX_DIGIT
);
1506 ffebad_here (0, ffelex_token_where_line (integer
),
1507 ffelex_token_where_column (integer
));
1515 /* ffetarget_integeroctal -- Convert token to an octal integer
1517 ffetarget_integeroctal x;
1518 if (ffetarget_integerdefault_8(&x,integer_token))
1521 Token use count not affected overall. */
1524 ffetarget_integeroctal (ffetargetIntegerDefault
*val
, ffelexToken integer
)
1526 ffetargetIntegerDefault x
;
1531 assert ((ffelex_token_type (integer
) == FFELEX_typeNAME
)
1532 || (ffelex_token_type (integer
) == FFELEX_typeNUMBER
));
1534 p
= ffelex_token_text (integer
);
1537 /* Skip past leading zeros. */
1539 while (((c
= *p
) != '\0') && (c
== '0'))
1542 /* Interpret rest of number. */
1547 if ((c
>= '0') && (c
<= '7'))
1555 #if 0 /* Don't complain about signed overflow; just
1556 unsigned overflow. */
1557 if ((x
== FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL
)
1558 && (c
== FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL
)
1559 && (*(p
+ 1) == '\0'))
1561 *val
= FFETARGET_integerBIG_OVERFLOW_OCTAL
;
1566 #if FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL == 0
1567 if (x
>= FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL
)
1569 if (x
== FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL
)
1571 if ((c
> FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL
)
1572 || (*(p
+ 1) != '\0'))
1574 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1575 ffebad_here (0, ffelex_token_where_line (integer
),
1576 ffelex_token_where_column (integer
));
1582 else if (x
> FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL
)
1585 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1586 ffebad_here (0, ffelex_token_where_line (integer
),
1587 ffelex_token_where_column (integer
));
1598 ffebad_start (FFEBAD_INVALID_OCTAL_DIGIT
);
1599 ffebad_here (0, ffelex_token_where_line (integer
),
1600 ffelex_token_where_column (integer
));
1608 /* ffetarget_multiply_complex1 -- Multiply function
1612 #if FFETARGET_okCOMPLEX1
1614 ffetarget_multiply_complex1 (ffetargetComplex1
*res
, ffetargetComplex1 l
,
1615 ffetargetComplex1 r
)
1618 ffetargetReal1 tmp1
, tmp2
;
1620 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, r
.real
);
1623 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, r
.imaginary
);
1626 bad
= ffetarget_subtract_real1 (&res
->real
, tmp1
, tmp2
);
1629 bad
= ffetarget_multiply_real1 (&tmp1
, l
.imaginary
, r
.real
);
1632 bad
= ffetarget_multiply_real1 (&tmp2
, l
.real
, r
.imaginary
);
1635 bad
= ffetarget_add_real1 (&res
->imaginary
, tmp1
, tmp2
);
1641 /* ffetarget_multiply_complex2 -- Multiply function
1645 #if FFETARGET_okCOMPLEX2
1647 ffetarget_multiply_complex2 (ffetargetComplex2
*res
, ffetargetComplex2 l
,
1648 ffetargetComplex2 r
)
1651 ffetargetReal2 tmp1
, tmp2
;
1653 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, r
.real
);
1656 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, r
.imaginary
);
1659 bad
= ffetarget_subtract_real2 (&res
->real
, tmp1
, tmp2
);
1662 bad
= ffetarget_multiply_real2 (&tmp1
, l
.imaginary
, r
.real
);
1665 bad
= ffetarget_multiply_real2 (&tmp2
, l
.real
, r
.imaginary
);
1668 bad
= ffetarget_add_real2 (&res
->imaginary
, tmp1
, tmp2
);
1674 /* ffetarget_power_complexdefault_integerdefault -- Power function
1679 ffetarget_power_complexdefault_integerdefault (ffetargetComplexDefault
*res
,
1680 ffetargetComplexDefault l
,
1681 ffetargetIntegerDefault r
)
1684 ffetargetRealDefault tmp
;
1685 ffetargetRealDefault tmp1
;
1686 ffetargetRealDefault tmp2
;
1687 ffetargetRealDefault two
;
1689 if (ffetarget_iszero_real1 (l
.real
)
1690 && ffetarget_iszero_real1 (l
.imaginary
))
1692 ffetarget_real1_zero (&res
->real
);
1693 ffetarget_real1_zero (&res
->imaginary
);
1699 ffetarget_real1_one (&res
->real
);
1700 ffetarget_real1_zero (&res
->imaginary
);
1707 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, l
.real
);
1710 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, l
.imaginary
);
1713 bad
= ffetarget_add_real1 (&tmp
, tmp1
, tmp2
);
1716 bad
= ffetarget_divide_real1 (&l
.real
, l
.real
, tmp
);
1719 bad
= ffetarget_divide_real1 (&l
.imaginary
, l
.imaginary
, tmp
);
1722 bad
= ffetarget_uminus_real1 (&l
.imaginary
, l
.imaginary
);
1727 ffetarget_real1_two (&two
);
1729 while ((r
& 1) == 0)
1731 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, l
.real
);
1734 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, l
.imaginary
);
1737 bad
= ffetarget_subtract_real1 (&tmp
, tmp1
, tmp2
);
1740 bad
= ffetarget_multiply_real1 (&l
.imaginary
, l
.real
, l
.imaginary
);
1743 bad
= ffetarget_multiply_real1 (&l
.imaginary
, l
.imaginary
, two
);
1755 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, l
.real
);
1758 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, l
.imaginary
);
1761 bad
= ffetarget_subtract_real1 (&tmp
, tmp1
, tmp2
);
1764 bad
= ffetarget_multiply_real1 (&l
.imaginary
, l
.real
, l
.imaginary
);
1767 bad
= ffetarget_multiply_real1 (&l
.imaginary
, l
.imaginary
, two
);
1773 bad
= ffetarget_multiply_real1 (&tmp1
, res
->real
, l
.real
);
1776 bad
= ffetarget_multiply_real1 (&tmp2
, res
->imaginary
,
1780 bad
= ffetarget_subtract_real1 (&tmp
, tmp1
, tmp2
);
1783 bad
= ffetarget_multiply_real1 (&tmp1
, res
->imaginary
, l
.real
);
1786 bad
= ffetarget_multiply_real1 (&tmp2
, res
->real
, l
.imaginary
);
1789 bad
= ffetarget_add_real1 (&res
->imaginary
, tmp1
, tmp2
);
1800 /* ffetarget_power_complexdouble_integerdefault -- Power function
1804 #if FFETARGET_okCOMPLEXDOUBLE
1806 ffetarget_power_complexdouble_integerdefault (ffetargetComplexDouble
*res
,
1807 ffetargetComplexDouble l
, ffetargetIntegerDefault r
)
1810 ffetargetRealDouble tmp
;
1811 ffetargetRealDouble tmp1
;
1812 ffetargetRealDouble tmp2
;
1813 ffetargetRealDouble two
;
1815 if (ffetarget_iszero_real2 (l
.real
)
1816 && ffetarget_iszero_real2 (l
.imaginary
))
1818 ffetarget_real2_zero (&res
->real
);
1819 ffetarget_real2_zero (&res
->imaginary
);
1825 ffetarget_real2_one (&res
->real
);
1826 ffetarget_real2_zero (&res
->imaginary
);
1833 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, l
.real
);
1836 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, l
.imaginary
);
1839 bad
= ffetarget_add_real2 (&tmp
, tmp1
, tmp2
);
1842 bad
= ffetarget_divide_real2 (&l
.real
, l
.real
, tmp
);
1845 bad
= ffetarget_divide_real2 (&l
.imaginary
, l
.imaginary
, tmp
);
1848 bad
= ffetarget_uminus_real2 (&l
.imaginary
, l
.imaginary
);
1853 ffetarget_real2_two (&two
);
1855 while ((r
& 1) == 0)
1857 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, l
.real
);
1860 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, l
.imaginary
);
1863 bad
= ffetarget_subtract_real2 (&tmp
, tmp1
, tmp2
);
1866 bad
= ffetarget_multiply_real2 (&l
.imaginary
, l
.real
, l
.imaginary
);
1869 bad
= ffetarget_multiply_real2 (&l
.imaginary
, l
.imaginary
, two
);
1881 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, l
.real
);
1884 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, l
.imaginary
);
1887 bad
= ffetarget_subtract_real2 (&tmp
, tmp1
, tmp2
);
1890 bad
= ffetarget_multiply_real2 (&l
.imaginary
, l
.real
, l
.imaginary
);
1893 bad
= ffetarget_multiply_real2 (&l
.imaginary
, l
.imaginary
, two
);
1899 bad
= ffetarget_multiply_real2 (&tmp1
, res
->real
, l
.real
);
1902 bad
= ffetarget_multiply_real2 (&tmp2
, res
->imaginary
,
1906 bad
= ffetarget_subtract_real2 (&tmp
, tmp1
, tmp2
);
1909 bad
= ffetarget_multiply_real2 (&tmp1
, res
->imaginary
, l
.real
);
1912 bad
= ffetarget_multiply_real2 (&tmp2
, res
->real
, l
.imaginary
);
1915 bad
= ffetarget_add_real2 (&res
->imaginary
, tmp1
, tmp2
);
1927 /* ffetarget_power_integerdefault_integerdefault -- Power function
1932 ffetarget_power_integerdefault_integerdefault (ffetargetIntegerDefault
*res
,
1933 ffetargetIntegerDefault l
, ffetargetIntegerDefault r
)
1954 *res
= ((-r
) & 1) == 0 ? 1 : -1;
1960 while ((r
& 1) == 0)
1980 /* ffetarget_power_realdefault_integerdefault -- Power function
1985 ffetarget_power_realdefault_integerdefault (ffetargetRealDefault
*res
,
1986 ffetargetRealDefault l
, ffetargetIntegerDefault r
)
1990 if (ffetarget_iszero_real1 (l
))
1992 ffetarget_real1_zero (res
);
1998 ffetarget_real1_one (res
);
2004 ffetargetRealDefault one
;
2006 ffetarget_real1_one (&one
);
2008 bad
= ffetarget_divide_real1 (&l
, one
, l
);
2013 while ((r
& 1) == 0)
2015 bad
= ffetarget_multiply_real1 (&l
, l
, l
);
2026 bad
= ffetarget_multiply_real1 (&l
, l
, l
);
2031 bad
= ffetarget_multiply_real1 (res
, *res
, l
);
2041 /* ffetarget_power_realdouble_integerdefault -- Power function
2046 ffetarget_power_realdouble_integerdefault (ffetargetRealDouble
*res
,
2047 ffetargetRealDouble l
,
2048 ffetargetIntegerDefault r
)
2052 if (ffetarget_iszero_real2 (l
))
2054 ffetarget_real2_zero (res
);
2060 ffetarget_real2_one (res
);
2066 ffetargetRealDouble one
;
2068 ffetarget_real2_one (&one
);
2070 bad
= ffetarget_divide_real2 (&l
, one
, l
);
2075 while ((r
& 1) == 0)
2077 bad
= ffetarget_multiply_real2 (&l
, l
, l
);
2088 bad
= ffetarget_multiply_real2 (&l
, l
, l
);
2093 bad
= ffetarget_multiply_real2 (res
, *res
, l
);
2103 /* ffetarget_print_binary -- Output typeless binary integer
2105 ffetargetTypeless val;
2106 ffetarget_typeless_binary(dmpout,val); */
2109 ffetarget_print_binary (FILE *f
, ffetargetTypeless value
)
2112 char digits
[sizeof (value
) * CHAR_BIT
+ 1];
2117 p
= &digits
[ARRAY_SIZE (digits
) - 1];
2121 *--p
= (value
& 1) + '0';
2123 } while (value
== 0);
2128 /* ffetarget_print_character1 -- Output character string
2130 ffetargetCharacter1 val;
2131 ffetarget_print_character1(dmpout,val); */
2134 ffetarget_print_character1 (FILE *f
, ffetargetCharacter1 value
)
2137 ffetargetCharacterSize i
;
2139 fputc ('\'', dmpout
);
2140 for (i
= 0, p
= value
.text
; i
< value
.length
; ++i
, ++p
)
2141 ffetarget_print_char_ (f
, *p
);
2142 fputc ('\'', dmpout
);
2145 /* ffetarget_print_hollerith -- Output hollerith string
2147 ffetargetHollerith val;
2148 ffetarget_print_hollerith(dmpout,val); */
2151 ffetarget_print_hollerith (FILE *f
, ffetargetHollerith value
)
2154 ffetargetHollerithSize i
;
2156 fputc ('\'', dmpout
);
2157 for (i
= 0, p
= value
.text
; i
< value
.length
; ++i
, ++p
)
2158 ffetarget_print_char_ (f
, *p
);
2159 fputc ('\'', dmpout
);
2162 /* ffetarget_print_octal -- Output typeless octal integer
2164 ffetargetTypeless val;
2165 ffetarget_print_octal(dmpout,val); */
2168 ffetarget_print_octal (FILE *f
, ffetargetTypeless value
)
2171 char digits
[sizeof (value
) * CHAR_BIT
/ 3 + 1];
2176 p
= &digits
[ARRAY_SIZE (digits
) - 3];
2180 *--p
= (value
& 3) + '0';
2182 } while (value
== 0);
2187 /* ffetarget_print_hex -- Output typeless hex integer
2189 ffetargetTypeless val;
2190 ffetarget_print_hex(dmpout,val); */
2193 ffetarget_print_hex (FILE *f
, ffetargetTypeless value
)
2196 char digits
[sizeof (value
) * CHAR_BIT
/ 4 + 1];
2197 static char hexdigits
[16] = "0123456789ABCDEF";
2202 p
= &digits
[ARRAY_SIZE (digits
) - 3];
2206 *--p
= hexdigits
[value
& 4];
2208 } while (value
== 0);
2213 /* ffetarget_real1 -- Convert token to a single-precision real number
2217 Pass NULL for any token not provided by the user, but a valid Fortran
2218 real number must be provided somehow. For example, it is ok for
2219 exponent_sign_token and exponent_digits_token to be NULL as long as
2220 exponent_token not only starts with "E" or "e" but also contains at least
2221 one digit following it. Token use counts not affected overall. */
2223 #if FFETARGET_okREAL1
2225 ffetarget_real1 (ffetargetReal1
*value
, ffelexToken integer
,
2226 ffelexToken decimal
, ffelexToken fraction
,
2227 ffelexToken exponent
, ffelexToken exponent_sign
,
2228 ffelexToken exponent_digits
)
2230 size_t sz
= 1; /* Allow room for '\0' byte at end. */
2231 char *ptr
= &ffetarget_string_
[0];
2235 #define dotok(x) if (x != NULL) ++sz;
2236 #define dotoktxt(x) if (x != NULL) sz += ffelex_token_length(x)
2240 dotoktxt (fraction
);
2241 dotoktxt (exponent
);
2242 dotok (exponent_sign
);
2243 dotoktxt (exponent_digits
);
2248 if (sz
> ARRAY_SIZE (ffetarget_string_
))
2249 p
= ptr
= (char *) malloc_new_ks (malloc_pool_image (), "ffetarget_real1",
2252 #define dotoktxt(x) if (x != NULL) \
2254 for (q = ffelex_token_text(x); *q != '\0'; ++q) \
2260 if (decimal
!= NULL
)
2263 dotoktxt (fraction
);
2264 dotoktxt (exponent
);
2266 if (exponent_sign
!= NULL
)
2268 if (ffelex_token_type (exponent_sign
) == FFELEX_typePLUS
)
2272 assert (ffelex_token_type (exponent_sign
) == FFELEX_typeMINUS
);
2277 dotoktxt (exponent_digits
);
2283 ffetarget_make_real1 (value
,
2284 FFETARGET_ATOF_ (ptr
,
2287 if (sz
> ARRAY_SIZE (ffetarget_string_
))
2288 malloc_kill_ks (malloc_pool_image (), ptr
, sz
);
2294 /* ffetarget_real2 -- Convert token to a single-precision real number
2298 Pass NULL for any token not provided by the user, but a valid Fortran
2299 real number must be provided somehow. For example, it is ok for
2300 exponent_sign_token and exponent_digits_token to be NULL as long as
2301 exponent_token not only starts with "E" or "e" but also contains at least
2302 one digit following it. Token use counts not affected overall. */
2304 #if FFETARGET_okREAL2
2306 ffetarget_real2 (ffetargetReal2
*value
, ffelexToken integer
,
2307 ffelexToken decimal
, ffelexToken fraction
,
2308 ffelexToken exponent
, ffelexToken exponent_sign
,
2309 ffelexToken exponent_digits
)
2311 size_t sz
= 1; /* Allow room for '\0' byte at end. */
2312 char *ptr
= &ffetarget_string_
[0];
2316 #define dotok(x) if (x != NULL) ++sz;
2317 #define dotoktxt(x) if (x != NULL) sz += ffelex_token_length(x)
2321 dotoktxt (fraction
);
2322 dotoktxt (exponent
);
2323 dotok (exponent_sign
);
2324 dotoktxt (exponent_digits
);
2329 if (sz
> ARRAY_SIZE (ffetarget_string_
))
2330 p
= ptr
= (char *) malloc_new_ks (malloc_pool_image (), "ffetarget_real1", sz
);
2332 #define dotoktxt(x) if (x != NULL) \
2334 for (q = ffelex_token_text(x); *q != '\0'; ++q) \
2337 #define dotoktxtexp(x) if (x != NULL) \
2340 for (q = ffelex_token_text(x) + 1; *q != '\0'; ++q) \
2346 if (decimal
!= NULL
)
2349 dotoktxt (fraction
);
2350 dotoktxtexp (exponent
);
2352 if (exponent_sign
!= NULL
)
2354 if (ffelex_token_type (exponent_sign
) == FFELEX_typePLUS
)
2358 assert (ffelex_token_type (exponent_sign
) == FFELEX_typeMINUS
);
2363 dotoktxt (exponent_digits
);
2369 ffetarget_make_real2 (value
,
2370 FFETARGET_ATOF_ (ptr
,
2373 if (sz
> ARRAY_SIZE (ffetarget_string_
))
2374 malloc_kill_ks (malloc_pool_image (), ptr
, sz
);
2381 ffetarget_typeless_binary (ffetargetTypeless
*xvalue
, ffelexToken token
)
2385 ffetargetTypeless value
= 0;
2386 ffetargetTypeless new_value
= 0;
2387 bool bad_digit
= FALSE
;
2388 bool overflow
= FALSE
;
2390 p
= ffelex_token_text (token
);
2392 for (c
= *p
; c
!= '\0'; c
= *++p
)
2395 if ((new_value
>> 1) != value
)
2398 new_value
+= c
- '0';
2406 ffebad_start (FFEBAD_INVALID_TYPELESS_BINARY_DIGIT
);
2407 ffebad_here (0, ffelex_token_where_line (token
),
2408 ffelex_token_where_column (token
));
2413 ffebad_start (FFEBAD_TYPELESS_OVERFLOW
);
2414 ffebad_here (0, ffelex_token_where_line (token
),
2415 ffelex_token_where_column (token
));
2421 return !bad_digit
&& !overflow
;
2425 ffetarget_typeless_octal (ffetargetTypeless
*xvalue
, ffelexToken token
)
2429 ffetargetTypeless value
= 0;
2430 ffetargetTypeless new_value
= 0;
2431 bool bad_digit
= FALSE
;
2432 bool overflow
= FALSE
;
2434 p
= ffelex_token_text (token
);
2436 for (c
= *p
; c
!= '\0'; c
= *++p
)
2439 if ((new_value
>> 3) != value
)
2442 new_value
+= c
- '0';
2450 ffebad_start (FFEBAD_INVALID_TYPELESS_OCTAL_DIGIT
);
2451 ffebad_here (0, ffelex_token_where_line (token
),
2452 ffelex_token_where_column (token
));
2457 ffebad_start (FFEBAD_TYPELESS_OVERFLOW
);
2458 ffebad_here (0, ffelex_token_where_line (token
),
2459 ffelex_token_where_column (token
));
2465 return !bad_digit
&& !overflow
;
2469 ffetarget_typeless_hex (ffetargetTypeless
*xvalue
, ffelexToken token
)
2473 ffetargetTypeless value
= 0;
2474 ffetargetTypeless new_value
= 0;
2475 bool bad_digit
= FALSE
;
2476 bool overflow
= FALSE
;
2478 p
= ffelex_token_text (token
);
2480 for (c
= *p
; c
!= '\0'; c
= *++p
)
2483 if ((new_value
>> 4) != value
)
2486 new_value
+= c
- '0';
2487 else if ((c
>= 'A') && (c
<= 'F'))
2488 new_value
+= c
- 'A' + 10;
2489 else if ((c
>= 'a') && (c
<= 'f'))
2490 new_value
+= c
- 'a' + 10;
2498 ffebad_start (FFEBAD_INVALID_TYPELESS_HEX_DIGIT
);
2499 ffebad_here (0, ffelex_token_where_line (token
),
2500 ffelex_token_where_column (token
));
2505 ffebad_start (FFEBAD_TYPELESS_OVERFLOW
);
2506 ffebad_here (0, ffelex_token_where_line (token
),
2507 ffelex_token_where_column (token
));
2513 return !bad_digit
&& !overflow
;
2517 ffetarget_verify_character1 (mallocPool pool
, ffetargetCharacter1 val
)
2519 if (val
.length
!= 0)
2520 malloc_verify_kp (pool
, val
.text
, val
.length
);
2523 /* This is like memcpy. It is needed because some systems' header files
2524 don't declare memcpy as a function but instead
2525 "#define memcpy(to,from,len) something". */
2528 ffetarget_memcpy_ (void *dst
, void *src
, size_t len
)
2530 return (void *) memcpy (dst
, src
, len
);
2533 /* ffetarget_num_digits_ -- Determine number of non-space characters in token
2535 ffetarget_num_digits_(token);
2537 All non-spaces are assumed to be binary, octal, or hex digits. */
2540 ffetarget_num_digits_ (ffelexToken token
)
2545 switch (ffelex_token_type (token
))
2547 case FFELEX_typeNAME
:
2548 case FFELEX_typeNUMBER
:
2549 return ffelex_token_length (token
);
2551 case FFELEX_typeCHARACTER
:
2553 for (c
= ffelex_token_text (token
); *c
!= '\0'; ++c
)
2561 assert ("weird token" == NULL
);