-
Notifications
You must be signed in to change notification settings - Fork 0
/
filename.cpp
294 lines (244 loc) · 9.61 KB
/
filename.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
281
282
283
284
285
286
287
288
289
290
291
292
293
//------------------------------------------------------------------------------
#include "filename.h"
#include "macros.h"
const string FileName::Xc(1,':');
// ADR bodgey workaround for discrepancies in file path character. Run-time OS detection would be better.
#ifdef __BORLANDC__
const string FileName::Xs(1,'\\');
#endif
#ifdef _MSC_VER
const string FileName::Xs(1,'\\');
#endif
#ifdef __GNUC__
const string FileName::Xs(1,'/');
#endif
const string FileName::Xd(1,'.');
const string FileName::X0;
//==============================================================================
FileName::FileName(string s)
// Constructor from input string
{
Sip = s; // Stuff the input data away
Parse(); // Build the output strings
}
//------------------------------------------------------------------------------
FileName::~FileName()
{
}
//------------------------------------------------------------------------------
void FileName::Dump()
{
printf("\nFileName dump.....\n");
printf("Input data Sip = %s\n",Sip.c_str());
printf("Drive substring S0 = %s\n",S0.c_str());
printf("Path substring vector S1 : \n");
WALKVECTOR(string,S1,i)
printf(" ||%s||\n",(*i).c_str());
printf("Extn string S2 = %s\n",S2.c_str());
printf("Last element of path removed S1e = %s\n",S1e.c_str());
printf("Output string: Complete SC = %s\n",SC.c_str());
printf("Output string: Drive SD = %s\n",SD.c_str());
printf("Output string: Path SP = %s\n",SP.c_str());
printf("Output string: Base SB = %s\n",SB.c_str());
printf("Output string: Extension SE = %s\n",SE.c_str());
printf("Old size of S1: oS1siz = %d\n",oS1siz);
printf("Problem = %s\n",problem?"true":"false");
printf("static const string Xc = %s\n",Xc.c_str());
printf("static const string Xs = %s\n",Xs.c_str());
printf("static const string Xd = %s\n",Xd.c_str());
}
//------------------------------------------------------------------------------
bool FileName::Err()
// Return problem status flag
{
return problem;
}
//------------------------------------------------------------------------------
string FileName::FNBase()
// Extract base name
{
return problem ? X0 : SB;
}
//------------------------------------------------------------------------------
void FileName::FNBase(string s)
// Set base name
{
SB = s;
Derive2(); // And the things that depend upon it
Sip = SC; // Recreate the input string
Parse(); // Update everything else
}
//------------------------------------------------------------------------------
string FileName::FNComplete()
// Extract complete filename
{
return problem ? X0 : SC;
}
//------------------------------------------------------------------------------
void FileName::FNComplete(string s)
// Set complete name
{
Sip = s; // New input string
Parse(); // Update everything
}
//------------------------------------------------------------------------------
string FileName::FNDrive()
// Extract drive letter
{
return problem ? X0 : SD;
}
//------------------------------------------------------------------------------
void FileName::FNDrive(string s)
// Set drive
{
SD = s;
if (!s.empty()) SD = string(1,s[0]); // Make sure it's one character
Derive2(); // And the things that depend upon it
Sip = SC; // Recreate the input string
Parse(); // Update everything else
}
//------------------------------------------------------------------------------
string FileName::FNExtn()
// Extract extension
{
return problem ? X0 : SE;
}
//------------------------------------------------------------------------------
void FileName::FNExtn(string s)
// Set extension
{
SE = s;
Derive2(); // And the things that depend upon it
Sip = SC; // Recreate the input string
Parse(); // Update everything else
}
//------------------------------------------------------------------------------
string FileName::FNPath(vector<string> & s)
// Extract full path. String vector goes out as reference argument, concatenated
// path (including drive) as a single string return value
{
s.clear();
if (problem) return X0;
s = S1; // Base already torn off
return SP;
}
//------------------------------------------------------------------------------
void FileName::FNPath(string s,int pos)
// Modify path string. If 'pos' is off either end, 's' is attached to that end.
// If it represents a valid position in the string vector, the string is
// replaced.
// THERE IS NO MECHANISM FOR INTRODUCING EXTRA LEVELS OF HIERARCHY EXCEPT AT THE
// TOP AND BOTTOM
// THERE IS NO MECHANISM FOR REMOVING LEVELS OF HIERARCHY
{
int siz = int(S1.size());
if (siz==0) { S1.push_back(s); goto done;} // Vector initially empty
if (pos<0) { S1.insert(S1.begin(),s); goto done;} // Bolt onto LHS
if (pos>=siz){ S1.push_back(s); goto done;} // Bolt onto RHS
S1[pos]=s; // Replace existing element
oS1siz--; // Decrement overriden by next line
done:
oS1siz++; // The path vector size goes up
Derive1(); // Recreate stuff that depends upon it
Derive2();
Sip = SC; // Recreate the input string
Parse(); // Update everything else
}
//------------------------------------------------------------------------------
string FileName::FNName()
// Simples...
{
return FNBase() + Xd + FNExtn();
}
//------------------------------------------------------------------------------
void FileName::Parse()
{
Lx.SetFile(Sip); // Point the lexer at it
Lx.SetMFlag(true); // Treat "-" as an alphanumeric
Lx.SetNFlag(false); // Tune lexer to *not* recognise numbers
Lx.SetDFlag(false); // '.' is a separator
Lx.SetCChar(EOF); // No continuation character
S0.clear(); // Re-initialise the extracted strings
S1.clear(); // Empty the path vector
S2.clear();
SE = SB = SP = SD = SC = X0;
problem = false; // So far, so good
// And away we go...
enum loctok {t0=0,t1,t2,t3,t4,t5} toktyp;
struct duple {int ns,ac;} next;
duple table[6][t5+1] =
// Incident symbol // Next
// 0 1 2 3 4 5 // state
{{{1, 1},{2, 0},{3, 0},{X, X},{R, 0},{0, X}}, // 0
{{X, X},{2, 0},{X, X},{5, 0},{R, 0},{0, X}}, // 1
{{X, X},{X, X},{3, 0},{X, X},{R, 0},{0, X}}, // 2
{{4, 2},{X, X},{X, X},{X, X},{R, 0},{0, X}}, // 3
{{X, X},{X, X},{3, 0},{5, 0},{R, 0},{0, X}}, // 4
{{R, 3},{X, X},{X, X},{X, X},{R, 0},{0, X}}}; // 5
for(int state=0;;) {
Lex::tokdat Td; // Current lexer token
Lx.GetTok(Td); // Get the next token...
// switch (state) { // Pre-transition (entry) actions
// }
// No exceptional cases (EOF in table)
if (Lx.IsError(Td)) problem = true;
switch (Td.t) { // Map to array index
case Lex::Sy_col : toktyp = t1; break;
case Lex::Sy_div :
case Lex::Sy_back : toktyp = t2; break;
case Lex::Sy_dot : toktyp = t3; break;
case Lex::Sy_EOF : toktyp = t4; break;
case Lex::Sy_mult : toktyp = t0; break; // "*" accepted as a valid string
default : toktyp = t5; break;
}
if (Lex::IsStr(Td.t)) toktyp = t0; // Reduction functions
next = table[state][toktyp]; // Make the transition
switch (next.ac) { // Post-transition (exit) actions
case 0 : break;
case X : problem = true; break;
case 1 : S0 = Td.s; break;
case 2 : S1.push_back(Td.s); break;
case 3 : S2 = Td.s; break;
default : break;
}
switch (state=next.ns) {
case X : goto done;
case R : goto done;
}
if (problem==true) break; // May be set elsewhere
}
if (problem==true) return;
done:
oS1siz = (unsigned int)S1.size();
if (!S1.empty()) { // If the path vector isn't empty...
S1e = S1.back(); // ...pull the basename off the end
S1.pop_back();
}
Derive1(); // Derive the secondary strings 'n' stuff
Derive2();
return;
}
//------------------------------------------------------------------------------
void FileName::Derive1()
// Derive extension, base and drive
{
SE = S2; // Extn
if (oS1siz!=0) SB = S1e; // Base
else {
if (!S0.empty()) SB = S0;
else SB = S2; // Even if S2 = empty
}
if ((!S0.empty())&&(oS1siz!=0)) SD = string(1,S0[0]); // Drive, else SD = ""
}
//------------------------------------------------------------------------------
void FileName::Derive2()
// Derive path and complete
{
SP.clear(); // Build the path as a single string
WALKVECTOR(string,S1,i) SP += Xs + *i;
if (!SD.empty()) SP = SD + Xc + SP;
SC = SB; // Complete reconstruction
if (!SP.empty()) SC = SP + Xs + SC;
if (!SE.empty()) SC += Xd + SE;
}
//------------------------------------------------------------------------------