/* * docproc is a simple preprocessor for the template files * used as placeholders for the kernel internal documentation. * docproc is used for documentation-frontend and * dependency-generator. * The two usages have in common that they require * some knowledge of the .tmpl syntax, therefore they * are kept together. * * documentation-frontend * Scans the template file and call kernel-doc for * all occurrences of ![EIF]file * Beforehand each referenced file are scanned for * any exported sympols "EXPORT_SYMBOL()" statements. * This is used to create proper -function and * -nofunction arguments in calls to kernel-doc. * Usage: docproc doc file.tmpl * * dependency-generator: * Scans the template file and list all files * referenced in a format recognized by make. * Usage: docproc depend file.tmpl * Writes dependency information to stdout * in the following format: * file.tmpl src.c src2.c * The filenames are obtained from the following constructs: * !Efilename * !Ifilename * !Dfilename * !Ffilename * */ #include #include #include #include #include #include #include #include /* exitstatus is used to keep track of any failing calls to kernel-doc, * but execution continues. */ int exitstatus = 0; typedef void DFL(char *); DFL *defaultline; typedef void FILEONLY(char * file); FILEONLY *internalfunctions; FILEONLY *externalfunctions; FILEONLY *symbolsonly; typedef void FILELINE(char * file, char * line); FILELINE * singlefunctions; FILELINE * entity_system; #define MAXLINESZ 2048 #define MAXFILES 250 #define KERNELDOCPATH "scripts/" #define KERNELDOC "kernel-doc" #define DOCBOOK "-docbook" #define FUNCTION "-function" #define NOFUNCTION "-nofunction" void usage (void) { fprintf(stderr, "Usage: docproc {doc|depend} file\n"); fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n"); fprintf(stderr, "doc: frontend when generating kernel documentation\n"); fprintf(stderr, "depend: generate list of files referenced within file\n"); } /* * Execute kernel-doc with parameters givin in svec */ void exec_kernel_doc(char **svec) { pid_t pid; int ret; char real_filename[PATH_MAX + 1]; /* Make sure output generated so far are flushed */ fflush(stdout); switch(pid=fork()) { case -1: perror("fork"); exit(1); case 0: memset(real_filename, 0, sizeof(real_filename)); strncat(real_filename, getenv("SRCTREE"), PATH_MAX); strncat(real_filename, KERNELDOCPATH KERNELDOC, PATH_MAX - strlen(real_filename)); execvp(real_filename, svec); fprintf(stderr, "exec "); perror(real_filename); exit(1); default: waitpid(pid, &ret ,0); } if (WIFEXITED(ret)) exitstatus |= WEXITSTATUS(ret); else exitstatus = 0xff; } /* Types used to create list of all exported symbols in a number of files */ struct symbols { char *name; }; struct symfile { char *filename; struct symbols *symbollist; int symbolcnt; }; struct symfile symfilelist[MAXFILES]; int symfilecnt = 0; void add_new_symbol(struct symfile *sym, char * symname) { sym->symbollist = realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *)); sym->symbollist[sym->symbolcnt++].name = strdup(symname); } /* Add a filename to the list */ struct symfile * add_new_file(char * filename) { symfilelist[symfilecnt++].filename = strdup(filename); return &symfilelist[symfilecnt - 1]; } /* Check if file already are present in the list */ struct symfile * filename_exist(char * filename) { int i; for (i=0; i < symfilecnt; i++) if (strcmp(symfilelist[i].filename, filename) == 0) return &symfilelist[i]; return NULL; } /* * List all files referenced within the template file. * Files are separated by tabs. */ void adddep(char * file) { printf("\t%s", file); } void adddep2(char * file, char * line) { line = line; adddep(file); } void noaction(char * line) { line = line; } void noaction2(char * file, char * line) { file = file; line = line; } /* Echo the line without further action */ void printline(char * line) { printf("%s", line); } /* * Find all symbols exported with EXPORT_SYMBOL and EXPORT_SYMBOL_GPL * in filename. * All symbols located are stored in symfilelist. */ void find_export_symbols(char * filename) { FILE * fp; struct symfile *sym; char line[MAXLINESZ]; if (filename_exist(filename) == NULL) { char real_filename[PATH_MAX + 1]; memset(real_filename, 0, sizeof(real_filename)); strncat(real_filename, getenv("SRCTREE"), PATH_MAX); strncat(real_filename, filename, PATH_MAX - strlen(real_filename)); sym = add_new_file(filename); fp = fopen(real_filename, "r"); if (fp == NULL) { fprintf(stderr, "docproc: "); perror(real_filename); exit(1); } while(fgets(line, MAXLINESZ, fp)) { char *p; char *e; if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) || ((p = strstr(line, "EXPORT_SYMBOL")) != 0)) { /* Skip EXPORT_SYMBOL{_GPL} */ while (isalnum(*p) || *p == '_') p++; /* Remove paranteses and additional ws */ while (isspace(*p)) p++; if (*p != '(') continue; /* Syntax error? */ else p++; while (isspace(*p)) p++; e = p; while (isalnum(*e) || *e == '_') e++; *e = '\0'; add_new_symbol(sym, p); } } fclose(fp); } } /* * Document all external or internal functions in a file. * Call kernel-doc with following parameters: * kernel-doc -docbook -nofunction function_name1 filename * function names are obtained from all the src files * by find_export_symbols. * intfunc uses -nofunction * extfunc uses -function */ void docfunctions(char * filename, char * type) { int i,j; int symcnt = 0; int idx = 0; char **vec; for (i=0; i <= symfilecnt; i++) symcnt += symfilelist[i].symbolcnt; vec = malloc((2 + 2 * symcnt + 2) * sizeof(char*)); if (vec == NULL) { perror("docproc: "); exit(1); } vec[idx++] = KERNELDOC; vec[idx++] = DOCBOOK; for (i=0; i < symfilecnt; i++) { struct symfile * sym = &symfilelist[i]; for (j=0; j < sym->symbolcnt; j++) { vec[idx++] = type; vec[idx++] = sym->symbollist[j].name; } } vec[idx++] = filename; vec[idx] = NULL; printf("\n", filename); exec_kernel_doc(vec); fflush(stdout); free(vec); } void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); } void extfunc(char * filename) { docfunctions(filename, FUNCTION); } /* * Document specific function(s) in a file. * Call kernel-doc with the following parameters: * kernel-doc -docbook -function function1 [-function function2] */ void singfunc(char * filename, char * line) { char *vec[200]; /* Enough for specific functions */ int i, idx = 0; int startofsym = 1; vec[idx++] = KERNELDOC; vec[idx++] = DOCBOOK; /* Split line up in individual parameters preceeded by FUNCTION */ for (i=0; line[i]; i++) { if (isspace(line[i])) { line[i] = '\0'; startofsym = 1; continue; } if (startofsym) { startofsym = 0; vec[idx++] = FUNCTION; vec[idx++] = &line[i]; } } vec[idx++] = filename; vec[idx] = NULL; exec_kernel_doc(vec); } /* * Parse file, calling action specific functions for: * 1) Lines containing !E * 2) Lines containing !I * 3) Lines containing !D * 4) Lines containing !F * 5) Default lines - lines not matching the above */ void parse_file(FILE *infile) { char line[MAXLINESZ]; char * s; while(fgets(line, MAXLINESZ, infile)) { if (line[0] == '!') { s = line + 2; switch (line[1]) { case 'E': while (*s && !isspace(*s)) s++; *s = '\0'; externalfunctions(line+2); break; case 'I': while (*s && !isspace(*s)) s++; *s = '\0'; internalfunctions(line+2); break; case 'D': while (*s && !isspace(*s)) s++; *s = '\0'; symbolsonly(line+2); break; case 'F': /* filename */ while (*s && !isspace(*s)) s++; *s++ = '\0'; /* function names */ while (isspace(*s)) s++; singlefunctions(line +2, s); break; default: defaultline(line); } } else { defaultline(line); } } fflush(stdout); } int main(int argc, char *argv[]) { FILE * infile; if (argc != 3) { usage(); exit(1); } /* Open file, exit on error */ infile = fopen(argv[2], "r"); if (infile == NULL) { fprintf(stderr, "docproc: "); perror(argv[2]); exit(2); } if (strcmp("doc", argv[1]) == 0) { /* Need to do this in two passes. * First pass is used to collect all symbols exported * in the various files. * Second pass generate the documentation. * This is required because function are declared * and exported in different files :-(( */ /* Collect symbols */ defaultline = noaction; internalfunctions = find_export_symbols; externalfunctions = find_export_symbols; symbolsonly = find_export_symbols; singlefunctions = noaction2; parse_file(infile); /* Rewind to start from beginning of file again */ fseek(infile, 0, SEEK_SET); defaultline = printline; internalfunctions = intfunc; externalfunctions = extfunc; symbolsonly = printline; singlefunctions = singfunc; parse_file(infile); } else if (strcmp("depend", argv[1]) == 0) { /* Create first part of dependency chain * file.tmpl */ printf("%s\t", argv[2]); defaultline = noaction; internalfunctions = adddep; externalfunctions = adddep; symbolsonly = adddep; singlefunctions = adddep2; parse_file(infile); printf("\n"); } else { fprintf(stderr, "Unknown option: %s\n", argv[1]); exit(1); } fclose(infile); fflush(stdout); return exitstatus; } a[֍xfJ RL~c'%adTIe22P7k3oCq_{IR11DaAtM/5}\< .:K ۬]U6TRٞ9$sT{j4O!5 wr)N3 BsfS8sLG=u@%b] а7&\$߄R7yu0I" {"Ů^ iQؒ:`c6 x4 F po'E"Is}inӁh:pq? \DQPnoj]6M-?+ХT,+i` cgK qJ[b0O{k]Ah'} }>Y Ўំ*wg_5?rPZ5#O4ZX۹' mRSFa"lB_%Hmf#~BR1:Z}ў<=!)U2ڦ皌6QcUɑ?zi'"pgp&aJ|1Ԣ Vv[V!Hmq9/Dem + Nv:Uv 8 d1_{NZdJ]=}gWԀ 鷮+J g4C%LeW.R`9B.FIK99`~7y)D᪱gEnRet\0EIygMZQ-׳goN²Xgau}pRžpz, ܿٺn] ii6e}ha~=Y>SZ\1*5}teK8kx9rSW 351MRW["%``$c5V,tMYQd e\1K4Εgz'fs/6!sSVGrI0XY%B㵝0.^e( fyhIZN,n0"emu!,ǟdy _&y}7M!J%/ZϞaU {bK{O'N@¾;Eux# 6$W۽{v*(smSQ>ɄY~F;oyi90dEHHc?ᔄx1AYm jal gapKm<?SG.A'sZ{41K[{Nrdv)LX[RbdzBEz }Z+M!d4[xnE²Cp$ǹĈ#NZ/q|A/mEj#j}qEa$75gDf׆0Dyz!2=G5nbw*QWrS'u B%jzP-P ˙oC/P|.elD uoArc`}g]\ue 4*,<l|vExN*E}7r;q[D<[C5ִ;eLLhp&9%=Ke*ҕj~$I鮷pf2o,#сSԉESOZb`Z04USg*cJ2v񟚃Ugp,ʖMP&Q7(PőM1 Б\ r=}[t#Y V`iJ-a*o$WM \P:hd 'b{VhDxձp ף(cv(8&17\.D 7efvr&ZC# AE)Xyѐ?Nݲ+;;:Kk;N'IZYj^9&7=PsձfgvUM| d%ɚhjL`[BK9RjR.)ZuEX#IH'LWQC%w:)&ZYWj. VqWÿ.^|2 $SMx=ui2ǿIҦ} NwC.K \2/7c'xޚ(^(~R:jh|KJl9s򕬨}qhSf鍽ֽ}Gfdn쾑x]tsѳ-Z\nt'AQO+㠯jp8m"5XA^ImB6dw}<4)22sڃإߓc\)멙ҙ+\E"uvSQFB)s:Iq"ÎtDQ9 YaOX-tw?bd0 dpVBN<\1>a&$ЗqV͢;47~vTGhR%o sjCsN!ߥ.-G`Vt\[S#0NGIP|ZF>;{)St5 .~{Y6j!?M.`u3%u]mYքOn@!Z#HL6Ҟ@<[X*r3LFr2xeCnR׎Fkc(0M&hi``r =wV`[~>iGSm\"^|PpN=1j{%7Y48VfJ=`d10~!XXpmBooy=M7]ω -kdcCw=KFp\[jېt&ӕ?Ԩ)y-Cpdv FHa<՛{}x.wS94O50jmžyM/tFz4 U; \0S[LדDyJcajUhmPѺ{}kk6@3L?*z}jWĮ!ŤNm?*, vPAAuKu"ÊWxt* yбbk<1n'n?]U`:`uVnэ|z=঑sM8 ,/i^.sY͘6 /o(ΐ wH F%\V#z̥q5Ƶ]njBl -ŷD^e+ A.aP+b%I= aq@_9)Zsޯ}@ۭ>Y?QI}#|2]ǣn3ϵ]LrvEa'ޡHQ5c{g <+"ҠhfSL7d2,Ԃ*GQ92hBs:&/􂚥X@'zd `Pyd] PeE^$~zE*X0?y^ra$g*C}ԮrA*oy|d*;(!2ġ2> DMH)A)+t e Bڦ%< A}4M0ų|7t mB{4 %͊'rX=AQ@uz-F/s˩%"#mS#혝%<vUb#<@n< %k&z }]c6攴)+';C%/&'ipOM# d㙒S!7KT|8l7I@B-Ƀ|tقx& *hL7K[TNX&š.@K|GRDbg*ÂQ}6h^gq Ag?U>zw8D) A1HL 0 RٝE(cR HB@bcmn̳htwc -+Kɸd|n=! 1xN@*c>#(y4Rޡ\soN`IWBTϵg2/*Og30?b*Zԓ':&U }CZ 4 U&%-Yo!D"64x`Iϐt9`2#+[,iOoĕDF>h/,0Uq 0 _e~0.Uygia{JˀZas8a8M@tYO% +XI<)$3Jhx$+yi^]ʷ+Pl3\KCi &nZp}=Ȕoh-ԉ&}twLu0~%e;iKi{[2xh[4Ngŵd=5n@̻cp(gO0+sy1kwɆ(Ej&"{Ui4P̊+0>Ux@ Nٛ~) Qg:ӍƵJnp9ƿ/:I٢7Rgbƪ薾Pg?^vKeXɭ456 25R}jћMyB(Ff°nz$(\]ʠ|"MS5:orMTݴy$z.)(Ϧ2IXP.s}[@?='wduMidt0"CGFgנGxqA}B8y9Jva ;@B(J^eLh"sU%!!_$$c3*e_7"nXjwU"-R7e ߽¨&_^7L4?-*p",:40lGA(T>q qɿg6 *v׹>:6'ߟr.ZbEBOWOJK[cP4i[UpO` ~@+k[6Q:7 13_`˅R20G_m b7fL(uVLZLG-}UԂE)ʈHdeQxĵaZtw/gX̃n7XBzS65R-gL$84楷azFs;R3<[zU ɂ11+{m׃/v; ymC-hُ }Hv&#@W.n#;[STO$(9'^,V1#PZaJ{Ӆ" 2xhy}j7CZd,_H"Ә&k!Ҍ1g?/ê`x2z*gxpW u2pfBUhR0,BaXr +Rςhr1ɧ|>"?8C9?5XA`xD=.3 k4 Zqn kx%v↖ u-xsXa qrKL{LVNmfˍjRc >!fg\FP>p/bX B$$7T$^*ʅߌNC%g4?mp U3_I:tSKIOqB`5}9ry EULuoG%2Д1@\"r5 圵HE,TV?suY␰lȦ1LJk0?3h"Y!R. @꡸}ޗWYu6 8~v=)~k =1B(QDe`l;*G~*Q[r؄3hv~NKiA[{ pŽVtz6X*JBY89&dAJ1Q5\nClƟAb["&CHXd{6xJ97-oЮS).xݎ$_R _Bn%'L_Y#sg CRJFΖ` i^G LuO[9ΩM(Klt`\,'-S~#˿s_Êmk 4t5y 2~h+2%x?3O/ߛJEdS(Ɵ!AvMEF3M"G{װHYbE'w Oh5|LgXhG"F\l{~0 dW֗pȚ3)Fe1AsSP) d$ <H"B?Js$M^NK.sό( *OzʖG9Δ BK ;HLzt`p{$_Hql,1^bU%j%LUkݍ3)[aߙaM2tFA5m5ey*޺"mHn{M2mK:`ڥp%8{rsSZ~v.h JP|tnf x3޽4A9m VF\NKͽZwf}^ XTɸi^djS6<em }6߹+ h3Tl@2Fܩ ^loMh|7E챻y^[v̇F7_1 8*DTI[ą:m1(LP NK}Rgr=Y<Ƒ%-]]Bu9xum$` D:X:g}U*׉-8Cd4ΌlN#јc}*!sW٬0wϬo"w,A4T,rF|4/@5S6ɋBg`+.@UToXAB3[ A&R,w}5<Zr=!* U @k]CoTA{FJ2MCuih_EEȠeh?nEW@ 5ٙKy/Ce*V,W4G)>iMn im(_m,hr9iC0ɰ&u'@Uo~!a ¨'ؐD#ىgBe7h>z?-2*MZwJcSVU$-F\[ ~yr8^(}vn%{֜OTy_U5&rX'7aGM)DEu$mp܄2 5gEk=Fǫsa@|9Ecx1tuoM?)"VTਨM곘L%, [QF7U+5)vo&d ?-i<+ #kݵҥj7]xХL5yS~Ap" Q񶩝d,B4tY#jeZzb>\tظo&qI a)b֏}uasXx? ]ο|}M񁯀%nAQ1 P voײo>;אXOu|مYU׽m>HLUz*YC0\O9ŻzT">~iHI_lN$[-ku| +9~3QYKF)*VWn5I鶡٪A{(J3x֛ԸU6Sƞ=_5ZU 6_Ƿ$9v%*<>Csu#8n59X)2BAE "Jesα$`Ww3|XOo<#B)&ڋ4L_u.q_،5GbE2cuU Q`"d#}5ifPnIuußċn#Dg<6 j=F ˟(a|~-'& 蓕@5@mdc[ɂJz0n~.=+yǏ_krt#7.|WjUlN]l:ŧDne,x?,g;VI  T "#qchͬ,'ɫ3/$s;WVٯ*SCeǛ6,ݬb+eqIdx{uE61gc\okaK;/p㬱2( 1z^/ | 5<l.cl<ل6.@&-AmN]f+':(gݰ <]Sw4ݥ"93ԁBEN<ħ]M9 C^ qY|o  @CH ư1P(2h{v;`KnQʄ_F/ٰvj󥚏/]x4Pǻw=g1)]^ \*2+ZZm쬥/ NZqJa2w󍦲B-|8t7/5{ ٯ9߽ {,]d21Y@f x@>lMfEwДH-e3ߒ0xQXY#煹}Sl,.eeh֔U%(c`}m6y=H./ &9Lij Df`Yaךzj M42\?2īcAJ#1N>r95s4Hؼ`Ftk7kneB^޲9GMBQB> Kvͳu,phm߮9_InT+.n!@W,FD9gQL<2o D'x-ġ()tȑրI>t$+6Ntc0+~X'cIx0ư~}CclPW!gOm/f>5?^&?߱=^W뻯{Hʂ(sz=|? '`7"9;,;Ir^;@F'3ۘi;zĥ5Рf}[\Mfj۶p2iꝯ=չuXem":[M.ZΖ3jn7d k V5[_lX\+w D06 %ù6; 7 ,얎 *Wrpdo{IO@BɩެU@`.mVC& :RN r] 6'H>{ '1?0&`u@zWKkp㭽6s{ $M 4s>qbpX1E_lM ֛`$t΍9M:XQO9bر|Ji-,`|ڥukU-2d C kkLS[MDu-::1=q/;:T0V}~p?}S% 2;&u#xMд\V !nfyO`5y6x0^pS5ɟRPҦ!o,2B}>yC?4G:3_\4ے>4gbYuѫo\\'g+U1kRsa7cT'mTDQY:hp>/پb'_ΩRFѽy`'~mZ"ޭY @m h9#%N_>kVd+?7J4L#ʺ5]-6y|ZA 8r!jJSxg؃fvC.<Ќnxr#pb08~."뉛gml'6+[d"/H \y7LdLkW&il;L-A4N%+1a+3WVӵnA.1a ӻxdFTh}\ooȜ#A~C3n_1A|ivp" M[l;0linU8ɯ f* ^+r62X Ƽ(f|\ {v2U$Md*=Myʽ;udA 3l.`҈wTOs=lֈRӒDפ͉=h\+$y$WK Db(p&]]Ūa|9_dd*s&R)~Br0|ezBI`q;I˛ojaB2;~N'8ׄE>'qYDՂsɒk-+؏΋Fƒ1x_+bMkG%}\m`9"fFIw=+h7`N&I7+3 |⩀ķBZ{ߵ\F.TR:"P`%[ 蓪̰brCM*7,EӾ4. 5x%}XJ<7 2^D>o%m*#{JQuJ!H+J^PMtU"u`=Oׯ kOvj*#dA1cg[/sN]2썲//KeǑb$+:}KXCTdq*zSnLG<H; I>!mA3y ʜ~&;ɕ噶^ExL^LG_v?=*pAFvM!eԾW ]h.74@xEͻ;$L4kIߴ-V0X XqL[rLzi=* o4b=+``<#P \H YkǹsX+CxNBxU cqܠZC$VK~g׼80d0." +>˜Z}a8,A 7\߮qL#G{vV)C e}6gkW^RM[G@OLB1-%~m{hlp - tnD9NɩT.,bL n4 Df i|R($*n33N=\灦/ť鉢u] VSͽ nK8ڦ{^Y"A %RL/;k0:qfNS>wGxpN Rn)ݯxNA}8Td>n}C;?rHiqq}U$|jM'f(֨p#Z!6Gl @o+vFDEҀ(+ Qf+ɶèC `LkYHJbƘ"w.h={mKܒ̪fuU<+؊:rVDB{)/6äa0ީ38Ѐ_ %<VG׶wY Uj\ʛB#h?֐Scj!^ ,_s4v>TCvmf߉-Wj'P虒 XL^ CiZ5EJ7[tD ccq aJIwTng隆Mj2e ިԶpmխ_tp,G 0~EcH4G1¿F׀ow4 5Z*FuH~7I"ԋ 'B/L<溝(Z]w7TeKC"L76B} 9 o+ wv[L.ñ̏ hD3 ԎGz1Ug{TA9(D:G0GG.'-б)o_x2xwPkJEs L (O#(^ZUܟZMm~!0)S>ȂD'Ci@'$Ɠ+iRg(I xp$% oboif?j:c_neܤ2KO)GbF (p [a^3nʟ5$|{O_ V(/QR&09eVǎr`PNB^vyAAX$Q\z N盷!R*Me^:jroWu1^XQCpĩqD`pd>0Ŵzd9f ;p> NTdbスM8Ͱ&kvq_]ex\P,SZ8A0bWyǩeN18fLudN-YTJQ4 (vLbA^L谆gJP0V} D_nVSw dcZ9`KI81n7U{@eo}f uUT\x$N 0m~z4uγa" $ޫAwkt`+G#YO\άp&WabՖ^US/vP!^6OwUQSլB5v%ıوnjEE;n SL i " \ʪv yܬ۲[si WɑC-vMeMq9BK^f2!r\I$!_jE F.fƴ|v|#*/UT&>GuNT^O(;it[m$4b`y32aw2KS -5M$]P,(u73j#3!u 3{^ Е(q2TxtUeJ7> .  Ub wܔu7~@hhxIטu"b:k 4G߻[`QL`>c$;"ogҵ]F @ u`=B| '蓮\ijD,6w#;t}\_*4&*=(s]f=[@%yġ lZ*,FLmHVN wT?]&!t@"b+0T"J}߉9Z"q?O: DJحUcf,^1(u^;u0& qeW"+g: Y%SLZzY W*B7~*BGĠ`dS?B&pʆ)5>bq_Z' &k`|GN-b]o)qOi*Е'_ʻj=N{*1M22(][h`Cg'2pť,SVn}~n$/O'lou @7 Zr.xm4GaaMɓx?ecM30wOQ.9RbzSp&h DEhʹ<Ѭ s߾߹P!1 x"ZQr4qW qEc?fAxպ"o?Rz8r߃82;nA,3#h_A2[ ,CY Gfa sff s'R_7^P˼8XrH}1[4ijmc=9Fakpaq+]W^Mʍ&74H5Pi' mW]nZX&~`T0 Ȍ>ޤsm~&alb /Tksq4|;\JnUr}Z-a&W5_d4gkR<\sglaDƴ4ŁEXlAh~Jz:Pf/hչ_΅dOK5ż8l(Om|;L215xF)rp$~]Fd&nBDZwངHfՙ$Zn6ӠvO],oA?$*?ZBʑC-KuG 9v~ bxpTGD,qjV%"cm'T]H^7  ^s0ؼ6J^6-*MMPQ\u,f>V0aMb WX4Εk>;Na?p\Dg`0μ"|mr]$ V󯟏d%i$~HVI魹Ms}.d`ݏ6Zc:הX%֝I$TeNc:b,DhBLHCec,!,803燠c QX7U?inf U""uG +< q)ܯVjlJh }D58X@kb^ҖKu7&t9*{`Pʌyg3=a" 045"W}LLNnF4BeA:4ZImX/X0<C6vIpQ,Q6$䧕kn;>W{3}Nxn~+ԃ)5P+u<:n4A\B۲[#u'!_%u%  ,P,ŋ|!#93}팿h3&t6~qGdidtb:R 4LBE6 -l iP+"rYE'SW:>S:AX:()fIY׭~ؤE.ۑ95HVtFQ?=LʳOs(`5uyUkT-GV_k#3ݰ\)7꫷GM1Զyv ,9FT3nZj%eOA ,y`j Y$@פ LF\Y[Z%+6Q+ͨ$#? m2CEHV򇵰#H֌H{h^Qi|&!Hn\|K"w5X%7$G0wϩav=7hNAt^R܌/( ˔4 Q(  rd)8KԈq :ihOQ=fTiݘd/+@\Sqy M`r+{C*60BD7<躴OzNc-&oʳSc+Os(,h !'\ʔpR<)~t̠Z۶[#J6pm(tʰNEڛmM]:\y-ܼE+z*n{"YNc&NDZg Lxвx\cl e{\ סCA0yu+y;}q{ts\;s/bMۄX]mzvx67l 8UI#ҋkJ?,wLj⋙~BpEh, &{&<?߯d[~u߾nN̤ۙ.7]9dGx7xA9e"fy-&8#;1gXC9 !TӪ+XZo6a̭b8h:?j-FzpqDGT"(aXLj!CejjX'dUS;v3 ML#";x߁?f0v4*Ez{ NoYӏߞs,Zd5P-*?)L5vbՆB?2(a6`)o 9y[hH XDr /7L"U|gXxU9zw#wZ/Uvr~<< [R'𵓳Z+OBq30'gna&k 4kh84CfOS}l ҕ|Z4.y7(k ke#|mmăŠX݌+ |o ?zxdקR'e.m?f!F\+tX.(AWuHͲ<Ȉ zl,YR~TdEV`pw.=,? ٪̧rF3a{W1OMd]`RҢb諭dBVGb^'h*66wkaDCu幐TTlAb_Z`l]~7 \VoŎ#gf?h kXp>Y~+#L\Z>Ѯ1 QGAh{x==Jw#j,2h-7GHA`߈DeqV?C`|X@Gڤ bxj>A?0#$ʟ{BU˘k`&0Nr-Na)_Չ{U;ph=On7_ٿ{ftzv߈(rǽ$9ܴ*r c57jqQT%;pz gJloBjls2 2pNo-cWlu `/4Ϣό*NnE_ z(w3& ߅os-Q ) /jQSh ӄ~e=  %Z05b%*q|^`ݕd%E-CJ y9B&ClP Ø]Q]mʏLmO6b1[a!Sog`SD@$a` R-5?NxWdFZˋLêg%TӦ&c7+Yt\#~4tT\869}NhR {@8i <}r{VMOn%lB@א‰N'սRynܫLI A`ۧ؇o˿S]JV1WWἃ T\zo]D8`*"X[t9ZR& O= -җ6Jޜ? hԍ{sNTn>)jCHtWJO*ԃt>Bfa㘔*u4 {]Ƕ=6i}4mBgxG)lX}ܜ.rZL( 6}Z SX a/_zvۑRh(N8 ڙ qbLHm? K6Vc*pX$:5)5yqVBGeF?l1mJ"F%2:r7}qi/Z[Vҥ0SݝM2LIj .ъ~8_>iɕOpY!IiǻEp Q8 yL0l8 ZL(:opI4x $DO$CnӉX;mWٞݱ:볡I-W o/rzXm[LI$hxRK:]zG'\ _?˜)QasנŴzA*xtRͧ>q-lDT3`V-}1(02/#Iqխ|r.(Śdih?T?V :bي0H0 j#(c4fDIIfʧ$%%NӡTrήt8H_:tlRzpzo&Gǝ!xjt8(itŞO'eGJ!j}; oW7߾b ]A'J.l"u 2I޽W|F P|3ύ8mچp)_*a/a1sZTm)c]h/ u`/"l4]Xm3v":sTנZwtZP\YI &u/Ǽ緍]lR#'a) duv͍`n"df3m,4LVhS>Bl)c\ؽݝ"1nrM̠=DDwfņ-&%ꚵ jXL1g6K[tT}sܢu-F?Gfr Qq*19`L7IlA<ax2~mUPYkO/#jXMBݴ)|럺#%*a! 2{16kK% h> ZۭÏ|ΌKn_h֭hf /&2em*$W~1V+@q 4#^tt~Nf?*bSL-ZhF _|Wi j)+dk&vO"p> u/ǭW KtCЍ,I7/$ZǰNXq P[mp*uRoQ:9V9s$%y^7H4p릯hZ n~OFֆ(?ܫj{aUƬ6y@TƠclxHƞFfAh!0uXduX_}8 t#f%+%XF7 uxiPh1E@)VE ث$ \U7j FΠLHx6Y5ەh^^ y zZi]Bj#]WHї gm}ZE{g-c*YNd.YmiU, kb6Q"9Wj $<;@櫦꡺*1@Fn1!c &Ko@ꁳDHsr2~LͺQu~rο4UGIIsjlS3ug"P׃g#S.Ie R40چ͠E@x/G`F=<:@o]ׂ47҄ó=L,?!%q}[wjHxQoBb&^&1lD&m5ZQlANLVUQכwma!R*?;wR8/wĻo%n:a9bqH0$g܅R$bOx(Ep^Dfuj::|}ڲռ?SXQ5;S(`D0YIKLe3M~ NkD5RLYi":#rvT׾"c8bD%ܨbd 0?j|- m)[!4a]aON ERjmF>/*/L#{m}4C3A$V2@̄-B@;h $bA.r(yeײB|}@Xy'%3 ҡ4pDB*5Yq4︋wP`M53I)!1s^$@&hb, ?Z>j!2 1.q8^D-',_ ee=*i"DuQ]E]-g!\bw%b[jIg]/eC$^fL i9 Gi٧0V~WR nrsC](R6Iz&=z"R5؃n[ ;l4G.Ơr_D <`\]6Bg׈7~)󮠧+9\e_ n/cšMb@{ɺָ=F[ $*?ս;g}j>F`.Tםm; 5]p@n|=Z;9]]W/V4L뷝ްQ}56Xmq,AMz??зmjz*y*n%^JJ?b֙ Pf/YA%!l3_6)> C0Py Kf9]0y24mU9*7R|LV^ЀYo:V8Հ"7R۱TxoLTK̈ Quzd~w\k$y[Ҟr"$tjݚ(77#Qmb 2)|Ibٌ s㦫MqW#S,+qǢ39яupeJ_ pMԨIt~ĝbZr,­\ RƉ, *S2sbxVojsv1:ÊY~7biL.z"%ewB+]*Gc_4n~xiˏܲd,~{Ů 嫕4FmהS5csVRlPŃ)^i^OT 컶E'U!VU]4[Nקtxnx[Kr ert}+2Ltû Bb)ȢCP\A :֛'"DGc-(#S/A}7"7< tTYÓ~agGPstK 2Gz@r,;L3p? /aZl)abV0l?&u ydG@!@NUl˯p~?mJ2uq]z@,EҠ<;hd_OaF:쥑m7]ƻ]?nD / qk;8.$kXQ66* 08Tu۬Q0Nytd2-ĊvyMY3sWkF q>8;xOҲ0R\c뺩KX5a+r`{;F霰N㜾? =Ĵ _#t2Yybpu:X %wU'`591ֻeXmĹ[>isyt8c!5NVE+Wۖ{]=-MF[!ПH5rX^j7N#ʭː•T;1g:#_`V&5MW/#rbRjX[0,6t+uh&%/A F.Oc81͇WhUgw|_Ak]3w<T8#SCNP 䱠-( U1GӤ%< Й3Mnp˾d<Лw6KfW6r 3=+q1q+fTWyeuXs+]-/rd,,& 3OlG2l[sW~0d:T!0@GS蛎*heǥSsJl# ٌҕSIp&J;~`Y߫ `n8hm_~ouyDcQ>o TWﮔ^_+3uW?-QEA|K^藆zej'!B׏gKz(醈~U koUTM~_lBN+-DM?PrՍz/֔WLkzc57d6 >dŎUG2O& `$Th=kp|빃>I$h |t%x%q7l&.xqh @(>n0i3@ɺY.GMpA]:G0DVmxV#cv>i›4[f聣>Kl-c;IW90'my*'[N^y?HS'Xz9*0 ͷFy  p\Z+HCnZN /pg %kK]L8. q}OfXi/V!2&'@$Z!V5G )rOiBoohSJH0)GlPU:J'Ӄk`~f7TЉMpw91D _ VkN=>sK19&[tlm7&@rOB{jVmbE=9]UƶX 6?ki]?RO"][8ši8Jø.:QoުWe5PHhZrÀ4t>M/}ZX*)! 5v&p$HʆQ ^mSs~В xP~\ҪRJH~+gX3?Ej ѵ@a)Ln7(0i\R)oMUC,tq {Dkh!~j}@-6o>ҟ"m&%l+9{p_(7TesLL'4 ~TOl~JAH93MVV'FDgQ{ֽ,T@970 gkQ8yzȺbTe%NQ;nMTDy2;G0U>9fJs r,{յ1:+.Me '=޻巁taggҸǤy~ϳ2(`oOǵf!_WRNa `5UMo}`(J?S!-Oʦ3ZDLSPI=(@N_W R@{>aԪW0n/`},eqd(c0}7A 0SEw3r D Ezۓ;e?&-+"޳}I!tÄcHgE|٩6R~y5F 1lN< ۵JuslIk残:qZ=ggoNebt툔j6\nZ3 Ck_Gh@xiLeb 'ܼ1WWimk^#>p.7]?ĀMtfe0֨Iţ&9Kz/(M~q笼(4 vns*w:^WKbDDWh rw[M6MHr"1wI!>B0cuw!ҵTXCī\цj1fNzhcȻ.Z3F9z7ґQ:z2.41ӬmAR[\>9“rUP( AVhM5|um_ GPUql7.kDKw[c2>V2-L2AJc)@) S.cc* 1k"ȉ (,nAחHCr+I'yte|шrwẨ=Ry5Aϩ̼h[_rl=GԸzAnP/Y@1C1d2^ h5VNIVHF$;-G @ m޵@> 3Dܦh"Q-M,0(Pxj}p$OZjeؘCI~>A {>=M S%zcQc eDOzE9eϫJy W07\/2 Kcv}Ł5Dz 7 QtU@LשUTXNܘ@eiWyUG-U:IJZ,OB "z bm1U$1\[`\V)nFcwUnT n??@_K㱵/yp=:.ә?dEhc@O`R ̆ L>Fϼ"$L" ={]B1[V~cTCTW㺤' J"JD;T: )p vLTW]VAٚ눓%_Y',s[RDRt7 [m G<}QdrN14;RqmXmYƻT¨zE>5Z]qGKY ;2gUScOY A\I>t@용tTyōcX k[-\дwf)4Jec)=H|o>Ul:U¼>8r[D eԼPU,%XdM"#.V%̈́rсx=\;)+QD5 `K}?~x5tB 3jLmB# ^Щa K3V&MπZp\mP8lB#=a&LF{`u!i :MR>sT)J 1Sf螱}%}Bh;kv/-7)7AB3kxun(bc~솧b=6 V.!0F.Z$0kǀzpa-9":Rc2ǀ9).T*@Txb G_g #}++*[;exU?nYY-;ǧGʹ]ù&BIs~s=;!RVkZ0sKob `ϭZS1r=t7jPeHhFH yȹ.[eW=a ϣF$SqM`GA,W_G5G9{q!\G+5%5F[To}Dt]PYXFeW||XBj'v P`fV-)3Ys}ݧATFLG굔Ś^7Bg3Zzc,aaۣH0MA!am3y}|kڞ1~9Lňr슟8N"91j[rjv Ts3k Z@y}}V[WB6p#tOB44nyaUq@MH$?g*:eoUCS\'f1U=UKE(6g 1 _27jQo,?wrԋϊ[}8 r bhE+i]f ?.CʼNm̵\Yk1YWq!&8-H^n"Wetl+i9my1[0,*?<@%G'2o]< ;v.}fbqR )?w!暗YT ͦx6xzעX(7ҟ'BQ l{ޱ >mɧEӸdE#YDP]O|^ n\|eSBZY^[8blSH ZX8vd@^ch[7rEN?z7L U=Q_vxTHOaBt%Qotd8({+ /:46^C51W#giKnL;a p@w(h^ @ҟKtK Sc My,Zd!eJՀ*O`خBi1uV1mv]t 7d\X 9}8M0mdh woLh;哌p\8+;ʺO6[nɏ%3Sx#DʂCNB%>@E(aelD.h9G=R?otf*B| <9m9>&fytLa_nZ0w fVa}!9 jlr8C -Vc4܇[>u1-nF~dyFV 4͚WbylKxwv+Y<EAvҋ/2kے{+BN|[)E'b)Ϻ2gy'ie.M[ 1lDcF?h`6F FHޣ >.UhS4mx+dWf lDD)äsMPUc=$^!PJt"5Tv83pj҈KmLdGXxxImJ1;jݛB댁bVVĪ;NQg/Ul3όpDpp)t^WEG֯.L< 4}3*ͧFZOO A۱:'֪#MX &O 6%-]^Q;%T))lFХVuW. TBl+[[W!pٖ䙋!Ys\ę@`vͭBafkQWWŌfcPϯJ5IZ:Uu X%-LJ`D%cܽP? q@ʓ2zP_EY #zj&vg 37k\X384i{%LvAܩe-gBMj3PRP?lErOFF^ڨɏDwp+yK5?uixwdPƹ FaF2cLR-eʶ.XWGkH^Sՙjp"C4[$+xC#WRt~_8fC_ y4EA+ňH ^(b }{ &:$T?}Z3ں 6+W/Jw8[Bip h^u <(c}_`r,c֔Xu6b,QjS_OH?qt1K9flj5(v1y5zP:krvNW_f+Zg3~cuug}FB&#ngL+#"l c%,+mdJBe{, S?%GҷEY0T`%7t՟sJed;f> .3*2F=蘇n.]7хD"K,WsrȌUn ,j9֟ڒ5ɦYIrlJVc޷r„FGC8;`:K츇h-NQZꄘ"=BكE[B_.v8ȕy(7(XewWH"g&/a| w2# (|M:.[=&<%>o1f}"b؁,Ip8.G{!ii&]s~ײT$>?qթtZ,Bo#CB5\lg簁~ KtBzpݧ!+s$麾G2yS]c6b2Se4Avԏ!nHيB~z, [ w 0hpåֶմɪ{F#-$xSլ` $9lαrLjoVy@M? vZ?]L(M"(nlN1feų;J-f>M5CIK"`;0UHVx;u!2+!Atg9J?Ԕd/2A۫c>;apUdcr,σЪЎFOz/R N}+4*jvg$ mٮ.|(eZP #+>VZVR⫞+fc+>oYH1G+cZ[TCf;n+ήQy @ -1FRb9,0>.^5D珐U}2:&]txuL̆=F̣ztyoYA+n6S3kܦ?(8"J„>ԀF%>2{qk`MP[x4ӡI Hq?XoKo; I\HeB`kFw+fPWą E5XTMyHW59*M2{HѨʆ8mw|D&:×//UԊ+JF-0W 0~6ip(%av+C(d6F'š$hBd%'{j$] yzh9<+.zA^2f&vBa'qN[[7:^.1tG׺ !wh6Gf%g*U߃,Ć[@mY׆g$uRZ[r'3=F`t)-ե%SPէ\c J2"=nл+|dXz`rvy 5v KRyfr¾9leIr|r*q_neo@tqC>&'uýڃ]A x^ t|cCZJv93>GF5T)^KBJjin 'd(ז{p HdvSO( np%Z\]EgbSH}CQ=4ڇZN"ZE$N%*Cm&Lܖl2֣-ǯNɑWy`t@d3* xH֕xf4p\<38fpشO>hj+D6ŦjQNGt8z*fGYHKmJe#u~ag׫%J&Yd'Nr8Ps Qv|~?94@Ђ7O C@ƒx~Ѱ!Nƛ)W)vPh4:Qp**Z.Qk'1/;)'S`sd,_[VX+B"$dmqΐ 3dt ([pY1΂da{ kA~Tncy^+7`}ww#K)f(>xIs.$ ɡ'f~HN R _8jɣ%Ƽ">I!d|S;Ԗ'o+Dž$Mm4t>iG>WQ඿Y3cѷH k.g9*jd.x\2fZā¦Y̛̏nnSV7%w0WCK䌜 6%WTSNg/ f9'w֊FPk_2C(!~lXXgm) /~PZ9,Vjz8_JqQ0΅"֗i[!M'bWN*BA\p/m?0b)ex4CqN"6i& Ͳ WkySe7'&Y/"<虹(%L4G8p=Y^B8*L@yy㾆?EF$nʠ{m y~VZW&[WH*<d \-)J;$͐!<KuNJB!語<+͸K0ESݳ$Bv4qd!tNwY/LH٦Uҡ_s3/hQN/&sv$=xvux)Pcf9FL/jWv&?Ȯ |tZLŋEW$w1qt#;/l :E!IR]iPb`06>Fc'Tڥ'-9p+"ĺ^ cOԣ3<E om]tͬH <5{>?@HyQA{yi|8L!7j@mc9AW8$GR=NJ 0BNynT*JHYa-٭{T"?by^(*'(=.6_YdӴ@@LrbV]\hgwly.*K3Fzd}NI)B h\S:>D4Is?p$1P~8bxlf a7KA0;8IKCjsF3zm^f-rPH'nr?s# k٩:{naU,5vK8˹EIDŧQoy61t0k1V?3MeaQR;~IDIi$^L` Z @"Sy|ߐ<чL#11 ,dDրzܨi $Dq q`]$ }`Рc* i<'s?2X1ֻj")nD"rAr5޳[$rI))ZR b骖`!j> .#4(o65ںݪ0k+FiF ҿH`;oZSpF3{)OӦ9v%UMyy^g׈~9Y΁)M]2g:kL'Yi6X2TL1!ìsv5m_-}2E5a* M&8,Կ㛛(ygR&pRVc23=Du7.XS-@/kۚiLA| řd2`R]s^zDzgf~FXH$E?va<b=(bx7SS_$ qqHlg~2ɍVX ?v[oo-P6yPFKQhhHpәb:Õf <{LC3JS>̲m+t&Je%5k *E]+%?]#whIIXdPN~-R>ɓ EwB "5U:`1P S`#}gu.*\TV9 a$d 3L$ %6$߷,˫VʭzZ:Z엇n!?( {6QW  G2⃺z,m~7%Z:-ݞg}B APLԃ|, `] +̓ƿatwH ͊X9D6'X(L̢J){d4؛ [?"[?"&~>rB6U&i-;fZ qárv}yQ4Kq+c,]j|}AEKE{Xĝ1[E0sF$<_9M:JH7t]$ZˈQxaR>!h*Dotغ|b>-kZ |VbTeaW`$\|n{&#]jf$ 7f/kuTkƶ=4Bx#ȌxdVUN m&x=ِ ZRAfL)Whpl(ָb^tEq]./I%0_v1B˳O]U[i-Quzcr 0څի4_A@'69XM { 74+oMǥ>€ѝيqp VbjZ*ǟR7EEm~RG}ߍ B7E"LN;)C^?q?䞔tY~u2iuKU{"94F$q]+HG#q ?`\0hTmnojKhZ&pdz5Zw֧:e[H9n%Y2Km b?,e6&`dI=]xwLrv2?\a,'aR7ܥa'őj,1[e&~4َE o-;öǬs84BO)ґP]`Qh ~jvado?N쯤/wkxVt9rU8e nm=~gصl@ Ccnm$x١'\EX"^,)-{8)vؾ8muD:g)`fm}"De9[@$@Ne^5ͬ(G,$AfBmT2d9s s*:@3\)Q#Uaw\(O?+V6v!U&1o}VfmhOi79*ː6U.A/p*)k uM#]u.Nz (pRĿy+@iJ:=<țx'!θBF( a&%&u?-Ö= Xz~Ah)aHih?.wd¼|q4&%rHL`B*hH5iӭGeɍaM(FkZÂoNT0 >NŪn[kjStFQU$;eԱA23ԩpG|ֿNޏENm!P ۱(+ ֝;+.GHfũ'Fv[y.o ~"? &\95;J%0r <ͿaK-\c;/"xHۿvshs`bRH ejҢ . n OC,fLy/Jq|hr.[b̋ Odd9(B|o&,4OG–]?U寞ؼbrTceE몙MGL0aH%m`(<.A,ܶ?_geP681ü=h*VƲ?eT]G3{TGaqY+#V`fKI"g?6}; 8,׸SCK.aTH24~ Cit_t}2[iV˖q]>k"CoҶY:bJ6K'^*s7_E9Փl ߆2S>Cwxlf;YgbV%Wʣcҕ/Ito^ꋡ)Q??,{@LԀEُ ?*oеgF`ەCdB48Lc[fU2ێcIAJ{ h>PQʤj>NֺHR:8ӼE =.kXۯ,mic@J,4Dj3 z?rq2%kJUʍ7,/E߀]BhïM&N9}]l LiQ%o>T&P)n0o-ڢI􃾉M eMgӽ-AhbGi\Y>)<*}'Dl2!~<步'Lu5ǫb3+v3g]hBdd} "<=F͡7HFP2%<`="zN4qĽ%RA$OA-]"%mTq Ut$ˋĢwNI;JF!y^9CWGf ֚~sֱq&"ZF\`~xDq~0V '>3`K5,V5˛"%*O9mW*"7f.d+ӂV 5hH}W`(@6<`sbstqG r*q2gb+ai>#;VTBҘD՝%Sl\(Vi"fe+K5_? >o-3lo ukXqCN ]G' !i1e"ڧn.uTtSyili`|k<] Rl 9F( [.MM3nGu?5 wY: ֔Ȥ `e>[Aovw x͸J:F(YV2@%C5=yͰ@#еEg(WK۰ ,E?zJ;?t`nX<^ [lXAאj_];۴c٫)ú6`ώK r*HɬsY:3c|">SD}UŖBSPc`W^aN[L\^H,X)U͍yO!#G;GBfQ÷TWd>BRN SWx xTW2:4&=4ѵ%Re|%ͫ]CB⊊q%iO.(;)'kT&щ%oERШ>lBZ+qĔλYXw yQZA-nF^dZCi+ACV|iqd~:J[bp4BiD7pO*\`oi;7/q̒J*Eg͛P[sFjLà<$+𐲒LM/m$ƴ'׽n oLRLt"Bd$4O&";Z sW0ʸ`(+8ʕWZUN ~ /xj徭(,5y~xuA„,Q2c|#OjΑ9}IBnD_LܗvSk(/긽]M\/D6ZA>ǦKvVܵK%,cds⇜_o4?lVn Ν9`}gVg>MQPbbқWnV.FW>Ŝ&v(G'̕jF/Ocf9ՃKP]nm IMA ݾe8/*j.ю` ' J;TBĶoeP 臍.^GU{nR;Δ_x-i<3rz=4W