static int pg_wc_isalpha(pg_wchar c) { switch (pg_regex_strategy) { case PG_REGEX_LOCALE_C: return (c <= (pg_wchar) 127 && (pg_char_properties[c] & PG_ISALPHA)); case PG_REGEX_LOCALE_WIDE: #ifdef USE_WIDE_UPPER_LOWER if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) return iswalpha((wint_t) c); #endif /* FALL THRU */ case PG_REGEX_LOCALE_1BYTE: return (c <= (pg_wchar) UCHAR_MAX && isalpha((unsigned char) c)); case PG_REGEX_LOCALE_WIDE_L: #if defined(HAVE_LOCALE_T) && defined(USE_WIDE_UPPER_LOWER) if (sizeof(wchar_t) >= 4 || c <= (pg_wchar) 0xFFFF) return iswalpha_l((wint_t) c, pg_regex_locale); #endif /* FALL THRU */ case PG_REGEX_LOCALE_1BYTE_L: #ifdef HAVE_LOCALE_T return (c <= (pg_wchar) UCHAR_MAX && isalpha_l((unsigned char) c, pg_regex_locale)); #endif break; } return 0; /* can't get here, but keep compiler quiet */ }
int getNextToken(void **attr) { string_t *s = NULL; keywords_t kw; int c; FSM { // --------------------------------------------------------------- // initial state // --------------------------------------------------------------- STATE(S_INIT) { SRC_GET(c); if (c == EOF) { NEXTSTATE(S_EOF); } else if (c == '\n') { NEXTSTATE(S_EOL); } else if (isspace(c)) { NEXTSTATE(S_INIT); } else if (isdigit(c)) { CHECKED(s = string_new(), alloc_failed); NEXTSTATE(S_INTEGRAL); } else if (isalpha_l(c, c_locale) || c == '_') { CHECKED(s = string_new(), alloc_failed); NEXTSTATE(S_IDENTIFIER); } else { switch (c) { default: NEXTSTATE(S_ERROR); case '+': NEXTSTATE(S_PLUS); case '-': NEXTSTATE(S_MINUS); case '!': NEXTSTATE(S_EXCL); case '=': NEXTSTATE(S_EQUAL); case '*': NEXTSTATE(S_ASTERISK); case '/': NEXTSTATE(S_SLASH); case '"': CHECKED(s = string_new(), alloc_failed); NEXTSTATE(S_QUOT); case '(': NEXTSTATE(S_LPAR); case ')': NEXTSTATE(S_RPAR); case '[': NEXTSTATE(S_LBRACK); case ']': NEXTSTATE(S_RBRACK); case '<': NEXTSTATE(S_LCHEV); case '>': NEXTSTATE(S_RCHEV); case ':': NEXTSTATE(S_COLON); case ',': NEXTSTATE(S_COMMA); } } } // --------------------------------------------------------------- // character + // --------------------------------------------------------------- STATE(S_PLUS) { _ifj_lexical_log("TOK_OP_SUM"); return TOK_OP_SUM; } // --------------------------------------------------------------- // character - // --------------------------------------------------------------- STATE(S_MINUS) { _ifj_lexical_log("TOK_OP_SUB"); return TOK_OP_SUB; } // --------------------------------------------------------------- // character ! // --------------------------------------------------------------- STATE(S_EXCL) { if (SRC_GET(c) == '=') { _ifj_lexical_log("TOK_OP_NEQ"); return TOK_OP_NEQ; } else { SRC_UNGET(c); NEXTSTATE(S_ERROR); } } // --------------------------------------------------------------- // character = // --------------------------------------------------------------- STATE(S_EQUAL) { if (SRC_GET(c) == '=') { _ifj_lexical_log("TOK_OP_EQ"); return TOK_OP_EQ; } else { SRC_UNGET(c); _ifj_lexical_log("TOK_OP_ASSIGN"); return TOK_OP_ASSIGN; } } // --------------------------------------------------------------- // character * // --------------------------------------------------------------- STATE(S_ASTERISK) { if (SRC_GET(c) == '*') { _ifj_lexical_log("TOK_OP_POW"); return TOK_OP_POW; } else { SRC_UNGET(c); _ifj_lexical_log("TOK_OP_MULT"); return TOK_OP_MULT; } } // --------------------------------------------------------------- // character ( // --------------------------------------------------------------- STATE(S_LPAR) { _ifj_lexical_log("TOK_LPAR"); return TOK_LPAR; } // --------------------------------------------------------------- // character ) // --------------------------------------------------------------- STATE(S_RPAR) { _ifj_lexical_log("TOK_RPAR"); return TOK_RPAR; } // --------------------------------------------------------------- // character [ // --------------------------------------------------------------- STATE(S_LBRACK) { _ifj_lexical_log("TOK_LBRACK"); return TOK_LBRACK; } // --------------------------------------------------------------- // character ] // --------------------------------------------------------------- STATE(S_RBRACK) { _ifj_lexical_log("TOK_RBRACK"); return TOK_RBRACK; } // --------------------------------------------------------------- // character < // --------------------------------------------------------------- STATE(S_LCHEV) { if (SRC_GET(c) == '=') { _ifj_lexical_log("TOK_OP_LE"); return TOK_OP_LE; } else { SRC_UNGET(c); _ifj_lexical_log("TOK_OP_LT"); return TOK_OP_LT; } } // --------------------------------------------------------------- // character > // --------------------------------------------------------------- STATE(S_RCHEV) { if (SRC_GET(c) == '=') { _ifj_lexical_log("TOK_OP_GE"); return TOK_OP_GE; } else { SRC_UNGET(c); _ifj_lexical_log("TOK_OP_GT"); return TOK_OP_GT; } } // --------------------------------------------------------------- // character : // --------------------------------------------------------------- STATE(S_COLON) { _ifj_lexical_log("TOK_COLON"); return TOK_COLON; } // --------------------------------------------------------------- // character , // --------------------------------------------------------------- STATE(S_COMMA) { _ifj_lexical_log("TOK_COMMA"); return TOK_COMMA; } // --------------------------------------------------------------- // character / // --------------------------------------------------------------- STATE(S_SLASH) { switch (SRC_GET(c)) { case '/': NEXTSTATE(S_COMMENT); case '*': NEXTSTATE(S_COMMENT_BLOCK); default: SRC_UNGET(c); _ifj_lexical_log("TOK_OP_DIV"); return TOK_OP_DIV; } } // --------------------------------------------------------------- // string -- inside quotes // --------------------------------------------------------------- STATE(S_QUOT) { SRC_GET(c); if (c == '"') { NEXTSTATE(S_STRING); } else if (c == '\\') { NEXTSTATE(S_ESCAPECHAR); } else if (isprint(c)) { CHECKED(string_append(&s, c), alloc_failed); NEXTSTATE(S_QUOT); } else { NEXTSTATE(S_ESTRING); } } // --------------------------------------------------------------- // string -- escape characters // --------------------------------------------------------------- STATE(S_ESCAPECHAR) { switch (SRC_GET(c)) { case 'n': CHECKED(string_append(&s, '\n'), alloc_failed); NEXTSTATE(S_QUOT); case 't': CHECKED(string_append(&s, '\t'), alloc_failed); NEXTSTATE(S_QUOT); case '"': CHECKED(string_append(&s, '"'), alloc_failed); NEXTSTATE(S_QUOT); case '\\': CHECKED(string_append(&s, '\\'), alloc_failed); NEXTSTATE(S_QUOT); case 'x': NEXTSTATE(S_HEXCHAR); default: NEXTSTATE(S_ESTRING); } } // --------------------------------------------------------------- // string -- character in hexadecimal notation // --------------------------------------------------------------- STATE(S_HEXCHAR) { unsigned char val = 0; if (isxdigit(SRC_GET(c))) { val = HEX_TO_INT(c) << 4; } else { NEXTSTATE(S_ESTRING); } if (isxdigit(SRC_GET(c))) { val += HEX_TO_INT(c); } else { NEXTSTATE(S_ESTRING); } CHECKED(string_append(&s, val), alloc_failed); NEXTSTATE(S_QUOT); } // --------------------------------------------------------------- // numeric -- integral part // --------------------------------------------------------------- STATE(S_INTEGRAL) { CHECKED(string_append(&s, c), alloc_failed); SRC_GET(c); if (isdigit(c)) { NEXTSTATE(S_INTEGRAL); } else if (c == '.') { CHECKED(string_append(&s, c), alloc_failed); SRC_GET(c); if (isdigit(c)) { NEXTSTATE(S_DECIMAL); } else { NEXTSTATE(S_ENUM); } } else if (c == 'e') { CHECKED(string_append(&s, c), alloc_failed); NEXTSTATE(S_EXPONENT_E); } else { NEXTSTATE(S_ENUM); } } // --------------------------------------------------------------- // numeric -- decimal part // --------------------------------------------------------------- STATE(S_DECIMAL) { CHECKED(string_append(&s, c), alloc_failed); SRC_GET(c); if (isdigit(c)) { NEXTSTATE(S_DECIMAL); } else if (c == 'e') { CHECKED(string_append(&s, c), alloc_failed); NEXTSTATE(S_EXPONENT_E); } else { SRC_UNGET(c); NEXTSTATE(S_NUMERIC); } } // --------------------------------------------------------------- // numeric -- exponent part // --------------------------------------------------------------- STATE(S_EXPONENT_E) { SRC_GET(c); if (c == '+' || c == '-') { CHECKED(string_append(&s, c), alloc_failed); SRC_GET(c); } if (isdigit(c)) { NEXTSTATE(S_EXPONENT); } else { NEXTSTATE(S_ENUM); } } STATE(S_EXPONENT) { CHECKED(string_append(&s, c), alloc_failed); if (isdigit(SRC_GET(c))) { NEXTSTATE(S_EXPONENT); } else { SRC_UNGET(c); NEXTSTATE(S_NUMERIC); } } // --------------------------------------------------------------- // identifier // --------------------------------------------------------------- STATE(S_IDENTIFIER) { CHECKED(string_append(&s, c), alloc_failed); if (isalnum_l(SRC_GET(c), c_locale) || c == '_') { NEXTSTATE(S_IDENTIFIER); } SRC_UNGET(c); #define X_(pstate, str, e) \ if (0 == strcmp(string_getstr(s), (str))) { \ kw = e; \ string_dispose(s); s = NULL; \ NEXTSTATE(pstate); \ } else #define X(a,b) X_(S_KEYWORD, b, KW_##a) #include "keywords.def" X_KEYWORD #undef X #define X(a,b) X_(S_BUILTIN, b, FN_##a) #include "builtin.def" //X_BUILTIN_FN #undef X #define X(a,b) X_(S_RESERVED_KEYWORD, b, RKW_##a) #include "keywords.def" X_KEYWORD_RESERVED #undef X #undef X_ // ------------------------------------------------------- // identifier // ------------------------------------------------------- { // else *attr = s; _ifj_lexical_log("TOK_TYPE_ID \"%s\"", string_getstr(s)); return TOK_TYPE_ID; } } // --------------------------------------------------------------- // reserved keyword // --------------------------------------------------------------- STATE(S_RESERVED_KEYWORD) { switch (kw) { default: break; #define X(a,b) \ case (RKW_##a): \ _ifj_lexical_log("TOK_TYPE_RKW \"%s\"", (b)); \ break; #include "keywords.def" X_KEYWORD_RESERVED #undef X } *attr = (void *) kw; return TOK_TYPE_RKW; } // --------------------------------------------------------------- // built-in function // --------------------------------------------------------------- #if 0 STATE(S_BUILTIN) { switch (kw) { default: break; #define X(a,b) \ case (FN_##a): \ _ifj_lexical_log("TOK_TYPE_FN \"%s\"", (b)); \ break; #include "builtin.def" //X_BUILTIN_FN #undef X } *attr = (void *) kw; return TOK_TYPE_FN; } #endif // --------------------------------------------------------------- // term -- numeric // --------------------------------------------------------------- STATE(S_NUMERIC) { *attr = s; _ifj_lexical_log("TOK_TYPE_NUM \"%s\"", string_getstr(s)); return TOK_TYPE_NUM; } STATE(S_KEYWORD) { switch (kw) { // ----------------------------------------------------------- // keyword // ----------------------------------------------------------- default: switch (kw) { default: break; #define X(a,b) \ case (KW_##a): \ _ifj_lexical_log("TOK_TYPE_KW \"%s\"", (b)); \ break; #include "keywords.def" X_KEYWORD #undef X } *attr = (void *) kw; return TOK_TYPE_KW; // ----------------------------------------------------------- // term -- boolean // ----------------------------------------------------------- case KW_TRUE: *attr = (void *) true; _ifj_lexical_log("TOK_TYPE_BOOL \"true\""); return TOK_TYPE_BOOL; case KW_FALSE: _ifj_lexical_log("TOK_TYPE_BOOL \"false\""); *attr = (void *) false; return TOK_TYPE_BOOL; // ----------------------------------------------------------- // term -- nil // ----------------------------------------------------------- case KW_NIL: _ifj_lexical_log("TOK_TYPE_NIL \"Nil\""); *attr = NULL; return TOK_TYPE_NIL; } } // --------------------------------------------------------------- // term -- string // --------------------------------------------------------------- STATE(S_STRING) { *attr = s; _ifj_lexical_log("TOK_TYPE_STR \"%s\"", string_getstr(s)); return TOK_TYPE_STR; } // --------------------------------------------------------------- // comment // --------------------------------------------------------------- STATE(S_COMMENT) { SRC_GET(c); if (c == EOF) { NEXTSTATE(S_EOF); } else if (c == '\n') { NEXTSTATE(S_EOL); } else { NEXTSTATE(S_COMMENT); } } // --------------------------------------------------------------- // block comment // --------------------------------------------------------------- STATE(S_COMMENT_BLOCK) { SRC_GET(c); if (c == EOF) { NEXTSTATE(S_EEOF); } else if (c != '*') { NEXTSTATE(S_COMMENT_BLOCK); } else { NEXTSTATE(S_COMMENT_BLOCK_2); } } STATE(S_COMMENT_BLOCK_2) { SRC_GET(c); if (c == EOF) { NEXTSTATE(S_EEOF); } else if (c == '/') { NEXTSTATE(S_INIT); } else { NEXTSTATE(S_COMMENT_BLOCK); } } // --------------------------------------------------------------- // eol // --------------------------------------------------------------- STATE(S_EOL) { ++_line; _col = 0; if (SRC_GET(c) == '\n') { NEXTSTATE(S_EOL); } else { SRC_UNGET(c); _ifj_lexical_log("TOK_EOL"); return TOK_EOL; } } // --------------------------------------------------------------- // eof // --------------------------------------------------------------- STATE(S_EOF) { _ifj_lexical_log("TOK_EOF"); return TOK_EOF; } // --------------------------------------------------------------- // error states // --------------------------------------------------------------- STATE(S_ERROR) { _ifj_error_log("%s:%zu:%zu: Neznamy znak %c", src_name, getCurrLine(), getCurrCol(), c); _ifj_lexical_log("TOK_EINVAL"); return TOK_EINVAL; } STATE(S_EEOF) { _ifj_error_log("%s:%zu:%zu: Neocekavany konec souboru", src_name, getCurrLine(), getCurrCol()); _ifj_lexical_log("TOK_EEOF"); return TOK_EEOF; } STATE(S_ESTRING) { _ifj_error_log ("%s:%zu:%zu: Neocekavany znak v retezci %c", src_name, getCurrLine(), getCurrCol(), c); _ifj_lexical_log("TOK_ESTRING"); return TOK_EINVAL; } STATE(S_ENUM) { _ifj_error_log("%s:%zu:%zu: Neocekavany tvar cisla %c", src_name, getCurrLine(), getCurrCol(), c); _ifj_lexical_log("TOK_ENUM"); return TOK_ENUM; } } NEXTSTATE(S_ERROR); alloc_failed: string_dispose(s); _ifj_error_log("%s", strerror(ENOMEM)); _ifj_lexical_log("TOK_ENOMEM"); return TOK_ENOMEM; }
static int scan(FILE *fp, const char *name, bool quiet) { int c; bool hasid = false; bool subversion = false; analyzer_states state = INIT; struct sbuf *id = sbuf_new_auto(); locale_t l; l = newlocale(LC_ALL_MASK, "C", NULL); if (name != NULL) printf("%s:\n", name); while ((c = fgetc(fp)) != EOF) { switch (state) { case INIT: if (c == '$') { /* Transit to DELIM_SEEN if we see $ */ state = DELIM_SEEN; } else { /* Otherwise, stay in INIT state */ continue; } break; case DELIM_SEEN: if (isalpha_l(c, l)) { /* Transit to KEYWORD if we see letter */ sbuf_clear(id); sbuf_putc(id, '$'); sbuf_putc(id, c); state = KEYWORD; continue; } else if (c == '$') { /* Or, stay in DELIM_SEEN if more $ */ continue; } else { /* Otherwise, transit back to INIT */ state = INIT; } break; case KEYWORD: sbuf_putc(id, c); if (isalpha_l(c, l)) { /* * Stay in KEYWORD if additional letter is seen */ continue; } else if (c == ':') { /* * See ':' for the first time, transit to * PUNC_SEEN. */ state = PUNC_SEEN; subversion = false; } else if (c == '$') { /* * Incomplete ident. Go back to DELIM_SEEN * state because we see a '$' which could be * the beginning of a keyword. */ state = DELIM_SEEN; } else { /* * Go back to INIT state otherwise. */ state = INIT; } break; case PUNC_SEEN: case PUNC_SEEN_SVN: sbuf_putc(id, c); switch (c) { case ':': /* * If we see '::' (seen : in PUNC_SEEN), * activate subversion treatment and transit * to PUNC_SEEN_SVN state. * * If more than two :'s were seen, the ident * is invalid and we would therefore go back * to INIT state. */ if (state == PUNC_SEEN) { state = PUNC_SEEN_SVN; subversion = true; } else { state = INIT; } break; case ' ': /* * A space after ':' or '::' indicates we are at the * last component of potential ident. */ state = TEXT; break; default: /* All other characters are invalid */ state = INIT; break; } break; case TEXT: sbuf_putc(id, c); if (iscntrl_l(c, l)) { /* Control characters are not allowed in this state */ state = INIT; } else if (c == '$') { sbuf_finish(id); /* * valid ident should end with a space. * * subversion extension uses '#' to indicate that * the keyword expansion have exceeded the fixed * width, so it is also permitted if we are in * subversion mode. No length check is enforced * because GNU RCS ident(1) does not do it either. */ c = sbuf_data(id)[sbuf_len(id) - 2]; if (c == ' ' || (subversion && c == '#')) { printf(" %s\n", sbuf_data(id)); hasid = true; } state = INIT; } /* Other characters: stay in the state */ break; } } sbuf_delete(id); freelocale(l); if (!hasid) { if (!quiet) fprintf(stderr, "%s warning: no id keywords in %s\n", getprogname(), name ? name : "standard input"); return (EXIT_FAILURE); } return (EXIT_SUCCESS); }
char * readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) { ssize_t nr; int input, output, save_errno; char ch, *p, *end; struct termios term, oterm; struct sigaction sa, saveint, savehup, savequit, saveterm; struct sigaction savetstp, savettin, savettou; locale_t loc = __current_locale(); /* I suppose we could alloc on demand in this case (XXX). */ if (bufsiz == 0) { errno = EINVAL; return(NULL); } restart: /* * Read and write to /dev/tty if available. If not, read from * stdin and write to stderr unless a tty is required. */ if ((input = output = _open(_PATH_TTY, O_RDWR)) == -1) { if (flags & RPP_REQUIRE_TTY) { errno = ENOTTY; return(NULL); } input = STDIN_FILENO; output = STDERR_FILENO; } /* * Catch signals that would otherwise cause the user to end * up with echo turned off in the shell. Don't worry about * things like SIGALRM and SIGPIPE for now. */ sigemptyset(&sa.sa_mask); sa.sa_flags = 0; /* don't restart system calls */ sa.sa_handler = handler; (void)_sigaction(SIGINT, &sa, &saveint); (void)_sigaction(SIGHUP, &sa, &savehup); (void)_sigaction(SIGQUIT, &sa, &savequit); (void)_sigaction(SIGTERM, &sa, &saveterm); (void)_sigaction(SIGTSTP, &sa, &savetstp); (void)_sigaction(SIGTTIN, &sa, &savettin); (void)_sigaction(SIGTTOU, &sa, &savettou); /* Turn off echo if possible. */ if (tcgetattr(input, &oterm) == 0) { memcpy(&term, &oterm, sizeof(term)); if (!(flags & RPP_ECHO_ON)) term.c_lflag &= ~(ECHO | ECHONL); if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) term.c_cc[VSTATUS] = _POSIX_VDISABLE; (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); } else { memset(&term, 0, sizeof(term)); memset(&oterm, 0, sizeof(oterm)); } (void)_write(output, prompt, strlen(prompt)); end = buf + bufsiz - 1; for (p = buf; (nr = _read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) { if (p < end) { if ((flags & RPP_SEVENBIT)) ch &= 0x7f; if (isalpha_l(ch, loc)) { if ((flags & RPP_FORCELOWER)) ch = tolower_l(ch, loc); if ((flags & RPP_FORCEUPPER)) ch = toupper_l(ch, loc); } *p++ = ch; } } *p = '\0'; save_errno = errno; if (!(term.c_lflag & ECHO)) (void)_write(output, "\n", 1); /* Restore old terminal settings and signals. */ if (memcmp(&term, &oterm, sizeof(term)) != 0) (void)tcsetattr(input, TCSANOW|TCSASOFT, &oterm); (void)_sigaction(SIGINT, &saveint, NULL); (void)_sigaction(SIGHUP, &savehup, NULL); (void)_sigaction(SIGQUIT, &savequit, NULL); (void)_sigaction(SIGTERM, &saveterm, NULL); (void)_sigaction(SIGTSTP, &savetstp, NULL); (void)_sigaction(SIGTTIN, &savettin, NULL); (void)_sigaction(SIGTTOU, &savettou, NULL); if (input != STDIN_FILENO) (void)_close(input); /* * If we were interrupted by a signal, resend it to ourselves * now that we have restored the signal handlers. */ if (signo) { kill(getpid(), signo); switch (signo) { case SIGTSTP: case SIGTTIN: case SIGTTOU: signo = 0; goto restart; } } errno = save_errno; return(nr == -1 ? NULL : buf); }