Regress because of errors.

Regress because of errors.

#!/usr/bin/awk -f
# tdbout -t publisher,plugin,publisher:info[contract],year,publisher:info[tester],status,publisher:info[back] *.tdb

BEGIN {
  FS="\t"
  pn = 0
    #str = "date +%m-%d-%Y";
    #str | getline date;
    #close str;
}
$3>date
{
  # add a loop to add line only if either status is (wanted or testing) or ending year is gt or eq to contract year
  # increased to 2015 July 1 2015.
  current_year = 2015
  # end_year is the AU year, or the second half of a range, ie 2014 in 2013-2014
  end_year = 0
  incontract = 0
  # test_year is the contract year, or the back year if there is one.
  test_year = ""
  if ($7 == "") {
    test_year = $3
  } else {
    test_year = $7
  }
  if (length($4) > 3) {
    end_year = substr($4,length($4)-3,4)
  }
  #printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", $1,$2,$3,$4,$7,end_year,test_year
  # Is the AU year >= the contract year or the back year. And then decide what to do with the current year.
  if ($6 == "wanted" || $6 == "testing") {
      incontract = 1;
  } else if ((end_year >= test_year) && ((end_year < current_year) || (end_year == current_year && incl_cur == 1))) {
      incontract = 1;
  }

  if (incontract == 1) {
      nn = split($2,na,/\./)
      lp2 = na[nn]
    if (!(($1,lp2,$4) in b)) {
      p[pn] = $1
      n[pn] = lp2
  #    n[pn] = $2
      t[pn] = $3
      if ($7 == "") {
        k[pn] = ".."
      } else {
        k[pn] = $7
      }
      d[pn] = $4
      r[pn] = $5
      pn++
    }
    b[$1,lp2,$4]++
    c[$1,lp2,$4,$6]++
    x[$6]++
    tt++
  }
}

END {
  s[0] = "expected"
  s[1] = "exists"
  s[2] = "manifest"
  s[3] = "wanted"
  s[4] = "testing"
  s[5] = "notReady"
  s[6] = "ready"
  s[7] = "crawling"
  s[8] = "frozen"
  s[9] = "ingNotReady"
  s[10] = "finished"
  s[11] = "down"
  s[12] = "superseded"
  s[13] = "zapped"
  s[14] = "doNotProcess"
  sn = 15

  sc[0] = "expe"
  sc[1] = "exis"
  sc[2] = "mani"
  sc[3] = "want"
  sc[4] = "test"
  sc[5] = "notR"
  sc[6] = "read"
  sc[7] = "craw"
  sc[8] = "froz"
  sc[9] = "ingN"
  sc[10] = "fini"
  sc[11] = "down"
  sc[12] = "supe"
  sc[13] = "zapp"
  sc[14] = "doNP"
  scn = 15

  #print out header
  printf "Publisher\tPlugin\tContr\tBack\tYear\tT\tTotal"
  for (j = 0 ; j < scn ; j++) {
    if (x[s[j]] > 0) {
    printf "\t%s", sc[j]
    }
  }
  printf "\n"

  #print out publisher, plugin, contract year, back, year, tester, total aus
  for (i = 0 ; i < pn ; i++) {
    printf "%s\t%s\t%s\t%s\t%s\t%s\t%d", p[i], n[i], t[i], k[i], d[i], r[i], b[p[i],n[i],d[i]]
    for (j = 0 ; j < sn ; j++) {
      if (x[s[j]] > 0){
      if (c[p[i],n[i],d[i],s[j]] == 0) {
        printf "\t.."
      } else {
        printf "\t%d", c[p[i],n[i],d[i],s[j]]
      }
    }
    }
    printf "\n"
  }
    #print out bottom line sums
    printf "Publisher\tPlugin\tContr\tBack\tYear\tT\t%d", tt
    for (j = 0 ; j < sn ; j++) {
      if (x[s[j]] > 0) {
        printf "\t%d", x[s[j]]
      }
    }

  printf "\n"
  #printf "%s", date
  #printf "\n"
}

#!/usr/bin/awk -f
# tdbout -t publisher,plugin,publisher:info[contract],year,publisher:info[tester],status,publisher:info[back] *.tdb

BEGIN {
  FS="\t"
  pn = 0
    str = "date +%m-%d-%Y";
    str | getline date;
    #close str;
}
$3>date
{
  # add a loop to add line only if either status is (wanted or testing) or ending year is gt or eq to contract year
  # increased to 2015 July 1 2015.
  current_year = 2015
  # end_year is the AU year, or the second half of a range, ie 2014 in 2013-2014
  end_year = 0
  incontract = 0
  # test_year is the contract year, or the back year if there is one.
  test_year = ""
  if ($7 == "") {
    test_year = $3
  } else {
    test_year = $7
  }
  if (length($4) > 3) {
    end_year = substr($4,length($4)-3,4)
  }
  #printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", $1,$2,$3,$4,$7,end_year,test_year
  # Is the AU year >= the contract year or the back year. And then decide what to do with the current year.
  if ($6 == "wanted" || $6 == "testing") {
      incontract = 1;
  } else if ((end_year >= test_year) && ((end_year < current_year) || (end_year == current_year && incl_cur == 1))) {
      incontract = 1;
  }

  if (incontract == 1) {
      nn = split($2,na,/\./)
      lp2 = na[nn]
    if (!(($1,lp2,$4) in b)) {
      p[pn] = $1
      n[pn] = lp2
  #    n[pn] = $2
      t[pn] = $3
      if ($7 == "") {
        k[pn] = ".."
      } else {
        k[pn] = $7
      }
      d[pn] = $4
      r[pn] = $5
      pn++
    }
    b[$1,lp2,$4]++
    c[$1,lp2,$4,$6]++
    x[$6]++
    tt++
  }
}

END {
  s[0] = "expected"
  s[1] = "exists"
  s[2] = "manifest"
  s[3] = "wanted"
  s[4] = "testing"
  s[5] = "notReady"
  s[6] = "ready"
  s[7] = "crawling"
  s[8] = "frozen"
  s[9] = "ingNotReady"
  s[10] = "finished"
  s[11] = "down"
  s[12] = "superseded"
  s[13] = "zapped"
  s[14] = "doNotProcess"
  sn = 15

  sc[0] = "expe"
  sc[1] = "exis"
  sc[2] = "mani"
  sc[3] = "want"
  sc[4] = "test"
  sc[5] = "notR"
  sc[6] = "read"
  sc[7] = "craw"
  sc[8] = "froz"
  sc[9] = "ingN"
  sc[10] = "fini"
  sc[11] = "down"
  sc[12] = "supe"
  sc[13] = "zapp"
  sc[14] = "doNP"
  scn = 15

  #print out header
  printf "Publisher\tPlugin\tContr\tBack\tYear\tT\tTotal"
  for (j = 0 ; j < scn ; j++) {
    if (x[s[j]] > 0) {
    printf "\t%s", sc[j]
    }
  }
  printf "\n"

  #print out publisher, plugin, contract year, back, year, tester, total aus
  for (i = 0 ; i < pn ; i++) {
    printf "%s\t%s\t%s\t%s\t%s\t%s\t%d", p[i], n[i], t[i], k[i], d[i], r[i], b[p[i],n[i],d[i]]
    for (j = 0 ; j < sn ; j++) {
      if (x[s[j]] > 0){
      if (c[p[i],n[i],d[i],s[j]] == 0) {
        printf "\t.."
      } else {
        printf "\t%d", c[p[i],n[i],d[i],s[j]]
      }
    }
    }
    printf "\n"
  }
    #print out bottom line sums
    printf "Publisher\tPlugin\tContr\tBack\tYear\tT\t%d", tt
    for (j = 0 ; j < sn ; j++) {
      if (x[s[j]] > 0) {
        printf "\t%d", x[s[j]]
      }
    }

  printf "\n"
  printf "%s", date
  printf "\n"
}


Fix comment

Fix comment

# Take TSV and turn it into Procedure Calls PorgreSQL
BEGIN {
 FS = OFS = "\t";
 # $1 Country Code
 # $2 Postal Code
 # $3 Place name, City, Township
 # $4 State abbrivation
 # $5 State full
 # $6 County
 # $7 Lat
 # $8 Long
 # $9 Accuracy
}
{
    sub(/\B/,"NULL",$9); # replace empty Accracy with NULL
    print "SELECT GetPostal('" $1 "','" $2 "','" $3  "','" $4 "','" $5 "','" $6 "'," $7 "," $8 "," $9 ") FROM DUAL;"
}
END {
}

# Take CSV and turn it into Procedure Calls PorgreSQL
# Copyright (c) 2014 Stephen A Jazdzewski
BEGIN {
 FS = OFS = "\t";
 # $1 Country Code
 # $2 Postal Code
 # $3 Place name, City, Township
 # $4 State abbrivation
 # $5 State full
 # $6 County
 # $7 Lat
 # $8 Long
 # $9 Accuracy
}
{
    sub(/\B/,"NULL",$9); # replace empty Accracy with NULL
    print "SELECT GetPostal('" $1 "','" $2 "','" $3  "','" $4 "','" $5 "','" $6 "'," $7 "," $8 "," $9 ") FROM DUAL;"
}
END {
}


add html tags

add html tags


correcting use getReply

correcting use getReply

@load "redis"
BEGIN{
  c=connectRedis()
  select(c,12)
  testListItem(c, 0)
  testPurchaseItem(c)
  testBenchmarkUpdateToken(c)
}

function testListItem(c, nested) {
  if (!nested){
     print "\n----- testListItem -----"
  }
  print "We need to set up just enough state so that a user can list an item"
  seller = "userX"
  item = "itemX"
  sadd(c,"inventory:"seller, item)
  delete(AR)
  smembers(c,"inventory:"seller,AR)
  print "The user's inventory has:"
  for(i in AR) {
    print "  "AR[i]
  }
  print
  print "Listing the item..."
  l = listItem(conn, item, seller, 10)
  print "Listing the item succeeded? "l
  delete(AR)
  zrangeWithScores(c,"market:",AR,0, -1)
  print "The market contains:"
  for(i=1;i<=length(AR);i+=2){
     print "  "AR[i]", "AR[i+1]
  }
}

function testPurchaseItem(c) {
   print "\n----- testPurchaseItem -----"
   testListItem(c, 1)
   print "We need to set up just enough state so a user can buy an item"
   hset(c,"users:userY", "funds", "125")
   delete(AR)
   hgetall(c,"users:userY",AR)
   print "The user has some money:"
   for(i=1;i<=length(AR);i+=2){
     print "  "AR[i]": "AR[i+1]
   }
   print
   print "Let's purchase an item"
   p = purchaseItem(c, "userY", "itemX", "userX", 10)
   print "Purchasing an item succeeded? "p
   delete(AR)
   hgetall(c,"users:userY",AR)
   print "Their money is now:"
   for(i=1;i<=length(AR);i+=2){
     print "  "AR[i]": "AR[i+1]
   }
   buyer = "userY"
   delete(AR)
   smembers(c,"inventory:"buyer,AR)
   print "Their inventory is now:"
   for(member in AR) {
     print "  "AR[member]
   }
}

function testBenchmarkUpdateToken(c) {
   print "\n----- testBenchmarkUpdate -----"
   benchmarkUpdateToken(c, 5)
}

function listItem(c, itemId, sellerId, price) {
   inventory = "inventory:"sellerId
   item = itemId"."sellerId
   now=systime()*1000
   end=now+5000
   while (now < end) {
     watch(c,inventory)
     if(!sismember(c,inventory, itemId)){
       unwatch(c)
       return 0
     }
     multi(c)
     zadd(c,"market:", price, item)
     srem(c,inventory, itemId)
     if(exec(c,R)==0) {
       now=systime()*1000
       continue
     }
     return 1
   }
   return 0
}

function purchaseItem(c, buyerId, itemId, sellerId, lprice) {
   buyer = "users:"buyerId
   seller = "users:"sellerId
   item = itemId"."sellerId
   inventory = "inventory:"buyerId
   end=(systime()*1000)+10000
   while ((systime()*1000) < end){
     watch(c,"market:"buyer)
     price = zscore(c,"market:", item)
     funds = hget(c,buyer, "funds")
     if (price != lprice || price > funds){
       unwatch()
       return 0
     }
     multi(c)
     hincrby(c, seller, "funds", price)
     hincrby(c, buyer, "funds", -price)
     sadd(c, inventory, itemId)
     zrem(c, "market:", item)
     if(exec(c,R)==0) {
        continue
     }
     return 1
   }
   return 0
}

function benchmarkUpdateToken(c, duration) {
  for(i=1;i<=2;i++) {
     if(i==1){
        method="updateToken"
     }
     else {
        method="updateTokenPipeline"
	p=pipeline(c)
     }
     count = 0
     start=systime()*1000
     end = start + (duration * 1000)
     while((systime()*1000) < end){
        count++;
	if(i==1){
          updateToken(c, "token", "user", "item")
        }
        else {
          updateTokenPipeline(c, "token", "user", "item", p)
        }
     }
     delta=(systime()*1000) - start
     print method" "count" "(delta / 1000)" "(count / (delta / 1000))
  }
}

function updateToken(c, token, user, item) {
   timestamp=systime()
   hset(c,"login:", token, user)
   zadd(c,"recent:", timestamp, token)
   if (item) {
     zadd(c,"viewed:"token, timestamp, item)
     zremrangebyrank(c, "viewed:"token, 0, -26)
     zincrby(c, "viewed:", -1, item)
   }
}

function updateTokenPipeline(c, token, user, item, p) {
    timestamp=systime()
    hset(p,"login:", token, user)
    zadd(p,"recent:", timestamp, token)
    if (item) {
      zadd(p,"viewed:"token, timestamp, item)
      zremrangebyrank(p,"viewed:"token, 0, -26)
      zincrby(p,"viewed:", -1, item)
    }
    for(ERRNO="" ; ERRNO="" ; var=getReply(p,REPLY)) ;
    ERRNO==""
}

@load "redis"
BEGIN{
  c=connectRedis()
  select(c,12)
  testListItem(c, 0)
  testPurchaseItem(c)
  testBenchmarkUpdateToken(c)
}

function testListItem(c, nested) {
  if (!nested){
     print "\n----- testListItem -----"
  }
  print "We need to set up just enough state so that a user can list an item"
  seller = "userX"
  item = "itemX"
  sadd(c,"inventory:"seller, item)
  delete(AR)
  smembers(c,"inventory:"seller,AR)
  print "The user's inventory has:"
  for(i in AR) {
    print "  "AR[i]
  }
  print
  print "Listing the item..."
  l = listItem(conn, item, seller, 10)
  print "Listing the item succeeded? "l
  delete(AR)
  zrangeWithScores(c,"market:",AR,0, -1)
  print "The market contains:"
  for(i=1;i<=length(AR);i+=2){
     print "  "AR[i]", "AR[i+1]
  }
}

function testPurchaseItem(c) {
   print "\n----- testPurchaseItem -----"
   testListItem(c, 1)
   print "We need to set up just enough state so a user can buy an item"
   hset(c,"users:userY", "funds", "125")
   delete(AR)
   hgetall(c,"users:userY",AR)
   print "The user has some money:"
   for(i=1;i<=length(AR);i+=2){
     print "  "AR[i]": "AR[i+1]
   }
   print
   print "Let's purchase an item"
   p = purchaseItem(c, "userY", "itemX", "userX", 10)
   print "Purchasing an item succeeded? "p
   delete(AR)
   hgetall(c,"users:userY",AR)
   print "Their money is now:"
   for(i=1;i<=length(AR);i+=2){
     print "  "AR[i]": "AR[i+1]
   }
   buyer = "userY"
   delete(AR)
   smembers(c,"inventory:"buyer,AR)
   print "Their inventory is now:"
   for(member in AR) {
     print "  "AR[member]
   }
}

