ruby-magic 0.4.0 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,6 +4,77 @@ extern "C" {
4
4
 
5
5
  #include "ruby-magic.h"
6
6
 
7
+ static int rb_mgc_do_not_auto_load;
8
+ static int rb_mgc_do_not_stop_on_error;
9
+ static int rb_mgc_warning;
10
+
11
+ static ID id_at_flags;
12
+ static ID id_at_paths;
13
+
14
+ static VALUE rb_cMagic;
15
+
16
+ static VALUE rb_mgc_eError;
17
+ static VALUE rb_mgc_eMagicError;
18
+ static VALUE rb_mgc_eLibraryError;
19
+ static VALUE rb_mgc_eNotImplementedError;
20
+ static VALUE rb_mgc_eParameterError;
21
+ static VALUE rb_mgc_eFlagsError;
22
+
23
+ static const rb_data_type_t rb_mgc_type;
24
+
25
+ static VALUE magic_get_parameter_internal(void *data);
26
+ static VALUE magic_set_parameter_internal(void *data);
27
+
28
+ static VALUE magic_get_flags_internal(void *data);
29
+ static VALUE magic_set_flags_internal(void *data);
30
+
31
+ static VALUE magic_load_internal(void *data);
32
+ static VALUE magic_load_buffers_internal(void *data);
33
+
34
+ static VALUE magic_compile_internal(void *data);
35
+ static VALUE magic_check_internal(void *data);
36
+
37
+ static VALUE magic_file_internal(void *data);
38
+ static VALUE magic_buffer_internal(void *data);
39
+ static VALUE magic_descriptor_internal(void *data);
40
+
41
+ static VALUE magic_close_internal(void *data);
42
+
43
+ static void *nogvl_magic_load(void *data);
44
+ static void *nogvl_magic_compile(void *data);
45
+ static void *nogvl_magic_check(void *data);
46
+ static void *nogvl_magic_file(void *data);
47
+ static void *nogvl_magic_descriptor(void *data);
48
+
49
+ static void *magic_library_open(void);
50
+ static void magic_library_close(void *data);
51
+
52
+ static VALUE magic_allocate(VALUE klass);
53
+ static void magic_mark(void *data);
54
+ static void magic_free(void *data);
55
+ static size_t magic_size(const void *data);
56
+ #if defined(HAVE_RUBY_GC_COMPACT)
57
+ static void magic_compact(void *data);
58
+ #endif
59
+
60
+ static VALUE magic_exception_wrapper(VALUE value);
61
+ static VALUE magic_exception(void *data);
62
+
63
+ static VALUE magic_library_error(VALUE klass, void *data);
64
+ static VALUE magic_generic_error(VALUE klass, int magic_errno,
65
+ const char *magic_error);
66
+
67
+ static VALUE magic_lock(VALUE object, VALUE (*function)(ANYARGS),
68
+ void *data);
69
+ static VALUE magic_unlock(VALUE object);
70
+
71
+ static VALUE magic_return(void *data);
72
+
73
+ static int magic_get_flags(VALUE object);
74
+ static void magic_set_flags(VALUE object, int flags);
75
+
76
+ static VALUE magic_set_paths(VALUE object, VALUE value);
77
+
7
78
  /*
8
79
  * call-seq:
9
80
  * Magic.do_not_auto_load -> boolean
@@ -56,6 +127,7 @@ VALUE
56
127
  rb_mgc_set_do_not_auto_load_global(RB_UNUSED_VAR(VALUE object), VALUE value)
57
128
  {
58
129
  rb_mgc_do_not_auto_load = RVAL2CBOOL(value);
130
+
59
131
  return value;
60
132
  }
61
133
 
@@ -96,6 +168,7 @@ VALUE
96
168
  rb_mgc_set_do_not_stop_on_error_global(RB_UNUSED_VAR(VALUE object), VALUE value)
97
169
  {
98
170
  rb_mgc_do_not_stop_on_error = RVAL2CBOOL(value);
171
+
99
172
  return value;
100
173
  }
101
174
 
@@ -117,7 +190,7 @@ rb_mgc_set_do_not_stop_on_error_global(RB_UNUSED_VAR(VALUE object), VALUE value)
117
190
  VALUE
118
191
  rb_mgc_initialize(VALUE object, VALUE arguments)
119
192
  {
120
- magic_object_t *mo;
193
+ rb_mgc_object_t *mgc;
121
194
  const char *klass = "Magic";
122
195
 
123
196
  if (!NIL_P(object))
@@ -127,21 +200,22 @@ rb_mgc_initialize(VALUE object, VALUE arguments)
127
200
  MAGIC_WARNING(0, "%s::new() does not take block; use %s::open() instead",
128
201
  klass, klass);
129
202
 
130
- if(RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_STOP_ON_ERROR']")))
203
+ if (RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_STOP_ON_ERROR']")))
131
204
  rb_mgc_do_not_stop_on_error = 1;
132
205
 
133
- if(RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_AUTOLOAD']")))
206
+ if (RTEST(rb_eval_string("ENV['MAGIC_DO_NOT_AUTOLOAD']")))
134
207
  rb_mgc_do_not_auto_load = 1;
135
208
 
136
- MAGIC_OBJECT(mo);
137
- mo->stop_on_errors = 1;
209
+ MAGIC_OBJECT(object, mgc);
210
+
211
+ mgc->stop_on_errors = 1;
138
212
  if (rb_mgc_do_not_stop_on_error)
139
- mo->stop_on_errors = 0;
213
+ mgc->stop_on_errors = 0;
140
214
 
141
- mo->mutex = rb_class_new_instance(0, 0, rb_const_get(rb_cObject,
142
- rb_intern("Mutex")));
215
+ mgc->mutex = rb_class_new_instance(0, 0, rb_const_get(rb_cObject,
216
+ rb_intern("Mutex")));
143
217
 
144
- magic_set_flags(object, INT2NUM(MAGIC_NONE));
218
+ magic_set_flags(object, MAGIC_NONE);
145
219
  magic_set_paths(object, RARRAY_EMPTY);
146
220
 
147
221
  if (rb_mgc_do_not_auto_load) {
@@ -153,6 +227,7 @@ rb_mgc_initialize(VALUE object, VALUE arguments)
153
227
  }
154
228
 
155
229
  rb_mgc_load(object, arguments);
230
+
156
231
  return object;
157
232
  }
158
233
 
@@ -165,12 +240,12 @@ rb_mgc_initialize(VALUE object, VALUE arguments)
165
240
  VALUE
166
241
  rb_mgc_get_do_not_stop_on_error(VALUE object)
167
242
  {
168
- magic_object_t *mo;
243
+ rb_mgc_object_t *mgc;
169
244
 
170
245
  MAGIC_CHECK_OPEN(object);
171
- MAGIC_OBJECT(mo);
246
+ MAGIC_OBJECT(object, mgc);
172
247
 
173
- return CBOOL2RVAL(!mo->stop_on_errors);
248
+ return CBOOL2RVAL(!mgc->stop_on_errors);
174
249
  }
175
250
 
176
251
  /*
@@ -182,12 +257,13 @@ rb_mgc_get_do_not_stop_on_error(VALUE object)
182
257
  VALUE
183
258
  rb_mgc_set_do_not_stop_on_error(VALUE object, VALUE value)
184
259
  {
185
- magic_object_t *mo;
260
+ rb_mgc_object_t *mgc;
186
261
 
187
262
  MAGIC_CHECK_OPEN(object);
188
- MAGIC_OBJECT(mo);
263
+ MAGIC_OBJECT(object, mgc);
264
+
265
+ mgc->stop_on_errors = !RVAL2CBOOL(value);
189
266
 
190
- mo->stop_on_errors = !RVAL2CBOOL(value);
191
267
  return value;
192
268
  }
193
269
 
@@ -229,14 +305,15 @@ rb_mgc_open_p(VALUE object)
229
305
  VALUE
230
306
  rb_mgc_close(VALUE object)
231
307
  {
232
- magic_object_t *mo;
308
+ rb_mgc_object_t *mgc;
233
309
 
234
310
  if (MAGIC_CLOSED_P(object))
235
311
  return Qnil;
236
312
 
237
- MAGIC_OBJECT(mo);
238
- if (mo) {
239
- MAGIC_SYNCHRONIZED(magic_close_internal, mo);
313
+ MAGIC_OBJECT(object, mgc);
314
+
315
+ if (mgc) {
316
+ MAGIC_SYNCHRONIZED(magic_close_internal, mgc);
240
317
  if (DATA_P(object))
241
318
  DATA_PTR(object) = NULL;
242
319
  }
@@ -263,12 +340,13 @@ rb_mgc_close(VALUE object)
263
340
  VALUE
264
341
  rb_mgc_close_p(VALUE object)
265
342
  {
266
- magic_object_t *mo;
343
+ rb_mgc_object_t *mgc;
267
344
  magic_t cookie = NULL;
268
345
 
269
- MAGIC_OBJECT(mo);
270
- if (mo)
271
- cookie = mo->cookie;
346
+ MAGIC_OBJECT(object, mgc);
347
+
348
+ if (mgc)
349
+ cookie = mgc->cookie;
272
350
 
273
351
  if (DATA_P(object) && cookie)
274
352
  return Qfalse;
@@ -295,14 +373,17 @@ rb_mgc_get_paths(VALUE object)
295
373
  MAGIC_CHECK_OPEN(object);
296
374
 
297
375
  value = rb_ivar_get(object, id_at_paths);
298
- if (!NIL_P(value) && !RARRAY_EMPTY_P(value) && !getenv("MAGIC"))
376
+ if (!NIL_P(value) && !RARRAY_EMPTY_P(value))
299
377
  return value;
300
378
 
301
- cstring = magic_getpath_wrapper();
302
- value = magic_split(CSTR2RVAL(cstring), CSTR2RVAL(":"));
303
- RB_GC_GUARD(value);
379
+ value = rb_funcall(rb_cMagic, rb_intern("default_paths"), 0);
380
+ if (getenv("MAGIC") || NIL_P(value)) {
381
+ cstring = magic_getpath_wrapper();
382
+ value = magic_split(CSTR2RVAL(cstring), CSTR2RVAL(":"));
383
+ RB_GC_GUARD(value);
384
+ }
304
385
 
305
- return value;
386
+ return magic_set_paths(object, value);
306
387
  }
307
388
 
308
389
  /*
@@ -313,28 +394,34 @@ VALUE
313
394
  rb_mgc_get_parameter(VALUE object, VALUE tag)
314
395
  {
315
396
  int local_errno;
316
- magic_object_t *mo;
317
- magic_arguments_t ma;
397
+ rb_mgc_object_t *mgc;
398
+ rb_mgc_arguments_t mga;
318
399
 
319
400
  MAGIC_CHECK_INTEGER_TYPE(tag);
401
+
320
402
  MAGIC_CHECK_OPEN(object);
321
- MAGIC_COOKIE(mo, ma.cookie);
403
+ MAGIC_OBJECT(object, mgc);
322
404
 
323
- ma.type.parameter.tag = NUM2INT(tag);
405
+ mga = (rb_mgc_arguments_t) {
406
+ .magic_object = mgc,
407
+ .parameter = {
408
+ .tag = NUM2INT(tag),
409
+ },
410
+ };
324
411
 
325
- MAGIC_SYNCHRONIZED(magic_get_parameter_internal, &ma);
412
+ MAGIC_SYNCHRONIZED(magic_get_parameter_internal, &mga);
326
413
  local_errno = errno;
327
414
 
328
- if (ma.status < 0) {
415
+ if (mga.status < 0) {
329
416
  if (local_errno == EINVAL)
330
417
  MAGIC_GENERIC_ERROR(rb_mgc_eParameterError,
331
418
  local_errno,
332
419
  E_PARAM_INVALID_TYPE);
333
420
 
334
- MAGIC_LIBRARY_ERROR(ma.cookie);
421
+ MAGIC_LIBRARY_ERROR(mgc);
335
422
  }
336
423
 
337
- return SIZET2NUM(ma.type.parameter.value);
424
+ return SIZET2NUM(mga.parameter.value);
338
425
  }
339
426
 
340
427
  /*
@@ -345,21 +432,27 @@ VALUE
345
432
  rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value)
346
433
  {
347
434
  int local_errno;
348
- magic_object_t *mo;
349
- magic_arguments_t ma;
435
+ rb_mgc_object_t *mgc;
436
+ rb_mgc_arguments_t mga;
350
437
 
351
438
  MAGIC_CHECK_INTEGER_TYPE(tag);
352
439
  MAGIC_CHECK_INTEGER_TYPE(value);
440
+
353
441
  MAGIC_CHECK_OPEN(object);
354
- MAGIC_COOKIE(mo, ma.cookie);
442
+ MAGIC_OBJECT(object, mgc);
355
443
 
356
- ma.type.parameter.tag = NUM2INT(tag);
357
- ma.type.parameter.value = NUM2SIZET(value);
444
+ mga = (rb_mgc_arguments_t) {
445
+ .magic_object = mgc,
446
+ .parameter = {
447
+ .tag = NUM2INT(tag),
448
+ .value = NUM2SIZET(value),
449
+ },
450
+ };
358
451
 
359
- MAGIC_SYNCHRONIZED(magic_set_parameter_internal, &ma);
452
+ MAGIC_SYNCHRONIZED(magic_set_parameter_internal, &mga);
360
453
  local_errno = errno;
361
454
 
362
- if (ma.status < 0) {
455
+ if (mga.status < 0) {
363
456
  switch (local_errno) {
364
457
  case EINVAL:
365
458
  MAGIC_GENERIC_ERROR(rb_mgc_eParameterError,
@@ -370,7 +463,8 @@ rb_mgc_set_parameter(VALUE object, VALUE tag, VALUE value)
370
463
  local_errno,
371
464
  E_PARAM_INVALID_VALUE);
372
465
  }
373
- MAGIC_LIBRARY_ERROR(ma.cookie);
466
+
467
+ MAGIC_LIBRARY_ERROR(mgc);
374
468
  }
375
469
 
376
470
  return Qnil;
@@ -393,19 +487,23 @@ VALUE
393
487
  rb_mgc_get_flags(VALUE object)
394
488
  {
395
489
  int local_errno;
396
- magic_object_t *mo;
397
- magic_arguments_t ma;
490
+ rb_mgc_object_t *mgc;
491
+ rb_mgc_arguments_t mga;
398
492
 
399
493
  MAGIC_CHECK_OPEN(object);
400
- MAGIC_COOKIE(mo, ma.cookie);
494
+ MAGIC_OBJECT(object, mgc);
495
+
496
+ mga = (rb_mgc_arguments_t) {
497
+ .magic_object = mgc,
498
+ };
401
499
 
402
- MAGIC_SYNCHRONIZED(magic_get_flags_internal, &ma);
500
+ MAGIC_SYNCHRONIZED(magic_get_flags_internal, &mga);
403
501
  local_errno = errno;
404
502
 
405
- if (ma.flags < 0 && local_errno == ENOSYS)
503
+ if (mga.status < 0 && local_errno == ENOSYS)
406
504
  return rb_ivar_get(object, id_at_flags);
407
505
 
408
- return INT2NUM(ma.flags);
506
+ return INT2NUM(mga.flags);
409
507
  }
410
508
 
411
509
  /*
@@ -422,19 +520,43 @@ VALUE
422
520
  rb_mgc_set_flags(VALUE object, VALUE value)
423
521
  {
424
522
  int local_errno;
425
- magic_object_t *mo;
426
- magic_arguments_t ma;
523
+ rb_mgc_object_t *mgc;
524
+ rb_mgc_arguments_t mga;
525
+ const char *klass = "Magic";
526
+ const char *flag = NULL;
427
527
 
428
528
  MAGIC_CHECK_INTEGER_TYPE(value);
529
+
429
530
  MAGIC_CHECK_OPEN(object);
430
- MAGIC_COOKIE(mo, ma.cookie);
531
+ MAGIC_OBJECT(object, mgc);
532
+
533
+ mga = (rb_mgc_arguments_t) {
534
+ .magic_object = mgc,
535
+ .flags = NUM2INT(value),
536
+ };
537
+
538
+ if (mga.flags < 0)
539
+ MAGIC_GENERIC_ERROR(rb_mgc_eFlagsError, EINVAL,
540
+ E_FLAG_INVALID_TYPE);
541
+
542
+ if (mga.flags & MAGIC_DEBUG)
543
+ flag = "DEBUG";
544
+ else if (mga.flags & MAGIC_CHECK)
545
+ flag = "CHECK";
546
+
547
+ if (flag) {
548
+ if (!NIL_P(object))
549
+ klass = rb_obj_classname(object);
431
550
 
432
- ma.flags = NUM2INT(value);
551
+ MAGIC_WARNING(0, "%s::%s flag is set; verbose information will "
552
+ "now be printed to the standard error output",
553
+ klass, flag);
554
+ }
433
555
 
434
- MAGIC_SYNCHRONIZED(magic_set_flags_internal, &ma);
556
+ MAGIC_SYNCHRONIZED(magic_set_flags_internal, &mga);
435
557
  local_errno = errno;
436
558
 
437
- if (ma.status < 0) {
559
+ if (mga.status < 0) {
438
560
  switch (local_errno) {
439
561
  case EINVAL:
440
562
  MAGIC_GENERIC_ERROR(rb_mgc_eFlagsError,
@@ -445,10 +567,11 @@ rb_mgc_set_flags(VALUE object, VALUE value)
445
567
  local_errno,
446
568
  E_FLAG_NOT_IMPLEMENTED);
447
569
  }
448
- MAGIC_LIBRARY_ERROR(ma.cookie);
570
+
571
+ MAGIC_LIBRARY_ERROR(mgc);
449
572
  }
450
573
 
451
- return rb_ivar_set(object, id_at_flags, INT2NUM(ma.flags));
574
+ return rb_ivar_set(object, id_at_flags, INT2NUM(mga.flags));
452
575
  }
453
576
 
454
577
  /*
@@ -464,8 +587,8 @@ rb_mgc_set_flags(VALUE object, VALUE value)
464
587
  VALUE
465
588
  rb_mgc_load(VALUE object, VALUE arguments)
466
589
  {
467
- magic_object_t *mo;
468
- magic_arguments_t ma;
590
+ rb_mgc_object_t *mgc;
591
+ rb_mgc_arguments_t mga;
469
592
  const char *klass = "Magic";
470
593
  VALUE value = Qundef;
471
594
 
@@ -473,40 +596,48 @@ rb_mgc_load(VALUE object, VALUE arguments)
473
596
  arguments = magic_flatten(arguments);
474
597
 
475
598
  MAGIC_CHECK_ARRAY_OF_STRINGS(arguments);
599
+
476
600
  MAGIC_CHECK_OPEN(object);
477
- MAGIC_COOKIE(mo, ma.cookie);
601
+ MAGIC_OBJECT(object, mgc);
478
602
 
479
603
  if (rb_mgc_do_not_auto_load) {
480
604
  if (!NIL_P(object))
481
605
  klass = rb_obj_classname(object);
482
606
 
483
607
  MAGIC_WARNING(2, "%s::do_not_auto_load is set; using %s#load "
484
- "will load Magic database from a file",
485
- klass, klass);
608
+ "will load Magic database from a file",
609
+ klass, klass);
486
610
  }
487
611
 
488
- ma.flags = magic_get_flags(object);
612
+ if (RARRAY_EMPTY_P(arguments))
613
+ arguments = rb_mgc_get_paths(object);
489
614
 
490
- if (!RARRAY_EMPTY_P(arguments)) {
491
- value = magic_join(arguments, CSTR2RVAL(":"));
492
- ma.type.file.path = RVAL2CSTR(value);
493
- }
494
- else
495
- ma.type.file.path = magic_getpath_wrapper();
615
+ value = magic_join(arguments, CSTR2RVAL(":"));
616
+ RB_GC_GUARD(value);
496
617
 
497
618
  magic_set_paths(object, RARRAY_EMPTY);
498
619
 
499
- MAGIC_SYNCHRONIZED(magic_load_internal, &ma);
500
- if (ma.status < 0) {
501
- mo->database_loaded = 0;
502
- MAGIC_LIBRARY_ERROR(ma.cookie);
620
+ mga = (rb_mgc_arguments_t) {
621
+ .magic_object = mgc,
622
+ .file = {
623
+ .path = RVAL2CSTR(value),
624
+ },
625
+ .flags = magic_get_flags(object),
626
+ };
627
+
628
+ MAGIC_SYNCHRONIZED(magic_load_internal, &mga);
629
+ if (mga.status < 0) {
630
+ mgc->database_loaded = 0;
631
+ MAGIC_LIBRARY_ERROR(mgc);
503
632
  }
504
- mo->database_loaded = 1;
505
633
 
506
- value = magic_split(CSTR2RVAL(ma.type.file.path), CSTR2RVAL(":"));
507
- magic_set_paths(object, value);
634
+ mgc->database_loaded = 1;
635
+
636
+ value = magic_split(CSTR2RVAL(mga.file.path), CSTR2RVAL(":"));
508
637
  RB_GC_GUARD(value);
509
638
 
639
+ magic_set_paths(object, value);
640
+
510
641
  return Qnil;
511
642
  }
512
643
 
@@ -522,8 +653,8 @@ rb_mgc_load_buffers(VALUE object, VALUE arguments)
522
653
  {
523
654
  size_t count;
524
655
  int local_errno;
525
- magic_object_t *mo;
526
- magic_arguments_t ma;
656
+ rb_mgc_object_t *mgc;
657
+ rb_mgc_arguments_t mga;
527
658
  void **pointers = NULL;
528
659
  size_t *sizes = NULL;
529
660
  VALUE value = Qundef;
@@ -538,8 +669,9 @@ rb_mgc_load_buffers(VALUE object, VALUE arguments)
538
669
 
539
670
  MAGIC_CHECK_ARRAY_EMPTY(arguments);
540
671
  MAGIC_CHECK_ARRAY_OF_STRINGS(arguments);
672
+
541
673
  MAGIC_CHECK_OPEN(object);
542
- MAGIC_COOKIE(mo, ma.cookie);
674
+ MAGIC_OBJECT(object, mgc);
543
675
 
544
676
  pointers = ALLOC_N(void *, count);
545
677
  if (!pointers) {
@@ -560,35 +692,41 @@ rb_mgc_load_buffers(VALUE object, VALUE arguments)
560
692
  sizes[i] = (size_t)RSTRING_LEN(value);
561
693
  }
562
694
 
563
- ma.flags = magic_get_flags(object);
564
- ma.type.buffers.count = count;
565
- ma.type.buffers.pointers = pointers;
566
- ma.type.buffers.sizes = sizes;
567
-
568
695
  magic_set_paths(object, RARRAY_EMPTY);
569
696
 
570
- MAGIC_SYNCHRONIZED(magic_load_buffers_internal, &ma);
571
- if (ma.status < 0) {
697
+ mga = (rb_mgc_arguments_t) {
698
+ .magic_object = mgc,
699
+ .buffers = {
700
+ .count = count,
701
+ .pointers = pointers,
702
+ .sizes = sizes,
703
+ },
704
+ .flags = magic_get_flags(object),
705
+ };
706
+
707
+ MAGIC_SYNCHRONIZED(magic_load_buffers_internal, &mga);
708
+ if (mga.status < 0) {
572
709
  local_errno = errno;
573
710
  ruby_xfree(pointers);
574
711
  ruby_xfree(sizes);
575
712
  goto error;
576
713
  }
577
- mo->database_loaded = 1;
714
+
715
+ mgc->database_loaded = 1;
578
716
 
579
717
  ruby_xfree(pointers);
580
718
  ruby_xfree(sizes);
581
719
 
582
720
  return Qnil;
583
721
  error:
584
- mo->database_loaded = 0;
722
+ mgc->database_loaded = 0;
585
723
 
586
724
  if (local_errno == ENOMEM)
587
725
  MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
588
726
  local_errno,
589
727
  E_NOT_ENOUGH_MEMORY);
590
728
 
591
- MAGIC_LIBRARY_ERROR(ma.cookie);
729
+ MAGIC_LIBRARY_ERROR(mgc);
592
730
  }
593
731
 
594
732
  /*
@@ -615,12 +753,12 @@ error:
615
753
  VALUE
616
754
  rb_mgc_load_p(VALUE object)
617
755
  {
618
- magic_object_t *mo;
756
+ rb_mgc_object_t *mgc;
619
757
 
620
758
  MAGIC_CHECK_OPEN(object);
621
- MAGIC_OBJECT(mo);
759
+ MAGIC_OBJECT(object, mgc);
622
760
 
623
- return CBOOL2RVAL(mo->database_loaded);
761
+ return CBOOL2RVAL(mgc->database_loaded);
624
762
  }
625
763
 
626
764
  /*
@@ -633,19 +771,25 @@ rb_mgc_load_p(VALUE object)
633
771
  VALUE
634
772
  rb_mgc_compile(VALUE object, VALUE value)
635
773
  {
636
- magic_object_t *mo;
637
- magic_arguments_t ma;
774
+ rb_mgc_object_t *mgc;
775
+ rb_mgc_arguments_t mga;
638
776
 
639
777
  MAGIC_CHECK_STRING_TYPE(value);
778
+
640
779
  MAGIC_CHECK_OPEN(object);
641
- MAGIC_COOKIE(mo, ma.cookie);
780
+ MAGIC_OBJECT(object, mgc);
642
781
 
643
- ma.flags = magic_get_flags(object);
644
- ma.type.file.path = RVAL2CSTR(value);
782
+ mga = (rb_mgc_arguments_t) {
783
+ .magic_object = mgc,
784
+ .file = {
785
+ .path = RVAL2CSTR(value),
786
+ },
787
+ .flags = magic_get_flags(object),
788
+ };
645
789
 
646
- MAGIC_SYNCHRONIZED(magic_compile_internal, &ma);
647
- if (ma.status < 0)
648
- MAGIC_LIBRARY_ERROR(ma.cookie);
790
+ MAGIC_SYNCHRONIZED(magic_compile_internal, &mga);
791
+ if (mga.status < 0)
792
+ MAGIC_LIBRARY_ERROR(mgc);
649
793
 
650
794
  return Qnil;
651
795
  }
@@ -660,18 +804,25 @@ rb_mgc_compile(VALUE object, VALUE value)
660
804
  VALUE
661
805
  rb_mgc_check(VALUE object, VALUE value)
662
806
  {
663
- magic_object_t *mo;
664
- magic_arguments_t ma;
807
+ rb_mgc_object_t *mgc;
808
+ rb_mgc_arguments_t mga;
665
809
 
666
810
  MAGIC_CHECK_STRING_TYPE(value);
811
+
667
812
  MAGIC_CHECK_OPEN(object);
668
- MAGIC_COOKIE(mo, ma.cookie);
813
+ MAGIC_OBJECT(object, mgc);
814
+
815
+ mga = (rb_mgc_arguments_t) {
816
+ .magic_object = mgc,
817
+ .file = {
818
+ .path = RVAL2CSTR(value),
819
+ },
820
+ .flags = magic_get_flags(object),
821
+ };
669
822
 
670
- ma.flags = magic_get_flags(object);
671
- ma.type.file.path = RVAL2CSTR(value);
823
+ MAGIC_SYNCHRONIZED(magic_check_internal, &mga);
672
824
 
673
- MAGIC_SYNCHRONIZED(magic_check_internal, &ma);
674
- return ma.status < 0 ? Qfalse : Qtrue;
825
+ return mga.status < 0 ? Qfalse : Qtrue;
675
826
  }
676
827
 
677
828
  /*
@@ -684,8 +835,8 @@ rb_mgc_check(VALUE object, VALUE value)
684
835
  VALUE
685
836
  rb_mgc_file(VALUE object, VALUE value)
686
837
  {
687
- magic_object_t *mo;
688
- magic_arguments_t ma;
838
+ rb_mgc_object_t *mgc;
839
+ rb_mgc_arguments_t mga;
689
840
  const char *empty = "(null)";
690
841
 
691
842
  UNUSED(empty);
@@ -695,7 +846,7 @@ rb_mgc_file(VALUE object, VALUE value)
695
846
 
696
847
  MAGIC_CHECK_OPEN(object);
697
848
  MAGIC_CHECK_LOADED(object);
698
- MAGIC_COOKIE(mo, ma.cookie);
849
+ MAGIC_OBJECT(object, mgc);
699
850
 
700
851
  if (rb_respond_to(value, rb_intern("to_io")))
701
852
  return rb_mgc_descriptor(object, value);
@@ -704,12 +855,16 @@ rb_mgc_file(VALUE object, VALUE value)
704
855
  if (NIL_P(value))
705
856
  goto error;
706
857
 
707
- ma.stop_on_errors = mo->stop_on_errors;
708
- ma.flags = magic_get_flags(object);
709
- ma.type.file.path = RVAL2CSTR(value);
858
+ mga = (rb_mgc_arguments_t) {
859
+ .magic_object = mgc,
860
+ .file = {
861
+ .path = RVAL2CSTR(value),
862
+ },
863
+ .flags = magic_get_flags(object),
864
+ };
710
865
 
711
- MAGIC_SYNCHRONIZED(magic_file_internal, &ma);
712
- if (ma.status < 0 && !ma.result) {
866
+ MAGIC_SYNCHRONIZED(magic_file_internal, &mga);
867
+ if (mga.status < 0 && !mga.result) {
713
868
  /*
714
869
  * Handle the case when the "ERROR" flag is set regardless of the
715
870
  * current version of the underlying Magic library.
@@ -723,15 +878,15 @@ rb_mgc_file(VALUE object, VALUE value)
723
878
  * This is an attempt to mitigate the problem and correct it to achieve
724
879
  * the desired behavior as per the standards.
725
880
  */
726
- if (mo->stop_on_errors || (ma.flags & MAGIC_ERROR))
727
- MAGIC_LIBRARY_ERROR(ma.cookie);
881
+ if (mgc->stop_on_errors || (mga.flags & MAGIC_ERROR))
882
+ MAGIC_LIBRARY_ERROR(mgc);
728
883
 
729
- ma.result = magic_error_wrapper(ma.cookie);
884
+ mga.result = magic_error_wrapper(mgc->cookie);
730
885
  }
