/*


 Copyright (C) 1990 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.


 *  
 * I/O support for internal defmacros
 *   Defmacros which execute in their own process use stdin and stdout.
 *   Defmacros which execute as cpp functions use these routines instead.
 *
 * Edit history
 * Created: LGO 30-Mar-89 -- Initial design and implementation.
 *
 */

#include <ctype.h>
#include <stdio.h>

#define EOS 0
#ifndef TRUE
#define TRUE  1
#define FALSE 0
#endif

typedef int Boolean;

/************************************************************/

/*  I moved these definitions in here from hash.c because the SAS C
 *  compiler (MVS) complains about not knowing about type Hash_Table
 *  in declaration    extern struct Hash_Table* init_Hash_Table(); 
 *  This looks like a bug their compiler ... DKM
 */

#define BUCKET_SIZE 8

struct hash_pair {
  char* key;
  void* value;
};

struct bucket {
  struct hash_pair data[BUCKET_SIZE];
};

struct Hash_Table {
  struct bucket* table;
  unsigned char* items_in_buckets;
  int entry_count;			
  int bucket_index;			
  int current_bucket;
  int current_index;
};

/**************************************************************/

extern char* strcpy(/* char*, char* */);
extern char* strcat(/* char*, char* */);
extern char* getmem(/* int byte_count */);
extern char* savestring(/* char* */);
extern cerror(/* char* format_string, char* string_arg */);

extern struct Hash_Table* init_Hash_Table();
extern void* get_hash(/* Hash_Table, key */);
extern Boolean put_hash(/* Hash_Table, key, value */);
extern void* next_hash(/* Hash_Table, firstp */);

extern char* lookup_symbol(/* char* pkgname, char* symname */);

extern void new_defmacro();		  /* Define a new defmacro */

/*
 * The FILEINFO structure stores information about open files
 * and macros being expanded.
 */
/* WARNING: This structure is duplicated in cpp.h */
typedef struct fileinfo {
	char		*bptr;		/* Buffer pointer	*/
	int		line;		/* for include or macro	*/
	FILE		*fp;		/* File if non-null	*/
	struct fileinfo	*parent;	/* Link to includer	*/
	char		*filename;	/* File/macro name	*/
	char		*progname;	/* From #line statement	*/
	unsigned int	unrecur;	/* For macro recursion	*/
	char*		buffer; 	/* current input line	*/
} FILEINFO;

extern FILEINFO *MacInFile, *MacOutFile;
extern char* MacOutEnd;
extern void NextMacOutString(); /* takes 1 char* parameter */
extern char NextMacInChar();
extern void NextMacOutBuffer();
extern void set_inbuffer(/* char* instring */);

/* get the next input character */
#undef getchar
#define getchar() (*MacInFile->bptr ? *MacInFile->bptr++ : NextMacInChar())

/* unget the last character */
#undef unget
#define unget() (MacInFile->bptr--)

/* put the next character to output */
#undef putchar
#define putchar(c) \
  {if (MacOutFile->bptr > MacOutEnd) NextMacOutBuffer(); \
  *MacOutFile->bptr++ = c;}

#define puts(s) NextMacOutString(s)

extern char  skip_blanks();
extern char  skip_line();
extern char* copytoken(/* char* */);
extern void scan_start();
extern char* scan_next(/* char delim */);
extern char* scan_list(/* char delim */);
extern char* scan_token(/* char* delims */);

extern void put_string(/* char* */);

extern char* c_upcase(/* char* */);
extern char* c_downcase(/* char* */);
extern char* c_capitalize(/* char* */);
extern char* c_trim_all (/* char*, char* */);

typedef struct buf_string {
  char* buff;
  char* buffp;
  char* buffend;
}* STRING;

STRING make_STRING(/* int size */);
void destroy_STRING(/* STRING string */);
void grow_STRING(/* STRING string, int len */);
void append_STRING(/* STRING string, char* chars */);
char append_blanks(/* STRING string */);

#define append_char(string, c) \
  { if(string->buffp>=string->buffend) grow_STRING(string,0); \
    *string->buffp++ = (c); }

extern STRING work_string;		/* string buffer for utilities */
extern int current_line;		/* line at start of defmacro */
extern char current_file[];		/* file at start of defmacro */
