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 #include "ParseNode.h"
29 #include "BaseClasses.h"
30 #include "ASN1Codes.h"
31 #include "Root.h"
32 #include "Groups.h"
33 #include <cctype>
34 #include "Ingredients.h" // For GetEventType
35 #include "Text.h" // For GetJustification etc
36 #include "Engine.h"
37 #include "Logging.h"
38 
39 
40 #ifndef WIN32
41 #define stricmp strcasecmp
42 #endif
43 
44 
46 {
47  free(m_String);
48 }
49 
50 // Get the next character.
52 {
53  if ((int)m_p >= m_data.size())
54  {
55  m_ch = EOF;
56  }
57  else
58  {
59  m_ch = m_data[m_p++];
60  }
61 }
62 
63 // Maximum length of a tag (i.e. a symbol beginning with a colon). Actually the longest is around 22 chars.
64 #define MAX_TAG_LENGTH 30
65 
66 const char *rchTagNames[] =
67 {
68  ":Application",
69  ":Scene",
70  ":StdID",
71  ":StdVersion",
72  ":ObjectInfo",
73  ":OnStartUp",
74  ":OnCloseDown",
75  ":OrigGCPriority",
76  ":Items",
77  ":ResidentPrg",
78  ":RemotePrg",
79  ":InterchgPrg",
80  ":Palette",
81  ":Font", // Occurs twice.
82  ":CursorShape",
83  ":BooleanVar",
84  ":IntegerVar",
85  ":OStringVar",
86  ":ObjectRefVar",
87  ":ContentRefVar",
88  ":Link",
89  ":Stream",
90  ":Bitmap",
91  ":LineArt",
92  ":DynamicLineArt",
93  ":Rectangle",
94  ":Hotspot",
95  ":SwitchButton",
96  ":PushButton",
97  ":Text",
98  ":EntryField",
99  ":HyperText",
100  ":Slider",
101  ":TokenGroup",
102  ":ListGroup",
103  ":OnSpawnCloseDown",
104  ":OnRestart",
105  "", // Default attributes - encoded as a group in binary
106  ":CharacterSet",
107  ":BackgroundColour",
108  ":TextCHook",
109  ":TextColour",
110  ":Font",
111  ":FontAttributes",
112  ":InterchgPrgCHook",
113  ":StreamCHook",
114  ":BitmapCHook",
115  ":LineArtCHook",
116  ":ButtonRefColour",
117  ":HighlightRefColour",
118  ":SliderRefColour",
119  ":InputEventReg",
120  ":SceneCS",
121  ":AspectRatio",
122  ":MovingCursor",
123  ":NextScenes",
124  ":InitiallyActive",
125  ":CHook",
126  ":OrigContent",
127  ":Shared",
128  ":ContentSize",
129  ":CCPriority",
130  "" , // Link condition - always replaced by EventSource, EventType and EventData
131  ":LinkEffect",
132  ":Name",
133  ":InitiallyAvailable",
134  ":ProgramConnectionTag",
135  ":OrigValue",
136  ":ObjectRef",
137  ":ContentRef",
138  ":MovementTable",
139  ":TokenGroupItems",
140  ":NoTokenActionSlots",
141  ":Positions",
142  ":WrapAround",
143  ":MultipleSelection",
144  ":OrigBoxSize",
145  ":OrigPosition",
146  ":OrigPaletteRef",
147  ":Tiling",
148  ":OrigTransparency",
149  ":BBBox",
150  ":OrigLineWidth",
151  ":OrigLineStyle",
152  ":OrigRefLineColour",
153  ":OrigRefFillColour",
154  ":OrigFont",
155  ":HJustification",
156  ":VJustification",
157  ":LineOrientation",
158  ":StartCorner",
159  ":TextWrapping",
160  ":Multiplex",
161  ":Storage",
162  ":Looping",
163  ":Audio",
164  ":Video",
165  ":RTGraphics",
166  ":ComponentTag",
167  ":OrigVolume",
168  ":Termination",
169  ":EngineResp",
170  ":Orientation",
171  ":MaxValue",
172  ":MinValue",
173  ":InitialValue",
174  ":InitialPortion",
175  ":StepSize",
176  ":SliderStyle",
177  ":InputType",
178  ":CharList",
179  ":ObscuredInput",
180  ":MaxLength",
181  ":OrigLabel",
182  ":ButtonStyle",
183  ":Activate",
184  ":Add",
185  ":AddItem",
186  ":Append",
187  ":BringToFront",
188  ":Call",
189  ":CallActionSlot",
190  ":Clear",
191  ":Clone",
192  ":CloseConnection",
193  ":Deactivate",
194  ":DelItem",
195  ":Deselect",
196  ":DeselectItem",
197  ":Divide",
198  ":DrawArc",
199  ":DrawLine",
200  ":DrawOval",
201  ":DrawPolygon",
202  ":DrawPolyline",
203  ":DrawRectangle",
204  ":DrawSector",
205  ":Fork",
206  ":GetAvailabilityStatus",
207  ":GetBoxSize",
208  ":GetCellItem",
209  ":GetCursorPosition",
210  ":GetEngineSupport",
211  ":GetEntryPoint",
212  ":GetFillColour",
213  ":GetFirstItem",
214  ":GetHighlightStatus",
215  ":GetInteractionStatus",
216  ":GetItemStatus",
217  ":GetLabel",
218  ":GetLastAnchorFired",
219  ":GetLineColour",
220  ":GetLineStyle",
221  ":GetLineWidth",
222  ":GetListItem",
223  ":GetListSize",
224  ":GetOverwriteMode",
225  ":GetPortion",
226  ":GetPosition",
227  ":GetRunningStatus",
228  ":GetSelectionStatus",
229  ":GetSliderValue",
230  ":GetTextContent",
231  ":GetTextData",
232  ":GetTokenPosition",
233  ":GetVolume",
234  ":Launch",
235  ":LockScreen",
236  ":Modulo",
237  ":Move",
238  ":MoveTo",
239  ":Multiply",
240  ":OpenConnection",
241  ":Preload",
242  ":PutBefore",
243  ":PutBehind",
244  ":Quit",
245  ":ReadPersistent",
246  ":Run",
247  ":ScaleBitmap",
248  ":ScaleVideo",
249  ":ScrollItems",
250  ":Select",
251  ":SelectItem",
252  ":SendEvent",
253  ":SendToBack",
254  ":SetBoxSize",
255  ":SetCachePriority",
256  ":SetCounterEndPosition",
257  ":SetCounterPosition",
258  ":SetCounterTrigger",
259  ":SetCursorPosition",
260  ":SetCursorShape",
261  ":SetData",
262  ":SetEntryPoint",
263  ":SetFillColour",
264  ":SetFirstItem",
265  ":SetFontRef",
266  ":SetHighlightStatus",
267  ":SetInteractionStatus",
268  ":SetLabel",
269  ":SetLineColour",
270  ":SetLineStyle",
271  ":SetLineWidth",
272  ":SetOverwriteMode",
273  ":SetPaletteRef",
274  ":SetPortion",
275  ":SetPosition",
276  ":SetSliderValue",
277  ":SetSpeed",
278  ":SetTimer",
279  ":SetTransparency",
280  ":SetVariable",
281  ":SetVolume",
282  ":Spawn",
283  ":Step",
284  ":Stop",
285  ":StorePersistent",
286  ":Subtract",
287  ":TestVariable",
288  ":Toggle",
289  ":ToggleItem",
290  ":TransitionTo",
291  ":Unload",
292  ":UnlockScreen",
293  ":GBoolean",
294  ":GInteger",
295  ":GOctetString",
296  ":GObjectRef",
297  ":GContentRef",
298  ":NewColourIndex",
299  ":NewAbsoluteColour",
300  ":NewFontName",
301  ":NewFontRef",
302  ":NewContentSize",
303  ":NewCCPriority",
304  ":IndirectRef",
305  /* UK MHEG */
306  ":SetBackgroundColour",
307  ":SetCellPosition",
308  ":SetInputRegister",
309  ":SetTextColour",
310  ":SetFontAttributes",
311  ":SetVideoDecodeOffset",
312  ":GetVideoDecodeOffset",
313  ":GetFocusPosition",
314  ":SetFocusPosition",
315  ":SetBitmapDecodeOffset",
316  ":GetBitmapDecodeOffset",
317  ":SetSliderParameters",
318  /* Pseudo-operations. These are encoded as LinkCondition in binary. */
319  ":EventSource",
320  ":EventType",
321  ":EventData",
322  ":ActionSlots"
323 };
324 
325 // Some example programs use these colour names
326 static struct
327 {
328  const char *m_name;
329  unsigned char m_r, m_g, m_b, m_t;
330 } colourTable[] =
331 {
332  { "black", 0, 0, 0, 0 },
333  { "transparent", 0, 0, 0, 255 },
334  { "gray"/*sic*/, 128, 128, 128, 0 },
335  { "darkgray"/*sic*/, 192, 192, 192, 0 },
336  { "red", 255, 0, 0, 0 },
337  { "darkred", 128, 0, 0, 0 },
338  { "blue", 0, 0, 255, 0 },
339  { "darkblue", 0, 0, 128, 0 },
340  { "green", 0, 255, 0, 0 },
341  { "darkgreen", 0, 128, 0, 0 },
342  { "yellow", 255, 255, 0, 0 },
343  { "cyan", 0, 255, 255, 0 },
344  { "magenta", 255, 0, 255, 0 }
345 };
346 
347 
348 // Search for a tag and return it if it exists. Returns -1 if it isn't found.
349 static int FindTag(const char *p)
350 {
351  for (int i = 0; i < (int)(sizeof(rchTagNames) / sizeof(rchTagNames[0])); i++)
352  {
353  if (stricmp(p, rchTagNames[i]) == 0)
354  {
355  return i;
356  }
357  }
358 
359  return -1;
360 }
361 
362 
363 // Ditto for the enumerated types
364 #define MAX_ENUM 30
365 
366 void MHParseText::Error(const char *str)
367 {
368  MHERROR(QString("%1- at line %2\n").arg(str).arg(m_lineCount));
369 }
370 
371 // Lexical analysis. Get the next symbol.
373 {
374  while (true)
375  {
376 
377  switch (m_ch)
378  {
379  case '\n':
380  m_lineCount++;
381  [[clang::fallthrough]];
382  case ' ':
383  case '\r':
384  case '\t':
385  case '\f':
386  // Skip white space.
387  GetNextChar();
388  continue;
389 
390  case '/':
391  {
392  // Comment.
393  GetNextChar();
394 
395  if (m_ch != '/')
396  {
397  Error("Malformed comment");
398  }
399 
400  do
401  {
402  GetNextChar();
403  }
404  while (m_ch != '\n' && m_ch != '\f' && m_ch != '\r');
405 
406  continue; // Next symbol
407  }
408 
409  case ':': // Start of a tag
410  {
411  m_nType = PTTag;
412  char buff[MAX_TAG_LENGTH+1];
413  char *p = buff;
414 
415  do
416  {
417  *p++ = m_ch;
418  GetNextChar();
419 
420  if (p == buff + MAX_TAG_LENGTH)
421  {
422  break;
423  }
424  }
425  while ((m_ch >= 'a' && m_ch <= 'z') || (m_ch >= 'A' && m_ch <= 'Z'));
426 
427  *p = 0;
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  {
444  m_nType = PTString;
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  {
487  m_nType = PTString;
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  char buff[MAX_ENUM+1];
702  char *p = buff;
703 
704  do
705  {
706  *p++ = m_ch;
707  GetNextChar();
708 
709  if (p == buff + MAX_ENUM)
710  {
711  break;
712  }
713  }
714  while ((m_ch >= 'a' && m_ch <= 'z') || (m_ch >= 'A' && m_ch <= 'Z') || m_ch == '-');
715 
716  *p = '\0';
717 
718  if (stricmp(buff, "NULL") == 0)
719  {
720  m_nType = PTNull;
721  return;
722  }
723 
724  if (stricmp(buff, "true") == 0)
725  {
726  m_nType = PTBool;
727  m_fBool = true;
728  return;
729  }
730 
731  if (stricmp(buff, "false") == 0)
732  {
733  m_nType = PTBool;
734  m_fBool = false;
735  return;
736  }
737 
738  // Look up the tag in all the tables. Fortunately all the enumerations
739  // are distinct so we don't need to know the context.
741 
742  if (m_nInt > 0)
743  {
744  return;
745  }
746 
748 
749  if (m_nInt > 0)
750  {
751  return;
752  }
753 
755 
756  if (m_nInt > 0)
757  {
758  return;
759  }
760 
762 
763  if (m_nInt > 0)
764  {
765  return;
766  }
767 
769 
770  if (m_nInt > 0)
771  {
772  return;
773  }
774 
775  m_nInt = MHSlider::GetStyle(buff);
776 
777  if (m_nInt > 0)
778  {
779  return;
780  }
781 
782  // Check the colour table. If it's there generate a string containing the colour info.
783  for (int i = 0; i < (int)(sizeof(colourTable) / sizeof(colourTable[0])); i++)
784  {
785  if (stricmp(buff, colourTable[i].m_name) == 0)
786  {
787  m_nType = PTString;
788  auto *str = (unsigned char *)realloc(m_String, 4 + 1);
789 
790  if (str == nullptr)
791  {
792  Error("Insufficient memory");
793  }
794 
795  m_String = str;
796  m_String[0] = colourTable[i].m_r;
797  m_String[1] = colourTable[i].m_g;
798  m_String[2] = colourTable[i].m_b;
799  m_String[3] = colourTable[i].m_t;
800  m_nStringLength = 4;
802  return;
803  }
804  }
805 
806  Error("Unrecognised enumeration");
807  break;
808  }
809 
810  case '{': // Start of a "section".
811  // The standard indicates that open brace followed by a tag should be written
812  // as a single word. We'll be more lenient and allow spaces or comments between them.
814  GetNextChar();
815  return;
816 
817  case '}': // End of a "section".
819  GetNextChar();
820  return;
821 
822  case '(': // Start of a sequence.
824  GetNextChar();
825  return;
826 
827  case ')': // End of a sequence.
828  m_nType = PTEndSeq;
829  GetNextChar();
830  return;
831 
832  case EOF:
833  m_nType = PTEOF;
834  return;
835 
836  default:
837  Error("Unknown character");
838  GetNextChar();
839  }
840  }
841 }
842 
844 {
845  MHParseNode *pRes = nullptr;
846 
847  try
848  {
849  switch (m_nType)
850  {
851  case PTStartSection: // Open curly bracket
852  {
853  NextSym();
854 
855  // Should be followed by a tag.
856  if (m_nType != PTTag)
857  {
858  Error("Expected ':' after '{'");
859  }
860 
861  auto *pTag = new MHPTagged(m_nTag);
862  pRes = pTag;
863  NextSym();
864 
865  while (m_nType != PTEndSection)
866  {
867  pTag->AddArg(DoParse());
868  }
869 
870  NextSym(); // Remove the close curly bracket.
871  break;
872  }
873 
874  case PTTag: // Tag on its own.
875  {
876  int nTag = m_nTag;
877  auto *pTag = new MHPTagged(nTag);
878  pRes = pTag;
879  NextSym();
880 
881  switch (nTag)
882  {
883  case C_ITEMS:
884  case C_LINK_EFFECT:
885  case C_ACTIVATE:
886  case C_ADD:
887  case C_ADD_ITEM:
888  case C_APPEND:
889  case C_BRING_TO_FRONT:
890  case C_CALL:
891  case C_CALL_ACTION_SLOT:
892  case C_CLEAR:
893  case C_CLONE:
894  case C_CLOSE_CONNECTION:
895  case C_DEACTIVATE:
896  case C_DEL_ITEM:
897  case C_DESELECT:
898  case C_DESELECT_ITEM:
899  case C_DIVIDE:
900  case C_DRAW_ARC:
901  case C_DRAW_LINE:
902  case C_DRAW_OVAL:
903  case C_DRAW_POLYGON:
904  case C_DRAW_POLYLINE:
905  case C_DRAW_RECTANGLE:
906  case C_DRAW_SECTOR:
907  case C_FORK:
909  case C_GET_BOX_SIZE:
910  case C_GET_CELL_ITEM:
913  case C_GET_ENTRY_POINT:
914  case C_GET_FILL_COLOUR:
915  case C_GET_FIRST_ITEM:
918  case C_GET_ITEM_STATUS:
919  case C_GET_LABEL:
921  case C_GET_LINE_COLOUR:
922  case C_GET_LINE_STYLE:
923  case C_GET_LINE_WIDTH:
924  case C_GET_LIST_ITEM:
925  case C_GET_LIST_SIZE:
927  case C_GET_PORTION:
928  case C_GET_POSITION:
931  case C_GET_SLIDER_VALUE:
932  case C_GET_TEXT_CONTENT:
933  case C_GET_TEXT_DATA:
935  case C_GET_VOLUME:
936  case C_LAUNCH:
937  case C_LOCK_SCREEN:
938  case C_MODULO:
939  case C_MOVE:
940  case C_MOVE_TO:
941  case C_MULTIPLY:
942  case C_OPEN_CONNECTION:
943  case C_PRELOAD:
944  case C_PUT_BEFORE:
945  case C_PUT_BEHIND:
946  case C_QUIT:
947  case C_READ_PERSISTENT:
948  case C_RUN:
949  case C_SCALE_BITMAP:
950  case C_SCALE_VIDEO:
951  case C_SCROLL_ITEMS:
952  case C_SELECT:
953  case C_SELECT_ITEM:
954  case C_SEND_EVENT:
955  case C_SEND_TO_BACK:
956  case C_SET_BOX_SIZE:
962  case C_SET_CURSOR_SHAPE:
963  case C_SET_DATA:
964  case C_SET_ENTRY_POINT:
965  case C_SET_FILL_COLOUR:
966  case C_SET_FIRST_ITEM:
967  case C_SET_FONT_REF:
970  case C_SET_LABEL:
971  case C_SET_LINE_COLOUR:
972  case C_SET_LINE_STYLE:
973  case C_SET_LINE_WIDTH:
975  case C_SET_PALETTE_REF:
976  case C_SET_PORTION:
977  case C_SET_POSITION:
978  case C_SET_SLIDER_VALUE:
979  case C_SET_SPEED:
980  case C_SET_TIMER:
981  case C_SET_TRANSPARENCY:
982  case C_SET_VARIABLE:
983  case C_SET_VOLUME:
984  case C_SPAWN:
985  case C_STEP:
986  case C_STOP:
987  case C_STORE_PERSISTENT:
988  case C_SUBTRACT:
989  case C_TEST_VARIABLE:
990  case C_TOGGLE:
991  case C_TOGGLE_ITEM:
992  case C_TRANSITION_TO:
993  case C_UNLOAD:
994  case C_UNLOCK_SCREEN:
995  case C_CONTENT_REFERENCE:
996  case C_TOKEN_GROUP_ITEMS:
997  case C_POSITIONS:
998  case C_MULTIPLEX:
999  {
1000  // These are parenthesised in the text form. We have to remove the
1001  // parentheses otherwise we will return a sequence which will not be
1002  // be compatible with the binary form.
1003  if (m_nType != PTStartSeq)
1004  {
1005  Error("Expected '('");
1006  }
1007 
1008  NextSym();
1009 
1010  while (m_nType != PTEndSeq)
1011  {
1012  pTag->AddArg(DoParse());
1013  }
1014 
1015  NextSym(); // Remove the close parenthesis.
1016  break;
1017  }
1018  case C_ORIGINAL_CONTENT:
1019  case C_NEW_GENERIC_BOOLEAN:
1020  case C_NEW_GENERIC_INTEGER:
1024  case C_ORIGINAL_VALUE:
1025  // These always have an argument which may be a tagged item.
1026  {
1027  // Is it always the case that there is at least one argument so if we haven't
1028  // had any arguments yet we should always process a tag as an argument?
1029  pTag->AddArg(DoParse());
1030  break;
1031  }
1032  default:
1033 
1034  // This can be followed by an int, etc but a new tag is dealt with by the caller.
1035  while (m_nType == PTBool || m_nType == PTInt || m_nType == PTString || m_nType == PTEnum || m_nType == PTStartSeq)
1036  {
1037  pTag->AddArg(DoParse());
1038  }
1039 
1040  }
1041 
1042  break;
1043  }
1044 
1045  case PTInt:
1046  {
1047  pRes = new MHPInt(m_nInt);
1048  NextSym();
1049  break;
1050  }
1051 
1052  case PTBool:
1053  {
1054  pRes = new MHPBool(m_fBool);
1055  NextSym();
1056  break;
1057  }
1058 
1059  case PTString:
1060  {
1061  MHOctetString str;
1062  str.Copy(MHOctetString((const char *)m_String, m_nStringLength));
1063  pRes = new MHPString(str);
1064  NextSym();
1065  break;
1066  }
1067 
1068  case PTEnum:
1069  {
1070  pRes = new MHPEnum(m_nInt);
1071  NextSym();
1072  break;
1073  }
1074 
1075  case PTNull:
1076  {
1077  pRes = new MHPNull;
1078  NextSym();
1079  break;
1080  }
1081 
1082  case PTStartSeq: // Open parenthesis.
1083  {
1084  auto *pSeq = new MHParseSequence;
1085  pRes = pSeq;
1086  NextSym();
1087 
1088  while (m_nType != PTEndSeq)
1089  {
1090  pSeq->Append(DoParse());
1091  }
1092 
1093  NextSym(); // Remove the close parenthesis.
1094  break;
1095  }
1096 
1097  default:
1098  Error("Unexpected symbol");
1099  }
1100 
1101  return pRes;
1102  }
1103  catch (...)
1104  {
1105  delete(pRes);
1106  throw;
1107  }
1108 }
1109 
1110 
1111 // Run the parser
1113 {
1114  GetNextChar(); // Initialise m_ch
1115  NextSym(); // Initialise the symbol values.
1116  return DoParse();
1117 }
1118 
unsigned char m_t
Definition: ParseText.cpp:329
#define C_BRING_TO_FRONT
Definition: ASN1Codes.h:152
#define C_GET_ENGINE_SUPPORT
Definition: ASN1Codes.h:175
unsigned int m_p
Definition: ParseText.h:61
ParseTextType m_nType
Definition: ParseText.h:52
#define C_APPEND
Definition: ASN1Codes.h:151
unsigned char m_b
Definition: ParseText.cpp:329
MHParseNode * Parse() override
Definition: ParseText.cpp:1112
#define C_DRAW_ARC
Definition: ASN1Codes.h:163
#define C_SCALE_VIDEO
Definition: ASN1Codes.h:213
#define C_GET_RUNNING_STATUS
Definition: ASN1Codes.h:192
#define MHERROR(__text)
Definition: Logging.h:42
#define C_SET_OVERWRITE_MODE
Definition: ASN1Codes.h:237
#define C_SET_INTERACTION_STATUS
Definition: ASN1Codes.h:232
static int GetStyle(const char *str)
Definition: Visible.cpp:712
#define C_ORIGINAL_CONTENT
Definition: ASN1Codes.h:91
#define C_DEACTIVATE
Definition: ASN1Codes.h:158
#define C_LOCK_SCREEN
Definition: ASN1Codes.h:200
#define C_GET_OVERWRITE_MODE
Definition: ASN1Codes.h:189
#define C_DRAW_SECTOR
Definition: ASN1Codes.h:169
#define C_GET_LAST_ANCHOR_FIRED
Definition: ASN1Codes.h:183
#define C_NEW_GENERIC_OCTETSTRING
Definition: ASN1Codes.h:260
#define C_SET_TRANSPARENCY
Definition: ASN1Codes.h:244
#define C_CLEAR
Definition: ASN1Codes.h:155
#define C_SET_VARIABLE
Definition: ASN1Codes.h:245
#define C_SET_FILL_COLOUR
Definition: ASN1Codes.h:228
#define C_GET_SLIDER_VALUE
Definition: ASN1Codes.h:194
#define C_GET_PORTION
Definition: ASN1Codes.h:190
#define C_SET_COUNTER_END_POSITION
Definition: ASN1Codes.h:221
#define C_SET_BOX_SIZE
Definition: ASN1Codes.h:219
#define C_GET_VOLUME
Definition: ASN1Codes.h:198
#define C_STOP
Definition: ASN1Codes.h:249
#define C_GET_FIRST_ITEM
Definition: ASN1Codes.h:178
#define C_TOGGLE_ITEM
Definition: ASN1Codes.h:254
int m_nInt
Definition: ParseText.h:56
#define C_DRAW_POLYLINE
Definition: ASN1Codes.h:167
#define C_GET_LINE_COLOUR
Definition: ASN1Codes.h:184
#define C_ITEMS
Definition: ASN1Codes.h:41
int m_lineCount
Definition: ParseText.h:47
void GetNextChar()
Definition: ParseText.cpp:51
#define C_NEW_GENERIC_CONTENT_REF
Definition: ASN1Codes.h:262
#define C_ADD_ITEM
Definition: ASN1Codes.h:150
#define C_CLOSE_CONNECTION
Definition: ASN1Codes.h:157
#define MAX_TAG_LENGTH
Definition: ParseText.cpp:64
#define C_GET_FILL_COLOUR
Definition: ASN1Codes.h:177
#define C_SET_POSITION
Definition: ASN1Codes.h:240
static int GetOrientation(const char *str)
Definition: Visible.cpp:692
#define C_TOGGLE
Definition: ASN1Codes.h:253
#define C_SELECT_ITEM
Definition: ASN1Codes.h:216
#define C_GET_LINE_STYLE
Definition: ASN1Codes.h:185
#define C_GET_LINE_WIDTH
Definition: ASN1Codes.h:186
void Error(const char *str)
Definition: ParseText.cpp:366
#define C_SET_LABEL
Definition: ASN1Codes.h:233
#define C_GET_CELL_ITEM
Definition: ASN1Codes.h:173
#define C_DRAW_LINE
Definition: ASN1Codes.h:164
#define C_SET_PALETTE_REF
Definition: ASN1Codes.h:238
#define C_FORK
Definition: ASN1Codes.h:170
#define C_SET_FONT_REF
Definition: ASN1Codes.h:230
virtual ~MHParseText()
Definition: ParseText.cpp:45
static int GetLineOrientation(const char *str)
Definition: Text.cpp:169
unsigned char m_r
Definition: ParseText.cpp:329
#define C_SET_TIMER
Definition: ASN1Codes.h:243
MHParseNode * DoParse()
Definition: ParseText.cpp:843
#define C_CLONE
Definition: ASN1Codes.h:156
#define C_SET_CURSOR_POSITION
Definition: ASN1Codes.h:224
#define C_SET_DATA
Definition: ASN1Codes.h:226
void Copy(const MHOctetString &str)
#define C_NEW_GENERIC_OBJECT_REF
Definition: ASN1Codes.h:261
#define C_GET_ENTRY_POINT
Definition: ASN1Codes.h:176
#define C_CONTENT_REFERENCE
Definition: ASN1Codes.h:102
#define C_QUIT
Definition: ASN1Codes.h:209
#define C_SEND_EVENT
Definition: ASN1Codes.h:217
#define C_DRAW_POLYGON
Definition: ASN1Codes.h:166
#define C_SET_PORTION
Definition: ASN1Codes.h:239
#define C_ADD
Definition: ASN1Codes.h:149
#define C_SET_LINE_WIDTH
Definition: ASN1Codes.h:236
#define C_DRAW_RECTANGLE
Definition: ASN1Codes.h:168
#define C_DRAW_OVAL
Definition: ASN1Codes.h:165
#define C_TRANSITION_TO
Definition: ASN1Codes.h:255
#define C_GET_HIGHLIGHT_STATUS
Definition: ASN1Codes.h:179
#define C_MULTIPLY
Definition: ASN1Codes.h:204
#define C_STEP
Definition: ASN1Codes.h:248
#define C_GET_BOX_SIZE
Definition: ASN1Codes.h:172
static int GetStartCorner(const char *str)
Definition: Text.cpp:190
#define C_SET_COUNTER_TRIGGER
Definition: ASN1Codes.h:223
#define C_SCROLL_ITEMS
Definition: ASN1Codes.h:214
#define C_MULTIPLEX
Definition: ASN1Codes.h:125
#define C_SET_CURSOR_SHAPE
Definition: ASN1Codes.h:225
#define C_GET_TOKEN_POSITION
Definition: ASN1Codes.h:197
#define C_GET_INTERACTION_STATUS
Definition: ASN1Codes.h:180
#define C_ACTIVATE
Definition: ASN1Codes.h:148
#define C_GET_AVAILABILITY_STATUS
Definition: ASN1Codes.h:171
unsigned char m_g
Definition: ParseText.cpp:329
#define C_CALL
Definition: ASN1Codes.h:153
QByteArray m_data
Definition: ParseText.h:62
const char * rchTagNames[]
Definition: ParseText.cpp:66
const char * m_name
Definition: ParseText.cpp:328
#define C_RUN
Definition: ASN1Codes.h:211
#define C_TEST_VARIABLE
Definition: ASN1Codes.h:252
static int GetJustification(const char *str)
Definition: Text.cpp:150
#define C_SUBTRACT
Definition: ASN1Codes.h:251
#define C_MOVE
Definition: ASN1Codes.h:202
#define C_DIVIDE
Definition: ASN1Codes.h:162
#define C_SET_LINE_STYLE
Definition: ASN1Codes.h:235
#define C_GET_CURSOR_POSITION
Definition: ASN1Codes.h:174
void NextSym()
Definition: ParseText.cpp:372
#define C_SET_LINE_COLOUR
Definition: ASN1Codes.h:234
#define C_PRELOAD
Definition: ASN1Codes.h:206
#define stricmp
Definition: ParseText.cpp:41
#define C_GET_LIST_SIZE
Definition: ASN1Codes.h:188
#define C_SET_SLIDER_VALUE
Definition: ASN1Codes.h:241
#define C_GET_ITEM_STATUS
Definition: ASN1Codes.h:181
#define C_ORIGINAL_VALUE
Definition: ASN1Codes.h:100
#define C_PUT_BEHIND
Definition: ASN1Codes.h:208
unsigned char * m_String
Definition: ParseText.h:58
#define C_SPAWN
Definition: ASN1Codes.h:247
#define C_SET_FIRST_ITEM
Definition: ASN1Codes.h:229
#define C_LAUNCH
Definition: ASN1Codes.h:199
#define MAX_ENUM
Definition: ParseText.cpp:364
#define C_UNLOCK_SCREEN
Definition: ASN1Codes.h:257
#define C_GET_TEXT_DATA
Definition: ASN1Codes.h:196
#define C_SET_SPEED
Definition: ASN1Codes.h:242
#define C_NEW_GENERIC_BOOLEAN
Definition: ASN1Codes.h:258
#define C_LINK_EFFECT
Definition: ASN1Codes.h:96
#define C_TOKEN_GROUP_ITEMS
Definition: ASN1Codes.h:104
#define C_READ_PERSISTENT
Definition: ASN1Codes.h:210
#define C_SET_CACHE_PRIORITY
Definition: ASN1Codes.h:220
#define C_PUT_BEFORE
Definition: ASN1Codes.h:207
#define C_GET_TEXT_CONTENT
Definition: ASN1Codes.h:195
#define C_MODULO
Definition: ASN1Codes.h:201
int m_nStringLength
Definition: ParseText.h:59
#define C_SCALE_BITMAP
Definition: ASN1Codes.h:212
#define C_DEL_ITEM
Definition: ASN1Codes.h:159
#define C_DESELECT_ITEM
Definition: ASN1Codes.h:161
#define C_SEND_TO_BACK
Definition: ASN1Codes.h:218
#define C_CALL_ACTION_SLOT
Definition: ASN1Codes.h:154
int m_nTag
Definition: ParseText.h:55
#define C_GET_POSITION
Definition: ASN1Codes.h:191
#define C_SELECT
Definition: ASN1Codes.h:215
static struct @11 colourTable[]
bool m_fBool
Definition: ParseText.h:57
static int FindTag(const char *p)
Definition: ParseText.cpp:349
#define C_SET_COUNTER_POSITION
Definition: ASN1Codes.h:222
#define C_STORE_PERSISTENT
Definition: ASN1Codes.h:250
#define C_NEW_GENERIC_INTEGER
Definition: ASN1Codes.h:259
#define C_SET_VOLUME
Definition: ASN1Codes.h:246
#define C_SET_ENTRY_POINT
Definition: ASN1Codes.h:227
#define C_GET_LIST_ITEM
Definition: ASN1Codes.h:187
#define C_OPEN_CONNECTION
Definition: ASN1Codes.h:205
#define C_SET_HIGHLIGHT_STATUS
Definition: ASN1Codes.h:231
#define C_DESELECT
Definition: ASN1Codes.h:160
#define C_POSITIONS
Definition: ASN1Codes.h:106
#define C_GET_SELECTION_STATUS
Definition: ASN1Codes.h:193
#define C_GET_LABEL
Definition: ASN1Codes.h:182
#define C_MOVE_TO
Definition: ASN1Codes.h:203
#define C_UNLOAD
Definition: ASN1Codes.h:256