#!/usr/bin/awk -f
# Generate GCC predefined macros as define_pre()/define_macro() calls.
# Usage: gcc -dM -E - < /dev/null | awk -f tools/get-gcc-predefined.awk

BEGIN {
    print "/* GCC predefined macros - generated by gcc -dM -E - */"
    print ""
    # macros suppressed because rcc does not yet implement the required features
    skip["__STDC_IEC_60559_BFP__"]   = 1  # missing femode_t, fesetexcept, fegetmode, strfromd/f/l, fromfp, SNANF, iseqsig, CR_DECIMAL_DIG
    skip["__STDC_IEC_60559_TYPES__"] = 1  # _FloatNx extended types not fully implemented
    skip["__STDC_IEC_60559_DFP__"]   = 1  # _DecimalN aliased to binary float, not true IEEE 754-2008 decimal
}

/^#define / {
    rest = substr($0, 9)

    # extract name for skip check (stops at space, tab, or paren)
    n_end = match(rest, /[ \t(]/)
    early_name = (n_end > 0) ? substr(rest, 1, n_end - 1) : rest
    if (early_name in skip) next

    # Check for function-like macro: NAME(params) value
    paren = index(rest, "(")
    if (paren > 0) {
        name = substr(rest, 1, paren - 1)
        # Verify it looks like an identifier before the paren
        if (name ~ /^[A-Za-z0-9_]+$/) {
            rest2 = substr(rest, paren + 1)
            close_p = index(rest2, ")")
            if (close_p > 0) {
                params = substr(rest2, 1, close_p - 1)
                value = substr(rest2, close_p + 1)
                sub(/^[ \t]+/, "", value)

                n = split(params, pa, /,[ \t]*/)
                if (n > 0 && pa[1] != "") {
                    printf "    char *%s_params[] = {", name
                    for (i = 1; i <= n; i++) {
                        if (i > 1) printf ", "
                        printf "\"%s\"", pa[i]
                    }
                    printf "};\n"
                    printf "    define_macro(\"%s\", true, %s_params, %d, \"", name, name, n
                } else {
                    printf "    define_macro(\"%s\", true, NULL, 0, \"", name
                }
                gsub(/\\/, "\\\\", value)
                gsub(/"/, "\\\"", value)
                printf "%s\");\n", value
                next
            }
        }
    }

    # Object-like macro
    space_idx = match(rest, /[ \t]/)
    if (space_idx == 0) {
        name = rest
        value = ""
    } else {
        name = substr(rest, 1, space_idx - 1)
        value = substr(rest, space_idx + 1)
        sub(/^[ \t]+/, "", value)
    }
    printf "    define_pre(\"%s\", \"", name
    gsub(/\\/, "\\\\", value)
    gsub(/"/, "\\\"", value)
    printf "%s\");\n", value
}
