Nigel Tao | 79a9455 | 2017-11-30 16:37:20 +1100 | [diff] [blame] | 1 | // Copyright 2017 The Wuffs Authors. |
Nigel Tao | e57c8d7 | 2017-11-03 15:05:19 +1100 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // https://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | // +build ignore |
| 16 | |
| 17 | package main |
| 18 | |
| 19 | // inline-c-relative-includes.go echoes the given C file to stdout, expanding |
| 20 | // #include lines that uses "quoted files" (but not <bracketed files>). |
| 21 | // |
| 22 | // The output should be a stand-alone C file that other people can easily |
Nigel Tao | d1399fa | 2018-03-16 10:48:33 +1100 | [diff] [blame] | 23 | // compile and run with no further dependencies, other than test/data files. |
Nigel Tao | e57c8d7 | 2017-11-03 15:05:19 +1100 | [diff] [blame] | 24 | // |
| 25 | // Usage: go run inline-c-relative-includes.go path/to/foo.c |
| 26 | |
| 27 | import ( |
| 28 | "bufio" |
| 29 | "bytes" |
| 30 | "fmt" |
| 31 | "os" |
| 32 | "path/filepath" |
| 33 | ) |
| 34 | |
| 35 | func main() { |
| 36 | if err := main1(); err != nil { |
| 37 | os.Stderr.WriteString(err.Error() + "\n") |
| 38 | os.Exit(1) |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | func main1() error { |
| 43 | if len(os.Args) != 2 { |
| 44 | return fmt.Errorf("inline-c-relative-includes takes exactly 1 argument") |
| 45 | } |
| 46 | w := bufio.NewWriter(os.Stdout) |
| 47 | defer w.Flush() |
| 48 | return do(w, ".", os.Args[1], 0) |
| 49 | } |
| 50 | |
| 51 | var ( |
| 52 | prefix = []byte(`#include "`) |
| 53 | suffix = []byte(`"`) |
| 54 | |
| 55 | seen = map[string]bool{} |
| 56 | ) |
| 57 | |
| 58 | func do(w *bufio.Writer, dir string, filename string, depth int) error { |
| 59 | if depth == 100 { |
| 60 | return fmt.Errorf("recursion too deep") |
| 61 | } |
| 62 | if depth != 0 { |
| 63 | fmt.Fprintf(w, "// BEGIN INLINE #include %q\n", filename) |
| 64 | defer fmt.Fprintf(w, "// END INLINE #include %q\n", filename) |
| 65 | } |
| 66 | depth++ |
| 67 | |
| 68 | filename = filepath.Join(dir, filename) |
| 69 | if seen[filename] { |
| 70 | return fmt.Errorf("duplicate filename %q", filename) |
| 71 | } |
| 72 | seen[filename] = true |
| 73 | |
| 74 | dir, _ = filepath.Split(filename) |
| 75 | f, err := os.Open(filename) |
| 76 | if err != nil { |
| 77 | return err |
| 78 | } |
| 79 | defer f.Close() |
| 80 | |
| 81 | r := bufio.NewScanner(f) |
| 82 | for r.Scan() { |
Nigel Tao | e364357 | 2017-11-03 15:33:23 +1100 | [diff] [blame] | 83 | line := r.Bytes() |
Nigel Tao | e57c8d7 | 2017-11-03 15:05:19 +1100 | [diff] [blame] | 84 | |
Nigel Tao | e364357 | 2017-11-03 15:33:23 +1100 | [diff] [blame] | 85 | if s := line; bytes.HasPrefix(s, prefix) { |
Nigel Tao | e57c8d7 | 2017-11-03 15:05:19 +1100 | [diff] [blame] | 86 | s = s[len(prefix):] |
| 87 | if bytes.HasSuffix(s, suffix) { |
| 88 | s = s[:len(s)-len(suffix)] |
| 89 | if err := do(w, dir, string(s), depth); err == nil { |
| 90 | continue |
| 91 | } else if os.IsNotExist(err) { |
| 92 | // This is probably an #include of a system header, like |
Nigel Tao | 024dc7f | 2017-11-30 18:18:40 +1100 | [diff] [blame] | 93 | // `#include "zlib.h"`, and not of Wuffs code. Fall through |
Nigel Tao | e57c8d7 | 2017-11-03 15:05:19 +1100 | [diff] [blame] | 94 | // and print the #include line as normal. |
| 95 | } else { |
| 96 | return err |
| 97 | } |
| 98 | } |
| 99 | } |
| 100 | |
Nigel Tao | e364357 | 2017-11-03 15:33:23 +1100 | [diff] [blame] | 101 | w.Write(line) |
Nigel Tao | e57c8d7 | 2017-11-03 15:05:19 +1100 | [diff] [blame] | 102 | w.WriteByte('\n') |
| 103 | } |
| 104 | return r.Err() |
| 105 | } |