//
// Copyright (C) 1991 Texas Instruments Incorporated.
//
// Permission is granted to any individual or institution to use, copy, modify,
// and distribute this software, provided that this complete copyright and
// permission notice is maintained, intact, in all copies and supporting
// documentation.
//
// Texas Instruments Incorporated provides this software "as is" without
// express or implied warranty.
//
// Created: LGO 05/22/89 -- Initial design and implementation.
// Updated: LGO 11/08/89 -- Simplify package file macro interface.
//
// This file contains macros which define and implement different kinds of
// symbol packages.  The types are:
//    1. enumeration	- Symbols as int's
//    2. symbol 	- symbol plus the ability to declare initial symbol
//			  values and properties.
//    3. text_resource	- Symbol value initialized to symbol name.
//    4. once_only	- Symbol as database for conditional compilation.
//

#ifndef DEFPACKAGEH                 // If we have not included this file
#define DEFPACKAGEH

/*
//Symbols in an enumeration_package are just numbers with no associated
// objects. enumeration symbols can be used anywhere an enumeration type can be
// used, but its easier to add new symbols (the .h file is edited for you).
//
// Example:
//    enumeration_package(enum, "enum_package.h") // package setup
//    // if foo is the 37'th symbol in the enum package, then
//    enum(foo)  // expands to 37
*/
 
MACRO enumeration_package(name, file, REST: options){
  DEFPACKAGE name file options
  #define name(symbol) \
    DEFPACKAGE_SYMBOL(name, symbol,,,, expand_##name)
  #define expand_##name(index, symbol, type, value) index
}
/*
// Symbols in a symbol_package are pointers to objects that may be assigned
// values at run-time.  compile-time Symbols are interned and additional
// symbols may be added at run-time.  Symbols have values and properties
// whose initial values may be declared.
//
// Example:
//   symbol_package(SYM, "sym_package.h") // package setup (in a header file)
//
//    // if foo is the 37'th symbol in the enum package, then
//    SYM(foo) // expands to &sym_symbols[37]
//
//    // Set the default value of "foo" to a String
//    DEF_SYM(foo, String, String("Greetings!"))
//
//    // Set a default property of foo
//    DEF_SYM_PROPERTY(foo, value-type, Symbol, sym(String))
*/
MACRO symbol_package(name, file, REST: options) {
  DEFPACKAGE name file length = name##_count, options
  #define expand_##name(index, symbol, type, value) \
    (&name##_symbols[index])
  MACRO name(symbol) \
   { DEFPACKAGE_SYMBOL(name, #symbol,,,, expand_##name) }
  MACRO EXPANDING DEF_##name(symbol, type, value) \
   { DEFPACKAGE_SYMBOL(name, #symbol, type, value,,) }
  MACRO EXPANDING DEF_##name##_PROPERTY(symbol, property, type, value) \
   { DEFPACKAGE_SYMBOL(name, #symbol, type, value, property,) }
  extern struct Package* name##_package_g;
  extern Symbol name##_symbols[];
}

/* Runtime initialization of a symbol_package	*/
MACRO implement_symbol_package(name, file){
  #include file
  #if name##_count > 0
    Symbol name##_symbols[name##_count];
  #endif
  #define MAKE_##name##_SYMBOL(index, symbol) \
    pkg->put(symbol, name##_symbols[index]);
  MACRO SET_##name##_VALUE(index, type, val) \
    {name##_symbols[index].set((Generic*) val);}
  MACRO SET_##name##_PROPERTY(index, prop, type, value) \
    {name##_symbols[index].put(prop, (Generic*) value);}
  void name##_package_initializer(Package* pkg) {
    name##_DEFINITIONS(MAKE_##name##_SYMBOL,SET_##name##_VALUE,SET_##name##_PROPERTY)
  }
  static Package name##_package_s(name##_count*2, name##_package_initializer);
  Package* name##_package_g = &name##_package_s;
}
/*
// symbols in a text_package have default values which are the same
// as the symbol's name.  If all the error messages in an application are
// text_symbols, then the symbol definition file will contain a
// summary of all the messages, and the message text may be substituted for
// another (in another language) at runtime.
//
// Example:
//   text_package(res, "sym_package.h") // package setup
//   res(Mary had a little lamb)
//   // If this is the 37'th symbol, it expands to:
//   res_symbols[37]->value() // default value is "Mary had a little lamb"
//
*/

struct text_package_entry {
  const char* value;			// Current translation
  const void* language;			// default char* or Symbol*
  struct text_package_entry* next;	// Linked list of translations
};

// set_text_language -- set a new language for a package
// Input:	Optional Symbol which specifies the new language
//		The default is the origional language of the code
//		(hacker English).
//
//		Optional pointer to the text_package.  The default is
//		&ERR_MSG_entries[0]
//
// Output:	When a package entry doesn't have a translation for
//		the specified language, a warning exception is raised.
//		The number of these exceptions is returned.
//
int set_text_language(Symbol* language = NULL,
		      text_package_entry* package = NULL);

MACRO text_package(name, file, REST: options){
  #define name(symbol) \
    DEFPACKAGE_SYMBOL(name, symbol,,,, expand_##name)
  #define expand_##name(index, symbol, type, val) \
    ((CONST char*) name##_entries[index].value)
  DEFPACKAGE name file length = name##_count, options
  extern text_package_entry name##_entries[];
}

/* Runtime initialization of a text_package	*/
MACRO implement_text_package(pname, file) {
  #include file
  struct text_package_entry pname##_entries[pname##_count+1];
  #define MAKE_##pname##_SYMBOL(index, symbol) \
    pname##_entries[index].language = symbol;
  MACRO SET_##pname##_VALUE(index, type, val)  \
    {pname##_entries[index].value = symbol;}
  MACRO SET_##pname##_PROPERTY(index, prop, type, value) \
    {text_package_put(pname##_entries[index], SYM(prop), value);}
  void pname##_package_initializer() {
    extern void text_package_put(text_package_entry&, Symbol*, const char*);
    pname##_DEFINITIONS(MAKE_##pname##_SYMBOL,SET_##pname##_VALUE,SET_##pname##_PROPERTY)
    set_text_language(NULL, &pname##_entries[0]);
  }
  INITIALIZE(pname##_package) {pname##_package_initializer();}
}

#endif

