# (C) Copyright International Business Machines Corporation 23 January 
# 1990.  All Rights Reserved. 
#  
# See the file USERAGREEMENT distributed with this software for full 
# terms and conditions of use. 
# SCCS Info: @(#)hcalls.awk	1.10 3/14/90

# This awk script produces cpp macro definitions from the greencard,
# for most of the LI instructions.  In most cases, the macro is given
# the same name as the instruction, but in cases where that would
# cause a conflict with the C language (e.g. 'and'), the instruction
# name is prepended with "h_" to form the macro name.

# There are a few instructions for which the rules in this script
# cannot produce a correct macro.  Individual macros for those
# instructions can be created by hand, or they can just be left out if
# not needed.

BEGIN {
    # Greencard fields separated by a vertical bar
    FS = "|"
    # instruction names that conflict with the C language
    c_names = "/and/or/not/return/if/case/boolean/size/typename/exit/"
    # instructions with difficult qualifiers, which we don't handle
    weird = "/exit/block/branch/drop/raise/trace/"
    # various categories of qualifier type
    record_quals = "/integer_pair/polymorph_info/callmessage_finalizer" \
      "/user_exception/typename/program/"
    table_quals = "/keyset/label_list/handler_list/"
    integer_quals = "/label/"
    nominal_quals = "/exitid/"
}

# We're only interested in the lines describing instructions, which
# always start with a LOWER CASE letter
/^[a-z_]/ {
    if (index("ABCDEFGHIJKLMNOPQRSTUVWXYZ", substr($0, 1, 1)) != 0)
      next
    # Pick out the function name, operand list, and qualifier specification
    fn = substr($1,0,index(($1 " ")," ")-1)
    args = substr($2,0,index(($2 " ")," ")-1)
    qual = substr($3,0,index(($3 " ")," ")-1)
    # zero-terminated args list, for use in calls to h_call which uses
    # the varargs mechanism
    if (length(args) == 0)
      varargs = "0"
    else
      varargs = args ",0"

    # Add prefix to instruction name if necessary to get macro name
    if (index(c_names,("/" fn "/")) != 0)
        macro = "h_" fn
    else
        macro = fn

    # We don't handle instructions with variable number of operands,
    # or a couple of instructions whose names correspond to
    # interpreter functions.  We log them to a file...
    if ( index(args,"...") != 0 || fn == "chs_lit" || fn == "new_table" ) 
        print fn " macro must be done manually." >"manualmacros"
    else {
	# Build the macro definition according to the type of
        # qualifier... The h_call routine expects a pointer to the
        # function implementing the instruction, followed by the
	# qualifier if any, followed by the instruction operands,
	# followed by a zero
	if ( length(qual) == 0 )
	  # No qualifier...
	  print sprintf("#define %s(%s) h_call(o_%s, %s)", \
	    macro, args, fn, varargs)
	else {
	  # We have a qualifier... translate specialized qualifier
	  # types to their base types
	  if (index(record_quals,"/" qual "/") != 0)
	    qual = "record"
	  else if (index(table_quals,"/" qual "/") != 0)
	    qual = "table"
	  else if (index(integer_quals,"/" qual "/") != 0)
	    qual = "integer"
	  else if (index(nominal_quals,"/" qual "/") != 0)
	    qual = "nominal"

	  # Special case for new_record, where we allow them to say
	  # new_record(dst,typename) and we generate typename__Size as
	  # the qualifier value
	  if ( fn == "new_record" ) {
	    print sprintf("#define %s(%s, %sp) (\\", macro, args, qual)
	    print sprintf("  _qh.val.%s = %sp/**/__Size, \\", qual, qual)
	    print sprintf("  h_qcall(o_%s, _qh, %s))", fn, varargs)
	  }
	  else {
	    # Remaining cases with qualifier just use the qualifier as
	    # given in the macro call
	    if (length(args) == 0)
	      print sprintf("#define %s(%sp) (\\", macro, qual)
	    else
	      print sprintf("#define %s(%s, %sp) (\\", macro, args, qual)
	    print sprintf("  _qh.val.%s = %sp, \\", qual, qual)
	    print sprintf("  h_qcall(o_%s, _qh, %s))", fn, varargs)
	  }
	}
    }
}
