DIRECTORY Ascii USING [BS, CR, FF, SP, TAB], BasicTime USING [earliestGMT, GMT, Now, Period, Unpack, Update], Convert USING [RopeFromInt], FileStream USING [OpenFileFromStream], FS USING[ Delete, Error, GetInfo, nullOpenFile, Open, OpenFile, SetByteCountAndCreatedTime, StreamOpen ], IO USING [Close, CreateStreamProcs, CreateStream, Flush, PutChar, PutF, PutFR, PutRope, STREAM, Value], Loader USING [BCDBuildTime], LupineMakeRpcModules USING [ MakeRpcControlModule, MakeRpcClientModule, MakeRpcClientBinderModule, MakeRpcServerModule ], LupineManager USING [], LupineManagerPrivate USING [ Abort, Error, ErrorCode, ErrorHandlerProc, ErrorType, ExplanationProc, IsNull, Language, ModuleTypes, Nest, Options, ParamPassingMethod, SHORT, String, StringNIL], LupineMarshal USING [ParameterProtocolVersions], LupineSymbolTable USING [ CloseInterface, GetInterfaceInfo, GMT, InterfaceInfo, OpenError, OpenInterface, VersionStampString, VersionStamp ], Rope USING [Cat, Find, Length, ROPE, Substr]; LupineManagerImpl: MONITOR IMPORTS BasicTime, Convert, FileStream, FS, IO, Loader, LupineMakeRpcModules, LupineManagerPrivate, Marshal: LupineMarshal, ST: LupineSymbolTable, Rope EXPORTS LupineManager, LupineManagerPrivate = BEGIN OPEN LupineManagerPrivate; LastCodeFileGMT: BasicTime.GMT _ BasicTime.earliestGMT; TranslateRemoteInterface: PUBLIC ENTRY PROCEDURE [ interfaceBcdFilename: String, interfaceBcdCapability: FS.OpenFile _ FS.nullOpenFile, errorHandler: ErrorHandlerProc, options: Options, desiredLineLength: LONG INTEGER ] = BEGIN ENABLE BEGIN UNWIND => NULL; AbortTranslation => GOTO AbortTranslation; ST.OpenError => -- This can come from ST.Open or MakeRpcXXX. Abort[ code: (SELECT why FROM badFileFormat => BadBcdFileFormat, badFileName => NoSuchFile, badFileVersion => BadBcdFileVersion, notInterfaceModule => NotInterfaceModule, ENDCASE => ERROR), problemText: fileOrModuleName]; END; -- ENABLE. EstablishErrorHandler[errorHandler]; SetCodeLineLength[desiredLineLength]; GetInterface[interfaceBcdFilename, interfaceBcdCapability]; BEGIN ENABLE UNWIND => { ST.CloseInterface; ClearErrorHandler }; interfaceName: String; contents: ST.InterfaceInfo; [contents: contents, moduleName: interfaceName] _ ST.GetInterfaceInfo[]; MakeModuleNames[interfaceName, options.targetLanguage]; BEGIN ENABLE UNWIND => FreeModuleNames[]; IF contents.variables THEN Error[InterfaceVariables, interfaceBcdFilename]; IF contents.transfers[Port] OR contents.transfers[Process] OR contents.transfers[Program] OR contents.transfers[Other] THEN Error[UnsupportedTransfers, interfaceBcdFilename]; BEGIN OPEN LupineMakeRpcModules; MakeRpcControlModule[options ! AbortTranslation => CONTINUE]; MakeRpcClientModule[options ! AbortTranslation => CONTINUE]; MakeRpcClientBinderModule[options ! AbortTranslation => CONTINUE]; MakeRpcServerModule[options ! AbortTranslation => CONTINUE]; END; END; -- ENABLE UNWIND => FreeModuleNames. FreeModuleNames[]; END; -- ENABLE UNWIND => ST.CloseInterface. ST.CloseInterface; ClearErrorHandler; EXITS AbortTranslation => NULL; -- The GOTO's UNWIND will cleanup. END; -- TranslateRemoteInterface. GetInterface: PROCEDURE [ interfaceFilename: String, interfaceCapability: FS.OpenFile ] = BEGIN IF interfaceCapability = FS.nullOpenFile THEN interfaceCapability _ FS.Open[AppendBcd[interfaceFilename] ! FS.Error => GOTO noFile ]; ST.OpenInterface[interfaceFilename, interfaceCapability]; EXITS noFile => Abort[code: NoSuchFile, problemText: interfaceFilename]; END; AppendBcd: PROCEDURE [s: String] RETURNS[new: String] = INLINE BEGIN IF Rope.Find[s, "."] >= 0 THEN new _ s ELSE new _ s.Cat[".bcd"] END; clientErrorHandler: ErrorHandlerProc _ NIL; EstablishErrorHandler: PROCEDURE [handler: ErrorHandlerProc] = INLINE {clientErrorHandler _ handler}; ClearErrorHandler: PROCEDURE = INLINE {clientErrorHandler _ NIL}; AbortTranslation: PRIVATE ERROR = CODE; ReportError: PUBLIC PROCEDURE [ type: ErrorType, code: ErrorCode, problemText: String ] = BEGIN Report: ExplanationProc = BEGIN clientSaysAbort: BOOLEAN = clientErrorHandler[ type: type, code: code, codeExplanation: explanation, outputFileName: GetCodeFileName[], outputFileCharPosition: GetCodeStreamIndex[], problemCausingText: problemText ].abortTranslation; IF type=abort OR clientSaysAbort THEN ERROR AbortTranslation; END; -- Explainer. GiveExplanation[code: code, explainer: Report]; END; GiveExplanation: PUBLIC PROCEDURE [ code: ErrorCode, explainer: ExplanationProc ] = BEGIN Explanation: PACKED ARRAY ErrorCode OF --explanation:-- String = [ AnonymousIdentifier: "Unnamed item (probably record component) encountered; cannot marshal this anonymous item.", BadBcdFileFormat: "Module or file has invalid BCD or symbols format.", BadBcdFileVersion: "So-called BCD file has an incorrect version stamp.", ComputedVariant: "Address-containing computed or overlaid variant record encountered; cannot marshal these records.", ComputedSequence: "Computed sequence encountered; cannot marshal these sequences.", EmbeddedRESULT: "VAR or RESULT parameter has embedded addresses; cannot marshal these parameters.", EmptyArray: "Empty (hint for dynamic?) array encountered; use explicit descriptors and sequences instead.", HandleREF: "REF-containing type being passed as a handle; this is extremely dangerous for the collector.", ImproperPassingMethod: "Parameter uses call by VAR, VALUE, RESULT, or HANDLE improperly.", ImproperReadonlyRESULT: "Readonly parameter cannot be called by VAR or RESULT.", ImproperRESULTResult: "Result parameter called by VAR or RESULT; only arguments can be called by VAR and RESULT.", InterfaceVariables: "Interface contains variables; interface variables are not supported.", InvalidHandle: "Ref or pointer to unspecified, completely opaque, or ANY encountered; it must be passed as a HANDLE.", MdsAllocation: "Argument or result requires allocating short POINTER storage (in the MDS).", NoSuchFile: "Could not find required file or module.", NotInterfaceModule: "Specified file is not a DEFINITIONS module; PROGRAM module translation is not supported.", ProbablePointerRecursion: "Probable list, tree, or graph detected; can only marshal explicit LIST OF types.", TransferParameter: "Cannot YET marshal transfer (e.g., procedure) parameter.", SequenceInsideVariant: "An arm of a variant record contains a sequence; this marshaling is not implemented.", ShortInterMdsPointers: "Parameter of interMDS call contains short pointers; use long pointers instead.", UnimplementedMarshaling: "Marshaling this type is either impossible or unimplemented.", Unknown: "", UnsupportedTransfers: "Interface contains PROCESSES, PROGRAMS, or PORTS; only procedures, signals, and errors are supported." ]; explainer[Explanation[code]]; END; moduleNames: ARRAY ModuleTypes OF String _ ALL[StringNIL]; ModuleName: PUBLIC PROC [module: ModuleTypes] RETURNS [--name:-- String] = BEGIN RETURN[moduleNames[module]] END; MakeModuleNames: PROCEDURE [interfaceName: String, language: Language] = BEGIN RpcInterfaceName: PACKED ARRAY Language OF String = [ Cedar: "RPC", Mesa: "MesaRPC" ]; RpcLupineInterfaceName: PACKED ARRAY Language OF String = [ Cedar: "RPCLupine", Mesa: "MesaRPCLupine" ]; MakeName: PROC [root: String, suffix: String_StringNIL] RETURNS[rootSuffix: String] = BEGIN RETURN[root.Cat[suffix]] END; -- MakeName. moduleNames[interface] _ MakeName[interfaceName]; moduleNames[openedInterface] _ MakeName[StringNIL]; moduleNames[control] _ MakeName[interfaceName, "RpcControl"]; moduleNames[client] _ MakeName[interfaceName, "RpcClientImpl"]; moduleNames[clientBinder] _ MakeName[interfaceName, "RpcBinderImpl"]; moduleNames[server] _ MakeName[interfaceName, "RpcServerImpl"]; moduleNames[rpcPublic] _ MakeName[RpcInterfaceName[language]]; moduleNames[rpcPrivate] _ MakeName[RpcLupineInterfaceName[language]]; moduleNames[lupineRuntime] _ MakeName["LupineRuntime"]; END; FreeModuleNames: PROCEDURE [] = BEGIN FOR module: ModuleTypes IN ModuleTypes DO moduleNames[module] _ NIL; ENDLOOP; END; codeFilename: String _ NIL; codeStream: ARRAY [1..9] OF IO.STREAM _ ALL[NIL]; codeStreamIndex: ARRAY [1..9] OF LONG INTEGER _ ALL[0]; OutputFileCount: INT _ 1; CurrentOutputFile: INT _ 1; OpenCodeFile: PUBLIC PROCEDURE [codeModuleName: String, numberOfOutputFiles: INT _ 1] = BEGIN OutputFileCount _ numberOfOutputFiles; IF OutputFileCount = 1 THEN { codeStream[1] _ FS.StreamOpen[ fileName: ModuleDotMesa[codeModuleName], accessOptions: $create ]; codeStreamIndex[1] _ 0; } ELSE { nameBeforeImpl: String = codeModuleName.Substr[0, codeModuleName.Length[]-4]; FOR no: INT IN [1..OutputFileCount] DO name: String = nameBeforeImpl.Cat[Convert.RopeFromInt[from: no, showRadix: FALSE] , "Impl.mesa"]; codeStream[no] _ FS.StreamOpen[ fileName: name, accessOptions: $create ]; codeStreamIndex[no] _ 0; ENDLOOP; }; InitializeCodeLinePut; CurrentOutputFile _ 0 ; END; OutputToAllFiles: PUBLIC PROCEDURE = { CurrentOutputFile _ 0 ; } ; NextOutputFile: PUBLIC PROCEDURE = { CurrentOutputFile _ CurrentOutputFile + 1; IF CurrentOutputFile > OutputFileCount THEN CurrentOutputFile _ 1; }; CodeStreamPut: PROCEDURE [char: CHARACTER] = INLINE BEGIN IF CurrentOutputFile = 0 THEN { FOR no: INT IN [1..OutputFileCount] DO codeStream[no].PutChar[char]; codeStreamIndex[no] _ codeStreamIndex[no] + 1; ENDLOOP; } ELSE { codeStream[CurrentOutputFile].PutChar[char]; codeStreamIndex[CurrentOutputFile] _ codeStreamIndex[CurrentOutputFile] + 1; }; END; CodeStreamPutRope: PROCEDURE [rope: String] = INLINE BEGIN IF CurrentOutputFile = 0 THEN { FOR no: INT IN [1..OutputFileCount] DO codeStream[no].PutRope[rope]; codeStreamIndex[no] _ codeStreamIndex[no] + rope.Length[]; ENDLOOP; } ELSE { codeStream[CurrentOutputFile].PutRope[rope]; codeStreamIndex[CurrentOutputFile] _ codeStreamIndex[CurrentOutputFile] + rope.Length[]; }; END; GetCodeFileName: PROC RETURNS [String] = INLINE { RETURN[IF IsNull[codeFilename] THEN StringNIL ELSE codeFilename ]}; GetCodeStreamIndex: PROC RETURNS [LONG INTEGER] = INLINE {IF CurrentOutputFile = 0 THEN RETURN [codeStreamIndex[1]] ELSE RETURN[codeStreamIndex[CurrentOutputFile]]}; StampCodeFile: PUBLIC PROCEDURE [codeModuleName:String] = BEGIN moduleName, fileName: String; now: ST.GMT = BasicTime.Now[]; year: INT = BasicTime.Unpack[now].year; lupineTime: ST.GMT _ Loader.BCDBuildTime[]; moduleVersion: ST.VersionStamp; moduleTime, sourceTime: ST.GMT; [moduleName: moduleName, fileName: fileName, moduleVersion: moduleVersion, moduleCreateTime: moduleTime, sourceCreateTime: sourceTime] _ ST.GetInterfaceInfo[]; CodeStreamPutRope[IO.PutFR["-- Copyright (C) %g by Xerox Corporation. All rights reserved.\n", [integer[year]]]]; CodeStreamPutRope[IO.PutFR[ "-- Stub file %g was translated on %g by Lupine of %g", [rope[codeFilename]], [time[now]], [time[lupineTime]] ]]; CodeStreamPutRope[IO.PutFR["\n-- Source interface %g came from file %g, which was created on %g with version stamp %g from source of %g.\n", [rope[moduleName]], [rope[fileName]], [time[moduleTime]], [rope[ST.VersionStampString[stamp: moduleVersion]]], [time[sourceTime]] ]]; END; StampTranslationOptions: PUBLIC PROCEDURE [options: Options] = BEGIN LanguageString: ARRAY Language OF String = [Cedar: "Cedar", Mesa: "Mesa"]; ParamPassingString: ARRAY ParamPassingMethod OF String = [ Var: "VAR", Value: "VALUE", Result: "RESULT", Handle: "HANDLE", InterMds: "InterMds" ]; BoolString: ARRAY BOOLEAN OF String = [TRUE: "TRUE", FALSE: "FALSE"]; oldest, newest: LONG INTEGER; [oldestSupported: oldest, newestSupported: newest] _ Marshal.ParameterProtocolVersions[]; CodeStreamPutRope[IO.PutFR[" -- The parameters for this translation are: -- Target language = %g -- Default parameter passing = %g -- Deallocate server heap arguments = %g -- Inline RpcServerImpl dispatcher stubs = %g -- Declare signals = %g", [rope[LanguageString[options.targetLanguage]]], [rope[ParamPassingString[options.defaultParamPassing]]], [rope[BoolString[options.freeServerArguments]]], [rope[BoolString[options.inlineServerDispatcherStubs]]], [rope[BoolString[options.declareSignals]]] ]]; CodeStreamPutRope[IO.PutFR[" -- Warn about short POINTER (\"MDS\") allocations = %g -- Maximum number of dynamic heap NEWs = %g, MDS NEWs = %g -- Acceptable parameter protocols = VersionRange[%g..%g].\n", [rope[BoolString[options.warnMDSAllocs]]], [integer[options.maxHeapAllocations]], [integer[options.maxMdsAllocations]], [integer[oldest]], [integer[newest]] ]]; END; -- StampTranslationOptions. CloseCodeFile: PUBLIC PROCEDURE = BEGIN FinalizeCodeLinePut[]; FOR no: INT IN [1..OutputFileCount] DO file: FS.OpenFile; bytes: INT; created: BasicTime.GMT _ BasicTime.earliestGMT; codeStream[no].Flush[]; file _ FileStream.OpenFileFromStream[codeStream[no]]; [bytes: bytes, created: created] _ file.GetInfo[]; IF BasicTime.Period[from: LastCodeFileGMT, to: created] <= 0 THEN { created _ BasicTime.Update[base: LastCodeFileGMT, period: 1]; file.SetByteCountAndCreatedTime[bytes: bytes, created: created]; }; LastCodeFileGMT _ created; codeStream[no].Close[]; codeStreamIndex[no] _ 0; ENDLOOP; codeFilename _ NIL; END; DeleteExistingCodeFiles: PROCEDURE = BEGIN DeleteOne: PROC [module: String] = BEGIN FS.Delete [ name: ModuleDotMesa[module] ! FS.Error => CONTINUE ]; END; DeleteOne[ModuleName[control]]; DeleteOne[ModuleName[client]]; DeleteOne[ModuleName[server]]; END; ModuleDotMesa: PROCEDURE [moduleName: String] RETURNS [String] = INLINE BEGIN RETURN[moduleName.Cat[".mesa"]] END; SpacesPerNest: INTEGER = 2; SpacesPerTab: INTEGER = 4; ExtraSpacesOnWrap: INTEGER = 2*SpacesPerNest; ApproxMaxIdentifierLength: INTEGER = 12; stillLeadingSpaces, doingComment: BOOLEAN; lineLength, spaces, lastHyphen, lineWrapThreshhold: INTEGER; formattedStream: PUBLIC IO.STREAM _ IO.CreateStream[ streamProcs: IO.CreateStreamProcs[variety: output, class: $Lupine, putChar: CodeLinePut], streamData: NIL]; SetCodeLineLength: PROCEDURE [desiredLineLength: LONG INTEGER] = INLINE BEGIN lineWrapThreshhold _ MAX[ 28, SHORT[desiredLineLength]-ApproxMaxIdentifierLength-ExtraSpacesOnWrap ]; END; InitializeCodeLinePut, StartNewCodeLine: PROCEDURE = INLINE BEGIN stillLeadingSpaces _ TRUE; lineLength _ spaces _ 0; lastHyphen _ -1; doingComment _ FALSE; END; FinalizeCodeLinePut: PROCEDURE = INLINE {}; CodeLinePut: SAFE PROCEDURE[self: IO.STREAM, char: CHAR] = TRUSTED BEGIN WrapLine: PROC = BEGIN IF stillLeadingSpaces THEN lineLength _ spaces _ lineWrapThreshhold ELSE BEGIN lineLength _ spaces; IF spaces >= lineWrapThreshhold THEN stillLeadingSpaces _ TRUE; CodeStreamPut[Ascii.CR]; CodeStreamPutRope[IndentInline[(spaces+ExtraSpacesOnWrap)/SpacesPerNest]]; IF doingComment THEN { CodeStreamPutRope["-- "]; lineLength _ lineLength + 3; lastHyphen _ -1 }; END; END; -- WrapLine. ExtendToNextTabStop: PROC [length: INTEGER] RETURNS [--lengthAtStop:-- INTEGER] = INLINE {RETURN[SpacesPerTab*(length/SpacesPerTab+1)]}; SELECT char FROM Ascii.SP => IF lineLength < lineWrapThreshhold THEN { lineLength _ lineLength + 1; IF stillLeadingSpaces THEN spaces _ spaces + 1; CodeStreamPut[Ascii.SP] } ELSE WrapLine; Ascii.TAB => IF lineLength < lineWrapThreshhold THEN { lineLength _ ExtendToNextTabStop[lineLength]; IF stillLeadingSpaces THEN spaces _ ExtendToNextTabStop[spaces]; CodeStreamPut[Ascii.TAB] } ELSE WrapLine; Ascii.CR, Ascii.FF => { StartNewCodeLine[]; CodeStreamPut[char] }; Ascii.BS => WrapLine; -- Special; BS not printed. ENDCASE => { stillLeadingSpaces _ FALSE; lineLength _ lineLength + 1; IF char = '- THEN { IF lastHyphen = lineLength-1 THEN doingComment _ ~doingComment ELSE lastHyphen _ lineLength }; CodeStreamPut[char] }; END; -- CodeLinePut. WF1: PUBLIC PROC[format: Rope.ROPE, v1: IO.Value] = BEGIN formattedStream.PutF[format, v1]; END; WFS, WriteFormattedStrings: PUBLIC PROCEDURE [ s01, s02, s03: String_StringNIL ] = BEGIN IF s01 # StringNIL THEN formattedStream.PutRope[s01]; IF s02 # StringNIL THEN formattedStream.PutRope[s02]; IF s03 # StringNIL THEN formattedStream.PutRope[s03]; END; WFSL, WriteFormattedStringsLong: PUBLIC PROCEDURE [ s01, s02, s03, s04, s05, s06, s07, s08, s09, s10, s11, s12, s13, s14, s15, s16, s17, s18: String_StringNIL] = BEGIN IF s01 # StringNIL THEN formattedStream.PutRope[s01]; IF s02 # StringNIL THEN formattedStream.PutRope[s02]; IF s03 # StringNIL THEN formattedStream.PutRope[s03]; IF s04 # StringNIL THEN formattedStream.PutRope[s04]; IF s05 # StringNIL THEN formattedStream.PutRope[s05]; IF s06 # StringNIL THEN formattedStream.PutRope[s06]; IF s07 # StringNIL THEN formattedStream.PutRope[s07]; IF s08 # StringNIL THEN formattedStream.PutRope[s08]; IF s09 # StringNIL THEN formattedStream.PutRope[s09]; IF s10 # StringNIL THEN formattedStream.PutRope[s10]; IF s11 # StringNIL THEN formattedStream.PutRope[s11]; IF s12 # StringNIL THEN formattedStream.PutRope[s12]; IF s13 # StringNIL THEN formattedStream.PutRope[s13]; IF s14 # StringNIL THEN formattedStream.PutRope[s14]; IF s15 # StringNIL THEN formattedStream.PutRope[s15]; IF s16 # StringNIL THEN formattedStream.PutRope[s16]; IF s17 # StringNIL THEN formattedStream.PutRope[s17]; IF s18 # StringNIL THEN formattedStream.PutRope[s18]; END; WFL, WriteFormattedLine: PUBLIC PROCEDURE [ nest: Nest, s01, s02, s03: String_StringNIL ] = BEGIN formattedStream.PutRope[IndentInline[nest]]; WFS[s01, s02, s03]; formattedStream.PutChar[Ascii.CR]; END; WFL1, WriteFormattedLine1: PUBLIC PROCEDURE [nest: Nest, s01: String] = BEGIN formattedStream.PutRope[IndentInline[nest]]; formattedStream.PutRope[s01]; formattedStream.PutChar[Ascii.CR]; END; WFLL, WriteFormattedLineLong: PUBLIC PROCEDURE [ nest: Nest, s01, s02, s03, s04, s05, s06: String_StringNIL ] = BEGIN formattedStream.PutRope[IndentInline[nest]]; WFSL[s01, s02, s03, s04, s05, s06]; formattedStream.PutChar[Ascii.CR]; END; Indent: PUBLIC PROCEDURE [nest: Nest] RETURNS [--tabsAndSpaces:-- String] = BEGIN RETURN[ IndentInline[nest] ]; END; IndentInline: PROCEDURE [nest: Nest] RETURNS [--tabsAndSpaces:-- String] = INLINE BEGIN RETURN[ NestTable[MIN[nest,LAST[NestTableIndex]]] ]; END; NestTableIndex: TYPE = Nest[0..30]; NestTable: PACKED ARRAY NestTableIndex OF String = [ --00-- "", --01-- " ", --02-- " ", --03-- " ", --04-- " ", --05-- " ", --06-- " ", --07-- " ", --08-- " ", --09-- " ", --10-- " ", --11-- " ", --12-- " ", --13-- " ", --14-- " ", --15-- " ", --16-- " ", --17-- " ", --18-- " ", --19-- " ", --20-- " ", --21-- " ", --22-- " ", --23-- " ", --24-- " ", --25-- " ", --26-- " ", --27-- " ", --28-- " ", --29-- " ", --30-- " " ]; END. -- LupineManagerImpl. *LupineManagerImpl.mesa. Copyright c 1985 by Xerox Corporation. All rights reserved. Last edited by BZM on 12-May-82 19:22:17. Last edited by Andrew Birrell on October 25, 1983 10:37 am Last Edited by: Swinehart, February 8, 1985 9:06:22 am PST Bob Hagmann February 12, 1985 12:53:46 pm PST Top-level translator routine. Can raise ST.OpenError. DeleteExistingCodeFiles; Client-level error handling routines. Raised by ReportError and caught by TranslateRemoteInterface. Routines that construct the string names of important modules. Global OPEN 'interfaceName'. if openedInterface=NIL; named otherwise. OPEN RpcPublic: RPC (or MesaRPC). OPEN RpcPrivate: RPCLupine (or MesaRPCLupine). OPEN Lupine: LupineRuntime. Output file routines (via IO) for the Mesa code that Lupine generates. It is VERY important to call CloseCodeFile on any relevant UNWINDs. Insure that the generated mesa files do not have the same date. This is to help the version map work better. Simple formatting routines for indenting and wrapping code lines. This routine WILL wrap comments and string constants. Lupine generates no troublesome strings (i.e., strings that are too long or contain one or more hyphens). Comments should be wrapped OK. The BS character is specially interpreted to mean start a new line and indent for a continuation (as in a multiline record declaration). If the current line is indented all the way to the RIGHT margin (lineWrapThreshhold), any further attempts to indent are ignored. These constants must have SpacesPerNest spaces per nest. No module initialization. ÊD˜headšœ™Icodešœ Ïmœ1™<—Jšœ)™)Jšœ:™:™:L™-—J˜J˜šÏk ˜ Jš œžœžœžœžœžœžœ˜"Jšœ žœ1˜@Jšœžœ˜Jšœ žœ˜&Jšžœžœa˜iJšžœžœPžœ ˜gJšœžœ˜šœžœ˜J˜*J˜1—Jšœžœ˜šœžœ˜J˜ J˜'J˜J˜ J˜/Jšžœ˜—Jšœžœ˜0šœžœ˜Jšœ"žœ˜5Jšœ=˜=—Jšœžœžœ ˜-J˜J˜—šœž˜šž˜Jšœ$žœ ˜/J˜+Jšœžœ˜.Jšœ˜—Jšžœ&˜-Jšžœžœ˜ J˜Jšœ7˜7J˜—J™Jšœ™˜šÏnœžœžœž œ˜2J˜J˜6J˜J˜Jšœžœžœ˜#šžœžœž˜Jšžœžœ˜Jšœžœ˜*šžœÏc,˜=˜šœžœž˜J˜"J˜˜$J˜)—Jšžœžœ˜—J˜——Jšžœ  ˜—J˜$J˜%˜;Jšœ™—šžœžœžœ˜Jšžœ˜J˜J˜Jšœ žœ˜Jšœ2žœ˜HJ˜7šžœžœžœ˜)Jšœ™Jšžœžœ1˜Kšžœžœ˜:šžœžœ˜;Jšžœ3˜7——šžœžœ˜ Jšœ3žœ˜=Jšœ2žœ˜Jšžœ ˜&J˜—JšŸœž œžœžœ˜AJ˜Jšœžœžœžœ˜'Jšœ=™=J˜šŸ œžœž œ˜J˜9Jšž˜˜Jšž˜šœžœ˜.J˜J˜J˜"J˜-J˜3—Jšžœ žœžœžœ˜=Jšžœ  ˜—J˜/Jšžœ˜J˜—šŸœžœž œ˜#J˜/Jšž˜š œ žœžœ žœ œ ˜B˜J˜\—˜J˜4—˜J˜5—˜J˜d—˜J˜A—˜J˜S—˜ J˜_—˜ J˜_—˜J˜C—˜J˜8—˜J˜\—˜J˜G—˜J˜g—˜J˜M—˜ J˜*—˜J˜[—˜J˜S—˜J˜;—˜J˜V—˜J˜Q—˜J˜>—˜J˜$—˜J˜j——J˜Jšžœ˜J˜——J˜Jšœ>™>˜Jšœ žœ žœ žœ ˜:J˜š Ÿ œžœžœžœ  œ ˜JJšžœžœžœ˜&J˜—šŸœž œ/˜IJšž˜šœžœžœ žœ ˜5J˜ —šœžœžœ žœ ˜;J˜,—šŸœžœ)˜7Jšžœ˜Jšž˜Jšžœ˜Jšžœ  ˜—J˜1šœ3˜3JšœE™E—J˜=J˜?J˜EJ˜?˜>Jšœ!™!—šœE˜EJšœ.™.—šœ7˜7Jšœ™—Jšžœ˜J˜—šŸœž œ˜ Jšž˜šžœžœ ž˜)Jšœžœ˜Jšžœ˜—Jšžœ˜J˜——J˜JšœF™F˜Jšœžœ˜Jš œ žœžœžœžœžœžœ˜1Jš œžœžœžœžœžœ˜7Jšœ˜J˜J˜šŸ œžœž œ/žœ˜WJšž˜Jšœ&˜&šžœžœ˜šœžœ ˜J˜(J˜—J˜J˜—šœžœ˜JšœM˜Mšžœžœžœž˜&JšœKžœ˜ašœžœ ˜Jšœ˜J˜—Jšœ˜Jšžœ˜—J˜—J˜J˜Jšžœ˜J˜—šÏbœž˜&J˜Jšœ˜—J˜šÐbnœžœ˜%J˜*Jšžœ%žœ˜BJšœ˜—J˜šŸ œž œž œ˜,Jšžœž˜ šžœžœ˜šžœžœžœž˜&Jšœ˜Jšœ.˜.Jšžœ˜—J˜—šœžœ˜J˜,J˜LJ˜—Jšžœ˜J˜—šŸœž œ˜-Jšžœž˜ šžœžœ˜šžœžœžœž˜&Jšœ˜Jšœ:˜:Jšžœ˜—J˜—šœžœ˜Jšœ,˜,JšœX˜XJ˜—Jšžœ˜J˜—šŸœžœžœ žœ˜1šžœžœžœ žœ˜CJ˜——š Ÿœžœžœžœžœ˜1Jš žœžœžœžœžœžœ&˜sJ˜—šŸ œžœž œ˜9Jšž˜J˜Jšœžœžœ˜Jšœžœ˜'Jšœ žœžœ˜+Jšœžœ˜Jšœžœžœ˜˜J˜;Jšœžœ˜——Jšœr˜rJšœ˜šœ7˜7Jšœ˜Jšœ ˜ Jšœ˜—šœŒ˜ŒJšœ˜Jšœ˜Jšœ˜Jšœžœ,˜4Jšœ˜—Jšžœ˜J˜—šŸœžœž œ˜>Jšž˜Jšœžœ žœ)˜Jšœžœžœ ˜:J˜-J˜)—Jš œ žœžœžœ žœ žœ ˜EJšœžœžœ˜J˜Yšœý˜ýJ˜/J˜8J˜0J˜8Jšœ*˜*J˜—šœÒ˜ÒJšœ*˜*Jšœ&˜&Jšœ%˜%Jšœ˜J˜J˜—Jšžœ ˜!—J˜šŸ œžœž œ˜!JšœC™CJšž˜J˜šžœžœžœžœ˜'Jšœ˜Jšœžœ˜ Jšœžœ˜/šœ˜J™m—Jšœ5˜5Jšœ2˜2šžœ;žœ˜CJšœ=˜=Jšœ@˜@J˜—Jšœ˜Jšœ˜J˜Jšžœ˜—Jšœžœ˜Jšžœ˜J˜—šŸœž œ˜$Jšž˜šŸ œžœ˜"Jšž˜˜ J˜—Jšœžœ˜Jšžœ˜—J˜J˜J˜Jšžœ˜J˜—šŸ œž œ˜-Jšžœ ˜Jšžœž˜ Jšžœ˜Jšžœ˜J˜——J˜JšœA™A˜Jšœžœ˜Jšœžœ˜Jšœžœ˜-Jšœžœ˜(J˜Jšœ"žœ˜*Jšœ4žœ˜Jš œ:˜@Jš œ<˜BJš œ>˜DJš œ@˜FJš œD˜JJ˜J˜Jšœ™J˜Jšžœ ˜J˜——…—LhfÖ