Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. byte Directives={
  2.         "IF","ELSE","ENDIF",    // Условная компиляция
  3.         "INCLUDE","DEFINE", // Включение файла/Определение константы
  4.         "IMPORT",       // Импорт из DLL по имени API
  5.         "IMPORTN",              // Импорт из DLL по номеру API
  6.         "MAP",                  // Генерация MAP-файла
  7.         "DEBUG",                // Генерация отладочной информации
  8.         "LIST",                 // Выдача ASM-листинга
  9.         "DLL",                  // Генерация DLL-файла
  10.         "DB","DW","DD",         // Типы переменных
  11.         "BYTE","CHAR","WORD","SHORT","DWORD","INT",
  12.         "ENUM",                 // Нумерованные константы
  13.         "STRUC",                // Определение структуры
  14.         "CYCLE","RETURN",
  15.         "WHILE","DO","INLINE",
  16.         "CONTINUE","BREAK",
  17.         "DOCASE","CASE","DEFAULT",
  18.         "CARRYFLAG","EXTRACT","FROM",
  19.         "NOTCARRYFLAG","NOTOVERFLOW","OVERFLOW",
  20.         "ZEROFLAG","NOTZEROFLAG",_END};
  21. // ----- Для tokens, НЕ обрабатываемых через таблицу переключателей
  22. EMPTY()
  23. {
  24.         WRITESTR(#string);
  25.         WRITESTR("-ToDo\n");
  26.         NextTok();
  27. }
  28.  
  29. // ---- Возвращает адрес из Jmp_....
  30. dword GetDirAddr(dword table,num)
  31. {
  32.         EAX=num<<2+table;
  33.         EAX=DSDWORD[EAX];
  34. }
  35.  
  36. // ----- Директива #define
  37. DirDefine()
  38. byte holdid[IDLENGTH];
  39. dword next;
  40. {
  41.         next=1;
  42.         NextTok();
  43.         if(tok==tk_id){
  44.                 lstrcpyA(#holdid,#string);      // Имя константы
  45.                 NextTok();
  46.                 IF(tok==tk_eof)  unexpectedeof();
  47.                 ELSE IF(tok==tk_number){
  48.                         AddConstToTree(#holdid,DoConstLongMath()); next = 0;
  49.                 }
  50.                 ELSE IF(tok==tk_minus){
  51.                         IF(tok2==tk_number) {
  52.                                 AddConstToTree(#holdid,DoConstLongMath());
  53.                                 next = 0;
  54.                         }
  55.                 }
  56.                 ELSE IF(tok==tk_undefproc){
  57.                         tok = tk_id; AddToTree(#holdid);
  58.                 }
  59.                 ELSE    AddToTree(#holdid);
  60.         }
  61.         ELSE idexpected();
  62.         IF(next)NextTok();
  63. }
  64.  
  65. // -- #enum
  66. DirEnum()
  67. dword counter;
  68. byte holdid[IDLENGTH];
  69. {
  70.         counter=0;
  71.         NextTok();
  72.         IF(tok!=tk_openbrace)expected('{');
  73.         for(;;){
  74.                 NextTok();
  75.                 IF(tok==tk_id){
  76.                         lstrcpyA(#holdid,#string);
  77.                         IF( tok2 == tk_assign ){
  78.                                 NextTok(); NextTok();
  79.                                 IF(tok==tk_number)counter=DoConstLongMath();
  80.                                 ELSE numexpected();
  81.                         }
  82.                         AddConstToTree(#holdid,counter);
  83.                         counter++;
  84.                         CONTINUE;
  85.                 }
  86.                 IF(tok==tk_comma)CONTINUE;
  87.                 IF(tok==tk_semicolon)BREAK;
  88.         }
  89.         NextTok();
  90. }
  91.  
  92. // Директива #import
  93. DirImport()
  94. {
  95.         NextTok();
  96.         IF(tok==tk_string)GetImport(1);         // import по имени API-функций
  97.         ELSE stringexpected();
  98.         NextTok();
  99. }
  100.  
  101. // Директива #importN
  102. DirImportN()
  103. {
  104.         NextTok();
  105.         IF(tok==tk_string)GetImport(0);         // import по имени API-функций
  106.         ELSE stringexpected();
  107.         NextTok();
  108. }
  109.  
  110. // ---- Импорт из DLL
  111. GetImport(dword byName)
  112. dword dll;
  113. dword dllpos,base,export,fptr,i,nexports,nsect,delta;
  114. byte path[80],name[120];
  115. dword tok0,type0,src0,post0;
  116. dword number0;
  117. dword ord;
  118. dword pname1,pname2,j;
  119. {
  120.         pname1 = 0; ord=0; importFlag=1;
  121.         IF(DLLcount>=MAXDLLS)outofmemory2();
  122.         IF(SearchTree(#tok0,#type0,#src0,#post0,#string,#number0))return; // DLL уже импортирован
  123.         wsprintfA(#name,"%s",#string);
  124.         dll=_lopen(#name,0);
  125.         IF(dll== -1){
  126.                 GetSystemDirectoryA(#path,80);
  127.                 wsprintfA(#name,"%s\\%s",#path,#string);
  128.                 dll=_lopen(#name,0);
  129.                 IF(dll==-1) {
  130.                         unabletoopen(#string);
  131.                         return;
  132.                 }
  133.         }
  134.         nsect=0;
  135.         _llseek(dll,0x3c,0); _lread(dll,#fptr,4);
  136.         _llseek(dll,fptr+120,0); _lread(dll,#export,4); // Get export address
  137.         IF(export==0) {
  138.                 wsprintfA(#mapstr,"ERROR: No export directory in file %s.\n",#string);
  139.                 preerror(#mapstr); return;
  140.         }
  141.         _llseek(dll,fptr+6,0); _lread(dll,#nsect,2);                     // Number of sections
  142.         delta=export;
  143.         i=1;
  144.         while(i<=nsect){
  145.                 EAX=i; EAX--; EAX=EAX*40; EAX+=260; EAX+=fptr;  // fptr+260+40*(i-1)
  146.                 _llseek(dll,EAX,0); _lread(dll,#base,4); // RVA of section
  147.                 IF(base<=export){
  148.                         EAX=export-base;
  149.                         IF(EAX<delta){
  150.                                 delta=export-base;
  151.                                 EAX=i; EAX--; EAX=EAX*40; EAX+=268; EAX+=fptr;  // fptr+268+40*(i-1)
  152.                                 _llseek(dll,EAX,0); _lread(dll,#dllpos,4);
  153.                         }
  154.                 }
  155.                 i++;
  156.         }
  157.         dllpos = dllpos + delta;         // filepos for export directory table
  158.         delta = dllpos - export;
  159.         _llseek(dll,dllpos+24,0); _lread(dll,#nexports,4);              // number of entries for export
  160.         _llseek(dll,dllpos+32,0); _lread(dll,#base,4);          // address of export name pointer table
  161.         _llseek(dll,dllpos+36,0); _lread(dll,#fptr,4);// address of Ordinal Table
  162.         base=base+delta; fptr=fptr+delta;
  163.         tok0=tok; number0=number;src0=src;type0=type;post0=post;
  164.         tok=tk_DLL; number=nexports;src=NULL; type=byName; post=0; modline=0;
  165.         AddToTree(#string);
  166.         EBX=DLLcount; EBX<<=2;
  167.         DLLlist[EBX] = treeptr;         // save ptr in tree
  168.         tok=tk_API; type=treeptr;
  169.         i=0;
  170.         while(nexports-1>i){
  171.                 EAX=i; EAX<<=1; EAX+=fptr;      // fptr+2*i
  172.                 _llseek(dll,EAX,0); _lread(dll,#ord,2);// Ordinal number
  173.                 EAX=i; EAX<<=2; EAX+=base;      // base+4*i
  174.                 _llseek(dll,EAX,0); _lread(dll,#pname1,8);      // address of name
  175.                 _llseek(dll,pname1+delta,0); _lread(dll,#string,pname2-pname1);// address of Ordinal Table
  176.                  number=ord+1;  // при загрузке используется номер на 1 больше экспортируемого из DLL
  177.                  AddToTree(#string);
  178. //       SHOW(#string);SHOW("\n");
  179.                  i++;
  180.         }
  181.         EAX=i; EAX<<=1; EAX+=fptr;      // fptr+2*i
  182.         _llseek(dll,EAX,0); _lread(dll,#ord,2); // Ordinal number
  183.         j=0;
  184.         for(;;){
  185.                 _llseek(dll,pname2+delta+j,0); EAX=j;
  186.                 _lread(dll,#string[EAX],1); EAX=j;
  187.                 IF(string[EAX]==0)BREAK;
  188.                 j++;
  189.         }
  190.         number=ord+1;
  191.         AddToTree(#string);
  192.         tok=tok0; number=number0;src=src0;type=type0;post=post0;
  193.         _lclose(dll);
  194.         DLLcount++; importFlag=0;
  195. }
  196.  
  197. // ----- Директива #include
  198. DirInclude()
  199. byte s[STRLEN],s2[STRLEN];
  200. {
  201.         NextTok();
  202.         if(tok==tk_string) {
  203.                 AL=cha2;
  204.                 $PUSH EAX,linenum2,inptr2,number,tok2,tok,input,inptr,endoffile,
  205.                                 displaytokerrors,currmod;
  206.                 lstrcpyA(#s,#string); lstrcpyA(#s2,#string2);
  207.                 Preview(#s);
  208.                 lstrcpyA(#string,#s); lstrcpyA(#string2,#s2);
  209.                 $POP currmod,displaytokerrors,endoffile,inptr,input,tok,tok2,number,inptr2,
  210.                         linenum2,EAX;
  211.                 cha2=AL;
  212.                 NextTok();
  213.         }
  214.         ELSE stringexpected();
  215. }
  216.  
  217. // ----- Директива list
  218. DirList()
  219. {
  220.         IF(mapfile==0){
  221.                 makemapfile=1;
  222.                 StartMapfile();
  223.         }
  224.         list^=1;                // Переключение вывода листинга
  225.         NextTok();
  226. }
  227.  
  228. // ----- Директива map
  229. DirMap()
  230. {
  231.         makemapfile = 1; StartMapfile();
  232.         NextTok();
  233. }
  234.  
  235. // ---- Обработка глобальной переменной или процедуры с типом
  236. GetProc(dword vartype)
  237. dword src0,beg,count;
  238. byte var_name[IDLENGTH];
  239. {
  240.         lstrcpyA(#var_name,#string);    // Имя процедуры
  241.         beg=inptr2;     // отметим начало описания
  242.         count=0; EAX=0;         // ищем начало блока процедуры
  243.         modline=currmod<<16+linenum2;
  244.         for(;;){
  245.                 ESI><inptr2;
  246.                 $LODSB;
  247.                 ESI><inptr2;
  248.                 cha2=AL;
  249.                 IF(AL==0){
  250.                         unexpectedeof();
  251.                         return;
  252.                 }
  253.                 IF(AL==13){     // CR
  254.                         linenum2++; // Обнаружен конец строки
  255.                         totallines++;
  256.                         CONTINUE;
  257.                 }
  258.                 IF(AL=='{'){    // список инициализации
  259.                         count++;
  260.                         BREAK;
  261.                 }
  262.         }
  263.         for(;;){
  264.                 ESI><inptr2;
  265.                 $LODSB;
  266.                 ESI><inptr2;
  267.                 cha2=AL;
  268.                 IF(AL==0){
  269.                         unexpectedeof();
  270.                         break;
  271.                 }
  272.                 IF(AL==13){     // CR
  273.                         linenum2++; // Обнаружен конец строки
  274.                         totallines++;
  275.                 }
  276.                 else if(AL=='}'){       // блок закрыт
  277.                         count--;
  278.                         IF(count==0){ // конец процедуры
  279.                                 ESI><inptr2;
  280.                                 $LODSB;
  281.                                 ESI><inptr2;
  282.                                 cha2=AL;        // замыкающая }
  283.                                 src0=LocalAlloc(0x40,inptr2-beg+2); // копируем исх.текст
  284.                                 EAX=src0;
  285.                                 DSBYTE[EAX]='(';
  286.                                 lstrcpynA(src0+1,beg,inptr2-beg);
  287.                                 tok=tk_proc;
  288.                                 type=vartype;
  289.                                 src=src0;
  290.                                 number=0;
  291.                                 post=1;
  292.                                 AddToTree(#var_name);
  293.                                 BREAK;
  294.                         }
  295.                 }
  296.                 ELSE IF(AL=='{'){       // список инициализации
  297.                         count++;
  298.                 }
  299.         }
  300.         NextTok();
  301. }
  302.  
  303. // ---- Обработка глобальной переменной или процедуры с типом
  304. GetVar(dword vartype)
  305. dword src0,beg,end,count,size;
  306. byte var_name[IDLENGTH];
  307. {
  308.         beg=inptr;
  309.         modline=0;              // отметим начало описания
  310.         NextTok();
  311.         IF(tok2==tk_openbracket){ // Объявление функции: type FunctionName(...)
  312.                 GetProc(vartype);
  313.                 return;
  314.         }
  315.         for(;;){                // Объявление переменной
  316.                 IF(tok==tk_semicolon){  // Конец определения переменной
  317.                         tok=tk_var;
  318.                         type=vartype;
  319.                         src=src0;
  320.                         number=0;
  321.                         post=1;
  322.                         AddToTree(#var_name);
  323.                         break;
  324.                 }
  325.                 IF(tok==tk_comma){              // список переменных
  326.                         tok=tk_var;
  327.                         type=vartype;
  328.                         src=src0;
  329.                         number=0;
  330.                         post=1;
  331.                         AddToTree(#var_name);
  332.                         NextTok();
  333.                 }
  334.                 else IF(tok==tk_id){                    //      tk_id
  335.                         src0=NULL;
  336.                         beg=inptr2;
  337.                         size=0;
  338.                         lstrcpyA(#var_name,#string);    // Имя переменной
  339.                         number=0;
  340.                         tok=tk_var;
  341.                         type=vartype;
  342.                         post=1;
  343.                         NextTok();
  344.                 }
  345.                 else if(tok==tk_assign)||(tok==tk_openblock){
  346.                         inptr2--;
  347.                         count=0;
  348.                         EAX=0;
  349.                         for(;;){
  350.                                 ESI><inptr2;
  351.                                 $LODSB;
  352.                                 ESI><inptr2;
  353.                                 cha2=AL;
  354.                                 IF(AL==0){
  355.                                         unexpectedeof();
  356.                                         break;
  357.                                 }
  358.                                 IF(AL=='"'){
  359.                                         ESI><inptr2;
  360.                                         do{
  361.                                                 $LODSB;
  362.                                         }while(AL!='"');
  363.                                         ESI><inptr2;
  364.                                         cha2=AL;
  365.                                 }
  366.                                 else IF(AL==',')||(AL==';'){
  367.                                         IF(count==0){
  368.                                                 end=inptr2;
  369.                                                 src0 = LocalAlloc(0x40,end-beg+2);
  370.                                                 IF(size){
  371.                                                         EAX=src0;
  372.                                                         DSBYTE[EAX]='[';
  373.                                                         lstrcpynA(src0+1,beg,end-beg);
  374.                                                 }
  375.                                                 ELSE lstrcpynA(src0,beg,end-beg);
  376.                                                 modline=currmod<<16+linenumber;
  377.                                                 BREAK;
  378.                                         }
  379.                                 }
  380.                                 ELSE IF(AL=='}'){       // список закончен
  381.                                         count--;
  382.                                 }
  383.                                 ELSE IF(AL=='{'){       // список инициализации
  384.                                         count++;
  385.                                 }
  386.                                 IF(AL==']'){    // размерность
  387.                                         size++;
  388.                                 }
  389.                         }
  390.                         NextTok();
  391.                 }
  392.         }
  393.         NextTok();
  394. }
  395.  
  396. // ---- Объявление типа данных
  397. CmdByte()
  398. {
  399.         GetVar(tk_byte);
  400. }
  401.  
  402. CmdChar()
  403. {
  404.         GetVar(tk_char);
  405. }
  406.  
  407. CmdWord()
  408. {
  409.         GetVar(tk_word);
  410. }
  411.  
  412. CmdShort()
  413. {
  414.         GetVar(tk_short);
  415. }
  416.  
  417. CmdDword()
  418. {
  419.         GetVar(tk_dword);
  420. }
  421.  
  422. CmdInt()
  423. {
  424.         GetVar(tk_int);
  425. }
  426.  
  427. // ----  break;
  428. CmdBreak()
  429. {
  430.         wsprintfA(#mapstr,"jmp @L%d",endlabel);
  431.         Asm(#mapstr);
  432.         NextSemiNext();
  433. }
  434.  
  435. // ---- case(Cond) ...
  436. CmdCase()
  437. dword loclabel;
  438. {
  439.         NextTok();
  440.         expecting(tk_openbracket);
  441.         loclabel=label;
  442.         label++;
  443.         relation=0;
  444.         if(tok==tk_command){
  445.                 GetDirAddr(#Jmp_Commands,number);
  446.                 IF(EAX==#CmdCarryFlag)wsprintfA(#mapstr,"jnc @L%d",loclabel);
  447.                 else IF(EAX==#CmdNotCarryFlag)wsprintfA(#mapstr,"jc @L%d",loclabel);
  448.                 ELSE IF(EAX==#CmdZeroFlag)wsprintfA(#mapstr,"jnz @L%d",loclabel);
  449.                 ELSE IF(EAX==#CmdNotZeroFlag)wsprintfA(#mapstr,"jz @L%d",loclabel);
  450.                 ELSE IF(EAX==#CmdOverflow)wsprintfA(#mapstr,"jno @L%d",loclabel);
  451.                 ELSE IF(EAX==#CmdNotOverflow)wsprintfA(#mapstr,"jo @L%d",loclabel);
  452.                 NextTok();
  453.         }
  454.         ELSE{
  455.                 IF(Expression("eax",tk_reg,tk_dword))wsprintfA(loclabel,"test eax,eax;jnz @L%d",#mapstr);
  456.                 ELSE wsprintfA(#mapstr,"test eax,eax;jz @L%d",loclabel);
  457.         }
  458.         Asm(#mapstr);
  459.         expecting(tk_closebracket);
  460.         DoCommand();
  461.         wsprintfA(#mapstr,"jmp @L%d",endlabel);
  462.         Asm(#mapstr);
  463.         wsprintfA(#mapstr,"@L%d:",loclabel);
  464.         Asm(#mapstr);
  465. }
  466.  
  467. // ---- continue;
  468. CmdContinue()
  469. {
  470.         wsprintfA(#mapstr,"jmp @L%d",startlabel);
  471.         Asm(#mapstr); NextSemiNext();
  472. }
  473.  
  474. // ---- cycle(Var) ...
  475. CmdCycle()
  476. byte varName[2*IDLENGTH];
  477. {
  478.         NextTok();
  479.         expecting(tk_openbracket);
  480.         $PUSH startlabel,endlabel;
  481.         startlabel=label;
  482.         label++;
  483.         endlabel=label;
  484.         label++;
  485.         relation=0;
  486.         wsprintfA(#mapstr,"@L%d:",startlabel);
  487.         Asm(#mapstr);
  488.         GetVarname(#varName);
  489.         NextTok();
  490.         expecting(tk_closebracket);
  491.         DoCommand();
  492.         IF(varName[0]==0){      // Счетчик цикла отсутствует - бесконечный цикл
  493.                 wsprintfA(#mapstr,"jmp @L%d",startlabel);
  494.         }
  495.          ELSE{
  496.                 wsprintfA(#mapstr,"dec %s;jnz @L%d",#varName,startlabel);
  497.         }
  498.         Asm(#mapstr);
  499.         wsprintfA(#mapstr,"@L%d:",endlabel);
  500.         Asm(#mapstr);
  501.         $POP endlabel,startlabel;
  502. }
  503.  
  504. // ---- Флаги условий в if
  505. CmdCarryFlag()
  506. {
  507.         CmdNotCarryFlag:
  508.         CmdZeroFlag:
  509.         CmdNotZeroFlag:
  510.         CmdOverflow:
  511.         CmdNotOverflow:
  512. }
  513. // ---- ... else ...
  514. CmdElse()
  515. {
  516. }
  517.  
  518. // ---- Объявление нумерованных констант
  519. CmdEnum()
  520. dword counter;
  521. byte holdid[IDLENGTH];
  522. {
  523.         counter=0;
  524.         NextTok();
  525.         expecting(tk_openbrace);
  526.         for(;;){
  527.                 IF(tok==tk_eof)unexpectedeof();
  528.                 ELSE IF(tok==tk_comma)NextTok();
  529.                 ELSE IF(tok==tk_closebrace)BREAK;
  530.                 ELSE IF(tok==tk_id){
  531.                         lstrcpyA(#holdid,#string);
  532.                         IF(tok2==tk_assign ){
  533.                                 NextTok();
  534.                                 NextTok();
  535.                                 IF(tok==tk_number)counter=DoConstLongMath();
  536.                                 ELSE numexpected();
  537.                         }
  538.                         AddConstToTree(#holdid,counter);
  539.                         counter++;
  540.                         NextTok();
  541.                 }
  542.                 ELSE{
  543.                         idexpected();
  544.                         NextTok();
  545.                 }
  546.         }
  547.         expecting(tk_closebrace);
  548.         SemiNext();
  549. }
  550.  
  551. // ---- while(Cond) ...
  552. CmdWhile()
  553. {
  554.         NextTok();
  555.         expecting(tk_openbracket);
  556.         $PUSH startlabel,endlabel;
  557.         startlabel=label;
  558.         label++;
  559.         endlabel=label;
  560.         label++;
  561.         relation=0;
  562.         wsprintfA(#mapstr,"@L%d:",startlabel);
  563.         Asm(#mapstr);
  564.         if(tok==tk_command){
  565.                 GetDirAddr(#Jmp_Commands,number);
  566.                 IF(EAX==#CmdCarryFlag)wsprintfA(#mapstr,"jnc @L%d",endlabel);
  567.                 else IF(EAX==#CmdNotCarryFlag)wsprintfA(#mapstr,"jc @L%d",endlabel);
  568.                 else IF(EAX==#CmdZeroFlag)wsprintfA(#mapstr,"jnz @L%d",endlabel);
  569.                 ELSE IF(EAX==#CmdNotZeroFlag)wsprintfA(#mapstr,"jz @L%d",endlabel);
  570.                 ELSE IF(EAX==#CmdOverflow)wsprintfA(#mapstr,"jno @L%d",endlabel);
  571.                 ELSE IF(EAX==#CmdNotOverflow)wsprintfA(#mapstr,"jo @L%d",endlabel);
  572.                 NextTok();
  573.         }
  574.         ELSE{
  575.                 IF(Expression("eax",tk_reg,tk_dword))wsprintfA(#mapstr,"test eax,eax;jnz @L%d",endlabel);
  576.                 ELSE wsprintfA(#mapstr,"test eax,eax;jz @L%d",endlabel);
  577.         }
  578.         Asm(#mapstr);
  579.         expecting(tk_closebracket);
  580.         DoCommand();
  581.         wsprintfA(#mapstr,"jmp @L%d",startlabel);
  582.         Asm(#mapstr);
  583.         wsprintfA(#mapstr,"@L%d:",endlabel);
  584.         Asm(#mapstr);
  585.         $POP endlabel,startlabel;
  586. }
  587.  
  588. // ---- default
  589. CmdDefault()
  590. {
  591.         NextTok();
  592.         DoCommand();
  593. }
  594.  
  595. CmdDb()
  596. {
  597.         NextTok();
  598.         for(;;){
  599.                 IF(tok==tk_number)OP(byte DoConstLongMath());
  600.                 ELSE IF(tok==tk_string ){
  601.                         ECX=number;
  602.                         EDX=#string;
  603.                         loop(ECX){
  604.                                 OP(byte DSBYTE[EDX]);
  605.                                 EDX++;
  606.                         }
  607.                         NextTok();
  608.                 }
  609.                 ELSE IF(tok==tk_comma)NextTok();
  610.                 ELSE IF(tok==tk_semicolon)BREAK;
  611.                 ELSE{
  612.                         numexpected();
  613.                         NextTok();
  614.                 }
  615.         }
  616. }
  617.  
  618. CmdDd()
  619. {
  620.         NextTok();
  621.         for(;;){
  622.                 IF(tok==tk_number)OUTDWORD(DoConstDwordMath());
  623.                 ELSE IF(tok==tk_comma)NextTok();
  624.                 ELSE IF(tok==tk_semicolon)BREAK;
  625.                 ELSE{
  626.                         numexpected();
  627.                         NextTok();
  628.                 }
  629.         }
  630. }
  631.  
  632. CmdDw()
  633. {
  634.         NextTok();
  635.         for(;;){
  636.                 IF(tok==tk_number)OUTWORD(DoConstDwordMath());
  637.                 ELSE IF(tok==tk_comma)NextTok();
  638.                 ELSE IF(tok==tk_semicolon)BREAK;
  639.                 ELSE{
  640.                         numexpected();
  641.                         NextTok();
  642.                 }
  643.         }
  644. }
  645.  
  646. // ---- do ... while(Cond)
  647. CmdDo()
  648. {
  649.         NextTok();
  650.         $PUSH startlabel,endlabel;
  651.         startlabel=label;
  652.         label++;
  653.         endlabel=label;
  654.         label++;
  655.         relation=0;
  656.         wsprintfA(#mapstr,"@L%d:",startlabel);
  657.         Asm(#mapstr);
  658.         DoCommand();
  659.         if(tok==tk_command){
  660.                 if(GetDirAddr(#Jmp_Commands,number)==#CmdWhile){
  661.                         NextTok();
  662.                         expecting(tk_openbracket);
  663.                         if(tok==tk_command){
  664.                                 GetDirAddr(#Jmp_Commands,number);
  665.                                 IF(EAX==#CmdCarryFlag)wsprintfA(#mapstr,"jc @L%d",startlabel);
  666.                                 else IF(EAX==#CmdNotCarryFlag)wsprintfA(#mapstr,"jnc @L%d",startlabel);
  667.                                 else IF(EAX==#CmdZeroFlag)wsprintfA(#mapstr,"jz @L%d",startlabel);
  668.                                 ELSE IF(EAX==#CmdNotZeroFlag)wsprintfA(#mapstr,"jnz @L%d",startlabel);
  669.                                 ELSE IF(EAX==#CmdOverflow)wsprintfA(#mapstr,"jo @L%d",startlabel);
  670.                                 ELSE IF(EAX==#CmdNotOverflow)wsprintfA(#mapstr,"jno @L%d",startlabel);
  671.                                 NextTok();
  672.                         }
  673.                         ELSE{
  674.                                 IF(Expression("eax",tk_reg,tk_dword))wsprintfA(#mapstr,"test eax,eax;jz @L%d",startlabel);
  675.                                 ELSE wsprintfA(#mapstr,"test eax,eax;jnz @L%d",startlabel);
  676.                         }
  677.                         Asm(#mapstr);
  678.                         expecting(tk_closebracket);
  679.                 }
  680.                 ELSE{
  681. ER:
  682.                         preerror("'while' expected following 'do'");
  683.                 }
  684.         }
  685.         ELSE GOTO ER;
  686.         wsprintfA(#mapstr,"@L%d:",endlabel);
  687.         Asm(#mapstr);
  688.         $POP endlabel,startlabel;
  689. }
  690.  
  691. // ---- docase ...
  692. CmdDoCase()
  693. {
  694.         NextTok();
  695.         $PUSH startlabel,endlabel;
  696.         startlabel=label;
  697.         label++;
  698.         endlabel=label;
  699.         label++;
  700.         wsprintfA(#mapstr,"@L%d:",startlabel);
  701.         Asm(#mapstr);
  702.         DoCommand();
  703.         wsprintfA(#mapstr,"@L%d:",endlabel);
  704.         Asm(#mapstr);
  705.         $POP endlabel,startlabel;
  706. }
  707.  
  708. // ---- if(Cond) ...
  709. CmdIf()
  710. dword loclabel;
  711. {
  712.         NextTok();
  713.         expecting(tk_openbracket);
  714.         loclabel=label;
  715.         label++;
  716.         relation=0;
  717.         if(tok==tk_command){
  718.                 GetDirAddr(#Jmp_Commands,number);
  719.                 IF(EAX==#CmdCarryFlag)wsprintfA(#mapstr,"jnc @L%d",loclabel);
  720.                 else IF(EAX==#CmdNotCarryFlag)wsprintfA(#mapstr,"jc @L%d",loclabel);
  721.                 ELSE IF(EAX==#CmdZeroFlag)wsprintfA(#mapstr,"jnz @L%d",loclabel);
  722.                 ELSE IF(EAX==#CmdNotZeroFlag)wsprintfA(#mapstr,"jz @L%d",loclabel);
  723.                 ELSE IF(EAX==#CmdOverflow)wsprintfA(#mapstr,"jno @L%d",loclabel);
  724.                 ELSE IF(EAX==#CmdNotOverflow)wsprintfA(#mapstr,"jo @L%d",loclabel);
  725.                 NextTok();
  726.         }
  727.         ELSE{
  728.                 IF(Expression("eax",tk_reg,tk_dword))wsprintfA(#mapstr,"test eax,eax;jnz @L%d",loclabel);
  729.                 ELSE wsprintfA(#mapstr,"test eax,eax;jz @L%d",loclabel);
  730.         }
  731.         Asm(#mapstr);
  732.         expecting(tk_closebracket);
  733.         DoCommand();
  734.         IF(tok==tk_command){
  735.                 IF(GetDirAddr(#Jmp_Commands,number)==#CmdElse){
  736.                         wsprintfA(#mapstr,"jmp @L%d;\n@L%d:",label,loclabel);
  737.                         Asm(#mapstr);
  738.                         loclabel=label;
  739.                         label++;
  740.                         NextTok();
  741.                         DoCommand();
  742.                 }
  743.         }
  744.         wsprintfA(#mapstr,"@L%d:",loclabel);
  745.         Asm(#mapstr);
  746. }
  747.  
  748. // ---- return(Expr)
  749. CmdReturn()
  750. {
  751.         NextTok();
  752.         IF(tok==tk_openbracket){
  753.                 NextTok();
  754.                 IF(tok!=tk_closebracket){
  755.                         IF(returntype!=tk_void)Expression("eax",tk_reg,returntype);
  756.                 }
  757.                 expecting(tk_closebracket);
  758.         }
  759.         LeaveProc();
  760.         SemiNext();
  761. }
  762.  
  763. // ---- Объявление глобальной переменной
  764. GlobalVar(dword vartype)        // both initialized and unitialized combined
  765. dword size,elements,ptr;
  766. long i,count;
  767. {
  768.         ptr=treeptr;
  769.         elements=1;
  770.         size = TypeSize(vartype);
  771.         NextTok();
  772.         for(;;){
  773.                 IF(tok==tk_eof)goto G04;        //break;
  774.                 ELSE IF(tok==tk_semicolon)NextTok();
  775.                 else IF(tok==tk_assign)NextTok();
  776.                 else IF(tok==tk_plus)NextTok();
  777.                 else IF(tok==tk_openblock){     // type VarName[...]
  778.                         NextTok();
  779.                         elements = DoConstLongMath();
  780.                         expecting(tk_closeblock);
  781.                 }
  782.                 else if(tok==tk_number){        // type VarName=initvalue
  783.                         ESI=ptr;        // Откорректируем ранее сделанную запись
  784.                         DSDWORD[ESI+recnumber] = outptr-output+OptImageBase+OptBaseOfCode;
  785.                         DSDWORD[ESI+recpost] = 0;
  786. G01:
  787.                         IF(vartype==tk_byte)i=DoConstDwordMath();
  788.                         ELSE IF(vartype==tk_word)i=DoConstDwordMath();
  789.                         ELSE IF(vartype==tk_dword)i=DoConstDwordMath();
  790.                         ELSE i=DoConstLongMath();
  791.                         count=elements;
  792.                         loop(count){
  793.                                 IF(size==1)OP(byte i);
  794.                                 ELSE IF(size==2)OUTWORD(i);
  795.                                 ELSE IF(size==4)OUTDWORD(i);
  796.                         }
  797.                 }
  798.                 else IF(tok==tk_minus){
  799.                         NextTok();
  800.                         number=-number;
  801.                         goto G01;
  802.                 }
  803.                 else IF(tok==tk_string){
  804.                         ESI=ptr;        // Откорректируем ранее сделанную запись
  805.                         DSDWORD[ESI+recnumber] = outptr-output+OptImageBase+OptBaseOfCode;
  806.                         DSDWORD[ESI+recpost] = 0;
  807.                         count = 1;
  808.                         do{
  809.                                 i=number;
  810.                                 EDX=#string;
  811.                                 loop(i){
  812.                                         OP(byte DSBYTE[EDX]);
  813.                                         EDX++;
  814.                                         count++;
  815.                                 }
  816.                                 NextTok();
  817.                         }while(tok==tk_string);
  818.                         OP(byte 0);// count++;
  819.                         i=elements;
  820.                         i-=count;
  821.                         IF(i>0)loop(i)OP(byte 0);
  822.                 }
  823.                 else IF(tok==tk_from){
  824.                         NextTok();
  825.                         SHOW("count = DoFrom(1);\n");
  826.                         i=size*elements;
  827.                         i-=count;
  828.                         loop(i)OP(byte 0);
  829.                         NextTok();
  830.                 }
  831.                 else IF(tok==tk_extract){
  832.                         NextTok();
  833.                         SHOW("count = DoExtract(1);\n");
  834.                         i=size*elements;
  835.                         i-=count;
  836.                         loop(i)OP(byte 0);
  837.                 }
  838.                 else if(tok==tk_openbrace){ // varname={...};
  839.                         ESI=ptr;        // Откорректируем ранее сделанную запись
  840.                         DSDWORD[ESI+recnumber] = outptr-output+OptImageBase+OptBaseOfCode;
  841.                         DSDWORD[ESI+recpost] = 0;
  842.                         count = 0;
  843.                         NextTok();
  844.                         for(;;){
  845.                                 IF(tok==tk_closebrace)break;
  846.                                 ELSE IF(tok==tk_comma)NextTok();
  847.                                 else IF(tok==tk_plus)NextTok();
  848.                                 else IF(tok==tk_string){
  849.                                         i=number;
  850.                                         EDX=#string;
  851.                                         loop(i){
  852.                                                 OP(DSBYTE[EDX]);
  853.                                                 EDX++;
  854.                                                 count++;
  855.                                         }
  856.                                         IF(tok2!=tk_plus){
  857.                                                 OP(byte 0);
  858.                                                 count++;
  859.                                         }
  860.                                         NextTok();
  861.                                 }
  862.                                 else IF(tok==tk_postnumber){
  863.                                         SetPost(treeptr,POST_DATA);
  864.                                         OUTDWORD(number);
  865.                                         NextTok();
  866.                                 }
  867.                                 else IF(tok==tk_number){
  868. G02:
  869.                                         IF(vartype==tk_byte)OP(byte DoConstDwordMath());
  870.                                         ELSE IF(vartype==tk_word)OUTWORD(DoConstDwordMath());
  871.                                         ELSE IF(vartype==tk_char)OP(byte DoConstLongMath());
  872.                                         ELSE IF(vartype==tk_short) OUTWORD(DoConstLongMath());
  873.                                         ELSE IF(vartype==tk_dword) OUTDWORD(DoConstDwordMath());
  874.                                         ELSE IF(vartype==tk_int) OUTDWORD(DoConstLongMath());
  875.                                         count++;
  876.                                 }
  877.                                 ELSE IF(tok==tk_minus){
  878.                                         NextTok();
  879.                                         number=-number;
  880.                                         goto G02;
  881.                                 }
  882.                                 ELSE{
  883.                                         numexpected();
  884.                                         NextTok();
  885.                                 }
  886.                         }
  887.                         count=elements-count;
  888.                         IF(count>0){
  889.                                 loop(count){
  890.                                         IF(size==1)OP(byte 0);
  891.                                         ELSE IF(size==2)OUTWORD(0);
  892.                                         ELSE IF(size==4)OUTDWORD(0);
  893.                                 }
  894.                         }
  895.                 }
  896.                 ELSE{
  897. G04:
  898.                         ESI=ptr;
  899.                         DSDWORD[ESI+recnumber] = postsize;
  900.                         DSDWORD[ESI+recpost] = 1;
  901.                         postsize = elements * size + postsize;
  902.                         BREAK;
  903.                 }
  904.         }
  905. }
  906.  
  907. //===== Таблица переключателей директив
  908. dword Jmp_Directives={
  909. //      "if","else","endif",    // Условная компиляция
  910.         #EMPTY,#EMPTY,#EMPTY,
  911. //      "include","define", // Включение фа ла
  912.         #DirInclude,#DirDefine,
  913. //      "import",       // Импорт из DLL
  914.         #DirImport,
  915. //      "importN",              // Импорт из DLL
  916.         #DirImportN,
  917. //      "map",                  // Генерация MAP-файла
  918.         #DirMap,
  919. //      "debug",                // Генерация отладочной информации
  920.         #EMPTY,
  921. //      "list",                 // Выдача ASM-листинга
  922.         #DirList,
  923. //      "dll",                  // Генерация DLL-файла
  924.         #EMPTY,
  925. //      "db","dw","dd",         // Типы переменных
  926.         #EMPTY,#EMPTY,#EMPTY,
  927. //      "byte","char","word","short","dword","int",
  928.         #EMPTY,#EMPTY,#EMPTY,#EMPTY,#EMPTY,#EMPTY,
  929. //      "enum",                 // Нумерованные константы
  930.         #DirEnum,
  931. //      "struc",                // Определение структуры
  932.         #EMPTY,
  933. //      "cycle","return",
  934.         #EMPTY,#EMPTY,
  935. //      "while","do","inline",
  936.         #EMPTY,#EMPTY,#EMPTY,
  937. //      "continue","break",
  938.         #EMPTY,#EMPTY,
  939. //      "docase","case","default",
  940.         #EMPTY,#EMPTY,#EMPTY,
  941. //      "CARRYFLAG","extract","from",
  942.         #EMPTY,#EMPTY,#EMPTY,
  943. //      "NOTCARRYFLAG","NOTOVERFLOW","OVERFLOW",
  944.         #EMPTY,#EMPTY,#EMPTY,
  945. //      "ZEROFLAG","NOTZEROFLAG"
  946.         #EMPTY,#EMPTY
  947. };
  948. //===== Таблица переключателей команд
  949. dword Jmp_Commands={
  950. //      "if","else","endif",    // Условная компиляция
  951.         #CmdIf,#CmdElse,#EMPTY,
  952. //      "include","define", // Включение фа ла
  953.         #EMPTY,#EMPTY,
  954. //      "import","importN", // Импорт из DLL
  955.         #EMPTY,#EMPTY,
  956. //      "map",                  // Генерация MAP-файла
  957.         #EMPTY,
  958. //      "debug",                // Генерация отладочно  информации
  959.         #EMPTY,
  960. //      "list",                 // Выдача ASM-л стинга
  961.         #EMPTY,
  962. //      "dll",                  // Генерация DLL-файла
  963.         #EMPTY,
  964. //      "db","dw","dd",         // Типы переменных
  965.         #CmdDb,#CmdDw,#CmdDd,
  966. //      "byte","char","word","short","dword","int",
  967.         #CmdByte,#CmdChar,#CmdWord,#CmdShort,#CmdDword,#CmdInt,
  968. //      "enum",                 // Нумерованные константы
  969.         #CmdEnum,
  970. //      "struc",                // Определение структуры
  971.         #EMPTY,
  972. //      "cycle","return",
  973.         #CmdCycle,#CmdReturn,
  974. //      "while","do","inline",
  975.         #CmdWhile,#CmdDo,#EMPTY,
  976. //      "continue","break",
  977.         #CmdContinue,#CmdBreak,
  978. //      "docase","case","default",
  979.         #CmdDoCase,#CmdCase,#CmdDefault,
  980. //      "CARRYFLAG","extract","from",
  981.         #CmdCarryFlag,#EMPTY,#EMPTY,
  982. //      "NOTCARRYFLAG","NOTOVERFLOW","OVERFLOW",
  983.         #CmdNotCarryFlag,#CmdNotOverflow,#CmdOverflow,
  984. //      "ZEROFLAG","NOTZEROFLAG"
  985.         #CmdZeroFlag,#CmdNotZeroFlag
  986. };
  987.