-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmarky.py
executable file
·1348 lines (1276 loc) · 66 KB
/
marky.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
########################################################################
# marky Markdown Preprocessor ##########################################
########################################################################
# Quick Make Example Project
############################
#
# > mkdir project
# > cp /path/to/marky.py project
# > cd project
# > chmod +x marky.py
# > ./marky.py --init
# > make scan html-all pdf-all httpd
#
# Open: project/pdf/*.pdf
# Goto: http://localhost:8000/
########################################################################
import sys
import argparse
import glob
import os
import base64
import yaml
########################################################################
if not sys.version_info.major == 3 and sys.version_info.minor >= 6:
try:
raise ValueError("marky requires Python 3.6 or higher.")
except Exception as ex:
print("# ERROR", type(ex), str(ex))
sys.exit(1)
########################################################################
_MARKY_VERSION = (0, 9)
########################################################################
# SECTION IS AUTO-PACKAGED USING ./marky.py --pack --force
########################################################################
###!!!:::marky_pack_data:::!!!###
pack_Makefile = '''
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjCgouUEhPTlk6IGhlbHAKaGVscDoKCSMKCSMgbWFya3kgREVQ
RU5ERU5DSUVTCgkjIyMjIyMjIyMjIyMjIyMjIyMjIwoJIyAqIHBhbmRvYyA+PSAyLjEwCgkj
ICogcGlwIGluc3RhbGwgcGFuZG9jLWZpZ25vcwoJIyAqIHBpcCBpbnN0YWxsIHBhbmRvYy1l
cW5vcwoJIyAqIHBpcCBpbnN0YWxsIHBhbmRvYy1zZWNub3MKCSMgKiBwaXAgaW5zdGFsbCBw
YW5kb2MtdGFibGVub3MKCSMgKiBwaXAgaW5zdGFsbCBwYW5kb2MteG5vcwoJIyAqIHBpcCBp
bnN0YWxsIHB5eWFtbAoJIwoJIyBBVFRFTlRJT04KCSMjIyMjIyMjIyMjCgkjIEFsbCBmaWxl
cyBpbiBgYnVpbGQvKi5tZGAgYW5kIGBodG1sLyouaHRtbGAgYXJlIGF1dG8tZ2VuZXJhdGVk
IQoJIyBVc2VyIGZpbGVzIGAqLm1kYCBoYXZlIHRvIGJlIHBsYWNlZCBpbiBgbWQvKi5tZGAh
CgkjIGBtYWtlIGNsZWFuYCBkZWxldGVzIGFsbCBmaWxlcyBpbiBgYnVpbGQvYCwgYGh0bWwv
YCBhbmQgYHBkZi9gLgoJIwoJIyBtYXJreSBVVElMUwoJIyMjIyMjIyMjIyMjIwoJIyAqIG1h
a2UgaGVscCAgICAgICAgICAgIC0gc2hvdyB0aGlzICpIZWxwIE1lc3NhZ2UqCgkjICogbWFr
ZSB0cmVlICAgICAgICAgICAgLSBzaG93IHRoZSAqUHJvamVjdCBUcmVlKgoJIyAqIG1ha2Ug
aHR0cGQgICAgICAgICAgIC0gcnVuIHB5dGhvbiAtbSBodHRwZC5zZXJ2ZXIgaW4gYGh0bWwv
YAoJIyAqIG1ha2UgY2xlYW4gICAgICAgICAgIC0gZGVsZXRlOiBgYnVpbGQvKmAsIGBodG1s
LypgLCBgcGRmLypgCgkjICogbWFrZSBxdWlldCBbLi4uXSAgICAgLSBidWlsZCB3aXRoIGAu
L21hcmt5IC0tcXVpZXQgWy4uLl1gCgkjICogbWFrZSBsaXN0ICAgICAgICAgICAgLSBsaXN0
IGFsbCBzY2FubmVkIGZpbGVzIGFuZCB0YXJnZXRzCgkjCgkjIG1hcmt5IEJVSUxEIEFMTAoJ
IyMjIyMjIyMjIyMjIyMjIyMKCSMgKiBtYWtlIHJlc2NhbiAgICAgICAgICAtPiBgYnVpbGQv
Ki5tYWtlYCwgb3ZlcndyaXRlIGFsbAoJIyAqIG1ha2Ugc2NhbiAgICAgICAgICAgIC0+IGBi
dWlsZC8qLm1ha2VgLCBvbmx5IG5ldyBmaWxlcwoJIyAqIG1ha2UgYnVpbGQgICAgICAgICAg
IC0+IGBidWlsZC8qLntodG1sLHBkZn0ubWRgCgkjICogbWFrZSB0ZXggICAgICAgICAgICAg
LT4gYGJ1aWxkLyoudGV4YAoJIyAqIG1ha2UgaHRtbCAgICAgICAgICAgIC0+IGBodG1sLyou
aHRtbGAKCSMgKiBtYWtlIHBkZiAgICAgICAgICAgICAtPiBgcGRmLyoucGRmYAoJIyAqIG1h
a2UgdGV4ICAgICAgICAgICAgIC0+IGBidWlsZC8qLnRleGAKCSMgKiBtYWtlIGF1eCAgICAg
ICAgICAgICAtPiBydW4gYWxsIGF1eCBjb21tYW5kcwoJIyAqIG1ha2UgYWxsICAgICAgICAg
ICAgIC0+IGBodG1sLyouaHRtbGAsIGBwZGYvKi5wZGZgCgkjCgkjIG1hcmt5IEJVSUxEIEZJ
TEUKCSMjIyMjIyMjIyMjIyMjIyMjIwoJIyAqIG1ha2Ugc2Nhbi9maWxlICAgICAgIC0+IGBi
dWlsZC9maWxlLm1ha2VgLCBvdmVyd3JpdGUKCSMgKiBtYWtlIGJ1aWxkL2ZpbGUgICAgICAt
PiBgYnVpbGQvZmlsZS57aHRtbCxwZGZ9Lm1kLHB5YAoJIyAqIG1ha2UgdGV4L2ZpbGUgICAg
ICAgIC0+IGBidWlsZC9maWxlLnRleGAKCSMgKiBtYWtlIGh0bWwvZmlsZSAgICAgICAtPiBg
aHRtbC9maWxlLmh0bWxgCgkjICogbWFrZSBwZGYvZmlsZSAgICAgICAgLT4gYHBkZi9wZGYu
cGRmYAoJIyAqIG1ha2UgYXV4L2ZpbGUgICAgICAgIC0+IHJ1biBhdXggY29tbWFuZHMgZm9y
IGZpbGUKCSMgKiBtYWtlIGNsZWFuL2ZpbGUgICAgICAtPiBjbGVhbiwgYnV0IGtlZXAgYG1h
a2UscGRmLGh0bWwsdGV4YAoJIwoJIyBFWEFNUExFCgkjIyMjIyMjIyMKCSMgMS4gcnVuIGBt
YWtlIHNjYW47IG1ha2UgaHRtbC9maWxlLmh0bWwgaHR0cGRgOgoJIyAgICAqIGdlbmVyYXRl
IGBidWlsZC9maWxlLm1ha2VgCgkjICAgICogdHJhbnNmb3JtIGBtZC9maWxlLm1kYCAtPiBg
aHRtbC9maWxlLmh0bWxgCgkjICAgICogc3RhcnQgYSBweXRob24gaHR0cGQgc2VydmVyIGlu
IGBodG1sYAoJIyAyLiBydW4gYG1ha2Ugc2NhbjsgbWFrZSBwZGYvZmlsZS5wZGZgCgkjICAg
ICogZ2VuZXJhdGUgYGJ1aWxkL2ZpbGUubWFrZWAKCSMgICAgKiB0cmFuc2Zvcm0gYG1kL2Zp
bGUubWRgIC0+IGBwZGYvZmlsZS5wZGZgCgkjIDMuIHJ1biBgbWFrZSBzY2FuOyBtYWtlIGxp
c3RgOiBsaXN0IGFsbCB0YXJnZXRzCgkjIDQuIHJ1biBgbWFrZSByZXNjYW5gOiBjbGVhciBh
bGwgYXV4IGZpbGUgbWFrZSBkZXBzCgkjCgouUEhPTlk6IHRyZWUKdHJlZToKCSMKCSMgUFJP
SkVDVCBUUkVFCgkjIyMjIyMjIyMjIyMjIwoJIyA8d29ya2luZ19kaXI+CgkjIHwtIG1hcmt5
LnB5ICAgICAgICAgICAgLSBtYXJreSBleGVjdXRhYmxlCgkjIHwtIE1ha2VmaWxlICAgICAg
ICAoKikgLSBtYXJreSBNYWtlZmlsZQoJIyB8LSBwYW5kb2MtcnVuICAgICAgKCopIC0gcGFu
ZG9jIHdyYXBwZXIKCSMgfC0gbWQvICAgICAgICAgICAgICgqKSAtIHVzZXIgTWFya2Rvd24g
ZGlyCgkjIHwgIHwtICoubWQgICAgICAgICAgICAgLSB1c2VyIE1hcmtkb3duIHRleHQKCSMg
fC0gZGF0YS8gICAgICAgICAgICgqKSAtIHVzZXIgZGF0YSBkaXIKCSMgfCAgfC0gKi4qICAg
ICAgICAgICAgICAgIHVzZXIgZGF0YSBmaWxlcwoJIyB8LSBidWlsZC8gICAgICAgICAgKCop
IC0gYnVpbGQgTWFya2Rvd24gZGlyCgkjIHwgIHwtICoucHkgICAgICAgICAoKikgLSBtYXJr
eSBQeXRob24gY29kZQoJIyB8ICB8LSAqLm1ha2UgICAgICAgKCopIC0gTWFrZWZpbGUgcnVs
ZXMKCSMgfCAgfC0gKi5odG1sLm1kICAgICgqKSAtIE1hcmtkb3duIGZvciBodG1sIGZvcm1h
dAoJIyB8ICB8LSAqLnBkZi5tZCAgICAgKCopIC0gTWFya2Rvd24gZm9yIHBkZiBmb3JtYXQK
CSMgfC0gaHRtbC8qLmh0bWwgICAgICgqKSAtIHJlbmRlcmVkIGh0bWwgZGlyCgkjIHwtIHBk
Zi8qLnBkZiAgICAgICAoKikgLSByZW5kZXJlZCBwZGYgZGlyCgkjCgkjICgqKSBkaXJlY3Rv
cmllcy9maWxlcyBhcmUgYXV0by1nZW5lcmF0ZWQgdXNpbmcKCSMgICAgYC4vbWFya3kucHkg
LS1pbml0OyBtYWtlIHNjYW47IG1ha2UgYWxswrQKCSMKCi5QSE9OWTogaHR0cGQKaHR0cGQ6
CgljZCBodG1sICYmIHB5dGhvbiAtbSBodHRwLnNlcnZlcgoKLlBIT05ZOiBzY2FuCnNjYW46
CgkuL21hcmt5LnB5IC0tc2NhbgoKLlBIT05ZOiByZXNjYW4KcmVzY2FuOgoJLi9tYXJreS5w
eSAtLXNjYW4gLS1mb3JjZQoKYWxsX3F1aWV0IDo9ICQoZmlsdGVyIHF1aWV0LCQoTUFLRUNN
REdPQUxTKSkKLlBIT05ZOiBxdWlldApxdWlldDoKCSMgZW5hYmxlIC4vbWFya3kgLS1xdWll
dCBbLi4uXQoKYWxsX2F1eGNtZCA6PSAkKGZpbHRlciBhdXhjbWQsJChNQUtFQ01ER09BTFMp
KQouUEhPTlk6IGF1eGNtZAphdXhjbWQ6CgkjIGVuYWJsZSAuL21hcmt5IC0tYXV4Y21kIFsu
Li5dCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCm1hcmt5X2FsaWFzOj0KLWluY2x1ZGUgYnVpbGQv
Ki5tYWtlIGJ1aWxkLyoqLyoubWFrZQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgouUEhPTlk6IGxp
bmsKYnVpbGQ6ICQoZm9yZWFjaCBpLCQobWFya3lfYWxpYXMpLGJ1aWxkLyQoaSkpCgouUEhP
Tlk6IGh0bWwKaHRtbDogJChmb3JlYWNoIGksJChtYXJreV9hbGlhcyksaHRtbC8kKGkpKQoK
LlBIT05ZOiBwZGYKcGRmOiAkKGZvcmVhY2ggaSwkKG1hcmt5X2FsaWFzKSxwZGYvJChpKSkK
Ci5QSE9OWTogdGV4CnRleDogJChmb3JlYWNoIGksJChtYXJreV9hbGlhcyksdGV4LyQoaSkp
CgouUEhPTlk6IGF1eAphdXg6ICQoZm9yZWFjaCBpLCQobWFya3lfYWxpYXMpLGF1eC8kKGkp
KQoKLlBIT05ZOiBjbGVhbgpjbGVhbjoKCXJtIC1yZiAuL2J1aWxkLyogLi9odG1sLyogLi9w
ZGYvKgoKLlBIT05ZOiBhbGwKYWxsOiBodG1sIHBkZgoKLlBIT05ZOiBsaXN0Cmxpc3Q6Cgkj
CgkjIG1hcmt5IFRBUkdFVFMKCSMjIyMjIyMjIyMjIyMjIwoJIyBtYWtlIHNjYW4vPEFMSUFT
PiAgLSBjcmVhdGUgTWFrZWZpbGUgYGJ1aWxkLzxBTElBUz4ubWFrZWAKCSMgbWFrZSBidWls
ZC88QUxJQVM+IC0gYnVpbGQgYGJ1aWxkLzxBTElBUz4ue2h0bWwscGRmfS5tZCxweWAKCSMg
bWFrZSB0ZXgvPEFMSUFTPiAgIC0gYnVpbGQgYGJ1aWxkLzxBTElBUz4udGV4YAoJIyBtYWtl
IGh0bWwvPEFMSUFTPiAgLSBidWlsZCBgaHRtbC88QUxJQVM+Lmh0bWxgCgkjIG1ha2UgcGRm
LzxBTElBUz4gICAtIGJ1aWxkIGBwZGYvPEFMSUFTPi5wZGZgCgkjIG1ha2UgYXV4LzxBTElB
Uz4gICAtIHJ1biBhdXggY29tbWFuZHMgZm9yIDxBTElBUz4KCSMgbWFrZSBjbGVhbi88QUxJ
QVM+IC0gY2xlYW4gZmlsZXMsIGtlZXA6YG1ha2UsaHRtbCxwZGYsdGV4YAoJIwoJIyA8QUxJ
QVM+CgkjIyMjIyMjIyMKCSMkKG1hcmt5X2FsaWFzKQo=
'''
pack_pandoc_run = '''
IyEvYmluL2Jhc2gKClsgJCMgPT0gMCBdICYmIGVjaG8gIiIiCiMgVXNhZ2U6ICQwOiA8Rk9S
TUFUPiA8SU5GSUxFPiA8T1VURklMRT4KIyBFeGFtcGxlOgojICQwIGh0bWwgYnVpbGQvZmls
ZS5odG1sLm1kIGh0bWwvZmlsZS5odG1sCiMgJDAgcGRmIGJ1aWxkL2ZpbGUucGRmLm1kIHBk
Zi9maWxlLnBkZgoiIiIgJiYgZXhpdCAxCgpQQU5ET0M9cGFuZG9jCgpNREVYVD1cCmFsbF9z
eW1ib2xzX2VzY2FwYWJsZStcCmludHJhd29yZF91bmRlcnNjb3JlcytcCmVzY2FwZWRfbGlu
ZV9icmVha3MrXApzcGFjZV9pbl9hdHhfaGVhZGVyK1wKbGlzdHNfd2l0aG91dF9wcmVjZWRp
bmdfYmxhbmtsaW5lK1wKaW5saW5lX2NvZGVfYXR0cmlidXRlcytcCnN0cmlrZW91dCtcCnlh
bWxfbWV0YWRhdGFfYmxvY2srXApwaXBlX3RhYmxlcytcCmxpbmVfYmxvY2tzK1wKaW1wbGlj
aXRfZmlndXJlcytcCmFiYnJldmlhdGlvbnMrXAppbmxpbmVfbm90ZXMrXApicmFja2V0ZWRf
c3BhbnMrXApuYXRpdmVfZGl2cytcCm5hdGl2ZV9zcGFucytcCmZvb3Rub3RlcwoKClBET1BU
PSIiIgotLXRhYmxlLW9mLWNvbnRlbnRzCi0tbnVtYmVyLXNlY3Rpb25zCiIiIgoKaWYgWyAk
MSA9PSBodG1sIF0gOyB0aGVuCiRQQU5ET0MgIiQyIiBcCi0tZmlsdGVyIHBhbmRvYy14bm9z
IFwKLS1jaXRlcHJvYyBcCi0tZnJvbT1tYXJrZG93biskTURFWFQgXAotLXRvPWh0bWw1IFwK
LS1zZWxmLWNvbnRhaW5lZCBcCi0tb3V0cHV0PSIkMyIgXAotLXJlc291cmNlLXBhdGg9Ii4v
YnVpbGQvIiBcCiRQRE9QVApmaQoKaWYgWyAkMSA9PSBwZGYgXSA7IHRoZW4KJFBBTkRPQyAi
JDIiIFwKLS1maWx0ZXIgcGFuZG9jLXhub3MgXAotLWNpdGVwcm9jIFwKLS1mcm9tPW1hcmtk
b3duK3Jhd19odG1sKyRNREVYVCBcCi0tdG89bGF0ZXggXAotLW91dHB1dD0iJDMiIFwKLS1y
ZXNvdXJjZS1wYXRoPSIuL2J1aWxkLyIgXAotLXBkZi1lbmdpbmU9eGVsYXRleCBcCiRQRE9Q
VApmaQoKaWYgWyAkMSA9PSB0ZXggXSA7IHRoZW4KJFBBTkRPQyAiJDIiIFwKLS1maWx0ZXIg
cGFuZG9jLXhub3MgXAotLWNpdGVwcm9jIFwKLS1mcm9tPW1hcmtkb3duK3Jhd190ZXgrJE1E
RVhUIFwKLS10bz1sYXRleCBcCi0tb3V0cHV0PSIkMyIgXAotLXJlc291cmNlLXBhdGg9Ii4v
YnVpbGQvIiBcCiRQRE9QVApmaQo=
'''
pack_marky_md = '''
LS0tCnRpdGxlOiAiYG1hcmt5YCBEb2N1bWVudGF0aW9uICIKdGl0bGUtLXBkZjogIi0tIGBw
ZGZgIgp0aXRsZS0taHRtbDogIi0tIGBodG1sYCIKZGF0ZTogdW5rbm93bgphdXRob3I6IGxl
aG1hbm43CmJpYmxpb2dyYXBoeTogZGF0YS9tYXJreS5iaWIKaGVhZGVyLWluY2x1ZGVzLS1w
ZGY6ID4KICAgXGh5cGVyc2V0dXB7Y29sb3JsaW5rcz1mYWxzZSwKICAgYWxsYm9yZGVyY29s
b3JzPXswIDAgMH0sCiAgIHBkZmJvcmRlcnN0eWxlPXsvUy9VL1cgMX19CmhlYWRlci1pbmNs
dWRlcy0taHRtbDogPgogICA8c3R5bGU+KiB7IGJveC1zaXppbmc6IGJvcmRlci1ib3g7IH0g
Ym9keSB7IG1heC13aWR0aDogOTB2dyAhaW1wb3J0YW50OyB9PC9zdHlsZT4KeG5vcy1jbGV2
ZXJlZjogdHJ1ZQp4bm9zLWNhcGl0YWxpc2U6IHRydWUKZm9udHNpemU6IDExcHQKCi0tLQo8
Pwpjb2wgPSBmbXRjb2RlKAoJaHRtbD0iPHNwYW4gc3R5bGU9J2NvbG9yOnsxfTsnPnswfTwv
c3Bhbj4iLAoJcGRmPXIiXHRleHRjb2xvcnt7ezF9fX17e3swfX19IgopCmRlZiB0ZXh0X3By
b2MoY21kLCBjcm9wPVRydWUpOgoJaW1wb3J0IHN1YnByb2Nlc3MgYXMgc3AKCXRleHQgPSAi
IgoJZm9yIGkgaW4gc3AuY2hlY2tfb3V0cHV0KGNtZC5zcGxpdCgpKS5kZWNvZGUoInV0Zi04
Iikuc3BsaXQoIlxuIik6CgkJaWYgbm90IGNyb3A6CgkJCXRleHQgKz0gaSArICJcbiIKCQll
bGlmIGkuc3RhcnRzd2l0aCgiIyAiKToKCQkJdGV4dCArPSBpWzI6XSArICJcbiIKCQllbGlm
IGkgPT0gIiMiOgoJCQl0ZXh0ICs9ICJcbiIKCQllbGlmIGkuc3RhcnRzd2l0aCgiIyIpOgoJ
CQl0ZXh0ICs9IGkgKyAiXG4iCglyZXR1cm4gdGV4dAp2ZXJzaW9uID0gdGV4dF9wcm9jKCJw
eXRob24gbWFya3kucHkgLS12ZXJzaW9uIiwgY3JvcD1GYWxzZSkuc3RyaXAoKQo/PgotLS0K
Cj4gKipBYnN0cmFjdCoqIC0tIGBtYXJreWAgaXMgYSBwcmVwcm9jZXNzb3Igd2l0aCBhbiBl
YXN5IGFuZCBpbnR1aXRpdmUKPiBzeW50YXggZm9yIGV4ZWN1dGlvbiBvZiBlbWJlZGRlZCB7
e2NvbCgicHlob24iLCJibHVlIil9fSBjb2RlIGR1cmluZyByZW5kZXJpbmcKPiBgaHRtbGAg
YW5kIGBwZGZgIGRvY3VtZW50cyBmcm9tIE1hcmtkb3duIHRleHQuCj4gVGhpcyBkb2N1bWVu
dCBpcyBjcmVhdGVkIHVzaW5nIGBtYXJreWAsIHZlcnNpb24gKnt7dmVyc2lvbn19Ki4KPiBG
b3IgbW9yZSBpbmZvcm1hdGlvbiBwbGVhc2UgcmVmZXIgdG8gdGhlCj4gW2BtYXJreWAgcmVw
b3NpdG9yeV0oaHR0cHM6Ly9naXRodWIuY29tL2xlaG1hbm43L21hcmt5KS4KCi0tLQoKIyBg
bWFya3lgIER5bmFtaWMgTWFya2Rvd24KCmBtYXJreWAgaXMgYSBNYXJrZG93biBwcmVwcm9j
ZXNzb3Igd2hpY2ggdHJhbnNmb3JtcyBhIE1hcmtkb3duIGRvY3VtZW50CnVzaW5nIHB5dGhv
bi4gYG1hcmt5YCBpbXBsZW1lbnRzIHRocmVlIHN0YXRlbWVudHMgd2l0aCBleHRyZW1lbHkg
ZWFzeQphbmQgaW50dWl0aXZlIHN5bnRheCwgd2hpY2ggYXJlIGVtYmVkZGVkIGRpcmVjdGx5
IGluIHRoZSBNYXJrZG93biB0ZXh0OgoKMS4gYDxcPy4uLj9cPmA6IFB5dGhvbiBjb2RlIGJs
b2NrLgoyLiBge1x7Li4ufVx9YDogYGZgLXN0cmluZyBvdXRwdXQgaW50byBNYXJrZG93bi4K
My4gYF9fXygpYDogRnVuY3Rpb24gZm9yIG91dHB1dCBpbnRvIE1hcmtkb3duLgoKVXNpbmcg
YDxcPy4uLj9cPmAgYW5kIGB7XHsuLi59XH1gIHB5dGhvbiBjb2RlIGFuZCBgZmAtc3RyaW5n
IG91dHB1dAphcmUgZW1iZWRkZWQgZGlyZWN0bHkgaW5zaWRlIHRoZSBNYXJrZG93biB0ZXh0
LgoKIyMjIyBFeGFtcGxlIDE6IElubGluZSBGb3JtYXR0ZWQgT3VwdXQgey19Cjw/IQp4ID0g
MTIzLjQ1CkxFRyA9IGxhbWJkYSB2LCB3OiAibGVzc2VyIiBpZiB2IDwgdyBlbHNlICJlcXVh
bCBvciBncmVhdGVyIgo/PgpgYGBwaHAKPFw/e3tfX18oY29kZT1UcnVlKX19P1w+CmBgYApg
YGBtYXJrZG93bgpUaGlzIGlzIGFuIGV4YW1wbGUgd2l0aCBhIHZhbHVlIHg9e1x7eDouM2Z9
XH0sCndoaWNoIGlzIHtce0xFRyh4LCAxMDApfVx9IHRoYW4gMTAwLgpgYGAKIyMjIyBSdW4g
YW5kIE91dHB1dCB7LX0KYGBgbWFya2Rvd24KVGhpcyBpcyBhbiBleGFtcGxlIHdpdGggYSB2
YWx1ZSB4PXt7eDouM2Z9fSwKd2hpY2ggaXMge3tMRUcoeCwgMTAwKX19IHRoYW4gMTAwLgpg
YGAKClVzaW5nIHRoZSBgX19fKClgIGZ1bmN0aW9uIHRleHQgaXMgZ2VuZXJhdGVkIGZyb20g
cHl0aG9uCmFsZ29yaXRobXMgYW5kIGR5bmFtaWNhbGx5IGluc2VydGVkIGludG8gdGhlIHJl
c3VsdGluZyBNYXJrZG93bi4KCiMjIyMgRXhhbXBsZSAyOiBEeW5hbWljIFRleHQgZnJvbSBD
b2RlIHstfQpgYGBwaHAKPFw/e3tfX18oY29kZT1UcnVlKX19P1w+CmBgYAojIyMjIFJ1biBh
bmQgT3V0cHV0IHstfQpgYGBtYXJrZG93bgo8PyEKZm9yIGkgaW4gcmFuZ2UoMyk6CglfX18o
ZiJ7aSsxfS4gYGkgPSB7aX1gIiwgImFiY2RlZmdoaWoiWzA6KGkrMSkqM10pCj8+CmBgYAoK
UHl0aG9uIGNvZGUsIHdoaWNoIGlzIGVtYmVkZGVkIGluIHRoZSBNYXJrZG93biB0ZXh0CmZv
bGxvd3MgdGhlIFB5dGhvbiBpbmRlbnRhdGlvbiBzdGFuZGFyZC4gTWFya2Rvd24KdGV4dCBp
cyBpbnRlZ3JhdGVkIGludG8gdGhlIHByb2dyYW0gZmxvdyB3aGVuIGJlaW5nCmluc2VydGVk
IGluIHB5dGhvbiBzdGF0ZW1lbnRzIGFjY29yZGluZ2x5LgoKIyMjIyBFeGFtcGxlIDM6IFRl
eHQgaW4gQ29uZGl0aW9uIHstfQpgYGBwaHAKVGhpcyBpcyB0aGUgZmlyc3QgbGluZS4KPFw/
CmlmIEZhbHNlOgoJP1w+VGhpcyBMaW5lIGlzICoqbm90Kiogc2hvd24uPFw/CmVsc2U6Cgk/
XD5UaGlzIExpbmUgaXMgc2hvd24uPFw/Cj9cPgpUaGlzIGlzIHRoZSBsYXN0IGxpbmUuCmBg
YAojIyMjIFJ1biBhbmQgT3V0cHV0IHstfQpgYGBtYXJrZG93bgpUaGlzIGlzIHRoZSBmaXJz
dCBsaW5lLgo8PwppZiBGYWxzZToKCT8+VGhpcyBMaW5lIGlzICoqbm90Kiogc2hvd24uPD8K
ZWxzZToKCT8+VGhpcyBMaW5lIGlzIHNob3duLjw/Cj8+ClRoaXMgaXMgdGhlIGxhc3QgbGlu
ZS4KYGBgCgojIyMjIEV4YW1wbGUgNDogVGV4dCBpbiBQcm9ncmFtIEZsb3cgey19CmBgYHBo
cAo8XD8KZm9yIGkgaW4gcmFuZ2UoMyk6Cgk/XD57XHtpKzF9XH0uIGBpID0ge1x7aX1cfWAg
aW4gdGhpcyBpdGVyYXRpb24uCjxcPwo/XD4KYGBgCiMjIyMgUnVuIGFuZCBPdXRwdXQgey19
CmBgYG1hcmtkb3duCjw/CmZvciBpIGluIHJhbmdlKDMpOgoJPz57e2krMX19LiBgaSA9IHt7
aX19YCBpbiB0aGlzIGl0ZXJhdGlvbi4KPD8KPz4KYGBgCgojIyBBIEZpcnN0IGBtYXJreWAg
RXhhbXBsZQoKYG1hcmt5YCBjb21iaW5lcyBweXRob24gZXhwcmVzc2lvbnMgd2l0aCBNYXJr
ZG93biwgZm9yIGR5bmFtaWMgY3JlYXRpb24Kb2YgdGV4dC4gSW4gdGhlIGZvbGxvd2luZywg
dHdvIGluLWRlcHRoIGV4YW1wbGVzIG9mIGBtYXJreWAgYXJlIHByZXNlbnRlZC4KCiMjIyMg
RXhhbXBsZSAxOiBgbWFya3lgIFN5bnRheCB7LX0KPD8hCnggPSAxMjMKeSA9IDQ1CmRlZiBh
YmNfZnVuKHYsIGEsIGIsIGMpOgoJcmV0dXJuIGEgaWYgdiA8IDEwMCBlbHNlIGIgaWYgdiA9
PSAxMDAgZWxzZSBjCkxFRyA9IGxhbWJkYSB2OiBhYmNfZnVuKHYsICJsZXNzZXIiLCAiZXF1
YWwiLCAiZ3JlYXRlciIpCj8+CmBgYHBocAo8XD97e19fXyhjb2RlPVRydWUpfX0/XD4KYGBg
CmBgYG1hcmtkb3duClRoaXMgaXMgYW4gZXhhbXBsZSB3aXRoIGEgdmFsdWUgeD17XHt4fVx9
LCB3aGljaCBpcwp7XHtMRUcoeCl9XH0gdGhhbiAxMDAuIFRoZXJlIGlzIGFub3RoZXIgdmFs
dWUgeT17XHt5fVx9LAp3aGljaCBpcyB7XHtMRUcoeSl9XH0gdGhhbiAxMDAuIEJvdGggdmFs
dWVzIHRvZ2V0aGVyCmFyZSB4K3k9e1x7eCt5fVx9LgpgYGAKIyMjIyBSdW4gYW5kIE91dHB1
dCB7LX0KYGBgbWFya2Rvd24KVGhpcyBpcyBhbiBleGFtcGxlIHdpdGggYSB2YWx1ZSB4PXt7
eH19LCB3aGljaCBpcwp7e0xFRyh4KX19IHRoYW4gMTAwLiBUaGVyZSBpcyBhbm90aGVyIHZh
bHVlIHk9e3t5fX0sCndoaWNoIGlzIHt7TEVHKHkpfX0gdGhhbiAxMDAuIEJvdGggdmFsdWVz
IHRvZ2V0aGVyCmFyZSB4K3k9e3t4K3l9fS4KYGBgCgpUaGUgZm9sbG93aW5nIGV4YW1wbGUg
Y29udGFpbnMgbWV0YSBkYXRhIGluIHRoZSBmcm9udCBtYXR0ZXIKYW5kICBjYW4gYmUgcmVu
ZGVyZWQgaW50byBgcGRmYCBhbmQgYGh0bWxgIGJ5IGp1c3QgY2FsbGluZwpgbWFrZSBwZGYv
ZmlsZWAgb3IgYG1ha2UgaHRtbC9maWxlYC4KCiMjIyMgRXhhbXBsZSAyOiBgbWQvZmlsZS5t
ZGAgey19CmBgYHBocAotLS0KdGl0bGU6IEFuIEV4YW1wbGUKLS0tCjxcPwpkZWYgY2FwX2Zp
cnN0KGkpOgoJcmV0dXJuICIgIi5qb2luKFtpWzBdLnVwcGVyKCkgKyBpWzE6XSBmb3IgaSBp
biBpLnNwbGl0KCldKQpmb3IgaSBpbiBbInZlcnkiLCAibm90IHNvIl06Cgk/XD4KKip7XHtj
YXBfZmlyc3QoaSl9XH0gU2VjdGlvbioqCgpUbyBkYXkgaXMgYSB7XHtpfVx9IHZlcnkgbmlj
ZSBkYXkuClRoZSBzdW4gaXMgc2hpbmluZyB7XHtpfVx9IGJyaWdodCBhbmQKdGhlIGJpcmRz
IGFyZSBzaW5naW5nIHtce2l9XH0gbG91ZCBhbmQKZmx5IHtce2l9XH0gaGlnaCBpbiB0aGUg
e1x7aX1cfSBibHVlIHNreS4KCTxcPwo/XD4KYGBgCiMjIyMgT3V0cHV0IGBidWlsZC9maWxl
Lm1kYCB7LX0KYGBgbWFya2Rvd24KLS0tCnRpdGxlOiBBbiBFeGFtcGxlCi0tLQo8PwpkZWYg
Y2FwX2ZpcnN0KGkpOgoJcmV0dXJuICIgIi5qb2luKFtpWzBdLnVwcGVyKCkgKyBpWzE6XSBm
b3IgaSBpbiBpLnNwbGl0KCldKQpmb3IgaSBpbiBbInZlcnkiLCAibm90IHNvIl06Cgk/Pgoq
Knt7Y2FwX2ZpcnN0KGkpfX0gU2VjdGlvbioqCgpUbyBkYXkgaXMgYSB7e2l9fSB2ZXJ5IG5p
Y2UgZGF5LgpUaGUgc3VuIGlzIHNoaW5pbmcge3tpfX0gYnJpZ2h0IGFuZAp0aGUgYmlyZHMg
YXJlIHNpbmdpbmcge3tpfX0gbG91ZCBhbmQKZmx5IHt7aX19IGhpZ2ggaW4gdGhlIHt7aX19
IGJsdWUgc2t5LgoJPD8KPz4KYGBgCgojIyBIb3cgZG9lcyBgbWFya3lgIHdvcmsgaW50ZXJu
YWxseT8KCmBtYXJreWAgdXNlcyBhbiBleHRyZW1lbHkgc2ltcGxlIG1lY2hhbmlzbSBmb3Ig
Z2VuZXJhdGluZyBhIHB5dGhvbiBwcm9ncmFtbQpmcm9tIHRoZSBNYXJrZG93biB0ZXh0LiBV
c2luZyB0aGUgYDxcPy4uLj9cPmAgYW5kIGB7XHsuLi59XH1gIHN0YXRlbWVudCwKUHl0aG9u
IGNvZGUgaXMgZW1iZWRkZWQgaW50byB0aGUgTWFya2Rvd24gdGV4dCBhbmQgdHJhbnNsYXRl
ZCBpbnRvIGEgc2VyaWVzCm9mIGNhbGxzIHRvIHRoZSBgX19fKClgIGZ1bmN0aW9uIHVzaW5n
IGBmYC1zdHJpbmdzIGFzIGFyZ3VtZW50cywgd2hlcmUKcHl0aG9uIHZhcmlhYmxlcyBhcmUg
cmVmZXJlbmNlZC4gVGhpcyByZXN1bHRzIGludG8gYSBweXRob24gcHJvZ3JhbQp3aGljaCBj
YW4gZ2VuZXJhdGUgTWFya2Rvd24gdGV4dCBhbGdvcml0aG1pY2FsbHkuCgojIyMjIEV4YW1w
bGU6IGBtZC9maWxlLm1kYCB7LX0KYGBgcGhwCiogVGhpcyBpcyB7Zmlyc3R9LiA8XD8KeCA9
IDEgIyB0aGlzIGlzIGNvZGUKZm9yIGkgaW4gcmFuZ2UoMyk6CglpZiB4OgoJCT9cPgp7XHtp
KzF9XH0uIFRoZSB2YWx1ZSBpcyB7XHtce3h9XH1cfS4KPFw/CgllbHNlOgoJCT9cPntce2kr
MX1cfS4gVGhlIHZhbHVlIGlzIHplcm8uCjxcPwoJeCA9IDAKP1w+KiBUaGlzIGlzIGxhc3Qu
CmBgYApUaGUgZmlsZSBwcm9kdWNlcyB0aGUgZm9sbG93aW5nIE1hcmtkb3duIG91dHB1dC4K
CiMjIyMgT3V0cHV0OiBNYXJrZG93biB7LX0KYGBgYmFzaAoqIFRoaXMgaXMge2ZpcnN0fS4g
PD8KeCA9IDEgIyB0aGlzIGlzIGNvZGUKZm9yIGkgaW4gcmFuZ2UoMyk6CglpZiB4OgoJCT8+
Cnt7aSsxfX0uIFRoZSB2YWx1ZSBpcyB7e3t4fX19Lgo8PwoJZWxzZToKCQk/Pnt7aSsxfX0u
IFRoZSB2YWx1ZSBpcyB6ZXJvLgo8PwoJeCA9IDAKPz4qIFRoaXMgaXMgbGFzdC4KYGBgCgpg
bWFya3lgIHRyYW5zZm9ybXMgdGhlIE1hcmtkb3duIGludG8gUHl0aG9uIHNvdXJjZSBjb2Rl
LgpFeGVjdXRpb24gb2YgdGhlIFB5dGhvbiBzb3VyY2UgY29kZSB5aWVsZHMgdGhlIG5ldyBN
YXJrZG93biB0ZXh0LgoKIyMjIyBPdXRwdXQ6IGBidWlsZC9maWxlLnB5YCB7LX0KYGBgcHl0
aG9uCl9fXyhyZiIiIiogVGhpcyBpcyB7XHtmaXJzdH1cfS4gIiIiLCBfX18pOwp4ID0gMSAj
IHRoaXMgaXMgY29kZQpmb3IgaSBpbiByYW5nZSgzKToKCWlmIHg6CgkJX19fKHJmIiIiCntp
KzF9LiBUaGUgdmFsdWUgaXMge1x7XHt4fVx9XH0uCiIiIiwgX19fKTsKCWVsc2U6CgkJX19f
KHJmIiIie2krMX0uIFRoZSB2YWx1ZSBpcyB6ZXJvLgoiIiIsIF9fXyk7Cgl4ID0gMApfX18o
cmYiIiIqIFRoaXMgaXMgbGFzdC4KIiIiLCBfX18pOwpgYGAKCiMgUXVpY2sgU3RhcnQKCiMj
IGBtYXJreWAgRGVwZW5kZW5jaWVzCgpgbWFya3lgIGRlcGVuZHMgb24gYHBhbmRvY2AgYW5k
IGBweXlhbWxgLiBgcGFuZG9jYCBpcyB1c2VkIGZvciByZW5kZXJpbmcKdGhlIE1hcmtkb3du
IGludG8gYGh0bWxgIGFuZCBgcGRmYC4gYG1hcmt5YCB1c2VzCltwYW5kb2NdKGh0dHBzOi8v
d3d3LnBhbmRvYy5vcmcvKSBmb3IgcmVuZGVyaW5nIGBodG1sYCBhbmQgYHBkZmAuCmBwYW5k
b2M+PTIuMTBgIHJlbGVhc2VzIGNhbiBiZSBmb3VuZApbaGVyZV0oaHR0cHM6Ly9naXRodWIu
Y29tL2pnbS9wYW5kb2MvcmVsZWFzZXMpLgpUaGUgb3RoZXIgcGFja2FnZXMgY2FuIGJlIGlu
c3RhbGxlZCB3aXRoIGBwaXBgLgoKYGBgYmFzaApwaXAgaW5zdGFsbCBwYW5kb2MtZmlnbm9z
CnBpcCBpbnN0YWxsIHBhbmRvYy1lcW5vcwpwaXAgaW5zdGFsbCBwYW5kb2Mtc2Vjbm9zCnBp
cCBpbnN0YWxsIHBhbmRvYy10YWJsZW5vcwpwaXAgaW5zdGFsbCBwYW5kb2MteG5vcwpwaXAg
aW5zdGFsbCBweXlhbWwKYGBgCgojIyBgbWFya3lgIFdvcmtmbG93CgpXb3JrZmxvdyBmb3Ig
Y3JlYXRpbmcgYGh0bWxgIG9yIGBwZGZgIHVzaW5nIGBtYXJreWAgYnkKaW52b2NhdGlvbiBv
ZiBgbWFrZSBzY2FuYCBhbmQgYG1ha2UgYWxsYC4KCiptYWtlKnwxLiAqd3JpdGUqICB8ICB8
Mi4gKmJ1aWxkKiAgICAgICAgICB8ICB8My4gKnJlbmRlcioKLS0tLS0tfC0tLS0tLS0tLS0t
LXwtLXwtLS0tLS0tLS0tLS0tLS0tLS0tLXwtLXwtLS0tLS0tLS0tLS0tLS0tCmBwZGZgIHwg
ICAgICAgICAgICB8ICB8YGJ1aWxkL2ZpbGUuaHRtbC5tZGB8LT58YGh0bWwvZmlsZS5odG1s
YApgLWAgICB8YG1kL2ZpbGUubWRgfC0+fCAgICAgICAgICAgICAgICAgICAgfCAgfApgaGZt
bGB8ICAgICAgICAgICAgfCAgfGBidWlsZC9maWxlLnBkZi5tZGAgfC0+fGBwZGYvZmlsZS5w
ZGZgCgoxLiAqKndyaXRlKio6IHVzZXIgd3JpdGVzIGEgTWFya2Rvd24gdGV4dCBmaWxlIGFu
ZCBwbGFjZXMgaXQgaW4gYG1kLyoubWRgCmRpcmVjdG9yeSB3aXRoIHRoZSBleHRlbnNpb24g
YC5tZGAuCjIuICoqYnVpbGQqKjogYG1hcmt5YCB0cmFuc2Zvcm1zIHRoZSBmaWxlcyBpbiBg
bWQvKi5tZGAgaW50byByZWd1bGFyIE1hcmtkb3duIHRleHQKYW5kIHBsYWNlcyB0aGUgdHJh
bnNmb3JtZWQgZmlsZXMgaW4gYGJ1aWxkL2AuCjMuICoqcmVuZGVyKio6IHRoZSByZWd1bGFy
IE1hcmtkb3duIHRleHQgaW4gdGhlIGZpbGVzIGBidWlsZC8qLm1kYCBpcyByZW5kZXJlZCBp
bnRvCmBodG1sYCBhbmQgYHBkZmAgdXNpbmcgYHBhbmRvY2AuCgpUaGUgdGhyZWUgc3RlcHMg
YXJlIGltcGxlbWVudGVkIGluIGEgTWFrZWZpbGUuCgojIyBEb3dubG9hZCBhbmQgSW5pdGlh
bGl6ZQoKYG1hcmt5YCBpcyBzdXBwbGllZCBhcyBhIHNpbmdsZS1maWxlIHNjcmlwdCB3aGlj
aCBhdXRvbWF0aWNhbGx5CnNldHMgdXAgdGhlIHByb2plY3Qgc3RydWN0dXJlIGNvbnRhaW5p
bmcgYWxsIHNjcmlwdHMKcmVxdWlyZWQgZm9yIHByb2Nlc3NpbmcgYW5kIHJlbmRlcmluZyBN
YXJrZG93bi4KCkZvciBleGFtcGxlLCBkb3dubG9hZCBgbWFya3lgIGZyb20gZ2l0aHViLgpg
YGBiYXNoCmdpdCBjbG9uZSBodHRwczovL2xlaG1hbm43LmdpdGh1Yi5jb20vbWFya3kuZ2l0
CmNkIG1hcmt5CmBgYAoKQWZ0ZXIgZG93bmxvYWQsIHRoZSBgbWFya3lgIGVudmlyb25tZW50
IGlzIGluaXRpYWxpemVkIHVzaW5nIGBtYXJreWAuCmBgYGJhc2gKLi9tYXJreS5weSAtLWlu
aXQKIyBta2RpciBidWlsZC8KIyBta2RpciBkYXRhCiMgbWtkaXIgbWQvCiMgV1JJVEUgTWFr
ZWZpbGUKIyBXUklURSBwYW5kb2MtcnVuCiMgV1JJVEUgbWQvbWFya3kubWQKIyBXUklURSAu
Z2l0aWdub3JlCiMgVVNBR0UKbWFrZSBoZWxwCmBgYAoKIyMgYG1hcmt5YCBFbnZpcm9ubWVu
dAoKRHVyaW5nIGluaXRpYWxpemF0aW9uLCBgbWFya3lgIGNyZWF0ZXMgZGlyZWN0b3JpZXMg
YW5kIGZpbGVzLgpBZnRlciBpbml0aWFsaXphdGlvbiwgdGhlIGZvbGxvd2luZyBzdHJ1Y3R1
cmUgaXMgYXV0by1nZW5lcmF0ZWQKaW4gdGhlIHByb2plY3QgZGlyZWN0b3J5LiBgbWFya3lg
IHNob3dzIHRoZSBwcm9qZWN0IHN0cnVjdHVyZQp3aGVuIGludm9raW5nIGBtYWtlIHRyZWVg
LgpgYGBiYXNoCjw/Cl9fXyh0ZXh0X3Byb2MoIm1ha2UgdHJlZSIpKQo/PgpgYGAKClRoZSBz
Y3JpcHQgYHBhbmRvYy1ydW5gIGNhbiBiZSBhZGp1c3RlZCBpbiBjYXNlIHNwZWNpZmljCmBw
YW5kb2NgIG9wdGlvbnMgYXJlIHJlcXVpcmVkIGZvciByZW5kZXJpbmcgdGhlIGBodG1sYCBh
bmQgYHBkZmAgZG9jdW1lbnRzLgoKIyMgRG9jdW1lbnQgUmVuZGVyaW5nCgpCeSBpbnZva2lu
ZyBgbWFrZSBhbGxgIGFsbCBmaWxlcyBgbWQvKi5tZGAgYXJlIHRyYW5zZm9ybWVkCmludG8g
Y29ycmVzcG9uZGluZyBgaHRtbC8qLmh0bWxgIGFuZCBgcGRmLyoucGRmYCBmaWxlcy4gQnkK
aW52b2tpbmcgYG1ha2UgaHR0cGRgIGEgcHl0aG9uIHdlYiBzZXJ2ZXIgaXMgc3RhcnRlZCBp
biBgaHRtbC9gLgoKQWxsIHVzZXItZ2VuZXJhdGVkIE1hcmtkb3duIGNvbnRlbnQgZ29lcyBp
bnRvIGBtZC8qYCB1c2VyLWdlbmVyYXRlZApkYXRhIGZpbGVzIGdvIGludG8gYGRhdGEvKmAu
CgoqKkFUVEVOVElPTjoqKiBUaGUgZmlsZXMgaW4gdGhlIGRpcmVjdG9yaWVzIGBidWlsZC8q
YCBhcmUKKiphdXRvLWdlbmVyYXRlZCoqLiBBbGwgdXNlciBmaWxlcyBoYXZlIHRvIGJlIHBs
YWNlZCBpbnNpZGUgdGhlCmRpcmVjdG9yeSBgbWQvKmAuIEludm9raW5nIGBtYWtlIGNsZWFu
YCB3aWxsICoqZGVsZXRlIGFsbCBmaWxlcyoqCmluIGBodG1sL2AsIGBidWlsZC9gIGFuZCBg
cGRmL2AuCgojIyBgbWFya3lgIE1ha2VmaWxlIFRhcmdldHMKCmBtYXJreWAgbWFuYWdlcyBh
bGwgZmlsZXMgdXNpbmcgTWFrZWZpbGUgdGFyZ2V0cy4gTWFrZWZpbGUgdGFyZ2V0cwphcmUg
aW5pdGlhbGl6ZWQgdXNpbmcgYG1ha2Ugc2NhbmAgYW5kIHNob3duIHVzaW5nIGBtYWtlIGxp
c3RgLgpgYGBiYXNoCjw/Cl9fXyh0ZXh0X3Byb2MoIm1ha2UgbGlzdCIpKQo/PgpgYGAKCiMj
IEludGVncmF0ZWQgRG9jdW1lbnRhdGlvbgoKYG1hcmt5YCBoYXMgYW4gaW50ZWdyYXRlZCBl
bnZpcm9ubWVudC4gVXNpbmcgYG1ha2UgaGVscGAgZGlzcGxheXMKYSBzaG9ydCBpbmZvIGFi
b3V0IHRoZSBgbWFya3lgIGRlcGVuZGVuY2llcywgbWFrZSB0YXJnZXRzIGFuZApleGFtcGxl
cy4KYGBgYmFzaAo8PwpfX18odGV4dF9wcm9jKCJtYWtlIGhlbHAiKSkKPz4KYGBgCgojIGBt
YXJreWAgRmVhdHVyZXMKCkluIG9yZGVyIHRvIHF1aWNrIHN0YXJ0IGEgbmV3IE1hcmtkb3du
IHByb2plY3QsIGp1c3QgbGluayB0aGUKYG1hcmt5LnB5YCBleGVjdXRhYmxlIGluIHRoZSBw
cm9qZWN0IGRpciBvciBjbG9uZSB0aGUgZ2l0IGFzCmRlc2NyaWJlZCBhYm92ZSwgYW5kIGlu
aXRpYWxpemUgdGhlIGVudmlyb25tZW50IHVzaW5nIGAtLWluaXRgLgpgYGBiYXNoCm1rZGly
IG15X3Byb2plY3QKY2QgbXlfcHJvamVjdApsbiAtcyB+L21hcmt5L21hcmt5LnB5IC4KIyAu
Li4gb3IgZ2l0IGNsb25lIC4uLgouL21hcmt5LnB5IC0taW5pdApgYGAKCk5vdyBgbWFya3lg
IGlzIHJlYWR5IGZvciBvcGVyYXRpb24uIFBsYWNlIGEgbmV3IGZpbGUgaW4gYG1kL2ZpbGUu
bWRgCmFuZCBydW4gdGhlIGZvbGxvd2luZyBjb21tYW5kcy4KYGBgYmFzaAp0b3VjaCBtZC9m
aWxlLm1kCm1ha2Ugc2NhbgojIFdSSVRFIGJ1aWxkL2ZpbGUubWFrZQpgYGAKCmBtYXJreWAg
ZGlzY292ZXJzIHRoZSBuZXcgZG9jdW1lbnQgd2hlbiBpbnZva2luZyBgbWFrZSBzY2FuYC4K
YG1hcmt5YCBhbHNvIHJlbmRlcnMgYGh0bWxgIGFuZCBgcGRmYCB1c2luZyBtYWtlIHRhcmdl
dHMuCmBgYGJhc2gKbWFrZSBodG1sL2ZpbGUKbWFrZSBwZGYvZmlsZQpgYGAKCiMjIE1ldGEg
RGF0YSBpbiBGcm9udCBNYXR0ZXIKCklmIGRvY3VtZW50IHN0YXJ0cyB3aXRoIGAtLS1gLCB5
YW1sIGlzIHVzZWQgdG8gcGFyc2UKdGhlIGZyb250IG1hdHRlciBibG9jayBkZWxpbWl0ZWQg
YnkgYC0tLWAuCkFsbCBtZXRhIGRhdGEga2V5cyB3aWxsIGJlIGV4cG9zZWQgaW50byB0aGUg
cHl0aG9uIHNjb3BlIGFzIGEgbG9jYWwKdmFyaWFibGUsIHVubGVzcyB0aGUgdmFyaWFibGUg
YWxyZWFkeSBleGlzdHMuCgojIyMjIEV4YW1wbGUgey19CmBgYHBocAotLS0KdGl0bGU6ICJQ
cmltZSBOdW1iZXJzIgphdXRob3I6IC4uLgpkYXRlOiAuLi4Kbm1heDogMjAKLS0tClRoZSB0
aXRsZSBvZiB0aGlzIGRvY3VtZW50IGlzIHtce3RpdGxlfVx9LgpMaXN0IG9mIHByaW1lIG51
bWJlcnMgc21hbGxlciB0aGFuIHtce25tYXh9XH06CjxcPwpmb3IgaSBpbiByYW5nZSgyLCBu
bWF4KToKCXByaW0gPSBUcnVlCglmb3IgaiBpbiByYW5nZSgyLCBpKToKCQlpZiBpICUgaiA9
PSAwOgoJCQlwcmltID0gRmFsc2UKCQkJYnJlYWsKCWlmIHByaW06CgkJP1w+KiBwcmltZSBu
dW1iZXI6IHtce2l9XH0KYGBgCiMjIyMgT3V0cHV0IHstfQpgYGBtYXJrZG93bgotLS0KdGl0
bGU6ICJQcmltZSBOdW1iZXJzIgphdXRob3I6IC4uLgpkYXRlOiAuLi4Kbm1heDogMjAKLS0t
ClRoZSB0aXRsZSBvZiB0aGlzIGRvY3VtZW50IGlzIFByaW1lIE51bWJlcnMuCkxpc3Qgb2Yg
cHJpbWUgbnVtYmVycyBzbWFsbGVyIHRoYW4gMjA6CiogcHJpbWUgbnVtYmVyOiAyCiogcHJp
bWUgbnVtYmVyOiAzCiogcHJpbWUgbnVtYmVyOiA1CiogcHJpbWUgbnVtYmVyOiA3CiogcHJp
bWUgbnVtYmVyOiAxMQoqIHByaW1lIG51bWJlcjogMTMKKiBwcmltZSBudW1iZXI6IDE3CmBg
YAoKIyMgSW5saW5lIEZvcm1hdHRlZCBPdXRwdXQKClB5dGhvbiBsb2NhbCB2YXJpYWJsZXMg
YW5kIHZhcmlhYmxlcyBmcm9tIG1ldGEgZGF0YSBpbiBmcm9udCBtYXR0ZXIKY2FuIGJlIGFj
Y2Vzc2VkIGRpcmV0bHkgZnJvbSB0aGUgbWFya2Rvd24gdGV4dC4KVGhlIGB7XHsuLi59XH1g
IHN0YXRlbWVudCB1c2VzIHN5bnRheCBzaW1pbGFyIHRvIHB5dGhvbiBgZmAtc3RyaW5ncyBm
b3IKZm9ybWF0dGVkIG91dHB1dCBvZiB2YXJpYWJsZXMgYW5kIHJlc3VsdHMgb2YgZXhwcmVz
c2lvbnMgaW50byBNYXJrZG93bgp0ZXh0LiBUaGUgYG1hcmt5YCBvcGVyYXRvciBge1x7PGV4
cHJlc3Npb24+Wzo8Zm9ybWF0Pl19XH1gIHVzZXMgdGhlCnN5bnRheCBvZiBbYGZgLXN0cmlu
Z3NdKGh0dHBzOi8vZG9jcy5weXRob24ub3JnLzMvcmVmZXJlbmNlL2xleGljYWxfYW5hbHlz
aXMuaHRtbCNmLXN0cmluZ3MpLgoKIyMjIyBFeGFtcGxlIDEgey19CmBgYGJhc2gKVGl0bGUg
b2YgdGhpcyBkb2N1bWVudCBpcyB7XHt0aXRsZX1cfSBhbmQgZm9udCBzaXplIGlzIHtce2Zv
bnRzaXplfVx9LgpgeGAgaXMge1x7eH1cfSBhbmQge1x7IiwiLmpvaW4oW3N0cihpKSBmb3Ig
aSBpbiByYW5nZSh4LTEwLHgpXSl9XH0uCmBgYAojIyMjIE91dHB1dCB7LX0KPiBUaXRsZSBv
ZiB0aGlzIGRvY3VtZW50IGlzIHt7dGl0bGV9fSBhbmQgZm9udCBzaXplIGlzIHt7Zm9udHNp
emV9fS4KPiBgeGAgaXMge3t4fX0gYW5kIHt7IiwiLmpvaW4oW3N0cihpKSBmb3IgaSBpbiBy
YW5nZSh4LTEwLHgpXSl9fS4KCiMjIyMgRXhhbXBsZSAyIHstfQo8PyEKeCA9IGludCgxKQp5
ID0gZmxvYXQoMi4zKQp6ID0gMAphID0gWzEsIDIsIDNdCmIgPSAoNCwgNSkKPz4KYGBgcHl0
aG9uCnt7X19fKGNvZGU9VHJ1ZSwgY3JvcD1UcnVlKX19CmBgYApgYGBtYXJrZG93bgpUaGlz
IGlzIGEgcGFyYWdyYXBoIGFuZCB4IGlzIHtce3g6MDNkfVx9IGFuZCB5IGlzIHtce3k6LjJm
fVx9LgpPdGhlciBjb250ZW50IGlzOiBhID0ge1x7YX1cfSwgYiA9IHtce2J9XH0uCmBgYAoj
IyMjIE91dHB1dCB7LX0KPiBUaGlzIGlzIGEgcGFyYWdyYXBoIGFuZCB4IGlzIHt7eDowM2R9
fSBhbmQgeSBpcyB7e3k6LjJmfX0uCj4gT3RoZXIgY29udGVudCBpczogYSA9IHt7YX19LCBi
ID0ge3tifX0uCgojIyBFbWJlZGRpbmcgUHl0aG9uIENvZGUKClB5dGhvbiBjb2RlIGJsb2Nr
cyBhcmUgZW1iZWRkZWQgaW50byBNYXJrZG93biB1c2luZyBgPFw/Li4uP1w+YCBhbmQgYHtc
ey4uLn1cfWAuCkFsbCBjb2RlIGJsb2NrcyBzcGFuIG9uZSBsYXJnZSBzY29wZSBzaGFyaW5n
IGZ1bmN0aW9ucyBhbmQgbG9jYWwKdmFyaWFibGVzLiBNZXRhIGRhdGEgaXMgaW1wb3J0ZWQg
ZnJvbSBNYXJrZG93biBmcm9udCBtYXR0ZXIgYXMgbG9jYWwKdmFyaWFibGVzIGluIHRoZSBw
eXRob24gc2NvcGUuIFRoZSBgaW1wb3J0YCBzdGF0ZW1lbnQgY2FuIGJlIHVzZWQgaW4KcHl0
aG9uIGNvZGUgaW4gb3JkZXIgdG8gYWNjZXNzIGluc3RhbGxlZCBweXRob24gcGFja2FnZXMg
YXMgdXN1YWwuCgojIyMgVmlzaWJsZSBDb2RlCgpVc2luZyBgPFw/IS4uLj9cPmAgY29kZSBp
cyBleGVjdXRlZCBhbmQgc3RvcmVkLgpUaGUgdGV4dCBvZiB0aGUgbGFzdCBgPFw/IS4uLj9c
PmAgYmxvY2sgY2FuIGJlCmFjY2Vzc2VkIGFuZCBwbGFjZWQgdmlhIGB7XHtfX18oY29kZT1U
cnVlKX1cfWAuCgojIyMjIEV4YW1wbGUgey19CmBgYHB5dGhvbgo8XD8hCnggPSA0MiAjIHZp
c2libGUgY29kZQpwcmludCgiSGVsbG8gY29uc29sZSEiKQo/XD4Ke1x7X19fKGNvZGU9VHJ1
ZSl9XH0KYGBgCgojIyMjIFJ1biBhbmQgT3V0cHV0IHstfQo8PyEKeCA9IDQyICMgdmlzaWJs
ZSBjb2RlCnByaW50KCJIZWxsbyBjb25zb2xlISIpCj8+CmBgYHB5dGhvbgp7e19fXyhjb2Rl
PVRydWUsIGNyb3A9VHJ1ZSl9fQpgYGAKCioqQVRURU5USU9OOioqIFVzaW5nIHRoZSBgcHJp
bnQoKWAgZnVuY3Rpb24gdGhlIHRleHQgd2lsbCBiZSBwcmludGVkCnRvIHRoZSBjb25zb2xl
IGFuZCAqKm5vdCoqIGluc2lkZSB0aGUgcmVzdWx0aW5nIE1hcmtkb3duIHRleHQuCgojIyMg
SGlkZGVuIENvZGUKClVzaW5nIGA8XD8uLi4/XD5gIGNvZGUgaXMgZXhlY3V0ZWQgYnV0IG5v
dCBzaG93biBpbiBNYXJrZG93bi4KCiMjIyMgRXhhbXBsZSB7LX0KYGBgcHl0aG9uCjxcP3t7
X19fKGNvZGU9VHJ1ZSl9fT9cPgpgYGAKIyMjIyBSdW4gYW5kIE91dHB1dCB7LX0KYGBgcHl0
aG9uCjw/IQp4ID0gNDEgIyBoaWRkZW4gY29kZQpfX18oZiJPdXRwdXQgdG8gTWFya2Rvd24u
IHggPSB7eH0hIikKPz4KYGBgCgoqKkFUVEVOVElPTjoqKiBVc2luZyB0aGUgYF9fXygpYCBm
dW5jdGlvbiB0aGUgdGV4dCB3aWxsIGJlIHByaW50ZWQKaW5zaWRlIHRoZSByZXN1bHRpbmcg
TWFya2Rvd24gdGV4dCAqKmFuZCBub3QqKiBvbiB0aGUgY29uc29sZS4KCiMjIyBFcnJvciBN
ZXNzYWdlcwoKYG1hcmt5YCBzaG93cyBlcnJvciBtZXNzYWdlcyBkaXJlY3RseSBpbnNpZGUg
dGhlIE1hcmtkb3duIHRleHQuCgojIyMjIEV4YW1wbGUgMTogYG1kL2ZpbGUubWRgIHstfQpg
YGBzY2FsYQogICAxICAtLS0KICAgMiAgdGl0bGU6ICJTeW50YXggRXJyb3IiCiAgIDMgIC0t
LQogICA0ICA8XD8KICAgNSAgeCA9IDEKICAgNiAgP1w+CiAgIDcgIFRoZSB2YWx1ZSB4IGlz
IHtce3l9XH0uCmBgYAojIyMjIFJ1biBhbmQgT3V0cHV0OiBgbWFrZSBidWlsZC9maWxlYCB7
LX0KYGBgYmFzaAo8IS0tIHJ1biBtZC9maWxlLm1kIC0tIT4KPCEtLSBydW4gYnVpbGQvZmls
ZS5weSAtLSE+CjwhLS0gUFlUSE9OIEVSUk9SCiAgRmlsZSAibWQvZmlsZS5tZCIsIGxpbmUg
NywgaW4gPG1vZHVsZT4KICAgIFRoZSB2YWx1ZSB4IGlzIHtce3l9XH0uCiAgRXJyb3IgPGNs
YXNzICdOYW1lRXJyb3InPiA6IG5hbWUgJ3knIGlzIG5vdCBkZWZpbmVkCi0tIT4KYGBgCgoj
IyMjIEV4YW1wbGUgMjogYG1kL2ZpbGUubWRgIHstfQpgYGBzY2FsYQogICAxICAtLS0KICAg
MiAgdGl0bGU6ICJJbnRlbmRhdGlvbiBFcnJvciIKICAgMyAgLS0tCiAgIDQgIDxcPwogICA1
ICBmb3IgaSBpbiByYW5nZSgzKToKICAgNiAgICAgIGlmIGkgJSAyOgogICA3ICAgICAgP1w+
KiBldmVuIGxpc3QgaXRlbQogICA4ICA8XD8KICAgOSAgICAgIGVsc2U6CiAgMTAgICAgICAg
ICAgP1w+KiBvZGQgbGlzdCBpdGVtCmBgYAojIyMjIFJ1biBhbmQgT3V0cHV0OiBgbWFrZSBi
dWlsZC9maWxlYCB7LX0KYGBgYmFzaAo8IS0tIHJ1biBtZC9maWxlLm1kIC0tIT4KPCEtLSBy
dW4gYnVpbGQvZmlsZS5weSAtLSE+CjwhLS0gUFlUSE9OIEVSUk9SCiAgRXJyb3IgPGNsYXNz
ICdJbmRlbnRhdGlvbkVycm9yJz4gOiBleHBlY3RlZCBhbiBpbmRlbnRlZCBibG9jawogICAg
ICAgID9cPiogZXZlbiBsaXN0IGl0ZW0gICAgICAgICAobWQvZmlsZS5tZCwgbGluZSA3KQot
LSE+CmBgYAoKIyMgVGhlIGBfX18oKWAgRnVuY3Rpb24KClVzaW5nIHRoZSBgcHJpbnQoKWAg
c3RhdGVtZW50IHRoZSB0ZXh0IHdpbGwgYmUgcHJpbnRlZCB0byB0aGUgY29uc29sZS4KV2hl
biB1c2luZyB0aGUgYF9fXygpYCBzdGF0ZW1lbnQgbmV3IE1hcmtkb3duIHRleHQgaXMKaW5z
ZXJ0ZWQgZHluYW1pY2FsbHkgaW50byB0aGUgZG9jdW1lbnQgZHVyaW5nIHByZXByb2Nlc3Np
bmcuCgojIyMjIEV4YW1wbGU6IExpbmUgQnJlYWsgey19CmBgYHB5dGhvbgo8XD97e19fXyhj
b2RlPVRydWUpfX0/XD4KYGBgCiMjIyMgUnVuIGFuZCBPdXRwdXQgey19CmBgYGJhc2gKPD8h
CnggPSA0MCAjIGhpZGRlbiBjb2RlCl9fXygiT3V0cHV0IGluICIsIF9fXykKX19fKCJzaW5n
bGUgbGluZSEgIiwgX19fKQpfX18oZiJ4ID0ge3h9IikKPz4KYGBgCgojIyMjIEV4YW1wbGU6
IFNoaWZ0LCBDcm9wLCBSZXR1cm4gey19CmBgYHB5dGhvbgo8XD97e19fXyhjb2RlPVRydWUp
fX0/XD4KYGBgCiMjIyMgUnVuIGFuZCBPdXRwdXQgey19CmBgYGJhc2gKPD8hCnJlc3VsdCA9
IF9fXygiIiIKICAgKiB0ZXh0IGlzIGNyb3BwZWQgYW5kIHNoaWZ0ZWQKICAgICAgICAgKiBz
aGlmdCBhbmQgY3JvcAogICAgICAgICAgICAqIGNhbiBiZSBjb21iaW5lZAogICAgICAgICAg
KiByZXR1cm5pbmcgdGhlIHJlc3VsdAoiIiIsIHNoaWZ0PSIjIyMjIyMjIyIsIGNyb3A9VHJ1
ZSwgcmV0PVRydWUpCl9fXyhyZXN1bHQpCj8+CmBgYAoKIyMgQWxnb3JpdGhtaWMgVGFibGUg
RXhhbXBsZQoKQHRibDphbGd0IGlzIGdlbmVyYXRlZCB1c2luZyB0aGUgZm9sbG93aW5nIHB5
dGhvbiBjbG9kZSBibG9jay4KCjw/IQpuID0gNQp0YWJsZSA9ICIiCmRlYyA9IFsiKiVzKiIs
ICIqKiVzKioiLCAifn4lc35+IiwgImAlc2AiLAogICAgICAgciIkXHRpbWVzXiVzJCIsICIk
XGluZnR5XyVzJCJdCnRhYmxlICs9ICJ8Ii5qb2luKCJYIipuKSArICJcbiIgKyAifCIuam9p
bigiLSIqbikgKyAiXG4iCmZvciBpIGluIHJhbmdlKG4pOgoJZmlsbCA9IFtjaHIob3JkKCJB
IikrKDIqaSszKmspJTI2KSBmb3IgayBpbiByYW5nZShpKzEpXQoJZmlsbCA9IFtkZWNbKGwr
aSklbGVuKGRlYyldJWsgZm9yIGwsIGsgaW4gZW51bWVyYXRlKGZpbGwpXQoJdGV4dCA9IGxp
c3QoIjAiKSpuCgl0ZXh0WyhuPj4xKS0oaT4+MSk6KG4+PjEpKyhpPj4xKV0gPSBmaWxsCgl0
YWJsZSArPSAifCIuam9pbih0ZXh0KSArICJcbiIKPz4KYGBgcHl0aG9uCnt7X19fKGNvZGU9
VHJ1ZSwgY3JvcD1UcnVlKX19CmBgYAoKe3t0YWJsZX19CgpUYWJsZTogVGFibGUgaXMgZ2Vu
ZXJhdGVkIHVzaW5nIGNvZGUgYW5kIHRoZSBgX19fKClgIHN0YXRlbWVudC4geyN0Ymw6YWxn
dH0KCiMjIEZvcm1hdCBMaW5rIEV4dGVuc2lvbgoKV2hlbiB3cml0aW5nIG11bHRpcGxlIGRv
Y3VtZW50cywgb2Z0ZW4gZG9jdW1lbnRzIGFyZSByZWZlcmVuY2VkCmJldHdlZW4gZWFjaCBv
dGhlciB1c2luZyBsaW5rcy4gSW4gb3JkZXIgdG8gcmVmZXIgdG8gZXh0ZXJuYWwKYGh0bWxg
IGFuZCBgcGRmYCBkb2N1bWVudHMgdGhlIE1hcmtkb3duIGxpbmsgc3RhdGVtZW50IGlzIHVz
ZWQuCmBgYG1kCltMaW5rIENhcHRpb25dKHBhdGgvdG8vZmlsZS5odG1sKQpbTGluayBDYXB0
aW9uXShwYXRoL3RvL2ZpbGUucGRmKQpgYGAKT25lIGxpbmsgc3RhdGVtZW50IGNhbm5vdCBi
ZSB1c2VkIGZvciByZW5kZXJpbmcgYGh0bWxgIGFuZCBgcGRmYAp3aXRoIGNvbnNpc3RlbnQg
cGF0aHMuIFVzaW5nIHRoZSBgbWFya3lgIGZvcm1hdCBsaW5rCiBgLlw/Pz9gIGZpbGUgZXh0
ZW5zaW9uIHJlc3VsdHMgaW4gY29uc2lzdGVudCBsaW5rcyBmb3IgYGh0bWxgIGFuZApgcGRm
YCBkb2N1bWVudHMuCgojIyMjIEV4YW1wbGUgey19CmBgYG1kCltMaW5rIHRvIHRoaXMgRG9j
dW1lbnRdKG1hcmt5Llw/Pz8pCmBgYAojIyMjIE91dHB1dCB7LX0KPiBbTGluayB0byB0aGlz
IERvY3VtZW50XShtYXJreS4/Pz8pCgojIyBGb3JtYXQgQ29kZXMKCk9mdGVuIHdoZW4gd3Jp
dGluZyBtYXJrZG93biBmb3IgYGh0bWxgIGFuZCBgcGRmYCBkb2N1bWVudHMsIHRoZQpvdXRw
dXQgbmVlZHMgdG8gYmUgdHdlYWtlZCBhY2NvcmRpbmdseS4KYG1hcmt5YCBzdXBwb3J0cyBm
b3JtYXQgc3BlY2lmaWMgdHdlYWtpbmcgYnkgaW5qZWN0aW5nCnJhdyBgaHRtbGAgb3IgYHRl
eGAgY29kZSBpbnRvIE1hcmtkb3duIHVzaW5nIGZvcm1hdCBjb2Rlcy4KCkluIG9yZGVyIHRv
IGluamVjdCBmb3JtYXQgc3BlY2lmaWMgY29kZSB0aGUgYGZtdGNvZGVgIGNsYXNzIGlzIHVz
ZWQuClRoZSBgZm10Y29kZWAgY2xhc3MgbWFuYWdlcyBpbmplY3Rpb24gb2YgYGh0bWxgIGFu
ZCBgdGV4YCBjb2RlCmRlcGVuZGluZyBvbiB0aGUgb3V0cHV0IGZvcm1hdC4KCioqQVRURU5U
SU9OOioqIGB0ZXhgIHBhY2thZ2VzIGhhdmUgdG8gYmUgaW5jbHVkZWQgZm9yIGBwZGZgIGFz
IHdlbGwgYXMKSmF2YVNjcmlwdCBhbmQgc3R5bGUgc2hlZXRzIGZvciBgaHRtbGAgdXNpbmcg
dGhlIG1ldGEgZGF0YSBmaWVsZHMKYGhlYWRlci1pbmNsdWRlcy0tcGRmYCBhbmQgYGhlYWRl
ci1pbmNsdWRlcy0taHRtbGAgcmVzcGVjdGl2ZWx5LgoKIyMjIyBFeGFtcGxlOiBgZm10Y29k
ZWAgey19Cjw/IQpGID0gZm10Y29kZShodG1sPSJIPHN1cD5UPC9zdXA+PHN1Yj5NPC9zdWI+
TCIsIHBkZj1yIlxMYVRlWCIpCj8+CmBgYHB5dGhvbgp7e19fXyhjb2RlPVRydWUsIGNyb3A9
VHJ1ZSl9fQpgYGAKYGBgbWFya2Rvd24KSW52b2NhdGlvbiBvZiBmb3JtYXQgY29kZSByZXN1
bHRzIGluOiB7XHtGKCl9XH0uCmBgYAojIyMjIE91dHB1dCB7LX0KPiBJbnZvY2F0aW9uIG9m
IGZvcm1hdCBjb2RlIHJlc3VsdHMgaW46IHt7RigpfX0uCgojIyMjIEV4YW1wbGU6IENvbG9y
IHstfQo8PyEKQyA9IGxhbWJkYSBjb2xvcjogZm10Y29kZSgKCWh0bWw9IjxzcGFuIHN0eWxl
PSdjb2xvcjolczsnPnswfTwvc3Bhbj4iICUgY29sb3IsCglwZGY9ciJcdGV4dGNvbG9ye3sl
c319e3t7MH19fSIgJSBjb2xvcgopCkIgPSBDKCJibHVlIikKUiA9IEMoInJlZCIpCj8+CmBg
YHB5dGhvbgp7e19fXyhjb2RlPVRydWUsIGNyb3A9VHJ1ZSl9fQpgYGAKYGBgbWFya2Rvd24K
VGV4dCB3aXRoIHtce0IoImJsdWUiKX1cfSBhbmQge1x7UigiUkVEIil9XH0uCmBgYAojIyMj
IE91dHB1dCB7LX0KPiBUZXh0IHdpdGgge3tCKCJibHVlIil9fSBhbmQge3tSKCJSRUQiKX19
LgoKCiMjIyMgRXhhbXBsZTogQ2xhc3NlcyB7LX0KPD8hCmNsYXNzIGNvbG9yOgoJZGVmIF9f
aW5pdF9fKHNlbGYsIGNvbG9yKToKCQlzZWxmLmNvbG9yID0gY29sb3IKCWRlZiB1cHBlcihz
ZWxmLCB4KToKCQlyZXR1cm4gc2VsZi50ZXh0KHgudXBwZXIoKSkKCWRlZiBsb3dlcihzZWxm
LCB4KToKCQlyZXR1cm4gc2VsZi50ZXh0KHgubG93ZXIoKSkKCmNsYXNzIGh0bWwoY29sb3Ip
OgoJZGVmIHRleHQoc2VsZiwgeCk6CgkJcmV0dXJuIGYiPHNwYW4gc3R5bGU9J2NvbG9yOntz
ZWxmLmNvbG9yfTsnPnt4fTwvc3Bhbj4iCgpjbGFzcyBwZGYoY29sb3IpOgoJZGVmIHRleHQo
c2VsZiwgeCk6CgkJcmV0dXJuIHJmIlx0ZXh0Y29sb3J7e3tzZWxmLmNvbG9yfX19e3t7eH19
fSIKCkNDID0gbGFtYmRhIHg6IGZtdGNvZGUoaHRtbD1odG1sKHgpLCBwZGY9cGRmKHgpKQpC
QiA9IENDKCJibHVlIikKUlIgPSBDQygicmVkIikKPz4KYGBgcHl0aG9uCnt7X19fKGNvZGU9
VHJ1ZSwgY3JvcD1UcnVlKX19CmBgYApgYGBtYXJrZG93bgpUZXh0IHdpdGgge1x7QkIudXBw
ZXIoImJsdWUiKX1cfSBhbmQge1x7UlIubG93ZXIoIlJFRCIpfVx9LgpgYGAKIyMjIyBPdXRw
dXQgey19Cj4gVGV4dCB3aXRoIHt7QkIudXBwZXIoImJsdWUiKX19IGFuZCB7e1JSLmxvd2Vy
KCJSRUQiKX19LgoKIyMgTWFya2Rvd24gSW5jbHVkZQoKVGhlIGBtYXJreWAgaW5jbHVkZSBz
dGF0ZW1lbnQgYF9fXyhmaWxlKWAgRm9yIGluY2x1c2lvbiBvZiB0ZXh0IGZyb20Kb3RoZXIg
ZmlsZXMgY2FuIGJlIHVzZWQgdG8gaW5jbHVkZSB0ZXh0IGludG8gYGh0bWxgIGFuZCBgcGRm
YCBkb2N1bWVudHMuCmBgYHB5dGhvbgo8XD8KX19fKGZpbGU9ImluY2x1ZGUubWQiLCBfX21h
cmt5X189RmFsc2UsIHJhdz1GYWxzZSwgYXV4PUZhbHNlLCBjbWQ9Tm9uZSkKP1w+CmBgYAoK
YF9fXyhmaWxlKWAgc3VwcG9ydHMgZm9sbG93aW5nIG9wdGlvbnMuCiogYF9fbWFya3lfX2A6
IGNvbnRyb2xzIHdoZXRoZXIgdGhlIGluY2x1ZGUgZmlsZSBpcyBwcm9jZXNzZWQgYXMgYG1h
cmt5YApzY3JpcHQgKGBUcnVlYCkgb3IgYXMgYSBgbWFya3lgIG1vZHVsZSAoYEZhbHNlYCwg
ZGVmYXVsdCkuCiogYHJhd2A6IGNvbnRyb2xzIHdoZXRoZXIgdGhlIGluY2x1ZGUgZmlsZSBp
cyBpbmNsdWRlZCBhcy1pcyAoYFRydWVgKQpvciBwcm9jZXNzZWQgdmlhIGBtYXJreWAgKGBG
YWxzZWAsIGRlZmF1bHQpLgoqIGBhdXhgOiBkaXNhYmxlcyBwcm9jZXNzaW5nIG9mIHRoZSBm
aWxlIGlmIGBUcnVlYCwgKGRlZmF1bHQ6IGBGYWxzZWApLgoqIGBjbWRgOiBjb21tYW5kIG9y
IGNhbGxhYmxlIGZvciBidWlsZHVuZyBhdXggZmlsZSwgd2hpY2ggd2lsbCBiZSBpbnZva2Vk
Cm9ubHkgaWYgYXV4IGZpbGUgZG9lcyBub3QgZXhpc3QuCgpJbmNsdWRlIGZpbGVzIGFuZCBh
dXggZmlsZXMgbXVzdCBleGlzdCBkdXJpbmcgcHJvY2Vzc2luZywgb3RoZXJ3aXNlCmBtYXJr
eWAgd2lsbCBmYWlsLiBDb21tYW5kcyBmb3IgbWFraW5nIGF1eCBmaWxlcyBhbHNvIGNhbiBi
ZSBhY2Nlc3NlZAp2aWEgTWFrZWZpbGUgdGFyZ2V0cywgc2VlIGBtYWtlIGhlbHBgIG9yIGBt
YWtlIGxpc3RgLgoKV2hlbiBzY3JpcHQgbW9kZSBpcyBhY3RpdmF0ZWQgKGBfX21hcmt5X189
VHJ1ZWApIHRoZW4gdGhlICptb2R1bGUgY29kZSoKYXMgd2VsbCBhcyB0aGUgKnNjcmlwdCBj
b2RlKiBhcmUgZXhlY3V0ZWQuIEhvd2V2ZXIsIGlmIG1vZHVsZSBtb2RlIGlzCmFjdGl2YXRl
ZCAoYF9fbWFya3lfXz1GYWxzZWApLCBvbmx5IHRoZSAqbW9kdWxlIGNvZGUqIGlzIHByb2Nl
c3NlZC4KCmBgYHBocAotLS0KdGl0bGU6IFRlc3QKLS0tCjxcPwojIG1hcmt5IG1vZHVsZSBj
b2RlCj9cPgpgbWFya3lgIG1vZHVsZSBvdXRwdXQKPFw/CmlmIF9fbWFya3lfXzoKCSMgbWFy
a3kgc2NyaXB0IGNvZGUKCT9cPmBtYXJreWAgc2NyaXB0IG91dHB1dDxcPwo/XD4KYGBgCgoj
IE1ldGEgRGF0YSBpbiBGcm9udCBNYXR0ZXIKCk1ldGEgZGF0YSBpcyBhbm5vdGF0ZWQgaW4g
dGhlIGZyb250IG1hdHRlciBvZiBhIE1hcmtkb3duIHRleHQgZG9jdW1lbnQuClRoZSBmcm9u
dCBtYXR0ZXIgbXVzdCBzdGFydCBpbiB0aGUgZmlyc3QgbGluZSB3aXRoIGAtLS1gIGFuZCBw
cmVjZWRlcyBhbGwKb3RoZXIgdGV4dCBiZWluZyBmZW5jZWQgYnkgYC0tLWAuIFRoZSBtZXRh
IGRhdGEgaXMgaW4gYHlhbWxgIGZvcm1hdC4KVGhlIGB5YW1sYCBibG9jayBpcyBwYXJzZWQg
dXNpbmcgYHB5dGhvbi1weXlhbWxgLiBBbGwgbWV0YQpkYXRhIGlzIGltcG9ydGVkIGludG8g
dGhlIHByZXByb2Nlc3NlZCBkb2N1bWVudC4KCiMjIFBhbmRvYyBGcm9udCBNYXR0ZXIKCiMj
IyMgRXhhbXBsZSB7LX0KYGBgeWFtbAotLS0KdGl0bGU6IE15IERvY3VtZW50CmRhdGU6IDIw
MjItMDEtMDEKYXV0aG9yOiAuLi4KbGluay1jaXRhdGlvbnM6IHRydWUKYmlibGlvZ3JhcGh5
OiBkYXRhL21hcmt5LmJpYgpoZWFkZXItaW5jbHVkZXM6ID4KICAgXGh5cGVyc2V0dXB7Y29s
b3JsaW5rcz1mYWxzZSwKICAgYWxsYm9yZGVyY29sb3JzPXswIDAgMH0sCiAgIHBkZmJvcmRl
cnN0eWxlPXsvUy9VL1cgMX1cfQp4bm9zLWNsZXZlcmVmOiB0cnVlCnhub3MtY2FwaXRhbGlz
ZTogdHJ1ZQpmb250c2l6ZTogMTFwdAotLS0KYGBgClRoZSBtZXRhIGRhdGEgZmllbGRzCltg
dGl0bGVgLCBgZGF0ZWAsIGBhdXRob3JgXShodHRwczovL3BhbmRvYy5vcmcvTUFOVUFMLmh0
bWwjbWV0YWRhdGEtdmFyaWFibGVzKSwKW2BsaW5rLWNpdGF0aW9uc2BdKGh0dHBzOi8vcGFu
ZG9jLm9yZy9NQU5VQUwuaHRtbCNvdGhlci1yZWxldmFudC1tZXRhZGF0YS1maWVsZHMpLApb
YGJpYmxpb2dyYXBoeWBdKGh0dHBzOi8vcGFuZG9jLm9yZy9NQU5VQUwuaHRtbCNjaXRhdGlv
bi1yZW5kZXJpbmcpIGFuZApbYGhlYWRlci1pbmNsdWRlc2BdKGh0dHBzOi8vcGFuZG9jLm9y
Zy9NQU5VQUwuaHRtbCN2YXJpYWJsZXMtc2V0LWF1dG9tYXRpY2FsbHkpCmFyZSBwcm9jZXNz
ZWQgYnkgYHBhbmRvY2AgZHVyaW5nIGRvY3VtZW50IHJlbmRlcmluZy4gYGZvbnRzaXplYCBh
ZGp1c3RzIHRoZQpmb250IHNpemUgaW4gW2BodG1sYF0oaHR0cHM6Ly9wYW5kb2Mub3JnL01B
TlVBTC5odG1sI3ZhcmlhYmxlcy1mb3ItaHRtbCkKYW5kIFtgcGRmYF0oaHR0cHM6Ly9wYW5k
b2Mub3JnL01BTlVBTC5odG1sI3ZhcmlhYmxlcy1mb3ItbGF0ZXgpIGRvY3VtZW50cy4KVGhl
IGB4bm9zLWNsZXZlcmVmYCBhbmQgYHhub3MtY2FwaXRhbGlzZWAKZmllbGRzIGFyZSB1c2Vk
IGJ5IHRoZSBbYHBhbmRvYy14bm9zYF0oaHR0cHM6Ly9naXRodWIuY29tL3RvbWR1Y2svcGFu
ZG9jLXhub3MpCmV4dGVuc2lvbnMgZm9yIHJlZmVyZW5jaW5nCltmaWd1cmVzXShodHRwczov
L2dpdGh1Yi5jb20vdG9tZHVjay9wYW5kb2MtZmlnbm9zI2N1c3RvbWl6YXRpb24pLApbdGFi
bGVzXShodHRwczovL2dpdGh1Yi5jb20vdG9tZHVjay9wYW5kb2MtdGFibGVub3MjY3VzdG9t
aXphdGlvbiksCltzZWN0aW9uc10oaHR0cHM6Ly9naXRodWIuY29tL3RvbWR1Y2svcGFuZG9j
LXNlY25vcyNjdXN0b21pemF0aW9uKSBhbmQKW2VxdWF0aW9uc10oaHR0cHM6Ly9naXRodWIu
Y29tL3RvbWR1Y2svcGFuZG9jLWVxbm9zI2N1c3RvbWl6YXRpb24pLgoKIyMgVXBkYXRlIE1l
dGEgRGF0YQoKVGhlIGZyb250IG1hdHRlciBzZWN0aW9uIGNvbnRhaW5zIG1ldGEgZGF0YSBv
ZiB0aGUgZG9jdW1lbnQuCm1ldGEgZGF0YSBrZXlzIGNhbiBiZSB1cGRhdGVkIGZyb20gY29k
ZSBibG9ja3MgdXNpbmcKYF9fXyhtZXRhPWRpY3QoKSlgLgoKIyMjIyBFeGFtcGxlOiBgbWQv
ZmlsZS5tZGAgey19CmBgYHBocAotLS0KdGl0bGU6IE15IERvY3VtZW50CmRhdGU6ICJ1bmtu
b3duIgotLS0KPFw/e3tfX18oY29kZT1UcnVlKX19P1w+CmBgYAo8PyEKaW1wb3J0IGRhdGV0
aW1lCnRvZGF5ID0gZGF0ZXRpbWUuZGF0ZS50b2RheSgpLnN0cmZ0aW1lKCIlQiAlZCwgJVki
KQpkYXRhID0gX19fKG1ldGE9VHJ1ZSkKZGF0YVsiZGF0ZSJdID0gdG9kYXkKPz4KIyMjIyBP
dXRwdXQgey19CmBgYHBocAotLS0KdGl0bGU6IE15IERvY3VtZW50CmRhdGU6ICJ7e3RvZGF5
fX0iCnZlcnNpb246ICIxLjAiCi0tLQpgYGAKCiMjIGBtYXJreWAgRm9ybWF0IEZpZWxkcwoK
IyMjIyBFeGFtcGxlOiBgbWQvZmlsZS5tZGAgey19CmBgYHlhbWwKLS0tCmhlYWRlci1pbmNs
dWRlcy0tcGRmOiA+CiAgXGh5cGVyc2V0dXB7CiAgY29sb3JsaW5rcz1mYWxzZSwKICBhbGxi
b3JkZXJjb2xvcnM9ezAgMCAwfSwKICBwZGZib3JkZXJzdHlsZT17L1MvVS9XIDF9XH0KaGVh
ZGVyLWluY2x1ZGVzLS1odG1sOiA+CiAgPHN0eWxlPiogeyBib3gtc2l6aW5nOiBib3JkZXIt
Ym94OyB9PC9zdHlsZT4KLS0tCmBgYAoKVGhlIHBhbmRvYyBgaGVhZGVyLWluY2x1ZGVzYCBm
aWVsZCBpcyB1c2VkIGZvciBgcGRmYCBhbmQgYGh0bWxgIGRvY3VtZW50cywKdGhlcmVmb3Jl
IGl0IG11c3QgY29udGFpbiBjb3JyZXNwb25kaW5nIHRleCBhbmQgYGh0bWxgIGNvZGUuCgpU
aGUgZmllbGQgYGhlYWRlci1pbmNsdWRlc2AgZW5kaW5nIHdpdGggYC0tcGRmYCBvciBgLS1o
dG1sYApzcGVjaWZpZXMgY29ycmVzcG9uZGluZyBvcHRpb25zIGZvciB0aGUgZ2VuZXJhdGlv
biBvZiBgcGRmYCBhbmQgYGh0bWxgCmRvY3VtZW50cy4gRHVyaW5nIG1ha2UsIGBtYXJreWAg
c2NhbnMgYWxsIG1ldGEgZGF0YSBmaWVsZHMsIGFuZApmaWVsZHMgd2hpY2ggZW5kIHdpdGgg
YC0tcGRmYCBhbmQgYC0taHRtbGAgYXJlIHNlbGVjdGVkIGFuZCBmb3J3YXJkZWQKdG8gYHBh
bmRvY2AgYmFzZWQgb24gdGhlIGZvcm1hdCB0byBiZSByZW5kZXJlZC4KCkFmdGVyIGJ1aWxk
IGBtYWtlIGJ1aWxkL2ZpbGVgIHRoZSBtZXRhIGRhdGEgZmllbGQgYGhlYWRlci1pbmNsdWRl
c2AKaXMgcHJlc2VudCBpbiB0aGUgZmlsZXMgYGJ1aWxkL2ZpbGUuaHRtbC5tZGAgYW5kYGJ1
aWxkL2ZpbGUucGRmLm1kYAphY2NvcmRpbmdseS4KCiMjIyMgRXhhbXBsZTogYGJ1aWxkL2Zp
bGUuaHRtbC5tZGAgey19CmBgYHlhbWwKLS0tCmhlYWRlci1pbmNsdWRlczogPgogIDxzdHls
ZT4qIHsgYm94LXNpemluZzogYm9yZGVyLWJveDsgfTwvc3R5bGU+Ci0tLQpgYGAKIyMjIyBF
eGFtcGxlOiBgYnVpbGQvZmlsZS5wZGYubWRgIHstfQpgYGB5YW1sCi0tLQpoZWFkZXItaW5j
bHVkZXM6ID4KICBcaHlwZXJzZXR1cHsKICBjb2xvcmxpbmtzPWZhbHNlLAogIGFsbGJvcmRl
cmNvbG9ycz17MCAwIDB9LAogIHBkZmJvcmRlcnN0eWxlPXsvUy9VL1cgMX1cfQotLS0KYGBg
CgojIFNjaWVudGlmaWMgV3JpdGluZyBpbiBNYXJrZG93bgoKW01hcmtkb3duXShodHRwczov
L3BhbmRvYy5vcmcvTUFOVUFMLmh0bWwjcGFuZG9jcy1tYXJrZG93bikgaXMgYSBtYXJrdXAK
bGFuZ3VhZ2UgZm9yIHRlY2huaWNhbCB3cml0aW5nLCB3aXRoIGVtcGhhc2lzIG9uIHJlYWRh
YmlsaXR5LiBNYXJrZG93bgpjYW4gYmUgcmVuZGVyZWQgaW4gbWFueSBmb3JtYXRzIGluY2x1
ZGluZyBgaHRtbGAgYW5kIGBwZGZgIGJ5IHVzaW5nCltgcGFuZG9jYF0oaHR0cHM6Ly9wYW5k
b2Mub3JnLykgZm9yIGV4YW1wbGUuCgpVc2luZyB2YXJpb3VzIE1hcmtkb3duIGV4dGVuc2lv
bnMgb2YgYHBhbmRvY2AgYSBzdWZmaWNpZW50IHN0cnVjdHVyZSBmb3IKd3JpdGluZyBzY2ll
bnRpZmljIGRvY3VtZW50cyBpcyByZWZsZWN0ZWQgdXNpbmcgTWFya2Rvd24gc3ludGF4Lgpg
bWFya3lgIGJ5IGRlZmF1bHQgdXNlcyB0aGUgZm9sbG93aW5nIGBwYW5kb2NgIE1hcmtkb3du
IGV4dGVuc2lvbnMuCiogcGFyc2luZyBleHRlbnNpb25zCgkqIFthbGxfc3ltYm9sc19lc2Nh
cGFibGVdKGh0dHBzOi8vcGFuZG9jLm9yZy9NQU5VQUwuaHRtbCNleHRlbnNpb24tYWxsX3N5
bWJvbHNfZXNjYXBhYmxlKQoJKiBbaW50cmF3b3JkX3VuZGVyc2NvcmVzXShodHRwczovL3Bh
bmRvYy5vcmcvTUFOVUFMLmh0bWwjZXh0ZW5zaW9uLWludHJhd29yZF91bmRlcnNjb3JlcykK
CSogW2VzY2FwZWRfbGluZV9icmVha3NdKGh0dHBzOi8vcGFuZG9jLm9yZy9NQU5VQUwuaHRt
bCNleHRlbnNpb24tZXNjYXBlZF9saW5lX2JyZWFrcykKCSogW3NwYWNlX2luX2F0eF9oZWFk
ZXJdKGh0dHBzOi8vcGFuZG9jLm9yZy9NQU5VQUwuaHRtbCNleHRlbnNpb24tc3BhY2VfaW5f
YXR4X2hlYWRlcikKCSogW2xpc3RzX3dpdGhvdXRfcHJlY2VkaW5nX2JsYW5rbGluZV0oaHR0
cHM6Ly9wYW5kb2Mub3JnL01BTlVBTC5odG1sI2V4dGVuc2lvbi1saXN0c193aXRob3V0X3By
ZWNlZGluZ19ibGFua2xpbmUpCiogc3R5bGluZyBleHRlbnNpb25zCgkqIFtpbmxpbmVfY29k
ZV9hdHRyaWJ1dGVzXShodHRwczovL3BhbmRvYy5vcmcvTUFOVUFMLmh0bWwjZXh0ZW5zaW9u
LWlubGluZV9jb2RlX2F0dHJpYnV0ZXMpCgkqIFtzdHJpa2VvdXRdKGh0dHBzOi8vcGFuZG9j
Lm9yZy9NQU5VQUwuaHRtbCNleHRlbnNpb24tc3RyaWtlb3V0KQoJKiBbYnJhY2tldGVkX3Nw
YW5zXShodHRwczovL3BhbmRvYy5vcmcvTUFOVUFMLmh0bWwjZXh0ZW5zaW9uLWJyYWNrZXRl
ZF9zcGFucykKKiBzdHJ1Y3R1cmluZyBleHRlbnNpb25zCgkqIFt5YW1sX21ldGFkYXRhX2Js
b2NrXShodHRwczovL3BhbmRvYy5vcmcvTUFOVUFMLmh0bWwjZXh0ZW5zaW9uLXlhbWxfbWV0
YWRhdGFfYmxvY2spCgkqIFtwaXBlX3RhYmxlc10oaHR0cHM6Ly9wYW5kb2Mub3JnL01BTlVB
TC5odG1sI2V4dGVuc2lvbi1waXBlX3RhYmxlcykKCSogW2xpbmVfYmxvY2tzXShodHRwczov
L3BhbmRvYy5vcmcvTUFOVUFMLmh0bWwjZXh0ZW5zaW9uLWxpbmVfYmxvY2tzKQoJKiBbaW1w
bGljaXRfZmlndXJlc10oaHR0cHM6Ly9wYW5kb2Mub3JnL01BTlVBTC5odG1sI2V4dGVuc2lv
bi1pbXBsaWNpdF9maWd1cmVzKQoJKiBbZm9vdG5vdGVzXShodHRwczovL3BhbmRvYy5vcmcv
TUFOVUFMLmh0bWwjZXh0ZW5zaW9uLWZvb3Rub3RlcykKCSogW2FiYnJldmlhdGlvbnNdKGh0
dHBzOi8vcGFuZG9jLm9yZy9NQU5VQUwuaHRtbCNleHRlbnNpb24tYWJicmV2aWF0aW9ucykK
CSogW2lubGluZV9ub3Rlc10oaHR0cHM6Ly9wYW5kb2Mub3JnL01BTlVBTC5odG1sI2V4dGVu
c2lvbi1pbmxpbmVfbm90ZXMpCiogY29kZSBpbmplY3Rpb24KCSogW3Jhd19odG1sXShodHRw
czovL3BhbmRvYy5vcmcvTUFOVUFMLmh0bWwjZXh0ZW5zaW9uLXJhd19odG1sKQoJKiBbcmF3
X3RleF0oaHR0cHM6Ly9wYW5kb2Mub3JnL01BTlVBTC5odG1sI2V4dGVuc2lvbi1yYXdfdGV4
KQoJKiBbbmF0aXZlX2RpdnNdKGh0dHBzOi8vcGFuZG9jLm9yZy9NQU5VQUwuaHRtbCNleHRl
bnNpb24tbmF0aXZlX2RpdnMpCgkqIFtuYXRpdmVfc3BhbnNdKGh0dHBzOi8vcGFuZG9jLm9y
Zy9NQU5VQUwuaHRtbCNleHRlbnNpb24tbmF0aXZlX3NwYW5zKQoKYHBhbmRvY2Agc3VwcG9y
dHMKW2VxdWF0aW9uc10oaHR0cHM6Ly9wYW5kb2Mub3JnL01BTlVBTC5odG1sI2V4dGVuc2lv
bi10ZXhfbWF0aF9kb2xsYXJzKQpyZW5kZXJlZCBpbmxpbmUgYW5kIHNpbmdsZS1saW5lIGlu
IHRleC1zdHlsZSB1c2luZyBgJC4uLiRgIGFuZCBgJCQuLi4kJGAsCltiaWJsaW9ncmFwaHld
KGh0dHBzOi8vcGFuZG9jLm9yZy9NQU5VQUwuaHRtbCNjaXRhdGlvbnMpCnVzaW5nIHRoZSBg
LS1jaXRlcHJvY2Agb3B0aW9uLApbc2VjdGlvbiBudW1iZXJpbmddKGh0dHBzOi8vcGFuZG9j
Lm9yZy9NQU5VQUwuaHRtbCNleHRlbnNpb24taGVhZGVyX2F0dHJpYnV0ZXMpCnVzaW5nIHRo
ZSBgLS1udW1iZXItc2VjdGlvbnNgIG9wdGlvbiBhbmQKW3RhYmxlIG9mIGNvbnRlbnRzXSho
dHRwczovL3BhbmRvYy5vcmcvTUFOVUFMLmh0bWwjb3B0aW9uLS10b2MpCnVzaW5nIHRoZSBg
LS10YWJsZS1vZi1jb250ZW50c2Agb3B0aW9uLgoKYHBhbmRvY2Agc3VwcG9ydHMgW2B4bm9z
YF0oaHR0cHM6Ly9naXRodWIuY29tL3RvbWR1Y2svcGFuZG9jLXhub3MpIGZpbHRlcnMKZm9y
IHJlZmVyZW5jaW5nIGRvY3VtZW50IGNvbnRlbnQgbGlrZQpbZmlndXJlc10oaHR0cHM6Ly9n
aXRodWIuY29tL3RvbWR1Y2svcGFuZG9jLWZpZ25vcyN1c2FnZSksCltlcXVhdGlvbnNdKGh0
dHBzOi8vZ2l0aHViLmNvbS90b21kdWNrL3BhbmRvYy1lcW5vcyN1c2FnZSksClt0YWJsZXNd
KGh0dHBzOi8vZ2l0aHViLmNvbS90b21kdWNrL3BhbmRvYy10YWJsZW5vcyN1c2FnZSksCltz
ZWN0aW9uc10oaHR0cHM6Ly9naXRodWIuY29tL3RvbWR1Y2svcGFuZG9jLXNlY25vcyN1c2Fn
ZSkKYnkgdXNpbmcgdGhlIGAtLWZpbHRlciBwYW5kb2MteG5vc2Agb3B0aW9uLgpgeG5vc2Ag
aW50ZWdyYXRlcyBjbGV2ZXIgcmVmZXJlbmNlcywgd2hpY2ggbWVhbnMgIkZpZy4iLCAiU2Vj
LiIsICJFcS4iCmFuZCAiVGFiLiIgYXJlIGFkZGVkIGF1dG9tYXRpY2FsbHkgdG8gdGhlIGNv
cnJlc3BvbmRpbmcgZWxlbWVudC4KSWYgdGhlIHByZWZpeCBpcyB0byBiZSBvbWl0dGVkLCB0
aGUgcmVmZXJlbmNlIGlzIHdyaXR0ZW4gYXMKYFwhQHJlZjpsYWJlbGAuCgojIyMjIEV4YW1w
bGUgey19CmBgYG1kCiMjIFJlZmVyZW5jZWQgU2VjdGlvbiB7I3NlYzpsYWJlbH0KClRoaXMg
aXMgYSByZWZlcmVuY2UgdG8gQHNlYzpsYWJlbC4KCiFbVGhpcyBpcyB0aGUgY2FwdGlvbl0o
ZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TClVoRVVnQUFBQVVBQUFB
RkNBWUFBQUNOYnlibEFBQUFIRWxFUVZRSTEyUDQvLzgvdzM4R0lBWERJQktFMERICnhnbGpO
QkFBTzlUWEwwWTRPSHdBQUFBQkpSVTVFcmtKZ2dnPT0peyNmaWc6bGFiZWx9CgpUaGlzIGlz
IGEgcmVmZXJlbmNlIHRvIEBmaWc6bGFiZWwuCgpBICB8QiAgfEMgIHxECi0tLXwtLS18LS0t
fC0tLQowMDB8MTExfDQ0NHw1NTUKMjIyfDMzM3w2NjZ8Nzc3CgpUYWJsZTogVGhpcyBpcyB0
aGUgY2FwdGlvbiB7I3RibDpsYWJlbH0KClRoaXMgaXMgYSByZWZlcmVuY2UgdG8gQHRibDps
YWJlbC4KCiQkXG1ib3h7ZX1ee1xtYm94e2l9XHBpfSsxPTAkJHsjZXE6bGFiZWx9CgpUaGlz
IGlzIGEgcmVmZXJlbmNlIHRvIEBlcTpsYWJlbC4KClRoaXMgaXMgYSBjaXRhdGlvbiBbQE11
bGxlcjE5OTNdLgpgYGAKClRoZSBmaWxlIGBtYXJreS5iaWJgIGlzIHNwZWNpZmllZCBpbiB0
aGUgbWV0YSBkYXRhIGluIHRoZSBmcm9udAptYXR0ZXIgb2YgdGhlIE1hcmtkb3duIHRleHQu
CgojIyBSZWZlcmVuY2VkIFNlY3Rpb24geyNzZWM6bGFiZWx9CgpUaGlzIGlzIGEgcmVmZXJl
bmNlIHRvIEBzZWM6bGFiZWwuCgohW1RoaXMgaXMgdGhlIGNhcHRpb25dKGRhdGE6aW1hZ2Uv
cG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQVVBQUFBRkNBWUFBQUNOYnli
bEFBQUFIRWxFUVZRSTEyUDQvLzgvdzM4R0lBWERJQktFMERIeGdsak5CQUFPOVRYTDBZNE9I
d0FBQUFCSlJVNUVya0pnZ2c9PSl7I2ZpZzpsYWJlbH0KClRoaXMgaXMgYSByZWZlcmVuY2Ug
dG8gQGZpZzpsYWJlbC4KCkEgIHxCICB8QyAgfEQKLS0tfC0tLXwtLS18LS0tCjAwMHwxMTF8
NDQ0fDU1NQoyMjJ8MzMzfDY2Nnw3NzcKClRhYmxlOiBUaGlzIGlzIHRoZSBjYXB0aW9uLiB7
I3RibDpsYWJlbH0KClRoaXMgaXMgYSByZWZlcmVuY2UgdG8gQHRibDpsYWJlbC4KCiQkXG1i
b3h7ZX1ee2lccGl9KzE9MCQkeyNlcTpsYWJlbH0KClRoaXMgaXMgYSByZWZlcmVuY2UgdG8g
QGVxOmxhYmVsLgoKVGhpcyBpcyBhIGNpdGF0aW9uIFtATXVsbGVyMTk5M10uCgotLS0KCiMg
UmVmZXJlbmNlcwo=
'''
pack_marky_bib = '''
QGFydGljbGV7TXVsbGVyMTk5MywKICAgIGF1dGhvciAgPSB7UGV0ZXIgTXVsbGVyfSwKICAg
IHRpdGxlICAgPSB7VGhlIHRpdGxlIG9mIHRoZSB3b3JrfSwKICAgIGpvdXJuYWwgPSB7VGhl
IG5hbWUgb2YgdGhlIGpvdXJuYWx9LAogICAgeWVhciAgICA9IHsxOTkzfSwKICAgIG51bWJl
ciAgPSB7Mn0sCiAgICBwYWdlcyAgID0gezIwMS0yMTN9LAogICAgbW9udGggICA9IHs3fSwK
ICAgIG5vdGUgICAgPSB7QW4gb3B0aW9uYWwgbm90ZX0sCiAgICB2b2x1bWUgID0gezR9Cn0K
'''
pack__gitignore = '''
YnVpbGQvCmh0bWwvCnBkZi8K
'''
###!!!:::marky_pack_data:::!!!###
########################################################################
# SECTION IS AUTO-PACKAGED USING ./marky.py --pack --force
########################################################################
########################################################################
def _marky_front_join(y, text):
return """---\n%s\n---\n%s""" % (
yaml.dump(y, allow_unicode=True, default_flow_style=False),
text
)
def _marky_front_split(t):
global _MARKY_EXEC_GLOBALS
global _MARKY_EXEC_QUIET
if not t.startswith("---\n"):
return dict(), t, 0
y = t.split("---\n")[1]
meta_lines = len(y.split("\n")) + 2
mark = "---\n".join(t.split("---\n")[2:])
_marky_print_mark("---\n" + y + "---")
data = dict()
try:
data = yaml.safe_load(y)
except Exception as ex:
print("# YAML ERROR", type(ex), str(ex))
sys.exit(1)
return data, mark, meta_lines
########################################################################
def _marky_print_mesg(*args):
print("<!--", *args, "--!>")
def _marky_print_mark(*args, end="\n"):
if not _MARKY_EXEC_QUIET: print(*args, end=end, flush=True)
def _marky_print_trace(ex, mlines, code):
print("# TRACEBACK")
import traceback
traceback.print_tb(ex.__traceback__)
print(dir(ex), ex.args, ex.__dict__)
if hasattr(ex, "filename") and ex.filename == "<string>":
print("# ERROR LOCATION")
code = code.split("\n")
print(len(code))
for i in range(max(0, ex.lineno-5), min(len(code), ex.lineno+5)):
print("*" if i + 1 == ex.lineno else " ", "%03d" % i, code[i])
print("# PYTHON ERROR")
print(type(ex), str(ex))
def _marky_file_mtime_older(f1, f2):
return os.path.getmtime(f1) < os.path.getmtime(f2)
def _marky_file_mtime_newer(f1, f2):
return os.path.getmtime(f1) > os.path.getmtime(f2)
def _marky_file_make_basename(f):
return "/".join(".".join(f.split(".")[0:-1]).split("/")[1:])
def _marky_mdtext_print(*args, sep=" ",
shift="", join="\n", crop=False, ret=False,
code=False, text=False, pop=True, meta=False,
file=None, __marky__=False, raw=False, aux=False, cmd=None
):
# MD output: args, sep=" ", shift="", crop=False, ret=False
# MD code output: code=False, pop=True
# MD include: file, __marky__, raw, aux
global _MARKY_EXEC_QUIET
global _MARKY_EXEC_TEXT
global _MARKY_EXEC_APPEND
global _MARKY_PASTE_CODE
global _MARKY_PASTE_TEXT
global _MARKY_COMMAND_LIST
global _MARKY_META_DICT
if meta:
return _MARKY_META_DICT
if text:
text = _MARKY_EXEC_TEXT[_MARKY_PASTE_TEXT:]
if pop: _MARKY_PASTE_TEXT = len(_MARKY_EXEC_TEXT)
return _marky_mdtext_print(text, shift=shift, crop=crop, ret=True)
if code:
if len(_MARKY_PASTE_CODE) == 0: return ""
code = _MARKY_PASTE_CODE[0]
if pop: _MARKY_PASTE_CODE = _MARKY_PASTE_CODE[1:]
return _marky_mdtext_print(code, shift=shift, crop=crop, ret=True)
if not file is None:
if aux:
if not os.path.exists(file):
if cmd is None or len(cmd.strip()) == 0:
pass
elif _MARKY_AUXCMD:
_marky_print_mesg("run aux cmd for", file, ":", cmd)
if callable(cmd):
cmd()
elif type(cmd) is str:
os.system(cmd)
else:
_marky_print_mesg("ERROR", "___(file, cmd=...) has wrong value:", cmd)
sys.exit(1)
if os.path.exists(file):
_marky_print_mesg("aux file exists:", file)
_MARKY_INCLUDE_LIST.append(file)
_MARKY_COMMAND_LIST.append("" if cmd is None or len(str(cmd).strip()) == 0 else cmd)
elif raw:
if not os.path.exists(file):
print("# ERROR", "no such file", file)
sys.exit(1)
_marky_mdtext_print(open(file, "r").read(), _marky_mdtext_print)
else:
_marky_run(file, _marky_file_make_basename(file), __marky__)
return
if len(args) == 0 or (len(args) == 1 and args[0] == _marky_mdtext_print):
if _MARKY_EXEC_APPEND == False: _MARKY_EXEC_TEXT += "\n"
_MARKY_EXEC_APPEND = False
else:
if ret: return _marky_mdtext_ret(args[0], shift, crop, join)
if crop or shift != "" or join != "\n":
_marky_mdtext_crop(args[0], shift, crop, join)
if args[-1] == _marky_mdtext_print:
_MARKY_EXEC_APPEND = True
return
exec_append_new = False
if args[-1] == _marky_mdtext_print:
exec_append_new = True
args = args[0:-1]
text = sep.join([str(i) for i in args])
if _MARKY_EXEC_APPEND and len(_MARKY_EXEC_TEXT) > 0:
_MARKY_EXEC_TEXT += text
else:
_MARKY_EXEC_TEXT += "\n" + text
_MARKY_EXEC_APPEND = exec_append_new
_marky_print_mark(text, end="" if _MARKY_EXEC_APPEND else "\n")
def _marky_mdtext_crop(arg, shift, crop, join):
global _MARKY_EXEC_TEXT
global _MARKY_EXEC_APPEND
if not type(arg) is str:
arg = str(arg)
arg = arg.split("\n")
if crop:
if len(arg[0].strip()) == 0:
arg = arg[1:]
if len(arg[-1].strip()) == 0:
arg = arg[:-1]
n = len(arg[0]) - len(arg[0].lstrip())
newtext = ""
for i in arg:
if crop and len(i[0:n].lstrip()) == 0:
i = i[n:]
newtext += join + shift + i
if join != "\n" and "\n" in newtext:
newtext = join.join(newtext.split("\n"))
_MARKY_EXEC_TEXT += newtext
def _marky_mdtext_ret(arg, shift, crop, join):
if not type(arg) is str:
arg = str(arg)
text = []
arg = arg.split("\n")
if crop:
if len(arg[0].strip()) == 0:
arg = arg[1:]
if len(arg[-1].strip()) == 0:
arg = arg[:-1]
n = len(arg[0]) - len(arg[0].lstrip())
newtext = ""
for i in arg:
if crop and len(i[0:n].lstrip()) == 0:
i = i[n:]
newtext += join + shift + i
if join != "\n" and "\n" in newtext:
newtext = join.join(newtext.split("\n"))
return newtext
########################################################################
class _marky_fmtcall:
def __init__(self, name, fmtc):
self.name = name
self.fmtc = fmtc
def __call__(self, *args, **kwargs):
text = "<<!HTML"
f = getattr(self.fmtc.html, self.name)
if callable(f):
v = f(*args, **kwargs)
if type(v) is str: text += v
elif type(f) is str:
text += f.format(*args, **kwargs)
text += "!>>"
text += "<<!PDF"
f = getattr(self.fmtc.pdf, self.name)
if callable(f):
v = f(*args, **kwargs)
if type(v) is str: text += v
elif type(f) is str:
text += f.format(*args, **kwargs)
text += "!>>"
return text
class _marky_fmtcode:
def __init__(self, pdf=None, html=None):
if not html is None: self.html = html
if not pdf is None: self.pdf = pdf
def __call__(self, *args, **kwargs):
text = "<<!HTML"
f = self.html
if callable(f):
v = f(*args, **kwargs)
if type(v) is str: text += v
elif type(f) is str:
text += f.format(*args, **kwargs)
text += "!>>"
text += "<<!PDF"
f = self.pdf
if callable(f):
v = f(*args, **kwargs)
if type(v) is str: text += v
elif type(f) is str:
text += f.format(*args, **kwargs)
text += "!>>"
return text
def __getattr__(self, name):
return _marky_fmtcall(name, self)
########################################################################
def _marky_rebrace(t):
t = t.replace("{{", "<<brace?")
t = t.replace("}}", "?brace>>")
t = t.replace("{", "{{")
t = t.replace("}", "}}")
t = t.replace("<<brace?", "{")
t = t.replace("?brace>>", "}")
return t
def _marky_code_text(t, fstring=True):
if fstring:
if not '"""' in t and not t.endswith('"'):
return '___(rf"""' + _marky_rebrace(t) + '""", ___); '
elif not "'''" in t and not t.endswith("'"):
return "___(rf'''" + _marky_rebrace(t) + "''', ___); "
else:
print("# ERROR", "python code contains \"\"\" as well as '''.")
sys.exit(1)
else:
if not '"""' in t and not t.endswith('"'):
return '___(r"""' + t + '""", ___); '
elif not "'''" in t and not t.endswith("'"):
return "___(r'''" + t + "''', ___); "
else:
print("# ERROR", "python code contains \"\"\" as well as '''.")
sys.exit(1)
def _marky_paste_code(t):
global _MARKY_PASTE_CODE
if t.startswith("!"):
t = t[1:]
_MARKY_PASTE_CODE.append(t)
return t
def _marky_meta_merge(old, front):
global _MARKY_EXEC_GLOBALS
meta = {}
meta.update(old)
try:
for k, v in front.items():
x = k.split("--")
if "--" in k and x[-1] in _MARKY_FORMAT:
if k in meta:
if type(v) is list:
_marky_print_mesg("field link, merge yaml list %s" % k)
meta[k].extend(v)
if type(v) is dict:
_marky_print_mesg("field link, merge yaml dict %s" % k)
meta[k].update(v)
if type(v) is str:
_marky_print_mesg("field link, merge yaml str %s" % k)
meta[k] += " " + v
else:
_marky_print_mesg("field exists, skip yaml %s %s" % (str(type(v)), k))
else:
_marky_print_mesg("field link, set yaml %s" % k)
meta[k] = v
else:
if k in meta:
_marky_print_mesg("field exists, skip yaml %s" % k)
else:
meta[k] = v
k = k.replace("-", "_")
if k in _MARKY_EXEC_GLOBALS:
_marky_print_mesg("field exists, skip local %s" % k)
else:
_MARKY_EXEC_GLOBALS[k] = v
except Exception as ex:
print("# META MERGE ERROR", type(ex), str(ex))
sys.exit(1)
return meta
def _marky_run(fname, inbase, run=True):
global _MARKY_EXEC_GLOBALS
global _MARKY_META_DICT
global _MARKY_INCLUDE_LIST
_MARKY_INCLUDE_LIST.append(fname)
_marky_print_mesg("run %s" % fname)
with open(fname, "r") as h:
front, t, meta_lines = _marky_front_split(h.read())
_MARKY_META_DICT = _marky_meta_merge(_MARKY_META_DICT, front)
p = 0
r = "\n"*(meta_lines-1)
while True:
p0 = t.find("<?", p)
p1 = t.find("?>", p)
if p0 > -1:
if p1 < p0:
print(t[max(0, p0-250):p0+2])
print("# ERROR", "?> before <?", r"... (can use <\? and ?\> for escaping)")
if "<<!?" in t:
print("# there is <<!? in text, did you mean: <?!")
sys.exit(1)
if p0 > 0: r += _marky_code_text(t[p:p0])
p1 = t.find("?>", p0)
if p1 > -1: