/* * handle_specials */ int handle_specials (parse_ctx_t pctx, void *vctx, quotelevel_t ql, lextype_t curlt) { macroctx_t ctx = vctx; strdesc_t *str; lexseq_t result; if (ctx->curexp == 0) { log_signal(parser_logctx(pctx), parser_curpos(pctx), STC__INVMACFUN); return 1; } switch (curlt) { case LEXTYPE_LXF_COUNT: // our internal counter is 1-based; %COUNT is zero-based. str = string_printf(parser_strctx(pctx), 0, "%ld", ctx->curexp->count-1); parser_insert(pctx, parser_lexeme_create(pctx, LEXTYPE_NUMERIC, str)); string_free(parser_strctx(pctx), str); break; case LEXTYPE_LXF_LENGTH: str = string_printf(parser_strctx(pctx), 0, "%ld", ctx->curexp->nactuals); parser_insert(pctx, parser_lexeme_create(pctx, LEXTYPE_NUMERIC, str)); string_free(parser_strctx(pctx), str); break; case LEXTYPE_LXF_REMAINING: lexseq_init(&result); lexseq_copy(parser_lexmemctx(pctx), &result, &ctx->curexp->remaining); parser_insert_seq(pctx, &result); break; default: break; } return 1; } /* handle_specials */
static void sig_exit (int sig) { log_signal (sig); server_quit = 1; // FIXME (JCF): pthread_*() are not async-signal-safe and // should not be used within signal handlers. if (!pthread_equal (server_tid, pthread_self())) pthread_kill (server_tid, sig); }
static void sig_chld (int sig LOGIT_ONLY) { int saved_errno; pid_t rc; log_signal (sig); saved_errno = errno; do { rc = waitpid (-1, NULL, WNOHANG); } while (rc > 0); errno = saved_errno; }
/* * lexer_insert_seq * * Inserts a sequence of lexemes at the front of the stream. */ void lexer_insert_seq (lexer_ctx_t ctx, lexseq_t *seq) { lexchain_t *chain = ctx->chain; if (seq == 0 || lexseq_length(seq) == 0) { return; } if (chain == 0) { chain = lexchain_alloc(ctx); if (chain == 0) { log_signal(ctx->logctx, 0, STC__OUTOFMEM, "lexer_insert_seq"); return; } chain->nextchain = ctx->chain; ctx->chain = chain; } lexseq_prepend(&chain->seq, seq); } /* lexer_insert_seq_internal */
/* * lexer_popen * Insert a programmatic input source at the front of the stream. */ int lexer_popen (lexer_ctx_t ctx, void *vinfn, void *fnctx) { scan_input_fn infn = vinfn; lexchain_t *chain = lexchain_alloc(ctx); if (chain == 0) { log_signal(ctx->logctx, 0, STC__OUTOFMEM, "lexer_popen"); return 0; } chain->strm = scan_popen(ctx->scnctx, infn, fnctx); if (chain->strm == 0) { lexchain_free(ctx, chain); return 0; } chain->filename_index = -1; chain->nextchain = ctx->chain; ctx->chain = chain; ctx->atend = 0; return 1; } /* lexer_popen */
/* * lexer_insert * * Insert a single lexeme to the front of the stream. */ void lexer_insert (lexer_ctx_t ctx, lexeme_t *lex) { lexchain_t *chain = ctx->chain; // The static ones should never be inserted, and // just ignore nulls. if (lex == &errlex || lex == &endlex || lex == 0) { return; } if (chain == 0) { chain = lexchain_alloc(ctx); if (chain == 0) { log_signal(ctx->logctx, 0, STC__OUTOFMEM, "lexer_insert"); return; } chain->nextchain = ctx->chain; ctx->chain = chain; } lexseq_inshead(&chain->seq, lex); } /* lexer_insert */
/* * lexer_fopen * Insert a new file at the front of the stream. */ int lexer_fopen (lexer_ctx_t ctx, const char *fname, size_t fnlen, char **actnamep) { lexchain_t *chain = lexchain_alloc(ctx); char *actname; if (chain == 0) { log_signal(ctx->logctx, 0, STC__OUTOFMEM, "lexer_fopen"); return 0; } chain->strm = scan_fopen(ctx->scnctx, fname, fnlen, &actname); if (chain->strm == 0) { lexchain_free(ctx, chain); return 0; } chain->filename_index = filename_lookup(ctx, actname, strlen(actname), 0); chain->nextchain = ctx->chain; ctx->chain = chain; if (actnamep != 0) *actnamep = actname; ctx->atend = 0; return 1; } /* lexer_fopen */
/* * lexer___next * * Returns the next lexeme in the stream. * If 'erroneof' is set, reaching the end of a file (not the * end of the stream) should be considered an error condition -- * this happens when we're in the middle of parsing a lexical * conditional or a macro definition; they must be wholly contained * within a single file. * * This is the internal version that handles both lexer_next * and lexer_peek processing. */ static lexeme_t * lexer___next (lexer_ctx_t ctx, int erroneof, int peek, textpos_t *posp) { lexeme_t *lex = 0; lextype_t lextype; strdesc_t *tok; unsigned int column; char *cp; if (ctx == 0) { return &errlex; } if (ctx->atend) { return &endlex; } while (ctx->chain != 0) { lexchain_t *chain = ctx->chain; lex = (peek ? lexseq_head(&chain->seq) : lexseq_remhead(&chain->seq)); if (lex != 0) { break; } if (chain->strm != 0) { scantype_t type; unsigned int sflags; sflags = (erroneof ? SCAN_M_ERRONEOF : 0) | (ctx->signok ? SCAN_M_SIGNOK : 0); type = scan_getnext(chain->strm, sflags, &tok, &chain->curline, &column); if (!scan_ok(type)) { textpos_t pos = textpos_create(chain->filename_index, chain->curline, column); log_signal(ctx->logctx, pos, STC__INVTOKEN); lex = &errlex; string_free(ctx->strctx, tok); break; } if (!peek && posp != 0) { *posp = textpos_create(chain->filename_index, chain->curline, column); } if (type == SCANTYPE_END) { scan_close(chain->strm); chain->strm = 0; ctx->chain = chain->nextchain; lexchain_free(ctx, chain); if (ctx->chain == 0) { lex = &endlex; ctx->atend = 1; string_free(ctx->strctx, tok); break; } string_free(ctx->strctx, tok); continue; } switch (type) { case SCANTYPE_DECLITERAL: lextype = LEXTYPE_NUMERIC; ctx->signok = 0; break; case SCANTYPE_QUOTEDSTRING: lextype = LEXTYPE_STRING; ctx->signok = 1; break; case SCANTYPE_OPERATOR: cp = strchr(operators, *tok->ptr); lextype = opertypes[cp-operators]; ctx->signok = 1; break; case SCANTYPE_PUNCTUATION: cp = strchr(delimiters, *tok->ptr); lextype = delimtypes[cp-delimiters]; ctx->signok = (strchr(")>]", *tok->ptr) == 0); break; case SCANTYPE_IDENTIFIER: lextype = LEXTYPE_NAME; ctx->signok = 0; break; default: lextype = LEXTYPE_NONE; break; } if (lextype == LEXTYPE_NONE) { lex = &errlex; } else { lex = lexeme_create(ctx->lexctx, lextype, tok); if (peek) { lexseq_inshead(&chain->seq, lex); } } string_free(ctx->strctx, tok); break; } else { ctx->chain = chain->nextchain; lexchain_free(ctx, chain); if (ctx->chain == 0) { lex = &endlex; ctx->atend = 1; break; } } } return lex; } /* lexer___next */
static int list_switch_handler (parse_ctx_t pctx, void *vctx, lextype_t dtype, lexeme_t *swlex) { lstgctx_t ctx = vctx; lexeme_t *lex; liststate_t *newstate; int i; if (!parser_expect(pctx, QL_NORMAL, LEXTYPE_DELIM_LPAR, 0, 1)) { log_signal(parser_logctx(pctx), parser_curpos(pctx), STC__DELIMEXP, "("); return 0; } if (parser_scope_get(pctx) != ctx->cur_state->this_scope) { newstate = malloc(sizeof(liststate_t)); if (newstate == 0) { log_signal(parser_logctx(pctx), parser_curpos(pctx), STC__INTCMPERR, "list_switch_handler"); return 0; } memcpy(newstate, ctx->cur_state, sizeof(liststate_t)); newstate->next = ctx->cur_state; newstate->this_scope = parser_scope_get(pctx); ctx->cur_state = newstate; } else { newstate = 0; } while (1) { i = parser_expect_oneof(pctx, QL_NORMAL, lopt_lextypes, sizeof(lopt_lextypes)/sizeof(lopt_lextypes[0]), &lex, 1); if (i < 0) { log_signal(parser_logctx(pctx), parser_curpos(pctx), STC__LSTOPTEXP); break; } if (lexeme_type(lex) == LEXTYPE_DCL_REQUIRE) { ctx->cur_state->listopts[LISTOPT_REQ] = 1; } else if (lexeme_type(lex) == LEXTYPE_DCL_LIBRARY) { ctx->cur_state->listopts[LISTOPT_LIB] = 1; } else { value_toggle_dispatch(pctx, ctx, dtype, lexeme_ctx_get(lex)); } lexeme_free(parser_lexmemctx(pctx), lex); if (parser_expect(pctx, QL_NORMAL, LEXTYPE_DELIM_RPAR, 0, 1)) { return 1; } if (!parser_expect(pctx, QL_NORMAL, LEXTYPE_DELIM_COMMA, 0, 1)) { log_signal(parser_logctx(pctx), parser_curpos(pctx), STC__DELIMEXP, ","); break; } } /* while */ // We break out of the loop only on error if (newstate != 0) { ctx->cur_state = newstate->next; free(newstate); } parser_skip_to_delim(pctx, LEXTYPE_DELIM_RPAR); return 0; } /* list_switch_handler */