xref: /aosp_15_r20/external/libpng/scripts/dfn.awk (revision a67afe4df73cf47866eedc69947994b8ff839aba)
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
16BEGIN{
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:
25NR==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
197END{
198   if (out_count > 0 || err > 0)
199      exit err
200
201   print "no definition lines found"
202   exit 1
203}
204