/* * #undef * (C99 6.10.5 Scope of macro definisions, paragraph 2) */ static void read_undef(CppContext *ctx) { Token *name = read_cpp_token(ctx); if (!name || name->toktype != TOKTYPE_IDENT) error_token(name, "undef works only to an identifier, but got '%s'", token_to_string(name)); expect_newline(ctx); dict_delete(ctx->defs, name->val.str); }
/* * Handles #if, #elif, #ifdef and #ifndef. If condition does not meet, the * function calls skip_cond_include(), defined in lex.c, to skip all tokens * until the next #elif, #else of #endif. * * (C99 6.10.1 Conditional inclusion) */ static void handle_cond_incl(CppContext *ctx, CondInclType type) { bool cond; switch (type) { case COND_IF: cond = read_constant_expr(ctx); break; case COND_IFDEF: cond = read_ifdef(ctx); break; case COND_IFNDEF: cond = !read_ifdef(ctx); break; case COND_ELIF: error_cpp_ctx(ctx, "stray #elif"); case COND_ELSE: expect_newline(ctx); if (LIST_IS_EMPTY(ctx->incl)) error_cpp_ctx(ctx, "stray #else"); bool in_else = (intptr)list_pop(ctx->incl); if (in_else) error_cpp_ctx(ctx, "#else appears twice"); CondInclType type1 = skip_cond_incl(ctx); if (type1 == COND_ELIF) error_cpp_ctx(ctx, "stray #elif"); if (type1 == COND_ELSE) error_cpp_ctx(ctx, "stray #else"); return; case COND_ENDIF: expect_newline(ctx); if (LIST_IS_EMPTY(ctx->incl)) error_cpp_ctx(ctx, "stray #endif"); list_pop(ctx->incl); return; } if (cond) { list_push(ctx->incl, (void *)false); return; } // skip_cond_incl() returns one of COND_ELIF, COND_ELSE or COND_ENDIF. CondInclType type1 = skip_cond_incl(ctx); if (type1 == COND_ELIF) handle_cond_incl(ctx, COND_IF); else if (type1 == COND_ELSE) list_push(ctx->incl, (void *)true); }
/* * #include * (C99 6.10.2 Source file inclusion) */ static void handle_include(CppContext *ctx) { String *name; bool std; read_cpp_header_name(ctx, &name, &std); expect_newline(ctx); List *include_path = std ? ctx->include_path : make_list1(to_string("")); File *file = open_header(ctx, name, include_path); do_include(ctx, file); }
/* * #line * (C99 6.10.4 Line control) * * Line directive must be one of the following form in macro-expanded form: * * #line digit-sequence * #line digit-sequence "s-char-sequenceopt" */ static void handle_line_directive(CppContext *ctx) { Token *tok = expand_one(ctx); if (!tok || tok->toktype != TOKTYPE_CPPNUM) error_token(tok, "number expected, but got '%s'", token_to_string(tok)); int line = cppnum_to_num(tok)->val.i; tok = expand_one(ctx); if (tok && tok->toktype == TOKTYPE_NEWLINE) { ctx->file->line = line; return; } if (tok && tok->toktype == TOKTYPE_STRING) { expect_newline(ctx); ctx->file->line = line; ctx->file->filename = tok->val.str; return; } error_token(tok, "filename expected, but got '%s'", token_to_string(tok)); }
static int parseit (void) { int r; char *dot = NULL; if (!exports_seen) { if ((r = lexit2 ()) == -1) return 0; if (r == TK_EXPORTS) { r = expect_newline ("EXPORTS"); return (r != -1 ? 1 : 0); } if (r == TK_LIBRARY) { r = lexit2 (); if (r != TK_STRING && r != TK_NAME) { fprintf (stderr, "Expect name/string after LIBRARY keyword.\n"); return (r != -1 ? 1 : 0); } cur_libname = unifyStr (t_buf); if ((dot = strchr (t_buf, '.')) != NULL) { *dot = '\0'; cur_libbasename = unifyStr (t_buf); } fprintf (stderr, "Current library-name set to %s'\n", cur_libname); cur_outlibbasename = unifyCat (cur_libbasename, SUFFIX); r = expect_newline ("LIBRARY"); return (r != -1 ? 1 : 0); } } else { if ((r = lexit2 ()) == -1) return 0; if (r != TK_NAME) { fprintf (stderr, "Unexpected token ,%s'. Would have expected a string/name.\n", t_buf); return (expect_newline ("UNKNOWN") == -1 ? 0 : 1); } cur_symbol = unifyStr (t_buf); cur_alias = ""; cur_libsymbol = ""; cur_srcfile = ""; cur_data = 0; while ((r = lexit2 ()) != -1 && r != TK_NL) { if (r == TK_DATA) cur_data = 1; else if (r == TK_EQUAL) { r = lexit2 (); if (r != TK_NAME) { fprintf (stderr, "Expected name after = expression.\n"); if (r != -1 && r != TK_NL) r = expect_newline ("SYMBOL"); return (r == -1 ? 0 : 1); } cur_libsymbol = unifyStr (t_buf); } else if (r == TK_EQUALEQUAL) { r = lexit2 (); if (r != TK_NAME) { fprintf (stderr, "Expected name after == expression.\n"); if (r != -1 && r != TK_NL) r = expect_newline ("SYMBOL"); return (r == -1 ? 0 : 1); } cur_alias = unifyStr (t_buf); } else if (r == TK_SOURCEFILENAME) { cur_srcfile = unifyStr (t_buf); } else { fprintf (stderr, "Unknown token ,%s'.\n", t_buf); } } addSymbol (cur_symbol, cur_libsymbol, cur_alias, cur_srcfile, cur_data); } return (r != -1 ? 1 : 0); }
/* * #ifdef * (C99 6.10.1 Conditional inclusion, paragraph 5) */ static int read_ifdef(CppContext *ctx) { int r = is_defined(ctx, read_cpp_token(ctx)); expect_newline(ctx); return r; }