Exemplo n.º 1
0
void Mesh::LoadOgreXML(const char* name_material, const char* name_mesh)
{
	std::fstream file(name_material, std::ios::in);
	std::string line;
	char name[1000];
	if(file.is_open())
	{
		Material mat,empty_mat;

		while(std::getline(file, line))
		{
			if(sscanf(line.c_str(),"material %s",name )==1){materials.push_back(mat);mat=empty_mat;mat.name=name;}
			sscanf(line.c_str()," ambient %f %f %f",&mat.ambient.x,&mat.ambient.y,&mat.ambient.z );
			sscanf(line.c_str()," diffuse %f %f %f",&mat.diffuse.x,&mat.diffuse.y,&mat.diffuse.z );
			sscanf(line.c_str()," specular %f %f %f",&mat.specular.x,&mat.specular.y,&mat.specular.z );
			sscanf(line.c_str()," emissive %f %f %f",&mat.emissive.x,&mat.emissive.y,&mat.emissive.z );
			if(sscanf(line.c_str()," texture %s",name )==1)
			{
				Texture *texture=&mat.diffuse_map; bool bump=0;
				if(strcmp(name,"_unit")==0)continue;
				if(strcmp(name,"_bump")==0)
				{
					bump=1;
					sscanf(line.c_str()," texture_bump %s",name );
					texture=&mat.bump_map;
				}
				if(strcmp(name,"_ambient")==0)
				{
					sscanf(line.c_str()," texture_ambient %s",name );
					texture=&mat.ambient_map;
				}
				std::string prename;
				std::string tempname(name_material);
				std::size_t pos = tempname.rfind("/");
				if(pos == std::string::npos)
					pos = tempname.rfind("\\");

				if(pos != std::string::npos)
					prename = tempname.substr(0, pos+1);
				texture->filename = prename + std::string(name);
				// texture->gl_handle = loadBMP_custom(texture->filename.c_str());
				texture->gl_handle = loadImage(texture->filename.c_str());
			}
			if(sscanf(line.c_str()," env_map %s",name )==1)
			{
				// To do
			}
		}
		materials.push_back(mat);
		//PrintMaterials();
	}
	else
	{
		std::cerr << "Can't read material" << name_material << std::endl;
		return;
	}

	file.close();
	LoadMesh(name_mesh);
}
Exemplo n.º 2
0
    // Execute the ToString algorithm as described in ECMA-262 Section 9.8.
    // This is ToString(ToPrimitive(input argument, hint String))
    // ToPrimitive(input argument, hint String) calls [[DefaultValue]]
    // described in ECMA-262 8.6.2.6.  The [[DefaultValue]] algorithm
    // with hint String is inlined here.
    Stringp ScriptObject::toString()
    {
        AvmCore *core = this->core();
        Toplevel* toplevel = this->toplevel();

        Atom atomv_out[1];

        // call this.toString()
        // NOTE use callers versioned public to get correct toString
        Multiname tempname(core->findPublicNamespace(), core->ktoString);
        atomv_out[0] = atom();
        Atom result = toplevel->callproperty(atom(), &tempname, 0, atomv_out, vtable);

        // if result is primitive, return its ToString
        if (atomKind(result) != kObjectType)
            return core->string(result);

        // otherwise call this.valueOf()
        tempname.setName(core->kvalueOf);
        atomv_out[0] = atom();
        result = toplevel->callproperty(atom(), &tempname, 0, atomv_out, vtable);

        // if result is primitive, return it
        if (atomKind(result) != kObjectType)
            return core->string(result);

        // could not convert to primitive.
        toplevel->throwTypeError(kConvertToPrimitiveError, core->toErrorString(traits()));
        return NULL; // unreachable
    }
Exemplo n.º 3
0
void ModelLoader::ReadBinSBObj(const tstring& assetName)
{
    //LAYOUT
    //Word: nameLength
        //buffer: name
    //DWord : #vert
        //vector3: pos, vector3: norm, vector2: tex, DWORD tetra, Vector3 bc     : vertex
    //DWord : #triangles
        //DWord, DWord, DWord : triangle


    string filename(assetName.cbegin(), assetName.cend());
    UserStream stream(filename.c_str(), true);

    WORD nameLength = stream.readWord();
    char* name = new char[nameLength];
    stream.readBuffer(name, nameLength);
        
    string tempname(name);
    delete name;
    m_pCurrentSBMesh->SetName(tstring(tempname.cbegin(), tempname.cend()));
      
    m_VPNTTData.clear();
    vector<DWORD> tetraData;
    vector<Vector3> bcData;

    DWORD numVertices = stream.readDword();
    for (DWORD v = 0; v < numVertices; ++v)
    {
        Vector3 pos = stream.readVector3();
        Vector3 norm = stream.readVector3();
        Vector2 tex = stream.readVector2();
        DWORD tetra = stream.readDword();
        Vector3 bc = stream.readVector3();
        m_VPNTTData.push_back(VertexPosNormTanTex(pos, norm, Vector3(), tex));

        tetraData.push_back(tetra);
        bcData.push_back(bc);
    }

    DWORD tris = stream.readDword();
    m_IndexData.clear();
    for (DWORD i = 0; i < tris * 3; ++i)
    {
        DWORD index = stream.readDword();
        m_IndexData.push_back(index);
    }

    m_pCurrentSBMesh->SetVertices(m_VPNTTData);
    m_pCurrentSBMesh->SetIndices(m_IndexData);
    m_pCurrentSBMesh->SetTetra(tetraData);
    m_pCurrentSBMesh->SetBaryCentricCoords(bcData);
}
Exemplo n.º 4
0
void ModelLoader::ReadBinObj(const tstring& assetName)
{
    //LAYOUT
    //DWord : #meshes
        //Word: nameLength
            //buffer: name
        //DWord : #vert
            //vector3: pos, vector3: norm, vector3 tan, vector2: tex     : vertex
        //DWord : #triangles
            //DWord, DWord, DWord : triangle
        //...


    string name(assetName.cbegin(), assetName.cend());
    UserStream stream(name.c_str(), true);

    DWORD meshes = stream.readDword();
    for (DWORD m = 0; m < meshes; ++m)
    {
        WORD nameLength = stream.readWord();
        char* name = new char[nameLength];
        stream.readBuffer(name, nameLength);
        
        string tempname(name);
        tempname = tempname.substr(0, nameLength);
        delete name;
        m_pCurrentMesh = m_pCurrentModel->AddMesh(tstring(tempname.cbegin(), tempname.cend()));

        m_VPNTTData.clear();
        DWORD vertices = stream.readDword();

        for (DWORD v = 0; v < vertices; ++v)
        {
            Vector3 pos = stream.readVector3();
            Vector3 norm = stream.readVector3();
            Vector3 tan = stream.readVector3();
            Vector2 tex = stream.readVector2();

            m_VPNTTData.push_back(VertexPosNormTanTex(pos, norm, tan, tex));
        }

        DWORD indices = stream.readDword() * 3;
        m_IndexData.clear();

        for (DWORD i = 0; i < indices; ++i)
        {
            DWORD index = stream.readDword();
            m_IndexData.push_back(index);
        }
        m_pCurrentMesh->SetVertices(m_VPNTTData);
        m_pCurrentMesh->SetIndices(m_IndexData);
    }
}
void InitMenu(HMENU menu,CString KeyName) 
{ 
    if ( menu==NULL || ( !::IsMenu(menu))) 
        return ; 
    CString tempname(_T(""));
	tempname=KeyName;
    CString szText; 
    int nCount,subCount, id; 
 
    nCount =GetMenuItemCount(menu);// menu->GetMenuItemCount();   //获取该层菜单数 
    for(int i=0;i<nCount;i++)                //遍历所有菜单项 
    { 
        //查看子菜单   如果有子菜单,返回0,否则返回子菜单项数目,如果是子菜单项,返回资源中的菜单COMMAND ID 
		 KeyName=_T("");
		 KeyName=tempname;
        id= GetMenuItemID(menu,i); 
             
         if (id!=-1)
         {
		   
		    szText.Format(_T("_%d"),id);
			 KeyName+=szText;
			//ModifyMenu(menu, i, MF_BYPOSITION|MF_STRING, id, gLoadString(KeyName));
         } 
		 else
		 {
		 
		  szText.Format(_T("_%d"),i);
		   KeyName+=szText;
		 // ModifyMenu(menu, i, MF_BYPOSITION|MF_STRING, i, gLoadString(KeyName));
		 }
        CString name=gLoadString(KeyName);
		if (name.CompareNoCase(_T("Not found"))!=0)
		{
		  ModifyMenu(menu, i, MF_BYPOSITION|MF_STRING, id, name);
		}
	  
		 

		 


		//ModifyMenu(menu, i, MF_BYPOSITION|MF_STRING, i, gLoadString(KeyName));
        if( id==-1 ) 
        { 
            subCount =GetMenuItemCount(GetSubMenu(menu,i)); 
            if ( subCount>0 ) 
                InitMenu(GetSubMenu(menu,i),KeyName); 
        } 
    } 
} 
Exemplo n.º 6
0
FILE *picopen(


    char	*path			/* picture file pathname */
)


{


    char	name[4096];		/* pathnames */
    long	total;			/* and sizes - from *fp_pic */
    char	*tname;			/* pathname */
    FILE	*fp;			/* and pointer for the new temp file */


/*
 *
 * Responsible for finding and opening the next picture file. If we've accumulated
 * any in-line pictures fp_pic won't be NULL and we'll look there first. If *path
 * is found in *fp_pic we create another temp file, open it for update, unlink it,
 * copy in the picture, seek back to the start of the new temp file, and return
 * the file pointer to the caller. If fp_pic is NULL or the lookup fails we just
 * open file *path and return the resulting file pointer to the caller.
 *
 */


    if ( fp_pic != NULL )  {
	fseek(fp_pic, 0L, SEEK_SET);
	while ( fscanf(fp_pic, "%s %ld\n", name, &total) != EOF )  {
	    if ( strcmp(path, name) == 0 )  {
		if ( (tname = tempname("dpost")) == NULL )
		    error(FATAL, "can't generate temp file name");
		if ( (fp = fopen(tname, "w+")) == NULL )
		    error(FATAL, "can't open %s", tname);
		unlink(tname);
		free(tname);
		piccopy(fp_pic, fp, total);
		fseek(fp, 0L, SEEK_SET);
		return(fp);
	    }   /* End if */
	    fseek(fp_pic, total, SEEK_CUR);
	}   /* End while */
    }	/* End if */

    return(fopen(path, "r"));

}   /* End of picopen */
Exemplo n.º 7
0
void CBCTestEikProc::TestFileL()
{
	CEikProcess* proc = CEikonEnv::Static()->Process();

	// main store
    CEikDocument* doc = CEikonEnv::Static()->EikAppUi()->Document();
	CFileStore* store = proc->MainStore();
	AssertNotNullL( store , _L("main store got"));
    proc->SetMainStore(store);
	AssertTrueL( ETrue , _L("main store set"));
	
	// save
	_LIT(KFileName, "C:\\BCTestLog\\foo.txt");
	TFileName newname(KFileName);

	{
		TRAPD( err, proc->SaveToDirectFileStoreL(doc));
		HandleErrL(err);
	}
	
	{
		TRAPD(err, proc->SaveToDirectFileStoreL(doc, &newname));
		HandleErrL(err);
	}
	
	{
		TRAPD( err, proc->SaveToDirectFileStoreL(doc, &newname, ETrue));
		HandleErrL(err);
	}
	
	{
		TRAPD(err, proc->SaveToDirectFileStoreL(doc, &newname, EFalse));
		HandleErrL(err);
	}
	
	_LIT(KTempFile, "C:\\BCTestLog\\temp.txt");
	TFileName tempname(KTempFile);
	{
		TRAPD(err, proc->SaveToDirectFileStoreL(doc, &newname, ETrue, &tempname));
		HandleErrL(err);
	}
	
	{
		TRAPD(err, proc->SaveToDirectFileStoreL(doc, &newname, EFalse, &tempname));
		HandleErrL(err);
	}
}
Exemplo n.º 8
0
void
inlinepic(


    FILE	*fp,			/* current input file */
    char	*buf			/* whatever followed "x X InlinePicture" */
)


{


    char	*tname;			/* temp file pathname - for *fp_pic */
    char	name[4096];		/* picture file pathname */
    long	total;			/* and size - both from *buf */


/*
 *
 * Adds an in-line picture file to the end of temporary file *fp_pic. All pictures
 * grabbed from the input file are saved in the same temp file. Each is preceeded
 * by a one line header that includes the original picture file pathname and the
 * size of the picture in bytes. The in-line picture file is opened for update,
 * left open, and unlinked so it disappears when we do.
 *
 */


    if ( fp_pic == NULL )  {
	if ( (tname = tempname("dpost")) == NULL )
	    error(FATAL, "can't generate in-line picture file name");
	if ( (fp_pic = fopen(tname, "w+")) == NULL )
	    error(FATAL, "can't open in-line picture file %s", tname);
	unlink(tname);
    }	/* End if */

    if ( sscanf(buf, "%s %ld", name, &total) != 2 )
	error(FATAL, "in-line picture error");

    fseek(fp_pic, 0L, SEEK_END);
    fprintf(fp_pic, "%s %ld\n", name, total);
    getc(fp);
    fflush(fp_pic);
    piccopy(fp, fp_pic, total);
    ungetc('\n', fp);

}   /* End of inlinepic */
Exemplo n.º 9
0
/**
 *  Läd einen Effekt.
 *
 *  @param[in] type Typ der Daten
 *  @param[in] data Datenblock
 *  @param[in] size Größe des Datenblocks
 *
 *  @return Sounddeskriptor bei Erfolg, @p NULL bei Fehler
 *
 *  @author FloSoft
 */
Sound *AudioSDL::LoadEffect(unsigned int data_type, unsigned char *data, unsigned long size)
{
	SoundSDL_Effect * sd = new SoundSDL_Effect();
	
	char file[512];
	if(!tempname(file, 512))
		return false;

	strncat(file, ".wav", 512);
	
	FILE *dat = fopen(file, "wb");
	if(!dat)
		return false;

	if(fwrite(data, 1, size, dat) != size)
		return false;
	
	fclose(dat);

	switch(data_type)
	{
	default:
		return false;

	case AudioDriver::AD_WAVE:
		{
			sd->sound = Mix_LoadWAV(file);
		} break;
	/// @todo Alle Formate die SDL mit LoadWAV laden kann angeben
	}

	unlink(file);

	if(sd->sound == NULL)
	{
		fprintf(stderr, "%s\n", Mix_GetError());
		delete sd;
		return NULL;
	}

	sd->SetNr((int)sounds.size());
	sounds.push_back(sd);

	return sd;
}
Exemplo n.º 10
0
/*
 * generate:
 *	res = n;
 * simplifies and calls gmove.
 */
