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