]> git.saurik.com Git - apple/mdnsresponder.git/blame - Clients/dnssdutil/dns-rcode-func-autogen
mDNSResponder-1310.80.1.tar.gz
[apple/mdnsresponder.git] / Clients / dnssdutil / dns-rcode-func-autogen
CommitLineData
19fa75a9
A
1#! /bin/bash
2#
3# Copyright (c) 2020 Apple Inc. All rights reserved.
4#
5
6declare -r version=1.0
7declare -r script=${BASH_SOURCE[0]}
8declare -r rcodesURL='https://www.iana.org/assignments/dns-parameters/dns-parameters-6.csv'
9
10#============================================================================================================================
11
12PrintHelp()
13{
14 echo ""
15 echo "Usage: $( basename "${script}" ) [options]"
16 echo ""
17 echo "Options:"
18 echo " -h Display script usage."
19 echo " -V Display version of this script and exit."
20 echo ""
21 echo "This script writes C functions to convert DNS RCODE values to strings and vice versa to stdout"
22 echo "based on the latest DNS RCODE data available at"
23 echo ""
24 echo " ${rcodesURL}"
25 echo ""
26}
27
28#============================================================================================================================
29
30ErrQuit()
31{
32 echo "error: $*" 1>&2
33 exit 1
34}
35
36#============================================================================================================================
37
38StripLeadingTrailingWhitespace()
39{
40 sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
41}
42
43#============================================================================================================================
44
45GetNamesAndValues()
46{
47 shopt -s nocasematch
48 while IFS=',' read value name others; do
49 name=$( StripLeadingTrailingWhitespace <<< "${name}" )
50 [[ ${name} =~ ^unassigned$ ]] && continue
51
52 value=$( StripLeadingTrailingWhitespace <<< "${value}" )
53 [[ ${value} =~ ^[0-9]+$ ]] || continue
54 [ "${value}" -le 15 ] || continue
55
56 echo "${name},${value}"
57 done
58 shopt -u nocasematch
59}
60
61#============================================================================================================================
62
63RCodeMnemonicToEnum()
64{
65 name="${1//[^A-Za-z0-9_]/_}" # Only allow alphanumeric and underscore characters.
66 printf "kDNSRCode_${name}"
67}
68
69#============================================================================================================================
70
71PrintRCodeEnums()
72{
73 local -r inputFile=${1}
74 printf "typedef enum\n"
75 printf "{\n"
76 local sep=""
77 < "${inputFile}" sort --field-separator=, --key=2,2 --numeric-sort --unique |
78 while IFS=',' read name value; do
79 printf "%b" "${sep}"
80 local enum=$( RCodeMnemonicToEnum "${name}" )
81 printf "\t%-20s= %d" "${enum}" "${value}"
82 sep=",\n"
83 done
84 printf "\n"
85 printf "\t\n"
86 printf "}\tDNSRCode;\n"
87}
88
89#============================================================================================================================
90
91PrintValueToStringElseIf()
92{
93 local -r first=${1}
94 local -r last=${2}
95 [ "${first}" -le "${last}" ] || ErrQuit "${first} > ${last}"
96 shift 2
97 local stringArray=( "$@" )
98
99 if [ "${last}" -ne "${first}" ]; then
100 printf "\telse if( ( inValue >= ${first} ) && ( inValue <= ${last} ) )\n"
101 local -r arrayVarName="sNames_${first}_${last}"
102 else
103 printf "\telse if( inValue == ${first} )\n"
104 local -r arrayVarName="sNames_${first}"
105 fi
106 printf "\t{\n"
107 printf "\t\tstatic const char * const\t\t${arrayVarName}[] =\n"
108 printf "\t\t{\n"
109 local value=${first}
110 for string in "${stringArray[@]}"; do
111 printf "\t\t\t%-15s // %3d\n" "\"${string}\"," "${value}"
112 value=$(( value + 1 ))
113 done
114 local -r stringCount=$(( value - first ))
115 local -r expectedCount=$(( last - first + 1 ))
116 [ "${stringCount}" -eq "${expectedCount}" ] || ErrQuit "${stringCount} != ${expectedCount}"
117 printf "\t\t};\n"
118 printf "\t\tstring = ${arrayVarName}[ inValue - ${first} ];\n"
119 printf "\t}\n"
120}
121
122#============================================================================================================================
123
124PrintValueToStringFunction()
125{
126 local -r inputFile=${1}
127 printf "const char *\tDNSRCodeToString( const int inValue )\n"
128 printf "{\n"
129 printf "\tswitch( inValue )\n"
130 printf "\t{\n"
131 < "${inputFile}" sort --field-separator=, --key=2,2 --numeric-sort --unique |
132 {
133 local stringArray=()
134 while IFS=',' read name value; do
135 local enum=$( RCodeMnemonicToEnum "${name}" )
136 printf "\t\t%-28s%s\n" "case ${enum}:" "return( \"${name}\" );"
137 done
138 }
139 printf "\t\t%-28sreturn( NULL );\n" "default:"
140 printf "\t}\n"
141 printf "}\n"
142}
143
144#============================================================================================================================
145
146PrintStringToValueFunction()
147{
148 local -r inputFile=${1}
149 printf "#include <stdlib.h>\n"
150 printf "\n"
151 printf "typedef struct\n"
152 printf "{\n"
153 printf "\tconst char *\t\tname;\n"
154 printf "\tint\t\t\t\t\tvalue;\n"
155 printf "\t\n"
156 printf "}\t_DNSRCodeTableEntry;\n"
157 printf "\n"
158 printf "static int\t_DNSRCodeFromStringCmp( const void *inKey, const void *inElement );\n"
159 printf "\n"
160 printf "int\tDNSRCodeFromString( const char * const inString )\n"
161 printf "{\n"
162 printf "\t// The name-value table is sorted by name in ascending lexicographical order to allow going from name to\n"
163 printf "\t// value in logarithmic time via a binary search.\n"
164 printf "\t\n"
165 printf "\tstatic const _DNSRCodeTableEntry\t\tsTable[] =\n"
166 printf "\t{\n"
167
168 local sep=""
169 < "${inputFile}" sort --field-separator=, --key=1,1 --ignore-case --unique |
170 while IFS=',' read name value; do
171 printf "%b" "${sep}"
172 local enum=$( RCodeMnemonicToEnum "${name}" )
173 printf "\t\t%-16s%-20s}" "{ \"${name}\"," "${enum}"
174 sep=",\n"
175 done
176 printf "\n"
177 printf "\t};\n"
178 printf "\tconst _DNSRCodeTableEntry *\t\t\tentry;\n"
179 printf "\t\n"
180 printf "\tentry = (_DNSRCodeTableEntry *) bsearch( inString, sTable, sizeof( sTable ) / sizeof( sTable[ 0 ] ),\n"
181 printf "\t\tsizeof( sTable[ 0 ] ), _DNSRCodeFromStringCmp );\n"
182 printf "\treturn( entry ? entry->value : -1 );\n"
183 printf "}\n"
184 printf "\n"
185 printf "static int\t_DNSRCodeFromStringCmp( const void * const inKey, const void * const inElement )\n"
186 printf "{\n"
187 printf "\tconst _DNSRCodeTableEntry * const\t\tentry = (const _DNSRCodeTableEntry *) inElement;\n"
188 printf "\treturn( strcasecmp( (const char *) inKey, entry->name ) );\n"
189 printf "}\n"
190}
191
192#============================================================================================================================
193
194ExitHandler()
195{
196 if [ -d "${tempDir}" ]; then
197 rm -fr "${tempDir}"
198 fi
199}
200
201#============================================================================================================================
202
203PrintAutoGenNote()
204{
205 printf "// This code was autogenerated on $( date -u '+%Y-%m-%d' ) by $( basename ${script} ) version ${version}\n"
206 printf "// Data source URL: ${rcodesURL}\n"
207 printf "\n"
208}
209
210#============================================================================================================================
211
212main()
213{
214 while getopts ":hO:V" option; do
215 case "${option}" in
216 h)
217 PrintHelp
218 exit 0
219 ;;
220 V)
221 echo "$( basename "${script}" ) version ${version}"
222 exit 0
223 ;;
224 :)
225 ErrQuit "option '${OPTARG}' requires an argument."
226 ;;
227 *)
228 ErrQuit "unknown option '${OPTARG}'."
229 ;;
230 esac
231 done
232
233 [ "${OPTIND}" -gt "$#" ] || ErrQuit "unexpected argument \"${!OPTIND}\"."
234
235 trap ExitHandler EXIT
236 tempDir=$( mktemp -d ) || ErrQuit "Failed to make temporary directory."
237 declare -r originalRCodesFile="${tempDir}/rcodesOriginal.csv"
238 curl --output "${originalRCodesFile}" "${rcodesURL}" || ErrQuit "Failed to download CSV file."
239
240 declare -r rcodesFile="${tempDir}/rcodes.csv"
241 < "${originalRCodesFile}" GetNamesAndValues > "${rcodesFile}"
242
243 declare -r tempFile="${tempDir}/temp.csv"
244 < "${rcodesFile}" sort --field-separator=, --key=2,2 --unique --numeric-sort > "${tempFile}"
245 < "${tempFile}" sort --field-separator=, --key=1,1 --unique --ignore-case > "${rcodesFile}"
246
247 PrintAutoGenNote
248 PrintRCodeEnums "${rcodesFile}"
249 printf "\n"
250 PrintAutoGenNote
251 PrintValueToStringFunction "${rcodesFile}"
252 printf "\n"
253 PrintAutoGenNote
254 PrintStringToValueFunction "${rcodesFile}"
255}
256
257main "$@"