home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Ami / source / utils.cpp < prev   
Encoding:
C/C++ Source or Header  |  2009-09-14  |  6.2 KB  |  234 lines

  1. #include <stdarg.h>
  2.  
  3. #include "utils.h"
  4. #include "lexer.h"
  5.  
  6. ///////////////////////////////////////////////////////////////////////////
  7. //
  8. //    utils
  9. //
  10. ///////////////////////////////////////////////////////////////////////////
  11.  
  12. std::string ANSIify(const std::wstring& unicode) {
  13.     std::string ansi;
  14.  
  15.     // ugh
  16.  
  17.     std::wstring::const_iterator it = unicode.begin(), itEnd = unicode.end();
  18.  
  19.     for(; it!=itEnd; ++it) {
  20.         char buf[8];
  21.  
  22.         int bytes = wctomb(buf, *it);
  23.  
  24.         if (bytes<0)
  25.             ansi += '?';
  26.         else
  27.             ansi.append(buf, bytes);
  28.     }
  29.  
  30.     return ansi;
  31. }
  32.  
  33. ///////////////////////////////////////////////////////////////////////////
  34. //
  35. //    error handling
  36. //
  37. ///////////////////////////////////////////////////////////////////////////
  38.  
  39. void warning(const char *format, ...) {
  40.     va_list val;
  41.  
  42.     printf("%s(%d) : warning: ", lexfilename(), lexlineno());
  43.     va_start(val, format);
  44.     vprintf(format, val);
  45.     va_end(val);
  46.     putchar('\n');
  47. }
  48.  
  49. void fatal(const char *format, ...) {
  50.     va_list val;
  51.  
  52.     printf("%s(%d): error: ", lexfilename(), lexlineno());
  53.     va_start(val, format);
  54.     vprintf(format, val);
  55.     va_end(val);
  56.     putchar('\n');
  57.  
  58.     exit(10);
  59. }
  60.  
  61. // :)
  62.  
  63. void fatal_internal(const char *fname, const int line) {
  64.     fatal("INTERNAL COMPILER ERROR\n"
  65.         "        (compiler file '%s', line %d)\n", fname, line);
  66. }
  67.  
  68.  
  69. namespace nsSCSU {
  70.     enum {
  71.         kSQx        = 0x01,        // 01-08 ch        Quote from window n
  72.  
  73.         kSDX        = 0x0B,        // 0B hb lb        Define extended
  74.  
  75.         kSQU        = 0x0E,        // 0E hb lb        Quote Unicode
  76.         kSCU        = 0x0F,        //                Switch to Unicode mode
  77.  
  78.         kSCx        = 0x10,        // 10-17        Change to window n
  79.         kSDx        = 0x18,        // 18-1F b        Define window n as OffsetTable[b]
  80.  
  81.         kUCx        = 0xE0,        // E0-E7        Change to window n
  82.         kUDx        = 0xE8,        // E8-EF b        Define window n as OffsetTable[b]
  83.         kUQU        = 0xF0,        // F0            Quote
  84.         kUDX        = 0xF1,        // F1            Define extended
  85.  
  86.     };
  87. }
  88.  
  89. // My SCSU encoder sucks, but oh well.  We deliberately use unsigned here
  90. // instead of wchar_t to head off possible wraparound issues when choosing
  91. // a window.
  92.  
  93. std::basic_string<unsigned char> ConvertToSCSU(const std::wstring& s) {
  94.     using namespace nsSCSU;
  95.  
  96.     std::wstring::const_iterator it = s.begin(), itEnd = s.end();
  97.     const unsigned static_windows[8]={0x0000,0x0080,0x0100,0x0300,0x2000,0x2080,0x2100,0x3000};
  98.     unsigned dynamic_windows[8]={0x0080,0x00c0,0x0400,0x0600,0x0900,0x3040,0x30A0,0xFF00};
  99.     int current_dynwnd = 0;
  100.     int next_redefine = 0;
  101.     std::basic_string<unsigned char> out;
  102.  
  103.     while(it!=itEnd) {
  104.         unsigned ch = *it;
  105.         unsigned lookahead = 0xFFFF0000;    // something not remotely close to anything else
  106.  
  107.         ++it;
  108.  
  109.         if (it != itEnd)
  110.             lookahead = *it;
  111.  
  112.         if (ch >= 0x10000)
  113.             fatal("Unicode surrogate characters are not supported");
  114.  
  115.         // Determine if the character can be encoded directly in static window 0.
  116.         // We can pass 00, 09, 0A, 0D, and 20-7F.
  117.  
  118.         if (ch < 0x100 && (ch >= 0x20 || (0x00002601UL & (1<<ch)))) {
  119.             out += (unsigned char)ch;
  120.         }
  121.  
  122.         // Try the current dynamic window.
  123.  
  124.         else if (ch >= dynamic_windows[current_dynwnd] && ch < dynamic_windows[current_dynwnd] + 0x80) {
  125.             out += (unsigned char)(0x80 + (ch - dynamic_windows[current_dynwnd]));
  126.         }
  127.  
  128.         // Check the static windows.
  129.  
  130.         else {
  131.             int i;
  132.  
  133.             for(i=0; i<8; ++i) {
  134.                 unsigned offset = (ch - static_windows[i]);
  135.  
  136.                 if (offset < 0x80) {        // unsigned comparison trick for 0 <= offset <= 0x80
  137.                     // If the next character is also from the same window, don't
  138.                     // use a static escape.  Instead, force a dynamic change.
  139.                     //
  140.                     // BTW, we can't do this for 00-7F since the window can't be placed that low....
  141.  
  142.                     if (i && !((lookahead ^ ch) & ~0x7f))
  143.                         goto force_dynamic;        // yeah, yeah
  144.  
  145.                     // Write a SQx tag followed by the offset.
  146.  
  147.                     out += (unsigned char)(kSQx + i);
  148.                     out += (unsigned char)offset;
  149.                     break;
  150.                 }
  151.             }
  152.  
  153.             if (i >= 8) {
  154.                 // Now check if one of the dynamic windows has the character we want.
  155.  
  156.                 for(i=0; i<8; ++i) {
  157.                     unsigned offset = (ch - dynamic_windows[i]);
  158.  
  159.                     if (offset < 0x80) {        // unsigned comparison trick for 0 <= offset <= 0x80
  160.  
  161.                         // If the next character is from the same window, do a dynamic
  162.                         // window switch, else do a quote.
  163.  
  164.                         if (lookahead >= dynamic_windows[i] && lookahead < dynamic_windows[i]+0x80) {
  165.                             out += (unsigned char)(kSCx + i);
  166.                             current_dynwnd = i;
  167.                         } else
  168.                             out += (unsigned char)(kSQx + i);
  169.  
  170.                         out += (unsigned char)(offset + 0x80);
  171.                         break;
  172.                     }
  173.                 }
  174.  
  175.                 if (i >= 8) {
  176. force_dynamic:
  177.                     // Okay, no window contains what we want.  Our solution: choose a dynamic
  178.                     // window in round-robin order, redefine it, and switch to it.  If we can't
  179.                     // shift a window into position, just quote it.  The characters we can't
  180.                     // window are U+3400 through U+BFFF.
  181.  
  182.                     unsigned new_window;
  183.                     unsigned char id;
  184.  
  185.                     if (ch >= 0x3400 && ch < 0xBFFF) {
  186.                         out += (unsigned char)(kSQU);
  187.                         out += (unsigned char)(ch>>8);
  188.                         out += (unsigned char)(ch&0xff);
  189.                         continue;
  190.                     } else if (ch >= 0x00c0 && ch < 0x0140) {
  191.                         new_window = 0x00c0;
  192.                         id = (unsigned char)0xF9;
  193.                     } else if (ch >= 0x0250 && ch < 0x02d0) {
  194.                         new_window = 0x0250;
  195.                         id = (unsigned char)0xFA;
  196.                     } else if (ch >= 0x0370 && ch < 0x03f0) {
  197.                         new_window = 0x0370;
  198.                         id = (unsigned char)0xFB;
  199.                     } else if (ch >= 0x0530 && ch < 0x05b0) {
  200.                         new_window = 0x0530;
  201.                         id = (unsigned char)0xFC;
  202.                     } else if (ch >= 0x3040 && ch < 0x30c0) {
  203.                         new_window = 0x3040;
  204.                         id = (unsigned char)0xFD;
  205.                     } else if (ch >= 0x30a0 && ch < 0x3120) {
  206.                         new_window = 0x30a0;
  207.                         id = (unsigned char)0xFE;
  208.                     } else if (ch >= 0xff60 && ch < 0xffe0) {
  209.                         new_window = 0xff60;
  210.                         id = (unsigned char)0xFF;
  211.                     } else if (ch <  0x3400) {
  212.                         new_window = ch & 0xff80;
  213.                         id = (unsigned char)(ch >> 7);
  214.                     } else {
  215.                         new_window = 0xff80;
  216.                         id = (unsigned char)((ch >> 7) - 0x158);
  217.                     }
  218.  
  219.                     out += (unsigned char)(kSDx + next_redefine);
  220.                     out += id;
  221.                     out += (unsigned char)(0x80 + (ch - new_window));
  222.  
  223.                     dynamic_windows[next_redefine] = new_window;
  224.  
  225.                     current_dynwnd = next_redefine;
  226.                     next_redefine = (next_redefine+1) & 7;
  227.                 }
  228.             }
  229.         }
  230.     }
  231.  
  232.     return out;
  233. }
  234.