diff options
Diffstat (limited to 'linden/indra/llmessage/llmessagetemplateparser.cpp')
-rw-r--r-- | linden/indra/llmessage/llmessagetemplateparser.cpp | 754 |
1 files changed, 754 insertions, 0 deletions
diff --git a/linden/indra/llmessage/llmessagetemplateparser.cpp b/linden/indra/llmessage/llmessagetemplateparser.cpp new file mode 100644 index 0000000..eb5e87e --- /dev/null +++ b/linden/indra/llmessage/llmessagetemplateparser.cpp | |||
@@ -0,0 +1,754 @@ | |||
1 | /** | ||
2 | * @file llmessagetemplateparser.cpp | ||
3 | * @brief LLMessageTemplateParser implementation | ||
4 | * | ||
5 | * Copyright (c) 2007-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * Second Life Viewer Source Code | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #include "llmessagetemplateparser.h" | ||
30 | #include <boost/tokenizer.hpp> | ||
31 | |||
32 | |||
33 | // What follows is a bunch of C functions to do validation. | ||
34 | |||
35 | // Lets support a small subset of regular expressions here | ||
36 | // Syntax is a string made up of: | ||
37 | // a - checks against alphanumeric ([A-Za-z0-9]) | ||
38 | // c - checks against character ([A-Za-z]) | ||
39 | // f - checks against first variable character ([A-Za-z_]) | ||
40 | // v - checks against variable ([A-Za-z0-9_]) | ||
41 | // s - checks against sign of integer ([-0-9]) | ||
42 | // d - checks against integer digit ([0-9]) | ||
43 | // * - repeat last check | ||
44 | |||
45 | // checks 'a' | ||
46 | BOOL b_return_alphanumeric_ok(char c) | ||
47 | { | ||
48 | if ( ( (c < 'A') | ||
49 | ||(c > 'Z')) | ||
50 | &&( (c < 'a') | ||
51 | ||(c > 'z')) | ||
52 | &&( (c < '0') | ||
53 | ||(c > '9'))) | ||
54 | { | ||
55 | return FALSE; | ||
56 | } | ||
57 | return TRUE; | ||
58 | } | ||
59 | |||
60 | // checks 'c' | ||
61 | BOOL b_return_character_ok(char c) | ||
62 | { | ||
63 | if ( ( (c < 'A') | ||
64 | ||(c > 'Z')) | ||
65 | &&( (c < 'a') | ||
66 | ||(c > 'z'))) | ||
67 | { | ||
68 | return FALSE; | ||
69 | } | ||
70 | return TRUE; | ||
71 | } | ||
72 | |||
73 | // checks 'f' | ||
74 | BOOL b_return_first_variable_ok(char c) | ||
75 | { | ||
76 | if ( ( (c < 'A') | ||
77 | ||(c > 'Z')) | ||
78 | &&( (c < 'a') | ||
79 | ||(c > 'z')) | ||
80 | &&(c != '_')) | ||
81 | { | ||
82 | return FALSE; | ||
83 | } | ||
84 | return TRUE; | ||
85 | } | ||
86 | |||
87 | // checks 'v' | ||
88 | BOOL b_return_variable_ok(char c) | ||
89 | { | ||
90 | if ( ( (c < 'A') | ||
91 | ||(c > 'Z')) | ||
92 | &&( (c < 'a') | ||
93 | ||(c > 'z')) | ||
94 | &&( (c < '0') | ||
95 | ||(c > '9')) | ||
96 | &&(c != '_')) | ||
97 | { | ||
98 | return FALSE; | ||
99 | } | ||
100 | return TRUE; | ||
101 | } | ||
102 | |||
103 | // checks 's' | ||
104 | BOOL b_return_signed_integer_ok(char c) | ||
105 | { | ||
106 | if ( ( (c < '0') | ||
107 | ||(c > '9')) | ||
108 | &&(c != '-')) | ||
109 | { | ||
110 | return FALSE; | ||
111 | } | ||
112 | return TRUE; | ||
113 | } | ||
114 | |||
115 | // checks 'd' | ||
116 | BOOL b_return_integer_ok(char c) | ||
117 | { | ||
118 | if ( (c < '0') | ||
119 | ||(c > '9')) | ||
120 | { | ||
121 | return FALSE; | ||
122 | } | ||
123 | return TRUE; | ||
124 | } | ||
125 | |||
126 | BOOL (*gParseCheckCharacters[])(char c) = | ||
127 | { | ||
128 | b_return_alphanumeric_ok, | ||
129 | b_return_character_ok, | ||
130 | b_return_first_variable_ok, | ||
131 | b_return_variable_ok, | ||
132 | b_return_signed_integer_ok, | ||
133 | b_return_integer_ok | ||
134 | }; | ||
135 | |||
136 | S32 get_checker_number(char checker) | ||
137 | { | ||
138 | switch(checker) | ||
139 | { | ||
140 | case 'a': | ||
141 | return 0; | ||
142 | case 'c': | ||
143 | return 1; | ||
144 | case 'f': | ||
145 | return 2; | ||
146 | case 'v': | ||
147 | return 3; | ||
148 | case 's': | ||
149 | return 4; | ||
150 | case 'd': | ||
151 | return 5; | ||
152 | case '*': | ||
153 | return 9999; | ||
154 | default: | ||
155 | return -1; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | // check token based on passed simplified regular expression | ||
160 | BOOL b_check_token(const char *token, char *regexp) | ||
161 | { | ||
162 | S32 tptr, rptr = 0; | ||
163 | S32 current_checker, next_checker = 0; | ||
164 | |||
165 | current_checker = get_checker_number(regexp[rptr++]); | ||
166 | |||
167 | if (current_checker == -1) | ||
168 | { | ||
169 | llerrs << "Invalid regular expression value!" << llendl; | ||
170 | return FALSE; | ||
171 | } | ||
172 | |||
173 | if (current_checker == 9999) | ||
174 | { | ||
175 | llerrs << "Regular expression can't start with *!" << llendl; | ||
176 | return FALSE; | ||
177 | } | ||
178 | |||
179 | for (tptr = 0; token[tptr]; tptr++) | ||
180 | { | ||
181 | if (current_checker == -1) | ||
182 | { | ||
183 | llerrs << "Input exceeds regular expression!\nDid you forget a *?" << llendl; | ||
184 | return FALSE; | ||
185 | } | ||
186 | |||
187 | if (!gParseCheckCharacters[current_checker](token[tptr])) | ||
188 | { | ||
189 | return FALSE; | ||
190 | } | ||
191 | if (next_checker != 9999) | ||
192 | { | ||
193 | next_checker = get_checker_number(regexp[rptr++]); | ||
194 | if (next_checker != 9999) | ||
195 | { | ||
196 | current_checker = next_checker; | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | return TRUE; | ||
201 | } | ||
202 | |||
203 | // C variable can be made up of upper or lower case letters, underscores, or numbers, but can't start with a number | ||
204 | BOOL b_variable_ok(const char *token) | ||
205 | { | ||
206 | if (!b_check_token(token, "fv*")) | ||
207 | { | ||
208 | llwarns << "Token '" << token << "' isn't a variable!" << llendl; | ||
209 | return FALSE; | ||
210 | } | ||
211 | return TRUE; | ||
212 | } | ||
213 | |||
214 | // An integer is made up of the digits 0-9 and may be preceded by a '-' | ||
215 | BOOL b_integer_ok(const char *token) | ||
216 | { | ||
217 | if (!b_check_token(token, "sd*")) | ||
218 | { | ||
219 | llwarns << "Token isn't an integer!" << llendl; | ||
220 | return FALSE; | ||
221 | } | ||
222 | return TRUE; | ||
223 | } | ||
224 | |||
225 | // An integer is made up of the digits 0-9 | ||
226 | BOOL b_positive_integer_ok(const char *token) | ||
227 | { | ||
228 | if (!b_check_token(token, "d*")) | ||
229 | { | ||
230 | llwarns << "Token isn't an integer!" << llendl; | ||
231 | return FALSE; | ||
232 | } | ||
233 | return TRUE; | ||
234 | } | ||
235 | |||
236 | |||
237 | // Done with C functions, here's the tokenizer. | ||
238 | |||
239 | typedef boost::tokenizer< boost::char_separator<char> > tokenizer; | ||
240 | |||
241 | LLTemplateTokenizer::LLTemplateTokenizer(const std::string & contents) : mStarted(false), mTokens() | ||
242 | { | ||
243 | boost::char_separator<char> newline("\r\n", "", boost::keep_empty_tokens); | ||
244 | boost::char_separator<char> spaces(" \t"); | ||
245 | U32 line_counter = 1; | ||
246 | |||
247 | tokenizer line_tokens(contents, newline); | ||
248 | for(tokenizer::iterator line_iter = line_tokens.begin(); | ||
249 | line_iter != line_tokens.end(); | ||
250 | ++line_iter, ++line_counter) | ||
251 | { | ||
252 | tokenizer word_tokens(*line_iter, spaces); | ||
253 | for(tokenizer::iterator word_iter = word_tokens.begin(); | ||
254 | word_iter != word_tokens.end(); | ||
255 | ++word_iter) | ||
256 | { | ||
257 | if((*word_iter)[0] == '/') | ||
258 | { | ||
259 | break; // skip to end of line on comments | ||
260 | } | ||
261 | positioned_token pt;// = new positioned_token(); | ||
262 | pt.str = std::string(*word_iter); | ||
263 | pt.line = line_counter; | ||
264 | mTokens.push_back(pt); | ||
265 | } | ||
266 | } | ||
267 | mCurrent = mTokens.begin(); | ||
268 | } | ||
269 | void LLTemplateTokenizer::inc() | ||
270 | { | ||
271 | if(atEOF()) | ||
272 | { | ||
273 | error("trying to increment token of EOF"); | ||
274 | } | ||
275 | else if(mStarted) | ||
276 | { | ||
277 | ++mCurrent; | ||
278 | } | ||
279 | else | ||
280 | { | ||
281 | mStarted = true; | ||
282 | mCurrent = mTokens.begin(); | ||
283 | } | ||
284 | } | ||
285 | void LLTemplateTokenizer::dec() | ||
286 | { | ||
287 | if(mCurrent == mTokens.begin()) | ||
288 | { | ||
289 | if(mStarted) | ||
290 | { | ||
291 | mStarted = false; | ||
292 | } | ||
293 | else | ||
294 | { | ||
295 | error("trying to decrement past beginning of file"); | ||
296 | } | ||
297 | } | ||
298 | else | ||
299 | { | ||
300 | mCurrent--; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | std::string LLTemplateTokenizer::get() const | ||
305 | { | ||
306 | if(atEOF()) | ||
307 | { | ||
308 | error("trying to get EOF"); | ||
309 | } | ||
310 | return mCurrent->str; | ||
311 | } | ||
312 | |||
313 | U32 LLTemplateTokenizer::line() const | ||
314 | { | ||
315 | if(atEOF()) | ||
316 | { | ||
317 | return 0; | ||
318 | } | ||
319 | return mCurrent->line; | ||
320 | } | ||
321 | |||
322 | bool LLTemplateTokenizer::atEOF() const | ||
323 | { | ||
324 | return mCurrent == mTokens.end(); | ||
325 | } | ||
326 | |||
327 | std::string LLTemplateTokenizer::next() | ||
328 | { | ||
329 | inc(); | ||
330 | return get(); | ||
331 | } | ||
332 | |||
333 | bool LLTemplateTokenizer::want(const std::string & token) | ||
334 | { | ||
335 | if(atEOF()) return false; | ||
336 | inc(); | ||
337 | if(atEOF()) return false; | ||
338 | if(get() != token) | ||
339 | { | ||
340 | dec(); // back up a step | ||
341 | return false; | ||
342 | } | ||
343 | return true; | ||
344 | } | ||
345 | |||
346 | bool LLTemplateTokenizer::wantEOF() | ||
347 | { | ||
348 | // see if the next token is EOF | ||
349 | if(atEOF()) return true; | ||
350 | inc(); | ||
351 | if(!atEOF()) | ||
352 | { | ||
353 | dec(); // back up a step | ||
354 | return false; | ||
355 | } | ||
356 | return true; | ||
357 | } | ||
358 | |||
359 | void LLTemplateTokenizer::error(std::string message) const | ||
360 | { | ||
361 | if(atEOF()) | ||
362 | { | ||
363 | llerrs << "Unexpected end of file: " << message << llendl; | ||
364 | } | ||
365 | else | ||
366 | { | ||
367 | llerrs << "Problem parsing message template at line " | ||
368 | << line() << ", with token '" << get() << "' : " | ||
369 | << message << llendl; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | |||
374 | // Done with tokenizer, next is the parser. | ||
375 | |||
376 | LLTemplateParser::LLTemplateParser(LLTemplateTokenizer & tokens): | ||
377 | mVersion(0.f), | ||
378 | mMessages() | ||
379 | { | ||
380 | // the version number should be the first thing in the file | ||
381 | if (tokens.want("version")) | ||
382 | { | ||
383 | // version number | ||
384 | std::string vers_string = tokens.next(); | ||
385 | mVersion = (F32)atof(vers_string.c_str()); | ||
386 | |||
387 | llinfos << "### Message template version " << mVersion << " ###" << llendl; | ||
388 | } | ||
389 | else | ||
390 | { | ||
391 | llerrs << "Version must be first in the message template, found " | ||
392 | << tokens.next() << llendl; | ||
393 | } | ||
394 | |||
395 | while(LLMessageTemplate * templatep = parseMessage(tokens)) | ||
396 | { | ||
397 | if (templatep->getDeprecation() != MD_DEPRECATED) | ||
398 | { | ||
399 | mMessages.push_back(templatep); | ||
400 | } | ||
401 | } | ||
402 | |||
403 | if(!tokens.wantEOF()) | ||
404 | { | ||
405 | llerrs << "Expected end of template or a message, instead found: " | ||
406 | << tokens.next() << " at " << tokens.line() << llendl; | ||
407 | } | ||
408 | } | ||
409 | |||
410 | F32 LLTemplateParser::getVersion() const | ||
411 | { | ||
412 | return mVersion; | ||
413 | } | ||
414 | |||
415 | LLTemplateParser::message_iterator LLTemplateParser::getMessagesBegin() const | ||
416 | { | ||
417 | return mMessages.begin(); | ||
418 | } | ||
419 | |||
420 | LLTemplateParser::message_iterator LLTemplateParser::getMessagesEnd() const | ||
421 | { | ||
422 | return mMessages.end(); | ||
423 | } | ||
424 | |||
425 | |||
426 | // static | ||
427 | LLMessageTemplate * LLTemplateParser::parseMessage(LLTemplateTokenizer & tokens) | ||
428 | { | ||
429 | LLMessageTemplate *templatep = NULL; | ||
430 | if(!tokens.want("{")) | ||
431 | { | ||
432 | return NULL; | ||
433 | } | ||
434 | |||
435 | // name first | ||
436 | std::string template_name = tokens.next(); | ||
437 | |||
438 | // is name a legit C variable name | ||
439 | if (!b_variable_ok(template_name.c_str())) | ||
440 | { | ||
441 | llerrs << "Not legit variable name: " << template_name << " at " << tokens.line() << llendl; | ||
442 | } | ||
443 | |||
444 | // ok, now get Frequency ("High", "Medium", or "Low") | ||
445 | EMsgFrequency frequency = MFT_LOW; | ||
446 | std::string freq_string = tokens.next(); | ||
447 | if (freq_string == "High") | ||
448 | { | ||
449 | frequency = MFT_HIGH; | ||
450 | } | ||
451 | else if (freq_string == "Medium") | ||
452 | { | ||
453 | frequency = MFT_MEDIUM; | ||
454 | } | ||
455 | else if (freq_string == "Low" || freq_string == "Fixed") | ||
456 | { | ||
457 | frequency = MFT_LOW; | ||
458 | } | ||
459 | else | ||
460 | { | ||
461 | llerrs << "Expected frequency, got " << freq_string << " at " << tokens.line() << llendl; | ||
462 | } | ||
463 | |||
464 | // TODO more explicit checking here pls | ||
465 | U32 message_number = strtoul(tokens.next().c_str(),NULL,0); | ||
466 | |||
467 | switch (frequency) { | ||
468 | case MFT_HIGH: | ||
469 | break; | ||
470 | case MFT_MEDIUM: | ||
471 | message_number = (255 << 8) | message_number; | ||
472 | break; | ||
473 | case MFT_LOW: | ||
474 | message_number = (255 << 24) | (255 << 16) | message_number; | ||
475 | break; | ||
476 | default: | ||
477 | llerrs << "Unknown frequency enum: " << frequency << llendl; | ||
478 | } | ||
479 | |||
480 | templatep = new LLMessageTemplate( | ||
481 | template_name.c_str(), | ||
482 | message_number, | ||
483 | frequency); | ||
484 | |||
485 | // Now get trust ("Trusted", "NotTrusted") | ||
486 | std::string trust = tokens.next(); | ||
487 | if (trust == "Trusted") | ||
488 | { | ||
489 | templatep->setTrust(MT_TRUST); | ||
490 | } | ||
491 | else if (trust == "NotTrusted") | ||
492 | { | ||
493 | templatep->setTrust(MT_NOTRUST); | ||
494 | } | ||
495 | else | ||
496 | { | ||
497 | llerrs << "Bad trust " << trust << " at " << tokens.line() << llendl; | ||
498 | } | ||
499 | |||
500 | // get encoding | ||
501 | std::string encoding = tokens.next(); | ||
502 | if(encoding == "Unencoded") | ||
503 | { | ||
504 | templatep->setEncoding(ME_UNENCODED); | ||
505 | } | ||
506 | else if(encoding == "Zerocoded") | ||
507 | { | ||
508 | templatep->setEncoding(ME_ZEROCODED); | ||
509 | } | ||
510 | else | ||
511 | { | ||
512 | llerrs << "Bad encoding " << encoding << " at " << tokens.line() << llendl; | ||
513 | } | ||
514 | |||
515 | // get deprecation | ||
516 | if(tokens.want("Deprecated")) | ||
517 | { | ||
518 | templatep->setDeprecation(MD_DEPRECATED); | ||
519 | } | ||
520 | else if (tokens.want("UDPDeprecated")) | ||
521 | { | ||
522 | templatep->setDeprecation(MD_UDPDEPRECATED); | ||
523 | } | ||
524 | else if (tokens.want("NotDeprecated")) | ||
525 | { | ||
526 | // this is the default value, but it can't hurt to set it twice | ||
527 | templatep->setDeprecation(MD_NOTDEPRECATED); | ||
528 | } | ||
529 | else { | ||
530 | // It's probably a brace, let's just start block processing | ||
531 | } | ||
532 | |||
533 | while(LLMessageBlock * blockp = parseBlock(tokens)) | ||
534 | { | ||
535 | templatep->addBlock(blockp); | ||
536 | } | ||
537 | |||
538 | if(!tokens.want("}")) | ||
539 | { | ||
540 | llerrs << "Expecting closing } for message " << template_name | ||
541 | << " at " << tokens.line() << llendl; | ||
542 | } | ||
543 | return templatep; | ||
544 | } | ||
545 | |||
546 | // static | ||
547 | LLMessageBlock * LLTemplateParser::parseBlock(LLTemplateTokenizer & tokens) | ||
548 | { | ||
549 | LLMessageBlock * blockp = NULL; | ||
550 | |||
551 | if(!tokens.want("{")) | ||
552 | { | ||
553 | return NULL; | ||
554 | } | ||
555 | |||
556 | // name first | ||
557 | std::string block_name = tokens.next(); | ||
558 | |||
559 | // is name a legit C variable name | ||
560 | if (!b_variable_ok(block_name.c_str())) | ||
561 | { | ||
562 | llerrs << "not a legal block name: " << block_name | ||
563 | << " at " << tokens.line() << llendl; | ||
564 | } | ||
565 | |||
566 | // now, block type ("Single", "Multiple", or "Variable") | ||
567 | std::string block_type = tokens.next(); | ||
568 | // which one is it? | ||
569 | if (block_type == "Single") | ||
570 | { | ||
571 | // ok, we can create a block | ||
572 | blockp = new LLMessageBlock(block_name.c_str(), MBT_SINGLE); | ||
573 | } | ||
574 | else if (block_type == "Multiple") | ||
575 | { | ||
576 | // need to get the number of repeats | ||
577 | std::string repeats = tokens.next(); | ||
578 | |||
579 | // is it a legal integer | ||
580 | if (!b_positive_integer_ok(repeats.c_str())) | ||
581 | { | ||
582 | llerrs << "not a legal integer for block multiple count: " | ||
583 | << repeats << " at " << tokens.line() << llendl; | ||
584 | } | ||
585 | |||
586 | // ok, we can create a block | ||
587 | blockp = new LLMessageBlock(block_name.c_str(), | ||
588 | MBT_MULTIPLE, | ||
589 | atoi(repeats.c_str())); | ||
590 | } | ||
591 | else if (block_type == "Variable") | ||
592 | { | ||
593 | // ok, we can create a block | ||
594 | blockp = new LLMessageBlock(block_name.c_str(), MBT_VARIABLE); | ||
595 | } | ||
596 | else | ||
597 | { | ||
598 | llerrs << "bad block type: " << block_type | ||
599 | << " at " << tokens.line() << llendl; | ||
600 | } | ||
601 | |||
602 | |||
603 | while(LLMessageVariable * varp = parseVariable(tokens)) | ||
604 | { | ||
605 | blockp->addVariable(varp->getName(), | ||
606 | varp->getType(), | ||
607 | varp->getSize()); | ||
608 | delete varp; | ||
609 | } | ||
610 | |||
611 | if(!tokens.want("}")) | ||
612 | { | ||
613 | llerrs << "Expecting closing } for block " << block_name | ||
614 | << " at " << tokens.line() << llendl; | ||
615 | } | ||
616 | return blockp; | ||
617 | |||
618 | } | ||
619 | |||
620 | // static | ||
621 | LLMessageVariable * LLTemplateParser::parseVariable(LLTemplateTokenizer & tokens) | ||
622 | { | ||
623 | LLMessageVariable * varp = NULL; | ||
624 | if(!tokens.want("{")) | ||
625 | { | ||
626 | return NULL; | ||
627 | } | ||
628 | |||
629 | std::string var_name = tokens.next(); | ||
630 | |||
631 | if (!b_variable_ok(var_name.c_str())) | ||
632 | { | ||
633 | llerrs << "Not a legit variable name: " << var_name | ||
634 | << " at " << tokens.line() << llendl; | ||
635 | } | ||
636 | |||
637 | std::string var_type = tokens.next(); | ||
638 | |||
639 | if (var_type == "U8") | ||
640 | { | ||
641 | varp = new LLMessageVariable(var_name.c_str(), MVT_U8, 1); | ||
642 | } | ||
643 | else if (var_type == "U16") | ||
644 | { | ||
645 | varp = new LLMessageVariable(var_name.c_str(), MVT_U16, 2); | ||
646 | } | ||
647 | else if (var_type == "U32") | ||
648 | { | ||
649 | varp = new LLMessageVariable(var_name.c_str(), MVT_U32, 4); | ||
650 | } | ||
651 | else if (var_type == "U64") | ||
652 | { | ||
653 | varp = new LLMessageVariable(var_name.c_str(), MVT_U64, 8); | ||
654 | } | ||
655 | else if (var_type == "S8") | ||
656 | { | ||
657 | varp = new LLMessageVariable(var_name.c_str(), MVT_S8, 1); | ||
658 | } | ||
659 | else if (var_type == "S16") | ||
660 | { | ||
661 | varp = new LLMessageVariable(var_name.c_str(), MVT_S16, 2); | ||
662 | } | ||
663 | else if (var_type == "S32") | ||
664 | { | ||
665 | varp = new LLMessageVariable(var_name.c_str(), MVT_S32, 4); | ||
666 | } | ||
667 | else if (var_type == "S64") | ||
668 | { | ||
669 | varp = new LLMessageVariable(var_name.c_str(), MVT_S64, 8); | ||
670 | } | ||
671 | else if (var_type == "F32") | ||
672 | { | ||
673 | varp = new LLMessageVariable(var_name.c_str(), MVT_F32, 4); | ||
674 | } | ||
675 | else if (var_type == "F64") | ||
676 | { | ||
677 | varp = new LLMessageVariable(var_name.c_str(), MVT_F64, 8); | ||
678 | } | ||
679 | else if (var_type == "LLVector3") | ||
680 | { | ||
681 | varp = new LLMessageVariable(var_name.c_str(), MVT_LLVector3, 12); | ||
682 | } | ||
683 | else if (var_type == "LLVector3d") | ||
684 | { | ||
685 | varp = new LLMessageVariable(var_name.c_str(), MVT_LLVector3d, 24); | ||
686 | } | ||
687 | else if (var_type == "LLVector4") | ||
688 | { | ||
689 | varp = new LLMessageVariable(var_name.c_str(), MVT_LLVector4, 16); | ||
690 | } | ||
691 | else if (var_type == "LLQuaternion") | ||
692 | { | ||
693 | varp = new LLMessageVariable(var_name.c_str(), MVT_LLQuaternion, 12); | ||
694 | } | ||
695 | else if (var_type == "LLUUID") | ||
696 | { | ||
697 | varp = new LLMessageVariable(var_name.c_str(), MVT_LLUUID, 16); | ||
698 | } | ||
699 | else if (var_type == "BOOL") | ||
700 | { | ||
701 | varp = new LLMessageVariable(var_name.c_str(), MVT_BOOL, 1); | ||
702 | } | ||
703 | else if (var_type == "IPADDR") | ||
704 | { | ||
705 | varp = new LLMessageVariable(var_name.c_str(), MVT_IP_ADDR, 4); | ||
706 | } | ||
707 | else if (var_type == "IPPORT") | ||
708 | { | ||
709 | varp = new LLMessageVariable(var_name.c_str(), MVT_IP_PORT, 2); | ||
710 | } | ||
711 | else if (var_type == "Fixed" || var_type == "Variable") | ||
712 | { | ||
713 | std::string variable_size = tokens.next(); | ||
714 | |||
715 | if (!b_positive_integer_ok(variable_size.c_str())) | ||
716 | { | ||
717 | llerrs << "not a legal integer variable size: " << variable_size | ||
718 | << " at " << tokens.line() << llendl; | ||
719 | } | ||
720 | |||
721 | EMsgVariableType type_enum; | ||
722 | if(var_type == "Variable") | ||
723 | { | ||
724 | type_enum = MVT_VARIABLE; | ||
725 | } | ||
726 | else if(var_type == "Fixed") | ||
727 | { | ||
728 | type_enum = MVT_FIXED; | ||
729 | } | ||
730 | else | ||
731 | { | ||
732 | type_enum = MVT_FIXED; // removes a warning | ||
733 | llerrs << "bad variable type: " << var_type | ||
734 | << " at " << tokens.line() << llendl; | ||
735 | } | ||
736 | |||
737 | varp = new LLMessageVariable( | ||
738 | var_name.c_str(), | ||
739 | type_enum, | ||
740 | atoi(variable_size.c_str())); | ||
741 | } | ||
742 | else | ||
743 | { | ||
744 | llerrs << "bad variable type:" << var_type | ||
745 | << " at " << tokens.line() << llendl; | ||
746 | } | ||
747 | |||
748 | if(!tokens.want("}")) | ||
749 | { | ||
750 | llerrs << "Expecting closing } for variable " << var_name | ||
751 | << " at " << tokens.line() << llendl; | ||
752 | } | ||
753 | return varp; | ||
754 | } | ||