hedgewars/ArgParsers.pas
changeset 9280 c3b11f913145
parent 9249 7b8c82785145
child 9302 1cf37fd7bc47
equal deleted inserted replaced
9277:ad1ec7212ac7 9280:c3b11f913145
       
     1 (*
       
     2  * Hedgewars, a free turn based strategy game
       
     3  * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  *)
       
    18  
       
    19 {$INCLUDE "options.inc"}
       
    20 
       
    21 unit ArgParsers;
       
    22 interface
       
    23 
       
    24 procedure GetParams;
       
    25 
       
    26 implementation
       
    27 uses uConsole, uVariables, uTypes, uUtils, uSound, uConsts;
       
    28 var isInternal: Boolean;
       
    29 
       
    30 procedure GciEasterEgg;
       
    31 begin
       
    32     WriteLn(stdout, '                                                                ');
       
    33     WriteLn(stdout, '      /\\\\\\\\\\\\        /\\\\\\\\\  /\\\\\\\\\\\             ');
       
    34     WriteLn(stdout, '     /\\\//////////      /\\\////////  \/////\\\///             ');
       
    35     WriteLn(stdout, '     /\\\               /\\\/               \/\\\               ');
       
    36     WriteLn(stdout, '     \/\\\    /\\\\\\\  /\\\                 \/\\\              ');
       
    37     WriteLn(stdout, '      \/\\\   \/////\\\ \/\\\                 \/\\\             ');
       
    38     WriteLn(stdout, '       \/\\\       \/\\\ \//\\\                \/\\\            ');
       
    39     WriteLn(stdout, '        \/\\\       \/\\\  \///\\\              \/\\\           ');
       
    40     WriteLn(stdout, '         \/\\\\\\\\\\\\\/     \////\\\\\\\\\  /\\\\\\\\\\\      ');
       
    41     WriteLn(stdout, '          \/////////////          \/////////  \///////////      ');
       
    42     WriteLn(stdout, '                                                                ');
       
    43     WriteLn(stdout, ' Command Line Parser Implementation by a Google Code-In Student ');
       
    44     WriteLn(stdout, '             ASCII Art easter egg idea by @sheepluva            ');
       
    45     WriteLn(stdout, '                                                                ');
       
    46 end;
       
    47 
       
    48 procedure DisplayUsage;
       
    49 begin
       
    50     WriteLn(stdout, 'Usage: hwengine <path to replay file> [options]');
       
    51     WriteLn(stdout, '');
       
    52     WriteLn(stdout, 'where [options] can be any of the following:');
       
    53     WriteLn(stdout, ' --prefix [path to folder]');
       
    54     WriteLn(stdout, ' --user-prefix [path to folder]');
       
    55     WriteLn(stdout, ' --locale [name of language file]');
       
    56     WriteLn(stdout, ' --nick [string]');
       
    57     WriteLn(stdout, ' --fullscreen-width [fullscreen width in pixels]');
       
    58     WriteLn(stdout, ' --fullscreen-height [fullscreen height in pixels]');
       
    59     WriteLn(stdout, ' --width [window width in pixels]');
       
    60     WriteLn(stdout, ' --height [window height in pixels]');
       
    61     WriteLn(stdout, ' --volume [sound level]');
       
    62     WriteLn(stdout, ' --frame-interval [milliseconds]');
       
    63     Writeln(stdout, ' --stereo [value]');
       
    64     WriteLn(stdout, ' --raw-quality [flags]');
       
    65     WriteLn(stdout, ' --low-quality');
       
    66     WriteLn(stdout, ' --nomusic');
       
    67     WriteLn(stdout, ' --nosound');
       
    68     WriteLn(stdout, ' --fullscreen');
       
    69     WriteLn(stdout, ' --showfps');
       
    70     WriteLn(stdout, ' --altdmg');
       
    71     WriteLn(stdout, ' --no-teamtag');
       
    72     WriteLn(stdout, ' --no-hogtag');
       
    73     WriteLn(stdout, ' --no-healthtag');
       
    74     WriteLn(stdout, ' --translucent-tags');
       
    75     WriteLn(stdout, ' --stats-only');
       
    76     WriteLn(stdout, ' --help');
       
    77     WriteLn(stdout, '');
       
    78     WriteLn(stdout, 'For more detailed help and examples go to:');
       
    79     WriteLn(stdout, 'http://code.google.com/p/hedgewars/wiki/CommandLineOptions');
       
    80     GameType:= gmtSyntax;
       
    81 end;
       
    82 
       
    83 procedure setDepth(var paramIndex: LongInt);
       
    84 begin
       
    85     WriteLn(stdout, 'WARNING: --depth is a deprecated command, which could be removed in a future version!');
       
    86     WriteLn(stdout, '         This option no longer does anything, please consider removing it');
       
    87     WriteLn(stdout, '');
       
    88    inc(ParamIndex);
       
    89 end;
       
    90 
       
    91 procedure statsOnlyGame;
       
    92 begin
       
    93     cOnlyStats:= true;
       
    94     cReducedQuality:= $FFFFFFFF xor rqLowRes;
       
    95     SetSound(false);
       
    96     SetMusic(false);
       
    97     SetVolume(0);
       
    98 end;
       
    99 
       
   100 procedure setIpcPort(port: LongInt; var wrongParameter:Boolean);
       
   101 begin
       
   102     if isInternal then
       
   103         ipcPort := port
       
   104     else
       
   105         begin
       
   106         WriteLn(stderr, 'ERROR: use of --port is not allowed');
       
   107         wrongParameter := true;
       
   108         end
       
   109 end;
       
   110 
       
   111 function parseNick(nick: String): String;
       
   112 begin
       
   113     if isInternal then
       
   114         parseNick:= DecodeBase64(nick)
       
   115     else
       
   116         parseNick:= nick;
       
   117 end;
       
   118 
       
   119 procedure setStereoMode(tmp: LongInt);
       
   120 begin
       
   121     GrayScale:= false;
       
   122 {$IFDEF USE_S3D_RENDERING}
       
   123     if (tmp > 6) and (tmp < 13) then
       
   124         begin
       
   125         // set the gray anaglyph rendering
       
   126         GrayScale:= true;
       
   127         cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp-6)))
       
   128         end
       
   129     else if tmp <= 6 then
       
   130         // set the fullcolor anaglyph
       
   131         cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp)))
       
   132     else
       
   133         // any other mode
       
   134         cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp-6)));
       
   135 {$ELSE}
       
   136     tmp:= tmp;
       
   137     cStereoMode:= smNone;
       
   138 {$ENDIF}
       
   139 end;
       
   140 
       
   141 procedure startVideoRecording(var paramIndex: LongInt);
       
   142 begin
       
   143     // Silence the hint that appears when USE_VIDEO_RECORDING is not defined
       
   144     paramIndex:= paramIndex;
       
   145 {$IFDEF USE_VIDEO_RECORDING}
       
   146     GameType:= gmtRecord;
       
   147     inc(paramIndex);
       
   148     cVideoFramerateNum:= StrToInt(ParamStr(paramIndex)); inc(paramIndex);
       
   149     cVideoFramerateDen:= StrToInt(ParamStr(paramIndex)); inc(paramIndex);
       
   150     RecPrefix:= ParamStr(paramIndex);                    inc(paramIndex);
       
   151     cAVFormat:= ParamStr(paramIndex);                    inc(paramIndex);
       
   152     cVideoCodec:= ParamStr(paramIndex);                  inc(paramIndex);
       
   153     cVideoQuality:= StrToInt(ParamStr(paramIndex));      inc(paramIndex);
       
   154     cAudioCodec:= ParamStr(paramIndex);                  inc(paramIndex);
       
   155 {$ENDIF}
       
   156 end;
       
   157 
       
   158 function getLongIntParameter(str:String; var paramIndex:LongInt; var wrongParameter:Boolean): LongInt;
       
   159 var tmpInt, c: LongInt;
       
   160 begin
       
   161     inc(paramIndex);
       
   162     val(str, tmpInt, c);
       
   163     wrongParameter:= c <> 0;
       
   164     if wrongParameter then
       
   165         WriteLn(stderr, 'ERROR: '+ParamStr(paramIndex-1)+' expects a number, you passed "'+str+'"');
       
   166     getLongIntParameter:= tmpInt;
       
   167 end;
       
   168 
       
   169 function getStringParameter(str:String; var paramIndex:LongInt; var wrongParameter:Boolean): String;
       
   170 begin
       
   171     inc(paramIndex);
       
   172     wrongParameter:= (str='') or (Copy(str,1,2) = '--');
       
   173     if wrongParameter then
       
   174          WriteLn(stderr, 'ERROR: '+ParamStr(paramIndex-1)+' expects a string, you passed "'+str+'"');
       
   175     getStringParameter:= str;
       
   176 end;
       
   177 
       
   178 
       
   179 procedure parseClassicParameter(cmdArray: Array of String; size:LongInt; var paramIndex:LongInt); Forward;
       
   180 
       
   181 function parseParameter(cmd:String; arg:String; var paramIndex:LongInt): Boolean;
       
   182 const videoArray: Array [1..5] of String = ('--fullscreen-width','--fullscreen-height', '--width', '--height', '--depth');
       
   183       audioArray: Array [1..3] of String = ('--volume','--nomusic','--nosound');
       
   184       otherArray: Array [1..3] of String = ('--locale','--fullscreen','--showfps');
       
   185       mediaArray: Array [1..10] of String = ('--fullscreen-width', '--fullscreen-height', '--width', '--height', '--depth', '--volume','--nomusic','--nosound','--locale','--fullscreen');
       
   186       allArray: Array [1..18] of String = ('--fullscreen-width','--fullscreen-height', '--width', '--height', '--depth','--volume','--nomusic','--nosound','--locale','--fullscreen','--showfps','--altdmg','--frame-interval','--low-quality','--no-teamtag','--no-hogtag','--no-healthtag','--translucent-tags');
       
   187       reallyAll: array[0..34] of shortstring = (
       
   188                 '--prefix', '--user-prefix', '--locale', '--fullscreen-width', '--fullscreen-height', '--width',
       
   189                 '--height', '--frame-interval', '--volume','--nomusic', '--nosound',
       
   190                 '--fullscreen', '--showfps', '--altdmg', '--low-quality', '--raw-quality', '--stereo', '--nick',
       
   191   {deprecated}  '--depth', '--set-video', '--set-audio', '--set-other', '--set-multimedia', '--set-everything',
       
   192   {internal}    '--internal', '--port', '--recorder', '--landpreview',
       
   193   {misc}        '--stats-only', '--gci', '--help','--no-teamtag','--no-hogtag','--no-healthtag','--translucent-tags');
       
   194 var cmdIndex: byte;
       
   195 begin
       
   196     parseParameter:= false;
       
   197     cmdIndex:= 0;
       
   198 
       
   199     //NOTE: Any update to the list of parameters must be reflected in the case statement below, the reallyAll array above,
       
   200     //      the the DisplayUsage() procedure, the HWForm::getDemoArguments() function, and the online wiki
       
   201 
       
   202     while (cmdIndex <= High(reallyAll)) and (cmd <> reallyAll[cmdIndex]) do inc(cmdIndex);
       
   203     case cmdIndex of
       
   204         {--prefix}               0 : PathPrefix        := getStringParameter (arg, paramIndex, parseParameter);
       
   205         {--user-prefix}          1 : UserPathPrefix    := getStringParameter (arg, paramIndex, parseParameter);
       
   206         {--locale}               2 : cLocaleFName      := getStringParameter (arg, paramIndex, parseParameter);
       
   207         {--fullscreen-width}     3 : cFullscreenWidth  := max(getLongIntParameter(arg, paramIndex, parseParameter), cMinScreenWidth);
       
   208         {--fullscreen-height}    4 : cFullscreenHeight := max(getLongIntParameter(arg, paramIndex, parseParameter), cMinScreenHeight);
       
   209         {--width}                5 : cWindowedWidth    := max(2 * (getLongIntParameter(arg, paramIndex, parseParameter) div 2), cMinScreenWidth);
       
   210         {--height}               6 : cWindowedHeight   := max(2 * (getLongIntParameter(arg, paramIndex, parseParameter) div 2), cMinScreenHeight);
       
   211         {--frame-interval}       7 : cTimerInterval    := getLongIntParameter(arg, paramIndex, parseParameter);
       
   212         {--volume}               8 : SetVolume          ( max(getLongIntParameter(arg, paramIndex, parseParameter), 0) );
       
   213         {--nomusic}              9 : SetMusic           ( false );
       
   214         {--nosound}             10 : SetSound           ( false );
       
   215         {--fullscreen}          11 : cFullScreen       := true;
       
   216         {--showfps}             12 : cShowFPS          := true;
       
   217         {--altdmg}              13 : cAltDamage        := true;
       
   218         {--low-quality}         14 : cReducedQuality   := $FFFFFFFF xor rqLowRes;
       
   219         {--raw-quality}         15 : cReducedQuality   := getLongIntParameter(arg, paramIndex, parseParameter);
       
   220         {--stereo}              16 : setStereoMode      ( getLongIntParameter(arg, paramIndex, parseParameter) );
       
   221         {--nick}                17 : UserNick          := parseNick( getStringParameter(arg, paramIndex, parseParameter) );
       
   222         {deprecated options}
       
   223         {--depth}               18 : setDepth(paramIndex);
       
   224         {--set-video}           19 : parseClassicParameter(videoArray,5,paramIndex);
       
   225         {--set-audio}           20 : parseClassicParameter(audioArray,3,paramIndex);
       
   226         {--set-other}           21 : parseClassicParameter(otherArray,3,paramIndex);
       
   227         {--set-multimedia}      22 : parseClassicParameter(mediaArray,10,paramIndex);
       
   228         {--set-everything}      23 : parseClassicParameter(allArray,14,paramIndex);
       
   229         {"internal" options}
       
   230         {--internal}            24 : {$IFDEF HWLIBRARY}isInternal:= true{$ENDIF};
       
   231         {--port}                25 : setIpcPort( getLongIntParameter(arg, paramIndex, parseParameter), parseParameter );
       
   232         {--recorder}            26 : startVideoRecording(paramIndex);
       
   233         {--landpreview}         27 : GameType := gmtLandPreview;
       
   234         {anything else}
       
   235         {--stats-only}          28 : statsOnlyGame();
       
   236         {--gci}                 29 : GciEasterEgg();
       
   237         {--help}                30 : DisplayUsage();
       
   238         {--no-teamtag}          31 : cTagsMask := cTagsMask and not htTeamName;
       
   239         {--no-hogtag}           32 : cTagsMask := cTagsMask and not htName;
       
   240         {--no-healthtag}        33 : cTagsMask := cTagsMask and not htHealth;
       
   241         {--translucent-tags}    34 : cTagsMask := cTagsMask or htTransparent 
       
   242     else
       
   243         begin
       
   244         //Asusme the first "non parameter" is the replay file, anything else is invalid
       
   245         if (recordFileName = '') and (Copy(cmd,1,2) <> '--') then
       
   246             recordFileName := cmd
       
   247         else
       
   248             begin
       
   249             WriteLn(stderr, '"'+cmd+'" is not a valid option');
       
   250             parseParameter:= true;
       
   251             end;
       
   252         end;
       
   253     end;
       
   254 end;
       
   255 
       
   256 procedure parseClassicParameter(cmdArray: Array of String; size:LongInt; var paramIndex:LongInt);
       
   257 var index, tmpInt: LongInt;
       
   258     isBool, isValid: Boolean;
       
   259     cmd, arg, newSyntax: String;
       
   260 begin
       
   261     WriteLn(stdout, 'WARNING: you are using a deprecated command, which could be removed in a future version!');
       
   262     WriteLn(stdout, '         Consider updating to the latest syntax, which is much more flexible!');
       
   263     WriteLn(stdout, '         Run `hwegine --help` to learn it!');
       
   264     WriteLn(stdout, '');
       
   265 
       
   266     index:= 0;
       
   267     tmpInt:= 1;
       
   268     while (index < size) do
       
   269         begin
       
   270         newSyntax:= '';
       
   271         inc(paramIndex);
       
   272         cmd:= cmdArray[index];
       
   273         arg:= ParamStr(paramIndex);
       
   274         isValid:= (cmd<>'--depth');
       
   275 
       
   276         // check if the parameter is a boolean one
       
   277         isBool:= (cmd = '--nomusic') or (cmd = '--nosound') or (cmd = '--fullscreen') or (cmd = '--showfps') or (cmd = '--altdmg') or (cmd = '--no-teamtag') or (cmd = '--no-hogtag') or (cmd = '--no-healthtag') or (cmd = '--translucent-tags');
       
   278         if isBool and (arg='0') then
       
   279             isValid:= false;
       
   280         if (cmd='--nomusic') or (cmd='--nosound') then
       
   281             isValid:= not isValid;
       
   282 
       
   283         if isValid then
       
   284             begin
       
   285             parseParameter(cmd, arg, tmpInt);
       
   286             newSyntax := newSyntax + cmd + ' ';
       
   287             if not isBool then
       
   288                 newSyntax := newSyntax + arg + ' ';
       
   289             end;
       
   290         inc(index);
       
   291         end;
       
   292 
       
   293     WriteLn(stdout, 'Attempted to automatically convert to the new syntax:');
       
   294     WriteLn(stdout, newSyntax);
       
   295     WriteLn(stdout, '');
       
   296 end;
       
   297 
       
   298 procedure parseCommandLine{$IFDEF HWLIBRARY}(argc: LongInt; argv: PPChar){$ENDIF};
       
   299 var paramIndex: LongInt;
       
   300     paramTotal: LongInt;
       
   301     index, nextIndex: LongInt;
       
   302     wrongParameter: boolean;
       
   303 //var tmpInt: LongInt;
       
   304 begin
       
   305     paramIndex:= {$IFDEF HWLIBRARY}0{$ELSE}1{$ENDIF};
       
   306     paramTotal:= {$IFDEF HWLIBRARY}argc-1{$ELSE}ParamCount{$ENDIF}; //-1 because pascal enumeration is inclusive
       
   307     (*
       
   308     WriteLn(stdout, 'total parameters: ' + inttostr(paramTotal));
       
   309     tmpInt:= 0;
       
   310     while (tmpInt <= paramTotal) do
       
   311         begin
       
   312         WriteLn(stdout, inttostr(tmpInt) + ': ' + {$IFDEF HWLIBRARY}argv[tmpInt]{$ELSE}paramCount(tmpInt){$ENDIF});
       
   313         inc(tmpInt);
       
   314         end;
       
   315     *)
       
   316     wrongParameter:= false;
       
   317     while (paramIndex <= paramTotal) do
       
   318         begin
       
   319         // avoid going past the number of paramTotal (esp. w/ library)
       
   320         index:= paramIndex;
       
   321         if index = paramTotal then nextIndex:= index
       
   322         else nextIndex:= index+1;
       
   323         {$IFDEF HWLIBRARY}
       
   324         wrongParameter:= parseParameter( argv[index], argv[nextIndex], paramIndex);
       
   325         {$ELSE}
       
   326         wrongParameter:= parseParameter( ParamStr(index), ParamStr(nextIndex), paramIndex);
       
   327         {$ENDIF}
       
   328         inc(paramIndex);
       
   329         end;
       
   330     if wrongParameter = true then
       
   331         GameType:= gmtSyntax;
       
   332 end;
       
   333 
       
   334 {$IFNDEF HWLIBRARY}
       
   335 procedure GetParams;
       
   336 begin
       
   337     isInternal:= (ParamStr(1) = '--internal');
       
   338 
       
   339     UserPathPrefix := '.';
       
   340     PathPrefix     := cDefaultPathPrefix;
       
   341     recordFileName := '';
       
   342     parseCommandLine();
       
   343 
       
   344     if (isInternal) and (ParamCount<=1) then
       
   345         begin
       
   346         WriteLn(stderr, '--internal should not be manually used');
       
   347         GameType := gmtSyntax;
       
   348         end;
       
   349 
       
   350     if (not isInternal) and (recordFileName = '') then
       
   351         begin
       
   352         WriteLn(stderr, 'You must specify a replay file');
       
   353         GameType := gmtSyntax;
       
   354         end
       
   355     else if (recordFileName <> '') then
       
   356         WriteLn(stdout, 'Attempting to play demo file "' + recordFilename + '"');
       
   357 
       
   358     if (GameType = gmtSyntax) then
       
   359         WriteLn(stderr, 'Please use --help to see possible arguments and their usage');
       
   360 
       
   361     (*
       
   362     WriteLn(stdout,'PathPrefix:     ' + PathPrefix);
       
   363     WriteLn(stdout,'UserPathPrefix: ' + UserPathPrefix);
       
   364     *)
       
   365 end;
       
   366 {$ENDIF}
       
   367 
       
   368 end.
       
   369