Phasor 2.2.0
Stack VM based Programming Language
Loading...
Searching...
No Matches
cat.phs
Go to the documentation of this file.
1// Port of 'cat' - concatenate files and print on the standard output for GNU.
2// 'cat' file concatenation program for Phasor.
3// Copyright (C) 2026 Daniel McGuire.
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18// Include standard libraries
19include_stdio();
20include_stdfile();
21include_stdsys();
22include_stdstr();
23
24// Global variables for options
25var g_show_all = false; // -A, --show-all
26var g_number_nonblank = false; // -b, --number-nonblank
27var g_show_ends = false; // -e, -E, --show-ends
28var g_number = false; // -n, --number
29var g_squeeze_blank = false; // -s, --squeeze-blank
30var g_show_tabs = false; // -t, -T, --show-tabs
31var g_show_nonprinting = false; // -v, --show-nonprinting
32
33// Line number counter
34var g_line_number = 1;
35
36fn startsWith(input: string, prefix: string) {
37 if (len(input) < len(prefix)) return false;
38 return substr(input, 0, len(prefix)) == prefix;
39}
40
41// Function to display help message
42fn show_help() -> void {
43 puts("Usage: cat [OPTION]... [FILE]...");
44 puts("Concatenate FILE(s) to standard output.");
45 puts("");
46 puts("With no FILE, or when FILE is -, read standard input.");
47 puts("");
48 puts("Options:");
49 puts(" -A, --show-all equivalent to -vET");
50 puts(" -b, --number-nonblank number nonempty output lines, overrides -n");
51 puts(" -e equivalent to -vE");
52 puts(" -E, --show-ends display $ at end of each line");
53 puts(" -n, --number number all output lines");
54 puts(" -s, --squeeze-blank suppress repeated empty output lines");
55 puts(" -t equivalent to -vT");
56 puts(" -T, --show-tabs display TAB characters as ^I");
57 puts(" -u (ignored)");
58 puts(" -v, --show-nonprinting use ^ and M- notation, except for LFD and TAB");
59 puts(" --help display this help and exit");
60 puts(" --version output version information and exit");
61 puts("");
62 puts("Examples:");
63 puts(" cat f - g Output f's contents, then standard input, then g's contents.");
64 puts(" cat Copy standard input to standard output.");
65 puts("");
66 puts("GNU coreutils online help: <https://www.gnu.org/software/coreutils/>");
67 puts("Report any translation bugs to <https://translationproject.org/team/>");
68}
69
70// Function to display version information
71fn show_version() -> void {
72 puts("cat (Phasor coreutils) 0.1");
73 puts("License GPLv3+: GNU GPL version 3 or later");
74 puts("This is free software: you are free to change and redistribute it.");
75 puts("There is NO WARRANTY, to the extent permitted by law.");
76 puts("");
77 puts("Written by Daniel McGuire");
78}
79
80// Process a file (or stdin if filename is "-")
81fn process_file(filename: string) -> void {
82 if (filename == "-") {
83 var line = gets();
84 while (line != null) {
85 puts(line);
86 line = gets();
87 }
88 return;
89 }
90
91 if (!fexists(filename)) {
92 puts_error("cat: file not found");
93 return;
94 }
95
96 var content = fread(filename);
97 if (content != null) {
98 puts(content);
99 }
100}
101
102// Main function
103fn main() -> int {
104 var arg_count = sys_argc();
105 var i = 1;
106
107 if (arg_count == 1) {
108 process_file("-");
109 return 0;
110 }
111
112 // Process options
113 for (; i < arg_count; i = i + 1) {
114 var arg = sys_argv(i);
115
116 if (arg == "--") {
117 i = i + 1;
118 break;
119 }
120
121 if (!startsWith(arg, "-")) break;
122
123 if (arg == "--help") {
124 show_help();
125 return 0;
126 }
127
128 if (arg == "--version") {
129 show_version();
130 return 0;
131 }
132
133 if (arg == "-A" || arg == "--show-all") {
134 g_show_all = true;
135 g_show_nonprinting = true;
136 g_show_ends = true;
137 g_show_tabs = true;
138 continue;
139 }
140
141 if (arg == "-b" || arg == "--number-nonblank") {
142 g_number_nonblank = true;
143 g_number = false;
144 continue;
145 }
146
147 if (arg == "-e") {
148 g_show_nonprinting = true;
149 g_show_ends = true;
150 continue;
151 }
152
153 if (arg == "-E" || arg == "--show-ends") {
154 g_show_ends = true;
155 continue;
156 }
157
158 if (arg == "-n" || arg == "--number") {
159 if (!g_number_nonblank) g_number = true;
160 continue;
161 }
162
163 if (arg == "-s" || arg == "--squeeze-blank") {
164 g_squeeze_blank = true;
165 continue;
166 }
167
168 if (arg == "-t") {
169 g_show_nonprinting = true;
170 g_show_tabs = true;
171 continue;
172 }
173
174 if (arg == "-T" || arg == "--show-tabs") {
175 g_show_tabs = true;
176 continue;
177 }
178
179 if (arg == "-v" || arg == "--show-nonprinting") {
180 g_show_nonprinting = true;
181 continue;
182 }
183
184 puts_error("cat: invalid option");
185 puts("Try 'cat --help' for more information.");
186 return 1;
187 }
188
189 // Process files
190 if (i >= arg_count) {
191 process_file("-");
192 } else {
193 while (i < arg_count) {
194 process_file(sys_argv(i));
195 i = i + 1;
196 }
197 }
198
199 return 0;
200}
201
202shutdown(main());