]>
Commit | Line | Data |
---|---|---|
6de9cd9a DN |
1 | /* Implement the SELECT statement for character variables. |
2 | Contributed by Andy Vaught | |
3 | ||
4 | This file is part of the GNU Fortran 95 runtime library (libgfor). | |
5 | ||
6 | Libgfor is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2, or (at your option) | |
9 | any later version. | |
10 | ||
11 | Libgfor is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with libgfor; see the file COPYING. If not, write to | |
18 | the Free Software Foundation, 59 Temple Place - Suite 330, | |
19 | Boston, MA 02111-1307, USA. */ | |
20 | ||
21 | #include "libgfortran.h" | |
22 | ||
23 | typedef struct | |
24 | { | |
25 | char *low; | |
26 | int low_len; | |
27 | char *high; | |
28 | int high_len; | |
29 | void *address; | |
30 | } | |
31 | select_struct; | |
32 | ||
33 | ||
34 | #define select_string prefix(select_string) | |
35 | ||
36 | ||
37 | /* select_string()-- Given a selector string and a table of | |
38 | * select_struct structures, return the address to jump to. */ | |
39 | ||
40 | void *select_string (select_struct *table, int table_len, void *default_jump, | |
41 | const char *selector, int selector_len) | |
42 | { | |
43 | select_struct *t; | |
44 | int i, low, high, mid; | |
45 | ||
46 | if (table_len == 0) | |
47 | return default_jump; | |
48 | ||
49 | /* Record the default address if present */ | |
50 | ||
51 | if (table->low == NULL && table->high == NULL) | |
52 | { | |
53 | default_jump = table->address; | |
54 | ||
55 | table++; | |
56 | table_len--; | |
57 | if (table_len == 0) | |
58 | return default_jump; | |
59 | } | |
60 | ||
61 | /* Try the high and low bounds if present. */ | |
62 | ||
63 | if (table->low == NULL) | |
64 | { | |
65 | if (compare_string (table->high_len, table->high, | |
66 | selector_len, selector) >= 0) | |
67 | return table->address; | |
68 | ||
69 | table++; | |
70 | table_len--; | |
71 | if (table_len == 0) | |
72 | return default_jump; | |
73 | } | |
74 | ||
75 | t = table + table_len - 1; | |
76 | ||
77 | if (t->high == NULL) | |
78 | { | |
79 | if (compare_string (t->low_len, t->low, | |
80 | selector_len, selector) <= 0) | |
81 | return t->address; | |
82 | ||
83 | table_len--; | |
84 | if (table_len == 0) | |
85 | return default_jump; | |
86 | } | |
87 | ||
88 | /* At this point, the only table entries are bounded entries. Find | |
89 | the right entry with a binary chop. */ | |
90 | ||
91 | low = -1; | |
92 | high = table_len; | |
93 | ||
94 | while (low + 1 < high) | |
95 | { | |
96 | mid = (low + high) / 2; | |
97 | ||
98 | t = table + mid; | |
99 | i = compare_string (t->low_len, t->low, selector_len, selector); | |
100 | ||
101 | if (i == 0) | |
102 | return t->address; | |
103 | ||
104 | if (i < 0) | |
105 | low = mid; | |
106 | else | |
107 | high = mid; | |
108 | } | |
109 | ||
110 | /* The string now lies between the low indeces of the now-adjacent | |
111 | high and low entries. Because it is less than the low entry of | |
112 | 'high', it can't be that one. If low is still -1, then no | |
113 | entries match. Otherwise, we have to check the high entry of | |
114 | 'low'. */ | |
115 | ||
116 | if (low == -1) | |
117 | return default_jump; | |
118 | ||
119 | t = table + low; | |
120 | if (compare_string (selector_len, selector, | |
121 | t->high_len, t->high) <= 0) | |
122 | return t->address; | |
123 | ||
124 | return default_jump; | |
125 | } |