void
complexmove(Node *f, Node *t)
{
	int ft, tt;
	Node n1, n2, n3, n4;

	if(debug['g']) {
		dump("\ncomplexmove-f", f);
		dump("complexmove-t", t);
	}

	if(!t->addable)
		fatal("complexmove: to not addable");

	ft = simsimtype(f->type);
	tt = simsimtype(t->type);
	switch(CASE(ft,tt)) {

	default:
		fatal("complexmove: unknown conversion: %T -> %T\n",
			f->type, t->type);

	case CASE(TCOMPLEX64,TCOMPLEX64):
	case CASE(TCOMPLEX64,TCOMPLEX128):
	case CASE(TCOMPLEX128,TCOMPLEX64):
	case CASE(TCOMPLEX128,TCOMPLEX128):
		// complex to complex move/convert.
		// make f addable.
		// also use temporary if possible stack overlap.
		if(!f->addable || overlap(f, t)) {
			tempname(&n1, f->type);
			complexmove(f, &n1);
			f = &n1;
		}

		subnode(&n1, &n2, f);
		subnode(&n3, &n4, t);

		cgen(&n1, &n3);
		cgen(&n2, &n4);
		break;
	}
}
Exemplo n.º 11
0
/*
 * convert switch of the form
 *	switch v := i.(type) { case t1: ..; case t2: ..; }
 * into if statements
 */
void
typeswitch(Node *sw)
{
	Node *def;
	NodeList *cas;
	Node *a;
	Case *c, *c0, *c1;
	int ncase;
	Type *t;

	if(sw->ntest == nil)
		return;
	if(sw->ntest->right == nil) {
		setlineno(sw);
		yyerror("type switch must have an assignment");
		return;
	}
	walkexpr(&sw->ntest->right, &sw->ninit);
	if(!istype(sw->ntest->right->type, TINTER)) {
		yyerror("type switch must be on an interface");
		return;
	}
	cas = nil;

	/*
	 * predeclare temporary variables
	 * and the boolean var
	 */
	facename = nod(OXXX, N, N);
	tempname(facename, sw->ntest->right->type);
	a = nod(OAS, facename, sw->ntest->right);
	typecheck(&a, Etop);
	cas = list(cas, a);

	casebody(sw, facename);

	boolname = nod(OXXX, N, N);
	tempname(boolname, types[TBOOL]);
	typecheck(&boolname, Erv);

	hashname = nod(OXXX, N, N);
	tempname(hashname, types[TUINT32]);
	typecheck(&hashname, Erv);

	t = sw->ntest->right->type;
	if(isnilinter(t))
		a = syslook("efacethash", 1);
	else
		a = syslook("ifacethash", 1);
	argtype(a, t);
	a = nod(OCALL, a, N);
	a->list = list1(facename);
	a = nod(OAS, hashname, a);
	typecheck(&a, Etop);
	cas = list(cas, a);

	c0 = mkcaselist(sw, Stype);
	if(c0 != C && c0->type == Tdefault) {
		def = c0->node->right;
		c0 = c0->link;
	} else {
		def = nod(OBREAK, N, N);
	}

loop:
	if(c0 == C) {
		cas = list(cas, def);
		sw->nbody = concat(cas, sw->nbody);
		sw->list = nil;
		walkstmtlist(sw->nbody);
		return;
	}

	// deal with the variables one-at-a-time
	if(c0->type != Ttypeconst) {
		a = typebsw(c0, 1);
		cas = list(cas, a);
		c0 = c0->link;
		goto loop;
	}

	// do binary search on run of constants
	ncase = 1;
	for(c=c0; c->link!=C; c=c->link) {
		if(c->link->type != Ttypeconst)
			break;
		ncase++;
	}

	// break the chain at the count
	c1 = c->link;
	c->link = C;

	// sort and compile constants
	c0 = csort(c0, typecmp);
	a = typebsw(c0, ncase);
	cas = list(cas, a);

	c0 = c1;
	goto loop;
}
Exemplo n.º 12
0
/* filename - process file name argument `name', return status */
static int filename(char *name, char *base) {
	int status = 0;
	static char *stemp, *itemp;

	if (base == 0)
		base = basename(name);
	switch (suffix(name, suffixes, 4)) {
	case 0:	/* C source files */
		compose(cpp, plist, append(name, 0), 0);
		if (Eflag) {
			status = callsys(av);
			break;
		}
		if (itemp == NULL)
			itemp = tempname(first(suffixes[1]));
		compose(cpp, plist, append(name, 0), append(itemp, 0));
		status = callsys(av);
		if (status == 0)
			return filename(itemp, base);
		break;
	case 1:	/* preprocessed source files */
		if (Eflag)
			break;
		if (Sflag)
			status = compile(name, outfile ? outfile : concat(base, first(suffixes[2])));
		else if ((status = compile(name, stemp?stemp:(stemp=tempname(first(suffixes[2]))))) == 0)
			return filename(stemp, base);
		break;
	case 2:	/* assembly language files */
		if (Eflag)
			break;
		if (!Sflag) {
			char *ofile;
			if (cflag && outfile)
				ofile = outfile;
			else if (cflag)
				ofile = concat(base, first(suffixes[3]));
			else
				ofile = tempname(first(suffixes[3]));
			compose(as, alist, append(name, 0), append(ofile, 0));
			status = callsys(av);
			if (!find(ofile, llist[1]))
				llist[1] = append(ofile, llist[1]);
		}
		break;
	case 3:	/* object files */
		if (!find(name, llist[1]))
			llist[1] = append(name, llist[1]);
		break;
	default:
		if (Eflag) {
			compose(cpp, plist, append(name, 0), 0);
			status = callsys(av);
		}
		llist[1] = append(name, llist[1]);
		break;
	}
	if (status)
		errcnt++;
	return status;
}
Exemplo n.º 13
0
void
complexgen(Node *n, Node *res)
{
	Node *nl, *nr;
	Node tnl, tnr;
	Node n1, n2, tmp;
	int tl, tr;

	if(debug['g']) {
		dump("\ncomplexgen-n", n);
		dump("complexgen-res", res);
	}

	// pick off float/complex opcodes
	switch(n->op) {
	case OCMPLX:
		subnode(&n1, &n2, res);
		tempname(&tmp, n1.type);
		cgen(n->left, &tmp);
		cgen(n->right, &n2);
		cgen(&tmp, &n1);
		return;

	case OREAL:
		subnode(&n1, &n2, n->left);
		cgen(&n1, res);
		return;

	case OIMAG:
		subnode(&n1, &n2, n->left);
		cgen(&n2, res);
		return;
	}

	// perform conversion from n to res
	tl = simsimtype(res->type);
	tl = cplxsubtype(tl);
	tr = simsimtype(n->type);
	tr = cplxsubtype(tr);
	if(tl != tr) {
		if(!n->addable) {
			tempname(&n1, n->type);
			complexmove(n, &n1);
			n = &n1;
		}
		complexmove(n, res);
		return;
	}

	if(!res->addable) {
		igen(res, &n1, N);
		cgen(n, &n1);
		regfree(&n1);
		return;
	}
	if(n->addable) {
		complexmove(n, res);
		return;
	}

	switch(n->op) {
	default:
		dump("complexgen: unknown op", n);
		fatal("complexgen: unknown op %O", n->op);

	case ODOT:
	case ODOTPTR:
	case OINDEX:
	case OIND:
	case ONAME:	// PHEAP or PPARAMREF var
		igen(n, &n1, res);
		complexmove(&n1, res);
		regfree(&n1);
		return;

	case OCONV:
	case OADD:
	case OSUB:
	case OMUL:
	case OMINUS:
	case OCMPLX:
	case OREAL:
	case OIMAG:
		break;
	}

	nl = n->left;
	if(nl == N)
		return;
	nr = n->right;

	// make both sides addable in ullman order
	if(nr != N) {
		if(nl->ullman > nr->ullman && !nl->addable) {
			tempname(&tnl, nl->type);
			cgen(nl, &tnl);
			nl = &tnl;
		}
		if(!nr->addable) {
			tempname(&tnr, nr->type);
			cgen(nr, &tnr);
			nr = &tnr;
		}
	}
	if(!nl->addable) {
		tempname(&tnl, nl->type);
		cgen(nl, &tnl);
		nl = &tnl;
	}

	switch(n->op) {
	default:
		fatal("complexgen: unknown op %O", n->op);
		break;

	case OCONV:
		complexmove(nl, res);
		break;

	case OMINUS:
		complexminus(nl, res);
		break;

	case OADD:
	case OSUB:
		complexadd(n->op, nl, nr, res);
		break;

	case OMUL:
		complexmul(nl, nr, res);
		break;
	// ODIV call a runtime function
	}
}
Exemplo n.º 14
0
/*
 * normal (expression) switch.
 * rebulid case statements into if .. goto
 */
void
exprswitch(Node *sw)
{
	Node *def;
	NodeList *cas;
	Node *a;
	Case *c0, *c, *c1;
	Type *t;
	int arg, ncase;

	casebody(sw, N);

	arg = Snorm;
	if(isconst(sw->ntest, CTBOOL)) {
		arg = Strue;
		if(sw->ntest->val.u.bval == 0)
			arg = Sfalse;
	}
	walkexpr(&sw->ntest, &sw->ninit);
	t = sw->type;
	if(t == T)
		return;

	/*
	 * convert the switch into OIF statements
	 */
	exprname = N;
	cas = nil;
	if(arg != Strue && arg != Sfalse) {
		exprname = nod(OXXX, N, N);
		tempname(exprname, sw->ntest->type);
		cas = list1(nod(OAS, exprname, sw->ntest));
		typechecklist(cas, Etop);
	}

	c0 = mkcaselist(sw, arg);
	if(c0 != C && c0->type == Tdefault) {
		def = c0->node->right;
		c0 = c0->link;
	} else {
		def = nod(OBREAK, N, N);
	}

loop:
	if(c0 == C) {
		cas = list(cas, def);
		sw->nbody = concat(cas, sw->nbody);
		sw->list = nil;
		walkstmtlist(sw->nbody);
		return;
	}

	// deal with the variables one-at-a-time
	if(c0->type != Texprconst) {
		a = exprbsw(c0, 1, arg);
		cas = list(cas, a);
		c0 = c0->link;
		goto loop;
	}

	// do binary search on run of constants
	ncase = 1;
	for(c=c0; c->link!=C; c=c->link) {
		if(c->link->type != Texprconst)
			break;
		ncase++;
	}

	// break the chain at the count
	c1 = c->link;
	c->link = C;

	// sort and compile constants
	c0 = csort(c0, exprcmp);
	a = exprbsw(c0, ncase, arg);
	cas = list(cas, a);

	c0 = c1;
	goto loop;

}
Exemplo n.º 15
0
Arquivo: mcc.c Projeto: JamesLinus/mcc
int main(int argc, char **argv)
{
    int ret = EXIT_SUCCESS;
    const char *tmpdir;
    size_t fails = 0;

    progname = argv[0];
    setup_sys();
    init_env();
    parse_opts(argc, argv);

    bool partial = opts.E || opts.ast_dump || opts.ir_dump || opts.S || opts.c;

    if (argc == 1) {
        usage();
        return EXIT_SUCCESS;
    } else if (vec_len(inputs) == 0) {
        fprintf(stderr, "no input file.\n");
        return EXIT_FAILURE;
    } else if (output && vec_len(inputs) > 1 && partial) {
        fprintf(stderr,
                "mcc: cannot specify -o when generating multiple output files\n");
        return EXIT_FAILURE;
    }

    if (!(tmpdir = mktmpdir()))
        die("Can't make temporary directory.");

    struct vector *objects = vec_new();

    for (int i = 0; i < vec_len(inputs); i++) {
        const char *ifile = vec_at(inputs, i);
        const char *iname = basename(xstrdup(ifile));
        const char *ofile = NULL;
        int ret;
        if (opts.E || opts.ast_dump || opts.ir_dump) {
            if (output)
                ofile = output;
            ret = translate(ifile, ofile);
        } else if (opts.S) {
            if (output)
                ofile = output;
            else
                ofile = replace_suffix(iname, "s");
            ret = translate(ifile, ofile);
        } else if (opts.c) {
            if (output)
                ofile = output;
            else
                ofile = replace_suffix(iname, "o");
            const char *sfile =
                tempname(tmpdir, replace_suffix(ifile, "s"));
            ret = translate(ifile, sfile);
            if (ret == 0)
                ret = assemble(sfile, ofile);
        } else {
            const char *sfile =
                tempname(tmpdir, replace_suffix(ifile, "s"));
            ret = translate(ifile, sfile);
            if (ret == 0) {
                ofile =
                    tempname(tmpdir,
                             replace_suffix(ifile, "o"));
                ret = assemble(sfile, ofile);
                vec_push(objects, (char *)ofile);
            }
        }
        if (ret == EXIT_FAILURE)
            fails++;
    }

    if (fails) {
        ret = EXIT_FAILURE;
        fprintf(stderr, "%lu succeed, %lu failed.\n",
                vec_len(inputs) - fails, fails);
    } else if (!partial) {
        // link
        ret = link(objects, output, opts.ld_options);
    }

    if (tmpdir)
        rmdir(tmpdir);
    return ret;
}
Exemplo n.º 16
0
/*
 * generate:
 *	res = &n;
 */
