summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/f/intrin.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/f/intrin.c')
-rw-r--r--contrib/gcc/f/intrin.c2119
1 files changed, 0 insertions, 2119 deletions
diff --git a/contrib/gcc/f/intrin.c b/contrib/gcc/f/intrin.c
deleted file mode 100644
index a379684..0000000
--- a/contrib/gcc/f/intrin.c
+++ /dev/null
@@ -1,2119 +0,0 @@
-/* intrin.c -- Recognize references to intrinsics
- Copyright (C) 1995, 1996, 1997, 1998, 2002,
- 2003 Free Software Foundation, Inc.
- Contributed by James Craig Burley.
-
-This file is part of GNU Fortran.
-
-GNU Fortran is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Fortran is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Fortran; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.
-
-*/
-
-#include "proj.h"
-#include "intrin.h"
-#include "expr.h"
-#include "info.h"
-#include "src.h"
-#include "symbol.h"
-#include "target.h"
-#include "top.h"
-
-struct _ffeintrin_name_
- {
- const char *const name_uc;
- const char *const name_lc;
- const char *const name_ic;
- const ffeintrinGen generic;
- const ffeintrinSpec specific;
- };
-
-struct _ffeintrin_gen_
- {
- const char *const name; /* Name as seen in program. */
- const ffeintrinSpec specs[2];
- };
-
-struct _ffeintrin_spec_
- {
- const char *const name; /* Uppercase name as seen in source code,
- lowercase if no source name, "none" if no
- name at all (NONE case). */
- const bool is_actualarg; /* Ok to pass as actual arg if -pedantic. */
- const ffeintrinFamily family;
- const ffeintrinImp implementation;
- };
-
-struct _ffeintrin_imp_
- {
- const char *const name; /* Name of implementation. */
- const ffecomGfrt gfrt_direct;/* library routine, direct-callable form. */
- const ffecomGfrt gfrt_f2c; /* library routine, f2c-callable form. */
- const ffecomGfrt gfrt_gnu; /* library routine, gnu-callable form. */
- const char *const control;
- const char y2kbad;
- };
-
-static ffebad ffeintrin_check_ (ffeintrinImp imp, ffebldOp op,
- ffebld args, ffeinfoBasictype *xbt,
- ffeinfoKindtype *xkt,
- ffetargetCharacterSize *xsz,
- bool *check_intrin,
- ffelexToken t,
- bool commit);
-static bool ffeintrin_check_any_ (ffebld arglist);
-static int ffeintrin_cmp_name_ (const void *name, const void *intrinsic);
-
-static const struct _ffeintrin_name_ ffeintrin_names_[]
-=
-{ /* Alpha order. */
-#define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC) \
- { UPPER, LOWER, MIXED, FFEINTRIN_ ## GEN, FFEINTRIN_ ## SPEC },
-#define DEFGEN(CODE,NAME,SPEC1,SPEC2)
-#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
-#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
-#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
-#include "intrin.def"
-#undef DEFNAME
-#undef DEFGEN
-#undef DEFSPEC
-#undef DEFIMP
-#undef DEFIMPY
-};
-
-static const struct _ffeintrin_gen_ ffeintrin_gens_[]
-=
-{
-#define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC)
-#define DEFGEN(CODE,NAME,SPEC1,SPEC2) \
- { NAME, { SPEC1, SPEC2, }, },
-#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
-#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
-#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
-#include "intrin.def"
-#undef DEFNAME
-#undef DEFGEN
-#undef DEFSPEC
-#undef DEFIMP
-#undef DEFIMPY
-};
-
-static const struct _ffeintrin_imp_ ffeintrin_imps_[]
-=
-{
-#define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC)
-#define DEFGEN(CODE,NAME,SPEC1,SPEC2)
-#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
-#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL) \
- { NAME, FFECOM_gfrt ## GFRTDIRECT, FFECOM_gfrt ## GFRTF2C, \
- FFECOM_gfrt ## GFRTGNU, CONTROL, FALSE },
-#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD) \
- { NAME, FFECOM_gfrt ## GFRTDIRECT, FFECOM_gfrt ## GFRTF2C, \
- FFECOM_gfrt ## GFRTGNU, CONTROL, Y2KBAD },
-#include "intrin.def"
-#undef DEFNAME
-#undef DEFGEN
-#undef DEFSPEC
-#undef DEFIMP
-#undef DEFIMPY
-};
-
-static const struct _ffeintrin_spec_ ffeintrin_specs_[]
-=
-{
-#define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC)
-#define DEFGEN(CODE,NAME,SPEC1,SPEC2)
-#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP) \
- { NAME, CALLABLE, FAMILY, IMP, },
-#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
-#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
-#include "intrin.def"
-#undef DEFGEN
-#undef DEFSPEC
-#undef DEFIMP
-#undef DEFIMPY
-};
-
-
-static ffebad
-ffeintrin_check_ (ffeintrinImp imp, ffebldOp op,
- ffebld args, ffeinfoBasictype *xbt,
- ffeinfoKindtype *xkt,
- ffetargetCharacterSize *xsz,
- bool *check_intrin,
- ffelexToken t,
- bool commit)
-{
- const char *c = ffeintrin_imps_[imp].control;
- bool subr = (c[0] == '-');
- const char *argc;
- ffebld arg;
- ffeinfoBasictype bt;
- ffeinfoKindtype kt;
- ffetargetCharacterSize sz = FFETARGET_charactersizeNONE;
- ffeinfoKindtype firstarg_kt;
- bool need_col;
- ffeinfoBasictype col_bt = FFEINFO_basictypeNONE;
- ffeinfoKindtype col_kt = FFEINFO_kindtypeNONE;
- int colon = (c[2] == ':') ? 2 : 3;
- int argno;
-
- /* Check procedure type (function vs. subroutine) against
- invocation. */
-
- if (op == FFEBLD_opSUBRREF)
- {
- if (!subr)
- return FFEBAD_INTRINSIC_IS_FUNC;
- }
- else if (op == FFEBLD_opFUNCREF)
- {
- if (subr)
- return FFEBAD_INTRINSIC_IS_SUBR;
- }
- else
- return FFEBAD_INTRINSIC_REF;
-
- /* Check the arglist for validity. */
-
- if ((args != NULL)
- && (ffebld_head (args) != NULL))
- firstarg_kt = ffeinfo_kindtype (ffebld_info (ffebld_head (args)));
- else
- firstarg_kt = FFEINFO_kindtype;
-
- for (argc = &c[colon + 3],
- arg = args;
- *argc != '\0';
- )
- {
- char optional = '\0';
- char required = '\0';
- char extra = '\0';
- char basic;
- char kind;
- int length;
- int elements;
- bool lastarg_complex = FALSE;
-
- /* We don't do anything with keywords yet. */
- do
- {
- } while (*(++argc) != '=');
-
- ++argc;
- if ((*argc == '?')
- || (*argc == '!')
- || (*argc == '*'))
- optional = *(argc++);
- if ((*argc == '+')
- || (*argc == 'n')
- || (*argc == 'p'))
- required = *(argc++);
- basic = *(argc++);
- kind = *(argc++);
- if (*argc == '[')
- {
- length = *++argc - '0';
- if (*++argc != ']')
- length = 10 * length + (*(argc++) - '0');
- ++argc;
- }
- else
- length = -1;
- if (*argc == '(')
- {
- elements = *++argc - '0';
- if (*++argc != ')')
- elements = 10 * elements + (*(argc++) - '0');
- ++argc;
- }
- else if (*argc == '&')
- {
- elements = -1;
- ++argc;
- }
- else
- elements = 0;
- if ((*argc == '&')
- || (*argc == 'i')
- || (*argc == 'w')
- || (*argc == 'x'))
- extra = *(argc++);
- if (*argc == ',')
- ++argc;
-
- /* Break out of this loop only when current arg spec completely
- processed. */
-
- do
- {
- bool okay;
- ffebld a;
- ffeinfo i;
- bool anynum;
- ffeinfoBasictype abt = FFEINFO_basictypeNONE;
- ffeinfoKindtype akt = FFEINFO_kindtypeNONE;
-
- if ((arg == NULL)
- || (ffebld_head (arg) == NULL))
- {
- if (required != '\0')
- return FFEBAD_INTRINSIC_TOOFEW;
- if (optional == '\0')
- return FFEBAD_INTRINSIC_TOOFEW;
- if (arg != NULL)
- arg = ffebld_trail (arg);
- break; /* Try next argspec. */
- }
-
- a = ffebld_head (arg);
- i = ffebld_info (a);
- anynum = (ffeinfo_basictype (i) == FFEINFO_basictypeHOLLERITH)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeTYPELESS);
-
- /* See how well the arg matches up to the spec. */
-
- switch (basic)
- {
- case 'A':
- okay = (ffeinfo_basictype (i) == FFEINFO_basictypeCHARACTER)
- && ((length == -1)
- || (ffeinfo_size (i) == (ffetargetCharacterSize) length));
- break;
-
- case 'C':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX);
- abt = FFEINFO_basictypeCOMPLEX;
- break;
-
- case 'I':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER);
- abt = FFEINFO_basictypeINTEGER;
- break;
-
- case 'L':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL);
- abt = FFEINFO_basictypeLOGICAL;
- break;
-
- case 'R':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
- abt = FFEINFO_basictypeREAL;
- break;
-
- case 'B':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL);
- break;
-
- case 'F':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
- break;
-
- case 'N':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
- break;
-
- case 'S':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
- break;
-
- case 'g':
- okay = ((ffebld_op (a) == FFEBLD_opLABTER)
- || (ffebld_op (a) == FFEBLD_opLABTOK));
- elements = -1;
- extra = '-';
- break;
-
- case 's':
- okay = (((((ffeinfo_basictype (i) == FFEINFO_basictypeNONE)
- && (ffeinfo_kindtype (i) == FFEINFO_kindtypeNONE)
- && (ffeinfo_kind (i) == FFEINFO_kindSUBROUTINE))
- || ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- && (ffeinfo_kindtype (i) == FFEINFO_kindtypeINTEGERDEFAULT)
- && (ffeinfo_kind (i) == FFEINFO_kindFUNCTION))
- || (ffeinfo_kind (i) == FFEINFO_kindNONE))
- && ((ffeinfo_where (i) == FFEINFO_whereDUMMY)
- || (ffeinfo_where (i) == FFEINFO_whereGLOBAL)))
- || ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- && (ffeinfo_kind (i) == FFEINFO_kindENTITY)));
- elements = -1;
- extra = '-';
- break;
-
- case '-':
- default:
- okay = TRUE;
- break;
- }
-
- switch (kind)
- {
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- akt = (kind - '0');
- if ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL))
- {
- switch (akt)
- { /* Translate to internal kinds for now! */
- default:
- break;
-
- case 2:
- akt = 4;
- break;
-
- case 3:
- akt = 2;
- break;
-
- case 4:
- akt = 5;
- break;
-
- case 6:
- akt = 3;
- break;
-
- case 7:
- akt = ffecom_pointer_kind ();
- break;
- }
- }
- okay &= anynum || (ffeinfo_kindtype (i) == akt);
- break;
-
- case 'A':
- okay &= anynum || (ffeinfo_kindtype (i) == firstarg_kt);
- akt = (firstarg_kt == FFEINFO_kindtype) ? FFEINFO_kindtypeNONE
- : firstarg_kt;
- break;
-
- case 'N':
- /* Accept integers and logicals not wider than the default integer/logical. */
- if (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- {
- okay &= anynum || (ffeinfo_kindtype (i) == FFEINFO_kindtypeINTEGER1
- || ffeinfo_kindtype (i) == FFEINFO_kindtypeINTEGER2
- || ffeinfo_kindtype (i) == FFEINFO_kindtypeINTEGER3);
- akt = FFEINFO_kindtypeINTEGER1; /* The default. */
- }
- else if (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL)
- {
- okay &= anynum || (ffeinfo_kindtype (i) == FFEINFO_kindtypeLOGICAL1
- || ffeinfo_kindtype (i) == FFEINFO_kindtypeLOGICAL2
- || ffeinfo_kindtype (i) == FFEINFO_kindtypeLOGICAL3);
- akt = FFEINFO_kindtypeLOGICAL1; /* The default. */
- }
- break;
-
- case '*':
- default:
- break;
- }
-
- switch (elements)
- {
- ffebld b;
-
- case -1:
- break;
-
- case 0:
- if (ffeinfo_rank (i) != 0)
- okay = FALSE;
- break;
-
- default:
- if ((ffeinfo_rank (i) != 1)
- || (ffebld_op (a) != FFEBLD_opSYMTER)
- || ((b = ffesymbol_arraysize (ffebld_symter (a))) == NULL)
- || (ffebld_op (b) != FFEBLD_opCONTER)
- || (ffeinfo_basictype (ffebld_info (b)) != FFEINFO_basictypeINTEGER)
- || (ffeinfo_kindtype (ffebld_info (b)) != FFEINFO_kindtypeINTEGERDEFAULT)
- || (ffebld_constant_integer1 (ffebld_conter (b)) != elements))
- okay = FALSE;
- break;
- }
-
- switch (extra)
- {
- case '&':
- if ((ffeinfo_kind (i) != FFEINFO_kindENTITY)
- || ((ffebld_op (a) != FFEBLD_opSYMTER)
- && (ffebld_op (a) != FFEBLD_opSUBSTR)
- && (ffebld_op (a) != FFEBLD_opARRAYREF)))
- okay = FALSE;
- break;
-
- case 'w':
- case 'x':
- if ((ffeinfo_kind (i) != FFEINFO_kindENTITY)
- || ((ffebld_op (a) != FFEBLD_opSYMTER)
- && (ffebld_op (a) != FFEBLD_opARRAYREF)
- && (ffebld_op (a) != FFEBLD_opSUBSTR)))
- okay = FALSE;
- break;
-
- case '-':
- case 'i':
- break;
-
- default:
- if (ffeinfo_kind (i) != FFEINFO_kindENTITY)
- okay = FALSE;
- break;
- }
-
- if ((optional == '!')
- && lastarg_complex)
- okay = FALSE;
-
- if (!okay)
- {
- /* If it wasn't optional, it's an error,
- else maybe it could match a later argspec. */
- if (optional == '\0')
- return FFEBAD_INTRINSIC_REF;
- break; /* Try next argspec. */
- }
-
- lastarg_complex
- = (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX);
-
- if (anynum)
- {
- /* If we know dummy arg type, convert to that now. */
-
- if ((abt != FFEINFO_basictypeNONE)
- && (akt != FFEINFO_kindtypeNONE)
- && commit)
- {
- /* We have a known type, convert hollerith/typeless
- to it. */
-
- a = ffeexpr_convert (a, t, NULL,
- abt, akt, 0,
- FFETARGET_charactersizeNONE,
- FFEEXPR_contextLET);
- ffebld_set_head (arg, a);
- }
- }
-
- arg = ffebld_trail (arg); /* Arg accepted, now move on. */
-
- if (optional == '*')
- continue; /* Go ahead and try another arg. */
- if (required == '\0')
- break;
- if ((required == 'n')
- || (required == '+'))
- {
- optional = '*';
- required = '\0';
- }
- else if (required == 'p')
- required = 'n';
- } while (TRUE);
- }
-
- if (arg != NULL)
- return FFEBAD_INTRINSIC_TOOMANY;
-
- /* Set up the initial type for the return value of the function. */
-
- need_col = FALSE;
- switch (c[0])
- {
- case 'A':
- bt = FFEINFO_basictypeCHARACTER;
- sz = (c[2] == '*') ? FFETARGET_charactersizeNONE : 1;
- break;
-
- case 'C':
- bt = FFEINFO_basictypeCOMPLEX;
- break;
-
- case 'I':
- bt = FFEINFO_basictypeINTEGER;
- break;
-
- case 'L':
- bt = FFEINFO_basictypeLOGICAL;
- break;
-
- case 'R':
- bt = FFEINFO_basictypeREAL;
- break;
-
- case 'B':
- case 'F':
- case 'N':
- case 'S':
- need_col = TRUE;
- /* Fall through. */
- case '-':
- default:
- bt = FFEINFO_basictypeNONE;
- break;
- }
-
- switch (c[1])
- {
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- kt = (c[1] - '0');
- if ((bt == FFEINFO_basictypeINTEGER)
- || (bt == FFEINFO_basictypeLOGICAL))
- {
- switch (kt)
- { /* Translate to internal kinds for now! */
- default:
- break;
-
- case 2:
- kt = 4;
- break;
-
- case 3:
- kt = 2;
- break;
-
- case 4:
- kt = 5;
- break;
-
- case 6:
- kt = 3;
- break;
-
- case 7:
- kt = ffecom_pointer_kind ();
- break;
- }
- }
- break;
-
- case 'C':
- if (ffe_is_90 ())
- need_col = TRUE;
- kt = 1;
- break;
-
- case '=':
- need_col = TRUE;
- /* Fall through. */
- case '-':
- default:
- kt = FFEINFO_kindtypeNONE;
- break;
- }
-
- /* Determine collective type of COL, if there is one. */
-
- if (need_col || c[colon + 1] != '-')
- {
- bool okay = TRUE;
- bool have_anynum = FALSE;
- int arg_count=0;
-
- for (arg = args, arg_count=0;
- arg != NULL;
- arg = ffebld_trail (arg), arg_count++ )
- {
- ffebld a = ffebld_head (arg);
- ffeinfo i;
- bool anynum;
-
- if (a == NULL)
- continue;
- i = ffebld_info (a);
-
- if ( c[colon+1] != '*' && (c[colon+1]-'0') != arg_count )
- continue;
-
- anynum = (ffeinfo_basictype (i) == FFEINFO_basictypeHOLLERITH)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeTYPELESS);
- if (anynum)
- {
- have_anynum = TRUE;
- continue;
- }
-
- if ((col_bt == FFEINFO_basictypeNONE)
- && (col_kt == FFEINFO_kindtypeNONE))
- {
- col_bt = ffeinfo_basictype (i);
- col_kt = ffeinfo_kindtype (i);
- }
- else
- {
- ffeexpr_type_combine (&col_bt, &col_kt,
- col_bt, col_kt,
- ffeinfo_basictype (i),
- ffeinfo_kindtype (i),
- NULL);
- if ((col_bt == FFEINFO_basictypeNONE)
- || (col_kt == FFEINFO_kindtypeNONE))
- return FFEBAD_INTRINSIC_REF;
- }
- }
-
- if (have_anynum
- && ((col_bt == FFEINFO_basictypeNONE)
- || (col_kt == FFEINFO_kindtypeNONE)))
- {
- /* No type, but have hollerith/typeless. Use type of return
- value to determine type of COL. */
-
- switch (c[0])
- {
- case 'A':
- return FFEBAD_INTRINSIC_REF;
-
- case 'B':
- case 'I':
- case 'L':
- if ((col_bt != FFEINFO_basictypeNONE)
- && (col_bt != FFEINFO_basictypeINTEGER))
- return FFEBAD_INTRINSIC_REF;
- /* Fall through. */
- case 'N':
- case 'S':
- case '-':
- default:
- col_bt = FFEINFO_basictypeINTEGER;
- col_kt = FFEINFO_kindtypeINTEGER1;
- break;
-
- case 'C':
- if ((col_bt != FFEINFO_basictypeNONE)
- && (col_bt != FFEINFO_basictypeCOMPLEX))
- return FFEBAD_INTRINSIC_REF;
- col_bt = FFEINFO_basictypeCOMPLEX;
- col_kt = FFEINFO_kindtypeREAL1;
- break;
-
- case 'R':
- if ((col_bt != FFEINFO_basictypeNONE)
- && (col_bt != FFEINFO_basictypeREAL))
- return FFEBAD_INTRINSIC_REF;
- /* Fall through. */
- case 'F':
- col_bt = FFEINFO_basictypeREAL;
- col_kt = FFEINFO_kindtypeREAL1;
- break;
- }
- }
-
- switch (c[0])
- {
- case 'B':
- okay = (col_bt == FFEINFO_basictypeINTEGER)
- || (col_bt == FFEINFO_basictypeLOGICAL);
- if (need_col)
- bt = col_bt;
- break;
-
- case 'F':
- okay = (col_bt == FFEINFO_basictypeCOMPLEX)
- || (col_bt == FFEINFO_basictypeREAL);
- if (need_col)
- bt = col_bt;
- break;
-
- case 'N':
- okay = (col_bt == FFEINFO_basictypeCOMPLEX)
- || (col_bt == FFEINFO_basictypeINTEGER)
- || (col_bt == FFEINFO_basictypeREAL);
- if (need_col)
- bt = col_bt;
- break;
-
- case 'S':
- okay = (col_bt == FFEINFO_basictypeINTEGER)
- || (col_bt == FFEINFO_basictypeREAL)
- || (col_bt == FFEINFO_basictypeCOMPLEX);
- if (need_col)
- bt = ((col_bt != FFEINFO_basictypeCOMPLEX) ? col_bt
- : FFEINFO_basictypeREAL);
- break;
- }
-
- switch (c[1])
- {
- case '=':
- if (need_col)
- kt = col_kt;
- break;
-
- case 'C':
- if (col_bt == FFEINFO_basictypeCOMPLEX)
- {
- if (col_kt != FFEINFO_kindtypeREALDEFAULT)
- *check_intrin = TRUE;
- if (need_col)
- kt = col_kt;
- }
- break;
- }
-
- if (!okay)
- return FFEBAD_INTRINSIC_REF;
- }
-
- /* Now, convert args in the arglist to the final type of the COL. */
-
- for (argno = 0, argc = &c[colon + 3],
- arg = args;
- *argc != '\0';
- ++argno)
- {
- char optional = '\0';
- char required = '\0';
- char extra = '\0';
- char basic;
- char kind;
- int length;
- int elements;
- bool lastarg_complex = FALSE;
-
- /* We don't do anything with keywords yet. */
- do
- {
- } while (*(++argc) != '=');
-
- ++argc;
- if ((*argc == '?')
- || (*argc == '!')
- || (*argc == '*'))
- optional = *(argc++);
- if ((*argc == '+')
- || (*argc == 'n')
- || (*argc == 'p'))
- required = *(argc++);
- basic = *(argc++);
- kind = *(argc++);
- if (*argc == '[')
- {
- length = *++argc - '0';
- if (*++argc != ']')
- length = 10 * length + (*(argc++) - '0');
- ++argc;
- }
- else
- length = -1;
- if (*argc == '(')
- {
- elements = *++argc - '0';
- if (*++argc != ')')
- elements = 10 * elements + (*(argc++) - '0');
- ++argc;
- }
- else if (*argc == '&')
- {
- elements = -1;
- ++argc;
- }
- else
- elements = 0;
- if ((*argc == '&')
- || (*argc == 'i')
- || (*argc == 'w')
- || (*argc == 'x'))
- extra = *(argc++);
- if (*argc == ',')
- ++argc;
-
- /* Break out of this loop only when current arg spec completely
- processed. */
-
- do
- {
- bool okay;
- ffebld a;
- ffeinfo i;
- bool anynum;
- ffeinfoBasictype abt = FFEINFO_basictypeNONE;
- ffeinfoKindtype akt = FFEINFO_kindtypeNONE;
-
- if ((arg == NULL)
- || (ffebld_head (arg) == NULL))
- {
- if (arg != NULL)
- arg = ffebld_trail (arg);
- break; /* Try next argspec. */
- }
-
- a = ffebld_head (arg);
- i = ffebld_info (a);
- anynum = (ffeinfo_basictype (i) == FFEINFO_basictypeHOLLERITH)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeTYPELESS);
-
- /* Determine what the default type for anynum would be. */
-
- if (anynum)
- {
- switch (c[colon + 1])
- {
- case '-':
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if (argno != (c[colon + 1] - '0'))
- break;
- case '*':
- abt = col_bt;
- akt = col_kt;
- break;
- }
- }
-
- /* Again, match arg up to the spec. We go through all of
- this again to properly follow the contour of optional
- arguments. Probably this level of flexibility is not
- needed, perhaps it's even downright naughty. */
-
- switch (basic)
- {
- case 'A':
- okay = (ffeinfo_basictype (i) == FFEINFO_basictypeCHARACTER)
- && ((length == -1)
- || (ffeinfo_size (i) == (ffetargetCharacterSize) length));
- break;
-
- case 'C':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX);
- abt = FFEINFO_basictypeCOMPLEX;
- break;
-
- case 'I':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER);
- abt = FFEINFO_basictypeINTEGER;
- break;
-
- case 'L':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL);
- abt = FFEINFO_basictypeLOGICAL;
- break;
-
- case 'R':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
- abt = FFEINFO_basictypeREAL;
- break;
-
- case 'B':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL);
- break;
-
- case 'F':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
- break;
-
- case 'N':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
- break;
-
- case 'S':
- okay = anynum
- || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
- break;
-
- case 'g':
- okay = ((ffebld_op (a) == FFEBLD_opLABTER)
- || (ffebld_op (a) == FFEBLD_opLABTOK));
- elements = -1;
- extra = '-';
- break;
-
- case 's':
- okay = (((((ffeinfo_basictype (i) == FFEINFO_basictypeNONE)
- && (ffeinfo_kindtype (i) == FFEINFO_kindtypeNONE)
- && (ffeinfo_kind (i) == FFEINFO_kindSUBROUTINE))
- || ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- && (ffeinfo_kindtype (i) == FFEINFO_kindtypeINTEGERDEFAULT)
- && (ffeinfo_kind (i) == FFEINFO_kindFUNCTION))
- || (ffeinfo_kind (i) == FFEINFO_kindNONE))
- && ((ffeinfo_where (i) == FFEINFO_whereDUMMY)
- || (ffeinfo_where (i) == FFEINFO_whereGLOBAL)))
- || ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- && (ffeinfo_kind (i) == FFEINFO_kindENTITY)));
- elements = -1;
- extra = '-';
- break;
-
- case '-':
- default:
- okay = TRUE;
- break;
- }
-
- switch (kind)
- {
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- akt = (kind - '0');
- if ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
- || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL))
- {
- switch (akt)
- { /* Translate to internal kinds for now! */
- default:
- break;
-
- case 2:
- akt = 4;
- break;
-
- case 3:
- akt = 2;
- break;
-
- case 4:
- akt = 5;
- break;
-
- case 6:
- akt = 3;
- break;
-
- case 7:
- akt = ffecom_pointer_kind ();
- break;
- }
- }
- okay &= anynum || (ffeinfo_kindtype (i) == akt);
- break;
-
- case 'A':
- okay &= anynum || (ffeinfo_kindtype (i) == firstarg_kt);
- akt = (firstarg_kt == FFEINFO_kindtype) ? FFEINFO_kindtypeNONE
- : firstarg_kt;
- break;
-
- case '*':
- default:
- break;
- }
-
- switch (elements)
- {
- ffebld b;
-
- case -1:
- break;
-
- case 0:
- if (ffeinfo_rank (i) != 0)
- okay = FALSE;
- break;
-
- default:
- if ((ffeinfo_rank (i) != 1)
- || (ffebld_op (a) != FFEBLD_opSYMTER)
- || ((b = ffesymbol_arraysize (ffebld_symter (a))) == NULL)
- || (ffebld_op (b) != FFEBLD_opCONTER)
- || (ffeinfo_basictype (ffebld_info (b)) != FFEINFO_basictypeINTEGER)
- || (ffeinfo_kindtype (ffebld_info (b)) != FFEINFO_kindtypeINTEGERDEFAULT)
- || (ffebld_constant_integer1 (ffebld_conter (b)) != elements))
- okay = FALSE;
- break;
- }
-
- switch (extra)
- {
- case '&':
- if ((ffeinfo_kind (i) != FFEINFO_kindENTITY)
- || ((ffebld_op (a) != FFEBLD_opSYMTER)
- && (ffebld_op (a) != FFEBLD_opSUBSTR)
- && (ffebld_op (a) != FFEBLD_opARRAYREF)))
- okay = FALSE;
- break;
-
- case 'w':
- case 'x':
- if ((ffeinfo_kind (i) != FFEINFO_kindENTITY)
- || ((ffebld_op (a) != FFEBLD_opSYMTER)
- && (ffebld_op (a) != FFEBLD_opARRAYREF)
- && (ffebld_op (a) != FFEBLD_opSUBSTR)))
- okay = FALSE;
- break;
-
- case '-':
- case 'i':
- break;
-
- default:
- if (ffeinfo_kind (i) != FFEINFO_kindENTITY)
- okay = FALSE;
- break;
- }
-
- if ((optional == '!')
- && lastarg_complex)
- okay = FALSE;
-
- if (!okay)
- {
- /* If it wasn't optional, it's an error,
- else maybe it could match a later argspec. */
- if (optional == '\0')
- return FFEBAD_INTRINSIC_REF;
- break; /* Try next argspec. */
- }
-
- lastarg_complex
- = (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX);
-
- if (anynum && commit)
- {
- /* If we know dummy arg type, convert to that now. */
-
- if (abt == FFEINFO_basictypeNONE)
- abt = FFEINFO_basictypeINTEGER;
- if (akt == FFEINFO_kindtypeNONE)
- akt = FFEINFO_kindtypeINTEGER1;
-
- /* We have a known type, convert hollerith/typeless to it. */
-
- a = ffeexpr_convert (a, t, NULL,
- abt, akt, 0,
- FFETARGET_charactersizeNONE,
- FFEEXPR_contextLET);
- ffebld_set_head (arg, a);
- }
- else if ((c[colon + 1] == '*') && commit)
- {
- /* This is where we promote types to the consensus
- type for the COL. Maybe this is where -fpedantic
- should issue a warning as well. */
-
- a = ffeexpr_convert (a, t, NULL,
- col_bt, col_kt, 0,
- ffeinfo_size (i),
- FFEEXPR_contextLET);
- ffebld_set_head (arg, a);
- }
-
- arg = ffebld_trail (arg); /* Arg accepted, now move on. */
-
- if (optional == '*')
- continue; /* Go ahead and try another arg. */
- if (required == '\0')
- break;
- if ((required == 'n')
- || (required == '+'))
- {
- optional = '*';
- required = '\0';
- }
- else if (required == 'p')
- required = 'n';
- } while (TRUE);
- }
-
- *xbt = bt;
- *xkt = kt;
- *xsz = sz;
- return FFEBAD;
-}
-
-static bool
-ffeintrin_check_any_ (ffebld arglist)
-{
- ffebld item;
-
- for (; arglist != NULL; arglist = ffebld_trail (arglist))
- {
- item = ffebld_head (arglist);
- if ((item != NULL)
- && (ffebld_op (item) == FFEBLD_opANY))
- return TRUE;
- }
-
- return FALSE;
-}
-
-/* Compare a forced-to-uppercase name with a known-upper-case name. */
-
-static int
-upcasecmp_ (const char *name, const char *ucname)
-{
- for ( ; *name != 0 && *ucname != 0; name++, ucname++)
- {
- int i = TOUPPER(*name) - *ucname;
-
- if (i != 0)
- return i;
- }
-
- return *name - *ucname;
-}
-
-/* Compare name to intrinsic's name.
- The intrinsics table is sorted on the upper case entries; so first
- compare irrespective of case on the `uc' entry. If it matches,
- compare according to the setting of intrinsics case comparison mode. */
-
-static int
-ffeintrin_cmp_name_ (const void *name, const void *intrinsic)
-{
- const char *const uc = ((const struct _ffeintrin_name_ *) intrinsic)->name_uc;
- const char *const lc = ((const struct _ffeintrin_name_ *) intrinsic)->name_lc;
- const char *const ic = ((const struct _ffeintrin_name_ *) intrinsic)->name_ic;
- int i;
-
- if ((i = upcasecmp_ (name, uc)) == 0)
- {
- switch (ffe_case_intrin ())
- {
- case FFE_caseLOWER:
- return strcmp(name, lc);
- case FFE_caseINITCAP:
- return strcmp(name, ic);
- default:
- return 0;
- }
- }
-
- return i;
-}
-
-/* Return basic type of intrinsic implementation, based on its
- run-time implementation *only*. (This is used only when
- the type of an intrinsic name is needed without having a
- list of arguments, i.e. an interface signature, such as when
- passing the intrinsic itself, or really the run-time-library
- function, as an argument.)
-
- If there's no eligible intrinsic implementation, there must be
- a bug somewhere else; no such reference should have been permitted
- to go this far. (Well, this might be wrong.) */
-
-ffeinfoBasictype
-ffeintrin_basictype (ffeintrinSpec spec)
-{
- ffeintrinImp imp;
- ffecomGfrt gfrt;
-
- assert (spec < FFEINTRIN_spec);
- imp = ffeintrin_specs_[spec].implementation;
- assert (imp < FFEINTRIN_imp);
-
- if (ffe_is_f2c ())
- gfrt = ffeintrin_imps_[imp].gfrt_f2c;
- else
- gfrt = ffeintrin_imps_[imp].gfrt_gnu;
-
- assert (gfrt != FFECOM_gfrt);
-
- return ffecom_gfrt_basictype (gfrt);
-}
-
-/* Return family to which specific intrinsic belongs. */
-
-ffeintrinFamily
-ffeintrin_family (ffeintrinSpec spec)
-{
- if (spec >= FFEINTRIN_spec)
- return FALSE;
- return ffeintrin_specs_[spec].family;
-}
-
-/* Check and fill in info on func/subr ref node.
-
- ffebld expr; // FUNCREF or SUBRREF with no info (caller
- // gets it from the modified info structure).
- ffeinfo info; // Already filled in, will be overwritten.
- ffelexToken token; // Used for error message.
- ffeintrin_fulfill_generic (&expr, &info, token);
-
- Based on the generic id, figure out which specific procedure is meant and
- pick that one. Else return an error, a la _specific. */
-
-void
-ffeintrin_fulfill_generic (ffebld *expr, ffeinfo *info, ffelexToken t)
-{
- ffebld symter;
- ffebldOp op;
- ffeintrinGen gen;
- ffeintrinSpec spec = FFEINTRIN_specNONE;
- ffeinfoBasictype bt = FFEINFO_basictypeNONE;
- ffeinfoKindtype kt = FFEINFO_kindtypeNONE;
- ffetargetCharacterSize sz = FFETARGET_charactersizeNONE;
- ffeintrinImp imp;
- ffeintrinSpec tspec;
- ffeintrinImp nimp = FFEINTRIN_impNONE;
- ffebad error;
- bool any = FALSE;
- bool highly_specific = FALSE;
- int i;
-
- op = ffebld_op (*expr);
- assert ((op == FFEBLD_opFUNCREF) || (op == FFEBLD_opSUBRREF));
- assert (ffebld_op (ffebld_left (*expr)) == FFEBLD_opSYMTER);
-
- gen = ffebld_symter_generic (ffebld_left (*expr));
- assert (gen != FFEINTRIN_genNONE);
-
- imp = FFEINTRIN_impNONE;
- error = FFEBAD;
-
- any = ffeintrin_check_any_ (ffebld_right (*expr));
-
- for (i = 0;
- (((size_t) i) < ARRAY_SIZE (ffeintrin_gens_[gen].specs))
- && ((tspec = ffeintrin_gens_[gen].specs[i]) != FFEINTRIN_specNONE)
- && !any;
- ++i)
- {
- ffeintrinImp timp = ffeintrin_specs_[tspec].implementation;
- ffeinfoBasictype tbt;
- ffeinfoKindtype tkt;
- ffetargetCharacterSize tsz;
- ffeIntrinsicState state
- = ffeintrin_state_family (ffeintrin_specs_[tspec].family);
- ffebad terror;
-
- if (state == FFE_intrinsicstateDELETED)
- continue;
-
- if (timp != FFEINTRIN_impNONE)
- {
- if (!(ffeintrin_imps_[timp].control[0] == '-')
- != !(ffebld_op (*expr) == FFEBLD_opSUBRREF))
- continue; /* Form of reference must match form of specific. */
- }
-
- if (state == FFE_intrinsicstateDISABLED)
- terror = FFEBAD_INTRINSIC_DISABLED;
- else if (timp == FFEINTRIN_impNONE)
- terror = FFEBAD_INTRINSIC_UNIMPL;
- else
- {
- terror = ffeintrin_check_ (timp, ffebld_op (*expr),
- ffebld_right (*expr),
- &tbt, &tkt, &tsz, NULL, t, FALSE);
- if (terror == FFEBAD)
- {
- if (imp != FFEINTRIN_impNONE)
- {
- ffebad_start (FFEBAD_INTRINSIC_AMBIG);
- ffebad_here (0, ffelex_token_where_line (t),
- ffelex_token_where_column (t));
- ffebad_string (ffeintrin_gens_[gen].name);
- ffebad_string (ffeintrin_specs_[spec].name);
- ffebad_string (ffeintrin_specs_[tspec].name);
- ffebad_finish ();
- }
- else
- {
- if (ffebld_symter_specific (ffebld_left (*expr))
- == tspec)
- highly_specific = TRUE;
- imp = timp;
- spec = tspec;
- bt = tbt;
- kt = tkt;
- sz = tkt;
- error = terror;
- }
- }
- else if (terror != FFEBAD)
- { /* This error has precedence over others. */
- if ((error == FFEBAD_INTRINSIC_DISABLED)
- || (error == FFEBAD_INTRINSIC_UNIMPL))
- error = FFEBAD;
- }
- }
-
- if (error == FFEBAD)
- error = terror;
- }
-
- if (any || (imp == FFEINTRIN_impNONE))
- {
- if (!any)
- {
- if (error == FFEBAD)
- error = FFEBAD_INTRINSIC_REF;
- ffebad_start (error);
- ffebad_here (0, ffelex_token_where_line (t),
- ffelex_token_where_column (t));
- ffebad_string (ffeintrin_gens_[gen].name);
- ffebad_finish ();
- }
-
- *expr = ffebld_new_any ();
- *info = ffeinfo_new_any ();
- }
- else
- {
- if (!highly_specific && (nimp != FFEINTRIN_impNONE))
- {
- fprintf (stderr, "lineno=%ld, gen=%s, imp=%s, timp=%s\n",
- (long) input_line,
- ffeintrin_gens_[gen].name,
- ffeintrin_imps_[imp].name,
- ffeintrin_imps_[nimp].name);
- assert ("Ambiguous generic reference" == NULL);
- abort ();
- }
- error = ffeintrin_check_ (imp, ffebld_op (*expr),
- ffebld_right (*expr),
- &bt, &kt, &sz, NULL, t, TRUE);
- assert (error == FFEBAD);
- *info = ffeinfo_new (bt,
- kt,
- 0,
- FFEINFO_kindENTITY,
- FFEINFO_whereFLEETING,
- sz);
- symter = ffebld_left (*expr);
- ffebld_symter_set_specific (symter, spec);
- ffebld_symter_set_implementation (symter, imp);
- ffebld_set_info (symter,
- ffeinfo_new (bt,
- kt,
- 0,
- (bt == FFEINFO_basictypeNONE)
- ? FFEINFO_kindSUBROUTINE
- : FFEINFO_kindFUNCTION,
- FFEINFO_whereINTRINSIC,
- sz));
-
- if ((ffesymbol_attrs (ffebld_symter (symter)) & FFESYMBOL_attrsTYPE)
- && (((bt != ffesymbol_basictype (ffebld_symter (symter)))
- || (kt != ffesymbol_kindtype (ffebld_symter (symter)))
- || ((sz != FFETARGET_charactersizeNONE)
- && (sz != ffesymbol_size (ffebld_symter (symter)))))))
- {
- ffebad_start (FFEBAD_INTRINSIC_TYPE);
- ffebad_here (0, ffelex_token_where_line (t),
- ffelex_token_where_column (t));
- ffebad_string (ffeintrin_gens_[gen].name);
- ffebad_finish ();
- }
- if (ffeintrin_imps_[imp].y2kbad)
- {
- ffebad_start (FFEBAD_INTRINSIC_Y2KBAD);
- ffebad_here (0, ffelex_token_where_line (t),
- ffelex_token_where_column (t));
- ffebad_string (ffeintrin_gens_[gen].name);
- ffebad_finish ();
- }
- }
-}
-
-/* Check and fill in info on func/subr ref node.
-
- ffebld expr; // FUNCREF or SUBRREF with no info (caller
- // gets it from the modified info structure).
- ffeinfo info; // Already filled in, will be overwritten.
- bool check_intrin; // May be omitted, else set TRUE if intrinsic needs checking.
- ffelexToken token; // Used for error message.
- ffeintrin_fulfill_specific (&expr, &info, &check_intrin, token);
-
- Based on the specific id, determine whether the arg list is valid
- (number, type, rank, and kind of args) and fill in the info structure
- accordingly. Currently don't rewrite the expression, but perhaps
- someday do so for constant collapsing, except when an error occurs,
- in which case it is overwritten with ANY and info is also overwritten
- accordingly. */
-
-void
-ffeintrin_fulfill_specific (ffebld *expr, ffeinfo *info,
- bool *check_intrin, ffelexToken t)
-{
- ffebld symter;
- ffebldOp op;
- ffeintrinGen gen;
- ffeintrinSpec spec;
- ffeintrinImp imp;
- ffeinfoBasictype bt = FFEINFO_basictypeNONE;
- ffeinfoKindtype kt = FFEINFO_kindtypeNONE;
- ffetargetCharacterSize sz = FFETARGET_charactersizeNONE;
- ffeIntrinsicState state;
- ffebad error;
- bool any = FALSE;
- const char *name;
-
- op = ffebld_op (*expr);
- assert ((op == FFEBLD_opFUNCREF) || (op == FFEBLD_opSUBRREF));
- assert (ffebld_op (ffebld_left (*expr)) == FFEBLD_opSYMTER);
-
- gen = ffebld_symter_generic (ffebld_left (*expr));
- spec = ffebld_symter_specific (ffebld_left (*expr));
- assert (spec != FFEINTRIN_specNONE);
-
- if (gen != FFEINTRIN_genNONE)
- name = ffeintrin_gens_[gen].name;
- else
- name = ffeintrin_specs_[spec].name;
-
- state = ffeintrin_state_family (ffeintrin_specs_[spec].family);
-
- imp = ffeintrin_specs_[spec].implementation;
- if (check_intrin != NULL)
- *check_intrin = FALSE;
-
- any = ffeintrin_check_any_ (ffebld_right (*expr));
-
- if (state == FFE_intrinsicstateDISABLED)
- error = FFEBAD_INTRINSIC_DISABLED;
- else if (imp == FFEINTRIN_impNONE)
- error = FFEBAD_INTRINSIC_UNIMPL;
- else if (!any)
- {
- error = ffeintrin_check_ (imp, ffebld_op (*expr),
- ffebld_right (*expr),
- &bt, &kt, &sz, check_intrin, t, TRUE);
- }
- else
- error = FFEBAD; /* Not really needed, but quiet -Wuninitialized. */
-
- if (any || (error != FFEBAD))
- {
- if (!any)
- {
-
- ffebad_start (error);
- ffebad_here (0, ffelex_token_where_line (t),
- ffelex_token_where_column (t));
- ffebad_string (name);
- ffebad_finish ();
- }
-
- *expr = ffebld_new_any ();
- *info = ffeinfo_new_any ();
- }
- else
- {
- *info = ffeinfo_new (bt,
- kt,
- 0,
- FFEINFO_kindENTITY,
- FFEINFO_whereFLEETING,
- sz);
- symter = ffebld_left (*expr);
- ffebld_set_info (symter,
- ffeinfo_new (bt,
- kt,
- 0,
- (bt == FFEINFO_basictypeNONE)
- ? FFEINFO_kindSUBROUTINE
- : FFEINFO_kindFUNCTION,
- FFEINFO_whereINTRINSIC,
- sz));
-
- if ((ffesymbol_attrs (ffebld_symter (symter)) & FFESYMBOL_attrsTYPE)
- && (((bt != ffesymbol_basictype (ffebld_symter (symter)))
- || (kt != ffesymbol_kindtype (ffebld_symter (symter)))
- || (sz != ffesymbol_size (ffebld_symter (symter))))))
- {
- ffebad_start (FFEBAD_INTRINSIC_TYPE);
- ffebad_here (0, ffelex_token_where_line (t),
- ffelex_token_where_column (t));
- ffebad_string (name);
- ffebad_finish ();
- }
- if (ffeintrin_imps_[imp].y2kbad)
- {
- ffebad_start (FFEBAD_INTRINSIC_Y2KBAD);
- ffebad_here (0, ffelex_token_where_line (t),
- ffelex_token_where_column (t));
- ffebad_string (name);
- ffebad_finish ();
- }
- }
-}
-
-/* Return run-time index of intrinsic implementation as direct call. */
-
-ffecomGfrt
-ffeintrin_gfrt_direct (ffeintrinImp imp)
-{
- assert (imp < FFEINTRIN_imp);
-
- return ffeintrin_imps_[imp].gfrt_direct;
-}
-
-/* Return run-time index of intrinsic implementation as actual argument. */
-
-ffecomGfrt
-ffeintrin_gfrt_indirect (ffeintrinImp imp)
-{
- assert (imp < FFEINTRIN_imp);
-
- if (! ffe_is_f2c ())
- return ffeintrin_imps_[imp].gfrt_gnu;
- return ffeintrin_imps_[imp].gfrt_f2c;
-}
-
-void
-ffeintrin_init_0 (void)
-{
- int i;
- const char *p1;
- const char *p2;
- const char *p3;
- int colon;
-
- if (!ffe_is_do_internal_checks ())
- return;
-
- assert (FFEINTRIN_gen == ARRAY_SIZE (ffeintrin_gens_));
- assert (FFEINTRIN_imp == ARRAY_SIZE (ffeintrin_imps_));
- assert (FFEINTRIN_spec == ARRAY_SIZE (ffeintrin_specs_));
-
- for (i = 1; ((size_t) i) < ARRAY_SIZE (ffeintrin_names_); ++i)
- { /* Make sure binary-searched list is in alpha
- order. */
- if (strcmp (ffeintrin_names_[i - 1].name_uc,
- ffeintrin_names_[i].name_uc) >= 0)
- assert ("name list out of order" == NULL);
- }
-
- for (i = 0; ((size_t) i) < ARRAY_SIZE (ffeintrin_names_); ++i)
- {
- assert ((ffeintrin_names_[i].generic == FFEINTRIN_genNONE)
- || (ffeintrin_names_[i].specific == FFEINTRIN_specNONE));
-
- p1 = ffeintrin_names_[i].name_uc;
- p2 = ffeintrin_names_[i].name_lc;
- p3 = ffeintrin_names_[i].name_ic;
- for (; *p1 != '\0' && *p2 != '\0' && *p3 != '\0'; ++p1, ++p2, ++p3)
- {
- if ((ISDIGIT (*p1) || (*p1 == '_')) && (*p1 == *p2) && (*p1 == *p3))
- continue;
- if (! ISUPPER ((unsigned char)*p1) || ! ISLOWER ((unsigned char)*p2)
- || (*p1 != TOUPPER (*p2))
- || ((*p3 != *p1) && (*p3 != *p2)))
- break;
- }
- assert ((*p1 == *p2) && (*p1 == *p3) && (*p1 == '\0'));
- }
-
- for (i = 0; ((size_t) i) < ARRAY_SIZE (ffeintrin_imps_); ++i)
- {
- const char *c = ffeintrin_imps_[i].control;
-
- if (c[0] == '\0')
- continue;
-
- if ((c[0] != '-')
- && (c[0] != 'A')
- && (c[0] != 'C')
- && (c[0] != 'I')
- && (c[0] != 'L')
- && (c[0] != 'R')
- && (c[0] != 'B')
- && (c[0] != 'F')
- && (c[0] != 'N')
- && (c[0] != 'S'))
- {
- fprintf (stderr, "%s: bad return-base-type\n",
- ffeintrin_imps_[i].name);
- continue;
- }
- if ((c[1] != '-')
- && (c[1] != '=')
- && ((c[1] < '1')
- || (c[1] > '9'))
- && (c[1] != 'C'))
- {
- fprintf (stderr, "%s: bad return-kind-type\n",
- ffeintrin_imps_[i].name);
- continue;
- }
- if (c[2] == ':')
- colon = 2;
- else
- {
- if (c[2] != '*')
- {
- fprintf (stderr, "%s: bad return-modifier\n",
- ffeintrin_imps_[i].name);
- continue;
- }
- colon = 3;
- }
- if ((c[colon] != ':') || (c[colon + 2] != ':'))
- {
- fprintf (stderr, "%s: bad control\n",
- ffeintrin_imps_[i].name);
- continue;
- }
- if ((c[colon + 1] != '-')
- && (c[colon + 1] != '*')
- && (! ISDIGIT (c[colon + 1])))
- {
- fprintf (stderr, "%s: bad COL-spec\n",
- ffeintrin_imps_[i].name);
- continue;
- }
- c += (colon + 3);
- while (c[0] != '\0')
- {
- while ((c[0] != '=')
- && (c[0] != ',')
- && (c[0] != '\0'))
- ++c;
- if (c[0] != '=')
- {
- fprintf (stderr, "%s: bad keyword\n",
- ffeintrin_imps_[i].name);
- break;
- }
- if ((c[1] == '?')
- || (c[1] == '!')
- || (c[1] == '+')
- || (c[1] == '*')
- || (c[1] == 'n')
- || (c[1] == 'p'))
- ++c;
- if ((c[1] != '-')
- && (c[1] != 'A')
- && (c[1] != 'C')
- && (c[1] != 'I')
- && (c[1] != 'L')
- && (c[1] != 'R')
- && (c[1] != 'B')
- && (c[1] != 'F')
- && (c[1] != 'N')
- && (c[1] != 'S')
- && (c[1] != 'g')
- && (c[1] != 's'))
- {
- fprintf (stderr, "%s: bad arg-base-type\n",
- ffeintrin_imps_[i].name);
- break;
- }
- if ((c[2] != '*')
- && ((c[2] < '1')
- || (c[2] > '9'))
- && (c[2] != 'A'))
- {
- fprintf (stderr, "%s: bad arg-kind-type\n",
- ffeintrin_imps_[i].name);
- break;
- }
- if (c[3] == '[')
- {
- if ((! ISDIGIT (c[4]))
- || ((c[5] != ']')
- && (++c, ! ISDIGIT (c[4])
- || (c[5] != ']'))))
- {
- fprintf (stderr, "%s: bad arg-len\n",
- ffeintrin_imps_[i].name);
- break;
- }
- c += 3;
- }
- if (c[3] == '(')
- {
- if ((! ISDIGIT (c[4]))
- || ((c[5] != ')')
- && (++c, ! ISDIGIT (c[4])
- || (c[5] != ')'))))
- {
- fprintf (stderr, "%s: bad arg-rank\n",
- ffeintrin_imps_[i].name);
- break;
- }
- c += 3;
- }
- else if ((c[3] == '&')
- && (c[4] == '&'))
- ++c;
- if ((c[3] == '&')
- || (c[3] == 'i')
- || (c[3] == 'w')
- || (c[3] == 'x'))
- ++c;
- if (c[3] == ',')
- {
- c += 4;
- continue;
- }
- if (c[3] != '\0')
- {
- fprintf (stderr, "%s: bad arg-list\n",
- ffeintrin_imps_[i].name);
- }
- break;
- }
- }
-}
-
-/* Determine whether intrinsic is okay as an actual argument. */
-
-bool
-ffeintrin_is_actualarg (ffeintrinSpec spec)
-{
- ffeIntrinsicState state;
-
- if (spec >= FFEINTRIN_spec)
- return FALSE;
-
- state = ffeintrin_state_family (ffeintrin_specs_[spec].family);
-
- return (!ffe_is_pedantic () || ffeintrin_specs_[spec].is_actualarg)
- && (ffe_is_f2c ()
- ? (ffeintrin_imps_[ffeintrin_specs_[spec].implementation].gfrt_f2c
- != FFECOM_gfrt)
- : (ffeintrin_imps_[ffeintrin_specs_[spec].implementation].gfrt_gnu
- != FFECOM_gfrt))
- && ((state == FFE_intrinsicstateENABLED)
- || (state == FFE_intrinsicstateHIDDEN));
-}
-
-/* Determine if name is intrinsic, return info.
-
- const char *name; // C-string name of possible intrinsic.
- ffelexToken t; // NULL if no diagnostic to be given.
- bool explicit; // TRUE if INTRINSIC name.
- ffeintrinGen gen; // (TRUE only) Generic id of intrinsic.
- ffeintrinSpec spec; // (TRUE only) Specific id of intrinsic.
- ffeintrinImp imp; // (TRUE only) Implementation id of intrinsic.
- if (ffeintrin_is_intrinsic (name, t, explicit,
- &gen, &spec, &imp))
- // is an intrinsic, use gen, spec, imp, and
- // kind accordingly. */
-
-bool
-ffeintrin_is_intrinsic (const char *name, ffelexToken t, bool explicit,
- ffeintrinGen *xgen, ffeintrinSpec *xspec,
- ffeintrinImp *ximp)
-{
- struct _ffeintrin_name_ *intrinsic;
- ffeintrinGen gen;
- ffeintrinSpec spec;
- ffeintrinImp imp;
- ffeIntrinsicState state;
- bool disabled = FALSE;
- bool unimpl = FALSE;
-
- intrinsic = bsearch (name, &ffeintrin_names_[0],
- ARRAY_SIZE (ffeintrin_names_),
- sizeof (struct _ffeintrin_name_),
- (void *) ffeintrin_cmp_name_);
-
- if (intrinsic == NULL)
- return FALSE;
-
- gen = intrinsic->generic;
- spec = intrinsic->specific;
- imp = ffeintrin_specs_[spec].implementation;
-
- /* Generic is okay only if at least one of its specifics is okay. */
-
- if (gen != FFEINTRIN_genNONE)
- {
- int i;
- ffeintrinSpec tspec;
- bool ok = FALSE;
-
- name = ffeintrin_gens_[gen].name;
-
- for (i = 0;
- (((size_t) i) < ARRAY_SIZE (ffeintrin_gens_[gen].specs))
- && ((tspec
- = ffeintrin_gens_[gen].specs[i]) != FFEINTRIN_specNONE);
- ++i)
- {
- state = ffeintrin_state_family (ffeintrin_specs_[tspec].family);
-
- if (state == FFE_intrinsicstateDELETED)
- continue;
-
- if (state == FFE_intrinsicstateDISABLED)
- {
- disabled = TRUE;
- continue;
- }
-
- if (ffeintrin_specs_[tspec].implementation == FFEINTRIN_impNONE)
- {
- unimpl = TRUE;
- continue;
- }
-
- if ((state == FFE_intrinsicstateENABLED)
- || (explicit
- && (state == FFE_intrinsicstateHIDDEN)))
- {
- ok = TRUE;
- break;
- }
- }
- if (!ok)
- gen = FFEINTRIN_genNONE;
- }
-
- /* Specific is okay only if not: unimplemented, disabled, deleted, or
- hidden and not explicit. */
-
- if (spec != FFEINTRIN_specNONE)
- {
- if (gen != FFEINTRIN_genNONE)
- name = ffeintrin_gens_[gen].name;
- else
- name = ffeintrin_specs_[spec].name;
-
- if (((state = ffeintrin_state_family (ffeintrin_specs_[spec].family))
- == FFE_intrinsicstateDELETED)
- || (!explicit
- && (state == FFE_intrinsicstateHIDDEN)))
- spec = FFEINTRIN_specNONE;
- else if (state == FFE_intrinsicstateDISABLED)
- {
- disabled = TRUE;
- spec = FFEINTRIN_specNONE;
- }
- else if (imp == FFEINTRIN_impNONE)
- {
- unimpl = TRUE;
- spec = FFEINTRIN_specNONE;
- }
- }
-
- /* If neither is okay, not an intrinsic. */
-
- if ((gen == FFEINTRIN_genNONE) && (spec == FFEINTRIN_specNONE))
- {
- /* Here is where we produce a diagnostic about a reference to a
- disabled or unimplemented intrinsic, if the diagnostic is desired. */
-
- if ((disabled || unimpl)
- && (t != NULL))
- {
- ffebad_start (disabled
- ? FFEBAD_INTRINSIC_DISABLED
- : FFEBAD_INTRINSIC_UNIMPLW);
- ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
- ffebad_string (name);
- ffebad_finish ();
- }
-
- return FALSE;
- }
-
- /* Determine whether intrinsic is function or subroutine. If no specific
- id, scan list of possible specifics for generic to get consensus. If
- not unanimous, or clear from the context, return NONE. */
-
- if (spec == FFEINTRIN_specNONE)
- {
- int i;
- ffeintrinSpec tspec;
- ffeintrinImp timp;
- bool at_least_one_ok = FALSE;
-
- for (i = 0;
- (((size_t) i) < ARRAY_SIZE (ffeintrin_gens_[gen].specs))
- && ((tspec
- = ffeintrin_gens_[gen].specs[i]) != FFEINTRIN_specNONE);
- ++i)
- {
- if (((state = ffeintrin_state_family (ffeintrin_specs_[tspec].family))
- == FFE_intrinsicstateDELETED)
- || (state == FFE_intrinsicstateDISABLED))
- continue;
-
- if ((timp = ffeintrin_specs_[tspec].implementation)
- == FFEINTRIN_impNONE)
- continue;
-
- at_least_one_ok = TRUE;
- break;
- }
-
- if (!at_least_one_ok)
- {
- *xgen = FFEINTRIN_genNONE;
- *xspec = FFEINTRIN_specNONE;
- *ximp = FFEINTRIN_impNONE;
- return FALSE;
- }
- }
-
- *xgen = gen;
- *xspec = spec;
- *ximp = imp;
- return TRUE;
-}
-
-/* Return TRUE if intrinsic is standard F77 (or, if -ff90, F90). */
-
-bool
-ffeintrin_is_standard (ffeintrinGen gen, ffeintrinSpec spec)
-{
- if (spec == FFEINTRIN_specNONE)
- {
- if (gen == FFEINTRIN_genNONE)
- return FALSE;
-
- spec = ffeintrin_gens_[gen].specs[0];
- if (spec == FFEINTRIN_specNONE)
- return FALSE;
- }
-
- if ((ffeintrin_specs_[spec].family == FFEINTRIN_familyF77)
- || (ffe_is_90 ()
- && ((ffeintrin_specs_[spec].family == FFEINTRIN_familyF90)
- || (ffeintrin_specs_[spec].family == FFEINTRIN_familyMIL)
- || (ffeintrin_specs_[spec].family == FFEINTRIN_familyASC))))
- return TRUE;
- return FALSE;
-}
-
-/* Return kind type of intrinsic implementation. See ffeintrin_basictype,
- its sibling. */
-
-ffeinfoKindtype
-ffeintrin_kindtype (ffeintrinSpec spec)
-{
- ffeintrinImp imp;
- ffecomGfrt gfrt;
-
- assert (spec < FFEINTRIN_spec);
- imp = ffeintrin_specs_[spec].implementation;
- assert (imp < FFEINTRIN_imp);
-
- if (ffe_is_f2c ())
- gfrt = ffeintrin_imps_[imp].gfrt_f2c;
- else
- gfrt = ffeintrin_imps_[imp].gfrt_gnu;
-
- assert (gfrt != FFECOM_gfrt);
-
- return ffecom_gfrt_kindtype (gfrt);
-}
-
-/* Return name of generic intrinsic. */
-
-const char *
-ffeintrin_name_generic (ffeintrinGen gen)
-{
- assert (gen < FFEINTRIN_gen);
- return ffeintrin_gens_[gen].name;
-}
-
-/* Return name of intrinsic implementation. */
-
-const char *
-ffeintrin_name_implementation (ffeintrinImp imp)
-{
- assert (imp < FFEINTRIN_imp);
- return ffeintrin_imps_[imp].name;
-}
-
-/* Return external/internal name of specific intrinsic. */
-
-const char *
-ffeintrin_name_specific (ffeintrinSpec spec)
-{
- assert (spec < FFEINTRIN_spec);
- return ffeintrin_specs_[spec].name;
-}
-
-/* Return state of family. */
-
-ffeIntrinsicState
-ffeintrin_state_family (ffeintrinFamily family)
-{
- ffeIntrinsicState state;
-
- switch (family)
- {
- case FFEINTRIN_familyNONE:
- return FFE_intrinsicstateDELETED;
-
- case FFEINTRIN_familyF77:
- return FFE_intrinsicstateENABLED;
-
- case FFEINTRIN_familyASC:
- state = ffe_intrinsic_state_f2c ();
- state = ffe_state_max (state, ffe_intrinsic_state_f90 ());
- return state;
-
- case FFEINTRIN_familyMIL:
- state = ffe_intrinsic_state_vxt ();
- state = ffe_state_max (state, ffe_intrinsic_state_f90 ());
- state = ffe_state_max (state, ffe_intrinsic_state_mil ());
- return state;
-
- case FFEINTRIN_familyGNU:
- state = ffe_intrinsic_state_gnu ();
- return state;
-
- case FFEINTRIN_familyF90:
- state = ffe_intrinsic_state_f90 ();
- return state;
-
- case FFEINTRIN_familyVXT:
- state = ffe_intrinsic_state_vxt ();
- return state;
-
- case FFEINTRIN_familyFVZ:
- state = ffe_intrinsic_state_f2c ();
- state = ffe_state_max (state, ffe_intrinsic_state_vxt ());
- return state;
-
- case FFEINTRIN_familyF2C:
- state = ffe_intrinsic_state_f2c ();
- return state;
-
- case FFEINTRIN_familyF2U:
- state = ffe_intrinsic_state_unix ();
- return state;
-
- case FFEINTRIN_familyBADU77:
- state = ffe_intrinsic_state_badu77 ();
- return state;
-
- default:
- assert ("bad family" == NULL);
- return FFE_intrinsicstateDELETED;
- }
-}
OpenPOWER on IntegriCloud