mandoc 0.0.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.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +7 -0
  3. data/COPYING +674 -0
  4. data/README.md +117 -0
  5. data/ext/mandoc/extconf.rb +59 -0
  6. data/ext/mandoc/rb_mandoc.c +548 -0
  7. data/ext/mandoc/rb_mandoc.h +22 -0
  8. data/lib/mandoc/version.rb +19 -0
  9. data/lib/mandoc.rb +26 -0
  10. data/mandoc-1.14.6/LICENSE +55 -0
  11. data/mandoc-1.14.6/arch.c +54 -0
  12. data/mandoc-1.14.6/att.c +49 -0
  13. data/mandoc-1.14.6/catman.c +260 -0
  14. data/mandoc-1.14.6/cgi.c +1279 -0
  15. data/mandoc-1.14.6/chars.c +507 -0
  16. data/mandoc-1.14.6/compat_err.c +103 -0
  17. data/mandoc-1.14.6/compat_fts.c +696 -0
  18. data/mandoc-1.14.6/compat_fts.h +106 -0
  19. data/mandoc-1.14.6/compat_getline.c +59 -0
  20. data/mandoc-1.14.6/compat_getsubopt.c +87 -0
  21. data/mandoc-1.14.6/compat_isblank.c +23 -0
  22. data/mandoc-1.14.6/compat_mkdtemp.c +50 -0
  23. data/mandoc-1.14.6/compat_mkstemps.c +63 -0
  24. data/mandoc-1.14.6/compat_ohash.c +330 -0
  25. data/mandoc-1.14.6/compat_ohash.h +72 -0
  26. data/mandoc-1.14.6/compat_progname.c +31 -0
  27. data/mandoc-1.14.6/compat_reallocarray.c +40 -0
  28. data/mandoc-1.14.6/compat_recallocarray.c +99 -0
  29. data/mandoc-1.14.6/compat_strcasestr.c +64 -0
  30. data/mandoc-1.14.6/compat_stringlist.c +135 -0
  31. data/mandoc-1.14.6/compat_stringlist.h +48 -0
  32. data/mandoc-1.14.6/compat_strlcat.c +57 -0
  33. data/mandoc-1.14.6/compat_strlcpy.c +52 -0
  34. data/mandoc-1.14.6/compat_strndup.c +42 -0
  35. data/mandoc-1.14.6/compat_strsep.c +70 -0
  36. data/mandoc-1.14.6/compat_strtonum.c +67 -0
  37. data/mandoc-1.14.6/compat_vasprintf.c +47 -0
  38. data/mandoc-1.14.6/config.h +52 -0
  39. data/mandoc-1.14.6/dba.c +508 -0
  40. data/mandoc-1.14.6/dba.h +50 -0
  41. data/mandoc-1.14.6/dba_array.c +190 -0
  42. data/mandoc-1.14.6/dba_array.h +47 -0
  43. data/mandoc-1.14.6/dba_read.c +74 -0
  44. data/mandoc-1.14.6/dba_write.c +127 -0
  45. data/mandoc-1.14.6/dba_write.h +30 -0
  46. data/mandoc-1.14.6/dbm.c +480 -0
  47. data/mandoc-1.14.6/dbm.h +68 -0
  48. data/mandoc-1.14.6/dbm_map.c +194 -0
  49. data/mandoc-1.14.6/dbm_map.h +29 -0
  50. data/mandoc-1.14.6/demandoc.c +260 -0
  51. data/mandoc-1.14.6/eqn.c +1132 -0
  52. data/mandoc-1.14.6/eqn.h +72 -0
  53. data/mandoc-1.14.6/eqn_html.c +246 -0
  54. data/mandoc-1.14.6/eqn_parse.h +48 -0
  55. data/mandoc-1.14.6/eqn_term.c +174 -0
  56. data/mandoc-1.14.6/html.c +1102 -0
  57. data/mandoc-1.14.6/html.h +142 -0
  58. data/mandoc-1.14.6/lib.c +35 -0
  59. data/mandoc-1.14.6/libman.h +42 -0
  60. data/mandoc-1.14.6/libmandoc.h +85 -0
  61. data/mandoc-1.14.6/libmdoc.h +87 -0
  62. data/mandoc-1.14.6/main.c +1375 -0
  63. data/mandoc-1.14.6/main.h +53 -0
  64. data/mandoc-1.14.6/man.c +345 -0
  65. data/mandoc-1.14.6/man.h +21 -0
  66. data/mandoc-1.14.6/man_html.c +640 -0
  67. data/mandoc-1.14.6/man_macro.c +470 -0
  68. data/mandoc-1.14.6/man_term.c +1143 -0
  69. data/mandoc-1.14.6/man_validate.c +660 -0
  70. data/mandoc-1.14.6/manconf.h +58 -0
  71. data/mandoc-1.14.6/mandoc.c +669 -0
  72. data/mandoc-1.14.6/mandoc.h +329 -0
  73. data/mandoc-1.14.6/mandoc_aux.c +118 -0
  74. data/mandoc-1.14.6/mandoc_aux.h +27 -0
  75. data/mandoc-1.14.6/mandoc_msg.c +375 -0
  76. data/mandoc-1.14.6/mandoc_ohash.c +65 -0
  77. data/mandoc-1.14.6/mandoc_ohash.h +23 -0
  78. data/mandoc-1.14.6/mandoc_parse.h +44 -0
  79. data/mandoc-1.14.6/mandoc_xr.c +123 -0
  80. data/mandoc-1.14.6/mandoc_xr.h +31 -0
  81. data/mandoc-1.14.6/mandocd.c +282 -0
  82. data/mandoc-1.14.6/mandocdb.c +2448 -0
  83. data/mandoc-1.14.6/manpath.c +363 -0
  84. data/mandoc-1.14.6/mansearch.c +851 -0
  85. data/mandoc-1.14.6/mansearch.h +118 -0
  86. data/mandoc-1.14.6/mdoc.c +433 -0
  87. data/mandoc-1.14.6/mdoc.h +158 -0
  88. data/mandoc-1.14.6/mdoc_argv.c +682 -0
  89. data/mandoc-1.14.6/mdoc_html.c +1762 -0
  90. data/mandoc-1.14.6/mdoc_macro.c +1600 -0
  91. data/mandoc-1.14.6/mdoc_man.c +1850 -0
  92. data/mandoc-1.14.6/mdoc_markdown.c +1610 -0
  93. data/mandoc-1.14.6/mdoc_state.c +256 -0
  94. data/mandoc-1.14.6/mdoc_term.c +1964 -0
  95. data/mandoc-1.14.6/mdoc_validate.c +3062 -0
  96. data/mandoc-1.14.6/msec.c +37 -0
  97. data/mandoc-1.14.6/out.c +544 -0
  98. data/mandoc-1.14.6/out.h +70 -0
  99. data/mandoc-1.14.6/preconv.c +179 -0
  100. data/mandoc-1.14.6/read.c +732 -0
  101. data/mandoc-1.14.6/roff.c +4390 -0
  102. data/mandoc-1.14.6/roff.h +561 -0
  103. data/mandoc-1.14.6/roff_html.c +119 -0
  104. data/mandoc-1.14.6/roff_int.h +94 -0
  105. data/mandoc-1.14.6/roff_term.c +266 -0
  106. data/mandoc-1.14.6/roff_validate.c +151 -0
  107. data/mandoc-1.14.6/soelim.c +182 -0
  108. data/mandoc-1.14.6/st.c +82 -0
  109. data/mandoc-1.14.6/tag.c +327 -0
  110. data/mandoc-1.14.6/tag.h +35 -0
  111. data/mandoc-1.14.6/tbl.c +183 -0
  112. data/mandoc-1.14.6/tbl.h +121 -0
  113. data/mandoc-1.14.6/tbl_data.c +323 -0
  114. data/mandoc-1.14.6/tbl_html.c +293 -0
  115. data/mandoc-1.14.6/tbl_int.h +47 -0
  116. data/mandoc-1.14.6/tbl_layout.c +376 -0
  117. data/mandoc-1.14.6/tbl_opts.c +173 -0
  118. data/mandoc-1.14.6/tbl_parse.h +30 -0
  119. data/mandoc-1.14.6/tbl_term.c +948 -0
  120. data/mandoc-1.14.6/term.c +1113 -0
  121. data/mandoc-1.14.6/term.h +158 -0
  122. data/mandoc-1.14.6/term_ascii.c +424 -0
  123. data/mandoc-1.14.6/term_ps.c +1362 -0
  124. data/mandoc-1.14.6/term_tab.c +130 -0
  125. data/mandoc-1.14.6/term_tag.c +227 -0
  126. data/mandoc-1.14.6/term_tag.h +34 -0
  127. data/mandoc-1.14.6/tree.c +536 -0
  128. metadata +170 -0
