bugfix このページをアンテナに追加 RSSフィード

20081111

[][]追記:vimdiff: シンボリックリンクを使ってオプション付きのコマンドを渡す方法

ほんとにありました.

vim-7.2のソースをダウンロードしてみると,

やはりargv[0]を評価しているようです.


まずは,mparam_Tという構造体を定義.

この中にはコマンドライン引数が格納されています.

39-42@main.c

39	typedef struct
40	{
41	    int		argc;
42	    char	**argv;

...

90	} mparm_T;

移植性のためか,mainの関数名あたりがごっちゃりしていたので,

main()の返り値(167より上の行)は転載しません.

これ見ると,関数の引数がK&Rスタイルなのですね.

167-341@main.c

167	main
168	#endif
169	(argc, argv)
170	    int		argc;
171	    char	**argv;
172	{
173	    char_u	**fnmae = NULL;		/* file name from command line */
174	    mparm_T	params;

...

337	/*
338	 * Figure out the way to work from the command name argv[0].
339	 * "vimdiff" starts diff mode, "rvim" sets "restricted", etc.
340	 */
341	parse_command_name(&params);

こんな感じにmparam_T型のparamsをparse_command_name()に渡しています.

つまり,コマンドの名称はこの関数に渡されています.


そして,parse_command_name()の中身.

1407-1488@main.c

1407	/*
1408	 * Check for: [r][e][g][vi|vim|view][diff][ex[im]]
1409	 * If the executable name starts with "r" we disable shell commands.
1410	 * If the next character is "e" we run in Easy mode.
1411	 * If the next character is "g" we run the GUI version.
1412	 * If the next characters are "view" we start in readonly mode.
1413	 * If the next characters are "diff" or "vimdiff" we start in diff mode.
1414	 * If the next characters are "ex" we start in Ex mode.  If it's followed
1415	 * by "im" use improved Ex mode.
1416	 */
1417	    static void
1418	parse_command_name(parmp)
1419	    mparm_T	*parmp;
1420	{
1421	    char_u	*initstr;
1422	
1423	    initstr = gettail((char_u *)parmp->argv[0]);

...

1475	    else if (STRNICMP(initstr, "vim", 3) == 0)
1476		initstr += 3;
1477	
1478	    /* Catch "[r][g]vimdiff" and "[r][g]viewdiff". */
1479	    if (STRICMP(initstr, "diff") == 0)
1480	    {
1481	#ifdef FEAT_DIFF
1482		parmp->diff_mode = TRUE;
1483	#else
1484		mch_errmsg(_("This Vim was not compiled with the diff feature."));
1485		mch_errmsg("\n");
1486		mch_exit(2);
1487	#endif
1488	    }

冒頭のコメント部に丁寧に書いてありますが,

コマンドの名称から順々にプレフィックス,サフィックスのチェックを行っていく関数です.

1423行目で,関数の引数として渡されたparmpに含まれるコマンドの名称からpath部分を取り除きます.

# gettail()はargv[0]からpathを取り除き,コマンド本体の名称のみを取り出す関数のようです.

# argv[0]の先頭文字からスキャンし,基本的には'/'を手立てにpathを取り除きます.

# gettailが多少深いので,これについては載せてません.

こうして取り出したコマンド本体の名称をinitstrは持ちます.


1476行目を見ていただけると分かるように,

それまでスキャン毎に次のステップに行く場合にはinitstrをインクリメントし,

スキャン位置を変えます.

そして,1479行目ではSTRICMP()関数を用いて,

"diff"文字列とマッチ判定をしているようです.


STRICMP()は,vim.hでマクロ定義されているもので,

実体はstrcasecmp()です.

1388@vim.h

1388	# define STRICMP(d, s)	    strcasecmp((char *)(d), (char *)(s))

この先は追ってはいませんが,

とにかくargv[0]を見てコマンドの挙動を変えていることは分かりました.


このようなソフトを初めて見たので,うまいやり方をするものだなあとちょっとびっくりです.

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/pneumaster/20081111/1226351072

この日記のはてなブックマーク数 [about] [archive] [g] [b] [f] [git] [twit]


メモ
□ オブジェクト指向のこころ・練習問題回答
9章   10章

1960 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2015 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2016 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
最近のコメント

AX
Connection: close