2002-08-02 10:01:35 +00:00
/*
2004-02-23 18:39:50 +00:00
2003-03-14 19:29:17 +00:00
Nullsoft Scriptable Install System ( NSIS )
makensis . cpp - installer compiler code
2002-08-02 10:01:35 +00:00
2006-01-20 12:36:30 +00:00
Copyright ( C ) 1999 - 2006 Nullsoft , Inc .
2004-02-23 18:39:50 +00:00
This license applies to everything in the NSIS package , except where otherwise noted .
2002-08-02 10:01:35 +00:00
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be
misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
2003-03-14 19:29:17 +00:00
This is the zlib / libpng license , which is approved by opensource . org .
Portions Copyright ( C ) 1995 - 1998 Jean - loup Gailly and Mark Adler ( zlib ) .
2004-02-23 18:39:50 +00:00
Portions Copyright ( C ) 1996 - 2002 Julian R Seward ( bzip2 ) .
Portions Copyright ( C ) 1999 - 2003 Igor Pavlov ( lzma ) .
2002-08-02 10:01:35 +00:00
*/
2004-01-30 22:04:10 +00:00
# include "Platform.h"
2002-08-02 10:01:35 +00:00
# include <stdio.h>
# include <signal.h>
2004-03-29 20:21:00 +00:00
# ifdef _WIN32
# include <direct.h>
2004-10-25 17:51:55 +00:00
# else
# include <unistd.h>
2004-03-29 20:21:00 +00:00
# endif
2004-11-30 18:00:27 +00:00
# include <string>
2002-08-02 10:01:35 +00:00
# include "build.h"
# include "util.h"
2004-11-30 18:00:27 +00:00
using namespace std ;
2002-08-02 10:01:35 +00:00
2002-11-20 17:41:00 +00:00
int g_noconfig = 0 ;
2002-08-02 10:01:35 +00:00
int g_display_errors = 1 ;
FILE * g_output = stdout ;
void quit ( )
{
if ( g_display_errors )
{
fprintf ( g_output , " \n Note: you may have one or two (large) stale temporary file(s) \n "
" left in your temporary directory (Generally this only happens on Windows 9x). \n " ) ;
fflush ( g_output ) ;
}
exit ( 1 ) ;
}
static void myatexit ( )
{
dopause ( ) ;
if ( g_output ! = stdout & & g_output ) fclose ( g_output ) ;
}
static void sigint ( int sig )
{
if ( g_display_errors )
{
fprintf ( g_output , " \n \n Aborting on Ctrl+C... \n " ) ;
fflush ( g_output ) ;
}
quit ( ) ;
}
2005-07-02 13:15:28 +00:00
static void print_logo ( )
{
2006-01-20 12:36:30 +00:00
fprintf ( g_output , " MakeNSIS %s - Copyright 1999-2006 Nullsoft, Inc. \n "
2005-07-02 13:15:28 +00:00
" \n "
" Portions Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler (zlib). \n "
" Portions Copyright (C) 1996-2002 Julian R Seward (bzip2). \n "
" Portions Copyright (C) 1999-2003 Igor Pavlov (lzma). \n "
" \n "
" Contributors: nnop@newmail.ru, Ryan Geiss, Andras Varga, Drew Davidson, Peter Windridge, Dave Laundon, Robert Rainwater, Yaroslav Faybishenko, Jeff Doozan, Amir Szekely, Ximon Eighteen, et al. \n \n " , CONST_STR ( NSIS_VERSION ) ) ;
fflush ( g_output ) ;
}
static void print_license ( )
{
2006-01-20 12:36:30 +00:00
fprintf ( g_output , " Copyright (C) 1999-2006 Nullsoft, Inc. \n \n "
2005-07-02 13:15:28 +00:00
" This license applies to everything in the NSIS package, except where otherwise \n noted. \n \n "
" This software is provided 'as-is', without any express or implied warranty. \n "
" In no event will the authors be held liable for any damages arising from the \n "
" use of this software. \n \n "
" Permission is granted to anyone to use this software for any purpose, including \n "
" commercial applications, and to alter it and redistribute it freely, subject to \n "
" the following restrictions: \n "
" 1. The origin of this software must not be misrepresented; you must not claim \n "
" that you wrote the original software. If you use this software in a \n "
" product, an acknowledgment in the product documentation would be \n "
" appreciated but is not required. \n "
" 2. Altered source versions must be plainly marked as such, and must not be \n "
" misrepresented as being the original software. \n "
" 3. This notice may not be removed or altered from any source distribution. \n \n " ) ;
fflush ( g_output ) ;
}
static void print_usage ( )
{
fprintf ( g_output , " Usage: \n "
" makensis [option | script.nsi | - [...]] \n "
" options are: \n "
" " OPT_STR " CMDHELP item prints out help for 'item', or lists all commands \n "
" " OPT_STR " HDRINFO prints information about what options makensis was compiled with \n "
" " OPT_STR " LICENSE prints the makensis software license \n "
" " OPT_STR " VERSION prints the makensis version and exits \n "
" " OPT_STR " Vx verbosity where x is 4=all,3=no script,2=no info,1=no warnings,0=none \n "
" " OPT_STR " Ofile specifies a text file to log compiler output (default is stdout) \n "
" " OPT_STR " PAUSE pauses after execution \n "
" " OPT_STR " NOCONFIG disables inclusion of <path to makensis.exe> " PLATFORM_PATH_SEPARATOR_STR " nsisconf.nsh \n "
" " OPT_STR " NOCD disabled the current directory change to that of the .nsi file \n "
" " OPT_STR " Ddefine[=value] defines the symbol \" define \" for the script [to value] \n "
" " OPT_STR " Xscriptcmd executes scriptcmd in script (i.e. \" " OPT_STR " XOutFile poop.exe \" ) \n "
" parameters are processed by order ( " OPT_STR " Ddef ins.nsi != ins.nsi " OPT_STR " Ddef) \n "
" for script file name, you can use - to read from the standard input \n " ) ;
fflush ( g_output ) ;
}
static void print_stub_info ( CEXEBuild & build )
{
if ( build . display_info )
{
fprintf ( g_output , " Size of first header is %d bytes. \n " , sizeof ( firstheader ) ) ;
fprintf ( g_output , " Size of main header is %d bytes. \n " , sizeof ( header ) ) ;
fprintf ( g_output , " Size of each section is %d bytes. \n " , sizeof ( section ) ) ;
fprintf ( g_output , " Size of each page is %d bytes. \n " , sizeof ( page ) ) ;
fprintf ( g_output , " Size of each instruction is %d bytes. \n " , sizeof ( entry ) ) ;
int x = build . definedlist . getnum ( ) ;
fprintf ( g_output , " \n Defined symbols: " ) ;
for ( int i = 0 ; i < x ; i + + )
{
fprintf ( g_output , " %s " , build . definedlist . getname ( i ) ) ;
char * p = build . definedlist . getvalue ( i ) ;
if ( * p ) fprintf ( g_output , " =%s " , p ) ;
if ( i < x - 1 ) fprintf ( g_output , " , " ) ;
}
if ( ! x ) fprintf ( g_output , " none " ) ;
fprintf ( g_output , " \n " ) ;
fflush ( g_output ) ;
}
}
2005-07-02 12:53:37 +00:00
static string get_home ( )
{
char * home = getenv (
# ifdef _WIN32
" APPDATA "
# else
" HOME "
# endif
) ;
return home ? home : " " ;
}
static int process_config ( CEXEBuild & build , string & conf )
{
FILE * cfg = fopen ( conf . c_str ( ) , " rt " ) ;
if ( cfg )
{
if ( build . display_script )
{
fprintf ( g_output , " Processing config: \n " ) ;
fflush ( g_output ) ;
}
int ret = build . process_script ( cfg , ( char * ) conf . c_str ( ) ) ;
fclose ( cfg ) ;
if ( ret ! = PS_OK & & ret ! = PS_EOF )
{
if ( build . display_errors )
{
fprintf ( g_output , " Error in config on line %d -- aborting creation process \n " , build . linecnt ) ;
fflush ( g_output ) ;
}
return 1 ;
}
if ( build . display_script )
{
fprintf ( g_output , " \n " ) ;
fflush ( g_output ) ;
}
}
return 0 ;
}
2005-07-02 13:15:28 +00:00
static int change_to_script_dir ( CEXEBuild & build , string & script )
{
string dir = get_dir_name ( get_full_path ( script ) ) ;
if ( ! dir . empty ( ) )
{
if ( build . display_script )
{
fprintf ( g_output , " Changing directory to: \" %s \" \n " , dir . c_str ( ) ) ;
fflush ( g_output ) ;
}
if ( chdir ( dir . c_str ( ) ) )
{
if ( build . display_errors )
{
fprintf ( g_output , " Error changing directory to \" %s \" \n " , dir . c_str ( ) ) ;
fflush ( g_output ) ;
}
return 1 ;
}
if ( build . display_script )
{
fprintf ( g_output , " \n " ) ;
fflush ( g_output ) ;
}
}
return 0 ;
}
2002-08-02 10:01:35 +00:00
int main ( int argc , char * * argv )
{
CEXEBuild build ;
2002-11-14 20:03:07 +00:00
int do_cd = 1 ;
2002-08-02 10:01:35 +00:00
int outputtried = 0 ;
int argpos = 1 ;
int nousage = 0 ;
int files_processed = 0 ;
int cmds_processed = 0 ;
FILE * fp ;
int tmpargpos = 1 ;
int no_logo = 0 ;
2004-11-19 13:45:22 +00:00
# ifndef _WIN32
int in_files = 0 ;
# endif
2002-08-02 10:01:35 +00:00
2005-04-02 12:04:07 +00:00
try
{
2005-07-02 12:53:37 +00:00
build . initialize ( argv [ 0 ] ) ;
2005-04-02 12:04:07 +00:00
}
catch ( exception & err )
{
fprintf ( g_output , " Error initalizing CEXEBuild: %s \n " , err . what ( ) ) ;
fflush ( g_output ) ;
return 1 ;
}
2004-03-29 20:21:00 +00:00
2004-11-12 13:58:11 +00:00
if ( argc > 1 & & ! stricmp ( argv [ 1 ] , OPT_STR " VERSION " ) )
2002-09-13 19:48:41 +00:00
{
2005-05-12 16:27:35 +00:00
fprintf ( g_output , CONST_STR ( NSIS_VERSION ) ) ;
2002-09-13 19:48:41 +00:00
fflush ( g_output ) ;
return 0 ;
}
2004-11-12 13:58:11 +00:00
if ( argc > 1 & & argv [ 1 ] [ 0 ] = = OPT_C & & ( argv [ 1 ] [ 1 ] = = ' v ' | | argv [ 1 ] [ 1 ] = = ' V ' ) )
2002-08-02 10:01:35 +00:00
{
tmpargpos + + ;
if ( argv [ 1 ] [ 2 ] < = ' 2 ' & & argv [ 1 ] [ 2 ] > = ' 0 ' )
{
no_logo = 1 ;
}
}
if ( ! no_logo )
{
2004-11-12 13:58:11 +00:00
if ( argc > tmpargpos & & argv [ tmpargpos ] [ 0 ] = = OPT_C & & ( argv [ tmpargpos ] [ 1 ] = = ' o ' | | argv [ tmpargpos ] [ 1 ] = = ' O ' ) & & argv [ tmpargpos ] [ 2 ] )
2002-08-02 10:01:35 +00:00
{
g_output = fopen ( argv [ tmpargpos ] + 2 , " w " ) ;
if ( ! g_output )
{
printf ( " Error opening output log for writing. Using stdout. \n " ) ;
g_output = stdout ;
}
outputtried = 1 ;
}
2005-07-02 13:15:28 +00:00
print_logo ( ) ;
2002-08-02 10:01:35 +00:00
}
atexit ( myatexit ) ;
signal ( SIGINT , sigint ) ;
if ( ! g_output ) g_output = stdout ;
while ( argpos < argc )
{
2004-11-19 13:45:22 +00:00
# ifndef _WIN32
if ( ! strcmp ( argv [ argpos ] , " -- " ) )
in_files = 1 ;
else if ( argv [ argpos ] [ 0 ] = = OPT_C & & strcmp ( argv [ argpos ] , " - " ) & & ! in_files )
# else
2004-11-12 13:58:11 +00:00
if ( argv [ argpos ] [ 0 ] = = OPT_C & & strcmp ( argv [ argpos ] , " - " ) )
2004-11-19 13:45:22 +00:00
# endif
2002-08-02 10:01:35 +00:00
{
2004-11-12 13:58:11 +00:00
if ( ( argv [ argpos ] [ 1 ] = = ' D ' | | argv [ argpos ] [ 1 ] = = ' d ' ) & & argv [ argpos ] [ 2 ] )
2002-08-02 10:01:35 +00:00
{
2004-11-12 13:58:11 +00:00
char * p = argv [ argpos ] + 2 ;
2002-08-02 10:01:35 +00:00
char * s = strdup ( p ) , * v ;
if ( build . display_script )
{
fprintf ( g_output , " Command line defined: \" %s \" \n " , p ) ;
fflush ( g_output ) ;
}
v = strstr ( s , " = " ) ;
if ( v ) * v + + = 0 ;
build . define ( s , v ? v : " " ) ;
free ( s ) ;
}
2004-11-12 13:58:11 +00:00
else if ( ( argv [ argpos ] [ 1 ] = = ' X ' | | argv [ argpos ] [ 1 ] = = ' x ' ) & & argv [ argpos ] [ 2 ] )
2002-08-02 10:01:35 +00:00
{
2004-11-12 13:58:11 +00:00
if ( build . process_oneline ( argv [ argpos ] + 2 , " command line " , argpos + 1 ) ! = PS_OK )
{
return 1 ;
}
cmds_processed + + ;
2002-08-02 10:01:35 +00:00
}
2004-11-12 13:58:11 +00:00
else if ( ( argv [ argpos ] [ 1 ] = = ' O ' | | argv [ argpos ] [ 1 ] = = ' o ' ) & & argv [ argpos ] [ 2 ] )
2002-08-02 10:01:35 +00:00
{
2004-11-12 13:58:11 +00:00
if ( ! outputtried )
{
g_output = fopen ( argv [ argpos ] + 2 , " w " ) ;
if ( ! g_output )
{
if ( build . display_errors ) printf ( " Error opening output log for writing. Using stdout. \n " ) ;
g_output = stdout ;
}
outputtried = 1 ;
}
2002-08-02 10:01:35 +00:00
}
2004-11-12 13:58:11 +00:00
else if ( ! stricmp ( & argv [ argpos ] [ 1 ] , " NOCD " ) ) do_cd = 0 ;
else if ( ( argv [ argpos ] [ 1 ] = = ' V ' | | argv [ argpos ] [ 1 ] = = ' v ' ) & &
argv [ argpos ] [ 2 ] > = ' 0 ' & & argv [ argpos ] [ 2 ] < = ' 4 ' & & ! argv [ argpos ] [ 3 ] )
2002-08-02 10:01:35 +00:00
{
2004-11-12 13:58:11 +00:00
int v = argv [ argpos ] [ 2 ] - ' 0 ' ;
build . display_script = v > 3 ;
build . display_info = v > 2 ;
build . display_warnings = v > 1 ;
build . display_errors = v > 0 ;
g_display_errors = build . display_errors ;
}
else if ( ! stricmp ( & argv [ argpos ] [ 1 ] , " NOCONFIG " ) ) g_noconfig = 1 ;
else if ( ! stricmp ( & argv [ argpos ] [ 1 ] , " PAUSE " ) ) g_dopause = 1 ;
else if ( ! stricmp ( & argv [ argpos ] [ 1 ] , " LICENSE " ) )
{
if ( build . display_info )
2002-08-02 10:01:35 +00:00
{
2005-07-02 13:15:28 +00:00
print_license ( ) ;
2002-08-02 10:01:35 +00:00
}
2004-11-12 13:58:11 +00:00
nousage + + ;
2002-08-02 10:01:35 +00:00
}
2004-11-12 13:58:11 +00:00
else if ( ! stricmp ( & argv [ argpos ] [ 1 ] , " CMDHELP " ) )
2002-08-02 10:01:35 +00:00
{
2004-11-12 13:58:11 +00:00
if ( argpos < argc - 1 )
build . print_help ( argv [ + + argpos ] ) ;
else
build . print_help ( NULL ) ;
nousage + + ;
2002-08-02 10:01:35 +00:00
}
2004-11-12 13:58:11 +00:00
else if ( ! stricmp ( & argv [ argpos ] [ 1 ] , " NOTIFYHWND " ) )
{
2004-03-29 20:21:00 +00:00
# ifdef _WIN32
2004-11-12 13:58:11 +00:00
build . notify_hwnd = ( HWND ) atol ( argv [ + + argpos ] ) ;
if ( ! IsWindow ( build . notify_hwnd ) )
build . notify_hwnd = 0 ;
2004-03-29 20:21:00 +00:00
# else
2004-11-12 13:58:11 +00:00
argpos + + ;
build . warning ( OPT_STR " NOTIFYHWND is disabled for non Win32 platforms. " ) ;
2004-03-29 20:21:00 +00:00
# endif
2004-11-12 13:58:11 +00:00
}
else if ( ! stricmp ( & argv [ argpos ] [ 1 ] , " HDRINFO " ) )
2002-08-02 10:01:35 +00:00
{
2005-07-02 13:15:28 +00:00
print_stub_info ( build ) ;
2004-11-12 13:58:11 +00:00
nousage + + ;
2002-08-02 10:01:35 +00:00
}
2004-11-12 13:58:11 +00:00
else break ;
2002-08-02 10:01:35 +00:00
}
2004-11-12 13:58:11 +00:00
else
2002-08-02 10:01:35 +00:00
{
files_processed + + ;
2004-11-19 13:45:22 +00:00
# ifndef _WIN32
if ( ! strcmp ( argv [ argpos ] , " - " ) & & ! in_files )
# else
if ( ! strcmp ( argv [ argpos ] , " - " ) )
# endif
g_dopause = 0 ;
2002-08-02 10:01:35 +00:00
if ( ! g_noconfig )
{
g_noconfig = 1 ;
2006-01-21 09:54:23 +00:00
string main_conf ;
char * env_var = getenv ( " NSISCONFDIR " ) ;
if ( env_var = = NULL )
# ifndef NSIS_CONFIG_CONST_DATA_PATH
main_conf = get_executable_dir ( argv [ 0 ] ) ;
# else
main_conf = CONST_STR ( PREFIX_CONF ) ;
# endif
else main_conf = env_var ;
main_conf + = PLATFORM_PATH_SEPARATOR_STR ;
main_conf + = " nsisconf.nsh " ;
2005-07-02 12:53:37 +00:00
if ( process_config ( build , main_conf ) )
return 1 ;
string home_conf = get_home ( ) ;
if ( home_conf ! = " " )
2002-08-02 10:01:35 +00:00
{
2005-07-02 12:53:37 +00:00
home_conf + = PLATFORM_PATH_SEPARATOR_STR ;
# ifdef _WIN32
home_conf + = " nsisconf.nsh " ;
# else
home_conf + = " .nsisconf.nsh " ;
# endif
if ( process_config ( build , home_conf ) )
2002-08-02 10:01:35 +00:00
return 1 ;
}
}
{
char sfile [ 1024 ] ;
2004-11-19 13:45:22 +00:00
# ifndef _WIN32
if ( ! strcmp ( argv [ argpos ] , " - " ) & & ! in_files )
# else
2002-08-02 10:01:35 +00:00
if ( ! strcmp ( argv [ argpos ] , " - " ) )
2004-11-19 13:45:22 +00:00
# endif
2002-08-02 10:01:35 +00:00
{
fp = stdin ;
strcpy ( sfile , " stdin " ) ;
}
else
{
strcpy ( sfile , argv [ argpos ] ) ;
fp = fopen ( sfile , " rt " ) ;
if ( ! fp )
{
sprintf ( sfile , " %s.nsi " , argv [ argpos ] ) ;
fp = fopen ( sfile , " rt " ) ;
if ( ! fp )
{
if ( build . display_errors )
{
2002-09-19 16:42:41 +00:00
sfile [ strlen ( sfile ) - 4 ] = 0 ;
2002-08-02 10:01:35 +00:00
fprintf ( g_output , " Can't open script \" %s \" \n " , sfile ) ;
fflush ( g_output ) ;
}
return 1 ;
}
}
if ( do_cd )
{
2005-07-02 16:49:31 +00:00
string script_file = string ( sfile ) ;
if ( change_to_script_dir ( build , script_file ) )
2005-07-02 13:15:28 +00:00
return 1 ;
2002-08-02 10:01:35 +00:00
}
}
if ( build . display_script )
{
2002-12-24 20:45:37 +00:00
build . notify ( MAKENSIS_NOTIFY_SCRIPT , sfile ) ;
2003-11-30 18:00:39 +00:00
fprintf ( g_output , " Processing script file: \" %s \" \n " , sfile ) ;
2002-08-02 10:01:35 +00:00
fflush ( g_output ) ;
}
2003-06-05 21:53:52 +00:00
int ret = build . process_script ( fp , sfile ) ;
2002-08-02 10:01:35 +00:00
if ( fp ! = stdin ) fclose ( fp ) ;
if ( ret ! = PS_EOF & & ret ! = PS_OK )
{
if ( build . display_errors )
{
2003-06-05 21:53:52 +00:00
fprintf ( g_output , " Error in script \" %s \" on line %d -- aborting creation process \n " , sfile , build . linecnt ) ;
2002-08-02 10:01:35 +00:00
fflush ( g_output ) ;
}
return 1 ;
}
}
}
argpos + + ;
}
if ( argpos < argc | | ( ! files_processed & & ! cmds_processed ) )
{
if ( build . display_errors & & ! nousage )
{
2005-07-02 13:15:28 +00:00
print_usage ( ) ;
2002-08-02 10:01:35 +00:00
}
return 1 ;
}
if ( build . display_info )
{
fprintf ( g_output , " \n Processed " ) ;
if ( files_processed ) fprintf ( g_output , " %d file%s, " , files_processed , files_processed = = 1 ? " " : " s " ) ;
if ( cmds_processed ) fprintf ( g_output , " %d command line command%s, " , cmds_processed , cmds_processed = = 1 ? " " : " s " ) ;
fprintf ( g_output , " writing output: \n " ) ;
fflush ( g_output ) ;
}
if ( build . write_output ( ) )
{
if ( build . display_errors )
{
fprintf ( g_output , " Error - aborting creation process \n " ) ;
fflush ( g_output ) ;
}
return 1 ;
}
return 0 ;
}