diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2699e61 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class diff --git a/renode_rcc/Dockerfile b/renode_rcc/Dockerfile index 1928bc1..91a3429 100644 --- a/renode_rcc/Dockerfile +++ b/renode_rcc/Dockerfile @@ -3,16 +3,17 @@ WORKDIR /root ENV DEBIAN_FRONTEND noninteractive RUN apt-get update -y && \ - apt-get install -y git \ - xz-utils \ + apt-get install -y automake \ + autoconf \ + ca-certificates \ + git \ make \ + netcat \ + tree \ vim \ - ca-certificates \ wget \ - automake \ - autoconf \ - netcat \ - tree + xterm \ + xz-utils ARG RENODE_VERSION=1.13.0 @@ -22,8 +23,8 @@ RUN wget https://github.com/renode/renode/releases/download/v${RENODE_VERSION}/r apt-get install -y --no-install-recommends ./renode_${RENODE_VERSION}_amd64.deb python3-dev && \ rm ./renode_${RENODE_VERSION}_amd64.deb RUN pip3 install -r /opt/renode/tests/requirements.txt --no-cache-dir -RUN git clone https://github.com/tonylitianyu/renode-rtems-leon3.git - +RUN git clone https://github.com/antmicro/renode-rtems-leon3.git +COPY renode-rtems-leon3/ /root/renode-rtems-leon3/ WORKDIR /root/renode-rtems-leon3 RUN ./build-rtems.sh @@ -34,6 +35,7 @@ RUN mv grlib-gpl-2021.2-b4267 /opt/renode/ ENV PATH $PATH:/opt/renode/rcc-1.3.0-gcc/bin WORKDIR /root +COPY config .config/renode/ #renode #s @renode-rtems-leon3/leon3_rtems.resc diff --git a/renode_rcc/README.md b/renode_rcc/README.md index 91c6688..9f684ec 100644 --- a/renode_rcc/README.md +++ b/renode_rcc/README.md @@ -1,2 +1,17 @@ # renode-RCC Building [RTEMS Cross Compilation System (RCC)](https://www.gaisler.com/index.php/products/operating-systems/rtems), has a different directory structure compare to building RTEMS from source (might not be true). This will run RTEMS on leon3 in a renode simulation. + +## Usage +To run the simulator in docker container +``` +renode +``` + +> If you face GTK protocol error then exit the container, run `xhost + local:` and restart the conatiner to allow other users (including root) run programs in the current session. + + +In the renode window, run +``` +start +s @renode-rtems-leon3/leon3_rtems.resc +``` diff --git a/renode_rcc/config b/renode_rcc/config new file mode 100755 index 0000000..9881e0c --- /dev/null +++ b/renode_rcc/config @@ -0,0 +1,22 @@ +[general] +terminal = Termsharp +collapse-repeated-log-entries = True +compiler-cache-enabled = False +serialization-mode = Generated +use-synchronous-logging = False +always-log-machine-name = False +log-history-limit = 1000 +history-path = /root/.config/renode/history +[monitor] +consume-exceptions-from-command = True +break-script-on-exception = True +number-format = Hexadecimal +[plugins] +enabled-plugins = +[termsharp] +append-CR-to-LF = True +font-face = Roboto Mono +font-size = 20 +window-width = 700 +window-height = 400 + diff --git a/renode_rcc/renode-rtems-leon3/build/dream.xml b/renode_rcc/renode-rtems-leon3/build/dream.xml new file mode 100755 index 0000000..0a0b17c --- /dev/null +++ b/renode_rcc/renode-rtems-leon3/build/dream.xml @@ -0,0 +1,4546 @@ + + + + +A Midsummer Night's Dream + + +

Text placed in the public domain by Moby Lexical Tools, 1992.

+

SGML markup by Jon Bosak, 1992-1994.

+

XML version by Jon Bosak, 1996-1998.

+

This work may be freely copied and distributed worldwide.

+
+ + + +Dramatis Personae + +THESEUS, Duke of Athens. +EGEUS, father to Hermia. + + +LYSANDER +DEMETRIUS +in love with Hermia. + + +PHILOSTRATE, master of the revels to Theseus. +QUINCE, a carpenter. +SNUG, a joiner. +BOTTOM, a weaver. +FLUTE, a bellows-mender. +SNOUT, a tinker. +STARVELING, a tailor. +HIPPOLYTA, queen of the Amazons, betrothed to Theseus. +HERMIA, daughter to Egeus, in love with Lysander. +HELENA, in love with Demetrius. +OBERON, king of the fairies. +TITANIA, queen of the fairies. +PUCK, or Robin Goodfellow. + + +PEASEBLOSSOM +COBWEB +MOTH +MUSTARDSEED +fairies. + + +Other fairies attending their King and Queen. +Attendants on Theseus and Hippolyta. + + +SCENE Athens, and a wood near it. + +A MIDSUMMER NIGHT'S DREAM + +ACT I + +SCENE I. Athens. The palace of THESEUS. +Enter THESEUS, HIPPOLYTA, PHILOSTRATE, and +Attendants + + +THESEUS +Now, fair Hippolyta, our nuptial hour +Draws on apace; four happy days bring in +Another moon: but, O, methinks, how slow +This old moon wanes! she lingers my desires, +Like to a step-dame or a dowager +Long withering out a young man revenue. + + + +HIPPOLYTA +Four days will quickly steep themselves in night; +Four nights will quickly dream away the time; +And then the moon, like to a silver bow +New-bent in heaven, shall behold the night +Of our solemnities. + + + +THESEUS +Go, Philostrate, +Stir up the Athenian youth to merriments; +Awake the pert and nimble spirit of mirth; +Turn melancholy forth to funerals; +The pale companion is not for our pomp. +Exit PHILOSTRATE +Hippolyta, I woo'd thee with my sword, +And won thy love, doing thee injuries; +But I will wed thee in another key, +With pomp, with triumph and with revelling. + + + +Enter EGEUS, HERMIA, LYSANDER, and DEMETRIUS + + +EGEUS +Happy be Theseus, our renowned duke! + + + +THESEUS +Thanks, good Egeus: what's the news with thee? + + + +EGEUS +Full of vexation come I, with complaint +Against my child, my daughter Hermia. +Stand forth, Demetrius. My noble lord, +This man hath my consent to marry her. +Stand forth, Lysander: and my gracious duke, +This man hath bewitch'd the bosom of my child; +Thou, thou, Lysander, thou hast given her rhymes, +And interchanged love-tokens with my child: +Thou hast by moonlight at her window sung, +With feigning voice verses of feigning love, +And stolen the impression of her fantasy +With bracelets of thy hair, rings, gawds, conceits, +Knacks, trifles, nosegays, sweetmeats, messengers +Of strong prevailment in unharden'd youth: +With cunning hast thou filch'd my daughter's heart, +Turn'd her obedience, which is due to me, +To stubborn harshness: and, my gracious duke, +Be it so she; will not here before your grace +Consent to marry with Demetrius, +I beg the ancient privilege of Athens, +As she is mine, I may dispose of her: +Which shall be either to this gentleman +Or to her death, according to our law +Immediately provided in that case. + + + +THESEUS +What say you, Hermia? be advised fair maid: +To you your father should be as a god; +One that composed your beauties, yea, and one +To whom you are but as a form in wax +By him imprinted and within his power +To leave the figure or disfigure it. +Demetrius is a worthy gentleman. + + + +HERMIA +So is Lysander. + + + +THESEUS +In himself he is; +But in this kind, wanting your father's voice, +The other must be held the worthier. + + + +HERMIA +I would my father look'd but with my eyes. + + + +THESEUS +Rather your eyes must with his judgment look. + + + +HERMIA +I do entreat your grace to pardon me. +I know not by what power I am made bold, +Nor how it may concern my modesty, +In such a presence here to plead my thoughts; +But I beseech your grace that I may know +The worst that may befall me in this case, +If I refuse to wed Demetrius. + + + +THESEUS +Either to die the death or to abjure +For ever the society of men. +Therefore, fair Hermia, question your desires; +Know of your youth, examine well your blood, +Whether, if you yield not to your father's choice, +You can endure the livery of a nun, +For aye to be in shady cloister mew'd, +To live a barren sister all your life, +Chanting faint hymns to the cold fruitless moon. +Thrice-blessed they that master so their blood, +To undergo such maiden pilgrimage; +But earthlier happy is the rose distill'd, +Than that which withering on the virgin thorn +Grows, lives and dies in single blessedness. + + + +HERMIA +So will I grow, so live, so die, my lord, +Ere I will my virgin patent up +Unto his lordship, whose unwished yoke +My soul consents not to give sovereignty. + + + +THESEUS +Take time to pause; and, by the nest new moon-- +The sealing-day betwixt my love and me, +For everlasting bond of fellowship-- +Upon that day either prepare to die +For disobedience to your father's will, +Or else to wed Demetrius, as he would; +Or on Diana's altar to protest +For aye austerity and single life. + + + +DEMETRIUS +Relent, sweet Hermia: and, Lysander, yield +Thy crazed title to my certain right. + + + +LYSANDER +You have her father's love, Demetrius; +Let me have Hermia's: do you marry him. + + + +EGEUS +Scornful Lysander! true, he hath my love, +And what is mine my love shall render him. +And she is mine, and all my right of her +I do estate unto Demetrius. + + + +LYSANDER +I am, my lord, as well derived as he, +As well possess'd; my love is more than his; +My fortunes every way as fairly rank'd, +If not with vantage, as Demetrius'; +And, which is more than all these boasts can be, +I am beloved of beauteous Hermia: +Why should not I then prosecute my right? +Demetrius, I'll avouch it to his head, +Made love to Nedar's daughter, Helena, +And won her soul; and she, sweet lady, dotes, +Devoutly dotes, dotes in idolatry, +Upon this spotted and inconstant man. + + + +THESEUS +I must confess that I have heard so much, +And with Demetrius thought to have spoke thereof; +But, being over-full of self-affairs, +My mind did lose it. But, Demetrius, come; +And come, Egeus; you shall go with me, +I have some private schooling for you both. +For you, fair Hermia, look you arm yourself +To fit your fancies to your father's will; +Or else the law of Athens yields you up-- +Which by no means we may extenuate-- +To death, or to a vow of single life. +Come, my Hippolyta: what cheer, my love? +Demetrius and Egeus, go along: +I must employ you in some business +Against our nuptial and confer with you +Of something nearly that concerns yourselves. + + + +EGEUS +With duty and desire we follow you. + + + +Exeunt all but LYSANDER and HERMIA + + +LYSANDER +How now, my love! why is your cheek so pale? +How chance the roses there do fade so fast? + + + +HERMIA +Belike for want of rain, which I could well +Beteem them from the tempest of my eyes. + + + +LYSANDER +Ay me! for aught that I could ever read, +Could ever hear by tale or history, +The course of true love never did run smooth; +But, either it was different in blood,-- + + + +HERMIA +O cross! too high to be enthrall'd to low. + + + +LYSANDER +Or else misgraffed in respect of years,-- + + + +HERMIA +O spite! too old to be engaged to young. + + + +LYSANDER +Or else it stood upon the choice of friends,-- + + + +HERMIA +O hell! to choose love by another's eyes. + + + +LYSANDER +Or, if there were a sympathy in choice, +War, death, or sickness did lay siege to it, +Making it momentany as a sound, +Swift as a shadow, short as any dream; +Brief as the lightning in the collied night, +That, in a spleen, unfolds both heaven and earth, +And ere a man hath power to say 'Behold!' +The jaws of darkness do devour it up: +So quick bright things come to confusion. + + + +HERMIA +If then true lovers have been ever cross'd, +It stands as an edict in destiny: +Then let us teach our trial patience, +Because it is a customary cross, +As due to love as thoughts and dreams and sighs, +Wishes and tears, poor fancy's followers. + + + +LYSANDER +A good persuasion: therefore, hear me, Hermia. +I have a widow aunt, a dowager +Of great revenue, and she hath no child: +From Athens is her house remote seven leagues; +And she respects me as her only son. +There, gentle Hermia, may I marry thee; +And to that place the sharp Athenian law +Cannot pursue us. If thou lovest me then, +Steal forth thy father's house to-morrow night; +And in the wood, a league without the town, +Where I did meet thee once with Helena, +To do observance to a morn of May, +There will I stay for thee. + + + +HERMIA +My good Lysander! +I swear to thee, by Cupid's strongest bow, +By his best arrow with the golden head, +By the simplicity of Venus' doves, +By that which knitteth souls and prospers loves, +And by that fire which burn'd the Carthage queen, +When the false Troyan under sail was seen, +By all the vows that ever men have broke, +In number more than ever women spoke, +In that same place thou hast appointed me, +To-morrow truly will I meet with thee. + + + +LYSANDER +Keep promise, love. Look, here comes Helena. + + + +Enter HELENA + + +HERMIA +God speed fair Helena! whither away? + + + +HELENA +Call you me fair? that fair again unsay. +Demetrius loves your fair: O happy fair! +Your eyes are lode-stars; and your tongue's sweet air +More tuneable than lark to shepherd's ear, +When wheat is green, when hawthorn buds appear. +Sickness is catching: O, were favour so, +Yours would I catch, fair Hermia, ere I go; +My ear should catch your voice, my eye your eye, +My tongue should catch your tongue's sweet melody. +Were the world mine, Demetrius being bated, +The rest I'd give to be to you translated. +O, teach me how you look, and with what art +You sway the motion of Demetrius' heart. + + + +HERMIA +I frown upon him, yet he loves me still. + + + +HELENA +O that your frowns would teach my smiles such skill! + + + +HERMIA +I give him curses, yet he gives me love. + + + +HELENA +O that my prayers could such affection move! + + + +HERMIA +The more I hate, the more he follows me. + + + +HELENA +The more I love, the more he hateth me. + + + +HERMIA +His folly, Helena, is no fault of mine. + + + +HELENA +None, but your beauty: would that fault were mine! + + + +HERMIA +Take comfort: he no more shall see my face; +Lysander and myself will fly this place. +Before the time I did Lysander see, +Seem'd Athens as a paradise to me: +O, then, what graces in my love do dwell, +That he hath turn'd a heaven unto a hell! + + + +LYSANDER +Helen, to you our minds we will unfold: +To-morrow night, when Phoebe doth behold +Her silver visage in the watery glass, +Decking with liquid pearl the bladed grass, +A time that lovers' flights doth still conceal, +Through Athens' gates have we devised to steal. + + + +HERMIA +And in the wood, where often you and I +Upon faint primrose-beds were wont to lie, +Emptying our bosoms of their counsel sweet, +There my Lysander and myself shall meet; +And thence from Athens turn away our eyes, +To seek new friends and stranger companies. +Farewell, sweet playfellow: pray thou for us; +And good luck grant thee thy Demetrius! +Keep word, Lysander: we must starve our sight +From lovers' food till morrow deep midnight. + + + +LYSANDER +I will, my Hermia. +Exit HERMIA +Helena, adieu: +As you on him, Demetrius dote on you! + + + +Exit + + +HELENA +How happy some o'er other some can be! +Through Athens I am thought as fair as she. +But what of that? Demetrius thinks not so; +He will not know what all but he do know: +And as he errs, doting on Hermia's eyes, +So I, admiring of his qualities: +Things base and vile, folding no quantity, +Love can transpose to form and dignity: +Love looks not with the eyes, but with the mind; +And therefore is wing'd Cupid painted blind: +Nor hath Love's mind of any judgement taste; +Wings and no eyes figure unheedy haste: +And therefore is Love said to be a child, +Because in choice he is so oft beguiled. +As waggish boys in game themselves forswear, +So the boy Love is perjured every where: +For ere Demetrius look'd on Hermia's eyne, +He hail'd down oaths that he was only mine; +And when this hail some heat from Hermia felt, +So he dissolved, and showers of oaths did melt. +I will go tell him of fair Hermia's flight: +Then to the wood will he to-morrow night +Pursue her; and for this intelligence +If I have thanks, it is a dear expense: +But herein mean I to enrich my pain, +To have his sight thither and back again. + + + +Exit + + +SCENE II. Athens. QUINCE'S house. +Enter QUINCE, SNUG, BOTTOM, FLUTE, SNOUT, and +STARVELING + + +QUINCE +Is all our company here? + + + +BOTTOM +You were best to call them generally, man by man, +according to the scrip. + + + +QUINCE +Here is the scroll of every man's name, which is +thought fit, through all Athens, to play in our +interlude before the duke and the duchess, on his +wedding-day at night. + + + +BOTTOM +First, good Peter Quince, say what the play treats +on, then read the names of the actors, and so grow +to a point. + + + +QUINCE +Marry, our play is, The most lamentable comedy, and +most cruel death of Pyramus and Thisby. + + + +BOTTOM +A very good piece of work, I assure you, and a +merry. Now, good Peter Quince, call forth your +actors by the scroll. Masters, spread yourselves. + + + +QUINCE +Answer as I call you. Nick Bottom, the weaver. + + + +BOTTOM +Ready. Name what part I am for, and proceed. + + + +QUINCE +You, Nick Bottom, are set down for Pyramus. + + + +BOTTOM +What is Pyramus? a lover, or a tyrant? + + + +QUINCE +A lover, that kills himself most gallant for love. + + + +BOTTOM +That will ask some tears in the true performing of +it: if I do it, let the audience look to their +eyes; I will move storms, I will condole in some +measure. To the rest: yet my chief humour is for a +tyrant: I could play Ercles rarely, or a part to +tear a cat in, to make all split. +The raging rocks +And shivering shocks +Shall break the locks +Of prison gates; +And Phibbus' car +Shall shine from far +And make and mar +The foolish Fates. +This was lofty! Now name the rest of the players. +This is Ercles' vein, a tyrant's vein; a lover is +more condoling. + + + +QUINCE +Francis Flute, the bellows-mender. + + + +FLUTE +Here, Peter Quince. + + + +QUINCE +Flute, you must take Thisby on you. + + + +FLUTE +What is Thisby? a wandering knight? + + + +QUINCE +It is the lady that Pyramus must love. + + + +FLUTE +Nay, faith, let me not play a woman; I have a beard coming. + + + +QUINCE +That's all one: you shall play it in a mask, and +you may speak as small as you will. + + + +BOTTOM +An I may hide my face, let me play Thisby too, I'll +speak in a monstrous little voice. 'Thisne, +Thisne;' 'Ah, Pyramus, lover dear! thy Thisby dear, +and lady dear!' + + + +QUINCE +No, no; you must play Pyramus: and, Flute, you Thisby. + + + +BOTTOM +Well, proceed. + + + +QUINCE +Robin Starveling, the tailor. + + + +STARVELING +Here, Peter Quince. + + + +QUINCE +Robin Starveling, you must play Thisby's mother. +Tom Snout, the tinker. + + + +SNOUT +Here, Peter Quince. + + + +QUINCE +You, Pyramus' father: myself, Thisby's father: +Snug, the joiner; you, the lion's part: and, I +hope, here is a play fitted. + + + +SNUG +Have you the lion's part written? pray you, if it +be, give it me, for I am slow of study. + + + +QUINCE +You may do it extempore, for it is nothing but roaring. + + + +BOTTOM +Let me play the lion too: I will roar, that I will +do any man's heart good to hear me; I will roar, +that I will make the duke say 'Let him roar again, +let him roar again.' + + + +QUINCE +An you should do it too terribly, you would fright +the duchess and the ladies, that they would shriek; +and that were enough to hang us all. + + + +ALL +That would hang us, every mother's son. + + + +BOTTOM +I grant you, friends, if that you should fright the +ladies out of their wits, they would have no more +discretion but to hang us: but I will aggravate my +voice so that I will roar you as gently as any +sucking dove; I will roar you an 'twere any +nightingale. + + + +QUINCE +You can play no part but Pyramus; for Pyramus is a +sweet-faced man; a proper man, as one shall see in a +summer's day; a most lovely gentleman-like man: +therefore you must needs play Pyramus. + + + +BOTTOM +Well, I will undertake it. What beard were I best +to play it in? + + + +QUINCE +Why, what you will. + + + +BOTTOM +I will discharge it in either your straw-colour +beard, your orange-tawny beard, your purple-in-grain +beard, or your French-crown-colour beard, your +perfect yellow. + + + +QUINCE +Some of your French crowns have no hair at all, and +then you will play bare-faced. But, masters, here +are your parts: and I am to entreat you, request +you and desire you, to con them by to-morrow night; +and meet me in the palace wood, a mile without the +town, by moonlight; there will we rehearse, for if +we meet in the city, we shall be dogged with +company, and our devices known. In the meantime I +will draw a bill of properties, such as our play +wants. I pray you, fail me not. + + + +BOTTOM +We will meet; and there we may rehearse most +obscenely and courageously. Take pains; be perfect: adieu. + + + +QUINCE +At the duke's oak we meet. + + + +BOTTOM +Enough; hold or cut bow-strings. + + + +Exeunt + + + + +ACT II + +SCENE I. A wood near Athens. +Enter, from opposite sides, a Fairy, and PUCK + + +PUCK +How now, spirit! whither wander you? + + + +Fairy +Over hill, over dale, +Thorough bush, thorough brier, +Over park, over pale, +Thorough flood, thorough fire, +I do wander everywhere, +Swifter than the moon's sphere; +And I serve the fairy queen, +To dew her orbs upon the green. +The cowslips tall her pensioners be: +In their gold coats spots you see; +Those be rubies, fairy favours, +In those freckles live their savours: +I must go seek some dewdrops here +And hang a pearl in every cowslip's ear. +Farewell, thou lob of spirits; I'll be gone: +Our queen and all our elves come here anon. + + + +PUCK +The king doth keep his revels here to-night: +Take heed the queen come not within his sight; +For Oberon is passing fell and wrath, +Because that she as her attendant hath +A lovely boy, stolen from an Indian king; +She never had so sweet a changeling; +And jealous Oberon would have the child +Knight of his train, to trace the forests wild; +But she perforce withholds the loved boy, +Crowns him with flowers and makes him all her joy: +And now they never meet in grove or green, +By fountain clear, or spangled starlight sheen, +But, they do square, that all their elves for fear +Creep into acorn-cups and hide them there. + + + +Fairy +Either I mistake your shape and making quite, +Or else you are that shrewd and knavish sprite +Call'd Robin Goodfellow: are not you he +That frights the maidens of the villagery; +Skim milk, and sometimes labour in the quern +And bootless make the breathless housewife churn; +And sometime make the drink to bear no barm; +Mislead night-wanderers, laughing at their harm? +Those that Hobgoblin call you and sweet Puck, +You do their work, and they shall have good luck: +Are not you he? + + + +PUCK +Thou speak'st aright; +I am that merry wanderer of the night. +I jest to Oberon and make him smile +When I a fat and bean-fed horse beguile, +Neighing in likeness of a filly foal: +And sometime lurk I in a gossip's bowl, +In very likeness of a roasted crab, +And when she drinks, against her lips I bob +And on her wither'd dewlap pour the ale. +The wisest aunt, telling the saddest tale, +Sometime for three-foot stool mistaketh me; +Then slip I from her bum, down topples she, +And 'tailor' cries, and falls into a cough; +And then the whole quire hold their hips and laugh, +And waxen in their mirth and neeze and swear +A merrier hour was never wasted there. +But, room, fairy! here comes Oberon. + + + +Fairy +And here my mistress. Would that he were gone! + + + +Enter, from one side, OBERON, with his train; +from the other, TITANIA, with hers + + +OBERON +Ill met by moonlight, proud Titania. + + + +TITANIA +What, jealous Oberon! Fairies, skip hence: +I have forsworn his bed and company. + + + +OBERON +Tarry, rash wanton: am not I thy lord? + + + +TITANIA +Then I must be thy lady: but I know +When thou hast stolen away from fairy land, +And in the shape of Corin sat all day, +Playing on pipes of corn and versing love +To amorous Phillida. Why art thou here, +Come from the farthest Steppe of India? +But that, forsooth, the bouncing Amazon, +Your buskin'd mistress and your warrior love, +To Theseus must be wedded, and you come +To give their bed joy and prosperity. + + + +OBERON +How canst thou thus for shame, Titania, +Glance at my credit with Hippolyta, +Knowing I know thy love to Theseus? +Didst thou not lead him through the glimmering night +From Perigenia, whom he ravished? +And make him with fair AEgle break his faith, +With Ariadne and Antiopa? + + + +TITANIA +These are the forgeries of jealousy: +And never, since the middle summer's spring, +Met we on hill, in dale, forest or mead, +By paved fountain or by rushy brook, +Or in the beached margent of the sea, +To dance our ringlets to the whistling wind, +But with thy brawls thou hast disturb'd our sport. +Therefore the winds, piping to us in vain, +As in revenge, have suck'd up from the sea +Contagious fogs; which falling in the land +Have every pelting river made so proud +That they have overborne their continents: +The ox hath therefore stretch'd his yoke in vain, +The ploughman lost his sweat, and the green corn +Hath rotted ere his youth attain'd a beard; +The fold stands empty in the drowned field, +And crows are fatted with the murrion flock; +The nine men's morris is fill'd up with mud, +And the quaint mazes in the wanton green +For lack of tread are undistinguishable: +The human mortals want their winter here; +No night is now with hymn or carol blest: +Therefore the moon, the governess of floods, +Pale in her anger, washes all the air, +That rheumatic diseases do abound: +And thorough this distemperature we see +The seasons alter: hoary-headed frosts +Far in the fresh lap of the crimson rose, +And on old Hiems' thin and icy crown +An odorous chaplet of sweet summer buds +Is, as in mockery, set: the spring, the summer, +The childing autumn, angry winter, change +Their wonted liveries, and the mazed world, +By their increase, now knows not which is which: +And this same progeny of evils comes +From our debate, from our dissension; +We are their parents and original. + + + +OBERON +Do you amend it then; it lies in you: +Why should Titania cross her Oberon? +I do but beg a little changeling boy, +To be my henchman. + + + +TITANIA +Set your heart at rest: +The fairy land buys not the child of me. +His mother was a votaress of my order: +And, in the spiced Indian air, by night, +Full often hath she gossip'd by my side, +And sat with me on Neptune's yellow sands, +Marking the embarked traders on the flood, +When we have laugh'd to see the sails conceive +And grow big-bellied with the wanton wind; +Which she, with pretty and with swimming gait +Following,--her womb then rich with my young squire,-- +Would imitate, and sail upon the land, +To fetch me trifles, and return again, +As from a voyage, rich with merchandise. +But she, being mortal, of that boy did die; +And for her sake do I rear up her boy, +And for her sake I will not part with him. + + + +OBERON +How long within this wood intend you stay? + + + +TITANIA +Perchance till after Theseus' wedding-day. +If you will patiently dance in our round +And see our moonlight revels, go with us; +If not, shun me, and I will spare your haunts. + + + +OBERON +Give me that boy, and I will go with thee. + + + +TITANIA +Not for thy fairy kingdom. Fairies, away! +We shall chide downright, if I longer stay. + + + +Exit TITANIA with her train + + +OBERON +Well, go thy way: thou shalt not from this grove +Till I torment thee for this injury. +My gentle Puck, come hither. Thou rememberest +Since once I sat upon a promontory, +And heard a mermaid on a dolphin's back +Uttering such dulcet and harmonious breath +That the rude sea grew civil at her song +And certain stars shot madly from their spheres, +To hear the sea-maid's music. + + + +PUCK +I remember. + + + +OBERON +That very time I saw, but thou couldst not, +Flying between the cold moon and the earth, +Cupid all arm'd: a certain aim he took +At a fair vestal throned by the west, +And loosed his love-shaft smartly from his bow, +As it should pierce a hundred thousand hearts; +But I might see young Cupid's fiery shaft +Quench'd in the chaste beams of the watery moon, +And the imperial votaress passed on, +In maiden meditation, fancy-free. +Yet mark'd I where the bolt of Cupid fell: +It fell upon a little western flower, +Before milk-white, now purple with love's wound, +And maidens call it love-in-idleness. +Fetch me that flower; the herb I shew'd thee once: +The juice of it on sleeping eye-lids laid +Will make or man or woman madly dote +Upon the next live creature that it sees. +Fetch me this herb; and be thou here again +Ere the leviathan can swim a league. + + + +PUCK +I'll put a girdle round about the earth +In forty minutes. + + + +Exit + + +OBERON +Having once this juice, +I'll watch Titania when she is asleep, +And drop the liquor of it in her eyes. +The next thing then she waking looks upon, +Be it on lion, bear, or wolf, or bull, +On meddling monkey, or on busy ape, +She shall pursue it with the soul of love: +And ere I take this charm from off her sight, +As I can take it with another herb, +I'll make her render up her page to me. +But who comes here? I am invisible; +And I will overhear their conference. + + + +Enter DEMETRIUS, HELENA, following him + + +DEMETRIUS +I love thee not, therefore pursue me not. +Where is Lysander and fair Hermia? +The one I'll slay, the other slayeth me. +Thou told'st me they were stolen unto this wood; +And here am I, and wode within this wood, +Because I cannot meet my Hermia. +Hence, get thee gone, and follow me no more. + + + +HELENA +You draw me, you hard-hearted adamant; +But yet you draw not iron, for my heart +Is true as steel: leave you your power to draw, +And I shall have no power to follow you. + + + +DEMETRIUS +Do I entice you? do I speak you fair? +Or, rather, do I not in plainest truth +Tell you, I do not, nor I cannot love you? + + + +HELENA +And even for that do I love you the more. +I am your spaniel; and, Demetrius, +The more you beat me, I will fawn on you: +Use me but as your spaniel, spurn me, strike me, +Neglect me, lose me; only give me leave, +Unworthy as I am, to follow you. +What worser place can I beg in your love,-- +And yet a place of high respect with me,-- +Than to be used as you use your dog? + + + +DEMETRIUS +Tempt not too much the hatred of my spirit; +For I am sick when I do look on thee. + + + +HELENA +And I am sick when I look not on you. + + + +DEMETRIUS +You do impeach your modesty too much, +To leave the city and commit yourself +Into the hands of one that loves you not; +To trust the opportunity of night +And the ill counsel of a desert place +With the rich worth of your virginity. + + + +HELENA +Your virtue is my privilege: for that +It is not night when I do see your face, +Therefore I think I am not in the night; +Nor doth this wood lack worlds of company, +For you in my respect are all the world: +Then how can it be said I am alone, +When all the world is here to look on me? + + + +DEMETRIUS +I'll run from thee and hide me in the brakes, +And leave thee to the mercy of wild beasts. + + + +HELENA +The wildest hath not such a heart as you. +Run when you will, the story shall be changed: +Apollo flies, and Daphne holds the chase; +The dove pursues the griffin; the mild hind +Makes speed to catch the tiger; bootless speed, +When cowardice pursues and valour flies. + + + +DEMETRIUS +I will not stay thy questions; let me go: +Or, if thou follow me, do not believe +But I shall do thee mischief in the wood. + + + +HELENA +Ay, in the temple, in the town, the field, +You do me mischief. Fie, Demetrius! +Your wrongs do set a scandal on my sex: +We cannot fight for love, as men may do; +We should be wood and were not made to woo. +Exit DEMETRIUS +I'll follow thee and make a heaven of hell, +To die upon the hand I love so well. + + + +Exit + + +OBERON +Fare thee well, nymph: ere he do leave this grove, +Thou shalt fly him and he shall seek thy love. +Re-enter PUCK +Hast thou the flower there? Welcome, wanderer. + + + +PUCK +Ay, there it is. + + + +OBERON +I pray thee, give it me. +I know a bank where the wild thyme blows, +Where oxlips and the nodding violet grows, +Quite over-canopied with luscious woodbine, +With sweet musk-roses and with eglantine: +There sleeps Titania sometime of the night, +Lull'd in these flowers with dances and delight; +And there the snake throws her enamell'd skin, +Weed wide enough to wrap a fairy in: +And with the juice of this I'll streak her eyes, +And make her full of hateful fantasies. +Take thou some of it, and seek through this grove: +A sweet Athenian lady is in love +With a disdainful youth: anoint his eyes; +But do it when the next thing he espies +May be the lady: thou shalt know the man +By the Athenian garments he hath on. +Effect it with some care, that he may prove +More fond on her than she upon her love: +And look thou meet me ere the first cock crow. + + + +PUCK +Fear not, my lord, your servant shall do so. + + + +Exeunt + + +SCENE II. Another part of the wood. +Enter TITANIA, with her train + + +TITANIA +Come, now a roundel and a fairy song; +Then, for the third part of a minute, hence; +Some to kill cankers in the musk-rose buds, +Some war with rere-mice for their leathern wings, +To make my small elves coats, and some keep back +The clamorous owl that nightly hoots and wonders +At our quaint spirits. Sing me now asleep; +Then to your offices and let me rest. +The Fairies sing +You spotted snakes with double tongue, +Thorny hedgehogs, be not seen; +Newts and blind-worms, do no wrong, +Come not near our fairy queen. +Philomel, with melody +Sing in our sweet lullaby; +Lulla, lulla, lullaby, lulla, lulla, lullaby: +Never harm, +Nor spell nor charm, +Come our lovely lady nigh; +So, good night, with lullaby. +Weaving spiders, come not here; +Hence, you long-legg'd spinners, hence! +Beetles black, approach not near; +Worm nor snail, do no offence. +Philomel, with melody, &c. + + + +Fairy +Hence, away! now all is well: +One aloof stand sentinel. + + +Exeunt Fairies. TITANIA sleeps +Enter OBERON and squeezes the flower on TITANIA's eyelids + + +OBERON +What thou seest when thou dost wake, +Do it for thy true-love take, +Love and languish for his sake: +Be it ounce, or cat, or bear, +Pard, or boar with bristled hair, +In thy eye that shall appear +When thou wakest, it is thy dear: +Wake when some vile thing is near. + + +Exit +Enter LYSANDER and HERMIA + + +LYSANDER +Fair love, you faint with wandering in the wood; +And to speak troth, I have forgot our way: +We'll rest us, Hermia, if you think it good, +And tarry for the comfort of the day. + + + +HERMIA +Be it so, Lysander: find you out a bed; +For I upon this bank will rest my head. + + + +LYSANDER +One turf shall serve as pillow for us both; +One heart, one bed, two bosoms and one troth. + + + +HERMIA +Nay, good Lysander; for my sake, my dear, +Lie further off yet, do not lie so near. + + + +LYSANDER +O, take the sense, sweet, of my innocence! +Love takes the meaning in love's conference. +I mean, that my heart unto yours is knit +So that but one heart we can make of it; +Two bosoms interchained with an oath; +So then two bosoms and a single troth. +Then by your side no bed-room me deny; +For lying so, Hermia, I do not lie. + + + +HERMIA +Lysander riddles very prettily: +Now much beshrew my manners and my pride, +If Hermia meant to say Lysander lied. +But, gentle friend, for love and courtesy +Lie further off; in human modesty, +Such separation as may well be said +Becomes a virtuous bachelor and a maid, +So far be distant; and, good night, sweet friend: +Thy love ne'er alter till thy sweet life end! + + + +LYSANDER +Amen, amen, to that fair prayer, say I; +And then end life when I end loyalty! +Here is my bed: sleep give thee all his rest! + + + +HERMIA +With half that wish the wisher's eyes be press'd! + + +They sleep +Enter PUCK + + +PUCK +Through the forest have I gone. +But Athenian found I none, +On whose eyes I might approve +This flower's force in stirring love. +Night and silence.--Who is here? +Weeds of Athens he doth wear: +This is he, my master said, +Despised the Athenian maid; +And here the maiden, sleeping sound, +On the dank and dirty ground. +Pretty soul! she durst not lie +Near this lack-love, this kill-courtesy. +Churl, upon thy eyes I throw +All the power this charm doth owe. +When thou wakest, let love forbid +Sleep his seat on thy eyelid: +So awake when I am gone; +For I must now to Oberon. + + +Exit +Enter DEMETRIUS and HELENA, running + + +HELENA +Stay, though thou kill me, sweet Demetrius. + + + +DEMETRIUS +I charge thee, hence, and do not haunt me thus. + + + +HELENA +O, wilt thou darkling leave me? do not so. + + + +DEMETRIUS +Stay, on thy peril: I alone will go. + + + +Exit + + +HELENA +O, I am out of breath in this fond chase! +The more my prayer, the lesser is my grace. +Happy is Hermia, wheresoe'er she lies; +For she hath blessed and attractive eyes. +How came her eyes so bright? Not with salt tears: +If so, my eyes are oftener wash'd than hers. +No, no, I am as ugly as a bear; +For beasts that meet me run away for fear: +Therefore no marvel though Demetrius +Do, as a monster fly my presence thus. +What wicked and dissembling glass of mine +Made me compare with Hermia's sphery eyne? +But who is here? Lysander! on the ground! +Dead? or asleep? I see no blood, no wound. +Lysander if you live, good sir, awake. + + + +LYSANDER +Awaking And run through fire I will for thy sweet sake. +Transparent Helena! Nature shows art, +That through thy bosom makes me see thy heart. +Where is Demetrius? O, how fit a word +Is that vile name to perish on my sword! + + + +HELENA +Do not say so, Lysander; say not so +What though he love your Hermia? Lord, what though? +Yet Hermia still loves you: then be content. + + + +LYSANDER +Content with Hermia! No; I do repent +The tedious minutes I with her have spent. +Not Hermia but Helena I love: +Who will not change a raven for a dove? +The will of man is by his reason sway'd; +And reason says you are the worthier maid. +Things growing are not ripe until their season +So I, being young, till now ripe not to reason; +And touching now the point of human skill, +Reason becomes the marshal to my will +And leads me to your eyes, where I o'erlook +Love's stories written in love's richest book. + + + +HELENA +Wherefore was I to this keen mockery born? +When at your hands did I deserve this scorn? +Is't not enough, is't not enough, young man, +That I did never, no, nor never can, +Deserve a sweet look from Demetrius' eye, +But you must flout my insufficiency? +Good troth, you do me wrong, good sooth, you do, +In such disdainful manner me to woo. +But fare you well: perforce I must confess +I thought you lord of more true gentleness. +O, that a lady, of one man refused. +Should of another therefore be abused! + + + +Exit + + +LYSANDER +She sees not Hermia. Hermia, sleep thou there: +And never mayst thou come Lysander near! +For as a surfeit of the sweetest things +The deepest loathing to the stomach brings, +Or as tie heresies that men do leave +Are hated most of those they did deceive, +So thou, my surfeit and my heresy, +Of all be hated, but the most of me! +And, all my powers, address your love and might +To honour Helen and to be her knight! + + + +Exit + + +HERMIA +Awaking Help me, Lysander, help me! do thy best +To pluck this crawling serpent from my breast! +Ay me, for pity! what a dream was here! +Lysander, look how I do quake with fear: +Methought a serpent eat my heart away, +And you sat smiling at his cruel pray. +Lysander! what, removed? Lysander! lord! +What, out of hearing? gone? no sound, no word? +Alack, where are you speak, an if you hear; +Speak, of all loves! I swoon almost with fear. +No? then I well perceive you all not nigh +Either death or you I'll find immediately. + + + +Exit + + + + +ACT III + +SCENE I. The wood. TITANIA lying asleep. +Enter QUINCE, SNUG, BOTTOM, FLUTE, SNOUT, and +STARVELING + + +BOTTOM +Are we all met? + + + +QUINCE +Pat, pat; and here's a marvellous convenient place +for our rehearsal. This green plot shall be our +stage, this hawthorn-brake our tiring-house; and we +will do it in action as we will do it before the duke. + + + +BOTTOM +Peter Quince,-- + + + +QUINCE +What sayest thou, bully Bottom? + + + +BOTTOM +There are things in this comedy of Pyramus and +Thisby that will never please. First, Pyramus must +draw a sword to kill himself; which the ladies +cannot abide. How answer you that? + + + +SNOUT +By'r lakin, a parlous fear. + + + +STARVELING +I believe we must leave the killing out, when all is done. + + + +BOTTOM +Not a whit: I have a device to make all well. +Write me a prologue; and let the prologue seem to +say, we will do no harm with our swords, and that +Pyramus is not killed indeed; and, for the more +better assurance, tell them that I, Pyramus, am not +Pyramus, but Bottom the weaver: this will put them +out of fear. + + + +QUINCE +Well, we will have such a prologue; and it shall be +written in eight and six. + + + +BOTTOM +No, make it two more; let it be written in eight and eight. + + + +SNOUT +Will not the ladies be afeard of the lion? + + + +STARVELING +I fear it, I promise you. + + + +BOTTOM +Masters, you ought to consider with yourselves: to +bring in--God shield us!--a lion among ladies, is a +most dreadful thing; for there is not a more fearful +wild-fowl than your lion living; and we ought to +look to 't. + + + +SNOUT +Therefore another prologue must tell he is not a lion. + + + +BOTTOM +Nay, you must name his name, and half his face must +be seen through the lion's neck: and he himself +must speak through, saying thus, or to the same +defect,--'Ladies,'--or 'Fair-ladies--I would wish +You,'--or 'I would request you,'--or 'I would +entreat you,--not to fear, not to tremble: my life +for yours. If you think I come hither as a lion, it +were pity of my life: no I am no such thing; I am a +man as other men are;' and there indeed let him name +his name, and tell them plainly he is Snug the joiner. + + + +QUINCE +Well it shall be so. But there is two hard things; +that is, to bring the moonlight into a chamber; for, +you know, Pyramus and Thisby meet by moonlight. + + + +SNOUT +Doth the moon shine that night we play our play? + + + +BOTTOM +A calendar, a calendar! look in the almanac; find +out moonshine, find out moonshine. + + + +QUINCE +Yes, it doth shine that night. + + + +BOTTOM +Why, then may you leave a casement of the great +chamber window, where we play, open, and the moon +may shine in at the casement. + + + +QUINCE +Ay; or else one must come in with a bush of thorns +and a lanthorn, and say he comes to disfigure, or to +present, the person of Moonshine. Then, there is +another thing: we must have a wall in the great +chamber; for Pyramus and Thisby says the story, did +talk through the chink of a wall. + + + +SNOUT +You can never bring in a wall. What say you, Bottom? + + + +BOTTOM +Some man or other must present Wall: and let him +have some plaster, or some loam, or some rough-cast +about him, to signify wall; and let him hold his +fingers thus, and through that cranny shall Pyramus +and Thisby whisper. + + + +QUINCE +If that may be, then all is well. Come, sit down, +every mother's son, and rehearse your parts. +Pyramus, you begin: when you have spoken your +speech, enter into that brake: and so every one +according to his cue. + + + +Enter PUCK behind + + +PUCK +What hempen home-spuns have we swaggering here, +So near the cradle of the fairy queen? +What, a play toward! I'll be an auditor; +An actor too, perhaps, if I see cause. + + + +QUINCE +Speak, Pyramus. Thisby, stand forth. + + + +BOTTOM +Thisby, the flowers of odious savours sweet,-- + + + +QUINCE +Odours, odours. + + + +BOTTOM +--odours savours sweet: +So hath thy breath, my dearest Thisby dear. +But hark, a voice! stay thou but here awhile, +And by and by I will to thee appear. + + + +Exit + + +PUCK +A stranger Pyramus than e'er played here. + + + +Exit + + +FLUTE +Must I speak now? + + + +QUINCE +Ay, marry, must you; for you must understand he goes +but to see a noise that he heard, and is to come again. + + + +FLUTE +Most radiant Pyramus, most lily-white of hue, +Of colour like the red rose on triumphant brier, +Most brisky juvenal and eke most lovely Jew, +As true as truest horse that yet would never tire, +I'll meet thee, Pyramus, at Ninny's tomb. + + + +QUINCE +'Ninus' tomb,' man: why, you must not speak that +yet; that you answer to Pyramus: you speak all your +part at once, cues and all Pyramus enter: your cue +is past; it is, 'never tire.' + + + +FLUTE +O,--As true as truest horse, that yet would +never tire. + + + +Re-enter PUCK, and BOTTOM with an ass's head + + +BOTTOM +If I were fair, Thisby, I were only thine. + + + +QUINCE +O monstrous! O strange! we are haunted. Pray, +masters! fly, masters! Help! + + + +Exeunt QUINCE, SNUG, FLUTE, SNOUT, and STARVELING + + +PUCK +I'll follow you, I'll lead you about a round, +Through bog, through bush, through brake, through brier: +Sometime a horse I'll be, sometime a hound, +A hog, a headless bear, sometime a fire; +And neigh, and bark, and grunt, and roar, and burn, +Like horse, hound, hog, bear, fire, at every turn. + + + +Exit + + +BOTTOM +Why do they run away? this is a knavery of them to +make me afeard. + + + +Re-enter SNOUT + + +SNOUT +O Bottom, thou art changed! what do I see on thee? + + + +BOTTOM +What do you see? you see an asshead of your own, do +you? + + +Exit SNOUT +Re-enter QUINCE + + +QUINCE +Bless thee, Bottom! bless thee! thou art +translated. + + + +Exit + + +BOTTOM +I see their knavery: this is to make an ass of me; +to fright me, if they could. But I will not stir +from this place, do what they can: I will walk up +and down here, and I will sing, that they shall hear +I am not afraid. +Sings +The ousel cock so black of hue, +With orange-tawny bill, +The throstle with his note so true, +The wren with little quill,-- + + + +TITANIA +Awaking What angel wakes me from my flowery bed? + + + +BOTTOM +Sings +The finch, the sparrow and the lark, +The plain-song cuckoo gray, +Whose note full many a man doth mark, +And dares not answer nay;-- +for, indeed, who would set his wit to so foolish +a bird? who would give a bird the lie, though he cry +'cuckoo' never so? + + + +TITANIA +I pray thee, gentle mortal, sing again: +Mine ear is much enamour'd of thy note; +So is mine eye enthralled to thy shape; +And thy fair virtue's force perforce doth move me +On the first view to say, to swear, I love thee. + + + +BOTTOM +Methinks, mistress, you should have little reason +for that: and yet, to say the truth, reason and +love keep little company together now-a-days; the +more the pity that some honest neighbours will not +make them friends. Nay, I can gleek upon occasion. + + + +TITANIA +Thou art as wise as thou art beautiful. + + + +BOTTOM +Not so, neither: but if I had wit enough to get out +of this wood, I have enough to serve mine own turn. + + + +TITANIA +Out of this wood do not desire to go: +Thou shalt remain here, whether thou wilt or no. +I am a spirit of no common rate; +The summer still doth tend upon my state; +And I do love thee: therefore, go with me; +I'll give thee fairies to attend on thee, +And they shall fetch thee jewels from the deep, +And sing while thou on pressed flowers dost sleep; +And I will purge thy mortal grossness so +That thou shalt like an airy spirit go. +Peaseblossom! Cobweb! Moth! and Mustardseed! + + + +Enter PEASEBLOSSOM, COBWEB, MOTH, and MUSTARDSEED + + +PEASEBLOSSOM +Ready. + + + +COBWEB +And I. + + + +MOTH +And I. + + + +MUSTARDSEED +And I. + + + +ALL +Where shall we go? + + + +TITANIA +Be kind and courteous to this gentleman; +Hop in his walks and gambol in his eyes; +Feed him with apricocks and dewberries, +With purple grapes, green figs, and mulberries; +The honey-bags steal from the humble-bees, +And for night-tapers crop their waxen thighs +And light them at the fiery glow-worm's eyes, +To have my love to bed and to arise; +And pluck the wings from Painted butterflies +To fan the moonbeams from his sleeping eyes: +Nod to him, elves, and do him courtesies. + + + +PEASEBLOSSOM +Hail, mortal! + + + +COBWEB +Hail! + + + +MOTH +Hail! + + + +MUSTARDSEED +Hail! + + + +BOTTOM +I cry your worship's mercy, heartily: I beseech your +worship's name. + + + +COBWEB +Cobweb. + + + +BOTTOM +I shall desire you of more acquaintance, good Master +Cobweb: if I cut my finger, I shall make bold with +you. Your name, honest gentleman? + + + +PEASEBLOSSOM +Peaseblossom. + + + +BOTTOM +I pray you, commend me to Mistress Squash, your +mother, and to Master Peascod, your father. Good +Master Peaseblossom, I shall desire you of more +acquaintance too. Your name, I beseech you, sir? + + + +MUSTARDSEED +Mustardseed. + + + +BOTTOM +Good Master Mustardseed, I know your patience well: +that same cowardly, giant-like ox-beef hath +devoured many a gentleman of your house: I promise +you your kindred had made my eyes water ere now. I +desire your more acquaintance, good Master +Mustardseed. + + + +TITANIA +Come, wait upon him; lead him to my bower. +The moon methinks looks with a watery eye; +And when she weeps, weeps every little flower, +Lamenting some enforced chastity. +Tie up my love's tongue bring him silently. + + + +Exeunt + + +SCENE II. Another part of the wood. +Enter OBERON + + +OBERON +I wonder if Titania be awaked; +Then, what it was that next came in her eye, +Which she must dote on in extremity. +Enter PUCK +Here comes my messenger. +How now, mad spirit! +What night-rule now about this haunted grove? + + + +PUCK +My mistress with a monster is in love. +Near to her close and consecrated bower, +While she was in her dull and sleeping hour, +A crew of patches, rude mechanicals, +That work for bread upon Athenian stalls, +Were met together to rehearse a play +Intended for great Theseus' nuptial-day. +The shallowest thick-skin of that barren sort, +Who Pyramus presented, in their sport +Forsook his scene and enter'd in a brake +When I did him at this advantage take, +An ass's nole I fixed on his head: +Anon his Thisbe must be answered, +And forth my mimic comes. When they him spy, +As wild geese that the creeping fowler eye, +Or russet-pated choughs, many in sort, +Rising and cawing at the gun's report, +Sever themselves and madly sweep the sky, +So, at his sight, away his fellows fly; +And, at our stamp, here o'er and o'er one falls; +He murder cries and help from Athens calls. +Their sense thus weak, lost with their fears +thus strong, +Made senseless things begin to do them wrong; +For briers and thorns at their apparel snatch; +Some sleeves, some hats, from yielders all +things catch. +I led them on in this distracted fear, +And left sweet Pyramus translated there: +When in that moment, so it came to pass, +Titania waked and straightway loved an ass. + + + +OBERON +This falls out better than I could devise. +But hast thou yet latch'd the Athenian's eyes +With the love-juice, as I did bid thee do? + + + +PUCK +I took him sleeping,--that is finish'd too,-- +And the Athenian woman by his side: +That, when he waked, of force she must be eyed. + + + +Enter HERMIA and DEMETRIUS + + +OBERON +Stand close: this is the same Athenian. + + + +PUCK +This is the woman, but not this the man. + + + +DEMETRIUS +O, why rebuke you him that loves you so? +Lay breath so bitter on your bitter foe. + + + +HERMIA +Now I but chide; but I should use thee worse, +For thou, I fear, hast given me cause to curse, +If thou hast slain Lysander in his sleep, +Being o'er shoes in blood, plunge in the deep, +And kill me too. +The sun was not so true unto the day +As he to me: would he have stolen away +From sleeping Hermia? I'll believe as soon +This whole earth may be bored and that the moon +May through the centre creep and so displease +Her brother's noontide with Antipodes. +It cannot be but thou hast murder'd him; +So should a murderer look, so dead, so grim. + + + +DEMETRIUS +So should the murder'd look, and so should I, +Pierced through the heart with your stern cruelty: +Yet you, the murderer, look as bright, as clear, +As yonder Venus in her glimmering sphere. + + + +HERMIA +What's this to my Lysander? where is he? +Ah, good Demetrius, wilt thou give him me? + + + +DEMETRIUS +I had rather give his carcass to my hounds. + + + +HERMIA +Out, dog! out, cur! thou drivest me past the bounds +Of maiden's patience. Hast thou slain him, then? +Henceforth be never number'd among men! +O, once tell true, tell true, even for my sake! +Durst thou have look'd upon him being awake, +And hast thou kill'd him sleeping? O brave touch! +Could not a worm, an adder, do so much? +An adder did it; for with doubler tongue +Than thine, thou serpent, never adder stung. + + + +DEMETRIUS +You spend your passion on a misprised mood: +I am not guilty of Lysander's blood; +Nor is he dead, for aught that I can tell. + + + +HERMIA +I pray thee, tell me then that he is well. + + + +DEMETRIUS +An if I could, what should I get therefore? + + + +HERMIA +A privilege never to see me more. +And from thy hated presence part I so: +See me no more, whether he be dead or no. + + + +Exit + + +DEMETRIUS +There is no following her in this fierce vein: +Here therefore for a while I will remain. +So sorrow's heaviness doth heavier grow +For debt that bankrupt sleep doth sorrow owe: +Which now in some slight measure it will pay, +If for his tender here I make some stay. + + + +Lies down and sleeps + + +OBERON +What hast thou done? thou hast mistaken quite +And laid the love-juice on some true-love's sight: +Of thy misprision must perforce ensue +Some true love turn'd and not a false turn'd true. + + + +PUCK +Then fate o'er-rules, that, one man holding troth, +A million fail, confounding oath on oath. + + + +OBERON +About the wood go swifter than the wind, +And Helena of Athens look thou find: +All fancy-sick she is and pale of cheer, +With sighs of love, that costs the fresh blood dear: +By some illusion see thou bring her here: +I'll charm his eyes against she do appear. + + + +PUCK +I go, I go; look how I go, +Swifter than arrow from the Tartar's bow. + + + +Exit + + +OBERON +Flower of this purple dye, +Hit with Cupid's archery, +Sink in apple of his eye. +When his love he doth espy, +Let her shine as gloriously +As the Venus of the sky. +When thou wakest, if she be by, +Beg of her for remedy. + + + +Re-enter PUCK + + +PUCK +Captain of our fairy band, +Helena is here at hand; +And the youth, mistook by me, +Pleading for a lover's fee. +Shall we their fond pageant see? +Lord, what fools these mortals be! + + + +OBERON +Stand aside: the noise they make +Will cause Demetrius to awake. + + + +PUCK +Then will two at once woo one; +That must needs be sport alone; +And those things do best please me +That befal preposterously. + + + +Enter LYSANDER and HELENA + + +LYSANDER +Why should you think that I should woo in scorn? +Scorn and derision never come in tears: +Look, when I vow, I weep; and vows so born, +In their nativity all truth appears. +How can these things in me seem scorn to you, +Bearing the badge of faith, to prove them true? + + + +HELENA +You do advance your cunning more and more. +When truth kills truth, O devilish-holy fray! +These vows are Hermia's: will you give her o'er? +Weigh oath with oath, and you will nothing weigh: +Your vows to her and me, put in two scales, +Will even weigh, and both as light as tales. + + + +LYSANDER +I had no judgment when to her I swore. + + + +HELENA +Nor none, in my mind, now you give her o'er. + + + +LYSANDER +Demetrius loves her, and he loves not you. + + + +DEMETRIUS +Awaking O Helena, goddess, nymph, perfect, divine! +To what, my love, shall I compare thine eyne? +Crystal is muddy. O, how ripe in show +Thy lips, those kissing cherries, tempting grow! +That pure congealed white, high Taurus snow, +Fann'd with the eastern wind, turns to a crow +When thou hold'st up thy hand: O, let me kiss +This princess of pure white, this seal of bliss! + + + +HELENA +O spite! O hell! I see you all are bent +To set against me for your merriment: +If you we re civil and knew courtesy, +You would not do me thus much injury. +Can you not hate me, as I know you do, +But you must join in souls to mock me too? +If you were men, as men you are in show, +You would not use a gentle lady so; +To vow, and swear, and superpraise my parts, +When I am sure you hate me with your hearts. +You both are rivals, and love Hermia; +And now both rivals, to mock Helena: +A trim exploit, a manly enterprise, +To conjure tears up in a poor maid's eyes +With your derision! none of noble sort +Would so offend a virgin, and extort +A poor soul's patience, all to make you sport. + + + +LYSANDER +You are unkind, Demetrius; be not so; +For you love Hermia; this you know I know: +And here, with all good will, with all my heart, +In Hermia's love I yield you up my part; +And yours of Helena to me bequeath, +Whom I do love and will do till my death. + + + +HELENA +Never did mockers waste more idle breath. + + + +DEMETRIUS +Lysander, keep thy Hermia; I will none: +If e'er I loved her, all that love is gone. +My heart to her but as guest-wise sojourn'd, +And now to Helen is it home return'd, +There to remain. + + + +LYSANDER +Helen, it is not so. + + + +DEMETRIUS +Disparage not the faith thou dost not know, +Lest, to thy peril, thou aby it dear. +Look, where thy love comes; yonder is thy dear. + + + +Re-enter HERMIA + + +HERMIA +Dark night, that from the eye his function takes, +The ear more quick of apprehension makes; +Wherein it doth impair the seeing sense, +It pays the hearing double recompense. +Thou art not by mine eye, Lysander, found; +Mine ear, I thank it, brought me to thy sound +But why unkindly didst thou leave me so? + + + +LYSANDER +Why should he stay, whom love doth press to go? + + + +HERMIA +What love could press Lysander from my side? + + + +LYSANDER +Lysander's love, that would not let him bide, +Fair Helena, who more engilds the night +Than all you fiery oes and eyes of light. +Why seek'st thou me? could not this make thee know, +The hate I bear thee made me leave thee so? + + + +HERMIA +You speak not as you think: it cannot be. + + + +HELENA +Lo, she is one of this confederacy! +Now I perceive they have conjoin'd all three +To fashion this false sport, in spite of me. +Injurious Hermia! most ungrateful maid! +Have you conspired, have you with these contrived +To bait me with this foul derision? +Is all the counsel that we two have shared, +The sisters' vows, the hours that we have spent, +When we have chid the hasty-footed time +For parting us,--O, is it all forgot? +All school-days' friendship, childhood innocence? +We, Hermia, like two artificial gods, +Have with our needles created both one flower, +Both on one sampler, sitting on one cushion, +Both warbling of one song, both in one key, +As if our hands, our sides, voices and minds, +Had been incorporate. So we grow together, +Like to a double cherry, seeming parted, +But yet an union in partition; +Two lovely berries moulded on one stem; +So, with two seeming bodies, but one heart; +Two of the first, like coats in heraldry, +Due but to one and crowned with one crest. +And will you rent our ancient love asunder, +To join with men in scorning your poor friend? +It is not friendly, 'tis not maidenly: +Our sex, as well as I, may chide you for it, +Though I alone do feel the injury. + + + +HERMIA +I am amazed at your passionate words. +I scorn you not: it seems that you scorn me. + + + +HELENA +Have you not set Lysander, as in scorn, +To follow me and praise my eyes and face? +And made your other love, Demetrius, +Who even but now did spurn me with his foot, +To call me goddess, nymph, divine and rare, +Precious, celestial? Wherefore speaks he this +To her he hates? and wherefore doth Lysander +Deny your love, so rich within his soul, +And tender me, forsooth, affection, +But by your setting on, by your consent? +What thought I be not so in grace as you, +So hung upon with love, so fortunate, +But miserable most, to love unloved? +This you should pity rather than despise. + + + +HERNIA +I understand not what you mean by this. + + + +HELENA +Ay, do, persever, counterfeit sad looks, +Make mouths upon me when I turn my back; +Wink each at other; hold the sweet jest up: +This sport, well carried, shall be chronicled. +If you have any pity, grace, or manners, +You would not make me such an argument. +But fare ye well: 'tis partly my own fault; +Which death or absence soon shall remedy. + + + +LYSANDER +Stay, gentle Helena; hear my excuse: +My love, my life my soul, fair Helena! + + + +HELENA +O excellent! + + + +HERMIA +Sweet, do not scorn her so. + + + +DEMETRIUS +If she cannot entreat, I can compel. + + + +LYSANDER +Thou canst compel no more than she entreat: +Thy threats have no more strength than her weak prayers. +Helen, I love thee; by my life, I do: +I swear by that which I will lose for thee, +To prove him false that says I love thee not. + + + +DEMETRIUS +I say I love thee more than he can do. + + + +LYSANDER +If thou say so, withdraw, and prove it too. + + + +DEMETRIUS +Quick, come! + + + +HERMIA +Lysander, whereto tends all this? + + + +LYSANDER +Away, you Ethiope! + + + +DEMETRIUS +No, no; he'll +Seem to break loose; take on as you would follow, +But yet come not: you are a tame man, go! + + + +LYSANDER +Hang off, thou cat, thou burr! vile thing, let loose, +Or I will shake thee from me like a serpent! + + + +HERMIA +Why are you grown so rude? what change is this? +Sweet love,-- + + + +LYSANDER +Thy love! out, tawny Tartar, out! +Out, loathed medicine! hated potion, hence! + + + +HERMIA +Do you not jest? + + + +HELENA +Yes, sooth; and so do you. + + + +LYSANDER +Demetrius, I will keep my word with thee. + + + +DEMETRIUS +I would I had your bond, for I perceive +A weak bond holds you: I'll not trust your word. + + + +LYSANDER +What, should I hurt her, strike her, kill her dead? +Although I hate her, I'll not harm her so. + + + +HERMIA +What, can you do me greater harm than hate? +Hate me! wherefore? O me! what news, my love! +Am not I Hermia? are not you Lysander? +I am as fair now as I was erewhile. +Since night you loved me; yet since night you left +me: +Why, then you left me--O, the gods forbid!-- +In earnest, shall I say? + + + +LYSANDER +Ay, by my life; +And never did desire to see thee more. +Therefore be out of hope, of question, of doubt; +Be certain, nothing truer; 'tis no jest +That I do hate thee and love Helena. + + + +HERMIA +O me! you juggler! you canker-blossom! +You thief of love! what, have you come by night +And stolen my love's heart from him? + + + +HELENA +Fine, i'faith! +Have you no modesty, no maiden shame, +No touch of bashfulness? What, will you tear +Impatient answers from my gentle tongue? +Fie, fie! you counterfeit, you puppet, you! + + + +HERMIA +Puppet? why so? ay, that way goes the game. +Now I perceive that she hath made compare +Between our statures; she hath urged her height; +And with her personage, her tall personage, +Her height, forsooth, she hath prevail'd with him. +And are you grown so high in his esteem; +Because I am so dwarfish and so low? +How low am I, thou painted maypole? speak; +How low am I? I am not yet so low +But that my nails can reach unto thine eyes. + + + +HELENA +I pray you, though you mock me, gentlemen, +Let her not hurt me: I was never curst; +I have no gift at all in shrewishness; +I am a right maid for my cowardice: +Let her not strike me. You perhaps may think, +Because she is something lower than myself, +That I can match her. + + + +HERMIA +Lower! hark, again. + + + +HELENA +Good Hermia, do not be so bitter with me. +I evermore did love you, Hermia, +Did ever keep your counsels, never wrong'd you; +Save that, in love unto Demetrius, +I told him of your stealth unto this wood. +He follow'd you; for love I follow'd him; +But he hath chid me hence and threaten'd me +To strike me, spurn me, nay, to kill me too: +And now, so you will let me quiet go, +To Athens will I bear my folly back +And follow you no further: let me go: +You see how simple and how fond I am. + + + +HERMIA +Why, get you gone: who is't that hinders you? + + + +HELENA +A foolish heart, that I leave here behind. + + + +HERMIA +What, with Lysander? + + + +HELENA +With Demetrius. + + + +LYSANDER +Be not afraid; she shall not harm thee, Helena. + + + +DEMETRIUS +No, sir, she shall not, though you take her part. + + + +HELENA +O, when she's angry, she is keen and shrewd! +She was a vixen when she went to school; +And though she be but little, she is fierce. + + + +HERMIA +'Little' again! nothing but 'low' and 'little'! +Why will you suffer her to flout me thus? +Let me come to her. + + + +LYSANDER +Get you gone, you dwarf; +You minimus, of hindering knot-grass made; +You bead, you acorn. + + + +DEMETRIUS +You are too officious +In her behalf that scorns your services. +Let her alone: speak not of Helena; +Take not her part; for, if thou dost intend +Never so little show of love to her, +Thou shalt aby it. + + + +LYSANDER +Now she holds me not; +Now follow, if thou darest, to try whose right, +Of thine or mine, is most in Helena. + + + +DEMETRIUS +Follow! nay, I'll go with thee, cheek by jole. + + + +Exeunt LYSANDER and DEMETRIUS + + +HERMIA +You, mistress, all this coil is 'long of you: +Nay, go not back. + + + +HELENA +I will not trust you, I, +Nor longer stay in your curst company. +Your hands than mine are quicker for a fray, +My legs are longer though, to run away. + + + +Exit + + +HERMIA +I am amazed, and know not what to say. + + + +Exit + + +OBERON +This is thy negligence: still thou mistakest, +Or else committ'st thy knaveries wilfully. + + + +PUCK +Believe me, king of shadows, I mistook. +Did not you tell me I should know the man +By the Athenian garment be had on? +And so far blameless proves my enterprise, +That I have 'nointed an Athenian's eyes; +And so far am I glad it so did sort +As this their jangling I esteem a sport. + + + +OBERON +Thou see'st these lovers seek a place to fight: +Hie therefore, Robin, overcast the night; +The starry welkin cover thou anon +With drooping fog as black as Acheron, +And lead these testy rivals so astray +As one come not within another's way. +Like to Lysander sometime frame thy tongue, +Then stir Demetrius up with bitter wrong; +And sometime rail thou like Demetrius; +And from each other look thou lead them thus, +Till o'er their brows death-counterfeiting sleep +With leaden legs and batty wings doth creep: +Then crush this herb into Lysander's eye; +Whose liquor hath this virtuous property, +To take from thence all error with his might, +And make his eyeballs roll with wonted sight. +When they next wake, all this derision +Shall seem a dream and fruitless vision, +And back to Athens shall the lovers wend, +With league whose date till death shall never end. +Whiles I in this affair do thee employ, +I'll to my queen and beg her Indian boy; +And then I will her charmed eye release +From monster's view, and all things shall be peace. + + + +PUCK +My fairy lord, this must be done with haste, +For night's swift dragons cut the clouds full fast, +And yonder shines Aurora's harbinger; +At whose approach, ghosts, wandering here and there, +Troop home to churchyards: damned spirits all, +That in crossways and floods have burial, +Already to their wormy beds are gone; +For fear lest day should look their shames upon, +They willfully themselves exile from light +And must for aye consort with black-brow'd night. + + + +OBERON +But we are spirits of another sort: +I with the morning's love have oft made sport, +And, like a forester, the groves may tread, +Even till the eastern gate, all fiery-red, +Opening on Neptune with fair blessed beams, +Turns into yellow gold his salt green streams. +But, notwithstanding, haste; make no delay: +We may effect this business yet ere day. + + + +Exit + + +PUCK +Up and down, up and down, +I will lead them up and down: +I am fear'd in field and town: +Goblin, lead them up and down. +Here comes one. + + + +Re-enter LYSANDER + + +LYSANDER +Where art thou, proud Demetrius? speak thou now. + + + +PUCK +Here, villain; drawn and ready. Where art thou? + + + +LYSANDER +I will be with thee straight. + + + +PUCK +Follow me, then, +To plainer ground. + + +Exit LYSANDER, as following the voice +Re-enter DEMETRIUS + + +DEMETRIUS +Lysander! speak again: +Thou runaway, thou coward, art thou fled? +Speak! In some bush? Where dost thou hide thy head? + + + +PUCK +Thou coward, art thou bragging to the stars, +Telling the bushes that thou look'st for wars, +And wilt not come? Come, recreant; come, thou child; +I'll whip thee with a rod: he is defiled +That draws a sword on thee. + + + +DEMETRIUS +Yea, art thou there? + + + +PUCK +Follow my voice: we'll try no manhood here. + + +Exeunt +Re-enter LYSANDER + + +LYSANDER +He goes before me and still dares me on: +When I come where he calls, then he is gone. +The villain is much lighter-heel'd than I: +I follow'd fast, but faster he did fly; +That fallen am I in dark uneven way, +And here will rest me. +Lies down +Come, thou gentle day! +For if but once thou show me thy grey light, +I'll find Demetrius and revenge this spite. + + +Sleeps +Re-enter PUCK and DEMETRIUS + + +PUCK +Ho, ho, ho! Coward, why comest thou not? + + + +DEMETRIUS +Abide me, if thou darest; for well I wot +Thou runn'st before me, shifting every place, +And darest not stand, nor look me in the face. +Where art thou now? + + + +PUCK +Come hither: I am here. + + + +DEMETRIUS +Nay, then, thou mock'st me. Thou shalt buy this dear, +If ever I thy face by daylight see: +Now, go thy way. Faintness constraineth me +To measure out my length on this cold bed. +By day's approach look to be visited. + + +Lies down and sleeps +Re-enter HELENA + + +HELENA +O weary night, O long and tedious night, +Abate thy hour! Shine comforts from the east, +That I may back to Athens by daylight, +From these that my poor company detest: +And sleep, that sometimes shuts up sorrow's eye, +Steal me awhile from mine own company. + + + +Lies down and sleeps + + +PUCK +Yet but three? Come one more; +Two of both kinds make up four. +Here she comes, curst and sad: +Cupid is a knavish lad, +Thus to make poor females mad. + + + +Re-enter HERMIA + + +HERMIA +Never so weary, never so in woe, +Bedabbled with the dew and torn with briers, +I can no further crawl, no further go; +My legs can keep no pace with my desires. +Here will I rest me till the break of day. +Heavens shield Lysander, if they mean a fray! + + + +Lies down and sleeps + + +PUCK +On the ground +Sleep sound: +I'll apply +To your eye, +Gentle lover, remedy. +Squeezing the juice on LYSANDER's eyes +When thou wakest, +Thou takest +True delight +In the sight +Of thy former lady's eye: +And the country proverb known, +That every man should take his own, +In your waking shall be shown: +Jack shall have Jill; +Nought shall go ill; +The man shall have his mare again, and all shall be well. + + + +Exit + + + + +ACT IV + +SCENE I. The same. LYSANDER, DEMETRIUS, HELENA, and HERMIA lying asleep. +Enter TITANIA and BOTTOM; PEASEBLOSSOM, COBWEB, MOTH, +MUSTARDSEED, and other Fairies attending; OBERON +behind unseen + + +TITANIA +Come, sit thee down upon this flowery bed, +While I thy amiable cheeks do coy, +And stick musk-roses in thy sleek smooth head, +And kiss thy fair large ears, my gentle joy. + + + +BOTTOM +Where's Peaseblossom? + + + +PEASEBLOSSOM +Ready. + + + +BOTTOM +Scratch my head Peaseblossom. Where's Mounsieur Cobweb? + + + +COBWEB +Ready. + + + +BOTTOM +Mounsieur Cobweb, good mounsieur, get you your +weapons in your hand, and kill me a red-hipped +humble-bee on the top of a thistle; and, good +mounsieur, bring me the honey-bag. Do not fret +yourself too much in the action, mounsieur; and, +good mounsieur, have a care the honey-bag break not; +I would be loath to have you overflown with a +honey-bag, signior. Where's Mounsieur Mustardseed? + + + +MUSTARDSEED +Ready. + + + +BOTTOM +Give me your neaf, Mounsieur Mustardseed. Pray you, +leave your courtesy, good mounsieur. + + + +MUSTARDSEED +What's your Will? + + + +BOTTOM +Nothing, good mounsieur, but to help Cavalery Cobweb +to scratch. I must to the barber's, monsieur; for +methinks I am marvellous hairy about the face; and I +am such a tender ass, if my hair do but tickle me, +I must scratch. + + + +TITANIA +What, wilt thou hear some music, +my sweet love? + + + +BOTTOM +I have a reasonable good ear in music. Let's have +the tongs and the bones. + + + +TITANIA +Or say, sweet love, what thou desirest to eat. + + + +BOTTOM +Truly, a peck of provender: I could munch your good +dry oats. Methinks I have a great desire to a bottle +of hay: good hay, sweet hay, hath no fellow. + + + +TITANIA +I have a venturous fairy that shall seek +The squirrel's hoard, and fetch thee new nuts. + + + +BOTTOM +I had rather have a handful or two of dried peas. +But, I pray you, let none of your people stir me: I +have an exposition of sleep come upon me. + + + +TITANIA +Sleep thou, and I will wind thee in my arms. +Fairies, begone, and be all ways away. +Exeunt fairies +So doth the woodbine the sweet honeysuckle +Gently entwist; the female ivy so +Enrings the barky fingers of the elm. +O, how I love thee! how I dote on thee! + + +They sleep +Enter PUCK + + +OBERON +Advancing Welcome, good Robin. +See'st thou this sweet sight? +Her dotage now I do begin to pity: +For, meeting her of late behind the wood, +Seeking sweet favours from this hateful fool, +I did upbraid her and fall out with her; +For she his hairy temples then had rounded +With a coronet of fresh and fragrant flowers; +And that same dew, which sometime on the buds +Was wont to swell like round and orient pearls, +Stood now within the pretty flowerets' eyes +Like tears that did their own disgrace bewail. +When I had at my pleasure taunted her +And she in mild terms begg'd my patience, +I then did ask of her her changeling child; +Which straight she gave me, and her fairy sent +To bear him to my bower in fairy land. +And now I have the boy, I will undo +This hateful imperfection of her eyes: +And, gentle Puck, take this transformed scalp +From off the head of this Athenian swain; +That, he awaking when the other do, +May all to Athens back again repair +And think no more of this night's accidents +But as the fierce vexation of a dream. +But first I will release the fairy queen. +Be as thou wast wont to be; +See as thou wast wont to see: +Dian's bud o'er Cupid's flower +Hath such force and blessed power. +Now, my Titania; wake you, my sweet queen. + + + +TITANIA +My Oberon! what visions have I seen! +Methought I was enamour'd of an ass. + + + +OBERON +There lies your love. + + + +TITANIA +How came these things to pass? +O, how mine eyes do loathe his visage now! + + + +OBERON +Silence awhile. Robin, take off this head. +Titania, music call; and strike more dead +Than common sleep of all these five the sense. + + + +TITANIA +Music, ho! music, such as charmeth sleep! + + + +Music, still + + +PUCK +Now, when thou wakest, with thine +own fool's eyes peep. + + + +OBERON +Sound, music! Come, my queen, take hands with me, +And rock the ground whereon these sleepers be. +Now thou and I are new in amity, +And will to-morrow midnight solemnly +Dance in Duke Theseus' house triumphantly, +And bless it to all fair prosperity: +There shall the pairs of faithful lovers be +Wedded, with Theseus, all in jollity. + + + +PUCK +Fairy king, attend, and mark: +I do hear the morning lark. + + + +OBERON +Then, my queen, in silence sad, +Trip we after the night's shade: +We the globe can compass soon, +Swifter than the wandering moon. + + + +TITANIA +Come, my lord, and in our flight +Tell me how it came this night +That I sleeping here was found +With these mortals on the ground. +Exeunt + + +Horns winded within +Enter THESEUS, HIPPOLYTA, EGEUS, and train + + +THESEUS +Go, one of you, find out the forester; +For now our observation is perform'd; +And since we have the vaward of the day, +My love shall hear the music of my hounds. +Uncouple in the western valley; let them go: +Dispatch, I say, and find the forester. +Exit an Attendant +We will, fair queen, up to the mountain's top, +And mark the musical confusion +Of hounds and echo in conjunction. + + + +HIPPOLYTA +I was with Hercules and Cadmus once, +When in a wood of Crete they bay'd the bear +With hounds of Sparta: never did I hear +Such gallant chiding: for, besides the groves, +The skies, the fountains, every region near +Seem'd all one mutual cry: I never heard +So musical a discord, such sweet thunder. + + + +THESEUS +My hounds are bred out of the Spartan kind, +So flew'd, so sanded, and their heads are hung +With ears that sweep away the morning dew; +Crook-knee'd, and dew-lapp'd like Thessalian bulls; +Slow in pursuit, but match'd in mouth like bells, +Each under each. A cry more tuneable +Was never holla'd to, nor cheer'd with horn, +In Crete, in Sparta, nor in Thessaly: +Judge when you hear. But, soft! what nymphs are these? + + + +EGEUS +My lord, this is my daughter here asleep; +And this, Lysander; this Demetrius is; +This Helena, old Nedar's Helena: +I wonder of their being here together. + + + +THESEUS +No doubt they rose up early to observe +The rite of May, and hearing our intent, +Came here in grace our solemnity. +But speak, Egeus; is not this the day +That Hermia should give answer of her choice? + + + +EGEUS +It is, my lord. + + + +THESEUS +Go, bid the huntsmen wake them with their horns. +Horns and shout within. LYSANDER, DEMETRIUS, +HELENA, and HERMIA wake and start up +Good morrow, friends. Saint Valentine is past: +Begin these wood-birds but to couple now? + + + +LYSANDER +Pardon, my lord. + + + +THESEUS +I pray you all, stand up. +I know you two are rival enemies: +How comes this gentle concord in the world, +That hatred is so far from jealousy, +To sleep by hate, and fear no enmity? + + + +LYSANDER +My lord, I shall reply amazedly, +Half sleep, half waking: but as yet, I swear, +I cannot truly say how I came here; +But, as I think,--for truly would I speak, +And now do I bethink me, so it is,-- +I came with Hermia hither: our intent +Was to be gone from Athens, where we might, +Without the peril of the Athenian law. + + + +EGEUS +Enough, enough, my lord; you have enough: +I beg the law, the law, upon his head. +They would have stolen away; they would, Demetrius, +Thereby to have defeated you and me, +You of your wife and me of my consent, +Of my consent that she should be your wife. + + + +DEMETRIUS +My lord, fair Helen told me of their stealth, +Of this their purpose hither to this wood; +And I in fury hither follow'd them, +Fair Helena in fancy following me. +But, my good lord, I wot not by what power,-- +But by some power it is,--my love to Hermia, +Melted as the snow, seems to me now +As the remembrance of an idle gaud +Which in my childhood I did dote upon; +And all the faith, the virtue of my heart, +The object and the pleasure of mine eye, +Is only Helena. To her, my lord, +Was I betroth'd ere I saw Hermia: +But, like in sickness, did I loathe this food; +But, as in health, come to my natural taste, +Now I do wish it, love it, long for it, +And will for evermore be true to it. + + + +THESEUS +Fair lovers, you are fortunately met: +Of this discourse we more will hear anon. +Egeus, I will overbear your will; +For in the temple by and by with us +These couples shall eternally be knit: +And, for the morning now is something worn, +Our purposed hunting shall be set aside. +Away with us to Athens; three and three, +We'll hold a feast in great solemnity. +Come, Hippolyta. + + + +Exeunt THESEUS, HIPPOLYTA, EGEUS, and train + + +DEMETRIUS +These things seem small and undistinguishable, + + + +HERMIA +Methinks I see these things with parted eye, +When every thing seems double. + + + +HELENA +So methinks: +And I have found Demetrius like a jewel, +Mine own, and not mine own. + + + +DEMETRIUS +Are you sure +That we are awake? It seems to me +That yet we sleep, we dream. Do not you think +The duke was here, and bid us follow him? + + + +HERMIA +Yea; and my father. + + + +HELENA +And Hippolyta. + + + +LYSANDER +And he did bid us follow to the temple. + + + +DEMETRIUS +Why, then, we are awake: let's follow him +And by the way let us recount our dreams. + + + +Exeunt + + +BOTTOM +Awaking When my cue comes, call me, and I will +answer: my next is, 'Most fair Pyramus.' Heigh-ho! +Peter Quince! Flute, the bellows-mender! Snout, +the tinker! Starveling! God's my life, stolen +hence, and left me asleep! I have had a most rare +vision. I have had a dream, past the wit of man to +say what dream it was: man is but an ass, if he go +about to expound this dream. Methought I was--there +is no man can tell what. Methought I was,--and +methought I had,--but man is but a patched fool, if +he will offer to say what methought I had. The eye +of man hath not heard, the ear of man hath not +seen, man's hand is not able to taste, his tongue +to conceive, nor his heart to report, what my dream +was. I will get Peter Quince to write a ballad of +this dream: it shall be called Bottom's Dream, +because it hath no bottom; and I will sing it in the +latter end of a play, before the duke: +peradventure, to make it the more gracious, I shall +sing it at her death. + + + +Exit + + +SCENE II. Athens. QUINCE'S house. +Enter QUINCE, FLUTE, SNOUT, and STARVELING + + +QUINCE +Have you sent to Bottom's house? is he come home yet? + + + +STARVELING +He cannot be heard of. Out of doubt he is +transported. + + + +FLUTE +If he come not, then the play is marred: it goes +not forward, doth it? + + + +QUINCE +It is not possible: you have not a man in all +Athens able to discharge Pyramus but he. + + + +FLUTE +No, he hath simply the best wit of any handicraft +man in Athens. + + + +QUINCE +Yea and the best person too; and he is a very +paramour for a sweet voice. + + + +FLUTE +You must say 'paragon:' a paramour is, God bless us, +a thing of naught. + + + +Enter SNUG + + +SNUG +Masters, the duke is coming from the temple, and +there is two or three lords and ladies more married: +if our sport had gone forward, we had all been made +men. + + + +FLUTE +O sweet bully Bottom! Thus hath he lost sixpence a +day during his life; he could not have 'scaped +sixpence a day: an the duke had not given him +sixpence a day for playing Pyramus, I'll be hanged; +he would have deserved it: sixpence a day in +Pyramus, or nothing. + + + +Enter BOTTOM + + +BOTTOM +Where are these lads? where are these hearts? + + + +QUINCE +Bottom! O most courageous day! O most happy hour! + + + +BOTTOM +Masters, I am to discourse wonders: but ask me not +what; for if I tell you, I am no true Athenian. I +will tell you every thing, right as it fell out. + + + +QUINCE +Let us hear, sweet Bottom. + + + +BOTTOM +Not a word of me. All that I will tell you is, that +the duke hath dined. Get your apparel together, +good strings to your beards, new ribbons to your +pumps; meet presently at the palace; every man look +o'er his part; for the short and the long is, our +play is preferred. In any case, let Thisby have +clean linen; and let not him that plays the lion +pair his nails, for they shall hang out for the +lion's claws. And, most dear actors, eat no onions +nor garlic, for we are to utter sweet breath; and I +do not doubt but to hear them say, it is a sweet +comedy. No more words: away! go, away! + + + +Exeunt + + + + +ACT V + +SCENE I. Athens. The palace of THESEUS. +Enter THESEUS, HIPPOLYTA, PHILOSTRATE, Lords and +Attendants + + +HIPPOLYTA +'Tis strange my Theseus, that these +lovers speak of. + + + +THESEUS +More strange than true: I never may believe +These antique fables, nor these fairy toys. +Lovers and madmen have such seething brains, +Such shaping fantasies, that apprehend +More than cool reason ever comprehends. +The lunatic, the lover and the poet +Are of imagination all compact: +One sees more devils than vast hell can hold, +That is, the madman: the lover, all as frantic, +Sees Helen's beauty in a brow of Egypt: +The poet's eye, in fine frenzy rolling, +Doth glance from heaven to earth, from earth to heaven; +And as imagination bodies forth +The forms of things unknown, the poet's pen +Turns them to shapes and gives to airy nothing +A local habitation and a name. +Such tricks hath strong imagination, +That if it would but apprehend some joy, +It comprehends some bringer of that joy; +Or in the night, imagining some fear, +How easy is a bush supposed a bear! + + + +HIPPOLYTA +But all the story of the night told over, +And all their minds transfigured so together, +More witnesseth than fancy's images +And grows to something of great constancy; +But, howsoever, strange and admirable. + + + +THESEUS +Here come the lovers, full of joy and mirth. +Enter LYSANDER, DEMETRIUS, HERMIA, and HELENA +Joy, gentle friends! joy and fresh days of love +Accompany your hearts! + + + +LYSANDER +More than to us +Wait in your royal walks, your board, your bed! + + + +THESEUS +Come now; what masques, what dances shall we have, +To wear away this long age of three hours +Between our after-supper and bed-time? +Where is our usual manager of mirth? +What revels are in hand? Is there no play, +To ease the anguish of a torturing hour? +Call Philostrate. + + + +PHILOSTRATE +Here, mighty Theseus. + + + +THESEUS +Say, what abridgement have you for this evening? +What masque? what music? How shall we beguile +The lazy time, if not with some delight? + + + +PHILOSTRATE +There is a brief how many sports are ripe: +Make choice of which your highness will see first. + + + +Giving a paper + + +THESEUS +Reads 'The battle with the Centaurs, to be sung +By an Athenian eunuch to the harp.' +We'll none of that: that have I told my love, +In glory of my kinsman Hercules. +Reads +'The riot of the tipsy Bacchanals, +Tearing the Thracian singer in their rage.' +That is an old device; and it was play'd +When I from Thebes came last a conqueror. +Reads +'The thrice three Muses mourning for the death +Of Learning, late deceased in beggary.' +That is some satire, keen and critical, +Not sorting with a nuptial ceremony. +Reads +'A tedious brief scene of young Pyramus +And his love Thisbe; very tragical mirth.' +Merry and tragical! tedious and brief! +That is, hot ice and wondrous strange snow. +How shall we find the concord of this discord? + + + +PHILOSTRATE +A play there is, my lord, some ten words long, +Which is as brief as I have known a play; +But by ten words, my lord, it is too long, +Which makes it tedious; for in all the play +There is not one word apt, one player fitted: +And tragical, my noble lord, it is; +For Pyramus therein doth kill himself. +Which, when I saw rehearsed, I must confess, +Made mine eyes water; but more merry tears +The passion of loud laughter never shed. + + + +THESEUS +What are they that do play it? + + + +PHILOSTRATE +Hard-handed men that work in Athens here, +Which never labour'd in their minds till now, +And now have toil'd their unbreathed memories +With this same play, against your nuptial. + + + +THESEUS +And we will hear it. + + + +PHILOSTRATE +No, my noble lord; +It is not for you: I have heard it over, +And it is nothing, nothing in the world; +Unless you can find sport in their intents, +Extremely stretch'd and conn'd with cruel pain, +To do you service. + + + +THESEUS +I will hear that play; +For never anything can be amiss, +When simpleness and duty tender it. +Go, bring them in: and take your places, ladies. + + + +Exit PHILOSTRATE + + +HIPPOLYTA +I love not to see wretchedness o'er charged +And duty in his service perishing. + + + +THESEUS +Why, gentle sweet, you shall see no such thing. + + + +HIPPOLYTA +He says they can do nothing in this kind. + + + +THESEUS +The kinder we, to give them thanks for nothing. +Our sport shall be to take what they mistake: +And what poor duty cannot do, noble respect +Takes it in might, not merit. +Where I have come, great clerks have purposed +To greet me with premeditated welcomes; +Where I have seen them shiver and look pale, +Make periods in the midst of sentences, +Throttle their practised accent in their fears +And in conclusion dumbly have broke off, +Not paying me a welcome. Trust me, sweet, +Out of this silence yet I pick'd a welcome; +And in the modesty of fearful duty +I read as much as from the rattling tongue +Of saucy and audacious eloquence. +Love, therefore, and tongue-tied simplicity +In least speak most, to my capacity. + + + +Re-enter PHILOSTRATE + + +PHILOSTRATE +So please your grace, the Prologue is address'd. + + + +THESEUS +Let him approach. + + +Flourish of trumpets +Enter QUINCE for the Prologue + + +Prologue +If we offend, it is with our good will. +That you should think, we come not to offend, +But with good will. To show our simple skill, +That is the true beginning of our end. +Consider then we come but in despite. +We do not come as minding to contest you, +Our true intent is. All for your delight +We are not here. That you should here repent you, +The actors are at hand and by their show +You shall know all that you are like to know. + + + +THESEUS +This fellow doth not stand upon points. + + + +LYSANDER +He hath rid his prologue like a rough colt; he knows +not the stop. A good moral, my lord: it is not +enough to speak, but to speak true. + + + +HIPPOLYTA +Indeed he hath played on his prologue like a child +on a recorder; a sound, but not in government. + + + +THESEUS +His speech, was like a tangled chain; nothing +impaired, but all disordered. Who is next? + + + +Enter Pyramus and Thisbe, Wall, Moonshine, and Lion + + +Prologue +Gentles, perchance you wonder at this show; +But wonder on, till truth make all things plain. +This man is Pyramus, if you would know; +This beauteous lady Thisby is certain. +This man, with lime and rough-cast, doth present +Wall, that vile Wall which did these lovers sunder; +And through Wall's chink, poor souls, they are content +To whisper. At the which let no man wonder. +This man, with lanthorn, dog, and bush of thorn, +Presenteth Moonshine; for, if you will know, +By moonshine did these lovers think no scorn +To meet at Ninus' tomb, there, there to woo. +This grisly beast, which Lion hight by name, +The trusty Thisby, coming first by night, +Did scare away, or rather did affright; +And, as she fled, her mantle she did fall, +Which Lion vile with bloody mouth did stain. +Anon comes Pyramus, sweet youth and tall, +And finds his trusty Thisby's mantle slain: +Whereat, with blade, with bloody blameful blade, +He bravely broach'd is boiling bloody breast; +And Thisby, tarrying in mulberry shade, +His dagger drew, and died. For all the rest, +Let Lion, Moonshine, Wall, and lovers twain +At large discourse, while here they do remain. + + + +Exeunt Prologue, Thisbe, Lion, and Moonshine + + +THESEUS +I wonder if the lion be to speak. + + + +DEMETRIUS +No wonder, my lord: one lion may, when many asses do. + + + +Wall +In this same interlude it doth befall +That I, one Snout by name, present a wall; +And such a wall, as I would have you think, +That had in it a crannied hole or chink, +Through which the lovers, Pyramus and Thisby, +Did whisper often very secretly. +This loam, this rough-cast and this stone doth show +That I am that same wall; the truth is so: +And this the cranny is, right and sinister, +Through which the fearful lovers are to whisper. + + + +THESEUS +Would you desire lime and hair to speak better? + + + +DEMETRIUS +It is the wittiest partition that ever I heard +discourse, my lord. + + + +Enter Pyramus + + +THESEUS +Pyramus draws near the wall: silence! + + + +Pyramus +O grim-look'd night! O night with hue so black! +O night, which ever art when day is not! +O night, O night! alack, alack, alack, +I fear my Thisby's promise is forgot! +And thou, O wall, O sweet, O lovely wall, +That stand'st between her father's ground and mine! +Thou wall, O wall, O sweet and lovely wall, +Show me thy chink, to blink through with mine eyne! +Wall holds up his fingers +Thanks, courteous wall: Jove shield thee well for this! +But what see I? No Thisby do I see. +O wicked wall, through whom I see no bliss! +Cursed be thy stones for thus deceiving me! + + + +THESEUS +The wall, methinks, being sensible, should curse again. + + + +Pyramus +No, in truth, sir, he should not. 'Deceiving me' +is Thisby's cue: she is to enter now, and I am to +spy her through the wall. You shall see, it will +fall pat as I told you. Yonder she comes. + + + +Enter Thisbe + + +Thisbe +O wall, full often hast thou heard my moans, +For parting my fair Pyramus and me! +My cherry lips have often kiss'd thy stones, +Thy stones with lime and hair knit up in thee. + + + +Pyramus +I see a voice: now will I to the chink, +To spy an I can hear my Thisby's face. Thisby! + + + +Thisbe +My love thou art, my love I think. + + + +Pyramus +Think what thou wilt, I am thy lover's grace; +And, like Limander, am I trusty still. + + + +Thisbe +And I like Helen, till the Fates me kill. + + + +Pyramus +Not Shafalus to Procrus was so true. + + + +Thisbe +As Shafalus to Procrus, I to you. + + + +Pyramus +O kiss me through the hole of this vile wall! + + + +Thisbe +I kiss the wall's hole, not your lips at all. + + + +Pyramus +Wilt thou at Ninny's tomb meet me straightway? + + + +Thisbe +'Tide life, 'tide death, I come without delay. + + + +Exeunt Pyramus and Thisbe + + +Wall +Thus have I, Wall, my part discharged so; +And, being done, thus Wall away doth go. + + + +Exit + + +THESEUS +Now is the mural down between the two neighbours. + + + +DEMETRIUS +No remedy, my lord, when walls are so wilful to hear +without warning. + + + +HIPPOLYTA +This is the silliest stuff that ever I heard. + + + +THESEUS +The best in this kind are but shadows; and the worst +are no worse, if imagination amend them. + + + +HIPPOLYTA +It must be your imagination then, and not theirs. + + + +THESEUS +If we imagine no worse of them than they of +themselves, they may pass for excellent men. Here +come two noble beasts in, a man and a lion. + + + +Enter Lion and Moonshine + + +Lion +You, ladies, you, whose gentle hearts do fear +The smallest monstrous mouse that creeps on floor, +May now perchance both quake and tremble here, +When lion rough in wildest rage doth roar. +Then know that I, one Snug the joiner, am +A lion-fell, nor else no lion's dam; +For, if I should as lion come in strife +Into this place, 'twere pity on my life. + + + +THESEUS +A very gentle beast, of a good conscience. + + + +DEMETRIUS +The very best at a beast, my lord, that e'er I saw. + + + +LYSANDER +This lion is a very fox for his valour. + + + +THESEUS +True; and a goose for his discretion. + + + +DEMETRIUS +Not so, my lord; for his valour cannot carry his +discretion; and the fox carries the goose. + + + +THESEUS +His discretion, I am sure, cannot carry his valour; +for the goose carries not the fox. It is well: +leave it to his discretion, and let us listen to the moon. + + + +Moonshine +This lanthorn doth the horned moon present;-- + + + +DEMETRIUS +He should have worn the horns on his head. + + + +THESEUS +He is no crescent, and his horns are +invisible within the circumference. + + + +Moonshine +This lanthorn doth the horned moon present; +Myself the man i' the moon do seem to be. + + + +THESEUS +This is the greatest error of all the rest: the man +should be put into the lanthorn. How is it else the +man i' the moon? + + + +DEMETRIUS +He dares not come there for the candle; for, you +see, it is already in snuff. + + + +HIPPOLYTA +I am aweary of this moon: would he would change! + + + +THESEUS +It appears, by his small light of discretion, that +he is in the wane; but yet, in courtesy, in all +reason, we must stay the time. + + + +LYSANDER +Proceed, Moon. + + + +Moonshine +All that I have to say, is, to tell you that the +lanthorn is the moon; I, the man in the moon; this +thorn-bush, my thorn-bush; and this dog, my dog. + + + +DEMETRIUS +Why, all these should be in the lanthorn; for all +these are in the moon. But, silence! here comes Thisbe. + + + +Enter Thisbe + + +Thisbe +This is old Ninny's tomb. Where is my love? + + + +Lion +Roaring Oh-- + + + +Thisbe runs off + + +DEMETRIUS +Well roared, Lion. + + + +THESEUS +Well run, Thisbe. + + + +HIPPOLYTA +Well shone, Moon. Truly, the moon shines with a +good grace. + + + +The Lion shakes Thisbe's mantle, and exit + + +THESEUS +Well moused, Lion. + + + +LYSANDER +And so the lion vanished. + + + +DEMETRIUS +And then came Pyramus. + + + +Enter Pyramus + + +Pyramus +Sweet Moon, I thank thee for thy sunny beams; +I thank thee, Moon, for shining now so bright; +For, by thy gracious, golden, glittering gleams, +I trust to take of truest Thisby sight. +But stay, O spite! +But mark, poor knight, +What dreadful dole is here! +Eyes, do you see? +How can it be? +O dainty duck! O dear! +Thy mantle good, +What, stain'd with blood! +Approach, ye Furies fell! +O Fates, come, come, +Cut thread and thrum; +Quail, crush, conclude, and quell! + + + +THESEUS +This passion, and the death of a dear friend, would +go near to make a man look sad. + + + +HIPPOLYTA +Beshrew my heart, but I pity the man. + + + +Pyramus +O wherefore, Nature, didst thou lions frame? +Since lion vile hath here deflower'd my dear: +Which is--no, no--which was the fairest dame +That lived, that loved, that liked, that look'd +with cheer. +Come, tears, confound; +Out, sword, and wound +The pap of Pyramus; +Ay, that left pap, +Where heart doth hop: +Stabs himself +Thus die I, thus, thus, thus. +Now am I dead, +Now am I fled; +My soul is in the sky: +Tongue, lose thy light; +Moon take thy flight: +Exit Moonshine +Now die, die, die, die, die. + + + +Dies + + +DEMETRIUS +No die, but an ace, for him; for he is but one. + + + +LYSANDER +Less than an ace, man; for he is dead; he is nothing. + + + +THESEUS +With the help of a surgeon he might yet recover, and +prove an ass. + + + +HIPPOLYTA +How chance Moonshine is gone before Thisbe comes +back and finds her lover? + + + +THESEUS +She will find him by starlight. Here she comes; and +her passion ends the play. + + + +Re-enter Thisbe + + +HIPPOLYTA +Methinks she should not use a long one for such a +Pyramus: I hope she will be brief. + + + +DEMETRIUS +A mote will turn the balance, which Pyramus, which +Thisbe, is the better; he for a man, God warrant us; +she for a woman, God bless us. + + + +LYSANDER +She hath spied him already with those sweet eyes. + + + +DEMETRIUS +And thus she means, videlicet:-- + + + +Thisbe +Asleep, my love? +What, dead, my dove? +O Pyramus, arise! +Speak, speak. Quite dumb? +Dead, dead? A tomb +Must cover thy sweet eyes. +These My lips, +This cherry nose, +These yellow cowslip cheeks, +Are gone, are gone: +Lovers, make moan: +His eyes were green as leeks. +O Sisters Three, +Come, come to me, +With hands as pale as milk; +Lay them in gore, +Since you have shore +With shears his thread of silk. +Tongue, not a word: +Come, trusty sword; +Come, blade, my breast imbrue: +Stabs herself +And, farewell, friends; +Thus Thisby ends: +Adieu, adieu, adieu. + + + +Dies + + +THESEUS +Moonshine and Lion are left to bury the dead. + + + +DEMETRIUS +Ay, and Wall too. + + + +BOTTOM +Starting up No assure you; the wall is down that +parted their fathers. Will it please you to see the +epilogue, or to hear a Bergomask dance between two +of our company? + + + +THESEUS +No epilogue, I pray you; for your play needs no +excuse. Never excuse; for when the players are all +dead, there needs none to be blamed. Marry, if he +that writ it had played Pyramus and hanged himself +in Thisbe's garter, it would have been a fine +tragedy: and so it is, truly; and very notably +discharged. But come, your Bergomask: let your +epilogue alone. +A dance +The iron tongue of midnight hath told twelve: +Lovers, to bed; 'tis almost fairy time. +I fear we shall out-sleep the coming morn +As much as we this night have overwatch'd. +This palpable-gross play hath well beguiled +The heavy gait of night. Sweet friends, to bed. +A fortnight hold we this solemnity, +In nightly revels and new jollity. + + +Exeunt +Enter PUCK + + +PUCK +Now the hungry lion roars, +And the wolf behowls the moon; +Whilst the heavy ploughman snores, +All with weary task fordone. +Now the wasted brands do glow, +Whilst the screech-owl, screeching loud, +Puts the wretch that lies in woe +In remembrance of a shroud. +Now it is the time of night +That the graves all gaping wide, +Every one lets forth his sprite, +In the church-way paths to glide: +And we fairies, that do run +By the triple Hecate's team, +From the presence of the sun, +Following darkness like a dream, +Now are frolic: not a mouse +Shall disturb this hallow'd house: +I am sent with broom before, +To sweep the dust behind the door. + + + +Enter OBERON and TITANIA with their train + + +OBERON +Through the house give gathering light, +By the dead and drowsy fire: +Every elf and fairy sprite +Hop as light as bird from brier; +And this ditty, after me, +Sing, and dance it trippingly. + + + +TITANIA +First, rehearse your song by rote +To each word a warbling note: +Hand in hand, with fairy grace, +Will we sing, and bless this place. + + + +Song and dance + + +OBERON +Now, until the break of day, +Through this house each fairy stray. +To the best bride-bed will we, +Which by us shall blessed be; +And the issue there create +Ever shall be fortunate. +So shall all the couples three +Ever true in loving be; +And the blots of Nature's hand +Shall not in their issue stand; +Never mole, hare lip, nor scar, +Nor mark prodigious, such as are +Despised in nativity, +Shall upon their children be. +With this field-dew consecrate, +Every fairy take his gait; +And each several chamber bless, +Through this palace, with sweet peace; +And the owner of it blest +Ever shall in safety rest. +Trip away; make no stay; +Meet me all by break of day. + + + +Exeunt OBERON, TITANIA, and train + + +PUCK +If we shadows have offended, +Think but this, and all is mended, +That you have but slumber'd here +While these visions did appear. +And this weak and idle theme, +No more yielding but a dream, +Gentles, do not reprehend: +if you pardon, we will mend: +And, as I am an honest Puck, +If we have unearned luck +Now to 'scape the serpent's tongue, +We will make amends ere long; +Else the Puck a liar call; +So, good night unto you all. +Give me your hands, if we be friends, +And Robin shall restore amends. + + + +
diff --git a/renode_rcc/renode-rtems-leon3/leon3_rtems.resc b/renode_rcc/renode-rtems-leon3/leon3_rtems.resc new file mode 100755 index 0000000..a7f36d4 --- /dev/null +++ b/renode_rcc/renode-rtems-leon3/leon3_rtems.resc @@ -0,0 +1,27 @@ +:name: Leon3 rtems demo +:description: This script runs the rtems shell demo on Leon3 + +using sysbus +$name?="Leon3" +mach create $name + +machine LoadPlatformDescription @platforms/boards/leon3.repl + +path add $ORIGIN + +$prom?=@grlib-gpl-2021.2-b4267/software/leon3/prom.bin +:$bin?=@rcc-1.3.0-gcc/src/samples/bin/leon3/rtems-shell +:$bin?=@renode-rtems-leon3/build/tinyxml2.o +$bin?=@renode-rtems-leon3/build/xmltest.exe + +showAnalyzer sysbus.uart + +macro reset +""" + sysbus LoadBinary $prom 0x0 + sysbus LoadELF $bin + + cpu PC 0 +""" + +runMacro $reset diff --git a/renode_rcc/run.sh b/renode_rcc/run.sh index 07b7978..3da3d71 100755 --- a/renode_rcc/run.sh +++ b/renode_rcc/run.sh @@ -1 +1 @@ -docker run -ti --rm -e DISPLAY -v $XAUTHORITY:/home/developer/.Xauthority --net=host openrobotics/renode +docker run -ti --rm -e DISPLAY -v $XAUTHORITY:/home/developer/.Xauthority --net=host openrobotics/renode:latest diff --git a/rtems/Dockerfile b/rtems/Dockerfile index 7d7dcc3..740631c 100644 --- a/rtems/Dockerfile +++ b/rtems/Dockerfile @@ -4,17 +4,27 @@ ENV DEBIAN_FRONTEND noninteractive RUN apt-get update \ && apt-get install -y \ - apt-utils build-essential \ - vim u-boot-tools git cmake \ - bison flex texinfo bzip2 \ - xz-utils unzip python \ - libexpat1-dev curl \ - python-dev \ - zlib1g-dev \ + apt-utils \ + bison \ + build-essential \ + bzip2 \ + cmake \ + curl \ + flex \ + git \ + libexpat1-dev \ libtinfo-dev \ pax \ - tree - + pkg-config \ + python \ + python-dev \ + texinfo \ + tree \ + u-boot-tools \ + unzip \ + vim \ + xz-utils \ + zlib1g-dev RUN mkdir -p development/rtems/5 ENV PREFIX /root/development/rtems/5 @@ -34,14 +44,20 @@ RUN ../source-builder/sb-set-builder --prefix=$PREFIX --target=sparc-rtems5 --wi WORKDIR /root RUN git clone https://github.com/robamu-org/rtems-cmake.git +RUN git clone https://github.com/leethomason/tinyxml2.git COPY example example/ +COPY hello hello/ +COPY hello_posix hello_posix/ +COPY tinyxml2 tinyxml2/ + WORKDIR /root/example/build RUN cmake ../src/ RUN cmake --build . -WORKDIR /root +WORKDIR /root/tinyxml2 -RUN echo 'alias sparc-rtems5-gcc="development/rtems/5/bin/sparc-rtems5-gcc"' >> ~/.bashrc +RUN echo 'alias sparc-rtems5-gcc="~/development/rtems/5/bin/sparc-rtems5-gcc"' >> ~/.bashrc +RUN echo 'alias sparc-rtems5-objdump="~/development/rtems/5/bin/sparc-rtems5-objdump"' >> ~/.bashrc #sparc-rtems5-gcc -Wall -lc --entry main hello.c -o hello diff --git a/rtems/README.md b/rtems/README.md index 65177c6..8ee7f2f 100644 --- a/rtems/README.md +++ b/rtems/README.md @@ -2,3 +2,24 @@ This folder contains a Dockerfile that build RTEMS from source following the [official doc](https://docs.rtems.org/branches/master/user/overview/index.html). The target platform for the build is leon3. This will not run RTEMS, just perform the build and set up tools. + +## Examples +There three examples in this demo: example, hello and tinxyxml2. +hello is ported from `rtems-cmake`, uses waf to cross-compile. +example is an hello world example build using `sparc-rtems5-gcc` tool. +tinyxml2 is modified to work with RTEMS build using `sparc-rtems5-gcc` tool.. + +## Compile +``` +cd /root/tinxyxml2 +./doit +``` + +## Save build artefacts +After compiling the binaries for the target, save the binaries and test payload for later use in renode. + +``` +docker cp containerId:/root/tinyxml2/tinyxml2.o /docker/renode_rcc/build/ + +docker cp containerId:/root/tinyxml2/xmltest.exe /docker/renode_rcc/build/ +``` diff --git a/rtems/example/src/CMakeLists.txt b/rtems/example/src/CMakeLists.txt index 336f4cb..c89070b 100644 --- a/rtems/example/src/CMakeLists.txt +++ b/rtems/example/src/CMakeLists.txt @@ -15,6 +15,7 @@ set(RTEMS_BSP CACHE FILEPATH "Board support package name" ) + include(${RTEMS_CONFIG_DIR}/RTEMSPreProjectConfig.cmake) rtems_pre_project_config(${RTEMS_PREFIX} ${RTEMS_BSP}) @@ -23,3 +24,4 @@ set(CMAKE_TOOLCHAIN_FILE ${RTEMS_CONFIG_DIR}/RTEMSToolchain.cmake) project(Example) add_executable(Example main.cpp) +target_include_directories(Example PUBLIC /root/development/rtems/5/sparc-rtems5/leon3/lib/include) diff --git a/rtems/example/src/doit b/rtems/example/src/doit new file mode 100755 index 0000000..16616e8 --- /dev/null +++ b/rtems/example/src/doit @@ -0,0 +1,7 @@ + +/root/development/rtems/5/bin/sparc-rtems5-gcc -qrtems -B/root/development/rtems/5/sparc-rtems5/lib/ -B/root/development/rtems/5/sparc-rtems5/leon3/lib/ --specs bsp_specs -mcpu=leon3 -ffunction-sections -fdata-sections -MMD -g -O2 main.cpp -c -o main.o + +/root/development/rtems/5/bin/sparc-rtems5-gcc -qrtems -B/root/development/rtems/5/sparc-rtems5/lib/ -B/root/development/rtems/5/sparc-rtems5/leon3/lib/ --specs bsp_specs -mcpu=leon3 -ffunction-sections -fdata-sections -MMD -Wl,--gc-sections main.o -omain.exe -Wl,-Bstatic -Wl,-Bdynamic + +/root/development/rtems/5/bin/rtems-run --rtems-bsps=leon3-sis main.exe + diff --git a/rtems/example/src/main.cpp b/rtems/example/src/main.cpp index 596e69d..7c10ef8 100644 --- a/rtems/example/src/main.cpp +++ b/rtems/example/src/main.cpp @@ -1,4 +1,31 @@ -int main() { - return 0; -} +/* + * Simple RTEMS configuration + */ + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_UNLIMITED_OBJECTS +#define CONFIGURE_UNIFIED_WORK_AREAS + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE +#define CONFIGURE_INIT + +#include + +/* + * Hello world example + */ +#include +#include +#include +#include + +rtems_task Init( + rtems_task_argument ignored +) +{ + printf( "\nHello World\n" ); + exit( 0 ); +} diff --git a/rtems/hello/doit b/rtems/hello/doit new file mode 100755 index 0000000..67cadb7 --- /dev/null +++ b/rtems/hello/doit @@ -0,0 +1,3 @@ +./waf configure --rtems=/root/development/rtems/5 --rtems-bsp=sparc/leon3 --rtems-version=5 --show-commands +./waf +/root/development/rtems/5/bin/rtems-run --rtems-bsps=leon3-sis build/sparc-rtems5-leon3/hello.exe diff --git a/rtems/hello/hello.c b/rtems/hello/hello.c new file mode 100644 index 0000000..4f5365a --- /dev/null +++ b/rtems/hello/hello.c @@ -0,0 +1,15 @@ + +/* + * Hello world example + */ +#include +#include +#include + +rtems_task Init( + rtems_task_argument ignored +) +{ + printf( "\nHello World\n" ); + exit( 0 ); +} diff --git a/rtems/hello/init.c b/rtems/hello/init.c new file mode 100644 index 0000000..b366d20 --- /dev/null +++ b/rtems/hello/init.c @@ -0,0 +1,17 @@ + +/* + * Simple RTEMS configuration + */ + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_UNLIMITED_OBJECTS +#define CONFIGURE_UNIFIED_WORK_AREAS + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include + diff --git a/rtems/hello/rtems_waf/README b/rtems/hello/rtems_waf/README new file mode 100644 index 0000000..29db6ef --- /dev/null +++ b/rtems/hello/rtems_waf/README @@ -0,0 +1,389 @@ +RTEMS Waf +~~~~~~~~~ + +RTEMS Waf is a module that supports the Waf build system and RTEMS. The module +is integrated into a project or library proividing Waf build support to create +RTEMS libraries or executables. + +RTEMS Waf provides: + +* Checking for a valid RTEMS installation of tools and kernel. + +* Support for multiple versions of RTEMS. + +* Support to build a number of BSPs at once. + +* Support for the RTEMS tools and kernel being installed under a shared or + separate prefixes [2]. + +* Flexible integration that allows easy project specific specialization. + +* Support to check which features RTEMS is built with. + +* Support for BSP compiler and linker flags. The flags are separated into their + various types to allow flexible options management in a project. + +* Support to list the available architectures and BSPs. + +* Additional support for creating root file systems for RTEMS targets. + +Bugs +---- + +Please report issues to the RTEMS Users list mailto:users@rtems.org or raise a +ticket in RTEMS's Trac under https://devel.rtems.org/. + +Feedback is always welcome. + +Waf +--- + +You can find the Waf project here: + + https://waf.io/ + +Waf does not come as a package in distrubitions so you need to download and +install it. + +1. Waf is a Python program so you will also need to have a current Python + installed and accessible via your environment's path. + +2. Download the latest signed Waf executable file from the Waf website. + +3. Place the waf executable in a personal directory that is in your path, for + example $HOME/bin. Modify the file's permissions so it can be executed: + + $ chmod +x $HOME/bin/waf + +Git Submodule +------------- + +RTEMS Waf can be used as a git submodule. This lets a number of projects share +the common waf support. + +1. Add RTEMS Waf a git submodule to your project: + + $ cd my_project + $ git submodule add git://git.rtems.org/rtems_waf.git rtems_waf + +2. Initialize the submodule(s) for your project: + + $ git submodule init + +3. Update the RTEMS Waf submodule: + + $ git submodule update rtems_waf + + Note, the `rtems_waf` submodule name is provided as some projects may have + other submodules you may not wish to update. + +4. When submodules are added they are headless which means they are not on a + current branch. Switch to a branch: + + $ cd rtems_waf + $ git checkout master + $ cd .. + + Note, you can replace `master` in the `checkout` above with any valid branch + in the RTEMS Waf repo. + +5. Update the RTEMS Waf submodule to the latest version on the selected branch: + + $ cd rtems_waf + $ git pull + $ cd .. + +6. Check the new submodule is part of your project and ready to be committed: + + $ git status + + The `rtems_waf` module will be listed as `modified`. + +7. Commit the change by adding it to your staged files: + + $ git add rtems_waf + + When ready commit: + + $ git commit + + Review the changes and if they are correct push them: + + $ git log -p + $ git push + +The RTEMS Waf module is updated from time to time as new features are added or +changes happen in waf. To update a project's existing RTEMS Waf submodule +perform steps 5. to 7. + +Project Instructions +-------------------- + +Create a README.waf file in your project and add the Waf installation section, +your project specific options and the following steps. These steps are for +RTEMS 5, change for the specific version of RTEMS your project supports. + +1. Build or install the tools. In this example the path is the personal prefix + of $HOME/development/rtems/5 [1]. + +2. Build and install the RTEMS Board Support Packages you want to use. In this + example separate tools and kernel prefixes are used [2]. The kernel path is + $HOME/development/rtems/bsps/5. + +3. Unpack this package somewhere, anywhere on your disk and change into the top + level directory. + +4. Populate the git submodule: + + $ git submodule init + $ git submodule update rtems_waf + +5. Configure with your specific settings. In this case the path to the tools + and the kernel are separate and provided on the command line. Your + envronment's path variable does not need to changed [3]. We limit the build + to 'sparc/erc32' BSP: + + $ waf configure --rtems=$HOME/development/rtems/bsps/5 \ + --rtems-tools=$HOME/development/rtems/5 \ + --rtems-bsps=sparc/erc32 + + You can use '--rtems-archs=sparc,i386' or + '--rtems-bsps=sparc/erc32,i386/pc586' to build more than BSP at a time. + +6. Build: + + $ waf + +An RTEMS Waf Project +-------------------- + +RTEMS Waf provides a base to build RTEMS application. + +Waf provides a build system framework. You can use waf in your project by +simply prooviding a list of files you wish to build and link to create an +executable or you can use waf as framework which is integrated into your +project to become is build system. + +Importing RTEMS Waf +~~~~~~~~~~~~~~~~~~~ + +Using RTEMS Waf as a submodule means it may not be present if the submodules +have not been initialized and updated. This results in a Python error. The +following import is recommended so a user friendly error is reported: + + from __future__ import print_function + + try: + import rtems_waf.rtems as rtems + except: + print('error: no rtems_waf git submodule; see README.waf', file = stderr) + import sys + sys.exit(1) + +Initialization +~~~~~~~~~~~~~~ + +The `wscript` `init()` function is called early in waf's processing. The RTEMS +Waf's `init()` call lets you provide: + +1. Filters + +2. RTEMS Version + +3. Long command line control + +4. Waf BSP initialization hook + +A example call to RTEMS Waf's `init()` is: + + rtems_version = "5" + + def init(ctx): + rtems.init(ctx, version = rtems_version, long_commands = True) + +Filters provide a way to control the tools, architectures and BSPs your project +supports. RTEMS Waf scans and finds all installed RTEMS tool sets and BSPs and +your project may only support a limited number of these. Filtering provides a +way for your project to control what RTEMS Waf accepts and rejects when +automatically scanning the installed tools and RTEMS kernels. A filter is a +Python dictionary and the following example will accept `arm` and `sparc` tool +chains and filtering out the `bfin` tool chain. The filter will only build the +`arm` acrhitecture and will accept all BSPs except ones starting with `lpc` if +they are installed: + + my_filter = { 'tools': { 'in': ['arm', 'sparc'], 'out': ['bfin'] }, + 'arch': { 'in': ['arm'], 'out': [] }, + 'bsps': { 'in': [], 'out': ['lpc.*'] } } + +There are three (3) filters the `tools`, `archs` and `bsps` and each of these +filter types has an `in` and `out` list. The `in` and `out` items are Python +regular expressions. + +The RTEMS Version lets your project provide the default RTEMS version. This can +be overridden by the configure option `--rtems-version`. + +Long commands is specific to Windows and provides support for tool command +lines that are longer than the standard Windows command shell's limit. The +support is based on the example available in Waf extra's. + +The Waf BSP initialization hook is a function called as part of the RTEMS Waf's +`init()` call with the Waf environment and list of BSP contexts. This hook can +be used to provide specialized BSP support. + +Options +~~~~~~~ + +The `wscript` `option()` function is called to collect command line options for +Waf argument processing. + +A example call to RTEMS Waf's `options()` is: + + def options(opt): + rtems.options(opt) + +Configure +~~~~~~~~~ + +The `wscript` `configure()` function is called when Waf is configuring a +build. The RTEMS Waf's `configure()` lets you provide: + +1. Waf BSP configure hook + +A example call to RTEMS Waf's `configure()` is: + + def configure(conf): + rtems.configure(conf) + +The BSP configure hook is called at end of a BSP's configuration. The BSP's +`conf` variable and the `arch/bsp` are passed as arguments. The `arch/bsp` is +the RTEMS standard for specifing a BSP, for example `sparc/erc32`. The BSP +configure support can be used to check a BSP for header, check an RTEMS feature +is present for a specific BSP or add per BSP build variant support: + + def bsp_configure(conf, arch_bsp): + conf.check(header_name = "dlfcn.h", features = "c") + conf.check(header_name = "rtems/pci.h", features = "c", mandatory = False) + if not rtems.check_posix(conf): + conf.fatal("POSIX is disabled; configure RTEMS with --enable-posix") + env = conf.env.derive() + for builder in builders: + ab = conf.env.RTEMS_ARCH_BSP + variant = ab + "-" + builder + conf.msg('Configure variant: ', variant) + conf.setenv(variant, env) + build_variant_bsp_configure(conf, arch_bsp) + conf.setenv(ab) + +Build +~~~~~ + +The `wscript` `build()` function is called when Waf is asking what to +build. + +A example call to RTEMS Waf's `build()` is: + + def build(bld): + rtems.build(bld) + bld(features = 'c cprogram', + target = 'hello.exe', + source = ['hello.c']) + +In this example the C source file `hello.c` is compiled and linked to create +the RTEMS executable `hello.exe`. The build is within the context of the BSP. + +Example +~~~~~~~ + +Save the following as `wscript`: + + # + # Example Waf build script for RTEMS + # + # To configure, build and run: + # + # $ waf configure --rtems=$HOME/development/rtems/build/5 \ + # --rtems-tools=$HOME/development/rtems/5 \ + # --rtems-bsps=sparc/erc32 + # $ waf + # $ $HOME/development/rtems/5/bin/sparc-rtems5-run \ + # ./build/sparc-rtems5-erc32/hello.exe + # + # You can use '--rtems-archs=sparc,i386' or + # '--rtems-bsps=sparc/erc32,i386/pc586' to build for more than one BSP at a + # time. + # + + from __future__ import print_function + + rtems_version = "5" + + try: + import rtems_waf.rtems as rtems + except: + print('error: no rtems_waf git submodule; see README.waf', file = stderr) + import sys + sys.exit(1) + + def init(ctx): + rtems.init(ctx, version = rtems_version, long_commands = True) + + def options(opt): + rtems.options(opt) + + def configure(conf): + rtems.configure(conf) + + def build(bld): + rtems.build(bld) + bld.env.CFLAGS += ['-O2','-g'] + bld(features = 'c cprogram', + target = 'hello.exe', + source = ['hello.c']) + +Save the example C hello world as `hello.c`: + + #include + #include + #include + + rtems_task Init(rtems_task_argument ignored) { + printf("Hello World\n"); + exit(0); + } + + /* configuration information */ + #include + #define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER + #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + #define CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM + #define CONFIGURE_RTEMS_INIT_TASKS_TABLE + #define CONFIGURE_MAXIMUM_TASKS 1 + #define CONFIGURE_INIT + #include + +-- + +[1] A personal prefix is private to you and located where you have enough disk + space to complete an RTEMS installation. We often show this as your home + directory ($HOME) because it works on machines you may not have root access + to and cannot configure. We recommend you never work as root on a machine + you control. + +[2] RTEMS supports shared or separate tool and kernel prefixes. The prefix is + the path given to the tools and kernel when building and is the path the + tools or kernel are installed into when you run the install phase of a + build. A shared tools and kernel prefix is often used with releases because + the tools and kernel in a release are matched and do not change. Separate + tools and kernel paths can be used if you have a common tool set with + changing kernel versions. This tends to happen when you are testing kernel + patches or changes. + +[3] It is good practice to keep your environment as empty as possible. Using + the environment to set paths to tools or specific values to configure and + control builds is dangerous because settings can leak between different + builds and change what you expect or not been and seen and lost. The waf + tool used here lets you specify on the command line the tools and RTEMS + paths and this is embedded in waf's configuration information. If you have + a few source trees working at any one time with different tool sets or + configurations you can easly move between them safe in the knowledge that + one build will not affect another. diff --git a/rtems/hello/rtems_waf/__init__.py b/rtems/hello/rtems_waf/__init__.py new file mode 100644 index 0000000..e60cc4d --- /dev/null +++ b/rtems/hello/rtems_waf/__init__.py @@ -0,0 +1,6 @@ +# Copyright 2013 Chris Johns (chrisj@rtems.org) +# +# This file's license is 2-clause BSD as in this distribution's LICENSE.2 file. +# + +__all__ = ['rtems', 'pkgconfig'] diff --git a/rtems/hello/rtems_waf/dl.py b/rtems/hello/rtems_waf/dl.py new file mode 100644 index 0000000..ec5b238 --- /dev/null +++ b/rtems/hello/rtems_waf/dl.py @@ -0,0 +1,118 @@ +# +# RTEMS Project (https://www.rtems.org/) +# +# Copyright (c) 2018 Chris Johns . All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os + +def _syms_rule(tsk): + ''' + A rule handler so 'no_errcheck_out' can be set. This avoids the + erronous duplicate output error from waf (2.0.14 and later). + ''' + setattr(tsk, 'no_errcheck_out', True) + src = tsk.inputs[0].abspath() + tgt = tsk.outputs[0].abspath() + cmd = '%s -e -C %s -c "%s" -o %s %s' % (' '.join(tsk.env.RTEMS_SYMS), + ' '.join(tsk.env.CC), + ' '.join(tsk.env.CFLAGS), + tgt, + src) + return tsk.exec_command(cmd) + +def syms(ctx, target, source): + ''' + Create a symbols object file from a base kernel image. The object + can be linked to the file executable providing it with a symbol + table. + + The created object file is read and available in a 'use' attribute + of the 'cprogram' build. + + :param ctx: Waf build context + :param target: The target object file to create and read + :param source: The kernel base image to generate the symbol table of + ''' + tgt = ctx.path.find_or_declare(target) + ctx(rule = _syms_rule, + target = tgt, + source = source, + color = 'CYAN') + ctx.read_object(tgt) + +def _strip_rule(tsk): + ''' + A rule handler so 'no_errcheck_out' can be set. We need this because + 'ranlib' takes only a single argument, the archive is rewritten so it + will appear in 2 outputs. + ''' + setattr(tsk, 'no_errcheck_out', True) + src = tsk.inputs[0].abspath() + tgt = tsk.outputs[0].abspath() + cmd = '%s -d -o %s %s' % (' '.join(tsk.env.STRIP), tgt, src) + return tsk.exec_command(cmd) + +def strip_debug_info(ctx, *k, **kw): + ''' + Strip the source object file or archive of debug information + creating a new archive in the build directory. + + :param ctx: Waf build context + :param target: The stripped target archive or object file + :param source: The source target or acthive file to strip + ''' + if 'source' not in kw: + ctx.fatal('No source in strip') + if 'target' not in kw: + ctx.fatal('No target in strip') + source = kw['source'] + target = kw['target'] + if 'name' in kw: + name = kw['name'] + else: + if not isinstance(source, str): + ctx.fatal('No name and source is not a path') + name = 'strip-%s' % (os.path.basename(source)) + print(type(source), str(source), target) + ctx(rule = _strip_rule, + name = name, + target = target, + source = source, + color = 'CYAN') + +def _ranlib_rule(tsk): + ''' + A rule handler so 'no_errcheck_out' can be set. We need this because + 'ranlib' takes only a single argument, the archive is rewritten so it + will appear in 2 outputs. + ''' + setattr(tsk, 'no_errcheck_out', True) + tgt = tsk.inputs[0].abspath() + cmd = '%s -t %s' % (' '.join(tsk.env.RANLIB), tgt) + return tsk.exec_command(cmd) + +def ranlib(ctx, lib): + ctx(rule = _ranlib_rule, + name = 'ranlib-%s' % (lib), + source = lib) diff --git a/rtems/hello/rtems_waf/gccdeps.py b/rtems/hello/rtems_waf/gccdeps.py new file mode 100644 index 0000000..bfabe72 --- /dev/null +++ b/rtems/hello/rtems_waf/gccdeps.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2008-2010 (ita) + +""" +Execute the tasks with gcc -MD, read the dependencies from the .d file +and prepare the dependency calculation for the next run. +This affects the cxx class, so make sure to load Qt5 after this tool. + +Usage:: + + def options(opt): + opt.load('compiler_cxx') + def configure(conf): + conf.load('compiler_cxx gccdeps') +""" + +import os, re, threading +from waflib import Task, Logs, Utils, Errors +from waflib.Tools import c_preproc +from waflib.TaskGen import before_method, feature + +lock = threading.Lock() + +gccdeps_flags = ['-MD'] +if not c_preproc.go_absolute: + gccdeps_flags = ['-MMD'] + +# Third-party tools are allowed to add extra names in here with append() +supported_compilers = ['gcc', 'icc', 'clang'] + +def scan(self): + if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: + return super(self.derived_gccdeps, self).scan() + nodes = self.generator.bld.node_deps.get(self.uid(), []) + names = [] + return (nodes, names) + +re_o = re.compile(r"\.o$") +re_splitter = re.compile(r'(?= 0: + return line[sep_idx + 2:] + else: + return line + +def path_to_node(base_node, path, cached_nodes): + # Take the base node and the path and return a node + # Results are cached because searching the node tree is expensive + # The following code is executed by threads, it is not safe, so a lock is needed... + if getattr(path, '__hash__'): + node_lookup_key = (base_node, path) + else: + # Not hashable, assume it is a list and join into a string + node_lookup_key = (base_node, os.path.sep.join(path)) + try: + lock.acquire() + node = cached_nodes[node_lookup_key] + except KeyError: + node = base_node.find_resource(path) + cached_nodes[node_lookup_key] = node + finally: + lock.release() + return node + +def post_run(self): + if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: + return super(self.derived_gccdeps, self).post_run() + + name = self.outputs[0].abspath() + name = re_o.sub('.d', name) + try: + txt = Utils.readf(name) + except EnvironmentError: + Logs.error('Could not find a .d dependency file, are cflags/cxxflags overwritten?') + raise + #os.remove(name) + + # Compilers have the choice to either output the file's dependencies + # as one large Makefile rule: + # + # /path/to/file.o: /path/to/dep1.h \ + # /path/to/dep2.h \ + # /path/to/dep3.h \ + # ... + # + # or as many individual rules: + # + # /path/to/file.o: /path/to/dep1.h + # /path/to/file.o: /path/to/dep2.h + # /path/to/file.o: /path/to/dep3.h + # ... + # + # So the first step is to sanitize the input by stripping out the left- + # hand side of all these lines. After that, whatever remains are the + # implicit dependencies of task.outputs[0] + txt = '\n'.join([remove_makefile_rule_lhs(line) for line in txt.splitlines()]) + + # Now join all the lines together + txt = txt.replace('\\\n', '') + + val = txt.strip() + val = [x.replace('\\ ', ' ') for x in re_splitter.split(val) if x] + + nodes = [] + bld = self.generator.bld + + # Dynamically bind to the cache + try: + cached_nodes = bld.cached_nodes + except AttributeError: + cached_nodes = bld.cached_nodes = {} + + for x in val: + + node = None + if os.path.isabs(x): + node = path_to_node(bld.root, x, cached_nodes) + else: + # TODO waf 1.9 - single cwd value + path = getattr(bld, 'cwdx', bld.bldnode) + # when calling find_resource, make sure the path does not contain '..' + x = [k for k in Utils.split_path(x) if k and k != '.'] + while '..' in x: + idx = x.index('..') + if idx == 0: + x = x[1:] + path = path.parent + else: + del x[idx] + del x[idx-1] + + node = path_to_node(path, x, cached_nodes) + + if not node: + raise ValueError('could not find %r for %r' % (x, self)) + if id(node) == id(self.inputs[0]): + # ignore the source file, it is already in the dependencies + # this way, successful config tests may be retrieved from the cache + continue + nodes.append(node) + + Logs.debug('deps: gccdeps for %s returned %s', self, nodes) + + bld.node_deps[self.uid()] = nodes + bld.raw_deps[self.uid()] = [] + + try: + del self.cache_sig + except AttributeError: + pass + + Task.Task.post_run(self) + +def sig_implicit_deps(self): + if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: + return super(self.derived_gccdeps, self).sig_implicit_deps() + try: + return Task.Task.sig_implicit_deps(self) + except Errors.WafError: + return Utils.SIG_NIL + +def wrap_compiled_task(classname): + derived_class = type(classname, (Task.classes[classname],), {}) + derived_class.derived_gccdeps = derived_class + derived_class.post_run = post_run + derived_class.scan = scan + derived_class.sig_implicit_deps = sig_implicit_deps + +for k in ('c', 'cxx'): + if k in Task.classes: + wrap_compiled_task(k) + +@before_method('process_source') +@feature('force_gccdeps') +def force_gccdeps(self): + self.env.ENABLE_GCCDEPS = ['c', 'cxx'] + +def configure(conf): + # in case someone provides a --enable-gccdeps command-line option + if not getattr(conf.options, 'enable_gccdeps', True): + return + + global gccdeps_flags + flags = conf.env.GCCDEPS_FLAGS or gccdeps_flags + if conf.env.CC_NAME in supported_compilers: + try: + conf.check(fragment='int main() { return 0; }', features='c force_gccdeps', cflags=flags, msg='Checking for c flags %r' % ''.join(flags)) + except Errors.ConfigurationError: + pass + else: + conf.env.append_value('CFLAGS', flags) + conf.env.append_unique('ENABLE_GCCDEPS', 'c') + + if conf.env.CXX_NAME in supported_compilers: + try: + conf.check(fragment='int main() { return 0; }', features='cxx force_gccdeps', cxxflags=flags, msg='Checking for cxx flags %r' % ''.join(flags)) + except Errors.ConfigurationError: + pass + else: + conf.env.append_value('CXXFLAGS', flags) + conf.env.append_unique('ENABLE_GCCDEPS', 'cxx') + +def options(opt): + raise ValueError('Do not load gccdeps options') + diff --git a/rtems/hello/rtems_waf/pkgconfig.py b/rtems/hello/rtems_waf/pkgconfig.py new file mode 100644 index 0000000..382f4dc --- /dev/null +++ b/rtems/hello/rtems_waf/pkgconfig.py @@ -0,0 +1,84 @@ +# Copyright 2013 Chris Johns (chrisj@rtems.org) +# +# This file's license is 2-clause BSD as in this distribution's LICENSE.2 file. +# + +# +# Pkg-config in python. Pkg-config as a tool is a good idea how-ever the +# implementation is really Linux (or Unix) based and requires a couple of +# packages that it should not. If it was implemented with all parts included it +# would be portable and I suspect useful to others on platforms other than +# Linux or Unix equivs that contain the required packages. +# +import re + +class error(Exception): + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return self.msg + +class package: + def __init__(self, file = None): + self.defines = {} + self.fields = {} + if file: + self.load(file) + + def load(self, file): + f = open(file) + tm = False + for l in f.readlines(): + l = l[:-1] + hash = l.find('#') + if hash >= 0: + l = l[:hash] + if len(l): + d = 0 + define = False + eq = l.find('=') + dd = l.find(':') + if eq > 0 and dd > 0: + if eq < dd: + define = True + d = eq + else: + define = False + d = dd + elif eq >= 0: + define = True + d = eq + elif dd >= 0: + define = False + d = dd + if d > 0: + lhs = l[:d].lower() + rhs = l[d + 1:] + + if tm: + print('define: ' + str(define) + ', lhs: ' + lhs + ', ' + rhs) + + if define: + self.defines[lhs] = rhs + else: + self.fields[lhs] = rhs + + def get(self, label): + if label.lower() not in self.fields: + raise error('Label not found: ' + label) + mre = re.compile('\$\{[^\}]+\}') + s = self.fields[label.lower()] + expanded = True + tm = False + while expanded: + expanded = False + if tm: + print('pc:get: "' + s + '"') + ms = mre.findall(s) + for m in ms: + mn = m[2:-1] + if mn.lower() in self.defines: + s = s.replace(m, self.defines[mn.lower()]) + expanded = True + return s diff --git a/rtems/hello/rtems_waf/rootfs.py b/rtems/hello/rtems_waf/rootfs.py new file mode 100644 index 0000000..6fef0e4 --- /dev/null +++ b/rtems/hello/rtems_waf/rootfs.py @@ -0,0 +1,143 @@ +# +# RTEMS Project (https://www.rtems.org/) +# +# Copyright (c) 2017 Chris Johns . All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os + +def join(*paths): + path = '' + for p in paths: + path = os.path.join(path, str(p)) + return path + +def copy(ctx, name, root, target, source): + '''Copy a file from the source to the target.''' + if isinstance(target, str): + target = ctx.path.make_node(target) + #print('copy: name=%s source=%s target=%s' % (name, source, target)) + ctx(rule = 'cp ${SRC} ${TGT}', + name = name, + source = source, + target = target) + +def tar(ctx, name, root, target, source, depends_on): + #print('tar: name=%s root=%s target=%r source=%r' % (name, root, target, source)) + ctx(rule = 'tar -C %s -cf ${TGT} .' % (root), + name = name, + target = target, + source = source, + root = join(ctx.path.get_bld(), root), + depends_on = depends_on, + color = 'CYAN') + +def bin2c(ctx, name, target, source): + ctx(rule = '${RTEMS_BIN2C} ${SRC} ${TGT}', + name = name, + target = target, + source = source, + color = 'PINK') + +def build(ctx, name, root, files): + """The files are truples of the name, source and target files to put in the tar + file. The truple is (name, src, dst). The src is the absolute path to the + source and the dst is the path on the target. + + The tar file will contain the files defined by the dst paths. These are + copied into the build path under the tar file's root path. Make sure the + desination paths are relative to the root of the tar file. + + For example: + import rtems_waf.rootfs as rtems_rootfs + tar_files = [('shell-init', ''shell-init', 'shell-init'), + ('rc-conf', 'rc.conf', 'etc/rc.conf')] + rtems_rootfs.build(ctx, 'fs-root', 'rootfs', tar_files) + """ + # + # The files must be a list of tuples. + # + if not isinstance(files, list): + ctx.fatal('rootfs build files is not a list') + + root_abspath = join(ctx.path.get_bld().abspath(), root) + + for f in files: + # + # Check each item in the list is a tuple with 3 elements. + # + if not isinstance(f, tuple): + ctx.fatal('rootfs build file is not a tuple') + if len(f) != 3: + ctx.fatal('rootfs build file tuple has 3 items (name, src, dst): %s' % (str(f))) + # + # Copy the file as a build task. The file is copied to the tar file's + # root. + # + #print(']]', ctx.path.make_node(join(root, f[2])).get_bld()) + if isinstance(f[1], str): + source = ctx.path.make_node(f[1]).get_src() + else: + source = f[1] + copy(ctx, + name = f[0], + root = root, + target = ctx.path.make_node(join(root, f[2])).get_bld(), + source = source) + + ctx.add_group() + + # + # Tar build task. + # + tar(ctx, + name = name + '-tar', + root = join(ctx.path.get_bld(), root), + target = name + '.tar', + source = [join(root, f[2]) for f in files], + depends_on = [f[0] for f in files]) + + ctx.add_group() + + # + # Binary to C build task. It converts the tar file to a C file. This uses + # the RTEMS Tools Project's `bin2c` command. + # + bin2c(ctx, + name = name, + target = name + '-tar.c', + source = name + '.tar') + + ctx.add_group() + + ctx.objects(features = 'c', + target = name + '-obj', + source = name + '-tar.c') + +def build_from_src_root(ctx, name, root): + root_path = ctx.path.make_node(root) + if not root_path.exists(): + ctx.fatal('tar root not found: %s' % (root_path)) + sources = [s.path_from(root_path) for s in root_path.ant_glob('**')] + build(ctx, name, root, [('%s-%s' % (name, os.path.basename(s)), + join(root, s), s) for s in sources]) diff --git a/rtems/hello/rtems_waf/rtems.py b/rtems/hello/rtems_waf/rtems.py new file mode 100644 index 0000000..55ed02b --- /dev/null +++ b/rtems/hello/rtems_waf/rtems.py @@ -0,0 +1,969 @@ + +# Copyright 2012-2016 Chris Johns (chrisj@rtems.org) +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from __future__ import print_function + +# +# RTEMS support for applications. +# + +import copy +import os +import os.path +from . import pkgconfig +import re +import subprocess +import sys + +rtems_default_version = None +rtems_filters = None +rtems_long_commands = False + +windows = os.name == 'nt' or sys.platform in ['msys', 'cygwin'] + +def options(opt): + opt.add_option('--rtems', + default = None, + dest = 'rtems_path', + help = 'Path to an installed RTEMS (defaults to prefix).') + opt.add_option('--rtems-tools', + default = None, + dest = 'rtems_tools', + help = 'Path to RTEMS tools (defaults to path to installed RTEMS).') + opt.add_option('--rtems-version', + default = None, + dest = 'rtems_version', + help = 'RTEMS version (default is derived from prefix).') + opt.add_option('--rtems-archs', + default = 'all', + dest = 'rtems_archs', + help = 'List of RTEMS architectures to build.') + opt.add_option('--rtems-bsps', + default = 'all', + dest = 'rtems_bsps', + help = 'List of BSPs to build.') + opt.add_option('--show-commands', + action = 'store_true', + default = False, + dest = 'show_commands', + help = 'Print the commands as strings.') + +def init(ctx, filters = None, version = None, long_commands = False, bsp_init = None): + global rtems_filters + global rtems_default_version + global rtems_long_commands + + # + # Set the RTEMS filter to the context. + # + rtems_filters = filters + + # + # Set the default version, can be overridden. + # + rtems_default_version = version + + # + # Set the long commands option. + # + rtems_long_commands = long_commands + + env = None + contexts = [] + try: + import waflib.Options + import waflib.ConfigSet + + # + # Load the configuation set from the lock file. + # + env = waflib.ConfigSet.ConfigSet() + env.load(waflib.Options.lockfile) + + # + # Check the tools, architectures and bsps. + # + rtems_version, rtems_path, rtems_tools, archs, arch_bsps = \ + check_options(ctx, + env.options['prefix'], + env.options['rtems_tools'], + env.options['rtems_path'], + env.options['rtems_version'], + env.options['rtems_archs'], + env.options['rtems_bsps']) + + # + # Update the contexts for all the bsps. + # + from waflib.Build import BuildContext, CleanContext, \ + InstallContext, UninstallContext + for x in arch_bsps: + for y in (BuildContext, CleanContext, InstallContext, UninstallContext): + name = y.__name__.replace('Context','').lower() + class context(y): + cmd = name + '-' + x + variant = x + contexts += [context] + + # + # Transform the command to per BSP commands. + # + commands = [] + for cmd in waflib.Options.commands: + if cmd in ['build', 'clean', 'install', 'uninstall']: + for x in arch_bsps: + commands += [cmd + '-' + x] + else: + commands += [cmd] + waflib.Options.commands = commands + except: + pass + + if bsp_init: + bsp_init(ctx, env, contexts) + +def test_application(more = []): + code = ['#include '] + code += more + code += ['void Init(rtems_task_argument arg) { (void)arg; }'] + code += ['#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER'] + code += ['#define CONFIGURE_MAXIMUM_TASKS 1'] + code += ['#define CONFIGURE_RTEMS_INIT_TASKS_TABLE'] + code += ['#define CONFIGURE_INIT'] + code += ['#include '] + return os.linesep.join(code) + +def configure(conf, bsp_configure = None): + # + # Check the environment for any flags. + # + for f in ['CC', 'CXX', 'AS', 'LD', 'AR', 'LINK_CC', 'LINK_CXX', + 'CPPFLAGS', 'CFLAGS', 'CXXFLAGS', 'ASFLAGS', 'LINKFLAGS', 'LIB' + 'WFLAGS', 'RFLAGS', 'MFLAGS', 'IFLAGS']: + if f in os.environ: + conf.msg('Environment variable set', f, color = 'RED') + + # + # Handle the configurable commands options. + # + if conf.options.show_commands: + show_commands = 'yes' + else: + show_commands = 'no' + if rtems_long_commands and windows: + long_commands = 'yes' + else: + long_commands = 'no' + + rtems_version, rtems_path, rtems_tools, archs, arch_bsps = \ + check_options(conf, + conf.options.prefix, + conf.options.rtems_tools, + conf.options.rtems_path, + conf.options.rtems_version, + conf.options.rtems_archs, + conf.options.rtems_bsps) + + if rtems_tools is None: + conf.fatal('RTEMS tools not found.') + + _log_header(conf) + + conf.msg('RTEMS Version', rtems_version, 'YELLOW') + conf.msg('Architectures', ', '.join(archs), 'YELLOW') + + tools = {} + env = conf.env.derive() + conf.env.RTEMS_ARCH_BSP_LIST = arch_bsps + + for ab in arch_bsps: + conf.setenv(ab, env) + + conf.msg('Board Support Package (BSP)', ab, 'YELLOW') + + # + # Show and long commands support. + # + conf.env.SHOW_COMMANDS = show_commands + conf.env.LONG_COMMANDS = long_commands + + conf.msg('Show commands', show_commands) + conf.msg('Long commands', long_commands) + + arch = _arch_from_arch_bsp(ab) + bsp = _bsp_from_arch_bsp(ab) + + conf.env.ARCH_BSP = '%s/%s' % (arch.split('-')[0], bsp) + + conf.env.RTEMS_PATH = rtems_path + conf.env.RTEMS_VERSION = rtems_version + conf.env.RTEMS_ARCH_BSP = ab + conf.env.RTEMS_ARCH = arch.split('-')[0] + conf.env.RTEMS_ARCH_RTEMS = arch + conf.env.RTEMS_BSP = bsp + + tools = _find_tools(conf, arch, rtems_tools, tools) + for t in tools[arch]: + conf.env[t] = tools[arch][t] + + conf.load('gcc') + conf.load('g++') + conf.load('gas') + conf.load('gccdeps', tooldir = os.path.dirname(__file__)) + + # + # Get the version of the tools being used. + # + rtems_cc = conf.env.CC[0] + try: + import waflib.Context + out = conf.cmd_and_log([rtems_cc, '--version'], + output = waflib.Context.STDOUT) + except Exception as e: + conf.fatal('CC version not found: %s' % (e.stderr)) + # + # First line is the version + # + vline = out.split('\n')[0] + conf.msg('Compiler version (%s)' % (os.path.basename(rtems_cc)), + ' '.join(vline.split()[2:])) + + flags = _load_flags(conf, ab, rtems_path) + + cflags = _filter_flags('cflags', flags['CFLAGS'], + arch, rtems_path) + ldflags = _filter_flags('ldflags', flags['LDFLAGS'], + arch, rtems_path) + + conf.env.CFLAGS = cflags['cflags'] + conf.env.CXXFLAGS = cflags['cflags'] + conf.env.ASFLAGS = cflags['cflags'] + conf.env.WFLAGS = cflags['warnings'] + conf.env.RFLAGS = cflags['specs'] + conf.env.MFLAGS = cflags['machines'] + conf.env.IFLAGS = cflags['includes'] + conf.env.LINKFLAGS = cflags['cflags'] + ldflags['ldflags'] + conf.env.LIB = flags['LIB'] + conf.env.LIBPATH = ldflags['libpath'] + + conf.env.RTRACE_WRAPPER_ST = '-W %s' + + # + # Checks for various RTEMS features. + # + conf.check_cc(fragment = test_application(), + execute = False, + msg = 'Checking for a valid RTEMS BSP installation') + load_cpuopts(conf) + + # + # Add tweaks. + # + tweaks(conf, ab) + + # + # If the user has supplied a BSP specific configure function + # call it. + # + if bsp_configure: + bsp_configure(conf, ab) + + conf.setenv('', env) + + conf.env.RTEMS_TOOLS = rtems_tools + conf.env.ARCHS = archs + conf.env.ARCH_BSPS = arch_bsps + + conf.env.SHOW_COMMANDS = show_commands + conf.env.LONG_COMMANDS = long_commands + +def build(bld): + if bld.env.SHOW_COMMANDS == 'yes': + output_command_line() + if bld.env.LONG_COMMANDS == 'yes': + long_command_line() + +def load_cpuopts(conf): + options = ['RTEMS_DEBUG', + 'RTEMS_MULTIPROCESSING', + 'RTEMS_NEWLIB', + 'RTEMS_POSIX_API', + 'RTEMS_SMP', + 'RTEMS_NETWORKING'] + for opt in options: + enabled = check_cpuopt(conf, opt) + if enabled: + conf.env[opt] = 'Yes' + else: + conf.env[opt] = 'No' + +def check(conf, *k, **kw): + if 'fragment' not in kw: + kw['fragment'] = test_application() + conf.check(k, kw) + +def check_cc(conf, *k, **kw): + if 'fragment' not in kw: + kw['fragment'] = test_application() + conf.check_cc(*k, **kw) + +def check_lib_path(ctx, lib, libpath = [], mandatory = True): + lib_lib = 'lib%s.a' % (lib) + ctx.start_msg('Library %s' % (lib_lib)) + cmd = '%s %s %s -print-file-name=%s' % (' '.join(ctx.env.CC), + ' '.join(ctx.env.CFLAGS), + ' '.join(['-B' + l for l in libpath]), + lib_lib) + out = ctx.cmd_and_log(cmd) + out = os.path.normpath(out.strip()) + if out == lib_lib: + if mandatory: + ctx.fatal('The library %s not found' % (lib_lib)) + ctx.end_msg('not found') + else: + ctx.env['LIBPATH_lib%s' % (lib)] = '..' + '/..' * (ctx.path.height() - 1) + out + ctx.end_msg('found') + +def check_lib(ctx, libs): + if not isinstance(libs, list): + lib = [libs] + for lib in libs: + if 'LIBPATH_lib%s' % (lib) not in ctx.env: + return False + return True + +def check_cpuopt(conf, opt): + code = ['#ifndef %s' % (opt)] + code += [' #error %s is not defined' % (opt)] + code += ['#endif'] + code += ['#if %s' % (opt)] + code += [' /* %s is true */' % (opt)] + code += ['#else'] + code += [' #error %s is false' % (opt)] + code += ['#endif'] + try: + conf.check_cc(fragment = test_application(code), + execute = False, + msg = 'Checking for %s' % (opt)) + except conf.errors.WafError: + return False; + return True + +def tweaks(conf, arch_bsp): + # + # Hack to work around NIOS2 naming. + # + if conf.env.RTEMS_ARCH in ['nios2']: + conf.env.OBJCOPY_FLAGS = ['-O', 'elf32-littlenios2'] + elif conf.env.RTEMS_ARCH in ['arm']: + conf.env.OBJCOPY_FLAGS = ['-I', 'binary', '-O', 'elf32-littlearm'] + else: + conf.env.OBJCOPY_FLAGS = ['-O', 'elf32-' + conf.env.RTEMS_ARCH] + + # + # Check for a i386 PC bsp. + # + if re.match('i386-.*-pc[3456]86', arch_bsp) is not None: + conf.env.LINKFLAGS += ['-Wl,-Ttext,0x00100000'] + + if '-ffunction-sections' in conf.env.CFLAGS: + conf.env.LINKFLAGS += ['-Wl,--gc-sections'] + +def check_options(ctx, prefix, rtems_tools, rtems_path, rtems_version, rtems_archs, rtems_bsps): + # + # Set defaults + # + if rtems_version is None: + if rtems_default_version is None: + m = re.compile('[^0-9.]*([0-9.]+)$').match(prefix) + if m: + rtems_version = m.group(1) + else: + ctx.fatal('RTEMS version cannot derived from prefix: ' + prefix) + else: + rtems_version = rtems_default_version + if rtems_path is None: + rtems_path = prefix + if rtems_tools is None: + rtems_tools = rtems_path + + # + # Check the paths are valid. + # + if not os.path.exists(rtems_path): + ctx.fatal('RTEMS path not found.') + if os.path.exists(os.path.join(rtems_path, 'lib', 'pkgconfig')): + rtems_config = None + elif os.path.exists(os.path.join(rtems_path, 'rtems-config')): + rtems_config = os.path.join(rtems_path, 'rtems-config') + else: + ctx.fatal('RTEMS path is not valid. No lib/pkgconfig or rtems-config found.') + rtems_share_rtems_version = os.path.join(rtems_path, 'share', 'rtems' + rtems_version) + if not os.path.exists(os.path.join(rtems_share_rtems_version)): + ctx.fatal('RTEMS path is not valid, "%s" not found.' % (rtems_share_rtems_version)) + + # + # We can more than one path to tools. This happens when testing different + # versions. + # + rt = rtems_tools.split(',') + tools = [] + for path in rt: + if not os.path.exists(path): + ctx.fatal('RTEMS tools path not found: ' + path) + if not os.path.exists(os.path.join(path, 'bin')): + ctx.fatal('RTEMS tools path does not contain a \'bin\' directory: ' + path) + tools += [os.path.join(path, 'bin')] + + # + # Filter the tools. + # + tools = filter(ctx, 'tools', tools) + + # + # Match the archs requested against the ones found. If the user + # wants all (default) set all used. + # + if rtems_archs == 'all': + archs = _find_installed_archs(rtems_config, rtems_path, rtems_version) + else: + archs = _check_archs(rtems_config, rtems_archs, rtems_path, rtems_version) + + # + # Filter the architectures. + # + archs = filter(ctx, 'archs', archs) + + # + # We some. + # + if len(archs) == 0: + ctx.fatal('Could not find any architectures') + + # + # Get the list of valid BSPs. This process filters the architectures + # to those referenced by the BSPs. + # + if rtems_bsps == 'all': + arch_bsps = _find_installed_arch_bsps(rtems_config, rtems_path, archs, rtems_version) + else: + arch_bsps = _check_arch_bsps(rtems_bsps, rtems_config, rtems_path, archs, rtems_version) + + if len(arch_bsps) == 0: + ctx.fatal('No valid arch/bsps found') + + # + # Filter the bsps. + # + arch_bsps = filter(ctx, 'bsps', arch_bsps) + + return rtems_version, rtems_path, tools, archs, arch_bsps + +def check_env(ctx, *env_vars): + for v in env_vars: + if v not in ctx.env or len(ctx.env[v]) == 0: + return False + return True + +def check(ctx, option, setting = 'Yes'): + if option in ctx.env: + if isinstance(setting, bool): + return True + return ctx.env[option] == setting + return False + +def check_debug(ctx): + return check(ctx, 'RTEMS_DEBUG') + +def check_multiprocessing(ctx): + return check(ctx, 'RTEMS_MULTIPROCESSING') + +def check_newlib(ctx): + return check(ctx, 'RTEMS_NEWLIB') + +def check_posix(ctx): + return check(ctx, 'RTEMS_POSIX_API') + +def check_smp(ctx): + return check(ctx, 'RTEMS_SMP') + +def check_networking(ctx): + return check(ctx, 'RTEMS_NETWORKING') + +def arch(arch_bsp): + """ Given an arch/bsp return the architecture.""" + return _arch_from_arch_bsp(arch_bsp).split('-')[0] + +def bsp(arch_bsp): + """ Given an arch/bsp return the BSP.""" + return _bsp_from_arch_bsp(arch_bsp) + +def arch_bsps(ctx): + """ Return the list of arch/bsps we are building.""" + return ctx.env.ARCH_BSPS + +def arch_bsp_env(ctx, arch_bsp): + return ctx.env_of_name(arch_bsp).derive() + +def filter(ctx, filter, items): + if rtems_filters is None: + return items + if type(rtems_filters) is not dict: + ctx.fatal("Invalid RTEMS filter type, " \ + "ie { 'tools': { 'in': [], 'out': [] }, 'arch': {}, 'bsps': {} }") + if filter not in rtems_filters: + return items + items_in = [] + items_out = [] + if 'in' in rtems_filters[filter]: + items_in = copy.copy(rtems_filters[filter]['in']) + if 'out' in rtems_filters[filter]: + items_out = copy.copy(rtems_filters[filter]['out']) + filtered_items = [] + for i in items: + item = i + ab = '%s/%s' % (arch(item), bsp(item)) + for inre in items_in: + if re.compile(inre).match(ab): + items_in.remove(inre) + filtered_items += [item] + item = None + break + if item is not None: + for outre in items_out: + if re.compile(outre).match(ab): + item = None + break + if item is not None: + filtered_items += [item] + if len(items_in) != 0: + ctx.fatal('Following %s not found: %s' % (filter, ', '.join(items_in))) + return sorted(filtered_items) + +def arch_rtems_version(version, arch): + """ Return the RTEMS architecture path, ie sparc-rtems4.11.""" + return '%s-rtems%s' % (arch, version) + +def arch_bsp_path(version, arch_bsp): + """ Return the BSP path.""" + return '%s/%s' % (arch_rtems_version(version, arch(arch_bsp)), bsp(arch_bsp)) + +def arch_bsp_include_path(version, arch_bsp): + """ Return the BSP include path.""" + return '%s/lib/include' % (arch_bsp_path(version, arch_bsp)) + +def arch_bsp_lib_path(version, arch_bsp): + """ Return the BSP library path. """ + return '%s/lib' % (arch_bsp_path(version, arch_bsp)) + +def library_path(library, cc, cflags): + cmd = cc + cflags + ['-print-file-name=%s' % library] + a = subprocess.check_output(cmd) + lib = os.path.abspath(a.strip()) + if os.path.exists(lib): + return os.path.dirname(lib) + return None + +def root_filesystem(bld, name, files, tar, obj): + tar_rule = 'tar -cf ${TGT} --format=ustar -C ../.. $(echo "${SRC}" | sed -e \'s/\.\.\/\.\.\///g\')' + if windows: + tar_rule = 'sh -c "%s"' % (tar_rule) + bld(name = name + '_tar', + target = tar, + source = files, + rule = tar_rule) + bld.objects(name = name, + target = obj, + source = tar, + rule = '${OBJCOPY} -I binary -B ${RTEMS_ARCH} ${OBJCOPY_FLAGS} ${SRC} ${TGT}') + +def clone_tasks(bld): + if bld.cmd == 'build': + for obj in bld.all_task_gen[:]: + for x in arch_bsp: + cloned_obj = obj.clone(x) + kind = Options.options.build_kind + if kind.find(x) < 0: + cloned_obj.posted = True + obj.posted = True + +# +# From the demos. Use this to get the command to cut+paste to play. +# +def output_command_line(): + # first, display strings, people like them + from waflib import Utils, Logs + from waflib.Context import Context + def exec_command(self, cmd, **kw): + subprocess = Utils.subprocess + kw['shell'] = isinstance(cmd, str) + if isinstance(cmd, str): + Logs.info('%s' % cmd) + else: + cmdstr = ' '.join(cmd) + Logs.info('(%d) %s' % (len(cmdstr), cmdstr)) # here is the change + if not isinstance(kw['cwd'], str): + kw['cwd'] = str(kw['cwd']) + Logs.debug('runner_env: kw=%s' % kw) + try: + if self.logger: + self.logger.info(cmd) + kw['stdout'] = kw['stderr'] = subprocess.PIPE + p = subprocess.Popen(cmd, **kw) + (out, err) = p.communicate() + if out: + self.logger.debug('out: %s' % out.decode(sys.stdout.encoding or 'iso8859-1')) + if err: + self.logger.error('err: %s' % err.decode(sys.stdout.encoding or 'iso8859-1')) + return p.returncode + else: + p = subprocess.Popen(cmd, **kw) + return p.wait() + except OSError: + return -1 + Context.exec_command = exec_command + + # Change the outputs for tasks too + from waflib.Task import Task + def display(self): + return '' # no output on empty strings + + Task.__str__ = display + +# +# From the extras. Use this to support long command lines. +# +def long_command_line(): + def exec_command(self, cmd, **kw): + # workaround for command line length limit: + # http://support.microsoft.com/kb/830473 + import tempfile + tmp = None + try: + if not isinstance(cmd, str) and len(str(cmd)) > 8192: + (fd, tmp) = tempfile.mkstemp(dir=self.generator.bld.bldnode.abspath()) + flat = ['"%s"' % x.replace('\\', '\\\\').replace('"', '\\"') for x in cmd[1:]] + try: + os.write(fd, ' '.join(flat).encode()) + finally: + if tmp: + os.close(fd) + # Line may be very long: + # Logs.debug('runner:' + ' '.join(flat)) + cmd = [cmd[0], '@' + tmp] + ret = super(self.__class__, self).exec_command(cmd, **kw) + finally: + if tmp: + os.remove(tmp) + return ret + for k in 'c cxx cprogram cxxprogram cshlib cxxshlib cstlib cxxstlib'.split(): + cls = Task.classes.get(k) + if cls: + derived_class = type(k, (cls,), {}) + derived_class.exec_command = exec_command + if hasattr(cls, 'hcode'): + derived_class.hcode = cls.hcode + +def _find_tools(conf, arch, paths, tools): + if arch not in tools: + arch_tools = {} + arch_tools['CC'] = conf.find_program([arch + '-gcc'], path_list = paths) + arch_tools['CXX'] = conf.find_program([arch + '-g++'], path_list = paths) + arch_tools['LINK_CC'] = arch_tools['CC'] + arch_tools['LINK_CXX'] = arch_tools['CXX'] + arch_tools['AS'] = conf.find_program([arch + '-gcc'], path_list = paths) + arch_tools['LD'] = conf.find_program([arch + '-ld'], path_list = paths) + arch_tools['AR'] = conf.find_program([arch + '-ar'], path_list = paths) + arch_tools['NM'] = conf.find_program([arch + '-nm'], path_list = paths) + arch_tools['OBJDUMP'] = conf.find_program([arch + '-objdump'], path_list = paths) + arch_tools['OBJCOPY'] = conf.find_program([arch + '-objcopy'], path_list = paths) + arch_tools['READELF'] = conf.find_program([arch + '-readelf'], path_list = paths) + arch_tools['STRIP'] = conf.find_program([arch + '-strip'], path_list = paths) + arch_tools['RANLIB'] = conf.find_program([arch + '-ranlib'], path_list = paths) + arch_tools['RTEMS_LD'] = conf.find_program(['rtems-ld'], path_list = paths, + mandatory = False) + arch_tools['RTEMS_TLD'] = conf.find_program(['rtems-tld'], path_list = paths, + mandatory = False) + arch_tools['RTEMS_SYMS'] = conf.find_program(['rtems-syms'], path_list = paths, + mandatory = False) + arch_tools['RTEMS_BIN2C'] = conf.find_program(['rtems-bin2c'], path_list = paths, + mandatory = False) + arch_tools['TAR'] = conf.find_program(['tar'], mandatory = False) + tools[arch] = arch_tools + return tools + +def _find_installed_archs(config, path, version): + archs = [] + if config is None: + for d in os.listdir(path): + if d.endswith('-rtems' + version): + archs += [d] + else: + a = subprocess.check_output([config, '--list-format', '"%(arch)s"']) + a = a[:-1].replace('"', '') + archs = set(a.split()) + archs = ['%s-rtems%s' % (x, version) for x in archs] + archs.sort() + return archs + +def _check_archs(config, req, path, version): + installed = _find_installed_archs(config, path, version) + archs = [] + for a in req.split(','): + arch = a + '-rtems' + version + if arch in installed: + archs += [arch] + archs.sort() + return archs + +def _find_installed_arch_bsps(config, path, archs, version): + arch_bsps = [] + if config is None: + for f in os.listdir(_pkgconfig_path(path)): + if f.endswith('.pc'): + if _arch_from_arch_bsp(f[:-3]) in archs: + arch_bsps += [f[:-3]] + else: + ab = subprocess.check_output([config, '--list-format']) + ab = ab[:-1].replace('"', '') + ab = ab.replace('/', '-rtems%s-' % (version)) + arch_bsps = [x for x in set(ab.split())] + arch_bsps.sort() + return arch_bsps + +def _check_arch_bsps(req, config, path, archs, version): + archs_bsps = [] + for ab in req.split(','): + abl = ab.split('/') + if len(abl) != 2: + return [] + found = False + for arch in archs: + a = '%s-rtems%s' % (abl[0], version) + if a == arch: + found = True + break + if not found: + return [] + archs_bsps += ['%s-%s' % (a, abl[1])] + if len(archs_bsps) == 0: + return [] + installed = _find_installed_arch_bsps(config, path, archs, version) + bsps = [] + for b in archs_bsps: + if b in installed: + bsps += [b] + bsps.sort() + return bsps + +def _arch_from_arch_bsp(arch_bsp): + return '-'.join(arch_bsp.split('-')[:2]) + +def _bsp_from_arch_bsp(arch_bsp): + return '-'.join(arch_bsp.split('-')[2:]) + +def _pkgconfig_path(path): + return os.path.join(path, 'lib', 'pkgconfig') + +def _load_flags(conf, arch_bsp, path): + if not os.path.exists(path): + ctx.fatal('RTEMS path not found.') + if os.path.exists(_pkgconfig_path(path)): + pc = os.path.join(_pkgconfig_path(path), arch_bsp + '.pc') + conf.to_log('Opening and load pkgconfig: ' + pc) + pkg = pkgconfig.package(pc) + config = None + elif os.path.exists(os.path.join(path, 'rtems-config')): + config = os.path.join(path, 'rtems-config') + pkg = None + flags = {} + _log_header(conf) + flags['CFLAGS'] = _load_flags_set('CFLAGS', arch_bsp, conf, config, pkg) + flags['LDFLAGS'] = _load_flags_set('LDFLAGS', arch_bsp, conf, config, pkg) + flags['LIB'] = _load_flags_set('LIB', arch_bsp, conf, config, pkg) + # + # Handle gccdeps flags. + # + if '-MMD' in conf.env['CFLAGS']: + flags['CFLAGS'] += ['-MMD'] + return flags + +def _load_flags_set(flags, arch_bsp, conf, config, pkg): + conf.to_log('%s ->' % flags) + if pkg is not None: + flagstr = '' + try: + flagstr = pkg.get(flags) + except pkgconfig.error as e: + conf.to_log('pkconfig warning: ' + e.msg) + conf.to_log(' ' + flagstr) + else: + flags_map = { 'CFLAGS': '--cflags', + 'LDFLAGS': '--ldflags', + 'LIB': '--libs' } + ab = arch_bsp.split('-') + #conf.check_cfg(path = config, + # package = '', + # uselib_store = 'rtems', + # args = '--bsp %s/%s %s' % (ab[0], ab[2], flags_map[flags])) + #print conf.env + #print '%r' % conf + #flagstr = '-l -c' + flagstr = subprocess.check_output([config, '--bsp', '%s/%s' % (ab[0], ab[2]), flags_map[flags]]) + #print flags, ">>>>", flagstr + if flags == 'CFLAGS': + flagstr += ' -DWAF_BUILD=1' + if flags == 'LIB': + flagstr = 'rtemscpu rtemsbsp c rtemscpu rtemsbsp' + return flagstr.split() + +def _filter_flags(label, flags, arch, rtems_path): + + flag_groups = \ + [ { 'key': 'warnings', 'path': False, 'flags': { '-W': 1 }, 'cflags': False, 'lflags': False }, + { 'key': 'includes', 'path': True, 'flags': { '-I': 1, '-isystem': 2, '-sysroot': 2 } }, + { 'key': 'libpath', 'path': True, 'flags': { '-L': 1 } }, + { 'key': 'machines', 'path': True, 'flags': { '-O': 1, '-m': 1, '-f': 1, '-G': 1, '-E': 1 } }, + { 'key': 'prepro', 'path': False, 'flags': { '-MMD': 1 } }, + { 'key': 'specs', 'path': True, 'flags': { '-q': 1, '-B': 2, '--specs': 2 } } ] + + flags = _strip_cflags(flags) + + _flags = { label: [] } + for fg in flag_groups: + _flags[fg['key']] = [] + + iflags = iter(flags) + for opt in iflags: + in_label = True + opts = [] + for fg in flag_groups: + key = fg['key'] + for flag in fg['flags']: + if opt.startswith(flag): + opt_count = fg['flags'][flag] + if opt_count > 1: + if opt != flag: + opt_count -= 1 + if fg['path'] and arch in opt: + opt = '%s%s/%s' % (flag, rtems_path, + opt[opt.find(arch):]) + opts += [opt] + for c in range(1, opt_count): + opt = next(iflags) + if fg['path'] and arch in opt: + opt = '%s%s/%s' % (f, rtems_path, + opt[opt.find(arch):]) + opts += [opt] + _flags[key] += opts + if label in fg and not fg[label]: + in_label = False + break + if in_label: + _flags[label] += opts + return _flags + +def _strip_cflags(cflags): + _cflags = [] + for o in cflags: + if o.startswith('-O'): + pass + elif o.startswith('-g'): + pass + else: + _cflags += [o] + return _cflags + +def _log_header(conf): + conf.to_log('-----------------------------------------') + +def _get_dir_hash(bld): + from waflib import ConfigSet, Options + import hashlib + + env = ConfigSet.ConfigSet() + env.load(Options.lockfile) + prefix = env.options['prefix'] + shahash = hashlib.sha1() + + for root, dirs, files in os.walk(prefix): + for names in files: + filepath = os.path.join(root, names) + try: + f1 = open(filepath, 'rb') + except: + f1.close() + continue + + while 1: + buf = f1.read(4096) + if not buf: + break + shahash.update(hashlib.sha1(buf).hexdigest()) + f1.close() + return shahash.hexdigest() + +def test_uninstall(bld): + from os import sys + + print('Test: uninstall') + initial_hash = _get_dir_hash(bld) + print('Preinstall hash: %s' % (initial_hash)) + try: + subprocess.call(['waf', 'install']) + subprocess.call(['waf', 'uninstall']) + except: + subprocess.call(['./waf', 'install']) + subprocess.call(['./waf', 'uninstall']) + final_hash = _get_dir_hash(bld) + print('Post install hash: %s' % (final_hash)) + + if (initial_hash == final_hash): + print("Test successful") + else: + print("Test failed") + +from waflib import Task +from waflib import TaskGen +from waflib import Utils +from waflib import Node +from waflib.Tools.ccroot import link_task, USELIB_VARS + +USELIB_VARS['rap'] = set(['RTEMS_LINKFLAGS']) +USELIB_VARS['rtrace'] = set(['RTRACE_FLAGS', 'RTRACE_CFG', 'RTRACE_WRAPPER', 'RTRACE_LINKCMDS']) + +class rap(link_task): + "Link object files into a RTEMS application" + run_str = '${RTEMS_LD} ${RTEMS_LINKFLAGS} --cc ${CC} ${SRC} -o ${TGT[0].abspath()} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}' + ext_out = ['.rap'] + vars = ['RTEMS_LINKFLAGS', 'LINKDEPS'] + inst_to = '${BINDIR}' + +class rtrace(link_task): + "Link object files into a RTEMS trace application" + run_str = '${RTEMS_TLD} ${RTACE_FLAGS} ${RTRACE_WRAPPER_ST:RTRACE_WRAPPER} -C ${RTRACE_CFG} -r ${RTEMS_PATH} -B ${ARCH_BSP} -c ${CC} -l ${CC} -- ${SRC} ${LINKFLAGS} ${RTRACE_LINKFLAGS} -o ${TGT[0].abspath()} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}' + ext_out = ['.texe'] + vars = ['RTRACE_FLAGS', 'RTRACE_CFG', 'RTRACE_WRAPER', 'RTRACE_LINKFLAGS', 'LINKDEPS'] + inst_to = '${BINDIR}' + color = 'PINK' diff --git a/rtems/hello/rtems_waf/rtems_bsd.py b/rtems/hello/rtems_waf/rtems_bsd.py new file mode 100644 index 0000000..f28ef1c --- /dev/null +++ b/rtems/hello/rtems_waf/rtems_bsd.py @@ -0,0 +1,150 @@ +# +# RTEMS Project (https://www.rtems.org/) +# +# Copyright (c) 2016 Chris Johns . All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from __future__ import print_function + +import os.path + +try: + import rtems_waf.rtems as rtems +except: + print("error: no rtems_waf module") + import sys + sys.exit(1) + +def init(ctx): + pass + +def options(opt): + opt.add_option('--net-config', + default = 'config.inc', + dest = 'net_config', + help = 'Network test configuration.') + opt.add_option('--rtems-libbsd', + action = 'store', + default = None, + dest = 'rtems_libbsd', + help = 'Path to install RTEMS LibBSD (defauls to prefix).') + +def bsp_configure(conf, arch_bsp, mandatory = True): + configure = mandatory + + if not mandatory and conf.options.rtems_libbsd is not None: + configure = True + + if configure: + conf.msg('RTEMS LibBSD', + rtems.arch(arch_bsp) + '/' + rtems.bsp(arch_bsp), + 'YELLOW') + + conf.check(header_name = 'dlfcn.h', features = 'c') + if not rtems.check_posix(conf): + conf.fatal('RTEMS kernel POSIX support is disabled; ' + + 'configure RTEMS with --enable-posix') + if rtems.check_networking(conf): + conf.fatal('RTEMS kernel contains the old network support; ' + + 'configure RTEMS with --disable-networking') + rtems_libbsd_path = conf.options.rtems_libbsd + if rtems_libbsd_path is None: + if conf.options.rtems is None: + rtems_libbsd_path = conf.options.rtems + else: + rtems_libbsd_path = conf.env.PREFIX + + if not os.path.exists(rtems_libbsd_path): + conf.fatal('RTEMS LibBSD path not found: %s' % (rtems_libbsd_path)) + + rtems_libbsd_inc_path = os.path.join(rtems_libbsd_path, + rtems.arch_bsp_include_path(conf.env.RTEMS_VERSION, + conf.env.RTEMS_ARCH_BSP)) + rtems_libbsd_lib_path = os.path.join(rtems_libbsd_path, + rtems.arch_bsp_lib_path(conf.env.RTEMS_VERSION, + conf.env.RTEMS_ARCH_BSP)) + + conf.env.IFLAGS += [rtems_libbsd_inc_path] + conf.check(header_name = 'machine/rtems-bsd-sysinit.h', + features = 'c', + includes = conf.env.IFLAGS) + + conf.env.RTEMS_LIBBSD = 'Yes' + conf.env.INCLUDES = conf.env.IFLAGS + conf.env.LIBPATH += [rtems_libbsd_lib_path] + conf.env.LIB += ['bsd', 'z', 'm'] + + configure_net_config(conf, arch_bsp) + +def configure_net_config(conf, arch_bsp): + if check_libbsd(conf) and conf.options.net_config is not None: + net_config = conf.options.net_config + + if not os.path.exists(net_config): + conf.fatal('network configuraiton \'%s\' not found' % (net_config)) + + try: + net_cfg_lines = open(net_config).readlines() + except: + conf.fatal('network configuraiton \'%s\' read failed' % (net_config)) + + tags = [ 'NET_CFG_SELF_IP', + 'NET_CFG_NETMASK', + 'NET_CFG_PEER_IP', + 'NET_CFG_GATEWAY_IP' ] + + lc = 0 + sed = 'sed ' + defines = [] + for l in net_cfg_lines: + lc += 1 + if l.strip().startswith('NET_CFG_'): + ls = l.split('=') + if len(ls) != 2: + conf.fatal('network configuraiton \'%s\' ' + \ + 'parse error: %d: %s' % (net_config, lc, l)) + lhs = ls[0].strip() + rhs = ls[1].strip() + for t in tags: + if lhs.startswith(t): + conf.env[lhs] = rhs + sed += "-e 's/@%s@/%s/'" % (lhs, rhs) + defines += ['%s="%s"' % (lhs, rhs)] + + conf.env.NET_CONFIG = net_config + conf.env.NET_CONFIG_SED = sed + conf.env.NET_CONFIG_DEFINES = ','.join(defines) + + conf.msg('Net Config', 'found', 'YELLOW') + +def check_libbsd(ctx): + return rtems.check(ctx, 'RTEMS_LIBBSD') + +def check_net_config(ctx): + return rtems.check(ctx, 'NET_CONFIG', setting = True) + +def net_config_header(ctx, target): + ctx(target = target, + source = "rtems_waf/network-config.h.in", + rule = sed + " < ${SRC} > ${TGT}", + update_outputs = True) diff --git a/rtems/hello/waf b/rtems/hello/waf new file mode 100755 index 0000000..7ceee16 --- /dev/null +++ b/rtems/hello/waf @@ -0,0 +1,173 @@ +#!/usr/bin/env python +# encoding: latin-1 +# Thomas Nagy, 2005-2018 +# +""" +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +""" + +import os, sys, inspect + +VERSION="2.0.19" +REVISION="1f3c580272b15a03d2566843c5fe872a" +GIT="61ee22b598cf80e260beb64e475966f58b304d0d" +INSTALL='' +C1='#6' +C2='#.' +C3='#%' +cwd = os.getcwd() +join = os.path.join + + +WAF='waf' +def b(x): + return x +if sys.hexversion>0x300000f: + WAF='waf3' + def b(x): + return x.encode() + +def err(m): + print(('\033[91mError: %s\033[0m' % m)) + sys.exit(1) + +def unpack_wafdir(dir, src): + f = open(src,'rb') + c = 'corrupt archive (%d)' + while 1: + line = f.readline() + if not line: err('run waf-light from a folder containing waflib') + if line == b('#==>\n'): + txt = f.readline() + if not txt: err(c % 1) + if f.readline() != b('#<==\n'): err(c % 2) + break + if not txt: err(c % 3) + txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r')).replace(b(C3), b('\x00')) + + import shutil, tarfile + try: shutil.rmtree(dir) + except OSError: pass + try: + for x in ('Tools', 'extras'): + os.makedirs(join(dir, 'waflib', x)) + except OSError: + err("Cannot unpack waf lib into %s\nMove waf in a writable directory" % dir) + + os.chdir(dir) + tmp = 't.bz2' + t = open(tmp,'wb') + try: t.write(txt) + finally: t.close() + + try: + t = tarfile.open(tmp) + except: + try: + os.system('bunzip2 t.bz2') + t = tarfile.open('t') + tmp = 't' + except: + os.chdir(cwd) + try: shutil.rmtree(dir) + except OSError: pass + err("Waf cannot be unpacked, check that bzip2 support is present") + + try: + for x in t: t.extract(x) + finally: + t.close() + + for x in ('Tools', 'extras'): + os.chmod(join('waflib',x), 493) + + if sys.hexversion<0x300000f: + sys.path = [join(dir, 'waflib')] + sys.path + import fixpy2 + fixpy2.fixdir(dir) + + os.remove(tmp) + os.chdir(cwd) + + try: dir = unicode(dir, 'mbcs') + except: pass + try: + from ctypes import windll + windll.kernel32.SetFileAttributesW(dir, 2) + except: + pass + +def test(dir): + try: + os.stat(join(dir, 'waflib')) + return os.path.abspath(dir) + except OSError: + pass + +def find_lib(): + src = os.path.abspath(inspect.getfile(inspect.getmodule(err))) + base, name = os.path.split(src) + + #devs use $WAFDIR + w=test(os.environ.get('WAFDIR', '')) + if w: return w + + #waf-light + if name.endswith('waf-light'): + w = test(base) + if w: return w + for dir in sys.path: + if test(dir): + return dir + err('waf-light requires waflib -> export WAFDIR=/folder') + + dirname = '%s-%s-%s' % (WAF, VERSION, REVISION) + for i in (INSTALL,'/usr','/usr/local','/opt'): + w = test(i + '/lib/' + dirname) + if w: return w + + #waf-local + dir = join(base, (sys.platform != 'win32' and '.' or '') + dirname) + w = test(dir) + if w: return w + + #unpack + unpack_wafdir(dir, src) + return dir + +wafdir = find_lib() +sys.path.insert(0, wafdir) + +if __name__ == '__main__': + + from waflib import Scripting + Scripting.waf_entry_point(cwd, VERSION, wafdir) + +#==> +#BZh91AY&SY9 ½´\¥ÿÿÿ³DPÿÿÿÿÿÿÿÿÿÿÿm (¬#%00e€(b÷/mЀ#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%öÞúzómmkîÖZžÞæ—²U#.´[iÚ¾îõ¹±µ–ú:¥'kd‹î7{ÛïoºµÛ¶ÖµK“¹]Øvµ'ÛßO¾ö¸gv÷s½÷¶N)#.Q+Ù½íp·µÞ]/{mš»<{guÒ‹@Ýó{§«vo;¾ø;ŸvÎiîáÉî44lºï{ß|ûëËßÚU9íõÝŸÝšî·¯y½÷½x#%#%@(}ìh#%` ï²€=âwfí˜:4§[aÓ¹½ y©³A¦€‡¸ê»´ö4=¦öìd+Ö¨ª)ífš0#6 *”¢”{ƒ’Q$#%#6#%YJzÚV½ƒ%çÍíîæ}»j½êºa’ïjÚØá3TTf˦Iv×]s}6óu7¾÷z:#.ÎxûÝW_=³ÛzÖ­åZ;Û»ÍÝÛ}Þsy¾¯³»ß{¸ûížÖîiÉÔ÷Ëzõ¶§rç>^æû}ñ¾íóÛa zúz{x¹-ìz̀ݳ­Ö²4÷³¼ÛÞ÷fÞÏs¬ô`u¡ÒãF°Û"’EE7w¼#%(J*’OCÀ#%lîè•=÷n{Ywº¹½»ÐdÜ öï>}Ü[vÇGÐ`>†ÛEmk®¥ÑMãW`×LæyÛãÚ^u½#%}÷aŽît;o¶û}|{mçO—vpòǼ΀Šo·*WµíƘܶ2>öí®®òÏŸwÖõ»]´î;ºjîí9QÚt×·Zt“ž>÷»Ü®¨ÜÙu÷‡ß|}í­«×ܬ‰&ÞíN«îq\îû½:¾Ã.ñŽ^ÙéyaC§¶Ó¶Û›—³®÷Ð¥&nCzî¤|öilöͶíÝîвë[¸˜÷»³Ûºû5ÖkoX«èqØ—nöÐl­îõÞÞ/`{´žó½wÌ>ï†Ðê¥PJªPTT´jB¹7uÐv&i¶v­Üèº]vú‰Ý›:kÛkÔØëUUܘ{x÷š)º¼»HЃºÚɯfw€#%7ZI#%#%;Ü^êåÉÎó²û3ÊF-Ÿm½ÜözÔíÝ™Üì_U.us[›¶ õv]]ó¸|˜Hû†,ÍqÑ»ÝÁæñ{c;úŒçvåJº{+¹éÔ²õ§l÷+ªWg¡»`úùÛÙ;{n#î²Ç]÷}çww»{»»xîvÛ#.¾Øú½mÝEfù‡"sž¼ï¯¼ùÚÀ°ËlÐú$/g¬íÑ”x<ïÜë°VØ6EÇ‘µÞ®ÚGxO{×>öø½ïwÞ´#%À*×Û;Fªµíí7¶;g<ÂÀëu´oSk´Ý­ëÓ­mï 9.ó’®Ú×ݬ» ݾçwÅówwtåvë¥Þç:#.[.ëwc Ó‚àéÕhÁ”gu“½Þ^ïŸnØu¼ÓÐŒ…/=ÝÚ4#%•c¹éî½Mö{ÜàìJ…U )½{xW»´×`ï{®ñÝÊäÅÖÃV¶•U[}÷IzovƒuÇH*Ší·u­$ëIÒÖªîúãÞncÚ[ÓµŽÛ× &Æ»»}öøø‡½óí·³acÜ| ìÁ“G»îñÌͼÜ&:·»}½í6µîÐíç;ï¹ßvÛRÀîï·Ÿw}-âòó[ãnh€ &€#%&€ £CBa0š#.#%‰ä™PÏTz†Ðš#%õ§’{SÔõA) B @†@©©á$zzI☠é4#%#%#%#%#%#%#%‚D!  M5TÿMŠoU<ÔôzTý(òÔõ)é¨mG¨#%#%Ñ£@#%#%'ªRD!4dÐODõ$ÙOFž¡£õM#.€ò@#.Sj#%#%#%#%#%#%$!#%&@bh&M#%M#.4SÓiˆŒ4 ¢ #%h#%#%#%I¨ˆ L˜#Až€&Œ¦=&”õmêˆ{SIé” h#%d4#%È#%—ÿÓ?£Uirê\ÕQWwk¹úµZvhʃ>5Zu!LA³ ,L•Q*"€)æ°Pcõ§óü Zü“•5OùÓ¦¸ üæJt¦î£Ä‘8•WoT"¢]^SÌÆ´_3ý†os2ì ÀlDs‚4;m»qE6­›®ñ‘ÎÊ­´ÚMí˜ÖØ`Vd…â]jíâ—˜•5o‚# åñ÷UŒI7wD¼áÌKUå¦/žÝ~«oÔBäE"ªSº»U¦ÖÖ5k3khÈ‹ €7#%H*-E Õ:¥”$HŠ& ˆ" HåP° !ß#%hŠ–‚¡#%ª$@d PÉ@mªfL…’ŒÍCLÓd@M$Rj6Ñ35–25)F”Sm&‰š$ÐJ2ZšQ°h[Fi,ši¢Z!#.F)iM€F¥ #.1eM£DRl–¨Š–ZSMhˆYi#.š ƒ(ÌÌcRF£Qµ&ƒJl†BjcI@˜hÒËHÆR›F¦›"[M¶³U´i˜’ÆfLÈM& ²m¦ÛM65%)-5±–¦Û3fZL“1‘f´ÄÑd¢‚™l‰B!Qf‘´R`4TH!`ؤ©„f•Jb0lB ‘XhdFIR&B4±ClÍ ’&)BFRÊËf$@ÒYŠY5“ccE#6‘d†K) -)¦ ±%&EDš2hhɉIF‘($@VAMEˆ¢fRÒ¦`›É ؉1M Í‚ab6¤Ø–V‹$”›‚$´”PRD•’%¤Q0EaÆIL# ”&RJME™±£XHÒjH’b iM$"H²[bË2ŠFÌ’‰²™3bdE(Í‘˜&U4Ä‹)A³Q`,i¦†Æ"5+%’6(”R"šIˆ&¤a³LcI¡ &¤–Q”Ôi3HÚ("šh¢kP,&YA¤²2‹%&DÐM2‘*4f6”)1¨6ÄÊA! "“1F4,Ë ŠÙ&TÌÕ˜£l¥±(‰™#.H¦!HŒØСYM$QF¤É&ÉØÆJšF¦h±b2’™˜²2³i„¬D`ˆ¢JM52i™!Œ¢)#.š1Sb‹5*R’š)#.‘“2)´…HÅ(ÊHR"‹E$˜’M)´i5DŠFÀ˜Œh&Ti¦DÚ#.ƒ,„Òe‹DÈY‘¦ÉJb”D!f™ k6lmd°$4–Ld5EPZ XR$Ècc1 Â2ƒRXÔY¤J&ŒE©M(Z˜hI™IŠ$2ɲ#)‚E,Ñ¥1„5„²e"$4M¶¦¶´`™BjfŒ¦F&”RLȈ­¥6À¥š,Å&‘”%–TÙ¢-L¬-”bC؈RˆšD#HJm~Ãk¢¦©aˆÍ¢ŒlVƶ*6L¥4ÔR¤š44´…¨ØFÉ5Y†¡¦c(ÉS*H¶D‰™¦[%´Q‰IKQµ…£&˜D±5˜±acR#6e¥™2eI´*Ò4TÙB+dË"©TÒT›63š¶,Y­“L¬‰S,¦ÖJ²ÙJSLl’‘µ)¬±%¤2RÔZ ªŒ!¨Õ£%AEVMd£jŠÅEH”kDÑ$m‹hÅŠÔl2ѵ€´™0°U@i€”R £F2™&•¦±Ʀ&±‹d‹i Õª–µ–* ”ÍKY4IR1!M¤lY"¶¥Y¶1Jm*–R¦YaZšDF¶•K"e5MM¶„”Êk,Xl²k+,…lÓ  ¨ÒD…bÃ4˜‰!´…-£T%¢†KQY&š6LšJ,ˆ&ËŠl¤#."+,‚E1”ÌJ”lÓ4 AE¢Ó$&Fm6“F6ÆÈS¦™cE%bHÌÔ#!4LÔQ¢JdR–P5BTÀ4˜Ó J™²Bj-#636£)F̤’Œ£!HbÊkÃi4F5&Éa $YP…-4) Äš4Y”©””²•˜d¬aš,‘± jE¨Õ5£4ECF¥)6b¥fQj4  2ÆA¦&Ä•%I”1Ršcd¤Ía)ME`Û0Ù¤²lf“E˜‰CJ2Zfµ‘hTÍ2–H’l£0D2hªih¬Òl”Ä,LDÒRBAh´[ Q¨ÔQŠÆ-–ÃI†’M#6LŒRˆ#b-f›C2ˆ6*2%,¤©‘Ñ´k£TI¢„Ë5EŠ$Ôš£PdðŒj”¡kA¥4Ë!E$Š¦Ih‚5Eˆ±JÛ"¥F±¤ÁdÑÌ¡jQHfJ$©±(‰•j#V#.2,Y*6Œ)‹4¢Ù2V-­&)+)¶D¶M¡¢T’™R¢Âƒccd£dÑ&#¶HÔRLÁ¬ÉƒA#6)³6&"šÆ¨©•“Y‘¤)¤šŠ¢Š&›RV-”’ÆɈ£F‚4˜2JÔˆÑie£he¨’ÑjŠ±”£i5² …Q¶5%)ЙÈ̌ƚ‘LÙ&kDlU%‹hÔ•,«&´LÚ1lj £cc$UE2©¥XÚ6¶1mI˜ÊQ f²±-F+iQµ´©QJV”f*šB (4X"J&ØÖ,Ê’+I[M²“+FbbÑIE[l¶¬R&T*&$¢1PÀ"CFŠi&ÔÃ%XÛØ´Í[F5¬´•42ÖÊY6ÔÔÛ!mI¦¬ME26’QA°ÖjMI™²Êˆ B¢LI&RLˆÈÄd"Ù-¢Ñ‚±“þn··ýÔ¥C)þB51jÄÿTqôe+(a(Æh”‡÷!þ§ ûbåÕ LÿL$hÒlùNzí¿Îó±½9¿‹øºô·¦SUIPª?ë[ŒlÈŸÎÿ·ÖYLâsÈ †ßùë;L(0\:8À¥‰pÁI äˆd˜*ƒ‰Ãß±¢rý*¤çÿœ3ÿ³ôZÑÿÊI(R×+ˆ½”g™,$b/­Í0ÿ-‹npz%ZM‡¼íõâ8ßwB¹ÁŒ¨d~Ë Õ‹NØœ“ÆZþ,3cRR(l“ŠrrXˆþúݳf¤áV…cÈÌ`I¥Û"lÆLhƒcôzç““G]“¼î˜Þ¹w§¥^¥ã\³Ë/âuçåu™Í\‚LŠëP¦"W‹4LªvcK™@¥JAF&Ä“M‚ê×bÈ‹Ò3ˆ(êñç]¨eñnY½74h6 m `Ù—(c2@sªªzoþÝ(‘ 7p‡ Êc#6Gv…)†ì,`¼rÂü®R[ŒR}ßÒëdzçgsÅéšÐN×VÄQL0¦Ð¤Y;ùd«Ïô8$ÚÍÏ£˜ØÐØžj¤Ï(%?·râƒþ°Ãµ “ºÀ¡…†JÅxžß÷k¶Œ¶cÂx-›2KËw%€•¬C°UyáyÜ–íÞw^QŽr車esn–CQW6éçqllO²ëå5¼Z4EA¯»ºŸ?_ÆW‹ò-ȦWÅȶÆåÈIºÕø¼u‘¨Û?Go*„Èyùæ|m<™b#4L9cuPEX°ž«©#.¹t@#6A!´ä#ñÆ#.¯)ÎãÂHˆÃz”^+›Ý\Ѩ8šë•ÞwcrŽ•Ë™(Ë®é$s™5öø‘ZA„ÿhÿŒJrÈ.YÚlCÙ’,0!M ðÛtÉÈe«#6ýR­‹ÁÃ79ô,ýפ¾ìÉþ˜FtÃÏxV¬@Gô¡€dž%lþ «p’—ÇãŠUË"õÖ“UO«pi)8ª—â”+ñ §Ó¬,‰±Èj[þv¼‹lQôÇôa™1Kèë¯Ç×FÌ÷¿SªÄ7Ím‰Z½”*‰£NŒ¼Pâ-#6¬AË@‰*•{iX<ÙZøW÷»(Éðâ»EEE¼nY5ÆÕ͵þ—ìw’>ÇS6½•ß‹«¦öøÿM‡fhŠF¨%2+zmýW!†ŒbSQIðîÜ®÷uVé(i%"÷@Xš'+¬¥&D§)J²‹šå¢¶/]öï^¯"R¬•k¹bÑ_·-×»±öõÆ*Š|ý{ü=o÷îèë˜ØÔl›|ÏÀÞ1¨4–üŽ‹> õÝŒ>¬žýóL—ÖȲ"4£~"Uä¨ræPaŒLÖ¶jϹ$Â![ÙùzÛ²†F²lWßî«âøùÑÊW=ì¼4D‰Áa«l—AHÒPŤ'Ò'mBµ§…C×Gƒ¶éE2„R]U¥"»wÕ¬ü*ÔðХ߲œœ²ôî²Á‹¨ÀSE#6lÃQ MZH"JuœëJ» *”Ó#6I¢L²íãe—¥Â„S²ŠŸ$+ b¨¬N¬<ÙkH](©É#6<*žoЗçAJõ ü/•;q°óap×^Ro^X„jÅÄ"_gñ‡Ë¼ê÷Œ:+#%ñ²(\HÎpÊ6ç–´zmï*'Ü©×1Ù»á?_kŒ#.êV£„ÊFyûeo–Ðæ”$ê?•ßjfA›­vß¾ÚœNü£ƒz…$…!¨.fä³Ü¡Ï\ˆiÌ©Ê#.#¥ŠÉE0F:E&©¯}Ùž…µAîg]°éˆÃp?X7d1€á\NB=}ÙILƘ#6P#6íç;¢gä˜ý=«»†"ž<ú¹áïïRî:I2Éðˆ\õ­q.Vž)gÉ…,Õ8`¬=jPŽûí‰ÞèqëZ®#.þø¯,nM´B8÷8»è¸×µÛº†ä1ž‡i‹l÷õ m±Ï׺|š5Ì=Zí鵦üLuÙ $‘(w0©WX uÒ‘Bd˜N>ù¢Ü¸I¸ì¾½i“íE•éËÒêwë+Õ^{å5ÁZU{Š)ŠãÉÂé¨c¼T˜ì˜í§ @^†Ç¡=4´îç ʉZÛoý4^Û1¶Ã‰±öíªÆË ˜ò-—îûâû™§õoÉÜn¬æU>õéºiúK|e˨†J/±ßåÇ}m}w*IeQ92e@êÛ íhQAA9¼CrºõÝO¡¸Ëðuu5¤&÷JÃF}w/Å¡j©jŠÿ}…(© Ÿ+þ«¯½û¿éºÚ|~þëÇT•öµö°ù¥±G‘R{¨«EŠ ¢€úªS>,õ‰÷öæß»åj»çíj܇±†¿•™Yõ¿¯œõâ‚ú·+$‰þ.hÚ>n·‚ªôj£]–P‚ê©¨Æ ×¶{âÝûïg˜œå mk4µ“O§k{Ñ”ÇÛEË£õ;n”dm¥AyÑQŸ#6ÚäúÓ«f‰Í²­ãX—8T¾NL\ð—ôP苘1 øˆ63œYî y²úUM3¦ùÝ#.X˜|è¤TWù“7ìÍÇΊD^jÀEŒR,Œ)9Õß¹ÊÈ·)óÜÑŒûúuO³~™¾$_¶ÏŠ ÊsãÆ4?ŒZu>žì]1yÅøÚüžkÓEµÛX)>óOÖâm8s´Ì‚ëéÞO–z\àÚÄÚ¸;â¦R¸Á1ŠŠ~FS_tí“Rn(‘ØPñ¼b˜¤Rf“WYüÊ¡êô„cì×ùúù«ÜËÎP¼B´ ú’Y×…é¤DQQe0¨x~‚Û{*©nf £ªwiX‡T¯)œ’6-Ï;Ë£êw³$3Ê¡¶Ö}•TÛÉ|-ºz²8ï5›`BüéÝââêÖh¢’…ƒÒ¡¸É~¦™J‘‹Î€¤Z+¯¦9r¬èœlÿV´xð¨#6h6ÀêD¶x0¥Ë)AX›³£*0²¹ë¯_#.Ç·†È÷zìe¥HÙÓ,›¿µñïñ²5AòõÁÞŸŠ{žeÔË7Sú­þ¡&yÖYñ¯¥³LÅSÂœ¹¾Ù?•”¾ŽÙƒÊ-„y¯69^èŽ}ž¦pà†BI‘iK‡&±nÎǨŸþ³…éÝs»Î¹ßŽe²‚ð,¼&2:LäßÏå[‹«¸óxHÇ®*–Ø×ÒU9„åé1䌟 DL5;þ²ÏiîÐå‚„QT nUÙ‘`ÒŸ#ÍoJò4†1Sºëïv馫ÚÕéa離Mô4O|®­–I$ {U½órà¼0‡;0©*ÃzG/½7ƒ+– #%Qb ]’öÙK\.ª¸­ÌÖ‡÷) I9q×ëa¾¡—¼òó#.ÑýýïÞ5К¾ä¬×w*8ÙA—'<ß:¥˜bÊï¬2×ÂxÕQn:ú,öTl8:<ôáyï9ëCÛ¢M\¡"#.JvX¢=Êóðw¹Ô%g±œCÍ•P´GhaÑû£™ªºÅH…”ö)¬¾U.ÎõÛ™Âî‰A=†”s È«Ôs›H]#.¤ú$¢8.‹\Ó³Mìòõò³Þ› TÑTaÓMš}ª P‚ «½È¥>?‚¿½¨èØkÕborR#Rñ/ŸÌç*3ÔÆѦø–Ú4u©ð±o‰c‡ÈÞéñÇ#.vnV»pÁáã)r‹³Z”,ª£Ž.O€êÀ’·}zwîÝlnª¥Ÿ.LQøy×@EHiwýÐçç=Q›q§"%V2&0+VŒq¬¨w=Pë¦uÁ7ºV^-Eu©QQ'çU0D}ÏéÞ™Ni×ôñ$¤úÊ'1ÎK¯U=_­“lS­#6´íŠ0ã×D­1zßÆǾ+âdpÚˆô±æZ?wéžx½\`<+½—f—Jøã×~WKËÕ¸îáÝ8n©$z«G»à<c½Ì/Y€á÷ˆÓ vfˆz3ó¹L´cz7k­ù%ûÚEΛY¥ñ¹-J`]ÞBvP\ÃÚïŸHm2LˆMßwðrÈ÷4›:ðÅ’µ¼`¡‚¯\Ô½u}˜<(ñf`¨Åˆ³÷ôͽ‰UQ9c:ªO+%‰ŽöPiP/º°<H¬§`±È6,Iq¡z<À®÷±¢—Ù è‘ì#Œá?Ÿ—™}ûI”¡ÓL»_KÃ'ë—B¶Øÿ#É+ù¢ËÖò„|ÑúåµömŽ±‹ת©ü°Œá˜Ç’7û"ònþ½bôŠ#sh¡›¶¢~¥?~´›V]6k)0úô£ ¦ÙUBÕñ °Uˆ¢,õ'«@ž5ûÜ+ÏÕlŸ±X6µÉ nŒ.ö{pùèü}´:ÑÚð†y¥ªŸbsf19%¢ØñZ³æ#Ô#6 ‚ ­ê,&Ñž3|#6y€"ú.$#. #.æuµÅ.÷ éÙד»*{gd¾Š­evKfûQοí¶ÒÌð7N ›hÄe hP"1b±êL`ÅMm¬"ã-ÅX]#6=™©Õ)˜«Î#.äÓ2¿+]øºtÉg“:Ô00Y½UDà’ÆŠÛHœIå#LÇÍ’6\j¾}›Þ#.‚Û»Æ6Ñ=U S¿ÑÏÞštÌ4så Ùº"ïg³.¾‰t(ÄÉ:qþ²c1û¦³^¹ÙÈÕýÉn*fb’¢fƒÛŠãš;èXhêöÛ÷Ç1•£a¼s>¬=N#.ä÷Áý(ûqÃÙ†fT`ÒalÚÞœ~2å8ŒÀr¥‘Ÿ¦!:Y@àe ¨Öj¡Á¥N¬Íec±;8`i‰j%ÉÓcW?äDM¶@0L‚¸¤\Þ'k‘KŽ«®NºËϧcV*±FÖ˜Òßãñð³Ô9O—äÇ»éìåôÁõ*5,<:Ø’|EI$¹$G4¡Õ{âS§#%bŸeÙ‚‡TöŽ¯äìÚÈQ·Ø!û€PveòóêÞ6‚^—ø\F´÷fX= ”*´nïú>Q/ãnNQŠž#64…¯¦E¼×^Æ~ú“’`GÈ'0’õÍ\P”DØLÍÕ7؃Ku„ÑohsyÛÝQ¼ã*Sšçsƒ;5XvPÍf8uŒÁ®[˜ÝÒS¬ÝÏ’³•ÔÍ4”¹²†s?…'ÚÝ­i Î;¾n)tYG.å¯K|íMÆ×6AâÖuü×8'¶¿UÊÒ»*se¦Ü™L)e‹8«|Šãý×W#%}O`×|AÊ>ƒbm€fò†\sIÑO##y3£Bé#.⊠}ÏÕ¡n«r£CDb+ÂÛ` ì™­úÛn¨>O½Õqòh‹¼’×59·b¢ fŒ~~˜V#+bç±^Ug•:^óŽ×ÿxºTq(Ū¿1™y{T‘áâzÒÔ²?[좧s ˆÔ5YÿÆgk’ —qjûWXvã_WmMÆñuÍZ3¥Q_{=’žìã³—¦(5#ˆ‡„Âæ©CÞØ ¥Î]«m9¹ÙãHˆ X1ºÈ½7¸ÙŸdÉ-”K†OèÜû¿—ŽqÛDË‹âíÜ×s²žó#%$ÌØ@²š%"£ÏiñÁGn¦· —›šÿ¦åg­sáºÖÉÑosã¢Ñ+-¯m%b”"¹mofŽŠÁfm{pYpÐØoÆ­Z”̸ Â4¸b³Øúxì^S™ÎuÜÛzVþîlbݵ Ï°POæÀŠ:›»ˆ¾Zn(Ô#{›7)×¹L ùσãÕñÁ”€÷YÓ¡á‡õ"6zXø£°ébc™G“ë-þ7J-YSÕ–#.™[òw_#6}P$RFÂ/þª:üó²§HèCþCo:“Të–=49yz¿ÃÆÊræÄ•{´R4IÖÌom¨3 ]•F“m;Àuc£tÇloz‰Á`(]ô¿5Œ¨å¥÷!œ.º¿»ZUǤe(®™¯ù‚Ê^ŽR÷ F““Ö\«ÈÞ¬Ãô²†Ct½FŽ«X 8Ž,Ò;hŸ˜Xj¾$8ÍûYùüxpå»È6püà ·Ý¤$ÀA7ýc€%#%%"A/üÕê¢c–å9Xãßá]5GóÚY"E5É#ÁÛ/*9/„QÉ?Bu˜jÑm-Ã&é;ýz|ž¯‚££Õ¨l@'ñ(¢¹*öúi|GÀS«êÓ©ÝœKð!7ÕmVÐÒ×>ƒø³9€&u ŽÈ„ƒ#% ’ûÿÕ»Ñþ-¢îÕáø­ÇîäévÞ»¥ #.cc¢¼¢ ÎD×Ì@?Ç4#6†¡o轶j0–ê**ÂŽ¸ÙsóîÅÇ#.„¾º"MŒ\îª"ˆ¤‘ò©¹#%gíÞœá4yR™b(Ñ>@€òtÆ¡R¿šÒ]eÑ·äsvÓ Én(+VpäÿE®‘+ü'6¹†ðN°¢3¤Ä[(ZŠaÉ»I{–Þa½x=™Ž9"1ˆ[ëJ¯l ê1­H#.ªñŒŠ%OÙŒ#%”ì#%ÄcÏm¾ÿ¶ç•aùã¤þÑI‡ç³ñåú#.5™ðׯ_ó~µ?èÌO“HÅGTUÙÀM¿ƒðý¶y´»õ¨5ц6¥—Ãcj™b²ø§¹ƒƒ$|_Cºuž0€^~c_ñd° "wƒ#%°>בj>ðõ—ER=Sþñ¶s|º5ŸÛå€Ãm¶fÕ¿.Õ4|œåÝj]“³‘¨:;£únŠ>’Ÿñ:ÿn@ é )ª×fËw#.·l¾¡ßþ0}÷îâ£(WÏÎüoNßÛès’ {G4ÆÞ|ö0t9×bbÎ?GÝ÷k_ÁÉfª ž"@îkò•X/E÷;¥fL¡¦¿qößÕ5¼8±“d¢*¡â{/Ìë¿D4áÅtÉšûàûoötgS³wÓ>¬XB§<ÈIÁM•mGý—ùu…9£Š>¿zsáþ¸'^Í¡c®¶7B ªƒ+Ã…À3ïr˜\«poª_P–ÜâÛô=‚TÁÖ“æõ§º»¶4ZMI:îäÙœ³[Ê+YòÈ{Q”Óho³…`#67]±áÄRd1ÌU…²[d"ˆ—”b$#6Jk!¬gÛªLk Š$,¸ûÌ£Ö[ËúžP&¶Ï•¢U´’†ð¼U1#ÅË;§¿&b±A…1dy%*üüóŒî€¨ "/Z7—cûÿuËBˆsrœ™§¿-‘œ$ýþ~…mLÀ:z®X»U ÄDq#6“Ïß©s <=Uƒ¨~L …¯R›5¸}Š ÛVIé­³íLgï› ¦aóÓáåvº˜ÿ_E—F–– -™áG8˜Ÿ“?ûmRGÒ=bSfqÖ7¶ÆAi+sèü"Ê|;O¦$÷#I±aiñÓíÁº×®[Hå[#.º“œu€ÆÆŽ²X[È—¡J×<óÙT¢ Þº™ÆÕQjª@J’ßü.Å#%…W&û9œo…èîD@¾Àß#.âë…cû§˜A,BCG:l¡úkLuÐ#6”‘Õž ?; éõæk¬‡©÷‘ž#.qÌvÊÐ3:^LŸUÈk4Ž#6`#.~•H‰5ðÏÙž>Ãõ›÷þ}¾Ó¯‘[ŠhyѺBJ2\¡~¬dâe#/¯ÿa7·§4ãYUáCÇMs÷þ{¿ÍcB'$Å;Ç©·8¦ø¦#.{,µj€weß#.røâ^˾<0fxþîÍÎ5&Ī¦š6P·cQǘ"5Uô†÷êŸE7¥ã˜y–l)p™Ú7úµ!$—Ó8>ž{K2®rãyòUçD#¯lüw¯åz€ã=wÊ‹Ý#6Dn…¸}^æ¡}ªé«)D¥ÐŠ”‚]âuq·à¿çÛ³2±³…®\ÚS{ûìSXãÅY% qßÀn©ÇA#°óÑUá]=@tÔ³žÅj&†Â»Æ5&fîŒðpK‰ ¶˜Sd&vEÚ}´zGYÌ*B#6 ìÃQ>Gêp¬vþ—Û…m}M‚ææ‰ï¤É *Ý0ƒÞþÓpì÷Æûè|A²vB0;½–k[Èé#6¦h˜"# _ ßzéòøÍ3ã 2&ˆBžÑ…5Â6‡…ܦ2,,»¹Ç|زØR¢"ÈQˆæY¼° ÆÒƒ •ÇLkG>'ôjŽ1* Èéô‹uüi‚S1ëŒu\SdIiÆTˆ°Š²O¨6ƘڱÔá‘¢»µázl_gêÿ8hx”MöX0-ôî ê#ôéŠsüKˆòÿ5ö¨»?#%Ýyx®)–˜À’7 y#%í2òw‰ ÐPc±   Æ#%tÀ`=!#.fîÁN¯%Ò[^v…'k³Q÷Þ´R“̧`ÆzÆ) û¼nuí¶#ÎÃí?.ÒIpJ[¥iB¡×*,ÂÒÅ š=ÕÕ`„ìQ×pgc¼Iâèez«ôC,Á†f{Ê2ѪRuš„Æú 빈7©Óyå_æ>£vöt…µÆ|ú9´VKœâR˜;#6(<äwãC)ª((F‚Ïv0ñ2hÊЭŒ–ˆDÊ#0+C“9°z“˜¼•]>ÄlÑJYb¦„ÒTœ-¨¦Å¾bàèÁFrÐpõŽ*(~¨Ñäû£sÐÌꆄÊ4 u»y!jŽÐ#8±sy#.bƒn=>tzËÌh†Á¡ÈÌ\åê¦å­…bPõYÄËþ:¹Â—nT ÝÐ`¨é“Õñ턱ֽnz1»DR‘Å+‡GèobŽÊØÛÑ£ŒU$2ÖåŸ#tóëñØó^¸émÖ½¹ªO8«,›}YEω{^ÜIfxOÐpLÂÅG•#.pßú¿‡¸ÊYE³>vKUÓç¼çûˆ} šgا©Ú§^Ï­ÜøÌÍ+#%®[Ÿaœ:9Þšœ9ÉÃd×+àB~e.wµ†¼qalñwE#%{j›,dº*1—®íwyæ]®îëO‘˜ÀFŽn‘snZ*4x’m1|F¢ ˆªÝ4s¡ÊŒýÖž{Ζ¹,äl D {#%ÓDhM´ÔD)$CTÅVƨʣ}íÁ14LT.%"¸ã #%l@'D188Ö÷#.A³èòñ®$Õ^¾0Ʊ³\´h$‡{Þ®#.NUzJ);I?×$è±ØíJö»‹? v#.ê‹Ùö‰T«T¾î°¦‡ãaÆ»EÀø5vÈbãlyA}·É¹»Ròš¢C÷)K.Ç(…ösN\0p¨¨S"Ðoœ*ñ“!WTðCyp2b2„ˆè/mû¬kÙÓY¢Kn9‚†¦µJ:¸Ü­³\ü{oM—h]¥ÂŠfŒXn#6àÛ¯d Ó™Â/QƒèØ…E®‘KNÀá®WöÙ=þ= ^u¶Ã?×›íÆÊ“5çãœ+8~Ñ…ZF0oÑ›48Ã@òð_¾*Çc0Z4ÛþþJ˜°q …áF‹Ã=’tÌÐÔ%Îln¶b–Š†æ˜¦Àé˜JÞ(BwyÉ.ÅBjܘx†HÃQ•TÊ8¦4c#6Å|mñd@ñ˜#%†ŠÒ奉c‹6PºËÈaFĈ`Ÿ]ÿw&ÅççqÕ2ü2GµÐQˆ¯ŠÛš1R^+¦¯LZ¾•yïÛn@m2(ʼn£-eFK`²(euDÕ 8IwN`;ª–4,œ:$VbV66ÄPEBD 2ÙN—ßYö;üó6é}rÛ=ùk²#6_³S0¢³*¸‰B¬¥yÔy¥,ôS°X¾.‡9€¶¤Ëuª‘ë@+ë#%)|ðÆÔÔ@zæX"% F #%Às´õ‹&Á;Æzüiûç|ú¶&í•Ÿïöíˆ0t 6‚5à1”L Þ=Ùôãõ¹H 9ív ¥RÜð¿4‡Þ{m›ÇnpíÔ+ãÍ=ŒSº!tî#6oÅgcì—tn€…™©t,–Ülu„VFÆ”±#.Ù%Æ·©ƒ_NÃÕsËÏù*\¶µ8r&Aö„²ÕÚ¨N6˜‘÷KY¾#¥ö’ZÔŸŽÌì:‚w¬9§ƒUf ‰Þj  Íñ0“ÀF•‡+IŽuœ,—NcUGEæÿÏ^ۤɎà˜4ó$„Á;>)Í™n$"˃ýȵ7æÍ–Ñ ÷šÈÙf1¡ýê(v Ž h«éC5ל`ò ã{Ô R#ƒ7(HTZ'ÖcJ­:7 Zf6NGÌQä8@ª‘sIÊۤ܎jì’Ú#%;qŒÂnwjÙ˜Q±¡3¿Áaªê©i·Š(Vj¡Š(bõëVðÖ\ÓâM´0kD>§¶U‰„zpNzb#.ý:ë8á“âJï}ŸC•ñ•Ov(ÀäOË ¦Ãÿ¡˜6ˆ8H^&ì×¥±Ó³?òtÇy™ë°#%#ûý¶¼·6é³]Vâ¡3‰ée›Á×GY`IÁ´Ú·%®Š ¼ï| HsϺš˜ÛE“H:u™Å) ²,Fj0ËsVºY#W6é­щ(4ÐÅ"´4Yˆ„aŒdtªÙ#6‚#}´‹Ü¶`Ø5ŒMõøf¤ëÀºfmj Î(#.árµ¯ VŸ¢¿í;'\ãS—´)=ǸöòÒ#%'Ü€”#%›½ƒzÜ\‹n@|ʼîmÛ¿6ôÙ ²êö¶¾7Ç¿ eÊçó)vaÒ¡ÃHF‚Á‰ XÏÛwêÖ?!¿òÑŸŸ©›Ââýj—Ìžx‹OuƒÖwð4r }ðÛãæáŸ7>ñ§Æ(8Ñ_Ì]`#÷˜úv#%ƒHÑ=©“UŠ°Q0…þrm¾H%x‘; Öõ‹™ý¹….?½VI|gxûœˆq¨[$›î}PT=]‘#6 Lk+ƒì ™•Ïãý¯²K»d9r_ Ÿ¹bD³åAˆÍÝðü(òìù· #6#føåðÝÿ¯c»ì²BŒÜÖÝÕÏtê~jðêêçßlúü3~i»Ónˆn>ûy¾{çñ~ùë]—‹ Þn¨`"1€Ø{ô°õ¯ƒ©Y.HGs$‘å<šÆë½\GŸ<ŸDºáëߧ=~ÏÕþÓCrqy!áã^H³U$ÅÕ2Änà cèúÔb3AÙîù½ùa.ÁGc@õ¼#6\Q\RÒ9¼ôUäÎ)u”Û¯ëqV RVÜ°¶·úûJ#%Gh¡ïÿÒ#%f—÷,ÛQ¾ß·èøvKx#% œè¡”#6€”»—wE·B¸cÖáÄîâ§Ï—¹øj<}Åz¤4:CíÖï÷7¥d€B‹b3Ôíh"™µ%“D˜€Í•,J/Îã14i±Wö ÑÛv¢e»véRŒIKûR…IXñ¥·õ‹jý_È^Ö„ÒVÅ&.Ìýü²Ü2SQui¶ø]ˆ!C†û^~7²^4snë«u*䔩󫺱5øuåw?çÔÕû%`¢åÑ©ÉãüjRD>=>ÿòu>œi>ÊÊ:##69dc|›ŒVþé­nmü/®ž~çú•´J:3#Þ'$!éþÝPY]oR®ˆm½$­òZ¯&Ö¯SQUQF@ö#Ûá aøè}ΑÙCui±œb)f¢y&¨ƒŠ•D éƒ*þn&NSìÓ°%ö$¨áTò¹^%\…™ýÖwbIlI{VTe—ùä§îjÅ‹çƒÞ•¥Ô:±…Ø1†’µ&óWR÷ñþÑùùÜ>2…ÿ#.#ú6q4¿~¿•ù·X30~>êí{P?œëF(¢,Ö>_#6à3~ž‘­Úˆ#6 ïž0\îr›fžÁ«#6C õÃü j1T,jƒ¥q¾#6Û6Od'@h'Á¤¢$„K“ð²åª¯1¶ œ ½šô† ±ùË=rÿˆ2·æðWÕPÅŒùw©1P°æ(óÚ‰ùPŸ™´†îΔVåRh!0ÁV“ñJ@-I[ú¤\T(–#6N=>$oŠ¿ƒïŸ-#ëüþoÌ}÷~?©¿SÄ>áŸçú}+ãä™SÖyà-[O¯?8Ñ[úF©î»ÏDÐÏcÒÿ½tz/Œƒº~˜ùÓïá7|çé6`¶œ¹‚ð‡ÍVúö«Ãñ˹G8©ç°híýqpä"#.ó$`{z—EÂêVsãbÆG˜¹ÄL¯“<„OeпõIGá=}}›’ô,k±Þá<öv}²#.¹—iÒå•ýº{ã¶+¦p±ß³0éý¹@ÒÍîÎÃ{¶uÁ#uwDa n'ª@ÆpTÏÝc#æP”OR˜1ß@y÷^¥ïPÊí8jßeÖÑnvµåô¸aËA¸cüU&dã#6V]#ÛêG²S "‡ Í÷ÙKÎw-ÃÑ4¾Pdé9ïÏåp.Q¯„Ÿ~9r—a#.xR^ö s›eH»q(â>ƒýºë9ÕÜ{Ϭý°±øï½áäÞQEV§ì±p2”/Xu|¶]æ¢c=!U%äi?Cù… CØcX¦ËìÆýýøPRv²Ä…¥24q`Þam;“ÿƒ ŸÕÛ¾×Î_\P Wë¾ëÝ2ÒÓÄ«>îþ ë¤îº~š¤>¶–=TM@òjj*©¢³ÒB''%=-–uûûHkû8ܪpÿXŽËؼ‡¡&>]°CÒp}!é8‘BvþZ>Ö-øÛ꘶*äĄǸ„$M®pƒ9@øI‡Hg­2q#.SýuFfŸÑýÿ›3ñyXx{Pî-ô2Ñ°oõIöO¶ž–$˜¬'Ñ¿ÆŠâ4ÊјŠÂCcíÔÓ×å óí5±y¿oœü|zÚ1QÈøÎóK,,$o_»Cd œÌˆbWά¯Ÿ–¥éŠÕ áZ¿V3XÀŸÓÐôüŠ¹CŠE.}•<åÔtÖšžv¹W‹:ìN#K»aÝÙ<ïíáËXÿZ0þ:4°4n'ô)¿©cç£*(ÑZ1F © ûÍIpŒ[Å ]E}¹ýæ™æzï ‘½Ô‰ˆÈ‡@x#Muaͧøô÷{»þyú¾ošÓé6låÕTÏG7°èôÓ6”Õò}Y]ûü¤~zú›)ùí`¯]š$Æ‚–×=ù\¹µYÖïS"Ëàîý­ßê#õoÛ}¶?=º;~Îícvφ\·X!kÊôCÍ~8ED´Õí«ù¿]mRáã>^Õçá&÷_#68êpbo×—›;ëvدµZSqŽ§iûöÇ÷oöjíôgËÈm‡ysrËG÷t{œvǃƒh²à¢á`×æÒúôÏG7…m óSžÜpa»£:H~ êþRöÄj9\RAï·î~^ÌîéçÇ]%=†"Ëù™é»‡íxâ¦É hæ^†LG’ëe#.·s-”ëÝÑ3Ú÷ÙÌêÏæ|Û%”n³¬|ðjãWuzµ}F×péÌœ°çþS¶1†š¶¯‘ãLSèyµìÑ­}˜í{ù`-¼-§z9Ðó%[¶5¡v»º½2Î;§'D‹?/Ã?À؃}öÛfª]wT¸(9=E)#.]ÙYY‰xôpaòÆÁ¿E3Æ£Ü0¹ÏѼF%Ì.lAÀ>2.sºUÍ?¯Öç½FŽ6e2w?.ì·Å¿–=ÛüÇn¢n–;å"^¯Nù]¦ëûi=Ü[ºó´y8bºwc|{a²rÜÞÁÐ#šŸgŽwùv[…qýª$R¿S›ú>]ÚwæÿÔtf¶³×ÖžOåð{£<î¾ßÇKjØtcú ®ê]·yïìDZ¡¯Ú’ÿ°Ëà” F«àËÕ¤pøzŽì¡Aó:Ð}Ù"¼p+ˆQÕ‡“ß_«ÐÃ^‰/±m&­îù<‡7;›(|]o”ÎÇO%~Wû™ß2lSœ–7µ|r¯ýæ†ï»,èá†vENJÞá^[#=6{}ŸÂ¶uýŽm™`žóùÌ~ÃýîÑÛŸ]nåÌ)ÖÿîËÕè¯m¶ÿ£Ïª£ò©#6ù¿GFqŸÂ^FÌÒìò7ðü4µ?w·ö¡(?1œ½è„ŒŒ®ßçõ`¶úO·¯¯Ûï)ÍÓ["†ï ÆŽH#%õ"ÕËÆÐ2Æ P~kZ#%RE¦)#%éŒ:³»“ÿ£O2ƒŸìô„ý½£•<Ý~¯Ïî·•üsŸ?·åõuåÚ%÷‹›WwPì»4ô¿IÛø×~÷%IôiÓtêüÚoæòšº³¢qüµiAŸ£ªÇçÃ@ïîøgÕÓùj¸aõv{À>ÑÀu.Þ?üB…Í´t¶¿®gºç*¯õhÛDAþ óSö䓈yGÇbeÎ>Í_ÝøþÌ)Ón¢¹8h¾>#.[¿g®øÔjý ¿º;¾œœ0v½=†áÑ›Éñ¯Ÿìá¡>1û4Šðx÷ gP#÷h÷óñÙÀpý_Yõ¥©Ü;ü|PåVˆQó•ñ=€ê?~‡u±ßåmAì#6`¿Ç™«–+¿÷¶ÔºÇ%ð#.ý‰Ã“ ¬óS³÷wt÷/vÎná#Ͷ?!b¿ƒpv ùlîâ¹ù;òžêÌ™/Ð|S¶ž9¢ ãþ?» "(H;G¾÷*Œt<&/»éÖ†ûçë’GK÷Dj`’à–õç9K#%#61ÜT'&D¯žñª¤½Œ[-2è+˜`†IBfH&ùÚ’~;†A΋wù´Åð8,†È¿{#Y^‰ýÙátÁôM ÏŽý®7Ü}·»,°§EÜÜpà…#.±J‘ÔÁ€ÐúìŽR#ÕÃîá4¶LÜhâ+µw».©™À’Xê%äqh– !ô¦ÏÇ~žIèù}A7Œ®«wèüº!À²h;ÐÁà· -˜>ðÐB)Ø ¼³»¥JÒˆ®Ç“>;ÚëZÁZ;ž|%9µdC–PSx½óƒsZËËgDås£wr×+)°±¶1/1B+SéÏkÍÞ·_!†(£«F€+~›4sgì¶W×M«°ìÆç/Ïö´©ݎ߶£Ní3¡hžl‰“3û‹Ý-ÌØm=O‹£Ûóp>Ø#&þQ¬½0â/Sß3 þ>mM©‡ñw“÷ì\•ý\} ÿ“—$Ùwü÷y¡ÔR‰$ìØú|¡ô_ÓIØÈDí'¶1ulu³LׄãÏú[=8á'x¿ƒôúè3ú†A¼#%Éé/SØC¡I%yb1ÖFÉ¥Góü™*”å˜bG‹ÑºüCª öIO4|žÿHï½c ÀøòŽ»ÚcY|uŠ·‹>Sþÿ—æ#`ó²{ÑÊÌáþBÔfeÌ©cv²Á¨9G…?G¥F5¨4iTlTŽ Ô¢¥nØ€Ðæ7#6ªÒƒÀ¢¢,tþÍÚ›HÁ¶¸}=3†´Ö¤On `˜a´ŽÅ-ŽÀ¦°Aȱ¬a¦ILA«"hhn„)"–4±[VWŒc€ì'Ë#.Ss¬6ÐÚ]&6)":ýº[ÅÖ¡É \’6ö‹B{qZ8dÚu‰ýÿ¶ø[Ñã"?›9ÌgBPP}‡¨üÖÊS<¦³ =a‹5þrÐÍAÉ]E··cˆXw\Š1´™ac0]WëøoýOSø\ýVæœ#¯#±E4DCÄHèé@ŒÖbï¡i7¨1lXT¥Q&FÈCV ±6Æ›f’J¤ƒÿj*P´Y¶Oà9þ¬éšq·ß›åñãrÌӛܙïëûpì—A¾öFþÞŒi|œ-'Ôl³D±€œçj·UuwåËu¾_…ãŸÉfºòöWV¯Ùãõlò:­ŸŸëôeñÖ1ýèæÕ»ê(¦áLS·ñþ>ܬù±ý9Hþÿ<ƒ·ˆjÄU±Ýmù}Z bçvù–U²«&¸ê²·ü³×†íú¡[GmC……fŸj#6#Ò$pçwÔ]uGÜ<Ý~ßÓø¯Ó§Ù£O«¸¢Z„xûþ#%8g#65U6ü;ܶ>®aL~ØY¿w?VPèÁwÙu~Uwö¹\ç3Ü®“šÀÂÐÃÉÑkøÿ.¬&5)n—|?±½¿>¯&¿án®nàM>äM¹¬ý“ûôwL[% û"ûBßæ<ëά#6)_@è¸à\S¼|8¿ÁéÎØÄÑ›^F+rEµh‘[J%c§l”õX*5¢gtõu¼^´yçœÛÆ9ÍfRÉ¢((Œ©[\0°Ä£#6’ œÙiéÈ¢ Ôch¥b…€È£°µÂÂ44W VR²ÙÿÒ£FÁ÷R­\æŒmFAKT­Q eBÑlB†#.°Q’ ƒtêMæîy3‘wä%r(*`¥2ƒshÙÀXœ;Ýg6®¶JhÇTChÆ%™ 8Ì+:ª-!ñiÜtu,¥µÌà’‡#.óÅ!ÚÐ@AFšþ§YÙ¬†žuD³Žmé¾#.äQ¡±‰‹$I•8‰ì ~UÒI‘#ü,D¢Ö–%\ȪrF‚(3š*ˆÂ®ÔÊŒp#®²R1Œlž°b¹ÓòJ®x3¸ø!U†$‚’IsJCÙõC‹ID&é½’ôAŒô;/ôôÆNô˜}€Ë ´íäë-ûLH ¬^Þ@ u3ÇD>Õ÷z“´ö#.QùUôhÉz°÷ý”OT=¾÷góxáˆ$g±S—óPü-ΊÃáÉj»#6ý£×£ŸLPL*ø–ý§f¶£Ô§ü!½ëÉ3§F9–û§ùj~¸îîh¨xÊìƒÍcÔºåøËãïÏ›""'NõOU87«6« üVûú„ÖY´¹ÄÞÏÇñ}NO#ûjÒõ@Tõ¹€â9Øs ‘•ûÊvA#%_œï†${Ó«”ÔŽVì6TÖÙõ¯’=óø~ç–{àäm·l’_/ÊÙµÇÒBÐ’Ä–'Ÿp€âqCó9Ë‹è‡æ÷¯!üyI£×<³ì©«.V|¾ŸÇÕ!‰æª£#6u¬êyÄC¸î'·>Åþ¹õüܯ±­öÝAe;6LèǨ4«9ÎCH¡QH2t2˜wT9"+1r_uLUv¹ä“h—ì¯F¬ÿÂÅê‘€wf\„F±>ž™[î÷QâZ%T»…#6ÏÕ¬ªŠÿM[hÅe”£$#ˆÜ‚±#.D¿ºÅlÅ˦ómòØÊŠŠB‚YQYCFF¶Ï7®_ËäÇÝã³áê_{HUuí;wùüÿ§OÉ“A󭬺!BAT‹‚1ž­sa虑sÊ,¿] WÚh&6p¦41-6—·n›ÑHÚ)¬1=j ±o\ËA„y©Y¦=Zﶊ°Ì#6Ô«ÉgAèpE30ËBƒH¨Á‰”V¢À*ø¹¢hâÒñ/mˆŒM}RdCÝ7ˆÌy#6Ú´s¶jdßå$ – 8ÛAmb{€„&‚ãì͆¬o*ž ©H¥›·86AUƒ„Œ‹³àrYb‘ÍZ¨¬ÛÕ§hCZ­¸ÆÛ…‘2SS­DÍ#.H#6J lXdL1aˆ4KDã#.­‹G‚í3³u#.Ðá1¶“­¡×l°lôÝX Ê-“m(Uz§ûÿñhÉäŽø1†µ—š(UX¬0âØ”©DƒlópÈ#.Ìi@¢OlƒÂÕ·åtS¼'Þ30\G¯øøJ½µ`CT<ʤ2+r‚i÷MŸ„š -+A‘¸·Tc£´øìz^Ƕò—ÅG=Úæ4Rë«Ùî65ÚaŽtHÇ‹µ0 óF‡ÞG[q·º¨ÊN𮋳 þü¥Å Ÿ™ˆ¶<ª¢‘¨6Óˆ®Ç!#6^¹"XÞ<(²ÀÐœk]o3ÆÌÀãH›5KœK¸´pLÊ,°¡+&°,”Êp#.#Za¿*V>#%ÐÎýhÂ8p™˜Í†K§9æe¼‹õ².l‘m¬8ÁV6>d4#±C§›à­¶——ÔAܺÉ&Fèé ᦠ¦€¬ÒKbíV4˜Î Ø=ÕÝ ¸Døn$DN÷»A£PÓŒ+gb†XÌ‘Œ®çFPá2-îc¶+Pƒ¥ò)2ÉÂ2™+ç*³v»ö—w?Ãzwò_Ûü9ô[ß™£oƒ×ûiþnþAý— èyÔÆÓýb'j¼ç3Xtß1ám¦,¼3êtäzÉù~îìa#.6uqöMÛ‰ó¦q9°gì,ªÄÊ;÷ ÁÍS¹(v-ª ­ù`kb—ô»­6ßV۾ϱ£)‹`åÈf=NÜRäòAUHtF¨ÚE’ëž1’œÕOSxWxe¶ãjh¨ˆô©Siyiºf6äÜ‘R®©n1v6«D˜E¼ Œqì’T'wÜÏ€.›gÊh#i™£^ÞM¼h½óé¶3`ìQ±q’&Úri3haÔ”9†ÙÆbX±AO}`PwÍUí«3Û¡~ÕoÒ_ÇúFÅš°¤<N=¦,Ü9}Ð'pø”F_smŒÕA—#6#.¬:M³±¸Œ-µÉ°àzÌ! 1IË(Dâ8ìMpî@Τ2ìl+ñ"V½†Üq·ž*t;$î§iœŽ¨Åo›;n3†Ù†-ÏŒu#.põQ…boyN×?u°ƒL…#.¹}#.IŽƒM¤$Á„ x¶ï‹)—Ï®v¼îÑŽ±­nú¼…Ë@:kï¯#.K¨iccndë‹ÔªÞAåj«[É•P]ÃK©)pU7ŽUØ"wW;´Ç ƒˆÁ’ß’ÛÄ!ÜÔr7 •JQoùŲmÛZé\¨ÂIA­Æ†àˆQÞ#6:26#.Š]î;ñ´ïC®â¶£¨ë³º ¬›ÌK%c¸Tnq°QÍ峺mñÙºâã!X ÷Ðk¶Ö·ÚåÇF=ˤV¬v„NŒSuÕÑÆs'&vl©”4µrÍb< vj—N›19ÆbÉÃ"°Ë0NrcZ6ŒßW$œãdŠB\ÜÖŠëwl #6Ó¨cÇ.Ûldå¤É6µ&†Dm<ÍŽc/³Ür±±5ß ÕoÓ:Ù›D$âoµ}ä«‚ÅÇy溽<¸üþY·íhÕŠ@óμžKaNâÒW•GiÝ/_³ym§,­qGr0÷GÂÜœFŒDdªõç›V׆¾†’¿òÜdIÄäF6$ˆ«,Ÿ©…5·\m4üŠb-ßöÐTM^í¶"R§".f哽ÿ¾ºáwu…œ¹RM|an‰¸ê!Ô¥•“ÄAl©·KÆ’ï ø2Ý䀹ÐiߥþCÒKíWnר>áüpbx_9³å¬×WÎŽ@žTÛBðÑŠZ·¼Bì–”b>ß_§çcOVz|ymx#6fǼYJ˜…²-™Ê  0#6@ŸŠwßwvOóÓ®ËÒëÎ!‘Þöƒ‚xnpŒF€°Q¨#%Š²ÝjŠ«ÀÎÇ·e#1T˜´ËRV¡Ö1(3‡È40° cpç¯T‡ô沪ÎA›œÏ¨9zâ"3áÅ‚NÇíí<·¹“ycÐœr—v>óZªQà:¹ý탂%ÖД~ND|²EÊÉ´à÷Ô%¸< &ÙÚq4öÁ …)UyøèÌùÿ_ó–Æu«޼?ßàzg nõ¼;qËô;剚ރ†Ò„&LÅSå1ºúeÃyg²)IVì–\—.B„m0J°þ’[qƒkdÅ°ó#´-©`®Rb]­8ð3ŠÏcÝÇÊûO¥Ÿ]ÝB“$ÄKÁÇ|\ÀÈ›|jÌÅg}'ò$j­•a±áêȵ¿<4Æ=6=&¹|§‹ð»®6…]ºÔOvé¸pX»Ü=ôTŸÖV*yumžì…+¾â1e¼#µöÚgDtž,DãFQiwqlÞŸäÀþµ#.س^O¢ƒàô.­é¤îÝϪ’‡-ÇIÐ÷]ÔAõõ…îÆQ72„I8€ïxL’joLk.ËŽˆ¢MDz=ýtï&½ó:oŸ$48;!Cªpóa}j‹ bÝ›94gÖ|«¯3­ß½›µ4#.ÒOè%èÛÔØ¡ñ­–ÓÞ:Î<4ÅôE#.54òì3R‘¬úTW-Çðk¥³øyçÈcUéN-<#.'çik“é;!:-DŒ¤§ 7)%#.M;î·$®ƒÂ÷h.Ø–CpíJi“˜5Ðéï¬Zñ™9þ®ß#%ÿ‡7±CðÉêpC ‚Ï#ò‰Á´ð ü¹“ßrÞÓ¬Grɧ嶖“9¶šE„“J¥™Í•aÕ…ë¶ú`xf¤-0è´%ùk‚ö2#Ž¼üx#.|^š:+Њ „ÒÉù­ÌÛS9lVŠo•azâ3!m ²<…¦y©CÞo{vþ|eŽûüÿdQ茌¶F÷T½Ä½Ïá~;¬wÚjl .r<0XîÍ1`àžœ1ß¹iê1æйºKj„¶Ó§\ž¾¯‡å;åd“ý|†:ó»OeÑ¡ÌìÉâcs§ãò²Íc↛Zøô<«LÁ“QÖE-¿”Æa H •àòµ0·Nõ3\JܘrSs t UýÒ>\}[ˆìäåúžŽÞc‡ríàXZ.ê,¥¯Ô#Îfi?ú'î¤è—DÁµÊŠ©æÔ÷½`£Ñ@ˆ¨úã´#6ˆoÍÇ~ÏhÊ0*Ü×ã:Ö hïÿKC¼i´Î|½_ðÍÓÃ_.¼71¼§½Âu"˜¹r—Fxô⠘Šç#LþÒ¹Æky™—óé“>Q†9¬€Àȳ÷›#%hÍÊÈ(²…Ÿ¨ˆž+fLmìßãh”}ƒãÄuÚŽŽBN[ëR fJé{ 2ñªA·Pjפ/ñté‚£YÚÚ$ùyPñŽÖ–øêú뢕‹@…)Õ§)O”~U$BO3âud¾‰Û1/5¿<’k«æ‡U«xd›í¬½ìu¶ø¦ta>y6œ­¡™û5œÍNîQáp­NHèºeò¸è>–·D.•÷*EdÌn2,Y—(迃f—ñ/¥sµÒ› ñ˜D‰µÒ‹Óô’ÌØ—›Ð¦wN—¯®ÖIóíîç#.¤PBbÛV¦u]í‡Un=Eœlã‹·ï¿>JªE·":Ç”Ì[~ÊÚ‹Ä&ÂOš¨ÁÄ­)ƒ%&UrfIJNgq¾aCF¦p—zP‡™†vß·SC…:l#ƒ:=ɪ/¢6<ç0DU­¼F9‘Š¦îÅR3–}m¡ð6‚£y)¤8Õáà7Õ¿QúÜñeìî#$†ã\¦Æ§ò^q1®J=f3£ÕÍkÆÝ$·LùÎã{ˆ–¦Ö=Jì‹mŸ&@׆vµÑ|^m÷"Xî<ºãcèšQÕ¨ŠR„­HyrÕòá#6̪\hlæÏ„„#6Qɺ*h9·¹Œ52g(eG=¦!ƒB-½FäÈ= *\¨½[=Ù4³Ê…ܧIm¯ƒÐŠã¹Fo%ë*œ¡açgþsé7s”¾›ð¤ß>­üç:¶è$qCñntl ûÜÂŒ=³D”OåùÅ@à}Äýó;Â_+'ç» EFžÍÇD_½@Ê´Î/HÌ(¹%“üñãÖÛ~!ÞʨÁõsÉMžªG4E8ŸˆyKåÒØÚ„¾ôc6Ãä´ÜàÎû6vâv¥l½Ë#.‡g“t>";¢ïm¼Ùu¼,ÉvõutÁ=;2hä!0ßH¿(âÞ}´s^G ap%N=¬c¥çµQ»Iz]¸lð«°S·#6eŽh´³$'°´¬çíHf#6^Uî…Ѓt.‡.k„“¤ö#.п4âî6 zÛXÛPÅ¥½“\9šÛ1mðR´t­}yUQ¯}[;î¨Æûáožs„˜-÷À•<¤¦TvZ§•H¤sÄ•éïã寻Ë&?Áß™Æf}ôèÁ>WÞ³ÅøÕO‡Ùwbe'½øëåÆqžçŒtÕÑ_I&5q¶–"æ¹Öçgõj2àE°™©£•½"*[WÕn¬2¾ëAá¦ÐM*’aFkmö0*áe"ë²°I@.µq|ž%hy±gt>›ûõGÌ0ÍxQ“¨ZQ]~¹„…LfÏ9ÖÑhjÀ’®“'»YžtX?PØçÜôTðQäj?¬½Èo]YQµfÐ[DÔ³áGçtP?ÒóèþØÎeϤ;ûmð÷\ã4•§á˜‘x§5¨íÍKèÒ@¥ÛY ü– —°¡•³([¥uã`£„"ñ%K ¢%b5j!®#TRé,Ы©’ªö`A¬5w,åu1ž…¶K#6¯uÌÍ+;¼òzÜÇEºâko¡.¦ùÕÏVÍ߇Ç>ëä(úXòV÷9Cg–­Œ ôuª<²w]ÇÞ7ÆðÛþë+™Þ#6–~J¢ÖÞož8Ð#!žõþ³PJ†#%)W&8Ø9¢/ï•®Îo7v°Ðv¸- õ 6âm¾Žæ¤C+«WA’z)zÄêéVµ{„Ñuå|NÉK›¦Ò ¥tßËòܹÆ"‘½E¦/séÑWa›Æº\T:Ü©ÝÆðñ#%̹ÖovJ±$o¨e›@„¦ëtLE#.õ Há­Ð­’æxizÎ @pžßyƒŠ¦M>úgŒV0P´¡ã/ïÚWFŒê ªÆê°ÊgR0y¹ö\÷› Ü+nS×GJÊÕ–^I¸ºY©}ªëÜ轄BÎYC™;-|ŽCÄDfVšsÖ#%Û5·\a?Æ ÖÖv•s>×_Òë5Fó¨÷ypfÝuÓÊ#-/Í\¿Tz>#»¸dq ÄËÍKÎ{e¿"ϽFòæŒÁ³Áµ@œ}#6#6pÂi†1šIc¯1Ž¡òª¯ ÇÃ|èŽIm'T\&IËlgï™´µp/jº~?†5óÎvÝ ææܲÓ5‘bŒ7fÓnº™N3[al@}sÙ…_ XƒFÉÆÛ„ß'mÂ6)k4ïÞ',Ö #6Ö•KdÒUÅCÞî… £¬ô#6F6¡H‰Dp¢JÊ÷ÖÚWS€“ä²R²sýÙí~ ¥axÆ«aázß5Ä7¾m.mí*E¨$ CAlæ¦BIm*øÒ¡ò˳5®Ø45ÖJ·jºï9}æžÖÏxôHü5Z¸QŒ·W«¯ê‚ñ‘B¢(PŽ%¶ÃD7K#..mØÎLjئ+Ô,#e3m{­wlˆ4º/}úî}¼ÎYðsEÞC9H2ƒ¶±ƒtflkA²´ÕM1‹C,áî…`âl„™Ø±„ëkù´OIiN•}¥áù#6nÆ#%ààÍA^†³(ÆÀl˜!Ê.±o7Bù[8fX»HíÚ€Wzò2ÔÕså@ç¬É“¯ËjÎc¯oN=,qkóPxÙ¡ÀË·qÊX8~ =Þ¡O½íÏ’‹Ó¯tÌqÁ8=þø´¼Âžûx–’ÔE†@é#%Åmp‰•‘ÀO˜NÐ’³Ïaj¬ ôe“³ÊÈT†I*ƒxzÊÔ¢ˆŽ4äãlûGüGþÞtОq͇¯5K¯ìëâì·VžÉxdÔÊ*Wž6—XËSm³¾‘$ðH/᦯°FŽì¤øS‰Ùà‚Q²{Æh‰e!wº(¦±Ïš]ºÈ—c!‡ïƒÂëOZÏ_…ÍÓy©1L6ðéšP¾·«>ºÃezÑa¦ö_j¸ï©~Z^¢iJ­áÝtQaè[›9ò-QÍïäzí$o“‰±ýL— ÷æsaÕHR1€ÒTÕ ×¡Áâè*aæu®|b¶ž‡µïææyÌ„…Ä“{Sê-p5cÞ§wsÕ_L›ÜÂG‚›ËÖôöû©åŽ¿¦àc}±Œ —«ûû5I³©jJ#fع¾”ÎM$rÂKLîg¡sß9a--JÉ–,°ã¾›õ½`¤Ç|ír]xä+n/ÑÖÕœELm¹‡˜‰‰›Èb3ÍO]a­Ó(£ì!^\C᛽¦Õ-(r"„ÇFgRÒ¸nXم꣥ü1½„+/!“ÆšÃ6d#6P ÕdØIá‚ÇT”ÁHS{ÚÔbÿ3Ÿ1棆…N¬ù \¤ë€`- xŠf<Ž3·¡Ù#6  g î®Þ|Ûc$âSâ¹@ág"Ä ÀÝ:9Òà»Ý.mÚ†—¾|×[6âjžg5sÍ¢ðºàÙ½KÚ=WæˆÐ#%U)Aµý³MU7/”Îà³E³V¶û³õb>|ÔÔsDD°#6T2À¦y Áq¢Ð²#6èü¥ŸÒk1~6ñ,ŸÑå%Øâèûgû—K°¶ˆ"hÔi2KúŸ;e#6é f¼¬T¡ ÅX]Ó¦h”vÍÖ°NZPqîWP¦õáÐä²I¼|Æ ág¬í÷ži ã¢\ÒªÊaîa·Øé8ºibP» ”Jr¬ÑÑkLØ0óöÖë¢vÝ\ê£q!ö•ytŸØ :÷Ôܵo‚û<£gŒÏ=Éo6¼IÞbì·låHÜCZýn±ù¯Ö7Fn²“žd»Ê¿_¦Ö„VM‚ü£cîƒ:v¹+F;³Ü¬)&#.M—'ÁÂ#.›Ë‚¯£¶Œb»ÀYÊw:$ƒ†±å½À=ë Z×û°' &hhmZžñX\Ë,€ÊŠÙ9CÆçò¤!9¹­0rÊÜ =ÞµmŒ©3¾¶[…ƒ¿ è‰ZÁW©TƒŒ·ÈÞÝ+(a 19Å‚‘Ìáë<¥Ñéæ¡ÜvÅF³Ôè©xñ‚è~ÅGÁB UU(;}ný½º¯œà•Þ¹™Áµzoô]4Œ‰B:ž­Ð=.®atÏ$³ôÒeJûœä™í` r=q`ÉiC J¿ç¼ø”D¡ùâÓÁ#.BY`œ‘åfYB¢òó¿Ay ±U /v¶ /—C—3¯¿±òÔ$¬sék:!ßr=®.ê«Y8=}«œ[SdІ*„¼¡÷M¹õ(œö´¯RÔ˜xÁ5&œ¾GÔ†¢¨)´èÉÄp¼Ió{ ã™.xGtÆ¡žÿ',©iAxdÙt½×ôY»7ÓFšsÅÓÐs=o¼[DØЂ unÄ2¨æƒû‹`Ü1˜ÛNAö;ñoó$³¶‹›¸x‹<¡³EüqÊíêK‘­/–¬ÙßbÐK¬„/aÑt÷h$&c„%n×çl#«'¬s¹â™(é­T¿·iاۤªËò¡^v*ø1Ö.)òFÅ?NŠá_§X#6ãûbo1QìÐb¼DzÞÒ¸Û¾nB¬htRߌM~Þ¹Ÿ¼çhæ>(â= 6º†6Mº1@ì|]½fÏ.×ösÛž(õ::l¬züø³jîOÁk)¾pVzקk÷û±jÔ3pV×>IÎf¥$™Jý€?LV2e*¤Xpå¹³‹nžÈ(#2òY¸zk0Ö9êŸ<õ-w¨õ°u¡Íˆ¶lÂnIv(˜"`‘îTaŠÙߦ:b×däB®zí†GmÚå»#6õÈyh3å„Œ³#.¡™Œæó‡vÏ=ýB´Ùîïj¸+8;å>N¼Ù8›dÃøݺÌu]:D£~·/Ò®*©z½pIs>•Ó¾Ä¶7¢ð¾ìæ|¡Ð.ÝC×o“ü<©Oz¬Û5*ôÚÐŒ}&E§xãÑŠ»ó!½SbGeœžFI-ÉU#%¦$Ô³I Ù™lM,–01Œ*Fe`÷ S~S G>»2@×ã¾~ï3¬ ZÂË/ÒsÛ¤¸zµkÓÆ.xï|~ñÍ‘•D¤#%¼Û鮈u™¯ÍÐ*±§Z#.ßËn¾‹€P>¡…uxi¬ëÍÔ¨&„'a¼ S9—2)igkHÏíð|·¯`çÛÜ¡à‚iÖÉÛS{Æ`'Œ+æU<:êI,öæÙ7¿_ǃVñ5î‡O/Iú~!®ìàœZ§ºÜÁáÈR¸÷pùqyàì^Km›ž$?«ÿr¢­‡u“à;46CR;,VÒ¤èøu'Ž/•0Î?­í5¯{íÀ™iÎÚÞÜsü"Vîu¾ jOð3ˆýKÉOäýN“w™³ª¯ÂÛ¦/½6¨ .¡#6×X”rpÑoHì~!ÑRKz¹£%dn(è)!ëßžnÈ€r†lšÔˆ£§‹G’ÜŸ#D’ÎŽ¸N5›çþwP$È~žåtÔŸNBeåkµîM„ ‚ÏÙèn æ²1Â7_êÝóÞ¹¾?5õü;{Óº'àãÕøÏŒ¥¡{ùq(#%`@)ïõ(õ§áôáÔŠç°Ö9MvŽ#Õ(JL+G;I@À€ðèz¼xÔ¾(H)­æ„gëxTWÆ®òØ] —÷ào»ýEkù©\ë¹lIi?K¶Wò¨Ø”‹Rm“cÚ-«®¯ñþ5ù³Lˆ–ˆ…>­(2Í›ÊþbFmp–ß‹gË~:×ô@ß4>$Ë_#p¼$’ ŠÅ"‘AƒY ä&©×‡™z½:œžÛ¬-&OŸÈÌySµgÎ]–ÜžlÈþÔÃfÁõ¤™^¥«Û¾÷Ê“Ao¼?“ñxüGŠ5‘ý7B÷ØH‡Ó\™ü¯íN9†1‚¤IY‘[Gtþ#%²©‚¨qHTi*7+¡þÜõÿ—‰Ëò?¯YC‹‰xþöaÏ(¾zÿ~[Ûá_Ú Ï]>Nt©"rNK(ö·ËçzÔöKíˆd¿»æïžðù´!Ú‡Eá¹tî›V}ëªÚÃÞíèÝnCiü˜]÷ùY??ÎýŽ…ªz¯nÇN¶:*F`6$´t%5®Ææ󳃊\ª#%±|´ãÓ¹ƒþ1“ì?£¾í/ÒÊY¡°ê8KË,H|ñ“‰"~¯Ð©¡ýj!Š#.K©wk|Y ž™²äèYû=v&‚Sú7åí}f“›¥h¯P#6ªÌ·Š Ϩ:ý_Býš>¼•s<­7E‰a§VNKÎõú]›(ú¶ÅÆQØ/ð~¶w+E@âõL›0½Æ\üƒª"XÉBÌÜ!œ?_þG7‹L˜zß„çmßÂÇ>¯+e§m¿—Á÷¡Øf c(QÆŠ#6‹"šýu9¡Ñ#.P?KóO¹ êL¥09]#%n‡?Ÿøí®@¡/T¨#%ž½t xÎè†"RµœKš Tg¹‘L°ÇJæhZ‡\j ¨µ+r¼ Lt#Èæ"#%oŽŠ®¡òËÒ(~†—ª#%¾± ´é§ëãcßÁmÃfÿU#%èõ@ÝEôÿR ðºØŒÄŸxi¯Ðþ•ëôBañŠ¾`Ù8ú&ØH¨Ù6óòP¿Ÿˆ€XøcÚi®à†í´ ÇK™÷$qý4¹a‹ß-)Á>ÏN99¨“Õ‰5v8ñ:je`a"ÅeOXï2€ƒ~ƒZhCq‹ yžÏWiƺ(T¾¦Û¿ol|ïøH,ézþë–(`L$¼{ †9gÕWR|1€¿{ÕŸ¹Ýø™@Äyi<×Þ€ÿ$ï è LJòS(ò‚ýäOgÏIëŽÕ¥OSIïô–õ#Ñzüco*(B¢Êvæý?Ít,¡xë©TÏ[]3«X(~Š¤ž©R”#6¥`UMKõ·;ã6Á¢(ܣ؊y·½?=Æ Ýа섀>Š©˜ aI\öñ}V$øÁ4º­2qÇ m¿Êe#.fqpÚi”ÌkZÔ·ü(b§RfÌ%ݵEÔR1#µ¤Ûp2„‚\4SywE9gŸ+ìôŸÐmÒü!Œô¯#À耠(&ë]Ì#%¹Öië…uQºâý:vêÙ®¨ÙJË5Iší4ôýn½2‘×m’pŒ­è«¡ön³DAñ|],ʈ‰[#6Øy`ïÄ#6€ŒPIµoßÕwÊîŽ,ßlN¹¬ç·Ü"‡c;þú†Y³:=Ÿ±Z&W¨å#6‚Çf½Y¦ÈÈ`¢ÃÏÅ3×8ÈŠ7K±´-•T"EÃvÉFQ`¹Š\ÏP.Dp1C¯f¶Öoe¹_}g¶âúà«âc'‰ŸKš³’T¢©Ö¨`¢XD$¡›\æ#6P8ÌüøÀ·Ì£€¾ý—tb•ÓÎOIan0aÓÖ€LŠ bBç#.°‚ ¶ö]\ñ²òBET dØÇ(°so¾)g®Ñ à#.4FÌ·e¦`1ÜL`òyJœIÅG§³Â¥ô ï#?øYÖzKéÄ2 ÷#.ÍÔþ:·Ü7ÃßüÕaÖNQżÿi˃2}}Jo£Èú¯.þ³ÊÍýÇÐïL_fs@ˆvô#6€Ä¥Í7–;Î_{Éž‘Fy"]yXºmý~,@yÆNr+(kîØ®™ñ3zL;,Ÿ" ì¼BN3$ü÷>åq6׿yðö]|'<@¶HZ°¦ „Ýè[ï*¹süÚÍæðX¤ßï”@¤U-0žàeœ‹{¶Ú3ÀÂÓ“ƒíTÆií’7q¢‘I¼y»Î…—'íýVç?rÕëHƒŒõ!d=1#3tÿe–®ÎÝ~AN{º4N ¡úÓ‡× ‚I5Ù(åtD# øŒ uÕ™Ü`ÔQP+&Ö—á`KH³ZŒhð!É î¾ÉA ê(‘e<ýd’¼þ½eý÷ímÊ5^äÞ¢)?̸Úþñçš–6`éØÂàäâ{î£Æák¼dVÔ™2S„Ä;¬7ÊN¤@‘`wdÃ@à¢`s¤˜á59—_E·OR« _ªzŽq…›Ks^GlÞ<ЈŠ¹\¡±BÖ³žBdF&!Úë\[S®~zÞd'¼ˆ’¢$6›ÒÙ¢½ÉŸ6NX |¼¡AÀ(噘øïÃrã;XËq-î¨ùöˆÎrI{@Î{"{íLÕźÞœ“5y\ˆJ‹Eã›%9×!}ÞCøI(ès=>§X.~Xp^‰éó{ì¨k±âøa§Ë%–&â’’Ñþ„Ww,/òmì¥z¹€Nãõ‡5ÇŽ/mKŸ¦$jìá +ÓK6L²8ª~í1‚o'š\8¸`À-€ #!C<×® lˆá2ô×8ëõÍÙXÃN¾eÌü®R«•b/!ö¥E7Â5ƒˆpdp«¬BÜqÖ;»8]c5 Ù½= L=«ô7#%í¾XžïÃ%3#6‰¥,4«ã¤"»¹¼±¦ÿò€uoŠ8‘KÔ<׬(¸§E¤;UZ ÙÃoXÍ:I¬‚ßMejyyBþBœT¥îú#6=‘q¨<ô,;¢ qÌ·¡Lá-á¨rjß~Ä‚=%³Š¿uû:RcŒ’x+#.ÃVe(Jź•¨ C°×¦m"¯ƒ‘1IÃÉ2*˜Ü¼ùÎÔ‡FÆ2­…?Ù0¨k˳ߔïÚ?Éðý\ðßCc£{ ž±¥õ‚>Ô儯p/UM†óè<g;e#6,Û¡¬…(àÆz¶bâJ ü¼¢‰®:…Öò7ã œlG1ÑŸát¸ù|±<ŸXÛ'M1çIñà /T½]‘)œÏo9ìð_Urb,ˆÝOèL{Sá_mTܶ§ã³ZY:Tú9°Ïo¿¥ÁÆš‚³(u™l;g}šm@óß‘¿²YµCfMjdÕó<#.x³:O)ºm‘÷/·ú4@[Zô’; Š÷hÙ‹hhP ¯;wœìÁÒ‚Vñ¸¥_F”m¥?ºø2_P|M9Ü©|r]¼­½–ko {†îPxÝ,lû5 =¹‡™ËJÔé{CTj‚Çh÷ñ•bìãšc°«¾DƒiÊî:L™$eR‹I¦ÆÚtî×ãÄtç)†¬ëÈß™·žÜŽÑ~“tÔÆã‚Ãœç£#.p²†}wÍ)@))ë 2d¨…t‘`!. 3ØYbô(%œD®‡#%ûtdb#ŠÐ7B™Ê©—Ÿ'Ø«ÁYúcþõCµg›ï‰îé¬ÔMRaÿ2[þ4¤ ]g†bÒ•»woÕNÝ«Ï,.1D¦•XËûØö¾ÛTÓ<’€5ÿ'ƒË.¸¿¢ª×?Øä*£b¯iöÅW-«cµ@UTÙ #%AýJÌ#%î? øó>ÝÚô¯á[íê{}¾¤aªô·ï«éE „aûÄEÃû(ÈõÍüÏŽðÝøÉöý–Áä?²ÔðNšxè` ß·¥"lÆP Þ·G?`lû=Úø ®j¹Ë—\ॣ4ʤˆAàP(AÍ&…à¾Ê0Ax2E¼«¸Móˆr“¹Ù2I#6Q0’D%9èÀ÷¯0(^Cg~‚ÁÛ•RT:F¯gŽw÷Ù}}v®‰ÄT$/d*>Q¾•4C´ãÝÞ¨¦ÙˆÇVÍT«Å„Kv#.ï­ÙÊ[Tú_‘üúl6q™½„ Ì:ÑAéé-‘¾ìE.ôñ x4‚à‘†ŽÎ2²#.±ñÞ‹|Â¥ÀÿóääqÚ¡K¥Èj#Åìðý3˜© 2r·2¢ «êÈš#6Óù¬<7ÐêžY’Ö1Ö‘$“â‚Íh>GÛTÌx~2‹ããéŸÊô@‰î*%Ô39h­þZš[ÃÏù`tgø·Ø’j«Úcü© Àïð÷Ãz¾ô! °,¹f°Ç­Ù”èd"Ô@„2 v¨0é³k(!ïh[YÙR |"€h/ #.( ³(00Ýú¸ …˜Mm”°¶>˜+dʈ¦²’ÆDTKƒ¥ÊGE´@ˆÅ2†. ¨&c¯u…ù8 #a j¥6MIF›EÜ.–3+ˆ;bÁ–$K*˜Ù’”³T”HBn|4D3Š¿Á#6Ù½3¡ç$ú{•OôÙ«ÂÿHô³ €i"Q`UK‹È–…s;$>ª¾5ñÌP({èlpùÈ?)ã¨,ý¾r˜b"Zô§KA±Æ’;5WÚ˜ øO´~‹Ë~ËýOî„Nâ¡{Zc#1¼¦Ìň…P'OäŠ)Ï­·ž±ŠÎ£¼M!+½E>÷TöƒÃßô9¶s¨ÎšÞ?— ä#%“`cnh?½öÝ+ŸBGG%om_}Žþ ¤M¼Q' ÀwG«ÏwE&h¢æÝnï%óªpmœÜ"&ñõëw&©$·)¢rÛu©í³Ùí«ûÉíööñp)\uÆUüdá{‘KãqÚÛ ãE¦é]RÎ*8#.ñ6lTxÌ2Œi†˜§DéÃL©Ýåj22JË‘ïuPݹš3Tj²‡©ÿ :§Å¦%tCAç0Û³ô=f[ŽªŠ®Û/0Mk­svLoTõw e1ð C¹{…ÉR‰â_qý“Zk‹ác>Õaü¬ûìfоáÜlJéæBBé€r'·;<[ŒKå€îñÛuïºä±f’È«%3J„a1b‘{Ûì=G\‹ULj#ERX城ncsÁÜr†sVÓmš;ÃX;MÆV Š]±#.Z²·›mÔ2$ †g-$F„ÄÆñ žLŠ%ð.ª_–L©§Ç6íßQSÔxÝš#.I»!¨œM#.”F×Ϫ‡MC€êvB¶ð#%æ! qŽI*™Øt‘§m­Œå´Æ¡t:CÖ\$×@0!ª†#6%ÀB‰eV‰7vd”‚À°ò®cÀAÖ©Fvt×FýeÐm6Û¨ëô_^qöÀ©3_éävjᙎ:¤ö7T%â#.aû ŸŽÈ3ÅÀã#’Dõá,üPCª†Ä{Æ–ò½˜½«XÜ©¦_=Þq¤¡A g6ОO¢¦‰_*’P!6E†3Ë87Xd]ä#6­æmóŽ±2M#%áF³™k#U@T¢yÂý3Ø›÷o#ÖÉÐÁfÞî,Ü ›;èΗm0T&â&4÷5I$ÂpŽº~¶4Æ1ržÍ/€‡ë›#6íÙj¼wüšXëËh:nx–fø|ñLJgXC§ÒPt/yÒŸ¿áìÍørŠ#6°\ÈÆØÍ(‰< UTȵ\[#%^™H#.}qš¨ÛVFX+1á÷D¨ûºÕÓ­Bà„#..”rªü‚˜m¾È½Í—¡—½Y]ŽZ† I„¸8ÓLÓA5À×ÏN·Ó0$ÑŽ–mÅ#6æ#.€Xõæa÷îÙâ.êôå“\ºHÜŽ9T¥w_–¥v¢E”F`0HƒÊ¡E%xÜÂ+º¸öî2<õç<Œ-“#.áê}›ϤÛy£¶™ÙÜT[§Ï%)Ý7°40¶ãòâæÙO:§dXoY£t¢«º{{»õÆU;ªR %£D P–ÈÌ0ì¼Y3#%€Û*V ÃØq@iãAF®L`àîë´'©!ç#´ ÏAVì#º(®RÐBVcÙ3±EÊí’ a „›¶)ÙXª`_€žôÉ ­X¸h£Dì;£Ûe¼ô‰ŒŽ'¡Ž4QÁJ#6 Q`¹”(T"’@ çK¨ ®¬`²ÇînÆ´Ý ïZ:uY¹í©ŸÆtFýð›ìÂ-¢˜RTˆÐfµs™K>÷Bo¾Hç¼~YÅuúý­sPÓÊÑ¿±ï ˜9:ô–Y†&Û˜:ö cU:çÙ›ëBûrÎ0º>È^i…[d6p;÷Š6¡ ’O‹ðƒ#.¿c>ëU o*&L:ÜÁÀŒ–.$ó³ôLx㤴»§Õ~àÂïÉ9Àë'tldæ…!¤1#.—@Ìäu*n&H÷QT*ÖËCî.졉=9"E‹.Ôœ+u˜e×̪¤HÈA$}á{;~æJ²\¨MâÔDF`aÝGnJB†PÁŒ=­Ù#.“ݱâcL¸¡Bž"Yáî¢ýYÏÒj@=½Ï<èq¾í!É‹ùÆÞf—l¹c\ƒü1GVø¦l.o6ÈêûlinDµÄ ®ÌCÆD ¬ïÁKøµˆÃÖ)Uf[(8?ìBª± §^fÀ] tJëM/œBóC]™éƒ¯…è×»i¡^|ÇE7u[d¥g¥ÊZ;KÚ`¤ ÆóÈ3;†óæï`n… 節qi‹8šöדOB!2ÌØCP;Èä{Ž]¡GÊ‚¢¼È0†QvDÝ9¼‘¥ºËY=†s³¤íEÃBî4¶:˜vAèC2.û\•|ÓioÝv®ZFQ4ZOí²i2e67­î1kÓkð/™#.§]Ž6@‘³4xÊ3töÕÑøželG•Í†²ÍÑ’@R† ]ˆ)˜NýþüueVL5š‡Ú)·é.´É©ü sà7§@4/:UÛ‘Ë]u‹C<äR\€wÂ'UWÞ:çQ“vbª§F†H RÉS©Ð,wÀ×ß=uÃYƒV\ë2‡“Rª™MÄ£8{ôíåŽíxÍ]z¨BìV'׿_ÝSÈ2È6½–_g¸ñ¢Öåä#%˜Æð§:¬É©£_ÑÆxÖyßÔ#%ŒÒéDÙ‡¯Š~ªJ†ó$ƒ?Ù~~é†8f>†îÑ=G/‰…Þe%A7Üüq,[Y§â­¿o¹€b΢oªd¡ÝŠãà¶4€CÄ™À?Æaûý?ËÉoôÝÝã‰è”Ÿßþ$Ý6aH*2AHe,-3ôWðþ>—|ðoÃpûgŠrñßã‹jËntKç;ÓøÂß­%ÂòJŸMY¨TßzÊüúQ÷óÌp?îüy÷?=BVüsɼcýNG8(´5Y‰yPYú¾ÎÞξ½¢jö«vÚÙÜ1¸ýË}+sk…6édص2½yÛù¯$Ü¡i)_?ï_Œ3÷ÓÇíüûàüéC6ª?·LG÷³û_Àȯ«ï5‹Mu¹=!£~*+LOú¤k2¨‘bÄ2ðÏVÞ 7üDÏDa{ª';âûƒ (#jº£ª€%3t»¬i×¥¦•A‰QÇŽ®¬2ÕYhqßž´w/ù‡øƒã¦Z7¤Åö#6uÑiM«ZÎ0—XL¡ëŒ!…9¼zóü€ª ²zYÏ¿hnÎHr`§fá5©¯N$fá"ßæßV Þ±Æeî>¥?ë.3/«ð>KÔ6½ŸM(Ÿ9ž—Ož‰ ÊK#6=mcÒï¾´'ª¬€§J¦1EæwŸ³g¶ËO… õR—¿Õó °"ûå m"À„Œ@¦D¡È_ßØ_éú«ÕÈqè4é|Ÿ`òßR쎉+´j`ŠQ‰(‰âL”&‡ПK#.FM=‡3–ÿ§úñ3£I¢Sø¦Ø¥cÒš ÈȹÄþƒ~î>ÜþËq•U×-Ã^Ë­uèàH19ôêaY?¸NN·Ñ¯¨]ó#.—y·Ûßù `2É/ÈDÏà‰ê>Ÿ #6m*€ÕHç<\2ê=|.mcÅwž~÷‡w§`PòMêÆ9^Þj¼=ÐXÂŽfulDRžÀç,±þBp­ˆRH‚ú‡Ð݉™îµ˜)_Å®ðߦ.üîÏÏôúýà|Iõü¸“ò» ãšMJîë áEŸO×ñ"aÚO‰A$ÉF‚ï5ýéúxqçÐû¦„Fwd;zçСËÓ².'œgòêç©äâ|9Êlrå€ó×ê¯l¢:vGÐi2] ™³ @ñ¦ Š ®3×#M»½‹.À;Gâ¿9BG8ý¯ý\žŽý»D=®h¯^þòÖØøÉýò=k‹âáú¿ÀØñ<ÎzüãËçò%LÑQû>\ÿ3pÓ°êvÇ1gío ¡¨Ócj‹ÛÚï^ÿø½\¯:³Hr!i ~ZT×°-î(ÿL½þ›rø†'›™@Ù·Uì:k¶+cJ ©Òò]ô8<Ãr¾ɹÐ#6È„Ô˜²¤ƒìüØõ^ˆcÕgqÁ”oTÔL#6$8ˆ=Ìò<Ë1c„‹Š4+?G£âòó¿x#.âÎ\ÝZs ÜŸ™ÀàF’)¡EŽhsŽ•ƒ.²`.z´ñò„Ù0öªÞÒʹQR~m+í»0†Ç._¯ÛË—ÑåÇC«nè5 ÏutßWv#60蔪Z.0òë𷵬žËðSŠF§NOƒµN®#.ÐûEÁ¤Ÿe˜ûøÑ3¦2J¦|;ìïMmQ³ ïºvj†x¼rïJœ¹¾Ý‘~“Ѐpr)‡c§~¢;wo«j£ï‹ïÎö1žsÑõñTh#0Ò!ãóR³UW•×}Úh¥bÍ exƒËá "æ|PH[ǧ:àJžäô/°qŒDC“×I¦™u„ÃGµ_z§ó8Xzgü‰Ï—N×È:ÎÝÓ¿¿x£aF÷›Ó¤ïÅø̺€["·½ò½ejøM†§Û™AéA&¶²¶®6)BЉˆ;XG꧕('ꢵ¬IB¬×(~ a{ŸÕpß5×.êµ 55‡½.>#b·—´Þç=ÿ©]oðÃG§Tmü#%AÁP1@zsÍnál?]ÞªzxkÝ@ˆ2 eó*+hÛ:¬¿w›ìݩΆÜ~‚ TJ–^9¿ Í‘4hB&¨ï¿#.xbðPýÀ;Ô¢Ÿ^Æýú}¡‡›¥Ø€K“Ú}´!IŸ+ê@=ªçŸÏ@- êá)"„-±ñ³êa”å7&#.J+Ç¢ñå™ÏL½pæ#.uÚ…ýŸÏó,fƒò¼5à‡(ÌTMB³î9ál¡0á5ŠÕ’:¦s‡V6z=oÝür¼úÙ,åƯ÷~\Ý¿£Œm½ñW#úLv‘ÅÙÏ#.‚{£PP·6Ú).zEËÃÂ{ï»ý›Üan!Ì@ï\Nø¯*}Wÿ†±›þÉ3ÄÒS+ÏPhÅu·¯cãßm’Ù Ó‡Ú]’<ÑÒõyÅÕ'ëïztW{ÛÚ³—êøÞ`Ì«í- XLm#¸ ‡F—u¢ÓZ±ä¾µïŒÿ9S9œí¶}È8ß+äªnæÓ^ßn$ÊdE[Ó'}ìt”¯íøѵK¥Q´Ûmï·“mˆs³‡ñVhïU¹á _@6½o‡ÞíöO¢êCU˜sª†V“Ãú«:ÇJM,²tnOƒäÛ伎r'Jh±Ï“ªŒÁ¬ˆW•è*˜• IJŽTy`¸­ñ´,xÂÆPèL*3(#.ÛàsÇÍ(Ç5Ã.wà~>>j; ›A^ZÕŠÂ0MÆÇ¿š*vˆaFš¸7Ï#%÷Ðgˆ}lÌÒÌÁì-a”Ôƒz3urî#.œ‚÷?̶›#6!î8P¹òˆ-ã¡lÕ]EïÇ®ÎZØð™[¥•ðRӇºÝâ“H‘53û5qµ‘ÓÝ¥ƒ¡ƒ(¨*‚—Sv†Akë«Ü´iXE¦ë%qaÅn_–#%ÑEò¸ÙeÑ.’g}‚H#lkÓ>§.¿ÙÔ¯-º(ž2}T|pðÔ=ˆæ ÊÓm.C:)]úÝ«ËÛyï§ÌåÝÖÇð …0«¥7§aÝçYјóÉî® úÁž™ÛEg'>±Ež®LNïˆzûë1Åè§âßÒ(íÓ\x¬ëµÎ©ê wƒõÆiYئóãÊe0wóÔ‡%íîæ˜~çÚã¯+}ß  Ùî"•6ÃõµÁU =c¥Ú8j~>Ï?sÓ×Òs…Å"Cqv…?·å N=3 ÏDü™ƒÆs\ùÿ‚¤­õ¤=§¤y-&*ŽJý†öãÃ[ÔÛw ™bÄØñéûDfNÖHZZÛóJQù«¿¯bÑÔ|¥¨Áv¼êšŠ±¤z(ó±V‹ÖÁtAµêq¶#.èÄ‘ø6ÔÔrÑþú#¸\ØÇÖgÞü},#6ÛNjBÅp®~ÇBYÅ7ŸàÅË;æ­ßO¶ï‡Ãß«…Ä* Â=µ³\F’˜v©ểÁRÚMܯ©”øeàE\G)×ÈLÅ­<ýŸ™];8iÉú‘Æ££í –]Ä ËĺÏYŽ\6Çg#%U¤{’Ø[†»¦.Iœ<:Øg‹#6¨Q.AQÁƒ´7漯#üá#.¬h;û!ƒ]žX–0ÇÏçò¸m‡gÝš1Ž9ÍÿžèmúH¾_H‡–GYÓ¼Ï?N××wíQ:)þ$ø/KyÎi6¡+žvŽJŠ¢ÕE‰B¹@¸ÊƉðˆP¢úz…¢,Š¡–ªÙm–¿¢„ÛiKˆ»eïAxý1_®ùS4`Š÷³…¿wÙ“»N¶{PÔôÖ÷ÅTXPD]Î*çDïCEžüYc¤ô¤ãð^FO¸Žëz]ÕÏéæ’cpÈÚUÊUÐ@œ,#%ŒÂpHmUWùa±ƒµ®*|ÛH¦Îˆ}Úu÷'Ø2›Ô¤æŸŒ¼…ìGC9BSu&3æÖ5ñh÷=3m"±|Ø\!€XPŠ‘.{ØyÝH¸›¹[¹BJ+ÅGPÍS#.O2,,<Ó¿f;r‘÷ú½M`ª)…®¢Ñ@9b\m@ü @@]¶ÐئD #_K®cR(ä?µ‰#QQÄpFñ#%¨ªêªÄÄ:UÙ#%œ¨"ñÓmÝ„²#.ž·4맯É(¾Î^¬(üEJBë…‹2 3º ¬W¾\îp®4«ÎJê#.¬ËqÂ&zÐB/ò‰!<Ë9#.ølc´“Àw£ôMzME‚×®#.CÁEEÁEà#%‚qÈ|ñ$T½‘Š"~ßÀ$ééí#.YqrA@f#%ûW°@Cë:ÑЊi&s7Ïôì¾&BOCüf+uÙòj” Ù$ßœº×Ïíz³¾EêOæÚ$>ùhÕn¡á™t÷HŒ†ú§¸!#*1"Ú.Nç¸Û;]\xVÙöùú¤šd^ ƒwÏ|gO6ÃϺí;ŒJæ0&é5Ó#%}¡8Ur/$€ß…3‘ì„>Ü­x¿,CŠq¨;™†•@v/#%å@]¹C9P¤grÏþ¸(9Á Èv kš$§9T¬Æ4˜h ÷~ÿm*ñ8꘻ˆÈ` #%X} ¹lJ‚‡^¾ü. #.JCVgˆ‚5t^‚ˆ7!߆÷ eøÆe#%~zT)AY`ʼNµÂù íUö)>Sæ׋rYXP\¨¢!Å&‚NŽ0#6±ƒzY*¥MtÛ ìt‰šÊl,tgÎçg2ˆj—bOåN@–Âq7´ñ&¿FŠ)¶¦=((œ{;›‚P'+ª×Ãw”V_ðÀëá?tf“¸Ÿ@¢ÛnóX.Ž3Q%x]]Ïv[ÒÉk¥סTÔ4¢¦ª%…e^ROkl(FX8g&øw†å!£?géâÊ#.#íYÍïj‡~†âi›e•Ä×u'³Ý˜e;g•ÂTüLìq1Ý ¯#¨(òáá#ŒÉ,p†“çt‡Aè•5+ÙldèwäÕÒ{øÞv‡åÆ;Úõm”P•'@î}ˆço=pÊ2H#6O G™ê_™0P&Ú‰J#%íËTO¦\ýæÀ¢j›hDp¿É“ꡧКy©9Sr³xêÚ-ÇhvÔdŠ#.Y|ÓãÃPmSÀˆ_¶V?L_"'(PvÖR«6ã$¾Z'Žxõ×=÷#.A='áTP‘)þ%¦}ýjW¿Íþ\èô´Ò¨õÑ3Ê¡â̸|ÅZ~c¡ÞFÊ0‡V‡(·ÙÛiúÿ+Þíôüt|~!s#.Ë@Å¥ÑZÃñxä·˜aƒ……%»©±ªþ½GŠK1à*ÒpÁþ'Â=6ŸqK½•¶±/öþ ®x ©®óÒ½±dRl/U¬ôdÂAÆr³#6+óÁ…G‹Ì&IŸòê“nçôBs\g"ìé _žKâéœ?ŠŸ§èMað­{4•„ÃCɸü¤ý³þ~öÜ…ÚázNö}Ëê˜9„)˜Jë³ÒïIÆ€f¸<Êw²Á»¤‹Æ=,µ¶&M•!.üpVí±ðNtÞe°Ø²”Ó¦p„1•ИàƒøôžzrżùX—wÇ+8So£°y1Ï,ð#.›0#йò½ÇÈB9:ƒ-{~Ã1[rµã[öÁå/{Ã"“ V«Ñ*&dÛëqì¶Y-Ï.õâÒÝpœO5Æw‹;-¹’¸ò ¦JÅff Ç»¼Á¤à°Õç–H‰|WÉ¡œ!I¥Æý1eEÖ¿Ö9†AŸtP_ªÈåÐêk‹WHV#6%±¥ì嬭1^ˆ´#0Ó)åªùº°E­óg*ímŲÜë èûßÁV–Bo^Eæñ4ûy­Ö°‡. éÄFŸ±¾z4÷ö`€¡(Ù§¢œW'¨f鶹Jb•‚®òÑ;¥:ZÑ;n‘»Íçe¤°,5÷¿_„¡==:©8¼á*è›çñŽ–_ozâ|qä“5v]QsÚö.2ß#6ïÓœ‡Ó~ýá*ÜEÛ‘"cƒ¬|T=ù<³#€‚ˆ#6àœÆ`—Ñ-¶™ŠP¦#.…ÀLï6– ÏÜѺ Gà¨ëÔTt6k®^m¾×¡Îu¾íˆr%ÄD>Ú‡òQŠMŸã~pÝŒ, ¬&»œ_Ag¨šŸ²„Naæ{¼'##6ØÊ°àY•€È‡#søýø²\¿ú-´Ø~mÞÂɱ*ƒ6i¨I@­¡¯PUG¶/G$YYzÑÎR0úgÏüŸ—î–å¯Cæ“ô~6·ÌS™PÔŸ^ÎÓ¤é#.Ózý¯kHmiÛm.•3Ìx‡K¦ÜÈÿ~®%Ä"Þ+G;L¡ïncï–53áõ>¬pxq¸dê}ƒŽ †¬=ÓÓ·Uý öA¶Ÿ—vr„v¤’9’“4‹>ü‘L¸½p¯´°©gL{Ùþµt6É{<]^ÒÞœ‚™Ó X ÈÁ\€‚ ¸­ALäo¢—Ïóü¢’Ôð8ºÜP6;Ak…Ù#.†›njú«xõm©ÁäXµEÕ-— ">/Ñ£§5ô¦`åä[R÷6qì./Ó#%®Prö9¤¡ÏTXŒù8H^ôѬPòÖ~•Zª¨‚S~§!¡™<פýUîO'›Uú¤–0°*û¡Â!5Éåúõ…`ØY—³¿ÂÁà$µD£#%¡<矘 A8¤y¦ç½â±F*$‚P’IåeÉ#%úZ;dž>žý{/ó n\ö»A8*Ž#vw3…*ü5`,rØ5¦#./¾ºËÜŽ 4W‘i•Z¢‰œG˜é­Ÿ!uá&(ÒÇ_q”Då®gˆ·3$g²a:¬ï,ÕMˆ{ÂkÌû!†ÚR [€#.Mßâ–i a½6`3­š"»—½§ïØÈNÐ+Ùbv™‡§ˆêëdë—ŠZO9ª$-]»°Û–ü"üfÕÃõ¸p‚ELÂçìîiUHšE¹é±e.™ÂC¼â‡gA¬6y¢gÃë]±éwÁ÷U îåã½}¿)¯#.A²ÌëðÀ`lAºÁ×dí9Èãjá*Ù݆ 渻²§°ñ,‘ƒ«hï Ü£dwÌ.°‚»d€åšy „r ‹%(sãeäFzeÚ­Xí¼#.Kó¿i†CÜÚ'~Z6´–# ±sY‘”JÉaL”Jƒ ˜¦#%39F¸¨™Q" ^Då6{PSS3yÝL†Ý'n˜'´sûõ*ãšz‚¶ƒ«cT¸ˆ#. 2!r(PhPÚë37nPᙌF;E6‹ƒ#%ò-®}“˜]…âRkß ×ø°Œ‘ç>Ðt©Ž[â¾Ú²Ù¯kYëõÉ×,oÅѲZf°Øâ'̆ü¼üFæ"_ê•ßv8í<[8›¢XæË«É;ýˆÚru06fåÚ¹$£”ìH½_¿ÅÌÖ_ÈB'ÑsÁ¾Wì$Š“³m#6E]}Ñ#.~j4aÙ£ Mfù‡ ‘À\ö=‚°¶²„„ÔJqå΂{ŠôÅO ª÷Üþ§Òj›AéTPº¦Êƒæ}Ëã1¨ò%¦ÿ£Ì÷"‡ÛÍ¢1#6HsMžÇ¡±Q¯5óßâ¬Ì½9ÆÂ>uRÂ#}ì3va¤gìvŽ‘m¹€ZUÀ#ª³qÆîëƒVØX®H2 ÚÏßÙ#.ÁÖ›@¨$7›°­íc<ƒŠ!"†·ô2¯È.îöö !Ò‡5‰ÐÀ„¡LŒ÷³á±Ú¶æ…™Ÿ`ÆVØäºÑb#6#6õϧë(¢Ý‹a'9ú#6«`Ž‰„4Z†¢ >P4i á~q\KAÔ!nAÌ‘)™ÁÑYÅɼLèÈÉ6Þ¼44mŠ§3r !±é郓Z-*5Þ/!*kâÔ €VäD­—K¸ù°;"Ön[z€2bŒˆèé}ˆÚÖ½ÖJ"ÃX¢žÌvh{X£è¹Øf¬b¡Z–ëó‰Šè¾´ò+AŽ­u~üâOÚ°Éqm©Þ„:¤Œ·C®aïÄ,«&q\È™A̶¿n<l4(ÉÙÛÄW†ŸΔ"oí?wŠ©zg\.Äf¾]%k€Ù’¢t<æÐ#.c–Êá tgß›r#%s-¤  ÷çmhÅ»]§ˆN4(ãZs´cÎ.ßx*sŸgi5‘ÃÌJI@íod/(&_ÊX·éåøC¥¿ZO¹V?0Ìd<—‰Ö‘¼ÌĉË0æ–•;bù¶ëðzàUö‡Kd3‹³ Ê— áh@Ù€Qm´c`‰ñíYÀíÌ ÀNò‰1ª8Ø”´œ+n5µ#˜ðF¼]²"†RO]WQ5#.ê/Ùªß~”aêÔàí#%鉣µ âÓ˜ê(-ˆ”+ƒGcÒÐÝ`|^D]ÿ¤¿³ÄœÁ#6El\q´`!z I¡¼<)MG~©oÖxEß¿øÍF'­Qn#%xTL9ó¸- 4‚€ÜÜÜÝOÂxp8Yx¶@Ø‘o\D÷Níuœ§WL7COÀ»îZ¨#6iY|ŸÊäVú—AÓ]&[óêæ¥À_5·i>sE/#6¸¹€%5ÿ/ÃN¿ÃÝìï(öþlâò9Ðs7Îåú§óˆh£ógTH‚€ŸðYg}ç_Aò0¢VÅSNÄ‚HQ–'Äá×õÀ£U GJ­ÙB3qØ÷dZšÞ gÅÒЇq÷q¥¢×‹_aÜ8#%Iü~JÚž79ÀëÒ6ò`á|û6¯/ YÚr´hÄú §]Ù3óþKÕ⻳«—Ä|3ü|cÈužyb3f‡ïíÃø‡Ý Cx-®–X3ÐPX‰ú†t?Qà œˆL#6Ô28~±s;{þ|%UVvþ,¿Æp‚gºÿ…ÀY²Tì*”Br)SŽ0e–Çûï¯Éþp>VÇù¸îü¡ü_ášbÖ?©BÈrøð½C9%_ý¹$TÅIÿUP©þ·÷êYE»üZÕôAêa#°^ˆØ”Xá©8Š1#%hÿ]¡ 0;5 gûYý¼³Ö÷vØà|ávçv…†ßë›ûîšÖáþйގc€Ë«±_wNóx©©A3CaÚ— ï:Æ]Û¸…xn4©‰ã×Ìê{3 ®íH¸éÍßYTBºâüT£Ca²lÀ–ºª<ƒý¼ƒ;ª§`xµÍG°{‘Ú€ÀÞõ{ƒ¯œaô{ý.Aô¯³í4A#.PÈû=¨íŠÚ+þ˜ªYÄ; ]ÃäNÁ5%–‘Ñ…î\þK¿ÞÍ5”9€Í=¶Ïâ}™ F²†¡®B Ötüû™§ }ËÔ:Ð$A7ýß¾ºÏîû]MéÎÉ㈠D|_÷*ØUÙý./Žœó,Õ!nÿP=`dÄ_¼çœâÜ&\’B7dªõ{ ²Aåý—ˆŽ qÈP#%)X†u„¬¯# #\>Ïæþ¯G¿å+÷[q7¡ˆç˜b<œ*„™Ïw÷ý=OŸâG­ÔûôŸH|ï=áãøN®A ÊL’ª´RÅßzáóHò?yˆCÔ”“àVøþí¼…ò>!”0нÈ^‡ûÆÁ„.4ñ6×å#.ý?ipvóÙ7ìj¢Ñ X…˜%.S–7pÂM”ÞbÀò6£ƒ4¡ÖyÂCaΚ#.Ì·¨¬Qv ´†&ËPÿ—<#6ÃvT‡«±}ž‚ ûXðÒ¥W–‡Ò`_Ýä }ÝâÄì9Åwœû[wmZ?¼“C`ðã tÌ{àsõ›Û?OqÂöžVÆȨ7RÁ°Æ.¸È’(H0µ˜p½#%o{‹‚íx-)F,=žÂÙ²"œÃÌ„ä—°íÀÚæ9Níw.i…c’vL0ìòÆ‚Ð*ÚÃz}pAZ€sŸmy^®šROÅö…îNÿïòðY GÔT%X›|ËBáá5¦ý4 ¨TÎ(ÔXÐ# ýeµeþô=]Hê#%ºwZÁÀH“_ž6£áúl¯ïwç£èÃ0%ï»=¡iìÁ'åƒÇ`w‚Ž%#{†ì;r6,#.øÖ,ć¤zdx`¿‡ý9p©CYÐÒTe*ÞiD¢-&¶Ö H<>Rg#65Y$îŸ?.ÔäxRR°Áîú=T²U}ø@ú1ME~ kmmÙG“åô¨óƒ&FØèÃefæj²’~G³M¬2ëôê‚YAÁwYÃâÖ÷ ™#%y M©o®#̉ôlBÉÕ@"Ð$eæ ˆÄ|³5:IF~Œ—¸"Ì-¨É>¤÷x›¸ºŽ"#.?â#6ª[pÆñ”·æ4ï* *˜D¨ uåsØmos¬!ÖÃfM€ð*fÀo5йdãÆ¿­ç=1…”V·ñÚÀÓömçÊkû8…6ú„l£\ðgŒbÝ’K!UU;¤’I#6ðïlJüý¸f¶­˜Çí86#îu︔öoz©žàÖó×„É „à<è:YhÜðyfÊ–çñΙSlK6ÉÆd–.Õåè‡SøÌöü½Aô–~Ã!#6ü§ù‘|N3ôÿ›»òï;§ÔO‘Úy K~ô¡…×Ä°´—SêœúfÄ=ºÔ#.óévdÖõò?IÆÉõáUê6ü‰“ƒôû”[~@ðˆ@X#6‚Ä`ÈÃ/õ{ü>Ÿ¨ #6èQÚ@Äöl„²Φ§\Ã)%±·P7À`«³¹ð×…÷C.ŽÐup È`gü­ŠûV}¹Î•|¥F1°bcC„2æ²Ëœæ‡0ž}"£‡A°o‚#. '#%ØÐhü÷‚ìÚ¹&F÷7yGÃÌ2M†Š:Œ„ÖúD(3ü_‹ý}Hlû·§qƒE#.2+Ï­M¦äûøæƒÖ039!×ÚFå—9-Eö V#6„ ‡`d’€êxïk #%ÔOÁ-=fŒŠq/¾Êƒõ¥*`k|X}yÅ^Eí“!l<—FDYºÓA ±¨TD â)#–¢š3S :€™™š‘i°q`wr$îï+à™±›">,Œòq$D©L#6„3ÎÏõk’NðÍÔk‡Ä^!rÈÌC¹éi Ñ93C<µ™½Ø2.¦„#.Y$ˆà ¸ûŸÙÓñŸoXÿËw^º#%r€ÿ™úõˆUv­Aýù+ŽRWáóÆVoë¸q®ž½v¤ÞŒ”™zíÛ$cÁú»e’XjÿÇý1ž-.õ„XÊf‰]dmffžµ¨Tä!Ô }™§§Å´5N*näl³+”¤CEš‘×’I$™ª5ŠLTË­MIikm§™«š²Öjãzef׌º†:õ„ '«^kA«ÐÖ·¢šféu†G¼ÇV:ŒÒÄeA)2¬gøY(Î:ü¾Ù#6ŒX#6ª4YH¹„ŸŽ²¨é™ô0 ˜A‘P~_bÑjTmå»2sxqnaÑX„î;ÚŸ%³ïöÞÙýµ£ƒ˜t€Gí^^ÈžÂÆÛýÁ éŒó˼ÉI~}~ÝÕ¼QRü¾ÔúÑ÷}‚q§‡#%è!À´>Ò^„¶Cwl9¨; Œ„‚6ð›IÝ·;¶¯¬ó·Þd]¶d>a؈ZjH M)ßQl‰ÐªïVY¬$ˆ €r¶PRm82d?ðÛc;ŽÆxézZªÎÀ«àU¶#AIE5º&W¾f^%àù§Sš«-5RkÓ„¾]ZÍÌ¿ŸÂ19l=1IAJ~ËöêuEð4+Õ.^‡¿%6‰è ßرfÆó£æŽg §-Ô¦ÝɽŠI"H±’~Å÷WN3v¥7(Š)sp‚ƒ*ˆKûû;®Î϶þÒÀû“´ÛïŸ3Ž£ßødc_dDôvö´€’»~¢µQ‹ý![~Æ1m—ؾñ!túíÈÿ©©¿)èlHÅ3ê+ì:ŸöK<¾¢ªQRR”Š"›äÙL„Ù°LÔËsMw¶`¡º îÍieBñ@0bRòK:R¢d|~“n|šâšWnƒGô „ݽ}‘8_¨à<'¯aòV¼Qîó5¯·o\W‹÷Û^0'h7 2u%‘¸Fmîò f±0/ÍÊÀ·ió¸ò@£P.£ùbúÈ+‹?NÎTáõPäDs#%>!ø½Þ@Y68þçxÉ\ż.Ü?€ú-¸QÙþ*°™D­jIôßç½a-êzÄRÏ¢ˆ*%ö›Q<ìr0}y,ýÂz ú>Ç[„žäv€ãòƒ`õ#.€²Â½ú&Ì2(Abã:’6ƒ¿ô9œv¾ðû`ç¾É±9ßÙú_¨ì>†Ê§8»ÀþÉù€ö»6x'ã7ˆu'€{Å;H©A5twµñíPI”É(Ö?xyX"DNþ}+»ÅÞy‡sF±èæÆÀY—€3m;0#6ŒJŸÊÌ#%âaAŒö÷D<…‚É„Y(‡Ìò ¯À.pW÷Îapõ÷lòÕs½8¾?~†ç3 PGÌpC© :¨3yC³ŠÐÕ?P«¯™»/id+ä?ÇGÞÙúÉõ­õɬ÷V7LUQX•®4=áù2»Ý–£¯ë‚ø|áçð*ú­Ä ‚êkCÔ¦j˜„‡£’I'±â©æ>·Ò »ø5UŠÈA°4d€>Ÿ/ЯãH¤ŸWb)ÙZ]CÝZ{Ž_\£ßö¨0G±Lùru‹pÖÖÆZžÿG}6\ÒšT…Éá žåõú÷£°20®UöÊ’°8MAÕñ#.7û;³ ƒ¬{Š¯Ïàtc$Ÿ:F†Þ,!î:€ìÎ:`âÁbq e¨s꾸äædQÒPÁ“NêƒËJCì2U‘ ÕZˆ*>RQÀÑИ†©üèeLæHãc;väáÁbNˆTm÷T†Í&†t”K£Pññø©†tóUŒ‚Hª%HYÇW¯>nÛC-Žmu‹r6ÑêE±½„¹Þô+šn}|=i³Ÿ'2)˜E^úÏSÐ2üY"æC}Àí•iòJ;)œ.Ù¹ž½ð˜ h_Ÿ™é籄¾üåw¼!,Œ#6|õ»ùN}Cƒà=åË)BB¡háô"þã3ì• kEµ,ã‚e”'?`vðßù\à£öíç¶>ã‰(}M|)kì`éþ¹­áaª]Ë•àa½E½h#ãòF%LæV #%ÚI0%‰¾ Z\Baнìh%R­À2` øÐlHvE6Œ˜‚(¤\D½€d󈸂HÅH"8‰ERG5Ö ™½Áù²AC€ DÖ55-~£¿Àú}ý#.>(#.ØÈðòÅÓ<³1™Z*¦°°'Qb¨r#%*ãIé}¨kOH~)Û´ÑLAG§QbY()9gb4 ÁˆGô~×ôs­¢×3Ü“×fH„z3J³íü`‘œV߶PÁý+_>q°Ù#64X”Ì¢3|»Í¯’r«Ò¸n‘[]0ÙP˜‚²ÙmÝyæ]­<(©h–‘ïô›“Wóúý?f’þÐ3MãÊ ³ìóžAì};`%õñºéîf ú‰#%–½'¼ŠYÍõù½HÃ[±#hqŽÃkóÔ6CôƒH&·j ˜ªY1#€(#.D†B2`ëJhL€é·E(ˆÒŽ*XZÌO/'œ ;+Ó³xBJ<ò9œ/;3§¨^-ûi^Cµ#6@Õ£wëÜŸ¢}”RN5 7ö†n9ÐõD#%ØpHo(ë u}›J6öÄ+pòi:ºØç¡<½s¶Üíö[c˜Û’.Ó à49°¶¨ <ïªÊ<Ïgã³ÙÛƒ; Âä=Åa¨]lùŒ‰úÇ#.ÒÒá)Š#6(£ß½d©ý`~¯YíˆIæIRJìóî9\§ÃÞúîŸ8ÿ‰#6Ù6zC¬÷|ý“>4Ò~Á1ØŠŸÂ¡ð&Il™LatɆ¼,#ZÅò4|˜kf_Ñ‚½š ´¸¹K†\ UÔ0½—¼$…´UO°ßÈùq¢úHhG®Ž¬’:Š#žY9!|úÿróŒ=HÍŠ@p2¡ «B#؉ë·×îüèt*KHÍÁÙ·Z<ƒ°ïC$"4˜ëêëç–?}z¢3ŒÔŸx'îM'oÝé#%ø÷ÿ´‹;)âB0®ƒôo%dLƒ›,6f(·—Öߤ¯J”¼u.î¯[ž½¾zDZN°ëÀàô·•NV’2KÀ.*Ð~› àGX5ºž!¶Å/K›¬Û…Ø©Ó€yâzK¨Š*üÌ`…–êAn߉lä¦ï/g«”*|[•B‰³‰¿âUBP„ Ÿ£âÍù·4„¸Å„á8'Pf,ÍŠ¥d‹Ä1éÿk‰üš;Ô¾Ö#Õ„žQÒRƒQŠñ{ùmzIIJ…0êĉ´Ã–Å…ãd…å1 *ç0%v_η?nTÖtÎ#lš1绸UgP=`Š‡*•IùI²8¢º'ʨ´§F¥‰ëPØ A¶_NáAJŽ`µ}ÿ¨|ýÅÓÚ/O€>9X<ü|z`î7Éíö¤Š»ÍýVèŸt¹ úd¨HÁ^mQÔЯ€ŒÒkK™ÖH¾‚ƒºëÓ.pâìDéGb\3>:ZA*à¡=^Wû< eÀ|ä 9 âp]û-³•¦hêØyƒš¡¥ÌŠšÁÐðN£{q¤bB:8jð´AK F#6#}븟O`y½JÝü‰Ñ <÷ à]ÈÈJ¬Êª%¤[9‡_Ôöì;#.HÂ.Ò‚PŽó÷áùOžÜ¶ÕÜ’“ÌúˆQœóμ8*eåàx _Xú(ÉA=ÐIÓ퇌É\½èÖÈ,Råí àý<ž?ÔÕ =>Âcp`¾Æø™ÏðAv}Ï°¦òO"¾€<ªŠƒR†{Ë€¦8r?ŠOësðo¶S·à~4Îj·¹£0gþðˆ¢¢™+dã(€Z‹@·˜A}î­lí…rÔåŸØޟ̤]×Ý®¥éÎ#%5I#%M$—ee5hPmØ؇5o¢àLÝpxûÂoJ#.0I Ò,6©‚BÈXõZªPýÑ÷w˜*÷o6`>Ϲ#.¨,~謙ðˆ!"Æ "?»  Þ`]Q{“jòNo.ä˾‡0,bd% ¯pA°kó:Î.îz³h*;¾ŸÏ»kõê'©uÑÔ9V/N|Ž¢½%œbªdÏ¡‘?*=…ym+Pw!Ýd#.Œ[*›p… ½ÈÁa°ln7â^€öÂ9„íLÀйp´4#6ú}>¿|{Vuï-¯MŠ«¼ô©)mï¥Ývó·n°­EÿQõ½Ä3t6ËnáññõÙºÈÀ®Þn]¯C9Q›pë’]q¾#.ãvË´[ÒQ¦ßô‡ßõ‡…ÌšD÷Fˆ§œ-hja°»^¹B†‡VͶl؈Å#%PX°V0PPÓ®¹ø:ä nî¡zgžxDeñŠÝÚb‡Ÿ³ÇÐ>ˆyÊék¦ô>z{h}Ás1óAˆdÑä–H>Ôéf X}„Ô¾îÍžÌ#¼ð8&`ÛwÐ6pŸÑF¾ý…BBM¬#6I#6çá~­Èëž H7V%íü/Äÿxên=@çE¶¡ï‚=jÛQQEV$[jUUD:ü‹•z⤊^*eV“Ø”!ªú¿¨Ì&&r¶l|ô—‡D\Üç´X†€Öi¡š?«Xiê%x¯<íæ ®ézîÒfSo—[Ö¨ ¬’ s4üåú¿ä'÷åcyÜÕÕáP”Ðv‚SÓú0Ñ"#ò ÈðÍ‘~éº{ç´×Dª_*9äÕ¸S^t œ§(MÉg#ärö=“§ßÆò}²„)NVú¿A>?Òe ³èÎýPã/#.Yl{d+×V=µpø£µ0têÔ¹2ý0‘‡â{Qnw™vï÷ê8KÎÛ¨àzÊk0Ó2¡#%óØéüú»#.qÉTÕK£ë‡±+WU‚шù÷ÜxÉ°ý *(D¾Ý!Q4ãH“À¢¤çæT,P@X$àY´5eHr€ëþ;lýÐèllWTKw{ºZÄš¬û?‘ü£øN=‰ªg±‹\ļ3à1ê¢Il“¸ù݃ã'0´`Œ°+Ãm÷@#.ÉY†Çî½Éc÷µóy§#êú’éàãœ/ê#%B§ôëé._0þjà%Æ/ò9Q»ür#6Wúÿ=…rý™¥ˆ“âÀ¡(‰#6`1—M3-“ÊS¼ómÛÛËÄï)s ª[!÷Œ™D–TL­¡Y¬ß¨è™Žhq9"ºT"Õ#6+èAá©…¤©˜¥q„¬©æŸøÚŸàúY¡š…ûfgñ ²¤(kf:ñ£ðåØŒÅCù¬”#. çXÑa¤Å¨klmYçqÎ3Ö~73™®Ô.¦Æ%½Q²’: v-°—r· ê0#6ÄlÖ¯H`³}gÏ¡‘t¼¨Lýïä|~Gôÿ‡ìÛnîv<ÁÌ!ìÊù #.‹ÓÕwÊŸ†,ý†Ã°õ*ŒUŠ0BA_Üá÷KÒ¡‰(æI:§*•‚þM?µ™Í®ßÅÁ5›ä=½ÖN}¼NÍ\ë׳ž&‡í?z Ð¤´Y-…„¤*¨õÃ~‘#%·žöµ¦ÚSŸõ’ Qk„#%Z…z³#%åÝÈW;ÀÏ„§m`ŽðŒÝ%#%&„âUêï1ó~{Žýq×ÙúùT{,eÃMÙ"bª!œÖŸÍÌ"qùz„Nº|úw¿1ˆÔe”É»D@’ å€Ày#6#°2;×₾÷%þ÷2zTXAÄ#%2€8Æð*5@åï'»ˆn„Êl„’V#6~Ž\bHQ^ÿ½èž¿,[>G;H=iêPÈJÞ§b¨$ ¦ð¯ñ”LÒú˜.½ÕÎ`ð4ƒÑm°É(4^?b——S*èdðpéÿ7f§Mó ÜÖñ?A‰£7DË$Ë—tÆûëÌ›dÞ>o#%dˆ„*6<¾Þ<Î= Í¸_èyËa°aú ðLfë9›ßm‚ÚíŸãÆxjt3û±]]î~N.5¿U4†K.w¤Í…ÒG…QëæìøŠæ°ÞŠi}‚kCeúÉî.§ZÆ8=6t™¸Yr#6„%Ý7"—sPDÖL1ܱ þ’‡^'y·=Ÿë;â*Slb¬lˆ{¼*þR{ „\2ˆî@¯çk·¨˜ªØPîᬅâðDçG½#6@<0GzÂò£|~Hø¤þ‡zN† ˜ØûcGÿÍý]ŽbïÓcy×÷Ò…Ø!éÅ!ù‰Æ?ƒí·oÙÜÙ?ÉåTQŽÜ)ÞQñ6ÓÒáÞú_7Ûƒàò‹à#.èðüª½ÚŠpÉê7?v¿~óAÞJî„îç'bœ—û,íÜz@®‘”^í@q(M¶9T*²õ†Ã.Évm‡¶Âºˆ9ψY t Æ"ñÌ&÷Ä;:„×ì<݇Lò0âÃñ{ü×R¬þ/$œúý3Ò#6?¿>þ_Óu,š6æšsl»sÄl˩Ň0â•Õ躨ƒsŸæG#ä.ñuÁgg¹mPÿk¼§l$XóüE‘æv˜Q ?™â[òÏÞßÆIGG”HNåwÒSƒîý çâ-‚¹³\Áx„µ”9ù¯ˆs£†{©¤`öù¤J÷ªÕ:^¶‰B4žœË?ÕzfêÞÿ•§„¥¢®¿)#.!£“†a’€û1¬KÚëõÌó€ê†2_‘ã[¬{™lAnµLL#6#.µ› qÍ¡S'[o”½ÂÓGf¬(`ƒ{JÂñw–óç¦$ÛÇRuœŽ:g<®ÏðÛ] 3êød¼çŒCpêÖ“4¦8óe2övÏw]Lâ0W½k³8h[¡åÁ,¶ †”{ö}/l\_G–H½£¤á¦#6ù^'…òlŸ­æ¢å®#6—Ê Ù.rƒ‚w ë0Þáü~-¼ï>]¸ã›ÉÀswsÜ&…ÑÜÝÛe‰ìü§]È]2ý3„Ë4Ù—–£UtÏ[žmjpªž¤9-ÐÁ@AbŒ#6™£AkãÕÓlÔ•ùúøoTqŽ˜4°—gÒ3,ΘwÉ1~¯&#Ùî+ïUÜ¿îÌ×}.µŒŠðƳӦ³K7wMïTD_UŒÒr{RniÐU!Üñȸ>mòi?]“Ðúsyü®ç:áéõ#6Œõ›3Pÿ[~´ì—ù¯§¹OšÏ.pìà?h‹^UÚfÞ|ð‰ 7䆨 DN&¥6iQ-9z-¶bêwþ{£K–Ý4d@òuL:Ø€ÝrŽËç}ÖÓ¶æ8\à4›Ýœ&dOË‹x”tð£ÕŠ1ÕoêïSßþþt¾þßã}¿FZ÷|iwïòÃ\EÂ^ÃÑq¼.Îúy­µŒß³Ì#F×›šcró°Ê 1J?„yŸU`< zŒôê­ 9Ÿ=(ÇV#%Û»#%øÓY]¦˜ÆÉNIör+Í0‰Õ‡”#%)aN^/X#÷$ 2ÂOaA~eœoa#%†aÓÈÅNÍ¿GõŽ‡ðãηÁ8•†ÝóÎ$÷ÍKs{üœtJä^ôeìQú¤ê(LÌ#.!Ž~ž=.gm “iijÞ]¨¦b¸MÐ6Eî@ýŒ´‡Þv`­w‡aY<<ëà›;% ‚Ó3!.áé»IÕ35Ç3å·®N†úÇÓ (¯§ëƒù6‰c9vòD[µ4;ȘQT 4¢Æ’R.²aV&¤BœÓÕ¯Nh¬Fz *åQH¼Õj´$fU"Â67U’fRàH¢Í«‡N¶s8„ˆ¬ Fe…qWžäz’§d¾5àÖ…!;xÀÞ>ï†ç†eÕeB-!Øœïm§0M.Î"Éô¤à7ñ¡NõbÈ>}¾X3ýä…:²íäÖNÅÍ÷ü7º[Sò„aéߦ#HáòÇéwo¦¢Ì³ÙÛ´!€;Z-"¡ø‰è’zbS Á#6ª…°ÐÕ’–²A±¨ÛAp¥i²e¢TA Ð@h=BµËŒº¿ f?´5û†»›q&­}Ûrd^Wð?üßk{K5™ Ú,_Öï{¬/+Yüt1Q!%¥*‰d`ü¿­ÚŸ@R¾Ä9AžäF"ÕÝ·fÛžPàw†£|}¯ôh„ {·g =×·½¬HER!AÓË´Ößè,?»ßØ=†ËȪŠÄDy_7xÿ<íî,ö‡+ɲ­.eñÖàÈÔhX؉‚+VBG=«ÝŠÛV =¼R7–Áý.ÎùrõT'(f¡Úh»V7Ê‘¤–sW´Ð’Ž¦À&’áõQN!ëMpqZ%·d岘—nƒ¶;±'Ú%1†LhˆUQú#6l}i Ã ó"™e¿¦šWâw}wλw̸á‘ŶòÕš˜Y$6ÎÖa7Åç4E#v8œ–¹omæf¸À¯C'am²H|MÜ4!vkÿ!VBÞ†ðÙ:Æ Å]å&@Éî[ÝÈù1àô#.sžµ3/MC4XÅ#6ÅE)ë‹nØáã´'a‚Ú[–\†£Àº½ŽfÖ@ƒ¬næ¨|?¢©£_w³Ý¨Ï¦ÐàY”ÎÀlô2K™‡?*#%a8xIéç×¾=¾øs¿AÜrø€‡‡fA#6¤–±á ·GÃM§o#.F¾™Üϵš*wQ¥íè¥T—ˆ”ñ˜›`Ñö7€õF4kÈAËð#.2ìª0hXøT¬ZÔß´åb µØ=H<àXoA#.!rqíg#%[:yléTËs©ÓT#q¿`Z×Í“^!|´Bl¶Ç¸ò´©Ê=1Ž#ÖÑ8šÆέ$'`äQ.º%ì+¶&†À÷{¡èzy…‰5 °ÔmyÁ,Tí6¾$pd‡—ø(Q13(%&ŤÂBß²°Ôla¥²HrÏ#.æcÎ7³wœ&–¥éÖû½C›9Û#%!zˆlžP?V[¸·=¾Û»ÊÄsÍÑÖ™Ò„&w·áÁ"TK¯=k9çÓäôzp¼m™)ðièÖšÜæÄÙ3=êFC¾hYCS8G+}9•­ÇÏ5®ÍGÞ˜sÔÁÐi“·d%(ô#6×nÜÉBiÄhŸáIw°P¨¡%Õ,±h¨¢ ^4˜{ûw+Ñ#6Æ]Án™³ÍÊÔJ,!25.!bÌÎ’[úsHƶg6|kë‡P奕èŽÐÐɪ×e‚ìëÁéë#.dÓ’C¸ÌG)¢”AkotcC~[^²Ù#%D¹ÞìÎBI(×¼®Ò´U6U;â´øÀ¸}=‡ »Ï|#%Ö«Õ¬´”ÑÂ7:ðäUC#6ŠS¥Áµ;’ȉèáÎ\6Fj«U*F7Û`žr¹á˜t¯äXÈ‚ë@¾v…^µš­G1)ã^ï4¡N)LvàYÎò`']ÑL„ª5m²Ý3ã}´Y¼5ÞB@-º· ¦ü¦ÏFµ&¶€á®) l‚ÐÑÛµŽm,¹r,±aòãH }3V%O2‘(ö›–„Ðà£J(‹ÐâHk2fdçqªºDôòÚy"èN‰5«Û¹ˆ]Æ#.¡¬Ï7Á£0¡ :þÿç‡06î쪻BÌÙµRÉÊ$Ç‘‡cHÃáŠÂûJ$ètU&WD9æÏ‚š*Ë!çÈÜåÞb½Êõž…8q¼D¨-ê½0ÒƘ»²ô:¢äåê=¦‘™&-O醥éÏÛgÆ úîí²]+ñ¬K‡¿·M>i#.$×ûwã_ÜŸóÐÑŒ‰¸$ëÌg­ñ\W«§Ñ3nWVGM§OUªy#.ñ”ÜY7#.ï·»·=h=BÐR´”‡gÌß»´_t=V[(@²2N. c ›!áHôØ>((Q6ÿÅ7Ý*Š…=Š°eHÐÿoµéÅr.#6ë\HîÚæzyŸðCÿ?²e˜³ý“€‡BÔVKÓÝò<`PA>B¢*£!>Ÿy5©÷Tõ.¥(¶fÉ(ε‚&@!åÌh!7#%Ü#.[Ó]ì¸F/ˆ5û"•µöi^øUÍÔdwéÖn­\¶qüŠ/  ‚êÌpá<` bˆé·¤Éê5e6Û}åcj墩i,ÚAE`d;ˆá;`‚þèˆ ˆè«UÛ4ÖÖéW¼ªÙ¬”àc‹ò z9$ž»u[}’ÌnS(î—ÁG¦" uÆäMö#%²¶×/lM²`Î 3 ˆ™ €Iˆ‡BÅ…‘ÆêÜ£ÉPbî 0*z*RI‹z»·M·7©½MÍv%»´^uå»ùÞy·‹›¦;¹ÕÍË%ewh䉽#.„ºEhÒÐ% Ô¦¯>6õ|,µ•ŸÁ}lƒ@›$~×Ú#%Üà=Ó$.4¡°†eÏE‡Y $$gñ¸|o'¯Øÿ&_xr¤¹ße{ÚƒŒ²qõøç#Øéêô/Í9xóÏsLXËü‚ðDo™Ã7 æzF%€A\Gv‚íg–}¡õ¨ÄhKmBˆx#6I!yb°hÚùëí*×O–é¦Ïî§{h“Vø­¶¹[sU>þ³Ö2šf00$Y§Ó‘Ä·+?߈ó÷ã–ì#%OPÐ?ÂUHïjÍgy诨·«f#.¼ç• ™r£k¸,“‹CÇ•sŒ(lÈd×XT ‘˜„¡…#.-¡¦êTÞè`¦–—`0¹þf( äC.¸hïâÜ_ |Çí½÷z»Õ‹r¦š7ËHdaÅÂ&ï’€fA=/Q…yžwßv) ß#%ÖHˆ}0!ÂÓã!ì?çîÿ—ðûoçôŸü6*‡œ9Ã}ŸâHß $Áßég‹/ƒŠb¬5B^!Õ i >ÐŒüÝhFŠD"°¢#誨d|M×½÷ÇNV2]Q5J…:4¡x¡²¢(.QÒHMŸnš]E>¶,xC6tŒ‰h/לá†É»²Ô{hÍDhËþ8_£÷ùóÄ“õÒ+µ˜A#.¬Zb ‚¡žÿiÞ0"$œqÝ»1ñ;“£n²èÓxIx5S²ù2ûõ#.Ou‚ *}–À©9,Ê1üKûEåž­è')®Á²#% ÈB £H싶0›º=IÐøõœþÚ;B ³q@lŠi8"d3¿!û±Üx#.ARúì:ýØp´xÔ…ˆ$‘¶¯SÓÖû·¿„'ˆCµ¥ß£sƒì¡ßlQñ»aúpð:r‰S²^uÍz놳ÃéÊdT$Ö`ý²À ”Œ>·†D=‡ÕNž3%c£xIîÝøµÏʼiă=ÏI#.-3}ûüÉr¯ÏõÉÀÃÄ#%ÿ4vvu„#%ÍN‘‘vº÷n¼Bq †ˆYƒ¼ê…(›lÊSiLúÚ¥Äcí&b‰3ãOx±“»#.k#6P2C+Ž´ãLjAçXô9¢”pªq¯ïf÷³®zçíblS¡-§œÚá&+šíXRka\¹ÙrÇŒ`„X#%ˆŒ žâ’¢¡ë ò£À;Ÿx‹¦h}§œ6uò:«1[w~ÿòÑ ³?Ä7¯(iHPjÊj¨¨4£QPuQöt?_‡ïbɱù*îíw(Qa–DçéýM ™ªEbyf:öõ¯ŒìôeÕË8C8èPX‰{il[ÍI~#6!OLcìš¾––@#9OÓçVvÐøX79° #¡Ž@úA¢•V/5MP4€0#.»Bgð¸k7ŸÃ¿ß^×ο}Ò‡¯Êùñ‹(=–côôþÁ~‡'‹¢!ÈD£v^ÿŽ#6îóÊ@²²ZÐXzñÍ}fT°Þ.Rá>çæÞ™¤SÚ¶8‘ècs(Ÿ:óž‹Á¿>z œ,>cº¸½¾1Þt*U¶¼G¡ÔL c3úZo¥î«ÂÁÞµÑáè㥷;WeÓÇc¶¹åpçqF;jÌt,½ÇÙ¤mÖÙ*a\£·¶|kžµÐ/ç¦ÅоÍhŒ¯›ËDP$S ¡x7ãmš£"äŠ[lmp`¯h8x–ÁÁ}7:ÙדlíA¦ÕÃÃ|v#6õw;60ný1ljmß>øµ;Q‰šcµnÊ$[ž9µœÚŒ5)Ü‹QžaH$ì£h8ŠâæfÏ{xÅlÔÝ.£Á°_+À£ÐÑðøbsaצóëÇ#%YbdSÎdÆ#.pûŸs{¼Il0ÜûÙR&ÌêAÇ#6ñÿBHjëP‘¹A골)œHTøL3 #%!+R¨Ï¢VAH©JÙêÄcv­>8}¥hà÷·2Ö|ÊöçÛ!ˆ¿#%ù˜ì÷;vÀ+…Ã"x%õéÑ×Ûc@­¤«x@¥Ñ ºï¡Ÿ8`Ŷoê¡ùÁS’'+ä9Ùýâ6*êvòñ‘­š¹lØ6‹Ÿ×ÆÛywPõ˜¤/ÊfïWÇ Œ„¬ï¡ëµ#.W#žÃòú¾ ædôn;vêÝFl[Ú ÷†w6%‰9‘ªM–ÛpZód½™òK[?i`ë¿WúX†šAžÔ„†Ó}{–n#.˹ÏeA–Ç=ÎB:£‰ îÎhá#¯$ïR¥ˆ"Ã!ÙÙã>|÷É8Žf#.(¤SôܾöÒcC|¸á6RGdõLÅõý}Œô=H )G¯†÷&r ‚ 0Á˜ô€z•s:ñ—•wdêßË-㡧"Ö$3!~ I$ß¿Ð4!•#(í¿‹ Ó]àôö klÑü™1v.ÂŽsϺ&®]Cj¤„Jöm7†ÊöÚ´õŠšúAôöh†)(r¡ÊV‡T’u©£Ý55#hý~=Yäk©"N(Dï·Ká%OÔŽœLzJ“"À^q\øëÑ•X0¸°&ÃaÅ?Õ³h„FE5|øeëëܼó¨_ ë'_·&µîP5' ;ûè`õVSªS¼Ž– ªˆ­*·Us²43d¶º\ÙIÝ]Mœ‹’ÆÚš[]¾TŒR5 ‚²0ƒ¹`¨ÈX¬%JBŒ¡i)¹d¥ÖpìnæDp¹”f²áݳ ²XÒŠÄé½Vù—µôh´55Šf¬Ê‘E$M¯ê ï!åÄ£c#6låÑ1¥gkÏ~ÓcíÝèginÿu[ÇPüúᆤ„ ×#6Ê´—é+¥dÖm¿JâÐÂO}Žˆgº„#%¨‚#%ÆÙCÜ#6„tü¥È|lûžäðv+ªÁÂ"®Ý ÙS)D¨­ìr«– 4óI£#gm‡±°æ´Sà¨P©Í×p„ã²µma·Ø¢žÏÎu„mwñž`W¹ ¤vëC0‚Ù_·«#%b ž˜n*F¢[föUŽŽÃÛ¦š¸í<¶‰ÞNHO–Nù'ùîHÙ¥#6¬…#.¬meQ€Fˆªd°QB$J”Œ`ÈÓD©*X²R’ A¡iP‰bB‹>&í'5mÌSÀ‡aõP#.ž3¼ù­«¯Uõ_\ÊƃnëµXÚ€Iét÷ÄAÓ¹jr‰ir%§Ã^[šõpÉ!1ßй×ÑXZÚ§TÙóYüÕfǦ³¶Kò`^üBþ“™:â"€^%GPß­:D×-nóD¿\“iKÛ6ªª§£Ú!ÚE$H#%;±Ä+†¦ûãÛþ:Á‰Ù(gœëw'`v2›OA¸ºÚ¡bˆb$(cÕ¨‡Bô6H Ðçªõ&™:å„Á[ýBðn‘6šLÙY¢’&oáoÃa gZæ4ÅS$.vøü}^Gwxù?LD(:íÔl†Ú£Ø|û»^ys*½ oèo’­è¡ýþ{o´Ò)”4±"ˆ‚EƒÖŠ"Îg™ÑŒf¯:ºJåM.î›8ˆgÕô8è$€ÍI¬´­e¨Ùòˆ”7Ú!ôäþF›­9Îòué¬ ÌV°WT…vgˆ÷ÙîNž^»Þ×·t) Õc=#j7®çkÏgÔKm&ðŠßÌåܹÁ5.”SêÔÆɸŸk4 JApN:lŠ§eÏÛÆ­‡m2LÆ?¯]°ËYØ¡¶“¯Áª¤úCÝÂûªC!!hl5ç©\¬Ð™J\ ¯×¥ dHÂdê43d=BÂÁH#¢‘¸pK5Qz 5ÑZt%Î^E†A‚@–@Èœ_àæ÷e{>ñ¢ ³<Ô ‰²Æw+¸s, "õ€5#%B «Piuô+55ƒÁ‚Ú4ÍÖo.Æ#*H) ŒBˆFõ‘ˆ®¦`Ș`¡âÏY¥­Âz¢ØÃɘj8MË!KI} ‹A#.``(3ŠU€Àõ¶­Ô&¢M•·ÊêëlU”j0À%Ô¥†-Ù_›œá烞;^Q=õ\¿)ŸI#6w¬©”H¹`Íöò€¨Åïå‘|ÙF×mÐA;8ck³èÚ{Î “{44‡ ”JàÉÜ™ÕÏ€}LPCæyBM±dY¾‡«²›ábyOÄ’ýäµ’ý™ˆƒ~šÉ¹úšØà›Õ#.¼C"¶‡I<Û;úÏÕ‹{FÊinlü~}|ßáñBûÅÉ{øºF¾ dìàÉ#6çîà±!!1134ã¹c÷t³Ê'HœC…˜-&Å#6°ªhvÏWqþD€ÈAˆèªt@‹QÙÃÇD¹Ö ‚[!ä åRÉÒs'tÃ-‚T#%g£è雕*ª“ÒY“Kt¥ÅF"(«UV#6Ñ0&(÷&T¼Ç0}zšƒŸO­‡²‰Qj#Æ%…ŒN¼ƒ±€¤nˆ²Ÿ™(VMBòÑsýà ¬¬ãb¨LcC@! ƒ.¤ð¥t˜1'?]‡ˆŠ& Õã¶ØÀÀ¨‘i‹®(DŽ÷¨æçÌâŽõy¤Z¬Ý*BèÀ½ej·–Mdø¨Fí¢FtHFØÑ}ÃZ0À"'•¦?ÑâÊõŠhØÒ;ðdYC*Ï;C¿ ­P…Ct_ À#%2Nÿµª©°¢dÔÔH<ü%ÝqHMÝI\uª´’ß ßΠŒäLĦæêpÚMÒ<ëç#.­†ÚÊ8ôã%˜fL‰QÇ&јÅ\‰*…å‹01ñxaj€ ;‰”ž‹ùžª{è™<(…pÑŽ® =¬¢ÿHy!ŽwD0íµÞÇ•˜ÔAc&™´²–b‚˜£Š¤Ø.5sSIý›1ôj2¶ŠEH¢ƒ¥·ÆÏ,k¬Õ=­ÍñÚÍÍ2äÁEœ ¸¨(ʽˆ„ :¡9ˆZkµ‘©´öO<שMFØÚË!Lc`0Ò3s@ï}Y÷N#6late<˜pÖ0÷J"DzØØÓˆßyCr6±Ë#%=l+§j¹0 jÒOþ¯|×f>-=q¦ûÊß:Û¿ƒ×¢ó1Èø¹¨õ’’ ^¼P“\aa£Oö¶³r@^õéu4¨’ãº} ˜xÚc4uÆÙàâ×Xgds°•;îæ"ÆÖ,_ãMþºl„áÇtï¡“ÛKV¬7LÅ¡8ƒ 9ŒÀ„²T(5T‰H†„™ ‘¨Œp­_;KŠ¦ùeÉYJ9-Uà AˆìXÛIò–.#.áï#bì’ lÃIm£€õ˜U±­ØdáA´”Ã)jѹ ÒMF…Ý4m¦¤’j!6I&̓³¦&1>ì!áÞ¦°ãm.[¼R>Ø]™Ã]+ÙÒí.ì]¥ñ•éx·´®jñašJ¥-#.ÐÑÇ#6†ƒ%±dA‹af“ÂÈ­[&fVî£ãøIå.Û¹ð‡Ç9ÝML™Í5#›Ô’#|¼™[A‹Úæèu˜‰_kØAÆ:œQB3³eÀÔ/ð°ÎÊF ws+¡-+¬œpä.Q­‚S&h%mK‡ƒOÖ¨fö¬¾ ÒŠ‡·šñßÝä:yGÈ`ÓÂ$F…½"šˆ„ˆ»|hÙàP;#.aHê‰Å4¦”K_kà@Çip[6‰6y3÷ˆóxpBÿFýfÔLâ[6ãknk׫‰™®TãÝ¥¹„ÊÊ—ÎúNº¬Ó 2I+FÂmá‚ØÙkå>)4+.b‹$馬ú‰¨Ë¶?m…ÃS>^O¹ðã³*0üÉÍhæŸ'£~;j–0æÕº5-Nîše¶F¯Á³9HßGIÚÉr,=ä°4!{nî8nØýÐë’Ùë œ~Æí:gg¿˜Ðƒ`È-@Tùÿ/¯Þ?D/«¹ÕíاÁB °!D±¡DÐE‰Ï% #.&3í÷R’ŽÖâƒ6æ¦÷0Ü Éu*:hë$‘ÌM4h@I&…M/WX(,¹§fh#6l°#%„ÌSÎ`°£X n¦yÓzÚ¹‹©i¥RJùkïVr2L”7käÜr˜E¤¼Ö¦EÇRJðÉ·ÂwXU :½–c7ãweû‰ÚŠ(AÓ×Lo®ÜXçû¡¸×-•=®1&òXËÙL9Éž‰! ’Ù}Á¹IǾä\y$þÉW¦G†~ÃE4ªm©•ëS_ÉþßÌ G®#%ˆ£sºvYBog•?’­~ËA%*j×Ú¹âÛˆ,#6ѵ¨¶¼TjæÕ¶5­¨ÖÕÍmͶ-V6«¥¥ÖévCÙç.'Q ÷¸ÁE5bõG9;#.¶ïY4¥•(ö±Ô÷u;ƒk®ŽÛœ+¦¤ùï4šÖ¿™D’4$‚S&e3JÓ,É)I¦)5E¤ÍAúΤÂZÒ1Q4Ô¡’š"P¢´±¯~Ü¡“ZLY%™[4)“4Ì‘˜hEQC”M½ÝDFÒY)˜¤”–PÃT%¢Ò£EL¦FhÆL•¦)¬T„Ê&ƒ%!MA”¨ÌA¦ƒLÚcH` ‹4ÑÜS¹&óg¶§äe/è#6b|[|X&Aï~l­U_SBݘ×Çøf̈þ¢˜;708ëY!,”Ìm¯Òfvòús†Á©Ù9`ÄÞ ¬ü8Î#.©‹4czKÖãj\ ‚0Ž¬Î]iÙ¼ ¼Ú(’5÷Ðz—àmÚn.Ö›¨—,mDñs0³Ž¥xÂxâN;Z-_ßK¡­# ý‰}úYJÒ»0teŒ^ÎÝfw†’~âÅçãîùA{*ÂïÃñŒŽƒbm°Ç Œªd© ­…ïúûZø^Ûo³_‘bc5 £#f²V*(“i–`!Faå³><9ôí0ݽò¬X ›#6"ƒtXaÛô3³ÙŸyèNUMæçaëÔY„b’™Â†+ÏNbC 4®}û0_ê®[ç/c´y‡OÀôW¿—¼‡}#êk#6xn4ëO–åûÒ3Ï=GQá’íPœê‹+™|ÎàÉ ÒV_£ãfåÄw&}z^Ë –p{"r>Mõ£ÓG]‡eUY´#.q¨ E)¢AT‘$/rdÇ¥oKý}eÂGÝ2û¶ÛùåßXÇÆiKôôˆ£¬Ê%x4ûmÁ÷cÇ—$I*#1â8-¹¬-ߣ¼8ó#+ígÇö£‡dÎ CìÖ“÷µ« ªIm¦úõöÃ{N¹”`g"â–PR¨EΨ¸)µ›xãcB?+ç#6cguVÖˬ!çE®PÓŠ#6Ú+G0Âè'­#66[ïG8 ápI5ö,nm_&·É‚Ôè2…ò˜í¶£·ŽWÂc.[õ"^7L³§<1YCŒu-Í4î'¼Ñ¯$º41² Úîg’Œ ®„Ä©OSååšä‡½ðæ^R°öœA虚O?M"… CòqôÂdìNIÈDBª‹´ÊxŒK'²Ùª ÕµÞŽ¢gd6Eõ)×FÛÀ¹m¹™—¼2ÙIb=OiÑ·,(ŸŸÕ5X@ý\µêž{w÷7g FÊHC–ï‰:ڷשÔ'®½]Æðëì±õz¼†— Ãíúëïúv“¢B¤†xà÷Ç}IÁ\³Âw¢â‡vÏ·§Ó–æÖ_¯¥ø? 畧ЪX‰@w Üóßœž5Ìíí†á#6áí)~¿.wðzŒàDà ¢Ÿn”GkBkjl8ògâm»]š•%}; àf.äIG^fP–så­3 jÓ5'B;Cq¬ ™™#6;뀛?/æåüÛ>é5ú³0ù²Yþ–¥7Q6È£Šö0¦Ä¦a i™ªF—˜»ÔÎELš¢ƒÖ¡•ÂŒœ‘u§÷5˜Ú30ÞW>ØÙ‹šÓ©œê<Ô4̵¶Í<¼ØÍ3‘©t,ņq4hÔQSRJbã5¬D‹(E…Æð¶ÒçVL›WUޜŵ¬ æß´¥(%©ñ?”ÕKľ$–.›¥âÃ1^{¶S{ÛeóL:Ø"ža‚ *cŠ“óuo\ a\MLËhz²IÆ´lÆV#6¶Â'¿S³Œ;ÙŒï¬îç;WGÚv Òá8ƒ acgµ9t!éî^ Ñ´åd»Ìê5+6É 5#.ÂÉ,0&àbÛNJÒ:¤é°~­g–]øì`ɽ/Ü,7#6ÁŒR[Ì&*_¨€ÊÐõ¡‰êìí§ž4ÍTo#.ª?02!ðnÐ6#.ÂΩª²æÑóÄï4Á&:ÏJFìÀ9]Ѥ]Ò¬ua®y:†š0jæó2w67¶ŒLªL¹‚$ôgç}õ‹´n£ð@ußpBƒŒí…´ñÖ=,æYí?9Š@í´ÓRP±áɬ@ºZßlAsø;oˆ‚Nñ©¦™«¬•qbÐ×gÉÙã6ô¯fl-&¢<ºF!ÏOB|VvÌïDDÆÇr¯/“,¸Ú‹z"VnöÍfrg£ÑñS­ëqH·:Óº¶6´=V_è-³eßÇ®ÚƱã‚æ·mˆO¸Œè¢õ¸t“¤÷)0–ešÔj§=1åŠÎØÐà’F§1žÜWVÕ£i–7îæ)¬Rãžw¾_<ã0Ý®È^ÏP•Üd>ÃÜllg:Žûà5Úã%¬GQÄî²a…3™§¦è:Ó;1¢dÆ9Ž°„LJ¡n5´š£Íš']ºß—ÊßQt×\PÄ##.'yJX5Ñ\F™Ö¸2L‘/Fò.ZX]ÔG¡‚Œ(¸jS }5#6jåVͶã]*—ïXTäÊ•Š°­óqdßûªÚöFSB™cÕ\llÏ^sÇ9*Në¡Ü,ßž]Ì•öO,ºK+çThu¿(vÎ[‚=e´Æ™™¹CAib u†S"“q0V^£ Zk¿kO+gX›]Ž°ÎNe6¼™_y#”n˜uÁÕÎkƒ¦©Éct9)¯Y6ª9àZ€nl8\e¢­‘±¿#ƒ¿˜A#M|fS®±*CP7ð˜vB¦šEVöU;"áÖ“€X.\†[DY\('¹Ä>›;Öï8‚óghh:yYz™ä×&YNÚ‹0,¶iQ!³é¥ØXlhÍÍÌpÑÓNVŸNÚ]#. ºÑH.q¼†Å:¦ÌR‚IFÈ¡“bÓÛ4=¸ÍÃ#6Y¬ŽÛëEÎ&)Ä+æaõ—Æ0[3A”@¡®bXßQÝëí*1‚¤X‚1qI—N~.2ߩݨÛháÛá£Ô7á‰)” ¬neïpOVêÑÙRQ9B&PÆ7Ês‹iõnc­ºÍ7Ûƒu³U·6vu†blâÂçìw‡Ûsðüa½evâæfcyž5Ù9ݬe|[Èu`z§ Û™ L>8¦²‡·¹O/ ¦ÅR=:„%›)Ç’:Ó{¸ÜÖZÍQëF72Ìf2û"t[¸—LLLb|¾ZÏÔáFc™êEæðó8™—‡S7G”´ÖQ²´ƒÓgórâ’Êܨ;ç¿©Ç1™£Wœ•· i©#\Z%±pƒˆð²ÌÝUX6嵡s2úBº9‰“†H4qÆ:jn¬21É O)&PmV†Ìâë\—[™lÖfõŽ™5,yU–LbÇ0vBŒ ¢&¨©ÒªC¤‰r# šSH‹^éi!°Ó×ÆÊ»I>ívÃ8YÙªüµW›a²EZN©Øχ–+aì'gj0šŽ²ÕUÎ☙ìrÓŠÖ*L¾#6$§Ê 3vðä{Á¨·É"aNû+â(0àe#6Bu öó›Rô`h©µÀŠp PI©š,#. f˜F’èã#6ëÚ°äÚ¸c¸M­™©_{RÆ£eé\½1åf2åR;ÎZ©a®šf%‡Ã±Âb"âzÿºïÍ·9V¶ßé2#.¾¦¡#º@DE»ÎuBI‘@aàÞÔs‰¯#]Öhè P h“}”’‚•èuz1‘Uõç €tÍ®NŒzzOQ(‹¶Twqh÷Ä঴üšÄõRù` »pZPLÒ;Ì7CN]ƒ"ÌŽÍ€äü#6.s׫ZÃ’‰4ý½Ø'»õâΠшä^î‹le,Tm®t• ‘쉌SR™ 3› @±0îÃt¬y\)&Œ#.:b8ô“!ËK@õ´]NÍc4Ü‚Ó@rÖàš²e53Al2ȈbiA-’™µR‘rîšvÖºS%#6#¥ÍÜ ¶ói"2ÐÀ…°œõ­3Sd”ÂÅtvNI-"ÚS#.ó['£‘2ä`éRqf à˜d5eëRªŒ#.XsL%q®i¶L§¤n2éÍc*±<.Gâ (N¶çc²ž¥i¶m£¦ TéÂ&pL*ˆ[#%ŒXŒ*tv™‰‚mœÀåŽÈB $I”3¥/ObYÚD³»w\ñ#.»dÃ펋xå/ºï#.Ó‰\lÜêÎ#6eÊ47Uç3}Ç/™ÒÙlpNZÖ)£¢Ájx#u±¡öMXNRÎÒ¬˜³ˆÎ ÔÁ|`5Œ`pËè²3Pò†à‚f—8¬&„7PÐÖÆn°Öj–›;Ã'žCSž…™_¿&™ÓŒPiIÛ+]#%ODö®÷Â,zÜÎùèe̲¤9i 7R#6tÈðS0@e°usÇùM׉#6KÕ5B˜E ¥!UAI HX.Ëb004’ÚÏêÀóbŒ;àG±.NâˆÑÔGI–F1T*©ÒNï_»;QwW‹˜m3ŠoüòÊA8ÐTX$GaJt®Þ†Á˜`g£é®á™ N Ž¡}[aY¢¹I‡°êˆÒB5RÙÂ[#%†—l8Øqˆ+CŽûÈ¡¢#.F+2fisÄØÜ l³3Y†ÅÖ¸©Hˆu#.Íî‘„ÌI‘awmwš#6nò“aæqÁÊŒWÃ;‘ÂeU ô88JD61C#%CGfú1Ãg­Æ$˜±ÆNØÃɆµ#.fŠšåî äi ’q¥º£ Ã0é#. (à›™œ hLÉåJII4ƒdpjŠì•ËrÁ·i3fÕ̺ÇEÐÙ™9—Fm0²jJG8ÒgtÓ^Rg~V@.·uXiØl4I˜%ÝlK9Ã00¡Ü[Xn&uA#%Š0ŒIF ÄúÈ%#6¯qCÿ$R5Á@w³;ÀiSh¦²…Ê#┈1Aÿ6¾*?g€|zœ(† íW¹ *I"Hƒ#$d‚#%‚|jÇØ?´È3$䈌@q:áÔ:7H¤ýhuF¤ˆ@„&È4€¨±TC8Ì •î#%ƒ»-=Ùk<Œ÷˜º›~¸X$Ÿ*vʪL>ô ÷ó¼JÓhiÁ×/‰Ô'‰Ø³‡—7®R™­ÆM߬·YEr,;Bó®_}®P«4ó¸ëá›&A±´Æ\©s'M•.áiR¸k5†…ÜÖBh7„nÂ20+aÀ7èu%¶ eŽxn„X!ÑÕöõ#%c=¤×Àæ^çõµ’§4pu\0R ÈpBÿev#6h•"J¨”ÔËkñ¦[m&òRjµ*ÕᚈPÙŒR€² q¶˜X¡1H_§‡D‰˜#.o=#6“JAµµ‚ÍBp5㊡Œš\¡íö÷¬C$;×á8·SoWÇ4íUú‚*ˆ#%nùnR 6._¡S—WwUÙn»³.nºn¨-sd¯å¯5<¿Fîȵ¾*ä}î³ÓÁAáÖ<‰`P¡ý÷©¬ŽÙLv*Žôr†ð8«#6#%„†|ž(u/¼ˆqœz0g-ZŠ"½ (àŠ{̸°'ìò@7>™GÔ»ìo?6©2.œþ“0Vè<œŸ­²¾Ü?Ø|~ rÚ=¹—ÈFÙÙwE¹µÈM 44¨ÈÀ,ˆœ;Si#67‹ –P¼o„Æn F¿½µ°bhÐ1D)¦ ‹õªS@£¦n0—.Ö”™Ò.eÆùA2Ac¿´z¸äf$YÞЂQ#.cG÷±3þ!¬:?+xø…Ë–%êá¹A.‡¦9FòKPí?Vþ?_¶×äUi´&RkF±£Q[FÔIDL“`Í3-‚‹lXÅ|ÿZ0Pˆì´O€ïö¸ñÒ´TîRºÔ᳧zä™K¼º:ŽØk5vˆz€4DŸ+ZÂ"kÂÑ’ÄDŒFÓI0Ž#%¬D‘¨í #”E¶V-ÄÞƒ‡ âêxÝïf§PD`@Ë[΋Iß3_Ùk̹<æÑÛ ÕŠ~«Qb*H²j}šJ²a_x;wÙ$”œŽ›l[^•ÖAõ4ÑLÔdÂËp‘çbˆ7úN(ŠÒcKi"ÈF'¸„Üf5jå]*¾M½KÓoB5L­âÕÙ1‹fR–@l@ÓE`›Œ+K†³D#0ŽQÆR&lcƒ8®åB+ Ö×ËHŸyÂ˱žJEƒ†ˆ­HÐq ²@Q¶“Uú©oƒ#.ê;˜‚eK¾ü'Ÿô(ï‰éz–”#.s’ddÞí¨»‹¼è‘%Ï$¡ˆïÏë&ðÙ»#.†PÔ…HåïT¥Èõ¢®î°]Æc(i“°·Ej#.^&Ž²Ð†åZHšp0…“8‹ˆW‹‹ª.¢cc#%mÆ LN¨–L…uÈÍY^sŲñüÞaÅ#%ò=§w‘Kbm´’lc+A)aLDHÀ Æ-Ÿ°5Iq0]i>â k…@ /_¢Àmˆ!š*  I,Ëñ  ‡Ý›¼;âdç¬D©™_&,ŠúMŽ“õÊŠ6Á­ ý{ˆ8QÌ`o¨¹U¹¾NJÚ## ‘qöe]²gÞRšrE0;>Ç/¼Ú#Ú:í¦Æ>µîÅÇmcz"4ˆŠïU#.è§ 2†]õÈl0ÒjøáiiZµ}†køw 3†FC“®•zª‰¶i!KábÇgØÌ:„'5˜’bCèVmÓc{”^ZÖH8 “‡ ÉË¿+#%­Ó¾æÖZ ­øA”ËIÃ4Áùz¶^ym£Á¬ÂÉ'Gi±†êØá9E$åPš«%*‰ ÀUŒeYNÜBº1B)#6×6¦Ô9sypYµ.ݘUfylM‘¥ç—x¸‡kÈDÔëi¦lïÊ‹]ôŽ†ÁúÑ ¡C‡|ÐÁÅF–1#6hÊ7n®ÆbC#%ktE.J Ô˜DbTJ¨š Q$Ø£J#.L„@Àc¤œ#%-P$PRÄ[¼ t`luqlg¨LÍ #6Ð?Æ@  ®åB<5í Ÿ¨;+Æ>ER+ýÜÉŸz¹M8¤Qb{(=Gø+t Ãï ~L>±ÿWTŸª/‚¢ÒkºÓÏ ó<1G¦A¢|A]fsÕ10#!ëGšú™"‰‚d„’FHÅ"½†«bƨÚɶ¬ZÚM«Š„ "BCÒ÷©š5 Ï?=x•T\½KŸJåÈûŸ ó[ʾ§ôÀikE/³Šâk|t¶u+W…þ n.¬­…¨ê¬ÞÔrØr­$®E#.“{:iÃYÞ%lšeäʵS0:2¥KŠYk8ißjÓm&ìÙ&èd­ñv5-zÔbŠºSc³AÎ##6pšHÒ.™KÄӃƶð¤¶Ê>-ÌÞI†SŒ1d¼­ÔèËÍ<»SâKÛ¦3‡Û’$•Šiȉ3̸jMÙsy†ô@#DmãŽü¼Õ‹Á(ÑŒíju¾N&H†mŠr¦=fÎþW˜ÑÇàËNÔë‡5ÀÈå‡Ë­µÝÀÆi>ŠSæ)1jnÀI™Ž‘®$ÌÜC#:¨y>ÖÞ*¨i½ðyXÛz›Mp“\ÎJùš}e)œãï3Ã&=¾¢¸É&B°‚âðÇ"íž–7•5¬´ÝÎ+c¤ØàdÌrpQ© »M=íW0ƒ arr1Æ@Æõ«t¥XE€D‹LXÄ%‚ѵeÌôö²ÒBÌ´¼›Ë•ôÖkUã\§›©­ê^y^¦¶¼¼âƺÜÛiÖíª ,ŠÜÔsK¡B4ªä!_ÁšhR‡M¢†:—«#ÿRDõìÍ”¤Dkm^| œ•ÝÅUÚì›"hƒI°’1Ž<¥jÆY*dÂK èíƒ0š]#6»jí&°n•ÝuÝÅ&ñ\µëµÉ–§›®ó*òlLi[©­Ãc]¦£hÒT¼e?äÐÉH‘Ã…(¦Ñ³R¤me-¦U$…”™f±¶5¦¤S5ÔµÒ´²–™5¥™SUFŸ6¾^xMEª *f‹VЕlÒ„T„7–öy™¼túccQ”Õ©£â™`IPÀ€¡Q6››@‚—bQ‘Q‘P´X!º+çÚD='qí°z³ÄõŒ.‡kÓWéaKÞ9S@Ð×î6ýy‡†´Oƒ;‘Øngq  ¾ Oz³,§E™ÀËÂqhöëÏKS-Àº#%DŒFßÝOXÅ¥*jXÃɪÓm'ÓO#»;ÎLÀMÉÞ¦l1JœSí "[ÕKŒR¥U(ÑJ01!¤Uý¨¦ÐŠa•#%¨Çj#%¨)"ìØn¢¶Í¸—eµsÆòèéf´Í:ð²ÿfÂs©÷ pÝ#%H…5¦µ.Gf` #6 ò®µ2™ñÞ‰ eRD£T5ïÓ×ûûyk#.Žæñ#.ãÀÇ=AõÕê4\¸Twíé©Øm?2s¦O^ßn’õU „\ˆ«#%rãÑâuJÿo‘¢Æéˆ%òÅ€´ AS¶(†L!¯$yB—`w?6Èl„¨íx3ÝŸb…ÍÁ‡L8o\šårEœÎD¹S¤,`&Q¶7ühÄ´t{Î+Áoœn/1~»bµxÙ#%à.jßÞ¡ö ~Ɉ0Tˆ„ªþ—¯æƹ¾óíèlodð8YGçÙ|fQ¯ãûô0*mùÊ‚¨<„ h%µj6¢ùýÕ²Eâì(–’eQ‰’MÍmr,¡–‰¬“Þûµk“M¥c)m&Ê6-")¦Y,¦JUÅ,µ”gå]aM«)˜lÚ1&ÑFÚ¦µMÓŠ+"µ+ºéµ }í®Öí^Ý»*b(2#6em¥­)­IkjhÆ¥Wµó¹Ư~í’lŠ-cd¶¶ÙH›e­n]ihÒeRMKmçáM‰´Úl¡3#6š°ÛilÚMìê­KlcãnŠÍ–ó«¯;’R­2hk–êÍRW‚ë5x®Ø”ĪÂFÛÂk±ŠË[L7ô®ßõLUšq¼ó¾T•ÔÇŽîRÈ´­,£›^›?/Ëá>Ïw>Bmôs'`˜ÆèOeÅ3$˜SF¯Xqå×⢵žåE÷Äô^éè†øì\$1gÁÚaž>Ž®ìk£g]7bÙ 3meÌz4º:¶š.L@ݤ¡áÈ"¥+´Ä»/šö7ñ_‡K3ü½©=Úßn9=½™C­#6?q°Å‘@P \cha!¼†„ )Ìæ]28ÐƘ‘›à¡ª ƒ(ÁW_@pÄ$•ûŽ -΄¸>õÒlÕsuæ°ÙåÈ)P;+ôø ž:ó‚lŽPù À‚.3ôу¿ŽI÷¾×‰ÅLFz%;8ã»m§f¸ñ¼õЫ´Ô¬ovÄÅ.šy‡Ëg ØPÝM±"Ê~¤}þ…b\åö2eÏàØ¥WCó|såÇéл\Lu#6“8TóT>µK‘ƒîªtJZ~ÙVêøPŸvÙÂíͳ ÏHdÖ°éè#ÅÄØÚ =õ øs«~O†Øõl£qGFù¬Öû#6¤Èƺj–µ¤7Ò6Wi0½«#._Èé}/[onÓ€‹ @òî#%#%‹lj¨Ê²N"Q@R+¥rÔ'8#6Èo(Õàž ‚"2! ÖDëê¥Ñxšíb¹Õu^¬U˜°‰=³¾_vóÒ…‘Xdé[ž&ya–&\T•CA¸œ!Š$Œ*¨c#.ª “SLÖ`O¼I.!&*x³VÏz§@â]7ù=ý«¨á×èv#.çWµ±ç]{|)LcÜšÃPó €fÛÊÖs²šD\OúÙÀ«–‚Îx…#6((S)øbî#úÛËR’dA] %Ù@ÿgìºùaZÞåe±F6ÐÊÊH‘F–Œæª&cD2LŒ#l#6Ðh{ÄC5U.mÈÁ¶“ ÄH)fáu'6ÑÆ¡‰†±ÅXƒVFA4^Z®¨ÆÎj v–©g6&  b S´·»RÅF[¢ÃK#6ª‘@Q®—I–­ŠL*cð¨Râ‘¿J“T#.t#%6:^ôtqs•èÕ(ñQ €jÔÎQ§×hXÔz´A;Pƒl|߶¨4"Ñ JÔL©ª‰‹hJ¸XÌîÁò€›`‘8ŤMýàž5çñæk±—°÷§ŒÁÜæ" k;CXx†j/zø/#£Pì|…4ÉL`ZhÚ-AXAKëí­ÚÛ­[EìÔ×9b$>#%ý0¸ Ìèª=V.ná·kmÿ>sê ý¹gźÆS®i{HÔ·t0Jcˆ*ßÁ$çL¼•·ŸZ«ùß$!›Ã¾$ë”ÚwËIƒ;àtn”l øÇ-i¥!I¡#.njßRY²’VTÊÁ[õðð™l…c0¶õ«ìXlA‘4„(Fë¹ËÈ/n•÷Odçèʃô½teú‹&YùA16ºa2‚e8 ÔÁõQv!h+åËbêÅó¿r@Ã…/¥)Æ®)iQÒÆâO±¹9&íBø>ÿ|­€É­p©*ÚYKmj”i!´ƒ:I$š””žm­DVCCpš€P±Èc&P1èó€´âÚs½s¯gÙ™² .Û!›H #6áPªR3ÂxQȵßxÇ™Š¥ƒcQ¢Á:÷Ts‹ hiß5¶JÆKF¤„ÉÃ'3ÔGÃœyÍãsKMûé:Ÿ]û`‚ª‡§ ÃÂ2‰UKÕ•JâòÌ«ŒÏZ§N7~R±î(: @"¡ÌȡⶶQfíf´Ä‘ÒiDÓ´ThAŒ´~Œù~ÿNè>‡—èëTšPå›úÇQpº¢ˆóG‚Çšpó ¥€CaFE<Q#%,ˆ2ªœä°®Gíâ&±û¼á9Ťð;õ1A¾¼uŒÈŒhœ)¹¢`Ûk­„NÑD’ =ó§#.ùüq ¹ Ž[tcv¦¢â#.iÉÆLjÆD.Ã1ì˜ÆVí¡¶&q±"J5†Òë`̆/¸:ž”¯l’F#6¾”R¯OQz‹#%ñ=;NÝÖo+fy*wЙ¹çF|û Å"TX¥BSM4…DB —¥×*¯rïšJZÀeE–¤É@òrÎf§„PÜ\/èÆQø#%»¶’(tWx.ǨÚP QÕ‚¤BÉUN#("»ðX¨2#%›LâF›M`”'°fT(#.à2–pâ§.=ZpË×v3œ{×raY &&´Ú²4î¤G] :\„clç¹¾,u/Ëß xµî¹anGÇå¬$46×PŠÁDùkŠ‰’It¼îÂ2žv¹ÍÄÀŽ+­¹,Òçžu ñŒú UGLc0õâu{2=AÑ+½ëÜ('_¹HCX=˜DàmÆq–zEn€ÆÅ$ONÃ-Ž’¥¯Ë¡e¤šÈ#6¤ÍSY}Ÿ—ƒ“¹‚YîêúÑ#6I£åíª† ¸%Ý£HÐÍ?]‰$E­/]jôåå˼n¤ÛìnÈ™”HNõæ½Z½jé%»mj©RC¤Š@…àmQcš°^:wn) «—1KÙ)yš#6†­QŠÒ€4šlß·ºw7¥´D9Š;¢¾âênïÕ¢ìÑꙧëÛÄtN(Àºü5šîIåÖïãrBÌ©[æq‚_S¾®¦Rg¿s%_Æ—¥àM~%Db+)'æhwJM¬0…«ö5¯YFqtªÁÏé‚ "懲‚:Ê­•½Õ4Ñ´L¢‹Z®Q•M4šjW]6èrbK$ج[FßVäbÄVkãJ*¯KÒõ-kÆ嬳oßýþñ¶Éki¶[V½*ÝrttÊ7ĸeÀ ®h 'kåŠг)ôãK —]¬Îe´"„¶JJˆPÉB7&®r°„2ý(-„Øo)’€<(˜ û7 Îu¡¬²h%,3al!™â ¦±hv>¹3Ù]´l4‚„}»ÒX(¸ÐÞì½qOt”T5(¿åiÀ’¤(‰º#8+!iH@ÛaSòÕ*ŒµVzPT*éd“W˜fTp9°ÌPð5 ëÖàtïôQìꪅ¨…E#5ÝvÆÓ"£I´Ul­#%&°ÝíÝ+Èt00p‘²Fù`Åì&á—,Ü}C…pÀ×t,Våp¨CšA2 ¬ ÛÑo¢|¸¾ÀÞï'´Pg=b,‹q¤  B€=cik=A’~x#6gLüqöÿË€.×HšÂà\‹h]IÕíø1…Œ‘#%¨%扨&?¿dÒI¡ÏÊçÕ~¶ÔØ;Îáâ¨Ë#.ÃÀa a‘Qúùh€ŸFÍpA24‘» Mšjÿ-ŸF?=+áÿ‡ûRâl~C~˜œƒ$4Kç‚^ˆn«&߃Byï‹(íê`=4ñ…x(«C’~¿´ŽA@TTвÏa81#6êå{œ êÒB|'¯—¯ï`Ãæy~6×Üß=a§,»rÞtï£ÔŸHÄT̉I9¨™¦¤¯V–¾T­ª‹SRÙÍTþ ËÁ˜I¦ƒúËúPцjˆ,TU#6©3û®ÜSE,#6@¼•I#6e,%Žì†€Ze¡Cð@ÃQ>9yñþ_›¼ï€Õ-’­6#ÆD“ca]‚ªñË<>ÙZcm¦É\ïg:F0¶ 0#BÌ £&D®¤ÍeµÄ±¡Gf–4'ÔF4ÆÒ„qI‰Žlb-ªÍå†LQ”X(‰‹J¶™*™Ef°‹-œH#.Ô’™a4J@fµ@¤ ±I2ÈPµ›„´Ù’œbƒb$]’ÌÐLïR`MS$’•‹ µZLibm-äB1ŒŒŒç+–=B`HVZM¨“F`L%¥ª¤mV>Lä±¼xa¶EXVÆ¢ÄÞª²¬ ÕÖAÉF¶áÃ4gJ’Z¢‹,j¨j¥0¤…'6Ñ´®è±\·6Årܾ#.ãc^»½.4<ºí¾-“¹1Šç4\3•¨lêApÌjÓ´KŒ&D`:3±ók0Ó,$i¾K†µbc‡,P¸yA®5&Ψ hÕQ.šHº5@€ák[R²°ðÕ5O<­#.ŽC:Q¨€6%Üe{îË]ƒúÓN×Ò!£ Ñ uP2Ëñ»h|€úim²O:“4MiãÁÖÆïØøÈxÕ,#>¸Òc!I¬ÆñÛmwºòeºÍ7YºÐ «áùqüô”Â1Ó ÍÍÓ+p8ñö¼þ#.áߣ .H(ô MTØØ?9ø Ñ 0€À«¢¯`1 «þ8÷‘A%Q#FååljT²j,ªê£TI’ñn’ª0±¬QrÕ]JƬQ¶ÜÝm’ÓDbd”@b -eAÔn*¬Z•$A$TɸúÓøC )È°íDÔ@QHXÄHE¤Ǽð?ÙÔX#.Gꂤ@ƒÆYÁáõ×g¿Â¬{S(±ƒk—Ùæf¹!¡çò«W²®]¦Ûnºë[ÎerZOºÂ¡.TP¤IËúìÀ&#ƒŒé¹‰ÍuÕñVã1 Ng°þ["ALàlBƒêŽPoÕTBD‘WáU‚š¼ZƒPø¯4²mdÛÎÝJT²«šæ·¯¥Vò̈¢Ù+Xl…TzšÅŠê»ª-zjö»×‘/]nË\Õ|š×šZƯ7uY‰…$¶¤Õ©3J’ö÷í¶ØšA¦@¨¢G¶2<㥩Xý|º!ÔÑò‘kk™E{”\±È5¨p¯Ê‘•E.I#%}3@¡„ ‘„Ë Á±“,€e rIcÇQ4×´Õ0NK2#.É#%½ Žçì”è¤0#q ÒòœMŽ›ÇnXq[‘l'µ}Ò@aš%Ç¿¯3Ëš‡74Â&iGÊ<Ø!DW‚bUTŠUðË›Â[åHŒ=TvU Äh¸¨Z7aq“P׈ñ0»¹aÌ°oËŽuÍ>¨½ ¥ECOˆbÈ€(¿ˆ|³”Mî®d=` T6qÓr.À;Q$!îa^ Ò¥#.-T””iKJTÕcj´×¼®ØÓUšk)êWQ´ŒE%D/å‰Ðñ9™‘çÙê°Ä@º5]°;c{nÑ÷µJ*ÎdBdñaöü’6µñ³'¤.ÿ¤ˆý¾v™íFqp£FC²êNº–3ìBKŸQé£4Ó]®“#6¤Ó‹‡ý#.ËÌg8¨¼±†bCÖ°¡ :ëŒÃPó¨êÎÉ&&42i•´PËZÇ0Û#%G{ª" M18=ɉÝGÜ`‡+hƒ}ñ¡È*M bð]þáñOC×ÝXd’I"BMçQýQ¹“‘ì<ÏÖônå¦F^Ϻú¹!}zæ±Ë`™ÉûdšWß#"‡ %54I7L0µš…°3'øþ|ˆ@å¹ÉY¶çA#6?KämɃ:Ž’®MœÓûlp(¡©ÐÌ“Ò¸×V¹ "ÄëˆÔ§VlÃ@,×j°nÅF•@ˆ$+û™RMŠ6SHDÀ˜B0 D¢¥Ø#P³N5X©Õ4O4D1öÍ—á=ü'§1ÀÁ5š5Ò¤”{Û:ðeQÃýi`êñ×K”ã;4Ï×ú´1$ÐÑеÊc£çF^Ó#Ž¼ô=¥ØΤú¡©“§A>iéTSíMZʸk2Pù|Tà€‘¨ðÛ‡’„‰Â5ˆ¶PajJL–i˜¶¦¶–¤ØÖŒŒe5ù¥tA&‰•2ÒÏØjܶ¦e©²-,Í`•³LKlÛl­6³Lµ™m–$µ‹J"©µ3f«4M5M±UQli$’1H³$#.GäiGåL"±£æÙ8î¸l–Ɖš¸Èéáü)D M´VµÔåV¢ÚÅ®¦µ®kvo^aQƒoѴצÕû»ËA'"vC¿¯†€œ#%#%ÛFÈD*TK[›R]Kí´·µUøˆm~B ²#ùKÐ=Q_fÚÈH†EQ ÆGúZ#>Õ†–aõ­óØø„á¼ådzApQÙ¸»h¥âB9¨!áOGŠk§!€' %JŠ¾ØÞ!¡ìNHlá`G´>ÒB ‰zAm¨#%û¢Ü‚%íKtŠD©ìByìçx‹Æqä;ÏÓ×8ÏW·ÑëU8;€¡¤g‘ê&L‘x‹Ñ;ˆQÄ7V«ZÖ‹œKš“è6˜x#6ÅéØ¡›¼ƒ¸€p[1v›*®š@âƒ7̨‡·Ý£Bò8#. Ò\Ð;Ÿ¤:háŸÜz°žp!¬a#.DV„††‰#„mbL¿ê¯(Ó4tì!#6°I£±…Oú;N¦Ï”Rbå.¡÷Ã-+?£VF0¥VªêãìŠ~}мáö™mFÂiîAÁÆQ:ïÄ•ƒ#%>°Ñ#&’!ƒ¦-ŒcöðtL”‚‰!/Ù¯9ãvþWà¼è¥æÔö€ršÍù[ë 9+ÁS:~“r˜âúýt&ø-tœõw–¼¤¦åÆåÒñL ,˜SÝðð4Ç]«Pø¦äº‘C#6(,H„QX€ŒPí‹‚ÇéÓ9À“óx§諒#%2O‡ùæ&ѬH›€ø8Õ–Y!D1ž4P)#.h¤4–ÉÓL*vƒ#6HÛLMûþ¯ŸéIJB#.™žüX11¾"lN9anTG§d#6숒6«Æ%Œ­  `–6‰ØÄ´wc&µi︷l¼C#.@6dÏZ«Hfh…ãëU)%E`Ò‰„c JO´'ñTŠ¨â*cm¬hæF‰&(}q#%çDBŸ ;s­R; SÎTyzg?~—~¼® ­QÐu€}Þ&`†]|Ñ÷N^@ÃÕUBÅf€ÔUЪ`EZó}MI¢#ðGðGù$=è‘ŽÞ;}%¡&Zi‚Á]ä4¸¸fÇfÙ«EC–n¢ÉBvP§`¾Cqh—„Š\5&+&ÉWsLŠjFà|Ûùfwâ{àrTPœÙ#6`R#.Õ!æÊ%•‰r)(#6a<,<Ï[Þ‰Kž:MåÊd¤.óÏ!Y;0•UQT»¸Y“™¡õñ²‹"‡½®$D0øBR0Š!ÔÜD½.Øbo’ìÀ#Š]œÌš T`Áѱ†É"žˆ.)¢†èÉd­rf5Âó"^¬ ž¿îi‰hˆžòœŠÝÝ%|Á#6‡ÓeOuB¥´àÈ©PÚW.T²¹[#.½i?†îÍL#%Ez¤#6©36¶~ôâüÞ*Ž”(›Âý4Ƕ¿Í»CVnÙ=è¾»VâHfmÚ¨·aYeÖ” je 5VWE·[Ñ$F¥”¤ŽÂB°ƒNÄy3ó, /¼ŒXŸ¼™½p †8¬§gdpŒ¨:©´>j"ìO=H£EëeäÎh ïË‹“§ÊgؤHÞ’–%?^uÝF§·ÙéV§mTS±ÄºÕ+nj„ÜBðôÕ#6´×9Íâ„BröÓ,à¾81rÂsÚU:âæìbúékÿgÖË:¼µÜ‹|ÖƲ:Š#6K%$—,è`˜#%*¨#%A DP€ÐÈŠÒ¥h€#ͨ¨I n1€l+p<;ŠTÈ)í ˜©Ù¿Ó:þ°UyónêïæÔe³#6ÔeëÇ·VÜÞQöº1ÈßÌÕ×ë2Q#%dd!C‹ÇBŽbuðE!¤G³v#6Ð($«U‰`ѽ­„ÀsƒqKòƒÙï Ñ£šÄv\5Ê ÎÐHÒž%A#%‚‰Î|É:LòOB§¯ÆSÌ‚N¦#64 / LdM´¼íÍr¼ó¦ëÏ5wŽÚëm¦ÖJ­I¶ÒËÇ’›BHTˆƒ*‰F2ÀD#6 üÿ_¸÷J(-ƒ!þÚnêÖwÁrPl ´ W1¢Šª`Gñúnî¿«Âb£ Œb´Fϸ•­:Ä6Ö4kR&'Ó&{‹_¿´)·w¶õÚV7t\-2á˜Ö5bB<* ˆ\K‰lH2Ym@¡&©€ª"Ó-PÒËf{½•nçˆØé¦{ÚG.®ÊÅz¢ç±¦&#.œ¼zPšÕ1`W¨¬PÙ²‡2¸ÛO!-Ý0éà›È”fÙF¢D$ #fKÀ0‡#.`—ömZhmmèØ•áͳŒX"bͲ9Pí( ¼X†m–ÌG0Õ.à£MË쀿˜â§iÅLüI!1²Éb;EP DüÀSqS¿•c²vwñÄä'Ñ祥ÎUñ<þÞzªßòNu ؈›'úû¤ÓIŒáÂfÊbWGq'NÄöP”!×#%ÄI¾åmøÛ^ef’Êd­‰–’ÒjØÕ)­}ʾÖÚL®»U?OÇ—ŒkÆÛ•Êæ°µ0}½ÃÞ^“xÇëaÎ6<îXJ.mèÚ¦Òv¨"«Om¬Õ¨}Pr)N=\w†žü²Ëˆ«Ÿ(ײ|J+±±òT-ªä`Uí èvÙïIðƒ{¨óÎ!WžâÛoUx$˜§áUýÇêYÐYy¾áa©<–·ØÍn6˜I6=Î q.ê`˜Â÷ývÇ]tú¦øo¹ƒ +œM`sZõQ4$n@âtÂpÅ&/m…ÇãîHF1מwë߸Æ,bÅè¬ÞBðì&Ù3‘°kŒÕ&˜†72^A#% •·4ß¹çLÌÑL´K3Jj í>E/Œ»ÛêÛçÌÚA!~ï,v7ÞÛ¯é#sµzø%ªì2t‹·‘ƶ€BʵŽ -úð*¨ð ¹FÇò,¬ðç" sž^ÓÅC^´GÌñUGÝ‚!p6m=ßmÃÝŒ#6NÓ0¨^b!”d%]±‚-Ê.ÛJZÊ0O ¾^!‰¡ÖÂ0ןbí‹-s¦µy䃉Õe‹´SZ·°òüX›K¾fsMÖï%ç8Tb»üè\²?}{Þ>%ËÂça‹8ð‰øqgêd;1Cð™ )æÁ… €ªT'çd%íBnpŸêá·>Ž¡˜¼»f>¥ó‰èÄyKp#ÃææG³´ÕsmGyç…cQ®»·¦Ûš%¶Ì\U#.¡$‰HH0‘Q·™KAŠCo·UïУç»Rˆƒ*·µsà$.?çû‹õà¶Kª bÓ\µ…‚ň„aÇY2J2ÄTX’ (·VyÛ¹ÖîuÞªZÛ¦Û#.1A¼A(ˆ‰ð ¬ ^3@¤dâÑnÀÕÁ£ò—ðt£àyžˆ“Åù¿r=‚÷‹·EI&þŸö01ü›„$Õ¥³º[›Ðö"û·'Ã4Š|·låËMÓGÎòçQÝOg”C_˜ù´4èÓwA0Cf±eÂEÃpÑIå¨GGè ö’à$ëªU˜èt§ÝÅÈòZ­ˆ¿0óhäk>1"°Õ—,”W%ëFþä;ùq56z{þÎ@ @qôÙ(”yCScpô_{J!0£:tª4‘“™QZ$†¸ê×\×v庺ͩ¦¬¦ÛNݵu&ÄÚÛ4¶«ªØÑ\¦^.^]ÚVòµ¾l²„@ Å#%C@US_B„Ä«ËÚ”­5ê)ALjºr·S9¬¹† 5öTX“lzï€ÀÊM‡†u>#.3ïk¤ÁÖøûí#ÂÈÉ j÷â ¿«G„í#. Ã0¾Ãn”º·JYUiKí€:ÍËažÛp¶¦þZ2nÇË׬-å®Wߢæ #%ß`+Âގɬí'm'­·õ#.|¹_úuØÑTF#6Ì5å*oµµX~ÍóÂ\èÄgi[á4Gëk®“]ä9*éitQ™0#6ñ'êwÉúgúÿ§îoÛ`§ñ!(RÄæY} _’bû.“»áÁ5Å(,D‡ÙéPºRð¹ßSX§%DAÀµ¶&Œ‚¤?3Y{ÀZ$*Áöm™˜k_ªèzÔ.¹#mäÐl¨AAì[œv,€aÈ$ºvÀ¥‚+ã'C‡-®H4(an~#.ÐÅ¡´ÁëX> 7¼Pˆ“Å£Ÿ›ã“Fs¼ðE’Ó£pè&¦‘—K¨€ü~iÿKn<£ª{6±€g™TSE_çõð¾ÌÏžRI'EÔ,Ìï‰#.™–ümQºC^[ò†#6Èì<¶’èÝPi¥ÀûqL…ñ =Lo³#%{BhÙë Ò¬Ü¿¶lÁs-†…¯¢jgÎ0‰‡€xAËÓ¥¶ßgLeXd¬b‘…û`Y)0(ÏQ3‡I!…áô®ÔùašÃŒý¡ø̽™:ТIÅÔeÁÙ)ýÕ‚Ô<=±®’áÐÁá†c),·[I _òÀ3r^”B8iý5³V-êWBÆCGµ÷cHgM‰ardæ7ÝÍO1U;žæf,Ý1!„Èk q.‚ìaì£P0ëO¯võѤÈg õá§NJ±ÐèO5Ĩw¿€y ‡ˆr²þÊçõm|µåê#%ĨƒÂ#%p+ÓUC'‘ÕG Ìñä¦j&¨ª™ßË– ¡!ÞÀ[©#%¦B‡½‘OE«¨¶Ö+Q´Z5mdÆ©5£Y,mb¶ @¢²*TEMŒ2…Èì5W‡Ùn—¹\ê4—"Ô–* AR‡æÀá¹Uz,.ã`!i ÅòìÚp:6ßvýøg7nYÁÞúËÝ;«Üd(]Š)5«=:™šC÷«‚Œ7ã„-\õûn}ªcâÀuÓWCÈ2ùmFm’ CEli î°2d–S ~Õê(‡åíOyÖ!¤ØwF¿?´"„Œ5jùíÌ<ÁCi²”R‘ÚPl.@ä#6ê%ºéçÓ5„ÊU¨ü=¹Ñ®%O™×?#6\¢p`v㋜NJɆ@;$™Ðs]‹_2B‘ªPôÐöVâ¢ßÌ0`Cm¶¬×7¶Ú9FD‡·7|Y´&©ªVÍ,[þ}¯]tÁ(L:’"W. {Ž§¶@,ϬGüÛo­ÖÍ ½”(TÐJÀÕs’ª¤ ó £äI/#6½y³ªîfx²&qK¨*.‘qß<¡ˆ¥¥LÒ®%–Å#6eq}Kw4(#ÔæH€ Ÿò*EZ#66°Ö‰Ÿ-5¸éW¾`[É@DêƒFq#.በ†ÌªMZ¡Pwgåõ{ö²Ÿ7>Gcúìcšò0Ä5™µÕÔâ»×võo1“kpÄ&Á|ÙôO«Y…ñ–¦ãQè‡î>Ž#.zÞ“®ùŇ'èkj—©a¨‰„²ÐÈTʥȔläÏ$Í íB…mÊ=·e×àšY bø¿]ع`±#%˜ ª£‹.êLãžÅÓ?ɧtÐnòu#%žNÐê„Ø€L8»1²üÁð¢zÏpÝ#.ž½…Ôêôn•‘êÌÇʪKq·t/Bª+5Ö˜kYfŒ…2ÉUBÆÐÀù¾Cˆ®YIô ÙMIÀǵÜ„$“Á¨˜Ø:¤Â*š›ËuÖηL«w]¥#jff±PÑh×]uôÕ<®óõ§½æèQfðÀÆÀnBhT¬ci0xÈ`hpTZÔJÄ0`Ä28Ü«hãÕJ!ÁÑ­S£‘ ÉLkLD²üaÐ6™Þ(Ú߃pHìÃWÖ™û%°Dûo!H¤HI¬j¬¦ºUÍôMÌ‹6J´¥\é23Í×Y2¤ …r»ˆàd­¨Å ¢‹Š#6&†Û¤ 3PE Ðî÷ZH ¨ÌÝZ@Œë ²Ä0ÂíV›52‘ ¥l¥f†Sµ$‘e6›,Û3$ÈÛe-/]Û˵riÝË›rAfë®[sNݽåÍy¼ï"h¡RÔ3–ùýw³Ù› šf¡å輸÷íï¼öÕæ"¢FJ°ë¦2†–šÙˆ¬ˆËAÁ\µh@Ò4EÙcÄôõf1ºÔ6î“#.j*Ócq¡¨ÑÈ0À×ÙUkH°[yÐ÷´IòãÁ¤óßQÆM¦Òp&äbÓ\3 PÍÖ†úÀ4Õ½1ΙóEåêÞnÕŠ ­zÚéEF¾ÊËIµð[¤ö#6ûµ>ÖùñkÑ6wć– äÁí0Ϻ¼è¨…Ì]hʈ°Ÿ,Ó`ûO]Œ‰ÿ3]¸™·7µLÌf7?,lc]Ì“MBbAŒ1H¬µ4Ýi†d8w&ßNÓ)Ä”v»Æ#.Áàu?²æñçãµì! 5éá1°<¦ˆt2b²tÙðVþ²ðæ8ÀU;¬"Ç‘¶C’}åtÈŽÏë“|w½µ^]™3aÌ8fùã—=ù6´ì§Í„%µ ~¹åšÑ¶»zÊW\=ÙXÛÔZh¸Ïa†°Ó(±Æ™må÷<H°UýÒvЬbE“È#6NÁÛ±=ôL~+"‡õ†È„eÛ)·‚È~ÏðV<0T‡&*ž“2ÊuJÚ©X¡à†÷BxQGš`…×Øhœ Ÿ-“T–­ŠÑªKo•/©ZºˆB2$"cü„\¯IÛ\â£rh¶·’{:²Ulm¨Ú¹Uˆ#Ÿ”U#%Ÿiy?Ò3vµÇ‡$eù»#%ˆb Zü¬ßàTy„/o\½Õ.@Úº[%´×]§·-lfmBÑl@Eá1Á¢#DBùRÈ8$j©À\0z¦Fü¡€¸ á[oZµ¾‚[[fIŒl•m\ÓX¾>Ù*¼î«ˆžË¼UÚDFÒæ»É×>µž¹éw“W–Ù’€“€œãKÁhã*7j*”™A#6´¶³V¥(1Ä*ÛAÍXU¬!R#. aS#6$D•Q#6#6ŠÆ,ÊŽXI˜…vU‡ï€DdЄÂ%¢¤€äÄã0õ‡ázâhÌ RƒLcAA‡¬–T#.9?³¿Ïïç*®·€(øhyÒ]aöàŸsÖÐa`ªsêpÄ%X¬gÕ™3nš#.Ç#.³ÈÂêH9F1˜ÖKQ·nžíùîÑ™ÛÌ mµ¶¾©kU­~[Â` #.Ä;@¸ˆâ@HŠnüÝ¡ã¦Qð!¼*‰ï'æ£[£Cõmþè¡/C ;¡ø&©“òƽq‡j¯ù#%AD^G9ŸÐÀÓz*‘J#.Š¬¤,XcÍ#6ŽÇ+Ìf¡„zœ#%fθåC8>yóvoÖ¢ŽJ¹ÛïFØØé”8ꦈbCDÐ#%ÅEœ7áÃGÐ*‰¨á%ÎÞÇ ¢tºÄ÷Å4Èn#6½¡1*ÃM63âqMí€!œý!ȵ¥ð¨W¬|TaøµX#»# hLCZ¢«xbi(6³‚Š±tŠ\°èYl…ˆEX#%$™—p‰4b9&K“`È°y~5D¼_¼ #%¡ôˆ^3Äê;HÓ× XïYU[ï"zGEM“pùC›Ý‘¶Íêц|J§NqÂIß.k6#.éï?XC߶ óð&‚©UMÛWJ(Õ]Ûeº»±š¿ºÄB¬€%Ÿò\;é(B¢ÔÈîLgÇõÙüÞ­ôÛWÎôNÝWu\v¶Âegd!Q‹ò –Bt?g> YA h7vgyÝ\º2嫆”uÝâòœÜËÍÅfË"i$l&Ê–£ÆÛ´Û&‹S60xÜMæÜ®UÍÜw^vo.Üu×l£ •ÝÛ¤W/ñäª9¦Ëy<Ëurîk2Ƈnój•hÈó¶Úæå®›VKhÔ¥ŠÎ·)³,›'ŠÝÝݧ5wft×$RÑœáÊ»eγQhÑÊÔX¥"µDh‚´m› ¹¸#6XTbzà„vA؉CH#%ömõoÊ´;TÄ< 8#%îGû;ƒ¾Š #P„ ¡A;X‰alExýª*ŠoN™¨xþÉÂ{S´pAÀúJA¸!áE ±#%ã›êwŒ'¬+Ó}†Ïu¯‰¥hÂ%öz3…#6ËïÜŸ›´æm:Ïr#%r"1Œ’ ”ÌÒùíêæÛVükZæ+kº¬ÿ¤¹gú£ #6Æ#%™Îžî6S!5²jÅjÐ¥¡–·½5{Ì|‹1À P÷€A!µ%AbÄB’VçjœuÝÔ²±c#.ݵêZðc^úªli¤#. ÷„5w!,8‘*àN߉D l&’PƒtI¨ÅiéÓ&Iš#.ˆ½Ö­|ý·\­{úµ¯UÑæÝÛ½(ÒDH"^‚b#6#.)k‹`‰E•Tb¤"M(0'ñn\ÄÈ)OŠŠVuç#6'÷ð=•øØ 1†„HA„cŠQ Aû†j=•€Ôáa­3‹¼D#%;" T€ÒÍ–ÖiµJ¢¶•fËMô¡ˆ!·/¤¸Ž‡Y@sÑV2#Í©ZdÍQ¶Ú…­DüÏ&1‰½#.@ §Ë†HH"Zf0šÚÿmFkB¦km…ˆ7€ÉLÍv¦vÓÆk‹±_T,£T ÂÊ$6#%þDûOPp%*¼CrW¿ªúÖó6óô÷}w~›¢|—ïd`ŸB2¿˜¦gËñꟙ´Cå#%a‚aÌHôÿ¹Xˆ4)RkU‘»M¶ ÈfÈOÆÑv`iñÎŒlD‘HI'2's¤Ñ’õ¡²yˆ?Àáýb€@cÈoSÑ5·câX¢^ü-ëpqû˜ZÇ#%‰ÄÄ#.IÇY%¢ˆiQ8ð$MÊ$4ªB£ŠQ!.pK#.dÔþÕâòºmsWI*å^ï&Å­Ä*6VjBTBW@#6Ö#.c0LK½àŒ1†åËBá-$‹ok#%´Â "JM!hKEÌ©#~NÍŠªð»/8Áo:¶f¾$öû^à쪰pÐÖ„ 331(Ä`m¥ÁØx]âO,’½).àdË0L\Ò² u"Áb…0«‹ÔÁh BX’T°€²+"¢7*© H4uÍ’it52LòêUÖRnݸ6 hüt#ùÓw2¢H×`ôÂò*ù{Ntp~m£fE…DAÙ‰`=aPP¬&i»PE±*Ð#6E#KT-ѺZÆž^Šv0ù lûa£ï€ƒÄ‘Œ$µb ÉS¯t·\ªvݪ–Ê­š[§.ê¾»mµõR¶¿’¶×ºØ+ìŠf‘MÄ”± f#.‘¨-RHE9À³­‰ŠÐÂѹÑxOd#.Ášyþg2Å>?åDÚñç—ì[Ýa3FÖAÊR±1m6¥ÒqŸÏ#.¾r¯©†×PäqŸPì†4`!‘ÄF˜ÁDm6›¬‰¶òÉ’c‚„$‘¦ÖcÁ¨ñ©˜ÛvHEJèGŒ+ú2LÌRØ&Ç.-S9;7¶£´3P–—´¹”-2µ‹–š}¦Ó’òxPëצè!àDûšOË[ˆm4;CìAÓA?{@~¨ìFêøʈ;gèª#. #°êÞ#6&àÍdT#%¤‚‚O]#.0UXû%H€ð+Qè¨÷#6'dÑg"æ”Ø;¾#%âßh§#%–6‡ÕáüÓ†#.š¶ö!þ]ßzLÉ¿¿¯¥$уHX*fO‚'Æ"°›[>PAÍ#%GÉQMAû={”}ᧃvY¬¯ÑõÖ)Ñu©A_°d FÛϲ½¿†Šc[Ü%•—oEÓ,y† ÷¢ˆJ2&óo†tÜÖ‚;¤¼6^o´uç‚A›(77ü“)– µ¶÷Y…ÄLx‹l+Ûš¨SÃù5ä4wòò$;8SV›âT:—<­‘t(ñH˜Èª†',ð³™RÚ€ÒâRgpo¤ˆŒÂÉ2"ZBÇË0/‚x†ã~æŸÇTCîûÖþIõ‚h&"´#6bƒéC;¾¯3Ž¯«ÚÉÖÙ’>úWš‰ûc~Ó ÊqÖ'lcØÆöœ·0´U>’L#»²8US›3H—¸¨wâ® B?‹ï‡kzþˆú&)¸E–m[p•´!oqÎJЗYÅ{™ÙL7£L€ÁA€Œ¸¦ÓŽ V0>²BG.­#ÄDDJª® )æŒM+I’¦Ík¥¦=i4b¦—sìž ‹'4ƒ³>é}2ksá²HÎó|DaXéw‡kÎú}e°&f´R‹˜ƒÚyiÚΔóKÛù=iæÙ° y/âu+‰`Çxö$ÝÀû0}]‚ÐJ3ñdáË-^Ýø϶Û9@Ѽ#.3]7üºÊê@óÀ¶ñXTÕ˜¬Fôõ{¹Œë²›Q…2fqLd–¦ñ!»o³!‡ ÄtÞ8<µ†çÂôÈ6c8Cg¥B~óQMãøÙKºŒËù®ÇC‰mª¹"9n¨¢ H´ÃÞ²âôž“s#.Anã"Ý3-½GCÔtä.9#¿å¼:öŸ´Ô>‰ÄÇpwÇÉÄP +m&™#%f¶FÖ´ÑÛd92hÅŸ$ÑEy#6,:@ä¡í’(:xÔw‡u#6Š©6Ï쯟T®Î®£Æ>ÞHˆ{:¨óÚrz¨öY5zº¹[­(úù³¨å•gõ 8Àu¢ÚO…±Ú¨¦ ¢0ôV#% FB$š‡¯°Þå÷Vgl6éÎ×Ó©ñCqš×ÐEúW9³‘v@ÓѨa´Nø¥7 ì⇲ñvVù¦…é ì€?ÔTÆ'»Ÿe¿Ü»Ù;}`£9úì=§„¦ò•…A+©/þnw‹®B’v>û¶çU;QUΆ¤”RtÐ:`#A‹'BÑ1Œ«¾ùa+Ð1 MpAH!ŸþO«mmCPç¢6îÐ*Á#ñÈr=ñ?£?ùûKÑTHØ?ÚáUŠ¦7ÊIÈ—Û—X”ÇrxiÞ7•ÎåÆš˜:tà€^³Í£Á!žKòó©,8AüÏzßóÄw(I ìäh·ÑQúöùw,ù.™1øµZw®íb!&t4!Ç.ü–ú2EŽ”)OkR¶Ä4³¬?eBF1³öeÑ$í8xnÕnùx-ˆPúÉŒé^û,ÇãXFKP­Í<œÇ+•wOÞ×j¤Ñ¬E¶Ëf³MRÍbZRµMR(gfí–sʵ$‘Èu.kOU;ÏïHÝEUõÔ«@È¥~Ïíýש?£ú~dm”eI£0h šm‰¨ŠLBLh”b#M*FJ&…!&Í“a#6ˆ±Šü$åÅögŒxɳ'€«:û“7Ü›o'6úÝyŸ”R’M›vÌ ÜÆ0Øh4MÌÝ4¢¤aKæÞ7t¶zh%*éMð·åÆ^&y}Gå1ÑÔ¦׃M6`¥·m—8™@¨…{*E#R«5sQƒí‹“øø˜ÞŽ¨Ã&D ¡+fCÐÄÆÛxÎ&cz\/Ó†À[]4šªœ„>n¨¤ôÜŸh#.ØL“ ïÖ9obkMNËÒuÕ.Âjõ!2̺ju^ëØÖ8ì3ŸÛë¨fèÎ[ŽG —ç_¸3ýO8†ž°Õ Úm𦶰9ãT’/è„ ™á­ž3°ûç™#6ƒRi¾m#%F÷"¢Ö[©Œ”¥m¦œiG#%0NPÈ©-D‚„#61u2H€âˆë—QUË;®JnVÝ®ésuu®ÈïkÎòYšÛ‰×·‰7®«— +lÆ4›hÆ@î’1ˆAš *ˆ‚•º%*»@Â’Žë&M’æ˘ª#%¦_å¬2H¢ÈAB,$Ö™WŠ¸rérÎësk$¢3—*çFד2 ËLEø:UÊA-H¡K29ÇXar„—ŽR×eFÉ‘?6¢teÌeÄÑs4Ñø©…~÷ð/c…ž ò—hâÓX!˜Ë#6Tr!žS“Ñ©/Þ:ãk‚Ãz)\Q„Ñ!TÁ`U«Š¢7*â͈Òll«/c\(­›Ž!¡6BÒˆ’¼«³5A”«¥¨Šž;Í·rÊ.»xÖúÇ®î×uQ”õíQ°i…¢I¥Âħ%4Ъ!h¨&MŽ9Q%Œ²ÛSM©·LÆüR˜ÕDôÑF¿œ•Y—Ú>REB#%!‰ŒT£AÜ‘Båµé{T}µ*Àì=UíŒ&„æë§ÎÎ00Ò °W!P‹'Û:D¯µg<¼ÕF r†™„O#.4P÷¨ì¬p£þÛ2FÄÙÝÛn®®›[{k®”;¸[ºU0Ir… Y…ƒvÊk^(¦µR˜¡LdÁ’ RËuB¦æ»³qP Ù(f3Т#‰omB‹7û¾¥°·°ø\¼ÌÚÒ㌊L6-Öýš"ò»-ëÛ¹Vçt$YÐI€ÛâóÝkXäœ$Y¬Ùæj±ˆtª/œvA»ˆ>#.¬—½HíÓÒ1ø¶GÛ«ÃD¯P‚VÑõ(þ¯àˆ© N½¤€L¯ÈÏa‚“‰‰r×(‰œ$ìÝÉÐ’³àw ïRb4w‡^×»C¾/…ìX,^¨bK”\«Ù½-!®ÓlßMvª|ºõö!üȦ7@Ï_]ßÌØuåÜ(7Ñúþ©ØÁ#%Ë·I#ú;}+¾?}œ­n‡*œ>—Û±ÏÒ[ì×{oѤvÒBÅÛ ³É~¹¼È?ÈùŒc(šñG‘© ÔU#6„+¿æ‚d礇¼ì½¦ÐðÉßz†R‰Ê'j[br¬#.v#%ôηUŠšûʸT71wV­fºËmŽEßÒX J§^v×# ï EC°yƱ,• ìA2±A„ETù°’á™òNÊR¨QeTÎÞ‰rá˜\ö9Ú5‘jªË#.&t0ßá‰cZb8z¤0À—mE„þf³ÈßçHœŽ°Mq4› ¤Š9 #.þš ÃUHr¢’\ªévÜV^ßÈò¼QkÚr¶Kh·²ÖìKrîêÛôK\6¼UÆŽnVéµ·MY#.cnm&Úæ²k—-µÍÞír,m“j Qª+—‹;«î-Ã#.âw²Ë»$çžv÷07Šü<¢ŒÍ}Zk¾˜•˜zÓo´=H^Êî"Øκ’!7@A"ä#6´Þ”=¯íÂäD ´‘ƒ»¿vú®_†o™ªƒ‹¾ªýQy>ð)Gä#6çøÑá"É4ÖÂ=$±òSè2w@d#%“ Gßè—q¢1¤(š‰IBHå%ŠJ*¨Nîòá^T#6Z\# x Ù b¡†*©""(¤›[u­#.mt›¦µø~{oF®Ü¨Rd%ÛÝäT]Ñ *½Q@–Q¤ÖHѶÛ%[¿™~k÷!D,#6 éB?õ@Ô#%šÿ$CÏ¥'¾ûHjÆMöFÒ¶FñÇÙ{ZPuðP甼P#%;²f_Œî@O÷A$‘;ý&Ô¬›¡Ôu`¯ª¤ª£Ù¨3`Ð: H#"&Q)òT(uqe-LÍ’IJ1idŒ´i66hmIEbÆÊRRJdÚ4)µ´Eª*ØÖÔkjZV™jZ52¥bÖ‹ci5³[ϺÏn·$cu¬È²#.Ç"6W"Dûne6˜ÛaPÊAÇ$r®tëÓ£Ò®Ï=tªò®<ìiq¨ò¤©¥’D£O c!&$Ü*+hlŒc ¬H˜É-a"#6@£`èÁi†“#.‰H… 4ECJ¤P*( B*Zë0$(¾B¡ Ô#6Y2?Íü5°Á#%™ô© DØ% %¦îéݘÜ:ÓõÚô·W®ìÛVÀ(@d‘‚$–f­2Óȸ@M°%Ä^û³„B3ã`ûÇNÙ"vÔôôm÷wc¾²³Ù”„…QRN {ABH,O½¸VÆÈŒÜÐö5OÈ¡äØf2vp®§W_—[—,1Z%ê/-l@Ò¨ˆŠ±±Ü¨Mâ xFß—¤jœ¯§1p‰V!TÌH!PáJu”0UR8Gõa£ÜœµõN¦’„µFénãɼ•ÖòË©R™”/Ú]êµsQµ±hÕZŽê®Á¥±ìóp–9‡ávº?®HEÊoz¤ÑïpÛ2#6e_ìÓjÎ`»8C®+dßX{Ap–Â!ê>ÿï(ü±YD©Ë³eJ[LTz÷F"Ë`ç`΃՚‚RúÕ ÿ™ùiÏJ—Šê%áMY¢ªS|š²|‰š®#6‘u¡‘àÖ½usFpÙ"}rC¼"Él³Êª<ÂoבøÏM™Ïr§ý–æØè„#Æ X}¨vµºt¡;?;#'•ËRùi@Ü¡ÍM¸Ôã|]?ÙÒί^¡ÔB}¨#.#%ù`ø€¨ÖîAå—Íã°Ï/Ñžÿ|hÒl\1º**;­»3Ú*¥â‘TþÈñÅ4¢ØìçÓ~ö3aƒ¦)¸÷GZ³*¥›z—ÁÑÇUƶÜ` ÂpÞ]ÎÚ£]u\Ê­Jã‰Q¢ë‡òUÓ3÷˜‘ðÁÆ&Òe¥”ÌI#‰ÆåÛJ{ií'[lüÇ¿Üo5ÕÛÄîÙ¥º'Q#%ä3!O¨"e¨BG½V×ÒH#´'53×ÕîZ×#.ÃP„˜ñçRn tÈCñžxm÷¦‰¾Ù¶Uúûïy/‘ãV°A„<(}ZÒÙ81K²‰$=·E4œ¢Bl‚:E’æÊSlµÉÆW_û­×¹/#.ÑÛ‡QuÔîí®:väì³G¸\§”µí{KXî{îV¾¬#%¤LÒ#6Bk¬¨7â¶(/%ÀèÞà÷Ô¦Çb-¬Ä¢õÂÕÄÀÂFÅÆixå$Z³™F®;ûó–©vÂqÙÔ!Äg ÷7tVBZÇS¼•/ yÀo#ß«½Þ%™&‡s©X½*77/²cMž±Ár˜øW^3Ý$"“Q?:yÛ„6"£ŠéÅƺ–{åøÉÐ#.ôŠ¡¡”ÌVË~ügƒÉg‰smm9)¸®jWMöÓÃm‹f±“ 虘·â®8kÃÓ[é‘þ]»±6årXöN”VRTâÌYÍZª¥;¢øùžgrª³s BÄyo…,pѾa& q<£“jf)‰ÐÙnÆÛ›ÐÓE¥Å—•›f5Šw©± ŠÑÄâV\º)2›Æƒl`œqÑáDë¾x¶ŒÅf^–a›TûåkĆŠWnëh6“³mØ—[ÑÆçhNI/$“ËÆfš7Ž)¤ÖŸô•öÍGŒb$C¥×ÃŒêC–C:ÚÒsŠ/}Ñw§Ê€ò¶DÉJŒnÛTóQíjP÷xÍ÷‡“bëZ:>춖Êü¹Ÿ9õÌW_J×°¦ŠéyƒiÄÆx’»uƒw}²™×:üç´ç”¼Žî'÷u{õõŒa*Ž½^W‹W0ïoèÌÐâò¹˜ô³8ÎÜVx˜«­¶®œ§|ʼntªCVo…Ž†#6åUvga*Fñêòª‹­éïlg¢/Ç=˜’Ã5ÅéüÔÂln÷.úþöb¢NΠlr²¶AÅ׬ÆРo#.°†(ÐÈ#×LC÷ªó#%€@:ó š#6`FãaÀP™˜‡a»ô:£L6 ñÕýxõ»Æ`vŒž¥›¤•`qG=æ26ð•9è•ÖkSAC«#%6ª„sÊ^æz±¿v‰•‘ Z3Kˆ—3.ªÞ&˘sxÃ\ã#6?#6«_Dd\¨¡PʸG`{»u½§D¯OÆ.þîO'6÷ûÞ [ž‡“°ìkÅÖÈ,½ÓÀý* “„GÄÂg ¾T©œ"VsïÎ ´##ËlºNÁƹÓkFÒéaùC·”úÏòghæz¢:§ç™ŽŠ–”žç—>ýcšŠETÚQSSNFüb((±SöÛœM—Ä e²Ú{Að]‘Ák]zVÔ4o““Œ{#.”Uû»ð*#%Å9ÇGÖ“ôÚÏ6(¯Û#.oÏ϶;3\4‘Š¡³G>FÎD(Öѽò‹çÇÑp²9–žfª7 ­Zæ0ÙºÞÝCë¡ã’šÖ‹NÚ21D‘ª!ƒŸ.e-lZ'ÚUbÕõQÃØ¡™ç~%‰@½vÝiVkQ-29¾ysæ83DñÅì^[)X×ÕÚÉš" Dv:e£;F#6Ç~›•Ù¸°ëíÓÓwÃŒãWoÕqÜÌ‹²¿';¢Cs:ö#.a º:ë¶Y¹Tû›èœ ¯[–ãÔÇ4v4n s©»x÷ÑÏ;èÝ 2÷~öç‰sw~/´j¦<“£\W‰t·Œåóm‚åG‘^5&ŽÉoä wªŸ7 AÍÄ%å#¾Þ0Må8pqäñ<³~7SÛ»å߃Ló‘Î¥mZ¡\dõQ†Ð{x09hRÄ¥ˆµ¥«#%}¥ë„ô—‰”D4·–bÍ…èŒ3¨ç’š®E’=¸¼ó‡ ;Hœðà>.Ãx[CUZØ=íô7,Èh¨·tz=<7~†O›œ í†fBñEo7ê9q À°ï‹ˆLBõ«•³üñ6°§«Y܉±Y…„;W¸Žœ –Îå›\¹Þq.ï6… )sf\=®Ë#ÕƒV4(êvµÐ<³Ê@Ç”,,¸Œg ¢(Ôy zw-•HÕ]B¡¡¯E´öq3¤:f,öÒ­'!Ñð ì@â†1HóFÔó vM\;€© É3@Úõì.Úg$$VtIm-äSLÛ0w0ÈÁ'‰#%ÕY"aÃßôèU×]õûC#.˜`fá˜+u¸mæò?‰N®°Cw"³0ñ²)qO‘n"xXŽ ‚í¸NÛ&Äy~‘å(ä·°ÇèpÅ`\r ‡Pž <ß‚ð(;ïÍVßáL{U#.>¿ãxKf °ÂwÀõüƒå'™y;`kàýpÃhST«CÙç2°gÏ¥_V«GªG±8v'$ODMáÀÖN}®;O‘[Tb,ŠÈÃäÒ¡E€~ ¯Á°e…D–aì»Ímlš…s˜Ô¸ª’“#I#6±Kº’Ì0ªm&@•<Æ…(Ó`YF91!²²"¨DÈ¢–‚“EXB!$JÆÕ½+F·5¨­nZÊèZ©”‹"(ØÁci¬¢ÅFPTÒŠˆ¢aQFR¥‚0ø!\Þg¬âþ&xØ…µ± Î@LñÜî#…# ¹vÐ…á¤é$c9ÍbŠž”Õé¼mãnEɱ­*µ¯¹m¶‹V®UQUUé¹UײóÇÐÜŒÍýÐçP:þ~–µÑøC5÷]cÇ-–§AKxæ*Æ1ƒK+udˆ×/¨ÒÁí¸i¶í®o Ü#.hÇHiþc£f-+°£W ¾ù¥SáîÀkN4bJ³ÄòÖ:¸`@¥,×–cÉ –(2ƒtHqbePDiòãOR;Æ]ÓxÖa%‚dH°!V“7V˜Á·Ù (š&ÓicRE,%ÝEcbi¦4C®Z*=Ê[ÌgA§Âu‹wL¤t’d½>ùlÀö›L!P9l›ª#6@Y0 šÂfœ‘L7zUàÅ3R·X›€QŽÆ6ëØËÖ¥4ÊÑÛŽv²ÍîFjh£MÔU¬zmkZ¦A¸Lk.<“µ†µcÔèç9«eo†LÑ$D”MqP\`SZ¨X³LÐ*±c‚ñcix1”2ëB‚ÕC$Î¥¯Õ¾5©Ï9;·hÓaY ÎS¼JÎ!ª#6A,ØTP”2„ÇcLhÇ»*ëµs½µPAôãn²‡U"^Ck*œêæVú†•“%+XIw­Ü&]J&0ghnÀot‚Çßh­siH“°N'a§ïšiÏ]P \‰ªR8ÙFö0TjŒ?ªãÞºÓÖ“cSˆ‚ò£œµ.¨CZF“Làèd¬q¨Ô"Ú7*ª#6”*à Ѹ”Ðá¤0m0m15+‹‹FÞn-¼™,²»zça›[ ¹tùÐC 2´CdT¨£]ž&09ÜEZÙ*å#.hFe¡›±—mÝF?Sã5@‚ŠLãRùg%¥¶È|4k ¸Ô €ˆÚhŽ¦ª~¬¶ÆŠä$¼*7Ä®é@ì€zi¤„<˜D¨°]8&è .ï®r#.V†FÚqÉ#——B–¡ZYm r˜m†2Lä­„ÊlbWfJÌæÚ¢&n\c§ˆF±V=¼§^1Q¼ÁèÞi•®›m·Xˆ9¢VßãÞŸßÞŠ= ­GÕy˜úe”}#611(÷"Ñ„Ž·e0Qsâš z±ƒXr8c™MAø¹¢@‚œ=6ñalÊSŽ!vH#.0ÕŒÏ ¶–‹€û0­\d#3ÉÜ$d9ö¥›:é¨WbTF¡£†MP1#BÌðCV#6æe´Î-ͳZ"Û­hDF ¤¨b0fµ8Ò†¸Â±¶FxØ7‘¨Ôƒ{ÔË ¦A¡6Á&'"Ë9#.+µU°ÍNß!UíÏ*ª™Û2‡s—£Û1ó•M`ÁC!0çr‡c$’Ûã½n‹ç€¿¦Ì+¾îÝiL™5–MÓõ6¯ÚÙH•$ä”´•¤$ˆz—O™®;ÅÝóèºbCóHwÀ©ÚªwUŒØÖ­À4†*SmÙüçƒ U+ {}E*ûXSÔÓ^#.“ñqº²±eÓ¦3™~sÈ+?2CÁûàÿ›Ð9¯¥Ag*Î*JAFä#.o³·Ä³Bx«ÇzQ€#È›»û<*±¿®væA§ ­öœšÁ›Kˆ?~Cóyßì¨×\Ubƒeª•Áå˜ó>\f÷={p1¼$a¦î“»¹0ˆ¿{w@y9;šbƪ¦[ƒ'º0’ÇotÜòä<×Ñ(õÈø¦k´à­µÕ÷ ¤qÁΑHû®øŽ›ü!‘¬í£Q:ǧ å@Hµð†ç© !Í’5iŠ Wj™KV——\Õ‹m]7‹hlPPH¯Ð†¬»öÐÖiä#ÔD~èì9ߥ}~•Œvý"°R(±H#%V ZÛ#61´Œ˜Æ&1¤ D©(Z¦UŠil[%¤¶¬RQ¶$¬š4(¦Ê£Í¡M5#JM’Q³JHIQÓhD¤KFHS4T¦È¥SF’a¶lÂ%(I1«X!#%øÞ:úx—ôÌÔžg´ê9šÉSÛŒº¬[Ç4UyÜÐ~ðWæòs5þW‘$$g1$8)×ÃÂÚµâW#o®å$î—VÐElO"¨>œ€#.¶ƒ˜4~‘ ¼Hga¡„’hf6ؽØLKn£’R& ¾~§Ûzk³pCõ%ßÚ(2ÆH\Àù9q]‡=½haѹS(ÂBY‰èâ°ª¦$ã…ß´ùû½šÂùïâsþŒCJ‘FÃÅqy§üÚµù¯×ÑÖÇ‹{!Ãë: ûo?“WÝjßµ¨’Û&ÑXªKXÑ÷Ö­si±©B“Q£±õÝ«™C!b”R©bXK2ïÈ0'uàEŠ$fPÉ#6>ÿ£"Ù›‹)ƒí¬÷ó.#.ƒ>+„¡Q…¡¦b0ÜürèÕcD>n.ž5ª(àÉX¦¤ŽRb"©¢˜ªŠD.éÊf’¡”+@6lxœËRXÐV,Iˆ.¾Þ1Ó{¯.íГ³šöó«ÌÑŒ¦»6ö•å&ñsD¬ÊÜ·/×–³PQÀº. a#%­ÅÝÞ!”`ŠÐ¡GLŒŠÄˆÄ½G¾ôÓIà{è5O‹†EÉŸ'& u1p6e¤J'LHQb`àËVAd¦¢ ŒbŒ¤…(Œó©#.LáGô`6  kgì›μÞ6ór1J¤NŽ2,=¤4,°pˆœ¦˜„| d<ÀÂÛ«6ìjHÚÛElmŠ#6­#%ÚÔ(ƒ"3@pBh_²*ÁUY‘U¦#6!ìßÕºLŽ@ ¦‰@¥+†Å-= #%½]­”ô¿~7c¿#´…`>ϾÈ÷÷ò3Œþ¨ž‰Cft½B$#!¿ö?‹"dê…„|êÙ¾~h%¡Ð{Ñæ#.‚’ Ÿ,(`šä塤|ÈØ”n2¦‰”­­LÓÈ3ÏÐ@„>€ã7ïØV†Æ’iy¼Â°÷ýÞ=ßµöR|ª2Zûf‹5ïðñÆUo¿[52UQJ–m¯ZÔÆÊJýKï*G;ó&¦¥„u Êqµm¢ò êg™*ñ4-o^…°n2nF-tiªD§7C5Æ6Ó&TS`Ò &Œ!*Q›±A÷Ä rê]uâ+NA–«B/¯Ô{,¢tòOئÊúÓ’rµÉF¯Aï J+«)è(° Éë;øNsê>«íó]ÊMË°#.ŠšL†|ÊÛéRæ!Á)’Bª9£^¤ÿjfÅ<Ì;¬#6Aî0xw;Þõ†HA)4g˜fzúœqŽòF­õcÏ á„ØE¡kõ|¦!»°uªMG&~逸²#%Q;úŒ¿ÜtŠ@d‰"Ȉˆ*¦#.>¸ô/}RŽâb_cóÖìT#D¥:Ζ£Ê±rÖîõý“'5>‹ç|â²âè}.šàý_Tl×=ÎÜÔ²]4X`C$0ÇVêã9'HØv'F³ñIÚj &¥g™õ@>3¹“ŽÐí€#%pàJrê`{ä7s@òq{ÊA/˜”UÒ\zge)^±²=sDþXÜÆ1×Æ£ÔŒå°nd[wof²XŒ‘²¾çg)P’6B·Þ\+ÉÚEµÜ,3âÍ„JS»uUtDÀý19Wž53ÂpTlÐÈÓ#.¤c€h‚` ñ‘0pP#.@ŸÐnªÁ`È%ÿV TU*2ìÈ/&YÛr-Þ¨»5!€PÔÊ0E#Q¤H›a¸’6P";^-ˆš@â–YÇ1Ìnì5Í—™¡#%1” ,½!‡sˆYÚŒñ¾¤flzÙ¹Ôé¥ÁciDã&‘Ho?/3²Ð½X2Ž(uÇÌ°´ÃdÝ­zYg$äÝ&Á5åD ˆEPÚ¥HŒA±è~“3#%‚ˆ Lˆ™ªÀC}ŠYf‚-"¼¤}q¥£ÌàIQ%¼†Ø^FZTz³µšHÅKÅ"@Sp¤u^<o.ÈB3@Dmï½àâ…×j”ta¦lrÞX@z‡QfkQ ‚Á¨‚À½Aƒ(Ö÷Šóò¯n7ÛžW üï¬"ù:ÈÏÓ7Ò`ÀR7{ƒ¦BdXg&ðS¨f%¤Š‰” É0ð»,í‹ýî“•¶ÜD¶uS2ºcre38ºt#%™aÁ%ç­»#6Lp²O§pß’X9 ¤à»WD¢ƒvkb”Ô+LÄ#.–܈#.»³BñC7<è‰D©#6H2#%ë¸ïšµ ‹!£!PÅ X#6ÉŠH žºÄyŽ-•_F¨é<´­ŒöÝaš•˜ñ¿n«ÍÛµ±S†o1ï[ÍœVWÁ¦e 2äptc¯,ã2®i²‹혎s¤°ð­Ž4F!ÇöR¨±AV,ñ³á‡‰$Eïæm;ÖcHo!Ó@3k9LJ_™'LÁ›YÓB¯iè1@'*kMž.³ˆÆ£6™‰6“ A»m¶ÒÁL\RE΢ŒFe¥%o˜Ý“*—,už›`Á´¾Ñ‘9¥É1260ìo)¯i#.&”÷Ã@V«¦Ä$l‚tšÊvÛck¦—r˜F)œÀKE ÙM‰,vLí.\º{Õ—[>!m´Áiå¬Þc#4Î!­äkû}av˜ÚߤœljW¸ä'7qÖ$[¬vŠÚÜßLU»ÆD<´ÑjlìïôH=fUÌœL3™aè’'£>4‹O¬ÈÐŒ!Zõ‰S5{ÓX¦¹‡—CÎ&—;±8k¦îŸ\@r¯2n&‘='I©Zã¤êBÅ FÕ—„,¹\¬*ÍV׳p™`—\ñ©HfJ•Y#%êë㚨‡"ß‘kkÌ›%ñO+vv&º?grà{Þºç(äUÐä×I¤  X¬E#65³6É›!ÅdhmÌóÀé­^]04©qs:ÙÁÇ0@ëæE}h·¨nœLeÁÃ}8 Üƒ^-1³ñ|2£Ãµ÷@¸p´V×›;"'›‚å¡„±•X%ôŒ–ºí#%í5`+IB27©t§#.NZÐÅ©º†B¸–°Aø±b+m:+¤‚BN\¯…mgY¬ñ[6L†ÎÀVælåŒa²DgÑ@iµDбP<ŽýÿB㌱§4ü lÔ?nŠMÖÎð„àM$ÕY'¯BÐòtoi´\Ûñ¥Ø+~8ᥢ]-YÃ[Ôtͤp‰?UÿÂQm—2áLØqEÍ#.q™ƒíñØåÓ<<4x¨1 (3Hr›ŽÞ<9²óëktò ¦Æ ‡r³òëz]YÒ1Íñ,ÌŠsÕ¦)³åÈFµ.ÉzˆÂ—y|²ÂÒ +d׳„ÛFó~BÀ™aud¤Ö †l”ŇÇ-Å…µ¾ù‚3XSC´=‹‰±ùq«óëth:j=iu]†Šp3B„Àtž§¯_ m}i¢2HÛ bvvÏxâ«$3@ä½Ì·gnªÕ ³ ŠP—JPÍ HÆÜq!¦YÛ%j®`Þˆ"–#I¢#P/¿=¹fgØMœÁC´;,LMµM4Yp'Ò*Úúµ˜·”ÉSìÎxÔEë¹Y¦§vM€Y@ôðSäÌŽœ™è‰åå#6ݹpf#%ÊÏÚ;tíyA&w©b¥‡OLìO#.&Âé?8L89ÞÝ“M7ã%†8Ž9Ê¡Ø-u#. ³/L]Ÿ¯\Õ¿%‚Ú.­cxŽ¨b‰4&µ!Ò`,fÄlLM‚á#6­˜‰Ó£p:5ÒHÄÄÌü¤Žd‘A¶¢„Hø0Ì‘Áö 4EqT¡ªk&§xÝÛ3ÅÖè)ïe£(Ã1YÚ`¢ÇŽ6! Ý]ÛÑ.$#.  €àT–0%DH!¹±Z¸å9Ç´ÒQ PP4 ˆwŒšÈi8,ÑHŠê%Fl!6aeÈ0à\*hÛiD5Üè8hé™–*¢P ƒK#6¦æÃ@ÀÀALCÄD‘6D“áS*¸è†wB]èÊ4,¨6"ŠwA³½ò3bà‡"¨)ØÙ˜Òi½‘ƒ†ûøU‘’« Hªå¶ÎMlEÜ 1 ˆÃØ#6š6v4#60gSP#.F†¸H¶WU%0MEó& 83ÐíÄ„3œmÂt대ÉHrºâÄ¢ œBB¢ê™• ¯3[Ò^6¼¯_#.óˆ±c%%¾²yyôŸCk£U@Ê(¨ˆ°צŽ½Èš“n‡£¤ž±°f÷ò C°5#6,"B@MbªPê ‡á¿öôl½€Èë:½u‹yÑ\ƒ²íšeX§—ëïk—°Õy+'J#.?Ö>£MÃ܇)üŽøx¨âÙàm&-£™×B¸kMµ7ⓃIf ŒsQ‡fE°Šë»ºf$‘$#6DXÍf¿šY¯§·š#%ó×W%U®ÔEüðMÑÎ^hÂò¨I#%ê¯JS°x|k0ÂJh(¨Gf‚uaÐÆzífˆ?“nôÓ'àÒ«„¨“¹*3#¼¹R'W((q#HªÕÝe’iŽè3³%<ªÙ 쪌JÅrØãz#ÈÄ6¹–7oSñkJêF9ÌTÍ@Z¿0TV(NAqKìÍËVè+ÈämÎÜa·4}o{ž«;Ù¬å¦66”˜µ²¶[[:ÁÖ®¿¢>¡DHª{hˇà}*s9e¾Dʳ:¯«d{÷ÅT°3ñD#.¶CvN]GÃL—@SÞ¡#%4„Ž©C»¶Çá^Wf“·DîΗZ²º÷áâÔRñ7p#6ªVŒˆÚX"kÕáË»[Í$2%ñ5;Îéo7v†È®òï^vÉåÒ¹Å×RÉ#6A‘Ü0@4Ћ5*ˆF ´8iQ¡øé3 iŽöGZK(4‡]-ÌUDÖ7v)<´MF¢¡ÇgVƒ#34u*ÌÙbQ „GFùèë쯷»È!ð†<ýZ÷ H|ÁpDäA#%¦Ï¡¦3ƒõ†j‘¬¼•dú.ÖÚ1<#P„$xîamˆ…ÁV†ŠÄ®ÉÉL+ÃàÀØšÁ$p ¶”(“Ÿ(7'§¨&µ9w²#6nc±ì³êžlæ!ÜúìçÙ#.:ª&Œª§­LYUå™ ùû¦ƒ÷×!ŸG´šÈ(|#%ÉÂmr,A-Ùa…NKÎMN8ÓR0;»n[5'Ã)Lª×³¨^b>%¹C3é8]6±uLDÔ`X€ B!:©O¬i悘ç³n%Ú’"öa\ÐØq¥ÑÃK×è‘£ñLôQ#.i‹1Ç¿†0Ú É 0µö~tm6V,ŒV"$ú‰¬á†sÈkÐÒŒ˜Ê¸ öò…0'º)HH2DO¢"öµ”ZÍ­iHJÔߪXDVBEGE„ìE—„0cUÆ„e5@Àm©n\0P‰`„M`¯8#%ì#%IîËÑ•…*Bé—øahš<2­½Æ¦Z\ÜìŠÈ¤°ƒ² H’€:¯ƒäßbš•X1¿ 8Íõ #6 #%HŠ’*¾ß–[·|4ÅO4oÕå}#›9†Ñth¼g#.`±Þ»Ž´Å¸3©Õñ*\žY9)h„¢‡#65½P4a£ePM£2X’l+%Ê«EE¨íD‰‘·LNA‰GUÕÂë×yåmÊ^¶²VÌÝv¬V`•%šQV@IÅN†ýWPË3:È$#.EG^2S4#%Ü¥…¤M—2,Às4µ§âPNÞ0:=G§‹Í,0!&*Ç·§ä=ÔÌÃaÂօз;sHc²iÞfÍ ŸŽtê1ëa°SàßÚ½&ñØÒ 7!,HÈ#%—5ëÃ@ä%é© ¾EsRÏr¢Íýï_kWÏ:ó¶¶*'õÍn¥‰†šHƒ[ïh4×·¢`wAu­uÚá#.,‡q89 ‰JþÏáÃ;«¯³‡3€¯ÅO8~kÔ1 Ü$9Ê%¯«y£6ŠZhI¥EG!‘+Ž]£fvßæoíÕ˜8”™`±Òùn¸¿¾¶^Óötš†Y[ÕôãBa»Ö›iAà~_X>ÈH‚&³ì‚‰ÔXb„#.4Ñ©î„5ë%ïë!rKïl}9úÓì='p>ýÉ­Ô(Ž^7/$‰ˆ¤´š’jYiŒVIJ#6«bÖa´&ÄŠ*kLmµ&ߺÑZ¸Îk¡£Y³k‡s¼ßÛ<“ÕXªå‘˜ûµ£aÞ¢þs”Ôæ: ÇÅ#.#.¾®¾Š+Ÿ˜±;öòÀMI@\Ùô‘²z°/‡aÙ°nâ#%žÕNÑ=ǾꉑäKÁŸFzùÂFC?6ëñ(ŽukµÃ Ž…XE{šJ•ƒ9&ärÔP|üi¶ŠöÔä4Ø-J[hyªôƒmše;“;ð´#.MÓIÓqA’q«)\»’ÄùÑe®qÄAäÒå˜CDƒ­ 8:ß 7$™l·}uf¶™ÛŽ6c„6ZAI¡%!pj[´-ÑÅ[åÍü ¬+cTdë‹ÔçL¨Í¶§fˆÜ€¤#%PYl±’Ú!VYCrhM ­#.Ñ­ÞîôÅN‚¡êÐ0LoäÅ£JÔ1”ÊȲnÅF´ýJÖ† bÕk#.¥ø?{5²b]%OZZl}Æ0 ¸äE!òó÷΀Ù,"÷•Ég4 )@w}* uAÔ ²$ALpIF wIÏž/ƒ©‰tÊð¨A°O€!##Æ Žj‚ U6¼ãÕt±ð<4O‡ ¢+ÙÚt÷ a‚­ŠÛ ‹L;ÏX#6ɨF §ßæý#%oÙ”1d”@Ç!”ƒ Tñ {õŸWnÿWòmî'y‰üµÍŒó6@gö8A°ÄZ‘´³0?yüä›é#%Å<Ô®Êû>Ê,U!¬Ûf,ÚÍ´õµ¿5÷­øµj÷û"Ñ-62)E’4²’©³jü¿tj7ßÕ~îú#. £D1SQ¶*¥)JÚüz§h’—µ¼'Ì‹x„"#%Z"göBRÖÃÖ1ȸ0ćÐ0–HrHNTŠ$è>ä#.D1¦î¹²)±¬-f¬Q¬lÈÅc+™E²Á‰ëÎò*ˆ„(@Š'](Š]ê4{qM_îòýé©çÜOsèùfaב$ðWÀ šõ‡#%£'¸}—ËeL|ó*j¹ #6ý{.³ƒæɃxv÷’,!Ú°3œ…ó˜ÈIÀôªyæ8öÑUãoË{Ø,E˜E'F™ñßt €ž&ny¤À˜ÞB Q¶Äb‘püÈt‡î"€Û@ÖôTÖ¡ódH˜E9§¹Z€¡ ½B!JŠS˜Újh(‘"jKNíÒkTÛRiIª[R’T šl‘‘@njm¯a0¨ ÿNR‚(”+Ô\/*SÞR¬‹e¬Ë/n£.žÃgUPû£ãÓ dtÎ=v£9é.k ¯Ni`MÄljh™ú([;³RÑÖ*È5õXV²Oµ8Ð"Å…k°ÞÚ4ì#.y@^K?ÞÑïW-ï%ë¼lcúé#nìˆzK™š!ö¦ ¸X÷¢Ї§øþàêüûo–—çãvMÅ)¦%I²5¶1R`ÔFÕ&Û#6Z7æm¿+W‰°ÑZ(F AUdQ$ïî9ú»,ì–i!`¡P*…ˆû¤6+°0rBF"EHÒ(ÄÉ…Š)¢hlÚQ¬,#%”†ýh—Æ}qÏzíÙ/uÝJQþÀ!"kWš±mF- Ú”5F„«6X‹X«QšZÊßÓ[¯3†:zº›üYݽ´ªË%$ÜkìÇègÍ#6Ñü5–#êŒ1KŠL5VÊå˜F·ÓLðкùÀÆ—àIô÷$È«miGlý/$²ÙÛ3"‹ *hc²øQ¶EF*‚d‚ÈÇ#%ª@ Sã’¡¬þ¤Ê[Fh¥È“(1P¹{äÁ5×\É&§4)DÚ›7Õ¥GôØ46àYêÓ’äö¢ìþ3OêÁ `>¸ˆ¯pÏ?~ðøfŒEº#6ݧ¾÷#R÷fìˆfKËÇXZ¦#.Yë9¾îã~07"ß^GÏõ–™“¤M#.UJœmG/¤lír$a®îB™1 ßèSJë@ë#³o(ƒ$QGÊ)ļ.#.õêLo.Eä`%Áæ1‰¢GP5¦Õñóç/ml·p†B#%|²$Ÿxk‘(#6™(iÎ ¹8>J¦ç¸iߎ„>ÔÒ9åÈt(a…-Q¢Þ–3oÐÕùUbÙ›õ`|¢‡B hÚ)I¨i¦×£|#.âöA¯qØÔùKŒ˜5Ó"÷gëtód›±BKûòVµw¬¢ö|jë‚P¤Ot~ÃìJ'`O8)¹A°.F´­'RK`¨¤,n#¨f4äÈlƽQÁ€ÑÔÂ!³n¶`¢úC#’ØÇwšƽ!ȱ|*é €ŠDŘaM ‚¶”FŠ›ÕÕšWáœuzC<óËû²œkGG ŽÄêîéÕ‚]Üãjþ?70ÚEy£ÉZ$£Y¨Ï¨ÑÐǽÁäuMmÐ/÷Ð…ÄZè8@¾?jã‚8“ù‹ç¯fƒYÁêF4dýŒ—-DEC=µvNÅ|ªÖÞm¨:ƒ´Pi\Xì"ð#.%t¢#‹Ì¸ÝѨU׎1Qߪ…@ãƒ[8AÀÓ Êö;÷—çKŽ¤B4Dbžƒ:[nXŠ#.édRS(´@Ír:†‘ä|Xr×c'pždl€A±ï47mà¶Ô~¤…f1Þ“‚BG¸Ô_h½GCˆô"W¾s;/~†D#.îfYÚÛÊÚ{aµÝ×oÊ÷}þëiäk×í¸*‰>ÜD-(?„LþdÓ* z©Q£fÜ@ ݨþQD¢¸ß³Ñ2Tm`ô=åWì#%ÇßwïØÁ²>u­Lä‘™› ™˜ÿl#%#%b#%?›Ùÿs¿ñõÿ¿ü¿éýŸôÿ¹íÿóÿûýíÿóîÿ/óÿëþ_òÿHþ]º>_¿ýÙ|¾ß÷Oþÿëëÿ‡þ?ðøÿãáÿ~#ü¿ãÿ/óþïü?ùÙÿ‡ú|åÿ/ôÿ=¸G£üúÿÓËæùGô_ôêüß_Õ¥P÷SÿLBÄ?iþ,ϳüêÈDÊy;"™e\?·ûäE7¨;ˆ‹‡©sÁþ±L@­ZüÄm4 þË#%öªŠÂ)40)*ÿšþþǹÝÔI I™ŸF·ÊÙVôh #%âQ³ßÌôjB »M¢Ï¡E˜SYˆ8ˆÛ,×g Ø+,€ƒþûö¦C¦Ò‚æ¨x¶æñ#.Öâ×ýÀä÷² ƒ¢îÇ‘^A‰:Õó»0ÉæfØÝ@„#Ì%*ãþU•Êlé·üiÙ\¾ÅŸÙ»Æøyö¡ÃÉvǧ‡¿„eÔ«jÿ݆떅 ¥&P"ƾrÿïUËrž#.ð7Ï_û«u”a:X˜„Ès+u‘ž#6Ù™ýþ.ÀÀ7µ*jH†þ”¦xii”Qš]d*ši‚—eaËœTÁŒ0ÙÿŠeTñhÞ¶ñïÕ¥ƒpvŒîm©TœYnœ44¼BÒÙl`…ÕÁËsO6e7ª¨5mÚ8øq훓Mmƶ9T¨¨ëÌFdMmT˜I†qx“Ý,ØY.䃆5¨mõyõx*ŧ7ŠFÎîs¢kCºFêâ ¬#y{¢ï4êÈh2ùÃá’f´Øäì¹a²…qS1a ïH²F#¸yí‹ÈdŒ¸ÐŽH?F:oÌÌü4ÃÃ)×Ц­ë^EúîÞK¨ŒëN‘±£\-˜ÑNàS4 '>:`«é”ßw´ÿJ±·ý4#.pó‹À@ÄžGßF;tk5SÞ’æ ш넞‰‡ gà w#6Hp,†#6¹^>`L³¬5¬R Eò™„ "IEq¸Ov˜]œ.fB¦æ<õ Ù3PEATV*AB“9wt¸¦cß·Y˜ÌÊ2 ¯kº\69‰¤U¥€ >È!§^²æF4?ícS9öɬצåU1Š"ü«Ç»­'_û6Ä+W] 扄8uîKºƒxteæ߶}C3¿¾z„g,r.;À}²“½©½Ç0À×–f­ÜT9†P^]*zgâ_§Æ³ò8ÎŽQHÔ¼=‰ #6@C&9›Ò’#.³QÁOª‹#.D'ÒáG½\áUò»µŠšP®›CGݼòöœ²áž˜¾¦ÕÍ-ø­¾v챯¤ƒ[êk˜Ø´|nmcãm½(ÕìµoSEªMAj½óZåUìÞÝy»¶ë€]#6.æäQ‰#. ©‘’| P?ç!xnãdN2Apã'PQ±Ôí±s¼p]º¡f!‘OVݤ—¿š7áUÁbÇá*J9…¨H{ÿî°÷cÍÔ¼(5É@$fáÌR¿æû'wØÊ=<ÑÜŽ§ÛÈ_.EúØqPôÇX¡ÿ’#"‹(]¨î;µ#D”)Qb(ÁmLÍtÖêÕÙjûËf¤ÅÍh é! H¤€ £þßÃ3ÏëÿÏئ¨¤"Žþ~˜™áã(ø{fYr0Ûm‹CòNÀ.!xN¦ çå,A‘^#y;³9ø¾Šÿѵú½gþs(ž?l-A!ñÿÔ¥ÝóG#%‰#%(ö#6”CÛ¢ OùI[¥BY=‹”+¨›4ÃÔkéýÕsø]¯üžB_Fœ*ÀN#.ÿ6pŸñäÑÎJíâqTE3‚o¦«…ÆY̘wÈâfÓ§m3 ÊÊÇðç,Má†/-„±¿Ñ8¨–¼­§0aw<}8fJÃ$É o§‚ì]aðx`HŠ$Y@zõnÒ=®Ù i„ÿ~éŽ1éÿµ^#.Jz(ÎLPÛæcè–ªÆ"ÿ“â|xã‡ü†œgê?I¼Ëò~ÿð"‰ÿü]ÉáB@ä&öÐ +#<== +#-----BEGIN PGP SIGNATURE-----\n\niQIzBAABCgAdFiEEivIt5aBoIuNHTzxwSbTGfAUneqoFAl3aW3cACgkQSbTGfAUn\neqruqA//Y9oJ46ZR8W7YB/e45bfrYxGbN7NnkvkwSPNziObYur+n1QpQEOaPTn/U\n5kFtPWHXRJzaG/A9poKn7pl1Xd7Edcu1aalfoEazZbuD37VOxIp9lnrefCAeICqj\nGv0SD96Zac91CbA+b20Q4xnqxKMi3LSI4NPjfFGy62FkSk3MS4p6Rdp0/WAKwwNj\nw7WEjQCNmLb37z+FGSzXg28aljYeteBZEthsVmGJ5QqVwMBwgj2+y5FOTzFfxmqB\nrWgjFYS0l85kgYRZv9yzdNmFs5SScwafwpT8Xmdr49tFn/+0LxXyRxX+rdODgrpV\nY4EOiQz0fd6mMMnaTDXlLSXls3JyVYmbTjeNL/9gcHmnStzJ851CJQfyQg7A+JoC\nc7nz0HbiFyTgB+PUZr1OhGj3A7287o8XQ0tqR3oa7jXIOX0OynrGplMQKr++0jE1\nBgKzjLoE9CTbjkQfICLG+aUy3S1ZyDk/BcO+5+Ytbru+qXuDsIgAdVosMfNSv9jJ\nXvOINsbRMekdejYMZv8fIkn5OEjCFHVhNpobEsCb768bjB3p7alQGECBvjHCm6dy\nXZPzl9cBMWIXcBjPTS+GZj+PIXGcu76pbsx6HBHWf+uJ+4xgOsUCVu//0AV09jvA\n0MjtLWwQ8mdRH6Wt4hsp4HKtSvQrhmljf2OnuYBgaFmcdJkN1zI=\n=C0oT\n-----END PGP SIGNATURE-----\n diff --git a/rtems/hello/wscript b/rtems/hello/wscript new file mode 100644 index 0000000..aa9c93a --- /dev/null +++ b/rtems/hello/wscript @@ -0,0 +1,36 @@ + +# +# Hello world Waf script +# +from __future__ import print_function + +rtems_version = "6" + +try: + import rtems_waf.rtems as rtems +except: + print('error: no rtems_waf git submodule') + import sys + sys.exit(1) + +def init(ctx): + rtems.init(ctx, version = rtems_version, long_commands = True) + +def bsp_configure(conf, arch_bsp): + # Add BSP specific configuration checks + pass + +def options(opt): + rtems.options(opt) + +def configure(conf): + rtems.configure(conf, bsp_configure = bsp_configure) + +def build(bld): + rtems.build(bld) + + bld(features = 'c cprogram', + target = 'hello.exe', + cflags = '-g -O2', + source = ['hello.c', + 'init.c']) diff --git a/rtems/hello_posix/doit b/rtems/hello_posix/doit new file mode 100755 index 0000000..67cadb7 --- /dev/null +++ b/rtems/hello_posix/doit @@ -0,0 +1,3 @@ +./waf configure --rtems=/root/development/rtems/5 --rtems-bsp=sparc/leon3 --rtems-version=5 --show-commands +./waf +/root/development/rtems/5/bin/rtems-run --rtems-bsps=leon3-sis build/sparc-rtems5-leon3/hello.exe diff --git a/rtems/hello_posix/hello.c b/rtems/hello_posix/hello.c new file mode 100644 index 0000000..3de4714 --- /dev/null +++ b/rtems/hello_posix/hello.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include + +void *POSIX_Init() +{ + printf("\nHello, POSIX world! %d\n", 42); + rtems_stack_checker_report_usage(); + exit(0); +} diff --git a/rtems/hello_posix/init.c b/rtems/hello_posix/init.c new file mode 100644 index 0000000..e03bb42 --- /dev/null +++ b/rtems/hello_posix/init.c @@ -0,0 +1,11 @@ +void *POSIX_Init(); + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_MAXIMUM_POSIX_THREADS 10 +#define CONFIGURE_POSIX_INIT_THREAD_TABLE +#define CONFIGURE_STACK_CHECKER_ENABLED +#define CONFIGURE_INIT + +#include diff --git a/rtems/hello_posix/rtems_waf/README b/rtems/hello_posix/rtems_waf/README new file mode 100644 index 0000000..29db6ef --- /dev/null +++ b/rtems/hello_posix/rtems_waf/README @@ -0,0 +1,389 @@ +RTEMS Waf +~~~~~~~~~ + +RTEMS Waf is a module that supports the Waf build system and RTEMS. The module +is integrated into a project or library proividing Waf build support to create +RTEMS libraries or executables. + +RTEMS Waf provides: + +* Checking for a valid RTEMS installation of tools and kernel. + +* Support for multiple versions of RTEMS. + +* Support to build a number of BSPs at once. + +* Support for the RTEMS tools and kernel being installed under a shared or + separate prefixes [2]. + +* Flexible integration that allows easy project specific specialization. + +* Support to check which features RTEMS is built with. + +* Support for BSP compiler and linker flags. The flags are separated into their + various types to allow flexible options management in a project. + +* Support to list the available architectures and BSPs. + +* Additional support for creating root file systems for RTEMS targets. + +Bugs +---- + +Please report issues to the RTEMS Users list mailto:users@rtems.org or raise a +ticket in RTEMS's Trac under https://devel.rtems.org/. + +Feedback is always welcome. + +Waf +--- + +You can find the Waf project here: + + https://waf.io/ + +Waf does not come as a package in distrubitions so you need to download and +install it. + +1. Waf is a Python program so you will also need to have a current Python + installed and accessible via your environment's path. + +2. Download the latest signed Waf executable file from the Waf website. + +3. Place the waf executable in a personal directory that is in your path, for + example $HOME/bin. Modify the file's permissions so it can be executed: + + $ chmod +x $HOME/bin/waf + +Git Submodule +------------- + +RTEMS Waf can be used as a git submodule. This lets a number of projects share +the common waf support. + +1. Add RTEMS Waf a git submodule to your project: + + $ cd my_project + $ git submodule add git://git.rtems.org/rtems_waf.git rtems_waf + +2. Initialize the submodule(s) for your project: + + $ git submodule init + +3. Update the RTEMS Waf submodule: + + $ git submodule update rtems_waf + + Note, the `rtems_waf` submodule name is provided as some projects may have + other submodules you may not wish to update. + +4. When submodules are added they are headless which means they are not on a + current branch. Switch to a branch: + + $ cd rtems_waf + $ git checkout master + $ cd .. + + Note, you can replace `master` in the `checkout` above with any valid branch + in the RTEMS Waf repo. + +5. Update the RTEMS Waf submodule to the latest version on the selected branch: + + $ cd rtems_waf + $ git pull + $ cd .. + +6. Check the new submodule is part of your project and ready to be committed: + + $ git status + + The `rtems_waf` module will be listed as `modified`. + +7. Commit the change by adding it to your staged files: + + $ git add rtems_waf + + When ready commit: + + $ git commit + + Review the changes and if they are correct push them: + + $ git log -p + $ git push + +The RTEMS Waf module is updated from time to time as new features are added or +changes happen in waf. To update a project's existing RTEMS Waf submodule +perform steps 5. to 7. + +Project Instructions +-------------------- + +Create a README.waf file in your project and add the Waf installation section, +your project specific options and the following steps. These steps are for +RTEMS 5, change for the specific version of RTEMS your project supports. + +1. Build or install the tools. In this example the path is the personal prefix + of $HOME/development/rtems/5 [1]. + +2. Build and install the RTEMS Board Support Packages you want to use. In this + example separate tools and kernel prefixes are used [2]. The kernel path is + $HOME/development/rtems/bsps/5. + +3. Unpack this package somewhere, anywhere on your disk and change into the top + level directory. + +4. Populate the git submodule: + + $ git submodule init + $ git submodule update rtems_waf + +5. Configure with your specific settings. In this case the path to the tools + and the kernel are separate and provided on the command line. Your + envronment's path variable does not need to changed [3]. We limit the build + to 'sparc/erc32' BSP: + + $ waf configure --rtems=$HOME/development/rtems/bsps/5 \ + --rtems-tools=$HOME/development/rtems/5 \ + --rtems-bsps=sparc/erc32 + + You can use '--rtems-archs=sparc,i386' or + '--rtems-bsps=sparc/erc32,i386/pc586' to build more than BSP at a time. + +6. Build: + + $ waf + +An RTEMS Waf Project +-------------------- + +RTEMS Waf provides a base to build RTEMS application. + +Waf provides a build system framework. You can use waf in your project by +simply prooviding a list of files you wish to build and link to create an +executable or you can use waf as framework which is integrated into your +project to become is build system. + +Importing RTEMS Waf +~~~~~~~~~~~~~~~~~~~ + +Using RTEMS Waf as a submodule means it may not be present if the submodules +have not been initialized and updated. This results in a Python error. The +following import is recommended so a user friendly error is reported: + + from __future__ import print_function + + try: + import rtems_waf.rtems as rtems + except: + print('error: no rtems_waf git submodule; see README.waf', file = stderr) + import sys + sys.exit(1) + +Initialization +~~~~~~~~~~~~~~ + +The `wscript` `init()` function is called early in waf's processing. The RTEMS +Waf's `init()` call lets you provide: + +1. Filters + +2. RTEMS Version + +3. Long command line control + +4. Waf BSP initialization hook + +A example call to RTEMS Waf's `init()` is: + + rtems_version = "5" + + def init(ctx): + rtems.init(ctx, version = rtems_version, long_commands = True) + +Filters provide a way to control the tools, architectures and BSPs your project +supports. RTEMS Waf scans and finds all installed RTEMS tool sets and BSPs and +your project may only support a limited number of these. Filtering provides a +way for your project to control what RTEMS Waf accepts and rejects when +automatically scanning the installed tools and RTEMS kernels. A filter is a +Python dictionary and the following example will accept `arm` and `sparc` tool +chains and filtering out the `bfin` tool chain. The filter will only build the +`arm` acrhitecture and will accept all BSPs except ones starting with `lpc` if +they are installed: + + my_filter = { 'tools': { 'in': ['arm', 'sparc'], 'out': ['bfin'] }, + 'arch': { 'in': ['arm'], 'out': [] }, + 'bsps': { 'in': [], 'out': ['lpc.*'] } } + +There are three (3) filters the `tools`, `archs` and `bsps` and each of these +filter types has an `in` and `out` list. The `in` and `out` items are Python +regular expressions. + +The RTEMS Version lets your project provide the default RTEMS version. This can +be overridden by the configure option `--rtems-version`. + +Long commands is specific to Windows and provides support for tool command +lines that are longer than the standard Windows command shell's limit. The +support is based on the example available in Waf extra's. + +The Waf BSP initialization hook is a function called as part of the RTEMS Waf's +`init()` call with the Waf environment and list of BSP contexts. This hook can +be used to provide specialized BSP support. + +Options +~~~~~~~ + +The `wscript` `option()` function is called to collect command line options for +Waf argument processing. + +A example call to RTEMS Waf's `options()` is: + + def options(opt): + rtems.options(opt) + +Configure +~~~~~~~~~ + +The `wscript` `configure()` function is called when Waf is configuring a +build. The RTEMS Waf's `configure()` lets you provide: + +1. Waf BSP configure hook + +A example call to RTEMS Waf's `configure()` is: + + def configure(conf): + rtems.configure(conf) + +The BSP configure hook is called at end of a BSP's configuration. The BSP's +`conf` variable and the `arch/bsp` are passed as arguments. The `arch/bsp` is +the RTEMS standard for specifing a BSP, for example `sparc/erc32`. The BSP +configure support can be used to check a BSP for header, check an RTEMS feature +is present for a specific BSP or add per BSP build variant support: + + def bsp_configure(conf, arch_bsp): + conf.check(header_name = "dlfcn.h", features = "c") + conf.check(header_name = "rtems/pci.h", features = "c", mandatory = False) + if not rtems.check_posix(conf): + conf.fatal("POSIX is disabled; configure RTEMS with --enable-posix") + env = conf.env.derive() + for builder in builders: + ab = conf.env.RTEMS_ARCH_BSP + variant = ab + "-" + builder + conf.msg('Configure variant: ', variant) + conf.setenv(variant, env) + build_variant_bsp_configure(conf, arch_bsp) + conf.setenv(ab) + +Build +~~~~~ + +The `wscript` `build()` function is called when Waf is asking what to +build. + +A example call to RTEMS Waf's `build()` is: + + def build(bld): + rtems.build(bld) + bld(features = 'c cprogram', + target = 'hello.exe', + source = ['hello.c']) + +In this example the C source file `hello.c` is compiled and linked to create +the RTEMS executable `hello.exe`. The build is within the context of the BSP. + +Example +~~~~~~~ + +Save the following as `wscript`: + + # + # Example Waf build script for RTEMS + # + # To configure, build and run: + # + # $ waf configure --rtems=$HOME/development/rtems/build/5 \ + # --rtems-tools=$HOME/development/rtems/5 \ + # --rtems-bsps=sparc/erc32 + # $ waf + # $ $HOME/development/rtems/5/bin/sparc-rtems5-run \ + # ./build/sparc-rtems5-erc32/hello.exe + # + # You can use '--rtems-archs=sparc,i386' or + # '--rtems-bsps=sparc/erc32,i386/pc586' to build for more than one BSP at a + # time. + # + + from __future__ import print_function + + rtems_version = "5" + + try: + import rtems_waf.rtems as rtems + except: + print('error: no rtems_waf git submodule; see README.waf', file = stderr) + import sys + sys.exit(1) + + def init(ctx): + rtems.init(ctx, version = rtems_version, long_commands = True) + + def options(opt): + rtems.options(opt) + + def configure(conf): + rtems.configure(conf) + + def build(bld): + rtems.build(bld) + bld.env.CFLAGS += ['-O2','-g'] + bld(features = 'c cprogram', + target = 'hello.exe', + source = ['hello.c']) + +Save the example C hello world as `hello.c`: + + #include + #include + #include + + rtems_task Init(rtems_task_argument ignored) { + printf("Hello World\n"); + exit(0); + } + + /* configuration information */ + #include + #define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER + #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + #define CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM + #define CONFIGURE_RTEMS_INIT_TASKS_TABLE + #define CONFIGURE_MAXIMUM_TASKS 1 + #define CONFIGURE_INIT + #include + +-- + +[1] A personal prefix is private to you and located where you have enough disk + space to complete an RTEMS installation. We often show this as your home + directory ($HOME) because it works on machines you may not have root access + to and cannot configure. We recommend you never work as root on a machine + you control. + +[2] RTEMS supports shared or separate tool and kernel prefixes. The prefix is + the path given to the tools and kernel when building and is the path the + tools or kernel are installed into when you run the install phase of a + build. A shared tools and kernel prefix is often used with releases because + the tools and kernel in a release are matched and do not change. Separate + tools and kernel paths can be used if you have a common tool set with + changing kernel versions. This tends to happen when you are testing kernel + patches or changes. + +[3] It is good practice to keep your environment as empty as possible. Using + the environment to set paths to tools or specific values to configure and + control builds is dangerous because settings can leak between different + builds and change what you expect or not been and seen and lost. The waf + tool used here lets you specify on the command line the tools and RTEMS + paths and this is embedded in waf's configuration information. If you have + a few source trees working at any one time with different tool sets or + configurations you can easly move between them safe in the knowledge that + one build will not affect another. diff --git a/rtems/hello_posix/rtems_waf/__init__.py b/rtems/hello_posix/rtems_waf/__init__.py new file mode 100644 index 0000000..e60cc4d --- /dev/null +++ b/rtems/hello_posix/rtems_waf/__init__.py @@ -0,0 +1,6 @@ +# Copyright 2013 Chris Johns (chrisj@rtems.org) +# +# This file's license is 2-clause BSD as in this distribution's LICENSE.2 file. +# + +__all__ = ['rtems', 'pkgconfig'] diff --git a/rtems/hello_posix/rtems_waf/dl.py b/rtems/hello_posix/rtems_waf/dl.py new file mode 100644 index 0000000..ec5b238 --- /dev/null +++ b/rtems/hello_posix/rtems_waf/dl.py @@ -0,0 +1,118 @@ +# +# RTEMS Project (https://www.rtems.org/) +# +# Copyright (c) 2018 Chris Johns . All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os + +def _syms_rule(tsk): + ''' + A rule handler so 'no_errcheck_out' can be set. This avoids the + erronous duplicate output error from waf (2.0.14 and later). + ''' + setattr(tsk, 'no_errcheck_out', True) + src = tsk.inputs[0].abspath() + tgt = tsk.outputs[0].abspath() + cmd = '%s -e -C %s -c "%s" -o %s %s' % (' '.join(tsk.env.RTEMS_SYMS), + ' '.join(tsk.env.CC), + ' '.join(tsk.env.CFLAGS), + tgt, + src) + return tsk.exec_command(cmd) + +def syms(ctx, target, source): + ''' + Create a symbols object file from a base kernel image. The object + can be linked to the file executable providing it with a symbol + table. + + The created object file is read and available in a 'use' attribute + of the 'cprogram' build. + + :param ctx: Waf build context + :param target: The target object file to create and read + :param source: The kernel base image to generate the symbol table of + ''' + tgt = ctx.path.find_or_declare(target) + ctx(rule = _syms_rule, + target = tgt, + source = source, + color = 'CYAN') + ctx.read_object(tgt) + +def _strip_rule(tsk): + ''' + A rule handler so 'no_errcheck_out' can be set. We need this because + 'ranlib' takes only a single argument, the archive is rewritten so it + will appear in 2 outputs. + ''' + setattr(tsk, 'no_errcheck_out', True) + src = tsk.inputs[0].abspath() + tgt = tsk.outputs[0].abspath() + cmd = '%s -d -o %s %s' % (' '.join(tsk.env.STRIP), tgt, src) + return tsk.exec_command(cmd) + +def strip_debug_info(ctx, *k, **kw): + ''' + Strip the source object file or archive of debug information + creating a new archive in the build directory. + + :param ctx: Waf build context + :param target: The stripped target archive or object file + :param source: The source target or acthive file to strip + ''' + if 'source' not in kw: + ctx.fatal('No source in strip') + if 'target' not in kw: + ctx.fatal('No target in strip') + source = kw['source'] + target = kw['target'] + if 'name' in kw: + name = kw['name'] + else: + if not isinstance(source, str): + ctx.fatal('No name and source is not a path') + name = 'strip-%s' % (os.path.basename(source)) + print(type(source), str(source), target) + ctx(rule = _strip_rule, + name = name, + target = target, + source = source, + color = 'CYAN') + +def _ranlib_rule(tsk): + ''' + A rule handler so 'no_errcheck_out' can be set. We need this because + 'ranlib' takes only a single argument, the archive is rewritten so it + will appear in 2 outputs. + ''' + setattr(tsk, 'no_errcheck_out', True) + tgt = tsk.inputs[0].abspath() + cmd = '%s -t %s' % (' '.join(tsk.env.RANLIB), tgt) + return tsk.exec_command(cmd) + +def ranlib(ctx, lib): + ctx(rule = _ranlib_rule, + name = 'ranlib-%s' % (lib), + source = lib) diff --git a/rtems/hello_posix/rtems_waf/gccdeps.py b/rtems/hello_posix/rtems_waf/gccdeps.py new file mode 100644 index 0000000..bfabe72 --- /dev/null +++ b/rtems/hello_posix/rtems_waf/gccdeps.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2008-2010 (ita) + +""" +Execute the tasks with gcc -MD, read the dependencies from the .d file +and prepare the dependency calculation for the next run. +This affects the cxx class, so make sure to load Qt5 after this tool. + +Usage:: + + def options(opt): + opt.load('compiler_cxx') + def configure(conf): + conf.load('compiler_cxx gccdeps') +""" + +import os, re, threading +from waflib import Task, Logs, Utils, Errors +from waflib.Tools import c_preproc +from waflib.TaskGen import before_method, feature + +lock = threading.Lock() + +gccdeps_flags = ['-MD'] +if not c_preproc.go_absolute: + gccdeps_flags = ['-MMD'] + +# Third-party tools are allowed to add extra names in here with append() +supported_compilers = ['gcc', 'icc', 'clang'] + +def scan(self): + if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: + return super(self.derived_gccdeps, self).scan() + nodes = self.generator.bld.node_deps.get(self.uid(), []) + names = [] + return (nodes, names) + +re_o = re.compile(r"\.o$") +re_splitter = re.compile(r'(?= 0: + return line[sep_idx + 2:] + else: + return line + +def path_to_node(base_node, path, cached_nodes): + # Take the base node and the path and return a node + # Results are cached because searching the node tree is expensive + # The following code is executed by threads, it is not safe, so a lock is needed... + if getattr(path, '__hash__'): + node_lookup_key = (base_node, path) + else: + # Not hashable, assume it is a list and join into a string + node_lookup_key = (base_node, os.path.sep.join(path)) + try: + lock.acquire() + node = cached_nodes[node_lookup_key] + except KeyError: + node = base_node.find_resource(path) + cached_nodes[node_lookup_key] = node + finally: + lock.release() + return node + +def post_run(self): + if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: + return super(self.derived_gccdeps, self).post_run() + + name = self.outputs[0].abspath() + name = re_o.sub('.d', name) + try: + txt = Utils.readf(name) + except EnvironmentError: + Logs.error('Could not find a .d dependency file, are cflags/cxxflags overwritten?') + raise + #os.remove(name) + + # Compilers have the choice to either output the file's dependencies + # as one large Makefile rule: + # + # /path/to/file.o: /path/to/dep1.h \ + # /path/to/dep2.h \ + # /path/to/dep3.h \ + # ... + # + # or as many individual rules: + # + # /path/to/file.o: /path/to/dep1.h + # /path/to/file.o: /path/to/dep2.h + # /path/to/file.o: /path/to/dep3.h + # ... + # + # So the first step is to sanitize the input by stripping out the left- + # hand side of all these lines. After that, whatever remains are the + # implicit dependencies of task.outputs[0] + txt = '\n'.join([remove_makefile_rule_lhs(line) for line in txt.splitlines()]) + + # Now join all the lines together + txt = txt.replace('\\\n', '') + + val = txt.strip() + val = [x.replace('\\ ', ' ') for x in re_splitter.split(val) if x] + + nodes = [] + bld = self.generator.bld + + # Dynamically bind to the cache + try: + cached_nodes = bld.cached_nodes + except AttributeError: + cached_nodes = bld.cached_nodes = {} + + for x in val: + + node = None + if os.path.isabs(x): + node = path_to_node(bld.root, x, cached_nodes) + else: + # TODO waf 1.9 - single cwd value + path = getattr(bld, 'cwdx', bld.bldnode) + # when calling find_resource, make sure the path does not contain '..' + x = [k for k in Utils.split_path(x) if k and k != '.'] + while '..' in x: + idx = x.index('..') + if idx == 0: + x = x[1:] + path = path.parent + else: + del x[idx] + del x[idx-1] + + node = path_to_node(path, x, cached_nodes) + + if not node: + raise ValueError('could not find %r for %r' % (x, self)) + if id(node) == id(self.inputs[0]): + # ignore the source file, it is already in the dependencies + # this way, successful config tests may be retrieved from the cache + continue + nodes.append(node) + + Logs.debug('deps: gccdeps for %s returned %s', self, nodes) + + bld.node_deps[self.uid()] = nodes + bld.raw_deps[self.uid()] = [] + + try: + del self.cache_sig + except AttributeError: + pass + + Task.Task.post_run(self) + +def sig_implicit_deps(self): + if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: + return super(self.derived_gccdeps, self).sig_implicit_deps() + try: + return Task.Task.sig_implicit_deps(self) + except Errors.WafError: + return Utils.SIG_NIL + +def wrap_compiled_task(classname): + derived_class = type(classname, (Task.classes[classname],), {}) + derived_class.derived_gccdeps = derived_class + derived_class.post_run = post_run + derived_class.scan = scan + derived_class.sig_implicit_deps = sig_implicit_deps + +for k in ('c', 'cxx'): + if k in Task.classes: + wrap_compiled_task(k) + +@before_method('process_source') +@feature('force_gccdeps') +def force_gccdeps(self): + self.env.ENABLE_GCCDEPS = ['c', 'cxx'] + +def configure(conf): + # in case someone provides a --enable-gccdeps command-line option + if not getattr(conf.options, 'enable_gccdeps', True): + return + + global gccdeps_flags + flags = conf.env.GCCDEPS_FLAGS or gccdeps_flags + if conf.env.CC_NAME in supported_compilers: + try: + conf.check(fragment='int main() { return 0; }', features='c force_gccdeps', cflags=flags, msg='Checking for c flags %r' % ''.join(flags)) + except Errors.ConfigurationError: + pass + else: + conf.env.append_value('CFLAGS', flags) + conf.env.append_unique('ENABLE_GCCDEPS', 'c') + + if conf.env.CXX_NAME in supported_compilers: + try: + conf.check(fragment='int main() { return 0; }', features='cxx force_gccdeps', cxxflags=flags, msg='Checking for cxx flags %r' % ''.join(flags)) + except Errors.ConfigurationError: + pass + else: + conf.env.append_value('CXXFLAGS', flags) + conf.env.append_unique('ENABLE_GCCDEPS', 'cxx') + +def options(opt): + raise ValueError('Do not load gccdeps options') + diff --git a/rtems/hello_posix/rtems_waf/pkgconfig.py b/rtems/hello_posix/rtems_waf/pkgconfig.py new file mode 100644 index 0000000..382f4dc --- /dev/null +++ b/rtems/hello_posix/rtems_waf/pkgconfig.py @@ -0,0 +1,84 @@ +# Copyright 2013 Chris Johns (chrisj@rtems.org) +# +# This file's license is 2-clause BSD as in this distribution's LICENSE.2 file. +# + +# +# Pkg-config in python. Pkg-config as a tool is a good idea how-ever the +# implementation is really Linux (or Unix) based and requires a couple of +# packages that it should not. If it was implemented with all parts included it +# would be portable and I suspect useful to others on platforms other than +# Linux or Unix equivs that contain the required packages. +# +import re + +class error(Exception): + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return self.msg + +class package: + def __init__(self, file = None): + self.defines = {} + self.fields = {} + if file: + self.load(file) + + def load(self, file): + f = open(file) + tm = False + for l in f.readlines(): + l = l[:-1] + hash = l.find('#') + if hash >= 0: + l = l[:hash] + if len(l): + d = 0 + define = False + eq = l.find('=') + dd = l.find(':') + if eq > 0 and dd > 0: + if eq < dd: + define = True + d = eq + else: + define = False + d = dd + elif eq >= 0: + define = True + d = eq + elif dd >= 0: + define = False + d = dd + if d > 0: + lhs = l[:d].lower() + rhs = l[d + 1:] + + if tm: + print('define: ' + str(define) + ', lhs: ' + lhs + ', ' + rhs) + + if define: + self.defines[lhs] = rhs + else: + self.fields[lhs] = rhs + + def get(self, label): + if label.lower() not in self.fields: + raise error('Label not found: ' + label) + mre = re.compile('\$\{[^\}]+\}') + s = self.fields[label.lower()] + expanded = True + tm = False + while expanded: + expanded = False + if tm: + print('pc:get: "' + s + '"') + ms = mre.findall(s) + for m in ms: + mn = m[2:-1] + if mn.lower() in self.defines: + s = s.replace(m, self.defines[mn.lower()]) + expanded = True + return s diff --git a/rtems/hello_posix/rtems_waf/rootfs.py b/rtems/hello_posix/rtems_waf/rootfs.py new file mode 100644 index 0000000..6fef0e4 --- /dev/null +++ b/rtems/hello_posix/rtems_waf/rootfs.py @@ -0,0 +1,143 @@ +# +# RTEMS Project (https://www.rtems.org/) +# +# Copyright (c) 2017 Chris Johns . All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os + +def join(*paths): + path = '' + for p in paths: + path = os.path.join(path, str(p)) + return path + +def copy(ctx, name, root, target, source): + '''Copy a file from the source to the target.''' + if isinstance(target, str): + target = ctx.path.make_node(target) + #print('copy: name=%s source=%s target=%s' % (name, source, target)) + ctx(rule = 'cp ${SRC} ${TGT}', + name = name, + source = source, + target = target) + +def tar(ctx, name, root, target, source, depends_on): + #print('tar: name=%s root=%s target=%r source=%r' % (name, root, target, source)) + ctx(rule = 'tar -C %s -cf ${TGT} .' % (root), + name = name, + target = target, + source = source, + root = join(ctx.path.get_bld(), root), + depends_on = depends_on, + color = 'CYAN') + +def bin2c(ctx, name, target, source): + ctx(rule = '${RTEMS_BIN2C} ${SRC} ${TGT}', + name = name, + target = target, + source = source, + color = 'PINK') + +def build(ctx, name, root, files): + """The files are truples of the name, source and target files to put in the tar + file. The truple is (name, src, dst). The src is the absolute path to the + source and the dst is the path on the target. + + The tar file will contain the files defined by the dst paths. These are + copied into the build path under the tar file's root path. Make sure the + desination paths are relative to the root of the tar file. + + For example: + import rtems_waf.rootfs as rtems_rootfs + tar_files = [('shell-init', ''shell-init', 'shell-init'), + ('rc-conf', 'rc.conf', 'etc/rc.conf')] + rtems_rootfs.build(ctx, 'fs-root', 'rootfs', tar_files) + """ + # + # The files must be a list of tuples. + # + if not isinstance(files, list): + ctx.fatal('rootfs build files is not a list') + + root_abspath = join(ctx.path.get_bld().abspath(), root) + + for f in files: + # + # Check each item in the list is a tuple with 3 elements. + # + if not isinstance(f, tuple): + ctx.fatal('rootfs build file is not a tuple') + if len(f) != 3: + ctx.fatal('rootfs build file tuple has 3 items (name, src, dst): %s' % (str(f))) + # + # Copy the file as a build task. The file is copied to the tar file's + # root. + # + #print(']]', ctx.path.make_node(join(root, f[2])).get_bld()) + if isinstance(f[1], str): + source = ctx.path.make_node(f[1]).get_src() + else: + source = f[1] + copy(ctx, + name = f[0], + root = root, + target = ctx.path.make_node(join(root, f[2])).get_bld(), + source = source) + + ctx.add_group() + + # + # Tar build task. + # + tar(ctx, + name = name + '-tar', + root = join(ctx.path.get_bld(), root), + target = name + '.tar', + source = [join(root, f[2]) for f in files], + depends_on = [f[0] for f in files]) + + ctx.add_group() + + # + # Binary to C build task. It converts the tar file to a C file. This uses + # the RTEMS Tools Project's `bin2c` command. + # + bin2c(ctx, + name = name, + target = name + '-tar.c', + source = name + '.tar') + + ctx.add_group() + + ctx.objects(features = 'c', + target = name + '-obj', + source = name + '-tar.c') + +def build_from_src_root(ctx, name, root): + root_path = ctx.path.make_node(root) + if not root_path.exists(): + ctx.fatal('tar root not found: %s' % (root_path)) + sources = [s.path_from(root_path) for s in root_path.ant_glob('**')] + build(ctx, name, root, [('%s-%s' % (name, os.path.basename(s)), + join(root, s), s) for s in sources]) diff --git a/rtems/hello_posix/rtems_waf/rtems.py b/rtems/hello_posix/rtems_waf/rtems.py new file mode 100644 index 0000000..55ed02b --- /dev/null +++ b/rtems/hello_posix/rtems_waf/rtems.py @@ -0,0 +1,969 @@ + +# Copyright 2012-2016 Chris Johns (chrisj@rtems.org) +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. + +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from __future__ import print_function + +# +# RTEMS support for applications. +# + +import copy +import os +import os.path +from . import pkgconfig +import re +import subprocess +import sys + +rtems_default_version = None +rtems_filters = None +rtems_long_commands = False + +windows = os.name == 'nt' or sys.platform in ['msys', 'cygwin'] + +def options(opt): + opt.add_option('--rtems', + default = None, + dest = 'rtems_path', + help = 'Path to an installed RTEMS (defaults to prefix).') + opt.add_option('--rtems-tools', + default = None, + dest = 'rtems_tools', + help = 'Path to RTEMS tools (defaults to path to installed RTEMS).') + opt.add_option('--rtems-version', + default = None, + dest = 'rtems_version', + help = 'RTEMS version (default is derived from prefix).') + opt.add_option('--rtems-archs', + default = 'all', + dest = 'rtems_archs', + help = 'List of RTEMS architectures to build.') + opt.add_option('--rtems-bsps', + default = 'all', + dest = 'rtems_bsps', + help = 'List of BSPs to build.') + opt.add_option('--show-commands', + action = 'store_true', + default = False, + dest = 'show_commands', + help = 'Print the commands as strings.') + +def init(ctx, filters = None, version = None, long_commands = False, bsp_init = None): + global rtems_filters + global rtems_default_version + global rtems_long_commands + + # + # Set the RTEMS filter to the context. + # + rtems_filters = filters + + # + # Set the default version, can be overridden. + # + rtems_default_version = version + + # + # Set the long commands option. + # + rtems_long_commands = long_commands + + env = None + contexts = [] + try: + import waflib.Options + import waflib.ConfigSet + + # + # Load the configuation set from the lock file. + # + env = waflib.ConfigSet.ConfigSet() + env.load(waflib.Options.lockfile) + + # + # Check the tools, architectures and bsps. + # + rtems_version, rtems_path, rtems_tools, archs, arch_bsps = \ + check_options(ctx, + env.options['prefix'], + env.options['rtems_tools'], + env.options['rtems_path'], + env.options['rtems_version'], + env.options['rtems_archs'], + env.options['rtems_bsps']) + + # + # Update the contexts for all the bsps. + # + from waflib.Build import BuildContext, CleanContext, \ + InstallContext, UninstallContext + for x in arch_bsps: + for y in (BuildContext, CleanContext, InstallContext, UninstallContext): + name = y.__name__.replace('Context','').lower() + class context(y): + cmd = name + '-' + x + variant = x + contexts += [context] + + # + # Transform the command to per BSP commands. + # + commands = [] + for cmd in waflib.Options.commands: + if cmd in ['build', 'clean', 'install', 'uninstall']: + for x in arch_bsps: + commands += [cmd + '-' + x] + else: + commands += [cmd] + waflib.Options.commands = commands + except: + pass + + if bsp_init: + bsp_init(ctx, env, contexts) + +def test_application(more = []): + code = ['#include '] + code += more + code += ['void Init(rtems_task_argument arg) { (void)arg; }'] + code += ['#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER'] + code += ['#define CONFIGURE_MAXIMUM_TASKS 1'] + code += ['#define CONFIGURE_RTEMS_INIT_TASKS_TABLE'] + code += ['#define CONFIGURE_INIT'] + code += ['#include '] + return os.linesep.join(code) + +def configure(conf, bsp_configure = None): + # + # Check the environment for any flags. + # + for f in ['CC', 'CXX', 'AS', 'LD', 'AR', 'LINK_CC', 'LINK_CXX', + 'CPPFLAGS', 'CFLAGS', 'CXXFLAGS', 'ASFLAGS', 'LINKFLAGS', 'LIB' + 'WFLAGS', 'RFLAGS', 'MFLAGS', 'IFLAGS']: + if f in os.environ: + conf.msg('Environment variable set', f, color = 'RED') + + # + # Handle the configurable commands options. + # + if conf.options.show_commands: + show_commands = 'yes' + else: + show_commands = 'no' + if rtems_long_commands and windows: + long_commands = 'yes' + else: + long_commands = 'no' + + rtems_version, rtems_path, rtems_tools, archs, arch_bsps = \ + check_options(conf, + conf.options.prefix, + conf.options.rtems_tools, + conf.options.rtems_path, + conf.options.rtems_version, + conf.options.rtems_archs, + conf.options.rtems_bsps) + + if rtems_tools is None: + conf.fatal('RTEMS tools not found.') + + _log_header(conf) + + conf.msg('RTEMS Version', rtems_version, 'YELLOW') + conf.msg('Architectures', ', '.join(archs), 'YELLOW') + + tools = {} + env = conf.env.derive() + conf.env.RTEMS_ARCH_BSP_LIST = arch_bsps + + for ab in arch_bsps: + conf.setenv(ab, env) + + conf.msg('Board Support Package (BSP)', ab, 'YELLOW') + + # + # Show and long commands support. + # + conf.env.SHOW_COMMANDS = show_commands + conf.env.LONG_COMMANDS = long_commands + + conf.msg('Show commands', show_commands) + conf.msg('Long commands', long_commands) + + arch = _arch_from_arch_bsp(ab) + bsp = _bsp_from_arch_bsp(ab) + + conf.env.ARCH_BSP = '%s/%s' % (arch.split('-')[0], bsp) + + conf.env.RTEMS_PATH = rtems_path + conf.env.RTEMS_VERSION = rtems_version + conf.env.RTEMS_ARCH_BSP = ab + conf.env.RTEMS_ARCH = arch.split('-')[0] + conf.env.RTEMS_ARCH_RTEMS = arch + conf.env.RTEMS_BSP = bsp + + tools = _find_tools(conf, arch, rtems_tools, tools) + for t in tools[arch]: + conf.env[t] = tools[arch][t] + + conf.load('gcc') + conf.load('g++') + conf.load('gas') + conf.load('gccdeps', tooldir = os.path.dirname(__file__)) + + # + # Get the version of the tools being used. + # + rtems_cc = conf.env.CC[0] + try: + import waflib.Context + out = conf.cmd_and_log([rtems_cc, '--version'], + output = waflib.Context.STDOUT) + except Exception as e: + conf.fatal('CC version not found: %s' % (e.stderr)) + # + # First line is the version + # + vline = out.split('\n')[0] + conf.msg('Compiler version (%s)' % (os.path.basename(rtems_cc)), + ' '.join(vline.split()[2:])) + + flags = _load_flags(conf, ab, rtems_path) + + cflags = _filter_flags('cflags', flags['CFLAGS'], + arch, rtems_path) + ldflags = _filter_flags('ldflags', flags['LDFLAGS'], + arch, rtems_path) + + conf.env.CFLAGS = cflags['cflags'] + conf.env.CXXFLAGS = cflags['cflags'] + conf.env.ASFLAGS = cflags['cflags'] + conf.env.WFLAGS = cflags['warnings'] + conf.env.RFLAGS = cflags['specs'] + conf.env.MFLAGS = cflags['machines'] + conf.env.IFLAGS = cflags['includes'] + conf.env.LINKFLAGS = cflags['cflags'] + ldflags['ldflags'] + conf.env.LIB = flags['LIB'] + conf.env.LIBPATH = ldflags['libpath'] + + conf.env.RTRACE_WRAPPER_ST = '-W %s' + + # + # Checks for various RTEMS features. + # + conf.check_cc(fragment = test_application(), + execute = False, + msg = 'Checking for a valid RTEMS BSP installation') + load_cpuopts(conf) + + # + # Add tweaks. + # + tweaks(conf, ab) + + # + # If the user has supplied a BSP specific configure function + # call it. + # + if bsp_configure: + bsp_configure(conf, ab) + + conf.setenv('', env) + + conf.env.RTEMS_TOOLS = rtems_tools + conf.env.ARCHS = archs + conf.env.ARCH_BSPS = arch_bsps + + conf.env.SHOW_COMMANDS = show_commands + conf.env.LONG_COMMANDS = long_commands + +def build(bld): + if bld.env.SHOW_COMMANDS == 'yes': + output_command_line() + if bld.env.LONG_COMMANDS == 'yes': + long_command_line() + +def load_cpuopts(conf): + options = ['RTEMS_DEBUG', + 'RTEMS_MULTIPROCESSING', + 'RTEMS_NEWLIB', + 'RTEMS_POSIX_API', + 'RTEMS_SMP', + 'RTEMS_NETWORKING'] + for opt in options: + enabled = check_cpuopt(conf, opt) + if enabled: + conf.env[opt] = 'Yes' + else: + conf.env[opt] = 'No' + +def check(conf, *k, **kw): + if 'fragment' not in kw: + kw['fragment'] = test_application() + conf.check(k, kw) + +def check_cc(conf, *k, **kw): + if 'fragment' not in kw: + kw['fragment'] = test_application() + conf.check_cc(*k, **kw) + +def check_lib_path(ctx, lib, libpath = [], mandatory = True): + lib_lib = 'lib%s.a' % (lib) + ctx.start_msg('Library %s' % (lib_lib)) + cmd = '%s %s %s -print-file-name=%s' % (' '.join(ctx.env.CC), + ' '.join(ctx.env.CFLAGS), + ' '.join(['-B' + l for l in libpath]), + lib_lib) + out = ctx.cmd_and_log(cmd) + out = os.path.normpath(out.strip()) + if out == lib_lib: + if mandatory: + ctx.fatal('The library %s not found' % (lib_lib)) + ctx.end_msg('not found') + else: + ctx.env['LIBPATH_lib%s' % (lib)] = '..' + '/..' * (ctx.path.height() - 1) + out + ctx.end_msg('found') + +def check_lib(ctx, libs): + if not isinstance(libs, list): + lib = [libs] + for lib in libs: + if 'LIBPATH_lib%s' % (lib) not in ctx.env: + return False + return True + +def check_cpuopt(conf, opt): + code = ['#ifndef %s' % (opt)] + code += [' #error %s is not defined' % (opt)] + code += ['#endif'] + code += ['#if %s' % (opt)] + code += [' /* %s is true */' % (opt)] + code += ['#else'] + code += [' #error %s is false' % (opt)] + code += ['#endif'] + try: + conf.check_cc(fragment = test_application(code), + execute = False, + msg = 'Checking for %s' % (opt)) + except conf.errors.WafError: + return False; + return True + +def tweaks(conf, arch_bsp): + # + # Hack to work around NIOS2 naming. + # + if conf.env.RTEMS_ARCH in ['nios2']: + conf.env.OBJCOPY_FLAGS = ['-O', 'elf32-littlenios2'] + elif conf.env.RTEMS_ARCH in ['arm']: + conf.env.OBJCOPY_FLAGS = ['-I', 'binary', '-O', 'elf32-littlearm'] + else: + conf.env.OBJCOPY_FLAGS = ['-O', 'elf32-' + conf.env.RTEMS_ARCH] + + # + # Check for a i386 PC bsp. + # + if re.match('i386-.*-pc[3456]86', arch_bsp) is not None: + conf.env.LINKFLAGS += ['-Wl,-Ttext,0x00100000'] + + if '-ffunction-sections' in conf.env.CFLAGS: + conf.env.LINKFLAGS += ['-Wl,--gc-sections'] + +def check_options(ctx, prefix, rtems_tools, rtems_path, rtems_version, rtems_archs, rtems_bsps): + # + # Set defaults + # + if rtems_version is None: + if rtems_default_version is None: + m = re.compile('[^0-9.]*([0-9.]+)$').match(prefix) + if m: + rtems_version = m.group(1) + else: + ctx.fatal('RTEMS version cannot derived from prefix: ' + prefix) + else: + rtems_version = rtems_default_version + if rtems_path is None: + rtems_path = prefix + if rtems_tools is None: + rtems_tools = rtems_path + + # + # Check the paths are valid. + # + if not os.path.exists(rtems_path): + ctx.fatal('RTEMS path not found.') + if os.path.exists(os.path.join(rtems_path, 'lib', 'pkgconfig')): + rtems_config = None + elif os.path.exists(os.path.join(rtems_path, 'rtems-config')): + rtems_config = os.path.join(rtems_path, 'rtems-config') + else: + ctx.fatal('RTEMS path is not valid. No lib/pkgconfig or rtems-config found.') + rtems_share_rtems_version = os.path.join(rtems_path, 'share', 'rtems' + rtems_version) + if not os.path.exists(os.path.join(rtems_share_rtems_version)): + ctx.fatal('RTEMS path is not valid, "%s" not found.' % (rtems_share_rtems_version)) + + # + # We can more than one path to tools. This happens when testing different + # versions. + # + rt = rtems_tools.split(',') + tools = [] + for path in rt: + if not os.path.exists(path): + ctx.fatal('RTEMS tools path not found: ' + path) + if not os.path.exists(os.path.join(path, 'bin')): + ctx.fatal('RTEMS tools path does not contain a \'bin\' directory: ' + path) + tools += [os.path.join(path, 'bin')] + + # + # Filter the tools. + # + tools = filter(ctx, 'tools', tools) + + # + # Match the archs requested against the ones found. If the user + # wants all (default) set all used. + # + if rtems_archs == 'all': + archs = _find_installed_archs(rtems_config, rtems_path, rtems_version) + else: + archs = _check_archs(rtems_config, rtems_archs, rtems_path, rtems_version) + + # + # Filter the architectures. + # + archs = filter(ctx, 'archs', archs) + + # + # We some. + # + if len(archs) == 0: + ctx.fatal('Could not find any architectures') + + # + # Get the list of valid BSPs. This process filters the architectures + # to those referenced by the BSPs. + # + if rtems_bsps == 'all': + arch_bsps = _find_installed_arch_bsps(rtems_config, rtems_path, archs, rtems_version) + else: + arch_bsps = _check_arch_bsps(rtems_bsps, rtems_config, rtems_path, archs, rtems_version) + + if len(arch_bsps) == 0: + ctx.fatal('No valid arch/bsps found') + + # + # Filter the bsps. + # + arch_bsps = filter(ctx, 'bsps', arch_bsps) + + return rtems_version, rtems_path, tools, archs, arch_bsps + +def check_env(ctx, *env_vars): + for v in env_vars: + if v not in ctx.env or len(ctx.env[v]) == 0: + return False + return True + +def check(ctx, option, setting = 'Yes'): + if option in ctx.env: + if isinstance(setting, bool): + return True + return ctx.env[option] == setting + return False + +def check_debug(ctx): + return check(ctx, 'RTEMS_DEBUG') + +def check_multiprocessing(ctx): + return check(ctx, 'RTEMS_MULTIPROCESSING') + +def check_newlib(ctx): + return check(ctx, 'RTEMS_NEWLIB') + +def check_posix(ctx): + return check(ctx, 'RTEMS_POSIX_API') + +def check_smp(ctx): + return check(ctx, 'RTEMS_SMP') + +def check_networking(ctx): + return check(ctx, 'RTEMS_NETWORKING') + +def arch(arch_bsp): + """ Given an arch/bsp return the architecture.""" + return _arch_from_arch_bsp(arch_bsp).split('-')[0] + +def bsp(arch_bsp): + """ Given an arch/bsp return the BSP.""" + return _bsp_from_arch_bsp(arch_bsp) + +def arch_bsps(ctx): + """ Return the list of arch/bsps we are building.""" + return ctx.env.ARCH_BSPS + +def arch_bsp_env(ctx, arch_bsp): + return ctx.env_of_name(arch_bsp).derive() + +def filter(ctx, filter, items): + if rtems_filters is None: + return items + if type(rtems_filters) is not dict: + ctx.fatal("Invalid RTEMS filter type, " \ + "ie { 'tools': { 'in': [], 'out': [] }, 'arch': {}, 'bsps': {} }") + if filter not in rtems_filters: + return items + items_in = [] + items_out = [] + if 'in' in rtems_filters[filter]: + items_in = copy.copy(rtems_filters[filter]['in']) + if 'out' in rtems_filters[filter]: + items_out = copy.copy(rtems_filters[filter]['out']) + filtered_items = [] + for i in items: + item = i + ab = '%s/%s' % (arch(item), bsp(item)) + for inre in items_in: + if re.compile(inre).match(ab): + items_in.remove(inre) + filtered_items += [item] + item = None + break + if item is not None: + for outre in items_out: + if re.compile(outre).match(ab): + item = None + break + if item is not None: + filtered_items += [item] + if len(items_in) != 0: + ctx.fatal('Following %s not found: %s' % (filter, ', '.join(items_in))) + return sorted(filtered_items) + +def arch_rtems_version(version, arch): + """ Return the RTEMS architecture path, ie sparc-rtems4.11.""" + return '%s-rtems%s' % (arch, version) + +def arch_bsp_path(version, arch_bsp): + """ Return the BSP path.""" + return '%s/%s' % (arch_rtems_version(version, arch(arch_bsp)), bsp(arch_bsp)) + +def arch_bsp_include_path(version, arch_bsp): + """ Return the BSP include path.""" + return '%s/lib/include' % (arch_bsp_path(version, arch_bsp)) + +def arch_bsp_lib_path(version, arch_bsp): + """ Return the BSP library path. """ + return '%s/lib' % (arch_bsp_path(version, arch_bsp)) + +def library_path(library, cc, cflags): + cmd = cc + cflags + ['-print-file-name=%s' % library] + a = subprocess.check_output(cmd) + lib = os.path.abspath(a.strip()) + if os.path.exists(lib): + return os.path.dirname(lib) + return None + +def root_filesystem(bld, name, files, tar, obj): + tar_rule = 'tar -cf ${TGT} --format=ustar -C ../.. $(echo "${SRC}" | sed -e \'s/\.\.\/\.\.\///g\')' + if windows: + tar_rule = 'sh -c "%s"' % (tar_rule) + bld(name = name + '_tar', + target = tar, + source = files, + rule = tar_rule) + bld.objects(name = name, + target = obj, + source = tar, + rule = '${OBJCOPY} -I binary -B ${RTEMS_ARCH} ${OBJCOPY_FLAGS} ${SRC} ${TGT}') + +def clone_tasks(bld): + if bld.cmd == 'build': + for obj in bld.all_task_gen[:]: + for x in arch_bsp: + cloned_obj = obj.clone(x) + kind = Options.options.build_kind + if kind.find(x) < 0: + cloned_obj.posted = True + obj.posted = True + +# +# From the demos. Use this to get the command to cut+paste to play. +# +def output_command_line(): + # first, display strings, people like them + from waflib import Utils, Logs + from waflib.Context import Context + def exec_command(self, cmd, **kw): + subprocess = Utils.subprocess + kw['shell'] = isinstance(cmd, str) + if isinstance(cmd, str): + Logs.info('%s' % cmd) + else: + cmdstr = ' '.join(cmd) + Logs.info('(%d) %s' % (len(cmdstr), cmdstr)) # here is the change + if not isinstance(kw['cwd'], str): + kw['cwd'] = str(kw['cwd']) + Logs.debug('runner_env: kw=%s' % kw) + try: + if self.logger: + self.logger.info(cmd) + kw['stdout'] = kw['stderr'] = subprocess.PIPE + p = subprocess.Popen(cmd, **kw) + (out, err) = p.communicate() + if out: + self.logger.debug('out: %s' % out.decode(sys.stdout.encoding or 'iso8859-1')) + if err: + self.logger.error('err: %s' % err.decode(sys.stdout.encoding or 'iso8859-1')) + return p.returncode + else: + p = subprocess.Popen(cmd, **kw) + return p.wait() + except OSError: + return -1 + Context.exec_command = exec_command + + # Change the outputs for tasks too + from waflib.Task import Task + def display(self): + return '' # no output on empty strings + + Task.__str__ = display + +# +# From the extras. Use this to support long command lines. +# +def long_command_line(): + def exec_command(self, cmd, **kw): + # workaround for command line length limit: + # http://support.microsoft.com/kb/830473 + import tempfile + tmp = None + try: + if not isinstance(cmd, str) and len(str(cmd)) > 8192: + (fd, tmp) = tempfile.mkstemp(dir=self.generator.bld.bldnode.abspath()) + flat = ['"%s"' % x.replace('\\', '\\\\').replace('"', '\\"') for x in cmd[1:]] + try: + os.write(fd, ' '.join(flat).encode()) + finally: + if tmp: + os.close(fd) + # Line may be very long: + # Logs.debug('runner:' + ' '.join(flat)) + cmd = [cmd[0], '@' + tmp] + ret = super(self.__class__, self).exec_command(cmd, **kw) + finally: + if tmp: + os.remove(tmp) + return ret + for k in 'c cxx cprogram cxxprogram cshlib cxxshlib cstlib cxxstlib'.split(): + cls = Task.classes.get(k) + if cls: + derived_class = type(k, (cls,), {}) + derived_class.exec_command = exec_command + if hasattr(cls, 'hcode'): + derived_class.hcode = cls.hcode + +def _find_tools(conf, arch, paths, tools): + if arch not in tools: + arch_tools = {} + arch_tools['CC'] = conf.find_program([arch + '-gcc'], path_list = paths) + arch_tools['CXX'] = conf.find_program([arch + '-g++'], path_list = paths) + arch_tools['LINK_CC'] = arch_tools['CC'] + arch_tools['LINK_CXX'] = arch_tools['CXX'] + arch_tools['AS'] = conf.find_program([arch + '-gcc'], path_list = paths) + arch_tools['LD'] = conf.find_program([arch + '-ld'], path_list = paths) + arch_tools['AR'] = conf.find_program([arch + '-ar'], path_list = paths) + arch_tools['NM'] = conf.find_program([arch + '-nm'], path_list = paths) + arch_tools['OBJDUMP'] = conf.find_program([arch + '-objdump'], path_list = paths) + arch_tools['OBJCOPY'] = conf.find_program([arch + '-objcopy'], path_list = paths) + arch_tools['READELF'] = conf.find_program([arch + '-readelf'], path_list = paths) + arch_tools['STRIP'] = conf.find_program([arch + '-strip'], path_list = paths) + arch_tools['RANLIB'] = conf.find_program([arch + '-ranlib'], path_list = paths) + arch_tools['RTEMS_LD'] = conf.find_program(['rtems-ld'], path_list = paths, + mandatory = False) + arch_tools['RTEMS_TLD'] = conf.find_program(['rtems-tld'], path_list = paths, + mandatory = False) + arch_tools['RTEMS_SYMS'] = conf.find_program(['rtems-syms'], path_list = paths, + mandatory = False) + arch_tools['RTEMS_BIN2C'] = conf.find_program(['rtems-bin2c'], path_list = paths, + mandatory = False) + arch_tools['TAR'] = conf.find_program(['tar'], mandatory = False) + tools[arch] = arch_tools + return tools + +def _find_installed_archs(config, path, version): + archs = [] + if config is None: + for d in os.listdir(path): + if d.endswith('-rtems' + version): + archs += [d] + else: + a = subprocess.check_output([config, '--list-format', '"%(arch)s"']) + a = a[:-1].replace('"', '') + archs = set(a.split()) + archs = ['%s-rtems%s' % (x, version) for x in archs] + archs.sort() + return archs + +def _check_archs(config, req, path, version): + installed = _find_installed_archs(config, path, version) + archs = [] + for a in req.split(','): + arch = a + '-rtems' + version + if arch in installed: + archs += [arch] + archs.sort() + return archs + +def _find_installed_arch_bsps(config, path, archs, version): + arch_bsps = [] + if config is None: + for f in os.listdir(_pkgconfig_path(path)): + if f.endswith('.pc'): + if _arch_from_arch_bsp(f[:-3]) in archs: + arch_bsps += [f[:-3]] + else: + ab = subprocess.check_output([config, '--list-format']) + ab = ab[:-1].replace('"', '') + ab = ab.replace('/', '-rtems%s-' % (version)) + arch_bsps = [x for x in set(ab.split())] + arch_bsps.sort() + return arch_bsps + +def _check_arch_bsps(req, config, path, archs, version): + archs_bsps = [] + for ab in req.split(','): + abl = ab.split('/') + if len(abl) != 2: + return [] + found = False + for arch in archs: + a = '%s-rtems%s' % (abl[0], version) + if a == arch: + found = True + break + if not found: + return [] + archs_bsps += ['%s-%s' % (a, abl[1])] + if len(archs_bsps) == 0: + return [] + installed = _find_installed_arch_bsps(config, path, archs, version) + bsps = [] + for b in archs_bsps: + if b in installed: + bsps += [b] + bsps.sort() + return bsps + +def _arch_from_arch_bsp(arch_bsp): + return '-'.join(arch_bsp.split('-')[:2]) + +def _bsp_from_arch_bsp(arch_bsp): + return '-'.join(arch_bsp.split('-')[2:]) + +def _pkgconfig_path(path): + return os.path.join(path, 'lib', 'pkgconfig') + +def _load_flags(conf, arch_bsp, path): + if not os.path.exists(path): + ctx.fatal('RTEMS path not found.') + if os.path.exists(_pkgconfig_path(path)): + pc = os.path.join(_pkgconfig_path(path), arch_bsp + '.pc') + conf.to_log('Opening and load pkgconfig: ' + pc) + pkg = pkgconfig.package(pc) + config = None + elif os.path.exists(os.path.join(path, 'rtems-config')): + config = os.path.join(path, 'rtems-config') + pkg = None + flags = {} + _log_header(conf) + flags['CFLAGS'] = _load_flags_set('CFLAGS', arch_bsp, conf, config, pkg) + flags['LDFLAGS'] = _load_flags_set('LDFLAGS', arch_bsp, conf, config, pkg) + flags['LIB'] = _load_flags_set('LIB', arch_bsp, conf, config, pkg) + # + # Handle gccdeps flags. + # + if '-MMD' in conf.env['CFLAGS']: + flags['CFLAGS'] += ['-MMD'] + return flags + +def _load_flags_set(flags, arch_bsp, conf, config, pkg): + conf.to_log('%s ->' % flags) + if pkg is not None: + flagstr = '' + try: + flagstr = pkg.get(flags) + except pkgconfig.error as e: + conf.to_log('pkconfig warning: ' + e.msg) + conf.to_log(' ' + flagstr) + else: + flags_map = { 'CFLAGS': '--cflags', + 'LDFLAGS': '--ldflags', + 'LIB': '--libs' } + ab = arch_bsp.split('-') + #conf.check_cfg(path = config, + # package = '', + # uselib_store = 'rtems', + # args = '--bsp %s/%s %s' % (ab[0], ab[2], flags_map[flags])) + #print conf.env + #print '%r' % conf + #flagstr = '-l -c' + flagstr = subprocess.check_output([config, '--bsp', '%s/%s' % (ab[0], ab[2]), flags_map[flags]]) + #print flags, ">>>>", flagstr + if flags == 'CFLAGS': + flagstr += ' -DWAF_BUILD=1' + if flags == 'LIB': + flagstr = 'rtemscpu rtemsbsp c rtemscpu rtemsbsp' + return flagstr.split() + +def _filter_flags(label, flags, arch, rtems_path): + + flag_groups = \ + [ { 'key': 'warnings', 'path': False, 'flags': { '-W': 1 }, 'cflags': False, 'lflags': False }, + { 'key': 'includes', 'path': True, 'flags': { '-I': 1, '-isystem': 2, '-sysroot': 2 } }, + { 'key': 'libpath', 'path': True, 'flags': { '-L': 1 } }, + { 'key': 'machines', 'path': True, 'flags': { '-O': 1, '-m': 1, '-f': 1, '-G': 1, '-E': 1 } }, + { 'key': 'prepro', 'path': False, 'flags': { '-MMD': 1 } }, + { 'key': 'specs', 'path': True, 'flags': { '-q': 1, '-B': 2, '--specs': 2 } } ] + + flags = _strip_cflags(flags) + + _flags = { label: [] } + for fg in flag_groups: + _flags[fg['key']] = [] + + iflags = iter(flags) + for opt in iflags: + in_label = True + opts = [] + for fg in flag_groups: + key = fg['key'] + for flag in fg['flags']: + if opt.startswith(flag): + opt_count = fg['flags'][flag] + if opt_count > 1: + if opt != flag: + opt_count -= 1 + if fg['path'] and arch in opt: + opt = '%s%s/%s' % (flag, rtems_path, + opt[opt.find(arch):]) + opts += [opt] + for c in range(1, opt_count): + opt = next(iflags) + if fg['path'] and arch in opt: + opt = '%s%s/%s' % (f, rtems_path, + opt[opt.find(arch):]) + opts += [opt] + _flags[key] += opts + if label in fg and not fg[label]: + in_label = False + break + if in_label: + _flags[label] += opts + return _flags + +def _strip_cflags(cflags): + _cflags = [] + for o in cflags: + if o.startswith('-O'): + pass + elif o.startswith('-g'): + pass + else: + _cflags += [o] + return _cflags + +def _log_header(conf): + conf.to_log('-----------------------------------------') + +def _get_dir_hash(bld): + from waflib import ConfigSet, Options + import hashlib + + env = ConfigSet.ConfigSet() + env.load(Options.lockfile) + prefix = env.options['prefix'] + shahash = hashlib.sha1() + + for root, dirs, files in os.walk(prefix): + for names in files: + filepath = os.path.join(root, names) + try: + f1 = open(filepath, 'rb') + except: + f1.close() + continue + + while 1: + buf = f1.read(4096) + if not buf: + break + shahash.update(hashlib.sha1(buf).hexdigest()) + f1.close() + return shahash.hexdigest() + +def test_uninstall(bld): + from os import sys + + print('Test: uninstall') + initial_hash = _get_dir_hash(bld) + print('Preinstall hash: %s' % (initial_hash)) + try: + subprocess.call(['waf', 'install']) + subprocess.call(['waf', 'uninstall']) + except: + subprocess.call(['./waf', 'install']) + subprocess.call(['./waf', 'uninstall']) + final_hash = _get_dir_hash(bld) + print('Post install hash: %s' % (final_hash)) + + if (initial_hash == final_hash): + print("Test successful") + else: + print("Test failed") + +from waflib import Task +from waflib import TaskGen +from waflib import Utils +from waflib import Node +from waflib.Tools.ccroot import link_task, USELIB_VARS + +USELIB_VARS['rap'] = set(['RTEMS_LINKFLAGS']) +USELIB_VARS['rtrace'] = set(['RTRACE_FLAGS', 'RTRACE_CFG', 'RTRACE_WRAPPER', 'RTRACE_LINKCMDS']) + +class rap(link_task): + "Link object files into a RTEMS application" + run_str = '${RTEMS_LD} ${RTEMS_LINKFLAGS} --cc ${CC} ${SRC} -o ${TGT[0].abspath()} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}' + ext_out = ['.rap'] + vars = ['RTEMS_LINKFLAGS', 'LINKDEPS'] + inst_to = '${BINDIR}' + +class rtrace(link_task): + "Link object files into a RTEMS trace application" + run_str = '${RTEMS_TLD} ${RTACE_FLAGS} ${RTRACE_WRAPPER_ST:RTRACE_WRAPPER} -C ${RTRACE_CFG} -r ${RTEMS_PATH} -B ${ARCH_BSP} -c ${CC} -l ${CC} -- ${SRC} ${LINKFLAGS} ${RTRACE_LINKFLAGS} -o ${TGT[0].abspath()} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}' + ext_out = ['.texe'] + vars = ['RTRACE_FLAGS', 'RTRACE_CFG', 'RTRACE_WRAPER', 'RTRACE_LINKFLAGS', 'LINKDEPS'] + inst_to = '${BINDIR}' + color = 'PINK' diff --git a/rtems/hello_posix/rtems_waf/rtems_bsd.py b/rtems/hello_posix/rtems_waf/rtems_bsd.py new file mode 100644 index 0000000..f28ef1c --- /dev/null +++ b/rtems/hello_posix/rtems_waf/rtems_bsd.py @@ -0,0 +1,150 @@ +# +# RTEMS Project (https://www.rtems.org/) +# +# Copyright (c) 2016 Chris Johns . All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from __future__ import print_function + +import os.path + +try: + import rtems_waf.rtems as rtems +except: + print("error: no rtems_waf module") + import sys + sys.exit(1) + +def init(ctx): + pass + +def options(opt): + opt.add_option('--net-config', + default = 'config.inc', + dest = 'net_config', + help = 'Network test configuration.') + opt.add_option('--rtems-libbsd', + action = 'store', + default = None, + dest = 'rtems_libbsd', + help = 'Path to install RTEMS LibBSD (defauls to prefix).') + +def bsp_configure(conf, arch_bsp, mandatory = True): + configure = mandatory + + if not mandatory and conf.options.rtems_libbsd is not None: + configure = True + + if configure: + conf.msg('RTEMS LibBSD', + rtems.arch(arch_bsp) + '/' + rtems.bsp(arch_bsp), + 'YELLOW') + + conf.check(header_name = 'dlfcn.h', features = 'c') + if not rtems.check_posix(conf): + conf.fatal('RTEMS kernel POSIX support is disabled; ' + + 'configure RTEMS with --enable-posix') + if rtems.check_networking(conf): + conf.fatal('RTEMS kernel contains the old network support; ' + + 'configure RTEMS with --disable-networking') + rtems_libbsd_path = conf.options.rtems_libbsd + if rtems_libbsd_path is None: + if conf.options.rtems is None: + rtems_libbsd_path = conf.options.rtems + else: + rtems_libbsd_path = conf.env.PREFIX + + if not os.path.exists(rtems_libbsd_path): + conf.fatal('RTEMS LibBSD path not found: %s' % (rtems_libbsd_path)) + + rtems_libbsd_inc_path = os.path.join(rtems_libbsd_path, + rtems.arch_bsp_include_path(conf.env.RTEMS_VERSION, + conf.env.RTEMS_ARCH_BSP)) + rtems_libbsd_lib_path = os.path.join(rtems_libbsd_path, + rtems.arch_bsp_lib_path(conf.env.RTEMS_VERSION, + conf.env.RTEMS_ARCH_BSP)) + + conf.env.IFLAGS += [rtems_libbsd_inc_path] + conf.check(header_name = 'machine/rtems-bsd-sysinit.h', + features = 'c', + includes = conf.env.IFLAGS) + + conf.env.RTEMS_LIBBSD = 'Yes' + conf.env.INCLUDES = conf.env.IFLAGS + conf.env.LIBPATH += [rtems_libbsd_lib_path] + conf.env.LIB += ['bsd', 'z', 'm'] + + configure_net_config(conf, arch_bsp) + +def configure_net_config(conf, arch_bsp): + if check_libbsd(conf) and conf.options.net_config is not None: + net_config = conf.options.net_config + + if not os.path.exists(net_config): + conf.fatal('network configuraiton \'%s\' not found' % (net_config)) + + try: + net_cfg_lines = open(net_config).readlines() + except: + conf.fatal('network configuraiton \'%s\' read failed' % (net_config)) + + tags = [ 'NET_CFG_SELF_IP', + 'NET_CFG_NETMASK', + 'NET_CFG_PEER_IP', + 'NET_CFG_GATEWAY_IP' ] + + lc = 0 + sed = 'sed ' + defines = [] + for l in net_cfg_lines: + lc += 1 + if l.strip().startswith('NET_CFG_'): + ls = l.split('=') + if len(ls) != 2: + conf.fatal('network configuraiton \'%s\' ' + \ + 'parse error: %d: %s' % (net_config, lc, l)) + lhs = ls[0].strip() + rhs = ls[1].strip() + for t in tags: + if lhs.startswith(t): + conf.env[lhs] = rhs + sed += "-e 's/@%s@/%s/'" % (lhs, rhs) + defines += ['%s="%s"' % (lhs, rhs)] + + conf.env.NET_CONFIG = net_config + conf.env.NET_CONFIG_SED = sed + conf.env.NET_CONFIG_DEFINES = ','.join(defines) + + conf.msg('Net Config', 'found', 'YELLOW') + +def check_libbsd(ctx): + return rtems.check(ctx, 'RTEMS_LIBBSD') + +def check_net_config(ctx): + return rtems.check(ctx, 'NET_CONFIG', setting = True) + +def net_config_header(ctx, target): + ctx(target = target, + source = "rtems_waf/network-config.h.in", + rule = sed + " < ${SRC} > ${TGT}", + update_outputs = True) diff --git a/rtems/hello_posix/waf b/rtems/hello_posix/waf new file mode 100755 index 0000000..7ceee16 --- /dev/null +++ b/rtems/hello_posix/waf @@ -0,0 +1,173 @@ +#!/usr/bin/env python +# encoding: latin-1 +# Thomas Nagy, 2005-2018 +# +""" +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +""" + +import os, sys, inspect + +VERSION="2.0.19" +REVISION="1f3c580272b15a03d2566843c5fe872a" +GIT="61ee22b598cf80e260beb64e475966f58b304d0d" +INSTALL='' +C1='#6' +C2='#.' +C3='#%' +cwd = os.getcwd() +join = os.path.join + + +WAF='waf' +def b(x): + return x +if sys.hexversion>0x300000f: + WAF='waf3' + def b(x): + return x.encode() + +def err(m): + print(('\033[91mError: %s\033[0m' % m)) + sys.exit(1) + +def unpack_wafdir(dir, src): + f = open(src,'rb') + c = 'corrupt archive (%d)' + while 1: + line = f.readline() + if not line: err('run waf-light from a folder containing waflib') + if line == b('#==>\n'): + txt = f.readline() + if not txt: err(c % 1) + if f.readline() != b('#<==\n'): err(c % 2) + break + if not txt: err(c % 3) + txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r')).replace(b(C3), b('\x00')) + + import shutil, tarfile + try: shutil.rmtree(dir) + except OSError: pass + try: + for x in ('Tools', 'extras'): + os.makedirs(join(dir, 'waflib', x)) + except OSError: + err("Cannot unpack waf lib into %s\nMove waf in a writable directory" % dir) + + os.chdir(dir) + tmp = 't.bz2' + t = open(tmp,'wb') + try: t.write(txt) + finally: t.close() + + try: + t = tarfile.open(tmp) + except: + try: + os.system('bunzip2 t.bz2') + t = tarfile.open('t') + tmp = 't' + except: + os.chdir(cwd) + try: shutil.rmtree(dir) + except OSError: pass + err("Waf cannot be unpacked, check that bzip2 support is present") + + try: + for x in t: t.extract(x) + finally: + t.close() + + for x in ('Tools', 'extras'): + os.chmod(join('waflib',x), 493) + + if sys.hexversion<0x300000f: + sys.path = [join(dir, 'waflib')] + sys.path + import fixpy2 + fixpy2.fixdir(dir) + + os.remove(tmp) + os.chdir(cwd) + + try: dir = unicode(dir, 'mbcs') + except: pass + try: + from ctypes import windll + windll.kernel32.SetFileAttributesW(dir, 2) + except: + pass + +def test(dir): + try: + os.stat(join(dir, 'waflib')) + return os.path.abspath(dir) + except OSError: + pass + +def find_lib(): + src = os.path.abspath(inspect.getfile(inspect.getmodule(err))) + base, name = os.path.split(src) + + #devs use $WAFDIR + w=test(os.environ.get('WAFDIR', '')) + if w: return w + + #waf-light + if name.endswith('waf-light'): + w = test(base) + if w: return w + for dir in sys.path: + if test(dir): + return dir + err('waf-light requires waflib -> export WAFDIR=/folder') + + dirname = '%s-%s-%s' % (WAF, VERSION, REVISION) + for i in (INSTALL,'/usr','/usr/local','/opt'): + w = test(i + '/lib/' + dirname) + if w: return w + + #waf-local + dir = join(base, (sys.platform != 'win32' and '.' or '') + dirname) + w = test(dir) + if w: return w + + #unpack + unpack_wafdir(dir, src) + return dir + +wafdir = find_lib() +sys.path.insert(0, wafdir) + +if __name__ == '__main__': + + from waflib import Scripting + Scripting.waf_entry_point(cwd, VERSION, wafdir) + +#==> +#BZh91AY&SY9 ½´\¥ÿÿÿ³DPÿÿÿÿÿÿÿÿÿÿÿm (¬#%00e€(b÷/mЀ#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%#%öÞúzómmkîÖZžÞæ—²U#.´[iÚ¾îõ¹±µ–ú:¥'kd‹î7{ÛïoºµÛ¶ÖµK“¹]Øvµ'ÛßO¾ö¸gv÷s½÷¶N)#.Q+Ù½íp·µÞ]/{mš»<{guÒ‹@Ýó{§«vo;¾ø;ŸvÎiîáÉî44lºï{ß|ûëËßÚU9íõÝŸÝšî·¯y½÷½x#%#%@(}ìh#%` ï²€=âwfí˜:4§[aÓ¹½ y©³A¦€‡¸ê»´ö4=¦öìd+Ö¨ª)ífš0#6 *”¢”{ƒ’Q$#%#6#%YJzÚV½ƒ%çÍíîæ}»j½êºa’ïjÚØá3TTf˦Iv×]s}6óu7¾÷z:#.ÎxûÝW_=³ÛzÖ­åZ;Û»ÍÝÛ}Þsy¾¯³»ß{¸ûížÖîiÉÔ÷Ëzõ¶§rç>^æû}ñ¾íóÛa zúz{x¹-ìz̀ݳ­Ö²4÷³¼ÛÞ÷fÞÏs¬ô`u¡ÒãF°Û"’EE7w¼#%(J*’OCÀ#%lîè•=÷n{Ywº¹½»ÐdÜ öï>}Ü[vÇGÐ`>†ÛEmk®¥ÑMãW`×LæyÛãÚ^u½#%}÷aŽît;o¶û}|{mçO—vpòǼ΀Šo·*WµíƘܶ2>öí®®òÏŸwÖõ»]´î;ºjîí9QÚt×·Zt“ž>÷»Ü®¨ÜÙu÷‡ß|}í­«×ܬ‰&ÞíN«îq\îû½:¾Ã.ñŽ^ÙéyaC§¶Ó¶Û›—³®÷Ð¥&nCzî¤|öilöͶíÝîвë[¸˜÷»³Ûºû5ÖkoX«èqØ—nöÐl­îõÞÞ/`{´žó½wÌ>ï†Ðê¥PJªPTT´jB¹7uÐv&i¶v­Üèº]vú‰Ý›:kÛkÔØëUUܘ{x÷š)º¼»HЃºÚɯfw€#%7ZI#%#%;Ü^êåÉÎó²û3ÊF-Ÿm½ÜözÔíÝ™Üì_U.us[›¶ õv]]ó¸|˜Hû†,ÍqÑ»ÝÁæñ{c;úŒçvåJº{+¹éÔ²õ§l÷+ªWg¡»`úùÛÙ;{n#î²Ç]÷}çww»{»»xîvÛ#.¾Øú½mÝEfù‡"sž¼ï¯¼ùÚÀ°ËlÐú$/g¬íÑ”x<ïÜë°VØ6EÇ‘µÞ®ÚGxO{×>öø½ïwÞ´#%À*×Û;Fªµíí7¶;g<ÂÀëu´oSk´Ý­ëÓ­mï 9.ó’®Ú×ݬ» ݾçwÅówwtåvë¥Þç:#.[.ëwc Ó‚àéÕhÁ”gu“½Þ^ïŸnØu¼ÓÐŒ…/=ÝÚ4#%•c¹éî½Mö{ÜàìJ…U )½{xW»´×`ï{®ñÝÊäÅÖÃV¶•U[}÷IzovƒuÇH*Ší·u­$ëIÒÖªîúãÞncÚ[ÓµŽÛ× &Æ»»}öøø‡½óí·³acÜ| ìÁ“G»îñÌͼÜ&:·»}½í6µîÐíç;ï¹ßvÛRÀîï·Ÿw}-âòó[ãnh€ &€#%&€ £CBa0š#.#%‰ä™PÏTz†Ðš#%õ§’{SÔõA) B @†@©©á$zzI☠é4#%#%#%#%#%#%#%‚D!  M5TÿMŠoU<ÔôzTý(òÔõ)é¨mG¨#%#%Ñ£@#%#%'ªRD!4dÐODõ$ÙOFž¡£õM#.€ò@#.Sj#%#%#%#%#%#%$!#%&@bh&M#%M#.4SÓiˆŒ4 ¢ #%h#%#%#%I¨ˆ L˜#Až€&Œ¦=&”õmêˆ{SIé” h#%d4#%È#%—ÿÓ?£Uirê\ÕQWwk¹úµZvhʃ>5Zu!LA³ ,L•Q*"€)æ°Pcõ§óü Zü“•5OùÓ¦¸ üæJt¦î£Ä‘8•WoT"¢]^SÌÆ´_3ý†os2ì ÀlDs‚4;m»qE6­›®ñ‘ÎÊ­´ÚMí˜ÖØ`Vd…â]jíâ—˜•5o‚# åñ÷UŒI7wD¼áÌKUå¦/žÝ~«oÔBäE"ªSº»U¦ÖÖ5k3khÈ‹ €7#%H*-E Õ:¥”$HŠ& ˆ" HåP° !ß#%hŠ–‚¡#%ª$@d PÉ@mªfL…’ŒÍCLÓd@M$Rj6Ñ35–25)F”Sm&‰š$ÐJ2ZšQ°h[Fi,ši¢Z!#.F)iM€F¥ #.1eM£DRl–¨Š–ZSMhˆYi#.š ƒ(ÌÌcRF£Qµ&ƒJl†BjcI@˜hÒËHÆR›F¦›"[M¶³U´i˜’ÆfLÈM& ²m¦ÛM65%)-5±–¦Û3fZL“1‘f´ÄÑd¢‚™l‰B!Qf‘´R`4TH!`ؤ©„f•Jb0lB ‘XhdFIR&B4±ClÍ ’&)BFRÊËf$@ÒYŠY5“ccE#6‘d†K) -)¦ ±%&EDš2hhɉIF‘($@VAMEˆ¢fRÒ¦`›É ؉1M Í‚ab6¤Ø–V‹$”›‚$´”PRD•’%¤Q0EaÆIL# ”&RJME™±£XHÒjH’b iM$"H²[bË2ŠFÌ’‰²™3bdE(Í‘˜&U4Ä‹)A³Q`,i¦†Æ"5+%’6(”R"šIˆ&¤a³LcI¡ &¤–Q”Ôi3HÚ("šh¢kP,&YA¤²2‹%&DÐM2‘*4f6”)1¨6ÄÊA! "“1F4,Ë ŠÙ&TÌÕ˜£l¥±(‰™#.H¦!HŒØСYM$QF¤É&ÉØÆJšF¦h±b2’™˜²2³i„¬D`ˆ¢JM52i™!Œ¢)#.š1Sb‹5*R’š)#.‘“2)´…HÅ(ÊHR"‹E$˜’M)´i5DŠFÀ˜Œh&Ti¦DÚ#.ƒ,„Òe‹DÈY‘¦ÉJb”D!f™ k6lmd°$4–Ld5EPZ XR$Ècc1 Â2ƒRXÔY¤J&ŒE©M(Z˜hI™IŠ$2ɲ#)‚E,Ñ¥1„5„²e"$4M¶¦¶´`™BjfŒ¦F&”RLȈ­¥6À¥š,Å&‘”%–TÙ¢-L¬-”bC؈RˆšD#HJm~Ãk¢¦©aˆÍ¢ŒlVƶ*6L¥4ÔR¤š44´…¨ØFÉ5Y†¡¦c(ÉS*H¶D‰™¦[%´Q‰IKQµ…£&˜D±5˜±acR#6e¥™2eI´*Ò4TÙB+dË"©TÒT›63š¶,Y­“L¬‰S,¦ÖJ²ÙJSLl’‘µ)¬±%¤2RÔZ ªŒ!¨Õ£%AEVMd£jŠÅEH”kDÑ$m‹hÅŠÔl2ѵ€´™0°U@i€”R £F2™&•¦±Ʀ&±‹d‹i Õª–µ–* ”ÍKY4IR1!M¤lY"¶¥Y¶1Jm*–R¦YaZšDF¶•K"e5MM¶„”Êk,Xl²k+,…lÓ  ¨ÒD…bÃ4˜‰!´…-£T%¢†KQY&š6LšJ,ˆ&ËŠl¤#."+,‚E1”ÌJ”lÓ4 AE¢Ó$&Fm6“F6ÆÈS¦™cE%bHÌÔ#!4LÔQ¢JdR–P5BTÀ4˜Ó J™²Bj-#636£)F̤’Œ£!HbÊkÃi4F5&Éa $YP…-4) Äš4Y”©””²•˜d¬aš,‘± jE¨Õ5£4ECF¥)6b¥fQj4  2ÆA¦&Ä•%I”1Ršcd¤Ía)ME`Û0Ù¤²lf“E˜‰CJ2Zfµ‘hTÍ2–H’l£0D2hªih¬Òl”Ä,LDÒRBAh´[ Q¨ÔQŠÆ-–ÃI†’M#6LŒRˆ#b-f›C2ˆ6*2%,¤©‘Ñ´k£TI¢„Ë5EŠ$Ôš£PdðŒj”¡kA¥4Ë!E$Š¦Ih‚5Eˆ±JÛ"¥F±¤ÁdÑÌ¡jQHfJ$©±(‰•j#V#.2,Y*6Œ)‹4¢Ù2V-­&)+)¶D¶M¡¢T’™R¢Âƒccd£dÑ&#¶HÔRLÁ¬ÉƒA#6)³6&"šÆ¨©•“Y‘¤)¤šŠ¢Š&›RV-”’ÆɈ£F‚4˜2JÔˆÑie£he¨’ÑjŠ±”£i5² …Q¶5%)ЙÈ̌ƚ‘LÙ&kDlU%‹hÔ•,«&´LÚ1lj £cc$UE2©¥XÚ6¶1mI˜ÊQ f²±-F+iQµ´©QJV”f*šB (4X"J&ØÖ,Ê’+I[M²“+FbbÑIE[l¶¬R&T*&$¢1PÀ"CFŠi&ÔÃ%XÛØ´Í[F5¬´•42ÖÊY6ÔÔÛ!mI¦¬ME26’QA°ÖjMI™²Êˆ B¢LI&RLˆÈÄd"Ù-¢Ñ‚±“þn··ýÔ¥C)þB51jÄÿTqôe+(a(Æh”‡÷!þ§ ûbåÕ LÿL$hÒlùNzí¿Îó±½9¿‹øºô·¦SUIPª?ë[ŒlÈŸÎÿ·ÖYLâsÈ †ßùë;L(0\:8À¥‰pÁI äˆd˜*ƒ‰Ãß±¢rý*¤çÿœ3ÿ³ôZÑÿÊI(R×+ˆ½”g™,$b/­Í0ÿ-‹npz%ZM‡¼íõâ8ßwB¹ÁŒ¨d~Ë Õ‹NØœ“ÆZþ,3cRR(l“ŠrrXˆþúݳf¤áV…cÈÌ`I¥Û"lÆLhƒcôzç““G]“¼î˜Þ¹w§¥^¥ã\³Ë/âuçåu™Í\‚LŠëP¦"W‹4LªvcK™@¥JAF&Ä“M‚ê×bÈ‹Ò3ˆ(êñç]¨eñnY½74h6 m `Ù—(c2@sªªzoþÝ(‘ 7p‡ Êc#6Gv…)†ì,`¼rÂü®R[ŒR}ßÒëdzçgsÅéšÐN×VÄQL0¦Ð¤Y;ùd«Ïô8$ÚÍÏ£˜ØÐØžj¤Ï(%?·râƒþ°Ãµ “ºÀ¡…†JÅxžß÷k¶Œ¶cÂx-›2KËw%€•¬C°UyáyÜ–íÞw^QŽr車esn–CQW6éçqllO²ëå5¼Z4EA¯»ºŸ?_ÆW‹ò-ȦWÅȶÆåÈIºÕø¼u‘¨Û?Go*„Èyùæ|m<™b#4L9cuPEX°ž«©#.¹t@#6A!´ä#ñÆ#.¯)ÎãÂHˆÃz”^+›Ý\Ѩ8šë•ÞwcrŽ•Ë™(Ë®é$s™5öø‘ZA„ÿhÿŒJrÈ.YÚlCÙ’,0!M ðÛtÉÈe«#6ýR­‹ÁÃ79ô,ýפ¾ìÉþ˜FtÃÏxV¬@Gô¡€dž%lþ «p’—ÇãŠUË"õÖ“UO«pi)8ª—â”+ñ §Ó¬,‰±Èj[þv¼‹lQôÇôa™1Kèë¯Ç×FÌ÷¿SªÄ7Ím‰Z½”*‰£NŒ¼Pâ-#6¬AË@‰*•{iX<ÙZøW÷»(Éðâ»EEE¼nY5ÆÕ͵þ—ìw’>ÇS6½•ß‹«¦öøÿM‡fhŠF¨%2+zmýW!†ŒbSQIðîÜ®÷uVé(i%"÷@Xš'+¬¥&D§)J²‹šå¢¶/]öï^¯"R¬•k¹bÑ_·-×»±öõÆ*Š|ý{ü=o÷îèë˜ØÔl›|ÏÀÞ1¨4–üŽ‹> õÝŒ>¬žýóL—ÖȲ"4£~"Uä¨ræPaŒLÖ¶jϹ$Â![ÙùzÛ²†F²lWßî«âøùÑÊW=ì¼4D‰Áa«l—AHÒPŤ'Ò'mBµ§…C×Gƒ¶éE2„R]U¥"»wÕ¬ü*ÔðХ߲œœ²ôî²Á‹¨ÀSE#6lÃQ MZH"JuœëJ» *”Ó#6I¢L²íãe—¥Â„S²ŠŸ$+ b¨¬N¬<ÙkH](©É#6<*žoЗçAJõ ü/•;q°óap×^Ro^X„jÅÄ"_gñ‡Ë¼ê÷Œ:+#%ñ²(\HÎpÊ6ç–´zmï*'Ü©×1Ù»á?_kŒ#.êV£„ÊFyûeo–Ðæ”$ê?•ßjfA›­vß¾ÚœNü£ƒz…$…!¨.fä³Ü¡Ï\ˆiÌ©Ê#.#¥ŠÉE0F:E&©¯}Ùž…µAîg]°éˆÃp?X7d1€á\NB=}ÙILƘ#6P#6íç;¢gä˜ý=«»†"ž<ú¹áïïRî:I2Éðˆ\õ­q.Vž)gÉ…,Õ8`¬=jPŽûí‰ÞèqëZ®#.þø¯,nM´B8÷8»è¸×µÛº†ä1ž‡i‹l÷õ m±Ï׺|š5Ì=Zí鵦üLuÙ $‘(w0©WX uÒ‘Bd˜N>ù¢Ü¸I¸ì¾½i“íE•éËÒêwë+Õ^{å5ÁZU{Š)ŠãÉÂé¨c¼T˜ì˜í§ @^†Ç¡=4´îç ʉZÛoý4^Û1¶Ã‰±öíªÆË ˜ò-—îûâû™§õoÉÜn¬æU>õéºiúK|e˨†J/±ßåÇ}m}w*IeQ92e@êÛ íhQAA9¼CrºõÝO¡¸Ëðuu5¤&÷JÃF}w/Å¡j©jŠÿ}…(© Ÿ+þ«¯½û¿éºÚ|~þëÇT•öµö°ù¥±G‘R{¨«EŠ ¢€úªS>,õ‰÷öæß»åj»çíj܇±†¿•™Yõ¿¯œõâ‚ú·+$‰þ.hÚ>n·‚ªôj£]–P‚ê©¨Æ ×¶{âÝûïg˜œå mk4µ“O§k{Ñ”ÇÛEË£õ;n”dm¥AyÑQŸ#6ÚäúÓ«f‰Í²­ãX—8T¾NL\ð—ôP苘1 øˆ63œYî y²úUM3¦ùÝ#.X˜|è¤TWù“7ìÍÇΊD^jÀEŒR,Œ)9Õß¹ÊÈ·)óÜÑŒûúuO³~™¾$_¶ÏŠ ÊsãÆ4?ŒZu>žì]1yÅøÚüžkÓEµÛX)>óOÖâm8s´Ì‚ëéÞO–z\àÚÄÚ¸;â¦R¸Á1ŠŠ~FS_tí“Rn(‘ØPñ¼b˜¤Rf“WYüÊ¡êô„cì×ùúù«ÜËÎP¼B´ ú’Y×…é¤DQQe0¨x~‚Û{*©nf £ªwiX‡T¯)œ’6-Ï;Ë£êw³$3Ê¡¶Ö}•TÛÉ|-ºz²8ï5›`BüéÝââêÖh¢’…ƒÒ¡¸É~¦™J‘‹Î€¤Z+¯¦9r¬èœlÿV´xð¨#6h6ÀêD¶x0¥Ë)AX›³£*0²¹ë¯_#.Ç·†È÷zìe¥HÙÓ,›¿µñïñ²5AòõÁÞŸŠ{žeÔË7Sú­þ¡&yÖYñ¯¥³LÅSÂœ¹¾Ù?•”¾ŽÙƒÊ-„y¯69^èŽ}ž¦pà†BI‘iK‡&±nÎǨŸþ³…éÝs»Î¹ßŽe²‚ð,¼&2:LäßÏå[‹«¸óxHÇ®*–Ø×ÒU9„åé1䌟 DL5;þ²ÏiîÐå‚„QT nUÙ‘`ÒŸ#ÍoJò4†1Sºëïv馫ÚÕéa離Mô4O|®­–I$ {U½órà¼0‡;0©*ÃzG/½7ƒ+– #%Qb ]’öÙK\.ª¸­ÌÖ‡÷) I9q×ëa¾¡—¼òó#.ÑýýïÞ5К¾ä¬×w*8ÙA—'<ß:¥˜bÊï¬2×ÂxÕQn:ú,öTl8:<ôáyï9ëCÛ¢M\¡"#.JvX¢=Êóðw¹Ô%g±œCÍ•P´GhaÑû£™ªºÅH…”ö)¬¾U.ÎõÛ™Âî‰A=†”s È«Ôs›H]#.¤ú$¢8.‹\Ó³Mìòõò³Þ› TÑTaÓMš}ª P‚ «½È¥>?‚¿½¨èØkÕborR#Rñ/ŸÌç*3ÔÆѦø–Ú4u©ð±o‰c‡ÈÞéñÇ#.vnV»pÁáã)r‹³Z”,ª£Ž.O€êÀ’·}zwîÝlnª¥Ÿ.LQøy×@EHiwýÐçç=Q›q§"%V2&0+VŒq¬¨w=Pë¦uÁ7ºV^-Eu©QQ'çU0D}ÏéÞ™Ni×ôñ$¤úÊ'1ÎK¯U=_­“lS­#6´íŠ0ã×D­1zßÆǾ+âdpÚˆô±æZ?wéžx½\`<+½—f—Jøã×~WKËÕ¸îáÝ8n©$z«G»à<c½Ì/Y€á÷ˆÓ vfˆz3ó¹L´cz7k­ù%ûÚEΛY¥ñ¹-J`]ÞBvP\ÃÚïŸHm2LˆMßwðrÈ÷4›:ðÅ’µ¼`¡‚¯\Ô½u}˜<(ñf`¨Åˆ³÷ôͽ‰UQ9c:ªO+%‰ŽöPiP/º°<H¬§`±È6,Iq¡z<À®÷±¢—Ù è‘ì#Œá?Ÿ—™}ûI”¡ÓL»_KÃ'ë—B¶Øÿ#É+ù¢ËÖò„|ÑúåµömŽ±‹ת©ü°Œá˜Ç’7û"ònþ½bôŠ#sh¡›¶¢~¥?~´›V]6k)0úô£ ¦ÙUBÕñ °Uˆ¢,õ'«@ž5ûÜ+ÏÕlŸ±X6µÉ nŒ.ö{pùèü}´:ÑÚð†y¥ªŸbsf19%¢ØñZ³æ#Ô#6 ‚ ­ê,&Ñž3|#6y€"ú.$#. #.æuµÅ.÷ éÙד»*{gd¾Š­evKfûQοí¶ÒÌð7N ›hÄe hP"1b±êL`ÅMm¬"ã-ÅX]#6=™©Õ)˜«Î#.äÓ2¿+]øºtÉg“:Ô00Y½UDà’ÆŠÛHœIå#LÇÍ’6\j¾}›Þ#.‚Û»Æ6Ñ=U S¿ÑÏÞštÌ4så Ùº"ïg³.¾‰t(ÄÉ:qþ²c1û¦³^¹ÙÈÕýÉn*fb’¢fƒÛŠãš;èXhêöÛ÷Ç1•£a¼s>¬=N#.ä÷Áý(ûqÃÙ†fT`ÒalÚÞœ~2å8ŒÀr¥‘Ÿ¦!:Y@àe ¨Öj¡Á¥N¬Íec±;8`i‰j%ÉÓcW?äDM¶@0L‚¸¤\Þ'k‘KŽ«®NºËϧcV*±FÖ˜Òßãñð³Ô9O—äÇ»éìåôÁõ*5,<:Ø’|EI$¹$G4¡Õ{âS§#%bŸeÙ‚‡TöŽ¯äìÚÈQ·Ø!û€PveòóêÞ6‚^—ø\F´÷fX= ”*´nïú>Q/ãnNQŠž#64…¯¦E¼×^Æ~ú“’`GÈ'0’õÍ\P”DØLÍÕ7؃Ku„ÑohsyÛÝQ¼ã*Sšçsƒ;5XvPÍf8uŒÁ®[˜ÝÒS¬ÝÏ’³•ÔÍ4”¹²†s?…'ÚÝ­i Î;¾n)tYG.å¯K|íMÆ×6AâÖuü×8'¶¿UÊÒ»*se¦Ü™L)e‹8«|Šãý×W#%}O`×|AÊ>ƒbm€fò†\sIÑO##y3£Bé#.⊠}ÏÕ¡n«r£CDb+ÂÛ` ì™­úÛn¨>O½Õqòh‹¼’×59·b¢ fŒ~~˜V#+bç±^Ug•:^óŽ×ÿxºTq(Ū¿1™y{T‘áâzÒÔ²?[좧s ˆÔ5YÿÆgk’ —qjûWXvã_WmMÆñuÍZ3¥Q_{=’žìã³—¦(5#ˆ‡„Âæ©CÞØ ¥Î]«m9¹ÙãHˆ X1ºÈ½7¸ÙŸdÉ-”K†OèÜû¿—ŽqÛDË‹âíÜ×s²žó#%$ÌØ@²š%"£ÏiñÁGn¦· —›šÿ¦åg­sáºÖÉÑosã¢Ñ+-¯m%b”"¹mofŽŠÁfm{pYpÐØoÆ­Z”̸ Â4¸b³Øúxì^S™ÎuÜÛzVþîlbݵ Ï°POæÀŠ:›»ˆ¾Zn(Ô#{›7)×¹L ùσãÕñÁ”€÷YÓ¡á‡õ"6zXø£°ébc™G“ë-þ7J-YSÕ–#.™[òw_#6}P$RFÂ/þª:üó²§HèCþCo:“Të–=49yz¿ÃÆÊræÄ•{´R4IÖÌom¨3 ]•F“m;Àuc£tÇloz‰Á`(]ô¿5Œ¨å¥÷!œ.º¿»ZUǤe(®™¯ù‚Ê^ŽR÷ F““Ö\«ÈÞ¬Ãô²†Ct½FŽ«X 8Ž,Ò;hŸ˜Xj¾$8ÍûYùüxpå»È6püà ·Ý¤$ÀA7ýc€%#%%"A/üÕê¢c–å9Xãßá]5GóÚY"E5É#ÁÛ/*9/„QÉ?Bu˜jÑm-Ã&é;ýz|ž¯‚££Õ¨l@'ñ(¢¹*öúi|GÀS«êÓ©ÝœKð!7ÕmVÐÒ×>ƒø³9€&u ŽÈ„ƒ#% ’ûÿÕ»Ñþ-¢îÕáø­ÇîäévÞ»¥ #.cc¢¼¢ ÎD×Ì@?Ç4#6†¡o轶j0–ê**ÂŽ¸ÙsóîÅÇ#.„¾º"MŒ\îª"ˆ¤‘ò©¹#%gíÞœá4yR™b(Ñ>@€òtÆ¡R¿šÒ]eÑ·äsvÓ Én(+VpäÿE®‘+ü'6¹†ðN°¢3¤Ä[(ZŠaÉ»I{–Þa½x=™Ž9"1ˆ[ëJ¯l ê1­H#.ªñŒŠ%OÙŒ#%”ì#%ÄcÏm¾ÿ¶ç•aùã¤þÑI‡ç³ñåú#.5™ðׯ_ó~µ?èÌO“HÅGTUÙÀM¿ƒðý¶y´»õ¨5ц6¥—Ãcj™b²ø§¹ƒƒ$|_Cºuž0€^~c_ñd° "wƒ#%°>בj>ðõ—ER=Sþñ¶s|º5ŸÛå€Ãm¶fÕ¿.Õ4|œåÝj]“³‘¨:;£únŠ>’Ÿñ:ÿn@ é )ª×fËw#.·l¾¡ßþ0}÷îâ£(WÏÎüoNßÛès’ {G4ÆÞ|ö0t9×bbÎ?GÝ÷k_ÁÉfª ž"@îkò•X/E÷;¥fL¡¦¿qößÕ5¼8±“d¢*¡â{/Ìë¿D4áÅtÉšûàûoötgS³wÓ>¬XB§<ÈIÁM•mGý—ùu…9£Š>¿zsáþ¸'^Í¡c®¶7B ªƒ+Ã…À3ïr˜\«poª_P–ÜâÛô=‚TÁÖ“æõ§º»¶4ZMI:îäÙœ³[Ê+YòÈ{Q”Óho³…`#67]±áÄRd1ÌU…²[d"ˆ—”b$#6Jk!¬gÛªLk Š$,¸ûÌ£Ö[ËúžP&¶Ï•¢U´’†ð¼U1#ÅË;§¿&b±A…1dy%*üüóŒî€¨ "/Z7—cûÿuËBˆsrœ™§¿-‘œ$ýþ~…mLÀ:z®X»U ÄDq#6“Ïß©s <=Uƒ¨~L …¯R›5¸}Š ÛVIé­³íLgï› ¦aóÓáåvº˜ÿ_E—F–– -™áG8˜Ÿ“?ûmRGÒ=bSfqÖ7¶ÆAi+sèü"Ê|;O¦$÷#I±aiñÓíÁº×®[Hå[#.º“œu€ÆÆŽ²X[È—¡J×<óÙT¢ Þº™ÆÕQjª@J’ßü.Å#%…W&û9œo…èîD@¾Àß#.âë…cû§˜A,BCG:l¡úkLuÐ#6”‘Õž ?; éõæk¬‡©÷‘ž#.qÌvÊÐ3:^LŸUÈk4Ž#6`#.~•H‰5ðÏÙž>Ãõ›÷þ}¾Ó¯‘[ŠhyѺBJ2\¡~¬dâe#/¯ÿa7·§4ãYUáCÇMs÷þ{¿ÍcB'$Å;Ç©·8¦ø¦#.{,µj€weß#.røâ^˾<0fxþîÍÎ5&Ī¦š6P·cQǘ"5Uô†÷êŸE7¥ã˜y–l)p™Ú7úµ!$—Ó8>ž{K2®rãyòUçD#¯lüw¯åz€ã=wÊ‹Ý#6Dn…¸}^æ¡}ªé«)D¥ÐŠ”‚]âuq·à¿çÛ³2±³…®\ÚS{ûìSXãÅY% qßÀn©ÇA#°óÑUá]=@tÔ³žÅj&†Â»Æ5&fîŒðpK‰ ¶˜Sd&vEÚ}´zGYÌ*B#6 ìÃQ>Gêp¬vþ—Û…m}M‚ææ‰ï¤É *Ý0ƒÞþÓpì÷Æûè|A²vB0;½–k[Èé#6¦h˜"# _ ßzéòøÍ3ã 2&ˆBžÑ…5Â6‡…ܦ2,,»¹Ç|زØR¢"ÈQˆæY¼° ÆÒƒ •ÇLkG>'ôjŽ1* Èéô‹uüi‚S1ëŒu\SdIiÆTˆ°Š²O¨6ƘڱÔá‘¢»µázl_gêÿ8hx”MöX0-ôî ê#ôéŠsüKˆòÿ5ö¨»?#%Ýyx®)–˜À’7 y#%í2òw‰ ÐPc±   Æ#%tÀ`=!#.fîÁN¯%Ò[^v…'k³Q÷Þ´R“̧`ÆzÆ) û¼nuí¶#ÎÃí?.ÒIpJ[¥iB¡×*,ÂÒÅ š=ÕÕ`„ìQ×pgc¼Iâèez«ôC,Á†f{Ê2ѪRuš„Æú 빈7©Óyå_æ>£vöt…µÆ|ú9´VKœâR˜;#6(<äwãC)ª((F‚Ïv0ñ2hÊЭŒ–ˆDÊ#0+C“9°z“˜¼•]>ÄlÑJYb¦„ÒTœ-¨¦Å¾bàèÁFrÐpõŽ*(~¨Ñäû£sÐÌꆄÊ4 u»y!jŽÐ#8±sy#.bƒn=>tzËÌh†Á¡ÈÌ\åê¦å­…bPõYÄËþ:¹Â—nT ÝÐ`¨é“Õñ턱ֽnz1»DR‘Å+‡GèobŽÊØÛÑ£ŒU$2ÖåŸ#tóëñØó^¸émÖ½¹ªO8«,›}YEω{^ÜIfxOÐpLÂÅG•#.pßú¿‡¸ÊYE³>vKUÓç¼çûˆ} šgا©Ú§^Ï­ÜøÌÍ+#%®[Ÿaœ:9Þšœ9ÉÃd×+àB~e.wµ†¼qalñwE#%{j›,dº*1—®íwyæ]®îëO‘˜ÀFŽn‘snZ*4x’m1|F¢ ˆªÝ4s¡ÊŒýÖž{Ζ¹,äl D {#%ÓDhM´ÔD)$CTÅVƨʣ}íÁ14LT.%"¸ã #%l@'D188Ö÷#.A³èòñ®$Õ^¾0Ʊ³\´h$‡{Þ®#.NUzJ);I?×$è±ØíJö»‹? v#.ê‹Ùö‰T«T¾î°¦‡ãaÆ»EÀø5vÈbãlyA}·É¹»Ròš¢C÷)K.Ç(…ösN\0p¨¨S"Ðoœ*ñ“!WTðCyp2b2„ˆè/mû¬kÙÓY¢Kn9‚†¦µJ:¸Ü­³\ü{oM—h]¥ÂŠfŒXn#6àÛ¯d Ó™Â/QƒèØ…E®‘KNÀá®WöÙ=þ= ^u¶Ã?×›íÆÊ“5çãœ+8~Ñ…ZF0oÑ›48Ã@òð_¾*Çc0Z4ÛþþJ˜°q …áF‹Ã=’tÌÐÔ%Îln¶b–Š†æ˜¦Àé˜JÞ(BwyÉ.ÅBjܘx†HÃQ•TÊ8¦4c#6Å|mñd@ñ˜#%†ŠÒ奉c‹6PºËÈaFĈ`Ÿ]ÿw&ÅççqÕ2ü2GµÐQˆ¯ŠÛš1R^+¦¯LZ¾•yïÛn@m2(ʼn£-eFK`²(euDÕ 8IwN`;ª–4,œ:$VbV66ÄPEBD 2ÙN—ßYö;üó6é}rÛ=ùk²#6_³S0¢³*¸‰B¬¥yÔy¥,ôS°X¾.‡9€¶¤Ëuª‘ë@+ë#%)|ðÆÔÔ@zæX"% F #%Às´õ‹&Á;Æzüiûç|ú¶&í•Ÿïöíˆ0t 6‚5à1”L Þ=Ùôãõ¹H 9ív ¥RÜð¿4‡Þ{m›ÇnpíÔ+ãÍ=ŒSº!tî#6oÅgcì—tn€…™©t,–Ülu„VFÆ”±#.Ù%Æ·©ƒ_NÃÕsËÏù*\¶µ8r&Aö„²ÕÚ¨N6˜‘÷KY¾#¥ö’ZÔŸŽÌì:‚w¬9§ƒUf ‰Þj  Íñ0“ÀF•‡+IŽuœ,—NcUGEæÿÏ^ۤɎà˜4ó$„Á;>)Í™n$"˃ýȵ7æÍ–Ñ ÷šÈÙf1¡ýê(v Ž h«éC5ל`ò ã{Ô R#ƒ7(HTZ'ÖcJ­:7 Zf6NGÌQä8@ª‘sIÊۤ܎jì’Ú#%;qŒÂnwjÙ˜Q±¡3¿Áaªê©i·Š(Vj¡Š(bõëVðÖ\ÓâM´0kD>§¶U‰„zpNzb#.ý:ë8á“âJï}ŸC•ñ•Ov(ÀäOË ¦Ãÿ¡˜6ˆ8H^&ì×¥±Ó³?òtÇy™ë°#%#ûý¶¼·6é³]Vâ¡3‰ée›Á×GY`IÁ´Ú·%®Š ¼ï| HsϺš˜ÛE“H:u™Å) ²,Fj0ËsVºY#W6é­щ(4ÐÅ"´4Yˆ„aŒdtªÙ#6‚#}´‹Ü¶`Ø5ŒMõøf¤ëÀºfmj Î(#.árµ¯ VŸ¢¿í;'\ãS—´)=ǸöòÒ#%'Ü€”#%›½ƒzÜ\‹n@|ʼîmÛ¿6ôÙ ²êö¶¾7Ç¿ eÊçó)vaÒ¡ÃHF‚Á‰ XÏÛwêÖ?!¿òÑŸŸ©›Ââýj—Ìžx‹OuƒÖwð4r }ðÛãæáŸ7>ñ§Æ(8Ñ_Ì]`#÷˜úv#%ƒHÑ=©“UŠ°Q0…þrm¾H%x‘; Öõ‹™ý¹….?½VI|gxûœˆq¨[$›î}PT=]‘#6 Lk+ƒì ™•Ïãý¯²K»d9r_ Ÿ¹bD³åAˆÍÝðü(òìù· #6#føåðÝÿ¯c»ì²BŒÜÖÝÕÏtê~jðêêçßlúü3~i»Ónˆn>ûy¾{çñ~ùë]—‹ Þn¨`"1€Ø{ô°õ¯ƒ©Y.HGs$‘å<šÆë½\GŸ<ŸDºáëߧ=~ÏÕþÓCrqy!áã^H³U$ÅÕ2Änà cèúÔb3AÙîù½ùa.ÁGc@õ¼#6\Q\RÒ9¼ôUäÎ)u”Û¯ëqV RVÜ°¶·úûJ#%Gh¡ïÿÒ#%f—÷,ÛQ¾ß·èøvKx#% œè¡”#6€”»—wE·B¸cÖáÄîâ§Ï—¹øj<}Åz¤4:CíÖï÷7¥d€B‹b3Ôíh"™µ%“D˜€Í•,J/Îã14i±Wö ÑÛv¢e»véRŒIKûR…IXñ¥·õ‹jý_È^Ö„ÒVÅ&.Ìýü²Ü2SQui¶ø]ˆ!C†û^~7²^4snë«u*䔩󫺱5øuåw?çÔÕû%`¢åÑ©ÉãüjRD>=>ÿòu>œi>ÊÊ:##69dc|›ŒVþé­nmü/®ž~çú•´J:3#Þ'$!éþÝPY]oR®ˆm½$­òZ¯&Ö¯SQUQF@ö#Ûá aøè}ΑÙCui±œb)f¢y&¨ƒŠ•D éƒ*þn&NSìÓ°%ö$¨áTò¹^%\…™ýÖwbIlI{VTe—ùä§îjÅ‹çƒÞ•¥Ô:±…Ø1†’µ&óWR÷ñþÑùùÜ>2…ÿ#.#ú6q4¿~¿•ù·X30~>êí{P?œëF(¢,Ö>_#6à3~ž‘­Úˆ#6 ïž0\îr›fžÁ«#6C õÃü j1T,jƒ¥q¾#6Û6Od'@h'Á¤¢$„K“ð²åª¯1¶ œ ½šô† ±ùË=rÿˆ2·æðWÕPÅŒùw©1P°æ(óÚ‰ùPŸ™´†îΔVåRh!0ÁV“ñJ@-I[ú¤\T(–#6N=>$oŠ¿ƒïŸ-#ëüþoÌ}÷~?©¿SÄ>áŸçú}+ãä™SÖyà-[O¯?8Ñ[úF©î»ÏDÐÏcÒÿ½tz/Œƒº~˜ùÓïá7|çé6`¶œ¹‚ð‡ÍVúö«Ãñ˹G8©ç°híýqpä"#.ó$`{z—EÂêVsãbÆG˜¹ÄL¯“<„OeпõIGá=}}›’ô,k±Þá<öv}²#.¹—iÒå•ýº{ã¶+¦p±ß³0éý¹@ÒÍîÎÃ{¶uÁ#uwDa n'ª@ÆpTÏÝc#æP”OR˜1ß@y÷^¥ïPÊí8jßeÖÑnvµåô¸aËA¸cüU&dã#6V]#ÛêG²S "‡ Í÷ÙKÎw-ÃÑ4¾Pdé9ïÏåp.Q¯„Ÿ~9r—a#.xR^ö s›eH»q(â>ƒýºë9ÕÜ{Ϭý°±øï½áäÞQEV§ì±p2”/Xu|¶]æ¢c=!U%äi?Cù… CØcX¦ËìÆýýøPRv²Ä…¥24q`Þam;“ÿƒ ŸÕÛ¾×Î_\P Wë¾ëÝ2ÒÓÄ«>îþ ë¤îº~š¤>¶–=TM@òjj*©¢³ÒB''%=-–uûûHkû8ܪpÿXŽËؼ‡¡&>]°CÒp}!é8‘BvþZ>Ö-øÛ꘶*äĄǸ„$M®pƒ9@øI‡Hg­2q#.SýuFfŸÑýÿ›3ñyXx{Pî-ô2Ñ°oõIöO¶ž–$˜¬'Ñ¿ÆŠâ4ÊјŠÂCcíÔÓ×å óí5±y¿oœü|zÚ1QÈøÎóK,,$o_»Cd œÌˆbWά¯Ÿ–¥éŠÕ áZ¿V3XÀŸÓÐôüŠ¹CŠE.}•<åÔtÖšžv¹W‹:ìN#K»aÝÙ<ïíáËXÿZ0þ:4°4n'ô)¿©cç£*(ÑZ1F © ûÍIpŒ[Å ]E}¹ýæ™æzï ‘½Ô‰ˆÈ‡@x#Muaͧøô÷{»þyú¾ošÓé6låÕTÏG7°èôÓ6”Õò}Y]ûü¤~zú›)ùí`¯]š$Æ‚–×=ù\¹µYÖïS"Ëàîý­ßê#õoÛ}¶?=º;~Îícvφ\·X!kÊôCÍ~8ED´Õí«ù¿]mRáã>^Õçá&÷_#68êpbo×—›;ëvدµZSqŽ§iûöÇ÷oöjíôgËÈm‡ysrËG÷t{œvǃƒh²à¢á`×æÒúôÏG7…m óSžÜpa»£:H~ êþRöÄj9\RAï·î~^ÌîéçÇ]%=†"Ëù™é»‡íxâ¦É hæ^†LG’ëe#.·s-”ëÝÑ3Ú÷ÙÌêÏæ|Û%”n³¬|ðjãWuzµ}F×péÌœ°çþS¶1†š¶¯‘ãLSèyµìÑ­}˜í{ù`-¼-§z9Ðó%[¶5¡v»º½2Î;§'D‹?/Ã?À؃}öÛfª]wT¸(9=E)#.]ÙYY‰xôpaòÆÁ¿E3Æ£Ü0¹ÏѼF%Ì.lAÀ>2.sºUÍ?¯Öç½FŽ6e2w?.ì·Å¿–=ÛüÇn¢n–;å"^¯Nù]¦ëûi=Ü[ºó´y8bºwc|{a²rÜÞÁÐ#šŸgŽwùv[…qýª$R¿S›ú>]ÚwæÿÔtf¶³×ÖžOåð{£<î¾ßÇKjØtcú ®ê]·yïìDZ¡¯Ú’ÿ°Ëà” F«àËÕ¤pøzŽì¡Aó:Ð}Ù"¼p+ˆQÕ‡“ß_«ÐÃ^‰/±m&­îù<‡7;›(|]o”ÎÇO%~Wû™ß2lSœ–7µ|r¯ýæ†ï»,èá†vENJÞá^[#=6{}ŸÂ¶uýŽm™`žóùÌ~ÃýîÑÛŸ]nåÌ)ÖÿîËÕè¯m¶ÿ£Ïª£ò©#6ù¿GFqŸÂ^FÌÒìò7ðü4µ?w·ö¡(?1œ½è„ŒŒ®ßçõ`¶úO·¯¯Ûï)ÍÓ["†ï ÆŽH#%õ"ÕËÆÐ2Æ P~kZ#%RE¦)#%éŒ:³»“ÿ£O2ƒŸìô„ý½£•<Ý~¯Ïî·•üsŸ?·åõuåÚ%÷‹›WwPì»4ô¿IÛø×~÷%IôiÓtêüÚoæòšº³¢qüµiAŸ£ªÇçÃ@ïîøgÕÓùj¸aõv{À>ÑÀu.Þ?üB…Í´t¶¿®gºç*¯õhÛDAþ óSö䓈yGÇbeÎ>Í_ÝøþÌ)Ón¢¹8h¾>#.[¿g®øÔjý ¿º;¾œœ0v½=†áÑ›Éñ¯Ÿìá¡>1û4Šðx÷ gP#÷h÷óñÙÀpý_Yõ¥©Ü;ü|PåVˆQó•ñ=€ê?~‡u±ßåmAì#6`¿Ç™«–+¿÷¶ÔºÇ%ð#.ý‰Ã“ ¬óS³÷wt÷/vÎná#Ͷ?!b¿ƒpv ùlîâ¹ù;òžêÌ™/Ð|S¶ž9¢ ãþ?» "(H;G¾÷*Œt<&/»éÖ†ûçë’GK÷Dj`’à–õç9K#%#61ÜT'&D¯žñª¤½Œ[-2è+˜`†IBfH&ùÚ’~;†A΋wù´Åð8,†È¿{#Y^‰ýÙátÁôM ÏŽý®7Ü}·»,°§EÜÜpà…#.±J‘ÔÁ€ÐúìŽR#ÕÃîá4¶LÜhâ+µw».©™À’Xê%äqh– !ô¦ÏÇ~žIèù}A7Œ®«wèüº!À²h;ÐÁà· -˜>ðÐB)Ø ¼³»¥JÒˆ®Ç“>;ÚëZÁZ;ž|%9µdC–PSx½óƒsZËËgDås£wr×+)°±¶1/1B+SéÏkÍÞ·_!†(£«F€+~›4sgì¶W×M«°ìÆç/Ïö´©ݎ߶£Ní3¡hžl‰“3û‹Ý-ÌØm=O‹£Ûóp>Ø#&þQ¬½0â/Sß3 þ>mM©‡ñw“÷ì\•ý\} ÿ“—$Ùwü÷y¡ÔR‰$ìØú|¡ô_ÓIØÈDí'¶1ulu³LׄãÏú[=8á'x¿ƒôúè3ú†A¼#%Éé/SØC¡I%yb1ÖFÉ¥Góü™*”å˜bG‹ÑºüCª öIO4|žÿHï½c ÀøòŽ»ÚcY|uŠ·‹>Sþÿ—æ#`ó²{ÑÊÌáþBÔfeÌ©cv²Á¨9G…?G¥F5¨4iTlTŽ Ô¢¥nØ€Ðæ7#6ªÒƒÀ¢¢,tþÍÚ›HÁ¶¸}=3†´Ö¤On `˜a´ŽÅ-ŽÀ¦°Aȱ¬a¦ILA«"hhn„)"–4±[VWŒc€ì'Ë#.Ss¬6ÐÚ]&6)":ýº[ÅÖ¡É \’6ö‹B{qZ8dÚu‰ýÿ¶ø[Ñã"?›9ÌgBPP}‡¨üÖÊS<¦³ =a‹5þrÐÍAÉ]E··cˆXw\Š1´™ac0]WëøoýOSø\ýVæœ#¯#±E4DCÄHèé@ŒÖbï¡i7¨1lXT¥Q&FÈCV ±6Æ›f’J¤ƒÿj*P´Y¶Oà9þ¬éšq·ß›åñãrÌӛܙïëûpì—A¾öFþÞŒi|œ-'Ôl³D±€œçj·UuwåËu¾_…ãŸÉfºòöWV¯Ùãõlò:­ŸŸëôeñÖ1ýèæÕ»ê(¦áLS·ñþ>ܬù±ý9Hþÿ<ƒ·ˆjÄU±Ýmù}Z bçvù–U²«&¸ê²·ü³×†íú¡[GmC……fŸj#6#Ò$pçwÔ]uGÜ<Ý~ßÓø¯Ó§Ù£O«¸¢Z„xûþ#%8g#65U6ü;ܶ>®aL~ØY¿w?VPèÁwÙu~Uwö¹\ç3Ü®“šÀÂÐÃÉÑkøÿ.¬&5)n—|?±½¿>¯&¿án®nàM>äM¹¬ý“ûôwL[% û"ûBßæ<ëά#6)_@è¸à\S¼|8¿ÁéÎØÄÑ›^F+rEµh‘[J%c§l”õX*5¢gtõu¼^´yçœÛÆ9ÍfRÉ¢((Œ©[\0°Ä£#6’ œÙiéÈ¢ Ôch¥b…€È£°µÂÂ44W VR²ÙÿÒ£FÁ÷R­\æŒmFAKT­Q eBÑlB†#.°Q’ ƒtêMæîy3‘wä%r(*`¥2ƒshÙÀXœ;Ýg6®¶JhÇTChÆ%™ 8Ì+:ª-!ñiÜtu,¥µÌà’‡#.óÅ!ÚÐ@AFšþ§YÙ¬†žuD³Žmé¾#.äQ¡±‰‹$I•8‰ì ~UÒI‘#ü,D¢Ö–%\ȪrF‚(3š*ˆÂ®ÔÊŒp#®²R1Œlž°b¹ÓòJ®x3¸ø!U†$‚’IsJCÙõC‹ID&é½’ôAŒô;/ôôÆNô˜}€Ë ´íäë-ûLH ¬^Þ@ u3ÇD>Õ÷z“´ö#.QùUôhÉz°÷ý”OT=¾÷góxáˆ$g±S—óPü-ΊÃáÉj»#6ý£×£ŸLPL*ø–ý§f¶£Ô§ü!½ëÉ3§F9–û§ùj~¸îîh¨xÊìƒÍcÔºåøËãïÏ›""'NõOU87«6« üVûú„ÖY´¹ÄÞÏÇñ}NO#ûjÒõ@Tõ¹€â9Øs ‘•ûÊvA#%_œï†${Ó«”ÔŽVì6TÖÙõ¯’=óø~ç–{àäm·l’_/ÊÙµÇÒBÐ’Ä–'Ÿp€âqCó9Ë‹è‡æ÷¯!üyI£×<³ì©«.V|¾ŸÇÕ!‰æª£#6u¬êyÄC¸î'·>Åþ¹õüܯ±­öÝAe;6LèǨ4«9ÎCH¡QH2t2˜wT9"+1r_uLUv¹ä“h—ì¯F¬ÿÂÅê‘€wf\„F±>ž™[î÷QâZ%T»…#6ÏÕ¬ªŠÿM[hÅe”£$#ˆÜ‚±#.D¿ºÅlÅ˦ómòØÊŠŠB‚YQYCFF¶Ï7®_ËäÇÝã³áê_{HUuí;wùüÿ§OÉ“A󭬺!BAT‹‚1ž­sa虑sÊ,¿] WÚh&6p¦41-6—·n›ÑHÚ)¬1=j ±o\ËA„y©Y¦=Zﶊ°Ì#6Ô«ÉgAèpE30ËBƒH¨Á‰”V¢À*ø¹¢hâÒñ/mˆŒM}RdCÝ7ˆÌy#6Ú´s¶jdßå$ – 8ÛAmb{€„&‚ãì͆¬o*ž ©H¥›·86AUƒ„Œ‹³àrYb‘ÍZ¨¬ÛÕ§hCZ­¸ÆÛ…‘2SS­DÍ#.H#6J lXdL1aˆ4KDã#.­‹G‚í3³u#.Ðá1¶“­¡×l°lôÝX Ê-“m(Uz§ûÿñhÉäŽø1†µ—š(UX¬0âØ”©DƒlópÈ#.Ìi@¢OlƒÂÕ·åtS¼'Þ30\G¯øøJ½µ`CT<ʤ2+r‚i÷MŸ„š -+A‘¸·Tc£´øìz^Ƕò—ÅG=Úæ4Rë«Ùî65ÚaŽtHÇ‹µ0 óF‡ÞG[q·º¨ÊN𮋳 þü¥Å Ÿ™ˆ¶<ª¢‘¨6Óˆ®Ç!#6^¹"XÞ<(²ÀÐœk]o3ÆÌÀãH›5KœK¸´pLÊ,°¡+&°,”Êp#.#Za¿*V>#%ÐÎýhÂ8p™˜Í†K§9æe¼‹õ².l‘m¬8ÁV6>d4#±C§›à­¶——ÔAܺÉ&Fèé ᦠ¦€¬ÒKbíV4˜Î Ø=ÕÝ ¸Døn$DN÷»A£PÓŒ+gb†XÌ‘Œ®çFPá2-îc¶+Pƒ¥ò)2ÉÂ2™+ç*³v»ö—w?Ãzwò_Ûü9ô[ß™£oƒ×ûiþnþAý— èyÔÆÓýb'j¼ç3Xtß1ám¦,¼3êtäzÉù~îìa#.6uqöMÛ‰ó¦q9°gì,ªÄÊ;÷ ÁÍS¹(v-ª ­ù`kb—ô»­6ßV۾ϱ£)‹`åÈf=NÜRäòAUHtF¨ÚE’ëž1’œÕOSxWxe¶ãjh¨ˆô©Siyiºf6äÜ‘R®©n1v6«D˜E¼ Œqì’T'wÜÏ€.›gÊh#i™£^ÞM¼h½óé¶3`ìQ±q’&Úri3haÔ”9†ÙÆbX±AO}`PwÍUí«3Û¡~ÕoÒ_ÇúFÅš°¤<N=¦,Ü9}Ð'pø”F_smŒÕA—#6#.¬:M³±¸Œ-µÉ°àzÌ! 1IË(Dâ8ìMpî@Τ2ìl+ñ"V½†Üq·ž*t;$î§iœŽ¨Åo›;n3†Ù†-ÏŒu#.põQ…boyN×?u°ƒL…#.¹}#.IŽƒM¤$Á„ x¶ï‹)—Ï®v¼îÑŽ±­nú¼…Ë@:kï¯#.K¨iccndë‹ÔªÞAåj«[É•P]ÃK©)pU7ŽUØ"wW;´Ç ƒˆÁ’ß’ÛÄ!ÜÔr7 •JQoùŲmÛZé\¨ÂIA­Æ†àˆQÞ#6:26#.Š]î;ñ´ïC®â¶£¨ë³º ¬›ÌK%c¸Tnq°QÍ峺mñÙºâã!X ÷Ðk¶Ö·ÚåÇF=ˤV¬v„NŒSuÕÑÆs'&vl©”4µrÍb< vj—N›19ÆbÉÃ"°Ë0NrcZ6ŒßW$œãdŠB\ÜÖŠëwl #6Ó¨cÇ.Ûldå¤É6µ&†Dm<ÍŽc/³Ür±±5ß ÕoÓ:Ù›D$âoµ}ä«‚ÅÇy溽<¸üþY·íhÕŠ@óμžKaNâÒW•GiÝ/_³ym§,­qGr0÷GÂÜœFŒDdªõç›V׆¾†’¿òÜdIÄäF6$ˆ«,Ÿ©…5·\m4üŠb-ßöÐTM^í¶"R§".f哽ÿ¾ºáwu…œ¹RM|an‰¸ê!Ô¥•“ÄAl©·KÆ’ï ø2Ý䀹ÐiߥþCÒKíWnר>áüpbx_9³å¬×WÎŽ@žTÛBðÑŠZ·¼Bì–”b>ß_§çcOVz|ymx#6fǼYJ˜…²-™Ê  0#6@ŸŠwßwvOóÓ®ËÒëÎ!‘Þöƒ‚xnpŒF€°Q¨#%Š²ÝjŠ«ÀÎÇ·e#1T˜´ËRV¡Ö1(3‡È40° cpç¯T‡ô沪ÎA›œÏ¨9zâ"3áÅ‚NÇíí<·¹“ycÐœr—v>óZªQà:¹ý탂%ÖД~ND|²EÊÉ´à÷Ô%¸< &ÙÚq4öÁ …)UyøèÌùÿ_ó–Æu«޼?ßàzg nõ¼;qËô;剚ރ†Ò„&LÅSå1ºúeÃyg²)IVì–\—.B„m0J°þ’[qƒkdÅ°ó#´-©`®Rb]­8ð3ŠÏcÝÇÊûO¥Ÿ]ÝB“$ÄKÁÇ|\ÀÈ›|jÌÅg}'ò$j­•a±áêȵ¿<4Æ=6=&¹|§‹ð»®6…]ºÔOvé¸pX»Ü=ôTŸÖV*yumžì…+¾â1e¼#µöÚgDtž,DãFQiwqlÞŸäÀþµ#.س^O¢ƒàô.­é¤îÝϪ’‡-ÇIÐ÷]ÔAõõ…îÆQ72„I8€ïxL’joLk.ËŽˆ¢MDz=ýtï&½ó:oŸ$48;!Cªpóa}j‹ bÝ›94gÖ|«¯3­ß½›µ4#.ÒOè%èÛÔØ¡ñ­–ÓÞ:Î<4ÅôE#.54òì3R‘¬úTW-Çðk¥³øyçÈcUéN-<#.'çik“é;!:-DŒ¤§ 7)%#.M;î·$®ƒÂ÷h.Ø–CpíJi“˜5Ðéï¬Zñ™9þ®ß#%ÿ‡7±CðÉêpC ‚Ï#ò‰Á´ð ü¹“ßrÞÓ¬Grɧ嶖“9¶šE„“J¥™Í•aÕ…ë¶ú`xf¤-0è´%ùk‚ö2#Ž¼üx#.|^š:+Њ „ÒÉù­ÌÛS9lVŠo•azâ3!m ²<…¦y©CÞo{vþ|eŽûüÿdQ茌¶F÷T½Ä½Ïá~;¬wÚjl .r<0XîÍ1`àžœ1ß¹iê1æйºKj„¶Ó§\ž¾¯‡å;åd“ý|†:ó»OeÑ¡ÌìÉâcs§ãò²Íc↛Zøô<«LÁ“QÖE-¿”Æa H •àòµ0·Nõ3\JܘrSs t UýÒ>\}[ˆìäåúžŽÞc‡ríàXZ.ê,¥¯Ô#Îfi?ú'î¤è—DÁµÊŠ©æÔ÷½`£Ñ@ˆ¨úã´#6ˆoÍÇ~ÏhÊ0*Ü×ã:Ö hïÿKC¼i´Î|½_ðÍÓÃ_.¼71¼§½Âu"˜¹r—Fxô⠘Šç#LþÒ¹Æky™—óé“>Q†9¬€Àȳ÷›#%hÍÊÈ(²…Ÿ¨ˆž+fLmìßãh”}ƒãÄuÚŽŽBN[ëR fJé{ 2ñªA·Pjפ/ñté‚£YÚÚ$ùyPñŽÖ–øêú뢕‹@…)Õ§)O”~U$BO3âud¾‰Û1/5¿<’k«æ‡U«xd›í¬½ìu¶ø¦ta>y6œ­¡™û5œÍNîQáp­NHèºeò¸è>–·D.•÷*EdÌn2,Y—(迃f—ñ/¥sµÒ› ñ˜D‰µÒ‹Óô’ÌØ—›Ð¦wN—¯®ÖIóíîç#.¤PBbÛV¦u]í‡Un=Eœlã‹·ï¿>JªE·":Ç”Ì[~ÊÚ‹Ä&ÂOš¨ÁÄ­)ƒ%&UrfIJNgq¾aCF¦p—zP‡™†vß·SC…:l#ƒ:=ɪ/¢6<ç0DU­¼F9‘Š¦îÅR3–}m¡ð6‚£y)¤8Õáà7Õ¿QúÜñeìî#$†ã\¦Æ§ò^q1®J=f3£ÕÍkÆÝ$·LùÎã{ˆ–¦Ö=Jì‹mŸ&@׆vµÑ|^m÷"Xî<ºãcèšQÕ¨ŠR„­HyrÕòá#6̪\hlæÏ„„#6Qɺ*h9·¹Œ52g(eG=¦!ƒB-½FäÈ= *\¨½[=Ù4³Ê…ܧIm¯ƒÐŠã¹Fo%ë*œ¡açgþsé7s”¾›ð¤ß>­üç:¶è$qCñntl ûÜÂŒ=³D”OåùÅ@à}Äýó;Â_+'ç» EFžÍÇD_½@Ê´Î/HÌ(¹%“üñãÖÛ~!ÞʨÁõsÉMžªG4E8ŸˆyKåÒØÚ„¾ôc6Ãä´ÜàÎû6vâv¥l½Ë#.‡g“t>";¢ïm¼Ùu¼,ÉvõutÁ=;2hä!0ßH¿(âÞ}´s^G ap%N=¬c¥çµQ»Iz]¸lð«°S·#6eŽh´³$'°´¬çíHf#6^Uî…Ѓt.‡.k„“¤ö#.п4âî6 zÛXÛPÅ¥½“\9šÛ1mðR´t­}yUQ¯}[;î¨Æûáožs„˜-÷À•<¤¦TvZ§•H¤sÄ•éïã寻Ë&?Áß™Æf}ôèÁ>WÞ³ÅøÕO‡Ùwbe'½øëåÆqžçŒtÕÑ_I&5q¶–"æ¹Öçgõj2àE°™©£•½"*[WÕn¬2¾ëAá¦ÐM*’aFkmö0*áe"ë²°I@.µq|ž%hy±gt>›ûõGÌ0ÍxQ“¨ZQ]~¹„…LfÏ9ÖÑhjÀ’®“'»YžtX?PØçÜôTðQäj?¬½Èo]YQµfÐ[DÔ³áGçtP?ÒóèþØÎeϤ;ûmð÷\ã4•§á˜‘x§5¨íÍKèÒ@¥ÛY ü– —°¡•³([¥uã`£„"ñ%K ¢%b5j!®#TRé,Ы©’ªö`A¬5w,åu1ž…¶K#6¯uÌÍ+;¼òzÜÇEºâko¡.¦ùÕÏVÍ߇Ç>ëä(úXòV÷9Cg–­Œ ôuª<²w]ÇÞ7ÆðÛþë+™Þ#6–~J¢ÖÞož8Ð#!žõþ³PJ†#%)W&8Ø9¢/ï•®Îo7v°Ðv¸- õ 6âm¾Žæ¤C+«WA’z)zÄêéVµ{„Ñuå|NÉK›¦Ò ¥tßËòܹÆ"‘½E¦/séÑWa›Æº\T:Ü©ÝÆðñ#%̹ÖovJ±$o¨e›@„¦ëtLE#.õ Há­Ð­’æxizÎ @pžßyƒŠ¦M>úgŒV0P´¡ã/ïÚWFŒê ªÆê°ÊgR0y¹ö\÷› Ü+nS×GJÊÕ–^I¸ºY©}ªëÜ轄BÎYC™;-|ŽCÄDfVšsÖ#%Û5·\a?Æ ÖÖv•s>×_Òë5Fó¨÷ypfÝuÓÊ#-/Í\¿Tz>#»¸dq ÄËÍKÎ{e¿"ϽFòæŒÁ³Áµ@œ}#6#6pÂi†1šIc¯1Ž¡òª¯ ÇÃ|èŽIm'T\&IËlgï™´µp/jº~?†5óÎvÝ ææܲÓ5‘bŒ7fÓnº™N3[al@}sÙ…_ XƒFÉÆÛ„ß'mÂ6)k4ïÞ',Ö #6Ö•KdÒUÅCÞî… £¬ô#6F6¡H‰Dp¢JÊ÷ÖÚWS€“ä²R²sýÙí~ ¥axÆ«aázß5Ä7¾m.mí*E¨$ CAlæ¦BIm*øÒ¡ò˳5®Ø45ÖJ·jºï9}æžÖÏxôHü5Z¸QŒ·W«¯ê‚ñ‘B¢(PŽ%¶ÃD7K#..mØÎLjئ+Ô,#e3m{­wlˆ4º/}úî}¼ÎYðsEÞC9H2ƒ¶±ƒtflkA²´ÕM1‹C,áî…`âl„™Ø±„ëkù´OIiN•}¥áù#6nÆ#%ààÍA^†³(ÆÀl˜!Ê.±o7Bù[8fX»HíÚ€Wzò2ÔÕså@ç¬É“¯ËjÎc¯oN=,qkóPxÙ¡ÀË·qÊX8~ =Þ¡O½íÏ’‹Ó¯tÌqÁ8=þø´¼Âžûx–’ÔE†@é#%Åmp‰•‘ÀO˜NÐ’³Ïaj¬ ôe“³ÊÈT†I*ƒxzÊÔ¢ˆŽ4äãlûGüGþÞtОq͇¯5K¯ìëâì·VžÉxdÔÊ*Wž6—XËSm³¾‘$ðH/᦯°FŽì¤øS‰Ùà‚Q²{Æh‰e!wº(¦±Ïš]ºÈ—c!‡ïƒÂëOZÏ_…ÍÓy©1L6ðéšP¾·«>ºÃezÑa¦ö_j¸ï©~Z^¢iJ­áÝtQaè[›9ò-QÍïäzí$o“‰±ýL— ÷æsaÕHR1€ÒTÕ ×¡Áâè*aæu®|b¶ž‡µïææyÌ„…Ä“{Sê-p5cÞ§wsÕ_L›ÜÂG‚›ËÖôöû©åŽ¿¦àc}±Œ —«ûû5I³©jJ#fع¾”ÎM$rÂKLîg¡sß9a--JÉ–,°ã¾›õ½`¤Ç|ír]xä+n/ÑÖÕœELm¹‡˜‰‰›Èb3ÍO]a­Ó(£ì!^\C᛽¦Õ-(r"„ÇFgRÒ¸nXم꣥ü1½„+/!“ÆšÃ6d#6P ÕdØIá‚ÇT”ÁHS{ÚÔbÿ3Ÿ1棆…N¬ù \¤ë€`- xŠf<Ž3·¡Ù#6  g î®Þ|Ûc$âSâ¹@ág"Ä ÀÝ:9Òà»Ý.mÚ†—¾|×[6âjžg5sÍ¢ðºàÙ½KÚ=WæˆÐ#%U)Aµý³MU7/”Îà³E³V¶û³õb>|ÔÔsDD°#6T2À¦y Áq¢Ð²#6èü¥ŸÒk1~6ñ,ŸÑå%Øâèûgû—K°¶ˆ"hÔi2KúŸ;e#6é f¼¬T¡ ÅX]Ó¦h”vÍÖ°NZPqîWP¦õáÐä²I¼|Æ ág¬í÷ži ã¢\ÒªÊaîa·Øé8ºibP» ”Jr¬ÑÑkLØ0óöÖë¢vÝ\ê£q!ö•ytŸØ :÷Ôܵo‚û<£gŒÏ=Éo6¼IÞbì·låHÜCZýn±ù¯Ö7Fn²“žd»Ê¿_¦Ö„VM‚ü£cîƒ:v¹+F;³Ü¬)&#.M—'ÁÂ#.›Ë‚¯£¶Œb»ÀYÊw:$ƒ†±å½À=ë Z×û°' &hhmZžñX\Ë,€ÊŠÙ9CÆçò¤!9¹­0rÊÜ =ÞµmŒ©3¾¶[…ƒ¿ è‰ZÁW©TƒŒ·ÈÞÝ+(a 19Å‚‘Ìáë<¥Ñéæ¡ÜvÅF³Ôè©xñ‚è~ÅGÁB UU(;}ný½º¯œà•Þ¹™Áµzoô]4Œ‰B:ž­Ð=.®atÏ$³ôÒeJûœä™í` r=q`ÉiC J¿ç¼ø”D¡ùâÓÁ#.BY`œ‘åfYB¢òó¿Ay ±U /v¶ /—C—3¯¿±òÔ$¬sék:!ßr=®.ê«Y8=}«œ[SdІ*„¼¡÷M¹õ(œö´¯RÔ˜xÁ5&œ¾GÔ†¢¨)´èÉÄp¼Ió{ ã™.xGtÆ¡žÿ',©iAxdÙt½×ôY»7ÓFšsÅÓÐs=o¼[DØЂ unÄ2¨æƒû‹`Ü1˜ÛNAö;ñoó$³¶‹›¸x‹<¡³EüqÊíêK‘­/–¬ÙßbÐK¬„/aÑt÷h$&c„%n×çl#«'¬s¹â™(é­T¿·iاۤªËò¡^v*ø1Ö.)òFÅ?NŠá_§X#6ãûbo1QìÐb¼DzÞÒ¸Û¾nB¬htRߌM~Þ¹Ÿ¼çhæ>(â= 6º†6Mº1@ì|]½fÏ.×ösÛž(õ::l¬züø³jîOÁk)¾pVzקk÷û±jÔ3pV×>IÎf¥$™Jý€?LV2e*¤Xpå¹³‹nžÈ(#2òY¸zk0Ö9êŸ<õ-w¨õ°u¡Íˆ¶lÂnIv(˜"`‘îTaŠÙߦ:b×däB®zí†GmÚå»#6õÈyh3å„Œ³#.¡™Œæó‡vÏ=ýB´Ùîïj¸+8;å>N¼Ù8›dÃøݺÌu]:D£~·/Ò®*©z½pIs>•Ó¾Ä¶7¢ð¾ìæ|¡Ð.ÝC×o“ü<©Oz¬Û5*ôÚÐŒ}&E§xãÑŠ»ó!½SbGeœžFI-ÉU#%¦$Ô³I Ù™lM,–01Œ*Fe`÷ S~S G>»2@×ã¾~ï3¬ ZÂË/ÒsÛ¤¸zµkÓÆ.xï|~ñÍ‘•D¤#%¼Û鮈u™¯ÍÐ*±§Z#.ßËn¾‹€P>¡…uxi¬ëÍÔ¨&„'a¼ S9—2)igkHÏíð|·¯`çÛÜ¡à‚iÖÉÛS{Æ`'Œ+æU<:êI,öæÙ7¿_ǃVñ5î‡O/Iú~!®ìàœZ§ºÜÁáÈR¸÷pùqyàì^Km›ž$?«ÿr¢­‡u“à;46CR;,VÒ¤èøu'Ž/•0Î?­í5¯{íÀ™iÎÚÞÜsü"Vîu¾ jOð3ˆýKÉOäýN“w™³ª¯ÂÛ¦/½6¨ .¡#6×X”rpÑoHì~!ÑRKz¹£%dn(è)!ëßžnÈ€r†lšÔˆ£§‹G’ÜŸ#D’ÎŽ¸N5›çþwP$È~žåtÔŸNBeåkµîM„ ‚ÏÙèn æ²1Â7_êÝóÞ¹¾?5õü;{Óº'àãÕøÏŒ¥¡{ùq(#%`@)ïõ(õ§áôáÔŠç°Ö9MvŽ#Õ(JL+G;I@À€ðèz¼xÔ¾(H)­æ„gëxTWÆ®òØ] —÷ào»ýEkù©\ë¹lIi?K¶Wò¨Ø”‹Rm“cÚ-«®¯ñþ5ù³Lˆ–ˆ…>­(2Í›ÊþbFmp–ß‹gË~:×ô@ß4>$Ë_#p¼$’ ŠÅ"‘AƒY ä&©×‡™z½:œžÛ¬-&OŸÈÌySµgÎ]–ÜžlÈþÔÃfÁõ¤™^¥«Û¾÷Ê“Ao¼?“ñxüGŠ5‘ý7B÷ØH‡Ó\™ü¯íN9†1‚¤IY‘[Gtþ#%²©‚¨qHTi*7+¡þÜõÿ—‰Ëò?¯YC‹‰xþöaÏ(¾zÿ~[Ûá_Ú Ï]>Nt©"rNK(ö·ËçzÔöKíˆd¿»æïžðù´!Ú‡Eá¹tî›V}ëªÚÃÞíèÝnCiü˜]÷ùY??ÎýŽ…ªz¯nÇN¶:*F`6$´t%5®Ææ󳃊\ª#%±|´ãÓ¹ƒþ1“ì?£¾í/ÒÊY¡°ê8KË,H|ñ“‰"~¯Ð©¡ýj!Š#.K©wk|Y ž™²äèYû=v&‚Sú7åí}f“›¥h¯P#6ªÌ·Š Ϩ:ý_Býš>¼•s<­7E‰a§VNKÎõú]›(ú¶ÅÆQØ/ð~¶w+E@âõL›0½Æ\üƒª"XÉBÌÜ!œ?_þG7‹L˜zß„çmßÂÇ>¯+e§m¿—Á÷¡Øf c(QÆŠ#6‹"šýu9¡Ñ#.P?KóO¹ êL¥09]#%n‡?Ÿøí®@¡/T¨#%ž½t xÎè†"RµœKš Tg¹‘L°ÇJæhZ‡\j ¨µ+r¼ Lt#Èæ"#%oŽŠ®¡òËÒ(~†—ª#%¾± ´é§ëãcßÁmÃfÿU#%èõ@ÝEôÿR ðºØŒÄŸxi¯Ðþ•ëôBañŠ¾`Ù8ú&ØH¨Ù6óòP¿Ÿˆ€XøcÚi®à†í´ ÇK™÷$qý4¹a‹ß-)Á>ÏN99¨“Õ‰5v8ñ:je`a"ÅeOXï2€ƒ~ƒZhCq‹ yžÏWiƺ(T¾¦Û¿ol|ïøH,ézþë–(`L$¼{ †9gÕWR|1€¿{ÕŸ¹Ýø™@Äyi<×Þ€ÿ$ï è LJòS(ò‚ýäOgÏIëŽÕ¥OSIïô–õ#Ñzüco*(B¢Êvæý?Ít,¡xë©TÏ[]3«X(~Š¤ž©R”#6¥`UMKõ·;ã6Á¢(ܣ؊y·½?=Æ Ýа섀>Š©˜ aI\öñ}V$øÁ4º­2qÇ m¿Êe#.fqpÚi”ÌkZÔ·ü(b§RfÌ%ݵEÔR1#µ¤Ûp2„‚\4SywE9gŸ+ìôŸÐmÒü!Œô¯#À耠(&ë]Ì#%¹Öië…uQºâý:vêÙ®¨ÙJË5Iší4ôýn½2‘×m’pŒ­è«¡ön³DAñ|],ʈ‰[#6Øy`ïÄ#6€ŒPIµoßÕwÊîŽ,ßlN¹¬ç·Ü"‡c;þú†Y³:=Ÿ±Z&W¨å#6‚Çf½Y¦ÈÈ`¢ÃÏÅ3×8ÈŠ7K±´-•T"EÃvÉFQ`¹Š\ÏP.Dp1C¯f¶Öoe¹_}g¶âúà«âc'‰ŸKš³’T¢©Ö¨`¢XD$¡›\æ#6P8ÌüøÀ·Ì£€¾ý—tb•ÓÎOIan0aÓÖ€LŠ bBç#.°‚ ¶ö]\ñ²òBET dØÇ(°so¾)g®Ñ à#.4FÌ·e¦`1ÜL`òyJœIÅG§³Â¥ô ï#?øYÖzKéÄ2 ÷#.ÍÔþ:·Ü7ÃßüÕaÖNQżÿi˃2}}Jo£Èú¯.þ³ÊÍýÇÐïL_fs@ˆvô#6€Ä¥Í7–;Î_{Éž‘Fy"]yXºmý~,@yÆNr+(kîØ®™ñ3zL;,Ÿ" ì¼BN3$ü÷>åq6׿yðö]|'<@¶HZ°¦ „Ýè[ï*¹süÚÍæðX¤ßï”@¤U-0žàeœ‹{¶Ú3ÀÂÓ“ƒíTÆií’7q¢‘I¼y»Î…—'íýVç?rÕëHƒŒõ!d=1#3tÿe–®ÎÝ~AN{º4N ¡úÓ‡× ‚I5Ù(åtD# øŒ uÕ™Ü`ÔQP+&Ö—á`KH³ZŒhð!É î¾ÉA ê(‘e<ýd’¼þ½eý÷ímÊ5^äÞ¢)?̸Úþñçš–6`éØÂàäâ{î£Æák¼dVÔ™2S„Ä;¬7ÊN¤@‘`wdÃ@à¢`s¤˜á59—_E·OR« _ªzŽq…›Ks^GlÞ<ЈŠ¹\¡±BÖ³žBdF&!Úë\[S®~zÞd'¼ˆ’¢$6›ÒÙ¢½ÉŸ6NX |¼¡AÀ(噘øïÃrã;XËq-î¨ùöˆÎrI{@Î{"{íLÕźÞœ“5y\ˆJ‹Eã›%9×!}ÞCøI(ès=>§X.~Xp^‰éó{ì¨k±âøa§Ë%–&â’’Ñþ„Ww,/òmì¥z¹€Nãõ‡5ÇŽ/mKŸ¦$jìá +ÓK6L²8ª~í1‚o'š\8¸`À-€ #!C<×® lˆá2ô×8ëõÍÙXÃN¾eÌü®R«•b/!ö¥E7Â5ƒˆpdp«¬BÜqÖ;»8]c5 Ù½= L=«ô7#%í¾XžïÃ%3#6‰¥,4«ã¤"»¹¼±¦ÿò€uoŠ8‘KÔ<׬(¸§E¤;UZ ÙÃoXÍ:I¬‚ßMejyyBþBœT¥îú#6=‘q¨<ô,;¢ qÌ·¡Lá-á¨rjß~Ä‚=%³Š¿uû:RcŒ’x+#.ÃVe(Jź•¨ C°×¦m"¯ƒ‘1IÃÉ2*˜Ü¼ùÎÔ‡FÆ2­…?Ù0¨k˳ߔïÚ?Éðý\ðßCc£{ ž±¥õ‚>Ô儯p/UM†óè<g;e#6,Û¡¬…(àÆz¶bâJ ü¼¢‰®:…Öò7ã œlG1ÑŸát¸ù|±<ŸXÛ'M1çIñà /T½]‘)œÏo9ìð_Urb,ˆÝOèL{Sá_mTܶ§ã³ZY:Tú9°Ïo¿¥ÁÆš‚³(u™l;g}šm@óß‘¿²YµCfMjdÕó<#.x³:O)ºm‘÷/·ú4@[Zô’; Š÷hÙ‹hhP ¯;wœìÁÒ‚Vñ¸¥_F”m¥?ºø2_P|M9Ü©|r]¼­½–ko {†îPxÝ,lû5 =¹‡™ËJÔé{CTj‚Çh÷ñ•bìãšc°«¾DƒiÊî:L™$eR‹I¦ÆÚtî×ãÄtç)†¬ëÈß™·žÜŽÑ~“tÔÆã‚Ãœç£#.p²†}wÍ)@))ë 2d¨…t‘`!. 3ØYbô(%œD®‡#%ûtdb#ŠÐ7B™Ê©—Ÿ'Ø«ÁYúcþõCµg›ï‰îé¬ÔMRaÿ2[þ4¤ ]g†bÒ•»woÕNÝ«Ï,.1D¦•XËûØö¾ÛTÓ<’€5ÿ'ƒË.¸¿¢ª×?Øä*£b¯iöÅW-«cµ@UTÙ #%AýJÌ#%î? øó>ÝÚô¯á[íê{}¾¤aªô·ï«éE „aûÄEÃû(ÈõÍüÏŽðÝøÉöý–Áä?²ÔðNšxè` ß·¥"lÆP Þ·G?`lû=Úø ®j¹Ë—\ॣ4ʤˆAàP(AÍ&…à¾Ê0Ax2E¼«¸Móˆr“¹Ù2I#6Q0’D%9èÀ÷¯0(^Cg~‚ÁÛ•RT:F¯gŽw÷Ù}}v®‰ÄT$/d*>Q¾•4C´ãÝÞ¨¦ÙˆÇVÍT«Å„Kv#.ï­ÙÊ[Tú_‘üúl6q™½„ Ì:ÑAéé-‘¾ìE.ôñ x4‚à‘†ŽÎ2²#.±ñÞ‹|Â¥ÀÿóääqÚ¡K¥Èj#Åìðý3˜© 2r·2¢ «êÈš#6Óù¬<7ÐêžY’Ö1Ö‘$“â‚Íh>GÛTÌx~2‹ããéŸÊô@‰î*%Ô39h­þZš[ÃÏù`tgø·Ø’j«Úcü© Àïð÷Ãz¾ô! °,¹f°Ç­Ù”èd"Ô@„2 v¨0é³k(!ïh[YÙR |"€h/ #.( ³(00Ýú¸ …˜Mm”°¶>˜+dʈ¦²’ÆDTKƒ¥ÊGE´@ˆÅ2†. ¨&c¯u…ù8 #a j¥6MIF›EÜ.–3+ˆ;bÁ–$K*˜Ù’”³T”HBn|4D3Š¿Á#6Ù½3¡ç$ú{•OôÙ«ÂÿHô³ €i"Q`UK‹È–…s;$>ª¾5ñÌP({èlpùÈ?)ã¨,ý¾r˜b"Zô§KA±Æ’;5WÚ˜ øO´~‹Ë~ËýOî„Nâ¡{Zc#1¼¦Ìň…P'OäŠ)Ï­·ž±ŠÎ£¼M!+½E>÷TöƒÃßô9¶s¨ÎšÞ?— ä#%“`cnh?½öÝ+ŸBGG%om_}Žþ ¤M¼Q' ÀwG«ÏwE&h¢æÝnï%óªpmœÜ"&ñõëw&©$·)¢rÛu©í³Ùí«ûÉíööñp)\uÆUüdá{‘KãqÚÛ ãE¦é]RÎ*8#.ñ6lTxÌ2Œi†˜§DéÃL©Ýåj22JË‘ïuPݹš3Tj²‡©ÿ :§Å¦%tCAç0Û³ô=f[ŽªŠ®Û/0Mk­svLoTõw e1ð C¹{…ÉR‰â_qý“Zk‹ác>Õaü¬ûìfоáÜlJéæBBé€r'·;<[ŒKå€îñÛuïºä±f’È«%3J„a1b‘{Ûì=G\‹ULj#ERX城ncsÁÜr†sVÓmš;ÃX;MÆV Š]±#.Z²·›mÔ2$ †g-$F„ÄÆñ žLŠ%ð.ª_–L©§Ç6íßQSÔxÝš#.I»!¨œM#.”F×Ϫ‡MC€êvB¶ð#%æ! qŽI*™Øt‘§m­Œå´Æ¡t:CÖ\$×@0!ª†#6%ÀB‰eV‰7vd”‚À°ò®cÀAÖ©Fvt×FýeÐm6Û¨ëô_^qöÀ©3_éävjᙎ:¤ö7T%â#.aû ŸŽÈ3ÅÀã#’Dõá,üPCª†Ä{Æ–ò½˜½«XÜ©¦_=Þq¤¡A g6ОO¢¦‰_*’P!6E†3Ë87Xd]ä#6­æmóŽ±2M#%áF³™k#U@T¢yÂý3Ø›÷o#ÖÉÐÁfÞî,Ü ›;èΗm0T&â&4÷5I$ÂpŽº~¶4Æ1ržÍ/€‡ë›#6íÙj¼wüšXëËh:nx–fø|ñLJgXC§ÒPt/yÒŸ¿áìÍørŠ#6°\ÈÆØÍ(‰< UTȵ\[#%^™H#.}qš¨ÛVFX+1á÷D¨ûºÕÓ­Bà„#..”rªü‚˜m¾È½Í—¡—½Y]ŽZ† I„¸8ÓLÓA5À×ÏN·Ó0$ÑŽ–mÅ#6æ#.€Xõæa÷îÙâ.êôå“\ºHÜŽ9T¥w_–¥v¢E”F`0HƒÊ¡E%xÜÂ+º¸öî2<õç<Œ-“#.áê}›ϤÛy£¶™ÙÜT[§Ï%)Ý7°40¶ãòâæÙO:§dXoY£t¢«º{{»õÆU;ªR %£D P–ÈÌ0ì¼Y3#%€Û*V ÃØq@iãAF®L`àîë´'©!ç#´ ÏAVì#º(®RÐBVcÙ3±EÊí’ a „›¶)ÙXª`_€žôÉ ­X¸h£Dì;£Ûe¼ô‰ŒŽ'¡Ž4QÁJ#6 Q`¹”(T"’@ çK¨ ®¬`²ÇînÆ´Ý ïZ:uY¹í©ŸÆtFýð›ìÂ-¢˜RTˆÐfµs™K>÷Bo¾Hç¼~YÅuúý­sPÓÊÑ¿±ï ˜9:ô–Y†&Û˜:ö cU:çÙ›ëBûrÎ0º>È^i…[d6p;÷Š6¡ ’O‹ðƒ#.¿c>ëU o*&L:ÜÁÀŒ–.$ó³ôLx㤴»§Õ~àÂïÉ9Àë'tldæ…!¤1#.—@Ìäu*n&H÷QT*ÖËCî.졉=9"E‹.Ôœ+u˜e×̪¤HÈA$}á{;~æJ²\¨MâÔDF`aÝGnJB†PÁŒ=­Ù#.“ݱâcL¸¡Bž"Yáî¢ýYÏÒj@=½Ï<èq¾í!É‹ùÆÞf—l¹c\ƒü1GVø¦l.o6ÈêûlinDµÄ ®ÌCÆD ¬ïÁKøµˆÃÖ)Uf[(8?ìBª± §^fÀ] tJëM/œBóC]™éƒ¯…è×»i¡^|ÇE7u[d¥g¥ÊZ;KÚ`¤ ÆóÈ3;†óæï`n… 節qi‹8šöדOB!2ÌØCP;Èä{Ž]¡GÊ‚¢¼È0†QvDÝ9¼‘¥ºËY=†s³¤íEÃBî4¶:˜vAèC2.û\•|ÓioÝv®ZFQ4ZOí²i2e67­î1kÓkð/™#.§]Ž6@‘³4xÊ3töÕÑøželG•Í†²ÍÑ’@R† ]ˆ)˜NýþüueVL5š‡Ú)·é.´É©ü sà7§@4/:UÛ‘Ë]u‹C<äR\€wÂ'UWÞ:çQ“vbª§F†H RÉS©Ð,wÀ×ß=uÃYƒV\ë2‡“Rª™MÄ£8{ôíåŽíxÍ]z¨BìV'׿_ÝSÈ2È6½–_g¸ñ¢Öåä#%˜Æð§:¬É©£_ÑÆxÖyßÔ#%ŒÒéDÙ‡¯Š~ªJ†ó$ƒ?Ù~~é†8f>†îÑ=G/‰…Þe%A7Üüq,[Y§â­¿o¹€b΢oªd¡ÝŠãà¶4€CÄ™À?Æaûý?ËÉoôÝÝã‰è”Ÿßþ$Ý6aH*2AHe,-3ôWðþ>—|ðoÃpûgŠrñßã‹jËntKç;ÓøÂß­%ÂòJŸMY¨TßzÊüúQ÷óÌp?îüy÷?=BVüsɼcýNG8(´5Y‰yPYú¾ÎÞξ½¢jö«vÚÙÜ1¸ýË}+sk…6édص2½yÛù¯$Ü¡i)_?ï_Œ3÷ÓÇíüûàüéC6ª?·LG÷³û_Àȯ«ï5‹Mu¹=!£~*+LOú¤k2¨‘bÄ2ðÏVÞ 7üDÏDa{ª';âûƒ (#jº£ª€%3t»¬i×¥¦•A‰QÇŽ®¬2ÕYhqßž´w/ù‡øƒã¦Z7¤Åö#6uÑiM«ZÎ0—XL¡ëŒ!…9¼zóü€ª ²zYÏ¿hnÎHr`§fá5©¯N$fá"ßæßV Þ±Æeî>¥?ë.3/«ð>KÔ6½ŸM(Ÿ9ž—Ož‰ ÊK#6=mcÒï¾´'ª¬€§J¦1EæwŸ³g¶ËO… õR—¿Õó °"ûå m"À„Œ@¦D¡È_ßØ_éú«ÕÈqè4é|Ÿ`òßR쎉+´j`ŠQ‰(‰âL”&‡ПK#.FM=‡3–ÿ§úñ3£I¢Sø¦Ø¥cÒš ÈȹÄþƒ~î>ÜþËq•U×-Ã^Ë­uèàH19ôêaY?¸NN·Ñ¯¨]ó#.—y·Ûßù `2É/ÈDÏà‰ê>Ÿ #6m*€ÕHç<\2ê=|.mcÅwž~÷‡w§`PòMêÆ9^Þj¼=ÐXÂŽfulDRžÀç,±þBp­ˆRH‚ú‡Ð݉™îµ˜)_Å®ðߦ.üîÏÏôúýà|Iõü¸“ò» ãšMJîë áEŸO×ñ"aÚO‰A$ÉF‚ï5ýéúxqçÐû¦„Fwd;zçСËÓ².'œgòêç©äâ|9Êlrå€ó×ê¯l¢:vGÐi2] ™³ @ñ¦ Š ®3×#M»½‹.À;Gâ¿9BG8ý¯ý\žŽý»D=®h¯^þòÖØøÉýò=k‹âáú¿ÀØñ<ÎzüãËçò%LÑQû>\ÿ3pÓ°êvÇ1gío ¡¨Ócj‹ÛÚï^ÿø½\¯:³Hr!i ~ZT×°-î(ÿL½þ›rø†'›™@Ù·Uì:k¶+cJ ©Òò]ô8<Ãr¾ɹÐ#6È„Ô˜²¤ƒìüØõ^ˆcÕgqÁ”oTÔL#6$8ˆ=Ìò<Ë1c„‹Š4+?G£âòó¿x#.âÎ\ÝZs ÜŸ™ÀàF’)¡EŽhsŽ•ƒ.²`.z´ñò„Ù0öªÞÒʹQR~m+í»0†Ç._¯ÛË—ÑåÇC«nè5 ÏutßWv#60蔪Z.0òë𷵬žËðSŠF§NOƒµN®#.ÐûEÁ¤Ÿe˜ûøÑ3¦2J¦|;ìïMmQ³ ïºvj†x¼rïJœ¹¾Ý‘~“Ѐpr)‡c§~¢;wo«j£ï‹ïÎö1žsÑõñTh#0Ò!ãóR³UW•×}Úh¥bÍ exƒËá "æ|PH[ǧ:àJžäô/°qŒDC“×I¦™u„ÃGµ_z§ó8Xzgü‰Ï—N×È:ÎÝÓ¿¿x£aF÷›Ó¤ïÅø̺€["·½ò½ejøM†§Û™AéA&¶²¶®6)BЉˆ;XG꧕('ꢵ¬IB¬×(~ a{ŸÕpß5×.êµ 55‡½.>#b·—´Þç=ÿ©]oðÃG§Tmü#%AÁP1@zsÍnál?]ÞªzxkÝ@ˆ2 eó*+hÛ:¬¿w›ìݩΆÜ~‚ TJ–^9¿ Í‘4hB&¨ï¿#.xbðPýÀ;Ô¢Ÿ^Æýú}¡‡›¥Ø€K“Ú}´!IŸ+ê@=ªçŸÏ@- êá)"„-±ñ³êa”å7&#.J+Ç¢ñå™ÏL½pæ#.uÚ…ýŸÏó,fƒò¼5à‡(ÌTMB³î9ál¡0á5ŠÕ’:¦s‡V6z=oÝür¼úÙ,åƯ÷~\Ý¿£Œm½ñW#úLv‘ÅÙÏ#.‚{£PP·6Ú).zEËÃÂ{ï»ý›Üan!Ì@ï\Nø¯*}Wÿ†±›þÉ3ÄÒS+ÏPhÅu·¯cãßm’Ù Ó‡Ú]’<ÑÒõyÅÕ'ëïztW{ÛÚ³—êøÞ`Ì«í- XLm#¸ ‡F—u¢ÓZ±ä¾µïŒÿ9S9œí¶}È8ß+äªnæÓ^ßn$ÊdE[Ó'}ìt”¯íøѵK¥Q´Ûmï·“mˆs³‡ñVhïU¹á _@6½o‡ÞíöO¢êCU˜sª†V“Ãú«:ÇJM,²tnOƒäÛ伎r'Jh±Ï“ªŒÁ¬ˆW•è*˜• IJŽTy`¸­ñ´,xÂÆPèL*3(#.ÛàsÇÍ(Ç5Ã.wà~>>j; ›A^ZÕŠÂ0MÆÇ¿š*vˆaFš¸7Ï#%÷Ðgˆ}lÌÒÌÁì-a”Ôƒz3urî#.œ‚÷?̶›#6!î8P¹òˆ-ã¡lÕ]EïÇ®ÎZØð™[¥•ðRӇºÝâ“H‘53û5qµ‘ÓÝ¥ƒ¡ƒ(¨*‚—Sv†Akë«Ü´iXE¦ë%qaÅn_–#%ÑEò¸ÙeÑ.’g}‚H#lkÓ>§.¿ÙÔ¯-º(ž2}T|pðÔ=ˆæ ÊÓm.C:)]úÝ«ËÛyï§ÌåÝÖÇð …0«¥7§aÝçYјóÉî® úÁž™ÛEg'>±Ež®LNïˆzûë1Åè§âßÒ(íÓ\x¬ëµÎ©ê wƒõÆiYئóãÊe0wóÔ‡%íîæ˜~çÚã¯+}ß  Ùî"•6ÃõµÁU =c¥Ú8j~>Ï?sÓ×Òs…Å"Cqv…?·å N=3 ÏDü™ƒÆs\ùÿ‚¤­õ¤=§¤y-&*ŽJý†öãÃ[ÔÛw ™bÄØñéûDfNÖHZZÛóJQù«¿¯bÑÔ|¥¨Áv¼êšŠ±¤z(ó±V‹ÖÁtAµêq¶#.èÄ‘ø6ÔÔrÑþú#¸\ØÇÖgÞü},#6ÛNjBÅp®~ÇBYÅ7ŸàÅË;æ­ßO¶ï‡Ãß«…Ä* Â=µ³\F’˜v©ểÁRÚMܯ©”øeàE\G)×ÈLÅ­<ýŸ™];8iÉú‘Æ££í –]Ä ËĺÏYŽ\6Çg#%U¤{’Ø[†»¦.Iœ<:Øg‹#6¨Q.AQÁƒ´7漯#üá#.¬h;û!ƒ]žX–0ÇÏçò¸m‡gÝš1Ž9ÍÿžèmúH¾_H‡–GYÓ¼Ï?N××wíQ:)þ$ø/KyÎi6¡+žvŽJŠ¢ÕE‰B¹@¸ÊƉðˆP¢úz…¢,Š¡–ªÙm–¿¢„ÛiKˆ»eïAxý1_®ùS4`Š÷³…¿wÙ“»N¶{PÔôÖ÷ÅTXPD]Î*çDïCEžüYc¤ô¤ãð^FO¸Žëz]ÕÏéæ’cpÈÚUÊUÐ@œ,#%ŒÂpHmUWùa±ƒµ®*|ÛH¦Îˆ}Úu÷'Ø2›Ô¤æŸŒ¼…ìGC9BSu&3æÖ5ñh÷=3m"±|Ø\!€XPŠ‘.{ØyÝH¸›¹[¹BJ+ÅGPÍS#.O2,,<Ó¿f;r‘÷ú½M`ª)…®¢Ñ@9b\m@ü @@]¶ÐئD #_K®cR(ä?µ‰#QQÄpFñ#%¨ªêªÄÄ:UÙ#%œ¨"ñÓmÝ„²#.ž·4맯É(¾Î^¬(üEJBë…‹2 3º ¬W¾\îp®4«ÎJê#.¬ËqÂ&zÐB/ò‰!<Ë9#.ølc´“Àw£ôMzME‚×®#.CÁEEÁEà#%‚qÈ|ñ$T½‘Š"~ßÀ$ééí#.YqrA@f#%ûW°@Cë:ÑЊi&s7Ïôì¾&BOCüf+uÙòj” Ù$ßœº×Ïíz³¾EêOæÚ$>ùhÕn¡á™t÷HŒ†ú§¸!#*1"Ú.Nç¸Û;]\xVÙöùú¤šd^ ƒwÏ|gO6ÃϺí;ŒJæ0&é5Ó#%}¡8Ur/$€ß…3‘ì„>Ü­x¿,CŠq¨;™†•@v/#%å@]¹C9P¤grÏþ¸(9Á Èv kš$§9T¬Æ4˜h ÷~ÿm*ñ8꘻ˆÈ` #%X} ¹lJ‚‡^¾ü. #.JCVgˆ‚5t^‚ˆ7!߆÷ eøÆe#%~zT)AY`ʼNµÂù íUö)>Sæ׋rYXP\¨¢!Å&‚NŽ0#6±ƒzY*¥MtÛ ìt‰šÊl,tgÎçg2ˆj—bOåN@–Âq7´ñ&¿FŠ)¶¦=((œ{;›‚P'+ª×Ãw”V_ðÀëá?tf“¸Ÿ@¢ÛnóX.Ž3Q%x]]Ïv[ÒÉk¥סTÔ4¢¦ª%…e^ROkl(FX8g&øw†å!£?géâÊ#.#íYÍïj‡~†âi›e•Ä×u'³Ý˜e;g•ÂTüLìq1Ý ¯#¨(òáá#ŒÉ,p†“çt‡Aè•5+ÙldèwäÕÒ{øÞv‡åÆ;Úõm”P•'@î}ˆço=pÊ2H#6O G™ê_™0P&Ú‰J#%íËTO¦\ýæÀ¢j›hDp¿É“ꡧКy©9Sr³xêÚ-ÇhvÔdŠ#.Y|ÓãÃPmSÀˆ_¶V?L_"'(PvÖR«6ã$¾Z'Žxõ×=÷#.A='áTP‘)þ%¦}ýjW¿Íþ\èô´Ò¨õÑ3Ê¡â̸|ÅZ~c¡ÞFÊ0‡V‡(·ÙÛiúÿ+Þíôüt|~!s#.Ë@Å¥ÑZÃñxä·˜aƒ……%»©±ªþ½GŠK1à*ÒpÁþ'Â=6ŸqK½•¶±/öþ ®x ©®óÒ½±dRl/U¬ôdÂAÆr³#6+óÁ…G‹Ì&IŸòê“nçôBs\g"ìé _žKâéœ?ŠŸ§èMað­{4•„ÃCɸü¤ý³þ~öÜ…ÚázNö}Ëê˜9„)˜Jë³ÒïIÆ€f¸<Êw²Á»¤‹Æ=,µ¶&M•!.üpVí±ðNtÞe°Ø²”Ó¦p„1•ИàƒøôžzrżùX—wÇ+8So£°y1Ï,ð#.›0#йò½ÇÈB9:ƒ-{~Ã1[rµã[öÁå/{Ã"“ V«Ñ*&dÛëqì¶Y-Ï.õâÒÝpœO5Æw‹;-¹’¸ò ¦JÅff Ç»¼Á¤à°Õç–H‰|WÉ¡œ!I¥Æý1eEÖ¿Ö9†AŸtP_ªÈåÐêk‹WHV#6%±¥ì嬭1^ˆ´#0Ó)åªùº°E­óg*ímŲÜë èûßÁV–Bo^Eæñ4ûy­Ö°‡. éÄFŸ±¾z4÷ö`€¡(Ù§¢œW'¨f鶹Jb•‚®òÑ;¥:ZÑ;n‘»Íçe¤°,5÷¿_„¡==:©8¼á*è›çñŽ–_ozâ|qä“5v]QsÚö.2ß#6ïÓœ‡Ó~ýá*ÜEÛ‘"cƒ¬|T=ù<³#€‚ˆ#6àœÆ`—Ñ-¶™ŠP¦#.…ÀLï6– ÏÜѺ Gà¨ëÔTt6k®^m¾×¡Îu¾íˆr%ÄD>Ú‡òQŠMŸã~pÝŒ, ¬&»œ_Ag¨šŸ²„Naæ{¼'##6ØÊ°àY•€È‡#søýø²\¿ú-´Ø~mÞÂɱ*ƒ6i¨I@­¡¯PUG¶/G$YYzÑÎR0úgÏüŸ—î–å¯Cæ“ô~6·ÌS™PÔŸ^ÎÓ¤é#.Ózý¯kHmiÛm.•3Ìx‡K¦ÜÈÿ~®%Ä"Þ+G;L¡ïncï–53áõ>¬pxq¸dê}ƒŽ †¬=ÓÓ·Uý öA¶Ÿ—vr„v¤’9’“4‹>ü‘L¸½p¯´°©gL{Ùþµt6É{<]^ÒÞœ‚™Ó X ÈÁ\€‚ ¸­ALäo¢—Ïóü¢’Ôð8ºÜP6;Ak…Ù#.†›njú«xõm©ÁäXµEÕ-— ">/Ñ£§5ô¦`åä[R÷6qì./Ó#%®Prö9¤¡ÏTXŒù8H^ôѬPòÖ~•Zª¨‚S~§!¡™<פýUîO'›Uú¤–0°*û¡Â!5Éåúõ…`ØY—³¿ÂÁà$µD£#%¡<矘 A8¤y¦ç½â±F*$‚P’IåeÉ#%úZ;dž>žý{/ó n\ö»A8*Ž#vw3…*ü5`,rØ5¦#./¾ºËÜŽ 4W‘i•Z¢‰œG˜é­Ÿ!uá&(ÒÇ_q”Då®gˆ·3$g²a:¬ï,ÕMˆ{ÂkÌû!†ÚR [€#.Mßâ–i a½6`3­š"»—½§ïØÈNÐ+Ùbv™‡§ˆêëdë—ŠZO9ª$-]»°Û–ü"üfÕÃõ¸p‚ELÂçìîiUHšE¹é±e.™ÂC¼â‡gA¬6y¢gÃë]±éwÁ÷U îåã½}¿)¯#.A²ÌëðÀ`lAºÁ×dí9Èãjá*Ù݆ 渻²§°ñ,‘ƒ«hï Ü£dwÌ.°‚»d€åšy „r ‹%(sãeäFzeÚ­Xí¼#.Kó¿i†CÜÚ'~Z6´–# ±sY‘”JÉaL”Jƒ ˜¦#%39F¸¨™Q" ^Då6{PSS3yÝL†Ý'n˜'´sûõ*ãšz‚¶ƒ«cT¸ˆ#. 2!r(PhPÚë37nPᙌF;E6‹ƒ#%ò-®}“˜]…âRkß ×ø°Œ‘ç>Ðt©Ž[â¾Ú²Ù¯kYëõÉ×,oÅѲZf°Øâ'̆ü¼üFæ"_ê•ßv8í<[8›¢XæË«É;ýˆÚru06fåÚ¹$£”ìH½_¿ÅÌÖ_ÈB'ÑsÁ¾Wì$Š“³m#6E]}Ñ#.~j4aÙ£ Mfù‡ ‘À\ö=‚°¶²„„ÔJqå΂{ŠôÅO ª÷Üþ§Òj›AéTPº¦Êƒæ}Ëã1¨ò%¦ÿ£Ì÷"‡ÛÍ¢1#6HsMžÇ¡±Q¯5óßâ¬Ì½9ÆÂ>uRÂ#}ì3va¤gìvŽ‘m¹€ZUÀ#ª³qÆîëƒVØX®H2 ÚÏßÙ#.ÁÖ›@¨$7›°­íc<ƒŠ!"†·ô2¯È.îöö !Ò‡5‰ÐÀ„¡LŒ÷³á±Ú¶æ…™Ÿ`ÆVØäºÑb#6#6õϧë(¢Ý‹a'9ú#6«`Ž‰„4Z†¢ >P4i á~q\KAÔ!nAÌ‘)™ÁÑYÅɼLèÈÉ6Þ¼44mŠ§3r !±é郓Z-*5Þ/!*kâÔ €VäD­—K¸ù°;"Ön[z€2bŒˆèé}ˆÚÖ½ÖJ"ÃX¢žÌvh{X£è¹Øf¬b¡Z–ëó‰Šè¾´ò+AŽ­u~üâOÚ°Éqm©Þ„:¤Œ·C®aïÄ,«&q\È™A̶¿n<l4(ÉÙÛÄW†ŸΔ"oí?wŠ©zg\.Äf¾]%k€Ù’¢t<æÐ#.c–Êá tgß›r#%s-¤  ÷çmhÅ»]§ˆN4(ãZs´cÎ.ßx*sŸgi5‘ÃÌJI@íod/(&_ÊX·éåøC¥¿ZO¹V?0Ìd<—‰Ö‘¼ÌĉË0æ–•;bù¶ëðzàUö‡Kd3‹³ Ê— áh@Ù€Qm´c`‰ñíYÀíÌ ÀNò‰1ª8Ø”´œ+n5µ#˜ðF¼]²"†RO]WQ5#.ê/Ùªß~”aêÔàí#%鉣µ âÓ˜ê(-ˆ”+ƒGcÒÐÝ`|^D]ÿ¤¿³ÄœÁ#6El\q´`!z I¡¼<)MG~©oÖxEß¿øÍF'­Qn#%xTL9ó¸- 4‚€ÜÜÜÝOÂxp8Yx¶@Ø‘o\D÷Níuœ§WL7COÀ»îZ¨#6iY|ŸÊäVú—AÓ]&[óêæ¥À_5·i>sE/#6¸¹€%5ÿ/ÃN¿ÃÝìï(öþlâò9Ðs7Îåú§óˆh£ógTH‚€ŸðYg}ç_Aò0¢VÅSNÄ‚HQ–'Äá×õÀ£U GJ­ÙB3qØ÷dZšÞ gÅÒЇq÷q¥¢×‹_aÜ8#%Iü~JÚž79ÀëÒ6ò`á|û6¯/ YÚr´hÄú §]Ù3óþKÕ⻳«—Ä|3ü|cÈužyb3f‡ïíÃø‡Ý Cx-®–X3ÐPX‰ú†t?Qà œˆL#6Ô28~±s;{þ|%UVvþ,¿Æp‚gºÿ…ÀY²Tì*”Br)SŽ0e–Çûï¯Éþp>VÇù¸îü¡ü_ášbÖ?©BÈrøð½C9%_ý¹$TÅIÿUP©þ·÷êYE»üZÕôAêa#°^ˆØ”Xá©8Š1#%hÿ]¡ 0;5 gûYý¼³Ö÷vØà|ávçv…†ßë›ûîšÖáþйގc€Ë«±_wNóx©©A3CaÚ— ï:Æ]Û¸…xn4©‰ã×Ìê{3 ®íH¸éÍßYTBºâüT£Ca²lÀ–ºª<ƒý¼ƒ;ª§`xµÍG°{‘Ú€ÀÞõ{ƒ¯œaô{ý.Aô¯³í4A#.PÈû=¨íŠÚ+þ˜ªYÄ; ]ÃäNÁ5%–‘Ñ…î\þK¿ÞÍ5”9€Í=¶Ïâ}™ F²†¡®B Ötüû™§ }ËÔ:Ð$A7ýß¾ºÏîû]MéÎÉ㈠D|_÷*ØUÙý./Žœó,Õ!nÿP=`dÄ_¼çœâÜ&\’B7dªõ{ ²Aåý—ˆŽ qÈP#%)X†u„¬¯# #\>Ïæþ¯G¿å+÷[q7¡ˆç˜b<œ*„™Ïw÷ý=OŸâG­ÔûôŸH|ï=áãøN®A ÊL’ª´RÅßzáóHò?yˆCÔ”“àVøþí¼…ò>!”0нÈ^‡ûÆÁ„.4ñ6×å#.ý?ipvóÙ7ìj¢Ñ X…˜%.S–7pÂM”ÞbÀò6£ƒ4¡ÖyÂCaΚ#.Ì·¨¬Qv ´†&ËPÿ—<#6ÃvT‡«±}ž‚ ûXðÒ¥W–‡Ò`_Ýä }ÝâÄì9Åwœû[wmZ?¼“C`ðã tÌ{àsõ›Û?OqÂöžVÆȨ7RÁ°Æ.¸È’(H0µ˜p½#%o{‹‚íx-)F,=žÂÙ²"œÃÌ„ä—°íÀÚæ9Níw.i…c’vL0ìòÆ‚Ð*ÚÃz}pAZ€sŸmy^®šROÅö…îNÿïòðY GÔT%X›|ËBáá5¦ý4 ¨TÎ(ÔXÐ# ýeµeþô=]Hê#%ºwZÁÀH“_ž6£áúl¯ïwç£èÃ0%ï»=¡iìÁ'åƒÇ`w‚Ž%#{†ì;r6,#.øÖ,ć¤zdx`¿‡ý9p©CYÐÒTe*ÞiD¢-&¶Ö H<>Rg#65Y$îŸ?.ÔäxRR°Áîú=T²U}ø@ú1ME~ kmmÙG“åô¨óƒ&FØèÃefæj²’~G³M¬2ëôê‚YAÁwYÃâÖ÷ ™#%y M©o®#̉ôlBÉÕ@"Ð$eæ ˆÄ|³5:IF~Œ—¸"Ì-¨É>¤÷x›¸ºŽ"#.?â#6ª[pÆñ”·æ4ï* *˜D¨ uåsØmos¬!ÖÃfM€ð*fÀo5йdãÆ¿­ç=1…”V·ñÚÀÓömçÊkû8…6ú„l£\ðgŒbÝ’K!UU;¤’I#6ðïlJüý¸f¶­˜Çí86#îu︔öoz©žàÖó×„É „à<è:YhÜðyfÊ–çñΙSlK6ÉÆd–.Õåè‡SøÌöü½Aô–~Ã!#6ü§ù‘|N3ôÿ›»òï;§ÔO‘Úy K~ô¡…×Ä°´—SêœúfÄ=ºÔ#.óévdÖõò?IÆÉõáUê6ü‰“ƒôû”[~@ðˆ@X#6‚Ä`ÈÃ/õ{ü>Ÿ¨ #6èQÚ@Äöl„²Φ§\Ã)%±·P7À`«³¹ð×…÷C.ŽÐup È`gü­ŠûV}¹Î•|¥F1°bcC„2æ²Ëœæ‡0ž}"£‡A°o‚#. '#%ØÐhü÷‚ìÚ¹&F÷7yGÃÌ2M†Š:Œ„ÖúD(3ü_‹ý}Hlû·§qƒE#.2+Ï­M¦äûøæƒÖ039!×ÚFå—9-Eö V#6„ ‡`d’€êxïk #%ÔOÁ-=fŒŠq/¾Êƒõ¥*`k|X}yÅ^Eí“!l<—FDYºÓA ±¨TD â)#–¢š3S :€™™š‘i°q`wr$îï+à™±›">,Œòq$D©L#6„3ÎÏõk’NðÍÔk‡Ä^!rÈÌC¹éi Ñ93C<µ™½Ø2.¦„#.Y$ˆà ¸ûŸÙÓñŸoXÿËw^º#%r€ÿ™úõˆUv­Aýù+ŽRWáóÆVoë¸q®ž½v¤ÞŒ”™zíÛ$cÁú»e’XjÿÇý1ž-.õ„XÊf‰]dmffžµ¨Tä!Ô }™§§Å´5N*näl³+”¤CEš‘×’I$™ª5ŠLTË­MIikm§™«š²Öjãzef׌º†:õ„ '«^kA«ÐÖ·¢šféu†G¼ÇV:ŒÒÄeA)2¬gøY(Î:ü¾Ù#6ŒX#6ª4YH¹„ŸŽ²¨é™ô0 ˜A‘P~_bÑjTmå»2sxqnaÑX„î;ÚŸ%³ïöÞÙýµ£ƒ˜t€Gí^^ÈžÂÆÛýÁ éŒó˼ÉI~}~ÝÕ¼QRü¾ÔúÑ÷}‚q§‡#%è!À´>Ò^„¶Cwl9¨; Œ„‚6ð›IÝ·;¶¯¬ó·Þd]¶d>a؈ZjH M)ßQl‰ÐªïVY¬$ˆ €r¶PRm82d?ðÛc;ŽÆxézZªÎÀ«àU¶#AIE5º&W¾f^%àù§Sš«-5RkÓ„¾]ZÍÌ¿ŸÂ19l=1IAJ~ËöêuEð4+Õ.^‡¿%6‰è ßرfÆó£æŽg §-Ô¦ÝɽŠI"H±’~Å÷WN3v¥7(Š)sp‚ƒ*ˆKûû;®Î϶þÒÀû“´ÛïŸ3Ž£ßødc_dDôvö´€’»~¢µQ‹ý![~Æ1m—ؾñ!túíÈÿ©©¿)èlHÅ3ê+ì:ŸöK<¾¢ªQRR”Š"›äÙL„Ù°LÔËsMw¶`¡º îÍieBñ@0bRòK:R¢d|~“n|šâšWnƒGô „ݽ}‘8_¨à<'¯aòV¼Qîó5¯·o\W‹÷Û^0'h7 2u%‘¸Fmîò f±0/ÍÊÀ·ió¸ò@£P.£ùbúÈ+‹?NÎTáõPäDs#%>!ø½Þ@Y68þçxÉ\ż.Ü?€ú-¸QÙþ*°™D­jIôßç½a-êzÄRÏ¢ˆ*%ö›Q<ìr0}y,ýÂz ú>Ç[„žäv€ãòƒ`õ#.€²Â½ú&Ì2(Abã:’6ƒ¿ô9œv¾ðû`ç¾É±9ßÙú_¨ì>†Ê§8»ÀþÉù€ö»6x'ã7ˆu'€{Å;H©A5twµñíPI”É(Ö?xyX"DNþ}+»ÅÞy‡sF±èæÆÀY—€3m;0#6ŒJŸÊÌ#%âaAŒö÷D<…‚É„Y(‡Ìò ¯À.pW÷Îapõ÷lòÕs½8¾?~†ç3 PGÌpC© :¨3yC³ŠÐÕ?P«¯™»/id+ä?ÇGÞÙúÉõ­õɬ÷V7LUQX•®4=áù2»Ý–£¯ë‚ø|áçð*ú­Ä ‚êkCÔ¦j˜„‡£’I'±â©æ>·Ò »ø5UŠÈA°4d€>Ÿ/ЯãH¤ŸWb)ÙZ]CÝZ{Ž_\£ßö¨0G±Lùru‹pÖÖÆZžÿG}6\ÒšT…Éá žåõú÷£°20®UöÊ’°8MAÕñ#.7û;³ ƒ¬{Š¯Ïàtc$Ÿ:F†Þ,!î:€ìÎ:`âÁbq e¨s꾸äædQÒPÁ“NêƒËJCì2U‘ ÕZˆ*>RQÀÑИ†©üèeLæHãc;väáÁbNˆTm÷T†Í&†t”K£Pññø©†tóUŒ‚Hª%HYÇW¯>nÛC-Žmu‹r6ÑêE±½„¹Þô+šn}|=i³Ÿ'2)˜E^úÏSÐ2üY"æC}Àí•iòJ;)œ.Ù¹ž½ð˜ h_Ÿ™é籄¾üåw¼!,Œ#6|õ»ùN}Cƒà=åË)BB¡háô"þã3ì• kEµ,ã‚e”'?`vðßù\à£öíç¶>ã‰(}M|)kì`éþ¹­áaª]Ë•àa½E½h#ãòF%LæV #%ÚI0%‰¾ Z\Baнìh%R­À2` øÐlHvE6Œ˜‚(¤\D½€d󈸂HÅH"8‰ERG5Ö ™½Áù²AC€ DÖ55-~£¿Àú}ý#.>(#.ØÈðòÅÓ<³1™Z*¦°°'Qb¨r#%*ãIé}¨kOH~)Û´ÑLAG§QbY()9gb4 ÁˆGô~×ôs­¢×3Ü“×fH„z3J³íü`‘œV߶PÁý+_>q°Ù#64X”Ì¢3|»Í¯’r«Ò¸n‘[]0ÙP˜‚²ÙmÝyæ]­<(©h–‘ïô›“Wóúý?f’þÐ3MãÊ ³ìóžAì};`%õñºéîf ú‰#%–½'¼ŠYÍõù½HÃ[±#hqŽÃkóÔ6CôƒH&·j ˜ªY1#€(#.D†B2`ëJhL€é·E(ˆÒŽ*XZÌO/'œ ;+Ó³xBJ<ò9œ/;3§¨^-ûi^Cµ#6@Õ£wëÜŸ¢}”RN5 7ö†n9ÐõD#%ØpHo(ë u}›J6öÄ+pòi:ºØç¡<½s¶Üíö[c˜Û’.Ó à49°¶¨ <ïªÊ<Ïgã³ÙÛƒ; Âä=Åa¨]lùŒ‰úÇ#.ÒÒá)Š#6(£ß½d©ý`~¯YíˆIæIRJìóî9\§ÃÞúîŸ8ÿ‰#6Ù6zC¬÷|ý“>4Ò~Á1ØŠŸÂ¡ð&Il™LatɆ¼,#ZÅò4|˜kf_Ñ‚½š ´¸¹K†\ UÔ0½—¼$…´UO°ßÈùq¢úHhG®Ž¬’:Š#žY9!|úÿróŒ=HÍŠ@p2¡ «B#؉ë·×îüèt*KHÍÁÙ·Z<ƒ°ïC$"4˜ëêëç–?}z¢3ŒÔŸx'îM'oÝé#%ø÷ÿ´‹;)âB0®ƒôo%dLƒ›,6f(·—Öߤ¯J”¼u.î¯[ž½¾zDZN°ëÀàô·•NV’2KÀ.*Ð~› àGX5ºž!¶Å/K›¬Û…Ø©Ó€yâzK¨Š*üÌ`…–êAn߉lä¦ï/g«”*|[•B‰³‰¿âUBP„ Ÿ£âÍù·4„¸Å„á8'Pf,ÍŠ¥d‹Ä1éÿk‰üš;Ô¾Ö#Õ„žQÒRƒQŠñ{ùmzIIJ…0êĉ´Ã–Å…ãd…å1 *ç0%v_η?nTÖtÎ#lš1绸UgP=`Š‡*•IùI²8¢º'ʨ´§F¥‰ëPØ A¶_NáAJŽ`µ}ÿ¨|ýÅÓÚ/O€>9X<ü|z`î7Éíö¤Š»ÍýVèŸt¹ úd¨HÁ^mQÔЯ€ŒÒkK™ÖH¾‚ƒºëÓ.pâìDéGb\3>:ZA*à¡=^Wû< eÀ|ä 9 âp]û-³•¦hêØyƒš¡¥ÌŠšÁÐðN£{q¤bB:8jð´AK F#6#}븟O`y½JÝü‰Ñ <÷ à]ÈÈJ¬Êª%¤[9‡_Ôöì;#.HÂ.Ò‚PŽó÷áùOžÜ¶ÕÜ’“ÌúˆQœóμ8*eåàx _Xú(ÉA=ÐIÓ퇌É\½èÖÈ,Råí àý<ž?ÔÕ =>Âcp`¾Æø™ÏðAv}Ï°¦òO"¾€<ªŠƒR†{Ë€¦8r?ŠOësðo¶S·à~4Îj·¹£0gþðˆ¢¢™+dã(€Z‹@·˜A}î­lí…rÔåŸØޟ̤]×Ý®¥éÎ#%5I#%M$—ee5hPmØ؇5o¢àLÝpxûÂoJ#.0I Ò,6©‚BÈXõZªPýÑ÷w˜*÷o6`>Ϲ#.¨,~謙ðˆ!"Æ "?»  Þ`]Q{“jòNo.ä˾‡0,bd% ¯pA°kó:Î.îz³h*;¾ŸÏ»kõê'©uÑÔ9V/N|Ž¢½%œbªdÏ¡‘?*=…ym+Pw!Ýd#.Œ[*›p… ½ÈÁa°ln7â^€öÂ9„íLÀйp´4#6ú}>¿|{Vuï-¯MŠ«¼ô©)mï¥Ývó·n°­EÿQõ½Ä3t6ËnáññõÙºÈÀ®Þn]¯C9Q›pë’]q¾#.ãvË´[ÒQ¦ßô‡ßõ‡…ÌšD÷Fˆ§œ-hja°»^¹B†‡VͶl؈Å#%PX°V0PPÓ®¹ø:ä nî¡zgžxDeñŠÝÚb‡Ÿ³ÇÐ>ˆyÊék¦ô>z{h}Ás1óAˆdÑä–H>Ôéf X}„Ô¾îÍžÌ#¼ð8&`ÛwÐ6pŸÑF¾ý…BBM¬#6I#6çá~­Èëž H7V%íü/Äÿxên=@çE¶¡ï‚=jÛQQEV$[jUUD:ü‹•z⤊^*eV“Ø”!ªú¿¨Ì&&r¶l|ô—‡D\Üç´X†€Öi¡š?«Xiê%x¯<íæ ®ézîÒfSo—[Ö¨ ¬’ s4üåú¿ä'÷åcyÜÕÕáP”Ðv‚SÓú0Ñ"#ò ÈðÍ‘~éº{ç´×Dª_*9äÕ¸S^t œ§(MÉg#ärö=“§ßÆò}²„)NVú¿A>?Òe ³èÎýPã/#.Yl{d+×V=µpø£µ0têÔ¹2ý0‘‡â{Qnw™vï÷ê8KÎÛ¨àzÊk0Ó2¡#%óØéüú»#.qÉTÕK£ë‡±+WU‚шù÷ÜxÉ°ý *(D¾Ý!Q4ãH“À¢¤çæT,P@X$àY´5eHr€ëþ;lýÐèllWTKw{ºZÄš¬û?‘ü£øN=‰ªg±‹\ļ3à1ê¢Il“¸ù݃ã'0´`Œ°+Ãm÷@#.ÉY†Çî½Éc÷µóy§#êú’éàãœ/ê#%B§ôëé._0þjà%Æ/ò9Q»ür#6Wúÿ=…rý™¥ˆ“âÀ¡(‰#6`1—M3-“ÊS¼ómÛÛËÄï)s ª[!÷Œ™D–TL­¡Y¬ß¨è™Žhq9"ºT"Õ#6+èAá©…¤©˜¥q„¬©æŸøÚŸàúY¡š…ûfgñ ²¤(kf:ñ£ðåØŒÅCù¬”#. çXÑa¤Å¨klmYçqÎ3Ö~73™®Ô.¦Æ%½Q²’: v-°—r· ê0#6ÄlÖ¯H`³}gÏ¡‘t¼¨Lýïä|~Gôÿ‡ìÛnîv<ÁÌ!ìÊù #.‹ÓÕwÊŸ†,ý†Ã°õ*ŒUŠ0BA_Üá÷KÒ¡‰(æI:§*•‚þM?µ™Í®ßÅÁ5›ä=½ÖN}¼NÍ\ë׳ž&‡í?z Ð¤´Y-…„¤*¨õÃ~‘#%·žöµ¦ÚSŸõ’ Qk„#%Z…z³#%åÝÈW;ÀÏ„§m`ŽðŒÝ%#%&„âUêï1ó~{Žýq×ÙúùT{,eÃMÙ"bª!œÖŸÍÌ"qùz„Nº|úw¿1ˆÔe”É»D@’ å€Ày#6#°2;×₾÷%þ÷2zTXAÄ#%2€8Æð*5@åï'»ˆn„Êl„’V#6~Ž\bHQ^ÿ½èž¿,[>G;H=iêPÈJÞ§b¨$ ¦ð¯ñ”LÒú˜.½ÕÎ`ð4ƒÑm°É(4^?b——S*èdðpéÿ7f§Mó ÜÖñ?A‰£7DË$Ë—tÆûëÌ›dÞ>o#%dˆ„*6<¾Þ<Î= Í¸_èyËa°aú ðLfë9›ßm‚ÚíŸãÆxjt3û±]]î~N.5¿U4†K.w¤Í…ÒG…QëæìøŠæ°ÞŠi}‚kCeúÉî.§ZÆ8=6t™¸Yr#6„%Ý7"—sPDÖL1ܱ þ’‡^'y·=Ÿë;â*Slb¬lˆ{¼*þR{ „\2ˆî@¯çk·¨˜ªØPîᬅâðDçG½#6@<0GzÂò£|~Hø¤þ‡zN† ˜ØûcGÿÍý]ŽbïÓcy×÷Ò…Ø!éÅ!ù‰Æ?ƒí·oÙÜÙ?ÉåTQŽÜ)ÞQñ6ÓÒáÞú_7Ûƒàò‹à#.èðüª½ÚŠpÉê7?v¿~óAÞJî„îç'bœ—û,íÜz@®‘”^í@q(M¶9T*²õ†Ã.Évm‡¶Âºˆ9ψY t Æ"ñÌ&÷Ä;:„×ì<݇Lò0âÃñ{ü×R¬þ/$œúý3Ò#6?¿>þ_Óu,š6æšsl»sÄl˩Ň0â•Õ躨ƒsŸæG#ä.ñuÁgg¹mPÿk¼§l$XóüE‘æv˜Q ?™â[òÏÞßÆIGG”HNåwÒSƒîý çâ-‚¹³\Áx„µ”9ù¯ˆs£†{©¤`öù¤J÷ªÕ:^¶‰B4žœË?ÕzfêÞÿ•§„¥¢®¿)#.!£“†a’€û1¬KÚëõÌó€ê†2_‘ã[¬{™lAnµLL#6#.µ› qÍ¡S'[o”½ÂÓGf¬(`ƒ{JÂñw–óç¦$ÛÇRuœŽ:g<®ÏðÛ] 3êød¼çŒCpêÖ“4¦8óe2övÏw]Lâ0W½k³8h[¡åÁ,¶ †”{ö}/l\_G–H½£¤á¦#6ù^'…òlŸ­æ¢å®#6—Ê Ù.rƒ‚w ë0Þáü~-¼ï>]¸ã›ÉÀswsÜ&…ÑÜÝÛe‰ìü§]È]2ý3„Ë4Ù—–£UtÏ[žmjpªž¤9-ÐÁ@AbŒ#6™£AkãÕÓlÔ•ùúøoTqŽ˜4°—gÒ3,ΘwÉ1~¯&#Ùî+ïUÜ¿îÌ×}.µŒŠðƳӦ³K7wMïTD_UŒÒr{RniÐU!Üñȸ>mòi?]“Ðúsyü®ç:áéõ#6Œõ›3Pÿ[~´ì—ù¯§¹OšÏ.pìà?h‹^UÚfÞ|ð‰ 7䆨 DN&¥6iQ-9z-¶bêwþ{£K–Ý4d@òuL:Ø€ÝrŽËç}ÖÓ¶æ8\à4›Ýœ&dOË‹x”tð£ÕŠ1ÕoêïSßþþt¾þßã}¿FZ÷|iwïòÃ\EÂ^ÃÑq¼.Îúy­µŒß³Ì#F×›šcró°Ê 1J?„yŸU`< zŒôê­ 9Ÿ=(ÇV#%Û»#%øÓY]¦˜ÆÉNIör+Í0‰Õ‡”#%)aN^/X#÷$ 2ÂOaA~eœoa#%†aÓÈÅNÍ¿GõŽ‡ðãηÁ8•†ÝóÎ$÷ÍKs{üœtJä^ôeìQú¤ê(LÌ#.!Ž~ž=.gm “iijÞ]¨¦b¸MÐ6Eî@ýŒ´‡Þv`­w‡aY<<ëà›;% ‚Ó3!.áé»IÕ35Ç3å·®N†úÇÓ (¯§ëƒù6‰c9vòD[µ4;ȘQT 4¢Æ’R.²aV&¤BœÓÕ¯Nh¬Fz *åQH¼Õj´$fU"Â67U’fRàH¢Í«‡N¶s8„ˆ¬ Fe…qWžäz’§d¾5àÖ…!;xÀÞ>ï†ç†eÕeB-!Øœïm§0M.Î"Éô¤à7ñ¡NõbÈ>}¾X3ýä…:²íäÖNÅÍ÷ü7º[Sò„aéߦ#HáòÇéwo¦¢Ì³ÙÛ´!€;Z-"¡ø‰è’zbS Á#6ª…°ÐÕ’–²A±¨ÛAp¥i²e¢TA Ð@h=BµËŒº¿ f?´5û†»›q&­}Ûrd^Wð?üßk{K5™ Ú,_Öï{¬/+Yüt1Q!%¥*‰d`ü¿­ÚŸ@R¾Ä9AžäF"ÕÝ·fÛžPàw†£|}¯ôh„ {·g =×·½¬HER!AÓË´Ößè,?»ßØ=†ËȪŠÄDy_7xÿ<íî,ö‡+ɲ­.eñÖàÈÔhX؉‚+VBG=«ÝŠÛV =¼R7–Áý.ÎùrõT'(f¡Úh»V7Ê‘¤–sW´Ð’Ž¦À&’áõQN!ëMpqZ%·d岘—nƒ¶;±'Ú%1†LhˆUQú#6l}i Ã ó"™e¿¦šWâw}wλw̸á‘ŶòÕš˜Y$6ÎÖa7Åç4E#v8œ–¹omæf¸À¯C'am²H|MÜ4!vkÿ!VBÞ†ðÙ:Æ Å]å&@Éî[ÝÈù1àô#.sžµ3/MC4XÅ#6ÅE)ë‹nØáã´'a‚Ú[–\†£Àº½ŽfÖ@ƒ¬næ¨|?¢©£_w³Ý¨Ï¦ÐàY”ÎÀlô2K™‡?*#%a8xIéç×¾=¾øs¿AÜrø€‡‡fA#6¤–±á ·GÃM§o#.F¾™Üϵš*wQ¥íè¥T—ˆ”ñ˜›`Ñö7€õF4kÈAËð#.2ìª0hXøT¬ZÔß´åb µØ=H<àXoA#.!rqíg#%[:yléTËs©ÓT#q¿`Z×Í“^!|´Bl¶Ç¸ò´©Ê=1Ž#ÖÑ8šÆέ$'`äQ.º%ì+¶&†À÷{¡èzy…‰5 °ÔmyÁ,Tí6¾$pd‡—ø(Q13(%&ŤÂBß²°Ôla¥²HrÏ#.æcÎ7³wœ&–¥éÖû½C›9Û#%!zˆlžP?V[¸·=¾Û»ÊÄsÍÑÖ™Ò„&w·áÁ"TK¯=k9çÓäôzp¼m™)ðièÖšÜæÄÙ3=êFC¾hYCS8G+}9•­ÇÏ5®ÍGÞ˜sÔÁÐi“·d%(ô#6×nÜÉBiÄhŸáIw°P¨¡%Õ,±h¨¢ ^4˜{ûw+Ñ#6Æ]Án™³ÍÊÔJ,!25.!bÌÎ’[úsHƶg6|kë‡P奕èŽÐÐɪ×e‚ìëÁéë#.dÓ’C¸ÌG)¢”AkotcC~[^²Ù#%D¹ÞìÎBI(×¼®Ò´U6U;â´øÀ¸}=‡ »Ï|#%Ö«Õ¬´”ÑÂ7:ðäUC#6ŠS¥Áµ;’ȉèáÎ\6Fj«U*F7Û`žr¹á˜t¯äXÈ‚ë@¾v…^µš­G1)ã^ï4¡N)LvàYÎò`']ÑL„ª5m²Ý3ã}´Y¼5ÞB@-º· ¦ü¦ÏFµ&¶€á®) l‚ÐÑÛµŽm,¹r,±aòãH }3V%O2‘(ö›–„Ðà£J(‹ÐâHk2fdçqªºDôòÚy"èN‰5«Û¹ˆ]Æ#.¡¬Ï7Á£0¡ :þÿç‡06î쪻BÌÙµRÉÊ$Ç‘‡cHÃáŠÂûJ$ètU&WD9æÏ‚š*Ë!çÈÜåÞb½Êõž…8q¼D¨-ê½0ÒƘ»²ô:¢äåê=¦‘™&-O醥éÏÛgÆ úîí²]+ñ¬K‡¿·M>i#.$×ûwã_ÜŸóÐÑŒ‰¸$ëÌg­ñ\W«§Ñ3nWVGM§OUªy#.ñ”ÜY7#.ï·»·=h=BÐR´”‡gÌß»´_t=V[(@²2N. c ›!áHôØ>((Q6ÿÅ7Ý*Š…=Š°eHÐÿoµéÅr.#6ë\HîÚæzyŸðCÿ?²e˜³ý“€‡BÔVKÓÝò<`PA>B¢*£!>Ÿy5©÷Tõ.¥(¶fÉ(ε‚&@!åÌh!7#%Ü#.[Ó]ì¸F/ˆ5û"•µöi^øUÍÔdwéÖn­\¶qüŠ/  ‚êÌpá<` bˆé·¤Éê5e6Û}åcj墩i,ÚAE`d;ˆá;`‚þèˆ ˆè«UÛ4ÖÖéW¼ªÙ¬”àc‹ò z9$ž»u[}’ÌnS(î—ÁG¦" uÆäMö#%²¶×/lM²`Î 3 ˆ™ €Iˆ‡BÅ…‘ÆêÜ£ÉPbî 0*z*RI‹z»·M·7©½MÍv%»´^uå»ùÞy·‹›¦;¹ÕÍË%ewh䉽#.„ºEhÒÐ% Ô¦¯>6õ|,µ•ŸÁ}lƒ@›$~×Ú#%Üà=Ó$.4¡°†eÏE‡Y $$gñ¸|o'¯Øÿ&_xr¤¹ße{ÚƒŒ²qõøç#Øéêô/Í9xóÏsLXËü‚ðDo™Ã7 æzF%€A\Gv‚íg–}¡õ¨ÄhKmBˆx#6I!yb°hÚùëí*×O–é¦Ïî§{h“Vø­¶¹[sU>þ³Ö2šf00$Y§Ó‘Ä·+?߈ó÷ã–ì#%OPÐ?ÂUHïjÍgy诨·«f#.¼ç• ™r£k¸,“‹CÇ•sŒ(lÈd×XT ‘˜„¡…#.-¡¦êTÞè`¦–—`0¹þf( äC.¸hïâÜ_ |Çí½÷z»Õ‹r¦š7ËHdaÅÂ&ï’€fA=/Q…yžwßv) ß#%ÖHˆ}0!ÂÓã!ì?çîÿ—ðûoçôŸü6*‡œ9Ã}ŸâHß $Áßég‹/ƒŠb¬5B^!Õ i >ÐŒüÝhFŠD"°¢#誨d|M×½÷ÇNV2]Q5J…:4¡x¡²¢(.QÒHMŸnš]E>¶,xC6tŒ‰h/לá†É»²Ô{hÍDhËþ8_£÷ùóÄ“õÒ+µ˜A#.¬Zb ‚¡žÿiÞ0"$œqÝ»1ñ;“£n²èÓxIx5S²ù2ûõ#.Ou‚ *}–À©9,Ê1üKûEåž­è')®Á²#% ÈB £H싶0›º=IÐøõœþÚ;B ³q@lŠi8"d3¿!û±Üx#.ARúì:ýØp´xÔ…ˆ$‘¶¯SÓÖû·¿„'ˆCµ¥ß£sƒì¡ßlQñ»aúpð:r‰S²^uÍz놳ÃéÊdT$Ö`ý²À ”Œ>·†D=‡ÕNž3%c£xIîÝøµÏʼiă=ÏI#.-3}ûüÉr¯ÏõÉÀÃÄ#%ÿ4vvu„#%ÍN‘‘vº÷n¼Bq †ˆYƒ¼ê…(›lÊSiLúÚ¥Äcí&b‰3ãOx±“»#.k#6P2C+Ž´ãLjAçXô9¢”pªq¯ïf÷³®zçíblS¡-§œÚá&+šíXRka\¹ÙrÇŒ`„X#%ˆŒ žâ’¢¡ë ò£À;Ÿx‹¦h}§œ6uò:«1[w~ÿòÑ ³?Ä7¯(iHPjÊj¨¨4£QPuQöt?_‡ïbɱù*îíw(Qa–DçéýM ™ªEbyf:öõ¯ŒìôeÕË8C8èPX‰{il[ÍI~#6!OLcìš¾––@#9OÓçVvÐøX79° #¡Ž@úA¢•V/5MP4€0#.»Bgð¸k7ŸÃ¿ß^×ο}Ò‡¯Êùñ‹(=–côôþÁ~‡'‹¢!ÈD£v^ÿŽ#6îóÊ@²²ZÐXzñÍ}fT°Þ.Rá>çæÞ™¤SÚ¶8‘ècs(Ÿ:óž‹Á¿>z œ,>cº¸½¾1Þt*U¶¼G¡ÔL c3úZo¥î«ÂÁÞµÑáè㥷;WeÓÇc¶¹åpçqF;jÌt,½ÇÙ¤mÖÙ*a\£·¶|kžµÐ/ç¦ÅоÍhŒ¯›ËDP$S ¡x7ãmš£"äŠ[lmp`¯h8x–ÁÁ}7:ÙדlíA¦ÕÃÃ|v#6õw;60ný1ljmß>øµ;Q‰šcµnÊ$[ž9µœÚŒ5)Ü‹QžaH$ì£h8ŠâæfÏ{xÅlÔÝ.£Á°_+À£ÐÑðøbsaצóëÇ#%YbdSÎdÆ#.pûŸs{¼Il0ÜûÙR&ÌêAÇ#6ñÿBHjëP‘¹A골)œHTøL3 #%!+R¨Ï¢VAH©JÙêÄcv­>8}¥hà÷·2Ö|ÊöçÛ!ˆ¿#%ù˜ì÷;vÀ+…Ã"x%õéÑ×Ûc@­¤«x@¥Ñ ºï¡Ÿ8`Ŷoê¡ùÁS’'+ä9Ùýâ6*êvòñ‘­š¹lØ6‹Ÿ×ÆÛywPõ˜¤/ÊfïWÇ Œ„¬ï¡ëµ#.W#žÃòú¾ ædôn;vêÝFl[Ú ÷†w6%‰9‘ªM–ÛpZód½™òK[?i`ë¿WúX†šAžÔ„†Ó}{–n#.˹ÏeA–Ç=ÎB:£‰ îÎhá#¯$ïR¥ˆ"Ã!ÙÙã>|÷É8Žf#.(¤SôܾöÒcC|¸á6RGdõLÅõý}Œô=H )G¯†÷&r ‚ 0Á˜ô€z•s:ñ—•wdêßË-㡧"Ö$3!~ I$ß¿Ð4!•#(í¿‹ Ó]àôö klÑü™1v.ÂŽsϺ&®]Cj¤„Jöm7†ÊöÚ´õŠšúAôöh†)(r¡ÊV‡T’u©£Ý55#hý~=Yäk©"N(Dï·Ká%OÔŽœLzJ“"À^q\øëÑ•X0¸°&ÃaÅ?Õ³h„FE5|øeëëܼó¨_ ë'_·&µîP5' ;ûè`õVSªS¼Ž– ªˆ­*·Us²43d¶º\ÙIÝ]Mœ‹’ÆÚš[]¾TŒR5 ‚²0ƒ¹`¨ÈX¬%JBŒ¡i)¹d¥ÖpìnæDp¹”f²áݳ ²XÒŠÄé½Vù—µôh´55Šf¬Ê‘E$M¯ê ï!åÄ£c#6låÑ1¥gkÏ~ÓcíÝèginÿu[ÇPüúᆤ„ ×#6Ê´—é+¥dÖm¿JâÐÂO}Žˆgº„#%¨‚#%ÆÙCÜ#6„tü¥È|lûžäðv+ªÁÂ"®Ý ÙS)D¨­ìr«– 4óI£#gm‡±°æ´Sà¨P©Í×p„ã²µma·Ø¢žÏÎu„mwñž`W¹ ¤vëC0‚Ù_·«#%b ž˜n*F¢[föUŽŽÃÛ¦š¸í<¶‰ÞNHO–Nù'ùîHÙ¥#6¬…#.¬meQ€Fˆªd°QB$J”Œ`ÈÓD©*X²R’ A¡iP‰bB‹>&í'5mÌSÀ‡aõP#.ž3¼ù­«¯Uõ_\ÊƃnëµXÚ€Iét÷ÄAÓ¹jr‰ir%§Ã^[šõpÉ!1ßй×ÑXZÚ§TÙóYüÕfǦ³¶Kò`^üBþ“™:â"€^%GPß­:D×-nóD¿\“iKÛ6ªª§£Ú!ÚE$H#%;±Ä+†¦ûãÛþ:Á‰Ù(gœëw'`v2›OA¸ºÚ¡bˆb$(cÕ¨‡Bô6H Ðçªõ&™:å„Á[ýBðn‘6šLÙY¢’&oáoÃa gZæ4ÅS$.vøü}^Gwxù?LD(:íÔl†Ú£Ø|û»^ys*½ oèo’­è¡ýþ{o´Ò)”4±"ˆ‚EƒÖŠ"Îg™ÑŒf¯:ºJåM.î›8ˆgÕô8è$€ÍI¬´­e¨Ùòˆ”7Ú!ôäþF›­9Îòué¬ ÌV°WT…vgˆ÷ÙîNž^»Þ×·t) Õc=#j7®çkÏgÔKm&ðŠßÌåܹÁ5.”SêÔÆɸŸk4 JApN:lŠ§eÏÛÆ­‡m2LÆ?¯]°ËYØ¡¶“¯Áª¤úCÝÂûªC!!hl5ç©\¬Ð™J\ ¯×¥ dHÂdê43d=BÂÁH#¢‘¸pK5Qz 5ÑZt%Î^E†A‚@–@Èœ_àæ÷e{>ñ¢ ³<Ô ‰²Æw+¸s, "õ€5#%B «Piuô+55ƒÁ‚Ú4ÍÖo.Æ#*H) ŒBˆFõ‘ˆ®¦`Ș`¡âÏY¥­Âz¢ØÃɘj8MË!KI} ‹A#.``(3ŠU€Àõ¶­Ô&¢M•·ÊêëlU”j0À%Ô¥†-Ù_›œá烞;^Q=õ\¿)ŸI#6w¬©”H¹`Íöò€¨Åïå‘|ÙF×mÐA;8ck³èÚ{Î “{44‡ ”JàÉÜ™ÕÏ€}LPCæyBM±dY¾‡«²›ábyOÄ’ýäµ’ý™ˆƒ~šÉ¹úšØà›Õ#.¼C"¶‡I<Û;úÏÕ‹{FÊinlü~}|ßáñBûÅÉ{øºF¾ dìàÉ#6çîà±!!1134ã¹c÷t³Ê'HœC…˜-&Å#6°ªhvÏWqþD€ÈAˆèªt@‹QÙÃÇD¹Ö ‚[!ä åRÉÒs'tÃ-‚T#%g£è雕*ª“ÒY“Kt¥ÅF"(«UV#6Ñ0&(÷&T¼Ç0}zšƒŸO­‡²‰Qj#Æ%…ŒN¼ƒ±€¤nˆ²Ÿ™(VMBòÑsýà ¬¬ãb¨LcC@! ƒ.¤ð¥t˜1'?]‡ˆŠ& Õã¶ØÀÀ¨‘i‹®(DŽ÷¨æçÌâŽõy¤Z¬Ý*BèÀ½ej·–Mdø¨Fí¢FtHFØÑ}ÃZ0À"'•¦?ÑâÊõŠhØÒ;ðdYC*Ï;C¿ ­P…Ct_ À#%2Nÿµª©°¢dÔÔH<ü%ÝqHMÝI\uª´’ß ßΠŒäLĦæêpÚMÒ<ëç#.­†ÚÊ8ôã%˜fL‰QÇ&јÅ\‰*…å‹01ñxaj€ ;‰”ž‹ùžª{è™<(…pÑŽ® =¬¢ÿHy!ŽwD0íµÞÇ•˜ÔAc&™´²–b‚˜£Š¤Ø.5sSIý›1ôj2¶ŠEH¢ƒ¥·ÆÏ,k¬Õ=­ÍñÚÍÍ2äÁEœ ¸¨(ʽˆ„ :¡9ˆZkµ‘©´öO<שMFØÚË!Lc`0Ò3s@ï}Y÷N#6late<˜pÖ0÷J"DzØØÓˆßyCr6±Ë#%=l+§j¹0 jÒOþ¯|×f>-=q¦ûÊß:Û¿ƒ×¢ó1Èø¹¨õ’’ ^¼P“\aa£Oö¶³r@^õéu4¨’ãº} ˜xÚc4uÆÙàâ×Xgds°•;îæ"ÆÖ,_ãMþºl„áÇtï¡“ÛKV¬7LÅ¡8ƒ 9ŒÀ„²T(5T‰H†„™ ‘¨Œp­_;KŠ¦ùeÉYJ9-Uà AˆìXÛIò–.#.áï#bì’ lÃIm£€õ˜U±­ØdáA´”Ã)jѹ ÒMF…Ý4m¦¤’j!6I&̓³¦&1>ì!áÞ¦°ãm.[¼R>Ø]™Ã]+ÙÒí.ì]¥ñ•éx·´®jñašJ¥-#.ÐÑÇ#6†ƒ%±dA‹af“ÂÈ­[&fVî£ãøIå.Û¹ð‡Ç9ÝML™Í5#›Ô’#|¼™[A‹Úæèu˜‰_kØAÆ:œQB3³eÀÔ/ð°ÎÊF ws+¡-+¬œpä.Q­‚S&h%mK‡ƒOÖ¨fö¬¾ ÒŠ‡·šñßÝä:yGÈ`ÓÂ$F…½"šˆ„ˆ»|hÙàP;#.aHê‰Å4¦”K_kà@Çip[6‰6y3÷ˆóxpBÿFýfÔLâ[6ãknk׫‰™®TãÝ¥¹„ÊÊ—ÎúNº¬Ó 2I+FÂmá‚ØÙkå>)4+.b‹$馬ú‰¨Ë¶?m…ÃS>^O¹ðã³*0üÉÍhæŸ'£~;j–0æÕº5-Nîše¶F¯Á³9HßGIÚÉr,=ä°4!{nî8nØýÐë’Ùë œ~Æí:gg¿˜Ðƒ`È-@Tùÿ/¯Þ?D/«¹ÕíاÁB °!D±¡DÐE‰Ï% #.&3í÷R’ŽÖâƒ6æ¦÷0Ü Éu*:hë$‘ÌM4h@I&…M/WX(,¹§fh#6l°#%„ÌSÎ`°£X n¦yÓzÚ¹‹©i¥RJùkïVr2L”7käÜr˜E¤¼Ö¦EÇRJðÉ·ÂwXU :½–c7ãweû‰ÚŠ(AÓ×Lo®ÜXçû¡¸×-•=®1&òXËÙL9Éž‰! ’Ù}Á¹IǾä\y$þÉW¦G†~ÃE4ªm©•ëS_ÉþßÌ G®#%ˆ£sºvYBog•?’­~ËA%*j×Ú¹âÛˆ,#6ѵ¨¶¼TjæÕ¶5­¨ÖÕÍmͶ-V6«¥¥ÖévCÙç.'Q ÷¸ÁE5bõG9;#.¶ïY4¥•(ö±Ô÷u;ƒk®ŽÛœ+¦¤ùï4šÖ¿™D’4$‚S&e3JÓ,É)I¦)5E¤ÍAúΤÂZÒ1Q4Ô¡’š"P¢´±¯~Ü¡“ZLY%™[4)“4Ì‘˜hEQC”M½ÝDFÒY)˜¤”–PÃT%¢Ò£EL¦FhÆL•¦)¬T„Ê&ƒ%!MA”¨ÌA¦ƒLÚcH` ‹4ÑÜS¹&óg¶§äe/è#6b|[|X&Aï~l­U_SBݘ×Çøf̈þ¢˜;708ëY!,”Ìm¯Òfvòús†Á©Ù9`ÄÞ ¬ü8Î#.©‹4czKÖãj\ ‚0Ž¬Î]iÙ¼ ¼Ú(’5÷Ðz—àmÚn.Ö›¨—,mDñs0³Ž¥xÂxâN;Z-_ßK¡­# ý‰}úYJÒ»0teŒ^ÎÝfw†’~âÅçãîùA{*ÂïÃñŒŽƒbm°Ç Œªd© ­…ïúûZø^Ûo³_‘bc5 £#f²V*(“i–`!Faå³><9ôí0ݽò¬X ›#6"ƒtXaÛô3³ÙŸyèNUMæçaëÔY„b’™Â†+ÏNbC 4®}û0_ê®[ç/c´y‡OÀôW¿—¼‡}#êk#6xn4ëO–åûÒ3Ï=GQá’íPœê‹+™|ÎàÉ ÒV_£ãfåÄw&}z^Ë –p{"r>Mõ£ÓG]‡eUY´#.q¨ E)¢AT‘$/rdÇ¥oKý}eÂGÝ2û¶ÛùåßXÇÆiKôôˆ£¬Ê%x4ûmÁ÷cÇ—$I*#1â8-¹¬-ߣ¼8ó#+ígÇö£‡dÎ CìÖ“÷µ« ªIm¦úõöÃ{N¹”`g"â–PR¨EΨ¸)µ›xãcB?+ç#6cguVÖˬ!çE®PÓŠ#6Ú+G0Âè'­#66[ïG8 ápI5ö,nm_&·É‚Ôè2…ò˜í¶£·ŽWÂc.[õ"^7L³§<1YCŒu-Í4î'¼Ñ¯$º41² Úîg’Œ ®„Ä©OSååšä‡½ðæ^R°öœA虚O?M"… CòqôÂdìNIÈDBª‹´ÊxŒK'²Ùª ÕµÞŽ¢gd6Eõ)×FÛÀ¹m¹™—¼2ÙIb=OiÑ·,(ŸŸÕ5X@ý\µêž{w÷7g FÊHC–ï‰:ڷשÔ'®½]Æðëì±õz¼†— Ãíúëïúv“¢B¤†xà÷Ç}IÁ\³Âw¢â‡vÏ·§Ó–æÖ_¯¥ø? 畧ЪX‰@w Üóßœž5Ìíí†á#6áí)~¿.wðzŒàDà ¢Ÿn”GkBkjl8ògâm»]š•%}; àf.äIG^fP–så­3 jÓ5'B;Cq¬ ™™#6;뀛?/æåüÛ>é5ú³0ù²Yþ–¥7Q6È£Šö0¦Ä¦a i™ªF—˜»ÔÎELš¢ƒÖ¡•ÂŒœ‘u§÷5˜Ú30ÞW>ØÙ‹šÓ©œê<Ô4̵¶Í<¼ØÍ3‘©t,ņq4hÔQSRJbã5¬D‹(E…Æð¶ÒçVL›WUޜŵ¬ æß´¥(%©ñ?”ÕKľ$–.›¥âÃ1^{¶S{ÛeóL:Ø"ža‚ *cŠ“óuo\ a\MLËhz²IÆ´lÆV#6¶Â'¿S³Œ;ÙŒï¬îç;WGÚv Òá8ƒ acgµ9t!éî^ Ñ´åd»Ìê5+6É 5#.ÂÉ,0&àbÛNJÒ:¤é°~­g–]øì`ɽ/Ü,7#6ÁŒR[Ì&*_¨€ÊÐõ¡‰êìí§ž4ÍTo#.ª?02!ðnÐ6#.ÂΩª²æÑóÄï4Á&:ÏJFìÀ9]Ѥ]Ò¬ua®y:†š0jæó2w67¶ŒLªL¹‚$ôgç}õ‹´n£ð@ußpBƒŒí…´ñÖ=,æYí?9Š@í´ÓRP±áɬ@ºZßlAsø;oˆ‚Nñ©¦™«¬•qbÐ×gÉÙã6ô¯fl-&¢<ºF!ÏOB|VvÌïDDÆÇr¯/“,¸Ú‹z"VnöÍfrg£ÑñS­ëqH·:Óº¶6´=V_è-³eßÇ®ÚƱã‚æ·mˆO¸Œè¢õ¸t“¤÷)0–ešÔj§=1åŠÎØÐà’F§1žÜWVÕ£i–7îæ)¬Rãžw¾_<ã0Ý®È^ÏP•Üd>ÃÜllg:Žûà5Úã%¬GQÄî²a…3™§¦è:Ó;1¢dÆ9Ž°„LJ¡n5´š£Íš']ºß—ÊßQt×\PÄ##.'yJX5Ñ\F™Ö¸2L‘/Fò.ZX]ÔG¡‚Œ(¸jS }5#6jåVͶã]*—ïXTäÊ•Š°­óqdßûªÚöFSB™cÕ\llÏ^sÇ9*Në¡Ü,ßž]Ì•öO,ºK+çThu¿(vÎ[‚=e´Æ™™¹CAib u†S"“q0V^£ Zk¿kO+gX›]Ž°ÎNe6¼™_y#”n˜uÁÕÎkƒ¦©Éct9)¯Y6ª9àZ€nl8\e¢­‘±¿#ƒ¿˜A#M|fS®±*CP7ð˜vB¦šEVöU;"áÖ“€X.\†[DY\('¹Ä>›;Öï8‚óghh:yYz™ä×&YNÚ‹0,¶iQ!³é¥ØXlhÍÍÌpÑÓNVŸNÚ]#. ºÑH.q¼†Å:¦ÌR‚IFÈ¡“bÓÛ4=¸ÍÃ#6Y¬ŽÛëEÎ&)Ä+æaõ—Æ0[3A”@¡®bXßQÝëí*1‚¤X‚1qI—N~.2ߩݨÛháÛá£Ô7á‰)” ¬neïpOVêÑÙRQ9B&PÆ7Ês‹iõnc­ºÍ7Ûƒu³U·6vu†blâÂçìw‡Ûsðüa½evâæfcyž5Ù9ݬe|[Èu`z§ Û™ L>8¦²‡·¹O/ ¦ÅR=:„%›)Ç’:Ó{¸ÜÖZÍQëF72Ìf2û"t[¸—LLLb|¾ZÏÔáFc™êEæðó8™—‡S7G”´ÖQ²´ƒÓgórâ’Êܨ;ç¿©Ç1™£Wœ•· i©#\Z%±pƒˆð²ÌÝUX6嵡s2úBº9‰“†H4qÆ:jn¬21É O)&PmV†Ìâë\—[™lÖfõŽ™5,yU–LbÇ0vBŒ ¢&¨©ÒªC¤‰r# šSH‹^éi!°Ó×ÆÊ»I>ívÃ8YÙªüµW›a²EZN©Øχ–+aì'gj0šŽ²ÕUÎ☙ìrÓŠÖ*L¾#6$§Ê 3vðä{Á¨·É"aNû+â(0àe#6Bu öó›Rô`h©µÀŠp PI©š,#. f˜F’èã#6ëÚ°äÚ¸c¸M­™©_{RÆ£eé\½1åf2åR;ÎZ©a®šf%‡Ã±Âb"âzÿºïÍ·9V¶ßé2#.¾¦¡#º@DE»ÎuBI‘@aàÞÔs‰¯#]Öhè P h“}”’‚•èuz1‘Uõç €tÍ®NŒzzOQ(‹¶Twqh÷Ä঴üšÄõRù` »pZPLÒ;Ì7CN]ƒ"ÌŽÍ€äü#6.s׫ZÃ’‰4ý½Ø'»õâΠшä^î‹le,Tm®t• ‘쉌SR™ 3› @±0îÃt¬y\)&Œ#.:b8ô“!ËK@õ´]NÍc4Ü‚Ó@rÖàš²e53Al2ȈbiA-’™µR‘rîšvÖºS%#6#¥ÍÜ ¶ói"2ÐÀ…°œõ­3Sd”ÂÅtvNI-"ÚS#.ó['£‘2ä`éRqf à˜d5eëRªŒ#.XsL%q®i¶L§¤n2éÍc*±<.Gâ (N¶çc²ž¥i¶m£¦ TéÂ&pL*ˆ[#%ŒXŒ*tv™‰‚mœÀåŽÈB $I”3¥/ObYÚD³»w\ñ#.»dÃ펋xå/ºï#.Ó‰\lÜêÎ#6eÊ47Uç3}Ç/™ÒÙlpNZÖ)£¢Ájx#u±¡öMXNRÎÒ¬˜³ˆÎ ÔÁ|`5Œ`pËè²3Pò†à‚f—8¬&„7PÐÖÆn°Öj–›;Ã'žCSž…™_¿&™ÓŒPiIÛ+]#%ODö®÷Â,zÜÎùèe̲¤9i 7R#6tÈðS0@e°usÇùM׉#6KÕ5B˜E ¥!UAI HX.Ëb004’ÚÏêÀóbŒ;àG±.NâˆÑÔGI–F1T*©ÒNï_»;QwW‹˜m3ŠoüòÊA8ÐTX$GaJt®Þ†Á˜`g£é®á™ N Ž¡}[aY¢¹I‡°êˆÒB5RÙÂ[#%†—l8Øqˆ+CŽûÈ¡¢#.F+2fisÄØÜ l³3Y†ÅÖ¸©Hˆu#.Íî‘„ÌI‘awmwš#6nò“aæqÁÊŒWÃ;‘ÂeU ô88JD61C#%CGfú1Ãg­Æ$˜±ÆNØÃɆµ#.fŠšåî äi ’q¥º£ Ã0é#. (à›™œ hLÉåJII4ƒdpjŠì•ËrÁ·i3fÕ̺ÇEÐÙ™9—Fm0²jJG8ÒgtÓ^Rg~V@.·uXiØl4I˜%ÝlK9Ã00¡Ü[Xn&uA#%Š0ŒIF ÄúÈ%#6¯qCÿ$R5Á@w³;ÀiSh¦²…Ê#┈1Aÿ6¾*?g€|zœ(† íW¹ *I"Hƒ#$d‚#%‚|jÇØ?´È3$䈌@q:áÔ:7H¤ýhuF¤ˆ@„&È4€¨±TC8Ì •î#%ƒ»-=Ùk<Œ÷˜º›~¸X$Ÿ*vʪL>ô ÷ó¼JÓhiÁ×/‰Ô'‰Ø³‡—7®R™­ÆM߬·YEr,;Bó®_}®P«4ó¸ëá›&A±´Æ\©s'M•.áiR¸k5†…ÜÖBh7„nÂ20+aÀ7èu%¶ eŽxn„X!ÑÕöõ#%c=¤×Àæ^çõµ’§4pu\0R ÈpBÿev#6h•"J¨”ÔËkñ¦[m&òRjµ*ÕᚈPÙŒR€² q¶˜X¡1H_§‡D‰˜#.o=#6“JAµµ‚ÍBp5㊡Œš\¡íö÷¬C$;×á8·SoWÇ4íUú‚*ˆ#%nùnR 6._¡S—WwUÙn»³.nºn¨-sd¯å¯5<¿Fîȵ¾*ä}î³ÓÁAáÖ<‰`P¡ý÷©¬ŽÙLv*Žôr†ð8«#6#%„†|ž(u/¼ˆqœz0g-ZŠ"½ (àŠ{̸°'ìò@7>™GÔ»ìo?6©2.œþ“0Vè<œŸ­²¾Ü?Ø|~ rÚ=¹—ÈFÙÙwE¹µÈM 44¨ÈÀ,ˆœ;Si#67‹ –P¼o„Æn F¿½µ°bhÐ1D)¦ ‹õªS@£¦n0—.Ö”™Ò.eÆùA2Ac¿´z¸äf$YÞЂQ#.cG÷±3þ!¬:?+xø…Ë–%êá¹A.‡¦9FòKPí?Vþ?_¶×äUi´&RkF±£Q[FÔIDL“`Í3-‚‹lXÅ|ÿZ0Pˆì´O€ïö¸ñÒ´TîRºÔ᳧zä™K¼º:ŽØk5vˆz€4DŸ+ZÂ"kÂÑ’ÄDŒFÓI0Ž#%¬D‘¨í #”E¶V-ÄÞƒ‡ âêxÝïf§PD`@Ë[΋Iß3_Ùk̹<æÑÛ ÕŠ~«Qb*H²j}šJ²a_x;wÙ$”œŽ›l[^•ÖAõ4ÑLÔdÂËp‘çbˆ7úN(ŠÒcKi"ÈF'¸„Üf5jå]*¾M½KÓoB5L­âÕÙ1‹fR–@l@ÓE`›Œ+K†³D#0ŽQÆR&lcƒ8®åB+ Ö×ËHŸyÂ˱žJEƒ†ˆ­HÐq ²@Q¶“Uú©oƒ#.ê;˜‚eK¾ü'Ÿô(ï‰éz–”#.s’ddÞí¨»‹¼è‘%Ï$¡ˆïÏë&ðÙ»#.†PÔ…HåïT¥Èõ¢®î°]Æc(i“°·Ej#.^&Ž²Ð†åZHšp0…“8‹ˆW‹‹ª.¢cc#%mÆ LN¨–L…uÈÍY^sŲñüÞaÅ#%ò=§w‘Kbm´’lc+A)aLDHÀ Æ-Ÿ°5Iq0]i>â k…@ /_¢Àmˆ!š*  I,Ëñ  ‡Ý›¼;âdç¬D©™_&,ŠúMŽ“õÊŠ6Á­ ý{ˆ8QÌ`o¨¹U¹¾NJÚ## ‘qöe]²gÞRšrE0;>Ç/¼Ú#Ú:í¦Æ>µîÅÇmcz"4ˆŠïU#.è§ 2†]õÈl0ÒjøáiiZµ}†køw 3†FC“®•zª‰¶i!KábÇgØÌ:„'5˜’bCèVmÓc{”^ZÖH8 “‡ ÉË¿+#%­Ó¾æÖZ ­øA”ËIÃ4Áùz¶^ym£Á¬ÂÉ'Gi±†êØá9E$åPš«%*‰ ÀUŒeYNÜBº1B)#6×6¦Ô9sypYµ.ݘUfylM‘¥ç—x¸‡kÈDÔëi¦lïÊ‹]ôŽ†ÁúÑ ¡C‡|ÐÁÅF–1#6hÊ7n®ÆbC#%ktE.J Ô˜DbTJ¨š Q$Ø£J#.L„@Àc¤œ#%-P$PRÄ[¼ t`luqlg¨LÍ #6Ð?Æ@  ®åB<5í Ÿ¨;+Æ>ER+ýÜÉŸz¹M8¤Qb{(=Gø+t Ãï ~L>±ÿWTŸª/‚¢ÒkºÓÏ ó<1G¦A¢|A]fsÕ10#!ëGšú™"‰‚d„’FHÅ"½†«bƨÚɶ¬ZÚM«Š„ "BCÒ÷©š5 Ï?=x•T\½KŸJåÈûŸ ó[ʾ§ôÀikE/³Šâk|t¶u+W…þ n.¬­…¨ê¬ÞÔrØr­$®E#.“{:iÃYÞ%lšeäʵS0:2¥KŠYk8ißjÓm&ìÙ&èd­ñv5-zÔbŠºSc³AÎ##6pšHÒ.™KÄӃƶð¤¶Ê>-ÌÞI†SŒ1d¼­ÔèËÍ<»SâKÛ¦3‡Û’$•Šiȉ3̸jMÙsy†ô@#DmãŽü¼Õ‹Á(ÑŒíju¾N&H†mŠr¦=fÎþW˜ÑÇàËNÔë‡5ÀÈå‡Ë­µÝÀÆi>ŠSæ)1jnÀI™Ž‘®$ÌÜC#:¨y>ÖÞ*¨i½ðyXÛz›Mp“\ÎJùš}e)œãï3Ã&=¾¢¸É&B°‚âðÇ"íž–7•5¬´ÝÎ+c¤ØàdÌrpQ© »M=íW0ƒ arr1Æ@Æõ«t¥XE€D‹LXÄ%‚ѵeÌôö²ÒBÌ´¼›Ë•ôÖkUã\§›©­ê^y^¦¶¼¼âƺÜÛiÖíª ,ŠÜÔsK¡B4ªä!_ÁšhR‡M¢†:—«#ÿRDõìÍ”¤Dkm^| œ•ÝÅUÚì›"hƒI°’1Ž<¥jÆY*dÂK èíƒ0š]#6»jí&°n•ÝuÝÅ&ñ\µëµÉ–§›®ó*òlLi[©­Ãc]¦£hÒT¼e?äÐÉH‘Ã…(¦Ñ³R¤me-¦U$…”™f±¶5¦¤S5ÔµÒ´²–™5¥™SUFŸ6¾^xMEª *f‹VЕlÒ„T„7–öy™¼túccQ”Õ©£â™`IPÀ€¡Q6››@‚—bQ‘Q‘P´X!º+çÚD='qí°z³ÄõŒ.‡kÓWéaKÞ9S@Ð×î6ýy‡†´Oƒ;‘Øngq  ¾ Oz³,§E™ÀËÂqhöëÏKS-Àº#%DŒFßÝOXÅ¥*jXÃɪÓm'ÓO#»;ÎLÀMÉÞ¦l1JœSí "[ÕKŒR¥U(ÑJ01!¤Uý¨¦ÐŠa•#%¨Çj#%¨)"ìØn¢¶Í¸—eµsÆòèéf´Í:ð²ÿfÂs©÷ pÝ#%H…5¦µ.Gf` #6 ò®µ2™ñÞ‰ eRD£T5ïÓ×ûûyk#.Žæñ#.ãÀÇ=AõÕê4\¸Twíé©Øm?2s¦O^ßn’õU „\ˆ«#%rãÑâuJÿo‘¢Æéˆ%òÅ€´ AS¶(†L!¯$yB—`w?6Èl„¨íx3ÝŸb…ÍÁ‡L8o\šårEœÎD¹S¤,`&Q¶7ühÄ´t{Î+Áoœn/1~»bµxÙ#%à.jßÞ¡ö ~Ɉ0Tˆ„ªþ—¯æƹ¾óíèlodð8YGçÙ|fQ¯ãûô0*mùÊ‚¨<„ h%µj6¢ùýÕ²Eâì(–’eQ‰’MÍmr,¡–‰¬“Þûµk“M¥c)m&Ê6-")¦Y,¦JUÅ,µ”gå]aM«)˜lÚ1&ÑFÚ¦µMÓŠ+"µ+ºéµ }í®Öí^Ý»*b(2#6em¥­)­IkjhÆ¥Wµó¹Ư~í’lŠ-cd¶¶ÙH›e­n]ihÒeRMKmçáM‰´Úl¡3#6š°ÛilÚMìê­KlcãnŠÍ–ó«¯;’R­2hk–êÍRW‚ë5x®Ø”ĪÂFÛÂk±ŠË[L7ô®ßõLUšq¼ó¾T•ÔÇŽîRÈ´­,£›^›?/Ëá>Ïw>Bmôs'`˜ÆèOeÅ3$˜SF¯Xqå×⢵žåE÷Äô^éè†øì\$1gÁÚaž>Ž®ìk£g]7bÙ 3meÌz4º:¶š.L@ݤ¡áÈ"¥+´Ä»/šö7ñ_‡K3ü½©=Úßn9=½™C­#6?q°Å‘@P \cha!¼†„ )Ìæ]28ÐƘ‘›à¡ª ƒ(ÁW_@pÄ$•ûŽ -΄¸>õÒlÕsuæ°ÙåÈ)P;+ôø ž:ó‚lŽPù À‚.3ôу¿ŽI÷¾×‰ÅLFz%;8ã»m§f¸ñ¼õЫ´Ô¬ovÄÅ.šy‡Ëg ØPÝM±"Ê~¤}þ…b\åö2eÏàØ¥WCó|såÇéл\Lu#6“8TóT>µK‘ƒîªtJZ~ÙVêøPŸvÙÂíͳ ÏHdÖ°éè#ÅÄØÚ =õ øs«~O†Øõl£qGFù¬Öû#6¤Èƺj–µ¤7Ò6Wi0½«#._Èé}/[onÓ€‹ @òî#%#%‹lj¨Ê²N"Q@R+¥rÔ'8#6Èo(Õàž ‚"2! ÖDëê¥Ñxšíb¹Õu^¬U˜°‰=³¾_vóÒ…‘Xdé[ž&ya–&\T•CA¸œ!Š$Œ*¨c#.ª “SLÖ`O¼I.!&*x³VÏz§@â]7ù=ý«¨á×èv#.çWµ±ç]{|)LcÜšÃPó €fÛÊÖs²šD\OúÙÀ«–‚Îx…#6((S)øbî#úÛËR’dA] %Ù@ÿgìºùaZÞåe±F6ÐÊÊH‘F–Œæª&cD2LŒ#l#6Ðh{ÄC5U.mÈÁ¶“ ÄH)fáu'6ÑÆ¡‰†±ÅXƒVFA4^Z®¨ÆÎj v–©g6&  b S´·»RÅF[¢ÃK#6ª‘@Q®—I–­ŠL*cð¨Râ‘¿J“T#.t#%6:^ôtqs•èÕ(ñQ €jÔÎQ§×hXÔz´A;Pƒl|߶¨4"Ñ JÔL©ª‰‹hJ¸XÌîÁò€›`‘8ŤMýàž5çñæk±—°÷§ŒÁÜæ" k;CXx†j/zø/#£Pì|…4ÉL`ZhÚ-AXAKëí­ÚÛ­[EìÔ×9b$>#%ý0¸ Ìèª=V.ná·kmÿ>sê ý¹gźÆS®i{HÔ·t0Jcˆ*ßÁ$çL¼•·ŸZ«ùß$!›Ã¾$ë”ÚwËIƒ;àtn”l øÇ-i¥!I¡#.njßRY²’VTÊÁ[õðð™l…c0¶õ«ìXlA‘4„(Fë¹ËÈ/n•÷Odçèʃô½teú‹&YùA16ºa2‚e8 ÔÁõQv!h+åËbêÅó¿r@Ã…/¥)Æ®)iQÒÆâO±¹9&íBø>ÿ|­€É­p©*ÚYKmj”i!´ƒ:I$š””žm­DVCCpš€P±Èc&P1èó€´âÚs½s¯gÙ™² .Û!›H #6áPªR3ÂxQȵßxÇ™Š¥ƒcQ¢Á:÷Ts‹ hiß5¶JÆKF¤„ÉÃ'3ÔGÃœyÍãsKMûé:Ÿ]û`‚ª‡§ ÃÂ2‰UKÕ•JâòÌ«ŒÏZ§N7~R±î(: @"¡ÌȡⶶQfíf´Ä‘ÒiDÓ´ThAŒ´~Œù~ÿNè>‡—èëTšPå›úÇQpº¢ˆóG‚Çšpó ¥€CaFE<Q#%,ˆ2ªœä°®Gíâ&±û¼á9Ťð;õ1A¾¼uŒÈŒhœ)¹¢`Ûk­„NÑD’ =ó§#.ùüq ¹ Ž[tcv¦¢â#.iÉÆLjÆD.Ã1ì˜ÆVí¡¶&q±"J5†Òë`̆/¸:ž”¯l’F#6¾”R¯OQz‹#%ñ=;NÝÖo+fy*wЙ¹çF|û Å"TX¥BSM4…DB —¥×*¯rïšJZÀeE–¤É@òrÎf§„PÜ\/èÆQø#%»¶’(tWx.ǨÚP QÕ‚¤BÉUN#("»ðX¨2#%›LâF›M`”'°fT(#.à2–pâ§.=ZpË×v3œ{×raY &&´Ú²4î¤G] :\„clç¹¾,u/Ëß xµî¹anGÇå¬$46×PŠÁDùkŠ‰’It¼îÂ2žv¹ÍÄÀŽ+­¹,Òçžu ñŒú UGLc0õâu{2=AÑ+½ëÜ('_¹HCX=˜DàmÆq–zEn€ÆÅ$ONÃ-Ž’¥¯Ë¡e¤šÈ#6¤ÍSY}Ÿ—ƒ“¹‚YîêúÑ#6I£åíª† ¸%Ý£HÐÍ?]‰$E­/]jôåå˼n¤ÛìnÈ™”HNõæ½Z½jé%»mj©RC¤Š@…àmQcš°^:wn) «—1KÙ)yš#6†­QŠÒ€4šlß·ºw7¥´D9Š;¢¾âênïÕ¢ìÑꙧëÛÄtN(Àºü5šîIåÖïãrBÌ©[æq‚_S¾®¦Rg¿s%_Æ—¥àM~%Db+)'æhwJM¬0…«ö5¯YFqtªÁÏé‚ "懲‚:Ê­•½Õ4Ñ´L¢‹Z®Q•M4šjW]6èrbK$ج[FßVäbÄVkãJ*¯KÒõ-kÆ嬳oßýþñ¶Éki¶[V½*ÝrttÊ7ĸeÀ ®h 'kåŠг)ôãK —]¬Îe´"„¶JJˆPÉB7&®r°„2ý(-„Øo)’€<(˜ û7 Îu¡¬²h%,3al!™â ¦±hv>¹3Ù]´l4‚„}»ÒX(¸ÐÞì½qOt”T5(¿åiÀ’¤(‰º#8+!iH@ÛaSòÕ*ŒµVzPT*éd“W˜fTp9°ÌPð5 ëÖàtïôQìꪅ¨…E#5ÝvÆÓ"£I´Ul­#%&°ÝíÝ+Èt00p‘²Fù`Åì&á—,Ü}C…pÀ×t,Våp¨CšA2 ¬ ÛÑo¢|¸¾ÀÞï'´Pg=b,‹q¤  B€=cik=A’~x#6gLüqöÿË€.×HšÂà\‹h]IÕíø1…Œ‘#%¨%扨&?¿dÒI¡ÏÊçÕ~¶ÔØ;Îáâ¨Ë#.ÃÀa a‘Qúùh€ŸFÍpA24‘» Mšjÿ-ŸF?=+áÿ‡ûRâl~C~˜œƒ$4Kç‚^ˆn«&߃Byï‹(íê`=4ñ…x(«C’~¿´ŽA@TTвÏa81#6êå{œ êÒB|'¯—¯ï`Ãæy~6×Üß=a§,»rÞtï£ÔŸHÄT̉I9¨™¦¤¯V–¾T­ª‹SRÙÍTþ ËÁ˜I¦ƒúËúPцjˆ,TU#6©3û®ÜSE,#6@¼•I#6e,%Žì†€Ze¡Cð@ÃQ>9yñþ_›¼ï€Õ-’­6#ÆD“ca]‚ªñË<>ÙZcm¦É\ïg:F0¶ 0#BÌ £&D®¤ÍeµÄ±¡Gf–4'ÔF4ÆÒ„qI‰Žlb-ªÍå†LQ”X(‰‹J¶™*™Ef°‹-œH#.Ô’™a4J@fµ@¤ ±I2ÈPµ›„´Ù’œbƒb$]’ÌÐLïR`MS$’•‹ µZLibm-äB1ŒŒŒç+–=B`HVZM¨“F`L%¥ª¤mV>Lä±¼xa¶EXVÆ¢ÄÞª²¬ ÕÖAÉF¶áÃ4gJ’Z¢‹,j¨j¥0¤…'6Ñ´®è±\·6Årܾ#.ãc^»½.4<ºí¾-“¹1Šç4\3•¨lêApÌjÓ´KŒ&D`:3±ók0Ó,$i¾K†µbc‡,P¸yA®5&Ψ hÕQ.šHº5@€ák[R²°ðÕ5O<­#.ŽC:Q¨€6%Üe{îË]ƒúÓN×Ò!£ Ñ uP2Ëñ»h|€úim²O:“4MiãÁÖÆïØøÈxÕ,#>¸Òc!I¬ÆñÛmwºòeºÍ7YºÐ «áùqüô”Â1Ó ÍÍÓ+p8ñö¼þ#.áߣ .H(ô MTØØ?9ø Ñ 0€À«¢¯`1 «þ8÷‘A%Q#FååljT²j,ªê£TI’ñn’ª0±¬QrÕ]JƬQ¶ÜÝm’ÓDbd”@b -eAÔn*¬Z•$A$TɸúÓøC )È°íDÔ@QHXÄHE¤Ǽð?ÙÔX#.Gꂤ@ƒÆYÁáõ×g¿Â¬{S(±ƒk—Ùæf¹!¡çò«W²®]¦Ûnºë[ÎerZOºÂ¡.TP¤IËúìÀ&#ƒŒé¹‰ÍuÕñVã1 Ng°þ["ALàlBƒêŽPoÕTBD‘WáU‚š¼ZƒPø¯4²mdÛÎÝJT²«šæ·¯¥Vò̈¢Ù+Xl…TzšÅŠê»ª-zjö»×‘/]nË\Õ|š×šZƯ7uY‰…$¶¤Õ©3J’ö÷í¶ØšA¦@¨¢G¶2<㥩Xý|º!ÔÑò‘kk™E{”\±È5¨p¯Ê‘•E.I#%}3@¡„ ‘„Ë Á±“,€e rIcÇQ4×´Õ0NK2#.É#%½ Žçì”è¤0#q ÒòœMŽ›ÇnXq[‘l'µ}Ò@aš%Ç¿¯3Ëš‡74Â&iGÊ<Ø!DW‚bUTŠUðË›Â[åHŒ=TvU Äh¸¨Z7aq“P׈ñ0»¹aÌ°oËŽuÍ>¨½ ¥ECOˆbÈ€(¿ˆ|³”Mî®d=` T6qÓr.À;Q$!îa^ Ò¥#.-T””iKJTÕcj´×¼®ØÓUšk)êWQ´ŒE%D/å‰Ðñ9™‘çÙê°Ä@º5]°;c{nÑ÷µJ*ÎdBdñaöü’6µñ³'¤.ÿ¤ˆý¾v™íFqp£FC²êNº–3ìBKŸQé£4Ó]®“#6¤Ó‹‡ý#.ËÌg8¨¼±†bCÖ°¡ :ëŒÃPó¨êÎÉ&&42i•´PËZÇ0Û#%G{ª" M18=ɉÝGÜ`‡+hƒ}ñ¡È*M bð]þáñOC×ÝXd’I"BMçQýQ¹“‘ì<ÏÖônå¦F^Ϻú¹!}zæ±Ë`™ÉûdšWß#"‡ %54I7L0µš…°3'øþ|ˆ@å¹ÉY¶çA#6?KämɃ:Ž’®MœÓûlp(¡©ÐÌ“Ò¸×V¹ "ÄëˆÔ§VlÃ@,×j°nÅF•@ˆ$+û™RMŠ6SHDÀ˜B0 D¢¥Ø#P³N5X©Õ4O4D1öÍ—á=ü'§1ÀÁ5š5Ò¤”{Û:ðeQÃýi`êñ×K”ã;4Ï×ú´1$ÐÑеÊc£çF^Ó#Ž¼ô=¥ØΤú¡©“§A>iéTSíMZʸk2Pù|Tà€‘¨ðÛ‡’„‰Â5ˆ¶PajJL–i˜¶¦¶–¤ØÖŒŒe5ù¥tA&‰•2ÒÏØjܶ¦e©²-,Í`•³LKlÛl­6³Lµ™m–$µ‹J"©µ3f«4M5M±UQli$’1H³$#.GäiGåL"±£æÙ8î¸l–Ɖš¸Èéáü)D M´VµÔåV¢ÚÅ®¦µ®kvo^aQƒoѴצÕû»ËA'"vC¿¯†€œ#%#%ÛFÈD*TK[›R]Kí´·µUøˆm~B ²#ùKÐ=Q_fÚÈH†EQ ÆGúZ#>Õ†–aõ­óØø„á¼ådzApQÙ¸»h¥âB9¨!áOGŠk§!€' %JŠ¾ØÞ!¡ìNHlá`G´>ÒB ‰zAm¨#%û¢Ü‚%íKtŠD©ìByìçx‹Æqä;ÏÓ×8ÏW·ÑëU8;€¡¤g‘ê&L‘x‹Ñ;ˆQÄ7V«ZÖ‹œKš“è6˜x#6ÅéØ¡›¼ƒ¸€p[1v›*®š@âƒ7̨‡·Ý£Bò8#. Ò\Ð;Ÿ¤:háŸÜz°žp!¬a#.DV„††‰#„mbL¿ê¯(Ó4tì!#6°I£±…Oú;N¦Ï”Rbå.¡÷Ã-+?£VF0¥VªêãìŠ~}мáö™mFÂiîAÁÆQ:ïÄ•ƒ#%>°Ñ#&’!ƒ¦-ŒcöðtL”‚‰!/Ù¯9ãvþWà¼è¥æÔö€ršÍù[ë 9+ÁS:~“r˜âúýt&ø-tœõw–¼¤¦åÆåÒñL ,˜SÝðð4Ç]«Pø¦äº‘C#6(,H„QX€ŒPí‹‚ÇéÓ9À“óx§諒#%2O‡ùæ&ѬH›€ø8Õ–Y!D1ž4P)#.h¤4–ÉÓL*vƒ#6HÛLMûþ¯ŸéIJB#.™žüX11¾"lN9anTG§d#6숒6«Æ%Œ­  `–6‰ØÄ´wc&µi︷l¼C#.@6dÏZ«Hfh…ãëU)%E`Ò‰„c JO´'ñTŠ¨â*cm¬hæF‰&(}q#%çDBŸ ;s­R; SÎTyzg?~—~¼® ­QÐu€}Þ&`†]|Ñ÷N^@ÃÕUBÅf€ÔUЪ`EZó}MI¢#ðGðGù$=è‘ŽÞ;}%¡&Zi‚Á]ä4¸¸fÇfÙ«EC–n¢ÉBvP§`¾Cqh—„Š\5&+&ÉWsLŠjFà|Ûùfwâ{àrTPœÙ#6`R#.Õ!æÊ%•‰r)(#6a<,<Ï[Þ‰Kž:MåÊd¤.óÏ!Y;0•UQT»¸Y“™¡õñ²‹"‡½®$D0øBR0Š!ÔÜD½.Øbo’ìÀ#Š]œÌš T`Áѱ†É"žˆ.)¢†èÉd­rf5Âó"^¬ ž¿îi‰hˆžòœŠÝÝ%|Á#6‡ÓeOuB¥´àÈ©PÚW.T²¹[#.½i?†îÍL#%Ez¤#6©36¶~ôâüÞ*Ž”(›Âý4Ƕ¿Í»CVnÙ=è¾»VâHfmÚ¨·aYeÖ” je 5VWE·[Ñ$F¥”¤ŽÂB°ƒNÄy3ó, /¼ŒXŸ¼™½p †8¬§gdpŒ¨:©´>j"ìO=H£EëeäÎh ïË‹“§ÊgؤHÞ’–%?^uÝF§·ÙéV§mTS±ÄºÕ+nj„ÜBðôÕ#6´×9Íâ„BröÓ,à¾81rÂsÚU:âæìbúékÿgÖË:¼µÜ‹|ÖƲ:Š#6K%$—,è`˜#%*¨#%A DP€ÐÈŠÒ¥h€#ͨ¨I n1€l+p<;ŠTÈ)í ˜©Ù¿Ó:þ°UyónêïæÔe³#6ÔeëÇ·VÜÞQöº1ÈßÌÕ×ë2Q#%dd!C‹ÇBŽbuðE!¤G³v#6Ð($«U‰`ѽ­„ÀsƒqKòƒÙï Ñ£šÄv\5Ê ÎÐHÒž%A#%‚‰Î|É:LòOB§¯ÆSÌ‚N¦#64 / LdM´¼íÍr¼ó¦ëÏ5wŽÚëm¦ÖJ­I¶ÒËÇ’›BHTˆƒ*‰F2ÀD#6 üÿ_¸÷J(-ƒ!þÚnêÖwÁrPl ´ W1¢Šª`Gñúnî¿«Âb£ Œb´Fϸ•­:Ä6Ö4kR&'Ó&{‹_¿´)·w¶õÚV7t\-2á˜Ö5bB<* ˆ\K‰lH2Ym@¡&©€ª"Ó-PÒËf{½•nçˆØé¦{ÚG.®ÊÅz¢ç±¦&#.œ¼zPšÕ1`W¨¬PÙ²‡2¸ÛO!-Ý0éà›È”fÙF¢D$ #fKÀ0‡#.`—ömZhmmèØ•áͳŒX"bͲ9Pí( ¼X†m–ÌG0Õ.à£MË쀿˜â§iÅLüI!1²Éb;EP DüÀSqS¿•c²vwñÄä'Ñ祥ÎUñ<þÞzªßòNu ؈›'úû¤ÓIŒáÂfÊbWGq'NÄöP”!×#%ÄI¾åmøÛ^ef’Êd­‰–’ÒjØÕ)­}ʾÖÚL®»U?OÇ—ŒkÆÛ•Êæ°µ0}½ÃÞ^“xÇëaÎ6<îXJ.mèÚ¦Òv¨"«Om¬Õ¨}Pr)N=\w†žü²Ëˆ«Ÿ(ײ|J+±±òT-ªä`Uí èvÙïIðƒ{¨óÎ!WžâÛoUx$˜§áUýÇêYÐYy¾áa©<–·ØÍn6˜I6=Î q.ê`˜Â÷ývÇ]tú¦øo¹ƒ +œM`sZõQ4$n@âtÂpÅ&/m…ÇãîHF1מwë߸Æ,bÅè¬ÞBðì&Ù3‘°kŒÕ&˜†72^A#% •·4ß¹çLÌÑL´K3Jj í>E/Œ»ÛêÛçÌÚA!~ï,v7ÞÛ¯é#sµzø%ªì2t‹·‘ƶ€BʵŽ -úð*¨ð ¹FÇò,¬ðç" sž^ÓÅC^´GÌñUGÝ‚!p6m=ßmÃÝŒ#6NÓ0¨^b!”d%]±‚-Ê.ÛJZÊ0O ¾^!‰¡ÖÂ0ןbí‹-s¦µy䃉Õe‹´SZ·°òüX›K¾fsMÖï%ç8Tb»üè\²?}{Þ>%ËÂça‹8ð‰øqgêd;1Cð™ )æÁ… €ªT'çd%íBnpŸêá·>Ž¡˜¼»f>¥ó‰èÄyKp#ÃææG³´ÕsmGyç…cQ®»·¦Ûš%¶Ì\U#.¡$‰HH0‘Q·™KAŠCo·UïУç»Rˆƒ*·µsà$.?çû‹õà¶Kª bÓ\µ…‚ň„aÇY2J2ÄTX’ (·VyÛ¹ÖîuÞªZÛ¦Û#.1A¼A(ˆ‰ð ¬ ^3@¤dâÑnÀÕÁ£ò—ðt£àyžˆ“Åù¿r=‚÷‹·EI&þŸö01ü›„$Õ¥³º[›Ðö"û·'Ã4Š|·låËMÓGÎòçQÝOg”C_˜ù´4èÓwA0Cf±eÂEÃpÑIå¨GGè ö’à$ëªU˜èt§ÝÅÈòZ­ˆ¿0óhäk>1"°Õ—,”W%ëFþä;ùq56z{þÎ@ @qôÙ(”yCScpô_{J!0£:tª4‘“™QZ$†¸ê×\×v庺ͩ¦¬¦ÛNݵu&ÄÚÛ4¶«ªØÑ\¦^.^]ÚVòµ¾l²„@ Å#%C@US_B„Ä«ËÚ”­5ê)ALjºr·S9¬¹† 5öTX“lzï€ÀÊM‡†u>#.3ïk¤ÁÖøûí#ÂÈÉ j÷â ¿«G„í#. Ã0¾Ãn”º·JYUiKí€:ÍËažÛp¶¦þZ2nÇË׬-å®Wߢæ #%ß`+Âގɬí'm'­·õ#.|¹_úuØÑTF#6Ì5å*oµµX~ÍóÂ\èÄgi[á4Gëk®“]ä9*éitQ™0#6ñ'êwÉúgúÿ§îoÛ`§ñ!(RÄæY} _’bû.“»áÁ5Å(,D‡ÙéPºRð¹ßSX§%DAÀµ¶&Œ‚¤?3Y{ÀZ$*Áöm™˜k_ªèzÔ.¹#mäÐl¨AAì[œv,€aÈ$ºvÀ¥‚+ã'C‡-®H4(an~#.ÐÅ¡´ÁëX> 7¼Pˆ“Å£Ÿ›ã“Fs¼ðE’Ó£pè&¦‘—K¨€ü~iÿKn<£ª{6±€g™TSE_çõð¾ÌÏžRI'EÔ,Ìï‰#.™–ümQºC^[ò†#6Èì<¶’èÝPi¥ÀûqL…ñ =Lo³#%{BhÙë Ò¬Ü¿¶lÁs-†…¯¢jgÎ0‰‡€xAËÓ¥¶ßgLeXd¬b‘…û`Y)0(ÏQ3‡I!…áô®ÔùašÃŒý¡ø̽™:ТIÅÔeÁÙ)ýÕ‚Ô<=±®’áÐÁá†c),·[I _òÀ3r^”B8iý5³V-êWBÆCGµ÷cHgM‰ardæ7ÝÍO1U;žæf,Ý1!„Èk q.‚ìaì£P0ëO¯võѤÈg õá§NJ±ÐèO5Ĩw¿€y ‡ˆr²þÊçõm|µåê#%ĨƒÂ#%p+ÓUC'‘ÕG Ìñä¦j&¨ª™ßË– ¡!ÞÀ[©#%¦B‡½‘OE«¨¶Ö+Q´Z5mdÆ©5£Y,mb¶ @¢²*TEMŒ2…Èì5W‡Ùn—¹\ê4—"Ô–* AR‡æÀá¹Uz,.ã`!i ÅòìÚp:6ßvýøg7nYÁÞúËÝ;«Üd(]Š)5«=:™šC÷«‚Œ7ã„-\õûn}ªcâÀuÓWCÈ2ùmFm’ CEli î°2d–S ~Õê(‡åíOyÖ!¤ØwF¿?´"„Œ5jùíÌ<ÁCi²”R‘ÚPl.@ä#6ê%ºéçÓ5„ÊU¨ü=¹Ñ®%O™×?#6\¢p`v㋜NJɆ@;$™Ðs]‹_2B‘ªPôÐöVâ¢ßÌ0`Cm¶¬×7¶Ú9FD‡·7|Y´&©ªVÍ,[þ}¯]tÁ(L:’"W. {Ž§¶@,ϬGüÛo­ÖÍ ½”(TÐJÀÕs’ª¤ ó £äI/#6½y³ªîfx²&qK¨*.‘qß<¡ˆ¥¥LÒ®%–Å#6eq}Kw4(#ÔæH€ Ÿò*EZ#66°Ö‰Ÿ-5¸éW¾`[É@DêƒFq#.በ†ÌªMZ¡Pwgåõ{ö²Ÿ7>Gcúìcšò0Ä5™µÕÔâ»×võo1“kpÄ&Á|ÙôO«Y…ñ–¦ãQè‡î>Ž#.zÞ“®ùŇ'èkj—©a¨‰„²ÐÈTʥȔläÏ$Í íB…mÊ=·e×àšY bø¿]ع`±#%˜ ª£‹.êLãžÅÓ?ɧtÐnòu#%žNÐê„Ø€L8»1²üÁð¢zÏpÝ#.ž½…Ôêôn•‘êÌÇʪKq·t/Bª+5Ö˜kYfŒ…2ÉUBÆÐÀù¾Cˆ®YIô ÙMIÀǵÜ„$“Á¨˜Ø:¤Â*š›ËuÖηL«w]¥#jff±PÑh×]uôÕ<®óõ§½æèQfðÀÆÀnBhT¬ci0xÈ`hpTZÔJÄ0`Ä28Ü«hãÕJ!ÁÑ­S£‘ ÉLkLD²üaÐ6™Þ(Ú߃pHìÃWÖ™û%°Dûo!H¤HI¬j¬¦ºUÍôMÌ‹6J´¥\é23Í×Y2¤ …r»ˆàd­¨Å ¢‹Š#6&†Û¤ 3PE Ðî÷ZH ¨ÌÝZ@Œë ²Ä0ÂíV›52‘ ¥l¥f†Sµ$‘e6›,Û3$ÈÛe-/]Û˵riÝË›rAfë®[sNݽåÍy¼ï"h¡RÔ3–ùýw³Ù› šf¡å輸÷íï¼öÕæ"¢FJ°ë¦2†–šÙˆ¬ˆËAÁ\µh@Ò4EÙcÄôõf1ºÔ6î“#.j*Ócq¡¨ÑÈ0À×ÙUkH°[yÐ÷´IòãÁ¤óßQÆM¦Òp&äbÓ\3 PÍÖ†úÀ4Õ½1ΙóEåêÞnÕŠ ­zÚéEF¾ÊËIµð[¤ö#6ûµ>ÖùñkÑ6wć– äÁí0Ϻ¼è¨…Ì]hʈ°Ÿ,Ó`ûO]Œ‰ÿ3]¸™·7µLÌf7?,lc]Ì“MBbAŒ1H¬µ4Ýi†d8w&ßNÓ)Ä”v»Æ#.Áàu?²æñçãµì! 5éá1°<¦ˆt2b²tÙðVþ²ðæ8ÀU;¬"Ç‘¶C’}åtÈŽÏë“|w½µ^]™3aÌ8fùã—=ù6´ì§Í„%µ ~¹åšÑ¶»zÊW\=ÙXÛÔZh¸Ïa†°Ó(±Æ™må÷<H°UýÒvЬbE“È#6NÁÛ±=ôL~+"‡õ†È„eÛ)·‚È~ÏðV<0T‡&*ž“2ÊuJÚ©X¡à†÷BxQGš`…×Øhœ Ÿ-“T–­ŠÑªKo•/©ZºˆB2$"cü„\¯IÛ\â£rh¶·’{:²Ulm¨Ú¹Uˆ#Ÿ”U#%Ÿiy?Ò3vµÇ‡$eù»#%ˆb Zü¬ßàTy„/o\½Õ.@Úº[%´×]§·-lfmBÑl@Eá1Á¢#DBùRÈ8$j©À\0z¦Fü¡€¸ á[oZµ¾‚[[fIŒl•m\ÓX¾>Ù*¼î«ˆžË¼UÚDFÒæ»É×>µž¹éw“W–Ù’€“€œãKÁhã*7j*”™A#6´¶³V¥(1Ä*ÛAÍXU¬!R#. aS#6$D•Q#6#6ŠÆ,ÊŽXI˜…vU‡ï€DdЄÂ%¢¤€äÄã0õ‡ázâhÌ RƒLcAA‡¬–T#.9?³¿Ïïç*®·€(øhyÒ]aöàŸsÖÐa`ªsêpÄ%X¬gÕ™3nš#.Ç#.³ÈÂêH9F1˜ÖKQ·nžíùîÑ™ÛÌ mµ¶¾©kU­~[Â` #.Ä;@¸ˆâ@HŠnüÝ¡ã¦Qð!¼*‰ï'æ£[£Cõmþè¡/C ;¡ø&©“òƽq‡j¯ù#%AD^G9ŸÐÀÓz*‘J#.Š¬¤,XcÍ#6ŽÇ+Ìf¡„zœ#%fθåC8>yóvoÖ¢ŽJ¹ÛïFØØé”8ꦈbCDÐ#%ÅEœ7áÃGÐ*‰¨á%ÎÞÇ ¢tºÄ÷Å4Èn#6½¡1*ÃM63âqMí€!œý!ȵ¥ð¨W¬|TaøµX#»# hLCZ¢«xbi(6³‚Š±tŠ\°èYl…ˆEX#%$™—p‰4b9&K“`È°y~5D¼_¼ #%¡ôˆ^3Äê;HÓ× XïYU[ï"zGEM“pùC›Ý‘¶Íêц|J§NqÂIß.k6#.éï?XC߶ óð&‚©UMÛWJ(Õ]Ûeº»±š¿ºÄB¬€%Ÿò\;é(B¢ÔÈîLgÇõÙüÞ­ôÛWÎôNÝWu\v¶Âegd!Q‹ò –Bt?g> YA h7vgyÝ\º2嫆”uÝâòœÜËÍÅfË"i$l&Ê–£ÆÛ´Û&‹S60xÜMæÜ®UÍÜw^vo.Üu×l£ •ÝÛ¤W/ñäª9¦Ëy<Ëurîk2Ƈnój•hÈó¶Úæå®›VKhÔ¥ŠÎ·)³,›'ŠÝÝݧ5wft×$RÑœáÊ»eγQhÑÊÔX¥"µDh‚´m› ¹¸#6XTbzà„vA؉CH#%ömõoÊ´;TÄ< 8#%îGû;ƒ¾Š #P„ ¡A;X‰alExýª*ŠoN™¨xþÉÂ{S´pAÀúJA¸!áE ±#%ã›êwŒ'¬+Ó}†Ïu¯‰¥hÂ%öz3…#6ËïÜŸ›´æm:Ïr#%r"1Œ’ ”ÌÒùíêæÛVükZæ+kº¬ÿ¤¹gú£ #6Æ#%™Îžî6S!5²jÅjÐ¥¡–·½5{Ì|‹1À P÷€A!µ%AbÄB’VçjœuÝÔ²±c#.ݵêZðc^úªli¤#. ÷„5w!,8‘*àN߉D l&’PƒtI¨ÅiéÓ&Iš#.ˆ½Ö­|ý·\­{úµ¯UÑæÝÛ½(ÒDH"^‚b#6#.)k‹`‰E•Tb¤"M(0'ñn\ÄÈ)OŠŠVuç#6'÷ð=•øØ 1†„HA„cŠQ Aû†j=•€Ôáa­3‹¼D#%;" T€ÒÍ–ÖiµJ¢¶•fËMô¡ˆ!·/¤¸Ž‡Y@sÑV2#Í©ZdÍQ¶Ú…­DüÏ&1‰½#.@ §Ë†HH"Zf0šÚÿmFkB¦km…ˆ7€ÉLÍv¦vÓÆk‹±_T,£T ÂÊ$6#%þDûOPp%*¼CrW¿ªúÖó6óô÷}w~›¢|—ïd`ŸB2¿˜¦gËñꟙ´Cå#%a‚aÌHôÿ¹Xˆ4)RkU‘»M¶ ÈfÈOÆÑv`iñÎŒlD‘HI'2's¤Ñ’õ¡²yˆ?Àáýb€@cÈoSÑ5·câX¢^ü-ëpqû˜ZÇ#%‰ÄÄ#.IÇY%¢ˆiQ8ð$MÊ$4ªB£ŠQ!.pK#.dÔþÕâòºmsWI*å^ï&Å­Ä*6VjBTBW@#6Ö#.c0LK½àŒ1†åËBá-$‹ok#%´Â "JM!hKEÌ©#~NÍŠªð»/8Áo:¶f¾$öû^à쪰pÐÖ„ 331(Ä`m¥ÁØx]âO,’½).àdË0L\Ò² u"Áb…0«‹ÔÁh BX’T°€²+"¢7*© H4uÍ’it52LòêUÖRnݸ6 hüt#ùÓw2¢H×`ôÂò*ù{Ntp~m£fE…DAÙ‰`=aPP¬&i»PE±*Ð#6E#KT-ѺZÆž^Šv0ù lûa£ï€ƒÄ‘Œ$µb ÉS¯t·\ªvݪ–Ê­š[§.ê¾»mµõR¶¿’¶×ºØ+ìŠf‘MÄ”± f#.‘¨-RHE9À³­‰ŠÐÂѹÑxOd#.Ášyþg2Å>?åDÚñç—ì[Ýa3FÖAÊR±1m6¥ÒqŸÏ#.¾r¯©†×PäqŸPì†4`!‘ÄF˜ÁDm6›¬‰¶òÉ’c‚„$‘¦ÖcÁ¨ñ©˜ÛvHEJèGŒ+ú2LÌRØ&Ç.-S9;7¶£´3P–—´¹”-2µ‹–š}¦Ó’òxPëצè!àDûšOË[ˆm4;CìAÓA?{@~¨ìFêøʈ;gèª#. #°êÞ#6&àÍdT#%¤‚‚O]#.0UXû%H€ð+Qè¨÷#6'dÑg"æ”Ø;¾#%âßh§#%–6‡ÕáüÓ†#.š¶ö!þ]ßzLÉ¿¿¯¥$уHX*fO‚'Æ"°›[>PAÍ#%GÉQMAû={”}ᧃvY¬¯ÑõÖ)Ñu©A_°d FÛϲ½¿†Šc[Ü%•—oEÓ,y† ÷¢ˆJ2&óo†tÜÖ‚;¤¼6^o´uç‚A›(77ü“)– µ¶÷Y…ÄLx‹l+Ûš¨SÃù5ä4wòò$;8SV›âT:—<­‘t(ñH˜Èª†',ð³™RÚ€ÒâRgpo¤ˆŒÂÉ2"ZBÇË0/‚x†ã~æŸÇTCîûÖþIõ‚h&"´#6bƒéC;¾¯3Ž¯«ÚÉÖÙ’>úWš‰ûc~Ó ÊqÖ'lcØÆöœ·0´U>’L#»²8US›3H—¸¨wâ® B?‹ï‡kzþˆú&)¸E–m[p•´!oqÎJЗYÅ{™ÙL7£L€ÁA€Œ¸¦ÓŽ V0>²BG.­#ÄDDJª® )æŒM+I’¦Ík¥¦=i4b¦—sìž ‹'4ƒ³>é}2ksá²HÎó|DaXéw‡kÎú}e°&f´R‹˜ƒÚyiÚΔóKÛù=iæÙ° y/âu+‰`Çxö$ÝÀû0}]‚ÐJ3ñdáË-^Ýø϶Û9@Ѽ#.3]7üºÊê@óÀ¶ñXTÕ˜¬Fôõ{¹Œë²›Q…2fqLd–¦ñ!»o³!‡ ÄtÞ8<µ†çÂôÈ6c8Cg¥B~óQMãøÙKºŒËù®ÇC‰mª¹"9n¨¢ H´ÃÞ²âôž“s#.Anã"Ý3-½GCÔtä.9#¿å¼:öŸ´Ô>‰ÄÇpwÇÉÄP +m&™#%f¶FÖ´ÑÛd92hÅŸ$ÑEy#6,:@ä¡í’(:xÔw‡u#6Š©6Ï쯟T®Î®£Æ>ÞHˆ{:¨óÚrz¨öY5zº¹[­(úù³¨å•gõ 8Àu¢ÚO…±Ú¨¦ ¢0ôV#% FB$š‡¯°Þå÷Vgl6éÎ×Ó©ñCqš×ÐEúW9³‘v@ÓѨa´Nø¥7 ì⇲ñvVù¦…é ì€?ÔTÆ'»Ÿe¿Ü»Ù;}`£9úì=§„¦ò•…A+©/þnw‹®B’v>û¶çU;QUΆ¤”RtÐ:`#A‹'BÑ1Œ«¾ùa+Ð1 MpAH!ŸþO«mmCPç¢6îÐ*Á#ñÈr=ñ?£?ùûKÑTHØ?ÚáUŠ¦7ÊIÈ—Û—X”ÇrxiÞ7•ÎåÆš˜:tà€^³Í£Á!žKòó©,8AüÏzßóÄw(I ìäh·ÑQúöùw,ù.™1øµZw®íb!&t4!Ç.ü–ú2EŽ”)OkR¶Ä4³¬?eBF1³öeÑ$í8xnÕnùx-ˆPúÉŒé^û,ÇãXFKP­Í<œÇ+•wOÞ×j¤Ñ¬E¶Ëf³MRÍbZRµMR(gfí–sʵ$‘Èu.kOU;ÏïHÝEUõÔ«@È¥~Ïíýש?£ú~dm”eI£0h šm‰¨ŠLBLh”b#M*FJ&…!&Í“a#6ˆ±Šü$åÅögŒxɳ'€«:û“7Ü›o'6úÝyŸ”R’M›vÌ ÜÆ0Øh4MÌÝ4¢¤aKæÞ7t¶zh%*éMð·åÆ^&y}Gå1ÑÔ¦׃M6`¥·m—8™@¨…{*E#R«5sQƒí‹“øø˜ÞŽ¨Ã&D ¡+fCÐÄÆÛxÎ&cz\/Ó†À[]4šªœ„>n¨¤ôÜŸh#.ØL“ ïÖ9obkMNËÒuÕ.Âjõ!2̺ju^ëØÖ8ì3ŸÛë¨fèÎ[ŽG —ç_¸3ýO8†ž°Õ Úm𦶰9ãT’/è„ ™á­ž3°ûç™#6ƒRi¾m#%F÷"¢Ö[©Œ”¥m¦œiG#%0NPÈ©-D‚„#61u2H€âˆë—QUË;®JnVÝ®ésuu®ÈïkÎòYšÛ‰×·‰7®«— +lÆ4›hÆ@î’1ˆAš *ˆ‚•º%*»@Â’Žë&M’æ˘ª#%¦_å¬2H¢ÈAB,$Ö™WŠ¸rérÎësk$¢3—*çFד2 ËLEø:UÊA-H¡K29ÇXar„—ŽR×eFÉ‘?6¢teÌeÄÑs4Ñø©…~÷ð/c…ž ò—hâÓX!˜Ë#6Tr!žS“Ñ©/Þ:ãk‚Ãz)\Q„Ñ!TÁ`U«Š¢7*â͈Òll«/c\(­›Ž!¡6BÒˆ’¼«³5A”«¥¨Šž;Í·rÊ.»xÖúÇ®î×uQ”õíQ°i…¢I¥Âħ%4Ъ!h¨&MŽ9Q%Œ²ÛSM©·LÆüR˜ÕDôÑF¿œ•Y—Ú>REB#%!‰ŒT£AÜ‘Båµé{T}µ*Àì=UíŒ&„æë§ÎÎ00Ò °W!P‹'Û:D¯µg<¼ÕF r†™„O#.4P÷¨ì¬p£þÛ2FÄÙÝÛn®®›[{k®”;¸[ºU0Ir… Y…ƒvÊk^(¦µR˜¡LdÁ’ RËuB¦æ»³qP Ù(f3Т#‰omB‹7û¾¥°·°ø\¼ÌÚÒ㌊L6-Öýš"ò»-ëÛ¹Vçt$YÐI€ÛâóÝkXäœ$Y¬Ùæj±ˆtª/œvA»ˆ>#.¬—½HíÓÒ1ø¶GÛ«ÃD¯P‚VÑõ(þ¯àˆ© N½¤€L¯ÈÏa‚“‰‰r×(‰œ$ìÝÉÐ’³àw ïRb4w‡^×»C¾/…ìX,^¨bK”\«Ù½-!®ÓlßMvª|ºõö!üȦ7@Ï_]ßÌØuåÜ(7Ñúþ©ØÁ#%Ë·I#ú;}+¾?}œ­n‡*œ>—Û±ÏÒ[ì×{oѤvÒBÅÛ ³É~¹¼È?ÈùŒc(šñG‘© ÔU#6„+¿æ‚d礇¼ì½¦ÐðÉßz†R‰Ê'j[br¬#.v#%ôηUŠšûʸT71wV­fºËmŽEßÒX J§^v×# ï EC°yƱ,• ìA2±A„ETù°’á™òNÊR¨QeTÎÞ‰rá˜\ö9Ú5‘jªË#.&t0ßá‰cZb8z¤0À—mE„þf³ÈßçHœŽ°Mq4› ¤Š9 #.þš ÃUHr¢’\ªévÜV^ßÈò¼QkÚr¶Kh·²ÖìKrîêÛôK\6¼UÆŽnVéµ·MY#.cnm&Úæ²k—-µÍÞír,m“j Qª+—‹;«î-Ã#.âw²Ë»$çžv÷07Šü<¢ŒÍ}Zk¾˜•˜zÓo´=H^Êî"Øκ’!7@A"ä#6´Þ”=¯íÂäD ´‘ƒ»¿vú®_†o™ªƒ‹¾ªýQy>ð)Gä#6çøÑá"É4ÖÂ=$±òSè2w@d#%“ Gßè—q¢1¤(š‰IBHå%ŠJ*¨Nîòá^T#6Z\# x Ù b¡†*©""(¤›[u­#.mt›¦µø~{oF®Ü¨Rd%ÛÝäT]Ñ *½Q@–Q¤ÖHѶÛ%[¿™~k÷!D,#6 éB?õ@Ô#%šÿ$CÏ¥'¾ûHjÆMöFÒ¶FñÇÙ{ZPuðP甼P#%;²f_Œî@O÷A$‘;ý&Ô¬›¡Ôu`¯ª¤ª£Ù¨3`Ð: H#"&Q)òT(uqe-LÍ’IJ1idŒ´i66hmIEbÆÊRRJdÚ4)µ´Eª*ØÖÔkjZV™jZ52¥bÖ‹ci5³[ϺÏn·$cu¬È²#.Ç"6W"Dûne6˜ÛaPÊAÇ$r®tëÓ£Ò®Ï=tªò®<ìiq¨ò¤©¥’D£O c!&$Ü*+hlŒc ¬H˜É-a"#6@£`èÁi†“#.‰H… 4ECJ¤P*( B*Zë0$(¾B¡ Ô#6Y2?Íü5°Á#%™ô© DØ% %¦îéݘÜ:ÓõÚô·W®ìÛVÀ(@d‘‚$–f­2Óȸ@M°%Ä^û³„B3ã`ûÇNÙ"vÔôôm÷wc¾²³Ù”„…QRN {ABH,O½¸VÆÈŒÜÐö5OÈ¡äØf2vp®§W_—[—,1Z%ê/-l@Ò¨ˆŠ±±Ü¨Mâ xFß—¤jœ¯§1p‰V!TÌH!PáJu”0UR8Gõa£ÜœµõN¦’„µFénãɼ•ÖòË©R™”/Ú]êµsQµ±hÕZŽê®Á¥±ìóp–9‡ávº?®HEÊoz¤ÑïpÛ2#6e_ìÓjÎ`»8C®+dßX{Ap–Â!ê>ÿï(ü±YD©Ë³eJ[LTz÷F"Ë`ç`΃՚‚RúÕ ÿ™ùiÏJ—Šê%áMY¢ªS|š²|‰š®#6‘u¡‘àÖ½usFpÙ"}rC¼"Él³Êª<ÂoבøÏM™Ïr§ý–æØè„#Æ X}¨vµºt¡;?;#'•ËRùi@Ü¡ÍM¸Ôã|]?ÙÒί^¡ÔB}¨#.#%ù`ø€¨ÖîAå—Íã°Ï/Ñžÿ|hÒl\1º**;­»3Ú*¥â‘TþÈñÅ4¢ØìçÓ~ö3aƒ¦)¸÷GZ³*¥›z—ÁÑÇUƶÜ` ÂpÞ]ÎÚ£]u\Ê­Jã‰Q¢ë‡òUÓ3÷˜‘ðÁÆ&Òe¥”ÌI#‰ÆåÛJ{ií'[lüÇ¿Üo5ÕÛÄîÙ¥º'Q#%ä3!O¨"e¨BG½V×ÒH#´'53×ÕîZ×#.ÃP„˜ñçRn tÈCñžxm÷¦‰¾Ù¶Uúûïy/‘ãV°A„<(}ZÒÙ81K²‰$=·E4œ¢Bl‚:E’æÊSlµÉÆW_û­×¹/#.ÑÛ‡QuÔîí®:väì³G¸\§”µí{KXî{îV¾¬#%¤LÒ#6Bk¬¨7â¶(/%ÀèÞà÷Ô¦Çb-¬Ä¢õÂÕÄÀÂFÅÆixå$Z³™F®;ûó–©vÂqÙÔ!Äg ÷7tVBZÇS¼•/ yÀo#ß«½Þ%™&‡s©X½*77/²cMž±Ár˜øW^3Ý$"“Q?:yÛ„6"£ŠéÅƺ–{åøÉÐ#.ôŠ¡¡”ÌVË~ügƒÉg‰smm9)¸®jWMöÓÃm‹f±“ 虘·â®8kÃÓ[é‘þ]»±6årXöN”VRTâÌYÍZª¥;¢øùžgrª³s BÄyo…,pѾa& q<£“jf)‰ÐÙnÆÛ›ÐÓE¥Å—•›f5Šw©± ŠÑÄâV\º)2›Æƒl`œqÑáDë¾x¶ŒÅf^–a›TûåkĆŠWnëh6“³mØ—[ÑÆçhNI/$“ËÆfš7Ž)¤ÖŸô•öÍGŒb$C¥×ÃŒêC–C:ÚÒsŠ/}Ñw§Ê€ò¶DÉJŒnÛTóQíjP÷xÍ÷‡“bëZ:>춖Êü¹Ÿ9õÌW_J×°¦ŠéyƒiÄÆx’»uƒw}²™×:üç´ç”¼Žî'÷u{õõŒa*Ž½^W‹W0ïoèÌÐâò¹˜ô³8ÎÜVx˜«­¶®œ§|ʼntªCVo…Ž†#6åUvga*Fñêòª‹­éïlg¢/Ç=˜’Ã5ÅéüÔÂln÷.úþöb¢NΠlr²¶AÅ׬ÆРo#.°†(ÐÈ#×LC÷ªó#%€@:ó š#6`FãaÀP™˜‡a»ô:£L6 ñÕýxõ»Æ`vŒž¥›¤•`qG=æ26ð•9è•ÖkSAC«#%6ª„sÊ^æz±¿v‰•‘ Z3Kˆ—3.ªÞ&˘sxÃ\ã#6?#6«_Dd\¨¡PʸG`{»u½§D¯OÆ.þîO'6÷ûÞ [ž‡“°ìkÅÖÈ,½ÓÀý* “„GÄÂg ¾T©œ"VsïÎ ´##ËlºNÁƹÓkFÒéaùC·”úÏòghæz¢:§ç™ŽŠ–”žç—>ýcšŠETÚQSSNFüb((±SöÛœM—Ä e²Ú{Að]‘Ák]zVÔ4o““Œ{#.”Uû»ð*#%Å9ÇGÖ“ôÚÏ6(¯Û#.oÏ϶;3\4‘Š¡³G>FÎD(Öѽò‹çÇÑp²9–žfª7 ­Zæ0ÙºÞÝCë¡ã’šÖ‹NÚ21D‘ª!ƒŸ.e-lZ'ÚUbÕõQÃØ¡™ç~%‰@½vÝiVkQ-29¾ysæ83DñÅì^[)X×ÕÚÉš" Dv:e£;F#6Ç~›•Ù¸°ëíÓÓwÃŒãWoÕqÜÌ‹²¿';¢Cs:ö#.a º:ë¶Y¹Tû›èœ ¯[–ãÔÇ4v4n s©»x÷ÑÏ;èÝ 2÷~öç‰sw~/´j¦<“£\W‰t·Œåóm‚åG‘^5&ŽÉoä wªŸ7 AÍÄ%å#¾Þ0Må8pqäñ<³~7SÛ»å߃Ló‘Î¥mZ¡\dõQ†Ð{x09hRÄ¥ˆµ¥«#%}¥ë„ô—‰”D4·–bÍ…èŒ3¨ç’š®E’=¸¼ó‡ ;Hœðà>.Ãx[CUZØ=íô7,Èh¨·tz=<7~†O›œ í†fBñEo7ê9q À°ï‹ˆLBõ«•³üñ6°§«Y܉±Y…„;W¸Žœ –Îå›\¹Þq.ï6… )sf\=®Ë#ÕƒV4(êvµÐ<³Ê@Ç”,,¸Œg ¢(Ôy zw-•HÕ]B¡¡¯E´öq3¤:f,öÒ­'!Ñð ì@â†1HóFÔó vM\;€© É3@Úõì.Úg$$VtIm-äSLÛ0w0ÈÁ'‰#%ÕY"aÃßôèU×]õûC#.˜`fá˜+u¸mæò?‰N®°Cw"³0ñ²)qO‘n"xXŽ ‚í¸NÛ&Äy~‘å(ä·°ÇèpÅ`\r ‡Pž <ß‚ð(;ïÍVßáL{U#.>¿ãxKf °ÂwÀõüƒå'™y;`kàýpÃhST«CÙç2°gÏ¥_V«GªG±8v'$ODMáÀÖN}®;O‘[Tb,ŠÈÃäÒ¡E€~ ¯Á°e…D–aì»Ímlš…s˜Ô¸ª’“#I#6±Kº’Ì0ªm&@•<Æ…(Ó`YF91!²²"¨DÈ¢–‚“EXB!$JÆÕ½+F·5¨­nZÊèZ©”‹"(ØÁci¬¢ÅFPTÒŠˆ¢aQFR¥‚0ø!\Þg¬âþ&xØ…µ± Î@LñÜî#…# ¹vÐ…á¤é$c9ÍbŠž”Õé¼mãnEɱ­*µ¯¹m¶‹V®UQUUé¹UײóÇÐÜŒÍýÐçP:þ~–µÑøC5÷]cÇ-–§AKxæ*Æ1ƒK+udˆ×/¨ÒÁí¸i¶í®o Ü#.hÇHiþc£f-+°£W ¾ù¥SáîÀkN4bJ³ÄòÖ:¸`@¥,×–cÉ –(2ƒtHqbePDiòãOR;Æ]ÓxÖa%‚dH°!V“7V˜Á·Ù (š&ÓicRE,%ÝEcbi¦4C®Z*=Ê[ÌgA§Âu‹wL¤t’d½>ùlÀö›L!P9l›ª#6@Y0 šÂfœ‘L7zUàÅ3R·X›€QŽÆ6ëØËÖ¥4ÊÑÛŽv²ÍîFjh£MÔU¬zmkZ¦A¸Lk.<“µ†µcÔèç9«eo†LÑ$D”MqP\`SZ¨X³LÐ*±c‚ñcix1”2ëB‚ÕC$Î¥¯Õ¾5©Ï9;·hÓaY ÎS¼JÎ!ª#6A,ØTP”2„ÇcLhÇ»*ëµs½µPAôãn²‡U"^Ck*œêæVú†•“%+XIw­Ü&]J&0ghnÀot‚Çßh­siH“°N'a§ïšiÏ]P \‰ªR8ÙFö0TjŒ?ªãÞºÓÖ“cSˆ‚ò£œµ.¨CZF“Làèd¬q¨Ô"Ú7*ª#6”*à Ѹ”Ðá¤0m0m15+‹‹FÞn-¼™,²»zça›[ ¹tùÐC 2´CdT¨£]ž&09ÜEZÙ*å#.hFe¡›±—mÝF?Sã5@‚ŠLãRùg%¥¶È|4k ¸Ô €ˆÚhŽ¦ª~¬¶ÆŠä$¼*7Ä®é@ì€zi¤„<˜D¨°]8&è .ï®r#.V†FÚqÉ#——B–¡ZYm r˜m†2Lä­„ÊlbWfJÌæÚ¢&n\c§ˆF±V=¼§^1Q¼ÁèÞi•®›m·Xˆ9¢VßãÞŸßÞŠ= ­GÕy˜úe”}#611(÷"Ñ„Ž·e0Qsâš z±ƒXr8c™MAø¹¢@‚œ=6ñalÊSŽ!vH#.0ÕŒÏ ¶–‹€û0­\d#3ÉÜ$d9ö¥›:é¨WbTF¡£†MP1#BÌðCV#6æe´Î-ͳZ"Û­hDF ¤¨b0fµ8Ò†¸Â±¶FxØ7‘¨Ôƒ{ÔË ¦A¡6Á&'"Ë9#.+µU°ÍNß!UíÏ*ª™Û2‡s—£Û1ó•M`ÁC!0çr‡c$’Ûã½n‹ç€¿¦Ì+¾îÝiL™5–MÓõ6¯ÚÙH•$ä”´•¤$ˆz—O™®;ÅÝóèºbCóHwÀ©ÚªwUŒØÖ­À4†*SmÙüçƒ U+ {}E*ûXSÔÓ^#.“ñqº²±eÓ¦3™~sÈ+?2CÁûàÿ›Ð9¯¥Ag*Î*JAFä#.o³·Ä³Bx«ÇzQ€#È›»û<*±¿®væA§ ­öœšÁ›Kˆ?~Cóyßì¨×\Ubƒeª•Áå˜ó>\f÷={p1¼$a¦î“»¹0ˆ¿{w@y9;šbƪ¦[ƒ'º0’ÇotÜòä<×Ñ(õÈø¦k´à­µÕ÷ ¤qÁΑHû®øŽ›ü!‘¬í£Q:ǧ å@Hµð†ç© !Í’5iŠ Wj™KV——\Õ‹m]7‹hlPPH¯Ð†¬»öÐÖiä#ÔD~èì9ߥ}~•Œvý"°R(±H#%V ZÛ#61´Œ˜Æ&1¤ D©(Z¦UŠil[%¤¶¬RQ¶$¬š4(¦Ê£Í¡M5#JM’Q³JHIQÓhD¤KFHS4T¦È¥SF’a¶lÂ%(I1«X!#%øÞ:úx—ôÌÔžg´ê9šÉSÛŒº¬[Ç4UyÜÐ~ðWæòs5þW‘$$g1$8)×ÃÂÚµâW#o®å$î—VÐElO"¨>œ€#.¶ƒ˜4~‘ ¼Hga¡„’hf6ؽØLKn£’R& ¾~§Ûzk³pCõ%ßÚ(2ÆH\Àù9q]‡=½haѹS(ÂBY‰èâ°ª¦$ã…ß´ùû½šÂùïâsþŒCJ‘FÃÅqy§üÚµù¯×ÑÖÇ‹{!Ãë: ûo?“WÝjßµ¨’Û&ÑXªKXÑ÷Ö­si±©B“Q£±õÝ«™C!b”R©bXK2ïÈ0'uàEŠ$fPÉ#6>ÿ£"Ù›‹)ƒí¬÷ó.#.ƒ>+„¡Q…¡¦b0ÜürèÕcD>n.ž5ª(àÉX¦¤ŽRb"©¢˜ªŠD.éÊf’¡”+@6lxœËRXÐV,Iˆ.¾Þ1Ó{¯.íГ³šöó«ÌÑŒ¦»6ö•å&ñsD¬ÊÜ·/×–³PQÀº. a#%­ÅÝÞ!”`ŠÐ¡GLŒŠÄˆÄ½G¾ôÓIà{è5O‹†EÉŸ'& u1p6e¤J'LHQb`àËVAd¦¢ ŒbŒ¤…(Œó©#.LáGô`6  kgì›μÞ6ór1J¤NŽ2,=¤4,°pˆœ¦˜„| d<ÀÂÛ«6ìjHÚÛElmŠ#6­#%ÚÔ(ƒ"3@pBh_²*ÁUY‘U¦#6!ìßÕºLŽ@ ¦‰@¥+†Å-= #%½]­”ô¿~7c¿#´…`>ϾÈ÷÷ò3Œþ¨ž‰Cft½B$#!¿ö?‹"dê…„|êÙ¾~h%¡Ð{Ñæ#.‚’ Ÿ,(`šä塤|ÈØ”n2¦‰”­­LÓÈ3ÏÐ@„>€ã7ïØV†Æ’iy¼Â°÷ýÞ=ßµöR|ª2Zûf‹5ïðñÆUo¿[52UQJ–m¯ZÔÆÊJýKï*G;ó&¦¥„u Êqµm¢ò êg™*ñ4-o^…°n2nF-tiªD§7C5Æ6Ó&TS`Ò &Œ!*Q›±A÷Ä rê]uâ+NA–«B/¯Ô{,¢tòOئÊúÓ’rµÉF¯Aï J+«)è(° Éë;øNsê>«íó]ÊMË°#.ŠšL†|ÊÛéRæ!Á)’Bª9£^¤ÿjfÅ<Ì;¬#6Aî0xw;Þõ†HA)4g˜fzúœqŽòF­õcÏ á„ØE¡kõ|¦!»°uªMG&~逸²#%Q;úŒ¿ÜtŠ@d‰"Ȉˆ*¦#.>¸ô/}RŽâb_cóÖìT#D¥:Ζ£Ê±rÖîõý“'5>‹ç|â²âè}.šàý_Tl×=ÎÜÔ²]4X`C$0ÇVêã9'HØv'F³ñIÚj &¥g™õ@>3¹“ŽÐí€#%pàJrê`{ä7s@òq{ÊA/˜”UÒ\zge)^±²=sDþXÜÆ1×Æ£ÔŒå°nd[wof²XŒ‘²¾çg)P’6B·Þ\+ÉÚEµÜ,3âÍ„JS»uUtDÀý19Wž53ÂpTlÐÈÓ#.¤c€h‚` ñ‘0pP#.@ŸÐnªÁ`È%ÿV TU*2ìÈ/&YÛr-Þ¨»5!€PÔÊ0E#Q¤H›a¸’6P";^-ˆš@â–YÇ1Ìnì5Í—™¡#%1” ,½!‡sˆYÚŒñ¾¤flzÙ¹Ôé¥ÁciDã&‘Ho?/3²Ð½X2Ž(uÇÌ°´ÃdÝ­zYg$äÝ&Á5åD ˆEPÚ¥HŒA±è~“3#%‚ˆ Lˆ™ªÀC}ŠYf‚-"¼¤}q¥£ÌàIQ%¼†Ø^FZTz³µšHÅKÅ"@Sp¤u^<o.ÈB3@Dmï½àâ…×j”ta¦lrÞX@z‡QfkQ ‚Á¨‚À½Aƒ(Ö÷Šóò¯n7ÛžW üï¬"ù:ÈÏÓ7Ò`ÀR7{ƒ¦BdXg&ðS¨f%¤Š‰” É0ð»,í‹ýî“•¶ÜD¶uS2ºcre38ºt#%™aÁ%ç­»#6Lp²O§pß’X9 ¤à»WD¢ƒvkb”Ô+LÄ#.–܈#.»³BñC7<è‰D©#6H2#%ë¸ïšµ ‹!£!PÅ X#6ÉŠH žºÄyŽ-•_F¨é<´­ŒöÝaš•˜ñ¿n«ÍÛµ±S†o1ï[ÍœVWÁ¦e 2äptc¯,ã2®i²‹혎s¤°ð­Ž4F!ÇöR¨±AV,ñ³á‡‰$Eïæm;ÖcHo!Ó@3k9LJ_™'LÁ›YÓB¯iè1@'*kMž.³ˆÆ£6™‰6“ A»m¶ÒÁL\RE΢ŒFe¥%o˜Ý“*—,už›`Á´¾Ñ‘9¥É1260ìo)¯i#.&”÷Ã@V«¦Ä$l‚tšÊvÛck¦—r˜F)œÀKE ÙM‰,vLí.\º{Õ—[>!m´Áiå¬Þc#4Î!­äkû}av˜ÚߤœljW¸ä'7qÖ$[¬vŠÚÜßLU»ÆD<´ÑjlìïôH=fUÌœL3™aè’'£>4‹O¬ÈÐŒ!Zõ‰S5{ÓX¦¹‡—CÎ&—;±8k¦îŸ\@r¯2n&‘='I©Zã¤êBÅ FÕ—„,¹\¬*ÍV׳p™`—\ñ©HfJ•Y#%êë㚨‡"ß‘kkÌ›%ñO+vv&º?grà{Þºç(äUÐä×I¤  X¬E#65³6É›!ÅdhmÌóÀé­^]04©qs:ÙÁÇ0@ëæE}h·¨nœLeÁÃ}8 Üƒ^-1³ñ|2£Ãµ÷@¸p´V×›;"'›‚å¡„±•X%ôŒ–ºí#%í5`+IB27©t§#.NZÐÅ©º†B¸–°Aø±b+m:+¤‚BN\¯…mgY¬ñ[6L†ÎÀVælåŒa²DgÑ@iµDбP<ŽýÿB㌱§4ü lÔ?nŠMÖÎð„àM$ÕY'¯BÐòtoi´\Ûñ¥Ø+~8ᥢ]-YÃ[Ôtͤp‰?UÿÂQm—2áLØqEÍ#.q™ƒíñØåÓ<<4x¨1 (3Hr›ŽÞ<9²óëktò ¦Æ ‡r³òëz]YÒ1Íñ,ÌŠsÕ¦)³åÈFµ.ÉzˆÂ—y|²ÂÒ +d׳„ÛFó~BÀ™aud¤Ö †l”ŇÇ-Å…µ¾ù‚3XSC´=‹‰±ùq«óëth:j=iu]†Šp3B„Àtž§¯_ m}i¢2HÛ bvvÏxâ«$3@ä½Ì·gnªÕ ³ ŠP—JPÍ HÆÜq!¦YÛ%j®`Þˆ"–#I¢#P/¿=¹fgØMœÁC´;,LMµM4Yp'Ò*Úúµ˜·”ÉSìÎxÔEë¹Y¦§vM€Y@ôðSäÌŽœ™è‰åå#6ݹpf#%ÊÏÚ;tíyA&w©b¥‡OLìO#.&Âé?8L89ÞÝ“M7ã%†8Ž9Ê¡Ø-u#. ³/L]Ÿ¯\Õ¿%‚Ú.­cxŽ¨b‰4&µ!Ò`,fÄlLM‚á#6­˜‰Ó£p:5ÒHÄÄÌü¤Žd‘A¶¢„Hø0Ì‘Áö 4EqT¡ªk&§xÝÛ3ÅÖè)ïe£(Ã1YÚ`¢ÇŽ6! Ý]ÛÑ.$#.  €àT–0%DH!¹±Z¸å9Ç´ÒQ PP4 ˆwŒšÈi8,ÑHŠê%Fl!6aeÈ0à\*hÛiD5Üè8hé™–*¢P ƒK#6¦æÃ@ÀÀALCÄD‘6D“áS*¸è†wB]èÊ4,¨6"ŠwA³½ò3bà‡"¨)ØÙ˜Òi½‘ƒ†ûøU‘’« Hªå¶ÎMlEÜ 1 ˆÃØ#6š6v4#60gSP#.F†¸H¶WU%0MEó& 83ÐíÄ„3œmÂt대ÉHrºâÄ¢ œBB¢ê™• ¯3[Ò^6¼¯_#.óˆ±c%%¾²yyôŸCk£U@Ê(¨ˆ°צŽ½Èš“n‡£¤ž±°f÷ò C°5#6,"B@MbªPê ‡á¿öôl½€Èë:½u‹yÑ\ƒ²íšeX§—ëïk—°Õy+'J#.?Ö>£MÃ܇)üŽøx¨âÙàm&-£™×B¸kMµ7ⓃIf ŒsQ‡fE°Šë»ºf$‘$#6DXÍf¿šY¯§·š#%ó×W%U®ÔEüðMÑÎ^hÂò¨I#%ê¯JS°x|k0ÂJh(¨Gf‚uaÐÆzífˆ?“nôÓ'àÒ«„¨“¹*3#¼¹R'W((q#HªÕÝe’iŽè3³%<ªÙ 쪌JÅrØãz#ÈÄ6¹–7oSñkJêF9ÌTÍ@Z¿0TV(NAqKìÍËVè+ÈämÎÜa·4}o{ž«;Ù¬å¦66”˜µ²¶[[:ÁÖ®¿¢>¡DHª{hˇà}*s9e¾Dʳ:¯«d{÷ÅT°3ñD#.¶CvN]GÃL—@SÞ¡#%4„Ž©C»¶Çá^Wf“·DîΗZ²º÷áâÔRñ7p#6ªVŒˆÚX"kÕáË»[Í$2%ñ5;Îéo7v†È®òï^vÉåÒ¹Å×RÉ#6A‘Ü0@4Ћ5*ˆF ´8iQ¡øé3 iŽöGZK(4‡]-ÌUDÖ7v)<´MF¢¡ÇgVƒ#34u*ÌÙbQ „GFùèë쯷»È!ð†<ýZ÷ H|ÁpDäA#%¦Ï¡¦3ƒõ†j‘¬¼•dú.ÖÚ1<#P„$xîamˆ…ÁV†ŠÄ®ÉÉL+ÃàÀØšÁ$p ¶”(“Ÿ(7'§¨&µ9w²#6nc±ì³êžlæ!ÜúìçÙ#.:ª&Œª§­LYUå™ ùû¦ƒ÷×!ŸG´šÈ(|#%ÉÂmr,A-Ùa…NKÎMN8ÓR0;»n[5'Ã)Lª×³¨^b>%¹C3é8]6±uLDÔ`X€ B!:©O¬i悘ç³n%Ú’"öa\ÐØq¥ÑÃK×è‘£ñLôQ#.i‹1Ç¿†0Ú É 0µö~tm6V,ŒV"$ú‰¬á†sÈkÐÒŒ˜Ê¸ öò…0'º)HH2DO¢"öµ”ZÍ­iHJÔߪXDVBEGE„ìE—„0cUÆ„e5@Àm©n\0P‰`„M`¯8#%ì#%IîËÑ•…*Bé—øahš<2­½Æ¦Z\ÜìŠÈ¤°ƒ² H’€:¯ƒäßbš•X1¿ 8Íõ #6 #%HŠ’*¾ß–[·|4ÅO4oÕå}#›9†Ñth¼g#.`±Þ»Ž´Å¸3©Õñ*\žY9)h„¢‡#65½P4a£ePM£2X’l+%Ê«EE¨íD‰‘·LNA‰GUÕÂë×yåmÊ^¶²VÌÝv¬V`•%šQV@IÅN†ýWPË3:È$#.EG^2S4#%Ü¥…¤M—2,Às4µ§âPNÞ0:=G§‹Í,0!&*Ç·§ä=ÔÌÃaÂօз;sHc²iÞfÍ ŸŽtê1ëa°SàßÚ½&ñØÒ 7!,HÈ#%—5ëÃ@ä%é© ¾EsRÏr¢Íýï_kWÏ:ó¶¶*'õÍn¥‰†šHƒ[ïh4×·¢`wAu­uÚá#.,‡q89 ‰JþÏáÃ;«¯³‡3€¯ÅO8~kÔ1 Ü$9Ê%¯«y£6ŠZhI¥EG!‘+Ž]£fvßæoíÕ˜8”™`±Òùn¸¿¾¶^Óötš†Y[ÕôãBa»Ö›iAà~_X>ÈH‚&³ì‚‰ÔXb„#.4Ñ©î„5ë%ïë!rKïl}9úÓì='p>ýÉ­Ô(Ž^7/$‰ˆ¤´š’jYiŒVIJ#6«bÖa´&ÄŠ*kLmµ&ߺÑZ¸Îk¡£Y³k‡s¼ßÛ<“ÕXªå‘˜ûµ£aÞ¢þs”Ôæ: ÇÅ#.#.¾®¾Š+Ÿ˜±;öòÀMI@\Ùô‘²z°/‡aÙ°nâ#%žÕNÑ=ǾꉑäKÁŸFzùÂFC?6ëñ(ŽukµÃ Ž…XE{šJ•ƒ9&ärÔP|üi¶ŠöÔä4Ø-J[hyªôƒmše;“;ð´#.MÓIÓqA’q«)\»’ÄùÑe®qÄAäÒå˜CDƒ­ 8:ß 7$™l·}uf¶™ÛŽ6c„6ZAI¡%!pj[´-ÑÅ[åÍü ¬+cTdë‹ÔçL¨Í¶§fˆÜ€¤#%PYl±’Ú!VYCrhM ­#.Ñ­ÞîôÅN‚¡êÐ0LoäÅ£JÔ1”ÊȲnÅF´ýJÖ† bÕk#.¥ø?{5²b]%OZZl}Æ0 ¸äE!òó÷΀Ù,"÷•Ég4 )@w}* uAÔ ²$ALpIF wIÏž/ƒ©‰tÊð¨A°O€!##Æ Žj‚ U6¼ãÕt±ð<4O‡ ¢+ÙÚt÷ a‚­ŠÛ ‹L;ÏX#6ɨF §ßæý#%oÙ”1d”@Ç!”ƒ Tñ {õŸWnÿWòmî'y‰üµÍŒó6@gö8A°ÄZ‘´³0?yüä›é#%Å<Ô®Êû>Ê,U!¬Ûf,ÚÍ´õµ¿5÷­øµj÷û"Ñ-62)E’4²’©³jü¿tj7ßÕ~îú#. £D1SQ¶*¥)JÚüz§h’—µ¼'Ì‹x„"#%Z"göBRÖÃÖ1ȸ0ćÐ0–HrHNTŠ$è>ä#.D1¦î¹²)±¬-f¬Q¬lÈÅc+™E²Á‰ëÎò*ˆ„(@Š'](Š]ê4{qM_îòýé©çÜOsèùfaב$ðWÀ šõ‡#%£'¸}—ËeL|ó*j¹ #6ý{.³ƒæɃxv÷’,!Ú°3œ…ó˜ÈIÀôªyæ8öÑUãoË{Ø,E˜E'F™ñßt €ž&ny¤À˜ÞB Q¶Äb‘püÈt‡î"€Û@ÖôTÖ¡ódH˜E9§¹Z€¡ ½B!JŠS˜Újh(‘"jKNíÒkTÛRiIª[R’T šl‘‘@njm¯a0¨ ÿNR‚(”+Ô\/*SÞR¬‹e¬Ë/n£.žÃgUPû£ãÓ dtÎ=v£9é.k ¯Ni`MÄljh™ú([;³RÑÖ*È5õXV²Oµ8Ð"Å…k°ÞÚ4ì#.y@^K?ÞÑïW-ï%ë¼lcúé#nìˆzK™š!ö¦ ¸X÷¢Ї§øþàêüûo–—çãvMÅ)¦%I²5¶1R`ÔFÕ&Û#6Z7æm¿+W‰°ÑZ(F AUdQ$ïî9ú»,ì–i!`¡P*…ˆû¤6+°0rBF"EHÒ(ÄÉ…Š)¢hlÚQ¬,#%”†ýh—Æ}qÏzíÙ/uÝJQþÀ!"kWš±mF- Ú”5F„«6X‹X«QšZÊßÓ[¯3†:zº›üYݽ´ªË%$ÜkìÇègÍ#6Ñü5–#êŒ1KŠL5VÊå˜F·ÓLðкùÀÆ—àIô÷$È«miGlý/$²ÙÛ3"‹ *hc²øQ¶EF*‚d‚ÈÇ#%ª@ Sã’¡¬þ¤Ê[Fh¥È“(1P¹{äÁ5×\É&§4)DÚ›7Õ¥GôØ46àYêÓ’äö¢ìþ3OêÁ `>¸ˆ¯pÏ?~ðøfŒEº#6ݧ¾÷#R÷fìˆfKËÇXZ¦#.Yë9¾îã~07"ß^GÏõ–™“¤M#.UJœmG/¤lír$a®îB™1 ßèSJë@ë#³o(ƒ$QGÊ)ļ.#.õêLo.Eä`%Áæ1‰¢GP5¦Õñóç/ml·p†B#%|²$Ÿxk‘(#6™(iÎ ¹8>J¦ç¸iߎ„>ÔÒ9åÈt(a…-Q¢Þ–3oÐÕùUbÙ›õ`|¢‡B hÚ)I¨i¦×£|#.âöA¯qØÔùKŒ˜5Ó"÷gëtód›±BKûòVµw¬¢ö|jë‚P¤Ot~ÃìJ'`O8)¹A°.F´­'RK`¨¤,n#¨f4äÈlƽQÁ€ÑÔÂ!³n¶`¢úC#’ØÇwšƽ!ȱ|*é €ŠDŘaM ‚¶”FŠ›ÕÕšWáœuzC<óËû²œkGG ŽÄêîéÕ‚]Üãjþ?70ÚEy£ÉZ$£Y¨Ï¨ÑÐǽÁäuMmÐ/÷Ð…ÄZè8@¾?jã‚8“ù‹ç¯fƒYÁêF4dýŒ—-DEC=µvNÅ|ªÖÞm¨:ƒ´Pi\Xì"ð#.%t¢#‹Ì¸ÝѨU׎1Qߪ…@ãƒ[8AÀÓ Êö;÷—çKŽ¤B4Dbžƒ:[nXŠ#.édRS(´@Ír:†‘ä|Xr×c'pždl€A±ï47mà¶Ô~¤…f1Þ“‚BG¸Ô_h½GCˆô"W¾s;/~†D#.îfYÚÛÊÚ{aµÝ×oÊ÷}þëiäk×í¸*‰>ÜD-(?„LþdÓ* z©Q£fÜ@ ݨþQD¢¸ß³Ñ2Tm`ô=åWì#%ÇßwïØÁ²>u­Lä‘™› ™˜ÿl#%#%b#%?›Ùÿs¿ñõÿ¿ü¿éýŸôÿ¹íÿóÿûýíÿóîÿ/óÿëþ_òÿHþ]º>_¿ýÙ|¾ß÷Oþÿëëÿ‡þ?ðøÿãáÿ~#ü¿ãÿ/óþïü?ùÙÿ‡ú|åÿ/ôÿ=¸G£üúÿÓËæùGô_ôêüß_Õ¥P÷SÿLBÄ?iþ,ϳüêÈDÊy;"™e\?·ûäE7¨;ˆ‹‡©sÁþ±L@­ZüÄm4 þË#%öªŠÂ)40)*ÿšþþǹÝÔI I™ŸF·ÊÙVôh #%âQ³ßÌôjB »M¢Ï¡E˜SYˆ8ˆÛ,×g Ø+,€ƒþûö¦C¦Ò‚æ¨x¶æñ#.Öâ×ýÀä÷² ƒ¢îÇ‘^A‰:Õó»0ÉæfØÝ@„#Ì%*ãþU•Êlé·üiÙ\¾ÅŸÙ»Æøyö¡ÃÉvǧ‡¿„eÔ«jÿ݆떅 ¥&P"ƾrÿïUËrž#.ð7Ï_û«u”a:X˜„Ès+u‘ž#6Ù™ýþ.ÀÀ7µ*jH†þ”¦xii”Qš]d*ši‚—eaËœTÁŒ0ÙÿŠeTñhÞ¶ñïÕ¥ƒpvŒîm©TœYnœ44¼BÒÙl`…ÕÁËsO6e7ª¨5mÚ8øq훓Mmƶ9T¨¨ëÌFdMmT˜I†qx“Ý,ØY.䃆5¨mõyõx*ŧ7ŠFÎîs¢kCºFêâ ¬#y{¢ï4êÈh2ùÃá’f´Øäì¹a²…qS1a ïH²F#¸yí‹ÈdŒ¸ÐŽH?F:oÌÌü4ÃÃ)×Ц­ë^EúîÞK¨ŒëN‘±£\-˜ÑNàS4 '>:`«é”ßw´ÿJ±·ý4#.pó‹À@ÄžGßF;tk5SÞ’æ ш넞‰‡ gà w#6Hp,†#6¹^>`L³¬5¬R Eò™„ "IEq¸Ov˜]œ.fB¦æ<õ Ù3PEATV*AB“9wt¸¦cß·Y˜ÌÊ2 ¯kº\69‰¤U¥€ >È!§^²æF4?ícS9öɬצåU1Š"ü«Ç»­'_û6Ä+W] 扄8uîKºƒxteæ߶}C3¿¾z„g,r.;À}²“½©½Ç0À×–f­ÜT9†P^]*zgâ_§Æ³ò8ÎŽQHÔ¼=‰ #6@C&9›Ò’#.³QÁOª‹#.D'ÒáG½\áUò»µŠšP®›CGݼòöœ²áž˜¾¦ÕÍ-ø­¾v챯¤ƒ[êk˜Ø´|nmcãm½(ÕìµoSEªMAj½óZåUìÞÝy»¶ë€]#6.æäQ‰#. ©‘’| P?ç!xnãdN2Apã'PQ±Ôí±s¼p]º¡f!‘OVݤ—¿š7áUÁbÇá*J9…¨H{ÿî°÷cÍÔ¼(5É@$fáÌR¿æû'wØÊ=<ÑÜŽ§ÛÈ_.EúØqPôÇX¡ÿ’#"‹(]¨î;µ#D”)Qb(ÁmLÍtÖêÕÙjûËf¤ÅÍh é! H¤€ £þßÃ3ÏëÿÏئ¨¤"Žþ~˜™áã(ø{fYr0Ûm‹CòNÀ.!xN¦ çå,A‘^#y;³9ø¾Šÿѵú½gþs(ž?l-A!ñÿÔ¥ÝóG#%‰#%(ö#6”CÛ¢ OùI[¥BY=‹”+¨›4ÃÔkéýÕsø]¯üžB_Fœ*ÀN#.ÿ6pŸñäÑÎJíâqTE3‚o¦«…ÆY̘wÈâfÓ§m3 ÊÊÇðç,Má†/-„±¿Ñ8¨–¼­§0aw<}8fJÃ$É o§‚ì]aðx`HŠ$Y@zõnÒ=®Ù i„ÿ~éŽ1éÿµ^#.Jz(ÎLPÛæcè–ªÆ"ÿ“â|xã‡ü†œgê?I¼Ëò~ÿð"‰ÿü]ÉáB@ä&öÐ +#<== +#-----BEGIN PGP SIGNATURE-----\n\niQIzBAABCgAdFiEEivIt5aBoIuNHTzxwSbTGfAUneqoFAl3aW3cACgkQSbTGfAUn\neqruqA//Y9oJ46ZR8W7YB/e45bfrYxGbN7NnkvkwSPNziObYur+n1QpQEOaPTn/U\n5kFtPWHXRJzaG/A9poKn7pl1Xd7Edcu1aalfoEazZbuD37VOxIp9lnrefCAeICqj\nGv0SD96Zac91CbA+b20Q4xnqxKMi3LSI4NPjfFGy62FkSk3MS4p6Rdp0/WAKwwNj\nw7WEjQCNmLb37z+FGSzXg28aljYeteBZEthsVmGJ5QqVwMBwgj2+y5FOTzFfxmqB\nrWgjFYS0l85kgYRZv9yzdNmFs5SScwafwpT8Xmdr49tFn/+0LxXyRxX+rdODgrpV\nY4EOiQz0fd6mMMnaTDXlLSXls3JyVYmbTjeNL/9gcHmnStzJ851CJQfyQg7A+JoC\nc7nz0HbiFyTgB+PUZr1OhGj3A7287o8XQ0tqR3oa7jXIOX0OynrGplMQKr++0jE1\nBgKzjLoE9CTbjkQfICLG+aUy3S1ZyDk/BcO+5+Ytbru+qXuDsIgAdVosMfNSv9jJ\nXvOINsbRMekdejYMZv8fIkn5OEjCFHVhNpobEsCb768bjB3p7alQGECBvjHCm6dy\nXZPzl9cBMWIXcBjPTS+GZj+PIXGcu76pbsx6HBHWf+uJ+4xgOsUCVu//0AV09jvA\n0MjtLWwQ8mdRH6Wt4hsp4HKtSvQrhmljf2OnuYBgaFmcdJkN1zI=\n=C0oT\n-----END PGP SIGNATURE-----\n diff --git a/rtems/hello_posix/wscript b/rtems/hello_posix/wscript new file mode 100644 index 0000000..aa9c93a --- /dev/null +++ b/rtems/hello_posix/wscript @@ -0,0 +1,36 @@ + +# +# Hello world Waf script +# +from __future__ import print_function + +rtems_version = "6" + +try: + import rtems_waf.rtems as rtems +except: + print('error: no rtems_waf git submodule') + import sys + sys.exit(1) + +def init(ctx): + rtems.init(ctx, version = rtems_version, long_commands = True) + +def bsp_configure(conf, arch_bsp): + # Add BSP specific configuration checks + pass + +def options(opt): + rtems.options(opt) + +def configure(conf): + rtems.configure(conf, bsp_configure = bsp_configure) + +def build(bld): + rtems.build(bld) + + bld(features = 'c cprogram', + target = 'hello.exe', + cflags = '-g -O2', + source = ['hello.c', + 'init.c']) diff --git a/rtems/run.sh b/rtems/run.sh index bdd75ff..bf1b3c0 100755 --- a/rtems/run.sh +++ b/rtems/run.sh @@ -1 +1 @@ -docker run --rm --gpus all --net=host -e DISPLAY=$DISPLAY --device=/dev/dri:/dev/dri --volume="$HOME/.Xauthority:/root/.Xauthority:rw" -it openrobotics/rtems \ No newline at end of file +docker run --rm --net=host -e DISPLAY=$DISPLAY --device=/dev/dri:/dev/dri --volume="$HOME/.Xauthority:/root/.Xauthority:rw" -it openrobotics/rtems:latest diff --git a/rtems/tinyxml2/doit b/rtems/tinyxml2/doit new file mode 100755 index 0000000..d6293ba --- /dev/null +++ b/rtems/tinyxml2/doit @@ -0,0 +1,9 @@ + +/root/development/rtems/5/bin/sparc-rtems5-g++ -qrtems -B/root/development/rtems/5/sparc-rtems5/lib/ -B/root/development/rtems/5/sparc-rtems5/leon3/lib/ --specs bsp_specs -mcpu=leon3 -ffunction-sections -fdata-sections -MMD -g -O2 tinyxml2.cpp -c -o tinyxml2.o + +/root/development/rtems/5/bin/sparc-rtems5-g++ -qrtems -B/root/development/rtems/5/sparc-rtems5/lib/ -B/root/development/rtems/5/sparc-rtems5/leon3/lib/ --specs bsp_specs -mcpu=leon3 -ffunction-sections -fdata-sections -MMD -g -O2 xmltest.cpp -c -o xmltest.o + +/root/development/rtems/5/bin/sparc-rtems5-g++ -qrtems -B/root/development/rtems/5/sparc-rtems5/lib/ -B/root/development/rtems/5/sparc-rtems5/leon3/lib/ --specs bsp_specs -mcpu=leon3 -ffunction-sections -fdata-sections -MMD -Wl,--gc-sections tinyxml2.o xmltest.o -oxmltest.exe -Wl,-Bstatic -Wl,-Bdynamic + +/root/development/rtems/5/bin/rtems-run --rtems-bsps=leon3-sis xmltest.exe + diff --git a/rtems/tinyxml2/tinyxml2.cpp b/rtems/tinyxml2/tinyxml2.cpp new file mode 100644 index 0000000..a747605 --- /dev/null +++ b/rtems/tinyxml2/tinyxml2.cpp @@ -0,0 +1,2994 @@ +/* +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "tinyxml2.h" + +#include // yes, this one new style header, is in the Android SDK. +#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) +# include +# include +#else +# include +# include +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) + // Microsoft Visual Studio, version 2005 and higher. Not WinCE. + /*int _snprintf_s( + char *buffer, + size_t sizeOfBuffer, + size_t count, + const char *format [, + argument] ... + );*/ + static inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) + { + va_list va; + va_start( va, format ); + const int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); + va_end( va ); + return result; + } + + static inline int TIXML_VSNPRINTF( char* buffer, size_t size, const char* format, va_list va ) + { + const int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); + return result; + } + + #define TIXML_VSCPRINTF _vscprintf + #define TIXML_SSCANF sscanf_s +#elif defined _MSC_VER + // Microsoft Visual Studio 2003 and earlier or WinCE + #define TIXML_SNPRINTF _snprintf + #define TIXML_VSNPRINTF _vsnprintf + #define TIXML_SSCANF sscanf + #if (_MSC_VER < 1400 ) && (!defined WINCE) + // Microsoft Visual Studio 2003 and not WinCE. + #define TIXML_VSCPRINTF _vscprintf // VS2003's C runtime has this, but VC6 C runtime or WinCE SDK doesn't have. + #else + // Microsoft Visual Studio 2003 and earlier or WinCE. + static inline int TIXML_VSCPRINTF( const char* format, va_list va ) + { + int len = 512; + for (;;) { + len = len*2; + char* str = new char[len](); + const int required = _vsnprintf(str, len, format, va); + delete[] str; + if ( required != -1 ) { + TIXMLASSERT( required >= 0 ); + len = required; + break; + } + } + TIXMLASSERT( len >= 0 ); + return len; + } + #endif +#else + // GCC version 3 and higher + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_VSNPRINTF vsnprintf + static inline int TIXML_VSCPRINTF( const char* format, va_list va ) + { + int len = vsnprintf( 0, 0, format, va ); + TIXMLASSERT( len >= 0 ); + return len; + } + #define TIXML_SSCANF sscanf +#endif + +#if defined(_WIN64) + #define TIXML_FSEEK _fseeki64 + #define TIXML_FTELL _ftelli64 +#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || (__CYGWIN__) + #define TIXML_FSEEK fseeko + #define TIXML_FTELL ftello +#elif defined(__ANDROID__) + #if __ANDROID_API__ > 24 + #define TIXML_FSEEK fseeko64 + #define TIXML_FTELL ftello64 + #else + #define TIXML_FSEEK fseeko + #define TIXML_FTELL ftello + #endif +#elif defined(__unix__) && defined(__x86_64__) + #define TIXML_FSEEK fseeko64 + #define TIXML_FTELL ftello64 +#else + #define TIXML_FSEEK fseek + #define TIXML_FTELL ftell +#endif + + +static const char LINE_FEED = static_cast(0x0a); // all line endings are normalized to LF +static const char LF = LINE_FEED; +static const char CARRIAGE_RETURN = static_cast(0x0d); // CR gets filtered out +static const char CR = CARRIAGE_RETURN; +static const char SINGLE_QUOTE = '\''; +static const char DOUBLE_QUOTE = '\"'; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// ef bb bf (Microsoft "lead bytes") - designates UTF-8 + +static const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +namespace tinyxml2 +{ + +struct Entity { + const char* pattern; + int length; + char value; +}; + +static const int NUM_ENTITIES = 5; +static const Entity entities[NUM_ENTITIES] = { + { "quot", 4, DOUBLE_QUOTE }, + { "amp", 3, '&' }, + { "apos", 4, SINGLE_QUOTE }, + { "lt", 2, '<' }, + { "gt", 2, '>' } +}; + + +StrPair::~StrPair() +{ + Reset(); +} + + +void StrPair::TransferTo( StrPair* other ) +{ + if ( this == other ) { + return; + } + // This in effect implements the assignment operator by "moving" + // ownership (as in auto_ptr). + + TIXMLASSERT( other != 0 ); + TIXMLASSERT( other->_flags == 0 ); + TIXMLASSERT( other->_start == 0 ); + TIXMLASSERT( other->_end == 0 ); + + other->Reset(); + + other->_flags = _flags; + other->_start = _start; + other->_end = _end; + + _flags = 0; + _start = 0; + _end = 0; +} + + +void StrPair::Reset() +{ + if ( _flags & NEEDS_DELETE ) { + delete [] _start; + } + _flags = 0; + _start = 0; + _end = 0; +} + + +void StrPair::SetStr( const char* str, int flags ) +{ + TIXMLASSERT( str ); + Reset(); + size_t len = strlen( str ); + TIXMLASSERT( _start == 0 ); + _start = new char[ len+1 ]; + memcpy( _start, str, len+1 ); + _end = _start + len; + _flags = flags | NEEDS_DELETE; +} + + +char* StrPair::ParseText( char* p, const char* endTag, int strFlags, int* curLineNumPtr ) +{ + TIXMLASSERT( p ); + TIXMLASSERT( endTag && *endTag ); + TIXMLASSERT(curLineNumPtr); + + char* start = p; + const char endChar = *endTag; + size_t length = strlen( endTag ); + + // Inner loop of text parsing. + while ( *p ) { + if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { + Set( start, p, strFlags ); + return p + length; + } else if (*p == '\n') { + ++(*curLineNumPtr); + } + ++p; + TIXMLASSERT( p ); + } + return 0; +} + + +char* StrPair::ParseName( char* p ) +{ + if ( !p || !(*p) ) { + return 0; + } + if ( !XMLUtil::IsNameStartChar( (unsigned char) *p ) ) { + return 0; + } + + char* const start = p; + ++p; + while ( *p && XMLUtil::IsNameChar( (unsigned char) *p ) ) { + ++p; + } + + Set( start, p, 0 ); + return p; +} + + +void StrPair::CollapseWhitespace() +{ + // Adjusting _start would cause undefined behavior on delete[] + TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 ); + // Trim leading space. + _start = XMLUtil::SkipWhiteSpace( _start, 0 ); + + if ( *_start ) { + const char* p = _start; // the read pointer + char* q = _start; // the write pointer + + while( *p ) { + if ( XMLUtil::IsWhiteSpace( *p )) { + p = XMLUtil::SkipWhiteSpace( p, 0 ); + if ( *p == 0 ) { + break; // don't write to q; this trims the trailing space. + } + *q = ' '; + ++q; + } + *q = *p; + ++q; + ++p; + } + *q = 0; + } +} + + +const char* StrPair::GetStr() +{ + TIXMLASSERT( _start ); + TIXMLASSERT( _end ); + if ( _flags & NEEDS_FLUSH ) { + *_end = 0; + _flags ^= NEEDS_FLUSH; + + if ( _flags ) { + const char* p = _start; // the read pointer + char* q = _start; // the write pointer + + while( p < _end ) { + if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) { + // CR-LF pair becomes LF + // CR alone becomes LF + // LF-CR becomes LF + if ( *(p+1) == LF ) { + p += 2; + } + else { + ++p; + } + *q = LF; + ++q; + } + else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) { + if ( *(p+1) == CR ) { + p += 2; + } + else { + ++p; + } + *q = LF; + ++q; + } + else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) { + // Entities handled by tinyXML2: + // - special entities in the entity table [in/out] + // - numeric character reference [in] + // 中 or 中 + + if ( *(p+1) == '#' ) { + const int buflen = 10; + char buf[buflen] = { 0 }; + int len = 0; + const char* adjusted = const_cast( XMLUtil::GetCharacterRef( p, buf, &len ) ); + if ( adjusted == 0 ) { + *q = *p; + ++p; + ++q; + } + else { + TIXMLASSERT( 0 <= len && len <= buflen ); + TIXMLASSERT( q + len <= adjusted ); + p = adjusted; + memcpy( q, buf, len ); + q += len; + } + } + else { + bool entityFound = false; + for( int i = 0; i < NUM_ENTITIES; ++i ) { + const Entity& entity = entities[i]; + if ( strncmp( p + 1, entity.pattern, entity.length ) == 0 + && *( p + entity.length + 1 ) == ';' ) { + // Found an entity - convert. + *q = entity.value; + ++q; + p += entity.length + 2; + entityFound = true; + break; + } + } + if ( !entityFound ) { + // fixme: treat as error? + ++p; + ++q; + } + } + } + else { + *q = *p; + ++p; + ++q; + } + } + *q = 0; + } + // The loop below has plenty going on, and this + // is a less useful mode. Break it out. + if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) { + CollapseWhitespace(); + } + _flags = (_flags & NEEDS_DELETE); + } + TIXMLASSERT( _start ); + return _start; +} + + + + +// --------- XMLUtil ----------- // + +const char* XMLUtil::writeBoolTrue = "true"; +const char* XMLUtil::writeBoolFalse = "false"; + +void XMLUtil::SetBoolSerialization(const char* writeTrue, const char* writeFalse) +{ + static const char* defTrue = "true"; + static const char* defFalse = "false"; + + writeBoolTrue = (writeTrue) ? writeTrue : defTrue; + writeBoolFalse = (writeFalse) ? writeFalse : defFalse; +} + + +const char* XMLUtil::ReadBOM( const char* p, bool* bom ) +{ + TIXMLASSERT( p ); + TIXMLASSERT( bom ); + *bom = false; + const unsigned char* pu = reinterpret_cast(p); + // Check for BOM: + if ( *(pu+0) == TIXML_UTF_LEAD_0 + && *(pu+1) == TIXML_UTF_LEAD_1 + && *(pu+2) == TIXML_UTF_LEAD_2 ) { + *bom = true; + p += 3; + } + TIXMLASSERT( p ); + return p; +} + + +void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) { + *length = 1; + } + else if ( input < 0x800 ) { + *length = 2; + } + else if ( input < 0x10000 ) { + *length = 3; + } + else if ( input < 0x200000 ) { + *length = 4; + } + else { + *length = 0; // This code won't convert this correctly anyway. + return; + } + + output += *length; + + // Scary scary fall throughs are annotated with carefully designed comments + // to suppress compiler warnings such as -Wimplicit-fallthrough in gcc + switch (*length) { + case 4: + --output; + *output = static_cast((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + //fall through + case 3: + --output; + *output = static_cast((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + //fall through + case 2: + --output; + *output = static_cast((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + //fall through + case 1: + --output; + *output = static_cast(input | FIRST_BYTE_MARK[*length]); + break; + default: + TIXMLASSERT( false ); + } +} + + +const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) +{ + // Presume an entity, and pull it out. + *length = 0; + + if ( *(p+1) == '#' && *(p+2) ) { + unsigned long ucs = 0; + TIXMLASSERT( sizeof( ucs ) >= 4 ); + ptrdiff_t delta = 0; + unsigned mult = 1; + static const char SEMICOLON = ';'; + + if ( *(p+2) == 'x' ) { + // Hexadecimal. + const char* q = p+3; + if ( !(*q) ) { + return 0; + } + + q = strchr( q, SEMICOLON ); + + if ( !q ) { + return 0; + } + TIXMLASSERT( *q == SEMICOLON ); + + delta = q-p; + --q; + + while ( *q != 'x' ) { + unsigned int digit = 0; + + if ( *q >= '0' && *q <= '9' ) { + digit = *q - '0'; + } + else if ( *q >= 'a' && *q <= 'f' ) { + digit = *q - 'a' + 10; + } + else if ( *q >= 'A' && *q <= 'F' ) { + digit = *q - 'A' + 10; + } + else { + return 0; + } + TIXMLASSERT( digit < 16 ); + TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); + const unsigned int digitScaled = mult * digit; + TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); + ucs += digitScaled; + TIXMLASSERT( mult <= UINT_MAX / 16 ); + mult *= 16; + --q; + } + } + else { + // Decimal. + const char* q = p+2; + if ( !(*q) ) { + return 0; + } + + q = strchr( q, SEMICOLON ); + + if ( !q ) { + return 0; + } + TIXMLASSERT( *q == SEMICOLON ); + + delta = q-p; + --q; + + while ( *q != '#' ) { + if ( *q >= '0' && *q <= '9' ) { + const unsigned int digit = *q - '0'; + TIXMLASSERT( digit < 10 ); + TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); + const unsigned int digitScaled = mult * digit; + TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); + ucs += digitScaled; + } + else { + return 0; + } + TIXMLASSERT( mult <= UINT_MAX / 10 ); + mult *= 10; + --q; + } + } + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + return p + delta + 1; + } + return p+1; +} + + +void XMLUtil::ToStr( int v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%d", v ); +} + + +void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%u", v ); +} + + +void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? writeBoolTrue : writeBoolFalse); +} + +/* + ToStr() of a number is a very tricky topic. + https://github.com/leethomason/tinyxml2/issues/106 +*/ +void XMLUtil::ToStr( float v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v ); +} + + +void XMLUtil::ToStr( double v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v ); +} + + +void XMLUtil::ToStr( int64_t v, char* buffer, int bufferSize ) +{ + // horrible syntax trick to make the compiler happy about %lld + TIXML_SNPRINTF(buffer, bufferSize, "%lld", static_cast(v)); +} + +void XMLUtil::ToStr( uint64_t v, char* buffer, int bufferSize ) +{ + // horrible syntax trick to make the compiler happy about %llu + TIXML_SNPRINTF(buffer, bufferSize, "%llu", (long long)v); +} + +bool XMLUtil::ToInt(const char* str, int* value) +{ + if (IsPrefixHex(str)) { + unsigned v; + if (TIXML_SSCANF(str, "%x", &v) == 1) { + *value = static_cast(v); + return true; + } + } + else { + if (TIXML_SSCANF(str, "%d", value) == 1) { + return true; + } + } + return false; +} + +bool XMLUtil::ToUnsigned(const char* str, unsigned* value) +{ + if (TIXML_SSCANF(str, IsPrefixHex(str) ? "%x" : "%u", value) == 1) { + return true; + } + return false; +} + +bool XMLUtil::ToBool( const char* str, bool* value ) +{ + int ival = 0; + if ( ToInt( str, &ival )) { + *value = (ival==0) ? false : true; + return true; + } + static const char* TRUE_VALS[] = { "true", "True", "TRUE", 0 }; + static const char* FALSE_VALS[] = { "false", "False", "FALSE", 0 }; + + for (int i = 0; TRUE_VALS[i]; ++i) { + if (StringEqual(str, TRUE_VALS[i])) { + *value = true; + return true; + } + } + for (int i = 0; FALSE_VALS[i]; ++i) { + if (StringEqual(str, FALSE_VALS[i])) { + *value = false; + return true; + } + } + return false; +} + + +bool XMLUtil::ToFloat( const char* str, float* value ) +{ + if ( TIXML_SSCANF( str, "%f", value ) == 1 ) { + return true; + } + return false; +} + + +bool XMLUtil::ToDouble( const char* str, double* value ) +{ + if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) { + return true; + } + return false; +} + + +bool XMLUtil::ToInt64(const char* str, int64_t* value) +{ + if (IsPrefixHex(str)) { + unsigned long long v = 0; // horrible syntax trick to make the compiler happy about %llx + if (TIXML_SSCANF(str, "%llx", &v) == 1) { + *value = static_cast(v); + return true; + } + } + else { + long long v = 0; // horrible syntax trick to make the compiler happy about %lld + if (TIXML_SSCANF(str, "%lld", &v) == 1) { + *value = static_cast(v); + return true; + } + } + return false; +} + + +bool XMLUtil::ToUnsigned64(const char* str, uint64_t* value) { + unsigned long long v = 0; // horrible syntax trick to make the compiler happy about %llu + if(TIXML_SSCANF(str, IsPrefixHex(str) ? "%llx" : "%llu", &v) == 1) { + *value = (uint64_t)v; + return true; + } + return false; +} + + +char* XMLDocument::Identify( char* p, XMLNode** node ) +{ + TIXMLASSERT( node ); + TIXMLASSERT( p ); + char* const start = p; + int const startLine = _parseCurLineNum; + p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum ); + if( !*p ) { + *node = 0; + TIXMLASSERT( p ); + return p; + } + + // These strings define the matching patterns: + static const char* xmlHeader = { "( _commentPool ); + returnNode->_parseLineNum = _parseCurLineNum; + p += xmlHeaderLen; + } + else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { + returnNode = CreateUnlinkedNode( _commentPool ); + returnNode->_parseLineNum = _parseCurLineNum; + p += commentHeaderLen; + } + else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { + XMLText* text = CreateUnlinkedNode( _textPool ); + returnNode = text; + returnNode->_parseLineNum = _parseCurLineNum; + p += cdataHeaderLen; + text->SetCData( true ); + } + else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { + returnNode = CreateUnlinkedNode( _commentPool ); + returnNode->_parseLineNum = _parseCurLineNum; + p += dtdHeaderLen; + } + else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { + returnNode = CreateUnlinkedNode( _elementPool ); + returnNode->_parseLineNum = _parseCurLineNum; + p += elementHeaderLen; + } + else { + returnNode = CreateUnlinkedNode( _textPool ); + returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character + p = start; // Back it up, all the text counts. + _parseCurLineNum = startLine; + } + + TIXMLASSERT( returnNode ); + TIXMLASSERT( p ); + *node = returnNode; + return p; +} + + +bool XMLDocument::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + if ( visitor->VisitEnter( *this ) ) { + for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) { + break; + } + } + } + return visitor->VisitExit( *this ); +} + + +// --------- XMLNode ----------- // + +XMLNode::XMLNode( XMLDocument* doc ) : + _document( doc ), + _parent( 0 ), + _value(), + _parseLineNum( 0 ), + _firstChild( 0 ), _lastChild( 0 ), + _prev( 0 ), _next( 0 ), + _userData( 0 ), + _memPool( 0 ) +{ +} + + +XMLNode::~XMLNode() +{ + DeleteChildren(); + if ( _parent ) { + _parent->Unlink( this ); + } +} + +const char* XMLNode::Value() const +{ + // Edge case: XMLDocuments don't have a Value. Return null. + if ( this->ToDocument() ) + return 0; + return _value.GetStr(); +} + +void XMLNode::SetValue( const char* str, bool staticMem ) +{ + if ( staticMem ) { + _value.SetInternedStr( str ); + } + else { + _value.SetStr( str ); + } +} + +XMLNode* XMLNode::DeepClone(XMLDocument* target) const +{ + XMLNode* clone = this->ShallowClone(target); + if (!clone) return 0; + + for (const XMLNode* child = this->FirstChild(); child; child = child->NextSibling()) { + XMLNode* childClone = child->DeepClone(target); + TIXMLASSERT(childClone); + clone->InsertEndChild(childClone); + } + return clone; +} + +void XMLNode::DeleteChildren() +{ + while( _firstChild ) { + TIXMLASSERT( _lastChild ); + DeleteChild( _firstChild ); + } + _firstChild = _lastChild = 0; +} + + +void XMLNode::Unlink( XMLNode* child ) +{ + TIXMLASSERT( child ); + TIXMLASSERT( child->_document == _document ); + TIXMLASSERT( child->_parent == this ); + if ( child == _firstChild ) { + _firstChild = _firstChild->_next; + } + if ( child == _lastChild ) { + _lastChild = _lastChild->_prev; + } + + if ( child->_prev ) { + child->_prev->_next = child->_next; + } + if ( child->_next ) { + child->_next->_prev = child->_prev; + } + child->_next = 0; + child->_prev = 0; + child->_parent = 0; +} + + +void XMLNode::DeleteChild( XMLNode* node ) +{ + TIXMLASSERT( node ); + TIXMLASSERT( node->_document == _document ); + TIXMLASSERT( node->_parent == this ); + Unlink( node ); + TIXMLASSERT(node->_prev == 0); + TIXMLASSERT(node->_next == 0); + TIXMLASSERT(node->_parent == 0); + DeleteNode( node ); +} + + +XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + InsertChildPreamble( addThis ); + + if ( _lastChild ) { + TIXMLASSERT( _firstChild ); + TIXMLASSERT( _lastChild->_next == 0 ); + _lastChild->_next = addThis; + addThis->_prev = _lastChild; + _lastChild = addThis; + + addThis->_next = 0; + } + else { + TIXMLASSERT( _firstChild == 0 ); + _firstChild = _lastChild = addThis; + + addThis->_prev = 0; + addThis->_next = 0; + } + addThis->_parent = this; + return addThis; +} + + +XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + InsertChildPreamble( addThis ); + + if ( _firstChild ) { + TIXMLASSERT( _lastChild ); + TIXMLASSERT( _firstChild->_prev == 0 ); + + _firstChild->_prev = addThis; + addThis->_next = _firstChild; + _firstChild = addThis; + + addThis->_prev = 0; + } + else { + TIXMLASSERT( _lastChild == 0 ); + _firstChild = _lastChild = addThis; + + addThis->_prev = 0; + addThis->_next = 0; + } + addThis->_parent = this; + return addThis; +} + + +XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + + TIXMLASSERT( afterThis ); + + if ( afterThis->_parent != this ) { + TIXMLASSERT( false ); + return 0; + } + if ( afterThis == addThis ) { + // Current state: BeforeThis -> AddThis -> OneAfterAddThis + // Now AddThis must disappear from it's location and then + // reappear between BeforeThis and OneAfterAddThis. + // So just leave it where it is. + return addThis; + } + + if ( afterThis->_next == 0 ) { + // The last node or the only node. + return InsertEndChild( addThis ); + } + InsertChildPreamble( addThis ); + addThis->_prev = afterThis; + addThis->_next = afterThis->_next; + afterThis->_next->_prev = addThis; + afterThis->_next = addThis; + addThis->_parent = this; + return addThis; +} + + + + +const XMLElement* XMLNode::FirstChildElement( const char* name ) const +{ + for( const XMLNode* node = _firstChild; node; node = node->_next ) { + const XMLElement* element = node->ToElementWithName( name ); + if ( element ) { + return element; + } + } + return 0; +} + + +const XMLElement* XMLNode::LastChildElement( const char* name ) const +{ + for( const XMLNode* node = _lastChild; node; node = node->_prev ) { + const XMLElement* element = node->ToElementWithName( name ); + if ( element ) { + return element; + } + } + return 0; +} + + +const XMLElement* XMLNode::NextSiblingElement( const char* name ) const +{ + for( const XMLNode* node = _next; node; node = node->_next ) { + const XMLElement* element = node->ToElementWithName( name ); + if ( element ) { + return element; + } + } + return 0; +} + + +const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const +{ + for( const XMLNode* node = _prev; node; node = node->_prev ) { + const XMLElement* element = node->ToElementWithName( name ); + if ( element ) { + return element; + } + } + return 0; +} + + +char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) +{ + // This is a recursive method, but thinking about it "at the current level" + // it is a pretty simple flat list: + // + // + // + // With a special case: + // + // + // + // + // Where the closing element (/foo) *must* be the next thing after the opening + // element, and the names must match. BUT the tricky bit is that the closing + // element will be read by the child. + // + // 'endTag' is the end tag for this node, it is returned by a call to a child. + // 'parentEnd' is the end tag for the parent, which is filled in and returned. + + XMLDocument::DepthTracker tracker(_document); + if (_document->Error()) + return 0; + + while( p && *p ) { + XMLNode* node = 0; + + p = _document->Identify( p, &node ); + TIXMLASSERT( p ); + if ( node == 0 ) { + break; + } + + const int initialLineNum = node->_parseLineNum; + + StrPair endTag; + p = node->ParseDeep( p, &endTag, curLineNumPtr ); + if ( !p ) { + DeleteNode( node ); + if ( !_document->Error() ) { + _document->SetError( XML_ERROR_PARSING, initialLineNum, 0); + } + break; + } + + const XMLDeclaration* const decl = node->ToDeclaration(); + if ( decl ) { + // Declarations are only allowed at document level + // + // Multiple declarations are allowed but all declarations + // must occur before anything else. + // + // Optimized due to a security test case. If the first node is + // a declaration, and the last node is a declaration, then only + // declarations have so far been added. + bool wellLocated = false; + + if (ToDocument()) { + if (FirstChild()) { + wellLocated = + FirstChild() && + FirstChild()->ToDeclaration() && + LastChild() && + LastChild()->ToDeclaration(); + } + else { + wellLocated = true; + } + } + if ( !wellLocated ) { + _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value()); + DeleteNode( node ); + break; + } + } + + XMLElement* ele = node->ToElement(); + if ( ele ) { + // We read the end tag. Return it to the parent. + if ( ele->ClosingType() == XMLElement::CLOSING ) { + if ( parentEndTag ) { + ele->_value.TransferTo( parentEndTag ); + } + node->_memPool->SetTracked(); // created and then immediately deleted. + DeleteNode( node ); + return p; + } + + // Handle an end tag returned to this level. + // And handle a bunch of annoying errors. + bool mismatch = false; + if ( endTag.Empty() ) { + if ( ele->ClosingType() == XMLElement::OPEN ) { + mismatch = true; + } + } + else { + if ( ele->ClosingType() != XMLElement::OPEN ) { + mismatch = true; + } + else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) { + mismatch = true; + } + } + if ( mismatch ) { + _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name()); + DeleteNode( node ); + break; + } + } + InsertEndChild( node ); + } + return 0; +} + +/*static*/ void XMLNode::DeleteNode( XMLNode* node ) +{ + if ( node == 0 ) { + return; + } + TIXMLASSERT(node->_document); + if (!node->ToDocument()) { + node->_document->MarkInUse(node); + } + + MemPool* pool = node->_memPool; + node->~XMLNode(); + pool->Free( node ); +} + +void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const +{ + TIXMLASSERT( insertThis ); + TIXMLASSERT( insertThis->_document == _document ); + + if (insertThis->_parent) { + insertThis->_parent->Unlink( insertThis ); + } + else { + insertThis->_document->MarkInUse(insertThis); + insertThis->_memPool->SetTracked(); + } +} + +const XMLElement* XMLNode::ToElementWithName( const char* name ) const +{ + const XMLElement* element = this->ToElement(); + if ( element == 0 ) { + return 0; + } + if ( name == 0 ) { + return element; + } + if ( XMLUtil::StringEqual( element->Name(), name ) ) { + return element; + } + return 0; +} + +// --------- XMLText ---------- // +char* XMLText::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) +{ + if ( this->CData() ) { + p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_CDATA, _parseLineNum, 0 ); + } + return p; + } + else { + int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES; + if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) { + flags |= StrPair::NEEDS_WHITESPACE_COLLAPSING; + } + + p = _value.ParseText( p, "<", flags, curLineNumPtr ); + if ( p && *p ) { + return p-1; + } + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_TEXT, _parseLineNum, 0 ); + } + } + return 0; +} + + +XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern? + text->SetCData( this->CData() ); + return text; +} + + +bool XMLText::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLText* text = compare->ToText(); + return ( text && XMLUtil::StringEqual( text->Value(), Value() ) ); +} + + +bool XMLText::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + + +// --------- XMLComment ---------- // + +XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLComment::~XMLComment() +{ +} + + +char* XMLComment::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) +{ + // Comment parses as text. + p = _value.ParseText( p, "-->", StrPair::COMMENT, curLineNumPtr ); + if ( p == 0 ) { + _document->SetError( XML_ERROR_PARSING_COMMENT, _parseLineNum, 0 ); + } + return p; +} + + +XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern? + return comment; +} + + +bool XMLComment::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLComment* comment = compare->ToComment(); + return ( comment && XMLUtil::StringEqual( comment->Value(), Value() )); +} + + +bool XMLComment::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + + +// --------- XMLDeclaration ---------- // + +XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLDeclaration::~XMLDeclaration() +{ + //printf( "~XMLDeclaration\n" ); +} + + +char* XMLDeclaration::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) +{ + // Declaration parses as text. + p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); + if ( p == 0 ) { + _document->SetError( XML_ERROR_PARSING_DECLARATION, _parseLineNum, 0 ); + } + return p; +} + + +XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern? + return dec; +} + + +bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLDeclaration* declaration = compare->ToDeclaration(); + return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() )); +} + + + +bool XMLDeclaration::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + +// --------- XMLUnknown ---------- // + +XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLUnknown::~XMLUnknown() +{ +} + + +char* XMLUnknown::ParseDeep( char* p, StrPair*, int* curLineNumPtr ) +{ + // Unknown parses as text. + p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr ); + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_UNKNOWN, _parseLineNum, 0 ); + } + return p; +} + + +XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern? + return text; +} + + +bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLUnknown* unknown = compare->ToUnknown(); + return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() )); +} + + +bool XMLUnknown::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + +// --------- XMLAttribute ---------- // + +const char* XMLAttribute::Name() const +{ + return _name.GetStr(); +} + +const char* XMLAttribute::Value() const +{ + return _value.GetStr(); +} + +char* XMLAttribute::ParseDeep( char* p, bool processEntities, int* curLineNumPtr ) +{ + // Parse using the name rules: bug fix, was using ParseText before + p = _name.ParseName( p ); + if ( !p || !*p ) { + return 0; + } + + // Skip white space before = + p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); + if ( *p != '=' ) { + return 0; + } + + ++p; // move up to opening quote + p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); + if ( *p != '\"' && *p != '\'' ) { + return 0; + } + + const char endTag[2] = { *p, 0 }; + ++p; // move past opening quote + + p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES, curLineNumPtr ); + return p; +} + + +void XMLAttribute::SetName( const char* n ) +{ + _name.SetStr( n ); +} + + +XMLError XMLAttribute::QueryIntValue( int* value ) const +{ + if ( XMLUtil::ToInt( Value(), value )) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const +{ + if ( XMLUtil::ToUnsigned( Value(), value )) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryInt64Value(int64_t* value) const +{ + if (XMLUtil::ToInt64(Value(), value)) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryUnsigned64Value(uint64_t* value) const +{ + if(XMLUtil::ToUnsigned64(Value(), value)) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryBoolValue( bool* value ) const +{ + if ( XMLUtil::ToBool( Value(), value )) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryFloatValue( float* value ) const +{ + if ( XMLUtil::ToFloat( Value(), value )) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryDoubleValue( double* value ) const +{ + if ( XMLUtil::ToDouble( Value(), value )) { + return XML_SUCCESS; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +void XMLAttribute::SetAttribute( const char* v ) +{ + _value.SetStr( v ); +} + + +void XMLAttribute::SetAttribute( int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute( unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute(int64_t v) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr(v, buf, BUF_SIZE); + _value.SetStr(buf); +} + +void XMLAttribute::SetAttribute(uint64_t v) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr(v, buf, BUF_SIZE); + _value.SetStr(buf); +} + + +void XMLAttribute::SetAttribute( bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( float v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +// --------- XMLElement ---------- // +XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), + _closingType( OPEN ), + _rootAttribute( 0 ) +{ +} + + +XMLElement::~XMLElement() +{ + while( _rootAttribute ) { + XMLAttribute* next = _rootAttribute->_next; + DeleteAttribute( _rootAttribute ); + _rootAttribute = next; + } +} + + +const XMLAttribute* XMLElement::FindAttribute( const char* name ) const +{ + for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) { + if ( XMLUtil::StringEqual( a->Name(), name ) ) { + return a; + } + } + return 0; +} + + +const char* XMLElement::Attribute( const char* name, const char* value ) const +{ + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return 0; + } + if ( !value || XMLUtil::StringEqual( a->Value(), value )) { + return a->Value(); + } + return 0; +} + +int XMLElement::IntAttribute(const char* name, int defaultValue) const +{ + int i = defaultValue; + QueryIntAttribute(name, &i); + return i; +} + +unsigned XMLElement::UnsignedAttribute(const char* name, unsigned defaultValue) const +{ + unsigned i = defaultValue; + QueryUnsignedAttribute(name, &i); + return i; +} + +int64_t XMLElement::Int64Attribute(const char* name, int64_t defaultValue) const +{ + int64_t i = defaultValue; + QueryInt64Attribute(name, &i); + return i; +} + +uint64_t XMLElement::Unsigned64Attribute(const char* name, uint64_t defaultValue) const +{ + uint64_t i = defaultValue; + QueryUnsigned64Attribute(name, &i); + return i; +} + +bool XMLElement::BoolAttribute(const char* name, bool defaultValue) const +{ + bool b = defaultValue; + QueryBoolAttribute(name, &b); + return b; +} + +double XMLElement::DoubleAttribute(const char* name, double defaultValue) const +{ + double d = defaultValue; + QueryDoubleAttribute(name, &d); + return d; +} + +float XMLElement::FloatAttribute(const char* name, float defaultValue) const +{ + float f = defaultValue; + QueryFloatAttribute(name, &f); + return f; +} + +const char* XMLElement::GetText() const +{ + /* skip comment node */ + const XMLNode* node = FirstChild(); + while (node) { + if (node->ToComment()) { + node = node->NextSibling(); + continue; + } + break; + } + + if ( node && node->ToText() ) { + return node->Value(); + } + return 0; +} + + +void XMLElement::SetText( const char* inText ) +{ + if ( FirstChild() && FirstChild()->ToText() ) + FirstChild()->SetValue( inText ); + else { + XMLText* theText = GetDocument()->NewText( inText ); + InsertFirstChild( theText ); + } +} + + +void XMLElement::SetText( int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText(int64_t v) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr(v, buf, BUF_SIZE); + SetText(buf); +} + +void XMLElement::SetText(uint64_t v) { + char buf[BUF_SIZE]; + XMLUtil::ToStr(v, buf, BUF_SIZE); + SetText(buf); +} + + +void XMLElement::SetText( bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( float v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +XMLError XMLElement::QueryIntText( int* ival ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToInt( t, ival ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToUnsigned( t, uval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryInt64Text(int64_t* ival) const +{ + if (FirstChild() && FirstChild()->ToText()) { + const char* t = FirstChild()->Value(); + if (XMLUtil::ToInt64(t, ival)) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryUnsigned64Text(uint64_t* uval) const +{ + if(FirstChild() && FirstChild()->ToText()) { + const char* t = FirstChild()->Value(); + if(XMLUtil::ToUnsigned64(t, uval)) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryBoolText( bool* bval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToBool( t, bval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryDoubleText( double* dval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToDouble( t, dval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryFloatText( float* fval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToFloat( t, fval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + +int XMLElement::IntText(int defaultValue) const +{ + int i = defaultValue; + QueryIntText(&i); + return i; +} + +unsigned XMLElement::UnsignedText(unsigned defaultValue) const +{ + unsigned i = defaultValue; + QueryUnsignedText(&i); + return i; +} + +int64_t XMLElement::Int64Text(int64_t defaultValue) const +{ + int64_t i = defaultValue; + QueryInt64Text(&i); + return i; +} + +uint64_t XMLElement::Unsigned64Text(uint64_t defaultValue) const +{ + uint64_t i = defaultValue; + QueryUnsigned64Text(&i); + return i; +} + +bool XMLElement::BoolText(bool defaultValue) const +{ + bool b = defaultValue; + QueryBoolText(&b); + return b; +} + +double XMLElement::DoubleText(double defaultValue) const +{ + double d = defaultValue; + QueryDoubleText(&d); + return d; +} + +float XMLElement::FloatText(float defaultValue) const +{ + float f = defaultValue; + QueryFloatText(&f); + return f; +} + + +XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) +{ + XMLAttribute* last = 0; + XMLAttribute* attrib = 0; + for( attrib = _rootAttribute; + attrib; + last = attrib, attrib = attrib->_next ) { + if ( XMLUtil::StringEqual( attrib->Name(), name ) ) { + break; + } + } + if ( !attrib ) { + attrib = CreateAttribute(); + TIXMLASSERT( attrib ); + if ( last ) { + TIXMLASSERT( last->_next == 0 ); + last->_next = attrib; + } + else { + TIXMLASSERT( _rootAttribute == 0 ); + _rootAttribute = attrib; + } + attrib->SetName( name ); + } + return attrib; +} + + +void XMLElement::DeleteAttribute( const char* name ) +{ + XMLAttribute* prev = 0; + for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) { + if ( XMLUtil::StringEqual( name, a->Name() ) ) { + if ( prev ) { + prev->_next = a->_next; + } + else { + _rootAttribute = a->_next; + } + DeleteAttribute( a ); + break; + } + prev = a; + } +} + + +char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr ) +{ + XMLAttribute* prevAttribute = 0; + + // Read the attributes. + while( p ) { + p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); + if ( !(*p) ) { + _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "XMLElement name=%s", Name() ); + return 0; + } + + // attribute. + if (XMLUtil::IsNameStartChar( (unsigned char) *p ) ) { + XMLAttribute* attrib = CreateAttribute(); + TIXMLASSERT( attrib ); + attrib->_parseLineNum = _document->_parseCurLineNum; + + const int attrLineNum = attrib->_parseLineNum; + + p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr ); + if ( !p || Attribute( attrib->Name() ) ) { + DeleteAttribute( attrib ); + _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "XMLElement name=%s", Name() ); + return 0; + } + // There is a minor bug here: if the attribute in the source xml + // document is duplicated, it will not be detected and the + // attribute will be doubly added. However, tracking the 'prevAttribute' + // avoids re-scanning the attribute list. Preferring performance for + // now, may reconsider in the future. + if ( prevAttribute ) { + TIXMLASSERT( prevAttribute->_next == 0 ); + prevAttribute->_next = attrib; + } + else { + TIXMLASSERT( _rootAttribute == 0 ); + _rootAttribute = attrib; + } + prevAttribute = attrib; + } + // end of the tag + else if ( *p == '>' ) { + ++p; + break; + } + // end of the tag + else if ( *p == '/' && *(p+1) == '>' ) { + _closingType = CLOSED; + return p+2; // done; sealed element. + } + else { + _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, 0 ); + return 0; + } + } + return p; +} + +void XMLElement::DeleteAttribute( XMLAttribute* attribute ) +{ + if ( attribute == 0 ) { + return; + } + MemPool* pool = attribute->_memPool; + attribute->~XMLAttribute(); + pool->Free( attribute ); +} + +XMLAttribute* XMLElement::CreateAttribute() +{ + TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); + XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + TIXMLASSERT( attrib ); + attrib->_memPool = &_document->_attributePool; + attrib->_memPool->SetTracked(); + return attrib; +} + + +XMLElement* XMLElement::InsertNewChildElement(const char* name) +{ + XMLElement* node = _document->NewElement(name); + return InsertEndChild(node) ? node : 0; +} + +XMLComment* XMLElement::InsertNewComment(const char* comment) +{ + XMLComment* node = _document->NewComment(comment); + return InsertEndChild(node) ? node : 0; +} + +XMLText* XMLElement::InsertNewText(const char* text) +{ + XMLText* node = _document->NewText(text); + return InsertEndChild(node) ? node : 0; +} + +XMLDeclaration* XMLElement::InsertNewDeclaration(const char* text) +{ + XMLDeclaration* node = _document->NewDeclaration(text); + return InsertEndChild(node) ? node : 0; +} + +XMLUnknown* XMLElement::InsertNewUnknown(const char* text) +{ + XMLUnknown* node = _document->NewUnknown(text); + return InsertEndChild(node) ? node : 0; +} + + + +// +// +// foobar +// +char* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) +{ + // Read the element name. + p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr ); + + // The closing element is the form. It is + // parsed just like a regular element then deleted from + // the DOM. + if ( *p == '/' ) { + _closingType = CLOSING; + ++p; + } + + p = _value.ParseName( p ); + if ( _value.Empty() ) { + return 0; + } + + p = ParseAttributes( p, curLineNumPtr ); + if ( !p || !*p || _closingType != OPEN ) { + return p; + } + + p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr ); + return p; +} + + + +XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern? + for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) { + element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern? + } + return element; +} + + +bool XMLElement::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLElement* other = compare->ToElement(); + if ( other && XMLUtil::StringEqual( other->Name(), Name() )) { + + const XMLAttribute* a=FirstAttribute(); + const XMLAttribute* b=other->FirstAttribute(); + + while ( a && b ) { + if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) { + return false; + } + a = a->Next(); + b = b->Next(); + } + if ( a || b ) { + // different count + return false; + } + return true; + } + return false; +} + + +bool XMLElement::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + if ( visitor->VisitEnter( *this, _rootAttribute ) ) { + for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) { + break; + } + } + } + return visitor->VisitExit( *this ); +} + + +// --------- XMLDocument ----------- // + +// Warning: List must match 'enum XMLError' +const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { + "XML_SUCCESS", + "XML_NO_ATTRIBUTE", + "XML_WRONG_ATTRIBUTE_TYPE", + "XML_ERROR_FILE_NOT_FOUND", + "XML_ERROR_FILE_COULD_NOT_BE_OPENED", + "XML_ERROR_FILE_READ_ERROR", + "XML_ERROR_PARSING_ELEMENT", + "XML_ERROR_PARSING_ATTRIBUTE", + "XML_ERROR_PARSING_TEXT", + "XML_ERROR_PARSING_CDATA", + "XML_ERROR_PARSING_COMMENT", + "XML_ERROR_PARSING_DECLARATION", + "XML_ERROR_PARSING_UNKNOWN", + "XML_ERROR_EMPTY_DOCUMENT", + "XML_ERROR_MISMATCHED_ELEMENT", + "XML_ERROR_PARSING", + "XML_CAN_NOT_CONVERT_TEXT", + "XML_NO_TEXT_NODE", + "XML_ELEMENT_DEPTH_EXCEEDED" +}; + + +XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) : + XMLNode( 0 ), + _writeBOM( false ), + _processEntities( processEntities ), + _errorID(XML_SUCCESS), + _whitespaceMode( whitespaceMode ), + _errorStr(), + _errorLineNum( 0 ), + _charBuffer( 0 ), + _parseCurLineNum( 0 ), + _parsingDepth(0), + _unlinked(), + _elementPool(), + _attributePool(), + _textPool(), + _commentPool() +{ + // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+) + _document = this; +} + + +XMLDocument::~XMLDocument() +{ + Clear(); +} + + +void XMLDocument::MarkInUse(const XMLNode* const node) +{ + TIXMLASSERT(node); + TIXMLASSERT(node->_parent == 0); + + for (int i = 0; i < _unlinked.Size(); ++i) { + if (node == _unlinked[i]) { + _unlinked.SwapRemove(i); + break; + } + } +} + +void XMLDocument::Clear() +{ + DeleteChildren(); + while( _unlinked.Size()) { + DeleteNode(_unlinked[0]); // Will remove from _unlinked as part of delete. + } + +#ifdef TINYXML2_DEBUG + const bool hadError = Error(); +#endif + ClearError(); + + delete [] _charBuffer; + _charBuffer = 0; + _parsingDepth = 0; + +#if 0 + _textPool.Trace( "text" ); + _elementPool.Trace( "element" ); + _commentPool.Trace( "comment" ); + _attributePool.Trace( "attribute" ); +#endif + +#ifdef TINYXML2_DEBUG + if ( !hadError ) { + TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); + TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); + TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); + TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); + } +#endif +} + + +void XMLDocument::DeepCopy(XMLDocument* target) const +{ + TIXMLASSERT(target); + if (target == this) { + return; // technically success - a no-op. + } + + target->Clear(); + for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) { + target->InsertEndChild(node->DeepClone(target)); + } +} + +XMLElement* XMLDocument::NewElement( const char* name ) +{ + XMLElement* ele = CreateUnlinkedNode( _elementPool ); + ele->SetName( name ); + return ele; +} + + +XMLComment* XMLDocument::NewComment( const char* str ) +{ + XMLComment* comment = CreateUnlinkedNode( _commentPool ); + comment->SetValue( str ); + return comment; +} + + +XMLText* XMLDocument::NewText( const char* str ) +{ + XMLText* text = CreateUnlinkedNode( _textPool ); + text->SetValue( str ); + return text; +} + + +XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) +{ + XMLDeclaration* dec = CreateUnlinkedNode( _commentPool ); + dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); + return dec; +} + + +XMLUnknown* XMLDocument::NewUnknown( const char* str ) +{ + XMLUnknown* unk = CreateUnlinkedNode( _commentPool ); + unk->SetValue( str ); + return unk; +} + +static FILE* callfopen( const char* filepath, const char* mode ) +{ + TIXMLASSERT( filepath ); + TIXMLASSERT( mode ); +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) + FILE* fp = 0; + const errno_t err = fopen_s( &fp, filepath, mode ); + if ( err ) { + return 0; + } +#else + FILE* fp = fopen( filepath, mode ); +#endif + return fp; +} + +void XMLDocument::DeleteNode( XMLNode* node ) { + TIXMLASSERT( node ); + TIXMLASSERT(node->_document == this ); + if (node->_parent) { + node->_parent->DeleteChild( node ); + } + else { + // Isn't in the tree. + // Use the parent delete. + // Also, we need to mark it tracked: we 'know' + // it was never used. + node->_memPool->SetTracked(); + // Call the static XMLNode version: + XMLNode::DeleteNode(node); + } +} + + +XMLError XMLDocument::LoadFile( const char* filename ) +{ + if ( !filename ) { + TIXMLASSERT( false ); + SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=" ); + return _errorID; + } + + Clear(); + FILE* fp = callfopen( filename, "rb" ); + if ( !fp ) { + SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename ); + return _errorID; + } + LoadFile( fp ); + fclose( fp ); + return _errorID; +} + +XMLError XMLDocument::LoadFile( FILE* fp ) +{ + Clear(); + + TIXML_FSEEK( fp, 0, SEEK_SET ); + if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + TIXML_FSEEK( fp, 0, SEEK_END ); + + unsigned long long filelength; + { + const long long fileLengthSigned = TIXML_FTELL( fp ); + TIXML_FSEEK( fp, 0, SEEK_SET ); + if ( fileLengthSigned == -1L ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + TIXMLASSERT( fileLengthSigned >= 0 ); + filelength = static_cast(fileLengthSigned); + } + + const size_t maxSizeT = static_cast(-1); + // We'll do the comparison as an unsigned long long, because that's guaranteed to be at + // least 8 bytes, even on a 32-bit platform. + if ( filelength >= static_cast(maxSizeT) ) { + // Cannot handle files which won't fit in buffer together with null terminator + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + if ( filelength == 0 ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return _errorID; + } + + const size_t size = static_cast(filelength); + TIXMLASSERT( _charBuffer == 0 ); + _charBuffer = new char[size+1]; + const size_t read = fread( _charBuffer, 1, size, fp ); + if ( read != size ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + _charBuffer[size] = 0; + + Parse(); + return _errorID; +} + + +XMLError XMLDocument::SaveFile( const char* filename, bool compact ) +{ + if ( !filename ) { + TIXMLASSERT( false ); + SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=" ); + return _errorID; + } + + FILE* fp = callfopen( filename, "w" ); + if ( !fp ) { + SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename ); + return _errorID; + } + SaveFile(fp, compact); + fclose( fp ); + return _errorID; +} + + +XMLError XMLDocument::SaveFile( FILE* fp, bool compact ) +{ + // Clear any error from the last save, otherwise it will get reported + // for *this* call. + ClearError(); + XMLPrinter stream( fp, compact ); + Print( &stream ); + return _errorID; +} + + +XMLError XMLDocument::Parse( const char* xml, size_t nBytes ) +{ + Clear(); + + if ( nBytes == 0 || !xml || !*xml ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return _errorID; + } + if ( nBytes == static_cast(-1) ) { + nBytes = strlen( xml ); + } + TIXMLASSERT( _charBuffer == 0 ); + _charBuffer = new char[ nBytes+1 ]; + memcpy( _charBuffer, xml, nBytes ); + _charBuffer[nBytes] = 0; + + Parse(); + if ( Error() ) { + // clean up now essentially dangling memory. + // and the parse fail can put objects in the + // pools that are dead and inaccessible. + DeleteChildren(); + _elementPool.Clear(); + _attributePool.Clear(); + _textPool.Clear(); + _commentPool.Clear(); + } + return _errorID; +} + + +void XMLDocument::Print( XMLPrinter* streamer ) const +{ + if ( streamer ) { + Accept( streamer ); + } + else { + XMLPrinter stdoutStreamer( stdout ); + Accept( &stdoutStreamer ); + } +} + + +void XMLDocument::ClearError() { + _errorID = XML_SUCCESS; + _errorLineNum = 0; + _errorStr.Reset(); +} + + +void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... ) +{ + TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT ); + _errorID = error; + _errorLineNum = lineNum; + _errorStr.Reset(); + + const size_t BUFFER_SIZE = 1000; + char* buffer = new char[BUFFER_SIZE]; + + TIXMLASSERT(sizeof(error) <= sizeof(int)); + TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d", ErrorIDToName(error), int(error), int(error), lineNum); + + if (format) { + size_t len = strlen(buffer); + TIXML_SNPRINTF(buffer + len, BUFFER_SIZE - len, ": "); + len = strlen(buffer); + + va_list va; + va_start(va, format); + TIXML_VSNPRINTF(buffer + len, BUFFER_SIZE - len, format, va); + va_end(va); + } + _errorStr.SetStr(buffer); + delete[] buffer; +} + + +/*static*/ const char* XMLDocument::ErrorIDToName(XMLError errorID) +{ + TIXMLASSERT( errorID >= 0 && errorID < XML_ERROR_COUNT ); + const char* errorName = _errorNames[errorID]; + TIXMLASSERT( errorName && errorName[0] ); + return errorName; +} + +const char* XMLDocument::ErrorStr() const +{ + return _errorStr.Empty() ? "" : _errorStr.GetStr(); +} + + +void XMLDocument::PrintError() const +{ + printf("%s\n", ErrorStr()); +} + +const char* XMLDocument::ErrorName() const +{ + return ErrorIDToName(_errorID); +} + +void XMLDocument::Parse() +{ + TIXMLASSERT( NoChildren() ); // Clear() must have been called previously + TIXMLASSERT( _charBuffer ); + _parseCurLineNum = 1; + _parseLineNum = 1; + char* p = _charBuffer; + p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum ); + p = const_cast( XMLUtil::ReadBOM( p, &_writeBOM ) ); + if ( !*p ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return; + } + ParseDeep(p, 0, &_parseCurLineNum ); +} + +void XMLDocument::PushDepth() +{ + _parsingDepth++; + if (_parsingDepth == TINYXML2_MAX_ELEMENT_DEPTH) { + SetError(XML_ELEMENT_DEPTH_EXCEEDED, _parseCurLineNum, "Element nesting is too deep." ); + } +} + +void XMLDocument::PopDepth() +{ + TIXMLASSERT(_parsingDepth > 0); + --_parsingDepth; +} + +XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) : + _elementJustOpened( false ), + _stack(), + _firstElement( true ), + _fp( file ), + _depth( depth ), + _textDepth( -1 ), + _processEntities( true ), + _compactMode( compact ), + _buffer() +{ + for( int i=0; i(entityValue); + TIXMLASSERT( flagIndex < ENTITY_RANGE ); + _entityFlag[flagIndex] = true; + } + _restrictedEntityFlag[static_cast('&')] = true; + _restrictedEntityFlag[static_cast('<')] = true; + _restrictedEntityFlag[static_cast('>')] = true; // not required, but consistency is nice + _buffer.Push( 0 ); +} + + +void XMLPrinter::Print( const char* format, ... ) +{ + va_list va; + va_start( va, format ); + + if ( _fp ) { + vfprintf( _fp, format, va ); + } + else { + const int len = TIXML_VSCPRINTF( format, va ); + // Close out and re-start the va-args + va_end( va ); + TIXMLASSERT( len >= 0 ); + va_start( va, format ); + TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 ); + char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator. + TIXML_VSNPRINTF( p, len+1, format, va ); + } + va_end( va ); +} + + +void XMLPrinter::Write( const char* data, size_t size ) +{ + if ( _fp ) { + fwrite ( data , sizeof(char), size, _fp); + } + else { + char* p = _buffer.PushArr( static_cast(size) ) - 1; // back up over the null terminator. + memcpy( p, data, size ); + p[size] = 0; + } +} + + +void XMLPrinter::Putc( char ch ) +{ + if ( _fp ) { + fputc ( ch, _fp); + } + else { + char* p = _buffer.PushArr( sizeof(char) ) - 1; // back up over the null terminator. + p[0] = ch; + p[1] = 0; + } +} + + +void XMLPrinter::PrintSpace( int depth ) +{ + for( int i=0; i 0 && *q < ENTITY_RANGE ) { + // Check for entities. If one is found, flush + // the stream up until the entity, write the + // entity, and keep looking. + if ( flag[static_cast(*q)] ) { + while ( p < q ) { + const size_t delta = q - p; + const int toPrint = ( INT_MAX < delta ) ? INT_MAX : static_cast(delta); + Write( p, toPrint ); + p += toPrint; + } + bool entityPatternPrinted = false; + for( int i=0; i(delta); + Write( p, toPrint ); + } + } + else { + Write( p ); + } +} + + +void XMLPrinter::PushHeader( bool writeBOM, bool writeDec ) +{ + if ( writeBOM ) { + static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 }; + Write( reinterpret_cast< const char* >( bom ) ); + } + if ( writeDec ) { + PushDeclaration( "xml version=\"1.0\"" ); + } +} + +void XMLPrinter::PrepareForNewNode( bool compactMode ) +{ + SealElementIfJustOpened(); + + if ( compactMode ) { + return; + } + + if ( _firstElement ) { + PrintSpace (_depth); + } else if ( _textDepth < 0) { + Putc( '\n' ); + PrintSpace( _depth ); + } + + _firstElement = false; +} + +void XMLPrinter::OpenElement( const char* name, bool compactMode ) +{ + PrepareForNewNode( compactMode ); + _stack.Push( name ); + + Write ( "<" ); + Write ( name ); + + _elementJustOpened = true; + ++_depth; +} + + +void XMLPrinter::PushAttribute( const char* name, const char* value ) +{ + TIXMLASSERT( _elementJustOpened ); + Putc ( ' ' ); + Write( name ); + Write( "=\"" ); + PrintString( value, false ); + Putc ( '\"' ); +} + + +void XMLPrinter::PushAttribute( const char* name, int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::PushAttribute( const char* name, unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::PushAttribute(const char* name, int64_t v) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr(v, buf, BUF_SIZE); + PushAttribute(name, buf); +} + + +void XMLPrinter::PushAttribute(const char* name, uint64_t v) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr(v, buf, BUF_SIZE); + PushAttribute(name, buf); +} + + +void XMLPrinter::PushAttribute( const char* name, bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::PushAttribute( const char* name, double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::CloseElement( bool compactMode ) +{ + --_depth; + const char* name = _stack.Pop(); + + if ( _elementJustOpened ) { + Write( "/>" ); + } + else { + if ( _textDepth < 0 && !compactMode) { + Putc( '\n' ); + PrintSpace( _depth ); + } + Write ( "" ); + } + + if ( _textDepth == _depth ) { + _textDepth = -1; + } + if ( _depth == 0 && !compactMode) { + Putc( '\n' ); + } + _elementJustOpened = false; +} + + +void XMLPrinter::SealElementIfJustOpened() +{ + if ( !_elementJustOpened ) { + return; + } + _elementJustOpened = false; + Putc( '>' ); +} + + +void XMLPrinter::PushText( const char* text, bool cdata ) +{ + _textDepth = _depth-1; + + SealElementIfJustOpened(); + if ( cdata ) { + Write( "" ); + } + else { + PrintString( text, true ); + } +} + + +void XMLPrinter::PushText( int64_t value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( uint64_t value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr(value, buf, BUF_SIZE); + PushText(buf, false); +} + + +void XMLPrinter::PushText( int value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( unsigned value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( bool value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( float value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( double value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushComment( const char* comment ) +{ + PrepareForNewNode( _compactMode ); + + Write( "" ); +} + + +void XMLPrinter::PushDeclaration( const char* value ) +{ + PrepareForNewNode( _compactMode ); + + Write( "" ); +} + + +void XMLPrinter::PushUnknown( const char* value ) +{ + PrepareForNewNode( _compactMode ); + + Write( "' ); +} + + +bool XMLPrinter::VisitEnter( const XMLDocument& doc ) +{ + _processEntities = doc.ProcessEntities(); + if ( doc.HasBOM() ) { + PushHeader( true, false ); + } + return true; +} + + +bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) +{ + const XMLElement* parentElem = 0; + if ( element.Parent() ) { + parentElem = element.Parent()->ToElement(); + } + const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode; + OpenElement( element.Name(), compactMode ); + while ( attribute ) { + PushAttribute( attribute->Name(), attribute->Value() ); + attribute = attribute->Next(); + } + return true; +} + + +bool XMLPrinter::VisitExit( const XMLElement& element ) +{ + CloseElement( CompactMode(element) ); + return true; +} + + +bool XMLPrinter::Visit( const XMLText& text ) +{ + PushText( text.Value(), text.CData() ); + return true; +} + + +bool XMLPrinter::Visit( const XMLComment& comment ) +{ + PushComment( comment.Value() ); + return true; +} + +bool XMLPrinter::Visit( const XMLDeclaration& declaration ) +{ + PushDeclaration( declaration.Value() ); + return true; +} + + +bool XMLPrinter::Visit( const XMLUnknown& unknown ) +{ + PushUnknown( unknown.Value() ); + return true; +} + +} // namespace tinyxml2 diff --git a/rtems/tinyxml2/tinyxml2.h b/rtems/tinyxml2/tinyxml2.h new file mode 100644 index 0000000..cfb1053 --- /dev/null +++ b/rtems/tinyxml2/tinyxml2.h @@ -0,0 +1,2380 @@ +/* +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#ifndef TINYXML2_INCLUDED +#define TINYXML2_INCLUDED + +#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) +# include +# include +# include +# include +# include +# if defined(__PS3__) +# include +# endif +#else +# include +# include +# include +# include +# include +#endif +#include + +/* + TODO: intern strings instead of allocation. +*/ +/* + gcc: + g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe + + Formatting, Artistic Style: + AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h +*/ + +#if defined( _DEBUG ) || defined (__DEBUG__) +# ifndef TINYXML2_DEBUG +# define TINYXML2_DEBUG +# endif +#endif + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4251) +#endif + +#ifdef _WIN32 +# ifdef TINYXML2_EXPORT +# define TINYXML2_LIB __declspec(dllexport) +# elif defined(TINYXML2_IMPORT) +# define TINYXML2_LIB __declspec(dllimport) +# else +# define TINYXML2_LIB +# endif +#elif __GNUC__ >= 4 +# define TINYXML2_LIB __attribute__((visibility("default"))) +#else +# define TINYXML2_LIB +#endif + + +#if !defined(TIXMLASSERT) +#if defined(TINYXML2_DEBUG) +# if defined(_MSC_VER) +# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like +# define TIXMLASSERT( x ) do { if ( !((void)0,(x))) { __debugbreak(); } } while(false) +# elif defined (ANDROID_NDK) +# include +# define TIXMLASSERT( x ) do { if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } } while(false) +# else +# include +# define TIXMLASSERT assert +# endif +#else +# define TIXMLASSERT( x ) do {} while(false) +#endif +#endif + +/* Versioning, past 1.0.14: + http://semver.org/ +*/ +static const int TIXML2_MAJOR_VERSION = 9; +static const int TIXML2_MINOR_VERSION = 0; +static const int TIXML2_PATCH_VERSION = 0; + +#define TINYXML2_MAJOR_VERSION 9 +#define TINYXML2_MINOR_VERSION 0 +#define TINYXML2_PATCH_VERSION 0 + +// A fixed element depth limit is problematic. There needs to be a +// limit to avoid a stack overflow. However, that limit varies per +// system, and the capacity of the stack. On the other hand, it's a trivial +// attack that can result from ill, malicious, or even correctly formed XML, +// so there needs to be a limit in place. +static const int TINYXML2_MAX_ELEMENT_DEPTH = 100; + +namespace tinyxml2 +{ +class XMLDocument; +class XMLElement; +class XMLAttribute; +class XMLComment; +class XMLText; +class XMLDeclaration; +class XMLUnknown; +class XMLPrinter; + +/* + A class that wraps strings. Normally stores the start and end + pointers into the XML file itself, and will apply normalization + and entity translation if actually read. Can also store (and memory + manage) a traditional char[] + + Isn't clear why TINYXML2_LIB is needed; but seems to fix #719 +*/ +class TINYXML2_LIB StrPair +{ +public: + enum Mode { + NEEDS_ENTITY_PROCESSING = 0x01, + NEEDS_NEWLINE_NORMALIZATION = 0x02, + NEEDS_WHITESPACE_COLLAPSING = 0x04, + + TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, + TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, + ATTRIBUTE_NAME = 0, + ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, + ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, + COMMENT = NEEDS_NEWLINE_NORMALIZATION + }; + + StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {} + ~StrPair(); + + void Set( char* start, char* end, int flags ) { + TIXMLASSERT( start ); + TIXMLASSERT( end ); + Reset(); + _start = start; + _end = end; + _flags = flags | NEEDS_FLUSH; + } + + const char* GetStr(); + + bool Empty() const { + return _start == _end; + } + + void SetInternedStr( const char* str ) { + Reset(); + _start = const_cast(str); + } + + void SetStr( const char* str, int flags=0 ); + + char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr ); + char* ParseName( char* in ); + + void TransferTo( StrPair* other ); + void Reset(); + +private: + void CollapseWhitespace(); + + enum { + NEEDS_FLUSH = 0x100, + NEEDS_DELETE = 0x200 + }; + + int _flags; + char* _start; + char* _end; + + StrPair( const StrPair& other ); // not supported + void operator=( const StrPair& other ); // not supported, use TransferTo() +}; + + +/* + A dynamic array of Plain Old Data. Doesn't support constructors, etc. + Has a small initial memory pool, so that low or no usage will not + cause a call to new/delete +*/ +template +class DynArray +{ +public: + DynArray() : + _mem( _pool ), + _allocated( INITIAL_SIZE ), + _size( 0 ) + { + } + + ~DynArray() { + if ( _mem != _pool ) { + delete [] _mem; + } + } + + void Clear() { + _size = 0; + } + + void Push( T t ) { + TIXMLASSERT( _size < INT_MAX ); + EnsureCapacity( _size+1 ); + _mem[_size] = t; + ++_size; + } + + T* PushArr( int count ) { + TIXMLASSERT( count >= 0 ); + TIXMLASSERT( _size <= INT_MAX - count ); + EnsureCapacity( _size+count ); + T* ret = &_mem[_size]; + _size += count; + return ret; + } + + T Pop() { + TIXMLASSERT( _size > 0 ); + --_size; + return _mem[_size]; + } + + void PopArr( int count ) { + TIXMLASSERT( _size >= count ); + _size -= count; + } + + bool Empty() const { + return _size == 0; + } + + T& operator[](int i) { + TIXMLASSERT( i>= 0 && i < _size ); + return _mem[i]; + } + + const T& operator[](int i) const { + TIXMLASSERT( i>= 0 && i < _size ); + return _mem[i]; + } + + const T& PeekTop() const { + TIXMLASSERT( _size > 0 ); + return _mem[ _size - 1]; + } + + int Size() const { + TIXMLASSERT( _size >= 0 ); + return _size; + } + + int Capacity() const { + TIXMLASSERT( _allocated >= INITIAL_SIZE ); + return _allocated; + } + + void SwapRemove(int i) { + TIXMLASSERT(i >= 0 && i < _size); + TIXMLASSERT(_size > 0); + _mem[i] = _mem[_size - 1]; + --_size; + } + + const T* Mem() const { + TIXMLASSERT( _mem ); + return _mem; + } + + T* Mem() { + TIXMLASSERT( _mem ); + return _mem; + } + +private: + DynArray( const DynArray& ); // not supported + void operator=( const DynArray& ); // not supported + + void EnsureCapacity( int cap ) { + TIXMLASSERT( cap > 0 ); + if ( cap > _allocated ) { + TIXMLASSERT( cap <= INT_MAX / 2 ); + const int newAllocated = cap * 2; + T* newMem = new T[newAllocated]; + TIXMLASSERT( newAllocated >= _size ); + memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs + if ( _mem != _pool ) { + delete [] _mem; + } + _mem = newMem; + _allocated = newAllocated; + } + } + + T* _mem; + T _pool[INITIAL_SIZE]; + int _allocated; // objects allocated + int _size; // number objects in use +}; + + +/* + Parent virtual class of a pool for fast allocation + and deallocation of objects. +*/ +class MemPool +{ +public: + MemPool() {} + virtual ~MemPool() {} + + virtual int ItemSize() const = 0; + virtual void* Alloc() = 0; + virtual void Free( void* ) = 0; + virtual void SetTracked() = 0; +}; + + +/* + Template child class to create pools of the correct type. +*/ +template< int ITEM_SIZE > +class MemPoolT : public MemPool +{ +public: + MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} + ~MemPoolT() { + MemPoolT< ITEM_SIZE >::Clear(); + } + + void Clear() { + // Delete the blocks. + while( !_blockPtrs.Empty()) { + Block* lastBlock = _blockPtrs.Pop(); + delete lastBlock; + } + _root = 0; + _currentAllocs = 0; + _nAllocs = 0; + _maxAllocs = 0; + _nUntracked = 0; + } + + virtual int ItemSize() const { + return ITEM_SIZE; + } + int CurrentAllocs() const { + return _currentAllocs; + } + + virtual void* Alloc() { + if ( !_root ) { + // Need a new block. + Block* block = new Block(); + _blockPtrs.Push( block ); + + Item* blockItems = block->items; + for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) { + blockItems[i].next = &(blockItems[i + 1]); + } + blockItems[ITEMS_PER_BLOCK - 1].next = 0; + _root = blockItems; + } + Item* const result = _root; + TIXMLASSERT( result != 0 ); + _root = _root->next; + + ++_currentAllocs; + if ( _currentAllocs > _maxAllocs ) { + _maxAllocs = _currentAllocs; + } + ++_nAllocs; + ++_nUntracked; + return result; + } + + virtual void Free( void* mem ) { + if ( !mem ) { + return; + } + --_currentAllocs; + Item* item = static_cast( mem ); +#ifdef TINYXML2_DEBUG + memset( item, 0xfe, sizeof( *item ) ); +#endif + item->next = _root; + _root = item; + } + void Trace( const char* name ) { + printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", + name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs, + ITEM_SIZE, _nAllocs, _blockPtrs.Size() ); + } + + void SetTracked() { + --_nUntracked; + } + + int Untracked() const { + return _nUntracked; + } + + // This number is perf sensitive. 4k seems like a good tradeoff on my machine. + // The test file is large, 170k. + // Release: VS2010 gcc(no opt) + // 1k: 4000 + // 2k: 4000 + // 4k: 3900 21000 + // 16k: 5200 + // 32k: 4300 + // 64k: 4000 21000 + // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK + // in private part if ITEMS_PER_BLOCK is private + enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE }; + +private: + MemPoolT( const MemPoolT& ); // not supported + void operator=( const MemPoolT& ); // not supported + + union Item { + Item* next; + char itemData[ITEM_SIZE]; + }; + struct Block { + Item items[ITEMS_PER_BLOCK]; + }; + DynArray< Block*, 10 > _blockPtrs; + Item* _root; + + int _currentAllocs; + int _nAllocs; + int _maxAllocs; + int _nUntracked; +}; + + + +/** + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a XMLVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs + are simply called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its siblings will be visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the XMLDocument, although all nodes support visiting. + + You should never change the document from a callback. + + @sa XMLNode::Accept() +*/ +class TINYXML2_LIB XMLVisitor +{ +public: + virtual ~XMLVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { + return true; + } + /// Visit a document. + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { + return true; + } + + /// Visit an element. + virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { + return true; + } + /// Visit an element. + virtual bool VisitExit( const XMLElement& /*element*/ ) { + return true; + } + + /// Visit a declaration. + virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { + return true; + } + /// Visit a text node. + virtual bool Visit( const XMLText& /*text*/ ) { + return true; + } + /// Visit a comment node. + virtual bool Visit( const XMLComment& /*comment*/ ) { + return true; + } + /// Visit an unknown node. + virtual bool Visit( const XMLUnknown& /*unknown*/ ) { + return true; + } +}; + +// WARNING: must match XMLDocument::_errorNames[] +enum XMLError { + XML_SUCCESS = 0, + XML_NO_ATTRIBUTE, + XML_WRONG_ATTRIBUTE_TYPE, + XML_ERROR_FILE_NOT_FOUND, + XML_ERROR_FILE_COULD_NOT_BE_OPENED, + XML_ERROR_FILE_READ_ERROR, + XML_ERROR_PARSING_ELEMENT, + XML_ERROR_PARSING_ATTRIBUTE, + XML_ERROR_PARSING_TEXT, + XML_ERROR_PARSING_CDATA, + XML_ERROR_PARSING_COMMENT, + XML_ERROR_PARSING_DECLARATION, + XML_ERROR_PARSING_UNKNOWN, + XML_ERROR_EMPTY_DOCUMENT, + XML_ERROR_MISMATCHED_ELEMENT, + XML_ERROR_PARSING, + XML_CAN_NOT_CONVERT_TEXT, + XML_NO_TEXT_NODE, + XML_ELEMENT_DEPTH_EXCEEDED, + + XML_ERROR_COUNT +}; + + +/* + Utility functionality. +*/ +class TINYXML2_LIB XMLUtil +{ +public: + static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) { + TIXMLASSERT( p ); + + while( IsWhiteSpace(*p) ) { + if (curLineNumPtr && *p == '\n') { + ++(*curLineNumPtr); + } + ++p; + } + TIXMLASSERT( p ); + return p; + } + static char* SkipWhiteSpace( char* const p, int* curLineNumPtr ) { + return const_cast( SkipWhiteSpace( const_cast(p), curLineNumPtr ) ); + } + + // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't + // correct, but simple, and usually works. + static bool IsWhiteSpace( char p ) { + return !IsUTF8Continuation(p) && isspace( static_cast(p) ); + } + + inline static bool IsNameStartChar( unsigned char ch ) { + if ( ch >= 128 ) { + // This is a heuristic guess in attempt to not implement Unicode-aware isalpha() + return true; + } + if ( isalpha( ch ) ) { + return true; + } + return ch == ':' || ch == '_'; + } + + inline static bool IsNameChar( unsigned char ch ) { + return IsNameStartChar( ch ) + || isdigit( ch ) + || ch == '.' + || ch == '-'; + } + + inline static bool IsPrefixHex( const char* p) { + p = SkipWhiteSpace(p, 0); + return p && *p == '0' && ( *(p + 1) == 'x' || *(p + 1) == 'X'); + } + + inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { + if ( p == q ) { + return true; + } + TIXMLASSERT( p ); + TIXMLASSERT( q ); + TIXMLASSERT( nChar >= 0 ); + return strncmp( p, q, nChar ) == 0; + } + + inline static bool IsUTF8Continuation( const char p ) { + return ( p & 0x80 ) != 0; + } + + static const char* ReadBOM( const char* p, bool* hasBOM ); + // p is the starting location, + // the UTF-8 value of the entity will be placed in value, and length filled in. + static const char* GetCharacterRef( const char* p, char* value, int* length ); + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + + // converts primitive types to strings + static void ToStr( int v, char* buffer, int bufferSize ); + static void ToStr( unsigned v, char* buffer, int bufferSize ); + static void ToStr( bool v, char* buffer, int bufferSize ); + static void ToStr( float v, char* buffer, int bufferSize ); + static void ToStr( double v, char* buffer, int bufferSize ); + static void ToStr(int64_t v, char* buffer, int bufferSize); + static void ToStr(uint64_t v, char* buffer, int bufferSize); + + // converts strings to primitive types + static bool ToInt( const char* str, int* value ); + static bool ToUnsigned( const char* str, unsigned* value ); + static bool ToBool( const char* str, bool* value ); + static bool ToFloat( const char* str, float* value ); + static bool ToDouble( const char* str, double* value ); + static bool ToInt64(const char* str, int64_t* value); + static bool ToUnsigned64(const char* str, uint64_t* value); + // Changes what is serialized for a boolean value. + // Default to "true" and "false". Shouldn't be changed + // unless you have a special testing or compatibility need. + // Be careful: static, global, & not thread safe. + // Be sure to set static const memory as parameters. + static void SetBoolSerialization(const char* writeTrue, const char* writeFalse); + +private: + static const char* writeBoolTrue; + static const char* writeBoolFalse; +}; + + +/** XMLNode is a base class for every object that is in the + XML Document Object Model (DOM), except XMLAttributes. + Nodes have siblings, a parent, and children which can + be navigated. A node is always in a XMLDocument. + The type of a XMLNode can be queried, and it can + be cast to its more defined type. + + A XMLDocument allocates memory for all its Nodes. + When the XMLDocument gets deleted, all its Nodes + will also be deleted. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + @endverbatim +*/ +class TINYXML2_LIB XMLNode +{ + friend class XMLDocument; + friend class XMLElement; +public: + + /// Get the XMLDocument that owns this XMLNode. + const XMLDocument* GetDocument() const { + TIXMLASSERT( _document ); + return _document; + } + /// Get the XMLDocument that owns this XMLNode. + XMLDocument* GetDocument() { + TIXMLASSERT( _document ); + return _document; + } + + /// Safely cast to an Element, or null. + virtual XMLElement* ToElement() { + return 0; + } + /// Safely cast to Text, or null. + virtual XMLText* ToText() { + return 0; + } + /// Safely cast to a Comment, or null. + virtual XMLComment* ToComment() { + return 0; + } + /// Safely cast to a Document, or null. + virtual XMLDocument* ToDocument() { + return 0; + } + /// Safely cast to a Declaration, or null. + virtual XMLDeclaration* ToDeclaration() { + return 0; + } + /// Safely cast to an Unknown, or null. + virtual XMLUnknown* ToUnknown() { + return 0; + } + + virtual const XMLElement* ToElement() const { + return 0; + } + virtual const XMLText* ToText() const { + return 0; + } + virtual const XMLComment* ToComment() const { + return 0; + } + virtual const XMLDocument* ToDocument() const { + return 0; + } + virtual const XMLDeclaration* ToDeclaration() const { + return 0; + } + virtual const XMLUnknown* ToUnknown() const { + return 0; + } + + /** The meaning of 'value' changes for the specific type. + @verbatim + Document: empty (NULL is returned, not an empty string) + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + const char* Value() const; + + /** Set the Value of an XML node. + @sa Value() + */ + void SetValue( const char* val, bool staticMem=false ); + + /// Gets the line number the node is in, if the document was parsed from a file. + int GetLineNum() const { return _parseLineNum; } + + /// Get the parent of this node on the DOM. + const XMLNode* Parent() const { + return _parent; + } + + XMLNode* Parent() { + return _parent; + } + + /// Returns true if this node has no children. + bool NoChildren() const { + return !_firstChild; + } + + /// Get the first child node, or null if none exists. + const XMLNode* FirstChild() const { + return _firstChild; + } + + XMLNode* FirstChild() { + return _firstChild; + } + + /** Get the first child element, or optionally the first child + element with the specified name. + */ + const XMLElement* FirstChildElement( const char* name = 0 ) const; + + XMLElement* FirstChildElement( const char* name = 0 ) { + return const_cast(const_cast(this)->FirstChildElement( name )); + } + + /// Get the last child node, or null if none exists. + const XMLNode* LastChild() const { + return _lastChild; + } + + XMLNode* LastChild() { + return _lastChild; + } + + /** Get the last child element or optionally the last child + element with the specified name. + */ + const XMLElement* LastChildElement( const char* name = 0 ) const; + + XMLElement* LastChildElement( const char* name = 0 ) { + return const_cast(const_cast(this)->LastChildElement(name) ); + } + + /// Get the previous (left) sibling node of this node. + const XMLNode* PreviousSibling() const { + return _prev; + } + + XMLNode* PreviousSibling() { + return _prev; + } + + /// Get the previous (left) sibling element of this node, with an optionally supplied name. + const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ; + + XMLElement* PreviousSiblingElement( const char* name = 0 ) { + return const_cast(const_cast(this)->PreviousSiblingElement( name ) ); + } + + /// Get the next (right) sibling node of this node. + const XMLNode* NextSibling() const { + return _next; + } + + XMLNode* NextSibling() { + return _next; + } + + /// Get the next (right) sibling element of this node, with an optionally supplied name. + const XMLElement* NextSiblingElement( const char* name = 0 ) const; + + XMLElement* NextSiblingElement( const char* name = 0 ) { + return const_cast(const_cast(this)->NextSiblingElement( name ) ); + } + + /** + Add a child node as the last (right) child. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the node does not + belong to the same document. + */ + XMLNode* InsertEndChild( XMLNode* addThis ); + + XMLNode* LinkEndChild( XMLNode* addThis ) { + return InsertEndChild( addThis ); + } + /** + Add a child node as the first (left) child. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the node does not + belong to the same document. + */ + XMLNode* InsertFirstChild( XMLNode* addThis ); + /** + Add a node after the specified child node. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the afterThis node + is not a child of this node, or if the node does not + belong to the same document. + */ + XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); + + /** + Delete all the children of this node. + */ + void DeleteChildren(); + + /** + Delete a child of this node. + */ + void DeleteChild( XMLNode* node ); + + /** + Make a copy of this node, but not its children. + You may pass in a Document pointer that will be + the owner of the new Node. If the 'document' is + null, then the node returned will be allocated + from the current Document. (this->GetDocument()) + + Note: if called on a XMLDocument, this will return null. + */ + virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; + + /** + Make a copy of this node and all its children. + + If the 'target' is null, then the nodes will + be allocated in the current document. If 'target' + is specified, the memory will be allocated is the + specified XMLDocument. + + NOTE: This is probably not the correct tool to + copy a document, since XMLDocuments can have multiple + top level XMLNodes. You probably want to use + XMLDocument::DeepCopy() + */ + XMLNode* DeepClone( XMLDocument* target ) const; + + /** + Test if 2 nodes are the same, but don't test children. + The 2 nodes do not need to be in the same Document. + + Note: if called on a XMLDocument, this will return false. + */ + virtual bool ShallowEqual( const XMLNode* compare ) const = 0; + + /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the XMLVisitor interface. + + This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + XMLPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( XMLVisitor* visitor ) const = 0; + + /** + Set user data into the XMLNode. TinyXML-2 in + no way processes or interprets user data. + It is initially 0. + */ + void SetUserData(void* userData) { _userData = userData; } + + /** + Get user data set into the XMLNode. TinyXML-2 in + no way processes or interprets user data. + It is initially 0. + */ + void* GetUserData() const { return _userData; } + +protected: + explicit XMLNode( XMLDocument* ); + virtual ~XMLNode(); + + virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); + + XMLDocument* _document; + XMLNode* _parent; + mutable StrPair _value; + int _parseLineNum; + + XMLNode* _firstChild; + XMLNode* _lastChild; + + XMLNode* _prev; + XMLNode* _next; + + void* _userData; + +private: + MemPool* _memPool; + void Unlink( XMLNode* child ); + static void DeleteNode( XMLNode* node ); + void InsertChildPreamble( XMLNode* insertThis ) const; + const XMLElement* ToElementWithName( const char* name ) const; + + XMLNode( const XMLNode& ); // not supported + XMLNode& operator=( const XMLNode& ); // not supported +}; + + +/** XML text. + + Note that a text node can have child element nodes, for example: + @verbatim + This is bold + @endverbatim + + A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCData() and query it with CData(). +*/ +class TINYXML2_LIB XMLText : public XMLNode +{ + friend class XMLDocument; +public: + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLText* ToText() { + return this; + } + virtual const XMLText* ToText() const { + return this; + } + + /// Declare whether this should be CDATA or standard text. + void SetCData( bool isCData ) { + _isCData = isCData; + } + /// Returns true if this is a CDATA text element. + bool CData() const { + return _isCData; + } + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + explicit XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} + virtual ~XMLText() {} + + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); + +private: + bool _isCData; + + XMLText( const XMLText& ); // not supported + XMLText& operator=( const XMLText& ); // not supported +}; + + +/** An XML Comment. */ +class TINYXML2_LIB XMLComment : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLComment* ToComment() { + return this; + } + virtual const XMLComment* ToComment() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + explicit XMLComment( XMLDocument* doc ); + virtual ~XMLComment(); + + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr); + +private: + XMLComment( const XMLComment& ); // not supported + XMLComment& operator=( const XMLComment& ); // not supported +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXML-2 will happily read or write files without a declaration, + however. + + The text of the declaration isn't interpreted. It is parsed + and written as a string. +*/ +class TINYXML2_LIB XMLDeclaration : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLDeclaration* ToDeclaration() { + return this; + } + virtual const XMLDeclaration* ToDeclaration() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + explicit XMLDeclaration( XMLDocument* doc ); + virtual ~XMLDeclaration(); + + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); + +private: + XMLDeclaration( const XMLDeclaration& ); // not supported + XMLDeclaration& operator=( const XMLDeclaration& ); // not supported +}; + + +/** Any tag that TinyXML-2 doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into XMLUnknowns. +*/ +class TINYXML2_LIB XMLUnknown : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLUnknown* ToUnknown() { + return this; + } + virtual const XMLUnknown* ToUnknown() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + explicit XMLUnknown( XMLDocument* doc ); + virtual ~XMLUnknown(); + + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); + +private: + XMLUnknown( const XMLUnknown& ); // not supported + XMLUnknown& operator=( const XMLUnknown& ); // not supported +}; + + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not XMLNodes. You may only query the + Next() attribute in a list. +*/ +class TINYXML2_LIB XMLAttribute +{ + friend class XMLElement; +public: + /// The name of the attribute. + const char* Name() const; + + /// The value of the attribute. + const char* Value() const; + + /// Gets the line number the attribute is in, if the document was parsed from a file. + int GetLineNum() const { return _parseLineNum; } + + /// The next attribute in the list. + const XMLAttribute* Next() const { + return _next; + } + + /** IntValue interprets the attribute as an integer, and returns the value. + If the value isn't an integer, 0 will be returned. There is no error checking; + use QueryIntValue() if you need error checking. + */ + int IntValue() const { + int i = 0; + QueryIntValue(&i); + return i; + } + + int64_t Int64Value() const { + int64_t i = 0; + QueryInt64Value(&i); + return i; + } + + uint64_t Unsigned64Value() const { + uint64_t i = 0; + QueryUnsigned64Value(&i); + return i; + } + + /// Query as an unsigned integer. See IntValue() + unsigned UnsignedValue() const { + unsigned i=0; + QueryUnsignedValue( &i ); + return i; + } + /// Query as a boolean. See IntValue() + bool BoolValue() const { + bool b=false; + QueryBoolValue( &b ); + return b; + } + /// Query as a double. See IntValue() + double DoubleValue() const { + double d=0; + QueryDoubleValue( &d ); + return d; + } + /// Query as a float. See IntValue() + float FloatValue() const { + float f=0; + QueryFloatValue( &f ); + return f; + } + + /** QueryIntValue interprets the attribute as an integer, and returns the value + in the provided parameter. The function will return XML_SUCCESS on success, + and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful. + */ + XMLError QueryIntValue( int* value ) const; + /// See QueryIntValue + XMLError QueryUnsignedValue( unsigned int* value ) const; + /// See QueryIntValue + XMLError QueryInt64Value(int64_t* value) const; + /// See QueryIntValue + XMLError QueryUnsigned64Value(uint64_t* value) const; + /// See QueryIntValue + XMLError QueryBoolValue( bool* value ) const; + /// See QueryIntValue + XMLError QueryDoubleValue( double* value ) const; + /// See QueryIntValue + XMLError QueryFloatValue( float* value ) const; + + /// Set the attribute to a string value. + void SetAttribute( const char* value ); + /// Set the attribute to value. + void SetAttribute( int value ); + /// Set the attribute to value. + void SetAttribute( unsigned value ); + /// Set the attribute to value. + void SetAttribute(int64_t value); + /// Set the attribute to value. + void SetAttribute(uint64_t value); + /// Set the attribute to value. + void SetAttribute( bool value ); + /// Set the attribute to value. + void SetAttribute( double value ); + /// Set the attribute to value. + void SetAttribute( float value ); + +private: + enum { BUF_SIZE = 200 }; + + XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {} + virtual ~XMLAttribute() {} + + XMLAttribute( const XMLAttribute& ); // not supported + void operator=( const XMLAttribute& ); // not supported + void SetName( const char* name ); + + char* ParseDeep( char* p, bool processEntities, int* curLineNumPtr ); + + mutable StrPair _name; + mutable StrPair _value; + int _parseLineNum; + XMLAttribute* _next; + MemPool* _memPool; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TINYXML2_LIB XMLElement : public XMLNode +{ + friend class XMLDocument; +public: + /// Get the name of an element (which is the Value() of the node.) + const char* Name() const { + return Value(); + } + /// Set the name of the element. + void SetName( const char* str, bool staticMem=false ) { + SetValue( str, staticMem ); + } + + virtual XMLElement* ToElement() { + return this; + } + virtual const XMLElement* ToElement() const { + return this; + } + virtual bool Accept( XMLVisitor* visitor ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none + exists. For example: + + @verbatim + const char* value = ele->Attribute( "foo" ); + @endverbatim + + The 'value' parameter is normally null. However, if specified, + the attribute will only be returned if the 'name' and 'value' + match. This allow you to write code: + + @verbatim + if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar(); + @endverbatim + + rather than: + @verbatim + if ( ele->Attribute( "foo" ) ) { + if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar(); + } + @endverbatim + */ + const char* Attribute( const char* name, const char* value=0 ) const; + + /** Given an attribute name, IntAttribute() returns the value + of the attribute interpreted as an integer. The default + value will be returned if the attribute isn't present, + or if there is an error. (For a method with error + checking, see QueryIntAttribute()). + */ + int IntAttribute(const char* name, int defaultValue = 0) const; + /// See IntAttribute() + unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const; + /// See IntAttribute() + int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const; + /// See IntAttribute() + uint64_t Unsigned64Attribute(const char* name, uint64_t defaultValue = 0) const; + /// See IntAttribute() + bool BoolAttribute(const char* name, bool defaultValue = false) const; + /// See IntAttribute() + double DoubleAttribute(const char* name, double defaultValue = 0) const; + /// See IntAttribute() + float FloatAttribute(const char* name, float defaultValue = 0) const; + + /** Given an attribute name, QueryIntAttribute() returns + XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion + can't be performed, or XML_NO_ATTRIBUTE if the attribute + doesn't exist. If successful, the result of the conversion + will be written to 'value'. If not successful, nothing will + be written to 'value'. This allows you to provide default + value: + + @verbatim + int value = 10; + QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 + @endverbatim + */ + XMLError QueryIntAttribute( const char* name, int* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryIntValue( value ); + } + + /// See QueryIntAttribute() + XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryUnsignedValue( value ); + } + + /// See QueryIntAttribute() + XMLError QueryInt64Attribute(const char* name, int64_t* value) const { + const XMLAttribute* a = FindAttribute(name); + if (!a) { + return XML_NO_ATTRIBUTE; + } + return a->QueryInt64Value(value); + } + + /// See QueryIntAttribute() + XMLError QueryUnsigned64Attribute(const char* name, uint64_t* value) const { + const XMLAttribute* a = FindAttribute(name); + if(!a) { + return XML_NO_ATTRIBUTE; + } + return a->QueryUnsigned64Value(value); + } + + /// See QueryIntAttribute() + XMLError QueryBoolAttribute( const char* name, bool* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryBoolValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryDoubleAttribute( const char* name, double* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryDoubleValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryFloatAttribute( const char* name, float* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryFloatValue( value ); + } + + /// See QueryIntAttribute() + XMLError QueryStringAttribute(const char* name, const char** value) const { + const XMLAttribute* a = FindAttribute(name); + if (!a) { + return XML_NO_ATTRIBUTE; + } + *value = a->Value(); + return XML_SUCCESS; + } + + + + /** Given an attribute name, QueryAttribute() returns + XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion + can't be performed, or XML_NO_ATTRIBUTE if the attribute + doesn't exist. It is overloaded for the primitive types, + and is a generally more convenient replacement of + QueryIntAttribute() and related functions. + + If successful, the result of the conversion + will be written to 'value'. If not successful, nothing will + be written to 'value'. This allows you to provide default + value: + + @verbatim + int value = 10; + QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 + @endverbatim + */ + XMLError QueryAttribute( const char* name, int* value ) const { + return QueryIntAttribute( name, value ); + } + + XMLError QueryAttribute( const char* name, unsigned int* value ) const { + return QueryUnsignedAttribute( name, value ); + } + + XMLError QueryAttribute(const char* name, int64_t* value) const { + return QueryInt64Attribute(name, value); + } + + XMLError QueryAttribute(const char* name, uint64_t* value) const { + return QueryUnsigned64Attribute(name, value); + } + + XMLError QueryAttribute( const char* name, bool* value ) const { + return QueryBoolAttribute( name, value ); + } + + XMLError QueryAttribute( const char* name, double* value ) const { + return QueryDoubleAttribute( name, value ); + } + + XMLError QueryAttribute( const char* name, float* value ) const { + return QueryFloatAttribute( name, value ); + } + + XMLError QueryAttribute(const char* name, const char** value) const { + return QueryStringAttribute(name, value); + } + + /// Sets the named attribute to value. + void SetAttribute( const char* name, const char* value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, int value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, unsigned value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + + /// Sets the named attribute to value. + void SetAttribute(const char* name, int64_t value) { + XMLAttribute* a = FindOrCreateAttribute(name); + a->SetAttribute(value); + } + + /// Sets the named attribute to value. + void SetAttribute(const char* name, uint64_t value) { + XMLAttribute* a = FindOrCreateAttribute(name); + a->SetAttribute(value); + } + + /// Sets the named attribute to value. + void SetAttribute( const char* name, bool value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, double value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, float value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + + /** + Delete an attribute. + */ + void DeleteAttribute( const char* name ); + + /// Return the first attribute in the list. + const XMLAttribute* FirstAttribute() const { + return _rootAttribute; + } + /// Query a specific attribute in the list. + const XMLAttribute* FindAttribute( const char* name ) const; + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the XMLText child + and accessing it directly. + + If the first child of 'this' is a XMLText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + */ + const char* GetText() const; + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, SetText() is limited compared to creating an XMLText child + and mutating it directly. + + If the first child of 'this' is a XMLText, SetText() sets its value to + the given string, otherwise it will create a first child that is an XMLText. + + This is a convenient method for setting the text of simple contained text: + @verbatim + This is text + fooElement->SetText( "Hullaballoo!" ); + Hullaballoo! + @endverbatim + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then it will not change "This is text", but rather prefix it with a text element: + @verbatim + Hullaballoo!This is text + @endverbatim + + For this XML: + @verbatim + + @endverbatim + SetText() will generate + @verbatim + Hullaballoo! + @endverbatim + */ + void SetText( const char* inText ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( int value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( unsigned value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText(int64_t value); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText(uint64_t value); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( bool value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( double value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( float value ); + + /** + Convenience method to query the value of a child text node. This is probably best + shown by example. Given you have a document is this form: + @verbatim + + 1 + 1.4 + + @endverbatim + + The QueryIntText() and similar functions provide a safe and easier way to get to the + "value" of x and y. + + @verbatim + int x = 0; + float y = 0; // types of x and y are contrived for example + const XMLElement* xElement = pointElement->FirstChildElement( "x" ); + const XMLElement* yElement = pointElement->FirstChildElement( "y" ); + xElement->QueryIntText( &x ); + yElement->QueryFloatText( &y ); + @endverbatim + + @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted + to the requested type, and XML_NO_TEXT_NODE if there is no child text to query. + + */ + XMLError QueryIntText( int* ival ) const; + /// See QueryIntText() + XMLError QueryUnsignedText( unsigned* uval ) const; + /// See QueryIntText() + XMLError QueryInt64Text(int64_t* uval) const; + /// See QueryIntText() + XMLError QueryUnsigned64Text(uint64_t* uval) const; + /// See QueryIntText() + XMLError QueryBoolText( bool* bval ) const; + /// See QueryIntText() + XMLError QueryDoubleText( double* dval ) const; + /// See QueryIntText() + XMLError QueryFloatText( float* fval ) const; + + int IntText(int defaultValue = 0) const; + + /// See QueryIntText() + unsigned UnsignedText(unsigned defaultValue = 0) const; + /// See QueryIntText() + int64_t Int64Text(int64_t defaultValue = 0) const; + /// See QueryIntText() + uint64_t Unsigned64Text(uint64_t defaultValue = 0) const; + /// See QueryIntText() + bool BoolText(bool defaultValue = false) const; + /// See QueryIntText() + double DoubleText(double defaultValue = 0) const; + /// See QueryIntText() + float FloatText(float defaultValue = 0) const; + + /** + Convenience method to create a new XMLElement and add it as last (right) + child of this node. Returns the created and inserted element. + */ + XMLElement* InsertNewChildElement(const char* name); + /// See InsertNewChildElement() + XMLComment* InsertNewComment(const char* comment); + /// See InsertNewChildElement() + XMLText* InsertNewText(const char* text); + /// See InsertNewChildElement() + XMLDeclaration* InsertNewDeclaration(const char* text); + /// See InsertNewChildElement() + XMLUnknown* InsertNewUnknown(const char* text); + + + // internal: + enum ElementClosingType { + OPEN, // + CLOSED, // + CLOSING // + }; + ElementClosingType ClosingType() const { + return _closingType; + } + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ); + +private: + XMLElement( XMLDocument* doc ); + virtual ~XMLElement(); + XMLElement( const XMLElement& ); // not supported + void operator=( const XMLElement& ); // not supported + + XMLAttribute* FindOrCreateAttribute( const char* name ); + char* ParseAttributes( char* p, int* curLineNumPtr ); + static void DeleteAttribute( XMLAttribute* attribute ); + XMLAttribute* CreateAttribute(); + + enum { BUF_SIZE = 200 }; + ElementClosingType _closingType; + // The attribute list is ordered; there is no 'lastAttribute' + // because the list needs to be scanned for dupes before adding + // a new attribute. + XMLAttribute* _rootAttribute; +}; + + +enum Whitespace { + PRESERVE_WHITESPACE, + COLLAPSE_WHITESPACE +}; + + +/** A Document binds together all the functionality. + It can be saved, loaded, and printed to the screen. + All Nodes are connected and allocated to a Document. + If the Document is deleted, all its Nodes are also deleted. +*/ +class TINYXML2_LIB XMLDocument : public XMLNode +{ + friend class XMLElement; + // Gives access to SetError and Push/PopDepth, but over-access for everything else. + // Wishing C++ had "internal" scope. + friend class XMLNode; + friend class XMLText; + friend class XMLComment; + friend class XMLDeclaration; + friend class XMLUnknown; +public: + /// constructor + XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE ); + ~XMLDocument(); + + virtual XMLDocument* ToDocument() { + TIXMLASSERT( this == _document ); + return this; + } + virtual const XMLDocument* ToDocument() const { + TIXMLASSERT( this == _document ); + return this; + } + + /** + Parse an XML file from a character string. + Returns XML_SUCCESS (0) on success, or + an errorID. + + You may optionally pass in the 'nBytes', which is + the number of bytes which will be parsed. If not + specified, TinyXML-2 will assume 'xml' points to a + null terminated string. + */ + XMLError Parse( const char* xml, size_t nBytes=static_cast(-1) ); + + /** + Load an XML file from disk. + Returns XML_SUCCESS (0) on success, or + an errorID. + */ + XMLError LoadFile( const char* filename ); + + /** + Load an XML file from disk. You are responsible + for providing and closing the FILE*. + + NOTE: The file should be opened as binary ("rb") + not text in order for TinyXML-2 to correctly + do newline normalization. + + Returns XML_SUCCESS (0) on success, or + an errorID. + */ + XMLError LoadFile( FILE* ); + + /** + Save the XML file to disk. + Returns XML_SUCCESS (0) on success, or + an errorID. + */ + XMLError SaveFile( const char* filename, bool compact = false ); + + /** + Save the XML file to disk. You are responsible + for providing and closing the FILE*. + + Returns XML_SUCCESS (0) on success, or + an errorID. + */ + XMLError SaveFile( FILE* fp, bool compact = false ); + + bool ProcessEntities() const { + return _processEntities; + } + Whitespace WhitespaceMode() const { + return _whitespaceMode; + } + + /** + Returns true if this document has a leading Byte Order Mark of UTF8. + */ + bool HasBOM() const { + return _writeBOM; + } + /** Sets whether to write the BOM when writing the file. + */ + void SetBOM( bool useBOM ) { + _writeBOM = useBOM; + } + + /** Return the root element of DOM. Equivalent to FirstChildElement(). + To get the first node, use FirstChild(). + */ + XMLElement* RootElement() { + return FirstChildElement(); + } + const XMLElement* RootElement() const { + return FirstChildElement(); + } + + /** Print the Document. If the Printer is not provided, it will + print to stdout. If you provide Printer, this can print to a file: + @verbatim + XMLPrinter printer( fp ); + doc.Print( &printer ); + @endverbatim + + Or you can use a printer to print to memory: + @verbatim + XMLPrinter printer; + doc.Print( &printer ); + // printer.CStr() has a const char* to the XML + @endverbatim + */ + void Print( XMLPrinter* streamer=0 ) const; + virtual bool Accept( XMLVisitor* visitor ) const; + + /** + Create a new Element associated with + this Document. The memory for the Element + is managed by the Document. + */ + XMLElement* NewElement( const char* name ); + /** + Create a new Comment associated with + this Document. The memory for the Comment + is managed by the Document. + */ + XMLComment* NewComment( const char* comment ); + /** + Create a new Text associated with + this Document. The memory for the Text + is managed by the Document. + */ + XMLText* NewText( const char* text ); + /** + Create a new Declaration associated with + this Document. The memory for the object + is managed by the Document. + + If the 'text' param is null, the standard + declaration is used.: + @verbatim + + @endverbatim + */ + XMLDeclaration* NewDeclaration( const char* text=0 ); + /** + Create a new Unknown associated with + this Document. The memory for the object + is managed by the Document. + */ + XMLUnknown* NewUnknown( const char* text ); + + /** + Delete a node associated with this document. + It will be unlinked from the DOM. + */ + void DeleteNode( XMLNode* node ); + + /// Clears the error flags. + void ClearError(); + + /// Return true if there was an error parsing the document. + bool Error() const { + return _errorID != XML_SUCCESS; + } + /// Return the errorID. + XMLError ErrorID() const { + return _errorID; + } + const char* ErrorName() const; + static const char* ErrorIDToName(XMLError errorID); + + /** Returns a "long form" error description. A hopefully helpful + diagnostic with location, line number, and/or additional info. + */ + const char* ErrorStr() const; + + /// A (trivial) utility function that prints the ErrorStr() to stdout. + void PrintError() const; + + /// Return the line where the error occurred, or zero if unknown. + int ErrorLineNum() const + { + return _errorLineNum; + } + + /// Clear the document, resetting it to the initial state. + void Clear(); + + /** + Copies this document to a target document. + The target will be completely cleared before the copy. + If you want to copy a sub-tree, see XMLNode::DeepClone(). + + NOTE: that the 'target' must be non-null. + */ + void DeepCopy(XMLDocument* target) const; + + // internal + char* Identify( char* p, XMLNode** node ); + + // internal + void MarkInUse(const XMLNode* const); + + virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { + return 0; + } + virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { + return false; + } + +private: + XMLDocument( const XMLDocument& ); // not supported + void operator=( const XMLDocument& ); // not supported + + bool _writeBOM; + bool _processEntities; + XMLError _errorID; + Whitespace _whitespaceMode; + mutable StrPair _errorStr; + int _errorLineNum; + char* _charBuffer; + int _parseCurLineNum; + int _parsingDepth; + // Memory tracking does add some overhead. + // However, the code assumes that you don't + // have a bunch of unlinked nodes around. + // Therefore it takes less memory to track + // in the document vs. a linked list in the XMLNode, + // and the performance is the same. + DynArray _unlinked; + + MemPoolT< sizeof(XMLElement) > _elementPool; + MemPoolT< sizeof(XMLAttribute) > _attributePool; + MemPoolT< sizeof(XMLText) > _textPool; + MemPoolT< sizeof(XMLComment) > _commentPool; + + static const char* _errorNames[XML_ERROR_COUNT]; + + void Parse(); + + void SetError( XMLError error, int lineNum, const char* format, ... ); + + // Something of an obvious security hole, once it was discovered. + // Either an ill-formed XML or an excessively deep one can overflow + // the stack. Track stack depth, and error out if needed. + class DepthTracker { + public: + explicit DepthTracker(XMLDocument * document) { + this->_document = document; + document->PushDepth(); + } + ~DepthTracker() { + _document->PopDepth(); + } + private: + XMLDocument * _document; + }; + void PushDepth(); + void PopDepth(); + + template + NodeType* CreateUnlinkedNode( MemPoolT& pool ); +}; + +template +inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT& pool ) +{ + TIXMLASSERT( sizeof( NodeType ) == PoolElementSize ); + TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() ); + NodeType* returnNode = new (pool.Alloc()) NodeType( this ); + TIXMLASSERT( returnNode ); + returnNode->_memPool = &pool; + + _unlinked.Push(returnNode); + return returnNode; +} + +/** + A XMLHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2 + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + XMLElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + XMLElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + XMLElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + XMLElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. XMLHandle addresses the verbosity + of such code. A XMLHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + XMLHandle docHandle( &document ); + XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + XMLHandle handleCopy = handle; + @endverbatim + + See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. +*/ +class TINYXML2_LIB XMLHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + explicit XMLHandle( XMLNode* node ) : _node( node ) { + } + /// Create a handle from a node. + explicit XMLHandle( XMLNode& node ) : _node( &node ) { + } + /// Copy constructor + XMLHandle( const XMLHandle& ref ) : _node( ref._node ) { + } + /// Assignment + XMLHandle& operator=( const XMLHandle& ref ) { + _node = ref._node; + return *this; + } + + /// Get the first child of this handle. + XMLHandle FirstChild() { + return XMLHandle( _node ? _node->FirstChild() : 0 ); + } + /// Get the first child element of this handle. + XMLHandle FirstChildElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 ); + } + /// Get the last child of this handle. + XMLHandle LastChild() { + return XMLHandle( _node ? _node->LastChild() : 0 ); + } + /// Get the last child element of this handle. + XMLHandle LastChildElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->LastChildElement( name ) : 0 ); + } + /// Get the previous sibling of this handle. + XMLHandle PreviousSibling() { + return XMLHandle( _node ? _node->PreviousSibling() : 0 ); + } + /// Get the previous sibling element of this handle. + XMLHandle PreviousSiblingElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); + } + /// Get the next sibling of this handle. + XMLHandle NextSibling() { + return XMLHandle( _node ? _node->NextSibling() : 0 ); + } + /// Get the next sibling element of this handle. + XMLHandle NextSiblingElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 ); + } + + /// Safe cast to XMLNode. This can return null. + XMLNode* ToNode() { + return _node; + } + /// Safe cast to XMLElement. This can return null. + XMLElement* ToElement() { + return ( _node ? _node->ToElement() : 0 ); + } + /// Safe cast to XMLText. This can return null. + XMLText* ToText() { + return ( _node ? _node->ToText() : 0 ); + } + /// Safe cast to XMLUnknown. This can return null. + XMLUnknown* ToUnknown() { + return ( _node ? _node->ToUnknown() : 0 ); + } + /// Safe cast to XMLDeclaration. This can return null. + XMLDeclaration* ToDeclaration() { + return ( _node ? _node->ToDeclaration() : 0 ); + } + +private: + XMLNode* _node; +}; + + +/** + A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the + same in all regards, except for the 'const' qualifiers. See XMLHandle for API. +*/ +class TINYXML2_LIB XMLConstHandle +{ +public: + explicit XMLConstHandle( const XMLNode* node ) : _node( node ) { + } + explicit XMLConstHandle( const XMLNode& node ) : _node( &node ) { + } + XMLConstHandle( const XMLConstHandle& ref ) : _node( ref._node ) { + } + + XMLConstHandle& operator=( const XMLConstHandle& ref ) { + _node = ref._node; + return *this; + } + + const XMLConstHandle FirstChild() const { + return XMLConstHandle( _node ? _node->FirstChild() : 0 ); + } + const XMLConstHandle FirstChildElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 ); + } + const XMLConstHandle LastChild() const { + return XMLConstHandle( _node ? _node->LastChild() : 0 ); + } + const XMLConstHandle LastChildElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 ); + } + const XMLConstHandle PreviousSibling() const { + return XMLConstHandle( _node ? _node->PreviousSibling() : 0 ); + } + const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); + } + const XMLConstHandle NextSibling() const { + return XMLConstHandle( _node ? _node->NextSibling() : 0 ); + } + const XMLConstHandle NextSiblingElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 ); + } + + + const XMLNode* ToNode() const { + return _node; + } + const XMLElement* ToElement() const { + return ( _node ? _node->ToElement() : 0 ); + } + const XMLText* ToText() const { + return ( _node ? _node->ToText() : 0 ); + } + const XMLUnknown* ToUnknown() const { + return ( _node ? _node->ToUnknown() : 0 ); + } + const XMLDeclaration* ToDeclaration() const { + return ( _node ? _node->ToDeclaration() : 0 ); + } + +private: + const XMLNode* _node; +}; + + +/** + Printing functionality. The XMLPrinter gives you more + options than the XMLDocument::Print() method. + + It can: + -# Print to memory. + -# Print to a file you provide. + -# Print XML without a XMLDocument. + + Print to Memory + + @verbatim + XMLPrinter printer; + doc.Print( &printer ); + SomeFunction( printer.CStr() ); + @endverbatim + + Print to a File + + You provide the file pointer. + @verbatim + XMLPrinter printer( fp ); + doc.Print( &printer ); + @endverbatim + + Print without a XMLDocument + + When loading, an XML parser is very useful. However, sometimes + when saving, it just gets in the way. The code is often set up + for streaming, and constructing the DOM is just overhead. + + The Printer supports the streaming case. The following code + prints out a trivially simple XML file without ever creating + an XML document. + + @verbatim + XMLPrinter printer( fp ); + printer.OpenElement( "foo" ); + printer.PushAttribute( "foo", "bar" ); + printer.CloseElement(); + @endverbatim +*/ +class TINYXML2_LIB XMLPrinter : public XMLVisitor +{ +public: + /** Construct the printer. If the FILE* is specified, + this will print to the FILE. Else it will print + to memory, and the result is available in CStr(). + If 'compact' is set to true, then output is created + with only required whitespace and newlines. + */ + XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 ); + virtual ~XMLPrinter() {} + + /** If streaming, write the BOM and declaration. */ + void PushHeader( bool writeBOM, bool writeDeclaration ); + /** If streaming, start writing an element. + The element must be closed with CloseElement() + */ + void OpenElement( const char* name, bool compactMode=false ); + /// If streaming, add an attribute to an open element. + void PushAttribute( const char* name, const char* value ); + void PushAttribute( const char* name, int value ); + void PushAttribute( const char* name, unsigned value ); + void PushAttribute( const char* name, int64_t value ); + void PushAttribute( const char* name, uint64_t value ); + void PushAttribute( const char* name, bool value ); + void PushAttribute( const char* name, double value ); + /// If streaming, close the Element. + virtual void CloseElement( bool compactMode=false ); + + /// Add a text node. + void PushText( const char* text, bool cdata=false ); + /// Add a text node from an integer. + void PushText( int value ); + /// Add a text node from an unsigned. + void PushText( unsigned value ); + /// Add a text node from a signed 64bit integer. + void PushText( int64_t value ); + /// Add a text node from an unsigned 64bit integer. + void PushText( uint64_t value ); + /// Add a text node from a bool. + void PushText( bool value ); + /// Add a text node from a float. + void PushText( float value ); + /// Add a text node from a double. + void PushText( double value ); + + /// Add a comment + void PushComment( const char* comment ); + + void PushDeclaration( const char* value ); + void PushUnknown( const char* value ); + + virtual bool VisitEnter( const XMLDocument& /*doc*/ ); + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { + return true; + } + + virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); + virtual bool VisitExit( const XMLElement& element ); + + virtual bool Visit( const XMLText& text ); + virtual bool Visit( const XMLComment& comment ); + virtual bool Visit( const XMLDeclaration& declaration ); + virtual bool Visit( const XMLUnknown& unknown ); + + /** + If in print to memory mode, return a pointer to + the XML file in memory. + */ + const char* CStr() const { + return _buffer.Mem(); + } + /** + If in print to memory mode, return the size + of the XML file in memory. (Note the size returned + includes the terminating null.) + */ + int CStrSize() const { + return _buffer.Size(); + } + /** + If in print to memory mode, reset the buffer to the + beginning. + */ + void ClearBuffer( bool resetToFirstElement = true ) { + _buffer.Clear(); + _buffer.Push(0); + _firstElement = resetToFirstElement; + } + +protected: + virtual bool CompactMode( const XMLElement& ) { return _compactMode; } + + /** Prints out the space before an element. You may override to change + the space and tabs used. A PrintSpace() override should call Print(). + */ + virtual void PrintSpace( int depth ); + virtual void Print( const char* format, ... ); + virtual void Write( const char* data, size_t size ); + virtual void Putc( char ch ); + + inline void Write(const char* data) { Write(data, strlen(data)); } + + void SealElementIfJustOpened(); + bool _elementJustOpened; + DynArray< const char*, 10 > _stack; + +private: + /** + Prepares to write a new node. This includes sealing an element that was + just opened, and writing any whitespace necessary if not in compact mode. + */ + void PrepareForNewNode( bool compactMode ); + void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. + + bool _firstElement; + FILE* _fp; + int _depth; + int _textDepth; + bool _processEntities; + bool _compactMode; + + enum { + ENTITY_RANGE = 64, + BUF_SIZE = 200 + }; + bool _entityFlag[ENTITY_RANGE]; + bool _restrictedEntityFlag[ENTITY_RANGE]; + + DynArray< char, 20 > _buffer; + + // Prohibit cloning, intentionally not implemented + XMLPrinter( const XMLPrinter& ); + XMLPrinter& operator=( const XMLPrinter& ); +}; + + +} // tinyxml2 + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + +#endif // TINYXML2_INCLUDED diff --git a/rtems/tinyxml2/xmltest.cpp b/rtems/tinyxml2/xmltest.cpp new file mode 100644 index 0000000..b945fca --- /dev/null +++ b/rtems/tinyxml2/xmltest.cpp @@ -0,0 +1,2606 @@ +/* + * Simple RTEMS configuration + */ + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_UNLIMITED_OBJECTS +#define CONFIGURE_UNIFIED_WORK_AREAS + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +/* filesystem */ +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM +#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 40 +#define CONFIGURE_IMFS_MEMFILE_BYTES_PER_BLOCK 512 + +#include + + + +#if defined( _MSC_VER ) + #if !defined( _CRT_SECURE_NO_WARNINGS ) + #define _CRT_SECURE_NO_WARNINGS // This test file is not intended to be secure. + #endif +#endif + +#include "tinyxml2.h" +#include +#include +#include +#include + +#include +#include + +#if defined( _MSC_VER ) || defined (WIN32) + #include + #define WIN32_LEAN_AND_MEAN + #include + _CrtMemState startMemState; + _CrtMemState endMemState; +#else + #include + #include +#endif + +using namespace tinyxml2; +using namespace std; +int gPass = 0; +int gFail = 0; + + +bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true, bool extraNL=false ) +{ + bool pass; + if ( !expected && !found ) + pass = true; + else if ( !expected || !found ) + pass = false; + else + pass = !strcmp( expected, found ); + if ( pass ) + printf ("[pass]"); + else + printf ("[fail]"); + + if ( !echo ) { + printf (" %s\n", testString); + } + else { + if ( extraNL ) { + printf( " %s\n", testString ); + printf( "%s\n", expected ); + printf( "%s\n", found ); + } + else { + printf (" %s [%s][%s]\n", testString, expected, found); + } + } + + if ( pass ) + ++gPass; + else + ++gFail; + return pass; +} + +bool XMLTest(const char* testString, XMLError expected, XMLError found, bool echo = true, bool extraNL = false) +{ + return XMLTest(testString, XMLDocument::ErrorIDToName(expected), XMLDocument::ErrorIDToName(found), echo, extraNL); +} + +bool XMLTest(const char* testString, bool expected, bool found, bool echo = true, bool extraNL = false) +{ + return XMLTest(testString, expected ? "true" : "false", found ? "true" : "false", echo, extraNL); +} + +template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true ) +{ + bool pass = ( expected == found ); + if ( pass ) + printf ("[pass]"); + else + printf ("[fail]"); + + if ( !echo ) + printf (" %s\n", testString); + else { + char expectedAsString[64]; + XMLUtil::ToStr(expected, expectedAsString, sizeof(expectedAsString)); + + char foundAsString[64]; + XMLUtil::ToStr(found, foundAsString, sizeof(foundAsString)); + + printf (" %s [%s][%s]\n", testString, expectedAsString, foundAsString ); + } + + if ( pass ) + ++gPass; + else + ++gFail; + return pass; +} + + +void NullLineEndings( char* p ) +{ + while( p && *p ) { + if ( *p == '\n' || *p == '\r' ) { + *p = 0; + return; + } + ++p; + } +} + + +int example_1() +{ + XMLDocument doc; + doc.LoadFile( "resources/dream.xml" ); + + return doc.ErrorID(); +} +/** @page Example_1 Load an XML File + * @dontinclude ./xmltest.cpp + * Basic XML file loading. + * The basic syntax to load an XML file from + * disk and check for an error. (ErrorID() + * will return 0 for no error.) + * @skip example_1() + * @until } + */ + + +int example_2() +{ + static const char* xml = ""; + XMLDocument doc; + doc.Parse( xml ); + + return doc.ErrorID(); +} +/** @page Example_2 Parse an XML from char buffer + * @dontinclude ./xmltest.cpp + * Basic XML string parsing. + * The basic syntax to parse an XML for + * a char* and check for an error. (ErrorID() + * will return 0 for no error.) + * @skip example_2() + * @until } + */ + + +int example_3() +{ + static const char* xml = + "" + "" + "" + "A Midsummer Night's Dream" + ""; + + XMLDocument doc; + doc.Parse( xml ); + + XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" ); + const char* title = titleElement->GetText(); + printf( "Name of play (1): %s\n", title ); + + XMLText* textNode = titleElement->FirstChild()->ToText(); + title = textNode->Value(); + printf( "Name of play (2): %s\n", title ); + + return doc.ErrorID(); +} +/** @page Example_3 Get information out of XML + @dontinclude ./xmltest.cpp + In this example, we navigate a simple XML + file, and read some interesting text. Note + that this example doesn't use error + checking; working code should check for null + pointers when walking an XML tree, or use + XMLHandle. + + (The XML is an excerpt from "dream.xml"). + + @skip example_3() + @until "; + + The structure of the XML file is: + +
    +
  • (declaration)
  • +
  • (dtd stuff)
  • +
  • Element "PLAY"
  • +
      +
    • Element "TITLE"
    • +
        +
      • Text "A Midsummer Night's Dream"
      • +
      +
    +
+ + For this example, we want to print out the + title of the play. The text of the title (what + we want) is child of the "TITLE" element which + is a child of the "PLAY" element. + + We want to skip the declaration and dtd, so the + method FirstChildElement() is a good choice. The + FirstChildElement() of the Document is the "PLAY" + Element, the FirstChildElement() of the "PLAY" Element + is the "TITLE" Element. + + @until ( "TITLE" ); + + We can then use the convenience function GetText() + to get the title of the play. + + @until title ); + + Text is just another Node in the XML DOM. And in + fact you should be a little cautious with it, as + text nodes can contain elements. + + @verbatim + Consider: A Midsummer Night's Dream + @endverbatim + + It is more correct to actually query the Text Node + if in doubt: + + @until title ); + + Noting that here we use FirstChild() since we are + looking for XMLText, not an element, and ToText() + is a cast from a Node to a XMLText. +*/ + + +bool example_4() +{ + static const char* xml = + "" + " " + " " + " 2" + " " + ""; + + XMLDocument doc; + doc.Parse( xml ); + + int v0 = 0; + int v1 = 0; + + XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" ); + attributeApproachElement->QueryIntAttribute( "v", &v0 ); + + XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" ); + textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 ); + + printf( "Both values are the same: %d and %d\n", v0, v1 ); + + return !doc.Error() && ( v0 == v1 ); +} +/** @page Example_4 Read attributes and text information. + @dontinclude ./xmltest.cpp + + There are fundamentally 2 ways of writing a key-value + pair into an XML file. (Something that's always annoyed + me about XML.) Either by using attributes, or by writing + the key name into an element and the value into + the text node wrapped by the element. Both approaches + are illustrated in this example, which shows two ways + to encode the value "2" into the key "v": + + @skip example_4() + @until ""; + + TinyXML-2 has accessors for both approaches. + + When using an attribute, you navigate to the XMLElement + with that attribute and use the QueryIntAttribute() + group of methods. (Also QueryFloatAttribute(), etc.) + + @skip XMLElement* attributeApproachElement + @until &v0 ); + + When using the text approach, you need to navigate + down one more step to the XMLElement that contains + the text. Note the extra FirstChildElement( "v" ) + in the code below. The value of the text can then + be safely queried with the QueryIntText() group + of methods. (Also QueryFloatText(), etc.) + + @skip XMLElement* textApproachElement + @until &v1 ); +*/ + +/* + * Hello world example + */ +#include +#include +#include + +rtems_task Init( + rtems_task_argument ignored +) +//int main( int argc, const char ** argv ) +{ + int argc = 0; + const char **argv = NULL; + + #if defined( _MSC_VER ) && defined( TINYXML2_DEBUG ) + _CrtMemCheckpoint( &startMemState ); + // Enable MS Visual C++ debug heap memory leaks dump on exit + _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); + { + int leaksOnStart = _CrtDumpMemoryLeaks(); + XMLTest( "No leaks on start?", FALSE, leaksOnStart ); + } + #endif + + { + TIXMLASSERT( true ); + } + + if ( argc > 1 ) { + XMLDocument* doc = new XMLDocument(); + clock_t startTime = clock(); + doc->LoadFile( argv[1] ); + clock_t loadTime = clock(); + int errorID = doc->ErrorID(); + delete doc; doc = 0; + clock_t deleteTime = clock(); + + printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID ); + if ( !errorID ) { + printf( "Load time=%u\n", (unsigned)(loadTime - startTime) ); + printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) ); + printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) ); + } + exit(0); + } + + FILE* fp = fopen( "resources/dream.xml", "r" ); + if ( !fp ) { + printf( "Error opening test file 'dream.xml'.\n" + "Is your working directory the same as where \n" + "the xmltest.cpp and dream.xml file are?\n\n" + #if defined( _MSC_VER ) + "In windows Visual Studio you may need to set\n" + "Properties->Debugging->Working Directory to '..'\n" + #endif + ); + exit( 1 ); + } + fclose( fp ); + + XMLTest( "Example_1", 0, example_1() ); + XMLTest( "Example_2", 0, example_2() ); + XMLTest( "Example_3", 0, example_3() ); + XMLTest( "Example_4", true, example_4() ); + + /* ------ Example 2: Lookup information. ---- */ + + { + static const char* test[] = { "", + "", + "", + "", + "", + "", + " \n \n ", + "", + "", + "Text inside element.", + "", + "Text inside and bolded in the element.", + "Text inside and bolded in the element.", + "This & That.", + "", + 0 + }; + for( int i=0; test[i]; ++i ) { + XMLDocument doc; + doc.Parse( test[i] ); + XMLTest( "Element test", false, doc.Error() ); + doc.Print(); + printf( "----------------------------------------------\n" ); + } + } +#if 1 + { + static const char* test = ""; + + XMLDocument doc; + doc.Parse( test ); + XMLTest( "Hello world declaration", false, doc.Error() ); + doc.Print(); + } + + { + // This test is pre-test for the next one + // (where Element1 is inserted "after itself". + // This code didn't use to crash. + XMLDocument doc; + XMLElement* element1 = doc.NewElement("Element1"); + XMLElement* element2 = doc.NewElement("Element2"); + doc.InsertEndChild(element1); + doc.InsertEndChild(element2); + doc.InsertAfterChild(element2, element2); + doc.InsertAfterChild(element2, element2); + } + + { + XMLDocument doc; + XMLElement* element1 = doc.NewElement("Element1"); + XMLElement* element2 = doc.NewElement("Element2"); + doc.InsertEndChild(element1); + doc.InsertEndChild(element2); + + // This insertion "after itself" + // used to cause invalid memory access and crash + doc.InsertAfterChild(element1, element1); + doc.InsertAfterChild(element1, element1); + doc.InsertAfterChild(element2, element2); + doc.InsertAfterChild(element2, element2); + } + + { + static const char* test = "Text before."; + XMLDocument doc; + doc.Parse( test ); + XMLTest( "Element text before", false, doc.Error() ); + XMLElement* root = doc.FirstChildElement(); + XMLElement* newElement = doc.NewElement( "Subelement" ); + root->InsertEndChild( newElement ); + doc.Print(); + } + { + XMLDocument* doc = new XMLDocument(); + static const char* test = ""; + doc->Parse( test ); + XMLTest( "Element with sub element", false, doc->Error() ); + delete doc; + } + { + // Test: Programmatic DOM nodes insertion return values + XMLDocument doc; + + XMLNode* first = doc.NewElement( "firstElement" ); + XMLTest( "New element", true, first != 0 ); + XMLNode* firstAfterInsertion = doc.InsertFirstChild( first ); + XMLTest( "New element inserted first", true, firstAfterInsertion == first ); + + XMLNode* last = doc.NewElement( "lastElement" ); + XMLTest( "New element", true, last != 0 ); + XMLNode* lastAfterInsertion = doc.InsertEndChild( last ); + XMLTest( "New element inserted last", true, lastAfterInsertion == last ); + + XMLNode* middle = doc.NewElement( "middleElement" ); + XMLTest( "New element", true, middle != 0 ); + XMLNode* middleAfterInsertion = doc.InsertAfterChild( first, middle ); + XMLTest( "New element inserted middle", true, middleAfterInsertion == middle ); + } + { + // Test: Programmatic DOM + // Build: + // + // + // + // + // & Text! + // + + XMLDocument* doc = new XMLDocument(); + XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) ); + + XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) }; + for( int i=0; i<3; ++i ) { + sub[i]->SetAttribute( "attrib", i ); + } + element->InsertEndChild( sub[2] ); + + const int dummyInitialValue = 1000; + int dummyValue = dummyInitialValue; + + XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) ); + comment->SetUserData(&dummyValue); + element->InsertAfterChild( comment, sub[0] ); + element->InsertAfterChild( sub[0], sub[1] ); + sub[2]->InsertFirstChild( doc->NewText( "& Text!" )); + doc->Print(); + XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() ); + XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) ); + XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) ); + XMLTest( "Programmatic DOM", "& Text!", + doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() ); + XMLTest("User data - pointer", true, &dummyValue == comment->GetUserData(), false); + XMLTest("User data - value behind pointer", dummyInitialValue, dummyValue, false); + + // And now deletion: + element->DeleteChild( sub[2] ); + doc->DeleteNode( comment ); + + element->FirstChildElement()->SetAttribute( "attrib", true ); + element->LastChildElement()->DeleteAttribute( "attrib" ); + + XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) ); + const int defaultIntValue = 10; + const int replacementIntValue = 20; + int value1 = defaultIntValue; + int value2 = doc->FirstChildElement()->LastChildElement()->IntAttribute( "attrib", replacementIntValue ); + XMLError result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value1 ); + XMLTest( "Programmatic DOM", XML_NO_ATTRIBUTE, result ); + XMLTest( "Programmatic DOM", defaultIntValue, value1 ); + XMLTest( "Programmatic DOM", replacementIntValue, value2 ); + + doc->Print(); + + { + XMLPrinter streamer; + doc->Print( &streamer ); + printf( "%s", streamer.CStr() ); + } + { + XMLPrinter streamer( 0, true ); + doc->Print( &streamer ); + XMLTest( "Compact mode", "", streamer.CStr(), false ); + } + doc->SaveFile( "./resources/out/pretty.xml" ); + XMLTest( "Save pretty.xml", false, doc->Error() ); + doc->SaveFile( "./resources/out/compact.xml", true ); + XMLTest( "Save compact.xml", false, doc->Error() ); + delete doc; + } + { + // Test: Dream + // XML1 : 1,187,569 bytes in 31,209 allocations + // XML2 : 469,073 bytes in 323 allocations + //int newStart = gNew; + XMLDocument doc; + doc.LoadFile( "resources/dream.xml" ); + XMLTest( "Load dream.xml", false, doc.Error() ); + + doc.SaveFile( "resources/out/dreamout.xml" ); + XMLTest( "Save dreamout.xml", false, doc.Error() ); + doc.PrintError(); + + XMLTest( "Dream", "xml version=\"1.0\"", + doc.FirstChild()->ToDeclaration()->Value() ); + XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() != 0 ); + XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"", + doc.FirstChild()->NextSibling()->ToUnknown()->Value() ); + XMLTest( "Dream", "And Robin shall restore amends.", + doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() ); + XMLTest( "Dream", "And Robin shall restore amends.", + doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() ); + + XMLDocument doc2; + doc2.LoadFile( "resources/out/dreamout.xml" ); + XMLTest( "Load dreamout.xml", false, doc2.Error() ); + XMLTest( "Dream-out", "xml version=\"1.0\"", + doc2.FirstChild()->ToDeclaration()->Value() ); + XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() != 0 ); + XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"", + doc2.FirstChild()->NextSibling()->ToUnknown()->Value() ); + XMLTest( "Dream-out", "And Robin shall restore amends.", + doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() ); + + //gNewTotal = gNew - newStart; + } + + + { + const char* error = "\n" + "\n" + " \n" + ""; + + XMLDocument doc; + doc.Parse( error ); + XMLTest( "Bad XML", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() ); + const char* errorStr = doc.ErrorStr(); + XMLTest("Formatted error string", + "Error=XML_ERROR_PARSING_ATTRIBUTE ErrorID=7 (0x7) Line number=3: XMLElement name=wrong", + errorStr); + } + + { + const char* str = ""; + + XMLDocument doc; + doc.Parse( str ); + XMLTest( "Top level attributes", false, doc.Error() ); + + XMLElement* ele = doc.FirstChildElement(); + + int iVal; + XMLError result; + double dVal; + + result = ele->QueryDoubleAttribute( "attr0", &dVal ); + XMLTest( "Query attribute: int as double", XML_SUCCESS, result); + XMLTest( "Query attribute: int as double", 1, (int)dVal ); + XMLTest( "Query attribute: int as double", 1, (int)ele->DoubleAttribute("attr0")); + + result = ele->QueryDoubleAttribute( "attr1", &dVal ); + XMLTest( "Query attribute: double as double", XML_SUCCESS, result); + XMLTest( "Query attribute: double as double", 2.0, dVal ); + XMLTest( "Query attribute: double as double", 2.0, ele->DoubleAttribute("attr1") ); + + result = ele->QueryIntAttribute( "attr1", &iVal ); + XMLTest( "Query attribute: double as int", XML_SUCCESS, result); + XMLTest( "Query attribute: double as int", 2, iVal ); + + result = ele->QueryIntAttribute( "attr2", &iVal ); + XMLTest( "Query attribute: not a number", XML_WRONG_ATTRIBUTE_TYPE, result ); + XMLTest( "Query attribute: not a number", 4.0, ele->DoubleAttribute("attr2", 4.0) ); + + result = ele->QueryIntAttribute( "bar", &iVal ); + XMLTest( "Query attribute: does not exist", XML_NO_ATTRIBUTE, result ); + XMLTest( "Query attribute: does not exist", true, ele->BoolAttribute("bar", true) ); + } + + { + const char* str = ""; + + XMLDocument doc; + doc.Parse( str ); + XMLTest( "Empty top element", false, doc.Error() ); + + XMLElement* ele = doc.FirstChildElement(); + + int iVal, iVal2; + double dVal, dVal2; + + ele->SetAttribute( "str", "strValue" ); + ele->SetAttribute( "int", 1 ); + ele->SetAttribute( "double", -1.0 ); + + const char* answer = 0; + ele->QueryAttribute("str", &answer); + XMLTest("Query char attribute", "strValue", answer); + + const char* cStr = ele->Attribute( "str" ); + { + XMLError queryResult = ele->QueryIntAttribute( "int", &iVal ); + XMLTest( "Query int attribute", XML_SUCCESS, queryResult); + } + { + XMLError queryResult = ele->QueryDoubleAttribute( "double", &dVal ); + XMLTest( "Query double attribute", XML_SUCCESS, queryResult); + } + + { + XMLError queryResult = ele->QueryAttribute( "int", &iVal2 ); + XMLTest( "Query int attribute generic", (int)XML_SUCCESS, queryResult); + } + { + XMLError queryResult = ele->QueryAttribute( "double", &dVal2 ); + XMLTest( "Query double attribute generic", (int)XML_SUCCESS, queryResult); + } + + XMLTest( "Attribute match test", "strValue", ele->Attribute( "str", "strValue" ) ); + XMLTest( "Attribute round trip. c-string.", "strValue", cStr ); + XMLTest( "Attribute round trip. int.", 1, iVal ); + XMLTest( "Attribute round trip. double.", -1, (int)dVal ); + XMLTest( "Alternate query", true, iVal == iVal2 ); + XMLTest( "Alternate query", true, dVal == dVal2 ); + XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") ); + XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") ); + } + + { + XMLDocument doc; + doc.LoadFile( "resources/utf8test.xml" ); + XMLTest( "Load utf8test.xml", false, doc.Error() ); + + // Get the attribute "value" from the "Russian" element and check it. + XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" ); + const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU, + 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 }; + + XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) ); + + const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U, + 0xd1U, 0x81U, 0xd1U, 0x81U, + 0xd0U, 0xbaU, 0xd0U, 0xb8U, + 0xd0U, 0xb9U, 0 }; + const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>"; + + XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText(); + XMLTest( "UTF-8: Browsing russian element name.", + russianText, + text->Value() ); + + // Now try for a round trip. + doc.SaveFile( "resources/out/utf8testout.xml" ); + XMLTest( "UTF-8: Save testout.xml", false, doc.Error() ); + + // Check the round trip. + bool roundTripOkay = false; + + FILE* saved = fopen( "resources/out/utf8testout.xml", "r" ); + XMLTest( "UTF-8: Open utf8testout.xml", true, saved != 0 ); + + FILE* verify = fopen( "resources/utf8testverify.xml", "r" ); + XMLTest( "UTF-8: Open utf8testverify.xml", true, verify != 0 ); + + if ( saved && verify ) + { + roundTripOkay = true; + char verifyBuf[256]; + while ( fgets( verifyBuf, 256, verify ) ) + { + char savedBuf[256]; + fgets( savedBuf, 256, saved ); + NullLineEndings( verifyBuf ); + NullLineEndings( savedBuf ); + + if ( strcmp( verifyBuf, savedBuf ) ) + { + printf( "verify:%s<\n", verifyBuf ); + printf( "saved :%s<\n", savedBuf ); + roundTripOkay = false; + break; + } + } + } + if ( saved ) + fclose( saved ); + if ( verify ) + fclose( verify ); + XMLTest( "UTF-8: Verified multi-language round trip.", true, roundTripOkay ); + } + + // --------GetText()----------- + { + const char* str = "This is text"; + XMLDocument doc; + doc.Parse( str ); + XMLTest( "Double whitespace", false, doc.Error() ); + const XMLElement* element = doc.RootElement(); + + XMLTest( "GetText() normal use.", "This is text", element->GetText() ); + + str = "This is text"; + doc.Parse( str ); + XMLTest( "Bold text simulation", false, doc.Error() ); + element = doc.RootElement(); + + XMLTest( "GetText() contained element.", element->GetText() == 0, true ); + } + + + // --------SetText()----------- + { + const char* str = ""; + XMLDocument doc; + doc.Parse( str ); + XMLTest( "Empty closed element", false, doc.Error() ); + XMLElement* element = doc.RootElement(); + + element->SetText("darkness."); + XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() ); + + element->SetText("blue flame."); + XMLTest( "SetText() replace.", "blue flame.", element->GetText() ); + + str = ""; + doc.Parse( str ); + XMLTest( "Empty self-closed element", false, doc.Error() ); + element = doc.RootElement(); + + element->SetText("The driver"); + XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() ); + + element->SetText("horses"); + XMLTest( "SetText() replace with tag-like text.", "horses", element->GetText() ); + //doc.Print(); + + str = "Text in nested element"; + doc.Parse( str ); + XMLTest( "Text in nested element", false, doc.Error() ); + element = doc.RootElement(); + + element->SetText("wolves"); + XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() ); + + str = ""; + doc.Parse( str ); + XMLTest( "Empty self-closed element round 2", false, doc.Error() ); + element = doc.RootElement(); + + element->SetText( "str" ); + XMLTest( "SetText types", "str", element->GetText() ); + + element->SetText( 1 ); + XMLTest( "SetText types", "1", element->GetText() ); + + element->SetText( 1U ); + XMLTest( "SetText types", "1", element->GetText() ); + + element->SetText( true ); + XMLTest( "SetText types", "true", element->GetText() ); + + element->SetText( 1.5f ); + XMLTest( "SetText types", "1.5", element->GetText() ); + + element->SetText( 1.5 ); + XMLTest( "SetText types", "1.5", element->GetText() ); + } + + // ---------- Attributes --------- + { + static const int64_t BIG = -123456789012345678; + static const uint64_t BIG_POS = 123456789012345678; + XMLDocument doc; + XMLElement* element = doc.NewElement("element"); + doc.InsertFirstChild(element); + + { + element->SetAttribute("attrib", int(-100)); + { + int v = 0; + XMLError queryResult = element->QueryIntAttribute("attrib", &v); + XMLTest("Attribute: int", XML_SUCCESS, queryResult, true); + XMLTest("Attribute: int", -100, v, true); + } + { + int v = 0; + XMLError queryResult = element->QueryAttribute("attrib", &v); + XMLTest("Attribute: int", (int)XML_SUCCESS, queryResult, true); + XMLTest("Attribute: int", -100, v, true); + } + XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true); + } + { + element->SetAttribute("attrib", unsigned(100)); + { + unsigned v = 0; + XMLError queryResult = element->QueryUnsignedAttribute("attrib", &v); + XMLTest("Attribute: unsigned", XML_SUCCESS, queryResult, true); + XMLTest("Attribute: unsigned", unsigned(100), v, true); + } + { + unsigned v = 0; + XMLError queryResult = element->QueryAttribute("attrib", &v); + XMLTest("Attribute: unsigned", (int)XML_SUCCESS, queryResult, true); + XMLTest("Attribute: unsigned", unsigned(100), v, true); + } + { + const char* v = "failed"; + XMLError queryResult = element->QueryStringAttribute("not-attrib", &v); + XMLTest("Attribute: string default", false, queryResult == XML_SUCCESS); + queryResult = element->QueryStringAttribute("attrib", &v); + XMLTest("Attribute: string", XML_SUCCESS, queryResult, true); + XMLTest("Attribute: string", "100", v); + } + XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true); + } + { + element->SetAttribute("attrib", BIG); + { + int64_t v = 0; + XMLError queryResult = element->QueryInt64Attribute("attrib", &v); + XMLTest("Attribute: int64_t", XML_SUCCESS, queryResult, true); + XMLTest("Attribute: int64_t", BIG, v, true); + } + { + int64_t v = 0; + XMLError queryResult = element->QueryAttribute("attrib", &v); + XMLTest("Attribute: int64_t", (int)XML_SUCCESS, queryResult, true); + XMLTest("Attribute: int64_t", BIG, v, true); + } + XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true); + } + { + element->SetAttribute("attrib", BIG_POS); + { + uint64_t v = 0; + XMLError queryResult = element->QueryUnsigned64Attribute("attrib", &v); + XMLTest("Attribute: uint64_t", XML_SUCCESS, queryResult, true); + XMLTest("Attribute: uint64_t", BIG_POS, v, true); + } + { + uint64_t v = 0; + XMLError queryResult = element->QueryAttribute("attrib", &v); + XMLTest("Attribute: uint64_t", (int)XML_SUCCESS, queryResult, true); + XMLTest("Attribute: uint64_t", BIG_POS, v, true); + } + XMLTest("Attribute: uint64_t", BIG_POS, element->Unsigned64Attribute("attrib"), true); + } + { + element->SetAttribute("attrib", true); + { + bool v = false; + XMLError queryResult = element->QueryBoolAttribute("attrib", &v); + XMLTest("Attribute: bool", XML_SUCCESS, queryResult, true); + XMLTest("Attribute: bool", true, v, true); + } + { + bool v = false; + XMLError queryResult = element->QueryAttribute("attrib", &v); + XMLTest("Attribute: bool", (int)XML_SUCCESS, queryResult, true); + XMLTest("Attribute: bool", true, v, true); + } + XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true); + } + { + element->SetAttribute("attrib", true); + const char* result = element->Attribute("attrib"); + XMLTest("Bool true is 'true'", "true", result); + + XMLUtil::SetBoolSerialization("1", "0"); + element->SetAttribute("attrib", true); + result = element->Attribute("attrib"); + XMLTest("Bool true is '1'", "1", result); + + XMLUtil::SetBoolSerialization(0, 0); + } + { + element->SetAttribute("attrib", 100.0); + { + double v = 0; + XMLError queryResult = element->QueryDoubleAttribute("attrib", &v); + XMLTest("Attribute: double", XML_SUCCESS, queryResult, true); + XMLTest("Attribute: double", 100.0, v, true); + } + { + double v = 0; + XMLError queryResult = element->QueryAttribute("attrib", &v); + XMLTest("Attribute: bool", (int)XML_SUCCESS, queryResult, true); + XMLTest("Attribute: double", 100.0, v, true); + } + XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true); + } + { + element->SetAttribute("attrib", 100.0f); + { + float v = 0; + XMLError queryResult = element->QueryFloatAttribute("attrib", &v); + XMLTest("Attribute: float", XML_SUCCESS, queryResult, true); + XMLTest("Attribute: float", 100.0f, v, true); + } + { + float v = 0; + XMLError queryResult = element->QueryAttribute("attrib", &v); + XMLTest("Attribute: float", (int)XML_SUCCESS, queryResult, true); + XMLTest("Attribute: float", 100.0f, v, true); + } + XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true); + } + { + element->SetText(BIG); + int64_t v = 0; + XMLError queryResult = element->QueryInt64Text(&v); + XMLTest("Element: int64_t", XML_SUCCESS, queryResult, true); + XMLTest("Element: int64_t", BIG, v, true); + } + { + element->SetText(BIG_POS); + uint64_t v = 0; + XMLError queryResult = element->QueryUnsigned64Text(&v); + XMLTest("Element: uint64_t", XML_SUCCESS, queryResult, true); + XMLTest("Element: uint64_t", BIG_POS, v, true); + } + } + + // ---------- XMLPrinter stream mode ------ + { + { + FILE* printerfp = fopen("resources/out/printer.xml", "w"); + XMLTest("Open printer.xml", true, printerfp != 0); + XMLPrinter printer(printerfp); + printer.OpenElement("foo"); + printer.PushAttribute("attrib-text", "text"); + printer.PushAttribute("attrib-int", int(1)); + printer.PushAttribute("attrib-unsigned", unsigned(2)); + printer.PushAttribute("attrib-int64", int64_t(3)); + printer.PushAttribute("attrib-uint64", uint64_t(37)); + printer.PushAttribute("attrib-bool", true); + printer.PushAttribute("attrib-double", 4.0); + printer.CloseElement(); + fclose(printerfp); + } + { + XMLDocument doc; + doc.LoadFile("resources/out/printer.xml"); + XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true); + + const XMLDocument& cdoc = doc; + + const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text"); + XMLTest("attrib-text", "text", attrib->Value(), true); + attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int"); + XMLTest("attrib-int", int(1), attrib->IntValue(), true); + attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned"); + XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true); + attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64"); + XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true); + attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-uint64"); + XMLTest("attrib-uint64", uint64_t(37), attrib->Unsigned64Value(), true); + attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool"); + XMLTest("attrib-bool", true, attrib->BoolValue(), true); + attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double"); + XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true); + } + // Add API_testcatse :PushDeclaration();PushText();PushComment() + { + FILE* fp1 = fopen("resources/out/printer_1.xml", "w"); + XMLPrinter printer(fp1); + + printer.PushDeclaration("version = '1.0' enconding = 'utf-8'"); + + printer.OpenElement("foo"); + printer.PushAttribute("attrib-text", "text"); + + printer.OpenElement("text"); + printer.PushText("Tinyxml2"); + printer.CloseElement(); + + printer.OpenElement("int"); + printer.PushText(int(11)); + printer.CloseElement(); + + printer.OpenElement("unsigned"); + printer.PushText(unsigned(12)); + printer.CloseElement(); + + printer.OpenElement("int64_t"); + printer.PushText(int64_t(13)); + printer.CloseElement(); + + printer.OpenElement("uint64_t"); + printer.PushText(uint64_t(14)); + printer.CloseElement(); + + printer.OpenElement("bool"); + printer.PushText(true); + printer.CloseElement(); + + printer.OpenElement("float"); + printer.PushText("1.56"); + printer.CloseElement(); + + printer.OpenElement("double"); + printer.PushText("12.12"); + printer.CloseElement(); + + printer.OpenElement("comment"); + printer.PushComment("this is Tinyxml2"); + printer.CloseElement(); + + printer.CloseElement(); + fclose(fp1); + } + { + XMLDocument doc; + doc.LoadFile("resources/out/printer_1.xml"); + XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true); + + const XMLDocument& cdoc = doc; + + const XMLElement* root = cdoc.FirstChildElement("foo"); + + const char* text_value; + text_value = root->FirstChildElement("text")->GetText(); + XMLTest("PushText( const char* text, bool cdata=false ) test", "Tinyxml2", text_value); + + int int_value; + int_value = root->FirstChildElement("int")->IntText(); + XMLTest("PushText( int value ) test", 11, int_value); + + unsigned unsigned_value; + unsigned_value = root->FirstChildElement("unsigned")->UnsignedText(); + XMLTest("PushText( unsigned value ) test", (unsigned)12, unsigned_value); + + int64_t int64_t_value; + int64_t_value = root->FirstChildElement("int64_t")->Int64Text(); + XMLTest("PushText( int64_t value ) test", (int64_t) 13, int64_t_value); + + uint64_t uint64_t_value; + uint64_t_value = root->FirstChildElement("uint64_t")->Unsigned64Text(); + XMLTest("PushText( uint64_t value ) test", (uint64_t) 14, uint64_t_value); + + float float_value; + float_value = root->FirstChildElement("float")->FloatText(); + XMLTest("PushText( float value ) test", 1.56f, float_value); + + double double_value; + double_value = root->FirstChildElement("double")->DoubleText(); + XMLTest("PushText( double value ) test", 12.12, double_value); + + bool bool_value; + bool_value = root->FirstChildElement("bool")->BoolText(); + XMLTest("PushText( bool value ) test", true, bool_value); + + const XMLComment* comment = root->FirstChildElement("comment")->FirstChild()->ToComment(); + const char* comment_value = comment->Value(); + XMLTest("PushComment() test", "this is Tinyxml2", comment_value); + + const XMLDeclaration* declaration = cdoc.FirstChild()->ToDeclaration(); + const char* declaration_value = declaration->Value(); + XMLTest("PushDeclaration() test", "version = '1.0' enconding = 'utf-8'", declaration_value); + } + } + + + // ---------- CDATA --------------- + { + const char* str = "" + " the rules!\n" + "...since I make symbolic puns" + "]]>" + ""; + XMLDocument doc; + doc.Parse( str ); + XMLTest( "CDATA symbolic puns round 1", false, doc.Error() ); + doc.Print(); + + XMLTest( "CDATA parse.", "I am > the rules!\n...since I make symbolic puns", + doc.FirstChildElement()->FirstChild()->Value(), + false ); + } + + // ----------- CDATA ------------- + { + const char* str = "" + "I am > the rules!\n" + "...since I make symbolic puns" + "]]>" + ""; + XMLDocument doc; + doc.Parse( str ); + XMLTest( "CDATA symbolic puns round 2", false, doc.Error() ); + doc.Print(); + + XMLTest( "CDATA parse. [ tixml1:1480107 ]", + "I am > the rules!\n...since I make symbolic puns", + doc.FirstChildElement()->FirstChild()->Value(), + false ); + } + + // InsertAfterChild causes crash. + { + // InsertBeforeChild and InsertAfterChild causes crash. + XMLDocument doc; + XMLElement* parent = doc.NewElement( "Parent" ); + doc.InsertFirstChild( parent ); + + XMLElement* childText0 = doc.NewElement( "childText0" ); + XMLElement* childText1 = doc.NewElement( "childText1" ); + + XMLNode* childNode0 = parent->InsertEndChild( childText0 ); + XMLTest( "InsertEndChild() return", true, childNode0 == childText0 ); + XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 ); + XMLTest( "InsertAfterChild() return", true, childNode1 == childText1 ); + + XMLTest( "Test InsertAfterChild on empty node. ", true, ( childNode1 == parent->LastChild() ) ); + } + + { + // Entities not being written correctly. + // From Lynn Allen + + const char* passages = + "" + "" + " " + ""; + + XMLDocument doc; + doc.Parse( passages ); + XMLTest( "Entity transformation parse round 1", false, doc.Error() ); + XMLElement* psg = doc.RootElement()->FirstChildElement(); + const char* context = psg->Attribute( "context" ); + const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9."; + + XMLTest( "Entity transformation: read. ", expected, context, true ); + + const char* textFilePath = "resources/out/textfile.txt"; + FILE* textfile = fopen( textFilePath, "w" ); + XMLTest( "Entity transformation: open text file for writing", true, textfile != 0, true ); + if ( textfile ) + { + XMLPrinter streamer( textfile ); + bool acceptResult = psg->Accept( &streamer ); + fclose( textfile ); + XMLTest( "Entity transformation: Accept", true, acceptResult ); + } + + textfile = fopen( textFilePath, "r" ); + XMLTest( "Entity transformation: open text file for reading", true, textfile != 0, true ); + if ( textfile ) + { + char buf[ 1024 ]; + fgets( buf, 1024, textfile ); + XMLTest( "Entity transformation: write. ", + "\n", + buf, false ); + fclose( textfile ); + } + } + + { + // Suppress entities. + const char* passages = + "" + "" + "Crazy &ttk;" + ""; + + XMLDocument doc( false ); + doc.Parse( passages ); + XMLTest( "Entity transformation parse round 2", false, doc.Error() ); + + XMLTest( "No entity parsing.", + "Line 5 has "quotation marks" and 'apostrophe marks'.", + doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ) ); + XMLTest( "No entity parsing.", "Crazy &ttk;", + doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value() ); + doc.Print(); + } + + { + const char* test = ""; + + XMLDocument doc; + doc.Parse( test ); + XMLTest( "dot in names", false, doc.Error() ); + XMLTest( "dot in names", "a.elem", doc.FirstChildElement()->Name() ); + XMLTest( "dot in names", "2.0", doc.FirstChildElement()->Attribute( "xmi.version" ) ); + } + + { + const char* test = "1.1 Start easy ignore fin thickness "; + + XMLDocument doc; + doc.Parse( test ); + XMLTest( "fin thickness", false, doc.Error() ); + + XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText(); + XMLTest( "Entity with one digit.", + "1.1 Start easy ignore fin thickness\n", text->Value(), + false ); + } + + { + // DOCTYPE not preserved (950171) + // + const char* doctype = + "" + "" + "" + "" + ""; + + XMLDocument doc; + doc.Parse( doctype ); + XMLTest( "PLAY SYSTEM parse", false, doc.Error() ); + doc.SaveFile( "resources/out/test7.xml" ); + XMLTest( "PLAY SYSTEM save", false, doc.Error() ); + doc.DeleteChild( doc.RootElement() ); + doc.LoadFile( "resources/out/test7.xml" ); + XMLTest( "PLAY SYSTEM load", false, doc.Error() ); + doc.Print(); + + const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown(); + XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() ); + + } + + { + // Comments do not stream out correctly. + const char* doctype = + ""; + XMLDocument doc; + doc.Parse( doctype ); + XMLTest( "Comment somewhat evil", false, doc.Error() ); + + XMLComment* comment = doc.FirstChild()->ToComment(); + + XMLTest( "Comment formatting.", " Somewhat ", comment->Value() ); + } + { + // Double attributes + const char* doctype = ""; + + XMLDocument doc; + doc.Parse( doctype ); + + XMLTest( "Parsing repeated attributes.", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() ); // is an error to tinyxml (didn't use to be, but caused issues) + doc.PrintError(); + } + + { + // Embedded null in stream. + const char* doctype = ""; + + XMLDocument doc; + doc.Parse( doctype ); + XMLTest( "Embedded null throws error.", true, doc.Error() ); + } + + { + // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717 + const char* str = ""; + XMLDocument doc; + doc.Parse( str ); + XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() ); + + // But be sure there is an error string! + const char* errorStr = doc.ErrorStr(); + XMLTest("Error string should be set", + "Error=XML_ERROR_EMPTY_DOCUMENT ErrorID=13 (0xd) Line number=0", + errorStr); + } + + { + // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717 + const char* str = " "; + XMLDocument doc; + doc.Parse( str ); + XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() ); + } + + { + // Low entities + XMLDocument doc; + doc.Parse( "" ); + XMLTest( "Hex values", false, doc.Error() ); + const char result[] = { 0x0e, 0 }; + XMLTest( "Low entities.", result, doc.FirstChildElement()->GetText() ); + doc.Print(); + } + + { + // Attribute values with trailing quotes not handled correctly + XMLDocument doc; + doc.Parse( "" ); + XMLTest( "Throw error with bad end quotes.", true, doc.Error() ); + } + + { + // [ 1663758 ] Failure to report error on bad XML + XMLDocument xml; + xml.Parse(""); + XMLTest("Missing end tag at end of input", true, xml.Error()); + xml.Parse(" "); + XMLTest("Missing end tag with trailing whitespace", true, xml.Error()); + xml.Parse(""); + XMLTest("Mismatched tags", XML_ERROR_MISMATCHED_ELEMENT, xml.ErrorID() ); + } + + + { + // [ 1475201 ] TinyXML parses entities in comments + XMLDocument xml; + xml.Parse("" + "" ); + XMLTest( "Declarations for head and body", false, xml.Error() ); + + XMLNode* e0 = xml.FirstChild(); + XMLNode* e1 = e0->NextSibling(); + XMLComment* c0 = e0->ToComment(); + XMLComment* c1 = e1->ToComment(); + + XMLTest( "Comments ignore entities.", " declarations for & ", c0->Value(), true ); + XMLTest( "Comments ignore entities.", " far & away ", c1->Value(), true ); + } + + { + XMLDocument xml; + xml.Parse( "" + "" + "" + "" + "" ); + XMLTest( "Comments iteration", false, xml.Error() ); + xml.Print(); + + int count = 0; + + for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild(); + ele; + ele = ele->NextSibling() ) + { + ++count; + } + + XMLTest( "Comments iterate correctly.", 3, count ); + } + + { + // trying to repro [1874301]. If it doesn't go into an infinite loop, all is well. + unsigned char buf[] = " " ); + XMLTest( "Handle end tag whitespace", false, xml.Error() ); + } + + { + // This one must not result in an infinite loop + XMLDocument xml; + xml.Parse( "loop" ); + XMLTest( "No closing element", true, xml.Error() ); + XMLTest( "Infinite loop test.", true, true ); + } +#endif + { + const char* pub = " "; + XMLDocument doc; + doc.Parse( pub ); + XMLTest( "Trailing DOCTYPE", false, doc.Error() ); + + XMLDocument clone; + for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) { + XMLNode* copy = node->ShallowClone( &clone ); + clone.InsertEndChild( copy ); + } + + clone.Print(); + + int count=0; + const XMLNode* a=clone.FirstChild(); + const XMLNode* b=doc.FirstChild(); + for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) { + ++count; + XMLTest( "Clone and Equal", true, a->ShallowEqual( b )); + } + XMLTest( "Clone and Equal", 4, count ); + } + + { + // Deep Cloning of root element. + XMLDocument doc2; + XMLPrinter printer1; + { + // Make sure doc1 is deleted before we test doc2 + const char* xml = + "" + " " + " " + " Text" + ""; + XMLDocument doc; + doc.Parse(xml); + XMLTest( "Parse before deep cloning root element", false, doc.Error() ); + + doc.Print(&printer1); + XMLNode* root = doc.RootElement()->DeepClone(&doc2); + doc2.InsertFirstChild(root); + } + XMLPrinter printer2; + doc2.Print(&printer2); + + XMLTest("Deep clone of element.", printer1.CStr(), printer2.CStr(), true); + } + + { + // Deep Cloning of sub element. + XMLDocument doc2; + XMLPrinter printer1; + { + // Make sure doc1 is deleted before we test doc2 + const char* xml = + "" + "" + " " + " " + " Text" + ""; + XMLDocument doc; + doc.Parse(xml); + XMLTest( "Parse before deep cloning sub element", false, doc.Error() ); + + const XMLElement* subElement = doc.FirstChildElement("root")->FirstChildElement("child2"); + bool acceptResult = subElement->Accept(&printer1); + XMLTest( "Accept before deep cloning", true, acceptResult ); + + XMLNode* clonedSubElement = subElement->DeepClone(&doc2); + doc2.InsertFirstChild(clonedSubElement); + } + XMLPrinter printer2; + doc2.Print(&printer2); + + XMLTest("Deep clone of sub-element.", printer1.CStr(), printer2.CStr(), true); + } + + { + // Deep cloning of document. + XMLDocument doc2; + XMLPrinter printer1; + { + // Make sure doc1 is deleted before we test doc2 + const char* xml = + "" + "" + "" + " " + " " + " Text" + ""; + XMLDocument doc; + doc.Parse(xml); + XMLTest( "Parse before deep cloning document", false, doc.Error() ); + doc.Print(&printer1); + + doc.DeepCopy(&doc2); + } + XMLPrinter printer2; + doc2.Print(&printer2); + + XMLTest("DeepCopy of document.", printer1.CStr(), printer2.CStr(), true); + } + + + { + // This shouldn't crash. + XMLDocument doc; + if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" )) + { + doc.PrintError(); + } + XMLTest( "Error in snprinf handling.", true, doc.Error() ); + } + + { + // Attribute ordering. + static const char* xml = ""; + XMLDocument doc; + doc.Parse( xml ); + XMLTest( "Parse for attribute ordering", false, doc.Error() ); + XMLElement* ele = doc.FirstChildElement(); + + const XMLAttribute* a = ele->FirstAttribute(); + XMLTest( "Attribute order", "1", a->Value() ); + a = a->Next(); + XMLTest( "Attribute order", "2", a->Value() ); + a = a->Next(); + XMLTest( "Attribute order", "3", a->Value() ); + XMLTest( "Attribute order", "attrib3", a->Name() ); + + ele->DeleteAttribute( "attrib2" ); + a = ele->FirstAttribute(); + XMLTest( "Attribute order", "1", a->Value() ); + a = a->Next(); + XMLTest( "Attribute order", "3", a->Value() ); + + ele->DeleteAttribute( "attrib1" ); + ele->DeleteAttribute( "attrib3" ); + XMLTest( "Attribute order (empty)", true, ele->FirstAttribute() == 0 ); + } + + { + // Make sure an attribute with a space in it succeeds. + static const char* xml0 = ""; + static const char* xml1 = ""; + static const char* xml2 = ""; + XMLDocument doc0; + doc0.Parse( xml0 ); + XMLTest( "Parse attribute with space 1", false, doc0.Error() ); + XMLDocument doc1; + doc1.Parse( xml1 ); + XMLTest( "Parse attribute with space 2", false, doc1.Error() ); + XMLDocument doc2; + doc2.Parse( xml2 ); + XMLTest( "Parse attribute with space 3", false, doc2.Error() ); + + XMLElement* ele = 0; + ele = doc0.FirstChildElement(); + XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) ); + ele = doc1.FirstChildElement(); + XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) ); + ele = doc2.FirstChildElement(); + XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) ); + } + + { + // Make sure we don't go into an infinite loop. + static const char* xml = ""; + XMLDocument doc; + doc.Parse( xml ); + XMLTest( "Parse two elements with attribute", false, doc.Error() ); + XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement(); + XMLElement* ele1 = ele0->NextSiblingElement(); + bool equal = ele0->ShallowEqual( ele1 ); + + XMLTest( "Infinite loop in shallow equal.", true, equal ); + } + + // -------- Handles ------------ + { + static const char* xml = "Text"; + XMLDocument doc; + doc.Parse( xml ); + XMLTest( "Handle, parse element with attribute and nested element", false, doc.Error() ); + + { + XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement(); + XMLTest( "Handle, non-const, element is found", true, ele != 0 ); + XMLTest( "Handle, non-const, element name matches", "sub", ele->Value() ); + } + + { + XMLHandle docH( doc ); + XMLElement* ele = docH.FirstChildElement( "noSuchElement" ).FirstChildElement( "element" ).ToElement(); + XMLTest( "Handle, non-const, element not found", true, ele == 0 ); + } + + { + const XMLElement* ele = XMLConstHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement(); + XMLTest( "Handle, const, element is found", true, ele != 0 ); + XMLTest( "Handle, const, element name matches", "sub", ele->Value() ); + } + + { + XMLConstHandle docH( doc ); + const XMLElement* ele = docH.FirstChildElement( "noSuchElement" ).FirstChildElement( "element" ).ToElement(); + XMLTest( "Handle, const, element not found", true, ele == 0 ); + } + } + { + // Default Declaration & BOM + XMLDocument doc; + doc.InsertEndChild( doc.NewDeclaration() ); + doc.SetBOM( true ); + + XMLPrinter printer; + doc.Print( &printer ); + + static const char* result = "\xef\xbb\xbf"; + XMLTest( "BOM and default declaration", result, printer.CStr(), false ); + XMLTest( "CStrSize", 42, printer.CStrSize(), false ); + } + { + const char* xml = "" + "voice" + ""; + XMLDocument doc; + doc.Parse( xml ); + const XMLNode* PlaylistNode = doc.RootElement(); + const XMLNode* PropertyNode = PlaylistNode->FirstChildElement(); + bool result; + result = PlaylistNode->ShallowEqual(PropertyNode); + XMLTest("ShallowEqual() test",false,result); + result = PlaylistNode->ShallowEqual(PlaylistNode); + XMLTest("ShallowEqual() test",true,result); + } + + { + //API: previousSiblingElement() and NextSiblingElement() test + const char* xml = "" + "voice" + "" + "" + ""; + XMLDocument doc; + doc.Parse( xml ); + XMLElement* ElementPlaylist = doc.FirstChildElement("playlist"); + XMLTest("previousSiblingElement() test",true,ElementPlaylist != 0); + const XMLElement* pre = ElementPlaylist->PreviousSiblingElement(); + XMLTest("previousSiblingElement() test",true,pre == 0); + const XMLElement* ElementBlank = ElementPlaylist->FirstChildElement("entry")->NextSiblingElement("blank"); + XMLTest("NextSiblingElement() test",true,ElementBlank != 0); + const XMLElement* next = ElementBlank->NextSiblingElement(); + XMLTest("NextSiblingElement() test",true,next == 0); + const XMLElement* ElementEntry = ElementBlank->PreviousSiblingElement("entry"); + XMLTest("PreviousSiblingElement test",true,ElementEntry != 0); + } + + // QueryXYZText + { + const char* xml = " 1.2 1 38 true "; + XMLDocument doc; + doc.Parse( xml ); + XMLTest( "Parse points", false, doc.Error() ); + + const XMLElement* pointElement = doc.RootElement(); + + { + int intValue = 0; + XMLError queryResult = pointElement->FirstChildElement( "y" )->QueryIntText( &intValue ); + XMLTest( "QueryIntText result", XML_SUCCESS, queryResult, false ); + XMLTest( "QueryIntText", 1, intValue, false ); + } + + { + unsigned unsignedValue = 0; + XMLError queryResult = pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue ); + XMLTest( "QueryUnsignedText result", XML_SUCCESS, queryResult, false ); + XMLTest( "QueryUnsignedText", (unsigned)1, unsignedValue, false ); + } + + { + float floatValue = 0; + XMLError queryResult = pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue ); + XMLTest( "QueryFloatText result", XML_SUCCESS, queryResult, false ); + XMLTest( "QueryFloatText", 1.2f, floatValue, false ); + } + + { + double doubleValue = 0; + XMLError queryResult = pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue ); + XMLTest( "QueryDoubleText result", XML_SUCCESS, queryResult, false ); + XMLTest( "QueryDoubleText", 1.2, doubleValue, false ); + } + + { + bool boolValue = false; + XMLError queryResult = pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue ); + XMLTest( "QueryBoolText result", XML_SUCCESS, queryResult, false ); + XMLTest( "QueryBoolText", true, boolValue, false ); + } + } + + { + const char* xml = "<_sub/><:sub/>"; + XMLDocument doc; + doc.Parse( xml ); + XMLTest( "Non-alpha element lead letter parses.", false, doc.Error() ); + } + + { + const char* xml = ""; + XMLDocument doc; + doc.Parse( xml ); + XMLTest("Non-alpha attribute lead character parses.", false, doc.Error()); + } + + { + const char* xml = "<3lement>"; + XMLDocument doc; + doc.Parse( xml ); + XMLTest("Element names with lead digit fail to parse.", true, doc.Error()); + } + + { + const char* xml = "WOA THIS ISN'T GOING TO PARSE"; + XMLDocument doc; + doc.Parse( xml, 10 ); + XMLTest( "Set length of incoming data", false, doc.Error() ); + } + + { + XMLDocument doc; + XMLTest( "Document is initially empty", true, doc.NoChildren() ); + doc.Clear(); + XMLTest( "Empty is empty after Clear()", true, doc.NoChildren() ); + doc.LoadFile( "resources/dream.xml" ); + XMLTest( "Load dream.xml", false, doc.Error() ); + XMLTest( "Document has something to Clear()", false, doc.NoChildren() ); + doc.Clear(); + XMLTest( "Document Clear()'s", true, doc.NoChildren() ); + } + + { + XMLDocument doc; + XMLTest( "No error initially", false, doc.Error() ); + XMLError error = doc.Parse( "This is not XML" ); + XMLTest( "Error after invalid XML", true, doc.Error() ); + XMLTest( "Error after invalid XML", error, doc.ErrorID() ); + doc.Clear(); + XMLTest( "No error after Clear()", false, doc.Error() ); + } + + // ----------- Whitespace ------------ + { + const char* xml = "" + " This \nis ' text ' " + " This is ' text ' \n" + "This is ' \n\n text '" + ""; + XMLDocument doc( true, COLLAPSE_WHITESPACE ); + doc.Parse( xml ); + XMLTest( "Parse with whitespace collapsing and &apos", false, doc.Error() ); + + const XMLElement* element = doc.FirstChildElement(); + for( const XMLElement* parent = element->FirstChildElement(); + parent; + parent = parent->NextSiblingElement() ) + { + XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() ); + } + } + +#if 0 + { + // Passes if assert doesn't fire. + XMLDocument xmlDoc; + + xmlDoc.NewDeclaration(); + xmlDoc.NewComment("Configuration file"); + + XMLElement *root = xmlDoc.NewElement("settings"); + root->SetAttribute("version", 2); + } +#endif + + { + const char* xml = " "; + XMLDocument doc( true, COLLAPSE_WHITESPACE ); + doc.Parse( xml ); + XMLTest( "Parse with all whitespaces", false, doc.Error() ); + XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() ); + } + + { + // An assert should not fire. + const char* xml = ""; + XMLDocument doc; + doc.Parse( xml ); + XMLTest( "Parse with self-closed element", false, doc.Error() ); + XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope. + XMLTest( "Tracking unused elements", true, ele != 0, false ); + } + + + { + const char* xml = "abc"; + XMLDocument doc; + doc.Parse( xml ); + XMLTest( "Parse for printing of sub-element", false, doc.Error() ); + XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child"); + + XMLPrinter printer; + bool acceptResult = ele->Accept( &printer ); + XMLTest( "Accept of sub-element", true, acceptResult ); + XMLTest( "Printing of sub-element", "abc\n", printer.CStr(), false ); + } + + + { + XMLDocument doc; + XMLError error = doc.LoadFile( "resources/empty.xml" ); + XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error ); + XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() ); + doc.PrintError(); + } + + { + // BOM preservation + static const char* xml_bom_preservation = "\xef\xbb\xbf\n"; + { + XMLDocument doc; + XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false ); + XMLPrinter printer; + doc.Print( &printer ); + + XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true ); + doc.SaveFile( "resources/out/bomtest.xml" ); + XMLTest( "Save bomtest.xml", false, doc.Error() ); + } + { + XMLDocument doc; + doc.LoadFile( "resources/out/bomtest.xml" ); + XMLTest( "Load bomtest.xml", false, doc.Error() ); + XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false ); + + XMLPrinter printer; + doc.Print( &printer ); + XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true ); + } + } + + { + // Insertion with Removal + const char* xml = "" + "" + "" + "" + "element 1text" + "" + "" + "" + ""; + const char* xmlInsideTwo = "" + "" + "" + "" + "" + "element 1text" + "" + "" + ""; + const char* xmlAfterOne = "" + "" + "" + "" + "element 1text" + "" + "" + ""; + const char* xmlAfterTwo = "" + "" + "" + "" + "" + "element 1text" + "" + ""; + + XMLDocument doc; + doc.Parse(xml); + XMLTest( "Insertion with removal parse round 1", false, doc.Error() ); + XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree"); + XMLElement* two = doc.RootElement()->FirstChildElement("two"); + two->InsertFirstChild(subtree); + XMLPrinter printer1(0, true); + bool acceptResult = doc.Accept(&printer1); + XMLTest("Move node from within to - Accept()", true, acceptResult); + XMLTest("Move node from within to ", xmlInsideTwo, printer1.CStr()); + + doc.Parse(xml); + XMLTest( "Insertion with removal parse round 2", false, doc.Error() ); + subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree"); + two = doc.RootElement()->FirstChildElement("two"); + doc.RootElement()->InsertAfterChild(two, subtree); + XMLPrinter printer2(0, true); + acceptResult = doc.Accept(&printer2); + XMLTest("Move node from within after - Accept()", true, acceptResult); + XMLTest("Move node from within after ", xmlAfterTwo, printer2.CStr(), false); + + doc.Parse(xml); + XMLTest( "Insertion with removal parse round 3", false, doc.Error() ); + XMLNode* one = doc.RootElement()->FirstChildElement("one"); + subtree = one->FirstChildElement("subtree"); + doc.RootElement()->InsertAfterChild(one, subtree); + XMLPrinter printer3(0, true); + acceptResult = doc.Accept(&printer3); + XMLTest("Move node from within after - Accept()", true, acceptResult); + XMLTest("Move node from within after ", xmlAfterOne, printer3.CStr(), false); + + doc.Parse(xml); + XMLTest( "Insertion with removal parse round 4", false, doc.Error() ); + subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree"); + two = doc.RootElement()->FirstChildElement("two"); + XMLTest(" is the last child at root level", true, two == doc.RootElement()->LastChildElement()); + doc.RootElement()->InsertEndChild(subtree); + XMLPrinter printer4(0, true); + acceptResult = doc.Accept(&printer4); + XMLTest("Move node from within after - Accept()", true, acceptResult); + XMLTest("Move node from within after ", xmlAfterTwo, printer4.CStr(), false); + } + + { + const char* xml = "" + " " + ""; + XMLDocument doc; + doc.Parse(xml); + XMLTest( "Parse svg with text", false, doc.Error() ); + doc.Print(); + } + + { + // Test that it doesn't crash. + const char* xml = "<12"; + XMLDocument doc; + doc.Parse(xml); + XMLTest( "Parse root-sample-field0", true, doc.Error() ); + doc.PrintError(); + } + +#if 1 + // the question being explored is what kind of print to use: + // https://github.com/leethomason/tinyxml2/issues/63 + { + //const char* xml = ""; + const char* xml = ""; + XMLDocument doc; + doc.Parse( xml ); + XMLTest( "Parse self-closed empty element", false, doc.Error() ); + doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 ); + doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 ); + doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 ); + doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 ); + doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 ); + doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 ); + + doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f ); + doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f ); + doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f ); + doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f ); + doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f ); + doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f ); + + doc.Print(); + + /* The result of this test is platform, compiler, and library version dependent. :(" + XMLPrinter printer; + doc.Print( &printer ); + XMLTest( "Float and double formatting.", + "\n", + printer.CStr(), + true ); + */ + } +#endif + + { + // Issue #184 + // If it doesn't assert, it passes. Caused by objects + // getting created during parsing which are then + // inaccessible in the memory pools. + const char* xmlText = ""; + { + XMLDocument doc; + doc.Parse(xmlText); + XMLTest( "Parse hex no closing tag round 1", true, doc.Error() ); + } + { + XMLDocument doc; + doc.Parse(xmlText); + XMLTest( "Parse hex no closing tag round 2", true, doc.Error() ); + doc.Clear(); + } + } + + { + // If this doesn't assert in TINYXML2_DEBUG, all is well. + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement *pRoot = doc.NewElement("Root"); + doc.DeleteNode(pRoot); + } + + { + XMLDocument doc; + XMLElement* root = doc.NewElement( "Root" ); + XMLTest( "Node document before insertion", true, &doc == root->GetDocument() ); + doc.InsertEndChild( root ); + XMLTest( "Node document after insertion", true, &doc == root->GetDocument() ); + } + + { + // If this doesn't assert in TINYXML2_DEBUG, all is well. + XMLDocument doc; + XMLElement* unlinkedRoot = doc.NewElement( "Root" ); + XMLElement* linkedRoot = doc.NewElement( "Root" ); + doc.InsertFirstChild( linkedRoot ); + unlinkedRoot->GetDocument()->DeleteNode( linkedRoot ); + unlinkedRoot->GetDocument()->DeleteNode( unlinkedRoot ); + } + + { + // Should not assert in TINYXML2_DEBUG + XMLPrinter printer; + } + + { + // Issue 291. Should not crash + const char* xml = "�"; + XMLDocument doc; + doc.Parse( xml ); + XMLTest( "Parse hex with closing tag", false, doc.Error() ); + + XMLPrinter printer; + doc.Print( &printer ); + } + { + // Issue 299. Can print elements that are not linked in. + // Will crash if issue not fixed. + XMLDocument doc; + XMLElement* newElement = doc.NewElement( "printme" ); + XMLPrinter printer; + bool acceptResult = newElement->Accept( &printer ); + XMLTest( "printme - Accept()", true, acceptResult ); + // Delete the node to avoid possible memory leak report in debug output + doc.DeleteNode( newElement ); + } + { + // Issue 302. Clear errors from LoadFile/SaveFile + XMLDocument doc; + XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() ); + doc.SaveFile( "./no/such/path/pretty.xml" ); + XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() ); + doc.SaveFile( "./resources/out/compact.xml", true ); + XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() ); + } + + { + // If a document fails to load then subsequent + // successful loads should clear the error + XMLDocument doc; + XMLTest( "Should be no error initially", false, doc.Error() ); + doc.LoadFile( "resources/no-such-file.xml" ); + XMLTest( "No such file - should fail", true, doc.Error() ); + + doc.LoadFile( "resources/dream.xml" ); + XMLTest( "Error should be cleared", false, doc.Error() ); + } + + { + // Check that declarations are allowed only at beginning of document + const char* xml0 = "" + " " + ""; + const char* xml1 = "" + "" + ""; + const char* xml2 = "" + ""; + const char* xml3 = "" + ""; + + const char* xml4 = ""; + + XMLDocument doc; + doc.Parse(xml0); + XMLTest("Test that the code changes do not affect normal parsing", false, doc.Error() ); + doc.Parse(xml1); + XMLTest("Test that the second declaration is allowed", false, doc.Error() ); + doc.Parse(xml2); + XMLTest("Test that declaration after self-closed child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() ); + doc.Parse(xml3); + XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() ); + doc.Parse(xml4); + XMLTest("Test that declaration inside a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() ); + } + + { + // No matter - before or after successfully parsing a text - + // calling XMLDocument::Value() used to cause an assert in debug. + // Null must be returned. + const char* validXml = "" + "" + ""; + XMLDocument* doc = new XMLDocument(); + XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() ); + doc->Parse( validXml ); + XMLTest( "Parse to test XMLDocument::Value()", false, doc->Error()); + XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() ); + delete doc; + } + + { + XMLDocument doc; + for( int i = 0; i < XML_ERROR_COUNT; i++ ) { + const XMLError error = static_cast(i); + const char* name = XMLDocument::ErrorIDToName(error); + XMLTest( "ErrorName() not null after ClearError()", true, name != 0 ); + if( name == 0 ) { + // passing null pointer into strlen() is undefined behavior, so + // compiler is allowed to optimise away the null test above if it's + // as reachable as the strlen() call + continue; + } + XMLTest( "ErrorName() not empty after ClearError()", true, strlen(name) > 0 ); + } + } + + { + const char* html("

test


"); + XMLDocument doc(false); + doc.Parse(html); + + XMLPrinter printer(0, true); + doc.Print(&printer); + + XMLTest(html, html, printer.CStr()); + } + + { + // Evil memory leaks. + // If an XMLElement (etc) is allocated via NewElement() (etc.) + // and NOT added to the XMLDocument, what happens? + // + // Previously (buggy): + // The memory would be free'd when the XMLDocument is + // destructed. But the XMLElement destructor wasn't called, so + // memory allocated for the XMLElement text would not be free'd. + // In practice this meant strings allocated for the XMLElement + // text would be leaked. An edge case, but annoying. + // Now: + // The XMLElement destructor is called. But the unlinked nodes + // have to be tracked using a list. This has a minor performance + // impact that can become significant if you have a lot of + // unlinked nodes. (But why would you do that?) + // The only way to see this bug was in a Visual C++ runtime debug heap + // leak tracker. This is compiled in by default on Windows Debug and + // enabled with _CRTDBG_LEAK_CHECK_DF parameter passed to _CrtSetDbgFlag(). + { + XMLDocument doc; + doc.NewElement("LEAK 1"); + } + { + XMLDocument doc; + XMLElement* ele = doc.NewElement("LEAK 2"); + doc.DeleteNode(ele); + } + } + + { + // Bad bad crash. Parsing error results in stack overflow, if uncaught. + const char* TESTS[] = { + "./resources/xmltest-5330.xml", + "./resources/xmltest-4636783552757760.xml", + "./resources/xmltest-5720541257269248.xml", + 0 + }; + for (int i=0; TESTS[i]; ++i) { + XMLDocument doc; + doc.LoadFile(TESTS[i]); + XMLTest("Stack overflow prevented.", XML_ELEMENT_DEPTH_EXCEEDED, doc.ErrorID()); + } + } + { + const char* TESTS[] = { + "./resources/xmltest-5662204197076992.xml", // Security-level performance issue. + 0 + }; + for (int i = 0; TESTS[i]; ++i) { + XMLDocument doc; + doc.LoadFile(TESTS[i]); + // Need only not crash / lock up. + XMLTest("Fuzz attack prevented.", true, true); + } + } + { + // Crashing reported via email. + const char* xml = + "" + "voice" + "1" + "" + "" + "" + "" + "" + "" + "" + ""; + + // It's not a good idea to delete elements as you walk the + // list. I'm not sure this technically should work; but it's + // an interesting test case. + XMLDocument doc; + XMLError err = doc.Parse(xml); + XMLTest("Crash bug parsing", XML_SUCCESS, err ); + + XMLElement* playlist = doc.FirstChildElement("playlist"); + XMLTest("Crash bug parsing", true, playlist != 0); + + { + const char* elementName = "entry"; + XMLElement* entry = playlist->FirstChildElement(elementName); + XMLTest("Crash bug parsing", true, entry != 0); + while (entry) { + XMLElement* todelete = entry; + entry = entry->NextSiblingElement(elementName); + playlist->DeleteChild(todelete); + } + entry = playlist->FirstChildElement(elementName); + XMLTest("Crash bug parsing", true, entry == 0); + } + { + const char* elementName = "blank"; + XMLElement* blank = playlist->FirstChildElement(elementName); + XMLTest("Crash bug parsing", true, blank != 0); + while (blank) { + XMLElement* todelete = blank; + blank = blank->NextSiblingElement(elementName); + playlist->DeleteChild(todelete); + } + XMLTest("Crash bug parsing", true, blank == 0); + } + + tinyxml2::XMLPrinter printer; + const bool acceptResult = playlist->Accept(&printer); + XMLTest("Crash bug parsing - Accept()", true, acceptResult); + printf("%s\n", printer.CStr()); + + // No test; it only need to not crash. + // Still, wrap it up with a sanity check + int nProperty = 0; + for (const XMLElement* p = playlist->FirstChildElement("property"); p; p = p->NextSiblingElement("property")) { + nProperty++; + } + XMLTest("Crash bug parsing", 2, nProperty); + } + + // ----------- Line Number Tracking -------------- + { + struct TestUtil: XMLVisitor + { + TestUtil() : str() {} + + void TestParseError(const char *testString, const char *docStr, XMLError expected_error, int expectedLine) + { + XMLDocument doc; + const XMLError parseError = doc.Parse(docStr); + + XMLTest(testString, parseError, doc.ErrorID()); + XMLTest(testString, true, doc.Error()); + XMLTest(testString, expected_error, parseError); + XMLTest(testString, expectedLine, doc.ErrorLineNum()); + }; + + void TestStringLines(const char *testString, const char *docStr, const char *expectedLines) + { + XMLDocument doc; + doc.Parse(docStr); + XMLTest(testString, false, doc.Error()); + TestDocLines(testString, doc, expectedLines); + } + + void TestFileLines(const char *testString, const char *file_name, const char *expectedLines) + { + XMLDocument doc; + doc.LoadFile(file_name); + XMLTest(testString, false, doc.Error()); + TestDocLines(testString, doc, expectedLines); + } + + private: + DynArray str; + + void Push(char type, int lineNum) + { + str.Push(type); + str.Push(char('0' + (lineNum / 10))); + str.Push(char('0' + (lineNum % 10))); + } + + bool VisitEnter(const XMLDocument& doc) + { + Push('D', doc.GetLineNum()); + return true; + } + bool VisitEnter(const XMLElement& element, const XMLAttribute* firstAttribute) + { + Push('E', element.GetLineNum()); + for (const XMLAttribute *attr = firstAttribute; attr != 0; attr = attr->Next()) + Push('A', attr->GetLineNum()); + return true; + } + bool Visit(const XMLDeclaration& declaration) + { + Push('L', declaration.GetLineNum()); + return true; + } + bool Visit(const XMLText& text) + { + Push('T', text.GetLineNum()); + return true; + } + bool Visit(const XMLComment& comment) + { + Push('C', comment.GetLineNum()); + return true; + } + bool Visit(const XMLUnknown& unknown) + { + Push('U', unknown.GetLineNum()); + return true; + } + + void TestDocLines(const char *testString, XMLDocument &doc, const char *expectedLines) + { + str.Clear(); + const bool acceptResult = doc.Accept(this); + XMLTest(testString, true, acceptResult); + str.Push(0); + XMLTest(testString, expectedLines, str.Mem()); + } + } tester; + + tester.TestParseError("ErrorLine-Parsing", "\n\n foo \n", XML_ERROR_PARSING, 2); + tester.TestParseError("ErrorLine-Declaration", "\n", XML_ERROR_PARSING_DECLARATION, 2); + tester.TestParseError("ErrorLine-Mismatch", "\n\n", XML_ERROR_MISMATCHED_ELEMENT, 2); + tester.TestParseError("ErrorLine-CData", "\n\n foo bar \n", XML_ERROR_PARSING_TEXT, 3); + tester.TestParseError("ErrorLine-Comment", "\n\n\n" // 6 Comment + "", // 7 Unknown + + "D01L01E02A02A03T03E03T04E05T05C06U07"); + + tester.TestStringLines( + "LineNumbers-CRLF", + + "\r\n" // 1 Doc (arguably should be line 2) + "\n" // 2 DecL + "\r\n" // 3 Element + "\n" // 4 + "text contining new line \n" // 5 Text + " and also containing crlf \r\n" // 6 + "", // 10 Element + + "D01L02E03T05E07T07E10"); + + tester.TestFileLines( + "LineNumbers-File", + "resources/utf8test.xml", + "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10"); + } + + { + const char* xml = "Text"; + XMLDocument doc; + doc.Parse(xml); + XMLTest("Test mismatched elements.", true, doc.Error()); + XMLTest("Test mismatched elements.", XML_ERROR_MISMATCHED_ELEMENT, doc.ErrorID()); + // For now just make sure calls work & doesn't crash. + // May solidify the error output in the future. + printf("%s\n", doc.ErrorStr()); + doc.PrintError(); + } + + // ----------- Performance tracking -------------- + { +#if defined( _MSC_VER ) + __int64 start, end, freq; + QueryPerformanceFrequency((LARGE_INTEGER*)&freq); +#endif + + FILE* perfFP = fopen("resources/dream.xml", "r"); + XMLTest("Open dream.xml", true, perfFP != 0); + fseek(perfFP, 0, SEEK_END); + long size = ftell(perfFP); + fseek(perfFP, 0, SEEK_SET); + + char* mem = new char[size + 1]; + memset(mem, 0xfe, size); + size_t bytesRead = fread(mem, 1, size, perfFP); + XMLTest("Read dream.xml", true, uint32_t(size) >= uint32_t(bytesRead)); + fclose(perfFP); + mem[size] = 0; + +#if defined( _MSC_VER ) + QueryPerformanceCounter((LARGE_INTEGER*)&start); +#else + clock_t cstart = clock(); +#endif + bool parseDreamXmlFailed = false; + static const int COUNT = 10; + for (int i = 0; i < COUNT; ++i) { + XMLDocument doc; + doc.Parse(mem); + parseDreamXmlFailed = parseDreamXmlFailed || doc.Error(); + } +#if defined( _MSC_VER ) + QueryPerformanceCounter((LARGE_INTEGER*)&end); +#else + clock_t cend = clock(); +#endif + XMLTest( "Parse dream.xml", false, parseDreamXmlFailed ); + + delete[] mem; + + static const char* note = +#ifdef TINYXML2_DEBUG + "DEBUG"; +#else + "Release"; +#endif + +#if defined( _MSC_VER ) + const double duration = 1000.0 * (double)(end - start) / ((double)freq * (double)COUNT); +#else + const double duration = (double)(cend - cstart) / (double)COUNT; +#endif + printf("\nParsing dream.xml (%s): %.3f milli-seconds\n", note, duration); + } + +#if defined( _MSC_VER ) && defined( TINYXML2_DEBUG ) + { + _CrtMemCheckpoint( &endMemState ); + + _CrtMemState diffMemState; + _CrtMemDifference( &diffMemState, &startMemState, &endMemState ); + _CrtMemDumpStatistics( &diffMemState ); + + { + int leaksBeforeExit = _CrtDumpMemoryLeaks(); + XMLTest( "No leaks before exit?", FALSE, leaksBeforeExit ); + } + } +#endif + + printf ("\nPass %d, Fail %d\n", gPass, gFail); + + // return gFail; + exit( gFail ); +} + +