@@ -0,0 +1,548 @@
1
+ /*
2
+ * Copyright (C) 2026 gemmaro
3
+ *
4
+ * This program is free software: you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License as published by
6
+ * the Free Software Foundation, either version 3 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU General Public License for more details.
13
+ */
14
+
15
+ #include "rb_mandoc.h"
16
+
17
+ #include "main.h"
18
+ #include "mandoc.h"
19
+ #include "roff.h"
20
+
21
+ /* This must be after roff.h. */
22
+ #include "mandoc_parse.h"
23
+
24
+ #include <ruby.h>
25
+ #include <stdio.h>
26
+ #include <stdlib.h>
27
+ #include <sys/types.h>
28
+ #include <unistd.h>
29
+
30
+ /* m_ is for mandoc prefix */
31
+ static VALUE rb_mMandoc, rb_cParser, rb_cMeta, rb_cMdocMeta, rb_cManMeta,
32
+ rb_cNode, rb_cRootNode, rb_cBlockNode, rb_cHeadNode, rb_cBodyNode,
33
+ rb_cTailNode, rb_cElemNode, rb_cTextNode, rb_cCommentNode, rb_cTBLNode,
34
+ rb_cEQNNode, rb_eError;
35
+
36
+ /* parser */
37
+
38
+ static void
39
+ rb_parser_free (void *parser)
40
+ {
41
+ struct mparse *parse = parser;
42
+ mparse_free (parse);
43
+ mchars_free ();
44
+ }
45
+
46
+ static const rb_data_type_t rb_parser_type
47
+ = { .wrap_struct_name = "mandoc parser",
48
+ .function = { .dfree = rb_parser_free },
49
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY };
50
+
51
+ static VALUE
52
+ rb_parser_alloc (VALUE klass)
53
+ {
54
+ mchars_alloc ();
55
+ /* MPARSE_VALIDATE is always required (as in mandoc(3) of course)
56
+ since it fills title and other attributes in meta. I don't find
57
+ any reason to disable this. */
58
+ struct mparse *parse = mparse_alloc (
59
+ MPARSE_VALIDATE /* TODO: support other options */,
60
+ MANDOC_OS_OTHER /* TODO: support explicitly set? */,
61
+ NULL /* TODO: support default string for the mdoc Os macro? */);
62
+ return rb_data_typed_object_wrap (klass, parse, &rb_parser_type);
63
+ }
64
+
65
+ static const rb_data_type_t rb_meta_type;
66
+ static VALUE
67
+ rb_parser_m_parse_file (VALUE self, VALUE fname)
68
+ {
69
+ char *name = rb_string_value_cstr (&fname);
70
+
71
+ struct mparse *parser = RTYPEDDATA_DATA (self);
72
+
73
+ /* Previous memories are kept. It will be freed when parsed
74
+ will, not now. */
75
+ mparse_reset (parser);
76
+
77
+ int descriptor = mparse_open (parser, name);
78
+ if (descriptor == -1)
79
+ rb_raise (rb_eError, "failed to open");
80
+ mparse_readfd (parser, descriptor, name);
81
+ if (close (descriptor) == -1)
82
+ rb_raise (rb_eError, "failed to close");
83
+ struct roff_meta *meta = mparse_result (parser);
84
+ /* TODO: fetch validity of the input with mparse_updaterc */
85
+
86
+ VALUE klass;
87
+ switch (meta->macroset)
88
+ {
89
+ case MACROSET_NONE:
90
+ rb_raise (rb_eError, "unknown macroset");
91
+ case MACROSET_MDOC:
92
+ klass = rb_cMdocMeta;
93
+ break;
94
+ case MACROSET_MAN:
95
+ klass = rb_cManMeta;
96
+ break;
97
+ }
98
+
99
+ VALUE val = rb_data_typed_object_wrap (klass, meta, &rb_meta_type);
100
+
101
+ /* To prevent garbage collect parser and for man-to-man output. */
102
+ rb_iv_set (val, "@parser", self);
103
+
104
+ return val;
105
+ }
106
+
107
+ /* roff meta */
108
+
109
+ void
110
+ rb_meta_free (void *meta)
111
+ {
112
+ (void)meta;
113
+ }
114
+
115
+ static const rb_data_type_t rb_meta_type
116
+ = { .wrap_struct_name = "mandoc meta",
117
+ .function = { .dfree = rb_meta_free },
118
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY };
119
+
120
+ static VALUE
121
+ rb_meta_alloc (VALUE klass)
122
+ {
123
+ return rb_data_typed_object_wrap (rb_cMeta, NULL, &rb_meta_type);
124
+ }
125
+
126
+ static VALUE
127
+ rb_meta_m_deroff (VALUE self)
128
+ {
129
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
130
+ char *text = NULL;
131
+ deroff (&text, meta->first);
132
+ VALUE str
133
+ = rb_str_new_cstr (text); /* user's responsibility to decide encoding */
134
+ free (text);
135
+ return str;
136
+ }
137
+
138
+ static VALUE
139
+ rb_meta_m_section (VALUE self)
140
+ {
141
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
142
+ return rb_str_new_cstr (meta->msec);
143
+ }
144
+
145
+ static VALUE
146
+ rb_meta_m_volume (VALUE self)
147
+ {
148
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
149
+ return rb_str_new_cstr (meta->vol);
150
+ }
151
+
152
+ static VALUE
153
+ rb_meta_m_os (VALUE self)
154
+ {
155
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
156
+ return rb_str_new_cstr (meta->os);
157
+ }
158
+
159
+ static VALUE
160
+ rb_meta_m_arch (VALUE self)
161
+ {
162
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
163
+ return meta->arch ? rb_str_new_cstr (meta->arch) : RUBY_Qnil;
164
+ }
165
+
166
+ static VALUE
167
+ rb_meta_m_title (VALUE self)
168
+ {
169
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
170
+ return rb_str_new_cstr (meta->title);
171
+ }
172
+
173
+ static VALUE
174
+ rb_meta_m_name (VALUE self)
175
+ {
176
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
177
+ return rb_str_new_cstr (meta->name);
178
+ }
179
+
180
+ static VALUE
181
+ rb_meta_m_date (VALUE self)
182
+ {
183
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
184
+ return rb_str_new_cstr (meta->date);
185
+ }
186
+
187
+ static VALUE
188
+ rb_meta_m_so_target (VALUE self)
189
+ {
190
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
191
+ return meta->sodest ? rb_str_new_cstr (meta->sodest) : RUBY_Qnil;
192
+ }
193
+
194
+ static VALUE
195
+ rb_meta_m_has_body (VALUE self)
196
+ {
197
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
198
+ return meta->hasbody ? RUBY_Qtrue : RUBY_Qfalse;
199
+ }
200
+
201
+ /* Return read end of pipe. */
202
+ static int
203
+ rb_backup_stdout (int *original_stdout)
204
+ {
205
+ int pipefd[2];
206
+ if (pipe (pipefd) == -1)
207
+ rb_raise (rb_eError, "failed to create pipe");
208
+ *original_stdout = dup (STDOUT_FILENO);
209
+ if (*original_stdout == -1)
210
+ rb_raise (rb_eError, "failed to dup stdout");
211
+ if (fflush (stdout) == EOF)
212
+ rb_raise (rb_eError, "failed to flush stdout");
213
+ if (dup2 (pipefd[1], STDOUT_FILENO) == -1)
214
+ rb_raise (rb_eError, "failed to set stdout to pipe");
215
+ if (close (pipefd[1]) == -1)
216
+ rb_raise (rb_eError, "failed to close pipe write end");
217
+ return pipefd[0];
218
+ }
219
+
220
+ static VALUE
221
+ rb_restore_stdout (int original_stdout, int read_end)
222
+ {
223
+ if (fflush (stdout) == EOF)
224
+ rb_raise (rb_eError, "failed to flush stdout after convert");
225
+ if (dup2 (original_stdout, STDOUT_FILENO) == -1)
226
+ rb_raise (rb_eError, "failed to restore stdout");
227
+ if (close (original_stdout) == -1)
228
+ rb_raise (rb_eError, "failed to close original stdout");
229
+
230
+ /* $ find mandoc-1.14.6 -name '*.1' | while read -r file; do wc $file; done
231
+ * 158 764 4593 mandoc-1.14.6/regress/regress.pl.1
232
+ * 513 1971 10983 mandoc-1.14.6/apropos.1
233
+ * 108 471 2707 mandoc-1.14.6/demandoc.1
234
+ * 431 1783 9833 mandoc-1.14.6/man.1
235
+ * 1332 4355 21554 mandoc-1.14.6/man.options.1
236
+ * 2412 10705 58653 mandoc-1.14.6/mandoc.1
237
+ * 86 441 2661 mandoc-1.14.6/soelim.1
238
+ */
239
+ VALUE md = rb_str_buf_new (3000);
240
+
241
+ char tmp[1 << 12];
242
+ ssize_t n;
243
+ while ((n = read (read_end, tmp, sizeof (tmp))) > 0)
244
+ rb_str_cat (md, tmp, n);
245
+
246
+ if (close (read_end) == -1)
247
+ rb_raise (rb_eError, "failed to close pipe read end");
248
+ return md;
249
+ }
250
+
251
+ static VALUE
252
+ rb_mdocmeta_m_tree (VALUE self)
253
+ {
254
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
255
+
256
+ int original_stdout;
257
+ int read_end = rb_backup_stdout (&original_stdout);
258
+
259
+ tree_mdoc (NULL, meta);
260
+
261
+ return rb_restore_stdout (original_stdout, read_end);
262
+ }
263
+
264
+ static VALUE
265
+ rb_manmeta_m_tree (VALUE self)
266
+ {
267
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
268
+
269
+ int original_stdout;
270
+ int read_end = rb_backup_stdout (&original_stdout);
271
+
272
+ tree_man (NULL, meta);
273
+
274
+ return rb_restore_stdout (original_stdout, read_end);
275
+ }
276
+
277
+ static VALUE
278
+ rb_mdocmeta_m_man (VALUE self)
279
+ {
280
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
281
+
282
+ int original_stdout;
283
+ int read_end = rb_backup_stdout (&original_stdout);
284
+
285
+ man_mdoc (NULL, meta);
286
+
287
+ return rb_restore_stdout (original_stdout, read_end);
288
+ }
289
+
290
+ /**
291
+ * The result depends on <tt>struct mparse</tt>, which means this
292
+ * method must be called BEFORE the next +parse_file+ method calling.
293
+ */
294
+ static VALUE
295
+ rb_manmeta_m_man (VALUE self)
296
+ {
297
+ int original_stdout;
298
+ int read_end = rb_backup_stdout (&original_stdout);
299
+
300
+ VALUE parser = rb_iv_get (self, "@parser");
301
+ struct mparse *p = RTYPEDDATA_DATA (parser);
302
+ mparse_copy (p);
303
+
304
+ return rb_restore_stdout (original_stdout, read_end);
305
+ }
306
+
307
+ static VALUE
308
+ rb_mdocmeta_m_markdown (VALUE self)
309
+ {
310
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
311
+
312
+ int original_stdout;
313
+ int read_end = rb_backup_stdout (&original_stdout);
314
+
315
+ markdown_mdoc (NULL, meta);
316
+
317
+ return rb_restore_stdout (original_stdout, read_end);
318
+ }
319
+
320
+ static const rb_data_type_t rb_node_type;
321
+ static VALUE
322
+ rb_wrap_node (struct roff_node *node)
323
+ {
324
+ VALUE klass;
325
+ switch (node->type)
326
+ {
327
+ case ROFFT_ROOT:
328
+ klass = rb_cRootNode;
329
+ break;
330
+ case ROFFT_BLOCK:
331
+ klass = rb_cBlockNode;
332
+ break;
333
+ case ROFFT_HEAD:
334
+ klass = rb_cHeadNode;
335
+ break;
336
+ case ROFFT_BODY:
337
+ klass = rb_cBodyNode;
338
+ break;
339
+ case ROFFT_TAIL:
340
+ klass = rb_cTailNode;
341
+ break;
342
+ case ROFFT_ELEM:
343
+ klass = rb_cElemNode;
344
+ break;
345
+ case ROFFT_TEXT:
346
+ klass = rb_cTextNode;
347
+ break;
348
+ case ROFFT_COMMENT:
349
+ klass = rb_cCommentNode;
350
+ break;
351
+ case ROFFT_TBL:
352
+ klass = rb_cTBLNode;
353
+ break;
354
+ case ROFFT_EQN:
355
+ klass = rb_cEQNNode;
356
+ break;
357
+ }
358
+ return rb_data_typed_object_wrap (klass, node, &rb_node_type);
359
+ }
360
+
361
+ static VALUE
362
+ rb_meta_m_first_node (VALUE self)
363
+ {
364
+ struct roff_meta *meta = RTYPEDDATA_DATA (self);
365
+ return rb_wrap_node (meta->first);
366
+ }
367
+
368
+ /* roff node */
369
+
370
+ static void
371
+ rb_node_free (void *node)
372
+ {
373
+ (void)node;
374
+ }
375
+
376
+ static const rb_data_type_t rb_node_type
377
+ = { .wrap_struct_name = "mandoc node",
378
+ .function = { .dfree = rb_node_free },
379
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY };
380
+
381
+ static VALUE
382
+ rb_node_alloc (VALUE klass)
383
+ {
384
+ return rb_data_typed_object_wrap (klass, NULL, &rb_node_type);
385
+ }
386
+
387
+ static VALUE
388
+ rb_node_m_parent (VALUE self)
389
+ {
390
+ struct roff_node *node = RTYPEDDATA_DATA (self);
391
+ return node->parent ? rb_wrap_node (node->parent) : RUBY_Qnil;
392
+ }
393
+
394
+ static VALUE
395
+ rb_node_m_first_child (VALUE self)
396
+ {
397
+ struct roff_node *node = RTYPEDDATA_DATA (self);
398
+ return node->child ? rb_wrap_node (node->child) : RUBY_Qnil;
399
+ }
400
+
401
+ static VALUE
402
+ rb_node_m_last_child (VALUE self)
403
+ {
404
+ struct roff_node *node = RTYPEDDATA_DATA (self);
405
+ return node->last ? rb_wrap_node (node->last) : RUBY_Qnil;
406
+ }
407
+
408
+ static VALUE
409
+ rb_node_m_next_sibling (VALUE self)
410
+ {
411
+ struct roff_node *node = RTYPEDDATA_DATA (self);
412
+ return node->next ? rb_wrap_node (node->next) : RUBY_Qnil;
413
+ }
414
+
415
+ static VALUE
416
+ rb_node_m_prev_sibling (VALUE self)
417
+ {
418
+ struct roff_node *node = RTYPEDDATA_DATA (self);
419
+ return node->prev ? rb_wrap_node (node->prev) : RUBY_Qnil;
420
+ }
421
+
422
+ static VALUE
423
+ rb_node_m_head (VALUE self)
424
+ {
425
+ struct roff_node *node = RTYPEDDATA_DATA (self);
426
+ return node->head ? rb_wrap_node (node->head) : RUBY_Qnil;
427
+ }
428
+
429
+ static VALUE
430
+ rb_node_m_body (VALUE self)
431
+ {
432
+ struct roff_node *node = RTYPEDDATA_DATA (self);
433
+ return node->body ? rb_wrap_node (node->body) : RUBY_Qnil;
434
+ }
435
+
436
+ static VALUE
437
+ rb_node_m_tail (VALUE self)
438
+ {
439
+ struct roff_node *node = RTYPEDDATA_DATA (self);
440
+ return node->tail ? rb_wrap_node (node->tail) : RUBY_Qnil;
441
+ }
442
+
443
+ static VALUE
444
+ rb_node_m_text (VALUE self)
445
+ {
446
+ struct roff_node *node = RTYPEDDATA_DATA (self);
447
+ return node->string ? rb_str_new_cstr (node->string) : RUBY_Qnil;
448
+ }
449
+
450
+ static VALUE
451
+ rb_node_m_tag (VALUE self)
452
+ {
453
+ struct roff_node *node = RTYPEDDATA_DATA (self);
454
+ return node->string ? rb_str_new_cstr (node->tag) : RUBY_Qnil;
455
+ }
456
+
457
+ static VALUE
458
+ rb_node_m_line (VALUE self)
459
+ {
460
+ struct roff_node *node = RTYPEDDATA_DATA (self);
461
+ return rb_int2num_inline (node->line);
462
+ }
463
+
464
+ static VALUE
465
+ rb_node_m_column (VALUE self)
466
+ {
467
+ struct roff_node *node = RTYPEDDATA_DATA (self);
468
+ return rb_int2num_inline (node->pos);
469
+ }
470
+
471
+ static VALUE
472
+ rb_node_m_name (VALUE self)
473
+ {
474
+ struct roff_node *node = RTYPEDDATA_DATA (self);
475
+ return rb_usascii_str_new_cstr (roff_name[node->tok]);
476
+ }
477
+
478
+ RUBY_FUNC_EXPORTED void
479
+ Init_mandoc (void)
480
+ {
481
+ rb_mMandoc = rb_define_module ("Mandoc");
482
+
483
+ rb_cParser = rb_define_class_under (rb_mMandoc, "Parser", rb_cObject);
484
+ rb_define_alloc_func (rb_cParser, rb_parser_alloc);
485
+ rb_define_method (rb_cParser, "parse_file", rb_parser_m_parse_file, 1);
486
+
487
+ rb_cMeta = rb_define_class_under (rb_mMandoc, "Meta", rb_cObject);
488
+ rb_define_alloc_func (rb_cMeta, rb_meta_alloc);
489
+ rb_define_method (rb_cMeta, "deroff", rb_meta_m_deroff, 0);
490
+ rb_define_method (rb_cMeta, "first_node", rb_meta_m_first_node, 0);
491
+
492
+ rb_define_method (rb_cMeta, "section", rb_meta_m_section, 0);
493
+ rb_define_method (rb_cMeta, "volume", rb_meta_m_volume, 0);
494
+ rb_define_method (rb_cMeta, "os", rb_meta_m_os, 0);
495
+ rb_define_method (rb_cMeta, "arch", rb_meta_m_arch, 0);
496
+ rb_define_method (rb_cMeta, "title", rb_meta_m_title, 0);
497
+ rb_define_method (rb_cMeta, "name", rb_meta_m_name, 0);
498
+ rb_define_method (rb_cMeta, "date", rb_meta_m_date, 0);
499
+ rb_define_method (rb_cMeta, "so_target", rb_meta_m_so_target, 0);
500
+ rb_define_method (rb_cMeta, "has_body?", rb_meta_m_has_body, 0);
501
+
502
+ /* TODO: Converters for HTML, PDF, ASCII, UTF8, LOCALE, PS
503
+ (PostScript) are tricky, since it expects outdata (void*) of
504
+ struct outstate pointer. */
505
+
506
+ rb_cMdocMeta = rb_define_class_under (rb_mMandoc, "MdocMeta", rb_cMeta);
507
+ rb_define_method (rb_cMdocMeta, "markdown", rb_mdocmeta_m_markdown, 0);
508
+ rb_define_method (rb_cMdocMeta, "tree", rb_mdocmeta_m_tree, 0);
509
+ rb_define_method (rb_cMdocMeta, "man", rb_mdocmeta_m_man, 0);
510
+
511
+ rb_cManMeta = rb_define_class_under (rb_mMandoc, "ManMeta", rb_cMeta);
512
+ rb_define_method (rb_cManMeta, "tree", rb_manmeta_m_tree, 0);
513
+ rb_define_method (rb_cManMeta, "man", rb_manmeta_m_man, 0);
514
+
515
+ rb_cNode = rb_define_class_under (rb_mMandoc, "Node", rb_cObject);
516
+ rb_define_alloc_func (rb_cNode, rb_node_alloc);
517
+
518
+ rb_define_method (rb_cNode, "parent", rb_node_m_parent, 0);
519
+ rb_define_method (rb_cNode, "first_child", rb_node_m_first_child, 0);
520
+ rb_define_method (rb_cNode, "last_child", rb_node_m_last_child, 0);
521
+ rb_define_method (rb_cNode, "next_sibling", rb_node_m_next_sibling, 0);
522
+ rb_define_method (rb_cNode, "prev_sibling", rb_node_m_prev_sibling, 0);
523
+ rb_define_method (rb_cNode, "head", rb_node_m_head, 0);
524
+ rb_define_method (rb_cNode, "body", rb_node_m_body, 0);
525
+ rb_define_method (rb_cNode, "tail", rb_node_m_tail, 0);
526
+
527
+ rb_define_method (rb_cNode, "text", rb_node_m_text, 0);
528
+ rb_define_method (rb_cNode, "tag", rb_node_m_tag, 0);
529
+
530
+ rb_define_method (rb_cNode, "line", rb_node_m_line, 0);
531
+ rb_define_method (rb_cNode, "column", rb_node_m_column, 0);
532
+
533
+ rb_define_method (rb_cNode, "name", rb_node_m_name, 0);
534
+
535
+ rb_cRootNode = rb_define_class_under (rb_mMandoc, "RootNode", rb_cNode);
536
+ rb_cBlockNode = rb_define_class_under (rb_mMandoc, "BlockNode", rb_cNode);
537
+ rb_cHeadNode = rb_define_class_under (rb_mMandoc, "HeadNode", rb_cNode);
538
+ rb_cBodyNode = rb_define_class_under (rb_mMandoc, "BodyNode", rb_cNode);
539
+ rb_cTailNode = rb_define_class_under (rb_mMandoc, "TailNode", rb_cNode);
540
+ rb_cElemNode = rb_define_class_under (rb_mMandoc, "ElemNode", rb_cNode);
541
+ rb_cTextNode = rb_define_class_under (rb_mMandoc, "TextNode", rb_cNode);
542
+ rb_cCommentNode
543
+ = rb_define_class_under (rb_mMandoc, "CommentNode", rb_cNode);
544
+ rb_cTBLNode = rb_define_class_under (rb_mMandoc, "TBLNode", rb_cNode);
545
+ rb_cEQNNode = rb_define_class_under (rb_mMandoc, "EQNNode", rb_cNode);
546
+
547
+ rb_eError = rb_define_class_under (rb_mMandoc, "Error", rb_eStandardError);
548
+ }
@@ -0,0 +1,22 @@
1
+ /*
2
+ * Copyright (C) 2026 gemmaro
3
+ *
4
+ * This program is free software: you can redistribute it and/or modify
5
+ * it under the terms of the GNU General Public License as published by
6
+ * the Free Software Foundation, either version 3 of the License, or
7
+ * (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ * GNU General Public License for more details.
13
+ */
14
+
15
+ #ifndef RB_MANDOC_H
16
+ #define RB_MANDOC_H 1
17
+
18
+ #include <ruby.h>
19
+
20
+ RUBY_FUNC_EXPORTED void Init_mandoc(void);
21
+
22
+ #endif /* RB_MANDOC_H */
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # Copyright (C) 2026 gemmaro
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #++
16
+
17
+ module Mandoc
18
+ VERSION = "0.0.1"
19
+ end
data/lib/mandoc.rb ADDED
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # Copyright (C) 2026 gemmaro
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #++
16
+
17
+ require_relative "mandoc/version"
18
+ require "mandoc/mandoc"
19
+
20
+ module Mandoc
21
+ # This class doen't have +new+ method. Use Mandoc::Parser#open
22
+ # instead.
23
+ class File
24
+ private_class_method :new
25
+ end
26
+ end
@@ -0,0 +1,55 @@
1
+ $Id: LICENSE,v 1.22 2021/09/19 11:02:09 schwarze Exp $
2
+
3
+ With the exceptions noted below, all non-trivial files contained
4
+ in the mandoc toolkit are protected by the Copyright of the following
5
+ developers:
6
+
7
+ Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
8
+ Copyright (c) 2010-2021 Ingo Schwarze <schwarze@openbsd.org>
9
+ Copyright (c) 1999, 2004, 2017 Marc Espie <espie@openbsd.org>
10
+ Copyright (c) 2009, 2010, 2011, 2012 Joerg Sonnenberger <joerg@netbsd.org>
11
+ Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
12
+ Copyright (c) 2014 Baptiste Daroussin <bapt@freebsd.org>
13
+ Copyright (c) 2016 Ed Maste <emaste@freebsd.org>
14
+ Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
15
+ Copyright (c) 2017 Anthony Bentley <bentley@openbsd.org>
16
+ Copyright (c) 1998, 2004, 2010, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
17
+ Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
18
+ Copyright (c) 2004 Ted Unangst <tedu@openbsd.org>
19
+ Copyright (c) 1994 Christos Zoulas <christos@netbsd.org>
20
+ Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org>
21
+
22
+ See the individual files for information about who contributed
23
+ to which file during which years.
24
+
25
+
26
+ The mandoc distribution as a whole is distributed by its developers
27
+ under the following license:
28
+
29
+ Permission to use, copy, modify, and distribute this software for any
30
+ purpose with or without fee is hereby granted, provided that the above
31
+ copyright notice and this permission notice appear in all copies.
32
+
33
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
34
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
35
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
36
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
37
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
38
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
39
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
40
+
41
+
42
+ The following files included from outside sources are protected by
43
+ other people's Copyright and are distributed under various 2-clause
44
+ and 3-clause BSD licenses; see these individual files for details.
45
+
46
+ soelim.c, soelim.1:
47
+ Copyright (c) 2014 Baptiste Daroussin <bapt@freebsd.org>
48
+
49
+ compat_err.c, compat_fts.c, compat_fts.h,
50
+ compat_getsubopt.c, compat_strcasestr.c, compat_strsep.c,
51
+ man.1:
52
+ Copyright (c) 1989,1990,1993,1994 The Regents of the University of California
53
+
54
+ compat_stringlist.c, compat_stringlist.h:
55
+ Copyright (c) 1994 Christos Zoulas <christos@netbsd.org>