MythTV master
ParseText.cpp
Go to the documentation of this file.
1/* ParseText.cpp
2
3 Copyright (C) David C. J. Matthews 2004, 2008 dm at prolingua.co.uk
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 Or, point your browser to http://www.gnu.org/copyleft/gpl.html
19
20*/
21
22/*
23Parser for the textual form of MHEG5.
24This is very basic and is only there to enable some test programs to be run.
25*/
26
27#include "ParseText.h"
28
29#include <cstdlib> // malloc etc.
30
31#include "ParseNode.h"
32#include "BaseClasses.h"
33#include "ASN1Codes.h"
34#include "Root.h"
35#include "Groups.h"
36#include <cctype>
37#include "Ingredients.h" // For GetEventType
38#include "Text.h" // For GetJustification etc
39#include "Engine.h"
40#include "Logging.h"
41
42
43#ifndef WIN32
44#define stricmp strcasecmp
45#endif
46
47
49{
50 free(m_string);
51}
52
53// Get the next character.
55{
56 if ((int)m_p >= m_data.size())
57 {
58 m_ch = EOF;
59 }
60 else
61 {
62 // NOLINTNEXTLINE(bugprone-signed-char-misuse)
63 m_ch = m_data[m_p++];
64 }
65}
66
67// Maximum length of a tag (i.e. a symbol beginning with a colon). Actually the longest is around 22 chars.
68#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
69static constexpr int MAX_TAG_LENGTH { 30 };
70#else
71static constexpr size_t MAX_TAG_LENGTH { 30 };
72#endif
73
74const std::array<const QString,253> rchTagNames
75{
76 ":Application",
77 ":Scene",
78 ":StdID",
79 ":StdVersion",
80 ":ObjectInfo",
81 ":OnStartUp",
82 ":OnCloseDown",
83 ":OrigGCPriority",
84 ":Items",
85 ":ResidentPrg",
86 ":RemotePrg",
87 ":InterchgPrg",
88 ":Palette",
89 ":Font", // Occurs twice.
90 ":CursorShape",
91 ":BooleanVar",
92 ":IntegerVar",
93 ":OStringVar",
94 ":ObjectRefVar",
95 ":ContentRefVar",
96 ":Link",
97 ":Stream",
98 ":Bitmap",
99 ":LineArt",
100 ":DynamicLineArt",
101 ":Rectangle",
102 ":Hotspot",
103 ":SwitchButton",
104 ":PushButton",
105 ":Text",
106 ":EntryField",
107 ":HyperText",
108 ":Slider",
109 ":TokenGroup",
110 ":ListGroup",
111 ":OnSpawnCloseDown",
112 ":OnRestart",
113 "", // Default attributes - encoded as a group in binary
114 ":CharacterSet",
115 ":BackgroundColour",
116 ":TextCHook",
117 ":TextColour",
118 ":Font",
119 ":FontAttributes",
120 ":InterchgPrgCHook",
121 ":StreamCHook",
122 ":BitmapCHook",
123 ":LineArtCHook",
124 ":ButtonRefColour",
125 ":HighlightRefColour",
126 ":SliderRefColour",
127 ":InputEventReg",
128 ":SceneCS",
129 ":AspectRatio",
130 ":MovingCursor",
131 ":NextScenes",
132 ":InitiallyActive",
133 ":CHook",
134 ":OrigContent",
135 ":Shared",
136 ":ContentSize",
137 ":CCPriority",
138 "" , // Link condition - always replaced by EventSource, EventType and EventData
139 ":LinkEffect",
140 ":Name",
141 ":InitiallyAvailable",
142 ":ProgramConnectionTag",
143 ":OrigValue",
144 ":ObjectRef",
145 ":ContentRef",
146 ":MovementTable",
147 ":TokenGroupItems",
148 ":NoTokenActionSlots",
149 ":Positions",
150 ":WrapAround",
151 ":MultipleSelection",
152 ":OrigBoxSize",
153 ":OrigPosition",
154 ":OrigPaletteRef",
155 ":Tiling",
156 ":OrigTransparency",
157 ":BBBox",
158 ":OrigLineWidth",
159 ":OrigLineStyle",
160 ":OrigRefLineColour",
161 ":OrigRefFillColour",
162 ":OrigFont",
163 ":HJustification",
164 ":VJustification",
165 ":LineOrientation",
166 ":StartCorner",
167 ":TextWrapping",
168 ":Multiplex",
169 ":Storage",
170 ":Looping",
171 ":Audio",
172 ":Video",
173 ":RTGraphics",
174 ":ComponentTag",
175 ":OrigVolume",
176 ":Termination",
177 ":EngineResp",
178 ":Orientation",
179 ":MaxValue",
180 ":MinValue",
181 ":InitialValue",
182 ":InitialPortion",
183 ":StepSize",
184 ":SliderStyle",
185 ":InputType",
186 ":CharList",
187 ":ObscuredInput",
188 ":MaxLength",
189 ":OrigLabel",
190 ":ButtonStyle",
191 ":Activate",
192 ":Add",
193 ":AddItem",
194 ":Append",
195 ":BringToFront",
196 ":Call",
197 ":CallActionSlot",
198 ":Clear",
199 ":Clone",
200 ":CloseConnection",
201 ":Deactivate",
202 ":DelItem",
203 ":Deselect",
204 ":DeselectItem",
205 ":Divide",
206 ":DrawArc",
207 ":DrawLine",
208 ":DrawOval",
209 ":DrawPolygon",
210 ":DrawPolyline",
211 ":DrawRectangle",
212 ":DrawSector",
213 ":Fork",
214 ":GetAvailabilityStatus",
215 ":GetBoxSize",
216 ":GetCellItem",
217 ":GetCursorPosition",
218 ":GetEngineSupport",
219 ":GetEntryPoint",
220 ":GetFillColour",
221 ":GetFirstItem",
222 ":GetHighlightStatus",
223 ":GetInteractionStatus",
224 ":GetItemStatus",
225 ":GetLabel",
226 ":GetLastAnchorFired",
227 ":GetLineColour",
228 ":GetLineStyle",
229 ":GetLineWidth",
230 ":GetListItem",
231 ":GetListSize",
232 ":GetOverwriteMode",
233 ":GetPortion",
234 ":GetPosition",
235 ":GetRunningStatus",
236 ":GetSelectionStatus",
237 ":GetSliderValue",
238 ":GetTextContent",
239 ":GetTextData",
240 ":GetTokenPosition",
241 ":GetVolume",
242 ":Launch",
243 ":LockScreen",
244 ":Modulo",
245 ":Move",
246 ":MoveTo",
247 ":Multiply",
248 ":OpenConnection",
249 ":Preload",
250 ":PutBefore",
251 ":PutBehind",
252 ":Quit",
253 ":ReadPersistent",
254 ":Run",
255 ":ScaleBitmap",
256 ":ScaleVideo",
257 ":ScrollItems",
258 ":Select",
259 ":SelectItem",
260 ":SendEvent",
261 ":SendToBack",
262 ":SetBoxSize",
263 ":SetCachePriority",
264 ":SetCounterEndPosition",
265 ":SetCounterPosition",
266 ":SetCounterTrigger",
267 ":SetCursorPosition",
268 ":SetCursorShape",
269 ":SetData",
270 ":SetEntryPoint",
271 ":SetFillColour",
272 ":SetFirstItem",
273 ":SetFontRef",
274 ":SetHighlightStatus",
275 ":SetInteractionStatus",
276 ":SetLabel",
277 ":SetLineColour",
278 ":SetLineStyle",
279 ":SetLineWidth",
280 ":SetOverwriteMode",
281 ":SetPaletteRef",
282 ":SetPortion",
283 ":SetPosition",
284 ":SetSliderValue",
285 ":SetSpeed",
286 ":SetTimer",
287 ":SetTransparency",
288 ":SetVariable",
289 ":SetVolume",
290 ":Spawn",
291 ":Step",
292 ":Stop",
293 ":StorePersistent",
294 ":Subtract",
295 ":TestVariable",
296 ":Toggle",
297 ":ToggleItem",
298 ":TransitionTo",
299 ":Unload",
300 ":UnlockScreen",
301 ":GBoolean",
302 ":GInteger",
303 ":GOctetString",
304 ":GObjectRef",
305 ":GContentRef",
306 ":NewColourIndex",
307 ":NewAbsoluteColour",
308 ":NewFontName",
309 ":NewFontRef",
310 ":NewContentSize",
311 ":NewCCPriority",
312 ":IndirectRef",
313 /* UK MHEG */
314 ":SetBackgroundColour",
315 ":SetCellPosition",
316 ":SetInputRegister",
317 ":SetTextColour",
318 ":SetFontAttributes",
319 ":SetVideoDecodeOffset",
320 ":GetVideoDecodeOffset",
321 ":GetFocusPosition",
322 ":SetFocusPosition",
323 ":SetBitmapDecodeOffset",
324 ":GetBitmapDecodeOffset",
325 ":SetSliderParameters",
326 /* Pseudo-operations. These are encoded as LinkCondition in binary. */
327 ":EventSource",
328 ":EventType",
329 ":EventData",
330 ":ActionSlots"
331};
332
333// Some example programs use these colour names
335{
336 const char *m_name;
337 unsigned char m_r, m_g, m_b, m_t;
338};
339static std::array<const struct colourTable,13> colourTable
340{{
341 { "black", 0, 0, 0, 0 },
342 { "transparent", 0, 0, 0, 255 },
343 { "gray"/*sic*/, 128, 128, 128, 0 },
344 { "darkgray"/*sic*/, 192, 192, 192, 0 },
345 { "red", 255, 0, 0, 0 },
346 { "darkred", 128, 0, 0, 0 },
347 { "blue", 0, 0, 255, 0 },
348 { "darkblue", 0, 0, 128, 0 },
349 { "green", 0, 255, 0, 0 },
350 { "darkgreen", 0, 128, 0, 0 },
351 { "yellow", 255, 255, 0, 0 },
352 { "cyan", 0, 255, 255, 0 },
353 { "magenta", 255, 0, 255, 0 }
354}};
355
356
357// Search for a tag and return it if it exists. Returns -1 if it isn't found.
358static int FindTag(const QString& str)
359{
360 for (size_t i = 0; i < rchTagNames.size(); i++)
361 {
362 if (str.compare(rchTagNames[i], Qt::CaseInsensitive) == 0)
363 {
364 return i;
365 }
366 }
367
368 return -1;
369}
370
371
372// Ditto for the enumerated types
373#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
374static constexpr int MAX_ENUM { 30 };
375#else
376static constexpr size_t MAX_ENUM { 30 };
377#endif
378
379void MHParseText::Error(const char *str) const
380{
381 MHERROR(QString("%1- at line %2\n").arg(str).arg(m_lineCount));
382}
383
384// Lexical analysis. Get the next symbol.
386{
387 while (true)
388 {
389
390 switch (m_ch)
391 {
392 case '\n':
393 m_lineCount++;
394 [[fallthrough]];
395 case ' ':
396 case '\r':
397 case '\t':
398 case '\f':
399 // Skip white space.
400 GetNextChar();
401 continue;
402
403 case '/':
404 {
405 // Comment.
406 GetNextChar();
407
408 if (m_ch != '/')
409 {
410 Error("Malformed comment");
411 }
412
413 while (m_ch != '\n' && m_ch != '\f' && m_ch != '\r')
414 {
415 GetNextChar();
416 }
417
418 continue; // Next symbol
419 }
420
421 case ':': // Start of a tag
422 {
423 m_nType = PTTag;
424 QString buff {};
425 buff.reserve(MAX_TAG_LENGTH);
426
427 buff += m_ch;
428 GetNextChar();
429 while (isalpha(m_ch) && (buff.size() < MAX_TAG_LENGTH))
430 {
431 buff += m_ch;
432 GetNextChar();
433 }
434
435 // Look it up and return it if it's found.
436 m_nTag = FindTag(buff);
437
438 if (m_nTag >= 0)
439 {
440 return;
441 }
442
443 // Unrecognised tag.
444 Error("Unrecognised tag");
445 break;
446 }
447
448 case '"': // Start of a string
449 {
451 // MHEG strings can include NULs. For the moment we pass back the length and also
452 // null-terminate the strings.
453 m_nStringLength = 0;
454
455 while (true)
456 {
457 GetNextChar();
458
459 if (m_ch == '"')
460 {
461 break; // Finished the string.
462 }
463
464 if (m_ch == '\\')
465 {
466 GetNextChar(); // Escape character. Include the next char in the string.
467 }
468
469 if (m_ch == '\n' || m_ch == '\r')
470 {
471 Error("Unterminated string");
472 }
473
474 // We grow the buffer to the largest string in the input.
475 auto *str = (unsigned char *)realloc(m_string, m_nStringLength + 2);
476
477 if (str == nullptr)
478 {
479 Error("Insufficient memory");
480 }
481
482 m_string = str;
484 }
485
486 GetNextChar(); // Skip the closing quote
488 return;
489 }
490
491 case '\'': // Start of a string using quoted printable
492 {
494 m_nStringLength = 0;
495
496 // Quotable printable strings contain escape sequences beginning with the
497 // escape character '='. The strings can span lines but each line must
498 // end with an equal sign.
499 while (true)
500 {
501 GetNextChar();
502
503 if (m_ch == '\'')
504 {
505 break;
506 }
507
508 if (m_ch == '\n')
509 {
510 Error("Unterminated string");
511 }
512
513 if (m_ch == '=') // Special code in quoted-printable.
514 {
515 // Should be followed by two hex digits or by white space and a newline.
516 GetNextChar();
517
518 if (m_ch == ' ' || m_ch == '\t' || m_ch == '\r' || m_ch == '\n')
519 {
520 // White space. Remove everything up to the newline.
521 while (m_ch != '\n')
522 {
523 if (m_ch != ' ' && m_ch != '\t' && m_ch != '\r')
524 {
525 Error("Malformed quoted printable string");
526 }
527
528 GetNextChar();
529 }
530
531 continue; // continue with the first character on the next line
532 }
533
534 int byte = 0;
535
536 if (m_ch >= '0' && m_ch <= '9')
537 {
538 byte = m_ch - '0';
539 }
540 else if (m_ch >= 'A' && m_ch <= 'F')
541 {
542 byte = m_ch - 'A' + 10;
543 }
544 else if (m_ch >= 'a' && m_ch <= 'f')
545 {
546 byte = m_ch - 'a' + 10;
547 }
548 else
549 {
550 Error("Malformed quoted printable string");
551 }
552
553 byte *= 16;
554 GetNextChar();
555
556 if (m_ch >= '0' && m_ch <= '9')
557 {
558 byte += m_ch - '0';
559 }
560 else if (m_ch >= 'A' && m_ch <= 'F')
561 {
562 byte += m_ch - 'A' + 10;
563 }
564 else if (m_ch >= 'a' && m_ch <= 'f')
565 {
566 byte += m_ch - 'a' + 10;
567 }
568 else
569 {
570 Error("Malformed quoted printable string");
571 }
572
573 m_ch = byte; // Put this into the string.
574 }
575
576 // We grow the buffer to the largest string in the input.
577 auto *str = (unsigned char *)realloc(m_string, m_nStringLength + 2);
578
579 if (str == nullptr)
580 {
581 Error("Insufficient memory");
582 }
583
584 m_string = str;
586 }
587
588 GetNextChar(); // Skip the closing quote
590 return;
591 }
592
593 case '`': // Start of a string using base 64
594 // These can, presumably span lines.
595 MHERROR("Base 64 string is not implemented");
596 break;
597
598 case '#': // Start of 3-byte hex constant.
599 MHERROR("3-byte hex constant is not implemented");
600 break;
601
602 case '-':
603 case '0':
604 case '1':
605 case '2':
606 case '3':
607 case '4':
608 case '5':
609 case '6':
610 case '7':
611 case '8':
612 case '9':
613 {
614 m_nType = PTInt;
615 bool negative = m_ch == '-';
616
617 if (negative)
618 {
619 GetNextChar();
620
621 if (m_ch < '0' || m_ch > '9')
622 {
623 Error("Expected digit after '-'");
624 }
625 }
626
627 // Start of a number. Hex can be represented as 0xn.
628 // Strictly speaking hex values cannot be preceded by a minus sign.
629 m_nInt = m_ch - '0';
630 GetNextChar();
631
632 if (m_nInt == 0 && (m_ch == 'x' || m_ch == 'X'))
633 {
634 MHERROR("Hex constant is not implemented");
635 }
636
637 while (m_ch >= '0' && m_ch <= '9')
638 {
639 m_nInt = (m_nInt * 10) + m_ch - '0';
640 // TODO: What about overflow?
641 GetNextChar();
642 }
643
644 if (negative)
645 {
646 m_nInt = -m_nInt;
647 }
648
649 return;
650 }
651
652 case 'a':
653 case 'b':
654 case 'c':
655 case 'd':
656 case 'e':
657 case 'f':
658 case 'g':
659 case 'h':
660 case 'i':
661 case 'j':
662 case 'k':
663 case 'l':
664 case 'm':
665 case 'n':
666 case 'o':
667 case 'p':
668 case 'q':
669 case 'r':
670 case 's':
671 case 't':
672 case 'u':
673 case 'v':
674 case 'w':
675 case 'x':
676 case 'y':
677 case 'z':
678 case 'A':
679 case 'B':
680 case 'C':
681 case 'D':
682 case 'E':
683 case 'F':
684 case 'G':
685 case 'H':
686 case 'I':
687 case 'J':
688 case 'K':
689 case 'L':
690 case 'M':
691 case 'N':
692 case 'O':
693 case 'P':
694 case 'Q':
695 case 'R':
696 case 'S':
697 case 'T':
698 case 'U':
699 case 'V':
700 case 'W':
701 case 'X':
702 case 'Y':
703 case 'Z':
704 {
705 // Start of an enumerated type.
706 m_nType = PTEnum;
707 QString buff;
708 buff.reserve(MAX_ENUM);
709
710 buff += m_ch;
711 GetNextChar();
712 while ((isalpha(m_ch) || m_ch == '-')
713 && (buff.size() < MAX_ENUM))
714 {
715 buff += m_ch;
716 GetNextChar();
717 }
718
719 if (buff.compare("NULL", Qt::CaseInsensitive) == 0)
720 {
721 m_nType = PTNull;
722 return;
723 }
724
725 if (buff.compare("true", Qt::CaseInsensitive) == 0)
726 {
727 m_nType = PTBool;
728 m_fBool = true;
729 return;
730 }
731
732 if (buff.compare("false", Qt::CaseInsensitive) == 0)
733 {
734 m_nType = PTBool;
735 m_fBool = false;
736 return;
737 }
738
739 // Look up the tag in all the tables. Fortunately all the enumerations
740 // are distinct so we don't need to know the context.
742
743 if (m_nInt > 0)
744 {
745 return;
746 }
747
749
750 if (m_nInt > 0)
751 {
752 return;
753 }
754
756
757 if (m_nInt > 0)
758 {
759 return;
760 }
761
763
764 if (m_nInt > 0)
765 {
766 return;
767 }
768
770
771 if (m_nInt > 0)
772 {
773 return;
774 }
775
777
778 if (m_nInt > 0)
779 {
780 return;
781 }
782
783 // Check the colour table. If it's there generate a string containing the colour info.
784 for (const auto & colour : colourTable)
785 {
786 if (buff.compare(colour.m_name, Qt::CaseInsensitive) == 0)
787 {
789 auto *str = (unsigned char *)realloc(m_string, 4 + 1);
790
791 if (str == nullptr)
792 {
793 Error("Insufficient memory");
794 }
795
796 m_string = str;
797 m_string[0] = colour.m_r;
798 m_string[1] = colour.m_g;
799 m_string[2] = colour.m_b;
800 m_string[3] = colour.m_t;
801 m_nStringLength = 4;
803 return;
804 }
805 }
806
807 Error("Unrecognised enumeration");
808 break;
809 }
810
811 case '{': // Start of a "section".
812 // The standard indicates that open brace followed by a tag should be written
813 // as a single word. We'll be more lenient and allow spaces or comments between them.
815 GetNextChar();
816 return;
817
818 case '}': // End of a "section".
820 GetNextChar();
821 return;
822
823 case '(': // Start of a sequence.
825 GetNextChar();
826 return;
827
828 case ')': // End of a sequence.
830 GetNextChar();
831 return;
832
833 case EOF:
834 m_nType = PTEOF;
835 return;
836
837 default:
838 Error("Unknown character");
839 GetNextChar();
840 }
841 }
842}
843
845{
846 MHParseNode *pRes = nullptr;
847
848 try
849 {
850 switch (m_nType)
851 {
852 case PTStartSection: // Open curly bracket
853 {
854 NextSym();
855
856 // Should be followed by a tag.
857 if (m_nType != PTTag)
858 {
859 Error("Expected ':' after '{'");
860 }
861
862 auto *pTag = new MHPTagged(m_nTag);
863 pRes = pTag;
864 NextSym();
865
866 while (m_nType != PTEndSection)
867 {
868 pTag->AddArg(DoParse());
869 }
870
871 NextSym(); // Remove the close curly bracket.
872 break;
873 }
874
875 case PTTag: // Tag on its own.
876 {
877 int nTag = m_nTag;
878 auto *pTag = new MHPTagged(nTag);
879 pRes = pTag;
880 NextSym();
881
882 switch (nTag)
883 {
884 case C_ITEMS:
885 case C_LINK_EFFECT:
886 case C_ACTIVATE:
887 case C_ADD:
888 case C_ADD_ITEM:
889 case C_APPEND:
890 case C_BRING_TO_FRONT:
891 case C_CALL:
893 case C_CLEAR:
894 case C_CLONE:
896 case C_DEACTIVATE:
897 case C_DEL_ITEM:
898 case C_DESELECT:
899 case C_DESELECT_ITEM:
900 case C_DIVIDE:
901 case C_DRAW_ARC:
902 case C_DRAW_LINE:
903 case C_DRAW_OVAL:
904 case C_DRAW_POLYGON:
905 case C_DRAW_POLYLINE:
906 case C_DRAW_RECTANGLE:
907 case C_DRAW_SECTOR:
908 case C_FORK:
910 case C_GET_BOX_SIZE:
911 case C_GET_CELL_ITEM:
916 case C_GET_FIRST_ITEM:
920 case C_GET_LABEL:
923 case C_GET_LINE_STYLE:
924 case C_GET_LINE_WIDTH:
925 case C_GET_LIST_ITEM:
926 case C_GET_LIST_SIZE:
928 case C_GET_PORTION:
929 case C_GET_POSITION:
934 case C_GET_TEXT_DATA:
936 case C_GET_VOLUME:
937 case C_LAUNCH:
938 case C_LOCK_SCREEN:
939 case C_MODULO:
940 case C_MOVE:
941 case C_MOVE_TO:
942 case C_MULTIPLY:
944 case C_PRELOAD:
945 case C_PUT_BEFORE:
946 case C_PUT_BEHIND:
947 case C_QUIT:
949 case C_RUN:
950 case C_SCALE_BITMAP:
951 case C_SCALE_VIDEO:
952 case C_SCROLL_ITEMS:
953 case C_SELECT:
954 case C_SELECT_ITEM:
955 case C_SEND_EVENT:
956 case C_SEND_TO_BACK:
957 case C_SET_BOX_SIZE:
964 case C_SET_DATA:
967 case C_SET_FIRST_ITEM:
968 case C_SET_FONT_REF:
971 case C_SET_LABEL:
973 case C_SET_LINE_STYLE:
974 case C_SET_LINE_WIDTH:
977 case C_SET_PORTION:
978 case C_SET_POSITION:
980 case C_SET_SPEED:
981 case C_SET_TIMER:
983 case C_SET_VARIABLE:
984 case C_SET_VOLUME:
985 case C_SPAWN:
986 case C_STEP:
987 case C_STOP:
989 case C_SUBTRACT:
990 case C_TEST_VARIABLE:
991 case C_TOGGLE:
992 case C_TOGGLE_ITEM:
993 case C_TRANSITION_TO:
994 case C_UNLOAD:
995 case C_UNLOCK_SCREEN:
998 case C_POSITIONS:
999 case C_MULTIPLEX:
1000 {
1001 // These are parenthesised in the text form. We have to remove the
1002 // parentheses otherwise we will return a sequence which will not be
1003 // be compatible with the binary form.
1004 if (m_nType != PTStartSeq)
1005 {
1006 Error("Expected '('");
1007 }
1008
1009 NextSym();
1010
1011 while (m_nType != PTEndSeq)
1012 {
1013 pTag->AddArg(DoParse());
1014 }
1015
1016 NextSym(); // Remove the close parenthesis.
1017 break;
1018 }
1019 case C_ORIGINAL_CONTENT:
1025 case C_ORIGINAL_VALUE:
1026 // These always have an argument which may be a tagged item.
1027 {
1028 // Is it always the case that there is at least one argument so if we haven't
1029 // had any arguments yet we should always process a tag as an argument?
1030 pTag->AddArg(DoParse());
1031 break;
1032 }
1033 default:
1034
1035 // This can be followed by an int, etc but a new tag is dealt with by the caller.
1036 while (m_nType == PTBool || m_nType == PTInt || m_nType == PTString || m_nType == PTEnum || m_nType == PTStartSeq)
1037 {
1038 pTag->AddArg(DoParse());
1039 }
1040
1041 }
1042
1043 break;
1044 }
1045
1046 case PTInt:
1047 {
1048 pRes = new MHPInt(m_nInt);
1049 NextSym();
1050 break;
1051 }
1052
1053 case PTBool:
1054 {
1055 pRes = new MHPBool(m_fBool);
1056 NextSym();
1057 break;
1058 }
1059
1060 case PTString:
1061 {
1062 MHOctetString str;
1063 str.Copy(MHOctetString((const char *)m_string, m_nStringLength));
1064 pRes = new MHPString(str);
1065 NextSym();
1066 break;
1067 }
1068
1069 case PTEnum:
1070 {
1071 pRes = new MHPEnum(m_nInt);
1072 NextSym();
1073 break;
1074 }
1075
1076 case PTNull:
1077 {
1078 pRes = new MHPNull;
1079 NextSym();
1080 break;
1081 }
1082
1083 case PTStartSeq: // Open parenthesis.
1084 {
1085 auto *pSeq = new MHParseSequence;
1086 pRes = pSeq;
1087 NextSym();
1088
1089 while (m_nType != PTEndSeq)
1090 {
1091 pSeq->Append(DoParse());
1092 }
1093
1094 NextSym(); // Remove the close parenthesis.
1095 break;
1096 }
1097
1098 default:
1099 Error("Unexpected symbol");
1100 }
1101
1102 return pRes;
1103 }
1104 catch (...)
1105 {
1106 delete(pRes);
1107 throw;
1108 }
1109}
1110
1111
1112// Run the parser
1114{
1115 GetNextChar(); // Initialise m_ch
1116 NextSym(); // Initialise the symbol values.
1117 return DoParse();
1118}
1119
@ C_CLOSE_CONNECTION
Definition: ASN1Codes.h:160
@ C_SET_POSITION
Definition: ASN1Codes.h:243
@ C_GET_BOX_SIZE
Definition: ASN1Codes.h:175
@ C_SET_SLIDER_VALUE
Definition: ASN1Codes.h:244
@ C_SET_LINE_STYLE
Definition: ASN1Codes.h:238
@ C_APPEND
Definition: ASN1Codes.h:154
@ C_SET_FIRST_ITEM
Definition: ASN1Codes.h:232
@ C_MODULO
Definition: ASN1Codes.h:204
@ C_ORIGINAL_VALUE
Definition: ASN1Codes.h:103
@ C_ORIGINAL_CONTENT
Definition: ASN1Codes.h:94
@ C_SEND_EVENT
Definition: ASN1Codes.h:220
@ C_NEW_GENERIC_OCTETSTRING
Definition: ASN1Codes.h:263
@ C_DRAW_POLYGON
Definition: ASN1Codes.h:169
@ C_GET_RUNNING_STATUS
Definition: ASN1Codes.h:195
@ C_SET_LABEL
Definition: ASN1Codes.h:236
@ C_ITEMS
Definition: ASN1Codes.h:44
@ C_GET_FILL_COLOUR
Definition: ASN1Codes.h:180
@ C_GET_FIRST_ITEM
Definition: ASN1Codes.h:181
@ C_SET_TIMER
Definition: ASN1Codes.h:246
@ C_GET_LABEL
Definition: ASN1Codes.h:185
@ C_DRAW_ARC
Definition: ASN1Codes.h:166
@ C_DRAW_OVAL
Definition: ASN1Codes.h:168
@ C_STORE_PERSISTENT
Definition: ASN1Codes.h:253
@ C_QUIT
Definition: ASN1Codes.h:212
@ C_SCALE_BITMAP
Definition: ASN1Codes.h:215
@ C_DRAW_POLYLINE
Definition: ASN1Codes.h:170
@ C_READ_PERSISTENT
Definition: ASN1Codes.h:213
@ C_TOKEN_GROUP_ITEMS
Definition: ASN1Codes.h:107
@ C_SELECT_ITEM
Definition: ASN1Codes.h:219
@ C_ADD_ITEM
Definition: ASN1Codes.h:153
@ C_GET_LINE_WIDTH
Definition: ASN1Codes.h:189
@ C_DIVIDE
Definition: ASN1Codes.h:165
@ C_LAUNCH
Definition: ASN1Codes.h:202
@ C_SPAWN
Definition: ASN1Codes.h:250
@ C_DRAW_LINE
Definition: ASN1Codes.h:167
@ C_MULTIPLEX
Definition: ASN1Codes.h:128
@ C_BRING_TO_FRONT
Definition: ASN1Codes.h:155
@ C_UNLOAD
Definition: ASN1Codes.h:259
@ C_GET_TEXT_CONTENT
Definition: ASN1Codes.h:198
@ C_DRAW_SECTOR
Definition: ASN1Codes.h:172
@ C_SELECT
Definition: ASN1Codes.h:218
@ C_TRANSITION_TO
Definition: ASN1Codes.h:258
@ C_GET_CURSOR_POSITION
Definition: ASN1Codes.h:177
@ C_SET_COUNTER_TRIGGER
Definition: ASN1Codes.h:226
@ C_CLONE
Definition: ASN1Codes.h:159
@ C_TEST_VARIABLE
Definition: ASN1Codes.h:255
@ C_DRAW_RECTANGLE
Definition: ASN1Codes.h:171
@ C_SET_COUNTER_POSITION
Definition: ASN1Codes.h:225
@ C_SET_TRANSPARENCY
Definition: ASN1Codes.h:247
@ C_SET_COUNTER_END_POSITION
Definition: ASN1Codes.h:224
@ C_GET_LINE_STYLE
Definition: ASN1Codes.h:188
@ C_SCALE_VIDEO
Definition: ASN1Codes.h:216
@ C_GET_SLIDER_VALUE
Definition: ASN1Codes.h:197
@ C_LINK_EFFECT
Definition: ASN1Codes.h:99
@ C_GET_POSITION
Definition: ASN1Codes.h:194
@ C_GET_TEXT_DATA
Definition: ASN1Codes.h:199
@ C_GET_LIST_SIZE
Definition: ASN1Codes.h:191
@ C_GET_ENTRY_POINT
Definition: ASN1Codes.h:179
@ C_GET_LIST_ITEM
Definition: ASN1Codes.h:190
@ C_RUN
Definition: ASN1Codes.h:214
@ C_UNLOCK_SCREEN
Definition: ASN1Codes.h:260
@ C_ADD
Definition: ASN1Codes.h:152
@ C_DEACTIVATE
Definition: ASN1Codes.h:161
@ C_GET_HIGHLIGHT_STATUS
Definition: ASN1Codes.h:182
@ C_ACTIVATE
Definition: ASN1Codes.h:151
@ C_TOGGLE
Definition: ASN1Codes.h:256
@ C_CLEAR
Definition: ASN1Codes.h:158
@ C_SET_LINE_WIDTH
Definition: ASN1Codes.h:239
@ C_GET_SELECTION_STATUS
Definition: ASN1Codes.h:196
@ C_SET_DATA
Definition: ASN1Codes.h:229
@ C_TOGGLE_ITEM
Definition: ASN1Codes.h:257
@ C_NEW_GENERIC_BOOLEAN
Definition: ASN1Codes.h:261
@ C_GET_LAST_ANCHOR_FIRED
Definition: ASN1Codes.h:186
@ C_SET_CURSOR_SHAPE
Definition: ASN1Codes.h:228
@ C_NEW_GENERIC_CONTENT_REF
Definition: ASN1Codes.h:265
@ C_GET_LINE_COLOUR
Definition: ASN1Codes.h:187
@ C_CALL_ACTION_SLOT
Definition: ASN1Codes.h:157
@ C_GET_PORTION
Definition: ASN1Codes.h:193
@ C_GET_INTERACTION_STATUS
Definition: ASN1Codes.h:183
@ C_SET_CACHE_PRIORITY
Definition: ASN1Codes.h:223
@ C_GET_ENGINE_SUPPORT
Definition: ASN1Codes.h:178
@ C_SET_HIGHLIGHT_STATUS
Definition: ASN1Codes.h:234
@ C_MOVE_TO
Definition: ASN1Codes.h:206
@ C_GET_CELL_ITEM
Definition: ASN1Codes.h:176
@ C_SET_SPEED
Definition: ASN1Codes.h:245
@ C_SET_CURSOR_POSITION
Definition: ASN1Codes.h:227
@ C_SET_PORTION
Definition: ASN1Codes.h:242
@ C_PUT_BEFORE
Definition: ASN1Codes.h:210
@ C_DESELECT
Definition: ASN1Codes.h:163
@ C_DESELECT_ITEM
Definition: ASN1Codes.h:164
@ C_STEP
Definition: ASN1Codes.h:251
@ C_STOP
Definition: ASN1Codes.h:252
@ C_SEND_TO_BACK
Definition: ASN1Codes.h:221
@ C_SET_VOLUME
Definition: ASN1Codes.h:249
@ C_SET_FONT_REF
Definition: ASN1Codes.h:233
@ C_POSITIONS
Definition: ASN1Codes.h:109
@ C_SET_PALETTE_REF
Definition: ASN1Codes.h:241
@ C_LOCK_SCREEN
Definition: ASN1Codes.h:203
@ C_MULTIPLY
Definition: ASN1Codes.h:207
@ C_GET_OVERWRITE_MODE
Definition: ASN1Codes.h:192
@ C_CONTENT_REFERENCE
Definition: ASN1Codes.h:105
@ C_SET_FILL_COLOUR
Definition: ASN1Codes.h:231
@ C_SET_INTERACTION_STATUS
Definition: ASN1Codes.h:235
@ C_SUBTRACT
Definition: ASN1Codes.h:254
@ C_DEL_ITEM
Definition: ASN1Codes.h:162
@ C_MOVE
Definition: ASN1Codes.h:205
@ C_GET_ITEM_STATUS
Definition: ASN1Codes.h:184
@ C_PUT_BEHIND
Definition: ASN1Codes.h:211
@ C_FORK
Definition: ASN1Codes.h:173
@ C_SCROLL_ITEMS
Definition: ASN1Codes.h:217
@ C_GET_VOLUME
Definition: ASN1Codes.h:201
@ C_GET_TOKEN_POSITION
Definition: ASN1Codes.h:200
@ C_SET_LINE_COLOUR
Definition: ASN1Codes.h:237
@ C_SET_VARIABLE
Definition: ASN1Codes.h:248
@ C_NEW_GENERIC_OBJECT_REF
Definition: ASN1Codes.h:264
@ C_SET_ENTRY_POINT
Definition: ASN1Codes.h:230
@ C_GET_AVAILABILITY_STATUS
Definition: ASN1Codes.h:174
@ C_CALL
Definition: ASN1Codes.h:156
@ C_PRELOAD
Definition: ASN1Codes.h:209
@ C_NEW_GENERIC_INTEGER
Definition: ASN1Codes.h:262
@ C_SET_OVERWRITE_MODE
Definition: ASN1Codes.h:240
@ C_SET_BOX_SIZE
Definition: ASN1Codes.h:222
@ C_OPEN_CONNECTION
Definition: ASN1Codes.h:208
#define MHERROR(__text)
Definition: Logging.h:42
const std::array< const QString, 253 > rchTagNames
Definition: ParseText.cpp:75
static constexpr size_t MAX_ENUM
Definition: ParseText.cpp:376
static constexpr size_t MAX_TAG_LENGTH
Definition: ParseText.cpp:71
static int FindTag(const QString &str)
Definition: ParseText.cpp:358
void Copy(const MHOctetString &str)
int m_nStringLength
Definition: ParseText.h:62
ParseTextType m_nType
Definition: ParseText.h:55
int m_lineCount
Definition: ParseText.h:49
MHParseNode * Parse() override
Definition: ParseText.cpp:1113
unsigned char * m_string
Definition: ParseText.h:61
@ PTStartSection
Definition: ParseText.h:52
@ PTEndSection
Definition: ParseText.h:53
unsigned int m_p
Definition: ParseText.h:64
int m_nInt
Definition: ParseText.h:59
void NextSym()
Definition: ParseText.cpp:385
QByteArray m_data
Definition: ParseText.h:65
bool m_fBool
Definition: ParseText.h:60
char m_ch
Definition: ParseText.h:57
MHParseNode * DoParse()
Definition: ParseText.cpp:844
void GetNextChar()
Definition: ParseText.cpp:54
~MHParseText() override
Definition: ParseText.cpp:48
int m_nTag
Definition: ParseText.h:58
void Error(const char *str) const
Definition: ParseText.cpp:379
static int GetStyle(const QString &str)
Definition: Visible.cpp:719
static int GetOrientation(const QString &str)
Definition: Visible.cpp:699
static int GetStartCorner(const QString &str)
Definition: Text.cpp:199
static int GetLineOrientation(const QString &str)
Definition: Text.cpp:178
static int GetJustification(const QString &str)
Definition: Text.cpp:159
unsigned char m_t
Definition: ParseText.cpp:337
unsigned char m_g
Definition: ParseText.cpp:337
const char * m_name
Definition: ParseText.cpp:336
unsigned char m_b
Definition: ParseText.cpp:337
unsigned char m_r
Definition: ParseText.cpp:337