Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/msgcc/msgcc.sh
1808 views
1
########################################################################
2
# #
3
# This software is part of the ast package #
4
# Copyright (c) 2000-2011 AT&T Intellectual Property #
5
# and is licensed under the #
6
# Eclipse Public License, Version 1.0 #
7
# by AT&T Intellectual Property #
8
# #
9
# A copy of the License is available at #
10
# http://www.eclipse.org/org/documents/epl-v10.html #
11
# (with md5 checksum b35adb5213ca9657e911e9befb180842) #
12
# #
13
# Information and Software Systems Research #
14
# AT&T Research #
15
# Florham Park NJ #
16
# #
17
# Glenn Fowler <[email protected]> #
18
# #
19
########################################################################
20
: C language message catalog compiler
21
22
# NOTE: all variable names match __*__ to avoid clash with msgcpp def vars
23
24
__command__=msgcc
25
integer __similar__=30
26
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) 2010-10-20 $
32
]
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 threshold.
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 threshold is '$__similar__$'. A
60
threshold 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.]
64
}
65
66
file ...
67
68
[+SEE ALSO?\bcc\b(1), \bcpp\b(1), \bgencat\b(1), \bmsggen\b(1),
69
\bmsgcpp\b(1), \bmsgcvt\b(1)]
70
'
71
;;
72
*) ARGV0=""
73
USAGE="M:[-option] [ cc-options ] file ..."
74
;;
75
esac
76
77
usage()
78
{
79
OPTIND=0
80
getopts $ARGV0 "$USAGE" OPT '-?'
81
exit 2
82
}
83
84
keys()
85
{
86
$1 --??keys -- 2>&1 | grep '^".*"$'
87
}
88
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__=
97
98
case " $* " in
99
*" --"*|*" -?"*)
100
while getopts $ARGV0 "$USAGE" OPT
101
do case $OPT in
102
*) break ;;
103
esac
104
done
105
;;
106
esac
107
while :
108
do case $# in
109
0) break ;;
110
esac
111
__arg__=$1
112
case $__arg__ in
113
-c) __compile__=1
114
;;
115
-[DIU]*)__argv__[__args__]=$__arg__
116
(( __args__++ ))
117
;;
118
-E) __preprocess__=1
119
;;
120
-M-debug)
121
__debug__=1
122
;;
123
-M-mkmsgs)
124
__mkmsgs__=1
125
;;
126
-M-new) __merge__=
127
;;
128
-M-perserve)
129
__preserve__=1
130
;;
131
-M-set=*)
132
__set__=$(msggen -s ${__arg__#*=}.1)
133
;;
134
-M-similar=*)
135
__similar__=${__arg__#*=}
136
;;
137
-M-verbose)
138
__verbose__=1
139
;;
140
-o) case $# in
141
1) print -u2 $"$__command__: output argument expected"
142
exit 1
143
;;
144
esac
145
shift
146
__out__=${1%.*}.msg
147
__OUT__=$1
148
;;
149
[-+]*|*.[aAlLsS]*)
150
;;
151
*.[cCiI]*|*.[oO]*)
152
case $__arg__ in
153
*.[oO]*);;
154
*) __srcv__[__files__]=$__arg__
155
(( __sources__++ ))
156
;;
157
esac
158
__arg__=${__arg__##*/}
159
__arg__=${__arg__%.*}.mso
160
__objv__[__files__]=$__arg__
161
(( __files__++ ))
162
;;
163
*.ms[go])
164
__objv__[__files__]=$__arg__
165
(( __files__++ ))
166
;;
167
*) __cmdv__[__cmds__]=$__arg__
168
(( __cmds__++ ))
169
;;
170
esac
171
shift
172
done
173
__arg__=${__out__##*/}
174
__arg__=${__arg__%.msg}
175
if [[ -x $__arg__ ]]
176
then __cmdv__[__cmds__]=$__arg__
177
(( __cmds__++ ))
178
fi
179
180
# generate the .mso files
181
182
if [[ $__OUT__ && $__compile__ ]]
183
then __objv__[0]=$__OUT__
184
fi
185
186
if (( __sources__ ))
187
then for (( __i__=0; __i__<=__files__; __i__++ ))
188
do if [[ ${__srcv__[__i__]} ]]
189
then if (( __sources__ > 1 ))
190
then print "${__srcv__[__i__]}:"
191
fi
192
if [[ $__preprocess__ ]]
193
then msgcpp "${__argv__[@]}" "${__srcv__[__i__]}"
194
else msgcpp "${__argv__[@]}" "${__srcv__[__i__]}" > "${__objv__[__i__]}"
195
fi
196
fi
197
done
198
fi
199
200
# combine the .mso and .msg files
201
202
if [[ ! $__compile__ && ! $__preprocess__ ]]
203
then if [[ $__merge__ && -r $__out__ ]]
204
then __tmp__=$__out__.tmp
205
trap '__code__=$?; rm -f ${__tmp__}*; exit $__code__' 0 1 2
206
while read -r __line__
207
do if (( $__skip__ ))
208
then if [[ $__line__ == '%}'* ]]
209
then __skip__=0
210
fi
211
continue
212
fi
213
if [[ $__mkmsgs__ && $__line__ == '%{'* ]]
214
then __skip__=1
215
continue
216
fi
217
if [[ $__mkmsgs__ ]]
218
then if [[ $__line__ == '%#'*';;'* ]]
219
then __line__=${__line__#'%#'}
220
__num__=${__line__%';;'*}
221
read -r __line__
222
elif [[ $__line__ == %* ]]
223
then continue
224
else print -u2 $"$__command__: unrecognized line=$__line__"
225
__code__=1
226
fi
227
else case $__line__ in
228
+([0-9])' '*)
229
__num__=${__line__%%' '*}
230
__line__=${__line__#*'"'}
231
__line__=${__line__%'"'}
232
;;
233
*) continue
234
;;
235
esac
236
fi
237
__index__["$__line__"]=$__num__
238
__text__[$__num__]=$__line__
239
if (( __max__ < __num__ ))
240
then (( __max__=__num__ ))
241
fi
242
done < $__out__
243
(( __new__=__max__+1 ))
244
else __tmp__=$__out__
245
(( __new__=1 ))
246
fi
247
if (( __code__ ))
248
then exit $__code__
249
fi
250
exec 1>$__tmp__ 9>&1
251
print -r -- '$'" ${__out__%.msg} message catalog"
252
print -r -- '$translation'" $__command__ $(date +%Y-%m-%d)"
253
print -r -- '$set'" $__set__"
254
print -r -- '$quote "'
255
sort -u "${__objv__[@]}" | {
256
__raw__=
257
while read -r __line__
258
do __op__=${__line__%% *}
259
__line__=${__line__#* }
260
case $__op__ in
261
cmd) __a1__=${__line__%% *}
262
case $__a1__ in
263
dot_cmd) __a1__=. ;;
264
esac
265
keys $__a1__
266
;;
267
def) __a1__=${__line__%% *}
268
__a2__=${__line__#* }
269
eval $__a1__='$'__a2__
270
;;
271
str) print -r -- "$__line__"
272
;;
273
raw) __raw__=$__raw__$'\n'$__line__
274
;;
275
var) __a1__=${__line__%% *}
276
__a2__=${__line__#* }
277
case $__a1__ in
278
[[:digit:]]*)
279
eval __v__='$'$__a2__
280
__v__='"'${__v__:__a1__+1}
281
;;
282
*) eval __v__='$'$__a1__
283
;;
284
esac
285
if [[ $__v__ == '"'*'"' ]]
286
then print -r -- "$__v__"
287
fi
288
;;
289
[[:digit:]]*)
290
[[ $__preserve__ ]] && print -r -- "$__line__"
291
;;
292
'$') print -r -u9 $__op__ include $__line__
293
;;
294
esac
295
done
296
for (( __i__=0; __i__ < __cmds__; __i__++ ))
297
do keys ${__cmdv__[__i__]}
298
done
299
[[ $__raw__ ]] && print -r "${__raw__#?}" | sed -e 's/^"//' -e 's/"$//' -e 's/\\/&&/g' -e 's/"/\\"/g' -e 's/.*/$RAW$"&"/'
300
} | {
301
__num__=1
302
while read -r __line__
303
do case $__line__ in
304
'$RAW$'*)
305
;;
306
'$'[\ \ ]*)
307
print -r -- "$__line__"
308
continue
309
;;
310
'$'*|*"@(#)"*|*"<"*([[:word:] .-])"@"*([[:word:] .-])">"*([ ])'"'|"http://"*)
311
continue
312
;;
313
*[[:alpha:]][[:alpha:]]*)
314
;;
315
*) continue
316
;;
317
esac
318
__line__=${__line__#*'"'}
319
__line__=${__line__%'"'}
320
if [[ $__line__ ]]
321
then if [[ ${__index__["$__line__"]} ]]
322
then if [[ ! $__preserve__ ]]
323
then __num__=${__index__["$__line__"]}
324
__keep__[$__num__]=1
325
fi
326
else while [[ ${__text__[$__num__]} ]]
327
do (( __num__++ ))
328
done
329
if (( __max__ < __num__ ))
330
then (( __max__=__num__ ))
331
fi
332
if [[ ! $__preserve__ ]]
333
then __keep__[$__num__]=1
334
fi
335
__text__[$__num__]=$__line__
336
__index__["$__line__"]=$__num__
337
(( __num__++ ))
338
fi
339
fi
340
done
341
if (( __max__ < __num__ ))
342
then (( __max__=__num__ ))
343
fi
344
if [[ $__debug__ ]]
345
then for (( __num__=1; __num__<=__max__; __num__++ ))
346
do if [[ ${__text__[$__num__]} ]]
347
then if (( __num__ > __new__ ))
348
then if [[ ! ${__keep__[$__num__]} ]]
349
then print -r -u2 -- $__num__ HUH '"'"${__text__[$__num__]}"'"'
350
else print -r -u2 -- $__num__ NEW '"'"${__text__[$__num__]}"'"'
351
fi
352
elif [[ ${__keep__[$__num__]} ]]
353
then print -r -u2 -- $__num__ OLD '"'"${__text__[$__num__]}"'"'
354
else print -r -u2 -- $__num__ XXX '"'"${__text__[$__num__]}"'"'
355
fi
356
fi
357
done
358
exit 0
359
fi
360
# check for replacements
361
if [[ ! $__preserve__ ]]
362
then for (( __num__=1; __num__<__new__; __num__++ ))
363
do if [[ ${__text__[$__num__]} && ! ${__keep__[$__num__]} ]]
364
then (( __ndrop__++ ))
365
__drop__[__ndrop__]=$__num__
366
fi
367
done
368
[[ $__verbose__ ]] && print -u2 $__command__: old:1-$((__new__-1)) new:$__new__-$__max__ drop $__ndrop__ add $((__max__-__new__+1))
369
if (( __ndrop__ ))
370
then for (( __i__=1; __i__<=__ndrop__; __i__++ ))
371
do (( __old__=${__drop__[$__i__]} ))
372
__oz__[__i__]=$(print -r -- "\"${__text__[$__old__]}\"" | gzip | wc -c)
373
done
374
for (( __num__=__new__; __num__<=__max__; __num__++ ))
375
do [[ ${__text__[$__num__]} ]] || continue
376
__nz__=$(print -r -- "\"${__text__[$__num__]}\"" | gzip | wc -c)
377
__hit__=0
378
(( __bz__=__similar__ ))
379
for (( __i__=1; __i__<=__ndrop__; __i__++ ))
380
do if (( __old__=${__drop__[$__i__]} ))
381
then __z__=$(print -r -- "\"${__text__[$__old__]}\"""\"${__text__[$__num__]}\"" | gzip | wc -c)
382
(( __z__ = (__z__ * 200 / (${__oz__[__i__]} + $__nz__)) - 100 ))
383
if (( __z__ < __bz__ ))
384
then (( __bz__=__z__ ))
385
(( __hit__=__old__ ))
386
(( __hit_i__=__i__ ))
387
fi
388
fi
389
done
390
if (( __hit__ ))
391
then [[ $__verbose__ ]] && print -u2 $__command__: $__hit__ $__num__ $__bz__
392
__text__[$__hit__]=${__text__[$__num__]}
393
__keep__[$__hit__]=1
394
__drop__[$__hit_i__]=0
395
__text__[$__num__]=
396
__keep__[$__num__]=
397
fi
398
done
399
fi
400
fi
401
# final output
402
for (( __num__=1; __num__<=__max__; __num__++ ))
403
do if [[ ${__text__[$__num__]} && ( $__preserve__ || ${__keep__[$__num__]} ) ]]
404
then print -r -- $__num__ "\"${__text__[$__num__]}\""
405
fi
406
done
407
}
408
if [[ $__tmp__ != $__out__ ]]
409
then grep -v '^\$' $__tmp__ > ${__tmp__}n
410
[[ -f $__out__ ]] && grep -v '^\$' $__out__ > ${__tmp__}o
411
cmp -s ${__tmp__}n ${__tmp__}o || {
412
[[ -f $__out__ ]] && mv $__out__ $__out__.old
413
mv $__tmp__ $__out__
414
}
415
fi
416
fi
417
exit $__code__
418
419