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 /*
23 Parser for the textual form of MHEG5.
24 This 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)
69 static constexpr int MAX_TAG_LENGTH { 30 };
70 #else
71 static constexpr size_t MAX_TAG_LENGTH { 30 };
72 #endif
73 
74 const 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 };
339 static 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.
358 static 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)
374 static constexpr int MAX_ENUM { 30 };
375 #else
376 static constexpr size_t MAX_ENUM { 30 };
377 #endif
378 
379 void 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  do
414  {
415  GetNextChar();
416  }
417  while (m_ch != '\n' && m_ch != '\f' && m_ch != '\r');
418 
419  continue; // Next symbol
420  }
421 
422  case ':': // Start of a tag
423  {
424  m_nType = PTTag;
425  QString buff {};
426  buff.reserve(MAX_TAG_LENGTH);
427 
428  do
429  {
430  buff += m_ch;
431  GetNextChar();
432 
433  if (buff.size() == MAX_TAG_LENGTH)
434  {
435  break;
436  }
437  }
438  while ((m_ch >= 'a' && m_ch <= 'z') || (m_ch >= 'A' && m_ch <= 'Z'));
439 
440  // Look it up and return it if it's found.
441  m_nTag = FindTag(buff);
442 
443  if (m_nTag >= 0)
444  {
445  return;
446  }
447 
448  // Unrecognised tag.
449  Error("Unrecognised tag");
450  break;
451  }
452 
453  case '"': // Start of a string
454  {
455  m_nType = PTString;
456  // MHEG strings can include NULs. For the moment we pass back the length and also
457  // null-terminate the strings.
458  m_nStringLength = 0;
459 
460  while (true)
461  {
462  GetNextChar();
463 
464  if (m_ch == '"')
465  {
466  break; // Finished the string.
467  }
468 
469  if (m_ch == '\\')
470  {
471  GetNextChar(); // Escape character. Include the next char in the string.
472  }
473 
474  if (m_ch == '\n' || m_ch == '\r')
475  {
476  Error("Unterminated string");
477  }
478 
479  // We grow the buffer to the largest string in the input.
480  auto *str = (unsigned char *)realloc(m_string, m_nStringLength + 2);
481 
482  if (str == nullptr)
483  {
484  Error("Insufficient memory");
485  }
486 
487  m_string = str;
489  }
490 
491  GetNextChar(); // Skip the closing quote
493  return;
494  }
495 
496  case '\'': // Start of a string using quoted printable
497  {
498  m_nType = PTString;
499  m_nStringLength = 0;
500 
501  // Quotable printable strings contain escape sequences beginning with the
502  // escape character '='. The strings can span lines but each line must
503  // end with an equal sign.
504  while (true)
505  {
506  GetNextChar();
507 
508  if (m_ch == '\'')
509  {
510  break;
511  }
512 
513  if (m_ch == '\n')
514  {
515  Error("Unterminated string");
516  }
517 
518  if (m_ch == '=') // Special code in quoted-printable.
519  {
520  // Should be followed by two hex digits or by white space and a newline.
521  GetNextChar();
522 
523  if (m_ch == ' ' || m_ch == '\t' || m_ch == '\r' || m_ch == '\n')
524  {
525  // White space. Remove everything up to the newline.
526  while (m_ch != '\n')
527  {
528  if (m_ch != ' ' && m_ch != '\t' && m_ch != '\r')
529  {
530  Error("Malformed quoted printable string");
531  }
532 
533  GetNextChar();
534  }
535 
536  continue; // continue with the first character on the next line
537  }
538 
539  int byte = 0;
540 
541  if (m_ch >= '0' && m_ch <= '9')
542  {
543  byte = m_ch - '0';
544  }
545  else if (m_ch >= 'A' && m_ch <= 'F')
546  {
547  byte = m_ch - 'A' + 10;
548  }
549  else if (m_ch >= 'a' && m_ch <= 'f')
550  {
551  byte = m_ch - 'a' + 10;
552  }
553  else
554  {
555  Error("Malformed quoted printable string");
556  }
557 
558  byte *= 16;
559  GetNextChar();
560 
561  if (m_ch >= '0' && m_ch <= '9')
562  {
563  byte += m_ch - '0';
564  }
565  else if (m_ch >= 'A' && m_ch <= 'F')
566  {
567  byte += m_ch - 'A' + 10;
568  }
569  else if (m_ch >= 'a' && m_ch <= 'f')
570  {
571  byte += m_ch - 'a' + 10;
572  }
573  else
574  {
575  Error("Malformed quoted printable string");
576  }
577 
578  m_ch = byte; // Put this into the string.
579  }
580 
581  // We grow the buffer to the largest string in the input.
582  auto *str = (unsigned char *)realloc(m_string, m_nStringLength + 2);
583 
584  if (str == nullptr)
585  {
586  Error("Insufficient memory");
587  }
588 
589  m_string = str;
591  }
592 
593  GetNextChar(); // Skip the closing quote
595  return;
596  }
597 
598  case '`': // Start of a string using base 64
599  // These can, presumably span lines.
600  MHERROR("Base 64 string is not implemented");
601  break;
602 
603  case '#': // Start of 3-byte hex constant.
604  MHERROR("3-byte hex constant is not implemented");
605  break;
606 
607  case '-':
608  case '0':
609  case '1':
610  case '2':
611  case '3':
612  case '4':
613  case '5':
614  case '6':
615  case '7':
616  case '8':
617  case '9':
618  {
619  m_nType = PTInt;
620  bool negative = m_ch == '-';
621 
622  if (negative)
623  {
624  GetNextChar();
625 
626  if (m_ch < '0' || m_ch > '9')
627  {
628  Error("Expected digit after '-'");
629  }
630  }
631 
632  // Start of a number. Hex can be represented as 0xn.
633  // Strictly speaking hex values cannot be preceded by a minus sign.
634  m_nInt = m_ch - '0';
635  GetNextChar();
636 
637  if (m_nInt == 0 && (m_ch == 'x' || m_ch == 'X'))
638  {
639  MHERROR("Hex constant is not implemented");
640  }
641 
642  while (m_ch >= '0' && m_ch <= '9')
643  {
644  m_nInt = m_nInt * 10 + m_ch - '0';
645  // TODO: What about overflow?
646  GetNextChar();
647  }
648 
649  if (negative)
650  {
651  m_nInt = -m_nInt;
652  }
653 
654  return;
655  }
656 
657  case 'a':
658  case 'b':
659  case 'c':
660  case 'd':
661  case 'e':
662  case 'f':
663  case 'g':
664  case 'h':
665  case 'i':
666  case 'j':
667  case 'k':
668  case 'l':
669  case 'm':
670  case 'n':
671  case 'o':
672  case 'p':
673  case 'q':
674  case 'r':
675  case 's':
676  case 't':
677  case 'u':
678  case 'v':
679  case 'w':
680  case 'x':
681  case 'y':
682  case 'z':
683  case 'A':
684  case 'B':
685  case 'C':
686  case 'D':
687  case 'E':
688  case 'F':
689  case 'G':
690  case 'H':
691  case 'I':
692  case 'J':
693  case 'K':
694  case 'L':
695  case 'M':
696  case 'N':
697  case 'O':
698  case 'P':
699  case 'Q':
700  case 'R':
701  case 'S':
702  case 'T':
703  case 'U':
704  case 'V':
705  case 'W':
706  case 'X':
707  case 'Y':
708  case 'Z':
709  {
710  // Start of an enumerated type.
711  m_nType = PTEnum;
712  QString buff;
713  buff.reserve(MAX_ENUM);
714 
715  do
716  {
717  buff += m_ch;
718  GetNextChar();
719 
720  if (buff.size() == MAX_ENUM)
721  {
722  break;
723  }
724  }
725  while ((m_ch >= 'a' && m_ch <= 'z') || (m_ch >= 'A' && m_ch <= 'Z') || m_ch == '-');
726 
727  if (buff.compare("NULL", Qt::CaseInsensitive) == 0)
728  {
729  m_nType = PTNull;
730  return;
731  }
732 
733  if (buff.compare("true", Qt::CaseInsensitive) == 0)
734  {
735  m_nType = PTBool;
736  m_fBool = true;
737  return;
738  }
739 
740  if (buff.compare("false", Qt::CaseInsensitive) == 0)
741  {
742  m_nType = PTBool;
743  m_fBool = false;
744  return;
745  }
746 
747  // Look up the tag in all the tables. Fortunately all the enumerations
748  // are distinct so we don't need to know the context.
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 
778 
779  if (m_nInt > 0)
780  {
781  return;
782  }
783 
784  m_nInt = MHSlider::GetStyle(buff);
785 
786  if (m_nInt > 0)
787  {
788  return;
789  }
790 
791  // Check the colour table. If it's there generate a string containing the colour info.
792  for (const auto & colour : colourTable)
793  {
794  if (buff.compare(colour.m_name, Qt::CaseInsensitive) == 0)
795  {
796  m_nType = PTString;
797  auto *str = (unsigned char *)realloc(m_string, 4 + 1);
798 
799  if (str == nullptr)
800  {
801  Error("Insufficient memory");
802  }
803 
804  m_string = str;
805  m_string[0] = colour.m_r;
806  m_string[1] = colour.m_g;
807  m_string[2] = colour.m_b;
808  m_string[3] = colour.m_t;
809  m_nStringLength = 4;
811  return;
812  }
813  }
814 
815  Error("Unrecognised enumeration");
816  break;
817  }
818 
819  case '{': // Start of a "section".
820  // The standard indicates that open brace followed by a tag should be written
821  // as a single word. We'll be more lenient and allow spaces or comments between them.
823  GetNextChar();
824  return;
825 
826  case '}': // End of a "section".
828  GetNextChar();
829  return;
830 
831  case '(': // Start of a sequence.
833  GetNextChar();
834  return;
835 
836  case ')': // End of a sequence.
837  m_nType = PTEndSeq;
838  GetNextChar();
839  return;
840 
841  case EOF:
842  m_nType = PTEOF;
843  return;
844 
845  default:
846  Error("Unknown character");
847  GetNextChar();
848  }
849  }
850 }
851 
853 {
854  MHParseNode *pRes = nullptr;
855 
856  try
857  {
858  switch (m_nType)
859  {
860  case PTStartSection: // Open curly bracket
861  {
862  NextSym();
863 
864  // Should be followed by a tag.
865  if (m_nType != PTTag)
866  {
867  Error("Expected ':' after '{'");
868  }
869 
870  auto *pTag = new MHPTagged(m_nTag);
871  pRes = pTag;
872  NextSym();
873 
874  while (m_nType != PTEndSection)
875  {
876  pTag->AddArg(DoParse());
877  }
878 
879  NextSym(); // Remove the close curly bracket.
880  break;
881  }
882 
883  case PTTag: // Tag on its own.
884  {
885  int nTag = m_nTag;
886  auto *pTag = new MHPTagged(nTag);
887  pRes = pTag;
888  NextSym();
889 
890  switch (nTag)
891  {
892  case C_ITEMS:
893  case C_LINK_EFFECT:
894  case C_ACTIVATE:
895  case C_ADD:
896  case C_ADD_ITEM:
897  case C_APPEND:
898  case C_BRING_TO_FRONT:
899  case C_CALL:
900  case C_CALL_ACTION_SLOT:
901  case C_CLEAR:
902  case C_CLONE:
903  case C_CLOSE_CONNECTION:
904  case C_DEACTIVATE:
905  case C_DEL_ITEM:
906  case C_DESELECT:
907  case C_DESELECT_ITEM:
908  case C_DIVIDE:
909  case C_DRAW_ARC:
910  case C_DRAW_LINE:
911  case C_DRAW_OVAL:
912  case C_DRAW_POLYGON:
913  case C_DRAW_POLYLINE:
914  case C_DRAW_RECTANGLE:
915  case C_DRAW_SECTOR:
916  case C_FORK:
918  case C_GET_BOX_SIZE:
919  case C_GET_CELL_ITEM:
922  case C_GET_ENTRY_POINT:
923  case C_GET_FILL_COLOUR:
924  case C_GET_FIRST_ITEM:
927  case C_GET_ITEM_STATUS:
928  case C_GET_LABEL:
930  case C_GET_LINE_COLOUR:
931  case C_GET_LINE_STYLE:
932  case C_GET_LINE_WIDTH:
933  case C_GET_LIST_ITEM:
934  case C_GET_LIST_SIZE:
936  case C_GET_PORTION:
937  case C_GET_POSITION:
940  case C_GET_SLIDER_VALUE:
941  case C_GET_TEXT_CONTENT:
942  case C_GET_TEXT_DATA:
944  case C_GET_VOLUME:
945  case C_LAUNCH:
946  case C_LOCK_SCREEN:
947  case C_MODULO:
948  case C_MOVE:
949  case C_MOVE_TO:
950  case C_MULTIPLY:
951  case C_OPEN_CONNECTION:
952  case C_PRELOAD:
953  case C_PUT_BEFORE:
954  case C_PUT_BEHIND:
955  case C_QUIT:
956  case C_READ_PERSISTENT:
957  case C_RUN:
958  case C_SCALE_BITMAP:
959  case C_SCALE_VIDEO:
960  case C_SCROLL_ITEMS:
961  case C_SELECT:
962  case C_SELECT_ITEM:
963  case C_SEND_EVENT:
964  case C_SEND_TO_BACK:
965  case C_SET_BOX_SIZE:
971  case C_SET_CURSOR_SHAPE:
972  case C_SET_DATA:
973  case C_SET_ENTRY_POINT:
974  case C_SET_FILL_COLOUR:
975  case C_SET_FIRST_ITEM:
976  case C_SET_FONT_REF:
979  case C_SET_LABEL:
980  case C_SET_LINE_COLOUR:
981  case C_SET_LINE_STYLE:
982  case C_SET_LINE_WIDTH:
984  case C_SET_PALETTE_REF:
985  case C_SET_PORTION:
986  case C_SET_POSITION:
987  case C_SET_SLIDER_VALUE:
988  case C_SET_SPEED:
989  case C_SET_TIMER:
990  case C_SET_TRANSPARENCY:
991  case C_SET_VARIABLE:
992  case C_SET_VOLUME:
993  case C_SPAWN:
994  case C_STEP:
995  case C_STOP:
996  case C_STORE_PERSISTENT:
997  case C_SUBTRACT:
998  case C_TEST_VARIABLE:
999  case C_TOGGLE:
1000  case C_TOGGLE_ITEM:
1001  case C_TRANSITION_TO:
1002  case C_UNLOAD:
1003  case C_UNLOCK_SCREEN:
1004  case C_CONTENT_REFERENCE:
1005  case C_TOKEN_GROUP_ITEMS:
1006  case C_POSITIONS:
1007  case C_MULTIPLEX:
1008  {
1009  // These are parenthesised in the text form. We have to remove the
1010  // parentheses otherwise we will return a sequence which will not be
1011  // be compatible with the binary form.
1012  if (m_nType != PTStartSeq)
1013  {
1014  Error("Expected '('");
1015  }
1016 
1017  NextSym();
1018 
1019  while (m_nType != PTEndSeq)
1020  {
1021  pTag->AddArg(DoParse());
1022  }
1023 
1024  NextSym(); // Remove the close parenthesis.
1025  break;
1026  }
1027  case C_ORIGINAL_CONTENT:
1028  case C_NEW_GENERIC_BOOLEAN:
1029  case C_NEW_GENERIC_INTEGER:
1033  case C_ORIGINAL_VALUE:
1034  // These always have an argument which may be a tagged item.
1035  {
1036  // Is it always the case that there is at least one argument so if we haven't
1037  // had any arguments yet we should always process a tag as an argument?
1038  pTag->AddArg(DoParse());
1039  break;
1040  }
1041  default:
1042 
1043  // This can be followed by an int, etc but a new tag is dealt with by the caller.
1044  while (m_nType == PTBool || m_nType == PTInt || m_nType == PTString || m_nType == PTEnum || m_nType == PTStartSeq)
1045  {
1046  pTag->AddArg(DoParse());
1047  }
1048 
1049  }
1050 
1051  break;
1052  }
1053 
1054  case PTInt:
1055  {
1056  pRes = new MHPInt(m_nInt);
1057  NextSym();
1058  break;
1059  }
1060 
1061  case PTBool:
1062  {
1063  pRes = new MHPBool(m_fBool);
1064  NextSym();
1065  break;
1066  }
1067 
1068  case PTString:
1069  {
1070  MHOctetString str;
1071  str.Copy(MHOctetString((const char *)m_string, m_nStringLength));
1072  pRes = new MHPString(str);
1073  NextSym();
1074  break;
1075  }
1076 
1077  case PTEnum:
1078  {
1079  pRes = new MHPEnum(m_nInt);
1080  NextSym();
1081  break;
1082  }
1083 
1084  case PTNull:
1085  {
1086  pRes = new MHPNull;
1087  NextSym();
1088  break;
1089  }
1090 
1091  case PTStartSeq: // Open parenthesis.
1092  {
1093  auto *pSeq = new MHParseSequence;
1094  pRes = pSeq;
1095  NextSym();
1096 
1097  while (m_nType != PTEndSeq)
1098  {
1099  pSeq->Append(DoParse());
1100  }
1101 
1102  NextSym(); // Remove the close parenthesis.
1103  break;
1104  }
1105 
1106  default:
1107  Error("Unexpected symbol");
1108  }
1109 
1110  return pRes;
1111  }
1112  catch (...)
1113  {
1114  delete(pRes);
1115  throw;
1116  }
1117 }
1118 
1119 
1120 // Run the parser
1122 {
1123  GetNextChar(); // Initialise m_ch
1124  NextSym(); // Initialise the symbol values.
1125  return DoParse();
1126 }
1127 
C_SET_ENTRY_POINT
@ C_SET_ENTRY_POINT
Definition: ASN1Codes.h:230
MHParseText::GetNextChar
void GetNextChar()
Definition: ParseText.cpp:54
C_STORE_PERSISTENT
@ C_STORE_PERSISTENT
Definition: ASN1Codes.h:253
MHParseText::m_string
unsigned char * m_string
Definition: ParseText.h:60
C_SET_PALETTE_REF
@ C_SET_PALETTE_REF
Definition: ASN1Codes.h:241
C_FORK
@ C_FORK
Definition: ASN1Codes.h:173
C_SET_HIGHLIGHT_STATUS
@ C_SET_HIGHLIGHT_STATUS
Definition: ASN1Codes.h:234
C_SET_CURSOR_POSITION
@ C_SET_CURSOR_POSITION
Definition: ASN1Codes.h:227
C_DRAW_POLYLINE
@ C_DRAW_POLYLINE
Definition: ASN1Codes.h:170
C_GET_ENTRY_POINT
@ C_GET_ENTRY_POINT
Definition: ASN1Codes.h:179
C_SET_TIMER
@ C_SET_TIMER
Definition: ASN1Codes.h:246
MHParseText::m_fBool
bool m_fBool
Definition: ParseText.h:59
Groups.h
C_GET_SLIDER_VALUE
@ C_GET_SLIDER_VALUE
Definition: ASN1Codes.h:197
C_DRAW_LINE
@ C_DRAW_LINE
Definition: ASN1Codes.h:167
colourTable::m_b
unsigned char m_b
Definition: ParseText.cpp:337
C_GET_CURSOR_POSITION
@ C_GET_CURSOR_POSITION
Definition: ASN1Codes.h:177
C_SET_INTERACTION_STATUS
@ C_SET_INTERACTION_STATUS
Definition: ASN1Codes.h:235
C_GET_FILL_COLOUR
@ C_GET_FILL_COLOUR
Definition: ASN1Codes.h:180
C_DRAW_RECTANGLE
@ C_DRAW_RECTANGLE
Definition: ASN1Codes.h:171
MHParseText::m_nStringLength
int m_nStringLength
Definition: ParseText.h:61
C_MULTIPLY
@ C_MULTIPLY
Definition: ASN1Codes.h:207
MHParseText::m_lineCount
int m_lineCount
Definition: ParseText.h:49
C_MOVE
@ C_MOVE
Definition: ASN1Codes.h:205
C_GET_LIST_ITEM
@ C_GET_LIST_ITEM
Definition: ASN1Codes.h:190
MHParseText::DoParse
MHParseNode * DoParse()
Definition: ParseText.cpp:852
ASN1Codes.h
MAX_ENUM
static constexpr size_t MAX_ENUM
Definition: ParseText.cpp:376
C_STEP
@ C_STEP
Definition: ASN1Codes.h:251
MHParseText::m_nTag
int m_nTag
Definition: ParseText.h:57
C_SET_VARIABLE
@ C_SET_VARIABLE
Definition: ASN1Codes.h:248
C_LAUNCH
@ C_LAUNCH
Definition: ASN1Codes.h:202
C_BRING_TO_FRONT
@ C_BRING_TO_FRONT
Definition: ASN1Codes.h:155
C_TOGGLE
@ C_TOGGLE
Definition: ASN1Codes.h:256
C_SEND_EVENT
@ C_SEND_EVENT
Definition: ASN1Codes.h:220
MHPTagged
Definition: ParseNode.h:84
C_NEW_GENERIC_OCTETSTRING
@ C_NEW_GENERIC_OCTETSTRING
Definition: ASN1Codes.h:263
C_SET_FONT_REF
@ C_SET_FONT_REF
Definition: ASN1Codes.h:233
C_SET_BOX_SIZE
@ C_SET_BOX_SIZE
Definition: ASN1Codes.h:222
C_UNLOAD
@ C_UNLOAD
Definition: ASN1Codes.h:259
C_OPEN_CONNECTION
@ C_OPEN_CONNECTION
Definition: ASN1Codes.h:208
C_NEW_GENERIC_BOOLEAN
@ C_NEW_GENERIC_BOOLEAN
Definition: ASN1Codes.h:261
C_GET_TOKEN_POSITION
@ C_GET_TOKEN_POSITION
Definition: ASN1Codes.h:200
C_GET_POSITION
@ C_GET_POSITION
Definition: ASN1Codes.h:194
C_SET_VOLUME
@ C_SET_VOLUME
Definition: ASN1Codes.h:249
C_TEST_VARIABLE
@ C_TEST_VARIABLE
Definition: ASN1Codes.h:255
C_SET_PORTION
@ C_SET_PORTION
Definition: ASN1Codes.h:242
C_CALL_ACTION_SLOT
@ C_CALL_ACTION_SLOT
Definition: ASN1Codes.h:157
C_MODULO
@ C_MODULO
Definition: ASN1Codes.h:204
MHParseText::PTInt
@ PTInt
Definition: ParseText.h:51
C_GET_LIST_SIZE
@ C_GET_LIST_SIZE
Definition: ASN1Codes.h:191
C_NEW_GENERIC_OBJECT_REF
@ C_NEW_GENERIC_OBJECT_REF
Definition: ASN1Codes.h:264
C_GET_BOX_SIZE
@ C_GET_BOX_SIZE
Definition: ASN1Codes.h:175
C_SET_FILL_COLOUR
@ C_SET_FILL_COLOUR
Definition: ASN1Codes.h:231
C_PUT_BEFORE
@ C_PUT_BEFORE
Definition: ASN1Codes.h:210
MHOctetString
Definition: BaseClasses.h:107
C_SET_OVERWRITE_MODE
@ C_SET_OVERWRITE_MODE
Definition: ASN1Codes.h:240
C_GET_TEXT_CONTENT
@ C_GET_TEXT_CONTENT
Definition: ASN1Codes.h:198
C_GET_FIRST_ITEM
@ C_GET_FIRST_ITEM
Definition: ASN1Codes.h:181
C_DEACTIVATE
@ C_DEACTIVATE
Definition: ASN1Codes.h:161
C_CONTENT_REFERENCE
@ C_CONTENT_REFERENCE
Definition: ASN1Codes.h:105
MHParseText::Error
void Error(const char *str) const
Definition: ParseText.cpp:379
MHParseText::m_ch
char m_ch
Definition: ParseText.h:56
C_SCALE_VIDEO
@ C_SCALE_VIDEO
Definition: ASN1Codes.h:216
C_SELECT_ITEM
@ C_SELECT_ITEM
Definition: ASN1Codes.h:219
C_SET_FIRST_ITEM
@ C_SET_FIRST_ITEM
Definition: ASN1Codes.h:232
C_SET_LINE_WIDTH
@ C_SET_LINE_WIDTH
Definition: ASN1Codes.h:239
C_UNLOCK_SCREEN
@ C_UNLOCK_SCREEN
Definition: ASN1Codes.h:260
colourTable
Definition: ParseText.cpp:334
C_SCROLL_ITEMS
@ C_SCROLL_ITEMS
Definition: ASN1Codes.h:217
MHParseText::m_data
QByteArray m_data
Definition: ParseText.h:64
MHText::GetJustification
static int GetJustification(const QString &str)
Definition: Text.cpp:150
C_SET_CURSOR_SHAPE
@ C_SET_CURSOR_SHAPE
Definition: ASN1Codes.h:228
C_ACTIVATE
@ C_ACTIVATE
Definition: ASN1Codes.h:151
MHPNull
Definition: ParseNode.h:135
C_READ_PERSISTENT
@ C_READ_PERSISTENT
Definition: ASN1Codes.h:213
C_SPAWN
@ C_SPAWN
Definition: ASN1Codes.h:250
MHParseText::PTNull
@ PTNull
Definition: ParseText.h:52
C_SET_POSITION
@ C_SET_POSITION
Definition: ASN1Codes.h:243
C_DRAW_OVAL
@ C_DRAW_OVAL
Definition: ASN1Codes.h:168
colourTable::m_r
unsigned char m_r
Definition: ParseText.cpp:337
C_NEW_GENERIC_INTEGER
@ C_NEW_GENERIC_INTEGER
Definition: ASN1Codes.h:262
C_GET_CELL_ITEM
@ C_GET_CELL_ITEM
Definition: ASN1Codes.h:176
C_TOKEN_GROUP_ITEMS
@ C_TOKEN_GROUP_ITEMS
Definition: ASN1Codes.h:107
C_PUT_BEHIND
@ C_PUT_BEHIND
Definition: ASN1Codes.h:211
C_CALL
@ C_CALL
Definition: ASN1Codes.h:156
C_RUN
@ C_RUN
Definition: ASN1Codes.h:214
ParseNode.h
C_TOGGLE_ITEM
@ C_TOGGLE_ITEM
Definition: ASN1Codes.h:257
MHParseText::~MHParseText
~MHParseText() override
Definition: ParseText.cpp:48
ParseText.h
C_TRANSITION_TO
@ C_TRANSITION_TO
Definition: ASN1Codes.h:258
C_SELECT
@ C_SELECT
Definition: ASN1Codes.h:218
MHParseText::PTEndSeq
@ PTEndSeq
Definition: ParseText.h:52
MHParseSequence
Definition: ParseNode.h:75
MHParseText::PTTag
@ PTTag
Definition: ParseText.h:51
C_MULTIPLEX
@ C_MULTIPLEX
Definition: ASN1Codes.h:128
rchTagNames
const std::array< const QString, 253 > rchTagNames
Definition: ParseText.cpp:75
C_DESELECT
@ C_DESELECT
Definition: ASN1Codes.h:163
Engine.h
MHPEnum
Definition: ParseNode.h:106
C_DIVIDE
@ C_DIVIDE
Definition: ASN1Codes.h:165
C_DESELECT_ITEM
@ C_DESELECT_ITEM
Definition: ASN1Codes.h:164
C_GET_LINE_STYLE
@ C_GET_LINE_STYLE
Definition: ASN1Codes.h:188
MHText::GetStartCorner
static int GetStartCorner(const QString &str)
Definition: Text.cpp:190
colourTable::m_t
unsigned char m_t
Definition: ParseText.cpp:337
Ingredients.h
C_DEL_ITEM
@ C_DEL_ITEM
Definition: ASN1Codes.h:162
C_SET_SPEED
@ C_SET_SPEED
Definition: ASN1Codes.h:245
C_SET_COUNTER_END_POSITION
@ C_SET_COUNTER_END_POSITION
Definition: ASN1Codes.h:224
MHSlider::GetStyle
static int GetStyle(const QString &str)
Definition: Visible.cpp:712
MHParseText::PTStartSection
@ PTStartSection
Definition: ParseText.h:51
C_SET_DATA
@ C_SET_DATA
Definition: ASN1Codes.h:229
C_CLEAR
@ C_CLEAR
Definition: ASN1Codes.h:158
C_LINK_EFFECT
@ C_LINK_EFFECT
Definition: ASN1Codes.h:99
C_SUBTRACT
@ C_SUBTRACT
Definition: ASN1Codes.h:254
Text.h
C_ITEMS
@ C_ITEMS
Definition: ASN1Codes.h:44
C_GET_LAST_ANCHOR_FIRED
@ C_GET_LAST_ANCHOR_FIRED
Definition: ASN1Codes.h:186
MHParseText::PTString
@ PTString
Definition: ParseText.h:51
MHPString
Definition: ParseNode.h:125
Root.h
MHPBool
Definition: ParseNode.h:115
C_SET_CACHE_PRIORITY
@ C_SET_CACHE_PRIORITY
Definition: ASN1Codes.h:223
C_ADD
@ C_ADD
Definition: ASN1Codes.h:152
C_ORIGINAL_VALUE
@ C_ORIGINAL_VALUE
Definition: ASN1Codes.h:103
MHParseText::PTEOF
@ PTEOF
Definition: ParseText.h:53
C_NEW_GENERIC_CONTENT_REF
@ C_NEW_GENERIC_CONTENT_REF
Definition: ASN1Codes.h:265
C_POSITIONS
@ C_POSITIONS
Definition: ASN1Codes.h:109
C_SET_TRANSPARENCY
@ C_SET_TRANSPARENCY
Definition: ASN1Codes.h:247
C_GET_OVERWRITE_MODE
@ C_GET_OVERWRITE_MODE
Definition: ASN1Codes.h:192
C_GET_VOLUME
@ C_GET_VOLUME
Definition: ASN1Codes.h:201
C_SET_LINE_COLOUR
@ C_SET_LINE_COLOUR
Definition: ASN1Codes.h:237
MHParseText::PTStartSeq
@ PTStartSeq
Definition: ParseText.h:52
C_GET_INTERACTION_STATUS
@ C_GET_INTERACTION_STATUS
Definition: ASN1Codes.h:183
MAX_TAG_LENGTH
static constexpr size_t MAX_TAG_LENGTH
Definition: ParseText.cpp:71
MHSlider::GetOrientation
static int GetOrientation(const QString &str)
Definition: Visible.cpp:692
MHParseText::m_p
unsigned int m_p
Definition: ParseText.h:63
BaseClasses.h
C_SET_SLIDER_VALUE
@ C_SET_SLIDER_VALUE
Definition: ASN1Codes.h:244
C_PRELOAD
@ C_PRELOAD
Definition: ASN1Codes.h:209
C_DRAW_ARC
@ C_DRAW_ARC
Definition: ASN1Codes.h:166
MHParseNode
Definition: ParseNode.h:38
FindTag
static int FindTag(const QString &str)
Definition: ParseText.cpp:358
C_GET_PORTION
@ C_GET_PORTION
Definition: ASN1Codes.h:193
C_SET_COUNTER_TRIGGER
@ C_SET_COUNTER_TRIGGER
Definition: ASN1Codes.h:226
MHParseText::PTEndSection
@ PTEndSection
Definition: ParseText.h:52
MHParseText::PTEnum
@ PTEnum
Definition: ParseText.h:51
C_SET_LINE_STYLE
@ C_SET_LINE_STYLE
Definition: ASN1Codes.h:238
colourTable::m_name
const char * m_name
Definition: ParseText.cpp:336
C_ORIGINAL_CONTENT
@ C_ORIGINAL_CONTENT
Definition: ASN1Codes.h:94
MHERROR
#define MHERROR(__text)
Definition: Logging.h:42
Logging.h
MHParseText::PTBool
@ PTBool
Definition: ParseText.h:53
C_SCALE_BITMAP
@ C_SCALE_BITMAP
Definition: ASN1Codes.h:215
MHParseText::m_nType
ParseTextType m_nType
Definition: ParseText.h:54
C_GET_LINE_WIDTH
@ C_GET_LINE_WIDTH
Definition: ASN1Codes.h:189
C_GET_LINE_COLOUR
@ C_GET_LINE_COLOUR
Definition: ASN1Codes.h:187
C_MOVE_TO
@ C_MOVE_TO
Definition: ASN1Codes.h:206
C_GET_RUNNING_STATUS
@ C_GET_RUNNING_STATUS
Definition: ASN1Codes.h:195
C_QUIT
@ C_QUIT
Definition: ASN1Codes.h:212
C_SEND_TO_BACK
@ C_SEND_TO_BACK
Definition: ASN1Codes.h:221
MHParseText::Parse
MHParseNode * Parse() override
Definition: ParseText.cpp:1121
MHPInt
Definition: ParseNode.h:96
MHText::GetLineOrientation
static int GetLineOrientation(const QString &str)
Definition: Text.cpp:169
MHParseText::NextSym
void NextSym()
Definition: ParseText.cpp:385
C_CLONE
@ C_CLONE
Definition: ASN1Codes.h:159
colourTable::m_g
unsigned char m_g
Definition: ParseText.cpp:337
C_DRAW_SECTOR
@ C_DRAW_SECTOR
Definition: ASN1Codes.h:172
C_DRAW_POLYGON
@ C_DRAW_POLYGON
Definition: ASN1Codes.h:169
C_SET_LABEL
@ C_SET_LABEL
Definition: ASN1Codes.h:236
C_GET_SELECTION_STATUS
@ C_GET_SELECTION_STATUS
Definition: ASN1Codes.h:196
C_SET_COUNTER_POSITION
@ C_SET_COUNTER_POSITION
Definition: ASN1Codes.h:225
C_GET_HIGHLIGHT_STATUS
@ C_GET_HIGHLIGHT_STATUS
Definition: ASN1Codes.h:182
C_LOCK_SCREEN
@ C_LOCK_SCREEN
Definition: ASN1Codes.h:203
C_STOP
@ C_STOP
Definition: ASN1Codes.h:252
MHOctetString::Copy
void Copy(const MHOctetString &str)
Definition: BaseClasses.cpp:131
MHParseText::m_nInt
int m_nInt
Definition: ParseText.h:58
C_ADD_ITEM
@ C_ADD_ITEM
Definition: ASN1Codes.h:153
C_CLOSE_CONNECTION
@ C_CLOSE_CONNECTION
Definition: ASN1Codes.h:160
C_GET_ENGINE_SUPPORT
@ C_GET_ENGINE_SUPPORT
Definition: ASN1Codes.h:178
C_GET_LABEL
@ C_GET_LABEL
Definition: ASN1Codes.h:185
C_GET_TEXT_DATA
@ C_GET_TEXT_DATA
Definition: ASN1Codes.h:199
C_GET_ITEM_STATUS
@ C_GET_ITEM_STATUS
Definition: ASN1Codes.h:184
C_GET_AVAILABILITY_STATUS
@ C_GET_AVAILABILITY_STATUS
Definition: ASN1Codes.h:174
C_APPEND
@ C_APPEND
Definition: ASN1Codes.h:154