731
- if (!ma.result)
886
+ if (!mga.result)
732
887
  MAGIC_GENERIC_ERROR(rb_mgc_eMagicError, EINVAL, E_UNKNOWN);
733
888
 
734
- assert(ma.result != NULL && \
889
+ assert(mga.result != NULL &&
735
890
  "Must be a valid pointer to `const char' type");
736
891
 
737
892
  /*
@@ -740,10 +895,10 @@ rb_mgc_file(VALUE object, VALUE value)
740
895
  * string instead. Often this would indicate that an older version of the
741
896
  * Magic library is in use.
742
897
  */
743
- assert(strncmp(ma.result, empty, strlen(empty)) != 0 && \
898
+ assert(strncmp(mga.result, empty, strlen(empty)) != 0 &&
744
899
  "Empty or invalid result");
745
900
 
746
- return magic_return(&ma);
901
+ return magic_return(&mga);
747
902
  error:
748
903
  MAGIC_ARGUMENT_TYPE_ERROR(value, "String or IO-like object");
749
904
  }
@@ -757,28 +912,34 @@ error:
757
912
  VALUE
758
913
  rb_mgc_buffer(VALUE object, VALUE value)
759
914
  {
760
- magic_object_t *mo;
761
- magic_arguments_t ma;
915
+ rb_mgc_object_t *mgc;
916
+ rb_mgc_arguments_t mga;
762
917
 
763
918
  MAGIC_CHECK_STRING_TYPE(value);
919
+
764
920
  MAGIC_CHECK_OPEN(object);
765
921
  MAGIC_CHECK_LOADED(object);
766
- MAGIC_COOKIE(mo, ma.cookie);
922
+ MAGIC_OBJECT(object, mgc);
767
923
 
768
924
  StringValue(value);
769
925
 
770
- ma.flags = magic_get_flags(object);
771
- ma.type.buffers.pointers = (void **)RSTRING_PTR(value);
772
- ma.type.buffers.sizes = (size_t *)RSTRING_LEN(value);
926
+ mga = (rb_mgc_arguments_t) {
927
+ .magic_object = mgc,
928
+ .buffers = {
929
+ .pointers = (void **)RSTRING_PTR(value),
930
+ .sizes = (size_t *)RSTRING_LEN(value),
931
+ },
932
+ .flags = magic_get_flags(object),
933
+ };
773
934
 
774
- MAGIC_SYNCHRONIZED(magic_buffer_internal, &ma);
775
- if (ma.status < 0)
776
- MAGIC_LIBRARY_ERROR(ma.cookie);
935
+ MAGIC_SYNCHRONIZED(magic_buffer_internal, &mga);
936
+ if (mga.status < 0)
937
+ MAGIC_LIBRARY_ERROR(mgc);
777
938
 
778
- assert(ma.result != NULL && \
939
+ assert(mga.result != NULL &&
779
940
  "Must be a valid pointer to `const char' type");
780
941
 
781
- return magic_return(&ma);
942
+ return magic_return(&mga);
782
943
  }
783
944
 
784
945
  /*
@@ -792,34 +953,40 @@ VALUE
792
953
  rb_mgc_descriptor(VALUE object, VALUE value)
793
954
  {
794
955
  int local_errno;
795
- magic_object_t *mo;
796
- magic_arguments_t ma;
956
+ rb_mgc_object_t *mgc;
957
+ rb_mgc_arguments_t mga;
797
958
 
798
959
  if (rb_respond_to(value, rb_intern("to_io")))
799
960
  value = INT2NUM(magic_fileno(value));
800
961
 
801
962
  MAGIC_CHECK_INTEGER_TYPE(value);
963
+
802
964
  MAGIC_CHECK_OPEN(object);
803
965
  MAGIC_CHECK_LOADED(object);
804
- MAGIC_COOKIE(mo, ma.cookie);
966
+ MAGIC_OBJECT(object, mgc);
805
967
 
806
- ma.flags = magic_get_flags(object);
807
- ma.type.file.fd = NUM2INT(value);
968
+ mga = (rb_mgc_arguments_t) {
969
+ .magic_object = mgc,
970
+ .file = {
971
+ .fd = NUM2INT(value),
972
+ },
973
+ .flags = magic_get_flags(object),
974
+ };
808
975
 
809
- MAGIC_SYNCHRONIZED(magic_descriptor_internal, &ma);
976
+ MAGIC_SYNCHRONIZED(magic_descriptor_internal, &mga);
810
977
  local_errno = errno;
811
978
 
812
- if (ma.status < 0) {
979
+ if (mga.status < 0) {
813
980
  if (local_errno == EBADF)
814
981
  rb_raise(rb_eIOError, "Bad file descriptor");
815
982
 
816
- MAGIC_LIBRARY_ERROR(ma.cookie);
983
+ MAGIC_LIBRARY_ERROR(mgc);
817
984
  }
818
985
 
819
- assert(ma.result != NULL && \
986
+ assert(mga.result != NULL &&
820
987
  "Must be a valid pointer to `const char' type");
821
988
 
822
- return magic_return(&ma);
989
+ return magic_return(&mga);
823
990
  }
824
991
 
825
992
  /*
@@ -841,59 +1008,69 @@ rb_mgc_version(RB_UNUSED_VAR(VALUE object))
841
1008
  static inline void*
842
1009
  nogvl_magic_load(void *data)
843
1010
  {
844
- magic_arguments_t *ma = data;
1011
+ rb_mgc_arguments_t *mga = data;
1012
+ magic_t cookie = mga->magic_object->cookie;
1013
+
1014
+ mga->status = magic_load_wrapper(cookie,
1015
+ mga->file.path,
1016
+ mga->flags);
845
1017
 
846
- ma->status = magic_load_wrapper(ma->cookie,
847
- ma->type.file.path,
848
- ma->flags);
849
1018
  return NULL;
850
1019
  }
851
1020
 
852
1021
  static inline void*
853
1022
  nogvl_magic_compile(void *data)
854
1023
  {
855
- magic_arguments_t *ma = data;
1024
+ rb_mgc_arguments_t *mga = data;
1025
+ magic_t cookie = mga->magic_object->cookie;
1026
+
1027
+ mga->status = magic_compile_wrapper(cookie,
1028
+ mga->file.path,
1029
+ mga->flags);
856
1030
 
857
- ma->status = magic_compile_wrapper(ma->cookie,
858
- ma->type.file.path,
859
- ma->flags);
860
1031
  return NULL;
861
1032
  }
862
1033
 
863
1034
  static inline void*
864
1035
  nogvl_magic_check(void *data)
865
1036
  {
866
- magic_arguments_t *ma = data;
1037
+ rb_mgc_arguments_t *mga = data;
1038
+ magic_t cookie = mga->magic_object->cookie;
1039
+
1040
+ mga->status = magic_check_wrapper(cookie,
1041
+ mga->file.path,
1042
+ mga->flags);
867
1043
 
868
- ma->status = magic_check_wrapper(ma->cookie,
869
- ma->type.file.path,
870
- ma->flags);
871
1044
  return NULL;
872
1045
  }
873
1046
 
874
1047
  static inline void*
875
1048
  nogvl_magic_file(void *data)
876
1049
  {
877
- magic_arguments_t *ma = data;
1050
+ rb_mgc_arguments_t *mga = data;
1051
+ magic_t cookie = mga->magic_object->cookie;
878
1052
 
879
- ma->result = magic_file_wrapper(ma->cookie,
880
- ma->type.file.path,
881
- ma->flags);
1053
+ mga->result = magic_file_wrapper(cookie,
1054
+ mga->file.path,
1055
+ mga->flags);
1056
+
1057
+ mga->status = !mga->result ? -1 : 0;
882
1058
 
883
- ma->status = !ma->result ? -1 : 0;
884
1059
  return NULL;
885
1060
  }
886
1061
 
887
1062
  static inline void*
888
1063
  nogvl_magic_descriptor(void *data)
889
1064
  {
890
- magic_arguments_t *ma = data;
1065
+ rb_mgc_arguments_t *mga = data;
1066
+ magic_t cookie = mga->magic_object->cookie;
1067
+
1068
+ mga->result = magic_descriptor_wrapper(cookie,
1069
+ mga->file.fd,
1070
+ mga->flags);
891
1071
 
892
- ma->result = magic_descriptor_wrapper(ma->cookie,
893
- ma->type.file.fd,
894
- ma->flags);
1072
+ mga->status = !mga->result ? -1 : 0;
895
1073
 
896
- ma->status = !ma->result ? -1 : 0;
897
1074
  return NULL;
898
1075
  }
899
1076
 
@@ -901,12 +1078,15 @@ static inline VALUE
901
1078
  magic_get_parameter_internal(void *data)
902
1079
  {
903
1080
  size_t value;
904
- magic_arguments_t *ma = data;
1081
+ rb_mgc_arguments_t *mga = data;
1082
+ magic_t cookie = mga->magic_object->cookie;
1083
+
1084
+ mga->status = magic_getparam_wrapper(cookie,
1085
+ mga->parameter.tag,
1086
+ &value);
1087
+
1088
+ mga->parameter.value = value;
905
1089
 
906
- ma->status = magic_getparam_wrapper(ma->cookie,
907
- ma->type.parameter.tag,
908
- &value);
909
- ma->type.parameter.value = value;
910
1090
  return (VALUE)NULL;
911
1091
  }
912
1092
 
@@ -914,30 +1094,44 @@ static inline VALUE
914
1094
  magic_set_parameter_internal(void *data)
915
1095
  {
916
1096
  size_t value;
917
- magic_arguments_t *ma = data;
1097
+ rb_mgc_arguments_t *mga = data;
1098
+ magic_t cookie = mga->magic_object->cookie;
1099
+
1100
+ value = mga->parameter.value;
1101
+
1102
+ mga->status = magic_setparam_wrapper(cookie,
1103
+ mga->parameter.tag,
1104
+ &value);
918
1105
 
919
- value = ma->type.parameter.value;
920
- ma->status = magic_setparam_wrapper(ma->cookie,
921
- ma->type.parameter.tag,
922
- &value);
923
1106
  return (VALUE)NULL;
924
1107
  }
925
1108
 
926
1109
  static inline VALUE
927
1110
  magic_get_flags_internal(void *data)
928
1111
  {
929
- magic_arguments_t *ma = data;
1112
+ int flags;
1113
+ rb_mgc_arguments_t *mga = data;
1114
+ magic_t cookie = mga->magic_object->cookie;
1115
+
1116
+ mga->status = 0;
1117
+
1118
+ flags = magic_getflags_wrapper(cookie);
1119
+ if (flags < 0)
1120
+ mga->status = -1;
1121
+ else
1122
+ mga->flags = flags;
930
1123
 
931
- ma->flags = magic_getflags_wrapper(ma->cookie);
932
1124
  return (VALUE)NULL;
933
1125
  }
934
1126
 
935
1127
  static inline VALUE
936
1128
  magic_set_flags_internal(void *data)
937
1129
  {
938
- magic_arguments_t *ma = data;
1130
+ rb_mgc_arguments_t *mga = data;
1131
+ magic_t cookie = mga->magic_object->cookie;
1132
+
1133
+ mga->status = magic_setflags_wrapper(cookie, mga->flags);
939
1134
 
940
- ma->status = magic_setflags_wrapper(ma->cookie, ma->flags);
941
1135
  return (VALUE)NULL;
942
1136
  }
943
1137
 
@@ -945,18 +1139,21 @@ static inline VALUE
945
1139
  magic_close_internal(void *data)
946
1140
  {
947
1141
  magic_library_close(data);
1142
+
948
1143
  return Qnil;
949
1144
  }
950
1145
 
951
1146
  static inline VALUE
952
1147
  magic_load_internal(void *data)
953
1148
  {
954
- magic_arguments_t *ma = data;
955
- int old_flags = ma->flags;
1149
+ rb_mgc_arguments_t *mga = data;
1150
+ magic_t cookie = mga->magic_object->cookie;
1151
+ int old_flags = mga->flags;
956
1152
 
957
- NOGVL(nogvl_magic_load, ma);
958
- if (MAGIC_STATUS_CHECK(ma->status < 0))
959
- magic_setflags_wrapper(ma->cookie, old_flags);
1153
+ NOGVL(nogvl_magic_load, mga);
1154
+
1155
+ if (MAGIC_STATUS_CHECK(mga->status < 0))
1156
+ magic_setflags_wrapper(cookie, old_flags);
960
1157
 
961
1158
  return (VALUE)NULL;
962
1159
  }
@@ -964,25 +1161,29 @@ magic_load_internal(void *data)
964
1161
  static inline VALUE
965
1162
  magic_load_buffers_internal(void *data)
966
1163
  {
967
- magic_arguments_t *ma = data;
1164
+ rb_mgc_arguments_t *mga = data;
1165
+ magic_t cookie = mga->magic_object->cookie;
1166
+
1167
+ mga->status = magic_load_buffers_wrapper(cookie,
1168
+ mga->buffers.pointers,
1169
+ mga->buffers.sizes,
1170
+ mga->buffers.count,
1171
+ mga->flags);
968
1172
 
969
- ma->status = magic_load_buffers_wrapper(ma->cookie,
970
- ma->type.buffers.pointers,
971
- ma->type.buffers.sizes,
972
- ma->type.buffers.count,
973
- ma->flags);
974
1173
  return (VALUE)NULL;
975
1174
  }
976
1175
 
977
1176
  static inline VALUE
978
1177
  magic_compile_internal(void *data)
979
1178
  {
980
- magic_arguments_t *ma = data;
981
- int old_flags = ma->flags;
1179
+ rb_mgc_arguments_t *mga = data;
1180
+ magic_t cookie = mga->magic_object->cookie;
1181
+ int old_flags = mga->flags;
1182
+
1183
+ NOGVL(nogvl_magic_compile, mga);
982
1184
 
983
- NOGVL(nogvl_magic_compile, ma);
984
- if (MAGIC_STATUS_CHECK(ma->status < 0))
985
- magic_setflags_wrapper(ma->cookie, old_flags);
1185
+ if (MAGIC_STATUS_CHECK(mga->status < 0))
1186
+ magic_setflags_wrapper(cookie, old_flags);
986
1187
 
987
1188
  return (VALUE)NULL;
988
1189
  }
@@ -990,12 +1191,14 @@ magic_compile_internal(void *data)
990
1191
  static inline VALUE
991
1192
  magic_check_internal(void *data)
992
1193
  {
993
- magic_arguments_t *ma = data;
994
- int old_flags = ma->flags;
1194
+ rb_mgc_arguments_t *mga = data;
1195
+ magic_t cookie = mga->magic_object->cookie;
1196
+ int old_flags = mga->flags;
995
1197
 
996
- NOGVL(nogvl_magic_check, ma);
997
- if (MAGIC_STATUS_CHECK(ma->status < 0))
998
- magic_setflags_wrapper(ma->cookie, old_flags);
1198
+ NOGVL(nogvl_magic_check, mga);
1199
+
1200
+ if (MAGIC_STATUS_CHECK(mga->status < 0))
1201
+ magic_setflags_wrapper(cookie, old_flags);
999
1202
 
1000
1203
  return (VALUE)NULL;
1001
1204
  }
@@ -1003,23 +1206,26 @@ magic_check_internal(void *data)
1003
1206
  static VALUE
1004
1207
  magic_file_internal(void *data)
1005
1208
  {
1006
- magic_arguments_t *ma = data;
1007
- int old_flags = ma->flags;
1008
- int restore_flags;
1009
1209
  int local_errno;
1210
+ int restore_flags = 0;
1211
+ rb_mgc_arguments_t *mga = data;
1212
+ rb_mgc_object_t *mgc = mga->magic_object;
1213
+ magic_t cookie = mgc->cookie;
1214
+ int old_flags = mga->flags;
1010
1215
 
1011
- if (ma->stop_on_errors)
1012
- ma->flags |= MAGIC_ERROR;
1216
+ if (mgc->stop_on_errors)
1217
+ mga->flags |= MAGIC_ERROR;
1013
1218
 
1014
- if (ma->flags & MAGIC_CONTINUE)
1015
- ma->flags |= MAGIC_RAW;
1219
+ if (mga->flags & MAGIC_CONTINUE)
1220
+ mga->flags |= MAGIC_RAW;
1016
1221
 
1017
- restore_flags = old_flags != ma->flags;
1222
+ if (old_flags != mga->flags)
1223
+ restore_flags = 1;
1018
1224
 
1019
1225
  if (restore_flags)
1020
- magic_setflags_wrapper(ma->cookie, ma->flags);
1226
+ magic_setflags_wrapper(cookie, mga->flags);
1021
1227
 
1022
- NOGVL(nogvl_magic_file, ma);
1228
+ NOGVL(nogvl_magic_file, mga);
1023
1229
  local_errno = errno;
1024
1230
  /*
1025
1231
  * The Magic library often does not correctly report errors,
@@ -1028,11 +1234,11 @@ magic_file_internal(void *data)
1028
1234
  * Magic library itself, and if that does not work, then from
1029
1235
  * the saved errno value.
1030
1236
  */
1031
- if (magic_errno_wrapper(ma->cookie) || local_errno)
1032
- ma->status = -1;
1237
+ if (magic_errno_wrapper(cookie) || local_errno)
1238
+ mga->status = -1;
1033
1239
 
1034
1240
  if (restore_flags)
1035
- magic_setflags_wrapper(ma->cookie, old_flags);
1241
+ magic_setflags_wrapper(cookie, old_flags);
1036
1242
 
1037
1243
  return (VALUE)NULL;
1038
1244
  }
@@ -1040,27 +1246,29 @@ magic_file_internal(void *data)
1040
1246
  static VALUE
1041
1247
  magic_buffer_internal(void *data)
1042
1248
  {
1043
- magic_arguments_t *ma = data;
1044
- int old_flags = ma->flags;
1045
- int restore_flags;
1249
+ int restore_flags = 0;
1250
+ rb_mgc_arguments_t *mga = data;
1251
+ magic_t cookie = mga->magic_object->cookie;
1252
+ int old_flags = mga->flags;
1046
1253
 
1047
- if (ma->flags & MAGIC_CONTINUE)
1048
- ma->flags |= MAGIC_RAW;
1254
+ if (mga->flags & MAGIC_CONTINUE)
1255
+ mga->flags |= MAGIC_RAW;
1049
1256
 
1050
- restore_flags = old_flags != ma->flags;
1257
+ if (old_flags != mga->flags)
1258
+ restore_flags = 1;
1051
1259
 
1052
1260
  if (restore_flags)
1053
- magic_setflags_wrapper(ma->cookie, ma->flags);
1261
+ magic_setflags_wrapper(cookie, mga->flags);
1054
1262
 
1055
- ma->result = magic_buffer_wrapper(ma->cookie,
1056
- (const void *)ma->type.buffers.pointers,
1057
- (size_t)ma->type.buffers.sizes,
1058
- ma->flags);
1263
+ mga->result = magic_buffer_wrapper(cookie,
1264
+ (const void *)mga->buffers.pointers,
1265
+ (size_t)mga->buffers.sizes,
1266
+ mga->flags);
1059
1267
 
1060
- ma->status = !ma->result ? -1 : 0;
1268
+ mga->status = !mga->result ? -1 : 0;
1061
1269
 
1062
1270
  if (restore_flags)
1063
- magic_setflags_wrapper(ma->cookie, old_flags);
1271
+ magic_setflags_wrapper(cookie, old_flags);
1064
1272
 
1065
1273
  return (VALUE)NULL;
1066
1274
  }
@@ -1068,22 +1276,24 @@ magic_buffer_internal(void *data)
1068
1276
  static VALUE
1069
1277
  magic_descriptor_internal(void *data)
1070
1278
  {
1071
- magic_arguments_t *ma = data;
1072
- int old_flags = ma->flags;
1073
- int restore_flags;
1279
+ int restore_flags = 0;
1280
+ rb_mgc_arguments_t *mga = data;
1281
+ magic_t cookie = mga->magic_object->cookie;
1282
+ int old_flags = mga->flags;
1074
1283
 
1075
- if (ma->flags & MAGIC_CONTINUE)
1076
- ma->flags |= MAGIC_RAW;
1284
+ if (mga->flags & MAGIC_CONTINUE)
1285
+ mga->flags |= MAGIC_RAW;
1077
1286
 
1078
- restore_flags = old_flags != ma->flags;
1287
+ if (old_flags != mga->flags)
1288
+ restore_flags = 1;
1079
1289
 
1080
1290
  if (restore_flags)
1081
- magic_setflags_wrapper(ma->cookie, ma->flags);
1291
+ magic_setflags_wrapper(cookie, mga->flags);
1082
1292
 
1083
- NOGVL(nogvl_magic_descriptor, ma);
1293
+ NOGVL(nogvl_magic_descriptor, mga);
1084
1294
 
1085
1295
  if (restore_flags)
1086
- magic_setflags_wrapper(ma->cookie, old_flags);
1296
+ magic_setflags_wrapper(cookie, old_flags);
1087
1297
 
1088
1298
  return (VALUE)NULL;
1089
1299
  }
@@ -1105,129 +1315,129 @@ magic_library_open(void)
1105
1315
  static inline void
1106
1316
  magic_library_close(void *data)
1107
1317
  {
1108
- magic_object_t *mo = data;
1318
+ rb_mgc_object_t *mgc = data;
1109
1319
 
1110
- assert(mo != NULL && \
1111
- "Must be a valid pointer to `magic_object_t' type");
1320
+ assert(mgc != NULL &&
1321
+ "Must be a valid pointer to `rb_mgc_object_t' type");
1112
1322
 
1113
- if (mo->cookie)
1114
- magic_close_wrapper(mo->cookie);
1323
+ if (mgc->cookie)
1324
+ magic_close_wrapper(mgc->cookie);
1115
1325
 
1116
- mo->cookie = NULL;
1326
+ mgc->cookie = NULL;
1117
1327
  }
1118
1328
 
1119
1329
  static VALUE
1120
1330
  magic_allocate(VALUE klass)
1121
1331
  {
1122
1332
  int local_errno;
1123
- magic_object_t *mo;
1333
+ rb_mgc_object_t *mgc;
1124
1334
 
1125
- mo = (magic_object_t *)ruby_xmalloc(sizeof(magic_object_t));
1335
+ mgc = RB_ALLOC(rb_mgc_object_t);
1126
1336
  local_errno = ENOMEM;
1127
1337
 
1128
- if (!mo) {
1338
+ if (!mgc) {
1129
1339
  errno = local_errno;
1130
1340
  MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
1131
1341
  local_errno,
1132
1342
  E_NOT_ENOUGH_MEMORY);
1133
1343
  }
1134
1344
 
1135
- mo->cookie = NULL;
1136
- mo->mutex = Qundef;
1137
- mo->database_loaded = 0;
1138
- mo->stop_on_errors = 0;
1345
+ mgc->cookie = NULL;
1346
+ mgc->mutex = Qundef;
1347
+ mgc->database_loaded = 0;
1348
+ mgc->stop_on_errors = 0;
1139
1349
 
1140
- mo->cookie = magic_library_open();
1350
+ mgc->cookie = magic_library_open();
1141
1351
  local_errno = errno;
1142
1352
 
1143
- if (!mo->cookie) {
1144
- ruby_xfree(mo);
1145
- mo = NULL;
1353
+ if (!mgc->cookie) {
1354
+ ruby_xfree(mgc);
1355
+ mgc = NULL;
1146
1356
  errno = local_errno;
1147
1357
  MAGIC_GENERIC_ERROR(rb_mgc_eLibraryError,
1148
1358
  local_errno,
1149
1359
  E_MAGIC_LIBRARY_INITIALIZE);
1150
1360
  }
1151
1361
 
1152
- return TypedData_Wrap_Struct(klass, &rb_magic_type, mo);
1362
+ return TypedData_Wrap_Struct(klass, &rb_mgc_type, mgc);
1153
1363
  }
1154
1364
 
1155
1365
  static inline void
1156
1366
  magic_mark(void *data)
1157
1367
  {
1158
- magic_object_t *mo = data;
1368
+ rb_mgc_object_t *mgc = data;
1159
1369
 
1160
- assert(mo != NULL && \
1161
- "Must be a valid pointer to `magic_object_t' type");
1370
+ assert(mgc != NULL &&
1371
+ "Must be a valid pointer to `rb_mgc_object_t' type");
1162
1372
 
1163
- MAGIC_GC_MARK(mo->mutex);
1373
+ MAGIC_GC_MARK(mgc->mutex);
1164
1374
  }
1165
1375
 
1166
1376
  static inline void
1167
1377
  magic_free(void *data)
1168
1378
  {
1169
- magic_object_t *mo = data;
1379
+ rb_mgc_object_t *mgc = data;
1170
1380
 
1171
- assert(mo != NULL && \
1172
- "Must be a valid pointer to `magic_object_t' type");
1381
+ assert(mgc != NULL &&
1382
+ "Must be a valid pointer to `rb_mgc_object_t' type");
1173
1383
 
1174
- if (mo->cookie)
1384
+ if (mgc->cookie)
1175
1385
  magic_library_close(data);
1176
1386
 
1177
- mo->cookie = NULL;
1178
- mo->mutex = Qundef;
1387
+ mgc->cookie = NULL;
1388
+ mgc->mutex = Qundef;
1179
1389
 
1180
- ruby_xfree(mo);
1390
+ ruby_xfree(mgc);
1181
1391
  }
1182
1392
 
1183
1393
  static inline size_t
1184
1394
  magic_size(const void *data)
1185
1395
  {
1186
- const magic_object_t *mo = data;
1396
+ const rb_mgc_object_t *mgc = data;
1187
1397
 
1188
- assert(mo != NULL && \
1189
- "Must be a valid pointer to `magic_object_t' type");
1398
+ assert(mgc != NULL &&
1399
+ "Must be a valid pointer to `rb_mgc_object_t' type");
1190
1400
 
1191
- return sizeof(*mo);
1401
+ return sizeof(*mgc);
1192
1402
  }
1193
1403
 
1194
1404
  #if defined(HAVE_RUBY_GC_COMPACT)
1195
1405
  static inline void
1196
1406
  magic_compact(void *data)
1197
1407
  {
1198
- magic_object_t *mo = data;
1408
+ rb_mgc_object_t *mgc = data;
1199
1409
 
1200
- assert(mo != NULL && \
1201
- "Must be a valid pointer to `magic_object_t' type");
1410
+ assert(mgc != NULL &&
1411
+ "Must be a valid pointer to `rb_mgc_object_t' type");
1202
1412
 
1203
- mo->mutex = rb_gc_location(mo->mutex);
1413
+ mgc->mutex = rb_gc_location(mgc->mutex);
1204
1414
  }
1205
1415
  #endif /* HAVE_RUBY_GC_COMPACT */
1206
1416
 
1207
1417
  static inline VALUE
1208
1418
  magic_exception_wrapper(VALUE value)
1209
1419
  {
1210
- magic_exception_t *e = (struct magic_exception *)value;
1420
+ rb_mgc_error_t *mge = (rb_mgc_error_t *)value;
1211
1421
 
1212
- return rb_exc_new2(e->klass, e->magic_error);
1422
+ return rb_exc_new2(mge->klass, mge->magic_error);
1213
1423
  }
1214
1424
 
1215
1425
  static VALUE
1216
1426
  magic_exception(void *data)
1217
1427
  {
1218
- magic_exception_t *e = data;
1219
1428
  int exception = 0;
1429
+ rb_mgc_error_t *mge = data;
1220
1430
  VALUE object = Qundef;
1221
1431
 
1222
- assert(e != NULL && \
1223
- "Must be a valid pointer to `magic_exception_t' type");
1432
+ assert(mge != NULL &&
1433
+ "Must be a valid pointer to `rb_mgc_error_t' type");
1224
1434
 
1225
- object = rb_protect(magic_exception_wrapper, (VALUE)e, &exception);
1435
+ object = rb_protect(magic_exception_wrapper, (VALUE)mge, &exception);
1226
1436
 
1227
1437
  if (exception)
1228
1438
  rb_jump_tag(exception);
1229
1439
 
1230
- rb_iv_set(object, "@errno", INT2NUM(e->magic_errno));
1440
+ rb_iv_set(object, "@errno", INT2NUM(mge->magic_errno));
1231
1441
  RB_GC_GUARD(object);
1232
1442
 
1233
1443
  return object;
@@ -1236,51 +1446,56 @@ magic_exception(void *data)
1236
1446
  static inline VALUE
1237
1447
  magic_generic_error(VALUE klass, int magic_errno, const char *magic_error)
1238
1448
  {
1239
- magic_exception_t e;
1449
+ rb_mgc_error_t mge;
1240
1450
 
1241
- e.magic_errno = magic_errno;
1242
- e.magic_error = magic_error;
1243
- e.klass = klass;
1451
+ mge = (rb_mgc_error_t) {
1452
+ .klass = klass,
1453
+ .magic_errno = magic_errno,
1454
+ .magic_error = magic_error,
1455
+ };
1244
1456
 
1245
- return magic_exception(&e);
1457
+ return magic_exception(&mge);
1246
1458
  }
1247
1459
 
1248
1460
  static VALUE
1249
1461
  magic_library_error(VALUE klass, void *data)
1250
1462
  {
1251
- magic_exception_t e;
1463
+ rb_mgc_error_t mge;
1252
1464
  const char *message = NULL;
1253
1465
  const char *empty = "(null)";
1254
1466
  magic_t cookie = data;
1255
1467
 
1256
1468
  UNUSED(empty);
1257
1469
 
1258
- assert(cookie != NULL && \
1470
+ assert(cookie != NULL &&
1259
1471
  "Must be a valid pointer to `magic_t' type");
1260
1472
 
1261
- e.magic_errno = -1;
1262
- e.magic_error = error(E_UNKNOWN);
1263
- e.klass = klass;
1473
+ mge = (rb_mgc_error_t) {
1474
+ .klass = klass,
1475
+ .magic_errno = -1,
1476
+ .magic_error = MAGIC_ERRORS(E_UNKNOWN),
1477
+ };
1264
1478
 
1265
1479
  message = magic_error_wrapper(cookie);
1266
1480
  if (message) {
1267
- e.magic_errno = magic_errno_wrapper(cookie);
1268
- e.magic_error = message;
1481
+ mge.magic_errno = magic_errno_wrapper(cookie);
1482
+ mge.magic_error = message;
1269
1483
  }
1270
1484
 
1271
- assert(strncmp(e.magic_error, empty, strlen(empty)) != 0 && \
1485
+ assert(strncmp(mge.magic_error, empty, strlen(empty)) != 0 &&
1272
1486
  "Empty or invalid error message");
1273
1487
 
1274
- return magic_exception(&e);
1488
+ return magic_exception(&mge);
1275
1489
  }
1276
1490
 
1277
1491
  VALUE
1278
1492
  magic_lock(VALUE object, VALUE(*function)(ANYARGS), void *data)
1279
1493
  {
1280
- magic_object_t *mo;
1494
+ rb_mgc_object_t *mgc;
1495
+
1496
+ MAGIC_OBJECT(object, mgc);
1281
1497
 
1282
- MAGIC_OBJECT(mo);
1283
- rb_funcall(mo->mutex, rb_intern("lock"), 0);
1498
+ rb_funcall(mgc->mutex, rb_intern("lock"), 0);
1284
1499
 
1285
1500
  return rb_ensure(function, (VALUE)data, magic_unlock, object);
1286
1501
  }
@@ -1288,10 +1503,11 @@ magic_lock(VALUE object, VALUE(*function)(ANYARGS), void *data)
1288
1503
  VALUE
1289
1504
  magic_unlock(VALUE object)
1290
1505
  {
1291
- magic_object_t *mo;
1506
+ rb_mgc_object_t *mgc;
1507
+
1508
+ MAGIC_OBJECT(object, mgc);
1292
1509
 
1293
- MAGIC_OBJECT(mo);
1294
- rb_funcall(mo->mutex, rb_intern("unlock"), 0);
1510
+ rb_funcall(mgc->mutex, rb_intern("unlock"), 0);
1295
1511
 
1296
1512
  return Qnil;
1297
1513
  }
@@ -1299,13 +1515,12 @@ magic_unlock(VALUE object)
1299
1515
  static VALUE
1300
1516
  magic_return(void *data)
1301
1517
  {
1302
- magic_arguments_t *ma = data;
1518
+ rb_mgc_arguments_t *mga = data;
1303
1519
  const char *unknown = "???";
1304
1520
  VALUE separator = Qundef;
1305
- VALUE array = Qundef;
1306
- VALUE string = Qundef;
1521
+ VALUE array, string;
1307
1522
 
1308
- string = CSTR2RVAL(ma->result);
1523
+ string = CSTR2RVAL(mga->result);
1309
1524
  RB_GC_GUARD(string);
1310
1525
 
1311
1526
  /*
@@ -1313,15 +1528,15 @@ magic_return(void *data)
1313
1528
  * when the CONTINUE flag is set causing all valid matches found by the
1314
1529
  * Magic library to be returned.
1315
1530
  */
1316
- if (ma->flags & MAGIC_CONTINUE)
1531
+ if (mga->flags & MAGIC_CONTINUE)
1317
1532
  separator = CSTR2RVAL(MAGIC_CONTINUE_SEPARATOR);
1318
1533
 
1319
- if (ma->flags & MAGIC_EXTENSION) {
1534
+ if (mga->flags & MAGIC_EXTENSION) {
1320
1535
  /*
1321
1536
  * A possible I/O-related error has occurred, and there is very
1322
1537
  * little sense processing the results, so return string as-is.
1323
1538
  */
1324
- if (ma->status < 0)
1539
+ if (mga->status < 0)
1325
1540
  return string;
1326
1541
  /*
1327
1542
  * A number of Magic flags that support primarily files e.g.,
@@ -1330,19 +1545,25 @@ magic_return(void *data)
1330
1545
  * return an empty string, to indicate lack of results, rather
1331
1546
  * than a confusing string consisting of three questions marks.
1332
1547
  */
1333
- if (strncmp(ma->result, unknown, strlen(unknown)) == 0)
1548
+ if (strncmp(mga->result, unknown, strlen(unknown)) == 0)
1334
1549
  return CSTR2RVAL("");
1335
1550
 
1336
1551
  separator = CSTR2RVAL(MAGIC_EXTENSION_SEPARATOR);
1337
1552
  }
1338
1553
 
1339
- if (ma->flags & (MAGIC_CONTINUE | MAGIC_EXTENSION)) {
1554
+ RB_GC_GUARD(separator);
1555
+
1556
+ if (mga->flags & (MAGIC_CONTINUE | MAGIC_EXTENSION)) {
1340
1557
  array = magic_split(string, separator);
1341
1558
  RB_GC_GUARD(array);
1342
- return (RARRAY_LEN(array) > 1) ? array : magic_shift(array);
1559
+
1560
+ if (RARRAY_LEN(array) > 1)
1561
+ return magic_strip_array(array);
1562
+
1563
+ string = magic_shift(array);
1343
1564
  }
1344
1565
 
1345
- return string;
1566
+ return magic_strip(string);
1346
1567
  }
1347
1568
 
1348
1569
  static inline int
@@ -1351,10 +1572,10 @@ magic_get_flags(VALUE object)
1351
1572
  return NUM2INT(rb_ivar_get(object, id_at_flags));
1352
1573
  }
1353
1574
 
1354
- static inline int
1355
- magic_set_flags(VALUE object, VALUE value)
1575
+ static inline void
1576
+ magic_set_flags(VALUE object, int flags)
1356
1577
  {
1357
- return NUM2INT(rb_ivar_set(object, id_at_flags, value));
1578
+ rb_ivar_set(object, id_at_flags, INT2NUM(flags));
1358
1579
  }
1359
1580
 
1360
1581
  static inline VALUE
@@ -1363,7 +1584,7 @@ magic_set_paths(VALUE object, VALUE value)
1363
1584
  return rb_ivar_set(object, id_at_paths, value);
1364
1585
  }
1365
1586
 
1366
- static const rb_data_type_t rb_magic_type = {
1587
+ static const rb_data_type_t rb_mgc_type = {
1367
1588
  .wrap_struct_name = "magic",
1368
1589
  .function = {
1369
1590
  .dmark = magic_mark,