void
agen(Node *n, Node *res)
{
	Node *nl, *nr;
	Node n1, n2, n3, tmp, n4;
	Prog *p1;
	uint32 w;
	uint64 v;
	Type *t;

	if(debug['g']) {
		dump("\nagen-res", res);
		dump("agen-r", n);
	}
	if(n == N || n->type == T)
		return;

	if(!isptr[res->type->etype])
		fatal("agen: not tptr: %T", res->type);

	while(n->op == OCONVNOP)
		n = n->left;

	if(n->addable) {
		regalloc(&n1, types[tptr], res);
		gins(ALEAQ, n, &n1);
		gmove(&n1, res);
		regfree(&n1);
		goto ret;
	}

	nl = n->left;
	nr = n->right;

	switch(n->op) {
	default:
		fatal("agen: unknown op %N", n);
		break;

	case OCALLMETH:
		cgen_callmeth(n, 0);
		cgen_aret(n, res);
		break;

	case OCALLINTER:
		cgen_callinter(n, res, 0);
		cgen_aret(n, res);
		break;

	case OCALLFUNC:
		cgen_call(n, 0);
		cgen_aret(n, res);
		break;

	case OINDEX:
		w = n->type->width;
		if(nr->addable)
			goto irad;
		if(nl->addable) {
			if(!isconst(nr, CTINT)) {
				regalloc(&n1, nr->type, N);
				cgen(nr, &n1);
			}
			regalloc(&n3, types[tptr], res);
			agen(nl, &n3);
			goto index;
		}
		tempname(&tmp, nr->type);
		cgen(nr, &tmp);
		nr = &tmp;

	irad:
		regalloc(&n3, types[tptr], res);
		agen(nl, &n3);
		if(!isconst(nr, CTINT)) {
			regalloc(&n1, nr->type, N);
			cgen(nr, &n1);
		}
		goto index;

	index:
		// &a is in &n3 (allocated in res)
		// i is in &n1 (if not constant)
		// w is width

		// explicit check for nil if array is large enough
		// that we might derive too big a pointer.
		if(!isslice(nl->type) && nl->type->width >= unmappedzero) {
			regalloc(&n4, types[tptr], &n3);
			gmove(&n3, &n4);
			n4.op = OINDREG;
			n4.type = types[TUINT8];
			n4.xoffset = 0;
			gins(ATESTB, nodintconst(0), &n4);
			regfree(&n4);
		}

		if(w == 0)
			fatal("index is zero width");

		// constant index
		if(isconst(nr, CTINT)) {
			v = mpgetfix(nr->val.u.xval);
			if(isslice(nl->type)) {

				if(!debug['B'] && !n->etype) {
					n1 = n3;
					n1.op = OINDREG;
					n1.type = types[tptr];
					n1.xoffset = Array_nel;
					nodconst(&n2, types[TUINT64], v);
					gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
					p1 = gbranch(optoas(OGT, types[TUINT32]), T);
					ginscall(throwindex, 0);
					patch(p1, pc);
				}

				n1 = n3;
				n1.op = OINDREG;
				n1.type = types[tptr];
				n1.xoffset = Array_array;
				gmove(&n1, &n3);
			} else
			if(!debug['B'] && !n->etype) {
				if(v < 0)
					yyerror("out of bounds on array");
				else
				if(v >= nl->type->bound)
					yyerror("out of bounds on array");
			}

			nodconst(&n2, types[tptr], v*w);
			gins(optoas(OADD, types[tptr]), &n2, &n3);

			gmove(&n3, res);
			regfree(&n3);
			break;
		}

		// type of the index
		t = types[TUINT64];
		if(issigned[n1.type->etype])
			t = types[TINT64];

		regalloc(&n2, t, &n1);			// i
		gmove(&n1, &n2);
		regfree(&n1);

		if(!debug['B'] && !n->etype) {
			// check bounds
			if(isslice(nl->type)) {
				n1 = n3;
				n1.op = OINDREG;
				n1.type = types[tptr];
				n1.xoffset = Array_nel;
			} else
				nodconst(&n1, types[TUINT64], nl->type->bound);
			gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
			p1 = gbranch(optoas(OLT, types[TUINT32]), T);
			ginscall(throwindex, 0);
			patch(p1, pc);
		}

		if(isslice(nl->type)) {
			n1 = n3;
			n1.op = OINDREG;
			n1.type = types[tptr];
			n1.xoffset = Array_array;
			gmove(&n1, &n3);
		}

		if(w == 1 || w == 2 || w == 4 || w == 8) {
			p1 = gins(ALEAQ, &n2, &n3);
			p1->from.scale = w;
			p1->from.index = p1->from.type;
			p1->from.type = p1->to.type + D_INDIR;
		} else {
			nodconst(&n1, t, w);
			gins(optoas(OMUL, t), &n1, &n2);
			gins(optoas(OADD, types[tptr]), &n2, &n3);
			gmove(&n3, res);
		}

		gmove(&n3, res);
		regfree(&n2);
		regfree(&n3);
		break;

	case ONAME:
		// should only get here with names in this func.
		if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
			dump("bad agen", n);
			fatal("agen: bad ONAME funcdepth %d != %d",
				n->funcdepth, funcdepth);
		}

		// should only get here for heap vars or paramref
		if(!(n->class & PHEAP) && n->class != PPARAMREF) {
			dump("bad agen", n);
			fatal("agen: bad ONAME class %#x", n->class);
		}
		cgen(n->heapaddr, res);
		if(n->xoffset != 0) {
			nodconst(&n1, types[TINT64], n->xoffset);
			gins(optoas(OADD, types[tptr]), &n1, res);
		}
		break;

	case OIND:
		cgen(nl, res);
		break;

	case ODOT:
		agen(nl, res);
		if(n->xoffset != 0) {
			nodconst(&n1, types[TINT64], n->xoffset);
			gins(optoas(OADD, types[tptr]), &n1, res);
		}
		break;

	case ODOTPTR:
		cgen(nl, res);
		if(n->xoffset != 0) {
			// explicit check for nil if struct is large enough
			// that we might derive too big a pointer.
			if(nl->type->type->width >= unmappedzero) {
				regalloc(&n1, types[tptr], res);
				gmove(res, &n1);
				n1.op = OINDREG;
				n1.type = types[TUINT8];
				n1.xoffset = 0;
				gins(ATESTB, nodintconst(0), &n1);
				regfree(&n1);
			}
			nodconst(&n1, types[TINT64], n->xoffset);
			gins(optoas(OADD, types[tptr]), &n1, res);
		}
		break;
	}

ret:
	;
}
Exemplo n.º 17
0
static void
maplit(int ctxt, Node *n, Node *var, NodeList **init)
{
	Node *r, *a;
	NodeList *l;
	int nerr, b;
	Type *t, *tk, *tv, *t1;
	Node *vstat, *index, *value;
	Sym *syma, *symb;

ctxt = 0;

	// make the map var
	nerr = nerrors;

	a = nod(OMAKE, N, N);
	a->list = list1(typenod(n->type));
	litas(var, a, init);

	// count the initializers
	b = 0;
	for(l=n->list; l; l=l->next) {
		r = l->n;

		if(r->op != OKEY)
			fatal("slicelit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;

		if(isliteral(index) && isliteral(value))
			b++;
	}

	t = T;
	if(b != 0) {
		// build type [count]struct { a Tindex, b Tvalue }
		t = n->type;
		tk = t->down;
		tv = t->type;

		symb = lookup("b");
		t = typ(TFIELD);
		t->type = tv;
		t->sym = symb;

		syma = lookup("a");
		t1 = t;
		t = typ(TFIELD);
		t->type = tk;
		t->sym = syma;
		t->down = t1;

		t1 = t;
		t = typ(TSTRUCT);
		t->type = t1;

		t1 = t;
		t = typ(TARRAY);
		t->bound = b;
		t->type = t1;

		dowidth(t);

		// make and initialize static array
		vstat = staticname(t, ctxt);
		b = 0;
		for(l=n->list; l; l=l->next) {
			r = l->n;

			if(r->op != OKEY)
				fatal("slicelit: rhs not OKEY: %N", r);
			index = r->left;
			value = r->right;

			if(isliteral(index) && isliteral(value)) {
				// build vstat[b].a = key;
				a = nodintconst(b);
				a = nod(OINDEX, vstat, a);
				a = nod(ODOT, a, newname(syma));
				a = nod(OAS, a, index);
				typecheck(&a, Etop);
				walkexpr(&a, init);
				a->dodata = 2;
				*init = list(*init, a);

				// build vstat[b].b = value;
				a = nodintconst(b);
				a = nod(OINDEX, vstat, a);
				a = nod(ODOT, a, newname(symb));
				a = nod(OAS, a, value);
				typecheck(&a, Etop);
				walkexpr(&a, init);
				a->dodata = 2;
				*init = list(*init, a);

				b++;
			}
		}

		// loop adding structure elements to map
		// for i = 0; i < len(vstat); i++ {
		//	map[vstat[i].a] = vstat[i].b
		// }
		index = nod(OXXX, N, N);
		tempname(index, types[TINT]);

		a = nod(OINDEX, vstat, index);
		a->etype = 1;	// no bounds checking
		a = nod(ODOT, a, newname(symb));

		r = nod(OINDEX, vstat, index);
		r->etype = 1;	// no bounds checking
		r = nod(ODOT, r, newname(syma));
		r = nod(OINDEX, var, r);

		r = nod(OAS, r, a);

		a = nod(OFOR, N, N);
		a->nbody = list1(r);

		a->ninit = list1(nod(OAS, index, nodintconst(0)));
		a->ntest = nod(OLT, index, nodintconst(t->bound));
		a->nincr = nod(OASOP, index, nodintconst(1));
		a->nincr->etype = OADD;

		typecheck(&a, Etop);
		walkstmt(&a);
		*init = list(*init, a);
	}

	// put in dynamic entries one-at-a-time
	for(l=n->list; l; l=l->next) {
		r = l->n;

		if(r->op != OKEY)
			fatal("slicelit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;

		if(isliteral(index) && isliteral(value))
			continue;

		// build list of var[c] = expr
		a = nod(OINDEX, var, r->left);
		a = nod(OAS, a, r->right);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		if(nerr != nerrors)
			break;

		*init = list(*init, a);
	}
}
Exemplo n.º 18
0
/*
 * Open the status file.  If scantime is not -1, the file is opened
 * for updating, otherwise, it is opened read-only. If the status file
 * couldn't be opened, NULL is returned and errmsg is set to the error
 * message.
 */
struct status *
status_open(struct coll *coll, time_t scantime, char **errmsg)
{
	struct status *st;
	struct stream *file;
	struct fattr *fa;
	char *destpath, *path;
	int error, rv;

	path = coll_statuspath(coll);
	file = stream_open_file(path, O_RDONLY);
	if (file == NULL) {
		if (errno != ENOENT) {
			xasprintf(errmsg, "Could not open \"%s\": %s\n",
			    path, strerror(errno));
			free(path);
			return (NULL);
		}
		st = status_fromnull(path);
	} else {
		st = status_fromrd(path, file);
		if (st == NULL) {
			xasprintf(errmsg, "Error in \"%s\": Bad header line",
			    path);
			free(path);
			return (NULL);
		}
	}

	if (scantime != -1) {
		/* Open for writing too. */
		xasprintf(&destpath, "%s/%s/%s/", coll->co_base,
		    coll->co_colldir, coll->co_name);
		st->tempfile = tempname(destpath);
		if (mkdirhier(destpath, coll->co_umask) != 0) {
			xasprintf(errmsg, "Cannot create directories leading "
			    "to \"%s\": %s", destpath, strerror(errno));
			free(destpath);
			status_free(st);
			return (NULL);
		}
		free(destpath);
		st->wr = stream_open_file(st->tempfile,
		    O_CREAT | O_TRUNC | O_WRONLY, 0644);
		if (st->wr == NULL) {
			xasprintf(errmsg, "Cannot create \"%s\": %s",
			    st->tempfile, strerror(errno));
			status_free(st);
			return (NULL);
		}
		fa = fattr_new(FT_FILE, -1);
		fattr_mergedefault(fa);
		fattr_umask(fa, coll->co_umask);
		rv = fattr_install(fa, st->tempfile, NULL);
		fattr_free(fa);
		if (rv == -1) {
			xasprintf(errmsg,
			    "Cannot set attributes for \"%s\": %s",
			    st->tempfile, strerror(errno));
			status_free(st);
			return (NULL);
		}
		if (scantime != st->scantime)
			st->dirty = 1;
		error = proto_printf(st->wr, "F %d %t\n", STATUS_VERSION,
		    scantime);
		if (error) {
			st->error = STATUS_ERR_WRITE;
			st->suberror = errno;
			*errmsg = status_errmsg(st);
			status_free(st);
			return (NULL);
		}
	}
	return (st);
}
Exemplo n.º 19
0
PUBLIC int LYNewsPost ARGS1(document *,newdoc)
{
	char *newsgroups = strchr(newdoc->address,':')+1;
	char user_input[1024];
	FILE *fd;
	char *tmptr;
	char c;  /* user input */
	char tmpfile[100];
	char cmd[130];
        DocAddress WWWDoc;

	term_message=FALSE;

	/* pop previous document off of stack and load into main memory */
	pop(newdoc);
	WWWDoc.address = newdoc->address;
	WWWDoc.post_data = newdoc->post_data;
	WWWDoc.post_content_type = newdoc->post_content_type;
        if(!HTLoadAbsolute(&WWWDoc))
            return(NOT_FOUND);

	clear();
	move(2,0);

	tempname(tmpfile,NEW_FILE);
	if((fd = fopen(tmpfile,"w")) == NULL) {
	    statusline("Unable to open temp file");
	    sleep(2);
	    return(NORMAL);
	}

	addstr("You will be posting to:");
	addstr("\n	");
	addstr(newsgroups);
	addch('\n');

	/* Use ^C to cancel mailing of comment */
	/* and don't let sigints exit lynx     */
        signal(SIGINT, terminate_message);

	term_message=FALSE;

	addstr("\n\n Please enter your mail address\n");
	strcpy(user_input,"From: ");
	/* add the mail address if there is one */
	if(personal_mail_address)
	    strcat(user_input,personal_mail_address);

	if (LYgetstr(user_input, VISIBLE) < 0 || term_message) {
            statusline("News Post Cancelled!!!");
	    sleep(1);
	    fclose(fd);  /* close the temp file */
	    goto cleanup;
	}
	fprintf(fd,"%s\n",user_input);

        addstr("\n\n Please enter a subject line\n");
        strcpy(user_input,"Subject: ");

	/* add the default subject */
	tmptr = newdoc->title;
	while(isspace(*tmptr)) tmptr++;
	if(strncasecomp(tmptr, "Re:",3))
            strcat(user_input, "Re: ");
        strcat(user_input, newdoc->title);

        if (LYgetstr(user_input, VISIBLE) < 0 || term_message) {
            statusline("News Post Cancelled!!!");
            sleep(1);
            fclose(fd);  /* close the temp file */
            goto cleanup;
        }

	fprintf(fd,"%s\n",user_input);

	/* add Newsgroups: summary: and Keywords: */
	fprintf(fd,"Newsgroups: %s\nSummary: \nKeywords: \n\n",newsgroups);

	if(!no_editor && editor && *editor != '\0') {
	    /* ask if the user wants to include the original message */
	    statusline("Do you wish to inlude the original message? (y/n) ");
	    c=0;
	    while((c = toupper(LYgetch())) != 'Y' && c != 'N')
	        ; /* null body */
	    if(toupper(c) == 'Y')
	        /* the 1 will add the reply ">" in front of every line */
	        print_wwwfile_to_fd(fd,1);

	    fclose(fd);

	    /* spawn the users editor on the news file */
	    sprintf(user_input,"%s %s",editor,tmpfile);
	    statusline("Spawning your selected editor to edit mail message");
	    stop_curses();
	    if(system(user_input)) {
		statusline("Error spawning editor, check your editor definition in the options menu");
	  	sleep(1);
	    }
	    start_curses();

	} else {
	
	    addstr("\n\n Please enter your message below.");
	    addstr("\n When you are done, press enter and put a single period (.)");
	    addstr("\n on a line and press enter again.");
	    addstr("\n\n");
	    scrollok(stdscr,TRUE);
	    refresh();
    	    *user_input = '\0';
	    if (LYgetstr(user_input, VISIBLE) < 0 || term_message) {
	        statusline("News Post Cancelled!!!");
	        sleep(1);
	        fclose(fd);  /* close the temp file */
	        goto cleanup;
	    }


	    while(!STREQ(user_input,".") && !term_message) { 
	       addch('\n');
	       fprintf(fd,"%s\n",user_input);
	       *user_input = '\0';
	       if (LYgetstr(user_input, VISIBLE) < 0) {
	          statusline("News Post Cancelled!!!");
	          sleep(1);
	          fclose(fd);  /* close the temp file */
	          goto cleanup;
	       }
	    }

	    fprintf(fd,"\n");

	    fclose(fd);  /* close the temp file */
	    scrollok(stdscr,FALSE);  /* stop scrolling */
	}

	statusline("Post this message? (y/n) ");
	while((c = toupper(LYgetch())) != 'Y' && c != 'N')
	    ; /* null body */

	clear();  /* clear the screen */

	if(c == 'N') {
	   goto cleanup;
	}

	sprintf(cmd,"%s %s",INEWS,tmpfile);

        stop_curses();
	printf("Posting your message:\n\n%s\n\nPlease wait...", cmd);
#ifndef VMS
	signal(SIGINT, SIG_IGN);
#endif /* not VMS */
	system(cmd);
	start_curses();
#ifdef VMS
	goto cleandown;
#endif /* VMS */

	/* come here to cleanup and exit */
cleanup:
	signal(SIGINT, cleanup_sig);
cleandown:
	term_message = FALSE;

	scrollok(stdscr,FALSE);  /* stop scrolling */
	remove(tmpfile);

	return(NORMAL);
}
Exemplo n.º 20
0
static void
slicelit(int ctxt, Node *n, Node *var, NodeList **init)
{
	Node *r, *a;
	NodeList *l;
	Type *t;
	Node *vstat, *vauto;
	Node *index, *value;
	int mode;

	// make an array type
	t = shallow(n->type);
	t->bound = mpgetfix(n->right->val.u.xval);
	t->width = 0;
	t->sym = nil;
	dowidth(t);

	if(ctxt != 0) {

		// put everything into static array
		vstat = staticname(t, ctxt);
		arraylit(ctxt, 1, n, vstat, init);
		arraylit(ctxt, 2, n, vstat, init);

		// copy static to slice
		a = nod(OSLICE, vstat, nod(OKEY, N, N));
		a = nod(OAS, var, a);
		typecheck(&a, Etop);
		a->dodata = 2;
		*init = list(*init, a);
		return;
	}

	// recipe for var = []t{...}
	// 1. make a static array
	//	var vstat [...]t
	// 2. assign (data statements) the constant part
	//	vstat = constpart{}
	// 3. make an auto pointer to array and allocate heap to it
	//	var vauto *[...]t = new([...]t)
	// 4. copy the static array to the auto array
	//	*vauto = vstat
	// 5. assign slice of allocated heap to var
	//	var = [0:]*auto
	// 6. for each dynamic part assign to the slice
	//	var[i] = dynamic part
	//
	// an optimization is done if there is no constant part
	//	3. var vauto *[...]t = new([...]t)
	//	5. var = [0:]*auto
	//	6. var[i] = dynamic part

	// if the literal contains constants,
	// make static initialized array (1),(2)
	vstat = N;
	mode = getdyn(n, 1);
	if(mode & MODECONST) {
		vstat = staticname(t, ctxt);
		arraylit(ctxt, 1, n, vstat, init);
	}

	// make new auto *array (3 declare)
	vauto = nod(OXXX, N, N);
	tempname(vauto, ptrto(t));

	// set auto to point at new heap (3 assign)
	a = nod(ONEW, N, N);
	a->list = list1(typenod(t));
	a = nod(OAS, vauto, a);
	typecheck(&a, Etop);
	walkexpr(&a, init);
	*init = list(*init, a);

	if(vstat != N) {
		// copy static to heap (4)
		a = nod(OIND, vauto, N);
		a = nod(OAS, a, vstat);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		*init = list(*init, a);
	}

	// make slice out of heap (5)
	a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N)));
	typecheck(&a, Etop);
	walkexpr(&a, init);
	*init = list(*init, a);

	// put dynamics into slice (6)
	for(l=n->list; l; l=l->next) {
		r = l->n;
		if(r->op != OKEY)
			fatal("slicelit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;
		a = nod(OINDEX, var, index);
		a->etype = 1;	// no bounds checking
		// TODO need to check bounds?

		switch(value->op) {
		case OARRAYLIT:
			if(value->type->bound < 0)
				break;
			arraylit(ctxt, 2, value, a, init);
			continue;

		case OSTRUCTLIT:
			structlit(ctxt, 2, value, a, init);
			continue;
		}

		if(isliteral(index) && isliteral(value))
			continue;

		// build list of var[c] = expr
		a = nod(OAS, a, value);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		*init = list(*init, a);
	}
}
Exemplo n.º 21
0
Arquivo: range.c Projeto: 8l/go-learn
void
walkrange(Node *n)
{
	Node *ohv1, *hv1, *hv2;	// hidden (old) val 1, 2
	Node *ha, *hit;	// hidden aggregate, iterator
	Node *a, *v1, *v2;	// not hidden aggregate, val 1, 2
	Node *fn;
	NodeList *body, *init;
	Type *th, *t;

	t = n->type;
	init = nil;

	a = n->right;
	if(t->etype == TSTRING && !eqtype(t, types[TSTRING])) {
		a = nod(OCONV, n->right, N);
		a->type = types[TSTRING];
	}
	ha = nod(OXXX, N, N);
	tempname(ha, a->type);
	init = list(init, nod(OAS, ha, a));

	v1 = n->list->n;
	hv1 = N;

	v2 = N;
	if(n->list->next)
		v2 = n->list->next->n;
	hv2 = N;

	switch(t->etype) {
	default:
		fatal("walkrange");

	case TARRAY:
		hv1 = nod(OXXX, N, n);
		tempname(hv1, types[TINT]);

		init = list(init, nod(OAS, hv1, N));
		n->ntest = nod(OLT, hv1, nod(OLEN, ha, N));
		n->nincr = nod(OASOP, hv1, nodintconst(1));
		n->nincr->etype = OADD;
		body = list1(nod(OAS, v1, hv1));
		if(v2)
			body = list(body, nod(OAS, v2, nod(OINDEX, ha, hv1)));
		break;

	case TMAP:
		th = typ(TARRAY);
		th->type = ptrto(types[TUINT8]);
		th->bound = (sizeof(struct Hiter) + widthptr - 1) / widthptr;
		hit = nod(OXXX, N, N);
		tempname(hit, th);

		fn = syslook("mapiterinit", 1);
		argtype(fn, t->down);
		argtype(fn, t->type);
		argtype(fn, th);
		init = list(init, mkcall1(fn, T, nil, ha, nod(OADDR, hit, N)));
		n->ntest = nod(ONE, nod(OINDEX, hit, nodintconst(0)), nodnil());

		fn = syslook("mapiternext", 1);
		argtype(fn, th);
		n->nincr = mkcall1(fn, T, nil, nod(OADDR, hit, N));

		if(v2 == N) {
			fn = syslook("mapiter1", 1);
			argtype(fn, th);
			argtype(fn, t->down);
			a = nod(OAS, v1, mkcall1(fn, t->down, nil, nod(OADDR, hit, N)));
		} else {
			fn = syslook("mapiter2", 1);
			argtype(fn, th);
			argtype(fn, t->down);
			argtype(fn, t->type);
			a = nod(OAS2, N, N);
			a->list = list(list1(v1), v2);
			a->rlist = list1(mkcall1(fn, getoutargx(fn->type), nil, nod(OADDR, hit, N)));
		}
		body = list1(a);
		break;

	case TCHAN:
		hv1 = nod(OXXX, N, n);
		tempname(hv1, t->type);

		n->ntest = nod(ONOT, nod(OCLOSED, ha, N), N);
		n->ntest->ninit = list1(nod(OAS, hv1, nod(ORECV, ha, N)));
		body = list1(nod(OAS, v1, hv1));
		break;

	case TSTRING:
		ohv1 = nod(OXXX, N, N);
		tempname(ohv1, types[TINT]);

		hv1 = nod(OXXX, N, N);
		tempname(hv1, types[TINT]);
		init = list(init, nod(OAS, hv1, N));

		if(v2 == N)
			a = nod(OAS, hv1, mkcall("stringiter", types[TINT], nil, ha, hv1));
		else {
			hv2 = nod(OXXX, N, N);
			tempname(hv2, types[TINT]);
			a = nod(OAS2, N, N);
			a->list = list(list1(hv1), hv2);
			fn = syslook("stringiter2", 0);
			a->rlist = list1(mkcall1(fn, getoutargx(fn->type), nil, ha, hv1));
		}
		n->ntest = nod(ONE, hv1, nodintconst(0));
		n->ntest->ninit = list(list1(nod(OAS, ohv1, hv1)), a);

		body = list1(nod(OAS, v1, ohv1));
		if(v2 != N)
			body = list(body, nod(OAS, v2, hv2));
		break;
	}

	n->op = OFOR;
	typechecklist(init, Etop);
	n->ninit = concat(n->ninit, init);
	typechecklist(n->ntest->ninit, Etop);
	typecheck(&n->ntest, Erv);
	typecheck(&n->nincr, Etop);
	typechecklist(body, Etop);
	n->nbody = concat(body, n->nbody);
	walkstmt(&n);
}
Exemplo n.º 22
0
/*
 * generate:
 *	res = n;
 * simplifies and calls gmove.
 */
