1da2e3ebdSchin######################################################################## 2da2e3ebdSchin# # 3da2e3ebdSchin# This software is part of the ast package # 4*34f9b3eeSRoland Mainz# Copyright (c) 2000-2009 AT&T Intellectual Property # 5da2e3ebdSchin# and is licensed under the # 6da2e3ebdSchin# Common Public License, Version 1.0 # 77c2fbfb3SApril Chin# by AT&T Intellectual Property # 8da2e3ebdSchin# # 9da2e3ebdSchin# A copy of the License is available at # 10da2e3ebdSchin# http://www.opensource.org/licenses/cpl1.0.txt # 11da2e3ebdSchin# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # 12da2e3ebdSchin# # 13da2e3ebdSchin# Information and Software Systems Research # 14da2e3ebdSchin# AT&T Research # 15da2e3ebdSchin# Florham Park NJ # 16da2e3ebdSchin# # 17da2e3ebdSchin# Glenn Fowler <gsf@research.att.com> # 18da2e3ebdSchin# # 19da2e3ebdSchin######################################################################## 20da2e3ebdSchin: C language message catalog compiler 21da2e3ebdSchin 22da2e3ebdSchin# NOTE: all variable names match __*__ to avoid clash with msgcpp def vars 23da2e3ebdSchin 24da2e3ebdSchin__command__=msgcc 25da2e3ebdSchininteger __similar__=30 26da2e3ebdSchin 27da2e3ebdSchincase `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in 28da2e3ebdSchin0123) ARGV0="-a $__command__" 29da2e3ebdSchin USAGE=$' 30da2e3ebdSchin[-? 31da2e3ebdSchin@(#)$Id: msgcc (AT&T Labs Research) 2002-09-15 $ 32da2e3ebdSchin] 33da2e3ebdSchin'$USAGE_LICENSE$' 34da2e3ebdSchin[+NAME?msgcc - C language message catalog compiler] 35da2e3ebdSchin[+DESCRIPTION?\bmsgcc\b is a C language message catalog compiler. It accepts 36da2e3ebdSchin \bcc\b(1) style options and arguments. A \bmsgcpp\b(1) \b.mso\b file 37da2e3ebdSchin is generated for each input \b.c\b file. If the \b-c\b option is not 38da2e3ebdSchin specified then a \bgencat\b(1) format \b.msg\b file is generated from 39da2e3ebdSchin the input \b.mso\b and \b.msg\b files. If \b-c\b is not specified then 40da2e3ebdSchin a \b.msg\b suffix is appended to the \b-o\b \afile\a if it doesn\'t 41da2e3ebdSchin already have a suffix. The default output is \ba.out.msg\b if \b-c\b 42da2e3ebdSchin and \b-o\b are not specified.] 43da2e3ebdSchin[+?If \b-M-new\b is not specified then messages are merged with those in the 44da2e3ebdSchin pre-existing \b-o\b file.] 45da2e3ebdSchin[M?Set a \bmsgcc\b specific \aoption\a. \aoption\a may be:]:[-option]{ 46da2e3ebdSchin [+mkmsgs?The \b-o\b file is assumed to be in \bmkmsgs\b(1) format.] 47da2e3ebdSchin [+new?Create a new \b-o\b file.] 48da2e3ebdSchin [+preserve?Messages in the \b-o\b file that are not in new 49da2e3ebdSchin \b.msg\b file arguments are preserved. The default is to 50da2e3ebdSchin either reuse the message numbers with new message text that 51da2e3ebdSchin is similar to the old or to delete the message text, leaving 52da2e3ebdSchin an unused message number.] 53da2e3ebdSchin [+set=\anumber\a?Set the message set number to \anumber\a. The default 54da2e3ebdSchin is \b1\b.] 55da2e3ebdSchin [+similar=\anumber\a?The message text similarity measure thresshold. 56da2e3ebdSchin The similarity measure between \aold\a and \anew\a message 57da2e3ebdSchin text is 100*(2*gzip(\aold\a+\anew\a)/(gzip(\aold\a)+gzip(\anew\a))-1), 58da2e3ebdSchin where gzip(\ax\a) is the size of text \ax\a when compressed by 59da2e3ebdSchin \bgzip\b(1). The default threshhold is '$__similar__$'. A 60da2e3ebdSchin threshhold of \b0\b turns off message replacement, but unused 61da2e3ebdSchin old messages are still deleted. Use \b-M-preserve\b to preserve 62da2e3ebdSchin all old messages.] 63da2e3ebdSchin [+verbose?Trace similar message replacements on the standard error.] 64da2e3ebdSchin} 65da2e3ebdSchin 66da2e3ebdSchinfile ... 67da2e3ebdSchin 68da2e3ebdSchin[+SEE ALSO?\bcc\b(1), \bcpp\b(1), \bgencat\b(1), \bmsggen\b(1), 69da2e3ebdSchin \bmsgcpp\b(1), \bmsgcvt\b(1)] 70da2e3ebdSchin' 71da2e3ebdSchin ;; 72da2e3ebdSchin*) ARGV0="" 73da2e3ebdSchin USAGE="M:[-option] [ cc-options ] file ..." 74da2e3ebdSchin ;; 75da2e3ebdSchinesac 76da2e3ebdSchin 77da2e3ebdSchinusage() 78da2e3ebdSchin{ 79da2e3ebdSchin OPTIND=0 80da2e3ebdSchin getopts $ARGV0 "$USAGE" OPT '-?' 81da2e3ebdSchin exit 2 82da2e3ebdSchin} 83da2e3ebdSchin 84da2e3ebdSchinkeys() 85da2e3ebdSchin{ 86da2e3ebdSchin $1 --??keys -- 2>&1 | grep '^".*"$' 87da2e3ebdSchin} 88da2e3ebdSchin 89da2e3ebdSchintypeset -A __index__ 90da2e3ebdSchintypeset __keep__ __text__ __drop__ __oz__ __nz__ __z__ __hit__ __hit_i__ 91da2e3ebdSchintypeset __compile__ __debug__ __mkmsgs__ __preprocess__ 92da2e3ebdSchintypeset __merge__=1 __preserve__ __verbose__ 93da2e3ebdSchininteger __i__=0 __args__=0 __code__=0 __files__=0 __max__=0 __num__=0 __skip__=0 94da2e3ebdSchininteger __set__=1 __sources__=0 __cmds__=0 __ndrop__=0 __new__=0 __old__=0 95da2e3ebdSchin__out__=a.out.msg 96da2e3ebdSchin__OUT__= 97da2e3ebdSchin 98da2e3ebdSchincase " $* " in 99da2e3ebdSchin*" --"*|*" -?"*) 100da2e3ebdSchin while getopts $ARGV0 "$USAGE" OPT 101da2e3ebdSchin do case $OPT in 102da2e3ebdSchin *) break ;; 103da2e3ebdSchin esac 104da2e3ebdSchin done 105da2e3ebdSchin ;; 106da2e3ebdSchinesac 107da2e3ebdSchinwhile : 108da2e3ebdSchindo case $# in 109da2e3ebdSchin 0) break ;; 110da2e3ebdSchin esac 111da2e3ebdSchin __arg__=$1 112da2e3ebdSchin case $__arg__ in 113da2e3ebdSchin -c) __compile__=1 114da2e3ebdSchin ;; 115da2e3ebdSchin -[DIU]*)__argv__[__args__]=$__arg__ 116da2e3ebdSchin (( __args__++ )) 117da2e3ebdSchin ;; 118da2e3ebdSchin -E) __preprocess__=1 119da2e3ebdSchin ;; 120da2e3ebdSchin -M-debug) 121da2e3ebdSchin __debug__=1 122da2e3ebdSchin ;; 123da2e3ebdSchin -M-mkmsgs) 124da2e3ebdSchin __mkmsgs__=1 125da2e3ebdSchin ;; 126da2e3ebdSchin -M-new) __merge__= 127da2e3ebdSchin ;; 128da2e3ebdSchin -M-perserve) 129da2e3ebdSchin __preserve__=1 130da2e3ebdSchin ;; 131da2e3ebdSchin -M-set=*) 132da2e3ebdSchin __set__=$(msggen -s ${__arg__#*=}.1) 133da2e3ebdSchin ;; 134da2e3ebdSchin -M-similar=*) 135da2e3ebdSchin __similar__=${__arg__#*=} 136da2e3ebdSchin ;; 137da2e3ebdSchin -M-verbose) 138da2e3ebdSchin __verbose__=1 139da2e3ebdSchin ;; 140da2e3ebdSchin -o) case $# in 141da2e3ebdSchin 1) print -u2 $"$__command__: output argument expected" 142da2e3ebdSchin exit 1 143da2e3ebdSchin ;; 144da2e3ebdSchin esac 145da2e3ebdSchin shift 146da2e3ebdSchin __out__=${1%.*}.msg 147da2e3ebdSchin __OUT__=$1 148da2e3ebdSchin ;; 149da2e3ebdSchin [-+]*|*.[aAlLsS]*) 150da2e3ebdSchin ;; 151da2e3ebdSchin *.[cCiI]*|*.[oO]*) 152da2e3ebdSchin case $__arg__ in 153da2e3ebdSchin *.[oO]*);; 154da2e3ebdSchin *) __srcv__[__files__]=$__arg__ 155da2e3ebdSchin (( __sources__++ )) 156da2e3ebdSchin ;; 157da2e3ebdSchin esac 158da2e3ebdSchin __arg__=${__arg__##*/} 159da2e3ebdSchin __arg__=${__arg__%.*}.mso 160da2e3ebdSchin __objv__[__files__]=$__arg__ 161da2e3ebdSchin (( __files__++ )) 162da2e3ebdSchin ;; 163da2e3ebdSchin *.ms[go]) 164da2e3ebdSchin __objv__[__files__]=$__arg__ 165da2e3ebdSchin (( __files__++ )) 166da2e3ebdSchin ;; 167da2e3ebdSchin *) __cmdv__[__cmds__]=$__arg__ 168da2e3ebdSchin (( __cmds__++ )) 169da2e3ebdSchin ;; 170da2e3ebdSchin esac 171da2e3ebdSchin shift 172da2e3ebdSchindone 173da2e3ebdSchin__cmdv__[__cmds__]=${__out__%.msg} 174da2e3ebdSchin(( __cmds__++ )) 175da2e3ebdSchin 176da2e3ebdSchin# generate the .mso files 177da2e3ebdSchin 178da2e3ebdSchinif [[ $__OUT__ && $__compile__ ]] 179da2e3ebdSchinthen __objv__[0]=$__OUT__ 180da2e3ebdSchinfi 181da2e3ebdSchin 182da2e3ebdSchinif (( __sources__ )) 183da2e3ebdSchinthen for (( __i__=0; __i__<=__files__; __i__++ )) 184da2e3ebdSchin do if [[ ${__srcv__[__i__]} ]] 185da2e3ebdSchin then if (( __sources__ > 1 )) 186da2e3ebdSchin then print "${__srcv__[__i__]}:" 187da2e3ebdSchin fi 188da2e3ebdSchin if [[ $__preprocess__ ]] 189da2e3ebdSchin then msgcpp "${__argv__[@]}" "${__srcv__[__i__]}" 190da2e3ebdSchin else msgcpp "${__argv__[@]}" "${__srcv__[__i__]}" > "${__objv__[__i__]}" 191da2e3ebdSchin fi 192da2e3ebdSchin fi 193da2e3ebdSchin done 194da2e3ebdSchinfi 195da2e3ebdSchin 196da2e3ebdSchin# combine the .mso and .msg files 197da2e3ebdSchin 198da2e3ebdSchinif [[ ! $__compile__ && ! $__preprocess__ ]] 199da2e3ebdSchinthen if [[ $__merge__ && -r $__out__ ]] 200da2e3ebdSchin then __tmp__=$__out__.tmp 201da2e3ebdSchin trap '__code__=$?; rm -f ${__tmp__}*; exit $__code__' 0 1 2 202da2e3ebdSchin while read -r __line__ 203da2e3ebdSchin do if (( $__skip__ )) 204da2e3ebdSchin then if [[ $__line__ == '%}'* ]] 205da2e3ebdSchin then __skip__=0 206da2e3ebdSchin fi 207da2e3ebdSchin continue 208da2e3ebdSchin fi 209da2e3ebdSchin if [[ $__mkmsgs__ && $__line__ == '%{'* ]] 210da2e3ebdSchin then __skip__=1 211da2e3ebdSchin continue 212da2e3ebdSchin fi 213da2e3ebdSchin if [[ $__mkmsgs__ ]] 214da2e3ebdSchin then if [[ $__line__ == '%#'*';;'* ]] 215da2e3ebdSchin then __line__=${__line__#'%#'} 216da2e3ebdSchin __num__=${__line__%';;'*} 217da2e3ebdSchin read -r __line__ 218da2e3ebdSchin elif [[ $__line__ == %* ]] 219da2e3ebdSchin then continue 220da2e3ebdSchin else print -u2 $"$__command__: unrecognized line=$__line__" 221da2e3ebdSchin __code__=1 222da2e3ebdSchin fi 223da2e3ebdSchin else case $__line__ in 224da2e3ebdSchin +([0-9])' '*) 225da2e3ebdSchin __num__=${__line__%%' '*} 226da2e3ebdSchin __line__=${__line__#*'"'} 227da2e3ebdSchin __line__=${__line__%'"'} 228da2e3ebdSchin ;; 229da2e3ebdSchin *) continue 230da2e3ebdSchin ;; 231da2e3ebdSchin esac 232da2e3ebdSchin fi 233da2e3ebdSchin __index__["$__line__"]=$__num__ 234da2e3ebdSchin __text__[$__num__]=$__line__ 235da2e3ebdSchin if (( __max__ < __num__ )) 236da2e3ebdSchin then (( __max__=__num__ )) 237da2e3ebdSchin fi 238da2e3ebdSchin done < $__out__ 239da2e3ebdSchin (( __new__=__max__+1 )) 240da2e3ebdSchin else __tmp__=$__out__ 241da2e3ebdSchin (( __new__=1 )) 242da2e3ebdSchin fi 243da2e3ebdSchin if (( __code__ )) 244da2e3ebdSchin then exit $__code__ 245da2e3ebdSchin fi 246da2e3ebdSchin exec 1>$__tmp__ 9>&1 247da2e3ebdSchin print -r -- '$'" ${__out__%.msg} message catalog" 248da2e3ebdSchin print -r -- '$translation'" $__command__ $(date +%Y-%m-%d)" 249da2e3ebdSchin print -r -- '$set'" $__set__" 250da2e3ebdSchin print -r -- '$quote "' 251da2e3ebdSchin sort -u "${__objv__[@]}" | { 252da2e3ebdSchin while read -r __line__ 253da2e3ebdSchin do __op__=${__line__%% *} 254da2e3ebdSchin __line__=${__line__#* } 255da2e3ebdSchin case $__op__ in 256da2e3ebdSchin cmd) __a1__=${__line__%% *} 257da2e3ebdSchin case $__a1__ in 258da2e3ebdSchin dot_cmd) __a1__=. ;; 259da2e3ebdSchin esac 260da2e3ebdSchin keys $__a1__ 261da2e3ebdSchin ;; 262da2e3ebdSchin def) __a1__=${__line__%% *} 263da2e3ebdSchin __a2__=${__line__#* } 264da2e3ebdSchin eval $__a1__='$'__a2__ 265da2e3ebdSchin ;; 266da2e3ebdSchin str) print -r -- "$__line__" 267da2e3ebdSchin ;; 268da2e3ebdSchin var) __a1__=${__line__%% *} 269da2e3ebdSchin __a2__=${__line__#* } 270da2e3ebdSchin case $__a1__ in 271da2e3ebdSchin [[:digit:]]*) 272da2e3ebdSchin eval __v__='$'$__a2__ 273da2e3ebdSchin __v__='"'${__v__:__a1__+1} 274da2e3ebdSchin ;; 275da2e3ebdSchin *) eval __v__='$'$__a1__ 276da2e3ebdSchin ;; 277da2e3ebdSchin esac 278da2e3ebdSchin if [[ $__v__ == '"'*'"' ]] 279da2e3ebdSchin then print -r -- "$__v__" 280da2e3ebdSchin fi 281da2e3ebdSchin ;; 282da2e3ebdSchin [[:digit:]]*) 283da2e3ebdSchin [[ $__preserve__ ]] && print -r -- "$__line__" 284da2e3ebdSchin ;; 285da2e3ebdSchin '$') print -r -u9 $__op__ include $__line__ 286da2e3ebdSchin ;; 287da2e3ebdSchin esac 288da2e3ebdSchin done 289da2e3ebdSchin for (( __i__=0; __i__ < __cmds__; __i__++ )) 290da2e3ebdSchin do keys ${__cmdv__[__i__]} 291da2e3ebdSchin done 292da2e3ebdSchin } | { 293da2e3ebdSchin __num__=1 294da2e3ebdSchin while read -r __line__ 295da2e3ebdSchin do case $__line__ in 296da2e3ebdSchin '$'[\ \ ]*) 297da2e3ebdSchin print -r -- "$__line__" 298da2e3ebdSchin continue 299da2e3ebdSchin ;; 300da2e3ebdSchin '$'*|*"@(#)"*|*"<"*([[:word:] .-])"@"*([[:word:] .-])">"*([ ])'"'|"http://"*) 301da2e3ebdSchin continue 302da2e3ebdSchin ;; 303da2e3ebdSchin *[[:alpha:]][[:alpha:]]*) 304da2e3ebdSchin __line__=${__line__#*'"'} 305da2e3ebdSchin __line__=${__line__%'"'} 306da2e3ebdSchin if [[ $__line__ ]] 307da2e3ebdSchin then if [[ ${__index__["$__line__"]} ]] 308da2e3ebdSchin then if [[ ! $__preserve__ ]] 309da2e3ebdSchin then __num__=${__index__["$__line__"]} 310da2e3ebdSchin __keep__[$__num__]=1 311da2e3ebdSchin fi 312da2e3ebdSchin else while [[ ${__text__[$__num__]} ]] 313da2e3ebdSchin do (( __num__++ )) 314da2e3ebdSchin done 315da2e3ebdSchin if (( __max__ < __num__ )) 316da2e3ebdSchin then (( __max__=__num__ )) 317da2e3ebdSchin fi 318da2e3ebdSchin if [[ ! $__preserve__ ]] 319da2e3ebdSchin then __keep__[$__num__]=1 320da2e3ebdSchin fi 321da2e3ebdSchin __text__[$__num__]=$__line__ 322da2e3ebdSchin __index__["$__line__"]=$__num__ 323da2e3ebdSchin (( __num__++ )) 324da2e3ebdSchin fi 325da2e3ebdSchin fi 326da2e3ebdSchin ;; 327da2e3ebdSchin esac 328da2e3ebdSchin done 329da2e3ebdSchin if (( __max__ < __num__ )) 330da2e3ebdSchin then (( __max__=__num__ )) 331da2e3ebdSchin fi 332da2e3ebdSchin if [[ $__debug__ ]] 333da2e3ebdSchin then for (( __num__=1; __num__<=__max__; __num__++ )) 334da2e3ebdSchin do if [[ ${__text__[$__num__]} ]] 335da2e3ebdSchin then if (( __num__ > __new__ )) 336da2e3ebdSchin then if [[ ! ${__keep__[$__num__]} ]] 337da2e3ebdSchin then print -r -u2 -- $__num__ HUH '"'"${__text__[$__num__]}"'"' 338da2e3ebdSchin else print -r -u2 -- $__num__ NEW '"'"${__text__[$__num__]}"'"' 339da2e3ebdSchin fi 340da2e3ebdSchin elif [[ ${__keep__[$__num__]} ]] 341da2e3ebdSchin then print -r -u2 -- $__num__ OLD '"'"${__text__[$__num__]}"'"' 342da2e3ebdSchin else print -r -u2 -- $__num__ XXX '"'"${__text__[$__num__]}"'"' 343da2e3ebdSchin fi 344da2e3ebdSchin fi 345da2e3ebdSchin done 346da2e3ebdSchin exit 0 347da2e3ebdSchin fi 348da2e3ebdSchin # check for replacements 349da2e3ebdSchin if [[ ! $__preserve__ ]] 350da2e3ebdSchin then for (( __num__=1; __num__<__new__; __num__++ )) 351da2e3ebdSchin do if [[ ${__text__[$__num__]} && ! ${__keep__[$__num__]} ]] 352da2e3ebdSchin then (( __ndrop__++ )) 353da2e3ebdSchin __drop__[__ndrop__]=$__num__ 354da2e3ebdSchin fi 355da2e3ebdSchin done 356da2e3ebdSchin [[ $__verbose__ ]] && print -u2 $__command__: old:1-$((__new__-1)) new:$__new__-$__max__ drop $__ndrop__ add $((__max__-__new__+1)) 357da2e3ebdSchin if (( __ndrop__ )) 358da2e3ebdSchin then for (( __i__=1; __i__<=__ndrop__; __i__++ )) 359da2e3ebdSchin do (( __old__=${__drop__[$__i__]} )) 360da2e3ebdSchin __oz__[__i__]=$(print -r -- "\"${__text__[$__old__]}\"" | gzip | wc -c) 361da2e3ebdSchin done 362da2e3ebdSchin for (( __num__=__new__; __num__<=__max__; __num__++ )) 363da2e3ebdSchin do [[ ${__text__[$__num__]} ]] || continue 364da2e3ebdSchin __nz__=$(print -r -- "\"${__text__[$__num__]}\"" | gzip | wc -c) 365da2e3ebdSchin __hit__=0 366da2e3ebdSchin (( __bz__=__similar__ )) 367da2e3ebdSchin for (( __i__=1; __i__<=__ndrop__; __i__++ )) 368da2e3ebdSchin do if (( __old__=${__drop__[$__i__]} )) 369da2e3ebdSchin then __z__=$(print -r -- "\"${__text__[$__old__]}\"""\"${__text__[$__num__]}\"" | gzip | wc -c) 370da2e3ebdSchin (( __z__ = (__z__ * 200 / (${__oz__[__i__]} + $__nz__)) - 100 )) 371da2e3ebdSchin if (( __z__ < __bz__ )) 372da2e3ebdSchin then (( __bz__=__z__ )) 373da2e3ebdSchin (( __hit__=__old__ )) 374da2e3ebdSchin (( __hit_i__=__i__ )) 375da2e3ebdSchin fi 376da2e3ebdSchin fi 377da2e3ebdSchin done 378da2e3ebdSchin if (( __hit__ )) 379da2e3ebdSchin then [[ $__verbose__ ]] && print -u2 $__command__: $__hit__ $__num__ $__bz__ 380da2e3ebdSchin __text__[$__hit__]=${__text__[$__num__]} 381da2e3ebdSchin __keep__[$__hit__]=1 382da2e3ebdSchin __drop__[$__hit_i__]=0 383da2e3ebdSchin __text__[$__num__]= 384da2e3ebdSchin __keep__[$__num__]= 385da2e3ebdSchin fi 386da2e3ebdSchin done 387da2e3ebdSchin fi 388da2e3ebdSchin fi 389da2e3ebdSchin # final output 390da2e3ebdSchin for (( __num__=1; __num__<=__max__; __num__++ )) 391da2e3ebdSchin do if [[ ${__text__[$__num__]} && ( $__preserve__ || ${__keep__[$__num__]} ) ]] 392da2e3ebdSchin then print -r -- $__num__ "\"${__text__[$__num__]}\"" 393da2e3ebdSchin fi 394da2e3ebdSchin done 395da2e3ebdSchin } 396da2e3ebdSchin if [[ $__tmp__ != $__out__ ]] 397da2e3ebdSchin then grep -v '^\$' $__tmp__ > ${__tmp__}n 398da2e3ebdSchin [[ -f $__out__ ]] && grep -v '^\$' $__out__ > ${__tmp__}o 399da2e3ebdSchin cmp -s ${__tmp__}n ${__tmp__}o || { 400da2e3ebdSchin [[ -f $__out__ ]] && mv $__out__ $__out__.old 401da2e3ebdSchin mv $__tmp__ $__out__ 402da2e3ebdSchin } 403da2e3ebdSchin fi 404da2e3ebdSchinfi 405da2e3ebdSchinexit $__code__ 406