


#ifndef _INC_KEYWORD_
#define _INC_KEYWORD_


#if      0
/********************************** KEYWORD *************************************
BEGIN DOCUMENTATION
  
  Descrition:  Keyword argument passing for GCC
  =============================================

  kwDefType(KWTY, [TYPE NAME;]*)

      defines the type KWTY to be used for passing keyword values of the
      specified names and types.  Note the regular-expression syntax.

          
  #define func(ARG1, ... ARGN, KWARGS...)  kwCall(FUNC, N, KWTY, ARG1, ... ARGN, KWARGS)

      is how you define a macro to pass keyword arguments to FUNC.  FUNC is
      the name of the actual function which will take keyword arguments.
      N is the number of required or non-keyword arguments it takes.  KWTY
      is the keyword value type declared with kwDefType().  Of course you
      could just use kwCall() itself without defining the macro.

      
  kwArgDecl(KWTY)

      is used in the actual function declaration to declare that the function
      takes keyword arguments with the names and types KWTY, as defined with
      kwDefType().

      
  kwDefault(KWNAME, VALUE)
  kwDefaultN(NAME, KWNAME, VALUE)

      are used within the keyword argument taking function's declaration list to
      specify the default value for the named keyword argument.  One of these
      MUST be done for EVERY keyword name.  kwDefaultA() is used to specify
      an alternate name, NAME, for the keyword argument KWNAME, within the
      function.  

      
  kwGetVal(KWNAME)

      can be used to get the value of a named keyword argument.


  kwSpecified(KWNAME)

      can be used within the keyword argument taking function's body to inquire
      whether the keyword argument KWNAME was specified.


      
  Example:
  ========
      
  kwDefType(FUNC_KW, int i, j; float f;);

  #define func(A, B, KWA...)   kwCall(func_, 2, FUNC_KW, A, B, KWA)


  void func_(int x, int y, kwArgDecl(FUNC_KW))
  {
    int foo = 6;
    kwDefault(i, 50);
    kwDefault(j, 30);
    kwDefault(f, 3.14159);
    float bar = 7.0;


    printf("x = %3d    y = %3d    i = %3d     j = %3d     f = %10.4f\n", x, y, i, j, f);
  }


  int main()
  {
    int a, b;
    float c;

    printf("\n");

    func(1, 1);
    func(1, 2, i: 3);
    func(1, 3, j: 5);
    func(1, 4, f: 2.718);
    func(1, 5, i: 100, f: 1.0);

    printf("\n");

    for (a = 0; a < 5; a++) {
      func(a, 5-a, i: 5*a, f: 1.0/a);
    }

    return 0;
  }

END DOCUMENTATION  
*********************************************************************************/
#endif  


#include "misc.h"


extern boolean _kwSpec_(char *name, char *kwstring);


#define kwDefType(KWTY, KWA...) typedef struct { char *_kws; struct { KWA } _kwa; } KWTY
#define kwArgDecl(KWTY)         KWTY *_kwargs
#define kwSpecified(NAME)       (_kwSpec_(" " #NAME ":", _kwargs->_kws))
#define kwGetVal(KWNAME)        (_kwargs->_kwa.KWNAME)
#define kwDefaultN(NAME, KWNAME, VAL)   typeof (_kwargs->_kwa.KWNAME) NAME =        \
                                        (kwSpecified(KWNAME) ? kwGetVal(KWNAME) : (VAL))
#define kwDefault(KWNAME, VAL)  kwDefaultN(KWNAME, KWNAME, VAL)
#define kwCall(FUNC, NREQ, KWTY, ARGS...)   (_kwCall_ ## NREQ (FUNC, KWTY , ## ARGS))


/* these are auxiliary macros */

#define _kwCall_0(FUNC, KWTY, KWA...)                                                  \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(&_kwpass); })

#define _kwCall_1(FUNC, KWTY, A, KWA...)                                               \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, &_kwpass); })

#define _kwCall_2(FUNC, KWTY, A, B, KWA...)                                            \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, &_kwpass); })

#define _kwCall_3(FUNC, KWTY, A, B, C, KWA...)                                         \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, &_kwpass); })

#define _kwCall_4(FUNC, KWTY, A, B, C, D, KWA...)                                      \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, D, &_kwpass); })

#define _kwCall_5(FUNC, KWTY, A, B, C, D, E, KWA...)                                   \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, D, E, &_kwpass); })

#define _kwCall_6(FUNC, KWTY, A, B, C, D, E, F, KWA...)                                \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, D, E, F, &_kwpass); })

#define _kwCall_7(FUNC, KWTY, A, B, C, D, E, F, G, KWA...)                             \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, D, E, F, G, &_kwpass); })

#define _kwCall_8(FUNC, KWTY, A, B, C, D, E, F, G, H, KWA...)                          \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, D, E, F, G, H, &_kwpass); })

#define _kwCall_9(FUNC, KWTY, A, B, C, D, E, F, G, H, I, KWA...)                       \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, D, E, F, G, H, I, &_kwpass); })

#define _kwCall_10(FUNC, KWTY, A, B, C, D, E, F, G, H, I, J, KWA...)                   \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, D, E, F, G, H, I, J, &_kwpass); })

#define _kwCall_11(FUNC, KWTY, A, B, C, D, E, F, G, H, I, J, K, KWA...)                \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, D, E, F, G, H, I, J, K, &_kwpass); })

#define _kwCall_12(FUNC, KWTY, A, B, C, D, E, F, G, H, I, J, K, L, KWA...)             \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, D, E, F, G, H, I, J, K, L, &_kwpass); })

#define _kwCall_13(FUNC, KWTY, A, B, C, D, E, F, G, H, I, J, K, L, M, KWA...)          \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, D, E, F, G, H, I, J, K, L, M, &_kwpass); })

#define _kwCall_14(FUNC, KWTY, A, B, C, D, E, F, G, H, I, J, K, L, M, N, KWA...)       \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, D, E, F, G, H, I, J, K, L, M, N, &_kwpass); })

#define _kwCall_15(FUNC, KWTY, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, KWA...)    \
  ({ KWTY _kwpass = {_kws: #KWA, _kwa: {KWA}}; FUNC(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, &_kwpass); })


#endif 
