/*	SDB	Main routine	*/

#include "bdscio.h"
#include "dbqdefs.h"

main()
{
	pbuf = gbuf;
	printf("DBQ - version 1.3\n");
	db_sinit();
	db_ifile("dbqinit.cmd");
	while (TRUE) {
		db_prompt("DBQ> ","\t> ");
		if (!db_parse(NULL)) {
			printf("### Error: %s ###\007\n",db_ertxt(dbv_errcode));
		}
	}
}

int db_parse(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
	char *fmt;

{
	int sts;
#ifdef DBPI
	if (fmt)
		db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
#endif
	switch (db_ntoken()) {

	case ';':	sts = TRUE;
			break;

/* comment - # to end of line */

	case COMMENT:	db_flush(1);
			sts = TRUE;
			break;
	case EXXIT:		/* close log if open */
			if (dbv_lfp != NULL) {
				putc(CPMEOF,dbv_lfp);
				fclose(dbv_lfp);
				printf("DBQ.LOG closed\n");
			}
			exit();
			break;

	case DELETE:
			sts = delete();
			break;
	case INSERT:
			sts = insert();
			break;
	case PRINT:
			sts = print();
			break;
	case SELECT:
			sts = select();
			break;
	case SORT:
			sts = db_sort(NULL);
			break;
	case UPDATE:
			sts = update();
			break;
	case HELP:
			sts = db_help();
			break;
	case DEFYNE:
			sts = mc_define(0);
			break;
	case PROMPT:
			sts = mc_define(1);
			break;
	case SHOW:
			sts = mc_show();
			break;
	case SET:
			sts = db_set();
			break;
/* from DBA */
	case COMPRESS:
			sts = db_squeeze(NULL);
			break;
	case CREATE:
			sts = create();
			break;
	case ERASE:
			sts = db_erase();
			break;
	case RENAME:
			sts = db_rename();
			break;
	case EXPORT:
			sts = db_export(NULL);
			break;
	case EXTRACT:
			sts = db_extract(NULL);
			break;
	case IMPORT:
			sts = db_import(NULL);
			break;
	default:
			RETERR(SYNTAX)
	}

	return (sts);
}

int db_set()
{
	int setval;

	while (db_token() == ID) {

		db_ntoken();

		if (db_scmp(dbv_tstring,"no") == 0) {
			setval = FALSE;
			if (db_token() != ID)
				{ RETERR(BADSET) }
			db_ntoken();
		}
		else
			setval = TRUE;

		if (db_scmp(dbv_tstring,"fold") == 0)
			dbv_fold = setval;
		else if (db_scmp(dbv_tstring,"verify") == 0)
			dbv_verify = setval;
		else if (db_scmp(dbv_tstring,"log") == 0) {
			dbv_logging = setval;
			if ((setval) && (dbv_lfp == NULL)) {
				if ((dbv_lfp = CALLOC(BUFSIZ)) == NULL) {
					RETERR(INSMEM) }
				if (fcreat("DBQ.LOG",dbv_lfp) == ERROR) {
					CFREE(dbv_lfp);
					dbv_lfp = NULL;
					dbv_logging = NULL;
					RETERR(OUTCRE)
					}
				}
			}
		else if (db_scmp(dbv_tstring,"page") == 0) {
		    if (setval)
			if (db_token() == NUMBER) {
				db_ntoken();
				dbv_pgln = dbv_tvalue;
				}
			else
				dbv_pgln = 60;
		    else
			dbv_pgln = 32000;
		    }
	}
	printf("Fold = %d, verify = %d, log = %d, page = %d\n",
			dbv_fold,dbv_verify,dbv_logging,dbv_pgln);

	return (TRUE);
}

int db_help()
{
	FILE *fp;
	int ch,kbrep,curhelp,helping;

		/*	Borrow the output buffer	*/

	fp = &obuf;
	helping = TRUE;

	if ((fopen("DBQ.HLP",&obuf)) == ERROR) {
		printf("Sorry - help file not available\n");
		}
	else {
		while ((ch = getc(fp)) != CPMEOF)
			if (ch == '?') {
				if ((curhelp = getc(fp)) == CPMEOF) break;
				if (helping) {
					printf("Press ENTER to continue, ^Z to quit, x for help on x...\n");
					kbrep = getchar();
					if (kbrep == -1) break;
					if (kbrep != '\n')
						helping = FALSE;
					}
				if (curhelp == kbrep)
					helping = TRUE;
				}
			else
				if (helping) putchar(ch);
		fclose(fp);
	}

	return (TRUE);
}

int create()
{
	struct relation *rptr;
	char aname[STRINGMAX+1];
	int atype,asize,ascale;

	if (db_ntoken() != ID)
		{ RETERR(SYNTAX) }

	if (!(rptr = db_rcreate(dbv_tstring)))
		return (FALSE);
/*
	if (db_ntoken() != '(') {
		free(rptr);
		RETERR(SYNTAX)
	}
*/
	while (TRUE) {

		if (db_ntoken() != ID) {
			free(rptr);
			RETERR(SYNTAX)
		}
		strcpy(aname,dbv_tstring);

		db_ntoken();
		if (dbv_token == CHARR)
			atype = TCHAR;
		else if (dbv_token == NUM)
			atype = TNUM;
		else {
			free(rptr);
			RETERR(SYNTAX)
		}

		if (db_ntoken() != NUMBER) {
			free(rptr);
			RETERR(SYNTAX)
		}
/*
		if ((atype == TCHAR) && (dbv_tvalue > STRINGMAX)) {
			printf("Max CHAR=%d\n",STRINGMAX);
			free(rptr);
			RETERR(SYNTAX)
		}

		if ((atype == TNUM) && (dbv_tvalue > NUMBERMAX)) {
			printf("Max NUM=%d\n",NUMBERMAX);
			free(rptr);
			RETERR(SYNTAX)
		}
*/
		asize = dbv_tvalue;
		ascale = 0;

		if (db_token() == NUMBER) {
			db_ntoken();
			ascale = dbv_tvalue;
		}

		if (!db_rcattr(rptr,aname,atype,asize,ascale)) {
			free(rptr);
			return (FALSE);
		}

		if (db_token() != ID)
			break;
	}
/*
	if (db_ntoken() != ')') {
		free(rptr);
		RETERR(SYNTAX)
	}

	
	if (db_ntoken() != NUMBER) {
		free(rptr);
		RETERR(SYNTAX)
	}
replace this with just 10 for starters */
	dbv_tvalue = 10;
	if (!db_rcheader(rptr))
		return (FALSE);
	if (!db_rctuples(rptr,dbv_tvalue))
		return (FALSE);
	if (!db_rcdone(rptr))
		return (FALSE);

	return (TRUE);
}

int db_erase()
{
	char filename[RNSIZE+13];
	if (db_ntoken() != ID)
		{ RETERR(SYNTAX) }

	sprintf(filename,"%s.dbq",dbv_tstring);
	unlink(&filename);

	return(TRUE);
}

int db_rename()
{
	char renfrom[RNSIZE+13], rento[RNSIZE+13];

	if (db_ntoken() != ID)
		{ RETERR(SYNTAX) }

	sprintf(renfrom,"%s.dbq",dbv_tstring);

	if (db_ntoken() != ID)
		{ RETERR(SYNTAX) }

	sprintf(rento,"%s.dbq",dbv_tstring);

	if (rename(renfrom,rento) == -1)
		{ RETERR(RELFNF) }

	return (TRUE);
}


int mc_define(fromcon)
int fromcon;
{
	struct macro *mptr,*mlast;
	struct mtext *tptr,*tlast;
	char textline[LINEMAX+1];

	if ((db_xntoken() != ID) && (dbv_token != STRING))
		{ RETERR(SYNTAX) };

	if (!fromcon)
	   if (!db_flush(0))
		return (FALSE);

	for (mptr = dbv_macros, mlast = NULL; mptr != NULL; mlast =mptr,
		mptr = mptr->mc_next)
		if (db_scmp(mptr->mc_name,dbv_tstring) == 0) {
			if (mlast == NULL)
				dbv_macros = mptr->mc_next;
			else
				mlast->mc_next = mptr->mc_next;
			mc_free(mptr);
		}

	if ((mptr = CALLOC(MACSIZE)) == NULL)
		{ RETERR(INSMEM) };
	if ((mptr->mc_name = CALLOC(strlen(dbv_tstring)+1)) == NULL) {
		CFREE(mptr);
		RETERR(INSMEM)
	}

	strcpy(mptr->mc_name,dbv_tstring);
	mptr->mc_mtext = NULL;

	db_prompt(NULL,"DEFINE> ");

	for (tlast = NULL; ; tlast = tptr) {

		if (fromcon) {
			printf("Enter %s ",dbv_tstring);
			linein(textline);
		}
		else
			db_gline(textline);

		if (textline[0] == EOS || textline[0] == '\n')
			if (fromcon) {
				textline[0] = '#';
				textline[1] = EOS;
			} else
				break;

		if ((tptr = CALLOC(MTSIZE)) == NULL) {
			mc_free(mptr);
			RETERR(INSMEM)
		}

	/*	Add an inter word space		*/

		if (!fromcon) strcat(textline," ");
		if ((tptr->mt_text = CALLOC(strlen(textline)+1)) == NULL) {
			mc_free(mptr);
			RETERR(INSMEM)
		}
		if (dbv_token == STRING) {
			strcpy(tptr->mt_text,"\"");
			strcat(tptr->mt_text,textline);
				/* replace linefeed with dblquote */
			tptr->mt_text[strlen(tptr->mt_text)-1] = 34;
			}
		else
			strcpy(tptr->mt_text,textline);
		tptr->mt_next = NULL;

		if (tlast == NULL)
			mptr->mc_mtext = tptr;
		else
			tlast->mt_next = tptr;

		if (fromcon) {
			tlast = tptr;
			break;
		}
	}

	if (tlast == NULL)
		mc_free(mptr);
	else {
		mptr->mc_next = dbv_macros;
		dbv_macros = mptr;
	}

	return (TRUE);
}

int mc_show()
{
	struct macro *mptr;
	struct mtext *tptr;

/*	just show ; will list macros	*/

	if (db_xntoken() != ID) {
		for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
			printf("\t%s\n",mptr->mc_name);
		return(TRUE);
		}

	for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
		if (db_scmp(mptr->mc_name,dbv_tstring) == 0) {
			for (tptr = mptr->mc_mtext; tptr != NULL; tptr = tptr->mt_next)
				printf("\t%s\n",tptr->mt_text);
			break;
		}

	if (mptr == NULL)
		printf("### Procedure <%s> not found ###\007\n",dbv_tstring);

	return(TRUE);
}

int mc_free(mptr)
	struct macro *mptr;
{
	struct mtext *tptr;

	while ((tptr = mptr->mc_mtext) != NULL) {
		mptr->mc_mtext = tptr->mt_next;
		CFREE(tptr->mt_text);
		CFREE(tptr);
	}
	CFREE(mptr->mc_name);
	CFREE(mptr);
}

/*	Debug routines for memory allocation - remove comments if reqd.	*/
/*
char *malloc(syze)
	int syze;
{
	char *mptr;

	mptr = alloc(syze);
	printf("malloc: allocated %d at %u\n",syze,mptr);

	return (mptr);
}

mfree(mptr)
	char *mptr;
{
	printf("mfree: freed at %u\n",mptr);
	hfree(mptr);
}
*/

hfree(block)
  char *block;
{
  struct _header *p, *q;

  if (block != NULL) {
  p = block - 4;
  for (q = _allocp; !(p > q  &&  p < q->_ptr); q = q->_ptr)
    if (q >= q->_ptr  &&  (p > q  ||  p < q->_ptr))  break;

  if (p + p->_size  ==  q->_ptr) {
      p->_size += q->_ptr->_size;
      p->_ptr   = q->_ptr->_ptr;
    }
  else  p->_ptr = q->_ptr;

  if (q + q->_size  ==  p) {
      q->_size += p->_size;
      q->_ptr   = p->_ptr;
    }
  else  q->_ptr = p;

  _allocp = q;
  }
}

e  ==  p) {
      q->_size += p->_size;
      q->_ptr   = p->_ptr;
    }
  