challenge コマンドライン引数の取得

以下にけだし同感なので。

inferno :: どう書く?orgは多言語クックブックになれるか > 一般投稿が可になった時に、ちょっと感じてたんですがやっぱり最近ある傾向が顕著で。というのは数学パズル系とか、(数学的な、事務処理などではない)アルゴリズム勝負!なお題ばっかりなんですよね。

というわけで、たまには簡単でその場で答えが出て、なによりある言語使いにとって「外国語」ではこういうんだというのがわかる問題として考えてみました。

% program a b c d

で a, b, c, d を得るにはどうしたらよいかという、それこそネイティブには刺身タンポポより簡単だけど、「外国人」にはとっさに浮かばないという問題です。

Dan the Practical Programmer

Posted feedbacks - Other

既出よりもう少し丁寧なの
1
2
3
foreach my $arg (@ARGV){
    print "$arg\n";
}

Mac OS X (PowerPC 32bit) アセンブリで。Mac OS X (PowerPC) のアセンブリでは、関数の引数はレジスタ r3-r10 に入ります。あとはmain関数の引数を操作するだけです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
        ;; Mac OS X (PowerPC 32bit)
        ;; % as -o cmdline.o cmdline.s && gcc cmdline.o -o cmdline
        .machine ppc
        .globl _main

_main:
        ;; r3 = int argc
        ;; r4 = char *argv[]
        ;; それぞれ r6, r7 にコピーしておく
        mr      r6, r3
        mr      r7, r4

_print_arg:
        ;; まず、文字列の長さをカウントする
        lwz     r4, 0(r7)       ; カウント用文字列
        li      r5, 0           ; 長さの初期化

_count_strlen:
        lbz     r0, 0(r4)       ; 1文字レジスタに移す
        cmpli   cr7, r0, 0
        beq     cr7, _print_arg_write
        addi    r4, r4, 1
        addi    r5, r5, 1
        b       _count_strlen

_print_arg_write:
        ;; 引数文字列の表示

        ;; 引数の残数をスタックに退避
        ;; sys_write() を呼ぶたびに実行
        subi    r1, r1, 4
        stw     r6, 0(r1)

        ;; sys_write()
        ;; r5 は _count_strlen で既に代入済み
        li      r3, 1           ; 標準出力
        lwz     r4, 0(r7)       ; 出力する文字列
        li      r0, 4           ; sys_write
        sc                      ; 呼び出し

        ;; スタックから引数の残数を復帰
        lwz     r6, 0(r1)
        addi    r1, r1, 4

        ;; 引数の残数をスタックに退避
        subi    r1, r1, 4
        stw     r6, 0(r1)

        ;; スペースを出力
        li      r3, 1           ; 標準出力
        li      r4, hi16(space)
        addi    r4, r4, lo16(space)
        li      r5, 1           ; 出力する文字列の長さ
        li      r0, 4           ; sys_write
        sc                      ; 呼び出し

        ;; スタックから引数の残数を復帰
        lwz     r6, 0(r1)
        addi    r1, r1, 4

        ;; 繰り返しの終了条件判断
        subi    r6, r6, 1       ; カウント減
        cmpi    cr7, r6, 0
        beq     cr7, _end
        addi    r7, r7, 4       ; 引数文字列のポインタを一つ進める
        b       _print_arg      ; 次の引数へ

_end:
        ;; 改行を出力
        li      r3, 1           ; 標準出力
        li      r4, hi16(lf)
        addi    r4, r4, lo16(lf)
        li      r5, 1
        li      r0, 4           ; sys_write
        sc                      ; 呼び出し

        ;; sys_exit()                                                             
        li      r3, 0
        li      r0, 1
        sc

        .data
        .align  2

space:
        .asciz  " "

lf:
        .asciz  "\n"

argc - コマンドラインパラメータ数を返す関数
argv - コマンドラインパラメータを返す関数
 ※argv(str, 0) => (空っぽ)

C:/>ge2exe para.g
C:/>para.exe a b c d
1 = a
2 = b
3 = c
4 = d
C:/>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
func main<main>
{
    uint i
    str stemp

    fornum i = 1, argc() + 1 
    { 
        print( "\(i) = \(argv( stemp, i ))\n") 
    } 
}

Factor では "-" 以外で始まる引数はファイル名とみなされてしまいます。"-引数名=値" という形式で渡す必要があります。引数名がそのままグローバル変数名になるので get で取得します。

factor-nt.exe -script arg.factor -arg1=a -arg2=b -arg3=c -arg4=d

1
2
3
4
5
USING: command-line prettyprint namespaces ;
"arg1" get .
"arg2" get .
"arg3" get .
"arg4" get .

Limboでは、initの引数として文字列リストを得ます。
習慣的に、名前はargvまたはargs。

先頭がコマンド名、続いてa, b, c, d...

リストは、hd(先頭の値を取得)、tl(先頭を除いたリストを取得)を使って操作します。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
implement Argv;

include "sys.m";
    sys: Sys;
include "draw.m";

Argv: module
{
    init: fn(nil: ref Draw->Context, argv: list of string);
};

init(nil: ref Draw->Context, argv: list of string)
{
    sys = load Sys Sys->PATH;
    for(p := tl argv; p != nil; p = tl p)
        sys->print("%s\n", hd p);
}

LLVMアセンブリでは、main関数のパラメータでコマンドライン引数を受け取れます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
declare i32 @puts(i8 *)

; コマンド名を除き、すべての引数を表示する
define i32 @main(i32 %argc, i8** %argv) {
    %i = alloca i32
    store i32 1, i32* %i 
    br label %loop

loop:
    %i_val = load i32* %i
    %cont = icmp slt i32 %i_val, %argc
    br i1 %cont, label %body, label %return

body:
    %argv_addr = ptrtoint i8** %argv to i32
    %count = mul i32 4, %i_val
    %arg_addr = add i32 %argv_addr, %count
    %args = inttoptr i32 %arg_addr to i8**
    %arg = load i8** %args
    call i32 @puts(i8* %arg)

    %next_i = add i32 %i_val, 1
    store i32 %next_i, i32* %i
    br label %loop

return:
    ret i32 0
}

Index

Feed

Other

Link

Pathtraq

loading...