11const std = @import ("std" );
2-
32const HACKER_DIR_SUFFIX = "/.hackeros/hacker-lang" ;
4-
53fn parse_hacker_file (allocator : std.mem.Allocator , file_path : []const u8 , verbose : bool ) ! struct {
6- deps : std.StringHashSet ,
7- libs : std.StringHashSet ,
4+ deps : std .StringHashMap ( void ) ,
5+ libs : std .StringHashMap ( void ) ,
86 vars_dict : std .StringHashMap ([]const u8 ),
97 cmds : std .ArrayList ([]const u8 ),
108 includes : std .ArrayList ([]const u8 ),
119 binaries : std .ArrayList ([]const u8 ),
1210 errors : std .ArrayList ([]const u8 ),
1311 config_data : std .StringHashMap ([]const u8 ),
1412} {
15- var deps = std .StringHashSet .init (allocator );
16- var libs = std .StringHashSet .init (allocator );
13+ var deps = std .StringHashMap ( void ) .init (allocator );
14+ var libs = std .StringHashMap ( void ) .init (allocator );
1715 var vars_dict = std .StringHashMap ([]const u8 ).init (allocator );
1816 var cmds = std .ArrayList ([]const u8 ).init (allocator );
1917 var includes = std .ArrayList ([]const u8 ).init (allocator );
2018 var binaries = std .ArrayList ([]const u8 ).init (allocator );
2119 var errors = std .ArrayList ([]const u8 ).init (allocator );
2220 var config_data = std .StringHashMap ([]const u8 ).init (allocator );
23-
2421 var in_config = false ;
2522 var line_num : u32 = 0 ;
26-
27- const home = std .os .getenv ("HOME" ) orelse "" ;
23+ const home = std .posix .getenv ("HOME" ) orelse "" ;
2824 const hacker_dir = try std .fs .path .join (allocator , &.{ home , HACKER_DIR_SUFFIX });
2925 defer allocator .free (hacker_dir );
30-
3126 const console = std .io .getStdOut ().writer ();
32-
3327 const file = std .fs .cwd ().openFile (file_path , .{}) catch | err | {
3428 if (err == error .FileNotFound ) {
3529 if (verbose ) try console .print ("File {s} not found\n " , .{file_path });
@@ -48,18 +42,14 @@ fn parse_hacker_file(allocator: std.mem.Allocator, file_path: []const u8, verbos
4842 return err ;
4943 };
5044 defer file .close ();
51-
5245 const reader = file .reader ();
5346 var line_buf : [4096 ]u8 = undefined ;
54-
5547 while (reader .readUntilDelimiterOrEof (& line_buf , '\n ' ) catch null ) | line_slice | {
5648 line_num += 1 ;
57- const line_trimmed = std .mem .trim (u8 , line_slice orelse break , " \t \r \n " );
49+ const line_trimmed = std .mem .trim (u8 , line_slice , " \t \r \n " );
5850 if (line_trimmed .len == 0 ) continue ;
59-
6051 const line = try allocator .dupe (u8 , line_trimmed );
6152 defer allocator .free (line );
62-
6353 if (std .mem .eql (u8 , line , "[" )) {
6454 if (in_config ) {
6555 try errors .append (try std .fmt .allocPrint (allocator , "Line {d}: Nested config section" , .{line_num }));
@@ -73,7 +63,6 @@ fn parse_hacker_file(allocator: std.mem.Allocator, file_path: []const u8, verbos
7363 in_config = false ;
7464 continue ;
7565 }
76-
7766 if (in_config ) {
7867 if (std .mem .indexOfScalar (u8 , line , '=' )) | eq_pos | {
7968 const key = std .mem .trim (u8 , line [0.. eq_pos ], " \t " );
@@ -82,11 +71,10 @@ fn parse_hacker_file(allocator: std.mem.Allocator, file_path: []const u8, verbos
8271 }
8372 continue ;
8473 }
85-
8674 if (std .mem .startsWith (u8 , line , "//" )) {
8775 const dep = std .mem .trim (u8 , line [2.. ], " \t " );
8876 if (dep .len > 0 ) {
89- _ = try deps .insert (try allocator .dupe (u8 , dep ));
77+ _ = try deps .put (try allocator .dupe (u8 , dep ), {} );
9078 } else {
9179 try errors .append (try std .fmt .allocPrint (allocator , "Line {d}: Empty system dependency" , .{line_num }));
9280 }
@@ -95,26 +83,27 @@ fn parse_hacker_file(allocator: std.mem.Allocator, file_path: []const u8, verbos
9583 if (lib .len > 0 ) {
9684 const lib_dir = try std .fs .path .join (allocator , &.{ hacker_dir , "libs" , lib });
9785 defer allocator .free (lib_dir );
98-
9986 const lib_hacker_path = try std .fs .path .join (allocator , &.{ lib_dir , "main.hacker" });
10087 defer allocator .free (lib_hacker_path );
101-
10288 const lib_bin_path = try std .fs .path .join (allocator , &.{ hacker_dir , "libs" , lib });
10389 defer allocator .free (lib_bin_path );
104-
10590 if (std .fs .cwd ().access (lib_hacker_path , .{})) | _ | {
10691 try includes .append (try allocator .dupe (u8 , lib ));
107- const sub = try parse_hacker_file (allocator , lib_hacker_path , verbose );
108- for (sub .deps .keys ()) | sub_dep | {
109- _ = try deps .insert (sub_dep );
92+ var sub = try parse_hacker_file (allocator , lib_hacker_path , verbose );
93+ var dep_it = sub .deps .keyIterator ();
94+ while (dep_it .next ()) | sub_dep_ptr | {
95+ const sub_dep = sub_dep_ptr .* ;
96+ _ = try deps .put (try allocator .dupe (u8 , sub_dep ), {});
11097 }
111- for (sub .libs .keys ()) | sub_lib | {
112- _ = try libs .insert (sub_lib );
98+ var lib_it = sub .libs .keyIterator ();
99+ while (lib_it .next ()) | sub_lib_ptr | {
100+ const sub_lib = sub_lib_ptr .* ;
101+ _ = try libs .put (try allocator .dupe (u8 , sub_lib ), {});
113102 }
114103 {
115104 var sub_it = sub .vars_dict .iterator ();
116105 while (sub_it .next ()) | entry | {
117- try vars_dict .put (entry .key_ptr .* , entry .value_ptr .* );
106+ try vars_dict .put (try allocator . dupe ( u8 , entry .key_ptr .* ), try allocator . dupe ( u8 , entry .value_ptr .* ) );
118107 }
119108 }
120109 try cmds .appendSlice (sub .cmds .items );
@@ -133,11 +122,10 @@ fn parse_hacker_file(allocator: std.mem.Allocator, file_path: []const u8, verbos
133122 sub .errors .deinit ();
134123 sub .config_data .deinit ();
135124 } else | _ | {} // ignore access error for now
136-
137- if (std .fs .cwd ().access (lib_bin_path , .{ .mode = .execute })) | _ | {
125+ if (std .posix .access (lib_bin_path , std .posix .X_OK )) | _ | {
138126 try binaries .append (try allocator .dupe (u8 , lib_bin_path ));
139127 } else | _ | {
140- _ = try libs .insert (try allocator .dupe (u8 , lib ));
128+ _ = try libs .put (try allocator .dupe (u8 , lib ), {} );
141129 }
142130 } else {
143131 try errors .append (try std .fmt .allocPrint (allocator , "Line {d}: Empty library/include" , .{line_num }));
@@ -211,24 +199,37 @@ fn parse_hacker_file(allocator: std.mem.Allocator, file_path: []const u8, verbos
211199 try errors .append (try std .fmt .allocPrint (allocator , "Line {d}: Invalid syntax" , .{line_num }));
212200 }
213201 }
214-
215202 if (in_config ) {
216203 try errors .append (try allocator .dupe (u8 , "Unclosed config section" ));
217204 }
218-
219205 if (verbose ) {
220- try console .print ("System Deps: {any}\n " , .{deps .keys ()});
221- try console .print ("Custom Libs: {any}\n " , .{libs .keys ()});
222- try console .print ("Vars: {any}\n " , .{vars_dict .unmanaged });
206+ var dep_keys = try allocator .alloc ([]const u8 , deps .count ());
207+ defer allocator .free (dep_keys );
208+ var i : usize = 0 ;
209+ var dep_it = deps .keyIterator ();
210+ while (dep_it .next ()) | key | {
211+ dep_keys [i ] = key .* ;
212+ i += 1 ;
213+ }
214+ try console .print ("System Deps: {any}\n " , .{dep_keys });
215+ var lib_keys = try allocator .alloc ([]const u8 , libs .count ());
216+ defer allocator .free (lib_keys );
217+ i = 0 ;
218+ var lib_it = libs .keyIterator ();
219+ while (lib_it .next ()) | key | {
220+ lib_keys [i ] = key .* ;
221+ i += 1 ;
222+ }
223+ try console .print ("Custom Libs: {any}\n " , .{lib_keys });
224+ try console .print ("Vars: {any}\n " , .{vars_dict });
223225 try console .print ("Cmds: {any}\n " , .{cmds .items });
224226 try console .print ("Includes: {any}\n " , .{includes .items });
225227 try console .print ("Binaries: {any}\n " , .{binaries .items });
226- try console .print ("Config: {any}\n " , .{config_data . unmanaged });
228+ try console .print ("Config: {any}\n " , .{config_data });
227229 if (errors .items .len > 0 ) {
228230 try console .print ("Errors: {any}\n " , .{errors .items });
229231 }
230232 }
231-
232233 return .{
233234 .deps = deps ,
234235 .libs = libs ,
@@ -240,15 +241,12 @@ fn parse_hacker_file(allocator: std.mem.Allocator, file_path: []const u8, verbos
240241 .config_data = config_data ,
241242 };
242243}
243-
244244pub fn main () ! void {
245245 var gpa = std .heap .GeneralPurposeAllocator (.{}){};
246246 defer _ = gpa .deinit ();
247247 const allocator = gpa .allocator ();
248-
249248 var verbose = false ;
250249 var file_path : ? []const u8 = null ;
251-
252250 for (std .os .argv [1.. ]) | arg_ptr | {
253251 const arg = std .mem .span (arg_ptr );
254252 if (std .mem .eql (u8 , arg , "--verbose" )) {
@@ -260,14 +258,11 @@ pub fn main() !void {
260258 std .process .exit (1 );
261259 }
262260 }
263-
264261 if (file_path == null ) {
265262 try std .io .getStdErr ().writer ().print ("Usage: hacker-parser [--verbose] <file>\n " , .{});
266263 std .process .exit (1 );
267264 }
268-
269- const res = try parse_hacker_file (allocator , file_path .? , verbose );
270-
265+ var res = try parse_hacker_file (allocator , file_path .? , verbose );
271266 defer res .deps .deinit ();
272267 defer res .libs .deinit ();
273268 defer res .vars_dict .deinit ();
@@ -276,17 +271,19 @@ pub fn main() !void {
276271 defer res .binaries .deinit ();
277272 defer res .errors .deinit ();
278273 defer res .config_data .deinit ();
279-
280274 var deps_list = std .ArrayList ([]const u8 ).init (allocator );
281275 defer deps_list .deinit ();
282- for (res .deps .keys ()) | d | try deps_list .append (d );
283-
276+ var dep_it = res .deps .keyIterator ();
277+ while (dep_it .next ()) | key | {
278+ try deps_list .append (key .* );
279+ }
284280 var libs_list = std .ArrayList ([]const u8 ).init (allocator );
285281 defer libs_list .deinit ();
286- for (res .libs .keys ()) | l | try libs_list .append (l );
287-
282+ var lib_it = res .libs .keyIterator ();
283+ while (lib_it .next ()) | key | {
284+ try libs_list .append (key .* );
285+ }
288286 const stdout = std .io .getStdOut ().writer ();
289-
290287 try stdout .print ("{{" , .{});
291288 try stdout .print ("\" deps\" :[" , .{});
292289 var first = true ;
0 commit comments