gettextpo 0.1.0 → 0.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f3ac361edc71b888a2d229cde89bb5502d51a46b3461a8d335879a5a4234141c
4
- data.tar.gz: fc2308b078480e83ba35408a8b37eb2044bde4066b73390946507fba6da7d1bd
3
+ metadata.gz: 3ac67f013230155611dd5bd8f673a19eb8d84153dbc3240e3f0849a3a78ebf9d
4
+ data.tar.gz: 5c3d1ac85ab300ccd98b798948448b64be26d1b69c055b0ec1e11c08641209d9
5
5
  SHA512:
6
- metadata.gz: c987dabcd215ecaa0faaf18958c62337443c838432eb45b7f154132aa1c7ebe11cb5771cc7b0e17fd9317de73e2c3c298aea28baca61c5305f5ffe4f1251d934
7
- data.tar.gz: 616e8b974e467b8bfbb11f8b316d937769bcead95bdf2785c0bd84767e8589a8e13e8ed41fd6bdc8fa8e511d15491130995f739506f96bf7a0d9c0116b001566
6
+ metadata.gz: 5cd5653bdff4094cbf3b14f57ae30b224ae0a20b775cf072ef008bf851e8fce4f129c8ffeb9071d271223c70c78035d717d82d70f8f00f32d1a2fe5c2ffae4d3
7
+ data.tar.gz: 77e26a94e04627ba399495819e25972b6dca2a9742e27e8c6ae9f5fff5032a3987f64e003707631c6a13ce38c4694a9d5a5692179a7e938d40023288d5965aa2
data/.dir-locals.el CHANGED
@@ -1,5 +1,6 @@
1
1
  ;;; Directory Local Variables -*- no-byte-compile: t -*-
2
2
  ;;; For more information see (info "(emacs) Directory Variables")
3
3
 
