00001 /*------------------------------------------------------------------------- 00002 * 00003 * kwlookup.c 00004 * lexical token lookup for key words in PostgreSQL 00005 * 00006 * NB - this file is also used by ECPG and several frontend programs in 00007 * src/bin/ including pg_dump and psql 00008 * 00009 * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group 00010 * Portions Copyright (c) 1994, Regents of the University of California 00011 * 00012 * 00013 * IDENTIFICATION 00014 * src/backend/parser/kwlookup.c 00015 * 00016 *------------------------------------------------------------------------- 00017 */ 00018 00019 /* use c.h so this can be built as either frontend or backend */ 00020 #include "c.h" 00021 00022 #include <ctype.h> 00023 00024 #include "parser/keywords.h" 00025 00026 /* 00027 * ScanKeywordLookup - see if a given word is a keyword 00028 * 00029 * Returns a pointer to the ScanKeyword table entry, or NULL if no match. 00030 * 00031 * The match is done case-insensitively. Note that we deliberately use a 00032 * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z', 00033 * even if we are in a locale where tolower() would produce more or different 00034 * translations. This is to conform to the SQL99 spec, which says that 00035 * keywords are to be matched in this way even though non-keyword identifiers 00036 * receive a different case-normalization mapping. 00037 */ 00038 const ScanKeyword * 00039 ScanKeywordLookup(const char *text, 00040 const ScanKeyword *keywords, 00041 int num_keywords) 00042 { 00043 int len, 00044 i; 00045 char word[NAMEDATALEN]; 00046 const ScanKeyword *low; 00047 const ScanKeyword *high; 00048 00049 len = strlen(text); 00050 /* We assume all keywords are shorter than NAMEDATALEN. */ 00051 if (len >= NAMEDATALEN) 00052 return NULL; 00053 00054 /* 00055 * Apply an ASCII-only downcasing. We must not use tolower() since it may 00056 * produce the wrong translation in some locales (eg, Turkish). 00057 */ 00058 for (i = 0; i < len; i++) 00059 { 00060 char ch = text[i]; 00061 00062 if (ch >= 'A' && ch <= 'Z') 00063 ch += 'a' - 'A'; 00064 word[i] = ch; 00065 } 00066 word[len] = '\0'; 00067 00068 /* 00069 * Now do a binary search using plain strcmp() comparison. 00070 */ 00071 low = keywords; 00072 high = keywords + (num_keywords - 1); 00073 while (low <= high) 00074 { 00075 const ScanKeyword *middle; 00076 int difference; 00077 00078 middle = low + (high - low) / 2; 00079 difference = strcmp(middle->name, word); 00080 if (difference == 0) 00081 return middle; 00082 else if (difference < 0) 00083 low = middle + 1; 00084 else 00085 high = middle - 1; 00086 } 00087 00088 return NULL; 00089 }