1f2e35a3aSmrg#!/usr/bin/perl -w
204b94745Smrg# $XTermId: print-vt-chars.pl,v 1.23 2020/12/13 15:05:06 tom Exp $
3f2e35a3aSmrg# -----------------------------------------------------------------------------
4f2e35a3aSmrg# this file is part of xterm
5f2e35a3aSmrg#
6f2e35a3aSmrg# Copyright 2018,2020 by Thomas E. Dickey
7f2e35a3aSmrg#
8f2e35a3aSmrg#                         All Rights Reserved
9f2e35a3aSmrg#
10f2e35a3aSmrg# Permission is hereby granted, free of charge, to any person obtaining a
11f2e35a3aSmrg# copy of this software and associated documentation files (the
12f2e35a3aSmrg# "Software"), to deal in the Software without restriction, including
13f2e35a3aSmrg# without limitation the rights to use, copy, modify, merge, publish,
14f2e35a3aSmrg# distribute, sublicense, and/or sell copies of the Software, and to
15f2e35a3aSmrg# permit persons to whom the Software is furnished to do so, subject to
16f2e35a3aSmrg# the following conditions:
17f2e35a3aSmrg#
18f2e35a3aSmrg# The above copyright notice and this permission notice shall be included
19f2e35a3aSmrg# in all copies or substantial portions of the Software.
20f2e35a3aSmrg#
21f2e35a3aSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22f2e35a3aSmrg# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23f2e35a3aSmrg# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24f2e35a3aSmrg# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
25f2e35a3aSmrg# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26f2e35a3aSmrg# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27f2e35a3aSmrg# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28f2e35a3aSmrg#
29f2e35a3aSmrg# Except as contained in this notice, the name(s) of the above copyright
30f2e35a3aSmrg# holders shall not be used in advertising or otherwise to promote the
31f2e35a3aSmrg# sale, use or other dealings in this Software without prior written
32f2e35a3aSmrg# authorization.
33f2e35a3aSmrg# -----------------------------------------------------------------------------
34f2e35a3aSmrg# Print GL and GR, with the same charset (if possible) for testing.
35f2e35a3aSmrg
36f2e35a3aSmrguse strict;
37f2e35a3aSmrguse warnings;
38f2e35a3aSmrg
39f2e35a3aSmrg$| = 2;
40f2e35a3aSmrg
41f2e35a3aSmrguse Getopt::Std;
42f2e35a3aSmrg
43f2e35a3aSmrgour ( $opt_L, $opt_l, $opt_R, $opt_r, $opt_v );
44f2e35a3aSmrg
45f2e35a3aSmrgour %charsets;
46f2e35a3aSmrgour %caseless;
47f2e35a3aSmrgour $vt_level;
48f2e35a3aSmrg
49f2e35a3aSmrgbinmode STDOUT;
50f2e35a3aSmrg
51f2e35a3aSmrgsub NRC($) {
52f2e35a3aSmrg    printf "\033[?42%s", $_[0] ? "h" : "l";
53f2e35a3aSmrg}
54f2e35a3aSmrg
55f2e35a3aSmrgsub LS0($) {
56f2e35a3aSmrg    printf "\017";
57f2e35a3aSmrg}
58f2e35a3aSmrg
59f2e35a3aSmrgsub LS1() {
60f2e35a3aSmrg    printf "\016";
61f2e35a3aSmrg}
62f2e35a3aSmrg
63f2e35a3aSmrgsub LS1R() {
64f2e35a3aSmrg    printf "\033~";
65f2e35a3aSmrg}
66f2e35a3aSmrg
67f2e35a3aSmrgsub LS2() {
68f2e35a3aSmrg    printf "\033n";
69f2e35a3aSmrg}
70f2e35a3aSmrg
71f2e35a3aSmrgsub LS2R() {
72f2e35a3aSmrg    printf "\033}";
73f2e35a3aSmrg}
74f2e35a3aSmrg
75f2e35a3aSmrgsub LS3() {
76f2e35a3aSmrg    printf "\033o";
77f2e35a3aSmrg}
78f2e35a3aSmrg
79f2e35a3aSmrgsub LS3R($) {
80f2e35a3aSmrg    printf "\033|";
81f2e35a3aSmrg}
82f2e35a3aSmrg
83f2e35a3aSmrgsub G0($) {
84f2e35a3aSmrg    my %charset = %{ $_[0] };
85f2e35a3aSmrg    printf "\033(%s", $charset{TAG} if ( $charset{HOW} == 0 );
86f2e35a3aSmrg}
87f2e35a3aSmrg
88f2e35a3aSmrgsub G1($) {
89f2e35a3aSmrg    my %charset = %{ $_[0] };
90f2e35a3aSmrg    printf "\033)%s", $charset{TAG} if ( $charset{HOW} == 0 );
91f2e35a3aSmrg    printf "\033-%s", $charset{TAG} if ( $charset{HOW} == 1 );
92f2e35a3aSmrg}
93f2e35a3aSmrg
94f2e35a3aSmrgsub G2($) {
95f2e35a3aSmrg    my %charset = %{ $_[0] };
96f2e35a3aSmrg    printf "\033*%s", $charset{TAG} if ( $charset{HOW} == 0 );
97f2e35a3aSmrg    printf "\033.%s", $charset{TAG} if ( $charset{HOW} == 1 );
98f2e35a3aSmrg}
99f2e35a3aSmrg
100f2e35a3aSmrgsub G3($) {
101f2e35a3aSmrg    my %charset = %{ $_[0] };
102f2e35a3aSmrg    printf "\033+%s", $charset{TAG} if ( $charset{HOW} == 0 );
103f2e35a3aSmrg    printf "\033/%s", $charset{TAG} if ( $charset{HOW} == 1 );
104f2e35a3aSmrg}
105f2e35a3aSmrg
106f2e35a3aSmrgsub init_charset($$$$$$) {
107f2e35a3aSmrg    my %charset;
108f2e35a3aSmrg    my $mixed = shift;
109f2e35a3aSmrg    $charset{WHO}     = $mixed;
110f2e35a3aSmrg    $charset{HOW}     = shift;
111f2e35a3aSmrg    $charset{TAG}     = shift;
112f2e35a3aSmrg    $charset{MIN}     = shift;
113f2e35a3aSmrg    $charset{MAX}     = shift;
114f2e35a3aSmrg    $charset{NRC}     = shift;
115f2e35a3aSmrg    $charsets{$mixed} = \%charset;
116f2e35a3aSmrg    my $lower = lc $charset{WHO};
117f2e35a3aSmrg    $caseless{$lower} = $charset{WHO};
118f2e35a3aSmrg}
119f2e35a3aSmrg
120f2e35a3aSmrgsub find_charset($) {
121f2e35a3aSmrg    my $mixed = shift;
122f2e35a3aSmrg    my $lower = lc $mixed;
123f2e35a3aSmrg    my %result;
124f2e35a3aSmrg    if ( $caseless{$lower} ) {
125f2e35a3aSmrg        $mixed  = $caseless{$lower};
126f2e35a3aSmrg        %result = %{ $charsets{$mixed} };
127f2e35a3aSmrg        undef %result
128f2e35a3aSmrg          if ( $result{MAX} < $vt_level or $result{MIN} > $vt_level );
129f2e35a3aSmrg    }
130f2e35a3aSmrg    printf STDERR "? no match for $mixed with VT-level $vt_level\n"
131f2e35a3aSmrg      unless %result;
132f2e35a3aSmrg    return \%result;
133f2e35a3aSmrg}
134f2e35a3aSmrg
135f2e35a3aSmrgsub failed($) {
136f2e35a3aSmrg    my $msg = shift;
137f2e35a3aSmrg    printf STDERR "? %s\n", $msg;
138f2e35a3aSmrg    exit 1;
139f2e35a3aSmrg}
140f2e35a3aSmrg
141f2e35a3aSmrgsub valid_code($) {
142f2e35a3aSmrg    my $code   = shift;
143f2e35a3aSmrg    my $result = 0;
144f2e35a3aSmrg    $result = 1 if ( $code =~ /^[0-3]$/ );
145f2e35a3aSmrg    return $result;
146f2e35a3aSmrg}
147f2e35a3aSmrg
148f2e35a3aSmrgsub valid_name($) {
149f2e35a3aSmrg    my $mixed  = shift;
150f2e35a3aSmrg    my $lower  = lc $mixed;
151f2e35a3aSmrg    my $result = 0;
152f2e35a3aSmrg    $result = 1 if ( defined( $caseless{$lower} ) );
153f2e35a3aSmrg    return $result;
154f2e35a3aSmrg}
155f2e35a3aSmrg
156f2e35a3aSmrgsub setup_charsets($$$$) {
157f2e35a3aSmrg    my $gl_code = shift;
158f2e35a3aSmrg    my $gl_name = shift;
159f2e35a3aSmrg    my $gr_code = shift;
160f2e35a3aSmrg    my $gr_name = shift;
161f2e35a3aSmrg    my %gl_data = %{ &find_charset($gl_name) };
162f2e35a3aSmrg    my %gr_data = %{ &find_charset($gr_name) };
163f2e35a3aSmrg
164f2e35a3aSmrg    return 0 unless %gl_data;
165f2e35a3aSmrg    return 0 unless %gr_data;
166f2e35a3aSmrg
167f2e35a3aSmrg    &NRC(1) if ( $gl_data{NRC} or $gr_data{NRC} );
168f2e35a3aSmrg
169f2e35a3aSmrg    if ( $gl_code == 0 ) {
170f2e35a3aSmrg        &G0( \%gl_data );
171f2e35a3aSmrg        &LS0;
172f2e35a3aSmrg    }
173f2e35a3aSmrg    elsif ( $gl_code == 1 ) {
174f2e35a3aSmrg        &G1( \%gl_data );
175f2e35a3aSmrg        &LS1;
176f2e35a3aSmrg    }
177f2e35a3aSmrg    elsif ( $gl_code == 2 ) {
178f2e35a3aSmrg        &G2( \%gl_data );
179f2e35a3aSmrg        &LS2;
180f2e35a3aSmrg    }
181f2e35a3aSmrg    elsif ( $gl_code == 3 ) {
182f2e35a3aSmrg        &G3( \%gl_data );
183f2e35a3aSmrg        &LS3;
184f2e35a3aSmrg    }
185f2e35a3aSmrg
186f2e35a3aSmrg    if ( $gr_code == 0 ) {
187f2e35a3aSmrg        &G0( \%gr_data );
188f2e35a3aSmrg    }
189f2e35a3aSmrg    elsif ( $gr_code == 1 ) {
190f2e35a3aSmrg        &G1( \%gr_data );
191f2e35a3aSmrg        &LS1R;
192f2e35a3aSmrg    }
193f2e35a3aSmrg    elsif ( $gr_code == 2 ) {
194f2e35a3aSmrg        &G2( \%gr_data );
195f2e35a3aSmrg        &LS2R;
196f2e35a3aSmrg    }
197f2e35a3aSmrg    elsif ( $gr_code == 3 ) {
198f2e35a3aSmrg        &G3( \%gr_data );
199f2e35a3aSmrg        &LS3R;
200f2e35a3aSmrg    }
201f2e35a3aSmrg    return 1;
202f2e35a3aSmrg}
203f2e35a3aSmrg
204f2e35a3aSmrgsub cleanup() {
205f2e35a3aSmrg    &setup_charsets( 0, "ASCII", 1, "ASCII" );
206f2e35a3aSmrg    &NRC(0);
207f2e35a3aSmrg}
208f2e35a3aSmrg
209f2e35a3aSmrgsub doit($$$$) {
210f2e35a3aSmrg    my $gl_code = shift;
211f2e35a3aSmrg    my $gl_name = shift;
212f2e35a3aSmrg    my $gr_code = shift;
213f2e35a3aSmrg    my $gr_name = shift;
214f2e35a3aSmrg
215f2e35a3aSmrg    &failed("Illegal left-code $gl_code")     unless &valid_code($gl_code);
216f2e35a3aSmrg    &failed("Illegal right-code $gr_code")    unless &valid_code($gr_code);
217f2e35a3aSmrg    &failed("Unknown left-charset $gl_name")  unless &valid_name($gl_name);
218f2e35a3aSmrg    &failed("Unknown right charset $gr_name") unless &valid_name($gr_name);
219f2e35a3aSmrg
220f2e35a3aSmrg    printf "GL (G%d %s):\n", $gl_code, $gl_name;
221f2e35a3aSmrg    if ( &setup_charsets( $gl_code, $gl_name, $gr_code, $gr_name ) ) {
222f2e35a3aSmrg
223f2e35a3aSmrg        for my $c ( 32 .. 127 ) {
224f2e35a3aSmrg            printf "%c", $c;
225f2e35a3aSmrg            printf "\n" if ( ( ( $c - 31 ) % 16 ) == 0 );
226f2e35a3aSmrg        }
227f2e35a3aSmrg        printf "\n";
228f2e35a3aSmrg
229f2e35a3aSmrg        &cleanup;
230f2e35a3aSmrg    }
231f2e35a3aSmrg
232f2e35a3aSmrg    printf "GR (G%d %s):\n", $gr_code, $gr_name;
233f2e35a3aSmrg    if ( &setup_charsets( $gl_code, $gl_name, $gr_code, $gr_name ) ) {
234f2e35a3aSmrg
235f2e35a3aSmrg        for my $c ( 32 .. 127 ) {
236f2e35a3aSmrg            printf "%c", $c + 128;
237f2e35a3aSmrg            printf "\n" if ( ( ( $c - 31 ) % 16 ) == 0 );
238f2e35a3aSmrg        }
239f2e35a3aSmrg        printf "\n";
240f2e35a3aSmrg
241f2e35a3aSmrg        &cleanup;
242f2e35a3aSmrg    }
243f2e35a3aSmrg}
244f2e35a3aSmrg
245f2e35a3aSmrgsub main::HELP_MESSAGE() {
246f2e35a3aSmrg    printf STDERR <<EOF
247f2e35a3aSmrgUsage: $0 [options]
248f2e35a3aSmrg
249f2e35a3aSmrgOptions:
250f2e35a3aSmrg
251f2e35a3aSmrg -L code    index 0-3 for GL
252f2e35a3aSmrg -l name    charset to map to GL
253f2e35a3aSmrg -R code    index 0-3 for GR
254f2e35a3aSmrg -r name    charset to map to GR
255f2e35a3aSmrg -v level   set/override VT-level
256f2e35a3aSmrg
257f2e35a3aSmrgCharsets are determined by the VT-level (currently VT${vt_level}xx):
258f2e35a3aSmrgEOF
259f2e35a3aSmrg      ;
260f2e35a3aSmrg    my @known;
261f2e35a3aSmrg    my $known = -1;
262f2e35a3aSmrg    my $width = 0;
263f2e35a3aSmrg    foreach my $key ( sort( keys %charsets ) ) {
264f2e35a3aSmrg        my %charset = %{ $charsets{$key} };
265f2e35a3aSmrg        next if ( $charset{MAX} < $vt_level );
266f2e35a3aSmrg        next if ( $charset{MIN} > $vt_level );
267f2e35a3aSmrg        $known[ ++$known ] = $key;
268f2e35a3aSmrg        $width = length($key) if ( length($key) > $width );
269f2e35a3aSmrg    }
270f2e35a3aSmrg    $width += 3;
271f2e35a3aSmrg    my $cols = int( 78 / $width );
272f2e35a3aSmrg    my $high = int( ( $known + $cols ) / $cols );
273f2e35a3aSmrg    for my $y ( 0 .. $high - 1 ) {
274f2e35a3aSmrg        printf STDERR " ";
275f2e35a3aSmrg        for my $x ( 0 .. $cols - 1 ) {
276f2e35a3aSmrg            my $z = $x * $high + $y;
277f2e35a3aSmrg            next if ( $z > $known );
278f2e35a3aSmrg            printf STDERR "%-*s", $width, $known[$z];
279f2e35a3aSmrg        }
280f2e35a3aSmrg        printf STDERR "\n";
281f2e35a3aSmrg    }
282f2e35a3aSmrg    exit 1;
283f2e35a3aSmrg}
284f2e35a3aSmrg
285f2e35a3aSmrg&init_charset( "ASCII",              0, 'B',  1, 9, 0 );
286f2e35a3aSmrg&init_charset( "British",            0, 'A',  1, 9, 0 );
287f2e35a3aSmrg&init_charset( "DEC_Spec_Graphic",   0, '0',  1, 9, 0 );
288f2e35a3aSmrg&init_charset( "DEC_Alt_Chars",      0, '1',  1, 1, 0 );
289f2e35a3aSmrg&init_charset( "DEC_Alt_Graphics",   0, '2',  1, 1, 0 );
290f2e35a3aSmrg&init_charset( "DEC_Supp",           0, '<',  2, 9, 0 );
291f2e35a3aSmrg&init_charset( "Dutch",              0, '4',  2, 9, 1 );
292f2e35a3aSmrg&init_charset( "Finnish",            0, '5',  2, 9, 1 );
293f2e35a3aSmrg&init_charset( "Finnish2",           0, 'C',  2, 9, 1 );
294f2e35a3aSmrg&init_charset( "French",             0, 'R',  2, 9, 1 );
295f2e35a3aSmrg&init_charset( "French2",            0, 'f',  2, 9, 1 );
296f2e35a3aSmrg&init_charset( "French_Canadian",    0, 'Q',  2, 9, 1 );
297f2e35a3aSmrg&init_charset( "German",             0, 'K',  2, 9, 1 );
298f2e35a3aSmrg&init_charset( "Italian",            0, 'Y',  2, 9, 1 );
299f2e35a3aSmrg&init_charset( "Norwegian_Danish2",  0, 'E',  2, 9, 1 );
300f2e35a3aSmrg&init_charset( "Norwegian_Danish3",  0, '6',  2, 9, 1 );
301f2e35a3aSmrg&init_charset( "Spanish",            0, 'Z',  2, 9, 1 );
302f2e35a3aSmrg&init_charset( "Swedish",            0, '7',  2, 9, 1 );
303f2e35a3aSmrg&init_charset( "Swedish2",           0, 'H',  2, 9, 1 );
304f2e35a3aSmrg&init_charset( "Swiss",              0, '=',  2, 9, 1 );
305f2e35a3aSmrg&init_charset( "British_Latin_1",    0, 'A',  3, 9, 1 );
306f2e35a3aSmrg&init_charset( "DEC_Supp_Graphic",   0, '%5', 3, 9, 0 );
307f2e35a3aSmrg&init_charset( "DEC_Technical",      0, '>',  3, 9, 0 );
308f2e35a3aSmrg&init_charset( "French_Canadian2",   0, '9',  3, 9, 1 );
309f2e35a3aSmrg&init_charset( "Norwegian_Danish",   0, '`',  3, 9, 1 );
310f2e35a3aSmrg&init_charset( "Portuguese",         0, '%6', 3, 9, 1 );
311f2e35a3aSmrg&init_charset( "ISO_Greek_Supp",     1, 'F',  5, 9, 0 );
312f2e35a3aSmrg&init_charset( "ISO_Hebrew_Supp",    1, 'H',  5, 9, 0 );
313f2e35a3aSmrg&init_charset( "ISO_Latin_5_Supp",   1, 'M',  5, 9, 0 );
314f2e35a3aSmrg&init_charset( "ISO_Latin_Cyrillic", 1, 'L',  5, 9, 0 );
315f2e35a3aSmrg&init_charset( "Greek",              0, '">', 5, 9, 1 );
316f2e35a3aSmrg&init_charset( "DEC_Greek",          0, '"?', 5, 9, 1 );
317f2e35a3aSmrg&init_charset( "Cyrillic",           0, '&4', 5, 9, 0 );
318f2e35a3aSmrg&init_charset( "DEC_Hebrew",         0, '"4', 5, 9, 0 );
319f2e35a3aSmrg&init_charset( "Hebrew",             0, '%=', 5, 9, 1 );
320f2e35a3aSmrg&init_charset( "Russian",            0, '&5', 5, 9, 1 );
321f2e35a3aSmrg&init_charset( "SCS_NRCS",           0, '%3', 5, 9, 0 );
322f2e35a3aSmrg&init_charset( "Turkish",            0, '%2', 5, 9, 1 );
323f2e35a3aSmrg&init_charset( "DEC_Turkish",        0, '%0', 5, 9, 0 );
324f2e35a3aSmrg
325f2e35a3aSmrg$vt_level = 1;    # don't expect much
326f2e35a3aSmrgif ( -t 0 and -t 1 ) {
327f2e35a3aSmrg    my $da2 = `
328f2e35a3aSmrg	old=\$(stty -g);
329f2e35a3aSmrg	stty raw -echo min 0  time 5;
330f2e35a3aSmrg	printf '\033[>c' >/dev/tty;
331f2e35a3aSmrg	read response;
332f2e35a3aSmrg	stty \$old;
333f2e35a3aSmrg	echo "\$response"`;
334f2e35a3aSmrg    if ( $da2 =~ /^\033\[>\d+;\d+;\d+c$/ ) {
335f2e35a3aSmrg        my $Pp = $da2;
336f2e35a3aSmrg        $Pp =~ s/^.*>//;
337f2e35a3aSmrg        $Pp =~ s/;.*$//;
338f2e35a3aSmrg        if ( $Pp == 0 ) {
339f2e35a3aSmrg            $vt_level = 1;
340f2e35a3aSmrg        }
341f2e35a3aSmrg        elsif ( $Pp == 1 or $Pp == 2 ) {
342f2e35a3aSmrg            $vt_level = 2;
343f2e35a3aSmrg        }
344f2e35a3aSmrg        elsif ( $Pp == 18 or $Pp == 19 or $Pp == 24 ) {
345f2e35a3aSmrg            $vt_level = 3;
346f2e35a3aSmrg        }
347f2e35a3aSmrg        elsif ( $Pp == 41 ) {
348f2e35a3aSmrg            $vt_level = 4;
349f2e35a3aSmrg        }
350f2e35a3aSmrg        elsif ( $Pp == 61 or $Pp == 64 or $Pp == 65 ) {
351f2e35a3aSmrg            $vt_level = 5;
352f2e35a3aSmrg        }
353f2e35a3aSmrg    }
354f2e35a3aSmrg}
355f2e35a3aSmrg
356f2e35a3aSmrg$Getopt::Std::STANDARD_HELP_VERSION = 1;
357f2e35a3aSmrg&getopts('L:l:R:r:v:') || main::HELP_MESSAGE;
358f2e35a3aSmrg$vt_level = $opt_v if ( defined $opt_v );
359f2e35a3aSmrg&failed("VT-level must be 1-5") if ( $vt_level < 1 or $vt_level > 5 );
360f2e35a3aSmrg
361f2e35a3aSmrgif ( $#ARGV >= 0 ) {
362f2e35a3aSmrg    while ( $#ARGV >= 0 ) {
363f2e35a3aSmrg        my $name = shift @ARGV;
364f2e35a3aSmrg        &doit(
365f2e35a3aSmrg            defined($opt_L) ? $opt_L : 2,        #
366f2e35a3aSmrg            defined($opt_l) ? $opt_l : $name,    #
367f2e35a3aSmrg            defined($opt_R) ? $opt_R : 3,        #
368f2e35a3aSmrg            defined($opt_r) ? $opt_r : $name
369f2e35a3aSmrg        );
370f2e35a3aSmrg        last
371f2e35a3aSmrg          if (
372f2e35a3aSmrg            defined($opt_L)                      #
373f2e35a3aSmrg            and defined($opt_l)                  #
374f2e35a3aSmrg            and defined($opt_R)                  #
375f2e35a3aSmrg            and defined($opt_r)
376f2e35a3aSmrg          );
377f2e35a3aSmrg    }
378f2e35a3aSmrg}
379f2e35a3aSmrgelse {
380f2e35a3aSmrg    &doit(
381f2e35a3aSmrg        defined($opt_L) ? $opt_L : 2,            #
382f2e35a3aSmrg        defined($opt_l) ? $opt_l : "ASCII",      #
383f2e35a3aSmrg        defined($opt_R) ? $opt_R : 3,            #
384f2e35a3aSmrg        defined($opt_r) ? $opt_r : "ASCII"
385f2e35a3aSmrg    );
386f2e35a3aSmrg}
387f2e35a3aSmrg
388f2e35a3aSmrg1;
389