| #!/bin/awk -f | 
 | # Check a list of symbols against the master definition | 
 | # (official) list.  Arguments: | 
 | # | 
 | # awk -f checksym.awk official-def list-to-check | 
 | # | 
 | # Output is a file in the current directory called 'symbols.new', | 
 | # the value of the awk variable "of" (which can be changed on the | 
 | # command line if required.)  stdout holds error messages.  Error | 
 | # code indicates success or failure. | 
 | # | 
 | # NOTE: this is a pure, old fashioned, awk script.  It will | 
 | # work with any awk | 
 |  | 
 | BEGIN{ | 
 |    err=0 | 
 |    master=""        # master file | 
 |    official[1] = "" # defined symbols from master file | 
 |    symbol[1] = ""   # defined symbols from png.h | 
 |    removed[1] = ""  # removed symbols from png.h | 
 |    lasto = 0        # last ordinal value from png.h | 
 |    mastero = 0      # highest ordinal in master file | 
 |    symbolo = 0      # highest ordinal in png.h | 
 |    missing = "error"# log an error on missing symbols | 
 |    of="symbols.new" # default to a fixed name | 
 | } | 
 |  | 
 | # Read existing definitions from the master file (the first | 
 | # file on the command line.)  This must be a def file and it | 
 | # has definition lines (others are ignored) of the form: | 
 | # | 
 | #   symbol @ordinal | 
 | # | 
 | master == "" { | 
 |    master = FILENAME | 
 | } | 
 | FILENAME==master && NF==2 && $2~/^@/ && $1!~/^;/ { | 
 |    o=0+substr($2,2) | 
 |    if (o > 0) { | 
 |       if (official[o] == "") { | 
 |          official[o] = $1 | 
 |          if (o > mastero) mastero = o | 
 |          next | 
 |       } else | 
 |          print master ": duplicated symbol:", official[o] ":", $0 | 
 |    } else | 
 |       print master ": bad export line format:", $0 | 
 |    err = 1 | 
 | } | 
 | FILENAME==master && $1==";missing" && NF==2{ | 
 |    # This allows the master file to control how missing symbols | 
 |    # are handled; symbols that aren't in either the master or | 
 |    # the new file.  Valid values are 'ignore', 'warning' and | 
 |    # 'error' | 
 |    missing = $2 | 
 | } | 
 | FILENAME==master { | 
 |    next | 
 | } | 
 |  | 
 | # Read new definitions, these are free form but the lines must | 
 | # just be symbol definitions.  Lines will be commented out for | 
 | # 'removed' symbols, introduced in png.h using PNG_REMOVED rather | 
 | # than PNG_EXPORT.  Use symbols.dfn or pngwin.dfn to generate the | 
 | # input file. | 
 | # | 
 | #  symbol @ordinal   # two fields, exported symbol | 
 | #  ; symbol @ordinal # three fields, removed symbol | 
 | #  ; @ordinal        # two fields, the last ordinal | 
 | NF==2 && $1 == ";" && $2 ~ /^@[1-9][0-9]*$/ { # last ordinal | 
 |    o=0+substr($2,2) | 
 |    if (lasto == 0 || lasto == o) | 
 |       lasto=o | 
 |    else { | 
 |       print "png.h: duplicated last ordinal:", lasto, o | 
 |       err = 1 | 
 |    } | 
 |    next | 
 | } | 
 | NF==3 && $1 == ";" && $3 ~ /^@[1-9][0-9]*$/ { # removed symbol | 
 |    o=0+substr($3,2) | 
 |    if (removed[o] == "" || removed[o] == $2) { | 
 |       removed[o] = $2 | 
 |       if (o > symbolo) symbolo = o | 
 |    } else { | 
 |       print "png.h: duplicated removed symbol", o ": '" removed[o] "' != '" $2 "'" | 
 |       err = 1 | 
 |    } | 
 |    next | 
 | } | 
 | NF==2 && $2 ~ /^@[1-9][0-9]*$/ { # exported symbol | 
 |    o=0+substr($2,2) | 
 |    if (symbol[o] == "" || symbol[o] == $1) { | 
 |       symbol[o] = $1 | 
 |       if (o > symbolo) symbolo = o | 
 |    } else { | 
 |       print "png.h: duplicated symbol", o ": '" symbol[o] "' != '" $1 "'" | 
 |       err = 1 | 
 |    } | 
 | } | 
 | { | 
 |    next # skip all other lines | 
 | } | 
 |  | 
 | # At the end check for symbols marked as both duplicated and removed | 
 | END{ | 
 |    if (symbolo > lasto) { | 
 |       print "highest symbol ordinal in png.h,", symbolo ", exceeds last ordinal from png.h", lasto | 
 |       err = 1 | 
 |    } | 
 |    if (mastero > lasto) { | 
 |       print "highest symbol ordinal in", master ",", mastero ", exceeds last ordinal from png.h", lasto | 
 |       err = 1 | 
 |    } | 
 |    unexported=0 | 
 |    # Add a standard header to symbols.new: | 
 |    print ";Version INSERT-VERSION-HERE" >of | 
 |    print ";--------------------------------------------------------------" >of | 
 |    print "; LIBPNG symbol list as a Win32 DEF file" >of | 
 |    print "; Contains all the symbols that can be exported from libpng" >of | 
 |    print ";--------------------------------------------------------------" >of | 
 |    print "LIBRARY" >of | 
 |    print "" >of | 
 |    print "EXPORTS" >of | 
 |  | 
 |    for (o=1; o<=lasto; ++o) { | 
 |       if (symbol[o] == "" && removed[o] == "") { | 
 |          if (unexported == 0) unexported = o | 
 |          if (official[o] == "") { | 
 |             # missing in export list too, so ok | 
 |             if (o < lasto) continue | 
 |          } | 
 |       } | 
 |       if (unexported != 0) { | 
 |          # Symbols in the .def but not in the new file are errors, but | 
 |          # the 'unexported' symbols aren't in either.  By default this | 
 |          # is an error too (see the setting of 'missing' at the start), | 
 |          # but this can be reset on the command line or by stuff in the | 
 |          # file - see the comments above. | 
 |          if (missing != "ignore") { | 
 |             if (o-1 > unexported) | 
 |                print "png.h:", missing ": missing symbols:", unexported "-" o-1 | 
 |             else | 
 |                print "png.h:", missing ": missing symbol:", unexported | 
 |             if (missing != "warning") | 
 |                err = 1 | 
 |          } | 
 |          unexported = 0 | 
 |       } | 
 |       if (symbol[o] != "" && removed[o] != "") { | 
 |          print "png.h: symbol", o, "both exported as '" symbol[o] "' and removed as '" removed[o] "'" | 
 |          err = 1 | 
 |       } else if (symbol[o] != official[o]) { | 
 |          # either the symbol is missing somewhere or it changed | 
 |          err = 1 | 
 |          if (symbol[o] == "") | 
 |             print "png.h: symbol", o, "is exported as '" official[o] "' in", master | 
 |          else if (official[o] == "") | 
 |             print "png.h: exported symbol", o, "'" symbol[o] "' not present in", master | 
 |          else | 
 |             print "png.h: exported symbol", o, "'" symbol[o] "' exists as '" official[o] "' in", master | 
 |       } | 
 |  | 
 |       # Finally generate symbols.new | 
 |       if (symbol[o] != "") | 
 |          print " " symbol[o], "@" o > of | 
 |    } | 
 |  | 
 |    if (err != 0) { | 
 |       print "*** A new list is in", of, "***" | 
 |       exit 1 | 
 |    } | 
 | } |