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