new .d file parser for C compilation

- wip for #2046
- clang .d output must be created with `clang -MV` switch
- implemented in Zig
- hybridized for zig stage0 and stage1
- zig test src-self-hosted/dep_tokenizer.zig
master
Michael Dusan 2019-05-27 19:47:10 -04:00
parent f68d8060ec
commit d4b241c14e
No known key found for this signature in database
GPG Key ID: ED4C5BA849FA1B74
6 changed files with 1234 additions and 58 deletions

View File

@ -6726,6 +6726,7 @@ add_custom_command(
"-Doutput-dir=${CMAKE_BINARY_DIR}"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
DEPENDS
"${CMAKE_SOURCE_DIR}/src-self-hosted/dep_tokenizer.zig"
"${CMAKE_SOURCE_DIR}/src-self-hosted/stage1.zig"
"${CMAKE_SOURCE_DIR}/src-self-hosted/translate_c.zig"
"${CMAKE_SOURCE_DIR}/build.zig"

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,10 @@ var stderr_file: fs.File = undefined;
var stderr: *io.OutStream(fs.File.WriteError) = undefined;
var stdout: *io.OutStream(fs.File.WriteError) = undefined;
comptime {
_ = @import("dep_tokenizer.zig");
}
// ABI warning
export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
const info_zen = @import("main.zig").info_zen;

View File

@ -5,6 +5,7 @@
* See http://opensource.org/licenses/MIT
*/
#include "userland.h"
#include "cache_hash.hpp"
#include "all_types.hpp"
#include "buffer.hpp"
@ -473,71 +474,62 @@ Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) {
if (err == ErrorFileNotFound)
return err;
if (verbose) {
fprintf(stderr, "unable to read .d file: %s\n", err_str(err));
fprintf(stderr, "%s: unable to read .d file: %s\n", err_str(err), buf_ptr(dep_file_path));
}
return ErrorReadingDepFile;
}
SplitIterator it = memSplit(buf_to_slice(contents), str("\r\n"));
// skip first line
SplitIterator_next(&it);
for (;;) {
Optional<Slice<uint8_t>> opt_line = SplitIterator_next(&it);
if (!opt_line.is_some)
break;
if (opt_line.value.len == 0)
continue;
// skip over indentation
while (opt_line.value.len != 0 && (opt_line.value.ptr[0] == ' ' || opt_line.value.ptr[0] == '\t')) {
opt_line.value.ptr += 1;
opt_line.value.len -= 1;
}
if (opt_line.value.len == 0)
continue;
if (opt_line.value.ptr[0] == '"') {
if (opt_line.value.len < 2) {
auto it = stage2_DepTokenizer_init(buf_ptr(contents), buf_len(contents));
// skip first token: target
{
auto result = stage2_DepTokenizer_next(&it);
switch (result.ent) {
case stage2_DepNextResult::error:
if (verbose) {
fprintf(stderr, "unable to process invalid .d file %s: line too short\n", buf_ptr(dep_file_path));
fprintf(stderr, "%s: failed processing .d file: %s\n", result.textz, buf_ptr(dep_file_path));
}
return ErrorInvalidDepFile;
}
opt_line.value.ptr += 1;
opt_line.value.len -= 2;
while (opt_line.value.len != 0 && opt_line.value.ptr[opt_line.value.len] != '"') {
opt_line.value.len -= 1;
}
if (opt_line.value.len == 0) {
if (verbose) {
fprintf(stderr, "unable to process invalid .d file %s: missing double quote\n", buf_ptr(dep_file_path));
}
return ErrorInvalidDepFile;
}
Buf *filename_buf = buf_create_from_slice(opt_line.value);
if ((err = cache_add_file(ch, filename_buf))) {
if (verbose) {
fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(filename_buf), err_str(err));
fprintf(stderr, "when processing .d file: %s\n", buf_ptr(dep_file_path));
}
return err;
}
} else {
// sometimes there are multiple files on the same line; we actually need space tokenization.
SplitIterator line_it = memSplit(opt_line.value, str(" \t"));
Slice<uint8_t> filename;
while (SplitIterator_next(&line_it).unwrap(&filename)) {
Buf *filename_buf = buf_create_from_slice(filename);
if (buf_eql_str(filename_buf, "\\")) continue;
if ((err = cache_add_file(ch, filename_buf))) {
if (verbose) {
fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(filename_buf), err_str(err));
fprintf(stderr, "when processing .d file: %s\n", buf_ptr(dep_file_path));
}
return err;
}
}
err = ErrorInvalidDepFile;
goto finish;
case stage2_DepNextResult::null:
err = ErrorNone;
goto finish;
case stage2_DepNextResult::target:
case stage2_DepNextResult::prereq:
err = ErrorNone;
break;
}
}
return ErrorNone;
// Process 0+ preqreqs.
// clang is invoked in single-source mode so we never get more targets.
for (;;) {
auto result = stage2_DepTokenizer_next(&it);
switch (result.ent) {
case stage2_DepNextResult::error:
if (verbose) {
fprintf(stderr, "%s: failed processing .d file: %s\n", result.textz, buf_ptr(dep_file_path));
}
err = ErrorInvalidDepFile;
goto finish;
case stage2_DepNextResult::null:
case stage2_DepNextResult::target:
err = ErrorNone;
goto finish;
case stage2_DepNextResult::prereq:
break;
}
auto textbuf = buf_alloc();
buf_init_from_str(textbuf, result.textz);
if ((err = cache_add_file(ch, textbuf))) {
if (verbose) {
fprintf(stderr, "unable to add %s to cache: %s\n", result.textz, err_str(err));
fprintf(stderr, "when processing .d file: %s\n", buf_ptr(dep_file_path));
}
goto finish;
}
}
finish:
stage2_DepTokenizer_deinit(&it);
return err;
}
static Error write_manifest_file(CacheHash *ch) {

View File

@ -42,3 +42,18 @@ int stage2_fmt(int argc, char **argv) {
const char *msg = "stage0 called stage2_fmt";
stage2_panic(msg, strlen(msg));
}
stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len) {
const char *msg = "stage0 called stage2_DepTokenizer_init";
stage2_panic(msg, strlen(msg));
}
void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self) {
const char *msg = "stage0 called stage2_DepTokenizer_deinit";
stage2_panic(msg, strlen(msg));
}
stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self) {
const char *msg = "stage0 called stage2_DepTokenizer_next";
stage2_panic(msg, strlen(msg));
}

View File

@ -9,6 +9,7 @@
#define ZIG_USERLAND_H
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus
@ -118,4 +119,36 @@ ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t le
// ABI warning
ZIG_EXTERN_C int stage2_fmt(int argc, char **argv);
// ABI warning
struct stage2_DepTokenizer {
void *handle;
};
// ABI warning
struct stage2_DepNextResult {
enum Ent : uint8_t {
error,
null,
target,
prereq,
};
Ent ent;
// when ent == error --> error text
// when ent == null --> undefined
// when ent == target --> target pathname
// when ent == prereq --> prereq pathname
const char *textz;
};
// ABI warning
ZIG_EXTERN_C stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len);
// ABI warning
ZIG_EXTERN_C void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self);
// ABI warning
ZIG_EXTERN_C stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self);
#endif