8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / ast / msgcc / msgcc.sh
blob209cbda167b3bc98d2da66fba131285b64dd5d8c
1 ########################################################################
2 # #
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 #
8 # #
9 # A copy of the License is available at #
10 # http://www.opensource.org/licenses/cpl1.0.txt #
11 # (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) #
12 # #
13 # Information and Software Systems Research #
14 # AT&T Research #
15 # Florham Park NJ #
16 # #
17 # Glenn Fowler <gsf@research.att.com> #
18 # #
19 ########################################################################
20 : C language message catalog compiler
22 # NOTE: all variable names match __*__ to avoid clash with msgcpp def vars
24 __command__=msgcc
25 integer __similar__=30
27 case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in
28 0123) ARGV0="-a $__command__"
29 USAGE=$'
30 [-?
31 @(#)$Id: msgcc (AT&T Labs Research) 2002-09-15 $
33 '$USAGE_LICENSE$'
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
54 is \b1\b.]
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
62 all old messages.]
63 [+verbose?Trace similar message replacements on the standard error.]
66 file ...
68 [+SEE ALSO?\bcc\b(1), \bcpp\b(1), \bgencat\b(1), \bmsggen\b(1),
69 \bmsgcpp\b(1), \bmsgcvt\b(1)]
72 *) ARGV0=""
73 USAGE="M:[-option] [ cc-options ] file ..."
75 esac
77 usage()
79 OPTIND=0
80 getopts $ARGV0 "$USAGE" OPT '-?'
81 exit 2
84 keys()
86 $1 --??keys -- 2>&1 | grep '^".*"$'
89 typeset -A __index__
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
95 __out__=a.out.msg
96 __OUT__=
98 case " $* " in
99 *" --"*|*" -?"*)
100 while getopts $ARGV0 "$USAGE" OPT
101 do case $OPT in
102 *) break ;;
103 esac
104 done
106 esac
107 while :
108 do case $# in
109 0) break ;;
110 esac
111 __arg__=$1
112 case $__arg__ in
113 -c) __compile__=1
115 -[DIU]*)__argv__[__args__]=$__arg__
116 (( __args__++ ))
118 -E) __preprocess__=1
120 -M-debug)
121 __debug__=1
123 -M-mkmsgs)
124 __mkmsgs__=1
126 -M-new) __merge__=
128 -M-perserve)
129 __preserve__=1
131 -M-set=*)
132 __set__=$(msggen -s ${__arg__#*=}.1)
134 -M-similar=*)
135 __similar__=${__arg__#*=}
137 -M-verbose)
138 __verbose__=1
140 -o) case $# in
141 1) print -u2 $"$__command__: output argument expected"
142 exit 1
144 esac
145 shift
146 __out__=${1%.*}.msg
147 __OUT__=$1
149 [-+]*|*.[aAlLsS]*)
151 *.[cCiI]*|*.[oO]*)
152 case $__arg__ in
153 *.[oO]*);;
154 *) __srcv__[__files__]=$__arg__
155 (( __sources__++ ))
157 esac
158 __arg__=${__arg__##*/}
159 __arg__=${__arg__%.*}.mso
160 __objv__[__files__]=$__arg__
161 (( __files__++ ))
163 *.ms[go])
164 __objv__[__files__]=$__arg__
165 (( __files__++ ))
167 *) __cmdv__[__cmds__]=$__arg__
168 (( __cmds__++ ))
170 esac
171 shift
172 done
173 __cmdv__[__cmds__]=${__out__%.msg}
174 (( __cmds__++ ))
176 # generate the .mso files
178 if [[ $__OUT__ && $__compile__ ]]
179 then __objv__[0]=$__OUT__
182 if (( __sources__ ))
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__]}"
193 done
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__ == '%}'* ]]
205 then __skip__=0
207 continue
209 if [[ $__mkmsgs__ && $__line__ == '%{'* ]]
210 then __skip__=1
211 continue
213 if [[ $__mkmsgs__ ]]
214 then if [[ $__line__ == '%#'*';;'* ]]
215 then __line__=${__line__#'%#'}
216 __num__=${__line__%';;'*}
217 read -r __line__
218 elif [[ $__line__ == %* ]]
219 then continue
220 else print -u2 $"$__command__: unrecognized line=$__line__"
221 __code__=1
223 else case $__line__ in
224 +([0-9])' '*)
225 __num__=${__line__%%' '*}
226 __line__=${__line__#*'"'}
227 __line__=${__line__%'"'}
229 *) continue
231 esac
233 __index__["$__line__"]=$__num__
234 __text__[$__num__]=$__line__
235 if (( __max__ < __num__ ))
236 then (( __max__=__num__ ))
238 done < $__out__
239 (( __new__=__max__+1 ))
240 else __tmp__=$__out__
241 (( __new__=1 ))
243 if (( __code__ ))
244 then exit $__code__
246 exec 1>$__tmp__ 9>&1
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__#* }
255 case $__op__ in
256 cmd) __a1__=${__line__%% *}
257 case $__a1__ in
258 dot_cmd) __a1__=. ;;
259 esac
260 keys $__a1__
262 def) __a1__=${__line__%% *}
263 __a2__=${__line__#* }
264 eval $__a1__='$'__a2__
266 str) print -r -- "$__line__"
268 var) __a1__=${__line__%% *}
269 __a2__=${__line__#* }
270 case $__a1__ in
271 [[:digit:]]*)
272 eval __v__='$'$__a2__
273 __v__='"'${__v__:__a1__+1}
275 *) eval __v__='$'$__a1__
277 esac
278 if [[ $__v__ == '"'*'"' ]]
279 then print -r -- "$__v__"
282 [[:digit:]]*)
283 [[ $__preserve__ ]] && print -r -- "$__line__"
285 '$') print -r -u9 $__op__ include $__line__
287 esac
288 done
289 for (( __i__=0; __i__ < __cmds__; __i__++ ))
290 do keys ${__cmdv__[__i__]}
291 done
292 } | {
293 __num__=1
294 while read -r __line__
295 do case $__line__ in
296 '$'[\ \ ]*)
297 print -r -- "$__line__"
298 continue
300 '$'*|*"@(#)"*|*"<"*([[:word:] .-])"@"*([[:word:] .-])">"*([ ])'"'|"http://"*)
301 continue
303 *[[:alpha:]][[:alpha:]]*)
304 __line__=${__line__#*'"'}
305 __line__=${__line__%'"'}
306 if [[ $__line__ ]]
307 then if [[ ${__index__["$__line__"]} ]]
308 then if [[ ! $__preserve__ ]]
309 then __num__=${__index__["$__line__"]}
310 __keep__[$__num__]=1
312 else while [[ ${__text__[$__num__]} ]]
313 do (( __num__++ ))
314 done
315 if (( __max__ < __num__ ))
316 then (( __max__=__num__ ))
318 if [[ ! $__preserve__ ]]
319 then __keep__[$__num__]=1
321 __text__[$__num__]=$__line__
322 __index__["$__line__"]=$__num__
323 (( __num__++ ))
327 esac
328 done
329 if (( __max__ < __num__ ))
330 then (( __max__=__num__ ))
332 if [[ $__debug__ ]]
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__]}"'"'
345 done
346 exit 0
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__
355 done
356 [[ $__verbose__ ]] && print -u2 $__command__: old:1-$((__new__-1)) new:$__new__-$__max__ drop $__ndrop__ add $((__max__-__new__+1))
357 if (( __ndrop__ ))
358 then for (( __i__=1; __i__<=__ndrop__; __i__++ ))
359 do (( __old__=${__drop__[$__i__]} ))
360 __oz__[__i__]=$(print -r -- "\"${__text__[$__old__]}\"" | gzip | wc -c)
361 done
362 for (( __num__=__new__; __num__<=__max__; __num__++ ))
363 do [[ ${__text__[$__num__]} ]] || continue
364 __nz__=$(print -r -- "\"${__text__[$__num__]}\"" | gzip | wc -c)
365 __hit__=0
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__ ))
377 done
378 if (( __hit__ ))
379 then [[ $__verbose__ ]] && print -u2 $__command__: $__hit__ $__num__ $__bz__
380 __text__[$__hit__]=${__text__[$__num__]}
381 __keep__[$__hit__]=1
382 __drop__[$__hit_i__]=0
383 __text__[$__num__]=
384 __keep__[$__num__]=
386 done
389 # final output
390 for (( __num__=1; __num__<=__max__; __num__++ ))
391 do if [[ ${__text__[$__num__]} && ( $__preserve__ || ${__keep__[$__num__]} ) ]]
392 then print -r -- $__num__ "\"${__text__[$__num__]}\""
394 done
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
401 mv $__tmp__ $__out__
405 exit $__code__