
/*
 *  OPS.C
 *
 *  Handle mnemonics and pseudo ops
 *
 */

/*#include "asm.h"*/

ubyte	 Gen[256];
ubyte	 OrgFill = DEFORGFILL;
int	 Glen;

extern MNE    Mne6502[];
extern MNE    Mne6803[];
extern MNE    MneHD6303[];
extern MNE    Mne68705[];
extern MNE    Mne68HC11[];

void generate(void);
void genfill(int fill, long bytes);
void pushif(int bool);
int gethexdig(int c);

/*
 *  An opcode modifies the SEGMENT flags in the following ways:
 */

void
v_processor(char *str, MNE *dummy)
{
    static int	  called;

    Processor = 0;
    if (called)
	return;
    called = 1;

    if (strcmp(str,"6502") == 0) {
	addhashtable(Mne6502);
	MsbOrder = 0;	    /*	lsb,msb */
	Processor = 6502;
    }
    if (strcmp(str,"6803") == 0) {
	addhashtable(Mne6803);
	MsbOrder = 1;	    /*	msb,lsb */
	Processor = 6803;
    }
    if (strcmp(str,"HD6303") == 0 || strcmp(str, "hd6303") == 0) {
	addhashtable(Mne6803);
	addhashtable(MneHD6303);
	MsbOrder = 1;	    /*	msb,lsb */
	Processor = 6303;
    }
    if (strcmp(str,"68705") == 0) {
	addhashtable(Mne68705);
	MsbOrder = 1;	    /*	msb,lsb */
	Processor = 68705;
    }
    if (strcmp(str,"68HC11") == 0 || strcmp(str, "68hc11") == 0) {
	addhashtable(Mne68HC11);
	MsbOrder = 1;	    /*	msb,lsb */
	Processor = 6811;
    }
    if (Processor == 0)
        asmerr(20,1);
}

#define badcode(mne,adrmode)	(!(mne->okmask & (1 << adrmode)))