void
cgen(Node *n, Node *res)
{
	Node *nl, *nr, *r;
	Node n1, n2;
	int a, f;
	Prog *p1, *p2, *p3;
	Addr addr;

	if(debug['g']) {
		dump("\ncgen-n", n);
		dump("cgen-res", res);
	}
	if(n == N || n->type == T)
		goto ret;

	if(res == N || res->type == T)
		fatal("cgen: res nil");

	while(n->op == OCONVNOP)
		n = n->left;

	// inline slices
	if(cgen_inline(n, res))
		goto ret;

	if(n->ullman >= UINF) {
		if(n->op == OINDREG)
			fatal("cgen: this is going to misscompile");
		if(res->ullman >= UINF) {
			tempname(&n1, n->type);
			cgen(n, &n1);
			cgen(&n1, res);
			goto ret;
		}
	}

	if(isfat(n->type)) {
		sgen(n, res, n->type->width);
		goto ret;
	}

	if(!res->addable) {
		if(n->ullman > res->ullman) {
			regalloc(&n1, n->type, res);
			cgen(n, &n1);
			if(n1.ullman > res->ullman) {
				dump("n1", &n1);
				dump("res", res);
				fatal("loop in cgen");
			}
			cgen(&n1, res);
			regfree(&n1);
			goto ret;
		}

		if(res->ullman >= UINF)
			goto gen;

		if(complexop(n, res)) {
			complexgen(n, res);
			goto ret;
		}

		f = 1;	// gen thru register
		switch(n->op) {
		case OLITERAL:
			if(smallintconst(n))
				f = 0;
			break;
		case OREGISTER:
			f = 0;
			break;
		}

		if(!iscomplex[n->type->etype]) {
			a = optoas(OAS, res->type);
			if(sudoaddable(a, res, &addr)) {
				if(f) {
					regalloc(&n2, res->type, N);
					cgen(n, &n2);
					p1 = gins(a, &n2, N);
					regfree(&n2);
				} else
					p1 = gins(a, n, N);
				p1->to = addr;
				if(debug['g'])
					print("%P [ignore previous line]\n", p1);
				sudoclean();
				goto ret;
			}
		}

	gen:
		igen(res, &n1, N);
		cgen(n, &n1);
		regfree(&n1);
		goto ret;
	}

	// update addressability for string, slice
	// can't do in walk because n->left->addable
	// changes if n->left is an escaping local variable.
	switch(n->op) {
	case OLEN:
		if(isslice(n->left->type) || istype(n->left->type, TSTRING))
			n->addable = n->left->addable;
		break;
	case OCAP:
		if(isslice(n->left->type))
			n->addable = n->left->addable;
		break;
	}

	if(complexop(n, res)) {
		complexgen(n, res);
		goto ret;
	}

	if(n->addable) {
		gmove(n, res);
		goto ret;
	}

	nl = n->left;
	nr = n->right;

	if(nl != N && nl->ullman >= UINF)
	if(nr != N && nr->ullman >= UINF) {
		tempname(&n1, nl->type);
		cgen(nl, &n1);
		n2 = *n;
		n2.left = &n1;
		cgen(&n2, res);
		goto ret;
	}

	if(!iscomplex[n->type->etype]) {
		a = optoas(OAS, n->type);
		if(sudoaddable(a, n, &addr)) {
			if(res->op == OREGISTER) {
				p1 = gins(a, N, res);
				p1->from = addr;
			} else {
				regalloc(&n2, n->type, N);
				p1 = gins(a, N, &n2);
				p1->from = addr;
				gins(a, &n2, res);
				regfree(&n2);
			}
			sudoclean();
			goto ret;
		}
	}

	switch(n->op) {
	default:
		dump("cgen", n);
		fatal("cgen: unknown op %N", n);
		break;

	// these call bgen to get a bool value
	case OOROR:
	case OANDAND:
	case OEQ:
	case ONE:
	case OLT:
	case OLE:
	case OGE:
	case OGT:
	case ONOT:
		p1 = gbranch(AJMP, T);
		p2 = pc;
		gmove(nodbool(1), res);
		p3 = gbranch(AJMP, T);
		patch(p1, pc);
		bgen(n, 1, p2);
		gmove(nodbool(0), res);
		patch(p3, pc);
		goto ret;

	case OPLUS:
		cgen(nl, res);
		goto ret;

	// unary
	case OCOM:
		a = optoas(OXOR, nl->type);
		regalloc(&n1, nl->type, N);
		cgen(nl, &n1);
		nodconst(&n2, nl->type, -1);
		gins(a, &n2, &n1);
		gmove(&n1, res);
		regfree(&n1);
		goto ret;

	case OMINUS:
		if(isfloat[nl->type->etype]) {
			nr = nodintconst(-1);
			convlit(&nr, n->type);
			a = optoas(OMUL, nl->type);
			goto sbop;
		}
		a = optoas(n->op, nl->type);
		goto uop;

	// symmetric binary
	case OAND:
	case OOR:
	case OXOR:
	case OADD:
	case OMUL:
		a = optoas(n->op, nl->type);
		if(a != AIMULB)
			goto sbop;
		cgen_bmul(n->op, nl, nr, res);
		break;

	// asymmetric binary
	case OSUB:
		a = optoas(n->op, nl->type);
		goto abop;

	case OCONV:
		regalloc(&n1, nl->type, res);
		regalloc(&n2, n->type, &n1);
		cgen(nl, &n1);

		// if we do the conversion n1 -> n2 here
		// reusing the register, then gmove won't
		// have to allocate its own register.
		gmove(&n1, &n2);
		gmove(&n2, res);
		regfree(&n2);
		regfree(&n1);
		break;

	case ODOT:
	case ODOTPTR:
	case OINDEX:
	case OIND:
	case ONAME:	// PHEAP or PPARAMREF var
		igen(n, &n1, res);
		gmove(&n1, res);
		regfree(&n1);
		break;

	case OLEN:
		if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
			// map and chan have len in the first 32-bit word.
			// a zero pointer means zero length
			regalloc(&n1, types[tptr], res);
			cgen(nl, &n1);

			nodconst(&n2, types[tptr], 0);
			gins(optoas(OCMP, types[tptr]), &n1, &n2);
			p1 = gbranch(optoas(OEQ, types[tptr]), T);

			n2 = n1;
			n2.op = OINDREG;
			n2.type = types[TINT32];
			gmove(&n2, &n1);

			patch(p1, pc);

			gmove(&n1, res);
			regfree(&n1);
			break;
		}
		if(istype(nl->type, TSTRING) || isslice(nl->type)) {
			// both slice and string have len one pointer into the struct.
			// a zero pointer means zero length
			regalloc(&n1, types[tptr], res);
			agen(nl, &n1);
			n1.op = OINDREG;
			n1.type = types[TUINT32];
			n1.xoffset = Array_nel;
			gmove(&n1, res);
			regfree(&n1);
			break;
		}
		fatal("cgen: OLEN: unknown type %lT", nl->type);
		break;

	case OCAP:
		if(istype(nl->type, TCHAN)) {
			// chan has cap in the second 32-bit word.
			// a zero pointer means zero length
			regalloc(&n1, types[tptr], res);
			cgen(nl, &n1);

			nodconst(&n2, types[tptr], 0);
			gins(optoas(OCMP, types[tptr]), &n1, &n2);
			p1 = gbranch(optoas(OEQ, types[tptr]), T);

			n2 = n1;
			n2.op = OINDREG;
			n2.xoffset = 4;
			n2.type = types[TINT32];
			gmove(&n2, &n1);

			patch(p1, pc);

			gmove(&n1, res);
			regfree(&n1);
			break;
		}
		if(isslice(nl->type)) {
			regalloc(&n1, types[tptr], res);
			agen(nl, &n1);
			n1.op = OINDREG;
			n1.type = types[TUINT32];
			n1.xoffset = Array_cap;
			gmove(&n1, res);
			regfree(&n1);
			break;
		}
		fatal("cgen: OCAP: unknown type %lT", nl->type);
		break;

	case OADDR:
		agen(nl, res);
		break;

	case OCALLMETH:
		cgen_callmeth(n, 0);
		cgen_callret(n, res);
		break;

	case OCALLINTER:
		cgen_callinter(n, res, 0);
		cgen_callret(n, res);
		break;

	case OCALLFUNC:
		cgen_call(n, 0);
		cgen_callret(n, res);
		break;

	case OMOD:
	case ODIV:
		if(isfloat[n->type->etype]) {
			a = optoas(n->op, nl->type);
			goto abop;
		}
		cgen_div(n->op, nl, nr, res);
		break;

	case OLSH:
	case ORSH:
		cgen_shift(n->op, nl, nr, res);
		break;
	}
	goto ret;

