1#! /bin/sh 2# $NetBSD: msg_xlat.sh,v 1.1 2014/07/26 19:30:44 dholland Exp $ 3 4#- 5# Copyright (c) 2003 The NetBSD Foundation, Inc. 6# All rights reserved. 7# 8# This code is derived from software contributed to The NetBSD Foundation 9# by David Laight. 10# 11# Redistribution and use in source and binary forms, with or without 12# modification, are permitted provided that the following conditions 13# are met: 14# 1. Redistributions of source code must retain the above copyright 15# notice, this list of conditions and the following disclaimer. 16# 2. Redistributions in binary form must reproduce the above copyright 17# notice, this list of conditions and the following disclaimer in the 18# documentation and/or other materials provided with the distribution. 19# 20# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30# POSSIBILITY OF SUCH DAMAGE. 31# 32 33usage() 34{ 35 echo "usage: msg_xlat.sh [-ci] [-d msg_defs.h] [-f fmt_count]" >&2 36 exit 1 37} 38 39count_fmtargs= 40msg_defs=msg_defs.h 41while getopts cd:f:i f 42do 43 case $f in 44 c) count_fmtargs=1;; 45 d) msg_defs=$OPTARG;; 46 f) fmt_count=$OPTARG;; 47 i) IGNORE_MISSING_TRANSLATIONS=y;; 48 *) usage;; 49 esac 50done 51shift $(($OPTIND - 1)) 52[ "$#" = 0 ] || usage 53 54nl=" 55" 56msg_long="((msg)(long)" 57close_paren=")" 58open_brace="{" 59close_brace="}" 60slash="/" 61 62rval=0 63 64# save stdin while we read the other files 65exec 3<&0 66 67# Read existing list of format arg counts 68[ -n "$fmt_count" ] && { 69 exec <$fmt_count || exit 2 70 while read name count 71 do 72 eval count_$name=\$count 73 done 74} 75 76# Read header file and set up map of message names to numbers 77 78exec <$msg_defs || exit 2 79 80while read define MSG_name number rest 81do 82 [ -z "$number" -o -n "$rest" ] && continue 83 [ "$define" = "#define" ] || continue 84 name="${MSG_name#MSG_}" 85 [ "$name" = "${MSG_name}" ] && continue 86 msg_number="${number#$msg_long}" 87 [ "$msg_number" = "$number" ] && continue 88 msg_number="${msg_number%$close_paren}" 89 90 eval $MSG_name=$msg_number 91 eval MSGNUM_$msg_number=\$MSG_name 92 # eval echo \$$MSG_name \$MSGNUM_$msg_number 93done 94 95last_msg_number="$msg_number" 96 97# Read message definition file and set up map of munbers to strings 98 99exec <&3 3<&- 100 101name= 102msg= 103OIFS="$IFS" 104while 105 IFS= 106 read -r line 107do 108 [ -z "$name" ] && { 109 IFS=" " 110 set -- $line 111 [ "$1" = message ] || continue 112 name="$2" 113 eval number=\$MSG_$name 114 [ -z "$number" ] && { 115 echo "ERROR: unknown message \"$name\"" >&2 116 [ -n "$IGNORE_MISSING_TRANSLATIONS" ] || rval=1 117 number=unknown 118 } 119 l=${line#*$open_brace} 120 [ "$l" = "$line" ] && continue 121 line="{$l" 122 } 123 [ -z "$msg" ] && { 124 l="${line#$open_brace}" 125 [ "$l" = "$line" ] && continue 126 msg="$line" 127 } || msg="$msg$nl$line" 128 m="${msg%$close_brace}" 129 [ "$m" = "$msg" ] && { 130 # Allow <tab>*/* comment */ (eg XXX translate) 131 m="${msg%%$close_brace*$slash[*]*[*]$slash}" 132 [ "$m" = "$msg" ] && 133 continue 134 } 135 # We need the %b to expand the \n that exist in the message file 136 msg="$(printf "%bz" "${m#$open_brace}")" 137 msg="${msg%z}" 138 eval old=\"\$MSGTEXT_$number\" 139 [ -n "$old" -a "$number" != unknown ] && { 140 echo "ERROR: Two translations for message \"$name\"" >&2 141 [ -n "$IGNORE_MISSING_TRANSLATIONS" ] || rval=1 142 } 143 eval MSGTEXT_$number=\"\${msg}\" 144 # echo $number $msg 145 sv_name="$name" 146 sv_msg="$msg" 147 name= 148 msg= 149 [ -z "$count_fmtargs" -a -z "$fmt_count" ] && continue 150 151 IFS='%' 152 set -- - x$sv_msg 153 [ -n "$count_fmtargs" ] && { 154 echo $number $# 155 continue 156 } 157 eval count=\${count_$number:-unknown} 158 [ "$count" = $# ] || { 159 echo "ERROR: Wrong number of format specifiers in \"$sv_name\", got $#, expected $count" >&2 160 [ -n "$IGNORE_MISSING_TRANSLATIONS" ] || rval=1 161 } 162done 163 164[ -n "$count_fmtargs" ] && exit $rval 165 166# Output the total number of messages and the offset of each in the file. 167# Use ascii numbers because generating target-ordered binary numbers 168# is just a smidgen tricky in the shell. 169 170offset="$(( 8 + $last_msg_number * 8 + 8 ))" 171printf 'MSGTXTS\0%-7d\0' $last_msg_number 172 173msgnum=0 174while 175 msgnum="$(( $msgnum + 1 ))" 176 [ "$msgnum" -le "$last_msg_number" ] 177do 178 eval msg=\${MSGTEXT_$msgnum} 179 [ -z "$msg" ] && { 180 eval echo "ERROR: No translation for message \$MSGNUM_$msgnum" >&2 181 printf '%-7d\0' 0 182 [ -n "$IGNORE_MISSING_TRANSLATIONS" ] || rval=1 183 continue 184 } 185 printf '%-7d\0' $offset 186 offset="$(( $offset + ${#msg} + 1 ))" 187done 188 189# Finally output and null terminate the messages. 190 191msgnum=0 192while 193 msgnum="$(( $msgnum + 1 ))" 194 [ "$msgnum" -le "$last_msg_number" ] 195do 196 eval msg=\${MSGTEXT_$msgnum} 197 [ -z "$msg" ] && continue 198 printf '%s\0' $msg 199done 200 201exit $rval 202