void
v_mnemonic(char *str, MNE *mne)
{
    register int addrmode;
    register SYMBOL *sym;
    SYMBOL *symbase;
    int     opsize;

    Csegment->flags |= SF_REF;
    programlabel();
    symbase = eval(str, 1);

    if (Xtrace)
	printf("PC: %04lx  MNE: %s  addrmode: %d  ",
	       Csegment->org, mne->name, symbase->addrmode);
    for (sym = symbase; sym; sym = sym->next) {
	if (sym->flags & SYM_UNKNOWN) {
	    ++Redo;
	    Redo_why |= 1 << 0;
	}
    }
    sym = symbase;
    if (sym->addrmode == AM_IMM8 || sym->addrmode == AM_BYTEADR) {
	if (sym->next) {
	    sym->addrmode = AM_BITMOD;
	    if (sym->next->next)
		sym->addrmode = AM_BITBRAMOD;
	}
    }
    addrmode = sym->addrmode;
    if ((sym->flags & SYM_UNKNOWN) || sym->value >= 0x100)
	opsize = 2;
    else
	opsize = (sym->value) ? 1 : 0;
    while (badcode(mne,addrmode) && Cvt[addrmode])
	addrmode = Cvt[addrmode];
    if (Xtrace)
	printf("mnemask: %08lx adrmode: %d  Cvt[am]: %d\n",
		mne->okmask, addrmode, Cvt[addrmode]);
    if (badcode(mne,addrmode)) {
	asmerr(5,0);
	freesymbollist(symbase);
	return;
    }
    if (Mnext >= 0 && Mnext < NUMOC) {		    /*	Force	*/
	addrmode = Mnext;
	if (badcode(mne,addrmode)) {
	    asmerr(19,0);
	    freesymbollist(symbase);
	    return;
	}
    }
    if (Xtrace)
	printf("final addrmode = %d\n", addrmode);

    while (opsize > Opsize[addrmode]) {
	if (Cvt[addrmode] == 0 || badcode(mne,Cvt[addrmode])) {
	    if (sym->flags & SYM_UNKNOWN)
		break;
	    puts("asmerr 14:");
	    asmerr(14,0);
	    break;
	}
	addrmode = Cvt[addrmode];
    }
    Glen = Adrbytes[addrmode];
    Gen[0] = mne->opcode[addrmode];
    Gen[1] = sym->value;
    if (Opsize[addrmode] > 1) {
	if (MsbOrder) {
	    Gen[1] = sym->value >> 8;
	    Gen[2] = sym->value;
	} else {
	    Gen[2] = sym->value >> 8;
	}
    }
    switch(addrmode) {
    case AM_BITMOD:
	sym = symbase->next;
	if (!(sym->flags & SYM_UNKNOWN) && sym->value >= 0x100)
	    asmerr(14,0);
	Gen[1] = sym->value;
	if (!(symbase->flags & SYM_UNKNOWN)) {
	    if (symbase->value > 7)
		asmerr(15,0);
	    else
		Gen[0] += symbase->value << 1;
	}
	break;
    case AM_BITBRAMOD:
	if (!(symbase->flags & SYM_UNKNOWN)) {
	    if (symbase->value > 7)
		asmerr(15,0);
	    else
		Gen[0] += symbase->value << 1;
	}
	sym = symbase->next;
	if (!(sym->flags & SYM_UNKNOWN) && sym->value >= 0x100)
	    asmerr(14,0);
	Gen[1] = sym->value;
	sym = sym->next;
    case AM_REL:
	if (!(sym->flags & SYM_UNKNOWN)) {
	    long    pc;
	    ubyte   pcf;
	    long    dest;
	    pc = (Csegment->flags & SF_RORG) ? Csegment->rorg : Csegment->org;
	    pcf= (Csegment->flags & SF_RORG) ? Csegment->rflags : Csegment->flags;
	    if ((pcf & 3) == 0) {
	    dest = sym->value - pc - Adrbytes[addrmode];
	    if (dest >= 128 || dest < -128)
		asmerr(10,0);
	    }
	    Gen[(addrmode == AM_REL) ? 1 : 2] = dest & 0xFF;
	}
	break;
    }
    generate();
    freesymbollist(symbase);
}

void
v_trace(char *str, MNE *dummy)
{
    if (str[1] == 'n')
	Xtrace = 1;
    else
	Xtrace = 0;
}

void
v_list(char *str, MNE *dummy)
{
    programlabel();
    if (str[1] == 'n')
	Incfile->flags &= ~INF_NOLIST;
    else
	Incfile->flags |=  INF_NOLIST;
}

void
v_include(char *str, MNE *dummy)
{
    char    *buf;

    programlabel();
    if (*str == '\"') {
	buf = malloc(strlen(str)+1-1);
	strcpy(buf, str+1);
	for (str = buf; *str && *str != '\"'; ++str);
	*str = 0;
	pushinclude(buf);
	free(buf);
    } else {
	pushinclude(str);
    }
}

void
v_seg(char *str, MNE *dummy)
{
    register SEGMENT *seg;

    for (seg = Seglist; seg; seg = seg->next) {
	if (strcmp(str, seg->name) == 0) {
	    Csegment = seg;
	    programlabel();
	    return;
	}
    }
    Csegment = seg = (SEGMENT *)zmalloc(sizeof(SEGMENT));
    seg->next = Seglist;
    seg->name = strcpy(malloc(strlen(str)+1), str);
    seg->flags= seg->rflags = seg->initflags = seg->initrflags = SF_UNKNOWN;
    Seglist = seg;
    if (Mnext == AM_BSS)
	seg->flags |= SF_BSS;
    programlabel();
}

