/* -------------------------------------------------------------------- */ /* SMS Client, send messages to mobile phones and pagers */ /* */ /* gs_token.c */ /* */ /* Copyright (C) 1997,1998 Angelo Masci */ /* */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library 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 */ /* Library General Public License for more details. */ /* */ /* You should have received a copy of the GNU Library General Public */ /* License along with this library; if not, write to the Free */ /* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* */ /* You can contact the author at this e-mail address: */ /* */ /* angelo@styx.demon.co.uk */ /* */ /* -------------------------------------------------------------------- */ /* $Id$ -------------------------------------------------------------------- */ #include #include #include #include #include "common/common.h" #include "logfile/logfile.h" #include "gs_token.h" #include "error.h" #include "gs_private.h" /* -------------------------------------------------------------------- */ TOKEN_ID null_tok, eof_tok, assignment_tok, lparen_tok, rparen_tok, lcurly_tok, rcurly_tok, comma_tok, dot_tok, semicolon_tok, true_tok, false_tok, yes_tok, no_tok; struct init_token_struct { TOKEN_ID *var; char *str; int type; int type_ptr; void *ptr; } init_token_table[] = { { &null_tok, "", T_SPECIAL, 0, NULL }, { &eof_tok, "", T_SPECIAL, 0, NULL }, { &assignment_tok, "=", T_SPECIAL, 0, NULL }, { &lparen_tok, "(", T_SPECIAL, 0, NULL }, { &rparen_tok, ")", T_SPECIAL, 0, NULL }, { &lcurly_tok, "{", T_SPECIAL, 0, NULL }, { &rcurly_tok, "}", T_SPECIAL, 0, NULL }, { &comma_tok, ",", T_SPECIAL, 0, NULL }, { &dot_tok, ".", T_SPECIAL, 0, NULL }, { &semicolon_tok, ";", T_SPECIAL, 0, NULL }, { &true_tok, "TRUE", T_STRING, 0, NULL }, { &false_tok, "FALSE", T_STRING, 0, NULL }, { &yes_tok, "YES", T_STRING, 0, NULL }, { &no_tok, "NO", T_STRING, 0, NULL }, { NULL, NULL, T_SPECIAL, 0, NULL } }; static TOKEN_ID token_pushed = NULL; static TOKEN_HEAP builtin = { NULL }; /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static int is_valid_first_identifier_character(int character); static int is_valid_identifier_character(int character); /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void push_back_token(TOKEN_ID token) { token_pushed = token; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static int is_valid_first_identifier_character(int character) { if ((isalpha(character)) || (character == '_')) { return TRUE; } return FALSE; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static int is_valid_identifier_character(int character) { if ((isalnum(character)) || (character == '_')) { return TRUE; } return FALSE; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ char *expand_environment_variables(char *str) { static char data[1024], env_str[1024], *env_value, *env_ptr, *dst, *src; dst = data; src = str; while(*src != '\0') { if (*src == '$') { env_ptr = env_str; src++; if (*src == '{') { src++; while((*src != '}') && (*src != '\0')) { *env_ptr++ = *src++; } *env_ptr = '\0'; fprintf(stderr, "FOUND VAR: '%s'\n", env_str); if (*src == '}') { src++; env_value = getenv(env_str); if (env_value != NULL) { strcpy(dst, env_value); dst += strlen(env_value); } } else { return NULL; } } else { return NULL; } } else { *dst++ = *src++; } } *dst = '\0'; return data; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ TOKEN_ID get_next_token(int fd, TOKEN_HEAP *heap) { unsigned char str[1024], *str_ptr, *env_str, *nstr; long value; unsigned char character; TOKEN_ID token_id; if (token_pushed != NULL) { token_id = token_pushed; token_pushed = NULL; return token_id; } if (gs_get_next_character(fd, &character) == -1) { return null_tok; } /* ---------------------------- */ /* Throw away any whitespace */ /* ---------------------------- */ while (isspace(character)) { if (gs_get_next_character(fd, &character) == -1) { return null_tok; } } /* ---------------------------- */ /* Identifier - */ /* A String without any quotes */ /* ---------------------------- */ if (is_valid_first_identifier_character(character)) { str_ptr = str; while (is_valid_identifier_character(character)) { *str_ptr++ = character; if (gs_get_next_character(fd, &character) == -1) { return null_tok; } } *str_ptr = '\0'; gs_push_character(character); lprintf(LOG_VERYVERBOSE, "Found Identifier '%s'\n", str); /* This Identifier could be a special */ /* reserved String. */ /* If it has a matching builtin string */ /* then return this. */ /* Else add the token as an identifier */ token_id = gs_find_item(builtin.list, str, T_STRING); if (token_id != NULL) { lprintf(LOG_VERYVERBOSE, "Overriding Identifier with Builtin String\n"); } else { token_id = add_token(heap, str, T_IDENTIFIER, TP_NULL, NULL); if (token_id == NULL) { return null_tok; } } } else if (character == '$') { if (gs_get_next_character(fd, &character) == -1) { return null_tok; } str_ptr = str; while ((!isspace(character)) && (character != (unsigned char)EOF)) { *str_ptr++ = character; if (gs_get_next_character(fd, &character) == -1) { return null_tok; } } *str_ptr = '\0'; lprintf(LOG_VERYVERBOSE, "Found Environment Variable '%s'\n", str); /* this is an environment variable */ /* expand it if it exists, else */ /* set it to an empty string */ env_str = getenv(str); if (env_str == NULL) { strcpy(str, ""); } else { strcpy(str, env_str); } lprintf(LOG_VERYVERBOSE, "Shell variable, expanding Identifier to '%s'\n", str); token_id = add_token(heap, str, T_STRING, TP_NULL, NULL); if (token_id == NULL) { return null_tok; } } else if (character == '"') { if (gs_get_next_character(fd, &character) == -1) { return null_tok; } str_ptr = str; while ((character != '"') && (character != (unsigned char)EOF)) { if (character == '\\') { if (gs_escape_character(fd, &character) == -1) { return null_tok; } } *str_ptr++ = character; if (gs_get_next_character(fd, &character) == -1) { return null_tok; } } *str_ptr = '\0'; if (character == '"') { lprintf(LOG_VERYVERBOSE, "Found Identifier '%s'\n", str); nstr = expand_environment_variables(str); if (nstr != NULL) { token_id = add_token(heap, nstr, T_STRING, TP_NULL, NULL); if (token_id == NULL) { return null_tok; } } else { token_id = null_tok; } } else { token_id = null_tok; } } else if (isdigit(character)) { value = character - '0'; str_ptr = str; *str_ptr++ = character; if (gs_get_next_character(fd, &character) == -1) { return null_tok; } while (isdigit(character) && (character != (unsigned char)EOF)) { value *= 10; value += character - '0'; *str_ptr++ = character; if (gs_get_next_character(fd, &character) == -1) { return null_tok; } } *str_ptr = '\0'; token_id = add_token(heap, str, T_NUMERIC, TP_NULL, NULL); if (token_id == NULL) { return null_tok; } } else if (character == '\'') { if (gs_get_next_character(fd, &character) == -1) { return null_tok; } str_ptr = str; while ((character != '\'') && (character != (unsigned char)EOF)) { *str_ptr++ = character; if (gs_get_next_character(fd, &character) == -1) { return null_tok; } } *str_ptr = '\0'; if (character == '\'') { lprintf(LOG_VERYVERBOSE, "Found Identifier '%s'\n", str); token_id = add_token(heap, str, T_STRING, TP_NULL, NULL); if (token_id == NULL) { return null_tok; } } else { token_id = null_tok; } } else if (character == '=') { token_id = assignment_tok; } else if (character == '(') { token_id = lparen_tok; } else if (character == ')') { token_id = rparen_tok; } else if (character == '{') { token_id = lcurly_tok; } else if (character == '}') { token_id = rcurly_tok; } else if (character == ',') { token_id = comma_tok; } else if (character == '.') { token_id = dot_tok; } else if (character == ';') { token_id = semicolon_tok; } else if (character == (unsigned char)EOF) { token_id = eof_tok; } else { token_id = null_tok; } lprintf(LOG_VERYVERBOSE, "Token id = %p\n", token_id); return token_id; } /* -------------------------------------------------------------------- */ /* Add token searches the token heap for 'str' */ /* -------------------------------------------------------------------- */ TOKEN_ID add_token(TOKEN_HEAP *heap, char *str, int type, int ptr_type, void *ptr) { TOKEN_ID token; lprintf(LOG_VERYVERBOSE, "Entering add_token()\n"); heap->list = gs_add_token_list_item(heap->list, &token, str, type, ptr_type, ptr); if (heap->list == NULL) { return NULL; } lprintf(LOG_VERYVERBOSE, "returning %p\n", token); return token; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ char *get_token_strvalue(TOKEN_HEAP *heap, TOKEN_ID token_id) { return token_id->str; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ long get_token_numvalue(TOKEN_HEAP *heap, TOKEN_ID token_id) { return token_id->value; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ char *get_token_strtype(TOKEN_HEAP *heap, TOKEN_ID token_id) { return "UNKNOWN"; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ int get_token_type(TOKEN_HEAP *heap, TOKEN_ID token_id) { return token_id->type; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ int get_token_indirect_type(TOKEN_HEAP *heap, TOKEN_ID token_id) { return token_id->ptr_type; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ char *get_token_indirect_strvalue(TOKEN_HEAP *heap, TOKEN_ID token_id) { return token_id->ptr; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ long get_token_indirect_numvalue(TOKEN_HEAP *heap, TOKEN_ID token_id) { return token_id->value; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ TOKEN_HEAP *get_token_indirect_dictionary(TOKEN_HEAP *heap, TOKEN_ID token_id) { return (TOKEN_HEAP *)token_id->ptr; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ TOKEN_HEAP *get_token_indirect_list(TOKEN_HEAP *heap, TOKEN_ID token_id) { return (TOKEN_HEAP *)token_id->ptr; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void token_assign_strvalue(TOKEN_HEAP *heap, TOKEN_ID token_id, char *string) { token_id->ptr_type = TP_STRING; token_id->ptr = string; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void token_assign_numvalue(TOKEN_HEAP *heap, TOKEN_ID token_id, long value) { token_id->ptr_type = TP_NUMERIC; token_id->value = value; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void token_assign_dictionary(TOKEN_HEAP *heap, TOKEN_ID token_id, TOKEN_HEAP *dictionary) { token_id->ptr_type = TP_DICTIONARY; token_id->ptr = dictionary; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void token_assign_list(TOKEN_HEAP *heap, TOKEN_ID token_id, TOKEN_HEAP *list) { token_id->ptr_type = TP_LIST; token_id->ptr = list; } /* -------------------------------------------------------------------- */ /* Add our reserved tokens to the reserved builtin heap. */ /* if builtin heap has been filled by an earlier call just */ /* return from this function. */ /* -------------------------------------------------------------------- */ int init_builtin_heap(void) { int i; if (builtin.list == NULL) { for (i=0; init_token_table[i].var != NULL; i++) { *(init_token_table[i].var) = add_token(&builtin, init_token_table[i].str, init_token_table[i].type, TP_NULL, init_token_table[i].ptr); if (*(init_token_table[i].var) == NULL) { return -1; } } } return 0; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ TOKEN_HEAP *init_heap(TOKEN_HEAP *heap) { heap->list = NULL; return heap; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ TOKEN_HEAP *generate_new_heap(void) { TOKEN_HEAP *heap; heap = (TOKEN_HEAP *)malloc(sizeof(TOKEN_HEAP)); if (heap == NULL) { lprintf(LOG_ERROR, "malloc() failed\n"); return NULL; } return init_heap(heap); } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void dump_heap(TOKEN_HEAP *heap, char *name) { dump_heaptofile(heap, name, stdout); } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void dump_heaptofile_internal(TOKEN_HEAP *heap, char *name, FILE *fp, int level, int islist) { int i; TOKEN_LIST *item; TOKEN_ID token; if (heap == NULL) { return; } item = heap->list; while(item != NULL) { token = item->token; if (get_token_type(heap, token) == T_IDENTIFIER) { if (get_token_indirect_type(heap, token) == TP_STRING) { for(i=0; inext != NULL))?",":"")); } else if (get_token_indirect_type(heap, token) == TP_NUMERIC) { for(i=0; inext != NULL))?",":"")); } else if (get_token_indirect_type(heap, token) == TP_DICTIONARY) { for(i=0; inext != NULL))?",":"")); } else if (get_token_indirect_type(heap, token) == TP_LIST) { for(i=0; inext != NULL))?",":"")); } } item = item->next; } } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void dump_heaptofile(TOKEN_HEAP *heap, char *name, FILE *fp) { fprintf(fp, "{\n"); dump_heaptofile_internal(heap, name, fp, 1, FALSE); fprintf(fp, "}\n"); } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ TOKEN_HEAP *dup_heap(TOKEN_HEAP *heap) { TOKEN_HEAP *new_heap, *list; TOKEN_LIST *item; TOKEN_ID token, new_token, identifier; char *str; if (heap == NULL) { return NULL; } new_heap = generate_new_heap(); item = heap->list; while(item != NULL) { token = item->token; if (get_token_type(heap, token) == T_IDENTIFIER) { identifier = add_token(new_heap, token->str, token->type, TP_NULL, NULL); if (get_token_indirect_type(heap, token) == TP_STRING) { str = get_token_indirect_strvalue(heap, token); new_token = add_token(new_heap, str, T_STRING, TP_NULL, NULL); str = get_token_strvalue(new_heap, new_token); token_assign_strvalue(new_heap, identifier, str); } else if ((get_token_indirect_type(heap, token) == TP_DICTIONARY) || (get_token_indirect_type(heap, token) == TP_LIST)) { list = dup_heap(get_token_indirect_dictionary(heap, token)); token_assign_list(new_heap, identifier, list); } } item = item->next; } return new_heap; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ void free_heap(TOKEN_HEAP *heap) { TOKEN_LIST *item, *prev_item; TOKEN_ID token; item = heap->list; while(item != NULL) { token = item->token; if (get_token_type(heap, token) == T_IDENTIFIER) { if (get_token_indirect_type(heap, token) == TP_DICTIONARY) { free_heap(get_token_indirect_dictionary(heap, token)); } else if (get_token_indirect_type(heap, token) == TP_LIST) { free_heap(get_token_indirect_list(heap, token)); } } prev_item = item; item = item->next; free(prev_item->token->str); free(prev_item->token); free(prev_item); } }