/*------------------------------------------------------------------*/
/*								    */
/*		      MC68000 Cross Assembler			    */
/*								    */
/*	      Copyright	(c) 1985 by Brian R. Anderson		    */
/*								    */
/*	   Assembler directive processing - June 21, 1988	    */
/*								    */
/*   This program may be copied	for personal, non-commercial use    */
/*   only, provided that the above copyright notice is included	    */
/*   on	all copies of the source code.	Copying	for any	other use   */
/*   without the consent of the	author is prohibited.		    */
/*								    */
/*------------------------------------------------------------------*/
/*								    */
/*		Originally published (in Modula-2) in		    */
/*	    Dr.	Dobb's Journal, April, May, and June 1986.          */
/*								    */
/*	AmigaDOS conversion copyright (c) 1988 by Charlie Gibbs.    */
/*								    */
/*------------------------------------------------------------------*/

#include <stdio.h>
#include <ctype.h>
#include "a68kdef.h"
#include "a68kglb.h"

/* Functions */
extern int  LineParts(), GetField(), Instructions();
extern int  GetSize(), GetInstModeSize(), GetMultReg();
extern int  ReadSymTab(), GetArgs(), GetAReg(),	OpenIncl();
extern long AddrBndW(),	AddrBndL(), GetValue(),	CalcValue();
extern char *malloc();
extern FILE *fopen();



