1 | #!/bin/awk -f
|
---|
2 |
|
---|
3 | # scripts/dfn.awk - process a .dfn file
|
---|
4 | #
|
---|
5 | # Copyright (c) 2013-2014 Glenn Randers-Pehrson
|
---|
6 | #
|
---|
7 | # This code is released under the libpng license.
|
---|
8 | # For conditions of distribution and use, see the disclaimer
|
---|
9 | # and license in png.h
|
---|
10 |
|
---|
11 | # The output of this script is written to the file given by
|
---|
12 | # the variable 'out', which should be set on the command line.
|
---|
13 | # Error messages are printed to stdout and if any are printed
|
---|
14 | # the script will exit with error code 1.
|
---|
15 |
|
---|
16 | BEGIN{
|
---|
17 | out="/dev/null" # as a flag
|
---|
18 | out_count=0 # count of output lines
|
---|
19 | err=0 # set if an error occurred
|
---|
20 | sort=0 # sort the output
|
---|
21 | array[""]=""
|
---|
22 | }
|
---|
23 |
|
---|
24 | # The output file must be specified before any input:
|
---|
25 | NR==1 && out == "/dev/null" {
|
---|
26 | print "out=output.file must be given on the command line"
|
---|
27 | # but continue without setting the error code; this allows the
|
---|
28 | # script to be checked easily
|
---|
29 | }
|
---|
30 |
|
---|
31 | # Output can be sorted; two lines are recognized
|
---|
32 | $1 == "PNG_DFN_START_SORT"{
|
---|
33 | sort=0+$2
|
---|
34 | next
|
---|
35 | }
|
---|
36 |
|
---|
37 | $1 ~ /^PNG_DFN_END_SORT/{
|
---|
38 | # Do a very simple, slow, sort; notice that blank lines won't be
|
---|
39 | # output by this
|
---|
40 | for (entry in array) {
|
---|
41 | while (array[entry] != "") {
|
---|
42 | key = entry
|
---|
43 | value = array[key]
|
---|
44 | array[key] = ""
|
---|
45 |
|
---|
46 | for (alt in array) {
|
---|
47 | if (array[alt] != "" && alt < key) {
|
---|
48 | array[key] = value
|
---|
49 | value = array[alt]
|
---|
50 | key = alt
|
---|
51 | array[alt] = ""
|
---|
52 | }
|
---|
53 | }
|
---|
54 |
|
---|
55 | print value >out
|
---|
56 | }
|
---|
57 | }
|
---|
58 | sort=0
|
---|
59 | next
|
---|
60 | }
|
---|
61 |
|
---|
62 | /^[^"]*PNG_DFN *".*"[^"]*$/{
|
---|
63 | # A definition line, apparently correctly formatted; extract the
|
---|
64 | # definition then replace any doubled "" that remain with a single
|
---|
65 | # double quote. Notice that the original doubled double quotes
|
---|
66 | # may have been split by tokenization
|
---|
67 | #
|
---|
68 | # Sometimes GCC splits the PNG_DFN lines; we know this has happened
|
---|
69 | # if the quotes aren't closed and must read another line. In this
|
---|
70 | # case it is essential to reject lines that start with '#' because those
|
---|
71 | # are introduced #line directives.
|
---|
72 | orig=$0
|
---|
73 | line=$0
|
---|
74 | lineno=FNR
|
---|
75 | if (lineno == "") lineno=NR
|
---|
76 |
|
---|
77 | if (sub(/^[^"]*PNG_DFN *"/,"",line) != 1) {
|
---|
78 | print "line", lineno ": processing failed:"
|
---|
79 | print orig
|
---|
80 | err=1
|
---|
81 | next
|
---|
82 | } else {
|
---|
83 | ++out_count
|
---|
84 | }
|
---|
85 |
|
---|
86 | # Now examine quotes within the value:
|
---|
87 | #
|
---|
88 | # @" - delete this and any following spaces
|
---|
89 | # "@ - delete this and any preceding spaces
|
---|
90 | # @' - replace this by a double quote
|
---|
91 | #
|
---|
92 | # This allows macro substitution by the C compiler thus:
|
---|
93 | #
|
---|
94 | # #define first_name John
|
---|
95 | # #define last_name Smith
|
---|
96 | #
|
---|
97 | # PNG_DFN"#define name @'@" first_name "@ @" last_name "@@'"
|
---|
98 | #
|
---|
99 | # Might get C preprocessed to:
|
---|
100 | #
|
---|
101 | # PNG_DFN "#define foo @'@" John "@ @" Smith "@@'"
|
---|
102 | #
|
---|
103 | # Which this script reduces to:
|
---|
104 | #
|
---|
105 | # #define name "John Smith"
|
---|
106 | #
|
---|
107 | while (1) {
|
---|
108 | # While there is an @" remove it and the next "@
|
---|
109 | if (line ~ /@"/) {
|
---|
110 | if (line ~ /@".*"@/) {
|
---|
111 | # Do this special case first to avoid swallowing extra spaces
|
---|
112 | # before or after the @ stuff:
|
---|
113 | if (!sub(/@" *"@/, "", line)) {
|
---|
114 | # Ok, do it in pieces - there has to be a non-space between the
|
---|
115 | # two. NOTE: really weird things happen if a leading @" is
|
---|
116 | # lost - the code will error out below (I believe).
|
---|
117 | if (!sub(/@" */, "", line) || !sub(/ *"@/, "", line)) {
|
---|
118 | print "line", lineno, ": internal error:", orig
|
---|
119 | exit 1
|
---|
120 | }
|
---|
121 | }
|
---|
122 | }
|
---|
123 |
|
---|
124 | # There is no matching "@. Assume a split line
|
---|
125 | else while (1) {
|
---|
126 | if (getline nextline) {
|
---|
127 | # If the line starts with '#' it is a preprocessor line directive
|
---|
128 | # from cc -E; skip it:
|
---|
129 | if (nextline !~ /^#/) {
|
---|
130 | line = line " " nextline
|
---|
131 | break
|
---|
132 | }
|
---|
133 | } else {
|
---|
134 | # This is end-of-input - probably a missing "@ on the first line:
|
---|
135 | print "line", lineno ": unbalanced @\" ... \"@ pair"
|
---|
136 | err=1
|
---|
137 | next
|
---|
138 | }
|
---|
139 | }
|
---|
140 |
|
---|
141 | # Keep going until all the @" have gone
|
---|
142 | continue
|
---|
143 | }
|
---|
144 |
|
---|
145 | # Attempt to remove a trailing " (not preceded by '@') - if this can
|
---|
146 | # be done, stop now; if not assume a split line again
|
---|
147 | if (sub(/"[^"]*$/, "", line))
|
---|
148 | break
|
---|
149 |
|
---|
150 | # Read another line
|
---|
151 | while (1) {
|
---|
152 | if (getline nextline) {
|
---|
153 | if (nextline !~ /^#/) {
|
---|
154 | line = line " " nextline
|
---|
155 | # Go back to stripping @" "@ pairs
|
---|
156 | break
|
---|
157 | }
|
---|
158 | } else {
|
---|
159 | print "line", lineno ": unterminated PNG_DFN string"
|
---|
160 | err=1
|
---|
161 | next
|
---|
162 | }
|
---|
163 | }
|
---|
164 | }
|
---|
165 |
|
---|
166 | # Put any needed double quotes in (at the end, because these would otherwise
|
---|
167 | # interfere with the processing above.)
|
---|
168 | gsub(/@'/,"\"", line)
|
---|
169 |
|
---|
170 | # Remove any trailing spaces (not really required, but for
|
---|
171 | # editorial consistency
|
---|
172 | sub(/ *$/, "", line)
|
---|
173 |
|
---|
174 | # Remove trailing CR
|
---|
175 | sub(/
|
---|
176 | $/, "", line)
|
---|
177 |
|
---|
178 | if (sort) {
|
---|
179 | if (split(line, parts) < sort) {
|
---|
180 | print "line", lineno ": missing sort field:", line
|
---|
181 | err=1
|
---|
182 | } else
|
---|
183 | array[parts[sort]] = line
|
---|
184 | }
|
---|
185 |
|
---|
186 | else
|
---|
187 | print line >out
|
---|
188 | next
|
---|
189 | }
|
---|
190 |
|
---|
191 | /PNG_DFN/{
|
---|
192 | print "line", NR, "incorrectly formatted PNG_DFN line:"
|
---|
193 | print $0
|
---|
194 | err = 1
|
---|
195 | }
|
---|
196 |
|
---|
197 | END{
|
---|
198 | if (out_count > 0 || err > 0)
|
---|
199 | exit err
|
---|
200 |
|
---|
201 | print "no definition lines found"
|
---|
202 | exit 1
|
---|
203 | }
|
---|