kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

cpp.c (2715B)


      1 /* cpp.c — public entry point for the kit C preprocessor.
      2  *
      3  * kit_cpp_preprocess() runs the preprocessor under the standard
      4  * frontend panic boundary and writes the resulting token stream as
      5  * text to the caller's writer. This is the implementation behind
      6  * `kit cpp` and `kit cc -E`; the full C frontend reuses it too. */
      7 
      8 #include <kit/preprocess.h>
      9 
     10 #include "cpp_support.h"
     11 #include "lex/lex.h"
     12 #include "pp/pp.h"
     13 
     14 static SrcLoc cpp_no_loc(void) {
     15   SrcLoc loc;
     16   loc.file_id = 0;
     17   loc.line = 0;
     18   loc.col = 0;
     19   return loc;
     20 }
     21 
     22 static _Noreturn void cpp_bad_options(Compiler* c, const char* msg) {
     23   compiler_panic(c, cpp_no_loc(), "bad preprocess options: %.*s",
     24                  KIT_SLICE_ARG(kit_slice_cstr(msg)));
     25 }
     26 
     27 static void cpp_apply_options(Pp* pp, const KitPreprocessOptions* opts) {
     28   u32 i;
     29 
     30   for (i = 0; i < opts->ninclude_dirs; ++i) {
     31     pp_add_include_dir(pp, opts->include_dirs[i], 0);
     32   }
     33   for (i = 0; i < opts->nsystem_include_dirs; ++i) {
     34     pp_add_include_dir(pp, opts->system_include_dirs[i], 1);
     35   }
     36   for (i = 0; i < opts->ndefines; ++i) {
     37     const char* body =
     38         opts->defines[i].body.len ? opts->defines[i].body.s : "1";
     39     pp_define(pp, opts->defines[i].name.s, body);
     40   }
     41   for (i = 0; i < opts->nundefines; ++i) {
     42     pp_undef(pp, opts->undefines[i].s);
     43   }
     44 }
     45 
     46 typedef struct CppRun {
     47   const KitPreprocessOptions* opts;
     48   KitSlice name;
     49   const KitSlice* input;
     50   KitWriter* out;
     51 } CppRun;
     52 
     53 static KitStatus cpp_preprocess_body(KitCompiler* c, void* user) {
     54   CppRun* r = (CppRun*)user;
     55   Pp* pp;
     56   SourceSpec spec;
     57 
     58   const KitPreprocessOptions* opts = r->opts;
     59   const KitSlice* input = r->input;
     60   KitWriter* out = r->out;
     61 
     62   if (!opts || !input || !out) {
     63     cpp_bad_options(c, "preprocess args missing");
     64   }
     65   if (!r->name.s) cpp_bad_options(c, "input name is NULL");
     66   if (!input->data && input->len != 0) {
     67     cpp_bad_options(c, "input data is NULL but len > 0");
     68   }
     69 
     70   pp = pp_new(c);
     71   if (!pp) compiler_panic(c, cpp_no_loc(), "C preprocessor out of memory");
     72   cpp_apply_options(pp, opts);
     73   /* -E / cpp: NOT parser-feed — newlines surface for text reconstruction. */
     74   memset(&spec, 0, sizeof(spec));
     75   spec.name = kit_slice_cstr(r->name.s);
     76   spec.bytes = input->s;
     77   spec.len = (u32)input->len;
     78   spec.flags = SRC_PRIMARY;
     79   pp_push_source(pp, &spec);
     80   pp_emit_text(pp, out);
     81   pp_free(pp);
     82   return KIT_OK;
     83 }
     84 
     85 KitStatus kit_cpp_preprocess(KitCompiler* c, const KitPreprocessOptions* opts,
     86                              KitSlice name, const KitSlice* input,
     87                              KitWriter* out) {
     88   CppRun r;
     89   r.opts = opts;
     90   r.name = name;
     91   r.input = input;
     92   r.out = out;
     93   return kit_frontend_run(c, cpp_preprocess_body, &r);
     94 }