home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 October / Chip_2001-10_cd1.bin / zkuste / delphi / nastroje / d23456 / NSIS.EXE / Source / script.cpp < prev    next >
C/C++ Source or Header  |  2001-05-30  |  67KB  |  2,037 lines

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <shlobj.h>
  4. #include "tokens.h"
  5. #include "build.h"
  6. #include "util.h"
  7. #include "exedata.h"
  8.  
  9. #define MAX_INCLUDEDEPTH 10
  10. #define MAX_LINELENGTH 4096
  11.  
  12. int CEXEBuild::process_script(FILE *fp, char *curfilename, int *lineptr)
  13. {
  14.   if (has_called_write_output)
  15.   {
  16.     printf("Error (process_script): write_output already called, can't continue\n");
  17.     return PS_ERROR;
  18.   }
  19.   int ret=parseScript(fp,curfilename,lineptr,0);
  20.   if (ret == PS_ENDIF) printf("!endif: stray !endif\n");
  21.   if (IS_PS_ELSE(ret)) printf("!else: stray !else\n");
  22.   if (m_linebuild.getlen())
  23.   {
  24.     printf("Error: invalid script: last line ended with \\\n");
  25.     return PS_ERROR;
  26.   }
  27.   return ret;
  28. }
  29.  
  30.  
  31. int CEXEBuild::parseLine(char *str, FILE *fp, char *curfilename, int *lineptr, int ignore)
  32. {
  33.   LineParser line;
  34.   int res;
  35.   
  36.   // remove trailing slash and null
  37.  
  38.   if (m_linebuild.getlen()>1) m_linebuild.resize(m_linebuild.getlen()-2);
  39.  
  40.   m_linebuild.add(str,strlen(str)+1);
  41.  
  42.   if (str[0] && str[strlen(str)-1] == '\\') return PS_OK;
  43.  
  44.   res=line.parse((char*)m_linebuild.get());
  45.  
  46.   m_linebuild.resize(0);
  47.  
  48.   if (res)
  49.   {
  50.     if (res==-2) printf("Error: unterminated string parsing line at %s:%d\n",curfilename,*lineptr);
  51.     else printf("Error: error parsing line (%s:%d)\n",curfilename,*lineptr);
  52.     return PS_ERROR;
  53.   }
  54.  
  55. parse_again:
  56.   if (line.getnumtokens() < 1) return PS_OK;
  57.  
  58.   int np,op;
  59.   int tkid=get_commandtoken(line.gettoken_str(0),&np,&op);
  60.   if (tkid == -1)
  61.   {
  62.     char *p=line.gettoken_str(0);
  63.     if (p[0] && p[strlen(p)-1]==':')
  64.     {
  65.       if (!ignore)
  66.       {
  67.         int a=add_label(line.gettoken_str(0));
  68.         if (a) return PS_ERROR;
  69.       }
  70.       line.eattoken();
  71.       goto parse_again;
  72.     }
  73.     printf("Invalid command: %s\n",line.gettoken_str(0));
  74.     return PS_ERROR;
  75.   }
  76.  
  77.   int v=line.getnumtokens()-(np+1);
  78.   if (v < 0 || (op >= 0 && v > op)) // opt_parms is -1 for unlimited
  79.   {
  80.     printf("%s expects %d",line.gettoken_str(0),np);
  81.     if (op < 0) printf("+");
  82.     if (op > 0) printf("-%d",op);
  83.     printf(" parameters, got %d.\n",line.getnumtokens()-1);
  84.     print_help(line.gettoken_str(0));
  85.     return PS_ERROR;
  86.   }
  87.  
  88.   int is_elseif=0;
  89.  
  90.   if (!fp && (tkid == TOK_P_ELSE || tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF))
  91.   {
  92.     printf("Error: !if/!else/!ifdef can only be specified in file mode, not in command mode.\n");
  93.     return PS_ERROR;
  94.   }
  95.  
  96.   if (tkid == TOK_P_ELSE) 
  97.   {
  98.     if (line.getnumtokens() == 1) return PS_ELSE;
  99.  
  100.     line.eattoken();
  101.  
  102.     int v=line.gettoken_enum(0,"ifdef\0ifndef\0");
  103.     if (v < 0)
  104.     {
  105.       print_help(line.gettoken_str(0));
  106.       return PS_ERROR;
  107.     }
  108.     if (line.getnumtokens() == 1)
  109.     {
  110.       print_help(line.gettoken_str(0));
  111.       return PS_ERROR;
  112.     }
  113.     if (!v) tkid = TOK_P_IFDEF;
  114.     else tkid = TOK_P_IFNDEF;
  115.     is_elseif=1;
  116.   }
  117.  
  118.   if (tkid == TOK_P_IFNDEF || tkid == TOK_P_IFDEF)
  119.   {
  120.     int istrue=0;
  121.     if (!ignore || is_elseif)
  122.     {
  123.       int mod=0;
  124.       int p;
  125.  
  126.        // pure left to right precedence. Not too powerful, but useful.
  127.       for (p = 1; p < line.getnumtokens(); p ++)
  128.       {         
  129.         if (p & 1)
  130.         {
  131.           int new_s=(definedlist.find(line.gettoken_str(p),0) >= 0);
  132.           if (tkid == TOK_P_IFNDEF) new_s=!new_s;
  133.  
  134.           if (mod == 0) istrue = istrue || new_s;
  135.           else istrue = istrue && new_s;
  136.         }
  137.         else
  138.         {
  139.           mod=line.gettoken_enum(p,"|\0&\0\0");
  140.           if (mod == -1)
  141.           {
  142.             print_help(line.gettoken_str(0));
  143.             return PS_ERROR;
  144.           }
  145.         }
  146.       }
  147.       if (is_elseif)
  148.       {
  149.         if (istrue) return PS_ELSE_IF1;
  150.         return PS_ELSE_IF0;
  151.       }
  152.     }
  153.  
  154.     int r;
  155.     int hasexec=0;
  156.     istrue=!istrue;
  157.  
  158.     for (;;)
  159.     {
  160.       r=parseScript(fp,curfilename,lineptr, ignore || hasexec || istrue);
  161.       if (!istrue) hasexec=1;
  162.       if (r == PS_ELSE_IF0) istrue=1;
  163.       else if (r == PS_ELSE_IF1) istrue=0;
  164.       else break;
  165.     }
  166.  
  167.     if (r == PS_ELSE)
  168.     {
  169.       r=parseScript(fp,curfilename,lineptr, ignore || hasexec);
  170.       if (IS_PS_ELSE(r))
  171.       {
  172.         printf("!else: stray !else\n");
  173.         return PS_ERROR;
  174.       }
  175.     }
  176.     if (r == PS_EOF)
  177.     {
  178.       printf("!ifdef: open at EOF - need !endif\n");
  179.       return PS_ERROR;
  180.     }
  181.     if (r == PS_ERROR) return r;
  182.     return PS_OK;
  183.   }
  184.   if (tkid == TOK_P_ENDIF) return PS_ENDIF;
  185.   if (!ignore) 
  186.   {
  187.     int ret=doCommand(tkid,line,fp,curfilename,*lineptr);
  188.     if (ret != PS_OK) return ret;
  189.   }
  190.   return PS_OK;
  191. }
  192.  
  193. int CEXEBuild::parseScript(FILE *fp, char *curfilename, int *lineptr, int ignore)
  194. {
  195.   char str[MAX_LINELENGTH];
  196.  
  197.   for (;;)
  198.   {
  199.     (*lineptr)++;
  200.     str[0]=0;
  201.     fgets(str,MAX_LINELENGTH,fp);
  202.     if (feof(fp)&&!str[0]) break;
  203.  
  204.     // remove trailing whitespace
  205.     {
  206.       char *p=str;
  207.       while (*p) p++;
  208.       if (p > str) p--;
  209.       while (p >= str && (*p == '\r' || *p == '\n' || *p == ' ' || *p == '\t')) p--;
  210.       *++p=0;
  211.     }
  212.  
  213.     GrowBuf linedata;
  214.     // convert $\r, $\n, $\t to their literals
  215.     {
  216.       char *in=str;
  217.       while (*in)
  218.       {
  219.         char c=*in++;
  220.         if (c == '$' && in[0] == '\\')
  221.         {
  222.           if (in[1] == 'r')
  223.           {
  224.             in+=2;
  225.             c='\r';
  226.           }
  227.           else if (in[1] == 'n')
  228.           {
  229.             in+=2;
  230.             c='\n';
  231.           }
  232.         }
  233.         linedata.add(&c,1);
  234.       }
  235.       linedata.add("",1);
  236.     }
  237.     int ret=parseLine((char*)linedata.get(),fp,curfilename,lineptr,ignore);
  238.     if (ret != PS_OK) return ret;
  239.   }
  240.   return PS_EOF;
  241. }
  242.  
  243. int CEXEBuild::process_jump(char *s, int *offs)
  244. {
  245.   if (!stricmp(s,"0") || !stricmp(s,"")) *offs=0;
  246.   else
  247.   {
  248.     if ((s[0] >= '0' && s[0] <= '9') || s[0] == '-')
  249.     {
  250.       printf("Error: Goto targets cannot begin with 0-9 or -\n");
  251.       return 1;
  252.     }
  253.     *offs=ns_label.add(s,0);
  254.   }
  255.   return 0;
  256. }
  257.  
  258. int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, char *curfilename, int linecnt)
  259. {
  260.   static char *usrvars="$0\0$1\0$2\0$3\0$4\0$5\0$6\0$7\0$8\0$9\0$INSTDIR\0$OUTDIR\0";
  261.   static char *rootkeys[2] = {
  262.     "HKCR\0HKLM\0HKCU\0HKU\0HKCC\0HKDD\0HKPD\0",
  263.     "HKEY_CLASSES_ROOT\0HKEY_LOCAL_MACHINE\0HKEY_CURRENT_USER\0HKEY_USERS\0HKEY_CURRENT_CONFIG\0HKEY_DYN_DATA\0HKEY_PERFORMANCE_DATA\0"
  264.   };
  265.   static HKEY rootkey_tab[] = {
  266.     HKEY_CLASSES_ROOT,HKEY_LOCAL_MACHINE,HKEY_CURRENT_USER,HKEY_USERS,HKEY_CURRENT_CONFIG,HKEY_DYN_DATA,HKEY_PERFORMANCE_DATA
  267.   };
  268.  
  269.   entry ent={0,};
  270.   switch (which_token)
  271.   {
  272.     // header flags
  273.     ///////////////////////////////////////////////////////////////////////////////
  274.     case TOK_NAME:
  275.       if (build_header.name_ptr >= 0)
  276.       {
  277.         warning("Name: specified multiple times, wasting space (%s:%d)",curfilename,linecnt);
  278.       }
  279.       build_header.name_ptr=add_string_main(line.gettoken_str(1));
  280. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  281.       build_uninst.name_ptr=add_string_uninst(line.gettoken_str(1));
  282. #endif
  283.       printf("Name: \"%s\"\n",line.gettoken_str(1));
  284.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  285.     case TOK_CAPTION:
  286.       if (build_header.caption_ptr >= 0)
  287.       {
  288.         warning("Caption: specified multiple times, wasting space (%s:%d)",curfilename,linecnt);
  289.       }
  290.       build_header.caption_ptr=add_string_main(line.gettoken_str(1));
  291.       printf("Caption: \"%s\"\n",line.gettoken_str(1));
  292.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  293.     case TOK_ICON:
  294.       printf("Icon: \"%s\"\n",line.gettoken_str(1));
  295.       if (replace_icon((char*)header_data_new+icon_offset,line.gettoken_str(1)))
  296.       {
  297.         print_help(line.gettoken_str(0));
  298.         return PS_ERROR;
  299.       }
  300.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  301.     case TOK_UNINSTICON:
  302. #ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
  303.       printf("UninstallIcon: installer not built with NSIS_CONFIG_UNINSTALL_SUPPORT\n");
  304.       return PS_ERROR;
  305. #else
  306.       printf("UninstallIcon: \"%s\"\n",line.gettoken_str(1));
  307.       if (replace_icon((char*)m_unicon_data,line.gettoken_str(1))) 
  308.       {
  309.         print_help(line.gettoken_str(0));
  310.         return PS_ERROR;
  311.       }
  312.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  313. #endif
  314.     case TOK_ENABLEDBITMAP:
  315.       printf("EnabledBitmap: \"%s\"\n",line.gettoken_str(1));
  316.       if (replace_bitmap((char*)header_data_new+enabled_bitmap_offset,line.gettoken_str(1))) 
  317.       {
  318.         print_help(line.gettoken_str(0));
  319.         return PS_ERROR;
  320.       }
  321.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  322.     case TOK_DISABLEDBITMAP:
  323.       printf("DisabledBitmap: \"%s\"\n",line.gettoken_str(1));
  324.       if (replace_bitmap((char*)header_data_new+disabled_bitmap_offset,line.gettoken_str(1))) 
  325.       {
  326.         print_help(line.gettoken_str(0));
  327.         return PS_ERROR;
  328.       }
  329.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  330.     case TOK_DIRTEXT:
  331.       if (build_header.text_ptr >= 0 && line.gettoken_str(1)[0])
  332.       {
  333.         warning("DirText: specified multiple times, wasting space (%s:%d)",curfilename,linecnt);
  334.       }
  335.       build_header.text_ptr=add_string_main(line.gettoken_str(1));
  336.       printf("DirText: \"%s\"\n",line.gettoken_str(1));
  337.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  338.     case TOK_COMPTEXT:
  339.       if (build_header.componenttext_ptr >= 0 && line.gettoken_str(1)[0])
  340.       {
  341.         warning("ComponentText: specified multiple times, wasting space (%s:%d)",curfilename,linecnt);
  342.       }
  343.       build_header.componenttext_ptr=add_string_main(line.gettoken_str(1));
  344.       printf("ComponentText: \"%s\"\n",line.gettoken_str(1));
  345.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  346.     case TOK_LICENSETEXT:
  347.       if (build_header.licensetext_ptr >= 0)
  348.       {
  349.         warning("LicenseText: specified multiple times, wasting space (%s:%d)",curfilename,linecnt);
  350.       }
  351.       build_header.licensetext_ptr=add_string_main(line.gettoken_str(1));
  352.       printf("LicenseText: \"%s\"\n",line.gettoken_str(1));
  353.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  354.     case TOK_LICENSEDATA:
  355.       if (build_header.licensedata_ptr != -1)
  356.       {
  357.         warning("LicenseData: specified multiple times, wasting space (%s:%d)",curfilename,linecnt);
  358.       }
  359.       if (build_header.silent_install)
  360.       {
  361.         warning("LicenseData: SilentInstall enabled, wasting space (%s:%d)",curfilename,linecnt);
  362.       }
  363.       {
  364.         char data[32768];
  365.         FILE *fp;
  366.         int datalen;
  367.         fp=fopen(line.gettoken_str(1),"rb");
  368.         if (!fp)
  369.         {
  370.           printf("LicenseData: open failed \"%s\"\n",line.gettoken_str(1));
  371.           print_help(line.gettoken_str(0));
  372.           return PS_ERROR;
  373.         }
  374.         datalen=fread(data,1,32767,fp);
  375.         if (!feof(fp))
  376.         {
  377.           printf("LicenseData: license must be < 32 kilobytes.\n");
  378.           fclose(fp);
  379.           return PS_ERROR;         
  380.         }
  381.         fclose(fp);
  382.         data[datalen]=0;
  383.         build_header.licensedata_ptr=add_string_main(data);
  384.         printf("LicenseData: \"%s\"      \n",line.gettoken_str(1));
  385.       }
  386.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  387.     case TOK_UNINSTTEXT:
  388. #ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
  389.       printf("UninstallText: installer not built with NSIS_CONFIG_UNINSTALL_SUPPORT\n");
  390.       return PS_ERROR;
  391. #else
  392.       if (build_uninst.uninstalltext_ptr >= 0)
  393.       {
  394.         warning("UninstallText: specified multiple times, wasting space (%s:%d)",curfilename,linecnt);
  395.       }
  396.       build_uninst.uninstalltext_ptr=add_string_uninst(line.gettoken_str(1));
  397.       printf("UninstallText: \"%s\"\n",line.gettoken_str(1));
  398.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  399. #endif
  400.     case TOK_SILENTINST:
  401.       build_header.silent_install=line.gettoken_enum(1,"normal\0silent\0silentlog\0");
  402.       if (build_header.silent_install<0)
  403.       {
  404.         print_help(line.gettoken_str(0));
  405.         return PS_ERROR;
  406.       }
  407. #ifndef NSIS_CONFIG_LOG
  408.       if (build_header.silent_install == 2)
  409.       {
  410.         printf("SilentInstall: silentlog specified, no log support compiled in (use NSIS_CONFIG_LOG)\n");
  411.         return PS_ERROR;
  412.       }
  413. #endif
  414.       printf("SilentInstall: %s\n",line.gettoken_str(1));
  415.       if (build_header.silent_install && build_header.licensedata_ptr != -1)
  416.       {
  417.         warning("SilentInstall: LicenseData already specified. wasting space (%s:%d)",curfilename,linecnt);
  418.       }
  419.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  420.     case TOK_INSTTYPE:
  421.       {
  422.         int x;
  423.         if (!stricmp(line.gettoken_str(1),"/NOCUSTOM"))
  424.         {
  425.           build_header.no_custom_instmode_flag=1;
  426.           printf("InstType: disabling custom install type\n");
  427.         }
  428.         else if (line.gettoken_str(1)[0]=='/')
  429.         {
  430.           print_help(line.gettoken_str(0));
  431.           return PS_ERROR;
  432.         }
  433.         else
  434.         {
  435.           for (x = 0; x < MAX_INST_TYPES && build_header.install_types_ptr[x]>=0; x ++);
  436.           if (x==MAX_INST_TYPES)
  437.           {
  438.             printf("InstType: no more than %d install types allowed. %d specified\n",MAX_INST_TYPES,MAX_INST_TYPES+1);
  439.             return PS_ERROR;
  440.           }
  441.           else 
  442.           {
  443.             build_header.install_types_ptr[x] = add_string_main(line.gettoken_str(1));
  444.             printf("InstType: %d=\"%s\"\n",x+1,line.gettoken_str(1));
  445.           }
  446.         }
  447.       }
  448.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  449.     case TOK_OUTFILE:
  450.       strncpy(build_output_filename,line.gettoken_str(1),1024-1);
  451.       printf("OutFile: \"%s\"\n",build_output_filename);
  452.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  453.     case TOK_INSTDIR:
  454.       if (build_header.install_directory_ptr >= 0)
  455.       {
  456.         warning("InstallDir: specified multiple times. wasting space (%s:%d)",curfilename,linecnt);
  457.       }
  458.       build_header.install_directory_ptr = add_string_main(line.gettoken_str(1));
  459.       printf("InstallDir: \"%s\"\n",line.gettoken_str(1));
  460.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  461.     case TOK_INSTALLDIRREGKEY: // InstallDirRegKey
  462.       {
  463.         if (build_header.install_reg_key_ptr>= 0)
  464.         {
  465.           warning("InstallRegKey: specified multiple times, wasting space (%s:%d)",curfilename,linecnt);
  466.         }
  467.         int k=line.gettoken_enum(1,rootkeys[0]);
  468.         if (k == -1) k=line.gettoken_enum(1,rootkeys[1]);
  469.         if (k == -1)
  470.         {
  471.           print_help(line.gettoken_str(0));
  472.           return PS_ERROR;
  473.         }
  474.         build_header.install_reg_rootkey=(int)rootkey_tab[k];
  475.         build_header.install_reg_key_ptr = add_string_main(line.gettoken_str(2));
  476.         build_header.install_reg_value_ptr = add_string_main(line.gettoken_str(3));
  477.         printf("InstallRegKey: \"%s\\%s\\%s\"\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
  478.       }
  479.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  480.     case TOK_UNINSTALLEXENAME:        
  481. #ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
  482.       printf("UninstallExeName: installer not built with NSIS_CONFIG_UNINSTALL_SUPPORT\n");
  483.       return PS_ERROR;
  484. #else
  485.       if (build_header.uninstall_exe_name_ptr>= 0)
  486.       {
  487.         warning("UninstallExeName: specified multiple times, wasting space (%s:%d)",curfilename,linecnt);
  488.       }
  489.       build_header.uninstall_exe_name_ptr=add_string_main(line.gettoken_str(1));
  490.       printf("UninstallExeName: \"%s\"\n",line.gettoken_str(1));       
  491.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  492. #endif
  493.     case TOK_CRCCHECK:
  494.       build_crcchk=line.gettoken_enum(1,"off\0on\0");
  495.       if (build_crcchk==-1)
  496.       {
  497.         print_help(line.gettoken_str(0));
  498.         return PS_ERROR;
  499.       }
  500.       printf("CRCCheck: %s\n",line.gettoken_str(1));
  501.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  502.     case TOK_AUTOCLOSE:
  503.       {
  504.         int k=line.gettoken_enum(1,"false\0true\0");
  505.         if (k == -1)
  506.         {
  507.           print_help(line.gettoken_str(0));
  508.           return PS_ERROR;
  509.         }
  510.         build_header.auto_close=k;
  511.         printf("AutoCloseWindow: %s\n",k?"true":"false");
  512.       }
  513.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  514.     case TOK_SHOWDETAILS:
  515.       {
  516.         int k=line.gettoken_enum(1,"hide\0show\0nevershow\0");
  517.         if (k == -1)
  518.         {
  519.           print_help(line.gettoken_str(0));
  520.           return PS_ERROR;
  521.         }
  522.         build_header.show_details=k;
  523.         printf("ShowInstDetails: %s\n",line.gettoken_str(1));
  524.       }
  525.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  526.     case TOK_DIRSHOW:
  527.       {
  528.         int k=line.gettoken_enum(1,"show\0hide\0");
  529.         if (k == -1)
  530.         {
  531.           print_help(line.gettoken_str(0));
  532.           return PS_ERROR;
  533.         }
  534.         build_header.no_show_dirpage=k;
  535.         printf("DirShow: %s\n",k?"hide":"show");
  536.       }
  537.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  538.     case TOK_BGGRADIENT:
  539. #ifndef NSIS_SUPPORT_BGBG
  540.       printf("BGGradient: support for BGGradient not compiled in (NSIS_SUPPORT_BGBG)\n");
  541.       return PS_ERROR;
  542. #else
  543.       if (line.getnumtokens()==1)
  544.       {
  545.         printf("BGGradient: default colors\n");
  546.         build_header.bg_color1=0;
  547.         build_header.bg_color2=RGB(0,0,255);
  548.       }
  549.       else if (!stricmp(line.gettoken_str(1),"off"))
  550.       {
  551.         build_header.bg_color1=build_header.bg_color2=-1;
  552.         printf("BGGradient: off\n");
  553.         if (line.getnumtokens()>2)
  554.         {
  555.           print_help(line.gettoken_str(0));
  556.           return PS_ERROR;
  557.         }
  558.       }
  559.       else
  560.       {
  561.         char *p = line.gettoken_str(1);
  562.         int v1,v2,v3=-1;
  563.         v1=strtoul(p,&p,16);
  564.         build_header.bg_color1=((v1&0xff)<<16)|(v1&0xff00)|((v1&0xff0000)>>16);
  565.         p=line.gettoken_str(2);
  566.         v2=strtoul(p,&p,16);
  567.         build_header.bg_color2=((v2&0xff)<<16)|(v2&0xff00)|((v2&0xff0000)>>16);
  568.  
  569.         p=line.gettoken_str(3);
  570.         if (*p)
  571.         {
  572.           if (!stricmp(p,"notext")) build_header.bg_textcolor=-1;
  573.           else
  574.           {
  575.             v3=strtoul(p,&p,16);
  576.             build_header.bg_textcolor=((v3&0xff)<<16)|(v3&0xff00)|((v3&0xff0000)>>16);
  577.           }
  578.         }
  579.         
  580.         printf("BGGradient: %06X->%06X (text=%d)\n",v1,v2,v3);
  581.       }
  582.  
  583. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  584.       build_uninst.bg_color1=build_header.bg_color1;
  585.       build_uninst.bg_color2=build_header.bg_color2;
  586.       build_uninst.bg_textcolor=build_header.bg_textcolor;
  587. #endif
  588. #endif
  589.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  590.     case TOK_INSTCOLORS:
  591.       {
  592.         char *p = line.gettoken_str(1);
  593.         if (p[0]=='/')
  594.         {
  595.           if (stricmp(p,"/windows") || line.getnumtokens()!=2) 
  596.           {
  597.             print_help(line.gettoken_str(0));
  598.             return PS_ERROR;
  599.           }
  600.           build_header.lb_fg=build_header.lb_bg=-1;
  601.           printf("InstallColors: windows default colors\n");
  602.         }
  603.         else
  604.         {
  605.           int v1,v2;
  606.           if (line.getnumtokens()!=3) 
  607.           {
  608.             print_help(line.gettoken_str(0));
  609.             return PS_ERROR;
  610.           }
  611.           v1=strtoul(p,&p,16);
  612.           build_header.lb_fg=((v1&0xff)<<16)|(v1&0xff00)|((v1&0xff0000)>>16);
  613.           p=line.gettoken_str(2);
  614.           v2=strtoul(p,&p,16);
  615.           build_header.lb_bg=((v2&0xff)<<16)|(v2&0xff00)|((v2&0xff0000)>>16);
  616.           printf("InstallColors: fg=%06X bg=%06X\n",v1,v2);
  617.         }
  618.  
  619. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  620.         build_uninst.lb_fg=build_header.lb_fg;
  621.         build_uninst.lb_bg=build_header.lb_bg;
  622. #endif
  623.       }
  624.     return make_sure_not_in_secorfunc(line.gettoken_str(0));
  625.  
  626.     // preprocessor-ish (ifdef/ifndef/else/endif are handled one step out from here)
  627.     ///////////////////////////////////////////////////////////////////////////////
  628.     case TOK_P_DEFINE:
  629.       definedlist.add(line.gettoken_str(1),0);
  630.       printf("!define: \"%s\"\n",line.gettoken_str(1));
  631.     return PS_OK;
  632.     case TOK_P_PACKEXEHEADER:
  633.       strncpy(build_packname,line.gettoken_str(1),sizeof(build_packname)-1);
  634.       strncpy(build_packcmd,line.gettoken_str(2),sizeof(build_packcmd)-1);
  635.       printf("!packhdr: filename=\"%s\", command=\"%s\"\n",
  636.         build_packname, build_packcmd);
  637.     return PS_OK;
  638.     case TOK_P_SYSTEMEXEC:
  639.       {
  640.         char *exec=line.gettoken_str(1);
  641.         int comp=line.gettoken_enum(2,"<\0>\0<>\0=\0ignore\0");
  642.         if (comp == -1)
  643.         {
  644.           print_help(line.gettoken_str(0));
  645.           return PS_ERROR;
  646.         }
  647.         int success=0;
  648.         int cmpv=line.gettoken_int(3,&success);
  649.         if (!success && comp != 4)
  650.         {
  651.           print_help(line.gettoken_str(0));
  652.           return PS_ERROR;
  653.         }
  654.         printf("!system: \"%s\"\n",exec);
  655.         int ret=system(exec);
  656.         if (comp == 0 && ret < cmpv);
  657.         else if (comp == 1 && ret > cmpv);
  658.         else if (comp == 2 && ret != cmpv);
  659.         else if (comp == 3 && ret == cmpv);
  660.         else if (comp == 4);
  661.         else
  662.         {
  663.           printf("!system: returned %d, aborting\n",ret);
  664.           return PS_ERROR;
  665.         }
  666.         printf("!system: returned %d\n",ret);
  667.       }
  668.     return PS_OK;
  669.     case TOK_P_INCLUDE:
  670.       {
  671.         char *f=line.gettoken_str(1);
  672.         printf("!include: \"%s\"\n",f);
  673.         FILE *incfp=fopen(f,"rt");
  674.         if (!incfp)
  675.         {
  676.           printf("!include: could not open file: \"%s\"\n",f);
  677.           return PS_ERROR;
  678.         }
  679.         static int depth;
  680.         if (depth >= MAX_INCLUDEDEPTH)
  681.         {
  682.           printf("parseScript: too many levels of includes (%d max).\n",MAX_INCLUDEDEPTH);
  683.           return PS_ERROR;
  684.         }
  685.         depth++;
  686.         int lc=0;
  687.         int r=parseScript(incfp,f,&lc,0);
  688.         depth--;
  689.         fclose(incfp);
  690.         if (r != PS_EOF && r != PS_OK)
  691.         {
  692.           if (r == PS_ENDIF) printf("!endif: stray !endif\n");
  693.           if (IS_PS_ELSE(r)) printf("!else: stray !else\n");
  694.           printf("!include: error in script: \"%s\" on line %d\n",f,lc);
  695.           return PS_ERROR;
  696.         }
  697.         printf("!include: closed: \"%s\"\n",f);
  698.       }
  699.     return PS_OK;
  700.     case TOK_P_CD:
  701.       if (!line.gettoken_str(1)[0] || !SetCurrentDirectory(line.gettoken_str(1)))
  702.       {
  703.         printf("!cd: error changing to: \"%s\"\n",line.gettoken_str(1));
  704.         return PS_ERROR;
  705.       }
  706.     return PS_OK;
  707.     case TOK_P_ERROR:
  708.       printf("!error: %s\n",line.gettoken_str(1));
  709.     return PS_ERROR;
  710.     case TOK_P_WARNING:
  711.       warning("!warning: %s (%s:%d)",line.gettoken_str(1),curfilename,linecnt);
  712.     return PS_OK;
  713.  
  714.     // section/function shit
  715.     ///////////////////////////////////////////////////////////////////////////////
  716.  
  717.     case TOK_SECTION:
  718.       printf("Section: \"%s\"\n",line.gettoken_str(1));
  719. #ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
  720.       if (!stricmp(line.gettoken_str(1),"uninstall"))
  721.       {
  722.         printf("Error: Uninstall section declared, no NSIS_CONFIG_UNINSTALL_SUPPORT\n");
  723.         return PS_ERROR;
  724.       }
  725. #endif
  726.       if (line.gettoken_str(1)[0]=='-') return add_section("",curfilename,linecnt);
  727.     return add_section(line.gettoken_str(1),curfilename,linecnt);
  728.     case TOK_SECTIONEND:
  729.       printf("SectionEnd\n");
  730.     return section_end();
  731.     case TOK_SECTIONIN:
  732.       {
  733.         printf("SectionIn: ");
  734.         int wt;
  735.         for (wt = 1; wt < line.getnumtokens(); wt ++)
  736.         {
  737.           char *p=line.gettoken_str(wt);
  738.           while (*p)
  739.           {
  740.             int x=*p-'1';
  741.             if (x >= 0 && x < MAX_INST_TYPES)
  742.             {
  743.               if (section_add_flags(1<<x) != PS_OK) return PS_ERROR;
  744.               printf("[%d] ",x);
  745.             }
  746.             p++;
  747.           }
  748.         }
  749.         printf("\n");
  750.       }
  751.     return PS_OK;
  752.     case TOK_SECTIONDIVIDER:
  753.       printf("SectionDivider\n");
  754.     return add_section("-",curfilename,linecnt);
  755.  
  756.     case TOK_FUNCTION:
  757.       printf("Function: \"%s\"\n",line.gettoken_str(1));
  758. #ifndef NSIS_CONFIG_UNINSTALL_SUPPORT
  759.       if (!strnicmp(line.gettoken_str(1),"un.",3))
  760.       {
  761.         printf("Error: Uninstall function declared, no NSIS_CONFIG_UNINSTALL_SUPPORT\n");
  762.         return PS_ERROR;
  763.       }
  764. #endif
  765.       return add_function(line.gettoken_str(1));
  766.     case TOK_FUNCTIONEND:
  767.       printf("FunctionEnd\n");
  768.     return function_end();
  769.  
  770.     // flag setters
  771.     ///////////////////////////////////////////////////////////////////////////////
  772.  
  773.     case TOK_SETDATESAVE:
  774.       build_datesave=line.gettoken_enum(1,"off\0on\0");
  775.       if (build_datesave==-1)
  776.       {
  777.         print_help(line.gettoken_str(0));
  778.         return PS_ERROR;
  779.       }
  780.       printf("SetDateSave: %s\n",line.gettoken_str(1));    
  781.     return PS_OK;
  782.     case TOK_SETOVERWRITE:
  783.       build_overwrite=line.gettoken_enum(1,"on\0off\0try\0ifnewer\0");
  784.       if (build_overwrite==-1)
  785.       {
  786.         print_help(line.gettoken_str(0));
  787.         return PS_ERROR;
  788.       }
  789.       printf("SetOverwrite: %s\n",line.gettoken_str(1));
  790.     return PS_OK;
  791.     case TOK_SETCOMPRESS:
  792.       build_compress=line.gettoken_enum(1,"off\0auto\0force\0");
  793.       if (build_compress==-1)
  794.       {
  795.         print_help(line.gettoken_str(0));
  796.         return PS_ERROR;
  797.       }
  798.       printf("SetCompress: %s\n",line.gettoken_str(1));
  799.     return PS_OK;
  800.     case TOK_DBOPTIMIZE:
  801.       build_optimize_datablock=line.gettoken_enum(1,"off\0on\0");
  802.       if (build_optimize_datablock==-1)
  803.       {
  804.         print_help(line.gettoken_str(0));
  805.         return PS_ERROR;
  806.       }
  807.       printf("SetDatablockOptimize: %s\n",line.gettoken_str(1));
  808.     return PS_OK;
  809.  
  810.     // instructions
  811.     ///////////////////////////////////////////////////////////////////////////////
  812.     case TOK_NOP: 
  813.       printf("Nop\n");
  814.       ent.which=EW_NOP;
  815.     return add_entry(&ent);
  816.     case TOK_GOTO: 
  817.       ent.which=EW_NOP;
  818.       if (process_jump(line.gettoken_str(1),&ent.offsets[0])) 
  819.       {
  820.         print_help(line.gettoken_str(0));
  821.         return PS_ERROR;
  822.       }
  823.       printf("Goto: %s\n",line.gettoken_str(1));
  824.     return add_entry(&ent);
  825.     case TOK_CALL:
  826.       if (!line.gettoken_str(1)[0])
  827.       {
  828.         print_help(line.gettoken_str(0));
  829.         return PS_ERROR;
  830.       }
  831. #ifdef NSIS_CONFIG_UNINSTALL_SUPPORT
  832.       if (uninstall_mode && strnicmp(line.gettoken_str(1),"un.",3))
  833.       {
  834.         printf("Call must be used with function names starting with \"un.\" in the uninstall section.\n");
  835.         print_help(line.gettoken_str(0));
  836.         return PS_ERROR;
  837.       }
  838.       if (!uninstall_mode && !strnicmp(line.gettoken_str(1),"un.",3))
  839.       {
  840.         printf("Call must not be used with functions starting with \"un.\" in the non-uninstall sections.\n");
  841.         print_help(line.gettoken_str(0));
  842.         return PS_ERROR;
  843.       }
  844. #endif
  845.       ent.which=EW_CALL;
  846.       ent.offsets[0]=ns_func.add(line.gettoken_str(1),0);
  847.       printf("Call \"%s\"\n",line.gettoken_str(1));
  848.     return add_entry(&ent);
  849.     case TOK_SETOUTPATH:
  850.       {
  851.         char *p=line.gettoken_str(1);
  852.         if (*p == '-') cur_out_path[0]=0;
  853.         else
  854.         { 
  855.           if (p[0] == '\\' && p[1] != '\\') p++;
  856.           strncpy(cur_out_path,p,1024-1);
  857.           if (cur_out_path[strlen(cur_out_path)-1]=='\\') 
  858.             cur_out_path[strlen(cur_out_path)-1]=0; // remove trailing slash
  859.         }
  860.         if (!cur_out_path[0]) strcpy(cur_out_path,"$INSTDIR");
  861.         printf("SetOutPath: \"%s\"\n",cur_out_path);
  862.         ent.which=EW_SETOUTPUTDIR;
  863.         ent.offsets[0]=add_string(cur_out_path);
  864.       }
  865.     return add_entry(&ent);
  866.     case TOK_CREATEDIR:
  867.       {
  868.         char out_path[1024];
  869.         char *p=line.gettoken_str(1);
  870.         if (*p == '-') out_path[0]=0;
  871.         else
  872.         { 
  873.           if (p[0] == '\\' && p[1] != '\\') p++;
  874.           strncpy(out_path,p,1024-1);
  875.           if (out_path[strlen(out_path)-1]=='\\') out_path[strlen(out_path)-1]=0; // remove trailing slash
  876.         }
  877.         if (!*out_path) 
  878.         {
  879.           print_help(line.gettoken_str(0));
  880.           return PS_ERROR;
  881.         }
  882.         printf("CreateDirectory: \"%s\"\n",out_path);
  883.         ent.which=EW_CREATEDIR;
  884.         ent.offsets[0]=add_string(out_path);
  885.       }
  886.     return add_entry(&ent);
  887.     case TOK_EXEC:
  888.     case TOK_EXECWAIT:
  889.       ent.which=EW_EXECUTE;
  890.       ent.offsets[0]=add_string(line.gettoken_str(1));
  891.       ent.offsets[1] = (which_token == TOK_EXECWAIT);
  892.       printf("%s: \"%s\"\n",ent.offsets[1]?"ExecWait":"Exec",line.gettoken_str(1));
  893.     return add_entry(&ent);
  894.     case TOK_EXECSHELL: // this uses improvements of Andras Varga
  895.       ent.which=EW_SHELLEXEC;
  896.       ent.offsets[0]=add_string(line.gettoken_str(1));
  897.       ent.offsets[1]=add_string(line.gettoken_str(2));
  898.       ent.offsets[2]=add_string(line.gettoken_str(3));
  899.       ent.offsets[3]=SW_SHOWNORMAL;
  900.       if (line.getnumtokens() > 4)
  901.       {
  902.         int tab[3]={SW_SHOWNORMAL,SW_SHOWMAXIMIZED,SW_SHOWMINIMIZED};
  903.         int a=line.gettoken_enum(4,"SW_SHOWNORMAL\0SW_SHOWMAXIMIZED\0SW_SHOWMINIMIZED\0");
  904.         if (a < 0)
  905.         {
  906.           print_help(line.gettoken_str(0));
  907.           return PS_ERROR;
  908.         }
  909.         ent.offsets[3]=tab[a];
  910.       }
  911.       printf("ExecShell: %s: \"%s\" \"%s\" %s\n",line.gettoken_str(1),line.gettoken_str(2),
  912.                                                  line.gettoken_str(3),line.gettoken_str(4));
  913.     return add_entry(&ent);
  914.     case TOK_REGDLL:
  915.     case TOK_UNREGDLL:
  916. #ifndef NSIS_SUPPORT_ACTIVEXREG
  917.       printf("RegDLL/UnRegDLL: support for RegDLL not compiled in (NSIS_SUPPORT_ACTIVEXREG)\n");
  918.       return PS_ERROR;
  919. #else
  920.     {
  921.       char *t;
  922.       ent.which=EW_REGISTERDLL;
  923.       ent.offsets[0]=add_string(line.gettoken_str(1));
  924.       if (which_token == TOK_UNREGDLL) 
  925.       {
  926.         t="DllUnregisterServer"; 
  927.         ent.offsets[2]=add_string("Unregistering: ");
  928.       }
  929.       else // register
  930.       {
  931.         t=line.gettoken_str(2);
  932.         if (!t || !*t) t="DllRegisterServer";
  933.         ent.offsets[2]=add_string("Registering: ");
  934.       }
  935.       ent.offsets[1] = add_string(t);
  936.  
  937.       printf("%s: \"%s\"\n",t,line.gettoken_str(1));
  938.     }
  939.     return add_entry(&ent);
  940. #endif
  941.     case TOK_RENAME:
  942.       {
  943.         int a=1;
  944.         ent.which=EW_RENAME;
  945.         if (!stricmp(line.gettoken_str(1),"/REBOOTOK"))
  946.         {
  947.           ent.offsets[2]=1;
  948.           a++;
  949.         }
  950.         else if (line.gettoken_str(1)[0]=='/')
  951.         {
  952.           a=line.getnumtokens(); // cause usage to go here:
  953.         }
  954.         if (line.getnumtokens()!=a+2)
  955.         {
  956.           print_help(line.gettoken_str(0));
  957.           return PS_ERROR;
  958.         }
  959.         ent.offsets[0]=add_string(line.gettoken_str(a));
  960.         ent.offsets[1]=add_string(line.gettoken_str(a+1));
  961.         printf("Rename: %s%s->%s\n",ent.offsets[2]?"/REBOOTOK ":"",line.gettoken_str(a),line.gettoken_str(a+1));
  962.       }
  963.     return add_entry(&ent);
  964.     case TOK_MESSAGEBOX:
  965.       {
  966.         #define MBD(x) {x,#x},
  967.         struct 
  968.         {
  969.           int id;
  970.           char *str;
  971.         } list[]=
  972.         {
  973.           MBD(MB_ABORTRETRYIGNORE)
  974.           MBD(MB_OK)
  975.           MBD(MB_OKCANCEL)
  976.           MBD(MB_RETRYCANCEL)
  977.           MBD(MB_YESNO)
  978.           MBD(MB_YESNOCANCEL)
  979.           MBD(MB_ICONEXCLAMATION)
  980.           MBD(MB_ICONINFORMATION)
  981.           MBD(MB_ICONQUESTION)
  982.           MBD(MB_ICONSTOP)
  983.           MBD(MB_TOPMOST)
  984.           MBD(MB_SETFOREGROUND)
  985.           MBD(MB_RIGHT)
  986.         };
  987.         #undef MBD
  988.         int r=0;
  989.         int x;
  990.         char *p=line.gettoken_str(1);
  991.  
  992.         while (*p)
  993.         {
  994.           char *np=p;
  995.           while (*np && *np != '|') np++;
  996.           if (*np) *np++=0;
  997.           for (x  =0 ; x < sizeof(list)/sizeof(list[0]) && strcmp(list[x].str,p); x ++);
  998.           if (x < sizeof(list)/sizeof(list[0]))
  999.           {
  1000.             r|=list[x].id;
  1001.           }
  1002.           else
  1003.           {
  1004.             print_help(line.gettoken_str(0));
  1005.             return PS_ERROR;
  1006.           }            
  1007.           p=np;
  1008.         }
  1009.         ent.which=EW_MESSAGEBOX;
  1010.         ent.offsets[0]=r;
  1011.         ent.offsets[1]=add_string(line.gettoken_str(2));
  1012.         if (line.getnumtokens() > 3)
  1013.         {
  1014.           ent.offsets[2]=line.gettoken_enum(3,"0\0IDABORT\0IDCANCEL\0IDIGNORE\0IDNO\0IDOK\0IDRETRY\0IDYES\0");
  1015.           if (ent.offsets[2] < 0)
  1016.           {
  1017.               print_help(line.gettoken_str(0));
  1018.               return PS_ERROR;
  1019.           }
  1020.           int rettab[] = 
  1021.           {
  1022.             0,IDABORT,IDCANCEL,IDIGNORE,IDNO,IDOK,IDRETRY,IDYES
  1023.           };
  1024.           ent.offsets[2] = rettab[ent.offsets[2]];
  1025.           if (process_jump(line.gettoken_str(4),&ent.offsets[3])) 
  1026.           {
  1027.             print_help(line.gettoken_str(0));
  1028.             return PS_ERROR;
  1029.           }
  1030.         }
  1031.         printf("MessageBox: %d: \"%s\"",r,line.gettoken_str(2));
  1032.         if (line.getnumtokens()>4) printf(" (on %s goto %s)",line.gettoken_str(3),line.gettoken_str(4));
  1033.         printf("\n");
  1034.       }      
  1035.     return add_entry(&ent);
  1036.     case TOK_DELETEREGVALUE:
  1037.     case TOK_DELETEREGKEY:
  1038.       {
  1039.         int a=1;
  1040.         if (which_token==TOK_DELETEREGKEY)
  1041.         {
  1042.           char *s=line.gettoken_str(a);
  1043.           if (s[0] == '/')
  1044.           {
  1045.             if (stricmp(s,"/ifempty")) 
  1046.             {
  1047.               print_help(line.gettoken_str(0));
  1048.               return PS_ERROR;
  1049.             }
  1050.             a++;
  1051.             ent.offsets[3]=1;
  1052.           }
  1053.         }
  1054.         int k=line.gettoken_enum(a,rootkeys[0]);
  1055.         if (k == -1) k=line.gettoken_enum(a,rootkeys[1]);
  1056.         if (k == -1)
  1057.         {
  1058.           print_help(line.gettoken_str(0));
  1059.           return PS_ERROR;
  1060.         }
  1061.         ent.which=EW_DELREG;
  1062.         ent.offsets[0]=(int)rootkey_tab[k];      
  1063.         ent.offsets[1]=add_string(line.gettoken_str(a+1));
  1064.         ent.offsets[2]=(which_token==TOK_DELETEREGKEY)?-1:add_string(line.gettoken_str(a+2));
  1065.         if (which_token==TOK_DELETEREGKEY)
  1066.           printf("DeleteRegKey: %s\\%s\n",line.gettoken_str(a),line.gettoken_str(a+1));
  1067.         else
  1068.           printf("DeleteRegValue: %s\\%s\\%s\n",line.gettoken_str(a),line.gettoken_str(a+1),line.gettoken_str(a+2));
  1069.       }
  1070.     return add_entry(&ent);
  1071.     case TOK_WRITEREGSTR:
  1072.     case TOK_WRITEREGBIN:
  1073.     case TOK_WRITEREGDWORD:
  1074.       {
  1075.         int k=line.gettoken_enum(1,rootkeys[0]);
  1076.         if (k == -1) k=line.gettoken_enum(1,rootkeys[1]);
  1077.         if (k == -1)
  1078.         {
  1079.           print_help(line.gettoken_str(0));
  1080.           return PS_ERROR;
  1081.         }
  1082.         ent.which=EW_WRITEREG;
  1083.         ent.offsets[0]=(int)rootkey_tab[k];
  1084.         ent.offsets[1]=add_string(line.gettoken_str(2));
  1085.         ent.offsets[2]=add_string(line.gettoken_str(3));
  1086.         if (which_token == TOK_WRITEREGSTR)
  1087.         {
  1088.           printf("WriteRegStr: %s\\%s\\%s=%s\n",
  1089.             line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
  1090.           ent.offsets[3]=add_string(line.gettoken_str(4));
  1091.           ent.offsets[4]=1;
  1092.         }
  1093.         if (which_token == TOK_WRITEREGBIN) 
  1094.         {
  1095.           char data[512];
  1096.           char *p=line.gettoken_str(4);
  1097.           int data_len=0;
  1098.           while (*p)
  1099.           {
  1100.             int c;
  1101.             int a,b;
  1102.             a=*p;
  1103.             if (a >= '0' && a <= '9') a-='0';
  1104.             else if (a >= 'a' && a <= 'f') a-='a'-10;
  1105.             else if (a >= 'A' && a <= 'F') a-='A'-10;
  1106.             else break;
  1107.             b=*++p;
  1108.             if (b >= '0' && b <= '9') b-='0';
  1109.             else if (b >= 'a' && b <= 'f') b-='a'-10;
  1110.             else if (b >= 'A' && b <= 'F') b-='A'-10;
  1111.             else break;
  1112.             p++;
  1113.             c=(a<<4)|b;
  1114.             if (data_len >= 512) 
  1115.             {
  1116.               printf("WriteRegBin: 512 bytes of data exceeded\n");
  1117.               return PS_ERROR;
  1118.             }
  1119.             data[data_len++]=c;
  1120.           }
  1121.           if (*p)
  1122.           {
  1123.             print_help(line.gettoken_str(0));
  1124.             return PS_ERROR;
  1125.           }
  1126.           printf("WriteRegBin: %s\\%s\\%s=%s\n",
  1127.             line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
  1128.           ent.offsets[3]=add_data(data,data_len);
  1129.           if (ent.offsets[3] < 0) return PS_ERROR;
  1130.           ent.offsets[4]=3;
  1131.         }
  1132.         if (which_token == TOK_WRITEREGDWORD) 
  1133.         {
  1134.           int s;
  1135.           ent.offsets[3]=line.gettoken_int(4,&s);
  1136.           if (!s)
  1137.           {
  1138.             print_help(line.gettoken_str(0));
  1139.             return PS_ERROR;
  1140.           }
  1141.           ent.offsets[4]=2;
  1142.           printf("WriteRegDword: %s\\%s\\%s=%d\n",
  1143.             line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),ent.offsets[3]);
  1144.         }
  1145.       }
  1146.     return add_entry(&ent);
  1147.     case TOK_DELETEINISEC:
  1148.     case TOK_DELETEINISTR:
  1149.       {
  1150.         char *vname="<section>";
  1151.         ent.which=EW_WRITEINI;
  1152.         ent.offsets[0]=add_string(line.gettoken_str(2)); // section name
  1153.         if (line.getnumtokens() > 3) 
  1154.         {
  1155.           vname=line.gettoken_str(3);
  1156.           ent.offsets[1]=add_string(vname); // value name
  1157.         }
  1158.         else ent.offsets[1]=-1;
  1159.         ent.offsets[2]=-1;
  1160.         ent.offsets[3]=add_string(line.gettoken_str(1));
  1161.         printf("DeleteINI%s: [%s] %s in %s\n",vname?"Str":"Sec",
  1162.           line.gettoken_str(2),vname,line.gettoken_str(1));
  1163.       }
  1164.     return add_entry(&ent);
  1165.     case TOK_WRITEINISTR:
  1166.       ent.which=EW_WRITEINI;
  1167.       ent.offsets[0]=add_string(line.gettoken_str(2));
  1168.       ent.offsets[1]=add_string(line.gettoken_str(3));
  1169.       ent.offsets[2]=add_string(line.gettoken_str(4));
  1170.       ent.offsets[3]=add_string(line.gettoken_str(1));
  1171.       printf("WriteINIStr: [%s] %s=%s in %s\n",
  1172.         line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(1));
  1173.     return add_entry(&ent);
  1174.     case TOK_CREATESHORTCUT:
  1175.       ent.which=EW_CREATESHORTCUT;
  1176.       ent.offsets[0]=add_string(line.gettoken_str(1));
  1177.       ent.offsets[1]=add_string(line.gettoken_str(2));
  1178.       ent.offsets[2]=add_string(line.gettoken_str(3));
  1179.       ent.offsets[3]=add_string(line.gettoken_str(4));
  1180.       int s;
  1181.       ent.offsets[4]=line.gettoken_int(5,&s)&0xff;
  1182.       if (!s)
  1183.       {
  1184.         if (line.getnumtokens() > 5)
  1185.         {
  1186.           printf("CreateShortCut: cannot interpret icon index\n");
  1187.           print_help(line.gettoken_str(0));
  1188.           return PS_ERROR;
  1189.         }
  1190.         ent.offsets[4]=0;
  1191.       }
  1192.       if (line.getnumtokens() > 6)
  1193.       {
  1194.         int tab[3]={SW_SHOWNORMAL,SW_SHOWMAXIMIZED,SW_SHOWMINIMIZED};
  1195.         int a=line.gettoken_enum(6,"SW_SHOWNORMAL\0SW_SHOWMAXIMIZED\0SW_SHOWMINIMIZED\0");
  1196.         if (a < 0)
  1197.         {
  1198.           printf("CreateShortCut: unknown show mode \"%s\"\n",line.gettoken_str(6));
  1199.           print_help(line.gettoken_str(0));
  1200.           return PS_ERROR;
  1201.         }
  1202.         ent.offsets[4]|=tab[a]<<8;
  1203.       }
  1204.       if (line.getnumtokens() > 7)
  1205.       {
  1206.         char *s=line.gettoken_str(7);
  1207.         if (*s)
  1208.         {
  1209.           int c=0;
  1210.           if (strstr(s,"ALT|")) ent.offsets[4]|=HOTKEYF_ALT << 24;
  1211.           if (strstr(s,"CONTROL|")) ent.offsets[4]|=HOTKEYF_CONTROL << 24;
  1212.           if (strstr(s,"EXT|")) ent.offsets[4]|=HOTKEYF_EXT << 24;
  1213.           if (strstr(s,"SHIFT|")) ent.offsets[4]|=HOTKEYF_SHIFT << 24;
  1214.           while (strstr(s,"|"))
  1215.           {
  1216.             s=strstr(s,"|")+1;
  1217.           }
  1218.           if ((s[0] == 'f' || s[0] == 'F') && (s[1] >= '1' && s[1] <= '9'))
  1219.           {
  1220.             c=VK_F1-1+atoi(s+1);
  1221.             if (atoi(s+1) < 1 || atoi(s+1) > 24)
  1222.             {
  1223.               warning("CreateShortCut: F-key \"%s\" out of range (%s:%d)\n",s,curfilename,linecnt);
  1224.             }
  1225.           }
  1226.           else if (s[0] >= 'a' && s[0] <= 'z' && !s[1])
  1227.             c=s[0]+'A'-'a';
  1228.           else if (((s[0] >= 'A' && s[0] <= 'Z') || (s[0] >= '0' && s[0] <= '9')) && !s[1])
  1229.             c=s[0];
  1230.           else
  1231.           {
  1232.             c=s[0];
  1233.             warning("CreateShortCut: unrecognized hotkey \"%s\" (%s:%d)\n",s,curfilename,linecnt);
  1234.           }
  1235.           ent.offsets[4] |= (c) << 16;
  1236.         }
  1237.       }
  1238.       printf("CreateShortCut: \"%s\"->\"%s\" %s  icon:%s,%d, showmode=0x%X, hotkey=0x%X\n",
  1239.         line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3),
  1240.         line.gettoken_str(4),ent.offsets[4]&0xff,(ent.offsets[4]>>8)&0xff,ent.offsets[4]>>16);
  1241.     return add_entry(&ent);
  1242.     case TOK_FINDWINDOW:
  1243.     case TOK_FINDWINDOWBYTITLE:
  1244.       ent.which=EW_FINDWINDOW;
  1245.       ent.offsets[0]=line.gettoken_enum(1,"close\0closeinstant\0prompt\0");
  1246.       if (ent.offsets[0] < 0)
  1247.       {
  1248.         if (!strnicmp(line.gettoken_str(1),"goto:",5) && strlen(line.gettoken_str(1)) > 5)
  1249.         {
  1250.           ent.offsets[0]=3;
  1251.           if (process_jump(line.gettoken_str(1)+5,&ent.offsets[4])) 
  1252.           {
  1253.             print_help(line.gettoken_str(0));
  1254.             return PS_ERROR;
  1255.           }
  1256.         }
  1257.         if (ent.offsets[0] < 0)
  1258.         {
  1259.           print_help(line.gettoken_str(0));
  1260.           return PS_ERROR;
  1261.         }
  1262.       }
  1263.       ent.offsets[1]=add_string(line.gettoken_str(2));
  1264.       ent.offsets[2]=add_string(line.gettoken_str(3));
  1265.       ent.offsets[3]=(which_token==TOK_FINDWINDOWBYTITLE);
  1266.       printf("FindWindow%s: mode=%s, class=\"%s\", text=\"%s\"\n",
  1267.         which_token==TOK_FINDWINDOWBYTITLE?"ByTitle":"",
  1268.         line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));    
  1269.     return add_entry(&ent);
  1270.     case TOK_INSTNSPLUG:
  1271. #ifndef NSIS_SUPPORT_NETSCAPEPLUGINS
  1272.       printf("InstNSPlug: support for InstNSPlug not compiled in (NSIS_SUPPORT_NETSCAPEPLUGINS)\n");
  1273.       return PS_ERROR;
  1274. #else
  1275.       {
  1276.         char dir[1024];
  1277.         char newfn[1024], *s;
  1278.         HANDLE h;
  1279.         WIN32_FIND_DATA d;
  1280.         strcpy(dir,line.gettoken_str(1));
  1281.         s=dir+strlen(dir);
  1282.         while (s > dir && *s != '\\') s--;
  1283.         *s=0;
  1284.  
  1285.         h = FindFirstFile(line.gettoken_str(1),&d);
  1286.         if (h != INVALID_HANDLE_VALUE)
  1287.         {
  1288.           do {
  1289.             HANDLE hFile,hFileMap;
  1290.             DWORD len;
  1291.             if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
  1292.             sprintf(newfn,"%s%s%s",dir,dir[0]?"\\":"",d.cFileName);
  1293.             hFile=CreateFile(newfn,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  1294.             if (hFile == INVALID_HANDLE_VALUE)
  1295.             {
  1296.               printf("InstNSPlug: failed opening file \"%s\"\n",newfn);
  1297.               return PS_ERROR;
  1298.             }
  1299.             len = GetFileSize(hFile, NULL);
  1300.             if (!len || !(hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL)))
  1301.             {
  1302.               CloseHandle(hFile);
  1303.               printf("InstNSPlug: failed creating mmap of \"%s\" (file is %d bytes)\n",newfn,len);
  1304.               return PS_ERROR;
  1305.             }
  1306.             char *filedata=(char*)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
  1307.             if (!filedata)
  1308.             {
  1309.               CloseHandle(hFileMap);
  1310.               CloseHandle(hFile);
  1311.               printf("InstNSPlug: failed mmapping file \"%s\"\n",newfn);
  1312.               return PS_ERROR;
  1313.             }
  1314.  
  1315.             section_add_size_kb((len+1023)/1024);
  1316.  
  1317.             printf("InstNSPlug: \"%s\"",d.cFileName);
  1318.             if (build_compress)
  1319.             {
  1320.               printf(" [compress]");
  1321.               fflush(stdout);
  1322.             }
  1323.             int last_build_datablock_used=getcurdbsize();
  1324.             ent.which=EW_INSTNETSCAPE;
  1325.             ent.offsets[0]=add_string(d.cFileName);
  1326.             ent.offsets[1]=0;
  1327.             ent.offsets[2]=add_data(filedata,len);
  1328.  
  1329.             UnmapViewOfFile(filedata);
  1330.             CloseHandle(hFileMap);
  1331.  
  1332.             if (ent.offsets[2] < 0)
  1333.             {
  1334.               CloseHandle(hFile);
  1335.               return PS_ERROR;
  1336.             }
  1337.  
  1338.             {
  1339.               DWORD s=getcurdbsize()-last_build_datablock_used;
  1340.               if (s) s-=4;
  1341.               if (s != len) printf(" %d/%d bytes\n",s,len);
  1342.               else printf(" %d bytes\n",len);
  1343.             }
  1344.  
  1345.  
  1346.             if (build_datesave)
  1347.             {
  1348.               FILETIME ft;
  1349.               if (GetFileTime(hFile,NULL,NULL,&ft))
  1350.               {
  1351.                 ent.offsets[3]=ft.dwHighDateTime;
  1352.                 ent.offsets[4]=ft.dwLowDateTime;
  1353.               }
  1354.               else
  1355.               {
  1356.                 printf("InstNSPlug: failed getting file date from \"%s\"\n",newfn);
  1357.                 CloseHandle(hFile);
  1358.                 return PS_ERROR;
  1359.               }
  1360.             }
  1361.             else
  1362.             {
  1363.               ent.offsets[3]=0xffffffff;
  1364.               ent.offsets[4]=0xffffffff;
  1365.             }
  1366.             CloseHandle(hFile);
  1367.  
  1368.             int a=add_entry(&ent);
  1369.             if (a != PS_OK) return a;
  1370.           } while (FindNextFile(h,&d));
  1371.           FindClose(h);
  1372.         }
  1373.         else
  1374.         {
  1375.           printf("InstNSPlug: failed finding file \"%s\"\n",line.gettoken_str(1));
  1376.           print_help(line.gettoken_str(0));
  1377.           return PS_ERROR;
  1378.         }
  1379.       }
  1380.     return PS_OK;
  1381. #endif
  1382.     case TOK_DELETENSPLUG:
  1383. #ifndef NSIS_SUPPORT_NETSCAPEPLUGINS
  1384.       printf("DeleteNSPlug: support for DeleteNSPlug not compiled in (NSIS_SUPPORT_NETSCAPEPLUGINS)\n");
  1385.       return PS_ERROR;
  1386. #else
  1387.       ent.which=EW_INSTNETSCAPE;
  1388.       ent.offsets[0]=add_string(line.gettoken_str(1));
  1389.       ent.offsets[1]=1;
  1390.       ent.offsets[2]=0;
  1391.       printf("DeleteNSPlug: \"%s\"\n",line.gettoken_str(1));
  1392.     return add_entry(&ent);
  1393. #endif
  1394.     case TOK_DELETE:
  1395.       {
  1396.         int a=1;
  1397.         ent.which=EW_DELETEFILE;
  1398.         if (!stricmp(line.gettoken_str(a),"/REBOOTOK"))
  1399.         {
  1400.           a++;
  1401.           ent.offsets[1]=1;
  1402.         }
  1403.         else if (line.gettoken_str(1)[0]=='/')
  1404.         {
  1405.           a=line.getnumtokens();
  1406.         }
  1407.         if (line.getnumtokens() != a+1)
  1408.         {
  1409.           print_help(line.gettoken_str(0));
  1410.           return PS_ERROR;
  1411.         }
  1412.         ent.offsets[0]=add_string(line.gettoken_str(a));
  1413.         printf("Delete: %s\"%s\"\n",ent.offsets[1]?"/REBOOTOK ":"",line.gettoken_str(a));
  1414.       }
  1415.     return add_entry(&ent);
  1416.     case TOK_RMDIR:
  1417.       {
  1418.         int a=1;
  1419.         ent.which=EW_RMDIR;
  1420.         if (!stricmp(line.gettoken_str(1),"/r"))
  1421.         {
  1422.           if (line.getnumtokens() < 3)
  1423.           {
  1424.             print_help(line.gettoken_str(0));
  1425.             return PS_ERROR;
  1426.           }
  1427.           a++;
  1428.           ent.offsets[1]=1;
  1429.         }
  1430.         else if (line.gettoken_str(1)[0]=='/')
  1431.         {
  1432.           print_help(line.gettoken_str(0));
  1433.           return PS_ERROR;
  1434.         }
  1435.         ent.offsets[0]=add_string(line.gettoken_str(a));
  1436.         printf("RMDir: %s\"%s\"\n",ent.offsets[1]?"/r " : "",line.gettoken_str(a));
  1437.       }
  1438.     return add_entry(&ent);
  1439.     case TOK_FILE:
  1440.       {
  1441.         int a=1,rec=0;
  1442.         if (!stricmp(line.gettoken_str(a),"/r"))
  1443.         {
  1444.           rec=1;
  1445.           a++;
  1446.         }
  1447.         else if (!strnicmp(line.gettoken_str(a),"/oname=",7))
  1448.         {
  1449.           char *on=line.gettoken_str(a)+7;
  1450.           a++;
  1451.           if (!*on||line.getnumtokens()!=a+1||strstr(on,"*") || strstr(on,"?") || strstr(on,"\\"))
  1452.           {
  1453.             print_help(line.gettoken_str(0));
  1454.             return PS_ERROR;
  1455.           }
  1456.  
  1457.           int tf=0;
  1458.           int v=do_add_file(line.gettoken_str(a), 0, linecnt,&tf,on);
  1459.           if (v != PS_OK) return v;
  1460.           if (tf > 1)
  1461.           {
  1462.             print_help(line.gettoken_str(0));
  1463.             return PS_ERROR;
  1464.           }
  1465.           if (!tf)
  1466.           {
  1467.             print_help(line.gettoken_str(0));
  1468.             printf("File: \"%s\" -> no files found.\n",line.gettoken_str(a));
  1469.             return PS_ERROR;
  1470.           }
  1471.  
  1472.  
  1473.           return PS_OK;
  1474.         }
  1475.         else if (line.gettoken_str(a)[0] == '/')
  1476.         {
  1477.           print_help(line.gettoken_str(0));
  1478.           return PS_ERROR;          
  1479.         }
  1480.         if (line.getnumtokens()<a+1)
  1481.         {
  1482.           print_help(line.gettoken_str(0));
  1483.           return PS_ERROR;
  1484.         }
  1485.         while (a < line.getnumtokens())
  1486.         {
  1487.           if (line.gettoken_str(a)[0]=='/')
  1488.           {
  1489.             print_help(line.gettoken_str(0));
  1490.             return PS_ERROR;
  1491.           }
  1492.           char buf[32];
  1493.           char *t=line.gettoken_str(a++);
  1494.           if (t[0] && t[1] == ':' && t[2] == '\\' && !t[3])
  1495.           {
  1496.             strcpy(buf,"X:\\*.*");
  1497.             buf[0]=t[0];
  1498.             t=buf;
  1499.           }
  1500.           int tf=0;
  1501.           int v=do_add_file(t, rec, linecnt,&tf);
  1502.           if (v != PS_OK) return v;
  1503.           if (!tf)
  1504.           {
  1505.             printf("File: \"%s\" -> no files found.\n",t);
  1506.             print_help(line.gettoken_str(0));
  1507.             return PS_ERROR;
  1508.           }
  1509.         }
  1510.       }
  1511.     return PS_OK;
  1512.     case TOK_COPYFILES:
  1513.       {
  1514.         ent.which=EW_COPYFILES;
  1515.         ent.offsets[0]=add_string(line.gettoken_str(1));
  1516.         ent.offsets[1]=add_string(line.gettoken_str(2));
  1517.         int s;
  1518.         int size_kb=line.gettoken_int(3,&s);
  1519.         if (!s)
  1520.         {
  1521.           print_help(line.gettoken_str(0));
  1522.           return PS_ERROR;
  1523.         }
  1524.         section_add_size_kb(size_kb);
  1525.         printf("CopyFiles: \"%s\" -> \"%s\", size=%iKb\n",line.gettoken_str(1),line.gettoken_str(2),size_kb);
  1526.       }
  1527.     return add_entry(&ent);
  1528.     case TOK_SETFILEATTRIBUTES:
  1529.       {
  1530.         #define MBD(x) {x,#x},
  1531.         struct 
  1532.         {
  1533.           int id;
  1534.           char *str;
  1535.         } list[]=
  1536.         {
  1537.           MBD(FILE_ATTRIBUTE_NORMAL)
  1538.           MBD(FILE_ATTRIBUTE_ARCHIVE)
  1539.           MBD(FILE_ATTRIBUTE_HIDDEN)
  1540.           MBD(FILE_ATTRIBUTE_OFFLINE)
  1541.           MBD(FILE_ATTRIBUTE_READONLY)
  1542.           MBD(FILE_ATTRIBUTE_SYSTEM)
  1543.           MBD(FILE_ATTRIBUTE_TEMPORARY)
  1544.           {FILE_ATTRIBUTE_NORMAL,"NORMAL"},
  1545.           {FILE_ATTRIBUTE_ARCHIVE,"ARCHIVE"},
  1546.           {FILE_ATTRIBUTE_HIDDEN,"HIDDEN"},
  1547.           {FILE_ATTRIBUTE_OFFLINE,"OFFLINE"},
  1548.           {FILE_ATTRIBUTE_READONLY,"READONLY"},
  1549.           {FILE_ATTRIBUTE_SYSTEM,"SYSTEM"},
  1550.           {FILE_ATTRIBUTE_TEMPORARY,"TEMPORARY"},
  1551.           {FILE_ATTRIBUTE_NORMAL,"0"},
  1552.         };
  1553.         #undef MBD
  1554.         int r=0;
  1555.         int x;
  1556.         char *p=line.gettoken_str(2);
  1557.  
  1558.         while (*p)
  1559.         {
  1560.           char *np=p;
  1561.           while (*np && *np != '|') np++;
  1562.           if (*np) *np++=0;
  1563.           for (x  =0 ; x < sizeof(list)/sizeof(list[0]) && stricmp(list[x].str,p); x ++);
  1564.  
  1565.           if (x < sizeof(list)/sizeof(list[0]))
  1566.           {
  1567.             r|=list[x].id;
  1568.           }
  1569.           else
  1570.           {
  1571.             print_help(line.gettoken_str(0));
  1572.             return PS_ERROR;
  1573.           }            
  1574.           p=np;
  1575.         }
  1576.         ent.which=EW_SETFILEATTRIBUTES;
  1577.         ent.offsets[0]=add_string(line.gettoken_str(1));
  1578.         ent.offsets[1]=r;
  1579.       }
  1580.     return add_entry(&ent);
  1581.     case TOK_SLEEP:
  1582.       {
  1583.         int s;
  1584.         ent.which=EW_SLEEP;        
  1585.         ent.offsets[0]=line.gettoken_int(1,&s);
  1586.         if (!s)
  1587.         {
  1588.           print_help(line.gettoken_str(0));
  1589.           return PS_ERROR;
  1590.         }
  1591.         printf("Sleep: %d ms\n",ent.offsets[0]);
  1592.       }
  1593.     return add_entry(&ent);
  1594.     case TOK_BRINGTOFRONT:
  1595.       ent.which=EW_BRINGTOFRONT;        
  1596.       printf("BringToFront\n");
  1597.     return add_entry(&ent);
  1598.     case TOK_HIDEWINDOW:
  1599.       ent.which=EW_HIDEWINDOW;        
  1600.       printf("HideWindow\n");
  1601.     return add_entry(&ent);
  1602.     case TOK_IFFILEEXISTS:
  1603.       ent.which=EW_IFFILEEXISTS;
  1604.       ent.offsets[0] = add_string(line.gettoken_str(1));
  1605.       if (process_jump(line.gettoken_str(2),&ent.offsets[1]) || 
  1606.           process_jump(line.gettoken_str(3),&ent.offsets[2])) 
  1607.       {
  1608.         print_help(line.gettoken_str(0));
  1609.         return PS_ERROR;
  1610.       }
  1611.       printf("IfFileExists: \"%s\" ? %s : %s\n",line.gettoken_str(1),line.gettoken_str(2),line.gettoken_str(3));
  1612.     return add_entry(&ent);
  1613.     case TOK_ABORT:
  1614.       ent.which=EW_ABORT;
  1615.       ent.offsets[0] = add_string(line.gettoken_str(1));
  1616.       printf("Abort: \"%s\"\n",line.gettoken_str(1));
  1617.     return add_entry(&ent);
  1618.     case TOK_SETDETAILSVIEW:
  1619.       ent.which=EW_CHDETAILSVIEW;
  1620.       ent.offsets[0] = line.gettoken_enum(1,"hide\0show\0");
  1621.       if (ent.offsets[0] < 0)
  1622.       {
  1623.         print_help(line.gettoken_str(0));
  1624.         return PS_ERROR;
  1625.       }
  1626.       printf("SetDetailsView: %s\n",line.gettoken_str(1));
  1627.     return add_entry(&ent);
  1628.     case TOK_SETAUTOCLOSE:
  1629.       ent.which=EW_SETWINDOWCLOSE;
  1630.       ent.offsets[0] = line.gettoken_enum(1,"false\0true\0");
  1631.       if (ent.offsets[0] < 0)
  1632.       {
  1633.         print_help(line.gettoken_str(0));
  1634.         return PS_ERROR;
  1635.       }
  1636.       printf("SetAutoClose: %s\n",line.gettoken_str(1));
  1637.     return add_entry(&ent);
  1638.     case TOK_IFERRORS:
  1639.       {
  1640.         int s=1;
  1641.         ent.which=EW_IFERRORS;
  1642.         if (process_jump(line.gettoken_str(1),&ent.offsets[0]) || 
  1643.             process_jump(line.gettoken_str(2),&ent.offsets[1])) 
  1644.         {
  1645.           print_help(line.gettoken_str(0));
  1646.           return PS_ERROR;
  1647.         }
  1648.         printf("IfErrors ?%s:%s\n",line.gettoken_str(1),line.gettoken_str(2));
  1649.       }
  1650.     return add_entry(&ent);
  1651.     case TOK_CLEARERRORS:
  1652.       ent.which=EW_IFERRORS;
  1653.       printf("ClearErrors\n");
  1654.     return add_entry(&ent);
  1655.     case TOK_SETERRORS:
  1656.       ent.which=EW_IFERRORS;
  1657.       ent.offsets[2]=1;
  1658.       printf("SetErrors\n");
  1659.     return add_entry(&ent);
  1660.     case TOK_STRCPY:
  1661.       ent.which=EW_ASSIGNVAR;
  1662.       ent.offsets[0]=line.gettoken_enum(1,usrvars);
  1663.       ent.offsets[1]=add_string(line.gettoken_str(2));
  1664.       if (line.getnumtokens()>3)
  1665.       {
  1666.         int s;
  1667.         ent.offsets[2]=line.gettoken_int(3,&s);
  1668.         if (!s || !ent.offsets[2]) ent.offsets[0]=-1;
  1669.       }
  1670.       if (ent.offsets[0] < 0)
  1671.       {
  1672.         print_help(line.gettoken_str(0));
  1673.         return PS_ERROR;
  1674.       }
  1675.       printf("StrCpy $%d \"%s\" (%d)\n",ent.offsets[0],line.gettoken_str(2),ent.offsets[2]);
  1676.     return add_entry(&ent);
  1677.     case TOK_GETPARENTDIR:
  1678.       ent.which=EW_GETPARENT;
  1679.       ent.offsets[0]=line.gettoken_enum(1,usrvars);
  1680.       ent.offsets[1]=add_string(line.gettoken_str(2));
  1681.       if (ent.offsets[0] < 0)
  1682.       {
  1683.         print_help(line.gettoken_str(0));
  1684.         return PS_ERROR;
  1685.       }
  1686.       printf("GetParentDir $%d \"%s\" (%d)\n",ent.offsets[0],line.gettoken_str(2),ent.offsets[2]);
  1687.     return add_entry(&ent);
  1688.     case TOK_STRCMP:
  1689.       ent.which=EW_STRCMP;
  1690.       ent.offsets[0]=add_string(line.gettoken_str(1));
  1691.       ent.offsets[1]=add_string(line.gettoken_str(2));
  1692.       if (process_jump(line.gettoken_str(3),&ent.offsets[2]) ||
  1693.           process_jump(line.gettoken_str(4),&ent.offsets[3])) 
  1694.       {
  1695.         print_help(line.gettoken_str(0));
  1696.         return PS_ERROR;
  1697.       }
  1698.       printf("StrCmp \"%s\" \"%s\" equal=%s, nonequal=%s\n",line.gettoken_str(1),line.gettoken_str(2), line.gettoken_str(3),line.gettoken_str(4));
  1699.     return add_entry(&ent);
  1700.     case TOK_READINISTR:
  1701.       ent.which=EW_READINISTR;
  1702.       ent.offsets[0]=line.gettoken_enum(1,usrvars);
  1703.       if (ent.offsets[0] < 0)
  1704.       {
  1705.         print_help(line.gettoken_str(0));
  1706.         return PS_ERROR;
  1707.       }
  1708.       ent.offsets[1]=add_string(line.gettoken_str(3));
  1709.       ent.offsets[2]=add_string(line.gettoken_str(4));
  1710.       ent.offsets[3]=add_string(line.gettoken_str(2));
  1711.       printf("ReadINIStr $%d [%s]:%s from %s\n",ent.offsets[0],line.gettoken_str(3),line.gettoken_str(4),line.gettoken_str(2));
  1712.     return add_entry(&ent);
  1713.     case TOK_READREGSTR:
  1714.       {
  1715.         ent.which=EW_READREGSTR;
  1716.         ent.offsets[0]=line.gettoken_enum(1,usrvars);
  1717.         int k=line.gettoken_enum(2,rootkeys[0]);
  1718.         if (k == -1) k=line.gettoken_enum(2,rootkeys[1]);
  1719.         if (ent.offsets[0] < 0 || k == -1)
  1720.         {
  1721.           print_help(line.gettoken_str(0));
  1722.           return PS_ERROR;
  1723.         }
  1724.         ent.offsets[1]=(int)rootkey_tab[k];
  1725.         ent.offsets[2]=add_string(line.gettoken_str(3));
  1726.         ent.offsets[3]=add_string(line.gettoken_str(4));
  1727.         printf("ReadRegStr $%d %s\\%s\\%s\n",ent.offsets[0],line.gettoken_str(2),line.gettoken_str(3),line.gettoken_str(4));
  1728.       }
  1729.     return add_entry(&ent);
  1730.     case TOK_DETAILPRINT:
  1731.       ent.which=EW_UPDATETEXT;
  1732.       ent.offsets[0]=add_string(line.gettoken_str(1));
  1733.       printf("DetailPrint: \"%s\"\n",line.gettoken_str(1));
  1734.     return add_entry(&ent);
  1735.     case TOK_GETFULLDLLPATH:
  1736.       ent.which=EW_GETFULLDLLPATH;
  1737.       ent.offsets[0]=line.gettoken_enum(1,usrvars);
  1738.       if (ent.offsets[0] < 0)
  1739.       {
  1740.         print_help(line.gettoken_str(0));
  1741.         return PS_ERROR;
  1742.       }
  1743.       ent.offsets[1]=add_string(line.gettoken_str(2));
  1744.       printf("GetFullDLLPath $%d %s\n",ent.offsets[0],line.gettoken_str(2));
  1745.     return add_entry(&ent);
  1746.     case TOK_COMPAREDLLS: // The version/date storing is based on ideas from Davison Long
  1747.       {
  1748.         int a=1;
  1749.         int flag=0;
  1750.         ent.which=EW_COMPAREDLLS;
  1751.         if (!stricmp(line.gettoken_str(a),"/STOREFROM"))
  1752.         {
  1753.           DWORD s;
  1754.           DWORD d;
  1755.           s=GetFileVersionInfoSize(line.gettoken_str(++a),&d);
  1756.           if (s)
  1757.           {
  1758.             void *buf;
  1759.             buf=(void*)GlobalAlloc(GPTR,s);
  1760.             if (buf)
  1761.             {
  1762.               UINT uLen;
  1763.               VS_FIXEDFILEINFO *pvsf;
  1764.               if (GetFileVersionInfo(line.gettoken_str(a),0,s,buf) && VerQueryValue(buf,"\\",(void**)&pvsf,&uLen))
  1765.               {
  1766.                 ent.offsets[0]=pvsf->dwFileVersionLS;
  1767.                 ent.offsets[4]=pvsf->dwFileVersionMS;
  1768.                 flag=0x80000000;
  1769.               }
  1770.               GlobalFree(buf);
  1771.             }
  1772.  
  1773.           }
  1774.           if (!flag)
  1775.           {
  1776.             printf("CompareDLLVersions: error reading version info from \"%s\"\n",line.gettoken_str(a));
  1777.             return PS_ERROR;
  1778.           }
  1779.           a++;
  1780.         }
  1781.         else
  1782.         {
  1783.           if (line.gettoken_str(a)[0]=='/')
  1784.           {
  1785.             print_help(line.gettoken_str(0));
  1786.             return PS_ERROR;
  1787.           }
  1788.           ent.offsets[0]=add_string(line.gettoken_str(a++));
  1789.         }
  1790.         ent.offsets[1]=add_string(line.gettoken_str(a++))|flag;
  1791.  
  1792.         if (process_jump(line.gettoken_str(a++),&ent.offsets[2]) ||
  1793.             process_jump(line.gettoken_str(a++),&ent.offsets[3]) || 
  1794.             a != line.getnumtokens()) 
  1795.         {
  1796.           print_help(line.gettoken_str(0));
  1797.           return PS_ERROR;
  1798.         }
  1799.         if (flag)
  1800.           printf("CompareDLLVersions: %08X:%08X > \"%s\" ? \"%s\" : \"%s\"\n",
  1801.             ent.offsets[4],ent.offsets[0],
  1802.             line.gettoken_str(a-3),
  1803.             line.gettoken_str(a-2),
  1804.             line.gettoken_str(a-1));
  1805.         else
  1806.           printf("CompareDLLVersions: \"%s\" > \"%s\" ? \"%s\" : \"%s\"\n",
  1807.             line.gettoken_str(a-4),
  1808.             line.gettoken_str(a-3),
  1809.             line.gettoken_str(a-2),
  1810.             line.gettoken_str(a-1));
  1811.       }
  1812.     return add_entry(&ent);
  1813.     case TOK_COMPAREFILETIMES:
  1814.       {
  1815.         int a=1;
  1816.         int flag=0;
  1817.         ent.which=EW_COMPAREFILETIMES;
  1818.         if (!stricmp(line.gettoken_str(a),"/STOREFROM"))
  1819.         {
  1820.           HANDLE hFile=CreateFile(line.gettoken_str(++a),0,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  1821.           if (hFile != INVALID_HANDLE_VALUE)
  1822.           {
  1823.             FILETIME ft;
  1824.             if (GetFileTime(hFile,NULL,NULL,&ft))
  1825.             {
  1826.               ent.offsets[4]=ft.dwHighDateTime;
  1827.               ent.offsets[0]=ft.dwLowDateTime;
  1828.               flag=0x80000000;
  1829.             }            
  1830.             CloseHandle(hFile);
  1831.           }
  1832.           if (!flag)
  1833.           {
  1834.             printf("CompareFileTimes: error reading date from \"%s\"\n",line.gettoken_str(a));
  1835.             return PS_ERROR;
  1836.           }
  1837.           a++;
  1838.         }
  1839.         else
  1840.         {
  1841.           if (line.gettoken_str(a)[0]=='/')
  1842.           {
  1843.             print_help(line.gettoken_str(0));
  1844.             return PS_ERROR;
  1845.           }
  1846.           ent.offsets[0]=add_string(line.gettoken_str(a++));
  1847.         }
  1848.         ent.offsets[1]=add_string(line.gettoken_str(a++))|flag;
  1849.         if (process_jump(line.gettoken_str(a++),&ent.offsets[2]) ||
  1850.             process_jump(line.gettoken_str(a++),&ent.offsets[3]) ||
  1851.             a != line.getnumtokens()) 
  1852.         {
  1853.           print_help(line.gettoken_str(0));
  1854.           return PS_ERROR;
  1855.         }
  1856.         if (flag)
  1857.           printf("CompareFileTimes: %08X:%08X > \"%s\" ? \"%s\" : \"%s\"\n",
  1858.             ent.offsets[4],ent.offsets[0],
  1859.             line.gettoken_str(a-3),
  1860.             line.gettoken_str(a-2),
  1861.             line.gettoken_str(a-1));
  1862.         else
  1863.           printf("CompareFileTimes: \"%s\" > \"%s\" ? \"%s\" : \"%s\"\n",
  1864.             line.gettoken_str(a-4),
  1865.             line.gettoken_str(a-3),
  1866.             line.gettoken_str(a-2),
  1867.             line.gettoken_str(a-1));
  1868.       }
  1869.     return add_entry(&ent);
  1870.  
  1871.     // end of instructions
  1872.     ///////////////////////////////////////////////////////////////////////////////
  1873.  
  1874.     default: break;
  1875.  
  1876.   }
  1877.   printf("Error: doCommand: Invalid token \"%s\".\n",line.gettoken_str(0));
  1878.   return PS_ERROR;
  1879. }
  1880.  
  1881. int CEXEBuild::do_add_file(char *lgss, int recurse, int linecnt, int *total_files, char *name_override)
  1882. {
  1883.   char dir[1024];
  1884.   char newfn[1024], *s;
  1885.   HANDLE h;
  1886.   WIN32_FIND_DATA d;
  1887.   strcpy(dir,lgss);
  1888.   s=dir+strlen(dir);
  1889.   while (s > dir && *s != '\\') s--;
  1890.   *s=0;
  1891.  
  1892.   h = FindFirstFile(lgss,&d);
  1893.   if (h != INVALID_HANDLE_VALUE)
  1894.   {
  1895.     do 
  1896.     {
  1897.       if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
  1898.       {
  1899.         if (recurse && strcmp(d.cFileName,"..") && strcmp(d.cFileName,".")) 
  1900.         {
  1901.           entry ent={0,};
  1902.           int a;
  1903.           char wd_save[1024];
  1904.           strcpy(wd_save,cur_out_path);
  1905.           if (cur_out_path[strlen(cur_out_path)-1]!='\\') strcat(cur_out_path,"\\");
  1906.           strcat(cur_out_path,d.cFileName);
  1907.           (*total_files)++;
  1908.           ent.which=EW_SETOUTPUTDIR;
  1909.           ent.offsets[0]=add_string(cur_out_path);
  1910.           a=add_entry(&ent);
  1911.           if (a != PS_OK) 
  1912.           {
  1913.             FindClose(h);
  1914.             return a;
  1915.           }
  1916.  
  1917.           char spec[1024];
  1918.           sprintf(spec,"%s%s%s",dir,dir[0]?"\\":"",d.cFileName);
  1919.           printf("File: Descending to: \"%s\" -> \"%s\"\n",spec,cur_out_path);
  1920.           strcat(spec,"\\*.*");
  1921.           a=do_add_file(spec,recurse,linecnt,total_files);
  1922.           if (a != PS_OK)
  1923.           {
  1924.             FindClose(h);
  1925.             return a;
  1926.           }
  1927.  
  1928.           strcpy(cur_out_path,wd_save);
  1929.           ent.which=EW_SETOUTPUTDIR;
  1930.           printf("File: Returning to: \"%s\" -> \"%s\"\n",dir,cur_out_path);
  1931.           ent.offsets[0]=add_string(cur_out_path);
  1932.           a=add_entry(&ent);
  1933.           if (a != PS_OK) 
  1934.           {
  1935.             FindClose(h);
  1936.             return a;
  1937.           }
  1938.         }
  1939.       }
  1940.       else
  1941.       {
  1942.         HANDLE hFile,hFileMap;
  1943.         DWORD len;
  1944.         (*total_files)++;
  1945.         sprintf(newfn,"%s%s%s",dir,dir[0]?"\\":"",d.cFileName);
  1946.         hFile=CreateFile(newfn,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  1947.         if (hFile == INVALID_HANDLE_VALUE)
  1948.         {
  1949.           printf("File: failed opening file \"%s\"\n",newfn);
  1950.           return PS_ERROR;
  1951.         }
  1952.         hFileMap=NULL;
  1953.         len = GetFileSize(hFile, NULL);
  1954.         if (len && !(hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL)))
  1955.         {
  1956.           CloseHandle(hFile);
  1957.           printf("File: failed creating mmap of \"%s\"\n",newfn);
  1958.           return PS_ERROR;
  1959.         }
  1960.         char *filedata=NULL;
  1961.         if (len)
  1962.         {
  1963.           filedata=(char*)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
  1964.           if (!filedata)
  1965.           {
  1966.             if (hFileMap) CloseHandle(hFileMap);
  1967.             CloseHandle(hFile);
  1968.             printf("File: failed mmapping file \"%s\"\n",newfn);
  1969.             return PS_ERROR;
  1970.           }
  1971.         }
  1972.  
  1973.         section_add_size_kb((len+1023)/1024);
  1974.         if (name_override) printf("File: \"%s\"->\"%s\"",d.cFileName,name_override);
  1975.         else printf("File: \"%s\"",d.cFileName);
  1976.         if (build_compress) printf(" [compress]");
  1977.         fflush(stdout);
  1978.  
  1979.         int last_build_datablock_used=getcurdbsize();
  1980.         entry ent={0,};
  1981.         ent.which=EW_EXTRACTFILE;
  1982.         ent.offsets[0]=build_overwrite;
  1983.         ent.offsets[1]=add_string(name_override?name_override:d.cFileName);
  1984.         ent.offsets[2]=add_data(filedata?filedata:"",len);
  1985.  
  1986.         if (filedata) UnmapViewOfFile(filedata);
  1987.         if (hFileMap) CloseHandle(hFileMap);
  1988.  
  1989.         if (ent.offsets[2] < 0) 
  1990.         {
  1991.           CloseHandle(hFile);
  1992.           return PS_ERROR;
  1993.         }
  1994.  
  1995.         {
  1996.           DWORD s=getcurdbsize()-last_build_datablock_used;
  1997.           if (s) s-=4;
  1998.           if (s != len) printf(" %d/%d bytes\n",s,len);
  1999.           else printf(" %d bytes\n",len);
  2000.         }
  2001.  
  2002.         if (build_datesave || build_overwrite==0x3 /*ifnewer*/)
  2003.         {
  2004.           FILETIME ft;
  2005.           if (GetFileTime(hFile,NULL,NULL,&ft))
  2006.           {
  2007.             ent.offsets[3]=ft.dwHighDateTime;
  2008.             ent.offsets[4]=ft.dwLowDateTime;
  2009.           }
  2010.           else
  2011.           {
  2012.             CloseHandle(hFile);
  2013.             printf("File: failed getting file date from \"%s\"\n",newfn);
  2014.             return PS_ERROR;
  2015.           }
  2016.         }
  2017.         else
  2018.         {
  2019.           ent.offsets[3]=0xffffffff;
  2020.           ent.offsets[4]=0xffffffff;
  2021.         }
  2022.  
  2023.         CloseHandle(hFile);
  2024.         int a=add_entry(&ent);
  2025.         if (a != PS_OK) 
  2026.         {
  2027.           FindClose(h);
  2028.           return a;
  2029.         }
  2030.       }
  2031.     } while (FindNextFile(h,&d));
  2032.     FindClose(h);
  2033.   }
  2034.   return PS_OK;
  2035. }
  2036.   
  2037.