1 /* target.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995-1997 Free Software Foundation, Inc.
3 Contributed by James Craig Burley (burley@gnu.ai.mit.edu).
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
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
)
134 if (isprint (c
) && isascii (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 (*updated_modulo
< *updated_alignment
);
219 assert (modulo
< alignment
);
221 /* The easy case: similar alignment requirements. */
223 if (*updated_alignment
== alignment
)
225 if (modulo
> *updated_modulo
)
226 pad
= alignment
- (modulo
- *updated_modulo
);
228 pad
= *updated_modulo
- modulo
;
229 pad
= (offset
+ pad
) % alignment
;
231 pad
= alignment
- pad
;
235 /* Sigh, find LCM (Least Common Multiple) for the two alignment factors. */
237 for (ua
= *updated_alignment
, ucnt
= 1;
239 ua
+= *updated_alignment
)
242 cnt
= ua
/ alignment
;
244 min_pad
= ~(ffetargetAlign
) 0;/* Set to largest value. */
246 /* Find all combinations of modulo values the two alignment requirements
247 have; pick the combination that results in the smallest padding
248 requirement. Of course, if a zero-pad requirement is encountered, just
251 for (um
= *updated_modulo
, i
= 0; i
< ucnt
; um
+= *updated_alignment
, ++i
)
253 for (m
= modulo
, j
= 0; j
< cnt
; m
+= alignment
, ++j
)
255 if (m
> um
) /* This code is similar to the "easy case"
260 pad
= (offset
+ pad
) % ua
;
264 { /* A zero pad means we've got something
266 *updated_alignment
= ua
;
267 *updated_modulo
= um
;
271 { /* New minimum padding value. */
278 *updated_alignment
= ua
;
279 *updated_modulo
= min_m
;
283 #if FFETARGET_okCHARACTER1
285 ffetarget_character1 (ffetargetCharacter1
*val
, ffelexToken character
,
288 val
->length
= ffelex_token_length (character
);
289 if (val
->length
== 0)
293 val
->text
= malloc_new_kp (pool
, "ffetargetCharacter1", val
->length
);
294 memcpy (val
->text
, ffelex_token_text (character
), val
->length
);
301 /* Produce orderable comparison between two constants
303 Compare lengths, if equal then use memcmp. */
305 #if FFETARGET_okCHARACTER1
307 ffetarget_cmp_character1 (ffetargetCharacter1 l
, ffetargetCharacter1 r
)
309 if (l
.length
< r
.length
)
311 if (l
.length
> r
.length
)
315 return memcmp (l
.text
, r
.text
, l
.length
);
319 /* ffetarget_concatenate_character1 -- Perform CONCAT op on two constants
321 Compare lengths, if equal then use memcmp. */
323 #if FFETARGET_okCHARACTER1
325 ffetarget_concatenate_character1 (ffetargetCharacter1
*res
,
326 ffetargetCharacter1 l
, ffetargetCharacter1 r
, mallocPool pool
,
327 ffetargetCharacterSize
*len
)
329 res
->length
= *len
= l
.length
+ r
.length
;
334 res
->text
= malloc_new_kp (pool
, "ffetargetCharacter1(CONCAT)", *len
);
336 memcpy (res
->text
, l
.text
, l
.length
);
338 memcpy (res
->text
+ l
.length
, r
.text
, r
.length
);
345 /* ffetarget_eq_character1 -- Perform relational comparison on char constants
347 Compare lengths, if equal then use memcmp. */
349 #if FFETARGET_okCHARACTER1
351 ffetarget_eq_character1 (bool *res
, ffetargetCharacter1 l
,
352 ffetargetCharacter1 r
)
354 assert (l
.length
== r
.length
);
355 *res
= (memcmp (l
.text
, r
.text
, l
.length
) == 0);
360 /* ffetarget_le_character1 -- Perform relational comparison on char constants
362 Compare lengths, if equal then use memcmp. */
364 #if FFETARGET_okCHARACTER1
366 ffetarget_le_character1 (bool *res
, ffetargetCharacter1 l
,
367 ffetargetCharacter1 r
)
369 assert (l
.length
== r
.length
);
370 *res
= (memcmp (l
.text
, r
.text
, l
.length
) <= 0);
375 /* ffetarget_lt_character1 -- Perform relational comparison on char constants
377 Compare lengths, if equal then use memcmp. */
379 #if FFETARGET_okCHARACTER1
381 ffetarget_lt_character1 (bool *res
, ffetargetCharacter1 l
,
382 ffetargetCharacter1 r
)
384 assert (l
.length
== r
.length
);
385 *res
= (memcmp (l
.text
, r
.text
, l
.length
) < 0);
390 /* ffetarget_ge_character1 -- Perform relational comparison on char constants
392 Compare lengths, if equal then use memcmp. */
394 #if FFETARGET_okCHARACTER1
396 ffetarget_ge_character1 (bool *res
, ffetargetCharacter1 l
,
397 ffetargetCharacter1 r
)
399 assert (l
.length
== r
.length
);
400 *res
= (memcmp (l
.text
, r
.text
, l
.length
) >= 0);
405 /* ffetarget_gt_character1 -- Perform relational comparison on char constants
407 Compare lengths, if equal then use memcmp. */
409 #if FFETARGET_okCHARACTER1
411 ffetarget_gt_character1 (bool *res
, ffetargetCharacter1 l
,
412 ffetargetCharacter1 r
)
414 assert (l
.length
== r
.length
);
415 *res
= (memcmp (l
.text
, r
.text
, l
.length
) > 0);
420 #if FFETARGET_okCHARACTER1
422 ffetarget_iszero_character1 (ffetargetCharacter1 constant
)
424 ffetargetCharacterSize i
;
426 for (i
= 0; i
< constant
.length
; ++i
)
427 if (constant
.text
[i
] != 0)
434 ffetarget_iszero_hollerith (ffetargetHollerith constant
)
436 ffetargetHollerithSize i
;
438 for (i
= 0; i
< constant
.length
; ++i
)
439 if (constant
.text
[i
] != 0)
444 /* ffetarget_layout -- Do storage requirement analysis for entity
446 Return the alignment/modulo requirements along with the size, given the
447 data type info and the number of elements an array (1 for a scalar). */
450 ffetarget_layout (char *error_text UNUSED
, ffetargetAlign
*alignment
,
451 ffetargetAlign
*modulo
, ffetargetOffset
*size
,
452 ffeinfoBasictype bt
, ffeinfoKindtype kt
,
453 ffetargetCharacterSize charsize
,
454 ffetargetIntegerDefault num_elements
)
456 bool ok
; /* For character type. */
457 ffetargetOffset numele
; /* Converted from num_elements. */
460 type
= ffeinfo_type (bt
, kt
);
461 assert (type
!= NULL
);
463 *alignment
= ffetype_alignment (type
);
464 *modulo
= ffetype_modulo (type
);
465 if (bt
== FFEINFO_basictypeCHARACTER
)
467 ok
= ffetarget_offset_charsize (size
, charsize
, ffetype_size (type
));
468 #ifdef ffetarget_offset_overflow
470 ffetarget_offset_overflow (error_text
);
474 *size
= ffetype_size (type
);
476 if ((num_elements
< 0)
477 || !ffetarget_offset (&numele
, num_elements
)
478 || !ffetarget_offset_multiply (size
, *size
, numele
))
480 ffetarget_offset_overflow (error_text
);
487 /* ffetarget_ne_character1 -- Perform relational comparison on char constants
489 Compare lengths, if equal then use memcmp. */
491 #if FFETARGET_okCHARACTER1
493 ffetarget_ne_character1 (bool *res
, ffetargetCharacter1 l
,
494 ffetargetCharacter1 r
)
496 assert (l
.length
== r
.length
);
497 *res
= (memcmp (l
.text
, r
.text
, l
.length
) != 0);
502 /* ffetarget_substr_character1 -- Perform SUBSTR op on three constants
504 Compare lengths, if equal then use memcmp. */
506 #if FFETARGET_okCHARACTER1
508 ffetarget_substr_character1 (ffetargetCharacter1
*res
,
509 ffetargetCharacter1 l
,
510 ffetargetCharacterSize first
,
511 ffetargetCharacterSize last
, mallocPool pool
,
512 ffetargetCharacterSize
*len
)
516 res
->length
= *len
= 0;
521 res
->length
= *len
= last
- first
+ 1;
522 res
->text
= malloc_new_kp (pool
, "ffetargetCharacter1(SUBSTR)", *len
);
523 memcpy (res
->text
, l
.text
+ first
- 1, *len
);
530 /* ffetarget_cmp_hollerith -- Produce orderable comparison between two
533 Compare lengths, if equal then use memcmp. */
536 ffetarget_cmp_hollerith (ffetargetHollerith l
, ffetargetHollerith r
)
538 if (l
.length
< r
.length
)
540 if (l
.length
> r
.length
)
542 return memcmp (l
.text
, r
.text
, l
.length
);
546 ffetarget_convert_any_character1_ (char *res
, size_t size
,
547 ffetargetCharacter1 l
)
549 if (size
<= (size_t) l
.length
)
552 ffetargetCharacterSize i
;
554 memcpy (res
, l
.text
, size
);
555 for (p
= &l
.text
[0] + size
, i
= l
.length
- size
;
559 return FFEBAD_TRUNCATING_CHARACTER
;
563 memcpy (res
, l
.text
, size
);
564 memset (res
+ l
.length
, ' ', size
- l
.length
);
571 ffetarget_convert_any_hollerith_ (char *res
, size_t size
,
572 ffetargetHollerith l
)
574 if (size
<= (size_t) l
.length
)
577 ffetargetCharacterSize i
;
579 memcpy (res
, l
.text
, size
);
580 for (p
= &l
.text
[0] + size
, i
= l
.length
- size
;
584 return FFEBAD_TRUNCATING_HOLLERITH
;
588 memcpy (res
, l
.text
, size
);
589 memset (res
+ l
.length
, ' ', size
- l
.length
);
596 ffetarget_convert_any_typeless_ (char *res
, size_t size
,
599 unsigned long long int l1
;
600 unsigned long int l2
;
602 unsigned short int l4
;
607 if (size
>= sizeof (l1
))
611 size_of
= sizeof (l1
);
613 else if (size
>= sizeof (l2
))
617 size_of
= sizeof (l2
);
620 else if (size
>= sizeof (l3
))
624 size_of
= sizeof (l3
);
627 else if (size
>= sizeof (l4
))
631 size_of
= sizeof (l4
);
634 else if (size
>= sizeof (l5
))
638 size_of
= sizeof (l5
);
643 assert ("stumped by conversion from typeless!" == NULL
);
649 int i
= size_of
- size
;
651 memcpy (res
, p
+ i
, size
);
652 for (; i
> 0; ++p
, --i
)
654 return FFEBAD_TRUNCATING_TYPELESS
;
658 int i
= size
- size_of
;
661 memcpy (res
+ i
, p
, size_of
);
665 return FFEBAD_TRUNCATING_TYPELESS
;
669 #if FFETARGET_okCHARACTER1
671 ffetarget_convert_character1_character1 (ffetargetCharacter1
*res
,
672 ffetargetCharacterSize size
,
673 ffetargetCharacter1 l
,
681 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
);
682 if (size
<= l
.length
)
683 memcpy (res
->text
, l
.text
, size
);
686 memcpy (res
->text
, l
.text
, l
.length
);
687 memset (res
->text
+ l
.length
, ' ', size
- l
.length
);
695 #if FFETARGET_okCHARACTER1
697 ffetarget_convert_character1_hollerith (ffetargetCharacter1
*res
,
698 ffetargetCharacterSize size
,
699 ffetargetHollerith l
, mallocPool pool
)
706 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
);
707 if (size
<= l
.length
)
710 ffetargetCharacterSize i
;
712 memcpy (res
->text
, l
.text
, size
);
713 for (p
= &l
.text
[0] + size
, i
= l
.length
- size
;
717 return FFEBAD_TRUNCATING_HOLLERITH
;
721 memcpy (res
->text
, l
.text
, l
.length
);
722 memset (res
->text
+ l
.length
, ' ', size
- l
.length
);
730 /* ffetarget_convert_character1_integer1 -- Raw conversion. */
732 #if FFETARGET_okCHARACTER1
734 ffetarget_convert_character1_integer4 (ffetargetCharacter1
*res
,
735 ffetargetCharacterSize size
,
736 ffetargetInteger4 l
, mallocPool pool
)
746 if (((size_t) size
) >= sizeof (l1
))
750 size_of
= sizeof (l1
);
752 else if (((size_t) size
) >= sizeof (l2
))
756 size_of
= sizeof (l2
);
759 else if (((size_t) size
) >= sizeof (l3
))
763 size_of
= sizeof (l3
);
766 else if (((size_t) size
) >= sizeof (l4
))
770 size_of
= sizeof (l4
);
773 else if (((size_t) size
) >= sizeof (l5
))
777 size_of
= sizeof (l5
);
782 assert ("stumped by conversion from integer1!" == NULL
);
791 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
);
792 if (((size_t) size
) <= size_of
)
794 int i
= size_of
- size
;
796 memcpy (res
->text
, p
+ i
, size
);
797 for (; i
> 0; ++p
, --i
)
799 return FFEBAD_TRUNCATING_NUMERIC
;
803 int i
= size
- size_of
;
805 memset (res
->text
, 0, i
);
806 memcpy (res
->text
+ i
, p
, size_of
);
811 return FFEBAD_TRUNCATING_NUMERIC
;
816 /* ffetarget_convert_character1_logical1 -- Raw conversion. */
818 #if FFETARGET_okCHARACTER1
820 ffetarget_convert_character1_logical4 (ffetargetCharacter1
*res
,
821 ffetargetCharacterSize size
,
822 ffetargetLogical4 l
, mallocPool pool
)
832 if (((size_t) size
) >= sizeof (l1
))
836 size_of
= sizeof (l1
);
838 else if (((size_t) size
) >= sizeof (l2
))
842 size_of
= sizeof (l2
);
845 else if (((size_t) size
) >= sizeof (l3
))
849 size_of
= sizeof (l3
);
852 else if (((size_t) size
) >= sizeof (l4
))
856 size_of
= sizeof (l4
);
859 else if (((size_t) size
) >= sizeof (l5
))
863 size_of
= sizeof (l5
);
868 assert ("stumped by conversion from logical1!" == NULL
);
877 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
);
878 if (((size_t) size
) <= size_of
)
880 int i
= size_of
- size
;
882 memcpy (res
->text
, p
+ i
, size
);
883 for (; i
> 0; ++p
, --i
)
885 return FFEBAD_TRUNCATING_NUMERIC
;
889 int i
= size
- size_of
;
891 memset (res
->text
, 0, i
);
892 memcpy (res
->text
+ i
, p
, size_of
);
897 return FFEBAD_TRUNCATING_NUMERIC
;
902 /* ffetarget_convert_character1_typeless -- Raw conversion. */
904 #if FFETARGET_okCHARACTER1
906 ffetarget_convert_character1_typeless (ffetargetCharacter1
*res
,
907 ffetargetCharacterSize size
,
908 ffetargetTypeless l
, mallocPool pool
)
910 unsigned long long int l1
;
911 unsigned long int l2
;
913 unsigned short int l4
;
918 if (((size_t) size
) >= sizeof (l1
))
922 size_of
= sizeof (l1
);
924 else if (((size_t) size
) >= sizeof (l2
))
928 size_of
= sizeof (l2
);
931 else if (((size_t) size
) >= sizeof (l3
))
935 size_of
= sizeof (l3
);
938 else if (((size_t) size
) >= sizeof (l4
))
942 size_of
= sizeof (l4
);
945 else if (((size_t) size
) >= sizeof (l5
))
949 size_of
= sizeof (l5
);
954 assert ("stumped by conversion from typeless!" == NULL
);
963 res
->text
= malloc_new_kp (pool
, "FFETARGET cvt char1", size
);
964 if (((size_t) size
) <= size_of
)
966 int i
= size_of
- size
;
968 memcpy (res
->text
, p
+ i
, size
);
969 for (; i
> 0; ++p
, --i
)
971 return FFEBAD_TRUNCATING_TYPELESS
;
975 int i
= size
- size_of
;
977 memset (res
->text
, 0, i
);
978 memcpy (res
->text
+ i
, p
, size_of
);
983 return FFEBAD_TRUNCATING_TYPELESS
;
988 /* ffetarget_divide_complex1 -- Divide function
992 #if FFETARGET_okCOMPLEX1
994 ffetarget_divide_complex1 (ffetargetComplex1
*res
, ffetargetComplex1 l
,
998 ffetargetReal1 tmp1
, tmp2
, tmp3
, tmp4
;
1000 bad
= ffetarget_multiply_real1 (&tmp1
, r
.real
, r
.real
);
1003 bad
= ffetarget_multiply_real1 (&tmp2
, r
.imaginary
, r
.imaginary
);
1006 bad
= ffetarget_add_real1 (&tmp3
, tmp1
, tmp2
);
1010 if (ffetarget_iszero_real1 (tmp3
))
1012 ffetarget_real1_zero (&(res
)->real
);
1013 ffetarget_real1_zero (&(res
)->imaginary
);
1014 return FFEBAD_DIV_BY_ZERO
;
1017 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, r
.real
);
1020 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, r
.imaginary
);
1023 bad
= ffetarget_add_real1 (&tmp4
, tmp1
, tmp2
);
1026 bad
= ffetarget_divide_real1 (&res
->real
, tmp4
, tmp3
);
1030 bad
= ffetarget_multiply_real1 (&tmp1
, r
.real
, l
.imaginary
);
1033 bad
= ffetarget_multiply_real1 (&tmp2
, l
.real
, r
.imaginary
);
1036 bad
= ffetarget_subtract_real1 (&tmp4
, tmp1
, tmp2
);
1039 bad
= ffetarget_divide_real1 (&res
->imaginary
, tmp4
, tmp3
);
1045 /* ffetarget_divide_complex2 -- Divide function
1049 #if FFETARGET_okCOMPLEX2
1051 ffetarget_divide_complex2 (ffetargetComplex2
*res
, ffetargetComplex2 l
,
1052 ffetargetComplex2 r
)
1055 ffetargetReal2 tmp1
, tmp2
, tmp3
, tmp4
;
1057 bad
= ffetarget_multiply_real2 (&tmp1
, r
.real
, r
.real
);
1060 bad
= ffetarget_multiply_real2 (&tmp2
, r
.imaginary
, r
.imaginary
);
1063 bad
= ffetarget_add_real2 (&tmp3
, tmp1
, tmp2
);
1067 if (ffetarget_iszero_real2 (tmp3
))
1069 ffetarget_real2_zero (&(res
)->real
);
1070 ffetarget_real2_zero (&(res
)->imaginary
);
1071 return FFEBAD_DIV_BY_ZERO
;
1074 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, r
.real
);
1077 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, r
.imaginary
);
1080 bad
= ffetarget_add_real2 (&tmp4
, tmp1
, tmp2
);
1083 bad
= ffetarget_divide_real2 (&res
->real
, tmp4
, tmp3
);
1087 bad
= ffetarget_multiply_real2 (&tmp1
, r
.real
, l
.imaginary
);
1090 bad
= ffetarget_multiply_real2 (&tmp2
, l
.real
, r
.imaginary
);
1093 bad
= ffetarget_subtract_real2 (&tmp4
, tmp1
, tmp2
);
1096 bad
= ffetarget_divide_real2 (&res
->imaginary
, tmp4
, tmp3
);
1102 /* ffetarget_hollerith -- Convert token to a hollerith constant
1106 Token use count not affected overall. */
1109 ffetarget_hollerith (ffetargetHollerith
*val
, ffelexToken integer
,
1112 val
->length
= ffelex_token_length (integer
);
1113 val
->text
= malloc_new_kp (pool
, "ffetargetHollerith", val
->length
);
1114 memcpy (val
->text
, ffelex_token_text (integer
), val
->length
);
1119 /* ffetarget_integer_bad_magical -- Complain about a magical number
1121 Just calls ffebad with the arguments. */
1124 ffetarget_integer_bad_magical (ffelexToken t
)
1126 ffebad_start (FFEBAD_BAD_MAGICAL
);
1127 ffebad_here (0, ffelex_token_where_line (t
), ffelex_token_where_column (t
));
1131 /* ffetarget_integer_bad_magical_binary -- Complain about a magical number
1133 Just calls ffebad with the arguments. */
1136 ffetarget_integer_bad_magical_binary (ffelexToken integer
,
1139 ffebad_start (FFEBAD_BAD_MAGICAL_BINARY
);
1140 ffebad_here (0, ffelex_token_where_line (integer
),
1141 ffelex_token_where_column (integer
));
1142 ffebad_here (1, ffelex_token_where_line (minus
),
1143 ffelex_token_where_column (minus
));
1147 /* ffetarget_integer_bad_magical_precedence -- Complain about a magical
1150 Just calls ffebad with the arguments. */
1153 ffetarget_integer_bad_magical_precedence (ffelexToken integer
,
1155 ffelexToken higher_op
)
1157 ffebad_start (FFEBAD_BAD_MAGICAL_PRECEDENCE
);
1158 ffebad_here (0, ffelex_token_where_line (integer
),
1159 ffelex_token_where_column (integer
));
1160 ffebad_here (1, ffelex_token_where_line (uminus
),
1161 ffelex_token_where_column (uminus
));
1162 ffebad_here (2, ffelex_token_where_line (higher_op
),
1163 ffelex_token_where_column (higher_op
));
1167 /* ffetarget_integer_bad_magical_precedence_binary -- Complain...
1169 Just calls ffebad with the arguments. */
1172 ffetarget_integer_bad_magical_precedence_binary (ffelexToken integer
,
1174 ffelexToken higher_op
)
1176 ffebad_start (FFEBAD_BAD_MAGICAL_PRECEDENCE_BINARY
);
1177 ffebad_here (0, ffelex_token_where_line (integer
),
1178 ffelex_token_where_column (integer
));
1179 ffebad_here (1, ffelex_token_where_line (minus
),
1180 ffelex_token_where_column (minus
));
1181 ffebad_here (2, ffelex_token_where_line (higher_op
),
1182 ffelex_token_where_column (higher_op
));
1186 /* ffetarget_integer1 -- Convert token to an integer
1190 Token use count not affected overall. */
1192 #if FFETARGET_okINTEGER1
1194 ffetarget_integer1 (ffetargetInteger1
*val
, ffelexToken integer
)
1196 ffetargetInteger1 x
;
1200 assert (ffelex_token_type (integer
) == FFELEX_typeNUMBER
);
1202 p
= ffelex_token_text (integer
);
1205 /* Skip past leading zeros. */
1207 while (((c
= *p
) != '\0') && (c
== '0'))
1210 /* Interpret rest of number. */
1214 if ((x
== FFETARGET_integerALMOST_BIG_MAGICAL
)
1215 && (c
== '0' + FFETARGET_integerFINISH_BIG_MAGICAL
)
1216 && (*(p
+ 1) == '\0'))
1218 *val
= (ffetargetInteger1
) FFETARGET_integerBIG_MAGICAL
;
1221 else if (x
== FFETARGET_integerALMOST_BIG_MAGICAL
)
1223 if ((c
> '0' + FFETARGET_integerFINISH_BIG_MAGICAL
)
1224 || (*(p
+ 1) != '\0'))
1226 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1227 ffebad_here (0, ffelex_token_where_line (integer
),
1228 ffelex_token_where_column (integer
));
1234 else if (x
> FFETARGET_integerALMOST_BIG_MAGICAL
)
1236 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1237 ffebad_here (0, ffelex_token_where_line (integer
),
1238 ffelex_token_where_column (integer
));
1243 x
= x
* 10 + c
- '0';
1252 /* ffetarget_integerbinary -- Convert token to a binary integer
1254 ffetarget_integerbinary x;
1255 if (ffetarget_integerdefault_8(&x,integer_token))
1258 Token use count not affected overall. */
1261 ffetarget_integerbinary (ffetargetIntegerDefault
*val
, ffelexToken integer
)
1263 ffetargetIntegerDefault x
;
1268 assert ((ffelex_token_type (integer
) == FFELEX_typeNAME
)
1269 || (ffelex_token_type (integer
) == FFELEX_typeNUMBER
));
1271 p
= ffelex_token_text (integer
);
1274 /* Skip past leading zeros. */
1276 while (((c
= *p
) != '\0') && (c
== '0'))
1279 /* Interpret rest of number. */
1284 if ((c
>= '0') && (c
<= '1'))
1292 #if 0 /* Don't complain about signed overflow; just
1293 unsigned overflow. */
1294 if ((x
== FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY
)
1295 && (c
== FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY
)
1296 && (*(p
+ 1) == '\0'))
1298 *val
= FFETARGET_integerBIG_OVERFLOW_BINARY
;
1303 #if FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY == 0
1304 if ((x
& FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY
) != 0)
1306 if (x
== FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY
)
1308 if ((c
> FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY
)
1309 || (*(p
+ 1) != '\0'))
1311 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1312 ffebad_here (0, ffelex_token_where_line (integer
),
1313 ffelex_token_where_column (integer
));
1319 else if (x
> FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY
)
1322 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1323 ffebad_here (0, ffelex_token_where_line (integer
),
1324 ffelex_token_where_column (integer
));
1335 ffebad_start (FFEBAD_INVALID_BINARY_DIGIT
);
1336 ffebad_here (0, ffelex_token_where_line (integer
),
1337 ffelex_token_where_column (integer
));
1345 /* ffetarget_integerhex -- Convert token to a hex integer
1347 ffetarget_integerhex x;
1348 if (ffetarget_integerdefault_8(&x,integer_token))
1351 Token use count not affected overall. */
1354 ffetarget_integerhex (ffetargetIntegerDefault
*val
, ffelexToken integer
)
1356 ffetargetIntegerDefault x
;
1361 assert ((ffelex_token_type (integer
) == FFELEX_typeNAME
)
1362 || (ffelex_token_type (integer
) == FFELEX_typeNUMBER
));
1364 p
= ffelex_token_text (integer
);
1367 /* Skip past leading zeros. */
1369 while (((c
= *p
) != '\0') && (c
== '0'))
1372 /* Interpret rest of number. */
1377 if ((c
>= 'A') && (c
<= 'F'))
1379 else if ((c
>= 'a') && (c
<= 'f'))
1381 else if ((c
>= '0') && (c
<= '9'))
1389 #if 0 /* Don't complain about signed overflow; just
1390 unsigned overflow. */
1391 if ((x
== FFETARGET_integerALMOST_BIG_OVERFLOW_HEX
)
1392 && (c
== FFETARGET_integerFINISH_BIG_OVERFLOW_HEX
)
1393 && (*(p
+ 1) == '\0'))
1395 *val
= FFETARGET_integerBIG_OVERFLOW_HEX
;
1400 #if FFETARGET_integerFINISH_BIG_OVERFLOW_HEX == 0
1401 if (x
>= FFETARGET_integerALMOST_BIG_OVERFLOW_HEX
)
1403 if (x
== FFETARGET_integerALMOST_BIG_OVERFLOW_HEX
)
1405 if ((c
> FFETARGET_integerFINISH_BIG_OVERFLOW_HEX
)
1406 || (*(p
+ 1) != '\0'))
1408 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1409 ffebad_here (0, ffelex_token_where_line (integer
),
1410 ffelex_token_where_column (integer
));
1416 else if (x
> FFETARGET_integerALMOST_BIG_OVERFLOW_HEX
)
1419 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1420 ffebad_here (0, ffelex_token_where_line (integer
),
1421 ffelex_token_where_column (integer
));
1432 ffebad_start (FFEBAD_INVALID_HEX_DIGIT
);
1433 ffebad_here (0, ffelex_token_where_line (integer
),
1434 ffelex_token_where_column (integer
));
1442 /* ffetarget_integeroctal -- Convert token to an octal integer
1444 ffetarget_integeroctal x;
1445 if (ffetarget_integerdefault_8(&x,integer_token))
1448 Token use count not affected overall. */
1451 ffetarget_integeroctal (ffetargetIntegerDefault
*val
, ffelexToken integer
)
1453 ffetargetIntegerDefault x
;
1458 assert ((ffelex_token_type (integer
) == FFELEX_typeNAME
)
1459 || (ffelex_token_type (integer
) == FFELEX_typeNUMBER
));
1461 p
= ffelex_token_text (integer
);
1464 /* Skip past leading zeros. */
1466 while (((c
= *p
) != '\0') && (c
== '0'))
1469 /* Interpret rest of number. */
1474 if ((c
>= '0') && (c
<= '7'))
1482 #if 0 /* Don't complain about signed overflow; just
1483 unsigned overflow. */
1484 if ((x
== FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL
)
1485 && (c
== FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL
)
1486 && (*(p
+ 1) == '\0'))
1488 *val
= FFETARGET_integerBIG_OVERFLOW_OCTAL
;
1493 #if FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL == 0
1494 if (x
>= FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL
)
1496 if (x
== FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL
)
1498 if ((c
> FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL
)
1499 || (*(p
+ 1) != '\0'))
1501 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1502 ffebad_here (0, ffelex_token_where_line (integer
),
1503 ffelex_token_where_column (integer
));
1509 else if (x
> FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL
)
1512 ffebad_start (FFEBAD_INTEGER_TOO_LARGE
);
1513 ffebad_here (0, ffelex_token_where_line (integer
),
1514 ffelex_token_where_column (integer
));
1525 ffebad_start (FFEBAD_INVALID_OCTAL_DIGIT
);
1526 ffebad_here (0, ffelex_token_where_line (integer
),
1527 ffelex_token_where_column (integer
));
1535 /* ffetarget_multiply_complex1 -- Multiply function
1539 #if FFETARGET_okCOMPLEX1
1541 ffetarget_multiply_complex1 (ffetargetComplex1
*res
, ffetargetComplex1 l
,
1542 ffetargetComplex1 r
)
1545 ffetargetReal1 tmp1
, tmp2
;
1547 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, r
.real
);
1550 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, r
.imaginary
);
1553 bad
= ffetarget_subtract_real1 (&res
->real
, tmp1
, tmp2
);
1556 bad
= ffetarget_multiply_real1 (&tmp1
, l
.imaginary
, r
.real
);
1559 bad
= ffetarget_multiply_real1 (&tmp2
, l
.real
, r
.imaginary
);
1562 bad
= ffetarget_add_real1 (&res
->imaginary
, tmp1
, tmp2
);
1568 /* ffetarget_multiply_complex2 -- Multiply function
1572 #if FFETARGET_okCOMPLEX2
1574 ffetarget_multiply_complex2 (ffetargetComplex2
*res
, ffetargetComplex2 l
,
1575 ffetargetComplex2 r
)
1578 ffetargetReal2 tmp1
, tmp2
;
1580 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, r
.real
);
1583 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, r
.imaginary
);
1586 bad
= ffetarget_subtract_real2 (&res
->real
, tmp1
, tmp2
);
1589 bad
= ffetarget_multiply_real2 (&tmp1
, l
.imaginary
, r
.real
);
1592 bad
= ffetarget_multiply_real2 (&tmp2
, l
.real
, r
.imaginary
);
1595 bad
= ffetarget_add_real2 (&res
->imaginary
, tmp1
, tmp2
);
1601 /* ffetarget_power_complexdefault_integerdefault -- Power function
1606 ffetarget_power_complexdefault_integerdefault (ffetargetComplexDefault
*res
,
1607 ffetargetComplexDefault l
,
1608 ffetargetIntegerDefault r
)
1611 ffetargetRealDefault tmp
;
1612 ffetargetRealDefault tmp1
;
1613 ffetargetRealDefault tmp2
;
1614 ffetargetRealDefault two
;
1616 if (ffetarget_iszero_real1 (l
.real
)
1617 && ffetarget_iszero_real1 (l
.imaginary
))
1619 ffetarget_real1_zero (&res
->real
);
1620 ffetarget_real1_zero (&res
->imaginary
);
1626 ffetarget_real1_one (&res
->real
);
1627 ffetarget_real1_zero (&res
->imaginary
);
1634 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, l
.real
);
1637 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, l
.imaginary
);
1640 bad
= ffetarget_add_real1 (&tmp
, tmp1
, tmp2
);
1643 bad
= ffetarget_divide_real1 (&l
.real
, l
.real
, tmp
);
1646 bad
= ffetarget_divide_real1 (&l
.imaginary
, l
.imaginary
, tmp
);
1649 bad
= ffetarget_uminus_real1 (&l
.imaginary
, l
.imaginary
);
1654 ffetarget_real1_two (&two
);
1656 while ((r
& 1) == 0)
1658 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, l
.real
);
1661 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, l
.imaginary
);
1664 bad
= ffetarget_subtract_real1 (&tmp
, tmp1
, tmp2
);
1667 bad
= ffetarget_multiply_real1 (&l
.imaginary
, l
.real
, l
.imaginary
);
1670 bad
= ffetarget_multiply_real1 (&l
.imaginary
, l
.imaginary
, two
);
1682 bad
= ffetarget_multiply_real1 (&tmp1
, l
.real
, l
.real
);
1685 bad
= ffetarget_multiply_real1 (&tmp2
, l
.imaginary
, l
.imaginary
);
1688 bad
= ffetarget_subtract_real1 (&tmp
, tmp1
, tmp2
);
1691 bad
= ffetarget_multiply_real1 (&l
.imaginary
, l
.real
, l
.imaginary
);
1694 bad
= ffetarget_multiply_real1 (&l
.imaginary
, l
.imaginary
, two
);
1700 bad
= ffetarget_multiply_real1 (&tmp1
, res
->real
, l
.real
);
1703 bad
= ffetarget_multiply_real1 (&tmp2
, res
->imaginary
,
1707 bad
= ffetarget_subtract_real1 (&tmp
, tmp1
, tmp2
);
1710 bad
= ffetarget_multiply_real1 (&tmp1
, res
->imaginary
, l
.real
);
1713 bad
= ffetarget_multiply_real1 (&tmp2
, res
->real
, l
.imaginary
);
1716 bad
= ffetarget_add_real1 (&res
->imaginary
, tmp1
, tmp2
);
1727 /* ffetarget_power_complexdouble_integerdefault -- Power function
1731 #if FFETARGET_okCOMPLEXDOUBLE
1733 ffetarget_power_complexdouble_integerdefault (ffetargetComplexDouble
*res
,
1734 ffetargetComplexDouble l
, ffetargetIntegerDefault r
)
1737 ffetargetRealDouble tmp
;
1738 ffetargetRealDouble tmp1
;
1739 ffetargetRealDouble tmp2
;
1740 ffetargetRealDouble two
;
1742 if (ffetarget_iszero_real2 (l
.real
)
1743 && ffetarget_iszero_real2 (l
.imaginary
))
1745 ffetarget_real2_zero (&res
->real
);
1746 ffetarget_real2_zero (&res
->imaginary
);
1752 ffetarget_real2_one (&res
->real
);
1753 ffetarget_real2_zero (&res
->imaginary
);
1760 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, l
.real
);
1763 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, l
.imaginary
);
1766 bad
= ffetarget_add_real2 (&tmp
, tmp1
, tmp2
);
1769 bad
= ffetarget_divide_real2 (&l
.real
, l
.real
, tmp
);
1772 bad
= ffetarget_divide_real2 (&l
.imaginary
, l
.imaginary
, tmp
);
1775 bad
= ffetarget_uminus_real2 (&l
.imaginary
, l
.imaginary
);
1780 ffetarget_real2_two (&two
);
1782 while ((r
& 1) == 0)
1784 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, l
.real
);
1787 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, l
.imaginary
);
1790 bad
= ffetarget_subtract_real2 (&tmp
, tmp1
, tmp2
);
1793 bad
= ffetarget_multiply_real2 (&l
.imaginary
, l
.real
, l
.imaginary
);
1796 bad
= ffetarget_multiply_real2 (&l
.imaginary
, l
.imaginary
, two
);
1808 bad
= ffetarget_multiply_real2 (&tmp1
, l
.real
, l
.real
);
1811 bad
= ffetarget_multiply_real2 (&tmp2
, l
.imaginary
, l
.imaginary
);
1814 bad
= ffetarget_subtract_real2 (&tmp
, tmp1
, tmp2
);
1817 bad
= ffetarget_multiply_real2 (&l
.imaginary
, l
.real
, l
.imaginary
);
1820 bad
= ffetarget_multiply_real2 (&l
.imaginary
, l
.imaginary
, two
);
1826 bad
= ffetarget_multiply_real2 (&tmp1
, res
->real
, l
.real
);
1829 bad
= ffetarget_multiply_real2 (&tmp2
, res
->imaginary
,
1833 bad
= ffetarget_subtract_real2 (&tmp
, tmp1
, tmp2
);
1836 bad
= ffetarget_multiply_real2 (&tmp1
, res
->imaginary
, l
.real
);
1839 bad
= ffetarget_multiply_real2 (&tmp2
, res
->real
, l
.imaginary
);
1842 bad
= ffetarget_add_real2 (&res
->imaginary
, tmp1
, tmp2
);
1854 /* ffetarget_power_integerdefault_integerdefault -- Power function
1859 ffetarget_power_integerdefault_integerdefault (ffetargetIntegerDefault
*res
,
1860 ffetargetIntegerDefault l
, ffetargetIntegerDefault r
)
1881 *res
= ((-r
) & 1) == 0 ? 1 : -1;
1887 while ((r
& 1) == 0)
1907 /* ffetarget_power_realdefault_integerdefault -- Power function
1912 ffetarget_power_realdefault_integerdefault (ffetargetRealDefault
*res
,
1913 ffetargetRealDefault l
, ffetargetIntegerDefault r
)
1917 if (ffetarget_iszero_real1 (l
))
1919 ffetarget_real1_zero (res
);
1925 ffetarget_real1_one (res
);
1931 ffetargetRealDefault one
;
1933 ffetarget_real1_one (&one
);
1935 bad
= ffetarget_divide_real1 (&l
, one
, l
);
1940 while ((r
& 1) == 0)
1942 bad
= ffetarget_multiply_real1 (&l
, l
, l
);
1953 bad
= ffetarget_multiply_real1 (&l
, l
, l
);
1958 bad
= ffetarget_multiply_real1 (res
, *res
, l
);
1968 /* ffetarget_power_realdouble_integerdefault -- Power function
1973 ffetarget_power_realdouble_integerdefault (ffetargetRealDouble
*res
,
1974 ffetargetRealDouble l
,
1975 ffetargetIntegerDefault r
)
1979 if (ffetarget_iszero_real2 (l
))
1981 ffetarget_real2_zero (res
);
1987 ffetarget_real2_one (res
);
1993 ffetargetRealDouble one
;
1995 ffetarget_real2_one (&one
);
1997 bad
= ffetarget_divide_real2 (&l
, one
, l
);
2002 while ((r
& 1) == 0)
2004 bad
= ffetarget_multiply_real2 (&l
, l
, l
);
2015 bad
= ffetarget_multiply_real2 (&l
, l
, l
);
2020 bad
= ffetarget_multiply_real2 (res
, *res
, l
);
2030 /* ffetarget_print_binary -- Output typeless binary integer
2032 ffetargetTypeless val;
2033 ffetarget_typeless_binary(dmpout,val); */
2036 ffetarget_print_binary (FILE *f
, ffetargetTypeless value
)
2039 char digits
[sizeof (value
) * CHAR_BIT
+ 1];
2044 p
= &digits
[ARRAY_SIZE (digits
) - 1];
2048 *--p
= (value
& 1) + '0';
2050 } while (value
== 0);
2055 /* ffetarget_print_character1 -- Output character string
2057 ffetargetCharacter1 val;
2058 ffetarget_print_character1(dmpout,val); */
2061 ffetarget_print_character1 (FILE *f
, ffetargetCharacter1 value
)
2064 ffetargetCharacterSize i
;
2066 fputc ('\'', dmpout
);
2067 for (i
= 0, p
= value
.text
; i
< value
.length
; ++i
, ++p
)
2068 ffetarget_print_char_ (f
, *p
);
2069 fputc ('\'', dmpout
);
2072 /* ffetarget_print_hollerith -- Output hollerith string
2074 ffetargetHollerith val;
2075 ffetarget_print_hollerith(dmpout,val); */
2078 ffetarget_print_hollerith (FILE *f
, ffetargetHollerith value
)
2081 ffetargetHollerithSize i
;
2083 fputc ('\'', dmpout
);
2084 for (i
= 0, p
= value
.text
; i
< value
.length
; ++i
, ++p
)
2085 ffetarget_print_char_ (f
, *p
);
2086 fputc ('\'', dmpout
);
2089 /* ffetarget_print_octal -- Output typeless octal integer
2091 ffetargetTypeless val;
2092 ffetarget_print_octal(dmpout,val); */
2095 ffetarget_print_octal (FILE *f
, ffetargetTypeless value
)
2098 char digits
[sizeof (value
) * CHAR_BIT
/ 3 + 1];
2103 p
= &digits
[ARRAY_SIZE (digits
) - 3];
2107 *--p
= (value
& 3) + '0';
2109 } while (value
== 0);
2114 /* ffetarget_print_hex -- Output typeless hex integer
2116 ffetargetTypeless val;
2117 ffetarget_print_hex(dmpout,val); */
2120 ffetarget_print_hex (FILE *f
, ffetargetTypeless value
)
2123 char digits
[sizeof (value
) * CHAR_BIT
/ 4 + 1];
2124 static char hexdigits
[16] = "0123456789ABCDEF";
2129 p
= &digits
[ARRAY_SIZE (digits
) - 3];
2133 *--p
= hexdigits
[value
& 4];
2135 } while (value
== 0);
2140 /* ffetarget_real1 -- Convert token to a single-precision real number
2144 Pass NULL for any token not provided by the user, but a valid Fortran
2145 real number must be provided somehow. For example, it is ok for
2146 exponent_sign_token and exponent_digits_token to be NULL as long as
2147 exponent_token not only starts with "E" or "e" but also contains at least
2148 one digit following it. Token use counts not affected overall. */
2150 #if FFETARGET_okREAL1
2152 ffetarget_real1 (ffetargetReal1
*value
, ffelexToken integer
,
2153 ffelexToken decimal
, ffelexToken fraction
,
2154 ffelexToken exponent
, ffelexToken exponent_sign
,
2155 ffelexToken exponent_digits
)
2157 size_t sz
= 1; /* Allow room for '\0' byte at end. */
2158 char *ptr
= &ffetarget_string_
[0];
2162 #define dotok(x) if (x != NULL) ++sz;
2163 #define dotoktxt(x) if (x != NULL) sz += ffelex_token_length(x)
2167 dotoktxt (fraction
);
2168 dotoktxt (exponent
);
2169 dotok (exponent_sign
);
2170 dotoktxt (exponent_digits
);
2175 if (sz
> ARRAY_SIZE (ffetarget_string_
))
2176 p
= ptr
= (char *) malloc_new_ks (malloc_pool_image (), "ffetarget_real1",
2179 #define dotoktxt(x) if (x != NULL) \
2181 for (q = ffelex_token_text(x); *q != '\0'; ++q) \
2187 if (decimal
!= NULL
)
2190 dotoktxt (fraction
);
2191 dotoktxt (exponent
);
2193 if (exponent_sign
!= NULL
)
2194 if (ffelex_token_type (exponent_sign
) == FFELEX_typePLUS
)
2198 assert (ffelex_token_type (exponent_sign
) == FFELEX_typeMINUS
);
2202 dotoktxt (exponent_digits
);
2208 ffetarget_make_real1 (value
,
2209 FFETARGET_ATOF_ (ptr
,
2212 if (sz
> ARRAY_SIZE (ffetarget_string_
))
2213 malloc_kill_ks (malloc_pool_image (), ptr
, sz
);
2219 /* ffetarget_real2 -- Convert token to a single-precision real number
2223 Pass NULL for any token not provided by the user, but a valid Fortran
2224 real number must be provided somehow. For example, it is ok for
2225 exponent_sign_token and exponent_digits_token to be NULL as long as
2226 exponent_token not only starts with "E" or "e" but also contains at least
2227 one digit following it. Token use counts not affected overall. */
2229 #if FFETARGET_okREAL2
2231 ffetarget_real2 (ffetargetReal2
*value
, ffelexToken integer
,
2232 ffelexToken decimal
, ffelexToken fraction
,
2233 ffelexToken exponent
, ffelexToken exponent_sign
,
2234 ffelexToken exponent_digits
)
2236 size_t sz
= 1; /* Allow room for '\0' byte at end. */
2237 char *ptr
= &ffetarget_string_
[0];
2241 #define dotok(x) if (x != NULL) ++sz;
2242 #define dotoktxt(x) if (x != NULL) sz += ffelex_token_length(x)
2246 dotoktxt (fraction
);
2247 dotoktxt (exponent
);
2248 dotok (exponent_sign
);
2249 dotoktxt (exponent_digits
);
2254 if (sz
> ARRAY_SIZE (ffetarget_string_
))
2255 p
= ptr
= (char *) malloc_new_ks (malloc_pool_image (), "ffetarget_real1", sz
);
2257 #define dotoktxt(x) if (x != NULL) \
2259 for (q = ffelex_token_text(x); *q != '\0'; ++q) \
2262 #define dotoktxtexp(x) if (x != NULL) \
2265 for (q = ffelex_token_text(x) + 1; *q != '\0'; ++q) \
2271 if (decimal
!= NULL
)
2274 dotoktxt (fraction
);
2275 dotoktxtexp (exponent
);
2277 if (exponent_sign
!= NULL
)
2278 if (ffelex_token_type (exponent_sign
) == FFELEX_typePLUS
)
2282 assert (ffelex_token_type (exponent_sign
) == FFELEX_typeMINUS
);
2286 dotoktxt (exponent_digits
);
2292 ffetarget_make_real2 (value
,
2293 FFETARGET_ATOF_ (ptr
,
2296 if (sz
> ARRAY_SIZE (ffetarget_string_
))
2297 malloc_kill_ks (malloc_pool_image (), ptr
, sz
);
2304 ffetarget_typeless_binary (ffetargetTypeless
*xvalue
, ffelexToken token
)
2308 ffetargetTypeless value
= 0;
2309 ffetargetTypeless new_value
= 0;
2310 bool bad_digit
= FALSE
;
2311 bool overflow
= FALSE
;
2313 p
= ffelex_token_text (token
);
2315 for (c
= *p
; c
!= '\0'; c
= *++p
)
2318 if ((new_value
>> 1) != value
)
2321 new_value
+= c
- '0';
2329 ffebad_start (FFEBAD_INVALID_TYPELESS_BINARY_DIGIT
);
2330 ffebad_here (0, ffelex_token_where_line (token
),
2331 ffelex_token_where_column (token
));
2336 ffebad_start (FFEBAD_TYPELESS_OVERFLOW
);
2337 ffebad_here (0, ffelex_token_where_line (token
),
2338 ffelex_token_where_column (token
));
2344 return !bad_digit
&& !overflow
;
2348 ffetarget_typeless_octal (ffetargetTypeless
*xvalue
, ffelexToken token
)
2352 ffetargetTypeless value
= 0;
2353 ffetargetTypeless new_value
= 0;
2354 bool bad_digit
= FALSE
;
2355 bool overflow
= FALSE
;
2357 p
= ffelex_token_text (token
);
2359 for (c
= *p
; c
!= '\0'; c
= *++p
)
2362 if ((new_value
>> 3) != value
)
2365 new_value
+= c
- '0';
2373 ffebad_start (FFEBAD_INVALID_TYPELESS_OCTAL_DIGIT
);
2374 ffebad_here (0, ffelex_token_where_line (token
),
2375 ffelex_token_where_column (token
));
2380 ffebad_start (FFEBAD_TYPELESS_OVERFLOW
);
2381 ffebad_here (0, ffelex_token_where_line (token
),
2382 ffelex_token_where_column (token
));
2388 return !bad_digit
&& !overflow
;
2392 ffetarget_typeless_hex (ffetargetTypeless
*xvalue
, ffelexToken token
)
2396 ffetargetTypeless value
= 0;
2397 ffetargetTypeless new_value
= 0;
2398 bool bad_digit
= FALSE
;
2399 bool overflow
= FALSE
;
2401 p
= ffelex_token_text (token
);
2403 for (c
= *p
; c
!= '\0'; c
= *++p
)
2406 if ((new_value
>> 4) != value
)
2409 new_value
+= c
- '0';
2410 else if ((c
>= 'A') && (c
<= 'F'))
2411 new_value
+= c
- 'A' + 10;
2412 else if ((c
>= 'a') && (c
<= 'f'))
2413 new_value
+= c
- 'a' + 10;
2421 ffebad_start (FFEBAD_INVALID_TYPELESS_HEX_DIGIT
);
2422 ffebad_here (0, ffelex_token_where_line (token
),
2423 ffelex_token_where_column (token
));
2428 ffebad_start (FFEBAD_TYPELESS_OVERFLOW
);
2429 ffebad_here (0, ffelex_token_where_line (token
),
2430 ffelex_token_where_column (token
));
2436 return !bad_digit
&& !overflow
;
2440 ffetarget_verify_character1 (mallocPool pool
, ffetargetCharacter1 val
)
2442 if (val
.length
!= 0)
2443 malloc_verify_kp (pool
, val
.text
, val
.length
);
2446 /* This is like memcpy. It is needed because some systems' header files
2447 don't declare memcpy as a function but instead
2448 "#define memcpy(to,from,len) something". */
2451 ffetarget_memcpy_ (void *dst
, void *src
, size_t len
)
2453 return (void *) memcpy (dst
, src
, len
);
2456 /* ffetarget_num_digits_ -- Determine number of non-space characters in token
2458 ffetarget_num_digits_(token);
2460 All non-spaces are assumed to be binary, octal, or hex digits. */
2463 ffetarget_num_digits_ (ffelexToken token
)
2468 switch (ffelex_token_type (token
))
2470 case FFELEX_typeNAME
:
2471 case FFELEX_typeNUMBER
:
2472 return ffelex_token_length (token
);
2474 case FFELEX_typeCHARACTER
:
2476 for (c
= ffelex_token_text (token
); *c
!= '\0'; ++c
)
2484 assert ("weird token" == NULL
);