blob: 8c700e2fde7efcbcedc32c850469a75e61d3ba91 [file] [log] [blame]
Nigel Tao79a94552017-11-30 16:37:20 +11001// Copyright 2017 The Wuffs Authors.
Nigel Taoe57c8d72017-11-03 15:05:19 +11002//
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
Nigel Tao788479d2021-08-22 10:52:51 +100015//go:build ignore
Nigel Taoe57c8d72017-11-03 15:05:19 +110016// +build ignore
17
18package main
19
20// inline-c-relative-includes.go echoes the given C file to stdout, expanding
21// #include lines that uses "quoted files" (but not <bracketed files>).
22//
23// The output should be a stand-alone C file that other people can easily
Nigel Taod1399fa2018-03-16 10:48:33 +110024// compile and run with no further dependencies, other than test/data files.
Nigel Taoe57c8d72017-11-03 15:05:19 +110025//
26// Usage: go run inline-c-relative-includes.go path/to/foo.c
27
28import (
29 "bufio"
30 "bytes"
31 "fmt"
32 "os"
33 "path/filepath"
34)
35
36func main() {
37 if err := main1(); err != nil {
38 os.Stderr.WriteString(err.Error() + "\n")
39 os.Exit(1)
40 }
41}
42
43func main1() error {
44 if len(os.Args) != 2 {
45 return fmt.Errorf("inline-c-relative-includes takes exactly 1 argument")
46 }
47 w := bufio.NewWriter(os.Stdout)
48 defer w.Flush()
49 return do(w, ".", os.Args[1], 0)
50}
51
52var (
53 prefix = []byte(`#include "`)
54 suffix = []byte(`"`)
55
56 seen = map[string]bool{}
57)
58
59func do(w *bufio.Writer, dir string, filename string, depth int) error {
60 if depth == 100 {
61 return fmt.Errorf("recursion too deep")
62 }
63 if depth != 0 {
64 fmt.Fprintf(w, "// BEGIN INLINE #include %q\n", filename)
65 defer fmt.Fprintf(w, "// END INLINE #include %q\n", filename)
66 }
67 depth++
68
69 filename = filepath.Join(dir, filename)
70 if seen[filename] {
71 return fmt.Errorf("duplicate filename %q", filename)
72 }
73 seen[filename] = true
74
75 dir, _ = filepath.Split(filename)
76 f, err := os.Open(filename)
77 if err != nil {
78 return err
79 }
80 defer f.Close()
81
82 r := bufio.NewScanner(f)
83 for r.Scan() {
Nigel Taoe3643572017-11-03 15:33:23 +110084 line := r.Bytes()
Nigel Taoe57c8d72017-11-03 15:05:19 +110085
Nigel Taoe3643572017-11-03 15:33:23 +110086 if s := line; bytes.HasPrefix(s, prefix) {
Nigel Taoe57c8d72017-11-03 15:05:19 +110087 s = s[len(prefix):]
88 if bytes.HasSuffix(s, suffix) {
89 s = s[:len(s)-len(suffix)]
90 if err := do(w, dir, string(s), depth); err == nil {
91 continue
92 } else if os.IsNotExist(err) {
93 // This is probably an #include of a system header, like
Nigel Tao024dc7f2017-11-30 18:18:40 +110094 // `#include "zlib.h"`, and not of Wuffs code. Fall through
Nigel Taoe57c8d72017-11-03 15:05:19 +110095 // and print the #include line as normal.
96 } else {
97 return err
98 }
99 }
100 }
101
Nigel Taoe3643572017-11-03 15:33:23 +1100102 w.Write(line)
Nigel Taoe57c8d72017-11-03 15:05:19 +1100103 w.WriteByte('\n')
104 }
105 return r.Err()
106}