wuc.c

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 
00005 #include "uctools.h"
00006 
00007 static opcode_desc push_table[]=
00008   {
00009     {"true",0,0x13},
00010     {"false",0,0x14},
00011     {"itemref",0,0x3e},
00012     {"eventid",0,0x48}
00013   };
00014 
00015 static opcode_desc pop_table[]=
00016   {
00017     {"eventid",0,0x4b}
00018   };
00019 
00020 static const char* compiler_table[]=
00021   {
00022     ".argc",
00023     ".extern",
00024     ".externsize",
00025     ".localc"
00026   };
00027 
00028 #define MAX_LABELS 3500
00029 #define TOKEN_LENGTH 25600
00030 
00031 char token[TOKEN_LENGTH],*token2,curlabel[256],indata;
00032 int byte,word,pass,offset,datasize,codesize,funcnum;
00033 int extended;
00034 
00035 char labels[MAX_LABELS][10];
00036 int offsets[MAX_LABELS];
00037 int lindex;
00038 
00039 FILE *fo,*fi;
00040 
00041 void emit_byte(int i)
00042 {
00043   if (pass>0)
00044     {
00045       fputc(i,fo);
00046       if (indata) datasize++;
00047     }
00048   offset++;
00049   codesize++;
00050 }
00051 
00052 void emit_word(int i)
00053 {
00054   emit_byte(i&0xff);
00055   emit_byte((i>>8)&0xff);
00056 }
00057 
00058 void emit_dword(int i)
00059 {
00060   emit_byte(i&0xff);
00061   emit_byte((i>>8)&0xff);
00062   emit_byte((i>>16)&0xff);
00063   emit_byte((i>>24)&0xff);
00064 }
00065 
00066 void add_label(void)
00067 {
00068   int i;
00069   if (token[strlen(token)-1]==':')
00070     token[strlen(token)-1]=0;
00071   if (lindex>=MAX_LABELS)
00072     {
00073       printf("Too many labels.\n");
00074       exit(0);
00075     }
00076   for (i=0;i<lindex;i++)
00077     {
00078       if (!strcasecmp(token,labels[i]))
00079         {
00080           printf("Warning: label '%s' already exists.\n",token);
00081           return;
00082         }
00083     }
00084   strcpy(labels[lindex],token);
00085   offsets[lindex++]=offset;
00086 }
00087 
00088 int get_label(void)
00089 {
00090   int i;
00091   for (i=0;i<lindex;i++)
00092     {
00093       if (!strcasecmp(token,labels[i]))
00094         return(offsets[i]);
00095     }
00096   printf("Warning: label '%s' does not exist.\n",token);
00097   if (token[0]=='L')
00098     sscanf(token,"L%x",&word);
00099   else
00100     sscanf(token,"%x",&word);
00101   return(word);
00102 }
00103 
00104 void check_jump_label_16(int label)
00105 {
00106   if (label < -32768 || label > 32767)
00107     printf("Warning: offset too big for 16 bit at label %s!\n", curlabel);
00108 }
00109 
00110 void check_data_label_16(int label)
00111 {
00112   if (label > 65535)
00113     printf("Warning: offset too big for 16 bit at label %s!\n", curlabel);
00114 }
00115 
00116 
00117 void read_token(FILE *fi)
00118 {
00119   int i=0,c=32;
00120   while (((c==' ') || (c=='\t') || (c=='\n') || (c==',')) && (!feof(fi)))
00121     c=fgetc(fi);
00122   while (!((c==' ') || (c=='\t') || (c=='\n') || (c==',')) && (!feof(fi)))
00123     {
00124       if (i >= TOKEN_LENGTH - 1) {
00125         fprintf(stderr, "Error: token too long!\n");
00126         exit(-1);
00127       }
00128       token[i++]=c;
00129       if (c==';')
00130         {
00131           while ((c=fgetc(fi))!='\n') /* do nothing */ ;
00132           i=0;
00133         }
00134       if (c==39)
00135         {
00136           while ((c=fgetc(fi))!='\n') {
00137             if (i >= TOKEN_LENGTH - 1) {
00138               fprintf(stderr, "Error: token too long!\n");
00139               exit(-1);
00140             }
00141             token[i++]=c;
00142           }
00143           ungetc(c,fi);
00144           i--;
00145         }
00146       c=fgetc(fi);
00147     }
00148           
00149   if (i >= TOKEN_LENGTH - 1) {
00150     fprintf(stderr, "Error: token too long!\n");
00151     exit(-1);
00152   }
00153   token[i]=0;
00154 }
00155 
00156 int main(int argc,char *argv[])
00157 {
00158   int i,opsize=sizeof(opcode_table)/sizeof(opcode_desc),
00159     pushsize=sizeof(push_table)/sizeof(opcode_desc),
00160     popsize=sizeof(pop_table)/sizeof(opcode_desc),
00161     compsize=sizeof(compiler_table)/sizeof(char*);
00162   int label;
00163   const char **func_table = bg_intrinsic_table;
00164   int funsize = bg_intrinsic_size;
00165   int findex = 1;     // Index in argv of 1st filename.
00166   unsigned int opcodetype;
00167   indata=codesize=datasize=0;
00168   /*  printf("Wody's Usecode Compiler v0.009\nCopyright (c) 1999 Wody "
00169     "Dragon (a.k.a. Wouter Dijkslag)\n");*/
00170   if (argc<3)
00171     {
00172       printf("syntax: %s [-s] infile outfile\n", argv[0]);
00173       exit(0);
00174     }
00175   // Serpent Isle?
00176   if (strcmp(argv[1], "-s") == 0)
00177     {
00178       findex++;
00179       func_table = si_intrinsic_table;
00180       funsize = si_intrinsic_size;
00181     }
00182 
00183   lindex=0;
00184   for (pass=0;pass<2;pass++)
00185     {
00186       //      printf("Pass %d\n",pass+1);
00187       if ((fi=fopen(argv[findex],"r"))==NULL)
00188         {
00189           printf("Can't open infile for reading\n");
00190           exit(0);
00191         }
00192       if ((fo=fopen(argv[findex + 1],"wb"))==NULL)
00193         {
00194           printf("Can't open outfile for writing\n");
00195           exit(0);
00196         }
00197       while (!feof(fi))
00198         {
00199           read_token(fi);
00200           if (strlen(token)>1 && token[strlen(token)-1]==':') {
00201             token[strlen(token)-1]=0; // remove trailing ':'
00202             if (pass == 0)
00203               add_label();
00204             strcpy(curlabel, token);
00205           }
00206           else if (!strcmp(token,".code"))
00207             {
00208               indata=0;
00209               offset=0;
00210             }
00211           else if (!strcmp(token,".data"))
00212             {
00213               if (extended == 0) {
00214                 emit_word(funcnum);
00215                 emit_word(0);
00216                 emit_word(0);
00217                 codesize = 2;
00218               } else {
00219                 emit_word(-1);
00220                 emit_word(funcnum);
00221                 emit_dword(0);
00222                 emit_dword(0);
00223                 codesize = 4;
00224               }
00225 
00226               indata=1;
00227               offset=0;
00228 
00229             }
00230           else if (!strcmp(token,".funcnumber"))
00231             {
00232               read_token(fi);
00233               sscanf(token,"%x",&funcnum);
00234               printf("Function %04X\n", funcnum);
00235               //              codesize=2;
00236               extended = 0;
00237             }
00238           else if (!strcmp(token,".ext32"))
00239             {
00240               extended = 1;
00241             }
00242           else if (token[0]=='.')
00243             {
00244               indata=0;
00245               for (i=0;i<compsize;i++)
00246                 if (!strcasecmp(compiler_table[i],token))
00247                   {
00248                     read_token(fi);
00249                     sscanf(token,"%x",&word);
00250                     emit_word(word);
00251                   }
00252             }
00253           else if (!strcmp(token,"db"))
00254             {
00255               read_token(fi);
00256               if (token[0]==39)
00257                 for (i=1;i<strlen(token);i++)
00258                   emit_byte(token[i]);
00259               else
00260                 {
00261                   sscanf(token,"%x",&byte);
00262                   emit_byte(byte);
00263                 }
00264             }
00265           else if (!strcasecmp(token,"dw"))
00266             {
00267               read_token(fi);
00268               sscanf(token,"%x",&word);
00269               emit_word(word);
00270             }
00271           else
00272             for (i=0;i<opsize;i++)
00273               {
00274                 if (!opcode_table[i].mnemonic) continue;
00275                 if (!strcasecmp(opcode_table[i].mnemonic,token))
00276                   {
00277                     if (opcode_table[i].nbytes==0 && opcode_table[i].type==0)
00278                       emit_byte(i);
00279                     else {
00280                       opcodetype = opcode_table[i].type;
00281                       if (i == 0x21) opcodetype = PUSH;
00282                       if (i == 0x12) opcodetype = POP;
00283                       switch (opcodetype)
00284                         {
00285                         case BYTE:
00286                           emit_byte(i);
00287                           read_token(fi);
00288                           sscanf(token,"%x",&word);
00289                           emit_byte(word);
00290                           break;
00291                         case CALL:
00292                           emit_byte(i);
00293                           read_token(fi);
00294                           if ((token2=strchr(token,'@'))!=NULL)
00295                             {
00296                               token2++;
00297                               read_token(fi);
00298                               sscanf(token, "(%x)", &word);
00299                               emit_word(word);
00300                               sscanf(token2,"%d",&word);
00301                             }
00302                           else
00303                             {
00304                               sscanf(token,"%x",&word);
00305                               emit_word(word);
00306                               read_token(fi);
00307                               sscanf(token,"%d",&word);
00308                             }
00309                           emit_byte(word);
00310                           break;
00311                         case DATA_STRING:
00312                           emit_byte(i);
00313                           read_token(fi);
00314                           label = get_label();
00315                           check_data_label_16(label);
00316                           emit_word(label);
00317                           break;
00318                         case DATA_STRING32:
00319                           emit_byte(i);
00320                           read_token(fi);
00321                           emit_dword(get_label());
00322                           break;
00323                         case EXTCALL:
00324                         case VARREF:
00325                           emit_byte(i);
00326                           read_token(fi);
00327                           sscanf(token,"[%x]",&word);
00328                           emit_word(word);
00329                           break;
00330                         case FLGREF:
00331                           emit_byte(i);
00332                           read_token(fi);
00333                           sscanf(token,"flag:[%x]",&word);
00334                           emit_word(word);
00335                           break;
00336                         case PUSH:
00337                           read_token(fi);
00338                           for (i=0;i<pushsize;i++)
00339                             {
00340                               if (!strcasecmp(push_table[i].mnemonic,token))
00341                                 {
00342                                   emit_byte(push_table[i].type);
00343                                   break;
00344                                 }
00345                             }
00346                           if (i==pushsize)
00347                             {
00348                               emit_byte(0x21);
00349                               sscanf(token,"[%x]",&word);
00350                               emit_word(word);
00351                             }
00352                           break;
00353                         case POP:
00354                           read_token(fi);
00355                           for (i=0;i<popsize;i++)
00356                             {
00357                               if (!strcasecmp(pop_table[i].mnemonic,token))
00358                                 {
00359                                   emit_byte(pop_table[i].type);
00360                                   break;
00361                                 }
00362                             }
00363                           if (i==popsize)
00364                             {
00365                               emit_byte(0x12);
00366                               sscanf(token,"[%x]",&word);
00367                               emit_word(word);
00368                             }
00369                           break;
00370                         case IMMED:
00371                           emit_byte(i);
00372                           read_token(fi);
00373                           sscanf(token,"%x",&word);
00374                           emit_word(word);
00375                           break;
00376                         case IMMED32:
00377                           emit_byte(i);
00378                           read_token(fi);
00379                           sscanf(token,"%x",&word);
00380                           emit_dword(word);
00381                           break;
00382                         case RELATIVE_JUMP:
00383                           emit_byte(i);
00384                           read_token(fi);
00385                           if (pass==1) {
00386                             //                            printf("%x, %x, %x\n", get_label(), offset, get_label() - offset-2);
00387                             label = get_label() - offset - 2;
00388                             check_jump_label_16(label);
00389                             emit_word(label);
00390                           } else
00391                             emit_word(-1);
00392                           break;
00393                         case RELATIVE_JUMP32:
00394                           emit_byte(i);
00395                           read_token(fi);
00396                           if (pass==1) {
00397                             //                            printf("%x, %x, %x\n", get_label(), offset, get_label() - offset-2);
00398                             emit_dword(get_label()-offset-4);
00399                           } else
00400                             emit_dword(-1);
00401                           break;
00402                         case IMMED_AND_RELATIVE_JUMP:
00403                           emit_byte(i);
00404                           read_token(fi);
00405                           sscanf(token,"%x",&word);
00406                           emit_word(word);
00407                           read_token(fi);
00408                           if (pass==1) {
00409                             label = get_label() - offset - 2;
00410                             check_jump_label_16(label);
00411                             emit_word(label);
00412                           } else
00413                             emit_word(-1);
00414                           break;
00415                         case IMMED_RELJUMP32:
00416                           emit_byte(i);
00417                           read_token(fi);
00418                           sscanf(token,"%x",&word);
00419                           emit_word(word);
00420                           read_token(fi);
00421                           if (pass==1)
00422                             emit_dword(get_label()-offset-4);
00423                           else
00424                             emit_dword(-1);
00425                           break;
00426                         case SLOOP:
00427 #if 0
00428                           emit_byte(0x2E);
00429                           if (pass == 0) {
00430                             sscanf(curlabel, "%x:",&word);
00431                             sprintf(token,"%04X:",word+1);
00432                             printf("adding sloop label %s (curlabel=%s)\n", token, curlabel);
00433                             add_label();
00434                           }
00435 #endif
00436                           emit_byte(0x02);
00437                           read_token(fi);
00438                           sscanf(token,"[%x]",&word);
00439                           emit_word(word);
00440                           read_token(fi);
00441                           sscanf(token,"[%x]",&word);
00442                           emit_word(word);
00443                           read_token(fi);
00444                           sscanf(token,"[%x]",&word);
00445                           emit_word(word);
00446                           read_token(fi);
00447                           sscanf(token,"[%x]",&word);
00448                           emit_word(word);
00449                           read_token(fi);
00450                           sscanf(token,"%x",&word);
00451                           if (pass==1) {
00452                             label = get_label() - offset - 2;
00453                             check_jump_label_16(label);
00454                             emit_word(label);
00455                           } else
00456                             emit_word(-1);
00457                           break;
00458                         case SLOOP32:
00459 #if 0
00460                           emit_byte(0xAE);
00461                           if (pass == 0) {
00462                             sscanf(curlabel, "%x:",&word);
00463                             sprintf(token,"%04X:",word+1);
00464                             printf("adding sloop label %s (curlabel=%s)\n", token, curlabel);
00465                             add_label();
00466                           }
00467 #endif
00468                           emit_byte(0x82);
00469                           read_token(fi);
00470                           sscanf(token,"[%x]",&word);
00471                           emit_word(word);
00472                           read_token(fi);
00473                           sscanf(token,"[%x]",&word);
00474                           emit_word(word);
00475                           read_token(fi);
00476                           sscanf(token,"[%x]",&word);
00477                           emit_word(word);
00478                           read_token(fi);
00479                           sscanf(token,"[%x]",&word);
00480                           emit_word(word);
00481                           read_token(fi);
00482                           sscanf(token,"%x",&word);
00483                           if (pass==1)
00484                             emit_dword(get_label()-offset-2);
00485                           else
00486                             emit_dword(-1);
00487                           break;
00488                         default:
00489                           break;
00490                         }
00491                     }
00492                   }
00493                 
00494               }
00495         }
00496 
00497       if (extended == 0) {
00498         fseek(fo,2,SEEK_SET);
00499         indata=0;
00500         i=codesize;
00501 
00502         if (codesize > 65535) {
00503           printf("Error: code size > 64Kb and not in ext32 mode!\n");
00504         }
00505         emit_word(i);
00506 
00507         if (datasize > 65535) {
00508           printf("Error: data size > 64Kb and not in ext32 mode!\n");
00509         }
00510 
00511         emit_word(datasize);
00512       } else {
00513         fseek(fo,4,SEEK_SET);
00514         indata=0;
00515         i=codesize;
00516         emit_dword(i);
00517         emit_dword(datasize);
00518       }
00519       fclose(fo);
00520       fclose(fi);
00521     }
00522   return 0;
00523 }

Generated on Mon Jul 9 14:42:51 2007 for ExultEngine by  doxygen 1.5.1