adlint 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/AUTHORS +27 -0
- data/COPYING +674 -0
- data/ChangeLog +820 -0
- data/INSTALL +78 -0
- data/MANIFEST +464 -0
- data/NEWS +38 -0
- data/README +74 -0
- data/Rakefile +167 -0
- data/TODO +29 -0
- data/bin/adlint +141 -0
- data/bin/adlint_chk +129 -0
- data/bin/adlint_cma +122 -0
- data/bin/adlint_sma +129 -0
- data/bin/adlintize +286 -0
- data/etc/conf.d/fallback/cinit.erb +11 -0
- data/etc/conf.d/fallback/traits.erb +216 -0
- data/etc/conf.d/i686-cygwin/cinit-gcc_4.3.4.erb +149 -0
- data/etc/conf.d/i686-cygwin/traits-gcc_4.3.4.erb +227 -0
- data/etc/conf.d/i686-devkit/cinit-gcc_4.5.2.erb +224 -0
- data/etc/conf.d/i686-devkit/traits-gcc_4.5.2.erb +226 -0
- data/etc/conf.d/i686-linux/cinit-gcc_4.5.1.erb +219 -0
- data/etc/conf.d/i686-linux/traits-gcc_4.5.1.erb +224 -0
- data/etc/conf.d/i686-mingw/cinit-gcc_4.6.1.erb +234 -0
- data/etc/conf.d/i686-mingw/traits-gcc_4.6.1.erb +226 -0
- data/etc/conf.d/noarch/GNUmakefile.erb +119 -0
- data/etc/conf.d/noarch/adlint_all_bat.erb +9 -0
- data/etc/conf.d/noarch/adlint_all_sh.erb +10 -0
- data/etc/conf.d/noarch/pinit.erb +11 -0
- data/etc/mesg.d/en_US/messages.yml +784 -0
- data/etc/mesg.d/ja_JP/messages.yml +784 -0
- data/lib/adlint/analyzer.rb +294 -0
- data/lib/adlint/c/branch.rb +251 -0
- data/lib/adlint/c/builtin.rb +92 -0
- data/lib/adlint/c/code.rb +490 -0
- data/lib/adlint/c/const.rb +465 -0
- data/lib/adlint/c/conv.rb +212 -0
- data/lib/adlint/c/ctrlexpr.rb +949 -0
- data/lib/adlint/c/domain.rb +7499 -0
- data/lib/adlint/c/environ.rb +133 -0
- data/lib/adlint/c/expr.rb +1725 -0
- data/lib/adlint/c/format.rb +3209 -0
- data/lib/adlint/c/interp.rb +1740 -0
- data/lib/adlint/c/lexer.rb +241 -0
- data/lib/adlint/c/mediator.rb +313 -0
- data/lib/adlint/c/message.rb +13597 -0
- data/lib/adlint/c/metric.rb +765 -0
- data/lib/adlint/c/object.rb +1018 -0
- data/lib/adlint/c/parser.rb +3800 -0
- data/lib/adlint/c/parser.y +2054 -0
- data/lib/adlint/c/phase.rb +712 -0
- data/lib/adlint/c/resolver.rb +270 -0
- data/lib/adlint/c/scanner.rb +248 -0
- data/lib/adlint/c/scope.rb +74 -0
- data/lib/adlint/c/syntax.rb +4279 -0
- data/lib/adlint/c/type.rb +7506 -0
- data/lib/adlint/c/util.rb +91 -0
- data/lib/adlint/c/value.rb +2310 -0
- data/lib/adlint/c.rb +56 -0
- data/lib/adlint/code.rb +500 -0
- data/lib/adlint/cpp/code.rb +189 -0
- data/lib/adlint/cpp/constexpr.rb +721 -0
- data/lib/adlint/cpp/constexpr.y +389 -0
- data/lib/adlint/cpp/eval.rb +1012 -0
- data/lib/adlint/cpp/lexer.rb +860 -0
- data/lib/adlint/cpp/macro.rb +637 -0
- data/lib/adlint/cpp/message.rb +992 -0
- data/lib/adlint/cpp/phase.rb +176 -0
- data/lib/adlint/cpp/scanner.rb +93 -0
- data/lib/adlint/cpp/source.rb +169 -0
- data/lib/adlint/cpp/subst.rb +300 -0
- data/lib/adlint/cpp/syntax.rb +1412 -0
- data/lib/adlint/cpp/util.rb +97 -0
- data/lib/adlint/cpp.rb +43 -0
- data/lib/adlint/driver.rb +147 -0
- data/lib/adlint/error.rb +179 -0
- data/lib/adlint/lang.rb +97 -0
- data/lib/adlint/ld/message.rb +259 -0
- data/lib/adlint/ld/metric.rb +57 -0
- data/lib/adlint/ld/object.rb +542 -0
- data/lib/adlint/ld/phase.rb +193 -0
- data/lib/adlint/ld/typedef.rb +109 -0
- data/lib/adlint/ld/util.rb +88 -0
- data/lib/adlint/ld.rb +37 -0
- data/lib/adlint/lexer.rb +293 -0
- data/lib/adlint/message.rb +368 -0
- data/lib/adlint/metric.rb +805 -0
- data/lib/adlint/monitor.rb +144 -0
- data/lib/adlint/phase.rb +90 -0
- data/lib/adlint/prelude.rb +314 -0
- data/lib/adlint/report.rb +617 -0
- data/lib/adlint/source.rb +155 -0
- data/lib/adlint/symbol.rb +127 -0
- data/lib/adlint/token.rb +215 -0
- data/lib/adlint/traits.rb +643 -0
- data/lib/adlint/util.rb +524 -0
- data/lib/adlint/version.rb +71 -0
- data/lib/adlint.rb +66 -0
- data/share/HEADER +45 -0
- data/share/demo/Makefile +110 -0
- data/share/demo/ambig_operator/ambig_operator.c +289 -0
- data/share/demo/arg_points_unset/arg_points_unset.c +37 -0
- data/share/demo/array_range/array_range.c +62 -0
- data/share/demo/bad_bitfields/bad_bitfields.c +74 -0
- data/share/demo/bad_brace/bad_brace.c +19 -0
- data/share/demo/bad_charset/abcde$.h +0 -0
- data/share/demo/bad_charset/bad_charset.c +22 -0
- data/share/demo/bad_comment/bad_comment.c +3 -0
- data/share/demo/bad_const/bad_const.c +19 -0
- data/share/demo/bad_conv/bad_conv.c +48 -0
- data/share/demo/bad_indent/bad_indent.c +50 -0
- data/share/demo/bad_init/bad_init.c +49 -0
- data/share/demo/bad_macro/bad_macro.c +97 -0
- data/share/demo/bitwise_expr/bitwise_expr.c +19 -0
- data/share/demo/call_by_value/call_by_value.c +26 -0
- data/share/demo/cross_ref/cross_ref.c +21 -0
- data/share/demo/dangling_else/dangling_else.c +20 -0
- data/share/demo/dead_code/dead_code.c +237 -0
- data/share/demo/deep_nest/deep_nest.c +57 -0
- data/share/demo/dense_switch/dense_switch.c +62 -0
- data/share/demo/direct_recur/direct_recur.c +15 -0
- data/share/demo/div_by_zero/div_by_zero.c +35 -0
- data/share/demo/dos_source/dos_source.c +7 -0
- data/share/demo/funptr_cast/funptr_cast.c +26 -0
- data/share/demo/goto_stmt/goto_stmt.c +19 -0
- data/share/demo/id_hiding/id_hiding.c +19 -0
- data/share/demo/ill_defined/ill_defined.c +13 -0
- data/share/demo/implicit_conv/implicit_conv.c +60 -0
- data/share/demo/implicit_int/implicit_int.c +14 -0
- data/share/demo/incomplete_type/incomplete_type.c +49 -0
- data/share/demo/indirect_recur/indirect_recur_1.c +14 -0
- data/share/demo/indirect_recur/indirect_recur_1.h +7 -0
- data/share/demo/indirect_recur/indirect_recur_2.c +12 -0
- data/share/demo/indirect_recur/indirect_recur_2.h +6 -0
- data/share/demo/indirect_recur/indirect_recur_3.c +6 -0
- data/share/demo/indirect_recur/indirect_recur_3.h +6 -0
- data/share/demo/indirect_recur/indirect_recur_4.c +25 -0
- data/share/demo/intro_demo/intro_demo.c +76 -0
- data/share/demo/intro_demo/intro_demo.h +12 -0
- data/share/demo/intro_demo/useless_header.h +5 -0
- data/share/demo/invalid_call/invalid_call.c +32 -0
- data/share/demo/kandr_fundef/kandr_fundef.c +10 -0
- data/share/demo/line_comment/line_comment.c +12 -0
- data/share/demo/local_decl/local_decl.c +9 -0
- data/share/demo/logical_trick/logical_trick.c +36 -0
- data/share/demo/long_sym/long_sym.c +5 -0
- data/share/demo/loop_var/loop_var.c +92 -0
- data/share/demo/malloc_or_die/malloc_or_die.c +43 -0
- data/share/demo/may_be_null/may_be_null.c +52 -0
- data/share/demo/may_be_null_arith/may_be_null_arith.c +15 -0
- data/share/demo/may_be_unset/may_be_unset.c +34 -0
- data/share/demo/mmapped_io/mmapped_io.c +23 -0
- data/share/demo/multi_break/multi_break.c +33 -0
- data/share/demo/multi_decl/multi_decl_1.c +17 -0
- data/share/demo/multi_decl/multi_decl_1.h +6 -0
- data/share/demo/multi_decl/multi_decl_2.c +13 -0
- data/share/demo/multi_decl/multi_decl_2.h +6 -0
- data/share/demo/multi_decl/multi_decl_3.c +22 -0
- data/share/demo/multi_def/multi_def_1.c +36 -0
- data/share/demo/multi_def/multi_def_1.h +6 -0
- data/share/demo/multi_def/multi_def_2.c +22 -0
- data/share/demo/multi_def/multi_def_2.h +6 -0
- data/share/demo/multi_def/multi_def_3.c +6 -0
- data/share/demo/multi_typedef/multi_typedef.c +11 -0
- data/share/demo/multi_typedef/multi_typedef_1.h +1 -0
- data/share/demo/multi_typedef/multi_typedef_2.h +1 -0
- data/share/demo/must_be_false/must_be_false.c +53 -0
- data/share/demo/must_be_null/must_be_null.c +13 -0
- data/share/demo/must_be_null_arith/must_be_null_arith.c +14 -0
- data/share/demo/must_be_true/must_be_true.c +21 -0
- data/share/demo/no_eof_nl/no_eof_nl.c +4 -0
- data/share/demo/no_void_arg/no_void_arg.c +14 -0
- data/share/demo/null_stmt/null_stmt.c +19 -0
- data/share/demo/octal_const/octal_const.c +20 -0
- data/share/demo/output_by_param/output_by_param.c +17 -0
- data/share/demo/overflow/overflow.c +74 -0
- data/share/demo/press_release/press_release.c +40 -0
- data/share/demo/retn_lvar_addr/retn_lvar_addr.c +47 -0
- data/share/demo/shift_expr/shift_expr.c +14 -0
- data/share/demo/should_be_typedef/should_be_typedef.c +51 -0
- data/share/demo/static_paths/static_paths.c +153 -0
- data/share/demo/static_vars/static_vars.c +39 -0
- data/share/demo/tag_hiding/tag_hiding.c +18 -0
- data/share/demo/tricky_incdec/tricky_incdec.c +12 -0
- data/share/demo/undefined_macro/undefined_macro.c +17 -0
- data/share/demo/uninit_vars/uninit_vars.c +28 -0
- data/share/demo/union_type/union_type.c +23 -0
- data/share/demo/unmatch_decl/unmatch_decl_1.c +12 -0
- data/share/demo/unmatch_decl/unmatch_decl_1.h +8 -0
- data/share/demo/unmatch_decl/unmatch_decl_2.c +10 -0
- data/share/demo/unmatch_decl/unmatch_decl_2.h +8 -0
- data/share/demo/unmatch_decl/unmatch_decl_3.c +7 -0
- data/share/demo/unmatch_paren_macro/unmatch_paren_macro.c +15 -0
- data/share/demo/unreachable/unreachable.c +34 -0
- data/share/demo/useless_exp_funs/useless_exp_funs_1.c +14 -0
- data/share/demo/useless_exp_funs/useless_exp_funs_1.h +1 -0
- data/share/demo/useless_exp_funs/useless_exp_funs_2.c +6 -0
- data/share/demo/useless_exp_vars/useless_export_1.c +8 -0
- data/share/demo/useless_exp_vars/useless_export_1.h +1 -0
- data/share/demo/useless_exp_vars/useless_export_2.c +7 -0
- data/share/demo/useless_expr/useless_expr.c +17 -0
- data/share/demo/useless_funs/useless_funs_1.c +21 -0
- data/share/demo/useless_funs/useless_funs_1.h +8 -0
- data/share/demo/useless_funs/useless_funs_2.c +6 -0
- data/share/demo/useless_header/useless_header.c +9 -0
- data/share/demo/useless_header/useless_header_1.h +12 -0
- data/share/demo/useless_header/useless_header_2.h +6 -0
- data/share/demo/useless_header/useless_header_3.h +9 -0
- data/share/demo/useless_header/useless_header_4.h +3 -0
- data/share/demo/useless_vars/useless_vars.c +17 -0
- data/share/demo/va_funcall/va_funcall.c +25 -0
- data/share/demo/various_fundef/various_fundef.c +36 -0
- data/share/demo/wchar_wstring/wchar_wstring.c +7 -0
- data/share/demo/wrap_around/wrap_around.c +38 -0
- data/share/doc/Makefile +16 -0
- data/share/doc/adlint_on_adqua.png +0 -0
- data/share/doc/adlint_on_eclipse_en.png +0 -0
- data/share/doc/adlint_on_eclipse_ja.png +0 -0
- data/share/doc/adlint_on_vim_en.png +0 -0
- data/share/doc/adlint_on_vim_ja.png +0 -0
- data/share/doc/developers_guide_ja.html +171 -0
- data/share/doc/developers_guide_ja.texi +87 -0
- data/share/doc/gen_mesg_sections.rb +39 -0
- data/share/doc/samples/GNUmakefile +162 -0
- data/share/doc/samples/adlint_traits.yml +238 -0
- data/share/doc/texinfo.css +22 -0
- data/share/doc/users_guide_en.html +39975 -0
- data/share/doc/users_guide_en.texi +32640 -0
- data/share/doc/users_guide_ja.html +40505 -0
- data/share/doc/users_guide_ja.texi +33189 -0
- data/share/logo/adlint-110.png +0 -0
- data/share/logo/adlint-524.png +0 -0
- data/share/logo/adlint.svg +4637 -0
- data/share/sample/README +6 -0
- data/share/sample/bison-2.5/adlint/GNUmakefile +170 -0
- data/share/sample/bison-2.5/adlint/adlint_traits.yml +225 -0
- data/share/sample/bison-2.5/adlint/lib/GNUmakefile +198 -0
- data/share/sample/bison-2.5/adlint/lib/adlint_cinit.h +228 -0
- data/share/sample/bison-2.5/adlint/lib/adlint_pinit.h +21 -0
- data/share/sample/bison-2.5/adlint/lib/adlint_traits.yml +238 -0
- data/share/sample/bison-2.5/adlint/src/GNUmakefile +166 -0
- data/share/sample/bison-2.5/adlint/src/adlint_cinit.h +228 -0
- data/share/sample/bison-2.5/adlint/src/adlint_pinit.h +21 -0
- data/share/sample/bison-2.5/adlint/src/adlint_traits.yml +239 -0
- data/share/sample/ctags-5.8/adlint/GNUmakefile +169 -0
- data/share/sample/ctags-5.8/adlint/adlint_cinit.h +219 -0
- data/share/sample/ctags-5.8/adlint/adlint_pinit.h +13 -0
- data/share/sample/ctags-5.8/adlint/adlint_traits.yml +225 -0
- data/share/sample/flex-2.5.35/adlint/GNUmakefile +140 -0
- data/share/sample/flex-2.5.35/adlint/adlint_cinit.h +219 -0
- data/share/sample/flex-2.5.35/adlint/adlint_pinit.h +14 -0
- data/share/sample/flex-2.5.35/adlint/adlint_traits.yml +225 -0
- data/share/sample/ruby-1.9.3-p0/adlint/GNUmakefile +314 -0
- data/share/sample/ruby-1.9.3-p0/adlint/adlint_traits.yml +225 -0
- data/share/sample/ruby-1.9.3-p0/adlint/core/GNUmakefile +204 -0
- data/share/sample/ruby-1.9.3-p0/adlint/core/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/core/adlint_pinit.h +28 -0
- data/share/sample/ruby-1.9.3-p0/adlint/core/adlint_traits.yml +240 -0
- data/share/sample/ruby-1.9.3-p0/adlint/enc/GNUmakefile +163 -0
- data/share/sample/ruby-1.9.3-p0/adlint/enc/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/enc/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/enc/adlint_traits.yml +240 -0
- data/share/sample/ruby-1.9.3-p0/adlint/enc-trans/GNUmakefile +149 -0
- data/share/sample/ruby-1.9.3-p0/adlint/enc-trans/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/enc-trans/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/enc-trans/adlint_traits.yml +240 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-bigdecimal/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-bigdecimal/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-bigdecimal/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-bigdecimal/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-continuation/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-continuation/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-continuation/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-continuation/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-coverage/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-coverage/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-coverage/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-coverage/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-curses/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-curses/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-curses/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-curses/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-date/GNUmakefile +134 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-date/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-date/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-date/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-dbm/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-dbm/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-dbm/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-dbm/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-bubblebabble/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-bubblebabble/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-bubblebabble/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-bubblebabble/adlint_traits.yml +242 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-md5/GNUmakefile +132 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-md5/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-md5/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-md5/adlint_traits.yml +242 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-rmd160/GNUmakefile +132 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-rmd160/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-rmd160/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-rmd160/adlint_traits.yml +242 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha1/GNUmakefile +132 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha1/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha1/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha1/adlint_traits.yml +242 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha2/GNUmakefile +132 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha2/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha2/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-digest-sha2/adlint_traits.yml +242 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-dl/GNUmakefile +134 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-dl/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-dl/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-dl/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-dl-callback/GNUmakefile +140 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-dl-callback/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-dl-callback/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-dl-callback/adlint_traits.yml +242 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-etc/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-etc/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-etc/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-etc/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-fcntl/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-fcntl/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-fcntl/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-fcntl/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-fiber/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-fiber/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-fiber/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-fiber/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-fiddle/GNUmakefile +134 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-fiddle/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-fiddle/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-fiddle/adlint_traits.yml +242 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-gdbm/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-gdbm/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-gdbm/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-gdbm/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-iconv/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-iconv/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-iconv/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-iconv/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-io-console/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-io-console/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-io-console/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-io-console/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-io-nonblock/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-io-nonblock/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-io-nonblock/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-io-nonblock/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-io-wait/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-io-wait/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-io-wait/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-io-wait/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-json-generator/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-json-generator/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-json-generator/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-json-generator/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-json-parser/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-json-parser/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-json-parser/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-json-parser/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-complex/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-complex/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-complex/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-complex/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-rational/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-rational/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-rational/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-mathn-rational/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-nkf/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-nkf/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-nkf/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-nkf/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-openssl/GNUmakefile +162 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-openssl/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-openssl/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-openssl/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-pathname/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-pathname/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-pathname/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-pathname/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-psych/GNUmakefile +135 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-psych/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-psych/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-psych/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-pty/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-pty/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-pty/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-pty/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-racc-cparse/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-racc-cparse/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-racc-cparse/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-racc-cparse/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-readline/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-readline/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-readline/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-readline/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-ripper/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-ripper/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-ripper/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-ripper/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-sdbm/GNUmakefile +132 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-sdbm/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-sdbm/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-sdbm/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-socket/GNUmakefile +144 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-socket/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-socket/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-socket/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-stringio/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-stringio/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-stringio/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-stringio/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-strscan/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-strscan/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-strscan/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-strscan/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-syck/GNUmakefile +140 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-syck/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-syck/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-syck/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-syslog/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-syslog/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-syslog/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-syslog/adlint_traits.yml +241 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-zlib/GNUmakefile +131 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-zlib/adlint_cinit.h +228 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-zlib/adlint_pinit.h +24 -0
- data/share/sample/ruby-1.9.3-p0/adlint/ext-zlib/adlint_traits.yml +241 -0
- data/share/sample/screen-4.0.3/adlint/GNUmakefile +162 -0
- data/share/sample/screen-4.0.3/adlint/adlint_cinit.h +228 -0
- data/share/sample/screen-4.0.3/adlint/adlint_pinit.h +21 -0
- data/share/sample/screen-4.0.3/adlint/adlint_traits.yml +238 -0
- data/share/sample/vim-7.3/adlint/vim/GNUmakefile +185 -0
- data/share/sample/vim-7.3/adlint/vim/adlint_cinit.h +228 -0
- data/share/sample/vim-7.3/adlint/vim/adlint_pinit.h +25 -0
- data/share/sample/vim-7.3/adlint/vim/adlint_traits.yml +250 -0
- data/share/sample/vim-7.3/adlint/xxd/GNUmakefile +131 -0
- data/share/sample/vim-7.3/adlint/xxd/adlint_cinit.h +228 -0
- data/share/sample/vim-7.3/adlint/xxd/adlint_pinit.h +24 -0
- data/share/sample/vim-7.3/adlint/xxd/adlint_traits.yml +237 -0
- data/share/sample/zsh-4.3.15/adlint/GNUmakefile +146 -0
- data/share/sample/zsh-4.3.15/adlint/adlint_traits.yml +225 -0
- data/share/sample/zsh-4.3.15/adlint/builtins/GNUmakefile +132 -0
- data/share/sample/zsh-4.3.15/adlint/builtins/adlint_cinit.h +228 -0
- data/share/sample/zsh-4.3.15/adlint/builtins/adlint_pinit.h +24 -0
- data/share/sample/zsh-4.3.15/adlint/builtins/adlint_traits.yml +240 -0
- data/share/sample/zsh-4.3.15/adlint/core/GNUmakefile +153 -0
- data/share/sample/zsh-4.3.15/adlint/core/adlint_cinit.h +228 -0
- data/share/sample/zsh-4.3.15/adlint/core/adlint_pinit.h +23 -0
- data/share/sample/zsh-4.3.15/adlint/core/adlint_traits.yml +239 -0
- data/share/sample/zsh-4.3.15/adlint/modules/GNUmakefile +147 -0
- data/share/sample/zsh-4.3.15/adlint/modules/adlint_cinit.h +228 -0
- data/share/sample/zsh-4.3.15/adlint/modules/adlint_pinit.h +24 -0
- data/share/sample/zsh-4.3.15/adlint/modules/adlint_traits.yml +240 -0
- data/share/sample/zsh-4.3.15/adlint/zle/GNUmakefile +144 -0
- data/share/sample/zsh-4.3.15/adlint/zle/adlint_cinit.h +228 -0
- data/share/sample/zsh-4.3.15/adlint/zle/adlint_pinit.h +24 -0
- data/share/sample/zsh-4.3.15/adlint/zle/adlint_traits.yml +239 -0
- data/spec/MUST_WRITE_SPECS_WITH_RSPEC +0 -0
- 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
|