/* -------------------------------------------------------------------- */ /* gs_character.c */ /* */ /* Copyright (C) 1997,1998,1999,2000 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 "gs_private.h" /* -------------------------------------------------------------------- */ #define MAX_CHARACTER_STACK 32 static char character_stack[MAX_CHARACTER_STACK]; static int character_stack_top = 0; /* -------------------------------------------------------------------- */ static int readchar(int fd, unsigned char *c); /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ static int readchar(int fd, unsigned char *c) { int res; do { res = read(fd, c, 1); } while ((res == -1) && (errno == EINTR)); if (res == 0) { *c = (unsigned char)EOF; } return res; } /* -------------------------------------------------------------------- */ /* If we have pushed back a character then return it, else */ /* return the next character. */ /* -------------------------------------------------------------------- */ int gs_get_next_character(int fd, unsigned char *character) { int res; if (gs_pop_character(character) != -1) { return 0; } res = readchar(fd, character); if (res == -1) { return -1; } if (*character == '#') { do { res = readchar(fd, character); if (res == -1) { return -1; } } while ((*character != '\n') && (*character != (unsigned char)EOF)); } if (*character == '\n') { gs_increment_linenumber(); } return 0; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ int gs_push_character(unsigned char character) { if (character_stack_top == MAX_CHARACTER_STACK) { return -1; } character_stack[character_stack_top] = character; character_stack_top++; if (character == '\n') { gs_decrement_linenumber(); } return 0; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ int gs_pop_character(unsigned char *character) { if (character_stack_top == 0) { return -1; } character_stack_top--; *character = character_stack[character_stack_top]; if (*character == '\n') { gs_increment_linenumber(); } return 0; } /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ int gs_escape_character(int fd, unsigned char *escaped_character) { unsigned char character; if (gs_get_next_character(fd, &character) == -1) { return -1; } if (character == 'a') { *escaped_character = '\f'; } else if (character == 'b') { *escaped_character = '\b'; } else if (character == 'f') { *escaped_character = '\f'; } else if (character == 'n') { *escaped_character = '\n'; } else if (character == 'r') { *escaped_character = '\r'; } else if (character == 't') { *escaped_character = '\t'; } else if (character == 'v') { *escaped_character = '\v'; } else if (character == 'x') { int low_nibble, high_nibble, high_character, low_character; if (gs_get_next_character(fd, &character) == -1) { return -1; } high_character = character; if (isxdigit(character)) { if ((character >= '0') && (character <= '9')) { high_nibble = (character - '0') << 4; } else if ((character >= 'a') && (character <= 'f')) { high_nibble = (10 + (character - 'a')) << 4; } else { high_nibble = (10 + (character - 'A')) << 4; } if (gs_get_next_character(fd, &character) == -1) { return -1; } low_character = character; if (isxdigit(character)) { if ((character >= '0') && (character <= '9')) { low_nibble = (character - '0'); } else if ((character >= 'a') && (character <= 'f')) { low_nibble = (10 + (character - 'a')); } else { low_nibble = (10 + (character - 'A')); } *escaped_character = high_nibble + low_nibble; } else { /* Error */ gs_push_character('x'); gs_push_character(high_character); gs_push_character(low_character); *escaped_character = '\\'; } } else { /* Error */ gs_push_character('x'); gs_push_character(high_character); *escaped_character = '\\'; } } else if (character == '\\') { *escaped_character = '\\'; } else if (character == '\"') { *escaped_character = '\"'; } else if (character == '\'') { *escaped_character = '\''; } else { /* Error */ gs_push_character(character); *escaped_character = '\\'; } return 0; }