xref: /freebsd/usr.sbin/bsdconfig/timezone/share/iso3166.subr (revision e9ac41698b2f322d55ccf9da50a3596edb2c1800)
1if [ ! "$_TIMEZONE_ISO3166_SUBR" ]; then _TIMEZONE_ISO3166_SUBR=1
2#
3# Copyright (c) 2011-2012 Devin Teske
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26#
27#
28############################################################ INCLUDES
29
30BSDCFG_SHARE="/usr/share/bsdconfig"
31. $BSDCFG_SHARE/common.subr || exit 1
32f_dprintf "%s: loading includes..." timezone/iso3166.subr
33
34BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="090.timezone"
35f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
36
37############################################################ CONFIGURATION
38
39#
40# Standard pathnames
41#
42_PATH_ISO3166="/usr/share/misc/iso3166"
43
44#
45# Export required i18n messages for awk(1) ENVIRON visibility
46#
47export msg_country_code_multiply_defined
48export msg_invalid_code
49export msg_invalid_format
50
51############################################################ FUNCTIONS
52
53# f_read_iso3166_table
54#
55# Read the ISO 3166 country code database in _PATH_ISO3166:
56# 	/usr/share/misc/iso3166 on FreeBSD
57# 	/usr/share/zoneinfo/iso3166.tab on Linux, Mac OS X, and Cygwin
58#
59# The format of this file on FreeBSD is:
60# 	two	three	number	name
61#
62# The format of this file on Linux, Mac OS X, and Cygwin is:
63# 	two	name
64#
65# With each of the following elements (described below) being separated by a
66# single tab character:
67#
68# 	two      ISO 3166 2-character country code
69# 	three    ISO 3166 3-character country code (if provided)
70# 	number   ISO 3166 numeric country code (if provided)
71# 	name     Human-readable country name (may contain spaces)
72#
73# Variables created by this function:
74#
75# 	COUNTRIES
76# 		A space-separated list of 2-character country codes.
77# 	country_CODE_name
78# 		The country `name' (as described above).
79#
80# where CODE is the 2-character country code.
81#
82# This function is a two-parter. Below is the awk(1) portion of the function,
83# afterward is the sh(1) function which utilizes the below awk script.
84#
85f_read_iso3166_table_awk='
86# Variables that should be defined on the invocation line:
87# 	-v progname="progname"
88#
89BEGIN {
90	lineno = 0
91	failed = 0
92}
93function die(fmt, argc, argv)
94{
95	printf "f_die 1 \"%%s: %s\" \"%s\"", fmt, progname
96	for (n = 1; n <= argc; n++)
97		printf " \"%s\"", argv[n]
98	print ""
99	failed++
100	exit 1
101}
102function add_country(tlc, name)
103{
104	if (country_name[tlc])
105	{
106		argv[1] = FILENAME
107		argv[2] = lineno
108		argv[3] = tlc
109		argv[4] = name
110		die(ENVIRON["msg_country_code_multiply_defined"], 4, argv)
111	}
112
113	country_name[tlc] = name
114}
115function print_country_name(tlc)
116{
117	name = country_name[tlc]
118	gsub(/"/, "\\\"", name)
119	printf "country_%s_name=\"%s\"\n", tlc, name
120	printf "export country_%s_name\n", tlc
121}
122/^#/ {
123	lineno++
124	next
125}
126!/^#/ {
127	lineno++
128
129	# Split the current record (on TAB) into an array
130	split($0, line, /\t/)
131
132	# Get the ISO3166-1 (Alpha 1) 2-letter country code
133	tlc = line[1]
134
135	#
136	# Validate the two-character country code
137	#
138	if (length(tlc) != 2)
139	{
140		argv[1] = FILENAME
141		argv[2] = lineno
142		die(ENVIRON["msg_invalid_format"], 2, argv)
143	}
144	if (!match(tlc, /^[A-Z][A-Z]$/))
145	{
146		argv[1] = FILENAME
147		argv[2] = lineno
148		argv[3] = tlc
149		die(ENVIRON["msg_invalid_code"], 3, argv)
150	}
151
152	#
153	# Calculate the substr start-position of the name
154	#
155	name_start = 0
156	n = 4
157	if (FILENAME ~ /\.tab$/)
158		n = 2
159	while (--n)
160	{
161		#
162		# Validate field-length of 2nd/3rd columns while we are here
163		#
164		if (n > 1  && length(line[n]) != 3)
165		{
166			argv[1] = FILENAME
167			argv[2] = lineno
168			die(ENVIRON["msg_invalid_format"], 2, argv)
169		}
170
171		name_start += length(line[n]) + 1
172	}
173
174	# Get the name field
175	name = substr($0, name_start + 1)
176
177	add_country(tlc, name)
178}
179END {
180	list = ""
181	for (tlc in country_name)
182	{
183		list = list (length(list) > 0 ? " " : "") tlc
184		print_country_name(tlc)
185	}
186	printf "COUNTRIES=\"%s\"\n", list
187	print "export COUNTRIES"
188}
189'
190f_read_iso3166_table()
191{
192	eval $( awk -v progname="$pgm"          \
193	            "$f_read_iso3166_table_awk" \
194	            "$_PATH_ISO3166"            )
195}
196
197############################################################ MAIN
198
199f_dprintf "%s: Successfully loaded." timezone/iso3166.subr
200
201fi # ! $_TIMEZONE_ISO3166_SUBR
202