void
v_hex(char *str, MNE *dummy)
{
    register int i;
    register int result;

    programlabel();
    Glen = 0;
    for (i = 0; str[i]; ++i) {
	if (str[i] == ' ')
	    continue;
	result = (gethexdig(str[i]) << 4) + gethexdig(str[i+1]);
	if (str[++i] == 0)
	    break;
	Gen[Glen++] = result;
    }
    generate();
}

int
gethexdig(int c)
{
    if (c >= '0' && c <= '9')
	return(c - '0');
    if (c >= 'a' && c <= 'f')
	return(c - 'a' + 10);
    if (c >= 'A' && c <= 'F')
	return(c - 'A' + 10);
    asmerr(0,0);
    puts("(Must be a valid hex digit)");
    if (F_listfile)
	fputs("(Must be a valid hex digit)\n", FI_listfile);
    return(0);
}

void
v_err(char *str, MNE *dummy)
{
    programlabel();
    asmerr(11, 1);
    exit(1);
}

void
v_dc(char *str, MNE *mne)
{
    register SYMBOL *sym;
    register SYMBOL *tmp;
    register ulong  value;
    char *macstr;
    char vmode = 0;

    Glen = 0;
    programlabel();
#if OlafByte
    /* for byte, .byte, word, .word, long, .long */
    if (mne->name[0] != 'd') {
	static char tmp[4];
	strcpy(tmp, "x.x");
	tmp[2] = mne->name[0];
	findext(tmp);
    }
#endif
    if (mne->name[1] == 'v') {
	register int i;
	vmode = 1;
	for (i = 0; str[i] && str[i] != ' '; ++i);
	tmp = findsymbol(str, i);
	str += i;
	if (tmp == NULL) {
	    puts("EQM label not found");
	    return;
	}
	if (tmp->flags & SYM_MACRO) {
	    macstr = (void *)tmp->string;
	} else {
	    puts("must specify EQM label for DV");
	    return;
	}
    }
    sym = eval(str, 0);
    for (; sym; sym = sym->next) {
	value = sym->value;
	if (sym->flags & SYM_UNKNOWN) {
	    ++Redo;
	    Redo_why |= (1 << 2);
	}
	if (sym->flags & SYM_STRING) {
	    register ubyte *ptr = (void *)sym->string;
	    while ((value = *ptr) != 0) {
		if (vmode) {
		    setspecial(value, 0);
		    tmp = eval(macstr, 0);
		    value = tmp->value;
		    if (tmp->flags & SYM_UNKNOWN) {
			++Redo;
			Redo_why |= (1 << 3);
		    }
		    freesymbollist(tmp);
		}
		switch(Mnext) {
		default:
		case AM_BYTE:
		    Gen[Glen++] = value & 0xFF;
		    break;
		case AM_WORD:
		    if (MsbOrder) {
			Gen[Glen++] = (value >> 8) & 0xFF;
			Gen[Glen++] = value & 0xFF;
		    } else {
			Gen[Glen++] = value & 0xFF;
			Gen[Glen++] = (value >> 8) & 0xFF;
		    }
		    break;
		case AM_LONG:
		    if (MsbOrder) {
			Gen[Glen++] = (value >> 24)& 0xFF;
			Gen[Glen++] = (value >> 16)& 0xFF;
			Gen[Glen++] = (value >> 8) & 0xFF;
			Gen[Glen++] = value & 0xFF;
		    } else {
			Gen[Glen++] = value & 0xFF;
			Gen[Glen++] = (value >> 8) & 0xFF;
			Gen[Glen++] = (value >> 16)& 0xFF;
			Gen[Glen++] = (value >> 24)& 0xFF;
		    }
		    break;
		}
		++ptr;
	    }
	} else {
	    if (vmode) {
		setspecial(value, sym->flags);
		tmp = eval(macstr, 0);
		value = tmp->value;
		if (tmp->flags & SYM_UNKNOWN) {
		    ++Redo;
		    Redo_why |= 1 << 4;
		}
		freesymbollist(tmp);
	    }
	    switch(Mnext) {
	    default:
	    case AM_BYTE:
		Gen[Glen++] = value & 0xFF;
		break;
	    case AM_WORD:
		if (MsbOrder) {
		    Gen[Glen++] = (value >> 8) & 0xFF;
		    Gen[Glen++] = value & 0xFF;
		} else {
		    Gen[Glen++] = value & 0xFF;
		    Gen[Glen++] = (value >> 8) & 0xFF;
		}
		break;
	    case AM_LONG:
		if (MsbOrder) {
		    Gen[Glen++] = (value >> 24)& 0xFF;
		    Gen[Glen++] = (value >> 16)& 0xFF;
		    Gen[Glen++] = (value >> 8) & 0xFF;
		    Gen[Glen++] = value & 0xFF;
		} else {
		    Gen[Glen++] = value & 0xFF;
		    Gen[Glen++] = (value >> 8) & 0xFF;
		    Gen[Glen++] = (value >> 16)& 0xFF;
		    Gen[Glen++] = (value >> 24)& 0xFF;
		}
		break;
	    }
	}
    }
    generate();
    freesymbollist(sym);
}