int ObjDir (f) FILE *f;
/* Generates Object Code for Assembler Directives */
{
    register int i, j;
    int	 oploc,	dummy;
    long templong;
    char tempop[MAXLINE], delim;

    AddrAdv = 0;

    if (strcmp (OpCode,	"ORG") == 0) {                  /* ORG */
	templong = GetValue (SrcOp, SrcLoc);
	if (Hunk2 < 0)
	    Error (SrcLoc, RelErr);	/* Can't ORG externally */
	else if	(DefLine2 > LineCount)
	    Error (SrcLoc, FwdRef);	/* Illegal forward reference */
	else {
	    AddrCnt = templong;
	    CurrHunk = Hunk2;
	}
	PrntAddr = MakeHunk = TRUE;
	return (Org);
    }

    if ((strcmp	(OpCode, "EQU") == 0)                   /* EQU */
    || (strcmp (OpCode,	"=") == 0)) {                   /* = */
	if (Label[0] ==	'\0')
	    Error (0, NeedLab);		/* Need	a label	*/
	ObjSrc = GetValue (SrcOp, SrcLoc);
	if (DefLine2 > LineCount)
	    Error (SrcLoc, FwdRef);	/* Illegal forward reference */
	Src.Hunk = Hunk2;
	PrntAddr = MakeHunk = TRUE;
	return (Equ);
    }

    if (strcmp (OpCode,	"DC") == 0) {                   /* DC */
	if ((Size == Word) || (Size == Long))
	    AddrCnt = AddrBndW (AddrCnt);
	i = SrcLoc;
	while (!isspace(Line[i]) && (Line[i] !=	'\0')) {
	    oploc = i;
	    if (((Line[i] == '\'') || (Line[i] == '"'))     /* String */
	    && (Size ==	Byte)) {
		delim =	Line[i++];		/* Get the delimiter */
		while (1) {
		    if (Line[i]	== '\0') {      /* No closing delimiter */
			Error (i, NoStrEnd);
			break;
		    }
		    if (Line[i]	== delim) { /* End of string? */
			if (Line[++i] != delim)	/* Check next character	*/
			    break;	    /* End of string */
		    }	/* Otherwise it's an apostrophe in the string */
		    Src.Hunk = ABSHUNK;		    /* Absolute	value */
		    ObjString[nX++] = Line[i++];    /* Current char. */
		}
	    } else {			/* Not a string	constant */
		i = GetField (Line, i, SrcOp);
		ObjSrc = GetValue (SrcOp, oploc);	/* Value */
		if ((Src.Hunk =	Hunk2) != ABSHUNK) {	/* Hunk	no. */
		    templong = AddrCnt + nX;		/* Relocatable */
		    PutRel (templong, Hunk2, Size);
		}
		if (Size == 4) {
		    ObjString[nX++] = (ObjSrc >> 24) & 0x00FF;
		    ObjString[nX++] = (ObjSrc >> 16) & 0x00FF;
		}
		if (Size >= 2)
		    ObjString[nX++] = (ObjSrc >> 8) & 0x00FF;
		ObjString[nX++]	= ObjSrc & 0x00FF;
		if (Size == 2)
		    templong = 0xFFFF0000L;
		else if	(Size == 1)
		    templong = 0xFFFFFF00L;
		if (Size < 4)
		    if (((ObjSrc & templong) !=	0)
		    && ((ObjSrc	& templong) != templong))
			Error (i, SizeErr);
	    }
	    if (Line[i]	== ',')
		i++;			/* Skip	over separator */
	}
	if ((Line[i] !=	'\0') && !isspace(Line[i]))
	    Error (i, OperErr);		/* Didn't end properly */
	AddrAdv	= InstSize = nX;
	PrntAddr = MakeHunk = TRUE;
	return (DC);
    }

    if (strcmp (OpCode,	"DS") == 0) {                   /* DS */
	if (DestLoc != 0) {
	    Error (DestLoc, OperErr);	/* Only	one operand is allowed */
	    PrntAddr = MakeHunk	= TRUE;
	    return (DS);
	}
	AddrAdv	= GetValue (SrcOp, SrcLoc);
	if (DefLine2 > LineCount) {
	    Error (SrcLoc, FwdRef);	/* Illegal forward reference */
	    AddrAdv = 0;
	}
	if (Hunk2 != ABSHUNK)
	    Error (SrcLoc, AbsReq);	/* Count must be absolute */

	if (Size == Word) {		/* Words */
	    AddrCnt = AddrBndW (AddrCnt);
	    AddrAdv <<=	1;
	}
	if (Size == Long) {		/* Long	words */
	    AddrCnt = AddrBndW (AddrCnt);
	    AddrAdv <<=	2;
	}
	if (Pass2 && (HunkType != HunkBSS)) {	/* If this isn't     */
	    templong = AddrAdv;			/*  a BSS hunk,	     */
	    while (templong >= 4) {		/*  generate zeros   */
		AppendSdata (f,	0L, 4);		/*  to fill the	area */
		templong -= 4;
	    }
	    if (templong > 0) {
		i = templong;
		AppendSdata (f,	0L, i);
	    }
	}
	PrntAddr = MakeHunk = TRUE;
	return (DS);
    }

    if (strcmp (OpCode,	"EVEN") == 0) {                /* EVEN */
	AddrCnt	= AddrBndW (AddrCnt);
	PrntAddr = MakeHunk = TRUE;
	return (Even);
    }

    if (strcmp (OpCode,	"END") == 0) {                  /* END */
	if (Pass2)
	    if (SrcOp[0] != '\0')
		EndAddr	= GetValue (SrcOp, SrcLoc);
	    else
		EndAddr	= 0;
	PrntAddr = MakeHunk = TRUE;
	return (End);
    }

    if (strcmp (OpCode,	"XDEF") == 0) {                 /* XDEF */
	if (SFormat)
	    Error (OpLoc, NotSFmt);		/* Not in S-format */
	i = SrcLoc;
	while (!isspace(Line[i]) && (Line[i] !=	'\0')) {
	    oploc = i;
	    i =	GetField (Line,	i, SrcOp);	/* Get a symbol	*/
	    if (ReadSymTab (SrcOp)) {
		if (!Pass2) {
		    if ((Sym->Flags & 0x60) == 0)
			Sym->Flags |= 2;	/* Set XDEF flag */
		} else {
		    AddRef (LineCount);
		    if (Sym->Defn == NODEF)
			Error (oploc, Undef);	/* Never got defined */
		    else if (Sym->Flags	& 0x60)
			Error (oploc, AddrErr);	/* Can't XDEF a register */
		}
	    } else if (!Pass2) {		/* Not yet defined */
		AddSymTab (SrcOp, 0L, CurrHunk,	NODEF, 2);
	    }
	    if (Line[i]	== ',')
		i++;				/* Skip	over separator */
	}
	return (Xdef);
    }

    if (strcmp (OpCode,	"XREF") == 0) {                 /* XREF */
	if (SFormat)
	    Error (OpLoc, NotSFmt);		/* Not in S-format */
	i = SrcLoc;
	while (!isspace(Line[i]) && (Line[i] !=	'\0')) {
	    oploc = i;
	    i =	GetField (Line,	i, SrcOp);
	    if (Pass2) {
		if (ReadSymTab (SrcOp) && (Sym->Defn !=	LineCount)) {
		    AddRef (LineCount);	/* Ignore extraneous XREF */
		}
	    } else {
		if (!ReadSymTab	(SrcOp)) {		/* Only	if not */
		    templong = ~(HeapLim - Heap);	/*   defined   */
		    templong &=	0x0000FFFF;
		    AddSymTab (SrcOp, 0L, templong, LineCount, 1);
		}
	    }
	    if (Line[i]	== ',')
		i++;			/* Skip	over separator */
	}
	return (Xref);
    }

    if (strcmp (OpCode,	"PAGE") == 0) {                 /* PAGE */
	if (Pass2)
	    LnCnt = LnMax;		/* Resume on a new page	*/
	return (Page);
    }

    if (strcmp (OpCode,	"LIST") == 0) {                 /* LIST */
	ListOff	= FALSE;
	return (DoList);
    }

    if ((strcmp(OpCode,"NOLIST")==0) || (strcmp(OpCode,"NOL")==0)) {
	ListOff	= TRUE;					/* NOLIST */
	return (NoList);
    }

    if (strcmp (OpCode,	"SPC") == 0) {                  /* SPC */
	if (Pass2 && !ListOff && !SuppList) {
	    if (SrcOp[0] != '\0')
		j = GetValue (SrcOp, SrcLoc);	/* Amount to space */
	    else
		j = 1;				/* Default to one line */
	    for	(i = 0;	i < j; i++) {
		if (LnCnt >= LnMax)
		    break;			/* Page	overflow */
		fprintf	(List, "\n");           /* Space one line */
	    }
	}
	return (Space);
    }

    if (strcmp (OpCode,	"TTL") == 0) {                  /* TTL */
	for (i = SrcLoc, j = 0;	Line[i]	!= '\0'; i++) {
	    TTLstring[j++] = Line[i];	/* Get title string */
	    if (j >= MAXLINE - 1)
		break;			/* The string is full */
	}
	TTLstring[j] = '\0';
	LnCnt =	LnMax;			/* Skip	to a new page */
	return (Title);
    }

    if (strcmp (OpCode,	"CNOP") == 0) {                 /* CNOP */
	i = TRUE;			/* "Error-free" flag */

	ObjSrc = GetValue (SrcOp, SrcLoc);
	if (DefLine2 > LineCount) {
	    Error (SrcLoc, FwdRef);	/* Illegal forward reference */
	    i =	FALSE;
	}
	if (Hunk2 != ABSHUNK) {
	    Error (SrcLoc, AbsReq);	/* Must	be absolute! */
	    i =	FALSE;
	}

	ObjDest	= GetValue (DestOp, DestLoc);
	if (DefLine2 > LineCount) {
	    Error (DestLoc, FwdRef);	/* Illegal forward reference */
	    i =	FALSE;
	}
	if (Hunk2 != ABSHUNK) {
	    Error (DestLoc, AbsReq);	/* Must	be absolute! */
	    i =	FALSE;
	}

	templong = ObjDest;
	while ((templong > 0) && ((templong & 1) == 0))
	    templong >>= 1;		/* Shift out low-order zeros */
	if ((templong != 1) || (ObjDest	== 1)) {
	    Error (DestLoc, OperErr);	/* DestOp must be a power of 2 */
	    i =	FALSE;
	}
	if ((ObjSrc & 1) || (ObjSrc >= ObjDest)) {
	    Error (SrcLoc, OperErr);	/* SrcOp is odd	or out of range	*/
	    i =	FALSE;
	}

	if (i) {			/* If no errors	so far */
	    AddrCnt = AddrBndW (AddrCnt);
	    templong = (AddrCnt	& ~(ObjDest-1))	+ ObjSrc;
	    if (templong < AddrCnt)
		templong += ObjDest;	/* We must advance to here */
	    if ((templong - AddrCnt) < MAXLINE)	{
		nX = templong -	AddrCnt;
		for (j = 0; j <	nX; ) {
		    ObjString[j++] = NOP / 256;
		    ObjString[j++] = NOP & 255;
		}
		AddrAdv	= InstSize = nX;	/* generate NOPs */
		PrntAddr = MakeHunk = TRUE;
	    } else {
		Error (DestLoc,	OperErr);	/* Too many NOPs */
	    }
	}
	return (Cnop);
    }

    if (strcmp (OpCode,	"INCLUDE") == 0) {              /* INCLUDE */
	i = SrcLoc;
	if ((Line[i] ==	'"') || (Line[i] == '\''))
	    i++;			/* Ignore quotes */
	j = 0;
	while (!isspace(Line[i])
	&& (Line[i] != '"')
	&& (Line[i] != '\'')
	&& (Line[i] != '\0'))
	    tempop[j++]	= Line[i++];
	tempop[j] = '\0';
	if (InF->UPtr == 0)
	    InF->Pos = ftell(InFile);	/* Position in outer file */
	if (!OpenIncl (tempop, InclList)) {
	    Error (SrcLoc, NoIncl);	/* Couldn't open file */
	    if (InF->UPtr == 0)	{
		InFile = fopen (InF->NPtr, "r");
		fseek (InFile, InF->Pos, 0);
	    }
	    return (Include);		/* Return to outer file	*/
	}
	InFNum++;				/* Bump	nesting	level */
	if (--InF < LowInF)
	    LowInF = InF;
	Heap2Space (strlen (tempop) + 1);	/* Check for space */
	InF->UPtr = 0;				/* Not a user macro */
	InF->NPtr = NextFNS;			/* New stack pointer */
	strcpy (NextFNS, tempop);		/* File	name */
	NextFNS	+= strlen (tempop) + 1;		/* Next	available space	*/
	if (NextFNS > High2)
	    High2 = NextFNS;			/* Set high-water mark */
	InF->NArg = -1;				/* Flag	as an INCLUDE */
	InF->Line = 0;				/* Clear line counter */
	return (Include);
    }

    if (strcmp (OpCode,	"SET") == 0) {                  /* SET */
	if (Label[0] ==	'\0')
	    Error (0, NeedLab);		/* Need	a label	*/
	ObjSrc = GetValue (SrcOp, SrcLoc);
	if (DefLine2 > LineCount)
	    Error (SrcLoc, FwdRef);	/* Illegal forward reference */
	Src.Hunk = Hunk2;
	if (!ReadSymTab	(Label))		/* Make	a new entry */
	    AddSymTab (Label, ObjSrc, Src.Hunk,	LineCount, 4);
	else if	(Sym->Flags & 4) {		/* Re-SET the symbol */
	    Sym->Val = ObjSrc;			/* SET value */
	    Sym->Hunk =	Src.Hunk;		/* Hunk	number */
	    Sym->Defn =	LineCount;		/* Statement number */
	}
	PrntAddr = MakeHunk = TRUE;
	return (Set);
    }

    if (strcmp (OpCode,	"MACRO") == 0) {                /* MACRO */
	Dir = Macro;
	tempop[0] = ' ';
	i = 0;				/* Prepend name	with a */
	j = 1;				/*  blank and convert */
	while (Label[i])		/*  it to upper	case */
	    tempop[j++]	= toupper (Label[i++]);
	tempop[j] = '\0';

	if (!Pass2) {			/* Pass	1 */
	    if (Label[0] != '\0') {             /* Need a label */
		templong = HeapLim - Heap;	/* Offset to text */
		if (!ReadSymTab	(tempop))	/* Save	MACRO name */
		    AddSymTab (tempop, 0L, templong, LineCount,	8);
		AddMacLine (Line);		/* Save	MACRO stmt. */

		while (strcmp (OpCode, "ENDM")) {
		    if (LineParts (dummy))
			break;			/* Premature EOF */
		    AddMacLine (Line);		/* Store a line	*/
		}
	    }
	} else {			/* Pass	2 */
	    if (Label[0] == '\0')
		Error (0, NeedLab);		/* Need	a label	*/
	    else {
		ReadSymTab (tempop);
		if (Sym->Defn != LineCount) {
		    Error (LabLoc, DupMac);	/* Duplicate MACRO */
		    AddRef (LineCount);
		}
	    }
	    if (!SuppList)
		WriteListLine (List);		/* Echo	MACRO */

	    while (1) {
		if (LineParts (dummy)) {
		    Error (OpLoc, NoENDM);	/* Premature EOF */
		    break;
		} else {
		    if (strcmp (OpCode,	"ENDM") == 0)
			break;
		    if (!SuppList)
			WriteListLine (List);	/* Echo	a line */
		}
	    }
	}

	return (Macro);
    }

    if (strcmp (OpCode,	"IFEQ") == 0) {                 /* IFEQ */
	ObjSrc = GetValue (SrcOp, SrcLoc);
	if (ObjSrc != 0)
	    SkipNest++;		/* Skip	to the next ENDC */
	return (If);
    }
    if (strcmp (OpCode,	"IFNE") == 0) {                 /* IFNE */
	ObjSrc = GetValue (SrcOp, SrcLoc);
	if (ObjSrc == 0)
	    SkipNest++;
	return (If);
    }
    if (strcmp (OpCode,	"IFGT") == 0) {                 /* IFGT */
	ObjSrc = GetValue (SrcOp, SrcLoc);
	if (ObjSrc <= 0)
	    SkipNest++;
	return (If);
    }
    if (strcmp (OpCode,	"IFGE") == 0) {                 /* IFGE */
	ObjSrc = GetValue (SrcOp, SrcLoc);
	if (ObjSrc < 0)
	    SkipNest++;
	return (If);
    }
    if (strcmp (OpCode,	"IFLT") == 0) {                 /* IFLT */
	ObjSrc = GetValue (SrcOp, SrcLoc);
	if (ObjSrc >= 0)
	    SkipNest++;
	return (If);
    }
    if (strcmp (OpCode,	"IFLE") == 0) {                 /* IFLE */
	ObjSrc = GetValue (SrcOp, SrcLoc);
	if (ObjSrc > 0)
	    SkipNest++;
	return (If);
    }
    if (strcmp (OpCode,	"IFC") == 0) {                  /* IFC */
	if (strcmp (SrcOp, DestOp) != 0)
	    SkipNest++;
	return (If);
    }
    if (strcmp (OpCode,	"IFNC") == 0) {                 /* IFNC */
	if (strcmp (SrcOp, DestOp) == 0)
	    SkipNest++;
	return (If);
    }
    if (strcmp (OpCode,	"IFD") == 0) {                  /* IFD */
	if (ReadSymTab (SrcOp))
	    AddRef (LineCount);
	if (DefLine2 > LineCount)
	    SkipNest++;
	return (If);
    }
    if (strcmp (OpCode,	"IFND") == 0) {                 /* IFND */
	if (ReadSymTab (SrcOp))
	    AddRef (LineCount);
	if (DefLine2 <=	LineCount)
	    SkipNest++;
	return (If);
    }

    if ((strcmp	(OpCode, "ENDC") == 0)                  /* ENDC */
    || (strcmp (OpCode,	"ENDIF") == 0))                 /* ENDIF */
	return (EndC);			/* LineParts will take care of it */

    if ((strcmp	(OpCode, "CODE") == 0)                  /* CODE */
    || (strcmp (OpCode,	"DATA") == 0)                   /* DATA */
    || (strcmp (OpCode,	"BSS") == 0)) {                 /* BSS */
	if (SFormat)
	    Error (OpLoc, NotSFmt);	/* Not in S-format */
	DoSection (SrcOp, SrcLoc, OpCode, OpLoc, DestOp, DestLoc);
	return (Section);		/* Treat as SECTION */
    }
    if (strcmp (OpCode,	"CSEG") == 0) {                 /* CSEG */
	if (SFormat)
	    Error (OpLoc, NotSFmt);	/* Not in S-format */
	DoSection (SrcOp, SrcLoc, "CODE", OpLoc, DestOp, DestLoc);
	return (Section);		/* Treat as CODE */
    }
    if (strcmp (OpCode,	"DSEG") == 0) {                 /* DSEG */
	if (SFormat)
	    Error (OpLoc, NotSFmt);	/* Not in S-format */
	DoSection (SrcOp, SrcLoc, "DATA", OpLoc, DestOp, DestLoc);
	return (Section);		/* Treat as DATA */
    }

    if (strcmp (OpCode,	"SECTION") == 0) {              /* SECTION */
	if (SFormat)
	    Error (OpLoc, NotSFmt);	/* Not in S-format */
	tempop[0] = '\0';
	j = DestLoc + strlen (DestOp);	/* Check for flags */
	if (Line[j] == ',') {
	    j++;
	    GetField (Line, j, tempop);	/* Get specification */
	}
	DoSection (SrcOp, SrcLoc, DestOp, DestLoc, tempop, j);
	return (Section);
    }

    if (strcmp (OpCode,	"IDNT") == 0) {                 /* IDNT */
	i = SrcLoc;
	if ((Line[i] ==	'"') || (Line[i] == '\''))
	    i++;			/* Ignore quotes */
	j = 0;
	while (!isspace(Line[i])
	&& (Line[i] != '"')
	&& (Line[i] != '\'')
	&& (Line[i] != '\0'))
	    IdntName[j++] = Line[i++];
	IdntName[j] = '\0';
	return (Idnt);
    }

    if (strcmp (OpCode,	"DCB") == 0) {                  /* DCB */
	if ((Size == Word) || (Size == Long))
	    AddrCnt = AddrBndW (AddrCnt);
	ObjSrc = GetValue (SrcOp, SrcLoc);	/* Replication factor */
	if (DefLine2 > LineCount) {
	    Error (SrcLoc, FwdRef);	/* Illegal forward reference */
	    ObjSrc = 0;
	}
	if (Hunk2 != ABSHUNK) {
	    Error (SrcLoc, AbsReq);	/* Must	be absolute! */
	    ObjSrc = 0;
	}
	ObjDest	= GetValue (DestOp, DestLoc);	/* Value to replicate */
	Dest.Hunk = Hunk2;
	for (i = 0; i <	ObjSrc;	i++) {
	    if (nX >= MAXLINE) {
		Error (SrcLoc, DCOflo);		/* ObjString overflowed	*/
		break;
	    }
	    if (Dest.Hunk != ABSHUNK) {
		templong = AddrCnt + nX;	/* Relocatable */
		PutRel (templong, Hunk2, Size);
	    }
	    if (Size ==	4) {
		ObjString[nX++]	= (ObjDest >> 24) & 0x00FF;
		ObjString[nX++]	= (ObjDest >> 16) & 0x00FF;
	    }
	    if (Size >=	2)
		ObjString[nX++]	= (ObjDest >> 8) & 0x00FF;
	    ObjString[nX++] = ObjDest &	0x00FF;
	}
	AddrAdv	= InstSize = nX;
	PrntAddr = MakeHunk = TRUE;
	return (DCB);
    }

    if (strcmp (OpCode,	"EQUR") == 0) {                 /* EQUR */
	if ((i = IsRegister (SrcOp, strlen (SrcOp))) < 0)
	    Error (SrcLoc, AddrErr);	/* Not a valid register	*/
	if (Label[0] ==	'\0')
	    Error (0, NeedLab);		/* Need	a label	*/
	else {
	    if (!ReadSymTab (Label))	/* Make	a new entry */
		AddSymTab (Label, (long) i, 0L,	LineCount, 0x20);
	    GotEqur = TRUE;		/* We have at least one	EQUR */
	}
	return (Equr);
    }

    if (strcmp (OpCode,	"REG") == 0) {                  /* REG */
	if (Label[0] ==	'\0')
	    Error (0, NeedLab);		/* Need	a label	*/
	else {
	    i =	GetMultReg (SrcOp, FALSE, SrcLoc);
	    if (!ReadSymTab (Label))	/* Make	a new entry */
		AddSymTab (Label, (long) i, 0L,	LineCount, 0x40);
	    GotEqur = TRUE;		/* We have at least one	EQUR */
	}
	return (Reg);
    }

    return (None);				/* Not a directive */
}



