📄 intdoc.c
字号:
/* intdoc.c Copyright (C) 1997 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 modifyit under the terms of the GNU General Public License as published bythe 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Fortran; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA02111-1307, USA. *//* From f/proj.h, which uses #error -- not all C compilers support that, and we want *this* program to be compilable by pretty much any C compiler. */#include "hconfig.j"#include "system.j"#include "assert.j"#if HAVE_STDDEF_H#include <stddef.h>#endiftypedef enum {#if !defined(false) || !defined(true) false = 0, true = 1,#endif#if !defined(FALSE) || !defined(TRUE) FALSE = 0, TRUE = 1,#endif Doggone_Trailing_Comma_Dont_Work = 1 } bool;#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))/* Pull in the intrinsics info, but only the doc parts. */#define FFEINTRIN_DOC 1#include "intrin.h"const char *family_name (ffeintrinFamily family);static void dumpif (ffeintrinFamily fam);static void dumpendif (void);static void dumpclearif (void);static void dumpem (void);static void dumpgen (int menu, const char *name, const char *name_uc, ffeintrinGen gen);static void dumpspec (int menu, const char *name, const char *name_uc, ffeintrinSpec spec);static void dumpimp (int menu, const char *name, const char *name_uc, size_t genno, ffeintrinFamily family, ffeintrinImp imp, ffeintrinSpec spec);static const char *argument_info_ptr (ffeintrinImp imp, int argno);static const char *argument_info_string (ffeintrinImp imp, int argno);static const char *argument_name_ptr (ffeintrinImp imp, int argno);static const char *argument_name_string (ffeintrinImp imp, int argno);#if 0static const char *elaborate_if_complex (ffeintrinImp imp, int argno);static const char *elaborate_if_maybe_complex (ffeintrinImp imp, int argno);static const char *elaborate_if_real (ffeintrinImp imp, int argno);#endifstatic void print_type_string (const char *c);intmain (int argc, char **argv ATTRIBUTE_UNUSED){ if (argc != 1) { fprintf (stderr, "\Usage: intdoc > intdoc.texi\n\ Collects and dumps documentation on g77 intrinsics\n\ to the file named intdoc.texi.\n"); exit (1); } dumpem (); return 0;}struct _ffeintrin_name_ { const char *name_uc; const char *name_lc; const char *name_ic; ffeintrinGen generic; ffeintrinSpec specific; };struct _ffeintrin_gen_ { const char *name; /* Name as seen in program. */ ffeintrinSpec specs[2]; };struct _ffeintrin_spec_ { const char *name; /* Uppercase name as seen in source code, lowercase if no source name, "none" if no name at all (NONE case). */ bool is_actualarg; /* Ok to pass as actual arg if -pedantic. */ ffeintrinFamily family; ffeintrinImp implementation; };struct _ffeintrin_imp_ { const char *name; /* Name of implementation. */#if 0 /* FFECOM_targetCURRENT == FFECOM_targetGCC */ ffecomGfrt gfrt; /* gfrt index in library. */#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */ const char *control; };static struct _ffeintrin_name_ names[] = {#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 struct _ffeintrin_gen_ 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 struct _ffeintrin_imp_ imps[] = {#define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC)#define DEFGEN(CODE,NAME,SPEC1,SPEC2)#define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)#if 0 /* FFECOM_targetCURRENT == FFECOM_targetGCC */#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL) \ { NAME, FFECOM_gfrt ## GFRT, CONTROL },#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD) \ { NAME, FFECOM_gfrt ## GFRT, CONTROL },#elif 1 /* FFECOM_targetCURRENT == FFECOM_targetFFE */#define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL) \ { NAME, CONTROL },#define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD) \ { NAME, CONTROL },#else#error#endif#include "intrin.def"#undef DEFNAME#undef DEFGEN#undef DEFSPEC#undef DEFIMP#undef DEFIMPY};static struct _ffeintrin_spec_ 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};struct cc_pair { ffeintrinImp imp; const char *text; };static const char *descriptions[FFEINTRIN_imp] = { 0 };static struct cc_pair cc_descriptions[] = {#define DEFDOC(IMP,SUMMARY,DESCRIPTION) { FFEINTRIN_imp ## IMP, DESCRIPTION },#include "intdoc.h0"#undef DEFDOC};static const char *summaries[FFEINTRIN_imp] = { 0 };static struct cc_pair cc_summaries[] = {#define DEFDOC(IMP,SUMMARY,DESCRIPTION) { FFEINTRIN_imp ## IMP, SUMMARY },#include "intdoc.h0"#undef DEFDOC};const char *family_name (ffeintrinFamily family){ switch (family) { case FFEINTRIN_familyF77: return "familyF77"; case FFEINTRIN_familyASC: return "familyASC"; case FFEINTRIN_familyMIL: return "familyMIL"; case FFEINTRIN_familyGNU: return "familyGNU"; case FFEINTRIN_familyF90: return "familyF90"; case FFEINTRIN_familyVXT: return "familyVXT"; case FFEINTRIN_familyFVZ: return "familyFVZ"; case FFEINTRIN_familyF2C: return "familyF2C"; case FFEINTRIN_familyF2U: return "familyF2U"; case FFEINTRIN_familyBADU77: return "familyBADU77"; default: assert ("bad family" == NULL); return "??"; }}static int in_ifset = 0;static ffeintrinFamily latest_family = FFEINTRIN_familyNONE;static voiddumpif (ffeintrinFamily fam){ assert (fam != FFEINTRIN_familyNONE); if ((in_ifset != 2) || (fam != latest_family)) { if (in_ifset == 2) printf ("@end ifset\n"); latest_family = fam; printf ("@ifset %s\n", family_name (fam)); } in_ifset = 1;}static voiddumpendif (){ in_ifset = 2;}static voiddumpclearif (){ if ((in_ifset == 2) || (latest_family != FFEINTRIN_familyNONE)) printf ("@end ifset\n"); latest_family = FFEINTRIN_familyNONE; in_ifset = 0;}static voiddumpem (){ int i; for (i = 0; ((size_t) i) < ARRAY_SIZE (cc_descriptions); ++i) { assert (descriptions[cc_descriptions[i].imp] == NULL); descriptions[cc_descriptions[i].imp] = cc_descriptions[i].text; } for (i = 0; ((size_t) i) < ARRAY_SIZE (cc_summaries); ++i) { assert (summaries[cc_summaries[i].imp] == NULL); summaries[cc_summaries[i].imp] = cc_summaries[i].text; } printf ("@c This file is automatically derived from intdoc.c, intdoc.in,\n"); printf ("@c ansify.c, intrin.def, and intrin.h. Edit those files instead.\n"); printf ("@menu\n"); for (i = 0; ((size_t) i) < ARRAY_SIZE (names); ++i) { if (names[i].generic != FFEINTRIN_genNONE) dumpgen (1, names[i].name_ic, names[i].name_uc, names[i].generic); if (names[i].specific != FFEINTRIN_specNONE) dumpspec (1, names[i].name_ic, names[i].name_uc, names[i].specific); } dumpclearif (); printf ("@end menu\n\n"); for (i = 0; ((size_t) i) < ARRAY_SIZE (names); ++i) { if (names[i].generic != FFEINTRIN_genNONE) dumpgen (0, names[i].name_ic, names[i].name_uc, names[i].generic); if (names[i].specific != FFEINTRIN_specNONE) dumpspec (0, names[i].name_ic, names[i].name_uc, names[i].specific); } dumpclearif ();}static voiddumpgen (int menu, const char *name, const char *name_uc, ffeintrinGen gen){ size_t i; int total = 0; if (!menu) { for (i = 0; i < ARRAY_SIZE (gens[gen].specs); ++i) { if (gens[gen].specs[i] != FFEINTRIN_specNONE) ++total; } } for (i = 0; i < ARRAY_SIZE (gens[gen].specs); ++i) { ffeintrinSpec spec; size_t j; if ((spec = gens[gen].specs[i]) == FFEINTRIN_specNONE) continue; dumpif (specs[spec].family); dumpimp (menu, name, name_uc, i, specs[spec].family, specs[spec].implementation, spec); if (!menu && (total > 0)) { if (total == 1) { printf ("\For information on another intrinsic with the same name:\n"); } else { printf ("\For information on other intrinsics with the same name:\n"); } for (j = 0; j < ARRAY_SIZE (gens[gen].specs); ++j) { if (j == i) continue; if ((spec = gens[gen].specs[j]) == FFEINTRIN_specNONE) continue; printf ("@xref{%s Intrinsic (%s)}.\n", name, specs[spec].name); } printf ("\n"); } dumpendif (); }}static voiddumpspec (int menu, const char *name, const char *name_uc, ffeintrinSpec spec){ dumpif (specs[spec].family); dumpimp (menu, name, name_uc, 0, specs[spec].family, specs[spec].implementation, FFEINTRIN_specNONE); dumpendif ();}static voiddumpimp (int menu, const char *name, const char *name_uc, size_t genno, ffeintrinFamily family, ffeintrinImp imp, ffeintrinSpec spec){ const char *c; bool subr; const char *argc; const char *argi; int colon; int argno; assert ((imp != FFEINTRIN_impNONE) || !genno); if (menu) { printf ("* %s Intrinsic", name); if (spec != FFEINTRIN_specNONE) printf (" (%s)", specs[spec].name); /* See XYZZY1 below */ printf ("::");#define INDENT_SUMMARY 24 if ((imp == FFEINTRIN_impNONE) || (summaries[imp] != NULL)) { int spaces = INDENT_SUMMARY - 14 - strlen (name); const char *c; if (spec != FFEINTRIN_specNONE) spaces -= (3 + strlen (specs[spec].name)); /* See XYZZY1 above */ if (spaces < 1) spaces = 1; while (spaces--) fputc (' ', stdout); if (imp == FFEINTRIN_impNONE) { printf ("(Reserved for future use.)\n"); return; } for (c = summaries[imp]; c[0] != '\0'; ++c) { if ((c[0] == '@') && (c[1] >= '0') && (c[1] <= '9')) { int argno = c[1] - '0'; c += 2; while ((c[0] >= '0') && (c[0] <= '9')) { argno = 10 * argno + (c[0] - '0'); ++c; } assert (c[0] == '@'); if (argno == 0) printf ("%s", name); else if (argno == 99) { /* Yeah, this is a major kludge. */ printf ("\n"); spaces = INDENT_SUMMARY + 1; while (spaces--) fputc (' ', stdout); } else printf ("%s", argument_name_string (imp, argno - 1)); } else fputc (c[0], stdout); } } printf ("\n"); return; } printf ("@node %s Intrinsic", name); if (spec != FFEINTRIN_specNONE) printf (" (%s)", specs[spec].name); printf ("\n@subsubsection %s Intrinsic", name); if (spec != FFEINTRIN_specNONE) printf (" (%s)", specs[spec].name); printf ("\n@cindex %s intrinsic\n@cindex intrinsics, %s\n", name, name); if (imp == FFEINTRIN_impNONE) { printf ("\n\This intrinsic is not yet implemented.\n\The name is, however, reserved as an intrinsic.\n\Use @samp{EXTERNAL %s} to use this name for an\n\external procedure.\n\\n\", name); return; } c = imps[imp].control; subr = (c[0] == '-'); colon = (c[2] == ':') ? 2 : 3; printf ("\n\@noindent\n\@example\n\%s%s(", (subr ? "CALL " : ""), name); fflush (stdout); for (argno = 0; ; ++argno) { argc = argument_name_ptr (imp, argno); if (argc == NULL) break; if (argno > 0) printf (", "); printf ("@var{%s}", argc); argi = argument_info_string (imp, argno); if ((argi[0] == '*') || (argi[0] == 'n') || (argi[0] == '+') || (argi[0] == 'p')) printf ("-1, @var{%s}-2, @dots{}, @var{%s}-n", argc, argc); } printf (")\n\@end example\n\\n\"); if (!subr) { int other_arg; const char *arg_string; const char *arg_info; if ((c[colon + 1] >= '0') && (c[colon + 1] <= '9')) { other_arg = c[colon + 1] - '0'; arg_string = argument_name_string (imp, other_arg); arg_info = argument_info_string (imp, other_arg); } else { other_arg = -1; arg_string = NULL; arg_info = NULL; } printf ("\@noindent\n\%s: ", name); print_type_string (c); printf (" function"); if ((c[0] == 'R') && (c[1] == 'C')) { assert (other_arg >= 0); if ((arg_info[0] == '?') || (arg_info[0] == '!') || (arg_info[0] == '+') || (arg_info[0] == '*') || (arg_info[0] == 'n') || (arg_info[0] == 'p')) ++arg_info; if ((arg_info[0] == 'F') || (arg_info[0] == 'N')) printf (".\n\The exact type is @samp{REAL(KIND=1)} when argument @var{%s} is\n\any type other than @code{COMPLEX}, or when it is @code{COMPLEX(KIND=1)}.\n\When @var{%s} is any @code{COMPLEX} type other than @code{COMPLEX(KIND=1)},\n\this intrinsic is valid only when used as the argument to\n\@code{REAL()}, as explained below.\n\n", arg_string, arg_string); else printf (".\n\This intrinsic is valid when argument @var{%s} is\n\@code{COMPLEX(KIND=1)}.\n\When @var{%s} is any other @code{COMPLEX} type,\n\this intrinsic is valid only when used as the argument to\n\@code{REAL()}, as explained below.\n\n", arg_string, arg_string); }#if 0 else if ((c[0] == 'I') && (c[1] == '7')) printf (", the exact type being wide enough to hold a pointer\n\on the target system (typically @code{INTEGER(KIND=1)} or @code{INTEGER(KIND=4)}).\n\n");#endif else if ((c[1] == '=') && (c[colon + 1] >= '0') && (c[colon + 1] <= '9')) { assert (other_arg >= 0); if ((arg_info[0] == '?') || (arg_info[0] == '!') || (arg_info[0] == '+') || (arg_info[0] == '*') || (arg_info[0] == 'n') || (arg_info[0] == 'p')) ++arg_info; if (((c[0] == arg_info[0]) && ((c[0] == 'A') || (c[0] == 'C') || (c[0] == 'I') || (c[0] == 'L') || (c[0] == 'R'))) || ((c[0] == 'R') && (arg_info[0] == 'C')) || ((c[0] == 'C') && (arg_info[0] == 'R'))) printf (", the @samp{KIND=} value of the type being that of argument @var{%s}.\n\n", arg_string); else if ((c[0] == 'S') && ((arg_info[0] == 'C') || (arg_info[0] == 'F') || (arg_info[0] == 'N'))) printf (".\n\The exact type depends on that of argument @var{%s}---if @var{%s} is\n\@code{COMPLEX}, this function's type is @code{REAL}\n\with the same @samp{KIND=} value as the type of @var{%s}.\n\Otherwise, this function's type is the same as that of @var{%s}.\n\n", arg_string, arg_string, arg_string, arg_string); else printf (", the exact type being that of argument @var{%s}.\n\n", arg_string); } else if ((c[1] == '=') && (c[colon + 1] == '*')) printf (", the exact type being the result of cross-promoting the\n\types of all the arguments.\n\n"); else if (c[1] == '=') assert ("?0:?:" == NULL); else printf (".\n\n"); } for (argno = 0, argc = &c[colon + 3]; *argc != '\0'; ++argno) { char optionality = '\0'; char extra = '\0'; char basic; char kind; int length; int elements; printf ("\@noindent\n\@var{"); for (; ; ++argc) { if (argc[0] == '=') break; printf ("%c", *argc); } printf ("}: "); ++argc; if ((*argc == '?') || (*argc == '!') || (*argc == '*') || (*argc == '+') || (*argc == 'n') || (*argc == 'p')) optionality = *(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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -