From 016bcdb8a88ba2397523cb009c199be8de9718f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Fri, 8 May 2015 08:53:56 +0200 Subject: [PATCH 1/6] Fix indentation --- tools/sky/serialdump.c | 419 ++++++++++++++++++++--------------------- 1 file changed, 209 insertions(+), 210 deletions(-) diff --git a/tools/sky/serialdump.c b/tools/sky/serialdump.c index ce6c2ae32..1174dbbec 100644 --- a/tools/sky/serialdump.c +++ b/tools/sky/serialdump.c @@ -15,26 +15,26 @@ #define MODEMDEVICE "/dev/com1" #endif /* linux */ -#define SLIP_END 0300 -#define SLIP_ESC 0333 -#define SLIP_ESC_END 0334 -#define SLIP_ESC_ESC 0335 +#define SLIP_END 0300 +#define SLIP_ESC 0333 +#define SLIP_ESC_END 0334 +#define SLIP_ESC_ESC 0335 -#define CSNA_INIT 0x01 +#define CSNA_INIT 0x01 -#define BUFSIZE 40 -#define HCOLS 20 -#define ICOLS 18 +#define BUFSIZE 40 +#define HCOLS 20 +#define ICOLS 18 -#define MODE_START_DATE 0 -#define MODE_DATE 1 -#define MODE_START_TEXT 2 -#define MODE_TEXT 3 -#define MODE_INT 4 -#define MODE_HEX 5 -#define MODE_SLIP_AUTO 6 -#define MODE_SLIP 7 -#define MODE_SLIP_HIDE 8 +#define MODE_START_DATE 0 +#define MODE_DATE 1 +#define MODE_START_TEXT 2 +#define MODE_TEXT 3 +#define MODE_INT 4 +#define MODE_HEX 5 +#define MODE_SLIP_AUTO 6 +#define MODE_SLIP 7 +#define MODE_SLIP_HIDE 8 static unsigned char rxbuf[2048]; @@ -80,7 +80,8 @@ print_hex_line(unsigned char *prefix, unsigned char *outbuf, int index) } } -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct termios options; fd_set mask, smask; @@ -95,100 +96,100 @@ int main(int argc, char **argv) unsigned char lastc = '\0'; int index = 1; - while (index < argc) { - if (argv[index][0] == '-') { + while(index < argc) { + if(argv[index][0] == '-') { switch(argv[index][1]) { - case 'b': - /* set speed */ - if (strcmp(&argv[index][2], "38400") == 0) { - speed = B38400; - speedname = "38400"; - } else if (strcmp(&argv[index][2], "19200") == 0) { - speed = B19200; - speedname = "19200"; - } else if (strcmp(&argv[index][2], "57600") == 0) { - speed = B57600; - speedname = "57600"; - } else if (strcmp(&argv[index][2], "115200") == 0) { - speed = B115200; - speedname = "115200"; - } else { - fprintf(stderr, "unsupported speed: %s\n", &argv[index][2]); - return usage(1); - } - break; - case 'x': - mode = MODE_HEX; - break; - case 'i': - mode = MODE_INT; - break; - case 's': - switch(argv[index][2]) { - case 'n': - mode = MODE_SLIP_HIDE; - break; - case 'o': - mode = MODE_SLIP; - break; - default: - mode = MODE_SLIP_AUTO; - break; - } - break; - case 'T': - if(strlen(&argv[index][2]) == 0) { - timeformat = "%Y-%m-%d %H:%M:%S"; - } else { - timeformat = &argv[index][2]; - } - mode = MODE_START_DATE; - break; - case 'h': - return usage(0); - default: - fprintf(stderr, "unknown option '%c'\n", argv[index][1]); - return usage(1); + case 'b': + /* set speed */ + if(strcmp(&argv[index][2], "38400") == 0) { + speed = B38400; + speedname = "38400"; + } else if(strcmp(&argv[index][2], "19200") == 0) { + speed = B19200; + speedname = "19200"; + } else if(strcmp(&argv[index][2], "57600") == 0) { + speed = B57600; + speedname = "57600"; + } else if(strcmp(&argv[index][2], "115200") == 0) { + speed = B115200; + speedname = "115200"; + } else { + fprintf(stderr, "unsupported speed: %s\n", &argv[index][2]); + return usage(1); + } + break; + case 'x': + mode = MODE_HEX; + break; + case 'i': + mode = MODE_INT; + break; + case 's': + switch(argv[index][2]) { + case 'n': + mode = MODE_SLIP_HIDE; + break; + case 'o': + mode = MODE_SLIP; + break; + default: + mode = MODE_SLIP_AUTO; + break; + } + break; + case 'T': + if(strlen(&argv[index][2]) == 0) { + timeformat = "%Y-%m-%d %H:%M:%S"; + } else { + timeformat = &argv[index][2]; + } + mode = MODE_START_DATE; + break; + case 'h': + return usage(0); + default: + fprintf(stderr, "unknown option '%c'\n", argv[index][1]); + return usage(1); } index++; } else { device = argv[index++]; - if (index < argc) { - fprintf(stderr, "too many arguments\n"); - return usage(1); + if(index < argc) { + fprintf(stderr, "too many arguments\n"); + return usage(1); } } } fprintf(stderr, "connecting to %s (%s)", device, speedname); #ifndef __APPLE__ - fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC ); + fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC); #else fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC ); #endif - if (fd <0) { + if(fd < 0) { fprintf(stderr, "\n"); perror(device); exit(-1); } fprintf(stderr, " [OK]\n"); - if (fcntl(fd, F_SETFL, 0) < 0) { + if(fcntl(fd, F_SETFL, 0) < 0) { perror("could not set fcntl"); exit(-1); } - if (tcgetattr(fd, &options) < 0) { + if(tcgetattr(fd, &options) < 0) { perror("could not get options"); exit(-1); } -/* fprintf(stderr, "serial options set\n"); */ + /* fprintf(stderr, "serial options set\n"); */ cfsetispeed(&options, speed); cfsetospeed(&options, speed); /* Enable the receiver and set local mode */ options.c_cflag |= (CLOCAL | CREAD); /* Mask the character size bits and turn off (odd) parity */ - options.c_cflag &= ~(CSIZE|PARENB|PARODD); + options.c_cflag &= ~(CSIZE | PARENB | PARODD); /* Select 8 data bits */ options.c_cflag |= CS8; @@ -197,30 +198,29 @@ int main(int argc, char **argv) /* Raw output */ options.c_oflag &= ~OPOST; - if (tcsetattr(fd, TCSANOW, &options) < 0) { + if(tcsetattr(fd, TCSANOW, &options) < 0) { perror("could not set options"); exit(-1); } /* Make read() return immediately */ -/* if (fcntl(fd, F_SETFL, FNDELAY) < 0) { */ -/* perror("\ncould not set fcntl"); */ -/* exit(-1); */ -/* } */ + /* if (fcntl(fd, F_SETFL, FNDELAY) < 0) { */ + /* perror("\ncould not set fcntl"); */ + /* exit(-1); */ + /* } */ FD_ZERO(&mask); FD_SET(fd, &mask); FD_SET(fileno(stdin), &mask); index = 0; - for (;;) { + for(;;) { smask = mask; - nfound = select(FD_SETSIZE, &smask, (fd_set *) 0, (fd_set *) 0, - (struct timeval *) 0); + nfound = select(FD_SETSIZE, &smask, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0); if(nfound < 0) { - if (errno == EINTR) { - fprintf(stderr, "interrupted system call\n"); - continue; + if(errno == EINTR) { + fprintf(stderr, "interrupted system call\n"); + continue; } /* something is very wrong! */ perror("select"); @@ -230,143 +230,142 @@ int main(int argc, char **argv) if(FD_ISSET(fileno(stdin), &smask)) { /* data from standard in */ int n = read(fileno(stdin), buf, sizeof(buf)); - if (n < 0) { - perror("could not read"); - exit(-1); - } else if (n > 0) { - /* because commands might need parameters, lines needs to be - separated which means the terminating LF must be sent */ -/* while(n > 0 && buf[n - 1] < 32) { */ -/* n--; */ -/* } */ - if(n > 0) { - int i; - /* fprintf(stderr, "SEND %d bytes\n", n);*/ - /* write slowly */ - for (i = 0; i < n; i++) { - if (write(fd, &buf[i], 1) <= 0) { - perror("write"); - exit(1); - } else { - fflush(NULL); - usleep(6000); - } - } - } + if(n < 0) { + perror("could not read"); + exit(-1); + } else if(n > 0) { + /* because commands might need parameters, lines needs to be + separated which means the terminating LF must be sent */ + /* while(n > 0 && buf[n - 1] < 32) { */ + /* n--; */ + /* } */ + if(n > 0) { + int i; + /* fprintf(stderr, "SEND %d bytes\n", n);*/ + /* write slowly */ + for(i = 0; i < n; i++) { + if(write(fd, &buf[i], 1) <= 0) { + perror("write"); + exit(1); + } else { + fflush(NULL); + usleep(6000); + } + } + } } else { - /* End of input, exit. */ - exit(0); + /* End of input, exit. */ + exit(0); } } if(FD_ISSET(fd, &smask)) { int i, j, n = read(fd, buf, sizeof(buf)); - if (n < 0) { - perror("could not read"); - exit(-1); + if(n < 0) { + perror("could not read"); + exit(-1); } for(i = 0; i < n; i++) { - switch(mode) { - case MODE_START_TEXT: - case MODE_TEXT: - printf("%c", buf[i]); - break; - case MODE_START_DATE: { - time_t t; - t = time(&t); - strftime(outbuf, HCOLS, timeformat, localtime(&t)); - printf("%s|", outbuf); - mode = MODE_DATE; - } - /* continue into the MODE_DATE */ - case MODE_DATE: - printf("%c", buf[i]); - if(buf[i] == '\n') { - mode = MODE_START_DATE; - } - break; - case MODE_INT: - printf("%03d ", buf[i]); - if(++index >= ICOLS) { - index = 0; - printf("\n"); - } - break; - case MODE_HEX: - rxbuf[index++] = buf[i]; - if(index >= HCOLS) { - print_hex_line("", rxbuf, index); - index = 0; - printf("\n"); - } - break; + switch(mode) { + case MODE_START_TEXT: + case MODE_TEXT: + printf("%c", buf[i]); + break; + case MODE_START_DATE: { + time_t t; + t = time(&t); + strftime(outbuf, HCOLS, timeformat, localtime(&t)); + printf("%s|", outbuf); + mode = MODE_DATE; + } + /* continue into the MODE_DATE */ + case MODE_DATE: + printf("%c", buf[i]); + if(buf[i] == '\n') { + mode = MODE_START_DATE; + } + break; + case MODE_INT: + printf("%03d ", buf[i]); + if(++index >= ICOLS) { + index = 0; + printf("\n"); + } + break; + case MODE_HEX: + rxbuf[index++] = buf[i]; + if(index >= HCOLS) { + print_hex_line("", rxbuf, index); + index = 0; + printf("\n"); + } + break; - case MODE_SLIP_AUTO: - case MODE_SLIP_HIDE: - if(!flags && (buf[i] != SLIP_END)) { - /* Not a SLIP packet? */ - printf("%c", buf[i]); - break; - } - /* continue to slip only mode */ - case MODE_SLIP: - switch(buf[i]) { - case SLIP_ESC: - lastc = SLIP_ESC; - break; + case MODE_SLIP_AUTO: + case MODE_SLIP_HIDE: + if(!flags && (buf[i] != SLIP_END)) { + /* Not a SLIP packet? */ + printf("%c", buf[i]); + break; + } + /* continue to slip only mode */ + case MODE_SLIP: + switch(buf[i]) { + case SLIP_ESC: + lastc = SLIP_ESC; + break; - case SLIP_END: - if(index > 0) { - if(flags != 2 && mode != MODE_SLIP_HIDE) { - /* not overflowed: show packet */ - print_hex_line("SLIP: ", rxbuf, - index > HCOLS ? HCOLS : index); - printf("\n"); - } - lastc = '\0'; - index = 0; - flags = 0; - } else { - flags = !flags; - } - break; + case SLIP_END: + if(index > 0) { + if(flags != 2 && mode != MODE_SLIP_HIDE) { + /* not overflowed: show packet */ + print_hex_line("SLIP: ", rxbuf, index > HCOLS ? HCOLS : index); + printf("\n"); + } + lastc = '\0'; + index = 0; + flags = 0; + } else { + flags = !flags; + } + break; - default: - if(lastc == SLIP_ESC) { - lastc = '\0'; + default: + if(lastc == SLIP_ESC) { + lastc = '\0'; - /* Previous read byte was an escape byte, so this byte will be - interpreted differently from others. */ - switch(buf[i]) { - case SLIP_ESC_END: - buf[i] = SLIP_END; - break; - case SLIP_ESC_ESC: - buf[i] = SLIP_ESC; - break; - } - } + /* Previous read byte was an escape byte, so this byte will be + interpreted differently from others. */ + switch(buf[i]) { + case SLIP_ESC_END: + buf[i] = SLIP_END; + break; + case SLIP_ESC_ESC: + buf[i] = SLIP_ESC; + break; + } + } - rxbuf[index++] = buf[i]; - if(index >= sizeof(rxbuf)) { - fprintf(stderr, "**** slip overflow\n"); - index = 0; - flags = 2; - } - break; - } - break; - } + rxbuf[index++] = buf[i]; + if(index >= sizeof(rxbuf)) { + fprintf(stderr, "**** slip overflow\n"); + index = 0; + flags = 2; + } + break; + } + break; + } } /* after processing for some output modes */ if(index > 0) { - switch(mode) { - case MODE_HEX: - print_hex_line("", rxbuf, index); - break; - } + switch(mode) { + case MODE_HEX: + print_hex_line("", rxbuf, index); + break; + } } fflush(stdout); } From d26afef966dc0ec0cfe53d639c01b5bfbc8c61ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Tue, 5 May 2015 18:14:35 +0200 Subject: [PATCH 2/6] Fix serialdump.c _GNU_SOURCE is needed for O_DIRECT time.h is needed for strftime --- tools/sky/serialdump.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/sky/serialdump.c b/tools/sky/serialdump.c index 1174dbbec..4a0573b9d 100644 --- a/tools/sky/serialdump.c +++ b/tools/sky/serialdump.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include #include @@ -6,6 +7,7 @@ #include #include #include +#include #define BAUDRATE B57600 #define BAUDRATE_S "57600" From 425c58e79dca67d380048b08c1b884543d6887cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Fri, 8 May 2015 08:55:31 +0200 Subject: [PATCH 3/6] Set default speed to 115200 --- tools/sky/serialdump.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/sky/serialdump.c b/tools/sky/serialdump.c index 4a0573b9d..447999026 100644 --- a/tools/sky/serialdump.c +++ b/tools/sky/serialdump.c @@ -9,8 +9,8 @@ #include #include -#define BAUDRATE B57600 -#define BAUDRATE_S "57600" +#define BAUDRATE B115200 +#define BAUDRATE_S "115200" #ifdef linux #define MODEMDEVICE "/dev/ttyS0" #else From 1e359d232451f19d668359ff5da79e3db021e99d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Fri, 8 May 2015 09:14:40 +0200 Subject: [PATCH 4/6] Improve O_SYNC logic --- tools/sky/serialdump.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/sky/serialdump.c b/tools/sky/serialdump.c index 447999026..d0e7fac3c 100644 --- a/tools/sky/serialdump.c +++ b/tools/sky/serialdump.c @@ -164,8 +164,11 @@ main(int argc, char **argv) } fprintf(stderr, "connecting to %s (%s)", device, speedname); -#ifndef __APPLE__ +#ifdef O_SYNC fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC); + if(fd < 0 && errno == EINVAL){ // O_SYNC not supported (e.g. raspberian) + fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT); + } #else fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC ); #endif From 16f7c2448cc1d2eb5c90e90169169636a9d8fff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Fri, 8 May 2015 09:15:21 +0200 Subject: [PATCH 5/6] Improve error message --- tools/sky/serialdump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sky/serialdump.c b/tools/sky/serialdump.c index d0e7fac3c..e3e47092b 100644 --- a/tools/sky/serialdump.c +++ b/tools/sky/serialdump.c @@ -174,7 +174,7 @@ main(int argc, char **argv) #endif if(fd < 0) { fprintf(stderr, "\n"); - perror(device); + perror("open"); exit(-1); } fprintf(stderr, " [OK]\n"); From 23d625058434dafd545f1c4a3171804b879ccbc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20=27Morty=27=20Str=C3=BCbe?= Date: Fri, 8 May 2015 09:21:19 +0200 Subject: [PATCH 6/6] Turn on optimization --- tools/sky/Makefile | 2 +- tools/sky/serialdump-linux | Bin 14922 -> 14748 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/sky/Makefile b/tools/sky/Makefile index 0b1fa08db..be3caa44b 100644 --- a/tools/sky/Makefile +++ b/tools/sky/Makefile @@ -22,4 +22,4 @@ endif all: $(SERIALDUMP) $(SERIALDUMP): serialdump.c - $(CC) -o $@ $< + $(CC) -O2 -o $@ $< diff --git a/tools/sky/serialdump-linux b/tools/sky/serialdump-linux index 8c7af779d6833ab75857ae8d2a59688e0d68cfab..8bb8192c282daa79e093d45bfdc0da9fdf59bb5b 100755 GIT binary patch literal 14748 zcmeHOeQ;aVmA{hn;TR%00fO^E^N3~Yz}naWvW{^;FR_wmYJ!{C5FkO4^^vH^l2&?7 zoDztGY$h7Vsdr1eOv|*{-EJpa*lD(fGIuQ z-D^K7)^@uyo!LM3di2gczkANP=YF00eBXOJT+OSj77LTf%5GuA?YhFrA>+zeorALi zt7FB?$riE&Y#NZM_&IqAQ6nemkT5N2v5+eQokDr50IW_UBj^HyLk&if9ulScCX!QR z4eI}b!Ai=Q!U57FUj+;5A#R+G2|tue3|I;hOnPOCftLwANk_>rlBBYI)HeDp5Ox<> zo#2Rf5@C(}Izf3~0Bdhdc1w2{Erdo=k?)G`_db) z5Bsaap-5*}Raf28s--tpC!*C$xc{XvL`_`1rj47F{V@+5)qOdBG?rBU)IC3X@!I)+ z|Aedc(w%GSLm&Qxb#0%8vV}qhgwgQO_>t}m{4T{$c6k}{WcLdED9y!>?9V2qKoZ@{ zu0pxF{Ut(P3=gw`pD8dqD0MHj?K1qRFUU_ySK>DZzv;w?G#`}ONIGPX*JDvwx24od z7}ZT_@m0GQ1lzo&%RcNQc+#{4=w$8rK>>V20lcaJeyjlg-2(W_1@NZ};K>5`)<N z3g9OS;7=96soxd+^3#_9OxB+R1@QU;IL*7s?5r+;KVJavD1iTC0lcLEeoX=V>H_$8 z3gCZR0N)OL7Ol2&4|2vDAgba=cyYN0xd}XlJmIC~9^@u)=5}xDh(_EA-5b~4ZiaB; zqv)}e1%u(v#AX)g3h68sh{vOG7VFd#bn$KW##tf|4)}DI(EXtZuJNEA>Ig7jFcHv0 ziC7@uhiRxqqV90i=hZ{e2-AHi^y+$?#RFbHsYW|>79@+rK$-I?%`RArRHEG z$Bl3qmq<{K8{uM$B$$;g@^DJ=&cbuXMKR$r#!^Y838$DSQ;i9idlHq^nQ*FGCZ`GK z@l+IOCfpo@TTHmzyGUid2}j3`Cyxo2djS=0HsNyLAv|WnX-|@=%Y@7QgUY&1IPE7g z?K0tVOsQBgMmvWp8@;N`+-BdT_NbbRtLm zW)jbgW|1nsO1y>m5zfbnrzx2k;`~>Lr>U6P&-r%ZX$ofca{eCTY3gMLIKP&7nsS+L z&fi8nO|?vn^DBs_DVFhYzMgoRTA3EkFCm_$RL05qYl)|+l&RtTBI0QZWfacOBc7&C zrj+xuiKnHUVVo}^o~BUd%;x|qti;pQ$&7OT{2cH!Wilh2|B!f^Dw!e9pCq29NM=9h z-z1)ffoGcLIhp!`6--m#UpTrS zWL5T_XE0`J|0;{R>?Qlx&S3zwzU2?0E-iKP&>-Y%htfYpg|$P6taq0J{X?4ivv){M z9kcK1k@8OJ3>Vuc4N%hg9urP@_4}nEE80`Ha-;yL#ZE*8h}aK;ZuZ>xAFK z@#h8pe)^}twSE&1{k|T@W7MMlN4Z$-IT%iU&+$00w?Q8T{k-Cp3)$?<{jioYq|mg?c6T7RR%OExQm)%JxwP$qABxSP~bEpX3OJ5>AA+Sdl@hFwFu2qT#j zBny7M;70}T5qw(kv~o%QjNoH}9}|3+;A!(Ad)sTVOmhfmJ4j3h^IT|A=M|KX_p;lJWmnjK|YUn9o0x94S&xA*Mi z^Gpu1T5UUQQe?!RPR&W!}bHOWgWjb4m;0LU{;gIEKS%BT+2SU_r3w= zUeIAD^B!`j$J!9F_q>cgYlzw(9Zn8UJN3$Qw6sqhug#`^4*gT#(UM24hwg+9MTxJV zatv0F29-lC0&ElDN&+_s&?&&55J(}4)UPwZ-X8%p#jVU;2rJzWS}_d2qhUaewQp#t zu%k4y93>b8WBs5TU917s`_SZuH|#xMqR!jyup>)n9ZkM}Qdp&U1chA>E9D+$ zf8?)e==)~wn1yggq1*^(o6tct2(H?<)jHFXu4M}eY6!^Hidf(P(bbmV4-m{d? zj^)?EM*6^iX0w@EOuzwGZ`R(s2_EwCb#`ar+Ho@V^)ZOdg&AZ1ptuu5H+T=~BnQ)P zpeMvx?A{fewIgLnDvyMkX&@wrha5aL*4> z*qC~E@CWGT^j3`DsVBMr>Fc1Hteax*y^8xk^MO+IK^ZI?eQ-7WNpGU&v|~C12X-N@ zW!fj|NBiwPgAm6AwfFujGVqcIKUZxwvkZb_ee^A#3(M*4s7~vbi!Ak0dOp=Z#?;hN z`)(^-u=lLQwf6L>MclvIECwJQgwSB@N_5+M$f+2CJ@x2at-lqE(DyOcs%H7+vlwZX z?)wCI@6e88gDvFxZqnohe}i0bpy4YrgQqoQL5RjTK8Y7xABgY+*U88}H_i3p&wdC7pT3VZ48e(Nm+(8{K<>aNBOQEyl z<81cqzyRGtYkgCfU5bYG4(ZnH2)~(zm4ShS*+m}Krd5rBXvr~~mU?Hab>r|sbT=11 zyK#_;vZG@C9wbi6A08`$yoQ^L!zXXmEF)U#nD*-DozQ>Q(0@&r`fm#T?&Yt-4c0lU z4VvkP(0v<^O+5t2^3gEe&uhu$`({8upFi%xthT{Y1>U9J$&PHyJOGu<7F@Xd1M5;j)8%K;Q)ehQmvRdAnVoWFbCH`$IVa^l{Rp{k%6&k&eU$q>j6F9&w&b;v_-6}kL40Ib~0cGNYd-a2)~fWS$A zCyJ7vUT*0B-q8Q-L+HN&efYw?cu0j8&r#Ld&ZAd@oGRmSX|NjAaW{Sj6>_7@e&FW* z)o(UdgJr=^qUTDNWq}VM{yFobo$Hwf?H#PgihH zUvYv6@N{!ZcbsWXZFh`msSOUyy7%gu7r&#XK5I&y(++=D)Rg*FdOlU#ds<&mi)J{X zcfL7=yX8Nq*~@=Je!zERK@zXTB$wcF-cCK*fiozdvaY$QMd^t8 z142;ROGLRKFOEjS+qjHU=?#Y!zgPDvp@g9t^ZM=&=!wM_)e}+lsIoca4@}6RrHOpG z)_dVMT-iwCUcX!AZV!PqtT4DieW#(&3FLF_`5F^31JrF=q|C zia(I>#X~VVZzCsV`$AkMudilSBv?hwlJ$^cwY4`bsi|SL%jkMT-Ho{3^p{I0Y zqNA$9uT*ID6}Q({tYg>v16!`w^=<2FSZ5^B8H+{Zdcd#ngSUF6B2fbP{z!CdM2T`g zlrL8JzF5NaXp|bTP4UJzb#??IIs|>uNCc;dp~xockBWp+S%JRg=Y7h(cYJ9hNpyz& zN+had&ghCb=o`my04OR+B^ zj*hv(uP~Yr^$NQdNlAo5F(tYs5D$i|Im`T_n;X#MbZ9VeI-6Y&>ik1CI|{lN zx0&6b40qXkK}vD2K>s%?bYlTZiT;P8Wclh^X6Y)m%)fMc@c_ykz~~&d1~&JTtgUpF zt?V}YC0mQT*{$<#zV-&kBA{HR5wr|--9>Q&d}Ja%!Wk#yVPJt5j`@YAb`p3R|&ioMtvd<$I+6em2`ir&cKan$=}1 z+f%f{ru0u)VXNFdRkhVTGEKGBC8w{p4NNJzW=e^z4j61hW<`!gYVTS6PQV`{0)s)K z_FfAAMu4XX`10Q2)IWv5|4;wdd%!ct$z5~`D*dIYM+rC9JjpZh zSc#MKGYyzMjyp6;bNLk)+}Tl@-iRMXOl+#+FB&IzbFY)BDIywFL^K6tdl|=@R z|MPirPBVB~zm(RCa(Tx8nE~fKQzpoKCQdy5XEM?v52tc&$3%waJth2;&J+IkGg7gW zQ;F}LZt$`l9$soZ+oo)p;PH<(Z%?<7$GsQlWj~)0{4JtfsQuZAe2*c&qHl_E{=T3G z1U)9`F9m&9&~t)LyTr*&%@On(L6-`;O3*t64GOwN&_@LQrl8*!^njqp1pTF;?+SWO z&}sNTiP9WFuMw1krpxM;E9;fY#z1=rw?sEq|7G=(s+$%Y8J1Uu(yAp?h74oXiESOa zw;fcE8+5bG@mqx$tH#YnpjutgRHb`232sxQv%0-Agx4%WepXG~W-lI&R{OU_V9%g< ztjSAogOH%7oo2?3vUniuB?Xa-g>_aPis0#LHQn{G>L3`DMd^N%RR=b^gK=+1z`fZI zUC9|5Zf`v9-DYUW{8xMsgLQ95$cL(3z)4zhIV|ZFXP~P zp`R87)JE!OS-*@&cLF0(sW0QIQv_BSMIMF`3`E#)M= zALSGiB`@P*x6oIFe!l+#W?w~y`cmr4IJ{TrdxW5@KfnDwdHPJmb=gsJA0U0&>+<#Y z0HZ#U_T|196C05YW#%NuU1BL@%=+CWPF~b4^!Yuc6b6<1u%wRyGwaj&5TzQiQHSM* z&Cv;c!Ln~5W7e1Z_~T-N%#ebD=KH@_=*#}!C+-9G34JY3LH3_CyDv{)zTYO_duxz_ zg65fH2lDi5u5xn8nyUw-olwbc4%4m$la$)kmg((1$^5ygSmmy=vPwE#d9&pf8 zIQgUcCm=>HN_{#Jql7bRp7QI<=YI<+ntM`T?&D<&S08^LQ7ngXf8_jm7h>l6<$ES$ zR~!2I^+{gRQ+fJqk;hP6WRSE$#;;OO(z7Tr*Pj;pX`wIulm?`pXT@pmUDtAFf9L;rhu3nssQQOl&Hh`h5pFDffSw3Yj;xv&U5A@|Q* zda=li8WeK)1RGcIr@>IKVFFRmn?|Nr*4fs;RF-_t z{^D_b6*$?E|G$$CCE6D(lgx)g?Yh9_XEVWf_d;`u}8 zXZ$Vey!p10%U?Wy?gl;^?V_h&lw^zyahyXrmxl`A-zb3p7`T#S!C+niKH2-QZ*lpH z=kxo(XHQ~>9G>j`*~@@WCVx!Qak%yW7?XHL!n@^^Fm;yB|jAfG6JKT-gHtN{KK z;H5bI$zShB3do-*fS(4gm>Vkc7l6;Q&Shuv`e8;9_47phl-pey@X7l5+5-431@N^T zw=sJBN{Q~*DYX}n-vXS*OS#U&<>ci7VMl&XBk_lYeE#_E5%O{$;b*u|`Z~v@_5}T> z0{Bn?{8t6=Oaa`Aj-9MO=KxnG+!)VYTR^^{0Nw(e#y7toHWaYGh1w5}B|!Q)Nzz@`wM6~*0phuas9M(`kS63FfLN8Ovk z(ROdx?boC6gxlNMh38Nmv2Xy-o2r-AEL#H0lL)!#u*W#MapO29zKt1&J$NG8u?;FF z&P``TIiha&s6!-L#H{@Fn;#Gei3Li}l7F60jI(=h&>g7K|DUO7L8Grlm$E#coO z%<`6mkW`w+*>q-ZvVUQHiK~vp3>L&$*lKKquiF40mS&-(1k+ zhbJf-sJo4{oL>Oe($~C`(y6C@4mZy>sC7)4q-W`a0#L#_qshT@DpouT^2ly-|oLj?~0@hJ=q!!q*8iH`2Aho@t8kl1d@i|FVOXa z?D7jm$_T~NhDfKPx}Ff-dUr6mC*H& zxFZ=cbkUheMq);%;=~mPN+U6m)B_qf)$AsP!L5`8A9*YbA+Vv}Ex}1IQ+x&|{)A7&D^C0;Q8#T(@rR z%2xk8Z!-`yJv#-!qMj{w~PEke?xYsc+O~HU>e=Ea4XFn^$z+?NC zVRASD{#3}Gqz{Fs=wq;+rjHIfLZ1@_he*vW`9mdINoQmTTx^0%)d>NvVZCI?N*a7o#uJ$0V_wJ|?GC^k)mPG51F1 zgs1q=D0MjzEVMA z);!EmMrNV27H%Ls2 zg*Ol{mzb6d-$L9hF)bM0MyyFpONLpYQl-SSXgEPEB&KDTbxw-T6dbhR^My>YJ(q2OfiegAtgE;;hvMY#C&;_+Kl%`Q z#*kfMrr^wF>%bk%YIr`%5@ly2#3jl|{wcEZ2g%A0F#64JRy_DZ#TN^?A2%Gz9YKz0 z&snG#<|9^&=}WgUOIx939yLfjn61Y1TQZMIgv>n1${!>vKfvhs%7ZI6jB>}Obf$n?b>p_=TtNzm-sw=*X*YeX}~wB&|Oz-wkbRgW10s1EEK9V6??u2 zyQ-tl}dV*+rWK>}0o zVWxH0@rSF(`i+(Ga#MDXQVvU@ry~=tne)B_R8tH2Y@xRX>92xx@zXY43&0!58c@p_ z)J(8^Ji%fn&}<3Z;N^W!Qrb+197Z8dpL8KZh^Cl`hocYz|V==1` zbEsHW@%69D+%X^TDpc(HEs8ZJQp-dypwu3$GsQr5n^{Ws;RVp1^9^PChJ@@;_b_{* zvPXN37LOxLZpGdQkXVKGAY=`WAzFtW^nTU^8ee^jwmc3IF}yYJJDz(%<>)xd60l0N zklEUu5Y86vVpskL=6nwmn-#xZm4b?jdsY1FSdbU5KzP7+TrLNWFYyiC`S-HvGyiot zd})gN?51dB+n!Z-GyjD&jqhZp@1(8z4wad#{u>PYiY!E_0zb7CPp1cSPqjd2<{+P* zihKXS-#7{K?t`H(tDn_k#nZdWXy{4Hg^kcxDj>x`b`7}fnXFGvqVc$`r`QA6Q9{l= zTn|Yrvju78pHm=f3b4ODM)SRmSj@UuC%sqxKZS&iyL4Jbb{YHy*QPvit6S48pOrvnuxf05acy5=k)K zS~a5#YxcafxEza?UX6P5NR#P%MWpB1R4*+USK8ntV;A2=6Fo(xE=XAjT`#=20g}gEOK@!l4cI_S-oT0poDChXP#o6 z?q@tE4B23^T4?3ppbl1jHlSSQ(hiAWMY-53eH&rcu;RV~E8=^l^dMsT`(Ax5eLck| z*J3%c*?Ex9*CA)jP~o35TrrIGckw0F1q;K|$H8mw-8QJ%GA>}YUpY2CJ%{?RkDmEG zhk>929*Uax6nKPs5w~C8V+x(VO`Sj_0-$?F+Dq9;iZ~J*RnmIjc zR6Wbk=+S)ZNM_iLnDm<&xtZH%?)k2kIlhf!0wgP52Bi4Vj5!4-8BVb=73k6zYbiY$ z2}DEb?u53vv1bb&sm<}&76u}GbhK^o`Bov+=DTU_igl}eo7T4ac#fqh*Vv_FOxcjLq-sI{$IyFu%Yhjd#Wskju9tavQi zEBRVOAR5&|0VAMAQYu*@5d4g8q~;*$SoW!yX2i8{B&3hapynyNO#5ck0oiY%Xdo2Q zcorqI)C0k=X6QYJhO=Q7$l<3Bcal%h4fS~8AmI zmG0JK29gHju^0~XBC#&kxjv;e)WdGmgtmG8r?!xtj)t^Y+&~90Gb(Bj+mWM?#f$29TS9=GT8`=A|vckXn*gsz*%^gQT?pkIJ~2RZ|qf%^|119?H$f^GzD1;s!+Kzl)713dwH9%SWF&it-x zZC$K2;F`c3ZN9g~yHIP`*pZGIX@wf+rX`w(h3Wf}Z1FaG=a1=>$kMrBqR#V|JpXcj zU^=DA@JbQ84?6ZPb?@W~8B&iHcup}L-9YgxcdLHL{>XmA{>grK0&P&IlE~*Zcsj*b z&Pw+-(y`zAkWS^R64gri&*J$7P%miG>t)1%@9edJGdwlmV>`6cmBZ!vsHfgDi*u%9 zrlWF76`u7oW=(g^_$b~YIqQUL#`Njeq6@na^r)b_1+j~#FPXk})+fuIm|n}S5^Fg- zO05$#A{QIJ88S{WkCKjeW?YD;gS`XfI7c59xM+b}AE>kJLS;@~`f?S7V}5PRvid7r zHQKFzQ+vg2o1M7q;J8w%zU*A8vAv5J-XK^)@DRxvX8AbyS-xem zM54^eS-|CW)Hc=L+J!ffsBD>&GlJ`K#4U4{sTd9v*EA)ytgET1d0B0()Uf*lFDyHd zy|A_8W#!D{s&ZI)qokaJTo*W0Sxg(I!r0bp9G>T8F8h4Ki6a`v4qiT}0_Oygt{4sp zg5f|?PAaYc#}CqY`mwZBq)Ig*YV!2xP4#vgfezutv4`@*RtOsOWI}jxexQ3-tX$h@ z1iFMb9Kfw1Z>Tqhgv!SSAa7SJ?Zsw3#mhc+;0G_MM=7rYiKrpGG@9`8Kt^~w0lu1TO5oTGrCg9A`i~!fCmb2=SK!hc? z26Ag4*KaYwqdwB-Y;v4VkDzgCcwNABl%d-Rvh;Bl8^WTQldI({)%PNTVb)jR*OwPK zchm5uv-Eu)*pl0gmq5F5snp_8)Czyul#?pBR@IcfC_`t-J%TXxQO*N7k9Kakf3(T* zwofJGEFEBtg};L^ZA^V!lUHl%z9`$5j%nC#Pl2p_d57+GZCnRfQjW6U2U&95V+?7y zTZcHyQHFFFWXY|;ng5#FiFa}-L-#U>`Lld{H_#3_jS;5PO#g@Qsn2qhyUG?}1%Czs zD@@t`D}>l>C4z6M{x!mOInR|s)Z64N-XAB)HA3#MWv5WWmK=W9Cg{5b%D8N`oF!K| zN$!V`d)8t?*b2@z<(f?exvPcvfu+opqb%2-w4LSFG~gbvr38^ykiM=SxOnK_GdY7Zp}HbN*9U<-mDPVU+>rGlf;} zwDz7Z*@M;mr1%)zaGZw}mY&?(D$H7_c|~FFlrjHe{!o}Rk=jNmTrM%^1BJQshU2)0 zbD1~BIldLJSty!Fk)uT8wrOwaq5bk;WyRlr=wFs=$O@M=u{ z7Kw518<^u))#nm%Eimt=S$Kmf&pDX(*#^vY41&Prq6=7FEjIBT!0l%FE7AWmz`S$Z zim8qA)>?(XbJX_@@U8hoL;pSiOlQ^S1z>CbtHKv8M@)VeGEDy;CSGmgVG~>J`HqRd zXY!|`V)pV?v7&IBK-4z}nA=LmRXNMWa^U`NE6n=%fO&_D$@tC4CIsx?Waz+FeJW9( zBn3^U!N14Ek0H$bzG7mlypKlh0grbJZ7`(1BK%fk60L2n)s zgyR0LXuKm3^~(*IKalPba%1MlC4=r>D+9dn9oKJx)i^l z97af+jDLAEF~!91dh9%YTV%)5Kx3Z-**WS9rAaYRY>(m94Lerf2iZ$W`vYU!Z}Q}~ zLuY+WWLLt20#jIh<78*5YRfwk_GtA1l|6=^C)qK-ZL(v(E)OJZA68A^`XdV$E%f5< ug+CGW8)01a@OJbF*&XFqQ4@qGe=23G!MQ#P8~Y;5u7p=J?0C|bWB&_iAMR-Y