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