1 1.1 mrg /* Implement the SELECT statement for character variables. 2 1.1.1.4 mrg Copyright (C) 2008-2024 Free Software Foundation, Inc. 3 1.1 mrg 4 1.1 mrg This file is part of the GNU Fortran runtime library (libgfortran). 5 1.1 mrg 6 1.1 mrg Libgfortran is free software; you can redistribute it and/or modify 7 1.1 mrg it under the terms of the GNU General Public License as published by 8 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 9 1.1 mrg any later version. 10 1.1 mrg 11 1.1 mrg Libgfortran is distributed in the hope that it will be useful, 12 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 mrg GNU General Public License for more details. 15 1.1 mrg 16 1.1 mrg Under Section 7 of GPL version 3, you are granted additional 17 1.1 mrg permissions described in the GCC Runtime Library Exception, version 18 1.1 mrg 3.1, as published by the Free Software Foundation. 19 1.1 mrg 20 1.1 mrg You should have received a copy of the GNU General Public License and 21 1.1 mrg a copy of the GCC Runtime Library Exception along with this program; 22 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 1.1 mrg <http://www.gnu.org/licenses/>. */ 24 1.1 mrg 25 1.1 mrg #define select_string SUFFIX(select_string) 26 1.1 mrg #define select_struct SUFFIX(select_struct) 27 1.1 mrg #define compare_string SUFFIX(compare_string) 28 1.1 mrg 29 1.1 mrg typedef struct 30 1.1 mrg { 31 1.1 mrg CHARTYPE *low; 32 1.1 mrg gfc_charlen_type low_len; 33 1.1 mrg CHARTYPE *high; 34 1.1 mrg gfc_charlen_type high_len; 35 1.1 mrg int address; 36 1.1 mrg } 37 1.1 mrg select_struct; 38 1.1 mrg 39 1.1 mrg extern int select_string (select_struct *table, int table_len, 40 1.1 mrg const CHARTYPE *selector, 41 1.1 mrg gfc_charlen_type selector_len); 42 1.1 mrg export_proto(select_string); 43 1.1 mrg 44 1.1 mrg 45 1.1 mrg /* select_string()-- Given a selector string and a table of 46 1.1 mrg * select_struct structures, return the address to jump to. */ 47 1.1 mrg 48 1.1 mrg int 49 1.1 mrg select_string (select_struct *table, int table_len, const CHARTYPE *selector, 50 1.1 mrg gfc_charlen_type selector_len) 51 1.1 mrg { 52 1.1 mrg select_struct *t; 53 1.1 mrg int i, low, high, mid; 54 1.1 mrg int default_jump = -1; 55 1.1 mrg 56 1.1 mrg if (table_len == 0) 57 1.1 mrg return -1; 58 1.1 mrg 59 1.1 mrg /* Record the default address if present */ 60 1.1 mrg 61 1.1 mrg if (table->low == NULL && table->high == NULL) 62 1.1 mrg { 63 1.1 mrg default_jump = table->address; 64 1.1 mrg 65 1.1 mrg table++; 66 1.1 mrg table_len--; 67 1.1 mrg if (table_len == 0) 68 1.1 mrg return default_jump; 69 1.1 mrg } 70 1.1 mrg 71 1.1 mrg /* Try the high and low bounds if present. */ 72 1.1 mrg 73 1.1 mrg if (table->low == NULL) 74 1.1 mrg { 75 1.1 mrg if (compare_string (table->high_len, table->high, 76 1.1 mrg selector_len, selector) >= 0) 77 1.1 mrg return table->address; 78 1.1 mrg 79 1.1 mrg table++; 80 1.1 mrg table_len--; 81 1.1 mrg if (table_len == 0) 82 1.1 mrg return default_jump; 83 1.1 mrg } 84 1.1 mrg 85 1.1 mrg t = table + table_len - 1; 86 1.1 mrg 87 1.1 mrg if (t->high == NULL) 88 1.1 mrg { 89 1.1 mrg if (compare_string (t->low_len, t->low, selector_len, selector) <= 0) 90 1.1 mrg return t->address; 91 1.1 mrg 92 1.1 mrg table_len--; 93 1.1 mrg if (table_len == 0) 94 1.1 mrg return default_jump; 95 1.1 mrg } 96 1.1 mrg 97 1.1 mrg /* At this point, the only table entries are bounded entries. Find 98 1.1 mrg the right entry with a binary chop. */ 99 1.1 mrg 100 1.1 mrg low = -1; 101 1.1 mrg high = table_len; 102 1.1 mrg 103 1.1 mrg while (low + 1 < high) 104 1.1 mrg { 105 1.1 mrg mid = (low + high) / 2; 106 1.1 mrg 107 1.1 mrg t = table + mid; 108 1.1 mrg i = compare_string (t->low_len, t->low, selector_len, selector); 109 1.1 mrg 110 1.1 mrg if (i == 0) 111 1.1 mrg return t->address; 112 1.1 mrg 113 1.1 mrg if (i < 0) 114 1.1 mrg low = mid; 115 1.1 mrg else 116 1.1 mrg high = mid; 117 1.1 mrg } 118 1.1 mrg 119 1.1 mrg /* The string now lies between the low indeces of the now-adjacent 120 1.1 mrg high and low entries. Because it is less than the low entry of 121 1.1 mrg 'high', it can't be that one. If low is still -1, then no 122 1.1 mrg entries match. Otherwise, we have to check the high entry of 123 1.1 mrg 'low'. */ 124 1.1 mrg 125 1.1 mrg if (low == -1) 126 1.1 mrg return default_jump; 127 1.1 mrg 128 1.1 mrg t = table + low; 129 1.1 mrg if (compare_string (selector_len, selector, t->high_len, t->high) <= 0) 130 1.1 mrg return t->address; 131 1.1 mrg 132 1.1 mrg return default_jump; 133 1.1 mrg } 134