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); }
// 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 }
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); }
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); } } }
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 */
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); } }
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 */
/** * 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; }
/* * 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; } }
/* * 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; }
/* 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; }
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 } }
/* * 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; }
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; }
/* * 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: ; }
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); } }
/* * 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); }
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); }
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); } }
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); }
/* * 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: ; }
/* * 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); }
/** * 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; }
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()); }
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); }
// 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; }