void
v_ds(char *str, MNE *dummy)
{
    register SYMBOL *sym;
    int mult = 1;
    long filler = 0;

    if (Mnext == AM_WORD)
	mult = 2;
    if (Mnext == AM_LONG)
	mult = 4;
    programlabel();
    if ((sym = eval(str, 0)) != NULL) {
	if (sym->next)
	    filler = sym->next->value;
	if (sym->flags & SYM_UNKNOWN) {
	    ++Redo;
	    Redo_why |= 1 << 5;
	} else {
	    if (sym->next && sym->next->flags & SYM_UNKNOWN) {
		++Redo;
		Redo_why |= 1 << 5;
	    }
	    genfill(filler, sym->value * mult);
	}
	freesymbollist(sym);
    }
}

void
v_org(char *str, MNE *dummy)
{
    register SYMBOL *sym = eval(str, 0);

    Csegment->org = sym->value;
    if (sym->flags & SYM_UNKNOWN)
	Csegment->flags |= SYM_UNKNOWN;
    else
	Csegment->flags &= ~SYM_UNKNOWN;
    if (Csegment->initflags & SYM_UNKNOWN) {
	Csegment->initorg = sym->value;
	Csegment->initflags = sym->flags;
    }
    if (sym->next) {
	OrgFill = sym->next->value;
	if (sym->next->flags & SYM_UNKNOWN)
	    asmerr(18,1);
    }
    programlabel();
    freesymbollist(sym);
}

void
v_rorg(char *str, MNE *dummy)
{
    register SYMBOL *sym = eval(str, 0);

    Csegment->flags |= SF_RORG;
    if (sym->addrmode != AM_IMP) {
	Csegment->rorg = sym->value;
	if (sym->flags & SYM_UNKNOWN)
	    Csegment->rflags |= SYM_UNKNOWN;
	else
	    Csegment->rflags &= ~SYM_UNKNOWN;
	if (Csegment->initrflags & SYM_UNKNOWN) {
	    Csegment->initrorg = sym->value;
	    Csegment->initrflags = sym->flags;
	}
    }
    programlabel();
    freesymbollist(sym);
}

void
v_rend(char *str, MNE *dummy)
{
    programlabel();
    Csegment->flags &= ~SF_RORG;
}

