|
MythTV
0.26-pre
|
00001 /* ParseText.cpp 00002 00003 Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk 00004 00005 This program is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU General Public License 00007 as published by the Free Software Foundation; either version 2 00008 of the License, or (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 Or, point your browser to http://www.gnu.org/copyleft/gpl.html 00019 00020 */ 00021 00022 /* 00023 Parser for the textual form of MHEG5. 00024 This is very basic and is only there to enable some test programs to be run. 00025 */ 00026 00027 #include "ParseText.h" 00028 #include "ParseNode.h" 00029 #include "BaseClasses.h" 00030 #include "ASN1Codes.h" 00031 #include "Root.h" 00032 #include "Groups.h" 00033 #include <ctype.h> 00034 #include "Ingredients.h" // For GetEventType 00035 #include "Text.h" // For GetJustification etc 00036 #include "Engine.h" 00037 #include "Logging.h" 00038 00039 00040 #ifndef WIN32 00041 #define stricmp strcasecmp 00042 #endif 00043 00044 00045 MHParseText::MHParseText(QByteArray &program) 00046 { 00047 m_data = program; 00048 m_lineCount = 1; 00049 m_String = (unsigned char *)malloc(100); // Initial size - may grow. 00050 m_p = 0; 00051 } 00052 00053 MHParseText::~MHParseText() 00054 { 00055 free(m_String); 00056 } 00057 00058 // Get the next character. 00059 void MHParseText::GetNextChar() 00060 { 00061 if ((int)m_p >= m_data.size()) 00062 { 00063 m_ch = EOF; 00064 } 00065 else 00066 { 00067 m_ch = m_data[m_p++]; 00068 } 00069 } 00070 00071 // Maximum length of a tag (i.e. a symbol beginning with a colon). Actually the longest is around 22 chars. 00072 #define MAX_TAG_LENGTH 30 00073 00074 const char *rchTagNames[] = 00075 { 00076 ":Application", 00077 ":Scene", 00078 ":StdID", 00079 ":StdVersion", 00080 ":ObjectInfo", 00081 ":OnStartUp", 00082 ":OnCloseDown", 00083 ":OrigGCPriority", 00084 ":Items", 00085 ":ResidentPrg", 00086 ":RemotePrg", 00087 ":InterchgPrg", 00088 ":Palette", 00089 ":Font", // Occurs twice. 00090 ":CursorShape", 00091 ":BooleanVar", 00092 ":IntegerVar", 00093 ":OStringVar", 00094 ":ObjectRefVar", 00095 ":ContentRefVar", 00096 ":Link", 00097 ":Stream", 00098 ":Bitmap", 00099 ":LineArt", 00100 ":DynamicLineArt", 00101 ":Rectangle", 00102 ":Hotspot", 00103 ":SwitchButton", 00104 ":PushButton", 00105 ":Text", 00106 ":EntryField", 00107 ":HyperText", 00108 ":Slider", 00109 ":TokenGroup", 00110 ":ListGroup", 00111 ":OnSpawnCloseDown", 00112 ":OnRestart", 00113 "", // Default attributes - encoded as a group in binary 00114 ":CharacterSet", 00115 ":BackgroundColour", 00116 ":TextCHook", 00117 ":TextColour", 00118 ":Font", 00119 ":FontAttributes", 00120 ":InterchgPrgCHook", 00121 ":StreamCHook", 00122 ":BitmapCHook", 00123 ":LineArtCHook", 00124 ":ButtonRefColour", 00125 ":HighlightRefColour", 00126 ":SliderRefColour", 00127 ":InputEventReg", 00128 ":SceneCS", 00129 ":AspectRatio", 00130 ":MovingCursor", 00131 ":NextScenes", 00132 ":InitiallyActive", 00133 ":CHook", 00134 ":OrigContent", 00135 ":Shared", 00136 ":ContentSize", 00137 ":CCPriority", 00138 "" , // Link condition - always replaced by EventSource, EventType and EventData 00139 ":LinkEffect", 00140 ":Name", 00141 ":InitiallyAvailable", 00142 ":ProgramConnectionTag", 00143 ":OrigValue", 00144 ":ObjectRef", 00145 ":ContentRef", 00146 ":MovementTable", 00147 ":TokenGroupItems", 00148 ":NoTokenActionSlots", 00149 ":Positions", 00150 ":WrapAround", 00151 ":MultipleSelection", 00152 ":OrigBoxSize", 00153 ":OrigPosition", 00154 ":OrigPaletteRef", 00155 ":Tiling", 00156 ":OrigTransparency", 00157 ":BBBox", 00158 ":OrigLineWidth", 00159 ":OrigLineStyle", 00160 ":OrigRefLineColour", 00161 ":OrigRefFillColour", 00162 ":OrigFont", 00163 ":HJustification", 00164 ":VJustification", 00165 ":LineOrientation", 00166 ":StartCorner", 00167 ":TextWrapping", 00168 ":Multiplex", 00169 ":Storage", 00170 ":Looping", 00171 ":Audio", 00172 ":Video", 00173 ":RTGraphics", 00174 ":ComponentTag", 00175 ":OrigVolume", 00176 ":Termination", 00177 ":EngineResp", 00178 ":Orientation", 00179 ":MaxValue", 00180 ":MinValue", 00181 ":InitialValue", 00182 ":InitialPortion", 00183 ":StepSize", 00184 ":SliderStyle", 00185 ":InputType", 00186 ":CharList", 00187 ":ObscuredInput", 00188 ":MaxLength", 00189 ":OrigLabel", 00190 ":ButtonStyle", 00191 ":Activate", 00192 ":Add", 00193 ":AddItem", 00194 ":Append", 00195 ":BringToFront", 00196 ":Call", 00197 ":CallActionSlot", 00198 ":Clear", 00199 ":Clone", 00200 ":CloseConnection", 00201 ":Deactivate", 00202 ":DelItem", 00203 ":Deselect", 00204 ":DeselectItem", 00205 ":Divide", 00206 ":DrawArc", 00207 ":DrawLine", 00208 ":DrawOval", 00209 ":DrawPolygon", 00210 ":DrawPolyline", 00211 ":DrawRectangle", 00212 ":DrawSector", 00213 ":Fork", 00214 ":GetAvailabilityStatus", 00215 ":GetBoxSize", 00216 ":GetCellItem", 00217 ":GetCursorPosition", 00218 ":GetEngineSupport", 00219 ":GetEntryPoint", 00220 ":GetFillColour", 00221 ":GetFirstItem", 00222 ":GetHighlightStatus", 00223 ":GetInteractionStatus", 00224 ":GetItemStatus", 00225 ":GetLabel", 00226 ":GetLastAnchorFired", 00227 ":GetLineColour", 00228 ":GetLineStyle", 00229 ":GetLineWidth", 00230 ":GetListItem", 00231 ":GetListSize", 00232 ":GetOverwriteMode", 00233 ":GetPortion", 00234 ":GetPosition", 00235 ":GetRunningStatus", 00236 ":GetSelectionStatus", 00237 ":GetSliderValue", 00238 ":GetTextContent", 00239 ":GetTextData", 00240 ":GetTokenPosition", 00241 ":GetVolume", 00242 ":Launch", 00243 ":LockScreen", 00244 ":Modulo", 00245 ":Move", 00246 ":MoveTo", 00247 ":Multiply", 00248 ":OpenConnection", 00249 ":Preload", 00250 ":PutBefore", 00251 ":PutBehind", 00252 ":Quit", 00253 ":ReadPersistent", 00254 ":Run", 00255 ":ScaleBitmap", 00256 ":ScaleVideo", 00257 ":ScrollItems", 00258 ":Select", 00259 ":SelectItem", 00260 ":SendEvent", 00261 ":SendToBack", 00262 ":SetBoxSize", 00263 ":SetCachePriority", 00264 ":SetCounterEndPosition", 00265 ":SetCounterPosition", 00266 ":SetCounterTrigger", 00267 ":SetCursorPosition", 00268 ":SetCursorShape", 00269 ":SetData", 00270 ":SetEntryPoint", 00271 ":SetFillColour", 00272 ":SetFirstItem", 00273 ":SetFontRef", 00274 ":SetHighlightStatus", 00275 ":SetInteractionStatus", 00276 ":SetLabel", 00277 ":SetLineColour", 00278 ":SetLineStyle", 00279 ":SetLineWidth", 00280 ":SetOverwriteMode", 00281 ":SetPaletteRef", 00282 ":SetPortion", 00283 ":SetPosition", 00284 ":SetSliderValue", 00285 ":SetSpeed", 00286 ":SetTimer", 00287 ":SetTransparency", 00288 ":SetVariable", 00289 ":SetVolume", 00290 ":Spawn", 00291 ":Step", 00292 ":Stop", 00293 ":StorePersistent", 00294 ":Subtract", 00295 ":TestVariable", 00296 ":Toggle", 00297 ":ToggleItem", 00298 ":TransitionTo", 00299 ":Unload", 00300 ":UnlockScreen", 00301 ":GBoolean", 00302 ":GInteger", 00303 ":GOctetString", 00304 ":GObjectRef", 00305 ":GContentRef", 00306 ":NewColourIndex", 00307 ":NewAbsoluteColour", 00308 ":NewFontName", 00309 ":NewFontRef", 00310 ":NewContentSize", 00311 ":NewCCPriority", 00312 ":IndirectRef", 00313 /* UK MHEG */ 00314 ":SetBackgroundColour", 00315 ":SetCellPosition", 00316 ":SetInputRegister", 00317 ":SetTextColour", 00318 ":SetFontAttributes", 00319 ":SetVideoDecodeOffset", 00320 ":GetVideoDecodeOffset", 00321 ":GetFocusPosition", 00322 ":SetFocusPosition", 00323 ":SetBitmapDecodeOffset", 00324 ":GetBitmapDecodeOffset", 00325 ":SetSliderParameters", 00326 /* Pseudo-operations. These are encoded as LinkCondition in binary. */ 00327 ":EventSource", 00328 ":EventType", 00329 ":EventData", 00330 ":ActionSlots" 00331 }; 00332 00333 // Some example programs use these colour names 00334 static struct 00335 { 00336 const char *name; 00337 unsigned char r, g, b, t; 00338 } colourTable[] = 00339 { 00340 { "black", 0, 0, 0, 0 }, 00341 { "transparent", 0, 0, 0, 255 }, 00342 { "gray"/*sic*/, 128, 128, 128, 0 }, 00343 { "darkgray"/*sic*/, 192, 192, 192, 0 }, 00344 { "red", 255, 0, 0, 0 }, 00345 { "darkred", 128, 0, 0, 0 }, 00346 { "blue", 0, 0, 255, 0 }, 00347 { "darkblue", 0, 0, 128, 0 }, 00348 { "green", 0, 255, 0, 0 }, 00349 { "darkgreen", 0, 128, 0, 0 }, 00350 { "yellow", 255, 255, 0, 0 }, 00351 { "cyan", 0, 255, 255, 0 }, 00352 { "magenta", 255, 0, 255, 0 } 00353 }; 00354 00355 00356 // Search for a tag and return it if it exists. Returns -1 if it isn't found. 00357 static int FindTag(const char *p) 00358 { 00359 for (int i = 0; i < (int)(sizeof(rchTagNames) / sizeof(rchTagNames[0])); i++) 00360 { 00361 if (stricmp(p, rchTagNames[i]) == 0) 00362 { 00363 return i; 00364 } 00365 } 00366 00367 return -1; 00368 } 00369 00370 00371 // Ditto for the enumerated types 00372 #define MAX_ENUM 30 00373 00374 void MHParseText::Error(const char *str) 00375 { 00376 MHERROR(QString("%1- at line %2\n").arg(str).arg(m_lineCount)); 00377 } 00378 00379 // Lexical analysis. Get the next symbol. 00380 void MHParseText::NextSym() 00381 { 00382 while (1) 00383 { 00384 00385 switch (m_ch) 00386 { 00387 case '\n': 00388 m_lineCount++; // And drop to next 00389 case ' ': 00390 case '\r': 00391 case '\t': 00392 case '\f': 00393 // Skip white space. 00394 GetNextChar(); 00395 continue; 00396 00397 case '/': 00398 { 00399 // Comment. 00400 GetNextChar(); 00401 00402 if (m_ch != '/') 00403 { 00404 Error("Malformed comment"); 00405 } 00406 00407 do 00408 { 00409 GetNextChar(); 00410 } 00411 while (m_ch != '\n' && m_ch != '\f' && m_ch != '\r'); 00412 00413 continue; // Next symbol 00414 } 00415 00416 case ':': // Start of a tag 00417 { 00418 m_nType = PTTag; 00419 char buff[MAX_TAG_LENGTH+1]; 00420 char *p = buff; 00421 00422 do 00423 { 00424 *p++ = m_ch; 00425 GetNextChar(); 00426 00427 if (p == buff + MAX_TAG_LENGTH) 00428 { 00429 break; 00430 } 00431 } 00432 while ((m_ch >= 'a' && m_ch <= 'z') || (m_ch >= 'A' && m_ch <= 'Z')); 00433 00434 *p = 0; 00435 00436 // Look it up and return it if it's found. 00437 m_nTag = FindTag(buff); 00438 00439 if (m_nTag >= 0) 00440 { 00441 return; 00442 } 00443 00444 // Unrecognised tag. 00445 Error("Unrecognised tag"); 00446 } 00447 00448 case '"': // Start of a string 00449 { 00450 m_nType = PTString; 00451 // MHEG strings can include NULLs. For the moment we pass back the length and also 00452 // null-terminate the strings. 00453 m_nStringLength = 0; 00454 00455 while (1) 00456 { 00457 GetNextChar(); 00458 00459 if (m_ch == '"') 00460 { 00461 break; // Finished the string. 00462 } 00463 00464 if (m_ch == '\\') 00465 { 00466 GetNextChar(); // Escape character. Include the next char in the string. 00467 } 00468 00469 if (m_ch == '\n' || m_ch == '\r') 00470 { 00471 Error("Unterminated string"); 00472 } 00473 00474 // We grow the buffer to the largest string in the input. 00475 unsigned char *str = (unsigned char *)realloc(m_String, m_nStringLength + 2); 00476 00477 if (str == NULL) 00478 { 00479 Error("Insufficient memory"); 00480 } 00481 00482 m_String = str; 00483 m_String[m_nStringLength++] = m_ch; 00484 } 00485 00486 GetNextChar(); // Skip the closing quote 00487 m_String[m_nStringLength] = 0; 00488 return; 00489 } 00490 00491 case '\'': // Start of a string using quoted printable 00492 { 00493 m_nType = PTString; 00494 m_nStringLength = 0; 00495 00496 // Quotable printable strings contain escape sequences beginning with the 00497 // escape character '='. The strings can span lines but each line must 00498 // end with an equal sign. 00499 while (1) 00500 { 00501 GetNextChar(); 00502 00503 if (m_ch == '\'') 00504 { 00505 break; 00506 } 00507 00508 if (m_ch == '\n') 00509 { 00510 Error("Unterminated string"); 00511 } 00512 00513 if (m_ch == '=') // Special code in quoted-printable. 00514 { 00515 // Should be followed by two hex digits or by white space and a newline. 00516 GetNextChar(); 00517 00518 if (m_ch == ' ' || m_ch == '\t' || m_ch == '\r' || m_ch == '\n') 00519 { 00520 // White space. Remove everything up to the newline. 00521 while (m_ch != '\n') 00522 { 00523 if (!(m_ch == ' ' || m_ch == '\t' || m_ch == '\r')) 00524 { 00525 Error("Malformed quoted printable string"); 00526 } 00527 00528 GetNextChar(); 00529 } 00530 00531 continue; // continue with the first character on the next line 00532 } 00533 else 00534 { 00535 int byte = 0; 00536 00537 if (m_ch >= '0' && m_ch <= '9') 00538 { 00539 byte = m_ch - '0'; 00540 } 00541 else if (m_ch >= 'A' && m_ch <= 'F') 00542 { 00543 byte = m_ch - 'A' + 10; 00544 } 00545 else if (m_ch >= 'a' && m_ch <= 'f') 00546 { 00547 byte = m_ch - 'a' + 10; 00548 } 00549 else 00550 { 00551 Error("Malformed quoted printable string"); 00552 } 00553 00554 byte *= 16; 00555 GetNextChar(); 00556 00557 if (m_ch >= '0' && m_ch <= '9') 00558 { 00559 byte += m_ch - '0'; 00560 } 00561 else if (m_ch >= 'A' && m_ch <= 'F') 00562 { 00563 byte += m_ch - 'A' + 10; 00564 } 00565 else if (m_ch >= 'a' && m_ch <= 'f') 00566 { 00567 byte += m_ch - 'a' + 10; 00568 } 00569 else 00570 { 00571 Error("Malformed quoted printable string"); 00572 } 00573 00574 m_ch = byte; // Put this into the string. 00575 } 00576 } 00577 00578 // We grow the buffer to the largest string in the input. 00579 unsigned char *str = (unsigned char *)realloc(m_String, m_nStringLength + 2); 00580 00581 if (str == NULL) 00582 { 00583 Error("Insufficient memory"); 00584 } 00585 00586 m_String = str; 00587 m_String[m_nStringLength++] = m_ch; 00588 } 00589 00590 GetNextChar(); // Skip the closing quote 00591 m_String[m_nStringLength] = 0; 00592 return; 00593 } 00594 00595 case '`': // Start of a string using base 64 00596 // These can, presumably span lines. 00597 MHERROR("Base 64 string is not implemented"); 00598 break; 00599 00600 case '#': // Start of 3-byte hex constant. 00601 MHERROR("3-byte hex constant is not implemented"); 00602 break; 00603 00604 case '-': 00605 case '0': 00606 case '1': 00607 case '2': 00608 case '3': 00609 case '4': 00610 case '5': 00611 case '6': 00612 case '7': 00613 case '8': 00614 case '9': 00615 { 00616 m_nType = PTInt; 00617 bool negative = m_ch == '-'; 00618 00619 if (negative) 00620 { 00621 GetNextChar(); 00622 00623 if (m_ch < '0' || m_ch > '9') 00624 { 00625 Error("Expected digit after '-'"); 00626 } 00627 } 00628 00629 // Start of a number. Hex can be represented as 0xn. 00630 // Strictly speaking hex values cannot be preceded by a minus sign. 00631 m_nInt = m_ch - '0'; 00632 GetNextChar(); 00633 00634 if (m_nInt == 0 && (m_ch == 'x' || m_ch == 'X')) 00635 { 00636 MHERROR("Hex constant is not implemented"); 00637 } 00638 00639 while (m_ch >= '0' && m_ch <= '9') 00640 { 00641 m_nInt = m_nInt * 10 + m_ch - '0'; 00642 // TODO: What about overflow? 00643 GetNextChar(); 00644 } 00645 00646 if (negative) 00647 { 00648 m_nInt = -m_nInt; 00649 } 00650 00651 return; 00652 } 00653 00654 case 'a': 00655 case 'b': 00656 case 'c': 00657 case 'd': 00658 case 'e': 00659 case 'f': 00660 case 'g': 00661 case 'h': 00662 case 'i': 00663 case 'j': 00664 case 'k': 00665 case 'l': 00666 case 'm': 00667 case 'n': 00668 case 'o': 00669 case 'p': 00670 case 'q': 00671 case 'r': 00672 case 's': 00673 case 't': 00674 case 'u': 00675 case 'v': 00676 case 'w': 00677 case 'x': 00678 case 'y': 00679 case 'z': 00680 case 'A': 00681 case 'B': 00682 case 'C': 00683 case 'D': 00684 case 'E': 00685 case 'F': 00686 case 'G': 00687 case 'H': 00688 case 'I': 00689 case 'J': 00690 case 'K': 00691 case 'L': 00692 case 'M': 00693 case 'N': 00694 case 'O': 00695 case 'P': 00696 case 'Q': 00697 case 'R': 00698 case 'S': 00699 case 'T': 00700 case 'U': 00701 case 'V': 00702 case 'W': 00703 case 'X': 00704 case 'Y': 00705 case 'Z': 00706 { 00707 // Start of an enumerated type. 00708 m_nType = PTEnum; 00709 char buff[MAX_ENUM+1]; 00710 char *p = buff; 00711 00712 do 00713 { 00714 *p++ = m_ch; 00715 GetNextChar(); 00716 00717 if (p == buff + MAX_ENUM) 00718 { 00719 break; 00720 } 00721 } 00722 while ((m_ch >= 'a' && m_ch <= 'z') || (m_ch >= 'A' && m_ch <= 'Z') || m_ch == '-'); 00723 00724 *p = '\0'; 00725 00726 if (stricmp(buff, "NULL") == 0) 00727 { 00728 m_nType = PTNull; 00729 return; 00730 } 00731 00732 if (stricmp(buff, "true") == 0) 00733 { 00734 m_nType = PTBool; 00735 m_fBool = true; 00736 return; 00737 } 00738 00739 if (stricmp(buff, "false") == 0) 00740 { 00741 m_nType = PTBool; 00742 m_fBool = false; 00743 return; 00744 } 00745 00746 // Look up the tag in all the tables. Fortunately all the enumerations 00747 // are distinct so we don't need to know the context. 00748 m_nInt = MHLink::GetEventType(buff); 00749 00750 if (m_nInt > 0) 00751 { 00752 return; 00753 } 00754 00755 m_nInt = MHText::GetJustification(buff); 00756 00757 if (m_nInt > 0) 00758 { 00759 return; 00760 } 00761 00762 m_nInt = MHText::GetLineOrientation(buff); 00763 00764 if (m_nInt > 0) 00765 { 00766 return; 00767 } 00768 00769 m_nInt = MHText::GetStartCorner(buff); 00770 00771 if (m_nInt > 0) 00772 { 00773 return; 00774 } 00775 00776 m_nInt = MHSlider::GetOrientation(buff); 00777 00778 if (m_nInt > 0) 00779 { 00780 return; 00781 } 00782 00783 m_nInt = MHSlider::GetStyle(buff); 00784 00785 if (m_nInt > 0) 00786 { 00787 return; 00788 } 00789 00790 // Check the colour table. If it's there generate a string containing the colour info. 00791 for (int i = 0; i < (int)(sizeof(colourTable) / sizeof(colourTable[0])); i++) 00792 { 00793 if (stricmp(buff, colourTable[i].name) == 0) 00794 { 00795 m_nType = PTString; 00796 unsigned char *str = (unsigned char *)realloc(m_String, 4 + 1); 00797 00798 if (str == NULL) 00799 { 00800 Error("Insufficient memory"); 00801 } 00802 00803 m_String[0] = colourTable[i].r; 00804 m_String[1] = colourTable[i].g; 00805 m_String[2] = colourTable[i].b; 00806 m_String[3] = colourTable[i].t; 00807 m_String = str; 00808 m_nStringLength = 4; 00809 return; 00810 } 00811 } 00812 00813 Error("Unrecognised enumeration"); 00814 break; 00815 } 00816 00817 case '{': // Start of a "section". 00818 // The standard indicates that open brace followed by a tag should be written 00819 // as a single word. We'll be more lenient and allow spaces or comments between them. 00820 m_nType = PTStartSection; 00821 GetNextChar(); 00822 return; 00823 00824 case '}': // End of a "section". 00825 m_nType = PTEndSection; 00826 GetNextChar(); 00827 return; 00828 00829 case '(': // Start of a sequence. 00830 m_nType = PTStartSeq; 00831 GetNextChar(); 00832 return; 00833 00834 case ')': // End of a sequence. 00835 m_nType = PTEndSeq; 00836 GetNextChar(); 00837 return; 00838 00839 case EOF: 00840 m_nType = PTEOF; 00841 return; 00842 00843 default: 00844 Error("Unknown character"); 00845 GetNextChar(); 00846 } 00847 } 00848 } 00849 00850 MHParseNode *MHParseText::DoParse() 00851 { 00852 MHParseNode *pRes = NULL; 00853 00854 try 00855 { 00856 switch (m_nType) 00857 { 00858 case PTStartSection: // Open curly bracket 00859 { 00860 NextSym(); 00861 00862 // Should be followed by a tag. 00863 if (m_nType != PTTag) 00864 { 00865 Error("Expected ':' after '{'"); 00866 } 00867 00868 MHPTagged *pTag = new MHPTagged(m_nTag); 00869 pRes = pTag; 00870 NextSym(); 00871 00872 while (m_nType != PTEndSection) 00873 { 00874 pTag->AddArg(DoParse()); 00875 } 00876 00877 NextSym(); // Remove the close curly bracket. 00878 break; 00879 } 00880 00881 case PTTag: // Tag on its own. 00882 { 00883 int nTag = m_nTag; 00884 MHPTagged *pTag = new MHPTagged(nTag); 00885 pRes = pTag; 00886 NextSym(); 00887 00888 switch (nTag) 00889 { 00890 case C_ITEMS: 00891 case C_LINK_EFFECT: 00892 case C_ACTIVATE: 00893 case C_ADD: 00894 case C_ADD_ITEM: 00895 case C_APPEND: 00896 case C_BRING_TO_FRONT: 00897 case C_CALL: 00898 case C_CALL_ACTION_SLOT: 00899 case C_CLEAR: 00900 case C_CLONE: 00901 case C_CLOSE_CONNECTION: 00902 case C_DEACTIVATE: 00903 case C_DEL_ITEM: 00904 case C_DESELECT: 00905 case C_DESELECT_ITEM: 00906 case C_DIVIDE: 00907 case C_DRAW_ARC: 00908 case C_DRAW_LINE: 00909 case C_DRAW_OVAL: 00910 case C_DRAW_POLYGON: 00911 case C_DRAW_POLYLINE: 00912 case C_DRAW_RECTANGLE: 00913 case C_DRAW_SECTOR: 00914 case C_FORK: 00915 case C_GET_AVAILABILITY_STATUS: 00916 case C_GET_BOX_SIZE: 00917 case C_GET_CELL_ITEM: 00918 case C_GET_CURSOR_POSITION: 00919 case C_GET_ENGINE_SUPPORT: 00920 case C_GET_ENTRY_POINT: 00921 case C_GET_FILL_COLOUR: 00922 case C_GET_FIRST_ITEM: 00923 case C_GET_HIGHLIGHT_STATUS: 00924 case C_GET_INTERACTION_STATUS: 00925 case C_GET_ITEM_STATUS: 00926 case C_GET_LABEL: 00927 case C_GET_LAST_ANCHOR_FIRED: 00928 case C_GET_LINE_COLOUR: 00929 case C_GET_LINE_STYLE: 00930 case C_GET_LINE_WIDTH: 00931 case C_GET_LIST_ITEM: 00932 case C_GET_LIST_SIZE: 00933 case C_GET_OVERWRITE_MODE: 00934 case C_GET_PORTION: 00935 case C_GET_POSITION: 00936 case C_GET_RUNNING_STATUS: 00937 case C_GET_SELECTION_STATUS: 00938 case C_GET_SLIDER_VALUE: 00939 case C_GET_TEXT_CONTENT: 00940 case C_GET_TEXT_DATA: 00941 case C_GET_TOKEN_POSITION: 00942 case C_GET_VOLUME: 00943 case C_LAUNCH: 00944 case C_LOCK_SCREEN: 00945 case C_MODULO: 00946 case C_MOVE: 00947 case C_MOVE_TO: 00948 case C_MULTIPLY: 00949 case C_OPEN_CONNECTION: 00950 case C_PRELOAD: 00951 case C_PUT_BEFORE: 00952 case C_PUT_BEHIND: 00953 case C_QUIT: 00954 case C_READ_PERSISTENT: 00955 case C_RUN: 00956 case C_SCALE_BITMAP: 00957 case C_SCALE_VIDEO: 00958 case C_SCROLL_ITEMS: 00959 case C_SELECT: 00960 case C_SELECT_ITEM: 00961 case C_SEND_EVENT: 00962 case C_SEND_TO_BACK: 00963 case C_SET_BOX_SIZE: 00964 case C_SET_CACHE_PRIORITY: 00965 case C_SET_COUNTER_END_POSITION: 00966 case C_SET_COUNTER_POSITION: 00967 case C_SET_COUNTER_TRIGGER: 00968 case C_SET_CURSOR_POSITION: 00969 case C_SET_CURSOR_SHAPE: 00970 case C_SET_DATA: 00971 case C_SET_ENTRY_POINT: 00972 case C_SET_FILL_COLOUR: 00973 case C_SET_FIRST_ITEM: 00974 case C_SET_FONT_REF: 00975 case C_SET_HIGHLIGHT_STATUS: 00976 case C_SET_INTERACTION_STATUS: 00977 case C_SET_LABEL: 00978 case C_SET_LINE_COLOUR: 00979 case C_SET_LINE_STYLE: 00980 case C_SET_LINE_WIDTH: 00981 case C_SET_OVERWRITE_MODE: 00982 case C_SET_PALETTE_REF: 00983 case C_SET_PORTION: 00984 case C_SET_POSITION: 00985 case C_SET_SLIDER_VALUE: 00986 case C_SET_SPEED: 00987 case C_SET_TIMER: 00988 case C_SET_TRANSPARENCY: 00989 case C_SET_VARIABLE: 00990 case C_SET_VOLUME: 00991 case C_SPAWN: 00992 case C_STEP: 00993 case C_STOP: 00994 case C_STORE_PERSISTENT: 00995 case C_SUBTRACT: 00996 case C_TEST_VARIABLE: 00997 case C_TOGGLE: 00998 case C_TOGGLE_ITEM: 00999 case C_TRANSITION_TO: 01000 case C_UNLOAD: 01001 case C_UNLOCK_SCREEN: 01002 case C_CONTENT_REFERENCE: 01003 case C_TOKEN_GROUP_ITEMS: 01004 case C_POSITIONS: 01005 case C_MULTIPLEX: 01006 { 01007 // These are parenthesised in the text form. We have to remove the 01008 // parentheses otherwise we will return a sequence which will not be 01009 // be compatible with the binary form. 01010 if (m_nType != PTStartSeq) 01011 { 01012 Error("Expected '('"); 01013 } 01014 01015 NextSym(); 01016 01017 while (m_nType != PTEndSeq) 01018 { 01019 pTag->AddArg(DoParse()); 01020 } 01021 01022 NextSym(); // Remove the close parenthesis. 01023 break; 01024 } 01025 case C_ORIGINAL_CONTENT: 01026 case C_NEW_GENERIC_BOOLEAN: 01027 case C_NEW_GENERIC_INTEGER: 01028 case C_NEW_GENERIC_OCTETSTRING: 01029 case C_NEW_GENERIC_OBJECT_REF: 01030 case C_NEW_GENERIC_CONTENT_REF: 01031 case C_ORIGINAL_VALUE: 01032 // These always have an argument which may be a tagged item. 01033 { 01034 // Is it always the case that there is at least one argument so if we haven't 01035 // had any arguments yet we should always process a tag as an argument? 01036 pTag->AddArg(DoParse()); 01037 break; 01038 } 01039 default: 01040 01041 // This can be followed by an int, etc but a new tag is dealt with by the caller. 01042 while (m_nType == PTBool || m_nType == PTInt || m_nType == PTString || m_nType == PTEnum || m_nType == PTStartSeq) 01043 { 01044 pTag->AddArg(DoParse()); 01045 } 01046 01047 } 01048 01049 break; 01050 } 01051 01052 case PTInt: 01053 { 01054 pRes = new MHPInt(m_nInt); 01055 NextSym(); 01056 break; 01057 } 01058 01059 case PTBool: 01060 { 01061 pRes = new MHPBool(m_fBool); 01062 NextSym(); 01063 break; 01064 } 01065 01066 case PTString: 01067 { 01068 MHOctetString str; 01069 str.Copy(MHOctetString((const char *)m_String, m_nStringLength)); 01070 pRes = new MHPString(str); 01071 NextSym(); 01072 break; 01073 } 01074 01075 case PTEnum: 01076 { 01077 pRes = new MHPEnum(m_nInt); 01078 NextSym(); 01079 break; 01080 } 01081 01082 case PTNull: 01083 { 01084 pRes = new MHPNull; 01085 NextSym(); 01086 break; 01087 } 01088 01089 case PTStartSeq: // Open parenthesis. 01090 { 01091 MHParseSequence *pSeq = new MHParseSequence; 01092 pRes = pSeq; 01093 NextSym(); 01094 01095 while (m_nType != PTEndSeq) 01096 { 01097 pSeq->Append(DoParse()); 01098 } 01099 01100 NextSym(); // Remove the close parenthesis. 01101 break; 01102 } 01103 01104 default: 01105 Error("Unexpected symbol"); 01106 } 01107 01108 return pRes; 01109 } 01110 catch (...) 01111 { 01112 delete(pRes); 01113 throw; 01114 } 01115 } 01116 01117 01118 // Run the parser 01119 MHParseNode *MHParseText::Parse() 01120 { 01121 GetNextChar(); // Initialise m_ch 01122 NextSym(); // Initialise the symbol values. 01123 return DoParse(); 01124 } 01125
1.7.6.1