追記: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(¶ms);こんな感じに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]を見てコマンドの挙動を変えていることは分かりました.
このようなソフトを初めて見たので,うまいやり方をするものだなあとちょっとびっくりです.