function testBenchmarkUpdateToken(c) {
   print "\n----- testBenchmarkUpdate -----"
   benchmarkUpdateToken(c, 5)
}

function listItem(c, itemId, sellerId, price) {
   inventory = "inventory:"sellerId
   item = itemId"."sellerId
   now=systime()*1000
   end=now+5000
   while (now < end) {
     watch(c,inventory)
     if(!sismember(c,inventory, itemId)){
       unwatch(c)
       return 0
     }
     multi(c)
     zadd(c,"market:", price, item)
     srem(c,inventory, itemId)
     if(exec(c,R)==0) {
       now=systime()*1000
       continue
     }
     return 1
   }
   return 0
}

function purchaseItem(c, buyerId, itemId, sellerId, lprice) {
   buyer = "users:"buyerId
   seller = "users:"sellerId
   item = itemId"."sellerId
   inventory = "inventory:"buyerId
   end=(systime()*1000)+10000
   while ((systime()*1000) < end){
     watch(c,"market:"buyer)
     price = zscore(c,"market:", item)
     funds = hget(c,buyer, "funds")
     if (price != lprice || price > funds){
       unwatch()
       return 0
     }
     multi(c)
     hincrby(c, seller, "funds", price)
     hincrby(c, buyer, "funds", -price)
     sadd(c, inventory, itemId)
     zrem(c, "market:", item)
     if(exec(c,R)==0) {
        continue
     }
     return 1
   }
   return 0
}

function benchmarkUpdateToken(c, duration) {
  for(i=1;i<=2;i++) {
     if(i==1){
        method="updateToken"
     }
     else {
        method="updateTokenPipeline"
	p=pipeline(c)
     }
     count = 0
     start=systime()*1000
     end = start + (duration * 1000)
     while((systime()*1000) < end){
        count++;
	if(i==1){
          updateToken(c, "token", "user", "item")
        }
        else {
          updateTokenPipeline(c, "token", "user", "item", p)
        }
     }
     delta=(systime()*1000) - start
     print method" "count" "(delta / 1000)" "(count / (delta / 1000))
  }
}

function updateToken(c, token, user, item) {
   timestamp=systime()
   hset(c,"login:", token, user)
   zadd(c,"recent:", timestamp, token)
   if (item) {
     zadd(c,"viewed:"token, timestamp, item)
     zremrangebyrank(c, "viewed:"token, 0, -26)
     zincrby(c, "viewed:", -1, item)
   }
}

function updateTokenPipeline(c, token, user, item, p) {
    timestamp=systime()
    hset(p,"login:", token, user)
    zadd(p,"recent:", timestamp, token)
    if (item) {
      zadd(p,"viewed:"token, timestamp, item)
      zremrangebyrank(p,"viewed:"token, 0, -26)
      zincrby(p,"viewed:", -1, item)
    }
    while((getReply(p,REPLY))!=-1 && ERRNO=="")
       { }
}


[1] Fixed day one bug in peruse awk script. TESTING

# Copyright 2021 Digital Aggregates Corporation, Colorado, USA
# Licensed under the terms in LICENSE.txt
# Chip Overclock <coverclock@diag.com>
# https://github.com/coverclock/com-diag-hazer
BEGIN   { inp="INP [  0]"; out="OUT [  0]"; arm=1; }
/^INP / { inp=substr($0,0,79); arm=1; next; }
/^OUT / { out=substr($0,0,79); arm=1; next; }
        { if (arm!=0) { print inp; print out; arm=0; } print $0; next; }
END     { if (arm!=0) { print inp; print out; arm=0; } }

# Copyright 2020 Digital Aggregates Corporation, Colorado, USA
# Licensed under the terms in LICENSE.txt
# Chip Overclock <coverclock@diag.com>
# https://github.com/coverclock/com-diag-hazer
begin   { inp="INP [   ]"; out="OUT [   ]"; arm=1; }
/^INP / { inp=substr($0,0,79); arm=1; next; }
/^OUT / { out=substr($0,0,79); arm=1; next; }
        { if (arm!=0) { print inp; print out; arm=0; } print $0; next; }
end     { if (arm!=0) { print inp; print out; arm=0; } }


Simplify ft handling in snip

Simplify ft handling in snip

BEGIN {
  ft = ENVIRON["FT"]

  # global
  FIXED["--"]   = "-------------------------------------------------"
  FIXED["#--"]  = "#-------------------------------------------------"
  FIXED["isod"] = strftime("%F")
  FIXED["ts"]   = strftime("%s")
  FIXED["cr"]   = "⏎"

  # javascript
  FIXED["javascript:fn"]       = "function"
  FIXED["javascript:function"] = "function (|) {}"
  FIXED["javascript:fori"]     = "for (let i = 0; i < |; i + = 1) {"
  FIXED["javascript:fe"]       = "forEach"
  FIXED["javascript:)"]        = ") => "
  PREFIX["javascript:json"]       = "JSON.stringify"
  PREFIX["javascript:require"]    = "require(\"|\")"
  PREFIX["javascript:console"]    = "console."
  PREFIX["javascript:settimeout"] = "setTimeout"

  # r
  FIXED["r:fn"] = "function"
  FIXED["r:|"]  = "%>%"
  FIXED["r:>"]  = "%>%"

  # go
  FIXED["go://--"]    = "//-------------------------------------------------"
  FIXED["go:fn"]      = "func |() {\n}"
  FIXED["go:fori"]    = "for i := 0; i < |; i++ {}"
  FIXED["go:forr"]    = "for i, _ := range | {}"
  FIXED["go:handler"] = "func(w http.ResponseWriter, r *http.Request)"
  PREFIX["go:print"] = "fmt.Printf(\"%v\\n\", |)"
}

#-------------------------------------------------

# blank, skip
NF == 0 {
  print
  next
}

# exact matches
{
  result = FIXED[$0]
  if (result) {
    print result
    next
  }
}

# exact matches, w/ ft
ft {
  result = FIXED[ft ":" $0]
  if (result) {
    print result
    next
  }
}

# prefix matches, w/ ft
ft {
  for (k in PREFIX) {
    if (index(k, ft ":" $0) == 1) {
      print PREFIX[k]
      next
    }
  }
}

# print everything else as-is
{
  print
}

BEGIN {
  ft = ENVIRON["FT"]

  # global
  FIXED["--"]   = "-------------------------------------------------"
  FIXED["#--"]  = "#-------------------------------------------------"
  FIXED["isod"] = strftime("%F")
  FIXED["ts"]   = strftime("%s")
  FIXED["cr"]   = "⏎"

  # javascript
  FIXED["javascript:fn"]       = "function"
  FIXED["javascript:function"] = "function (|) {}"
  FIXED["javascript:fori"]     = "for (let i = 0; i < |; i + = 1) {"
  FIXED["javascript:fe"]       = "forEach"
  FIXED["javascript:)"]        = ") => "
  PREFIX["javascript:json"]       = "JSON.stringify"
  PREFIX["javascript:require"]    = "require(\"|\")"
  PREFIX["javascript:console"]    = "console."
  PREFIX["javascript:settimeout"] = "setTimeout"

  # r
  FIXED["r:fn"] = "function"
  FIXED["r:|"]  = "%>%"
  FIXED["r:>"]  = "%>%"

  # go
  FIXED["go://--"]    = "//-------------------------------------------------"
  FIXED["go:fn"]      = "func |() {\n}"
  FIXED["go:fori"]    = "for i := 0; i < |; i++ {}"
  FIXED["go:forr"]    = "for i, _ := range | {}"
  FIXED["go:handler"] = "func(w http.ResponseWriter, r *http.Request)"
  PREFIX["go:print"] = "fmt.Printf(\"%v\\n\", |)"
}

#-------------------------------------------------

# blank, skip
NF == 0 {
  print
  next
}

# exact matches
{
  result = FIXED[$0]
  if (result) {
    print result
    next
  }
}

# no ft, skip
ft == "" {
  print
  next
}

# exact matches, w/ ft
{
  result = FIXED[ft ":" $0]
  if (result) {
    print result
    next
  }
}

# prefix matches, w/ ft
{
  for (k in PREFIX) {
    if (index(k, ft ":" $0) == 1) {
      print PREFIX[k]
      next
    }
  }
}

# print everything else as-is
{
  print
}


pack (unused) structures like pcidevs is

#! /usr/bin/awk -f
#	$OpenBSD: devlist2h.awk,v 1.4 2001/01/27 21:15:27 deraadt Exp $
#	$NetBSD: devlist2h.awk,v 1.1 1999/10/15 06:07:22 haya Exp $
#
# Copyright (c) 1995, 1996 Christopher G. Demetriou
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#      This product includes software developed by Christopher G. Demetriou.
# 4. The name of the author may not be used to endorse or promote products
#    derived from this software without specific prior written permission
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
BEGIN {
	nproducts = nvendors = 0
	dfile="cardbusdevs_data.h"
	hfile="cardbusdevs.h"
}
NR == 1 {
	VERSION = $0
	gsub("\\$", "", VERSION)

	printf("/*\t\$OpenBSD\$\t*/\n\n") > dfile
	printf("/*\n") > dfile
	printf(" * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.\n") \
	    > dfile
	printf(" *\n") > dfile
	printf(" * generated from:\n") > dfile
	printf(" *\t%s\n", VERSION) > dfile
	printf(" */\n") > dfile

	printf("/*\t\$OpenBSD\$\t*/\n\n") > hfile
	printf("/*\n") > hfile
	printf(" * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.\n") \
	    > hfile
	printf(" *\n") > hfile
	printf(" * generated from:\n") > hfile
	printf(" *\t%s\n", VERSION) > hfile
	printf(" */\n") > hfile

	next
}
$1 == "vendor" {
	nvendors++

	vendorindex[$2] = nvendors;		# record index for this name, for later.
	vendors[nvendors, 1] = $2;		# name
	vendors[nvendors, 2] = $3;		# id
	printf("#define\tCARDBUS_VENDOR_%s\t%s\t", vendors[nvendors, 1],
	    vendors[nvendors, 2]) > hfile

	i = 3; f = 4;

	# comments
	ocomment = oparen = 0
	if (f <= NF) {
		printf("\t/* ") > hfile
		ocomment = 1;
	}
	while (f <= NF) {
		if ($f == "#") {
			printf("(") > hfile
			oparen = 1
			f++
			continue
		}
		if (oparen) {
			printf("%s", $f) > hfile
			if (f < NF)
				printf(" ") > hfile
			f++
			continue
		}
		vendors[nvendors, i] = $f
		printf("%s", vendors[nvendors, i]) > hfile
		if (f < NF)
			printf(" ") > hfile
		i++; f++;
	}
	if (oparen)
		printf(")") > hfile
	if (ocomment)
		printf(" */") > hfile
	printf("\n") > hfile

	next
}
$1 == "product" {
	nproducts++

	products[nproducts, 1] = $2;		# vendor name
	products[nproducts, 2] = $3;		# product id
	products[nproducts, 3] = $4;		# id
	printf("#define\tCARDBUS_PRODUCT_%s_%s\t%s\t", products[nproducts, 1],
	    products[nproducts, 2], products[nproducts, 3]) > hfile

	i=4; f = 5;

	# comments
	ocomment = oparen = 0
	if (f <= NF) {
		printf("\t/* ") > hfile
		ocomment = 1;
	}
	while (f <= NF) {
		if ($f == "#") {
			printf("(") > hfile
			oparen = 1
			f++
			continue
		}
		if (oparen) {
			printf("%s", $f) > hfile
			if (f < NF)
				printf(" ") > hfile
			f++
			continue
		}
		products[nproducts, i] = $f
		printf("%s", products[nproducts, i]) > hfile
		if (f < NF)
			printf(" ") > hfile
		i++; f++;
	}
	if (oparen)
		printf(")") > hfile
	if (ocomment)
		printf(" */") > hfile
	printf("\n") > hfile

	next
}
{
	if ($0 == "")
		blanklines++
	print $0 > hfile
	if (blanklines < 2)
		print $0 > dfile
}
END {
	# print out the match tables

	printf("\n") > dfile

	printf("struct cardbus_known_product cardbus_known_product[] = {\n") \
	    > dfile
	for (i = 1; i <= nproducts; i++) {
		printf("\t{\n") > dfile
		printf("\t    CARDBUS_VENDOR_%s, CARDBUS_PRODUCT_%s_%s,\n",
		    products[i, 1], products[i, 1], products[i, 2]) \
		    > dfile

		printf("\t    \"") > dfile
		j = 4;
		needspace = 0;
		while (products[i, j] != "") {
			if (needspace)
				printf(" ") > dfile
			printf("%s", products[i, j]) > dfile
			needspace = 1
			j++
		}
		printf("\",\n") > dfile
		printf("\t},\n") > dfile
	}
	printf("\t{ 0, 0, NULL }\n") > dfile
	printf("};\n\n") > dfile

	printf("struct cardbus_known_vendor cardbus_known_vendors[] = {\n") > dfile
	for (i = 1; i <= nvendors; i++) {
		printf("\t{\n") > dfile
		printf("\t    CARDBUS_VENDOR_%s, 0,\n", vendors[i, 1]) \
		    > dfile
		printf("\t    \"") > dfile
		j = 3;
		needspace = 0;
		while (vendors[i, j] != "") {
			if (needspace)
				printf(" ") > dfile
			printf("%s", vendors[i, j]) > dfile
			needspace = 1
			j++
		}
		printf("\",\n") > dfile
		printf("\t},\n") > dfile
	}
	printf("\t{ 0, 0, NULL }\n") > dfile
	printf("};\n") > dfile
}

