Class: ParamDecl

Inherits:
BDNode show all
Defined in:
lib/tecsgen/core/syntaxobj.rb,
lib/tecsgen/core/tecsinfo.rb

Overview

関数パラメータの宣言

Instance Method Summary collapse

Methods inherited from BDNode

#get_owner, #set_owner

Methods inherited from Node

#cdl_error, #cdl_error2, #cdl_error3, #cdl_info, #cdl_info2, #cdl_warning, #cdl_warning2, #get_locale, #locale_str, #set_locale

Constructor Details

#initialize(declarator, specifier, param_specifier) ⇒ ParamDecl

  1. ポインタレベルが適切なこと



717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
# File 'lib/tecsgen/core/syntaxobj.rb', line 717

def initialize(declarator, specifier, param_specifier)
  super()
  @declarator = declarator
  @declarator.set_owner self # Decl (ParamDecl)
  @declarator.set_type(specifier)
  @param_specifier = param_specifier
  @b_ref = false
  @b_nullable = false

  if @declarator.is_function? # (1)
    cdl_error("S2006 \'$1\' function", get_name)
    return
  end

  res = @declarator.check
  if res # (2)
    cdl_error("S2007 \'$1\' $2", get_name, res)
    return
  end

  @param_specifier.each {|i|
    case i[0] # (3)
    when :IN, :OUT, :INOUT, :SEND, :RECEIVE
      if @direction.nil?
        @direction = i[0]
      elsif i[0] == @direction
        cdl_warning("W3001 $1: duplicate", i[0])
        next
      else
        cdl_error("S2008 $1: inconsitent with previous one", i[0])
        next
      end

      case i[0]
      when :SEND, :RECEIVE
        @allocator = Namespace.find(i[1]) # 1
        if !@allocator.instance_of?(Signature)
          cdl_error("S2009 $1: not found or not signature", i[1])
          next
        elsif !@allocator.is_allocator?
          # cdl_error( "S2010 $1: not allocator signature" , i[1] )
        end
      end

    when :SIZE_IS
      if @size
        cdl_error("S2011 size_is duplicate")
      else
        @size = i[1]
      end
    when :COUNT_IS
      if @count
        cdl_error("S2012 count_is duplicate")
      else
        @count = i[1]
      end
    when :STRING
      if @string
        cdl_error("S2013 string duplicate")
      elsif i[1]
        @string = i[1]
      else
        @string = -1
      end
    when :MAX_IS
      # max_is は、内部的なもの bnf.y.rb 参照
      # size_is で重複チェックされる
      @max = i[1]
    when :NULLABLE
      # if ! @declarator.get_type.kind_of?( PtrType ) then
      #  cdl_error( "S2026 '$1' nullable specified for non-pointer type", @declarator.get_name )
      # else
      @b_nullable = true
      # end
    end

  }

  if @direction.nil?
    cdl_error("S2014 No direction specified. [in/out/inout/send/receive]")
  end

  if (@direction == :OUT || @direction == :INOUT) && @string == -1
    cdl_warning("W3002 $1: this string might cause buffer over run", get_name)
  end

  # mikan ポインタの配列(添数有)のレベルが0
  ptr_level = @declarator.get_ptr_level

  # p "ptr_level: #{@declarator.get_identifier} #{ptr_level}"
  # p @declarator

  #----  set req_level, min_level & max_level  ----#
  if !(@size || @count || @string) # (4)
    req_level = 1
  elsif (@size || @count) && @string
    req_level = 2
  else
    req_level = 1
  end

  if @direction == :RECEIVE
    req_level += 1
  end
  min_level = req_level
  max_level = req_level

  # IN without pointer specifier can be non-pointer type
  if @direction == :IN && !(@size || @count || @string)
    min_level = 0
  end

  # if size_is specified and pointer refer to struct, max_level increase
  if @size
    type = @declarator.get_type.get_original_type
    while type.is_a? PtrType
      type = type.get_referto.get_original_type
    end
    if type.is_a? StructType
      max_level += 1
    end
  end
  #----  end req_level & max_level    ----#

  # p "req_level: #{req_level} ptr_level: #{ptr_level}"
  # if ptr_level < req_level && ! ( @direction == :IN && req_level == 1 && ptr_level == 0) then
  if ptr_level < min_level
    cdl_error("S2014 $1 need pointer or more pointer", @declarator.get_identifier)
  elsif ptr_level > max_level
    # note: 構文解析段階で実行のため get_current 可
    if Signature.get_current.nil? || Signature.get_current.is_deviate? == false
      cdl_warning("W3003 $1 pointer level mismatch", @declarator.get_identifier)
    end
  end

  type = @declarator.get_type
  while type.is_a?(DefinedType)
    type = type.get_original_type
  end

  if ptr_level > 0
    # size_is, count_is, string をセット
    if @direction == :RECEIVE && ptr_level > 1
      type.get_type.set_scs(@size, @count, @string, @max, @b_nullable)
    else
      type.set_scs(@size, @count, @string, @max, @b_nullable)
    end

# p ptr_level
# type.show_tree 1

    # ポインタが指している先のデータ型を得る
    i = 0
    t2 = type
    while i < ptr_level
      t2 = t2.get_referto
      while t2.is_a?(DefinedType)
        t2 = t2.get_original_type
      end
      i += 1
    end

# p @declarator.get_name
# t2.show_tree 1
# p t2.is_const?

    # const 修飾が適切かチェック
    if @direction == :IN
      if !t2.is_const?
        cdl_error("S2015 '$1' must be const for \'in\' parameter $2", get_name, type.class)
      end
    else
      if t2.is_const?
        cdl_error("S2016 '$1' can not be const for $2 parameter", get_name, @direction)
      end
    end
  else
    # 非ポインタタイプ
    if !@size.nil? || !@count.nil? || !@string.nil? || !@max.nil? || @b_nullable
      type.set_scs(@size, @count, @string, @max, @b_nullable)
    end
  end