sbop:	// symmetric binary
	if(nl->ullman < nr->ullman) {
		r = nl;
		nl = nr;
		nr = r;
	}

abop:	// asymmetric binary
	if(nl->ullman >= nr->ullman) {
		regalloc(&n1, nl->type, res);
		cgen(nl, &n1);

		if(sudoaddable(a, nr, &addr)) {
			p1 = gins(a, N, &n1);
			p1->from = addr;
			gmove(&n1, res);
			sudoclean();
			regfree(&n1);
			goto ret;
		}
		regalloc(&n2, nr->type, N);
		cgen(nr, &n2);
	} else {
		regalloc(&n2, nr->type, N);
		cgen(nr, &n2);
		regalloc(&n1, nl->type, res);
		cgen(nl, &n1);
	}
	gins(a, &n2, &n1);
	gmove(&n1, res);
	regfree(&n1);
	regfree(&n2);
	goto ret;

uop:	// unary
	regalloc(&n1, nl->type, res);
	cgen(nl, &n1);
	gins(a, N, &n1);
	gmove(&n1, res);
	regfree(&n1);
	goto ret;

ret:
	;
}
Exemplo n.º 23
0
Arquivo: cgen64.c Projeto: 8l/go-learn
/*
 * attempt to generate 64-bit
 *	res = n
 * return 1 on success, 0 if op not handled.
 */
void
cgen64(Node *n, Node *res)
{
	Node t1, t2, *l, *r;
	Node lo1, lo2, hi1, hi2;
	Node al, ah, bl, bh, cl, ch, s, n1, creg;
	Prog *p1, *p2, *p3, *p4, *p5, *p6;

	uint64 v;

	if(res->op != OINDREG && res->op != ONAME) {
		dump("n", n);
		dump("res", res);
		fatal("cgen64 %O of %O", n->op, res->op);
	}

	l = n->left;
	if(!l->addable) {
		tempname(&t1, l->type);
		cgen(l, &t1);
		l = &t1;
	}

	split64(l, &lo1, &hi1);
	switch(n->op) {
	default:
		fatal("cgen64 %O", n->op);

	case OMINUS:
		split64(res, &lo2, &hi2);

		regalloc(&t1, lo1.type, N);
		regalloc(&al, lo1.type, N);
		regalloc(&ah, hi1.type, N);

		gins(AMOVW, &lo1, &al);
		gins(AMOVW, &hi1, &ah);

		gmove(ncon(0), &t1);
		p1 = gins(ASUB, &al, &t1);
		p1->scond |= C_SBIT;
		gins(AMOVW, &t1, &lo2);

		gmove(ncon(0), &t1);
		gins(ASBC, &ah, &t1);
		gins(AMOVW, &t1, &hi2);

		regfree(&t1);
		regfree(&al);
		regfree(&ah);
		splitclean();
		splitclean();
		return;

	case OCOM:
		split64(res, &lo2, &hi2);
		regalloc(&n1, lo1.type, N);

		gins(AMOVW, &lo1, &n1);
		gins(AMVN, &n1, &n1);
		gins(AMOVW, &n1, &lo2);

		gins(AMOVW, &hi1, &n1);
		gins(AMVN, &n1, &n1);
		gins(AMOVW, &n1, &hi2);

		regfree(&n1);
		splitclean();
		splitclean();
		return;

	case OADD:
	case OSUB:
	case OMUL:
	case OLSH:
	case ORSH:
	case OAND:
	case OOR:
	case OXOR:
		// binary operators.
		// common setup below.
		break;
	}

	// setup for binary operators
	r = n->right;
	if(r != N && !r->addable) {
		tempname(&t2, r->type);
		cgen(r, &t2);
		r = &t2;
	}
	if(is64(r->type))
		split64(r, &lo2, &hi2);

	regalloc(&al, lo1.type, N);
	regalloc(&ah, hi1.type, N);

	// Do op.  Leave result in ah:al.
	switch(n->op) {
	default:
		fatal("cgen64: not implemented: %N\n", n);

	case OADD:
		// TODO: Constants
		regalloc(&bl, types[TPTR32], N);
		regalloc(&bh, types[TPTR32], N);
		gins(AMOVW, &hi1, &ah);
		gins(AMOVW, &lo1, &al);
		gins(AMOVW, &hi2, &bh);
		gins(AMOVW, &lo2, &bl);
		p1 = gins(AADD, &bl, &al);
		p1->scond |= C_SBIT;
		gins(AADC, &bh, &ah);
		regfree(&bl);
		regfree(&bh);
		break;

	case OSUB:
		// TODO: Constants.
		regalloc(&bl, types[TPTR32], N);
		regalloc(&bh, types[TPTR32], N);
		gins(AMOVW, &lo1, &al);
		gins(AMOVW, &hi1, &ah);
		gins(AMOVW, &lo2, &bl);
		gins(AMOVW, &hi2, &bh);
		p1 = gins(ASUB, &bl, &al);
		p1->scond |= C_SBIT;
		gins(ASBC, &bh, &ah);
		regfree(&bl);
		regfree(&bh);
		break;

	case OMUL:
		// TODO(kaib): this can be done with 4 regs and does not need 6
		regalloc(&bl, types[TPTR32], N);
		regalloc(&bh, types[TPTR32], N);
		regalloc(&cl, types[TPTR32], N);
		regalloc(&ch, types[TPTR32], N);

		// load args into bh:bl and bh:bl.
		gins(AMOVW, &hi1, &bh);
		gins(AMOVW, &lo1, &bl);
		gins(AMOVW, &hi2, &ch);
		gins(AMOVW, &lo2, &cl);

		// bl * cl
		p1 = gins(AMULLU, N, N);
		p1->from.type = D_REG;
		p1->from.reg = bl.val.u.reg;
		p1->reg = cl.val.u.reg;
		p1->to.type = D_REGREG;
		p1->to.reg = ah.val.u.reg;
		p1->to.offset = al.val.u.reg;
//print("%P\n", p1);

		// bl * ch
		p1 = gins(AMULA, N, N);
		p1->from.type = D_REG;
		p1->from.reg = bl.val.u.reg;
		p1->reg = ch.val.u.reg;
		p1->to.type = D_REGREG;
		p1->to.reg = ah.val.u.reg;
		p1->to.offset = ah.val.u.reg;
//print("%P\n", p1);

		// bh * cl
		p1 = gins(AMULA, N, N);
		p1->from.type = D_REG;
		p1->from.reg = bh.val.u.reg;
		p1->reg = cl.val.u.reg;
		p1->to.type = D_REGREG;
		p1->to.reg = ah.val.u.reg;
		p1->to.offset = ah.val.u.reg;
//print("%P\n", p1);

		regfree(&bh);
		regfree(&bl);
		regfree(&ch);
		regfree(&cl);

		break;

	case OLSH:
		regalloc(&bl, lo1.type, N);
		regalloc(&bh, hi1.type, N);
		gins(AMOVW, &hi1, &bh);
		gins(AMOVW, &lo1, &bl);

		if(r->op == OLITERAL) {
			v = mpgetfix(r->val.u.xval);
			if(v >= 64) {
				// TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al)
				// here and below (verify it optimizes to EOR)
				gins(AEOR, &al, &al);
				gins(AEOR, &ah, &ah);
			} else if(v > 32) {
				gins(AEOR, &al, &al);
				//	MOVW	bl<<(v-32), ah
				gshift(AMOVW, &bl, SHIFT_LL, (v-32), &ah);
			} else if(v == 32) {
				gins(AEOR, &al, &al);
				gins(AMOVW, &bl, &ah);
			} else if(v > 0) {
				//	MOVW	bl<<v, al
				gshift(AMOVW, &bl, SHIFT_LL, v, &al);

				//	MOVW	bh<<v, ah
				gshift(AMOVW, &bh, SHIFT_LL, v, &ah);

				//	OR		bl>>(32-v), ah
				gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
			} else {
				gins(AMOVW, &bl, &al);
				gins(AMOVW, &bh, &ah);
			}
			goto olsh_break;
		}

		regalloc(&s, types[TUINT32], N);
		regalloc(&creg, types[TUINT32], N);
		if (is64(r->type)) {
			// shift is >= 1<<32
			split64(r, &cl, &ch);
			gmove(&ch, &s);
			p1 = gins(AMOVW, &s, &s);
			p1->scond |= C_SBIT;
			p6 = gbranch(ABNE, T);
			gmove(&cl, &s);
			splitclean();
		} else {
			gmove(r, &s);
			p6 = P;
		}
		p1 = gins(AMOVW, &s, &s);
		p1->scond |= C_SBIT;

		// shift == 0
		p1 = gins(AMOVW, &bl, &al);
		p1->scond = C_SCOND_EQ;
		p1 = gins(AMOVW, &bh, &ah);
		p1->scond = C_SCOND_EQ;
		p2 = gbranch(ABEQ, T);

		// shift is < 32
		nodconst(&n1, types[TUINT32], 32);
		gmove(&n1, &creg);
		gcmp(ACMP, &s, &creg);

		//	MOVW.LO		bl<<s, al
		p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &al);
		p1->scond = C_SCOND_LO;

		//	MOVW.LO		bh<<s, ah
		p1 = gregshift(AMOVW, &bh, SHIFT_LL, &s, &ah);
		p1->scond = C_SCOND_LO;

		//	SUB.LO		s, creg
		p1 = gins(ASUB, &s, &creg);
		p1->scond = C_SCOND_LO;

		//	OR.LO		bl>>creg, ah
		p1 = gregshift(AORR, &bl, SHIFT_LR, &creg, &ah);
		p1->scond = C_SCOND_LO;

		//	BLO	end
		p3 = gbranch(ABLO, T);

		// shift == 32
		p1 = gins(AEOR, &al, &al);
		p1->scond = C_SCOND_EQ;
		p1 = gins(AMOVW, &bl, &ah);
		p1->scond = C_SCOND_EQ;
		p4 = gbranch(ABEQ, T);

		// shift is < 64
		nodconst(&n1, types[TUINT32], 64);
		gmove(&n1, &creg);
		gcmp(ACMP, &s, &creg);

		//	EOR.LO	al, al
		p1 = gins(AEOR, &al, &al);
		p1->scond = C_SCOND_LO;

		//	MOVW.LO		creg>>1, creg
		p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
		p1->scond = C_SCOND_LO;

		//	SUB.LO		creg, s
		p1 = gins(ASUB, &creg, &s);
		p1->scond = C_SCOND_LO;

		//	MOVW	bl<<s, ah
		p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah);
		p1->scond = C_SCOND_LO;

		p5 = gbranch(ABLO, T);

		// shift >= 64
		if (p6 != P) patch(p6, pc);
		gins(AEOR, &al, &al);
		gins(AEOR, &ah, &ah);

		patch(p2, pc);
		patch(p3, pc);
		patch(p4, pc);
		patch(p5, pc);
		regfree(&s);
		regfree(&creg);