DoSection (name, nameloc, type,	typeloc, flags,	flagloc)
char *name, *type, *flags;
int nameloc, typeloc, flagloc;
/* Processes SECTION directive or equivalent */
{
    static long	HunkPos;	/* Seek	address	of start of section */
    register int i, j;
    long newflags, templong;
    char tempop[MAXLINE];

    PrntAddr = TRUE;

    for	(i = 0;	type[i]; i++)		/* Convert section type	*/
	type[i]	= toupper (type[i]);	/*  to upper case */
    if ((type[0] == '\0') || (strcmp (type, "CODE") == 0))
	newflags = HunkCode;		/* Code	section	*/
    else if (strcmp (type, "DATA") == 0)
	newflags = HunkData;		/* Data	section	*/
    else if (strcmp (type, "BSS") == 0)
	newflags = HunkBSS;		/* BSS section */
    else {
	Error (typeloc,	OperErr);	/* Invalid type	*/
	strcpy (type, "CODE");
	newflags = HunkCode;		/* Make	it CODE	*/
    }
    newflags <<= 16;	/* Shift to high-order 16 bits */

    if (flags[0]) {
	for (i = 0; flags[i]; i++)		/* Convert flags */
	    flags[i] = toupper (flags[i]);	/*  to upper case */
	if (strcmp (flags, "CHIP") == 0)
	    newflags |=	MEMF_CHIP;		/* CHIP	memory */
	else if	(strcmp	(flags,	"FAST") == 0)
	    newflags |=	MEMF_FAST;		/* FAST	memory */
	else
	    Error (flagloc, OperErr);		/* Invalid - ignore */
    }

    AddrCnt = AddrBndL (AddrCnt);	/* Finish on long word */
    templong = (newflags & 0xFFFF0000) >> 16;
    sprintf (tempop,"  %4x",HunkSeq++); /* Make section name unique */
    i =	0;
    if ((name[i] == '"') || (name[i] == '\''))
	i++;				/* Ignore quotes */
    j =	6;
    while (!isspace(name[i])
    && (name[i]	!= '"')
    && (name[i]	!= '\'')
    && (name[i]	!= '\0'))
	tempop[j++] = name[i++];	/* Concatenate section name */
    tempop[j] =	'\0';

    if (ReadSymTab (tempop)) {		/* Scan	for section name */
	if (HunkType ==	HunkNone) {
	    SectLine = 1;		/* Start of first section */
	} else {
	    if (Pass2) {
		AddRef (LineCount);
		DumpSdata (Srec);	/* Finish the previous hunk */
		if (!MakeHunk)		/* If it was a null hunk,   */
		    fseek (Srec, HunkPos, 0);	/*  overwrite it.   */
	    }
	    Sect->Val =	AddrCnt;	/* End of old section */
	    SectLine = LineCount;	/* Start of new	section	*/
	}
	Sect = Sym;			/* Point to new	section	*/
	AddrCnt	= SectStart = Sym->Val;	/* Continuation	*/
	TempAddr = StartAddr = AddrCnt;
	CurrHunk = Sym->Hunk & 0x0000FFFFL;	    /* Hunk no.	*/
	HunkType = (Sym->Hunk &	0x3FFF0000L) >>	16; /* Type */
	HunkFlags = Sym->Hunk &	0xC0000000L;	    /* Flags */
	if (Pass2 && !SFormat) {		/* Start a new hunk */
	    HunkPos = ftell (Srec);
	    templong = HunkName;
	    putl (Srec,	templong);
	    if (tempop[6])
		DumpName (Srec,	&tempop[6], 0L);	/* Hunk	name */
	    else
		DumpName (Srec,	" ", 0L);
	    putl (Srec,	HunkType);	/* Hunk	type */
	    LenPos = ftell (Srec);	/* Hunk	length goes here */
	    putl (Srec,	0L);		/* For now, set	it to zero */
	}
	MakeHunk = FALSE;		/* We don't have anything yet */
	return;
    }

    if (Pass2) {
	Error (OpLoc, ManySect);	/* Table overflowed in pass 1 */
	return;
    }
    if (NextHunk >= ABSHUNK)		/* Set up a new	table entry */
	return;				/* Section table overflow */

    if (HunkType != HunkNone) {
	Sect->Val = AddrCnt;		/* End of old section */
	SectLine = LineCount;		/* Starting line number	*/
    } else {
	SectLine = 1;			/* Start of first section */
    }
    AddrCnt = SectStart	= 0L;		/* Reset location counter */
    TempAddr = StartAddr = AddrCnt;
    HunkType = (newflags & 0x3FFF0000L)	>> 16;	/* Type	*/
    HunkFlags =	newflags & 0xC0000000L;		/* Flags */
    CurrHunk = NextHunk++;		/* Bump	next hunk number */
    newflags |=	CurrHunk;		/* Add hunk number */
    AddSymTab (tempop, 0L, newflags, LineCount,	16);	/* New entry */
    Sect = Sym;				/* Pointer to new entry	*/
    MakeHunk = FALSE;			/* We don't have anything yet */
    return;
}
