DIRECTORY Ascii USING [BS, ControlA, ControlQ, ControlW, ControlX, DEL], BasicTime USING[ TimeNotKnown ], Booting USING[ Switches, switches ], DebuggerSwap USING [EnableSwatWatcher], DefaultRemoteNames USING [DefaultNames, Get], File USING [Error, RC, Volume, LogicalInfo, NextVolume], FS USING [Error], FSPseudoServers USING [GetPseudoServers, PseudoServerList], FSPseudoServersExtra USING [DeletePseudoServer, InsertPseudoServer, PseudoServerFromRope, RopeFromPseudoServer], GermSwap USING[ bootedFrom, Switch ], IagoCommands USING [Attach, BootLogical, Copy, CreateLogical, CreatePhysical, CreateUserWorld, CreateVM, Delete, DescribeDrives, DescribeLV, DescribeMachine, DescribePV, EraseLogical, FlushCache, FormatOrScan, InstallCredentials, InstallInitial, InstallLogicalFile, ListCache, ListFileInfo, ListNames, Login, Rename, Rollback, RunDiagnosticBCD, Scavenge, SetKeep, SetPhysicalFile, SetWDir], IagoOps USING [CommandInfo, Confirm, FileError, GetArg, GetCommand, ReadRemoteNames, RegisterCommand, ReserveAltoRegions, Rubout, WriteRemoteNames], IO USING [EraseChar, GetChar, PutChar, PutF, PutRope, STREAM], PhysicalVolume USING [Physical, NextPhysical], Rope USING [Cat, Concat, Fetch, FromChar, Length, ROPE, SkipTo, Substr], SimpleTerminal USING [TurnOff, TurnOn]; IagoMainImpl: CEDAR PROGRAM IMPORTS BasicTime, Booting, DebuggerSwap, DefaultRemoteNames, File, FS, FSPseudoServers, FSPseudoServersExtra, GermSwap, IagoCommands, IagoOps, IO, PhysicalVolume, Rope, SimpleTerminal = { PseudoServerList: TYPE = FSPseudoServers.PseudoServerList; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; DiskState: TYPE = {diskIsOK, bootedWithN, noPhysicalVolume, notCedarDisk, diskNotReady}; DoCommand: PROC [in, out: STREAM, c: IagoOps.CommandInfo] RETURNS [exit: BOOL _ FALSE, overwritten: BOOL _ FALSE] = { ENABLE { IagoOps.Rubout => { IO.PutRope[out, " XXX"]; GO TO leave }; File.Error => { IO.PutRope[out, " ... \n "]; IO.PutRope[out, IagoOps.FileError[why]]; GO TO leave }; FS.Error => { IO.PutRope[out, " ... \n "]; IO.PutRope[out, IF error.explanation.Length[] # 0 THEN error.explanation ELSE "FS.Error without a message: consult an expert"]; GO TO leave }; BasicTime.TimeNotKnown => { IO.PutRope[out, " ... I can't do that without knowing the current time."]; GO TO leave }; ForceExit => { exit _ TRUE; GO TO leave }; Overwritten => { overwritten _ TRUE; GO TO leave }; }; c.commandProc[in, out]; EXITS leave => {}; }; ForceExit: ERROR = CODE; Overwritten: ERROR = CODE; InitCommands: PROC = { IagoOps.RegisterCommand[[ IagoCommands.Attach, "Attach File"]]; IagoOps.RegisterCommand[[ IagoCommands.BootLogical, "Boot Logical Volume"]]; IagoOps.RegisterCommand[[ CheckDriveCommand, "Check Drive", TRUE]]; IagoOps.RegisterCommand[[ ClearPseudoServerCommand, "Clear Pseudo Server"]]; IagoOps.RegisterCommand[[ IagoCommands.Copy, "Copy File"]]; IagoOps.RegisterCommand[[ IagoCommands.CreateLogical, "Create Logical Volume"]]; IagoOps.RegisterCommand[[ CreatePhysicalCommand, "Create Physical Volume", TRUE]]; IagoOps.RegisterCommand[[ IagoCommands.CreateUserWorld, "Create User World", TRUE]]; IagoOps.RegisterCommand[[ IagoCommands.CreateVM, "Create VM Backing File"]]; IagoOps.RegisterCommand[[ IagoCommands.Delete, "Delete Files"]]; IagoOps.RegisterCommand[[ IagoCommands.DescribeDrives, "Describe Drives", TRUE]]; IagoOps.RegisterCommand[[ IagoCommands.DescribeLV, "Describe Logical Volumes"]]; IagoOps.RegisterCommand[[ IagoCommands.DescribeMachine, "Describe Machine", TRUE]]; IagoOps.RegisterCommand[[ IagoCommands.DescribePV, "Describe Physical Volumes", TRUE]]; IagoOps.RegisterCommand[[ IagoCommands.EraseLogical, "Erase Logical Volume"]]; IagoOps.RegisterCommand[[ IagoCommands.FlushCache, "Flush Cache"]]; IagoOps.RegisterCommand[[ FormatCommand, "Format Disk", TRUE]]; IagoOps.RegisterCommand[[ InstallBootFileCommand, "Install Boot File"]]; IagoOps.RegisterCommand[[ IagoCommands.InstallCredentials, "Install Credentials"]]; IagoOps.RegisterCommand[[ InstallGermFileCommand, "Install Germ"]]; IagoOps.RegisterCommand[[ IagoCommands.InstallInitial, "Install Initial Microcode", TRUE]]; IagoOps.RegisterCommand[[ InstallMicrocodeFileCommand, "Install Cedar Microcode"]]; IagoOps.RegisterCommand[[ IagoCommands.ListCache, "List Cache"]]; IagoOps.RegisterCommand[[ IagoCommands.ListFileInfo, "List File Info", TRUE]]; IagoOps.RegisterCommand[[ IagoCommands.ListNames, "List Names"]]; IagoOps.RegisterCommand[[ ListPseudoServerCommand, "List Pseudo Servers"]]; IagoOps.RegisterCommand[[ LoginCommand, "Login", TRUE]]; IagoOps.RegisterCommand[[ QuitCommand, "Quit"]]; IagoOps.RegisterCommand[[ IagoCommands.Rename, "Rename"]]; IagoOps.RegisterCommand[[ IagoOps.ReserveAltoRegions, "Reserve Alto Regions", TRUE]]; IagoOps.RegisterCommand[[ IagoCommands.Rollback, "Rollback Logical Volume"]]; IagoOps.RegisterCommand[[ IagoCommands.RunDiagnosticBCD, "Run Diagnostic BCD", TRUE]]; IagoOps.RegisterCommand[[ IagoCommands.Scavenge, "Scavenge"]]; IagoOps.RegisterCommand[[ IagoCommands.SetKeep, "Set Keep"]]; IagoOps.RegisterCommand[[ SetPhysicalBootCommand, "Set Physical Boot File"]]; IagoOps.RegisterCommand[[ SetPhysicalGermCommand, "Set Physical Germ"]]; IagoOps.RegisterCommand[[ SetPhysicalMicrocodeCommand, "Set Physical Microcode"]]; IagoOps.RegisterCommand[[ SetPseudoServerCommand, "Set Pseudo Server"]]; IagoOps.RegisterCommand[[ SetRemoteNamesCommand, "Set Remote Names"]]; IagoOps.RegisterCommand[[ IagoCommands.SetWDir, "Set Working Directory"]]; }; Main: PROC[in, out: STREAM, mode: { normal, nSwitch, createWorld }] = { remoteNames: DefaultRemoteNames.DefaultNames = DefaultRemoteNames.Get[]; InitCommands[]; IO.PutRope[out, "\n\nType \"?\" at any time if you need help.\n"]; IF Booting.switches[d] THEN IO.PutRope[out, "Booted with the \"D\" switch.\n"]; IO.PutF[out, " (systemHost: %g, userHost: %g)\n", [rope[remoteNames.systemHost]], [rope[remoteNames.userHost]] ]; PrintPseudoServerList[out, FSPseudoServers.GetPseudoServers[]]; DO ENABLE { ABORTED => EXIT; IagoOps.Rubout => { IO.PutRope[out, " XXX"]; LOOP }; }; c: IagoOps.CommandInfo = IagoOps.GetCommand[in: in, out: out, diskReadable: mode = normal]; exit, overwritten: BOOL; [exit, overwritten] _ DoCommand[in, out, c]; IF overwritten THEN mode _ normal; IF exit THEN EXIT; ENDLOOP; IO.PutRope[out, "\nLeaving Iago ...\n"]; }; UseIago: PROC = { in, out: STREAM; [in: in, out: out] _ SimpleTerminal.TurnOn[]; Main[in: in, out: out, mode: normal ! UNWIND => SimpleTerminal.TurnOff[]]; SimpleTerminal.TurnOff[]; }; DoIt: PROC = { in, out: STREAM; etherBoot: BOOL = GermSwap.bootedFrom.location.deviceType = ethernet; bootedWithN: BOOL = Booting.switches[n]; ignoreDisk: BOOL_ FALSE; rootStatus: File.RC_ ok; IF ~bootedWithN THEN rootStatus_ CheckForDisk[]; ignoreDisk_ bootedWithN OR (rootStatus#ok); IagoCommands.Login[[ignoreDiskEntirely: ignoreDisk]]; IF NOT bootedWithN THEN DebuggerSwap.EnableSwatWatcher[TRUE] -- ELSE it may be enabled by the "I" switch--; [in: in, out: out] _ SimpleTerminal.TurnOn[]; IF ~ignoreDisk THEN [] _ IagoOps.ReadRemoteNames[NIL]; IF etherBoot THEN { DO IO.PutRope[out, "\nDo you want to initialize your disk from scratch for use by Cedar (selecting from the standard options I will offer you)? "]; IF NOT IagoOps.Confirm[in, out ! IagoOps.Rubout => CONTINUE] THEN EXIT; [] _ DoCommand[in, out, [IagoCommands.CreateUserWorld, "Create User World"]]; ENDLOOP; }; SELECT TRUE FROM ignoreDisk => { SELECT rootStatus FROM ok => IF bootedWithN THEN IO.PutRope[out, "\nBooted with the \"N\" switch."]; inconsistent => IO.PutRope[out, "\nRoot page is inconsistent (wrong version?)."]; nonCedarVolume => IO.PutRope[out, "\nNot a Cedar disk."]; wentOffline => IO.PutRope[out, "\nDisk went offline."]; hardware => IO.PutRope[out, "\nHard disk error reading the volume root page."]; ENDCASE => IO.PutRope[out, "\nOther file error"]; IO.PutRope[out, " Invoking Iago, with restricted command set"]; Main[in: in, out: out, mode: nSwitch]; }; Booting.switches[l] OR etherBoot => { IO.PutRope[out, "\nDo you want to use \"Iago\", the Cedar disk utility program? "]; IF IagoOps.Confirm[in, out ! IagoOps.Rubout => CONTINUE] THEN Main[in: in, out: out, mode: normal]; }; ENDCASE => NULL; SimpleTerminal.TurnOff[]; }; CheckForDisk: PROC RETURNS[rt: File.RC] = BEGIN v: File.Volume; IF PhysicalVolume.NextPhysical[NIL] = NIL THEN RETURN[nonCedarVolume]; IF (v_ File.NextVolume[NIL]) = NIL THEN RETURN[nonCedarVolume]; rt_ File.LogicalInfo[v].rootStatus; END; CheckDriveCommand: PROC [in,out: STREAM] = TRUSTED { IagoCommands.FormatOrScan[in: in, out: out, format: FALSE] }; CreatePhysicalCommand: PROC [in,out: STREAM] = { IF IagoCommands.CreatePhysical[in, out] THEN ERROR Overwritten; }; FormatCommand: PROC [in,out: STREAM] = TRUSTED { IagoCommands.FormatOrScan[in: in, out: out, format: TRUE]; }; InstallBootFileCommand: PROC [in,out: STREAM] = { IagoCommands.InstallLogicalFile[in, out, bootFile]; }; InstallGermFileCommand: PROC [in,out: STREAM] = { IagoCommands.InstallLogicalFile[in, out, germ]; }; InstallMicrocodeFileCommand: PROC [in,out: STREAM] = { IagoCommands.InstallLogicalFile[in, out, microcode]; }; LoginCommand: PROC [in,out: STREAM] = { IagoCommands.Login[[alwaysInteract: TRUE, ignoreDiskEntirely: TRUE]]; }; QuitCommand: PROC [in,out: STREAM] = { IO.PutRope[out, "\nAre you sure? "]; IF IagoOps.Confirm[in, out] THEN ERROR ForceExit; }; SetPhysicalBootCommand: PROC [in,out: STREAM] = { IagoCommands.SetPhysicalFile[in, out, bootFile]; }; SetPhysicalGermCommand: PROC [in,out: STREAM] = { IagoCommands.SetPhysicalFile[in, out, germ]; }; SetPhysicalMicrocodeCommand: PROC [in,out: STREAM] = { IagoCommands.SetPhysicalFile[in, out, microcode]; }; StripBrackets: PROC [name: ROPE] RETURNS [ROPE] = { len: INT _ Rope.Length[name]; pos1: INT _ Rope.SkipTo[name, 0, "["]; pos2: INT _ Rope.SkipTo[name, 0, "]"]; nlen: INT _ pos2-pos1-1; IF pos2 = len AND pos1 = len AND len > 0 THEN RETURN [name]; IF nlen <= 0 THEN RETURN [NIL]; RETURN [Rope.Substr[name, pos1+1, nlen]]; }; SetRemoteNamesCommand: PROC [in,out: STREAM] = { names: DefaultRemoteNames.DefaultNames = DefaultRemoteNames.Get[]; systemHost: ROPE _ StripBrackets[names.systemHost]; userHost: ROPE _ StripBrackets[names.userHost]; systemHost _ StripBrackets[IagoOps.GetArg[in, out, "\n System Host: ", systemHost, NIL]]; IF systemHost = NIL THEN GO TO bailOut; userHost _ StripBrackets[IagoOps.GetArg[in, out, "\n User Host: ", userHost, NIL]]; IF userHost = NIL THEN GO TO bailOut; names.systemHost _ systemHost _ Rope.Cat["[", systemHost, "]"]; names.userHost _ userHost _ Rope.Cat["[", userHost, "]"]; names.current _ Rope.Cat[ systemHost, Rope.Substr[names.current, Rope.SkipTo[names.current, 0, "]" ]+1]]; [] _ IagoOps.WriteRemoteNames[NIL, systemHost, userHost, out]; EXITS bailOut => { IO.PutRope[out, "\nEmpty host names not permitted, command aborted.\n"]; }; }; PrintPseudoServerList: PROC [out: STREAM, list: PseudoServerList] = { FOR each: PseudoServerList _ list, each.rest WHILE each # NIL DO IO.PutRope[out, " "]; IO.PutRope[out, FSPseudoServersExtra.RopeFromPseudoServer[each]]; IO.PutRope[out, "\n"]; ENDLOOP; }; GetLine: PROC [in, out: STREAM, prompt: ROPE] RETURNS [line: ROPE _ NIL] = { c: CHAR _ 0C; EraseAll: PROC = { FOR i: INT DECREASING IN [0..Rope.Length[line]) DO IO.EraseChar[out, Rope.Fetch[line, i]]; ENDLOOP; line _ NIL; }; IO.PutRope[out, prompt]; DO c: CHAR _ IO.GetChar[in]; len: INT _ Rope.Length[line]; SELECT c FROM '\n => RETURN; Ascii.DEL => RETURN [NIL]; Ascii.ControlA, Ascii.BS => IF len > 0 THEN { len _ len - 1; IO.EraseChar[out, Rope.Fetch[line, len]]; line _ Rope.Substr[line, 0, len]; }; Ascii.ControlW, Ascii.ControlQ => { alpha: BOOL _ FALSE; FOR i: INT DECREASING IN [0..len) DO ch: CHAR = Rope.Fetch[line, i]; SELECT ch FROM IN ['A..'Z], IN ['a..'z], IN ['0..'9] => alpha _ TRUE; ENDCASE => IF alpha THEN {line _ Rope.Substr[line, 0, i + 1]; EXIT}; IO.EraseChar[out, ch]; REPEAT FINISHED => line _ NIL; ENDLOOP; }; Ascii.ControlX => EraseAll[]; ENDCASE => { line _ Rope.Concat[line, Rope.FromChar[c]]; IO.PutChar[out, c]; }; ENDLOOP; }; SetPseudoServerCommand: PROC [in,out: STREAM] = { line: ROPE _ GetLine[in, out, "\n Syntax: *\n Switches: -r assumes files are replicated\n Pseudo server line: "]; err: ROPE _ NIL; new: PseudoServerList; [err, new] _ FSPseudoServersExtra.PseudoServerFromRope[line]; IF err = NIL THEN { FSPseudoServersExtra.InsertPseudoServer[new]; [] _ IagoOps.WriteRemoteNames[NIL, NIL, NIL, out]; } ELSE { IO.PutRope[out, "\n-- Can't set pseudo server, "]; IO.PutRope[out, err]; }; IO.PutRope[out, "\n"]; }; ClearPseudoServerCommand: PROC [in,out: STREAM] = { server: ROPE _ IagoOps.GetArg[in, out, "\n Pseudo server: ", NIL, NIL]; IF FSPseudoServersExtra.DeletePseudoServer[server] # NIL THEN { IO.PutRope[out, "\n-- Cleared.\n"]; [] _ IagoOps.WriteRemoteNames[NIL, NIL, NIL, out]; } ELSE IO.PutRope[out, "\n-- No such pseudo server.\n"]; }; ListPseudoServerCommand: PROC [in,out: STREAM] = { list: PseudoServerList _ FSPseudoServers.GetPseudoServers[]; IO.PutRope[out, "\n"]; IF list = NIL THEN IO.PutRope[out, "-- No pseudo servers.\n"] ELSE PrintPseudoServerList[out, FSPseudoServers.GetPseudoServers[]]; }; DoIt[]; }. ^IagoMainImpl.mesa - Iago user interface Copyright c 1984 by Xerox Corporation. All rights reserved. Andrew Birrell December 7, 1983 4:07 pm Levin, September 22, 1983 1:32 pm Russ Atkinson, June 14, 1984 5:38:47 pm PDT Willie-Sue, August 14, 1984 1:51:27 pm PDT ******** Main program ******** This is intended for use from the Cedar interpreter We always set the remote host names if we are allowed to touch the disk. This is true even when we don't use the rest of Iago so we can redirect system host names as soon as reasonable. We don't care if we can't read them right now. Write the remote names on the system volume text to be backed up is of the form ..., the and following are to be removed. Write the remote names on the system volume Write the remote names on the system volume Ê®˜šœ'™'Jšœ Ïmœ1™Kšœ žœ˜ Kšœžœ˜$Kšœ žœ˜'Kšœžœ˜-Kšœžœ žœ#˜8Kšžœžœ ˜Kšœžœ&˜;KšœžœV˜pKšœ žœ˜%Kšœ žœô˜†Kšœžœ‡˜”Kšžœžœ.žœ˜>Kšœžœ˜.Kšœžœ(žœ˜HKšœžœ˜'—J˜šœžœž˜Kšžœ=žœJžœ*˜¼—˜Jšœžœ$˜:Jšžœžœžœ˜Jšžœžœžœžœ˜J˜Jšœ žœI˜X—˜J˜—Jšœ,™,˜šÏn œž˜Jšœ žœ˜)Jš žœžœžœžœžœ˜;šžœ˜šœ˜Jšžœ˜Jšžœžœ˜ Jšœ˜—šœ˜Jšžœ˜Jšžœ&˜(Jšžœžœ˜ Jšœ˜—šžœ ˜ Jšžœ˜šžœ˜šžœ˜!Jšžœ˜Jšžœ2˜6——Jšžœžœ˜ Jšœ˜—šœ˜JšžœH˜JJšžœžœ˜ Jšœ˜—šœ˜Jšœžœ˜ Jšžœžœ˜ Jšœ˜—šœ˜Jšœžœ˜Jšžœžœ˜ Jšœ˜—Jšœ˜—Jšœ˜Jšžœ ˜Jšœ˜J˜—šœ žœžœ˜J˜—šœ žœžœ˜J˜—šŸ œžœ˜šœ˜Jšœ%˜%—šœ˜Jšœ2˜2—šœ˜Jšœ"žœ˜)—šœ˜Jšœ2˜2—šœ˜Jšœ!˜!—šœ˜Jšœ6˜6—šœ˜Jšœ1žœ˜8—šœ˜Jšœ3žœ˜:—šœ˜Jšœ2˜2—šœ˜Jšœ&˜&—šœ˜Jšœ0žœ˜7—šœ˜Jšœ6˜6—šœ˜Jšœ2žœ˜9—šœ˜Jšœ6žœ˜=—šœ˜Jšœ4˜4—šœ˜Jšœ)˜)—šœ˜Jšœžœ˜%—šœ˜Jšœ.˜.—šœ˜Jšœ9˜9—šœ˜Jšœ)˜)—šœ˜Jšœ:žœ˜A—šœ˜Jšœ9˜9—šœ˜Jšœ'˜'—šœ˜Jšœ-žœ˜4—šœ˜Jšœ'˜'—šœ˜Jšœ1˜1—šœ˜Jšœžœ˜—šœ˜Jšœ˜—šœ˜Jšœ ˜ —šœ˜Jšœ4žœ˜;—šœ˜Jšœ3˜3—šœ˜Jšœ5žœ˜<—šœ˜Jšœ$˜$—šœ˜Jšœ#˜#—šœ˜Jšœ3˜3—šœ˜Jšœ.˜.—šœ˜Jšœ8˜8—šœ˜Jšœ.˜.—šœ˜Jšœ,˜,—šœ˜Jšœ0˜0—J˜—J˜šŸœžœ žœ-˜GJšœH˜HJ˜Jšžœ@˜BJšžœžœ1˜Ošžœ0˜2Jšœ?˜?—Jšœ?˜?šž˜šžœ˜Jšžœžœ˜Jšœžœžœ˜4Jšœ˜—šœ˜JšœB˜B—Jšœžœ˜Jšœ,˜,Jšžœ žœ˜"Jšžœžœžœ˜Jšžœ˜—Jšžœ&˜(Jšœ˜—J˜šŸœžœ˜Jšœ3™3Jšœ žœ˜Jšœ-˜-Jšœ&žœ˜JJšœ˜Jšœ˜—J˜šŸœžœ˜Jšœ žœ˜Jšœ žœ6˜EJšœ žœ˜(Jšœ žœžœ˜Jšœžœ˜Jšžœžœ˜0Jšœžœ˜+Jšœ5˜5šžœžœ ž˜JšœžœÏc-œ˜S—Jšœ-˜-šžœ žœžœ˜6Jšœê™ê—šžœ žœ˜šž˜šžœ ˜Jšœ€˜€—Jš žœžœ-žœžœžœ˜GJšœM˜MJšžœ˜—Jšœ˜—šž˜šœ˜šžœ ž˜Jšœžœ žœžœ1˜MJšœžœ?˜QJšœžœ%˜9Jšœžœ&˜7Jšœ žœA˜OJšžœžœ$˜2—Jšžœ>˜@Jšœ&˜&Jšœ˜—šœžœ˜%JšžœQ˜Sšžœ-žœž˜=Jšœ%˜%—Jšœ˜—Jšžœžœ˜—Jšœž˜Jšœ˜—J˜šŸ œžœžœ žœ˜)šž˜Jšœ˜Jš žœžœžœžœžœ˜FJš žœžœžœžœžœ˜?Jšœ#˜#—Jšžœ˜J˜—šŸœžœ žœžœ˜4Jšœ4žœ˜:Jšœ˜J˜—šŸœžœ žœ˜0Jšžœ&žœžœ ˜?Jšœ˜J˜—šŸ œžœ žœžœ˜0Jšœ4žœ˜:Jšœ˜J˜—šŸœžœ žœ˜1Jšœ3˜3Jšœ˜J˜—šŸœžœ žœ˜1Jšœ/˜/Jšœ˜J˜—šŸœžœ žœ˜6Jšœ4˜4Jšœ˜J˜—šŸ œžœ žœ˜'Jšœ$žœžœ˜EJšœ˜J˜—šŸ œžœ žœ˜&Jšžœ"˜$Jšžœžœžœ ˜1Jšœ˜J˜—šŸœžœ žœ˜1Jšœ0˜0Jšœ˜J˜—šŸœžœ žœ˜1Jšœ,˜,Jšœ˜J˜—šŸœžœ žœ˜6Jšœ1˜1Jšœ˜J˜—š Ÿ œžœžœžœžœ˜3Jšœžœ˜Jšœžœ˜&Jšœžœ˜&Jšœžœ˜Jš žœ žœ žœ žœžœ˜Jšœ+™+—šžœ ˜JšžœF˜HJ˜—J˜—J˜šŸœžœžœ˜Ešžœ*žœžœž˜@Jšžœ˜Jšžœ?˜AJšžœ˜Jšžœ˜—J˜J˜—š Ÿœžœ žœ žœžœž œ˜LJšœžœ˜ šŸœžœ˜š žœžœž œžœž˜2Jšžœ%˜'Jšžœ˜—Jšœžœ˜ J˜—Jšžœ˜šž˜Jšœžœžœ ˜Jšœžœ˜šžœž˜ Jšœžœ˜Jšœžœžœžœ˜šœžœ˜šžœ žœ˜J˜Jšžœ'˜)Jšœ!˜!Jšœ˜——šœ#˜#Jšœ~™~Jšœžœžœ˜š žœžœž œžœ ž˜$Jšœžœ˜šžœž˜Jšžœ žœ žœžœ˜6Jšžœžœžœ&žœ˜D—Jšžœ˜šž˜Jšžœ žœ˜—Jšžœ˜—J˜—Jšœ˜šžœ˜ Jšœ+˜+Jšžœ˜Jšœ˜——Jšžœ˜—Jšœ˜J˜—šŸœžœ žœ˜1Kšœžœ‰˜“Kšœž ˜Kšœ˜Kšœ=˜=šžœž˜ šžœ˜Kšœ-˜-šœžœžœžœ˜2Jšœ+™+—K˜—šžœ˜Kšžœ0˜2Kšžœ˜K˜——Kšžœ˜K˜K˜—šŸœžœ žœ˜3Jšœžœ2žœžœ˜Hšžœ3ž˜8šžœ˜Jšžœ!˜#šœžœžœžœ˜2Jšœ+™+—J˜—Jšžœžœ/˜6—J˜J˜—šŸœžœ žœ˜2Jšœ<˜