#' Analyze Three Dots and Return the Names and the Values
#'
#' @param ... The three dots to be analyzed.
#' @param omit_NULL = 0 to include the NULL arguments.
#' @param print_the_result = 1 to print the result
#' @param debug_Debug = 1 to print intermediate info
#'
#' @details
#' ... will be analyzed and the pair of ( name, val ) and name2
#'  will be returned.\cr
#'  See the first example below.
#'
#'  Note that, when ... is used, partial match of formal and actual arguments
#'  may cause a confusing error. \cr
#'  See the last example below.
#'
#' @return A list of: \cr
#' name  A vector consisting of the names of each of ... \cr
#' val   A list consisting of the values of each of ... or NULL \cr
#' name2  For the named arguments, name2 contains the righthand side of
#' the equal signs which appear in ... . \cr
#' For the positional arguments, name2 contains the actual argument itself.
#'
#'
#' @examples
#' cc="cccc"
#' analyze_three_dots( a=1, b=c(2,3), cc, list(aa=1,2), diag(2) )
#' analyze_three_dots( a=1, b=c(2,3), cc=NULL, d=0, NULL )
#' analyze_three_dots( a=1, b=c(2,3), cc=NULL, d=0, NULL, omit_NULL=0 )
#'
#' # a function to print all of ... with names
#' mprint <- function( ... ){
#'  atd=analyze_three_dots( ... )
#'  for( i in 1:length(atd$name) ){
#'   cat(atd$name[i], ":", atd$name2[i],"\n")
#'   print(atd$val[[i]])
#'  }
#' }
#' mprint( 1:5, b=7:11 )
#'#'
#' # About partial match of the arguments
#' # "e" will be missing
#' test <- function( exp, ..., debug_Debug=0 ){
#' 	res=analyze_three_dots( ..., debug_Debug=debug_Debug  )
#' 	Print(res)
#' }
#' expr="aaa"
#' test( expr, a=1, b=2, c=3, d=4, e=5, f=6, g=7 )
#'
#'
#'
#' @export
#'

analyze_three_dots <- function( ..., omit_NULL=1
                                , print_the_result=0, debug_Debug=0 ){
	# analyze three dots and return name and val
	# Shin-ichi Mayekawa
	# 20161127
	# bugfix: 20170513
	# roxgen2 added: 20170926
	# name2: 20200609dnc
	# example bugfix: 20200701
	# roxygen2: 20220719dnc
	# omit_NULL: 20220910
	# new method to get name: 20230508
	#

 # get name and value from ... : new method 20230508
 name2=as.character(substitute(list(...)))[-1L]
	name=names( as.list(substitute(list(...)))[-1L] )
	val=list(...)

	if( is.null(name) ) name=character(length(val))
	if( is.null(names(val)) ) names(val)=character(length(val))



	if( debug_Debug ){
		Print( name,val,name2)
	}

	if( length(val) == 0 ){
		return(NULL)
	}

	if( omit_NULL ){
  # Omit NULL elements
 	locnull=which(unlist(lapply(val,is.null)))
 	if( length(locnull) > 0 ){
 		name=name[-locnull]
 		name2=name2[-locnull]    # 20220910
 		val=val[-locnull]
 	}
	}
	n=length(name)

	if( n == 0 ) return( NULL )

	# replace the name by the value name if name does not contain name
	for( i in 1:n ){
		ni=names(val[i])
		if( debug_Debug ) Print(i,name[i],names(val[i]))
		if( length(ni) > 0 && ni != "" ){
			if( name[i] == "" ) name[i]=ni               # 20230508
		}
		else{
		 if( name[i] == "" ) name[i]=name2[i]         # 20230508
		}
	}

	if( print_the_result ){
		for( i in 1:n ){
			cat(i, ": name = ", name[i], ",   name2 = ", name2[i], sep="" )
			if( !is.list(val[[i]]) && !is.array(val[[i]]) )
				cat("   value = ", val[[i]], sep="", "\n")
			else{
				cat("\n")
		 	print(val[[i]])
			}
		}
	}

	return( list(name=name, val=val, name2=name2) )

} # end of analyze_three_dots


