1 /* src.c -- Implementation File
2 Copyright (C) 1995 Free Software Foundation, Inc.
3 Contributed by James Craig Burley (burley@gnu.ai.mit.edu).
5 This file is part of GNU Fortran.
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Fortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Fortran; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 Source-file functions to handle various combinations of case sensitivity
26 and insensitivity at run time.
36 /* This array does a toupper (), but any valid char type is valid as an
37 index and returns identity if not a lower-case character. */
39 char ffesrc_toupper_[256];
41 /* This array does a tolower (), but any valid char type is valid as an
42 index and returns identity if not an upper-case character. */
44 char ffesrc_tolower_[256];
46 /* This array is set up so that, given a source-mapped character, the result
47 of indexing into this array will match an upper-cased character depending
48 on the source-mapped character's case and the established ffe_case_match()
49 setting. So the uppercase cells contain identies (e.g. ['A'] == 'A')
50 as long as uppercase matching is permitted (!FFE_caseLOWER) and the
51 lowercase cells contain uppercased identities (e.g. ['a'] == 'A') as long
52 as lowercase matching is permitted (!FFE_caseUPPER). Else the case
53 cells contain -1. _init_ is for the first character of a keyword,
54 and _noninit_ is for other characters. */
56 char ffesrc_char_match_init_[256];
57 char ffesrc_char_match_noninit_[256];
59 /* This array is used to map input source according to the established
60 ffe_case_source() setting: for FFE_caseNONE, the array is all
61 identities; for FFE_caseUPPER, the lowercase cells contain
62 uppercased identities; and vice versa for FFE_caseLOWER. */
64 char ffesrc_char_source_[256];
66 /* This array is used to map an internally generated character so that it
67 will be accepted as an initial character in a keyword. The assumption
68 is that the incoming character is uppercase. */
70 char ffesrc_char_internal_init_[256];
72 /* This array is used to determine if a particular character is valid in
73 a symbol name according to the established ffe_case_symbol() setting:
74 for FFE_caseNONE, the array is all FFEBAD; for FFE_caseUPPER, the
75 lowercase cells contain a non-FFEBAD error code (FFEBAD_SYMBOL_UPPER_CASE);
76 and vice versa for FFE_caseLOWER. _init_ and _noninit_ distinguish
77 between initial and subsequent characters for the caseINITCAP case,
78 and their error codes are different for appropriate messages --
79 specifically, _noninit_ contains a non-FFEBAD error code for all
80 except lowercase characters for the caseINITCAP case.
82 See ffesrc_check_symbol_, it must be TRUE if this array is not all
85 ffebad ffesrc_bad_symbol_init_[256];
86 ffebad ffesrc_bad_symbol_noninit_[256];
88 /* Set TRUE if any element in ffesrc_bad_symbol (with an index representing
89 a character that can also be in the text of a token passed to
90 ffename_find, strictly speaking) is not FFEBAD. I.e., TRUE if it is
91 necessary to check token characters against the ffesrc_bad_symbol_
94 bool ffesrc_check_symbol_;
96 /* These are set TRUE if the kind of character (upper/lower) is ok as a match
97 in the context (initial/noninitial character of keyword). */
99 bool ffesrc_ok_match_init_upper_;
100 bool ffesrc_ok_match_init_lower_;
101 bool ffesrc_ok_match_noninit_upper_;
102 bool ffesrc_ok_match_noninit_lower_;
104 /* Initialize table of alphabetic matches. */
111 for (i = 0; i < 256; ++i)
113 ffesrc_char_match_init_[i] = i;
114 ffesrc_char_match_noninit_[i] = i;
115 ffesrc_char_source_[i] = i;
116 ffesrc_char_internal_init_[i] = i;
117 ffesrc_toupper_[i] = i;
118 ffesrc_tolower_[i] = i;
119 ffesrc_bad_symbol_init_[i] = FFEBAD;
120 ffesrc_bad_symbol_noninit_[i] = FFEBAD;
123 for (i = 'A'; i <= 'Z'; ++i)
124 ffesrc_tolower_[i] = tolower (i);
126 for (i = 'a'; i <= 'z'; ++i)
127 ffesrc_toupper_[i] = toupper (i);
129 ffesrc_check_symbol_ = (ffe_case_symbol () != FFE_caseNONE);
131 ffesrc_ok_match_init_upper_ = (ffe_case_match () != FFE_caseLOWER);
132 ffesrc_ok_match_init_lower_ = (ffe_case_match () != FFE_caseUPPER)
133 && (ffe_case_match () != FFE_caseINITCAP);
134 ffesrc_ok_match_noninit_upper_ = (ffe_case_match () != FFE_caseLOWER)
135 && (ffe_case_match () != FFE_caseINITCAP);
136 ffesrc_ok_match_noninit_lower_ = (ffe_case_match () != FFE_caseUPPER);
138 /* Note that '-' is used to flag an invalid match character. '-' is
139 somewhat arbitrary, actually. -1 was used, but that's not wise on a
140 system with unsigned chars as default -- it'd turn into 255 or some such
141 large positive number, which would sort higher than the alphabetics and
142 thus possibly cause problems. So '-' is picked just because it's never
143 likely to be a symbol character in Fortran and because it's "less than"
144 any alphabetic character. EBCDIC might see things differently, I don't
145 remember it well enough, but that's just tough -- lots of other things
146 might have to change to support EBCDIC -- anyway, some other character
147 could easily be picked. */
149 #define FFESRC_INVALID_SYMBOL_CHAR_ '-'
151 if (!ffesrc_ok_match_init_upper_)
152 for (i = 'A'; i <= 'Z'; ++i)
153 ffesrc_char_match_init_[i] = FFESRC_INVALID_SYMBOL_CHAR_;
155 if (ffesrc_ok_match_init_lower_)
156 for (i = 'a'; i <= 'z'; ++i)
157 ffesrc_char_match_init_[i] = toupper (i);
159 for (i = 'a'; i <= 'z'; ++i)
160 ffesrc_char_match_init_[i] = FFESRC_INVALID_SYMBOL_CHAR_;
162 if (!ffesrc_ok_match_noninit_upper_)
163 for (i = 'A'; i <= 'Z'; ++i)
164 ffesrc_char_match_noninit_[i] = FFESRC_INVALID_SYMBOL_CHAR_;
166 if (ffesrc_ok_match_noninit_lower_)
167 for (i = 'a'; i <= 'z'; ++i)
168 ffesrc_char_match_noninit_[i] = toupper (i);
170 for (i = 'a'; i <= 'z'; ++i)
171 ffesrc_char_match_noninit_[i] = FFESRC_INVALID_SYMBOL_CHAR_;
173 if (ffe_case_source () == FFE_caseLOWER)
174 for (i = 'A'; i <= 'Z'; ++i)
175 ffesrc_char_source_[i] = tolower (i);
176 else if (ffe_case_source () == FFE_caseUPPER)
177 for (i = 'a'; i <= 'z'; ++i)
178 ffesrc_char_source_[i] = toupper (i);
180 if (ffe_case_match () == FFE_caseLOWER)
181 for (i = 'A'; i <= 'Z'; ++i)
182 ffesrc_char_internal_init_[i] = tolower (i);
184 switch (ffe_case_symbol ())
187 for (i = 'A'; i <= 'Z'; ++i)
189 ffesrc_bad_symbol_init_[i] = FFEBAD_SYMBOL_UPPER_CASE;
190 ffesrc_bad_symbol_noninit_[i] = FFEBAD_SYMBOL_UPPER_CASE;
195 for (i = 'a'; i <= 'z'; ++i)
197 ffesrc_bad_symbol_init_[i] = FFEBAD_SYMBOL_LOWER_CASE;
198 ffesrc_bad_symbol_noninit_[i] = FFEBAD_SYMBOL_LOWER_CASE;
202 case FFE_caseINITCAP:
203 for (i = 0; i < 256; ++i)
204 ffesrc_bad_symbol_noninit_[i] = FFEBAD_SYMBOL_NOLOWER_INITCAP;
205 for (i = 'a'; i <= 'z'; ++i)
207 ffesrc_bad_symbol_init_[i] = FFEBAD_SYMBOL_LOWER_INITCAP;
208 ffesrc_bad_symbol_noninit_[i] = FFEBAD;
217 /* Compare two strings a la strcmp, the first being a source string with its
218 length passed, and the second being a constant string passed
219 in InitialCaps form. Also, the return value is always -1, 0, or 1. */
222 ffesrc_strcmp_1ns2i (ffeCase mcase, const char *var, int len,
231 for (; len > 0; --len, ++var, ++str_ic)
233 c = ffesrc_char_source (*var); /* Transform source. */
234 c = ffesrc_toupper (c); /* Upcase source. */
235 d = ffesrc_toupper (*str_ic); /* Upcase InitialCaps char. */
237 if ((d != '\0') && (c < d))
245 for (; len > 0; --len, ++var, ++str_ic)
247 c = ffesrc_char_source (*var); /* Transform source. */
248 d = ffesrc_toupper (*str_ic); /* Transform InitialCaps char. */
250 if ((d != '\0') && (c < d))
258 for (; len > 0; --len, ++var, ++str_ic)
260 c = ffesrc_char_source (*var); /* Transform source. */
261 d = ffesrc_tolower (*str_ic); /* Transform InitialCaps char. */
263 if ((d != '\0') && (c < d))
270 case FFE_caseINITCAP:
271 for (; len > 0; --len, ++var, ++str_ic)
273 c = ffesrc_char_source (*var); /* Transform source. */
274 d = *str_ic; /* No transform of InitialCaps char. */
277 c = ffesrc_toupper (c);
278 d = ffesrc_toupper (d);
279 while ((len > 0) && (c == d))
280 { /* Skip past equivalent (case-ins) chars. */
281 --len, ++var, ++str_ic;
283 c = ffesrc_toupper (*var);
284 d = ffesrc_toupper (*str_ic);
286 if ((d != '\0') && (c < d))
295 assert ("bad case value" == NULL);
304 /* Compare two strings a la strcmp, the second being a constant string passed
305 in both uppercase and lowercase form. If not equal, the uppercase string
306 is used to determine the sign of the return value. Also, the return
307 value is always -1, 0, or 1. */
310 ffesrc_strcmp_2c (ffeCase mcase, const char *var, const char *str_uc,
311 const char *str_lc, const char *str_ic)
319 for (; *var != '\0'; ++var, ++str_uc)
321 c = ffesrc_toupper (*var); /* Upcase source. */
323 if ((*str_uc != '\0') && (c < *str_uc))
333 i = strcmp (var, str_uc);
337 i = strcmp (var, str_lc);
340 case FFE_caseINITCAP:
341 for (; *var != '\0'; ++var, ++str_ic, ++str_uc)
345 c = ffesrc_toupper (*var);
346 while ((c != '\0') && (c == *str_uc))
347 { /* Skip past equivalent (case-ins) chars. */
349 c = ffesrc_toupper (*var);
351 if ((*str_uc != '\0') && (c < *str_uc))
362 assert ("bad case value" == NULL);
373 /* Compare two strings a la strncmp, the second being a constant string passed
374 in uppercase, lowercase, and InitialCaps form. If not equal, the
375 uppercase string is used to determine the sign of the return value. */
378 ffesrc_strncmp_2c (ffeCase mcase, const char *var, const char *str_uc,
379 const char *str_lc, const char *str_ic, int len)
387 for (; len > 0; ++var, ++str_uc, --len)
389 c = ffesrc_toupper (*var); /* Upcase source. */
399 i = strncmp (var, str_uc, len);
403 i = strncmp (var, str_lc, len);
406 case FFE_caseINITCAP:
407 for (; len > 0; ++var, ++str_ic, ++str_uc, --len)
411 c = ffesrc_toupper (*var);
412 while ((len > 0) && (c == *str_uc))
413 { /* Skip past equivalent (case-ins) chars. */
414 --len, ++var, ++str_uc;
416 c = ffesrc_toupper (*var);
418 if ((len > 0) && (c < *str_uc))
427 assert ("bad case value" == NULL);