void
v_align(char *str, MNE *dummy)
{
    SYMBOL *sym = eval(str, 0);
    ubyte   fill = 0;
    ubyte   rorg = Csegment->flags & SF_RORG;

    if (rorg)
	Csegment->rflags |= SF_REF;
    else
	Csegment->flags |= SF_REF;
    if (sym->next) {
	if (sym->next->flags & SYM_UNKNOWN) {
	    ++Redo;
	    Redo_why |= 1 << 6;
	} else {
	    fill = sym->value;
	}
    }
    if (rorg) {
	if ((Csegment->rflags | sym->flags) & SYM_UNKNOWN) {
	    ++Redo;
	    Redo_why |= 1 << 7;
	} else {
	    register long n = sym->value - (Csegment->rorg % sym->value);
	    if (n != sym->value)
	    genfill(fill, n);
	}
    } else {
	if ((Csegment->flags | sym->flags) & SYM_UNKNOWN) {
	    ++Redo;
	    Redo_why |= 1 << 8;
	} else {
	    register long n = sym->value - (Csegment->org % sym->value);
	    if (n != sym->value)
	    genfill(fill, n);
	}
    }
    freesymbollist(sym);
    programlabel();
}

void
v_subroutine(char *str, MNE *dummy)
{
    ++Lastlocalindex;
    Localindex = Lastlocalindex;
    programlabel();
}

void
v_equ(char *str, MNE *dummy)
{
    SYMBOL *sym = eval(str, 0);
    SYMBOL *lab;

    lab = findsymbol(Av[0], strlen(Av[0]));
    if (!lab)
	lab = createsymbol(Av[0], strlen(Av[0]));
    if (!(lab->flags & SYM_UNKNOWN)) {
	if (sym->flags & SYM_UNKNOWN) {
	    ++Redo;
	    Redo_why |= 1 << 9;
	} else {
	    if (lab->value != sym->value) {
		asmerr(13,0);
		printf("old value: $%04lx  new value: $%04lx\n",
		       lab->value, sym->value);
		++Redo;
		Redo_why |= 1 << 10;
	    }
	}
    }
    lab->value = sym->value;
    lab->flags = sym->flags & (SYM_UNKNOWN|SYM_STRING);
    lab->string = sym->string;
    sym->flags &= ~(SYM_STRING|SYM_MACRO);
    freesymbollist(sym);
}

void
v_eqm(char *str, MNE *dummy)
{
    register SYMBOL *lab;
    register int len = strlen(Av[0]);

    if ((lab = findsymbol(Av[0], len)) != NULL) {
	if (lab->flags & SYM_STRING)
	    free(lab->string);
    } else {
	lab = createsymbol(Av[0], len);
    }
    lab->value = 0;
    lab->flags = SYM_STRING | SYM_SET | SYM_MACRO;
    lab->string = strcpy(malloc(strlen(str)+1), str);
}

void
v_echo(char *str, MNE *dummy)
{
    SYMBOL *sym = eval(str, 0);
    SYMBOL *s;
    char buf[256];

    for (s = sym; s; s = s->next) {
	if (!(s->flags & SYM_UNKNOWN)) {
	    if (s->flags & (SYM_MACRO|SYM_STRING))
	    sprintf(buf,"%s", s->string);
	    else
	    sprintf(buf,"$%lx", s->value);
	    if (FI_listfile)
	    fprintf(FI_listfile, " %s", buf);
	    printf(" %s", buf);
	}
    }
    puts("");
    if (FI_listfile)
	putc('\n', FI_listfile);
}

void
v_set(char *str, MNE *dummy)
{
    SYMBOL *sym = eval(str, 0);
    SYMBOL *lab;

    lab = findsymbol(Av[0], strlen(Av[0]));
    if (!lab)
	lab = createsymbol(Av[0], strlen(Av[0]));
    lab->value = sym->value;
    lab->flags = sym->flags & (SYM_UNKNOWN|SYM_STRING);
    lab->string = sym->string;
    sym->flags &= ~(SYM_STRING|SYM_MACRO);
    freesymbollist(sym);
}

