adlint 1.0.0

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 (465) hide show
  1. data/AUTHORS +27 -0
  2. data/COPYING +674 -0
  3. data/ChangeLog +820 -0
  4. data/INSTALL +78 -0
  5. data/MANIFEST +464 -0
  6. data/NEWS +38 -0
  7. data/README +74 -0
  8. data/Rakefile +167 -0
  9. data/TODO +29 -0
  10. data/bin/adlint +141 -0
  11. data/bin/adlint_chk +129 -0
  12. data/bin/adlint_cma +122 -0
  13. data/bin/adlint_sma +129 -0
  14. data/bin/adlintize +286 -0
  15. data/etc/conf.d/fallback/cinit.erb +11 -0
  16. data/etc/conf.d/fallback/traits.erb +216 -0
  17. data/etc/conf.d/i686-cygwin/cinit-gcc_4.3.4.erb +149 -0
  18. data/etc/conf.d/i686-cygwin/traits-gcc_4.3.4.erb +227 -0
  19. data/etc/conf.d/i686-devkit/cinit-gcc_4.5.2.erb +224 -0
  20. data/etc/conf.d/i686-devkit/traits-gcc_4.5.2.erb +226 -0
  21. data/etc/conf.d/i686-linux/cinit-gcc_4.5.1.erb +219 -0
  22. data/etc/conf.d/i686-linux/traits-gcc_4.5.1.erb +224 -0
  23. data/etc/conf.d/i686-mingw/cinit-gcc_4.6.1.erb +234 -0
  24. data/etc/conf.d/i686-mingw/traits-gcc_4.6.1.erb +226 -0
  25. data/etc/conf.d/noarch/GNUmakefile.erb +119 -0
  26. data/etc/conf.d/noarch/adlint_all_bat.erb +9 -0
  27. data/etc/conf.d/noarch/adlint_all_sh.erb +10 -0
  28. data/etc/conf.d/noarch/pinit.erb +11 -0
  29. data/etc/mesg.d/en_US/messages.yml +784 -0
  30. data/etc/mesg.d/ja_JP/messages.yml +784 -0
  31. data/lib/adlint/analyzer.rb +294 -0
  32. data/lib/adlint/c/branch.rb +251 -0
  33. data/lib/adlint/c/builtin.rb +92 -0
  34. data/lib/adlint/c/code.rb +490 -0
  35. data/lib/adlint/c/const.rb +465 -0
  36. data/lib/adlint/c/conv.rb +212 -0
  37. data/lib/adlint/c/ctrlexpr.rb +949 -0
  38. data/lib/adlint/c/domain.rb +7499 -0
  39. data/lib/adlint/c/environ.rb +133 -0
  40. data/lib/adlint/c/expr.rb +1725 -0
  41. data/lib/adlint/c/format.rb +3209 -0
  42. data/lib/adlint/c/interp.rb +1740 -0
  43. data/lib/adlint/c/lexer.rb +241 -0
  44. data/lib/adlint/c/mediator.rb +313 -0
  45. data/lib/adlint/c/message.rb +13597 -0
  46. data/lib/adlint/c/metric.rb +765 -0
  47. data/lib/adlint/c/object.rb +1018 -0
  48. data/lib/adlint/c/parser.rb +3800 -0
  49. data/lib/adlint/c/parser.y +2054 -0
  50. data/lib/adlint/c/phase.rb +712 -0
  51. data/lib/adlint/c/resolver.rb +270 -0
  52. data/lib/adlint/c/scanner.rb +248 -0
  53. data/lib/adlint/c/scope.rb +74 -0
  54. data/lib/adlint/c/syntax.rb +4279 -0
  55. data/lib/adlint/c/type.rb +7506 -0
  56. data/lib/adlint/c/util.rb +91 -0
  57. data/lib/adlint/c/value.rb +2310 -0
  58. data/lib/adlint/c.rb +56 -0
  59. data/lib/adlint/code.rb +500 -0
  60. data/lib/adlint/cpp/code.rb +189 -0
  61. data/lib/adlint/cpp/constexpr.rb +721 -0
  62. data/lib/adlint/cpp/constexpr.y +389 -0
  63. data/lib/adlint/cpp/eval.rb +1012 -0
  64. data/lib/adlint/cpp/lexer.rb +860 -0
  65. data/lib/adlint/cpp/macro.rb +637 -0
  66. data/lib/adlint/cpp/message.rb +992 -0
  67. data/lib/adlint/cpp/phase.rb +176 -0
  68. data/lib/adlint/cpp/scanner.rb +93 -0
  69. data/lib/adlint/cpp/source.rb +169 -0
  70. data/lib/adlint/cpp/subst.rb +300 -0
  71. data/lib/adlint/cpp/syntax.rb +1412 -0
  72. data/lib/adlint/cpp/util.rb +97 -0
  73. data/lib/adlint/cpp.rb +43 -0
  74. data/lib/adlint/driver.rb +147 -0
  75. data/lib/adlint/error.rb +179 -0
  76. data/lib/adlint/lang.rb +97 -0
  77. data/lib/adlint/ld/message.rb +259 -0
  78. data/lib/adlint/ld/metric.rb +57 -0
  79. data/lib/adlint/ld/object.rb +542 -0
  80. data/lib/adlint/ld/phase.rb +193 -0
  81. data/lib/adlint/ld/typedef.rb +109 -0
  82. data/lib/adlint/ld/util.rb +88 -0
  83. data/lib/adlint/ld.rb +37 -0
  84. data/lib/adlint/lexer.rb +293 -0
  85. data/lib/adlint/message.rb +368 -0
  86. data/lib/adlint/metric.rb +805 -0
  87. data/lib/adlint/monitor.rb +144 -0
  88. data/lib/adlint/phase.rb +90 -0
  89. data/lib/adlint/prelude.rb +314 -0
  90. data/lib/adlint/report.rb +617 -0
  91. data/lib/adlint/source.rb +155 -0
  92. data/lib/adlint/symbol.rb +127 -0
  93. data/lib/adlint/token.rb +215 -0
  94. data/lib/adlint/traits.rb +643 -0
  95. data/lib/adlint/util.rb +524 -0
  96. data/lib/adlint/version.rb +71 -0
  97. data/lib/adlint.rb +66 -0
  98. data/share/HEADER +45 -0
  99. data/share/demo/Makefile +110 -0
  100. data/share/demo/ambig_operator/ambig_operator.c +289 -0
  101. data/share/demo/arg_points_unset/arg_points_unset.c +37 -0
  102. data/share/demo/array_range/array_range.c +62 -0
  103. data/share/demo/bad_bitfields/bad_bitfields.c +74 -0
  104. data/share/demo/bad_brace/bad_brace.c +19 -0
  105. data/share/demo/bad_charset/abcde$.h +0 -0
  106. data/share/demo/bad_charset/bad_charset.c +22 -0
  107. data/share/demo/bad_comment/bad_comment.c +3 -0
  108. data/share/demo/bad_const/bad_const.c +19 -0
  109. data/share/demo/bad_conv/bad_conv.c +48 -0
  110. data/share/demo/bad_indent/bad_indent.c +50 -0
  111. data/share/demo/bad_init/bad_init.c +49 -0
  112. data/share/demo/bad_macro/bad_macro.c +97 -0
  113. data/share/demo/bitwise_expr/bitwise_expr.c +19 -0
  114. data/share/demo/call_by_value/call_by_value.c +26 -0
  115. data/share/demo/cross_ref/cross_ref.c +21 -0
  116. data/share/demo/dangling_else/dangling_else.c +20 -0
  117. data/share/demo/dead_code/dead_code.c +237 -0
  118. data/share/demo/deep_nest/deep_nest.c +57 -0
  119. data/share/demo/dense_switch/dense_switch.c +62 -0
  120. data/share/demo/direct_recur/direct_recur.c +15 -0
  121. data/share/demo/div_by_zero/div_by_zero.c +35 -0
  122. data/share/demo/dos_source/dos_source.c +7 -0
  123. data/share/demo/funptr_cast/funptr_cast.c +26 -0
  124. data/share/demo/goto_stmt/goto_stmt.c +19 -0
  125. data/share/demo/id_hiding/id_hiding.c +19 -0
  126. data/share/demo/ill_defined/ill_defined.c +13 -0
  127. data/share/demo/implicit_conv/implicit_conv.c +60 -0
  128. data/share/demo/implicit_int/implicit_int.c +14 -0
  129. data/share/demo/incomplete_type/incomplete_type.c +49 -0
  130. data/share/demo/indirect_recur/indirect_recur_1.c +14 -0
  131. data/share/demo/indirect_recur/indirect_recur_1.h +7 -0
  132. data/share/demo/indirect_recur/indirect_recur_2.c +12 -0
  133. data/share/demo/indirect_recur/indirect_recur_2.h +6 -0
  134. data/share/demo/indirect_recur/indirect_recur_3.c +6 -0
  135. data/share/demo/indirect_recur/indirect_recur_3.h +6 -0
  136. data/share/demo/indirect_recur/indirect_recur_4.c +25 -0
  137. data/share/demo/intro_demo/intro_demo.c +76 -0
  138. data/share/demo/intro_demo/intro_demo.h +12 -0
  139. data/share/demo/intro_demo/useless_header.h +5 -0
  140. data/share/demo/invalid_call/invalid_call.c +32 -0
  141. data/share/demo/kandr_fundef/kandr_fundef.c +10 -0
  142. data/share/demo/line_comment/line_comment.c +12 -0
  143. data/share/demo/local_decl/local_decl.c +9 -0
  144. data/share/demo/logical_trick/logical_trick.c +36 -0
  145. data/share/demo/long_sym/long_sym.c +5 -0
  146. data/share/demo/loop_var/loop_var.c +92 -0
  147. data/share/demo/malloc_or_die/malloc_or_die.c +43 -0
  148. data/share/demo/may_be_null/may_be_null.c +52 -0
  149. data/share/demo/may_be_null_arith/may_be_null_arith.c +15 -0
  150. data/share/demo/may_be_unset/may_be_unset.c +34 -0
  151. data/share/demo/mmapped_io/mmapped_io.c +23 -0
  152. data/share/demo/multi_break/multi_break.c +33 -0
  153. data/share/demo/multi_decl/multi_decl_1.c +17 -0
  154. data/share/demo/multi_decl/multi_decl_1.h +6 -0
  155. data/share/demo/multi_decl/multi_decl_2.c +13 -0
  156. data/share/demo/multi_decl/multi_decl_2.h +6 -0
  157. data/share/demo/multi_decl/multi_decl_3.c +22 -0
  158. data/share/demo/multi_def/multi_def_1.c +36 -0
  159. data/share/demo/multi_def/multi_def_1.h +6 -0
  160. data/share/demo/multi_def/multi_def_2.c +22 -0
  161. data/share/demo/multi_def/multi_def_2.h +6 -0
  162. data/share/demo/multi_def/multi_def_3.c +6 -0
  163. data/share/demo/multi_typedef/multi_typedef.c +11 -0
  164. data/share/demo/multi_typedef/multi_typedef_1.h +1 -0
  165. data/share/demo/multi_typedef/multi_typedef_2.h +1 -0
  166. data/share/demo/must_be_false/must_be_false.c +53 -0
  167. data/share/demo/must_be_null/must_be_null.c +13 -0
  168. data/share/demo/must_be_null_arith/must_be_null_arith.c +14 -0
  169. data/share/demo/must_be_true/must_be_true.c +21 -0
  170. data/share/demo/no_eof_nl/no_eof_nl.c +4 -0
  171. data/share/demo/no_void_arg/no_void_arg.c +14 -0
  172. data/share/demo/null_stmt/null_stmt.c +19 -0
  173. data/share/demo/octal_const/octal_const.c +20 -0
  174. data/share/demo/output_by_param/output_by_param.c +17 -0
  175. data/share/demo/overflow/overflow.c +74 -0
  176. data/share/demo/press_release/press_release.c +40 -0
  177. data/share/demo/retn_lvar_addr/retn_lvar_addr.c +47 -0
  178. data/share/demo/shift_expr/shift_expr.c +14 -0
  179. data/share/demo/should_be_typedef/should_be_typedef.c +51 -0
  180. data/share/demo/static_paths/static_paths.c +153 -0
  181. data/share/demo/static_vars/static_vars.c +39 -0
  182. data/share/demo/tag_hiding/tag_hiding.c +18 -0
  183. data/share/demo/tricky_incdec/tricky_incdec.c +12 -0
  184. data/share/demo/undefined_macro/undefined_macro.c +17 -0
  185. data/share/demo/uninit_vars/uninit_vars.c +28 -0
  186. data/share/demo/union_type/union_type.c +23 -0
  187. data/share/demo/unmatch_decl/unmatch_decl_1.c +12 -0
  188. data/share/demo/unmatch_decl/unmatch_decl_1.h +8 -0
  189. data/share/demo/unmatch_decl/unmatch_decl_2.c +10 -0
  190. data/share/demo/unmatch_decl/unmatch_decl_2.h +8 -0
  191. data/share/demo/unmatch_decl/unmatch_decl_3.c +7 -0
  192. data/share/demo/unmatch_paren_macro/unmatch_paren_macro.c +15 -0
  193. data/share/demo/unreachable/unreachable.c +34 -0
  194. data/share/demo/useless_exp_funs/useless_exp_funs_1.c +14 -0
  195. data/share/demo/useless_exp_funs/useless_exp_funs_1.h +1 -0
  196. data/share/demo/useless_exp_funs/useless_exp_funs_2.c +6 -0
  197. data/share/demo/useless_exp_vars/useless_export_1.c +8 -0
  198. data/share/demo/useless_exp_vars/useless_export_1.h +1 -0
  199. data/share/demo/useless_exp_vars/useless_export_2.c +7 -0
  200. data/share/demo/useless_expr/useless_expr.c +17 -0
  201. data/share/demo/useless_funs/useless_funs_1.c +21 -0
  202. data/share/demo/useless_funs/useless_funs_1.h +8 -0
  203. data/share/demo/useless_funs/useless_funs_2.c +6 -0
  204. data/share/demo/useless_header/useless_header.c +9 -0
  205. data/share/demo/useless_header/useless_header_1.h +12 -0
  206. data/share/demo/useless_header/useless_header_2.h +6 -0
  207. data/share/demo/useless_header/useless_header_3.h +9 -0
  208. data/share/demo/useless_header/useless_header_4.h +3 -0
  209. data/share/demo/useless_vars/useless_vars.c +17 -0
  210. data/share/demo/va_funcall/va_funcall.c +25 -0
  211. data/share/demo/various_fundef/various_fundef.c +36 -0
  212. data/share/demo/wchar_wstring/wchar_wstring.c +7 -0
  213. data/share/demo/wrap_around/wrap_around.c +38 -0
  214. data/share/doc/Makefile +16 -0
  215. data/share/doc/adlint_on_adqua.png +0 -0
  216. data/share/doc/adlint_on_eclipse_en.png +0 -0
  217. data/share/doc/adlint_on_eclipse_ja.png +0 -0
  218. data/share/doc/adlint_on_vim_en.png +0 -0
  219. data/share/doc/adlint_on_vim_ja.png +0 -0
  220. data/share/doc/developers_guide_ja.html +171 -0
  221. data/share/doc/developers_guide_ja.texi +87 -0
  222. data/share/doc/gen_mesg_sections.rb +39 -0
  223. data/share/doc/samples/GNUmakefile +162 -0
  224. data/share/doc/samples/adlint_traits.yml +238 -0
  225. data/share/doc/texinfo.css +22 -0
  226. data/share/doc/users_guide_en.html +39975 -0
  227. data/share/doc/users_guide_en.texi +32640 -0
  228. data/share/doc/users_guide_ja.html +40505 -0
  229. data/share/doc/users_guide_ja.texi +33189 -0
  230. data/share/logo/adlint-110.png +0 -0
  231. data/share/logo/adlint-524.png +0 -0
  232. data/share/logo/adlint.svg +4637 -0
  233. data/share/sample/README +6 -0
  234. data/share/sample/bison-2.5/adlint/GNUmakefile +170 -0
  235. data/share/sample/bison-2.5/adlint/adlint_traits.yml +225 -0
  236. data/share/sample/bison-2.5/adlint/lib/GNUmakefile +198 -0
  237. data/share/sample/bison-2.5/adlint/lib/adlint_cinit.h +228 -0
  238. data/share/sample/bison-2.5/adlint/lib/adlint_pinit.h +21 -0
  239. data/share/sample/bison-2.5/adlint/lib/adlint_traits.yml +238 -0
  240. data/share/sample/bison-2.5/adlint/src/GNUmakefile +166 -0
  241. data/share/sample/bison-2.5/adlint/src/adlint_cinit.h +228 -0
  242. data/share/sample/bison-2.5/adlint/src/adlint_pinit.h +21 -0
  243. data/share/sample/bison-2.5/adlint/src/adlint_traits.yml +239 -0
  244. data/share/sample/ctags-5.8/adlint/GNUmakefile +169 -0
  245. data/share/sample/ctags-5.8/adlint/adlint_cinit.h +219 -0
  246. data/share/sample/ctags-5.8/adlint/adlint_pinit.h +13 -0
  247. data/share/sample/ctags-5.8/adlint/adlint_traits.yml +225 -0
  248. data/share/sample/flex-2.5.35/adlint/GNUmakefile +140 -0
  249. data/share/sample/flex-2.5.35/adlint/adlint_cinit.h +219 -0
  250. data/share/sample/flex-2.5.35/adlint/adlint_pinit.h +14 -0
  251. data/share/sample/flex-2.5.35/adlint/adlint_traits.yml +225 -0
  252. data/share/sample/ruby-1.9.3-p0/adlint/GNUmakefile +314 -0
  253. data/share/sample/ruby-1.9.3-p0/adlint/adlint_traits.yml +225 -0
  254. data/share/sample/ruby-1.9.3-p0/adlint/core/GNUmakefile +204 -0
  255. data/share/sample/ruby-1.9.3-p0/adlint/core/adlint_cinit.h +228 -0
  256. data/share/sample/ruby-1.9.3-p0/adlint/core/adlint_pinit.h +28 -0
  257. data/share/sample/ruby-1.9.3-p0/adlint/core/adlint_traits.yml +240 -0
  258. data/share/sample/ruby-1.9.3-p0/adlint/enc/GNUmakefile +163 -0
  259. data/share/sample/ruby-1.9.3-p0/adlint/enc/adlint_cinit.h +228 -0
  260. data/share/sample/ruby-1.9.3-p0/adlint/enc/adlint_pinit.h +24 -0
  261. data/share/sample/ruby-1.9.3-p0/adlint/enc/adlint_traits.yml +240 -0
  262. data/share/sample/ruby-1.9.3-p0/adlint/enc-trans/GNUmakefile +149 -0
  263. data/share/sample/ruby-1.9.3-p0/adlint/enc-trans/adlint_cinit.h +228 -0
  264. data/share/sample/ruby-1.9.3-p0/adlint/enc-trans/adlint_pinit.h +24 -0
  265. data/share/sample/ruby-1.9.3-p0/adlint/enc-trans/adlint_traits.yml +240 -0
  266. data/share/sample/ruby-1.9.3-p0/adlint/ext-bigdecimal/GNUmakefile +131 -0
  267. data/share/sample/ruby-1.9.3-p0/adlint/ext-bigdecimal/adlint_cinit.h +228 -0
  268. data/share/sample/ruby-1.9.3-p0/adlint/ext-bigdecimal/adlint_pinit.h +24 -0
  269. data/share/sample/ruby-1.9.3-p0/adlint/ext-bigdecimal/adlint_traits.yml +241 -0
  270. data/share/sample/ruby-1.9.3-p0/adlint/ext-continuation/GNUmakefile +131 -0
  271. data/share/sample/ruby-1.9.3-p0/adlint/ext-continuation/adlint_cinit.h +228 -0
  272. data/share/sample/ruby-1.9.3-p0/adlint/ext-continuation/adlint_pinit.h +24 -0
  273. data/share/sample/ruby-1.9.3-p0/adlint/ext-continuation/adlint_traits.yml +241 -0
  274. data/share/sample/ruby-1.9.3-p0/adlint/ext-coverage/GNUmakefile +131 -0
  275. data/share/sample/ruby-1.9.3-p0/adlint/ext-coverage/adlint_cinit.h +228 -0
  276. data/share/sample/ruby-1.9.3-p0/adlint/ext-coverage/adlint_pinit.h +24 -0
  277. data/share/sample/ruby-1.9.3-p0/adlint/ext-coverage/adlint_traits.yml +241 -0
  278. data/share/sample/ruby-1.9.3-p0/adlint/ext-curses/GNUmakefile +131 -0
  279. data/share/sample/ruby-1.9.3-p0/adlint/ext-curses/adlint_cinit.h +228 -0
  280. data/share/sample/ruby-1.9.3-p0/adlint/ext-curses/adlint_pinit.h +24 -0
  281. data/share/sample/ruby-1.9.3-p0/adlint/ext-curses/adlint_traits.yml +241 -0
  282. data/share/sample/ruby-1.9.3-p0/adlint/ext-date/GNUmakefile +134 -0
  283. data/share/sample/ruby-1.9.3-p0/adlint/ext-date/adlint_cinit.h +228 -0
  284. data/share/sample/ruby-1.9.3-p0/adlint/ext-date/adlint_pinit.h +24 -0
  285. data/share/sample/ruby-1.9.3-p0/adlint/ext-date/adlint_traits.yml +241 -0
  286. data/share/sample/ruby-1.9.3-p0/adlint/ext-dbm/GNUmakefile +131 -0
  287. data/share/sample/ruby-1.9.3-p0/adlint/ext-dbm/adlint_cinit.h +228 -0
  288. data/share/sample/ruby-1.9.3-p0/adlint/ext-dbm/adlint_pinit.h +24 -0
  289. data/share/sample/ruby-1.9.3-p0/adlint/ext-dbm/adlint_traits.yml +241 -0
  290. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest/GNUmakefile +131 -0
  291. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest/adlint_cinit.h +228 -0
  292. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest/adlint_pinit.h +24 -0
  293. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest/adlint_traits.yml +241 -0
  294. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-bubblebabble/GNUmakefile +131 -0
  295. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-bubblebabble/adlint_cinit.h +228 -0
  296. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-bubblebabble/adlint_pinit.h +24 -0
  297. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-bubblebabble/adlint_traits.yml +242 -0
  298. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-md5/GNUmakefile +132 -0
  299. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-md5/adlint_cinit.h +228 -0
  300. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-md5/adlint_pinit.h +24 -0
  301. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-md5/adlint_traits.yml +242 -0
  302. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-rmd160/GNUmakefile +132 -0
  303. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-rmd160/adlint_cinit.h +228 -0
  304. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-rmd160/adlint_pinit.h +24 -0
  305. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-rmd160/adlint_traits.yml +242 -0
  306. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha1/GNUmakefile +132 -0
  307. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha1/adlint_cinit.h +228 -0
  308. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha1/adlint_pinit.h +24 -0
  309. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha1/adlint_traits.yml +242 -0
  310. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha2/GNUmakefile +132 -0
  311. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha2/adlint_cinit.h +228 -0
  312. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha2/adlint_pinit.h +24 -0
  313. data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha2/adlint_traits.yml +242 -0
  314. data/share/sample/ruby-1.9.3-p0/adlint/ext-dl/GNUmakefile +134 -0
  315. data/share/sample/ruby-1.9.3-p0/adlint/ext-dl/adlint_cinit.h +228 -0
  316. data/share/sample/ruby-1.9.3-p0/adlint/ext-dl/adlint_pinit.h +24 -0
  317. data/share/sample/ruby-1.9.3-p0/adlint/ext-dl/adlint_traits.yml +241 -0
  318. data/share/sample/ruby-1.9.3-p0/adlint/ext-dl-callback/GNUmakefile +140 -0
  319. data/share/sample/ruby-1.9.3-p0/adlint/ext-dl-callback/adlint_cinit.h +228 -0
  320. data/share/sample/ruby-1.9.3-p0/adlint/ext-dl-callback/adlint_pinit.h +24 -0
  321. data/share/sample/ruby-1.9.3-p0/adlint/ext-dl-callback/adlint_traits.yml +242 -0
  322. data/share/sample/ruby-1.9.3-p0/adlint/ext-etc/GNUmakefile +131 -0
  323. data/share/sample/ruby-1.9.3-p0/adlint/ext-etc/adlint_cinit.h +228 -0
  324. data/share/sample/ruby-1.9.3-p0/adlint/ext-etc/adlint_pinit.h +24 -0
  325. data/share/sample/ruby-1.9.3-p0/adlint/ext-etc/adlint_traits.yml +241 -0
  326. data/share/sample/ruby-1.9.3-p0/adlint/ext-fcntl/GNUmakefile +131 -0
  327. data/share/sample/ruby-1.9.3-p0/adlint/ext-fcntl/adlint_cinit.h +228 -0
  328. data/share/sample/ruby-1.9.3-p0/adlint/ext-fcntl/adlint_pinit.h +24 -0
  329. data/share/sample/ruby-1.9.3-p0/adlint/ext-fcntl/adlint_traits.yml +241 -0
  330. data/share/sample/ruby-1.9.3-p0/adlint/ext-fiber/GNUmakefile +131 -0
  331. data/share/sample/ruby-1.9.3-p0/adlint/ext-fiber/adlint_cinit.h +228 -0
  332. data/share/sample/ruby-1.9.3-p0/adlint/ext-fiber/adlint_pinit.h +24 -0
  333. data/share/sample/ruby-1.9.3-p0/adlint/ext-fiber/adlint_traits.yml +241 -0
  334. data/share/sample/ruby-1.9.3-p0/adlint/ext-fiddle/GNUmakefile +134 -0
  335. data/share/sample/ruby-1.9.3-p0/adlint/ext-fiddle/adlint_cinit.h +228 -0
  336. data/share/sample/ruby-1.9.3-p0/adlint/ext-fiddle/adlint_pinit.h +24 -0
  337. data/share/sample/ruby-1.9.3-p0/adlint/ext-fiddle/adlint_traits.yml +242 -0
  338. data/share/sample/ruby-1.9.3-p0/adlint/ext-gdbm/GNUmakefile +131 -0
  339. data/share/sample/ruby-1.9.3-p0/adlint/ext-gdbm/adlint_cinit.h +228 -0
  340. data/share/sample/ruby-1.9.3-p0/adlint/ext-gdbm/adlint_pinit.h +24 -0
  341. data/share/sample/ruby-1.9.3-p0/adlint/ext-gdbm/adlint_traits.yml +241 -0
  342. data/share/sample/ruby-1.9.3-p0/adlint/ext-iconv/GNUmakefile +131 -0
  343. data/share/sample/ruby-1.9.3-p0/adlint/ext-iconv/adlint_cinit.h +228 -0
  344. data/share/sample/ruby-1.9.3-p0/adlint/ext-iconv/adlint_pinit.h +24 -0
  345. data/share/sample/ruby-1.9.3-p0/adlint/ext-iconv/adlint_traits.yml +241 -0
  346. data/share/sample/ruby-1.9.3-p0/adlint/ext-io-console/GNUmakefile +131 -0
  347. data/share/sample/ruby-1.9.3-p0/adlint/ext-io-console/adlint_cinit.h +228 -0
  348. data/share/sample/ruby-1.9.3-p0/adlint/ext-io-console/adlint_pinit.h +24 -0
  349. data/share/sample/ruby-1.9.3-p0/adlint/ext-io-console/adlint_traits.yml +241 -0
  350. data/share/sample/ruby-1.9.3-p0/adlint/ext-io-nonblock/GNUmakefile +131 -0
  351. data/share/sample/ruby-1.9.3-p0/adlint/ext-io-nonblock/adlint_cinit.h +228 -0
  352. data/share/sample/ruby-1.9.3-p0/adlint/ext-io-nonblock/adlint_pinit.h +24 -0
  353. data/share/sample/ruby-1.9.3-p0/adlint/ext-io-nonblock/adlint_traits.yml +241 -0
  354. data/share/sample/ruby-1.9.3-p0/adlint/ext-io-wait/GNUmakefile +131 -0
  355. data/share/sample/ruby-1.9.3-p0/adlint/ext-io-wait/adlint_cinit.h +228 -0
  356. data/share/sample/ruby-1.9.3-p0/adlint/ext-io-wait/adlint_pinit.h +24 -0
  357. data/share/sample/ruby-1.9.3-p0/adlint/ext-io-wait/adlint_traits.yml +241 -0
  358. data/share/sample/ruby-1.9.3-p0/adlint/ext-json-generator/GNUmakefile +131 -0
  359. data/share/sample/ruby-1.9.3-p0/adlint/ext-json-generator/adlint_cinit.h +228 -0
  360. data/share/sample/ruby-1.9.3-p0/adlint/ext-json-generator/adlint_pinit.h +24 -0
  361. data/share/sample/ruby-1.9.3-p0/adlint/ext-json-generator/adlint_traits.yml +241 -0
  362. data/share/sample/ruby-1.9.3-p0/adlint/ext-json-parser/GNUmakefile +131 -0
  363. data/share/sample/ruby-1.9.3-p0/adlint/ext-json-parser/adlint_cinit.h +228 -0
  364. data/share/sample/ruby-1.9.3-p0/adlint/ext-json-parser/adlint_pinit.h +24 -0
  365. data/share/sample/ruby-1.9.3-p0/adlint/ext-json-parser/adlint_traits.yml +241 -0
  366. data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-complex/GNUmakefile +131 -0
  367. data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-complex/adlint_cinit.h +228 -0
  368. data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-complex/adlint_pinit.h +24 -0
  369. data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-complex/adlint_traits.yml +241 -0
  370. data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-rational/GNUmakefile +131 -0
  371. data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-rational/adlint_cinit.h +228 -0
  372. data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-rational/adlint_pinit.h +24 -0
  373. data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-rational/adlint_traits.yml +241 -0
  374. data/share/sample/ruby-1.9.3-p0/adlint/ext-nkf/GNUmakefile +131 -0
  375. data/share/sample/ruby-1.9.3-p0/adlint/ext-nkf/adlint_cinit.h +228 -0
  376. data/share/sample/ruby-1.9.3-p0/adlint/ext-nkf/adlint_pinit.h +24 -0
  377. data/share/sample/ruby-1.9.3-p0/adlint/ext-nkf/adlint_traits.yml +241 -0
  378. data/share/sample/ruby-1.9.3-p0/adlint/ext-openssl/GNUmakefile +162 -0
  379. data/share/sample/ruby-1.9.3-p0/adlint/ext-openssl/adlint_cinit.h +228 -0
  380. data/share/sample/ruby-1.9.3-p0/adlint/ext-openssl/adlint_pinit.h +24 -0
  381. data/share/sample/ruby-1.9.3-p0/adlint/ext-openssl/adlint_traits.yml +241 -0
  382. data/share/sample/ruby-1.9.3-p0/adlint/ext-pathname/GNUmakefile +131 -0
  383. data/share/sample/ruby-1.9.3-p0/adlint/ext-pathname/adlint_cinit.h +228 -0
  384. data/share/sample/ruby-1.9.3-p0/adlint/ext-pathname/adlint_pinit.h +24 -0
  385. data/share/sample/ruby-1.9.3-p0/adlint/ext-pathname/adlint_traits.yml +241 -0
  386. data/share/sample/ruby-1.9.3-p0/adlint/ext-psych/GNUmakefile +135 -0
  387. data/share/sample/ruby-1.9.3-p0/adlint/ext-psych/adlint_cinit.h +228 -0
  388. data/share/sample/ruby-1.9.3-p0/adlint/ext-psych/adlint_pinit.h +24 -0
  389. data/share/sample/ruby-1.9.3-p0/adlint/ext-psych/adlint_traits.yml +241 -0
  390. data/share/sample/ruby-1.9.3-p0/adlint/ext-pty/GNUmakefile +131 -0
  391. data/share/sample/ruby-1.9.3-p0/adlint/ext-pty/adlint_cinit.h +228 -0
  392. data/share/sample/ruby-1.9.3-p0/adlint/ext-pty/adlint_pinit.h +24 -0
  393. data/share/sample/ruby-1.9.3-p0/adlint/ext-pty/adlint_traits.yml +241 -0
  394. data/share/sample/ruby-1.9.3-p0/adlint/ext-racc-cparse/GNUmakefile +131 -0
  395. data/share/sample/ruby-1.9.3-p0/adlint/ext-racc-cparse/adlint_cinit.h +228 -0
  396. data/share/sample/ruby-1.9.3-p0/adlint/ext-racc-cparse/adlint_pinit.h +24 -0
  397. data/share/sample/ruby-1.9.3-p0/adlint/ext-racc-cparse/adlint_traits.yml +241 -0
  398. data/share/sample/ruby-1.9.3-p0/adlint/ext-readline/GNUmakefile +131 -0
  399. data/share/sample/ruby-1.9.3-p0/adlint/ext-readline/adlint_cinit.h +228 -0
  400. data/share/sample/ruby-1.9.3-p0/adlint/ext-readline/adlint_pinit.h +24 -0
  401. data/share/sample/ruby-1.9.3-p0/adlint/ext-readline/adlint_traits.yml +241 -0
  402. data/share/sample/ruby-1.9.3-p0/adlint/ext-ripper/GNUmakefile +131 -0
  403. data/share/sample/ruby-1.9.3-p0/adlint/ext-ripper/adlint_cinit.h +228 -0
  404. data/share/sample/ruby-1.9.3-p0/adlint/ext-ripper/adlint_pinit.h +24 -0
  405. data/share/sample/ruby-1.9.3-p0/adlint/ext-ripper/adlint_traits.yml +241 -0
  406. data/share/sample/ruby-1.9.3-p0/adlint/ext-sdbm/GNUmakefile +132 -0
  407. data/share/sample/ruby-1.9.3-p0/adlint/ext-sdbm/adlint_cinit.h +228 -0
  408. data/share/sample/ruby-1.9.3-p0/adlint/ext-sdbm/adlint_pinit.h +24 -0
  409. data/share/sample/ruby-1.9.3-p0/adlint/ext-sdbm/adlint_traits.yml +241 -0
  410. data/share/sample/ruby-1.9.3-p0/adlint/ext-socket/GNUmakefile +144 -0
  411. data/share/sample/ruby-1.9.3-p0/adlint/ext-socket/adlint_cinit.h +228 -0
  412. data/share/sample/ruby-1.9.3-p0/adlint/ext-socket/adlint_pinit.h +24 -0
  413. data/share/sample/ruby-1.9.3-p0/adlint/ext-socket/adlint_traits.yml +241 -0
  414. data/share/sample/ruby-1.9.3-p0/adlint/ext-stringio/GNUmakefile +131 -0
  415. data/share/sample/ruby-1.9.3-p0/adlint/ext-stringio/adlint_cinit.h +228 -0
  416. data/share/sample/ruby-1.9.3-p0/adlint/ext-stringio/adlint_pinit.h +24 -0
  417. data/share/sample/ruby-1.9.3-p0/adlint/ext-stringio/adlint_traits.yml +241 -0
  418. data/share/sample/ruby-1.9.3-p0/adlint/ext-strscan/GNUmakefile +131 -0
  419. data/share/sample/ruby-1.9.3-p0/adlint/ext-strscan/adlint_cinit.h +228 -0
  420. data/share/sample/ruby-1.9.3-p0/adlint/ext-strscan/adlint_pinit.h +24 -0
  421. data/share/sample/ruby-1.9.3-p0/adlint/ext-strscan/adlint_traits.yml +241 -0
  422. data/share/sample/ruby-1.9.3-p0/adlint/ext-syck/GNUmakefile +140 -0
  423. data/share/sample/ruby-1.9.3-p0/adlint/ext-syck/adlint_cinit.h +228 -0
  424. data/share/sample/ruby-1.9.3-p0/adlint/ext-syck/adlint_pinit.h +24 -0
  425. data/share/sample/ruby-1.9.3-p0/adlint/ext-syck/adlint_traits.yml +241 -0
  426. data/share/sample/ruby-1.9.3-p0/adlint/ext-syslog/GNUmakefile +131 -0
  427. data/share/sample/ruby-1.9.3-p0/adlint/ext-syslog/adlint_cinit.h +228 -0
  428. data/share/sample/ruby-1.9.3-p0/adlint/ext-syslog/adlint_pinit.h +24 -0
  429. data/share/sample/ruby-1.9.3-p0/adlint/ext-syslog/adlint_traits.yml +241 -0
  430. data/share/sample/ruby-1.9.3-p0/adlint/ext-zlib/GNUmakefile +131 -0
  431. data/share/sample/ruby-1.9.3-p0/adlint/ext-zlib/adlint_cinit.h +228 -0
  432. data/share/sample/ruby-1.9.3-p0/adlint/ext-zlib/adlint_pinit.h +24 -0
  433. data/share/sample/ruby-1.9.3-p0/adlint/ext-zlib/adlint_traits.yml +241 -0
  434. data/share/sample/screen-4.0.3/adlint/GNUmakefile +162 -0
  435. data/share/sample/screen-4.0.3/adlint/adlint_cinit.h +228 -0
  436. data/share/sample/screen-4.0.3/adlint/adlint_pinit.h +21 -0
  437. data/share/sample/screen-4.0.3/adlint/adlint_traits.yml +238 -0
  438. data/share/sample/vim-7.3/adlint/vim/GNUmakefile +185 -0
  439. data/share/sample/vim-7.3/adlint/vim/adlint_cinit.h +228 -0
  440. data/share/sample/vim-7.3/adlint/vim/adlint_pinit.h +25 -0
  441. data/share/sample/vim-7.3/adlint/vim/adlint_traits.yml +250 -0
  442. data/share/sample/vim-7.3/adlint/xxd/GNUmakefile +131 -0
  443. data/share/sample/vim-7.3/adlint/xxd/adlint_cinit.h +228 -0
  444. data/share/sample/vim-7.3/adlint/xxd/adlint_pinit.h +24 -0
  445. data/share/sample/vim-7.3/adlint/xxd/adlint_traits.yml +237 -0
  446. data/share/sample/zsh-4.3.15/adlint/GNUmakefile +146 -0
  447. data/share/sample/zsh-4.3.15/adlint/adlint_traits.yml +225 -0
  448. data/share/sample/zsh-4.3.15/adlint/builtins/GNUmakefile +132 -0
  449. data/share/sample/zsh-4.3.15/adlint/builtins/adlint_cinit.h +228 -0
  450. data/share/sample/zsh-4.3.15/adlint/builtins/adlint_pinit.h +24 -0
  451. data/share/sample/zsh-4.3.15/adlint/builtins/adlint_traits.yml +240 -0
  452. data/share/sample/zsh-4.3.15/adlint/core/GNUmakefile +153 -0
  453. data/share/sample/zsh-4.3.15/adlint/core/adlint_cinit.h +228 -0
  454. data/share/sample/zsh-4.3.15/adlint/core/adlint_pinit.h +23 -0
  455. data/share/sample/zsh-4.3.15/adlint/core/adlint_traits.yml +239 -0
  456. data/share/sample/zsh-4.3.15/adlint/modules/GNUmakefile +147 -0
  457. data/share/sample/zsh-4.3.15/adlint/modules/adlint_cinit.h +228 -0
  458. data/share/sample/zsh-4.3.15/adlint/modules/adlint_pinit.h +24 -0
  459. data/share/sample/zsh-4.3.15/adlint/modules/adlint_traits.yml +240 -0
  460. data/share/sample/zsh-4.3.15/adlint/zle/GNUmakefile +144 -0
  461. data/share/sample/zsh-4.3.15/adlint/zle/adlint_cinit.h +228 -0
  462. data/share/sample/zsh-4.3.15/adlint/zle/adlint_pinit.h +24 -0
  463. data/share/sample/zsh-4.3.15/adlint/zle/adlint_traits.yml +239 -0
  464. data/spec/MUST_WRITE_SPECS_WITH_RSPEC +0 -0
  465. metadata +532 -0
