Imported Upstream version 1.6.39
[platform/upstream/libpng.git] / scripts / dfn.awk
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(/\r$/, "", line)
176
177    if (sort) {
178       if (split(line, parts) < sort) {
179          print "line", lineno ": missing sort field:", line
180          err=1
181       } else
182          array[parts[sort]] = line
183    }
184
185    else
186       print line >out
187    next
188 }
189
190 /PNG_DFN/{
191    print "line", NR, "incorrectly formatted PNG_DFN line:"
192    print $0
193    err = 1
194 }
195
196 END{
197    if (out_count > 0 || err > 0)
198         exit err
199
200    print "no definition lines found"
201    exit 1
202 }