home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Asuka / source / filecreator.cpp next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  37.3 KB  |  1,635 lines

  1. //    VDCompiler - Custom shader video filter for VirtualDub
  2. //    Copyright (C) 2007 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include "stdafx.h"
  19. #include <math.h>
  20. #include <vd2/system/vdstl.h>
  21. #include <vd2/system/file.h>
  22. #include <vd2/system/text.h>
  23. #include <vd2/system/VDString.h>
  24. #include <vd2/system/binary.h>
  25. #include "filecreator.h"
  26.  
  27. using namespace nsVDCompilerTokens;
  28.  
  29. namespace {
  30.     uint32 Checksum(const char *s, int len) {
  31.         uint32 sum = 0;
  32.  
  33.         while(len--)
  34.             sum += *s++;
  35.  
  36.         return sum;
  37.     }
  38. }
  39.  
  40. void VDCompilerWriteLogOutputF(IVDCompilerLogOutput& out, const char *format ...) {
  41.     char buf[3072];
  42.     va_list val;
  43.  
  44.     va_start(val, format);
  45.     int len = _vsnprintf(buf, 3071, format, val);
  46.     va_end(val);
  47.  
  48.     if ((unsigned)len <= 3071) {
  49.         buf[len] = 0;
  50.         out.WriteLogOutput(buf);
  51.     }
  52. }
  53.  
  54. void VDCompilerLexer::Init(const char *src, size_t len, const char *context, IVDCompilerLogOutput *pOutput) {
  55.     mpSrc = src;
  56.     mpSrcEnd = src + len;
  57.     mpSrcLineStart = src;
  58.     mpToken = src;
  59.     mpTokenLineStart = src;
  60.     mpContext = context;
  61.     mLineNo = 1;
  62.     mTokenLength = 0;
  63.     mbError = false;
  64.     mpOutput = pOutput;
  65. }
  66.  
  67. bool VDCompilerLexer::GetErrorInfo(VDCompilerErrorInfo& errorInfo) {
  68.     if (!mbError)
  69.         return false;
  70.  
  71.     errorInfo = mErrorInfo;
  72.     return true;
  73. }
  74.  
  75. void VDCompilerLexer::AddToken(int token, const char *s) {
  76.     int len = (int)strlen(s);
  77.     uint32 checksum = Checksum(s, len);
  78.     Keyword k;
  79.  
  80.     k.len = len;
  81.     k.text = s;
  82.     k.token = token;
  83.  
  84.     mKeywords.insert(Keywords::value_type(checksum, k));
  85.  
  86. }
  87.  
  88. int VDCompilerLexer::Token() {
  89.     bool inComment = false;
  90.     char c;
  91.  
  92.     // parse out whitespace and comments
  93.     for(;;) {
  94.         if (mpSrc == mpSrcEnd) {
  95.             mpTokenLineStart = mpSrcLineStart;
  96.             mpToken = mpSrc;
  97.             mTokenLength = 0;
  98.             return 0;
  99.         }
  100.  
  101.         c = *mpSrc++;
  102.         if (c == ' ' || c == '\t')
  103.             continue;
  104.  
  105.         if (c == '\n' || c == '\r') {
  106.             if (mpSrc != mpSrcEnd) {
  107.                 char d = *mpSrc;
  108.                 if ((c ^ d) == ('\n' ^ '\r'))
  109.                     ++mpSrc;
  110.             }
  111.             ++mLineNo;
  112.             mpSrcLineStart = mpSrc;
  113.             continue;
  114.         }
  115.  
  116.         if (inComment) {
  117.             if (c == '*' && mpSrc != mpSrcEnd && *mpSrc == '/') {
  118.                 ++mpSrc;
  119.  
  120.                 inComment = false;
  121.             }
  122.         } else {
  123.             if (c == '/' && mpSrc != mpSrcEnd) {
  124.                 char d = *mpSrc;
  125.                 if (d == '/') {                // C++-style comment
  126.                     ++mpSrc;
  127.                     while(mpSrc != mpSrcEnd) {
  128.                         c = *mpSrc;
  129.  
  130.                         if (c == '\n' || c == '\r')
  131.                             break;
  132.  
  133.                         ++mpSrc;
  134.                     }
  135.                     continue;
  136.                 } else if (d == '*') {        // C-style comment
  137.                     ++mpSrc;
  138.  
  139.                     inComment = true;
  140.                     continue;
  141.                 }
  142.             }
  143.  
  144.             break;
  145.         }
  146.     }
  147.  
  148.     mpToken = mpSrc - 1;
  149.     mpTokenLineStart = mpSrcLineStart;
  150.  
  151.     // check for numeric tokens
  152.     if ((unsigned char)(c - '0') < 10) {
  153.         bool overflow = false;
  154.         int value = c - '0';
  155.  
  156.         if (!value && mpSrc != mpSrcEnd && (*mpSrc == 'x' || *mpSrc == 'X')) {
  157.             ++mpSrc;
  158.  
  159.             int digits = 0;
  160.             mIntVal = 0;
  161.             while(mpSrc != mpSrcEnd) {
  162.                 c = *mpSrc;
  163.                 if (!isxdigit((unsigned char)c))
  164.                     break;
  165.                 ++mpSrc;
  166.  
  167.                 c = (c - '0') & 0x1f;
  168.                 if (c >= 10)
  169.                     c -= 7;
  170.  
  171.                 mIntVal = (mIntVal << 4) + c;
  172.                 ++digits;
  173.             }
  174.  
  175.             if (!digits) {
  176.                 SetError("Invalid hex constant");
  177.                 return 0;
  178.             }
  179.  
  180.             return kTokenInt;
  181.         }
  182.  
  183.         while(mpSrc != mpSrcEnd) {
  184.             c = *mpSrc;
  185.  
  186.             if (c == '.') {
  187.                 double fvalue = 0;
  188.  
  189.                 for(const char *s = mpToken; s != mpSrc; ++s)
  190.                     fvalue = fvalue * 10.0 + (float)(*s - '0');
  191.  
  192.                 ++mpSrc;
  193.  
  194.                 double scale = 0.1;
  195.                 while(mpSrc != mpSrcEnd) {
  196.                     c = *mpSrc;
  197.  
  198.                     int digit = (c - '0');
  199.                     if ((unsigned)digit >= 10)
  200.                         break;
  201.  
  202.                     ++mpSrc;
  203.                     fvalue += scale * (float)digit;
  204.                     scale *= 0.1;
  205.                 }
  206.  
  207.                 if (mpSrc != mpSrcEnd) {
  208.                     c = *mpSrc;
  209.                     if (c == 'e' || c == 'E') {
  210.                         ++mpSrc;
  211.  
  212.                         const char *pExpBase = mpSrc;
  213.                         int exp = 0;
  214.  
  215.                         while(mpSrc != mpSrcEnd) {
  216.                             c = *mpSrc;
  217.  
  218.                             int digit = (c - '0');
  219.                             if ((unsigned)digit >= 10)
  220.                                 break;
  221.  
  222.                             exp = (exp*10) + digit;
  223.  
  224.                             ++mpSrc;
  225.                         }
  226.  
  227.                         if (mpSrc == pExpBase) {
  228.                             SetError("Invalid real number");
  229.                             return 0;
  230.                         }
  231.  
  232.                         fvalue *= pow(10.0, exp);
  233.                     }
  234.                 }
  235.  
  236.                 if (mpSrc != mpSrcEnd) {
  237.                     c = *mpSrc;
  238.                     if (c == 'f' || c == 'F')
  239.                         ++mpSrc;
  240.                 }
  241.  
  242.                 mFloatVal = (float)fvalue;
  243.                 mTokenLength = mpSrc - mpToken;
  244.                 return kTokenFloat;
  245.             }
  246.  
  247.             int digit = (c - '0');
  248.             if ((unsigned)digit >= 10)
  249.                 break;
  250.             ++mpSrc;
  251.  
  252.             if (value > 214748364)
  253.                 overflow = true;
  254.  
  255.             value *= 10;
  256.  
  257.             if (value > 2147483647 - digit)
  258.                 overflow = true;
  259.  
  260.             value += digit;
  261.         
  262.         }
  263.  
  264.         if (overflow) {
  265.             SetError("Integer literal too large");
  266.             return 0;
  267.         }
  268.  
  269.         mIntVal = value;
  270.         mTokenLength = mpSrc - mpToken;
  271.         return kTokenInt;
  272.     }
  273.  
  274.     // check for identifiers
  275.     if (c == '_' || (unsigned char)((c & 0xdf) - 'A') < 26) {
  276.         while(mpSrc != mpSrcEnd) {
  277.             c = *mpSrc++;
  278.  
  279.             if (c != '_' && (unsigned char)((c & 0xdf) - 'A') >= 26 && (unsigned char)(c - '0') >= 10) {
  280.                 --mpSrc;
  281.                 break;
  282.             }
  283.         }
  284.  
  285.         mTokenLength = mpSrc - mpToken;
  286.  
  287.         uint32 checksum = Checksum(mpToken, mTokenLength);
  288.  
  289.         std::pair<Keywords::const_iterator, Keywords::const_iterator> range(mKeywords.equal_range(checksum));
  290.  
  291.         for(; range.first != range.second; ++range.first)
  292.         {
  293.             const Keyword& kw = range.first->second;
  294.  
  295.             if (kw.len == mTokenLength && !memcmp(kw.text, mpToken, mTokenLength))
  296.                 return kw.token;
  297.         }
  298.  
  299.         return kTokenIdent;
  300.     }
  301.  
  302.     // check for single character
  303.     if (c == '\'') {
  304.         if (mpSrc == mpSrcEnd) {
  305.             SetError("End of file encountered in character literal");
  306.             return 0;
  307.         }
  308.  
  309.         c = *mpSrc++;
  310.         bool escaped = false;
  311.         if (c == '\\') {
  312.             escaped = true;
  313.             if (mpSrc == mpSrcEnd) {
  314.                 SetError("End of file encountered in character literal");
  315.                 return 0;
  316.             }
  317.             c = *mpSrc++;
  318.         } else {
  319.             if (c == '\'') {
  320.                 SetError("Empty character literal");
  321.                 return 0;
  322.             }
  323.         }
  324.  
  325.         mIntVal = (int)(uint8)c;
  326.  
  327.         if (mpSrc == mpSrcEnd) {
  328.             SetError("End of file encountered in character literal");
  329.             return 0;
  330.         }
  331.  
  332.         c = *mpSrc++;
  333.         if (c != '\'') {
  334.             SetError("Expected \' at end of character literal");
  335.             return 0;
  336.         }
  337.  
  338.         mTokenLength = mpSrc - mpToken;
  339.         return kTokenInt;
  340.     }
  341.  
  342.     // check for string
  343.     if (c == '"') {
  344.         mString.clear();
  345.         for(;;) {
  346.             if (mpSrc == mpSrcEnd) {
  347.                 SetError("End of file encountered in string literal");
  348.                 return 0;
  349.             }
  350.  
  351.             c = *mpSrc++;
  352.             if (c == '\r' || c == '\n') {
  353.                 SetError("Newline encountered in string literal");
  354.                 return 0;
  355.             }
  356.  
  357.             if (c == '"')
  358.                 break;
  359.  
  360.             if (c == '\\') {
  361.                 if (mpSrc == mpSrcEnd) {
  362.                     SetError("Invalid escape sequence");
  363.                     return 0;
  364.                 }
  365.  
  366.                 c = *mpSrc++;
  367.                 switch(c) {
  368.                     case 'a':    c = '\a';    break;
  369.                     case 'b':    c = '\b';    break;
  370.                     case 'f':    c = '\f';    break;
  371.                     case 'n':    c = '\n';    break;
  372.                     case 'r':    c = '\r';    break;
  373.                     case 't':    c = '\t';    break;
  374.                     case 'u':    c = '\u';    break;
  375.                     case 'v':    c = '\v';    break;
  376.                     case 'x':
  377.                         c = 0;
  378.                         for(;;) {
  379.                             if (mpSrc == mpSrcEnd) {
  380.                                 SetError("Unterminated hex escape sequence");
  381.                                 return 0;
  382.                             }
  383.  
  384.                             char d = *mpSrc;
  385.                             if (!isxdigit((unsigned char)d))
  386.                                 break;
  387.                             ++mpSrc;
  388.  
  389.                             d = (d - 0x30) & 0x1f;
  390.                             if (d >= 10)
  391.                                 d -= 7;
  392.  
  393.                             c = (c << 4) + d;
  394.                         }
  395.                         break;
  396.                     case '\\':
  397.                         break;
  398.                     default:
  399.                         SetErrorF("Unknown escape sequence \\%c", c);
  400.                         return 0;
  401.                 }
  402.             }
  403.             mString.push_back(c);
  404.         }
  405.  
  406.         mTokenLength = mpSrc - mpToken;
  407.         return kTokenString;
  408.     }
  409.  
  410.     if ((unsigned char)(c - 0x20) >= 0x5f) {
  411.         SetErrorF("Unrecognized character '%c'", c);
  412.         return 0;
  413.     }
  414.  
  415.     mTokenLength = 1;
  416.     return c;
  417. }
  418.  
  419. void VDCompilerLexer::Push() {
  420.     mpSrc = mpToken;
  421. }
  422.  
  423. bool VDCompilerLexer::SetError(const char *s) {
  424.     if (mbError)
  425.         return false;
  426.  
  427.     mbError = true;
  428.     mErrorInfo.mLine = mLineNo;
  429.     mErrorInfo.mColumn = (mpToken - mpSrcLineStart) + 1;
  430.     mErrorInfo.mLength = mTokenLength;
  431.  
  432.     char buf[2048];
  433.     if (_snprintf(buf, 2047, "%s(%d,%d): Error! %s\r\n", mpContext, mLineNo, (int)(mpSrc - mpSrcLineStart) + 1, s) > 0) {
  434.         buf[2047] = 0;
  435.         mpOutput->WriteLogOutput(buf);
  436.     }
  437.     return false;
  438. }
  439.  
  440. bool VDCompilerLexer::SetErrorF(const char *format, ...) {
  441.     if (mbError)
  442.         return false;
  443.  
  444.     mbError = true;
  445.     mErrorInfo.mLine = mLineNo;
  446.     mErrorInfo.mColumn = (mpToken - mpSrcLineStart) + 1;
  447.     mErrorInfo.mLength = mTokenLength;
  448.  
  449.     va_list val;
  450.     char buf[2048], *s = buf, *limit = s + 2047;
  451.     int len;
  452.     len = _snprintf(s, limit-s, "%s(%d,%d): Error! ", mpContext, mLineNo, (int)(mpSrc - mpSrcLineStart) + 1);
  453.     if (len >= 0) {
  454.         s += len;
  455.         va_start(val, format);
  456.         len = _vsnprintf(s, limit-s, format, val);
  457.         va_end(val);
  458.  
  459.         if (len >= 0) {
  460.             s += len;
  461.  
  462.             if (limit-s >= 2) {
  463.                 *s++ = '\r';
  464.                 *s++ = '\n';
  465.                 *s = 0;
  466.                 mpOutput->WriteLogOutput(buf);
  467.             }
  468.         }
  469.     }
  470.     return false;
  471. }
  472.  
  473. ///////////////////////////////////////////////////////////////////////////////
  474.  
  475. namespace {
  476.     enum Opcode {
  477.         kInsnEnd,
  478.         kInsnLoadConstI4,
  479.         kInsnLoadConstI8,
  480.         kInsnLoadConstR8,
  481.         kInsnDupI4,
  482.         kInsnWriteI1,
  483.         kInsnWriteI2,
  484.         kInsnWriteI4,
  485.         kInsnWriteI8,
  486.         kInsnWriteR4,
  487.         kInsnWriteR8,
  488.         kInsnSetIndexAnchor,
  489.         kInsnWriteIndex,
  490.         kInsnBeginChunk,
  491.         kInsnEndChunk,
  492.         kInsnEndIndexedChunk
  493.     };
  494. }
  495.  
  496. class VDFileCreator : public vdrefcounted<IVDFileCreator> {
  497. public:
  498.     VDFileCreator();
  499.  
  500.     void Create(const wchar_t *filename);
  501.  
  502.     void Emit8(uint8 c);
  503.     void Emit16(uint16 c);
  504.     void Emit32(uint32 c);
  505.     void Emit64(uint64 c);
  506.     void EmitR8(double c);
  507.  
  508. protected:
  509.     sint64    mIndexOffset;
  510.  
  511.     typedef vdfastvector<uint8> Bytecode;
  512.     Bytecode    mBytecode;
  513.  
  514.     union StackVal {
  515.         uint32    i4;
  516.         uint64    i8;
  517.         double    r8;
  518.         const char *s;
  519.     };
  520.  
  521.     typedef vdfastvector<StackVal> Stack;
  522.     Stack    mStack;
  523.  
  524.     struct IndexEntry {
  525.         uint32 pos;
  526.         uint32 size;
  527.         uint32 flags;
  528.         uint32 ckid;
  529.     };
  530.  
  531.     typedef vdfastvector<IndexEntry> Index;
  532.     Index mIndex;
  533.  
  534.     typedef vdfastvector<sint64> Chunks;
  535.     Chunks mChunks;
  536. };
  537.  
  538. VDFileCreator::VDFileCreator()
  539.     : mIndexOffset(0)
  540. {
  541. }
  542.  
  543. void VDFileCreator::Create(const wchar_t *filename) {
  544.     VDFile file(filename, nsVDFile::kWrite | nsVDFile::kDenyRead | nsVDFile::kCreateAlways);
  545.  
  546.     const uint8 *ip = mBytecode.data();
  547.     while(uint8 op = *ip++) {
  548.         switch(op) {
  549.             case kInsnLoadConstI4:
  550.                 mStack.push_back().i4 = VDReadUnalignedS32(ip);
  551.                 ip += 4;
  552.                 break;
  553.  
  554.             case kInsnLoadConstI8:
  555.                 mStack.push_back().i8 = VDReadUnalignedS64(ip);
  556.                 ip += 8;
  557.                 break;
  558.  
  559.             case kInsnLoadConstR8:
  560.                 mStack.push_back().r8 = VDReadUnalignedD(ip);
  561.                 ip += 8;
  562.                 break;
  563.  
  564.             case kInsnDupI4:
  565.                 {
  566.                     sint32 v = mStack.back().i4;
  567.                     mStack.push_back().i4 = v;
  568.                 }
  569.                 break;
  570.  
  571.             case kInsnWriteI1:
  572.                 {
  573.                     uint8 c = (uint8)mStack.back().i4;
  574.                     mStack.pop_back();
  575.  
  576.                     file.write(&c, 1);
  577.                 }
  578.                 break;
  579.  
  580.             case kInsnWriteI2:
  581.                 {
  582.                     uint16 c = (uint16)mStack.back().i4;
  583.                     mStack.pop_back();
  584.  
  585.                     file.write(&c, 2);
  586.                 }
  587.                 break;
  588.  
  589.             case kInsnWriteI4:
  590.                 {
  591.                     uint32 c = mStack.back().i4;
  592.                     mStack.pop_back();
  593.  
  594.                     file.write(&c, 4);
  595.                 }
  596.                 break;
  597.  
  598.             case kInsnWriteI8:
  599.                 {
  600.                     uint64 c = mStack.back().i8;
  601.                     mStack.pop_back();
  602.  
  603.                     file.write(&c, 8);
  604.                 }
  605.                 break;
  606.  
  607.             case kInsnWriteR4:
  608.                 {
  609.                     float c = (float)mStack.back().r8;
  610.                     mStack.pop_back();
  611.  
  612.                     file.write(&c, 4);
  613.                 }
  614.                 break;
  615.  
  616.             case kInsnWriteR8:
  617.                 {
  618.                     double c = mStack.back().r8;
  619.                     mStack.pop_back();
  620.  
  621.                     file.write(&c, 8);
  622.                 }
  623.                 break;
  624.  
  625.             case kInsnSetIndexAnchor:
  626.                 mIndexOffset = file.tell();
  627.                 break;
  628.  
  629.             case kInsnWriteIndex:
  630.                 {
  631.                     Index::const_iterator it(mIndex.begin()), itEnd(mIndex.end());
  632.                     for(; it!=itEnd; ++it) {
  633.                         const IndexEntry& ie = *it;
  634.  
  635.                         uint32 t[4];
  636.                         t[0] = ie.ckid;
  637.                         t[1] = ie.flags;
  638.                         t[2] = ie.pos;
  639.                         t[3] = ie.size;
  640.  
  641.                         file.write(t, sizeof t);
  642.                     }
  643.                 }
  644.                 break;
  645.  
  646.             case kInsnBeginChunk:
  647.                 {
  648.                     mChunks.push_back(file.tell());
  649.  
  650.                     uint32 c = 0;
  651.                     file.write(&c, 4);
  652.                 }
  653.                 break;
  654.  
  655.             case kInsnEndChunk:
  656.                 {
  657.                     sint64 pos = file.tell();
  658.                     sint64 cpos = mChunks.back();
  659.                     mChunks.pop_back();
  660.                     file.seek(cpos);
  661.  
  662.                     uint32 size = (uint32)(pos - (cpos + 4));
  663.                     file.write(&size, 4);
  664.  
  665.                     uint8 pad = 0;
  666.                     if (pos & 1)
  667.                         file.write(&pad, 1);
  668.  
  669.                     file.seek(pos);
  670.                 }
  671.                 break;
  672.  
  673.             case kInsnEndIndexedChunk:
  674.                 {
  675.                     uint32 flags = mStack.back().i4;
  676.                     mStack.pop_back();
  677.  
  678.                     uint32 ckid = mStack.back().i4;
  679.                     mStack.pop_back();
  680.  
  681.                     sint64 pos = file.tell();
  682.                     sint64 cpos = mChunks.back();
  683.                     mChunks.pop_back();
  684.                     file.seek(cpos);
  685.  
  686.                     uint32 size = (uint32)(pos - (cpos + 4));
  687.                     file.write(&size, 4);
  688.  
  689.                     uint8 pad = 0;
  690.                     if (pos & 1)
  691.                         file.write(&pad, 1);
  692.  
  693.                     file.seek(pos);
  694.  
  695.                     IndexEntry ie;
  696.                     ie.pos = (uint32)((cpos - 4) - mIndexOffset);
  697.                     ie.size = size;
  698.                     ie.flags = flags;
  699.                     ie.ckid = ckid;
  700.  
  701.                     mIndex.push_back(ie);
  702.                 }
  703.                 break;
  704.         }
  705.     }
  706. }
  707.  
  708. void VDFileCreator::Emit8(uint8 c) {
  709.     mBytecode.push_back(c);
  710. }
  711.  
  712. void VDFileCreator::Emit16(uint16 c) {
  713.     mBytecode.insert(mBytecode.end(), (const uint8 *)&c, (const uint8 *)(&c+1));
  714. }
  715.  
  716. void VDFileCreator::Emit32(uint32 c) {
  717.     mBytecode.insert(mBytecode.end(), (const uint8 *)&c, (const uint8 *)(&c+1));
  718. }
  719.  
  720. void VDFileCreator::Emit64(uint64 c) {
  721.     mBytecode.insert(mBytecode.end(), (const uint8 *)&c, (const uint8 *)(&c+1));
  722. }
  723.  
  724. void VDFileCreator::EmitR8(double c) {
  725.     mBytecode.insert(mBytecode.end(), (const uint8 *)&c, (const uint8 *)(&c+1));
  726. }
  727.  
  728. ///////////////////////////////////////////////////////////////////////////////
  729.  
  730. namespace {
  731.     enum {
  732.         kKeywordWrite_i1 = kTokenKeywordBase,
  733.         kKeywordWrite_i2,
  734.         kKeywordWrite_i4,
  735.         kKeywordWrite_i8,
  736.         kKeywordWrite_u1,
  737.         kKeywordWrite_u2,
  738.         kKeywordWrite_u4,
  739.         kKeywordWrite_u8,
  740.         kKeywordWrite_r4,
  741.         kKeywordWrite_r8,
  742.         kKeywordWrite_fcc,
  743.         kKeywordSet_index_anchor,
  744.         kKeywordAdd_to_index,
  745.         kKeywordWrite_index,
  746.         kKeywordChunk,
  747.         kKeywordIndexed_chunk
  748.     };
  749.  
  750.     enum ExpressionOp {
  751.         kOpNone,
  752.         kOpAdd,
  753.         kOpSub,
  754.         kOpMul,
  755.         kOpDiv,
  756.         kOpNegate,
  757.         kOpSwizzle,
  758.     };
  759.  
  760.     enum VDFileCreatorValueType {
  761.         kTypeI1,
  762.         kTypeI2,
  763.         kTypeI4,
  764.         kTypeI8,
  765.         kTypeU1,
  766.         kTypeU2,
  767.         kTypeU4,
  768.         kTypeU8,
  769.         kTypeR4,
  770.         kTypeR8,
  771.         kTypeS
  772.     };
  773.  
  774.     const char *GetTypeName(VDFileCreatorValueType type) {
  775.         switch(type) {
  776.             case kTypeI1:
  777.                 return "int8";
  778.  
  779.             case kTypeI2:
  780.                 return "int16";
  781.  
  782.             case kTypeI4:
  783.                 return "int32";
  784.  
  785.             case kTypeI8:
  786.                 return "int64";
  787.  
  788.             case kTypeU1:
  789.                 return "uint8";
  790.  
  791.             case kTypeU2:
  792.                 return "uint16";
  793.  
  794.             case kTypeU4:
  795.                 return "uint32";
  796.  
  797.             case kTypeU8:
  798.                 return "uint64";
  799.  
  800.             case kTypeR4:
  801.                 return "float";
  802.  
  803.             case kTypeR8:
  804.                 return "double";
  805.  
  806.             case kTypeS:
  807.                 return "string";
  808.  
  809.             default:
  810.                 return "???";
  811.         }
  812.     }
  813.  
  814.     VDFileCreatorValueType GetBinaryResultType(VDFileCreatorValueType type1, VDFileCreatorValueType type2) {
  815.         // promote to at least double or int32/uint32
  816.         switch(type1) {
  817.             case kTypeI1:
  818.             case kTypeI2:
  819.                 type1 = kTypeI4;
  820.                 break;
  821.             case kTypeU1:
  822.             case kTypeU2:
  823.                 type1 = kTypeU4;
  824.                 break;
  825.             case kTypeR4:
  826.                 type1 = kTypeR8;
  827.                 break;
  828.         }
  829.  
  830.         switch(type2) {
  831.             case kTypeI1:
  832.             case kTypeI2:
  833.                 type2 = kTypeI4;
  834.                 break;
  835.             case kTypeU1:
  836.             case kTypeU2:
  837.                 type2 = kTypeU4;
  838.                 break;
  839.             case kTypeR4:
  840.                 type2 = kTypeR8;
  841.                 break;
  842.         }
  843.  
  844.         // promote to double if either is double
  845.         if (type1 == kTypeR8 || type2 == kTypeR8)
  846.             return kTypeR8;
  847.  
  848.         // promote to uint64 if either is uint64
  849.         if (type1 == kTypeU8 || type2 == kTypeU8)
  850.             return kTypeU8;
  851.  
  852.         // promote to int64 if either is int64
  853.         if (type1 == kTypeI8 || type2 == kTypeI8)
  854.             return kTypeI8;
  855.  
  856.         // promote to int64 if uint32 and int32 are mixed
  857.         if ((type1 == kTypeI4 && type2 == kTypeU4) || (type1 == kTypeU4 && type2 == kTypeI4))
  858.             return kTypeI8;
  859.  
  860.         VDASSERT(type1 == type2);
  861.         return type1;
  862.     }
  863. }
  864.  
  865. struct VDFileCreatorValue {
  866.     VDFileCreatorValueType    mType;
  867.     union {
  868.         sint32 i4;
  869.         sint64 i8;
  870.         double r8;
  871.         const char *s;
  872.     };
  873.  
  874.     bool ConvertToType(VDFileCreatorValueType type);
  875. };
  876.  
  877. bool VDFileCreatorValue::ConvertToType(VDFileCreatorValueType type) {
  878.     switch(type) {
  879.     case kTypeI1:
  880.         switch(mType) {
  881.         case kTypeU1:    i4 = (sint8 )(uint8 )i4;    break;
  882.         case kTypeI1:    i4 = (sint8 )(sint8 )i4;    break;
  883.         case kTypeI2:    i4 = (sint8 )(sint16)i4;    break;
  884.         case kTypeU2:    i4 = (sint8 )(uint16)i4;    break;
  885.         case kTypeI4:    i4 = (sint8 )(sint32)i4;    break;
  886.         case kTypeU4:    i4 = (sint8 )(uint32)i4;    break;
  887.         case kTypeI8:    i4 = (sint8 )(sint64)i8;    break;
  888.         case kTypeU8:    i4 = (sint8 )(uint64)i8;    break;
  889.         case kTypeR4:    i4 = (sint8 )(float )r8;    break;
  890.         case kTypeR8:    i4 = (sint8 )(double)r8;    break;
  891.         default:        return false;
  892.         }
  893.         break;
  894.  
  895.     case kTypeU1:
  896.         switch(mType) {
  897.         case kTypeU1:    i4 = (uint8 )(uint8 )i4;    break;
  898.         case kTypeI1:    i4 = (uint8 )(sint8 )i4;    break;
  899.         case kTypeI2:    i4 = (uint8 )(sint16)i4;    break;
  900.         case kTypeU2:    i4 = (uint8 )(uint16)i4;    break;
  901.         case kTypeI4:    i4 = (uint8 )(sint32)i4;    break;
  902.         case kTypeU4:    i4 = (uint8 )(uint32)i4;    break;
  903.         case kTypeI8:    i4 = (uint8 )(sint64)i8;    break;
  904.         case kTypeU8:    i4 = (uint8 )(uint64)i8;    break;
  905.         case kTypeR4:    i4 = (uint8 )(float )r8;    break;
  906.         case kTypeR8:    i4 = (uint8 )(double)r8;    break;
  907.         default:        return false;
  908.         }
  909.         break;
  910.  
  911.     case kTypeI2:
  912.         switch(mType) {
  913.         case kTypeU1:    i4 = (sint16)(uint8 )i4;    break;
  914.         case kTypeI1:    i4 = (sint16)(sint8 )i4;    break;
  915.         case kTypeI2:    i4 = (sint16)(sint16)i4;    break;
  916.         case kTypeU2:    i4 = (sint16)(uint16)i4;    break;
  917.         case kTypeI4:    i4 = (sint16)(sint32)i4;    break;
  918.         case kTypeU4:    i4 = (sint16)(uint32)i4;    break;
  919.         case kTypeI8:    i4 = (sint16)(sint64)i8;    break;
  920.         case kTypeU8:    i4 = (sint16)(uint64)i8;    break;
  921.         case kTypeR4:    i4 = (sint16)(float )r8;    break;
  922.         case kTypeR8:    i4 = (sint16)(double)r8;    break;
  923.         default:        return false;
  924.         }
  925.         break;
  926.  
  927.     case kTypeU2:
  928.         switch(mType) {
  929.         case kTypeU1:    i4 = (uint16)(uint8 )i4;    break;
  930.         case kTypeI1:    i4 = (uint16)(sint8 )i4;    break;
  931.         case kTypeI2:    i4 = (uint16)(sint16)i4;    break;
  932.         case kTypeU2:    i4 = (uint16)(uint16)i4;    break;
  933.         case kTypeI4:    i4 = (uint16)(sint32)i4;    break;
  934.         case kTypeU4:    i4 = (uint16)(uint32)i4;    break;
  935.         case kTypeI8:    i4 = (uint16)(sint64)i8;    break;
  936.         case kTypeU8:    i4 = (uint16)(uint64)i8;    break;
  937.         case kTypeR4:    i4 = (uint16)(float )r8;    break;
  938.         case kTypeR8:    i4 = (uint16)(double)r8;    break;
  939.         default:        return false;
  940.         }
  941.         break;
  942.  
  943.     case kTypeI4:
  944.         switch(mType) {
  945.         case kTypeU1:    i4 = (sint32)(uint8 )i4;    break;
  946.         case kTypeI1:    i4 = (sint32)(sint8 )i4;    break;
  947.         case kTypeI2:    i4 = (sint32)(sint16)i4;    break;
  948.         case kTypeU2:    i4 = (sint32)(uint16)i4;    break;
  949.         case kTypeI4:    i4 = (sint32)(sint32)i4;    break;
  950.         case kTypeU4:    i4 = (sint32)(uint32)i4;    break;
  951.         case kTypeI8:    i4 = (sint32)(sint64)i8;    break;
  952.         case kTypeU8:    i4 = (sint32)(uint64)i8;    break;
  953.         case kTypeR4:    i4 = (sint32)(float )r8;    break;
  954.         case kTypeR8:    i4 = (sint32)(double)r8;    break;
  955.         default:        return false;
  956.         }
  957.         break;
  958.  
  959.     case kTypeU4:
  960.         switch(mType) {
  961.         case kTypeU1:    i4 = (uint32)(uint8 )i4;    break;
  962.         case kTypeI1:    i4 = (uint32)(sint8 )i4;    break;
  963.         case kTypeI2:    i4 = (uint32)(sint16)i4;    break;
  964.         case kTypeU2:    i4 = (uint32)(uint16)i4;    break;
  965.         case kTypeI4:    i4 = (uint32)(sint32)i4;    break;
  966.         case kTypeU4:    i4 = (uint32)(uint32)i4;    break;
  967.         case kTypeI8:    i4 = (uint32)(sint64)i8;    break;
  968.         case kTypeU8:    i4 = (uint32)(uint64)i8;    break;
  969.         case kTypeR4:    i4 = (uint32)(float )r8;    break;
  970.         case kTypeR8:    i4 = (uint32)(double)r8;    break;
  971.         default:        return false;
  972.         }
  973.         break;
  974.  
  975.     case kTypeI8:
  976.         switch(mType) {
  977.         case kTypeU1:    i8 = (sint64)(uint8 )i4;    break;
  978.         case kTypeI1:    i8 = (sint64)(sint8 )i4;    break;
  979.         case kTypeI2:    i8 = (sint64)(sint16)i4;    break;
  980.         case kTypeU2:    i8 = (sint64)(uint16)i4;    break;
  981.         case kTypeI4:    i8 = (sint64)(sint32)i4;    break;
  982.         case kTypeU4:    i8 = (sint64)(uint32)i4;    break;
  983.         case kTypeI8:    i8 = (sint64)(sint64)i8;    break;
  984.         case kTypeU8:    i8 = (sint64)(uint64)i8;    break;
  985.         case kTypeR4:    i8 = (sint64)(float )r8;    break;
  986.         case kTypeR8:    i8 = (sint64)(double)r8;    break;
  987.         default:        return false;
  988.         }
  989.         break;
  990.  
  991.     case kTypeU8:
  992.         switch(mType) {
  993.         case kTypeU1:    i8 = (uint64)(uint8 )i4;    break;
  994.         case kTypeI1:    i8 = (uint64)(sint8 )i4;    break;
  995.         case kTypeI2:    i8 = (uint64)(sint16)i4;    break;
  996.         case kTypeU2:    i8 = (uint64)(uint16)i4;    break;
  997.         case kTypeI4:    i8 = (uint64)(sint32)i4;    break;
  998.         case kTypeU4:    i8 = (uint64)(uint32)i4;    break;
  999.         case kTypeI8:    i8 = (uint64)(sint64)i8;    break;
  1000.         case kTypeU8:    i8 = (uint64)(uint64)i8;    break;
  1001.         case kTypeR4:    i8 = (uint64)(float )r8;    break;
  1002.         case kTypeR8:    i8 = (uint64)(double)r8;    break;
  1003.         default:        return false;
  1004.         }
  1005.         break;
  1006.  
  1007.     case kTypeR4:
  1008.         switch(mType) {
  1009.         case kTypeU1:    r8 = (float )(uint8 )i4;    break;
  1010.         case kTypeI1:    r8 = (float )(sint8 )i4;    break;
  1011.         case kTypeI2:    r8 = (float )(sint16)i4;    break;
  1012.         case kTypeU2:    r8 = (float )(uint16)i4;    break;
  1013.         case kTypeI4:    r8 = (float )(sint32)i4;    break;
  1014.         case kTypeU4:    r8 = (float )(uint32)i4;    break;
  1015.         case kTypeI8:    r8 = (float )(sint64)i8;    break;
  1016.         case kTypeU8:    r8 = (float )(uint64)i8;    break;
  1017.         case kTypeR4:    r8 = (float )(float )r8;    break;
  1018.         case kTypeR8:    r8 = (float )(double)r8;    break;
  1019.         default:        return false;
  1020.         }
  1021.         break;
  1022.  
  1023.     case kTypeR8:
  1024.         switch(mType) {
  1025.         case kTypeU1:    r8 = (double)(uint8 )i4;    break;
  1026.         case kTypeI1:    r8 = (double)(sint8 )i4;    break;
  1027.         case kTypeI2:    r8 = (double)(sint16)i4;    break;
  1028.         case kTypeU2:    r8 = (double)(uint16)i4;    break;
  1029.         case kTypeI4:    r8 = (double)(sint32)i4;    break;
  1030.         case kTypeU4:    r8 = (double)(uint32)i4;    break;
  1031.         case kTypeI8:    r8 = (double)(sint64)i8;    break;
  1032.         case kTypeU8:    r8 = (double)(uint64)i8;    break;
  1033.         case kTypeR4:    r8 = (double)(float )r8;    break;
  1034.         case kTypeR8:    r8 = (double)(double)r8;    break;
  1035.         default:        return false;
  1036.         }
  1037.         break;
  1038.  
  1039.     default:
  1040.         return false;
  1041.     }
  1042.  
  1043.     mType = type;
  1044.     return true;
  1045. }
  1046.  
  1047. VDFileCreatorParser::VDFileCreatorParser() {
  1048.     mLexer.AddToken(kKeywordWrite_i1, "write_i1");
  1049.     mLexer.AddToken(kKeywordWrite_i2, "write_i2");
  1050.     mLexer.AddToken(kKeywordWrite_i4, "write_i4");
  1051.     mLexer.AddToken(kKeywordWrite_i8, "write_i8");
  1052.     mLexer.AddToken(kKeywordWrite_u1, "write_u1");
  1053.     mLexer.AddToken(kKeywordWrite_u2, "write_u2");
  1054.     mLexer.AddToken(kKeywordWrite_u4, "write_u4");
  1055.     mLexer.AddToken(kKeywordWrite_u8, "write_u8");
  1056.     mLexer.AddToken(kKeywordWrite_r4, "write_r4");
  1057.     mLexer.AddToken(kKeywordWrite_r8, "write_r8");
  1058.     mLexer.AddToken(kKeywordWrite_fcc, "write_fcc");
  1059.     mLexer.AddToken(kKeywordSet_index_anchor, "set_index_anchor");
  1060.     mLexer.AddToken(kKeywordIndexed_chunk, "indexed_chunk");
  1061.     mLexer.AddToken(kKeywordWrite_index, "write_index");
  1062.     mLexer.AddToken(kKeywordChunk, "chunk");
  1063. }
  1064.  
  1065. VDFileCreatorParser::~VDFileCreatorParser() {
  1066. }
  1067.  
  1068. bool VDFileCreatorParser::Parse(const char *src, size_t len, const char *context, IVDCompilerLogOutput *pOutput, IVDFileCreator **ppCreator) {
  1069.     mpCreator = new VDFileCreator;
  1070.  
  1071.     mLexer.Init(src, len, context, pOutput);
  1072.  
  1073.     while(TryParseGlobalStatement())
  1074.         Collect();
  1075.  
  1076.     mpCreator->Emit8(kInsnEnd);
  1077.  
  1078.     if (mLexer.IsErrorFlagSet())
  1079.         return false;
  1080.  
  1081.     *ppCreator = mpCreator.release();
  1082.     return true;
  1083. }
  1084.  
  1085. bool VDFileCreatorParser::GetErrorInfo(VDCompilerErrorInfo& errorInfo) {
  1086.     return mLexer.GetErrorInfo(errorInfo);
  1087. }
  1088.  
  1089. bool VDFileCreatorParser::TryParseGlobalStatement() {
  1090.     int tok = mLexer.Token();
  1091.  
  1092.     if (!tok)
  1093.         return false;
  1094.  
  1095.     switch(tok) {
  1096.         case '{':
  1097.             for(;;) {
  1098.                 int tok = mLexer.Token();
  1099.  
  1100.                 if (!tok)
  1101.                     return mLexer.SetError("Unmatched '{'");
  1102.  
  1103.                 if (tok == '}')
  1104.                     break;
  1105.  
  1106.                 mLexer.Push();
  1107.                 if (!TryParseGlobalStatement())
  1108.                     return false;
  1109.             }
  1110.             return true;
  1111.  
  1112.         case kKeywordWrite_i1:
  1113.             if (!EmitExpressionI1())
  1114.                 return false;
  1115.             mpCreator->Emit8(kInsnWriteI1);
  1116.             break;
  1117.  
  1118.         case kKeywordWrite_i2:
  1119.             if (!EmitExpressionI2())
  1120.                 return false;
  1121.             mpCreator->Emit8(kInsnWriteI2);
  1122.             break;
  1123.  
  1124.         case kKeywordWrite_i4:
  1125.             if (!EmitExpressionI4())
  1126.                 return false;
  1127.             mpCreator->Emit8(kInsnWriteI4);
  1128.             break;
  1129.  
  1130.         case kKeywordWrite_i8:
  1131.             if (!EmitExpressionI8())
  1132.                 return false;
  1133.             mpCreator->Emit8(kInsnWriteI8);
  1134.             break;
  1135.  
  1136.         case kKeywordWrite_u1:
  1137.             if (!EmitExpressionU1())
  1138.                 return false;
  1139.             mpCreator->Emit8(kInsnWriteI1);
  1140.             break;
  1141.  
  1142.         case kKeywordWrite_u2:
  1143.             if (!EmitExpressionU2())
  1144.                 return false;
  1145.             mpCreator->Emit8(kInsnWriteI2);
  1146.             break;
  1147.  
  1148.         case kKeywordWrite_u4:
  1149.             if (!EmitExpressionU4())
  1150.                 return false;
  1151.             mpCreator->Emit8(kInsnWriteI4);
  1152.             break;
  1153.  
  1154.         case kKeywordWrite_u8:
  1155.             if (!EmitExpressionU8())
  1156.                 return false;
  1157.             mpCreator->Emit8(kInsnWriteI8);
  1158.             break;
  1159.  
  1160.         case kKeywordWrite_r4:
  1161.             if (!EmitExpressionR4())
  1162.                 return false;
  1163.             mpCreator->Emit8(kInsnWriteR4);
  1164.             break;
  1165.  
  1166.         case kKeywordWrite_r8:
  1167.             if (!EmitExpressionR8())
  1168.                 return false;
  1169.             mpCreator->Emit8(kInsnWriteR8);
  1170.             break;
  1171.  
  1172.         case kKeywordWrite_fcc:
  1173.             if (!EmitExpressionFCC())
  1174.                 return false;
  1175.             mpCreator->Emit8(kInsnWriteI4);
  1176.             break;
  1177.  
  1178.         case kKeywordSet_index_anchor:
  1179.             mpCreator->Emit8(kInsnSetIndexAnchor);
  1180.             break;
  1181.  
  1182.         case kKeywordWrite_index:
  1183.             mpCreator->Emit8(kInsnWriteIndex);
  1184.             break;
  1185.  
  1186.         case kKeywordChunk:
  1187.             if (!ParseChunk())
  1188.                 return false;
  1189.             return true;
  1190.  
  1191.         case kKeywordIndexed_chunk:
  1192.             if (!ParseIndexedChunk())
  1193.                 return false;
  1194.             return true;
  1195.  
  1196.         default:
  1197.             return mLexer.SetError("Syntax error");
  1198.     }
  1199.  
  1200.     tok = mLexer.Token();
  1201.     if (tok != ';')
  1202.         return mLexer.SetError("Expected end of statement");
  1203.  
  1204.     return true;
  1205. }
  1206.  
  1207. bool VDFileCreatorParser::ParseChunk() {
  1208.     if (!EmitExpressionFCC())
  1209.         return false;
  1210.     mpCreator->Emit8(kInsnWriteI4);
  1211.     mpCreator->Emit8(kInsnBeginChunk);
  1212.     if (!TryParseGlobalStatement())
  1213.         return false;
  1214.     mpCreator->Emit8(kInsnEndChunk);
  1215.     return true;
  1216. }
  1217.  
  1218. bool VDFileCreatorParser::ParseIndexedChunk() {
  1219.     if (!EmitExpressionFCC())
  1220.         return false;
  1221.     mpCreator->Emit8(kInsnDupI4);
  1222.     mpCreator->Emit8(kInsnWriteI4);
  1223.  
  1224.     int tok = mLexer.Token();
  1225.     if (tok != ',')
  1226.         return mLexer.SetError("Expected ','");
  1227.  
  1228.     if (!EmitExpressionU4())
  1229.         return false;
  1230.  
  1231.     mpCreator->Emit8(kInsnBeginChunk);
  1232.     if (!TryParseGlobalStatement())
  1233.         return false;
  1234.     mpCreator->Emit8(kInsnEndIndexedChunk);
  1235.     return true;
  1236. }
  1237.  
  1238. bool VDFileCreatorParser::ParseExpression(VDFileCreatorValue& value) {
  1239.     vdfastvector<uint32> opStack;
  1240.     vdfastvector<VDFileCreatorValue> valStack;
  1241.     bool expectValue = true;
  1242.     int parenLevel = 0;
  1243.  
  1244.     for(;;) {
  1245.         int tok = mLexer.Token();
  1246.  
  1247.         if (expectValue) {
  1248.             if (tok == '+') {        // unary +
  1249.                 continue;
  1250.             } else if (tok == '-') {
  1251.                 opStack.push_back(kOpNegate + (9<<8));
  1252.                 continue;
  1253.             } else if (tok == '(') {
  1254.                 parenLevel += 0x10000;
  1255.             } else if (tok == kTokenFloat) {
  1256.                 VDFileCreatorValue val;
  1257.                 val.mType = kTypeR8;
  1258.                 val.r8 = mLexer.mFloatVal;
  1259.  
  1260.                 valStack.push_back(val);
  1261.                 expectValue = false;
  1262.             } else if (tok == kTokenInt) {
  1263.                 VDFileCreatorValue val;
  1264.                 val.mType = kTypeI4;
  1265.                 val.i4 = mLexer.mIntVal;
  1266.  
  1267.                 valStack.push_back(val);
  1268.                 expectValue = false;
  1269.             } else if (tok == kTokenString) {
  1270.                 int len = (int)mLexer.mString.size();
  1271.                 char *s = new char[len + 1];
  1272.                 mTempStrings.push_back(s);
  1273.                 memcpy(s, mLexer.mString.data(), len);
  1274.                 s[len] = 0;
  1275.  
  1276.                 VDFileCreatorValue val;
  1277.                 val.mType = kTypeS;
  1278.                 val.s = s;
  1279.  
  1280.                 valStack.push_back(val);
  1281.                 expectValue = false;
  1282.             } else {
  1283.                 return mLexer.SetError("Expected expression value");
  1284.             }
  1285.         } else {
  1286.             int op = 0;
  1287.             if (tok == '+')
  1288.                 op = kOpAdd + (1 << 8) + parenLevel;
  1289.             else if (tok == '-')
  1290.                 op = kOpSub + (1 << 8) + parenLevel;
  1291.             else if (tok == '*')
  1292.                 op = kOpMul + (2 << 8) + parenLevel;
  1293.             else if (tok == '/')
  1294.                 op = kOpDiv + (2 << 8) + parenLevel;
  1295.             else if (tok == ')') {
  1296.                 if (parenLevel) {
  1297.                     parenLevel -= 0x10000;
  1298.                     continue;
  1299.                 }
  1300.             }
  1301.  
  1302.             // reduce as necessary
  1303.             while(!opStack.empty()) {
  1304.                 int otherop = opStack.back();
  1305.  
  1306.                 if (op > otherop)
  1307.                     break;
  1308.  
  1309.                 opStack.pop_back();
  1310.  
  1311.                 ExpressionOp baseop = (ExpressionOp)(otherop & 0xff);
  1312.  
  1313.                 if (baseop == kOpNegate) {
  1314.                     VDFileCreatorValue& v = valStack.back();
  1315.  
  1316.                     switch(v.mType) {
  1317.                         case kTypeU1:
  1318.                         case kTypeI1:
  1319.                         case kTypeU2:
  1320.                         case kTypeI2:
  1321.                         case kTypeU4:
  1322.                         case kTypeI4:
  1323.                             v.i4 = -v.i4;
  1324.                             break;
  1325.                         case kTypeU8:
  1326.                         case kTypeI8:
  1327.                             v.i8 = -v.i8;
  1328.                             break;
  1329.                         case kTypeR4:
  1330.                         case kTypeR8:
  1331.                             v.r8 = -v.r8;
  1332.                             break;
  1333.                     }
  1334.                 } else {
  1335.                     // coerce
  1336.                     VDFileCreatorValue& var1 = *(valStack.end() - 2);
  1337.                     VDFileCreatorValue& var2 = valStack.back();
  1338.  
  1339.                     VDFileCreatorValueType commonType = GetBinaryResultType(var1.mType, var2.mType);
  1340.                     if (!commonType)
  1341.                         return mLexer.SetErrorF("Cannot operate between types '%s' and '%s'", GetTypeName(var1.mType), GetTypeName(var2.mType));
  1342.  
  1343.                     if (!var1.ConvertToType(commonType))
  1344.                         return mLexer.SetErrorF("Cannot convert value from '%s' to '%s'", GetTypeName(var1.mType), GetTypeName(commonType));
  1345.  
  1346.                     if (!var2.ConvertToType(commonType))
  1347.                         return mLexer.SetErrorF("Cannot convert value from '%s' to '%s'", GetTypeName(var2.mType), GetTypeName(commonType));
  1348.  
  1349.                     switch(baseop) {
  1350.                         case kOpAdd:
  1351.                             switch(commonType) {
  1352.                                 case kTypeI4:
  1353.                                 case kTypeU4:
  1354.                                     var1.i4 += var2.i4;
  1355.                                     break;
  1356.                                 case kTypeI8:
  1357.                                 case kTypeU8:
  1358.                                     var1.i8 += var2.i8;
  1359.                                     break;
  1360.                                 case kTypeR8:
  1361.                                     var1.r8 += var2.r8;
  1362.                                     break;
  1363.                                 default:
  1364.                                     return mLexer.SetErrorF("Cannot add values of type '%s'", GetTypeName(commonType));
  1365.                             }
  1366.                             break;
  1367.                         case kOpSub:
  1368.                             switch(commonType) {
  1369.                                 case kTypeI4:
  1370.                                 case kTypeU4:
  1371.                                     var1.i4 -= var2.i4;
  1372.                                     break;
  1373.                                 case kTypeI8:
  1374.                                 case kTypeU8:
  1375.                                     var1.i8 -= var2.i8;
  1376.                                     break;
  1377.                                 case kTypeR8:
  1378.                                     var1.r8 -= var2.r8;
  1379.                                     break;
  1380.                                 default:
  1381.                                     return mLexer.SetErrorF("Cannot subtract values of type '%s'", GetTypeName(commonType));
  1382.                             }
  1383.                             break;
  1384.                         case kOpMul:
  1385.                             switch(commonType) {
  1386.                                 case kTypeI4:
  1387.                                     var1.i4 *= var2.i4;
  1388.                                     break;
  1389.                                 case kTypeU4:
  1390.                                     var1.i4 = (uint32)var1.i4 * (uint32)var2.i4;
  1391.                                     break;
  1392.                                 case kTypeI8:
  1393.                                     var1.i8 *= var2.i8;
  1394.                                     break;
  1395.                                 case kTypeU8:
  1396.                                     var1.i8 = (uint64)var1.i8 * (uint64)var2.i8;
  1397.                                     break;
  1398.                                 case kTypeR8:
  1399.                                     var1.r8 *= var2.r8;
  1400.                                     break;
  1401.                                 default:
  1402.                                     return mLexer.SetErrorF("Cannot multiply values of type '%s'", GetTypeName(commonType));
  1403.                             }
  1404.                             break;
  1405.                         case kOpDiv:
  1406.                             switch(commonType) {
  1407.                                 case kTypeI4:
  1408.                                     if (!var2.i4)
  1409.                                         return mLexer.SetError("Divide by zero");
  1410.                                     var1.i4 /= var2.i4;
  1411.                                     break;
  1412.                                 case kTypeU4:
  1413.                                     if (!var2.i4)
  1414.                                         return mLexer.SetError("Divide by zero");
  1415.                                     var1.i4 = (sint32)((uint32)var1.i4 / (uint32)var2.i4);
  1416.                                     break;
  1417.                                 case kTypeI8:
  1418.                                     if (!var2.i8)
  1419.                                         return mLexer.SetError("Divide by zero");
  1420.                                     var1.i8 /= var2.i8;
  1421.                                     break;
  1422.                                 case kTypeU8:
  1423.                                     if (!var2.i8)
  1424.                                         return mLexer.SetError("Divide by zero");
  1425.                                     var1.i8 = (sint64)((uint64)var1.i8 / (uint64)var2.i8);
  1426.                                     break;
  1427.                                 case kTypeR8:
  1428.                                     if (var2.r8 == 0.0)
  1429.                                         return mLexer.SetError("Divide by zero");
  1430.                                     var1.r8 /= var2.r8;
  1431.                                     break;
  1432.                                 default:
  1433.                                     return mLexer.SetErrorF("Cannot divide values of type '%s'", GetTypeName(commonType));
  1434.                             }
  1435.                             break;
  1436.                     }
  1437.  
  1438.                     var1.mType = commonType;
  1439.                     valStack.pop_back();
  1440.                 }
  1441.             }
  1442.  
  1443.             expectValue = true;
  1444.  
  1445.             if (!op)
  1446.                 break;
  1447.  
  1448.             opStack.push_back(op);
  1449.         }
  1450.     }
  1451.  
  1452.     if (parenLevel)
  1453.         return mLexer.SetError("Unmatched '(' in expression");
  1454.  
  1455.     mLexer.Push();
  1456.  
  1457.     VDASSERT(valStack.size() == 1);
  1458.     value = valStack.back();
  1459.     return true;
  1460. }
  1461.  
  1462. bool VDFileCreatorParser::EmitExpressionI1() {
  1463.     VDFileCreatorValue value;
  1464.     if (!ParseExpression(value))
  1465.         return false;
  1466.     if (!value.ConvertToType(kTypeI1))
  1467.         return mLexer.SetError("Cannot convert value to type 'int8'");
  1468.     mpCreator->Emit8(kInsnLoadConstI4);
  1469.     mpCreator->Emit32(value.i4);
  1470.     return true;
  1471. }
  1472.  
  1473. bool VDFileCreatorParser::EmitExpressionI2() {
  1474.     VDFileCreatorValue value;
  1475.     if (!ParseExpression(value))
  1476.         return false;
  1477.     if (!value.ConvertToType(kTypeI2))
  1478.         return mLexer.SetError("Cannot convert value to type 'int16'");
  1479.     mpCreator->Emit8(kInsnLoadConstI4);
  1480.     mpCreator->Emit32(value.i4);
  1481.     return true;
  1482. }
  1483.  
  1484. bool VDFileCreatorParser::EmitExpressionI4() {
  1485.     VDFileCreatorValue value;
  1486.     if (!ParseExpression(value))
  1487.         return false;
  1488.     if (!value.ConvertToType(kTypeI4))
  1489.         return mLexer.SetError("Cannot convert value to type 'int32'");
  1490.     mpCreator->Emit8(kInsnLoadConstI4);
  1491.     mpCreator->Emit32(value.i4);
  1492.     return true;
  1493. }
  1494.  
  1495. bool VDFileCreatorParser::EmitExpressionI8() {
  1496.     VDFileCreatorValue value;
  1497.     if (!ParseExpression(value))
  1498.         return false;
  1499.     if (!value.ConvertToType(kTypeI8))
  1500.         return mLexer.SetError("Cannot convert value to type 'int64'");
  1501.     mpCreator->Emit8(kInsnLoadConstI8);
  1502.     mpCreator->Emit64(value.i8);
  1503.     return true;
  1504. }
  1505.  
  1506. bool VDFileCreatorParser::EmitExpressionU1() {
  1507.     VDFileCreatorValue value;
  1508.     if (!ParseExpression(value))
  1509.         return false;
  1510.     if (!value.ConvertToType(kTypeU1))
  1511.         return mLexer.SetError("Cannot convert value to type 'uint8'");
  1512.     mpCreator->Emit8(kInsnLoadConstI4);
  1513.     mpCreator->Emit32(value.i4);
  1514.     return true;
  1515. }
  1516.  
  1517. bool VDFileCreatorParser::EmitExpressionU2() {
  1518.     VDFileCreatorValue value;
  1519.     if (!ParseExpression(value))
  1520.         return false;
  1521.     if (!value.ConvertToType(kTypeU2))
  1522.         return mLexer.SetError("Cannot convert value to type 'uint16'");
  1523.     mpCreator->Emit8(kInsnLoadConstI4);
  1524.     mpCreator->Emit32(value.i4);
  1525.     return true;
  1526. }
  1527.  
  1528. bool VDFileCreatorParser::EmitExpressionU4() {
  1529.     VDFileCreatorValue value;
  1530.     if (!ParseExpression(value))
  1531.         return false;
  1532.     if (!value.ConvertToType(kTypeU4))
  1533.         return mLexer.SetError("Cannot convert value to type 'uint32'");
  1534.     mpCreator->Emit8(kInsnLoadConstI4);
  1535.     mpCreator->Emit32(value.i4);
  1536.     return true;
  1537. }
  1538.  
  1539. bool VDFileCreatorParser::EmitExpressionU8() {
  1540.     VDFileCreatorValue value;
  1541.     if (!ParseExpression(value))
  1542.         return false;
  1543.     if (!value.ConvertToType(kTypeU8))
  1544.         return mLexer.SetError("Cannot convert value to type 'uint64'");
  1545.     mpCreator->Emit8(kInsnLoadConstI8);
  1546.     mpCreator->Emit64(value.i8);
  1547.     return true;
  1548. }
  1549.  
  1550. bool VDFileCreatorParser::EmitExpressionR4() {
  1551.     VDFileCreatorValue value;
  1552.     if (!ParseExpression(value))
  1553.         return false;
  1554.     if (!value.ConvertToType(kTypeR4))
  1555.         return mLexer.SetError("Cannot convert value to type 'float'");
  1556.     mpCreator->Emit8(kInsnLoadConstR8);
  1557.     mpCreator->EmitR8(value.r8);
  1558.     return true;
  1559. }
  1560.  
  1561. bool VDFileCreatorParser::EmitExpressionR8() {
  1562.     VDFileCreatorValue value;
  1563.     if (!ParseExpression(value))
  1564.         return false;
  1565.     if (!value.ConvertToType(kTypeR8))
  1566.         return mLexer.SetError("Cannot convert value to type 'double'");
  1567.     mpCreator->Emit8(kInsnLoadConstR8);
  1568.     mpCreator->EmitR8(value.r8);
  1569.     return true;
  1570. }
  1571.  
  1572. bool VDFileCreatorParser::EmitExpressionFCC() {
  1573.     VDFileCreatorValue value;
  1574.     if (!ParseExpression(value))
  1575.         return false;
  1576.  
  1577.     if (value.mType == kTypeS) {
  1578.         const char *s = value.s;
  1579.         int len = (int)strlen(s);
  1580.  
  1581.         if (len > 4)
  1582.             return mLexer.SetError("String too long for FOURCC");
  1583.  
  1584.         char buf[4]={' ', ' ', ' ', ' '};
  1585.         memcpy(buf, s, len);
  1586.  
  1587.         value.i4 = *(uint32 *)buf;
  1588.     } else if (!value.ConvertToType(kTypeU4))
  1589.         return mLexer.SetError("Cannot convert value to FOURCC");
  1590.  
  1591.     mpCreator->Emit8(kInsnLoadConstI4);
  1592.     mpCreator->Emit32(value.i4);
  1593.     return true;
  1594. }
  1595.  
  1596. void VDFileCreatorParser::Collect() {
  1597.     while(!mTempStrings.empty()) {
  1598.         const char *s = mTempStrings.back();
  1599.         mTempStrings.pop_back();
  1600.         delete[] s;
  1601.     }
  1602. }
  1603.  
  1604. ///////////////////////////////////////////////////////////////////////////////
  1605.  
  1606. class VDCompilerLogOutputStdout : public IVDCompilerLogOutput {
  1607. public:
  1608.     void WriteLogOutput(const char *s) {
  1609.         fputs(s, stdout);
  1610.     }
  1611. };
  1612.  
  1613. void tool_filecreate(const vdfastvector<const char *>& args, const vdfastvector<const char *>& switches) {
  1614.     if (args.size() != 2) {
  1615.         puts("usage: asuka filecreate source.filescript target.bin");
  1616.         exit(5);
  1617.     }
  1618.     const char *fnin = args[0];
  1619.     const char *fnout = args[1];
  1620.  
  1621.     VDFile file(fnin);
  1622.     vdfastvector<char> buf((uint32)file.size());
  1623.     file.read(buf.data(), buf.size());
  1624.     file.close();
  1625.  
  1626.     VDFileCreatorParser parser;
  1627.     VDCompilerLogOutputStdout out;
  1628.  
  1629.     vdrefptr<IVDFileCreator> creator;
  1630.     if (!parser.Parse(buf.data(), buf.size(), fnin, &out, ~creator))
  1631.         exit(5);
  1632.  
  1633.     creator->Create(VDTextAToW(fnout).c_str());
  1634. }
  1635.