olsh_break:
		regfree(&bl);
		regfree(&bh);
		break;


	case ORSH:
		regalloc(&bl, lo1.type, N);
		regalloc(&bh, hi1.type, N);
		gins(AMOVW, &hi1, &bh);
		gins(AMOVW, &lo1, &bl);

		if(r->op == OLITERAL) {
			v = mpgetfix(r->val.u.xval);
			if(v >= 64) {
				if(bh.type->etype == TINT32) {
					//	MOVW	bh->31, al
					gshift(AMOVW, &bh, SHIFT_AR, 31, &al);

					//	MOVW	bh->31, ah
					gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
				} else {
					gins(AEOR, &al, &al);
					gins(AEOR, &ah, &ah);
				}
			} else if(v > 32) {
				if(bh.type->etype == TINT32) {
					//	MOVW	bh->(v-32), al
					gshift(AMOVW, &bh, SHIFT_AR, v-32, &al);

					//	MOVW	bh->31, ah
					gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
				} else {
					//	MOVW	bh>>(v-32), al
					gshift(AMOVW, &bh, SHIFT_LR, v-32, &al);
					gins(AEOR, &ah, &ah);
				}
			} else if(v == 32) {
				gins(AMOVW, &bh, &al);
				if(bh.type->etype == TINT32) {
					//	MOVW	bh->31, ah
					gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
				} else {
					gins(AEOR, &ah, &ah);
				}
			} else if( v > 0) {
				//	MOVW	bl>>v, al
				gshift(AMOVW, &bl, SHIFT_LR, v, &al);
	
				//	OR		bh<<(32-v), al
				gshift(AORR, &bh, SHIFT_LL, 32-v, &al);

				if(bh.type->etype == TINT32) {
					//	MOVW	bh->v, ah
					gshift(AMOVW, &bh, SHIFT_AR, v, &ah);
				} else {
					//	MOVW	bh>>v, ah
					gshift(AMOVW, &bh, SHIFT_LR, v, &ah);
				}
			} else {
				gins(AMOVW, &bl, &al);
				gins(AMOVW, &bh, &ah);
			}
			goto orsh_break;
		}

		regalloc(&s, types[TUINT32], N);
		regalloc(&creg, types[TUINT32], N);
		if (is64(r->type)) {
			// shift is >= 1<<32
			split64(r, &cl, &ch);
			gmove(&ch, &s);
			p1 = gins(AMOVW, &s, &s);
			p1->scond |= C_SBIT;
			p6 = gbranch(ABNE, T);
			gmove(&cl, &s);
			splitclean();
		} else {
			gmove(r, &s);
			p6 = P;
		}
		p1 = gins(AMOVW, &s, &s);
		p1->scond |= C_SBIT;

		// shift == 0
		p1 = gins(AMOVW, &bl, &al);
		p1->scond = C_SCOND_EQ;
		p1 = gins(AMOVW, &bh, &ah);
		p1->scond = C_SCOND_EQ;
		p2 = gbranch(ABEQ, T);

		// check if shift is < 32
		nodconst(&n1, types[TUINT32], 32);
		gmove(&n1, &creg);
		gcmp(ACMP, &s, &creg);

		//	MOVW.LO		bl>>s, al
		p1 = gregshift(AMOVW, &bl, SHIFT_LR, &s, &al);
		p1->scond = C_SCOND_LO;

		//	SUB.LO		s,creg
		p1 = gins(ASUB, &s, &creg);
		p1->scond = C_SCOND_LO;

		//	OR.LO		bh<<(32-s), al
		p1 = gregshift(AORR, &bh, SHIFT_LL, &creg, &al);
		p1->scond = C_SCOND_LO;

		if(bh.type->etype == TINT32) {
			//	MOVW	bh->s, ah
			p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &ah);
		} else {
			//	MOVW	bh>>s, ah
			p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &ah);
		}
		p1->scond = C_SCOND_LO;

		//	BLO	end
		p3 = gbranch(ABLO, T);

		// shift == 32
		if(bh.type->etype == TINT32)
			p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
		else
			p1 = gins(AEOR, &al, &al);
		p1->scond = C_SCOND_EQ;
		p1 = gins(AMOVW, &bh, &al);
		p1->scond = C_SCOND_EQ;
		p4 = gbranch(ABEQ, T);

		// check if shift is < 64
		nodconst(&n1, types[TUINT32], 64);
		gmove(&n1, &creg);
		gcmp(ACMP, &s, &creg);

		//	MOVW.LO		creg>>1, creg
		p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
		p1->scond = C_SCOND_LO;

		//	SUB.LO		creg, s
		p1 = gins(ASUB, &creg, &s);
		p1->scond = C_SCOND_LO;

		if(bh.type->etype == TINT32) {
			//	MOVW	bh->(s-32), al
			p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &al);
			p1->scond = C_SCOND_LO;

			//	MOVW	bh->31, ah
			p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
			p1->scond = C_SCOND_LO;
		} else {
			//	MOVW	bh>>(v-32), al
			p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &al);
			p1->scond = C_SCOND_LO;

			p1 = gins(AEOR, &ah, &ah);
			p1->scond = C_SCOND_LO;
		}

		//	BLO	end
		p5 = gbranch(ABLO, T);

		// s >= 64
		if (p6 != P) patch(p6, pc);
		if(bh.type->etype == TINT32) {
			//	MOVW	bh->31, al
			gshift(AMOVW, &bh, SHIFT_AR, 31, &al);

			//	MOVW	bh->31, ah
			gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
		} else {
			gins(AEOR, &al, &al);
			gins(AEOR, &ah, &ah);
		}

		patch(p2, pc);
		patch(p3, pc);
		patch(p4, pc);
		patch(p5, pc);
		regfree(&s);
		regfree(&creg);


orsh_break:
		regfree(&bl);
		regfree(&bh);
		break;

	case OXOR:
	case OAND:
	case OOR:
		// TODO(kaib): literal optimizations
		// make constant the right side (it usually is anyway).
//		if(lo1.op == OLITERAL) {
//			nswap(&lo1, &lo2);
//			nswap(&hi1, &hi2);
//		}
//		if(lo2.op == OLITERAL) {
//			// special cases for constants.
//			lv = mpgetfix(lo2.val.u.xval);
//			hv = mpgetfix(hi2.val.u.xval);
//			splitclean();	// right side
//			split64(res, &lo2, &hi2);
//			switch(n->op) {
//			case OXOR:
//				gmove(&lo1, &lo2);
//				gmove(&hi1, &hi2);
//				switch(lv) {
//				case 0:
//					break;
//				case 0xffffffffu:
//					gins(ANOTL, N, &lo2);
//					break;
//				default:
//					gins(AXORL, ncon(lv), &lo2);
//					break;
//				}
//				switch(hv) {
//				case 0:
//					break;
//				case 0xffffffffu:
//					gins(ANOTL, N, &hi2);
//					break;
//				default:
//					gins(AXORL, ncon(hv), &hi2);
//					break;
//				}
//				break;

//			case OAND:
//				switch(lv) {
//				case 0:
//					gins(AMOVL, ncon(0), &lo2);
//					break;
//				default:
//					gmove(&lo1, &lo2);
//					if(lv != 0xffffffffu)
//						gins(AANDL, ncon(lv), &lo2);
//					break;
//				}
//				switch(hv) {
//				case 0:
//					gins(AMOVL, ncon(0), &hi2);
//					break;
//				default:
//					gmove(&hi1, &hi2);
//					if(hv != 0xffffffffu)
//						gins(AANDL, ncon(hv), &hi2);
//					break;
//				}
//				break;

//			case OOR:
//				switch(lv) {
//				case 0:
//					gmove(&lo1, &lo2);
//					break;
//				case 0xffffffffu:
//					gins(AMOVL, ncon(0xffffffffu), &lo2);
//					break;
//				default:
//					gmove(&lo1, &lo2);
//					gins(AORL, ncon(lv), &lo2);
//					break;
//				}
//				switch(hv) {
//				case 0:
//					gmove(&hi1, &hi2);
//					break;
//				case 0xffffffffu:
//					gins(AMOVL, ncon(0xffffffffu), &hi2);
//					break;
//				default:
//					gmove(&hi1, &hi2);
//					gins(AORL, ncon(hv), &hi2);
//					break;
//				}
//				break;
//			}
//			splitclean();
//			splitclean();
//			goto out;
//		}
		regalloc(&n1, lo1.type, N);
		gins(AMOVW, &lo1, &al);
		gins(AMOVW, &hi1, &ah);
		gins(AMOVW, &lo2, &n1);
		gins(optoas(n->op, lo1.type), &n1, &al);
		gins(AMOVW, &hi2, &n1);
		gins(optoas(n->op, lo1.type), &n1, &ah);
		regfree(&n1);
		break;
	}
	if(is64(r->type))
		splitclean();
	splitclean();

	split64(res, &lo1, &hi1);
	gins(AMOVW, &al, &lo1);
	gins(AMOVW, &ah, &hi1);
	splitclean();

//out:
	regfree(&al);
	regfree(&ah);
}
Exemplo n.º 24
0
/**
 *  Läd ein Musikstück.
 *
 *  @param[in] type Typ der Daten
 *  @param[in] data Datenblock
 *  @param[in] size Größe des Datenblocks
 *
 *  @return Sounddeskriptor bei Erfolg, @p NULL bei Fehler
 *
 *  @author FloSoft
 */