void
v_execmac(char *str, MACRO *mac)
{
    register INCFILE *inc;
    STRLIST *base;
    register STRLIST **psl, *sl;
    register char *s1;

    programlabel();

    if (Mlevel == MAXMACLEVEL) {
	puts("infinite macro recursion");
	return;
    }
    ++Mlevel;
    base = (STRLIST *)malloc(sizeof(STRLIST)-4+strlen(str)+1);
    base->next = NULL;
    strcpy(base->buf, str);
    psl = &base->next;
    while (*str && *str != '\n') {
	s1 = str;
	while (*str && *str != '\n' && *str != ',')
	    ++str;
	sl = (STRLIST *)malloc(sizeof(STRLIST)-4+1+(str-s1));
	sl->next = NULL;
	*psl = sl;
	psl = &sl->next;
	memcpy(sl->buf, s1, (str-s1));
	sl->buf[str-s1] = 0;
	if (*str == ',')
	    ++str;
	while (*str == ' ')
	    ++str;
    }

    inc = (INCFILE *)zmalloc(sizeof(INCFILE));
    inc->next = Incfile;
    inc->name = mac->name;
    inc->fi   = Incfile->fi;	/* garbage */
    inc->lineno = 0;
    inc->flags = INF_MACRO;
    inc->saveidx = Localindex;
#if OlafDol
    inc->savedolidx = Localdollarindex;
#endif
    inc->strlist = mac->strlist;
    inc->args	  = base;
    Incfile = inc;

    ++Lastlocalindex;
    Localindex = Lastlocalindex;
#if OlafDol
    ++Lastlocaldollarindex;
    Localdollarindex = Lastlocaldollarindex;
#endif
}

void
v_end(char *str, MNE *dummy)
{
    puts("END not implemented yet");
}

void
v_endm(char *str, MNE *dummy)
{
    register INCFILE *inc = Incfile;
    register STRLIST *args, *an;

    programlabel();
    if (inc->flags & INF_MACRO) {
	--Mlevel;
	for (args = inc->args; args; args = an) {
	    an = args->next;
	    free(args);
	}
	Localindex = inc->saveidx;
#if OlafDol
	Localdollarindex = inc->savedolidx;
#endif
	Incfile = inc->next;
	free(inc);
	return;
    }
    puts("not within a macro");
}

void
v_mexit(char *str, MNE *dummy)
{
    v_endm(NULL, NULL);
}

void
v_ifconst(char *str, MNE *dummy)
{
    SYMBOL *sym;

    programlabel();
    sym = eval(str, 0);
    pushif(sym->flags == 0);
    freesymbollist(sym);
}

void
v_ifnconst(char *str, MNE *dummy)
{
    SYMBOL *sym;

    programlabel();
    sym = eval(str, 0);
    pushif(sym->flags != 0);
    freesymbollist(sym);
}

void
v_if(char *str, MNE *dummy)
{
    SYMBOL *sym;

    if (!Ifstack->true || !Ifstack->acctrue) {
	pushif(0);
	return;
    }
    programlabel();
    sym = eval(str, 0);
    if (sym->flags) {
	++Redo;
	Redo_why |= 1 << 11;
	pushif(0);
	Ifstack->acctrue = 0;
    } else {
	pushif(!!sym->value);
    }
    freesymbollist(sym);
}

void
v_else(char *str, MNE *dummy)
{
    if (Ifstack->acctrue && !(Ifstack->flags & IFF_BASE)) {
	programlabel();
	Ifstack->true = !Ifstack->true;
    }
}

void
v_endif(char *str, MNE *dummy)
{
    IFSTACK *ifs = Ifstack;

    if (!(ifs->flags & IFF_BASE)) {
	if (ifs->acctrue)
	    programlabel();
	if (ifs->file != Incfile) {
	    puts("too many endif's");
	} else {
	    Ifstack = ifs->next;
	    free(ifs);
	}
    }
}

void
v_repeat(char *str, MNE *dummy)
{
    register REPLOOP *rp;
    register SYMBOL *sym;

    programlabel();
    sym = eval(str, 0);
    rp = (REPLOOP *)zmalloc(sizeof(REPLOOP));
    rp->next = Reploop;
    rp->file = Incfile;
    rp->seek = ftell(Incfile->fi);
    rp->lineno = Incfile->lineno;
    rp->count = sym->value;
    if ((rp->flags = sym->flags) != 0) {
	++Redo;
	Redo_why |= 1 << 12;
    }
    Reploop = rp;
    freesymbollist(sym);
}

