mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 09:24:36 +00:00
154 lines
3.4 KiB
ObjectPascal
Executable File
154 lines
3.4 KiB
ObjectPascal
Executable File
//
|
|
//
|
|
// Nimrod's Runtime Library
|
|
// (c) Copyright 2008 Andreas Rumpf
|
|
//
|
|
// See the file "copying.txt", included in this
|
|
// distribution, for details about the copyright.
|
|
//
|
|
unit parseopt;
|
|
|
|
// A command line parser; the Nimrod version of this file
|
|
// will become part of the standard library.
|
|
|
|
interface
|
|
|
|
{$include 'config.inc'}
|
|
|
|
uses
|
|
nsystem, charsets, nos, strutils;
|
|
|
|
type
|
|
TCmdLineKind = (
|
|
cmdEnd, // end of command line reached
|
|
cmdArgument, // argument detected
|
|
cmdLongoption, // a long option ``--option`` detected
|
|
cmdShortOption // a short option ``-c`` detected
|
|
);
|
|
TOptParser = object(NObject)
|
|
cmd: string;
|
|
pos: int;
|
|
inShortState: bool;
|
|
kind: TCmdLineKind;
|
|
key, val: string;
|
|
end;
|
|
|
|
function init(const cmdline: string = ''): TOptParser;
|
|
procedure next(var p: TOptParser);
|
|
|
|
function getRestOfCommandLine(const p: TOptParser): string;
|
|
|
|
implementation
|
|
|
|
function init(const cmdline: string = ''): TOptParser;
|
|
var
|
|
i: int;
|
|
begin
|
|
result.pos := strStart;
|
|
result.inShortState := false;
|
|
if cmdline <> '' then
|
|
result.cmd := cmdline
|
|
else begin
|
|
result.cmd := '';
|
|
for i := 1 to ParamCount() do
|
|
result.cmd := result.cmd +{&} quoteIfContainsWhite(paramStr(i)) +{&} ' ';
|
|
{@ignore}
|
|
result.cmd := result.cmd + #0;
|
|
{@emit}
|
|
end;
|
|
result.kind := cmdEnd;
|
|
result.key := '';
|
|
result.val := '';
|
|
end;
|
|
|
|
function parseWord(const s: string; const i: int; var w: string;
|
|
const delim: TCharSet = {@set}[#9, ' ', #0]): int;
|
|
begin
|
|
result := i;
|
|
if s[result] = '"' then begin
|
|
inc(result);
|
|
while not (s[result] in [#0, '"']) do begin
|
|
addChar(w, s[result]);
|
|
inc(result);
|
|
end;
|
|
if s[result] = '"' then inc(result)
|
|
end
|
|
else begin
|
|
while not (s[result] in delim) do begin
|
|
addChar(w, s[result]);
|
|
inc(result);
|
|
end
|
|
end
|
|
end;
|
|
|
|
procedure handleShortOption(var p: TOptParser);
|
|
var
|
|
i: int;
|
|
begin
|
|
i := p.pos;
|
|
p.kind := cmdShortOption;
|
|
addChar(p.key, p.cmd[i]);
|
|
inc(i);
|
|
p.inShortState := true;
|
|
while p.cmd[i] in [#9, ' '] do begin
|
|
inc(i);
|
|
p.inShortState := false;
|
|
end;
|
|
if p.cmd[i] in [':', '='] then begin
|
|
inc(i); p.inShortState := false;
|
|
while p.cmd[i] in [#9, ' '] do inc(i);
|
|
i := parseWord(p.cmd, i, p.val);
|
|
end;
|
|
if p.cmd[i] = #0 then p.inShortState := false;
|
|
p.pos := i;
|
|
end;
|
|
|
|
procedure next(var p: TOptParser);
|
|
var
|
|
i: int;
|
|
begin
|
|
i := p.pos;
|
|
while p.cmd[i] in [#9, ' '] do inc(i);
|
|
p.pos := i;
|
|
setLength(p.key, 0);
|
|
setLength(p.val, 0);
|
|
if p.inShortState then begin
|
|
handleShortOption(p); exit
|
|
end;
|
|
case p.cmd[i] of
|
|
#0: p.kind := cmdEnd;
|
|
'-': begin
|
|
inc(i);
|
|
if p.cmd[i] = '-' then begin
|
|
p.kind := cmdLongOption;
|
|
inc(i);
|
|
i := parseWord(p.cmd, i, p.key, {@set}[#0, ' ', #9, ':', '=']);
|
|
while p.cmd[i] in [#9, ' '] do inc(i);
|
|
if p.cmd[i] in [':', '='] then begin
|
|
inc(i);
|
|
while p.cmd[i] in [#9, ' '] do inc(i);
|
|
p.pos := parseWord(p.cmd, i, p.val);
|
|
end
|
|
else
|
|
p.pos := i;
|
|
end
|
|
else begin
|
|
p.pos := i;
|
|
handleShortOption(p)
|
|
end
|
|
end;
|
|
else begin
|
|
p.kind := cmdArgument;
|
|
p.pos := parseWord(p.cmd, i, p.key);
|
|
end
|
|
end
|
|
end;
|
|
|
|
function getRestOfCommandLine(const p: TOptParser): string;
|
|
begin
|
|
result := strip(ncopy(p.cmd, p.pos+strStart, length(p.cmd)-1))
|
|
// always -1, because Pascal version uses a trailing zero here
|
|
end;
|
|
|
|
end.
|