1 ########################################################################
3 # This software is part of the ast package #
4 # Copyright (c) 2000-2009 AT&T Intellectual Property #
5 # and is licensed under the #
6 # Common Public License, Version 1.0 #
7 # by AT&T Intellectual Property #
9 # A copy of the License is available at #
10 # http://www.opensource.org/licenses/cpl1.0.txt #
11 # (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) #
13 # Information and Software Systems Research #
17 # Glenn Fowler <gsf@research.att.com> #
19 ########################################################################
20 : C language message catalog compiler
22 # NOTE: all variable names match __*__ to avoid clash with msgcpp def vars
25 integer __similar__
=30
27 case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
28 0123) ARGV0
="-a $__command__"
31 @(#)$Id: msgcc (AT&T Labs Research) 2002-09-15 $
34 [+NAME?msgcc - C language message catalog compiler]
35 [+DESCRIPTION?\bmsgcc\b is a C language message catalog compiler. It accepts
36 \bcc\b(1) style options and arguments. A \bmsgcpp\b(1) \b.mso\b file
37 is generated for each input \b.c\b file. If the \b-c\b option is not
38 specified then a \bgencat\b(1) format \b.msg\b file is generated from
39 the input \b.mso\b and \b.msg\b files. If \b-c\b is not specified then
40 a \b.msg\b suffix is appended to the \b-o\b \afile\a if it doesn\'t
41 already have a suffix. The default output is \ba.out.msg\b if \b-c\b
42 and \b-o\b are not specified.]
43 [+?If \b-M-new\b is not specified then messages are merged with those in the
44 pre-existing \b-o\b file.]
45 [M?Set a \bmsgcc\b specific \aoption\a. \aoption\a may be:]:[-option]{
46 [+mkmsgs?The \b-o\b file is assumed to be in \bmkmsgs\b(1) format.]
47 [+new?Create a new \b-o\b file.]
48 [+preserve?Messages in the \b-o\b file that are not in new
49 \b.msg\b file arguments are preserved. The default is to
50 either reuse the message numbers with new message text that
51 is similar to the old or to delete the message text, leaving
52 an unused message number.]
53 [+set=\anumber\a?Set the message set number to \anumber\a. The default
55 [+similar=\anumber\a?The message text similarity measure thresshold.
56 The similarity measure between \aold\a and \anew\a message
57 text is 100*(2*gzip(\aold\a+\anew\a)/(gzip(\aold\a)+gzip(\anew\a))-1),
58 where gzip(\ax\a) is the size of text \ax\a when compressed by
59 \bgzip\b(1). The default threshhold is '$__similar__$
'. A
60 threshhold of \b0\b turns off message replacement, but unused
61 old messages are still deleted. Use \b-M-preserve\b to preserve
63 [+verbose?Trace similar message replacements on the standard error.]
68 [+SEE ALSO?\bcc\b(1), \bcpp\b(1), \bgencat\b(1), \bmsggen\b(1),
69 \bmsgcpp\b(1), \bmsgcvt\b(1)]
73 USAGE
="M:[-option] [ cc-options ] file ..."
80 getopts $ARGV0 "$USAGE" OPT
'-?'
86 $1 --??keys
-- 2>&1 |
grep '^".*"$'
90 typeset __keep__ __text__ __drop__ __oz__ __nz__ __z__ __hit__ __hit_i__
91 typeset __compile__ __debug__ __mkmsgs__ __preprocess__
92 typeset __merge__
=1 __preserve__ __verbose__
93 integer __i__
=0 __args__
=0 __code__
=0 __files__
=0 __max__
=0 __num__
=0 __skip__
=0
94 integer __set__
=1 __sources__
=0 __cmds__
=0 __ndrop__
=0 __new__
=0 __old__
=0
100 while getopts $ARGV0 "$USAGE" OPT
115 -[DIU
]*)__argv__
[__args__
]=$__arg__
132 __set__
=$
(msggen
-s ${__arg__#*=}.1)
135 __similar__
=${__arg__#*=}
141 1) print
-u2 $
"$__command__: output argument expected"
154 *) __srcv__
[__files__
]=$__arg__
158 __arg__
=${__arg__##*/}
159 __arg__
=${__arg__%.*}.mso
160 __objv__
[__files__
]=$__arg__
164 __objv__
[__files__
]=$__arg__
167 *) __cmdv__
[__cmds__
]=$__arg__
173 __cmdv__
[__cmds__
]=${__out__%.msg}
176 # generate the .mso files
178 if [[ $__OUT__ && $__compile__ ]]
179 then __objv__
[0]=$__OUT__
183 then for (( __i__
=0; __i__
<=__files__
; __i__
++ ))
184 do if [[ ${__srcv__[__i__]} ]]
185 then if (( __sources__
> 1 ))
186 then print
"${__srcv__[__i__]}:"
188 if [[ $__preprocess__ ]]
189 then msgcpp
"${__argv__[@]}" "${__srcv__[__i__]}"
190 else msgcpp
"${__argv__[@]}" "${__srcv__[__i__]}" > "${__objv__[__i__]}"
196 # combine the .mso and .msg files
198 if [[ ! $__compile__ && ! $__preprocess__ ]]
199 then if [[ $__merge__ && -r $__out__ ]]
200 then __tmp__
=$__out__.tmp
201 trap '__code__=$?; rm -f ${__tmp__}*; exit $__code__' 0 1 2
202 while read -r __line__
203 do if (( $__skip__ ))
204 then if [[ $__line__ == '%}'* ]]
209 if [[ $__mkmsgs__ && $__line__ == '%{'* ]]
214 then if [[ $__line__ == '%#'*';;'* ]]
215 then __line__
=${__line__#'%#'}
216 __num__
=${__line__%';;'*}
218 elif [[ $__line__ == %* ]]
220 else print
-u2 $
"$__command__: unrecognized line=$__line__"
223 else case $__line__ in
225 __num__
=${__line__%%' '*}
226 __line__
=${__line__#*'"'}
227 __line__
=${__line__%'"'}
233 __index__
["$__line__"]=$__num__
234 __text__
[$__num__]=$__line__
235 if (( __max__
< __num__
))
236 then (( __max__
=__num__
))
239 (( __new__
=__max__
+1 ))
240 else __tmp__
=$__out__
247 print
-r -- '$'" ${__out__%.msg} message catalog"
248 print
-r -- '$translation'" $__command__ $(date +%Y-%m-%d)"
249 print
-r -- '$set'" $__set__"
250 print
-r -- '$quote "'
251 sort -u "${__objv__[@]}" |
{
252 while read -r __line__
253 do __op__
=${__line__%% *}
254 __line__
=${__line__#* }
256 cmd
) __a1__
=${__line__%% *}
262 def
) __a1__
=${__line__%% *}
263 __a2__
=${__line__#* }
264 eval $__a1__='$'__a2__
266 str
) print
-r -- "$__line__"
268 var
) __a1__
=${__line__%% *}
269 __a2__
=${__line__#* }
272 eval __v__
='$'$__a2__
273 __v__
='"'${__v__:__a1__+1}
275 *) eval __v__
='$'$__a1__
278 if [[ $__v__ == '"'*'"' ]]
279 then print
-r -- "$__v__"
283 [[ $__preserve__ ]] && print
-r -- "$__line__"
285 '$') print
-r -u9 $__op__ include
$__line__
289 for (( __i__
=0; __i__
< __cmds__
; __i__
++ ))
290 do keys
${__cmdv__[__i__]}
294 while read -r __line__
297 print
-r -- "$__line__"
300 '$'*|
*"@(#)"*|
*"<"*([[:word
:] .
-])"@"*([[:word
:] .
-])">"*([ ])'"'|
"http://"*)
303 *[[:alpha
:]][[:alpha
:]]*)
304 __line__
=${__line__#*'"'}
305 __line__
=${__line__%'"'}
307 then if [[ ${__index__["$__line__"]} ]]
308 then if [[ ! $__preserve__ ]]
309 then __num__
=${__index__["$__line__"]}
312 else while [[ ${__text__[$__num__]} ]]
315 if (( __max__
< __num__
))
316 then (( __max__
=__num__
))
318 if [[ ! $__preserve__ ]]
319 then __keep__
[$__num__]=1
321 __text__
[$__num__]=$__line__
322 __index__
["$__line__"]=$__num__
329 if (( __max__
< __num__
))
330 then (( __max__
=__num__
))
333 then for (( __num__
=1; __num__
<=__max__
; __num__
++ ))
334 do if [[ ${__text__[$__num__]} ]]
335 then if (( __num__
> __new__
))
336 then if [[ ! ${__keep__[$__num__]} ]]
337 then print
-r -u2 -- $__num__ HUH
'"'"${__text__[$__num__]}"'"'
338 else print
-r -u2 -- $__num__ NEW
'"'"${__text__[$__num__]}"'"'
340 elif [[ ${__keep__[$__num__]} ]]
341 then print
-r -u2 -- $__num__ OLD
'"'"${__text__[$__num__]}"'"'
342 else print
-r -u2 -- $__num__ XXX
'"'"${__text__[$__num__]}"'"'
348 # check for replacements
349 if [[ ! $__preserve__ ]]
350 then for (( __num__
=1; __num__
<__new__
; __num__
++ ))
351 do if [[ ${__text__[$__num__]} && ! ${__keep__[$__num__]} ]]
352 then (( __ndrop__
++ ))
353 __drop__
[__ndrop__
]=$__num__
356 [[ $__verbose__ ]] && print
-u2 $__command__: old
:1-$
((__new__-1
)) new
:$__new__-$__max__ drop
$__ndrop__ add $
((__max__-__new__
+1))
358 then for (( __i__
=1; __i__
<=__ndrop__
; __i__
++ ))
359 do (( __old__
=${__drop__[$__i__]} ))
360 __oz__
[__i__
]=$
(print
-r -- "\"${__text__[$__old__]}\"" |
gzip |
wc -c)
362 for (( __num__
=__new__
; __num__
<=__max__
; __num__
++ ))
363 do [[ ${__text__[$__num__]} ]] ||
continue
364 __nz__
=$
(print
-r -- "\"${__text__[$__num__]}\"" |
gzip |
wc -c)
366 (( __bz__
=__similar__
))
367 for (( __i__
=1; __i__
<=__ndrop__
; __i__
++ ))
368 do if (( __old__
=${__drop__[$__i__]} ))
369 then __z__
=$
(print
-r -- "\"${__text__[$__old__]}\"""\"${__text__[$__num__]}\"" |
gzip |
wc -c)
370 (( __z__
= (__z__
* 200 / (${__oz__[__i__]} + $__nz__)) - 100 ))
371 if (( __z__
< __bz__
))
372 then (( __bz__
=__z__
))
373 (( __hit__
=__old__
))
374 (( __hit_i__
=__i__
))
379 then [[ $__verbose__ ]] && print
-u2 $__command__: $__hit__ $__num__ $__bz__
380 __text__
[$__hit__]=${__text__[$__num__]}
382 __drop__
[$__hit_i__]=0
390 for (( __num__
=1; __num__
<=__max__
; __num__
++ ))
391 do if [[ ${__text__[$__num__]} && ( $__preserve__ ||
${__keep__[$__num__]} ) ]]
392 then print
-r -- $__num__ "\"${__text__[$__num__]}\""
396 if [[ $__tmp__ != $__out__ ]]
397 then grep -v '^\$' $__tmp__ > ${__tmp__}n
398 [[ -f $__out__ ]] && grep -v '^\$' $__out__ > ${__tmp__}o
399 cmp -s ${__tmp__}n
${__tmp__}o ||
{
400 [[ -f $__out__ ]] && mv $__out__ $__out__.old