#! /usr/bin/awk -f
#	$OpenBSD: devlist2h.awk,v 1.3 2000/05/15 06:31:37 niklas Exp $
#	$NetBSD: devlist2h.awk,v 1.1 1999/10/15 06:07:22 haya Exp $
#
# Copyright (c) 1995, 1996 Christopher G. Demetriou
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#      This product includes software developed by Christopher G. Demetriou.
# 4. The name of the author may not be used to endorse or promote products
#    derived from this software without specific prior written permission
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
BEGIN {
	nproducts = nvendors = 0
	dfile="cardbusdevs_data.h"
	hfile="cardbusdevs.h"
}
NR == 1 {
	VERSION = $0
	gsub("\\$", "", VERSION)

	printf("/*\t\$OpenBSD\$\t*/\n\n") > dfile
	printf("/*\n") > dfile
	printf(" * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.\n") \
	    > dfile
	printf(" *\n") > dfile
	printf(" * generated from:\n") > dfile
	printf(" *\t%s\n", VERSION) > dfile
	printf(" */\n") > dfile

	printf("/*\t\$OpenBSD\$\t*/\n\n") > hfile
	printf("/*\n") > hfile
	printf(" * THIS FILE AUTOMATICALLY GENERATED.  DO NOT EDIT.\n") \
	    > hfile
	printf(" *\n") > hfile
	printf(" * generated from:\n") > hfile
	printf(" *\t%s\n", VERSION) > hfile
	printf(" */\n") > hfile

	next
}
$1 == "vendor" {
	nvendors++

	vendorindex[$2] = nvendors;		# record index for this name, for later.
	vendors[nvendors, 1] = $2;		# name
	vendors[nvendors, 2] = $3;		# id
	printf("#define\tCARDBUS_VENDOR_%s\t%s\t", vendors[nvendors, 1],
	    vendors[nvendors, 2]) > hfile

	i = 3; f = 4;

	# comments
	ocomment = oparen = 0
	if (f <= NF) {
		printf("\t/* ") > hfile
		ocomment = 1;
	}
	while (f <= NF) {
		if ($f == "#") {
			printf("(") > hfile
			oparen = 1
			f++
			continue
		}
		if (oparen) {
			printf("%s", $f) > hfile
			if (f < NF)
				printf(" ") > hfile
			f++
			continue
		}
		vendors[nvendors, i] = $f
		printf("%s", vendors[nvendors, i]) > hfile
		if (f < NF)
			printf(" ") > hfile
		i++; f++;
	}
	if (oparen)
		printf(")") > hfile
	if (ocomment)
		printf(" */") > hfile
	printf("\n") > hfile

	next
}
$1 == "product" {
	nproducts++

	products[nproducts, 1] = $2;		# vendor name
	products[nproducts, 2] = $3;		# product id
	products[nproducts, 3] = $4;		# id
	printf("#define\tCARDBUS_PRODUCT_%s_%s\t%s\t", products[nproducts, 1],
	    products[nproducts, 2], products[nproducts, 3]) > hfile

	i=4; f = 5;

	# comments
	ocomment = oparen = 0
	if (f <= NF) {
		printf("\t/* ") > hfile
		ocomment = 1;
	}
	while (f <= NF) {
		if ($f == "#") {
			printf("(") > hfile
			oparen = 1
			f++
			continue
		}
		if (oparen) {
			printf("%s", $f) > hfile
			if (f < NF)
				printf(" ") > hfile
			f++
			continue
		}
		products[nproducts, i] = $f
		printf("%s", products[nproducts, i]) > hfile
		if (f < NF)
			printf(" ") > hfile
		i++; f++;
	}
	if (oparen)
		printf(")") > hfile
	if (ocomment)
		printf(" */") > hfile
	printf("\n") > hfile

	next
}
{
	if ($0 == "")
		blanklines++
	print $0 > hfile
	if (blanklines < 2)
		print $0 > dfile
}
END {
	# print out the match tables

	printf("\n") > dfile

	printf("struct cardbus_knowndev cardbus_knowndevs[] = {\n") > dfile
	for (i = 1; i <= nproducts; i++) {
		printf("\t{\n") > dfile
		printf("\t    CARDBUS_VENDOR_%s, CARDBUS_PRODUCT_%s_%s,\n",
		    products[i, 1], products[i, 1], products[i, 2]) \
		    > dfile
		printf("\t    ") > dfile
		printf("0") > dfile
		printf(",\n") > dfile

		vendi = vendorindex[products[i, 1]];
		printf("\t    \"") > dfile
		j = 3;
		needspace = 0;
		while (vendors[vendi, j] != "") {
			if (needspace)
				printf(" ") > dfile
			printf("%s", vendors[vendi, j]) > dfile
			needspace = 1
			j++
		}
		printf("\",\n") > dfile

		printf("\t    \"") > dfile
		j = 4;
		needspace = 0;
		while (products[i, j] != "") {
			if (needspace)
				printf(" ") > dfile
			printf("%s", products[i, j]) > dfile
			needspace = 1
			j++
		}
		printf("\",\n") > dfile
		printf("\t},\n") > dfile
	}
	for (i = 1; i <= nvendors; i++) {
		printf("\t{\n") > dfile
		printf("\t    CARDBUS_VENDOR_%s, 0,\n", vendors[i, 1]) \
		    > dfile
		printf("\t    CARDBUS_KNOWNDEV_NOPROD,\n") \
		    > dfile
		printf("\t    \"") > dfile
		j = 3;
		needspace = 0;
		while (vendors[i, j] != "") {
			if (needspace)
				printf(" ") > dfile
			printf("%s", vendors[i, j]) > dfile
			needspace = 1
			j++
		}
		printf("\",\n") > dfile
		printf("\t    NULL,\n") > dfile
		printf("\t},\n") > dfile
	}
	printf("\t{ 0, 0, 0, NULL, NULL, }\n") > dfile
	printf("};\n") > dfile
}


new vendor id for Phoenix Technologies

new vendor id for Phoenix Technologies

Appeared with Acer Aspire V5-571's BIOS vendor.

#
# Warning: this script used GNU Awk features.
#

#@include "../utils.awk"

BEGIN {
  # boolean value
  parsing_fwts_bios_info=0;
}

parse_fwts_bios_info();

END {
  print_shell_variables();
}

#
# Print shell variables that may be required for scripting.
# So far:
#   - part of the BIOS Information table to build the directory where results should be stored.
#
function print_shell_variables() {
  print "# automatically parsed from ", FILENAME, ". Please check.";
  print_shell_variables_bios_info();
}

#
# Print BIOS information as POSIX shell variables.
# For each bios information entry, print a variable assignment of the value quoted.
# Example:
# VENDOR_BIOS='intel'
#
function print_shell_variables_bios_info() {
  print to_shell_variable("FWTR_BIOS_INFO_BIOS_VENDOR",       sanitize_vendor(bios_vendor));
  print to_shell_variable("FWTR_BIOS_INFO_BIOS_VERSION",      sanitize_text(bios_version));
  print to_shell_variable("FWTR_BIOS_INFO_BIOS_RELEASE_DATE", sanitize_text(bios_release_date));
  print to_shell_variable("FWTR_BIOS_INFO_BOARD_NAME",        sanitize_text(board_name));
  print to_shell_variable("FWTR_BIOS_INFO_BOARD_VERSION",     sanitize_text(board_version));
  print to_shell_variable("FWTR_BIOS_INFO_PRODUCT_NAME",      sanitize_text(product_name));
  print to_shell_variable("FWTR_BIOS_INFO_PRODUCT_VERSION",   sanitize_text(product_version));
  print to_shell_variable("FWTR_BIOS_INFO_SYSTEM_VENDOR",     sanitize_vendor(system_vendor));
}

#
# Parse the BIOS Information Table from FWTS test results.
# Assumed beginning with `bios_info:` and ending with `System Vendor:` rows.
#
# Example:
# > bios_info: Gather BIOS DMI information.
# > --------------------------------------------------------------------------------
# > Test 1 of 1: Gather BIOS DMI information
# > BIOS Vendor       : Intel Corp.
# > BIOS Version      : TYBYT10H.86A.0046.2015.1014.1057
# > BIOS Release Date : 10/14/2015
# > Board Name        : DE3815TYKH
# > Board Serial #    :
# > Board Version     : H26998-401
# > Board Asset Tag   :
# > Chassis Serial #  :
# > Chassis Type      : 3
# > Chassis Vendor    :
# > Chassis Version   :
# > Chassic Asset Tag :
# > Product Name      :
# > Product Serial #  :
# > Product UUID      :
# > Product Version   :
# > System Vendor     :
#
function parse_fwts_bios_info() {
  if ($0 ~ /bios_info:/) {
    parsing_fwts_bios_info=1; # true, we are parsing the BIOS Infos
    FS=":"; # `:` as field-separator. Cf. the bios info table example
  }

  if (parsing_fwts_bios_info) {
    parse_fwts_bios_info_entry("BIOS Vendor",       "bios_vendor");
    parse_fwts_bios_info_entry("BIOS Version",      "bios_version");
    parse_fwts_bios_info_entry("BIOS Release Date", "bios_release_date");
    parse_fwts_bios_info_entry("Board Name",        "board_name");
    # ignored: Board Serial #
    parse_fwts_bios_info_entry("Board Version",     "board_version");
    # ignored: Board Asset Tag
    # ignored: Chassis Serial #
    # ignored: Chassis Type
    # ignored: Chassis Vendor
    # ignored: Chassis Version
    # ignored: Chassis Asset Tag
    parse_fwts_bios_info_entry("Product Name",      "product_name");
    # ignored: Product Serial #
    # ignored: Product UUID
    parse_fwts_bios_info_entry("Product Version",   "product_version");
    # last line of the bios info table reached
    parse_fwts_bios_info_entry("System Vendor",     "system_vendor") && parsing_fwts_bios_info=0;

  }
}

#
# Return the vendor ID string: a lower-case unique and single company name.
# Instead of trying to remove `Inc.`, `Corp.`, etc. directly match company substrings.
#
function to_vendor_id(vendor)
{
  vendor = tolower(vendor);

  switch (vendor) {
    # Phoenix Technologies Ltd.
    case /phoenix/:
      return "phoenix"

    # Intel Corp.
    case /intel/:
      return "intel";

    case /american megatrends/:
      return "ami";

    case /award/:
      return "award";

    case /gigabyte/:
      return "gigabyte";

    case /dell/:
      return "dell";

    case /samsung/:
      return "samsung";

    # failsafe attempt:
    # vendor names with a single word sould be usable as they are.
    # matches things like: ibm, asus, intel, lenovo, dell...
    # Names compound with `Inc.`
    case /^[[:alnum:]]{2,}$/:
      return vendor;

    default:
      print "ERROR: unknown vendor name `" vendor "`" > "/dev/stderr";
      print "       please add your new vendor name in `to_vendor_id()` function"  > "/dev/stderr";
      return "error";
  }
}

#
# Sanitize a vendor text string.
#
function sanitize_vendor(vendor) {
  if (vendor ~ /^$/)
    return "";

  vendor=sanitize_text(vendor);
  vendor=to_vendor_id(vendor)
  gsub(/[^/\-_ \\[:alnum:]]/, "", vendor);
  return vendor;
}

#
# Retrieve an entry value from the BIOS DMI table into `variable` when it matches `pattern`.
#
function parse_fwts_bios_info_entry(pattern, variable) {
  if ($0 ~ pattern) {
    sub(/<.*>/, "", $2);
    set(variable, trim($2));
    return 1;
  }
  return 0;
}

#
# Setter functions required by `set()`.
#
function set_bios_vendor(value)       { bios_vendor=value; }
function set_bios_version(value)      { bios_version=value; }
function set_bios_release_date(value) { bios_release_date=value; }
function set_board_name(value)        { board_name=value; }
function set_board_version(value)     { board_version=value; }
function set_product_name(value)      { product_name=value; }
function set_product_version(value)   { product_version=value; }
function set_system_vendor(value)     { system_vendor=value; }

#
# Warning: this script used GNU Awk features.
#

#@include "../utils.awk"

BEGIN {
  # boolean value
  parsing_fwts_bios_info=0;
}

parse_fwts_bios_info();

END {
  print_shell_variables();
}

#
# Print shell variables that may be required for scripting.
# So far:
#   - part of the BIOS Information table to build the directory where results should be stored.
#
function print_shell_variables() {
  print "# automatically parsed from ", FILENAME, ". Please check.";
  print_shell_variables_bios_info();
}

#
# Print BIOS information as POSIX shell variables.
# For each bios information entry, print a variable assignment of the value quoted.
# Example:
# VENDOR_BIOS='intel'
#
function print_shell_variables_bios_info() {
  print to_shell_variable("FWTR_BIOS_INFO_BIOS_VENDOR",       sanitize_vendor(bios_vendor));
  print to_shell_variable("FWTR_BIOS_INFO_BIOS_VERSION",      sanitize_text(bios_version));
  print to_shell_variable("FWTR_BIOS_INFO_BIOS_RELEASE_DATE", sanitize_text(bios_release_date));
  print to_shell_variable("FWTR_BIOS_INFO_BOARD_NAME",        sanitize_text(board_name));
  print to_shell_variable("FWTR_BIOS_INFO_BOARD_VERSION",     sanitize_text(board_version));
  print to_shell_variable("FWTR_BIOS_INFO_PRODUCT_NAME",      sanitize_text(product_name));
  print to_shell_variable("FWTR_BIOS_INFO_PRODUCT_VERSION",   sanitize_text(product_version));
  print to_shell_variable("FWTR_BIOS_INFO_SYSTEM_VENDOR",     sanitize_vendor(system_vendor));
}

#
# Parse the BIOS Information Table from FWTS test results.
# Assumed beginning with `bios_info:` and ending with `System Vendor:` rows.
#
# Example:
# > bios_info: Gather BIOS DMI information.
# > --------------------------------------------------------------------------------
# > Test 1 of 1: Gather BIOS DMI information
# > BIOS Vendor       : Intel Corp.
# > BIOS Version      : TYBYT10H.86A.0046.2015.1014.1057
# > BIOS Release Date : 10/14/2015
# > Board Name        : DE3815TYKH
# > Board Serial #    :
# > Board Version     : H26998-401
# > Board Asset Tag   :
# > Chassis Serial #  :
# > Chassis Type      : 3
# > Chassis Vendor    :
# > Chassis Version   :
# > Chassic Asset Tag :
# > Product Name      :
# > Product Serial #  :
# > Product UUID      :
# > Product Version   :
# > System Vendor     :
#
function parse_fwts_bios_info() {
  if ($0 ~ /bios_info:/) {
    parsing_fwts_bios_info=1; # true, we are parsing the BIOS Infos
    FS=":"; # `:` as field-separator. Cf. the bios info table example
  }

  if (parsing_fwts_bios_info) {
    parse_fwts_bios_info_entry("BIOS Vendor",       "bios_vendor");
    parse_fwts_bios_info_entry("BIOS Version",      "bios_version");
    parse_fwts_bios_info_entry("BIOS Release Date", "bios_release_date");
    parse_fwts_bios_info_entry("Board Name",        "board_name");
    # ignored: Board Serial #
    parse_fwts_bios_info_entry("Board Version",     "board_version");
    # ignored: Board Asset Tag
    # ignored: Chassis Serial #
    # ignored: Chassis Type
    # ignored: Chassis Vendor
    # ignored: Chassis Version
    # ignored: Chassis Asset Tag
    parse_fwts_bios_info_entry("Product Name",      "product_name");
    # ignored: Product Serial #
    # ignored: Product UUID
    parse_fwts_bios_info_entry("Product Version",   "product_version");
    # last line of the bios info table reached
    parse_fwts_bios_info_entry("System Vendor",     "system_vendor") && parsing_fwts_bios_info=0;

  }
}

#
# Return the vendor ID string: a lower-case unique and single company name.
# Instead of trying to remove `Inc.`, `Corp.`, etc. directly match company substrings.
#
function to_vendor_id(vendor)
{
  vendor = tolower(vendor);

  switch (vendor) {
    # Intel Corp.
    case /intel/:
      return "intel";

    case /american megatrends/:
      return "ami";

    case /award/:
      return "award";

    case /gigabyte/:
      return "gigabyte";

    case /dell/:
      return "dell";

    case /samsung/:
      return "samsung";

    # failsafe attempt:
    # vendor names with a single word sould be usable as they are.
    # matches things like: ibm, asus, intel, lenovo, dell...
    # Names compound with `Inc.`
    case /^[[:alnum:]]{2,}$/:
      return vendor;

    default:
      print "ERROR: unknown vendor name `" vendor "`" > "/dev/stderr";
      print "       please add your new vendor name in `to_vendor_id()` function"  > "/dev/stderr";
      return "error";
  }
}

#
# Sanitize a vendor text string.
#
function sanitize_vendor(vendor) {
  if (vendor ~ /^$/)
    return "";

  vendor=sanitize_text(vendor);
  vendor=to_vendor_id(vendor)
  gsub(/[^/\-_ \\[:alnum:]]/, "", vendor);
  return vendor;
}

#
# Retrieve an entry value from the BIOS DMI table into `variable` when it matches `pattern`.
#
function parse_fwts_bios_info_entry(pattern, variable) {
  if ($0 ~ pattern) {
    sub(/<.*>/, "", $2);
    set(variable, trim($2));
    return 1;
  }
  return 0;
}

