adlint 1.0.0

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