4
- ((nil . ((eval . (progn (add-to-list 'grep-find-ignored-directories "tmp")
4
+ ((nil . ((eval . (progn (require 'grep)
5
+ (add-to-list 'grep-find-ignored-directories "tmp")
5
6
  (add-to-list 'grep-find-ignored-directories "doc"))))))
data/.rdoc_options CHANGED
@@ -4,3 +4,4 @@ exclude:
4
4
  - bin
5
5
  - Rakefile
6
6
  - Gemfile
7
+ - vendor
data/CHANGELOG.md CHANGED
@@ -1,7 +1,14 @@
1
1
  # Change log of Ruby GettextPO gem
2
2
 
3
- ## [Unreleased]
3
+ ## Unreleased
4
4
 
5
- ## [0.1.0] - 2026-03-07
5
+ ## 0.1.1 - 2026-03-09
6
+
7
+ - Fix dangling pointer issue.
8
+ - Add libgettextpo version constant.
9
+ - Add severities constants.
10
+ - Improve API document.
11
+
12
+ ## 0.1.0 - 2026-03-07
6
13
 
7
14
  - Initial release
data/README.md CHANGED
@@ -55,16 +55,15 @@ GettextPO::File.read(po_path).message_iterator.each do |message|
55
55
  end
56
56
  ```
57
57
 
58
- Please refer to the API documentation and test cases for details.
58
+ Please refer to the [API documentation][api] and test cases for
59
+ details.
60
+
61
+ [api]: https://gemmaro.github.io/ruby-gettextpo/
59
62
 
60
63
  ## Development
61
64
 
62
65
  `./bin/debug` to debug when segmentation fault.
63
66
 
64
- References: [RubyのC APIの手引き 決定版][def], [Developers'
65
- documentation for Ruby][dev], [Rubyの拡張ライブラリの作り方][ext],
66
- [library rdoc/parser/c][parser], and [library rdoc][rdoc].
67
-
68
67
  After checking out the repo, run `bin/setup` to install
69
68
  dependencies. Then, run `rake test` to run the tests. You can also run
70
69
  `bin/console` for an interactive prompt that will allow you to
@@ -76,16 +75,16 @@ install`. To release a new version, update the version number in
76
75
  create a git tag for the version, push git commits and the created
77
76
  tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
78
77
 
79
- [def]: https://gemmaro.github.io/emberb/
80
- [dev]: https://docs.ruby-lang.org/capi/en/master/index.html
81
- [ext]: https://docs.ruby-lang.org/en/master/extension_ja_rdoc.html
82
- [parser]: https://docs.ruby-lang.org/ja/latest/library/rdoc=2fparser=2fc.html
83
- [rdoc]: https://docs.ruby-lang.org/ja/latest/library/rdoc.html
84
-
85
78
  ## Contributing
86
79
 
87
- Bug reports and pull requests are welcome on Disroot at
88
- <https://git.disroot.org/gemmaro/ruby-gettextpo>.
80
+ Bug reports and pull requests are welcome on [Disroot][disroot].
81
+
82
+ Other links:
83
+
84
+ * [RubyGems](https://rubygems.org/gems/gettextpo)
85
+ * [GitHub repository](https://github.com/gemmaro/ruby-gettextpo)
86
+
87
+ [disroot]: https://git.disroot.org/gemmaro/ruby-gettextpo
89
88
 
90
89
  ## License
91
90
 
@@ -1,5 +1,4 @@
1
- /**
2
- * Copyright (C) 2026 gemmaro
1
+ /* Copyright (C) 2026 gemmaro
3
2
  *
4
3
  * This program is free software: you can redistribute it and/or modify
5
4
  * it under the terms of the GNU General Public License as published by
@@ -16,36 +15,21 @@
16
15
  */
17
16
 
18
17
  #include "gettextpo.h"
19
- #include <gettext-po.h>
20
- #include <ruby/internal/anyargs.h>
21
- #include <ruby/internal/arithmetic/int.h>
22
- #include <ruby/internal/core/rdata.h>
23
- #include <ruby/internal/core/rstring.h>
24
- #include <ruby/internal/core/rtypeddata.h>
25
- #include <ruby/internal/eval.h>
26
- #include <ruby/internal/globals.h>
27
- #include <ruby/internal/intern/array.h>
28
- #include <ruby/internal/intern/hash.h>
29
- #include <ruby/internal/intern/object.h>
30
- #include <ruby/internal/intern/proc.h>
31
- #include <ruby/internal/intern/range.h>
32
- #include <ruby/internal/intern/string.h>
33
- #include <ruby/internal/intern/vm.h>
34
- #include <ruby/internal/module.h>
35
- #include <ruby/internal/scan_args.h>
36
- #include <ruby/internal/special_consts.h>
37
- #include <ruby/internal/symbol.h>
38
- #include <ruby/internal/value.h>
39
- #include <stdbool.h>
40
- #include <stddef.h>
41
- #include <stdlib.h>
42
- #include <time.h>
43
18
 
44
19
  VALUE rb_cMessage;
45
20
  VALUE rb_cMessageIterator;
46
21
  VALUE rb_cFilePos;
47
22
  VALUE rb_eError;
48
23
 
24
+ /* FilePos, Message, and MessageIterator each hold a @file instance
25
+ * variable (ivar) pointing to the GettextPO::File object that owns
26
+ * the underlying po_file_t. This prevents the File object from being
27
+ * garbage collected while any of these objects are still alive, which
28
+ * would otherwise cause their po_file_t pointers to become dangling.
29
+ * When allocating one of these objects, @file must be propagated from
30
+ * the parent object: File -> MessageIterator -> Message -> FilePos.
31
+ */
32
+
49
33
  /* ********** error ********** */
50
34
 
51
35
  static struct
@@ -53,6 +37,7 @@ static struct
53
37
  bool error;
54
38
  VALUE *user_xerror;
55
39
  VALUE *user_xerror2;
40
+ VALUE *file;
56
41
  } gettextpo_xerror_context = {};
57
42
 
58
43
  static void
@@ -61,6 +46,7 @@ gettextpo_xerror_context_reset (void)
61
46
  gettextpo_xerror_context.error = false;
62
47
  gettextpo_xerror_context.user_xerror = NULL;
63
48
  gettextpo_xerror_context.user_xerror2 = NULL;
49
+ gettextpo_xerror_context.file = NULL;
64
50
  }
65
51
 
66
52
  static void
@@ -79,6 +65,8 @@ gettextpo_xerror (const int severity, const po_message_t message,
79
65
  {
80
66
  VALUE message_value = rb_obj_alloc (rb_cMessage);
81
67
  DATA_PTR (message_value) = message;
68
+ rb_ivar_set (message_value, rb_intern ("@file"),
69
+ *gettextpo_xerror_context.file);
82
70
  rb_hash_aset (kwargs, ID2SYM (rb_intern ("message")), message_value);
83
71
  }
84
72
  if (filename)
@@ -120,6 +108,8 @@ gettextpo_xerror2 (const int severity, const po_message_t message1,
120
108
  {
121
109
  VALUE message_value1 = rb_obj_alloc (rb_cMessage);
122
110
  DATA_PTR (message_value1) = message1;
111
+ rb_ivar_set (message_value1, rb_intern ("@file"),
112
+ *gettextpo_xerror_context.file);
123
113
  rb_hash_aset (kwargs, ID2SYM (rb_intern ("message1")), message_value1);
124
114
  }
125
115
  if (filename1)
@@ -138,6 +128,8 @@ gettextpo_xerror2 (const int severity, const po_message_t message1,
138
128
  {
139
129
  VALUE message_value2 = rb_obj_alloc (rb_cMessage);
140
130
  DATA_PTR (message_value2) = message2;
131
+ rb_ivar_set (message_value2, rb_intern ("@file"),
132
+ *gettextpo_xerror_context.file);
141
133
  rb_hash_aset (kwargs, ID2SYM (rb_intern ("message2")), message_value2);
142
134
  }
143
135
  if (filename2)
@@ -470,6 +462,8 @@ gettextpo_po_message_m_filepos (VALUE self, VALUE index)
470
462
  {
471
463
  VALUE filepos = rb_obj_alloc (rb_cFilePos);
472
464
  DATA_PTR (filepos) = pos;
465
+ rb_ivar_set (filepos, rb_intern ("@file"),
466
+ rb_ivar_get (self, rb_intern ("@file")));
473
467
  return filepos;
474
468
  }
475
469
  else
@@ -500,7 +494,7 @@ gettextpo_po_message_m_add_filepos (VALUE self, VALUE file, VALUE start_line)
500
494
  /**
501
495
  * call-seq: check_all (iterator, xerror: nil, xerror2: nil)
502
496
  *
503
- * See also GettextPO::File.read.
497
+ * See also GettextPO::File.read for exception error handlings.
504
498
  */
505
499
  VALUE
506
500
  gettextpo_po_message_m_check_all (int argc, VALUE *argv, VALUE self)
@@ -511,6 +505,8 @@ gettextpo_po_message_m_check_all (int argc, VALUE *argv, VALUE self)
511
505
  VALUE kwargs_vals[] = { Qundef, Qundef };
512
506
  rb_get_kwargs (kwargs, kwargs_ids, 0, 2, kwargs_vals);
513
507
  gettextpo_xerror_context_reset ();
508
+ VALUE file = rb_ivar_get (self, rb_intern ("@file"));
509
+ gettextpo_xerror_context.file = &file;
514
510
  if (kwargs_vals[0] != Qundef)
515
511
  gettextpo_xerror_context.user_xerror = &kwargs_vals[0];
516
512
  if (kwargs_vals[1] != Qundef)
@@ -525,7 +521,7 @@ gettextpo_po_message_m_check_all (int argc, VALUE *argv, VALUE self)
525
521
  /**
526
522
  * call-seq: check_format (xerror: nil, xerror2: nil)
527
523
  *
528
- * See also GettextPO::File.read.
524
+ * See also GettextPO::File.read for exception error handlings.
529
525
  */
530
526
  VALUE
531
527
  gettextpo_po_message_m_check_format (int argc, VALUE *argv, VALUE self)
@@ -536,6 +532,8 @@ gettextpo_po_message_m_check_format (int argc, VALUE *argv, VALUE self)
536
532
  VALUE kwargs_vals[] = { Qundef, Qundef };
537
533
  rb_get_kwargs (kwargs, kwargs_ids, 0, 2, kwargs_vals);
538
534
  gettextpo_xerror_context_reset ();
535
+ VALUE file = rb_ivar_get (self, rb_intern ("@file"));
536
+ gettextpo_xerror_context.file = &file;
539
537
  if (kwargs_vals[0] != Qundef)
540
538
  gettextpo_xerror_context.user_xerror = &kwargs_vals[0];
541
539
  if (kwargs_vals[1] != Qundef)
@@ -562,6 +560,10 @@ gettextpo_po_file_alloc (VALUE self)
562
560
  return TypedData_Wrap_Struct (self, &gettextpo_po_file_type, NULL);
563
561
  }
564
562
 
563
+ /**
564
+ * See also #message_iterator and GettextPO::MessageIterator#insert
565
+ * methods for the further manipulations.
566
+ */
565
567
  VALUE
566
568
  gettextpo_po_file_m_initialize (VALUE self)
567
569
  {
@@ -577,7 +579,8 @@ gettextpo_po_file_m_initialize (VALUE self)
577
579
  * +multiline+, and +message_text+. +xerror2+ takes keyword arguments
578
580
  * +severity+, +message1+, +filename1+, +lineno1+, +column1+,
579
581
  * +multiline1+, +message_text1+, +message2+, +filename2+, +lineno2+,
580
- * +column2+, +multiline2+, and +message_text2+.
582
+ * +column2+, +multiline2+, and +message_text2+. See also GettextPO
583
+ * for general exception handlings.
581
584
  */
582
585
  VALUE
583
586
  gettextpo_po_file_m_read (int argc, VALUE *argv, VALUE klass)
@@ -588,11 +591,12 @@ gettextpo_po_file_m_read (int argc, VALUE *argv, VALUE klass)
588
591
  VALUE kwargs_vals[] = { Qundef, Qundef };
589
592
  rb_get_kwargs (kwargs, kwargs_ids, 0, 2, kwargs_vals);
590
593
  gettextpo_xerror_context_reset ();
594
+ VALUE self = rb_obj_alloc (klass);
595
+ gettextpo_xerror_context.file = &self;
591
596
  if (kwargs_vals[0] != Qundef)
592
597
  gettextpo_xerror_context.user_xerror = &kwargs_vals[0];
593
598
  if (kwargs_vals[1] != Qundef)
594
599
  gettextpo_xerror_context.user_xerror2 = &kwargs_vals[1];
595
- VALUE self = rb_obj_alloc (klass);
596
600
  DATA_PTR (self)
597
601
  = po_file_read (StringValueCStr (filename), &gettextpo_xerror_handler);
598
602
  if (gettextpo_xerror_context.error)
@@ -603,7 +607,7 @@ gettextpo_po_file_m_read (int argc, VALUE *argv, VALUE klass)
603
607
  /**
604
608
  * call-seq: write (filename, xerror: nil, xerror2: nil)
605
609
  *
606
- * See also ::read.
610
+ * See also ::read for exception error handlings.
607
611
  */
608
612
  VALUE
609
613
  gettextpo_po_file_m_write (int argc, VALUE *argv, VALUE self)
@@ -614,6 +618,7 @@ gettextpo_po_file_m_write (int argc, VALUE *argv, VALUE self)
614
618
  VALUE kwargs_vals[] = { Qundef, Qundef };
615
619
  rb_get_kwargs (kwargs, kwargs_ids, 0, 2, kwargs_vals);
616
620
  gettextpo_xerror_context_reset ();
621
+ gettextpo_xerror_context.file = &self;
617
622
  if (kwargs_vals[0] != Qundef)
618
623
  gettextpo_xerror_context.user_xerror = &kwargs_vals[0];
619
624
  if (kwargs_vals[1] != Qundef)
@@ -646,11 +651,12 @@ gettextpo_po_file_m_message_iterator (int argc, VALUE *argv, VALUE self)
646
651
  VALUE iterator = rb_obj_alloc (rb_cMessageIterator);
647
652
  DATA_PTR (iterator) = po_message_iterator (
648
653
  DATA_PTR (self), NIL_P (domain) ? NULL : StringValueCStr (domain));
654
+ rb_ivar_set (iterator, rb_intern ("@file"), self);
649
655
  return iterator;
650
656
  }
651
657
 
652
658
  /**
653
- * call-seq: domain_header (domain)
659
+ * call-seq: domain_header (domain = nil)
654
660
  *
655
661
  * +domain+ can be +nil+ to use a default. Possibly returns +nil+.
656
662
  *
@@ -669,7 +675,7 @@ gettextpo_po_file_m_domain_header (int argc, VALUE *argv, VALUE self)
669
675
  /**
670
676
  * call-seq: check_all (xerror: nil, xerror2: nil)
671
677
  *
672
- * See also ::read.
678
+ * See also ::read for exception error handlings.
673
679
  */
674
680
  VALUE
675
681
  gettextpo_po_file_m_check_all (int argc, VALUE *argv, VALUE self)
@@ -680,6 +686,7 @@ gettextpo_po_file_m_check_all (int argc, VALUE *argv, VALUE self)
680
686
  VALUE kwargs_vals[] = { Qundef, Qundef };
681
687
  rb_get_kwargs (kwargs, kwargs_ids, 0, 2, kwargs_vals);
682
688
  gettextpo_xerror_context_reset ();
689
+ gettextpo_xerror_context.file = &self;
683
690
  if (kwargs_vals[0] != Qundef)
684
691
  gettextpo_xerror_context.user_xerror = &kwargs_vals[0];
685
692
  if (kwargs_vals[1] != Qundef)
@@ -718,6 +725,8 @@ gettextpo_po_message_iterator_m_next (VALUE self)
718
725
  {
719
726
  VALUE message_value = rb_obj_alloc (rb_cMessage);
720
727
  DATA_PTR (message_value) = message;
728
+ rb_ivar_set (message_value, rb_intern ("@file"),
729
+ rb_ivar_get (self, rb_intern ("@file")));
721
730
  return message_value;
722
731
  }
723
732
  else
@@ -736,6 +745,8 @@ gettextpo_po_message_iterator_m_insert (VALUE self, VALUE msgid, VALUE msgstr)
736
745
  po_message_insert (DATA_PTR (self), message);
737
746
  VALUE value = rb_obj_alloc (rb_cMessage);
738
747
  DATA_PTR (value) = message;
748
+ rb_ivar_set (value, rb_intern ("@file"),
749
+ rb_ivar_get (self, rb_intern ("@file")));
739
750
  return value;
740
751
  }
741
752
 
@@ -831,6 +842,8 @@ gettextpo_po_format_list (VALUE self)
831
842
  * call-seq: format_pretty_name (format)
832
843
  *
833
844
  * Possibly returns +nil+.
845
+ *
846
+ * See also ::formats method for available format types.
834
847
  */
835
848
  VALUE
836
849
  gettextpo_po_format_pretty_name (VALUE self, VALUE format)
@@ -845,6 +858,14 @@ RUBY_FUNC_EXPORTED void
845
858
  Init_gettextpo (void)
846
859
  {
847
860
  VALUE rb_mGettextPO = rb_define_module ("GettextPO");
861
+ rb_define_const (rb_mGettextPO, "LIBGETTEXTPO_VERSION",
862
+ INT2NUM (libgettextpo_version));
863
+ rb_define_const (rb_mGettextPO, "SEVERITY_WARNING",
864
+ INT2NUM (PO_SEVERITY_WARNING));
865
+ rb_define_const (rb_mGettextPO, "SEVERITY_ERROR",
866
+ INT2NUM (PO_SEVERITY_ERROR));
867
+ rb_define_const (rb_mGettextPO, "SEVERITY_FATAL_ERROR",
868
+ INT2NUM (PO_SEVERITY_FATAL_ERROR));
848
869
  rb_define_singleton_method (rb_mGettextPO, "header_entry_value",
849
870
  gettextpo_m_header_entry_value, 2);
850
871
  rb_define_singleton_method (rb_mGettextPO, "header_with_updated_entry_value",
@@ -1,5 +1,4 @@
1
- /**
2
- * Copyright (C) 2026 gemmaro
1
+ /* Copyright (C) 2026 gemmaro
3
2
  *
4
3
  * This program is free software: you can redistribute it and/or modify
5
4
  * it under the terms of the GNU General Public License as published by
@@ -18,6 +17,7 @@
18
17
  #ifndef GETTEXTPO_H
19
18
  #define GETTEXTPO_H 1
20
19
 
21
- #include "ruby.h"
20
+ #include <gettext-po.h>
21
+ #include <ruby.h>
22
22
 
23
23
  #endif /* GETTEXTPO_H */
@@ -18,5 +18,6 @@
18
18
  #++
19
19
 
20
20
  module GettextPO
21
- VERSION = "0.1.0"
21
+ # Version of this gem.
22
+ VERSION = "0.1.1"
22
23
  end
data/lib/gettextpo.rb CHANGED
@@ -20,6 +20,16 @@ require_relative "gettextpo/gettextpo"
20
20
 
21
21
  # The main entrypoints to parse PO files are GettextPO::File.new and
22
22
  # GettextPO::File.read.
23
+ #
24
+ # == Error handling
25
+ #
26
+ # Some functions takes exception error handling paramters like
27
+ # +xerror+ and +xerror2+. These parameters expect +Proc+ object which
28
+ # takes several parameters. See also the description of
29
+ # GettextPO::File.read method. The +severity+ parameter among these
30
+ # parameters is either SEVERITY_WARNING, SEVERITY_ERROR, or
31
+ # SEVERITY_FATAL_ERROR.
32
+ #
23
33
  module GettextPO
24
34
  class Error < StandardError; end
25
35
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gettextpo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - gemmaro
@@ -40,6 +40,7 @@ metadata:
40
40
  rubygems_mfa_required: 'true'
41
41
  bug_tracker_uri: https://git.disroot.org/gemmaro/ruby-gettextpo/issues
42
42
  changelog_uri: https://git.disroot.org/gemmaro/ruby-gettextpo/src/branch/main/CHANGELOG.md
43
+ documentation_uri: https://gemmaro.github.io/ruby-gettextpo/
43
44
  homepage_uri: https://git.disroot.org/gemmaro/ruby-gettextpo
44
45
  source_code_uri: https://git.disroot.org/gemmaro/ruby-gettextpo
45
46
  wiki_uri: https://git.disroot.org/gemmaro/ruby-gettextpo/wiki