Home | History | Annotate | Line # | Download | only in runtime
      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