Sound *AudioSDL::LoadMusic(unsigned int data_type, unsigned char *data, unsigned long size)
{
	SoundSDL_Music * sd = new SoundSDL_Music;

	char file[512];
	if(!tempname(file, 512))
		return false;

	switch(data_type)
	{
	default:
		return false;

	case AudioDriver::AD_MIDI:
		{
			strncat(file, ".mid", 512);
		} break;

	case AudioDriver::AD_WAVE:
		{
			strncat(file, ".wav", 512);
		} break;

	case AudioDriver::AD_OTHER:
		{
			const char *header = (const char*)data;
			if(strncmp(header, "OggS", 4) == 0)
				strncat(file, ".ogg", 512);
			else if (strncmp(header, "ID3", 3) == 0 || ((unsigned char)header[0] == 0xFF && (unsigned char)header[1] == 0xFB) )
				strncat(file, ".mp3", 512);
			else
				strncat(file, ".tmp", 512);
		} break;

	/// @todo Alle Formate die SDL mit LoadMUS laden kann angeben
	}

	FILE *dat = fopen(file, "wb");
	if(!dat)
		return false;

	if(fwrite(data, 1, size, dat) != size)
		return false;

	fclose(dat);

	sd->music = Mix_LoadMUS(file);

	unlink(file);

	if(sd->music == NULL)
	{
		fprintf(stderr, "%s\n", Mix_GetError());
		delete sd;
		return NULL;
	}
	
	sd->SetNr((int)sounds.size());
	sounds.push_back(sd);

	return sd;
}
Exemplo n.º 25
0
void WriteWav::
        rewriteNormalized()
{
    _sndfile.reset();

    std::string tempfilename;
    {
        QTemporaryFile tempname("XXXXXX.wav");

        tempname.open();

        tempfilename = tempname.fileName().toStdString();
    }

    bool renamestatus = QFile::rename( _filename.c_str(), tempfilename.c_str() );

    TaskInfo ti("renaming '%s' to '%s': %s",
                _filename.c_str(), tempfilename.c_str(),
                renamestatus?"success":"failed");
    if (!renamestatus)
        return;

    try
    {
        SndfileHandle inputfile(tempfilename);
        if (!inputfile || 0 == inputfile.frames())
        {
            TaskInfo("ERROR: Couldn't read from %s", tempfilename.c_str());
            return;
        }
        SndfileHandle outputfile(_filename, SFM_WRITE, inputfile.format(), inputfile.channels(), inputfile.samplerate());
        if (!outputfile)
        {
            TaskInfo("ERROR: Couldn't write to %s", _filename.c_str());
            return;
        }

        long double mean = _sum/_sumsamples;

        //    -1 + 2*(v - low)/(high-low);
        //    -1 + (v - low)/std::max(_high-mean, mean-_low)

        long double k = std::max(_high-mean, mean-_low);
        float affine_s = 1/k;
        float affine_d = -1 - _low/k;

        if (!_normalize)
        {
            affine_d = mean;
            affine_s = k;
        }

        // when sndfile converts float to 16-bit integers it doesn't bother with rounding to nearest. Adding an offset in advance accomodates for that.
        affine_d += 1.f/(1<<16);

        sf_count_t frames = inputfile.frames();
        TaskInfo ti2("rewriting %u frames", (unsigned)frames);
        int num_channels = inputfile.channels();
        size_t frames_per_buffer = (4 << 20)/sizeof(float)/num_channels; // 4 MB buffer
        std::vector<float> buffer(num_channels * frames_per_buffer);
        float* p = &buffer[0];

        while (true)
        {
            sf_count_t items_read = inputfile.read(p, buffer.size());
            if (0 == items_read)
                break;

            for (int x=0; x<items_read; ++x)
                p[x] = affine_d + affine_s*p[x];

            outputfile.write(p, items_read );
        }

    } catch (...) {
        QFile::remove(tempfilename.c_str());
        throw;
    }

    QFile::remove(tempfilename.c_str());
}
Exemplo n.º 26
0
static char *get_suitable_filename(struct rfc2045 *r, const char *pfix,
	int ignore_filename)
{
const char *disposition_s;
const char *disposition_name_s;
const char *disposition_filename_s;
char	*filename_buf;
const char *content_name_s;
char	*p, *q;
char	*dyn_disp_name=0;

	rfc2045_dispositioninfo(r, &disposition_s, &disposition_name_s,
		&disposition_filename_s);

	content_name_s=rfc2045_contentname(r);

	if (!disposition_filename_s || !*disposition_filename_s)
		disposition_filename_s=disposition_name_s;
	if (!disposition_filename_s || !*disposition_filename_s)
		disposition_filename_s=content_name_s;

	filename_buf=rfc2047_decode_simple(disposition_filename_s);

	if (!filename_buf)
	{
		perror("rfc2047_decode_simple");
		exit(1);
	}

	if (strlen(filename_buf) > 32)
	{
		p=filename_buf;
		q=filename_buf + strlen(filename_buf)-32;
		while ( (*p++ = *q++) != 0)
			;
	}

	disposition_filename_s=filename_buf;

	if (ignore_filename)
	{
	char	numbuf[NUMBUFSIZE];
	static size_t counter=0;
	const char *p=str_size_t(++counter, numbuf);

		dyn_disp_name=malloc(strlen(disposition_filename_s)
			+ strlen(p)+2);
		if (!dyn_disp_name)
		{
			perror("malloc");
			exit(1);
		}
		disposition_filename_s=strcat(strcat(strcpy(
			dyn_disp_name, p), "-"),
			disposition_filename_s);
	}
	else if (!disposition_filename_s || !*disposition_filename_s)
	{
		dyn_disp_name=tempname(".");
		disposition_filename_s=dyn_disp_name+2;	/* Skip over ./ */
	}

	p=malloc((pfix ? strlen(pfix):0)+strlen(disposition_filename_s)+1);
	if (!p)
	{
		perror("malloc");
		exit(1);
	}
	*p=0;
	if (pfix)	strcpy(p, pfix);
	q=p+strlen(p);
	for (strcpy(q, disposition_filename_s); *q; q++)
		if (!isalnum(*q) && *q != '.' && *q != '-')
			*q='_';

	if (dyn_disp_name)	free(dyn_disp_name);

	if (!pfix)
	{
        const char *content_type_s;
        const char *content_transfer_encoding_s;
        const char *charset_s;
	int c;
	static char filenamebuf[256];
	char	*t;
	FILE	*tty;

		if ((tty=fopen("/dev/tty", "r+")) == 0)
		{
			perror("/dev/tty");
			exit(1);
		}

		rfc2045_mimeinfo(r, &content_type_s,
			&content_transfer_encoding_s, &charset_s);

		fprintf (tty, "Extract %s? ", content_type_s);
		fflush(tty);
		c=getc(tty);
		if (c != '\n' && c != EOF)
		{
		int	cc;

			while ((cc=getc(tty)) != '\n' && cc != EOF)
				;
		}
		if (c != 'y' && c != 'Y')
		{
			free(p);
			fclose(tty);
			free(filename_buf);
			return (0);
		}
		fprintf (tty, "Filename [%s]: ", p);
		fgets(filenamebuf, sizeof(filenamebuf)-1, tty);
		fclose(tty);
		t=strchr(filenamebuf, '\n');
		if (t)	*t=0;
		else
		{
			fprintf(stderr, "Filename too long.\n");
			exit(1);
		}
		if (filenamebuf[0])
		{
			free(p);
			p=strdup(filenamebuf);
			if (!p)
			{
				perror("malloc");
				exit(1);
			}
		}
	}
	free(filename_buf);
	return (p);
}
Exemplo n.º 27
0
// Add, update, freshen, or delete zip entries in a zip file. argc; /*
//   Number of tokens in command line. argv; /* Command line tokens.
int ZipProcess(struct Globals *pG)
{
  int a; // attributes of zip file
  ulg c; // start of central directory
  struct flist *f; // steps through "found" linked list
  int i; // arg counter, root directory flag
  int k; // next argument type, marked counter, comment size, entry count
  int marks; // replaces k as marked counter
  ulg n; // total of entry len's

  // int o; /* true if there were any ZEN_OPEN errors
  char *p; // steps through option arguments
  int r; // temporary variable
  ulg t; // file time, length of central directory
  //  int           first_listarg = 0;  // index of first arg of "process these files" list
  struct zlist *v; // temporary variable
  struct zlist **w; // pointer to last link in "zfiles" list
  struct zlist *z; // steps through "zfiles" linked list
  int altered; // RP 173 counter for altered comments

  int DestType; // 1.75  destination drive type
  unsigned long TotFiles = 0;
  unsigned /* long */__int64 TotSize = 0;
  unsigned long KeptCnt = 0; // number of 'kept' files
  unsigned __int64 KeptSize = 0; // size of 'kept' files
  unsigned long ofs; // current file offset
  int fsz; // file size;
  int No_File = 0; // 1.75 try if file does not exist
  long hi;

  // Process arguments
  diag("processing lists", pG);

  if (pG->verbose)
  {
    switch (pG->action)
    {
      case ADD:
        diag("action = ADD", pG);
        break;
      case UPDATE:
        diag("action = UPDATE", pG);
        break;
      case FRESHEN:
        diag("action = FRESHEN", pG);
        break;
      case PURGE:
        diag("action = PURGE", pG);
    }

    // zcount is no. of entries in linked-list
    // zfiles is name of the linked-list of filenames for the archive
    Inform(pG, 0, IDIAG, "zcount=%d (no. of files in ZIP already)", pG->zcount);
  }

  // if first_listarg is 0, then we didn't got any fspecs on cmd line
  if (pG->doall && (pG->action == UPDATE || pG->action == FRESHEN))
  {
    // if -update or -freshen with no args, do all, but, when present, apply
    //   filters
    for (z = pG->zfiles; z != NULL; z = z->nxt)
    {
      z->mark = pG->pcount ? filter(z->zname, pG): 1;
    }
  }

  if ((r = check_dup(pG)) != ZEN_OK)
  // remove duplicates in list
    return (ziperr(r, pG));

  // Check option combinations
  // ?????
  if (pG->action == PURGE && (pG->dispose || pG->recurse || pG->key))
    return (ziperr(ZEN_PARMS12, pG));
  if (pG->linkput && pG->dosify)
  {
    Inform(pG, 0, IWARNING, "can't use -y with -k, -y ignored");
    pG->linkput = 0;
  }

  // AllowGrow is the "allow append" indicator
  if (!pG->zcount && ((pG->action == ADD) || (pG->action == UPDATE)))
    pG->AllowGrow = 55;
  //1;   // RP173 - create new file normally

  // if zcount is 0, then zipfile doesn't exist, or is empty
  if (pG->zcount == 0 && ((pG->action != ADD && pG->action != UPDATE) || !pG
    ->AllowGrow))
  {
    // RCV150199 added UPDATE
    Inform(pG, 0, IWARNING, "%s: not found or empty", pG->zipfile);
    if (pG->zcount)
      FREE(pG->zsort);
    return 0;
  }

  if (pG->zcount)
  {
    FREE(pG->zsort);
    pG->zsort = NULL;
  }

  DestType = DriveType(pG->zipfile);
  if (pG->verbose < 0)
    Inform(pG, 0, IDIAG, "Destination type = %d", DestType);

  // RP - check destination type - if CD set tempath to Windows Temp
  if (pG->tempath == NULL && (DestType != DRIVE_FIXED && DestType !=
    DRIVE_RAMDISK))
  {
    unsigned int plen;
    plen = GetTempPath(2047, pG->ewemsg);
    if (plen && (pG->tempath = (char*)MALLOC(plen + 1)) != NULL)
      lstrcpy(pG->tempath, pG->ewemsg);
    else
      return (ziperr(ZEN_MEM10, pG));
  }

  // If -b not specified, set temporary path to zipfile path
  if (pG->tempath == NULL && ((p = strrchr(pG->zipfile, '\\')) != NULL || (p =
    strrchr(pG->zipfile, ':')) != NULL))
  {
    if (*p == ':')
      p++;
    if ((pG->tempath = (char*)MALLOC((int)(p - pG->zipfile) + 1)) == NULL)
      return (ziperr(ZEN_MEM10, pG));
    r =  *p;
    *p = 0;
    lstrcpy(pG->tempath, pG->zipfile);
    *p = (char)r;
  }

  // NOTE: "k" is being redefined below this point. Now, it going to
  // track the no. of marked files in the "zfiles" linked list.
  // For each marked entry in "zfiles" linked list, if not deleting, check
  //   if a corresponding "external" file exists. If updating or freshening,
  //   compare date of "external" file with entry in orig zipfile. Unmark if it
  //   external file doesn't exist or is too old, else mark it. Entries that
  //   are marked will cause that file to be rezipped.
  diag("checking marked entries", pG);

  marks = 0; // Initialize marked count

  // zfiles is name of the linked-list of filenames for the archive
  #ifdef USE_STRM_INPUT
    if (!pG->UseInStream)
  #endif
  for (z = pG->zfiles; z != NULL; z = z->nxt)
  {
    if (z->mark)
    {
      ulg FileAttr;
      #ifdef USE_EF_UX_TIME
        ztimbuf f_utim, z_utim;
      #endif
      #ifdef USE_EF_UX_TIME
        if (pG->action != PURGE && ((t = filetime(z->name, &FileAttr, (long*)
          NULL, &f_utim, pG)) == 0 || t < pG->before || ((pG->action == UPDATE
          || pG->action == FRESHEN) && (get_ef_ux_ztime(z, &z_utim) ?
          f_utim.modtime <= z_utim.modtime: t <= z->tim)) || (pG->ArchiveFiles
          && pG->action == FRESHEN && !(FileAttr &A_ARCHIVE))))
        {
          z->mark = 0;
          z->trash = t && t >= pG->before; // delete if -um or -fm
          if (pG->verbose)
          {
            Inform(pG, 0, 0, "%s %s", z->name, z->trash ? "up to date" :
              "missing or early");
          }
        }
        else
          marks++;
        // incr. number of marked entries
      #else
        if (pG->action != PURGE)
        {
          t = filetime(z->name, &FileAttr, &fsz /* NULL */, NULL, pG);
          //           && (
          //               (t = filetime( z->name, &FileAttr, &fsz /*NULL*/, NULL, pG )) == 0
          if ((t == 0 || t < pG->before || ((pG->action == UPDATE || pG->action
            == FRESHEN) && t <= z->tim) || (pG->ArchiveFiles && pG->action ==
            FRESHEN && !(FileAttr &A_ARCHIVE))) || ( /* (int) */fsz <  - 2))
          // RP - check size
          {
            z->mark = 0;
            z->trash = (t && t >= pG->before) || ( /* (int) */fsz <  - 2);
              // delete if -um or -fm
            //              z->trash = t && t >= pG->before;  // delete if -um or -fm
            if (pG->verbose)
            {
              Inform(pG, 0, 0, "%s %s", z->name, z->trash ? (int)fsz <  - 2 ?
                "now too big" : "up to date": "missing or early");
              //                    z->trash ? "up to date" : "missing or early" );
            }
          }
          else
          {
            TotSize += fsz;
            TotFiles++;
            marks++;
          }
        }
        else
        // PURGE
          marks++;
        // incr. number of marked entries
      #endif
    }
  }

  #ifdef USE_STRM_INPUT
    if (pG->UseInStream)
      marks = 1;
  #endif

  // RP - verify file specified to 'Purge'
  if (pG->action == PURGE && !marks)
    return (ziperr(ZEN_NONE03, pG));

  // Remove entries from "found" linked list if: Action is PURGE or FRESHEN
  //   or No "external" matching file is found, or if found, but is too old or
  //   The external file is equal to the ziparchive name while ziparchive name
  //   != "-" If filetime() returns any valid time, then at least we know the
  //   file was found.
  diag("checking new entries", pG);

  // fileio.c built the found list
  #ifdef USE_STRM_INPUT
    if (!pG->UseInStream)
  #endif
  for (f = pG->found; f != NULL;)
  {
    int sz = 0;
    if (pG->action == PURGE || pG->action == FRESHEN || (t = filetime(f->name,
      (ulg*)NULL, &sz, (ztimbuf*)NULL, pG)) == 0
    //         || (t = filetime( f->name, ( ulg * )NULL, ( long * )NULL, ( ztimbuf * )NULL, pG )) == 0
     || t < pG->before || (namecmp(GetFullPath(pG, f->name), pG->zipfile) == 0
       && strcmp(pG->zipfile, "-")) || (sz <  - 2))
    {
      if (sz <  - 2)
        Inform(pG, ZEN_SIZE04, IWARNING, "%s is too large", f->name); 
      if (pG->verbose && t < pG->before)
      {
        Inform(pG, 0, IDIAG, "rejecting %s as too early", f->name );
      }
      if (pG->verbose < 0)
        Inform(pG, 0, IDIAG, "expel being called for %s", f->name);
      f = fexpel(f, pG); // delete an entry in the list.
    }
    else
    // file found, and not too old.
      f = f->nxt;
    // save this one, link it up.
  }

  if (pG->found == NULL)
    diag("found list empty - a", pG);
  else
    diag("found list has at least one entry - a", pG);

  if ( /* ( pG->action == UPDATE || pG->action == FRESHEN ) && */(pG->adjust <=
    0))
    pG->adjust = 0;

  // Make sure there's something left to do RP adjust always 1
  if (marks == 0 && pG->found == NULL && !(pG->zfiles != NULL && (pG->latest ||
    pG->adjust || pG->junk_sfx)))
  {
    // FOUND WAS NULL HERE, so just figure out which error message to show
    //   the user
    if (pG->action == UPDATE || pG->action == FRESHEN)
    {
      finish(pG);
      Inform(pG, 0, IWARNING, "no files %s", (pG->action == UPDATE) ? "updated"
        : "freshened");
      return 0;
    }
    else if (pG->zfiles == NULL && (pG->latest || pG->adjust || pG->junk_sfx))
    {
      return (ziperr(ZEN_NAME01, pG));
    }
    else if (pG->recurse && (pG->pcount == 0) && (!pG->doall))
    //first_listarg > 0) )
    {
      // add the list of filenames from cmd line to error msg
      ///      for ( i = first_listarg; i < argc; i++ )
      ///        lstrcat( lstrcat( pG->errbuf, " " ), argv[i] );
      return (ziperr(ZEN_NONE01, pG));
    }
    else
      return (ziperr(ZEN_NONE02, pG));
  }

  // AllowGrow is false if writing temporary file
  pG->AllowGrow = (pG->AllowGrow && (marks == 0)
    // is allowed and no changes to existing
   && (pG->zipbeg || pG->zfiles != NULL) // something to append to
  );

  // continue on to add new files
  a = 0;

  // ignore self-extracting code in front of the zip file (for -J)
  if (pG->junk_sfx)
    pG->zipbeg = 0;

  // Count files and sizes which we have to Keep; RP Added
  w = &pG->zfiles;
  while ((z =  *w) != NULL)
  {
    if (pG->global_abort_sw)
      return (ziperr(ZEN_ABORT, pG));
    if (!z->mark)
    {
      KeptSize += (z->siz + (ulg)(4+LOCHEAD) + (ulg)z->nam + (ulg)z->ext);
      if (z->lflg &8)
        KeptSize += 16;
      KeptCnt++;
    }

    w = &z->nxt;
  }

  //Inform( pG, 0, IDIAG, "Kept = %u %Lu Total = %u %Lu", KeptCnt, KeptSize, TotFiles, TotSize );
  // Count files and sizes which we have to process; RCV Added
  // First the files in the old zip file...
  // RP - already calculated with new sizes
  // And the found list...
  for (f = pG->found; f != NULL; f = f->nxt)
  {
    if (pG->global_abort_sw)
      return (ziperr(ZEN_ABORT, pG));
    TotSize += f->len;
    TotFiles++;
  }
  //    Inform( pG, 0, IDIAG, "Found = %u %u", tc, ts );
  // OPEN ZIP FILE and temporary output file
  //  diag( "opening zip file and creating temporary zip file", pG );
  pG->hInz = INVALID_HANDLE_VALUE; //0;
  pG->hTempzf = INVALID_HANDLE_VALUE;
  pG->tempzn = 0;


  if (!pG->AllowGrow)
  {
    // check file exists
    No_File = access(pG->zipfile, 0) && errno == ENOENT;
    if (No_File && DestType == DRIVE_FIXED || DestType == DRIVE_RAMDISK)
    {
      // create file using given name
      diag("in dllzip - ready to create new file", pG);
      if ((pG->hOutz = CreateFile(pG->zipfile, GENERIC_WRITE, 0, NULL,
        CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL)) !=
        INVALID_HANDLE_VALUE)
      {
        pG->tempzip = pG->zipfile;

        pG->hTempzf = pG->hOutz;
        pG->AllowGrow =  - 1; // new files do grow
      }
    }
  }

  if (pG->AllowGrow > 0)
  {
    // zipfile is not stdout, and we are allowed to append
    // AllowGrow is true if we're just appending (-g)
    diag("in dllzip - ready to open for appending", pG);
    if ((pG->hOutz = CreateFile(pG->zipfile, GENERIC_READ | GENERIC_WRITE, 0,
      NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
      NULL)) == INVALID_HANDLE_VALUE)
      return (ziperr(ZEN_NAME02, pG));
    pG->tempzip = pG->zipfile;

    pG->hTempzf = pG->hOutz;

    /* long */
    hi = 0;
    if (SetFilePointer(pG->hOutz, pG->cenbeg, &hi, FILE_BEGIN) ==
      INVALID_SET_FILE_POINTER && GetLastError())
      return (ziperr(GetLastError() ? ZEN_READ01 : ZEN_EOF01, pG));
    pG->tempzn = pG->cenbeg;
  }

  if (!pG->AllowGrow)
  {
    diag("in dllzip - ready to open for Exclusive Read", pG);
    if ((pG->zfiles != NULL || pG->zipbeg) && (pG->hInz = CreateFile(pG
      ->zipfile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
      FILE_FLAG_SEQUENTIAL_SCAN, NULL)) == INVALID_HANDLE_VALUE)
      return (ziperr(ZEN_NAME03, pG));
    if ((pG->tempzip = tempname(pG)) == NULL)
      return (ziperr(ZEN_MEM11, pG));

    //		if (pG->Verbose)
    Inform(pG, 0, IDIAG, "Temp Filename = %s", pG->tempzip);
    if ((pG->hTempzf = pG->hOutz = CreateFile(pG->tempzip, GENERIC_WRITE, 0,
      NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS |
      FILE_ATTRIBUTE_TEMPORARY, NULL)) == INVALID_HANDLE_VALUE)
      return (ziperr(ZEN_TEMP01, pG));
  }

  if (!pG->AllowGrow)
  {
    TotFiles += KeptCnt;
    TotSize += KeptSize;
  }
  // Pass total number of files and Total Filesize.    (moved)
  user_callback(zacCount, 0, TotFiles, NULL, pG);
  user_callback(zacSize, (long)(TotSize >> 32), ((unsigned)TotSize), NULL, pG);
  pG->BatchStarted = 1;

  if (!pG->AllowGrow && pG->zipbeg)
  {
    // copy a compressed file from old archive to new archive
    user_callback(zacItem, 0, pG->zipbeg, "SFX", pG);
    if ((r = fcopy(pG->hInz, pG->hOutz, pG->zipbeg, pG)) != ZEN_OK)
      return (ziperr(r, pG));
    pG->tempzn = pG->zipbeg;
  }

  // o = 0; /* no ZEN_OPEN errors yet
  // Process zip file, copying from old archive to new archive. Rezip any
  //   marked files
  if (pG->zfiles != NULL)
    diag("going through old zip file", pG);
  w = &pG->zfiles;

  while ((z =  *w) != NULL)
  {
    if (pG->global_abort_sw)
    {
      return (ziperr(ZEN_ABORT, pG));
    }

    if (z->mark == 1)
    {
      // This file is marked
      // if not deleting, rezip it
      if (pG->action != PURGE)
      {
        Inform(pG, 0, 0, "updating: %s", Oem2Iso(z->zname, pG));

        // zipup is in file zipup.c
        if ((r = zipup(z, pG->hOutz, pG)) != ZEN_OK && (int)(char)(r &0xFF) !=
          ZEN_OPEN && (int)(char)(r &0xFF) != ZEN_MISS)
        {
          return (ziperr(r, pG));
        }

        if ((int)(char)(r &0xFF) == ZEN_OPEN || (int)(char)(r &0xFF) ==
          ZEN_MISS)
        {
          if ((int)(char)(r &0xFF) == ZEN_OPEN)
          {
            Inform(pG, r, IWARNING, "could not open for reading: %s", z->name);
            user_callback(4, r, 0, z->name, pG);
          }
          else
          {
            Inform(pG, 0, IWARNING, "file and directory with the same name: %s",
              z->name);
            user_callback(4, r, 0, z->name, pG);
          }

          Inform(pG, 0, IWARNING, "will just copy entry over: %s", z->zname);

          if ((r = zipcopy(z, pG->hInz, pG->hOutz, pG)) != ZEN_OK)
          {
            sprintf(pG->errbuf, "was copying %s", z->zname);
            return (ziperr(r, pG));
          }

          z->mark = 0;
        }

        w = &z->nxt;
        pG->files_acted_on++;
      }
      else
      {
        // desired action is DELETE, this file marked
        // NOTE: no progress bar supt for DELETE yet
        Inform(pG, 0, 0, "deleting: %s", Oem2Iso(z->zname, pG));

        v = z->nxt; // delete entry from list
        FREE(z->name);
        FREE(z->zname);
        if (z->ext)
          FREE(z->extra);
        if (z->cext && z->cextra != z->extra)
          FREE(z->cextra);
        if (z->com)
          FREE(z->comment);
        FREE(z);
        *w = v;
        pG->zcount--;
        pG->files_acted_on++;
      }
    }
    else
    {
      // this file wasn't marked
      // copy the original entry verbatim
      if (!pG->AllowGrow)
      {
        Inform(pG, 0, 0, "keeping: %s", Oem2Iso(z->zname, pG));
        if ((r = zipcopy(z, pG->hInz, pG->hOutz, pG)) != ZEN_OK)
        {
          sprintf(pG->errbuf, "was copying %s", z->zname);

          // user_callback ( zacEndOfBatch, 0, 0, NULL, pG ); // done with a
          // batch of files
          return (ziperr(r, pG));
        }
      }
      w = &z->nxt;
    }
  } // end while

  // Process the "found" list, adding them to the zip file.
  // This is used to add files that weren't already in the archive.
  if (pG->verbose)
  {
    Inform(pG, 0, IDIAG, "Zipping up %d NEW entries from found list", pG
      ->fcount);
  }

  // For each new file to add (src names in found list), make a new entry
  //   for it in the "zfiles" linked list, zip up the new file, then remove the
  //   entry from the found list.
  // The last item in the for loop control deallocates spc for fname that
  //   was just zipped up
  for (f = pG->found; f != NULL; f = fexpel(f, pG))
  {
    // add a new entry to "zfiles" list, before we zip up the file. That way
    //   we'll be ready to update the ZIP file's directory later.
    if (pG->global_abort_sw)
    {
      // user_callback ( zacEndOfBatch, 0, 0, NULL, pG ); // done with a
      // batch of files
      return (ziperr(ZEN_ABORT, pG));
    }

    if ((z = (struct zlist*)MALLOC(sizeof(struct zlist))) == NULL)
    {
      return (ziperr(ZEN_MEM12, pG));
    }

    // RP 1.73 clear all fields
    memset(z, 0, sizeof(struct zlist));

    // Similar names below are confusing: f->name f->zname z->name z->zname
    // z z->nxt = NULL;
    z->name = f->name;
    f->name = NULL;

    z->zname = f->zname;
    f->zname = NULL;

    // z z->ext = z->cext = z->com = 0;
    // z z->extra = z->cextra = z->comment = NULL;
    // pRP173 z->ext = strlen( f->passw ); //Added RAEL
    // pRP173 z->extra = f->passw; //Added RAEL for per file password
    z->passw = f->passw; // p
    f->passw = NULL; // Added RAEL
    z->mark = 1;
    z->dosflag = f->dosflag;
    z->len = f->len; // RCV added.

    // zip it up
    Inform(pG, 0, 0, "  adding: %s", Oem2Iso(z->zname, pG));

    // This is it - try to zip up new file
    if ((r = zipup(z, pG->hOutz, pG)) != ZEN_OK && (int)(char)(r &0xFF) !=
      ZEN_OPEN && (int)(char)(r &0xFF) != ZEN_MISS)
    {
      return (ziperr(r, pG));
    }

    if ((int)(char)(r &0xFF) == ZEN_OPEN || (int)(char)(r &0xFF) == ZEN_MISS)
    {
      // o = 1;
      if ((int)(char)(r &0xFF) == ZEN_OPEN)
      {
        Inform(pG, r, IWARNING, "could not open for reading: %s", z->name);
      }
      else
      {
        Inform(pG, 0, IWARNING, "file and directory with the same name: %s", z
          ->name);
      }

      FREE(z->name);
      FREE(z->zname);
      FREE(z);
    }
    else
    {
      // "zipup" of this file was good
      *w = z;
      w = &z->nxt;
      pG->zcount++;
      pG->files_acted_on++;
    }
  }

  // Write central directory and end header to temporary zip
  diag("writing central directory", pG);
  hi = 0;
  ofs = SetFilePointer(pG->hOutz, 0, &hi, FILE_CURRENT);
  if (hi || (ofs > 0xFFFFFFF0u) || (ofs == INVALID_SET_FILE_POINTER &&
    GetLastError()))
  {
    return ziperr(ZEN_SIZE01, pG);
  }

  k = 0; // keep count of new fnames for ZIPfile's end header
  c = pG->tempzn; // get start of central directory
  n = t = 0;
  altered = 0; // RP 173 - count changes
  for (z = pG->zfiles; z != NULL; z = z->nxt)
  {
    // Handle callback and result for the filecomments... DLL v1.609,
    // Component v1.60L
    if (pG->action != PURGE)
    {
      memset(pG->ewetmp, 0, 513); // Clear all
      strncpy(pG->ewetmp, z->zname, 255); // Copy external filename
      if (z->com)
      // Copy old comment if present
        strncpy(pG->ewetmp + 256, z->comment, min(z->com, 255));
      else
        z->comment = 0;
      user_callback(12, 0, z->com, pG->ewetmp, pG);
      if (pG->callbackdata.error_code)
      {
        // User changed the comment
        FREE(z->comment);
        z->com = pG->callbackdata.fsize;
        if ((z->comment = (char*)MALLOC(z->com + 1)) == NULL)
          return (ziperr(ZEN_MEM37, pG));
        strncpy(z->comment, pG->callbackdata.filenameormsg, z->com + 1);
        altered++;
      }
    }

    if (pG->files_acted_on < altered)
    // RP 173 - comments changed is acted on
      pG->files_acted_on = altered;

    if ((r = putcentral(z, pG->hOutz, pG)) != ZEN_OK)
    {
      // v1.6014
      return (ziperr(r, pG));
    }

    pG->tempzn += 4+CENHEAD + z->nam + z->cext + z->com;
    n += z->len;
    t += z->siz;
    k++;
  }

  if (k == 0)
    Inform(pG, 0, IWARNING, "zip file empty");

  if ((pG->verbose) && (pG->action == ADD) && (!pG->global_error_code) && (pG
    ->files_acted_on > 0))
  {
    Inform(pG, 0, 0, "Total Bytes=%lu, compr bytes=%lu -> %d%% savings", n, t,
      percent(n, t));
  }

  t = pG->tempzn - c; // compute length of central
  diag("writing end of central directory", pG);

  if (k && ((r = putend(k, t, c, pG->hOutz, pG)) != ZEN_OK))
  {
    return (ziperr(r, pG));
  }

  //       if ( pG->hInz != INVALID_HANDLE_VALUE )
  //       {
  Close_Handle(&pG->hInz);
  //         pG->hInz = INVALID_HANDLE_VALUE;
  //       }

  // pG->tempzf = NULL;
  // if ( fclose ( pG->y ) )
  pG->hTempzf = INVALID_HANDLE_VALUE; //NULL;
  //       if ( pG->hOutz != INVALID_HANDLE_VALUE && !CloseHandle( pG->hOutz ) )
  if (!Close_Handle(&pG->hOutz))
  {
    return (ziperr(pG->AllowGrow ? ZEN_WRITE03 : ZEN_TEMP02, pG));
  }

  //       pG->hOutz = INVALID_HANDLE_VALUE;

  #ifdef DYN_ALLOC
    lm_free(pG);
  #endif

  //  if ( pG->verbose )
  //    Inform( pG, 0, IDIAG, "Files closed in: %X out: %x", pG->hInz, pG->hOutz );
  // Replace old zip file with new zip file, leaving only the new one
  //  if ( !pG->AllowGrow )     // && lstrcmp(pG->zipfile, pG->tempzip))
  if (!pG->AllowGrow && (k || pG->action != PURGE))
  // && lstrcmp(pG->zipfile, pG->tempzip))
  {
    diag("replacing old zip file with new zip file", pG);
    if ((r = replace(pG->zipfile, pG->tempzip, pG)) != ZEN_OK)
    {
      Inform(pG, 0, IWARNING, "new zip file left as: %s", pG->tempzip);
      FREE(pG->tempzip);
      pG->tempzip = NULL;

      return (ziperr(r, pG));
    }

    FREE(pG->tempzip);
    pG->tempzip = NULL;
  }

  // 1.78.1.2
  if (!k && pG->action == PURGE)
  // empty file - remove
  {
    a = pG->latest = 0;
    DeleteFile(pG->zipfile);
    if (!pG->AllowGrow)
      DeleteFile(pG->tempzip);
  }

  pG->tempzip = NULL;
  if (a)
    setfileattr(pG->zipfile, a);

  // Reset the archive bit when needed for all successfull zipped files
  if (pG->ResetArchiveBit && pG->action != PURGE)
  {
    unsigned cnt = 0; // 1.71.0.0 added extra callbacks
    diag("resetting archive bits", pG);
    for (z = pG->zfiles; z != NULL; z = z->nxt)
      if (z->mark)
        cnt++;
    if (cnt)
    {
      // new file op.
      // Pass total number of files. filesize.
      user_callback(zacXItem, 1, cnt, "*resetting archive bits", pG);
    }

    cnt = 0;
    for (z = pG->zfiles; z != NULL; z = z->nxt)
    {
      if (z->mark)
      {
        char *fullname;
        if (++cnt == 30)
        {
          user_callback(zacXProgress, 1, cnt, "", pG);
          cnt = 0;
          if (pG->global_abort_sw)
            break;
        }

        fullname = GetFullPath(pG, z->name); // v.16017
        if (!SetFileAttributes(fullname, GetFileAttributes(fullname)
          &~FILE_ATTRIBUTE_ARCHIVE))
        {
          Inform(pG, 0, IWARNING, "Archive bit could not be set for: %s", z
            ->name);
        }
      }
    }

    if (cnt)
    {
      user_callback(zacXProgress, 1, cnt, "", pG); // last few
    }
  }

  finish(pG);
  return 0;
}