SearchNotesWidget::SearchNotesWidget(NoteManager & m) : m_accel_group(Gtk::AccelGroup::create()) , m_no_matches_box(NULL) , m_manager(m) , m_clickX(0), m_clickY(0) , m_matches_column(NULL) , m_note_list_context_menu(NULL) , m_notebook_list_context_menu(NULL) , m_initial_position_restored(false) , m_sort_column_id(2) , m_sort_column_order(Gtk::SORT_DESCENDING) { set_hexpand(true); set_vexpand(true); make_actions(); // Notebooks Pane Gtk::Widget *notebooksPane = Gtk::manage(make_notebooks_pane()); notebooksPane->show(); set_position(150); add1(*notebooksPane); add2(m_matches_window); make_recent_tree(); m_tree = manage(m_tree); m_tree->set_enable_search(false); m_tree->show(); update_results(); m_matches_window.property_hscrollbar_policy() = Gtk::POLICY_AUTOMATIC; m_matches_window.property_vscrollbar_policy() = Gtk::POLICY_AUTOMATIC; m_matches_window.add(*m_tree); m_matches_window.show(); // Update on changes to notes m.signal_note_deleted.connect(sigc::mem_fun(*this, &SearchNotesWidget::on_note_deleted)); m.signal_note_added.connect(sigc::mem_fun(*this, &SearchNotesWidget::on_note_added)); m.signal_note_renamed.connect(sigc::mem_fun(*this, &SearchNotesWidget::on_note_renamed)); m.signal_note_saved.connect(sigc::mem_fun(*this, &SearchNotesWidget::on_note_saved)); // Watch when notes are added to notebooks so the search // results will be updated immediately instead of waiting // until the note's queue_save () kicks in. notebooks::NotebookManager::obj().signal_note_added_to_notebook() .connect(sigc::mem_fun(*this, &SearchNotesWidget::on_note_added_to_notebook)); notebooks::NotebookManager::obj().signal_note_removed_from_notebook() .connect(sigc::mem_fun(*this, &SearchNotesWidget::on_note_removed_from_notebook)); notebooks::NotebookManager::obj().signal_note_pin_status_changed .connect(sigc::mem_fun(*this, &SearchNotesWidget::on_note_pin_status_changed)); Glib::RefPtr<Gio::Settings> settings = Preferences::obj().get_schema_settings(Preferences::SCHEMA_GNOTE); settings->signal_changed().connect(sigc::mem_fun(*this, &SearchNotesWidget::on_settings_changed)); parse_sorting_setting(settings->get_string(Preferences::SEARCH_SORTING)); settings = Preferences::obj().get_schema_settings(Preferences::SCHEMA_DESKTOP_GNOME_INTERFACE); settings->signal_changed().connect(sigc::mem_fun(*this, &SearchNotesWidget::on_settings_changed)); }
void tryadd(node *p, node **item, node **nufork, double *place) { /* temporarily adds one fork and one tip to the tree. Records scores in ARRAY place */ add2(p, *item, *nufork, &root, restoring, wasleft, treenode); evaluate(root); place[p->index - 1] = -like; re_move2(item, nufork, &root, &wasleft, treenode); } /* tryadd */
int main(int argc, char *argv[]) { setIO("sample");CLEAR(st,0xff);st[0] = 0; int64 n=gi,m = gi,q=gi;s = gi; for(int64 i = 1;i<=n;++i) a[i] = gi; for(int64 i = 1,x,y,z;i<=m;++i) x = gi,y=gi,z = gi,add(x,y,z); tot = n;sort(e+1,e+tote+1); for(int64 i = 1,u,v;i<=tote;++i) { u = gf(e[i].u);v = gf(e[i].v); if(u == v) continue;++tot;w[tot] = e[i].w;add2(u,tot);add2(tot,u);add2(v,tot);add2(tot,v);fa[u] = tot;fa[v] = tot; } qu[SIZE(qu)=1] = tot; for(int64 i = 1,u;i<=SIZE(qu);++i) TRA(x,u=qu[i]) { int64 v = lk[x].v;f[v][0] = u;++SIZE(qu);qu[SIZE(qu)] = v;lk[x^1].f = 1; }
int main(void) { printf("add2(%d, %d) = %d\n", 3, 1, add2(3, 1)); printf("add3(%d, %d, %d) = %d\n", 1, 3, 1, add3(1, 3, 1)); printf("bic(%d, %d) = %d\n", 3, 1, bic(3, 1)); printf("mvn(%d, %d) = %d\n", 3, 1, mvn(3, 1)); printf("rsb3(%d, %d, %d) = %d\n", 3, 1, 1, rsb3(3, 1, 1)); printf("rsb1(%d) = %d\n", 3, rsb1(3)); return 0; }
//ham main int main() { init1(); add1(); add2(); system("clear"); menu(); btcls(bt1); btcls(bt2); }
void growstr(dynstr *str, size_t newlen) { if (newlen < str->alloc) return; str->buf = realloc(str->buf, str->alloc = add2(newlen, 1)); if (!str->buf) { fprintf(stderr, "\nOut of memory 4\n"); doexit(4); } }
int main(void) { int a; int b; int c; a=1; b=2; add2(&a,&b,&c); fprintf(stdout, " %d+%d=%d\n",a,b,c); return(EXIT_SUCCESS); }
float main() { float n; float result; scanf("%d", &n); result = add2(n,n*n); printf("Sum = %ld\n", result); return 0; }
static void *start_routine_2(void *arg) { int x, status; x = add2(40, 2, 100); assert(x == 142); status = sem_post(&done); assert(status == 0); return arg; }
void gensymtab_worker(char *t, tree *n) { if(n->type == t_id) { fprintf(out, "def\t%s\t%s\n", t, n->value.idval); add2(n->value.idval, t); return; } gensymtab_worker(t, n->left); gensymtab_worker(t, n->right); }
void init() { int a,b,t; scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) { scanf("%d%d%d",&a,&b,&t); add(a,b,t); add2(b,a,t); } scanf("%d%d%d",&S,&T,&K); if(S==T) ++K; }
int main() { long a = 3; long b = 4; long c1 = 0; long c2 = 0; c1 = add1(a, b); c2 = add2(a, b); printf("add1: %ld\n", c1); printf("add2: %ld\n", c2); return 0; }
void init(){ int i,a,b; scanf("%d",&n); memset(head,-1,sizeof(head)); memset(q,-1,sizeof(q)); memset(flag,false,sizeof(flag)); memset(ans,0,sizeof(ans)); top=0; for(i=1;i<n;i++){ scanf("%d %d",&a,&b); add(a,b); flag[b]=true; } for(i=1;i<=n;i++) if(!flag[i]){ ro=i; break; } memset(flag,false,sizeof(flag)); scanf("%d %d",&a,&b); add2(a,b); add2(b,a); }
bool CWSTaggerImpl::add(const string& line) { vector<string> tokens; EncodeUtil::split_utf8(line, tokens); const char* column[2]; size_t size=1; for(size_t i=0; i<tokens.size(); ++i) { column[0]=feature_index_->strdup( tokens[i].c_str() ); // only one colume for each token if (!add2(size, column, false)) return false; } return true; }
void test() { complex a, b; a.x = 2.0; a.y = 3.0; b.x = 4; b.y = 5; printf("Enter a and b where a + ib is the first complex number.\n"); printf("a = "); scanf("%f", &a.x); printf("b = "); scanf("%f", &a.y); printf("Enter c and d where c + id is the second complex number.\n"); printf("c = "); scanf("%f", &b.x); printf("d = "); scanf("%f", &b.y); printf (" The complex numbers entered are :%.1f %+.1f and %.1f %+.1fi\n", a.x,a.y,b.x,b.y); printf ("The multiplication of complex numbers are :%.1f %+.1fi\n", mult2(a,b).x, mult2(a,b).y); printf ("The square of complex number is :%.1f %+.1fi\n", square(a).x, square(a).y); printf ("The addition of complex numbers are :%.1f %+.1fi\n", add2(a,b).x, add2(a,b).y); printf ("The juliamap of complex numbers are :%.1f %+.1fi\n", juliamap(a,b).x, juliamap(a,b).y); complex_print(a); complex_print(b); }
int main(void){ int nums[2]; int i; for(i=0;i<20;i+= 2){ printf("%d\n", i); } i = 0; do{ printf("%d\n", i); i++; }while(i<5); printf("Enter two numbers:\n"); scanf("%d", &nums[0]); scanf("%d", &nums[1]); if(nums[0] > nums[1]){ printf("First number is greater than second.\n"); }else if(nums[0] < nums[1]){ printf("First number is less than second.\n"); }else{ printf("First number is equal to second\n"); } printf("The sum is %d\n", add2(nums[0],nums[1])); lua_State *L; L = luaL_newstate(); luaL_openlibs(L); luaL_loadfile(L, "programs.lua"); lua_pcall( L, number_of_args, number_of_returns, errfunc_idx ); lua_pcall( L, number_of_args, number_of_returns, errfunc_idx ); lua_close(L); printf("Press any key to exit..."); getch(); return 0; }
/* It returns the result of the desirable function among the functions defined above (mult2, square, add2, juliamap)*/ COMPLEX get_result(char *name, COMPLEX *a, COMPLEX *b){ COMPLEX c; if(strcmp("mult2",name)==0){ c=mult2(a,b); } else if(strcmp("square",name)==0){ c=square(a); } else if(strcmp("add2",name)==0){ c=add2(a,b); } else if(strcmp("juliamap",name)==0){ c=juliamap(a,b); } return c; }
void add(double *A1, double *A2, double *B1, double *B2, int n, double *outA, double *outB) { double *A = A1, *B = A1 + 2 * n * n, *C = A1 + n, *D = A1 + 2 * n * n + n, *E = B1, *F = B1 + n, *G = A2, *H = A2 + 2 * n * n, *I_ = A2 + n, *J = A2 + 2 * n * n + n, *K = B2, *L = B2 + n, *oA = outA, *oB = outA + 3 * n * n, *oC = outA + 2 * 3 * n * n, *oD = outA + n, *oE = outA + 3 * n * n + n, *oF = outA + 2 * 3 * n * n + n, *oG = outA + 2 * n, *oH = outA + 3 * n * n + 2 * n, *oI = outA + 2 * 3 * n * n + 2 * n, *oK = outB, *oL = outB + n, *oM = outB + 2 * n; /* oA = D+G oB = C oC = H oD = B oE = A oF = 0 oG = I oH = 0 oI = I oK = F + K oL = E oM = L */ copy2(oA, D, n, 3 * n, 2 * n); add2(oA, G, n, 3 * n, 2 * n); copy2(oB, C, n, 3 * n, 2 * n); copy2(oC, H, n, 3 * n, 2 * n); copy2(oD, B, n, 3 * n, 2 * n); copy2(oE, A, n, 3 * n, 2 * n); zero2(oF, n, 3 * n); copy2(oG, I_, n, 3 * n, 2 * n); zero2(oH, n, 3 * n); copy2(oI, J, n, 3 * n, 2 * n); memcpy(oK, F, n * sizeof(double)); for (int i = 0; i < n; i++) oK[i] += K[i]; memcpy(oL, E, n * sizeof(double)); memcpy(oM, L, n * sizeof(double)); }
void reduce(const Poly2& p,Poly2Mod& rem) { int m,d; GF2m t; big *G; term2 *ptr,*pos=NULL; int n=degree(p); int degm=degree(Modulus); if (n-degm < KARAT_BREAK_EVEN) { rem=(Poly2Mod)p; return; } G=(big *)mr_alloc(2*(N+2),sizeof(big)); ptr=p.start; while (ptr!=NULL) { G[ptr->n]=getbig(ptr->an); ptr=ptr->next; } karmul2_poly(N,T,GRF,&G[N],W); // W=(G/x^n) * h for (d=N-1;d<2*N;d++) copy(W[d],Q[d-N+1]); m=N+1; if(m%2==1) m=N+2; // make sure m is even - pad if necessary for (d=m;d<2*m;d++) copy(G[d],W[d]); karmul2_poly_upper(m,T,GF,Q,W); pos=NULL; rem.clear(); for (d=N-1;d>=0;d--) { add2(W[d],G[d],W[d]); t=W[d]; if (t.iszero()) continue; pos=rem.addterm(t,d,pos); } mr_free(G); }
void rearrange() { long i, j; boolean ok1, ok2; node *p, *q; printf("Remove everything to the right of which node? "); inpnum(&i, &ok1); ok1 = (ok1 && i >= 1 && i < spp * 2 && i != root->index); if (ok1) { printf("Add before which node? "); inpnum(&j, &ok2); ok2 = (ok2 && j >= 1 && j < spp * 2); if (ok2) { ok2 = (treenode[j - 1] != treenode[treenode[i - 1]->back->index - 1]); p = treenode[j - 1]; while (p != root) { ok2 = (ok2 && p != treenode[i - 1]); p = treenode[p->back->index - 1]; } if (ok1 && ok2) { what = i; q = treenode[treenode[i - 1]->back->index - 1]; if (q->next->back->index == i) fromwhere = q->next->next->back->index; else fromwhere = q->next->back->index; towhere = j; re_move2(&treenode[i - 1], &q, &root, &wasleft, treenode); add2(treenode[j - 1], treenode[i - 1], q, &root, restoring, wasleft, treenode); } lastop = rearr; } } changed = (ok1 && ok2); dolmove_printree(); if (!(ok1 && ok2)) printf("Not a possible rearrangement. Try again: \n"); else { oldwritten = written; written = false; } } /* rearrange */
MobileWindow::MobileWindow(MusicPlayer* player) { ui.setupUi(this); this->player = player; //initFolderList(); // SIGNALS // CALL NUMBERS connect(ui.call1Button, SIGNAL(clicked()), this, SLOT(add1())); connect(ui.call2Button, SIGNAL(clicked()), this, SLOT(add2())); connect(ui.call3Button, SIGNAL(clicked()), this, SLOT(add3())); connect(ui.call4Button, SIGNAL(clicked()), this, SLOT(add4())); connect(ui.call5Button, SIGNAL(clicked()), this, SLOT(add5())); connect(ui.call6Button, SIGNAL(clicked()), this, SLOT(add6())); connect(ui.call7Button, SIGNAL(clicked()), this, SLOT(add7())); connect(ui.call8Button, SIGNAL(clicked()), this, SLOT(add8())); connect(ui.call9Button, SIGNAL(clicked()), this, SLOT(add9())); connect(ui.call0Button, SIGNAL(clicked()), this, SLOT(add0())); connect(ui.callAsteriskButton, SIGNAL(clicked()), this, SLOT(addAsterisk())); connect(ui.callHashButton, SIGNAL(clicked()), this, SLOT(addHash())); // CALL, HANG UP AND DELETE BUTTONS connect(ui.removeButton, SIGNAL(clicked()), this, SLOT(removeDigit())); connect(ui.callButton, SIGNAL(clicked()), this, SLOT(call())); connect(ui.hangUpButton, SIGNAL(clicked()), this, SLOT(hangUp())); // CONTACTS connect(ui.contactList, SIGNAL(itemSelectionChanged()), this, SLOT(contactSelected())); // FILL CONTACTS ddbb.readFromFile("ddbb\\contacts.xml"); QList<Contact*> contacts = ddbb.getContacts(); foreach (Contact* c,contacts) { ui.contactList->addItem(c->name); }
void test(){/*this function demonstrates that all of the functions defined above,work correctly.*/ a.x=1.; a.y=3.; b.x=2.; b.y=1.; c=mult2(a,b); assert(c.x==-1.); assert(c.y==7.); printf("mult2 is correct.\n"); c=square(a); assert(c.x==-8.); assert(c.y==6.); printf("square is correct.\n"); c=add2(a,b); assert(c.x==3.); assert(c.y==4.); printf("add2 is correct.\n"); c=juliamap(a,b); assert(c.x==-6.); assert(c.y==7.); printf("juliamap is correct.\n"); complex_print(a); printf("If the previous sentence is 'z=1.000000+3.000000i', the function complex_print is working correctly.\n"); }
hash operator+ (hash const & a, hash const & b) { return {(add1(a.h >> 32, b.h >> 32, b.len) << 32) | add2(a.h & MASK, b.h & MASK, b.len), a.len + b.len}; }
complex juliamap(complex a, complex b) { complex temp; temp = add2(square(a),b); return(temp); }
int main(int argc, char* argv[]) { // stack 프레임 그리는 법을 이해하는게 중요 int a = 2, b = 3; printf("%d\n", add1(a, b)); printf("%d\n", add2(&a, &b)); printf("%d, %d\n", a, b); //2,3 swap(&a, &b); printf("%d, %d\n", a, b); //3,2 char *pszData = "Hello~"; printf("%d\n", getLength("Hi")); // 2 printf("%d\n", getLength(pszData)); // 6 // 함수에서 중요한 것은 리턴할때, 반환한 주소가 가리키는 대상 메모리는 반드시 유효한 것이어야 한다! // 즉, 운영체제에 반환했거나 곧 사라질 메모리에 대한 주소를 반환하면 안된다! int nResult; nResult = *getNum(); //printf("%d\n", nResult); // warning C4172: 지역 변수 또는 임시: nData의 주소를 반환하고 있습니다. << 에러 발생! // 이를 이해하려면 스택프레임에 대한 이해가 필요. // 자동변수는 스택 영역 메모리를 사용한다. ex) 함수의 매개변수 or 지역변수 등 // 함수 내부에 선언된 변수와 매개변수는 기본적으로 '스택'을 사용한다. // 함수별로 스코프가 생성되어, 스택이 차곡차곡 쌓인다. // 매개변수 -> 변수 순으로 스택에 쌓이고, // 함수 리턴하면, 스택에 있는 함수와 거기 딸린 변수들이 사라진다. 해당 스코프의 변수들이 모두 사라진다는 얘기. // 스택에서 식별자를 검색할 때는 스택의 맨 위에서 아래쪽으로 검색한다. 그리고 최대 함수 몸체 스코프까지 검색. 그래도 없으면 전역변수에서 찾는다. // 동적할당된 메모리는 스택 영역이 아니므로 별도로 표시하고, 스택에 있는 포인터 변수와 연결해준다. // 따라서 이 포인터 변수와 동적할당된 메모리와의 연결된 끈이 끊어지지 않도록 신경 써서 개발하는게 중요! // free()를 안하거나, 포인터 변수를 반환하지 않아 함수 소멸시 변수도 사라지게 되면, 메모리 누수(memory leak)가 발생하는 것! // 정적변수, 전역변수는 데이터 영역을 사용하는 변수들이므로 스택과는 무관하게 별도 영역에 표시. // 재귀호출. 스택 프레임을 잘 보여주는 예랄까.. putData("TestData"); putchar('\n'); // 재귀호출은 간편하고 좋다. // 하지만 단점은 // 1. 스택에는 자동변수나 매개변수 말고도 스택 프레임을 관리하기 위한 여러 정보들이 포함됨 // 2. 함수호출에 의해 프로그램의 흐름도 변경되고 // 3. 매개변수를 복사하는 연산도 수행해야 함. // -> 반복문에 비해 훨씬 더 많은 연산이 수행됨(함수 호출에 수반되는 call overhead -> 이걸 개선한게 매크로 -> 인라인 함수. 뒤에서 배움 ) // 스택 크기는 1MB 밖에 안되는데, 이게 계속 올라가다보면 순식간에 메모리 사용량이 80~90%까지 오를 수 있고, 스택 메모리를 모두 소진하면 Stack overflow가 발생하기도 한다. // 반복문으로 할 수 있다면 반복문으로 하자. // 재귀호출 하는 이유는 코드가 '간결'해지기 때문 // 하지만 tree 를 다룰때는 대부분 재귀호출을 사용하고, 그것이 맞다! // 문자열의 본질은 문자 배열 // char[n] // 문자열 상수란 write 안되는 read only라는 것이고 // const char[n] 과 같다. // 문제가 되는 상황은 이름 입력받을때 // 사용자가 입력하는 가변길이의 문자열을 고정길이의 메모리에 저장해야 하는데, 이때 over가 발생할 수 있다. // 왜냐면 사용자가 입력하는 문자열의 길이를 알수가 없으니까! // 이게 Buffer overflow 문제... 심각한 보안 결함을 동반함. // 그러므로 항상 가변길이의 데이터를 '검사'하는 과정이 꼭 필요하다. 이게 시큐리티 코딩. _s 붙은 시큐리티 인핸스드(?) 함수를 써야 하는 이유... 자세한건 책을 보자. // 유니코드 문자열 // MBCS VS Unicoide // "Hello" VS L"Hello" // char[6] VS wchar_t[6] ms에서 만든 형식 // 1byte VS ucs16 = 2bytes 용량이 두배. wchar_t wcsBuffer[12] = { L"Hello" }; // 디버그해서 보면 H0e0l0l0o0 이런식으로 들어가있음.. 24바이트.. puts(wcsBuffer); // H 이렇게 나오는게 당연하다. 중간에 0이 들어가있으니~ _putws(wcsBuffer); // Hello // 유니코드 다룰 때는 유니코드 전용 함수를 쓰자. // 프로젝트 > 속성 > 구성 속성 > 일반 > 문자 집합 <<<< 여기서 선택 가능. 윈도우는 기본이 유니코드. // 조건부 컴파일을 사용해보자 TCHAR ch; printf("%d\n", sizeof(TCHAR)); // 문자집합이 유니코드인 경우 2 출력, 문자집합이 멀티 바이트인 경우 1 출력 // 윈도우는 wchar_t 사용해야하지만.. 리눅스는 char.. return 0; }
// Apply juliamap to complex numbers complex juliamap(complex *a, complex *b){ complex out_juliamap; out_juliamap = square(a); return add2(&out_juliamap,b); }
long add1(int n) { return add2(n+1,n-1); }
int main(int argc, char **argv) { int ch; int i; dynstr nam1 = {NULL, 0}; while ((ch = getopt (argc, argv, "cnvhf")) != -1) { switch (ch) { case 'n': no_link++; break; case 'v': verbose++; break; case 'c': content_only++; break; case 'f': force=1; break; case 'h': default: usage(argv[0]); } } if (optind >= argc) usage(argv[0]); for (i = optind; i < argc; i++) rf(argv[i]); while (dirs) { DIR *dh; struct dirent *di; d * dp = dirs; size_t nam1baselen = strlen(dp->name); dirs = dp->next; growstr(&nam1, add2(nam1baselen, 1)); memcpy(nam1.buf, dp->name, nam1baselen); free (dp); nam1.buf[nam1baselen++] = '/'; nam1.buf[nam1baselen] = 0; dh = opendir (nam1.buf); if (dh == NULL) continue; ndirs++; while ((di = readdir (dh)) != NULL) { if (!di->d_name[0]) continue; if (di->d_name[0] == '.') { char *q; if (!di->d_name[1] || !strcmp (di->d_name, "..") || !strncmp (di->d_name, ".in.", 4)) continue; q = strrchr (di->d_name, '.'); if (q && strlen (q) == 7 && q != di->d_name) { nam1.buf[nam1baselen] = 0; if (verbose) fprintf(stderr, "Skipping %s%s\n", nam1.buf, di->d_name); continue; } } { size_t subdirlen; growstr(&nam1, add2(nam1baselen, subdirlen = strlen(di->d_name))); memcpy(&nam1.buf[nam1baselen], di->d_name, add2(subdirlen, 1)); } rf(nam1.buf); } closedir(dh); } doexit(0); return 0; }
void rf (const char *name) { struct stat st, st2, st3; const size_t namelen = strlen(name); nobjects++; if (lstat (name, &st)) return; if (st.st_dev != dev && !force) { if (dev) { fprintf(stderr, "%s is on different filesystem than the rest.\nUse -f option to override.\n", name); doexit(6); } dev = st.st_dev; } if (S_ISDIR (st.st_mode)) { d * dp = malloc(add3(sizeof(d), namelen, 1)); if (!dp) { fprintf(stderr, "\nOut of memory 3\n"); doexit(3); } memcpy(dp->name, name, namelen + 1); dp->next = dirs; dirs = dp; } else if (S_ISREG (st.st_mode)) { int fd, i; f * fp, * fp2; h * hp; const char *n1, *n2; int cksumsize = sizeof(buf); unsigned int cksum; time_t mtime = content_only ? 0 : st.st_mtime; unsigned int hsh = hash (st.st_size, mtime); off_t fsize; nregfiles++; if (verbose > 1) fprintf(stderr, " %s", name); fd = open (name, O_RDONLY); if (fd < 0) return; if (st.st_size < sizeof(buf)) { cksumsize = st.st_size; memset (((char *)buf) + cksumsize, 0, (sizeof(buf) - cksumsize) % sizeof(buf[0])); } if (read (fd, buf, cksumsize) != cksumsize) { close(fd); if (verbose > 1 && namelen <= NAMELEN) fprintf(stderr, "\r%*s\r", (int)(namelen + 2), ""); return; } cksumsize = (cksumsize + sizeof(buf[0]) - 1) / sizeof(buf[0]); for (i = 0, cksum = 0; i < cksumsize; i++) { if (cksum + buf[i] < cksum) cksum += buf[i] + 1; else cksum += buf[i]; } for (hp = hps[hsh]; hp; hp = hp->next) if (hp->size == st.st_size && hp->mtime == mtime) break; if (!hp) { hp = malloc(sizeof(h)); if (!hp) { fprintf(stderr, "\nOut of memory 1\n"); doexit(1); } hp->size = st.st_size; hp->mtime = mtime; hp->chain = NULL; hp->next = hps[hsh]; hps[hsh] = hp; } for (fp = hp->chain; fp; fp = fp->next) if (fp->cksum == cksum) break; for (fp2 = fp; fp2 && fp2->cksum == cksum; fp2 = fp2->next) if (fp2->ino == st.st_ino && fp2->dev == st.st_dev) { close(fd); if (verbose > 1 && namelen <= NAMELEN) fprintf(stderr, "\r%*s\r", (int)(namelen + 2), ""); return; } for (fp2 = fp; fp2 && fp2->cksum == cksum; fp2 = fp2->next) if (!lstat (fp2->name, &st2) && S_ISREG (st2.st_mode) && !stcmp (&st, &st2, content_only) && st2.st_ino != st.st_ino && st2.st_dev == st.st_dev) { int fd2 = open (fp2->name, O_RDONLY); if (fd2 < 0) continue; if (fstat (fd2, &st2) || !S_ISREG (st2.st_mode) || st2.st_size == 0) { close (fd2); continue; } ncomp++; lseek(fd, 0, SEEK_SET); for (fsize = st.st_size; fsize > 0; fsize -= NIOBUF) { off_t rsize = fsize >= NIOBUF ? NIOBUF : fsize; if (read (fd, iobuf1, rsize) != rsize || read (fd2, iobuf2, rsize) != rsize) { close(fd); close(fd2); fprintf(stderr, "\nReading error\n"); return; } if (memcmp (iobuf1, iobuf2, rsize)) break; } close(fd2); if (fsize > 0) continue; if (lstat (name, &st3)) { fprintf(stderr, "\nCould not stat %s again\n", name); close(fd); return; } st3.st_atime = st.st_atime; if (stcmp (&st, &st3, 0)) { fprintf(stderr, "\nFile %s changed underneath us\n", name); close(fd); return; } n1 = fp2->name; n2 = name; if (!no_link) { const char *suffix = ".$$$___cleanit___$$$"; const size_t suffixlen = strlen(suffix); size_t n2len = strlen(n2); dynstr nam2 = {NULL, 0}; growstr(&nam2, add2(n2len, suffixlen)); memcpy(nam2.buf, n2, n2len); memcpy(&nam2.buf[n2len], suffix, suffixlen + 1); if (rename (n2, nam2.buf)) { fprintf(stderr, "\nFailed to rename %s to %s\n", n2, nam2.buf); free(nam2.buf); continue; } if (link (n1, n2)) { fprintf(stderr, "\nFailed to hardlink %s to %s\n", n1, n2); if (rename (nam2.buf, n2)) { fprintf(stderr, "\nBad bad - failed to rename back %s to %s\n", nam2.buf, n2); } close(fd); free(nam2.buf); return; } unlink (nam2.buf); free(nam2.buf); } nlinks++; if (st3.st_nlink > 1) { /* We actually did not save anything this time, since the link second argument had some other links as well. */ if (verbose > 1) fprintf(stderr, "\r%*s\r%s %s to %s\n", (int)(((namelen > NAMELEN) ? 0 : namelen) + 2), "", (no_link ? "Would link" : "Linked"), n1, n2); } else { nsaved+=((st.st_size+4095)/4096)*4096; if (verbose > 1) fprintf(stderr, "\r%*s\r%s %s to %s, %s %ld\n", (int)(((namelen > NAMELEN) ? 0 : namelen) + 2), "", (no_link ? "Would link" : "Linked"), n1, n2, (no_link ? "would save" : "saved"), st.st_size); } close(fd); return; } fp2 = malloc(add3(sizeof(f), namelen, 1)); if (!fp2) { fprintf(stderr, "\nOut of memory 2\n"); doexit(2); } close(fd); fp2->ino = st.st_ino; fp2->dev = st.st_dev; fp2->cksum = cksum; memcpy(fp2->name, name, namelen + 1); if (fp) { fp2->next = fp->next; fp->next = fp2; } else { fp2->next = hp->chain; hp->chain = fp2; } if (verbose > 1 && namelen <= NAMELEN) fprintf(stderr, "\r%*s\r", (int)(namelen + 2), ""); return; } }
inline size_t add3(size_t a, size_t b, size_t c) { return add2(add2(a, b), c); }