xref: /freebsd/usr.sbin/bsdconfig/timezone/share/iso3166.subr (revision 0b3105a37d7adcadcb720112fed4dc4e8040be99)
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# $FreeBSD$
28#
29############################################################ INCLUDES
30
31BSDCFG_SHARE="/usr/share/bsdconfig"
32. $BSDCFG_SHARE/common.subr || exit 1
33f_dprintf "%s: loading includes..." timezone/iso3166.subr
34
35BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="090.timezone"
36f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
37
38############################################################ CONFIGURATION
39
40#
41# Standard pathnames
42#
43_PATH_ISO3166="/usr/share/misc/iso3166"
44
45#
46# Export required i18n messages for awk(1) ENVIRON visibility
47#
48export msg_country_code_multiply_defined
49export msg_invalid_code
50export msg_invalid_format
51
52############################################################ FUNCTIONS
53
54# f_read_iso3166_table
55#
56# Read the ISO 3166 country code database in _PATH_ISO3166:
57# 	/usr/share/misc/iso3166 on FreeBSD
58# 	/usr/share/zoneinfo/iso3166.tab on Linux, Mac OS X, and Cygwin
59#
60# The format of this file on FreeBSD is:
61# 	two	three	number	name
62#
63# The format of this file on Linux, Mac OS X, and Cygwin is:
64# 	two	name
65#
66# With each of the following elements (described below) being separated by a
67# single tab character:
68#
69# 	two      ISO 3166 2-character country code
70# 	three    ISO 3166 3-character country code (if provided)
71# 	number   ISO 3166 numeric country code (if provided)
72# 	name     Human-readable country name (may contain spaces)
73#
74# Variables created by this function:
75#
76# 	COUNTRIES
77# 		A space-separated list of 2-character country codes.
78# 	country_CODE_name
79# 		The country `name' (as described above).
80#
81# where CODE is the 2-character country code.
82#
83# This function is a two-parter. Below is the awk(1) portion of the function,
84# afterward is the sh(1) function which utilizes the below awk script.
85#
86f_read_iso3166_table_awk='
87# Variables that should be defined on the invocation line:
88# 	-v progname="progname"
89#
90BEGIN {
91	lineno = 0
92	failed = 0
93}
94function die(fmt, argc, argv)
95{
96	printf "f_die 1 \"%%s: %s\" \"%s\"", fmt, progname
97	for (n = 1; n <= argc; n++)
98		printf " \"%s\"", argv[n]
99	print ""
100	failed++
101	exit 1
102}
103function add_country(tlc, name)
104{
105	if (country_name[tlc])
106	{
107		argv[1] = FILENAME
108		argv[2] = lineno
109		argv[3] = tlc
110		argv[4] = name
111		die(ENVIRON["msg_country_code_multiply_defined"], 4, argv)
112	}
113
114	country_name[tlc] = name
115}
116function print_country_name(tlc)
117{
118	name = country_name[tlc]
119	gsub(/"/, "\\\"", name)
120	printf "country_%s_name=\"%s\"\n", tlc, name
121	printf "export country_%s_name\n", tlc
122}
123/^#/ {
124	lineno++
125	next
126}
127!/^#/ {
128	lineno++
129
130	# Split the current record (on TAB) into an array
131	split($0, line, /\t/)
132
133	# Get the ISO3166-1 (Alpha 1) 2-letter country code
134	tlc = line[1]
135
136	#
137	# Validate the two-character country code
138	#
139	if (length(tlc) != 2)
140	{
141		argv[1] = FILENAME
142		argv[2] = lineno
143		die(ENVIRON["msg_invalid_format"], 2, argv)
144	}
145	if (!match(tlc, /^[A-Z][A-Z]$/))
146	{
147		argv[1] = FILENAME
148		argv[2] = lineno
149		argv[3] = tlc
150		die(ENVIRON["msg_invalid_code"], 3, argv)
151	}
152
153	#
154	# Calculate the substr start-position of the name
155	#
156	name_start = 0
157	n = 4
158	if (FILENAME ~ /\.tab$/)
159		n = 2
160	while (--n)
161	{
162		#
163		# Validate field-length of 2nd/3rd columns while we are here
164		#
165		if (n > 1  && length(line[n]) != 3)
166		{
167			argv[1] = FILENAME
168			argv[2] = lineno
169			die(ENVIRON["msg_invalid_format"], 2, argv)
170		}
171
172		name_start += length(line[n]) + 1
173	}
174
175	# Get the name field
176	name = substr($0, name_start + 1)
177
178	add_country(tlc, name)
179}
180END {
181	list = ""
182	for (tlc in country_name)
183	{
184		list = list (length(list) > 0 ? " " : "") tlc
185		print_country_name(tlc)
186	}
187	printf "COUNTRIES=\"%s\"\n", list
188	print "export COUNTRIES"
189}
190'
191f_read_iso3166_table()
192{
193	eval $( awk -v progname="$pgm"          \
194	            "$f_read_iso3166_table_awk" \
195	            "$_PATH_ISO3166"            )
196}
197
198############################################################ MAIN
199
200f_dprintf "%s: Successfully loaded." timezone/iso3166.subr
201
202fi # ! $_TIMEZONE_ISO3166_SUBR
203