* cfgloop.c (flow_loop_entry_edges_find): Fix typo.
[official-gcc.git] / gcc / f / target.c
blob11fb0b1d83bb18849aca87dc5995612aa44cd900
1 /* target.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
3 Contributed by James Craig Burley.
5 This file is part of GNU Fortran.
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
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
20 02111-1307, USA.
22 Related Modules:
23 None
25 Description:
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
48 manageable.
50 A nonobvious change to ffetarget would be if the target machine was
51 not a 2's-complement machine. Any item with the word "magical" (case-
52 insensitive) in the FFE's source code (at least) indicates an assumption
53 that a 2's-complement machine is the target, and thus that there exists
54 a magnitude that can be represented as a negative number but not as
55 a positive number. It is possible that this situation can be dealt
56 with by changing only ffetarget, for example, on a 1's-complement
57 machine, perhaps #defineing ffetarget_constant_is_magical to simply
58 FALSE along with making the appropriate changes in ffetarget's number
59 parsing functions would be sufficient to effectively "comment out" code
60 in places like ffeexpr that do certain magical checks. But it is
61 possible there are other 2's-complement dependencies lurking in the
62 FFE (as possibly is true of any large program); if you find any, please
63 report them so we can replace them with dependencies on ffetarget
64 instead.
66 Modifications:
69 /* Include files. */
71 #include "proj.h"
72 #include "glimits.h"
73 #include "target.h"
74 #include "bad.h"
75 #include "info.h"
76 #include "lex.h"
77 #include "malloc.h"
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))
108 #else
109 #define FFETARGET_ATOF_(p,m) atof ((p))
110 #endif
113 /* ffetarget_print_char_ -- Print a single character (in apostrophe context)
115 See prototype.
117 Outputs char so it prints or is escaped C style. */
119 static void
120 ffetarget_print_char_ (FILE *f, unsigned char c)
122 switch (c)
124 case '\\':
125 fputs ("\\\\", f);
126 break;
128 case '\'':
129 fputs ("\\\'", f);
130 break;
132 default:
133 if (ISPRINT (c))
134 fputc (c, f);
135 else
136 fprintf (f, "\\%03o", (unsigned int) c);
137 break;
141 /* ffetarget_aggregate_info -- Determine type for aggregate storage area
143 See prototype.
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
148 machines).
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
157 types mixed in.
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. */
165 void
166 ffetarget_aggregate_info (ffeinfoBasictype *ebt, ffeinfoKindtype *ekt,
167 ffetargetAlign *units, ffeinfoBasictype abt,
168 ffeinfoKindtype akt)
170 ffetype type;
172 if ((abt == FFEINFO_basictypeNONE) || (abt == FFEINFO_basictypeANY)
173 || (akt == FFEINFO_kindtypeNONE))
175 *ebt = FFEINFO_basictypeCHARACTER;
176 *ekt = FFEINFO_kindtypeCHARACTERDEFAULT;
178 else
180 *ebt = abt;
181 *ekt = akt;
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
192 See prototype.
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. */
201 ffetargetAlign
202 ffetarget_align (ffetargetAlign *updated_alignment,
203 ffetargetAlign *updated_modulo, ffetargetOffset offset,
204 ffetargetAlign alignment, ffetargetAlign modulo)
206 ffetargetAlign pad;
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. */
214 ffetargetAlign i;
215 ffetargetAlign j;
217 assert (alignment > 0);
218 assert (*updated_alignment > 0);
220 assert (*updated_modulo < *updated_alignment);
221 assert (modulo < alignment);
223 /* The easy case: similar alignment requirements. */
224 if (*updated_alignment == alignment)
226 if (modulo > *updated_modulo)
227 pad = alignment - (modulo - *updated_modulo);
228 else
229 pad = *updated_modulo - modulo;
230 if (offset < 0)
231 /* De-negatize offset, since % wouldn't do the expected thing. */
232 offset = alignment - ((- offset) % alignment);
233 pad = (offset + pad) % alignment;
234 if (pad != 0)
235 pad = alignment - pad;
236 return pad;
239 /* Sigh, find LCM (Least Common Multiple) for the two alignment factors. */
241 for (ua = *updated_alignment, ucnt = 1;
242 ua % alignment != 0;
243 ua += *updated_alignment)
244 ++ucnt;
246 cnt = ua / alignment;
248 if (offset < 0)
249 /* De-negatize offset, since % wouldn't do the expected thing. */
250 offset = ua - ((- offset) % ua);
252 /* Set to largest value. */
253 min_pad = ~(ffetargetAlign) 0;
255 /* Find all combinations of modulo values the two alignment requirements
256 have; pick the combination that results in the smallest padding
257 requirement. Of course, if a zero-pad requirement is encountered, just
258 use that one. */
260 for (um = *updated_modulo, i = 0; i < ucnt; um += *updated_alignment, ++i)
262 for (m = modulo, j = 0; j < cnt; m += alignment, ++j)
264 /* This code is similar to the "easy case" code above. */
265 if (m > um)
266 pad = ua - (m - um);
267 else
268 pad = um - m;
269 pad = (offset + pad) % ua;
270 if (pad == 0)
272 /* A zero pad means we've got something useful. */
273 *updated_alignment = ua;
274 *updated_modulo = um;
275 return 0;
277 pad = ua - pad;
278 if (pad < min_pad)
279 { /* New minimum padding value. */
280 min_pad = pad;
281 min_m = um;
286 *updated_alignment = ua;
287 *updated_modulo = min_m;
288 return min_pad;
291 /* Always append a null byte to the end, in case this is wanted in
292 a special case such as passing a string as a FORMAT or %REF.
293 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
294 because it isn't a "feature" that is self-documenting. Use the
295 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
296 in the code. */
298 #if FFETARGET_okCHARACTER1
299 bool
300 ffetarget_character1 (ffetargetCharacter1 *val, ffelexToken character,
301 mallocPool pool)
303 val->length = ffelex_token_length (character);
304 if (val->length == 0)
305 val->text = NULL;
306 else
308 val->text = malloc_new_kp (pool, "ffetargetCharacter1", val->length + 1);
309 memcpy (val->text, ffelex_token_text (character), val->length);
310 val->text[val->length] = '\0';
313 return TRUE;
316 #endif
317 /* Produce orderable comparison between two constants
319 Compare lengths, if equal then use memcmp. */
321 #if FFETARGET_okCHARACTER1
323 ffetarget_cmp_character1 (ffetargetCharacter1 l, ffetargetCharacter1 r)
325 if (l.length < r.length)
326 return -1;
327 if (l.length > r.length)
328 return 1;
329 if (l.length == 0)
330 return 0;
331 return memcmp (l.text, r.text, l.length);
334 #endif
335 /* ffetarget_concatenate_character1 -- Perform CONCAT op on two constants
337 Always append a null byte to the end, in case this is wanted in
338 a special case such as passing a string as a FORMAT or %REF.
339 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
340 because it isn't a "feature" that is self-documenting. Use the
341 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
342 in the code. */
344 #if FFETARGET_okCHARACTER1
345 ffebad
346 ffetarget_concatenate_character1 (ffetargetCharacter1 *res,
347 ffetargetCharacter1 l, ffetargetCharacter1 r, mallocPool pool,
348 ffetargetCharacterSize *len)
350 res->length = *len = l.length + r.length;
351 if (*len == 0)
352 res->text = NULL;
353 else
355 res->text = malloc_new_kp (pool, "ffetargetCharacter1(CONCAT)", *len + 1);
356 if (l.length != 0)
357 memcpy (res->text, l.text, l.length);
358 if (r.length != 0)
359 memcpy (res->text + l.length, r.text, r.length);
360 res->text[*len] = '\0';
363 return FFEBAD;
366 #endif
367 /* ffetarget_eq_character1 -- Perform relational comparison on char constants
369 Compare lengths, if equal then use memcmp. */
371 #if FFETARGET_okCHARACTER1
372 ffebad
373 ffetarget_eq_character1 (bool *res, ffetargetCharacter1 l,
374 ffetargetCharacter1 r)
376 assert (l.length == r.length);
377 *res = (memcmp (l.text, r.text, l.length) == 0);
378 return FFEBAD;
381 #endif
382 /* ffetarget_le_character1 -- Perform relational comparison on char constants
384 Compare lengths, if equal then use memcmp. */
386 #if FFETARGET_okCHARACTER1
387 ffebad
388 ffetarget_le_character1 (bool *res, ffetargetCharacter1 l,
389 ffetargetCharacter1 r)
391 assert (l.length == r.length);
392 *res = (memcmp (l.text, r.text, l.length) <= 0);
393 return FFEBAD;
396 #endif
397 /* ffetarget_lt_character1 -- Perform relational comparison on char constants
399 Compare lengths, if equal then use memcmp. */
401 #if FFETARGET_okCHARACTER1
402 ffebad
403 ffetarget_lt_character1 (bool *res, ffetargetCharacter1 l,
404 ffetargetCharacter1 r)
406 assert (l.length == r.length);
407 *res = (memcmp (l.text, r.text, l.length) < 0);
408 return FFEBAD;
411 #endif
412 /* ffetarget_ge_character1 -- Perform relational comparison on char constants
414 Compare lengths, if equal then use memcmp. */
416 #if FFETARGET_okCHARACTER1
417 ffebad
418 ffetarget_ge_character1 (bool *res, ffetargetCharacter1 l,
419 ffetargetCharacter1 r)
421 assert (l.length == r.length);
422 *res = (memcmp (l.text, r.text, l.length) >= 0);
423 return FFEBAD;
426 #endif
427 /* ffetarget_gt_character1 -- Perform relational comparison on char constants
429 Compare lengths, if equal then use memcmp. */
431 #if FFETARGET_okCHARACTER1
432 ffebad
433 ffetarget_gt_character1 (bool *res, ffetargetCharacter1 l,
434 ffetargetCharacter1 r)
436 assert (l.length == r.length);
437 *res = (memcmp (l.text, r.text, l.length) > 0);
438 return FFEBAD;
440 #endif
442 #if FFETARGET_okCHARACTER1
443 bool
444 ffetarget_iszero_character1 (ffetargetCharacter1 constant)
446 ffetargetCharacterSize i;
448 for (i = 0; i < constant.length; ++i)
449 if (constant.text[i] != 0)
450 return FALSE;
451 return TRUE;
453 #endif
455 bool
456 ffetarget_iszero_hollerith (ffetargetHollerith constant)
458 ffetargetHollerithSize i;
460 for (i = 0; i < constant.length; ++i)
461 if (constant.text[i] != 0)
462 return FALSE;
463 return TRUE;
466 /* ffetarget_layout -- Do storage requirement analysis for entity
468 Return the alignment/modulo requirements along with the size, given the
469 data type info and the number of elements an array (1 for a scalar). */
471 void
472 ffetarget_layout (const char *error_text UNUSED, ffetargetAlign *alignment,
473 ffetargetAlign *modulo, ffetargetOffset *size,
474 ffeinfoBasictype bt, ffeinfoKindtype kt,
475 ffetargetCharacterSize charsize,
476 ffetargetIntegerDefault num_elements)
478 bool ok; /* For character type. */
479 ffetargetOffset numele; /* Converted from num_elements. */
480 ffetype type;
482 type = ffeinfo_type (bt, kt);
483 assert (type != NULL);
485 *alignment = ffetype_alignment (type);
486 *modulo = ffetype_modulo (type);
487 if (bt == FFEINFO_basictypeCHARACTER)
489 ok = ffetarget_offset_charsize (size, charsize, ffetype_size (type));
490 #ifdef ffetarget_offset_overflow
491 if (!ok)
492 ffetarget_offset_overflow (error_text);
493 #endif
495 else
496 *size = ffetype_size (type);
498 if ((num_elements < 0)
499 || !ffetarget_offset (&numele, num_elements)
500 || !ffetarget_offset_multiply (size, *size, numele))
502 ffetarget_offset_overflow (error_text);
503 *alignment = 1;
504 *modulo = 0;
505 *size = 0;
509 /* ffetarget_ne_character1 -- Perform relational comparison on char constants
511 Compare lengths, if equal then use memcmp. */
513 #if FFETARGET_okCHARACTER1
514 ffebad
515 ffetarget_ne_character1 (bool *res, ffetargetCharacter1 l,
516 ffetargetCharacter1 r)
518 assert (l.length == r.length);
519 *res = (memcmp (l.text, r.text, l.length) != 0);
520 return FFEBAD;
523 #endif
524 /* ffetarget_substr_character1 -- Perform SUBSTR op on three constants
526 Always append a null byte to the end, in case this is wanted in
527 a special case such as passing a string as a FORMAT or %REF.
528 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
529 because it isn't a "feature" that is self-documenting. Use the
530 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
531 in the code. */
533 #if FFETARGET_okCHARACTER1
534 ffebad
535 ffetarget_substr_character1 (ffetargetCharacter1 *res,
536 ffetargetCharacter1 l,
537 ffetargetCharacterSize first,
538 ffetargetCharacterSize last, mallocPool pool,
539 ffetargetCharacterSize *len)
541 if (last < first)
543 res->length = *len = 0;
544 res->text = NULL;
546 else
548 res->length = *len = last - first + 1;
549 res->text = malloc_new_kp (pool, "ffetargetCharacter1(SUBSTR)", *len + 1);
550 memcpy (res->text, l.text + first - 1, *len);
551 res->text[*len] = '\0';
554 return FFEBAD;
557 #endif
558 /* ffetarget_cmp_hollerith -- Produce orderable comparison between two
559 constants
561 Compare lengths, if equal then use memcmp. */
564 ffetarget_cmp_hollerith (ffetargetHollerith l, ffetargetHollerith r)
566 if (l.length < r.length)
567 return -1;
568 if (l.length > r.length)
569 return 1;
570 return memcmp (l.text, r.text, l.length);
573 ffebad
574 ffetarget_convert_any_character1_ (char *res, size_t size,
575 ffetargetCharacter1 l)
577 if (size <= (size_t) l.length)
579 char *p;
580 ffetargetCharacterSize i;
582 memcpy (res, l.text, size);
583 for (p = &l.text[0] + size, i = l.length - size;
584 i > 0;
585 ++p, --i)
586 if (*p != ' ')
587 return FFEBAD_TRUNCATING_CHARACTER;
589 else
591 memcpy (res, l.text, size);
592 memset (res + l.length, ' ', size - l.length);
595 return FFEBAD;
598 ffebad
599 ffetarget_convert_any_hollerith_ (char *res, size_t size,
600 ffetargetHollerith l)
602 if (size <= (size_t) l.length)
604 char *p;
605 ffetargetCharacterSize i;
607 memcpy (res, l.text, size);
608 for (p = &l.text[0] + size, i = l.length - size;
609 i > 0;
610 ++p, --i)
611 if (*p != ' ')
612 return FFEBAD_TRUNCATING_HOLLERITH;
614 else
616 memcpy (res, l.text, size);
617 memset (res + l.length, ' ', size - l.length);
620 return FFEBAD;
623 ffebad
624 ffetarget_convert_any_typeless_ (char *res, size_t size,
625 ffetargetTypeless l)
627 unsigned long long int l1;
628 unsigned long int l2;
629 unsigned int l3;
630 unsigned short int l4;
631 unsigned char l5;
632 size_t size_of;
633 char *p;
635 if (size >= sizeof (l1))
637 l1 = l;
638 p = (char *) &l1;
639 size_of = sizeof (l1);
641 else if (size >= sizeof (l2))
643 l2 = l;
644 p = (char *) &l2;
645 size_of = sizeof (l2);
646 l1 = l2;
648 else if (size >= sizeof (l3))
650 l3 = l;
651 p = (char *) &l3;
652 size_of = sizeof (l3);
653 l1 = l3;
655 else if (size >= sizeof (l4))
657 l4 = l;
658 p = (char *) &l4;
659 size_of = sizeof (l4);
660 l1 = l4;
662 else if (size >= sizeof (l5))
664 l5 = l;
665 p = (char *) &l5;
666 size_of = sizeof (l5);
667 l1 = l5;
669 else
671 assert ("stumped by conversion from typeless!" == NULL);
672 abort ();
675 if (size <= size_of)
677 int i = size_of - size;
679 memcpy (res, p + i, size);
680 for (; i > 0; ++p, --i)
681 if (*p != '\0')
682 return FFEBAD_TRUNCATING_TYPELESS;
684 else
686 int i = size - size_of;
688 memset (res, 0, i);
689 memcpy (res + i, p, size_of);
692 if (l1 != l)
693 return FFEBAD_TRUNCATING_TYPELESS;
694 return FFEBAD;
697 /* Always append a null byte to the end, in case this is wanted in
698 a special case such as passing a string as a FORMAT or %REF.
699 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
700 because it isn't a "feature" that is self-documenting. Use the
701 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
702 in the code. */
704 #if FFETARGET_okCHARACTER1
705 ffebad
706 ffetarget_convert_character1_character1 (ffetargetCharacter1 *res,
707 ffetargetCharacterSize size,
708 ffetargetCharacter1 l,
709 mallocPool pool)
711 res->length = size;
712 if (size == 0)
713 res->text = NULL;
714 else
716 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
717 if (size <= l.length)
718 memcpy (res->text, l.text, size);
719 else
721 memcpy (res->text, l.text, l.length);
722 memset (res->text + l.length, ' ', size - l.length);
724 res->text[size] = '\0';
727 return FFEBAD;
730 #endif
732 /* Always append a null byte to the end, in case this is wanted in
733 a special case such as passing a string as a FORMAT or %REF.
734 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
735 because it isn't a "feature" that is self-documenting. Use the
736 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
737 in the code. */
739 #if FFETARGET_okCHARACTER1
740 ffebad
741 ffetarget_convert_character1_hollerith (ffetargetCharacter1 *res,
742 ffetargetCharacterSize size,
743 ffetargetHollerith l, mallocPool pool)
745 res->length = size;
746 if (size == 0)
747 res->text = NULL;
748 else
750 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
751 res->text[size] = '\0';
752 if (size <= l.length)
754 char *p;
755 ffetargetCharacterSize i;
757 memcpy (res->text, l.text, size);
758 for (p = &l.text[0] + size, i = l.length - size;
759 i > 0;
760 ++p, --i)
761 if (*p != ' ')
762 return FFEBAD_TRUNCATING_HOLLERITH;
764 else
766 memcpy (res->text, l.text, l.length);
767 memset (res->text + l.length, ' ', size - l.length);
771 return FFEBAD;
774 #endif
775 /* ffetarget_convert_character1_integer4 -- Raw conversion.
777 Always append a null byte to the end, in case this is wanted in
778 a special case such as passing a string as a FORMAT or %REF.
779 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
780 because it isn't a "feature" that is self-documenting. Use the
781 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
782 in the code. */
784 #if FFETARGET_okCHARACTER1
785 ffebad
786 ffetarget_convert_character1_integer4 (ffetargetCharacter1 *res,
787 ffetargetCharacterSize size,
788 ffetargetInteger4 l, mallocPool pool)
790 long long int l1;
791 long int l2;
792 int l3;
793 short int l4;
794 char l5;
795 size_t size_of;
796 char *p;
798 if (((size_t) size) >= sizeof (l1))
800 l1 = l;
801 p = (char *) &l1;
802 size_of = sizeof (l1);
804 else if (((size_t) size) >= sizeof (l2))
806 l2 = l;
807 p = (char *) &l2;
808 size_of = sizeof (l2);
809 l1 = l2;
811 else if (((size_t) size) >= sizeof (l3))
813 l3 = l;
814 p = (char *) &l3;
815 size_of = sizeof (l3);
816 l1 = l3;
818 else if (((size_t) size) >= sizeof (l4))
820 l4 = l;
821 p = (char *) &l4;
822 size_of = sizeof (l4);
823 l1 = l4;
825 else if (((size_t) size) >= sizeof (l5))
827 l5 = l;
828 p = (char *) &l5;
829 size_of = sizeof (l5);
830 l1 = l5;
832 else
834 assert ("stumped by conversion from integer1!" == NULL);
835 abort ();
838 res->length = size;
839 if (size == 0)
840 res->text = NULL;
841 else
843 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
844 res->text[size] = '\0';
845 if (((size_t) size) <= size_of)
847 int i = size_of - size;
849 memcpy (res->text, p + i, size);
850 for (; i > 0; ++p, --i)
851 if (*p != 0)
852 return FFEBAD_TRUNCATING_NUMERIC;
854 else
856 int i = size - size_of;
858 memset (res->text, 0, i);
859 memcpy (res->text + i, p, size_of);
863 if (l1 != l)
864 return FFEBAD_TRUNCATING_NUMERIC;
865 return FFEBAD;
868 #endif
869 /* ffetarget_convert_character1_logical4 -- Raw conversion.
871 Always append a null byte to the end, in case this is wanted in
872 a special case such as passing a string as a FORMAT or %REF.
873 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
874 because it isn't a "feature" that is self-documenting. Use the
875 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
876 in the code. */
878 #if FFETARGET_okCHARACTER1
879 ffebad
880 ffetarget_convert_character1_logical4 (ffetargetCharacter1 *res,
881 ffetargetCharacterSize size,
882 ffetargetLogical4 l, mallocPool pool)
884 long long int l1;
885 long int l2;
886 int l3;
887 short int l4;
888 char l5;
889 size_t size_of;
890 char *p;
892 if (((size_t) size) >= sizeof (l1))
894 l1 = l;
895 p = (char *) &l1;
896 size_of = sizeof (l1);
898 else if (((size_t) size) >= sizeof (l2))
900 l2 = l;
901 p = (char *) &l2;
902 size_of = sizeof (l2);
903 l1 = l2;
905 else if (((size_t) size) >= sizeof (l3))
907 l3 = l;
908 p = (char *) &l3;
909 size_of = sizeof (l3);
910 l1 = l3;
912 else if (((size_t) size) >= sizeof (l4))
914 l4 = l;
915 p = (char *) &l4;
916 size_of = sizeof (l4);
917 l1 = l4;
919 else if (((size_t) size) >= sizeof (l5))
921 l5 = l;
922 p = (char *) &l5;
923 size_of = sizeof (l5);
924 l1 = l5;
926 else
928 assert ("stumped by conversion from logical1!" == NULL);
929 abort ();
932 res->length = size;
933 if (size == 0)
934 res->text = NULL;
935 else
937 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
938 res->text[size] = '\0';
939 if (((size_t) size) <= size_of)
941 int i = size_of - size;
943 memcpy (res->text, p + i, size);
944 for (; i > 0; ++p, --i)
945 if (*p != 0)
946 return FFEBAD_TRUNCATING_NUMERIC;
948 else
950 int i = size - size_of;
952 memset (res->text, 0, i);
953 memcpy (res->text + i, p, size_of);
957 if (l1 != l)
958 return FFEBAD_TRUNCATING_NUMERIC;
959 return FFEBAD;
962 #endif
963 /* ffetarget_convert_character1_typeless -- Raw conversion.
965 Always append a null byte to the end, in case this is wanted in
966 a special case such as passing a string as a FORMAT or %REF.
967 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
968 because it isn't a "feature" that is self-documenting. Use the
969 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
970 in the code. */
972 #if FFETARGET_okCHARACTER1
973 ffebad
974 ffetarget_convert_character1_typeless (ffetargetCharacter1 *res,
975 ffetargetCharacterSize size,
976 ffetargetTypeless l, mallocPool pool)
978 unsigned long long int l1;
979 unsigned long int l2;
980 unsigned int l3;
981 unsigned short int l4;
982 unsigned char l5;
983 size_t size_of;
984 char *p;
986 if (((size_t) size) >= sizeof (l1))
988 l1 = l;
989 p = (char *) &l1;
990 size_of = sizeof (l1);
992 else if (((size_t) size) >= sizeof (l2))
994 l2 = l;
995 p = (char *) &l2;
996 size_of = sizeof (l2);
997 l1 = l2;
999 else if (((size_t) size) >= sizeof (l3))
1001 l3 = l;
1002 p = (char *) &l3;
1003 size_of = sizeof (l3);
1004 l1 = l3;
1006 else if (((size_t) size) >= sizeof (l4))
1008 l4 = l;
1009 p = (char *) &l4;
1010 size_of = sizeof (l4);
1011 l1 = l4;
1013 else if (((size_t) size) >= sizeof (l5))
1015 l5 = l;
1016 p = (char *) &l5;
1017 size_of = sizeof (l5);
1018 l1 = l5;
1020 else
1022 assert ("stumped by conversion from typeless!" == NULL);
1023 abort ();
1026 res->length = size;
1027 if (size == 0)
1028 res->text = NULL;
1029 else
1031 res->text = malloc_new_kp (pool, "FFETARGET cvt char1", size + 1);
1032 res->text[size] = '\0';
1033 if (((size_t) size) <= size_of)
1035 int i = size_of - size;
1037 memcpy (res->text, p + i, size);
1038 for (; i > 0; ++p, --i)
1039 if (*p != 0)
1040 return FFEBAD_TRUNCATING_TYPELESS;
1042 else
1044 int i = size - size_of;
1046 memset (res->text, 0, i);
1047 memcpy (res->text + i, p, size_of);
1051 if (l1 != l)
1052 return FFEBAD_TRUNCATING_TYPELESS;
1053 return FFEBAD;
1056 #endif
1057 /* ffetarget_divide_complex1 -- Divide function
1059 See prototype. */
1061 #if FFETARGET_okCOMPLEX1
1062 ffebad
1063 ffetarget_divide_complex1 (ffetargetComplex1 *res, ffetargetComplex1 l,
1064 ffetargetComplex1 r)
1066 ffebad bad;
1067 ffetargetReal1 tmp1, tmp2, tmp3, tmp4;
1069 bad = ffetarget_multiply_real1 (&tmp1, r.real, r.real);
1070 if (bad != FFEBAD)
1071 return bad;
1072 bad = ffetarget_multiply_real1 (&tmp2, r.imaginary, r.imaginary);
1073 if (bad != FFEBAD)
1074 return bad;
1075 bad = ffetarget_add_real1 (&tmp3, tmp1, tmp2);
1076 if (bad != FFEBAD)
1077 return bad;
1079 if (ffetarget_iszero_real1 (tmp3))
1081 ffetarget_real1_zero (&(res)->real);
1082 ffetarget_real1_zero (&(res)->imaginary);
1083 return FFEBAD_DIV_BY_ZERO;
1086 bad = ffetarget_multiply_real1 (&tmp1, l.real, r.real);
1087 if (bad != FFEBAD)
1088 return bad;
1089 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, r.imaginary);
1090 if (bad != FFEBAD)
1091 return bad;
1092 bad = ffetarget_add_real1 (&tmp4, tmp1, tmp2);
1093 if (bad != FFEBAD)
1094 return bad;
1095 bad = ffetarget_divide_real1 (&res->real, tmp4, tmp3);
1096 if (bad != FFEBAD)
1097 return bad;
1099 bad = ffetarget_multiply_real1 (&tmp1, r.real, l.imaginary);
1100 if (bad != FFEBAD)
1101 return bad;
1102 bad = ffetarget_multiply_real1 (&tmp2, l.real, r.imaginary);
1103 if (bad != FFEBAD)
1104 return bad;
1105 bad = ffetarget_subtract_real1 (&tmp4, tmp1, tmp2);
1106 if (bad != FFEBAD)
1107 return bad;
1108 bad = ffetarget_divide_real1 (&res->imaginary, tmp4, tmp3);
1110 return FFEBAD;
1113 #endif
1114 /* ffetarget_divide_complex2 -- Divide function
1116 See prototype. */
1118 #if FFETARGET_okCOMPLEX2
1119 ffebad
1120 ffetarget_divide_complex2 (ffetargetComplex2 *res, ffetargetComplex2 l,
1121 ffetargetComplex2 r)
1123 ffebad bad;
1124 ffetargetReal2 tmp1, tmp2, tmp3, tmp4;
1126 bad = ffetarget_multiply_real2 (&tmp1, r.real, r.real);
1127 if (bad != FFEBAD)
1128 return bad;
1129 bad = ffetarget_multiply_real2 (&tmp2, r.imaginary, r.imaginary);
1130 if (bad != FFEBAD)
1131 return bad;
1132 bad = ffetarget_add_real2 (&tmp3, tmp1, tmp2);
1133 if (bad != FFEBAD)
1134 return bad;
1136 if (ffetarget_iszero_real2 (tmp3))
1138 ffetarget_real2_zero (&(res)->real);
1139 ffetarget_real2_zero (&(res)->imaginary);
1140 return FFEBAD_DIV_BY_ZERO;
1143 bad = ffetarget_multiply_real2 (&tmp1, l.real, r.real);
1144 if (bad != FFEBAD)
1145 return bad;
1146 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, r.imaginary);
1147 if (bad != FFEBAD)
1148 return bad;
1149 bad = ffetarget_add_real2 (&tmp4, tmp1, tmp2);
1150 if (bad != FFEBAD)
1151 return bad;
1152 bad = ffetarget_divide_real2 (&res->real, tmp4, tmp3);
1153 if (bad != FFEBAD)
1154 return bad;
1156 bad = ffetarget_multiply_real2 (&tmp1, r.real, l.imaginary);
1157 if (bad != FFEBAD)
1158 return bad;
1159 bad = ffetarget_multiply_real2 (&tmp2, l.real, r.imaginary);
1160 if (bad != FFEBAD)
1161 return bad;
1162 bad = ffetarget_subtract_real2 (&tmp4, tmp1, tmp2);
1163 if (bad != FFEBAD)
1164 return bad;
1165 bad = ffetarget_divide_real2 (&res->imaginary, tmp4, tmp3);
1167 return FFEBAD;
1170 #endif
1171 /* ffetarget_hollerith -- Convert token to a hollerith constant
1173 Always append a null byte to the end, in case this is wanted in
1174 a special case such as passing a string as a FORMAT or %REF.
1175 Done to save a bit of hassle, nothing more, but it's a kludge anyway,
1176 because it isn't a "feature" that is self-documenting. Use the
1177 string "FFETARGET-NULL-KLUDGE" to flag anyplace you use this feature
1178 in the code. */
1180 bool
1181 ffetarget_hollerith (ffetargetHollerith *val, ffelexToken integer,
1182 mallocPool pool)
1184 val->length = ffelex_token_length (integer);
1185 val->text = malloc_new_kp (pool, "ffetargetHollerith", val->length + 1);
1186 memcpy (val->text, ffelex_token_text (integer), val->length);
1187 val->text[val->length] = '\0';
1189 return TRUE;
1192 /* ffetarget_integer_bad_magical -- Complain about a magical number
1194 Just calls ffebad with the arguments. */
1196 void
1197 ffetarget_integer_bad_magical (ffelexToken t)
1199 ffebad_start (FFEBAD_BAD_MAGICAL);
1200 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1201 ffebad_finish ();
1204 /* ffetarget_integer_bad_magical_binary -- Complain about a magical number
1206 Just calls ffebad with the arguments. */
1208 void
1209 ffetarget_integer_bad_magical_binary (ffelexToken integer,
1210 ffelexToken minus)
1212 ffebad_start (FFEBAD_BAD_MAGICAL_BINARY);
1213 ffebad_here (0, ffelex_token_where_line (integer),
1214 ffelex_token_where_column (integer));
1215 ffebad_here (1, ffelex_token_where_line (minus),
1216 ffelex_token_where_column (minus));
1217 ffebad_finish ();
1220 /* ffetarget_integer_bad_magical_precedence -- Complain about a magical
1221 number
1223 Just calls ffebad with the arguments. */
1225 void
1226 ffetarget_integer_bad_magical_precedence (ffelexToken integer,
1227 ffelexToken uminus,
1228 ffelexToken higher_op)
1230 ffebad_start (FFEBAD_BAD_MAGICAL_PRECEDENCE);
1231 ffebad_here (0, ffelex_token_where_line (integer),
1232 ffelex_token_where_column (integer));
1233 ffebad_here (1, ffelex_token_where_line (uminus),
1234 ffelex_token_where_column (uminus));
1235 ffebad_here (2, ffelex_token_where_line (higher_op),
1236 ffelex_token_where_column (higher_op));
1237 ffebad_finish ();
1240 /* ffetarget_integer_bad_magical_precedence_binary -- Complain...
1242 Just calls ffebad with the arguments. */
1244 void
1245 ffetarget_integer_bad_magical_precedence_binary (ffelexToken integer,
1246 ffelexToken minus,
1247 ffelexToken higher_op)
1249 ffebad_start (FFEBAD_BAD_MAGICAL_PRECEDENCE_BINARY);
1250 ffebad_here (0, ffelex_token_where_line (integer),
1251 ffelex_token_where_column (integer));
1252 ffebad_here (1, ffelex_token_where_line (minus),
1253 ffelex_token_where_column (minus));
1254 ffebad_here (2, ffelex_token_where_line (higher_op),
1255 ffelex_token_where_column (higher_op));
1256 ffebad_finish ();
1259 /* ffetarget_integer1 -- Convert token to an integer
1261 See prototype.
1263 Token use count not affected overall. */
1265 #if FFETARGET_okINTEGER1
1266 bool
1267 ffetarget_integer1 (ffetargetInteger1 *val, ffelexToken integer)
1269 ffetargetInteger1 x;
1270 char *p;
1271 char c;
1273 assert (ffelex_token_type (integer) == FFELEX_typeNUMBER);
1275 p = ffelex_token_text (integer);
1276 x = 0;
1278 /* Skip past leading zeros. */
1280 while (((c = *p) != '\0') && (c == '0'))
1281 ++p;
1283 /* Interpret rest of number. */
1285 while (c != '\0')
1287 if ((x == FFETARGET_integerALMOST_BIG_MAGICAL)
1288 && (c == '0' + FFETARGET_integerFINISH_BIG_MAGICAL)
1289 && (*(p + 1) == '\0'))
1291 *val = (ffetargetInteger1) FFETARGET_integerBIG_MAGICAL;
1292 return TRUE;
1294 else if (x == FFETARGET_integerALMOST_BIG_MAGICAL)
1296 if ((c > '0' + FFETARGET_integerFINISH_BIG_MAGICAL)
1297 || (*(p + 1) != '\0'))
1299 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1300 ffebad_here (0, ffelex_token_where_line (integer),
1301 ffelex_token_where_column (integer));
1302 ffebad_finish ();
1303 *val = 0;
1304 return FALSE;
1307 else if (x > FFETARGET_integerALMOST_BIG_MAGICAL)
1309 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1310 ffebad_here (0, ffelex_token_where_line (integer),
1311 ffelex_token_where_column (integer));
1312 ffebad_finish ();
1313 *val = 0;
1314 return FALSE;
1316 x = x * 10 + c - '0';
1317 c = *(++p);
1320 *val = x;
1321 return TRUE;
1324 #endif
1325 /* ffetarget_integerbinary -- Convert token to a binary integer
1327 ffetarget_integerbinary x;
1328 if (ffetarget_integerdefault_8(&x,integer_token))
1329 // conversion ok.
1331 Token use count not affected overall. */
1333 bool
1334 ffetarget_integerbinary (ffetargetIntegerDefault *val, ffelexToken integer)
1336 ffetargetIntegerDefault x;
1337 char *p;
1338 char c;
1339 bool bad_digit;
1341 assert ((ffelex_token_type (integer) == FFELEX_typeNAME)
1342 || (ffelex_token_type (integer) == FFELEX_typeNUMBER));
1344 p = ffelex_token_text (integer);
1345 x = 0;
1347 /* Skip past leading zeros. */
1349 while (((c = *p) != '\0') && (c == '0'))
1350 ++p;
1352 /* Interpret rest of number. */
1354 bad_digit = FALSE;
1355 while (c != '\0')
1357 if ((c >= '0') && (c <= '1'))
1358 c -= '0';
1359 else
1361 bad_digit = TRUE;
1362 c = 0;
1365 #if 0 /* Don't complain about signed overflow; just
1366 unsigned overflow. */
1367 if ((x == FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY)
1368 && (c == FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY)
1369 && (*(p + 1) == '\0'))
1371 *val = FFETARGET_integerBIG_OVERFLOW_BINARY;
1372 return TRUE;
1374 else
1375 #endif
1376 #if FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY == 0
1377 if ((x & FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY) != 0)
1378 #else
1379 if (x == FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY)
1381 if ((c > FFETARGET_integerFINISH_BIG_OVERFLOW_BINARY)
1382 || (*(p + 1) != '\0'))
1384 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1385 ffebad_here (0, ffelex_token_where_line (integer),
1386 ffelex_token_where_column (integer));
1387 ffebad_finish ();
1388 *val = 0;
1389 return FALSE;
1392 else if (x > FFETARGET_integerALMOST_BIG_OVERFLOW_BINARY)
1393 #endif
1395 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1396 ffebad_here (0, ffelex_token_where_line (integer),
1397 ffelex_token_where_column (integer));
1398 ffebad_finish ();
1399 *val = 0;
1400 return FALSE;
1402 x = (x << 1) + c;
1403 c = *(++p);
1406 if (bad_digit)
1408 ffebad_start (FFEBAD_INVALID_BINARY_DIGIT);
1409 ffebad_here (0, ffelex_token_where_line (integer),
1410 ffelex_token_where_column (integer));
1411 ffebad_finish ();
1414 *val = x;
1415 return !bad_digit;
1418 /* ffetarget_integerhex -- Convert token to a hex integer
1420 ffetarget_integerhex x;
1421 if (ffetarget_integerdefault_8(&x,integer_token))
1422 // conversion ok.
1424 Token use count not affected overall. */
1426 bool
1427 ffetarget_integerhex (ffetargetIntegerDefault *val, ffelexToken integer)
1429 ffetargetIntegerDefault x;
1430 char *p;
1431 char c;
1432 bool bad_digit;
1434 assert ((ffelex_token_type (integer) == FFELEX_typeNAME)
1435 || (ffelex_token_type (integer) == FFELEX_typeNUMBER));
1437 p = ffelex_token_text (integer);
1438 x = 0;
1440 /* Skip past leading zeros. */
1442 while (((c = *p) != '\0') && (c == '0'))
1443 ++p;
1445 /* Interpret rest of number. */
1447 bad_digit = FALSE;
1448 while (c != '\0')
1450 if (hex_p (c))
1451 c = hex_value (c);
1452 else
1454 bad_digit = TRUE;
1455 c = 0;
1458 #if 0 /* Don't complain about signed overflow; just
1459 unsigned overflow. */
1460 if ((x == FFETARGET_integerALMOST_BIG_OVERFLOW_HEX)
1461 && (c == FFETARGET_integerFINISH_BIG_OVERFLOW_HEX)
1462 && (*(p + 1) == '\0'))
1464 *val = FFETARGET_integerBIG_OVERFLOW_HEX;
1465 return TRUE;
1467 else
1468 #endif
1469 #if FFETARGET_integerFINISH_BIG_OVERFLOW_HEX == 0
1470 if (x >= FFETARGET_integerALMOST_BIG_OVERFLOW_HEX)
1471 #else
1472 if (x == FFETARGET_integerALMOST_BIG_OVERFLOW_HEX)
1474 if ((c > FFETARGET_integerFINISH_BIG_OVERFLOW_HEX)
1475 || (*(p + 1) != '\0'))
1477 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1478 ffebad_here (0, ffelex_token_where_line (integer),
1479 ffelex_token_where_column (integer));
1480 ffebad_finish ();
1481 *val = 0;
1482 return FALSE;
1485 else if (x > FFETARGET_integerALMOST_BIG_OVERFLOW_HEX)
1486 #endif
1488 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1489 ffebad_here (0, ffelex_token_where_line (integer),
1490 ffelex_token_where_column (integer));
1491 ffebad_finish ();
1492 *val = 0;
1493 return FALSE;
1495 x = (x << 4) + c;
1496 c = *(++p);
1499 if (bad_digit)
1501 ffebad_start (FFEBAD_INVALID_HEX_DIGIT);
1502 ffebad_here (0, ffelex_token_where_line (integer),
1503 ffelex_token_where_column (integer));
1504 ffebad_finish ();
1507 *val = x;
1508 return !bad_digit;
1511 /* ffetarget_integeroctal -- Convert token to an octal integer
1513 ffetarget_integeroctal x;
1514 if (ffetarget_integerdefault_8(&x,integer_token))
1515 // conversion ok.
1517 Token use count not affected overall. */
1519 bool
1520 ffetarget_integeroctal (ffetargetIntegerDefault *val, ffelexToken integer)
1522 ffetargetIntegerDefault x;
1523 char *p;
1524 char c;
1525 bool bad_digit;
1527 assert ((ffelex_token_type (integer) == FFELEX_typeNAME)
1528 || (ffelex_token_type (integer) == FFELEX_typeNUMBER));
1530 p = ffelex_token_text (integer);
1531 x = 0;
1533 /* Skip past leading zeros. */
1535 while (((c = *p) != '\0') && (c == '0'))
1536 ++p;
1538 /* Interpret rest of number. */
1540 bad_digit = FALSE;
1541 while (c != '\0')
1543 if ((c >= '0') && (c <= '7'))
1544 c -= '0';
1545 else
1547 bad_digit = TRUE;
1548 c = 0;
1551 #if 0 /* Don't complain about signed overflow; just
1552 unsigned overflow. */
1553 if ((x == FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL)
1554 && (c == FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL)
1555 && (*(p + 1) == '\0'))
1557 *val = FFETARGET_integerBIG_OVERFLOW_OCTAL;
1558 return TRUE;
1560 else
1561 #endif
1562 #if FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL == 0
1563 if (x >= FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL)
1564 #else
1565 if (x == FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL)
1567 if ((c > FFETARGET_integerFINISH_BIG_OVERFLOW_OCTAL)
1568 || (*(p + 1) != '\0'))
1570 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1571 ffebad_here (0, ffelex_token_where_line (integer),
1572 ffelex_token_where_column (integer));
1573 ffebad_finish ();
1574 *val = 0;
1575 return FALSE;
1578 else if (x > FFETARGET_integerALMOST_BIG_OVERFLOW_OCTAL)
1579 #endif
1581 ffebad_start (FFEBAD_INTEGER_TOO_LARGE);
1582 ffebad_here (0, ffelex_token_where_line (integer),
1583 ffelex_token_where_column (integer));
1584 ffebad_finish ();
1585 *val = 0;
1586 return FALSE;
1588 x = (x << 3) + c;
1589 c = *(++p);
1592 if (bad_digit)
1594 ffebad_start (FFEBAD_INVALID_OCTAL_DIGIT);
1595 ffebad_here (0, ffelex_token_where_line (integer),
1596 ffelex_token_where_column (integer));
1597 ffebad_finish ();
1600 *val = x;
1601 return !bad_digit;
1604 /* ffetarget_multiply_complex1 -- Multiply function
1606 See prototype. */
1608 #if FFETARGET_okCOMPLEX1
1609 ffebad
1610 ffetarget_multiply_complex1 (ffetargetComplex1 *res, ffetargetComplex1 l,
1611 ffetargetComplex1 r)
1613 ffebad bad;
1614 ffetargetReal1 tmp1, tmp2;
1616 bad = ffetarget_multiply_real1 (&tmp1, l.real, r.real);
1617 if (bad != FFEBAD)
1618 return bad;
1619 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, r.imaginary);
1620 if (bad != FFEBAD)
1621 return bad;
1622 bad = ffetarget_subtract_real1 (&res->real, tmp1, tmp2);
1623 if (bad != FFEBAD)
1624 return bad;
1625 bad = ffetarget_multiply_real1 (&tmp1, l.imaginary, r.real);
1626 if (bad != FFEBAD)
1627 return bad;
1628 bad = ffetarget_multiply_real1 (&tmp2, l.real, r.imaginary);
1629 if (bad != FFEBAD)
1630 return bad;
1631 bad = ffetarget_add_real1 (&res->imaginary, tmp1, tmp2);
1633 return bad;
1636 #endif
1637 /* ffetarget_multiply_complex2 -- Multiply function
1639 See prototype. */
1641 #if FFETARGET_okCOMPLEX2
1642 ffebad
1643 ffetarget_multiply_complex2 (ffetargetComplex2 *res, ffetargetComplex2 l,
1644 ffetargetComplex2 r)
1646 ffebad bad;
1647 ffetargetReal2 tmp1, tmp2;
1649 bad = ffetarget_multiply_real2 (&tmp1, l.real, r.real);
1650 if (bad != FFEBAD)
1651 return bad;
1652 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, r.imaginary);
1653 if (bad != FFEBAD)
1654 return bad;
1655 bad = ffetarget_subtract_real2 (&res->real, tmp1, tmp2);
1656 if (bad != FFEBAD)
1657 return bad;
1658 bad = ffetarget_multiply_real2 (&tmp1, l.imaginary, r.real);
1659 if (bad != FFEBAD)
1660 return bad;
1661 bad = ffetarget_multiply_real2 (&tmp2, l.real, r.imaginary);
1662 if (bad != FFEBAD)
1663 return bad;
1664 bad = ffetarget_add_real2 (&res->imaginary, tmp1, tmp2);
1666 return bad;
1669 #endif
1670 /* ffetarget_power_complexdefault_integerdefault -- Power function
1672 See prototype. */
1674 ffebad
1675 ffetarget_power_complexdefault_integerdefault (ffetargetComplexDefault *res,
1676 ffetargetComplexDefault l,
1677 ffetargetIntegerDefault r)
1679 ffebad bad;
1680 ffetargetRealDefault tmp;
1681 ffetargetRealDefault tmp1;
1682 ffetargetRealDefault tmp2;
1683 ffetargetRealDefault two;
1685 if (ffetarget_iszero_real1 (l.real)
1686 && ffetarget_iszero_real1 (l.imaginary))
1688 ffetarget_real1_zero (&res->real);
1689 ffetarget_real1_zero (&res->imaginary);
1690 return FFEBAD;
1693 if (r == 0)
1695 ffetarget_real1_one (&res->real);
1696 ffetarget_real1_zero (&res->imaginary);
1697 return FFEBAD;
1700 if (r < 0)
1702 r = -r;
1703 bad = ffetarget_multiply_real1 (&tmp1, l.real, l.real);
1704 if (bad != FFEBAD)
1705 return bad;
1706 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, l.imaginary);
1707 if (bad != FFEBAD)
1708 return bad;
1709 bad = ffetarget_add_real1 (&tmp, tmp1, tmp2);
1710 if (bad != FFEBAD)
1711 return bad;
1712 bad = ffetarget_divide_real1 (&l.real, l.real, tmp);
1713 if (bad != FFEBAD)
1714 return bad;
1715 bad = ffetarget_divide_real1 (&l.imaginary, l.imaginary, tmp);
1716 if (bad != FFEBAD)
1717 return bad;
1718 bad = ffetarget_uminus_real1 (&l.imaginary, l.imaginary);
1719 if (bad != FFEBAD)
1720 return bad;
1723 ffetarget_real1_two (&two);
1725 while ((r & 1) == 0)
1727 bad = ffetarget_multiply_real1 (&tmp1, l.real, l.real);
1728 if (bad != FFEBAD)
1729 return bad;
1730 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, l.imaginary);
1731 if (bad != FFEBAD)
1732 return bad;
1733 bad = ffetarget_subtract_real1 (&tmp, tmp1, tmp2);
1734 if (bad != FFEBAD)
1735 return bad;
1736 bad = ffetarget_multiply_real1 (&l.imaginary, l.real, l.imaginary);
1737 if (bad != FFEBAD)
1738 return bad;
1739 bad = ffetarget_multiply_real1 (&l.imaginary, l.imaginary, two);
1740 if (bad != FFEBAD)
1741 return bad;
1742 l.real = tmp;
1743 r >>= 1;
1746 *res = l;
1747 r >>= 1;
1749 while (r != 0)
1751 bad = ffetarget_multiply_real1 (&tmp1, l.real, l.real);
1752 if (bad != FFEBAD)
1753 return bad;
1754 bad = ffetarget_multiply_real1 (&tmp2, l.imaginary, l.imaginary);
1755 if (bad != FFEBAD)
1756 return bad;
1757 bad = ffetarget_subtract_real1 (&tmp, tmp1, tmp2);
1758 if (bad != FFEBAD)
1759 return bad;
1760 bad = ffetarget_multiply_real1 (&l.imaginary, l.real, l.imaginary);
1761 if (bad != FFEBAD)
1762 return bad;
1763 bad = ffetarget_multiply_real1 (&l.imaginary, l.imaginary, two);
1764 if (bad != FFEBAD)
1765 return bad;
1766 l.real = tmp;
1767 if ((r & 1) == 1)
1769 bad = ffetarget_multiply_real1 (&tmp1, res->real, l.real);
1770 if (bad != FFEBAD)
1771 return bad;
1772 bad = ffetarget_multiply_real1 (&tmp2, res->imaginary,
1773 l.imaginary);
1774 if (bad != FFEBAD)
1775 return bad;
1776 bad = ffetarget_subtract_real1 (&tmp, tmp1, tmp2);
1777 if (bad != FFEBAD)
1778 return bad;
1779 bad = ffetarget_multiply_real1 (&tmp1, res->imaginary, l.real);
1780 if (bad != FFEBAD)
1781 return bad;
1782 bad = ffetarget_multiply_real1 (&tmp2, res->real, l.imaginary);
1783 if (bad != FFEBAD)
1784 return bad;
1785 bad = ffetarget_add_real1 (&res->imaginary, tmp1, tmp2);
1786 if (bad != FFEBAD)
1787 return bad;
1788 res->real = tmp;
1790 r >>= 1;
1793 return FFEBAD;
1796 /* ffetarget_power_complexdouble_integerdefault -- Power function
1798 See prototype. */
1800 #if FFETARGET_okCOMPLEXDOUBLE
1801 ffebad
1802 ffetarget_power_complexdouble_integerdefault (ffetargetComplexDouble *res,
1803 ffetargetComplexDouble l, ffetargetIntegerDefault r)
1805 ffebad bad;
1806 ffetargetRealDouble tmp;
1807 ffetargetRealDouble tmp1;
1808 ffetargetRealDouble tmp2;
1809 ffetargetRealDouble two;
1811 if (ffetarget_iszero_real2 (l.real)
1812 && ffetarget_iszero_real2 (l.imaginary))
1814 ffetarget_real2_zero (&res->real);
1815 ffetarget_real2_zero (&res->imaginary);
1816 return FFEBAD;
1819 if (r == 0)
1821 ffetarget_real2_one (&res->real);
1822 ffetarget_real2_zero (&res->imaginary);
1823 return FFEBAD;
1826 if (r < 0)
1828 r = -r;
1829 bad = ffetarget_multiply_real2 (&tmp1, l.real, l.real);
1830 if (bad != FFEBAD)
1831 return bad;
1832 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, l.imaginary);
1833 if (bad != FFEBAD)
1834 return bad;
1835 bad = ffetarget_add_real2 (&tmp, tmp1, tmp2);
1836 if (bad != FFEBAD)
1837 return bad;
1838 bad = ffetarget_divide_real2 (&l.real, l.real, tmp);
1839 if (bad != FFEBAD)
1840 return bad;
1841 bad = ffetarget_divide_real2 (&l.imaginary, l.imaginary, tmp);
1842 if (bad != FFEBAD)
1843 return bad;
1844 bad = ffetarget_uminus_real2 (&l.imaginary, l.imaginary);
1845 if (bad != FFEBAD)
1846 return bad;
1849 ffetarget_real2_two (&two);
1851 while ((r & 1) == 0)
1853 bad = ffetarget_multiply_real2 (&tmp1, l.real, l.real);
1854 if (bad != FFEBAD)
1855 return bad;
1856 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, l.imaginary);
1857 if (bad != FFEBAD)
1858 return bad;
1859 bad = ffetarget_subtract_real2 (&tmp, tmp1, tmp2);
1860 if (bad != FFEBAD)
1861 return bad;
1862 bad = ffetarget_multiply_real2 (&l.imaginary, l.real, l.imaginary);
1863 if (bad != FFEBAD)
1864 return bad;
1865 bad = ffetarget_multiply_real2 (&l.imaginary, l.imaginary, two);
1866 if (bad != FFEBAD)
1867 return bad;
1868 l.real = tmp;
1869 r >>= 1;
1872 *res = l;
1873 r >>= 1;
1875 while (r != 0)
1877 bad = ffetarget_multiply_real2 (&tmp1, l.real, l.real);
1878 if (bad != FFEBAD)
1879 return bad;
1880 bad = ffetarget_multiply_real2 (&tmp2, l.imaginary, l.imaginary);
1881 if (bad != FFEBAD)
1882 return bad;
1883 bad = ffetarget_subtract_real2 (&tmp, tmp1, tmp2);
1884 if (bad != FFEBAD)
1885 return bad;
1886 bad = ffetarget_multiply_real2 (&l.imaginary, l.real, l.imaginary);
1887 if (bad != FFEBAD)
1888 return bad;
1889 bad = ffetarget_multiply_real2 (&l.imaginary, l.imaginary, two);
1890 if (bad != FFEBAD)
1891 return bad;
1892 l.real = tmp;
1893 if ((r & 1) == 1)
1895 bad = ffetarget_multiply_real2 (&tmp1, res->real, l.real);
1896 if (bad != FFEBAD)
1897 return bad;
1898 bad = ffetarget_multiply_real2 (&tmp2, res->imaginary,
1899 l.imaginary);
1900 if (bad != FFEBAD)
1901 return bad;
1902 bad = ffetarget_subtract_real2 (&tmp, tmp1, tmp2);
1903 if (bad != FFEBAD)
1904 return bad;
1905 bad = ffetarget_multiply_real2 (&tmp1, res->imaginary, l.real);
1906 if (bad != FFEBAD)
1907 return bad;
1908 bad = ffetarget_multiply_real2 (&tmp2, res->real, l.imaginary);
1909 if (bad != FFEBAD)
1910 return bad;
1911 bad = ffetarget_add_real2 (&res->imaginary, tmp1, tmp2);
1912 if (bad != FFEBAD)
1913 return bad;
1914 res->real = tmp;
1916 r >>= 1;
1919 return FFEBAD;
1922 #endif
1923 /* ffetarget_power_integerdefault_integerdefault -- Power function
1925 See prototype. */
1927 ffebad
1928 ffetarget_power_integerdefault_integerdefault (ffetargetIntegerDefault *res,
1929 ffetargetIntegerDefault l, ffetargetIntegerDefault r)
1931 if (l == 0)
1933 *res = 0;
1934 return FFEBAD;
1937 if (r == 0)
1939 *res = 1;
1940 return FFEBAD;
1943 if (r < 0)
1945 if (l == 1)
1946 *res = 1;
1947 else if (l == 0)
1948 *res = 1;
1949 else if (l == -1)
1950 *res = ((-r) & 1) == 0 ? 1 : -1;
1951 else
1952 *res = 0;
1953 return FFEBAD;
1956 while ((r & 1) == 0)
1958 l *= l;
1959 r >>= 1;
1962 *res = l;
1963 r >>= 1;
1965 while (r != 0)
1967 l *= l;
1968 if ((r & 1) == 1)
1969 *res *= l;
1970 r >>= 1;
1973 return FFEBAD;
1976 /* ffetarget_power_realdefault_integerdefault -- Power function
1978 See prototype. */
1980 ffebad
1981 ffetarget_power_realdefault_integerdefault (ffetargetRealDefault *res,
1982 ffetargetRealDefault l, ffetargetIntegerDefault r)
1984 ffebad bad;
1986 if (ffetarget_iszero_real1 (l))
1988 ffetarget_real1_zero (res);
1989 return FFEBAD;
1992 if (r == 0)
1994 ffetarget_real1_one (res);
1995 return FFEBAD;
1998 if (r < 0)
2000 ffetargetRealDefault one;
2002 ffetarget_real1_one (&one);
2003 r = -r;
2004 bad = ffetarget_divide_real1 (&l, one, l);
2005 if (bad != FFEBAD)
2006 return bad;
2009 while ((r & 1) == 0)
2011 bad = ffetarget_multiply_real1 (&l, l, l);
2012 if (bad != FFEBAD)
2013 return bad;
2014 r >>= 1;
2017 *res = l;
2018 r >>= 1;
2020 while (r != 0)
2022 bad = ffetarget_multiply_real1 (&l, l, l);
2023 if (bad != FFEBAD)
2024 return bad;
2025 if ((r & 1) == 1)
2027 bad = ffetarget_multiply_real1 (res, *res, l);
2028 if (bad != FFEBAD)
2029 return bad;
2031 r >>= 1;
2034 return FFEBAD;
2037 /* ffetarget_power_realdouble_integerdefault -- Power function
2039 See prototype. */
2041 ffebad
2042 ffetarget_power_realdouble_integerdefault (ffetargetRealDouble *res,
2043 ffetargetRealDouble l,
2044 ffetargetIntegerDefault r)
2046 ffebad bad;
2048 if (ffetarget_iszero_real2 (l))
2050 ffetarget_real2_zero (res);
2051 return FFEBAD;
2054 if (r == 0)
2056 ffetarget_real2_one (res);
2057 return FFEBAD;
2060 if (r < 0)
2062 ffetargetRealDouble one;
2064 ffetarget_real2_one (&one);
2065 r = -r;
2066 bad = ffetarget_divide_real2 (&l, one, l);
2067 if (bad != FFEBAD)
2068 return bad;
2071 while ((r & 1) == 0)
2073 bad = ffetarget_multiply_real2 (&l, l, l);
2074 if (bad != FFEBAD)
2075 return bad;
2076 r >>= 1;
2079 *res = l;
2080 r >>= 1;
2082 while (r != 0)
2084 bad = ffetarget_multiply_real2 (&l, l, l);
2085 if (bad != FFEBAD)
2086 return bad;
2087 if ((r & 1) == 1)
2089 bad = ffetarget_multiply_real2 (res, *res, l);
2090 if (bad != FFEBAD)
2091 return bad;
2093 r >>= 1;
2096 return FFEBAD;
2099 /* ffetarget_print_binary -- Output typeless binary integer
2101 ffetargetTypeless val;
2102 ffetarget_typeless_binary(dmpout,val); */
2104 void
2105 ffetarget_print_binary (FILE *f, ffetargetTypeless value)
2107 char *p;
2108 char digits[sizeof (value) * CHAR_BIT + 1];
2110 if (f == NULL)
2111 f = dmpout;
2113 p = &digits[ARRAY_SIZE (digits) - 1];
2114 *p = '\0';
2117 *--p = (value & 1) + '0';
2118 value >>= 1;
2119 } while (value == 0);
2121 fputs (p, f);
2124 /* ffetarget_print_character1 -- Output character string
2126 ffetargetCharacter1 val;
2127 ffetarget_print_character1(dmpout,val); */
2129 void
2130 ffetarget_print_character1 (FILE *f, ffetargetCharacter1 value)
2132 unsigned char *p;
2133 ffetargetCharacterSize i;
2135 fputc ('\'', dmpout);
2136 for (i = 0, p = value.text; i < value.length; ++i, ++p)
2137 ffetarget_print_char_ (f, *p);
2138 fputc ('\'', dmpout);
2141 /* ffetarget_print_hollerith -- Output hollerith string
2143 ffetargetHollerith val;
2144 ffetarget_print_hollerith(dmpout,val); */
2146 void
2147 ffetarget_print_hollerith (FILE *f, ffetargetHollerith value)
2149 unsigned char *p;
2150 ffetargetHollerithSize i;
2152 fputc ('\'', dmpout);
2153 for (i = 0, p = value.text; i < value.length; ++i, ++p)
2154 ffetarget_print_char_ (f, *p);
2155 fputc ('\'', dmpout);
2158 /* ffetarget_print_octal -- Output typeless octal integer
2160 ffetargetTypeless val;
2161 ffetarget_print_octal(dmpout,val); */
2163 void
2164 ffetarget_print_octal (FILE *f, ffetargetTypeless value)
2166 char *p;
2167 char digits[sizeof (value) * CHAR_BIT / 3 + 1];
2169 if (f == NULL)
2170 f = dmpout;
2172 p = &digits[ARRAY_SIZE (digits) - 3];
2173 *p = '\0';
2176 *--p = (value & 3) + '0';
2177 value >>= 3;
2178 } while (value == 0);
2180 fputs (p, f);
2183 /* ffetarget_print_hex -- Output typeless hex integer
2185 ffetargetTypeless val;
2186 ffetarget_print_hex(dmpout,val); */
2188 void
2189 ffetarget_print_hex (FILE *f, ffetargetTypeless value)
2191 char *p;
2192 char digits[sizeof (value) * CHAR_BIT / 4 + 1];
2193 static char hexdigits[16] = "0123456789ABCDEF";
2195 if (f == NULL)
2196 f = dmpout;
2198 p = &digits[ARRAY_SIZE (digits) - 3];
2199 *p = '\0';
2202 *--p = hexdigits[value & 4];
2203 value >>= 4;
2204 } while (value == 0);
2206 fputs (p, f);
2209 /* ffetarget_real1 -- Convert token to a single-precision real number
2211 See prototype.
2213 Pass NULL for any token not provided by the user, but a valid Fortran
2214 real number must be provided somehow. For example, it is ok for
2215 exponent_sign_token and exponent_digits_token to be NULL as long as
2216 exponent_token not only starts with "E" or "e" but also contains at least
2217 one digit following it. Token use counts not affected overall. */
2219 #if FFETARGET_okREAL1
2220 bool
2221 ffetarget_real1 (ffetargetReal1 *value, ffelexToken integer,
2222 ffelexToken decimal, ffelexToken fraction,
2223 ffelexToken exponent, ffelexToken exponent_sign,
2224 ffelexToken exponent_digits)
2226 size_t sz = 1; /* Allow room for '\0' byte at end. */
2227 char *ptr = &ffetarget_string_[0];
2228 char *p = ptr;
2229 char *q;
2231 #define dotok(x) if (x != NULL) ++sz;
2232 #define dotoktxt(x) if (x != NULL) sz += ffelex_token_length(x)
2234 dotoktxt (integer);
2235 dotok (decimal);
2236 dotoktxt (fraction);
2237 dotoktxt (exponent);
2238 dotok (exponent_sign);
2239 dotoktxt (exponent_digits);
2241 #undef dotok
2242 #undef dotoktxt
2244 if (sz > ARRAY_SIZE (ffetarget_string_))
2245 p = ptr = (char *) malloc_new_ks (malloc_pool_image (), "ffetarget_real1",
2246 sz);
2248 #define dotoktxt(x) if (x != NULL) \
2250 for (q = ffelex_token_text(x); *q != '\0'; ++q) \
2251 *p++ = *q; \
2254 dotoktxt (integer);
2256 if (decimal != NULL)
2257 *p++ = '.';
2259 dotoktxt (fraction);
2260 dotoktxt (exponent);
2262 if (exponent_sign != NULL)
2264 if (ffelex_token_type (exponent_sign) == FFELEX_typePLUS)
2265 *p++ = '+';
2266 else
2268 assert (ffelex_token_type (exponent_sign) == FFELEX_typeMINUS);
2269 *p++ = '-';
2273 dotoktxt (exponent_digits);
2275 #undef dotoktxt
2277 *p = '\0';
2279 ffetarget_make_real1 (value,
2280 FFETARGET_ATOF_ (ptr,
2281 SFmode));
2283 if (sz > ARRAY_SIZE (ffetarget_string_))
2284 malloc_kill_ks (malloc_pool_image (), ptr, sz);
2286 return TRUE;
2289 #endif
2290 /* ffetarget_real2 -- Convert token to a single-precision real number
2292 See prototype.
2294 Pass NULL for any token not provided by the user, but a valid Fortran
2295 real number must be provided somehow. For example, it is ok for
2296 exponent_sign_token and exponent_digits_token to be NULL as long as
2297 exponent_token not only starts with "E" or "e" but also contains at least
2298 one digit following it. Token use counts not affected overall. */
2300 #if FFETARGET_okREAL2
2301 bool
2302 ffetarget_real2 (ffetargetReal2 *value, ffelexToken integer,
2303 ffelexToken decimal, ffelexToken fraction,
2304 ffelexToken exponent, ffelexToken exponent_sign,
2305 ffelexToken exponent_digits)
2307 size_t sz = 1; /* Allow room for '\0' byte at end. */
2308 char *ptr = &ffetarget_string_[0];
2309 char *p = ptr;
2310 char *q;
2312 #define dotok(x) if (x != NULL) ++sz;
2313 #define dotoktxt(x) if (x != NULL) sz += ffelex_token_length(x)
2315 dotoktxt (integer);
2316 dotok (decimal);
2317 dotoktxt (fraction);
2318 dotoktxt (exponent);
2319 dotok (exponent_sign);
2320 dotoktxt (exponent_digits);
2322 #undef dotok
2323 #undef dotoktxt
2325 if (sz > ARRAY_SIZE (ffetarget_string_))
2326 p = ptr = (char *) malloc_new_ks (malloc_pool_image (), "ffetarget_real1", sz);
2328 #define dotoktxt(x) if (x != NULL) \
2330 for (q = ffelex_token_text(x); *q != '\0'; ++q) \
2331 *p++ = *q; \
2333 #define dotoktxtexp(x) if (x != NULL) \
2335 *p++ = 'E'; \
2336 for (q = ffelex_token_text(x) + 1; *q != '\0'; ++q) \
2337 *p++ = *q; \
2340 dotoktxt (integer);
2342 if (decimal != NULL)
2343 *p++ = '.';
2345 dotoktxt (fraction);
2346 dotoktxtexp (exponent);
2348 if (exponent_sign != NULL)
2350 if (ffelex_token_type (exponent_sign) == FFELEX_typePLUS)
2351 *p++ = '+';
2352 else
2354 assert (ffelex_token_type (exponent_sign) == FFELEX_typeMINUS);
2355 *p++ = '-';
2359 dotoktxt (exponent_digits);
2361 #undef dotoktxt
2363 *p = '\0';
2365 ffetarget_make_real2 (value,
2366 FFETARGET_ATOF_ (ptr,
2367 DFmode));
2369 if (sz > ARRAY_SIZE (ffetarget_string_))
2370 malloc_kill_ks (malloc_pool_image (), ptr, sz);
2372 return TRUE;
2375 #endif
2376 bool
2377 ffetarget_typeless_binary (ffetargetTypeless *xvalue, ffelexToken token)
2379 char *p;
2380 char c;
2381 ffetargetTypeless value = 0;
2382 ffetargetTypeless new_value = 0;
2383 bool bad_digit = FALSE;
2384 bool overflow = FALSE;
2386 p = ffelex_token_text (token);
2388 for (c = *p; c != '\0'; c = *++p)
2390 new_value <<= 1;
2391 if ((new_value >> 1) != value)
2392 overflow = TRUE;
2393 if (ISDIGIT (c))
2394 new_value += c - '0';
2395 else
2396 bad_digit = TRUE;
2397 value = new_value;
2400 if (bad_digit)
2402 ffebad_start (FFEBAD_INVALID_TYPELESS_BINARY_DIGIT);
2403 ffebad_here (0, ffelex_token_where_line (token),
2404 ffelex_token_where_column (token));
2405 ffebad_finish ();
2407 else if (overflow)
2409 ffebad_start (FFEBAD_TYPELESS_OVERFLOW);
2410 ffebad_here (0, ffelex_token_where_line (token),
2411 ffelex_token_where_column (token));
2412 ffebad_finish ();
2415 *xvalue = value;
2417 return !bad_digit && !overflow;
2420 bool
2421 ffetarget_typeless_octal (ffetargetTypeless *xvalue, ffelexToken token)
2423 char *p;
2424 char c;
2425 ffetargetTypeless value = 0;
2426 ffetargetTypeless new_value = 0;
2427 bool bad_digit = FALSE;
2428 bool overflow = FALSE;
2430 p = ffelex_token_text (token);
2432 for (c = *p; c != '\0'; c = *++p)
2434 new_value <<= 3;
2435 if ((new_value >> 3) != value)
2436 overflow = TRUE;
2437 if (ISDIGIT (c))
2438 new_value += c - '0';
2439 else
2440 bad_digit = TRUE;
2441 value = new_value;
2444 if (bad_digit)
2446 ffebad_start (FFEBAD_INVALID_TYPELESS_OCTAL_DIGIT);
2447 ffebad_here (0, ffelex_token_where_line (token),
2448 ffelex_token_where_column (token));
2449 ffebad_finish ();
2451 else if (overflow)
2453 ffebad_start (FFEBAD_TYPELESS_OVERFLOW);
2454 ffebad_here (0, ffelex_token_where_line (token),
2455 ffelex_token_where_column (token));
2456 ffebad_finish ();
2459 *xvalue = value;
2461 return !bad_digit && !overflow;
2464 bool
2465 ffetarget_typeless_hex (ffetargetTypeless *xvalue, ffelexToken token)
2467 char *p;
2468 char c;
2469 ffetargetTypeless value = 0;
2470 ffetargetTypeless new_value = 0;
2471 bool bad_digit = FALSE;
2472 bool overflow = FALSE;
2474 p = ffelex_token_text (token);
2476 for (c = *p; c != '\0'; c = *++p)
2478 new_value <<= 4;
2479 if ((new_value >> 4) != value)
2480 overflow = TRUE;
2481 if (hex_p (c))
2482 new_value += hex_value (c);
2483 else
2484 bad_digit = TRUE;
2485 value = new_value;
2488 if (bad_digit)
2490 ffebad_start (FFEBAD_INVALID_TYPELESS_HEX_DIGIT);
2491 ffebad_here (0, ffelex_token_where_line (token),
2492 ffelex_token_where_column (token));
2493 ffebad_finish ();
2495 else if (overflow)
2497 ffebad_start (FFEBAD_TYPELESS_OVERFLOW);
2498 ffebad_here (0, ffelex_token_where_line (token),
2499 ffelex_token_where_column (token));
2500 ffebad_finish ();
2503 *xvalue = value;
2505 return !bad_digit && !overflow;
2508 void
2509 ffetarget_verify_character1 (mallocPool pool, ffetargetCharacter1 val)
2511 if (val.length != 0)
2512 malloc_verify_kp (pool, val.text, val.length);
2515 /* This is like memcpy. It is needed because some systems' header files
2516 don't declare memcpy as a function but instead
2517 "#define memcpy(to,from,len) something". */
2519 void *
2520 ffetarget_memcpy_ (void *dst, void *src, size_t len)
2522 return (void *) memcpy (dst, src, len);
2525 /* ffetarget_num_digits_ -- Determine number of non-space characters in token
2527 ffetarget_num_digits_(token);
2529 All non-spaces are assumed to be binary, octal, or hex digits. */
2532 ffetarget_num_digits_ (ffelexToken token)
2534 int i;
2535 char *c;
2537 switch (ffelex_token_type (token))
2539 case FFELEX_typeNAME:
2540 case FFELEX_typeNUMBER:
2541 return ffelex_token_length (token);
2543 case FFELEX_typeCHARACTER:
2544 i = 0;
2545 for (c = ffelex_token_text (token); *c != '\0'; ++c)
2547 if (*c != ' ')
2548 ++i;
2550 return i;
2552 default:
2553 assert ("weird token" == NULL);
2554 return 1;