/* $Id: keyword.c,v 1.3 2009/01/22 01:01:18 kiesling Exp $ */

/*
  This file is part of Ctalk.
  Copyright © 2005-2009  Robert Kiesling, ctalk@ctalklang.org.
  Permission is granted to copy this software provided that this copyright
  notice is included in all source code modules.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software Foundation, 
  Inc., 51 Franklin St., Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include <string.h>

#define FALSE 0
#define TRUE !(FALSE)

#define N_CTALK_KEYWORDS 6

int is_ctalk_keyword (char *s) {
  int i, is_keyword;
  char *ctalk_keywords[] = {
    "self",
    "super",
    "value",
    "arg",
    "method",
    "returnObjectClass"
  };

  for (i = 0, is_keyword = FALSE;
       (i < N_CTALK_KEYWORDS) && ! is_keyword;
       i++) {
    if (!strcmp (s, ctalk_keywords[i]))
      is_keyword = TRUE;
  }
  return is_keyword;
}

#ifdef __GNUC__
#define N_MACRO_KEYWORDS 18
#else
#define N_MACRO_KEYWORDS 14
#endif

int is_macro_keyword (char *s) {

  int i, is_keyword;
  char *macro_keywords[] = {
    "include",
#ifdef __GNUC__
    "include_next",
    "ident",
    "sccs",
    "unassert",
#endif
    "define",
    "undef",
    "if",
    "ifdef",
    "ifndef",
    "else",
    "elif",
    "endif",
    "error",
    "warning",
    "assert",
    "line",
    "pragma",
  };

  for (i = 0, is_keyword = FALSE; 
       (i < N_MACRO_KEYWORDS) && ! is_keyword; 
       i++) {
    if (!strcmp (s, macro_keywords[i]))
      is_keyword = TRUE;
  }
  return is_keyword;
}

static char *c_keywords[] = {
  "auto",
  "break",
  "case",
  "char",
  "const",
  "continue",
  "default",
  "do",
  "double",
  "else",
  "enum",
  "extern",
  "float",
  "for",
  "goto",
  "if",
  "inline",
  "int",
  "long",
  "register",
  "restrict",
  "return",
  "short",
  "signed",
  "sizeof",
  "static",
  "struct",
  "switch",
  "typedef",
  "union",
  "unsigned",
  "void",
  "volatile",
  "while",
  "_Bool",
  "_Complex",
  "_Imaginary"
#ifdef __GNUC__
  , "__complex__"
#endif
};

#ifdef __GNUC__
# define N_C_KEYWORDS 38
# else
# define N_C_KEYWORDS 37
#endif

/* Check if a label is an ANSI C or C99 keyword, including data types.  
   A subset that checks only the data types is below.
*/

int is_c_keyword (char *s) {

  int i;

  for (i = 0; i < N_C_KEYWORDS; i++) {
    if (!strcmp (s, c_keywords[i]))
      return TRUE;
  }

  return FALSE;
}

/* 
 *    Check if a label is an ANSI C data type.  This is a subset of
 *    the ANSI C keywords, above.
*/

static char *c_data_types[] = {
  "char",
  "const",
  "double",
  "enum",
  "extern",
  "float",
  "inline",
  "int",
  "long",
  "register",
  "short",
  "signed",
  "static",
  "struct",
  "union",
  "unsigned",
  "void",
  "volatile",
  "_Bool",
  "_Complex",
  "_Imaginary"
#ifdef __GNUC__
  , "__complex__"
#endif
};

#ifdef __GNUC__
# define N_C_DATA_TYPES 22
# else
# define N_C_DATA_TYPES 21
#endif

/* 
 *    Check if a label is an ANSI C data type.  This is a subset of
 *    the ANSI C keywords, above.
*/

int is_c_data_type (char *s) {

  int i, returnval = FALSE;

  for (i = 0; i < N_C_DATA_TYPES; i++)
    if (!strcmp (s, c_data_types[i]))
      returnval = TRUE;

  return returnval;
}

static char *c_storage_classes[] = {
  "const",
  "extern",
  "inline",
  "register",
  "static",
  "volatile",
};

#define N_C_STORAGE_CLASSES 5

/* 
 *    Check if a label is an ANSI C storage class keyword.  
 *    This is a subset of the ANSI C keywords, above.
 */

int is_c_storage_class (char *s) {

  int i, returnval = FALSE;

  for (i = 0; i < N_C_STORAGE_CLASSES; i++)
    if (!strcmp (s, c_storage_classes[i]))
      returnval = TRUE;

  return returnval;
}

#ifdef __GNUC__

static char *c_extensions[] = {
  "__extension__",                 /* GNU C. */
  "__const",
  "__restrict",
  "__attribute__",
  "__mode__",
}; 

#define N_EXTENSIONS 5

#else

#define N_EXTENSIONS 0

#endif

int is_extension_keyword (char *s) {

  int i, returnval = FALSE;

  for (i = 0; i < N_EXTENSIONS; i++)
    if (!strcmp (s, c_extensions[i]))
      returnval = TRUE;

  return returnval;
}

static char *c_ctrl_keywords[] = {
  "break",
  "case",
  "do",
  "else",
  "for",
  "goto",
  "if",
  "switch",
  "while"
};

#define N_CTRL_KEYWORDS 9

/*
 *  Check if a label is a control structure keyword.
 */

int is_ctrl_keyword (char *s) {

  int i;

  for (i = 0; i < N_CTRL_KEYWORDS; i++) {
    if (!strcmp (s, c_ctrl_keywords[i]))
      return TRUE;
  }

  return FALSE;
}
