77#include "../bestline/bestline.h"
88#include "ketopt.h"
99#include "gc.h"
10+ #include "repl.h"
1011#include "minilisp.h"
1112
1213int ends_with (const char * str , const char * suffix )
@@ -49,8 +50,12 @@ char *hints(const char *buf, const char **ansi1, const char **ansi2) {
4950 return NULL ;
5051}
5152
53+ // This struct keeps track of the current file/line being evaluated
54+ filepos_t filepos = {"" , 0 , 0 };
55+
5256void minilisp (char * text , size_t length , bool with_repl , Obj * * env , Obj * * expr ) {
5357
58+ // Process file
5459 if (text != NULL ){
5560 // Save old stdin
5661 FILE * old_stdin = stdin ;
@@ -65,53 +70,40 @@ void minilisp(char *text, size_t length, bool with_repl, Obj **env, Obj **expr)
6570 fclose (stream );
6671 }
6772
68- int max_iter = (with_repl ) ? __INT_MAX__ : 0 ;
69- for (int promptnum = 1 ; promptnum < max_iter ; promptnum ++ ) {
70- char prompt [15 ] = "" ;
71- sprintf (prompt , "%d:" , promptnum );
72- char * line = bestline (prompt );
73- if (line == NULL ) continue ;
74-
75- // Save old stdin
76- FILE * old_stdin = stdin ;
77- // Open a memory stream
78- FILE * stream = fmemopen (line , strlen (line ), "r" );
79- // Redirect stdin to the in memory stream in order to use getchar()
80- stdin = stream ;
81-
82- usleep (10000 );
83-
84- if (line [0 ] != '\0' && line [0 ] != '/' ) {
85- int ok = eval_input (line , env , expr );
86- if (ok == 0 ) {
73+ // REPL
74+ if (with_repl )
75+ for (int promptnum = 1 ;; promptnum ++ ) {
76+ char prompt [15 ] = "" ;
77+ sprintf (prompt , "%d:" , promptnum );
78+ char * line = bestline (prompt );
79+ if (line == NULL ) continue ;
80+ // Save old stdin
81+ FILE * old_stdin = stdin ;
82+ // Open a memory stream
83+ FILE * stream = fmemopen (line , strlen (line ), "r" );
84+ // Redirect stdin to the in memory stream in order to use getchar()
85+ stdin = stream ;
86+
87+ usleep (10000 );
88+
89+ if (line [0 ] != '\0' && line [0 ] != '/' ) {
90+ eval_input (line , env , expr );
8791 bestlineHistoryAdd (line );
8892 bestlineHistorySave ("history.txt" );
93+ } else if (line [0 ] == '/' ) {
94+ fputs ("Unreconized command: " , stdout );
95+ fputs (line , stdout );
96+ putchar ('\n' );
8997 }
90- } else if (line [0 ] == '/' ) {
91- fputs ("Unreconized command: " , stdout );
92- fputs (line , stdout );
93- putchar ('\n' );
94- }
9598
96- free (line );
97- // restore stdin
98- stdin = old_stdin ;
99- fclose (stream );
100- }
99+ free (line );
100+ // restore stdin
101+ stdin = old_stdin ;
102+ fclose (stream );
103+ }
101104}
102105
103- __attribute((noreturn )) void error (char * fmt , ...);
104-
105- // Duplicate a string
106- static char * dup_string (const char * str ) {
107- const size_t len = strlen (str );
108- char * copy = malloc (len + 1 );
109- if (copy ){
110- strcpy (copy , str );
111- copy [len ] = '\0' ;
112- }
113- return copy ;
114- }
106+ void error (char * fmt , ...);
115107
116108static size_t read_file (char * fname , char * * text ) {
117109 size_t length = 0 ;
@@ -150,6 +142,10 @@ void process_file(char *fname, Obj **env, Obj **expr) {
150142 char * text ;
151143 size_t len = read_file (fname , & text );
152144 if (len == 0 ) return ;
145+
146+ filepos .filename = strdup (fname );
147+ filepos .file_len = len ;
148+ filepos .line_num = 0 ;
153149
154150 // Save old stdin
155151 FILE * old_stdin = stdin ;
@@ -173,11 +169,12 @@ void process_file(char *fname, Obj **env, Obj **expr) {
173169 stdin = old_stdin ;
174170 fclose (stream );
175171 free (text );
172+ //if (filepos.filename) free(filepos.filename);
176173}
177174
178175static bool no_history = false;
179- static int num_args = 0 ;
180176static char * one_liner = NULL ;
177+ static int num_files = 0 ;
181178static char * * filenames ;
182179static bool with_repl = true;
183180
@@ -223,7 +220,7 @@ void parse_args(int argc, char **argv) {
223220
224221 case 'x' :
225222 case 300 : // --exec "... lisp code ..."
226- one_liner = dup_string (option .arg );
223+ one_liner = strdup (option .arg );
227224 break ;
228225
229226 case 'H' :
@@ -259,10 +256,10 @@ void parse_args(int argc, char **argv) {
259256 }
260257
261258 // regular arguments: run files
262- filenames = ( char * * ) malloc ( argc * sizeof ( char * )) ;
263- for ( int i = option . ind ; i < argc ; i ++ ) {
264- filenames [ i ] = dup_string ( argv [ i ]);
265- printf ( "Executing %s\n" , filenames [i ]);
259+ num_files = argc - option . ind ;
260+ filenames = ( char * * ) malloc ( num_files * sizeof ( char * ));
261+ for ( int i = 1 ; i <= num_files ; i ++ ) {
262+ filenames [ i - 1 ] = strdup ( argv [i ]);
266263 }
267264}
268265
@@ -273,10 +270,12 @@ int main(int argc, char **argv) {
273270 DEFINE2 (env , expr );
274271 init_minilisp (env );
275272
276- for (int i = 0 ; i < num_args ; i ++ ) {
277- printf ("%s" , filenames [i ]);
278- process_file (filenames [i ], env , expr );
273+ for (int i = 0 ; i < num_files ; i ++ ) {
274+ printf ("Loading %s\n" , filenames [i ]);
275+ process_file (filenames [i ], env , expr );
276+ free (filenames [i ]);
279277 }
278+ free (filenames );
280279
281280 /* Set the completion callback. This will be called every time the
282281 * user uses the <tab> key. */
@@ -292,8 +291,6 @@ int main(int argc, char **argv) {
292291 fputs ("Command history disengaged." , stdout );
293292 }
294293
295-
296- //printf("%s\n", one_liner);
297294 size_t len = one_liner ? strlen (one_liner ) : 0 ;
298295 minilisp (one_liner , len , with_repl , env , expr );
299296
0 commit comments