#
# Setter functions required by `set()`.
#
function set_bios_vendor(value)       { bios_vendor=value; }
function set_bios_version(value)      { bios_version=value; }
function set_bios_release_date(value) { bios_release_date=value; }
function set_board_name(value)        { board_name=value; }
function set_board_version(value)     { board_version=value; }
function set_product_name(value)      { product_name=value; }
function set_product_version(value)   { product_version=value; }
function set_system_vendor(value)     { system_vendor=value; }


Drop now hidden ioctl(2) operations for NetBSD

POWER_IOC_GET_TYPE_WITH_LOSSAGE is no longer accessible from userland.

git-svn-id: c199f293c43da69278bea8e88f92242bf3aa95f7@345572 91177308-0d34-0410-b5e6-96231b3b80d8

#!/usr/bin/awk -f

#===-- generate_netbsd_ioctls.awk ------------------------------------------===#
#
#                     The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===------------------------------------------------------------------------===#
#
# This file is a generator of:
#  - include/sanitizer/sanitizer_interceptors_ioctl_netbsd.inc
#
# This script reads public headers from a NetBSD host.
#
#===------------------------------------------------------------------------===#

BEGIN {
  # harcode the script name
  script_name = "generate_netbsd_ioctls.awk"
  outputinc = "../lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc"

  # assert that we are in the directory with scripts
  in_utils = system("test -f " script_name " && exit 1 || exit 0")
  if (in_utils == 0) {
    usage()
  }

  # assert 0 argument passed
  if (ARGC != 1) {
    usage()
  }

  # accept overloading CLANGFORMAT from environment
  clangformat = "clang-format"
  if ("CLANGFORMAT" in ENVIRON) {
    clangformat = ENVIRON["CLANGFORMAT"]
  }

  # accept overloading ROOTDIR from environment
  rootdir = "/usr/include/"
  if ("ROOTDIR" in ENVIRON) {
    rootdir = ENVIRON["ROOTDIR"]
  }

  # hardcode list of headers with ioctl(2) entries
  # List generated manually with the following script:
  #   for w in `find /usr/include/ -type f -name '*.h' -exec echo {} \;`; \
  #   do awk '/[^a-zA-Z0-9_]_IO[W]*[R]*[ ]*\(/ && $2 ~ /^[A-Z_]+$/ {got=1} END{if(got) {print ARGV[1]}}' $w; \
  #   done|awk '{print "  ARGV[ARGC++] = rootdir \"" substr($0, 14) "\""}'

  ARGV[ARGC++] = rootdir "altq/altq_afmap.h"
  ARGV[ARGC++] = rootdir "altq/altq.h"
  ARGV[ARGC++] = rootdir "altq/altq_blue.h"
  ARGV[ARGC++] = rootdir "altq/altq_cbq.h"
  ARGV[ARGC++] = rootdir "altq/altq_cdnr.h"
  ARGV[ARGC++] = rootdir "altq/altq_fifoq.h"
  ARGV[ARGC++] = rootdir "altq/altq_hfsc.h"
  ARGV[ARGC++] = rootdir "altq/altq_jobs.h"
  ARGV[ARGC++] = rootdir "altq/altq_priq.h"
  ARGV[ARGC++] = rootdir "altq/altq_red.h"
  ARGV[ARGC++] = rootdir "altq/altq_rio.h"
  ARGV[ARGC++] = rootdir "altq/altq_wfq.h"
  ARGV[ARGC++] = rootdir "crypto/cryptodev.h"
  ARGV[ARGC++] = rootdir "dev/apm/apmio.h"
  ARGV[ARGC++] = rootdir "dev/dm/netbsd-dm.h"
  ARGV[ARGC++] = rootdir "dev/dmover/dmover_io.h"
  ARGV[ARGC++] = rootdir "dev/dtv/dtvio_demux.h"
  ARGV[ARGC++] = rootdir "dev/dtv/dtvio_frontend.h"
  ARGV[ARGC++] = rootdir "dev/filemon/filemon.h"
  ARGV[ARGC++] = rootdir "dev/hdaudio/hdaudioio.h"
  ARGV[ARGC++] = rootdir "dev/hdmicec/hdmicecio.h"
  ARGV[ARGC++] = rootdir "dev/hpc/hpcfbio.h"
  ARGV[ARGC++] = rootdir "dev/i2o/iopio.h"
  ARGV[ARGC++] = rootdir "dev/ic/athioctl.h"
  ARGV[ARGC++] = rootdir "dev/ic/bt8xx.h"
  ARGV[ARGC++] = rootdir "dev/ic/hd44780var.h"
  ARGV[ARGC++] = rootdir "dev/ic/icp_ioctl.h"
  ARGV[ARGC++] = rootdir "dev/ic/isp_ioctl.h"
  ARGV[ARGC++] = rootdir "dev/ic/mlxio.h"
  ARGV[ARGC++] = rootdir "dev/ic/nvmeio.h"
  ARGV[ARGC++] = rootdir "dev/ir/irdaio.h"
  ARGV[ARGC++] = rootdir "dev/isa/satlinkio.h"
  ARGV[ARGC++] = rootdir "dev/isa/isvio.h"
  ARGV[ARGC++] = rootdir "dev/isa/wtreg.h"
  ARGV[ARGC++] = rootdir "dev/iscsi/iscsi_ioctl.h"
  ARGV[ARGC++] = rootdir "dev/ofw/openfirmio.h"
  ARGV[ARGC++] = rootdir "dev/pci/amrio.h"
  ARGV[ARGC++] = rootdir "dev/pci/mlyio.h"
  ARGV[ARGC++] = rootdir "dev/pci/pciio.h"
  ARGV[ARGC++] = rootdir "dev/pci/tweio.h"
  ARGV[ARGC++] = rootdir "dev/pcmcia/if_cnwioctl.h"
  ARGV[ARGC++] = rootdir "dev/pcmcia/if_rayreg.h"
  ARGV[ARGC++] = rootdir "dev/raidframe/raidframeio.h"
  ARGV[ARGC++] = rootdir "dev/sbus/mbppio.h"
  ARGV[ARGC++] = rootdir "dev/scsipi/ses.h"
  ARGV[ARGC++] = rootdir "dev/sun/disklabel.h"
  ARGV[ARGC++] = rootdir "dev/sun/fbio.h"
  ARGV[ARGC++] = rootdir "dev/sun/kbio.h"
  ARGV[ARGC++] = rootdir "dev/sun/vuid_event.h"
  ARGV[ARGC++] = rootdir "dev/tc/sticio.h"
  ARGV[ARGC++] = rootdir "dev/usb/ukyopon.h"
  ARGV[ARGC++] = rootdir "dev/usb/urio.h"
  ARGV[ARGC++] = rootdir "dev/usb/usb.h"
  ARGV[ARGC++] = rootdir "dev/usb/utoppy.h"
  ARGV[ARGC++] = rootdir "dev/vme/xio.h"
  ARGV[ARGC++] = rootdir "dev/wscons/wsdisplay_usl_io.h"
  ARGV[ARGC++] = rootdir "dev/wscons/wsconsio.h"
  ARGV[ARGC++] = rootdir "dev/biovar.h"
  ARGV[ARGC++] = rootdir "dev/md.h"
  ARGV[ARGC++] = rootdir "dev/ccdvar.h"
  ARGV[ARGC++] = rootdir "dev/cgdvar.h"
  ARGV[ARGC++] = rootdir "dev/fssvar.h"
  ARGV[ARGC++] = rootdir "dev/bluetooth/btdev.h"
  ARGV[ARGC++] = rootdir "dev/bluetooth/btsco.h"
  ARGV[ARGC++] = rootdir "dev/kttcpio.h"
  ARGV[ARGC++] = rootdir "dev/lockstat.h"
  ARGV[ARGC++] = rootdir "dev/vndvar.h"
  ARGV[ARGC++] = rootdir "dev/spkrio.h"
  ARGV[ARGC++] = rootdir "net/bpf.h"
  ARGV[ARGC++] = rootdir "net/if_atm.h"
  ARGV[ARGC++] = rootdir "net/if_gre.h"
  ARGV[ARGC++] = rootdir "net/if_ppp.h"
  ARGV[ARGC++] = rootdir "net/npf.h"
  ARGV[ARGC++] = rootdir "net/if_pppoe.h"
  ARGV[ARGC++] = rootdir "net/if_sppp.h"
  ARGV[ARGC++] = rootdir "net/if_srt.h"
  ARGV[ARGC++] = rootdir "net/if_tap.h"
  ARGV[ARGC++] = rootdir "net/if_tun.h"
  ARGV[ARGC++] = rootdir "net/pfvar.h"
  ARGV[ARGC++] = rootdir "net/slip.h"
  ARGV[ARGC++] = rootdir "netbt/hci.h"
  ARGV[ARGC++] = rootdir "netinet/ip_nat.h"
  ARGV[ARGC++] = rootdir "netinet/ip_proxy.h"
  ARGV[ARGC++] = rootdir "netinet6/in6_var.h"
  ARGV[ARGC++] = rootdir "netnatm/natm.h"
  ARGV[ARGC++] = rootdir "netsmb/smb_dev.h"
  ARGV[ARGC++] = rootdir "sys/agpio.h"
  ARGV[ARGC++] = rootdir "sys/audioio.h"
  ARGV[ARGC++] = rootdir "sys/ataio.h"
  ARGV[ARGC++] = rootdir "sys/cdio.h"
  ARGV[ARGC++] = rootdir "sys/chio.h"
  ARGV[ARGC++] = rootdir "sys/clockctl.h"
  ARGV[ARGC++] = rootdir "sys/cpuio.h"
  ARGV[ARGC++] = rootdir "sys/dkio.h"
  ARGV[ARGC++] = rootdir "sys/drvctlio.h"
  ARGV[ARGC++] = rootdir "sys/dvdio.h"
  ARGV[ARGC++] = rootdir "sys/envsys.h"
  ARGV[ARGC++] = rootdir "sys/event.h"
  ARGV[ARGC++] = rootdir "sys/fdio.h"
  ARGV[ARGC++] = rootdir "sys/filio.h"
  ARGV[ARGC++] = rootdir "sys/gpio.h"
  ARGV[ARGC++] = rootdir "sys/ioctl.h"
  ARGV[ARGC++] = rootdir "sys/ioctl_compat.h"
  ARGV[ARGC++] = rootdir "sys/joystick.h"
  ARGV[ARGC++] = rootdir "sys/ksyms.h"
  ARGV[ARGC++] = rootdir "sys/lua.h"
  ARGV[ARGC++] = rootdir "sys/midiio.h"
  ARGV[ARGC++] = rootdir "sys/mtio.h"
  ARGV[ARGC++] = rootdir "sys/power.h"
  ARGV[ARGC++] = rootdir "sys/radioio.h"
  ARGV[ARGC++] = rootdir "sys/rndio.h"
  ARGV[ARGC++] = rootdir "sys/scanio.h"
  ARGV[ARGC++] = rootdir "sys/scsiio.h"
  ARGV[ARGC++] = rootdir "sys/sockio.h"
  ARGV[ARGC++] = rootdir "sys/timepps.h"
  ARGV[ARGC++] = rootdir "sys/ttycom.h"
  ARGV[ARGC++] = rootdir "sys/verified_exec.h"
  ARGV[ARGC++] = rootdir "sys/videoio.h"
  ARGV[ARGC++] = rootdir "sys/wdog.h"
  ARGV[ARGC++] = rootdir "soundcard.h"
  ARGV[ARGC++] = rootdir "xen/xenio.h"

  ioctl_table_max = 0
}

# Scan RCS ID
FNR == 1 {
  fname[ioctl_table_max] = substr(FILENAME, length(rootdir) + 1)
}

