1MODULE Config:Section:Arguments; 2 3IMPORT 4 Object, Msg, Channel, TextRider, LongStrings, 5 XMLBuilder := XML:Builder, XML:Locator, 6 Config:Parser, CS := Config:Section; 7 8 9TYPE 10 Section* = POINTER TO SectionDesc; 11 ArgumentArray = POINTER TO ARRAY OF STRING; 12 SectionDesc = RECORD 13 (CS.SectionDesc) 14 args: ArgumentArray; 15 argNumber: LONGINT; 16 END; 17 18 19 20CONST 21 invalidContent = 1; 22 invalidAttribute = 2; 23 requireCharDataContent = 5; 24 25TYPE 26 ErrorContext = POINTER TO ErrorContextDesc; 27 ErrorContextDesc = RECORD (* stateless *) 28 (CS.ErrorContextDesc) 29 END; 30 31VAR 32 argumentsContext: ErrorContext; 33 34 35PROCEDURE (context: ErrorContext) GetTemplate* (msg: Msg.Msg; VAR templ: Msg.LString); 36 VAR 37 t: ARRAY 128 OF Msg.LChar; 38 BEGIN 39 CASE msg. code OF 40 | invalidContent: 41 t := "Invalid content for element `${name}'" 42 | invalidAttribute: 43 t := "Attribute `${name}' is not defined for this element" 44 | requireCharDataContent: 45 t := "This element must contain character data only" 46 END; 47 context. WriteTemplate (msg, t, templ) 48 END GetTemplate; 49 50 51 52PROCEDURE Init (s: Section; id: Parser.String); 53 BEGIN 54 CS.Init (s, id); 55 s. argNumber := 0; 56 NEW (s. args, 4) 57 END Init; 58 59PROCEDURE New* (sectionName: Parser.String): Section; 60 VAR 61 s: Section; 62 BEGIN 63 NEW (s); 64 Init (s, sectionName); 65 RETURN s 66 END New; 67 68 69PROCEDURE (s: Section) ArgNumber* (): LONGINT; 70 BEGIN 71 RETURN s. argNumber 72 END ArgNumber; 73 74PROCEDURE (s: Section) Get* (position: LONGINT): STRING; 75 BEGIN 76 IF (0 <= position) & (position < s. argNumber) THEN 77 RETURN s.args[position]; 78 ELSE 79 RETURN NIL 80 END 81 END Get; 82 83 84PROCEDURE (s: Section) ProcessElements* (sectionRoot: Parser.Element; 85 errorListener: Locator.ErrorListener); 86 VAR 87 node: Parser.Node; 88 parserString: Parser.StringPtr; 89 newArgs: ArgumentArray; 90 i: LONGINT; 91 att: XMLBuilder.Attribute; 92 lastError: Msg.Msg; 93 94 PROCEDURE Err (code: Msg.Code; xmlNode: Parser.Node); 95 BEGIN 96 lastError := errorListener. Error (argumentsContext, code, FALSE, xmlNode. pos) 97 END Err; 98 99 BEGIN 100 node := sectionRoot. content; 101 WHILE (node # NIL) DO 102 WITH node: Parser.Element DO 103 IF (node. name^ = "arg") THEN 104 FOR i := 0 TO node. attrList. len-1 DO 105 att := node. attrList. attr[i]; 106 Err (invalidAttribute, node); 107 lastError. SetLStringAttrib ("name", Msg.GetLStringPtr (att. localName^)) 108 END; 109 110 IF ~node. HasNoElementContent() THEN 111 Err (requireCharDataContent, node) 112 ELSE 113 IF (s. argNumber = LEN (s. args^)) THEN 114 NEW (newArgs, LEN (s. args^)*2); 115 FOR i := 0 TO LEN (s. args^)-1 DO 116 newArgs[i] := s. args[i] 117 END; 118 s. args := newArgs 119 END; 120 parserString := node. GetCharDataContent(); 121 s.args[s.argNumber] := Object.NewUTF16(parserString^); 122 INC (s.argNumber) 123 END 124 125 ELSE 126 Err (invalidContent, node); 127 lastError. SetLStringAttrib ("name", Msg.GetLStringPtr (s. name^)) 128 END 129 130 | node: Parser.CharData DO 131 IF ~node. IsWhitespace() THEN 132 Err (invalidContent, node) 133 END 134 END; 135 node := node. nextNode 136 END 137 END ProcessElements; 138 139PROCEDURE (s: Section) DumpContent* (ch: Channel.Channel); 140 VAR 141 w: TextRider.Writer; 142 i: LONGINT; 143 str8: ARRAY 2048 OF CHAR; 144 BEGIN 145 w := TextRider.ConnectWriter (ch); 146 LongStrings.Short (s. name^, "?", str8); 147 w. WriteString ("<"); 148 w. WriteString (str8); 149 w. WriteString (">"); w. WriteLn; 150 FOR i := 0 TO s. argNumber-1 DO 151 w. WriteString (" <arg>"); 152 w. WriteObject (s. args[i]); 153 w. WriteString ("</arg>"); 154 w. WriteLn 155 END; 156 LongStrings.Short (s. name^, "?", str8); 157 w. WriteString ("</"); 158 w. WriteString (str8); 159 w. WriteString (">"); w. WriteLn 160 END DumpContent; 161 162BEGIN 163 NEW (argumentsContext); 164 Msg.InitContext (argumentsContext, "Config:Section:Arguments"); 165END Config:Section:Arguments. 166