Skip to content

Commit d0be268

Browse files
misc functions and stuff
1 parent 2bfe157 commit d0be268

File tree

4 files changed

+124
-25
lines changed

4 files changed

+124
-25
lines changed

files.c

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#define _FORTIFY_SOURCE 3
22
#include "files.h"
33
#include <stdio.h>
4-
#include <sys/stat.h>
54
#include <fcntl.h>
65

76
static void closefile(cog_object* stream) {
@@ -136,6 +135,7 @@ cog_object* fn_open() {
136135
char* buf = (char*)alloca(len + 1);
137136
memset(buf, 0, len + 1);
138137
cog_string_to_cstring(filename, buf, len);
138+
errno = 0;
139139
FILE* f = fopen(buf, mod);
140140
if (errno) COG_RETURN_ERROR(cog_sprintf("While opening %O: [Errno %i] %s", filename, errno, strerror(errno)));
141141
else if (!f) COG_RETURN_ERROR(cog_sprintf("Unknown error while opening %O", filename));
@@ -150,22 +150,75 @@ cog_object* fn_readfile() {
150150
COG_ENSURE_TYPE(file, &ot_file);
151151
FILE* f = (FILE*)file->as_ptr;
152152
if (!f) COG_RETURN_ERROR(cog_string("Tried to read a closed file"));
153-
fseek(f, 0, SEEK_SET);
154-
struct stat st;
155-
fstat(fileno(f), &st);
156-
char* b = (char*)alloca(st.st_size + 1);
157-
memset(b, 0, st.st_size + 1);
158-
size_t read = fread(b, sizeof(char), st.st_size, f);
159-
if (read != st.st_size) COG_RETURN_ERROR(cog_sprintf("Couldn't read file %O", file->next));
160-
b[st.st_size] = 0; // remove trailing EOF
161-
cog_push(cog_string(b));
153+
cog_object* str = cog_emptystring();
154+
cog_object* tail = str;
155+
for (int ch = fgetc(f); ch != EOF; ch = fgetc(f))
156+
cog_string_append_byte(&tail, ch);
157+
cog_push(str);
162158
return NULL;
163159
}
164-
cog_modfunc fne_readfile = {"Read-file", COG_FUNC, fn_readfile, "Read the entire contents of the file into a string."};
160+
cog_modfunc fne_readfile = {"Read-File", COG_FUNC, fn_readfile, "Read the entire contents of the file into a string, from beginning to end."};
161+
162+
cog_object* fn_seek() {
163+
COG_ENSURE_N_ITEMS(3);
164+
cog_object* how = cog_pop();
165+
cog_object* where = cog_pop();
166+
cog_object* what = cog_pop();
167+
COG_ENSURE_TYPE(how, &cog_ot_symbol);
168+
float n = 0;
169+
COG_GET_NUMBER(where, n);
170+
COG_ENSURE_TYPE(what, &ot_file);
171+
int w = SEEK_SET;
172+
FILE* f = (FILE*)what->as_ptr;
173+
if (!f) COG_RETURN_ERROR(cog_string("Tried to seek a closed file"));
174+
if (cog_same_identifiers(how->next, cog_make_identifier_c("start"))) w = SEEK_SET;
175+
else if (cog_same_identifiers(how->next, cog_make_identifier_c("end"))) w = SEEK_END;
176+
else if (cog_same_identifiers(how->next, cog_make_identifier_c("current"))) w = SEEK_CUR;
177+
else COG_RETURN_ERROR(cog_sprintf("Expected one of \\start, \\end, \\current but got %O", how));
178+
long nf = n;
179+
if (nf != n) COG_RETURN_ERROR(cog_sprintf("can't seek to a non-integer offset: %O", where));
180+
int err = fseek(f, n, w);
181+
if (err) COG_RETURN_ERROR(cog_sprintf("failed to seek to %O for %O", where, how));
182+
return NULL;
183+
}
184+
cog_modfunc fne_seek = {"Seek", COG_FUNC, fn_seek, "Seeks a file to a particular offset,"};
185+
186+
cog_object* fn_readline() {
187+
COG_ENSURE_N_ITEMS(1);
188+
cog_object* file = cog_pop();
189+
COG_ENSURE_TYPE(file, &ot_file);
190+
FILE* f = (FILE*)file->as_ptr;
191+
if (!f) COG_RETURN_ERROR(cog_string("Tried to read a closed file"));
192+
cog_object* str = cog_emptystring();
193+
cog_object* tail = str;
194+
int ch;
195+
do {
196+
ch = fgetc(f);
197+
cog_string_append_byte(&tail, ch);
198+
} while (ch != '\n');
199+
cog_push(str);
200+
return NULL;
201+
}
202+
cog_modfunc fne_readline = {"Read-Line", COG_FUNC, fn_readline, "Read a line of text from the file, until and including the next newline (ASCII 0x0A) character."};
203+
204+
cog_object* fn_close() {
205+
COG_ENSURE_N_ITEMS(1);
206+
cog_object* file = cog_pop();
207+
COG_ENSURE_TYPE(file, &ot_file);
208+
FILE* f = (FILE*)file->as_ptr;
209+
if (!f) COG_RETURN_ERROR(cog_string("File is already closed"));
210+
fclose(f);
211+
file->as_ptr = NULL;
212+
return NULL;
213+
}
214+
cog_modfunc fne_close = {"Close", COG_FUNC, fn_close, "Close an opened file."};
165215

166216
cog_modfunc* m_file_functions[] = {
167217
&fne_open,
168218
&fne_readfile,
219+
&fne_readline,
220+
&fne_seek,
221+
&fne_close,
169222
NULL
170223
};
171224

main.c

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,10 @@
1010

1111
#include "cogni.h"
1212
#include "files.h"
13+
#include "misc_io.h"
1314
#include "prelude.inc"
1415
#include "prelude2.inc"
1516

16-
cog_object* fn_test() {
17-
cog_printf("Hello, World! The top item is %O\n", cog_pop());
18-
return NULL;
19-
}
20-
cog_modfunc af_test = {"Test-builtin", COG_FUNC, fn_test, "test functionality"};
21-
22-
cog_modfunc* m_test_table[] = {
23-
&af_test,
24-
NULL
25-
};
26-
27-
cog_module test = {"Test", m_test_table, NULL, NULL};
28-
2917
bool do_top(cog_object* cookie) {
3018
cog_run_next(cog_pop(), NULL, cookie);
3119
cog_object* end_status = cog_mainloop(NULL);
@@ -110,12 +98,19 @@ void usage(const char* argv0) {
11098

11199
int main(int argc, char* argv[]) {
112100
cog_init();
113-
cog_add_module(&test);
114101
cog_add_module(&m_file);
102+
cog_add_module(&m_misc_io);
115103
cog_set_stdout(cog_open_file("/dev/stdout", "w"));
116104
cog_set_stdin(cog_open_file("/dev/stdin", "r"));
117105
cog_set_stderr(cog_open_file("/dev/stderr", "w"));
118106

107+
// push parameters
108+
cog_object* params = NULL;
109+
for (int i = argc - 1; i >= 0; i--) {
110+
cog_push_to(&params, cog_string(argv[i]));
111+
}
112+
cog_defun(cog_make_identifier_c("Parameters"), cog_make_var(params));
113+
119114
cog_object* prelude = cog_string_from_bytes((char*)cognac_src_prelude_cog, cognac_src_prelude_cog_len);
120115
cog_object* userscript = NULL;
121116
if (!run(prelude)) goto end;

misc_io.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#define _FORTIFY_SOURCE 3
2+
#include "files.h"
3+
#include <stdio.h>
4+
#include <unistd.h>
5+
6+
cog_object* fn_path() {
7+
char buf[FILENAME_MAX];
8+
errno = 0;
9+
if (!getcwd(buf, FILENAME_MAX)) COG_RETURN_ERROR(cog_sprintf("Couldn't get current path: [Errno %i] %s", errno, strerror(errno)));
10+
cog_push(cog_string(buf));
11+
return NULL;
12+
}
13+
cog_modfunc fne_path = {"Path", COG_FUNC, fn_path, "Return the current working directory."};
14+
15+
#if __has_include(<readline/readline.h>)
16+
#define USE_READLINE 1
17+
#include <readline/readline.h>
18+
#else
19+
#define USE_READLINE 0
20+
#endif
21+
22+
cog_object* fn_input() {
23+
// TODO: use cog_get_stdin()
24+
char* input;
25+
#if USE_READLINE
26+
if (isatty(fileno(stdin))) {
27+
input = readline("");
28+
goto gotten;
29+
}
30+
#endif
31+
size_t len;
32+
getline(&input, &len, stdin);
33+
gotten:
34+
cog_push(cog_string(input));
35+
free(input);
36+
return NULL;
37+
}
38+
cog_modfunc fne_input = {"Input", COG_FUNC, fn_input, "Return a line of user input form stdin."};
39+
40+
cog_modfunc* m_misc_io_functions[] = {
41+
&fne_path,
42+
&fne_input,
43+
NULL
44+
};
45+
46+
cog_module m_misc_io = {"IO::Misc", m_misc_io_functions, NULL, NULL};

misc_io.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#pragma once
2+
3+
#include "cogni.h"
4+
5+
extern cog_module m_misc_io;

0 commit comments

Comments
 (0)