# _IO
/[^a-zA-Z0-9_]_IO[W]*[R]*[ ]*\(/ && $2 ~ /^[A-Z_]+$/ {
  if ($0 ~ /RAIDFRAME_GET_ACCTOTALS/ ||
      $0 ~ /ALTQATTACH/ ||
      $0 ~ /ALTQDETACH/ ||
      $0 ~ /ALTQENABLE/ ||
      $0 ~ /ALTQDISABLE/ ||
      $0 ~ /ALTQCLEAR/ ||
      $0 ~ /ALTQCONFIG/ ||
      $0 ~ /ALTQADDCLASS/ ||
      $0 ~ /ALTQMODCLASS/ ||
      $0 ~ /ALTQDELCLASS/ ||
      $0 ~ /ALTQADDFILTER/ ||
      $0 ~ /ALTQDELFILTER/ ||
      $0 ~ /ALTQGETSTATS/ ||
      $0 ~ /ALTQGETCNTR/ ||
      $0 ~ /HFSC_IF_ATTACH/ ||
      $0 ~ /HFSC_MOD_CLASS/ ||
      $0 ~ /HLCD_DISPCTL/ ||
      $0 ~ /HLCD_RESET/ ||
      $0 ~ /HLCD_CLEAR/ ||
      $0 ~ /HLCD_CURSOR_LEFT/ ||
      $0 ~ /HLCD_CURSOR_RIGHT/ ||
      $0 ~ /HLCD_GET_CURSOR_POS/ ||
      $0 ~ /HLCD_SET_CURSOR_POS/ ||
      $0 ~ /HLCD_GETC/ ||
      $0 ~ /HLCD_PUTC/ ||
      $0 ~ /HLCD_SHIFT_LEFT/ ||
      $0 ~ /HLCD_SHIFT_RIGHT/ ||
      $0 ~ /HLCD_HOME/ ||
      $0 ~ /HLCD_WRITE/ ||
      $0 ~ /HLCD_READ/ ||
      $0 ~ /HLCD_REDRAW/ ||
      $0 ~ /HLCD_WRITE_INST/ ||
      $0 ~ /HLCD_WRITE_DATA/ ||
      $0 ~ /HLCD_GET_INFO/ ||
      $0 ~ /HLCD_GET_CHIPNO/ ||
      $0 ~ /HLCD_SET_CHIPNO/ ||
      $0 ~ /RAIDFRAME_TEST_ACC/ ||
      $0 ~ /FBIOGINFO/ ||
      $0 ~ /FBIOSATTR/ ||
      $0 ~ /OBIOCDISK/ ||
      $0 ~ /OBIOCVOL/ ||
      $0 ~ /BIOCSORTIMEOUT/ ||
      $0 ~ /BIOCGORTIMEOUT/ ||
      $0 ~ /PPPIOCSPASS/ ||
      $0 ~ /PPPIOCSACTIVE/ ||
      $0 ~ /PPPIOCSIPASS/ ||
      $0 ~ /PPPIOCSOPASS/ ||
      $0 ~ /PPPIOCSIACTIVE/ ||
      $0 ~ /PPPIOCSOACTIVE/ ||
      $0 ~ /SIOCPROXY/ ||
      $0 ~ /SIOCXRAWATM/ ||
      $0 ~ /AGPIOC_RESERVE/ ||
      $0 ~ /AGPIOC_PROTECT/ ||
      $0 ~ /CDIOCREADSUBCHANNEL_BUF/ ||
      $0 ~ /CDIOREADTOCENTRIES_BUF/ ||
      $0 ~ /MMCGETDISCINFO/ ||
      $0 ~ /MMCGETTRACKINFO/ ||
      $0 ~ /MMCOP/ ||
      $0 ~ /MMCSETUPWRITEPARAMS/ ||
      $0 ~ /DIOCGPARTINFO/ ||
      $0 ~ /ODIOCGDINFO/ ||
      $0 ~ /ODIOCSDINFO/ ||
      $0 ~ /ODIOCWDINFO/ ||
      $0 ~ /ODIOCGDEFLABEL/ ||
      $0 ~ /GPIOPINREAD/ ||
      $0 ~ /GPIOPINWRITE/ ||
      $0 ~ /GPIOPINTOGGLE/ ||
      $0 ~ /GPIOPINCTL/ ||
      $0 ~ /GPIODETACH/ ||
      $0 ~ /SEQUENCER_PERCMODE/ ||
      $0 ~ /SEQUENCER_TESTMIDI/ ||
      $0 ~ /SEQUENCER_MIDI_INFO/ ||
      $0 ~ /SEQUENCER_ID/ ||
      $0 ~ /SEQUENCER_CONTROL/ ||
      $0 ~ /SEQUENCER_REMOVESAMPLE/ ||
      $0 ~ /EVTCHN_RESET/ ||
      $0 ~ /EVTCHN_BIND/ ||
      $0 ~ /EVTCHN_UNBIND/) {
    # broken entry, incomplete definition of the 3rd parameterm etc
    next
  }

  if ($0 ~ /APM_IOC_STANDBY/ ||
      $0 ~ /APM_IOC_SUSPEND/ ||
      $0 ~ /SCIOC_USE_ADF/ ||
      $0 ~ /SCBUSIOLLSCAN/ ||
      $0 ~ /UTOPPYIOCANCEL/ ||
      $0 ~ /JOY_GET_X_OFFSET/ ||
      $0 ~ /CHIOGPICKER/ ||
      $0 ~ /SLIOCGUNIT/ ||
      $0 ~ /SATIOSBUFSIZE/ ||
      $0 ~ /TUNSLMODE/ ||
      $0 ~ /CBQ_IF_ATTACH/ ||
      $0 ~ /CDNR_IF_ATTACH/ ||
      $0 ~ /RIO_IF_ATTACH/ ||
      $0 ~ /CBQ_IF_DETACH/ ||
      $0 ~ /HFSC_IF_DETACH/ ||
      $0 ~ /WFQ_IF_DETACH/ ||
      $0 ~ /RIO_IF_DETACH/ ||
      $0 ~ /FIFOQ_IF_DETACH/ ||
      $0 ~ /RED_IF_DETACH/ ||
      $0 ~ /CDNR_ENABLE/ ||
      $0 ~ /HFSC_ENABLE/ ||
      $0 ~ /WFQ_ENABLE/ ||
      $0 ~ /RIO_ENABLE/ ||
      $0 ~ /FIFOQ_ENABLE/ ||
      $0 ~ /RED_ENABLE/ ||
      $0 ~ /BLUE_ENABLE/ ||
      $0 ~ /CDNR_DISABLE/ ||
      $0 ~ /HFSC_DISABLE/ ||
      $0 ~ /WFQ_DISABLE/ ||
      $0 ~ /RIO_DISABLE/ ||
      $0 ~ /FIFOQ_DISABLE/ ||
      $0 ~ /PRIQ_DISABLE/ ||
      $0 ~ /CDNR_DEL_FILTER/ ||
      $0 ~ /JOBS_DEL_CLASS/ ||
      $0 ~ /JOBS_DEL_FILTER/ ||
      $0 ~ /JOBS_GETSTATS/ ||
      $0 ~ /WFQ_GET_STATS/ ||
      $0 ~ /CBQ_ADD_FILTER/ ||
      $0 ~ /HFSC_ADD_FILTER/ ||
      $0 ~ /JOBS_ADD_FILTER/ ||
      $0 ~ /RED_IF_ATTACH/ ||
      $0 ~ /FIFOQ_IF_ATTACH/ ||
      $0 ~ /BLUE_IF_DETACH/ ||
      $0 ~ /CBQ_DISABLE/ ||
      $0 ~ /RED_DISABLE/ ||
      $0 ~ /CBQ_CLEAR_HIERARCHY/ ||
      $0 ~ /HFSC_DEL_CLASS/ ||
      $0 ~ /PRIQ_IF_DETACH/ ||
      $0 ~ /PRIQ_ENABLE/ ||
      $0 ~ /WFQ_IF_ATTACH/ ||
      $0 ~ /POWER_IOC_GET_TYPE_WITH_LOSSAGE/ ||
      $0 ~ /HFSC_DEL_FILTER/) {
    # There are entries with duplicate codes.. disable the less used ones
    next
  }

  if ($2 in known) {
    # Avoid duplicates
    # There are entries compatible with K&R and ANSI preprocessor
    next
  }

  known[$2] = 1

  ioctl_name[ioctl_table_max] = $2

  split($3, a, "(")
  a3 = a[1]
  if (a3 ~ /_IO[ ]*$/) {
    ioctl_mode[ioctl_table_max] = "NONE"
  } else if (a3 ~ /_IOR[ ]*$/) {
    ioctl_mode[ioctl_table_max] = "WRITE"
  } else if (a3 ~ /_IOW[ ]*$/) {
    ioctl_mode[ioctl_table_max] = "READ"
  } else if (a3 ~ /_IOWR[ ]*$/) {
    ioctl_mode[ioctl_table_max] = "READWRITE"
  } else {
    print "Unknown mode, cannot parse: '" $3 "'"
  }

  # This !NONE check allows to skip some unparsable entries
  if (ioctl_mode[ioctl_table_max] != "NONE") {
    n = split($0, a, ",")
    if (n == 3) {
      gsub(/^[ ]+/, "", a[3])
      match(a[3], /[a-zA-Z0-9_* ]+/)
      type = get_type(substr(a[3], 0, RLENGTH))
      ioctl_type[ioctl_table_max] = type
    }
  }

  ioctl_table_max++
}

END {
  # empty files?
  if (NR < 1 && !abnormal_exit) {
    usage()
  }

  # Handle abnormal exit
  if (abnormal_exit) {
    exit(abnormal_exit)
  }

  # Generate sanitizer_interceptors_ioctl_netbsd.inc

  # open pipe
  cmd = clangformat " > " outputinc

  pcmd("//===-- sanitizer_interceptors_ioctl_netbsd.inc -----------------*- C++ -*-===//")
  pcmd("//")
  pcmd("//                     The LLVM Compiler Infrastructure")
  pcmd("//")
  pcmd("// This file is distributed under the University of Illinois Open Source")
  pcmd("// License. See LICENSE.TXT for details.")
  pcmd("//")
  pcmd("//===----------------------------------------------------------------------===//")
  pcmd("//")
  pcmd("// Ioctl handling in common sanitizer interceptors.")
  pcmd("//===----------------------------------------------------------------------===//")
  pcmd("")
  pcmd("#if SANITIZER_NETBSD")
  pcmd("")
  pcmd("#include \"sanitizer_flags.h\"")
  pcmd("")
  pcmd("struct ioctl_desc {")
  pcmd("  unsigned req;")
  pcmd("  // FIXME: support read+write arguments. Currently READWRITE and WRITE do the")
  pcmd("  // same thing.")
  pcmd("  // XXX: The declarations below may use WRITE instead of READWRITE, unless")
  pcmd("  // explicitly noted.")
  pcmd("  enum {")
  pcmd("    NONE,")
  pcmd("    READ,")
  pcmd("    WRITE,")
  pcmd("    READWRITE,")
  pcmd("    CUSTOM")
  pcmd("  } type : 3;")
  pcmd("  unsigned size : 29;")
  pcmd("  const char* name;")
  pcmd("};")
  pcmd("")
  pcmd("const unsigned ioctl_table_max = " ioctl_table_max ";")
  pcmd("static ioctl_desc ioctl_table[ioctl_table_max];")
  pcmd("static unsigned ioctl_table_size = 0;")
  pcmd("")
  pcmd("// This can not be declared as a global, because references to struct_*_sz")
  pcmd("// require a global initializer. And this table must be available before global")
  pcmd("// initializers are run.")
  pcmd("static void ioctl_table_fill() {")
  pcmd("#define _(rq, tp, sz)                                    \\")
  pcmd("  if (IOCTL_##rq != IOCTL_NOT_PRESENT) {                 \\")
  pcmd("    CHECK(ioctl_table_size < ioctl_table_max);           \\")
  pcmd("    ioctl_table[ioctl_table_size].req = IOCTL_##rq;      \\")
  pcmd("    ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \\")
  pcmd("    ioctl_table[ioctl_table_size].size = sz;             \\")
  pcmd("    ioctl_table[ioctl_table_size].name = #rq;            \\")
  pcmd("    ++ioctl_table_size;                                  \\")
  pcmd("  }")
  pcmd("")

  for (i = 0; i < ioctl_table_max; i++) {
    if (i in fname) {
      pcmd("  /* Entries from file: " fname[i] " */")
    }

    if (i in ioctl_type) {
      type = ioctl_type[i]
    } else {
      type = "0"
    }

    pcmd("  _(" ioctl_name[i] ", " ioctl_mode[i] "," type ");")
  }

  pcmd("#undef _")
  pcmd("}")
  pcmd("")
  pcmd("static bool ioctl_initialized = false;")
  pcmd("")
  pcmd("struct ioctl_desc_compare {")
  pcmd("  bool operator()(const ioctl_desc& left, const ioctl_desc& right) const {")
  pcmd("    return left.req < right.req;")
  pcmd("  }")
  pcmd("};")
  pcmd("")
  pcmd("static void ioctl_init() {")
  pcmd("  ioctl_table_fill();")
  pcmd("  Sort(ioctl_table, ioctl_table_size, ioctl_desc_compare());")
  pcmd("")
  pcmd("  bool bad = false;")
  pcmd("  for (unsigned i = 0; i < ioctl_table_size - 1; ++i) {")
  pcmd("    if (ioctl_table[i].req >= ioctl_table[i + 1].req) {")
  pcmd("      Printf(\"Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\\n\",")
  pcmd("             ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name,")
  pcmd("             ioctl_table[i + 1].name);")
  pcmd("      bad = true;")
  pcmd("    }")
  pcmd("  }")
  pcmd("")
  pcmd("  if (bad) Die();")
  pcmd("")
  pcmd("  ioctl_initialized = true;")
  pcmd("}")
  pcmd("")
  pcmd("static const ioctl_desc *ioctl_table_lookup(unsigned req) {")
  pcmd("  int left = 0;")
  pcmd("  int right = ioctl_table_size;")
  pcmd("  while (left < right) {")
  pcmd("    int mid = (left + right) / 2;")
  pcmd("    if (ioctl_table[mid].req < req)")
  pcmd("      left = mid + 1;")
  pcmd("    else")
  pcmd("      right = mid;")
  pcmd("  }")
  pcmd("  if (left == right && ioctl_table[left].req == req)")
  pcmd("    return ioctl_table + left;")
  pcmd("  else")
  pcmd("    return nullptr;")
  pcmd("}")
  pcmd("")
  pcmd("static bool ioctl_decode(unsigned req, ioctl_desc *desc) {")
  pcmd("  CHECK(desc);")
  pcmd("  desc->req = req;")
  pcmd("  desc->name = \"<DECODED_IOCTL>\";")
  pcmd("  desc->size = IOC_SIZE(req);")
  pcmd("  // Sanity check.")
  pcmd("  if (desc->size > 0xFFFF) return false;")
  pcmd("  unsigned dir = IOC_DIR(req);")
  pcmd("  switch (dir) {")
  pcmd("    case IOC_NONE:")
  pcmd("      desc->type = ioctl_desc::NONE;")
  pcmd("      break;")
  pcmd("    case IOC_READ | IOC_WRITE:")
  pcmd("      desc->type = ioctl_desc::READWRITE;")
  pcmd("      break;")
  pcmd("    case IOC_READ:")
  pcmd("      desc->type = ioctl_desc::WRITE;")
  pcmd("      break;")
  pcmd("    case IOC_WRITE:")
  pcmd("      desc->type = ioctl_desc::READ;")
  pcmd("      break;")
  pcmd("    default:")
  pcmd("      return false;")
  pcmd("  }")
  pcmd("  // Size can be 0 iff type is NONE.")
  pcmd("  if ((desc->type == IOC_NONE) != (desc->size == 0)) return false;")
  pcmd("  // Sanity check.")
  pcmd("  if (IOC_TYPE(req) == 0) return false;")
  pcmd("  return true;")
  pcmd("}")
  pcmd("")
  pcmd("static const ioctl_desc *ioctl_lookup(unsigned req) {")
  pcmd("  const ioctl_desc *desc = ioctl_table_lookup(req);")
  pcmd("  if (desc) return desc;")
  pcmd("")
  pcmd("  // Try stripping access size from the request id.")
  pcmd("  desc = ioctl_table_lookup(req & ~(IOC_SIZEMASK << IOC_SIZESHIFT));")
  pcmd("  // Sanity check: requests that encode access size are either read or write and")
  pcmd("  // have size of 0 in the table.")
  pcmd("  if (desc && desc->size == 0 &&")
  pcmd("      (desc->type == ioctl_desc::READWRITE || desc->type == ioctl_desc::WRITE ||")
  pcmd("       desc->type == ioctl_desc::READ))")
  pcmd("    return desc;")
  pcmd("  return nullptr;")
  pcmd("}")
  pcmd("")
  pcmd("static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,")
  pcmd("                             unsigned request, void *arg) {")
  pcmd("  if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) {")
  pcmd("    unsigned size = desc->size ? desc->size : IOC_SIZE(request);")
  pcmd("    COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);")
  pcmd("  }")
  pcmd("  if (desc->type != ioctl_desc::CUSTOM)")
  pcmd("    return;")
  pcmd("  if (request == IOCTL_SIOCGIFCONF) {")
  pcmd("    struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;")
  pcmd("    COMMON_INTERCEPTOR_READ_RANGE(ctx, (char*)&ifc->ifc_len,")
  pcmd("                                  sizeof(ifc->ifc_len));")
  pcmd("  }")
  pcmd("}")
  pcmd("")
  pcmd("static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d,")
  pcmd("                              unsigned request, void *arg) {")
  pcmd("  if (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READWRITE) {")
  pcmd("    // FIXME: add verbose output")
  pcmd("    unsigned size = desc->size ? desc->size : IOC_SIZE(request);")
  pcmd("    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);")
  pcmd("  }")
  pcmd("  if (desc->type != ioctl_desc::CUSTOM)")
  pcmd("    return;")
  pcmd("  if (request == IOCTL_SIOCGIFCONF) {")
  pcmd("    struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;")
  pcmd("    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len);")
  pcmd("  }")
  pcmd("}")
  pcmd("")
  pcmd("#endif // SANITIZER_NETBSD")

  close(cmd)
}

function usage()
{
  print "Usage: " script_name
  abnormal_exit = 1
  exit 1
}

function pcmd(string)
{
  print string | cmd
}

function get_type(string)
{
  if (string == "int") {
    return "sizeof(int)"
  } else if (string == "unsigned int" || string == "u_int" || string == "uint") {
    return "sizeof(unsigned int)"
  } else if (string == "long") {
    return "sizeof(long)"
  } else if (string == "unsigned long" || string == "u_long") {
    return "sizeof(unsigned long)"
  } else if (string == "short") {
    return "sizeof(short)"
  } else if (string == "unsigned short") {
    return "sizeof(unsigned short)"
  } else if (string == "char") {
    return "sizeof(char)"
  } else if (string == "signed char") {
    return "sizeof(signed char)"
  } else if (string == "unsigned char") {
    return "sizeof(unsigned char)"
  } else if (string == "uint8_t") {
    return "sizeof(u8)"
  } else if (string == "uint16_t") {
    return "sizeof(u16)"
  } else if (string == "u_int32_t" || string == "uint32_t") {
    return "sizeof(u32)"
  } else if (string ~ /\*$/) {
    return "sizeof(uptr)"
  } else if (string == "off_t") {
    return "sizeof(uptr)"
  } else if (string == "pid_t" || string == "kbd_t") {
    return "sizeof(int)"
  } else if (string == "daddr_t" || string == "dev_t") {
    return "sizeof(u64)"
  } else if (substr(string, 0, 7) == "struct " ) {
    gsub(/ /, "", string)
    return "struct_" substr(string, 7) "_sz"
  } else if (string == "scsireq_t") {
    return "struct_scsireq_sz"
  } else if (string == "tone_t") {
    return "struct_tone_sz"
  } else if (string == "union twe_statrequest") {
    return "union_twe_statrequest_sz"
  } else if (string == "usb_device_descriptor_t") {
    return "struct_usb_device_descriptor_sz"
  } else if (string == "v4l2_std_id") {
    return "sizeof(u64)"
  } else if (string == "vtmode_t") {
    return "struct_vt_mode_sz"
  } else if (string == "_old_mixer_info") {
    return "struct__old_mixer_info_sz"
  } else if (string == "agp_allocate") {
    return "struct__agp_allocate_sz"
  } else if (string == "agp_bind") {
    return "struct__agp_bind_sz"
  } else if (string == "agp_info") {
    return "struct__agp_info_sz"
  } else if (string == "agp_region") {
    return "struct__agp_region_sz"
  } else if (string == "agp_setup") {
    return "struct__agp_setup_sz"
  } else if (string == "agp_unbind") {
    return "struct__agp_unbind_sz"
  } else if (string == "atareq_t") {
    return "struct_atareq_sz"
  } else if (string == "cpustate_t") {
    return "struct_cpustate_sz"
  } else if (string == "dmx_caps_t") {
    return "struct_dmx_caps_sz"
  } else if (string == "dmx_source_t") {
    return "enum_dmx_source_sz"
  } else if (string == "dvd_authinfo") {
    return "union_dvd_authinfo_sz"
  } else if (string == "dvd_struct") {
    return "union_dvd_struct_sz"
  } else if (string == "enum v4l2_priority") {
    return "enum_v4l2_priority_sz"
  } else if (string == "envsys_basic_info_t") {
    return "struct_envsys_basic_info_sz"
  } else if (string == "envsys_tre_data_t") {
    return "struct_envsys_tre_data_sz"
  } else if (string == "ext_accm") {
    return "(8 * sizeof(u32))"
  } else if (string == "fe_sec_mini_cmd_t") {
    return "enum_fe_sec_mini_cmd_sz"
  } else if (string == "fe_sec_tone_mode_t") {
    return "enum_fe_sec_tone_mode_sz"
  } else if (string == "fe_sec_voltage_t") {
    return "enum_fe_sec_voltage_sz"
  } else if (string == "fe_status_t") {
    return "enum_fe_status_sz"
  } else if (string == "gdt_ctrt_t") {
    return "struct_gdt_ctrt_sz"
  } else if (string == "gdt_event_t") {
    return "struct_gdt_event_sz"
  } else if (string == "gdt_osv_t") {
    return "struct_gdt_osv_sz"
  } else if (string == "gdt_rescan_t") {
    return "struct_gdt_rescan_sz"
  } else if (string == "gdt_statist_t") {
    return "struct_gdt_statist_sz"
  } else if (string == "gdt_ucmd_t") {
    return "struct_gdt_ucmd_sz"
  } else if (string == "iscsi_conn_status_parameters_t") {
    return "struct_iscsi_conn_status_parameters_sz"
  } else if (string == "iscsi_get_version_parameters_t") {
    return "struct_iscsi_get_version_parameters_sz"
  } else if (string == "iscsi_iocommand_parameters_t") {
    return "struct_iscsi_iocommand_parameters_sz"
  } else if (string == "iscsi_login_parameters_t") {
    return "struct_iscsi_login_parameters_sz"
  } else if (string == "iscsi_logout_parameters_t") {
    return "struct_iscsi_logout_parameters_sz"
  } else if (string == "iscsi_register_event_parameters_t") {
    return "struct_iscsi_register_event_parameters_sz"
  } else if (string == "iscsi_remove_parameters_t") {
    return "struct_iscsi_remove_parameters_sz"
  } else if (string == "iscsi_send_targets_parameters_t") {
    return "struct_iscsi_send_targets_parameters_sz"
  } else if (string == "iscsi_set_node_name_parameters_t") {
    return "struct_iscsi_set_node_name_parameters_sz"
  } else if (string == "iscsi_wait_event_parameters_t") {
    return "struct_iscsi_wait_event_parameters_sz"
  } else if (string == "isp_stats_t") {
    return "struct_isp_stats_sz"
  } else if (string == "lsenable_t") {
    return "struct_lsenable_sz"
  } else if (string == "lsdisable_t") {
    return "struct_lsdisable_sz"
  } else if (string == "mixer_ctrl_t") {
    return "struct_mixer_ctrl_sz"
  } else if (string == "mixer_devinfo_t") {
    return "struct_mixer_devinfo_sz"
  } else if (string == "mpu_command_rec") {
    return "struct_mpu_command_rec_sz"
  } else if (string == "rndstat_t") {
    return "struct_rndstat_sz"
  } else if (string == "rndstat_name_t") {
    return "struct_rndstat_name_sz"
  } else if (string == "rndctl_t") {
    return "struct_rndctl_sz"
  } else if (string == "rnddata_t") {
    return "struct_rnddata_sz"
  } else if (string == "rndpoolstat_t") {
    return "struct_rndpoolstat_sz"
  } else if (string == "rndstat_est_t") {
    return "struct_rndstat_est_sz"
  } else if (string == "rndstat_est_name_t") {
    return "struct_rndstat_est_name_sz"
  } else if (string == "pps_params_t") {
    return "struct_pps_params_sz"
  } else if (string == "pps_info_t") {
    return "struct_pps_info_sz"
  } else if (string == "linedn_t") {
    return "(32 * sizeof(char))"
  } else if (string == "mixer_info") {
    return "struct_mixer_info_sz"
  } else if (string == "RF_SparetWait_t") {
    return "struct_RF_SparetWait_sz"
  } else if (string == "RF_ComponentLabel_t") {
    return "struct_RF_ComponentLabel_sz"
  } else if (string == "RF_SingleComponent_t") {
    return "struct_RF_SingleComponent_sz"
  } else if (string == "RF_ProgressInfo_t") {
    return "struct_RF_ProgressInfo_sz"
  } else {
    print "Unrecognized entry: " string
    print "Aborting"
    abnormal_exit = 1
    exit 1
  }

  return string
}

#!/usr/bin/awk -f

#===-- generate_netbsd_ioctls.awk ------------------------------------------===#
#
#                     The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===------------------------------------------------------------------------===#
#
# This file is a generator of:
#  - include/sanitizer/sanitizer_interceptors_ioctl_netbsd.inc
#
# This script reads public headers from a NetBSD host.
#
#===------------------------------------------------------------------------===#

BEGIN {
  # harcode the script name
  script_name = "generate_netbsd_ioctls.awk"
  outputinc = "../lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc"

  # assert that we are in the directory with scripts
  in_utils = system("test -f " script_name " && exit 1 || exit 0")
  if (in_utils == 0) {
    usage()
  }

  # assert 0 argument passed
  if (ARGC != 1) {
    usage()
  }

  # accept overloading CLANGFORMAT from environment
  clangformat = "clang-format"
  if ("CLANGFORMAT" in ENVIRON) {
    clangformat = ENVIRON["CLANGFORMAT"]
  }

  # accept overloading ROOTDIR from environment
  rootdir = "/usr/include/"
  if ("ROOTDIR" in ENVIRON) {
    rootdir = ENVIRON["ROOTDIR"]
  }

  # hardcode list of headers with ioctl(2) entries
  # List generated manually with the following script:
  #   for w in `find /usr/include/ -type f -name '*.h' -exec echo {} \;`; \
  #   do awk '/[^a-zA-Z0-9_]_IO[W]*[R]*[ ]*\(/ && $2 ~ /^[A-Z_]+$/ {got=1} END{if(got) {print ARGV[1]}}' $w; \
  #   done|awk '{print "  ARGV[ARGC++] = rootdir \"" substr($0, 14) "\""}'

  ARGV[ARGC++] = rootdir "altq/altq_afmap.h"
  ARGV[ARGC++] = rootdir "altq/altq.h"
  ARGV[ARGC++] = rootdir "altq/altq_blue.h"
  ARGV[ARGC++] = rootdir "altq/altq_cbq.h"
  ARGV[ARGC++] = rootdir "altq/altq_cdnr.h"
  ARGV[ARGC++] = rootdir "altq/altq_fifoq.h"
  ARGV[ARGC++] = rootdir "altq/altq_hfsc.h"
  ARGV[ARGC++] = rootdir "altq/altq_jobs.h"
  ARGV[ARGC++] = rootdir "altq/altq_priq.h"
  ARGV[ARGC++] = rootdir "altq/altq_red.h"
  ARGV[ARGC++] = rootdir "altq/altq_rio.h"
  ARGV[ARGC++] = rootdir "altq/altq_wfq.h"
  ARGV[ARGC++] = rootdir "crypto/cryptodev.h"
  ARGV[ARGC++] = rootdir "dev/apm/apmio.h"
  ARGV[ARGC++] = rootdir "dev/dm/netbsd-dm.h"
  ARGV[ARGC++] = rootdir "dev/dmover/dmover_io.h"
  ARGV[ARGC++] = rootdir "dev/dtv/dtvio_demux.h"
  ARGV[ARGC++] = rootdir "dev/dtv/dtvio_frontend.h"
  ARGV[ARGC++] = rootdir "dev/filemon/filemon.h"
  ARGV[ARGC++] = rootdir "dev/hdaudio/hdaudioio.h"
  ARGV[ARGC++] = rootdir "dev/hdmicec/hdmicecio.h"
  ARGV[ARGC++] = rootdir "dev/hpc/hpcfbio.h"
  ARGV[ARGC++] = rootdir "dev/i2o/iopio.h"
  ARGV[ARGC++] = rootdir "dev/ic/athioctl.h"
  ARGV[ARGC++] = rootdir "dev/ic/bt8xx.h"
  ARGV[ARGC++] = rootdir "dev/ic/hd44780var.h"
  ARGV[ARGC++] = rootdir "dev/ic/icp_ioctl.h"
  ARGV[ARGC++] = rootdir "dev/ic/isp_ioctl.h"
  ARGV[ARGC++] = rootdir "dev/ic/mlxio.h"
  ARGV[ARGC++] = rootdir "dev/ic/nvmeio.h"
  ARGV[ARGC++] = rootdir "dev/ir/irdaio.h"
  ARGV[ARGC++] = rootdir "dev/isa/satlinkio.h"
  ARGV[ARGC++] = rootdir "dev/isa/isvio.h"
  ARGV[ARGC++] = rootdir "dev/isa/wtreg.h"
  ARGV[ARGC++] = rootdir "dev/iscsi/iscsi_ioctl.h"
  ARGV[ARGC++] = rootdir "dev/ofw/openfirmio.h"
  ARGV[ARGC++] = rootdir "dev/pci/amrio.h"
  ARGV[ARGC++] = rootdir "dev/pci/mlyio.h"
  ARGV[ARGC++] = rootdir "dev/pci/pciio.h"
  ARGV[ARGC++] = rootdir "dev/pci/tweio.h"
  ARGV[ARGC++] = rootdir "dev/pcmcia/if_cnwioctl.h"
  ARGV[ARGC++] = rootdir "dev/pcmcia/if_rayreg.h"
  ARGV[ARGC++] = rootdir "dev/raidframe/raidframeio.h"
  ARGV[ARGC++] = rootdir "dev/sbus/mbppio.h"
  ARGV[ARGC++] = rootdir "dev/scsipi/ses.h"
  ARGV[ARGC++] = rootdir "dev/sun/disklabel.h"
  ARGV[ARGC++] = rootdir "dev/sun/fbio.h"
  ARGV[ARGC++] = rootdir "dev/sun/kbio.h"
  ARGV[ARGC++] = rootdir "dev/sun/vuid_event.h"
  ARGV[ARGC++] = rootdir "dev/tc/sticio.h"
  ARGV[ARGC++] = rootdir "dev/usb/ukyopon.h"
  ARGV[ARGC++] = rootdir "dev/usb/urio.h"
  ARGV[ARGC++] = rootdir "dev/usb/usb.h"
  ARGV[ARGC++] = rootdir "dev/usb/utoppy.h"
  ARGV[ARGC++] = rootdir "dev/vme/xio.h"
  ARGV[ARGC++] = rootdir "dev/wscons/wsdisplay_usl_io.h"
  ARGV[ARGC++] = rootdir "dev/wscons/wsconsio.h"
  ARGV[ARGC++] = rootdir "dev/biovar.h"
  ARGV[ARGC++] = rootdir "dev/md.h"
  ARGV[ARGC++] = rootdir "dev/ccdvar.h"
  ARGV[ARGC++] = rootdir "dev/cgdvar.h"
  ARGV[ARGC++] = rootdir "dev/fssvar.h"
  ARGV[ARGC++] = rootdir "dev/bluetooth/btdev.h"
  ARGV[ARGC++] = rootdir "dev/bluetooth/btsco.h"
  ARGV[ARGC++] = rootdir "dev/kttcpio.h"
  ARGV[ARGC++] = rootdir "dev/lockstat.h"
  ARGV[ARGC++] = rootdir "dev/vndvar.h"
  ARGV[ARGC++] = rootdir "dev/spkrio.h"
  ARGV[ARGC++] = rootdir "net/bpf.h"
  ARGV[ARGC++] = rootdir "net/if_atm.h"
  ARGV[ARGC++] = rootdir "net/if_gre.h"
  ARGV[ARGC++] = rootdir "net/if_ppp.h"
  ARGV[ARGC++] = rootdir "net/npf.h"
  ARGV[ARGC++] = rootdir "net/if_pppoe.h"
  ARGV[ARGC++] = rootdir "net/if_sppp.h"
  ARGV[ARGC++] = rootdir "net/if_srt.h"
  ARGV[ARGC++] = rootdir "net/if_tap.h"
  ARGV[ARGC++] = rootdir "net/if_tun.h"
  ARGV[ARGC++] = rootdir "net/pfvar.h"
  ARGV[ARGC++] = rootdir "net/slip.h"
  ARGV[ARGC++] = rootdir "netbt/hci.h"
  ARGV[ARGC++] = rootdir "netinet/ip_nat.h"
  ARGV[ARGC++] = rootdir "netinet/ip_proxy.h"
  ARGV[ARGC++] = rootdir "netinet6/in6_var.h"
  ARGV[ARGC++] = rootdir "netnatm/natm.h"
  ARGV[ARGC++] = rootdir "netsmb/smb_dev.h"
  ARGV[ARGC++] = rootdir "sys/agpio.h"
  ARGV[ARGC++] = rootdir "sys/audioio.h"
  ARGV[ARGC++] = rootdir "sys/ataio.h"
  ARGV[ARGC++] = rootdir "sys/cdio.h"
  ARGV[ARGC++] = rootdir "sys/chio.h"
  ARGV[ARGC++] = rootdir "sys/clockctl.h"
  ARGV[ARGC++] = rootdir "sys/cpuio.h"
  ARGV[ARGC++] = rootdir "sys/dkio.h"
  ARGV[ARGC++] = rootdir "sys/drvctlio.h"
  ARGV[ARGC++] = rootdir "sys/dvdio.h"
  ARGV[ARGC++] = rootdir "sys/envsys.h"
  ARGV[ARGC++] = rootdir "sys/event.h"
  ARGV[ARGC++] = rootdir "sys/fdio.h"
  ARGV[ARGC++] = rootdir "sys/filio.h"
  ARGV[ARGC++] = rootdir "sys/gpio.h"
  ARGV[ARGC++] = rootdir "sys/ioctl.h"
  ARGV[ARGC++] = rootdir "sys/ioctl_compat.h"
  ARGV[ARGC++] = rootdir "sys/joystick.h"
  ARGV[ARGC++] = rootdir "sys/ksyms.h"
  ARGV[ARGC++] = rootdir "sys/lua.h"
  ARGV[ARGC++] = rootdir "sys/midiio.h"
  ARGV[ARGC++] = rootdir "sys/mtio.h"
  ARGV[ARGC++] = rootdir "sys/power.h"
  ARGV[ARGC++] = rootdir "sys/radioio.h"
  ARGV[ARGC++] = rootdir "sys/rndio.h"
  ARGV[ARGC++] = rootdir "sys/scanio.h"
  ARGV[ARGC++] = rootdir "sys/scsiio.h"
  ARGV[ARGC++] = rootdir "sys/sockio.h"
  ARGV[ARGC++] = rootdir "sys/timepps.h"
  ARGV[ARGC++] = rootdir "sys/ttycom.h"
  ARGV[ARGC++] = rootdir "sys/verified_exec.h"
  ARGV[ARGC++] = rootdir "sys/videoio.h"
  ARGV[ARGC++] = rootdir "sys/wdog.h"
  ARGV[ARGC++] = rootdir "soundcard.h"
  ARGV[ARGC++] = rootdir "xen/xenio.h"

  ioctl_table_max = 0
}

# Scan RCS ID
FNR == 1 {
  fname[ioctl_table_max] = substr(FILENAME, length(rootdir) + 1)
}

# _IO
/[^a-zA-Z0-9_]_IO[W]*[R]*[ ]*\(/ && $2 ~ /^[A-Z_]+$/ {
  if ($0 ~ /RAIDFRAME_GET_ACCTOTALS/ ||
      $0 ~ /ALTQATTACH/ ||
      $0 ~ /ALTQDETACH/ ||
      $0 ~ /ALTQENABLE/ ||
      $0 ~ /ALTQDISABLE/ ||
      $0 ~ /ALTQCLEAR/ ||
      $0 ~ /ALTQCONFIG/ ||
      $0 ~ /ALTQADDCLASS/ ||
      $0 ~ /ALTQMODCLASS/ ||
      $0 ~ /ALTQDELCLASS/ ||
      $0 ~ /ALTQADDFILTER/ ||
      $0 ~ /ALTQDELFILTER/ ||
      $0 ~ /ALTQGETSTATS/ ||
      $0 ~ /ALTQGETCNTR/ ||
      $0 ~ /HFSC_IF_ATTACH/ ||
      $0 ~ /HFSC_MOD_CLASS/ ||
      $0 ~ /HLCD_DISPCTL/ ||
      $0 ~ /HLCD_RESET/ ||
      $0 ~ /HLCD_CLEAR/ ||
      $0 ~ /HLCD_CURSOR_LEFT/ ||
      $0 ~ /HLCD_CURSOR_RIGHT/ ||
      $0 ~ /HLCD_GET_CURSOR_POS/ ||
      $0 ~ /HLCD_SET_CURSOR_POS/ ||
      $0 ~ /HLCD_GETC/ ||
      $0 ~ /HLCD_PUTC/ ||
      $0 ~ /HLCD_SHIFT_LEFT/ ||
      $0 ~ /HLCD_SHIFT_RIGHT/ ||
      $0 ~ /HLCD_HOME/ ||
      $0 ~ /HLCD_WRITE/ ||
      $0 ~ /HLCD_READ/ ||
      $0 ~ /HLCD_REDRAW/ ||
      $0 ~ /HLCD_WRITE_INST/ ||
      $0 ~ /HLCD_WRITE_DATA/ ||
      $0 ~ /HLCD_GET_INFO/ ||
      $0 ~ /HLCD_GET_CHIPNO/ ||
      $0 ~ /HLCD_SET_CHIPNO/ ||
      $0 ~ /RAIDFRAME_TEST_ACC/ ||
      $0 ~ /FBIOGINFO/ ||
      $0 ~ /FBIOSATTR/ ||
      $0 ~ /OBIOCDISK/ ||
      $0 ~ /OBIOCVOL/ ||
      $0 ~ /BIOCSORTIMEOUT/ ||
      $0 ~ /BIOCGORTIMEOUT/ ||
      $0 ~ /PPPIOCSPASS/ ||
      $0 ~ /PPPIOCSACTIVE/ ||
      $0 ~ /PPPIOCSIPASS/ ||
      $0 ~ /PPPIOCSOPASS/ ||
      $0 ~ /PPPIOCSIACTIVE/ ||
      $0 ~ /PPPIOCSOACTIVE/ ||
      $0 ~ /SIOCPROXY/ ||
      $0 ~ /SIOCXRAWATM/ ||
      $0 ~ /AGPIOC_RESERVE/ ||
      $0 ~ /AGPIOC_PROTECT/ ||
      $0 ~ /CDIOCREADSUBCHANNEL_BUF/ ||
      $0 ~ /CDIOREADTOCENTRIES_BUF/ ||
      $0 ~ /MMCGETDISCINFO/ ||
      $0 ~ /MMCGETTRACKINFO/ ||
      $0 ~ /MMCOP/ ||
      $0 ~ /MMCSETUPWRITEPARAMS/ ||
      $0 ~ /DIOCGPARTINFO/ ||
      $0 ~ /ODIOCGDINFO/ ||
      $0 ~ /ODIOCSDINFO/ ||
      $0 ~ /ODIOCWDINFO/ ||
      $0 ~ /ODIOCGDEFLABEL/ ||
      $0 ~ /GPIOPINREAD/ ||
      $0 ~ /GPIOPINWRITE/ ||
      $0 ~ /GPIOPINTOGGLE/ ||
      $0 ~ /GPIOPINCTL/ ||
      $0 ~ /GPIODETACH/ ||
      $0 ~ /SEQUENCER_PERCMODE/ ||
      $0 ~ /SEQUENCER_TESTMIDI/ ||
      $0 ~ /SEQUENCER_MIDI_INFO/ ||
      $0 ~ /SEQUENCER_ID/ ||
      $0 ~ /SEQUENCER_CONTROL/ ||
      $0 ~ /SEQUENCER_REMOVESAMPLE/ ||
      $0 ~ /EVTCHN_RESET/ ||
      $0 ~ /EVTCHN_BIND/ ||
      $0 ~ /EVTCHN_UNBIND/) {
    # broken entry, incomplete definition of the 3rd parameterm etc
    next
  }

  if ($0 ~ /APM_IOC_STANDBY/ ||
      $0 ~ /APM_IOC_SUSPEND/ ||
      $0 ~ /SCIOC_USE_ADF/ ||
      $0 ~ /SCBUSIOLLSCAN/ ||
      $0 ~ /UTOPPYIOCANCEL/ ||
      $0 ~ /JOY_GET_X_OFFSET/ ||
      $0 ~ /CHIOGPICKER/ ||
      $0 ~ /SLIOCGUNIT/ ||
      $0 ~ /SATIOSBUFSIZE/ ||
      $0 ~ /TUNSLMODE/ ||
      $0 ~ /CBQ_IF_ATTACH/ ||
      $0 ~ /CDNR_IF_ATTACH/ ||
      $0 ~ /RIO_IF_ATTACH/ ||
      $0 ~ /CBQ_IF_DETACH/ ||
      $0 ~ /HFSC_IF_DETACH/ ||
      $0 ~ /WFQ_IF_DETACH/ ||
      $0 ~ /RIO_IF_DETACH/ ||
      $0 ~ /FIFOQ_IF_DETACH/ ||
      $0 ~ /RED_IF_DETACH/ ||
      $0 ~ /CDNR_ENABLE/ ||
      $0 ~ /HFSC_ENABLE/ ||
      $0 ~ /WFQ_ENABLE/ ||
      $0 ~ /RIO_ENABLE/ ||
      $0 ~ /FIFOQ_ENABLE/ ||
      $0 ~ /RED_ENABLE/ ||
      $0 ~ /BLUE_ENABLE/ ||
      $0 ~ /CDNR_DISABLE/ ||
      $0 ~ /HFSC_DISABLE/ ||
      $0 ~ /WFQ_DISABLE/ ||
      $0 ~ /RIO_DISABLE/ ||
      $0 ~ /FIFOQ_DISABLE/ ||
      $0 ~ /PRIQ_DISABLE/ ||
      $0 ~ /CDNR_DEL_FILTER/ ||
      $0 ~ /JOBS_DEL_CLASS/ ||
      $0 ~ /JOBS_DEL_FILTER/ ||
      $0 ~ /JOBS_GETSTATS/ ||
      $0 ~ /WFQ_GET_STATS/ ||
      $0 ~ /CBQ_ADD_FILTER/ ||
      $0 ~ /HFSC_ADD_FILTER/ ||
      $0 ~ /JOBS_ADD_FILTER/ ||
      $0 ~ /RED_IF_ATTACH/ ||
      $0 ~ /FIFOQ_IF_ATTACH/ ||
      $0 ~ /BLUE_IF_DETACH/ ||
      $0 ~ /CBQ_DISABLE/ ||
      $0 ~ /RED_DISABLE/ ||
      $0 ~ /CBQ_CLEAR_HIERARCHY/ ||
      $0 ~ /HFSC_DEL_CLASS/ ||
      $0 ~ /PRIQ_IF_DETACH/ ||
      $0 ~ /PRIQ_ENABLE/ ||
      $0 ~ /WFQ_IF_ATTACH/ ||
      $0 ~ /HFSC_DEL_FILTER/) {
    # There are entries with duplicate codes.. disable the less used ones
    next
  }

  if ($2 in known) {
    # Avoid duplicates
    # There are entries compatible with K&R and ANSI preprocessor
    next
  }

  known[$2] = 1

  ioctl_name[ioctl_table_max] = $2

  split($3, a, "(")
  a3 = a[1]
  if (a3 ~ /_IO[ ]*$/) {
    ioctl_mode[ioctl_table_max] = "NONE"
  } else if (a3 ~ /_IOR[ ]*$/) {
    ioctl_mode[ioctl_table_max] = "WRITE"
  } else if (a3 ~ /_IOW[ ]*$/) {
    ioctl_mode[ioctl_table_max] = "READ"
  } else if (a3 ~ /_IOWR[ ]*$/) {
    ioctl_mode[ioctl_table_max] = "READWRITE"
  } else {
    print "Unknown mode, cannot parse: '" $3 "'"
  }

  # This !NONE check allows to skip some unparsable entries
  if (ioctl_mode[ioctl_table_max] != "NONE") {
    # special cases first
    if ($0 ~ /POWER_IOC_GET_TYPE_WITH_LOSSAGE/) {
      ioctl_type[ioctl_table_max] = "sizeof(uptr)"
    } else {
      n = split($0, a, ",")
      if (n == 3) {
        gsub(/^[ ]+/, "", a[3])
        match(a[3], /[a-zA-Z0-9_* ]+/)
        type = get_type(substr(a[3], 0, RLENGTH))
        ioctl_type[ioctl_table_max] = type
      }
    }
  }

  ioctl_table_max++
}

END {
  # empty files?
  if (NR < 1 && !abnormal_exit) {
    usage()
  }

  # Handle abnormal exit
  if (abnormal_exit) {
    exit(abnormal_exit)
  }

  # Generate sanitizer_interceptors_ioctl_netbsd.inc

  # open pipe
  cmd = clangformat " > " outputinc

  pcmd("//===-- sanitizer_interceptors_ioctl_netbsd.inc -----------------*- C++ -*-===//")
  pcmd("//")
  pcmd("//                     The LLVM Compiler Infrastructure")
  pcmd("//")
  pcmd("// This file is distributed under the University of Illinois Open Source")
  pcmd("// License. See LICENSE.TXT for details.")
  pcmd("//")
  pcmd("//===----------------------------------------------------------------------===//")
  pcmd("//")
  pcmd("// Ioctl handling in common sanitizer interceptors.")
  pcmd("//===----------------------------------------------------------------------===//")
  pcmd("")
  pcmd("#if SANITIZER_NETBSD")
  pcmd("")
  pcmd("#include \"sanitizer_flags.h\"")
  pcmd("")
  pcmd("struct ioctl_desc {")
  pcmd("  unsigned req;")
  pcmd("  // FIXME: support read+write arguments. Currently READWRITE and WRITE do the")
  pcmd("  // same thing.")
  pcmd("  // XXX: The declarations below may use WRITE instead of READWRITE, unless")
  pcmd("  // explicitly noted.")
  pcmd("  enum {")
  pcmd("    NONE,")
  pcmd("    READ,")
  pcmd("    WRITE,")
  pcmd("    READWRITE,")
  pcmd("    CUSTOM")
  pcmd("  } type : 3;")
  pcmd("  unsigned size : 29;")
  pcmd("  const char* name;")
  pcmd("};")
  pcmd("")
  pcmd("const unsigned ioctl_table_max = " ioctl_table_max ";")
  pcmd("static ioctl_desc ioctl_table[ioctl_table_max];")
  pcmd("static unsigned ioctl_table_size = 0;")
  pcmd("")
  pcmd("// This can not be declared as a global, because references to struct_*_sz")
  pcmd("// require a global initializer. And this table must be available before global")
  pcmd("// initializers are run.")
  pcmd("static void ioctl_table_fill() {")
  pcmd("#define _(rq, tp, sz)                                    \\")
  pcmd("  if (IOCTL_##rq != IOCTL_NOT_PRESENT) {                 \\")
  pcmd("    CHECK(ioctl_table_size < ioctl_table_max);           \\")
  pcmd("    ioctl_table[ioctl_table_size].req = IOCTL_##rq;      \\")
  pcmd("    ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \\")
  pcmd("    ioctl_table[ioctl_table_size].size = sz;             \\")
  pcmd("    ioctl_table[ioctl_table_size].name = #rq;            \\")
  pcmd("    ++ioctl_table_size;                                  \\")
  pcmd("  }")
  pcmd("")

  for (i = 0; i < ioctl_table_max; i++) {
    if (i in fname) {
      pcmd("  /* Entries from file: " fname[i] " */")
    }

    if (i in ioctl_type) {
      type = ioctl_type[i]
    } else {
      type = "0"
    }

    pcmd("  _(" ioctl_name[i] ", " ioctl_mode[i] "," type ");")
  }

  pcmd("#undef _")
  pcmd("}")
  pcmd("")
  pcmd("static bool ioctl_initialized = false;")
  pcmd("")
  pcmd("struct ioctl_desc_compare {")
  pcmd("  bool operator()(const ioctl_desc& left, const ioctl_desc& right) const {")
  pcmd("    return left.req < right.req;")
  pcmd("  }")
  pcmd("};")
  pcmd("")
  pcmd("static void ioctl_init() {")
  pcmd("  ioctl_table_fill();")
  pcmd("  Sort(ioctl_table, ioctl_table_size, ioctl_desc_compare());")
  pcmd("")
  pcmd("  bool bad = false;")
  pcmd("  for (unsigned i = 0; i < ioctl_table_size - 1; ++i) {")
  pcmd("    if (ioctl_table[i].req >= ioctl_table[i + 1].req) {")
  pcmd("      Printf(\"Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\\n\",")
  pcmd("             ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name,")
  pcmd("             ioctl_table[i + 1].name);")
  pcmd("      bad = true;")
  pcmd("    }")
  pcmd("  }")
  pcmd("")
  pcmd("  if (bad) Die();")
  pcmd("")
  pcmd("  ioctl_initialized = true;")
  pcmd("}")
  pcmd("")
  pcmd("static const ioctl_desc *ioctl_table_lookup(unsigned req) {")
  pcmd("  int left = 0;")
  pcmd("  int right = ioctl_table_size;")
  pcmd("  while (left < right) {")
  pcmd("    int mid = (left + right) / 2;")
  pcmd("    if (ioctl_table[mid].req < req)")
  pcmd("      left = mid + 1;")
  pcmd("    else")
  pcmd("      right = mid;")
  pcmd("  }")
  pcmd("  if (left == right && ioctl_table[left].req == req)")
  pcmd("    return ioctl_table + left;")
  pcmd("  else")
  pcmd("    return nullptr;")
  pcmd("}")
  pcmd("")
  pcmd("static bool ioctl_decode(unsigned req, ioctl_desc *desc) {")
  pcmd("  CHECK(desc);")
  pcmd("  desc->req = req;")
  pcmd("  desc->name = \"<DECODED_IOCTL>\";")
  pcmd("  desc->size = IOC_SIZE(req);")
  pcmd("  // Sanity check.")
  pcmd("  if (desc->size > 0xFFFF) return false;")
  pcmd("  unsigned dir = IOC_DIR(req);")
  pcmd("  switch (dir) {")
  pcmd("    case IOC_NONE:")
  pcmd("      desc->type = ioctl_desc::NONE;")
  pcmd("      break;")
  pcmd("    case IOC_READ | IOC_WRITE:")
  pcmd("      desc->type = ioctl_desc::READWRITE;")
  pcmd("      break;")
  pcmd("    case IOC_READ:")
  pcmd("      desc->type = ioctl_desc::WRITE;")
  pcmd("      break;")
  pcmd("    case IOC_WRITE:")
  pcmd("      desc->type = ioctl_desc::READ;")
  pcmd("      break;")
  pcmd("    default:")
  pcmd("      return false;")
  pcmd("  }")
  pcmd("  // Size can be 0 iff type is NONE.")
  pcmd("  if ((desc->type == IOC_NONE) != (desc->size == 0)) return false;")
  pcmd("  // Sanity check.")
  pcmd("  if (IOC_TYPE(req) == 0) return false;")
  pcmd("  return true;")
  pcmd("}")
  pcmd("")
  pcmd("static const ioctl_desc *ioctl_lookup(unsigned req) {")
  pcmd("  const ioctl_desc *desc = ioctl_table_lookup(req);")
  pcmd("  if (desc) return desc;")
  pcmd("")
  pcmd("  // Try stripping access size from the request id.")
  pcmd("  desc = ioctl_table_lookup(req & ~(IOC_SIZEMASK << IOC_SIZESHIFT));")
  pcmd("  // Sanity check: requests that encode access size are either read or write and")
  pcmd("  // have size of 0 in the table.")
  pcmd("  if (desc && desc->size == 0 &&")
  pcmd("      (desc->type == ioctl_desc::READWRITE || desc->type == ioctl_desc::WRITE ||")
  pcmd("       desc->type == ioctl_desc::READ))")
  pcmd("    return desc;")
  pcmd("  return nullptr;")
  pcmd("}")
  pcmd("")
  pcmd("static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,")
  pcmd("                             unsigned request, void *arg) {")
  pcmd("  if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) {")
  pcmd("    unsigned size = desc->size ? desc->size : IOC_SIZE(request);")
  pcmd("    COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);")
  pcmd("  }")
  pcmd("  if (desc->type != ioctl_desc::CUSTOM)")
  pcmd("    return;")
  pcmd("  if (request == IOCTL_SIOCGIFCONF) {")
  pcmd("    struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;")
  pcmd("    COMMON_INTERCEPTOR_READ_RANGE(ctx, (char*)&ifc->ifc_len,")
  pcmd("                                  sizeof(ifc->ifc_len));")
  pcmd("  }")
  pcmd("}")
  pcmd("")
  pcmd("static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d,")
  pcmd("                              unsigned request, void *arg) {")
  pcmd("  if (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READWRITE) {")
  pcmd("    // FIXME: add verbose output")
  pcmd("    unsigned size = desc->size ? desc->size : IOC_SIZE(request);")
  pcmd("    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);")
  pcmd("  }")
  pcmd("  if (desc->type != ioctl_desc::CUSTOM)")
  pcmd("    return;")
  pcmd("  if (request == IOCTL_SIOCGIFCONF) {")
  pcmd("    struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;")
  pcmd("    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len);")
  pcmd("  }")
  pcmd("}")
  pcmd("")
  pcmd("#endif // SANITIZER_NETBSD")

  close(cmd)
}

function usage()
{
  print "Usage: " script_name
  abnormal_exit = 1
  exit 1
}

function pcmd(string)
{
  print string | cmd
}

function get_type(string)
{
  if (string == "int") {
    return "sizeof(int)"
  } else if (string == "unsigned int" || string == "u_int" || string == "uint") {
    return "sizeof(unsigned int)"
  } else if (string == "long") {
    return "sizeof(long)"
  } else if (string == "unsigned long" || string == "u_long") {
    return "sizeof(unsigned long)"
  } else if (string == "short") {
    return "sizeof(short)"
  } else if (string == "unsigned short") {
    return "sizeof(unsigned short)"
  } else if (string == "char") {
    return "sizeof(char)"
  } else if (string == "signed char") {
    return "sizeof(signed char)"
  } else if (string == "unsigned char") {
    return "sizeof(unsigned char)"
  } else if (string == "uint8_t") {
    return "sizeof(u8)"
  } else if (string == "uint16_t") {
    return "sizeof(u16)"
  } else if (string == "u_int32_t" || string == "uint32_t") {
    return "sizeof(u32)"
  } else if (string ~ /\*$/) {
    return "sizeof(uptr)"
  } else if (string == "off_t") {
    return "sizeof(uptr)"
  } else if (string == "pid_t" || string == "kbd_t") {
    return "sizeof(int)"
  } else if (string == "daddr_t" || string == "dev_t") {
    return "sizeof(u64)"
  } else if (substr(string, 0, 7) == "struct " ) {
    gsub(/ /, "", string)
    return "struct_" substr(string, 7) "_sz"
  } else if (string == "scsireq_t") {
    return "struct_scsireq_sz"
  } else if (string == "tone_t") {
    return "struct_tone_sz"
  } else if (string == "union twe_statrequest") {
    return "union_twe_statrequest_sz"
  } else if (string == "usb_device_descriptor_t") {
    return "struct_usb_device_descriptor_sz"
  } else if (string == "v4l2_std_id") {
    return "sizeof(u64)"
  } else if (string == "vtmode_t") {
    return "struct_vt_mode_sz"
  } else if (string == "_old_mixer_info") {
    return "struct__old_mixer_info_sz"
  } else if (string == "agp_allocate") {
    return "struct__agp_allocate_sz"
  } else if (string == "agp_bind") {
    return "struct__agp_bind_sz"
  } else if (string == "agp_info") {
    return "struct__agp_info_sz"
  } else if (string == "agp_region") {
    return "struct__agp_region_sz"
  } else if (string == "agp_setup") {
    return "struct__agp_setup_sz"
  } else if (string == "agp_unbind") {
    return "struct__agp_unbind_sz"
  } else if (string == "atareq_t") {
    return "struct_atareq_sz"
  } else if (string == "cpustate_t") {
    return "struct_cpustate_sz"
  } else if (string == "dmx_caps_t") {
    return "struct_dmx_caps_sz"
  } else if (string == "dmx_source_t") {
    return "enum_dmx_source_sz"
  } else if (string == "dvd_authinfo") {
    return "union_dvd_authinfo_sz"
  } else if (string == "dvd_struct") {
    return "union_dvd_struct_sz"
  } else if (string == "enum v4l2_priority") {
    return "enum_v4l2_priority_sz"
  } else if (string == "envsys_basic_info_t") {
    return "struct_envsys_basic_info_sz"
  } else if (string == "envsys_tre_data_t") {
    return "struct_envsys_tre_data_sz"
  } else if (string == "ext_accm") {
    return "(8 * sizeof(u32))"
  } else if (string == "fe_sec_mini_cmd_t") {
    return "enum_fe_sec_mini_cmd_sz"
  } else if (string == "fe_sec_tone_mode_t") {
    return "enum_fe_sec_tone_mode_sz"
  } else if (string == "fe_sec_voltage_t") {
    return "enum_fe_sec_voltage_sz"
  } else if (string == "fe_status_t") {
    return "enum_fe_status_sz"
  } else if (string == "gdt_ctrt_t") {
    return "struct_gdt_ctrt_sz"
  } else if (string == "gdt_event_t") {
    return "struct_gdt_event_sz"
  } else if (string == "gdt_osv_t") {
    return "struct_gdt_osv_sz"
  } else if (string == "gdt_rescan_t") {
    return "struct_gdt_rescan_sz"
  } else if (string == "gdt_statist_t") {
    return "struct_gdt_statist_sz"
  } else if (string == "gdt_ucmd_t") {
    return "struct_gdt_ucmd_sz"
  } else if (string == "iscsi_conn_status_parameters_t") {
    return "struct_iscsi_conn_status_parameters_sz"
  } else if (string == "iscsi_get_version_parameters_t") {
    return "struct_iscsi_get_version_parameters_sz"
  } else if (string == "iscsi_iocommand_parameters_t") {
    return "struct_iscsi_iocommand_parameters_sz"
  } else if (string == "iscsi_login_parameters_t") {
    return "struct_iscsi_login_parameters_sz"
  } else if (string == "iscsi_logout_parameters_t") {
    return "struct_iscsi_logout_parameters_sz"
  } else if (string == "iscsi_register_event_parameters_t") {
    return "struct_iscsi_register_event_parameters_sz"
  } else if (string == "iscsi_remove_parameters_t") {
    return "struct_iscsi_remove_parameters_sz"
  } else if (string == "iscsi_send_targets_parameters_t") {
    return "struct_iscsi_send_targets_parameters_sz"
  } else if (string == "iscsi_set_node_name_parameters_t") {
    return "struct_iscsi_set_node_name_parameters_sz"
  } else if (string == "iscsi_wait_event_parameters_t") {
    return "struct_iscsi_wait_event_parameters_sz"
  } else if (string == "isp_stats_t") {
    return "struct_isp_stats_sz"
  } else if (string == "lsenable_t") {
    return "struct_lsenable_sz"
  } else if (string == "lsdisable_t") {
    return "struct_lsdisable_sz"
  } else if (string == "mixer_ctrl_t") {
    return "struct_mixer_ctrl_sz"
  } else if (string == "mixer_devinfo_t") {
    return "struct_mixer_devinfo_sz"
  } else if (string == "mpu_command_rec") {
    return "struct_mpu_command_rec_sz"
  } else if (string == "rndstat_t") {
    return "struct_rndstat_sz"
  } else if (string == "rndstat_name_t") {
    return "struct_rndstat_name_sz"
  } else if (string == "rndctl_t") {
    return "struct_rndctl_sz"
  } else if (string == "rnddata_t") {
    return "struct_rnddata_sz"
  } else if (string == "rndpoolstat_t") {
    return "struct_rndpoolstat_sz"
  } else if (string == "rndstat_est_t") {
    return "struct_rndstat_est_sz"
  } else if (string == "rndstat_est_name_t") {
    return "struct_rndstat_est_name_sz"
  } else if (string == "pps_params_t") {
    return "struct_pps_params_sz"
  } else if (string == "pps_info_t") {
    return "struct_pps_info_sz"
  } else if (string == "linedn_t") {
    return "(32 * sizeof(char))"
  } else if (string == "mixer_info") {
    return "struct_mixer_info_sz"
  } else if (string == "RF_SparetWait_t") {
    return "struct_RF_SparetWait_sz"
  } else if (string == "RF_ComponentLabel_t") {
    return "struct_RF_ComponentLabel_sz"
  } else if (string == "RF_SingleComponent_t") {
    return "struct_RF_SingleComponent_sz"
  } else if (string == "RF_ProgressInfo_t") {
    return "struct_RF_ProgressInfo_sz"
  } else {
    print "Unrecognized entry: " string
    print "Aborting"
    abnormal_exit = 1
    exit 1
  }

  return string
}


Drop unused functions.

Drop unused functions.

function printUrlQueryString(queryString, j)
{
    split(queryString, pairs, "&")
    for (j = 1; j < len; ++j) {
        split(pairs[j], keyValue, "=")
        k = keyValue[1]
        v = keyValue[2]
        result[k] = v
    }
    return result
}

function base64Decode(thing)
{
  "echo "$thing" | base64 --decode" | getline x
  return x
}

function urlDecode(url, i) {
    for (i = 0x20; i < 0x40; ++i) {
        repl = sprintf("%c", i);
        if ((repl == "&") || (repl == "\\")) {
            repl = "\\" repl;
        }
        url = gensub(sprintf("%%%02X", i), repl, "g", url);
        url = gensub(sprintf("%%%02x", i), repl, "g", url);
    }
    return url;
}

BEGIN {

}

function enrich(property, n, j)
{
    if ("cs-uri-query" == property) {
        queryString = logs[n][property]
        delete logs[n][property]
        parsed = urlDecode(queryString)
        split(queryString, pairs, "&")
        len = length(pairs)
        for (j = 1; j < len; ++j) {
            split(pairs[j], keyValue, "=")
            k = keyValue[1]
            v = keyValue[2]
            result[k] = v
            logs[n][property][k] = v
        }
    }
}

END {
    print "{"
    printf "\"version\": \"%s\",\n", version
    print "\"records\": ["
    numLogs = length(logs)
    i = 1
    for (lineNr in logs)
    {
        printf "{\n";
        j = 1
        for (j = 1; j < numFields; j++)
        {
            field = fields[j]
            enrich(field, lineNr)
            if(isarray(logs[lineNr][field])) {
                printf "\"%s\": {\n", field
                k = 1
                numSubFields = length(logs[lineNr][field])
                for (subField in logs[lineNr][field]) {
                    printf "\"%s\": \"%s\"", subField, logs[lineNr][field][subField]
                    if (k < numSubFields) {
                        printf ","
                    }
                    k++
                    printf "\n"
                }
                print "}"
            } else {
                printf "\"%s\": \"%s\"", field, logs[lineNr][field]
            }
            if (j + 1 < numFields) {
                printf ","
            }
            printf "\n"
        }
        printf "}"
        if (i < numLogs) {
            printf ","
        }
        printf "\n"
        i++
    }
    print "]"
    print "}"
}

/^#Version: / {
    version = substr($0, length("#Version: ") + 1)
}

/^#Fields: / {
    rest = substr($0, length("#Fields: ") + 1)
    split(rest, fields, " ")
    numFields = length(fields)
}

/^#/ {
    # ignore anything else starting with "#"
}

! /^#/ {
    split($0, fieldsThisLine, " ")
    numFieldsThisLine = length(fieldsThisLine)
    for (i = 1; i < numFieldsThisLine; i++)
    {
         logs[NR][fields[i]] = fieldsThisLine[i]
    }
}