ruby-magic 0.4.0 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,