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