MS-DOS 2.0のソースコードが公開された

9月末にMS-DOS 2.0のソースコード（https://github.com/Microsoft/MS-DOS/tree/master/v2.0）が公開された。ここでは、ソースコードを見ながら、Windowsのパス区切り文字が、なぜ「\」（英語表示では逆スラッシュ）になったのかを考えてみる。

ただ、MS-DOSは8086のアセンブラで記述されているため、コードを説明するのではなく、必要な定義部分などを使って解説することにする。

まずは簡単にMS-DOSという名称について説明しておく。IBMがIBM PC用のOSとしてマイクロソフトに開発を依頼したため、IBM PC用のものはPC-DOSという名称であり、MS-DOSはIBM以外のメーカー用に使われた。この時点では、PC-DOSとMS-DOSはほぼ同一のものとしてよい。ここでは、すべてMS-DOSとして表記する。

MS-DOS 2.0でパス区切りに逆スラッシュを採用

マイクロソフトは1983年のMS-DOS 2.0でフォルダー（当時はディレクトリーと呼んだ）を使う階層構造ファイルシステムを搭載した。このとき、ファイルを指定するパスの区切り文字を逆スラッシュとした。

MS-DOS 2.0が階層型ファイルシステムを導入したのは、マイクロソフトが当時マルチユーザー向けにはXenix（1980年にAT&Tからライセンスを受けたUnixをマイクロソフトが移植したもの）、シングルユーザー向けには、MS-DOSという戦略を持っていたからだ。つまり、MS-DOSをUnixに近づけるべく、改良が進められていたのである。MS-DOS 2.0で階層型ファイルシステムを扱うために用意されたAPI（MS-DOSではファンクションコールと呼んでいた）に関連するソースコードを見ると「XENIX CALLS」という表記がある。

しかし、Unix系では、パスの区切り文字にスラッシュを使っている。当然マイクロソフトもパス区切りにスラッシュを用いることを考えただろう。しかし、いくつかの事情から、それは困難だった。

その理由としては、マイクロソフトがオプション文字（オプション区切り文字などともいう）としてすでにスラッシュを使っていたという点だ。MS-DOS 1.xの時点でも、付属アプリのオプション指定にスラッシュを使っている。これは今でも続く慣習である。

一般にコマンドラインには、コマンド名に続き、パラメーターとオプションをスペースで区切って指定する。Unixでは、パラメーターとして指定されることが多いファイルのパスの区切りにスラッシュ、オプションであることを示す「オプション文字」としてハイフンを使う。

これに対してMS-DOS 2.0では、オプション文字としてスラッシュの利用を継続したため、パス区切り文字に逆スラッシュを採用した。逆スラッシュは、MS-DOS 1.25では、ファイル名に利用できない文字ではなかったが、利用頻度が低いとしてこの文字が選ばれたのではないかと想像される。

また、スラッシュとは向きが違うだけなので、見た目が似ているというのも理由だったと思われる。ただ、このときマイクロソフトは意識していなかったが、米国のASCIIコードは、7単位コードの米国向けのものであり、日本のJIS 7単位コードでは、同じ位置に円マークを割り当てて使っていたことを知らなかったのではないか思われる（海外のことなど気にしてないというのは今でも同じだが）。

MS-DOSでオプション文字を変更できなかったのには理由がある。切り替えてしまうと、MS-DOS 1.x向けに作成したバッチファイルが動作できなくなる。そしてサードパーティのアプリケーションにも影響が出てしまう。

MS-DOSでは、オプション文字をファイル名には使えない文字とすることで、コマンドラインの解釈を簡単にできるようにしてあった。たとえば、「DIR/W」のようにコマンド名の直後にスペースを置かずにオプション「/W」を指定することが可能だった。もし、スラッシュをパス区切りとすると、これはDIRフォルダにあるWというファイルとして解釈されてしまう。もしこの省略が不可能だったら「DIR /W」とファイル名に利用できないスペースが入るため、パスと区別が可能だっだ。

当時のPCのメモリやストレージ（フロッピーディスク）の容量キロバイト単位であり、Unixなどのように、コマンドラインを解釈するためのライブラリを提供することが困難だった。このため、アプリケーションは自力でコマンドラインを解釈せねばならなかった。

そのため、もしスラッシュをオプション文字として利用していたら、プログラムの書き換えが必要となり、MS-DOS 1.xと2.0の間で互換性がなくなってしまう。立ち上がり時期のマイクロソフトにとっては、ソフトウェアの互換性は重要な問題だった。

そういうわけで、マイクロソフトは、オプション文字をスラッシュとしたまま、パス区切り文字を変更することを選択した。

と言いながら、ホントはスラッシュにも対応していた！

しかし、MS-DOS 2.0での逆スラッシュによるパス区切りに関しては一応の対策があった。それが「CONFIG.SYS」で指定する「SWITCHAR」コマンドである。CONFIG.SYSとは、起動時にMS-DOSが読み込むファイルで、システムの初期設定パラメーターや読み込むデバイスドライバーなどが記載してある。

このSWITCHARコマンドは、オプション文字を指定するためのもので、このコマンドが指定されると、ファイルのパス区切りは自動的に「/」になる。MS-DOS付属のツールでオプションを指定するものは対応していたのだが、サードパーティのアプリケーションではほとんどサポートされていなかった。

このパス区切り文字を変更する機能に対して、MS-DOSは、CONFIG.SYSで指定された現在のオプション文字がなにか（デフォルト値は当然スラッシュ）を返すファンクションコールを提供していた。マイクロソフトが想定していたのは、アプリケーションはすべてこの機能を使って、パス区切り文字がどうなっているのかを調べ、それに応じて動くようにアプリケーションを作ることだが、サードパーティには、このような面倒な機能には対応しようとしなかった。前述のように当時のPCは、メモリに余裕がなく、最低スペックのIBM PCのメモリは16キロバイトしかなかったのである。

