-
Notifications
You must be signed in to change notification settings - Fork 0
/
wc.pas
274 lines (227 loc) · 7.95 KB
/
wc.pas
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
program wc;
{
* count how many bytes, characters, words
* and lines are into a given file.
* Compile it using TP3 - more free memory.
* }
{$i d:types.inc}
{$i d:memory.inc}
{$i d:dos.inc}
{$i d:dos2err.inc}
{$i d:dos2file.inc}
{$i d:fastwrit.inc}
Var
MSXDOSversion: TMSXDOSVersion;
InputFileName: TFileName;
hInputFileName: byte;
hInputFile: text;
TotalLines, TotalBytes, TotalChars, TotalWords: real;
i, j, LengthPrintString: integer;
TemporaryChar, Character: char;
Flag: boolean;
Temporary, PrintString: string[255];
(* Finds the last occurence of a char into a string. *)
function LastPos(Character: char; Phrase: TString): integer;
var
i: byte;
Found: boolean;
begin
i := length(Phrase);
Found := false;
repeat
if Phrase[i] = Character then
begin
LastPos := i + 1;
Found := true;
end;
i := i - 1;
until Found = true;
if Not Found then LastPos := 0;
end;
(* Here we use the APPEND environment variable. *)
procedure CheatAPPEND (FileName: TFileName);
var
i, FirstTwoDotsFound, LastBackSlashFound: byte;
APPEND: string[7];
Path, Temporary: TFileName;
Registers: TRegs;
begin
(* Initializing some variables... *)
fillchar(Path, sizeof(Path), ' ' );
fillchar(Temporary, sizeof(Temporary), ' ' );
APPEND[0] := 'A'; APPEND[1] := 'P'; APPEND[2] := 'P';
APPEND[3] := 'E'; APPEND[4] := 'N'; APPEND[5] := 'D';
APPEND[6] := #0;
(* Sees if in the path there is a ':', used with drive letter. *)
FirstTwoDotsFound := Pos (chr(58), FileName);
(* If there is a two dots... *)
if FirstTwoDotsFound <> 0 then
begin
(* Let me see where is the last backslash character... *)
LastBackSlashFound := LastPos (chr(92), FileName);
Path := copy (FileName, 1, LastBackSlashFound);
(* Copy the path to the variable. *)
for i := 1 to LastBackSlashFound - 1 do
Temporary[i - 1] := Path[i];
Temporary[LastBackSlashFound] := #0;
Path := Temporary;
(* Sets the APPEND environment variable. *)
with Registers do
begin
B := sizeof (Path);
C := ctSetEnvironmentItem;
HL := addr (APPEND);
DE := addr (Path);
end;
MSXBDOS (Registers);
end;
end;
(* Here we use MSX-DOS 2 to do the error handling. *)
procedure ErrorCode (ExitsOrNot: boolean);
var
ErrorCodeNumber: byte;
ErrorMessage: TMSXDOSString;
begin
ErrorCodeNumber := GetLastErrorCode;
GetErrorMessage (ErrorCodeNumber, ErrorMessage);
WriteLn (ErrorMessage);
if ExitsOrNot = true then
Exit;
end;
(* Command help.*)
procedure WCHelp;
begin
clrscr;
fastwriteln('Usage: wc <file> <parameters>.');
fastwriteln('print newline, word, and byte counts');
fastwriteln('for each file.');
writeln;
fastwriteln('File: Text file from where we are ');
fastwriteln('getting lines.');
writeln;
fastwriteln('Parameters: ');
fastwriteln('/h - Display this help and exit.');
fastwriteln('/c - Print the byte counts.');
fastwriteln('/l - Print the newline counts.');
fastwriteln('/m - Print the character counts.');
fastwriteln('/w - Print the word counts.');
fastwriteln('/v - Output version information and');
fastwriteln('exit.');
writeln;
halt;
end;
(* Command version.*)
procedure WCVersion;
begin
clrscr;
fastwriteln('wc version 2.0');
fastwriteln('Copyright (c) 2020 Brazilian MSX Crew.');
fastwriteln('Some rights reserved.');
writeln;
fastwriteln('License GPLv3+: GNU GPL v. 3 or later');
fastwriteln('<https://gnu.org/licenses/gpl.html>');
fastwriteln('This is free software: you are free to');
fastwriteln('change and redistribute it. There is');
fastwriteln('NO WARRANTY to the extent permitted');
fastwriteln('by law.');
writeln;
halt;
end;
begin
(* Initializing some variables. *)
TotalBytes := 0.0;
TotalChars := 0.0;
TotalWords := 0.0;
TotalLines := 0.0;
Flag := false;
Character := 'A';
TemporaryChar := ' ';
fillchar(InputFileName, sizeof(InputFileName), ' ' );
(* if are we not running in a MSX-DOS 2 machine, exits.
* Else... Runs the program. *)
GetMSXDOSVersion (MSXDOSversion);
if (MSXDOSversion.nKernelMajor < 2) then
begin
fastwriteln('MSX-DOS 1.x not supported.');
halt;
end
else
begin
(* No parameters, command prints the help. *)
if paramcount = 0 then WCHelp;
(* Read parameters, and upcase them. *)
for i := 1 to paramcount do
begin
Temporary := paramstr(i);
for j := 1 to length(Temporary) do
Temporary[j] := upcase(Temporary[j]);
if paramcount > 1 then
begin
Character := Temporary[2];
if Temporary[1] = '/' then
begin
delete(Temporary, 1, 2);
(* Parameters. *)
case Character of
'H': WCHelp;
'V': WCVersion;
end;
end;
end;
end;
(* The first parameter should be the file (or the standard input). *)
InputFileName := paramstr(1);
(* Cheats the APPEND environment variable. *)
CheatAPPEND(InputFileName);
(* Open file *)
hInputFileName := FileOpen (InputFileName, 'r');
(* if there is any problem regarding the opening process, show the error code. *)
if (hInputFileName in [ctInvalidFileHandle, ctInvalidOpenMode]) then ErrorCode (true);
(* Close file *)
if (not FileClose(hInputFileName)) then ErrorCode(true);
(* Open file again, as a text file *)
assign(hInputFile, InputFileName);
reset(hInputFile);
(* Finds how many bytes, characters and lines does the file has. *)
while not EOF(hInputFile) do
begin
fillchar(PrintString, sizeof(PrintString), ' ' );
readln(hInputFile, PrintString);
LengthPrintString := Length(PrintString);
if (Character = 'A') or (Character = 'L') then
TotalLines := TotalLines + 1;
if (Character = 'A') or (Character = 'C') then
TotalBytes := TotalBytes + LengthPrintString + 2;
if (Character = 'A') or (Character = 'M') then
TotalChars := TotalChars + LengthPrintString;
if (Character = 'A') or (Character = 'W') then
for i := 1 to LengthPrintString do
begin
TemporaryChar := PrintString[i];
if (ord(TemporaryChar) in [9,13,32]) then
Flag := true
else
if Flag = true then
begin
TotalWords := TotalWords + 1;
flag := false;
end;
end;
end;
CheatAPPEND(' ');
close(hInputFile);
(* C - Print how many bytes does the file has. *)
(* L - Print how many lines does the file has. *)
(* M - Print how many printable chars does the file has. *)
(* W - Print how many words does the file has. *)
(* A - Print everything about the file. *)
case Character of
'C': writeln(TotalBytes:0:0, ' ', InputFileName);
'L': writeln(TotalLines:0:0, ' ', InputFileName);
'M': writeln(TotalChars:0:0, ' ', InputFileName);
'W': writeln(TotalWords:0:0, ' ', InputFileName);
'A': writeln(TotalLines:0:0, ' ', TotalWords:0:0, ' ', TotalBytes:0:0, ' ', InputFileName);
else WCHelp;
end;
end;
end.