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