diff options
Diffstat (limited to 'nim/parseopt.pas')
-rw-r--r-- | nim/parseopt.pas | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/nim/parseopt.pas b/nim/parseopt.pas new file mode 100644 index 000000000..d543b998e --- /dev/null +++ b/nim/parseopt.pas @@ -0,0 +1,153 @@ +// +// +// 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 +{&} quoteIfSpaceExists(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. |