@@ -177,6 +177,8 @@ static term nif_base64_encode(Context *ctx, int argc, term argv[]);
177
177
static term nif_base64_decode (Context * ctx , int argc , term argv []);
178
178
static term nif_base64_encode_to_string (Context * ctx , int argc , term argv []);
179
179
static term nif_base64_decode_to_string (Context * ctx , int argc , term argv []);
180
+ static term nif_code_all_available (Context * ctx , int argc , term argv []);
181
+ static term nif_code_all_loaded (Context * ctx , int argc , term argv []);
180
182
static term nif_code_load_abs (Context * ctx , int argc , term argv []);
181
183
static term nif_code_load_binary (Context * ctx , int argc , term argv []);
182
184
static term nif_lists_reverse (Context * ctx , int argc , term argv []);
@@ -728,6 +730,16 @@ static const struct Nif base64_decode_to_string_nif =
728
730
.base .type = NIFFunctionType ,
729
731
.nif_ptr = nif_base64_decode_to_string
730
732
};
733
+ static const struct Nif code_all_available_nif =
734
+ {
735
+ .base .type = NIFFunctionType ,
736
+ .nif_ptr = nif_code_all_available
737
+ };
738
+ static const struct Nif code_all_loaded_nif =
739
+ {
740
+ .base .type = NIFFunctionType ,
741
+ .nif_ptr = nif_code_all_loaded
742
+ };
731
743
static const struct Nif code_load_abs_nif =
732
744
{
733
745
.base .type = NIFFunctionType ,
@@ -4435,6 +4447,121 @@ static term nif_base64_decode_to_string(Context *ctx, int argc, term argv[])
4435
4447
return base64_decode (ctx , argc , argv , false);
4436
4448
}
4437
4449
4450
+ static term nif_code_all_loaded (Context * ctx , int argc , term argv [])
4451
+ {
4452
+ UNUSED (argc );
4453
+ UNUSED (argv );
4454
+
4455
+ term result = term_nil ();
4456
+ int loaded_modules_count = ctx -> global -> loaded_modules_count ;
4457
+ if (UNLIKELY (memory_ensure_free (ctx , LIST_SIZE (loaded_modules_count , TUPLE_SIZE (2 ))) != MEMORY_GC_OK )) {
4458
+ RAISE_ERROR (OUT_OF_MEMORY_ATOM );
4459
+ }
4460
+
4461
+ for (int ix = 0 ; ix < loaded_modules_count ; ix ++ ) {
4462
+ Module * module = globalcontext_get_module_by_index (ctx -> global , ix );
4463
+ term module_tuple = term_alloc_tuple (2 , & ctx -> heap );
4464
+ term_put_tuple_element (module_tuple , 0 , module_get_name (module ));
4465
+ term_put_tuple_element (module_tuple , 1 , UNDEFINED_ATOM );
4466
+ result = term_list_prepend (module_tuple , result , & ctx -> heap );
4467
+ }
4468
+
4469
+ return result ;
4470
+ }
4471
+
4472
+ struct CodeAllAvailableAcc {
4473
+ Context * ctx ;
4474
+ struct AVMPackData * avmpack_data ;
4475
+ term result ;
4476
+ size_t acc_count ;
4477
+ };
4478
+
4479
+ static void * nif_code_all_available_fold (void * accum , const void * section_ptr , uint32_t section_size , const void * beam_ptr , uint32_t flags , const char * section_name )
4480
+ {
4481
+ UNUSED (section_ptr );
4482
+ UNUSED (section_size );
4483
+ UNUSED (beam_ptr );
4484
+ UNUSED (flags );
4485
+
4486
+ struct CodeAllAvailableAcc * acc = (struct CodeAllAvailableAcc * ) accum ;
4487
+ size_t section_name_len = strlen (section_name );
4488
+ if (section_name_len < 260 ) {
4489
+ if (memcmp (".beam" , section_name + section_name_len - 5 , 5 ) == 0 ) {
4490
+ bool loaded ;
4491
+ if (acc -> avmpack_data -> in_use ) {
4492
+ // Check if module is loaded
4493
+ char atom_str [section_name_len - 5 ];
4494
+ atom_str [0 ] = section_name_len - 5 ;
4495
+ memcpy (atom_str + 1 , section_name , atom_str [0 ]);
4496
+ Module * loaded_module = globalcontext_get_module (acc -> ctx -> global , (AtomString ) & atom_str );
4497
+ loaded = loaded_module != NULL ;
4498
+ } else {
4499
+ loaded = false;
4500
+ }
4501
+ if (!loaded ) {
4502
+ acc -> acc_count ++ ;
4503
+ if (!term_is_invalid_term (acc -> result )) {
4504
+ term module_tuple = term_alloc_tuple (3 , & acc -> ctx -> heap );
4505
+ term_put_tuple_element (module_tuple , 0 , term_from_const_binary (section_name , section_name_len - 5 , & acc -> ctx -> heap , acc -> ctx -> global ));
4506
+ term_put_tuple_element (module_tuple , 1 , UNDEFINED_ATOM );
4507
+ term_put_tuple_element (module_tuple , 2 , FALSE_ATOM );
4508
+ acc -> result = term_list_prepend (module_tuple , acc -> result , & acc -> ctx -> heap );
4509
+ }
4510
+ }
4511
+ }
4512
+ }
4513
+ return accum ;
4514
+ }
4515
+
4516
+ static term nif_code_all_available (Context * ctx , int argc , term argv [])
4517
+ {
4518
+ UNUSED (argc );
4519
+ UNUSED (argv );
4520
+
4521
+ // We return the list of loaded modules and all modules that are
4522
+ // found in loaded avm packs.
4523
+ struct ListHead * item ;
4524
+ struct ListHead * avmpack_data = synclist_rdlock (& ctx -> global -> avmpack_data );
4525
+ struct CodeAllAvailableAcc acc ;
4526
+ acc .ctx = ctx ;
4527
+ acc .result = term_invalid_term ();
4528
+ acc .acc_count = 0 ;
4529
+ LIST_FOR_EACH (item , avmpack_data ) {
4530
+ struct AVMPackData * avmpack_data = GET_LIST_ENTRY (item , struct AVMPackData , avmpack_head );
4531
+ acc .avmpack_data = avmpack_data ;
4532
+ avmpack_fold (& acc , avmpack_data -> data , nif_code_all_available_fold );
4533
+ }
4534
+
4535
+ size_t available_count = acc .acc_count + ctx -> global -> loaded_modules_count ;
4536
+
4537
+ if (UNLIKELY (memory_ensure_free (ctx , LIST_SIZE (available_count , TUPLE_SIZE (3 ) + TERM_BOXED_REFC_BINARY_SIZE )) != MEMORY_GC_OK )) {
4538
+ synclist_unlock (& ctx -> global -> avmpack_data );
4539
+ RAISE_ERROR (OUT_OF_MEMORY_ATOM );
4540
+ }
4541
+
4542
+ // List may be incomplete if modules are loaded while we are iterating on them
4543
+ acc .acc_count = 0 ;
4544
+ acc .result = term_nil ();
4545
+ LIST_FOR_EACH (item , avmpack_data ) {
4546
+ struct AVMPackData * avmpack_data = GET_LIST_ENTRY (item , struct AVMPackData , avmpack_head );
4547
+ acc .avmpack_data = avmpack_data ;
4548
+ avmpack_fold (& acc , avmpack_data -> data , nif_code_all_available_fold );
4549
+ }
4550
+ synclist_unlock (& ctx -> global -> avmpack_data );
4551
+
4552
+ for (size_t ix = 0 ; ix < available_count - acc .acc_count ; ix ++ ) {
4553
+ Module * module = globalcontext_get_module_by_index (ctx -> global , ix );
4554
+ term module_tuple = term_alloc_tuple (3 , & ctx -> heap );
4555
+ AtomString module_atom_str = globalcontext_atomstring_from_term (ctx -> global , module_get_name (module ));
4556
+ term_put_tuple_element (module_tuple , 0 , term_from_const_binary (((const char * ) module_atom_str ) + 1 , ((const char * ) module_atom_str )[0 ], & ctx -> heap , ctx -> global ));
4557
+ term_put_tuple_element (module_tuple , 1 , UNDEFINED_ATOM );
4558
+ term_put_tuple_element (module_tuple , 2 , TRUE_ATOM );
4559
+ acc .result = term_list_prepend (module_tuple , acc .result , & ctx -> heap );
4560
+ }
4561
+
4562
+ return acc .result ;
4563
+ }
4564
+
4438
4565
static term nif_code_load_abs (Context * ctx , int argc , term argv [])
4439
4566
{
4440
4567
UNUSED (argc );
0 commit comments