Table 2 時刻の取得 なります (List 2 , touch2. c)o / 逆 TOUCH コマンドの DOS ファンクション 2Ch 時刻の取得 作成 引数 AH = 2Ch 筆者は少々ひねくれてるのて , TOUCH コ INT 21h マンドの逆のコマンドを作成してみます ( List 戻り値 CH = 時 ( 0 ~ 23 ) 3 , objtouch. c)o TOUCH コマンドはソース ( 0 ~ 59 ) CL = 分 ファイルを最新の日付に設定することて DH = 秒 ( 0 ~ 59 ) MAKE を実行しますが , このプログラムて 1 / 100 秒 ( 0 ~ 99 ) DL はオプジェクトファイルを最古の日付に設 機能 DOS が管理する時刻を取得する。旧 M ー PC 互換機ては 1 / 100 秒まで取得 定し , MAKE を実行します。それにオプジ できるが , PC ー 9801 シリーズでは DL レジスタは必ず 00h を設定する ェクトファイルはコンノヾイルやアセンプル の結果て更新されますから日付を変えても まったく問題ありませんが , ソースファイ て、 , 拡張子を省略した場合は . OBJ としま OBJTOUCH くファイル 1 > ルの日付を変えたくない場合があるかもし す。また , 環境変数 OBJTOUCH にオプジェ [ ・・・くファイル n > ] れません。 OBJTOUCH コマンドの使用法は となります。くファイル名 > は複数指定可能 クトを格納しているディレクトリをセット TabIe 3 現在の日付の取得 —dos—getdate 関数 (MS-C 5.1 ) # include<dos. h> 医 getdate 関数 (TurbO C 2.0 ) #include く dos. h 〉 void—dos—getdate(date) ; struct dosdate—t * date ; void getdate (pdate) ; 現在の日付 現在の日付 struct date * pdate ; struct dosdate—t { unsigned char day, unsigned char month; unsigned int year; unsigned char dayofweek; struct date int Char Char 日 1 ~ 31 月 1 ~ 12 / * 年 1980 ~ 2099 / * 曜日 0 ~ 6 , 0 = 日曜 * / / * 年 日 / * 月 da—year; da—day; da—mon; TabIe 4 現在の時刻の取得 —dos—gettime 関数 (MS-C 5.1 ) # include く dos. h> void—dos—gettime(time) ; struct dostime—t *time, gettime 関数 ()u 「 b0 C 2.0 ) # include く dos. h> VOid gettime(ptime) ; struct time *ptime; 現在の時刻 現在の時刻 struct dostime—t { unsigned Char hour; unsigned Char minute, unsigned Char second; unsigned char hsecond; struct time unsigned char unsigned Char unsigned Char unsigned Char / * 分 / * 時 1 / 100 秒 / * 秒 3 9 9 9 っ 4 5 5 9 / * 時 / * 分 / * 秒 / * 1 / 100 秒 ti—hour; ti—hund, ti—sec ; 86 CMAGAZINE 1991 2
List 1 8 God Hand さんの解答 (gh—tail. c) 11 : * / 22 : { 53 : } 128 インクルードしています。ほカ ~ 系の 方はこ分を肖畭してください標準 しカっていなしで , 情なく すると思います ( MS - C でも memo 「 y. h と m 訓 oc. h をインク丿ドする必要はありま せんね ) 。 このプログラムになるのは駄 10 行しカま示できないということです。少し 手直しす何行でも ( もちろんメモリの 内で ) 表示することカ河能なので , やっ てみましよう。まず , 2 斫ラ目の *tbl [MAX], buf [READBF] : という部分を * *tbl, buf [READBF] ; のように , tb をポインタのポインタに して宣言します。そして 2 ラ目の関数 memset を餘します。それから , 31 ~ 36 行目を List 19 のように修正します。そし て main 力鮗了する直前立置 ( 5 哘 目 ) に free( tb り ; と挿入すれば何行でも表示することカ河 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 : 12 : 20 : 21 : 23 : 24 : 26 : 28 : 29 : 30 : 32 : 33 : 34 : 35 : 36 : 38 : 39 : 40 : 42 : 43 : 44 : 45 : 46 : 49 : 50 : 52 : System i I e name Author Date Description 参考文献 Compiler OS : C 言語入門講座 9 0 年 1 1 月号クイズ : GH_TAIL. C : God Hand ( 匿名希望 ) : 90 / 10 / 23 簡易版 T A I L コマンド : MS-DOS Ver. 3. 10 ( Toshiba J ー 3300 日本語 ) . MS-C Ver. 5. 10 : MSC V5. 1 開発ハント・フ・ツク技術開発室編秀和システム #include 13 : #include 14 : #include 15 : # i nc 1 ude 16 : #include 18 : #define MAX く stdio. h> く std 1 i b. h> く string. h> く memory. h> く malloc. h> 19 : #define READBP 512 / * 表示行数最大値 * / / * 読み込み用ハ・ツファーサイス・ * / void main(unsigned int argc, unsigned char **argv) 日し E *fp; unsigned char *tbl buf[READBF] : unsigned int cnt=MAX; memset(tbl, 0 , sizeof(tbl)) : fp=(FILE * ) 0 : while( * 十十 argv ) { if( **argv= / * オフ・ション取得 * / / * テ・フォルトの表示行数をセット * / / * ホ・インターテーフ・ルを強引にクリアー * / / * ファイルホ・インターを Nu Ⅱクリアー * / cnt=( (cnt=(unsigned int)atoi ( + 十 *argv) ) く =MAX & & cnt>=l ) ?cnt:MAX; whi le( fgets(buf, READBF, (p) !=NU し L ) { / * 一行読む * / fp=( fp==(FILE * ) 0 )?stdin:fp; else fp=fopen( *argv, "rt" ) : / * ファイルオーフ・ンエラーも標準入力にする * / 能です。 CMAGAZINE 1991 2 造を表示行分だけ出力させています。 ていくのです。そして , 最後に , リスト構 にそを寺しながらリスト構造を作っ アからなります。そして , 1 彳豫み込むたび リスト構造を構築する ) と , 1 行分のバッフ 構はそ型のポインタ型 ( 線形 体をリストにしています。読み用 この wæ(List 20 ) は読み用造 藤澤昌聡さんの解答 るでしよう。 どを用いさらによいプログラムにな せんれ前介したマクロ mem alloc な きなかったときのエラーを行っていま 正 m 訓 oc 賦カで てにすればよいのです。ただ , するため己列を ma Ⅱ oc を用い このようにバッフアの知頁ポインタを if( tbI[0] ) free( tbl[0] ) : for( i=0;i く cnt-lä + + ) tblCi]=tbl[i + 1]: tbl[cnt-l]=malloc( strlen(buf) + 1 ) ; / * 古いハ・ツファーを捨てる * / / * ハ・ツファーのホ・インターを地道に前へずらす * / / * 新しいハ・ツファーを盗み取る * / / * ハ・ツファーへコヒ・ strcpy( tbl [cnt-l], buf ) : fclose( fp ) : for( i=o;i く cnt;i + + ) { if( tbl[i] ) fputs( tbl[i],stdout ) : / * 標準入力であろうとクロース・してしまえ * / / * Nu Ⅱでなければ表示 * / List 18 の 31 ~ 36 行目の修正 List 1 9 Ⅱ **argv if( **argv= 1 : while( * + + argv ) { 5 : 4 : 3 : 2 : ー ( ( cnt = (unsigned int)atoi ( + + *argv ) ) 〉 = 1 ) ? cnt : MAX; 8 : memset( tbl, 0 , sizeof( unsigned char * ) * cnt ) : 7 : tbl = (unsigned char **)malloc( sizeof( unsigned char * ) * cnt ) : fopen ( *argv, else cnt ー
Fig. 2 0 : 00 12 : 53 12 : 55 12 : 55 12 : 55 12 : 59 13 : 圓 13 : 00 13 : 00 12 : 54 12 : 55 12 : 55 12 : 55 12 : 53 wh--d- 隠しティレクトリの効果 DNTEST>dir \ ドライプ D: のディスクのポリュームラベルは M B し -DISK ディレクトリは D:y COMMAND COM 24931 89 ー 1 1 ー 27 LSIC86 CFG 111 90 ー 07 ー 15 TEST 90 ー 07 ー 15 く田 R > 3 個のファイルがあります . 6113280 バイトが使用可能です . DNTEST>chgatr -h + Ytest D:YTEST>dspatr Ytest Ytest D: YTEST>cd Y D:Y>dir \ ドライプ D: のディスクのポリュームラベルは M E L -DISK ドライプ D: のディスクのポリュームラベルは M E し -DISK D:y 〉 dir test 6113280 バイトが使用可能です . 2 個のファイルがあります . 111 90 ー 07 ー 15 LS I C86 C FG COMMAND COM 24931 89 ー 11 ー 27 ディレクトリは D:Y 0 : 00 12 : 53 ←テ・イレクトリ TEST は見えない ←隠しテ・イレクトリでも中身は見える ←通常の属性 ←隠し属性を設定 ←隠し属性が設定されている ディレクトリは DNTEST CHGATR CHGATR CHGATR CHGATR DSPATR DSPATR DSPATR DSPATR C EXE MAP OBJ C EXE MAP OBJ く田 R 〉 く田 R > 653 1946 9025 1815 1365 2606 9653 4480 。 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 10 個のファイルがあります . 6113280 バイトが使用可能です . DN>cd test D: YTEST>dir \ ←隠しテ・イレクトリでも移れる ドライプ D: のディスクのポリュームラベルは M E L -DISK ディレクトリは D:y COMMAND COM 24931 89 ー 1 1 ー 27 し SIC86 CFG 111 90 ー 07 ー 15 2 個のファイルがあります . 6113280 バイトが使用可能です . ファイル属性の取得 ( ge 廿ⅱ ea. c ) D:YTEST 〉 0 : 00 LiSt List ファイル属性の設定 ( setf ⅱ ea. c ) #include く dos. h> int getfileattr(char * int getfileattr( path, 6 : char path[]; uns igned *attr; union REGS iregs: 9 : 7 : 5 : 4 : 3 : 2 : 1 : , unsigned attr ) ファイル名 * / 2 : 3 : 4 : 5 : 7 : 9 : 1 : #include く dos. h> int setfileattr(char * , unsigned) : int setfileattr( path, 6 : char path[]; unsigned attr; union REGS 'iregs; attr ) / * 属性を取得する / * 属性へのホ・インタ ( unsigned )path; iregs. X. dX iregs. x. ax = 0X4300 : intdos( &iregs. &iregs ) : if ( iregs. x. cflag ) return ( iregs. X. cx; *attr return( 0 ) : / 事 ds:dx ハ・ス名の位置 / * ファイル属性の取得 / * ファイル属性 ( unsigned )path; dx = 0X4301 : cx ニ attr; intdos( &iregs. &iregs ) : iregs. x. cflag ? ー 1 return ( lregs. X. lregs. X. ax lregs. X. / * 属性を設定するファイル名 * / / * 設定する属性 / * ファイル属性 / * ファイル属性の設定 ハ・ス名の位置 / * ds:dx 92 CMAGAZINE 1991 2
プログラマのための ~ 新 MS ー DOS プロクラミンク入門 TabIe 7 #define _A_VO い D #define _A_SUBDI R attr & _A_ARCH 1 : h . 26 : * / —dos—setfileattr 関数 (MS-C 5.1 ) ファイル属性の設定 unsigned—dos—setfileattr(path, attr) ; # include <dos. h> Table 8 getfileattr 関数 char *path; unsigned *attr; 属性を取得するファイル名 設定する属性 ファイル属性の取得 属性定数 MS-C 5.1 unsigned *attr; char *path; int getfileattr(path, attr) ; #include<dos. h> 属性定数 Turbo C 2.0 戻り値 TabIe 9 = 0 : 正常終了 = 0 : 工ラー ( MS ー DOS のエラーコード ) ファイル属性の設定 setfileattr 関数 # include <dos. h> int setfileattr (path, unsigned attr, char *path; attr) ; 属性を取得するファイル名 属性へのポインタ 通常のファイル 意味 アーカイプ属性 サプティレクトリ ボリューム旧 システム属性 隠し属性 書き込み不可属性 戻り値 —A—NORMAL —A—RDONLY —A—HIIDDEN —A—SYSTEM —A—VOLI D —A—SUBD 旧 —A—ARCH List 6 FA—RDONLY FA—HIDDEN FA—SYSTEM FA—LABEL FA—D 旧 EC FA—ARCH 属性を設定するファイル名 設定する属性 戻り値 List 0 : 正常終了 ー 1 : 工ラー 属性表示 (dspatr. c) ファイル名 : dspatr. c 属性表示サンフ・ル・フ・ロク・ラム 0 : 正常終了 ー 1 : 工ラー #define _A_ARCH 36 : 37 : 38 : 39 : 40 : 42 : 43 : 44 : 45 : 46 : 47 : 49 : 50 : 52 : 53 : 54 : 55 : 56 : 58 : 59 : 60 : 62 : 63 : 64 : 65 : 66 : 68 : 69 : 70 : FA_ し ABE し FA_DIREC PA_ARCH 3 : 5 : 6 : 8 : 16 : 22 : 23 : 24 : 25 : 30 : 35 : int getfi leattr(char *,unsigned * ) : 7 : 使用法 : dspatr くファイル 1 〉 [.. 9 : [ 表示属性 ] 13 : コンハ・イル・スイッチ 1 5 : MS-C 5. 1 20 : Turbo C 2. 0 くファイル n > ] . テ・イレクトリ属性 隠し属性 書込不可属性 ホ・リューム・ラへ・ル Sma Ⅱ Model S a . システム属性 . 保存属性 41 : #endif int main(int,char * * ) : int main( argc,veargv ) int argc; char *argv ロ : uns igned attr; if ( argc く = fprintf ( stderr, return( 1 ) : while ( * + 十 argv ) { usage ・ dspatr くファイル 1 > [. くファイル n > ] \ n " ) : 17 : 引 /J /W3 /ZdI dspatr. c XMSCXYI ibYsetargv. 0bj / link s libcr + libh/st : 0X2800 / cp : 0X1000 / noe Sma Ⅱ Model getfi leattr が必要 tcc -w dspatr. c XTC%YlibYwildargs. obJ / * ファイル属性の取得 * / if ( _dos_getfi leattr( *argv, return( 1 ) : &attr ) ) { fprintf( stderr, " ファイル Xs の属性が取得できません。 yn", 28 : #include く stdio. h 〉 29 : #include く dos. h> 31 : #ifdef 32 : #define 33 : #define _A_RDON し Y 34 : #define _A_HIDDEN #define 0 printf ( " % ー 20S XcXcXcXcXcXcYn" attr & _A_SUBDIR ? attr & _A_VO い D attr & _A_SYSTEM attr & _A_RDON し Y attr & A_HIDDEN ? _TURBOC_ dos-getfil eattr A_SYSTEM getfileattr FA_RDON し Y FA_HIDDEN FA_SYSTEM return ( *argv ) : 新 MS—DOS プログラミング入門 *argv, 93
プログラマのための List 7 属性変更 (chgatr. c) List attr & ー ( -A-VO い D ー -A-SUBDIR ) ) ) { / * ファイル属性の設定 * / fprintf ( stderr, ”ファイル Xs の属性が変更できません。 Yn ” , *argv ) : return( 1 ) : 79 : 82 : 85 : 86 : 88 : 89 : VOid getargs ( argc, argv ) 90 : int argc; 91 : char *argv[]; while ( --argc ) { 93 : 94 : register char *p; 95 : if ( ( p = * + + argv ) [ 0 ] 96 : while ( * + + p ! = swi tch( tolower ( *p ) 98 : 99 : if ( p[l] = 100 : 101 : _A_ARCH,• set_atr 102 : p 十十 : } else if ( p[l] = 103 : 104 : res_atr 105 : p 十十 : 106 : 107 : break : 108 : if ( 矼 1 ] ー 109 : 1 10 : set_atr p 十十 : } else if ( p[l] = 1 12 : 113 : res_atr 114 : p 十十 : 115 : 116 : break : 117 : 118 : if ( p[l] ー 119 : set_atr 120 : p 十十 : } 引 se i f ( 121 : 122 : res_atr 123 : p 十十 : 124 : break : 125 : case 'r' 126 : if ( p[l] = 127 : 128 : set_atr 129 : p 十十 : } else if ( p[l] = 130 : 131 : res_atr 132 : p 十十 : 133 : 134 : break : 135 : default ・ usage ( ) : 136 : 137 : 138 : 139 : 140 : 141 : } 142 : 143 : void usage() 144. 145 : static char *msg[] " 使用法 : chgatr トく属性士 > ] くファイル 1 〉 [.. 146 : 書込不可属性 h ... 隠し属性 147 : S r " a ... 保存属性 + ... 属性ヒ・ツト 0N 148 : 149 : 150 : 151 : reg ister char **pmsg 152 : while ( **pmsg ) 153 : printf( *pmsg + 十 ) : 154 : exit( 1 ) : 155 : 156 : } 1 : 属性変更サンフ・ル・フ・ロク・ラム 3 : ファイル名 : chgatr. c 5 : 6 : 7 : 使用法 : chgatr トく属性土〉 ] くファイル 1 > [.. くファイル n > ] 8 : ( d, v は無効 ) 9 : [ 属性指定子の詳細 ] 10 : . システム属性 h . . 隠し属性 r . 書込不可属性 S . テ・イレクトリ属性 a . 保存属性 ホ・リューム・ラへ・ル 12 : V 属性ヒ・ツト OFP 属性ヒ・ツト 0N 14 : 15 : 使用例 : chgatr -s 十 h 十 r 十 a- file. ext システム属性 . 隠し属性 , 書込不可属性をセットし、 保存属性をリセットします。 19 : コンハ・イル・スイッチ 20 : Sma Ⅱ Model 21 : MS-C 5. 1 22 : 23 : /J /W3 /Zdl chgatr. c XMSCXYIibYsetargv. 0bj /link slibcr + ⅱbh/St:0X2800/CP:0X1000/n0e 24 : 25 : 26 : Turbo C 2.0 Sma Ⅱ Model 27 : が必要 * * * * * setfileattr 28 : * * * * * getfil eattr 29 : 30 : tcc -w chgatr. c XTCXYlibYwildargs. Obj 32 : * / 33 : 34 : #include く stdio. h> 35 : #include く ctype. h> 36 : #include く process. h> 37 : #include く dos. h> 38 : 39 : # ifdef _TURBOC_ 40 : #define getfileattr dos-getfil eattr 41 : #define setfileattr dos_setfileattr 42 : #define _A_RDON し Y FA_RDON し Y 43 : #define _A_HIDDEN FA_HI DDEN 44 : #define _A_SYSTEM FA_SYSTEM 45 : #define _A_VO い D FA_ し ABEL 46 : #define A_SUBDIR FA_DIREC 47 : #define A_ARCH FA_ARCH 49 : int getfileattr(char *,unsigned * ) , setfi leattr(char *,unsigned) : 50 : #endif 52 : int main(int,char * * ) : VOid getargs(int,char * * ) , usage(void) : 53 : 54 : 55 : unsigned set-atr = 0 , 56 : res_atr = 0 : 58 : int main( argc, argv 59 : int argc; 60 : char *argv[] : 62 : uns igned attr: if ( argc く = 1 ) usage() : 65 : getargs( argc, argv ) : 66 : while ( * + + argv ) { 67 : if ( **argv 68 : / * オフ・ション・スイッチ continue; / * ファイル属性の取得 * / if ( -dos_getfileattr( *argv, &attr ) ) { fprintf ( stderr, Xs の属性が取得できません。 Yn ” ”ファイル *argv return( 1 ) : 75 : attr ト set_atr; 76 : attr & : res atr; if ( _dos_setfileattr( *argv, return( 0 ) : / * 引数の取得 カ′ル′ 了 定定ッ 指指チ 性存 属保 / * システム・ファイル A SYSTEM : A_SYSTEM : / * 隠しファイル _A_HIDDEN : A_HIDDEN; / * 読出専用ファイル A_RDONLY : A_RDONLY : / * セット属性 / * リセット属性 / * 引数の取得 くファイル n 〉 ] \ n \ n ” . システム属性 \ n ” 属性ヒ・ツト 0FFYn", msg: / * セット属性 / * リセット属性 1991 2 94 CMAGAZINE
おわりに C 言語のライプラリてサポートしている DOS ファンクションを呼び出す関数に互換性が ないため掲載したリストが多少見にくくな ってしまいました 0MS-C が Ver. 3 からサポ ートしていれば TurboC もあわせたのてし ようが , Ver. 5 からのサポートて、すから互 換性のないのも仕方がないのて、しよう。 DOS ファンクションを呼び出す関数に互 換性がないことを考慮すれば新たに作成し たほうがよかったかもしれませんが , 今回 は条件コンパイルにより複数のコンパイラ に対応する方法をとりました。これらの関 数をサポートしていないコンパイラて、も intdos 関数に相当する関数はサポートしているは ずてすから , その関数を用いれば DOS ファ ンクションを直接呼び出すことがて、きます。 本文てもいくつか示している例を参考にし て作成してください。これらの例は MASM て、記述することもてきますが ,MASM< 記 述する例は別の機会に紹介します。 今回はふたつの項目について考察しまし た。いずれも MS ー DOS の機能を利用した簡 単なプログラミングをその機能の裏側をの ぞきながら ( 筆者の推測も入っていますから まちがっているかもしれませんが ) 説明しま した。どのような印象をもたれたて、しよう か ? 少々しつこい印象をもたれたかもし れません。しかし , MS ー DOS に限らず何事 も一度は , とことん追及する姿勢はたいせ ってす。別の分野て、も応用力となって現れ てくるはずてす。といっても MS-DOS を追 及しても仕方がないてすから , 仕事の背景 を考えながら仕事をすると上達が速くなる かもしれませんよ。 ( 参考文献 ) 1. 中島信行 , 「 MS-DOS のディスク管理とフ ァイル復活ユーティリティ」 , 『インタフェ イス』 1990 年 5 月号 90 CMAGAZINE 1991 2 76 : 82 : 84 : 85 : 86 : 87 : TabIe 5 引数 戻り値 機能 List 3 81 : #endif 77 : #else 73 : #ifdef name ) : fprintf ( stderr, " ファイル %s の日付変更に失敗しました。 \ 心 , / * ファイルの日付を 1980. 1. 1 にセット * / setfiletime( objname, 0X21 , 0 ) ) ) { = NU ししⅡ & & ( pobjtouch = if ( setfiletime( name, 0X21 , 0 ) setfiletime( objname, &ftime ) ) ) { & & ( pobjtouch = = NULL Ⅱ if ( setfiletime( name, &ftime ) TURBOC_ name ) : ret ファイル属性の取得 / 設定 return( ret ) : = ファイル属性 ( AL = 01h の場合 ) = 01 h : ファイル属性の設定 = 00h : ファイル属性の取得 DS : DX = ASC にノヾス名のアドレス AH = 43h DOS ファンクション 43h ファイル属性の取得 / 設定 CX AL AL キャリー キャリー INT 21h CX = ファイル属性 ( AL = 00h の場合 ) = 05h : アクセスの拒否 = 03h : 無効なパス = 02h : ファイルか存在しない AX = 01 h : 無効なファンクション 1 ションでボリュー D ピット ( 08h ) およびサプティレクトリピット ( 10h ) を変更するこ DS : DX レジスタで指定されたファイルの属性の取得または設定を行う。このファンク とはできない TabIe 6 —dos—getfileattr 関数 (MS-C 5.1 ) ファイル属性の取得 unsigned —dos—getfileattr(path, attr) ; # include く dos. h> cha 「 *path; unsigned * a 「 ; 属性定数 —A—NORMAL 属性を取得するファイル名 属性へのポインタ 意味 通常のファイル 書き込み不可属性 隠し属性 システム属性 ボリューム サプティレクトリ アーカイプ属性 = 0 : 正常終了 = 0 : 工ラー ( MS ー DOS のエラーコード ) —A—ARCH —A—SUBD 旧 —A—VOLI D —A—SYSTEM —A—HIDDEN —A—RDONLY 戻り値
List 67 : 60 : 59 : 58 : 55 : 54 : 53 : 50 : 49 : 47 : 46 : 45 : 44 : 42 : 41 : 40 : 39 : 36 : 35 : 33 : 32 : 30 : 28 : 26 : 24 : 22 : 14 : 12 : 8 : 7 : 6 : 5 : 3 : 1 : 逆 TOUCH コマンド (objtouch. c) ファイル日付を 1980. 01.01 に設定 ファイル名 : objtouch. c 使用法 : objtouch くファイル 1 〉 [.. くファイル n > ] 9 : くファイル名 > は複数指定可能で、拡張子を省略した場合 . obj とします。 10 : 環境変数 OBJTOUCH にオフ・シ・エクトを格納しているテ・イレクトリをセットしてく (OBJTOUCH で指定するテ・イレクトリは漢字のテ・イレクトリ名に対応していません ) * * * * * setfi letime 関数が必要 * * * * * 16 : コンハ・イル・スイッチ 18 : MS-C 5. 1 Sma Ⅱ Model C プログラマのための 第 韋 に ロ 20 : /J /W3 / 2d1 objtouch. c %MSCXYIibYsetargv. obj /link slibcr + ⅱbh/St:0X2800/CP:0X1000/n0e 25 : tcc -w objtouch. c %TC%YI ib%wi ldargs. Obj Sma Ⅱ MOdel 23 : Turbo C 2. 0 / * 環境変数 OBJTOUCH * / int setfi letime(char * , unsigned, unsigned) ; 27 : * / 29 : #include く stdio. h> #include く string. h> 31 : #include く stdlib. h> #include く dos. h 〉 34 : #define PATH し EN int main(int,char * * ) : register int ret char *argv ロ : int argc; int main( argc, argv 43 : #endif #else int setfiletime(char *,struct ftime * ) : 38 : #include く io. h > _TURBOC_ 37 : #ifdef ハ・ス名の長さ register char *pobjtouch 52 : #ifdef __TURBOC_ struct ftime ftime; getenv ( "OBJTOUCH ” ) : * ( long * )&ftime = 0X00210000 し : 56 : #endif if ( argc く = / * 1980. 01. 01 fprintf( stderr, : objtouch くファイル 1 〉 [.. くファイル n > ] \ n " ) : usage return( 1 ) : while ( --argc ) { char name[ PATHLEN ] , objname[ PATH し EN ] : strcpy( name, * 十十 argv ) : if ( strchr ( name, ニ NU しし ) / * テ・フォルト拡張子セット strcat ( name, if ( pobjtouch ! ニ NU しし ) { / * 環境変数 OBJTOUCH Ⅱ pobjtouch [ str len ( pobjtouch ) ( pobjtouch[ strlen( pobjtouch ) "XsXsXs", pobjtouch, sprintf( objname, 定義 新 MS ー DOS プログラミンク入門 MS-DOS の ティレクトリは ? 動もてきます。何か不思議な感じがしませ の内容を見ることがてき , CD コマンドて、移 いますが , DIR コマンドてディレクトリ TEST はディレクトリ TEST に隠し属性を設定して みましよう。 Fig. 2 を見てください。 Fig. 2 List 7(chgatr. c) を使ってちょっと遊んて 効果 隠しティレクトリの ては参考文献 1. を参照してください を大きく超えてしまいますのて詳細につい Fig. 1 の詳しい説明は今回のテーマの範囲 1 参照 ) 。 込まれているわけてす ( ' 91 年 1 月号 88 頁 TabIe トリエントリが 32 バイトを一組にして書き すなわちサプディレクトリには , ディレク ます。これがサプディレクトリの実体てす。 のふたつのディレクトリがあるのがわかり ( 親ディレクトリ ) ( 自分自身のディレクトリ ) の部分を見れば先頭に見なれた 内容をダンプしています。アスキーダンプ ことにより , 強制的にファイルとしてその サプディレクトリ TEST の属性を書き換える はディスクをアプソリュートに読み書きし , こて、ちょっと遊んて、みましよう。 Fig. 1 ます。 スクを直接読み書きすれば強引に変更て、き ァンクションて、変更て、きないだけて , ディ しかし , 変更てきないといっても DOS フ ないわけて、す。 前述のサプディレクトリの属性が変更て、き て、きません。このあたりに違いがあるため ープンてきますがディレクトリはオープン どういうことかというと , ファイルはオ は特別な扱いをされています。 て、はファイルと同じように感じますが , 実 MS-DOS のディレクトリは操作するうえ 新 MS ー DOS プログラミング入門 89
マイクロソフト lnformation from Compiler Makers MS-C 6.0 今回は , 昨年の 11 月に出荷され た MS-C 6.0 に関する代表的な問 い合わせについてお答えます。 Q MS-C 6.0 で追加された言語 仕様を教えてください。 A MS-C 6.0 は , より ANSI C 標 準に近づけ , さらに数々のマイク ロソフトオリジナルの言語仕様を もちます。 Fig. 1 がその言語仕様の 一覧て、す ( 後ろにアスタリスク ( * ) のついているものは , 新たに追加 された言語仕様て、す ) 。 ライプラリも , MS-C 5.1 に比べ 多数の関数が追加されました 0Fig. 2 がその関数名の一覧てす ( 関数名 の後ろにアスタリスクのついてい るものは ,QuickC 2.0 て、追加され た関数て、す ) 。 Q MS-C 6.0 のバッケージを購 入したところ , 中に『デベロッパ ーズツールキット』という商品の 購入申込用紙が入っていました。 この製品の概要を教えてください。 A MS- C Developer's TooIkit は ,MS—C 6.0 のオフィシャルユー ザの方だけが購入てきるプロフェ ッショナルプログラマ向けのライ プラリと資料て、構成されます。 製品の内容は , 以下の 3 つに大き く分けることがてきます。 ・ MS-C 6 . 0 ランタイムライプラリ ソースコード MS-C 6.0 に添付される標準ラ ンタイムライプラリのソースコー ド集て、す。 MATH ライプラリ , BIOS ライプラリ , GRAPHICS 関 連ライプラリ , DOS および OS / 2 用 の標準ランタイムライプラリ ( いく 148 CMAGAZINE 1991 2 Fig. 1 MS-C 6.0 の言語仕様 ・修飾 asm * auto based * cdecl const —export exters fa 「 fastcall fO 「 tran ・プリプロセッサ演算子 defined # (stringize) ・グローノヾル変数 amblksiz daylight dose 「 rno envtron ・キーワード argc argv _asm * autO based * break case cdecl Char const e 「「 no fmode fileinfo * osma 」 0 「 continue default do double e lse _emit * enum envp _export —huge interrupt loadds long #@ (charize) * osmlno 「 _osmode osverslon —PSP extern fa 「 fastcall * float fo 「 fortran goto —huge _near —pascal register _saveregs # # (token-paste) retu rn register —pascal near maln long loadds interrupt int tzname timezone sysnerr syse 「「ⅱ st —segment —segname se げ short sizeof signed shO 「 t setenvp * setargv * self* —segname * _segment * saveregs signed static unsigned volatile while volatile * VOid unsigned umon typedef switc h struct static つかのローレベルルーチンを除く ) 約 350 のソースコードて、す。もちろ んこのソースコードをもとに標準 ライプラリと同等品が作成てきる MAKE ファイルも添付されていま すから , ソースコードの内容を改 編し , ライプラリにして自分のア プリケーションに組み込むことが て、きます。 作成したアプリケーションは , 製品添付のランタイムライプラリ と同様に自由に再販て、きます。ラ ンタイムライプラリの構造解析 , 実行ファイルの特殊環境て、の用途 に欠かせない商品て、す。 Microsoft Advisor HELP Library MS-C 6.0 の PWB , CodeView, QuickHELP, また QuickC 2.0 , QuickBASIC 4.5 が搭載する Mi crosoft Advisor を自作アプリケー ションて、使用するのに必要なライ プラリて、構成されます。 MS ー C 6.0 に付属の HELPMAKE ューティリ ティて作成した HELP ファイル , Microsoft Advisor に対応する HELP ファイルと自由にアクセスが 可能て、す。このライプラリの使用 により , HELP システムの構築時間 を最小限にとどめることが可能て、 す。 出荷は 3 月末の予定て、す。 や名称は変史する場合があります。 て、す。なお製品構成の細かい仕様 上記のパッケージをまとめた商品 MS-C Developer's Toolkit は , 報も含まれます。 ス , PWB 拡張機能に関する補足情 そのライプラリの API リファレン アクセスするためのライプラリと , る Browseri•—タベースファイルを た , Source Browser 機能が利用す ォーマット情報て、す ( Fig. 3 ) 。ま 従来非公開て、あったファイルフ ・ DeveIoper's Toolkit
C フログラマのための TOUCH コマンド (touch. c) LiSt するとカレントディレクトリに指定ファイ ルがない場合 , 指定したディレクトリを検 索します。たとえば set OBJTOUCH=A:%OBJD 旧 または set OBJTOUCH=A:%OBJD 旧 \ のように設定すると , カレントディレクト リの次にディレクトリ A:YOBJDIR を検索し ます (OBJTOUCH て、指定するディレクトリ は漢字のディレクトリ名に対応していませ TOUCH コマンドは現在の時刻に書き換え ますが ,OBJTOUCH ューティリティは 1980 年 1 月 1 日 0 時 0 分 0 秒に書き換えます。 ファイル属性の 取得 / 設定 DOS コマンドて、は ATTRIB コマンドて、リ ードオンリ属性とアーカイプ属性を変更す ることがてきますが , そのほかの属性は変 更てきません。しかし , DOS ファンクショ ン 43h(TabIe 5 ) を使えば隠し属性とシステ ム属性も変更てきるようになります。 MS-C 5.1 て、は属性の取得と設定を行う dos getfileatt 「関数 (Table 6 ) dos setfileattr 関数 (Table 7 ) の関数が用意されていますが TurboC 2.0 にはないようて、す ( 筆者の見落としかもしれ ませんが ) 。そこて getfileatt 「関数 (Table 8 , List 4 ) setfileattr 関数 (Table 9 , List 5 ) のふたつの関数を作成してみました。 これらの関数を使用してファイルの属性 を表示するサンプルプログラムを List 6 (dspatr. c) に , また , ファイルの属性を変更 するサンプルプログラムを List 7(chgatr. c) に示します。 DSPATR の使用法は DSPATR くファイル 1 > [ ... くファイル n > ] て , 表示属性は以下のようになっています。 ・書き込み不可属性 ・・隠し属性 1 : TOUCH コマント・サンフ・ル・フ・ロク・ラム 3 : ファイル名 : touch. c 5 : 6 : 使用法 : touch くファイル 1 > [.. くファイル n > ] 7 : 8 : 9 : setfiletime 関数が必要 * * * * * 11 : コンハ・イル・スイッチ 13 : MS-C 5. 1 Sma 1 1 Model 14 : 15 : cl /J /W3 /Zdl touch. c XMSCXYlibYsetargv. 0bj / 1 ink sl ibcr + libh/st: 0X2800 / cp : 0X1000 / noe 18 : Turbo C 2.0 Small Model 20 : tcc -w touch. c %TC%YI ibYwildargs. obj 22 : * / 23 : 24 : #include く stdio. h> 25 : #include く dos. h> 26 : 27 : int main( int, char 28 : #ifdef TURBOC_ 29 : #include く io. h 〉 30 : 31 : #define dosdate_t date 32 : #define dostime_t t i me 33 : #def ine _dos_getdate getdate 34 : #define _dos-gettime gettime 35 : 36 : int setfiletime(char *,struct ftime * ) : 37 : #else int setfiletime(char *,unsigned. unsigned); 38 : 39 : #endif 40 : int main( argc, argv 41 : 42 : int argc; 43 : char *argv[]; 44 : { struct dosdate_t sdate; 46 : struct dostime_t St i me : 47 : #ifdef _TURBOC_ struct ftime ftime; 49 : #e I se 50 : uns igned udate ; uns igned utime; 52 : #endif 53 : if ( argc ← 1 ) { 54 : fprintf( stderr, return( 1 ) : 56 : -dos-getdate( &sdate ) : -dos-gettime( &stime ) : 60 : #ifdef __TURBOC_ ft i me. ft_year = sdate. da_year ft i me. ft_month = sdate. da_mon : 63 : ft i me. ft_day = sdate. da_day; ft i 田 e. ft_hour stime. ti_hour; ftime. ft_min St i me. t i m ー n : ftime. ft-tsec = stime. ti-sec / 2 : 67 : #else ( ( sdate. year - 1980 ) くく 9 ( sdate. month くく 5 ) \ udate sdate. day; 0 / * 現在の日付 / * 現在の時刻 / * 更新日付 / 時刻 / * 更新日付 / * 更新時刻 . touch くファイル 1 > [.. くファイル n > ] \ n usage - 1980 : 新 MS ー DOS プログラミング入門 87
五ロ はしめて学ぶ 0 プログラー ニンク ・ extern の記憶クラス ン上の OS(MS-DOS や UNIX)< は , ポイン まいます。第 2 にレジスタの数には限りがあ タ ( アドレス ) が , その CPU のレジスタ幅て 内部変数て、 extern の記憶クラスを指定する ります。たとえば 8086 系の CPU ては , レジ 表せるからてす。 と , 外部変数の参照をするための宣言とな スタ自体の数も少ないうえにレジスタごと こて、気をつけてほしいのは , レジスタ ります。 extern 宣言を行うと , 実際に記憶領 に役割分担が決まっているのて , 実際には 変数て、はアドレスを求めることがてきない 域をその変数に割り当てることは行いませ ごくわずかのレジスタしかレジスタ変数に ということてす。たとえば , ん。つまり , 変数の名前と属性 ( 型など ) を 割り当てることがてきません ( 処理系によ 関連づけることだけを行うのて、す。別のい register int a : る ) 。 い方をすると , 狭い意味ての宣言のみが行 int *b また register 宣言をした変数が , すべてレ という記述は , 間違いてす。なぜかという われ , 定義は行われません ( 内部変数の場 ジスタに割り当てられるとはかぎりません。 とレジスタ変数 a は , 記憶領域がレジスタに 合 , 変数を宣言するというと , 変数に記憶 「 egiste 「宣言した変数が , 実際にレジスタに 割り当てられているのて , &a ( 変数 a のアド 領域を割り当てる ( 定義する ) ことも暗黙の 割り当てることがて、きなかった場合は , たん レス ) は存在しないからてす。 内に含まれていることが普通て、す ) 。この点 なる自動変数になります ( レジスタに割り当 については外部変数の項てさらに詳しく説 てることのてきない型の記憶クラスを「 egiste 「 外部変数の場合 明します。 宣言したとしても自動変数になります ) 。従 ・「 egiste 「の記憶クラス っていくら「 egiste 「宣言をしても , レジスタ 「 egiste 「の記憶クラスとは , その名のとお 外部変数ては , 2 種類の記憶クラス指定子 に割り当てられない変数は , 自動変数にな り CPU のレジスタに変数の記憶領域を割り (extern, static) が指定てきます。 るだけなのて、実害はありません。しかしレ 当てます。レジスタに割り当てられた変数 外部変数は処理系によって扱いが異なる ジスタ変数にする必要もない変数を registe 「 のことを , レジスタ変数と呼びます。メモ のて注意して下さい。 宣言すると , 本当にレジスタ変数にしたい リアクセスをしないのて , レジスタ変数は 変数が「 egiste 「宣言したにも関わらず自動変 ・定義と宣言 メモリ上に置かれる普通の変数に比べて高 数になってしまうのて注意してくださいね。 外部変数とは , 変数の定義と宣言を明確 速に動作します。高速に動作するという理 いろいろな制限はありますが , レジスタ に区別するものてしたね。 由から , 文字列操作の関数を作るときなど こて , 簡単に復習しておきましよう。 変数は効果的に使うとかなり強力な武器と に威力を発揮します。 変数を定義するということは , 変数に記憶 なります 0List 3 は文字列をコヒ。ーする関数 しかし , レジスタ変数には , 種々の制限 pstrcpy< す。このアルゴリズムについて 領域を実際に割り当てることてす ( コンパイ があります。まず第 1 に型の問題がありま ル時に固定アドレスが割り当てられます ) 。 は , もう説明する必要はありませんね。 List す。レジスタを使うのてすから , ちょうど 3 て、重要なのは , 仮引数の部分に bregister 1 回だけ確実に変数の定義を行う必要があり レジスタに納まる型てないといけませんね。 宣言てきるということと , ポインタ型も通 ます。 常レジスタ変数にてきるということてす。 従って , 型としては (signed, unsigned)int それに対して , 変数を宣言するというこ 型か (signed,unsigned)char 型 ( さらにポイ ポインタ型がレジスタ変数として扱える理 とは , 変数の名前と属性 ( 記憶クラスや型な ンタ型も含まれることも多い ) に限られてし 由は , 通常のパソコンやワークステーショ ど ) を関連づけるだけて , 記憶領域は確保さ れません。外部変数は複数ファイルにまた 文字列をコピーする関数 pstrcpy(list3. c) がって大域的に使われることが多いてすね。 複数ファイルにまたがって大域的に使う場 合 , 大域的に使われている外部変数が定義 されているファイルと , その大域変数を参 照する ( 宣言して用いる ) ファイルがありま す。 大域変数を参照するファイルては , その 大域変数を使うために , 大域変数の宣言を 行う必要があります。また , 外部変数を定 義するというと暗黙のうちに宣言も含まれ ています。 List 3 1 : char *pstrcpy( register char *sl, register char *s2 ) 3 : char *p 4 : while ( * sl + + ニ * s2 + + ) 5 : 6 : 7 : *sl 8 : 9 : return p; はじめて学ぶ C プログラミング 121