Home | History | Annotate | Download | only in scripts
      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(/
$/, "", 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 }
    205