#    if ptr_level > 0 && @direction == :IN then
#      if type.is_const != :CONST
#    end

  # p self
end

Instance Method Details

#check_struct_tag(kind) ⇒ Object



907
908
909
# File 'lib/tecsgen/core/syntaxobj.rb', line 907

def check_struct_tag(kind)
  @declarator.get_type.check_struct_tag :PARAMETER
end

#clear_maxObject



931
932
933
934
935
# File 'lib/tecsgen/core/syntaxobj.rb', line 931

def clear_max
  # p "clear_max: #{@declarator.get_name} #{@max.to_s}"
  @max = nil
  @declarator.get_type.clear_max
end

#get_allocatorObject



953
954
955
# File 'lib/tecsgen/core/syntaxobj.rb', line 953

def get_allocator
  @allocator
end

#get_countObject



919
920
921
# File 'lib/tecsgen/core/syntaxobj.rb', line 919

def get_count
  @count
end

#get_declaratorObject



949
950
951
# File 'lib/tecsgen/core/syntaxobj.rb', line 949

def get_declarator
  @declarator
end

#get_directionObject



945
946
947
# File 'lib/tecsgen/core/syntaxobj.rb', line 945

def get_direction
  @direction
end

#get_maxObject



927
928
929
# File 'lib/tecsgen/core/syntaxobj.rb', line 927

def get_max
  @max
end

#get_nameObject



911
912
913
# File 'lib/tecsgen/core/syntaxobj.rb', line 911

def get_name
  @declarator.get_name
end

#get_sizeObject



915
916
917
# File 'lib/tecsgen/core/syntaxobj.rb', line 915

def get_size
  @size
end

#get_stringObject



923
924
925
# File 'lib/tecsgen/core/syntaxobj.rb', line 923

def get_string
  @string
end

#get_typeObject



941
942
943
# File 'lib/tecsgen/core/syntaxobj.rb', line 941

def get_type
  @declarator.get_type
end

#is_nullable?Boolean

Returns:

  • (Boolean)


937
938
939
# File 'lib/tecsgen/core/syntaxobj.rb', line 937

def is_nullable?
  @b_nullable
end

#is_referenced?Boolean

Returns:

  • (Boolean)


961
962
963
# File 'lib/tecsgen/core/syntaxobj.rb', line 961

def is_referenced?
  @b_ref
end

#need_PPAllocator?(b_opaque = false) ⇒ Boolean

PPAllocator が必要か

Transparent RPC の場合 in で size_is, count_is, string のいずれかが指定されている場合 oneway では PPAllocator が必要Transparent PC で oneway かどうかは、ここでは判断しないので別途判断が必要Opaque RPC の場合 size_is, count_is, string のいずれかが指定されている場合、PPAllocator が必要

Returns:

  • (Boolean)


969
970
971
972
973
974
975
976
977
978
979
980
981
982
# File 'lib/tecsgen/core/syntaxobj.rb', line 969

def need_PPAllocator?(b_opaque = false)
  if !b_opaque
#      if @direction == :IN && ( @size || @count || @string ) then
    if @direction == :IN && @declarator.get_type.get_original_type.is_a?(PtrType)
      return true
    end
  else
    if (@direction == :IN || @direction == :OUT || @direction == :INOUT) &&
        @declarator.get_type.get_original_type.is_a?(PtrType)
      return true
    end
  end
  return false
end


712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
# File 'lib/tecsgen/core/tecsinfo.rb', line 712

def print_info(f, signature_global_name, func_name, paramdecl_list, indent)
  if @size
    size = "\"#{@size.get_rpn(paramdecl_list)}\""
  else
    size = "(char_t*)0"
  end
  if @count
    count = "\"#{@count.get_rpn(paramdecl_list)}\""
  else
    count = "(char_t*)0"
  end
  if @string
    if @string == -1
      string = '""'
    else
      string =  "\"#{@string.get_rpn(paramdecl_list)}\""
    end
  else
    string = "(char_t*)0"
  end
  f.print <<EOT
#{indent}cell nTECSInfo::tParamInfo #{signature_global_name}_#{func_name}_#{get_name}ParamInfo {
#{indent}    name            = "#{get_name}";
#{indent}    dir             = PARAM_DIR_#{@direction};
#{indent}    sizeIsExpr      = #{size};
#{indent}    countIsExpr     = #{count};
#{indent}    stringExpr      = #{string};
#{indent}    cTypeInfo       = #{get_type.get_ID_str}TypeInfo.eTypeInfo;
#{indent}};
EOT
  get_type.print_info f, indent
end

#referencedObject



957
958
959
# File 'lib/tecsgen/core/syntaxobj.rb', line 957

def referenced
  @b_ref = true
end

#show_tree(indent) ⇒ Object



984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
# File 'lib/tecsgen/core/syntaxobj.rb', line 984

def show_tree(indent)
  indent.times { print "  " }
  puts "ParamDecl: direction: #{@direction} #{locale_str}"
  @declarator.show_tree(indent + 1)
  if @size
    (indent + 1).times { print "  " }
    puts "size:"
    @size.show_tree(indent + 2)
  end
  if @count
    (indent + 1).times { print "  " }
    puts "count:"
    @count.show_tree(indent + 2)
  end
  if @string
    (indent + 1).times { print "  " }
    puts "string:"
    if @string == -1
      (indent + 2).times { print "  " }
      puts "size is not specified"
    else
      @string.show_tree(indent + 2)
    end
  end
  if @allocator
    (indent + 1).times { print "  " }
    puts "allocator: signature: #{@allocator.get_name}"
  end
end