当時のPCは、メモリも数キロバイトと小さく、OSにさまざまな機能を持たせることはできなかった。たとえば、Unixであれば、コマンドラインとして受け取ったパラメーターを解析する機能は、標準的なライブラリとして提供されていた。なので、ほとんどのコマンドの書式が一定のものになっていた。

MS-DOSには仮想記憶機能がなく（そもそも8086にそのための機構がなかった）、当時大きなアプリケーションは、自分でメモリを管理し、フロッピーからプログラムを読み込んで切り替えていく「オーバーレイ」が普通に行なわれていた。IBM PCの最低メモリは16キロバイトであり、必ずしもすべてのユーザーがメモリを最大まで増設しているとは限らなかった。

このため、どんなアプリケーションもできる限りコンパクトにしなければメモリに読み込むことができなかった。MS-DOS自体もできるだけメモリを占有しないように提供する機能も最低限のものだけだった。このため、アプリケーションはコマンドラインに何が指定されたのかを自分で調べる必要があったのだ。ただでさえ少ないメモリである。親切なコマンドラインの書式など作る余裕はない。ましてや、パスの区切り文字が違ってるなんてことに対応したいと考える開発者はほとんどいなかったわけである。一方でMS-DOS 2.0付属のアプリケーションでは、このあたりに正しく対応していたのだが。

ついでにこの機能は隠しコマンドでもなかった

なお、SWITCHARやこれを取得するAPIが「隠しコマンド」「隠しAPI」だったという説もある。しかし、これは単純にドキュメントが貧弱だったせいだ。つまり、まともなドキュメントがなく、公開された資料も不十分のものであったために、隠されていたように見えたのではないかと考えられる。当時、MS-DOSのドキュメントは、実際に添付するPCのメーカーに任されていた。OEM向けに最低限の資料は提供されるが、印刷されたマニュアルを作るのはPCメーカーであり、その内容はPCメーカー次第だったわけだ。

MS-DOSのソースコードに付属するConfig.sysに関するドキュメントには、ちゃんと「SWITCHAR」コマンドが記述されているほか、「typecal configuration」として「SWITCHAR=-」という記述がある。

また、ソースコードには、OEMメーカー向けに作られたMS-DOS APIのドキュメントがあり、その中に外部に公開しないことを警告する記述がある。

この指定があるのは、マイクロソフト純正の「隠し機能」だ。しかし、現在のオプション文字を調べるための「CHAR_OPER」というAPIには、この指定がない。つまりは公開機能だったのである。

このドキュメントはPCメーカーに対して技術情報を提供するためのファイルなのだが、現在のオプション文字を取得する機能には、非公開の指定はなく、隠し機能ではなかったのである。もっとも、当時どれだけの人が、この記述の意味を理解していたかはかなり疑問がある。オプション文字とパス区切り文字の関係は、Config.sysのSWITCHARに記述があるものの、その機能とCHAR_OPERというファンクションコールが関係しているかどうかは深く理解しない限りわからない。しかも、そもそも「オプション文字」とはなんであるか、どのように扱われているのかについては記述がなかった。

マイクロソフトは、Windows NTでファイルやディレクトリの名前にUnicodeを利用できるようにした。このとき、アプリケーションから呼び出されるファイル関連のAPIでは、その内部で、逆スラッシュをスラッシュに変換して利用していた。というのも、Unicode対応の段階で、パス文字列などを含め文字列を扱うAPIすべてがUnicode用になったが、同時に従来の文字コードを受け付けるAPIも用意され、内部では文字コードを変換してUnicode用APIを呼び出していた。

たとえば、日本語版Windowsの場合、アプリケーションやファイルはシフトJISコードで記述されている。日本語版Windows NTには、シフトJISの文字列を受け付けるAPIかあり、それが文字コードを変換してユニコード対応のAPIを呼び出している。このとき、ファイルパスを扱うAPIでは、パス区切りを逆スラッシュ（円マーク）からスラッシュに変換していた。なぜなら、Unicodeでは逆スラッシュと円マークは違うコードを持つ文字であり、何もせずに文字コードだけを変換してしまうと、2種類の区切り文字を扱わねばならなくなるからだ。

現在のWindowsでは、APIに渡す文字列であれば、パス区切りをスラッシュとしても正しく動作する。問題が生じるのは、アプリケーションがスラッシュをオプション文字として解釈していたり、逆スラッシュだけがパス区切りと思って動作している場合だ。

コマンドプロンプトなどでも、アプリケーション側が対応できるなら、パス区切りにスラッシュを利用することができる。たとえば、コマンドプロンプトなら「cd /temp/X」でも「cd \temp\X」と同じように動作する。cdコマンドはオプションがないため、スラッシュを解釈しないからだ。スラッシュをオプション文字として解釈するDIRコマンドではエラーになってしまう。

現在では、UNCによるネットワークファイルなどの指定を除けば、多くの場合、ファイルパスをスラッシュで区切った文字列で扱うことができる。逆スラッシュは、多くの言語システムでエスケープキャラクタとして使われる関係から、逆スラッシュを含む文字列の扱いはめんどうなもので、Unix／Linux系などのオープンソースソフトウェアの移植の妨げになると考えられていた。1993年にWindowsNTが登場し、WindowsXP（2001年）で一般消費者向けのWindowsがNT系カーネルに移行して以来、それは問題ではなかったが、この事実が開発者の間に広く知られるようになったのはここ数年ぐらいのことである。