home *** CD-ROM | disk | FTP | other *** search
/ PSION CD 2 / PsionCDVol2.iso / Programs / 720 / PDF090B4-SorceCode / pdf / Lexer.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-30  |  10.2 KB  |  494 lines

  1. //========================================================================
  2. //
  3. // Lexer.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8. //
  9. // Ported to EPOC by Sander van der Wal
  10. //
  11. // $Log: Lexer.cpp $
  12. // Revision 1.3  2000-09-21 14:45:15+02  svdwal
  13. // Xpdf 0.91 bugfix added
  14. //
  15. // Revision 1.2  2000-09-17 13:38:23+02  svdwal
  16. // Ported
  17. //
  18.  
  19. #ifdef __GNUC__
  20. #pragma implementation
  21. #endif
  22.  
  23. #ifndef __E32DEF_H__
  24. #include <e32def.h> // remove warning about NULL redefinition
  25. #endif
  26.  
  27. #include <ctype.h>
  28.  
  29. #include "Lexer.h"
  30. #include "Error.h"
  31.  
  32. #include "Pdf.rsg"
  33. #include "PROFILE.h"
  34.  
  35. //------------------------------------------------------------------------
  36.  
  37. // A '1' in this array means the corresponding character ends a name
  38. // or command.
  39. static const char endOfNameChars[128] = {
  40.   0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,   // 0x
  41.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 1x
  42.   1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1,   // 2x
  43.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,   // 3x
  44.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 4x
  45.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0,   // 5x
  46.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   // 6x
  47.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0    // 7x
  48. };
  49.  
  50. //------------------------------------------------------------------------
  51. // Lexer
  52. //------------------------------------------------------------------------
  53. Lexer::Lexer(Stream* str)
  54. {
  55.   curStr.initStream(str);
  56. }
  57.  
  58. void Lexer::ConstructL() {
  59.   RAutoObject obj;
  60.  
  61.   freeArray = gTrue;
  62.   streams = new(ELeave) Array();
  63.   streams->addL(curStr.copyL(&obj));
  64.   obj.initNull();
  65.   strPtr = 0;
  66.  
  67.   curStr.streamReset();
  68. }
  69.  
  70. Lexer::Lexer() {}
  71.  
  72. void Lexer::ConstructL(Object *obj) {
  73.  
  74.   if (obj->isStream()) {
  75.     RAutoObject obj2;
  76.     freeArray = gTrue;
  77.     streams = new(ELeave) Array();
  78.     streams->addL(obj->copyL(&obj2));
  79.     obj2.initNull();
  80.   } else {
  81.     streams = obj->getArray();
  82.     freeArray = gFalse;
  83.   }
  84.   strPtr = 0;
  85.   if (streams->getLength() > 0) {
  86.     streams->getL(strPtr, &curStr);
  87.     curStr.streamReset();
  88.   }
  89. }
  90.  
  91. Lexer::~Lexer() {
  92.   if (!curStr.isNone())
  93.     curStr.free();
  94.   if (freeArray)
  95.     delete streams;
  96. }
  97.  
  98. int Lexer::getChar() {
  99.   register int c;
  100.  
  101.   c = curStr.isNone() ? EOF : curStr.streamGetChar();
  102.   if (c != EOF) 
  103.     return c;
  104.   while (!curStr.isNone() && (c == EOF)) {
  105.     curStr.free();
  106.     ++strPtr;
  107.     if (strPtr < streams->getLength()) {
  108.       streams->getL(strPtr, &curStr);
  109.       curStr.streamReset();
  110.       c = curStr.streamGetChar();
  111.     }
  112.   }
  113.   return c;
  114. }
  115.  
  116. int Lexer::lookChar() {
  117.   register int c;
  118.  
  119.   c = curStr.isNone() ? EOF : curStr.streamLookChar();
  120.   if (c != EOF) 
  121.     return c;
  122.   while (!curStr.isNone() && (c == EOF)) {
  123.     curStr.free();
  124.     ++strPtr;
  125.     if (strPtr < streams->getLength()) {
  126.       streams->getL(strPtr, &curStr);
  127.       curStr.streamReset();
  128.       c = curStr.streamLookChar();
  129.     }
  130.   }
  131.   return c;
  132. }
  133.  
  134. Object *Lexer::getObjL(Object *obj) {
  135.  
  136.   PROFILE_START(LEXER__GETOBJ);
  137.  
  138.   register char *p;
  139.   register int c;
  140.   GBool comment, done;
  141.   int numParen;
  142.   register GString *s;
  143.   int n; //, m;
  144.  
  145.   // skip whitespace and comments
  146.   comment = gFalse;
  147.   for(;;) {
  148.     if ((c = getChar()) == EOF)
  149.       return obj->initEOF();
  150.     if (comment) {
  151.       if (c == '\r' || c == '\n')
  152.     comment = gFalse;
  153.     } else if (c == '%') {
  154.       comment = gTrue;
  155.     } else if (!isspace(c)) {
  156.       break;
  157.     }
  158.   }
  159.  
  160.   // start reading token
  161.   switch (c) {
  162.  
  163.   // number
  164.   case '0': case '1': case '2': case '3': case '4':
  165.   case '5': case '6': case '7': case '8': case '9':
  166.   case '-': case '.': 
  167.     {
  168.       GBool neg = gFalse;
  169.       register int xi = 0;
  170.       if (c == '-') {
  171.         neg = gTrue;
  172.       } else if (c == '.') {
  173.         goto doReal;
  174.       } else {
  175.         xi = c - '0';
  176.       }
  177.       for(;;) {
  178.         c = lookChar();
  179.         if (isdigit(c)) {
  180.           getChar();
  181.       xi = xi * 10 + (c - '0');
  182.         } else if (c == '.') {
  183.       getChar();
  184.       goto doReal;
  185.         } else {
  186.       break;
  187.         }
  188.       }
  189.       if (neg)
  190.         xi = -xi;
  191.       obj->initInt(xi);
  192.       break;
  193.     doReal:
  194.       register int scale = 1;
  195.       for(;;) {
  196.         c = lookChar();
  197.         if (!isdigit(c))
  198.       break;
  199.         getChar();
  200.         xi = 10 * xi + (c - '0');
  201.         scale *= 10;
  202.       }
  203.       if (neg)
  204.         xi = -xi;
  205.       obj->initReal(double(xi)/scale);
  206.     }
  207.     break;
  208.  
  209.   // string
  210.   case '(':
  211.     p = tokBuf;
  212.     n = 0;
  213.     numParen = 1;
  214.     done = gFalse;
  215.     s = NULL;
  216.     do {
  217.       register int c2 = EOF;
  218.       switch (c = getChar()) {
  219.  
  220.       case EOF:
  221. #if 0 // This breaks some PDF files, e.g., ones from Photoshop.
  222.       case '\r':
  223.       case '\n':
  224. #endif
  225.     error(getPos(), R_UNTERMINATED_STRING);
  226.     done = gTrue;
  227.     break;
  228.  
  229.       case '(':
  230.     ++numParen;
  231.     break;
  232.  
  233.       case ')':
  234.     if (--numParen == 0)
  235.       done = gTrue;
  236.     break;
  237.  
  238.       case '\\':
  239.     switch (c = getChar()) {
  240.     case 'n':
  241.       c2 = '\n';
  242.       break;
  243.     case 'r':
  244.       c2 = '\r';
  245.       break;
  246.     case 't':
  247.       c2 = '\t';
  248.       break;
  249.     case 'b':
  250.       c2 = '\b';
  251.       break;
  252.     case 'f':
  253.       c2 = '\f';
  254.       break;
  255.     case '\\':
  256.     case '(':
  257.     case ')':
  258.       c2 = c;
  259.       break;
  260.     case '0': case '1': case '2': case '3':
  261.     case '4': case '5': case '6': case '7':
  262.       c2 = c - '0';
  263.       c = lookChar();
  264.       if (c >= '0' && c <= '7') {
  265.         getChar();
  266.         c2 = (c2 << 3) + (c - '0');
  267.         c = lookChar();
  268.         if (c >= '0' && c <= '7') {
  269.           getChar();
  270.           c2 = (c2 << 3) + (c - '0');
  271.         }
  272.       }
  273.       break;
  274.     case '\r':
  275.       c = lookChar();
  276.       if (c == '\n')
  277.         getChar();
  278.       break;
  279.     case '\n':
  280.       break;
  281.     case EOF:
  282.       error(getPos(), R_UNTERMINATED_STRING);
  283.       done = gTrue;
  284.       break;
  285.     default:
  286.       c2 = c;
  287.       break;
  288.     }
  289.     break;
  290.  
  291.       default:
  292.     c2 = c;
  293.     break;
  294.       }
  295.  
  296.       if (c2 != EOF) {
  297.     if (n == tokBufSize) {
  298.       if (!s)
  299.             s = GString::NewLC(tokBuf, tokBufSize);
  300.       else
  301.         s->appendL(tokBuf, tokBufSize);
  302.       p = tokBuf;
  303.       n = 0;
  304.     }
  305.     *p++ = (char)c2;
  306.     ++n;
  307.       }
  308.     } while (!done);
  309.     if (!s)
  310.       s = GString::NewLC(tokBuf, n);
  311.     else
  312.       s->appendL(tokBuf, n);
  313.     CleanupStack::Pop(); // s
  314.     obj->initString(s);
  315.     break;
  316.  
  317.   // name
  318.   case '/':
  319.     p = tokBuf;
  320.     n = 0;
  321.     while ((c = lookChar()) != EOF && !(c < 128 && endOfNameChars[c])) {
  322.       getChar();
  323.       if (c == '#') {
  324.     register int c2 = lookChar();
  325.     if (c2 >= '0' && c2 <= '9')
  326.       c = c2 - '0';
  327.     else if (c2 >= 'A' && c2 <= 'F')
  328.       c = c2 - 'A' + 10;
  329.     else if (c2 >= 'a' && c2 <= 'f')
  330.       c = c2 - 'a' + 10;
  331.     else
  332.       goto notEscChar;
  333.     getChar();
  334.     c <<= 4;
  335.     c2 = getChar();
  336.     if (c2 >= '0' && c2 <= '9')
  337.       c += c2 - '0';
  338.     else if (c2 >= 'A' && c2 <= 'F')
  339.       c += c2 - 'A' + 10;
  340.     else if (c2 >= 'a' && c2 <= 'f')
  341.       c += c2 - 'a' + 10;
  342.     else
  343.       error(getPos(), R_ILLEGAL_DIGIT_IN_HEX_CHAR_IN_NAME);
  344.       }
  345.      notEscChar:
  346.       if (++n == tokBufSize) {
  347.     error(getPos(), R_NAME_TOKEN_TOO_LONG);
  348.     break;
  349.       }
  350.       *p++ = (char)c;
  351.     }
  352.     *p = '\0';
  353.     obj->initNameL(tokBuf);
  354.     break;
  355.  
  356.   // array punctuation
  357.   case '[':
  358.   case ']':
  359.     tokBuf[0] = (char)c;
  360.     tokBuf[1] = '\0';
  361.     obj->initCmdL(tokBuf);
  362.     break;
  363.  
  364.   // hex string or dict punctuation
  365.   case '<':
  366.     c = lookChar();
  367.  
  368.     // dict punctuation
  369.     if (c == '<') {
  370.       getChar();
  371.       tokBuf[0] = tokBuf[1] = '<';
  372.       tokBuf[2] = '\0';
  373.       obj->initCmdL(tokBuf);
  374.  
  375.     // hex string
  376.     } else {
  377.       obj->initNull();
  378.       p = tokBuf;
  379.       int m = n = 0;
  380.       register int c2 = 0;
  381.       s = NULL;
  382.       for(;;) {
  383.         c = getChar();
  384.         if (c == '>') {
  385.           break;
  386.         } 
  387.         else if (c == EOF) {
  388.           error(getPos(), R_UNTERMINATED_HEX_STRING);
  389.           break;
  390.         } 
  391.         else if (!isspace(c)) {
  392.           c2 = c2 << 4;
  393.           if (c >= '0' && c <= '9')
  394.             c2 += c - '0';
  395.           else if (c >= 'A' && c <= 'F')
  396.             c2 += c - 'A' + 10;
  397.           else if (c >= 'a' && c <= 'f')
  398.             c2 += c - 'a' + 10;
  399.           else
  400.             error(getPos(), R_ILLEGAL_CHARACTER___02X__IN_HEX_STRING, c);
  401.           if (++m == 2) {
  402.             if (n == tokBufSize) {
  403.               if (!s)
  404.                 s = GString::NewLC(tokBuf, tokBufSize);
  405.               else
  406.                 s->appendL(tokBuf, tokBufSize);
  407.               p = tokBuf;
  408.               n = 0;
  409.             }
  410.             *p++ = (char)c2;
  411.             ++n;
  412.             c2 = 0;
  413.             m = 0;
  414.           }
  415.         }
  416.       }
  417.       if (!s)
  418.         s = GString::NewLC(tokBuf, n);
  419.       else
  420.         s->appendL(tokBuf, n);
  421.       if (m == 1)
  422.         s->appendL((char)(c2 << 4));
  423.       CleanupStack::Pop(); // s
  424.       obj->initString(s);
  425.     }
  426.     break;
  427.  
  428.   // dict punctuation
  429.   case '>':
  430.     c = lookChar();
  431.     if (c == '>') {
  432.       getChar();
  433.       tokBuf[0] = tokBuf[1] = '>';
  434.       tokBuf[2] = '\0';
  435.       obj->initCmdL(tokBuf);
  436.     } else {
  437.       error(getPos(), R_ILLEGAL_CHARACTER___C_, '>');
  438.       obj->initError();
  439.     }
  440.     break;
  441.  
  442.   // error
  443.   case ')':
  444.   case '{':
  445.   case '}':
  446.     error(getPos(), R_ILLEGAL_CHARACTER___C_, c);
  447.     obj->initError();
  448.     break;
  449.  
  450.   // command
  451.   default:
  452.     p = tokBuf;
  453.     *p++ = (char)c;
  454.     n = 1;
  455.     while ((c = lookChar()) != EOF && !(c < 128 && endOfNameChars[c])) {
  456.       getChar();
  457.       if (++n == tokBufSize) {
  458.     error(getPos(), R_COMMAND_TOKEN_TOO_LONG);
  459.     break;
  460.       }
  461.       *p++ = (char)c;
  462.     }
  463.     *p = '\0';
  464.     if (tokBuf[0] == 't' && !strcmp(tokBuf, "true"))
  465.       obj->initBool(gTrue);
  466.     else if (tokBuf[0] == 'f' && !strcmp(tokBuf, "false"))
  467.       obj->initBool(gFalse);
  468.     else if (tokBuf[0] == 'n' && !strcmp(tokBuf, "null"))
  469.       obj->initNull();
  470.     else
  471.       obj->initCmdL(tokBuf);
  472.     break;
  473.   }
  474.  
  475.   PROFILE_STOP(LEXER__GETOBJ);
  476.  
  477.   return obj;
  478. }
  479.  
  480. void Lexer::skipToNextLine() {
  481.   int c;
  482.  
  483.   for(;;) {
  484.     c = getChar();
  485.     if (c == EOF || c == '\n')
  486.       return;
  487.     if (c == '\r') {
  488.       if ((c = lookChar()) == '\n')
  489.     getChar();
  490.       return;
  491.     }
  492.   }
  493. }
  494.