OSDN Git Service

* acinclude.m4 (LIBGFOR_CHECK_ATTRIBUTE_VISIBILITY): New.
[pf3gnuchains/gcc-fork.git] / libgfortran / runtime / select.c
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 extern void * select_string (select_struct *table, int table_len,
34                              void *default_jump, const char *selector,
35                              int selector_len);
36 export_proto(select_string);
37
38
39 /* select_string()-- Given a selector string and a table of
40  * select_struct structures, return the address to jump to. */
41
42 void *
43 select_string (select_struct *table, int table_len, void *default_jump,
44                const char *selector, int selector_len)
45 {
46   select_struct *t;
47   int i, low, high, mid;
48
49   if (table_len == 0)
50     return default_jump;
51
52   /* Record the default address if present */
53
54   if (table->low == NULL && table->high == NULL)
55     {
56       default_jump = table->address;
57
58       table++;
59       table_len--;
60       if (table_len == 0)
61         return default_jump;
62     }
63
64   /* Try the high and low bounds if present. */
65
66   if (table->low == NULL)
67     {
68       if (compare_string (table->high_len, table->high,
69                                 selector_len, selector) >= 0)
70         return table->address;
71
72       table++;
73       table_len--;
74       if (table_len == 0)
75         return default_jump;
76     }
77
78   t = table + table_len - 1;
79
80   if (t->high == NULL)
81     {
82       if (compare_string (t->low_len, t->low,
83                                 selector_len, selector) <= 0)
84         return t->address;
85
86       table_len--;
87       if (table_len == 0)
88         return default_jump;
89     }
90
91   /* At this point, the only table entries are bounded entries.  Find
92      the right entry with a binary chop. */
93
94   low = -1;
95   high = table_len;
96
97   while (low + 1 < high)
98     {
99       mid = (low + high) / 2;
100
101       t = table + mid;
102       i = compare_string (t->low_len, t->low, selector_len, selector);
103
104       if (i == 0)
105         return t->address;
106
107       if (i < 0)
108         low = mid;
109       else
110         high = mid;
111     }
112
113   /* The string now lies between the low indeces of the now-adjacent
114      high and low entries.  Because it is less than the low entry of
115      'high', it can't be that one.  If low is still -1, then no
116      entries match.  Otherwise, we have to check the high entry of
117      'low'. */
118
119   if (low == -1)
120     return default_jump;
121
122   t = table + low;
123   if (compare_string (selector_len, selector,
124                             t->high_len, t->high) <= 0)
125     return t->address;
126
127   return default_jump;
128 }