@@ -0,0 +1,3209 @@
1
+ # Format of the formatted input/output functions.
2
+ #
3
+ # Author:: Yutaka Yanoh <mailto:yanoh@users.sourceforge.net>
4
+ # Copyright:: Copyright (C) 2010-2012, OGIS-RI Co.,Ltd.
5
+ # License:: GPLv3+: GNU General Public License version 3 or later
6
+ #
7
+ # Owner:: Yutaka Yanoh <mailto:yanoh@users.sourceforge.net>
8
+
9
+ #--
10
+ # ___ ____ __ ___ _________
11
+ # / | / _ |/ / / / | / /__ __/ Source Code Static Analyzer
12
+ # / /| | / / / / / / / |/ / / / AdLint - Advanced Lint
13
+ # / __ |/ /_/ / /___/ / /| / / /
14
+ # /_/ |_|_____/_____/_/_/ |_/ /_/ Copyright (C) 2010-2012, OGIS-RI Co.,Ltd.
15
+ #
16
+ # This file is part of AdLint.
17
+ #
18
+ # AdLint is free software: you can redistribute it and/or modify it under the
19
+ # terms of the GNU General Public License as published by the Free Software
20
+ # Foundation, either version 3 of the License, or (at your option) any later
21
+ # version.
22
+ #
23
+ # AdLint is distributed in the hope that it will be useful, but WITHOUT ANY
24
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
25
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
26
+ #
27
+ # You should have received a copy of the GNU General Public License along with
28
+ # AdLint. If not, see <http://www.gnu.org/licenses/>.
29
+ #
30
+ #++
31
+
32
+ require "adlint/c/mediator"
33
+
34
+ module AdLint #:nodoc:
35
+ module C #:nodoc:
36
+
37
+ class PrintfFormat
38
+ def initialize(format_str, location, trailing_args, environment)
39
+ @location = location
40
+ @directives = create_directives(format_str, trailing_args, environment)
41
+ @extra_arguments = trailing_args
42
+ end
43
+
44
+ attr_reader :location
45
+ attr_reader :directives
46
+ attr_reader :extra_arguments
47
+
48
+ def conversion_specifiers
49
+ @directives.select { |directive| directive.conversion_specifier? }
50
+ end
51
+
52
+ def min_length
53
+ @directives.reduce(0) { |len, directive| len + directive.min_length }
54
+ end
55
+
56
+ def max_length
57
+ @directives.reduce(0) { |len, directive| len + directive.max_length }
58
+ end
59
+
60
+ private
61
+ def create_directives(format_str, trailing_args, environment)
62
+ directives = []
63
+ str = format_str.dup
64
+ until str.empty?
65
+ directives.push(Directive.guess(str, trailing_args, environment))
66
+ end
67
+ directives
68
+ end
69
+
70
+ # == DESCRIPTION
71
+ # === Directive class hierarchy
72
+ # Directive
73
+ # <--- Ordinary
74
+ # <--- ConversionSpecifier
75
+ # <--- CompleteConversionSpecifier
76
+ # <--- NumberConversionSpecifier
77
+ # <--- Conversion_d
78
+ # <--- Conversion_i
79
+ # <--- Conversion_o
80
+ # <--- Conversion_u
81
+ # <--- Conversion_x
82
+ # <--- Conversion_X
83
+ # <--- Conversion_f
84
+ # <--- Conversion_F
85
+ # <--- Conversion_e
86
+ # <--- Conversion_E
87
+ # <--- Conversion_g
88
+ # <--- Conversion_G
89
+ # <--- Conversion_a
90
+ # <--- Conversion_A
91
+ # <--- Conversion_p
92
+ # <--- CharacterConversionSpecifier
93
+ # <--- Conversion_c
94
+ # <--- StringConversionSpecifier
95
+ # <--- Conversion_s
96
+ # <--- Conversion_n
97
+ # <--- Conversion_percent
98
+ # <--- UndefinedConversionSpecifier
99
+ # <--- IncompleteConversionSpecifier
100
+ class Directive
101
+ def self.guess(format_str, trailing_args, environ)
102
+ try_to_create_ordinary(format_str) or
103
+ try_to_create_conversion_specifier(format_str, trailing_args, environ)
104
+ end
105
+
106
+ def initialize(format, consume_args)
107
+ @format = format
108
+ @consume_arguments = consume_args
109
+ end
110
+
111
+ attr_reader :format
112
+
113
+ def ordinary?
114
+ !conversion_specifier?
115
+ end
116
+
117
+ def conversion_specifier?
118
+ subclass_responsibility
119
+ end
120
+
121
+ def consume_arguments?
122
+ @consume_arguments
123
+ end
124
+
125
+ # === DESCRIPTION
126
+ # Checks whether types of arguments match this directive.
127
+ #
128
+ # === RETURN VALUE
129
+ # Boolean -- True if types of arguments match this directive.
130
+ def acceptable?
131
+ subclass_responsibility
132
+ end
133
+
134
+ # === DESCRIPTION
135
+ # Checks whether the format string of this directive is the ISO C99
136
+ # compliant.
137
+ #
138
+ # === RETURN VALUE
139
+ # Boolean -- True if the format string is wellformed.
140
+ def wellformed?
141
+ subclass_responsibility
142
+ end
143
+
144
+ def illformed?
145
+ !wellformed?
146
+ end
147
+
148
+ def complete?
149
+ subclass_responsibility
150
+ end
151
+
152
+ def incomplete?
153
+ !complete?
154
+ end
155
+
156
+ def undefined?
157
+ subclass_responsibility
158
+ end
159
+
160
+ def valid_flags?
161
+ subclass_responsibility
162
+ end
163
+
164
+ def valid_field_width?
165
+ subclass_responsibility
166
+ end
167
+
168
+ def valid_precision?
169
+ subclass_responsibility
170
+ end
171
+
172
+ def valid_length_modifier?
173
+ subclass_responsibility
174
+ end
175
+
176
+ def valid_conversion_specifier_character?
177
+ subclass_responsibility
178
+ end
179
+
180
+ def min_length
181
+ subclass_responsibility
182
+ end
183
+
184
+ def max_length
185
+ subclass_responsibility
186
+ end
187
+
188
+ def flags
189
+ subclass_responsibility
190
+ end
191
+
192
+ def field_width
193
+ subclass_responsibility
194
+ end
195
+
196
+ def precision
197
+ subclass_responsibility
198
+ end
199
+
200
+ def length_modifier
201
+ subclass_responsibility
202
+ end
203
+
204
+ def conversion_specifier_character
205
+ subclass_responsibility
206
+ end
207
+
208
+ def self.try_to_create_ordinary(format_str)
209
+ (format = Ordinary.scan(format_str)) ? Ordinary.new(format) : nil
210
+ end
211
+ private_class_method :try_to_create_ordinary
212
+
213
+ def self.try_to_create_conversion_specifier(format_str,
214
+ trailing_args, environment)
215
+ format, flags, field_width, precision, length_modifier, cs_char =
216
+ ConversionSpecifier.scan(format_str)
217
+
218
+ case
219
+ when cs_char.nil?
220
+ IncompleteConversionSpecifier.new(format, flags, field_width,
221
+ precision, length_modifier)
222
+ when cs_class = CONVERSION_SPECIFIER_TBL[cs_char]
223
+ cs_class.new(format, trailing_args, environment,
224
+ flags, field_width, precision, length_modifier, cs_char)
225
+ else
226
+ UndefinedConversionSpecifier.new(format, flags, field_width,
227
+ precision, length_modifier, cs_char)
228
+ end
229
+ end
230
+ private_class_method :try_to_create_conversion_specifier
231
+ end
232
+ private_constant :Directive
233
+
234
+ class Ordinary < Directive
235
+ def self.scan(format_str)
236
+ # NOTE: The ISO C99 standard saids;
237
+ #
238
+ # 7.19.6.1 The fprintf function
239
+ #
240
+ # 3 The format shall be a multibyte character sequence, beginning and
241
+ # ending in its initial shift state. The format is composed of zero
242
+ # or more directives: ordinary multibyte characters (not %), which
243
+ # are copied unchanged to the output stream; and conversion
244
+ # specifiers, each of which results in fetching zero or more
245
+ # subsequent arguments, converting them, if applicable, according to
246
+ # the corresponding conversion specifier, and then writing the result
247
+ # to the output stream.
248
+ format_str.slice!(/\A[^%]+/)
249
+ end
250
+
251
+ def initialize(format)
252
+ super(format, false)
253
+ end
254
+
255
+ def conversion_specifier?
256
+ false
257
+ end
258
+
259
+ # === DESCRIPTION
260
+ # Checks whether types of arguments match this directive.
261
+ #
262
+ # === RETURN VALUE
263
+ # Boolean -- True if types of arguments match this directive.
264
+ def acceptable?
265
+ true
266
+ end
267
+
268
+ # === DESCRIPTION
269
+ # Checks whether the format string of this directive is the ISO C99
270
+ # compliant.
271
+ #
272
+ # === RETURN VALUE
273
+ # Boolean -- True if the format string is wellformed.
274
+ def wellformed?
275
+ true
276
+ end
277
+
278
+ def complete?
279
+ true
280
+ end
281
+
282
+ def undefined?
283
+ false
284
+ end
285
+
286
+ def valid_flags?
287
+ false
288
+ end
289
+
290
+ def valid_field_width?
291
+ false
292
+ end
293
+
294
+ def valid_precision?
295
+ false
296
+ end
297
+
298
+ def valid_length_modifier?
299
+ false
300
+ end
301
+
302
+ def valid_conversion_specifier_character?
303
+ false
304
+ end
305
+
306
+ def min_length
307
+ format.bytes.count
308
+ end
309
+
310
+ def max_length
311
+ min_length
312
+ end
313
+
314
+ def flags
315
+ nil
316
+ end
317
+
318
+ def field_width
319
+ nil
320
+ end
321
+
322
+ def precision
323
+ nil
324
+ end
325
+
326
+ def length_modifier
327
+ nil
328
+ end
329
+
330
+ def conversion_specifier_character
331
+ nil
332
+ end
333
+ end
334
+ private_constant :Ordinary
335
+
336
+ class ConversionSpecifier < Directive
337
+ include TypeTableMediator
338
+ include MemoryPoolMediator
339
+
340
+ def self.scan(format_str)
341
+ # NOTE: The ISO C99 standard saids;
342
+ #
343
+ # 7.19.6.1 The fprintf function
344
+ #
345
+ # 4 Each conversion specification is introduced by the character %.
346
+ # After the %, the following appear in sequence:
347
+ #
348
+ # -- Zero or more flags (in any order) that modify the meaning of the
349
+ # conversion specification.
350
+ # -- An optional minimum field width. If the converted value has
351
+ # fewer characters than the field width, it is padded with spaces
352
+ # (by default) on the left (or right, if the left adjustment flag,
353
+ # described later, has been given) to the field width. The field
354
+ # width takes the form of an asterisk * (described later) or a
355
+ # nonnegative decimal integer.
356
+ # -- An optional precision that gives the minimum number of digits to
357
+ # appear for the d, i, o, u, x, and X conversions, the number of
358
+ # digits to appear after the decimal-point character for a, A, e,
359
+ # E, f, and F conversions, the maximum number of significant
360
+ # digits for the g and G conversions, or the maximum number of
361
+ # bytes to be written for s conversions. The precision takes the
362
+ # form of a period (.) followed either by an asterisk * (described
363
+ # later) or by an optional decimal interger; if only the period is
364
+ # specified, the precision is taken as zero. If a precision
365
+ # appears with any other conversion specifier, the behavior is
366
+ # undefined.
367
+ # -- An optional length modifier that specifies the size of the
368
+ # argument.
369
+ # -- A conversion specifier character that specifies the type of
370
+ # conversion to be applied.
371
+
372
+ if header = format_str.slice!(/\A%/)
373
+ scanned = header
374
+ else
375
+ return nil, nil, nil, nil, nil, nil
376
+ end
377
+
378
+ if flags = format_str.slice!(/\A#{flags_re}/)
379
+ scanned += flags
380
+ end
381
+
382
+ if field_width = format_str.slice!(/\A#{field_width_re}/)
383
+ scanned += field_width
384
+ end
385
+
386
+ if precision = format_str.slice!(/\A#{precision_re}/)
387
+ scanned += precision
388
+ end
389
+
390
+ if length_modifier = format_str.slice!(/\A#{length_modifier_re}/)
391
+ scanned += length_modifier
392
+ end
393
+
394
+ if cs_char = format_str.slice!(/\A#{cs_char_re}/)
395
+ scanned += cs_char
396
+ else
397
+ # NOTE: If no valid conversion specifier character, force to scan
398
+ # the heading 1 character as a conversion specifier character.
399
+ if cs_char = format_str.slice!(/\A[a-z]/i)
400
+ scanned += cs_char
401
+ end
402
+ end
403
+
404
+ return scanned, flags, field_width, precision, length_modifier, cs_char
405
+ end
406
+
407
+ def initialize(format, trailing_args, environment, consume_args,
408
+ flags, field_width, precision, length_modifier,
409
+ conversion_specifier_character)
410
+ super(format, consume_args)
411
+
412
+ @flags = flags
413
+ @field_width = field_width
414
+ @precision = precision
415
+ @length_modifier = length_modifier
416
+ @conversion_specifier_character = conversion_specifier_character
417
+
418
+ if consume_arguments? && @field_width == "*"
419
+ @field_width_argument = trailing_args.shift
420
+ else
421
+ @field_width_argument = nil
422
+ end
423
+
424
+ if consume_arguments? && @precision == ".*"
425
+ @precision_argument = trailing_args.shift
426
+ else
427
+ @precision_argument = nil
428
+ end
429
+
430
+ if consume_arguments?
431
+ @conversion_argument = trailing_args.shift
432
+ else
433
+ @conversion_argument = nil
434
+ end
435
+
436
+ @environment = environment
437
+ end
438
+
439
+ def conversion_specifier?
440
+ true
441
+ end
442
+
443
+ def undefined?
444
+ false
445
+ end
446
+
447
+ attr_reader :flags
448
+ attr_reader :field_width
449
+ attr_reader :precision
450
+ attr_reader :length_modifier
451
+ attr_reader :conversion_specifier_character
452
+ attr_reader :field_width_argument
453
+ attr_reader :precision_argument
454
+ attr_reader :conversion_argument
455
+
456
+ def field_width_value
457
+ case @field_width
458
+ when "*"
459
+ # TODO: Should support the parameterized field width.
460
+ 1
461
+ when /\A[1-9][0-9]*\z/
462
+ @field_width.to_i
463
+ else
464
+ 1
465
+ end
466
+ end
467
+
468
+ def precision_value
469
+ # NOTE: The ISO C99 standard saids;
470
+ #
471
+ # 7.19.6.1 The fprintf function
472
+ #
473
+ # 4 Each conversion specification is introduced by the character %.
474
+ # After the %, the following appear in sequence:
475
+ #
476
+ # -- An optional precision that gives the minimum number of digits to
477
+ # appear for the d, i, o, u, x, and X conversions, the number of
478
+ # digits to appear after the decimal-point character for a, A, e,
479
+ # E, f, and F conversions, the maximum number of significant
480
+ # digits for the g and G conversions, or the maximum number of
481
+ # bytes to be written for s conversions. The precision takes the
482
+ # form of a period (.) followed either by an asterisk * (described
483
+ # later) or by an optional decimal interger; if only the period is
484
+ # specified, the precision is taken as zero. If a precision
485
+ # appears with any other conversion specifier, the behavior is
486
+ # undefined.
487
+ case @precision
488
+ when "."
489
+ 0
490
+ when ".*"
491
+ # TODO: Should support the parameterized precision.
492
+ default_precision_value
493
+ when /\A\.([1-9][0-9]*)\z/
494
+ $1.to_i
495
+ else
496
+ default_precision_value
497
+ end
498
+ end
499
+
500
+ def self.flags_re
501
+ # NOTE: The ISO C99 standard saids;
502
+ #
503
+ # 7.19.6.1 The fprintf function
504
+ #
505
+ # 6 The flag characters and their meaning are:
506
+ #
507
+ # - The result of the conversion is left-justified within the
508
+ # field. (It is right-justified if this flag is not specified.)
509
+ # + The result of a signed conversion always begins with a plus
510
+ # or minus sign. (It begins with a sign only when a negative
511
+ # value is converted if this flag is not specified.)
512
+ # space If the first character of a signed conversion is not a sign,
513
+ # or if a signed conversion results in no characters, a space
514
+ # is prefixed to the result. If the space and + flags both
515
+ # appear, the space flag is ignored.
516
+ # # The result is converted to an "alternative form". For o
517
+ # conversion, it increases the precision, if an only if
518
+ # necessary, to force the first digit of the result to be a
519
+ # zero (if the value and precision are both 0, a single 0 is
520
+ # printed). For x (or X) conversion, a nonzero result has 0x
521
+ # (or 0X) prefixed to it. For a, A, e, E, f, F, g, and G
522
+ # conversions, the result of converting a floating-point number
523
+ # always contains a decimal-point character, even if no digits
524
+ # follow it. (Normally, a decimal-point character appears in
525
+ # the result of these conversions only if a digit follows it.)
526
+ # For g and G conversions, trailing zeros are not removed from
527
+ # the result. For other conversions, the behavior is
528
+ # undefined.
529
+ # 0 For d, i, o, u, x, X, a, A, e, E, f, F, g, and G conversions,
530
+ # leading zeros (following any indication of sign or base) are
531
+ # used to pad to the field width rather than performing space
532
+ # padding, except when converting an infinity or NaN. If the 0
533
+ # and - flags both appear, the 0 flag is ignored. For d, i, o,
534
+ # u, x, and X conversions, if a precision is specified, the 0
535
+ # flag is ignored. For other conversions, the behavior is
536
+ # undefined.
537
+ /[-+ #0]*/
538
+ end
539
+ private_class_method :flags_re
540
+
541
+ def self.field_width_re
542
+ /(?:\*|[1-9][0-9]*)?/
543
+ end
544
+ private_class_method :field_width_re
545
+
546
+ def self.precision_re
547
+ /(?:\.\*|\.[1-9][0-9]*)?/
548
+ end
549
+ private_class_method :precision_re
550
+
551
+ def self.length_modifier_re
552
+ # NOTE: The ISO C99 standard saids;
553
+ #
554
+ # 7.19.6.1 The fprintf function
555
+ #
556
+ # 7 The length modifiers and their meanings are:
557
+ #
558
+ # hh Specifies that a following d, i, o, u, x, or X conversion
559
+ # specifier applies to a signed char or unsigned char argument
560
+ # (the argument will have been promoted according to the integer
561
+ # promotions, but its value shall be converted to signed char or
562
+ # unsigned char before printing); or that a following n
563
+ # conversion specifier applies to a pointer to a signed char
564
+ # argument.
565
+ # h Specifies that a following d, i, o, u, x, or X conversion
566
+ # specifier applies to a short int or unsigned short int
567
+ # argument (the argument will have been promoted according to
568
+ # the integer promotions, but its value shall be converted to
569
+ # short int or unsigned short int before printing); or that a
570
+ # following n conversion specifier applies to a pointer to a
571
+ # short int argument.
572
+ # l Specifies that a following d, i, o, u, x, or X conversion
573
+ # specifier applies to a long int or unsigned long int argument;
574
+ # that a following n conversion specifier applies to a pointer
575
+ # to a long int argument; that a following c conversion
576
+ # specifier applies to a wint_t argument; that a following s
577
+ # conversion specifier applies to a pointer to a wchar_t
578
+ # argument; or has no effect on a following a, A, e, E, f, F, g,
579
+ # or G conversion specifier.
580
+ # ll Specifies that a following d, i, o, u, x, or X conversion
581
+ # specifier applies to a long long int or unsigned long long int
582
+ # argument; or that a following n conversion specifier applies
583
+ # to a pointer to a long long int argument.
584
+ # j Specifies that a following d, i, o, u, x, or X conversion
585
+ # specifier applies to an intmax_t or uintmax_t argument; or
586
+ # that a following n conversion specifier applies to a pointer
587
+ # to an intmax_t argument.
588
+ # z Specifies that a following d, i, o, u, x, or X conversion
589
+ # specifier applies to a size_t or the corresponding signed
590
+ # integer type argument; or that a following n conversion
591
+ # specifier applies to a pointer to a signed integer type
592
+ # corresponding to size_t argument.
593
+ # t Specifies that a following d, i, o, u, x, or X conversion
594
+ # specifier applies to a ptrdiff_t or the corresponding unsigned
595
+ # integer type argument; or that a following n conversion
596
+ # specifier applies to a pointer to a ptrdiff_t argument.
597
+ # L Specifies that a following a, A, e, E, f, F, g, or G
598
+ # conversion specifier applies to a long double argument.
599
+ /(?:h+|l+|j|z|t|L)?/
600
+ end
601
+ private_class_method :length_modifier_re
602
+
603
+ def self.cs_char_re
604
+ # NOTE: The ISO C99 standard saids;
605
+ #
606
+ # 7.19.6.1 The fprintf function
607
+ #
608
+ # 8 The conversion specifiers and their meanings are:
609
+ #
610
+ # d,i The int argument is converted to signed decimal in the
611
+ # style [-]dddd. The precision specifies the minimum number
612
+ # of digits to appear; if the value being converted can be
613
+ # represented in fewer digits, it is expanded with leading
614
+ # zeros. The default precision is 1. The result of
615
+ # converting a zero value with a precision of zero is no
616
+ # characters.
617
+ # o,u,x,X The unsigned int argument is converted to unsigned octal
618
+ # (o), unsigned decimal (u), or unsigned hexadecimal notation
619
+ # (x or X) in the style dddd; the letters abcdef are used for
620
+ # x conversion and the letters ABCDEF for X conversion. The
621
+ # precision specifies the minimum number of digits to appear;
622
+ # if the value being converted can be represented in fewer
623
+ # digits, it is expanded with leading zeros. The default
624
+ # precision in 1. The result of converting a zero value with
625
+ # a precision of zero is no characters.
626
+ # f,F A double argument representing a floating-point number is
627
+ # converted to decimal notation in the style [-]ddd.ddd,
628
+ # where the number of digits after the decimal-point
629
+ # character is equal to the precision specification. If the
630
+ # precision is missing, it is taken as 6; if the precision is
631
+ # zero and the # flag is not specified, no decimal-point
632
+ # character appears. If a decimal-point character appears,
633
+ # at least one digit appears before it. The value is rounded
634
+ # to the appropriate number of digits.
635
+ # A double argument representing an infinity is converted in
636
+ # one of the styles [-]inf or [-]infinity -- which style is
637
+ # implementation-defined. A double argument representing a
638
+ # NaN is converted in one of the styles [-]nan or
639
+ # [-]nan(n-char-sequence) -- which style, and the meaning of
640
+ # any n-char-sequence, is implementation-defined. The F
641
+ # conversion specifier produces INF, INFINITY, or NAN instead
642
+ # of inf, infinity, or nan, respectively.
643
+ # e,E A double argument representing a floating-point number is
644
+ # converted in the style [-]d.ddde[+-]dd, where there is one
645
+ # digit (which is nonzero if the argument is nonzero) before
646
+ # the decimal-point character and the number of digits after
647
+ # it is equal to the precision; if the precision is missing,
648
+ # it is taken as 6; if the precision is zero and the # flag
649
+ # is not specified, no decimal-point character appears. The
650
+ # value is rounded to the appropriate number of digits. The
651
+ # E conversion specifier produces a number with E instead of
652
+ # e introducing the exponent. The exponent always contains
653
+ # at least two digits, and only as many more digits as
654
+ # necessary to represent the exponent. If the value is zero,
655
+ # the exponent is zero.
656
+ # g,G A double argument representing a floating-point number is
657
+ # converted in style f or e (or in style F or E in the case
658
+ # of a G conversion specifier), depending on the value
659
+ # converted and the precision. Let P equal the precision if
660
+ # nonzero, 6 if the precision is omitted, or 1 if the
661
+ # precision is zero. Then, if a conversion with style E
662
+ # would have an exponent of X:
663
+ # -- if P > X >= -4, the conversion is which style f (or F)
664
+ # and precision P - (X + 1).
665
+ # -- otherwise, the conversion is with style e (or E) and
666
+ # precision P - 1.
667
+ # Finally, unless the # flag is used, any trailing zeros are
668
+ # removed from the fractional portion of the result and the
669
+ # decimal-point character is removed if there is no
670
+ # fractional portion remaining.
671
+ # A double argument representing an infinity or NaN is
672
+ # converted in the style of an f or F conversion specifier.
673
+ # a,A A double argument representing a floating-point number is
674
+ # converted in the style [-]0xh.hhhhp[+-]d, where there is
675
+ # one hexadecimal digit (which is nonzero if the argument is
676
+ # a normalized floating-point number and is otherwise
677
+ # unspecified) before the decimal-point character and the
678
+ # number of hexadecimal digits after it is equal to the
679
+ # precision; if the precision is missing and FLT_RADIX is a
680
+ # power of 2, then the precision is sufficient for an exact
681
+ # representation of the value; if the precision is missing
682
+ # and FLT_RADIX is not a power of 2, then the precision is
683
+ # sufficient to distinguish values of type double, except
684
+ # that trailing zeros may be omitted; if the precision is
685
+ # zero and the # flag is not specified, no decimal-point
686
+ # character appears. The letters abcdef are used for a
687
+ # conversion and the letters ABCDEF for A conversion. The A
688
+ # conversion specifier produces a number with X and P instead
689
+ # of x and p. The exponent always contains at least one
690
+ # digit, and only as many more digits as necessary to
691
+ # represent the decimal exponent of 2. If the value is zero,
692
+ # the exponent is zero.
693
+ # c If no l length modifier is present, the int argument is
694
+ # converted to an unsigned char, and the resulting character
695
+ # is written.
696
+ # s If no l length modifier is present, the argument shall be a
697
+ # pointer to the initial element of an array of character
698
+ # type. Characters from the array are written up to (but not
699
+ # including) the terminating null character. If the
700
+ # precision is specified, no more than that many bytes are
701
+ # written. If the precision is not specified or is greater
702
+ # than the size of the array, the array shall contain a null
703
+ # character.
704
+ # If an l length modifier is present, the argument shall be a
705
+ # pointer to the initial element of an array of wchar_t type.
706
+ # Wide characters from the array are converted to multibyte
707
+ # characters (each as if by a call to the wcrtomb function,
708
+ # with the conversion state described by an mbstate_t object
709
+ # initialized to zero before the first wide character is
710
+ # converted) up to and including a terminating null wide
711
+ # character. The resulting multibyte characters are written
712
+ # up to (but not including) the terminating null character
713
+ # (byte). If no precision is specified, the array shall
714
+ # contain a null wide character. If a precision is
715
+ # specified, no more than that many bytes are written
716
+ # (including shift sequence, if any), and the array shall
717
+ # contain a null wide character if, to equal the multibyte
718
+ # character sequence length given by the precision, the
719
+ # function would need to access a wide character one past the
720
+ # end of the array. In no case is a partial multibyte
721
+ # character written.
722
+ # p The argument shall be a pointer to void. The value of the
723
+ # pointer is converted to a sequence of printing characters,
724
+ # in an implementation-defined manner.
725
+ # n The argument shall be a pointer to signed integer into
726
+ # which is written the number of characters written to the
727
+ # output stream so far by this call to fprintf. No argument
728
+ # is converted, but one is consumed. If the conversion
729
+ # specification includes any flags, a field width, or a
730
+ # precision, the behavior is undefined.
731
+ # % A % character is written. No argument is converted. The
732
+ # complete conversion specification shall be %%.
733
+ /[diouxXfFeEgGaAcspn%]/
734
+ end
735
+ private_class_method :cs_char_re
736
+
737
+ private
738
+ def default_precision_value
739
+ subclass_responsibility
740
+ end
741
+
742
+ def ruby_sprintf_format
743
+ # TODO: Should support the parameterized field width and the
744
+ # parameterized precision.
745
+ fw = @field_width == "*" ? "1" : @field_width
746
+ pr = @precision == ".*" ? ".1" : @precision
747
+ "%#{flags}#{fw}#{pr}#{conversion_specifier_character}"
748
+ end
749
+
750
+ def type_table
751
+ @environment.type_table
752
+ end
753
+
754
+ def memory_pool
755
+ @environment.memory_pool
756
+ end
757
+ end
758
+ private_constant :ConversionSpecifier
759
+
760
+ class CompleteConversionSpecifier < ConversionSpecifier
761
+ # === DESCRIPTION
762
+ # Checks whether types of arguments match this directive.
763
+ #
764
+ # === RETURN VALUE
765
+ # Boolean -- True if types of arguments match this directive.
766
+ def acceptable?
767
+ if @field_width_argument
768
+ unless @field_width_argument.type.same_as?(signed_int_type) ||
769
+ @field_width_argument.type.same_as?(unsigned_int_type)
770
+ return false
771
+ end
772
+ end
773
+
774
+ if @precision_argument
775
+ unless @precision_argument.type.same_as?(signed_int_type) ||
776
+ @precision_argument.type.same_as?(unsigned_int_type)
777
+ return false
778
+ end
779
+ end
780
+
781
+ if @conversion_argument
782
+ if argument_types
783
+ argument_types.any? do |arg_type|
784
+ @conversion_argument.type.same_as?(arg_type)
785
+ end
786
+ else
787
+ true
788
+ end
789
+ else
790
+ false
791
+ end
792
+ end
793
+
794
+ # === DESCRIPTION
795
+ # Checks whether the format string of this directive is the ISO C99
796
+ # compliant.
797
+ #
798
+ # === RETURN VALUE
799
+ # Boolean -- True if the format string is wellformed.
800
+ def wellformed?
801
+ valid_flags? && valid_field_width? && valid_precision? &&
802
+ valid_length_modifier? && valid_conversion_specifier_character?
803
+ end
804
+
805
+ def complete?
806
+ true
807
+ end
808
+
809
+ def valid_flags?
810
+ true
811
+ end
812
+
813
+ def valid_field_width?
814
+ true
815
+ end
816
+
817
+ def valid_precision?
818
+ true
819
+ end
820
+
821
+ def valid_length_modifier?
822
+ if length_modifier.empty?
823
+ true
824
+ else
825
+ suitable_length_modifiers.include?(length_modifier)
826
+ end
827
+ end
828
+
829
+ private
830
+ def argument_types
831
+ subclass_responsibility
832
+ end
833
+
834
+ def suitable_length_modifiers
835
+ subclass_responsibility
836
+ end
837
+ end
838
+ private_constant :CompleteConversionSpecifier
839
+
840
+ class NumberConversionSpecifier < CompleteConversionSpecifier
841
+ def initialize(format, trailing_args, environment,
842
+ flags, field_width, precision, length_modifier,
843
+ conversion_specifier_character)
844
+ super(format, trailing_args, environment, true,
845
+ flags, field_width, precision, length_modifier,
846
+ conversion_specifier_character)
847
+ end
848
+
849
+ def valid_conversion_specifier_character?
850
+ true
851
+ end
852
+
853
+ def min_length
854
+ # NOTE: Ruby has the buitin mostly C compliant sprintf.
855
+ sprintf(ruby_sprintf_format, 0).length
856
+ end
857
+
858
+ def max_length
859
+ # NOTE: Ruby has the buitin mostly C compliant sprintf.
860
+ if conversion_type.signed?
861
+ sprintf(ruby_sprintf_format, conversion_type.min_value).length
862
+ else
863
+ sprintf(ruby_sprintf_format, conversion_type.max_value).length
864
+ end
865
+ end
866
+
867
+ private
868
+ def conversion_type
869
+ subclass_responsibility
870
+ end
871
+ end
872
+ private_constant :NumberConversionSpecifier
873
+
874
+ class Conversion_d < NumberConversionSpecifier
875
+ def self.suitable_conversion_specifier_character
876
+ "d"
877
+ end
878
+
879
+ private
880
+ def default_precision_value
881
+ # NOTE: The ISO C99 standard saids;
882
+ #
883
+ # 7.19.6.1 The fprintf function
884
+ #
885
+ # 8 The conversion specifiers and their meanings are:
886
+ #
887
+ # d,i The int argument is converted to signed decimal in the
888
+ # style [-]dddd. The precision specifies the minimum number
889
+ # of digits to appear; if the value being converted can be
890
+ # represented in fewer digits, it is expanded with leading
891
+ # zeros. The default precision is 1. The result of
892
+ # converting a zero value with a precision of zero is no
893
+ # characters.
894
+ # o,u,x,X The unsigned int argument is converted to unsigned octal
895
+ # (o), unsigned decimal (u), or unsigned hexadecimal notation
896
+ # (x or X) in the style dddd; the letters abcdef are used for
897
+ # x conversion and the letters ABCDEF for X conversion. The
898
+ # precision specifies the minimum number of digits to appear;
899
+ # if the value being converted can be represented in fewer
900
+ # digits, it is expanded with leading zeros. The default
901
+ # precision in 1. The result of converting a zero value with
902
+ # a precision of zero is no characters.
903
+ 1
904
+ end
905
+
906
+ def argument_types
907
+ # NOTE: The ISO C99 standard saids;
908
+ #
909
+ # 7.19.6.1 The fprintf function
910
+ #
911
+ # 7 The length modifiers and their meanings are:
912
+ #
913
+ # hh Specifies that a following d, i, o, u, x, or X conversion
914
+ # specifier applies to a signed char or unsigned char argument
915
+ # (the argument will have been promoted according to the integer
916
+ # promotions, but its value shall be converted to signed char or
917
+ # unsigned char before printing); or that a following n
918
+ # conversion specifier applies to a pointer to a signed char
919
+ # argument.
920
+ # h Specifies that a following d, i, o, u, x, or X conversion
921
+ # specifier applies to a short int or unsigned short int
922
+ # argument (the argument will have been promoted according to
923
+ # the integer promotions, but its value shall be converted to
924
+ # short int or unsigned short int before printing); or that a
925
+ # following n conversion specifier applies to a pointer to a
926
+ # short int argument.
927
+ # l Specifies that a following d, i, o, u, x, or X conversion
928
+ # specifier applies to a long int or unsigned long int argument;
929
+ # that a following n conversion specifier applies to a pointer
930
+ # to a long int argument; that a following c conversion
931
+ # specifier applies to a wint_t argument; that a following s
932
+ # conversion specifier applies to a pointer to a wchar_t
933
+ # argument; or has no effect on a following a, A, e, E, f, F, g,
934
+ # or G conversion specifier.
935
+ # ll Specifies that a following d, i, o, u, x, or X conversion
936
+ # specifier applies to a long long int or unsigned long long int
937
+ # argument; or that a following n conversion specifier applies
938
+ # to a pointer to a long long int argument.
939
+ # j Specifies that a following d, i, o, u, x, or X conversion
940
+ # specifier applies to an intmax_t or uintmax_t argument; or
941
+ # that a following n conversion specifier applies to a pointer
942
+ # to an intmax_t argument.
943
+ # z Specifies that a following d, i, o, u, x, or X conversion
944
+ # specifier applies to a size_t or the corresponding signed
945
+ # integer type argument; or that a following n conversion
946
+ # specifier applies to a pointer to a signed integer type
947
+ # corresponding to size_t argument.
948
+ # t Specifies that a following d, i, o, u, x, or X conversion
949
+ # specifier applies to a ptrdiff_t or the corresponding unsigned
950
+ # integer type argument; or that a following n conversion
951
+ # specifier applies to a pointer to a ptrdiff_t argument.
952
+ case length_modifier
953
+ when "hh"
954
+ [signed_char_type, unsigned_char_type]
955
+ when "h"
956
+ [signed_short_type, unsigned_short_type]
957
+ when "l"
958
+ [signed_long_type, unsigned_long_type]
959
+ when "ll"
960
+ [signed_long_long_type, unsigned_long_long_type]
961
+ when "j"
962
+ # FIXME: `intmax_t' and `uintmax_t' are not supported yet.
963
+ [signed_long_long_type, unsigned_long_long_type]
964
+ when "z"
965
+ # FIXME: `size_t' is not supported yet.
966
+ [unsigned_long_type]
967
+ when "t"
968
+ # FIXME: `ptrdiff_t' is not supported yet.
969
+ [signed_int_type]
970
+ else
971
+ [signed_int_type, unsigned_int_type]
972
+ end
973
+ end
974
+
975
+ def suitable_length_modifiers
976
+ ["hh", "h", "l", "ll", "j", "z", "t"]
977
+ end
978
+
979
+ def conversion_type
980
+ case length_modifier
981
+ when "hh"
982
+ if conversion_argument && conversion_argument.type.signed?
983
+ signed_char_type
984
+ else
985
+ unsigned_char_type
986
+ end
987
+ when "h"
988
+ if conversion_argument && conversion_argument.type.signed?
989
+ signed_short_type
990
+ else
991
+ unsigned_short_type
992
+ end
993
+ when "l"
994
+ if conversion_argument && conversion_argument.type.signed?
995
+ signed_long_type
996
+ else
997
+ unsigned_long_type
998
+ end
999
+ when "ll"
1000
+ if conversion_argument && conversion_argument.type.signed?
1001
+ signed_long_long_type
1002
+ else
1003
+ unsigned_long_long_type
1004
+ end
1005
+ when "j"
1006
+ # FIXME: `intmax_t' and `uintmax_t' are not supported yet.
1007
+ if conversion_argument && conversion_argument.type.signed?
1008
+ signed_long_long_type
1009
+ else
1010
+ unsigned_long_long_type
1011
+ end
1012
+ when "z"
1013
+ # FIXME: `size_t' is not supported yet.
1014
+ unsigned_long_type
1015
+ when "t"
1016
+ # FIXME: `ptrdiff_t' is not supported yet.
1017
+ signed_int_type
1018
+ else
1019
+ default_conversion_type
1020
+ end
1021
+ end
1022
+
1023
+ def default_conversion_type
1024
+ signed_int_type
1025
+ end
1026
+ end
1027
+ private_constant :Conversion_d
1028
+
1029
+ class Conversion_i < Conversion_d
1030
+ def self.suitable_conversion_specifier_character
1031
+ "i"
1032
+ end
1033
+ end
1034
+ private_constant :Conversion_i
1035
+
1036
+ class Conversion_o < Conversion_d
1037
+ def self.suitable_conversion_specifier_character
1038
+ "o"
1039
+ end
1040
+
1041
+ private
1042
+ def default_conversion_type
1043
+ unsigned_int_type
1044
+ end
1045
+ end
1046
+ private_constant :Conversion_o
1047
+
1048
+ class Conversion_u < Conversion_o
1049
+ def self.suitable_conversion_specifier_character
1050
+ "u"
1051
+ end
1052
+ end
1053
+ private_constant :Conversion_u
1054
+
1055
+ class Conversion_x < Conversion_o
1056
+ def self.suitable_conversion_specifier_character
1057
+ "x"
1058
+ end
1059
+ end
1060
+ private_constant :Conversion_x
1061
+
1062
+ class Conversion_X < Conversion_o
1063
+ def self.suitable_conversion_specifier_character
1064
+ "X"
1065
+ end
1066
+ end
1067
+ private_constant :Conversion_X
1068
+
1069
+ class Conversion_f < NumberConversionSpecifier
1070
+ def self.suitable_conversion_specifier_character
1071
+ "f"
1072
+ end
1073
+
1074
+ private
1075
+ def default_precision_value
1076
+ # NOTE: The ISO C99 standard saids;
1077
+ #
1078
+ # 7.19.6.1 The fprintf function
1079
+ #
1080
+ # 8 The conversion specifiers and their meanings are:
1081
+ #
1082
+ # f,F A double argument representing a floating-point number is
1083
+ # converted to decimal notation in the style [-]ddd.ddd,
1084
+ # where the number of digits after the decimal-point
1085
+ # character is equal to the precision specification. If the
1086
+ # precision is missing, it is taken as 6; if the precision is
1087
+ # zero and the # flag is not specified, no decimal-point
1088
+ # character appears. If a decimal-point character appears,
1089
+ # at least one digit appears before it. The value is rounded
1090
+ # to the appropriate number of digits.
1091
+ # A double argument representing an infinity is converted in
1092
+ # one of the styles [-]inf or [-]infinity -- which style is
1093
+ # implementation-defined. A double argument representing a
1094
+ # NaN is converted in one of the styles [-]nan or
1095
+ # [-]nan(n-char-sequence) -- which style, and the meaning of
1096
+ # any n-char-sequence, is implementation-defined. The F
1097
+ # conversion specifier produces INF, INFINITY, or NAN instead
1098
+ # of inf, infinity, or nan, respectively.
1099
+ # e,E A double argument representing a floating-point number is
1100
+ # converted in the style [-]d.ddde[+-]dd, where there is one
1101
+ # digit (which is nonzero if the argument is nonzero) before
1102
+ # the decimal-point character and the number of digits after
1103
+ # it is equal to the precision; if the precision is missing,
1104
+ # it is taken as 6; if the precision is zero and the # flag
1105
+ # is not specified, no decimal-point character appears. The
1106
+ # value is rounded to the appropriate number of digits. The
1107
+ # E conversion specifier produces a number with E instead of
1108
+ # e introducing the exponent. The exponent always contains
1109
+ # at least two digits, and only as many more digits as
1110
+ # necessary to represent the exponent. If the value is zero,
1111
+ # the exponent is zero.
1112
+ # g,G A double argument representing a floating-point number is
1113
+ # converted in style f or e (or in style F or E in the case
1114
+ # of a G conversion specifier), depending on the value
1115
+ # converted and the precision. Let P equal the precision if
1116
+ # nonzero, 6 if the precision is omitted, or 1 if the
1117
+ # precision is zero. Then, if a conversion with style E
1118
+ # would have an exponent of X:
1119
+ # -- if P > X >= -4, the conversion is which style f (or F)
1120
+ # and precision P - (X + 1).
1121
+ # -- otherwise, the conversion is with style e (or E) and
1122
+ # precision P - 1.
1123
+ # Finally, unless the # flag is used, any trailing zeros are
1124
+ # removed from the fractional portion of the result and the
1125
+ # decimal-point character is removed if there is no
1126
+ # fractional portion remaining.
1127
+ # A double argument representing an infinity or NaN is
1128
+ # converted in the style of an f or F conversion specifier.
1129
+ 6
1130
+ end
1131
+
1132
+ def argument_types
1133
+ # NOTE: The ISO C99 standard saids;
1134
+ #
1135
+ # 7.19.6.1 The fprintf function
1136
+ #
1137
+ # 7 The length modifiers and their meanings are:
1138
+ #
1139
+ # L Specifies that a following a, A, e, E, f, F, g, or G
1140
+ # conversion specifier applies to a long double argument.
1141
+ case length_modifier
1142
+ when "L"
1143
+ [long_double_type]
1144
+ else
1145
+ # NOTE: The argument will be argument promoted, so float type should
1146
+ # be acceptable, too.
1147
+ [float_type, double_type]
1148
+ end
1149
+ end
1150
+
1151
+ def suitable_length_modifiers
1152
+ ["L"]
1153
+ end
1154
+
1155
+ def conversion_type
1156
+ case length_modifier
1157
+ when "L"
1158
+ long_double_type
1159
+ else
1160
+ double_type
1161
+ end
1162
+ end
1163
+ end
1164
+ private_constant :Conversion_f
1165
+
1166
+ class Conversion_F < Conversion_f
1167
+ def self.suitable_conversion_specifier_character
1168
+ "F"
1169
+ end
1170
+ end
1171
+ private_constant :Conversion_F
1172
+
1173
+ class Conversion_e < Conversion_f
1174
+ def self.suitable_conversion_specifier_character
1175
+ "e"
1176
+ end
1177
+ end
1178
+ private_constant :Conversion_e
1179
+
1180
+ class Conversion_E < Conversion_f
1181
+ def self.suitable_conversion_specifier_character
1182
+ "E"
1183
+ end
1184
+ end
1185
+ private_constant :Conversion_E
1186
+
1187
+ class Conversion_g < Conversion_f
1188
+ def self.suitable_conversion_specifier_character
1189
+ "g"
1190
+ end
1191
+ end
1192
+ private_constant :Conversion_g
1193
+
1194
+ class Conversion_G < Conversion_f
1195
+ def self.suitable_conversion_specifier_character
1196
+ "G"
1197
+ end
1198
+ end
1199
+ private_constant :Conversion_G
1200
+
1201
+ class Conversion_a < Conversion_f
1202
+ def self.suitable_conversion_specifier_character
1203
+ "a"
1204
+ end
1205
+
1206
+ private
1207
+ def default_precision_value
1208
+ # NOTE: The ISO C99 standard saids;
1209
+ #
1210
+ # 7.19.6.1 The fprintf function
1211
+ #
1212
+ # 8 The conversion specifiers and their meanings are:
1213
+ #
1214
+ # a,A A double argument representing a floating-point number is
1215
+ # converted in the style [-]0xh.hhhhp[+-]d, where there is
1216
+ # one hexadecimal digit (which is nonzero if the argument is
1217
+ # a normalized floating-point number and is otherwise
1218
+ # unspecified) before the decimal-point character and the
1219
+ # number of hexadecimal digits after it is equal to the
1220
+ # precision; if the precision is missing and FLT_RADIX is a
1221
+ # power of 2, then the precision is sufficient for an exact
1222
+ # representation of the value; if the precision is missing
1223
+ # and FLT_RADIX is not a power of 2, then the precision is
1224
+ # sufficient to distinguish values of type double, except
1225
+ # that trailing zeros may be omitted; if the precision is
1226
+ # zero and the # flag is not specified, no decimal-point
1227
+ # character appears. The letters abcdef are used for a
1228
+ # conversion and the letters ABCDEF for A conversion. The A
1229
+ # conversion specifier produces a number with X and P instead
1230
+ # of x and p. The exponent always contains at least one
1231
+ # digit, and only as many more digits as necessary to
1232
+ # represent the decimal exponent of 2. If the value is zero,
1233
+ # the exponent is zero.
1234
+
1235
+ # FIXME: This is not the ISO C99 compliant.
1236
+ 6
1237
+ end
1238
+ end
1239
+ private_constant :Conversion_a
1240
+
1241
+ class Conversion_A < Conversion_f
1242
+ def self.suitable_conversion_specifier_character
1243
+ "A"
1244
+ end
1245
+ end
1246
+ private_constant :Conversion_A
1247
+
1248
+ class CharacterConversionSpecifier < CompleteConversionSpecifier
1249
+ def initialize(format, trailing_args, environment,
1250
+ flags, field_width, precision, length_modifier,
1251
+ conversion_specifier_character)
1252
+ super(format, trailing_args, environment, true,
1253
+ flags, field_width, precision, length_modifier,
1254
+ conversion_specifier_character)
1255
+ end
1256
+
1257
+ def valid_conversion_specifier_character?
1258
+ true
1259
+ end
1260
+
1261
+ def min_length
1262
+ # NOTE: Ruby has the buitin mostly C compliant sprintf.
1263
+ sprintf(ruby_sprintf_format, " ").length
1264
+ end
1265
+
1266
+ def max_length
1267
+ min_length
1268
+ end
1269
+ end
1270
+ private_constant :CharacterConversionSpecifier
1271
+
1272
+ class Conversion_c < CharacterConversionSpecifier
1273
+ def self.suitable_conversion_specifier_character
1274
+ "c"
1275
+ end
1276
+
1277
+ private
1278
+ def default_precision_value
1279
+ 0
1280
+ end
1281
+
1282
+ def argument_types
1283
+ # NOTE: The ISO C99 standard saids;
1284
+ #
1285
+ # 7.19.6.1 The fprintf function
1286
+ #
1287
+ # 7 The length modifiers and their meanings are:
1288
+ #
1289
+ # l Specifies that a following d, i, o, u, x, or X conversion
1290
+ # specifier applies to a long int or unsigned long int argument;
1291
+ # that a following n conversion specifier applies to a pointer
1292
+ # to a long int argument; that a following c conversion
1293
+ # specifier applies to a wint_t argument; that a following s
1294
+ # conversion specifier applies to a pointer to a wchar_t
1295
+ # argument; or has no effect on a following a, A, e, E, f, F, g,
1296
+ # or G conversion specifier.
1297
+ case length_modifier
1298
+ when "l"
1299
+ # FIXME: `wint_t' is not supported yet.
1300
+ [wchar_type]
1301
+ else
1302
+ # NOTE: The argument will be integer promoted, so the argument type
1303
+ # whose conversion-rank is less than one of the int should be
1304
+ # acceptable, too.
1305
+ [signed_char_type, unsigned_char_type, signed_short_type,
1306
+ unsigned_short_type, signed_int_type, unsigned_int_type]
1307
+ end
1308
+ end
1309
+
1310
+ def suitable_length_modifiers
1311
+ ["l"]
1312
+ end
1313
+ end
1314
+ private_constant :Conversion_c
1315
+
1316
+ class StringConversionSpecifier < CompleteConversionSpecifier
1317
+ def initialize(format, trailing_args, environment,
1318
+ flags, field_width, precision, length_modifier,
1319
+ conversion_specifier_character)
1320
+ super(format, trailing_args, environment, true,
1321
+ flags, field_width, precision, length_modifier,
1322
+ conversion_specifier_character)
1323
+ end
1324
+
1325
+ def valid_conversion_specifier_character?
1326
+ true
1327
+ end
1328
+
1329
+ def min_length
1330
+ # NOTE: Ruby has the buitin mostly C compliant sprintf.
1331
+ sprintf(ruby_sprintf_format, "").length
1332
+ end
1333
+
1334
+ def max_length
1335
+ # NOTE: Ruby has the buitin mostly C compliant sprintf.
1336
+ if conversion_argument && conversion_argument.type.pointer? and
1337
+ pointee = pointee_of(conversion_argument) and pointee.type.array?
1338
+ length = pointee.type.length ? pointee.type.length - 1 : 0
1339
+ sprintf(ruby_sprintf_format, " " * length).length
1340
+ else
1341
+ min_length
1342
+ end
1343
+ end
1344
+ end
1345
+ private_constant :StringConversionSpecifier
1346
+
1347
+ class Conversion_s < StringConversionSpecifier
1348
+ def self.suitable_conversion_specifier_character
1349
+ "s"
1350
+ end
1351
+
1352
+ private
1353
+ def default_precision_value
1354
+ 0
1355
+ end
1356
+
1357
+ def argument_types
1358
+ # NOTE: The ISO C99 standard saids;
1359
+ #
1360
+ # 7.19.6.1 The fprintf function
1361
+ #
1362
+ # 7 The length modifiers and their meanings are:
1363
+ #
1364
+ # l Specifies that a following d, i, o, u, x, or X conversion
1365
+ # specifier applies to a long int or unsigned long int argument;
1366
+ # that a following n conversion specifier applies to a pointer
1367
+ # to a long int argument; that a following c conversion
1368
+ # specifier applies to a wint_t argument; that a following s
1369
+ # conversion specifier applies to a pointer to a wchar_t
1370
+ # argument; or has no effect on a following a, A, e, E, f, F, g,
1371
+ # or G conversion specifier.
1372
+ case length_modifier
1373
+ when "l"
1374
+ [pointer_type(wchar_type)]
1375
+ else
1376
+ [pointer_type(signed_char_type), pointer_type(unsigned_char_type)]
1377
+ end
1378
+ end
1379
+
1380
+ def suitable_length_modifiers
1381
+ ["l"]
1382
+ end
1383
+ end
1384
+ private_constant :Conversion_s
1385
+
1386
+ class Conversion_p < NumberConversionSpecifier
1387
+ def self.suitable_conversion_specifier_character
1388
+ "p"
1389
+ end
1390
+
1391
+ def min_length
1392
+ # NOTE: `%p' conversion specifier of the Ruby's builtin sprintf does
1393
+ # not convert the argument.
1394
+ sprintf("%##{flags}#{field_width}#{precision}x", 0).length
1395
+ end
1396
+
1397
+ def max_length
1398
+ # NOTE: `%p' conversion specifier of the Ruby's builtin sprintf does
1399
+ # not convert the argument.
1400
+ sprintf("%##{flags}#{field_width}#{precision}x",
1401
+ conversion_type.max_value).length
1402
+ end
1403
+
1404
+ private
1405
+ def default_precision_value
1406
+ 0
1407
+ end
1408
+
1409
+ def argument_types
1410
+ if conversion_argument && conversion_argument.type.pointer?
1411
+ [conversion_argument.type.unqualify]
1412
+ else
1413
+ [pointer_type(void_type)]
1414
+ end
1415
+ end
1416
+
1417
+ def suitable_length_modifiers
1418
+ []
1419
+ end
1420
+
1421
+ def conversion_type
1422
+ pointer_type(void_type)
1423
+ end
1424
+ end
1425
+ private_constant :Conversion_p
1426
+
1427
+ class Conversion_n < CompleteConversionSpecifier
1428
+ def self.suitable_conversion_specifier_character
1429
+ "n"
1430
+ end
1431
+
1432
+ def initialize(format, trailing_args, environment,
1433
+ flags, field_width, precision, length_modifier,
1434
+ conversion_specifier_character)
1435
+ super(format, trailing_args, environment, true,
1436
+ flags, field_width, precision, length_modifier,
1437
+ conversion_specifier_character)
1438
+ end
1439
+
1440
+ def valid_conversion_specifier_character?
1441
+ true
1442
+ end
1443
+
1444
+ def min_length
1445
+ 0
1446
+ end
1447
+
1448
+ def max_length
1449
+ 0
1450
+ end
1451
+
1452
+ private
1453
+ def default_precision_value
1454
+ 0
1455
+ end
1456
+
1457
+ def argument_types
1458
+ # NOTE: The ISO C99 standard saids;
1459
+ #
1460
+ # 7.19.6.1 The fprintf function
1461
+ #
1462
+ # 7 The length modifiers and their meanings are:
1463
+ #
1464
+ # hh Specifies that a following d, i, o, u, x, or X conversion
1465
+ # specifier applies to a signed char or unsigned char argument
1466
+ # (the argument will have been promoted according to the integer
1467
+ # promotions, but its value shall be converted to signed char or
1468
+ # unsigned char before printing); or that a following n
1469
+ # conversion specifier applies to a pointer to a signed char
1470
+ # argument.
1471
+ # h Specifies that a following d, i, o, u, x, or X conversion
1472
+ # specifier applies to a short int or unsigned short int
1473
+ # argument (the argument will have been promoted according to
1474
+ # the integer promotions, but its value shall be converted to
1475
+ # short int or unsigned short int before printing); or that a
1476
+ # following n conversion specifier applies to a pointer to a
1477
+ # short int argument.
1478
+ # l Specifies that a following d, i, o, u, x, or X conversion
1479
+ # specifier applies to a long int or unsigned long int argument;
1480
+ # that a following n conversion specifier applies to a pointer
1481
+ # to a long int argument; that a following c conversion
1482
+ # specifier applies to a wint_t argument; that a following s
1483
+ # conversion specifier applies to a pointer to a wchar_t
1484
+ # argument; or has no effect on a following a, A, e, E, f, F, g,
1485
+ # or G conversion specifier.
1486
+ # ll Specifies that a following d, i, o, u, x, or X conversion
1487
+ # specifier applies to a long long int or unsigned long long int
1488
+ # argument; or that a following n conversion specifier applies
1489
+ # to a pointer to a long long int argument.
1490
+ # j Specifies that a following d, i, o, u, x, or X conversion
1491
+ # specifier applies to an intmax_t or uintmax_t argument; or
1492
+ # that a following n conversion specifier applies to a pointer
1493
+ # to an intmax_t argument.
1494
+ # z Specifies that a following d, i, o, u, x, or X conversion
1495
+ # specifier applies to a size_t or the corresponding signed
1496
+ # integer type argument; or that a following n conversion
1497
+ # specifier applies to a pointer to a signed integer type
1498
+ # corresponding to size_t argument.
1499
+ # t Specifies that a following d, i, o, u, x, or X conversion
1500
+ # specifier applies to a ptrdiff_t or the corresponding unsigned
1501
+ # integer type argument; or that a following n conversion
1502
+ # specifier applies to a pointer to a ptrdiff_t argument.
1503
+ case length_modifier
1504
+ when "hh"
1505
+ [pointer_type(signed_char_type)]
1506
+ when "h"
1507
+ [pointer_type(signed_short_type)]
1508
+ when "l"
1509
+ [pointer_type(signed_long_type)]
1510
+ when "ll"
1511
+ [pointer_type(signed_long_long_type)]
1512
+ when "j"
1513
+ # FIXME: `intmax_t' is not supported yet.
1514
+ [pointer_type(signed_long_long_type)]
1515
+ when "z"
1516
+ # FIXME: `size_t' is not supported yet.
1517
+ [pointer_type(signed_long_type)]
1518
+ when "t"
1519
+ # FIXME: `ptrdiff_t' is not supported yet.
1520
+ [pointer_type(signed_int_type)]
1521
+ else
1522
+ [pointer_type(signed_int_type)]
1523
+ end
1524
+ end
1525
+
1526
+ def suitable_length_modifiers
1527
+ ["hh", "h", "l", "ll", "j", "z", "t"]
1528
+ end
1529
+ end
1530
+ private_constant :Conversion_n
1531
+
1532
+ class Conversion_percent < CompleteConversionSpecifier
1533
+ def self.suitable_conversion_specifier_character
1534
+ "%"
1535
+ end
1536
+
1537
+ def initialize(format, trailing_args, environment,
1538
+ flags, field_width, precision, length_modifier,
1539
+ conversion_specifier_character)
1540
+ super(format, trailing_args, environment, false,
1541
+ flags, field_width, precision, length_modifier,
1542
+ conversion_specifier_character)
1543
+ end
1544
+
1545
+ def valid_flags?
1546
+ flags.empty?
1547
+ end
1548
+
1549
+ def valid_field_width?
1550
+ field_width.empty?
1551
+ end
1552
+
1553
+ def valid_precision?
1554
+ precision.empty?
1555
+ end
1556
+
1557
+ def valid_length_modifier?
1558
+ length_modifier.empty?
1559
+ end
1560
+
1561
+ def valid_conversion_specifier_character?
1562
+ true
1563
+ end
1564
+
1565
+ def min_length
1566
+ 1
1567
+ end
1568
+
1569
+ def max_length
1570
+ 1
1571
+ end
1572
+
1573
+ private
1574
+ def default_precision_value
1575
+ 0
1576
+ end
1577
+
1578
+ def argument_types
1579
+ nil
1580
+ end
1581
+
1582
+ def suitable_length_modifiers
1583
+ []
1584
+ end
1585
+ end
1586
+ private_constant :Conversion_percent
1587
+
1588
+ class UndefinedConversionSpecifier < CompleteConversionSpecifier
1589
+ def initialize(format, flags, field_width, precision, length_modifier,
1590
+ conversion_specifier_character)
1591
+ super(format, [], nil, false,
1592
+ flags, field_width, precision, length_modifier,
1593
+ conversion_specifier_character)
1594
+ end
1595
+
1596
+ def undefined?
1597
+ true
1598
+ end
1599
+
1600
+ def valid_conversion_specifier_character?
1601
+ false
1602
+ end
1603
+
1604
+ def min_length
1605
+ 0
1606
+ end
1607
+
1608
+ def max_length
1609
+ 0
1610
+ end
1611
+
1612
+ private
1613
+ def default_precision_value
1614
+ 0
1615
+ end
1616
+
1617
+ def argument_types
1618
+ nil
1619
+ end
1620
+
1621
+ def suitable_length_modifiers
1622
+ []
1623
+ end
1624
+ end
1625
+ private_constant :UndefinedConversionSpecifier
1626
+
1627
+ class IncompleteConversionSpecifier < ConversionSpecifier
1628
+ def initialize(format, flags, field_width, precision, length_modifier)
1629
+ super(format, [], nil, false,
1630
+ flags, field_width, precision, length_modifier, nil)
1631
+ end
1632
+
1633
+ # === DESCRIPTION
1634
+ # Checks whether types of arguments match this directive.
1635
+ #
1636
+ # === RETURN VALUE
1637
+ # Boolean -- True if types of arguments match this directive.
1638
+ def acceptable?
1639
+ false
1640
+ end
1641
+
1642
+ # === DESCRIPTION
1643
+ # Checks whether the format string of this directive is the ISO C99
1644
+ # compliant.
1645
+ #
1646
+ # === RETURN VALUE
1647
+ # Boolean -- True if the format string is wellformed.
1648
+ def wellformed?
1649
+ false
1650
+ end
1651
+
1652
+ def complete?
1653
+ false
1654
+ end
1655
+
1656
+ def undefined?
1657
+ true
1658
+ end
1659
+
1660
+ def valid_flags?
1661
+ false
1662
+ end
1663
+
1664
+ def valid_field_width?
1665
+ false
1666
+ end
1667
+
1668
+ def valid_precision?
1669
+ false
1670
+ end
1671
+
1672
+ def valid_length_modifier?
1673
+ false
1674
+ end
1675
+
1676
+ def valid_conversion_specifier_character?
1677
+ false
1678
+ end
1679
+
1680
+ def min_length
1681
+ 0
1682
+ end
1683
+
1684
+ def max_length
1685
+ 0
1686
+ end
1687
+
1688
+ private
1689
+ def default_precision_value
1690
+ 0
1691
+ end
1692
+ end
1693
+ private_constant :IncompleteConversionSpecifier
1694
+
1695
+ CONVERSION_SPECIFIERS = [
1696
+ Conversion_d,
1697
+ Conversion_i,
1698
+ Conversion_o,
1699
+ Conversion_u,
1700
+ Conversion_x,
1701
+ Conversion_X,
1702
+ Conversion_f,
1703
+ Conversion_F,
1704
+ Conversion_e,
1705
+ Conversion_E,
1706
+ Conversion_g,
1707
+ Conversion_G,
1708
+ Conversion_a,
1709
+ Conversion_A,
1710
+ Conversion_p,
1711
+ Conversion_c,
1712
+ Conversion_s,
1713
+ Conversion_n,
1714
+ Conversion_percent
1715
+ ]
1716
+ private_constant :CONVERSION_SPECIFIERS
1717
+
1718
+ CONVERSION_SPECIFIER_TBL =
1719
+ CONVERSION_SPECIFIERS.each_with_object({}) { |cs_class, hash|
1720
+ hash[cs_class.suitable_conversion_specifier_character] = cs_class
1721
+ }.freeze
1722
+ private_constant :CONVERSION_SPECIFIER_TBL
1723
+ end
1724
+
1725
+ class ScanfFormat
1726
+ def initialize(format_str, location, trailing_args, environment)
1727
+ @location = location
1728
+ @directives = create_directives(format_str, trailing_args, environment)
1729
+ @extra_arguments = trailing_args
1730
+ end
1731
+
1732
+ attr_reader :location
1733
+ attr_reader :directives
1734
+ attr_reader :extra_arguments
1735
+
1736
+ def conversion_specifiers
1737
+ @directives.select { |directive| directive.conversion_specifier? }
1738
+ end
1739
+
1740
+ private
1741
+ def create_directives(format_str, trailing_args, environment)
1742
+ directives = []
1743
+ str = format_str.dup
1744
+ until str.empty?
1745
+ directives.push(Directive.guess(str, trailing_args, environment))
1746
+ end
1747
+ directives
1748
+ end
1749
+
1750
+ # == DESCRIPTION
1751
+ # === Directive class hierarchy
1752
+ # Directive
1753
+ # <--- Whitespace
1754
+ # <--- Ordinary
1755
+ # <--- ConversionSpecifier
1756
+ # <--- CompleteConversionSpecifier
1757
+ # <--- Conversion_d
1758
+ # <--- Conversion_i
1759
+ # <--- Conversion_o
1760
+ # <--- Conversion_u
1761
+ # <--- Conversion_x
1762
+ # <--- Conversion_X
1763
+ # <--- Conversion_a
1764
+ # <--- Conversion_A
1765
+ # <--- Conversion_e
1766
+ # <--- Conversion_E
1767
+ # <--- Conversion_f
1768
+ # <--- Conversion_F
1769
+ # <--- Conversion_g
1770
+ # <--- Conversion_G
1771
+ # <--- Conversion_c
1772
+ # <--- Conversion_s
1773
+ # <--- Conversion_bracket
1774
+ # <--- Conversion_p
1775
+ # <--- Conversion_n
1776
+ # <--- Conversion_percent
1777
+ # <--- UndefinedConversionSpecifier
1778
+ # <--- IncompleteConversionSpecifier
1779
+ class Directive
1780
+ def self.guess(format_str, trailing_args, environ)
1781
+ try_to_create_whitespace(format_str) or
1782
+ try_to_create_ordinary(format_str) or
1783
+ try_to_create_conversion_specifier(format_str, trailing_args, environ)
1784
+ end
1785
+
1786
+ def initialize(format)
1787
+ @format = format
1788
+ end
1789
+
1790
+ attr_reader :format
1791
+
1792
+ def whitespace?
1793
+ subclass_responsibility
1794
+ end
1795
+
1796
+ def ordinary?
1797
+ subclass_responsibility
1798
+ end
1799
+
1800
+ def conversion_specifier?
1801
+ subclass_responsibility
1802
+ end
1803
+
1804
+ def consume_arguments?
1805
+ subclass_responsibility
1806
+ end
1807
+
1808
+ # === DESCRIPTION
1809
+ # Checks whether types of arguments match this directive.
1810
+ #
1811
+ # === RETURN VALUE
1812
+ # Boolean -- True if types of arguments match this directive.
1813
+ def acceptable?
1814
+ subclass_responsibility
1815
+ end
1816
+
1817
+ # === DESCRIPTION
1818
+ # Checks whether the format string of this directive is the ISO C99
1819
+ # compliant.
1820
+ #
1821
+ # === RETURN VALUE
1822
+ # Boolean -- True if the format string is wellformed.
1823
+ def wellformed?
1824
+ subclass_responsibility
1825
+ end
1826
+
1827
+ def illformed?
1828
+ !wellformed?
1829
+ end
1830
+
1831
+ def complete?
1832
+ subclass_responsibility
1833
+ end
1834
+
1835
+ def incomplete?
1836
+ !complete?
1837
+ end
1838
+
1839
+ def undefined?
1840
+ subclass_responsibility
1841
+ end
1842
+
1843
+ def valid_assignment_suppressing_character?
1844
+ subclass_responsibility
1845
+ end
1846
+
1847
+ def valid_field_width?
1848
+ subclass_responsibility
1849
+ end
1850
+
1851
+ def valid_length_modifier?
1852
+ subclass_responsibility
1853
+ end
1854
+
1855
+ def valid_conversion_specifier_character?
1856
+ subclass_responsibility
1857
+ end
1858
+
1859
+ def valid_scanset?
1860
+ subclass_responsibility
1861
+ end
1862
+
1863
+ def assignment_suppressing_character
1864
+ subclass_responsibility
1865
+ end
1866
+
1867
+ def field_width
1868
+ subclass_responsibility
1869
+ end
1870
+
1871
+ def length_modifier
1872
+ subclass_responsibility
1873
+ end
1874
+
1875
+ def conversion_specifier_character
1876
+ subclass_responsibility
1877
+ end
1878
+
1879
+ def scanset
1880
+ subclass_responsibility
1881
+ end
1882
+
1883
+ def self.try_to_create_whitespace(format_str)
1884
+ (format = Whitespace.scan(format_str)) ? Whitespace.new(format) : nil
1885
+ end
1886
+ private_class_method :try_to_create_whitespace
1887
+
1888
+ def self.try_to_create_ordinary(format_str)
1889
+ (format = Ordinary.scan(format_str)) ? Ordinary.new(format) : nil
1890
+ end
1891
+ private_class_method :try_to_create_ordinary
1892
+
1893
+ def self.try_to_create_conversion_specifier(format_str,
1894
+ trailing_args, environment)
1895
+ format, as_char, field_width, length_modifier, cs_char, scanset =
1896
+ ConversionSpecifier.scan(format_str)
1897
+
1898
+ case
1899
+ when cs_char.nil?
1900
+ IncompleteConversionSpecifier.new(format, as_char, field_width,
1901
+ length_modifier, nil)
1902
+ when cs_char == "[" && scanset.nil?
1903
+ IncompleteConversionSpecifier.new(format, as_char, field_width,
1904
+ length_modifier, cs_char)
1905
+ when cs_class = CONVERSION_SPECIFIER_TBL[cs_char]
1906
+ cs_class.new(format, trailing_args, environment,
1907
+ as_char, field_width, length_modifier, cs_char, scanset)
1908
+ else
1909
+ UndefinedConversionSpecifier.new(format, as_char, field_width,
1910
+ length_modifier, cs_char)
1911
+ end
1912
+ end
1913
+ private_class_method :try_to_create_conversion_specifier
1914
+ end
1915
+ private_constant :Directive
1916
+
1917
+ class Whitespace < Directive
1918
+ def self.scan(format_str)
1919
+ # NOTE: The ISO C99 standard saids;
1920
+ #
1921
+ # 7.19.6.2 The fscanf function
1922
+ #
1923
+ # 3 The format shall be a multibyte character sequence, beginning and
1924
+ # ending in its initial shift state. The format is composed of zero
1925
+ # or more directives: one or more white-space characters, an ordinary
1926
+ # multibyte character (neither % nor a white-space character), or a
1927
+ # conversion specification. Each conversion specification is
1928
+ # introduced by the character %. After the %, the following appear
1929
+ # in sequence:
1930
+ #
1931
+ # -- An optional assignment-suppressing character *.
1932
+ # -- An optional decimal integer greater than zero that specifies the
1933
+ # maximum field width (in characters).
1934
+ # -- An optional length modifier that specifies the size of the
1935
+ # receiving object.
1936
+ # -- A conversion specifier character that specifies the type of
1937
+ # conversion to be applied.
1938
+ format_str.slice!(/\A\s+/)
1939
+ end
1940
+
1941
+ def whitespace?
1942
+ true
1943
+ end
1944
+
1945
+ def ordinary?
1946
+ false
1947
+ end
1948
+
1949
+ def conversion_specifier?
1950
+ false
1951
+ end
1952
+
1953
+ def consume_arguments?
1954
+ false
1955
+ end
1956
+
1957
+ # === DESCRIPTION
1958
+ # Checks whether types of arguments match this directive.
1959
+ #
1960
+ # === RETURN VALUE
1961
+ # Boolean -- True if types of arguments match this directive.
1962
+ def acceptable?
1963
+ true
1964
+ end
1965
+
1966
+ # === DESCRIPTION
1967
+ # Checks whether the format string of this directive is the ISO C99
1968
+ # compliant.
1969
+ #
1970
+ # === RETURN VALUE
1971
+ # Boolean -- True if the format string is wellformed.
1972
+ def wellformed?
1973
+ true
1974
+ end
1975
+
1976
+ def complete?
1977
+ true
1978
+ end
1979
+
1980
+ def undefined?
1981
+ false
1982
+ end
1983
+
1984
+ def valid_assignment_suppressing_character?
1985
+ false
1986
+ end
1987
+
1988
+ def valid_field_width?
1989
+ false
1990
+ end
1991
+
1992
+ def valid_length_modifier?
1993
+ false
1994
+ end
1995
+
1996
+ def valid_conversion_specifier_character?
1997
+ false
1998
+ end
1999
+
2000
+ def valid_scanset?
2001
+ false
2002
+ end
2003
+
2004
+ def assignment_suppressing_character
2005
+ nil
2006
+ end
2007
+
2008
+ def field_width
2009
+ nil
2010
+ end
2011
+
2012
+ def length_modifier
2013
+ nil
2014
+ end
2015
+
2016
+ def conversion_specifier_character
2017
+ nil
2018
+ end
2019
+
2020
+ def scanset
2021
+ nil
2022
+ end
2023
+ end
2024
+ private_constant :Whitespace
2025
+
2026
+ class Ordinary < Directive
2027
+ def self.scan(format_str)
2028
+ # NOTE: The ISO C99 standard saids;
2029
+ #
2030
+ # 7.19.6.2 The fscanf function
2031
+ #
2032
+ # 3 The format shall be a multibyte character sequence, beginning and
2033
+ # ending in its initial shift state. The format is composed of zero
2034
+ # or more directives: one or more white-space characters, an ordinary
2035
+ # multibyte character (neither % nor a white-space character), or a
2036
+ # conversion specification. Each conversion specification is
2037
+ # introduced by the character %. After the %, the following appear
2038
+ # in sequence:
2039
+ #
2040
+ # -- An optional assignment-suppressing character *.
2041
+ # -- An optional decimal integer greater than zero that specifies the
2042
+ # maximum field width (in characters).
2043
+ # -- An optional length modifier that specifies the size of the
2044
+ # receiving object.
2045
+ # -- A conversion specifier character that specifies the type of
2046
+ # conversion to be applied.
2047
+ format_str.slice!(/\A[^%\s]+/)
2048
+ end
2049
+
2050
+ def whitespace?
2051
+ false
2052
+ end
2053
+
2054
+ def ordinary?
2055
+ true
2056
+ end
2057
+
2058
+ def conversion_specifier?
2059
+ false
2060
+ end
2061
+
2062
+ def consume_arguments?
2063
+ false
2064
+ end
2065
+
2066
+ # === DESCRIPTION
2067
+ # Checks whether types of arguments match this directive.
2068
+ #
2069
+ # === RETURN VALUE
2070
+ # Boolean -- True if types of arguments match this directive.
2071
+ def acceptable?
2072
+ true
2073
+ end
2074
+
2075
+ # === DESCRIPTION
2076
+ # Checks whether the format string of this directive is the ISO C99
2077
+ # compliant.
2078
+ #
2079
+ # === RETURN VALUE
2080
+ # Boolean -- True if the format string is wellformed.
2081
+ def wellformed?
2082
+ true
2083
+ end
2084
+
2085
+ def complete?
2086
+ true
2087
+ end
2088
+
2089
+ def undefined?
2090
+ false
2091
+ end
2092
+
2093
+ def valid_assignment_suppressing_character?
2094
+ false
2095
+ end
2096
+
2097
+ def valid_field_width?
2098
+ false
2099
+ end
2100
+
2101
+ def valid_length_modifier?
2102
+ false
2103
+ end
2104
+
2105
+ def valid_conversion_specifier_character?
2106
+ false
2107
+ end
2108
+
2109
+ def valid_scanset?
2110
+ false
2111
+ end
2112
+
2113
+ def assignment_suppressing_character
2114
+ nil
2115
+ end
2116
+
2117
+ def field_width
2118
+ nil
2119
+ end
2120
+
2121
+ def length_modifier
2122
+ nil
2123
+ end
2124
+
2125
+ def conversion_specifier_character
2126
+ nil
2127
+ end
2128
+
2129
+ def scanset
2130
+ nil
2131
+ end
2132
+ end
2133
+ private_constant :Ordinary
2134
+
2135
+ class ConversionSpecifier < Directive
2136
+ include TypeTableMediator
2137
+
2138
+ def self.scan(format_str)
2139
+ # NOTE: The ISO C99 standard saids;
2140
+ #
2141
+ # 7.19.6.2 The fscanf function
2142
+ #
2143
+ # 3 The format shall be a multibyte character sequence, beginning and
2144
+ # ending in its initial shift state. The format is composed of zero
2145
+ # or more directives: one or more white-space characters, an ordinary
2146
+ # multibyte character (neither % nor a white-space character), or a
2147
+ # conversion specification. Each conversion specification is
2148
+ # introduced by the character %. After the %, the following appear
2149
+ # in sequence:
2150
+ #
2151
+ # -- An optional assignment-suppressing character *.
2152
+ # -- An optional decimal integer greater than zero that specifies the
2153
+ # maximum field width (in characters).
2154
+ # -- An optional length modifier that specifies the size of the
2155
+ # receiving object.
2156
+ # -- A conversion specifier character that specifies the type of
2157
+ # conversion to be applied.
2158
+
2159
+ if header = format_str.slice!(/\A%/)
2160
+ scanned = header
2161
+ else
2162
+ return nil, nil, nil, nil, nil, nil
2163
+ end
2164
+
2165
+ if as_char = format_str.slice!(/\A#{as_char_re}/)
2166
+ scanned += as_char
2167
+ end
2168
+
2169
+ if field_width = format_str.slice!(/\A#{field_width_re}/)
2170
+ scanned += field_width
2171
+ end
2172
+
2173
+ if length_modifier = format_str.slice!(/\A#{length_modifier_re}/)
2174
+ scanned += length_modifier
2175
+ end
2176
+
2177
+ if cs_char = format_str.slice!(/\A#{cs_char_re}/)
2178
+ scanned += cs_char
2179
+ else
2180
+ # NOTE: If no valid conversion specifier character, force to scan
2181
+ # the heading 1 character as a conversion specifier character.
2182
+ if cs_char = format_str.slice!(/\A[a-z]/i)
2183
+ scanned += cs_char
2184
+ end
2185
+ end
2186
+
2187
+ if cs_char == "["
2188
+ if scanset = format_str.slice!(/\A#{scanset_re}/)
2189
+ scanned += scanset
2190
+ end
2191
+ else
2192
+ scanset = nil
2193
+ end
2194
+
2195
+ return scanned, as_char, field_width, length_modifier, cs_char, scanset
2196
+ end
2197
+
2198
+ def initialize(format, trailing_args, environment, consume_args,
2199
+ assignment_suppressing_character, field_width,
2200
+ length_modifier, conversion_specifier_character, scanset)
2201
+ super(format)
2202
+
2203
+ if assignment_suppressing_character == "*"
2204
+ @consume_arguments = false
2205
+ else
2206
+ @consume_arguments = consume_args
2207
+ end
2208
+
2209
+ @assignment_suppressing_character = assignment_suppressing_character
2210
+ @field_width = field_width
2211
+ @length_modifier = length_modifier
2212
+ @conversion_specifier_character = conversion_specifier_character
2213
+ @scanset = scanset
2214
+
2215
+ if consume_arguments?
2216
+ @conversion_argument = trailing_args.shift
2217
+ else
2218
+ @conversion_argument = nil
2219
+ end
2220
+
2221
+ @environment = environment
2222
+ end
2223
+
2224
+ def whitespace?
2225
+ false
2226
+ end
2227
+
2228
+ def ordinary?
2229
+ false
2230
+ end
2231
+
2232
+ def conversion_specifier?
2233
+ true
2234
+ end
2235
+
2236
+ def consume_arguments?
2237
+ @consume_arguments
2238
+ end
2239
+
2240
+ def undefined?
2241
+ false
2242
+ end
2243
+
2244
+ attr_reader :assignment_suppressing_character
2245
+ attr_reader :field_width
2246
+ attr_reader :length_modifier
2247
+ attr_reader :conversion_specifier_character
2248
+ attr_reader :scanset
2249
+ attr_reader :conversion_argument
2250
+
2251
+ def field_width_value
2252
+ case @field_width
2253
+ when /\A[1-9][0-9]*\z/
2254
+ @field_width.to_i
2255
+ else
2256
+ 1
2257
+ end
2258
+ end
2259
+
2260
+ def self.as_char_re
2261
+ /\*?/
2262
+ end
2263
+ private_class_method :as_char_re
2264
+
2265
+ def self.field_width_re
2266
+ /(?:[1-9][0-9]*)?/
2267
+ end
2268
+ private_class_method :field_width_re
2269
+
2270
+ def self.length_modifier_re
2271
+ # NOTE: The ISO C99 standard saids;
2272
+ #
2273
+ # 7.19.6.2 The fscanf function
2274
+ #
2275
+ # 11 The length modifiers and their meanings are:
2276
+ #
2277
+ # hh Specifies that a following d, i, o, u, x, X, or n conversion
2278
+ # specifier applies to an argument with type pointer to signed
2279
+ # char or unsigned char.
2280
+ # h Specifies that a following d, i, o, u, x, X, or n conversion
2281
+ # specifier applies to an argument with type pointer to short int
2282
+ # or unsigned short int.
2283
+ # l Specifies that a following d, i, o, u, x, X, or n conversion
2284
+ # specifier applies to an argument with type pointer to long int
2285
+ # or unsigned long int; that a following a, A, e, E, f, F, g, or
2286
+ # G conversion specifier applies to an argument with type pointer
2287
+ # to double; or that a following c, s, or [ conversion specifier
2288
+ # applies to an argument with type pointer to wchar_t.
2289
+ # ll Specifies that a following d, i, o, u, x, X, or n conversion
2290
+ # specifier applies to an argument with type pointer to long long
2291
+ # int or unsigned long long int.
2292
+ # j Specifies that a following d, i, o, u, x, X, or n conversion
2293
+ # specifier applies to an argument with type pointer to intmax_t
2294
+ # or uintmax_t.
2295
+ # z Specifies that a following d, i, o, u, x, X, or n conversion
2296
+ # specifier applies to an argument with type pointer to size_t or
2297
+ # the corresponding signed integer type.
2298
+ # t Specifies that a following d, i, o, u, x, X, or n conversion
2299
+ # specifier applies to an argument with type pointer to ptrdiff_t
2300
+ # or the corresponding unsigned integer type.
2301
+ # L Specifies that a following a, A, e, E, f, F, g, or G conversion
2302
+ # specifier applies to an argument with type pointer to long
2303
+ # double.
2304
+ /(?:h+|l+|j|z|t|L)?/
2305
+ end
2306
+ private_class_method :length_modifier_re
2307
+
2308
+ def self.cs_char_re
2309
+ # NOTE: The ISO C99 standard saids;
2310
+ #
2311
+ # 7.19.6.2 The fscanf function
2312
+ #
2313
+ # 12 The conversion specifiers and their meanings are:
2314
+ #
2315
+ # d Matches an optionally signed decimal integer, whose format
2316
+ # is the same as expected for the subject sequence of the
2317
+ # strtol function with the value 10 for the base argument.
2318
+ # The corresponding argument shall be a pointer to signed
2319
+ # integer.
2320
+ # i Matches an optionally signed integer, whose format is the
2321
+ # same as expected for the subject sequence of the strtol
2322
+ # function with the value 0 for the base argument. The
2323
+ # corresponding argument shall be a pointer to signed
2324
+ # integer.
2325
+ # o Matches an optionally signed octal integer, whose format
2326
+ # is the same as expected for the subject sequence of the
2327
+ # strtoul function with the value 8 for the base argument.
2328
+ # The corresponding argument shall be a pointer to unsigned
2329
+ # integer.
2330
+ # u Matches an optionally signed decimal integer, whose format
2331
+ # is the same as expected for the subject sequence of the
2332
+ # strtoul function with the value 10 for the base argument.
2333
+ # The corresponding argument shall be a pointer to unsigned
2334
+ # integer.
2335
+ # x Matches an optionally signed hexadecimal integer, whose
2336
+ # format is the same as expected for the subject sequence of
2337
+ # the strtoul function with the value 16 for the base
2338
+ # argument. The corresponding argument shall be a pointer
2339
+ # to unsigned integer.
2340
+ # a,e,f,g Matches an optionally signed floating-point number,
2341
+ # infinity, or NaN, whose format is the same as expected for
2342
+ # the subject sequence of the strtod function. The
2343
+ # corresponding argument shall be a pointer to floating.
2344
+ # c Matches a sequence of characters of exactly the number
2345
+ # specified by the field width (1 if no field width is
2346
+ # present in the directive).
2347
+ # If no l length modifier is present, the corresponding
2348
+ # argument shall be a pointer to the initial element of
2349
+ # character array large enough to accept the sequence. No
2350
+ # null character is added.
2351
+ # If an l length modifier is present, the input shall be a
2352
+ # sequence of multibyte characters that begins in the
2353
+ # initial shift state. Each multibyte character in the
2354
+ # sequence is converted to a wide character as if by a call
2355
+ # to the mbrtowc function, with the conversion state
2356
+ # described by an mbstate_t object initialized to zero
2357
+ # before the first multibyte character is converted. The
2358
+ # corresponding argument shall be a pointer to the initial
2359
+ # element of an array of wchar_t large enough to accept the
2360
+ # resulting sequence of wide characters. No null wide
2361
+ # character is added.
2362
+ # s Matches a sequence of non-white-space characters.
2363
+ # If no l length modifier is present, the corresponding
2364
+ # argument shall be a pointer to the initial element of a
2365
+ # character array large enough to accept the sequence and a
2366
+ # terminating null character, which will be added
2367
+ # automatically.
2368
+ # If an l length modifier is present, the input shall be a
2369
+ # sequence of multibyte characters that begins in the
2370
+ # initial shift state. Each multibyte character is
2371
+ # converted to a wide character as if by a call to the
2372
+ # mbrtowc function, with the conversion state described by
2373
+ # an mbstate_t object initialized to zero before the first
2374
+ # multibyte character is converted. The corresponding
2375
+ # argument shall be a pointer to the initial element of an
2376
+ # array of wchar_t large enough to accept the sequence and
2377
+ # the terminating null wide character, which will be added
2378
+ # automatically.
2379
+ # [ Matches a nonempty sequence of characters from a set of
2380
+ # expected characters (the scanset).
2381
+ # If no l length modifier is present, the corresponding
2382
+ # argument shall be a pointer to the initial element of a
2383
+ # character array large enough to accept the sequence and a
2384
+ # terminating null character, which will be added
2385
+ # automatically.
2386
+ # If an l length modifier is present, the input shall be a
2387
+ # sequence of multibyte characters that begins in the
2388
+ # initial shift state. Each multibyte character is
2389
+ # converted to a wide character as if by a call to the
2390
+ # mbrtowc function, with the conversion state described by
2391
+ # an mbstate_t object initialized to zero before the first
2392
+ # multibyte character is converted. The corresponding
2393
+ # argument shall be a pointer to the initial element of an
2394
+ # array of wchar_t large enough to accept the sequence and
2395
+ # the terminating null wide character, which will be added
2396
+ # automatically.
2397
+ # The conversion specifier includes all subsequent
2398
+ # characters in the format string, up to and including the
2399
+ # matching right bracket (]). The characters between the
2400
+ # brackets (the scanlist) compose the scanset, unless the
2401
+ # character after the left bracket is a circumflex (^), in
2402
+ # which case the scanset contains all characters that do not
2403
+ # appear in the scanlist between the circumflex and the
2404
+ # right bracket. If the conversion specifier begins with []
2405
+ # or [^], the right bracket character is in the scanlist and
2406
+ # the next following right bracket character is the matching
2407
+ # right bracket that ends the specification; otherwise the
2408
+ # first following right bracket character is the one that
2409
+ # ends the specification. If a - character is in the
2410
+ # scanlist and is not the first, nor the second where the
2411
+ # first character is a ^, nor the last character, the
2412
+ # behavior is implementation-defined.
2413
+ # p Matches an implementation-defined set of sequences, which
2414
+ # should be the same as the set of sequence that may be
2415
+ # produced by the %p conversion of the fprintf function.
2416
+ # The corresponding argument shall be a pointer to a pointer
2417
+ # to void. The input item is converted to a pointer value
2418
+ # in an implementation-defined manner. If the input item is
2419
+ # a value converted earlier during the same program
2420
+ # execution, the pointer that results shall compare equal to
2421
+ # the value; otherwise the behavior of the %p conversion is
2422
+ # undefined.
2423
+ # n No input is consumed. The corresponding argument shall be
2424
+ # a pointer to signed integer into which is to be written
2425
+ # the number of characters read from the input stream so far
2426
+ # by this call to the fscanf function. Execution of a %n
2427
+ # directive does not increment the assignment count returned
2428
+ # at the completion of execution of the fscanf function. No
2429
+ # argument is converted, but one is consumed. If the
2430
+ # conversion specification includes an
2431
+ # assignment-suppressing character or a field width, the
2432
+ # behavior is undefined.
2433
+ # % Matches a single % character; no conversion or assignment
2434
+ # occurs. The complete conversion specification shall be
2435
+ # %%.
2436
+ #
2437
+ # 14 The conversion specifiers A, E, F, G, and X are also valid and
2438
+ # behave the same as, respectively, a, e, f, g, and x.
2439
+ /[diouxXaAeEfFgGcs\[pn%]/
2440
+ end
2441
+ private_class_method :cs_char_re
2442
+
2443
+ def self.scanset_re
2444
+ # NOTE: The ISO C99 standard saids;
2445
+ #
2446
+ # 7.19.6.2 The fscanf function
2447
+ #
2448
+ # 12 The conversion specifiers and their meanings are:
2449
+ #
2450
+ # [ Matches a nonempty sequence of characters from a set of
2451
+ # expected characters (the scanset).
2452
+ # If no l length modifier is present, the corresponding
2453
+ # argument shall be a pointer to the initial element of a
2454
+ # character array large enough to accept the sequence and a
2455
+ # terminating null character, which will be added
2456
+ # automatically.
2457
+ # If an l length modifier is present, the input shall be a
2458
+ # sequence of multibyte characters that begins in the
2459
+ # initial shift state. Each multibyte character is
2460
+ # converted to a wide character as if by a call to the
2461
+ # mbrtowc function, with the conversion state described by
2462
+ # an mbstate_t object initialized to zero before the first
2463
+ # multibyte character is converted. The corresponding
2464
+ # argument shall be a pointer to the initial element of an
2465
+ # array of wchar_t large enough to accept the sequence and
2466
+ # the terminating null wide character, which will be added
2467
+ # automatically.
2468
+ # The conversion specifier includes all subsequent
2469
+ # characters in the format string, up to and including the
2470
+ # matching right bracket (]). The characters between the
2471
+ # brackets (the scanlist) compose the scanset, unless the
2472
+ # character after the left bracket is a circumflex (^), in
2473
+ # which case the scanset contains all characters that do not
2474
+ # appear in the scanlist between the circumflex and the
2475
+ # right bracket. If the conversion specifier begins with []
2476
+ # or [^], the right bracket character is in the scanlist and
2477
+ # the next following right bracket character is the matching
2478
+ # right bracket that ends the specification; otherwise the
2479
+ # first following right bracket character is the one that
2480
+ # ends the specification. If a - character is in the
2481
+ # scanlist and is not the first, nor the second where the
2482
+ # first character is a ^, nor the last character, the
2483
+ # behavior is implementation-defined.
2484
+ /\].*?\]|\^\].*?\]|.*?\]/
2485
+ end
2486
+ private_class_method :scanset_re
2487
+
2488
+ private
2489
+ def type_table
2490
+ @environment.type_table
2491
+ end
2492
+ end
2493
+ private_constant :ConversionSpecifier
2494
+
2495
+ class CompleteConversionSpecifier < ConversionSpecifier
2496
+ # === DESCRIPTION
2497
+ # Checks whether types of arguments match this directive.
2498
+ #
2499
+ # === RETURN VALUE
2500
+ # Boolean -- True if types of arguments match this directive.
2501
+ def acceptable?
2502
+ if @conversion_argument
2503
+ if argument_types
2504
+ argument_types.any? do |arg_type|
2505
+ @conversion_argument.type.same_as?(arg_type)
2506
+ end
2507
+ else
2508
+ true
2509
+ end
2510
+ else
2511
+ false
2512
+ end
2513
+ end
2514
+
2515
+ # === DESCRIPTION
2516
+ # Checks whether the format string of this directive is the ISO C99
2517
+ # compliant.
2518
+ #
2519
+ # === RETURN VALUE
2520
+ # Boolean -- True if the format string is wellformed.
2521
+ def wellformed?
2522
+ valid_assignment_suppressing_character? && valid_field_width? &&
2523
+ valid_length_modifier? && valid_conversion_specifier_character?
2524
+ end
2525
+
2526
+ def complete?
2527
+ true
2528
+ end
2529
+
2530
+ def valid_length_modifier?
2531
+ if length_modifier.empty?
2532
+ true
2533
+ else
2534
+ suitable_length_modifiers.include?(length_modifier)
2535
+ end
2536
+ end
2537
+
2538
+ private
2539
+ def argument_types
2540
+ if consume_arguments?
2541
+ subclass_responsibility
2542
+ else
2543
+ nil
2544
+ end
2545
+ end
2546
+
2547
+ def suitable_length_modifiers
2548
+ subclass_responsibility
2549
+ end
2550
+ end
2551
+ private_constant :CompleteConversionSpecifier
2552
+
2553
+ class Conversion_d < CompleteConversionSpecifier
2554
+ def self.suitable_conversion_specifier_character
2555
+ "d"
2556
+ end
2557
+
2558
+ def initialize(format, trailing_args, environment,
2559
+ assignment_suppressing_character, field_width,
2560
+ length_modifier, conversion_specifier_character, scanset)
2561
+ super(format, trailing_args, environment, true,
2562
+ assignment_suppressing_character, field_width,
2563
+ length_modifier, conversion_specifier_character, scanset)
2564
+ end
2565
+
2566
+ def valid_assignment_suppressing_character?
2567
+ true
2568
+ end
2569
+
2570
+ def valid_field_width?
2571
+ true
2572
+ end
2573
+
2574
+ def valid_conversion_specifier_character?
2575
+ true
2576
+ end
2577
+
2578
+ def valid_scanset?
2579
+ true
2580
+ end
2581
+
2582
+ private
2583
+ def argument_types
2584
+ # NOTE: The ISO C99 standard saids;
2585
+ #
2586
+ # 7.19.6.2 The fscanf function
2587
+ #
2588
+ # 11 The length modifiers and their meanings are:
2589
+ #
2590
+ # hh Specifies that a following d, i, o, u, x, X, or n conversion
2591
+ # specifier applies to an argument with type pointer to signed
2592
+ # char or unsigned char.
2593
+ # h Specifies that a following d, i, o, u, x, X, or n conversion
2594
+ # specifier applies to an argument with type pointer to short int
2595
+ # or unsigned short int.
2596
+ # l Specifies that a following d, i, o, u, x, X, or n conversion
2597
+ # specifier applies to an argument with type pointer to long int
2598
+ # or unsigned long int; that a following a, A, e, E, f, F, g, or
2599
+ # G conversion specifier applies to an argument with type pointer
2600
+ # to double; or that a following c, s, or [ conversion specifier
2601
+ # applies to an argument with type pointer to wchar_t.
2602
+ # ll Specifies that a following d, i, o, u, x, X, or n conversion
2603
+ # specifier applies to an argument with type pointer to long long
2604
+ # int or unsigned long long int.
2605
+ # j Specifies that a following d, i, o, u, x, X, or n conversion
2606
+ # specifier applies to an argument with type pointer to intmax_t
2607
+ # or uintmax_t.
2608
+ # z Specifies that a following d, i, o, u, x, X, or n conversion
2609
+ # specifier applies to an argument with type pointer to size_t or
2610
+ # the corresponding signed integer type.
2611
+ # t Specifies that a following d, i, o, u, x, X, or n conversion
2612
+ # specifier applies to an argument with type pointer to ptrdiff_t
2613
+ # or the corresponding unsigned integer type.
2614
+ case length_modifier
2615
+ when "hh"
2616
+ [pointer_type(signed_char_type), pointer_type(unsigned_char_type)]
2617
+ when "h"
2618
+ [pointer_type(signed_short_type), pointer_type(unsigned_short_type)]
2619
+ when "l"
2620
+ [pointer_type(signed_long_type), pointer_type(unsigned_long_type)]
2621
+ when "ll"
2622
+ [pointer_type(signed_long_long_type),
2623
+ pointer_type(unsigned_long_long_type)]
2624
+ when "j"
2625
+ # FIXME: `intmax_t' and `uintmax_t' are not supported yet.
2626
+ [pointer_type(signed_long_long_type),
2627
+ pointer_type(unsigned_long_long_type)]
2628
+ when "z"
2629
+ # FIXME: `size_t' is not supported yet.
2630
+ [pointer_type(signed_long_type), pointer_type(unsigned_long_type)]
2631
+ when "t"
2632
+ # FIXME: `ptrdiff_t' is not supported yet.
2633
+ [pointer_type(signed_int_type), pointer_type(unsigned_int_type)]
2634
+ else
2635
+ default_argument_types
2636
+ end
2637
+ end
2638
+
2639
+ def suitable_length_modifiers
2640
+ ["hh", "h", "l", "ll", "j", "z", "t"]
2641
+ end
2642
+
2643
+ def default_argument_types
2644
+ [pointer_type(signed_int_type)]
2645
+ end
2646
+ end
2647
+ private_constant :Conversion_d
2648
+
2649
+ class Conversion_i < Conversion_d
2650
+ def self.suitable_conversion_specifier_character
2651
+ "i"
2652
+ end
2653
+ end
2654
+ private_constant :Conversion_i
2655
+
2656
+ class Conversion_o < Conversion_d
2657
+ def self.suitable_conversion_specifier_character
2658
+ "o"
2659
+ end
2660
+
2661
+ private
2662
+ def default_argument_types
2663
+ [pointer_type(unsigned_int_type)]
2664
+ end
2665
+ end
2666
+ private_constant :Conversion_o
2667
+
2668
+ class Conversion_u < Conversion_o
2669
+ def self.suitable_conversion_specifier_character
2670
+ "u"
2671
+ end
2672
+ end
2673
+ private_constant :Conversion_u
2674
+
2675
+ class Conversion_x < Conversion_o
2676
+ def self.suitable_conversion_specifier_character
2677
+ "x"
2678
+ end
2679
+ end
2680
+ private_constant :Conversion_x
2681
+
2682
+ class Conversion_X < Conversion_o
2683
+ def self.suitable_conversion_specifier_character
2684
+ "X"
2685
+ end
2686
+ end
2687
+ private_constant :Conversion_X
2688
+
2689
+ class Conversion_a < CompleteConversionSpecifier
2690
+ def self.suitable_conversion_specifier_character
2691
+ "a"
2692
+ end
2693
+
2694
+ def initialize(format, trailing_args, environment,
2695
+ assignment_suppressing_character, field_width,
2696
+ length_modifier, conversion_specifier_character, scanset)
2697
+ super(format, trailing_args, environment, true,
2698
+ assignment_suppressing_character, field_width,
2699
+ length_modifier, conversion_specifier_character, scanset)
2700
+ end
2701
+
2702
+ def valid_assignment_suppressing_character?
2703
+ true
2704
+ end
2705
+
2706
+ def valid_field_width?
2707
+ true
2708
+ end
2709
+
2710
+ def valid_conversion_specifier_character?
2711
+ true
2712
+ end
2713
+
2714
+ def valid_scanset?
2715
+ true
2716
+ end
2717
+
2718
+ private
2719
+ def argument_types
2720
+ # NOTE: The ISO C99 standard saids;
2721
+ #
2722
+ # 7.19.6.2 The fscanf function
2723
+ #
2724
+ # 11 The length modifiers and their meanings are:
2725
+ #
2726
+ # l Specifies that a following d, i, o, u, x, X, or n conversion
2727
+ # specifier applies to an argument with type pointer to long int
2728
+ # or unsigned long int; that a following a, A, e, E, f, F, g, or
2729
+ # G conversion specifier applies to an argument with type pointer
2730
+ # to double; or that a following c, s, or [ conversion specifier
2731
+ # applies to an argument with type pointer to wchar_t.
2732
+ # L Specifies that a following a, A, e, E, f, F, g, or G conversion
2733
+ # specifier applies to an argument with type pointer to long
2734
+ # double.
2735
+ case length_modifier
2736
+ when "l"
2737
+ [pointer_type(double_type)]
2738
+ when "L"
2739
+ [pointer_type(long_double_type)]
2740
+ else
2741
+ [pointer_type(float_type)]
2742
+ end
2743
+ end
2744
+
2745
+ def suitable_length_modifiers
2746
+ ["l", "L"]
2747
+ end
2748
+ end
2749
+ private_constant :Conversion_a
2750
+
2751
+ class Conversion_A < Conversion_a
2752
+ def self.suitable_conversion_specifier_character
2753
+ "A"
2754
+ end
2755
+ end
2756
+ private_constant :Conversion_A
2757
+
2758
+ class Conversion_e < Conversion_a
2759
+ def self.suitable_conversion_specifier_character
2760
+ "e"
2761
+ end
2762
+ end
2763
+ private_constant :Conversion_e
2764
+
2765
+ class Conversion_E < Conversion_a
2766
+ def self.suitable_conversion_specifier_character
2767
+ "E"
2768
+ end
2769
+ end
2770
+ private_constant :Conversion_E
2771
+
2772
+ class Conversion_f < Conversion_a
2773
+ def self.suitable_conversion_specifier_character
2774
+ "f"
2775
+ end
2776
+ end
2777
+ private_constant :Conversion_f
2778
+
2779
+ class Conversion_F < Conversion_a
2780
+ def self.suitable_conversion_specifier_character
2781
+ "F"
2782
+ end
2783
+ end
2784
+ private_constant :Conversion_F
2785
+
2786
+ class Conversion_g < Conversion_a
2787
+ def self.suitable_conversion_specifier_character
2788
+ "g"
2789
+ end
2790
+ end
2791
+ private_constant :Conversion_g
2792
+
2793
+ class Conversion_G < Conversion_a
2794
+ def self.suitable_conversion_specifier_character
2795
+ "G"
2796
+ end
2797
+ end
2798
+ private_constant :Conversion_G
2799
+
2800
+ class Conversion_c < CompleteConversionSpecifier
2801
+ def self.suitable_conversion_specifier_character
2802
+ "c"
2803
+ end
2804
+
2805
+ def initialize(format, trailing_args, environment,
2806
+ assignment_suppressing_character, field_width,
2807
+ length_modifier, conversion_specifier_character, scanset)
2808
+ super(format, trailing_args, environment, true,
2809
+ assignment_suppressing_character, field_width,
2810
+ length_modifier, conversion_specifier_character, scanset)
2811
+ end
2812
+
2813
+ def valid_assignment_suppressing_character?
2814
+ true
2815
+ end
2816
+
2817
+ def valid_field_width?
2818
+ true
2819
+ end
2820
+
2821
+ def valid_conversion_specifier_character?
2822
+ true
2823
+ end
2824
+
2825
+ def valid_scanset?
2826
+ true
2827
+ end
2828
+
2829
+ private
2830
+ def argument_types
2831
+ # NOTE: The ISO C99 standard saids;
2832
+ #
2833
+ # 7.19.6.2 The fscanf function
2834
+ #
2835
+ # 11 The length modifiers and their meanings are:
2836
+ #
2837
+ # l Specifies that a following d, i, o, u, x, X, or n conversion
2838
+ # specifier applies to an argument with type pointer to long int
2839
+ # or unsigned long int; that a following a, A, e, E, f, F, g, or
2840
+ # G conversion specifier applies to an argument with type pointer
2841
+ # to double; or that a following c, s, or [ conversion specifier
2842
+ # applies to an argument with type pointer to wchar_t.
2843
+ case length_modifier
2844
+ when "l"
2845
+ [pointer_type(wchar_type)]
2846
+ else
2847
+ [pointer_type(signed_char_type), pointer_type(unsigned_char_type)]
2848
+ end
2849
+ end
2850
+
2851
+ def suitable_length_modifiers
2852
+ ["l"]
2853
+ end
2854
+ end
2855
+ private_constant :Conversion_c
2856
+
2857
+ class Conversion_s < Conversion_c
2858
+ def self.suitable_conversion_specifier_character
2859
+ "s"
2860
+ end
2861
+ end
2862
+ private_constant :Conversion_s
2863
+
2864
+ class Conversion_bracket < Conversion_c
2865
+ def self.suitable_conversion_specifier_character
2866
+ "["
2867
+ end
2868
+
2869
+ def valid_scanset?
2870
+ # NOTE: The `-' character in the scanset causes implementation-defined
2871
+ # behavior. So, AdLint treats the `-' character as an ordinary
2872
+ # character in the scanset.
2873
+ orig_set = scanset.chop.chars.to_a
2874
+ uniq_set = orig_set.uniq
2875
+ orig_set.size == uniq_set.size
2876
+ end
2877
+ end
2878
+ private_constant :Conversion_bracket
2879
+
2880
+ class Conversion_p < CompleteConversionSpecifier
2881
+ def self.suitable_conversion_specifier_character
2882
+ "p"
2883
+ end
2884
+
2885
+ def initialize(format, trailing_args, environment,
2886
+ assignment_suppressing_character, field_width,
2887
+ length_modifier, conversion_specifier_character, scanset)
2888
+ super(format, trailing_args, environment, true,
2889
+ assignment_suppressing_character, field_width,
2890
+ length_modifier, conversion_specifier_character, scanset)
2891
+ end
2892
+
2893
+ def valid_assignment_suppressing_character?
2894
+ true
2895
+ end
2896
+
2897
+ def valid_field_width?
2898
+ true
2899
+ end
2900
+
2901
+ def valid_conversion_specifier_character?
2902
+ true
2903
+ end
2904
+
2905
+ def valid_scanset?
2906
+ true
2907
+ end
2908
+
2909
+ private
2910
+ def argument_types
2911
+ if conversion_argument && conversion_argument.type.pointer?
2912
+ [conversion_argument.type.unqualify]
2913
+ else
2914
+ [pointer_type(void_type)]
2915
+ end
2916
+ end
2917
+
2918
+ def suitable_length_modifiers
2919
+ []
2920
+ end
2921
+ end
2922
+ private_constant :Conversion_p
2923
+
2924
+ class Conversion_n < CompleteConversionSpecifier
2925
+ def self.suitable_conversion_specifier_character
2926
+ "n"
2927
+ end
2928
+
2929
+ def initialize(format, trailing_args, environment,
2930
+ assignment_suppressing_character, field_width,
2931
+ length_modifier, conversion_specifier_character, scanset)
2932
+ super(format, trailing_args, environment, true,
2933
+ assignment_suppressing_character, field_width,
2934
+ length_modifier, conversion_specifier_character, scanset)
2935
+ end
2936
+
2937
+ def valid_assignment_suppressing_character?
2938
+ # NOTE: The ISO C99 standard saids;
2939
+ #
2940
+ # 7.19.6.2 The fscanf function
2941
+ #
2942
+ # 12 The conversion specifiers and their meanings are:
2943
+ #
2944
+ # n No input is consumed. The corresponding argument shall be
2945
+ # a pointer to signed integer into which is to be written
2946
+ # the number of characters read from the input stream so far
2947
+ # by this call to the fscanf function. Execution of a %n
2948
+ # directive does not increment the assignment count returned
2949
+ # at the completion of execution of the fscanf function. No
2950
+ # argument is converted, but one is consumed. If the
2951
+ # conversion specification includes an
2952
+ # assignment-suppressing character or a field width, the
2953
+ # behavior is undefined.
2954
+ assignment_suppressing_character.empty?
2955
+ end
2956
+
2957
+ def valid_field_width?
2958
+ field_width.empty?
2959
+ end
2960
+
2961
+ def valid_conversion_specifier_character?
2962
+ true
2963
+ end
2964
+
2965
+ def valid_scanset?
2966
+ true
2967
+ end
2968
+
2969
+ private
2970
+ def argument_types
2971
+ # NOTE: The ISO C99 standard saids;
2972
+ #
2973
+ # 7.19.6.2 The fscanf function
2974
+ #
2975
+ # 11 The length modifiers and their meanings are:
2976
+ #
2977
+ # hh Specifies that a following d, i, o, u, x, X, or n conversion
2978
+ # specifier applies to an argument with type pointer to signed
2979
+ # char or unsigned char.
2980
+ # h Specifies that a following d, i, o, u, x, X, or n conversion
2981
+ # specifier applies to an argument with type pointer to short int
2982
+ # or unsigned short int.
2983
+ # l Specifies that a following d, i, o, u, x, X, or n conversion
2984
+ # specifier applies to an argument with type pointer to long int
2985
+ # or unsigned long int; that a following a, A, e, E, f, F, g, or
2986
+ # G conversion specifier applies to an argument with type pointer
2987
+ # to double; or that a following c, s, or [ conversion specifier
2988
+ # applies to an argument with type pointer to wchar_t.
2989
+ # ll Specifies that a following d, i, o, u, x, X, or n conversion
2990
+ # specifier applies to an argument with type pointer to long long
2991
+ # int or unsigned long long int.
2992
+ # j Specifies that a following d, i, o, u, x, X, or n conversion
2993
+ # specifier applies to an argument with type pointer to intmax_t
2994
+ # or uintmax_t.
2995
+ # z Specifies that a following d, i, o, u, x, X, or n conversion
2996
+ # specifier applies to an argument with type pointer to size_t or
2997
+ # the corresponding signed integer type.
2998
+ # t Specifies that a following d, i, o, u, x, X, or n conversion
2999
+ # specifier applies to an argument with type pointer to ptrdiff_t
3000
+ # or the corresponding unsigned integer type.
3001
+ case length_modifier
3002
+ when "hh"
3003
+ [pointer_type(signed_char_type), pointer_type(unsigned_char_type)]
3004
+ when "h"
3005
+ [pointer_type(signed_short_type), pointer_type(unsigned_short_type)]
3006
+ when "l"
3007
+ [pointer_type(signed_long_type), pointer_type(unsigned_long_type)]
3008
+ when "ll"
3009
+ [pointer_type(signed_long_long_type),
3010
+ pointer_type(unsigned_long_long_type)]
3011
+ when "j"
3012
+ # FIXME: `intmax_t' and `uintmax_t' are not supported yet.
3013
+ [pointer_type(signed_long_long_type),
3014
+ pointer_type(unsigned_long_long_type)]
3015
+ when "z"
3016
+ # FIXME: `size_t' is not supported yet.
3017
+ [pointer_type(signed_long_type), pointer_type(unsigned_long_type)]
3018
+ when "t"
3019
+ # FIXME: `ptrdiff_t' is not supported yet.
3020
+ [pointer_type(signed_int_type), pointer_type(unsigned_int_type)]
3021
+ else
3022
+ [pointer_type(signed_int_type)]
3023
+ end
3024
+ end
3025
+
3026
+ def suitable_length_modifiers
3027
+ ["hh", "h", "l", "ll", "j", "z", "t"]
3028
+ end
3029
+ end
3030
+ private_constant :Conversion_n
3031
+
3032
+ class Conversion_percent < CompleteConversionSpecifier
3033
+ def self.suitable_conversion_specifier_character
3034
+ "%"
3035
+ end
3036
+
3037
+ def initialize(format, trailing_args, environment,
3038
+ assignment_suppressing_character, field_width,
3039
+ length_modifier, conversion_specifier_character, scanset)
3040
+ super(format, trailing_args, environment, false,
3041
+ assignment_suppressing_character, field_width,
3042
+ length_modifier, conversion_specifier_character, scanset)
3043
+ end
3044
+
3045
+ def valid_assignment_suppressing_character?
3046
+ # NOTE: The ISO C99 standard saids;
3047
+ #
3048
+ # 7.19.6.2 The fscanf function
3049
+ #
3050
+ # 12 The conversion specifiers and their meanings are:
3051
+ #
3052
+ # % Matches a single % character; no conversion or assignment
3053
+ # occurs. The complete conversion specification shall be
3054
+ # %%.
3055
+ assignment_suppressing_character.empty?
3056
+ end
3057
+
3058
+ def valid_field_width?
3059
+ field_width.empty?
3060
+ end
3061
+
3062
+ def valid_conversion_specifier_character?
3063
+ true
3064
+ end
3065
+
3066
+ def valid_scanset?
3067
+ true
3068
+ end
3069
+
3070
+ private
3071
+ def argument_types
3072
+ nil
3073
+ end
3074
+
3075
+ def suitable_length_modifiers
3076
+ []
3077
+ end
3078
+ end
3079
+ private_constant :Conversion_percent
3080
+
3081
+ class UndefinedConversionSpecifier < CompleteConversionSpecifier
3082
+ def initialize(format, assignment_suppressing_character, field_width,
3083
+ length_modifier, conversion_specifier_character)
3084
+ super(format, [], nil, false,
3085
+ assignment_suppressing_character, field_width,
3086
+ length_modifier, conversion_specifier_character, nil)
3087
+ end
3088
+
3089
+ def undefined?
3090
+ true
3091
+ end
3092
+
3093
+ def valid_assignment_suppressing_character?
3094
+ false
3095
+ end
3096
+
3097
+ def valid_field_width?
3098
+ false
3099
+ end
3100
+
3101
+ def valid_conversion_specifier_character?
3102
+ false
3103
+ end
3104
+
3105
+ def valid_scanset?
3106
+ true
3107
+ end
3108
+
3109
+ private
3110
+ def argument_types
3111
+ nil
3112
+ end
3113
+
3114
+ def suitable_length_modifiers
3115
+ []
3116
+ end
3117
+ end
3118
+ private_constant :UndefinedConversionSpecifier
3119
+
3120
+ class IncompleteConversionSpecifier < ConversionSpecifier
3121
+ def initialize(format, assignment_suppressing_character, field_width,
3122
+ length_modifier, conversion_specifier_character)
3123
+ super(format, [], nil, false, assignment_suppressing_character,
3124
+ field_width, length_modifier, conversion_specifier_character,
3125
+ nil)
3126
+ end
3127
+
3128
+ # === DESCRIPTION
3129
+ # Checks whether types of arguments match this directive.
3130
+ #
3131
+ # === RETURN VALUE
3132
+ # Boolean -- True if types of arguments match this directive.
3133
+ def acceptable?
3134
+ false
3135
+ end
3136
+
3137
+ # === DESCRIPTION
3138
+ # Checks whether the format string of this directive is the ISO C99
3139
+ # compliant.
3140
+ #
3141
+ # === RETURN VALUE
3142
+ # Boolean -- True if the format string is wellformed.
3143
+ def wellformed?
3144
+ false
3145
+ end
3146
+
3147
+ def complete?
3148
+ false
3149
+ end
3150
+
3151
+ def undefined?
3152
+ true
3153
+ end
3154
+
3155
+ def valid_assignment_suppressing_character?
3156
+ false
3157
+ end
3158
+
3159
+ def valid_field_width?
3160
+ false
3161
+ end
3162
+
3163
+ def valid_length_modifier?
3164
+ false
3165
+ end
3166
+
3167
+ def valid_conversion_specifier_character?
3168
+ conversion_specifier_character == "["
3169
+ end
3170
+
3171
+ def valid_scanset?
3172
+ conversion_specifier_character == "[" ? !scanset.nil? : false
3173
+ end
3174
+ end
3175
+ private_constant :IncompleteConversionSpecifier
3176
+
3177
+ CONVERSION_SPECIFIERS = [
3178
+ Conversion_d,
3179
+ Conversion_i,
3180
+ Conversion_o,
3181
+ Conversion_u,
3182
+ Conversion_x,
3183
+ Conversion_X,
3184
+ Conversion_a,
3185
+ Conversion_A,
3186
+ Conversion_e,
3187
+ Conversion_E,
3188
+ Conversion_f,
3189
+ Conversion_F,
3190
+ Conversion_g,
3191
+ Conversion_G,
3192
+ Conversion_c,
3193
+ Conversion_s,
3194
+ Conversion_bracket,
3195
+ Conversion_p,
3196
+ Conversion_n,
3197
+ Conversion_percent
3198
+ ]
3199
+ private_constant :CONVERSION_SPECIFIERS
3200
+
3201
+ CONVERSION_SPECIFIER_TBL =
3202
+ CONVERSION_SPECIFIERS.each_with_object({}) { |cs_class, hash|
3203
+ hash[cs_class.suitable_conversion_specifier_character] = cs_class
3204
+ }.freeze
3205
+ private_constant :CONVERSION_SPECIFIER_TBL
3206
+ end
3207
+
3208
+ end
3209
+ end