void
v_repend(char *str, MNE *dummy)
{
    if (Reploop) {
	if (Reploop->file == Incfile) {
	    if (Reploop->flags == 0 && --Reploop->count) {
		fseek(Incfile->fi,Reploop->seek,0);
		Incfile->lineno = Reploop->lineno;
	    } else {
		rmnode((void **)&Reploop, sizeof(REPLOOP));
		programlabel();
	    }
	    return;
	}
    }
    puts("no repeat");
}

static long Seglen;
static long Seekback;

void
generate(void)
{
    long seekpos;
    static ulong org;

    if (!Redo) {
	if (!(Csegment->flags & SF_BSS)) {
	    if (Fisclear) {
		Fisclear = 0;
		if (Csegment->flags & SF_UNKNOWN) {
		    ++Redo;
		    Redo_why |= 1 << 1;
		    return;
		}
		org = Csegment->org;
		if (F_format < 3) {
		    putc((org & 0xFF), FI_temp);
		    putc(((org >> 8) & 0xFF), FI_temp);
		    if (F_format == 2) {
			Seekback = ftell(FI_temp);
			Seglen = 0;
			putc(0, FI_temp);
			putc(0, FI_temp);
		    }
		}
	    }
	    switch(F_format) {
	    default:
	    case 3:
	    case 1:
		if (Csegment->org < org) {
		    printf("segment: %s %s  vs current org: %04lx\n",
		    Csegment->name, sftos(Csegment->org, Csegment->flags), org);
		    asmerr(12, 1);
		    exit(1);
		}
		while (Csegment->org != org) {
		    putc(OrgFill, FI_temp);
		    ++org;
		}
		fwrite(Gen, Glen, 1, FI_temp);
		break;
	    case 2:
		if (org != Csegment->org) {
		    org = Csegment->org;
		    seekpos = ftell(FI_temp);
		    fseek(FI_temp, Seekback, 0);
		    putc((Seglen & 0xFF), FI_temp);
		    putc(((Seglen >> 8) & 0xFF), FI_temp);
		    fseek(FI_temp, seekpos, 0);
		    putc((org & 0xFF), FI_temp);
		    putc(((org >> 8) & 0xFF), FI_temp);
		    Seekback = ftell(FI_temp);
		    Seglen = 0;
		    putc(0, FI_temp);
		    putc(0, FI_temp);
		}
		fwrite(Gen, Glen, 1, FI_temp);
		Seglen += Glen;
	    }
	    org += Glen;
	}
    }
    Csegment->org += Glen;
    if (Csegment->flags & SF_RORG)
    Csegment->rorg += Glen;
}

void
closegenerate(void)
{
    if (!Redo) {
	if (F_format == 2) {
	    fseek(FI_temp, Seekback, 0);
	    putc((Seglen & 0xFF), FI_temp);
	    putc(((Seglen >> 8) & 0xFF), FI_temp);
	    fseek(FI_temp, 0L, 2);
	}
    }
}

void
genfill(int fill, long bytes)
{
    memset(Gen, fill, sizeof(Gen));
    while (bytes > sizeof(Gen)) {
	Glen = sizeof(Gen);
	bytes -= sizeof(Gen);
	generate();
    }
    Glen = bytes;
    generate();
}

void
pushif(int bool)
{
    register IFSTACK *ifs = (IFSTACK *)zmalloc(sizeof(IFSTACK));
    ifs->next = Ifstack;
    ifs->file = Incfile;
    ifs->flags = 0;
    ifs->true  = bool;
    ifs->acctrue = Ifstack->acctrue && Ifstack->true;
    Ifstack = ifs;
}
