-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcmdchdir.cpp
280 lines (258 loc) · 6.93 KB
/
cmdchdir.cpp
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/* ディレクトリ操作関係のコマンドの定義ソース */
#include <ctype.h>
#include <stdlib.h>
#include "ntcons.h"
#include "nndir.h"
#include "shell.h"
static NnVector dirstack;
static NnString prevdir , currdir ;
/* スタックの内容を ~n に反映する */
static void chg_tilde()
{
int i;
for( i=1 ; i <= 9 ; ++i ){
char no[]={ '0' + i , '\0' };
int n=dirstack.size()-i;
if( n >= 0 ){
NnDir::specialFolder.put( no , ((NnString*)dirstack.at(n))->clone() );
}else{
NnDir::specialFolder.remove( no );
}
}
}
/* chdir のラッパー. 一つ前のディレクトリを記憶する.
* dir - 移動先ディレクトリ
* return
* 0 - 成功 , not 0 - 失敗
*/
static int chdir_( const NnString &dir )
{
int rc;
if( currdir.empty() ){
NnDir::getcwd( currdir );
}
if( (rc=NnDir::chdir( dir.chars() )) == 0 ){
prevdir = currdir;
NnDir::getcwd( currdir );
Console::setConsoleTitle( currdir.chars() );
}
return rc;
}
/* カレントディレクトリをスタックへ */
static void pushd_here()
{
NnString *cwd=new NnString();
NnDir::getcwd(*cwd);
dirstack.append( cwd );
}
/* スタックトップをカレントディレクトリへ
* return
* NULL: 成功
* not NULL: 失敗した時のディレクトリ名
* (呼び出し元にて、delete すること)
*/
static NnString *popd_here()
{
NnString *cwd = (NnString*)dirstack.shift();
if( chdir_( *cwd ) != 0 ){
return cwd;
}else{
delete cwd;
return NULL;
}
}
/* スタックトップとカレントディレクトリを交換
* return
* NULL - 成功
* not NULL - 移動できなかった場合のスタックトップ
*/
static NnString *swap_here()
{
NnString *top=(NnString*)dirstack.top();
NnString newcwd( *top );
NnDir::getcwd( *top );
if( chdir_( newcwd ) != 0 ){
delete (NnString*)dirstack.shift();
return new NnString(newcwd);
}
return NULL;
}
/* 内蔵コマンド dirs */
int cmd_dirs( NyadosShell &shell , const NnString & )
{
NnString cwd;
NnDir::getcwd(cwd);
shell.out() << cwd ;
for(int i=dirstack.size()-1 ; i>=0 ; i-- ){
shell.out() << ' ' << *(NnString*)dirstack.at(i);
}
shell.out() << '\n';
return 0;
}
/* 内蔵コマンド pushd */
int cmd_pushd( NyadosShell &shell , const NnString &argv_ )
{
NnString argv(argv_);
int here_flag = 0;
if( argv.startsWith("-") ){
NnString arg1,left;
argv.splitTo( arg1,left);
argv = left;
if( arg1.compare("-h")==0 ){
here_flag = 1;
}else if( arg1.compare("-H")==0 ){
here_flag = 2;
}
}
if( argv.empty() ){
/* スタックトップのディレクトリとカレントディレクトリを入れ替える */
if( dirstack.size() < 1 ){
if( here_flag ){
pushd_here();
}else{
shell.err() << "pushd: directory stack empty.\n";
return 0;
}
}else{
if( here_flag == 2 ){
pushd_here();
}else{
NnString *dir=swap_here();
if( dir != NULL ){
shell.err() << "pushd: stack top `" << *dir << "' not found.\n";
delete dir;
return 0;
}
}
}
}else if( argv.at(0) == '+' && isDigit(argv.at(1)) ){
/* スタックを +n 形式で指定する。n 回回転させる */
int n=atoi(argv.chars()+1);
if( n > 0 ){
/* 末尾にカレントディレクトリを push した時点で、
* すでに一回転扱い
*/
pushd_here();
while( --n > 0 )
dirstack.append( dirstack.shift() );
NnString *faildir=popd_here();
if( faildir != NULL ){
shell.err() << "pushd: directory `" << *faildir << "' not found.\n";
delete faildir;
return 0;
}
}
}else{
/* 現在のディレクトリをスタックに保存 */
pushd_here();
/* ディレクトリを移動 */
NyadosShell::dequote( argv );
if( chdir_( argv ) != 0 ){
shell.err() << argv << ": no such directory.\n";
delete popd_here();
return 0;
}
}
chg_tilde();
return cmd_dirs(shell,argv);
}
/* 内蔵コマンド popd 処理ルーチン */
int cmd_popd( NyadosShell &shell , const NnString &argv )
{
if( dirstack.size() <= 0 ){
shell.err() << "popd: dir stack is empty.\n";
return 0;
}
if( argv.at(0) == '+' && isDigit(argv.at(1)) ){
NnString *dir=(NnString*)dirstack.at(atoi(argv.chars()+1));
if( dir == NULL ){
shell.err() << "popd: " << argv << ": bad directory stack index\n";
return 0;
}else{
if( chdir_( *dir ) != 0 ){
shell.err() << "popd: " << *dir << ": not found.\n";
return 0;
}
}
}else{
NnString *dir=(NnString*)dirstack.pop();
chg_tilde();
if( chdir_( *dir ) != 0 ){
shell.err() << "popd: " << *dir << ": not found.\n";
delete dir;
return 0;
}
delete dir;
}
return cmd_dirs(shell,argv);
}
int cmd_shift( NyadosShell &shell , const NnString & )
{
shell.shift();
return 0;
}
int cmd_goto( NyadosShell &shell , const NnString &argv )
{
NnString label( argv );
label.trim();
shell.goLabel(label);
return 0;
}
int cmd_pwd( NyadosShell &shell , const NnString & )
{
NnString pwd;
if( NnDir::getcwd( pwd ) == 0 ){
shell.out() << pwd << '\n';
}else{
shell.err() << "can't get current working directory.\n";
}
return 0;
}
/* 内蔵コマンド chdir 処理ルーチン */
int cmd_chdir( NyadosShell &shell , const NnString &argv )
{
int basedir=0;
NnString newdir;
if( argv.empty() ){
/* 引数が空の場合 */
if( getEnv("HOME") == NULL &&
getEnv("USERPROFILE") == NULL )
return cmd_pwd(shell,argv);
newdir = "~";
}else if( argv.startsWith("-") ){
/* オプション処理 */
NnString tmp , opt;
argv.splitTo( opt , tmp );
if( opt.icompare("--basedir") == 0 ){
basedir = 1;
}else if( opt.compare("-") == 0 ){
if( prevdir.empty() ){
shell.err() << opt << ": can not chdir.\n";
return 0;
}
tmp = prevdir;
}else{
shell.err() << opt << ": no such option.\n";
return 0;
}
NyadosShell::dequote( tmp.chars() , newdir );
}else{
NyadosShell::dequote( argv.chars() , newdir );
}
/* chdir 処理 */
if( chdir_( newdir ) == 0 )
return 0;
/* chdir 自体が失敗した場合、--basedir オプションで処理する場合がある */
if( basedir ){
int lastroot=NnDir::lastRoot( newdir.chars() );
if( lastroot != -1 ){
NnString bdir( newdir.chars() , lastroot );
bdir << "\\."; // rootディレクトリ対策
if( chdir_( bdir ) == 0 )
return 0;
}
}
/* エラー終了 */
shell.err() << newdir << ": no such file or directory.\n";
return 0;
}