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