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 (burley@gnu.org).
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 (*updated_modulo < *updated_alignment);
218 assert (modulo < alignment);
220 /* The easy case: similar alignment requirements. */
221 if (*updated_alignment == alignment)
223 if (modulo > *updated_modulo)
224 pad = alignment - (modulo - *updated_modulo);
226 pad = *updated_modulo - modulo;
228 /* De-negatize offset, since % wouldn't do the expected thing. */
229 offset = alignment - ((- offset) % alignment);
230 pad = (offset + pad) % alignment;
232 pad = alignment - pad;
236 /* Sigh, find LCM (Least Common Multiple) for the two alignment factors. */
238 for (ua = *updated_alignment, ucnt = 1;
240 ua += *updated_alignment)
243 cnt = ua / alignment;
246 /* De-negatize offset, since % wouldn't do the expected thing. */
247 offset = ua - ((- offset) % ua);
249 /* Set to largest value. */
250 min_pad = ~(ffetargetAlign) 0;
252 /* Find all combinations of modulo values the two alignment requirements
253 have; pick the combination that results in the smallest padding
254 requirement. Of course, if a zero-pad requirement is encountered, just
257 for (um = *updated_modulo, i = 0; i < ucnt; um += *updated_alignment, ++i)
259 for (m = modulo, j = 0; j < cnt; m += alignment, ++j)
261 /* This code is similar to the "easy case" code above. */
266 pad = (offset + pad) % ua;
269 /* A zero pad means we've got something useful. */
270 *updated_alignment = ua;
271 *updated_modulo = um;
276 { /* New minimum padding value. */
283 *updated_alignment = ua;
284 *updated_modulo = min_m;
288 /* Always append a null byte to the end, in case this is wanted in
289 a special case such as passing a string as a FORMAT or %REF.
290 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
291 because it isn't a "feature" that is self-documenting. Use the
292 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
295 #if FFETARGET_okCHARACTER1
297 ffetarget_character1 (ffetargetCharacter1 *val, ffelexToken character,
300 val->length = ffelex_token_length (character);
301 if (val->length == 0)
305 val->text = malloc_new_kp (pool, "ffetargetCharacter1", val->length + 1);
306 memcpy (val->text, ffelex_token_text (character), val->length);
307 val->text[val->length] = '\0';
314 /* Produce orderable comparison between two constants
316 Compare lengths, if equal then use memcmp. */
318 #if FFETARGET_okCHARACTER1
320 ffetarget_cmp_character1 (ffetargetCharacter1 l, ffetargetCharacter1 r)
322 if (l.length < r.length)
324 if (l.length > r.length)
328 return memcmp (l.text, r.text, l.length);
332 /* ffetarget_concatenate_character1 -- Perform CONCAT op on two constants
334 Always append a null byte to the end, in case this is wanted in
335 a special case such as passing a string as a FORMAT or %REF.
336 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
337 because it isn't a "feature" that is self-documenting. Use the
338 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
341 #if FFETARGET_okCHARACTER1
343 ffetarget_concatenate_character1 (ffetargetCharacter1 *res,
344 ffetargetCharacter1 l, ffetargetCharacter1 r, mallocPool pool,
345 ffetargetCharacterSize *len)
347 res->length = *len = l.length + r.length;
352 res->text = malloc_new_kp (pool, "ffetargetCharacter1(CONCAT)", *len + 1);
354 memcpy (res->text, l.text, l.length);
356 memcpy (res->text + l.length, r.text, r.length);
357 res->text[*len] = '\0';
364 /* ffetarget_eq_character1 -- Perform relational comparison on char constants
366 Compare lengths, if equal then use memcmp. */
368 #if FFETARGET_okCHARACTER1
370 ffetarget_eq_character1 (bool *res, ffetargetCharacter1 l,
371 ffetargetCharacter1 r)
373 assert (l.length == r.length);
374 *res = (memcmp (l.text, r.text, l.length) == 0);
379 /* ffetarget_le_character1 -- Perform relational comparison on char constants
381 Compare lengths, if equal then use memcmp. */
383 #if FFETARGET_okCHARACTER1
385 ffetarget_le_character1 (bool *res, ffetargetCharacter1 l,
386 ffetargetCharacter1 r)
388 assert (l.length == r.length);
389 *res = (memcmp (l.text, r.text, l.length) <= 0);
394 /* ffetarget_lt_character1 -- Perform relational comparison on char constants
396 Compare lengths, if equal then use memcmp. */
398 #if FFETARGET_okCHARACTER1
400 ffetarget_lt_character1 (bool *res, ffetargetCharacter1 l,
401 ffetargetCharacter1 r)
403 assert (l.length == r.length);
404 *res = (memcmp (l.text, r.text, l.length) < 0);
409 /* ffetarget_ge_character1 -- Perform relational comparison on char constants
411 Compare lengths, if equal then use memcmp. */
413 #if FFETARGET_okCHARACTER1
415 ffetarget_ge_character1 (bool *res, ffetargetCharacter1 l,
416 ffetargetCharacter1 r)
418 assert (l.length == r.length);
419 *res = (memcmp (l.text, r.text, l.length) >= 0);
424 /* ffetarget_gt_character1 -- Perform relational comparison on char constants
426 Compare lengths, if equal then use memcmp. */
428 #if FFETARGET_okCHARACTER1
430 ffetarget_gt_character1 (bool *res, ffetargetCharacter1 l,
431 ffetargetCharacter1 r)
433 assert (l.length == r.length);
434 *res = (memcmp (l.text, r.text, l.length) > 0);
439 #if FFETARGET_okCHARACTER1
441 ffetarget_iszero_character1 (ffetargetCharacter1 constant)
443 ffetargetCharacterSize i;
445 for (i = 0; i < constant.length; ++i)
446 if (constant.text[i] != 0)
453 ffetarget_iszero_hollerith (ffetargetHollerith constant)
455 ffetargetHollerithSize i;
457 for (i = 0; i < constant.length; ++i)
458 if (constant.text[i] != 0)
463 /* ffetarget_layout -- Do storage requirement analysis for entity
465 Return the alignment/modulo requirements along with the size, given the
466 data type info and the number of elements an array (1 for a scalar). */
469 ffetarget_layout (char *error_text UNUSED, ffetargetAlign *alignment,
470 ffetargetAlign *modulo, ffetargetOffset *size,
471 ffeinfoBasictype bt, ffeinfoKindtype kt,
472 ffetargetCharacterSize charsize,
473 ffetargetIntegerDefault num_elements)
475 bool ok; /* For character type. */
476 ffetargetOffset numele; /* Converted from num_elements. */
479 type = ffeinfo_type (bt, kt);
480 assert (type != NULL);
482 *alignment = ffetype_alignment (type);
483 *modulo = ffetype_modulo (type);
484 if (bt == FFEINFO_basictypeCHARACTER)
486 ok = ffetarget_offset_charsize (size, charsize, ffetype_size (type));
487 #ifdef ffetarget_offset_overflow
489 ffetarget_offset_overflow (error_text);
493 *size = ffetype_size (type);
495 if ((num_elements < 0)
496 || !ffetarget_offset (&numele, num_elements)
497 || !ffetarget_offset_multiply (size, *size, numele))
499 ffetarget_offset_overflow (error_text);
506 /* ffetarget_ne_character1 -- Perform relational comparison on char constants
508 Compare lengths, if equal then use memcmp. */
510 #if FFETARGET_okCHARACTER1
512 ffetarget_ne_character1 (bool *res, ffetargetCharacter1 l,
513 ffetargetCharacter1 r)
515 assert (l.length == r.length);
516 *res = (memcmp (l.text, r.text, l.length) != 0);
521 /* ffetarget_substr_character1 -- Perform SUBSTR op on three constants
523 Always append a null byte to the end, in case this is wanted in
524 a special case such as passing a string as a FORMAT or %REF.
525 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
526 because it isn't a "feature" that is self-documenting. Use the
527 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
530 #if FFETARGET_okCHARACTER1
532 ffetarget_substr_character1 (ffetargetCharacter1 *res,
533 ffetargetCharacter1 l,
534 ffetargetCharacterSize first,
535 ffetargetCharacterSize last, mallocPool pool,
536 ffetargetCharacterSize *len)
540 res->length = *len = 0;
545 res->length = *len = last - first + 1;
546 res->text = malloc_new_kp (pool, "ffetargetCharacter1(SUBSTR)", *len + 1);
547 memcpy (res->text, l.text + first - 1, *len);
548 res->text[*len] = '\0';
555 /* ffetarget_cmp_hollerith -- Produce orderable comparison between two
558 Compare lengths, if equal then use memcmp. */
561 ffetarget_cmp_hollerith (ffetargetHollerith l, ffetargetHollerith r)
563 if (l.length < r.length)
565 if (l.length > r.length)
567 return memcmp (l.text, r.text, l.length);
571 ffetarget_convert_any_character1_ (char *res, size_t size,
572 ffetargetCharacter1 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_CHARACTER;
588 memcpy (res, l.text, size);
589 memset (res + l.length, ' ', size - l.length);
596 ffetarget_convert_any_hollerith_ (char *res, size_t size,
597 ffetargetHollerith l)
599 if (size <= (size_t) l.length)
602 ffetargetCharacterSize i;
604 memcpy (res, l.text, size);
605 for (p = &l.text[0] + size, i = l.length - size;
609 return FFEBAD_TRUNCATING_HOLLERITH;
613 memcpy (res, l.text, size);
614 memset (res + l.length, ' ', size - l.length);
621 ffetarget_convert_any_typeless_ (char *res, size_t size,
624 unsigned long long int l1;
625 unsigned long int l2;
627 unsigned short int l4;
632 if (size >= sizeof (l1))
636 size_of = sizeof (l1);
638 else if (size >= sizeof (l2))
642 size_of = sizeof (l2);
645 else if (size >= sizeof (l3))
649 size_of = sizeof (l3);
652 else if (size >= sizeof (l4))
656 size_of = sizeof (l4);
659 else if (size >= sizeof (l5))
663 size_of = sizeof (l5);
668 assert ("stumped by conversion from typeless!" == NULL);
674 int i = size_of - size;
676 memcpy (res, p + i, size);
677 for (; i > 0; ++p, --i)
679 return FFEBAD_TRUNCATING_TYPELESS;
683 int i = size - size_of;
686 memcpy (res + i, p, size_of);
690 return FFEBAD_TRUNCATING_TYPELESS;
694 /* Always append a null byte to the end, in case this is wanted in
695 a special case such as passing a string as a FORMAT or %REF.
696 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
697 because it isn't a "feature" that is self-documenting. Use the
698 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
701 #if FFETARGET_okCHARACTER1
703 ffetarget_convert_character1_character1 (ffetargetCharacter1 *res,
704 ffetargetCharacterSize size,
705 ffetargetCharacter1 l,
713 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
714 if (size <= l.length)
715 memcpy (res->text, l.text, size);
718 memcpy (res->text, l.text, l.length);
719 memset (res->text + l.length, ' ', size - l.length);
721 res->text[size] = '\0';
729 /* Always append a null byte to the end, in case this is wanted in
730 a special case such as passing a string as a FORMAT or %REF.
731 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
732 because it isn't a "feature" that is self-documenting. Use the
733 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
736 #if FFETARGET_okCHARACTER1
738 ffetarget_convert_character1_hollerith (ffetargetCharacter1 *res,
739 ffetargetCharacterSize size,
740 ffetargetHollerith l, mallocPool pool)
747 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
748 res->text[size] = '\0';
749 if (size <= l.length)
752 ffetargetCharacterSize i;
754 memcpy (res->text, l.text, size);
755 for (p = &l.text[0] + size, i = l.length - size;
759 return FFEBAD_TRUNCATING_HOLLERITH;
763 memcpy (res->text, l.text, l.length);
764 memset (res->text + l.length, ' ', size - l.length);
772 /* ffetarget_convert_character1_integer4 -- Raw conversion.
774 Always append a null byte to the end, in case this is wanted in
775 a special case such as passing a string as a FORMAT or %REF.
776 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
777 because it isn't a "feature" that is self-documenting. Use the
778 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
781 #if FFETARGET_okCHARACTER1
783 ffetarget_convert_character1_integer4 (ffetargetCharacter1 *res,
784 ffetargetCharacterSize size,
785 ffetargetInteger4 l, mallocPool pool)
795 if (((size_t) size) >= sizeof (l1))
799 size_of = sizeof (l1);
801 else if (((size_t) size) >= sizeof (l2))
805 size_of = sizeof (l2);
808 else if (((size_t) size) >= sizeof (l3))
812 size_of = sizeof (l3);
815 else if (((size_t) size) >= sizeof (l4))
819 size_of = sizeof (l4);
822 else if (((size_t) size) >= sizeof (l5))
826 size_of = sizeof (l5);
831 assert ("stumped by conversion from integer1!" == NULL);
840 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
841 res->text[size] = '\0';
842 if (((size_t) size) <= size_of)
844 int i = size_of - size;
846 memcpy (res->text, p + i, size);
847 for (; i > 0; ++p, --i)
849 return FFEBAD_TRUNCATING_NUMERIC;
853 int i = size - size_of;
855 memset (res->text, 0, i);
856 memcpy (res->text + i, p, size_of);
861 return FFEBAD_TRUNCATING_NUMERIC;
866 /* ffetarget_convert_character1_logical4 -- Raw conversion.
868 Always append a null byte to the end, in case this is wanted in
869 a special case such as passing a string as a FORMAT or %REF.
870 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
871 because it isn't a "feature" that is self-documenting. Use the
872 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
875 #if FFETARGET_okCHARACTER1
877 ffetarget_convert_character1_logical4 (ffetargetCharacter1 *res,
878 ffetargetCharacterSize size,
879 ffetargetLogical4 l, mallocPool pool)
889 if (((size_t) size) >= sizeof (l1))
893 size_of = sizeof (l1);
895 else if (((size_t) size) >= sizeof (l2))
899 size_of = sizeof (l2);
902 else if (((size_t) size) >= sizeof (l3))
906 size_of = sizeof (l3);
909 else if (((size_t) size) >= sizeof (l4))
913 size_of = sizeof (l4);
916 else if (((size_t) size) >= sizeof (l5))
920 size_of = sizeof (l5);
925 assert ("stumped by conversion from logical1!" == NULL);
934 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
935 res->text[size] = '\0';
936 if (((size_t) size) <= size_of)
938 int i = size_of - size;
940 memcpy (res->text, p + i, size);
941 for (; i > 0; ++p, --i)
943 return FFEBAD_TRUNCATING_NUMERIC;
947 int i = size - size_of;
949 memset (res->text, 0, i);
950 memcpy (res->text + i, p, size_of);
955 return FFEBAD_TRUNCATING_NUMERIC;
960 /* ffetarget_convert_character1_typeless -- Raw conversion.
962 Always append a null byte to the end, in case this is wanted in
963 a special case such as passing a string as a FORMAT or %REF.
964 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
965 because it isn't a "feature" that is self-documenting. Use the
966 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
969 #if FFETARGET_okCHARACTER1
971 ffetarget_convert_character1_typeless (ffetargetCharacter1 *res,
972 ffetargetCharacterSize size,
973 ffetargetTypeless l, mallocPool pool)
975 unsigned long long int l1;
976 unsigned long int l2;
978 unsigned short int l4;
983 if (((size_t) size) >= sizeof (l1))
987 size_of = sizeof (l1);
989 else if (((size_t) size) >= sizeof (l2))
993 size_of = sizeof (l2);
996 else if (((size_t) size) >= sizeof (l3))
1000 size_of = sizeof (l3);
1003 else if (((size_t) size) >= sizeof (l4))
1007 size_of = sizeof (l4);
1010 else if (((size_t) size) >= sizeof (l5))
1014 size_of = sizeof (l5);
1019 assert ("stumped by conversion from typeless!" == NULL);
1028 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
1029 res->text[size] = '\0';
1030 if (((size_t) size) <= size_of)
1032 int i = size_of - size;
1034 memcpy (res->text, p + i, size);
1035 for (; i > 0; ++p, --i)
1037 return FFEBAD_TRUNCATING_TYPELESS;
1041 int i = size - size_of;
1043 memset (res->text, 0, i);
1044 memcpy (res->text + i, p, size_of);
1049 return FFEBAD_TRUNCATING_TYPELESS;
1054 /* ffetarget_divide_complex1 -- Divide function
1058 #if FFETARGET_okCOMPLEX1
1060 ffetarget_divide_complex1 (ffetargetComplex1 *res, ffetargetComplex1 l,
1061 ffetargetComplex1 r)
1064 ffetargetReal1 tmp1, tmp2, tmp3, tmp4;
1066 bad = ffetarget_multiply_real1 (&tmp1, r.real, r.real);
1069 bad = ffetarget_multiply_real1 (&tmp2, r.imaginary, r.imaginary);
1072 bad = ffetarget_add_real1 (&tmp3, tmp1, tmp2);
1076 if (ffetarget_iszero_real1 (tmp3))
1078 ffetarget_real1_zero (&(res)->real);
1079 ffetarget_real1_zero (&(res)->imaginary);
1080 return FFEBAD_DIV_BY_ZERO;
1083 bad = ffetarget_multiply_real1 (&tmp1, l.real, r.real);
1086 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, r.imaginary);
1089 bad = ffetarget_add_real1 (&tmp4, tmp1, tmp2);
1092 bad = ffetarget_divide_real1 (&res->real, tmp4, tmp3);
1096 bad = ffetarget_multiply_real1 (&tmp1, r.real, l.imaginary);
1099 bad = ffetarget_multiply_real1 (&tmp2, l.real, r.imaginary);
1102 bad = ffetarget_subtract_real1 (&tmp4, tmp1, tmp2);
1105 bad = ffetarget_divide_real1 (&res->imaginary, tmp4, tmp3);
1111 /* ffetarget_divide_complex2 -- Divide function
1115 #if FFETARGET_okCOMPLEX2
1117 ffetarget_divide_complex2 (ffetargetComplex2 *res, ffetargetComplex2 l,
1118 ffetargetComplex2 r)
1121 ffetargetReal2 tmp1, tmp2, tmp3, tmp4;
1123 bad = ffetarget_multiply_real2 (&tmp1, r.real, r.real);
1126 bad = ffetarget_multiply_real2 (&tmp2, r.imaginary, r.imaginary);
1129 bad = ffetarget_add_real2 (&tmp3, tmp1, tmp2);
1133 if (ffetarget_iszero_real2 (tmp3))
1135 ffetarget_real2_zero (&(res)->real);
1136 ffetarget_real2_zero (&(res)->imaginary);
1137 return FFEBAD_DIV_BY_ZERO;
1140 bad = ffetarget_multiply_real2 (&tmp1, l.real, r.real);
1143 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, r.imaginary);
1146 bad = ffetarget_add_real2 (&tmp4, tmp1, tmp2);
1149 bad = ffetarget_divide_real2 (&res->real, tmp4, tmp3);
1153 bad = ffetarget_multiply_real2 (&tmp1, r.real, l.imaginary);
1156 bad = ffetarget_multiply_real2 (&tmp2, l.real, r.imaginary);
1159 bad = ffetarget_subtract_real2 (&tmp4, tmp1, tmp2);
1162 bad = ffetarget_divide_real2 (&res->imaginary, tmp4, tmp3);
1168 /* ffetarget_hollerith -- Convert token to a hollerith constant
1170 Always append a null byte to the end, in case this is wanted in
1171 a special case such as passing a string as a FORMAT or %REF.
1172 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
1173 because it isn't a "feature" that is self-documenting. Use the
1174 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
1178 ffetarget_hollerith (ffetargetHollerith *val, ffelexToken integer,
1181 val->length = ffelex_token_length (integer);
1182 val->text = malloc_new_kp (pool, "ffetargetHollerith", val->length + 1);
1183 memcpy (val->text, ffelex_token_text (integer), val->length);
1184 val->text[val->length] = '\0';
1189 /* ffetarget_integer_bad_magical -- Complain about a magical number
1191 Just calls ffebad with the arguments. */
1194 ffetarget_integer_bad_magical (ffelexToken t)
1196 ffebad_start (FFEBAD_BAD_MAGICAL);
1197 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1201 /* ffetarget_integer_bad_magical_binary -- Complain about a magical number
1203 Just calls ffebad with the arguments. */
1206 ffetarget_integer_bad_magical_binary (ffelexToken integer,
1209 ffebad_start (FFEBAD_BAD_MAGICAL_BINARY);
1210 ffebad_here (0, ffelex_token_where_line (integer),
1211 ffelex_token_where_column (integer));
1212 ffebad_here (1, ffelex_token_where_line (minus),
1213 ffelex_token_where_column (minus));
1217 /* ffetarget_integer_bad_magical_precedence -- Complain about a magical
1220 Just calls ffebad with the arguments. */
1223 ffetarget_integer_bad_magical_precedence (ffelexToken integer,
1225 ffelexToken higher_op)
1227 ffebad_start (FFEBAD_BAD_MAGICAL_PRECEDENCE);
1228 ffebad_here (0, ffelex_token_where_line (integer),
1229 ffelex_token_where_column (integer));
1230 ffebad_here (1, ffelex_token_where_line (uminus),
1231 ffelex_token_where_column (uminus));
1232 ffebad_here (2, ffelex_token_where_line (higher_op),
1233 ffelex_token_where_column (higher_op));
1237 /* ffetarget_integer_bad_magical_precedence_binary -- Complain...
1239 Just calls ffebad with the arguments. */
1242 ffetarget_integer_bad_magical_precedence_binary (ffelexToken integer,
1244 ffelexToken higher_op)
1246 ffebad_start (FFEBAD_BAD_MAGICAL_PRECEDENCE_BINARY);
1247 ffebad_here (0, ffelex_token_where_line (integer),
1248 ffelex_token_where_column (integer));
1249 ffebad_here (1, ffelex_token_where_line (minus),
1250 ffelex_token_where_column (minus));
1251 ffebad_here (2, ffelex_token_where_line (higher_op),
1252 ffelex_token_where_column (higher_op));
1256 /* ffetarget_integer1 -- Convert token to an integer
1260 Token use count not affected overall. */
1262 #if FFETARGET_okINTEGER1
1264 ffetarget_integer1 (ffetargetInteger1 *val, ffelexToken integer)
1266 ffetargetInteger1 x;
1270 assert (ffelex_token_type (integer) == FFELEX_typeNUMBER);
1272 p = ffelex_token_text (integer);
1275 /* Skip past leading zeros. */
1277 while (((c = *p) != '\0') && (c == '0'))
1280 /* Interpret rest of number. */
1284 if ((x == FFETARGET_integerALMOST_BIG_MAGICAL)
1285 && (c == '0' + FFETARGET_integerFINISH_BIG_MAGICAL)
1286 && (*(p + 1) == '\0'))
1288 *val = (ffetargetInteger1) FFETARGET_integerBIG_MAGICAL;
1291 else if (x == FFETARGET_integerALMOST_BIG_MAGICAL)
1293 if ((c > '0' + FFETARGET_integerFINISH_BIG_MAGICAL)
1294 || (*(p + 1) != '\0'))
1296 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1297 ffebad_here (0, ffelex_token_where_line (integer),
1298 ffelex_token_where_column (integer));
1304 else if (x > FFETARGET_integerALMOST_BIG_MAGICAL)
1306 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1307 ffebad_here (0, ffelex_token_where_line (integer),
1308 ffelex_token_where_column (integer));
1313 x = x * 10 + c - '0';
1322 /* ffetarget_integerbinary -- Convert token to a binary integer
1324 ffetarget_integerbinary x;
1325 if (ffetarget_integerdefault_8(&x,integer_token))
1328 Token use count not affected overall. */
1331 ffetarget_integerbinary (ffetargetIntegerDefault *val, ffelexToken integer)
1333 ffetargetIntegerDefault x;
1338 assert ((ffelex_token_type (integer) == FFELEX_typeNAME)
1339 || (ffelex_token_type (integer) == FFELEX_typeNUMBER));
1341 p = ffelex_token_text (integer);
1344 /* Skip past leading zeros. */
1346 while (((c = *p) != '\0') && (c == '0'))
1349 /* Interpret rest of number. */
1354 if ((c >= '0') && (c <= '1'))
1362 #if 0 /* Don't complain about signed overflow; just
1363 unsigned overflow. */
1364 if ((x == FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY)
1365 && (c == FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY)
1366 && (*(p + 1) == '\0'))
1368 *val = FFETARGET_integerBIG_OVERFLOW_BINARY;
1373 #if FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY == 0
1374 if ((x & FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY) != 0)
1376 if (x == FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY)
1378 if ((c > FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY)
1379 || (*(p + 1) != '\0'))
1381 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1382 ffebad_here (0, ffelex_token_where_line (integer),
1383 ffelex_token_where_column (integer));
1389 else if (x > FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY)
1392 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1393 ffebad_here (0, ffelex_token_where_line (integer),
1394 ffelex_token_where_column (integer));
1405 ffebad_start (FFEBAD_INVALID_BINARY_DIGIT);
1406 ffebad_here (0, ffelex_token_where_line (integer),
1407 ffelex_token_where_column (integer));
1415 /* ffetarget_integerhex -- Convert token to a hex integer
1417 ffetarget_integerhex x;
1418 if (ffetarget_integerdefault_8(&x,integer_token))
1421 Token use count not affected overall. */
1424 ffetarget_integerhex (ffetargetIntegerDefault *val, ffelexToken integer)
1426 ffetargetIntegerDefault x;
1431 assert ((ffelex_token_type (integer) == FFELEX_typeNAME)
1432 || (ffelex_token_type (integer) == FFELEX_typeNUMBER));
1434 p = ffelex_token_text (integer);
1437 /* Skip past leading zeros. */
1439 while (((c = *p) != '\0') && (c == '0'))
1442 /* Interpret rest of number. */
1447 if ((c >= 'A') && (c <= 'F'))
1449 else if ((c >= 'a') && (c <= 'f'))
1451 else if ((c >= '0') && (c <= '9'))
1459 #if 0 /* Don't complain about signed overflow; just
1460 unsigned overflow. */
1461 if ((x == FFETARGET_integerALMOST_BIG_OVERFLOW_HEX)
1462 && (c == FFETARGET_integerFINISH_BIG_OVERFLOW_HEX)
1463 && (*(p + 1) == '\0'))
1465 *val = FFETARGET_integerBIG_OVERFLOW_HEX;
1470 #if FFETARGET_integerFINISH_BIG_OVERFLOW_HEX == 0
1471 if (x >= FFETARGET_integerALMOST_BIG_OVERFLOW_HEX)
1473 if (x == FFETARGET_integerALMOST_BIG_OVERFLOW_HEX)
1475 if ((c > FFETARGET_integerFINISH_BIG_OVERFLOW_HEX)
1476 || (*(p + 1) != '\0'))
1478 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1479 ffebad_here (0, ffelex_token_where_line (integer),
1480 ffelex_token_where_column (integer));
1486 else if (x > FFETARGET_integerALMOST_BIG_OVERFLOW_HEX)
1489 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1490 ffebad_here (0, ffelex_token_where_line (integer),
1491 ffelex_token_where_column (integer));
1502 ffebad_start (FFEBAD_INVALID_HEX_DIGIT);
1503 ffebad_here (0, ffelex_token_where_line (integer),
1504 ffelex_token_where_column (integer));
1512 /* ffetarget_integeroctal -- Convert token to an octal integer
1514 ffetarget_integeroctal x;
1515 if (ffetarget_integerdefault_8(&x,integer_token))
1518 Token use count not affected overall. */
1521 ffetarget_integeroctal (ffetargetIntegerDefault *val, ffelexToken integer)
1523 ffetargetIntegerDefault x;
1528 assert ((ffelex_token_type (integer) == FFELEX_typeNAME)
1529 || (ffelex_token_type (integer) == FFELEX_typeNUMBER));
1531 p = ffelex_token_text (integer);
1534 /* Skip past leading zeros. */
1536 while (((c = *p) != '\0') && (c == '0'))
1539 /* Interpret rest of number. */
1544 if ((c >= '0') && (c <= '7'))
1552 #if 0 /* Don't complain about signed overflow; just
1553 unsigned overflow. */
1554 if ((x == FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL)
1555 && (c == FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL)
1556 && (*(p + 1) == '\0'))
1558 *val = FFETARGET_integerBIG_OVERFLOW_OCTAL;
1563 #if FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL == 0
1564 if (x >= FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL)
1566 if (x == FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL)
1568 if ((c > FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL)
1569 || (*(p + 1) != '\0'))
1571 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1572 ffebad_here (0, ffelex_token_where_line (integer),
1573 ffelex_token_where_column (integer));
1579 else if (x > FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL)
1582 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1583 ffebad_here (0, ffelex_token_where_line (integer),
1584 ffelex_token_where_column (integer));
1595 ffebad_start (FFEBAD_INVALID_OCTAL_DIGIT);
1596 ffebad_here (0, ffelex_token_where_line (integer),
1597 ffelex_token_where_column (integer));
1605 /* ffetarget_multiply_complex1 -- Multiply function
1609 #if FFETARGET_okCOMPLEX1
1611 ffetarget_multiply_complex1 (ffetargetComplex1 *res, ffetargetComplex1 l,
1612 ffetargetComplex1 r)
1615 ffetargetReal1 tmp1, tmp2;
1617 bad = ffetarget_multiply_real1 (&tmp1, l.real, r.real);
1620 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, r.imaginary);
1623 bad = ffetarget_subtract_real1 (&res->real, tmp1, tmp2);
1626 bad = ffetarget_multiply_real1 (&tmp1, l.imaginary, r.real);
1629 bad = ffetarget_multiply_real1 (&tmp2, l.real, r.imaginary);
1632 bad = ffetarget_add_real1 (&res->imaginary, tmp1, tmp2);
1638 /* ffetarget_multiply_complex2 -- Multiply function
1642 #if FFETARGET_okCOMPLEX2
1644 ffetarget_multiply_complex2 (ffetargetComplex2 *res, ffetargetComplex2 l,
1645 ffetargetComplex2 r)
1648 ffetargetReal2 tmp1, tmp2;
1650 bad = ffetarget_multiply_real2 (&tmp1, l.real, r.real);
1653 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, r.imaginary);
1656 bad = ffetarget_subtract_real2 (&res->real, tmp1, tmp2);
1659 bad = ffetarget_multiply_real2 (&tmp1, l.imaginary, r.real);
1662 bad = ffetarget_multiply_real2 (&tmp2, l.real, r.imaginary);
1665 bad = ffetarget_add_real2 (&res->imaginary, tmp1, tmp2);
1671 /* ffetarget_power_complexdefault_integerdefault -- Power function
1676 ffetarget_power_complexdefault_integerdefault (ffetargetComplexDefault *res,
1677 ffetargetComplexDefault l,
1678 ffetargetIntegerDefault r)
1681 ffetargetRealDefault tmp;
1682 ffetargetRealDefault tmp1;
1683 ffetargetRealDefault tmp2;
1684 ffetargetRealDefault two;
1686 if (ffetarget_iszero_real1 (l.real)
1687 && ffetarget_iszero_real1 (l.imaginary))
1689 ffetarget_real1_zero (&res->real);
1690 ffetarget_real1_zero (&res->imaginary);
1696 ffetarget_real1_one (&res->real);
1697 ffetarget_real1_zero (&res->imaginary);
1704 bad = ffetarget_multiply_real1 (&tmp1, l.real, l.real);
1707 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, l.imaginary);
1710 bad = ffetarget_add_real1 (&tmp, tmp1, tmp2);
1713 bad = ffetarget_divide_real1 (&l.real, l.real, tmp);
1716 bad = ffetarget_divide_real1 (&l.imaginary, l.imaginary, tmp);
1719 bad = ffetarget_uminus_real1 (&l.imaginary, l.imaginary);
1724 ffetarget_real1_two (&two);
1726 while ((r & 1) == 0)
1728 bad = ffetarget_multiply_real1 (&tmp1, l.real, l.real);
1731 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, l.imaginary);
1734 bad = ffetarget_subtract_real1 (&tmp, tmp1, tmp2);
1737 bad = ffetarget_multiply_real1 (&l.imaginary, l.real, l.imaginary);
1740 bad = ffetarget_multiply_real1 (&l.imaginary, l.imaginary, two);
1752 bad = ffetarget_multiply_real1 (&tmp1, l.real, l.real);
1755 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, l.imaginary);
1758 bad = ffetarget_subtract_real1 (&tmp, tmp1, tmp2);
1761 bad = ffetarget_multiply_real1 (&l.imaginary, l.real, l.imaginary);
1764 bad = ffetarget_multiply_real1 (&l.imaginary, l.imaginary, two);
1770 bad = ffetarget_multiply_real1 (&tmp1, res->real, l.real);
1773 bad = ffetarget_multiply_real1 (&tmp2, res->imaginary,
1777 bad = ffetarget_subtract_real1 (&tmp, tmp1, tmp2);
1780 bad = ffetarget_multiply_real1 (&tmp1, res->imaginary, l.real);
1783 bad = ffetarget_multiply_real1 (&tmp2, res->real, l.imaginary);
1786 bad = ffetarget_add_real1 (&res->imaginary, tmp1, tmp2);
1797 /* ffetarget_power_complexdouble_integerdefault -- Power function
1801 #if FFETARGET_okCOMPLEXDOUBLE
1803 ffetarget_power_complexdouble_integerdefault (ffetargetComplexDouble *res,
1804 ffetargetComplexDouble l, ffetargetIntegerDefault r)
1807 ffetargetRealDouble tmp;
1808 ffetargetRealDouble tmp1;
1809 ffetargetRealDouble tmp2;
1810 ffetargetRealDouble two;
1812 if (ffetarget_iszero_real2 (l.real)
1813 && ffetarget_iszero_real2 (l.imaginary))
1815 ffetarget_real2_zero (&res->real);
1816 ffetarget_real2_zero (&res->imaginary);
1822 ffetarget_real2_one (&res->real);
1823 ffetarget_real2_zero (&res->imaginary);
1830 bad = ffetarget_multiply_real2 (&tmp1, l.real, l.real);
1833 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, l.imaginary);
1836 bad = ffetarget_add_real2 (&tmp, tmp1, tmp2);
1839 bad = ffetarget_divide_real2 (&l.real, l.real, tmp);
1842 bad = ffetarget_divide_real2 (&l.imaginary, l.imaginary, tmp);
1845 bad = ffetarget_uminus_real2 (&l.imaginary, l.imaginary);
1850 ffetarget_real2_two (&two);
1852 while ((r & 1) == 0)
1854 bad = ffetarget_multiply_real2 (&tmp1, l.real, l.real);
1857 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, l.imaginary);
1860 bad = ffetarget_subtract_real2 (&tmp, tmp1, tmp2);
1863 bad = ffetarget_multiply_real2 (&l.imaginary, l.real, l.imaginary);
1866 bad = ffetarget_multiply_real2 (&l.imaginary, l.imaginary, two);
1878 bad = ffetarget_multiply_real2 (&tmp1, l.real, l.real);
1881 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, l.imaginary);
1884 bad = ffetarget_subtract_real2 (&tmp, tmp1, tmp2);
1887 bad = ffetarget_multiply_real2 (&l.imaginary, l.real, l.imaginary);
1890 bad = ffetarget_multiply_real2 (&l.imaginary, l.imaginary, two);
1896 bad = ffetarget_multiply_real2 (&tmp1, res->real, l.real);
1899 bad = ffetarget_multiply_real2 (&tmp2, res->imaginary,
1903 bad = ffetarget_subtract_real2 (&tmp, tmp1, tmp2);
1906 bad = ffetarget_multiply_real2 (&tmp1, res->imaginary, l.real);
1909 bad = ffetarget_multiply_real2 (&tmp2, res->real, l.imaginary);
1912 bad = ffetarget_add_real2 (&res->imaginary, tmp1, tmp2);
1924 /* ffetarget_power_integerdefault_integerdefault -- Power function
1929 ffetarget_power_integerdefault_integerdefault (ffetargetIntegerDefault *res,
1930 ffetargetIntegerDefault l, ffetargetIntegerDefault r)
1951 *res = ((-r) & 1) == 0 ? 1 : -1;
1957 while ((r & 1) == 0)
1977 /* ffetarget_power_realdefault_integerdefault -- Power function
1982 ffetarget_power_realdefault_integerdefault (ffetargetRealDefault *res,
1983 ffetargetRealDefault l, ffetargetIntegerDefault r)
1987 if (ffetarget_iszero_real1 (l))
1989 ffetarget_real1_zero (res);
1995 ffetarget_real1_one (res);
2001 ffetargetRealDefault one;
2003 ffetarget_real1_one (&one);
2005 bad = ffetarget_divide_real1 (&l, one, l);
2010 while ((r & 1) == 0)
2012 bad = ffetarget_multiply_real1 (&l, l, l);
2023 bad = ffetarget_multiply_real1 (&l, l, l);
2028 bad = ffetarget_multiply_real1 (res, *res, l);
2038 /* ffetarget_power_realdouble_integerdefault -- Power function
2043 ffetarget_power_realdouble_integerdefault (ffetargetRealDouble *res,
2044 ffetargetRealDouble l,
2045 ffetargetIntegerDefault r)
2049 if (ffetarget_iszero_real2 (l))
2051 ffetarget_real2_zero (res);
2057 ffetarget_real2_one (res);
2063 ffetargetRealDouble one;
2065 ffetarget_real2_one (&one);
2067 bad = ffetarget_divide_real2 (&l, one, l);
2072 while ((r & 1) == 0)
2074 bad = ffetarget_multiply_real2 (&l, l, l);
2085 bad = ffetarget_multiply_real2 (&l, l, l);
2090 bad = ffetarget_multiply_real2 (res, *res, l);
2100 /* ffetarget_print_binary -- Output typeless binary integer
2102 ffetargetTypeless val;
2103 ffetarget_typeless_binary(dmpout,val); */
2106 ffetarget_print_binary (FILE *f, ffetargetTypeless value)
2109 char digits[sizeof (value) * CHAR_BIT + 1];
2114 p = &digits[ARRAY_SIZE (digits) - 1];
2118 *--p = (value & 1) + '0';
2120 } while (value == 0);
2125 /* ffetarget_print_character1 -- Output character string
2127 ffetargetCharacter1 val;
2128 ffetarget_print_character1(dmpout,val); */
2131 ffetarget_print_character1 (FILE *f, ffetargetCharacter1 value)
2134 ffetargetCharacterSize i;
2136 fputc ('\'', dmpout);
2137 for (i = 0, p = value.text; i < value.length; ++i, ++p)
2138 ffetarget_print_char_ (f, *p);
2139 fputc ('\'', dmpout);
2142 /* ffetarget_print_hollerith -- Output hollerith string
2144 ffetargetHollerith val;
2145 ffetarget_print_hollerith(dmpout,val); */
2148 ffetarget_print_hollerith (FILE *f, ffetargetHollerith value)
2151 ffetargetHollerithSize i;
2153 fputc ('\'', dmpout);
2154 for (i = 0, p = value.text; i < value.length; ++i, ++p)
2155 ffetarget_print_char_ (f, *p);
2156 fputc ('\'', dmpout);
2159 /* ffetarget_print_octal -- Output typeless octal integer
2161 ffetargetTypeless val;
2162 ffetarget_print_octal(dmpout,val); */
2165 ffetarget_print_octal (FILE *f, ffetargetTypeless value)
2168 char digits[sizeof (value) * CHAR_BIT / 3 + 1];
2173 p = &digits[ARRAY_SIZE (digits) - 3];
2177 *--p = (value & 3) + '0';
2179 } while (value == 0);
2184 /* ffetarget_print_hex -- Output typeless hex integer
2186 ffetargetTypeless val;
2187 ffetarget_print_hex(dmpout,val); */
2190 ffetarget_print_hex (FILE *f, ffetargetTypeless value)
2193 char digits[sizeof (value) * CHAR_BIT / 4 + 1];
2194 static char hexdigits[16] = "0123456789ABCDEF";
2199 p = &digits[ARRAY_SIZE (digits) - 3];
2203 *--p = hexdigits[value & 4];
2205 } while (value == 0);
2210 /* ffetarget_real1 -- Convert token to a single-precision real number
2214 Pass NULL for any token not provided by the user, but a valid Fortran
2215 real number must be provided somehow. For example, it is ok for
2216 exponent_sign_token and exponent_digits_token to be NULL as long as
2217 exponent_token not only starts with "E" or "e" but also contains at least
2218 one digit following it. Token use counts not affected overall. */
2220 #if FFETARGET_okREAL1
2222 ffetarget_real1 (ffetargetReal1 *value, ffelexToken integer,
2223 ffelexToken decimal, ffelexToken fraction,
2224 ffelexToken exponent, ffelexToken exponent_sign,
2225 ffelexToken exponent_digits)
2227 size_t sz = 1; /* Allow room for '\0' byte at end. */
2228 char *ptr = &ffetarget_string_[0];
2232 #define dotok(x) if (x != NULL) ++sz;
2233 #define dotoktxt(x) if (x != NULL) sz += ffelex_token_length(x)
2237 dotoktxt (fraction);
2238 dotoktxt (exponent);
2239 dotok (exponent_sign);
2240 dotoktxt (exponent_digits);
2245 if (sz > ARRAY_SIZE (ffetarget_string_))
2246 p = ptr = (char *) malloc_new_ks (malloc_pool_image (), "ffetarget_real1",
2249 #define dotoktxt(x) if (x != NULL) \
2251 for (q = ffelex_token_text(x); *q != '\0'; ++q) \
2257 if (decimal != NULL)
2260 dotoktxt (fraction);
2261 dotoktxt (exponent);
2263 if (exponent_sign != NULL)
2265 if (ffelex_token_type (exponent_sign) == FFELEX_typePLUS)
2269 assert (ffelex_token_type (exponent_sign) == FFELEX_typeMINUS);
2274 dotoktxt (exponent_digits);
2280 ffetarget_make_real1 (value,
2281 FFETARGET_ATOF_ (ptr,
2284 if (sz > ARRAY_SIZE (ffetarget_string_))
2285 malloc_kill_ks (malloc_pool_image (), ptr, sz);
2291 /* ffetarget_real2 -- Convert token to a single-precision real number
2295 Pass NULL for any token not provided by the user, but a valid Fortran
2296 real number must be provided somehow. For example, it is ok for
2297 exponent_sign_token and exponent_digits_token to be NULL as long as
2298 exponent_token not only starts with "E" or "e" but also contains at least
2299 one digit following it. Token use counts not affected overall. */
2301 #if FFETARGET_okREAL2
2303 ffetarget_real2 (ffetargetReal2 *value, ffelexToken integer,
2304 ffelexToken decimal, ffelexToken fraction,
2305 ffelexToken exponent, ffelexToken exponent_sign,
2306 ffelexToken exponent_digits)
2308 size_t sz = 1; /* Allow room for '\0' byte at end. */
2309 char *ptr = &ffetarget_string_[0];
2313 #define dotok(x) if (x != NULL) ++sz;
2314 #define dotoktxt(x) if (x != NULL) sz += ffelex_token_length(x)
2318 dotoktxt (fraction);
2319 dotoktxt (exponent);
2320 dotok (exponent_sign);
2321 dotoktxt (exponent_digits);
2326 if (sz > ARRAY_SIZE (ffetarget_string_))
2327 p = ptr = (char *) malloc_new_ks (malloc_pool_image (), "ffetarget_real1", sz);
2329 #define dotoktxt(x) if (x != NULL) \
2331 for (q = ffelex_token_text(x); *q != '\0'; ++q) \
2334 #define dotoktxtexp(x) if (x != NULL) \
2337 for (q = ffelex_token_text(x) + 1; *q != '\0'; ++q) \
2343 if (decimal != NULL)
2346 dotoktxt (fraction);
2347 dotoktxtexp (exponent);
2349 if (exponent_sign != NULL)
2351 if (ffelex_token_type (exponent_sign) == FFELEX_typePLUS)
2355 assert (ffelex_token_type (exponent_sign) == FFELEX_typeMINUS);
2360 dotoktxt (exponent_digits);
2366 ffetarget_make_real2 (value,
2367 FFETARGET_ATOF_ (ptr,
2370 if (sz > ARRAY_SIZE (ffetarget_string_))
2371 malloc_kill_ks (malloc_pool_image (), ptr, sz);
2378 ffetarget_typeless_binary (ffetargetTypeless *xvalue, ffelexToken token)
2382 ffetargetTypeless value = 0;
2383 ffetargetTypeless new_value = 0;
2384 bool bad_digit = FALSE;
2385 bool overflow = FALSE;
2387 p = ffelex_token_text (token);
2389 for (c = *p; c != '\0'; c = *++p)
2392 if ((new_value >> 1) != value)
2395 new_value += c - '0';
2403 ffebad_start (FFEBAD_INVALID_TYPELESS_BINARY_DIGIT);
2404 ffebad_here (0, ffelex_token_where_line (token),
2405 ffelex_token_where_column (token));
2410 ffebad_start (FFEBAD_TYPELESS_OVERFLOW);
2411 ffebad_here (0, ffelex_token_where_line (token),
2412 ffelex_token_where_column (token));
2418 return !bad_digit && !overflow;
2422 ffetarget_typeless_octal (ffetargetTypeless *xvalue, ffelexToken token)
2426 ffetargetTypeless value = 0;
2427 ffetargetTypeless new_value = 0;
2428 bool bad_digit = FALSE;
2429 bool overflow = FALSE;
2431 p = ffelex_token_text (token);
2433 for (c = *p; c != '\0'; c = *++p)
2436 if ((new_value >> 3) != value)
2439 new_value += c - '0';
2447 ffebad_start (FFEBAD_INVALID_TYPELESS_OCTAL_DIGIT);
2448 ffebad_here (0, ffelex_token_where_line (token),
2449 ffelex_token_where_column (token));
2454 ffebad_start (FFEBAD_TYPELESS_OVERFLOW);
2455 ffebad_here (0, ffelex_token_where_line (token),
2456 ffelex_token_where_column (token));
2462 return !bad_digit && !overflow;
2466 ffetarget_typeless_hex (ffetargetTypeless *xvalue, ffelexToken token)
2470 ffetargetTypeless value = 0;
2471 ffetargetTypeless new_value = 0;
2472 bool bad_digit = FALSE;
2473 bool overflow = FALSE;
2475 p = ffelex_token_text (token);
2477 for (c = *p; c != '\0'; c = *++p)
2480 if ((new_value >> 4) != value)
2483 new_value += c - '0';
2484 else if ((c >= 'A') && (c <= 'F'))
2485 new_value += c - 'A' + 10;
2486 else if ((c >= 'a') && (c <= 'f'))
2487 new_value += c - 'a' + 10;
2495 ffebad_start (FFEBAD_INVALID_TYPELESS_HEX_DIGIT);
2496 ffebad_here (0, ffelex_token_where_line (token),
2497 ffelex_token_where_column (token));
2502 ffebad_start (FFEBAD_TYPELESS_OVERFLOW);
2503 ffebad_here (0, ffelex_token_where_line (token),
2504 ffelex_token_where_column (token));
2510 return !bad_digit && !overflow;
2514 ffetarget_verify_character1 (mallocPool pool, ffetargetCharacter1 val)
2516 if (val.length != 0)
2517 malloc_verify_kp (pool, val.text, val.length);
2520 /* This is like memcpy. It is needed because some systems' header files
2521 don't declare memcpy as a function but instead
2522 "#define memcpy(to,from,len) something". */
2525 ffetarget_memcpy_ (void *dst, void *src, size_t len)
2527 return (void *) memcpy (dst, src, len);
2530 /* ffetarget_num_digits_ -- Determine number of non-space characters in token
2532 ffetarget_num_digits_(token);
2534 All non-spaces are assumed to be binary, octal, or hex digits. */
2537 ffetarget_num_digits_ (ffelexToken token)
2542 switch (ffelex_token_type (token))
2544 case FFELEX_typeNAME:
2545 case FFELEX_typeNUMBER:
2546 return ffelex_token_length (token);
2548 case FFELEX_typeCHARACTER:
2550 for (c = ffelex_token_text (token); *c != '\0'; ++c)
2558 assert ("weird token" == NULL);